pi-gauntlet 7.30.0 → 7.31.0

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v7.31.0 - 2026-10-23
4
+
5
+ ### Added
6
+
7
+ - **`gatekeep-pr` accepts a set of PRs in pi**, for example `/skill:gatekeep-pr 12 15 18 --rebase main`. One fresh `pr-gatekeeper` orchestrator and worktree per PR keep nested Verify/Review dispatch and consent isolated; the parent shows a summary and ordered per-PR menus, then runs queued picks in parallel. Sets are bounded by pi-cohort's `parallel.maxTasks` (default `8`), with one eligible-other-author rebase confirmation per set. Single-PR behavior is unchanged; multi-PR mode is pi-only. Requires pi-cohort >= 7.4.5 (a `subagent`-enabled persona could not start with inherited extensions before, [pi-cohort #26](https://github.com/jjuraszek/pi-cohort/issues/26)). (#79)
8
+
3
9
  ## v7.30.0 - 2026-10-23
4
10
 
5
11
  ### Added
package/README.md CHANGED
@@ -73,14 +73,14 @@ Everything between gate 1 and gate 2 - task breakdown, implementation, both revi
73
73
 
74
74
  ## Architecture
75
75
 
76
- `gatekeep-pr` retains explicit, action-scoped `fix` and `merge base` grants for one run so covered repairs can continue to a fresh final menu. Bare `fix` covers source-verified blockers within the agreed scope; named fixes retain only their selected IDs for later reassessments. Nits are one-shot. Final merge, approval, external posts, workflow approval, check dispositions, and contract changes require separate decisions. Exact PR-description corrections are `fix` targets that require exact-text selection and readback plus a narrow recheck; they cannot clear independent test or scope blockers. See the [next-action and consent protocol](skills/gatekeep-pr/reference/post-selection-loop.md).
76
+ `gatekeep-pr` retains explicit, action-scoped `fix` and `merge base` grants for one run so covered repairs can continue to a fresh final menu. Bare `fix` covers source-verified blockers within the agreed scope; named fixes retain only their selected IDs for later reassessments. Nits are one-shot. Final merge, approval, external posts, workflow approval, check dispositions, and contract changes require separate decisions. Exact PR-description corrections are `fix` targets that require exact-text selection and readback plus a narrow recheck; they cannot clear independent test or scope blockers. See the [next-action and consent protocol](skills/gatekeep-pr/reference/post-selection-loop.md). In pi, `/skill:gatekeep-pr 12 15 18 [--rebase [base]]` gates a set of PR numbers or same-repository URLs, with one fresh `pr-gatekeeper` child and one worktree per PR. The parent shows a summary and unchanged per-PR menus in input order, queues every pick until the last menu, then executes the queued work in parallel. The set must fit pi-cohort's `parallel.maxTasks` (default `8`); it is never chunked. With `--rebase`, the parent asks once per set for eligible other-author or unreadable-author heads, excluding no-op heads and heads with merge commits. Multi-PR mode rejects positional issue references and is pi-only; single-PR behavior on Claude Code is unchanged. See the [parent-child contract](skills/gatekeep-pr/reference/batch.md).
77
77
 
78
78
  The run's grants, target/scope baseline, repair usage, and poll deadline live in one OS temporary continuation record, whose path appears in the tracker or checklist and `show evidence`. Missing or invalid state pauses authority without resetting the budget. Terminal exit deletes the record; OS cleanup can remove it earlier, and a new session never discovers authority automatically. This is a skill protocol, not hard runtime enforcement.
79
79
 
80
80
  pi-gauntlet ships three kinds of pieces, layered on top of pi-cohort's dispatch:
81
81
 
