Skip to content

feat: add v0.8 review truth helpers#48

Merged
flyingrobots merged 14 commits into
mainfrom
cycle/CORE_structural-test-coverage-map
May 5, 2026
Merged

feat: add v0.8 review truth helpers#48
flyingrobots merged 14 commits into
mainfrom
cycle/CORE_structural-test-coverage-map

Conversation

@flyingrobots
Copy link
Copy Markdown
Owner

@flyingrobots flyingrobots commented May 5, 2026

Summary

Stacks five v0.8 Review Truth helpers on cycle/CORE_structural-test-coverage-map:

  • Adds graft_test_coverage / graft struct test-coverage structural-reference coverage mapping.
  • Adds bounded provenance hints to git graft enhance --since using graft_blame where WARP history is available.
  • Adds graft symbol history as a timeline-first renderer over the existing provenance-backed symbol blame model.
  • Adds graft_dead_symbols / graft struct dead-symbols for removed-and-not-readded WARP history signals.
  • Adds graft review cooldown to calculate CodeRabbit review cooldown readiness from PR comments or fixtures.

User Impact

This pushes the v0.8 lane toward Review Truth: reviewers can see what changed structurally, where changed symbols came from, which removed symbols stayed gone, which exports have obvious structural test references, and whether the automated review loop is ready for another pass.

Docs

Updated README, CLI/MCP docs, CHANGELOG, the three-surface capability matrix, and the affected v0.8 backlog cards.

Validation

  • git diff --check
  • pnpm vitest run test/unit/cli/command-parser.test.ts test/unit/cli/structural-blame-render.test.ts test/unit/cli/dead-symbols-render.test.ts test/unit/operations/review-cooldown-status.test.ts tests/playback/WARP_symbol-history-timeline.test.ts tests/playback/WARP_dead-symbol-detection.test.ts tests/playback/SURFACE_review-cooldown-status.test.ts test/unit/contracts/output-schemas.test.ts test/unit/contracts/capabilities.test.ts tests/playback/0078-three-surface-capability-baseline-and-parity-matrix.test.ts
  • pnpm typecheck
  • pnpm lint
  • pnpm vitest run test/unit/cli/git-graft-enhance-model.test.ts test/unit/cli/git-graft-enhance-render.test.ts tests/playback/CORE_git-graft-enhance.test.ts test/integration/cli/git-graft-enhance-cli.test.ts
  • pnpm test (Docker isolated): 216 files / 1568 tests passing

Summary by CodeRabbit

  • New Features
    • New CLI: struct test-coverage — structural reference coverage report
    • New CLI: struct dead-symbols — detect removed/unused symbols
    • New CLI: review cooldown — shows CodeRabbit review rate-limit status
    • symbol history expanded (accepts history alias) with richer timeline view
    • Graft enhance now surfaces provenance hints for symbol changes
    • Added GraphQL and Python outline extraction and coverage support

@flyingrobots flyingrobots marked this pull request as ready for review May 5, 2026 16:01
@flyingrobots
Copy link
Copy Markdown
Owner Author

@coderabbitai review please 🥕

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@flyingrobots: Sure! Starting a review of PR #48 now. 🥕

[review]

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Warning

Rate limit exceeded

@flyingrobots has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 35 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: de54423d-f179-4d91-91ed-6b9a4971156c

📥 Commits

Reviewing files that changed from the base of the PR and between 2cafd0c and f99d4a6.

⛔ Files ignored due to path filters (6)
  • CHANGELOG.md is excluded by !**/*.md
  • README.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_go-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_json-structured-config.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_toml-structured-config.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_yaml-structured-config.md is excluded by !**/*.md
📒 Files selected for processing (23)
  • src/operations/review-cooldown-status.ts
  • src/operations/structural-review.ts
  • src/operations/structural-test-coverage-map.ts
  • src/parser/extractors/go.ts
  • src/parser/extractors/index.ts
  • src/parser/extractors/json.ts
  • src/parser/extractors/toml.ts
  • src/parser/extractors/yaml.ts
  • src/parser/lang.ts
  • src/parser/runtime.ts
  • src/parser/types.ts
  • src/ports/semantic-enrichment.ts
  • test/fixtures/go/agent_service.go
  • test/fixtures/json/package-config.json
  • test/fixtures/toml/Cargo.toml
  • test/fixtures/toml/pyproject.toml
  • test/fixtures/yaml/github-actions.yml
  • test/unit/library/index.test.ts
  • test/unit/operations/review-cooldown-status.test.ts
  • test/unit/operations/structural-test-coverage-map.test.ts
  • test/unit/parser/lang.test.ts
  • test/unit/parser/outline.test.ts
  • test/unit/warp/index-head.test.ts
📝 Walkthrough

Walkthrough

Adds structural CLI commands (test-coverage, dead-symbols, symbol history, review cooldown), corresponding MCP tools and schemas, structural parsing for GraphQL/Python, provenance-hint collection in git-graft-enhance, renderers, operations for coverage and cooldown, and comprehensive unit/playback tests.

Changes

Multi-Feature CLI and MCP Expansion

