Skip to content

Retain bounded live liveness materializations#773

Merged
flyingrobots merged 3 commits into
mainfrom
v19/cas-bounded-materialization
Jul 24, 2026
Merged

Retain bounded live liveness materializations#773
flyingrobots merged 3 commits into
mainfrom
v19/cas-bounded-materialization

Conversation

@flyingrobots

Copy link
Copy Markdown
Member

Summary

  • stream cold live node and edge liveness into page-bounded git-cas state sessions without constructing WarpState or adjacency
  • retain partial materialization handles with stateHash: null so bounded roots cannot masquerade as whole-state snapshots
  • establish descriptor schema v5 as the first release contract and remove migration and cleanup support for unreleased v2-v4 cache profiles

Issue

Refs #738

Test plan

  • npm run typecheck
  • npm run lint
  • npm run test:coverage:ci (609 files, 7,357 tests; 92.95% lines)
  • npm run test:local (six stable shards, 589 files, 7,188 tests)
  • npx vitest run test/integration (21 files, 103 tests)
  • markdown, docs topology, source-version, consumer, publication-surface, and link gates
  • full pre-push IRONCLAD M9 gate

ADR checks

  • This PR does not implement ADR 2 without satisfying ADR 3
  • If this PR touches persisted op formats, I linked the ADR 3 readiness issue
  • If this PR touches wire compatibility, I confirmed canonical-only ops are still rejected on the wire pre-cutover
  • If this PR touches schema constants, I confirmed patch and checkpoint namespaces remain distinct

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@flyingrobots, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 17cb7a5d-d491-4c25-8ff5-d1150cd78646

📥 Commits

Reviewing files that changed from the base of the PR and between ac34e6a and f5eae41.

📒 Files selected for processing (9)
  • src/domain/orset/session/StateSession.ts
  • src/domain/services/controllers/BoundedLiveMaterialization.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreValidation.ts
  • test/integration/infrastructure/adapters/GitCasMaterializationStoreAdapter.integration.test.ts
  • test/unit/domain/orset/session/StateSession.test.ts
  • test/unit/domain/services/controllers/BoundedLiveMaterialization.test.ts
  • test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.resume.test.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreValidation.test.ts
📝 Walkthrough

Walkthrough

Materialization descriptors advance to schema v5 and support partial handles with stateHash: null. Live reads can boundedly replay liveness operations into CAS-backed sessions, while whole-state resume excludes partial handles. Controllers, adapters, documentation, and tests reflect the new contracts.

Changes

Schema v5 partial materialization

