pi-gauntlet 7.40.0 → 7.41.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 +17 -0
- package/README.md +16 -4
- package/agents/code-reviewer.md +2 -0
- package/agents/implementer.md +2 -0
- package/agents/loop-implementer.md +10 -0
- package/agents/plan-writer.md +1 -1
- package/agents/spec-reviewer.md +2 -0
- package/bin/gauntlet-telemetry-seal.mjs +18 -3
- package/bin/gauntlet-telemetry-seal.test.mjs +30 -0
- package/extensions/lib/plan-check.test.ts +116 -0
- package/extensions/lib/plan-check.ts +149 -20
- package/extensions/lib/telemetry-record.test.ts +11 -0
- package/extensions/lib/telemetry-record.ts +7 -0
- package/extensions/phase-tracker.test.ts +201 -3
- package/extensions/phase-tracker.ts +77 -9
- package/extensions/verify-before-ship.test.ts +240 -2
- package/extensions/verify-before-ship.ts +180 -25
- package/package.json +2 -2
- package/skills/brainstorming/SKILL.md +2 -2
- package/skills/brainstorming/gatherer.md +20 -7
- package/skills/brainstorming/reference/amendment-surface.md +13 -1
- package/skills/brainstorming/reference/legs.md +187 -0
- package/skills/brainstorming/reference/pr-subject.md +15 -9
- package/skills/brainstorming/reference/spec-finalization.md +16 -2
- package/skills/brainstorming/reference/ticket-acceptance.md +2 -2
- package/skills/finishing-a-development-branch/SKILL.md +21 -22
- package/skills/finishing-a-development-branch/reference/legs.md +76 -0
- package/skills/gauntlet-handoff/SKILL.md +2 -2
- package/skills/gauntlet-resume/SKILL.md +3 -2
- package/skills/gauntlet-resume/reference/brief-contract.md +40 -6
- package/skills/gauntlet-resume/reference/reconstruction.md +9 -7
- package/skills/gauntlet-resume/reference/seed.md +2 -0
- package/skills/loop-implementation/SKILL.md +89 -2
- package/skills/subagent-driven-development/SKILL.md +12 -0
- package/skills/using-git-worktrees/SKILL.md +59 -22
- package/skills/using-git-worktrees/reference/pr-head.md +36 -15
- package/skills/writing-plans/SKILL.md +16 -1
- package/skills/writing-plans/reference/plan-contract.md +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-gauntlet",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.41.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",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"test": "node scripts/ci.mjs"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"pi-cohort": ">=7.6.
|
|
65
|
+
"pi-cohort": ">=7.6.4"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"yaml": "^2.9.0"
|
|
@@ -18,7 +18,7 @@ You **may** read code/docs, run the existing system to observe current behavior,
|
|
|
18
18
|
|
|
19
19
|
You may **not** write outside the resolved spec dirs; build, deploy, validate, or exercise the proposed change; run implementation skills; commit the spec on `main`; or start `/skill:writing-plans`.
|
|
20
20
|
|
|
21
|
-
For a PR subject, the base merge and each
|
|
21
|
+
For a PR subject, the base sync (rebase or merge) and each member replay or merge, their conflict helpers' edits to the conflicted files, and their scoped conflict tests in `using-git-worktrees/reference/pr-head.md` are the sole pre-approval writes and runs outside the spec dirs; nothing else moves.
|
|
22
22
|
|
|
23
23
|
The line: current-system observation is research; exercising the proposed change waits for approval.
|
|
24
24
|
|
|
@@ -67,7 +67,7 @@ Detection order: (1) infer from ticket labels, description, or paths; (2) use th
|
|
|
67
67
|
|
|
68
68
|
The spec is the first commit in a dedicated worktree, never a separate commit on `main`. For a PR subject, the worktree is the PR's branch and the spec commit is appended to it.
|
|
69
69
|
|
|
70
|
-
Invoke `/skill:using-git-worktrees
|
|
70
|
+
Read [reference/legs.md](reference/legs.md) and settle membership before creation. Invoke `/skill:using-git-worktrees` for each member with explicit `$ROOT` = its primary and `$BRANCH` = the shared branch; carry every `Worktree ready at <full-path>` value, home first. Root the home spec at `<home worktree>/<home spec dir>/<filename>.md`; root each dispatch and `git -C` in its owning leg's worktree. Keep the process cwd unchanged. Gather each leg's rules and record portable contracts and companion artifacts using that reference; a one-member run adds only its one-block `## Legs` section.
|
|
71
71
|
|
|
72
72
|
Spec, plan, and implementation share this worktree. The spec and its telemetry record (`<telemetry.dir>/<spec path with .md -> .yaml>`, default `.pi/gauntlet/telemetry/doc/specs/<spec>.yaml`) are deliverables and ship in the squash; only the plan is stripped. `/skill:finishing-a-development-branch` strips the plan, then seals the record before landing (a `telemetry:` commit under git; the working-copy snapshot in a plain jj workspace). Explicit trivial one-off edits outside this flow need no worktree.
|
|
73
73
|
|
|
@@ -12,6 +12,11 @@ Mint a temp dir outside the worktree (never committed):
|
|
|
12
12
|
GATHER_DIR=$(mktemp -d)
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
Read [reference/legs.md](reference/legs.md) for the settled member order and rules walk.
|
|
16
|
+
Expand the scout task below once per leg, home first, using that leg's worktree
|
|
17
|
+
as `cwd` and a distinct `<GATHER_DIR>/scout-<index>.md` output. Preserve one scout
|
|
18
|
+
for a single-member run. Keep context-builder home-owned and conditional.
|
|
19
|
+
|
|
15
20
|
Set the substep, then dispatch one foreground parallel-tasks `subagent` call (`async: false`; no
|
|
16
21
|
`model:` — pi-cohort `agentOverrides` owns builder models). Preserve the parallel batch and await
|
|
17
22
|
its terminal result before assembling the draft:
|
|
@@ -45,6 +50,13 @@ Use that SKILL.md directory, never `reference/` as the base.
|
|
|
45
50
|
Scout (always dispatched):
|
|
46
51
|
|
|
47
52
|
> Recon for an upcoming design discussion. The request: `<initial prompt verbatim>`.
|
|
53
|
+
> Owning leg: `<repo>`; touched paths in this leg: `<paths or unresolved>`.
|
|
54
|
+
> Apply `reference/legs.md`'s rules walk: root and touched-directory `AGENTS.md`
|
|
55
|
+
> and `CLAUDE.md`, one hop of local documentation links in prose, bullets, and
|
|
56
|
+
> tables, deduped by `realpath`; linked documents contribute no more links.
|
|
57
|
+
> Emit repo-relative `Rules:` lines, `Rules: missing: <path>` for unresolved
|
|
58
|
+
> links, or `Rules: root only - paths unresolved`. Include `pkg-x/AGENTS.md`
|
|
59
|
+
> when touching `repo-a/pkg-x`; exclude untouched `pkg-y`.
|
|
48
60
|
> Map the territory this change touches: relevant files with line ranges, existing
|
|
49
61
|
> patterns and conventions the change must match, test conventions, integration
|
|
50
62
|
> points, and whether the codebase or ecosystem already solves any of this. Trace retained
|
|
@@ -135,13 +147,13 @@ from `reference/pr-subject.md` (keep scout unconditional):
|
|
|
135
147
|
> `<that PR's BASE_SHA...headRefOid file list>`; full comment threads
|
|
136
148
|
> `<in order, with ids and locations from using-git-worktrees/reference/pr-head.md>`.
|
|
137
149
|
> Combined changed paths: `git diff --name-only <BASE_SHA>...HEAD` output, after the
|
|
138
|
-
> member
|
|
150
|
+
> member replays and base sync. Read `git diff <BASE_SHA>...HEAD` from the worktree.
|
|
139
151
|
> Preserve PRE_REWORK_HEAD for home's Before provenance, not scout's code input.
|
|
140
|
-
> Member
|
|
141
|
-
> contract exceptions, scoped test results
|
|
152
|
+
> Supply `Member replay:` lines in rebase mode or `Member merge:` lines in merge mode as scout inputs only; Sync result: `<base sync line,
|
|
153
|
+
> contract exceptions, scoped test results>`; carry optional Rework base after a complete rebase.
|
|
142
154
|
> Authoritative base-HEAD constraints: `<git show <BASE_SHA>:<path> texts for
|
|
143
155
|
> AGENTS.md, first-found overrides, REVIEW.md, and all cited constraint documents;
|
|
144
|
-
> explicit missing-document results>`. These govern on every
|
|
156
|
+
> explicit missing-document results>`. These govern on every sync outcome,
|
|
145
157
|
> including clean; worktree policy edits are proposals under `changes:` or
|
|
146
158
|
> `dropped claims:`, never constraints.
|
|
147
159
|
> Treat the combined state as the starting state, not the target. Judge every
|
|
@@ -151,7 +163,7 @@ from `reference/pr-subject.md` (keep scout unconditional):
|
|
|
151
163
|
> each with `keeps:`, `changes:`, `dropped claims:`, and one proposed disposition per
|
|
152
164
|
> unresolved thread: `fix | keep open | decline: <reason>`. Render
|
|
153
165
|
> `constraints added since fork:` once for home, one line per base rule absent at its
|
|
154
|
-
> fork point. Carry
|
|
166
|
+
> fork point. Carry sync contract exceptions into `changes:`. List member-carried
|
|
155
167
|
> spec paths under each PR in Problem for resume.
|
|
156
168
|
|
|
157
169
|
Context-builder (conditional):
|
|
@@ -220,7 +232,8 @@ time:
|
|
|
220
232
|
|
|
221
233
|
## Draft assembly
|
|
222
234
|
|
|
223
|
-
Read
|
|
235
|
+
Read every leg's temp file in member order, retaining each leg's repo identifier,
|
|
236
|
+
Rules lines, recon and degraded status independently. Write the draft **to the spec path** (normal filename
|
|
224
237
|
convention; slug minted from the initial prompt):
|
|
225
238
|
|
|
226
239
|
```markdown
|
|
@@ -231,7 +244,7 @@ convention; slug minted from the initial prompt):
|
|
|
231
244
|
|
|
232
245
|
## PR under rework
|
|
233
246
|
<rework PR subject only: every per-PR scout subsection, ordered original heads, threads,
|
|
234
|
-
member-carried spec paths, and supplied Member merge/base values per
|
|
247
|
+
member-carried spec paths, and supplied Member replay or Member merge/base values per
|
|
235
248
|
reference/pr-subject.md; retain these values even when scout failed>
|
|
236
249
|
|
|
237
250
|
## External context
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Amendment surface
|
|
2
2
|
|
|
3
|
-
`read` this file (the `read` tool at its absolute path, never a shell command) from `skills/brainstorming/SKILL.md`
|
|
3
|
+
`read` this file (the `read` tool at its absolute path, never a shell command) from `skills/brainstorming/SKILL.md` section Amending an approved spec, from any phase, for amend-class changes; at approval, load only [Standing grants](#standing-grants), not the batch procedure. Keep redraws outside this procedure. Classify a change to an approved drafted acceptance-criteria row - its text, a row added, a row removed - as a redraw at batch preparation, before any standing grant, never a disposition amendment: re-draft from the new design and ratify at the full gate; keep a disposition-only change to such a row in this grammar so it keeps the cut question. Apply an item the human has answered by letter or custom text as recorded. Only the main loop holding `edit`/`write` authors amendments and human-facing amendment text. Use the human last: a fresh reviewer clears evidence-backed factual corrections; present the rest to the human once per batch plainly.
|
|
4
4
|
|
|
5
5
|
## Standing grants
|
|
6
6
|
|
|
@@ -145,6 +145,18 @@ Before the aftermath, `read` this section again; never run it from memory.
|
|
|
145
145
|
|
|
146
146
|
Apply accepted items only: reviewer clears, `accept`, `alt-n`, and state-changing `custom`. Print one line per applied item: `amended the spec: <title> - <what>`.
|
|
147
147
|
|
|
148
|
+
Preserve scope indices on disposition-only amendments, including cuts; validate
|
|
149
|
+
all blocks using [legs.md](legs.md)'s scope grammar before committing.
|
|
150
|
+
Apply [legs.md](legs.md)'s companion aftermath in this same amendment: changes
|
|
151
|
+
to Problem, shared Design/Errors/Out-of-scope, repo-binding clauses, or a leg
|
|
152
|
+
block rewrite each affected companion artifact. Commit home, then the affected
|
|
153
|
+
files through their own `git -C`; preserve the amendment audit in those commits.
|
|
154
|
+
Do not complete the amendment while any carried text disagrees. For specs with
|
|
155
|
+
`## Legs`, recorded contracts are authoritative, replacing finish Step 6's
|
|
156
|
+
reread rule; amend the block before using a changed contract. Legacy specs
|
|
157
|
+
without that section retain finish-time rereading. A one-member run has no
|
|
158
|
+
companion artifact or companion aftermath.
|
|
159
|
+
|
|
148
160
|
Aftermath, once per batch, only when at least one item applied (nothing applied -> skip to the commit below). Ledger exists (line 1 `# Ledger - loop engine` in the resolved plan dir) -> skip `plan-writer`, `plan_check`, and `plan_tracker`. Reconcile the ledger against the approved spec dispositions: `deviates:`, `deferred:`, or `elsewhere:` -> `cut`, evidence = the disposition; factual or requirement-preserving amendment -> preserve rows; re-bounded `done` row -> `open`, evidence = `reopened by amendment`. Preserve every row's attempts and the ledger's iterations. Never auto-edit ticket or approved drafted AC row texts; reconcile dispositions only, never text/add/remove changes. Commit spec + ledger together with subject `loop: cut row <n>` for a batch containing only one cut, otherwise `loop: amend` (including mixed batches), carrying the amendment audit body below (including each `granted` record and granting sentence); continue without task-plan aftermath. No plan yet -> commit the spec; continue. Plan exists -> read `git -C "<abs worktree path>" status --porcelain` (plain jj: `jj -R "<abs worktree path>" diff --summary`); collect the parent's in-flight workflow edits as worktree-relative paths, including the amended spec and staged in-place wave-repair deliverables. Dispatch `plan-writer` per `writing-plans` `## Author the plan` step 3 with an `Amend:` block naming the amended spec sections, an `In-flight:` list of those paths (the parent supplies the set; the child never infers it), and the rule "preserve every task title and wave position the amendment does not touch; edit only affected anchors and tasks", then run that section's steps 5-6 (the parent `plan_check` and its branches).
|
|
149
161
|
|
|
150
162
|
At that return point, classify human-facing outcomes with this table; let writing-plans' first `Findings:` repair run as written.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Legs
|
|
2
|
+
|
|
3
|
+
Use this reference as the portable membership, leg-block, and companion-file grammar.
|
|
4
|
+
Keep tracker and dispatch APIs unchanged.
|
|
5
|
+
|
|
6
|
+
## Settle membership before Worktree First
|
|
7
|
+
|
|
8
|
+
Read the home primary's first-found overrides file: `.pi/gauntlet-overrides.md`,
|
|
9
|
+
`gauntlet-overrides.md`, `doc/gauntlet-overrides.md`. Treat `## shape-ticket`
|
|
10
|
+
`- sibling: <clone url>` declarations as eligibility, not membership. Parse selected values
|
|
11
|
+
with shape-ticket's [shared parser](../../shape-ticket/reference/repo-audit.md);
|
|
12
|
+
use `PATH` = `<home PRIMARY parent>/<NAME>` as each companion primary.
|
|
13
|
+
|
|
14
|
+
Match only companions explicitly selected by the ask (repo identifier, `NAME`,
|
|
15
|
+
or declared clone URL) or the ticket's repo-group headings. Compare
|
|
16
|
+
case-insensitively, trailing `owner/name` of `IDENTITY` before `NAME`. Derive each companion's portable identifier
|
|
17
|
+
from the shared parser's trailing `owner/name` of `IDENTITY` for the validated stored origin
|
|
18
|
+
read with `git -C <primary> config --get remote.origin.url`. Derive the home's identifier
|
|
19
|
+
from `git -C <primary> remote get-url origin`'s `owner/name`, stripping `.git`;
|
|
20
|
+
without origin use `repo:` from that member's own first-found overrides
|
|
21
|
+
`## Issue tracker` section; without that value use the member's primary directory basename. Use the same identifier
|
|
22
|
+
in `### Leg:`, task `Leg:`, and brief `repo:` fields. For an ambiguous basename,
|
|
23
|
+
ask once before any creation; never guess. Order members home first, then selected siblings in declared order.
|
|
24
|
+
An existing PR alone never activates membership; PR home provisioning still uses
|
|
25
|
+
`using-git-worktrees/reference/pr-head.md`.
|
|
26
|
+
|
|
27
|
+
Match identifiers before any filesystem or git probe; probe only matching siblings,
|
|
28
|
+
or remaining declarations when nothing matches. Never probe unselected siblings. With no selected companion,
|
|
29
|
+
keep the single-member flow. Validate every selected declaration before creating
|
|
30
|
+
any tree: invalid configuration, missing `PATH`, not a checkout, no origin,
|
|
31
|
+
unparseable origin, wrong repo, or `PATH` equal to home stops naming the line.
|
|
32
|
+
Read origins with `git -C <PATH> config --get remote.origin.url` and compare the
|
|
33
|
+
full parsed `IDENTITY`; canonicalize paths before the home comparison. Keep these machine paths in working state and briefs, never in committed blocks.
|
|
34
|
+
|
|
35
|
+
## Resolve each member
|
|
36
|
+
|
|
37
|
+
| Field | Contract |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `repo` | Portable identifier above; preserve one spelling everywhere |
|
|
40
|
+
| `primary` | Home checkout at brainstorm start, or selected sibling clone URL parsed to `<home PRIMARY parent>/<NAME>`; machine-local |
|
|
41
|
+
| `worktree` | Absolute `Worktree ready` result; machine-local |
|
|
42
|
+
| `branch` | One full caller `BRANCH` shared by all members |
|
|
43
|
+
| `name` | Shared `NAME`, derived from `BRANCH` by replacing `/` with `-` |
|
|
44
|
+
| `Rules:` | Repo-relative files from the rules walk below |
|
|
45
|
+
|
|
46
|
+
Read each primary's first-found overrides using the ladder above. Read its
|
|
47
|
+
`.pi/settings.json` by file and apply the existing preset rules in
|
|
48
|
+
`extensions/lib/gauntlet-settings.ts`: repo top-level piGauntlet keys replace
|
|
49
|
+
preset keys wholesale; absent keys fall through. Missing configuration uses defaults.
|
|
50
|
+
Keep flow policy (council, grants, tracker, response channels, finish choice and
|
|
51
|
+
home flow guards) under home `.pi/settings.json#piGauntlet` and home overrides.
|
|
52
|
+
Never use `gauntlet_setting` for companions or add a `piGauntlet.*` key.
|
|
53
|
+
|
|
54
|
+
Record portable templates, not expanded absolute paths:
|
|
55
|
+
|
|
56
|
+
- Create: retain the leg's `## using-git-worktrees` keyed `home:`/`create:` contract,
|
|
57
|
+
native tool, discovered wrapper, or owned built-in. Resolve other wrapper tokens
|
|
58
|
+
from that leg's touched top-level directory; zero or several candidates ask once
|
|
59
|
+
for that leg. Retain the resolved portable value, not a machine path.
|
|
60
|
+
- Destroy: prefer the `## cleanup` worktree line, then `destroy:`, then owned
|
|
61
|
+
built-in removal matching `home:`. Include configured
|
|
62
|
+
`subagents.worktreeTeardownHook` with pi-cohort's existing semantics. Never
|
|
63
|
+
bypass a wrapper with `git worktree remove`; unmatched homes remain host-owned.
|
|
64
|
+
- Directories: resolve `flowGuards.specDirs` with the existing default
|
|
65
|
+
`doc/specs`, `docs/specs`; derive plan directories with `planDirsFor`.
|
|
66
|
+
Never read `planDirs` as settings input. Choose the leg's spec directory by the
|
|
67
|
+
existing spec-location convention. Keep plan and ledger home-owned.
|
|
68
|
+
- Verification: retain commands from `## verification-before-completion` and
|
|
69
|
+
`## PR gate`, plus merged `piGauntlet.verifyBeforeShip`. Preserve templates
|
|
70
|
+
describing execution against the leg's worktree or primary.
|
|
71
|
+
|
|
72
|
+
Invoke using-git-worktrees once per member with explicit `$ROOT` = primary and
|
|
73
|
+
`$BRANCH` = shared branch; require the affirmative read-back in
|
|
74
|
+
[Step 4](../../using-git-worktrees/SKILL.md#step-4--report-location).
|
|
75
|
+
Carry every `Worktree ready at <path>` result, home
|
|
76
|
+
first. On any failure stop naming repo and branch and list already-created legs;
|
|
77
|
+
leave them preserved, never auto-remove them.
|
|
78
|
+
|
|
79
|
+
## Gather rules
|
|
80
|
+
|
|
81
|
+
Dispatch one scout per leg with its worktree as `cwd`. Collect root `AGENTS.md`
|
|
82
|
+
and `CLAUDE.md` when present; walk root through every touched directory and
|
|
83
|
+
collect those filenames on the path. For a touch in `repo-a/pkg-x`, include
|
|
84
|
+
`repo-a/pkg-x/AGENTS.md`, not rules from untouched `pkg-y`.
|
|
85
|
+
Read every local documentation link in those walked files, including prose,
|
|
86
|
+
bullets, and tables, exactly one hop. Resolve targets relative to the linking
|
|
87
|
+
file and require them to stay inside the leg. Dedupe files by `realpath` so a
|
|
88
|
+
symlinked `CLAUDE.md` counts once. Linked documents contribute no further links.
|
|
89
|
+
Emit `Rules: <repo-relative path>` for each file and `Rules: missing: <path>` for
|
|
90
|
+
unresolved or outside-leg targets; never invent their contents. Without touched
|
|
91
|
+
paths, retain root rules and emit `Rules: root only - paths unresolved`; the
|
|
92
|
+
plan-writer's touched-path walk fills the task rules later. Every leg block
|
|
93
|
+
carries at least one `Rules:` line; a block with no rules walk result carries
|
|
94
|
+
`Rules: root only - paths unresolved`, never an omitted key or a deferral note.
|
|
95
|
+
|
|
96
|
+
## Home block and companion files
|
|
97
|
+
|
|
98
|
+
Place `## Legs` after `## Acceptance criteria` and optional `## Rework record`.
|
|
99
|
+
Write one block per member, home first. Use repo-relative rules and design paths;
|
|
100
|
+
the following shows the field grammar, not configuration values to copy:
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
## Legs
|
|
104
|
+
|
|
105
|
+
### Leg: repo-a
|
|
106
|
+
branch: feature/shared-change
|
|
107
|
+
contract:
|
|
108
|
+
- create: git worktree add <home> -b <branch>
|
|
109
|
+
- destroy: git worktree remove <home> && git worktree prune
|
|
110
|
+
- home: .worktrees/<name>
|
|
111
|
+
- spec-dir: doc/specs
|
|
112
|
+
- plan-dir: doc/plans
|
|
113
|
+
- verification: <resolved portable verification templates and policy>
|
|
114
|
+
Rules: AGENTS.md
|
|
115
|
+
Rules: pkg-x/AGENTS.md
|
|
116
|
+
scope: AC 1, AC 3
|
|
117
|
+
design: <owned paths, observable outcomes, and clauses binding this leg>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Scope grammar and validation
|
|
121
|
+
|
|
122
|
+
Write exactly one `scope:` line in each block: `scope: none` or a comma-separated
|
|
123
|
+
list of `AC <index>` entries, as in the template. Use one-based original AC indices, including cut rows;
|
|
124
|
+
count checkbox rows in their original order, not ledger entries or disposition-filtered rows.
|
|
125
|
+
Repeat shared indices in each owning leg; indices unlisted across all legs default home.
|
|
126
|
+
When all legs say `scope: none`, every original AC defaults home.
|
|
127
|
+
Never infer ownership from `design:` prose or paths: `design: implements AC 2`
|
|
128
|
+
does not claim AC 2 without an explicit scope entry. Put owned paths and
|
|
129
|
+
observable outcomes in `design:` instead.
|
|
130
|
+
|
|
131
|
+
Before committing home or companion artifacts, validate every block against the
|
|
132
|
+
original AC count. Reject missing or duplicate scope lines, duplicate indices within one leg,
|
|
133
|
+
malformed lists, and nonexistent original indices; the same index in different legs is valid.
|
|
134
|
+
Use these rejection cases as the boundary checks:
|
|
135
|
+
|
|
136
|
+
| Invalid line | Reason |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `scope: AC 0` | Zero is not one-based |
|
|
139
|
+
| `scope: AC 1.5` | Fractional index |
|
|
140
|
+
| `scope: AC 1-3` | Range rather than individual indices |
|
|
141
|
+
| `scope: 1` | Bare number without `AC ` |
|
|
142
|
+
| `scope: AC 1,` | Trailing comma / empty entry |
|
|
143
|
+
| `scope: none, AC 1` | Mixed sentinel and list |
|
|
144
|
+
| `scope: AC 1, AC 1` | Duplicate within one leg |
|
|
145
|
+
| `scope: AC 4` with only three original ACs | Nonexistent original index |
|
|
146
|
+
|
|
147
|
+
Reject empty values, negative indices and any other entry not matching
|
|
148
|
+
`AC [1-9][0-9]*`, separated by comma and space. Preserve scope indices on
|
|
149
|
+
disposition-only amendments, including cuts; validate again before the amendment commit.
|
|
150
|
+
Keep this grammar here; consumers refer to it rather than inventing ownership rules.
|
|
151
|
+
|
|
152
|
+
Keep shared Design, Errors and edge cases, and Out of scope outside `## Legs`;
|
|
153
|
+
those clauses bind every member. Assign member ticket groups `in-scope` and name
|
|
154
|
+
their ownership through original AC indices in `scope:`. Unmatched groups retain ticket-acceptance's
|
|
155
|
+
`this repo / elsewhere / repair` question; `elsewhere:` creates no leg.
|
|
156
|
+
|
|
157
|
+
Commit home first using spec-finalization's existing gate and audit. Then write
|
|
158
|
+
one companion file per companion in its own spec directory with the home's
|
|
159
|
+
filename. Use `git -C <companion worktree>` to add and commit that file:
|
|
160
|
+
|
|
161
|
+
```markdown
|
|
162
|
+
# <home spec title>
|
|
163
|
+
|
|
164
|
+
**Home:** <home repo> <shared branch> <home repo-relative spec path>
|
|
165
|
+
|
|
166
|
+
## Problem
|
|
167
|
+
<home Problem copied verbatim>
|
|
168
|
+
|
|
169
|
+
## Decisions
|
|
170
|
+
<shared Design, Errors and edge cases, Out of scope, and clauses naming this
|
|
171
|
+
repo or its owned paths in design, copied from home>
|
|
172
|
+
|
|
173
|
+
### Leg: repo-b
|
|
174
|
+
<that companion's entire block verbatim>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Rewrite and commit affected companion files in the same amendment when Problem,
|
|
178
|
+
shared decisions, repo-binding clauses, or their block changes. Do not call an
|
|
179
|
+
amendment complete while a carried part disagrees.
|
|
180
|
+
|
|
181
|
+
Treat recorded `contract:` lines as authority for every spec with `## Legs`,
|
|
182
|
+
including one-member specs. This replaces finishing Step 6's creation-time
|
|
183
|
+
reread rule; legacy specs without `## Legs` retain the finish-time reread and
|
|
184
|
+
mean home-only. Amend a recorded contract before a later stage uses a change.
|
|
185
|
+
|
|
186
|
+
For one member add exactly one block only: no companion artifact, no `legs:`
|
|
187
|
+
brief block, no `--leg`, no receipt, and no companion loop.
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Parse only a trimmed leading run of one or more GitHub references: `#N`, `owner/repo#N`, or a GitHub `/pull/N` or `/issues/N` URL, separated by whitespace or commas. The first token that is not a ref starts intent text; carry it verbatim without looking up later references. Read `#12 #13 #14` as three PRs, `#12, #13 tighten the retry path` as two plus intent, and `#12 fix the retry path, see #13 for context` as one plus intent. Route mid-sentence mentions through the free-text path with context-builder: for `make the retry logic work like #55 did`, gather #55 as context, not a PR subject; skip PR classification and PR-head provisioning. Keep Linear/Jira and other free-text subjects on their existing paths.
|
|
6
6
|
|
|
7
|
+
When the first intent token is `merge-forward`, set `SYNC=merge` and strip only that token from intent; otherwise set `SYNC=rebase`. Preserve all remaining intent. Pass SYNC beside the admitted PR array only to provisioning. Carry `SYNC` nowhere else; infer the mode later from the record.
|
|
8
|
+
|
|
7
9
|
Resolve and admit in listed order before any write; stop at the first failing ref with its observed reason. Create no worktree and leave existing worktrees unchanged on admission failure. Complete classification in order, never in parallel: `gh issue view` can return a PR as an issue.
|
|
8
10
|
|
|
9
11
|
1. Run `gh pr view <N> [-R owner/repo] --json number,url,state,isDraft,title,body,headRefName,headRefOid,headRepository,isCrossRepository,baseRefName`. Accept exit 0 with `state: OPEN`, including `isDraft` true.
|
|
@@ -29,9 +31,9 @@ Immediately after ordered admission and before binding, classify N=1 read-only.
|
|
|
29
31
|
|
|
30
32
|
| Observation | Route |
|
|
31
33
|
|---|---|
|
|
32
|
-
| Shape fails | Continue unchanged through bind, gather, scout, and Rework record. |
|
|
33
|
-
| Shape passes, marker absent | Print `spec-only PR without the gate marker - running lint and council`. Provision the one-element admitted PR array through pr-head's checkout, base merge, and Step 4 report with no thread fetch (bypass its `## Fetch unresolved review threads` as on the marked route). Skip ticket binding, context-builder, the PR scout block, and gather; never write a `## Rework record`. Resume at checklist step 4 with the carried spec file at `<worktree>/<path>` as the draft, as a redraw does (recon falls to the questionary); spec-writing overwrites that file at its carried path. Run lint, council, and the gate as for any spec, with 6 withheld (`Withheld: draft PR - #N already exists`). On approval 1/2/4/5 persist `**Engine:**`, `**Amend-grant:**`, and `**PR:** <owner/repo#N>` as a new commit per spec-pr.md's re-gate persistence. |
|
|
34
|
-
| Shape and marker pass | Provision the one-element admitted PR array through pr-head's checkout/base merge/Step 4, then follow spec-pr.md's re-gate. Skip binding and all before-gather thread queries. Treat draft and ready PRs equally. |
|
|
34
|
+
| Shape fails | Pass the selected SYNC to provisioning. Continue unchanged through bind, gather, scout, and Rework record. |
|
|
35
|
+
| Shape passes, marker absent | Force `SYNC=merge` for provisioning. Print `spec-only PR without the gate marker - running lint and council`. Provision the one-element admitted PR array through pr-head's checkout, base merge, and Step 4 report with no thread fetch (bypass its `## Fetch unresolved review threads` as on the marked route). Skip ticket binding, context-builder, the PR scout block, and gather; never write a `## Rework record`. Resume at checklist step 4 with the carried spec file at `<worktree>/<path>` as the draft, as a redraw does (recon falls to the questionary); spec-writing overwrites that file at its carried path. Run lint, council, and the gate as for any spec, with 6 withheld (`Withheld: draft PR - #N already exists`). On approval 1/2/4/5 persist `**Engine:**`, `**Amend-grant:**`, and `**PR:** <owner/repo#N>` as a new commit per spec-pr.md's re-gate persistence. |
|
|
36
|
+
| Shape and marker pass | Force `SYNC=merge` for provisioning. Provision the one-element admitted PR array through pr-head's checkout/base merge/Step 4, then follow spec-pr.md's re-gate. Skip binding and all before-gather thread queries. Treat draft and ready PRs equally. |
|
|
35
37
|
|
|
36
38
|
## Relatedness before provisioning
|
|
37
39
|
|
|
@@ -49,17 +51,17 @@ Bind the spec's ticket only from home's first tracker reference in the title, th
|
|
|
49
51
|
|
|
50
52
|
For an unbound home PR, retain the gather-time result `none - no ticket`; at spec-writing use `ticket-acceptance.md`'s drafted branch from the agreed rework design. Carry raw title/body as stated intent, not invented AC rows; derive the drafted outcomes from the agreed design, not the title/body carry-over. Name its spec `YYYY-MM-DD-pr-<N>-<topic>.md`; emit the concrete filename with the actual date, PR number, and topic slug derived from the PR title. For a bound ticket keep `YYYY-MM-DD-<ticket-id>-<topic>.md`.
|
|
51
53
|
|
|
52
|
-
Pass an ordered array, home first, of exactly `{ number, url, title, headRefName, headRefOid, baseRefName, isCrossRepository, headRepository.nameWithOwner }` by value to provisioning in `using-git-worktrees/reference/pr-head.md`; use a one-element array for N=1 and write nothing during resolution.
|
|
54
|
+
Pass an ordered array, home first, of exactly `{ number, url, title, headRefName, headRefOid, baseRefName, isCrossRepository, headRepository.nameWithOwner }` by value beside SYNC to provisioning in `using-git-worktrees/reference/pr-head.md`; use a one-element array for N=1 and write nothing during resolution.
|
|
53
55
|
|
|
54
56
|
## Gather from the PR and fetched base
|
|
55
57
|
|
|
56
58
|
Apply this section's thread fetch, carried-spec discovery, scout dispatch, and `## PR under rework` rendering to the rework route only; the unmarked spec-only route skips gather. Require every retained PR's title/body, carried specs, and full threads before spec-writing. Stop before gather on any query failure, N=1 included: `threads for #<N> not fetched (<gh error>)`; name the ref and reason for unreadable title/body/specs too. Discover PR-carried specs per PR with `git diff --name-only <BASE_SHA>...<that PR's headRefOid> -- <each flowGuards.specDirs dir>` using the resolved spec directories. Read every carried spec's contents with `git show <that PR's headRefOid>:<path>` as that PR's stated contract beside its title/body; preserve the owning PR, original head, and path even when multiple PRs carry different versions of the same path. List member-carried spec paths under their PR in `## Problem` so resume can exclude them from new-spec candidates. Only when superseded, name it in `**Predecessor:**` and apply `reference/superseding.md`'s banner; that banner is the allowed spec-directory write.
|
|
57
59
|
|
|
58
|
-
On every
|
|
60
|
+
On every sync outcome, including clean, no-op, and unresolved, read constraints using `git show <BASE_SHA>:<path>`: `AGENTS.md`, the first-found overrides file (check `.pi/gauntlet-overrides.md`, `gauntlet-overrides.md`, `doc/gauntlet-overrides.md` in order at BASE_SHA), `REVIEW.md`, and all cited constraint documents. Carry missing-document results explicitly. Use these fetched base-HEAD rules, never fork-point or worktree copies. Treat PR edits to policy documents as proposals recorded under `changes:` or `dropped claims:`, not governing constraints.
|
|
59
61
|
|
|
60
|
-
Dispatch scout always, and context-builder only for the home-bound ticket. Supply per PR the title/body verbatim, own changed paths and PR-carried specs as attributed original-head text separately from the combined worktree code input, and full comment threads with ids and locations from the query owned by `using-git-worktrees/reference/pr-head.md`. Supply combined changed paths from `git diff --name-only <BASE_SHA>...HEAD` run in the worktree after member and base
|
|
62
|
+
Dispatch scout always, and context-builder only for the home-bound ticket. Supply per PR the title/body verbatim, own changed paths and PR-carried specs as attributed original-head text separately from the combined worktree code input, and full comment threads with ids and locations from the query owned by `using-git-worktrees/reference/pr-head.md`. Supply combined changed paths from `git diff --name-only <BASE_SHA>...HEAD` run in the worktree after member replays and base sync, and have scout read `git diff <BASE_SHA>...HEAD` there. Supply base-SHA constraint documents, `Member replay:` lines in rebase mode or `Member merge:` lines in merge mode, and base sync outcomes; do not pass the selector to scout. Keep `PRE_REWORK_HEAD` as home's original provenance anchor for Before, record, and brief, not the code-input boundary.
|
|
61
63
|
|
|
62
|
-
Instruct scout: treat the combined PR state as the starting state, not the target; judge every stated claim against its diff and current base rules. Name the smallest repair satisfying those rules; propose a rewrite only when no repair can satisfy them. Render `## PR under rework` after `## Codebase recon`, with one `### PR #<N> - <title>` subsection per PR, home first, each with lowercase `keeps:`, `changes:`, `dropped claims:`, and one disposition per unresolved thread: `fix | keep open | decline: <reason>`. Render `constraints added since fork:` once for home, one line per base-HEAD rule absent at its fork point. Carry
|
|
64
|
+
Instruct scout: treat the combined PR state as the starting state, not the target; judge every stated claim against its diff and current base rules. Name the smallest repair satisfying those rules; propose a rewrite only when no repair can satisfy them. Render `## PR under rework` after `## Codebase recon`, with one `### PR #<N> - <title>` subsection per PR, home first, each with lowercase `keeps:`, `changes:`, `dropped claims:`, and one disposition per unresolved thread: `fix | keep open | decline: <reason>`. Render `constraints added since fork:` once for home, one line per base-HEAD rule absent at its fork point. Carry sync contract exceptions into `changes:`. Run the framing check in SKILL.md ### 3 against the combined diff as the ask.
|
|
63
65
|
|
|
64
66
|
## Record in the spec
|
|
65
67
|
|
|
@@ -75,7 +77,9 @@ Threads:
|
|
|
75
77
|
PR: <owner/repo#M> - <title>
|
|
76
78
|
Pre-rework head: <40-char sha>
|
|
77
79
|
Threads: none
|
|
78
|
-
Base: <baseRefName> @ <sha7> - merge:
|
|
80
|
+
Base: <baseRefName> @ <sha7> - <rebased: pre7..new7, n stop(s) in files | sync: no-op | sync: unresolved - files | merge: no-op | merge: sha7 | merge: unresolved - files>
|
|
81
|
+
Rework base: <40-char sha>
|
|
82
|
+
Member replay: #<M> <first7..last7 | empty | (already landed) | unresolved - files | pending>
|
|
79
83
|
Keeps: <what of the combined original survives>
|
|
80
84
|
Changes: <what the rework alters, repair over rewrite>
|
|
81
85
|
Dropped claims: <one `- <claim>` per PR-stated claim no longer true | none>
|
|
@@ -92,8 +96,10 @@ changes: <copied change>
|
|
|
92
96
|
dropped claims: <copied claims | none>
|
|
93
97
|
```
|
|
94
98
|
|
|
99
|
+
Include Rework base only after a complete rebase sync; omit it for merge records and incomplete syncs. Put rebase `Member replay:` outcomes in listed order after Base and optional Rework base, before combined claims. Retain merge `Member merge:` outcomes in Step 4 and scout inputs only, not in the record.
|
|
100
|
+
|
|
95
101
|
For N=1 render one group and one subsection; place `Threads:` immediately after `Pre-rework head:`. Use `Threads: none` for a successful empty fetch. A failed fetch stops before gather, never continues with `Threads: not fetched`. Preserve the query owner's outdated/path-only location fallback and all thread dispositions. Preserve full original heads; add no member merge SHA field. Keep lowercase provenance distinct from the capitalized combined fields: finish/handoff copy only top-level capitalized fields, never subsection claims.
|
|
96
102
|
|
|
97
|
-
Instantiate `Scoped tests: none run (<reason>)` when no documented file-scoped runner exists or `requires credentials: true`; otherwise record the scoped result, including failures. Name landed contract exceptions in `Changes:`.
|
|
103
|
+
Instantiate `Scoped tests: none run (<reason>)` when no documented file-scoped runner exists or `requires credentials: true`; otherwise record the scoped result, including failures. Name landed contract exceptions in `Changes:`. Open Design with the matching eventual Task 1: `rebase onto origin/<base> and resolve <files>` for `sync: unresolved`, `replay #<N> onto home and resolve <files>` for an unresolved member replay, or `merge origin/<base> and resolve <files>` for `merge: unresolved`. In rebase mode Task 1 also replays pending members in order and persists Rework base and final outcomes before finishing.
|
|
98
104
|
|
|
99
105
|
Preserve this record when `reference/spec-finalization.md` replaces the draft; dropping any retained PR fails inline lint. Use provisioning Step 4's home plus `MEMBER_HEADS` as the expected inputs. Carry every retained PR title/body verbatim beside home-bound-ticket rows in the council's `Human input`. Do not attach a rework record to ticket or free-text specs.
|
|
@@ -19,12 +19,19 @@ Spec-writing replaces the context draft, in this exact order:
|
|
|
19
19
|
For a rework PR subject (a draft carrying `## PR under rework`), follow `pr-subject.md`'s spec contract:
|
|
20
20
|
carry the draft's `## PR under rework` into `## Rework record` after `## Acceptance criteria`,
|
|
21
21
|
preserving its repeated PR/Pre-rework head/Threads groups, one per retained PR,
|
|
22
|
-
home first, each 40-character pre-rework SHA,
|
|
22
|
+
home first, each 40-character pre-rework SHA, sync result, rework base, and member replay lines,
|
|
23
23
|
keeps/changes/dropped claims, thread dispositions and fetch status, contract exceptions,
|
|
24
24
|
and scoped test results (including failures and reasons none ran), then one
|
|
25
25
|
`### PR #<N>` provenance subsection per PR with lowercase claims. Carry every PR's
|
|
26
26
|
stated intent and constraints added since fork into Problem. Open Design with the
|
|
27
|
-
unresolved
|
|
27
|
+
unresolved sync repair when present. Omit the record from a ticket or free-text spec.
|
|
28
|
+
Then write `## Legs` after `## Acceptance criteria` and optional `## Rework record`,
|
|
29
|
+
using [legs.md](legs.md): one `### Leg: <repo>` block per member, home first,
|
|
30
|
+
with `branch:`, portable `contract:`, `Rules:`, exactly one `scope:` line and
|
|
31
|
+
`design:` prose for owned paths and observable outcomes.
|
|
32
|
+
Validate every block using [legs.md](legs.md)'s scope grammar before committing.
|
|
33
|
+
Keep machine-local paths out of committed blocks. Even a single-member spec
|
|
34
|
+
carries exactly one block; legacy specs without the section remain home-only.
|
|
28
35
|
3. **Immediately after the write**, confirm line 1 of the file is no longer
|
|
29
36
|
`# CONTEXT DRAFT - NOT A SPEC - fully replaced at spec-writing` - before
|
|
30
37
|
dispatching lint, critique, council, or summarizer. The phase-tracker commit
|
|
@@ -116,6 +123,13 @@ git -C <abs worktree path> add -- <spec path> [<predecessor path>] && git -C <ab
|
|
|
116
123
|
EOF
|
|
117
124
|
```
|
|
118
125
|
|
|
126
|
+
After the home commit, write and commit every companion leg file through
|
|
127
|
+
`git -C <companion worktree>` using [legs.md](legs.md)'s artifact grammar:
|
|
128
|
+
`**Home:**` tuple, copied `## Problem`, `## Decisions` from shared
|
|
129
|
+
Design/Errors/Out-of-scope and repo-binding clauses, and its own block verbatim.
|
|
130
|
+
Stop naming any failed companion; do not present artifact completion until all
|
|
131
|
+
files agree. A single-member run writes no companion file.
|
|
132
|
+
|
|
119
133
|
If the council path ran, the body is its audit (`Coverage:` when present, then `Applied:` / `Deferred:` / `Rejected:`, verbatim from `/skill:roasting-the-spec`'s return) - the durable, non-contractual record a finish-time revert and row 3 below read back; the audit is never a committed spec section. On the worker path the body is empty except for a main-loop drafted-AC repair audit line when a repair occurred. Append that repair line after the council audit on the council path; never alter its labels, cluster lines, or counts. `-m`, `-F <file>`, `printf | ... -F -`, and `$'...'` strings are not used for this commit. The `add` on the same line is required because the spec is untracked at its first commit and `commit -- <path>` rejects an untracked path.
|
|
120
134
|
|
|
121
135
|
Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
|
|
@@ -4,7 +4,7 @@ A ticket is guidance, not sole truth. Fetch it; propose scope, approach, or acce
|
|
|
4
4
|
|
|
5
5
|
**Extract the ticket's ACs.** When the ticket body has a heading matching `/acceptance criteria/i`, every list item under it is an AC (numbered, bullet, or checkbox) until the next heading of that heading's level or higher, and no other list in the body is; a heading one level deeper inside the section is a repo group - it names the repo whose part delivers the rows under it and does not end extraction. When there is no such heading, every top-level checkbox row in the body is an AC, except rows under a `Post-deployment housekeeping`, `Out of scope`, or `Follow-up` heading. Otherwise the ticket has no ACs. A nested list under an AC row rides with its parent as one row; an AC heading holding prose and no list makes each paragraph one row. Carry checked and unchecked rows alike, all written `- [ ]`. Take the rows and their repo-group headings from the gather draft's `## Ticket acceptance criteria (verbatim)` heading; when the ticket was not fetched, the gate summary shows the `none` line so the user can paste the rows, which then become rows.
|
|
6
6
|
|
|
7
|
-
**This repo** is the `repo:` value of the overrides `## Issue tracker` section, else the `owner/name` path of `git remote get-url origin` with any `.git` suffix stripped; a repo group matches it when the group name equals that value or its basename, case-insensitive. A ticket without repo groups holds only this repo's rows; never guess attribution. A grouped ticket with no group matching
|
|
7
|
+
**This repo** is the `repo:` value of the overrides `## Issue tracker` section, else the `owner/name` path of `git remote get-url origin` with any `.git` suffix stripped; a repo group matches it when the group name equals that value or its basename, case-insensitive. Apply [legs.md](legs.md)'s identifier-before-basename membership resolution before attribution. A ticket without repo groups holds only this repo's rows; never guess attribution. A grouped ticket with no group matching any member stops the brainstorm with that fact.
|
|
8
8
|
|
|
9
9
|
**Write the section in every spec**, after `## Problem`:
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ Ticket <ref>, <heading or "checkbox list">, rows verbatim:
|
|
|
17
17
|
<disposition>
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Under `Ticket <ref>, <heading or "checkbox list">, rows verbatim:`, the section names the ticket contract only; the spec's own requirements stay in Design. Keep every provenance form flat - a row's repo lives in its disposition token, never in a heading. Disposition is exactly one of `in-scope`, `deviates: <why>`, `deferred: <where>`, `venue: <env> - <observation>`, `elsewhere: <repo>`; default `in-scope`. For ticket rows, never edit the row text: an ambiguous row stays `in-scope` with the chosen reading written as a Design clause, and a moved path or a workflow artifact (spec, plan, changelog, telemetry file) is a Design clause too, never a disposition and never asked. A row under a repo group
|
|
20
|
+
Under `Ticket <ref>, <heading or "checkbox list">, rows verbatim:`, the section names the ticket contract only; the spec's own requirements stay in Design. Keep every provenance form flat - a row's repo lives in its disposition token, never in a heading. Disposition is exactly one of `in-scope`, `deviates: <why>`, `deferred: <where>`, `venue: <env> - <observation>`, `elsewhere: <repo>`; default `in-scope`. For ticket rows, never edit the row text: an ambiguous row stays `in-scope` with the chosen reading written as a Design clause, and a moved path or a workflow artifact (spec, plan, changelog, telemetry file) is a Design clause too, never a disposition and never asked. A row under a repo group matching a settled member is `in-scope`; encode that member's ownership through original AC indices in its leg's `scope:` using [legs.md](legs.md), with owned paths only in `design:`. A known nonmember repo group is `elsewhere: <repo>`, stated, never asked; `elsewhere:` creates no leg. A group matching no repo asks `A) this repo B) elsewhere: <name> C) repair the ticket - /skill:shape-ticket <ref>`. Replace `<name>` with the supplied unmatched group heading verbatim in option B, not a request to name a repo. Name a `venue:` row's enabling change in Design; `venue:` states where the observation can happen and is never `prd`, `prod`, or `production` - a row observable only in production is a wrong row. An `in-scope` row is a requirement as written; disposition reasons are never normative for the plan or the reviewer, so a `deviates:` reason that adopts part of a row restates that part as a Design clause. A `deferred:` destination is a tracker ref (`#N`, `owner/repo#N`, `ABC-123`), a spec path, or a URL; a prose destination with none of these is a gap at the PR gate.
|
|
21
21
|
|
|
22
22
|
**Cut question.**
|
|
23
23
|
|
|
@@ -29,9 +29,9 @@ The process cwd never changes; every command targets `$WORKTREE` or `$PRIMARY` e
|
|
|
29
29
|
Then call `phase_tracker({ action: "start", phase: "ship" })`.
|
|
30
30
|
|
|
31
31
|
## The Process
|
|
32
|
-
|
|
33
32
|
### Step 1: Verify Tests
|
|
34
33
|
**Hard verification gate.** Tests/format/lint must pass before presenting any options — including Discard. The user's stated intent to throw the branch away does not change whether the diff is in a verifiable state; verifying first surfaces accidental damage to unrelated code before the branch is gone forever. The skip rule below is the only exception.
|
|
34
|
+
Read [coordinated finish](reference/legs.md) once for `## Legs` activation, recorded contracts, per-leg Steps 1/3.5, the single Step 4 choice, Step 5 receipts and home strip-and-seal, and Step 6 cleanup. Apply its coordinated mechanics for multiple members; retain the ordinary path for one member or no section.
|
|
35
35
|
Reuse the selected run spec read in Input. Detect a rework PR subject by its `## Rework record`; use Input's header-linked route for `**PR:**`, never discover by an open PR on `$FEATURE`. For the rework route only, read every top-level `PR:`/`Pre-rework head:` pair, home first, retaining each full SHA; missing pre-head -> stop naming the spec path. Set `PRE_REWORK_HEAD` to home's SHA. Read only combined capitalized `Base:`, `Keeps:`, `Changes:`, `Dropped claims:`, `Scoped tests:` fields; ignore lowercase provenance under `### PR #<N>`. For N=1, read `Threads:` directly after `Pre-rework head:` and retain the provenance subsection without changing finish output. Confirm only home with `gh pr view <N> --json number,url,headRefName,baseRefName,state` (use the record's repository): non-`OPEN` -> stop: `PR #N is <state>; the rework cannot be pushed to it.`; headRefName != `$FEATURE` -> stop naming both branches. Retain baseRefName for Step 3.
|
|
36
36
|
Recognize a ledger by line 1 exactly `# Ledger - loop engine`. For a ledger, use its `verification:` command throughout finish, including the minors round. For a rework PR subject with a task plan, use the union of every plan task's `Tests:` commands plus the executable lint/format commands in the header's `**Verification:**` line; treat `none - PR subject, scoped` as no header commands, not an empty task union. Capture this set and accepted-complete task evidence before stripping the plan. Apply the hard gate and skip rule below to this set. For every other subject with a task plan, run the plan header's `**Verification:**` set in the worktree: `(cd "$WORKTREE" && <command>)`. With no plan in this session, run the verification command(s) of the affected services from the gauntlet overrides file or `AGENTS.md` (look for "verification", "CI", or "test" sections).
|
|
37
37
|
**Skip rule.** Skip the run only when this set passed on a known clean commit in the verify phase of this session and no edit or write landed outside `<telemetry.dir>` since. Check the current tree: `git -C "$WORKTREE" diff --quiet <commit the run passed on> -- . ':!<telemetry.dir>'` must exit 0, and `git -C "$WORKTREE" status --porcelain --untracked-files=all -- . ':!<telemetry.dir>'` must exit 0 with empty output (`<telemetry.dir>` defaults to `.pi/gauntlet/telemetry`). These checks cover committed, staged, unstaged, and untracked changes outside telemetry. Otherwise run it once; a missing verified commit, a failed check, or uncertainty means run.
|
|
@@ -164,12 +164,11 @@ Amendments auto-applied (N):
|
|
|
164
164
|
|
|
165
165
|
Omit the block when N = 0.
|
|
166
166
|
|
|
167
|
-
**Rework PR subject - preflight and six-row menu.** Fetch origin with `git -C "$WORKTREE" fetch origin`; stop on failure. Run
|
|
168
|
-
|
|
|
169
|
-
|
|
170
|
-
| `git merge-base --is-ancestor <
|
|
171
|
-
| `git merge-base --is-ancestor origin/<headRefName> HEAD
|
|
172
|
-
Run the first proof for every recorded original head, home first; the first exit 1 stops with the table's exact message naming that PR's SHA. Run the second proof only for home. Run each proof with `git -C "$WORKTREE"`. Treat every exit other than 0 or 1 as a command error and stop with its output. For a withheld push only, separately prove `git -C "$WORKTREE" merge-base --is-ancestor <PRE_REWORK_HEAD> origin/<headRefName>`: exit 0 appends `(origin moved past the rework's base <PRE_REWORK_HEAD7>)`; exit 1 adds nothing; other exits stop as command errors. Divergence alone proves no origin advance.
|
|
167
|
+
**Rework PR subject - preflight and six-row menu.** Read the record form: `Rework base:` selects rebase mode. Only `Base:` in `merge:` form selects merge mode. A rebase record without `Rework base:` (`sync: unresolved` or an `unresolved`/`pending` member) stops before the menu: `rework sync incomplete for PR #<home>: no Rework base recorded; finish Task 1 first.` Fetch origin with `git -C "$WORKTREE" fetch origin`; stop on failure. Run proofs with `git -C "$WORKTREE"`; every exit other than 0 or 1 is a command error: stop with its output.
|
|
168
|
+
| Mode | Proof and decision |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Rebase | Once, `git merge-base --is-ancestor <Rework base> HEAD`: exit 1 stops with `PR branch history was rewritten: <sha7> is not an ancestor of HEAD; the rework must restart from the recorded rework base.` After fetch, resolve `origin/<headRefName>` with `git rev-parse`: origin equals `PRE_REWORK_HEAD` -> lease push; origin descends from `Rework base` and is an ancestor of HEAD (prove both with `git merge-base --is-ancestor`) -> non-force push; otherwise withhold row 1: `push withheld: origin/<headRefName> moved past <PRE_REWORK_HEAD7>`. |
|
|
171
|
+
| Merge | For every recorded original head, home first, `git merge-base --is-ancestor <PRE_REWORK_HEAD> HEAD`: first exit 1 stops with `PR branch history was rewritten: <PRE_REWORK_HEAD7> is not an ancestor of HEAD; the rework must be re-merged, not rebased.` Only for home, `git merge-base --is-ancestor origin/<headRefName> HEAD`: exit 0 offers non-force push; exit 1 withholds: `push withheld: origin/<headRefName> is at <sha7>, local HEAD at <sha7>; a non-force push cannot land`. For that withheld push, prove `<PRE_REWORK_HEAD>` ancestor of `origin/<headRefName>`: exit 0 appends `(origin moved past the rework's base <PRE_REWORK_HEAD7>)`; exit 1 adds nothing. Divergence alone proves no origin advance. |
|
|
173
172
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) for rendering and numeric replies. Present:
|
|
174
173
|
```
|
|
175
174
|
gauntlet: gate=finishing-a-development-branch/step-4
|
|
@@ -261,21 +260,14 @@ For the close-absorbed-PR question, start the message with `gauntlet: gate=finis
|
|
|
261
260
|
| Recorded `decline` | `declined - <reason>` |
|
|
262
261
|
| Successful fetch, empty set | `Threads: none` |
|
|
263
262
|
| Fetch failure | `Threads: not fetched (<reason>)` |
|
|
264
|
-
Count naming commits with `git -C "$WORKTREE" log --first-parent --format=%h --grep '<thread id>' <merge-sha | PRE_REWORK_HEAD>..HEAD` (
|
|
265
|
-
Run the existing strip-and-seal block with `--option pr --base origin/<baseRefName>` and the selected spec; retain its stop-on-error behavior. This seal measures the whole PR, not rework-only; never use PRE_REWORK_HEAD as its base. Then:
|
|
266
|
-
|
|
267
|
-
git -C "$WORKTREE" update-ref refs/gauntlet/pre-rework/pr-<N> <PRE_REWORK_HEAD>
|
|
268
|
-
```
|
|
269
|
-
Write this ref for every recorded PR with its own number and original SHA; stop on update-ref failure. Push only home, non-force:
|
|
270
|
-
```bash
|
|
271
|
-
git -C "$WORKTREE" push --no-follow-tags origin HEAD:refs/heads/<home headRefName>
|
|
272
|
-
```
|
|
273
|
-
Save the pushed home head SHA on success. Report a rejected push once, skip body editing and closure, name members left open, and return to the menu without retrying or forcing. Preserve the worktree.
|
|
263
|
+
Count naming commits with `git -C "$WORKTREE" log --first-parent --format=%h --grep '<thread id>' <Rework base | merge-sha | PRE_REWORK_HEAD>..HEAD` (use the first recorded value present). A touched file, grep match, or first-parent filter alone is not completion proof.
|
|
264
|
+
Run the existing strip-and-seal block with `--option pr --base origin/<baseRefName>` and the selected spec; retain its stop-on-error behavior. This seal measures the whole PR, not rework-only; never use PRE_REWORK_HEAD as its base. Then probe each recorded PR with its own number using `git -C "$WORKTREE" rev-parse -q --verify refs/gauntlet/pre-rework/pr-<N>`; only when absent, run `git -C "$WORKTREE" update-ref refs/gauntlet/pre-rework/pr-<N> <PRE_REWORK_HEAD>` with that PR's original SHA. Preserve existing refs and stop on command error or update-ref failure. Push only home with the preflight-selected form: lease case `git -C "$WORKTREE" push --no-follow-tags --force-with-lease=<home headRefName>:<PRE_REWORK_HEAD> origin HEAD:refs/heads/<home headRefName>`; other admitted cases (including merge records) `git -C "$WORKTREE" push --no-follow-tags origin HEAD:refs/heads/<home headRefName>`.
|
|
265
|
+
Save the pushed home head SHA on success. A lease refusal (`stale info`) skips body editing and closure, names members left open, preserves the worktree, and returns with row 1 withheld: `push withheld: origin/<headRefName> moved past <PRE_REWORK_HEAD7>`; no retry, no reset. Report any other rejected push once, skip body editing and closure, name members left open, and return to the menu without retrying or forcing. Preserve the worktree.
|
|
274
266
|
After a successful push, fetch only home's description fresh with `gh pr view <N> --json body` in the record's repository. Decode the JSON body without trimming or shell command substitution (which loses trailing newlines). Create a scratch body file with `mktemp` outside the repo; write the existing body bytes exactly, then one blank line, then this block:
|
|
275
267
|
```markdown
|
|
276
268
|
## Rework
|
|
277
269
|
|
|
278
|
-
Before: <PRE_REWORK_HEAD> (local ref `refs/gauntlet/pre-rework/pr-<N>` in the rework checkout
|
|
270
|
+
Before: <PRE_REWORK_HEAD> (local ref `refs/gauntlet/pre-rework/pr-<N>` in the rework checkout)
|
|
279
271
|
Absorbs: #13 (<url>), #14 (<url>)
|
|
280
272
|
Spec: <spec path> at <HEAD7>
|
|
281
273
|
Keeps: <from the record>
|
|
@@ -287,7 +279,13 @@ Threads:
|
|
|
287
279
|
- <path>:<line> - <resolution for this PR>
|
|
288
280
|
```
|
|
289
281
|
Instantiate `Absorbs:` from every non-home pair in record order; omit it for N=1. Label each PR Threads list `#<N>:` for N>1; retain the unchanged unlabeled list for N=1. Put `supersedes the description above` on the block's second line only when every original claim is dropped. Use `Threads: none` or `Threads: not fetched (<reason>)` instead of the list for those outcomes. Run `gh pr edit <N> --body-file <scratch-file>` in the record's repository without another approval. On body fetch/edit failure, keep the push and print the block for manual paste with the error; never replace the description with just the block. Skip closure on body fetch/edit failure and name members left open.
|
|
290
|
-
Only after a successful push and successful home body edit, refresh each member with `gh pr view <N> -R <owner/repo> --json state,headRefOid`. Fetch each refreshed head that is not yet local (`git -C "$WORKTREE" fetch origin <current headRefOid>`; for a fork member use its head repository URL) before the ancestry test. Skip and name a member whose head fetch fails: `#14 skipped: head <sha7> not fetchable`. Require state `OPEN`
|
|
282
|
+
Only after a successful push and successful home body edit, refresh each member with `gh pr view <N> -R <owner/repo> --json state,headRefOid`. Fetch each refreshed head that is not yet local (`git -C "$WORKTREE" fetch origin <current headRefOid>`; for a fork member use its head repository URL) before the ancestry test. Skip and name a member whose head fetch fails: `#14 skipped: head <sha7> not fetchable`. Require state `OPEN` in both modes; otherwise name `#14 skipped: state CLOSED`. In merge mode require `git -C "$WORKTREE" merge-base --is-ancestor <current headRefOid> <pushed home head>` exit 0; otherwise name `#14 skipped: head moved to <sha7>, not in home`. In rebase mode require current head equal to its recorded pre-rework head; otherwise name `#14 skipped: head moved to <sha7>`. Validate that member's recorded replay outcome:
|
|
283
|
+
| Outcome | Rebase eligibility proof |
|
|
284
|
+
|---|---|
|
|
285
|
+
| `<first7>..<last7>` | `git -C "$WORKTREE" merge-base --is-ancestor <last7> <pushed home head>` exits 0. |
|
|
286
|
+
| `empty` or `(already landed)` | `git -C "$WORKTREE" cherry <pushed home head> <pre-rework head>` succeeds with no `+` line. |
|
|
287
|
+
| Missing, unresolved, pending, or failed proof | Withhold closure and name the member and reason. |
|
|
288
|
+
Treat unexpected Git exits and failed refreshes as errors, withhold closure and report the reason; merge nothing implicitly.
|
|
291
289
|
Ask nothing when none qualify or N=1. Otherwise render one gated question before marking ship complete. Instantiate each actual eligible target and its exact comment using its recorded pre-rework SHA7 and home's number/URL; the two-member rendering is:
|
|
292
290
|
```text
|
|
293
291
|
gauntlet: gate=finishing-a-development-branch/pr-subject-row-1
|
|
@@ -297,6 +295,7 @@ Close the absorbed PRs with these comments?
|
|
|
297
295
|
1 - yes, close #13, #14
|
|
298
296
|
2 - no, leave them open
|
|
299
297
|
```
|
|
298
|
+
In rebase mode replace each displayed comment with `Reworked into #12 (<home url>) by the gauntlet; this PR's commits are replayed there as <first7>..<last7>.` for a range, or `Reworked into #12 (<home url>) by the gauntlet; this PR's commits are already contained there.` for `empty` or `(already landed)`. Keep the displayed merge comments in merge mode.
|
|
300
299
|
On `1`, re-fetch state/head immediately before each `gh pr close <N> --comment "<that line's text>" -R <owner/repo>`. Execute only the displayed target/text pairs in the displayed repository; never pass `--delete-branch`. Skip and report any target whose state or head changed after approval, or whose refresh fails, rather than acting under stale authorization. Report a failed close once, never retry. On `2`, leave members open. Then mark ship complete and report each member outcome: `Closed: #13, #14`, `Closed: #13; #14 close failed (<error>)`, or `Member PRs #13, #14 left open.` Instantiate actual members in all summaries, including partial outcomes and skipped members; for N=1 omit every member line and question.
|
|
301
300
|
Rows 2-6, withheld/failed ancestry, withheld/rejected push, and failed body fetch/edit never offer closure; name untouched members with `Member PRs #13, #14 left open.` Post no review-thread replies, merge no PR, change no ticket state, and close no PR other than the absorbed members through the question above.
|
|
302
301
|
#### Option 1: Push and Create PR
|
|
@@ -381,7 +380,7 @@ If confirmed: Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `
|
|
|
381
380
|
|
|
382
381
|
**Only runs for the Squash-merge and Discard options (3 and 5).** The PR, draft PR, and Keep options always preserve the worktree.
|
|
383
382
|
|
|
384
|
-
|
|
383
|
+
Use recorded `contract:` lines when the spec carries `## Legs`, including one member; apply the recorded cleanup authority from the Step 1 reference. 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).
|
|
385
384
|
|
|
386
385
|
**Keyed contract** - the section has at least one of `- home:`, `- create:`, `- destroy:`:
|
|
387
386
|
|
|
@@ -410,7 +409,7 @@ Removal precedes branch deletion in both options; `git branch -d`/`-D` fails whi
|
|
|
410
409
|
|
|
411
410
|
| Option | Merge | Push | Keep Worktree | Cleanup Branch | Plan strip + record seal |
|
|
412
411
|
|---|---|---|---|---|---|
|
|
413
|
-
| PR row 1. Push to PR branch | - | yes (non-force) | yes | - | yes (whole PR; see row 1 recipe) |
|
|
412
|
+
| PR row 1. Push to PR branch | - | yes (lease; non-force for merge records) | yes | - | yes (whole PR; see row 1 recipe) |
|
|
414
413
|
| 1. Create PR | - | yes | yes | - | yes (guarded, on the branch before push) |
|
|
415
414
|
| 2. Create draft PR | - | yes | yes | - | yes (guarded, on the branch before push) |
|
|
416
415
|
| 3. Squash-merge locally | yes (squash) | - | - | yes (after Step 6 removal) | yes (guarded, on the branch before squash) |
|
|
@@ -472,7 +471,7 @@ Once the merge (and any deploy) has landed, `/skill:check-delivery <ticket-ref>`
|
|
|
472
471
|
- Merge without verifying tests on result
|
|
473
472
|
- Delete work without confirmation
|
|
474
473
|
- Force-push without explicit request
|
|
475
|
-
- Force-push a PR-subject rework
|
|
474
|
+
- Force-push a PR-subject rework without `--force-with-lease=<headRefName>:<PRE_REWORK_HEAD>`, or retry after a refused lease
|
|
476
475
|
- Remove a worktree before confirming merge success
|
|
477
476
|
- Clean up worktrees you didn't create (provenance check)
|
|
478
477
|
- Retry a failed `destroy:` with `git worktree remove --force`
|