Skip to content

Fix warm state-cache materialization hits - #750

Merged
flyingrobots merged 7 commits into
mainfrom
v19-materialization-warm-hit
Jul 15, 2026
Merged

Fix warm state-cache materialization hits#750
flyingrobots merged 7 commits into
mainfrom
v19-materialization-warm-hit

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Jul 15, 2026

Copy link
Copy Markdown
Member

Refs #734.
Refs #738.
Refs #739.

Summary

  • Honor exact live state-cache hits even when RuntimeHost requests a diff for its resident bitmap view.
  • Keep exact misses on the replay path when a diff is required, rather than applying a predecessor snapshot against the wrong resident basis.
  • Preserve basis-equivalent resident provenance across unchanged warm hits.
  • Derive maximum observed Lamport time from restored state, including snapshot, predecessor, and checkpoint bases.
  • Mark state-only cache and checkpoint payloads as provenance-degraded until the retained payload actually includes its provenance index.
  • Preserve the checkpoint prefix index when present and fail closed when checkpoint or materializeAt() replay omits it.
  • Keep eager patch and sync state installs tied to their updated causal coordinates so the next provenance decision compares the correct basis.
  • Skip duplicate snapshot publication and bitmap/property view reconstruction on an unchanged second materialization.

Root Cause

RuntimeHost.materialize() requests a diff after its bitmap index has been built. MaterializeLiveStrategy treated wantDiff as a reason to bypass the state cache entirely, so every subsequent materialization replayed patch history even when an exact retained snapshot existed.

Simply allowing the exact hit exposed two metadata hazards in the existing snapshot result: it replaced a valid resident provenance index with an empty index, and it reported maximum observed Lamport time as zero. The fix makes exact-hit reuse conditional only at the cache lookup layer, then preserves resident provenance only when hash, frontier, ceiling, and zero-replay facts prove the basis is unchanged. Restored Lamport truth comes from the state itself.

The same provenance comparison also depends on the basis metadata attached to the resident state. Eager patch and sync installation now advance _cachedFrontier and _cachedCeiling together with _materializedGraph; calls without a known coordinate clear that metadata rather than retaining a stale basis.

Evidence Contract

The current state-cache payload stores WarpState, not ProvenanceIndex. Cache-only restoration therefore reports degraded provenance instead of presenting an empty index as complete support. An unchanged resident runtime may keep its existing index, but its degraded/full posture is never upgraded by the cache hit.

The same rule now covers checkpoint replay. A checkpoint carrying a prefix provenance index retains full posture and extends that index with suffix patches. A cache-backed checkpoint without that index, and the state-only materializeAt() path, report degraded provenance.

Materialized state installation accepts an explicit causal coordinate. Patch and sync controllers supply the coordinate they actually installed; unknown or legacy bases fail closed to null, preventing a later materialization from preserving provenance against stale coordinate metadata.

Validation

  • npm run test:local: 563 files passed, 6,952 tests passed, 2 skipped.
  • npm run test:coverage:ci: 575 files passed, 1 skipped; 7,026 tests passed, 2 skipped; 92.72% line coverage.
  • Changed executable statements: 31/31 covered.
  • npm run typecheck
  • npm run lint
  • npm run build
  • npm run typecheck:consumer
  • npm run lint:semgrep
  • npm run lint:sludge
  • npm run lint:docs-topology
  • npm run typecheck:surface
  • Pre-push IRONCLAD M9 firewall passed at 4c2392e0e298.

Scope

This removes redundant replay for exact warm hits and fixes the causal metadata contract around those hits. It does not close #738 or #739: full WarpState hydration remains, and bounded CAS page-backed observer reads, shared checkpoint/materialization bundles, cache diagnostics, and removal of remaining WARP-local cache policy are still required.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change updates state-cache materialization to track degraded provenance explicitly, preserve resident provenance for matching exact hits, compute observed Lamport values from state, and cover cache, checkpoint, replay, and warm-hit behavior with tests and documentation.

Changes

Provenance-aware materialization

