pi-gauntlet 7.35.0 → 7.36.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 +12 -0
- package/README.md +26 -6
- package/package.json +3 -2
- package/skills/brainstorming/SKILL.md +4 -4
- package/skills/brainstorming/gatherer.md +23 -16
- package/skills/brainstorming/reference/amendment-surface.md +2 -2
- package/skills/brainstorming/reference/pr-subject.md +53 -17
- package/skills/brainstorming/reference/spec-finalization.md +6 -4
- package/skills/brainstorming/reference/ticket-acceptance.md +1 -1
- package/skills/finishing-a-development-branch/SKILL.md +26 -26
- package/skills/gauntlet-handoff/SKILL.md +1 -1
- package/skills/gauntlet-resume/SKILL.md +1 -1
- package/skills/gauntlet-resume/reference/brief-contract.md +16 -7
- package/skills/gauntlet-resume/reference/reconstruction.md +8 -2
- package/skills/using-git-worktrees/reference/pr-head.md +29 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v7.36.1 - 2026-10-27
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Claude Code marketplace installs no longer register pi-only personas. A versionless plugin manifest disables default agent discovery while the marketplace retains the six portable skills and owns the release version. Real Claude startup and cached-upgrade tests gate releases; pi persona files and installation behavior are unchanged.
|
|
8
|
+
|
|
9
|
+
## v7.36.0 - 2026-10-26
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Brainstorming accepts a leading list of related open, same-repository, non-fork PRs on one base as one rework subject. Admission and relatedness checks precede provisioning; member heads merge into the first retained PR's branch before the base, and each PR retains its claims, threads, and original-head provenance through the spec and handoff. Finish offers gated close comments for absorbed members only after a successful home push and description update, without deleting branches. (#89)
|
|
14
|
+
|
|
3
15
|
## v7.35.0 - 2026-10-26
|
|
4
16
|
|
|
5
17
|
### Added
|
package/README.md
CHANGED
|
@@ -36,13 +36,13 @@ pi-gauntlet's only hard dependency is pi-cohort - every gate that dispatches a r
|
|
|
36
36
|
Concretely, one change through the gauntlet:
|
|
37
37
|
|
|
38
38
|
0. *(Optional)* Before there's even a spec, `/skill:shape-ticket` can create one tracker issue or repair a comma/whitespace list of issue refs - shaping each into a Context/Problem/Idea/Acceptance Criteria ticket, grounded by a repository audit, an AC integrity check, and a cheap council roast. Repair finishes preparation for all tickets before presenting exact-diff confirmations sequentially in ref order; each approval writes that ticket before the next gate, and may include one optional gated comment for a Reporter note or overlap evidence. The audit checks factual claims, Idea fit, AC mechanisms against cited repo guidance, and already-stated observable legs in configured sibling checkouts. It reports in-motion work and attempts a best-effort scenario through authorized current-system reads, without promising reproduction or a fix; missing access or nothing to observe is reported, not a new approval gate. Implementer detail moves into the gated Reporter note; brainstorming reads that note with the ticket so the spec retains the detail. A failed roast is retried once, then surfaced inline at the gate if it fails again. It's a tool, not a phase: no worktree, no plan/phase tracker, runs from any repo state. The agent may start it on its own when the ask is "file a ticket" or another skill routes there; the write still waits for your yes on the presented diff. Similarly, `/skill:chase-bug` triages a raw bug report into an evidenced verdict - and can hand off to shape-ticket, brainstorming, or a bounded hotfix - before any spec exists.
|
|
39
|
-
1. Opt in with `/skill:brainstorming` and describe the change. The command is the reliable discovery-and-entry path; explicit prose requesting brainstorming/the gauntlet also supplies consent when the skill is already loaded or an available instruction or route identifies it. An ordinary implementation request or an agent recommendation is not consent. A leading GitHub
|
|
39
|
+
1. Opt in with `/skill:brainstorming` and describe the change. The command is the reliable discovery-and-entry path; explicit prose requesting brainstorming/the gauntlet also supplies consent when the skill is already loaded or an available instruction or route identifies it. An ordinary implementation request or an agent recommendation is not consent. A leading run of GitHub references (`#N`, `owner/repo#N`, or a `/pull/N` or `/issues/N` URL), separated by whitespace or commas, resolves each reference as a PR first: related open, same-repository, non-fork PRs on one base form one rework subject, including drafts. Admission runs in listed order and relatedness is checked before provisioning; the first retained PR is home, and member heads merge into its existing branch in listed order before the fetched base merges. An unresolved member conflict after its scoped helper aborts that merge and stops the run before any spec, later merge, push, or close. A single non-PR reference follows the ticket path. The first non-reference token starts intent text; mid-sentence references and other ticket/free-text subjects keep their existing paths. The combined code, PR-carried specs, claims, and review threads are the brainstorm input, with each PR's provenance retained; only home's bound ticket supplies acceptance criteria, while member tickets supply context. A single PR retains the same rework path without member merges or a close offer. The combined state is judged against constraints from the fetched current base HEAD, not the fork point or the PRs' proposed policy edits; see the [PR-subject contract](skills/brainstorming/reference/pr-subject.md) and [PR-head worktree owner](skills/using-git-worktrees/reference/pr-head.md). **`brainstorming`** sets up an isolated worktree (on the existing branch for PR rework), explores the codebase, and turns the subject into a written spec - when its recon finds a cited case that the ask is the wrong change (misdiagnosed, wrong-sized, already solved, a band-aid, or cutting across a sound pattern - including a repo convention that is itself debt) and can name the alternative, question one is a framing question (`as framed`, `pivot: <alternative>`, or `smaller or none`); otherwise it opens with one sentence naming what it checked, and every approach it proposes ends with a `Pattern:` line naming what it follows or cuts across; when the run starts from a ticket, the spec carries the ticket's acceptance criteria verbatim, each with a disposition (`in-scope`, `deviates:`, `deferred:`, `venue:`, `elsewhere:` for a row another repo's part delivers), scope cuts come only from your answer to a cut question and are listed at the gate, the conformance gate checks the in-scope ones, and `/skill:check-delivery` verifies `venue:` rows before the prod deploy. A multi-model critique runs on it automatically. If the spec replaces a known prior spec, brainstorming marks the predecessor with a `> **Superseded by:**` banner under its title (default format, syntax overridable via `.pi/gauntlet-overrides.md`; candidates come from brainstorming's scout recon, never a mechanical sweep). **You read and approve the spec - human gate 1.** Before approval, PR rework's sole write/run exception outside the spec directories permits only the base merge, each admitted member-head merge, their conflict helpers' edits to the conflicted files, and their scoped conflict tests; other subjects have no implementation code yet.
|
|
40
40
|
2. By default, **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files. Experimental approval options 4/5 instead select **`loop-implementation`**: the plan phase is skipped and a stamped acceptance-criteria ledger replaces the task plan. Option 4 retains amendment review; option 5 grants auto-apply amends, with redraws still stopping. See [Loop engine operations](doc/configuration.md#loop-engine-operations).
|
|
41
41
|
3. **`subagent-driven-development`** executes the plan one task at a time, each in a fresh subagent, behind spec-compliance review then code-quality review. TDD-locked: red, green, refactor. Independent implementation, review, and council batches remain parallel, but their dispatches are foreground: the orchestrator waits for terminal results before accepting work or advancing a phase.
|
|
42
42
|
The loop alternative to step 3 runs one fresh `loop-implementer` per seed or row iteration, without implement-phase reviewers. It stops for a human decision on stagnation or a failed exit verification; passing full verification with every row closed enters the same verify gates.
|
|
43
43
|
|
|
44
44
|
4. **verify**: the parent first runs the plan's full verification command set (the ledger's `verification:` command for loop); only a passing result permits whole-diff code review, then the **conformance gate**. A review fix invalidates that result, so the parent reruns full verification before the next review or conformance gate. When the overrides file declares a happy path for the touched paths (see [Project-specific overrides](#project-specific-overrides)), the parent runs it once here, between code review and the conformance gate, and the reviewer reads its transcript as runtime evidence - a hang or a failed request shows up in the audit with the transcript quoted - as a gap when an origin clause ties to it, otherwise as a `happy-path: failed - unattributable` line - never as a silent green. The conformance subagent reads the finished code and docs against your *original words* from step 1, not the plan, and reports per-requirement: delivered, partial, missing, drifted, or unauthorized. Unauthorized rows - shipped surface no human input asked for, whether it crept in or was laundered through the spec - follow their recommendation like every other row: a contained removal auto-runs, anything another requirement leans on is deferred with a plain-language "I'd cut it / I'd keep it" recommendation. Inside a brainstorming-entered flow this gate is machine-blocked from being skipped. Compatible executable recommendations auto-run through an isolated fix-and-re-audit loop with no prompt; anything still open surfaces as a numbered decision brief - one item per decision, the problem in plain words first, lettered options each with a one-line consequence, and `Recommended: <letter> - <reason>` or `No recommendation - pick one`. Reply with one line per item (`1. B`), or bare `1` to take every recommendation (no-recommendation items are re-asked by number); a current `CONFORMS` / no-concerns result goes straight to the branch options with no extra conformance sign-off.
|
|
45
|
-
5. **`finishing-a-development-branch`**: PR, draft PR, squash, keep, or discard; PR rework also offers a non-force push to the existing PR branch. That push preserves history and appends a `## Rework` block while retaining the original description bytes. Its `Before:` handle includes the full portable pre-rework SHA and the local `refs/gauntlet/pre-rework/pr-<N>` ref in the rework checkout. The [finishing owner](skills/finishing-a-development-branch/SKILL.md#pr-subject-row-1-push-to-the-pr-branch) defines the landing and body-update contract. Once a PR exists, run `/skill:gatekeep-pr <pr>` to verify it before merging - it judges the diff against the spec at the PR's head (the acceptance-criteria dispositions and Design you approved; the PR description when no spec applies) - rows the spec defers or deviates are settled, every other row needs its mechanism (code, tests, docs) - and against the rubric; whatever can be seen only after merge is left to step 6. **Human gate 2** - the only other decision you make.
|
|
45
|
+
5. **`finishing-a-development-branch`**: PR, draft PR, squash, keep, or discard; PR rework also offers a non-force push to the existing PR branch. That push proves every recorded original head remains an ancestor, preserves history, and appends a `## Rework` block naming absorbed PRs while retaining the original description bytes. Only after a successful push and home-description edit does one gated confirmation show the exact close comments and eligible member targets, linking home; declining or any other finish option leaves members open. Closing never deletes member branches, and finish posts no review-thread replies. Its `Before:` handle includes the full portable pre-rework SHA and the local `refs/gauntlet/pre-rework/pr-<N>` ref in the rework checkout. The [finishing owner](skills/finishing-a-development-branch/SKILL.md#pr-subject-row-1-push-to-the-pr-branch) defines the landing and body-update contract. Once a PR exists, run `/skill:gatekeep-pr <pr>` to verify it before merging - it judges the diff against the spec at the PR's head (the acceptance-criteria dispositions and Design you approved; the PR description when no spec applies) - rows the spec defers or deviates are settled, every other row needs its mechanism (code, tests, docs) - and against the rubric; whatever can be seen only after merge is left to step 6. **Human gate 2** - the only other decision you make.
|
|
46
46
|
6. *(Optional)* Once the merge lands, `/skill:check-delivery <ref>` can prove delivery - default-branch landing, delivery target, per-AC evidence - before the tracker status advances. Explicit ask only, no auto-chain: deploys commonly lag merges by minutes to hours, so an auto-run would routinely check too early.
|
|
47
47
|
|
|
48
48
|
Only the machine-owned `plan -> implement` and `verify -> ship` handoffs receive a branch-local one-shot nudge after an unexpected settled stop; it is fire-and-forget, does not bypass either human gate, and older Pi hosts without `agent_settled` retain existing behavior.
|
|
@@ -126,7 +126,7 @@ Run by a human against pi-cohort >= 7.1.0, before a pi-gauntlet release claims t
|
|
|
126
126
|
## Requirements
|
|
127
127
|
|
|
128
128
|
- [pi-coding-agent](https://github.com/earendil-works/pi) ≥ 0.85.1 - tested minimum for sequential `phase_tracker` tool execution, which persists a tracker update before a later tool call in the same model message.
|
|
129
|
-
- [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.
|
|
129
|
+
- [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.6.1 - required peer package, including binary-safe worktree patches; it also lets a persona with `subagent` in `tools:` start with inherited extensions ([pi-cohort #26](https://github.com/jjuraszek/pi-cohort/issues/26)), which multi-PR `gatekeep-pr` needs. Skills that dispatch agents (`requesting-code-review`, `subagent-driven-development`, `dispatching-parallel-agents`, `writing-plans`, `forge-skill`, `shape-ticket`, `roasting-the-spec`) call `subagent({})`, which pi-cohort provides. pi-gauntlet does not vendor the dispatch tool; without pi-cohort those skills have nothing to call. Gauntlet execution dispatches explicitly use `async: false`; do not enable pi-cohort's incompatible `forceTopLevelAsync` setting. See pi-cohort's [dispatch configuration](https://github.com/jjuraszek/pi-cohort/blob/main/doc/configuration.md) for that setting's owner and semantics. A wave of N >= 1 tasks dispatches its implementers and first spec reviews as one chain call. `subagent-driven-development` stops before dispatch on unsupported installs; there is no older-runtime fallback.
|
|
130
130
|
|
|
131
131
|
Both packages must be listed in your `.pi/settings.json#packages` array (pi adds them automatically when you `pi install`). pi-gauntlet and pi-cohort are versioned independently but release together whenever dispatch semantics change - pin compatible versions of both. At each pi-gauntlet release, set the pi-cohort peer minimum and README floor together to the newest released pi-cohort version; `/skill:release` checks the registry before proceeding.
|
|
132
132
|
|
|
@@ -229,7 +229,9 @@ Invocation: `/gauntlet:shape-ticket` (or bare `/shape-ticket` when unambiguous).
|
|
|
229
229
|
|
|
230
230
|
Updates: the plugin's marketplace `version` equals the npm version; the release
|
|
231
231
|
script writes it on every release, so Claude Code sees each release as a new
|
|
232
|
-
plugin version.
|
|
232
|
+
plugin version. `.claude-plugin/plugin.json` intentionally omits `version`, so
|
|
233
|
+
it cannot override the marketplace's release version. Third-party marketplaces
|
|
234
|
+
do not auto-update by default - run
|
|
233
235
|
`claude plugin update gauntlet@pi-gauntlet` or turn on auto-update for the
|
|
234
236
|
marketplace in `/plugin`. `claude update` updates Claude Code itself, not plugins.
|
|
235
237
|
|
|
@@ -246,6 +248,20 @@ exact repo folder* in interactive Claude Code. Trusting a parent folder,
|
|
|
246
248
|
|
|
247
249
|
### Smoke test
|
|
248
250
|
|
|
251
|
+
`npm test` runs the pinned Claude Code development dependency against disposable
|
|
252
|
+
Git marketplaces and isolated homes. It checks actual session inventories for
|
|
253
|
+
fresh installs and cached upgrades: zero gauntlet agents, exactly the six skills,
|
|
254
|
+
and native helper availability. Negative controls reproduce the agent leak,
|
|
255
|
+
manifest conflict, and full-skill scan. No credentials or model responses are
|
|
256
|
+
used; artifacts remain under the printed temp directory. Run it separately with
|
|
257
|
+
`node scripts/claude-plugin-smoke.test.mjs`; `CLAUDE_BIN` selects another binary
|
|
258
|
+
for compatibility testing. This test gates local releases and CI publication.
|
|
259
|
+
|
|
260
|
+
Use the interactive smoke below to check model-driven skill behavior and helper
|
|
261
|
+
execution before a Claude packaging release. For a candidate that is not yet
|
|
262
|
+
published, add its local marketplace checkout in an isolated `CLAUDE_CONFIG_DIR`
|
|
263
|
+
instead of the GitHub source. Stop before tracker writes.
|
|
264
|
+
|
|
249
265
|
1. Create a scratch repo and add the marketplace config:
|
|
250
266
|
|
|
251
267
|
mkdir -p /tmp/cc-smoke/.claude && cd /tmp/cc-smoke && git init
|
|
@@ -289,8 +305,12 @@ exact repo folder* in interactive Claude Code. Trusting a parent folder,
|
|
|
289
305
|
pi-gauntlet (strict mode if available). Expected: no schema errors.
|
|
290
306
|
11. Agent check: type `@gauntlet:` in the mention typeahead (or open the
|
|
291
307
|
plugin's details). Expected: the plugin registers no agents - `"agents": []`
|
|
292
|
-
in
|
|
293
|
-
repo's pi personas.
|
|
308
|
+
in `.claude-plugin/plugin.json` suppresses the default `agents/` scan of the
|
|
309
|
+
repo's pi personas. The marketplace uses `strict: true` so its skill allowlist
|
|
310
|
+
can coexist with that manifest. Keep the skill allowlist in the marketplace:
|
|
311
|
+
a manifest `skills` field adds to the default scan rather than restricting it.
|
|
312
|
+
Direct `--plugin-dir` loading of the repository bypasses the marketplace's
|
|
313
|
+
skill allowlist and is not the supported installation path.
|
|
294
314
|
|
|
295
315
|
## Project-specific overrides
|
|
296
316
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-gauntlet",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.36.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,12 +62,13 @@
|
|
|
62
62
|
"test": "node scripts/ci.mjs"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"pi-cohort": ">=7.
|
|
65
|
+
"pi-cohort": ">=7.6.1"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"yaml": "^2.9.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
+
"@anthropic-ai/claude-code": "2.1.309",
|
|
71
72
|
"esbuild": "0.28.2"
|
|
72
73
|
}
|
|
73
74
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: brainstorming
|
|
3
|
-
description: "Use only when the user explicitly requests brainstorming or selects a handoff into it; the subject is a free prompt, one tracker ticket, or one open PR
|
|
3
|
+
description: "Use only when the user explicitly requests brainstorming or selects a handoff into it; the subject is a free prompt, one tracker ticket, or one open PR or a leading list of related open PRs reworked on the home PR's branch."
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -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
|
|
21
|
+
For a PR subject, the base merge and each admitted member-head 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
|
|
|
@@ -44,7 +44,7 @@ Work through the items below **in order**. After a user answer or completed side
|
|
|
44
44
|
phase_tracker({ action: "start", phase: "brainstorm" })
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
2. **Set up the worktree** - resolve
|
|
47
|
+
2. **Set up the worktree** - resolve the leading run per `reference/pr-subject.md`; pass the ordered per-PR array (home first) to `/skill:using-git-worktrees`' PR-head path. Then see [Worktree First](#worktree-first).
|
|
48
48
|
3. **Gather context** - read [Ticket Handling](#ticket-handling), then follow [`gatherer.md`](gatherer.md) without a human stop.
|
|
49
49
|
4. **Understand the idea against the draft** - if `reference/ticket-acceptance.md` is not already in context this session (restored entry, or a redraw after a fresh start), read [Ticket Handling](#ticket-handling) before the rest of this step; then see [Understand the idea](#3-understand-the-idea).
|
|
50
50
|
5. **Propose 2-3 approaches** - see [Explore approaches](#4-explore-approaches).
|
|
@@ -142,7 +142,7 @@ Propose 2-3 genuinely distinct approaches and name what separates them (the axis
|
|
|
142
142
|
|
|
143
143
|
### 5. Design for clarity and isolation
|
|
144
144
|
|
|
145
|
-
Prefer clear testable boundaries, YAGNI, existing conventions when they are sound - when the convention is the debt, say so and do not extend it - the owning schema/contract rather than parallel state, and explicit errors and edge cases. Retain every existing user-approved design detail in approaches and design, including when drafting or replacing the spec.
|
|
145
|
+
Prefer clear testable boundaries, YAGNI, existing conventions when they are sound - when the convention is the debt, say so and do not extend it - the owning schema/contract rather than parallel state, and explicit errors and edge cases. Retain every existing user-approved design detail in approaches and design, including supplied presentation details in the design recap and when drafting or replacing the spec.
|
|
146
146
|
|
|
147
147
|
### 6. Present the design in two rounds
|
|
148
148
|
|
|
@@ -128,25 +128,31 @@ Scout (always dispatched):
|
|
|
128
128
|
For a PR subject, supply this additional scout block as values from
|
|
129
129
|
`reference/pr-subject.md` (keep scout unconditional):
|
|
130
130
|
|
|
131
|
-
> PR title and
|
|
132
|
-
>
|
|
133
|
-
>
|
|
134
|
-
>
|
|
135
|
-
>
|
|
136
|
-
>
|
|
137
|
-
>
|
|
131
|
+
> Require every retained PR's title/body, carried specs, and full threads before
|
|
132
|
+
> gather, including N=1. Stop on query failure: `threads for #<N> not fetched (<gh error>)`.
|
|
133
|
+
> Per PR, home first: PR title and body verbatim: `<title>`, `<body>`;
|
|
134
|
+
> PR-carried specs: `<paths and stated contracts>`; own changed paths:
|
|
135
|
+
> `<that PR's BASE_SHA...headRefOid file list>`; full comment threads
|
|
136
|
+
> `<in order, with ids and locations from using-git-worktrees/reference/pr-head.md>`.
|
|
137
|
+
> Combined changed paths: `git diff --name-only <BASE_SHA>...HEAD` output, after the
|
|
138
|
+
> member merges and base merge. Read `git diff <BASE_SHA>...HEAD` from the worktree.
|
|
139
|
+
> Preserve PRE_REWORK_HEAD for home's Before provenance, not scout's code input.
|
|
140
|
+
> Member merge: `<per-member outcome lines>`; Merge result: `<base merge line,
|
|
141
|
+
> contract exceptions, scoped test results>`.
|
|
138
142
|
> Authoritative base-HEAD constraints: `<git show <BASE_SHA>:<path> texts for
|
|
139
143
|
> AGENTS.md, first-found overrides, REVIEW.md, and all cited constraint documents;
|
|
140
144
|
> explicit missing-document results>`. These govern on every merge outcome,
|
|
141
145
|
> including clean; worktree policy edits are proposals under `changes:` or
|
|
142
146
|
> `dropped claims:`, never constraints.
|
|
143
|
-
>
|
|
144
|
-
> the diff and supplied base rules. Name the smallest repair
|
|
145
|
-
> propose a rewrite only where no repair can. Render
|
|
146
|
-
>
|
|
147
|
-
>
|
|
148
|
-
> unresolved thread: `fix | keep open | decline: <reason>`.
|
|
149
|
-
>
|
|
147
|
+
> Treat the combined state as the starting state, not the target. Judge every
|
|
148
|
+
> PR-stated claim against the diff and supplied base rules. Name the smallest repair
|
|
149
|
+
> satisfying them; propose a rewrite only where no repair can. Render
|
|
150
|
+
> `## PR under rework` with one `### PR #<N> - <title>` subsection per PR, home first,
|
|
151
|
+
> each with `keeps:`, `changes:`, `dropped claims:`, and one proposed disposition per
|
|
152
|
+
> unresolved thread: `fix | keep open | decline: <reason>`. Render
|
|
153
|
+
> `constraints added since fork:` once for home, one line per base rule absent at its
|
|
154
|
+
> fork point. Carry merge contract exceptions into `changes:`. List member-carried
|
|
155
|
+
> spec paths under each PR in Problem for resume.
|
|
150
156
|
|
|
151
157
|
Context-builder (conditional):
|
|
152
158
|
|
|
@@ -180,7 +186,7 @@ Context-builder (conditional):
|
|
|
180
186
|
|
|
181
187
|
## Context-builder trigger rule
|
|
182
188
|
|
|
183
|
-
For a resolved PR subject, dispatch context-builder only for the bound ticket
|
|
189
|
+
For a resolved PR subject, dispatch context-builder only for the bound ticket of home
|
|
184
190
|
using `reference/pr-subject.md`; an unbound PR supplies intent, not ticket ACs.
|
|
185
191
|
Title wins a title/body-first-line ticket conflict; carry the other reference into
|
|
186
192
|
`## Problem` as context. For other subjects, dispatch context-builder when the initial prompt (or a file it explicitly references)
|
|
@@ -224,7 +230,8 @@ convention; slug minted from the initial prompt):
|
|
|
224
230
|
<scout output, or the degraded text>
|
|
225
231
|
|
|
226
232
|
## PR under rework
|
|
227
|
-
<PR subject only:
|
|
233
|
+
<PR subject only: every per-PR scout subsection, ordered original heads, threads,
|
|
234
|
+
member-carried spec paths, and supplied Member merge/base values per
|
|
228
235
|
reference/pr-subject.md; retain these values even when scout failed>
|
|
229
236
|
|
|
230
237
|
## External context
|
|
@@ -62,7 +62,7 @@ The working tree stays at pre-batch HEAD until apply (section 5) - nothing is ed
|
|
|
62
62
|
|
|
63
63
|
Send an item straight to the human batch (step 4) when any holds:
|
|
64
64
|
|
|
65
|
-
- the edit removes or narrows approved text (a descope or rescope);
|
|
65
|
+
- the edit removes or narrows approved text (a descope or rescope). Without a standing amend grant, send a re-bounded row to human review before applying it;
|
|
66
66
|
- the location is a human-owned section: problem statement, goal, acceptance criteria, in/out scope or non-goals, component list or boundaries, public contracts (API, schema, config shape, CLI surface);
|
|
67
67
|
- at the conformance entry: the gap is `UNAUTHORIZED`, or its `origin` quotes an acceptance criterion.
|
|
68
68
|
|
|
@@ -142,7 +142,7 @@ Before the aftermath, `read` this section again; never run it from memory.
|
|
|
142
142
|
|
|
143
143
|
Apply accepted items only: reviewer clears, `accept`, `alt-n`, and state-changing `custom`. Print one line per applied item: `amended the spec: <title> - <what>`.
|
|
144
144
|
|
|
145
|
-
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
|
|
145
|
+
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), then read the amended plan once (step 7's read, without its phase completion or `plan_tracker` init) - the main loop never edits the plan text; then update the tracker: `plan_tracker` `add` for new tasks; anchor-changed completed tasks are reopened as `in_progress` and re-run the task loop (`update` never sets `pending`). A removed task is deleted from the plan; then re-`init` the tracker with `{ name, status }` elements: preserved tasks keep their order and statuses, reopened tasks are `in_progress` in place, every still-`pending` task (including newly added ones, whatever wave label they carry) trails the non-pending ones, removed tasks are the only deletions (the only permitted `init` after handoff; never `clear`). Commit spec + plan together; continue. A task reopened while `verify` or `ship` is in progress stays in that phase - no `phase_tracker` call. Repair it through the current phase's fix loop and `plan_tracker({ action: "update", index: N, status: "complete" })` it once that repair's review or re-audit accepts; open tasks block `complete verify`, and in `ship` nothing checks them, so close them explicitly.
|
|
146
146
|
|
|
147
147
|
One commit per batch:
|
|
148
148
|
|
|
@@ -2,50 +2,86 @@
|
|
|
2
2
|
|
|
3
3
|
## Resolve before provisioning
|
|
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
|
-
Complete classification in order, never in parallel: `gh issue view` can return a PR as an issue.
|
|
7
|
+
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
8
|
|
|
9
|
-
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.
|
|
10
|
-
2. Only a not-a-PR result reaches `gh issue view <N
|
|
9
|
+
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.
|
|
10
|
+
2. Only a not-a-PR result reaches `gh issue view <N>`. Keep an isolated issue on the existing ticket path; stop for an issue in a list.
|
|
11
11
|
3. For neither, stop: `#N resolves to neither a pull request nor an issue in <owner/repo>.`
|
|
12
12
|
|
|
13
|
-
Parse the PR base repository from `url` and this checkout's repository from `git remote get-url origin`; compare lowercase owner/repo identities.
|
|
13
|
+
Parse the PR base repository from `url` and this checkout's repository from `git remote get-url origin`; compare lowercase owner/repo identities. Resolve bare `#N` in this checkout. Compare duplicates by resolved repository and number, including URL/bare duplicates. Require every PR, home included, to pass these checks; instantiate all refs, states, repositories, fork names, and branches from observations:
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
| Check | Stop text | Remedy |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| State not OPEN | `#13 is MERGED; only an open PR can be reworked.` | none |
|
|
18
|
+
| Issue in list | `#13 is an issue, not a pull request; a list admits only PRs. Drop #13 from the list, or brainstorm it alone as a ticket.` | direct correction |
|
|
19
|
+
| Foreign repository | `PR <owner/repo#N> belongs to <repo>, not this checkout (<origin owner/repo>).` | umbrella |
|
|
20
|
+
| isCrossRepository true | `PR #13's head lives on fork <nameWithOwner>; rework needs an in-repo branch.` | umbrella |
|
|
21
|
+
| Different baseRefName from first PR | `#13 targets release-2 but home #12 targets main; mixed bases are not admitted.` | umbrella |
|
|
22
|
+
| Duplicate resolved identity | `#13 is listed twice; list each PR once.` | direct correction |
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
Append this paragraph only for foreign-repository, fork, and mixed-base failures: To rework these together anyway, merge the heads into one branch by hand, open one PR, and brainstorm that PR.
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
## Relatedness before provisioning
|
|
27
|
+
|
|
28
|
+
For N>1, fetch every admitted PR's title/body with `gh pr view <N> -R <owner/repo> --json title,body` and actual diff with `gh pr diff <N> -R <owner/repo>`. On failure stop before provisioning naming the ref and observed reason: `<ref>: title/body not fetched (<gh error>)` or `<ref>: diff not fetched (<gh error>)`.
|
|
29
|
+
|
|
30
|
+
Group by the hunks' behavior, contract, or defect, using titles and bodies as stated intent, not shared paths. Treat unrelated hunks in one file as separate concerns and related hunks across files as one concern. Define groups here, not through shape-ticket's split axes. For one group continue; for multiple groups ask one question in the questionary format: a lead-in naming the concerns, one lettered option per group with its PRs and shared concern on its own line, then `Recommendation:` on its own final line recommending the initial-home group. Offer no all option. For an answer naming no offered group, re-ask once, then stop.
|
|
31
|
+
|
|
32
|
+
Retain the chosen group's listed order; make its first PR home. Name dropped PRs and exclude them from merges, records, and closure. Apply all per-PR fetch and record requirements even to a retained group of one. Keep this preflight separate from question one: gather, the framing question in SKILL.md ### 3, and the post-worktree scope check still run afterward.
|
|
33
|
+
|
|
34
|
+
## Bind and pass the retained list
|
|
35
|
+
|
|
36
|
+
Bind the spec's ticket only from home's first tracker reference in the title, then the body's first line. Name each member binding in `## Problem` as `PR #13 binds <ref> (context)`; extract no member AC rows. Never bind from branch names, commit subjects, or `closingIssuesReferences`. Fetch a bound ticket, extract its AC rows using `reference/ticket-acceptance.md`, and dispatch context-builder for it. Preserve `none - ticket not fetched (<reason>)` on fetch failure. When title and first body line name different tickets, use the title's ticket and name the other in `## Problem` as context.
|
|
37
|
+
|
|
38
|
+
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`.
|
|
39
|
+
|
|
40
|
+
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.
|
|
20
41
|
|
|
21
42
|
## Gather from the PR and fetched base
|
|
22
43
|
|
|
23
|
-
Discover PR-carried specs with `git diff --name-only
|
|
44
|
+
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.
|
|
24
45
|
|
|
25
46
|
On every merge 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.
|
|
26
47
|
|
|
27
|
-
Dispatch scout always, and context-builder
|
|
48
|
+
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 merges, and have scout read `git diff <BASE_SHA>...HEAD` there. Supply base-SHA constraint documents, `Member merge:` lines, and base merge outcomes. Keep `PRE_REWORK_HEAD` as home's original provenance anchor for Before, record, and brief, not the code-input boundary.
|
|
28
49
|
|
|
29
|
-
Instruct scout: treat the PR 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
|
|
50
|
+
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 merge contract exceptions into `changes:`. Run the framing check in SKILL.md ### 3 against the combined diff as the ask.
|
|
30
51
|
|
|
31
52
|
## Record in the spec
|
|
32
53
|
|
|
33
|
-
In `## Problem`, name `PR <owner/repo#N> - <title>`, its stated intent, every `constraints added since fork:` line as a constraint, and the existing `Framing:` line. Preserve
|
|
54
|
+
In `## Problem`, name every `PR <owner/repo#N> - <title>`, its stated intent, member ticket bindings and carried spec paths, every `constraints added since fork:` line as a constraint, and the existing `Framing:` line. Preserve this grammar after `## Acceptance criteria`: repeat the PR/Pre-rework head/Threads group for every retained PR, home first; write the combined fields once, then one provenance subsection per PR.
|
|
34
55
|
|
|
35
56
|
```markdown
|
|
36
57
|
## Rework record
|
|
37
58
|
|
|
38
59
|
PR: <owner/repo#N> - <title>
|
|
39
60
|
Pre-rework head: <40-char sha>
|
|
61
|
+
Threads:
|
|
62
|
+
- <path>:<line> <thread id> - fix | keep open | decline: <reason>
|
|
63
|
+
PR: <owner/repo#M> - <title>
|
|
64
|
+
Pre-rework head: <40-char sha>
|
|
65
|
+
Threads: none
|
|
40
66
|
Base: <baseRefName> @ <sha7> - merge: <no-op | sha7 | unresolved - files>
|
|
41
|
-
Keeps: <what of the original survives>
|
|
67
|
+
Keeps: <what of the combined original survives>
|
|
42
68
|
Changes: <what the rework alters, repair over rewrite>
|
|
43
69
|
Dropped claims: <one `- <claim>` per PR-stated claim no longer true | none>
|
|
44
|
-
Threads:
|
|
45
|
-
- <path>:<line> <thread id> - fix | keep open | decline: <reason>
|
|
46
70
|
Scoped tests: none run | <file>: green | <file>: red - <tests>
|
|
71
|
+
|
|
72
|
+
### PR #<N> - <title>
|
|
73
|
+
keeps: <copied claim>
|
|
74
|
+
changes: <copied change>
|
|
75
|
+
dropped claims: <copied claims | none>
|
|
76
|
+
|
|
77
|
+
### PR #<M> - <title>
|
|
78
|
+
keeps: <copied claim>
|
|
79
|
+
changes: <copied change>
|
|
80
|
+
dropped claims: <copied claims | none>
|
|
47
81
|
```
|
|
48
82
|
|
|
49
|
-
Use `Threads: none` for a successful empty fetch
|
|
83
|
+
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.
|
|
84
|
+
|
|
85
|
+
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:`. For an unresolved base merge, open Design with `merge origin/<base> and resolve <files>` as eventual plan Task 1.
|
|
50
86
|
|
|
51
|
-
Preserve this record when `reference/spec-finalization.md` replaces the draft; dropping
|
|
87
|
+
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.
|
|
@@ -18,9 +18,11 @@ Spec-writing replaces the context draft, in this exact order:
|
|
|
18
18
|
rewrite carries `none` too - a redraw is a new approval, with no carry-over.
|
|
19
19
|
For a PR subject, follow `pr-subject.md`'s spec contract: carry the draft's
|
|
20
20
|
`## PR under rework` into `## Rework record` after `## Acceptance criteria`,
|
|
21
|
-
preserving its
|
|
21
|
+
preserving its repeated PR/Pre-rework head/Threads groups, one per retained PR,
|
|
22
|
+
home first, each 40-character pre-rework SHA, merge result,
|
|
22
23
|
keeps/changes/dropped claims, thread dispositions and fetch status, contract exceptions,
|
|
23
|
-
and scoped test results (including failures and reasons none ran)
|
|
24
|
+
and scoped test results (including failures and reasons none ran), then one
|
|
25
|
+
`### PR #<N>` provenance subsection per PR with lowercase claims. Carry every PR's
|
|
24
26
|
stated intent and constraints added since fork into Problem. Open Design with the
|
|
25
27
|
unresolved merge repair when present. Omit the record from a ticket or free-text spec.
|
|
26
28
|
3. **Immediately after the write**, confirm line 1 of the file is no longer
|
|
@@ -51,7 +53,7 @@ After writing the spec to `<project>/doc/specs/<filename>.md` (per [Filename Con
|
|
|
51
53
|
- **Placeholder scan.** Any `TODO`, `TBD`, `<fill in>`, `[example]`, `xxx`? Either resolve them or convert to explicit "Open Questions" with names.
|
|
52
54
|
- **Internal consistency.** Does Section 4 contradict Section 2? Does the header block carry `**Amend-grant:**` exactly once with the value `none` (the [predicate](amendment-surface.md#standing-grants))? Are component names and field names consistent throughout? If the spec replaces a prior design, confirm the predecessor carries the supersession banner and its href resolves to this spec's final filename.
|
|
53
55
|
- **Documentation named.** Does the spec name all three classes (feature/user-facing introduced; materially amended; derived/memory invalidated), or an explicit "none" for each? Enforce the materiality bar in `documentation-impact.md` without restating it: each listed doc names the category it clears, none is a code-mirror, amend-over-create was applied, and skill/agent bodies are implementation surface, not doc-impact entries here.
|
|
54
|
-
- **Ticket contract present.** Require `## Acceptance criteria` in exactly three forms: ticket provenance (`Ticket <ref>, <heading or "checkbox list">, rows verbatim:`) with verbatim rows and dispositions; drafted provenance (`Drafted from the design, no ticket rows:` or `Drafted from the design, ticket <ref> has no acceptance criteria:`) with at least one `- [ ]` row and a disposition on every row; or the single line `none - ticket not fetched (<reason>)`. Reject `none - no ticket` and `none - ticket has no acceptance criteria` as final bodies. For a PR subject, require the complete `## Rework record` per `pr-subject.md`; absence fails inline lint, including after a full replacement or redraw.
|
|
56
|
+
- **Ticket contract present.** Require `## Acceptance criteria` in exactly three forms: ticket provenance (`Ticket <ref>, <heading or "checkbox list">, rows verbatim:`) with verbatim rows and dispositions; drafted provenance (`Drafted from the design, no ticket rows:` or `Drafted from the design, ticket <ref> has no acceptance criteria:`) with at least one `- [ ]` row and a disposition on every row; or the single line `none - ticket not fetched (<reason>)`. Reject `none - no ticket` and `none - ticket has no acceptance criteria` as final bodies. For a PR subject, require the complete `## Rework record` per `pr-subject.md`; absence fails inline lint, including after a full replacement or redraw. Build expected identities and original heads from the provisioning Step 4 report (home plus `MEMBER_HEADS`), not from the record itself. Require each expected identity's `PR:`/`Pre-rework head:`/`Threads:` group with its full matching head and a `### PR #<N>` provenance subsection; reject a missing group or subsection naming the missing PR. Apply the same predicate for N=1.
|
|
55
57
|
- **Scope check.** Does every paragraph serve the goal? Cut filler. If something is out of scope, say it's out of scope.
|
|
56
58
|
- **Ambiguity check.** Is every "we should..." backed by a concrete decision? Replace "we could probably" with "we will" or "we won't".
|
|
57
59
|
|
|
@@ -63,7 +65,7 @@ Exclude drafted rows from `Human input (verbatim; off-limits for over-spec)`; th
|
|
|
63
65
|
|
|
64
66
|
Before dispatching the worker below, resolve `documentation-impact.md` relative to this loaded reference as one absolute `<DOCUMENTATION_IMPACT_GUIDELINE>` path value. Pass that value in the worker task; do not add it to the spec.
|
|
65
67
|
|
|
66
|
-
After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate**; council **apply mechanics** live in `/skill:roasting-the-spec` (single source of truth - link, don't restate). Resolve the council with `gauntlet_setting({ key: "specCouncil" })` - the tool returns the merged (repo-over-preset) value as `{ verdict, members, chair, malformed, warning, errors }`. **Do not** hand-roll a settings read. When `verdict` is `"council"`, the council *is* the critique pass - invoke `/skill:roasting-the-spec` automatically (no offer, no prompt), passing `members`/`chair`; for a PR subject include
|
|
68
|
+
After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate**; council **apply mechanics** live in `/skill:roasting-the-spec` (single source of truth - link, don't restate). Resolve the council with `gauntlet_setting({ key: "specCouncil" })` - the tool returns the merged (repo-over-preset) value as `{ verdict, members, chair, malformed, warning, errors }`. **Do not** hand-roll a settings read. When `verdict` is `"council"`, the council *is* the critique pass - invoke `/skill:roasting-the-spec` automatically (no offer, no prompt), passing `members`/`chair`; for a PR subject include every retained PR title and body verbatim beside the home-bound ticket rows in `Human input`; also pass the verbatim human input (the original prompt, any ticket AC snapshot - the raw rows under the gather draft's `## Ticket acceptance criteria (verbatim)` heading, never the spec's section, which holds the author's dispositions - and, for every question that offered a disposition (the cut question and the unmatched-group question in `ticket-acceptance.md`), the full question and the user's answer) - roasting-the-spec forwards it to members, chair, and applier as the `Human input (verbatim; off-limits for over-spec)` block; its dispatched applier applies the spec edits and supplies the returned audit (Applied/Deferred/Rejected). When `verdict` is `"worker"`, dispatch the worker below. If `malformed` is true or `errors` is non-empty, emit the `warning`/error as one line, then branch strictly on `verdict` - `malformed` can accompany *either* verdict (e.g. a bad `chair` with valid `members` still returns `council`), so never infer the worker path from `malformed` alone. If `gauntlet_setting` is unavailable, stop and report - never fall back to a manual bash/JSON settings merge. The already-applied council edits (or the worker's in-place fixes) ride in the same worktree commit. The conceptual precedence rule lives in `../../verification-before-completion/reference/settings-precedence.md`.
|
|
67
69
|
|
|
68
70
|
When `verdict` is `"worker"`, dispatch one fresh `worker` that applies the scope + ambiguity checks and fixes them in place:
|
|
69
71
|
|
|
@@ -42,7 +42,7 @@ Apply these integrity classes inline without invoking ticket shaping. Preserve e
|
|
|
42
42
|
|---|---|
|
|
43
43
|
| Wishful | Rewrite to the design's observable with design-sourced baseline, target, and measurement |
|
|
44
44
|
| Tautological | Rewrite to a design-sourced, already-enumerated set or observable |
|
|
45
|
-
| Tree-wide | Split a drafted row requiring zero/no findings of one or several kinds anywhere in or across a tree or set into one row per family from the explicit complete enumeration in Design for that row, covering every kind it names; give each family's own observable and preserve every outcome across the resulting rows. For an absent, partial, or unrelated enumeration, stop before writing, quote the row, and request the complete enumeration in Design. Keep this recovery drafted-only: a ticket row of this shape stays one verbatim row; require human ticket repair through `/skill:shape-ticket` before approval to split it |
|
|
45
|
+
| Tree-wide | Split a drafted row requiring zero/no findings of one or several kinds anywhere in or across a tree or set into one row per family from the explicit complete enumeration in Design for that row, covering every kind it names; give each family's own observable and preserve every outcome across the resulting rows. For an absent, partial, or unrelated enumeration, stop before writing, quote the row, and request the complete enumeration in Design; obtain it from the human or Design; never invent the list in question options or recommendations or infer completion of a partial list. Keep this recovery drafted-only: a ticket row of this shape stays one verbatim row; require human ticket repair through `/skill:shape-ticket` before approval to split it |
|
|
46
46
|
| Unspecified-but-binding | Resolve the value from Design and record the resolution there; ask the user for a missing value |
|
|
47
47
|
| External-input | Ask the user for the external yardstick before writing |
|
|
48
48
|
| Post-deployment | Rewrite to a pre-production observation when available, retaining `venue:`; move production-only observations to a tracked, non-blocking `Post-deployment housekeeping` Design clause, never an AC row |
|
|
@@ -31,21 +31,12 @@ Then call `phase_tracker({ action: "start", phase: "ship" })`.
|
|
|
31
31
|
## The Process
|
|
32
32
|
|
|
33
33
|
### Step 1: Verify Tests
|
|
34
|
-
|
|
35
34
|
**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.
|
|
36
|
-
|
|
37
|
-
Read the selected run spec before verification. Detect a PR subject only by its `## Rework record`, never by an open PR on `$FEATURE`. Read `PR:` and the full `Pre-rework head:` into `PRE_REWORK_HEAD` from that record; missing pre-head -> stop naming the spec path. Confirm 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.
|
|
38
|
-
|
|
35
|
+
Read the selected run spec before verification. Detect a PR subject only by its `## Rework record`, never by an open PR on `$FEATURE`. 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.
|
|
39
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 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).
|
|
40
|
-
|
|
41
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.
|
|
42
|
-
|
|
43
38
|
**Scoping caveat — pre-existing findings.** Some services carry lint findings unrelated to the diff. If verification fails on lines you didn't touch:
|
|
44
|
-
|
|
45
|
-
1. Confirm with `git -C "$WORKTREE" diff <base>...HEAD --name-only` that the offending file isn't in your diff.
|
|
46
|
-
2. Surface the pre-existing finding to the user as a separate issue — do **not** auto-fix it in this completion ("surface, don't auto-fix").
|
|
47
|
-
3. Proceed only after the user acknowledges.
|
|
48
|
-
|
|
39
|
+
Confirm with `git -C "$WORKTREE" diff <base>...HEAD --name-only` that the offending file isn't in your diff. Surface the pre-existing finding to the user as a separate issue - do **not** auto-fix it in this completion ("surface, don't auto-fix"). Proceed only after the user acknowledges.
|
|
49
40
|
**If tests fail (within your diff):**
|
|
50
41
|
```
|
|
51
42
|
Tests failing (<N> failures). Must fix before completing:
|
|
@@ -54,13 +45,7 @@ Tests failing (<N> failures). Must fix before completing:
|
|
|
54
45
|
|
|
55
46
|
Cannot proceed until tests pass.
|
|
56
47
|
```
|
|
57
|
-
|
|
58
|
-
Stop. Don't proceed to Step 2.
|
|
59
|
-
|
|
60
|
-
**If tests pass:** Continue to Step 2.
|
|
61
|
-
|
|
62
|
-
No documentation prompt here: Documentation impact is decided at spec time (`/skill:brainstorming` section 6, gated by `brainstorming/reference/documentation-impact.md`) and has already shipped in the diff by the time you reach finishing.
|
|
63
|
-
|
|
48
|
+
Stop. Don't proceed to Step 2. **If tests pass:** Continue to Step 2. No documentation prompt here: Documentation impact is decided at spec time (`/skill:brainstorming` section 6, gated by `brainstorming/reference/documentation-impact.md`) and has already shipped in the diff by the time you reach finishing.
|
|
64
49
|
### Step 2: Detect Environment
|
|
65
50
|
|
|
66
51
|
For a PR subject, use the Step 4 PR menu. For other subjects: detached HEAD (`git -C "$WORKTREE" symbolic-ref -q HEAD` prints nothing) -> reduced 4-option menu (no merge), no cleanup. Otherwise the standard 5 options.
|
|
@@ -187,7 +172,7 @@ Omit the block when N = 0.
|
|
|
187
172
|
|---|---|---|
|
|
188
173
|
| `git merge-base --is-ancestor <PRE_REWORK_HEAD> HEAD` | Continue | Stop: `PR branch history was rewritten: <PRE_REWORK_HEAD7> is not an ancestor of HEAD; the rework must be re-merged, not rebased.` |
|
|
189
174
|
| `git merge-base --is-ancestor origin/<headRefName> HEAD` | Offer push | Withhold push: `push withheld: origin/<headRefName> is at <sha7>, local HEAD at <sha7>; a non-force push cannot land` |
|
|
190
|
-
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.
|
|
175
|
+
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.
|
|
191
176
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) for rendering and numeric replies. Present:
|
|
192
177
|
```
|
|
193
178
|
Implementation complete. What would you like to do?
|
|
@@ -267,7 +252,7 @@ node <bin>/gauntlet-telemetry-seal.mjs --worktree "$WORKTREE" --option <pr|squas
|
|
|
267
252
|
|
|
268
253
|
The seal prints one line per record (`sealed <path>`, `already sealed <path>`) or one bare outcome (`no telemetry run`, `telemetry disabled`) and exits 0; print its stdout verbatim in the ship completion message. Any nonzero exit stops the flow before the first landing command, quoting the bin's line: exit 2 (`no record at <path>`, `unparseable record <path>: <reason>`) means this gauntlet run's recorder never armed or its record is corrupt; exit 1 is a usage, environment, or git/jj failure (`seal failed <path>: <reason>` restored the pre-seal bytes). The user decides; never land without the seal.
|
|
269
254
|
#### PR-subject row 1: Push to the PR branch
|
|
270
|
-
Capture the scoped verification set and thread evidence before the strip. Refetch
|
|
255
|
+
Capture the scoped verification set and accepted-complete task/thread evidence before the strip. Refetch threads per recorded PR using the paginated single-`$n` query (one invocation per PR) owned by [pr-head](../using-git-worktrees/reference/pr-head.md); retain PR attribution and use the query's location rendering. For home, use the table below and omit threads now resolved on GitHub. For members, copy recorded dispositions and mark newly resolved or newly opened states from the refresh; never use home's first-parent history as member-fix proof.
|
|
271
256
|
| Refetched thread / evidence | Resolution |
|
|
272
257
|
|---|---|
|
|
273
258
|
| Recorded `fix`, matching task title carries id, task accepted by spec and code review and `complete`, exactly one naming commit | `fixed in <sha7>` |
|
|
@@ -280,23 +265,39 @@ Count naming commits with `git -C "$WORKTREE" log --first-parent --format=%h --g
|
|
|
280
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:
|
|
281
266
|
```bash
|
|
282
267
|
git -C "$WORKTREE" update-ref refs/gauntlet/pre-rework/pr-<N> <PRE_REWORK_HEAD>
|
|
283
|
-
git -C "$WORKTREE" push --no-follow-tags origin HEAD:refs/heads/<headRefName>
|
|
284
268
|
```
|
|
285
|
-
|
|
286
|
-
|
|
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.
|
|
274
|
+
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:
|
|
287
275
|
```markdown
|
|
288
276
|
## Rework
|
|
289
277
|
|
|
290
278
|
Before: <PRE_REWORK_HEAD> (local ref `refs/gauntlet/pre-rework/pr-<N>` in the rework checkout; the SHA is the portable handle and stays on origin because the push was not forced)
|
|
279
|
+
Absorbs: #13 (<url>), #14 (<url>)
|
|
291
280
|
Spec: <spec path> at <HEAD7>
|
|
292
281
|
Keeps: <from the record>
|
|
293
282
|
Changes: <from the record>
|
|
294
283
|
Dropped claims: <none | one "No longer true: <claim>" line per dropped claim>
|
|
295
284
|
Verification: scoped - <commands>; CI on this push holds the full run. Telemetry: whole PR against <baseRefName>.
|
|
296
285
|
Threads:
|
|
297
|
-
|
|
286
|
+
#<N>:
|
|
287
|
+
- <path>:<line> - <resolution for this PR>
|
|
288
|
+
```
|
|
289
|
+
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` and `git -C "$WORKTREE" merge-base --is-ancestor <current headRefOid> <pushed home head>` exit 0. Exclude and name ineligible members: `#14 skipped: head moved to <sha7>, not in home` or `#14 skipped: state CLOSED`. Treat unexpected Git exits and failed refreshes as errors, withhold closure and report the reason; merge nothing implicitly.
|
|
291
|
+
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
|
+
```text
|
|
293
|
+
Close the absorbed PRs with these comments?
|
|
294
|
+
#13: "Reworked into #12 (<home url>) by the gauntlet; this PR's commits are merged there and remain reachable as <#13 pre-rework sha7>."
|
|
295
|
+
#14: "Reworked into #12 (<home url>) by the gauntlet; this PR's commits are merged there and remain reachable as <#14 pre-rework sha7>."
|
|
296
|
+
1 - yes, close #13, #14
|
|
297
|
+
2 - no, leave them open
|
|
298
298
|
```
|
|
299
|
-
|
|
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.
|
|
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.
|
|
300
301
|
#### Option 1: Push and Create PR
|
|
301
302
|
|
|
302
303
|
Run the strip-and-seal block above first (plan stripped, telemetry record sealed), then:
|
|
@@ -456,7 +457,6 @@ A host-owned worktree (Step 6: no `home:` match, or the legacy "Otherwise") keep
|
|
|
456
457
|
- **Fix:** Never `git rm` under the telemetry dir. Until the seal the record is untracked and git-excluded, so a plan strip cannot reach it; after the seal it is a committed deliverable.
|
|
457
458
|
|
|
458
459
|
## Completion
|
|
459
|
-
|
|
460
460
|
Once the chosen option (Options 1-4 or PR-subject row 1 - not Discard) is executed successfully, mark the ship phase complete:
|
|
461
461
|
|
|
462
462
|
```
|
|
@@ -83,7 +83,7 @@ loop: tracker state is extension state no subagent can read.
|
|
|
83
83
|
- A phase `in_progress` (verify or ship included - resume stops at verify on its own)
|
|
84
84
|
-> append the process-state section exactly as `## Producers` in
|
|
85
85
|
`reference/brief-contract.md` lays it out: both status outputs verbatim
|
|
86
|
-
(`No plan active.` verbatim when there is no plan), the contract's artifact-specific fields, and the gate-history line. Recognize the loop alternative by ledger line 1; read the ledger from the run worktree for its durable last decision. Read the run worktree's spec; when it carries `## Rework record`, copy
|
|
86
|
+
(`No plan active.` verbatim when there is no plan), the contract's artifact-specific fields, and the gate-history line. Recognize the loop alternative by ledger line 1; read the ledger from the run worktree for its durable last decision. Read the run worktree's spec; when it carries `## Rework record`, copy every top-level PR identity (without the title) and its full pre-rework head, home first in record order, into the optional fields in the contract's producer layout. Without that record, use the ordinary layout. Use only the contract's grammar; write no second state file. Append with a single
|
|
87
87
|
`cat >> "<brief path>" <<'EOF' ... EOF` whose body is that block.
|
|
88
88
|
- Re-read the file tail and confirm it ends with the gate-history line from the
|
|
89
89
|
contract and nothing after.
|
|
@@ -142,7 +142,7 @@ owning skill **without** its reset-bearing entry:
|
|
|
142
142
|
| Active after restore | Continue in | Entry point |
|
|
143
143
|
|---|---|---|
|
|
144
144
|
| brainstorm | [brainstorming checklist](../brainstorming/SKILL.md#checklist) | on-disk state decides the step: draft marker on line 1 of the spec file -> step 4; spec title -> step 8. Never `/skill:brainstorming` entry (it resets both trackers) |
|
|
145
|
-
| approved spec with `**Engine:** loop`, no ledger | loop-implementation | after check 6, arm with `start brainstorm`, then `skip brainstorm resume: <spec path>` before driver admission; carry absolute worktree/spec paths and plan directory through Entry steps 1-5 per `reference/reconstruction.md` "Spec without plan":
|
|
145
|
+
| approved spec with `**Engine:** loop`, no ledger | loop-implementation | after check 6, arm with `start brainstorm`, then `skip brainstorm resume: <spec path>` before driver admission; carry absolute worktree/spec paths and plan directory through Entry steps 1-5 per `reference/reconstruction.md` "Spec without plan": label Entry steps 1-5 explicitly in the response as Entry step 1: resolved settings; Entry step 2: verification; Entry step 3: driver's plan skip; Entry step 4: clean named-branch check and ledger creation; Entry step 5: `plan_check`, commit and implement start; no writing-plans body or task tracker |
|
|
146
146
|
| plan with task engine | writing-plans body | skip its `start plan` call (already in_progress) |
|
|
147
147
|
| implement with line-1 ledger | loop-implementation | complete `reference/reconstruction.md` "Spec with ledger" ordered restore, cited by `reference/brief-contract.md`'s call table: entry checks 1-6, brainstorm start/skip, plan start/check/skip with reason `resume: <spec> (loop engine)`, implement start, no task tracker; state the entire ordered sequence explicitly even when entry checks are already reported as passed; then continue at step 5 (`Before each dispatch`), applying the shared cap boundary in reconstruction step 4 before continuation and preserving ledger cap, iterations/retry data; dirty tree stops before dispatch; reuse the existing ledger |
|
|
148
148
|
| implement with task plan | subagent-driven-development | re-validate `<task>` first (re-run its `Tests:`), then the task loop from the first non-complete task |
|
|
@@ -27,7 +27,7 @@ Headings, fixed order. A consumer keys on headings, never prose.
|
|
|
27
27
|
| `## Repo state` | one field per line: `toplevel`, `worktree: yes <path>` or `worktree: no`, `branch` (`detached` when none), `HEAD`, `base` (`unknown` when no remote resolves), `dirty: <porcelain>` or `dirty: clean`, `diff-stat` (`unavailable` when base unknown), `test cmd`; any field `unavailable` when its command failed; heading `## Repo state: not a git repo` outside git | always |
|
|
28
28
|
| `## Decisions` | bullets; rejected alternatives marked `rejected:` | always |
|
|
29
29
|
| `## Skills loaded` | frontmatter `name`s; `## Skills loaded: none` when none | always |
|
|
30
|
-
| `## Process state` | `phase_tracker status` then `plan_tracker status` verbatim; `Active task: <name|none>`; optional `PR: <owner/repo#N>`
|
|
30
|
+
| `## Process state` | `phase_tracker status` then `plan_tracker status` verbatim; `Active task: <name|none>`; optional one or more consecutive `PR: <owner/repo#N>` / `Pre-rework head: <40-char sha>` pairs, one per record group, home first, in record order, only for a PR subject; the line `Gate history not restored - re-validate before advancing.` | only when a phase is `in_progress` and no hotfix flow is in context |
|
|
31
31
|
|
|
32
32
|
For a loop ledger (line 1 exactly `# Ledger - loop engine`), replace `Active task` with these two fields, retaining both tracker status outputs and the gate-history line:
|
|
33
33
|
|
|
@@ -51,10 +51,11 @@ inline. `## Repo state` is matched by prefix: `## Repo state` or
|
|
|
51
51
|
cohort's `handoff` skill wrote, which ends at `## Skills loaded`. Layout, byte-exact:
|
|
52
52
|
one blank line, the heading on its own line, a blank line, the `phase_tracker status`
|
|
53
53
|
output verbatim, a blank line, the `plan_tracker status` output verbatim, a blank line,
|
|
54
|
-
`Active task: <name|none>`, then, only for a PR subject,
|
|
55
|
-
`PR: <owner/repo#N>`
|
|
54
|
+
`Active task: <name|none>`, then, only for a PR subject, one or more consecutive
|
|
55
|
+
`PR: <owner/repo#N>` / `Pre-rework head: <40-char sha>` pairs, one per record group,
|
|
56
|
+
home first, in record order, then the gate-history line after the last pair -
|
|
56
57
|
unfenced, nothing after.
|
|
57
|
-
For a task plan, set `Active task` to the first `→` task name, else `none` (also for `No plan active.`). For a line-1 ledger, read its path and last decision and use the loop alternative above, retaining the optional PR
|
|
58
|
+
For a task plan, set `Active task` to the first `→` task name, else `none` (also for `No plan active.`). For a line-1 ledger, read its path and last decision and use the loop alternative above, retaining the optional PR pairs before the gate-history line. Copy only top-level record pairs, without titles; `Threads:` and record `### PR #<N>` subsections are not brief fields. For N=1 emit one pair; without a Rework record use the ordinary layout.
|
|
58
59
|
|
|
59
60
|
Example appended block (the fence is documentation; the brief carries no fence):
|
|
60
61
|
|
|
@@ -114,12 +115,20 @@ Parse stops (print the offending line, make no tracker call):
|
|
|
114
115
|
|
|
115
116
|
## Process-state restore
|
|
116
117
|
|
|
117
|
-
Before any tracker write, read the optional PR
|
|
118
|
+
Before any tracker write, read the optional ordered PR pairs. Fetch branch identity
|
|
119
|
+
from the first pair only (home) with
|
|
118
120
|
`gh pr view <N> --repo <owner/repo> --json headRefName`. Compare `headRefName` with
|
|
119
121
|
`git -C <worktree> branch --show-current`. A mismatch stops with
|
|
120
122
|
`brief names PR #N on <headRefName>, worktree is on <branch>`, substituting the observed PR number and both actual branch names, never literal placeholders; a failed fetch stops
|
|
121
|
-
with its error.
|
|
122
|
-
|
|
123
|
+
with its error. Do not fetch later pairs' branches for this identity check.
|
|
124
|
+
Read the worktree spec's `## Rework record` and compare its top-level `PR:` identities
|
|
125
|
+
(without titles) with the brief identities in order. A mismatch stops with
|
|
126
|
+
`brief lists <brief order>, record lists <record order>`, substituting both observed
|
|
127
|
+
ordered lists, before any tracker call. Resolve the spec through reconstruction's
|
|
128
|
+
candidate rules below before this comparison; artifact presence supplies no approval.
|
|
129
|
+
Carry all paired full pre-rework heads downstream in their original order;
|
|
130
|
+
reconstruction uses the first pair's head as its scan base. Without optional pairs,
|
|
131
|
+
retain ordinary restoration.
|
|
123
132
|
Preserve the entry checks, standing-grant validation, plan repair, and task snapshot;
|
|
124
133
|
PR identity implies no approval or gate evidence.
|
|
125
134
|
|
|
@@ -25,7 +25,7 @@ for a base ref before reading any artifact.
|
|
|
25
25
|
|
|
26
26
|
A pinned spec (seed route, `seed.md`) skips this section.
|
|
27
27
|
|
|
28
|
-
When the brief carries `Pre-rework head
|
|
28
|
+
When the brief carries PR pairs, use the first pair's full `Pre-rework head:` SHA as `<base>` for spec
|
|
29
29
|
and plan candidate scans instead of the merge-base from "Base"; the PR's earlier
|
|
30
30
|
spec remains input, not an added candidate, so it does not trigger a multi-spec pick.
|
|
31
31
|
Keep pairing, untracked candidates, task evidence, and human confirmation below.
|
|
@@ -41,7 +41,13 @@ git -C <worktree> ls-files --others --exclude-standard -- <dirs>
|
|
|
41
41
|
Candidates are files under those directories added after base, plus untracked files
|
|
42
42
|
there. Paths returned by these commands are relative to `<worktree>`; resolve them to
|
|
43
43
|
absolute paths under `<worktree>` before reading artifacts, showing paths in prompts,
|
|
44
|
-
or calling `plan_check`. Read
|
|
44
|
+
or calling `plan_check`. Read candidate contents before choosing. For a PR-list brief,
|
|
45
|
+
read the rework candidate's `## Rework record` and the member-carried spec paths listed
|
|
46
|
+
under each member in `## Problem`; exclude exactly those paths from new-rework spec
|
|
47
|
+
candidates before the multi-spec prompt. Keep this explicit exclusion set authoritative through plan/ledger pairing: when a task plan's basename or a ledger's `**Spec:**` header resolves to an excluded member spec, skip that pair in route candidates. Never promote an excluded member spec through its carried plan or ledger. Keep all other plan/spec pairing below, including
|
|
48
|
+
base-tracked specs. Artifact presence never supplies approval. Never choose by filename
|
|
49
|
+
when remaining candidates are genuinely ambiguous; ask the human.
|
|
50
|
+
Read every plan-directory candidate's first line. A line exactly `# Ledger - loop engine` pairs by its path-only `**Spec:**` header, not basename; resolve that spec under the worktree's configured spec dirs, including a spec tracked from base. Stop on a missing or foreign spec. A task-plan candidate pairs with
|
|
45
51
|
`<worktree>/<specDir>/<same basename>` whether that spec is a candidate or tracked
|
|
46
52
|
from base; count a base-tracked spec so paired as a spec in the route table below.
|
|
47
53
|
The plan commit is the first
|
|
@@ -2,16 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Select home and stop before writes
|
|
4
4
|
|
|
5
|
-
For a caller passing PR values, follow this reference instead of `using-git-worktrees/SKILL.md` Steps 0 and 1. Derive ROOT from the absolute git common directory as in Step 0, applying its submodule guard. Resolve the worktree home through the existing overrides/native-tool/wrapper contract; default to `$ROOT/.worktrees/<name>`. Set `<name>` to `headRefName` with every `/` replaced by `-`. Never adopt the session's linked tree unless it is the selected home on `headRefName`.
|
|
5
|
+
Consume the ordered array of admitted PR values, home first; use home's `headRefName` for checkout and `PRE_REWORK_HEAD=<home headRefOid>`. Carry the remaining entries as MEMBER_HEADS `{ number, url, title, headRefName, headRefOid }`. For a caller passing PR values, follow this reference instead of `using-git-worktrees/SKILL.md` Steps 0 and 1. Derive ROOT from the absolute git common directory as in Step 0, applying its submodule guard. Resolve the worktree home through the existing overrides/native-tool/wrapper contract; default to `$ROOT/.worktrees/<name>`. Set `<name>` to `headRefName` with every `/` replaced by `-`. Never adopt the session's linked tree unless it is the selected home on `headRefName`.
|
|
6
6
|
|
|
7
|
-
Run `git -C "$ROOT" fetch origin`, then check these stops in order before creating or modifying any file in the primary or a worktree, or running `git worktree add`.
|
|
7
|
+
Run `git -C "$ROOT" fetch origin`, then check reachability and remote equality for every admitted PR (home and members) before any worktree write: require each original `headRefOid` object and `origin/<headRefName>` equal to it; use the branch-moved stop below naming that PR. Resolve `BASE_SHA=$(git -C "$ROOT" rev-parse origin/<baseRefName>)` as a full SHA before any conflict helper needs fetched-base overrides. Then check these stops in order before creating or modifying any file in the primary or a worktree, or running `git worktree add`.
|
|
8
8
|
|
|
9
9
|
| Observable case | Exact stop |
|
|
10
10
|
|---|---|
|
|
11
11
|
| `isCrossRepository` true | `PR #N's head lives on fork <headRepository.nameWithOwner>; rework needs an in-repo branch.` |
|
|
12
12
|
| `headRefName` listed by `git -C "$ROOT" worktree list --porcelain` at another path, including `.worktrees/pr-<N>` | `branch <headRefName> is checked out at <path>; finish or remove that worktree first.` |
|
|
13
13
|
| `git -C "$ROOT" rev-parse --verify -q <headRefOid>^{commit}` fails after fetch, or `origin/<headRefName>` differs from `headRefOid` | `PR #N head <headRefOid7> is not reachable (origin/<headRefName> is at <sha7>); the branch moved.` |
|
|
14
|
-
|
|
|
14
|
+
| N=1: local branch exists and `git -C "$ROOT" merge-base --is-ancestor <headRefName> origin/<headRefName>` exits 1 | `local branch <headRefName> is at <sha7>, not an ancestor of origin/<headRefName> (<sha7>); rework needs the PR head.` |
|
|
15
|
+
|
|
16
|
+
## Recover interrupted member merges
|
|
17
|
+
|
|
18
|
+
For a list with an existing home worktree or local branch, inspect the actual local home branch tip with `git -C "$ROOT" rev-parse refs/heads/<headRefName>`, never caller HEAD. Require home `headRefOid` ancestry, then walk `git -C "$ROOT" log --first-parent --format='%H %P %s' <headRefOid>..<local home tip>`. Require every entry to be a two-parent merge with canonical subject `merge PR #<N> head <sha7> into PR #<home>`, where N is an admitted member, sha7 matches its original head, and its full original `headRefOid` is the second parent. Require a clean existing home tree. On unrelated commits, failed ancestry, or dirt, stop before writes: `worktree <path> on <headRefName> carries commits beyond PR #<home>'s head (<sha7>) that are not member merges from this list; resolve by hand or remove the worktree.` Use the selected home path even when no worktree exists.
|
|
19
|
+
|
|
20
|
+
Continue from the validated tip without reset, rebase, or branch deletion. For recognized merges skip the member and report `Member merge: #<N> <sha7> (already landed)` using the existing merge commit SHA. N=1 retains the exact-head checks below.
|
|
15
21
|
|
|
16
22
|
## Provision the exact head
|
|
17
23
|
|
|
@@ -19,13 +25,14 @@ Apply the first matching row after all stops pass. Keep the process cwd unchange
|
|
|
19
25
|
|
|
20
26
|
| State | Action |
|
|
21
27
|
|---|---|
|
|
22
|
-
|
|
|
28
|
+
| List recovery validated an existing home branch | Reuse its clean selected worktree unchanged; with no worktree, run `git -C "$ROOT" worktree add "$WORKTREE" <headRefName>` on that existing branch. Verify `git -C "$WORKTREE" rev-parse HEAD` equals the validated local tip. Never use update-ref, -b, reset, clean, or deletion on recovery. |
|
|
29
|
+
| Selected home is already on `headRefName` (N=1) | Run Step 3's dirty-tree ask first; do not stash or clean automatically. Then run `git -C "$WORKTREE" merge --ff-only origin/<headRefName>` and require HEAD equal to `headRefOid`; otherwise stop naming both SHAs. |
|
|
23
30
|
| No worktree, local branch exists | Only after ancestry proof, run `git -C "$ROOT" update-ref refs/heads/<headRefName> origin/<headRefName>`, then `git -C "$ROOT" worktree add "<home>" <headRefName>`. Never use `git -C "$ROOT" branch -f`. |
|
|
24
31
|
| No worktree, no local branch | Run `git -C "$ROOT" worktree add "<home>" <headRefName>`. Git's unique-remote DWIM resolves exactly one matching remote-tracking branch as `--track -b <headRefName> "<home>" origin/<headRefName>`; do not substitute the generic new-branch `-b` creation path. |
|
|
25
32
|
|
|
26
33
|
For fresh creation, apply Step 3's source-clean ask and the existing home safety checks after the ordered stops. Respect the resolved home and native tool/wrapper, but use an overrides `create:` only when it takes `<branch>` as an existing branch and contains no `-b`/`-B`. Otherwise run the built-in checkout above and add `create: override skipped (contains -b)` to the report. Resolve tokens and surface wrapper failures through the existing contract.
|
|
27
34
|
|
|
28
|
-
Verify `git -C "$WORKTREE" rev-parse HEAD` equals `headRefOid
|
|
35
|
+
Verify `git -C "$WORKTREE" rev-parse HEAD` equals `headRefOid` for fresh creation or N=1, or the validated recovery tip for a list. On a post-create head race, leave the tree intact and stop naming its path and both SHAs. Capture `PRE_REWORK_HEAD=<headRefOid>` and `BASE_SHA=$(git -C "$ROOT" rev-parse origin/<baseRefName>)` as full SHAs. In the Step 4 report use `Base: <headRefName> @ <sha7>` and add immediately after it:
|
|
29
36
|
|
|
30
37
|
```text
|
|
31
38
|
PR: <owner/repo#N>
|
|
@@ -37,6 +44,16 @@ Base SHA: <sha7>
|
|
|
37
44
|
|
|
38
45
|
Advance by merge: preserve every commit reachable from PRE_REWORK_HEAD. Never `git rebase`, or use `reset` or `commit --amend` to replace a commit at or below that boundary. Keep the flow's appended-spec approval `commit --amend --no-edit` in `brainstorming/reference/spec-finalization.md` and appended-wave fold `reset --soft "$WAVE_BASE_SHA"` in `subagent-driven-development/SKILL.md` unchanged; require WAVE_BASE_SHA to descend from PRE_REWORK_HEAD.
|
|
39
46
|
|
|
47
|
+
## Merge admitted member heads
|
|
48
|
+
|
|
49
|
+
Before the base merge, iterate remaining MEMBER_HEADS in listed order. Save the last-good home SHA before each merge. Run `git -C "$WORKTREE" merge --no-ff -m "merge PR #<N> head <sha7> into PR #<home>" <headRefOid>` using the original supplied head, not a newly advanced remote tip. On success record `Member merge: #<N> <merge sha7>`; an ancestor no-op records no new commit.
|
|
50
|
+
|
|
51
|
+
For conflicts use the fetched-base scoped-runner selection and helper/completion recipe in "Merge the fetched base": fresh foreground implementer, exact conflicted paths, staging, empty unmerged index, contained status delta, and orchestrator `git -C "$WORKTREE" commit --no-edit`. Preserve the canonical subject, including in a manual resolution. Record any contract exception for the spec's Rework record.
|
|
52
|
+
|
|
53
|
+
On helper or completion failure run `git -C "$WORKTREE" merge --abort` and capture its exit status. Before claiming restoration, require abort exit status 0, `git -C "$WORKTREE" rev-parse HEAD` equal to the saved last-good full SHA, `git -C "$WORKTREE" branch --show-current` equal to home's `headRefName`, and successful `git -C "$WORKTREE" status --porcelain --untracked-files=all` with empty output (checkout and index clean). On any failed check or residual edit, stop naming the failing PR, conflicted files, selected worktree, observed branch and HEAD, abort exit status, remaining status paths or inspection errors, and saved last-good SHA with earlier merged members; require manual recovery before rerunning and do not claim restoration. Never reset or clean to force recovery. Only after all checks pass, stop with `PR #<N> conflicts with home PR #<home> in <files>; the worktree at <path> is left on <headRefName> at <sha7> with #<earlier members> already merged; merge #<N> by hand there (git merge --no-ff <headRefOid>) and rerun the same list, or rerun without #<N>.` Tell the developer to retain the canonical subject for manual merging. Stop before the base merge, spec, plan, later member merges, push, or close. Do not use the base-conflict continuation for member failures.
|
|
54
|
+
|
|
55
|
+
After all members, merge the fetched base. In the Step 4 report print one `PR:` / `Pre-rework head:` pair per admitted PR, home first, followed by member outcome lines in listed order, then the base outcome; print Base SHA once. Carry MEMBER_HEADS to gather.
|
|
56
|
+
|
|
40
57
|
## Merge the fetched base
|
|
41
58
|
|
|
42
59
|
Run `git -C "$WORKTREE" merge --no-ff --no-edit origin/<baseRefName>` and record the matching outcome:
|
|
@@ -44,10 +61,10 @@ Run `git -C "$WORKTREE" merge --no-ff --no-edit origin/<baseRefName>` and record
|
|
|
44
61
|
| Outcome | Record and continuation |
|
|
45
62
|
|---|---|
|
|
46
63
|
| Base already an ancestor | `merge: no-op - head contains origin/<base>`; no commit. |
|
|
47
|
-
| Clean merge | `merge: <sha7>`; this merge
|
|
64
|
+
| Clean merge | `merge: <sha7>`; this merge follows the member merges (the first rework commit for N=1). |
|
|
48
65
|
| Conflicts | Follow the helper recipe below. |
|
|
49
66
|
|
|
50
|
-
Snapshot `git -C "$WORKTREE" status --porcelain` before helper dispatch. Get conflicted paths with `git -C "$WORKTREE" diff --name-only --diff-filter=U`. Dispatch one fresh foreground `implementer`, `cwd` the worktree, `async: false`, with that exact file list, fetched base, and SCOPED_TEST_COMMANDS. Require resolution of every listed file preserving both sides' intent, exactly the supplied scoped commands, and `git -C "$WORKTREE" add` for every resolved file. Require return `done`, or `done - contract exception: <why>` when resolution changes a PR or bound-ticket obligation. Forbid helper commits, aborts, and edits outside the list.
|
|
67
|
+
Keep the process cwd unchanged; explicitly target the selected worktree in every helper discovery, status, staging, completion, commit, and abort command. Snapshot `git -C "$WORKTREE" status --porcelain` before helper dispatch. Get conflicted paths with `git -C "$WORKTREE" diff --name-only --diff-filter=U`. Dispatch one fresh foreground `implementer`, `cwd` the worktree, `async: false`, with that exact file list, fetched base, and SCOPED_TEST_COMMANDS. Require resolution of every listed file preserving both sides' intent, exactly the supplied scoped commands, and `git -C "$WORKTREE" add` for every resolved file. Require return `done`, or `done - contract exception: <why>` when resolution changes a PR or bound-ticket obligation. Forbid helper commits, aborts, and edits outside the list.
|
|
51
68
|
|
|
52
69
|
Read the first-found overrides file from BASE_SHA, not the conflicted tree: `git -C "$ROOT" show <BASE_SHA>:<overrides path>`. Use SCOPED_TEST_COMMANDS only from a documented file-scoped runner under `## PR gate` or `## verification-before-completion` with `requires credentials` not `true`. Missing runner or `requires credentials: true` means `none`, with the reason recorded as `none run (<reason>)`. Never infer file scope from a full-suite script such as `npm test`.
|
|
53
70
|
|
|
@@ -55,11 +72,13 @@ Continue only with an empty unmerged index (`git -C "$WORKTREE" diff --name-only
|
|
|
55
72
|
|
|
56
73
|
For any failed helper/completion checks, run `git -C "$WORKTREE" merge --abort`, record `merge: unresolved - <files>`, and continue on the original unmerged head. Open the spec's Design with `merge origin/<base> and resolve <files>` as eventual Task 1. On every outcome, require the base-SHA constraint reads owned by `brainstorming/reference/pr-subject.md`.
|
|
57
74
|
|
|
58
|
-
|
|
75
|
+
After every base-merge outcome, including clean, no-op, resolved, and aborted unresolved, prove home and every member's original head against final HEAD: require `git -C "$WORKTREE" merge-base --is-ancestor <each original head> HEAD` to exit 0. Stop on any nonzero exit, naming that PR and its original head.
|
|
76
|
+
|
|
77
|
+
Treat the base merge and each admitted member-head merge, their conflict helpers' edits to the conflicted files, and their scoped conflict tests as the sole preapproval write/run exception outside spec directories. Run no other brainstorming tests, dispatch no reviewer, and push nothing; leave review of the merge to end-of-flow code review.
|
|
59
78
|
|
|
60
79
|
## Fetch unresolved review threads
|
|
61
80
|
|
|
62
|
-
Run this query; callers cite this owner rather than copying it:
|
|
81
|
+
Run this query per admitted PR, N=1 included, before gather; callers cite this owner rather than copying it:
|
|
63
82
|
|
|
64
83
|
```
|
|
65
84
|
gh api graphql --paginate -f query='query($o:String!,$r:String!,$n:Int!,$endCursor:String){repository(owner:$o,name:$r){pullRequest(number:$n){reviewThreads(first:100,after:$endCursor){pageInfo{hasNextPage endCursor} nodes{id isResolved isOutdated path line originalLine comments(first:100){pageInfo{hasNextPage endCursor} totalCount nodes{url body author{login} createdAt}}}}}}}' -F o=<owner> -F r=<repo> -F n=<N>
|
|
@@ -71,4 +90,4 @@ Merge every reviewThreads page and filter to `isResolved == false`. For each thr
|
|
|
71
90
|
gh api graphql --paginate -f query='query($id:ID!,$endCursor:String){node(id:$id){... on PullRequestReviewThread{comments(first:100,after:$endCursor){pageInfo{hasNextPage endCursor} nodes{url body author{login} createdAt}}}}}' -F id=<thread id>
|
|
72
91
|
```
|
|
73
92
|
|
|
74
|
-
Start that thread's follow-up query at its first comment page, then replace its initial comments with the complete paginated connection to avoid duplicates. Keep each thread's comment cursor separate from the reviewThreads cursor and fetch until its last page. Carry all comments in order: read the first request and every reply because replies can change the request. Render location as `<path>:<line>`, else `<path>:<originalLine> (outdated)`, else `<path>`. On
|
|
93
|
+
Start that thread's follow-up query at its first comment page, then replace its initial comments with the complete paginated connection to avoid duplicates. Keep each thread's comment cursor separate from the reviewThreads cursor and fetch until its last page. Carry all comments in order: read the first request and every reply because replies can change the request. Render location as `<path>:<line>`, else `<path>:<originalLine> (outdated)`, else `<path>`. On any thread or comment fetch failure stop before gather and spec with `threads for #<N> not fetched (<gh error>)`. Finish owns its distinct post-verification fetch-failure reporting. On successful empty fetch record `Threads: none`.
|