Skip to content

feat: add repository usage diagnostics#66

Merged
flyingrobots merged 6 commits into
mainfrom
feat/repository-usage-diagnostics
Jul 13, 2026
Merged

feat: add repository usage diagnostics#66
flyingrobots merged 6 commits into
mainfrom
feat/repository-usage-diagnostics

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Jul 13, 2026

Copy link
Copy Markdown
Member

Linked Issue

Design / Proof

  • Design doc: API-0047 application storage/cache boundary
  • Witness: repository diagnostics
  • Adds the immutable, lazily initialized cas.diagnostics.doctor() capability for repository object, reachability, and managed-storage evidence.
  • Streams Git object/ref inventories, delegates volatile inspection to plumbing's safe dry-run API, and inspects every CacheSet, RootSet, ExpiringSet, and Vault before capping only returned detail rows.
  • Exposes no object-write, ref-update, GC, or destructive prune operation; fails closed when concurrent writes invalidate inventory arithmetic; preserves privacy-vault key boundaries.
  • Documents unavoidable unknowns for shared physical bytes, packed-object age, reflog counts, alternates, and pack metadata.
  • Upgrades @git-stunts/plumbing to 3.1.0.

Validation

pnpm run release:verify
  • 13/13 verification steps passed with 6,109 tests observed across Node, Bun, and Deno before review hardening.
  • The review-hardening push passed ESLint and the complete 1,869-test Node unit gate.
  • Real-Git integration coverage proves exact object and ref inventories are unchanged.
  • npm pack and JSR publish dry-runs passed.
  • Graft reports +20 exported symbols, minor semver impact, no removed or changed exports, and no breaking changes.

Release Impact

  • Changelog updated, if release behavior changed.
  • Public docs updated, if user-facing behavior changed.
  • Issue labels/milestone reflect final disposition.
  • Additive public API; intended for the v6.2.0 minor release.

@flyingrobots flyingrobots added this to the v6.2.0 milestone Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a non-mutating repository inspection port and Git adapter, a repository-wide cas.diagnostics.doctor() API, facade wiring, structured error handling, documentation, and unit/integration coverage for reachability, usage, limits, and safe inspection.

Changes

Repository diagnostics

Layer / File(s) Summary
Inspection contract and Git adapter
index.d.ts, src/ports/RepositoryInspectionPort.js, src/infrastructure/adapters/GitRepositoryInspectionAdapter.js, package.json, src/domain/errors/Codes.js
Defines inspection types and streams validated Git object, ref, reachability, prunable-object, and physical-byte evidence without mutation.
RepositoryDoctor report construction
src/domain/services/RepositoryDoctor.js, index.d.ts
Adds policy validation, repository-wide anchored/orphaned/volatile classification, collection and vault usage summaries, bounded details, limitations, safe-integer checks, and frozen reports.
Facade capability wiring
index.js, index.d.ts
Exports diagnostics components and adds lazily initialized cas.diagnostics.doctor(options).
Behavior validation
test/unit/domain/services/RepositoryDoctor.test.js, test/unit/infrastructure/adapters/GitRepositoryInspectionAdapter.test.js, test/unit/facade/ContentAddressableStore.diagnostics.test.js, test/integration/repository-diagnostics.test.js, test/unit/types/declaration-accuracy.test.js
Covers streaming parsing, invalid output, policy rules, collection limits, privacy behavior, concurrency changes, declaration accuracy, and non-mutating real-Git diagnostics.
API and witness documentation
docs/API.md, README.md, CHANGELOG.md, docs/design/0047-application-storage-cache-boundary/...
Documents the diagnostics API, inspection port, error code, capability mapping, dependency requirement, and supporting witness evidence.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ContentAddressableStore
  participant RepositoryDoctor
  participant GitRepositoryInspectionAdapter
  Client->>ContentAddressableStore: diagnostics.doctor(options)
  ContentAddressableStore->>RepositoryDoctor: doctor(options)
  RepositoryDoctor->>GitRepositoryInspectionAdapter: stream repository evidence
  GitRepositoryInspectionAdapter-->>RepositoryDoctor: objects, refs, reachability, prunable records
  RepositoryDoctor-->>ContentAddressableStore: frozen diagnostic report
  ContentAddressableStore-->>Client: repository and usage diagnostics
Loading

