feat(pr-gatekeeper): review a staged diff pre-push, for GitOps repos with no PR
infra#470 resolved a doctrine conflict: root rule 5 wants a PR for risk/medium+, and mathias/infra forbids branches because Flux watches main — a branch there can be linted but never reconciled, so a PR reviews a state that was never deployed. The agreed lane is that such work stays on main and gets a recorded adversarial review pass BEFORE the push. That lane names this agent as its reviewer, and the definition only knew how to review an open PR. A lane whose reviewer cannot see the diff resolves to "the author was careful", which is what rule 5 was written to replace. ONE AGENT, TWO MODES — NOT A SECOND FILE Only three of twelve sections were PR-specific: the diff command, the CI step, and the verdict. Everything else — the iron laws, "the test is the claim", the three attack habits, probing without causing the incident, escalation — is diff-agnostic. Forking a near-duplicate 226-line definition would give the estate two implementations of one review standard, and they would drift; the same argument tests/litellm-validate_test.sh makes about its own consolidation. WHAT DIFFERS, AND WHY - Diff: three commands, run all of them. Which one holds the change is itself information — work that is neither staged nor committed is a working tree, not a diff under review. Untracked files appear in neither diff, so `git status --porcelain` is how a control that exists only in an unstaged file gets noticed. - CI: it CANNOT have run, nothing is pushed. So "CI absent" must not block here — that rule is for a pushed branch with no runs, which is a platform failure; unpushed with no runs is arithmetic. Instead run the local gate and check its EXIT CODE, because a grep over gate output has hidden a failing test in this estate before. - Verdict: nothing to merge, no PR to close, no branch to delete. The entire output is a comment on the issue. That is what makes the lane RECORDED rather than a conversation — a verdict living only in a chat transcript is indistinguishable from no review having happened. The report must state that it carries strictly less external evidence than PR mode: "nothing I could find blocks this push", never "CI confirms this". TDD, and one vacuous assertion caught Five assertions written first, all red. One passed spuriously — an unscoped grep for "do not merge" matched line 202, the ESCALATION step talking about a PR. A pass for entirely the wrong reason, which is what rule 9 is about. Now scoped to the pre-push section, and the comment records why, so nobody re-loosens it. agents_test 19/19. Repo check exit 0, 45 skills, manifest matches tag. Refs mathias/infra#470 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -103,6 +103,62 @@ else
|
||||
ok 'doctor is silent when no host-local copy exists'
|
||||
fi
|
||||
|
||||
# --- the pre-push mode the GitOps review lane depends on (infra#470) ---------
|
||||
#
|
||||
# infra#470 resolved a doctrine conflict: root rule 5 wants a PR for risk/medium+,
|
||||
# and mathias/infra forbids branches because Flux watches main and a branch can be
|
||||
# linted but never reconciled. The agreed lane is that such work stays on main and
|
||||
# instead gets a RECORDED ADVERSARIAL REVIEW PASS before the push.
|
||||
#
|
||||
# That lane names this agent as its reviewer. If the definition only knows how to
|
||||
# review an open PR, the lane resolves to "be careful" — which is what rule 5 was
|
||||
# written to replace. These assertions observe FILE CONTENT only: that the mode is
|
||||
# documented, that it does not merge, and that the verdict has a stated home. They
|
||||
# do NOT claim the agent reviews a staged diff well (rule 9).
|
||||
|
||||
if grep -qi 'git diff --staged\|git diff --cached' "$AGENT"; then
|
||||
ok 'the definition names a command that reads a staged diff, not only a branch diff'
|
||||
else
|
||||
no 'the definition has no staged-diff command, so the infra#470 lane has no reviewer'
|
||||
fi
|
||||
|
||||
if grep -qi 'pre-push' "$AGENT"; then
|
||||
ok 'the definition names the pre-push mode'
|
||||
else
|
||||
no 'the definition does not name a pre-push mode (infra#470)'
|
||||
fi
|
||||
|
||||
# The verdict has to land somewhere durable, or "recorded review pass" is untrue.
|
||||
# The lane specifies the issue, deliberately not a PR thread — there is no PR.
|
||||
if grep -qi 'verdict in the issue\|verdict goes in the issue' "$AGENT"; then
|
||||
ok 'the definition states the verdict goes in the issue'
|
||||
else
|
||||
no 'the definition does not say where a pre-push verdict is recorded'
|
||||
fi
|
||||
|
||||
# In pre-push mode there is nothing to merge and no PR to close. An agent that
|
||||
# reaches for pr_merge there would be acting on a PR that does not exist.
|
||||
#
|
||||
# SCOPED to the pre-push section on purpose. An unscoped grep for "do not merge"
|
||||
# passes on line 202 of the current file, which is the ESCALATION step talking
|
||||
# about a PR — a pass for entirely the wrong reason, and the kind of vacuous
|
||||
# assertion rule 9 is about. Caught by checking what the green was matching.
|
||||
PREPUSH=$(awk '/[Pp]re-push/{f=1} f&&/^## [^#]/&&!/[Pp]re-push/{f=0} f' "$AGENT")
|
||||
if printf '%s' "$PREPUSH" | grep -qi 'nothing to merge\|do not merge\|no PR to merge'; then
|
||||
ok 'the pre-push section itself rules out merging'
|
||||
else
|
||||
no 'the pre-push section does not rule out merging (an unscoped grep would pass here wrongly)'
|
||||
fi
|
||||
|
||||
# CI cannot have run on an unpushed diff, so the CI step's meaning changes. A
|
||||
# definition that still treats "CI green" as available would grade on a signal
|
||||
# that does not exist yet.
|
||||
if grep -qi 'CI has not run\|no CI run yet\|CI cannot have run' "$AGENT"; then
|
||||
ok 'the definition acknowledges CI has not run on an unpushed diff'
|
||||
else
|
||||
no 'the definition does not address CI being absent pre-push'
|
||||
fi
|
||||
|
||||
rm -rf "$WORK"
|
||||
printf '\n%s passed, %s failed\n' "$pass" "$fail"
|
||||
[ "$fail" -eq 0 ]
|
||||
|
||||
Reference in New Issue
Block a user