Skip to content

feat(bundles): add bounded lazy reference reads#82

Merged
flyingrobots merged 11 commits into
mainfrom
perf/lazy-bundle-reads
Jul 18, 2026
Merged

feat(bundles): add bounded lazy reference reads#82
flyingrobots merged 11 commits into
mainfrom
perf/lazy-bundle-reads

Conversation

@flyingrobots

Copy link
Copy Markdown
Member

Summary

  • add getMemberReference() and iterateMemberReferences() for selected-path bundle access without recursive support-graph validation
  • add bounded, immutable, rejection-safe metadata and descriptor caches
  • preserve the existing complete-validation methods for callers that require recursive integrity checks
  • recover narrowly evidenced silent root-set compare-and-swap races while leaving unrelated Git failures terminal

Why

git-warp reads a small causal support slice from materialization bundles, but git-cas 6.4.0 recursively validated every nested support object. On the retained-property fixture, one selected read issued 192 Git commands and took approximately 3-5 seconds. This API gives consumers an explicit integrity/performance boundary suitable for bounded reads.

Measured impact

Posture Reads Git commands Wall time Node CPU
git-cas 6.4.0 recursive validation 1 192 approximately 3-5 s 210-234 ms
lazy reference reads plus bounded caches 1 69 1.291 s 92.065 ms
before descriptor cache 16 521 8.943 s 626.554 ms
after descriptor cache 16 309 5.173 s 397.1 ms

The stable regression contract uses Git command counts rather than host-sensitive latency thresholds.

Integrity boundary

Direct reads validate the root summary, every selected child summary, the persisted descriptor-byte budget, the direct Git edge, and the selected target's object type/existence. They intentionally do not recurse through nested target support.