Layer / File(s) Summary
Descriptor and retention contracts
CHANGELOG.md, docs/topics/cas-first-memoized-materialization.md, src/domain/materialization/MaterializationHandle.ts, src/infrastructure/adapters/*, src/ports/MaterializationWorkspacePort.ts
Descriptor schema v5 and workspace requests accept nullable state hashes, validate partial-root capabilities, reject partial replay bases, and remove legacy cache cleanup.
Contract and adapter validation
test/unit/domain/materialization/MaterializationIdentity.test.ts, test/unit/infrastructure/adapters/*
Tests cover partial handles, v5 keys, nullable-state retention, root validation, and removal of legacy cleanup scenarios.

Bounded live materialization

Layer / File(s) Summary
Liveness replay and live routing
src/domain/services/JoinReducerSession.ts, src/domain/services/controllers/BoundedLiveMaterialization.ts, src/domain/services/controllers/MaterializeLiveStrategy.ts
Node and edge liveness operations are replayed into bounded sessions, promoted as partial roots, validated on acquisition, and selected before whole-state replay.
Bounded-flow tests
test/unit/domain/services/JoinReducer.stateSession.test.ts, test/unit/domain/services/controllers/BoundedLiveMaterialization.test.ts, test/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.ts
Tests cover liveness replay, resource cleanup, acquisition failures, exact snapshot fallback, and missing session configuration.

Resume and resolution behavior

Layer / File(s) Summary
Retained resume and resolution
src/domain/services/controllers/MaterializationRetention.ts, src/domain/services/controllers/MaterializeController.ts, src/domain/services/controllers/MaterializedLiveResolution.ts, src/domain/services/controllers/MaterializeLiveStrategy.ts
Partial handles are excluded from whole-state resume, and acquired live resolutions validate coordinate, state hash, and bundle identity before delegating release.
Resolution and integration tests
test/unit/domain/services/controllers/MaterializedLiveResolution.test.ts, test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts
Tests cover successful resolution, missing or changed handles, delegated release, and nullable state hashes on live-coordinate misses.

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

Possibly related issues

Possibly related PRs

  • git-stunts/git-warp#751 — Provides the retained CAS materialization foundation extended here with partial handles and schema v5.
  • git-stunts/git-warp#755 — Shares the bounded session and workspace-retention infrastructure used by this flow.
  • git-stunts/git-warp#771 — Directly relates to descriptor schema and replay-basis changes for retained materialization.

Sequence Diagram(s)

sequenceDiagram
  participant MaterializeLiveStrategy
  participant BoundedLiveMaterialization
  participant PatchCollector
  participant StateSession
  participant MaterializationWorkspacePort
  MaterializeLiveStrategy->>BoundedLiveMaterialization: resolve bounded live materialization
  BoundedLiveMaterialization->>PatchCollector: stream liveness patches
  BoundedLiveMaterialization->>StateSession: apply node and edge liveness
  BoundedLiveMaterialization->>MaterializationWorkspacePort: promote partial roots
  BoundedLiveMaterialization-->>MaterializeLiveStrategy: return live resolution
Loading

Poem

A rabbit hops through roots of green,
With nullable hashes tucked unseen.
Liveness patches dance and stream,
CAS pages hold a partial dream.
Schema five guards every byte—
Then rebuilds stale caches right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly reflects the main change: retaining bounded live liveness materializations.
Description check ✅ Passed The description matches the template with Summary, Issue, Test plan, and ADR checks filled in.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

❤️ Share

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

@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[bot]
coderabbitai Bot previously requested changes Jul 24, 2026

@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: 3

🤖 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/controllers/BoundedLiveMaterialization.ts`:
- Around line 79-102: Update buildBoundedMaterialization so any failure after
openStateSession succeeds closes the session before propagating the error,
covering both replayLiveness and retainPreparedLiveness failures. Preserve the
existing patchCount === 0 cleanup and successful retention behavior, while
ensuring cleanup does not mask the original error.

In `@src/infrastructure/adapters/GitCasMaterializationStoreValidation.ts`:
- Around line 12-31: Update requireRetainStateHash to enforce the
complete-retain invariant: when request.stateHash is non-null, require
request.roots.replayBasis.status to be 'retained' before allowing validation to
succeed. Reject this invalid combination before stageWorkspaceBundle, while
preserving the existing partial-materialization checks and non-empty stateHash
validation.

In
`@test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts`:
- Line 656: Update the assertion for resolution.materialization to first verify
that the bounded resolution returned a materialization handle, then assert its
stateHash is null. Avoid relying solely on optional chaining so the test fails
when materialization is absent.
🪄 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 Plus

Run ID: 8fa5c899-0d83-412e-a933-f9c356b80ce2

📥 Commits

Reviewing files that changed from the base of the PR and between c872789 and ac34e6a.

📒 Files selected for processing (24)
  • CHANGELOG.md
  • docs/topics/cas-first-memoized-materialization.md
  • src/domain/materialization/MaterializationHandle.ts
  • src/domain/services/JoinReducerSession.ts
  • src/domain/services/controllers/BoundedLiveMaterialization.ts
  • src/domain/services/controllers/MaterializationRetention.ts
  • src/domain/services/controllers/MaterializeController.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/MaterializedLiveResolution.ts
  • src/infrastructure/adapters/GitCasMaterializationDescriptor.ts
  • src/infrastructure/adapters/GitCasMaterializationReplayBasis.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreAdapter.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreValidation.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreWitness.ts
  • src/ports/MaterializationWorkspacePort.ts
  • test/unit/domain/materialization/MaterializationIdentity.test.ts
  • test/unit/domain/services/JoinReducer.stateSession.test.ts
  • test/unit/domain/services/controllers/BoundedLiveMaterialization.test.ts
  • test/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.ts
  • test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts
  • test/unit/domain/services/controllers/MaterializedLiveResolution.test.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.lifecycle.test.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.test.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreValidation.test.ts
💤 Files with no reviewable changes (2)
  • src/infrastructure/adapters/GitCasMaterializationStoreWitness.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.lifecycle.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: preflight
  • GitHub Check: test-node (22)
  • GitHub Check: coverage-threshold
🧰 Additional context used
📓 Path-based instructions (5)
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/MaterializationWorkspacePort.ts
  • src/infrastructure/adapters/GitCasMaterializationReplayBasis.ts
  • src/domain/services/controllers/BoundedLiveMaterialization.ts
  • src/domain/services/controllers/MaterializeController.ts
  • src/domain/services/controllers/MaterializedLiveResolution.ts
  • src/domain/services/JoinReducerSession.ts
  • src/domain/materialization/MaterializationHandle.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/MaterializationRetention.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreValidation.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreAdapter.ts
  • src/infrastructure/adapters/GitCasMaterializationDescriptor.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/MaterializationWorkspacePort.ts
**/*.{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:

  • src/ports/MaterializationWorkspacePort.ts
  • src/infrastructure/adapters/GitCasMaterializationReplayBasis.ts
  • test/unit/domain/materialization/MaterializationIdentity.test.ts
  • test/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreValidation.test.ts
  • src/domain/services/controllers/BoundedLiveMaterialization.ts
  • test/unit/domain/services/JoinReducer.stateSession.test.ts
  • test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts
  • src/domain/services/controllers/MaterializeController.ts
  • src/domain/services/controllers/MaterializedLiveResolution.ts
  • src/domain/services/JoinReducerSession.ts
  • src/domain/materialization/MaterializationHandle.ts
  • test/unit/domain/services/controllers/MaterializedLiveResolution.test.ts
  • test/unit/domain/services/controllers/BoundedLiveMaterialization.test.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.test.ts
  • src/domain/services/controllers/MaterializationRetention.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreValidation.ts
  • src/infrastructure/adapters/GitCasMaterializationStoreAdapter.ts
  • src/infrastructure/adapters/GitCasMaterializationDescriptor.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/controllers/BoundedLiveMaterialization.ts
  • src/domain/services/controllers/MaterializeController.ts
  • src/domain/services/controllers/MaterializedLiveResolution.ts
  • src/domain/services/JoinReducerSession.ts
  • src/domain/materialization/MaterializationHandle.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/MaterializationRetention.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/controllers/BoundedLiveMaterialization.ts
  • src/domain/services/controllers/MaterializeController.ts
  • src/domain/services/controllers/MaterializedLiveResolution.ts
  • src/domain/services/JoinReducerSession.ts
  • src/domain/materialization/MaterializationHandle.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/MaterializationRetention.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 (21)
CHANGELOG.md (1)

69-83: LGTM!

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

101-111: LGTM!

Also applies to: 146-162, 227-243

src/ports/MaterializationWorkspacePort.ts (1)

17-17: LGTM!

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

14-59: LGTM!

src/domain/services/JoinReducerSession.ts (1)

134-165: LGTM!

src/domain/services/controllers/BoundedLiveMaterialization.ts (1)

25-49: LGTM!

Also applies to: 104-179

test/unit/domain/services/JoinReducer.stateSession.test.ts (1)

121-150: LGTM!

test/unit/domain/services/controllers/BoundedLiveMaterialization.test.ts (1)

38-79: LGTM!

test/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.ts (1)

15-15: LGTM!

Also applies to: 147-157

src/domain/services/controllers/MaterializeController.ts (1)

278-338: LGTM!

src/domain/materialization/MaterializationHandle.ts (1)

13-28: LGTM!

Also applies to: 69-71

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

12-19: LGTM!

Also applies to: 54-60, 128-145, 238-240

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

74-76: LGTM!

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

39-39: LGTM!

Also applies to: 232-233


168-176: 🗄️ Data Integrity & Integration

No change needed.

retain() already rejects stateHash: null with any preserved replay basis before replayBasis.stage() runs, and descriptor decoding enforces the same invariant for stale cache entries.

test/unit/domain/materialization/MaterializationIdentity.test.ts (1)

202-214: LGTM!

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

74-74: LGTM!

Also applies to: 380-407, 498-504, 718-718

src/domain/services/controllers/MaterializeLiveStrategy.ts (1)

30-31: LGTM!

Also applies to: 123-129

src/domain/services/controllers/MaterializationRetention.ts (1)

30-54: LGTM!

src/domain/services/controllers/MaterializedLiveResolution.ts (1)

1-41: LGTM!

test/unit/domain/services/controllers/MaterializedLiveResolution.test.ts (1)

15-104: LGTM!

Comment thread src/domain/services/controllers/BoundedLiveMaterialization.ts
Comment thread src/infrastructure/adapters/GitCasMaterializationStoreValidation.ts
Comment thread test/unit/domain/services/controllers/MaterializeController.stateSession.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.

@flyingrobots
flyingrobots dismissed coderabbitai[bot]’s stale review July 24, 2026 17:16

All three actionable threads are resolved by acdbc5d; f5eae41 corrects the integration fixtures exposed by the new invariant. CodeRabbit re-review is rate limited on current head f5eae41, and every required check including Node 22 unit/integration/BATS, coverage, and release preflight is green.

@flyingrobots
flyingrobots merged commit 571389a into main Jul 24, 2026
17 checks passed
@flyingrobots
flyingrobots deleted the v19/cas-bounded-materialization branch July 24, 2026 17:16
@coderabbitai coderabbitai Bot mentioned this pull request Jul 25, 2026
4 tasks
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.

1 participant