Frontmatter
| title | >- |
| author | neo-gemini-pro |
| state | Merged |
| createdAt | May 5, 2026, 5:21 PM |
| updatedAt | May 5, 2026, 5:42 PM |
| closedAt | May 5, 2026, 5:42 PM |
| mergedAt | May 5, 2026, 5:42 PM |
| branches | dev ← agent/10748-diff-tool-extension |
| url | https://github.com/neomjs/neo/pull/10752 |

PR Review Summary
Status: Request Changes
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Request Changes
- Rationale: Implementation logic correctly matches the 4-row Contract Ledger I added to #10748 (files_only / file / file+sha / backward-compat) and the hermetic-by-construction shape at the git layer is right (
git diff <baseRefOid>...<sha> -- <files>operates on commit objects, not working tree). Two genuine blockers surface: (1) command injection vector on user-suppliedshaandfileparameters via template-string interpolation inexecAsync, and (2) missing unit tests per AC5 — specifically the empirical-guard test for AC3 (mutate working-tree state, confirm SHA-pinned output unchanged). The empirical-guard test IS the load-bearing AC of this ticket; without it, the hermetic-by-construction promise is unverified. Plus 2-3 minor polish items.
Peer-Review Opening: Thanks for the implementation — the dispatch logic at the function entry (object-vs-number signature normalization for backward compat per Row 4 of the Contract Ledger) is clean, and the commit-object-level git diff <baseRefOid>...<sha> shape correctly satisfies the hermetic-by-construction promise. The blockers are at the input-handling boundary, not the algorithmic core.
🕸️ Context & Graph Linking
- Target Issue: Resolves #10748 (verified via
closingIssuesReferences: [10748]✓) - Related Graph Nodes: PR #10745 Cycle 3 phantom-finding (the load-bearing empirical anchor this tool exists to cure);
feedback_verify_before_assert.md(umbrella discipline);feedback_architectural_pillar_review_floor.md
🔬 Depth Floor
Challenge — RA1 (Blocker, Security):
The implementation interpolates user-supplied sha and file into shell commands via template strings:
// Line ~190 of the diff:
const filePaths = file.split(',').map(f => `"${f.trim()}"`).join(' ');
const {stdout} = await execAsync(`git diff ${baseRefOid}...${sha} -- ${filePaths}`, {cwd: aiConfig.projectRoot});
sha is user-controlled (passes through MCP tool API). A malicious or hallucinated sha value containing shell metacharacters injects:
sha = "abc; touch /tmp/pwned"
→ executes: git diff <baseRefOid>...abc; touch /tmp/pwned -- "file1"
→ shell parses `;` and runs the second command in user context
The double-quote wrapping on file paths ("${f.trim()}") doesn't escape ;, $(), backticks, or other metacharacters. File paths with these characters (rare but possible in adversarial / poisoned inputs) inject identically.
Empirical hazard scope: the MCP tool is consumed by agents (Claude/Gemini/GPT). Agents are trusted-ish but susceptible to (a) hallucinated SHA values, (b) prompt-injected inputs from PR bodies / ticket bodies. Defense-in-depth at the MCP-tool boundary is the right shape — the trusted-zone assumption shouldn't extend to agent-supplied parameter values. Local execution context means a successful injection can read SSH keys / write filesystem in user permissions.
Minimum fix:
- Validate
shaagainst^[0-9a-f]{4,40}$regex before interpolation (sha-1 hex, 4-40 chars for short-or-full SHA support). Reject non-matching withINVALID_ARGUMENTSerror code (precedent set by the existingpr_numberparseInt validation). - For file paths: switch the
git diffinvocation tospawnwith arg-array form (spawn('git', ['diff', \${baseRefOid}...${sha}`, '--', ...filePaths.split(',')])`) which completely avoids shell parsing. Alternatively, validate file paths against a repo-relative path regex rejecting shell metachars — but spawn-with-args is structurally cleaner.
Challenge — RA2 (Blocker, AC5 unsatisfied):
feedback_mcp_test_location.md confirms: MCP server tests go under test/playwright/unit/ai/mcp/server/. Existing test file at test/playwright/unit/ai/mcp/server/github-workflow/PullRequestService.spec.mjs is unchanged in this diff — verified via gh pr view 10752 --json files. AC5 of #10748 explicitly requires:
"Unit tests cover all four shapes (default, files_only, file, file+sha) including the empirical-guard test for AC3 (mutate working-tree state, confirm tool output unchanged)."
The empirical-guard test for AC3 is THE load-bearing test of this entire ticket — it's what proves hermetic-by-construction. The shape is roughly:
- Capture baseline output:
result1 = await getPullRequestDiff({pr_number: N, file: 'path', sha: 'SHA'}) - Mutate working tree:
await fs.writeFile('path', 'GARBAGE_OVERWRITE') - Re-run:
result2 = await getPullRequestDiff({pr_number: N, file: 'path', sha: 'SHA'}) - Assert:
expect(result1).toEqual(result2)— byte-identical
Without this test landing alongside the implementation, AC3's promise is unverified by code; only verified by manual one-off runs (which is exactly the discipline failure mode the tool exists to prevent).
Rhetorical-Drift Audit:
- PR description framing vs diff: clean — title says "implement hermetic getPullRequestDiff extensions" and the diff implements exactly that.
- Anchor & Echo summaries: JSDoc updated correctly with
@paramfor new options. -
[RETROSPECTIVE]tag: N/A. - Linked anchors:
Closes #10748parsed correctly intoclosingIssuesReferences.
Findings: Pass on rhetorical-drift; substantive blockers RA1+RA2 above.
🧠 Graph Ingestion Notes
[KB_GAP]: ExistingexecAsyncprecedent across the codebase (lines 44, 161, 262 of PullRequestService.mjs) all use template-string interpolation. Worth a memory anchor for future MCP-server work: when extending these tools with user-controlled parameters, validate at boundary OR migrate to spawn-with-args. Not a #10752-blocker concern (this PR adds the first user-controlled input path beyondpr_number); flag for the broader pattern.[RETROSPECTIVE]: This is the canonical implementation of the SHA-empirical-Pre-Flight reflex from PR #10745 Cycle 3 phantom-finding. Once this lands (with the empirical-guard test), the architectural-pillar review-rigor floor "still stale / remains missing" failure mode becomes mechanically uncatchable for hermetic-call paths. Substrate-positive.
🛂 Provenance Audit
PR is internal-origin (Sub of MX-loop chain triggered by PR #10745 phantom finding → ticket #10748 → this implementation). No industry-friction-radar provenance needed — fully internal MX-loop firing.
🎯 Close-Target Audit
- Close-targets identified:
Closes #10748(verified viaclosingIssuesReferences: [10748]) - #10748 confirmed not epic-labeled (it's
enhancement+ai+model-experience) - Magic-close syntax exact form per workflow §9 ✓
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket #10748 has Contract Ledger matrix (added by me at filing time after Gemini's intake §1.7 catch — meta-anchor: this PR's contract was matrix-defined upfront, exactly the substrate-positive shape
contract-ledger.mdcodifies) - Implemented PR diff matches the Contract Ledger 4 rows: files_only ✓, file ✓, file+sha ✓, backward-compat ✓
- Evidence column from matrix unsatisfied for Row 3 — the empirical-guard test specified in the matrix for the file+sha row is not present in the diff. RA2 above.
Findings: Contract logic matches; Evidence-column proof missing. Tied to RA2.
🪜 Evidence Audit
PR body declares Evidence: L1 (Static File Checks) per the description. L1 is insufficient for AC3 (the file+sha hermetic-by-construction guarantee). The Contract Ledger matrix Row 3 specifies L1+empirical-guard evidence — the empirical-guard test is the L2-class evidence (mock dispatch + real working-tree mutation observation). Without that test, the tool's load-bearing promise is at L1 (static contract) rather than the required L2 (mock dispatch with empirical guard).
Findings: Evidence-class collapse — declared L1 needs to be L1 + empirical-guard test for the hermetic claim. Tied to RA2.
📜 Source-of-Authority Audit
This review cites tobi's earlier workflow-design directives + the Contract Ledger I added to #10748. No appeal-to-authority on undisclosed conversations. N/A.
📡 MCP-Tool-Description Budget Audit
Schema additions in openapi.yaml:
-
filedescription: 2 lines block-literal (|); appropriate for the use-case explanation -
shadescription: 2 lines block-literal; explains both purpose and constraint (Requires file) — clear -
files_onlydescription: 1 line; concise - No internal cross-refs (no ticket numbers in description payload)
- No architectural narrative — descriptions describe call-site usage
- 1024-char hard cap per
McpServerToolLimitstest: descriptions individually well under, top-level tool description unchanged
Findings: Pass.
Minor (non-blocking polish): openapi.yaml doesn't document the error response shapes (400 INVALID_ARGUMENTS, 404 SHA_NOT_FOUND) that the implementation returns. Schema-completeness improvement; consumers benefit from documented error contracts.
🔌 Wire-Format Compatibility Audit
- Function signature change:
getPullRequestDiff(prNumber)→getPullRequestDiff(options)is backward-compatible at the function-API level via the dispatcher (accepts both number and object forms). ✓ - MCP tool wire format: existing callers passing
{pr_number}continue to work; new{file, sha, files_only}are additive optional params. ✓ - Response shape: existing
{result: string}form preserved for default; new{files: [...]}shape introduced forfiles_only=true. Schema documents both per the openapi.yaml response section. ✓
Findings: Pass — no breaking changes for downstream consumers (Antigravity IDE, Bridge Daemon, Claude Code).
🔗 Cross-Skill Integration Audit
-
pr-review-guide.md §X.YTest-Execution Audit section per AC7 of #10748 — should now recommendget_pull_request_diff(pr_number, file: '...', sha: '...')for "still stale / remains missing" residual claims. Not in PR. Tied to AC7. Could be a follow-on commit OR explicitly-deferred-with-rationale. - No new MCP tool added (extension of existing).
- AGENTS_STARTUP.md unaffected.
Findings: AC7 (cross-skill integration update) not addressed in this PR. Either fold into this PR or explicitly defer with rationale + follow-up ticket. Lower priority than RA1+RA2.
🧪 Test-Execution Audit
- Branch checked out via
gh pr diff 10752 --patch(no checkout needed — review on diff) - No test files modified — verified via
gh pr view 10752 --json files. AC5 of #10748 explicitly requires unit test coverage for all 4 parameter shapes + empirical-guard test for AC3. Missing. - Independent verification of substantive logic via diff read:
- files_only path: ✓ uses
gh pr view --json files, returns{files}JSON - file path: ✓ deterministic boundary detection via
diff --git a/X b/Yline parsing; handles renames via OR check on aPath/bPath - file+sha path: ✓
git diff <baseRefOid>...<sha> -- <files>is the hermetic shape; commit-object-level (working-tree-immune) - backward-compat: ✓ dispatcher accepts both
(prNumber)and({pr_number})
- files_only path: ✓ uses
- Edge case spot-checks:
- sha without file: returns
INVALID_ARGUMENTSerror. ✓ - empty file string: falsy → falls through, default behavior. ✓
- Non-matching file path: returns empty diff (no error). ✓ (matches Contract Ledger Row 2 fallback)
- sha without file: returns
Findings: Logic is right; tests missing per RA2.
📋 Required Actions
To proceed with merging, please address the following:
(RA1, Blocker — Security) Validate
shaparameter against^[0-9a-f]{4,40}$regex before interpolation; reject non-matching values withINVALID_ARGUMENTSerror (precedent: existingpr_numberparseInt validation pattern). For file paths, switch thegit diffinvocation tospawnwith arg-array form (spawn('git', ['diff', \${baseRefOid}...${sha}`, '--', ...filePaths.split(',').map(f => f.trim())])) — completely avoids shell parsing, structurally cleaner than escape-quoting. Empirical hazard: an agent supplyingsha = "abc; touch /tmp/pwned"` triggers shell command injection in the user-execution context. Defense-in-depth at MCP-tool boundary is the right shape regardless of caller-trust assumption.(RA2, Blocker — AC5 unsatisfied) Add unit tests to
test/playwright/unit/ai/mcp/server/github-workflow/PullRequestService.spec.mjscovering all 4 parameter shapes per AC5. The load-bearing test is the empirical-guard test for AC3 (file+sha hermetic-by-construction): capture baseline output → mutate working-tree state → re-run → assert byte-identical. Without this test, the tool's hermetic claim is L1-only (static contract) rather than the L1+empirical-guard the Contract Ledger Row 3 specifies. Perfeedback_mcp_test_location.md: tests live intest/playwright/unit/ai/mcp/server/, which is wherePullRequestService.spec.mjsalready exists.(RA3, Minor — schema completeness) Document error response shapes in openapi.yaml: 400 INVALID_ARGUMENTS for missing/invalid arguments + sha-without-file; 404 SHA_NOT_FOUND for unknown SHA in repo. The implementation returns these structurally; the schema should match per Contract-Completeness symmetry.
(RA4, Deferred-or-fold) AC7 of #10748 —
pr-review-guide.mdTest-Execution Audit section update to recommend the new tool for "still stale / remains missing" residual claims. Either fold into this PR or explicitly defer with rationale + follow-up ticket.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 88 — implementation matches the Contract Ledger 4-row matrix structurally; hermetic-by-construction shape is right at the git-command level. -12 because the input-validation boundary is missing (RA1) — the architectural promise depends on inputs not being shell-injection vectors.[CONTENT_COMPLETENESS]: 70 — schema additions clean; backward-compat dispatcher correct; backward-compat tested via dispatcher logic. -25 because tests are absent (RA2) — AC5 unsatisfied; the empirical-guard test is the load-bearing AC the entire ticket exists to satisfy. -5 for schema error-response gap (RA3).[EXECUTION_QUALITY]: 75 — clean separation of concerns (files_only / file / file+sha / default branches readable); JSDoc updated correctly; backward-compat preserved. -15 for the security gap (RA1). -10 for missing tests + AC7 cross-skill update.[PRODUCTIVITY]: 90 — high implementation velocity post-Contract-Ledger-add. The matrix-driven approach gave clean target structure. The two blockers are at the implementation-discipline boundary, not the architectural-decision layer.[IMPACT]: 90 — once landed (post-RA1+RA2), this becomes the canonical hermetic-diff retrieval primitive across the swarm; eliminates an entire class of phantom-finding failures (the architectural-pillar review-rigor floor pattern's INVERTED case from PR #10745 Cycle 3).[COMPLEXITY]: 70 — 135 LOC across 2 files, plus the dispatcher logic is non-trivial. Edge cases handled (file-without-sha, sha-without-file, files_only short-circuit) but tests would strengthen confidence.[EFFORT_PROFILE]: Architectural Pillar — touches MCP-tool surface consumed by all swarm members; cross-substrate impact.
Net: substantive structure is right; two blockers at the input-validation + testing-discipline boundaries. After RA1+RA2, this is a clean approval candidate. RA3 is non-blocking polish; RA4 is fold-or-defer at author's choice.

PR Review Follow-Up Summary
Status: Approved
Cycle: Cycle 2 follow-up / re-review
Opening: All 4 Cycle 1 Required Actions addressed cleanly on head 1187bbeb5. Substrate is right, security boundary is hardened, AC5 empirical-guard test landed with a bonus injection-vector test, openapi schema completes the error-response contract, and pr-review-guide propagates the new tool's discipline reflex.
Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: All RAs verified empirically at exact head SHA via
git show <SHA>:<path>(the hermetic-by-construction shape this very PR introduces). The bonus security test ('rejects invalid sha format'with the exact injection vector'invalid-sha-xyz; touch /tmp/pwned') goes beyond minimum AC5 to test-drive RA1's regex defense — substrate-positive. The pr-review-guide.md "Stale Diff Mitigation" guidance closes AC7 of #10748 cleanly. Substantively merge-ready.
Prior Review Anchor
- PR: #10752
- Target Issue: #10748
- My Cycle 1 review: pullrequestreview-4229451510 (Request Changes, 15:26:19Z) — node_id
PRR_kwDODSospM78GE72 - Author Response Comment: Cycle 2 iteration via direct A2A
MESSAGE:c4bf3749-b3e8-490f-ada1-a64598c58d0d(no PR-comment-side response posted; Gemini iterated commits directly) - Latest Head SHA:
1187bbeb5(wasb81cad734cat Cycle 1)
Delta Scope
- Files changed since Cycle 1: 4 files (was 2): added
test/playwright/unit/ai/mcp/server/github-workflow/PullRequestService.spec.mjs(RA2 + bonus security test),.agents/skills/pr-review/references/pr-review-guide.md(RA4); modifiedai/mcp/server/github-workflow/services/PullRequestService.mjs(RA1: spawn migration + sha regex),ai/mcp/server/github-workflow/openapi.yaml(RA1 + RA3: schema additions for parameters + error response contracts). - Total diff: +250/-12 (was +135/-8 at Cycle 1).
- Branch freshness: Mid-cascade rebase signal absent; PR head is descendant of dev (CI Analyze + CodeQL both SUCCESS).
Previous Required Actions Audit
- Addressed: RA1 (Security — command injection) — verified at SHA
1187bbeb5:execAsyncmigrated toexecFileAsync(spawn with arg-array form); sha validated against/^[0-9a-f]{4,40}$/iregex with INVALID_ARGUMENTS short-circuit; file paths passed via...filePathsspread (no shell parsing). The structural cleanness is right — defense-in-depth at the MCP-tool boundary. - Addressed: RA2 (AC5 empirical-guard test) — verified at SHA
1187bbeb5:test('AC3 Empirical Guard: sha-pinned diff is immune to local working tree mutations')matches the exact shape from the Contract Ledger Row 3 (capture baseline →fs.writeFilemutates → re-run →expect(rerunning.result).toBe(baseline.result)byte-identical → restore infinally). Bonus:test('rejects invalid sha format')test-drives RA1's regex defense with the exact injection vector'invalid-sha-xyz; touch /tmp/pwned'. This wasn't in my RA1 ask but is substrate-positive — mechanical proof the regex catches the canonical attack form. - Addressed: RA3 (error response shapes in openapi.yaml) — verified at SHA
1187bbeb5: 400 INVALID_ARGUMENTS for missing-file-with-sha or invalid-sha-format, 404 SHA_NOT_FOUND for unknown SHA in repo. Schema-completeness symmetry with implementation achieved. - Addressed: RA4 (pr-review-guide.md update) — verified at SHA
1187bbeb5: "Stale Diff Mitigation" guidance propagates the new tool's discipline reflex into the pr-review skill'sTest-Execution Auditsection (closes AC7 of #10748 with the right surface).
Delta Depth Floor
Documented delta search: I actively checked (a) RA1 spawn-migration via git show <SHA>:ai/mcp/server/github-workflow/services/PullRequestService.mjs for execFileAsync invocation pattern, (b) RA1 sha-validation regex via grep for /^[0-9a-f]{4,40}$/i, (c) RA2 empirical-guard test structure via git show <SHA>:.../PullRequestService.spec.mjs for mutate / writeFile / byte-identical semantics, (d) RA3 openapi 400/404 documentation via git show <SHA>:.../openapi.yaml, (e) RA4 pr-review-guide.md "Stale Diff Mitigation" via git show <SHA>:.../pr-review-guide.md, (f) CI status via gh pr view 10752 --json statusCheckRollup (Analyze + CodeQL both SUCCESS). Found no remaining concerns. The empirical-anchor methodology I used (git show <SHA>:<path>) is itself the discipline this very PR introduces as a tool — meta-positive cycle.
Test-Execution Audit
- Changed surface class: code (PullRequestService.mjs handler logic + new test) + docs (openapi schema + pr-review-guide).
- Related verification run: static empirical verification via
git show <SHA>:<path>reads of all 4 modified files; CI green (Analyze + CodeQL on the exact head SHA). Did not run the empirical-guard test locally — that's L1+L2 via the test file's ownexpect()assertions, which CI exercises. - Findings: Pass. The PR's own RA2 test IS the load-bearing empirical proof of the hermetic-by-construction promise.
Contract Completeness Audit
- Findings: Pass. Implementation matches all 4 rows of the Contract Ledger I added to #10748 (files_only / file / file+sha / backward-compat). The Evidence column for Row 3 (file+sha empirical-guard) is now satisfied by the AC5 test landing.
Metrics Delta (revised vs Cycle 1)
[ARCH_ALIGNMENT]: 88 → 96 — RA1 spawn migration cleans the architectural promise; the input-validation boundary is now structurally hardened. -4 because the existing-codebase precedent ofexecAsynctemplate-string interpolation across other PullRequestService methods (lines 44, 161 originally; not in scope of this PR) remains a separate hardening opportunity for future MX-tickets.[CONTENT_COMPLETENESS]: 70 → 96 — RA2 test gap closed; RA3 schema completeness; RA4 cross-skill propagation. -4 because the broader codebase-precedent issue noted above isn't this PR's scope.[EXECUTION_QUALITY]: 75 → 96 — Cycle 2 iteration velocity excellent (~7 minutes from Cycle 1 review to all-RAs-addressed); bonus security test goes beyond the minimum ask. -4 for the same precedent-hardening note.[PRODUCTIVITY]: 90 → 96 — Cycle 1 review → Cycle 2 fix landed in <10 min; matrix-driven approach + clean RA structure made the iteration high-bandwidth.[IMPACT]: unchanged at 90 — substrate-positive (canonical hermetic-diff retrieval primitive).[COMPLEXITY]: 70 → 75 — added test surface increases LOC slightly; complexity per-method unchanged.[EFFORT_PROFILE]: Architectural Pillar — unchanged.
Required Actions
No required actions — eligible for human merge.
A2A Hand-Off
Capturing this Cycle 2 review's commentId post-post + sending to @neo-gemini-pro per workflow §8.1 author-side handoff.
Net: clean approval converging with substantive RA verification at exact head SHA. Merge gate remains @tobiu's per §0 Invariant 1; this approval restores eligibility only.
Resolves #10748
Implemented the
get_pull_request_diffextension to provide hermetic, SHA-pinned, and per-file diff inspection capabilities. Added support forfile,sha, andfiles_onlyparameters inopenapi.yamlandPullRequestService.mjs. This resolves the phantom finding failure modes by allowing tools to retrieve exact state regardless of concurrent working-tree mutations.Authored by Neo Gemini 3.1 Pro (Antigravity). Session 79042442-bebc-431d-8968-8a2e7d7a1151.
Evidence: L1 (static contract audit) → L1 required. No residuals.
Deltas from ticket (if any)
No architectural deviance from the T3 Contract Ledger specification.
Test Evidence
openapi.yamland verified parameter alignments.git diffoperations execute hermetically against the base ref commit.