Layer / File(s) Summary
Data Shape & Contracts
src/contracts/capabilities.ts, src/contracts/output-schema-mcp.ts, src/contracts/output-schema-cli.ts, src/contracts/output-schemas.ts
Added CLI commands (struct_test_coverage, struct_dead_symbols, review_cooldown) and MCP tool names (graft_test_coverage, graft_dead_symbols); reshaped graft_blame; added graft_test_coverage / graft_dead_symbols MCP schemas; added reviewCooldownBodySchema; appended provenanceHints to git_graft_enhance schema.
Core Operations / Models
src/operations/structural-test-coverage-map.ts, src/operations/review-cooldown-status.ts, src/cli/git-graft-enhance-model.ts
Implemented structuralTestCoverageMap (reference-based coverage), reviewCooldownStatus (compute cooldown from comments), extended git-graft-enhance model/types to carry provenance hints and added candidate collection helper.
MCP Tool Implementations
src/mcp/tools/structural-test-coverage.ts, src/mcp/tools/dead-symbols.ts
Added MCP tools graft_test_coverage and graft_dead_symbols that run coverage/dead-symbol analysis and return structured payloads with footprints.
Runtime / Parser Extensions
src/parser/runtime.ts, src/parser/extractors/*, src/parser/lang.ts, src/parser/types.ts, src/ports/semantic-enrichment.ts
Loaded GraphQL and Python Tree-sitter grammars; added GraphqlExtractor and PythonExtractor; extended supported language lists and EntryKind/semantic language unions.
CLI Parsing & Dispatch
src/cli/command-parser.ts, src/cli/main.ts, src/cli/cli-error.ts
Extended parseStructCommand for test-coverage/dead-symbols; added parseReviewCooldownCommand; routed review cooldown to new handler; updated help/usage messages.
Rendering Modules & Peer Handling
src/cli/structural-test-coverage-render.ts, src/cli/dead-symbols-render.ts, src/cli/structural-blame-render.ts, src/cli/review-cooldown.ts, src/cli/git-graft-enhance-render.ts, src/cli/peer-command.ts
Added renderers for coverage, dead symbols, blame history, and review cooldown; git-graft-enhance renderer now prints provenance hints; emitPeerCommand dispatches new renderers.
Provenance Hint Collection & Wiring
src/cli/git-graft-enhance.ts
Collects provenance candidates from structural diffs, invokes graft_blame per candidate, maps responses into provenanceHints, and passes them into model builder.
Tool Registry / Metadata
src/mcp/tool-registry.ts, src/mcp/burden.ts, src/operations/projection-safety.ts
Registered new tools in registry, classified their burden as search, and marked them in projection-safety question class as structure.
Tests & Fixtures
test/unit/**, tests/playback/**, test/fixtures/**, test/unit/parser/outline.test.ts
Added/updated unit and playback tests for command parsing, renderers, coverage map, dead-symbols, symbol history, review cooldown, parser extractors, capability baselines, and schema validations; added GraphQL and Python fixtures.
Misc / deps
package.json
Added runtime dependency tree-sitter-graphql-grammar-wasm.

Sequence Diagram(s)

sequenceDiagram
    participant User as User / CLI
    participant CLI as Command Parser
    participant Op as Operation / Tool Logic
    participant MCP as MCP Tool
    participant WARP as WARP Index / Git
    participant FS as File System
    participant Render as Renderer

    User->>CLI: struct test-coverage --src src --tests test
    CLI->>Op: structuralTestCoverageMap(opts)
    Op->>FS: read source/test files, parse outlines
    Op->>MCP: (local search) run rg/grep via ProcessRunner
    Op->>Op: aggregate per-symbol refs -> covered/uncovered
    Op-->>Render: StructuralTestCoverageMapResult
    Render-->>User: human-readable or JSON output

    User->>CLI: struct dead-symbols --limit 100
    CLI->>MCP: invoke graft_dead_symbols(maxCommits)
    MCP->>WARP: findDeadSymbols(warp, maxCommits)
    WARP-->>MCP: removed symbols
    MCP-->>Render: structured response
    Render-->>User: dead-symbols report

    User->>CLI: review cooldown --comments-file comments.json --now T
    CLI->>Op: load comments, reviewCooldownStatus(comments, now)
    Op->>Op: parse markers, compute expiry/remaining/status
    Op-->>Render: ReviewCooldownStatus
    Render-->>User: human-readable or JSON cooldown status

    User->>CLI: git-graft-enhance ...
    CLI->>Op: collect provenance candidates
    Op->>MCP: invoke graft_blame per candidate
    MCP-->>Op: blame histories
    Op->>Op: build provenanceHints, pass to model
    Op-->>Render: enhanced graft model output
    Render-->>User: enhanced report with provenance hints
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 I hopped through files, parsed each name,
Found covered hops and ghosts of fame.
Dead symbols traced, timelines unfurled,
Cooldown clocks told when to re-enter the world.
With hints and maps, the rabbit smiles—code tidy for miles.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cycle/CORE_structural-test-coverage-map

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d3ca4fa25

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/operations/structural-test-coverage-map.ts
@flyingrobots
Copy link
Copy Markdown
Owner Author

Issue Reviewer Resolution SHA
src/operations/structural-test-coverage-map.ts could throw when git ls-files returned tracked test files deleted from the working tree and rg exited with missing-path status. Codex Review Added a regression that deletes a tracked test file after commit; filtered candidate test paths through the filesystem port before reference search so missing tests are skipped and symbols degrade to uncovered. 308a90b

Validation: pnpm vitest run test/unit/operations/structural-test-coverage-map.test.ts tests/playback/CORE_structural-test-coverage-map.test.ts, pnpm typecheck, pnpm lint, git diff --check, and Docker-isolated pnpm test (216 files / 1569 tests).

@flyingrobots
Copy link
Copy Markdown
Owner Author

@coderabbitai review please 🥕

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@flyingrobots: Sure! Starting a review of PR #48 now. 🥕

[review]

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (6)
src/contracts/output-schema-mcp.ts (1)

409-415: 💤 Low value

Consider constraining tick to an integer.

tick: z.number() accepts floats, but a tick is a discrete ordinal position in commit history — floats are semantically meaningless here. z.number().int().nonnegative() would match the field's intent exactly.

♻️ Proposed fix
-      tick: z.number(),
+      tick: z.number().int().nonnegative(),
🤖 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/contracts/output-schema-mcp.ts` around lines 409 - 415, The history
array's object schema currently uses tick: z.number(), which allows floats;
update the tick property in the history schema (the z.object(...) inside
history: z.array(...).strict()) to z.number().int().nonnegative() so ticks are
constrained to non-negative integers; keep the surrounding schema and .strict()
unchanged.
test/unit/cli/structural-blame-render.test.ts (1)

4-39: ⚡ Quick win

Add a test case for the empty-history branch.

The else branch in renderStructuralBlame (when model.history.length === 0) is a completely distinct, reachable code path that currently has no unit coverage. The renderer outputs a specific "unavailable" sentinel line in this case.

🧪 Suggested additional test case
+  it("renders 'unavailable' timeline when history is empty", () => {
+    const rendered = renderStructuralBlame({
+      symbol: "deletedFn",
+      filePath: "src/lib.ts",
+      changeCount: 0,
+      createdInCommit: null,
+      lastSignatureChange: null,
+      referenceCount: 0,
+      history: [],
+    });
+
+    expect(rendered).toContain("Graft Symbol History");
+    expect(rendered).toContain("created: unknown");
+    expect(rendered).toContain("last signature change: none");
+    expect(rendered).toContain("- unavailable: symbol was not found in the indexed WARP graph");
+  });
🤖 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 `@test/unit/cli/structural-blame-render.test.ts` around lines 4 - 39, Add a
unit test that calls renderStructuralBlame with a symbol-blame model whose
history is an empty array (e.g., same shape as in existing test but history: []
and counts as appropriate) to cover the else branch where model.history.length
=== 0; assert the rendered output contains the specific "unavailable" sentinel
line the renderer emits for empty history (and other key header fields like
symbol and path) so the empty-history code path in renderStructuralBlame is
covered.
src/cli/structural-test-coverage-render.ts (1)

4-8: 💤 Low value

Prefer z.strictObject() over .extend().strict() in Zod v4.

In Zod v4, .strict() and .passthrough() still work, but the preferred approach is to use the top-level constructors z.strictObject({...}) and z.looseObject({...}) when defining new schemas. The Zod v4 docs also note that after calling .extend(), you can change the strictness level of the resulting schema by using z.strictObject() or z.looseObject() — meaning spread-based construction is the idiomatic path.

♻️ Idiomatic Zod v4 equivalent
-const structuralTestCoverageRenderSchema = mcpOutputBodySchemas.graft_test_coverage.extend({
-  _schema: z.unknown().optional(),
-  _receipt: z.unknown().optional(),
-  tripwire: z.unknown().optional(),
-}).strict();
+const structuralTestCoverageRenderSchema = z.strictObject({
+  ...mcpOutputBodySchemas.graft_test_coverage.shape,
+  _schema: z.unknown().optional(),
+  _receipt: z.unknown().optional(),
+  tripwire: z.unknown().optional(),
+});
🤖 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/cli/structural-test-coverage-render.ts` around lines 4 - 8, Replace the
current use of mcpOutputBodySchemas.graft_test_coverage.extend(...).strict() by
constructing a strict object via z.strictObject(...) that merges the original
graft_test_coverage shape with the additional keys; specifically, build
structuralTestCoverageRenderSchema using z.strictObject({
...mcpOutputBodySchemas.graft_test_coverage.shape, _schema:
z.unknown().optional(), _receipt: z.unknown().optional(), tripwire:
z.unknown().optional() }) (referencing structuralTestCoverageRenderSchema and
mcpOutputBodySchemas.graft_test_coverage to locate the code).
src/operations/structural-test-coverage-map.ts (1)

228-287: 🏗️ Heavy lift

Serial synchronous subprocess per symbol is a linear event-loop bottleneck.

runReferenceSearch is synchronous and called once per exported symbol inside the sequential for loop (line 321). For a project with 100 exported symbols this spawns 100 blocking rg subprocesses one after another, while the enclosing structuralTestCoverageMap is async and runs inside an MCP tool handler that is supposed to yield the event loop.

A significantly cheaper path is a single rg invocation with one -e flag per symbol, then group results by symbol name:

♻️ Sketch: batch all symbols in a single rg pass
-for (const sourceFile of sourceFiles) {
-  const symbols: StructuralTestCoverageSymbol[] = [];
-  for (const symbol of sourceFile.symbols) {
-    const refs = runReferenceSearch(opts.cwd, opts.process, symbol.name, codeTestFiles);
-    ...
-  }
-}
+// Collect every unique symbol name across all source files
+const allSymbolNames = [...new Set(
+  sourceFiles.flatMap((f) => f.symbols.map((s) => s.name))
+)];
+
+// Single rg run: one -e per symbol
+const batchArgs = [
+  "--no-heading", "--line-number", "--with-filename", "-F", "--color", "never",
+  ...allSymbolNames.flatMap((name) => ["-e", name]),
+  "--", ...codeTestFiles,
+];
+const batchResult = opts.process.run({
+  command: "rg",
+  args: batchArgs,
+  cwd: opts.cwd,
+  timeoutMs: REFERENCE_SEARCH_TIMEOUT_MS,
+  maxBufferBytes: REFERENCE_SEARCH_MAX_BUFFER_BYTES,
+});
+// parse batchResult.stdout and bucket lines by matched symbol name

Alternatively, expose an async variant of runReferenceSearch and fan out with Promise.all if the ProcessRunner supports concurrent execution.

Also applies to: 318-338

🤖 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/operations/structural-test-coverage-map.ts` around lines 228 - 287,
runReferenceSearch currently runs a blocking ripgrep/grep subprocess per symbol
(function runReferenceSearch) which serializes calls and blocks the event loop;
refactor by either (A) batching symbols into a single ripgrep invocation (build
one rg command with multiple -e <symbol> patterns created from the array of
symbols passed in, parse stdout and group matches by symbol to return
ReferenceSearchResult per symbol) or (B) convert runReferenceSearch to an async
variant and call it concurrently (change signature of runReferenceSearch to
async, use the ProcessRunner's non-blocking run API or spawn/promisified
execution, then fan out Promise.all for all symbols from
structuralTestCoverageMap) and apply the same approach to the grep fallback;
ensure you update parseMatchedFiles/countSearchLines usage to support grouped
results and preserve the same return shape for each symbol.
test/unit/cli/git-graft-enhance-render.test.ts (1)

34-60: ⚡ Quick win

Add coverage for non-empty provenance hint rendering.

The new renderer path (model.provenanceHints.length > 0) is currently untested. A focused assertion for both available and unavailable entries would harden this feature.

Suggested test addition
 describe("cli: git graft enhance renderer", () => {
+  it("renders provenance hints when present", () => {
+    const rendered = renderGitGraftEnhance({
+      ...model(),
+      provenanceHints: [
+        {
+          symbol: "updateUser",
+          filePath: "src/api.ts",
+          changeKind: "changed",
+          ambiguous: true,
+          status: "available",
+          createdInCommit: "abc123",
+          lastSignatureChange: "def456",
+          referenceCount: 2,
+          changeCount: 3,
+        },
+        {
+          symbol: "legacyUser",
+          filePath: "src/old.ts",
+          changeKind: "removed",
+          ambiguous: false,
+          status: "unavailable",
+          reason: "not_indexed_or_not_found",
+        },
+      ],
+    });
+
+    expect(rendered).toContain("Provenance hints");
+    expect(rendered).toContain("src/api.ts: updateUser changed");
+    expect(rendered).toContain("ambiguous symbol name");
+    expect(rendered).toContain("src/old.ts: legacyUser removed unavailable (not_indexed_or_not_found)");
+  });
+
   it("renders a deterministic human review summary from the model only", () => {
🤖 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 `@test/unit/cli/git-graft-enhance-render.test.ts` around lines 34 - 60, Add a
unit test calling renderGitGraftEnhance with a model prepared by model() but
with provenanceHints populated (e.g. one hint with name/path and metadata
present, and another hint marked unavailable or missing fields) to exercise the
model.provenanceHints.length > 0 path; assert the rendered output contains the
provenance heading (e.g. "provenance:"), the available hint's identifying text
(name/path or URL), and a clear marker for unavailable entries (e.g.
"unavailable" or "not found") so both present and missing-provenance cases are
validated; place this alongside the existing tests that call
renderGitGraftEnhance and reference model() and renderGitGraftEnhance to locate
where to add the new it(...) block.
test/unit/cli/git-graft-enhance-model.test.ts (1)

107-168: ⚡ Quick win

Test intent and assertion scope are mismatched.

This case is named as candidate-selection/ambiguity logic, but it only verifies passthrough of provenanceHints into the model. Please split this into (1) passthrough test and (2) direct collector-behavior test so ambiguity/limit logic is actually exercised.

Proposed test refactor
-import { buildGitGraftEnhanceModel } from "../../../src/cli/git-graft-enhance-model.js";
+import {
+  buildGitGraftEnhanceModel,
+  collectGitGraftEnhanceProvenanceCandidates,
+} from "../../../src/cli/git-graft-enhance-model.js";

-it("selects bounded provenance candidates and marks duplicate symbol names ambiguous", () => {
+it("passes provenance hints through the model unchanged", () => {
   const model = buildGitGraftEnhanceModel({
     // existing fixture...
   });

   expect(model.provenanceHints).toEqual([
     expect.objectContaining({
       symbol: "shared",
       filePath: "src/a.ts",
       ambiguous: true,
       status: "available",
     }),
   ]);
 });

+it("collects provenance candidates with ambiguity marking and limit", () => {
+  const candidates = collectGitGraftEnhanceProvenanceCandidates({
+    base: "HEAD~1",
+    head: "HEAD",
+    summary: "changed",
+    layer: "ref_view",
+    files: [
+      {
+        path: "src/a.ts",
+        status: "modified",
+        summary: "src/a.ts | modified | ~1 changed",
+        diff: { added: [], removed: [], changed: [{ name: "shared" }], unchangedCount: 0 },
+      },
+      {
+        path: "src/b.ts",
+        status: "modified",
+        summary: "src/b.ts | modified | -1 removed",
+        diff: { added: [], removed: [{ name: "shared" }], changed: [], unchangedCount: 0 },
+      },
+    ],
+  }, 1);
+
+  expect(candidates).toHaveLength(1);
+  expect(candidates[0]).toEqual(expect.objectContaining({
+    symbol: "shared",
+    ambiguous: true,
+  }));
+});
🤖 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 `@test/unit/cli/git-graft-enhance-model.test.ts` around lines 107 - 168, The
test currently only verifies passthrough of provenanceHints via
buildGitGraftEnhanceModel but is named to exercise candidate-selection/ambiguity
logic; split it into two tests: (1) a simple passthrough test that constructs
the model with provenanceHints and asserts model.provenanceHints contains the
expected object (keep the existing expect block), and (2) a direct
collector-behavior test that calls the actual collector/selection function used
by buildGitGraftEnhanceModel (locate the collector or selection helper used
inside that function) with representative file diffs and symbols to assert
bounded-candidate selection and that duplicate symbol names are marked
ambiguous; ensure you reference the same symbols ("shared", file paths like
"src/a.ts"/"src/b.ts") and assert the collector output (not just
model.provenanceHints) for ambiguity and candidate limits.
🤖 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/operations/review-cooldown-status.ts`:
- Around line 66-68: isCodeRabbitComment currently treats undefined authors as
CodeRabbit; change it to require an explicit author match by returning
CODERABBIT_AUTHOR_PATTERN.test(comment.author) only when comment.author is
defined (i.e., return false if author is undefined). For opt-in flexibility, add
an optional parameter (e.g., trustUnknown: boolean = false) to
isCodeRabbitComment so callers can opt into the previous behavior; update
callers of isCodeRabbitComment and any tests to pass trustUnknown where
fixture-driven paths intentionally omit author. Ensure references:
isCodeRabbitComment, ReviewCooldownComment, and CODERABBIT_AUTHOR_PATTERN.

---

Nitpick comments:
In `@src/cli/structural-test-coverage-render.ts`:
- Around line 4-8: Replace the current use of
mcpOutputBodySchemas.graft_test_coverage.extend(...).strict() by constructing a
strict object via z.strictObject(...) that merges the original
graft_test_coverage shape with the additional keys; specifically, build
structuralTestCoverageRenderSchema using z.strictObject({
...mcpOutputBodySchemas.graft_test_coverage.shape, _schema:
z.unknown().optional(), _receipt: z.unknown().optional(), tripwire:
z.unknown().optional() }) (referencing structuralTestCoverageRenderSchema and
mcpOutputBodySchemas.graft_test_coverage to locate the code).

In `@src/contracts/output-schema-mcp.ts`:
- Around line 409-415: The history array's object schema currently uses tick:
z.number(), which allows floats; update the tick property in the history schema
(the z.object(...) inside history: z.array(...).strict()) to
z.number().int().nonnegative() so ticks are constrained to non-negative
integers; keep the surrounding schema and .strict() unchanged.

In `@src/operations/structural-test-coverage-map.ts`:
- Around line 228-287: runReferenceSearch currently runs a blocking ripgrep/grep
subprocess per symbol (function runReferenceSearch) which serializes calls and
blocks the event loop; refactor by either (A) batching symbols into a single
ripgrep invocation (build one rg command with multiple -e <symbol> patterns
created from the array of symbols passed in, parse stdout and group matches by
symbol to return ReferenceSearchResult per symbol) or (B) convert
runReferenceSearch to an async variant and call it concurrently (change
signature of runReferenceSearch to async, use the ProcessRunner's non-blocking
run API or spawn/promisified execution, then fan out Promise.all for all symbols
from structuralTestCoverageMap) and apply the same approach to the grep
fallback; ensure you update parseMatchedFiles/countSearchLines usage to support
grouped results and preserve the same return shape for each symbol.

In `@test/unit/cli/git-graft-enhance-model.test.ts`:
- Around line 107-168: The test currently only verifies passthrough of
provenanceHints via buildGitGraftEnhanceModel but is named to exercise
candidate-selection/ambiguity logic; split it into two tests: (1) a simple
passthrough test that constructs the model with provenanceHints and asserts
model.provenanceHints contains the expected object (keep the existing expect
block), and (2) a direct collector-behavior test that calls the actual
collector/selection function used by buildGitGraftEnhanceModel (locate the
collector or selection helper used inside that function) with representative
file diffs and symbols to assert bounded-candidate selection and that duplicate
symbol names are marked ambiguous; ensure you reference the same symbols
("shared", file paths like "src/a.ts"/"src/b.ts") and assert the collector
output (not just model.provenanceHints) for ambiguity and candidate limits.

In `@test/unit/cli/git-graft-enhance-render.test.ts`:
- Around line 34-60: Add a unit test calling renderGitGraftEnhance with a model
prepared by model() but with provenanceHints populated (e.g. one hint with
name/path and metadata present, and another hint marked unavailable or missing
fields) to exercise the model.provenanceHints.length > 0 path; assert the
rendered output contains the provenance heading (e.g. "provenance:"), the
available hint's identifying text (name/path or URL), and a clear marker for
unavailable entries (e.g. "unavailable" or "not found") so both present and
missing-provenance cases are validated; place this alongside the existing tests
that call renderGitGraftEnhance and reference model() and renderGitGraftEnhance
to locate where to add the new it(...) block.

In `@test/unit/cli/structural-blame-render.test.ts`:
- Around line 4-39: Add a unit test that calls renderStructuralBlame with a
symbol-blame model whose history is an empty array (e.g., same shape as in
existing test but history: [] and counts as appropriate) to cover the else
branch where model.history.length === 0; assert the rendered output contains the
specific "unavailable" sentinel line the renderer emits for empty history (and
other key header fields like symbol and path) so the empty-history code path in
renderStructuralBlame is covered.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ee022c6e-96d0-4dd4-812c-d34d7f29d109

📥 Commits

Reviewing files that changed from the base of the PR and between 16fb182 and 2d3ca4f.

⛔ Files ignored due to path filters (11)
  • CHANGELOG.md is excluded by !**/*.md
  • README.md is excluded by !**/*.md
  • docs/CLI.md is excluded by !**/*.md
  • docs/MCP.md is excluded by !**/*.md
  • docs/design/CORE_structural-test-coverage-map.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_structural-test-coverage-map.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/SURFACE_git-graft-enhance-provenance-hints.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/SURFACE_review-cooldown-status.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/WARP_dead-symbol-detection.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/WARP_symbol-history-timeline.md is excluded by !**/*.md
  • docs/three-surface-capability-matrix.md is excluded by !**/*.md
📒 Files selected for processing (37)
  • src/cli/cli-error.ts
  • src/cli/command-parser.ts
  • src/cli/dead-symbols-render.ts
  • src/cli/git-graft-enhance-model.ts
  • src/cli/git-graft-enhance-render.ts
  • src/cli/git-graft-enhance.ts
  • src/cli/main.ts
  • src/cli/peer-command.ts
  • src/cli/review-cooldown.ts
  • src/cli/structural-blame-render.ts
  • src/cli/structural-test-coverage-render.ts
  • src/contracts/capabilities.ts
  • src/contracts/output-schema-cli.ts
  • src/contracts/output-schema-mcp.ts
  • src/contracts/output-schemas.ts
  • src/mcp/burden.ts
  • src/mcp/tool-registry.ts
  • src/mcp/tools/dead-symbols.ts
  • src/mcp/tools/structural-test-coverage.ts
  • src/operations/projection-safety.ts
  • src/operations/review-cooldown-status.ts
  • src/operations/structural-test-coverage-map.ts
  • test/unit/cli/command-parser.test.ts
  • test/unit/cli/dead-symbols-render.test.ts
  • test/unit/cli/git-graft-enhance-model.test.ts
  • test/unit/cli/git-graft-enhance-render.test.ts
  • test/unit/cli/structural-blame-render.test.ts
  • test/unit/cli/structural-test-coverage-render.test.ts
  • test/unit/contracts/capabilities.test.ts
  • test/unit/contracts/output-schemas.test.ts
  • test/unit/operations/review-cooldown-status.test.ts
  • test/unit/operations/structural-test-coverage-map.test.ts
  • tests/playback/0078-three-surface-capability-baseline-and-parity-matrix.test.ts
  • tests/playback/CORE_structural-test-coverage-map.test.ts
  • tests/playback/SURFACE_review-cooldown-status.test.ts
  • tests/playback/WARP_dead-symbol-detection.test.ts
  • tests/playback/WARP_symbol-history-timeline.test.ts

Comment thread src/operations/review-cooldown-status.ts Outdated
@flyingrobots
Copy link
Copy Markdown
Owner Author

Review feedback resolution summary:

Issue Source Outcome SHA
Deleted tracked test files made structural test coverage fail during rg search Codex inline thread Skips missing test files before reference search; added deleted-test regression 308a90b
Unauthored CodeRabbit cooldown marker was trusted CodeRabbit inline thread Requires explicit CodeRabbit author by default; added unauthored-marker regression 6f690ed
graft_blame.history[].tick allowed floats CodeRabbit nitpick Tightened MCP schema tick to non-negative integer in both schema registries 6f690ed
Empty structural-blame history branch lacked test coverage CodeRabbit nitpick Added renderer test for unavailable empty-history sentinel 6f690ed
Structural coverage renderer used .extend(...).strict() CodeRabbit nitpick Switched to direct z.strictObject schema construction 6f690ed
Structural test coverage spawned one sync search per symbol CodeRabbit nitpick Batched all symbol patterns into one rg/grep pass and added batching regression 6f690ed
Git enhance provenance renderer/model tests were incomplete CodeRabbit nitpicks Added non-empty provenance rendering coverage and split passthrough vs collector tests 6f690ed
Docker full-suite playback timeout was marginal under load Local validation gate Added explicit timeout for temp-repo git-enhance playback cases 6f690ed
Feedback fixes needed changelog entry Workflow cleanup Added Unreleased fixed note; no version bump because package remains v0.7.1 eae9720

Validation after eae9720: targeted Vitest suites, pnpm typecheck, pnpm lint, git diff --check, and Docker-isolated pnpm test (216 files / 1574 tests) all passed.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
test/unit/operations/structural-test-coverage-map.test.ts (1)

55-186: ⚡ Quick win

Add regressions for symbol-name collision cases.

Great coverage additions. One gap remains: there’s no test for foo vs foobar (substring collision) or same export name in different source files. Adding these would lock in correctness of coverage attribution.

🤖 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 `@test/unit/operations/structural-test-coverage-map.test.ts` around lines 55 -
186, Add two new unit tests to this suite that exercise symbol-name collisions:
one where one file exports "foo" and another exports "foobar" to ensure
structuralTestCoverageMap only marks the intended "foo" as referenced when tests
reference "foo" (use createTestRepo, write files under src and test similar to
writeCoverageScenario, call structuralTestCoverageMap and assert per-file symbol
statuses and totals), and another where two different source files export the
same name (e.g., both export "sharedApi") to verify references are attributed to
the correct source file (create both src files, create a test that references
only one, then assert that the referenced file shows covered status and the
other remains uncovered). Ensure tests also cover batching behavior (use
RecordingReferenceSearchRunner) and that totals reflect distinct exportedSymbols
and covered/uncovered counts.
🤖 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/operations/review-cooldown-status.ts`:
- Around line 77-87: The current filtering/sorting of markerComments silently
treats timestamp === null as 0 so untimestamped markers are ignored; change the
logic in the marker collection (the block that builds markerComments using
isCodeRabbitComment, RATE_LIMIT_PATTERN, timestampForComment, and
durationMsFromBody) to first detect any marker with timestamp === null and, if
any exist, immediately return the "unknown" status (or otherwise surface
ambiguity) instead of continuing to sort; ensure the same guard is added to the
equivalent logic later (the similar block around the code that computes latest
and uses latest.timestamp/durationMs) so untimestamped markers no longer get
treated as older than timestamped ones.

In `@src/operations/structural-test-coverage-map.ts`:
- Around line 364-376: The current coverage lookup uses only symbol.name (built
into symbolNames and read from referenceResults returned by
runReferenceSearches), which conflates same-named exports across files; change
the keying to a disambiguated identifier (e.g., combine sourceFile path/module
with symbol.name such as `${sourceFile.path}::${symbol.name}` or an export
unique id) when building the symbolNames array passed into runReferenceSearches
and when later looking up refs for each symbol in the loop (replace
referenceResults.get(symbol.name) with referenceResults.get(disambiguatedKey)).
Update any types or StructuralTestCoverageSymbol/StructuralTestCoverageFile
population to map back to the original name and file so coverage still reports
per-file symbols.
- Around line 267-273: The current loop uses string.includes(line.content) which
can falsely match when one symbol is a substring of another; replace that
substring check with an identifier-boundary regex: create or reuse an
escapeRegExp helper to safely escape symbolName, then build a RegExp like new
RegExp(`(?<![A-Za-z0-9_$])${escapedName}(?![A-Za-z0-9_$])`) and use
regex.test(line.content) instead of includes; update the existing loop over
parseMatchedReferenceLines(stdout) / symbolNames and keep the same counts.set
and fileSets.get(symbolName)?.add(line.filePath) logic when the regex matches.

---

Nitpick comments:
In `@test/unit/operations/structural-test-coverage-map.test.ts`:
- Around line 55-186: Add two new unit tests to this suite that exercise
symbol-name collisions: one where one file exports "foo" and another exports
"foobar" to ensure structuralTestCoverageMap only marks the intended "foo" as
referenced when tests reference "foo" (use createTestRepo, write files under src
and test similar to writeCoverageScenario, call structuralTestCoverageMap and
assert per-file symbol statuses and totals), and another where two different
source files export the same name (e.g., both export "sharedApi") to verify
references are attributed to the correct source file (create both src files,
create a test that references only one, then assert that the referenced file
shows covered status and the other remains uncovered). Ensure tests also cover
batching behavior (use RecordingReferenceSearchRunner) and that totals reflect
distinct exportedSymbols and covered/uncovered counts.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 21ea1c1a-b0db-4e8c-8794-a792851f909f

📥 Commits

Reviewing files that changed from the base of the PR and between 2d3ca4f and 2cafd0c.

⛔ Files ignored due to path filters (24)
  • CHANGELOG.md is excluded by !**/*.md
  • README.md is excluded by !**/*.md
  • docs/method/backlog/dependency-dag.dot is excluded by !**/*.dot
  • docs/method/backlog/dependency-dag.svg is excluded by !**/*.svg
  • docs/method/backlog/v0.8.0/CORE_c-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_cpp-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_csharp-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_go-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_hcl-structured-config.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_java-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_json-structured-config.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_jupyter-notebook-structure.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_kotlin-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_php-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_python-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_ruby-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_shell-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_sql-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_swift-structural-parsing.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_toml-structured-config.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/CORE_yaml-structured-config.md is excluded by !**/*.md
  • docs/method/backlog/v0.8.0/README.md is excluded by !**/*.md
  • docs/public-api.md is excluded by !**/*.md
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • package.json
  • src/cli/structural-test-coverage-render.ts
  • src/contracts/output-schema-mcp.ts
  • src/contracts/output-schemas.ts
  • src/operations/review-cooldown-status.ts
  • src/operations/structural-test-coverage-map.ts
  • src/parser/extractors/graphql.ts
  • src/parser/extractors/index.ts
  • src/parser/extractors/python.ts
  • src/parser/lang.ts
  • src/parser/runtime.ts
  • src/parser/types.ts
  • src/ports/semantic-enrichment.ts
  • test/fixtures/graphql/continuum-runtime-boundary-family.graphql
  • test/fixtures/python/agent_service.py
  • test/unit/cli/git-graft-enhance-model.test.ts
  • test/unit/cli/git-graft-enhance-render.test.ts
  • test/unit/cli/structural-blame-render.test.ts
  • test/unit/operations/review-cooldown-status.test.ts
  • test/unit/operations/structural-test-coverage-map.test.ts
  • test/unit/parser/lang.test.ts
  • test/unit/parser/outline.test.ts
  • tests/playback/CORE_git-graft-enhance.test.ts
