Repository navigation
Description
Observed in .claude/plugins/data/plugin-quality-melodic-software/evidence/c7ff503b-19e2-40d2-b99e-38c747f7fc0f/review-code-reviewer/20260919T205610Z/audit-notes.md, findings F3 and F5 (auditor severity: IMPORTANT, confidence high; mapped to medium per the run contract). It leads the security block on ordering, not on priority, because the failure state is reachable through the plugin's own dispatcher.
Where: agents/code-reviewer.md step 2, the git diff "$(git merge-base ... || echo HEAD)" block. Reproduced twice in scratch repos:
- No
originremote, clean tree, two commits onfeature: the chain resolves to the literalHEADandgit diff HEADemits 0 lines. - A real
git clone --depth 1 -b feature file://<bare>, the shapeactions/checkoutproduces by default: thels-remote --symreffallback finds and fetchesmain, butgit merge-base FETCH_HEAD HEADfails on shallow history with no shared ancestor, theorigin/mainfallback has no such ref, and the chain again resolves toHEADwith 0 diff lines.
The reviewer then gets an empty change set with no error and no way to tell "nothing changed" from "I could not find a base", so the output is a clean bill of health on an unreviewed change. The author knew of the adjacent case (the inline comment mentions shallow or single-branch clones lacking origin/$PR_BASE), but the mitigation does not cover the merge-base failure shallowness causes.
skills/fanout/context/run-everything-mode.md line ~51 sets const REVIEW_DIFF = 'HEAD' as the unsubstituted placeholder, commented "Substituted at dispatch by the main thread", and interpolates it into the agent prompt as git diff HEAD: the exact string F3 fails open to. Because the prompt supplies the command, the agent's step-2 chain is bypassed.
Not exercised in the evidence run: the session supplied git diff origin/main...HEAD, so step 2 never fired. The finding rests on the auditor's reproduction, not the packet.
Cheapest fix: replace the terminal || echo HEAD with a sentinel and add one line to step 2: an unresolved base is reported as such and the change set treated as unresolved, not empty. Same for fanout: make the placeholder '<UNRESOLVED>' so a missed substitution fails loudly. Fuller fix: add git rev-parse --is-shallow-repository to the block and, when true, instruct git fetch --unshallow --filter=blob:none before resolving.
Verification: re-run both reproductions. Each must name the base as unresolved and decline to grade, not return clean.
🤖 Generated with Claude Code
Activity
fix(review): fail loud on unresolved merge-base; no HEAD fallback (#4245
fix(review): close audit findings in base ladders, emit-stubs, securi…