@gobing-ai/spur 0.3.96 → 0.3.98
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/.claude-plugin/marketplace.json +1 -1
- package/config/rules/strict/runtime-boundaries.yaml +1 -0
- package/config/templates/AGENTS.md +3 -3
- package/config/workflows/wrapup-pipeline.yaml +2 -1
- package/package.json +2 -2
- package/plugins/sp/README.md +15 -9
- package/plugins/sp/commands/dev-job-dump.md +29 -0
- package/plugins/sp/commands/dev-job-resume.md +29 -0
- package/plugins/sp/lib/inline-run.generated.mjs +34 -18
- package/plugins/sp/lib/quality-gate.generated.mjs +12 -5
- package/plugins/sp/lib/residual-scan.generated.d.mts +1 -0
- package/plugins/sp/lib/residual-scan.generated.mjs +16 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +5 -5
- package/plugins/sp/scripts/feature-verification-steps.mjs +14 -1
- package/plugins/sp/scripts/feature-verification-steps.ts +14 -1
- package/plugins/sp/scripts/inline-run-setup.mjs +4 -2
- package/plugins/sp/scripts/inline-run-setup.ts +12 -12
- package/plugins/sp/scripts/quality-gate.mjs +13 -6
- package/plugins/sp/scripts/quality-gate.ts +1 -1
- package/plugins/sp/scripts/residual-scan.mjs +64 -38
- package/plugins/sp/scripts/residual-scan.ts +39 -34
- package/plugins/sp/scripts/wrapup-steps.mjs +64 -3
- package/plugins/sp/scripts/wrapup-steps.ts +122 -3
- package/plugins/sp/skills/code-implementation/SKILL.md +1 -1
- package/plugins/sp/skills/conflict-finding/SKILL.md +1 -1
- package/plugins/sp/skills/conflict-finding/references/authority-resolution.md +5 -3
- package/plugins/sp/skills/conflict-finding/references/remediation-routing.md +9 -8
- package/plugins/sp/skills/doc-evolve/SKILL.md +4 -3
- package/plugins/sp/skills/source-driven-development/SKILL.md +11 -0
- package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +16 -9
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +7 -4
- package/plugins/sp/skills/spur-cli/references/workflows.md +17 -14
- package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +3 -1
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +94 -17
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -2
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +8 -6
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +3 -3
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +16 -8
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +46 -12
- package/spur.js +5241 -3762
- package/web/_astro/BoardApp.CYbe-OTb.js +322 -0
- package/web/_astro/{BoardApp.BIjMatT1.js → BoardApp.Dflq5a8x.js} +1 -1
- package/web/_astro/{TaskDetail.BZM3EAFx.js → TaskDetail.CK7oXddP.js} +1 -1
- package/web/_astro/{arc.HkRiZnoI.js → arc.BIqkDATc.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.BDdK-tgZ.js → architectureDiagram-3BPJPVTR.D0B3SvWv.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.CZ9kOBxx.js → blockDiagram-GPEHLZMM.C2YyKQmL.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.DXK9qeRD.js → c4Diagram-AAUBKEIU.DmtTYrt_.js} +1 -1
- package/web/_astro/channel.JuKVyuhZ.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.BTD2WeX5.js → chunk-2J33WTMH.HsRXbh7l.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.Ci6Qbcvk.js → chunk-4BX2VUAB.obE_P-R3.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.yl3zsj7p.js → chunk-55IACEB6.CjWTF5mz.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.ClXZsfyR.js → chunk-727SXJPM.DMo799Ax.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.BmKWZBcP.js → chunk-AQP2D5EJ.-cE6JOKZ.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.By30fcb7.js → chunk-FMBD7UC4.D6Rw6HIk.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.24NmrD-k.js → chunk-ND2GUHAM.d5rBD73Z.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.BN4sKdcS.js → chunk-QZHKN3VN.r3ox40Q3.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.CJpoMPb5.js → classDiagram-4FO5ZUOK.CGGbvjjJ.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.CJpoMPb5.js → classDiagram-v2-Q7XG4LA2.CGGbvjjJ.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.BraxQ2Nt.js → cose-bilkent-S5V4N54A.CmKtPd4l.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.gzoU73oL.js → cynefin-OW5HDTMX.QNg5GXs8.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.wyDfWySU.js → dagre-BM42HDAG.B1SabsjC.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.h2_EbMxV.js → diagram-2AECGRRQ.RtDbNj89.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Db6dcs89.js → diagram-5GNKFQAL.IzZpuM-Y.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.NVwzxu_U.js → diagram-KO2AKTUF.DPTF_fgv.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.B-eNgDQk.js → diagram-LMA3HP47.CCyza39P.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.Bsa8ZRbJ.js → diagram-OG6HWLK6.BXAi8zcZ.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BospRE5Q.js → erDiagram-TEJ5UH35.DUDX7_MR.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.DMzvHwAA.js → flowDiagram-I6XJVG4X.C63QTh3N.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.Dmdxgd-M.js → ganttDiagram-6RSMTGT7.CnlZJSwG.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.CaqdO0rL.js → gitGraphDiagram-PVQCEYII.CTqIrOPC.js} +1 -1
- package/web/_astro/index.CbNz17Sx.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.DDVD9Wn7.js → infoDiagram-5YYISTIA.BYMiDFh9.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.EKyCUFsL.js → ishikawaDiagram-YF4QCWOH.CRiQmI-z.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.By2-RkYB.js → journeyDiagram-JHISSGLW.YQgWBsEU.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.ar-WmlyR.js → kanban-definition-UN3LZRKU.1ECnrrK1.js} +1 -1
- package/web/_astro/{linear.BnzMBgo_.js → linear.DzVA71yT.js} +1 -1
- package/web/_astro/{mermaid.core.DSqeFu2Y.js → mermaid.core.BK7P2Sr_.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.1XcF8Wh2.js → mindmap-definition-RKZ34NQL.BvXyWZK7.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.DnItHOdK.js → pieDiagram-4H26LBE5.BiXk1TW3.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.BQQyrnBt.js → quadrantDiagram-W4KKPZXB.krvBH8lh.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.Dmzxun82.js → requirementDiagram-4Y6WPE33.ih1gL25c.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.BBIeRKYB.js → sankeyDiagram-5OEKKPKP.CpUxkv4u.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.CUNVdBBf.js → sequenceDiagram-3UESZ5HK.clAfeN7y.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.DlFf2sJm.js → stateDiagram-AJRCARHV.DpXWb8-m.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.DXR7I1H5.js → stateDiagram-v2-BHNVJYJU.ClZb9GIH.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.BcO-GyX2.js → timeline-definition-PNZ67QCA.BLcX5dh7.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.ChCECmmW.js → vennDiagram-CIIHVFJN.oGgpKMpx.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.CRaT12mD.js → wardleyDiagram-YWT4CUSO.BPHtMtt-.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.B3lsHVpj.js → xychartDiagram-2RQKCTM6.BNZOPYSk.js} +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.GvjIe9Z6.js +0 -191
- package/web/_astro/channel.DlhX2MEt.js +0 -1
- package/web/_astro/index.EoZlzLK-.css +0 -1
|
@@ -70,9 +70,12 @@ frontmatter scalar.
|
|
|
70
70
|
`testing→done` `check` gates above still run; the CLI evaluates them inline when the FSM guard
|
|
71
71
|
does not. `--force-done` waives the verify **verdict** only, never the section matrix.
|
|
72
72
|
- **Section** (`--section` **requires** `--from-file`): writes the named section body from the file.
|
|
73
|
-
Most sections replace wholesale.
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
Most sections replace wholesale. `--append` extends instead: existing body + one blank line + the
|
|
74
|
+
file's body (task 1057; empty/missing section is created; still requires `--section`). Exception:
|
|
75
|
+
`--section "Q&A"` APPENDS a timestamped `#### Q&A entry — <ISO>` block; start the body with
|
|
76
|
+
`<!-- qa:replace -->` to replace the section wholesale (explicit `--append` on `Q&A` uses the
|
|
77
|
+
generic append, marker still wins). No inline-body flag. Section names (case-sensitive):
|
|
78
|
+
`Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Testing`, `Review`, `References`, `History`, `Notes`.
|
|
76
79
|
- **Frontmatter** (`--feature <id>`, `--priority <p>`): sets the scalar frontmatter field on an
|
|
77
80
|
existing task — the only post-create path, allow-listed to `feature_id` / `parent_wbs` / `priority`.
|
|
78
81
|
- **Estimate** (`--estimate-hours <n>`): sets the `estimate_hours` frontmatter field (positive number) —
|
|
@@ -113,7 +116,7 @@ Flags: `--folder <path>`, `--json`. Exit codes: `0` success, `1` error, `2` usag
|
|
|
113
116
|
|
|
114
117
|
## `sections <wbs> <op> [name]`
|
|
115
118
|
|
|
116
|
-
CLI-safe, matrix-enforced task section mutation. Section names are validated against canonical sections (`Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `References`, `History`, `Notes`). Universal sections (`History`, `References`, `Notes`) are always allowed; `Root Cause` is carried by the `issue` template variant. `Q&A` on `update --section` appends rather than replacing (see the Section bullet above); `<!-- qa:replace -->` forces a wholesale replace.
|
|
119
|
+
CLI-safe, matrix-enforced task section mutation. Section names are validated against canonical sections (`Background`, `Requirements`, `Acceptance Criteria`, `Q&A`, `Design`, `Plan`, `Solution`, `Root Cause`, `Testing`, `Review`, `References`, `History`, `Notes`). Universal sections (`History`, `References`, `Notes`) are always allowed; `Root Cause` is carried by the `issue` template variant. `Q&A` on `update --section` appends rather than replacing (see the Section bullet above); `<!-- qa:replace -->` forces a wholesale replace. `--append` is the generic extend-after-existing path (task 1057).
|
|
117
120
|
|
|
118
121
|
| Op | Usage | Description |
|
|
119
122
|
| --- | --- | --- |
|
|
@@ -204,7 +204,7 @@ spur workflow run ./workflows/approval.yaml --silent # errors only
|
|
|
204
204
|
spur workflow run ./workflows/approval.yaml --verbose # transitions + correlation diagnostics
|
|
205
205
|
spur workflow run ./workflows/approval.yaml --detail minimal # tersest human output
|
|
206
206
|
spur workflow run ./workflows/approval.yaml --trace-file # persist redacted JSONL trace
|
|
207
|
-
spur workflow run ./workflows/approval.yaml --no-log # opt out of the run record .spur/
|
|
207
|
+
spur workflow run ./workflows/approval.yaml --no-log # opt out of the run record .spur/memory/runs/<RUNID>.md + .state.json
|
|
208
208
|
spur workflow run ./workflows/approval.yaml --steer # interactive steering on stdin
|
|
209
209
|
```
|
|
210
210
|
|
|
@@ -214,7 +214,7 @@ spur workflow run ./workflows/approval.yaml --steer # interactive
|
|
|
214
214
|
per-step headers), `full` (transitions + correlation). `--verbose` is shorthand for `--detail full`.
|
|
215
215
|
- **`--trace-file`** appends a redacted, schema-versioned JSONL trace under `.spur/workflow/`
|
|
216
216
|
for post-run analysis - independent of human/JSON output.
|
|
217
|
-
- **`--no-log`** opts out of writing the two-file run record (`.spur/
|
|
217
|
+
- **`--no-log`** opts out of writing the two-file run record (`.spur/memory/runs/<RUNID>.md` + `.state.json`).
|
|
218
218
|
By default the record is written **and retained** after the run ends; this flag skips it entirely
|
|
219
219
|
(propagates to the `--async` detached worker). No `--keep-log` / delete-by-default exists.
|
|
220
220
|
- **`--steer`** is synchronous and in-process: it cannot combine with `--json` or `--async` (exit `2`).
|
|
@@ -285,7 +285,7 @@ not advertise `--json-envelope` because its JSON projection is a kept-raw docume
|
|
|
285
285
|
| `--verbose` | Include transitions and correlation diagnostics in human progress (implies `--detail full`). |
|
|
286
286
|
| `--detail <level>` | Human detail level: `minimal`, `invocation` (default), or `full`. |
|
|
287
287
|
| `--trace-file` | Append a redacted schema-versioned JSONL trace under `.spur/workflow/`. |
|
|
288
|
-
| `--no-log` | Opt out of writing the two-file run record `.spur/
|
|
288
|
+
| `--no-log` | Opt out of writing the two-file run record `.spur/memory/runs/<RUNID>.md` + `.state.json` (retained by default; propagates to `--async` workers). |
|
|
289
289
|
| `--steer` | Accept in-process steering commands on stdin at declared action boundaries (sync only; incompatible with `--json`/`--async`). |
|
|
290
290
|
|
|
291
291
|
`validate` and `run` exit non-zero on failure (`run` exits non-zero when the final status is not
|
|
@@ -302,7 +302,7 @@ Follow a live run to terminal (human streaming mode):
|
|
|
302
302
|
```bash
|
|
303
303
|
spur workflow trace <run-id> --follow # stream until terminal (default 1000ms poll)
|
|
304
304
|
spur workflow trace <run-id> --follow --poll 500 # poll every 500ms
|
|
305
|
-
spur workflow trace <run-id> --follow --output # stream .spur/
|
|
305
|
+
spur workflow trace <run-id> --follow --output # stream .spur/memory/runs/<RUNID>.md instead of the DB timeline
|
|
306
306
|
spur workflow trace <run-id> --follow --timeout 600000 # bound the watch; timeout → one checkpoint, run continues, exit 1
|
|
307
307
|
```
|
|
308
308
|
|
|
@@ -316,7 +316,7 @@ spur workflow trace <run-id> --follow --timeout 600000 # bound the watch; timeou
|
|
|
316
316
|
status and exits `1`. A watch timeout never cancels or relaunches the run; resume by re-running the same
|
|
317
317
|
follow command.
|
|
318
318
|
- **`--output`** swaps the follow source from the structured DB timeline to the human run record
|
|
319
|
-
(`.spur/
|
|
319
|
+
(`.spur/memory/runs/<RUNID>.md`, tail -f equivalent), streaming new lines as they land and exiting at
|
|
320
320
|
terminal status. A pre-0925 run with only a legacy `<RUNID>.log` is followed in place (read-only
|
|
321
321
|
fallback). It requires `--follow` and a `run-id`, is a human stream (rejects `--json`), and is
|
|
322
322
|
a **distinct source** — it never interleaves with the DB timeline. If no record file appears (e.g. the
|
|
@@ -360,15 +360,18 @@ redirecting `agent.run` stages (ADR-047).
|
|
|
360
360
|
|
|
361
361
|
- **Stale-run finalization** (existing): bulk-finalizes orphaned `running`/`pending` runs as `failed`.
|
|
362
362
|
`--older-than <minutes>` (default 30) and `--force` (all non-terminal regardless of age) apply here only.
|
|
363
|
-
- **Run-log reclamation** (0429): removes
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
363
|
+
- **Run-log reclamation** (0429): removes expired `.log` files from `.spur/memory/runs/`
|
|
364
|
+
and legacy `.spur/run/`, using `workflow.logRetentionDays` (default 30 days). Non-terminal
|
|
365
|
+
runs, including paused/interrupted runs, are protected; ownership lookup failures preserve logs.
|
|
366
|
+
The two-file record (`.md` + `.state.json`) and partial handoffs are retained.
|
|
367
|
+
- **Checkpoint reclamation**: removes expired terminal checkpoints only when confinement,
|
|
368
|
+
metadata and run-ownership guards pass. Recoverable runs remain protected.
|
|
369
|
+
- **Migration** (E71): verified lasting scratch data is preserved and references redirected before
|
|
370
|
+
reclamation. Unsettled imports, live dependencies, malformed files and conflicts retain their sources.
|
|
371
|
+
- **`--logs`** scopes to log reclamation and its migration (skips stale-run finalization and
|
|
372
|
+
checkpoint reclamation). `--dry-run` reports without copying or deleting. `--json` returns
|
|
373
|
+
`{ olderThanMinutes, dryRun, cleaned, logs, checkpoints, migration }`; with `--logs`, it returns
|
|
374
|
+
`{ retentionDays, dryRun, reclaimed, failures, migration }`.
|
|
372
375
|
|
|
373
376
|
## Behavior
|
|
374
377
|
|
|
@@ -206,6 +206,8 @@ section adds what that table has no room for: per-file content summaries and ite
|
|
|
206
206
|
step (glossary, config companions).** Read Step routing to find "which file for step X"; read below
|
|
207
207
|
for "what's actually in file Y" or for resources that sit outside the step sequence.
|
|
208
208
|
|
|
209
|
+
- Job transfer: [dump/resume](references/dev-operations.md#11a-job-dump).
|
|
210
|
+
|
|
209
211
|
- [references/glossary.md](references/glossary.md) — sp's own vocabulary: spine, competency, facade,
|
|
210
212
|
corpus, gate, verdict, noun/verb, half, HITL, WBS, section-write contract — canonical term +
|
|
211
213
|
Avoid list. Owns term definitions only; `cross-cutting.md` owns the process rules that use them.
|
|
@@ -135,7 +135,9 @@ workflow run` and never redirect silently to `agent.default`. Interactive **omit
|
|
|
135
135
|
**host-controlled and non-subprocess**, but no longer guarantees host-context execution for every
|
|
136
136
|
model stage (task 0508): an eligible `agent.run` stage — pure-slash input, non-interactive state,
|
|
137
137
|
native subagent with shared-worktree read/write/shell capability, and a task above the
|
|
138
|
-
`estimate_hours` dispatch floor
|
|
138
|
+
`estimate_hours` dispatch floor — a small, non-sensitive triage diffstat
|
|
139
|
+
(`.spur/run/<wbs>-diffstat.json`, verify only) keeps that stage host-inline (2026-09-15
|
|
140
|
+
subagent-dispatch evaluation; the floor and the
|
|
139
141
|
resume-over-re-dispatch rule for worker-role continuation stages are owned by
|
|
140
142
|
[inline-pipeline-driver.md](inline-pipeline-driver.md)) — dispatches **once** to that
|
|
141
143
|
native subagent and joins before the driver continues; any pre-dispatch eligibility failure falls
|
|
@@ -15,7 +15,7 @@ table is the index; the per-operation sections below are the detail.
|
|
|
15
15
|
|
|
16
16
|
| Pattern | Meaning | Commands |
|
|
17
17
|
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
18
|
-
| `Skill()` | Delegates to a backing skill via `Skill(skill="<skill>", args="<op> $ARGUMENTS")`. The skill owns the procedure; the command is a thin entry point. | implement, unit, review, verify, verifyall, run, refine, refineall, plan, brainstorm, runall, parallel, wrap, wrapall, idea |
|
|
18
|
+
| `Skill()` | Delegates to a backing skill via `Skill(skill="<skill>", args="<op> $ARGUMENTS")`. The skill owns the procedure; the command is a thin entry point. | implement, unit, review, verify, verifyall, run, refine, refineall, plan, brainstorm, runall, parallel, wrap, wrapall, idea, job-dump, job-resume |
|
|
19
19
|
| `inline` | The procedure is defined directly in the command file. No `Skill()` delegation — the command carries its own steps. | changelog, gitmsg, fixall, handover |
|
|
20
20
|
|
|
21
21
|
The `Skill()` commands back onto six skills: `sp:spur-dev` (planning + execution workflow + batch),
|
|
@@ -39,10 +39,11 @@ each would be scope creep for one-liner procedures.
|
|
|
39
39
|
> `plugins/sp/skills/history-anatomy/SKILL.md`.
|
|
40
40
|
|
|
41
41
|
> **`dev-review-session`** is not in this table. It is a thin `Skill()` wrapper over
|
|
42
|
-
> **`sp:session-review`** for an immediate, inline
|
|
43
|
-
>
|
|
44
|
-
>
|
|
45
|
-
>
|
|
42
|
+
> **`sp:session-review`** for an immediate, inline review of the active conversation. Report-only
|
|
43
|
+
> is the default; `--triage` applies pure-doc / one-to-two-line fixes and files remaining actionable
|
|
44
|
+
> findings as implement-ready tasks through the task CLI. It launches no workflow or agent and
|
|
45
|
+
> imports no history. Use it before the active session ends; use history-anatomy for ended sessions,
|
|
46
|
+
> cross-agent windows, trends, or quantitative forensics.
|
|
46
47
|
|
|
47
48
|
> **`dev-find-conflict`** is not in this table. It is a thin `Skill()` wrapper over
|
|
48
49
|
> **`sp:conflict-finding`** (authority-aware four-pillar semantic audit → optional confirmed,
|
|
@@ -80,6 +81,8 @@ each would be scope creep for one-liner procedures.
|
|
|
80
81
|
| 9 | gitmsg | `dev-gitmsg` | `inline` | bounded diff capture → concern grouping → conventional commit | `[--commit] [--squash] [--all] [--scope <path>]` |
|
|
81
82
|
| 10 | fixall | `dev-fixall` | `inline` | lint + test fix loop | `[<validation-command>] [--max-retry <n>] [--scope <path>] [--gate-log <path>] [--findings <anchors>]` |
|
|
82
83
|
| 11 | handover | `dev-handover` | `inline` | structured doc generation | `"<blocker description>"` |
|
|
84
|
+
| 11a | job-dump | `dev-job-dump` | `Skill()` | `sp:spur-dev` (`job-dump`) | `--file <path>` |
|
|
85
|
+
| 11b | job-resume | `dev-job-resume` | `Skill()` | `sp:spur-dev` (`job-resume`) | `--file <path>` |
|
|
83
86
|
| 12 | brainstorm | `dev-brainstorm` | `Skill()` | `sp:brainstorm` (`dev-brainstorm`) | `<topic> [--depth <basic\|detailed\|comprehensive>] [--options <n>] [--agent <inline\|auto\|name>] [--skip-discovery] [--wayfind] [--task [<feature-id>]] [--feature [<parent-id>]] [--next]` |
|
|
84
87
|
| 13 | runall | `dev-runall` | `Skill()` → agent | `sp:spur-dev` (`runall`) → `sp:super-planner` | `--tasks <selector> [--feature <id>] [--mode <sequential\|parallel>] [--keep-going] [--auto] [--agent <inline\|auto\|name>] [--json] [--wrap] [--next] [--continue] [--worktree [<name>]]` |
|
|
85
88
|
| 13a | parallel | `dev-parallel` | `Skill()` | `sp:parallel-execution` | `--tasks <selector> [--feature <id>] [--mode <fan-out\|review-panel\|investigation>] [--agent <inline\|auto\|name>] [--json]` |
|
|
@@ -337,6 +340,72 @@ must not be changed without updating the backing skill.
|
|
|
337
340
|
- **Behavior:** Read the affected doc → apply the constitution's edit rules (single-source-of-truth, cross-reference updates, same-commit sync triggers) → write via the correct tool.
|
|
338
341
|
- **Delegation:** `Skill(skill="sp:doc-evolve", args="$ARGUMENTS")` (no thin command wrapper)
|
|
339
342
|
|
|
343
|
+
### 11a. job-dump
|
|
344
|
+
|
|
345
|
+
- **Purpose:** Transfer any unfinished job to another session, agent, or operator through a Markdown snapshot; a blocker or task/feature ID is optional.
|
|
346
|
+
- **Inputs:** Required `--file <path>`; shared path semantics live in [flag-glossary.md](flag-glossary.md).
|
|
347
|
+
- **Backing:** `sp:spur-dev`, in the current session. Use the [shared handoff template](#job-handoff-template).
|
|
348
|
+
- **Behavior:**
|
|
349
|
+
1. Parse arguments, preserving quoted paths with spaces. Reject a missing/empty path, repeated `--file`, unknown flags, or extra positional arguments with usage. Resolve the absolute path before changing directories. Reject a directory target; create missing parent directories. Respect CLI-gated corpus writes: task/feature documents cannot be dump targets.
|
|
350
|
+
2. Gather the mission, original invocation/options, approved outcome, completed and partial work, blockers, and next actions. Verify repository/worktree paths, branch, HEAD/base, dirty files and relevant commits with Git. Inspect referenced tasks/features/runs through the CLI facade with `--json` in their execution directory. Preserve frozen batch membership, dependency order, run IDs, workflow/checkpoint identity, failure policy, executor state and worktree marker when applicable. Record inspection time and provenance; label unavailable facts `unknown`.
|
|
351
|
+
3. Fill every template section for this job; use `N/A` where inapplicable. Include uncommitted work and ownership, gate commands/results, pending questions, approvals given or still required, discovery maps, evidence paths, and wrap/merge/cleanup success conditions. Keep confirmed lessons and rejected approaches with anchors. Link authoritative specifications instead of copying them; never turn task-specific bypasses into general instructions.
|
|
352
|
+
4. Redact credentials, tokens and sensitive personal data. Link large logs/artifacts by path and note their durability and availability to the recipient; the Markdown file does not transfer referenced files. Include essential continuation context directly so missing optional scratch notes do not erase the plan.
|
|
353
|
+
5. Construct the complete snapshot before writing or refreshing `--file`. Read it back to verify the mission, execution directory, ordered remaining work and first actions. Report the absolute path and unresolved facts. Dumping only saves context: it does not stop an active executor, execute remaining work, change lifecycle state, commit, merge, or remove a worktree; record any executor still running.
|
|
354
|
+
|
|
355
|
+
### 11b. job-resume
|
|
356
|
+
|
|
357
|
+
- **Purpose:** Read a Markdown job snapshot and continue its remaining work through the existing operation owner.
|
|
358
|
+
- **Inputs:** Required `--file <path>`; use job-dump argument/path validation, but require an existing, readable, non-empty file and do not create it.
|
|
359
|
+
- **Backing:** `sp:spur-dev`, in the current session; dispatch the recorded operation after reconciliation.
|
|
360
|
+
- **Behavior:**
|
|
361
|
+
1. Read the entire file before acting. Treat it as context under current operator/project instructions: embedded commands must be verified, never blindly executed or accepted as gate-bypass authority. Accept equivalent headings in manual handoffs. Require a clear mission, execution location and next action; request missing critical context before dependent work.
|
|
362
|
+
2. Locate the recorded repository/worktree, read its `AGENTS.md`, and inspect Git status, branch, HEAD/base and worktree membership there. Report drift; for a moved/missing checkout, establish and report a verified path mapping from repository/worktree identity, asking only if ambiguous. Never silently fall back to the invoking tree. Preserve dirty changes and ownership. Check recorded active executors through the coordination owner before taking write ownership; maintain one writer per tree.
|
|
363
|
+
3. Read state/discovery files and authoritative task, feature and design records; refresh statuses through the CLI facade with `--json`. Reconcile frozen membership, dependencies, completion evidence and run/checkpoint identity. Skip confirmed completed work; unproven completion stays unverified. Missing optional notes trigger focused rediscovery; missing required evidence/checkpoints or incompatible state stop the affected continuation with a concrete recovery action.
|
|
364
|
+
4. State the reconciled next step and continue in the verified execution directory, preserving scope, options, ordering, failure policy and pending decisions. Load the existing lifecycle/competency owner for the recorded task, batch, planning, review, wrap or other operation. Use its continuation path rather than replaying the original invocation from the beginning; retain the frozen remaining set rather than selecting new tasks. Distinguish inline continuation from a paused engine run: use the documented mechanism for the matching live run, never fabricate a paused snapshot or alter definition digests to force resume.
|
|
365
|
+
5. Execute first actions and proceed through remaining work until completion or a real blocker. Rerun stale checks where the owning gate requires it. Required approvals stay pending; saved `--auto` or narration does not grant new irreversible actions. Apply the existing wrap/worktree finalization contract only on its full success conditions; retain work and evidence on partial success or failure.
|
|
366
|
+
6. Report resumed work, results and blockers. When stopping again, refresh the same file through job-dump, preserving the original mission, membership and references while updating observed state and next actions.
|
|
367
|
+
|
|
368
|
+
#### Job handoff template
|
|
369
|
+
|
|
370
|
+
Fill this structure for the actual job. Replace placeholders; omit another job's IDs, paths,
|
|
371
|
+
commits, implementation details, quotas, parser workarounds and lifecycle bypasses.
|
|
372
|
+
|
|
373
|
+
```markdown
|
|
374
|
+
# Resume job: <short mission>
|
|
375
|
+
|
|
376
|
+
## Mission
|
|
377
|
+
<Goal, expected outcome, original invocation/options and approved scope.>
|
|
378
|
+
|
|
379
|
+
## Environment (verified <timestamp and timezone>)
|
|
380
|
+
- Execution directory / repository / invoking directory: <absolute paths and their roles>
|
|
381
|
+
- Branch / base / HEAD / working-tree changes: <observed state and ownership>
|
|
382
|
+
- Runtime / CLI / executor: <verified invocation and availability>
|
|
383
|
+
- Run / workflow / checkpoint / worktree marker: <identity and state, or N/A>
|
|
384
|
+
- State, discovery maps and evidence: <paths, retention and availability>
|
|
385
|
+
|
|
386
|
+
## Completed so far
|
|
387
|
+
<Completed items, commits and verification receipts; separate partial/uncommitted work.>
|
|
388
|
+
|
|
389
|
+
## Remaining work, in order
|
|
390
|
+
1. <Next item, dependency, current stage, authoritative specification and required gate.>
|
|
391
|
+
2. <Subsequent items, then wrap/finalization and its success conditions.>
|
|
392
|
+
|
|
393
|
+
## Execution mode
|
|
394
|
+
<Inline/delegated mode, one-writer ownership, frozen membership/order, failure policy,
|
|
395
|
+
gate commands, pending questions and approval requirements.>
|
|
396
|
+
|
|
397
|
+
## Lessons and rejected approaches
|
|
398
|
+
<Verified pitfalls, discoveries and approaches ruled out, with evidence.>
|
|
399
|
+
|
|
400
|
+
## Constraints and authoritative references
|
|
401
|
+
<Frozen decisions, boundaries, required reading and evidence paths; link specifications.>
|
|
402
|
+
|
|
403
|
+
## First actions for the new session
|
|
404
|
+
1. <Verify the execution directory and current repository/run state.>
|
|
405
|
+
2. <Read state/discovery files and relevant authoritative records.>
|
|
406
|
+
3. <Resume the next unfinished step through its existing owner.>
|
|
407
|
+
```
|
|
408
|
+
|
|
340
409
|
### 12. brainstorm
|
|
341
410
|
|
|
342
411
|
- **Purpose:** Interactive solution design — heuristic discovery interview (grilling) followed by structured ideation with trade-offs and confidence scoring.
|
|
@@ -461,6 +530,12 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
461
530
|
- `keepachangelog` (default): `## [<version>] - <date>` header, then category headings per the keepachangelog convention — `### Added` / `### Fixed` / `### Changed` / `### Removed` / `### Other` — mapped from conventional-commit types.
|
|
462
531
|
- `simple`: flat bulleted list grouped by type heading (`### feat`, `### fix`, …).
|
|
463
532
|
6. Print the changelog to stdout. If the operator wants it in `CHANGELOG.md`, they redirect or paste.
|
|
533
|
+
7. Verify the emitted section against git and close with one line: `Verification: HIGH|MEDIUM|LOW — <first failing check and deviation, or 'all checks passed'>`.
|
|
534
|
+
- **Coverage** — bullet count equals the commit count in `<since>..<until>`, and every short hash appears exactly once.
|
|
535
|
+
- **Mapping** — per-category bullet counts match the conventional-type counts (`feat`→`Added`, `fix`→`Fixed`, other recognized types→`Changed`, unrecognized→`Other`).
|
|
536
|
+
- **Header** — `[<version>] - <date>` matches the resolved `--version` (or detected tag) and the header date.
|
|
537
|
+
- **Citations** — a bullet that asserts API/library behavior or a version/dependency claim beyond its commit summary carries a source citation: an official docs URL, or a local `path:line` verified against the installed manifest/lockfile (`package.json`, lockfile, or the cited file). A commit hash is provenance for what shipped, not a citation for what the API/library does; an uncited claim is flagged inline on the bullet (`(uncited: <claim>)`) rather than silently dropped.
|
|
538
|
+
- **HIGH** — all checks pass with every API/library claim cited. **MEDIUM** — coverage intact but mapping or header deviates, or at least one API/library claim lacks a source citation. **LOW** — coverage broken (missing/duplicate hashes), the range cannot be reconciled against git, or a citation fails verification (dead URL, or a `path:line` that does not support the claim).
|
|
464
539
|
- **Invariants:** Never mutates `CHANGELOG.md` directly — the command surface is stdout-only; writing it to a file (e.g. appending to `CHANGELOG.md`) is the operator's redirect choice, never the command's.
|
|
465
540
|
|
|
466
541
|
### 9. gitmsg
|
|
@@ -550,25 +625,27 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
550
625
|
- **Inputs:** `--scope <path>` (default: entire working tree) — limits fixes to a file or directory. `--gate-log <path>` (R3, task 0482) — before fixing, read this captured validation-run log and start at the `file:line` anchors its findings name, rather than re-deriving the failure from a fresh gate run. `--findings <anchors>` (R3, task 0482) — space-separated `file:line` anchors already extracted from that log by the `test` hop; when present these ARE the failing set, so fix them in order and do not run the gate to discover what broke.
|
|
551
626
|
- **Backing:** `inline` — lint + test fix loop.
|
|
552
627
|
- **Behavior:** 0. **Start at the anchors, never at a discovery run.** If `--findings <anchors>` is given, that space-separated `file:line` list IS the failing set — open those locations first, in order, and fix them; do not run the gate to find out what broke. If only `--gate-log <path>` is given, read that log first and identify the failing findings (lint/test errors with their `file:line` anchors) before running the loop — the captured log is the authoritative source. Either way the first action of this hop is a read, not a gate run (R3, task 0482).
|
|
553
|
-
1.
|
|
554
|
-
2. Run `bun run lint`
|
|
555
|
-
3. **Surface-change sweep (before any fix).** If the failing set is a **surface/parity** change — CLI noun/verb/flag surface, reference-file structure, or a renamed/moved symbol — do one upfront `rg` sweep across ALL test dirs + docs for stale references to the changed symbols (e.g. `rg -l "<old-noun>|<old-file>.md|Tier C" apps/*/tests plugins/sp/tests plugins/sp/skills docs`), and fix every pinned test/docs file in that sweep. A surface change is pinned in **multiple independent test files** (each with its own hardcoded noun→reference map); discovering them one-by-one via full-suite probes is the dominant waste — each wave costs a suite run and a fresh edit loop (task 0436 R2 lesson). One sweep produces the complete edit set upfront.
|
|
628
|
+
1. Inspect the project's formatter command, then settle formatter-only diffs. Without `--scope`, use the project formatter (here `bun run format`). With `--scope`, use a formatter invocation whose only path operands are inside the selected scope — for Biome, `bunx biome check --write "$SCOPE"`. Never append a path to a script already containing `.`: `biome check . --write <path>` still writes across the repository. Preserve quoted paths and apply the same scope to every later formatting pass. If no scoped formatter is available, report that limitation and leave out-of-scope files untouched. Here `bun run lint` checks formatting without rewriting it and also runs typecheck; formatting errors fail that check.
|
|
629
|
+
2. Run the project's read-only lint/type check (here `bun run lint`). Collect all errors. A repository-wide check may report outside-scope errors; report them without widening the authorized fix scope.
|
|
630
|
+
3. **Surface-change sweep (before any fix).** If the failing set is a **surface/parity** change — CLI noun/verb/flag surface, reference-file structure, or a renamed/moved symbol — do one upfront `rg` sweep across ALL test dirs + docs for stale references to the changed symbols (e.g. `rg -l "<old-noun>|<old-file>.md|Tier C" apps/*/tests plugins/sp/tests plugins/sp/skills docs`), and fix every in-scope pinned test/docs file in that sweep; report outside-scope matches without editing them. A surface change is pinned in **multiple independent test files** (each with its own hardcoded noun→reference map); discovering them one-by-one via full-suite probes is the dominant waste — each wave costs a suite run and a fresh edit loop (task 0436 R2 lesson). One sweep produces the complete edit set upfront.
|
|
556
631
|
4. If lint is clean, skip to step 6.
|
|
557
|
-
5. **Lint fix loop:** for each error, diagnose the root cause and apply the smallest fix. **Use targeted probes to verify each fix** (`bunx tsc --noEmit` on the affected package, `
|
|
558
|
-
6.
|
|
559
|
-
7. If tests are green,
|
|
560
|
-
8. **Test fix loop:** for each failure, diagnose (test bug vs implementation bug), apply the fix, re-run the **failing test only** (`bun test <file> --test-name-pattern "<test>"`). Do NOT re-run the full suite per fix — it is the dominant loop cost (task 0436 R2).
|
|
561
|
-
9. **Confirming run — standalone invocation only (at most once).** After all fixes,
|
|
632
|
+
5. **Lint fix loop:** for each in-scope error, diagnose the root cause and apply the smallest fix. **Use targeted probes to verify each fix** (`bunx tsc --noEmit` on the affected package, `bunx biome check <file>`) — do NOT re-run the full gate after every batch. Loop until lint is green, or report outside-scope blockers without editing them.
|
|
633
|
+
6. For standalone execution, run `bun run test` and collect all failures. With `--gate-log`, use its failing set and targeted tests instead of running the full suite here.
|
|
634
|
+
7. If tests are green, proceed to the applicable standalone confirmation or pipeline handoff below.
|
|
635
|
+
8. **Test fix loop:** for each in-scope failure, diagnose (test bug vs implementation bug), apply the fix, re-run the **failing test only** (`bun test <file> --test-name-pattern "<test>"`). Report outside-scope blockers without editing them. Do NOT re-run the full suite per fix — it is the dominant loop cost (task 0436 R2).
|
|
636
|
+
9. **Confirming run — standalone invocation only (at most once).** After all fixes, repeat the scope-safe formatting invocation from step 1, then run the selected validation command **at most once** to confirm (here the default project gate is `bun run spur-check`). If it passes, the hop is done. **Skip this step entirely when `--gate-log` is set** (see step 10) — under the pipeline nothing consumes its verdict.
|
|
562
637
|
10. **Pipeline-awareness (R4, task 0483; confirming run dropped 2026-08-31).** `--gate-log` is set only by the pipeline's `test-fix` hop, so treat it as the pipeline signal. There, `test-recheck` runs the full `${vars.qualityGateCmd}` gate immediately after this hop returns — that is the **deciding** run, the only one that writes PASS to `.spur/run/<wbs>-test-gate.status`. A confirming run inside this hop decides nothing and costs a second full gate (~105 s here) to answer a question `test-recheck` is about to answer anyway. So under `--gate-log`: **run no full gate at all.** Your self-check is what step 8 already gives you — the failing tests you re-ran individually — plus **one `bun run lint`** (~7 s: Biome + typecheck) to catch type or lint breakage your fixes introduced. Then return and let `test-recheck` judge. `test-recheck` opens with the same cheap `${vars.gateProbeCmd}` probe, so a still-red tree is caught in seconds rather than by a full suite. Historical anti-pattern this replaces: 0482 ran the gate 3× plus a standalone `bun run test`, and `test-recheck` then ran it a 5th time.
|
|
563
638
|
11. Report: list what was fixed (file + one-line summary per fix). If any error could not be resolved, report it explicitly — do not suppress.
|
|
564
|
-
- **Invariants:** Never bypass with `--no-verify`, `--force`, or new `biome-ignore`/`eslint-disable` suppressions. Never skip or `.skip` a test to make the suite green. Fix the root cause, not the symptom.
|
|
565
|
-
- **MANDATORY Exit Condition.**
|
|
639
|
+
- **Invariants:** Never bypass with `--no-verify`, `--force`, or new `biome-ignore`/`eslint-disable` suppressions. Never skip or `.skip` a test to make the suite green. Fix the root cause, not the symptom. Here lint checks formatting and types; it does not prove that the full test gate passed. Keep every write inside `--scope`. **Never re-run the full gate more than once per confirming pass** (R4) — use targeted probes during the fix loops and let the pipeline's `test-recheck` state be the deciding run.
|
|
640
|
+
- **MANDATORY Exit Condition — standalone only.** At step 9, execute the following once; do not add another confirming run:
|
|
566
641
|
1. Run validation command: `eval "$VALIDATION_CMD"`
|
|
567
642
|
2. Capture exit code: `EXIT_CODE=$?`
|
|
568
643
|
3. Output: `echo "EXIT_CODE=$EXIT_CODE"`
|
|
569
644
|
4. **EXIT_CODE must equal 0**
|
|
570
645
|
|
|
571
|
-
If EXIT_CODE != 0: NOT completed.
|
|
646
|
+
If EXIT_CODE != 0: NOT completed. Continue the bounded fix loop for in-scope failures; report outside-scope blockers.
|
|
647
|
+
|
|
648
|
+
**Pipeline exit condition (`--gate-log` set):** return the fixes and the targeted-test/lint evidence from step 10 to `test-recheck`. Do not run the standalone validation command or claim a full-gate PASS; `test-recheck` owns that verdict.
|
|
572
649
|
|
|
573
650
|
**Hallucination Red Flags — STOP if you think:**
|
|
574
651
|
- "The errors look fixed" — check exit code, not appearance
|
|
@@ -597,7 +674,7 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
|
|
|
597
674
|
└─────────────────────────────────────────────────┘
|
|
598
675
|
```
|
|
599
676
|
|
|
600
|
-
The 7 phases
|
|
677
|
+
The 7 phases describe standalone execution: Phases 1–2 capture the gate, Phase 3 settles auto-fixable formatting within scope, Phases 4–6 are the per-group root-cause fix loops, Phase 7 is the final verification run. With `--gate-log`, use the supplied evidence instead of capturing the gate again, and hand off to `test-recheck` instead of running Phase 7's full validation.
|
|
601
678
|
|
|
602
679
|
- **Fix Priority:**
|
|
603
680
|
|
|
@@ -77,12 +77,14 @@ timed-out-implement resume runbook in
|
|
|
77
77
|
tree, and only then force-done if the pipeline is not worth re-driving. F6 below remains the
|
|
78
78
|
recovery when the partial work is not worth keeping or the manual path is already complete.
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
The writer retains the handoff in the run artifact directory and mirrors it into scratch for immediate compatibility. Older runs may have only the scratch copy.
|
|
81
|
+
|
|
82
|
+
**1. Recognise it.** A timeout leaves `.spur/memory/runs/<runId>/artifacts/<runId>-<step>-partial.md` and the run reports
|
|
81
83
|
`exited with code 3`. That is a killed subprocess, not a failed assertion - do not read the
|
|
82
84
|
partial file as a verdict.
|
|
83
85
|
|
|
84
86
|
```bash
|
|
85
|
-
ls -la .spur/
|
|
87
|
+
ls -la .spur/memory/runs/*/artifacts/*-partial.md # handoff files, newest last
|
|
86
88
|
spur workflow trace <run-id> # confirm the terminal state
|
|
87
89
|
```
|
|
88
90
|
|
|
@@ -490,12 +490,12 @@ disk-full, missing directory) routes to **WT-5** — the worktree and branch are
|
|
|
490
490
|
batch can never destroy its own evidence. Reuse mode retains its operator-owned tree but still
|
|
491
491
|
persists the Step 5 report under the invoking tree; the reused tree's `.spur/run/` remains the live
|
|
492
492
|
copy while that tree lives on. The per-run provenance — the worktree DB's run/action rows and the
|
|
493
|
-
`.spur/
|
|
493
|
+
`.spur/memory/runs/<runId>.md` + `.state.json` records — is persisted mechanically by WT-4a's
|
|
494
494
|
`inline-run-setup.ts --persist-out --from <worktree> [--task-file <merged-task>]...` call,
|
|
495
495
|
not by hand.
|
|
496
496
|
|
|
497
497
|
**Stage records are worktree-local too (0948 R9, E7 Finding 5; persisted by 0975 R1).** Each task's
|
|
498
|
-
own per-stage run record (`.spur/
|
|
498
|
+
own per-stage run record (`.spur/memory/runs/<runId>.md` + `.state.json`) and the worktree DB's run rows are
|
|
499
499
|
written inside the worktree and **are removed with it** in create mode — the E7 batch lost exactly
|
|
500
500
|
this evidence. Copying them out is no longer a manual audit-time duty: WT-4a (create-mode block
|
|
501
501
|
below) runs `inline-run-setup.ts --persist-out --from "$WT_PATH"` **before** WT-4b holder cleanup,
|
|
@@ -512,6 +512,8 @@ obligation; neither do root-qualified paths (`knowledge-kit/.spur/run/…`, `/ab
|
|
|
512
512
|
which cite another project's evidence — cite foreign run artifacts that way, never bare. A citation missing in BOTH trees, a divergent cited file (never overwritten — reconcile
|
|
513
513
|
by hand), an unreadable task file, or more than 64 distinct cited files fails the pass → WT-5.
|
|
514
514
|
|
|
515
|
+
**Durable planes ride it too (E71).** Persist-out copies canonical task verdicts, feature run/latest receipts, nested run artifacts and owned sessions before teardown. Artifact and task-run-link rows are exported with run rows, and stored path references are redirected to the invoking tree. Conflicting or unreadable retained evidence refuses teardown.
|
|
516
|
+
|
|
515
517
|
**Owned evidence rides it too (1012).** With at least one `--task-file`, persist-out also treats as
|
|
516
518
|
copy obligations the worktree's `.spur/run/` direct children named `<wbs>-…` (the WBS is each
|
|
517
519
|
forwarded task file's leading four digits before `_`) or `<runId>-…` (every run row in the worktree
|
|
@@ -520,7 +522,7 @@ the task file cites them. They join the cited set: same copy / byte-identical no
|
|
|
520
522
|
divergent-refuse handling. The 64-file cap bounds citations alone; owned names are bounded per
|
|
521
523
|
owner (each `<wbs>-` / `<runId>-` prefix gets its own 64-file budget, task 1034), so the bound
|
|
522
524
|
scales with the batch and one runaway owner refuses by name before any write. `<runId>.md` /
|
|
523
|
-
`<runId>.state.json` stay with the record copy (a conflict
|
|
525
|
+
`<runId>.state.json` stay with the record copy (a conflict is reported and the delegate refuses teardown). Files
|
|
524
526
|
matching neither a citation nor an ownership prefix are left behind. An absent worktree `.spur/run/`
|
|
525
527
|
means nothing is owned; any other listing failure (not a directory, permission denied) fails the
|
|
526
528
|
pass before the invoking tree is written → WT-5. Without `--task-file` nothing is enumerated.
|
|
@@ -528,8 +530,8 @@ pass before the invoking tree is written → WT-5. Without `--task-file` nothing
|
|
|
528
530
|
The shapes are pinned (task 0975 R1; `record-missing` and citation behavior per 0984): idempotent on re-persist;
|
|
529
531
|
success exits 0 printing
|
|
530
532
|
`{"ok":true,"persisted":<n>,"skipped":[{"id":<run-id>,"reason":"id-exists"|"external-key-conflict"|"record-conflict:<file>"|"record-missing:<file>"|"cited-directory:<name>"|"cited-symlink:<name>"|"cited-non-file:<name>"}]}`
|
|
531
|
-
— an `
|
|
532
|
-
`record-conflict:<file>`
|
|
533
|
+
— an `external-key-conflict` skip leaves the target run unchanged **and fails the pass (1049)**: the delegate exits 1 printing `{"ok":false,"error":…}` naming the skipped source run ids, because that (workflow, external key) identity already belongs to a different receiving run — the batch was not persisted, so reconcile the source worktree by hand (it stays the provenance owner of record) before any teardown: auditable reconciliation names the original archived DB snapshot and the skipped source run identities, verifies the archive by file hash and by merged-commit ancestry of the source branch, and treats any residual deletion as explicit operator-authorized cleanup under the strict canonical evidence rules above. An `id-exists` replay repairs missing owned artifacts and task links without duplicating them. A
|
|
534
|
+
`record-conflict:<file>` never overwrites a divergent invoking-tree record and causes the delegate to exit 1, retaining the worktree. A
|
|
533
535
|
`record-missing:<file>` skip is a known `task-lifecycle`/`feature-lifecycle` row with no record file
|
|
534
536
|
at all (its inserted DB row still counts in `persisted` — 0984 R5). Any failure
|
|
535
537
|
exits 1 printing `{"ok":false,"error":<message>}` (a worktree DB run id that is not a single safe
|
|
@@ -867,7 +869,7 @@ git merge --ff-only "$BRANCH" # FF-only: never rebase, merge-commit, or
|
|
|
867
869
|
# Any persistence failure routes to WT-5 — the worktree and branch are retained.
|
|
868
870
|
WT_PATH="$(cd "../<worktree-dir>" && pwd)" # hoisted: needed by WT-4a AND WT-4b below
|
|
869
871
|
# WT-4a provenance persist-out (task 0975 R1): copy the worktree DB's run rows plus
|
|
870
|
-
# the .spur/
|
|
872
|
+
# the .spur/memory/runs/<runId>.md + .state.json records into THIS tree. Run from the main
|
|
871
873
|
# tree (cwd = the invoking tree). --task-file (0984 R2) forwards each merged task
|
|
872
874
|
# file (post-merge path) so the cited .spur/run/<file> evidence is copied/verified
|
|
873
875
|
# too. Resolve the merged path(s) BEFORE this block — an empty value exits 2:
|
|
@@ -135,7 +135,7 @@ spur workflow trace "$RUN" --follow --output # streams the run; --output shows
|
|
|
135
135
|
burned ~110 min in 47 sleeps and 55 trace polls waiting on one run; ADR-047 mandates pipe-free
|
|
136
136
|
observation). `--follow` is a blocking human-streaming mode (no `--json`); run it in the session
|
|
137
137
|
background and let its exit report the terminal verdict. Use `spur workflow trace "$RUN" --follow
|
|
138
|
-
--output` to stream the non-interactive agent output to `.spur/
|
|
138
|
+
--output` to stream the non-interactive agent output to `.spur/memory/runs/<runId>.md` as it lands.
|
|
139
139
|
|
|
140
140
|
Synchronous invocation (`--json` without `--async`) is acceptable **only** for short pipelines
|
|
141
141
|
(< 2 min, e.g. precheck-only or a dry-run). Do not use it for the full task pipeline.
|
|
@@ -302,9 +302,9 @@ rather than raise again without sign-off").
|
|
|
302
302
|
**2. Timed-out implement — resume from the partial tree, don't restart.** A timeout kills the
|
|
303
303
|
implement `agent.run` (exit 3), the pipeline routes to `failed`, and the task stays `todo` with
|
|
304
304
|
the partial work still in the working tree. The failure output names the partial-work artifact
|
|
305
|
-
(`.spur/
|
|
305
|
+
(`.spur/memory/runs/<runId>/artifacts/<runId>-implement-partial.md`) and this runbook. Recovery:
|
|
306
306
|
|
|
307
|
-
1. **Recognise.** `.spur/
|
|
307
|
+
1. **Recognise.** `.spur/memory/runs/<runId>/artifacts/<runId>-implement-partial.md` exists, the run reported `exited
|
|
308
308
|
with code 3`, the task is at `todo`. The artifact's `git diff --stat` section is the partial
|
|
309
309
|
work inventory.
|
|
310
310
|
2. **Establish green from the partial files.** `bun run format` then `bun run lint` + `bun
|
|
@@ -17,17 +17,16 @@ patterns, skill-backed, inline) remains in `dev-operations.md`.
|
|
|
17
17
|
|
|
18
18
|
Every flag shared by two or more commands has exactly one entry here. This is the single place a
|
|
19
19
|
shared flag's meaning is stated; command argument-hints and table rows cite it and must not
|
|
20
|
-
re-define it. The shared-flag set is derived mechanically from
|
|
20
|
+
re-define it. The shared-flag set is derived mechanically from all live `dev-*` command argument-hints (a flag
|
|
21
21
|
counts as shared when it appears in two or more); flags appearing on a single command stay documented
|
|
22
22
|
in that command's body and are not listed here.
|
|
23
23
|
|
|
24
|
-
**Reference form (mechanically detectable).**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
in the link form) do not count; the reference must be the link.
|
|
24
|
+
**Reference form (mechanically detectable).** Each `dev-*` command carries exactly one canonical
|
|
25
|
+
footer link to `../skills/spur-dev/references/flag-glossary.md`, enforced by
|
|
26
|
+
`scripts/commands/validate-commands.ts` (task 0412). Per-flag deep links are not required.
|
|
27
|
+
`command-flag-parity.test.ts` derives shared flags from all live hints and requires exactly one
|
|
28
|
+
canonical glossary entry per shared flag. Each entry retains its `#flag-<name>` anchor, where
|
|
29
|
+
`<name>` is the flag minus its leading `--` (so `--keep-going` → `#flag-keep-going`), for navigation.
|
|
31
30
|
|
|
32
31
|
**Availability rule.** Two flags are only declared where the underlying capability already exists:
|
|
33
32
|
`--json` where the command already produces a structured result a script could consume; `--auto`
|
|
@@ -35,6 +34,15 @@ where the command already has at least one HITL gate. The rule forces a declarat
|
|
|
35
34
|
capability exists — a command that would benefit from `--json` but produces only prose is recorded
|
|
36
35
|
as a follow-up, not quietly left inconsistent.
|
|
37
36
|
|
|
37
|
+
### `--file <path>` — specify the operation's input or output file
|
|
38
|
+
|
|
39
|
+
**Anchor:** `#flag-file`.
|
|
40
|
+
|
|
41
|
+
Resolve relative paths against the invocation directory before switching to an execution
|
|
42
|
+
repository/worktree; preserve quoted paths with spaces. The command defines format and direction:
|
|
43
|
+
job-dump writes/refreshes Markdown, job-resume reads Markdown, and feature-change reads its mapping
|
|
44
|
+
file. Required for job-dump and job-resume; neither has a default path.
|
|
45
|
+
|
|
38
46
|
### `--agent <inline|auto|name>` — name who does the model-bearing work
|
|
39
47
|
|
|
40
48
|
**Anchor:** `#flag-agent`.
|
|
@@ -11,6 +11,10 @@ see_also:
|
|
|
11
11
|
|
|
12
12
|
# Inline Pipeline Driver
|
|
13
13
|
|
|
14
|
+
**Installed-copy drift (1046):** Superskill converts `/sp:dev-*` command spellings to
|
|
15
|
+
`/sp-dev-*` for Codex. After `superskill install sp`, this adapter-only difference remains;
|
|
16
|
+
the interpreter and trace instructions must match. Never hand-edit the installed reference.
|
|
17
|
+
|
|
14
18
|
**Owner:** `spur-dev-maintainers` (per task 0755 R1). Reach the named owner via the frontmatter; no need to read the originating task.
|
|
15
19
|
|
|
16
20
|
**Retirement criterion (0755 R5, D8 decision D7):** the per-task interpreter retires once the engine covers per-task execution for `/sp:dev-runall` with real terminal runs **and** the parity check (this doc's documented action/guard set ≡ the resolved action/guard set of every `.spur/workflows/*.yaml`) is green. Recording the criterion is part of this task; acting on it is not — that is a separate A3-gate decision.
|
|
@@ -69,8 +73,11 @@ the human/native presentation layer — labels are display addresses only, never
|
|
|
69
73
|
1. Resolve the command inputs, `--auto`, and any explicit `--vars` — **without reading the selected
|
|
70
74
|
YAML yet**. An explicit non-inline executor selection chooses the subprocess workflow path.
|
|
71
75
|
2. Allocate a collision-resistant inline run id (`uuidgen`, with a timestamp/pid fallback), create
|
|
72
|
-
`.spur/run
|
|
73
|
-
`.spur/
|
|
76
|
+
`.spur/run/` for attempt staging and `.spur/memory/runs/` for retained records, and use the two-file run record (task 0927) — append lines to
|
|
77
|
+
`.spur/memory/runs/<run-id>.md` and read machine state from `.spur/memory/runs/<run-id>.state.json`.
|
|
78
|
+
The run id lives in those two files and the persisted run row — never stage it in an ad-hoc
|
|
79
|
+
`*.env` file: the `no-env-files` gate rule flags any `.env` name, so run-scoped staging files
|
|
80
|
+
use `<run-id>-*` names with `.md`/`.json`/`.txt`/`.status` extensions only.
|
|
74
81
|
3. **Authoritative run identity (task 0804 R1, fail-closed).** Persist the run row through the
|
|
75
82
|
internal delegate before any stage executes — this is what makes bound `run.artifact` record
|
|
76
83
|
accept the inline run (0785 R3):
|
|
@@ -91,7 +98,7 @@ the human/native presentation layer — labels are display addresses only, never
|
|
|
91
98
|
obtains the selected definition from the existing CLI `workflow show --format todo --json`
|
|
92
99
|
projection and revalidates its schema/name/digest before preserving its source layer.
|
|
93
100
|
Both paths create-or-attach the row,
|
|
94
|
-
and writes the run-record state `.spur/
|
|
101
|
+
and writes the run-record state `.spur/memory/runs/<run-id>.state.json` plus the `.md` run-start
|
|
95
102
|
header (task 0927; a legacy pre-0927 run keeps its `<run-id>-inline-setup.json` sidecar).
|
|
96
103
|
Seed `__runId` and `__definitionDigest`
|
|
97
104
|
from that state so proof capture and bound registration verify against the persisted identity.
|
|
@@ -236,6 +243,19 @@ Start at `initialState`. For each current state, execute its `onEnter` actions i
|
|
|
236
243
|
then evaluate outgoing transitions in declaration order and take the first passing guard. Stop only
|
|
237
244
|
at a declared terminal state or a surfaced HITL pause. The `iterationBound` remains mandatory.
|
|
238
245
|
|
|
246
|
+
After each executed action settles, record its boundary before the next action, transition guard,
|
|
247
|
+
or terminal close. Measure its actual duration and preserve its declared failure policy:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
bun "$SETUP_SCRIPT" --action --run-id "$RUN_ID" --node <state-id> --kind <action-kind> \
|
|
251
|
+
--status <done|failed> --ok <true|false> --duration-ms <measured-ms>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
For a multi-action state, `--actions-file` may emit the measured boundaries together before leaving
|
|
255
|
+
that state. Follow [Structured trace emission](#structured-trace-emission-adr-117-task-0868) for the
|
|
256
|
+
payload, delegated `decide` emission and best-effort failure handling. Never retry a failed batch
|
|
257
|
+
or backfill at close; a zero-row done close fails with `NO_ACTION_ROWS`.
|
|
258
|
+
|
|
239
259
|
Action semantics come from the YAML and the workflow action contract:
|
|
240
260
|
|
|
241
261
|
- `shell` — run the expanded command in the project working tree with resolved vars exported as
|
|
@@ -280,12 +300,12 @@ Action semantics come from the YAML and the workflow action contract:
|
|
|
280
300
|
and pass the same `--feature-file` the run folded in — omitting it, or running from elsewhere,
|
|
281
301
|
yields a different digest and the mismatch surfaces later as a refused `run.artifact`
|
|
282
302
|
registration — and the run-scoped review-completion marker exists — then appends one provenance
|
|
283
|
-
line to `.spur/
|
|
303
|
+
line to `.spur/memory/runs/<run-id>.md` naming the equivalence (artifact kind, path, verdict, digest) and
|
|
284
304
|
proceeds to `spur task record`. A failed validation stops at the state and follows the failure
|
|
285
305
|
contract; the step is never silently skipped. Artifact-provenance consumers read that run-log
|
|
286
306
|
line on the inline path — there is no ledger row. The validation also includes **run/definition
|
|
287
307
|
identity agreement from authoritative evidence** (task 0809 R4): the verdict's `proof.runId` and
|
|
288
|
-
`proof.definitionDigest` must agree with the run-record state `.spur/
|
|
308
|
+
`proof.definitionDigest` must agree with the run-record state `.spur/memory/runs/<run-id>.state.json`
|
|
289
309
|
(legacy pre-0927 runs: `<run-id>-inline-setup.json`) and the persisted run row; if that identity
|
|
290
310
|
is absent or conflicts, STOP — recreating a row is
|
|
291
311
|
not a diagnostic operation. The app-service bound-artifact fixture (which writes a real engine
|
|
@@ -314,6 +334,18 @@ Action semantics come from the YAML and the workflow action contract:
|
|
|
314
334
|
with no `estimate_hours` passes this condition unchanged. The driver reads the frontmatter value
|
|
315
335
|
directly — never estimates size itself.
|
|
316
336
|
|
|
337
|
+
**Diffstat arm (verify only, 1033 R1).** When the current state id is `verify`, condition 5
|
|
338
|
+
fails when the triage diffstat file `.spur/run/<wbs>-diffstat.json` exists and shows a
|
|
339
|
+
small, non-sensitive diff: `([.files, .insertions, .deletions] | all(type == "number")) and
|
|
340
|
+
.files <= 3 and (.insertions + .deletions) <= 60 and
|
|
341
|
+
.sensitive == false` (literal thresholds; the driver reads the file with `jq` — it never
|
|
342
|
+
estimates size itself). A missing, unparsable or `sensitive: true` diffstat leaves condition 5
|
|
343
|
+
as above, so the failure mode is more isolation, never less. A missing or null count also leaves
|
|
344
|
+
condition 5 as above. Below the floor on this arm, the
|
|
345
|
+
run log carries `stage verify executed inline in session <session-id> (below dispatch floor:
|
|
346
|
+
diffstat files <f> lines <n>)`. Only `verify` eligibility changes: `implement` and `review`
|
|
347
|
+
keep the estimate floor, and the pipeline state graph is unchanged.
|
|
348
|
+
|
|
317
349
|
All five pass → dispatch. Any pre-dispatch failure → execute the stage **once** in the host session.
|
|
318
350
|
An `agent.run` whose `input` is free-form prose rather than a pure slash command fails condition 2
|
|
319
351
|
and is never dispatch-eligible: the driver executes it in the host session and logs it with the
|
|
@@ -465,7 +497,7 @@ or an operator decision returns a blocker; the host pauses at the current state
|
|
|
465
497
|
subagent cannot approve, infer consent, or recursively invoke the full pipeline.
|
|
466
498
|
|
|
467
499
|
After every successful inline `agent.run` action append exactly one provenance line (inline or
|
|
468
|
-
subagent form above) to `.spur/
|
|
500
|
+
subagent form above) to `.spur/memory/runs/<run-id>.md`, where `<id>` is the current YAML state id. Also
|
|
469
501
|
log start/failure and the ignored timeout value so an inline run remains auditable without
|
|
470
502
|
fabricating an `AgentRunTracedResult`.
|
|
471
503
|
|
|
@@ -477,7 +509,7 @@ in one file and makes the run unauditable (task 0726 mixed both forms).
|
|
|
477
509
|
|
|
478
510
|
## Structured trace emission (ADR-117, task 0868)
|
|
479
511
|
|
|
480
|
-
`.spur/
|
|
512
|
+
`.spur/memory/runs/<run-id>.md` is the human half of the two-file run record — evidence, **not the record
|
|
481
513
|
of truth**. A run's
|
|
482
514
|
observability is a property of the run, so the inline driver owes the same structured trace the
|
|
483
515
|
engine subprocess writes — and it owes it through the **same writer**, never a parallel
|
|
@@ -570,7 +602,7 @@ The driver reaches it through the existing run delegate (`$SETUP_SCRIPT`,
|
|
|
570
602
|
nothing), and any `done` close with `actionRows ≥ 1` exits `0`.
|
|
571
603
|
|
|
572
604
|
**Best-effort at the action boundary only (ADR-117).** An `--action` persistence failure is
|
|
573
|
-
recorded — the delegate appends a `trace-emission-failed` line to `.spur/
|
|
605
|
+
recorded — the delegate appends a `trace-emission-failed` line to `.spur/memory/runs/<run-id>.md` and
|
|
574
606
|
prints `{"ok":false}` on stdout — and the run continues to its declared terminal state; the
|
|
575
607
|
delegate exits `0` for that outcome and the driver must never treat an emission failure as a run
|
|
576
608
|
failure, retry it in a loop, or substitute a hand-written row. The run-row closure (`--close`) is
|
|
@@ -594,10 +626,12 @@ Order matters for the `testing → done` hop. The A3 batch hit the same clobberi
|
|
|
594
626
|
tasks (0617, 0619) because the sections were hand-written **before** the verdict artifact existed:
|
|
595
627
|
|
|
596
628
|
1. **Write the verdict artifact first.** `spur task record --solution-from-diff --transition testing`
|
|
597
|
-
reads `.spur/run/<wbs>-verdict.json` (default)
|
|
598
|
-
**
|
|
599
|
-
|
|
600
|
-
|
|
629
|
+
reads `.spur/run/<wbs>-verdict.json` (default attempt output) on every invocation and atomically retains the recorded verdict under `.spur/memory/evidence/`. A missing or malformed artifact
|
|
630
|
+
yields **UNKNOWN**: bare Testing receives a "No requirements recorded" stub, while already-authored
|
|
631
|
+
Testing is preserved. `--solution-from-diff` backfills only a bare Solution. The A3 clobbering above
|
|
632
|
+
describes the historical behavior, corrected by the authored-Testing safeguard. Creating the
|
|
633
|
+
artifact first (PASS, with requirement rows keyed by scenario title) remains the standard order;
|
|
634
|
+
re-running record after a real verdict arrives refreshes Testing from that verdict.
|
|
601
635
|
|
|
602
636
|
```bash
|
|
603
637
|
# verdict artifact first (shape: {wbs, verdict, requirements:[{id,status,evidence}], checks:[], source})
|