pi-gauntlet 8.4.8 → 8.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +16 -10
- package/extensions/phase-tracker.test.ts +78 -2
- package/extensions/phase-tracker.ts +11 -4
- package/extensions/telemetry-settlement-contract.test.ts +29 -1
- package/extensions/verify-before-ship.test.ts +47 -22
- package/extensions/verify-before-ship.ts +3 -3
- package/package.json +2 -2
- package/skills/brainstorming/reference/legs.md +57 -10
- package/skills/brainstorming/reference/spec-pr.md +41 -9
- package/skills/finishing-a-development-branch/SKILL.md +5 -5
- package/skills/finishing-a-development-branch/reference/legs.md +14 -4
- package/skills/gatekeep-pr/SKILL.md +39 -28
- package/skills/gatekeep-pr/reference/batch.md +10 -10
- package/skills/gatekeep-pr/reference/cleanup.md +5 -5
- package/skills/gatekeep-pr/reference/findings.md +28 -13
- package/skills/gatekeep-pr/reference/menus.md +103 -74
- package/skills/gatekeep-pr/reference/post-selection-loop.md +31 -17
- package/skills/gatekeep-pr/reference/report.md +33 -101
- package/skills/gatekeep-pr/reference/sync.md +1 -1
- package/skills/gatekeep-pr/verification-brief.md +6 -6
- package/skills/gauntlet-resume/reference/brief-contract.md +1 -1
- package/skills/using-git-worktrees/reference/pr-head.md +33 -7
- package/skills/writing-plans/SKILL.md +1 -1
- package/skills/writing-plans/reference/plan-contract.md +1 -1
- package/skills/gatekeep-pr/reference/decision-menu.md +0 -53
|
@@ -24,7 +24,7 @@ git -C <worktree> diff --name-status origin/$DEFAULT...HEAD
|
|
|
24
24
|
|
|
25
25
|
Prove the shared predicate against `origin/$DEFAULT` before pushing. Stop on command errors. On invalid shape print the offending name-status lines and `origin/$DEFAULT`, retain the amended spec and checkout, and redraw with `Withheld: draft PR - diff against origin/$DEFAULT is not spec-only (<paths>)` replacing 6. Keep implementation approvals available.
|
|
26
26
|
|
|
27
|
-
Push, then create with explicit head/base and the spec H1 as title. Run gh against the worktree repository:
|
|
27
|
+
Push, then create with explicit head/base and the spec H1 as title. Pass the summary verbatim through the quoted heredoc shown below, including its literal delimiter in narrated commands. Run gh against the worktree repository:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
git -C <worktree> push -u origin <branch>
|
|
@@ -40,7 +40,28 @@ EOF
|
|
|
40
40
|
| Retry 6 after published handoff | Refresh origin's branch head; require `origin/<branch>` == HEAD. On mismatch print both full SHAs and stop. On equality rerun create only, no push, no amend. |
|
|
41
41
|
| Create succeeds | Print URL before completing brainstorm; then perform ownership-based cleanup below. |
|
|
42
42
|
|
|
43
|
-
After URL output call `phase_tracker({ action: "complete", phase: "brainstorm" })
|
|
43
|
+
After URL output call `phase_tracker({ action: "complete", phase: "brainstorm" })`, then run [Draft-PR cleanup](#draft-pr-cleanup) once for home. Start no plan or loop, produce no handoff brief, and leave telemetry unchanged.
|
|
44
|
+
|
|
45
|
+
### Draft-PR cleanup
|
|
46
|
+
|
|
47
|
+
Bind `<repo>` and `<branch>` from the recorded block, `<primary>` to that repo's primary, and `<tree>` to the session's home worktree. For a legacy spec without `## Legs`, use the repo and branch just pushed and the recipe's worktree. For companions, locate `<tree>` by [Locate a leg tree](legs.md#locate-a-leg-tree), not the carried Worktree First path; on lookup failure run no destroy or branch deletion, report `<repo>: kept <branch> - <lookup reason>`, and continue.
|
|
48
|
+
|
|
49
|
+
1. Require `git -C <tree> branch --show-current` to print `<branch>`. Read `git -C <tree> ls-remote --exit-code --heads origin refs/heads/<branch>`, `git -C <tree> rev-parse HEAD`, and `git -C <primary> rev-parse refs/heads/<branch>`. Pin the SHA only on exit 0 with all three SHAs equal. Otherwise keep tree and branch and report the reason below.
|
|
50
|
+
2. Select ownership and destruction through finishing's [Step 6](../../finishing-a-development-branch/SKILL.md#step-6-cleanup-workspace), using the recorded contract for a spec with Legs and the overrides reread only for a legacy spec. A recorded block with `home:` keeps its pattern ownership test. Without `home:`, run its recorded `destroy:` from the primary on the located tree, with `<name>` set to the folder basename and `<branch>` to the recorded branch; resolve other tokens before execution. Neither `home:` nor `destroy:` means host-owned: keep both. Never fall back to native removal after a refused or failed wrapper. Before running a branch-deleting wrapper, require its source to delete only after the tree is gone and only at the pinned commit or behind a check refusing a tip the remote does not hold; refuse unguarded deletion.
|
|
51
|
+
3. After destruction, whatever its exit, read `git -C <primary> worktree list --porcelain`, the folder's on-disk presence, and `git -C <primary> rev-parse -q --verify refs/heads/<branch>`. Count the tree removed only when neither listed nor on disk; otherwise keep any remaining branch. Decide from read-back, never the destroy exit alone.
|
|
52
|
+
4. With the tree removed and the ref still present, compare its tip to the pinned SHA. Keep a moved ref; otherwise run `git -C <primary> update-ref -d refs/heads/<branch> <pinned SHA>`, never `git branch -D`. Read back the ref after deletion to report its actual state. A guarded wrapper that already deleted it needs no second deletion.
|
|
53
|
+
5. Report from the observed tree and branch state:
|
|
54
|
+
|
|
55
|
+
| State | Report |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Tree removed, branch deleted | `<repo>: removed <path>, deleted <branch>` |
|
|
58
|
+
| Both remain | `<repo>: kept <path> and <branch> - <reason>` |
|
|
59
|
+
| Tree removed, branch remains | `<repo>: removed <path>, branch <branch> kept - <reason>` |
|
|
60
|
+
| Tree remains, branch gone | `<repo>: kept <path>, branch <branch> deleted - <output>` |
|
|
61
|
+
|
|
62
|
+
Use the observed reason: `tree is on <current branch or detached>, not <branch>`, `origin/<branch> is at <sha>, tree is at <sha>`, `<branch> is at <sha>, tree is at <sha>`, `origin/<branch> is missing` (ls-remote exit 2), `remote lookup failed: <output>` (other nonzero exit), `host-owned`, `destroy deletes <branch> unguarded`, or `removal failed: <output>`. For a removed tree with a retained branch, report `<branch> moved to <sha>` or the update-ref output. A nonzero destroy exit with the tree removed still proceeds to step 4; append ` - destroy exited <code>: <output>` to the report.
|
|
63
|
+
|
|
64
|
+
Attempt every leg regardless of another cleanup outcome, companions in declared order then home. For a retained tree outside a recorded `home:`'s resolved path, explain that later `brainstorming #N` stops on a branch checked out at another path; a no-`home:` tree is reused by continuation. Run no cleanup when PR creation fails.
|
|
44
65
|
|
|
45
66
|
### Coordinated publication passes
|
|
46
67
|
|
|
@@ -61,23 +82,34 @@ Publish companions in declared order from the preflight observations:
|
|
|
61
82
|
|
|
62
83
|
Then run home's existing push/create recipe. Home push/create failures keep its failure rows and also list published companions; never roll back. After home create failure freeze the published handoff commit: the create-only retry above does not amend or push any member or rerun publication passes. On success print `pushed: <repo> origin/<branch>` for each companion before the single home URL, then complete brainstorm.
|
|
63
84
|
|
|
64
|
-
|
|
85
|
+
Run [Draft-PR cleanup](#draft-pr-cleanup) for companions in declared order, then home, retaining each leg's report even after another leg's refusal. Write no receipt, companion PR, telemetry or brief.
|
|
65
86
|
|
|
66
87
|
### Coordinated marked settlement
|
|
67
88
|
|
|
68
89
|
Use only the N>1 context observed by pr-subject's marked classifier at the original PR head. Preserve home's provisioned tree on every stop. Read the committed Legs in order; reject missing repo/branch/contract, mismatched shared branches or invalid blocks without falling into ordinary sibling discovery.
|
|
69
90
|
|
|
70
|
-
1. Settle only recorded companions with [legs.md](legs.md)'s first-found home overrides at `BASE_SHA` (`git show <BASE_SHA>:<overrides path>`), sibling parser and `<home PRIMARY parent>/<NAME>` paths. Match repo identifiers before probing paths; validate declaration, checkout
|
|
71
|
-
2. Preflight every companion before creating or syncing any companion: run `git -C <PATH> fetch origin` in its primary, then `git -C <PATH> ls-remote --exit-code --heads origin refs/heads/<branch>`. Exit 2 means missing: take the missing-remote stop below even when a stale `origin/<branch>` still resolves. Exit 0 proves live existence; require the recorded shared `origin/<branch>`. On any fetch failure or other lookup exit stop naming member and command output, never diagnose absence. Resolve its own settings/overrides
|
|
72
|
-
3. Permit fetch/tracking-ref updates during preflight, but no worktree add, local branch/ref update or merge. A missing last declaration/remote prevents provisioning even the first companion. On missing remote
|
|
73
|
-
4. After every companion passes, invoke using-git-worktrees once each with explicit `ROOT` = primary, shared `BRANCH`, `REMOTE_BRANCH=existing`. Use pr-head's companion mode and race backstop; carry each Step 4 report, including `Base sync recovered: <sha7>` and its proof. Never construct companion PR fields, pre-rework refs, thread queries or `MEMBER_HEADS`.
|
|
91
|
+
1. Settle only recorded companions with [legs.md](legs.md)'s first-found home overrides at `BASE_SHA` (`git show <BASE_SHA>:<overrides path>`), sibling parser and `<home PRIMARY parent>/<NAME>` paths. Match repo identifiers before probing paths; validate declaration, checkout and stored origin identity. Canonicalize both PATH and home PRIMARY, compare them explicitly, and stop on equality before any companion provisioning. Never activate unrecorded siblings or infer membership from existing PRs. On no match stop: `leg <repo> matches no sibling declaration in <overrides path>`.
|
|
92
|
+
2. Preflight every companion before creating or syncing any companion: run `git -C <PATH> fetch origin` in its primary, then `git -C <PATH> ls-remote --exit-code --heads origin refs/heads/<branch>`. Exit 2 means missing: take the missing-remote stop below even when a stale `origin/<branch>` still resolves. Exit 0 proves live existence; require the recorded shared `origin/<branch>`. On any fetch failure or other lookup exit stop naming member and command output, never diagnose absence. Resolve its own settings/overrides with legs.md's preset/default rules. Compare portable values by the table below. Stop on drift: `contract drift for <repo>: recorded <key>: <recorded value>, resolved <current value>; amend the recorded contract or restore the repo convention, then rerun brainstorming #N`. Never silently choose between them. Resolve a user amendment through the existing home-plus-companion reconciliation path.
|
|
93
|
+
3. Permit fetch/tracking-ref updates during preflight, but no worktree add, local branch/ref update or merge. A missing last declaration/remote prevents provisioning even the first companion. On missing remote use pr-head's [Missing remote recovery](../../using-git-worktrees/reference/pr-head.md#missing-remote-recovery): check the local branch's file-scoped log in the primary before choosing the push or restore ending.
|
|
94
|
+
4. After every companion passes, invoke using-git-worktrees once each with explicit `ROOT` = primary, shared `BRANCH`, `REMOTE_BRANCH=existing`. Use pr-head's companion mode and race backstop; carry each Step 4 report, including `Base sync recovered: <sha7>` and its proof. Never construct companion PR fields, pre-rework refs, thread queries or `MEMBER_HEADS`. Apply pr-head's [Recorded no-home provisioning](../../using-git-worktrees/reference/pr-head.md#recorded-no-home-provisioning) for a block without `home:`; keep the `-b`/`-B` native fallback only for a block with `home:`. Invent no second provisioning path.
|
|
74
95
|
5. On unresolved companion base merge stop: `base merge unresolved for <repo> (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`. Keep all trees and refs; on every stop print `Preserved created legs:` listing home and every already-provisioned companion, with repo and path. Never remove any on retries. Preserve home's recovered base-sync proof even if a later companion stops; rerun using the same home recovery path.
|
|
75
96
|
|
|
76
|
-
|
|
97
|
+
Compare the recorded contract before provisioning:
|
|
98
|
+
|
|
99
|
+
| Recorded field | Current value |
|
|
100
|
+
|---|---|
|
|
101
|
+
| Keyed or built-in `create:` | Step 1a's resolved portable `create:`. |
|
|
102
|
+
| Discovered-script `create:` | Step 1b's native-tool/script discovery in that primary, rendered through [Record portable templates](legs.md#record-portable-templates), not Step 1a's built-in default. |
|
|
103
|
+
| Recorded `home:` | The current creator's `home:`; when none, print the drift stop with `resolved absent`. |
|
|
104
|
+
| No `home:` recorded | Skip home comparison. |
|
|
105
|
+
|
|
106
|
+
For a script-placed leg with an unwanted recorded `home:`, require a user-approved amendment dropping that line from both the home block and companion file through their existing reconciliation path. Rewrite nothing automatically.
|
|
107
|
+
|
|
108
|
+
At gate readiness render each observed Step 4 report in full, home first then companions in recorded order: `Worktree ready at <path>`, `Branch: <branch>`, Base and Base SHA, and the observed `merge:` outcome. Include each returned `create: override skipped (contains -b)` and `Base sync recovered:` line; preserve home's PR and Pre-rework head lines only on home. Inside the rendered gate block, explicitly print `Worktrees: <home repo> <home path>, <companion repo> <companion path>, ...` naming every Worktree First path, home first then each companion in recorded order, never home alone. Render these values, not a promise to include them. Offer the ordinary AC-dependent 1/2/4/5 choices and optional pinned audit 3 below, and `Withheld: draft PR - #N already exists`. Keep ordinary pinned-audit and approval persistence below; no companion approval record or second council.
|
|
77
109
|
|
|
78
110
|
## Re-gate a marked spec PR
|
|
79
111
|
|
|
80
|
-
Reuse [pr-head](../../using-git-worktrees/reference/pr-head.md)'s checkout, base merge, and Step 4 report, not its before-gather thread fetch. Preserve its checked-out-at-another-path stop
|
|
112
|
+
Reuse [pr-head](../../using-git-worktrees/reference/pr-head.md)'s checkout, base merge, and Step 4 report, not its before-gather thread fetch. Preserve its checked-out-at-another-path stop for recorded `home:` blocks and unmarked subjects; use its no-home provisioning rows for a marked home without `home:`. On observed `merge: unresolved - <files>`, print `base merge unresolved for PR #N (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`; preserve checkout, render no gate, write no approval or repair task.
|
|
81
113
|
|
|
82
114
|
For observed N>1 carried Legs, finish [coordinated marked settlement](#coordinated-marked-settlement) after home's Step 4 report and before rendering the gate. For zero/one block keep the home-only route unchanged.
|
|
83
115
|
|
|
@@ -380,11 +380,11 @@ If confirmed: Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `
|
|
|
380
380
|
|
|
381
381
|
**Only runs for the Squash-merge and Discard options (3 and 5).** The PR, draft PR, and Keep options always preserve the worktree.
|
|
382
382
|
|
|
383
|
-
Use recorded `contract:` lines when the spec carries `## Legs`, including one member; apply
|
|
383
|
+
Use recorded `contract:` lines when the spec carries `## Legs`, including one member; apply [recorded cleanup ownership](reference/legs.md#recorded-cleanup-ownership) before the keyed path below. For a legacy spec without `## Legs`, read the gauntlet overrides file now (ladder in Project overrides) and its `## using-git-worktrees` section as the cleanup contract (keys written like `## cleanup` items: `using-git-worktrees/SKILL.md` Step 1a).
|
|
384
384
|
|
|
385
385
|
**Keyed contract** - the section has at least one of `- home:`, `- create:`, `- destroy:`:
|
|
386
386
|
|
|
387
|
-
1. Resolve `home:` against `$PRIMARY` (absent -> `$PRIMARY/.worktrees/<name>`; an absolute value is used as-is). `<name>` must appear exactly once, inside one path segment that may carry a literal prefix or suffix; otherwise stop and name the line.
|
|
387
|
+
1. Resolve `home:` against `$PRIMARY` (absent in legacy overrides only -> `$PRIMARY/.worktrees/<name>`; an absolute value is used as-is). `<name>` must appear exactly once, inside one path segment that may carry a literal prefix or suffix; otherwise stop and name the line.
|
|
388
388
|
2. Ownership match: canonicalize both sides (`realpath`) and compare `$WORKTREE` to the resolved pattern, treating the `<name>` segment as `<prefix>*<suffix>` where `*` matches the remainder of that one segment. The text `*` matched is `NAME` - the creation identifier (`jacek/fix-x` was created as `jacek-fix-x`; `home: ../acme-mono-<name>` recovers `fix-x` from `acme-mono-fix-x`). A pattern that cannot isolate one segment -> stop and report.
|
|
389
389
|
3. Match and `destroy:` set -> run it from `$PRIMARY` with `<name>` -> `'NAME'` and `<branch>` -> `'$FEATURE'`, each value one single-quoted shell word (`'...'`, an embedded `'` escaped), any other `<token>` resolved from context or asked once, never executed raw. Non-zero exit -> print its output, keep the branch, end this step; never fall back to `git worktree remove --force`. On success, run no `git worktree remove` or `prune`; continue to `git -C "$PRIMARY" branch -D "$FEATURE"`.
|
|
390
390
|
4. Match and no `destroy:` -> `git -C "$PRIMARY" worktree remove "$WORKTREE"` then `git -C "$PRIMARY" worktree prune`; after success, continue to `git -C "$PRIMARY" branch -D "$FEATURE"`.
|
|
@@ -442,7 +442,7 @@ A host-owned worktree (Step 6: no `home:` match, or the legacy "Otherwise") keep
|
|
|
442
442
|
|
|
443
443
|
**Cleaning up harness-owned worktrees**
|
|
444
444
|
- **Problem:** Removing a worktree the harness created causes phantom state
|
|
445
|
-
- **Fix:**
|
|
445
|
+
- **Fix:** Apply [recorded cleanup ownership](reference/legs.md#recorded-cleanup-ownership) for specs with `## Legs`; otherwise use Step 6's overrides or legacy ownership proof
|
|
446
446
|
|
|
447
447
|
**No confirmation for discard**
|
|
448
448
|
- **Problem:** Accidentally delete work
|
|
@@ -488,8 +488,8 @@ Once the merge (and any deploy) has landed, `/skill:check-delivery <ticket-ref>`
|
|
|
488
488
|
- Get typed confirmation for Option 5 (Discard)
|
|
489
489
|
- Clean up worktree for Options 3 & 5 (Squash-merge, Discard) only
|
|
490
490
|
- Target `$PRIMARY` with `git -C` for merge, worktree removal, and branch deletion
|
|
491
|
-
- Run `git -C "$PRIMARY" worktree prune` after removal
|
|
492
|
-
- Match `$WORKTREE` against
|
|
491
|
+
- Run `git -C "$PRIMARY" worktree prune` only after owned built-in removal
|
|
492
|
+
- Match `$WORKTREE` against `home:` for recorded blocks that have it; apply Step 6's default only to legacy overrides
|
|
493
493
|
- Surface the closure / conformance verdict as its own section before the options menu
|
|
494
494
|
|
|
495
495
|
## Project overrides
|
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Activation and authority
|
|
4
4
|
|
|
5
|
-
Read the home spec's `## Legs` once at Step 1. Use the membership, portable identifiers, scope validation and
|
|
5
|
+
Read the home spec's `## Legs` once at Step 1. Use the membership, portable identifiers, scope validation and [Locate a leg tree](../../brainstorming/reference/legs.md#locate-a-leg-tree) rules in the leg grammar. Resolve selected primaries from home's declared siblings; keep the session's home worktree and locate companions by recorded branch, regardless of a brief path or `home:`. Validate branch, repository identity and each companion's full `**Home:**` tuple before acting. Admit a missing delivered worktree only through a validated receipt below.
|
|
6
6
|
|
|
7
7
|
Use recorded `contract:` lines for every spec with `## Legs`, including one member. Amend the home block and affected companion file before using a changed contract; do not reread overrides to replace it. For one member, return to the ordinary finish steps using that block's contract: keep exactly one `### Leg:`, no companion artifact, `legs:` brief block, receipt, `--leg` argument or companion loop. For no `## Legs`, use the ordinary home-only flow and Step 6's overrides reread.
|
|
8
8
|
|
|
9
9
|
For more than one member, apply the following steps instead of the home-only verification, delivery and cleanup mechanics. Keep Step 3.5's disposition protocol, the home's review policy, Step 4 menu and confirmations. Keep machine-local paths out of committed bodies and messages.
|
|
10
10
|
|
|
11
|
+
## Recorded cleanup ownership
|
|
12
|
+
|
|
13
|
+
Apply this table to every recorded block, including a one-member spec, before Step 6's keyed path. Keep legacy specs without `## Legs` on the finish-time overrides reread. Use the recorded cleanup worktree command in preference to `destroy:` and retain the configured teardown hook's existing semantics; never replace recorded authority from current overrides.
|
|
14
|
+
|
|
15
|
+
| Block | Cleanup |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Has `home:` | Apply Step 6's existing ownership pattern match and recovered `<name>`, then `destroy:` or owned built-in removal; preserve unmatched host-owned trees and branches. |
|
|
18
|
+
| No `home:`, has `destroy:` | Run the recorded command from the leg's primary against the located tree: set `<name>` to its folder basename and `<branch>` to the recorded branch, each as one single-quoted shell word using Step 6's escaping; resolve other tokens from context or ask once. After the command, whatever its exit, read `git -C <primary> worktree list --porcelain`, test the folder's existence, and read `git -C <primary> rev-parse -q --verify refs/heads/<branch>`. Treat the tree as removed only when neither listed nor on disk. After confirmed removal, delete a remaining branch through finish's existing `git -C <primary> branch -D <branch>` step; otherwise keep it. Report the observed tree/ref state and any command failure, not success from exit alone. Run no built-in remove or prune fallback on any outcome. Draft-PR cleanup uses its own gated branch deletion instead. |
|
|
19
|
+
| Neither | Keep the host-owned tree and branch; run no cleanup command and report ownership. |
|
|
20
|
+
|
|
11
21
|
## Durable receipts
|
|
12
22
|
|
|
13
23
|
Keep one home-owned file per delivered leg at `<home git common dir>/gauntlet/receipts/<spec filename>/<repo>`, where `<home git common dir>` is `git -C <home worktree> rev-parse --path-format=absolute --git-common-dir` (the home primary's `.git`, e.g. `/work/repo-a/.git/gauntlet/receipts/shared.md/repo-b`) - never inside any worktree, so a removed home tree never takes a receipt with it. Include the full spec filename, including `.md`, and preserve repo path segments; create directories before writing. Git metadata is never tracked, so no exclude entry is needed. Treat them as flow restoration artifacts, not telemetry, approval evidence or proof without validation.
|
|
@@ -67,10 +77,10 @@ A squash with failed post-verification belongs under Not shipped with its create
|
|
|
67
77
|
|
|
68
78
|
## Discard and recorded cleanup - Steps 5 and 6
|
|
69
79
|
|
|
70
|
-
List every member's branch, commit count, and worktree path as a resolved absolute path (
|
|
80
|
+
List every member's branch, commit count, and located worktree path as a resolved absolute path (e.g. `/work/repo-b/trees/fix-x`; never a pattern or placeholder), or the lookup failure reason in place of a path, before one typed `discard` confirmation. Obtain exact confirmation once for the run, then clean every member, home included, through its recorded contract regardless of other members' refusals. Do not strip or seal for discard.
|
|
71
81
|
|
|
72
|
-
For cleanup,
|
|
82
|
+
For cleanup, apply [Recorded cleanup ownership](#recorded-cleanup-ownership) from each leg's primary. Retain its read-back rule even after a wrapper failure; a hook refusal leaves the wrapper unrun. Never bypass a wrapper or hook with `git worktree remove`.
|
|
73
83
|
|
|
74
|
-
Clean companions in declared order, then home. Report a refusal as that leg's `failed` line
|
|
84
|
+
Clean companions in declared order, then home. Report a refusal as that leg's `failed` line with its observed tree/ref state, preserve anything remaining, and continue the remaining cleanup attempts and report lines. After squash, stop only the refused companion's cleanup and attempt every remaining companion's recorded contract from its own primary; on any companion cleanup failure, skip home's cleanup and report `<home repo>: preserved - companion cleanup failed` to retain the home checkout for a fresh-session retry via /skill:gauntlet-resume. Delete a branch only after successful removal of its worktree. Run prune only for successful owned built-in removal, not after a wrapper. Report each repo's actual removed, preserved or failed state.
|
|
75
85
|
|
|
76
86
|
Remove receipts only after home delivery and all required cleanup succeed, and report that removal in one explicit line (`Home delivery and required cleanup succeeded; receipts removed`). Receipts live in the home primary's git dir, so worktree removal never touches them; when any required cleanup failed, report `receipts retained - required cleanup failed` and leave every receipt in place for the retry. PR/draft success has no cleanup requirement and preserves every worktree, so its receipts are removed right after the home PR lands. Keep retains receipts for later validation. Mark ship complete only after the chosen action succeeds for every member; never mark discard as shipped.
|
|
@@ -6,7 +6,7 @@ argument-hint: "[no argument: my open PRs] | <pr> [issue-ref] [--rebase [base]]
|
|
|
6
6
|
|
|
7
7
|
# gatekeep-pr
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Judge whether code, tests and docs at the assessed head make each promised behavior possible; leave observations requiring the merged change to `/skill:check-delivery`. Persist one course through `reference/post-selection-loop.md`'s run record; keep final merge/approval and posts separately selected. Before the initial pick, permit only provisioning and the explicit `--rebase` sync; steps 1-5 read, verify and draft. Execute later writes under a set course, terminal pick or the sync's `--rebase` authority. Running the verification command executes PR code with your ambient credentials and no sandbox - gate only PRs you are willing to execute.
|
|
10
10
|
|
|
11
11
|
## Arguments
|
|
12
12
|
|
|
@@ -28,8 +28,8 @@ Verify (step 3) and Review (step 4) each run as a fresh helper with `cwd` the PR
|
|
|
28
28
|
| 3 Verify | `verification-brief.md` Section B | evidence record (CI-first) and one disposition per material claim | `verify` |
|
|
29
29
|
| 4 Review | `verification-brief.md` Section C | reviewer findings and the internal comment ledger | `review` |
|
|
30
30
|
| 5 Integrate + report | `reference/post-selection-loop.md` `### Pre-menu refresh`, then `reference/findings.md`, then `reference/report.md` | AC outcomes, blockers, nits, drafted payloads, the rendered report | `report` |
|
|
31
|
-
| 6 Menu | `reference/
|
|
32
|
-
| 7 Loop | `reference/post-selection-loop.md` (delivery continues in `reference/fix-wave.md`) | the fixed delivery body until readiness, obstacle or cap; terminal picks and contract decisions through `reference/menus.md`; re-entry until stop | (re-opens the re-entered stage) |
|
|
31
|
+
| 6 Menu | `reference/menus.md` | state-selected action, final or post archetype; row 1 is the sole recommendation | `menu` |
|
|
32
|
+
| 7 Loop | `reference/post-selection-loop.md` (delivery continues in `reference/fix-wave.md`) | the fixed delivery body until readiness, obstacle or cap; terminal picks and contract decisions through `reference/menus.md`; re-entry until stop or completion of the terminal post set | (re-opens the re-entered stage) |
|
|
33
33
|
|
|
34
34
|
Re-entry: a fix wave's own push re-enters step 4 through the own-push sequence (`reference/fix-wave.md` `## Evidence after push`, then `reference/post-selection-loop.md` `### Re-render`); any other head move re-enters step 3; an unchanged head re-enters step 5 through `reference/post-selection-loop.md` `### Pre-menu refresh`. A loop re-entry never re-runs step 2b; the sync runs once per invocation.
|
|
35
35
|
|
|
@@ -47,38 +47,49 @@ For pi file-finding row dispatch, use `subagent({ agent: "loop-implementer", con
|
|
|
47
47
|
|
|
48
48
|
These bind every rendered report, menu, and external payload (review bodies, replies, commit subjects, tracker comments). A `## comms style` section in the overrides file extends them.
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
- Write for a reader with neither the code nor this run's notes open. Ground each claim in gathered facts; name the behavior and give one concrete example per problem. Explain a needed term in everyday words before using it.
|
|
51
|
+
- Write one or two whole sentences per finding: what is wrong, then why it matters. In a posted review body, trail each finding with its file and line in parentheses. Name files, lines and checks only where the reader must open or type them; keep exact supplied failing-test locators with their blocker.
|
|
52
|
+
- Omit empty sections. Use ASCII, American English, no hedges on checked facts and no intensifiers.
|
|
53
|
+
- Keep explanatory prose free of field names, run ids, commit ids and repair or sync counters outside `show evidence`; translate internal vocabulary and leave records unchanged. Write thread replies as plain sentences.
|
|
54
|
+
- Keep output unfenced. Preserve these exceptions verbatim: first-line markers, settlement rows, per-step result lines, typed commands, `[recommended]`, set queue/retirement lines, consent previews, the `AC coverage` heading and checkbox rows, and exact commands with substituted values in rows or closing messages. Keep repository-owned cleanup item text unchanged.
|
|
55
|
+
|
|
56
|
+
| Internal term | Say instead |
|
|
57
|
+
|---|---|
|
|
58
|
+
| binding pending check | a required check is still running |
|
|
59
|
+
| merge_state_status BLOCKED | GitHub won't let this merge yet |
|
|
60
|
+
| assessed head | the commit being reviewed |
|
|
61
|
+
| durable run record | saved progress |
|
|
62
|
+
| PR-named action | the step the PR asks for |
|
|
63
|
+
| coverage post | a comment saying which requirements the PR covers |
|
|
64
|
+
| withhold | the reason this cannot merge yet |
|
|
65
|
+
| terminal pick | your choice |
|
|
66
|
+
| post set | the steps you picked |
|
|
67
|
+
| disposition | how you classified the check |
|
|
68
|
+
| merge blocked, no bypass | GitHub reports the merge as blocked for you |
|
|
69
|
+
| bypass eligible | you can use GitHub's admin override |
|
|
70
|
+
| conflicting / behind | the branch conflicts with, or is behind, the base branch |
|
|
71
|
+
| evidence source ci / local | the checks ran in CI / on this machine |
|
|
72
|
+
| cap reached | the repair attempts allowed for this run are used up |
|
|
73
|
+
| nit | a smaller point that does not block merging |
|
|
74
|
+
| contradicted claim | the description says one thing and the code does another |
|
|
75
|
+
| observable half | the part that can only be seen after merge |
|
|
76
|
+
| deferred / deviates / elsewhere | the spec defers it, deliberately differs, or assigns it to another repo |
|
|
77
|
+
| pending reviewer placeholder | an automated review is still running |
|
|
78
|
+
|
|
79
|
+
### Output done-check
|
|
80
|
+
|
|
81
|
+
Before sending any report, menu or external payload, reread it for internal jargon, raw field/value pairs, labeled-field scaffolding and instructions for the human to run a command the skill can run. Rewrite those lines in plain language, preserve the facts and concrete step commands needed for a choice, and execute selected commands yourself. Treat commands for steps not run as information, never a request to paste them.
|
|
60
82
|
|
|
61
83
|
## Red flags - STOP
|
|
62
84
|
|
|
63
|
-
- A mutation without a set course, a terminal pick, or the sync's `--rebase` authority - owner: `reference/post-selection-loop.md` `### Continuation record`.
|
|
64
|
-
- A code or doc edit sitting in the worktree when a menu renders - except helper residue that `reference/fix-wave.md` `## Wave` names in the re-rendered menu - owner: `reference/findings.md` `## Drafted payloads`.
|
|
65
|
-
- Blocking on an AC's observation half, or on a PR-body claim the gate cannot check - owner: `reference/findings.md` `## AC outcomes`.
|
|
66
|
-
- Judging a ticket row the spec does not carry, or treating a spec `deferred: <ref>` row as a gap - owner: `reference/findings.md` `## AC outcomes`.
|
|
67
|
-
- Reading the rubric, the verification command, or any ladder source from the PR's head instead of the base branch's merge-base - owner: `reference/assessment.md` `## Configuration`.
|
|
68
|
-
- Raw command output, drafted payloads except the exact description consent preview, or internal IDs in the rendered report - owner: `reference/report.md`.
|
|
69
|
-
- A menu rendered under deliver before an exit condition, other than the contract-exception template; a menu not rendered from `reference/menus.md`, two recommendations, stop not last or no show evidence hint - owner: `reference/menus.md`.
|
|
70
|
-
- `cleanup` rendered on a non-terminal template, or cleanup steps 2-4 run on non-final stop - owner: `reference/cleanup.md` `## Non-final stop`.
|
|
71
|
-
- A CI watch outside D3 step 4 or before the first report, or a second push inside one iteration - owner: `reference/post-selection-loop.md` `### Next action`.
|
|
72
|
-
- The orchestrator resolving a merge conflict itself, or editing or committing a tracked file during a fix wave - owner: `reference/fix-wave.md` `## Sync` and `## Wave`.
|
|
73
|
-
- A helper's duty run in the orchestrator's own context - owner: `## Harness notes`.
|
|
74
|
-
- Approving your own PR - owner: `reference/decision-menu.md` `## Availability`.
|
|
75
85
|
- Merging around an undispositioned failing check or a binding pending check, or a merge-state withhold under `reference/post-selection-loop.md` `### Merge preconditions` - owner: `reference/findings.md` `## Dispositions`.
|
|
86
|
+
- A menu rendered under deliver before an exit condition, other than the contract-exception template; a menu not rendered from `reference/menus.md`, two recommendations, a recommendation not on row 1 or no show evidence hint - owner: `reference/menus.md`.
|
|
87
|
+
- `cleanup` rendered on a non-terminal template, or cleanup steps 2-4 run on non-final stop - owner: `reference/cleanup.md` `## Non-final stop`.
|
|
88
|
+
- Approving your own PR - owner: `reference/menus.md` `## final`.
|
|
76
89
|
- A menu rendered without the pre-menu refresh - owner: `reference/post-selection-loop.md` `### Pre-menu refresh`.
|
|
77
|
-
- Reading `mergeStateStatus` from anything but a `gh pr view` invocation, attributing a `BLOCKED` to a named rule, or treating a non-`BLOCKED` value as a merge verdict - owner: `verification-brief.md` Section A.
|
|
78
|
-
- A claim verdict recorded behind a pending tracker stage - owner: `## Progress tracking`.
|
|
79
90
|
|
|
80
91
|
## Project overrides
|
|
81
92
|
|
|
82
|
-
If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it once per session - a skill that already has the file's content in context from an earlier skill's read skips the read; a restored session has nothing in context and reads it. Read and apply `## conventions` whenever present, without a relevance judgment. Give this skill's named section precedence over conflicting `## conventions` rules. Use other relevant sections - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - to override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands. `## PR gate` keys are read in step 2 (`reference/assessment.md`); `## comms style` extends the wording rules. `## cleanup` steps
|
|
93
|
+
If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it once per session - a skill that already has the file's content in context from an earlier skill's read skips the read; a restored session has nothing in context and reads it. Read and apply `## conventions` whenever present, without a relevance judgment. Give this skill's named section precedence over conflicting `## conventions` rules. Use other relevant sections - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - to override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands. `## PR gate` keys are read in step 2 (`reference/assessment.md`); `## comms style` extends the wording rules. `## cleanup` items are separate steps selected through the post menu (`reference/menus.md` `## post`); execute them through `reference/cleanup.md`.
|
|
83
94
|
|
|
84
95
|
The recognized headings, their readers, and the rules an override cannot change are listed in the [configuration front door](../../README.md#project-specific-overrides); an override extends or replaces the step it names and never lifts this skill's HARD CONSTRAINT or MUST text.
|
|
@@ -28,7 +28,7 @@ With rebase requested, read the viewer via `gh api user --jq .login`. After fetc
|
|
|
28
28
|
|
|
29
29
|
Create the OS-temp roster with `mktemp "${TMPDIR:-/tmp}/gatekeep-roster.XXXXXX"`, never in a worktree. Store per PR number, worktree, record path, report path, status (`pending`, `report`, `conflicting`, `failed`, `stopped`, `retired`), reason, and queued pick. Pre-mint record/report paths outside worktrees.
|
|
30
30
|
|
|
31
|
-
Initialize each existing-format continuation record once: `consent.target` (lowercase base owner/repo, PR number, gathered baseRefName), PR identity, worktree, `course` null, `repair.rounds_used` and `repair.syncs_used` zero, `approved_head` null
|
|
31
|
+
Initialize each existing-format continuation record once: `consent.target` (lowercase base owner/repo, PR number, gathered baseRefName), PR identity, worktree, `course` null, `repair.rounds_used` and `repair.syncs_used` zero, `approved_head` null. Use the continuation-record schema; initialize `repair.rounds_cap` and `repair.syncs_cap` to `2 x` the resolved `closureReview.maxFixRounds` under D4 (`fix-wave.md` `## Wave`). Only the first course pick may resolve its initial D4 allowance; re-dispatch never reinitializes usage or caps. The parent owns only initialization and direct queued picks; the child owns all assessment and execution fields, findings, digest, evidence, repair state, approved head, payloads, and comment ledger. Carry confirmations and answers in task text only; never overwrite course, counters, caps, deadline, ledger, or helper paths on refresh or re-dispatch. Carry `repair.wave.spec` and `repair.wave.ledger` once created, with their row history and counters, through every private handoff; wave settlement retains the pair until terminal teardown. Validate supplied records using the continuation-record identity and finding-artifact rules: a missing locator or missing, unreadable or malformed artifact exits `stuck - run record unreadable`, never resets them.
|
|
32
32
|
|
|
33
33
|
## Foreground dispatch
|
|
34
34
|
|
|
@@ -76,24 +76,24 @@ Re-assess from steps 1-5 with the same record; substitute the answer at that ask
|
|
|
76
76
|
|
|
77
77
|
## Summary and menu round
|
|
78
78
|
|
|
79
|
-
The parent alone renders menus, gathers answers, and runs
|
|
79
|
+
The parent alone renders menus, gathers answers, and runs post/stop consequences. Render the summary once, after the children's closing lines and before the first menu, without a standalone report block before it. Preserve each supplied child report unchanged, including under show evidence. For each PR in roster order, print `#<N>` and copy the child's standing sentence unchanged on one line; add no verdict, evidence or blocker fields. For a child without a report, state its recorded conflict, failure or ask as a sentence. Describe a pending required check in that PR's deliver row; leave the supplied standing sentence unchanged. Follow with `Shared files:` and every changed path shared by two or more PRs, `<path> - #<N>, #<M>`. Include `#<N> - files unknown` for missing gathered files; print `none` when no path overlaps. Never schedule merges or choose landing order.
|
|
80
80
|
|
|
81
|
-
`#<N
|
|
81
|
+
Print each supplied child report file verbatim in roster order, each under its own `#<N>` heading and directly above that PR's queued menu from `menus.md`; add no synthetic `Verdict:` restatement at the menu turn. Render only the first PR's report and menu in the summary turn; collect each PR's pick before rendering the next PR's report and menu in a new turn. Never put two PRs' menus in one message or ask for all picks in one combined reply. Render each child's template from `menus.md`: reports with their template rows, conflicts through `menus.md` `## batch summary`'s recovered CONFLICTING template, failures with retry/evidence/stop, STOPPED with the recorded ask and stop. Apply `menus.md`'s row ordering to every child menu. For retry use exactly `retry - re-dispatch this PR's assessment with the same record`, recommended only after clean recovery and no rebase. Resolve the actual gitdir with git (a worktree .git can be a file); require empty `git -C <worktree> status --porcelain` and neither rebase-merge nor rebase-apply there. Otherwise omit retry and explain that the worktree is dirty or mid-rebase, naming the observed porcelain line or rebase directory.
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
Render one post menu per merged PR, each in its own message, using `menus.md` `## post`. Keep the batch summary in a separate message before these menus. Each post-menu message starts with `gauntlet: gate=gatekeep-pr/own-merge recommended=1`, never the batch-summary marker. Before substitution, assign a `## cleanup` item whose unresolved text holds none of `<issue>`, `<pr>`, `<merge-sha>` to the shared set: include it in the last merged PR's row 1 only, in roster order for this round. Offer its individual row on earlier merged PRs while it has not run. Keep PR-specific items with their PR. Record shared-item execution in the parent roster across rounds: a shared item runs at most once in the set. Omit it from later menus and skip it in queued picks only after its command runs with a recorded result, never because an earlier pick is queued.
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
Queue every parent-owned terminal pick (a post row or set of rows, merge, wait, stop) until every roster entry's pick for the round is collected. Print `Queued until all picks are collected (<roster summary>)` before the execution block for each queued pick, including a single-entry roster. Summarize each roster entry's collected pick or pending status inside `<roster summary>`.
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Show evidence in-place from retained record/helper paths and leave the same menu waiting. Queue all other picks and answers until the round's final pick. Record direct picks as the child's `course` or terminal selection; do not turn answers into grants. Execute queued terminal picks in roster order from the primary checkout through `post-selection-loop.md` `### Post steps`, preserving its step order, deduplication, guards, failed-step continuation and nested-skill pauses. Keep remaining steps and other PRs' queued picks waiting until a picked skill returns. The parent owns every post step, even after cleanup removes a PR worktree; exclude terminal picks from child dispatch and never use a removed worktree as cwd. Run no helper for terminal posts. Skip compare-and-swap only on merged or closed PRs; delegate approved/open reply freshness to `### Post steps`.
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
For `merge queued`, the parent handles `wait` after all picks: re-read `gh pr view <N> --json state,mergeCommit` per `post-selection-loop.md` `### Merge course`. On `MERGED`, persist `pr.state` and `pr.merge_commit` and render its one post menu under `own merge`; otherwise re-render `merge queued` with wait/stop and the evidence hint, without helper, child or CI watch. Next batch mixes retry/answered-ask `report` with ordinary nonterminal `execute` tasks, always the same record.
|
|
90
90
|
|
|
91
91
|
## Between batches and retirement
|
|
92
92
|
|
|
93
|
-
Run parent
|
|
93
|
+
Run parent post/stop consequences only after all children finish, never on a live child's tree. After all selected post steps finish for a PR, retire it with no re-render, including when a step failed. On stop retire it without running unpicked post steps. For non-final stop run `cleanup.md` `## Non-final stop`; under terminal overlays leave the checkout as found and print its leftover path/branch.
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
Before teardown, retain each PR's settlement row and per-PR not-run sentences from `post-selection-loop.md` `### Teardown` in the parent roster for the final message. Keep payload files for unrun or failed posts; delete only that PR's other helper/log files and record under those teardown rules. Start every PR retirement message, including the last, with `gauntlet: retired #<N> - <reason>`, without a terminal marker or settlement row; keep private child result lines unchanged. Await all next-batch results and render only nonretired PRs until all retire.
|
|
96
96
|
|
|
97
|
-
After the last PR retires and every selected
|
|
97
|
+
After the last PR retires and every selected step finishes, render one parent closing message. Start the message with `gauntlet: stuck retired` when any retained outcome is `stuck - <reason>`, otherwise `gauntlet: done retired`. Print every retained PR settlement row and its not-run sentences in roster order, including PRs retired in earlier rounds.
|
|
98
98
|
|
|
99
99
|
Initialize parent tracker tasks `pr-<N> state: <record path>`; mark in_progress on dispatch, complete on retirement, failed on unretried failure. Child trackers are session-local stages, not parent roster tasks. Use a plain checklist if plan_tracker is unavailable.
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# gatekeep-pr: cleanup
|
|
2
2
|
|
|
3
|
-
Read from `
|
|
3
|
+
Read from `menus.md` `## post` to resolve step guards and commands before numbering, and from `post-selection-loop.md` `### Post steps` to execute a picked cleanup, PR-named action or override. Input: the digest (`pr.url`, `pr.merge_commit`, `pr.state`, `pr.headRefOid`, `pr.baseRefName`, `issue.ref` or `issue: null`, `worktree`), the continuation record and merge-base overrides (`assessment.md` `## Configuration`). Return each result to the picked set's executor, not a menu.
|
|
4
4
|
|
|
5
5
|
**Landed** means `pr.state` is `MERGED`. **Primary** is the parent directory of `git -C <worktree.path> rev-parse --git-common-dir`; it is the checkout the session runs in. Never remove it and never change its branch. Run every git command as `git -C <primary>`; touch nothing under the removed worktree path after step 1.
|
|
6
6
|
|
|
7
|
-
Run the steps
|
|
7
|
+
Run only the picked step: cleanup executes steps 1-3 as one group, each override executes its own step-4 item, and a resolved PR-named action uses step 4's dispatcher. Keep guards in execution as well as row preparation. A failed sub-step prints its first error line and the loop continues; retry nothing. Before a picked PR-named action or `/skill:release` item, require step 3's synced result; run step 3 first when cleanup is not picked. A failed or skipped base pull yields `skipped - base not synced` for the dependent action.
|
|
8
8
|
|
|
9
9
|
1. **Worktree.** Eligible when `worktree.path` is not the primary, `git -C <worktree.path> status --porcelain --untracked-files=no` is empty (tracked-clean; untracked files never block removal), and - when landed - `git -C <worktree.path> log origin/<baseRefName>..HEAD` shows no commit outside the assessed head's history (`git -C <worktree.path> merge-base --is-ancestor HEAD <headRefOid>` succeeds). When the merge-base `## using-git-worktrees` section has at least one of `- home:`, `- create:`, `- destroy:` (the keyed contract), eligibility also requires the ownership match of `../../finishing-a-development-branch/SKILL.md` Step 6 (the recorded `worktree.destroy` already carries the recovered identifier): `home:` resolved against `$PRIMARY` (absent -> `.worktrees/<name>`), the `<name>` segment matched as `<prefix>*<suffix>` within one segment (`../acme-mono-<name>` against `/work/acme-mono-fix-x` recovers `fix-x`), `$WORKTREE` (the digest `worktree.path`) and the pattern both through `realpath`; an ambiguous match stops; no match -> `worktree: skipped - outside configured home, left at <path>` and the branch step reports it still checked out. Eligible and (`worktree.created` or landed) -> run `worktree.destroy` when recorded (from the primary; a non-zero exit prints `worktree: failed - <its output>`, keeps the branch (the branch step reports it still checked out), and never falls back to a forced removal), else `git worktree remove --force <worktree.path>` (the single `--force` removes a tree whose only dirt is untracked files; those files are deleted); then `git worktree prune`; print `worktree: done`. Reused and not landed -> `worktree: skipped - reused, left at <path>`. Dirty -> `worktree: skipped - uncommitted changes at <path>`. Commits beyond the assessed head -> `worktree: skipped - unmerged commits <shas> at <path>`. Under `approved` on a `rebased locally` head this step reports `unmerged commits` and leaves the tree, and `stop` leaves the rewritten local head in place and names it.
|
|
10
10
|
2. **Branch.** A non-zero `worktree.destroy` exit in step 1 -> `branch: skipped - worktree destroy failed`, whatever `git worktree list` shows. Landed, the branch exists locally, and no worktree holds it (`git worktree list --porcelain` lists no `branch refs/heads/<worktree.branch>`) -> `git branch -D <worktree.branch>`; print `branch: done`. Not landed -> `branch: skipped - PR not merged`. Still checked out -> `branch: skipped - checked out at <path>`. Never delete a remote branch.
|
|
11
11
|
3. **Base.** Landed, the primary is on `<baseRefName>`, and its tree is tracked-clean -> `git fetch origin` then `git pull --ff-only`; print `base: synced <sha>` when `git merge-base --is-ancestor <pr.merge_commit> HEAD` succeeds, else `base: failed - merge commit not on local <baseRefName>`. Primary on another branch -> `base: skipped - primary on <branch>`; dirty -> `base: skipped - uncommitted changes`; not landed -> `base: skipped - PR not merged`. Never switch the primary's branch.
|
|
12
|
-
4. **Override
|
|
12
|
+
4. **Override dispatcher**, invoked separately for each picked `## cleanup` item in list order. An item is `<label>: <text>`; any other shape -> `skipped - malformed item: <text>`.
|
|
13
13
|
- Landed-change guard first: not landed and the text contains `<merge-sha>` or `/skill:release` -> `skipped - needs a landed change`. The guard decides before any placeholder is read, so an item it skips never prints a `no <name> resolved` line, whatever its placeholders hold. A `/skill:release` item when step 3 did not print `synced` -> `skipped - base not synced`.
|
|
14
14
|
- Substitute: `<issue>` is `issue.ref` with a leading `#` stripped for the bare `#N` form (other forms verbatim); `<pr>` is `pr.url`; `<merge-sha>` is `pr.merge_commit`. A null `<merge-sha>` -> `skipped - needs a landed change` in both the cleanup row text and the result block. Other null values -> `skipped - no <name> resolved`: `skipped - no issue resolved`, `skipped - no pr resolved`. Any other `<...>` token -> `skipped - malformed item: <text>`. Insert each value as literal argument text: inside an existing quoted span verbatim; outside, single-quoted as one shell word.
|
|
15
15
|
- Text starting with `/skill:` -> invoke that skill with the rest of the text as its arguments, gates intact: the step's line is `<label>: invoked /skill:<name> - <where it paused or what it returned>` (for example `release: invoked /skill:release - paused at its level pick`) - never a `skipped` or `failed` line about skill availability, because the gate itself runs as a skill and every `/skill:` item is invokable; `/skill:release` with no level runs the skill's propose-then-pick gate; a level written in the item (`patch`, `minor`, `major`) authorizes the release without a pause. Any other text -> run it as a non-interactive shell command with cwd the primary, bounded by the resolved `timeout minutes` (default 15) through the Safety contract ladder of `../verification-brief.md` Section B; a timeout prints `failed - timed out after <n> minutes` and later steps still run.
|
|
16
16
|
|
|
17
|
-
With no
|
|
17
|
+
With no `## cleanup` section, offer no overrides. Build each row through `menus.md` `## post` with its resolved command and worktree removal's deletion of untracked files; keep overrides separate.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
For [Teardown's closing message](post-selection-loop.md#teardown), include each unpicked, skipped or failed cleanup sub-step's command: recorded `worktree.destroy` or `git -C <primary> worktree remove --force <worktree.path>`, `git -C <primary> branch -D <worktree.branch>`, `git -C <primary> fetch origin` then `git -C <primary> pull --ff-only`, and each `## cleanup` item's resolved command; repeat the executable command literally in each closing sentence, never an alias, reference to earlier text or retained worktree path. List a skipped sub-step even when its group was picked and all other steps ran.
|
|
20
20
|
|
|
21
21
|
## Non-final stop
|
|
22
22
|
|
|
@@ -4,7 +4,7 @@ Read from SKILL.md step 5, before `report.md`. Inputs: the digest, the step-2 `s
|
|
|
4
4
|
|
|
5
5
|
## Provenance
|
|
6
6
|
|
|
7
|
-
Local evidence: `worktree_root` matches the provisioned path, every `run_cwd` sits inside it, `head_sha` matches the digest's `headRefOid`. On mismatch, re-fetch the PR head once and re-sync + re-run steps 3-4 when it advanced; a second mismatch, or any path mismatch, is missing evidence.
|
|
7
|
+
Local evidence: `worktree_root` matches the provisioned path, every `run_cwd` sits inside it, `head_sha` matches the digest's `headRefOid`. On mismatch, re-fetch the PR head once and re-sync + re-run steps 3-4 when it advanced; a second mismatch, or any path mismatch, is missing evidence. Preserve the resolved evidence source in the record. In report prose, distinguish a local verification result from CI; never describe CI success as a local run (`report.md` `## Standing`).
|
|
8
8
|
|
|
9
9
|
## AC outcomes
|
|
10
10
|
|
|
@@ -12,25 +12,40 @@ Inputs: the digest's `scope` block (step 2: the spec's rows with dispositions an
|
|
|
12
12
|
|
|
13
13
|
Split each AC row once into a **mechanism half** (code + test + doc that make the behavior possible) and, when the row names an observation that needs an environment, dataset, deployed target, or external system that repository tests cannot reach, an **observation half**. Behavior a unit test can assert ("retries three times then fails", "rejects a nil name") is mechanism, never an observation half. A `venue:` row's mechanism half is judged like an `in-scope` row. Judge the mechanism half only; the observation half is checked after merge, not here, and blocks nothing.
|
|
14
14
|
|
|
15
|
-
| Outcome | Condition |
|
|
15
|
+
| Outcome | Condition | Report through `report.md` | Blocks |
|
|
16
16
|
|---|---|---|---|
|
|
17
|
-
| `covered` | evidence matches what the AC promises: executable behavior needs the code path plus a real test that exercises it; a documentation-only AC is judged against the promised doc text and demands no test; in both cases docs that describe the behavior agree with it |
|
|
18
|
-
| `gap` | any part of the mechanism absent in this PR for an `in-scope` or `venue:` row, a `deferred:` row with empty `ref`, or a Design clause |
|
|
19
|
-
| `not judged here` | the observation half; the mechanism half of the same row is still judged `covered`/`gap` |
|
|
20
|
-
| `deferred per spec` | a `deferred: <ref>` row with non-empty `ref` |
|
|
21
|
-
| `deviates per spec` | a `deviates: <why>` row; the Design clauses the `<why>` names or quotes are judged for mechanism like an `in-scope` row |
|
|
22
|
-
| `elsewhere per spec` | an `elsewhere: <repo>` row |
|
|
17
|
+
| `covered` | evidence matches what the AC promises: executable behavior needs the code path plus a real test that exercises it; a documentation-only AC is judged against the promised doc text and demands no test; in both cases docs that describe the behavior agree with it | covered behavior | no |
|
|
18
|
+
| `gap` | any part of the mechanism absent in this PR for an `in-scope` or `venue:` row, a `deferred:` row with empty `ref`, or a Design clause | missing behavior as a blocker | yes - a mechanism `gap` is a blocker |
|
|
19
|
+
| `not judged here` | the observation half; the mechanism half of the same row is still judged `covered`/`gap` | observation half is checked after merge, not here; write, list or hand nothing to check-delivery | no |
|
|
20
|
+
| `deferred per spec` | a `deferred: <ref>` row with non-empty `ref` | deferred behavior and its `ref` | no |
|
|
21
|
+
| `deviates per spec` | a `deviates: <why>` row; the Design clauses the `<why>` names or quotes are judged for mechanism like an `in-scope` row | deviation and its `why`; keep a missing adopted clause as one blocker | only an adopted clause's `gap` |
|
|
22
|
+
| `elsewhere per spec` | an `elsewhere: <repo>` row | external behavior and its `repo` | no |
|
|
23
23
|
|
|
24
24
|
The `design` section is always part of the judged contract: a Design requirement with no mechanism in the diff is a `gap` blocker whether or not an AC row points at it. A `deferred:` row whose `ref` is empty is a `gap` ("row <n> is deferred to no ticket, spec, or URL"); the gate checks the reference's shape only, never that its destination shipped - delivery is `/skill:check-delivery`'s job. A row the repository cannot satisfy is corrected in the spec (`deviates: <why>` through brainstorming's amendment path) and, for `/skill:check-delivery`, on the ticket through `/skill:shape-ticket`; this gate posts no tracker comment, and no ticket edit lifts a withhold.
|
|
25
25
|
|
|
26
|
-
**No spec rows** (`source: pr`, or `source: spec` with empty `rows`):
|
|
26
|
+
**No spec rows** (`source: pr`, or `source: spec` with empty `rows`): judge the PR's intent from its title and body and `design` when present; apply neither `not judged here` nor scope creep against rows. Render through `report.md`.
|
|
27
27
|
|
|
28
|
-
**Coverage.** With `source: spec`,
|
|
28
|
+
**Coverage.** With `source: spec`, retain covered, `deferred per spec`, `deviates per spec`, `elsewhere per spec` and observation-half outcomes; classify any other uncovered row as `gap`. Render through `report.md`. The spec's disposition is the record: a tracker comment, a PR named in the body, or a later PR never widens or narrows it, and a bare `deferred:` is never confirmed by the ticket.
|
|
29
29
|
|
|
30
30
|
**Claims.** Treat `contradicted` as a blocker and draft a scope-neutral exact description correction; when a correction would narrow either spec-owned or PR-owned scope, pause the correction and route to the explicit contract-decision course in `post-selection-loop.md` `### Continuation record`, retaining the independent mechanism blocker. Render `unverifiable-pre-merge` as optional non-blocking Description uncertainty naming what the gate cannot verify, not as a nit or proof. Assess supplied evidence; leave `matched`, explicitly pending observations, and qualitative prose alone. Never invent unperformed work or a future commitment. Draft requested factual clarification only after an explicit human request; preserve the assertion with the two-part replacement `Author's statement: <assertion> (not verified by this gate). Gate evidence: <evidence>`, rather than deleting it. Use pending-work wording only with an explicit record in the assessed body, approved spec, linked ticket, or request; conflicting records remain uncertain.
|
|
31
31
|
|
|
32
32
|
Treat a human body rewording dropping a mechanism sentence as a description defect; repair the description without amending untouched spec requirements. Keep spec-owned scope and independent mechanism blockers in force. Record a real proposed contract change and its paused continuation through `post-selection-loop.md` `### Contract decision`; limit it to the requested obligation, not omitted description mechanisms.
|
|
33
33
|
|
|
34
|
+
## PR-named steps
|
|
35
|
+
|
|
36
|
+
At step 5, record every sentence in the PR body or spec at the assessed head assigning the merger an action after merge. Keep each action's label and source sentences in `post_steps`; state each action in one report sentence. Leave observation-only acceptance or verification clauses and automatic deploy or release notes to `/skill:check-delivery`, not post steps.
|
|
37
|
+
|
|
38
|
+
Resolve commands only from merge-base files: the overrides file, `AGENTS.md`, and documents it links directly (one hop). Count a command only when the document names it for that action in the same sentence, list item or table row. Count distinct command strings; repeated citations of the same string count once. PR text triggers an action and never supplies its command.
|
|
39
|
+
|
|
40
|
+
| Resolution | Step |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Exactly one command with all tokens resolved | Mark runnable; substitute `<issue>`, `<pr>` and `<merge-sha>` through `cleanup.md` step 4. |
|
|
43
|
+
| No command, two or more distinct commands, or any unfilled token | Keep open; execute nothing for it. |
|
|
44
|
+
|
|
45
|
+
Before numbering, combine sentences naming the same action into one step retaining every source sentence. Match a resolved command against resolved `## cleanup` item text: keep one row at that item's place in list order, retaining the action's sources and mandatory inclusion in row 1. List each open action in the post menu and closing message with its reason and every source sentence, without a runnable row or a command borrowed from the PR.
|
|
46
|
+
|
|
47
|
+
Offer resolved steps through `menus.md` `## post`; execute picked steps through `cleanup.md`'s dispatcher after its base-sync prerequisite succeeds. Keep the resolved command and sources in `post_steps` through settlement.
|
|
48
|
+
|
|
34
49
|
## Namespaces
|
|
35
50
|
|
|
36
51
|
Every finding is one of two:
|
|
@@ -76,7 +91,7 @@ For an ancestor step-4 review, match each live inline `C#` comment id to `prior_
|
|
|
76
91
|
|
|
77
92
|
## Dispositions
|
|
78
93
|
|
|
79
|
-
Any blocking conclusion in the resolved check set (required or not - `../verification-brief.md` Section B, Evidence resolution table) withholds `merge` until the user dispositions it, and mints a `P#` - except the reviewer check, whose exception the brief's Section B defines (one `show evidence` line `reviewer check <name> failed - inert`). A **binding** pending check (`../verification-brief.md` Section B, binding classification) mints nothing and is not dispositionable: merge waits until it turns green, or `merge_state_status` leaves `BLOCKED`, or it converts to a failing check with its own `P#`. A not-binding pending check withholds nothing
|
|
94
|
+
Any blocking conclusion in the resolved check set (required or not - `../verification-brief.md` Section B, Evidence resolution table) withholds `merge` until the user dispositions it, and mints a `P#` - except the reviewer check, whose exception the brief's Section B defines (one `show evidence` line `reviewer check <name> failed - inert`). A **binding** pending check (`../verification-brief.md` Section B, binding classification) mints nothing and is not dispositionable: merge waits until it turns green, or `merge_state_status` leaves `BLOCKED`, or it converts to a failing check with its own `P#`. A not-binding pending check withholds nothing; render it through `report.md` under `show evidence` only, as `<name> pending - not binding this viewer (merge_state_status <value>)`; the `required` field stays gathered and no longer withholds on its own.
|
|
80
95
|
|
|
81
96
|
| Disposition | Annotation on the `P#` |
|
|
82
97
|
|---|---|
|
|
@@ -87,7 +102,7 @@ Any blocking conclusion in the resolved check set (required or not - `../verific
|
|
|
87
102
|
|
|
88
103
|
Only `flaky` lifts the blocker; an undispositioned check, `real`, and `ci-infrastructure-broken` keep it until the check - or, for `ci-infrastructure-broken`, the fallback local run (brief Section B, Failed CI row) - is green.
|
|
89
104
|
|
|
90
|
-
Record dispositions only from direct human check commands. A flaky disposition followed by numeric deliver can resume; no helper can disposition a check. With BLOCKED, no eligible bypass under `post-selection-loop.md` `### Merge preconditions`, and no dispositionable local repair, render the obstacle template from `menus.md`, even with course unset, and
|
|
105
|
+
Record dispositions only from direct human check commands. A flaky disposition followed by numeric deliver can resume; no helper can disposition a check. With BLOCKED, no eligible bypass under `post-selection-loop.md` `### Merge preconditions`, and no dispositionable local repair, render the obstacle template from `menus.md`, even with course unset, and explain that GitHub blocks this actor from merging and no local repair applies. Keep raw merge-state and review values under `show evidence`; never attribute a named rule.
|
|
91
106
|
|
|
92
107
|
## Drafted payloads
|
|
93
108
|
|
|
@@ -97,4 +112,4 @@ Extend each finding-keyed evidence pack with `target: file | description`. For f
|
|
|
97
112
|
|
|
98
113
|
A payload is the smallest in-repo edit that turns the finding green and keeps the behavior the PR promises; it never adds infrastructure, a dependency, or a new module. A failure caused outside the repo (image pull, toolchain, credentials, external service) gets the smallest in-repo workaround with its reason in one sentence; a skip never removes a test an AC row relies on. Keep a finding whose smallest fix needs another repo, infrastructure, or a credential open with the `loop-implementer` failed decision's `needs <what>` second slot on pi, or the native helper's `open - needs <what>` sentence on Claude Code. A delivery course applies a description payload alongside the file payloads through `post-selection-loop.md` `### Description repair`; show compact exact old-to-new text under the blocker and the full replacement body under `show evidence`. Apply a requested factual clarification only within selected course work; mint no fake blocker. Never draft an unsolicited style rewrite.
|
|
99
114
|
|
|
100
|
-
Compose a posted review body at post time from the blockers being addressed
|
|
115
|
+
Compose a posted review body at post time from the blockers being addressed through SKILL.md `## Wording rules`. For a carried open blocker backed by a pi row, include `open - <last decision line>` on its item so the next run's prior review retains the failed-attempt knowledge.
|