[cite: src/domain/services/BundleService.js#114-155@7ddbda5d369b4c0694b1bbf337834a7fc6e776cb]
[cite: src/domain/services/BundleService.js#229-275@7ddbda5d369b4c0694b1bbf337834a7fc6e776cb]

Verification

  • pnpm run release:verify: 14/14 steps passed; 6,619 tests observed across Node, Bun, and Deno
  • guarded root-set replacement stress: 500 consecutive two-writer races passed with exactly one accepted winner each
  • immediate rejected-cache retry probe: 0 stale rejections in 10,000 iterations after repair
  • git diff --check origin/main...HEAD: passed
  • Graft export review: minor-only API addition; no removals or signature changes
  • self-review: zero unresolved findings

[cite: src/helpers/boundedPromiseCache.js#35-101@f1d219973d40bfa8a728093d39f793c3486037ad]
[cite: src/domain/services/RootSetPersistence.js#267-337@d7841acbaffbc4c5b14c78d31d3dc65ac4618cce]

Closes #81.

Related upstream diagnostic-loss defect: git-stunts/plumbing#9.

@flyingrobots

Copy link
Copy Markdown
Member Author

@codex self-code review complete.

Severity Count Result
Critical 0 None found
High 0 None found
Medium 0 None found
Low 0 None found
Markdown/style 0 Prettier and diff checks passed

Review scope: origin/main...998606c9 (20 files, 1,377 insertions, 47 deletions).

Evidence:

  • clean worktree after fetch; branch was 0 behind / 7 ahead
  • Graft structural review found no breaking changes
  • package export map exposes only ., ./service, and ./schema; the internal BoundedPromiseCache helper is not a package subpath
  • pnpm run release:verify passed 14/14 steps with 6,619 observed tests across Node, Bun, and Deno
  • real-Git integration coverage passed 192/192 on each runtime
  • 500/500 guarded two-writer root-set races passed after the narrow CAS recovery repair
  • immediate rejected-cache retry probe passed 10,000/10,000 after settlement ordering was corrected
  • git diff --check origin/main...HEAD passed

Please confirm the review posture and call out any contrary finding with file/line evidence.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 18 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

Run ID: 06b728f8-7c0a-492f-84ec-ee5de302533a

📥 Commits

Reviewing files that changed from the base of the PR and between 998606c and 3969e46.

📒 Files selected for processing (6)
  • docs/design/0050-lazy-bundle-reference-reads/witness/verification.md
  • scripts/diagnostics/stress-root-set-replacement.js
  • src/domain/services/RootSetPersistence.js
  • src/helpers/boundedPromiseCache.js
  • test/unit/domain/services/RootSetPersistence.test.js
  • test/unit/helpers/boundedPromiseCache.test.js
📝 Walkthrough

Walkthrough

The change adds direct bundle member-reference APIs, bounded coalescing caches for immutable Git and descriptor reads, stronger bundle traversal validation, and improved compare-and-swap conflict classification for root-set updates. Documentation, typings, unit tests, and real-Git performance tests are included.

Changes

Direct bundle references

Layer / File(s) Summary
Reference API contract and documentation
index.d.ts, index.js, docs/API.md, docs/design/0050-lazy-bundle-reference-reads/*, README.md, CHANGELOG.md, test/unit/types/*, test/unit/facade/*, docs/design/README.md
Adds BundleMemberReference, public lookup and iteration methods, validation-boundary documentation, and declaration/facade coverage.
Direct reference traversal and validation
src/domain/services/BundleService.js, test/unit/domain/services/BundleService.test.js
Validates bundle structure and direct Git edges while allowing reference reads to avoid recursive support-graph resolution.
Reference performance verification
test/integration/bundle-reference-performance.test.js
Counts Git operations for cold and warm direct-reference reads and compares direct iteration with complete member validation.

Bounded immutable-read caching

Layer / File(s) Summary
Bounded promise cache
src/helpers/boundedPromiseCache.js, test/unit/helpers/boundedPromiseCache.test.js, ARCHITECTURE.md, CHANGELOG.md
Adds bounded LRU-style promise coalescing with weight limits, retryable rejection handling, and coverage for eviction and invalid weights.
Git metadata cache integration
src/infrastructure/adapters/GitPersistenceAdapter.js, test/unit/infrastructure/adapters/GitPersistenceAdapter.readTree.test.js
Caches tree-entry and object metadata reads with configurable entry limits, cloning, freezing, LRU eviction, and retryable failures.
Bundle descriptor cache
src/domain/services/BundleService.js, test/unit/domain/services/BundleService.test.js
Caches descriptor blobs by object and byte limit and returns cloned descriptor data during traversal.

Observed root-set conflicts

Layer / File(s) Summary
Observed update-ref conflict classification
src/domain/services/RootSetPersistence.js, test/unit/domain/services/RootSetPersistence.test.js
Adds exact command matching and observed-head comparison for classifying empty fatal update-ref failures as root-set conflicts.

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

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant ContentAddressableStore
  participant BundleService
  participant GitPersistenceAdapter
  Caller->>ContentAddressableStore: iterateMemberReferences(options)
  ContentAddressableStore->>BundleService: iterateMemberReferences(options)
  BundleService->>GitPersistenceAdapter: read cached tree and object metadata
  GitPersistenceAdapter-->>BundleService: coalesced immutable metadata
  BundleService-->>ContentAddressableStore: direct BundleMemberReference values
  ContentAddressableStore-->>Caller: async reference stream
Loading

Possibly related PRs

  • git-stunts/git-cas#63: Earlier bundle traversal structures underpin the new descriptor caching and direct-reference validation.
  • git-stunts/git-cas#64: Both changes modify Git object metadata reads through cat-file --batch-check.
  • git-stunts/git-cas#78: Both changes extend RootSetPersistence update-ref conflict handling.

Suggested reviewers: git-stunts

Poem

I’m a rabbit with references bright,
Caching each carrot read just right.
No failed nibble stays in the den,
Direct paths hop faster than then.
Bundles bloom, conflicts clear—
Hop, hop, the new APIs are here!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change: bounded lazy bundle reference reads.
Description check ✅ Passed The description covers the summary, rationale, measurements, integrity boundary, and verification, with only minor template omissions.
Linked Issues check ✅ Passed The PR implements direct bundle reference APIs, bounded immutable caches, fail-closed validation, and real-Git tests required by #81.
Out of Scope Changes check ✅ Passed The changes stay within the issue scope, and the root-set race recovery plus docs/tests support the same bounded-read objective.

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: 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/design/0050-lazy-bundle-reference-reads/witness/verification.md`:
- Around line 109-113: The verification evidence around the pre-fix Docker
stress run and repaired 500-iteration result lacks reproducible provenance. Add
a compact provenance block or exact linked records covering Docker
image/configuration, git-warp revision, Node and pnpm versions, host, fixture
parameters, and command invocations for each result, while keeping the evidence
in the durable design verification document.

In `@src/domain/services/RootSetPersistence.js`:
- Around line 56-59: Update the observed-advance comparison in the
RootSetPersistence conflict classification to compare normalized OIDs rather
than raw strings. Use Oid’s canonical lowercase representation for both
actualHeadOid and expectedHeadOid, while preserving the existing validity and
exact-update-arguments checks.

In `@src/helpers/boundedPromiseCache.js`:
- Around line 53-64: Prevent oversized resolved entries from evicting unrelated
cache contents: in the resolution flow of BoundedPromiseCache around
`#resolvedWeight` and `#totalWeight`, remove the entry immediately when its
individual weight exceeds maxWeight before adding it to the total or calling
`#evict`. In test/unit/helpers/boundedPromiseCache.test.js lines 94-105, add
coverage that caches a small resident entry and verifies it remains cached
across repeated reads of an oversized value.

In `@test/unit/helpers/boundedPromiseCache.test.js`:
- Around line 94-105: Strengthen the test for oversized values in the bounded
cache by first creating a small resident entry, then reading the oversized
value, and finally reading the resident again. In the test around
BoundedPromiseCache, use separate factories and assert the resident factory is
called only once, confirming the oversized result does not evict existing
residents.
🪄 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: a673453d-cbf2-4d98-afe1-c0c2a582de9a

📥 Commits

Reviewing files that changed from the base of the PR and between b6cd2b3 and 998606c.

📒 Files selected for processing (20)
  • ARCHITECTURE.md
  • CHANGELOG.md
  • README.md
  • docs/API.md
  • docs/design/0050-lazy-bundle-reference-reads/lazy-bundle-reference-reads.md
  • docs/design/0050-lazy-bundle-reference-reads/witness/verification.md
  • docs/design/README.md
  • index.d.ts
  • index.js
  • src/domain/services/BundleService.js
  • src/domain/services/RootSetPersistence.js
  • src/helpers/boundedPromiseCache.js
  • src/infrastructure/adapters/GitPersistenceAdapter.js
  • test/integration/bundle-reference-performance.test.js
  • test/unit/domain/services/BundleService.test.js
  • test/unit/domain/services/RootSetPersistence.test.js
  • test/unit/facade/ContentAddressableStore.application-storage.test.js
  • test/unit/helpers/boundedPromiseCache.test.js
  • test/unit/infrastructure/adapters/GitPersistenceAdapter.readTree.test.js
  • test/unit/types/declaration-accuracy.test.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
docs/design/**

📄 CodeRabbit inference engine (AGENTS.md)

Use docs/design/ directory for durable design contracts and proof plans

Files:

  • docs/design/README.md
  • docs/design/0050-lazy-bundle-reference-reads/witness/verification.md
  • docs/design/0050-lazy-bundle-reference-reads/lazy-bundle-reference-reads.md
ARCHITECTURE.md

📄 CodeRabbit inference engine (AGENTS.md)

Use ARCHITECTURE.md as the authoritative structural reference (Facade, Domain, Ports)

Files:

  • ARCHITECTURE.md
README.md

📄 CodeRabbit inference engine (AGENTS.md)

Use README.md as the public front door, core value prop, and quick start documentation

Files:

  • README.md
CHANGELOG.md

📄 CodeRabbit inference engine (AGENTS.md)

Use CHANGELOG.md to record the historical truth of merged behavior

Files:

  • CHANGELOG.md
🧠 Learnings (3)
📚 Learning: 2026-02-28T19:21:13.982Z
Learnt from: flyingrobots
Repo: git-stunts/git-cas PR: 15
File: test/unit/domain/services/CasService.envelope.test.js:326-330
Timestamp: 2026-02-28T19:21:13.982Z
Learning: In fuzz tests for cryptographic operations, use a seeded PRNG (e.g., xorshift32) for control-flow variables such as plaintext size selection and recipient index selection to ensure reproducibility. Continue to use randomBytes() for cryptographic keys and nonces to preserve realistic randomness and avoid security anti-patterns. This guideline applies to test files that perform fuzz testing of crypto logic; implement a consistent seed setup (e.g., fixed seed in test initialization) and document the rationale to enable deterministic replays across runs.

Applied to files:

  • test/unit/types/declaration-accuracy.test.js
  • test/unit/facade/ContentAddressableStore.application-storage.test.js
  • test/unit/domain/services/BundleService.test.js
  • test/integration/bundle-reference-performance.test.js
  • test/unit/helpers/boundedPromiseCache.test.js
  • test/unit/infrastructure/adapters/GitPersistenceAdapter.readTree.test.js
  • test/unit/domain/services/RootSetPersistence.test.js
📚 Learning: 2026-03-30T19:53:48.000Z
Learnt from: flyingrobots
Repo: git-stunts/git-cas PR: 29
File: docs/design/TR-010-planning-index-consistency-review.md:121-131
Timestamp: 2026-03-30T19:53:48.000Z
Learning: In this repo, CHANGELOG.md entries should be user-facing and descriptive (bullet points) rather than cycle-ID headings (e.g., use a phrase like “Planning-index consistency review” instead of a “TR-010 — …” heading). When searching the changelog, don’t rely on grepping for cycle IDs (e.g., “TR-010”) because it may cause false negatives; search for the descriptive keywords/phrases from the bullet entries instead.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2026-07-13T17:00:46.222Z
Learnt from: flyingrobots
Repo: git-stunts/git-cas PR: 65
File: src/domain/helpers/isCanonicalCollectionKey.js:21-35
Timestamp: 2026-07-13T17:00:46.222Z
Learning: In git-stunts/git-cas, the codebase is intended to run on multiple JavaScript runtimes (Node, Bun, and Deno), not just Node. During code review, don’t suggest replacing existing portable helper logic with newer Node-only built-ins (e.g., Node 20+ APIs like `String.prototype.isWellFormed()`) unless the change preserves Bun/Deno compatibility (via portable/polyfill implementations or safe runtime gating). If a file includes manual implementations (such as `src/domain/helpers/isCanonicalCollectionKey.js`), treat them as intentional to avoid requiring a higher host built-in baseline.

Applied to files:

  • src/helpers/boundedPromiseCache.js
  • src/domain/services/BundleService.js
  • src/infrastructure/adapters/GitPersistenceAdapter.js
  • src/domain/services/RootSetPersistence.js
🪛 ast-grep (0.44.1)
test/integration/bundle-reference-performance.test.js

[warning] 9-9: 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 { spawnSync } from 'node:child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process)

🪛 LanguageTool
docs/design/0050-lazy-bundle-reference-reads/lazy-bundle-reference-reads.md

[style] ~315-~315: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ge reference from a resolved member? 3. Can it consume a manifest without materiali...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔇 Additional comments (21)
test/integration/bundle-reference-performance.test.js (1)

1-152: LGTM!

docs/design/0050-lazy-bundle-reference-reads/witness/verification.md (1)

1-108: LGTM!

Also applies to: 115-133, 155-167

index.d.ts (1)

567-571: LGTM!

Also applies to: 1463-1471, 1493-1497

index.js (1)

219-223: LGTM!

Also applies to: 493-497

docs/API.md (1)

1080-1119: LGTM!

docs/design/0050-lazy-bundle-reference-reads/lazy-bundle-reference-reads.md (1)

1-351: LGTM!

docs/design/README.md (1)

14-14: LGTM!

README.md (1)

141-142: LGTM!

CHANGELOG.md (1)

10-25: LGTM!

test/unit/types/declaration-accuracy.test.js (1)

124-136: LGTM!

test/unit/facade/ContentAddressableStore.application-storage.test.js (1)

38-40: LGTM!

src/domain/services/BundleService.js (2)

114-152: LGTM!

Also applies to: 234-234, 615-619


15-15: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Remove the duplicate DEFAULT_CLOCK declaration.

Line 15 declares the same const twice in module scope, causing a parse-time “already been declared” error and preventing every bundle API from loading.

Proposed fix
 const DEFAULT_CLOCK = Object.freeze({ now: () => new Date() });
-const DEFAULT_CLOCK = Object.freeze({ now: () => new Date() });
			> Likely an incorrect or invalid review comment.
test/unit/domain/services/BundleService.test.js (1)

266-336: LGTM!

src/domain/services/RootSetPersistence.js (1)

4-4: LGTM!

Also applies to: 15-55, 60-72, 276-280, 314-337

test/unit/domain/services/RootSetPersistence.test.js (1)

71-84: LGTM!

Also applies to: 100-125, 217-245

src/helpers/boundedPromiseCache.js (1)

1-52: LGTM!

Also applies to: 65-102

test/unit/helpers/boundedPromiseCache.test.js (1)

1-93: LGTM!

Also applies to: 106-124

src/infrastructure/adapters/GitPersistenceAdapter.js (1)

7-7: LGTM!

Also applies to: 19-22, 31-50, 157-165, 223-268

test/unit/infrastructure/adapters/GitPersistenceAdapter.readTree.test.js (1)

91-114: LGTM!

Also applies to: 147-213

ARCHITECTURE.md (1)

377-378: LGTM!

Comment thread src/domain/services/RootSetPersistence.js
Comment thread src/helpers/boundedPromiseCache.js
Comment thread test/unit/helpers/boundedPromiseCache.test.js
@flyingrobots

Copy link
Copy Markdown
Member Author

@codex follow-up self-review after CodeRabbit requested changes:

The initial zero-finding review missed three valid issues: non-canonical OID comparison, oversized-value cache eviction ordering, and incomplete benchmark provenance. All are now repaired; the fourth thread duplicated the cache regression request.

Severity Found by CodeRabbit Remaining
Critical 0 0
Major 1 behavior + 1 duplicate test thread 0
Minor 1 0
Trivial 1 0

Evidence:

  • canonical OID comparison and regression: b7695ab
  • oversized-value resident preservation and regression: b7695ab
  • checked-in 500-race harness: 4d5600c + formatting-only 684e673
  • reproducible provenance and final totals: 3969e46
  • 500/500 guarded replacement races passed
  • pnpm run release:verify passed 14/14 with 6,622 observed tests
  • pre-push lint and 2,019 Node unit tests passed
  • Graft reports no breaking exports; semver impact remains minor
  • all four review threads have evidence replies and are resolved

No further self-review findings remain. Please confirm the updated review posture against 3969e46.

@flyingrobots
flyingrobots merged commit d5f770f into main Jul 18, 2026
6 checks passed
@flyingrobots
flyingrobots deleted the perf/lazy-bundle-reads branch July 18, 2026 09:37
@flyingrobots flyingrobots mentioned this pull request Jul 18, 2026
5 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.

perf: add lazy bundle references and bounded immutable metadata reads

1 participant