SDK extension inventories, scoped activation, and stable agent context - #884
Conversation
Deliver a cohesive SDK/CLI context-management tranche across pm-021kdp, pm-j0w7j9, pm-77okxr, pm-h85e, pm-4uplae, and pm-2cv2o1. Persist typed contribution inventories, honor command-scoped activation, retain bounded cache variants, expose token-bounded extension health, improve failed extension-command recovery, and refresh vulnerable transitive dependencies. Verification includes 6,791 tests at 100/100/100/100 coverage, strict lint/docstring/duplication gates, packed npm and Bun consumers, scaffolded extension activation, real-scale alternating-cache measurements, secrets scanning, and zero pnpm audit findings.
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
@greptileai please perform a full review of this broad SDK/CLI context-management tranche. @coderabbitai full review |
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 59 minutes. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis change adds schema-versioned extension contribution inventories, static activation discovery, persisted runtime metadata, command-specific recovery diagnostics, extension health reporting, context-aware cache variants, dependency updates, and project execution records. ChangesExtension contribution inventories and activation
Context health and cache behavior
Project metadata and dependency maintenance
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Manifest as Extension manifest
participant Loader as Extension loader
participant Probe as Runtime probe
participant State as Managed state
participant CLI as CLI activation
participant Context as Context command
Manifest->>Loader: provide contribution inventory
Loader->>Probe: expose normalized extension metadata
Probe->>State: persist activation-derived inventory
CLI->>Loader: inspect static contribution paths
Loader-->>CLI: return activation decision
Context->>Loader: discover installed extensions
Loader-->>Context: return diagnostics and health metadata
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
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 |
Reviewer's GuideImplements static extension contribution inventories and scoped activation semantics, adds token-bounded extension health to Sequence diagram for pm context extension health projectionsequenceDiagram
actor User
participant CliContextCommand as pm_context_cli
participant SdkContext as runContext
participant HealthProjection as resolveContextExtensionHealthProjection
participant ExtensionDiscovery as discoverExtensions
User->>CliContextCommand: pm context --no-extension-health?
CliContextCommand->>SdkContext: runContext(ContextOptions)
SdkContext->>HealthProjection: resolveContextExtensionHealthProjection(options.noExtensionHealth, pmRoot, settings)
HealthProjection->>ExtensionDiscovery: discoverExtensions({ pmRoot, settings, cwd, noExtensions: false })
ExtensionDiscovery-->>HealthProjection: discovery.discovered
HealthProjection-->>SdkContext: { extension_health? }
SdkContext->>SdkContext: Object.assign(result, extension_health)
SdkContext-->>CliContextCommand: ContextResult
CliContextCommand-->>User: context JSON/markdown with extension_health
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Regenerate the full CLI/SDK/MCP contract snapshot, public error-code catalog, and SDK surface after hosted CI identified the missing noExtensionHealth and extension_command_activation_failed projections. Link the exact hosted gate and generated artifacts to pm-h85e and pm-4uplae.
|
Regarding #884 (comment): acknowledged. Gemini Code Assist has ceased review activity, so this notice provides no actionable code finding; the PR remains covered by the active hosted security, analysis, coverage, and requested review agents. |
|
Regarding #884 (comment): acknowledged the CodeRabbit usage-limit notice. The exact head is now |
|
Regarding #884 (comment): the initial CodeRabbit run covered |
|
Regarding #884 (comment): the Sourcery guide accurately captures the six behavior areas. The follow-up head additionally publishes |
|
Regarding #884 (comment): the unchanged CodSpeed benchmark set is consistent with the PR. The cache regression is additionally verified on the real 2,000+ item tracker: restored alternating list variants are 0.432s/0.346s and no longer mutually trigger 5s corpus rebuilds. |
|
Regarding #884 (comment): acknowledged and verified. Codecov reports every modified coverable line covered; the complete local suite independently passes 6,791 tests at exact 100% statements/branches/functions/lines. |
|
Regarding Sourcery review |
|
@greptileai please perform a full exact-head review of @coderabbitai full review The new head fixes the first CI finding by regenerating the CLI/SDK/MCP contract snapshot, public error-code catalog, and SDK surface; |
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 44 minutes. |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/core/store/item-metadata-cache.ts (2)
392-429: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winFix the
active === nullshort-circuit inloadCache.The guard returns
activebefore checking the fingerprinted variant whenactive === null. Compare withloadBodyCache(line 449) andloadCollectionsCache(line 475): both useactive?.context_fingerprint !== contextFingerprint, which istruewhenactiveisnull, so both correctly attempt the fingerprinted variant even when the primary cache is missing.loadCachedoes not do this. If the primary metadata cache file is absent (deleted, corrupted, or pruned) but the requested context's fingerprinted variant exists on disk,loadCachereturnsnulland skips the variant entirely, forcing a full rebuild and never reporting themetadata_cache_context_changeddiagnostic. AlignloadCachewith the other two loaders.🐛 Proposed fix
const cachePath = getCachePath(pmRoot); const active = await loadEnvelopeMemoized(cachePath, parse); - if ( - !contextFingerprint || - active === null || - active.context_fingerprint === contextFingerprint - ) { - return active; - } + if (!contextFingerprint || active?.context_fingerprint === contextFingerprint) { + return active; + } const retained = await loadEnvelopeMemoized( getContextCachePath(cachePath, contextFingerprint), parse, ); if (retained === null) { appendWarning( diagnostics, - `metadata_cache_context_changed:${active.context_fingerprint}->${contextFingerprint}`, + `metadata_cache_context_changed:${active?.context_fingerprint ?? "none"}->${contextFingerprint}`, ); } return retained;🤖 Prompt for 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. In `@src/core/store/item-metadata-cache.ts` around lines 392 - 429, Update the guard in loadCache so a missing active envelope does not short-circuit loading the context-specific variant. Align its condition with loadBodyCache and loadCollectionsCache by using the optional active context_fingerprint comparison, while preserving the existing return and metadata_cache_context_changed diagnostic behavior.
431-481: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider parity for context-mismatch diagnostics.
loadCacherecords ametadata_cache_context_changeddiagnostic when no matching fingerprinted variant exists.loadBodyCacheandloadCollectionsCachehave nodiagnosticsparameter and silently returnnullin the same scenario. Body/collections cache misses are just as impactful (they force a full re-read of item bodies/collections) but are invisible to callers inspectingcacheDiagnostics. Extend the same diagnostic reporting to these two loaders for consistency.🤖 Prompt for 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. In `@src/core/store/item-metadata-cache.ts` around lines 431 - 481, Extend loadBodyCache and loadCollectionsCache to accept the diagnostics sink used by loadCache, and record a metadata_cache_context_changed diagnostic when a context fingerprint is requested but no matching fingerprinted cache variant is found. Update their callers to pass the diagnostics object while preserving existing cache fallback and return behavior.src/sdk/extension.ts (1)
2370-2404: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winPreserve manifest contributions when runtime activation fails.
runtimeProbe.contribution_inventories[name]is a truthy object whenever the extension loads, even if activation fails and the activation summary records no registered surfaces. Theif (contributionInventory)check therefore still replaces the manifest-declaredcontributionsstored just before the runtime probe with an empty inventory, and the install result exposes the same emptycontributions.Only apply the runtime inventory when
activation.activatedis true; otherwise keepvalidated.manifest.contributionsfor both persisted state and the install result.🤖 Prompt for 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. In `@src/sdk/extension.ts` around lines 2370 - 2404, Update the contribution inventory handling in the install flow so runtimeProbe.contribution_inventories is persisted and returned only when activation.activated is true. When activation fails, retain validated.manifest.contributions in persisted.managedState and the install result instead of replacing it with the runtime inventory.
🤖 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 @.agents/pm/features/pm-021kdp.toon:
- Around line 33-45: Link sdk/public-surface.json to pm-021kdp by registering it
through the PM CLI and regenerating the derived artifacts. Update
.agents/pm/features/pm-021kdp.toon lines 33-45 to include the file, and preserve
the generated append-only entry in .agents/pm/history/pm-021kdp.jsonl lines 5-5;
do not edit the history file directly.
In @.agents/pm/features/pm-h85e.toon:
- Around line 46-53: The PM item’s affected-file list is missing the
release-readiness integration test. Register
tests/integration/release-readiness-runtime.spec.ts with pm using the
appropriate CLI, then regenerate the derived artifacts; update
.agents/pm/features/pm-h85e.toon at lines 46-53 and preserve the CLI-generated
append-only entry in .agents/pm/history/pm-h85e.jsonl at line 9 without editing
history directly.
In `@src/cli/register-list-query.ts`:
- Around line 1098-1101: Update the CLI option normalization before runContext
so Commander’s extensionHealth: false result is translated to noExtensionHealth:
true, matching the existing noTags translation in normalizeContextOptions. Add
CLI-level coverage verifying --no-extension-health suppresses the extension
health summary.
In `@src/core/extensions/contribution-inventory.ts`:
- Around line 128-175: Update createExtensionContributionInventory to
canonicalize summary.renderer_ownership before assigning it, reusing
normalizeRendererOwnership so each renderer’s commands are deduplicated and
sorted consistently with normalizeExtensionContributionInventory. Preserve the
existing conditional omission when renderer_ownership is absent.
In `@src/core/store/item-metadata-cache.ts`:
- Around line 580-589: Update the variants filter in the cache-pruning logic to
exclude the primary cache file by comparing each entry name against the primary
filename, while retaining only fingerprinted files matching the existing stem
and extension criteria. Ensure the primary file cannot be counted toward
MAX_CACHE_CONTEXTS or selected for removal.
- Around line 571-576: Update the context-fingerprinted write path using
contextPath and envelopeMemo so it stores the just-written envelope in the memo
after writeFileAtomic, matching the primary cache write behavior, rather than
deleting the entry.
- Around line 590-599: Update the pruning logic in the variants Promise.all
within persistCache to handle fs.stat failures per variant. Treat a missing or
otherwise unavailable variant as already gone, exclude it from age sorting and
deletion, and ensure one rejected stat cannot propagate out of persistCache or
interrupt metadata/body/collections persistence.
- Around line 566-570: In persistCache, extract
path.dirname(path.dirname(cachePath)) into a single pmRoot value and reuse it in
the getCachePath, getBodyCachePath, and getCollectionsCachePath comparisons.
Keep the existing cache-path matching behavior unchanged.
In `@tests/integration/extension-command-recovery.integration.spec.ts`:
- Around line 29-45: Guard the built-artifact dependency in the integration test
before invoking spawnSync: validate that dist/cli.js exists and fail with a
clear build-related message if it is missing, then preserve the existing process
status and recovery-message assertions. Alternatively, switch this test to
execute src/cli.ts through tsx consistently with
extension-startup.integration.spec.ts.
In `@tests/unit/cli/cli-main-errors.spec.ts`:
- Around line 1433-1445: Extend the hasGlobalExtensionContributions tests around
the existing assertion to cover the renderer comparison branch: add one case
where renderer_overrides contains a format without a matching renderer_ownership
record and expect eager activation, plus another where every overridden format
is owned and expect no renderer contribution. Use the existing contribution
object shape and keep the hooks and empty-inventory assertions unchanged.
In `@tests/unit/core/item/item-metadata-cache.spec.ts`:
- Around line 679-684: In the retention-count assertion for retainedContexts,
replace the broad range checks with an exact expectation of four files. Keep the
existing metadata-cache filename filtering and test setup unchanged so the
assertion verifies the four-variant retention boundary and catches pruning
off-by-one errors.
- Around line 688-733: Add an analogous test beside “keeps cache publication
best-effort when retained-context enumeration fails” that spies on fs.stat and
throws for one retained variant path, then verifies
listAllDocumentCandidatesCached still completes successfully. Exercise the
retained-variant persistence path and restore the spy in cleanup, confirming the
stat failure is tolerated after the corresponding persistCache guard is added.
---
Outside diff comments:
In `@src/core/store/item-metadata-cache.ts`:
- Around line 392-429: Update the guard in loadCache so a missing active
envelope does not short-circuit loading the context-specific variant. Align its
condition with loadBodyCache and loadCollectionsCache by using the optional
active context_fingerprint comparison, while preserving the existing return and
metadata_cache_context_changed diagnostic behavior.
- Around line 431-481: Extend loadBodyCache and loadCollectionsCache to accept
the diagnostics sink used by loadCache, and record a
metadata_cache_context_changed diagnostic when a context fingerprint is
requested but no matching fingerprinted cache variant is found. Update their
callers to pass the diagnostics object while preserving existing cache fallback
and return behavior.
In `@src/sdk/extension.ts`:
- Around line 2370-2404: Update the contribution inventory handling in the
install flow so runtimeProbe.contribution_inventories is persisted and returned
only when activation.activated is true. When activation fails, retain
validated.manifest.contributions in persisted.managedState and the install
result instead of replacing it with the runtime inventory.
🪄 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 Plus
Run ID: 4ef1f79f-61d1-4909-85a7-318a6e80d341
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (47)
.agents/pm/extensions/.managed-extensions.json.agents/pm/features/pm-021kdp.toon.agents/pm/features/pm-h85e.toon.agents/pm/history/pm-021kdp.jsonl.agents/pm/history/pm-2cv2o1.jsonl.agents/pm/history/pm-4uplae.jsonl.agents/pm/history/pm-77okxr.jsonl.agents/pm/history/pm-h85e.jsonl.agents/pm/history/pm-j0w7j9.jsonl.agents/pm/issues/pm-2cv2o1.toon.agents/pm/issues/pm-4uplae.toon.agents/pm/issues/pm-77okxr.toon.agents/pm/issues/pm-j0w7j9.toondocs/EXTENSIONS.mddocs/schemas/extension-manifest.schema.jsonpackage.jsonpackages/pm-governance-audit/extensions/governance-audit/manifest.jsonpnpm-workspace.yamlsdk/public-surface.jsonsrc/cli/commander-usage.tssrc/cli/extension-recovery.tssrc/cli/main.tssrc/cli/register-list-query.tssrc/core/extensions/contribution-inventory.tssrc/core/extensions/extension-candidate.tssrc/core/extensions/extension-types.tssrc/core/extensions/loader.tssrc/core/store/item-metadata-cache.tssrc/sdk/authoring.tssrc/sdk/cli-contracts/flag-contracts.tssrc/sdk/cli-contracts/tool-option-contracts.tssrc/sdk/cli-contracts/tool-parameter-tables.tssrc/sdk/extension.tssrc/sdk/extension/managed-state.tssrc/sdk/extension/runtime-summary.tssrc/sdk/extension/shared.tssrc/sdk/query/context.tstests/fixtures/contracts/full.jsontests/integration/extension-command-recovery.integration.spec.tstests/integration/extension-startup.integration.spec.tstests/integration/release-readiness-runtime.spec.tstests/unit/cli/cli-main-errors.spec.tstests/unit/cli/recovery-context-usage.spec.tstests/unit/commands/context-extension-health.spec.tstests/unit/core/item/item-metadata-cache.spec.tstests/unit/extensions/contribution-inventory.spec.tstests/unit/extensions/extension-loader.spec.ts
Map Commander negated extension-health options into the SDK contract, memoize context variants after publication, and make bounded cache pruning resilient to concurrent removals. Add exact retention, filesystem-race, real CLI option, and built-entrypoint regression coverage while recording review evidence on the canonical pm items.
|
CodeRabbit exact-head follow-up: all 12 inline threads were individually acknowledged and reacted to; the nine actionable findings are fixed in |
|
@coderabbitai full review\n\n@greptileai please perform a full exact-head review of |
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 25 minutes. |
|
Regarding CodeRabbit review invocation |
Attach the green hosted matrix, 6,792-test 100% coverage result, resolved CodeRabbit findings, and explicit reviewer quota limitations to each active canonical item.
|
@coderabbitai full review |
|
@greptileai please perform a full exact-head review of |
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 22 minutes. |
|
Regarding the final CodeRabbit invocation on |
Summary
This broad SDK/CLI context-management tranche makes extension contributions statically discoverable and durable, honors declared activation scopes across every capability, stabilizes metadata caches across extension modes, adds token-bounded extension health to
pm context, and turns failed declared extension commands into accurate actionable recovery. It also refreshes newly vulnerable transitive dependencies and the current compatibletsxpatch.activation.commandsauthoritative while preserving conservative compatibility for legacy packages and eager global contributions.--no-extensionsreads stop evicting one another.extension_healthcontext with--no-extension-health; empty installs add zero bytes and the large-workspace baseline remains exactly 1,231 estimated tokens.brace-expansionand PostCSS floors; refresh the lockfile andtsx4.23.5.PM lineage
Verification
pnpm auditreports no known vulnerabilities. GitHub Dependabot, code-scanning, and secret-scanning APIs reported zero open alerts before publication.npxand Bun/bunxconsumers were initialized in unrelated temporary roots; create/context JSON flows passed. A scaffolded third-party extension persisted contributions, invoked its lazily activated command, and appeared in context health.npxsmoke and 88-command package-first dogfood suite pass.pm validatereports zero history drift. The graph has 10,781 edges with no active isolated or degree-one items; remaining graph findings are legacy informational history.pm-changelog@2026.8.3is current and generatedCHANGELOG.mdis unchanged because these items remain in progress until merge/release proof.Compatibility notes
npm-package-arg14 is intentionally not adopted because its Node engine excludes the supported Node 22.18 floor. TypeScript 7 is intentionally deferred because the current typescript-eslint peer range is below 6.1. These are incompatible majors rather than unattended safe updates.Summary by Sourcery
Stabilize extension-related runtime behavior by introducing a static contribution inventory, tightening activation scoping, preserving multiple metadata cache variants per context, and exposing installed extension health in pm context, alongside improved CLI recovery for failed extension commands and refreshed dependency floors.
New Features:
Enhancements:
Build:
Documentation:
Tests:
Summary by cubic
Persist extension contributions and enforce command-scoped activation to load only what’s needed. Adds extension health to
pm context, hardens and stabilizes cache variants across modes, improves failed command recovery, and updates vulnerable deps.New Features
createExtensionContributionInventory,normalizeExtensionContributionInventory).activation.commandsacross all capabilities; uses static contributions for matching.--no-extensionsmodes don’t evict each other.pm contextincludes token-boundedextension_health; opt out with--no-extension-health(SDK:noExtensionHealth).extension_command_activation_failedand JSONextension_command_failure.contributions; publishes CLI/SDK contracts for--no-extension-healthand the new error code.Dependencies
brace-expansion≥ 5.0.9,postcss≥ 8.5.23; bumpedtsxto^4.23.5.npm-package-arg@14, TypeScript 7).Written for commit 57515f5. Summary will update on new commits.