Repository navigation
feat(sdk): govern runtime context, write safety, and verification gates - #935
Conversation
Add SDK-owned stale project-runtime compatibility, action-aware mixed command classification, source-context write fencing for linked tests, and reusable host environment fault contracts.\n\nMake the gate registry own the canonical local preflight receipt, strengthen CLI refusal ownership and untracked-file replication checks, document the new runtime boundaries, and preserve exact SDK surface contracts.\n\nResolve the nanoid advisory with a narrow patched floor, regenerate the pm-changelog output, and record complete PM lineage and verification evidence.
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe change adds runtime compatibility checks, linked-test source-write isolation, shared host filesystem error translation, registry-driven release preflight execution, refusal-parity validation, dependency remediation records, and related tests and documentation. ChangesRuntime safety and release governance
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Agent
participant CLI
participant SDK
participant Project
participant ReleaseGates
Agent->>CLI: invoke command
CLI->>SDK: inspect project runtime compatibility
SDK->>Project: read manifests and lockfiles
SDK-->>CLI: allow read, allow override, or reject stale mutation
CLI->>ReleaseGates: run registry-defined preflight
ReleaseGates-->>CLI: report gate results and refusal parity
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
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 GuideThis PR introduces SDK-level runtime compatibility enforcement and host-environment fault handling, adds a source-context write policy for linked tests and merge-install, makes the release gate registry own the canonical local preflight and receipt validation, tightens CLI refusal ownership reporting, and pins nanoid to a patched version for a security advisory. Sequence diagram for CLI runtime compatibility enforcementsequenceDiagram
actor User
participant CliEntrypoint as cli_ts
participant RuntimeBoundary as runRuntimeCompatibleCli
participant RuntimeCompat as assertProjectRuntimeCompatibility
participant CliMain as runCliWithBundleIntegrity
User->>CliEntrypoint: invoke_cli
CliEntrypoint->>RuntimeBoundary: runRuntimeCompatibleCli(executingVersion, projectRoot, argv, allowStale)
alt executingVersion_defined
RuntimeBoundary->>RuntimeCompat: assertProjectRuntimeCompatibility({executingVersion, projectRoot, argv, allowStale})
RuntimeCompat-->>RuntimeBoundary: ProjectRuntimeCompatibilityResult
end
alt compatible_invocation
RuntimeBoundary->>CliMain: runCliWithBundleIntegrity(argv, cliEntrypointPath, import_cli_main, writeError)
CliMain-->>RuntimeBoundary: ok_or_PmCliError
else stale_mutation
RuntimeCompat-->>RuntimeBoundary: throw PmCliError(project_runtime_stale_mutation)
end
alt PmCliError_thrown
RuntimeBoundary->>RuntimeBoundary: formatPmCliErrorForDisplay_or_formatPmCliErrorForJson
RuntimeBoundary-->>CliEntrypoint: writeError(formatted_error)
RuntimeBoundary->>RuntimeBoundary: set_process_exitCode
else unexpected_error
RuntimeBoundary-->>CliEntrypoint: rethrow_error
end
Sequence diagram for gate-registry local preflight receipt validationsequenceDiagram
actor Developer
participant RunGates as run_gates_mjs
participant RegistryFile as gate_registry_json
participant Validator as validateGateRegistry
Developer->>RunGates: node scripts/release/run-gates.mjs
RunGates->>RunGates: runCheckedStep(...)
RunGates-->>Developer: checks_array
Developer->>RunGates: request_json_or_text_output
RunGates->>RegistryFile: readFileSync(gate-registry.json)
RegistryFile-->>RunGates: registry_object
RunGates->>RunGates: assertRegistryPreflightReceipt(checks)
RunGates->>Validator: validateGateRegistry(registry, {discovered})
Validator-->>RunGates: violations
alt receipt_matches_registry && violations_empty
RunGates-->>Developer: { ok: true, checks }
else receipt_mismatch_or_violations
RunGates->>RunGates: fail("Local preflight drifted" or "Gate registry validation failed")
RunGates-->>Developer: nonzero_exit
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
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! |
|
@coderabbitai full review @greptileai please review this exact head. The local Greptile gate reported |
|
Your plan includes PR reviews subject to rate limits. Reviews are available now. |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/unit/scripts/release/surface-replication-gate.spec.ts (1)
158-184: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd an ownership rejection test.
These assertions cover the valid
all_occurrencescase only. Add cases that omitrule_ownershipand set it to a different value. Assert thatvalidateSurfaceReplicationreturnsok: falseand reports the refusal violation. This protects the fail-closed condition inscripts/release/surface-replication-gate.mjslines 260-269.🤖 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 `@tests/unit/scripts/release/surface-replication-gate.spec.ts` around lines 158 - 184, Add tests around the existing validateSurfaceReplication ownership case for configurations that omit rule_ownership and that use a non-all_occurrences value. Assert each report has ok: false and includes the expected refusal violation, while preserving the current valid-case assertions and fixture setup.
🤖 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/RELEASING.md`:
- Around line 153-158: Move the canonical pnpm verify:preflight step in the
release checklist to after the final implementation commit has been pushed and
before the hosted-analysis-dependent checks. Preserve the existing command and
ensure the documented sequence establishes the required hosted evidence first.
In `@docs/SDK_RUNTIME_BOUNDARIES.md`:
- Around line 47-54: Remove private release-operation details from
docs/SDK_RUNTIME_BOUNDARIES.md lines 47-54, replacing the release-gate
implementation description with the public CLI/SDK refusal contract. Update
CHANGELOG.md lines 13 and 31 to remove refusal counts, ownership, gate topology,
and command details; describe the user-visible consistency fix and delivered
verification outcome instead.
In `@scripts/release/gate-registry.mjs`:
- Around line 180-240: Make the registry the source of local gate execution and
ensure skipped gates cannot receive successful receipts. In
scripts/release/gate-registry.mjs lines 180-240, extend validLocalPreflightStep
and validateLocalPreflight to require executable step definitions and an
explicit skip policy; in scripts/release/run-gates.mjs lines 62-77, execute
those registry-defined steps and validate receipt status including declared
skips. Update docs/RELEASING.md lines 160-164 and docs/TESTING.md lines 38-43 to
describe the implemented registry-driven execution and selection-manifest
behavior.
In `@src/cli/runtime-compatibility-boundary.ts`:
- Around line 46-50: Update the jsonErrors detection near outputFormatIndex to
also recognize the inline --output-format=json argument, while preserving the
existing --json and separate-value checks. Ensure runtime compatibility refusal
output remains JSON for either Commander-supported output-format syntax.
In `@src/sdk/environment/project-runtime-compatibility.ts`:
- Around line 315-334: Update textLockPin to restrict parsing to the lockfile
entry beginning at the matched PACKAGE_NAME, stopping at the next package-entry
boundary rather than using a fixed 600-character window. Within that bounded
entry, prefer the explicit version field and only return a date-like version
belonging to that entry, preserving undefined when no valid pin is found.
- Around line 82-88: The argv parsing logic must recognize both separated and
equals-form options. In
src/sdk/environment/project-runtime-compatibility.ts:82-88, update hasAnyToken
to compare each argument’s portion before “=” and route the direct argv.includes
checks at lines 132, 136, 156, 179, and 389 through it; in
src/cli/runtime-compatibility-boundary.ts:46-50, update the output-format
selection to accept --output-format=json as well as --output-format json.
- Around line 279-300: Update the dependencyPin comment to describe extracting
the highest explicit pm date version, matching its descending sort and index-0
result. In dependencyPin, skip dependency specifiers beginning with “<” or
expressing exclusion (such as “!=”) before applying VERSION_PATTERN, so only
valid minimum pins are added to versions.
- Around line 384-401: Update command resolution for isProjectMutatingInvocation
and commandFromArgv to share a helper that returns the command and its resolved
index while skipping GLOBAL_VALUE_FLAGS values. Use that index when slicing
positionals, and remove the independent argv.findIndex scan so classifiers
receive only arguments after the actual command.
In `@src/sdk/environment/source-context.ts`:
- Around line 31-42: Update source-context access resolution in
src/sdk/environment/source-context.ts lines 31-42 to default to write only when
PM_SOURCE_CONTEXT_ACCESS is absent or explicitly equals the supported write
mode; resolve empty, misspelled, and other present unsupported values to
read_only so source_writes_allowed remains false. Add coverage in
tests/unit/sdk/source-context.spec.ts lines 15-39 for write, empty, and
unrecognized values, asserting unsupported values do not permit source writes.
In `@src/sdk/workspace-snapshot.ts`:
- Around line 40-44: Update SNAPSHOT_HOST_FAULT_CODES.resource so resource
faults use a resource-specific snapshot error code instead of
workspace_snapshot_storage_exhausted; leave the capacity and permission mappings
unchanged.
In `@tests/unit/cli/runtime-compatibility-boundary.spec.ts`:
- Around line 57-69: Strengthen the test “runs without a readable executable
version and returns no exit code” by explicitly asserting that the
runtime-compatible CLI path leaves process.exitCode undefined, while preserving
the existing run invocation assertion.
---
Outside diff comments:
In `@tests/unit/scripts/release/surface-replication-gate.spec.ts`:
- Around line 158-184: Add tests around the existing validateSurfaceReplication
ownership case for configurations that omit rule_ownership and that use a
non-all_occurrences value. Assert each report has ok: false and includes the
expected refusal violation, while preserving the current valid-case assertions
and fixture setup.
🪄 Autofix
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: 65a5b607-9981-4ae7-a651-72f4e97f927b
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (55)
.agents/pm/chores/pm-8l1m5t.toon.agents/pm/chores/pm-ksr40d.toon.agents/pm/extensions/.managed-extensions.json.agents/pm/history/pm-0xmajx.jsonl.agents/pm/history/pm-1eted6.jsonl.agents/pm/history/pm-3lhth4.jsonl.agents/pm/history/pm-5dwz1a.jsonl.agents/pm/history/pm-8l1m5t.jsonl.agents/pm/history/pm-alhqbz.jsonl.agents/pm/history/pm-e70zh5.jsonl.agents/pm/history/pm-ei6x66.jsonl.agents/pm/history/pm-ksr40d.jsonl.agents/pm/history/pm-zjelve.jsonl.agents/pm/issues/pm-0xmajx.toon.agents/pm/issues/pm-1eted6.toon.agents/pm/issues/pm-3lhth4.toon.agents/pm/issues/pm-5dwz1a.toon.agents/pm/issues/pm-alhqbz.toon.agents/pm/issues/pm-e70zh5.toon.agents/pm/issues/pm-zjelve.toon.agents/pm/tasks/pm-ei6x66.toonCHANGELOG.mddocs/AGENT_RUNTIME_PRIMITIVES.mddocs/RELEASING.mddocs/SDK_RUNTIME_BOUNDARIES.mddocs/TESTING.mdpackage.jsonpnpm-workspace.yamlscripts/release/gate-registry.jsonscripts/release/gate-registry.mjsscripts/release/run-gates.mjsscripts/release/surface-replication-gate.mjsscripts/release/surface-replication-sets.jsonsdk/public-surface.jsonsrc/cli.tssrc/cli/runtime-compatibility-boundary.tssrc/sdk/environment/host-environment-errors.tssrc/sdk/environment/project-runtime-compatibility.tssrc/sdk/environment/source-context.tssrc/sdk/generated-error-code-catalog.tssrc/sdk/index.tssrc/sdk/merge/index.tssrc/sdk/merge/install.tssrc/sdk/test/execution.tssrc/sdk/test/parsers.tssrc/sdk/workspace-snapshot.tstests/unit/cli/runtime-compatibility-boundary.spec.tstests/unit/scripts/release/gate-registry.spec.tstests/unit/scripts/release/run-gates.spec.tstests/unit/scripts/release/surface-replication-gate.spec.tstests/unit/sdk/host-environment-errors.spec.tstests/unit/sdk/merge-safety.spec.tstests/unit/sdk/project-runtime-compatibility.spec.tstests/unit/sdk/source-context.spec.tstests/unit/sdk/workspace-snapshot.spec.ts
Make the release gate registry the executable source of truth, record explicit skipped receipts, harden stale-runtime flag and lockfile parsing, fail closed on inherited source access, and separate snapshot resource exhaustion from storage capacity. Regenerate public contracts and changelog wording, and add exact regression coverage for all PR #935 review findings.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/sdk/environment/project-runtime-compatibility.ts (1)
409-412: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winSkip global option values after the command.
Line 411 removes
--authorbut retainsalice. Forschema --author alice add-type Bug, the classifier receivesaliceas the first positional and returns read-only. A stale runtime can then run a mutating command.Skip the value after every
GLOBAL_VALUE_FLAGStoken while buildingpositionals. Add a regression case for a global option afterschema.Based on PR objectives: mutating commands must fail closed.
🤖 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/environment/project-runtime-compatibility.ts` around lines 409 - 412, Update the positional-argument construction to skip both each GLOBAL_VALUE_FLAGS token and its following value, including when the option appears after the command; preserve unrelated positional arguments such as add-type and ensure mutating commands fail closed. Add a regression case covering schema --author alice add-type Bug.
🤖 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.
Outside diff comments:
In `@src/sdk/environment/project-runtime-compatibility.ts`:
- Around line 409-412: Update the positional-argument construction to skip both
each GLOBAL_VALUE_FLAGS token and its following value, including when the option
appears after the command; preserve unrelated positional arguments such as
add-type and ensure mutating commands fail closed. Add a regression case
covering schema --author alice add-type Bug.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 80aafeaf-911f-403e-a614-5d3e26714eca
📒 Files selected for processing (29)
.agents/pm/history/pm-0xmajx.jsonl.agents/pm/history/pm-dskxwf.jsonl.agents/pm/history/pm-ei6x66.jsonl.agents/pm/history/pm-n41vay.jsonl.agents/pm/issues/pm-0xmajx.toon.agents/pm/issues/pm-dskxwf.toon.agents/pm/issues/pm-n41vay.toon.agents/pm/tasks/pm-ei6x66.toonCHANGELOG.mddocs/RELEASING.mddocs/SDK_RUNTIME_BOUNDARIES.mddocs/TESTING.mdscripts/release/gate-registry.jsonscripts/release/gate-registry.mjsscripts/release/run-gates.mjssdk/public-surface.jsonsrc/cli/runtime-compatibility-boundary.tssrc/sdk/environment/project-runtime-compatibility.tssrc/sdk/environment/source-context.tssrc/sdk/generated-error-code-catalog.tssrc/sdk/workspace-snapshot.tstests/fixtures/contracts/full.jsontests/integration/release-automation-contract.spec.tstests/unit/cli/runtime-compatibility-boundary.spec.tstests/unit/scripts/release/gate-registry.spec.tstests/unit/scripts/release/run-gates.spec.tstests/unit/sdk/project-runtime-compatibility.spec.tstests/unit/sdk/source-context.spec.tstests/unit/sdk/workspace-snapshot.spec.ts
Extend the public SDK compatibility result with typed stale-read diagnostics, emit machine-readable and human CLI warnings while preserving stdout, and exercise context/health/help transports through unit and packaged acceptance coverage. Refresh generated contracts, SDK surface classification, changelog, and the completed pm-1eted6 evidence trail.
Keep stale-runtime mutation classification fail closed when global value flags occur after the command, and cover schema --author alice add-type as a mutating regression. Record the exact-head CodeRabbit remediation on pm-n41vay.
|
Valid fail-closed parsing finding. Fixed at f2e7775 by skipping each global value flag and its following value while deriving post-command positionals; added schema --author alice add-type Bug regression coverage. Focused SDK/CLI suite passes 76 tests. |
|
Useful consolidated walkthrough. This broad scope is intentional and linked to the canonical PM items in the PR description; the repository static-quality gate reports 100% docstring coverage, superseding the bot's changed-file heuristic. All actionable inline findings and the later classifier finding are fixed through f2e7775. |
|
CodSpeed result acknowledged. The benchmark workflow is part of the exact-head required-check inventory and will be evaluated after the current f2e7775 run settles. |
|
Codecov report acknowledged. Local exact coverage is 100/100/100/100 with zero uncovered counts; the exact-head hosted coverage result remains part of the merge gate. |
|
Acknowledged. The requested full review was completed, every actionable finding was handled, and the later outside-diff positional-classifier finding is fixed at f2e7775 with regression coverage. |
|
No review findings were produced because the provider reported a rate limit. This is recorded as an unavailable review signal, not approval; other exact-head reviews and required checks remain enforced. |
|
Actionable review acknowledged. The reported findings were validated against current code, fixed through f2e7775, covered by focused regressions and exact repository coverage, and all inline threads were resolved with commit-specific replies. |
|
Exact-head review request for f2e7775 after all prior findings and the stale-read acceptance gap were remediated. @coderabbitai full review |
|
|
|
The requested exact-head full review could not run because CodeRabbit rate-limited it. This is treated as an unavailable provider signal, not an approval. Exact-head f2e7775 has all hosted checks green, no unresolved threads, and every finding from the completed review rounds is fixed and acknowledged. |
Record the fully green f2e7775 hosted check inventory, provider limitations, complete review acknowledgements, and corrected resolution/actual-result metadata for pm-n41vay. Regenerate the package-owned changelog entry and release the final active claim.
|
Final exact-head review request for 13aabce. This commit contains only PM closeout history/item metadata and the package-generated changelog entry after the fully green f2e7775 inventory. @coderabbitai full review |
|
|
|
Final exact-head review was requested after the PM-only closeout commit, but CodeRabbit again reported rate limiting. No review ran, so this is an unavailable signal rather than approval. Exact head 13aabce is mergeable CLEAN, every hosted check is green, and the fresh thread inventory is empty. |
Summary
PM lineage
Verification
Closes #926
Closes #933
Refs #934
Summary by Sourcery
Enforce SDK-governed runtime compatibility and host-environment fault handling, tighten source-context write safety, and formalize local/hosted gate parity and CLI refusal ownership while pinning a patched nanoid version.
New Features:
Bug Fixes:
Enhancements:
Build:
CI:
Documentation:
Tests:
Chores:
Summary by cubic
Adds SDK-governed runtime safety and a registry-owned, fail-closed preflight so stale pm binaries can’t mutate projects; stale reads now warn without blocking; linked tests inherit read-only source context; host faults are classified; pins
nanoidto 3.3.17.New Features - New features added
--json/equals-form flags; one-shot override viaPM_ALLOW_STALE_CLI=1(Warn before a stale global pm mutates a project pinned to a newer CLI/SDK #926, pm-zjelve).PM_SOURCE_CONTEXT_ACCESS=read_only; allow a single write withPM_ALLOW_SOURCE_CONTEXT_WRITES=1;resolveMergeInstallContextenables non-writing resolution and merge-install honors policy (Agent safety: nested PM writes in non-PM linked tests can mutate the source project #933).--versionstartup (pm-dskxwf).pnpm verify:preflightruns the canonical plan and records explicit skipped receipts; run fails on drift or undeclared steps; stronger per-occurrence CLI refusal ownership inventory and untracked-file detection; pinsnanoid3.3.17 (pm-n41vay).Migration - Steps needed for adoption
@unbrained/pm-clito the project’s pin, or setPM_ALLOW_STALE_CLI=1to proceed once; reads still work and now warn.PM_SOURCE_CONTEXT_ACCESS=read_only; setPM_ALLOW_SOURCE_CONTEXT_WRITES=1to permit a single nested write when needed.pnpm verify:preflightto run the canonical local gates; receipts and step set are enforced at exact Git HEAD.Written for commit 13aabce. Summary will update on new commits.