feat: resume retained materialization predecessors#771
Conversation
📝 WalkthroughWalkthroughRetained materialization support now stores a canonical replay basis, upgrades descriptors to schema v4, resumes exact or compatible predecessor materializations, and replays only predecessor suffixes when eligible. CAS adapters, controller wiring, shared caching, ports, fixtures, tests, and documentation are updated accordingly. ChangesRetained materialization resume
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Runtime
participant MaterializeLiveStrategy
participant RetainedMaterializationResumeStrategy
participant MaterializationStore
participant GitCasCache
participant ReplayBasis
Runtime->>MaterializeLiveStrategy: materialize coordinate
MaterializeLiveStrategy->>RetainedMaterializationResumeStrategy: tryResume coordinate
RetainedMaterializationResumeStrategy->>MaterializationStore: acquire exact or predecessor
MaterializationStore->>GitCasCache: inspect v4 cache entries
GitCasCache-->>MaterializationStore: compatible retained coordinate
MaterializationStore->>ReplayBasis: load canonical replay basis
ReplayBasis-->>MaterializationStore: validated WarpState
MaterializationStore-->>RetainedMaterializationResumeStrategy: acquired materialization
RetainedMaterializationResumeStrategy-->>MaterializeLiveStrategy: resumed MaterializeResult
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Release Preflight
If this PR is from a |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/topics/cas-first-memoized-materialization.md`:
- Around line 87-95: Update the lifecycle diagram and its “Check the WARP state
cache” step to show that MaterializeLiveStrategy.materialize() first attempts
retained exact and compatible-predecessor resume, then reads the WARP state
cache only when retained resume does not apply. Preserve the existing branching
and behavior descriptions while correcting the documented lookup order.
In `@src/infrastructure/adapters/GitCasMaterializationPredecessorResolver.ts`:
- Around line 17-18: Update the predecessor resolution flow around
acquireBestCompatiblePredecessorLocked to scope cache keys and scan-budget
accounting by lane and coordinate before reading descriptors, preventing one
lane’s entries from consuming another’s budget. Convert
storageError('materialization cache exceeds predecessor scan limit') into a null
predecessor result so MaterializeLiveStrategy.materialize() can fall back to
resolveConfiguredStateCache instead of propagating the error.
In `@test/helpers/InMemoryMaterializationStore.ts`:
- Around line 125-127: Update the replay-basis handling in
InMemoryMaterializationStore to store a detached codec round-trip snapshot
rather than request.replayBasis directly, and apply the same conversion when
returning the basis so callers receive a fresh instance. Preserve the existing
replayBases keying and behavior for undefined bases.
In
`@test/integration/infrastructure/adapters/GitCasMaterializationStoreAdapter.integration.test.ts`:
- Line 384: Update the fixture’s replayBasis setup near
MaterializationRoot.retained so it does not alias replayBasis to
provenanceSupport. Either create a dedicated ninth bundle containing the
replay-basis member, or use MaterializationRoot.unavailable() when the fixture
does not intend to provide replay data.
🪄 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: 10800259-9856-4f2b-9c86-d7fcc9da2d61
📒 Files selected for processing (34)
docs/topics/cas-first-memoized-materialization.mdsrc/domain/materialization/MaterializationRoots.tssrc/domain/materialization/TrieMaterializationReader.tssrc/domain/services/controllers/MaterializationRetention.tssrc/domain/services/controllers/MaterializeController.tssrc/domain/services/controllers/MaterializeHelpers.tssrc/domain/services/controllers/MaterializeLiveStrategy.tssrc/domain/services/controllers/MaterializeSessionBridge.tssrc/domain/services/controllers/MaterializeStrategyRuntime.tssrc/domain/services/controllers/RetainedMaterializationResumeStrategy.tssrc/domain/warp/RuntimeHostBoot.tssrc/infrastructure/adapters/GitCasMaterializationDescriptor.tssrc/infrastructure/adapters/GitCasMaterializationPredecessorResolver.tssrc/infrastructure/adapters/GitCasMaterializationReplayBasis.tssrc/infrastructure/adapters/GitCasMaterializationStoreAdapter.tssrc/infrastructure/adapters/GitCasMaterializationStoreTypes.tssrc/infrastructure/adapters/GitCasMaterializationStoreWitness.tssrc/infrastructure/adapters/GitCasMaterializationWorkspace.tssrc/infrastructure/codecs/WarpStateCborCodec.tssrc/ports/MaterializationStorePort.tssrc/ports/MaterializationWorkspacePort.tstest/helpers/InMemoryGitCasFacade.tstest/helpers/InMemoryMaterializationStore.tstest/integration/api/materialization.retainedResume.test.tstest/integration/infrastructure/adapters/GitCasMaterializationStoreAdapter.integration.test.tstest/unit/domain/materialization/MaterializationIdentity.test.tstest/unit/domain/materialization/TrieMaterializationReader.test.tstest/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.tstest/unit/domain/services/controllers/MaterializeController.stateSession.test.tstest/unit/domain/services/controllers/MaterializeController.test.tstest/unit/domain/warp/hydrateCheckpointIndex.regression.test.tstest/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.lifecycle.test.tstest/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.resume.test.tstest/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: coverage-threshold
- GitHub Check: test-node (22)
- GitHub Check: preflight
🧰 Additional context used
📓 Path-based instructions (5)
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx,js,jsx}: Do not introduceany,as any,as unknown as,unknown(outside adapters),Record<string, unknown>(outside adapters),*Likeplaceholder types,JSON.parse/JSON.stringify(outside adapters),fetch(outside adapters),process.env(outside adapters),@ts-ignore, orz.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 createutils.ts,helpers.ts,misc.ts, orcommon.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 asUint8Array;Bufferbelongs in infrastructure adapters.
Files:
src/domain/services/controllers/MaterializeHelpers.tssrc/domain/services/controllers/MaterializeStrategyRuntime.tssrc/infrastructure/codecs/WarpStateCborCodec.tssrc/infrastructure/adapters/GitCasMaterializationWorkspace.tssrc/ports/MaterializationWorkspacePort.tssrc/infrastructure/adapters/GitCasMaterializationStoreTypes.tssrc/domain/warp/RuntimeHostBoot.tssrc/infrastructure/adapters/GitCasMaterializationReplayBasis.tssrc/infrastructure/adapters/GitCasMaterializationDescriptor.tssrc/domain/materialization/TrieMaterializationReader.tssrc/infrastructure/adapters/GitCasMaterializationStoreWitness.tssrc/domain/materialization/MaterializationRoots.tssrc/domain/services/controllers/MaterializeSessionBridge.tssrc/ports/MaterializationStorePort.tssrc/infrastructure/adapters/GitCasMaterializationPredecessorResolver.tssrc/domain/services/controllers/MaterializationRetention.tssrc/domain/services/controllers/MaterializeController.tssrc/domain/services/controllers/MaterializeLiveStrategy.tssrc/domain/services/controllers/RetainedMaterializationResumeStrategy.tssrc/infrastructure/adapters/GitCasMaterializationStoreAdapter.ts
src/domain/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/domain/**/*.{ts,tsx,js,jsx}: Insrc/domain/**, do not useDate.now(),new Date(),Date(),performance.now(),Math.random(),crypto.randomUUID(),crypto.getRandomValues(),setTimeout,setInterval, rawnew 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 extendWarpError.
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/MaterializeHelpers.tssrc/domain/services/controllers/MaterializeStrategyRuntime.tssrc/domain/warp/RuntimeHostBoot.tssrc/domain/materialization/TrieMaterializationReader.tssrc/domain/materialization/MaterializationRoots.tssrc/domain/services/controllers/MaterializeSessionBridge.tssrc/domain/services/controllers/MaterializationRetention.tssrc/domain/services/controllers/MaterializeController.tssrc/domain/services/controllers/MaterializeLiveStrategy.tssrc/domain/services/controllers/RetainedMaterializationResumeStrategy.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use explicit domain concepts with validated constructors,
Object.freeze, andinstanceofdispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.
Files:
src/domain/services/controllers/MaterializeHelpers.tssrc/domain/services/controllers/MaterializeStrategyRuntime.tssrc/domain/warp/RuntimeHostBoot.tssrc/domain/materialization/TrieMaterializationReader.tssrc/domain/materialization/MaterializationRoots.tssrc/domain/services/controllers/MaterializeSessionBridge.tssrc/domain/services/controllers/MaterializationRetention.tssrc/domain/services/controllers/MaterializeController.tssrc/domain/services/controllers/MaterializeLiveStrategy.tssrc/domain/services/controllers/RetainedMaterializationResumeStrategy.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Do not use direct imports fromsrc/infrastructure/**insrc/domain/**orsrc/ports/**; depend on a port instead.
Do not use direct Node built-ins insrc/domain/**orsrc/ports/**; use a port instead.
Files:
src/domain/services/controllers/MaterializeHelpers.tstest/unit/domain/materialization/TrieMaterializationReader.test.tssrc/domain/services/controllers/MaterializeStrategyRuntime.tssrc/infrastructure/codecs/WarpStateCborCodec.tstest/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.tssrc/infrastructure/adapters/GitCasMaterializationWorkspace.tstest/unit/domain/warp/hydrateCheckpointIndex.regression.test.tstest/integration/infrastructure/adapters/GitCasMaterializationStoreAdapter.integration.test.tssrc/ports/MaterializationWorkspacePort.tssrc/infrastructure/adapters/GitCasMaterializationStoreTypes.tssrc/domain/warp/RuntimeHostBoot.tstest/unit/domain/materialization/MaterializationIdentity.test.tstest/helpers/InMemoryMaterializationStore.tstest/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.resume.test.tssrc/infrastructure/adapters/GitCasMaterializationReplayBasis.tssrc/infrastructure/adapters/GitCasMaterializationDescriptor.tssrc/domain/materialization/TrieMaterializationReader.tssrc/infrastructure/adapters/GitCasMaterializationStoreWitness.tssrc/domain/materialization/MaterializationRoots.tssrc/domain/services/controllers/MaterializeSessionBridge.tssrc/ports/MaterializationStorePort.tssrc/infrastructure/adapters/GitCasMaterializationPredecessorResolver.tssrc/domain/services/controllers/MaterializationRetention.tstest/unit/domain/services/controllers/MaterializeController.test.tstest/integration/api/materialization.retainedResume.test.tssrc/domain/services/controllers/MaterializeController.tstest/helpers/InMemoryGitCasFacade.tstest/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.test.tssrc/domain/services/controllers/MaterializeLiveStrategy.tstest/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.lifecycle.test.tstest/unit/domain/services/controllers/MaterializeController.stateSession.test.tssrc/domain/services/controllers/RetainedMaterializationResumeStrategy.tssrc/infrastructure/adapters/GitCasMaterializationStoreAdapter.ts
src/ports/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
In
src/ports/**, do not import Node built-ins orsrc/infrastructure/**; ports must stay abstract and depend only on boundary-safe types.
Files:
src/ports/MaterializationWorkspacePort.tssrc/ports/MaterializationStorePort.ts
🪛 ast-grep (0.44.1)
test/integration/infrastructure/adapters/GitCasMaterializationStoreAdapter.integration.test.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 { 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)
test/integration/api/materialization.retainedResume.test.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 { 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)
[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 { 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)
[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 { 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)
[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 { 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)
🔇 Additional comments (36)
src/domain/services/controllers/MaterializationRetention.ts (1)
16-99: LGTM!src/domain/services/controllers/MaterializeController.ts (5)
56-58: LGTM!
241-245: LGTM!
311-313: LGTM!
368-406: LGTM!
423-437: LGTM!src/domain/services/controllers/MaterializeSessionBridge.ts (3)
57-57: LGTM!
131-134: LGTM!
196-206: LGTM!src/domain/services/controllers/MaterializeStrategyRuntime.ts (1)
75-75: LGTM!test/integration/api/materialization.retainedResume.test.ts (5)
10-12: LGTM!
77-78: LGTM!
181-222: LGTM!
226-232: LGTM!
279-300: LGTM!test/unit/domain/services/controllers/MaterializeController.liveNodeRead.test.ts (1)
366-366: LGTM!test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts (1)
518-519: LGTM!test/unit/domain/warp/hydrateCheckpointIndex.regression.test.ts (1)
57-60: LGTM!src/domain/materialization/MaterializationRoots.ts (1)
12-12: LGTM!Also applies to: 26-26, 40-40, 53-53, 63-63
src/domain/materialization/TrieMaterializationReader.ts (1)
26-33: LGTM!Also applies to: 45-47, 63-63, 150-156
src/domain/warp/RuntimeHostBoot.ts (1)
346-354: LGTM!Also applies to: 363-363
src/infrastructure/adapters/GitCasMaterializationStoreTypes.ts (1)
1-36: LGTM!src/infrastructure/adapters/GitCasMaterializationStoreWitness.ts (1)
1-63: LGTM!src/infrastructure/codecs/WarpStateCborCodec.ts (1)
55-66: LGTM!Also applies to: 230-244
src/ports/MaterializationWorkspacePort.ts (1)
5-5: LGTM!Also applies to: 18-18
test/helpers/InMemoryMaterializationStore.ts (1)
15-15: LGTM!Also applies to: 96-96
src/infrastructure/adapters/GitCasMaterializationDescriptor.ts (1)
12-12: LGTM!Also applies to: 65-81
src/ports/MaterializationStorePort.ts (1)
5-5: LGTM!Also applies to: 15-18, 31-41
src/infrastructure/adapters/GitCasMaterializationWorkspace.ts (1)
26-36: LGTM!src/infrastructure/adapters/GitCasMaterializationReplayBasis.ts (1)
34-118: LGTM!src/infrastructure/adapters/GitCasMaterializationStoreAdapter.ts (2)
108-189: LGTM! Replay-basis staging, legacy v2/v3 cleanup, and the predecessor/replay-basis port overrides are wired correctly and match the resolver/replay-basis contracts.Also applies to: 234-330
191-213: 🗄️ Data Integrity & IntegrationCheck the git-cas bundle ordering semantics, not just the adapter surface.
requireWorkspaceStage(bundle)validates the retained bundle, butrequireWorkspaceStage(descriptorPage)was dropped for the descriptor page. IfputOrderedonly records handles rather than retaining/fault-catching each member, the bundle check may not catch a descriptor page that never staged/retained properly; if it does, add a short invariant comment so future readers understand the transitive validation.test/helpers/InMemoryGitCasFacade.ts (1)
18-26: LGTM!Also applies to: 69-69, 347-347, 388-418, 548-557, 630-654
test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.resume.test.ts (1)
1-201: LGTM! Solid coverage of the retained-resume happy path, fail-closed corruption handling, and the two predecessor-exclusion edge cases.test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.test.ts (1)
26-26: LGTM!Also applies to: 74-74, 583-607, 624-662, 671-698, 710-722
test/unit/infrastructure/adapters/GitCasMaterializationStoreAdapter.lifecycle.test.ts (1)
20-20: LGTM!Also applies to: 63-121, 145-171, 221-270
Release Preflight
If this PR is from a |
Summary
Safety and compatibility
Validation
Refs #738
Refs #759