Skip to content

Fix: anchor state-cache payloads against Git GC#732

Merged
flyingrobots merged 15 commits into
mainfrom
v19-closeout-next-five
Jul 13, 2026
Merged

Fix: anchor state-cache payloads against Git GC#732
flyingrobots merged 15 commits into
mainfrom
v19-closeout-next-five

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Jul 12, 2026

Copy link
Copy Markdown
Member

Summary

  • upgrade git-cas to 6.1.0 and anchor live state-cache payload trees through a graph-scoped RootSet
  • make state-cache writes crash-safe with pre-anchoring, index compare-and-swap, guarded cleanup, and lazy adoption of legacy JSON-only references
  • add doctor retention findings and --repair-state-cache, documentation, and a real prune witness
  • harden the checkpoint boundaries found during review: one OR-Set wire implementation, canonical envelope delegation, runtime-honest dependencies, concurrent fallback writes, and one concept per receipt codec

Root cause

WARP persisted payload OIDs as JSON strings under refs/warp/.../state-cache. Git does not treat text containing an OID as a reachability edge, so git prune considered live payload trees dangling even while WARP's index still referred to them.

Verification

  • IRONCLAD pre-push: link, lint, policy, source/test/consumer types, public surface, Markdown, docs topology, and all six unit shards
  • local stable matrix: 7,408 passed; 2 skipped
  • repository coverage run: 7,447 passed; 2 skipped; 92.61% lines
  • focused review regression suite: 129 passed
  • real git prune -n --expire=now integration witness
  • current-head self-review and Code Lawyer review recorded in the PR discussion

Fixes #731

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds Git-backed state-cache retention inspection and repair, moves serialization into infrastructure codecs, changes checkpoint persistence to component artifacts, introduces a lint gate for vacuous test returns, and updates related CLI, tests, documentation, exports, and dependency versions.

Changes

State-cache retention and repair

