pi-gauntlet 5.18.7 → 5.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +5 -2
- package/bin/gauntlet-telemetry-seal.mjs +346 -0
- package/bin/gauntlet-telemetry-seal.test.mjs +271 -0
- package/extensions/lib/telemetry-diff.test.ts +108 -0
- package/extensions/lib/telemetry-diff.ts +61 -0
- package/extensions/lib/telemetry-paths.test.ts +11 -35
- package/extensions/lib/telemetry-paths.ts +13 -42
- package/extensions/lib/telemetry-record.test.ts +0 -6
- package/extensions/lib/telemetry-ship.test.ts +1 -5
- package/extensions/lib/telemetry-ship.ts +1 -4
- package/extensions/telemetry.test.ts +243 -135
- package/extensions/telemetry.ts +148 -201
- package/package.json +2 -2
- package/skills/brainstorming/SKILL.md +1 -1
- package/skills/finishing-a-development-branch/SKILL.md +19 -16
- package/skills/gatekeep-pr/reference/assessment.md +0 -13
- package/skills/gatekeep-pr/reference/decision-menu.md +1 -2
- package/skills/gatekeep-pr/reference/post-selection-loop.md +3 -3
- package/skills/gauntlet-performance/SKILL.md +1 -1
- package/skills/gauntlet-resume/SKILL.md +46 -32
- package/skills/gauntlet-resume/reference/brief-contract.md +12 -8
- package/skills/gauntlet-resume/reference/reconstruction.md +10 -3
- package/skills/gauntlet-resume/reference/seed.md +47 -0
- package/bin/gauntlet-telemetry-salvage.mjs +0 -273
- package/bin/gauntlet-telemetry-salvage.test.mjs +0 -466
|
@@ -181,9 +181,11 @@ Rows 1-2 run the Option 1/2 blocks; row 3 runs the Keep block and row 4 the Disc
|
|
|
181
181
|
|
|
182
182
|
### Step 5: Execute Choice
|
|
183
183
|
|
|
184
|
-
#### Strip the plan,
|
|
184
|
+
#### Strip the plan, seal the record (Options 1-3)
|
|
185
185
|
|
|
186
|
-
Run this on the feature branch before any landing path. The spec and its telemetry record (`<telemetry.dir>/<spec path with .md -> .yaml>`, default `.pi/gauntlet/telemetry/doc/specs/<spec>.yaml`) are deliverables and ship in the squash; only the plan is stripped. `<bin>` is `<directory of this skill's SKILL.md>/../../bin`, resolved from the skill's `<location>` in the system prompt.
|
|
186
|
+
Run this on the feature branch before any landing path. The spec and its telemetry record (`<telemetry.dir>/<spec path with .md -> .yaml>`, default `.pi/gauntlet/telemetry/doc/specs/<spec>.yaml`) are deliverables and ship in the squash; only the plan is stripped. The record is an untracked, git-excluded file until this step commits it. `<bin>` is `<directory of this skill's SKILL.md>/../../bin`, resolved from the skill's `<location>` in the system prompt.
|
|
187
|
+
|
|
188
|
+
Read the plan's `**Spec:**` header (repo-relative, backticks stripped) before the strip; that value is `--spec`.
|
|
187
189
|
|
|
188
190
|
```bash
|
|
189
191
|
# Plans are ephemeral - if one was committed on this branch, remove it before landing.
|
|
@@ -192,15 +194,16 @@ if git -C "$WORKTREE" ls-files --error-unmatch "$PLAN_PATH" >/dev/null 2>&1; the
|
|
|
192
194
|
git -C "$WORKTREE" rm "$PLAN_PATH" && git -C "$WORKTREE" commit -m "Remove ephemeral plan doc"
|
|
193
195
|
fi
|
|
194
196
|
|
|
195
|
-
#
|
|
196
|
-
|
|
197
|
+
# Seal the telemetry record: stamp shipped, compute the diff, commit it once.
|
|
198
|
+
# --option is pr for Options 1-2 and squash for Option 3; --spec is the plan header's **Spec:** value (omit when no plan is known).
|
|
199
|
+
node <bin>/gauntlet-telemetry-seal.mjs --worktree "$WORKTREE" --option <pr|squash> --base <base-branch> --spec <spec path>
|
|
197
200
|
```
|
|
198
201
|
|
|
199
|
-
The
|
|
202
|
+
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 failure (`seal failed <path>: <reason>` restored the pre-seal bytes). The user decides; never land without the seal.
|
|
200
203
|
|
|
201
204
|
#### Option 1: Push and Create PR
|
|
202
205
|
|
|
203
|
-
Run the strip-and-
|
|
206
|
+
Run the strip-and-seal block above first (plan stripped, telemetry record sealed), then:
|
|
204
207
|
|
|
205
208
|
```bash
|
|
206
209
|
# Push branch
|
|
@@ -231,11 +234,11 @@ When the spec's `## Acceptance criteria` has at least one `venue:` or `deferred:
|
|
|
231
234
|
|
|
232
235
|
#### Option 2: Push and Create Draft PR
|
|
233
236
|
|
|
234
|
-
Run the strip-and-
|
|
237
|
+
Run the strip-and-seal block above first (plan stripped, telemetry record sealed), then Option 1's push and `gh pr create` commands with `--draft` added. The PR body is unchanged. Do not clean up the worktree.
|
|
235
238
|
|
|
236
239
|
#### Option 3: Squash-merge to base
|
|
237
240
|
|
|
238
|
-
Run the strip-and-
|
|
241
|
+
Run the strip-and-seal block above first (plan stripped, telemetry record sealed), then:
|
|
239
242
|
|
|
240
243
|
```bash
|
|
241
244
|
git -C "$PRIMARY" checkout <base-branch>
|
|
@@ -245,7 +248,7 @@ git -C "$PRIMARY" commit -m "<imperative summary> (ref <ticket-id>)"
|
|
|
245
248
|
(cd "$PRIMARY" && <the Step 1 set>)
|
|
246
249
|
```
|
|
247
250
|
|
|
248
|
-
The plan was already removed on the branch, so the staged squash tree carries the spec, the telemetry record, and the implementation - never the plan.
|
|
251
|
+
The plan was already removed and the telemetry record sealed on the branch, so the staged squash tree carries the spec, the telemetry record, and the implementation - never the plan.
|
|
249
252
|
|
|
250
253
|
The post-squash re-verify is not optional - `git merge --squash` can surface conflict-resolution mistakes the worktree-side run couldn't catch.
|
|
251
254
|
|
|
@@ -255,7 +258,7 @@ Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `git -C "$PRIMA
|
|
|
255
258
|
|
|
256
259
|
#### Option 4: Keep As-Is
|
|
257
260
|
|
|
258
|
-
Report: "Keeping branch <name>. Worktree preserved at <path>."
|
|
261
|
+
Report: "Keeping branch <name>. Worktree preserved at <path>." The telemetry record stays untracked and in_progress in the worktree; a later finishing run on this worktree seals it.
|
|
259
262
|
|
|
260
263
|
**Don't cleanup worktree.**
|
|
261
264
|
|
|
@@ -273,7 +276,7 @@ Type 'discard' to confirm.
|
|
|
273
276
|
|
|
274
277
|
Wait for exact confirmation.
|
|
275
278
|
|
|
276
|
-
If confirmed: Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `git -C "$PRIMARY" branch -D "$FEATURE"`.
|
|
279
|
+
If confirmed: Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `git -C "$PRIMARY" branch -D "$FEATURE"`. The record is git-excluded, so git worktree remove needs no --force; it goes with the worktree.
|
|
277
280
|
|
|
278
281
|
### Step 6: Cleanup Workspace
|
|
279
282
|
|
|
@@ -294,7 +297,7 @@ Removal precedes branch deletion in both options; `git branch -d`/`-D` fails whi
|
|
|
294
297
|
|
|
295
298
|
## Quick Reference
|
|
296
299
|
|
|
297
|
-
| Option | Merge | Push | Keep Worktree | Cleanup Branch | Plan strip + record
|
|
300
|
+
| Option | Merge | Push | Keep Worktree | Cleanup Branch | Plan strip + record seal |
|
|
298
301
|
|---|---|---|---|---|---|
|
|
299
302
|
| 1. Create PR | - | yes | yes | - | yes (guarded, on the branch before push) |
|
|
300
303
|
| 2. Create draft PR | - | yes | yes | - | yes (guarded, on the branch before push) |
|
|
@@ -334,13 +337,13 @@ A host-owned worktree (Step 6 "Otherwise") keeps both the worktree and the branc
|
|
|
334
337
|
- **Problem:** Accidentally delete work
|
|
335
338
|
- **Fix:** Require typed "discard" confirmation
|
|
336
339
|
|
|
337
|
-
**Skipping the strip-and-
|
|
340
|
+
**Skipping the strip-and-seal block in Options 1-3 (any path that lands on base)**
|
|
338
341
|
- **Problem:** Plan docs are ephemeral and shouldn't land on `<base-branch>`; the telemetry record is a deliverable and must. Skipping the block ships the plan, or drops the record the spec index reads.
|
|
339
342
|
- **Fix:** Run the block on `$WORKTREE` before the squash or the push. The plan stays in the branch's git history (`git -C "$PRIMARY" log --all -- doc/plans/...`). Spec and telemetry record stay on `<base-branch>`; plan does not.
|
|
340
343
|
|
|
341
344
|
**Widening the plan strip to the telemetry record**
|
|
342
345
|
- **Problem:** `.pi/gauntlet/telemetry/**` looks like scaffolding next to the plan and gets deleted in the same commit - main then has no record for the run.
|
|
343
|
-
- **Fix:** Never `git rm` under the telemetry dir.
|
|
346
|
+
- **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.
|
|
344
347
|
|
|
345
348
|
## Completion
|
|
346
349
|
|
|
@@ -363,12 +366,12 @@ Once the merge (and any deploy) has landed, `/skill:check-delivery <ticket-ref>`
|
|
|
363
366
|
- Clean up worktrees you didn't create (provenance check)
|
|
364
367
|
- Run any step without the `<worktree-path>` argument
|
|
365
368
|
- Auto-proceed past an undispositioned carried-open gap
|
|
366
|
-
- Skip the strip-and-
|
|
369
|
+
- Skip the strip-and-seal block before the Option 3 squash or the Option 1/2 push
|
|
367
370
|
- Delete the telemetry record (`.pi/gauntlet/telemetry/**` or the configured `telemetry.dir`) on any path
|
|
368
371
|
|
|
369
372
|
**Always:**
|
|
370
373
|
- Verify, or apply the Step 1 skip rule, before offering options
|
|
371
|
-
- Print the `gauntlet-telemetry-
|
|
374
|
+
- Print the `gauntlet-telemetry-seal.mjs` output verbatim in the ship completion message
|
|
372
375
|
- Derive `$PRIMARY` and `$FEATURE` from `<worktree-path>` before presenting the menu
|
|
373
376
|
- Present exactly 5 options (or 4 for detached HEAD)
|
|
374
377
|
- Get typed confirmation for Option 5 (Discard)
|
|
@@ -67,19 +67,6 @@ Orchestrator step.
|
|
|
67
67
|
local reproduction, never implying the local command ran; `<sha>` is the assessed
|
|
68
68
|
`headRefOid`, `<url>` degrades to `unavailable` when absent. Provenance checks on
|
|
69
69
|
`worktree_root`/`run_cwd` bind only to the local path.
|
|
70
|
-
- **Telemetry record:** run
|
|
71
|
-
`node <bin>/gauntlet-telemetry-salvage.mjs --worktree <provisioned path> --base
|
|
72
|
-
origin/<baseRefName> --check`. The `--check` flag makes the probe detect-only: it
|
|
73
|
-
never mutates. `present` / `no telemetry run` / `never written` land in
|
|
74
|
-
`## Evidence` as one line each. `stripped <path> in <sha>` mints a blocking `P#`
|
|
75
|
-
(`source_ref`: `gauntlet-telemetry-salvage`) whose drafted fix is "run the salvage
|
|
76
|
-
without `--check`" - the spec and its telemetry record are deliverables that ship
|
|
77
|
-
in the squash. On a cell with no push row (fork overlay, report-only states) the
|
|
78
|
-
same finding is a non-blocking follow-up instead: the record stays recoverable
|
|
79
|
-
from the PR head ref after merge, and blocking would stop a ship the gate cannot
|
|
80
|
-
repair. `unfinished <path>` (record still `in_progress` with no ship phase) also
|
|
81
|
-
lands in `## Evidence` as one line and is non-blocking: pre-landing `in_progress`
|
|
82
|
-
is normal, and the merge course's salvage run stamps it.
|
|
83
70
|
- **Evidence:** on the CI path, list each satisfying check's name, conclusion,
|
|
84
71
|
assessed SHA, and run URL - there is no command or `raw_tail` to paste. On the
|
|
85
72
|
local path, paste each run's `command` and `raw_tail` verbatim, fenced - never
|
|
@@ -12,8 +12,7 @@ Actions (compose freely in the custom row):
|
|
|
12
12
|
reviewed doc edits exist
|
|
13
13
|
in the worktree)
|
|
14
14
|
merge-squash | merge-commit (preconditions per Verdict;
|
|
15
|
-
never bundled with a push
|
|
16
|
-
except the telemetry: restore commit)
|
|
15
|
+
never bundled with a push)
|
|
17
16
|
merge-squash anyway | merge-commit anyway (custom row only: overrides a
|
|
18
17
|
reviewer-withheld merge - the literal
|
|
19
18
|
`anyway` accepts the named reason;
|
|
@@ -14,17 +14,17 @@ For a `fix <set>` selection, filter the selected set to worktree-fixable `P#`s f
|
|
|
14
14
|
|
|
15
15
|
Batch the remaining worktree-fixable set by the union of files each finding's drafted edit in `## Drafted fixes / review` touches - fall back to the `source_ref` file only when a finding has no draft. Findings whose drafts share a file share a batch.
|
|
16
16
|
|
|
17
|
-
Use one child contract for every batch, whether there is one or many: dispatch `implementer` children with `subagent({ agent: "implementer", context: "fresh", cwd: <PR worktree> })`. The orchestrator owns commit, gate, and push - never a child. Every dispatched child gets `cwd` = the PR worktree; `worktree: true` is forbidden per `assessment.md` `## Inline-first execution`. Each child is edit-only - no git commands, no verification runs
|
|
17
|
+
Use one child contract for every batch, whether there is one or many: dispatch `implementer` children with `subagent({ agent: "implementer", context: "fresh", cwd: <PR worktree> })`. The orchestrator owns commit, gate, and push - never a child. Every dispatched child gets `cwd` = the PR worktree; `worktree: true` is forbidden per `assessment.md` `## Inline-first execution`. Each child is edit-only - no git commands, no verification runs. Each child's task is that batch's `P#` lines plus the drafted edit already keyed to each ID in `## Drafted fixes / review` - the child applies the consented payload, it does not re-solve the finding.
|
|
18
18
|
|
|
19
19
|
At a cutoff of 2 worktree-fixable findings or fewer, the orchestrator applies the fix inline instead of dispatching - the no-cohort path stays available at any batch count per `assessment.md` `## Inline-first execution`. Past that cutoff, when more than one batch results, dispatch the batches' children in parallel, all under the same contract.
|
|
20
20
|
|
|
21
|
-
Once every dispatched or inline batch returns, commit the golden course as one local commit set - the code fixes plus any already-applied reviewed doc edits selected alongside them (one commit, or one per batch sequentially; subjects name the fixes). Re-resolve the evidence for the new head once (the brief's stale-head row: prior evidence is stale; the local command executes only on a fallback/opt-out resolution).
|
|
21
|
+
Once every dispatched or inline batch returns, commit the golden course as one local commit set - the code fixes plus any already-applied reviewed doc edits selected alongside them (one commit, or one per batch sequentially; subjects name the fixes). Re-resolve the evidence for the new head once (the brief's stale-head row: prior evidence is stale; the local command executes only on a fallback/opt-out resolution). On green, push once - gate and push are per-wave invariants, never per-fix or per-batch. On red, do not push: leave the commit(s) local, re-render with the unresolved `P#`s still open, and warn that unpushed fix commits sit in the worktree exactly like unpushed doc edits (per `### Teardown`).
|
|
22
22
|
|
|
23
23
|
Doc fixes (`push-docs` alone) follow the same rule: stage and commit (subject names what is documented), re-run the gate, and push only on green. Execute reviews, replies, and tracker actions via `gh pr review` / `gh api` / the tracker tool, non-interactively, with the drafted payload for the selected IDs.
|
|
24
24
|
|
|
25
25
|
### Merge course
|
|
26
26
|
|
|
27
|
-
Merge always executes as `gh pr merge --match-head-commit <assessed-sha>`. Push and merge are never bundled into one selection
|
|
27
|
+
Merge always executes as `gh pr merge --match-head-commit <assessed-sha>`. Push and merge are never bundled into one selection. A merge selection while any precondition (SKILL.md `## Verdict`) fails is refused, naming the failing precondition, and the menu re-renders - never a dead end, never a silent merge.
|
|
28
28
|
|
|
29
29
|
### Re-render
|
|
30
30
|
|
|
@@ -18,7 +18,7 @@ The CLI parses and aggregates; you reason. Never open a telemetry YAML record yo
|
|
|
18
18
|
|
|
19
19
|
## Read the digest
|
|
20
20
|
|
|
21
|
-
`runs` has one row per record; `shipped*` marks a truncated run (no ship phase recorded - salvage stamped it at landing; its `wall` is `-` and it feeds no aggregate). `by version` groups by pi-gauntlet version: `n` counts every row, `shipped` counts the rows behind the p50/max columns. `grants` is `fix_round_grants` - the fix-round proxy (human-granted extra review rounds); schema 1 has no code-review round count.
|
|
21
|
+
`runs` has one row per record; `shipped*` marks a truncated run (no ship phase recorded - an older salvage stamped it at landing; its `wall` is `-` and it feeds no aggregate). `by version` groups by pi-gauntlet version: `n` counts every row, `shipped` counts the rows behind the p50/max columns. `grants` is `fix_round_grants` - the fix-round proxy (human-granted extra review rounds); schema 1 has no code-review round count.
|
|
22
22
|
|
|
23
23
|
## Reply - exactly this, in this order
|
|
24
24
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gauntlet-resume
|
|
3
|
-
description: Use when a human wants to continue an interrupted gauntlet flow in a fresh session - from a gauntlet-handoff brief (file, pasted, or picked from the default handoff directory)
|
|
3
|
+
description: Use when a human wants to continue an interrupted gauntlet flow in a fresh session - from a gauntlet-handoff brief (file, pasted, or picked from the default handoff directory), from a bare worktree that already holds a spec, or from a spec tracked on main (creates or reuses its worktree via `/skill:using-git-worktrees`). Human-only; the sole resume entry point. Restores phase/plan tracker state through the legal arming sequence, never infers approval.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
argument-hint: "[<brief-file>
|
|
5
|
+
argument-hint: "[<brief-file> | <spec>.md | <worktree-name-or-path>]"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
> **Related skills:** Continues into `/skill:writing-plans`, `/skill:subagent-driven-development`, or `/skill:verification-before-completion` depending on the restored stage. `/skill:brainstorming` is where new ideas go - a free-form prompt is not a resume input.
|
|
@@ -11,48 +11,61 @@ argument-hint: "[<brief-file>] [<worktree-name-or-path>]"
|
|
|
11
11
|
|
|
12
12
|
## Overview
|
|
13
13
|
|
|
14
|
-
Re-enter an interrupted gauntlet flow in a fresh session.
|
|
15
|
-
produced by `/skill:gauntlet-handoff` (grammar in `reference/brief-contract.md`),
|
|
14
|
+
Re-enter an interrupted gauntlet flow in a fresh session. Three inputs: a handoff brief
|
|
15
|
+
produced by `/skill:gauntlet-handoff` (grammar in `reference/brief-contract.md`), a bare
|
|
16
16
|
worktree whose spec/plan artifacts are reconstructed into tracker state
|
|
17
|
-
(`reference/reconstruction.md`). Every check runs
|
|
18
|
-
stop names the offending path, field, or line.
|
|
17
|
+
(`reference/reconstruction.md`), a spec seed (`reference/seed.md`). Every check runs
|
|
18
|
+
before any tracker mutation; every stop names the offending path, field, or line.
|
|
19
19
|
|
|
20
20
|
**Announce at start:** "I'm using the gauntlet-resume skill to continue an interrupted flow."
|
|
21
21
|
|
|
22
22
|
## Boundaries
|
|
23
23
|
|
|
24
24
|
- Reads: anything.
|
|
25
|
-
- Writes: `phase_tracker` / `plan_tracker` state
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
the
|
|
25
|
+
- Writes: `phase_tracker` / `plan_tracker` state after every check passes and every
|
|
26
|
+
human question is answered; on the seed route, what `/skill:using-git-worktrees`
|
|
27
|
+
writes. Never a spec copy, rename, or marker commit.
|
|
28
|
+
- Never: `git worktree add` directly; worktree creation by resume itself only on
|
|
29
|
+
the seed route, only through `/skill:using-git-worktrees`; infer approval from
|
|
30
|
+
artifact presence; restore
|
|
31
|
+
gate history, closure-review evidence, or fix rounds; start a later phase directly
|
|
32
|
+
(that does not arm the flow).
|
|
30
33
|
|
|
31
34
|
## Arguments
|
|
32
35
|
|
|
33
|
-
`/skill:gauntlet-resume [<
|
|
34
|
-
optional pasted text after the command line.
|
|
36
|
+
`/skill:gauntlet-resume [<token>] [<worktree>]` - zero to two positional tokens, plus
|
|
37
|
+
optional pasted text after the command line. Count tokens first; then first match wins.
|
|
38
|
+
Spec dirs resolve per `reference/reconstruction.md` "Candidates" (`flowGuards.specDirs`
|
|
39
|
+
precedence).
|
|
35
40
|
|
|
36
|
-
|
|
|
41
|
+
| Input | Route |
|
|
37
42
|
|---|---|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
| no tokens, no pasted text | discovery: `<tmpdir>` via `node -p "require('os').tmpdir()"`; candidates are the regular files directly under `<tmpdir>/pi-handoff/` ending `.md` (non-recursive) whose line 1 starts `# Handoff:`; sorted by mtime, newest first; displayed one per line as `<n>. <title line> - <worktree: field value> - <mtime ISO-8601>` with `worktree: unavailable` when the field is absent; the human picks `<n>` (a single candidate is still confirmed); none -> STOP "no handoff briefs found under <tmpdir>/pi-handoff" |
|
|
44
|
+
| pasted text, line 1 starts `# Handoff:` | brief |
|
|
45
|
+
| two tokens, first an existing file with line 1 `# Handoff:` | brief with worktree override: required when the brief's worktree field is `no`/`unavailable`/not a git repo; must equal the brief's worktree after `realpath` otherwise |
|
|
46
|
+
| two tokens, first a spec seed | stop: `a spec seed takes no worktree: <second token>` |
|
|
47
|
+
| one token, existing regular file, line 1 starts `# Handoff:` | brief |
|
|
48
|
+
| one token, existing regular file ending `.md`, `realpath` under `<primary>/<specDir>` | spec seed - `reference/seed.md` |
|
|
49
|
+
| one token, existing regular file, anything else | stop: `not a handoff brief and not under <specDirs>: <path>` |
|
|
50
|
+
| one token, existing directory that is a git worktree root (`git -C <dir> rev-parse --show-toplevel` equals its `realpath`) other than `<primary>` | worktree |
|
|
51
|
+
| one token, missing path (ends `.md` or contains a separator) | stop: `not found: <path>` |
|
|
52
|
+
| one token, bare name | worktree at `<primary>/.worktrees/<name>`; missing or not a git worktree -> entry check 2 stop |
|
|
53
|
+
| anything else | stop: "this is a new idea - run /skill:brainstorming" |
|
|
54
|
+
|
|
55
|
+
A relative token resolves against the session cwd; a bare `name.md` absent there is
|
|
56
|
+
tried at `<primary>/<specDir>/name.md` per resolved spec dir in order, first hit wins.
|
|
57
|
+
`<primary>` is the checkout owning `.worktrees/`:
|
|
58
|
+
`dirname "$(git rev-parse --path-format=absolute --git-common-dir)"` run in the session
|
|
59
|
+
cwd - absolute from any primary subdirectory and from inside a linked worktree
|
|
60
|
+
(`--show-toplevel` would return the linked worktree there). A pasted brief that needs
|
|
61
|
+
an override uses the file form. A brief then runs entry checks 1-5, so a stale or
|
|
62
|
+
foreign-repo brief stops there.
|
|
52
63
|
|
|
53
64
|
## Entry checks
|
|
54
65
|
|
|
55
|
-
In order. All before any tracker mutation; entry check 1 is read-only.
|
|
66
|
+
In order. All before any tracker mutation; entry check 1 is read-only. A spec
|
|
67
|
+
seed runs check 1 here, then `reference/seed.md`, which runs check 3 itself;
|
|
68
|
+
checks 2, 4, 5 do not apply.
|
|
56
69
|
|
|
57
70
|
1. **Idle session.** `phase_tracker({ action: "status" })`. Any phase not pending ->
|
|
58
71
|
stop: "session already carries flow state - reset is your call".
|
|
@@ -91,6 +104,7 @@ In order. All before any tracker mutation; entry check 1 is read-only.
|
|
|
91
104
|
| brief without process state, `worktree: no` | invoke `/skill:brainstorming` with `## Intent` as the idea, in the current directory; resume creates no worktree - brainstorming's own Worktree First applies (a plain handoff is a new flow) |
|
|
92
105
|
| brief without process state, worktree present | `reference/reconstruction.md`, with `## Intent` and `## Decisions` carried into every confirmation prompt |
|
|
93
106
|
| bare worktree | `reference/reconstruction.md`; prompts state that no brief context is available (never invent Intent/Decisions) |
|
|
107
|
+
| spec seed | `reference/seed.md` |
|
|
94
108
|
|
|
95
109
|
**Hotfix route.** `skills/chase-bug/hotfix.md` consumes only a hotfix record at
|
|
96
110
|
`$TMPDIR/hotfix-<slug>.md`. If `## Decisions` or `## Intent` names an existing record
|
|
@@ -113,11 +127,11 @@ owning skill **without** its reset-bearing entry:
|
|
|
113
127
|
|
|
114
128
|
## Red flags — STOP
|
|
115
129
|
|
|
116
|
-
- Any `phase_tracker` or `plan_tracker` mutation before entry checks
|
|
117
|
-
human question is answered.
|
|
130
|
+
- Any `phase_tracker` or `plan_tracker` mutation before the route's entry checks pass and
|
|
131
|
+
every human question is answered.
|
|
118
132
|
- `start <phase>` for anything other than brainstorm as the first arming call.
|
|
119
133
|
- `complete` on a prior phase during restore (priors are `skip`ped with a `resume:` reason).
|
|
120
|
-
- Running `git worktree add
|
|
134
|
+
- Running `git worktree add` directly, or `cd`-ing to "fix" a cwd mismatch.
|
|
121
135
|
- Accepting a free-form prompt as a brief.
|
|
122
136
|
|
|
123
137
|
## Project overrides
|
|
@@ -53,7 +53,7 @@ Example appended block (the fence is documentation; the brief carries no fence):
|
|
|
53
53
|
## Process state
|
|
54
54
|
|
|
55
55
|
Phases:
|
|
56
|
-
⊘ brainstorm (resume:
|
|
56
|
+
⊘ brainstorm (resume: <spec path>)
|
|
57
57
|
⊘ plan (resume: pasted brief)
|
|
58
58
|
→ implement(W2)
|
|
59
59
|
○ verify
|
|
@@ -117,21 +117,25 @@ Facts that fix the order (from the extensions):
|
|
|
117
117
|
- `plan_tracker init` on an in-progress implement with every task `complete`/`skipped`
|
|
118
118
|
auto-completes implement.
|
|
119
119
|
|
|
120
|
-
Per-stage call table, keyed by the brief's active phase (`→`).
|
|
121
|
-
`resume: <brief file or "pasted brief"
|
|
120
|
+
Per-stage call table, keyed by the brief's active phase (`→`). Use
|
|
121
|
+
`R = resume: <brief file or "pasted brief">` for plan/implement/verify skips and
|
|
122
|
+
`S = resume: <spec path>` for brainstorm skips. Resolve `<spec path>` to the absolute
|
|
123
|
+
path of the single `*.md` spec added after base in the worktree under `flowGuards.specDirs`
|
|
124
|
+
(as enumerated in `reconstruction.md`, "Candidates"). Zero specs -> stop; more than
|
|
125
|
+
one -> human picks.
|
|
122
126
|
|
|
123
127
|
| Active | Calls, in order |
|
|
124
128
|
|---|---|
|
|
125
129
|
| brainstorm | `start brainstorm`; `substep` if the brief shows one |
|
|
126
|
-
| plan | `start brainstorm`; `skip brainstorm
|
|
127
|
-
| implement | `start brainstorm`; `skip brainstorm
|
|
130
|
+
| plan | `start brainstorm`; `skip brainstorm S`; `start plan`; `substep` if shown |
|
|
131
|
+
| implement | `start brainstorm`; `skip brainstorm S`; `start plan`; `plan_check({ planPath })`; on FAIL print findings and stop with plan in_progress, no init; on PASS `skip plan R`; `start implement`; `substep` if shown; `plan_tracker init` |
|
|
128
132
|
| verify | as implement through `skip plan R`, then `skip implement R`; `start verify`; `substep` if shown; `plan_tracker init` |
|
|
129
133
|
| ship | as verify. Restoration stops at verify in_progress: `complete verify` needs a fresh conformance dispatch and `skip verify` would bypass a real gate. Announce that the closure review re-runs before ship |
|
|
130
134
|
|
|
131
|
-
`planPath
|
|
135
|
+
`planPath` (implement onward): the brief carries none. Resolve as reconstruction does
|
|
132
136
|
(`reconstruction.md`, "Candidates", including its `flowGuards.specDirs` resolution): the
|
|
133
|
-
single
|
|
134
|
-
|
|
137
|
+
single plan added after base, paired with `<specDir>/<same basename>` whether that
|
|
138
|
+
spec was added after base or tracked from base (`reconstruction.md` "Candidates");
|
|
135
139
|
resolve the selected plan to an absolute path under the worktree before `plan_check`.
|
|
136
140
|
Zero pairs -> stop; more than one -> human picks.
|
|
137
141
|
|
|
@@ -23,6 +23,8 @@ for a base ref before reading any artifact.
|
|
|
23
23
|
|
|
24
24
|
## Candidates
|
|
25
25
|
|
|
26
|
+
A pinned spec (seed route, `seed.md`) skips this section.
|
|
27
|
+
|
|
26
28
|
Spec/plan directories: `piGauntlet.flowGuards.specDirs` plus each one's sibling `plans` directory. Resolve with the precedence `doc/configuration.md` documents for every `piGauntlet.*` key: the session cwd's `.pi/settings.json` if it defines `flowGuards`,
|
|
27
29
|
else the active pi profile's `settings.json`, else the default `["doc/specs"]` (sibling
|
|
28
30
|
`doc/plans`). An empty array is the default. `<dirs>` below is that resolved list,
|
|
@@ -36,15 +38,17 @@ git -C <worktree> ls-files --others --exclude-standard -- <dirs>
|
|
|
36
38
|
Candidates are files under those directories added after base, plus untracked files
|
|
37
39
|
there. Paths returned by these commands are relative to `<worktree>`; resolve them to
|
|
38
40
|
absolute paths under `<worktree>` before reading artifacts, showing paths in prompts,
|
|
39
|
-
or calling `plan_check`. A
|
|
40
|
-
|
|
41
|
+
or calling `plan_check`. A candidate plan pairs with
|
|
42
|
+
`<worktree>/<specDir>/<same basename>` whether that spec is a candidate or tracked
|
|
43
|
+
from base; count a base-tracked spec so paired as a spec in the route table below.
|
|
44
|
+
The plan commit is the first
|
|
41
45
|
post-base commit that added the plan file: `git -C <worktree> log --diff-filter=A
|
|
42
46
|
--format=%H --reverse <base>..HEAD -- <plan>`, first line. An uncommitted plan has no
|
|
43
47
|
plan commit; treat every task as `pending`.
|
|
44
48
|
|
|
45
49
|
| Candidates | Route |
|
|
46
50
|
|---|---|
|
|
47
|
-
| no spec | stop; offer `/skill:brainstorming`; no tracker call |
|
|
51
|
+
| no spec | stop; offer `/skill:brainstorming` or pass the spec: `/skill:gauntlet-resume <specDir>/<name>.md`; no tracker call |
|
|
48
52
|
| more than one spec | the human picks one, then continue below with that spec |
|
|
49
53
|
| one spec, no plan | "Spec without plan" |
|
|
50
54
|
| one spec with plan | "Spec with plan" |
|
|
@@ -71,6 +75,9 @@ Show, and ask the human to confirm or edit both in one reply:
|
|
|
71
75
|
Uncommitted plan (no
|
|
72
76
|
plan commit): skip this query entirely - there is no range to search - and show
|
|
73
77
|
"plan uncommitted; no task evidence" in its place; every task is proposed `pending`.
|
|
78
|
+
Plan commit lookup empty while `git -C <worktree> cat-file -e <base>:<plan>` exits 0
|
|
79
|
+
(plan at or before base): skip the log query, show
|
|
80
|
+
`plan predates base; no post-base task evidence`, every task proposed `pending`.
|
|
74
81
|
2. Uncommitted files: `git -C <worktree> status --porcelain`.
|
|
75
82
|
3. Proposed task statuses: `complete` iff at least one matching commit, else `pending`.
|
|
76
83
|
4. Proposed stage: `implement` if any task is `pending`, else `verify`.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Spec seed (gauntlet-resume supplementary)
|
|
2
|
+
|
|
3
|
+
Consumed only by `SKILL.md` in this directory, for a one-token `.md` argument classified
|
|
4
|
+
as a spec seed. `<seed>` is its `realpath`; `<rel>` is `<seed>` relative to `<primary>`.
|
|
5
|
+
Entry check 1 (idle session) runs first. Then, in order; every stop names the path.
|
|
6
|
+
|
|
7
|
+
1. **Primary session.** `git rev-parse --git-dir --git-common-dir` in the session cwd
|
|
8
|
+
prints two paths; their `realpath`s must agree. Otherwise stop:
|
|
9
|
+
`seed from the primary checkout`.
|
|
10
|
+
2. **Tracked.** `git -C <primary> ls-files --error-unmatch <rel>` exits 0; otherwise
|
|
11
|
+
stop: `not tracked: <seed> - commit it first`. Line 1 of `<seed>` equal to
|
|
12
|
+
`# CONTEXT DRAFT - NOT A SPEC - fully replaced at spec-writing` -> stop:
|
|
13
|
+
`context draft, not a spec: <seed> - finish brainstorming`.
|
|
14
|
+
3. **Not shipped.** Read `<primary>/<telemetry.dir>/<rel with .md -> .yaml>`
|
|
15
|
+
(`piGauntlet.telemetry.dir`, default `.pi/gauntlet/telemetry`). A `shipped_at:` or
|
|
16
|
+
`abandoned_at:` line carrying a value -> stop:
|
|
17
|
+
`spec already shipped at <ts> - write a superseding spec`. No record, or
|
|
18
|
+
`in_progress`: continue; the extension folds this run into the record on
|
|
19
|
+
`plan_check` pass.
|
|
20
|
+
4. **Name.** `<name>` = basename of `<rel>` minus `.md`, minus a leading `YYYY-MM-DD-`:
|
|
21
|
+
`2026-09-17-gh-31-gauntlet-resume.md` -> `gh-31-gauntlet-resume`. Same shape as
|
|
22
|
+
brainstorming's Filename Convention slug; wrappers receive it as `<name>`.
|
|
23
|
+
5. **Reuse or create.** `git -C <primary> worktree list --porcelain`. A block whose
|
|
24
|
+
`branch` line is `refs/heads/<name>` or ends in `/<name>` -> `<full-path>` is that
|
|
25
|
+
block's `worktree` line; skip creation (layout-agnostic: wrapper sibling dirs,
|
|
26
|
+
wrapper branch prefixes such as `<user>/<name>`, and `.worktrees/` alike); more than
|
|
27
|
+
one match -> the human picks. No block -> invoke `/skill:using-git-worktrees` with branch `<name>` and carry its
|
|
28
|
+
`Worktree ready at <full-path>`; its Step 1a applies project `## using-git-worktrees`
|
|
29
|
+
overrides, its Step 3 runs the clean-base check and dirty ask. Wrapper arguments
|
|
30
|
+
beyond `<name>` are that skill's ask, never inferred here. Any stop it raises is this
|
|
31
|
+
route's stop, verbatim. Never invent a second name.
|
|
32
|
+
6. **Same repository.** Entry check 3 against `<full-path>`.
|
|
33
|
+
7. **Pinned copy.** `<full-path>/<rel>` exists, is readable, and its line 1 is not the
|
|
34
|
+
context-draft marker; otherwise stop naming that path. Never copy `<seed>` in.
|
|
35
|
+
8. **Continue** in `reconstruction.md` with the spec pinned at `<full-path>/<rel>`,
|
|
36
|
+
skipping Candidates: `<full-path>/<sibling plans dir>/<basename of rel>` exists ->
|
|
37
|
+
"Spec with plan"; otherwise "Spec without plan". Prompts say "no brief context
|
|
38
|
+
available".
|
|
39
|
+
|
|
40
|
+
The seed route writes no spec copy, rename, or marker commit: the spec stays where main
|
|
41
|
+
tracks it, amends ride the squash as ordinary diffs, and `finishing-a-development-branch`
|
|
42
|
+
strips only the plan. `gauntlet-telemetry-salvage` prints `no spec on branch` for an
|
|
43
|
+
unamended seed throughout the flow (it selects specs from `git diff --name-only
|
|
44
|
+
<base>...HEAD`, which never lists a file tracked at base), so the extension's live ship
|
|
45
|
+
stamp is the only writer of `shipped_at`; the record still binds on `plan_check` pass.
|
|
46
|
+
Before a plan exists beside the spec, re-pass the seed to resume; after, plain `<worktree>` resume and
|
|
47
|
+
`gauntlet-handoff` -> `gauntlet-resume <brief>` restore the flow.
|