pi-gauntlet 7.40.1 → 7.41.1
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 +18 -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 +1 -1
- package/skills/brainstorming/gatherer.md +14 -1
- package/skills/brainstorming/reference/amendment-surface.md +13 -1
- package/skills/brainstorming/reference/legs.md +187 -0
- package/skills/brainstorming/reference/pr-subject.md +1 -1
- package/skills/brainstorming/reference/spec-finalization.md +14 -0
- package/skills/brainstorming/reference/spec-pr.md +42 -5
- package/skills/brainstorming/reference/ticket-acceptance.md +2 -2
- package/skills/finishing-a-development-branch/SKILL.md +2 -2
- package/skills/finishing-a-development-branch/reference/legs.md +76 -0
- package/skills/finishing-a-development-branch/reference/spec-pr.md +12 -4
- package/skills/gauntlet-handoff/SKILL.md +2 -2
- package/skills/gauntlet-resume/SKILL.md +3 -2
- package/skills/gauntlet-resume/reference/brief-contract.md +37 -3
- package/skills/gauntlet-resume/reference/reconstruction.md +4 -0
- package/skills/gauntlet-resume/reference/seed.md +2 -0
- package/skills/loop-implementation/SKILL.md +89 -2
- package/skills/subagent-driven-development/SKILL.md +10 -0
- package/skills/using-git-worktrees/SKILL.md +58 -21
- package/skills/using-git-worktrees/reference/pr-head.md +25 -1
- package/skills/writing-plans/SKILL.md +8 -0
- 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.1",
|
|
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.5"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"yaml": "^2.9.0"
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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.
|
|
@@ -33,7 +33,7 @@ Immediately after ordered admission and before binding, classify N=1 read-only.
|
|
|
33
33
|
|---|---|
|
|
34
34
|
| Shape fails | Pass the selected SYNC to provisioning. Continue unchanged through bind, gather, scout, and Rework record. |
|
|
35
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 |
|
|
36
|
+
| Shape and marker pass | Count carried `### Leg:` blocks under `## Legs` from the same `git show <headRefOid>:<path>` used for the marker, before home provisioning. Force `SYNC=merge`. Zero/one block keeps home-only pr-head checkout/base merge/Step 4. For observed N>1 blocks pass that coordinated marked context to pr-head's home base-sync recovery; malformed blocks missing repo, branch or contract stop naming the block and preserve home. Provision only the one-element admitted PR array, then follow spec-pr.md's re-gate and its coordinated settlement after home's Step 4. Skip binding and all before-gather thread queries. Treat draft and ready PRs equally. |
|
|
37
37
|
|
|
38
38
|
## Relatedness before provisioning
|
|
39
39
|
|
|
@@ -25,6 +25,13 @@ Spec-writing replaces the context draft, in this exact order:
|
|
|
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
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):
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Shared predicate and marker
|
|
4
4
|
|
|
5
|
-
Resolve `gauntlet_setting({ key: "flowGuards" })` and use its `specDirs`. Inspect `git diff --name-status <base>...<head>` and every modified file's hunks against the same pinned endpoints. Require exactly one `A` under a resolved spec dir: the selected spec. Require every other entry to be an `M` under a spec dir that adds only active supersession-banner lines plus adjacent blank lines and removes nothing. Read [superseding.md](superseding.md): use `> **Superseded by:**` by default or the declared override syntax; enforce title-adjacent placement and append-only insertion below existing banners. Reject renames, deletes, multiple additions, non-spec paths, and arbitrary modifications. Evaluate the whole diff, not commit count: earlier implementation, non-default-source changes, and an ignore-file commit all count.
|
|
5
|
+
Resolve home `gauntlet_setting({ key: "flowGuards" })` and use its `specDirs`. For a companion, read that repo's `.pi/settings.json` by file with [legs.md](legs.md)'s preset/default rules (`doc/specs`, `docs/specs` by default), never session `gauntlet_setting`; require the sole added file at its recorded `<spec-dir>/<home spec filename>`. Inspect `git diff --name-status <base>...<head>` and every modified file's hunks against the same pinned endpoints. Require exactly one `A` under a resolved spec dir: the selected spec. Require every other entry to be an `M` under a spec dir that adds only active supersession-banner lines plus adjacent blank lines and removes nothing. Read [superseding.md](superseding.md): use `> **Superseded by:**` by default or the declared override syntax; enforce title-adjacent placement and append-only insertion below existing banners. Reject renames, deletes, multiple additions, non-spec paths, and arbitrary modifications. Evaluate the whole diff, not commit count: earlier implementation, non-default-source changes, and an ignore-file commit all count.
|
|
6
6
|
|
|
7
|
-
Keep shape separate from approval. Read the added spec with `git show <head>:<spec path>`; match `^\*\*Engine:\*\*[ \t]+deferred[ \t]*$` only in the header before the first `## `. Use that marker plus shape for re-gating. Use shape alone for publication. Ignore draft status, labels, PR body, telemetry, and audit presence as classification proof. Route N>1 through rework.
|
|
7
|
+
Keep shape separate from approval. Read the added spec with `git show <head>:<spec path>`; match `^\*\*Engine:\*\*[ \t]+deferred[ \t]*$` only in the header before the first `## `. Use that marker plus shape for re-gating. Use shape alone for publication. Ignore draft status, labels, PR body, telemetry, and audit presence as classification proof. Route a list of N>1 PRs through rework; count carried Legs separately.
|
|
8
8
|
|
|
9
9
|
## Publish option 6
|
|
10
10
|
|
|
11
11
|
Decode the reply before writes. A hidden `6` gets the clarifying question naming rendered choices. A funded `6` is malformed: re-present, write nothing. `3` plus `6` prints the audit and re-presents without approval; `6` plus a change request revises and re-presents.
|
|
12
12
|
|
|
13
|
-
On clean `6`, edit `**Amend-grant:** none` and exactly one `**Engine:** deferred` directly below it. A 6 never grants. Stage the spec with `git -C <worktree> add -- <spec path>`, then `git -C <worktree> commit --amend --no-edit -q`; verify both lines through `git -C <worktree> show HEAD:<spec path>`. Stop on failure.
|
|
13
|
+
On clean `6`, edit home only: `**Amend-grant:** none` and exactly one `**Engine:** deferred` directly below it. A 6 never grants. Stage the spec with `git -C <worktree> add -- <spec path>`, then `git -C <worktree> commit --amend --no-edit -q`; verify both lines through `git -C <worktree> show HEAD:<spec path>`. Stop on failure.
|
|
14
|
+
|
|
15
|
+
Read the committed home spec's `## Legs` in [legs.md](legs.md) order. Carry Worktree First paths; treat recorded repo, branch, contract, spec-dir, home and create as authoritative. Keep the one-block and legacy recipe below verbatim (one push/PR/cleanup, no companion prefixes). For N>1 run the coordinated passes below instead of executing the home recipe immediately: they invoke its preflight last, then its push/create after companion publication, and replace its output/cleanup ordering. Keep companion files unchanged.
|
|
14
16
|
|
|
15
17
|
Resolve the default base once, never substitute the worktree creation ref:
|
|
16
18
|
|
|
@@ -40,10 +42,45 @@ EOF
|
|
|
40
42
|
|
|
41
43
|
After URL output call `phase_tracker({ action: "complete", phase: "brainstorm" })`. Read finishing's [Step 6](../../finishing-a-development-branch/SKILL.md#step-6-cleanup-workspace), using only its ownership test and wrapper selection: resolve home/destroy, legacy native script, or native remove/prune. Disable every branch-deletion step, including within a destroy wrapper: verify the wrapper preserves the branch before running it; stop cleanup and report when it cannot. Never delete the local branch. Report host-owned or failed removal with checkout path and command output; explain that later `brainstorming #N` hits pr-head's checked-out-at-another-path stop until that checkout is gone. Start no plan or loop, produce no handoff brief, and leave telemetry unchanged.
|
|
42
44
|
|
|
45
|
+
### Coordinated publication passes
|
|
46
|
+
|
|
47
|
+
Finish preflight for every companion in declared order, then home, before any push:
|
|
48
|
+
|
|
49
|
+
1. Resolve each companion's default with `DEFAULT=$(gh repo view <owner/name> --json defaultBranchRef -q .defaultBranchRef.name)` (positional repo, not `-R`); require nonempty. Run `git -C <companion worktree> fetch origin "$DEFAULT"` and `git -C <companion worktree> diff --name-status origin/$DEFAULT...HEAD`. Apply the shared predicate with that member's own dirs and recorded added file.
|
|
50
|
+
2. Discover remote publication with `git -C <companion worktree> ls-remote --exit-code --heads origin <branch>`. Exit 2 means absent: attempt no branch fetch. Exit 0 means present: fetch `origin <branch>`, then read full `origin/<branch>` and HEAD SHAs for publication. Any other exit is a command failure, never absence; ignore stale tracking refs as discovery proof.
|
|
51
|
+
3. Run home's default/fetch/shape recipe last. On any shape failure print the member, offending name-status lines and `origin/<default>`, retain every amended spec and checkout, and redraw with `Withheld: draft PR - <repo> diff against origin/<default> is not spec-only (<paths>)` replacing 6; keep implementation approvals. On gh/default/fetch/ls-remote failure stop naming member and command output. Nothing has been pushed on either preflight failure.
|
|
52
|
+
|
|
53
|
+
Publish companions in declared order from the preflight observations:
|
|
54
|
+
|
|
55
|
+
| Observation | Action |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Absent | `git -C <companion worktree> push -u origin <branch>`; record published member. |
|
|
58
|
+
| Present, full remote SHA equals HEAD | Skip with `<repo>: already published`; include it in the published inventory. |
|
|
59
|
+
| Present, different full SHA | Print repo, both full SHAs and already-published members; retain every checkout and list paths; re-present 6 retryable after by-hand resolution. Never force or reconcile. |
|
|
60
|
+
| Push rejected | Print member and git output, already-published members and retained paths; re-present 6 retryable. Retry both passes; equality skips completed companions. |
|
|
61
|
+
|
|
62
|
+
Then run home's existing push/create recipe. Home push/create failures keep its failure rows and also list published companions; never roll back. After home create failure freeze the published handoff commit: the create-only retry above does not amend or push any member or rerun publication passes. On success print `pushed: <repo> origin/<branch>` for each companion before the single home URL, then complete brainstorm.
|
|
63
|
+
|
|
64
|
+
Clean companions in declared order, then home. Apply finishing Step 6's ownership test and wrapper selection to each recorded contract (legacy without Legs keeps its reread). Verify every wrapper preserves its branch before execution; refuse unsafe wrappers without native fallback. Report each host-owned/refused/failed removal with repo, path and command output, leave its branch intact, and attempt all remaining cleanups even after refusal. Keep branches everywhere, including after owned built-in remove/prune. Write no receipt, companion PR, telemetry or brief.
|
|
65
|
+
|
|
66
|
+
### Coordinated marked settlement
|
|
67
|
+
|
|
68
|
+
Use only the N>1 context observed by pr-subject's marked classifier at the original PR head. Preserve home's provisioned tree on every stop. Read the committed Legs in order; reject missing repo/branch/contract, mismatched shared branches or invalid blocks without falling into ordinary sibling discovery.
|
|
69
|
+
|
|
70
|
+
1. Settle only recorded companions with [legs.md](legs.md)'s first-found home overrides at `BASE_SHA` (`git show <BASE_SHA>:<overrides path>`), sibling parser and `<home PRIMARY parent>/<NAME>` paths. Match repo identifiers before probing paths; validate declaration, checkout, stored origin identity and nonhome canonical path. Never activate unrecorded siblings or infer membership from existing PRs. On no match stop: `leg <repo> matches no sibling declaration in <overrides path>`.
|
|
71
|
+
2. Preflight every companion before creating or syncing any companion: run `git -C <PATH> fetch origin` in its primary, then `git -C <PATH> ls-remote --exit-code --heads origin refs/heads/<branch>`. Exit 2 means missing: take the missing-remote stop below even when a stale `origin/<branch>` still resolves. Exit 0 proves live existence; require the recorded shared `origin/<branch>`. On any fetch failure or other lookup exit stop naming member and command output, never diagnose absence. Resolve its own settings/overrides home/create with legs.md's preset/default rules. Compare both portable values with the recorded contract. Stop on drift: `contract drift for <repo>: recorded <key>: <recorded value>, resolved <current value>; amend the recorded contract or restore the repo convention, then rerun brainstorming #N`. Never silently choose between them. Resolve a user amendment through the existing home-plus-companion reconciliation path.
|
|
72
|
+
3. Permit fetch/tracking-ref updates during preflight, but no worktree add, local branch/ref update or merge. A missing last declaration/remote prevents provisioning even the first companion. On missing remote say `origin/<branch> is missing in <repo>; on the machine that ran option 6, push <branch> from that companion's checkout, then rerun brainstorming #N`. For recovery, first verify the leg file's commit with `git log -1 --format=%H refs/heads/<branch> -- <spec-dir>/<home spec filename>` in the retained tree or primary without checking out or modifying the primary, then run `git push -u origin <branch>` from that existing branch and rerun. No commit anywhere means an incomplete handle: stop; regenerate nothing. An unrelated branch-tip commit does not prove the file exists.
|
|
73
|
+
4. After every companion passes, invoke using-git-worktrees once each with explicit `ROOT` = primary, shared `BRANCH`, `REMOTE_BRANCH=existing`. Use pr-head's companion mode and race backstop; carry each Step 4 report, including `Base sync recovered: <sha7>` and its proof. Never construct companion PR fields, pre-rework refs, thread queries or `MEMBER_HEADS`. Do not bypass wrapper safety (`-b`/`-B` falls back to native existing-branch creation) or invent a second provisioning path.
|
|
74
|
+
5. On unresolved companion base merge stop: `base merge unresolved for <repo> (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`. Keep all trees and refs; on every stop print `Preserved created legs:` listing home and every already-provisioned companion, with repo and path. Never remove any on retries. Preserve home's recovered base-sync proof even if a later companion stops; rerun using the same home recovery path.
|
|
75
|
+
|
|
76
|
+
At gate readiness list every Worktree First path home first, then companions in recorded order. Offer the ordinary AC-dependent 1/2/4/5 choices and optional pinned audit 3 below, and `Withheld: draft PR - #N already exists`. Keep ordinary pinned-audit and approval persistence below; no companion approval record or second council.
|
|
77
|
+
|
|
43
78
|
## Re-gate a marked spec PR
|
|
44
79
|
|
|
45
80
|
Reuse [pr-head](../../using-git-worktrees/reference/pr-head.md)'s checkout, base merge, and Step 4 report, not its before-gather thread fetch. Preserve its checked-out-at-another-path stop. On observed `merge: unresolved - <files>`, print `base merge unresolved for PR #N (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`; preserve checkout, render no gate, write no approval or repair task.
|
|
46
81
|
|
|
82
|
+
For observed N>1 carried Legs, finish [coordinated marked settlement](#coordinated-marked-settlement) after home's Step 4 report and before rendering the gate. For zero/one block keep the home-only route unchanged.
|
|
83
|
+
|
|
47
84
|
Skip ticket binding, context-builder, review threads, gather, questionary, spec-writing, inline lint, council, worker, and the second predecessor pass. Carry trailing intent as `Intent carried from the command: <text>` beside the gate.
|
|
48
85
|
|
|
49
86
|
Pin the originating audit once on the PR branch:
|
|
@@ -57,6 +94,6 @@ Recognize an audit only with all `Applied:`, `Deferred:`, and `Rejected:` labels
|
|
|
57
94
|
|
|
58
95
|
Reuse [User Review Gate](spec-finalization.md#user-review-gate)'s summarizer dispatch, fresh temp path, last content-producing Read, verbatim render, degraded path, and unconditional temp cleanup, but skip its unconditional initial spec commit. Render Scope cuts and drafted rows from the carried spec. Offer 1/2/4/5 and optional 3; with zero AC rows omit 4/5 and explain `Loop engine unavailable: this spec has no acceptance-criteria rows.` Withhold 6 with `Withheld: draft PR - #N already exists`; clarify a 6 reply by naming rendered choices.
|
|
59
96
|
|
|
60
|
-
For a change request, revise and stage the spec and reconciled banners; make a new commit without the old audit body (no new council ran).
|
|
97
|
+
For a change request, revise and stage the spec and reconciled banners; make a new commit without the old audit body (no new council ran). For coordinated changes touching Problem, shared Design, Errors and edge cases, Out of scope, companion-binding clauses or a Leg block, rewrite and commit affected companion files in their live worktrees per [legs.md](legs.md) before re-dispatching the summarizer with a fresh temp path and re-presenting. Complete the amendment only when carried parts agree; infer no second council or approval.
|
|
61
98
|
|
|
62
|
-
For approval 1/2/4/5,
|
|
99
|
+
For approval 1/2/4/5, persist on home only; leave companion files untouched. Decode grant/funding under the ordinary gate. Replace deferred with waves or loop, write the decoded `**Amend-grant:**`, and write exactly one `**PR:** <owner/repo#N>` directly below Engine, lowercasing owner/repo parsed from the admitted PR URL. Stage and make a new commit `spec: select engine and grant for PR #N`; never amend a published commit. Verify all three fields through `git show HEAD:<spec path>` before brainstorm completion and the selected writing-plans/loop-implementation chain. Stop on persistence or verification failure. The unmarked route's gate approval (1/2/4/5) applies this same new-commit persistence: `waves` or `loop` as the engine, the decoded grant, and `**PR:**` directly below `**Engine:**`, never `--amend`.
|
|
@@ -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.
|
|
@@ -380,7 +380,7 @@ If confirmed: Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `
|
|
|
380
380
|
|
|
381
381
|
**Only runs for the Squash-merge and Discard options (3 and 5).** The PR, draft PR, and Keep options always preserve the worktree.
|
|
382
382
|
|
|
383
|
-
|
|
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).
|
|
384
384
|
|
|
385
385
|
**Keyed contract** - the section has at least one of `- home:`, `- create:`, `- destroy:`:
|
|
386
386
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Coordinated finish
|
|
2
|
+
|
|
3
|
+
## Activation and authority
|
|
4
|
+
|
|
5
|
+
Read the home spec's `## Legs` once at Step 1. Use the membership, portable identifiers, scope validation and path resolution in [the leg grammar](../../brainstorming/reference/legs.md). Resolve selected primaries from home's declared siblings and worktrees from the brief or recorded `home:` pattern. Validate branch, repository identity and each companion's full `**Home:**` tuple before acting. Admit a missing delivered worktree only through a validated receipt below.
|
|
6
|
+
|
|
7
|
+
Use recorded `contract:` lines for every spec with `## Legs`, including one member. Amend the home block and affected companion file before using a changed contract; do not reread overrides to replace it. For one member, return to the ordinary finish steps using that block's contract: keep exactly one `### Leg:`, no companion artifact, `legs:` brief block, receipt, `--leg` argument or companion loop. For no `## Legs`, use the ordinary home-only flow and Step 6's overrides reread.
|
|
8
|
+
|
|
9
|
+
For more than one member, apply the following steps instead of the home-only verification, delivery and cleanup mechanics. Keep Step 3.5's disposition protocol, the home's review policy, Step 4 menu and confirmations. Keep machine-local paths out of committed bodies and messages.
|
|
10
|
+
|
|
11
|
+
## Durable receipts
|
|
12
|
+
|
|
13
|
+
Keep one home-owned file per delivered leg at `<home git common dir>/gauntlet/receipts/<spec filename>/<repo>`, where `<home git common dir>` is `git -C <home worktree> rev-parse --path-format=absolute --git-common-dir` (the home primary's `.git`, e.g. `/work/repo-a/.git/gauntlet/receipts/shared.md/repo-b`) - never inside any worktree, so a removed home tree never takes a receipt with it. Include the full spec filename, including `.md`, and preserve repo path segments; create directories before writing. Git metadata is never tracked, so no exclude entry is needed. Treat them as flow restoration artifacts, not telemetry, approval evidence or proof without validation.
|
|
14
|
+
|
|
15
|
+
Write after each delivery attempt that produced a PR or squash commit, including failed post-squash verification:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
attempted-head: <full feature SHA attempted>
|
|
19
|
+
delivered: pr <url> <full delivered PR head> | squash <full squash SHA>
|
|
20
|
+
verification: passed | <actual verification failure>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Choose one `delivered:` alternative. Use `verification: passed` only for successful verification; preserve the error otherwise. Retain the selected spec path, recorded commands, membership and accepted task evidence before stripping the plan, and carry the receipt locations into the brief. On fresh-session retry admit a stripped plan only when every companion has a receipt; validate each receipt rather than inferring delivery from missing files. Recover commands from the spec's recorded contract, not the absent plan.
|
|
24
|
+
|
|
25
|
+
Before checkout-based verification and conformance fan-out, validate receipt identity against the selected spec, repo and recorded delivery choice; reconcile it with the selected action before delivery. Malformed, mismatched or unverifiable receipts leave the leg unlanded; stop on an unavailable boundary rather than creating duplicate delivery. Apply these proofs:
|
|
26
|
+
|
|
27
|
+
| Receipt | Required proof and retry action |
|
|
28
|
+
|---|---|
|
|
29
|
+
| PR | Fetch the receipt URL using `gh pr view <url> --json state,headRefOid` in its repository. Require `OPEN`, head equal to the attempted head, delivered head equal to attempted head, passed verification, and unchanged current feature head when the tree exists. A stale head must re-push the verified branch non-force and update the existing PR, not create another PR. Refresh and rewrite the receipt after success. A closed PR is not a validated skip; stop for disposition. |
|
|
30
|
+
| Squash | Require `verification: passed` and the squash SHA reachable from the primary's default branch: `git -C <primary> merge-base --is-ancestor <squash SHA> <default branch>` must exit 0. Confirm the current attempted feature head when available. For recorded failed post-squash verification, rerun verification, not squash, against the delivered primary state; rewrite the receipt on pass. Require the recorded squash to remain reachable and stop on unrelated primary movement requiring review. |
|
|
31
|
+
|
|
32
|
+
Never use feature-head ancestry as proof of squash delivery. Resolve the actual primary default branch, not an assumed `main`. Treat unexpected Git exits as errors, not negative proofs. Preserve receipts on every failure, including seal failure and cleanup refusal.
|
|
33
|
+
|
|
34
|
+
## Verification and closure - Steps 1 and 3.5
|
|
35
|
+
|
|
36
|
+
Exempt a leg with a validated receipt and a missing worktree from checkout-based verification and conformance. Run fresh checks for every unlanded leg; stop on a missing unlanded worktree. Handle failed-squash verification in the delivered primary through the receipt retry action above; replace feature-checkout checks with that primary verification even when the feature tree still exists.
|
|
37
|
+
|
|
38
|
+
Before Step 4, run every leg's recorded verification set with that leg's worktree as command cwd, except the receipt-proven exemptions above, then perform conformance review with that leg's `cwd`, Rules and owned AC rows. Use original AC indices from `scope:`; shared rows belong to each named owner and unclaimed rows default home. Apply Step 1's hard gate and skip proof independently per leg. Route fixes and commits through `git -C <owning worktree>`, never home's checkout for companion code.
|
|
39
|
+
|
|
40
|
+
Retain each present member's audited head and tree, including staged, unstaged and untracked state. Immediately before delivery compare them to the current checkout; re-verify and re-review every changed leg before its delivery. Apply the same freshness check after disposition fixes and minors fixes. Aggregate closure before presenting one menu; no leg bypasses open dispositions.
|
|
41
|
+
|
|
42
|
+
Apply leg-local `piGauntlet.verifyBeforeShip` evidence to commands targeting that checkout. Read each primary's `.pi/settings.json` by file and merge the preset using the existing settings rules; do not use home's `gauntlet_setting` result or home's successful test flag as companion evidence. Use the recorded verification set, including when a retry has no plan.
|
|
43
|
+
|
|
44
|
+
## Execute one choice - Steps 4 and 5
|
|
45
|
+
|
|
46
|
+
Apply one chosen action to companions in declared sibling order, then home. Preserve every PR, draft and keep worktree and branch. Keep reports all retained locations without strip, seal, delivery or cleanup.
|
|
47
|
+
|
|
48
|
+
For a PR-subject home, compose the supported existing home action with companion delivery: row 1 pushes and edits the existing home PR through its recipe, rows 2-3 retain the existing-PR disclosure and refusal rather than attempting a duplicate, and squash/keep/discard retain their existing disclosures and confirmations. Deliver companions before the supported home ship action; keep absorbed-PR closure authorization separate and unchanged. Do not start fan-out for a home action withheld by preflight.
|
|
49
|
+
|
|
50
|
+
For PR, draft and squash:
|
|
51
|
+
|
|
52
|
+
1. Validate existing receipts first. Skip only receipt-proven delivery. Check freshness for every unlanded leg before its delivery.
|
|
53
|
+
2. Deliver each companion: for PR/draft, push with `git -C <worktree> push -u origin <branch>`, then run `gh pr create` in that worktree's cwd, adding `--draft` on every draft create. On retry of an existing PR use its URL and edit rather than duplicate create. For squash, use the existing Option 3 primary checkout/pull/merge/commit recipe and run that leg's recorded post-squash commands in the primary. Write its receipt even when those commands fail. No companion plan strip or telemetry seal runs.
|
|
54
|
+
3. Collect complete companion results, including validated skips. Capture the spec path and evidence before the home plan strip. Run home's strip-and-seal block with repeated `--leg <repo>=<sha|pr-url>`, one per companion. Never seal partial results. Compare collected `{ repo, sha }` or `{ repo, pr }` entries with an existing seal's `legs:` set; differences stop naming stored and collected results. Retain all receipts when the bin fails and print its output. Never write companion `.pi/gauntlet/telemetry/`.
|
|
55
|
+
4. Deliver home through the selected existing recipe after successful sealing, without running a second seal lacking the companion arguments. For PR-subject row 1 retain the whole-PR base and all body-edit/closure rules. Write home's receipt, including post-squash failures. Run cleanup only for squash, after successful post-squash verification.
|
|
56
|
+
|
|
57
|
+
Put `Home: <repo> <shared branch> <home spec path>` in every companion PR body and squash message. Respect each leg's PR body style. List every companion PR URL in the home PR body (including the existing home PR's rework block), and every companion squash SHA in home's squash message.
|
|
58
|
+
|
|
59
|
+
On the first delivery, verification or seal failure, stop fan-out and preserve delivered work and receipts. Print actual results, including validated skips, in member order:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Shipped: <repo> <sha|pr> ...
|
|
63
|
+
Not shipped: <repo> <reason> ...
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
A squash with failed post-verification belongs under Not shipped with its created SHA and error; do not conceal the commit. Include home when not delivered and every untouched remaining companion. Perform no rollback. A fresh-session retry validates the same receipts before continuing.
|
|
67
|
+
|
|
68
|
+
## Discard and recorded cleanup - Steps 5 and 6
|
|
69
|
+
|
|
70
|
+
List every member's branch, commit count, and worktree path as a resolved absolute path (the brief's or the recorded `home:` pattern expanded for this branch, e.g. `/work/repo-b/.worktrees/feature-shared-change`; never a pattern or placeholder) before one typed `discard` confirmation. Obtain exact confirmation once for the run, then clean every member, home included, through its recorded contract regardless of other members' refusals. Do not strip or seal for discard.
|
|
71
|
+
|
|
72
|
+
For cleanup, use the recorded `## cleanup` worktree command, else `destroy:`, with the configured teardown hook using pi-cohort's existing semantics, else the owned built-in matched against that leg's recorded `home:`. Execute from that leg's primary. Expand recorded `<name>` and `<branch>` as single shell words using Step 6's escaping and ownership proof; resolve other tokens before execution. Never use `git worktree remove` past a wrapper or hook failure. Leave unmatched host-owned trees and their branches preserved.
|
|
73
|
+
|
|
74
|
+
Clean companions in declared order, then home. Report a refusal as that leg's `failed` line, leave the tree intact, and continue the remaining cleanup attempts and the remaining report lines. After squash, stop only the refused companion's cleanup and attempt every remaining companion's recorded contract from its own primary; on any companion cleanup failure, skip home's cleanup and report `<home repo>: preserved - companion cleanup failed` to retain the home checkout for a fresh-session retry via /skill:gauntlet-resume. Delete a branch only after successful removal of its worktree. Run prune only for successful owned built-in removal, not after a wrapper. Report each repo's actual removed, preserved or failed state.
|
|
75
|
+
|
|
76
|
+
Remove receipts only after home delivery and all required cleanup succeed, and report that removal in one explicit line (`Home delivery and required cleanup succeeded; receipts removed`). Receipts live in the home primary's git dir, so worktree removal never touches them; when any required cleanup failed, report `receipts retained - required cleanup failed` and leave every receipt in place for the retry. PR/draft success has no cleanup requirement and preserves every worktree, so its receipts are removed right after the home PR lands. Keep retains receipts for later validation. Mark ship complete only after the chosen action succeeds for every member; never mark discard as shipped.
|
|
@@ -8,7 +8,7 @@ Resolve the selected run spec once: use the carried spec path or the active plan
|
|
|
8
8
|
gh pr view <N> -R <owner/repo> --json number,url,state,isDraft,headRefName,baseRefName
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Stop on query failure. Require OPEN, otherwise print `PR #N is <state>; the branch cannot be pushed to it.` Require headRefName == `$FEATURE`, otherwise stop naming both branches. Retain the live baseRefName for Step 3 (skip common-base probing), sealing, and squash.
|
|
11
|
+
Stop on query failure. Require OPEN, otherwise print `PR #N is <state>; the branch cannot be pushed to it.` Require headRefName == `$FEATURE`, otherwise stop naming both branches. Retain the live baseRefName for Step 3 (skip common-base probing), sealing, and squash. For N>1 `## Legs` blocks, read [Coordinated finish](legs.md) now: apply its activation/identity checks and "Verification and closure - Steps 1 and 3.5" instead of home-only verification. Retain every leg's recorded commands, own checkout cwd, Rules, original owned ACs, receipt-proven exemptions and audited-head/tree freshness checks. For one block or no `## Legs`, run full ordinary verification, not rework-scoped verification. Keep ordinary closure/conformance gates.
|
|
12
12
|
|
|
13
13
|
## Menu and preflight
|
|
14
14
|
|
|
@@ -26,14 +26,22 @@ Implementation complete. What would you like to do?
|
|
|
26
26
|
5. Discard this work (removes the worktree and local branch; the PR branch on origin is untouched)
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
For observed isDraft false replace row 2 with `2. Push to PR #N (already ready for review)`. Never convert ready to draft. Map rows 3-5 to ordinary Options 3-5,
|
|
29
|
+
For observed isDraft false replace row 2 with `2. Push to PR #N (already ready for review)`. Never convert ready to draft. Map rows 3-5 to ordinary Options 3-5, using legs.md's coordinated squash/keep/discard mechanics for N>1 blocks; retain typed discard confirmation and recorded ownership/cleanup. Option 3 squash seal uses `--option squash --base origin/<baseRefName>` and the selected spec.
|
|
30
30
|
|
|
31
31
|
## Push rows 1/2
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
For N>1 blocks, use this sequence instead of the standalone strip-and-seal recipe. Complete steps 1-2 for each companion in block order before the next companion. Start no companion fan-out for a home action withheld by menu preflight.
|
|
34
|
+
|
|
35
|
+
1. Apply legs.md "Execute one choice" steps 1-2 to companions in block order: validate receipts, check freshness, push `origin <branch>` and create each missing PR in its own worktree. Add `--draft` on row 2 creates; create ready PRs on row 1. Write home-owned receipts after delivery. Keep each companion body's `Home:` pointer. Run no companion strip or seal.
|
|
36
|
+
2. Reconcile receipt-proven companions too: query `gh pr view <url> --json state,headRefOid,isDraft` in that repository and apply legs.md's live identity/head/verification proofs. On row 1 run `gh pr ready <url>` for a valid draft, then refresh its receipt before home delivery. On row 2 leave already-ready companions unchanged; never redraft. A closed receipt takes legs.md's disposition stop, not a skip or duplicate create.
|
|
37
|
+
3. Collect every companion URL, including validated skips, before stripping/sealing home exactly once: use `--option pr --base origin/<baseRefName>`, the selected spec and one `--leg <repo>=<pr-url>` per companion. Preserve legs.md's existing-seal result comparison. On seal failure print `Not shipped: <home repo> <bin output>` and stop before home push, retaining companions and receipts. Never seal partial results or run the standalone home seal as well.
|
|
38
|
+
|
|
39
|
+
For one block or absent `## Legs`, run the ordinary strip-and-seal block first, with `--option pr --base origin/<baseRefName>` and the selected spec. Preserve every seal failure stop. After successful sealing, push home non-force:
|
|
34
40
|
|
|
35
41
|
```bash
|
|
36
42
|
git -C "$WORKTREE" push --no-follow-tags origin HEAD:refs/heads/<headRefName>
|
|
37
43
|
```
|
|
38
44
|
|
|
39
|
-
Only after successful push on row 1 run `gh pr ready <N> -R <owner/repo>`. Row 2 pushes only. Report a rejected push once, skip ready, and return to the menu without force or automatic retry. On ready failure report the completed push and that the PR remains a draft for manual action or a later retry; preserve checkout.
|
|
45
|
+
Only after successful push on row 1 run `gh pr ready <N> -R <owner/repo>`. Row 2 pushes only. Report a rejected push once, skip ready, and return to the menu without force or automatic retry. On ready failure report the completed push and that the PR remains a draft for manual action or a later retry; preserve checkout. For coordinated delivery, report all shipped companions too and retain receipts. Companion create/ready failures stop before home push with legs.md's `Not shipped: <repo> <reason>`; preserve delivered companions and receipts, report untouched members and perform no rollback. Apply the same retained-results reporting to home push failure.
|
|
46
|
+
|
|
47
|
+
Preserve the home PR body byte-for-byte without a Rework block. For N>1 blocks on this header-linked route only, waive legs.md's home-body companion-URL insertion; retain each companion's `Home:` pointer. For coordinated delivery, print `Shipped: <repo> pr <url>` for every delivered member, companions first and home last. Tell the user to keep this summary for cross-repo review because the home body does not list companions and receipts are removed after successful home delivery under legs.md. Complete ship only after successful delivery of every member; keep every worktree for both push rows.
|