Layer / File(s) Summary
Retention contracts and RootSet coordination
src/domain/services/state/*, src/ports/*, src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
Adds normalized retention reports and repair results, retention-capable cache ports, and RootSet adoption, publication, inspection, and repair workflows.
Cache adapter integration
src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts, src/infrastructure/adapters/GitGraphAdapter.ts, test/unit/infrastructure/adapters/*, test/integration/infrastructure/adapters/*
Anchors payload trees before index publication, adopts legacy retention, uses CAS index updates, and exposes retention inspection and repair.
Doctor CLI support
bin/cli/commands/doctor/*, bin/cli/schemas.ts, test/unit/cli/*, test/bats/cli-doctor.bats
Adds state-cache findings and the repair-state-cache option, including successful, partial, and failed repair outcomes.

Checkpoint and serialization changes

Layer / File(s) Summary
Checkpoint artifact storage
src/ports/CheckpointStorePort.ts, src/domain/services/state/checkpoint*, src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
Replaces the single state blob with separate CBOR state artifacts and routes checkpoint creation and loading through the checkpoint store.
Serialization boundaries
src/domain/services/state/*WireBoundary.ts, src/infrastructure/codecs/*, src/domain/crdt/ORSet.ts, src/domain/types/*
Moves ORSet, full-state, and canonical receipt serialization into dedicated codec modules and removes serialization methods from domain types.

Test-law and supporting updates

Layer / File(s) Summary
Vacuous-return linting
scripts/lint-test-vacuous-returns.ts, package.json, test/unit/scripts/*
Adds AST-based detection of bare returns in test callbacks and changes conditional test guards to explicit failures or registration-time skips.
Contracts, exports, and documentation
index.ts, legacy.ts, docs/topics/*, CHANGELOG.md, vitest.config.ts, scripts/lint-markdown-code-samples.ts, test/unit/*
Updates codec re-exports, generated API references, retention documentation, coverage thresholds, dependency versions, and related test contracts.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

  • git-stunts/git-warp#679 — Introduces the source-backed reference tooling connected to the regenerated API inventories.

Poem

I’m a rabbit guarding roots in the ground,
Keeping cache trees safely bound.
Coders moved bytes where codecs belong,
And tests now hop when returns go wrong.
Doctor repairs what Git cannot grow—
So prunable payloads stay safely aglow.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Most changes fit the retention fix, but the Markdown lint dist exclusion/test and coverage-threshold tweak appear unrelated to #731. Move unrelated lint/coverage cleanup into a separate PR, or explain why it is part of the Git GC retention fix scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 9.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: anchoring state-cache payloads against Git GC.
Description check ✅ Passed The description includes Summary, Issue, Test plan, and ADR checks, and it references Fixes #731.
Linked Issues check ✅ Passed The changes satisfy the linked issue’s requirements: RootSet anchoring, guarded cleanup, legacy adoption, repair findings, upgrade, and prune proof.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🤖 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 `@bin/cli/commands/doctor/stateCacheCapability.ts`:
- Around line 20-26: Update repairStateCache to catch failures from
stateCache.repairRetention() and convert them into the same warn/fail
DoctorFinding used by the doctor checks, instead of allowing the error to
propagate out of handleDoctor. Preserve the existing null return when repair is
not requested or stateCache is unavailable, and keep successful repairs using
stateCacheRepairFinding.
- Around line 14-16: Replace the dynamic import of CborCodec in
createRuntimeStateCache with a top-level static import, and use the imported
codec directly within the function. Remove the per-call import and preserve the
existing codec behavior.

In `@scripts/lint-test-vacuous-returns.ts`:
- Around line 84-89: Update testFilesFromRipgrep to remove the runtime
dependency on the undeclared rg executable. Enumerate matching .ts and .js files
under the test directory using Node filesystem APIs, preserving the current
string-array result and empty-directory behavior; do not rely on execFileSync or
ripgrep.

In `@src/domain/services/state/CheckpointSerializer.ts`:
- Around line 33-42: Extract the shared OR-Set wire-format shapes and helpers
used by serializeORSet, deserializeORSet, sortEncodedDots, and the
entry/tombstone utilities into a domain-owned module such as ORSetWireFormat.
Update CheckpointSerializer and ORSetCodec to import and reuse that module,
removing their duplicate SerializedORSet/ORSetWire definitions and
implementations while preserving both persistence paths’ existing behavior.

In `@src/domain/services/state/WarpStateCacheRetentionReport.ts`:
- Around line 14-26: Define a named constant for the shared
'E_CACHE_RETENTION_REPORT_INVALID' error code and use it in both normalizedNames
and the WarpStateCacheRetentionReport constructor, replacing each duplicated
string while preserving existing error behavior.

In `@src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts`:
- Around line 159-163: Update the lazy initializer in _getRootSet so a rejected
options.openRootSet(this.rootSetRef) promise clears rootSetPromise before
propagating the error. Preserve successful promise caching while allowing later
adoption, inspection, or repair calls to retry after a transient opening
failure.

In `@src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts`:
- Around line 215-227: Update _readIndexState so failures from readBlob or
_parseIndexBlob with a valid headOid are propagated to the caller instead of
returning _emptyIndex(). Preserve the existing empty-index result only when
_persistence.readRef finds no valid head, preventing subsequent mutations from
publishing an empty index after a failed read.
- Around line 270-275: Update _mutateIndex around _commitIndexMutation so
retries occur only for pre-commit CAS conflicts; once publishTransition has
successfully committed the index, propagate cleanup errors without re-running
the mutation or reporting the committed write as failed. Preserve retry behavior
for genuine CAS conflicts and use the existing commit/publish state to
distinguish post-commit failures.

In `@src/infrastructure/codecs/ORSetCodec.ts`:
- Around line 48-72: Update deserializeEntriesInto and deserializeTombstonesInto
to validate every dot before adding it to target, rejecting malformed or
non-string dot values at deserialization time rather than allowing them into the
sets. Reuse the existing dot validation/decoding mechanism, such as Dot.decode,
so invalid input fails clearly at the boundary while valid dots retain the
current behavior.

In `@src/infrastructure/codecs/ReceiptJsonCodec.ts`:
- Around line 1-16: Split ReceiptJsonCodec into separate codec files for
TickReceipt, EffectEmission, and DeliveryObservation, keeping each
canonicalization function with its corresponding type and sortedReplacer import.
Update all imports and references to use the new modules, and remove the bundled
file once no longer needed.

In `@src/infrastructure/codecs/WarpStateCborCodec.ts`:
- Around line 148-159: Define a named constant for the legacy patch-sha
placeholder and replace both hardcoded '0000' values in legacyNumericEdgeBirth
and edgeBirthWireToEventId with it.
- Around line 178-193: Update deserializeLWWRegister to defensively normalize
the decoded eventId fields using the same nullish fallbacks as
edgeBirthWireToEventId and legacyNumericEdgeBirth. Handle a missing eventId
safely and ensure lamport/opIndex default to 0 while writerId/patchSha default
to the established empty-value defaults before constructing the LWWRegister.

In
`@test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts`:
- Around line 67-78: Hoist the whitespace-splitting regular expression used by
prunableOids outside the map callback to module scope, then reuse that static
regex when splitting each output line.

In `@test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts`:
- Around line 44-45: Hoist the inline regular expressions used by the report
assertions into module-scope constants named EMPTY_NAME_ERROR and
EMPTY_ROOT_SET_ERROR, then replace the matching regex literals at all referenced
call sites with those constants.

In
`@test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts`:
- Line 72: Update the affected entry assignments in the test to use spread
syntax for iterable conversion instead of Array.from, including the occurrences
in the referenced test cases. Hoist the two repeated assertion regular
expressions into module-level constants and reuse those constants at each
assertion site.

In
`@test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts`:
- Line 29: Update the affected test cases to replace all three Array.from calls
with spread syntax, and move both assertion regular expressions into
module-level constants. Apply these changes at the usages around rootEntries and
the other referenced locations while preserving the existing assertions and
behavior.

In `@test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts`:
- Line 32: Update the affected test setup and assertions in the
GitCasWarpStateCacheAdapter tests: replace Array.from(...) around mutator
results with spread syntax, and move both repeated assertion regular expressions
to module-level constants. Apply these changes at all referenced occurrences
while preserving the existing test behavior.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 237399bf-c783-4477-b717-e0ec60214a6e

📥 Commits

Reviewing files that changed from the base of the PR and between 9bbf6c1 and 68fd04f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (63)
  • CHANGELOG.md
  • bin/cli/commands/doctor/checksStateCache.ts
  • bin/cli/commands/doctor/codes.ts
  • bin/cli/commands/doctor/index.ts
  • bin/cli/commands/doctor/stateCacheCapability.ts
  • bin/cli/commands/doctor/types.ts
  • bin/cli/schemas.ts
  • docs/topics/cas-first-memoized-materialization.md
  • docs/topics/cli.md
  • docs/topics/reference.md
  • index.ts
  • legacy.ts
  • package.json
  • scripts/lint-test-vacuous-returns.ts
  • src/domain/crdt/ORSet.ts
  • src/domain/services/state/CheckpointSerializer.ts
  • src/domain/services/state/WarpStateCacheRepairResult.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/domain/types/DeliveryObservation.ts
  • src/domain/types/EffectEmission.ts
  • src/domain/types/TickReceipt.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
  • src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts
  • src/infrastructure/adapters/GitGraphAdapter.ts
  • src/infrastructure/codecs/ORSetCodec.ts
  • src/infrastructure/codecs/ReceiptJsonCodec.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • src/ports/RuntimeStorageCapabilityPort.ts
  • src/ports/WarpStateCacheRetentionPort.ts
  • test/conformance/readonlyBytePropValueSnapshot.test.ts
  • test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts
  • test/runtime/deno/deno.json
  • test/unit/benchmark/TrieGeometryProfile.profile.test.ts
  • test/unit/cli/doctor-state-cache-retention.test.ts
  • test/unit/cli/doctor.test.ts
  • test/unit/cli/schemas.test.ts
  • test/unit/domain/WarpFacade.test.ts
  • test/unit/domain/WarpGraph.audit.test.ts
  • test/unit/domain/WarpGraph.seekDiff.test.ts
  • test/unit/domain/crdt/ORSet.test.ts
  • test/unit/domain/orset/session/StateSession.semilattice.property.test.ts
  • test/unit/domain/orset/shadow/ShadowTrieORSet.compaction.test.ts
  • test/unit/domain/orset/shadow/ShadowTrieORSet.test.ts
  • test/unit/domain/properties/Join.property.test.ts
  • test/unit/domain/properties/ORSet.property.test.ts
  • test/unit/domain/publicReadingSurface.behavior.test.ts
  • test/unit/domain/services/query/BoundedQueryNodePageReader.test.ts
  • test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts
  • test/unit/domain/types/DeliveryObservation.test.ts
  • test/unit/domain/types/EffectEmission.test.ts
  • test/unit/domain/types/TickReceipt.test.ts
  • test/unit/domain/utils/toBytes.test.ts
  • test/unit/domain/warp/RuntimeStateStore.test.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts
  • test/unit/infrastructure/adapters/NodeHttpAdapter.boundary.test.ts
  • test/unit/infrastructure/codecs/ORSetCodec.test.ts
  • test/unit/scripts/lint-test-vacuous-returns.test.ts
  • test/unit/scripts/v18-v17-public-read-legacy-reading-builder.test.ts
  • vitest.config.ts
💤 Files with no reviewable changes (5)
  • src/domain/types/EffectEmission.ts
  • src/domain/types/TickReceipt.ts
  • src/domain/types/DeliveryObservation.ts
  • test/unit/domain/crdt/ORSet.test.ts
  • src/domain/crdt/ORSet.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: coverage-threshold
  • GitHub Check: test-node (22)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Do not use direct imports from src/infrastructure/** in src/domain/** or src/ports/**; depend on a port instead.
Do not use direct Node built-ins in src/domain/** or src/ports/**; use a port instead.

Files:

  • bin/cli/commands/doctor/codes.ts
  • vitest.config.ts
  • test/unit/domain/publicReadingSurface.behavior.test.ts
  • test/unit/domain/services/query/BoundedQueryNodePageReader.test.ts
  • bin/cli/schemas.ts
  • test/unit/scripts/v18-v17-public-read-legacy-reading-builder.test.ts
  • test/unit/infrastructure/adapters/NodeHttpAdapter.boundary.test.ts
  • src/domain/services/state/WarpStateCacheRepairResult.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/ports/WarpStateCacheRetentionPort.ts
  • test/unit/domain/utils/toBytes.test.ts
  • test/conformance/readonlyBytePropValueSnapshot.test.ts
  • test/unit/cli/schemas.test.ts
  • test/unit/scripts/lint-test-vacuous-returns.test.ts
  • src/ports/RuntimeStorageCapabilityPort.ts
  • src/infrastructure/adapters/GitGraphAdapter.ts
  • test/unit/domain/WarpGraph.audit.test.ts
  • test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts
  • src/infrastructure/codecs/ReceiptJsonCodec.ts
  • test/unit/domain/properties/Join.property.test.ts
  • test/unit/domain/WarpFacade.test.ts
  • test/unit/domain/WarpGraph.seekDiff.test.ts
  • test/unit/domain/warp/RuntimeStateStore.test.ts
  • test/unit/benchmark/TrieGeometryProfile.profile.test.ts
  • test/unit/domain/types/TickReceipt.test.ts
  • test/unit/domain/types/EffectEmission.test.ts
  • test/unit/domain/types/DeliveryObservation.test.ts
  • test/unit/domain/properties/ORSet.property.test.ts
  • test/unit/infrastructure/codecs/ORSetCodec.test.ts
  • test/unit/domain/orset/session/StateSession.semilattice.property.test.ts
  • bin/cli/commands/doctor/types.ts
  • bin/cli/commands/doctor/stateCacheCapability.ts
  • test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts
  • src/infrastructure/codecs/ORSetCodec.ts
  • test/unit/cli/doctor.test.ts
  • test/unit/domain/orset/shadow/ShadowTrieORSet.test.ts
  • legacy.ts
  • bin/cli/commands/doctor/checksStateCache.ts
  • test/unit/cli/doctor-state-cache-retention.test.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • index.ts
  • bin/cli/commands/doctor/index.ts
  • scripts/lint-test-vacuous-returns.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • test/unit/domain/orset/shadow/ShadowTrieORSet.compaction.test.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • src/domain/services/state/CheckpointSerializer.ts
  • src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
  • test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts
  • src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx,js,jsx}: Do not introduce any, as any, as unknown as, unknown (outside adapters), Record<string, unknown> (outside adapters), *Like placeholder types, JSON.parse/JSON.stringify (outside adapters), fetch (outside adapters), process.env (outside adapters), @ts-ignore, or z.any() in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not create utils.ts, helpers.ts, misc.ts, or common.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; Buffer belongs in infrastructure adapters.

Files:

  • src/domain/services/state/WarpStateCacheRepairResult.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/ports/WarpStateCacheRetentionPort.ts
  • src/ports/RuntimeStorageCapabilityPort.ts
  • src/infrastructure/adapters/GitGraphAdapter.ts
  • src/infrastructure/codecs/ReceiptJsonCodec.ts
  • src/infrastructure/codecs/ORSetCodec.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • src/domain/services/state/CheckpointSerializer.ts
  • src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
  • src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts
src/domain/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.{ts,tsx,js,jsx}: In src/domain/**, do not use Date.now(), new Date(), Date(), performance.now(), Math.random(), crypto.randomUUID(), crypto.getRandomValues(), setTimeout, setInterval, raw new Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extend WarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/ must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.

Files:

  • src/domain/services/state/WarpStateCacheRepairResult.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/domain/services/state/CheckpointSerializer.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use explicit domain concepts with validated constructors, Object.freeze, and instanceof dispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.

Files:

  • src/domain/services/state/WarpStateCacheRepairResult.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/domain/services/state/CheckpointSerializer.ts
src/ports/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

In src/ports/**, do not import Node built-ins or src/infrastructure/**; ports must stay abstract and depend only on boundary-safe types.

Files:

  • src/ports/WarpStateCacheRetentionPort.ts
  • src/ports/RuntimeStorageCapabilityPort.ts
🧠 Learnings (2)
📚 Learning: 2026-03-04T12:08:30.347Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 63
File: package.json:126-126
Timestamp: 2026-03-04T12:08:30.347Z
Learning: Vitest 4 removes vite-node as a dependency and rewrites its pool system. Do not flag the absence of vite-node in package.json or lockfiles as an error for Vitest 4 projects. Use this as a general guideline: if a project uses Vitest 4, missing vite-node is expected and correct; only flag issues if there is evidence the project is not using Vitest 4 or if vite-node is explicitly required by the project.

Applied to files:

  • package.json
📚 Learning: 2026-03-08T19:50:17.519Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 65
File: CHANGELOG.md:88-88
Timestamp: 2026-03-08T19:50:17.519Z
Learning: Follow the Keep a Changelog convention for CHANGELOG.md. Allow duplicate subheadings across versions (e.g., '### Added', '### Fixed'). Configure markdownlint MD024 with {"siblings_only": true} to avoid cross-version false positives.

Applied to files:

  • CHANGELOG.md
🪛 ast-grep (0.44.1)
test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts

[warning] 3-3: Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFile } from 'node:child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

scripts/lint-test-vacuous-returns.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFileSync } from 'node:child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🪛 ESLint
test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts

[error] 44-44: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 45-45: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 77-77: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 80-80: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 84-84: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts

[error] 75-75: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts

[error] 32-32: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 44-44: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 58-58: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 287-287: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 294-294: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts

[error] 29-29: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 42-42: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 57-57: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 186-186: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 216-216: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts

[error] 72-72: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 87-87: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 134-134: Use spread syntax [...iterable] instead of Array.from(iterable) when no mapper function is provided

(e18e/prefer-spread-syntax)


[error] 286-286: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 321-321: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

🪛 GitHub Actions: Release Preflight (PR) / 0_preflight.txt
package.json

[error] 1-1: Command failed with exit code 1: 'npm run lint --if-present' (runs eslint . && node scripts/lint-test-vacuous-returns.ts && npm run lint:source-size && npm run lint:cas-invariants).

scripts/lint-test-vacuous-returns.ts

[error] 85-115: Lint step failed: spawnSync rg ENOENT. The command 'rg' (ripgrep) is not available in the CI environment. Error: 'spawnSync rg ENOENT' (syscall: 'spawnSync rg', path: 'rg').

🪛 GitHub Actions: Release Preflight (PR) / preflight
package.json

[error] Command failed: 'npm run lint --if-present' / 'eslint . "$@" && npm run lint:test-law && npm run lint:source-size && npm run lint:cas-invariants'. Underlying failure occurred in 'npm run lint:test-law' -> 'node scripts/lint-test-vacuous-returns.ts'.

scripts/lint-test-vacuous-returns.ts

[error] 85-115: lint step failed while running 'node scripts/lint-test-vacuous-returns.ts' (ESLint command wrapper). Error: spawnSync rg ENOENT (missing 'rg' executable). syscall: 'spawnSync rg', path: 'rg', spawnargs: ['--files','test','-g','.ts','-g','.js']. Node.js v22.23.1. Process exited with code 1.

🔇 Additional comments (58)
bin/cli/commands/doctor/codes.ts (1)

46-55: LGTM!

vitest.config.ts (1)

33-33: LGTM!

test/unit/domain/publicReadingSurface.behavior.test.ts (1)

64-64: LGTM!

bin/cli/commands/doctor/checksStateCache.ts (1)

1-141: LGTM!

test/unit/cli/doctor-state-cache-retention.test.ts (1)

1-93: LGTM!

CHANGELOG.md (1)

8-56: LGTM!

index.ts (1)

109-127: 🎯 Functional Correctness

No issue: the re-exports already exist in src/infrastructure/codecs/ReceiptJsonCodec.ts.

			> Likely an incorrect or invalid review comment.
test/unit/domain/services/query/BoundedQueryNodePageReader.test.ts (2)

17-44: LGTM!

Also applies to: 46-58


64-87: 🎯 Functional Correctness

Confirm MemoryBudgetError is the intended error for basic input validation.

The constructor throws MemoryBudgetError for a null readModel/pool (Lines 64-74), and readPage rejects with the same error for a malformed limit/cursor/null request (Lines 76-87). These look like plain argument-validation failures rather than a memory-budget violation; reusing the budget error type for both concerns makes it harder for callers to distinguish "invalid input" from "pool exhausted." Worth confirming this is intentional in BoundedQueryNodePageReader.ts (not included in this review) rather than a mislabeled error path.

docs/topics/cas-first-memoized-materialization.md (1)

7-11: LGTM!

Also applies to: 83-126, 135-137

legacy.ts (1)

75-84: LGTM!

Also applies to: 117-124

src/infrastructure/codecs/WarpStateCborCodec.ts (1)

1-146: LGTM!

src/infrastructure/adapters/CborCheckpointStoreAdapter.ts (1)

7-7: LGTM!

Also applies to: 45-45, 134-134

docs/topics/reference.md (1)

47-62: LGTM!

Also applies to: 73-84, 98-98, 107-109, 325-552

test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts (1)

5-5: LGTM!

Also applies to: 305-321, 323-333, 364-364, 380-382, 392-407

bin/cli/schemas.ts (1)

131-131: LGTM!

test/unit/cli/schemas.test.ts (1)

66-70: LGTM!

package.json (1)

79-88: LGTM!

Also applies to: 134-134

test/unit/domain/types/DeliveryObservation.test.ts (1)

4-5: LGTM!

bin/cli/commands/doctor/types.ts (1)

9-9: LGTM!

Also applies to: 68-68

bin/cli/commands/doctor/index.ts (1)

18-27: LGTM!

Also applies to: 36-36, 55-67, 106-109, 219-223

bin/cli/commands/doctor/stateCacheCapability.ts (1)

9-18: 🎯 Functional Correctness

No issue: createRuntimeStateCache already returns GitCasWarpStateCacheAdapter, which implements inspectRetention and repairRetention.

test/unit/infrastructure/adapters/NodeHttpAdapter.boundary.test.ts (1)

110-129: LGTM!

test/unit/domain/types/TickReceipt.test.ts (1)

4-7: LGTM!

test/unit/domain/types/EffectEmission.test.ts (1)

4-7: LGTM!

test/runtime/deno/deno.json (1)

4-4: LGTM!

test/unit/cli/doctor.test.ts (1)

5-6: LGTM!

Also applies to: 224-271

test/unit/domain/orset/shadow/ShadowTrieORSet.test.ts (1)

127-131: LGTM!

src/domain/services/state/WarpStateCacheRepairResult.ts (1)

12-56: 🗄️ Data Integrity & Integration

No overlap check needed
anchoredSnapshotIds comes from after.anchoredSnapshotIds, while unrecoverableSnapshotIds is built only from missingSnapshotIds and wrongTypeSnapshotIds, so the two sets are disjoint.

			> Likely an incorrect or invalid review comment.
test/unit/scripts/v18-v17-public-read-legacy-reading-builder.test.ts (1)

50-50: 🎯 Functional Correctness

The _content hash is intentionally runtime-generated
This fixture now pins the OID returned by RuntimeContentOidResolver/GitGraphAdapter.createRuntimeBlobStorage(), so the new value tracks deterministic blob output rather than legacy serialization.

			> Likely an incorrect or invalid review comment.
src/domain/services/state/WarpStateCacheRetentionReport.ts (1)

28-65: LGTM!

test/unit/domain/utils/toBytes.test.ts (1)

18-21: LGTM!

test/conformance/readonlyBytePropValueSnapshot.test.ts (1)

26-26: LGTM!

test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts (2)

7-32: LGTM!


65-86: LGTM!

test/unit/domain/WarpGraph.seekDiff.test.ts (1)

289-289: LGTM!

test/unit/domain/warp/RuntimeStateStore.test.ts (1)

107-107: LGTM!

test/unit/benchmark/TrieGeometryProfile.profile.test.ts (2)

12-30: LGTM!


32-59: LGTM!

src/ports/WarpStateCacheRetentionPort.ts (1)

1-11: LGTM!

src/ports/RuntimeStorageCapabilityPort.ts (1)

5-5: LGTM!

Also applies to: 16-16

src/infrastructure/adapters/GitGraphAdapter.ts (1)

25-25: LGTM!

Also applies to: 166-166

test/unit/domain/WarpGraph.audit.test.ts (1)

151-153: LGTM!

Also applies to: 174-174

docs/topics/cli.md (1)

42-46: LGTM!

test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts (1)

1-142: LGTM!

test/unit/scripts/lint-test-vacuous-returns.test.ts (1)

1-40: LGTM!

scripts/lint-test-vacuous-returns.ts (1)

1-83: LGTM!

Also applies to: 92-98, 100-116

test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts (1)

8-31: LGTM!

Also applies to: 33-43, 45-57, 59-127, 184-285, 291-292, 391-424, 629-649

test/unit/domain/orset/shadow/ShadowTrieORSet.compaction.test.ts (1)

262-262: LGTM!

Also applies to: 273-273, 305-305, 316-316, 349-349, 360-360, 390-390, 401-401, 430-430, 441-441, 455-455, 477-477

test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts (1)

1-28: LGTM!

Also applies to: 30-41, 43-56, 58-185, 187-215, 217-311

src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts (1)

1-158: LGTM!

Also applies to: 164-304

test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts (1)

1-71: LGTM!

Also applies to: 73-86, 88-133, 135-285, 287-320, 322-402

src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts (1)

17-214: LGTM!

Also applies to: 228-269, 276-419

test/unit/domain/properties/Join.property.test.ts (1)

19-19: LGTM!

Also applies to: 152-162

test/unit/domain/WarpFacade.test.ts (1)

301-303: LGTM!

test/unit/domain/properties/ORSet.property.test.ts (1)

5-5: LGTM!

Also applies to: 68-68, 157-158, 172-173

test/unit/infrastructure/codecs/ORSetCodec.test.ts (1)

1-133: LGTM!

test/unit/domain/orset/session/StateSession.semilattice.property.test.ts (1)

12-12: LGTM!

Also applies to: 134-138, 262-262

Comment thread bin/cli/commands/doctor/stateCacheCapability.ts Outdated
Comment thread bin/cli/commands/doctor/stateCacheCapability.ts
Comment thread scripts/lint-test-vacuous-returns.ts Outdated
Comment thread src/domain/services/state/CheckpointSerializer.ts Outdated
Comment thread src/domain/services/state/WarpStateCacheRetentionReport.ts
Comment thread test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts Outdated
Comment thread test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts Outdated
Comment thread test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts Outdated
Comment thread test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts Outdated
@github-actions

Copy link
Copy Markdown

Release Preflight

  • package version: 18.2.1
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v18.2.1. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@github-actions

Copy link
Copy Markdown

Release Preflight

  • package version: 18.2.1
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v18.2.1. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

# Conflicts:
#	docs/topics/reference.md
#	index.ts
#	src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
#	test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts (1)

202-215: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Silently swallowing all cleanup errors removes observability into persistent failures.

The catch was widened from selectively rethrowing on ROOT_SET_CONFLICT to swallowing any replace() failure. This is safe for the intended race case (doctor/repair can reconcile the superset later), but a persistent bug (auth/network/malformed-input error) during cleanup would now fail silently forever, with no signal until someone manually runs doctor/--repair-state-cache.

Consider logging the swallowed error (non-fatally) so operators have a trail without changing the safe-retention behavior.

♻️ Proposed fix
-  private async _cleanupPreparedSuperset(
+  private async _cleanupPreparedSuperset(
     rootSet: RootSetClient,
     prepared: RootSetMutationResult,
     desired: readonly RootSetEntry[],
   ): Promise<void> {
     if (entryListsEqual(prepared.entries, desired)) { return; }
     // The index is already committed. Any cleanup failure safely retains a
     // superset that doctor/repair can reconcile without risking live payloads.
     try {
       await rootSet.replace({ entries: desired, expectedHeadOid: prepared.commitOid });
-    } catch {
-      // The prepared superset remains authoritative and safe.
+    } catch (err) {
+      // The prepared superset remains authoritative and safe.
+      this._logger?.warn('GitCasStateCacheRootSetCoordinator: root-set cleanup failed, retaining superset', { err });
     }
   }
🤖 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/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts` around
lines 202 - 215, Update _cleanupPreparedSuperset to log the error caught from
rootSet.replace when cleanup fails, using the existing coordinator logging
mechanism and enough context to identify the cleanup failure. Preserve the
non-fatal behavior and safe retention of the prepared superset; do not rethrow
the error.
🤖 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 `@test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts`:
- Around line 264-299: Hoist the inline assertion regexes used in the “fails
closed on unreadable or invalid persisted indexes” and “does not publish after a
persisted index read fails” tests to module-scope constants, including reusable
constants for malformed index, unsupported schema, object validation, snapshots
validation, and BLOB_READ_FAILED_ERROR. Replace the inline regex literals in
each expect(...).rejects.toThrow assertion with those constants.

---

Outside diff comments:
In `@src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts`:
- Around line 202-215: Update _cleanupPreparedSuperset to log the error caught
from rootSet.replace when cleanup fails, using the existing coordinator logging
mechanism and enough context to identify the cleanup failure. Preserve the
non-fatal behavior and safe retention of the prepared superset; do not rethrow
the error.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5f57d569-d34e-4fee-9d41-ed3fb6b4cbd6

📥 Commits

Reviewing files that changed from the base of the PR and between 9a34c7c and 2b4ba87.

📒 Files selected for processing (16)
  • bin/cli/commands/doctor/checksStateCache.ts
  • bin/cli/commands/doctor/stateCacheCapability.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
  • src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts
  • src/infrastructure/codecs/ORSetCodec.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts
  • test/unit/cli/doctor-state-cache-retention.test.ts
  • test/unit/cli/doctor.test.ts
  • test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts
  • test/unit/infrastructure/codecs/ORSetCodec.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: test-node (22)
  • GitHub Check: coverage-threshold
  • GitHub Check: preflight
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Do not use direct imports from src/infrastructure/** in src/domain/** or src/ports/**; depend on a port instead.
Do not use direct Node built-ins in src/domain/** or src/ports/**; use a port instead.

Files:

  • test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts
  • test/unit/infrastructure/codecs/ORSetCodec.test.ts
  • test/unit/cli/doctor.test.ts
  • bin/cli/commands/doctor/stateCacheCapability.ts
  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • test/unit/cli/doctor-state-cache-retention.test.ts
  • src/infrastructure/codecs/ORSetCodec.ts
  • bin/cli/commands/doctor/checksStateCache.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts
  • src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts
  • test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts
  • src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx,js,jsx}: Do not introduce any, as any, as unknown as, unknown (outside adapters), Record<string, unknown> (outside adapters), *Like placeholder types, JSON.parse/JSON.stringify (outside adapters), fetch (outside adapters), process.env (outside adapters), @ts-ignore, or z.any() in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not create utils.ts, helpers.ts, misc.ts, or common.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; Buffer belongs in infrastructure adapters.

Files:

  • src/domain/services/state/WarpStateCacheRetentionReport.ts
  • src/infrastructure/codecs/ORSetCodec.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts
  • src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts
src/domain/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.{ts,tsx,js,jsx}: In src/domain/**, do not use Date.now(), new Date(), Date(), performance.now(), Math.random(), crypto.randomUUID(), crypto.getRandomValues(), setTimeout, setInterval, raw new Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extend WarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/ must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.

Files:

  • src/domain/services/state/WarpStateCacheRetentionReport.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use explicit domain concepts with validated constructors, Object.freeze, and instanceof dispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.

Files:

  • src/domain/services/state/WarpStateCacheRetentionReport.ts
🪛 ESLint
test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts

[error] 267-267: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 270-270: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 273-273: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 276-276: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 287-287: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)


[error] 295-295: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts

[error] 202-202: Move this regular expression to module scope to avoid re-compilation on every call.

(e18e/prefer-static-regex)

🔇 Additional comments (21)
test/unit/domain/services/state/WarpStateCacheRetentionResults.test.ts (1)

7-90: LGTM!

Past regex-hoisting comment is resolved — EMPTY_NAME_ERROR, EMPTY_ROOT_SET_ERROR, INVALID_AFTER_REPORT, INVALID_BEFORE_REPORT are now module-scope constants and used consistently at the throw-assertion call sites.

test/unit/cli/doctor.test.ts (1)

224-299: LGTM!

Both new tests (successful repair with STATE_CACHE_RETENTION_REPAIRED, and repair failure surfaced as a fail finding with CHECK_INTERNAL_ERROR) correctly exercise the try/catch added in repairStateCache.

bin/cli/commands/doctor/stateCacheCapability.ts (1)

3-31: LGTM!

Both prior review findings are addressed: the codec is now imported statically (line 3) and repairStateCache wraps repairRetention() in try/catch, converting failures into stateCacheRepairFailureFinding instead of letting them crash handleDoctor (lines 26-30).

src/domain/services/state/WarpStateCacheRetentionReport.ts (1)

1-67: LGTM!

The duplicated error code is now a single INVALID_RETENTION_REPORT constant used consistently, resolving the prior review comment. Constructor validation, freezing, and isHealthy() aggregation look correct.

test/unit/cli/doctor-state-cache-retention.test.ts (1)

95-104: LGTM!

Test correctly asserts stateCacheRepairFailureFinding maps an Error to the expected fail/CHECK_INTERNAL_ERROR finding shape.

bin/cli/commands/doctor/checksStateCache.ts (1)

142-151: LGTM!

stateCacheRepairFailureFinding correctly derives the message from Error vs. non-Error values and matches the DoctorFinding contract used by both callers and tests.

src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts (5)

263-272: LGTM!

Prior critical finding resolved: a failed head read/parse now propagates instead of silently degrading to an empty index (which previously risked publishing a CAS'd empty index and losing every live RootSet edge).


326-339: LGTM!

Prior major finding resolved: cleanup failures inside publishTransition/_cleanupPreparedSuperset are swallowed internally (retaining the safe superset) rather than propagating into _mutateIndex's retry loop, so a successfully committed index write is no longer retried/misreported as failed.


65-140: LGTM!

The new schema/checkpoint/snapshots validators (cacheIndexCandidate, validateIndexSchema, validateCheckpointHeadId, validateSnapshots, _parseIndexBlob) correctly fail closed on malformed persisted index data and wrap non-CacheError failures, matching the new adapter test expectations.


446-456: LGTM!

inspectRetention/repairRetention correctly delegate to the coordinator and only mark _retentionReady on the synchronous line after a successful await, so a thrown repair error won't incorrectly mark retention as ready.


173-183: 🩺 Stability & Availability

No change needed for these lookups. _buildPrunedSnapshotIndex and _filterSnapshotsByIndex iterate the same snapshots object they read from, so snapshots[key]! cannot be absent in this path.

			> Likely an incorrect or invalid review comment.
test/unit/infrastructure/codecs/ORSetCodec.test.ts (1)

1-142: LGTM!

src/infrastructure/codecs/ORSetCodec.ts (1)

48-82: LGTM! The malformed-dot validation gap flagged in the previous review is now closed via validatedDots/Dot.decode, matching the new codec-boundary test.

src/infrastructure/codecs/WarpStateCborCodec.ts (1)

12-12: LGTM! This correctly implements the previously-requested defensive fallbacks (LEGACY_PATCH_SHA_PLACEHOLDER constant, numberOrZero/stringOr normalization for eventId), verified against the new decoder test in CborCheckpointStoreAdapter.test.ts.

Also applies to: 147-158, 177-212

test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.test.ts (1)

14-15: LGTM! Spread-syntax fixes address the prior ESLint findings, and the new "does not retry an index mutation after post-commit cleanup fails" test correctly exercises the guarded-cleanup swallow path.

Also applies to: 25-38, 58-65, 188-188, 218-218, 297-318

src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts (1)

152-166: LGTM! Lazy _getRootSet now clears the cached promise on rejection, fixing the previously flagged retry gap.

test/unit/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.test.ts (3)

73-73: LGTM! Spread-syntax fixes resolve the prior ESLint findings.

Also applies to: 88-88, 135-135


191-208: 📐 Maintainability & Code Quality | ⚡ Quick win

Hoist the inline regex to module scope.

Static analysis flags the /root set unavailable/ literal at line 202 as re-compiled on every call. INDEX_CAS_FAILURE is already correctly hoisted elsewhere in this file — apply the same pattern here.

🔧 Proposed fix
+const ROOT_SET_UNAVAILABLE = /root set unavailable/;
+
 it('retries opening the root set after a transient failure', async () => {
     const rootSet = new MockRootSet([]);
     const openRootSet = vi.fn()
       .mockRejectedValueOnce(new Error('root set unavailable'))
       .mockResolvedValue(rootSet);
     const coordinator = new GitCasStateCacheRootSetCoordinator({
       graphName: 'demo',
       openRootSet,
       objectProbe: new MockObjectProbe(),
     });

-    await expect(coordinator.inspect([])).rejects.toThrow(/root set unavailable/);
+    await expect(coordinator.inspect([])).rejects.toThrow(ROOT_SET_UNAVAILABLE);

Source: Linters/SAST tools


306-306: LGTM!

Also applies to: 331-352

test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts (1)

5-5: LGTM! Test assertions align with the eventIdFromUnknown/numberOrZero/stringOr normalization behavior in WarpStateCborCodec.ts.

Also applies to: 305-334, 337-383, 392-392, 405-448

test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts (1)

27-27: LGTM! Regex hoisting fix resolves the prior ESLint finding.

Also applies to: 68-79

@github-actions

Copy link
Copy Markdown

Release Preflight

  • package version: 18.2.1
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v18.2.1. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

1 similar comment
@github-actions

Copy link
Copy Markdown

Release Preflight

  • package version: 18.2.1
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v18.2.1. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/infrastructure/adapters/CborCheckpointStoreAdapter.ts (1)

160-168: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use the shared schema constant and drop the fake stateHash schema: 5 should reuse CURRENT_CHECKPOINT_SCHEMA, and CheckpointData.stateHash shouldn’t be a required string if this adapter can only return ''; make it optional/null or keep the real hash on the commit-message path.

🤖 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/infrastructure/adapters/CborCheckpointStoreAdapter.ts` around lines 160 -
168, Update the return object in CborCheckpointStoreAdapter to use the shared
CURRENT_CHECKPOINT_SCHEMA constant instead of the literal schema value. Remove
the fake empty stateHash by making CheckpointData.stateHash optional or
nullable, and preserve the actual hash where the commit-message path provides
one.
🤖 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 `@src/domain/services/state/checkpointCreate.ts`:
- Around line 166-180: Update the checkpoint creation fallback around the
stateEnvelope, frontier, and appliedVV blob writes to start all independent
persistence.writeBlob operations together and await them with Promise.all,
preserving the corresponding OID assignments. Include the optional
provenanceIndex serialization/write in the parallel batch when present, while
retaining its conditional behavior.
- Around line 139-144: Update the computeStateHash call in createCheckpoint to
stop force-casting crypto to CryptoPort. Follow the existing conditional-spread
pattern used for codecOpt and provenanceIndex so the crypto property is included
only when defined, while preserving the current codec handling and
runtime-accurate optional typing.

In `@src/infrastructure/adapters/CborCheckpointStoreAdapter.ts`:
- Around line 12-15: Remove the local BlobPort interface declaration and import
the shared BlobPort type from the existing port module. Update
CborCheckpointStoreAdapter to use that imported type while preserving its
current behavior.
- Around line 173-181: Update _encodeStateEnvelope in CborCheckpointStoreAdapter
to reuse the shared checkpoint envelope serializer from CheckpointSerializer for
nodeAlive, edgeAlive, prop, and observedFrontier instead of duplicating their
encoding logic. Retain only the adapter-specific edgeBirthEvent encoding and
validation layered on top, preserving the shared wire format.

---

Outside diff comments:
In `@src/infrastructure/adapters/CborCheckpointStoreAdapter.ts`:
- Around line 160-168: Update the return object in CborCheckpointStoreAdapter to
use the shared CURRENT_CHECKPOINT_SCHEMA constant instead of the literal schema
value. Remove the fake empty stateHash by making CheckpointData.stateHash
optional or nullable, and preserve the actual hash where the commit-message path
provides one.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 61ab0a8f-ed77-4282-b1e0-11ebfba3b3d3

📥 Commits

Reviewing files that changed from the base of the PR and between 2b4ba87 and 7aefb13.

📒 Files selected for processing (13)
  • CHANGELOG.md
  • docs/topics/reference.md
  • index.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/checkpointLoad.ts
  • src/domain/warp/RuntimeHostBoot.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • src/ports/CheckpointStorePort.ts
  • test/unit/domain/WarpFacade.test.ts
  • test/unit/domain/publicStrandAndRuntimeSeams.test.ts
  • test/unit/domain/services/CheckpointService.edgeCases.test.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • test/unit/ports/CheckpointStorePort.test.ts
💤 Files with no reviewable changes (2)
  • src/domain/warp/RuntimeHostBoot.ts
  • index.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: test-node (22)
  • GitHub Check: coverage-threshold
  • GitHub Check: preflight
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Do not use direct imports from src/infrastructure/** in src/domain/** or src/ports/**; depend on a port instead.
Do not use direct Node built-ins in src/domain/** or src/ports/**; use a port instead.

Files:

  • test/unit/ports/CheckpointStorePort.test.ts
  • test/unit/domain/publicStrandAndRuntimeSeams.test.ts
  • src/ports/CheckpointStorePort.ts
  • test/unit/domain/services/CheckpointService.edgeCases.test.ts
  • test/unit/domain/WarpFacade.test.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/checkpointLoad.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx,js,jsx}: Do not introduce any, as any, as unknown as, unknown (outside adapters), Record<string, unknown> (outside adapters), *Like placeholder types, JSON.parse/JSON.stringify (outside adapters), fetch (outside adapters), process.env (outside adapters), @ts-ignore, or z.any() in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not create utils.ts, helpers.ts, misc.ts, or common.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; Buffer belongs in infrastructure adapters.

Files:

  • src/ports/CheckpointStorePort.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/checkpointLoad.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
src/ports/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

In src/ports/**, do not import Node built-ins or src/infrastructure/**; ports must stay abstract and depend only on boundary-safe types.

Files:

  • src/ports/CheckpointStorePort.ts
src/domain/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.{ts,tsx,js,jsx}: In src/domain/**, do not use Date.now(), new Date(), Date(), performance.now(), Math.random(), crypto.randomUUID(), crypto.getRandomValues(), setTimeout, setInterval, raw new Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extend WarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/ must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.

Files:

  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/checkpointLoad.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use explicit domain concepts with validated constructors, Object.freeze, and instanceof dispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.

Files:

  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/checkpointLoad.ts
🧠 Learnings (1)
📚 Learning: 2026-03-08T19:50:17.519Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 65
File: CHANGELOG.md:88-88
Timestamp: 2026-03-08T19:50:17.519Z
Learning: Follow the Keep a Changelog convention for CHANGELOG.md. Allow duplicate subheadings across versions (e.g., '### Added', '### Fixed'). Configure markdownlint MD024 with {"siblings_only": true} to avoid cross-version false positives.

Applied to files:

  • CHANGELOG.md
🔇 Additional comments (11)
test/unit/ports/CheckpointStorePort.test.ts (1)

16-25: LGTM!

Also applies to: 34-34

test/unit/domain/publicStrandAndRuntimeSeams.test.ts (1)

249-257: LGTM!

test/unit/domain/WarpFacade.test.ts (1)

63-103: LGTM!

Also applies to: 236-240, 351-351

CHANGELOG.md (1)

22-24: LGTM!

Also applies to: 35-63

src/ports/CheckpointStorePort.ts (1)

25-29: 🗄️ Data Integrity & Integration

No versioning concern here The port isn’t part of the public package export surface, and the internal adapter/call sites already use the new fields.

			> Likely an incorrect or invalid review comment.
test/unit/domain/services/CheckpointService.edgeCases.test.ts (1)

845-852: LGTM!

Also applies to: 875-876

src/domain/services/state/checkpointCreate.ts (1)

17-17: LGTM!

Also applies to: 92-135, 146-161, 183-253

src/domain/services/state/checkpointLoad.ts (1)

90-92: LGTM!

Also applies to: 106-123

docs/topics/reference.md (1)

33-57: LGTM!

Also applies to: 69-73, 79-84, 253-480

test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts (1)

1-4: LGTM!

Also applies to: 44-53, 81-106, 108-129, 131-156, 175-175, 184-189, 198-201, 218-218, 229-251, 284-305, 307-329, 331-345

src/infrastructure/adapters/CborCheckpointStoreAdapter.ts (1)

65-82: LGTM!

Also applies to: 84-108, 110-159, 224-304, 344-388

Comment thread src/domain/services/state/checkpointCreate.ts
Comment thread src/domain/services/state/checkpointCreate.ts Outdated
Comment thread src/infrastructure/adapters/CborCheckpointStoreAdapter.ts Outdated
Comment thread src/infrastructure/adapters/CborCheckpointStoreAdapter.ts Outdated
@github-actions

Copy link
Copy Markdown

Release Preflight

  • package version: 18.2.1
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v18.2.1. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@flyingrobots

Copy link
Copy Markdown
Member Author

Self-review

Reviewed the complete PR diff at a5b6d617982bcaf5e87c01776db80e97e208ab25 against issue #731, the RootSet publication protocol, failure ordering, checkpoint wire compatibility, and the repository anti-sludge rules.

The review found and fixed four classes of defects before this revision: duplicate OR-Set/checkpoint encoders, fabricated checkpoint metadata, an optional-crypto force cast plus sequential fallback writes, and bundled receipt codecs. The OR-Set wire shape now has one domain-owned implementation with decode-time dot validation, while the checkpoint adapter delegates the complete current envelope to the canonical serializer. [cite: src/domain/services/state/ORSetWireBoundary.ts#L6-L27@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/domain/services/state/ORSetWireBoundary.ts#L50-L84@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/CborCheckpointStoreAdapter.ts#L149-L180@a5b6d617982bcaf5e87c01776db80e97e208ab25]

The state-cache critical section preserves the required order: prepare the RootSet superset, publish the index, then attempt guarded cleanup. Cleanup failures are absorbed only after index publication and retain a safe superset, so they cannot trigger a duplicate mutation retry. [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L186-L215@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts#L305-L339@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Persisted-index reads fail closed: only a missing ref yields an empty index; blob and parse failures propagate before any write or compare-and-swap. [cite: src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts#L263-L271@a5b6d617982bcaf5e87c01776db80e97e208ab25]

The real-Git witness proves a legacy payload starts prunable, becomes non-prunable after lazy RootSet adoption, and becomes prunable again after the live index drops it. [cite: test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts#L118-L141@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Validation on the current code: IRONCLAD pre-push passed all static gates and six unit shards; stable local matrix passed 7,408 tests with 2 skipped; coverage passed 7,447 tests with 2 skipped at 92.61% lines; the focused review suite passed 129 tests; git diff --check passed.

Result: no unresolved self-review findings.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer review

Claim boundary: This PR fixes state-cache payload reachability and repair for #731. It does not claim that git-warp has already reached the broader zero-manual-CAS/cache architecture tracked by emergency goalpost #734; that migration remains separate work.

Reachability invariant: every live snapshot payload admitted to the state-cache index is represented by a graph-scoped git-cas RootSet entry with the payload OID, object type, and retention policy. Legacy index entries are adopted before use. [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L63-L76@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts#L278-L298@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Publication invariant: roots are prepared before the index compare-and-swap. Once the index is committed, cleanup is best-effort and may only leave additional reachable objects; it may not remove a live root or cause the committed mutation to be replayed. [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L186-L215@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts#L326-L339@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Corruption invariant: a present index ref with unreadable or invalid content is an error, never an empty cache. This prevents corruption from being laundered into a destructive replacement index. [cite: src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts#L89-L139@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/GitCasWarpStateCacheAdapter.ts#L263-L271@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Repair invariant: doctor can inspect and repair retention without crashing the command path; repair failures become explicit findings, while missing or wrong-type payloads remain identified as unrecoverable rather than invented. [cite: bin/cli/commands/doctor/stateCacheCapability.ts#L13-L30@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L217-L264@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Wire-contract invariant: current checkpoint envelope encoding and decoding have one implementation, strict current edge-birth validation, and no fabricated stateHash or schema values from a tree-only read. Commit-message metadata remains owned by the checkpoint loader. [cite: src/domain/services/state/CheckpointSerializer.ts#L134-L170@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/domain/services/state/CheckpointSerializer.ts#L261-L311@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: src/infrastructure/adapters/CborCheckpointStoreAdapter.ts#L123-L155@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Proof posture: the integration test invokes real Git pruning diagnostics, not a mocked reachability predicate, and exercises both adoption and release. [cite: test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts#L68-L78@a5b6d617982bcaf5e87c01776db80e97e208ab25] [cite: test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts#L118-L141@a5b6d617982bcaf5e87c01776db80e97e208ab25]

Verdict: contract-consistent for #731; no blocking legal, semantic, or retention ambiguity found.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 13, 2026
@flyingrobots

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@flyingrobots

Copy link
Copy Markdown
Member Author

Self-review addendum for current head

Reviewed follow-up commit d86193eed7d15963cc817552eebbaaaff2cccb8a after GitHub CI exposed a scanner-only defect. The three fallback diagnostic labels used a token reserved by the 0025B boundary rule; the fix replaces them with one named unidentified-key constant without changing accepted data, rejection conditions, error type, or error code. [cite: src/domain/services/state/CheckpointSerializer.ts#L261-L295@d86193eed7d15963cc817552eebbaaaff2cccb8a] [cite: src/domain/services/state/CheckpointSerializer.ts#L310-L314@d86193eed7d15963cc817552eebbaaaff2cccb8a]

Current-head verification: Semgrep anti-sludge passes with zero unquarantined violations; contamination remains exactly 3 pre-existing file entries with no manifest diff; lint and typecheck pass; focused tests pass 19/19; clean-worktree JSR dry-run succeeds; IRONCLAD pre-push passes all static gates and 7,408 tests with 2 skipped.

Result: no unresolved current-head self-review findings.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer addendum for current head

Diagnostic-contract invariant: malformed current edge-birth payloads still fail with WarpError code E_INVALID_CHECKPOINT_EDGE_BIRTH_EVENT; only the non-identity placeholder rendered in the message changed from a policy-reserved token to <unidentified>. Valid keys and constructor-validation failures retain their concrete key. [cite: src/domain/services/state/CheckpointSerializer.ts#L269-L295@d86193eed7d15963cc817552eebbaaaff2cccb8a] [cite: src/domain/services/state/CheckpointSerializer.ts#L310-L314@d86193eed7d15963cc817552eebbaaaff2cccb8a]

Policy invariant: the follow-up does not expand a quarantine or suppress a scanner finding. The source is now compliant as written, and the checked-in contamination manifests remain unchanged.

Verdict: the prior Code Lawyer verdict remains valid on d86193ee; no semantic or policy exception was introduced.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/domain/services/state/CheckpointSerializer.ts (1)

68-86: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Extract the shared prop/edge-birth/LWW-register wire helpers

serializePropsArray, serializeEdgeBirthArray, and serializeLWWRegister are duplicated in CheckpointSerializer.ts and WarpStateCborCodec.ts. Move that wire-format logic into a shared domain boundary module and import it from both paths so the checkpoint and CBOR encoders stay aligned.

🤖 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/domain/services/state/CheckpointSerializer.ts` around lines 68 - 86,
Extract serializePropsArray, serializeEdgeBirthArray, and serializeLWWRegister
into a shared domain-boundary module, then import and use those helpers from
both serializers. Update src/domain/services/state/CheckpointSerializer.ts:68-86
and :322-322 to remove the local implementations/usages, and update
src/infrastructure/codecs/WarpStateCborCodec.ts:83-93, :94-113, and :164-180 to
remove duplicated wire-format logic and use the shared helpers, keeping both
encoders aligned.
🤖 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/domain/services/state/CheckpointSerializer.ts`:
- Around line 68-86: Extract serializePropsArray, serializeEdgeBirthArray, and
serializeLWWRegister into a shared domain-boundary module, then import and use
those helpers from both serializers. Update
src/domain/services/state/CheckpointSerializer.ts:68-86 and :322-322 to remove
the local implementations/usages, and update
src/infrastructure/codecs/WarpStateCborCodec.ts:83-93, :94-113, and :164-180 to
remove duplicated wire-format logic and use the shared helpers, keeping both
encoders aligned.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e844b229-4929-4cf6-bbea-816428200c17

📥 Commits

Reviewing files that changed from the base of the PR and between 7aefb13 and a5b6d61.

📒 Files selected for processing (25)
  • docs/topics/reference.md
  • legacy.ts
  • scripts/lint-markdown-code-samples.ts
  • src/domain/services/state/CheckpointSerializer.ts
  • src/domain/services/state/ORSetWireBoundary.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • src/infrastructure/codecs/DeliveryObservationJsonCodec.ts
  • src/infrastructure/codecs/EffectEmissionJsonCodec.ts
  • src/infrastructure/codecs/TickReceiptJsonCodec.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • src/ports/CheckpointStorePort.ts
  • test/unit/domain/orset/session/StateSession.semilattice.property.test.ts
  • test/unit/domain/properties/Join.property.test.ts
  • test/unit/domain/properties/ORSet.property.test.ts
  • test/unit/domain/services/state/CheckpointSerializerBoundary.test.ts
  • test/unit/domain/services/state/ORSetWireBoundary.test.ts
  • test/unit/domain/types/DeliveryObservation.test.ts
  • test/unit/domain/types/EffectEmission.test.ts
  • test/unit/domain/types/TickReceipt.test.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts
  • test/unit/ports/CheckpointStorePort.test.ts
  • test/unit/scripts/lint-markdown-code-samples.test.ts
  • vitest.config.ts
💤 Files with no reviewable changes (1)
  • src/ports/CheckpointStorePort.ts
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: Release Preflight (PR) / 0_preflight.txt: Fix: anchor state-cache payloads against Git GC

Conclusion: failure

View job details

##[group]Run npx -y jsr publish --dry-run
 �[36;1mnpx -y jsr publish --dry-run�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 Downloading JSR release binary...
 Download completed
 Checking for slow types in the public API...
 Uncommitted changes:
 M policy/quarantines/0025B-boundary.json
 �[0m�[1m�[31merror�[0m: Aborting due to uncommitted changes. Check in source code or run with --allow-dirty
 Command: /home/runner/.npm/_npx/91d31d47806d2506/node_modules/jsr/.download/v2.6.7/linux/deno publish --unstable-bare-node-builtins --unstable-sloppy-imports --unstable-byonm --no-check --dry-run
 CWD: /home/runner/work/git-warp/git-warp
 Output:
 Child process exited with: 1
 ##[error]Process completed with exit code 1.

GitHub Actions: Release Preflight (PR) / preflight: Fix: anchor state-cache payloads against Git GC

Conclusion: failure

View job details

##[group]Run npx -y jsr publish --dry-run
 �[36;1mnpx -y jsr publish --dry-run�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 Downloading JSR release binary...
 Download completed
 Checking for slow types in the public API...
 Uncommitted changes:
 M policy/quarantines/0025B-boundary.json
 �[0m�[1m�[31merror�[0m: Aborting due to uncommitted changes. Check in source code or run with --allow-dirty
 Command: /home/runner/.npm/_npx/91d31d47806d2506/node_modules/jsr/.download/v2.6.7/linux/deno publish --unstable-bare-node-builtins --unstable-sloppy-imports --unstable-byonm --no-check --dry-run
 CWD: /home/runner/work/git-warp/git-warp
 Output:
 Child process exited with: 1
 ##[error]Process completed with exit code 1.
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Do not use direct imports from src/infrastructure/** in src/domain/** or src/ports/**; depend on a port instead.
Do not use direct Node built-ins in src/domain/** or src/ports/**; use a port instead.

Files:

  • vitest.config.ts
  • src/infrastructure/codecs/EffectEmissionJsonCodec.ts
  • test/unit/domain/types/TickReceipt.test.ts
  • src/infrastructure/codecs/DeliveryObservationJsonCodec.ts
  • src/infrastructure/codecs/TickReceiptJsonCodec.ts
  • scripts/lint-markdown-code-samples.ts
  • test/unit/scripts/lint-markdown-code-samples.test.ts
  • test/unit/domain/types/EffectEmission.test.ts
  • src/domain/services/state/ORSetWireBoundary.ts
  • test/unit/domain/types/DeliveryObservation.test.ts
  • test/unit/domain/properties/Join.property.test.ts
  • test/unit/domain/services/state/CheckpointSerializerBoundary.test.ts
  • test/unit/domain/services/state/ORSetWireBoundary.test.ts
  • test/unit/domain/properties/ORSet.property.test.ts
  • test/unit/domain/orset/session/StateSession.semilattice.property.test.ts
  • test/unit/ports/CheckpointStorePort.test.ts
  • src/domain/services/state/checkpointCreate.ts
  • test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts
  • legacy.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts
  • src/domain/services/state/CheckpointSerializer.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx,js,jsx}: Do not introduce any, as any, as unknown as, unknown (outside adapters), Record<string, unknown> (outside adapters), *Like placeholder types, JSON.parse/JSON.stringify (outside adapters), fetch (outside adapters), process.env (outside adapters), @ts-ignore, or z.any() in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not create utils.ts, helpers.ts, misc.ts, or common.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; Buffer belongs in infrastructure adapters.

Files:

  • src/infrastructure/codecs/EffectEmissionJsonCodec.ts
  • src/infrastructure/codecs/DeliveryObservationJsonCodec.ts
  • src/infrastructure/codecs/TickReceiptJsonCodec.ts
  • src/domain/services/state/ORSetWireBoundary.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/infrastructure/adapters/CborCheckpointStoreAdapter.ts
  • src/infrastructure/codecs/WarpStateCborCodec.ts
  • src/domain/services/state/CheckpointSerializer.ts
src/domain/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.{ts,tsx,js,jsx}: In src/domain/**, do not use Date.now(), new Date(), Date(), performance.now(), Math.random(), crypto.randomUUID(), crypto.getRandomValues(), setTimeout, setInterval, raw new Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extend WarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/ must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.

Files:

  • src/domain/services/state/ORSetWireBoundary.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/CheckpointSerializer.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use explicit domain concepts with validated constructors, Object.freeze, and instanceof dispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.

Files:

  • src/domain/services/state/ORSetWireBoundary.ts
  • src/domain/services/state/checkpointCreate.ts
  • src/domain/services/state/CheckpointSerializer.ts
🔇 Additional comments (26)
vitest.config.ts (1)

33-33: LGTM!

src/infrastructure/codecs/EffectEmissionJsonCodec.ts (1)

4-5: LGTM!

test/unit/domain/types/TickReceipt.test.ts (1)

7-7: LGTM!

src/infrastructure/codecs/DeliveryObservationJsonCodec.ts (1)

4-5: LGTM!

src/infrastructure/codecs/TickReceiptJsonCodec.ts (1)

4-5: LGTM!

test/unit/domain/types/EffectEmission.test.ts (1)

7-7: LGTM!

test/unit/domain/types/DeliveryObservation.test.ts (1)

5-5: LGTM!

legacy.ts (1)

80-82: LGTM!

Also applies to: 120-122

scripts/lint-markdown-code-samples.ts (1)

12-12: LGTM!

src/domain/services/state/ORSetWireBoundary.ts (1)

1-63: LGTM!

test/unit/domain/services/state/CheckpointSerializerBoundary.test.ts (1)

1-45: LGTM!

test/unit/domain/orset/session/StateSession.semilattice.property.test.ts (1)

12-12: LGTM!

test/unit/ports/CheckpointStorePort.test.ts (1)

6-46: LGTM!

src/domain/services/state/checkpointCreate.ts (1)

97-276: LGTM!

src/infrastructure/codecs/WarpStateCborCodec.ts (1)

9-13: LGTM!

src/domain/services/state/CheckpointSerializer.ts (1)

156-171: LGTM!

Also applies to: 261-313

test/unit/scripts/lint-markdown-code-samples.test.ts (1)

185-192: LGTM!

test/unit/domain/properties/Join.property.test.ts (1)

19-19: LGTM!

Also applies to: 154-159

test/unit/domain/services/state/ORSetWireBoundary.test.ts (1)

1-152: LGTM!

test/unit/domain/properties/ORSet.property.test.ts (1)

5-5: LGTM!

Also applies to: 68-68, 157-158, 172-173

test/unit/infrastructure/adapters/GitCasWarpStateCacheAdapter.test.ts (1)

6-10: LGTM! Hoisted regex constants resolve the prior lint feedback, and the new fail-closed assertions for _readIndex/_mutateIndex line up with the PR's crash-safety goals.

Also applies to: 272-301

src/infrastructure/adapters/CborCheckpointStoreAdapter.ts (2)

2-12: LGTM! Both prior review findings (local BlobPort redeclaration, duplicated envelope encode/decode) are fully resolved — the adapter now imports the canonical port and delegates entirely to CheckpointSerializer.

Also applies to: 160-162, 178-180


57-71: 🎯 Functional Correctness

Drop this comment RuntimeHostBoot passes only codec and blobPort to CborCheckpointStoreAdapter; no blobStorage property is being ignored.

			> Likely an incorrect or invalid review comment.
test/unit/infrastructure/adapters/CborCheckpointStoreAdapter.test.ts (2)

372-437: LGTM! Good negative-path coverage for malformed edgeBirthEvent payloads (missing value, non-string key, invalid lamport), and the explicit treeOids literals confirm the adapter's mixed extension/no-extension key scheme is intentional and consistently tested.


38-42: LGTM!

Also applies to: 81-91, 197-199, 270-325

docs/topics/reference.md (1)

69-84: 🗄️ Data Integrity & Integration

Root export narrowing is intentional

These types now live on legacy.ts only, matching the narrowed root API surface.

			> Likely an incorrect or invalid review comment.

@github-actions

Copy link
Copy Markdown

Release Preflight

  • package version: 18.2.1
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v18.2.1. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@flyingrobots

Copy link
Copy Markdown
Member Author

Merge gate

  • Current head: d86193eed7d15963cc817552eebbaaaff2cccb8a
  • All required GitHub checks are successful, including Node 22, Bun, Deno, coverage, release preflight, link checking, and every type-firewall lane.
  • CodeRabbit completed successfully on this head.
  • Thread-aware review audit: 0 unresolved threads.
  • Self-review and Code Lawyer review are complete.

Source evidence:

  • RootSet entries preserve each snapshot retention policy. [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L63-L76@d86193eed7d15963cc817552eebbaaaff2cccb8a]
  • RootSet publication precedes index publication, and failed narrowing leaves a safe retained superset. [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L186-L214@d86193eed7d15963cc817552eebbaaaff2cccb8a]
  • Doctor and repair compare live records to roots and reconcile the RootSet. [cite: src/infrastructure/adapters/GitCasStateCacheRootSetCoordinator.ts#L217-L260@d86193eed7d15963cc817552eebbaaaff2cccb8a]
  • The integration test proves a legacy payload becomes non-prunable before use and becomes prunable after its live index entry is removed. [cite: test/integration/infrastructure/adapters/GitCasWarpStateCacheAdapter.retention.integration.test.ts#L118-L141@d86193eed7d15963cc817552eebbaaaff2cccb8a]

Merge gate: clean.

@flyingrobots flyingrobots merged commit fb2c0c4 into main Jul 13, 2026
17 checks passed
@flyingrobots flyingrobots deleted the v19-closeout-next-five branch July 13, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

State-cache payload refs are not anchored against Git GC

1 participant