From 535aa396ea9809154396018cb97102c5129e32e9 Mon Sep 17 00:00:00 2001 From: Invoker Bot Date: Sat, 12 Sep 2026 18:24:13 +0000 Subject: [PATCH 1/3] =?UTF-8?q?invoker:=20wf-1789236110851-19/implement-sw?= =?UTF-8?q?eep-diff-read-gate=20=E2=80=94=20Require=20a=20full=20diff=20re?= =?UTF-8?q?ad=20per=20PR=20before=20an=20admin=20merge,=20and=20mark=20a?= =?UTF-8?q?=20narrowed=20read=20unchecked.=20Review=20claim:=20A=20PR=20wh?= =?UTF-8?q?ose=20diff=20was=20read=20through=20a=20truncating=20filter=20i?= =?UTF-8?q?s=20unchecked,=20never=20reviewed.=20Review=20lane:=20behavior?= =?UTF-8?q?=20Safety=20invariant:=20A=20truncated=20or=20filtered=20diff?= =?UTF-8?q?=20read=20marks=20that=20PR=20unchecked,=20never=20reviewed;=20?= =?UTF-8?q?no=20PR=20that=20is=20reviewable=20today=20becomes=20unmergeabl?= =?UTF-8?q?e,=20because=20the=20gate=20reports=20rather=20than=20blocks=20?= =?UTF-8?q?the=20merge=20command.=20Effectiveness=20measurement:=20A=20fix?= =?UTF-8?q?ture=20review=20command=20piped=20through=20`head`=20marks=20it?= =?UTF-8?q?s=20PR=20unchecked,=20and=20the=20same=20command=20without=20th?= =?UTF-8?q?e=20pipe=20marks=20it=20reviewed.=20Both=20asserted=20in=20the?= =?UTF-8?q?=20skill's=20test=20directory.=20Slice=20rationale:=20One=20ste?= =?UTF-8?q?p=20of=20the=20sweep=20skill's=20review=20procedure;=20stacked?= =?UTF-8?q?=20behind=20the=20tally=20step=20because=20both=20edit=20the=20?= =?UTF-8?q?same=20SKILL.md.=20Architectural=20effect:=20Step=204=20gains?= =?UTF-8?q?=20an=20explicit=20read-completeness=20precondition=20expressed?= =?UTF-8?q?=20as=20the=20same=20three-outcome=20contract=20the=20rest=20of?= =?UTF-8?q?=20the=20stack=20uses.=20Goal:=20Change=20Step=204=20of=20produ?= =?UTF-8?q?ct/skills/admin-bypass-sweep/SKILL.md=20so=20each=20PR's=20diff?= =?UTF-8?q?=20is=20written=20to=20a=20file,=20fully=20read,=20and=20assert?= =?UTF-8?q?ed=20line-complete=20before=20`gh=20pr=20merge=20--admin`,=20wi?= =?UTF-8?q?th=20a=20narrowed=20read=20reported=20as=20unchecked.=20Motivat?= =?UTF-8?q?ion:=20A=20sweep=20reported=20'Reviewed=20all=2019'=20after=20t?= =?UTF-8?q?wo=20commands=20that=20between=20them=20truncated=20one=20PR=20?= =?UTF-8?q?entirely=20and=20filtered=20every=20test=20file=20out=20of=20fi?= =?UTF-8?q?ve=20others.=20The=20largest=20diff=20in=20the=20sweep,=20touch?= =?UTF-8?q?ing=20six=20hook=20detectors,=20was=20cleared=20for=20merge=20o?= =?UTF-8?q?n=20about=2021%=20of=20its=20non-test=20changes.=20Alternative?= =?UTF-8?q?=20considerations:=20Telling=20the=20operator=20not=20to=20pipe?= =?UTF-8?q?=20through=20head=20was=20rejected=20as=20unenforceable=20prose?= =?UTF-8?q?.=20Blocking=20the=20merge=20outright=20on=20a=20narrowed=20rea?= =?UTF-8?q?d=20was=20rejected=20for=20this=20slice:=20the=20skill's=20own?= =?UTF-8?q?=20consent=20model=20puts=20the=20merge=20decision=20with=20the?= =?UTF-8?q?=20human,=20so=20the=20gate=20reports=20unchecked=20and=20the?= =?UTF-8?q?=20operator=20decides.=20Implementation=20details:=20In=20Step?= =?UTF-8?q?=204,=20replace=20the=20ad=20hoc=20`gh=20pr=20diff`=20skim=20wi?= =?UTF-8?q?th:=20write=20each=20PR's=20diff=20to=20a=20file,=20record=20`w?= =?UTF-8?q?c=20-l`,=20read=20the=20whole=20file,=20and=20assert=20lines=5F?= =?UTF-8?q?read=20equals=20the=20recorded=20total=20before=20merging=20tha?= =?UTF-8?q?t=20PR.=20Any=20read=20through=20head,=20tail,=20grep,=20awk,?= =?UTF-8?q?=20or=20sed=20marks=20that=20PR=20unchecked.=20Use=20the=20same?= =?UTF-8?q?=20three=20outcomes=20as=20the=20rest=20of=20the=20stack:=20rev?= =?UTF-8?q?iewed,=20flagged,=20unchecked.=20Add=20fixtures=20under=20the?= =?UTF-8?q?=20skill's=20tests=20directory=20for=20a=20full=20read=20and=20?= =?UTF-8?q?a=20truncated=20read.=20Non-goals:=20Does=20not=20change=20what?= =?UTF-8?q?=20counts=20as=20a=20review=20finding,=20does=20not=20add=20an?= =?UTF-8?q?=20automated=20code=20review,=20does=20not=20alter=20the=20cons?= =?UTF-8?q?ent=20requirements=20in=20the=20STOP=20section,=20and=20does=20?= =?UTF-8?q?not=20touch=20any=20other=20skill.=20Layer:=20domain=20Feature?= =?UTF-8?q?=20state:=20active=20Files:=20product/skills/admin-bypass-sweep?= =?UTF-8?q?/SKILL.md,=20product/skills/admin-bypass-sweep/tests/=20Change?= =?UTF-8?q?=20types:=20-=20product/skills/admin-bypass-sweep/SKILL.md:=20d?= =?UTF-8?q?ocs-only=20-=20product/skills/admin-bypass-sweep/tests/fires=5F?= =?UTF-8?q?truncated=5Fdiff=5Fread.md:=20create=20-=20product/skills/admin?= =?UTF-8?q?-bypass-sweep/tests/stays=5Fsilent=5Ffull=5Fdiff=5Fread.md:=20c?= =?UTF-8?q?reate=20Acceptance=20criteria:=20-=20`python3=20-m=20unittest?= =?UTF-8?q?=20discover=20-s=20product/skills/admin-bypass-sweep/tests=20-v?= =?UTF-8?q?`=20exits=200.=20-=20Step=204=20requires=20a=20recorded=20line?= =?UTF-8?q?=20count=20and=20a=20full=20read=20before=20`gh=20pr=20merge=20?= =?UTF-8?q?--admin`.=20-=20A=20read=20through=20head,=20tail,=20grep,=20aw?= =?UTF-8?q?k,=20or=20sed=20is=20documented=20as=20unchecked.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Solution: Require a full diff read per PR before an admin merge, and mark a narrowed read unchecked. Review claim: A PR whose diff was read through a truncating filter is unchecked, never reviewed. Review lane: behavior Safety invariant: A truncated or filtered diff read marks that PR unchecked, never reviewed; no PR that is reviewable today becomes unmergeable, because the gate reports rather than blocks the merge command. Effectiveness measurement: A fixture review command piped through `head` marks its PR unchecked, and the same command without the pipe marks it reviewed. Both asserted in the skill's test directory. Slice rationale: One step of the sweep skill's review procedure; stacked behind the tally step because both edit the same SKILL.md. Architectural effect: Step 4 gains an explicit read-completeness precondition expressed as the same three-outcome contract the rest of the stack uses. Goal: Change Step 4 of product/skills/admin-bypass-sweep/SKILL.md so each PR's diff is written to a file, fully read, and asserted line-complete before `gh pr merge --admin`, with a narrowed read reported as unchecked. Motivation: A sweep reported 'Reviewed all 19' after two commands that between them truncated one PR entirely and filtered every test file out of five others. The largest diff in the sweep, touching six hook detectors, was cleared for merge on about 21% of its non-test changes. Alternative considerations: Telling the operator not to pipe through head was rejected as unenforceable prose. Blocking the merge outright on a narrowed read was rejected for this slice: the skill's own consent model puts the merge decision with the human, so the gate reports unchecked and the operator decides. Implementation details: In Step 4, replace the ad hoc `gh pr diff` skim with: write each PR's diff to a file, record `wc -l`, read the whole file, and assert lines_read equals the recorded total before merging that PR. Any read through head, tail, grep, awk, or sed marks that PR unchecked. Use the same three outcomes as the rest of the stack: reviewed, flagged, unchecked. Add fixtures under the skill's tests directory for a full read and a truncated read. Non-goals: Does not change what counts as a review finding, does not add an automated code review, does not alter the consent requirements in the STOP section, and does not touch any other skill. Layer: domain Feature state: active Files: product/skills/admin-bypass-sweep/SKILL.md, product/skills/admin-bypass-sweep/tests/ Change types: - product/skills/admin-bypass-sweep/SKILL.md: docs-only - product/skills/admin-bypass-sweep/tests/fires_truncated_diff_read.md: create - product/skills/admin-bypass-sweep/tests/stays_silent_full_diff_read.md: create Acceptance criteria: - `python3 -m unittest discover -s product/skills/admin-bypass-sweep/tests -v` exits 0. - Step 4 requires a recorded line count and a full read before `gh pr merge --admin`. - A read through head, tail, grep, awk, or sed is documented as unchecked. Invoker-Finalize-Id: 86232251-f80f-4a4b-a379-36417182163d --- product/skills/admin-bypass-sweep/SKILL.md | 41 +++++++++++-- .../tests/fixture_complete_diff_read.md | 20 +++++++ .../tests/fixture_truncated_diff_read.md | 23 +++++++ .../tests/test_diff_read_gate.py | 60 +++++++++++++++++++ 4 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 product/skills/admin-bypass-sweep/tests/fixture_complete_diff_read.md create mode 100644 product/skills/admin-bypass-sweep/tests/fixture_truncated_diff_read.md create mode 100644 product/skills/admin-bypass-sweep/tests/test_diff_read_gate.py diff --git a/product/skills/admin-bypass-sweep/SKILL.md b/product/skills/admin-bypass-sweep/SKILL.md index becb9df3..1558da55 100644 --- a/product/skills/admin-bypass-sweep/SKILL.md +++ b/product/skills/admin-bypass-sweep/SKILL.md @@ -141,10 +141,43 @@ diffs; stop and re-derive the safe approach first. Both requirements in the STOP section must be satisfied before this step runs. -Skim `gh pr diff ` for each PR before merging it, even under consent — -this is the only review most of these PRs get, since the merge bypasses -required checks entirely. The human's consent authorizes bypassing CI; it -does not stand in for having actually looked at what's being merged. +Before any `gh pr merge --admin`, write that PR's diff to a file, record +the file's total line count with `wc -l`, read the whole file, and assert +that the number of lines read equals the recorded total. This is the only +review most of these PRs get, since the merge bypasses required checks +entirely. The human's consent authorizes bypassing CI; it does not stand in +for having actually looked at what's being merged. + +Use this read-completeness precondition for each PR: + +```bash +pr= +diff_file="$(mktemp -t admin-bypass-pr-${pr}.diff.XXXXXX)" +gh pr diff "$pr" --repo / > "$diff_file" +diff_lines="$(wc -l < "$diff_file" | tr -d ' ')" +nl -ba "$diff_file" +lines_read= +test "$lines_read" = "$diff_lines" +``` + +Classify the PR before merging it, using the same three outcomes as the +rest of this procedure: + +- `reviewed` — the diff file was read line-complete, `lines_read` equals + `diff_lines`, and no review finding was found. +- `flagged` — the diff file was read line-complete, `lines_read` equals + `diff_lines`, and one or more review findings were recorded for the + human. +- `unchecked` — the diff read was narrowed, filtered, or truncated, so + line completeness was not established. + +A read through `head`, `tail`, `grep`, `awk`, or `sed` is a narrowed read: +mark that PR `unchecked`, never `reviewed`, even if the visible lines look +fine. The operator may not report such a PR as reviewed. This check reports +the PR's review state; it does not create a new authorization path or block +the human from deciding to proceed with the admin merge anyway. If an +`unchecked` PR is merged, the final report must still list it as +`unchecked`, not reviewed. For a single-PR stack: diff --git a/product/skills/admin-bypass-sweep/tests/fixture_complete_diff_read.md b/product/skills/admin-bypass-sweep/tests/fixture_complete_diff_read.md new file mode 100644 index 00000000..b3baba78 --- /dev/null +++ b/product/skills/admin-bypass-sweep/tests/fixture_complete_diff_read.md @@ -0,0 +1,20 @@ +User invokes `/admin-bypass-sweep` with the required consent sentence and the +operator reaches Step 4 for PR 42. + +The operator writes the full diff to a file: + +```bash +pr=42 +diff_file="$(mktemp -t admin-bypass-pr-${pr}.diff.XXXXXX)" +gh pr diff "$pr" --repo neko/example > "$diff_file" +diff_lines="$(wc -l < "$diff_file" | tr -d ' ')" +nl -ba "$diff_file" +lines_read=184 +test "$lines_read" = "$diff_lines" +``` + +The recorded `diff_lines` value is 184, and the complete `nl -ba` output ends +at line 184. No review finding is found. + +Expected outcome: PR 42 may be reported as `reviewed` before the operator runs +`gh pr merge 42 --repo neko/example --admin --squash`. diff --git a/product/skills/admin-bypass-sweep/tests/fixture_truncated_diff_read.md b/product/skills/admin-bypass-sweep/tests/fixture_truncated_diff_read.md new file mode 100644 index 00000000..3c1a1646 --- /dev/null +++ b/product/skills/admin-bypass-sweep/tests/fixture_truncated_diff_read.md @@ -0,0 +1,23 @@ +User invokes `/admin-bypass-sweep` with the required consent sentence and the +operator reaches Step 4 for PR 77. + +The operator writes the diff to a file, but reads it through a truncating +filter: + +```bash +pr=77 +diff_file="$(mktemp -t admin-bypass-pr-${pr}.diff.XXXXXX)" +gh pr diff "$pr" --repo neko/example > "$diff_file" +diff_lines="$(wc -l < "$diff_file" | tr -d ' ')" +head -200 "$diff_file" +lines_read=200 +test "$lines_read" = "$diff_lines" +``` + +The recorded `diff_lines` value is 913, and only the first 200 lines were read +through `head`. + +Expected outcome: PR 77 is `unchecked`, not `reviewed`. The operator may not +report PR 77 as reviewed, even if the visible lines look fine. If the human +decides to proceed with `gh pr merge 77 --repo neko/example --admin --squash`, +the final report must still list PR 77 as `unchecked`. diff --git a/product/skills/admin-bypass-sweep/tests/test_diff_read_gate.py b/product/skills/admin-bypass-sweep/tests/test_diff_read_gate.py new file mode 100644 index 00000000..254c27e1 --- /dev/null +++ b/product/skills/admin-bypass-sweep/tests/test_diff_read_gate.py @@ -0,0 +1,60 @@ +from pathlib import Path +import re +import unittest + + +ROOT = Path(__file__).resolve().parents[1] +SKILL = ROOT / "SKILL.md" +TESTS = ROOT / "tests" + + +class DiffReadGateTests(unittest.TestCase): + def setUp(self): + self.skill = SKILL.read_text() + step4_match = re.search( + r"## Step 4: Merge each stack, bottom-up(?P.*?)## Step 5:", + self.skill, + re.S, + ) + self.assertIsNotNone(step4_match, "Step 4 section is present") + self.step4 = step4_match.group("body") + + def test_step4_requires_recorded_line_count_and_full_read_before_admin_merge(self): + merge_index = self.step4.index("gh pr merge ") + pre_merge = self.step4[:merge_index] + + self.assertIn("Before any `gh pr merge --admin`", pre_merge) + self.assertIn("gh pr diff", pre_merge) + self.assertIn("> \"$diff_file\"", pre_merge) + self.assertIn("wc -l", pre_merge) + self.assertIn("nl -ba \"$diff_file\"", pre_merge) + self.assertIn('test "$lines_read" = "$diff_lines"', pre_merge) + self.assertIn("number of lines read equals the recorded total", pre_merge) + + def test_step4_documents_narrowed_reads_as_unchecked_not_reviewed(self): + for command in ("head", "tail", "grep", "awk", "sed"): + self.assertIn(f"`{command}`", self.step4) + + self.assertIn("mark that PR `unchecked`, never `reviewed`", self.step4) + self.assertIn("may not report such a PR as reviewed", self.step4) + + def test_complete_read_fixture_marks_pr_reviewed(self): + fixture = (TESTS / "fixture_complete_diff_read.md").read_text() + + self.assertIn("wc -l", fixture) + self.assertIn("nl -ba", fixture) + self.assertIn("lines_read=184", fixture) + self.assertIn("Expected outcome: PR 42 may be reported as `reviewed`", fixture) + + def test_truncated_read_fixture_marks_pr_unchecked(self): + fixture = (TESTS / "fixture_truncated_diff_read.md").read_text() + fixture_lower = fixture.lower() + + self.assertIn("head -200", fixture) + self.assertIn("diff_lines` value is 913", fixture) + self.assertIn("PR 77 is `unchecked`, not `reviewed`", fixture) + self.assertIn("operator may not\nreport pr 77 as reviewed", fixture_lower) + + +if __name__ == "__main__": + unittest.main() From df1cf2dc4a123a0198de29eace777496ffff49b4 Mon Sep 17 00:00:00 2001 From: Invoker Bot Date: Sat, 12 Sep 2026 18:24:57 +0000 Subject: [PATCH 2/3] =?UTF-8?q?invoker:=20wf-1789236110851-19/verify-sweep?= =?UTF-8?q?-diff-read-gate=20=E2=80=94=20Run=20the=20deterministic=20proof?= =?UTF-8?q?=20for=20the=20full-diff-read=20gate.=20Review=20claim:=20The?= =?UTF-8?q?=20skill's=20fixtures=20assert=20a=20truncated=20diff=20read=20?= =?UTF-8?q?is=20reported=20unchecked.=20Review=20lane:=20proof=20Safety=20?= =?UTF-8?q?invariant:=20Proof-only;=20adds=20no=20product=20behavior.=20Ef?= =?UTF-8?q?fectiveness=20measurement:=20The=20suite=20fails=20if=20the=20t?= =?UTF-8?q?runcated-read=20fixture=20is=20reported=20as=20reviewed.=20Slic?= =?UTF-8?q?e=20rationale:=20One=20proof=20slice=20for=20this=20step.=20Arc?= =?UTF-8?q?hitectural=20effect:=20None;=20verification=20only.=20Goal:=20P?= =?UTF-8?q?rove=20the=20full-diff-read=20gate=20deterministically.=20Motiv?= =?UTF-8?q?ation:=20The=20defect=20is=20an=20over-claimed=20review,=20so?= =?UTF-8?q?=20the=20proof=20asserts=20the=20narrowed=20case=20is=20named?= =?UTF-8?q?=20unchecked.=20Alternative=20considerations:=20Manual=20verifi?= =?UTF-8?q?cation=20was=20rejected=20as=20non-deterministic.=20Implementat?= =?UTF-8?q?ion=20details:=20Execute=20the=20command=20below=20as=20the=20t?= =?UTF-8?q?erminal=20proof.=20Non-goals:=20No=20product=20edits=20here;=20?= =?UTF-8?q?proof=20only.=20Layer:=20app=5Fregression=20Feature=20state:=20?= =?UTF-8?q?active?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exit code: 0 Invoker-Finalize-Id: 4cde49f2-d3fe-41d7-ad5f-4c24fb36f491 From 6cd1a053b2c52546d09671366102d18f196fc57c Mon Sep 17 00:00:00 2001 From: Invoker Bot Date: Sat, 12 Sep 2026 18:25:46 +0000 Subject: [PATCH 3/3] =?UTF-8?q?invoker:=20wf-1789236110851-19/scrub-handof?= =?UTF-8?q?f-artifacts=20=E2=80=94=20Terminal=20check=20that=20no=20epheme?= =?UTF-8?q?ral=20inter-task=20handoff=20files=20remain.=20Review=20claim:?= =?UTF-8?q?=20The=20workflow=20leaves=20no=20scratch=20handoff=20artifacts?= =?UTF-8?q?=20behind.=20Review=20lane:=20cleanup=20Safety=20invariant:=20R?= =?UTF-8?q?ead-only;=20never=20deletes=20files,=20alters=20the=20index,=20?= =?UTF-8?q?or=20commits=20caller=20work.=20Effectiveness=20measurement:=20?= =?UTF-8?q?The=20gate=20fails=20when=20a=20plans/invoker-handoff.*=20or=20?= =?UTF-8?q?lens-*.json=20file=20is=20still=20present=20after=20the=20leaf?= =?UTF-8?q?=20tasks=20complete.=20Slice=20rationale:=20One=20terminal=20hy?= =?UTF-8?q?giene=20gate=20for=20the=20workflow.=20Architectural=20effect:?= =?UTF-8?q?=20None;=20check=20only.=20Goal:=20Confirm=20no=20ephemeral=20h?= =?UTF-8?q?andoff=20files=20survive=20the=20run.=20Motivation:=20Inter-tas?= =?UTF-8?q?k=20scratch=20files=20leak=20into=20diffs=20and=20read=20as=20p?= =?UTF-8?q?art=20of=20the=20work.=20Alternative=20considerations:=20Deleti?= =?UTF-8?q?ng=20them=20automatically=20was=20rejected;=20the=20gate=20repo?= =?UTF-8?q?rts,=20it=20does=20not=20mutate.=20Implementation=20details:=20?= =?UTF-8?q?Run=20scripts/scrub-handoff-artifacts.sh=20without=20--apply.?= =?UTF-8?q?=20Non-goals:=20No=20deletion,=20no=20index=20changes,=20no=20c?= =?UTF-8?q?ommits.=20Layer:=20app=5Fregression=20Feature=20state:=20active?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exit code: 0 Invoker-Finalize-Id: 401825e5-c8a7-488b-9472-5b8212a9ca68