Repository navigation
fix(guardrails): reference-verify flags a quoted claude -p prompt and blocks every push that merges main #9843
Copy link
Copy link
Open
Labels
admission-deferredReady for the issue lane; work-unblock admits it when queued work is under the queued capReady for the issue lane; work-unblock admits it when queued work is under the queued cappriority: highSignificant impact, or blocks an imminent release; staff this cycle.Significant impact, or blocks an imminent release; staff this cycle.status: readyTriaged, unblocked, and fully specified; eligible to pick up.Triaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.A briefed fix or small feature; blast radius bounded by the brief, tests exist.
Description
Problem
The guardrails pre-push reference-verify entry blocks every push whose range includes c39a5fea3 (#9670), which is every branch that merges current main. Branches whose base is stale must merge main to pass check-affected's stale-base-overlap check, so they cannot be pushed at all.
Output, from plugins/guardrails/git-hooks/reference-verify.sh origin <url> with the pushed ref on stdin:
plugins/machine-health/skills/setup/SKILL.md:154: cli-flag-verify: unknown flag(s) in plugins/machine-health/skills/setup/SKILL.md, unverified, not proven wrong: the installed --help may predate the flag.
plugins/machine-health/skills/setup/SKILL.md:154: claude on-demand --scheduled (not in 'claude on-demand --help')
Three defects:
- False positive. The text it flags is
plugins/machine-health/skills/setup/SKILL.md:340:`claude -p "/machine-health:audit on-demand --scheduled"`.on-demand --scheduledare arguments of a slash command inside the quoted-pprompt, not aclaudesubcommand and flag. - Wrong line. It reports line 154, which is a PowerShell line (
. (Join-Path $pluginRoot ...)). No line near 154 holdson-demand. - Content from the base counts as pushed. The finding comes from a commit already on
main, brought in by mergingorigin/maininto a feature branch. A pushed range should not re-judge linesmainalready holds.
Cost measured
- The same branch, before merging main:
reference-verifytook 0.07 seconds and passed. - After merging main: 58 seconds when run alone (
time, Claude Code 2.1.310), and 380 seconds inside agit push, where the SSH session dropped first (Connection to github.com closed by remote host). Expected: a few seconds. - Two PRs are blocked: fix(pr-pipeline): remove refine and Refs-hold stops that wait on a person #9802 and feat(pr-pipeline): keep one rolling issue per monitor signal and one lane-sweep digest #9772.
Suggested fix
- Treat a quoted
-p/--printprompt argument as data, not as a subcommand chain. - Report the line the match was found on.
- Drop lines the remote default branch already holds from the range, for example by diffing against the merge-base with
origin/<default>after a merge from it.
Add a stay-quiet test with the SKILL.md:340 form that fails before the fix (hook-precision convention).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
admission-deferredReady for the issue lane; work-unblock admits it when queued work is under the queued capReady for the issue lane; work-unblock admits it when queued work is under the queued cappriority: highSignificant impact, or blocks an imminent release; staff this cycle.Significant impact, or blocks an imminent release; staff this cycle.status: readyTriaged, unblocked, and fully specified; eligible to pick up.Triaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.A briefed fix or small feature; blast radius bounded by the brief, tests exist.
Type
Fields
No fields configured for Bug.
Activity
kyle-sexton commentedon Oct 24, 2026
Two more findings, 2026-10-24 ~20:25Z on the WSL host:
install.mjs decline --entry reference-verifysetchecks.guardrails.reference-verify.declined truein this clone's git config, but pushes still run.lefthook/pre-push/guardrails-reference-verify.shfrom.git/info/lefthook-remotes/claude-code-plugins-main/. That wrapperexecsplugins/guardrails/git-hooks/reference-verify.sh, andgrep -n declinedoverplugins/guardrails/git-hooks/in the lefthook-remote copy finds nothing, so the decline flag is never read on that path.reference-verify(run-guards.sh cli-flag-verify.sh) had been running for 20 min 06 s (psetime), with three other sessions' pushes in the same step at 3 min 44 s to 3 min 55 s. Expected: seconds.Fix needed in addition to the parser fix above: the lefthook-remote entry (or
reference-verify.shitself) must honor the decline flag, and the check needs a time bound.🤖 Generated with Claude Code
github-actions commentedon Oct 24, 2026
The triage sweep dispatched intake triage for this issue (attempt 1 of 2).
github-actions commentedon Oct 24, 2026
Proposed work class: work-class: scoped
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Medium
Uncertainty: Known
Flags: none
Blocked by: none
#9843 (comment)
The decision settles the open questions. The quoted
-pprompt and base-lines defects are already fixed by #9852. The time bound moves to #9861. What remains is reporting the true line of a match and honoring thedeclinedflag in reference-verify.sh on the lefthook-remote path, each with a test, plus a link to #9861 from this issue.Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 24, 2026
Not admitted to the issue lane: no trusted-human acceptance criteria: a listed human must put the confirmed
- [ ]criteria in the body or post them as their own comment, or, on an issue a listed human filed, intake's newest refinement comment must hold them unedited. A recorded decision does not change these rules (.github/actions/resolve-config/admission-rules.json); a person who wants it worked addsagent-ready.melodic-automation-lanes commentedon Oct 24, 2026
Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.
Intended outcome: reference-verify stays quiet on a quoted claude -p prompt, reports the real line, skips lines the default branch already holds after a merge from it, honors the decline flag on the lefthook-remote path, and is time-bounded.
Related work
Open questions
RECOMMENDED: Do the false positive, line number and decline fixes here, and leave the time bound and range limit to #9861, with each issue linking the other. Basis: 9861
RECOMMENDED: A 30 second total bound that prints a NOTICE and lets the push proceed, since a cli-flag finding is already described as unverified, not proven wrong. Basis: plugins/guardrails/git-hooks/reference-verify.sh:185
RECOMMENDED: In reference-verify.sh, since the wrapper execs it and no declined check exists under plugins/guardrails/git-hooks, so every install path honors it. Basis: plugins/guardrails/git-hooks/reference-verify.sh:41
RECOMMENDED: Yes: map the verifier's matched text back to its line in the added lines, falling back to the first added line when no match is found. Basis: plugins/guardrails/git-hooks/reference-verify.sh:138
Sources read
Automated refinement by the lanes App. Answer with a comment whose first line is
**Decision recorded.**.kyle-sexton commentedon Oct 26, 2026
Decision recorded. The owner answered in the Refinement session (2026-10-25), deciding the open items below on the facts:
Question asked: Narrow this issue to the remaining defects (true line number, decline flag on the lefthook-remote path), and move the time bound to #9861?
Defects 1 (quoted
-pprompt) and 3 (lines main already holds) are no longer open, as facts, not decisions: #9852 (9110877) on origin/main reads a quoted prompt as one argument and judges only a merged branch's own lines (plugins/guardrails/hooks/cli-flag-verify.sh:232,277; plugins/guardrails/git-hooks/reference-verify.sh:70,108-116). Its PR has a stay-quiet test per its Verification section; not re-run here.Decided: In perf(guardrails): pre-push reference-verify takes 8-17 min on stacked branches and pushes fail silently #9861, with each issue linking the other; this issue keeps the line number and decline fixes. Basis: kept; perf(guardrails): pre-push reference-verify takes 8-17 min on stacked branches and pushes fail silently #9861's body covers the run time.
Decided: Decide it in perf(guardrails): pre-push reference-verify takes 8-17 min on stacked branches and pushes fail silently #9861. A skip on expiry makes the guard fail open, which is the owner's call; the cli-flag finding already calls itself "unverified, not proven wrong". Basis: kept, moved; plugins/guardrails/hooks/cli-flag-verify.sh:564.
Decided: In reference-verify.sh, which the lefthook-remote wrapper execs, so every install path honors
checks.guardrails.reference-verify.declined. Basis: kept; nodeclinedread under plugins/guardrails/git-hooks or lib/git-hooks except install.mjs:464-466; reference-verify.sh:236 only prints the decline hint.Decided: Yes: map the matched text back to its added line, falling back to the first added line. Basis: kept; reference-verify.sh:127,183 report
first_line.Acceptance criteria:
checks.guardrails.reference-verify.declinedtrue, reference-verify.sh exits 0 without checking, including when run from the lefthook-remote wrapper, with a test.