Layer / File(s) Summary
Provenance selection contracts
src/domain/services/controllers/MaterializeProvenancePolicy.ts, src/domain/services/controllers/MaterializeHelpers.ts, src/domain/services/controllers/MaterializeStrategyRuntime.ts, src/ports/WarpStateCachePort.ts, test/unit/domain/services/controllers/MaterializeProvenancePolicy.test.ts
Adds provenance selection rules, explicit wrapper posture typing, Lamport extraction, and tests for resident-index preservation and degraded fallback.
Materialization and cache resolution
src/domain/services/controllers/MaterializeController.ts, src/domain/services/controllers/Materialize*Strategy.ts, src/domain/services/controllers/MaterializeSnapshotCacheResult.ts, test/unit/domain/services/controllers/MaterializeController*.test.ts
Propagates provenance posture through materialization, marks cache-derived results degraded, computes observed Lamport values, and updates exact-hit, predecessor, diff, and checkpoint behavior.
Runtime and checkpoint integration
src/domain/RuntimeHost.ts, src/domain/services/controllers/CheckpointController.ts, test/unit/domain/RuntimeHost.snapshotCache.test.ts, test/unit/domain/services/controllers/CheckpointController.snapshotCache.test.ts, docs/topics/cas-first-memoized-materialization.md
Applies post-materialization provenance selection, stores degraded checkpoint records, verifies warm-cache reuse, and documents cache provenance behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RuntimeHost
  participant MaterializeLiveStrategy
  participant MaterializeSnapshotCacheResult
  participant MaterializeController
  RuntimeHost->>MaterializeLiveStrategy: request materialization
  MaterializeLiveStrategy->>MaterializeSnapshotCacheResult: resolve exact snapshot
  MaterializeSnapshotCacheResult->>MaterializeController: return degraded result and observed Lamport
  MaterializeController->>RuntimeHost: publish materialized state
  RuntimeHost->>RuntimeHost: select resident or materialized provenance
Loading

Possibly related PRs

Poem

I’m a rabbit in the cache tonight,
Preserving proofs when hashes align just right.
Lamports hop from state to state,
Degraded marks keep records straight.
Exact hits bloom, replays behave—
A tidy burrow for the paths we save.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR does not implement #738's CAS-backed MaterializationHandle replacement and explicitly leaves that scope for later. Replace RuntimeHost's in-process WarpState/full-view caches with MaterializationHandle-based bounded, opt-in materialization as required by #738.
Out of Scope Changes check ⚠️ Warning Most changes add warm-hit provenance and Lamport handling, which are unrelated to #738's CAS-backed handle replacement scope. Split these warm-hit/provenance fixes into a separate PR, or retarget the changes to the #738 CAS-backed materialization scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing warm state-cache materialization hits.
Description check ✅ Passed The description covers summary, linked issues, validation, and the main behavioral changes; only the optional ADR checklist is omitted.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

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

Caution

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

⚠️ Outside diff range comments (1)
src/domain/RuntimeHost.ts (1)

829-853: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Keep the provenance basis in sync in _setMaterializedState _onMaterialized now compares against _materializedGraph?.stateHash, _cachedFrontier, and _cachedCeiling; this path updates _materializedGraph but leaves the other two stale, so the next materialization can make the wrong preserve/degrade call.

🤖 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/RuntimeHost.ts` around lines 829 - 853, Update
_setMaterializedState to refresh _cachedFrontier and _cachedCeiling alongside
_materializedGraph after materialization, using the corresponding values from
result or the established materialized-state basis. Ensure the provenance inputs
consumed by _onMaterialized remain synchronized for the next materialization.
🤖 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/MaterializeStrategyRuntime.ts`:
- Around line 40-41: Remove the duplicate MaterializeWrappedStateProvenance
union and import the existing WarpStateSnapshotProvenancePosture type from the
shared port definition. Update any references in MaterializeStrategyRuntime.ts
to use the shared alias while preserving the existing full/degraded behavior.

---

Outside diff comments:
In `@src/domain/RuntimeHost.ts`:
- Around line 829-853: Update _setMaterializedState to refresh _cachedFrontier
and _cachedCeiling alongside _materializedGraph after materialization, using the
corresponding values from result or the established materialized-state basis.
Ensure the provenance inputs consumed by _onMaterialized remain synchronized for
the next materialization.
🪄 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: cb8bf8b5-9a88-4f8e-ab24-d7814e9beb56

📥 Commits

Reviewing files that changed from the base of the PR and between 1d621bc and 44cfb8f.

📒 Files selected for processing (18)
  • docs/topics/cas-first-memoized-materialization.md
  • src/domain/RuntimeHost.ts
  • src/domain/services/controllers/CheckpointController.ts
  • src/domain/services/controllers/MaterializeCheckpointStrategy.ts
  • src/domain/services/controllers/MaterializeController.ts
  • src/domain/services/controllers/MaterializeCoordinateStrategy.ts
  • src/domain/services/controllers/MaterializeHelpers.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/MaterializeProvenancePolicy.ts
  • src/domain/services/controllers/MaterializeSnapshotCacheResult.ts
  • src/domain/services/controllers/MaterializeStrategyRuntime.ts
  • src/ports/WarpStateCachePort.ts
  • test/unit/domain/RuntimeHost.snapshotCache.test.ts
  • test/unit/domain/services/controllers/CheckpointController.snapshotCache.test.ts
  • test/unit/domain/services/controllers/MaterializeController.snapshotCache.test.ts
  • test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts
  • test/unit/domain/services/controllers/MaterializeController.test.ts
  • test/unit/domain/services/controllers/MaterializeProvenancePolicy.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)
