Repository navigation
feat(sdk): add extension version compatibility preflight - #350
Conversation
Add a shared extension version-compatibility core for pm_min_version and pm_max_version evaluation, wire the loader to it, and expose checkExtensionManifestCompatibility plus assertExtensionManifestCompatible for package authors. Document the author-time compatibility guard, update the pm-changelog output, and include pm evidence for pm-1w0d/pm-sjea/pm-knma/pm-hng2 plus the GH-348 separation note on pm-2kkl. Verification: pnpm build; focused SDK/version tests (168 tests); pnpm quality:static; pnpm security:scan; pnpm audit --audit-level moderate; pnpm contracts:check; pnpm changelog:pm:check; node scripts/run-tests.mjs coverage (4949 tests, 100/100/100/100); isolated temp PM_PATH/PM_GLOBAL_PATH SDK+loader smoke.
Reviewer's GuideIntroduces a shared core module for extension-manifest pm version bound evaluation and exposes new SDK helpers for author-time and test-time compatibility checks, while refactoring the runtime loader to delegate to the shared logic and documenting the new workflow. Sequence diagram for assertExtensionManifestCompatible author-time checksequenceDiagram
actor Author
participant Test as assertExtensionManifestCompatible
participant SDK as checkExtensionManifestCompatibility
participant Core as version_compat_core
Author->>Test: assertExtensionManifestCompatible(manifest, target)
Test->>SDK: checkExtensionManifestCompatibility(manifest, target)
SDK->>Core: evaluatePmMinVersionBound(pm_min_version, pmVersion)
SDK->>Core: evaluatePmMaxVersionBound(pm_max_version, pmVersion, pmMaxVersionExceededMode)
Core-->>SDK: PmVersionBoundEvaluation(min, max)
SDK-->>Test: ExtensionManifestCompatibilityResult
alt blocking_incompatibility
Test-->>Author: throw Error("Extension manifest is not compatible…")
else compatible_or_warnings_only
Test-->>Author: return ExtensionManifestCompatibilityResult
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
@codex review |
|
Warning Review limit reached
More reviews will be available in 46 minutes and 16 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (21)
📝 WalkthroughWalkthroughAdds an author-time version-compatibility preflight feature: extracts shared ChangesVersion-compat preflight feature
Sequence Diagram(s)sequenceDiagram
participant Author as Extension Author
participant checkFn as checkExtensionManifestCompatibility
participant assertFn as assertExtensionManifestCompatible
participant versionCompat as version-compat.ts
participant loader as loader.ts
Author->>checkFn: manifest + target pmVersion
checkFn->>versionCompat: evaluatePmMinVersionBound(pm_min_version, pmVersion)
versionCompat-->>checkFn: PmVersionBoundEvaluation {status, allowed}
checkFn->>versionCompat: evaluatePmMaxVersionBound(pm_max_version, pmVersion, mode)
versionCompat-->>checkFn: PmVersionBoundEvaluation {status, allowed}
checkFn-->>Author: ExtensionManifestCompatibilityResult {compatible, findings, pmVersion}
Author->>assertFn: manifest + target pmVersion
assertFn->>checkFn: delegate
checkFn-->>assertFn: result
assertFn-->>Author: throws Error (blocking findings) OR returns result
loader->>versionCompat: evaluatePmMinVersionBound / evaluatePmMaxVersionBound
versionCompat-->>loader: PmVersionBoundEvaluation {status, allowed}
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
To use Codex here, create a Codex account and connect to github. |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The loader’s
evaluatePmMinVersionCompatibility/evaluatePmMaxVersionCompatibilitynow mirrorevaluatePm*VersionBoundstatus mapping via bespokeswitchblocks; consider centralizing warning-string formatting in a helper that consumesPmVersionBoundEvaluationto avoid future drift between SDK and loader outcomes. - The error message in
assertExtensionManifestCompatibleconcatenates multiple blocking findings with a single space, which may be hard to scan; joining with newlines or a separator token would make multi-finding failures significantly more readable in CI output.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The loader’s `evaluatePmMinVersionCompatibility` / `evaluatePmMaxVersionCompatibility` now mirror `evaluatePm*VersionBound` status mapping via bespoke `switch` blocks; consider centralizing warning-string formatting in a helper that consumes `PmVersionBoundEvaluation` to avoid future drift between SDK and loader outcomes.
- The error message in `assertExtensionManifestCompatible` concatenates multiple blocking findings with a single space, which may be hard to scan; joining with newlines or a separator token would make multi-finding failures significantly more readable in CI output.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Code Review
This pull request introduces an author-time version-compatibility preflight to the SDK. It extracts core version parsing and comparison logic from the runtime loader into a new shared, pure module src/core/extensions/version-compat.ts. Using this shared core, it implements checkExtensionManifestCompatibility for synchronous manifest version-bound analysis and assertExtensionManifestCompatible as a throwing test guard, exporting both from the SDK. Comprehensive unit tests, documentation, and changelog updates are also included. No review comments were provided, and the implementation is clean and well-tested.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review
This pull request introduces an author-time version-compatibility preflight feature for the SDK by extracting version-bound evaluation logic into a shared pure module (src/core/extensions/version-compat.ts). The runtime loader now delegates to this module, and new SDK helpers—checkExtensionManifestCompatibility and assertExtensionManifestCompatible—have been added along with comprehensive unit tests and documentation. The review feedback correctly identifies that non-string values for pm_min_version and pm_max_version are coerced to empty strings and treated as absent, which violates the specification in docs/EXTENSIONS.md stating they should make the manifest malformed. Implementing the suggested type checks and updating the unit tests will ensure alignment with the specification and prevent silent bypasses of compatibility checks.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const declared = typeof required === "string" ? required : ""; | ||
| if (declared.trim().length === 0) { | ||
| return { kind: "pm_min_version", status: "absent", allowed: true, required: declared, current: currentVersion }; | ||
| } |
There was a problem hiding this comment.
According to the package manifest specification in docs/EXTENSIONS.md, a non-string pm_min_version is invalid and should make the manifest malformed. Currently, evaluatePmMinVersionBound coerces non-string values to an empty string, treating them as absent (and thus allowed). Explicitly checking for non-string types and returning an invalid status ensures alignment with the specification and prevents silent bypasses of compatibility checks.
| const declared = typeof required === "string" ? required : ""; | |
| if (declared.trim().length === 0) { | |
| return { kind: "pm_min_version", status: "absent", allowed: true, required: declared, current: currentVersion }; | |
| } | |
| if (required !== undefined && required !== null && typeof required !== "string") { | |
| return { kind: "pm_min_version", status: "invalid", allowed: false, required: String(required), current: currentVersion }; | |
| } | |
| const declared = typeof required === "string" ? required : ""; | |
| if (declared.trim().length === 0) { | |
| return { kind: "pm_min_version", status: "absent", allowed: true, required: declared, current: currentVersion }; | |
| } |
| const declared = typeof required === "string" ? required : ""; | ||
| if (declared.trim().length === 0) { | ||
| return { kind: "pm_max_version", status: "absent", allowed: true, required: declared, current: currentVersion }; | ||
| } |
There was a problem hiding this comment.
Similarly to pm_min_version, a non-string pm_max_version should be treated as invalid rather than absent to align with the specification in docs/EXTENSIONS.md and prevent silent bypasses of compatibility checks.
| const declared = typeof required === "string" ? required : ""; | |
| if (declared.trim().length === 0) { | |
| return { kind: "pm_max_version", status: "absent", allowed: true, required: declared, current: currentVersion }; | |
| } | |
| if (required !== undefined && required !== null && typeof required !== "string") { | |
| return { kind: "pm_max_version", status: "invalid", allowed: false, required: String(required), current: currentVersion }; | |
| } | |
| const declared = typeof required === "string" ? required : ""; | |
| if (declared.trim().length === 0) { | |
| return { kind: "pm_max_version", status: "absent", allowed: true, required: declared, current: currentVersion }; | |
| } |
| it("is absent for an undefined, empty, or non-string bound", () => { | ||
| expect(evaluatePmMinVersionBound(undefined, "2026.6.23").status).toBe("absent"); | ||
| expect(evaluatePmMinVersionBound(" ", "2026.6.23").status).toBe("absent"); | ||
| expect(evaluatePmMinVersionBound(7 as unknown as string, "2026.6.23")).toMatchObject({ | ||
| status: "absent", | ||
| allowed: true, | ||
| required: "", | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Update the test assertions to expect an invalid status for non-string bounds, aligning with the corrected behavior of evaluatePmMinVersionBound and the specification in docs/EXTENSIONS.md.
it("is absent for an undefined or empty bound", () => {
expect(evaluatePmMinVersionBound(undefined, "2026.6.23").status).toBe("absent");
expect(evaluatePmMinVersionBound(" ", "2026.6.23").status).toBe("absent");
});
it("is invalid for a non-string bound", () => {
expect(evaluatePmMinVersionBound(7 as unknown as string, "2026.6.23")).toMatchObject({
status: "invalid",
allowed: false,
required: "7",
});
});There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/SDK.md`:
- Around line 893-916: Add tracker references to the Testing Helpers section in
the documentation to establish the lineage of the newly introduced functions.
Include a reference to pm-knma for the checkExtensionManifestCompatibility
function and pm-hng2 for the assertExtensionManifestCompatible function. Place
these tracker references near the top of the section (after the section
introduction or as a comment line) to clearly document which pm items created
each function.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 3fcd7e1a-c31f-459c-884e-4fa324fe995e
📒 Files selected for processing (21)
.agents/pm/features/pm-1w0d.toon.agents/pm/history/pm-1w0d.jsonl.agents/pm/history/pm-2kkl.jsonl.agents/pm/history/pm-hng2.jsonl.agents/pm/history/pm-knma.jsonl.agents/pm/history/pm-sjea.jsonl.agents/pm/issues/pm-2kkl.toon.agents/pm/tasks/pm-hng2.toon.agents/pm/tasks/pm-knma.toon.agents/pm/tasks/pm-sjea.toonCHANGELOG.mddocs/EXTENSIONS.mddocs/SDK.mdsrc/core/extensions/loader.tssrc/core/extensions/version-compat.tssrc/sdk/compose.tssrc/sdk/index.tssrc/sdk/testing.tstests/unit/extensions/version-compat.spec.tstests/unit/sdk/sdk-compose.spec.tstests/unit/sdk/sdk-index.spec.ts
Address PR review feedback by treating blank and non-string pm version bounds as invalid in the author-time SDK analyzer, matching the loader manifest parser and docs. Centralize loader warning formatting around PmVersionBoundEvaluation and separate multiple assertExtensionManifestCompatible blocking findings with semicolons for readable CI output. Verification: pnpm build; focused version/loader/SDK tests (277 tests); pnpm quality:static; isolated temp PM_PATH/PM_GLOBAL_PATH smoke; node scripts/run-tests.mjs coverage (4952 tests, 100/100/100/100).
|
Review feedback addressed in 7a6489d. Please review the latest head again. @codex review |
|
To use Codex here, create a Codex account and connect to github. |
Address CodeRabbit feedback by naming the pm-knma and pm-hng2 lineage beside the SDK compatibility helper documentation. Verification: pnpm build; pnpm quality:static; pnpm quality:docs-skills.
|
CodeRabbit docs feedback addressed in a9ed3b3. Please review the latest head again. @codex review |
|
To use Codex here, create a Codex account and connect to github. |
|
✅ Action performedFull review finished. |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Code Review
This pull request introduces an author-time version-compatibility preflight primitive to the SDK. It extracts the version parsing and comparison logic from the runtime loader into a new shared core module (src/core/extensions/version-compat.ts) to ensure that author-time and runtime checks share a single source of truth. It adds checkExtensionManifestCompatibility as a pure synchronous analyzer and assertExtensionManifestCompatible as a throwing CI/test guard, complete with comprehensive unit tests and updated documentation. No review comments were provided, so there is no additional feedback to address.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review
This pull request extracts a shared version-compatibility core module (src/core/extensions/version-compat.ts) to serve as a single source of truth for both runtime and author-time version-bound checks. The runtime loader (src/core/extensions/loader.ts) is updated to delegate to this core. Additionally, new author-facing SDK primitives are introduced: checkExtensionManifestCompatibility for synchronous compatibility analysis and assertExtensionManifestCompatible as a throwing test/CI guard. These changes are accompanied by comprehensive unit tests, updated documentation, and changelog entries. No review comments were provided, so there is no additional feedback to address.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Summary
PM lineage
Verification
GitHub/release/observability
Summary by Sourcery
Introduce shared extension manifest version-compatibility core and expose SDK helpers for author-time compatibility checks and CI guards.
New Features:
Enhancements:
Documentation:
Tests:
Chores: