diff --git a/.github/ISSUE_TEMPLATE/feature_lifecycle.yml b/.github/ISSUE_TEMPLATE/feature_lifecycle.yml new file mode 100644 index 0000000000..5343c41b3d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_lifecycle.yml @@ -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.' diff --git a/docs/cli/feature-lifecycle.md b/docs/cli/feature-lifecycle.md index 9648d0c522..9aea455051 100644 --- a/docs/cli/feature-lifecycle.md +++ b/docs/cli/feature-lifecycle.md @@ -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 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 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 deprecating and removing it. -### Adding a Feature +### Adding a feature 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`]. ```typescript @@ -108,6 +127,7 @@ To add a new feature under lifecycle management: preRelease: FeatureStage.Alpha, since: '0.31.0', 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` 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 validated. ```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. ```typescript 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: -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 GA**: Set `preRelease: FeatureStage.GA` (Defaults to `true` and locked). - 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. -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. ### Deprecating a Feature diff --git a/packages/cli/src/ui/components/views/FeaturesList.tsx b/packages/cli/src/ui/components/views/FeaturesList.tsx index 93855eeb18..8b7b96e485 100644 --- a/packages/cli/src/ui/components/views/FeaturesList.tsx +++ b/packages/cli/src/ui/components/views/FeaturesList.tsx @@ -130,12 +130,22 @@ export const FeaturesList: React.FC = ({ features }) => { {feature.description && ( - + {feature.description} )} + {feature.issueUrl && ( + + + Tracker: {feature.issueUrl} + + + )} + {!feature.issueUrl && feature.description && ( + + )} ))} diff --git a/packages/core/src/config/features.test.ts b/packages/core/src/config/features.test.ts index 3180462738..1630c485c6 100644 --- a/packages/core/src/config/features.test.ts +++ b/packages/core/src/config/features.test.ts @@ -131,6 +131,7 @@ describe('FeatureGate', () => { since: '0.1.0', until: undefined, description: 'Feature 1', + issueUrl: undefined, }); expect(feat2).toEqual({ key: 'feat2', @@ -139,6 +140,27 @@ describe('FeatureGate', () => { since: '0.2.0', until: '0.3.0', 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', }); }); diff --git a/packages/core/src/config/features.ts b/packages/core/src/config/features.ts index a0fe00b6e9..57a9dca5b4 100644 --- a/packages/core/src/config/features.ts +++ b/packages/core/src/config/features.ts @@ -65,6 +65,10 @@ export interface FeatureSpec { * Description of the feature. */ description?: string; + /** + * Link to the Lifecycle Tracking Issue on GitHub. + */ + issueUrl?: string; } /** @@ -77,6 +81,7 @@ export interface FeatureInfo { since?: string; until?: string; description?: string; + issueUrl?: string; } /** @@ -216,6 +221,7 @@ class FeatureGateImpl implements MutableFeatureGate { since: latestSpec.since, until: latestSpec.until, description: latestSpec.description, + issueUrl: latestSpec.issueUrl, }; }) .sort((a, b) => a.key.localeCompare(b.key));