82
82
  - **21 skills** - the workflow logic. Sixteen activate automatically when pi sees the matching kind of task, and the workflow skills chain through their gates: `shape-ticket` (creates one tracker issue or repairs a comma/whitespace list of refs against a Context/Problem/Idea/Acceptance-Criteria template, with a grounded repo audit, an AC integrity check, a cheap council roast, and sequential per-ticket exact-diff write confirmations; model-invocable so other skills and commands can route "file a ticket" to it, the gate still needs your yes), `gatekeep-pr` (model-invocable on an explicit ask that names the PR and the verb; the gates still need your selection - is consent-gated pre-merge verification of a PR against the scope contract at its head - the approved spec's acceptance-criteria dispositions and Design when the PR carries one, else the PR's stated intent; the ticket is cross-checked, never judged here (`check-delivery` owns it) - read-only gathering, verification evidence resolved CI-first (green checks on the exact assessed head count as evidence; a pending commit status that GitHub does not report as blocking the gating actor (`mergeStateStatus` not `BLOCKED`) is not waited for - external-CI commit statuses included - while a running Actions check, an unknown merge state, and every other merge precondition still withhold; the project's verification command runs only as fallback), a rubric-based review, a compact bottom-up report (what the PR delivers, including rows deferred or deviating per spec, PR comments, nits, blockers, then a `mergeable` / `fixable` verdict) and a verb menu whose rows derive from the actor's permissions on the PR; nothing mutates (fixes, pushes, reviews, merges, tracker comments) until you pick a row, except the opt-in `--rebase [base]` sync that rebases, reviews, and lease-pushes the head before verification, or holds the rebased head locally when a conflict stop's scoped tests fail, so the normal `fix` row resolves it before the lease push; after your own merge two opt-in rows post the `AC coverage` block to the ticket or the PR; every terminal menu offers a recommended `cleanup` row that tears down the gate's worktree and branch and runs the overrides file's `## cleanup` steps - run it with `/skill:gatekeep-pr <pr> [--rebase [base]]`), `check-delivery` (model-invocable on an explicit ask that names the ticket and the verb; the gates still need your selection - is a post-merge detective control: proves an issue actually shipped (default-branch landing, delivery target, per-AC evidence) before its tracker status advances; it never writes a terminal status - run it with `/skill:check-delivery <ref>`), `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `loop-implementation` (the plan-free implement driver that iterates a fresh `loop-implementer` over the spec's acceptance-criteria ledger when approval picks the loop engine), `dispatching-parallel-agents`, `verification-before-completion`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `forge-skill`, `linear` (reads/searches/comments on/manages Linear tickets via the `linearis` CLI; owns all linearis mechanics and the `## Issue tracker` overrides schema; tracker-facing skills route to it). Five more require explicit entry (`disable-model-invocation: true`): `brainstorming` starts the gated workflow on explicit consent - use `/skill:brainstorming` for reliable discovery, or opt in through reachable explicit prose or a human-selected handoff; after spec approval, downstream planning and implementation still chain automatically. `chase-bug` is human-only bug triage: read-only root-cause discovery to an evidenced verdict menu (real bug -> ticket/brainstorm/hotfix/respond; five negative verdicts), then a gated response to the reporter for addressable origins (GitHub issue / tracker ticket) and a rendered verdict summary otherwise - it never fixes during triage; the hotfix row hands off to `skills/chase-bug/hotfix.md` after the menu - run it with `/skill:chase-bug`. `gauntlet-performance` reads the committed run telemetry (current repo by default, `--dir <path>` adds others) through the parse-only `gauntlet-performance` CLI and answers with one example-led recommendation, 3-5 cornerstone numbers, a council assessment when available, and a menu of at most three actions (render a report file, open the recommendation as a ticket via `shape-ticket`, drill into one run); it writes nothing unless you pick render - run it with `/skill:gauntlet-performance [--dir <path>]... [--since <version>]`. `gauntlet-handoff` ends a session whose flow a fresh session will continue: it invokes pi-cohort's `handoff` skill (`--out <path>` or `--key <name>`, default key = the run worktree's branch with `/` flattened to `-`, default file `<tmpdir>/pi-handoff/<key>.md`), then appends the gauntlet process-state section (phase/plan tracker status) per the shared contract `skills/gauntlet-resume/reference/brief-contract.md` - run it with `/skill:gauntlet-handoff [--out <path> | --key <name>]`. `gauntlet-resume` is the only way back into an interrupted flow from a fresh session: it takes a `gauntlet-handoff` brief (a file path, pasted text, or - with no arguments - a pick from the briefs under `<tmpdir>/pi-handoff/`), a bare worktree that already holds a spec, or a spec tracked on main under a configured spec dir (a spec seed: it creates or reuses the worktree through `using-git-worktrees` and pins the spec), restores phase/plan tracker state through the legal arming sequence (`start brainstorm`, `skip` with `resume:` reasons, `plan_check` before implement-or-later), and never infers approval from artifacts - run it with `/skill:gauntlet-resume [<brief-file> | <spec>.md | <worktree-name-or-path>]`.
