refactor: range-based spec version tagging (introducedIn/removedIn)#265
Open
pcarleton wants to merge 2 commits into
Open
refactor: range-based spec version tagging (introducedIn/removedIn)#265pcarleton wants to merge 2 commits into
pcarleton wants to merge 2 commits into
Conversation
… tagging Replaces per-scenario `specVersions: SpecVersion[]` arrays with `introducedIn` and optional `removedIn` range fields on all three scenario interfaces. Extension scenarios get an orthogonal `extension?: boolean` flag instead of the former `'extension'` tag in the versions list. matchesSpecVersion() is rewritten as a range comparison (introducedIn <= target && (!removedIn || target < removedIn)), with draft sorting after all dated versions. getScenarioSpecVersions() reconstructs the effective version list from the range for backward-compat with tier-check. Closes #256.
commit: |
…ionId Extension scenarios were forced to set a placeholder introducedIn that was never read (matchesSpecVersion/getScenarioSpecVersions short-circuit on the flag). Replace `extension?: boolean` with a string `source` discriminant on ScenarioSource so off-timeline scenarios carry no spec-version fields at all. Adds typed ExtensionId so each extension scenario names which extension it exercises. A class cannot `implements` a union type (TS2422), so ScenarioSource is a flat interface with optional fields; the cross-field invariant (extension scenarios must have extensionId and no introducedIn/removedIn; spec-timeline scenarios must have introducedIn) is asserted in spec-version.test.ts. Also renames the cross-app-access scenario to enterprise-managed-auth to match the extension's canonical name: file, class, slug, context schema literal, and the everything-client runner.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #256. Follows up on #255.
Problem
Scenarios were tagged with an explicit list of every spec version they apply to:
This means every new spec release requires touching every carried-forward scenario. It also can't express removal — a SEP that tightens or removes an existing requirement has no way to mark an old scenario as "no longer valid in draft".
Changes
Range-based version tagging
src/types.ts: replacedspecVersions: ScenarioSpecTag[]on all three scenario interfaces with a range expressed viaScenarioSource:The
sourcediscriminant replaces the old'extension'tag. Whensourceis unset (the default), the scenario sits on the dated spec timeline andintroducedInis required; whensource === 'extension', the scenario is off-timeline and carries anextensionIdinstead — no spec-version fields. This avoids the placeholderintroducedIn = LATEST_SPEC_VERSIONthat an earlier draft of this PR put on extension scenarios. The string discriminant leaves room for future off-timeline kinds.A class cannot
implementsa union type (TS2422), soScenarioSourceis a flat interface with optional fields; the cross-field invariant is asserted byassertSourceInvariant()inspec-version.test.ts.src/scenarios/index.ts: rewrotematchesSpecVersion()as a range comparison gated onsource:'draft'sorts after all dated versions via index lookup intoALL_SPEC_VERSIONS.getScenarioSpecVersions()reconstructs aScenarioSpecTag[]from the range (returns['extension']forsource === 'extension') for backward-compat with tier-check output.ALL_SPEC_VERSIONS,resolveSpecVersion, and all--spec-versionCLI semantics are unchanged.Scenario migration (~29 files)
specVersions['2025-03-26', '2025-06-18', '2025-11-25']introducedIn: '2025-03-26'['2025-06-18', '2025-11-25']introducedIn: '2025-06-18'['2025-11-25']introducedIn: '2025-11-25'['2025-03-26']introducedIn: '2025-03-26', removedIn: '2025-06-18'[DRAFT_PROTOCOL_VERSION]introducedIn: DRAFT_PROTOCOL_VERSION['extension']source: 'extension', extensionId: <id>cross-app-access→enterprise-managed-authrenameThe extension's canonical name is enterprise-managed-auth. Renamed for consistency: file, class
EnterpriseManagedAuthScenario, slugauth/enterprise-managed-auth,context.tsschema literal, and theeverything-client.tsrunner.Tests
src/scenarios/spec-version.test.tsrewritten to assert range semantics and theScenarioSourceinvariant directly. Superset and isolation tests preserved.Testing
Build, type-check, and lint clean.
node dist/index.js listshowsauth/enterprise-managed-auth [extension].