mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
feat(core): implement lifecycle tracking issues for features
- Add GitHub issue template for tracking feature maturity (Alpha/Beta/GA). - Add issueUrl field to FeatureSpec metadata. - Update /features UI to display tracking issue links. - Update documentation with requirement for lifecycle trackers.
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
name: 'Feature Lifecycle Tracker'
|
||||||
|
description: 'Track a feature through Alpha, Beta, and GA stages'
|
||||||
|
labels:
|
||||||
|
- 'lifecycle/alpha'
|
||||||
|
- 'status/need-triage'
|
||||||
|
body:
|
||||||
|
- type: 'markdown'
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
## 🚀 Feature Overview
|
||||||
|
Provide a concise description of what this feature does and why it is being introduced.
|
||||||
|
|
||||||
|
- type: 'textarea'
|
||||||
|
id: 'spec'
|
||||||
|
attributes:
|
||||||
|
label: 'Feature Specification'
|
||||||
|
description: 'Link to design docs, RFCs, or PRs.'
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: 'markdown'
|
||||||
|
attributes:
|
||||||
|
value: |-
|
||||||
|
## 🗺️ Progression Roadmap
|
||||||
|
*Maintainers: Update this table and the checkboxes below as the feature matures.*
|
||||||
|
|
||||||
|
| Stage | Targeted Version | Actual Version | Date |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **Alpha** | 0.x.x | | |
|
||||||
|
| **Beta** | 0.x.x | | |
|
||||||
|
| **GA** | 0.x.x | | |
|
||||||
|
|
||||||
|
- type: 'checkboxes'
|
||||||
|
id: 'alpha-checklist'
|
||||||
|
attributes:
|
||||||
|
label: 'Alpha Requirements (Disabled by Default)'
|
||||||
|
options:
|
||||||
|
- label: 'Feature gated by Alpha flag in `packages/core/src/config/features.ts`'
|
||||||
|
- label: 'Initial implementation merged'
|
||||||
|
- label: 'Basic unit and integration tests'
|
||||||
|
|
||||||
|
- type: 'checkboxes'
|
||||||
|
id: 'beta-checklist'
|
||||||
|
attributes:
|
||||||
|
label: 'Beta Requirements (Enabled by Default)'
|
||||||
|
options:
|
||||||
|
- label: 'Feature stable (no major architectural changes) for >= 2 minor versions'
|
||||||
|
- label: 'Comprehensive documentation in `docs/`'
|
||||||
|
- label: 'Telemetry/metrics implemented and verified'
|
||||||
|
- label: 'Promotion PR merged (stage moved to Beta)'
|
||||||
|
|
||||||
|
- type: 'checkboxes'
|
||||||
|
id: 'ga-checklist'
|
||||||
|
attributes:
|
||||||
|
label: 'GA Requirements (Locked to Enabled)'
|
||||||
|
options:
|
||||||
|
- label: 'Stable for >= 4 minor versions since Beta'
|
||||||
|
- label: 'No high-priority regressions reported'
|
||||||
|
- label: 'Performance audit complete'
|
||||||
|
- label: 'Migration plan (if applicable) documented'
|
||||||
|
- label: 'PR merged (feature gate removed, code integrated into core)'
|
||||||
|
|
||||||
|
- type: 'textarea'
|
||||||
|
id: 'feedback'
|
||||||
|
attributes:
|
||||||
|
label: 'Key Feedback & Bug Links'
|
||||||
|
description: 'List major bug reports or user feedback threads here.'
|
||||||
@@ -49,7 +49,23 @@ The stability of each feature is visually indicated in the
|
|||||||
[`/settings` UI](/docs/cli/settings.md) with colored badges. **GA** features are
|
[`/settings` UI](/docs/cli/settings.md) with colored badges. **GA** features are
|
||||||
considerd stable and look identical to standard settings.
|
considerd stable and look identical to standard settings.
|
||||||
|
|
||||||
### Precedence and Reconciliation
|
## Lifecycle tracking issues
|
||||||
|
|
||||||
|
Every feature managed under this system must have a corresponding **Lifecycle
|
||||||
|
Tracking Issue** on GitHub. These issues act as a living roadmap and a public
|
||||||
|
feedback loop for the feature's progression through Alpha, Beta, and GA stages.
|
||||||
|
|
||||||
|
You can find the link to a feature's tracking issue in the following ways:
|
||||||
|
|
||||||
|
1. **`/features` Command:** The tracker URL is displayed alongside the metadata
|
||||||
|
for each feature.
|
||||||
|
2. **`FeatureDefinitions`:** The `issueUrl` is defined in
|
||||||
|
`packages/core/src/config/features.ts`.
|
||||||
|
|
||||||
|
Maintainers use these issues to document promotion criteria, link related bug
|
||||||
|
reports, and collect user feedback before moving a feature to the next stage.
|
||||||
|
|
||||||
|
### Precedence and reconciliation
|
||||||
|
|
||||||
When determining if a feature is enabled, the system follows this order of
|
When determining if a feature is enabled, the system follows this order of
|
||||||
precedence (highest priority first):
|
precedence (highest priority first):
|
||||||
@@ -92,11 +108,14 @@ For more details on persistent configuration, see the [Configuration guide].
|
|||||||
Maintaining a feature involves promoting it through stages or eventually
|
Maintaining a feature involves promoting it through stages or eventually
|
||||||
deprecating and removing it.
|
deprecating and removing it.
|
||||||
|
|
||||||
### Adding a Feature
|
### Adding a feature
|
||||||
|
|
||||||
To add a new feature under lifecycle management:
|
To add a new feature under lifecycle management:
|
||||||
|
|
||||||
1. **Define the Feature**: Add a new entry to [`FeatureDefinitions`] in
|
1. **Create a Tracker Issue:** Use the **Feature Lifecycle Tracker** template
|
||||||
|
on GitHub to create a new issue. This issue will track the feature from
|
||||||
|
Alpha through GA.
|
||||||
|
2. **Define the Feature:** Add a new entry to [`FeatureDefinitions`] in
|
||||||
[`features.ts`].
|
[`features.ts`].
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@@ -108,6 +127,7 @@ To add a new feature under lifecycle management:
|
|||||||
preRelease: FeatureStage.Alpha,
|
preRelease: FeatureStage.Alpha,
|
||||||
since: '0.31.0',
|
since: '0.31.0',
|
||||||
description: 'Description of my new feature.',
|
description: 'Description of my new feature.',
|
||||||
|
issueUrl: 'https://github.com/google-gemini/gemini-cli/issues/123',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -116,7 +136,7 @@ To add a new feature under lifecycle management:
|
|||||||
_Note: The `default` field is optional. If omitted, it defaults to `false`
|
_Note: The `default` field is optional. If omitted, it defaults to `false`
|
||||||
for Alpha/Deprecated and `true` for Beta/GA._
|
for Alpha/Deprecated and `true` for Beta/GA._
|
||||||
|
|
||||||
2. **Expose in Settings**: Add the feature to the `features` object in
|
3. **Expose in Settings**: Add the feature to the `features` object in
|
||||||
[`settingsSchema.ts`]. This ensures it appears in the `/settings` UI and is
|
[`settingsSchema.ts`]. This ensures it appears in the `/settings` UI and is
|
||||||
validated.
|
validated.
|
||||||
```typescript
|
```typescript
|
||||||
@@ -135,7 +155,7 @@ To add a new feature under lifecycle management:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
3. **Use the Feature**: In your code, check if the feature is enabled using the
|
4. **Use the Feature**: In your code, check if the feature is enabled using the
|
||||||
`Config` object.
|
`Config` object.
|
||||||
```typescript
|
```typescript
|
||||||
if (this.config.isFeatureEnabled('myNewFeature')) {
|
if (this.config.isFeatureEnabled('myNewFeature')) {
|
||||||
@@ -143,18 +163,21 @@ To add a new feature under lifecycle management:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Promoting a Feature
|
### Promoting a feature
|
||||||
|
|
||||||
When a feature is ready for the next stage:
|
When a feature is ready for the next stage:
|
||||||
|
|
||||||
1. **Update [`features.ts`]**: Add a new `FeatureSpec` to the feature's array.
|
1. **Update the Tracker:** Review the requirements in the lifecycle tracker
|
||||||
|
issue. Once met, update the roadmap table in the issue description and post
|
||||||
|
a comment announcing the promotion.
|
||||||
|
2. **Update [`features.ts`]**: Add a new `FeatureSpec` to the feature's array.
|
||||||
- **To BETA**: Set `preRelease: FeatureStage.Beta` (Defaults to `true`).
|
- **To BETA**: Set `preRelease: FeatureStage.Beta` (Defaults to `true`).
|
||||||
- **To GA**: Set `preRelease: FeatureStage.GA` (Defaults to `true` and
|
- **To GA**: Set `preRelease: FeatureStage.GA` (Defaults to `true` and
|
||||||
locked).
|
locked).
|
||||||
- Update the `since` version.
|
- Update the `since` version.
|
||||||
2. **Update [`settingsSchema.ts`]**: Update the `label` and `description` if
|
3. **Update [`settingsSchema.ts`]**: Update the `label` and `description` if
|
||||||
necessary.
|
necessary.
|
||||||
3. **GA Cleanup**: Once a feature is GA and no longer optional, remove the
|
4. **GA Cleanup**: Once a feature is GA and no longer optional, remove the
|
||||||
feature gate check from the code and make it a core part of the logic.
|
feature gate check from the code and make it a core part of the logic.
|
||||||
|
|
||||||
### Deprecating a Feature
|
### Deprecating a Feature
|
||||||
|
|||||||
@@ -130,12 +130,22 @@ export const FeaturesList: React.FC<FeaturesListProps> = ({ features }) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
{feature.description && (
|
{feature.description && (
|
||||||
<Box marginLeft={2} marginBottom={1}>
|
<Box marginLeft={2}>
|
||||||
<Text dimColor color={theme.text.primary}>
|
<Text dimColor color={theme.text.primary}>
|
||||||
{feature.description}
|
{feature.description}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
{feature.issueUrl && (
|
||||||
|
<Box marginLeft={2} marginBottom={1}>
|
||||||
|
<Text color={theme.text.accent}>
|
||||||
|
Tracker: <Text dimColor>{feature.issueUrl}</Text>
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{!feature.issueUrl && feature.description && (
|
||||||
|
<Box marginBottom={1} />
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ describe('FeatureGate', () => {
|
|||||||
since: '0.1.0',
|
since: '0.1.0',
|
||||||
until: undefined,
|
until: undefined,
|
||||||
description: 'Feature 1',
|
description: 'Feature 1',
|
||||||
|
issueUrl: undefined,
|
||||||
});
|
});
|
||||||
expect(feat2).toEqual({
|
expect(feat2).toEqual({
|
||||||
key: 'feat2',
|
key: 'feat2',
|
||||||
@@ -139,6 +140,27 @@ describe('FeatureGate', () => {
|
|||||||
since: '0.2.0',
|
since: '0.2.0',
|
||||||
until: '0.3.0',
|
until: '0.3.0',
|
||||||
description: 'Feature 2',
|
description: 'Feature 2',
|
||||||
|
issueUrl: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include issueUrl in feature info', () => {
|
||||||
|
const gate = DefaultFeatureGate.deepCopy();
|
||||||
|
gate.add({
|
||||||
|
featWithUrl: [
|
||||||
|
{
|
||||||
|
preRelease: FeatureStage.Alpha,
|
||||||
|
issueUrl: 'https://github.com/google/gemini-cli/issues/1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = gate.getFeatureInfo();
|
||||||
|
const feat = info.find((f) => f.key === 'featWithUrl');
|
||||||
|
|
||||||
|
expect(feat).toMatchObject({
|
||||||
|
key: 'featWithUrl',
|
||||||
|
issueUrl: 'https://github.com/google/gemini-cli/issues/1',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ export interface FeatureSpec {
|
|||||||
* Description of the feature.
|
* Description of the feature.
|
||||||
*/
|
*/
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/**
|
||||||
|
* Link to the Lifecycle Tracking Issue on GitHub.
|
||||||
|
*/
|
||||||
|
issueUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,6 +81,7 @@ export interface FeatureInfo {
|
|||||||
since?: string;
|
since?: string;
|
||||||
until?: string;
|
until?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
issueUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,6 +221,7 @@ class FeatureGateImpl implements MutableFeatureGate {
|
|||||||
since: latestSpec.since,
|
since: latestSpec.since,
|
||||||
until: latestSpec.until,
|
until: latestSpec.until,
|
||||||
description: latestSpec.description,
|
description: latestSpec.description,
|
||||||
|
issueUrl: latestSpec.issueUrl,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a, b) => a.key.localeCompare(b.key));
|
.sort((a, b) => a.key.localeCompare(b.key));
|
||||||
|
|||||||
Reference in New Issue
Block a user