✅ Files skipped from review due to trivial changes (5)
  • package.json
  • test/unit/cli/git-graft-enhance-render.test.ts
  • test/fixtures/python/agent_service.py
  • test/unit/cli/structural-blame-render.test.ts
  • test/unit/operations/review-cooldown-status.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/unit/cli/git-graft-enhance-model.test.ts
  • src/cli/structural-test-coverage-render.ts
  • src/contracts/output-schema-mcp.ts

Comment thread src/operations/review-cooldown-status.ts
Comment thread src/operations/structural-test-coverage-map.ts Outdated
Comment thread src/operations/structural-test-coverage-map.ts
@flyingrobots
Copy link
Copy Markdown
Owner Author

Review feedback resolution summary:

Issue Reviewer Resolution SHA
Missing-timestamp CodeRabbit rate-limit markers could be silently sorted behind timestamped markers CodeRabbit inline thread Cooldown status now returns unknown when any authored rate-limit marker lacks timestamp or duration evidence; added regression coverage for mixed complete/incomplete markers f5143f4
Structural test coverage could count foo references from foobar lines CodeRabbit inline thread Reference matching now uses identifier boundaries rather than substring includes; added foo/foobar regression coverage f5143f4
Same-named exports in different source files could all be marked covered from one reference CodeRabbit inline thread Duplicate exported names now filter ambiguous matches to lines that reference the source file path/module; added two-file sharedApi attribution regression f5143f4
Feedback fixes needed changelog coverage Workflow cleanup Added Unreleased fixed note; no version bump because package remains v0.7.1 f99d4a6

Validation after f5143f4: pnpm vitest run test/unit/operations/review-cooldown-status.test.ts test/unit/operations/structural-test-coverage-map.test.ts, pnpm typecheck, pnpm lint, git diff --check, and Docker-isolated pnpm test (216 files / 1592 tests) all passed.

@coderabbitai review please 🥕

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Review rate limit: 0/1 reviews remaining, refill in 10 minutes and 37 seconds.

Copy link
Copy Markdown
Owner Author

@flyingrobots flyingrobots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Publishing remaining review-thread reply for f5143f4 feedback fixes.

Comment thread src/operations/structural-test-coverage-map.ts Outdated
Copy link
Copy Markdown
Owner Author

@flyingrobots flyingrobots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Publishing review-thread replies for f5143f4 feedback fixes.

Comment thread src/operations/structural-test-coverage-map.ts
@flyingrobots flyingrobots merged commit 8f3f6dd into main May 5, 2026
3 checks passed
@flyingrobots flyingrobots deleted the cycle/CORE_structural-test-coverage-map branch May 5, 2026 23:45
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