83
- - **10 subagent personas** - the specialized child agents the skills dispatch via pi-cohort: `implementer`, `loop-implementer`, `code-reviewer`, `spec-reviewer`, `conformance-reviewer`, `spec-summarizer`, `plan-writer`, `spec-council-member`, `spec-council-synthesizer`, `spec-council-applier`. See [doc/personas.md](./doc/personas.md) for what each one does and why its permissions are scoped the way they are.
83
+ - **11 subagent personas** - the specialized child agents the skills dispatch via pi-cohort: `implementer`, `loop-implementer`, `code-reviewer`, `spec-reviewer`, `conformance-reviewer`, `spec-summarizer`, `plan-writer`, `spec-council-member`, `spec-council-synthesizer`, `spec-council-applier`, `pr-gatekeeper`. See [doc/personas.md](./doc/personas.md) for what each one does and why its permissions are scoped the way they are.
84
84
  - **4 runtime extensions** - the enforcement layer. `plan-tracker` and `phase-tracker` are tools skills call to track progress (with a TUI widget); `verify-before-ship` is a hook that warns if you push or open a PR without a passing test run since your last edit; a phase-tracker flow guard reminds on implement-phase commits missing spec/code review. In a brainstorming-entered flow, phase-tracker rejects `implement` or `verify` completion while tracker tasks remain pending or in progress; see [its configuration reference](./doc/configuration.md#phase-tracker). phase-tracker also registers `plan_check`, which verifies a plan against its spec and against the grammar in [skills/writing-plans/reference/plan-contract.md](./skills/writing-plans/reference/plan-contract.md), including that each task's `Tests:` commands are selective and never the full suite, and that every test command carries a passing base-commit result; a pass stamps the plan for implementation. `telemetry` records one YAML record per gauntlet run (phase timing, models, personas, gate/fix rounds, diff at ship) that ships in the squash beside the spec - it is written only inside a brainstorming-entered flow, kept out of history until `finishing-a-development-branch` seals it once with `gauntlet-telemetry-seal` (a `telemetry:` commit under git; the working-copy snapshot in a plain jj workspace) - and blocks a brainstorm `write` into an already-shipped spec; see [its configuration reference](./doc/configuration.md#telemetry). See [doc/configuration.md](./doc/configuration.md) for the settings each one reads.
85
85
 
86
86
  pi-gauntlet is **opinionated**: it recommends this pipeline for non-trivial changes, but starts `brainstorming` only after explicit user consent. Enforcement is opt-in by entry, not ambient: once brainstorming starts a flow, the phase-tracker extension mechanically blocks a phase from closing before its gate runs, and warns once if the main loop writes code during implement (subagents own implement-phase edits). A change made *without* entering the flow (a typo, a formatting run, a dependency bump - see "When to use / when NOT to use") is not gated; the discipline of routing real work through the pipeline is a convention the tooling supports, not a trap it springs on every edit.
@@ -124,7 +124,7 @@ Run by a human against pi-cohort >= 7.1.0, before a pi-gauntlet release claims t
124
124
  ## Requirements
125
125
 
126
126
  - [pi-coding-agent](https://github.com/earendil-works/pi) ≥ 0.85.1 - tested minimum for sequential `phase_tracker` tool execution, which persists a tracker update before a later tool call in the same model message.
127
- - [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.4.5 - required peer package, including binary-safe worktree patches. Skills that dispatch agents (`requesting-code-review`, `subagent-driven-development`, `dispatching-parallel-agents`, `writing-plans`, `forge-skill`, `shape-ticket`, `roasting-the-spec`) call `subagent({})`, which pi-cohort provides. pi-gauntlet does not vendor the dispatch tool; without pi-cohort those skills have nothing to call. Gauntlet execution dispatches explicitly use `async: false`; do not enable pi-cohort's incompatible `forceTopLevelAsync` setting. See pi-cohort's [dispatch configuration](https://github.com/jjuraszek/pi-cohort/blob/main/doc/configuration.md) for that setting's owner and semantics. A wave of N >= 1 tasks dispatches its implementers and first spec reviews as one chain call. `subagent-driven-development` stops before dispatch on unsupported installs; there is no older-runtime fallback.
127
+ - [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.4.5 - required peer package, including binary-safe worktree patches; it also lets a persona with `subagent` in `tools:` start with inherited extensions ([pi-cohort #26](https://github.com/jjuraszek/pi-cohort/issues/26)), which multi-PR `gatekeep-pr` needs. Skills that dispatch agents (`requesting-code-review`, `subagent-driven-development`, `dispatching-parallel-agents`, `writing-plans`, `forge-skill`, `shape-ticket`, `roasting-the-spec`) call `subagent({})`, which pi-cohort provides. pi-gauntlet does not vendor the dispatch tool; without pi-cohort those skills have nothing to call. Gauntlet execution dispatches explicitly use `async: false`; do not enable pi-cohort's incompatible `forceTopLevelAsync` setting. See pi-cohort's [dispatch configuration](https://github.com/jjuraszek/pi-cohort/blob/main/doc/configuration.md) for that setting's owner and semantics. A wave of N >= 1 tasks dispatches its implementers and first spec reviews as one chain call. `subagent-driven-development` stops before dispatch on unsupported installs; there is no older-runtime fallback.
128
128
 
129
129
  Both packages must be listed in your `.pi/settings.json#packages` array (pi adds them automatically when you `pi install`). pi-gauntlet and pi-cohort are versioned independently but release together whenever dispatch semantics change - pin compatible versions of both. At each pi-gauntlet release, set the pi-cohort peer minimum and README floor together to the newest released pi-cohort version; `/skill:release` checks the registry before proceeding.
130
130
 
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: pr-gatekeeper
3
+ description: "runs one PR of a gatekeep-pr multi-PR set to its report or executes one queued pick. Not for direct dispatch."
4
+ tools: read, grep, find, ls, bash, edit, write, subagent, gauntlet_setting, plan_tracker
5
+ defaultContext: fresh
6
+ inheritProjectContext: true
7
+ inheritSkills: false
8
+ systemPromptMode: replace
9
+ completionGuard: false
10
+ ---
11
+
12
+ Run one supplied PR to its report or execute one queued pick. Keep each PR isolated so helpers, evidence, and authority never cross into a sibling. Return one result line, never a human menu or a question.
13
+
14
+ Use the supplied record and report paths only. Never re-initialize a supplied record or mint a second record/report. Validate repository/number identity, worktree, and HEAD before work. Treat the injected skill and batch contract as the procedure; use the supplied mode, PR, base, rebase flag, confirmation, optional answer, and paths. Read the injected procedure's named dependencies using the caller-supplied absolute procedure root or absolute paths. Do not discover unrelated skills or procedure files.
15
+
16
+ ## Method
17
+
18
+ - In `assess`, run steps 1-5 in the provisioned worktree. Skip the already completed provisioning fetch/gitignore/add only; verify HEAD against the supplied headRefOid and preserve sync's safety fetch. Keep trusted merge-base configuration and assessed-head binding. Dispatch Verify then Review sequentially as fresh helpers with cwd the same worktree, never new helper worktrees.
19
+ - In `execute`, refresh before writing. If the head moved or the picked row disappeared, return a fresh report without executing the stale pick. Otherwise run step 7 and its next-action/fix-wave loop. Keep retained grants, round caps, deadline, ledger, helper paths, and no-progress decisions PR-local. Never reset consent or counters on re-entry.
20
+ - Substitute supplied rebase confirmation at the existing ask only: yes proceeds; no records `sync: declined - other author's branch`, stage skipped, then assesses unsynced. Use supplied `verification command: <command>` or `spec: <path>` at that ask only, re-assessing from the start with the same record. Never treat answers as broader authority.
21
+ - Track single-PR stages with session-local plan_tracker or a checklist. Delegate tracked source edits and commits to implementer; perform only orchestrator writes authorized by the injected procedure. Never push, edit PR metadata, comment, review, or write to a tracker before direct human authority, except the requested sync push. Never choose a sibling's actions.
22
+
23
+ ## Recovery and output
24
+
25
+ Apply the injected batch-only outcome adapter without changing single-PR behavior. On sync failure first run the existing recovery to restore pre_head and assert exact HEAD and a clean tree. Never retry unsafe checkout or continue after a failed recovery assertion.
26
+
27
+ | Event | Result |
28
+ |---|---|
29
+ | Unresolved stop, implementer open, residue, or sync reviewer finding | After recovery record sync failure; no rendered report; CONFLICTING |
30
+ | Rebase command or server push rejection | After recovery FAILED with sync reason |
31
+ | Terminal sync precondition, baseline mismatch, lease refusal | FAILED with sync reason, never conflict |
32
+ | Without rebase, false/unreadable pushability | FAILED before Verify, naming head destination |
33
+ | Required fallback verification unavailable | FAILED with no-verification-evidence reason |
34
+ | Empty, off-contract, non-zero, or async helper output | FAILED naming helper role and quoted failure |
35
+ | Other steps 1-5 and 7 outcomes | Write supplied report and return REPORT |
36
+
37
+ Return only the enumerated pre-report asks: `STOPPED - verification command - <subproject dirs seen>` or `STOPPED - spec candidate - <paths>`. Stop without further writes at the ask. UNKNOWN merge state after the single re-poll returns a report with merge withheld. Return reports for step-7 contract, no-progress, and budget menus. Leave all menus, confirmations, answers, cleanup, stop consequences, and retirement to the parent; never tear down a live child's tree.
38
+
39
+ Write the rendered report only to the supplied path. For CONFLICTING leave that report unrendered and include the sync record. Make exactly one of these the last line, with nothing after it: `REPORT <report path>`, `CONFLICTING <report path> - <sync record>`, `FAILED - <reason>`, `STOPPED - <ask> - <what the user must supply>`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "7.30.0",
3
+ "version": "7.31.0",
4
4
  "description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
5
5
  "author": "Jacek Juraszek",
6
6
  "type": "module",
@@ -10,6 +10,7 @@ Verify, don't trust: a PR description is a claim, and over-claimed coverage, hal
10
10
 
11
11
  ## Arguments
12
12
 
13
+ - Route two or more PR tokens (numbers or URLs, space-separated, before any `--rebase`) through the set-routing row before steps 1-7; reject a positional issue reference in a set with a one-line error. Apply `--rebase [base]` to every PR in the set; keep zero or one PR token on the existing single-PR path below.
13
14
  - PR number or URL; omitted -> resolved from the current branch per `verification-brief.md` Section A.
14
15
  - Optional issue reference; omitted -> resolved in step 1 (`verification-brief.md` Section A) and fetched in step 2; none found -> select the scope contract in step 2 (spec at the head, else the PR's stated intent), never invent acceptance criteria.
15
16
  - Optional `--rebase [base]`, parsed after `<pr> [issue-ref]`: the token after it, when present, is the base branch name (`123 --rebase gh-45` means base `gh-45`, not an issue ref); absent, the base is the digest's `baseRefName`. Step 2b fetches `origin/<base>` and validates it: a missing ref stops with a one-line error before any rebase or push. Without `--rebase` the run performs no additional fetch, rebase, or push before a menu pick and renders no sync line.
@@ -20,6 +21,7 @@ Verify (step 3) and Review (step 4) each run as a fresh helper with `cwd` the PR
20
21
 
21
22
  | Step | Read now | Output | Tracker stage |
22
23
  |---|---|---|---|
24
+ | Set routing | `reference/batch.md` | pi-only admission and isolated per-PR assessment, summary, queued menus, and execution for two or more PRs; return through that procedure | - |
23
25
  | 1 Gather | `verification-brief.md` Section A | PR digest: metadata, diff, checks, comments, worktree discovery | `gather` |
24
26
  | 2 Provision + configure | `reference/assessment.md` | provisioned worktree; config resolved from the merge-base; ticket fetched; the `scope` block selected (spec rows and `design`, or stated intent) | `provision` |
25
27
  | 2b Sync (only with `--rebase`) | `reference/sync.md` | the PR worktree on the rebased, pushed head with a refreshed digest, or a `sync` record and the unsynced head, or a rebased, unpushed head (`rebased locally`, `complete`) | `sync` |
@@ -0,0 +1,91 @@
1
+ # gatekeep-pr: multi-PR parent-child contract
2
+
3
+ Use this contract only for two or more PR tokens. Keep the single-PR path and its duties unchanged. The parent owns admission, primary-checkout provisioning, human menus, and teardown; each child owns one PR's assessment and execution.
4
+
5
+ ## Admit before effects
6
+
7
+ Reject with a one-line error before any fetch, confirmation, provisioning, or dispatch: positional issue references, duplicate identities (normalize number and URL to the same repository/number), URLs from different repositories or not matching origin, an oversized set, and Claude Code. Multi-PR mode requires pi's nested dispatch. Resolve each issue from its PR, never from a positional issue argument.
8
+
9
+ Read the active pi-cohort configuration's `parallel.maxTasks`, default `8`; gauntlet_setting is not its source. Never chunk the set. For an oversized set print exactly:
10
+
11
+ `multi-PR mode takes at most <max> PRs (pi-cohort parallel.maxTasks); got <n>`
12
+
13
+ Gather each PR with `gh pr view --json number,author,headRefOid,headRefName,baseRefName,isCrossRepository,headRepository,state,files`. Resolve trusted worktree configuration from the base merge-base, never from PR-controlled files.
14
+
15
+ ## Provision serially
16
+
17
+ Fetch origin once with `git fetch origin`; for each fork PR, run `git fetch origin pull/<N>/head:pr-<N>` only when no worktree holds a local `pr-<N>` branch, and otherwise leave the reuse row's `git fetch origin pull/<N>/head` + `git merge --ff-only FETCH_HEAD` to that PR's provisioning step. Apply assessment's gitignore-first rule before built-in creation when the resolved home is inside the primary; sibling homes need no edit. Provision in roster order, one at a time. No concurrent primary fetch or worktree add is allowed, regardless of cohort concurrency.
18
+
19
+ Reuse assessment's provisioning table unchanged: reuse an expected branch at any path, fast-forward only, stop on dirt, divergence, local-only commits, or foreign operations; never repurpose a foreign branch at the default path. Resolve keyed home/create/destroy with `<name>` = `pr-<N>`, shell-quote tokens, check the created path in `git worktree list --porcelain`, and verify `HEAD == headRefOid`. A non-zero create marks that PR failed; never fall back to worktree add. Ask unresolved create tokens in the parent once per token, never execute unresolved placeholders. Isolate `failed - provisioning - <reason>` with no child; continue siblings. A provisioning retry re-provisions only after the obstacle clears.
20
+
21
+ With rebase requested, read the viewer via `gh api user --jq .login`. After fetch exclude sync preconditions 4-5 from confirmation: heads already containing origin/base and heads containing merge commits. Compare `git merge-base --is-ancestor origin/<base> <headRefOid>` and `git rev-list --merges origin/<base>..<headRefOid>`. List only remaining other-author or unreadable-author PRs. Explain once that replay changes SHAs and committer identity, can outdate anchored comments, and can dismiss approvals; ask yes once for the set. No eligible PR means no question. Supply each task `rebase confirmation: yes | no | not asked`. Keep sync's own safety fetch and baseline checks; skip duplicate provisioning only.
22
+
23
+ ## Private handoff
24
+
25
+ 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.
26
+
27
+ Initialize each existing-format continuation record once: `consent.target` (lowercase base owner/repo, PR number, gathered baseRefName), PR identity, worktree, grants null, rounds zero, `approved_head` null, `cleanup_done` false. Use the existing field schema, no new schema. 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 grants, counters, deadline, ledger, or helper paths on refresh or re-dispatch. Validate supplied records using the continuation-record identity rules, never reset them.
28
+
29
+ ## Foreground dispatch
30
+
31
+ Dispatch one foreground fresh `subagent` tasks batch, one `pr-gatekeeper` task per provisioned PR. Use `async: false`, `context: "fresh"`, each PR's worktree as cwd, and `skill: "gatekeep-pr"` for explicit injection. Use per-task `acceptance: { level: "none", reason: "the gatekeep child result line is the handoff contract" }`; the persona's completionGuard pin is separate. Let cohort concurrency bound running tasks, not alter membership.
32
+
33
+ Supply mode `assess` or `execute`, PR identity, rebase flag/base, confirmation, optional answer, record/report paths, queued pick for execute, and this statement:
34
+
35
+ `worktree provisioned at <path> on <headRefOid>; fetch and gitignore done - skip the fetch, run no worktree add, verify HEAD`
36
+
37
+ Supply the skill and this batch contract explicitly; do not depend on child discovery. Derive the installed procedure root from the selected skill's absolute `filePath` metadata (the path returned by the runtime's skill resolution), taking the directory containing `SKILL.md`. Supply `procedure root: <absolute installed skill directory>` in every assess and execute task. Resolve all named procedure dependencies relative to this root, never the PR worktree or cwd; this includes sibling briefs and baseline files as well as files under `reference/`. Assess runs steps 1-5 with sequential fresh Verify then Review in the supplied worktree, never separate helper worktrees. Preserve trusted configuration, digest/head binding, and PR-local tracking. Delegate tracked source edits and commits to implementer. Execute refreshes first, then runs step 7 using the existing next-action/fix-wave rules. Refresh before any execute write: if HEAD moved or the row is unavailable, return a fresh report instead of doing the stale action. Retained fix/merge-base grants, caps, deadlines, and no-progress decisions stay PR-local; never borrow sibling consent. Parallel waits are independent bounded watches.
38
+
39
+ Write only the supplied report, never a second record/report. End with exactly one closing result line:
40
+
41
+ | Result | Closing line |
42
+ |---|---|
43
+ | Report | `REPORT <report path>` |
44
+ | Conflict after recovery, no rendered report | `CONFLICTING <report path> - <sync record>` |
45
+ | Failure | `FAILED - <reason>` |
46
+ | Pre-report ask | `STOPPED - <ask> - <what the user must supply>` |
47
+
48
+ Await all children before rendering or running consequences; never overlap batches. Classify non-zero, timeout, absent or off-contract result as `failed - <first error line>`, using the first error, not an invented success. Isolate failures. All terminal PRs get summary and terminal menus with no helper dispatch.
49
+
50
+ ## Recovery-first outcome adapter
51
+
52
+ Apply only in multi-PR mode at existing decision points. Leave single-PR owners and reference contracts unchanged. Never retry an unsafe checkout. For sync failures first restore/assert `<pre_head>` and a clean tree using the existing abort/reset recovery; a failed assertion is a hard failure, not permission to continue.
53
+
54
+ | Event | Child result after required recovery |
55
+ |---|---|
56
+ | `unresolved stop in <commit7>`, `implementer returned open`, `residue outside conflicted files`, `reviewer: <top finding>` | Record `sync: failed - <reason>`; no rendered report; `CONFLICTING <report path> - <sync record>` |
57
+ | `rebase failed: <first line>` or `push rejected: <first server line>` | `FAILED - sync: <reason>` |
58
+ | Sync terminal preconditions, baseline mismatch, lease refusal | `FAILED - sync: <reason>`; never conflict rows |
59
+ | Without rebase, head pushability false or unreadable | `FAILED - head not pushable: <head_url>:<head_ref>` before Verify |
60
+ | Required fallback cannot run: credentials, unresolved verification command after answer handling, or refused run | `FAILED - no verification evidence: <reason>`; never fabricate evidence |
61
+ | Helper output empty, off-contract, non-zero, or async | `FAILED - helper <role>: <quoted failure>` |
62
+ | All other steps 1-5 or 7 outcomes | `REPORT <report path>` |
63
+
64
+ Use only these pre-report asks; stop at the ask without further writes:
65
+
66
+ | Ask | Closing line | Re-dispatched assess task answer |
67
+ |---|---|---|
68
+ | Verification configuration rung 4 | `STOPPED - verification command - <subproject dirs seen>` | `verification command: <command>` |
69
+ | Multiple spec candidates | `STOPPED - spec candidate - <paths>` | `spec: <path>` |
70
+
71
+ Re-assess from steps 1-5 with the same record; substitute the answer at that ask only. Use `yes` confirmation as typed authority; `no` records `sync: declined - other author's branch`, stage skipped, then assesses unsynced. `not asked` covers same-author/no-op/skipped cases. Never ask the human from a child. UNKNOWN merge state after the single re-poll produces a report with merge withheld, not an ask. Step-7 contract, no-progress, and budget decisions return reports for parent menus.
72
+
73
+ ## Summary and menu round
74
+
75
+ The parent alone renders menus, prints reports verbatim, gathers answers, and runs cleanup/stop consequences. Render in roster order:
76
+
77
+ `#<N> <verdict line> | evidence: <ci | local | pending | unknown> | blockers: <count | unknown>`
78
+
79
+ Use report Verdict text, `conflicting - <sync record>`, `failed - <reason>`, or `stopped - <ask>`. Evidence is the record's resolved source; use unknown before Verify. Count open P# findings; use unknown without review. 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
+
81
+ Render unchanged per-PR menus in roster order: report plus existing rows, conflicts with existing conflict rows and evidence, failures with retry/evidence/stop, STOPPED with the recorded ask and stop last. 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 the row and print `Not offered: retry (worktree dirty or mid-rebase: <state>)`.
82
+
83
+ Show evidence only in-place from record/helper paths, then re-ask. Queue all other picks and answers until the final menu. Record direct picks with existing grant grammar; do not turn answers into grants. For terminal overlays, the parent handles `post coverage to ticket`, `post coverage to PR`, and `show evidence` from the primary checkout, even after cleanup removes the PR worktree; assign the parent the `merge queued` overlay's `wait` pick after all picks are collected: re-run `post-selection-loop.md` `### Merge course`'s post-merge read (`gh pr view <N> --json state,mergeCommit`), on `MERGED` persist `pr.state` and `pr.merge_commit` and render coverage/menu under `own merge`, otherwise re-render `merge queued` (`wait`/`show evidence`/`stop`), with no helper, child, or CI watch. Follow `decision-menu.md`'s terminal rows and `post-selection-loop.md` `### Merge course` and `### Output done-check`: execute the direct selected post only, with no compare-and-swap or helper dispatch; preserve successful-post suppression, failed-post rows, and terminal re-rendering. Queue terminal posts with all other external writes until every PR's pick is collected; keep evidence in-place from the retained record/helper paths. Exclude terminal picks from child dispatch; never use a removed worktree as cwd. Next batch mixes retry/answered-ask `assess` with ordinary nonterminal `execute` tasks, always same record.
84
+
85
+ ## Between batches and retirement
86
+
87
+ Run parent cleanup/stop only after all children finish, never on a live child's tree. For cleanup apply cleanup guards and ordered overrides. Keep the PR and post rows in the roster, set cleanup_done, and re-render with cleanup gone. Cleanup does not retire.
88
+
89
+ For stop on rebased-local heads reset to `<pre_head>` and assert exact HEAD and clean tree. For ordinary open PRs offer human-selected teardown naming unpushed fix commits that would be discarded, never auto-destroy. Under terminal overlays leave checkout as found and print leftover path/branch. Delete only that PR's record, helper outputs, and log_path files under existing teardown rules, then retire it. Await all next-batch results and re-render every nonretired PR; repeat until all retire.
90
+
91
+ 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.