**/*.{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/controllers/MaterializeProvenancePolicy.test.ts
  • test/unit/domain/RuntimeHost.snapshotCache.test.ts
  • src/ports/WarpStateCachePort.ts
  • src/domain/services/controllers/MaterializeHelpers.ts
  • src/domain/services/controllers/MaterializeCheckpointStrategy.ts
  • src/domain/services/controllers/MaterializeCoordinateStrategy.ts
  • test/unit/domain/services/controllers/CheckpointController.snapshotCache.test.ts
  • src/domain/services/controllers/MaterializeProvenancePolicy.ts
  • src/domain/services/controllers/MaterializeStrategyRuntime.ts
  • src/domain/RuntimeHost.ts
  • test/unit/domain/services/controllers/MaterializeController.stateSession.test.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • test/unit/domain/services/controllers/MaterializeController.test.ts
  • src/domain/services/controllers/CheckpointController.ts
  • test/unit/domain/services/controllers/MaterializeController.snapshotCache.test.ts
  • src/domain/services/controllers/MaterializeSnapshotCacheResult.ts
  • src/domain/services/controllers/MaterializeController.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/WarpStateCachePort.ts
  • src/domain/services/controllers/MaterializeHelpers.ts
  • src/domain/services/controllers/MaterializeCheckpointStrategy.ts
  • src/domain/services/controllers/MaterializeCoordinateStrategy.ts
  • src/domain/services/controllers/MaterializeProvenancePolicy.ts
  • src/domain/services/controllers/MaterializeStrategyRuntime.ts
  • src/domain/RuntimeHost.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/CheckpointController.ts
  • src/domain/services/controllers/MaterializeSnapshotCacheResult.ts
  • src/domain/services/controllers/MaterializeController.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/WarpStateCachePort.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/MaterializeHelpers.ts
  • src/domain/services/controllers/MaterializeCheckpointStrategy.ts
  • src/domain/services/controllers/MaterializeCoordinateStrategy.ts
  • src/domain/services/controllers/MaterializeProvenancePolicy.ts
  • src/domain/services/controllers/MaterializeStrategyRuntime.ts
  • src/domain/RuntimeHost.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/CheckpointController.ts
  • src/domain/services/controllers/MaterializeSnapshotCacheResult.ts
  • src/domain/services/controllers/MaterializeController.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/MaterializeHelpers.ts
  • src/domain/services/controllers/MaterializeCheckpointStrategy.ts
  • src/domain/services/controllers/MaterializeCoordinateStrategy.ts
  • src/domain/services/controllers/MaterializeProvenancePolicy.ts
  • src/domain/services/controllers/MaterializeStrategyRuntime.ts
  • src/domain/RuntimeHost.ts
  • src/domain/services/controllers/MaterializeLiveStrategy.ts
  • src/domain/services/controllers/CheckpointController.ts
  • src/domain/services/controllers/MaterializeSnapshotCacheResult.ts
  • src/domain/services/controllers/MaterializeController.ts
🔇 Additional comments (17)
src/domain/services/controllers/MaterializeHelpers.ts (1)

110-118: LGTM!

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

1-58: LGTM!

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

129-139: LGTM!

Also applies to: 243-252, 291-291

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

145-145: LGTM!

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

3-3: LGTM!

Also applies to: 48-51

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

58-67: LGTM!

Also applies to: 188-217, 244-244, 253-300, 450-450, 484-484

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

1-79: LGTM!

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

20-20: LGTM!

Also applies to: 55-55, 215-228, 232-248, 254-275, 332-333, 342-346, 359-359

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

33-33: LGTM!

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

402-424: LGTM!

Also applies to: 426-446, 449-468

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

251-255: LGTM!

src/ports/WarpStateCachePort.ts (1)

15-15: LGTM!

src/domain/RuntimeHost.ts (1)

47-51: LGTM!

Also applies to: 744-746

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

29-30: LGTM!

Also applies to: 137-140, 195-210

test/unit/domain/RuntimeHost.snapshotCache.test.ts (1)

1-100: LGTM!

test/unit/domain/services/controllers/CheckpointController.snapshotCache.test.ts (1)

189-192: LGTM!

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

50-59: LGTM!

Comment thread src/domain/services/controllers/MaterializeStrategyRuntime.ts Outdated
@flyingrobots

Copy link
Copy Markdown
Member Author

Addressed both CodeRabbit findings in 4c2392e0e298: the materialization path now reuses the canonical provenance-posture type, and every installed state synchronizes or fail-closed clears its cached causal basis. Eager patch coordinates derive from the frontier paired with the cached state; sync coordinates derive from the applied response. Validation: 6,952 stable tests, 7,026 coverage tests, and 31/31 changed executable statements covered.

@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 commented Jul 15, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

@flyingrobots
flyingrobots merged commit 494d62c into main Jul 15, 2026
18 checks passed
@flyingrobots
flyingrobots deleted the v19-materialization-warm-hit branch July 15, 2026 23:42
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.

Replace RuntimeHost full state with CAS-backed materialization handles

1 participant