Poem

I’m a rabbit with a doctor’s chart,
Counting Git roots from end to start.
No prune command, no vanished byte,
Just frozen facts in moonlit light.
Hop, hop—your refs are right!

🚥 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
Linked Issues check ✅ Passed The changes implement repository-wide reachability classification, usage diagnostics, non-mutating inspection, and bounded unknowns for [#49, #55].
Out of Scope Changes check ✅ Passed The code, docs, tests, and dependency bump all support the diagnostics work and do not introduce unrelated scope.
Title check ✅ Passed The title is concise and clearly summarizes the main change: adding repository usage diagnostics.
Description check ✅ Passed The description includes all required sections with issue links, design/witness details, validation notes, and release impact items; the validation command differs slightly from the template.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@flyingrobots

Copy link
Copy Markdown
Member Author

Self-review

Verdict: no blocking findings.

Reviewed the complete branch against #49, #55, and API-0047 for destructive Git paths, ref/reflog reachability, grace-policy semantics, concurrent repository writes, bounded residency, collection-total completeness, shared-byte attribution, Vault privacy, facade initialization, declaration/runtime parity, and cross-runtime behavior.

Key evidence:

  • The public capability is frozen and lazily initialized after ordinary registries exist. [cite: index.js#184-196@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: index.js#404-410@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  • The repository port has no mutation method, and volatile inspection delegates only to the safe plumbing API. [cite: src/ports/RepositoryInspectionPort.js#1-33@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: src/infrastructure/adapters/GitRepositoryInspectionAdapter.js#57-71@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  • Every managed collection is inspected sequentially and included in totals before detail capping. [cite: src/domain/services/RepositoryDoctor.js#108-163@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: src/domain/services/RepositoryDoctor.js#428-480@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  • The real-Git proof preserves the exact object and ref inventories. [cite: test/integration/repository-diagnostics.test.js#115-168@868cc7080513f8fed71f28dd93bb744ebdf0fc85]

Verification: pnpm run release:verify passed 13/13 steps with 6,109 tests observed across Node, Bun, and Deno; npm and JSR publish dry-runs passed. Graft reports +20 exports, minor semver impact, no removed or changed exports, and no breaking changes.

Full source witness: repository-diagnostics.md

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer review

Disposition: all identified ambiguity and adversarial cases are addressed; no blocking finding remains.

  1. Detail caps could undercount usage. All refs are inspected and aggregated before only the returned detail array is capped; coverage reports observed, inspected, and detailed counts. [cite: src/domain/services/RepositoryDoctor.js#108-134@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: src/domain/services/RepositoryDoctor.js#428-480@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  2. A doctor API could smuggle in destructive prune. The port exposes no mutator, and the adapter calls only inspectPrunableObjects(). [cite: src/ports/RepositoryInspectionPort.js#1-33@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: src/infrastructure/adapters/GitRepositoryInspectionAdapter.js#57-71@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  3. Concurrent writers could make subtraction lie. Unsafe or negative derived values make the report unhealthy, null the derived counts, and add REPOSITORY_CHANGED_DURING_INSPECTION. [cite: src/domain/services/RepositoryDoctor.js#32-42@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: src/domain/services/RepositoryDoctor.js#80-103@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  4. Deduplicated physical bytes could be double-attributed. Per-owner and split unreachable-class bytes remain null; every unavailable dimension is named in limitations. [cite: src/domain/services/RepositoryDoctor.js#90-104@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: src/domain/services/RepositoryDoctor.js#539-560@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  5. Chunked, malformed, or failed Git output could be partially trusted. The parser carries partial lines across chunks, validates every field, flushes the decoder, and checks final process status. [cite: src/infrastructure/adapters/GitRepositoryInspectionAdapter.js#103-161@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  6. A safe integer can exceed the Date range. The computed cutoff is validated before toISOString(), preserving the CAS error contract. [cite: src/domain/services/RepositoryDoctor.js#259-272@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  7. Vault diagnostics could demand privacy keys. Privacy mode reports unknown cardinality plus an explicit limitation and never calls readState(). [cite: src/domain/services/RepositoryDoctor.js#165-205@868cc7080513f8fed71f28dd93bb744ebdf0fc85]
  8. New plumbing requirements could break ordinary facade construction. Diagnostics wiring is lazy, so the adapter requirement is evaluated only when doctor is requested. [cite: index.js#184-196@868cc7080513f8fed71f28dd93bb744ebdf0fc85] [cite: index.js#404-410@868cc7080513f8fed71f28dd93bb744ebdf0fc85]

The committed witness records the complete argument and real-Git proof: repository-diagnostics.md.

@flyingrobots

Copy link
Copy Markdown
Member Author

Self-review follow-up

The final declaration-parity pass found and fixed one additive omission: runtime truncation limitations expose detailed, so RepositoryDiagnosticLimitation now declares it and the declaration-accuracy suite pins the field. [cite: index.d.ts#1094-1101@e7d44dcb1a87db4e3f1a36e5840a2d23eaaf2f20] [cite: test/unit/types/declaration-accuracy.test.js#98-105@e7d44dcb1a87db4e3f1a36e5840a2d23eaaf2f20]

Focused declaration tests and the complete 1,866-test Node unit gate passed before push.

@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/RepositoryDoctor.js`:
- Around line 136-163: Update unhealthyCollection and its callers in
`#inspectCache`, `#inspectRootSet`, and `#inspectExpiringSet` to produce kind-specific
error usage shapes matching the declared RepositoryCacheUsage,
RepositoryRootSetUsage, and RepositoryExpiringSetUsage contracts. Ensure
root-set errors omit cache-only fields, expiring-set errors omit retention and
other cache-only fields, and preserve the existing error details and
success-path helpers.

In `@src/infrastructure/adapters/GitRepositoryInspectionAdapter.js`:
- Line 6: Update the timeout used by reachablePhysicalBytes() for the full
rev-list inventory scan so it does not inherit the shared DEFAULT_POLICY
30-second limit. Assign this operation a dedicated longer timeout or use its
supported per-call override, while leaving DEFAULT_POLICY unchanged for other
operations.

In `@test/unit/infrastructure/adapters/GitRepositoryInspectionAdapter.test.js`:
- Around line 77-112: Add negative-path tests covering the validation branches
in iterateRefs and iteratePrunableObjects. Verify iterateRefs rejects streamed
lines without a refs/ prefix and iteratePrunableObjects rejects lines that do
not contain exactly two fields, asserting both failures expose code
REPOSITORY_INSPECTION_INVALID while preserving the existing successful-stream
tests.
🪄 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: e86b610f-807b-49ba-85c1-cc49f8227238

📥 Commits

Reviewing files that changed from the base of the PR and between 1f10e5c and a904cba.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • CHANGELOG.md
  • README.md
  • docs/API.md
  • docs/design/0047-application-storage-cache-boundary/application-storage-cache-boundary.md
  • docs/design/0047-application-storage-cache-boundary/witness/repository-diagnostics.md
  • index.d.ts
  • index.js
  • package.json
  • src/domain/errors/Codes.js
  • src/domain/services/RepositoryDoctor.js
  • src/infrastructure/adapters/GitRepositoryInspectionAdapter.js
  • src/ports/RepositoryInspectionPort.js
  • test/integration/repository-diagnostics.test.js
  • test/unit/domain/services/RepositoryDoctor.test.js
  • test/unit/facade/ContentAddressableStore.diagnostics.test.js
  • test/unit/infrastructure/adapters/GitRepositoryInspectionAdapter.test.js
  • test/unit/types/declaration-accuracy.test.js
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: test-docker (bun)
  • GitHub Check: test-docker (deno)
  • GitHub Check: test-docker (node)
🧰 Additional context used
📓 Path-based instructions (3)
docs/design/**

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • docs/design/0047-application-storage-cache-boundary/application-storage-cache-boundary.md
  • docs/design/0047-application-storage-cache-boundary/witness/repository-diagnostics.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/facade/ContentAddressableStore.diagnostics.test.js
  • test/integration/repository-diagnostics.test.js
  • test/unit/types/declaration-accuracy.test.js
  • test/unit/domain/services/RepositoryDoctor.test.js
  • test/unit/infrastructure/adapters/GitRepositoryInspectionAdapter.test.js
📚 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/domain/errors/Codes.js
  • src/ports/RepositoryInspectionPort.js
  • src/infrastructure/adapters/GitRepositoryInspectionAdapter.js
  • src/domain/services/RepositoryDoctor.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
🪛 ast-grep (0.44.1)
test/integration/repository-diagnostics.test.js

[warning] 4-4: 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)

🔇 Additional comments (18)
CHANGELOG.md (1)

56-61: LGTM!

Also applies to: 65-67

README.md (1)

107-107: LGTM!

Also applies to: 138-141

docs/design/0047-application-storage-cache-boundary/application-storage-cache-boundary.md (1)

803-805: LGTM!

docs/design/0047-application-storage-cache-boundary/witness/repository-diagnostics.md (1)

1-159: LGTM!

test/unit/infrastructure/adapters/GitRepositoryInspectionAdapter.test.js (2)

34-58: LGTM!

Also applies to: 60-75, 90-112


114-144: LGTM!

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

117-291: LGTM!

test/unit/facade/ContentAddressableStore.diagnostics.test.js (1)

15-48: LGTM!

test/integration/repository-diagnostics.test.js (1)

1-169: LGTM!

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

42-43: LGTM!

Also applies to: 56-58, 100-108

index.d.ts (1)

531-555: LGTM!

Also applies to: 1065-1249, 1361-1364, 1414-1414

docs/API.md (1)

20-29: LGTM!

Also applies to: 1375-1377, 1688-1750, 2641-2665, 3082-3082

src/ports/RepositoryInspectionPort.js (1)

1-34: LGTM!

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

1-163: Remaining logic in this file (constructor validation, iterateObjects, iterateReachableObjectIds, iteratePrunableObjects, iterateRefs, #stream, consumeLines, and the parseOid/parseType/parseBytes/invalidOutput helpers) is correct: git command syntax/order verified against git-cat-file/git-rev-list docs, structured-output parsing is strict and defensive, and streaming/error-propagation is consistent.

package.json (1)

101-101: LGTM!

src/domain/errors/Codes.js (1)

63-63: LGTM!

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

1-24: Remaining logic (constructor/dependency validation, doctor() composition, object/usage inventory arithmetic with fail-closed nulling, success-path usage builders, coverage/truncation accounting, options validation, and deepFreeze) is sound and matches the documented design precisely.

Also applies to: 25-69, 71-134, 208-513, 532-626, 627-635

index.js (1)

19-26: LGTM!

Also applies to: 72-75, 106-106, 194-196, 242-243, 306-320, 404-412

Comment thread src/domain/services/RepositoryDoctor.js
Comment thread src/infrastructure/adapters/GitRepositoryInspectionAdapter.js
@flyingrobots

Copy link
Copy Markdown
Member Author

Review-fix verification

All three CodeRabbit findings were valid and are fixed on the current branch:

  1. Error-path diagnostics now build kind-specific CacheSet, RootSet, and ExpiringSet usage records while preserving the original public error. [cite: `src/domain/services/RepositoryDoctor.js#136-163@6ba961ab2aefb704c2e3d9c56a71d161d67b77be`] [cite: `src/domain/services/RepositoryDoctor.js#514-550@6ba961ab2aefb704c2e3d9c56a71d161d67b77be`]
  2. Full reachable-byte scans use a dedicated five-minute default, while an explicitly supplied caller policy remains authoritative. [cite: `src/infrastructure/adapters/GitRepositoryInspectionAdapter.js#6-28@6ba961ab2aefb704c2e3d9c56a71d161d67b77be`] [cite: `src/infrastructure/adapters/GitRepositoryInspectionAdapter.js#91-95@6ba961ab2aefb704c2e3d9c56a71d161d67b77be`]
  3. Negative-path tests now pin rejection of out-of-namespace refs and malformed prunable-object records as `REPOSITORY_INSPECTION_INVALID`. [cite: `test/unit/infrastructure/adapters/GitRepositoryInspectionAdapter.test.js#114-140@6ba961ab2aefb704c2e3d9c56a71d161d67b77be`]

The hardening push passed ESLint and all 1,869 Node unit tests. CodeRabbit has recognized each fix and automatically resolved all three review threads.

@flyingrobots flyingrobots merged commit 6d222dd into main Jul 13, 2026
6 checks passed
@flyingrobots flyingrobots deleted the feat/repository-usage-diagnostics branch July 13, 2026 19:22
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.

Expose repository and cache usage diagnostics Repository-wide reachability classification for RootSet doctor

1 participant