@gobing-ai/spur 0.4.31 → 0.4.34

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.
Files changed (91) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.global.yaml +1 -4
  3. package/config/decisions/task-pipeline.yaml +1 -29
  4. package/config/rules/boundary/sp-runtime-path.yaml +0 -2
  5. package/config/rules/strict/runtime-boundaries.yaml +2 -12
  6. package/config/rules/structure/protected-files.yaml +0 -3
  7. package/config/rules/surface/check-cli-surface.yaml +1 -2
  8. package/config/workflow-candidates.json +1 -1
  9. package/config/workflows/idea-pipeline.yaml +1 -1
  10. package/config/workflows/task-pipeline.yaml +53 -185
  11. package/package.json +1 -1
  12. package/plugins/sp/agents/super-reviewer.md +18 -60
  13. package/plugins/sp/commands/dev-fixall.md +0 -7
  14. package/plugins/sp/commands/dev-review.md +1 -1
  15. package/plugins/sp/commands/dev-run.md +8 -3
  16. package/plugins/sp/commands/dev-runall.md +7 -4
  17. package/plugins/sp/commands/dev-verify.md +0 -10
  18. package/plugins/sp/commands/dev-verifyall.md +0 -5
  19. package/plugins/sp/plugin.json +1 -1
  20. package/plugins/sp/skills/code-implementation/SKILL.md +1 -3
  21. package/plugins/sp/skills/code-verification/SKILL.md +11 -41
  22. package/plugins/sp/skills/code-verification/references/verdict-schema.md +18 -119
  23. package/plugins/sp/skills/issue-finding/SKILL.md +1 -1
  24. package/plugins/sp/skills/next-router/references/routing-table.md +0 -7
  25. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +1 -6
  26. package/plugins/sp/skills/spur-cli/references/decision.md +3 -6
  27. package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +0 -28
  28. package/plugins/sp/skills/spur-cli/references/tasks.md +9 -7
  29. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +5 -12
  30. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +2 -3
  31. package/plugins/sp/skills/spur-dev/references/dev-operations.md +4 -4
  32. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -5
  33. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +9 -5
  34. package/plugins/sp/skills/spur-dev/references/execution-batch.md +4 -5
  35. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +1 -1
  36. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +34 -0
  37. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +14 -1
  38. package/spur.js +1437 -4409
  39. package/web/_astro/{BoardApp.CuCuw0lw.js → BoardApp.BzY_krKQ.js} +1 -1
  40. package/web/_astro/{BoardApp.BGGDrfHl.js → BoardApp.CIImQFjG.js} +3 -3
  41. package/web/_astro/{TaskDetail.DWXct9_X.js → TaskDetail.c48Pnba6.js} +1 -1
  42. package/web/_astro/{arc.BxG3NS1o.js → arc.CpU6Cddr.js} +1 -1
  43. package/web/_astro/{architectureDiagram-3BPJPVTR.BxaiM2Hv.js → architectureDiagram-3BPJPVTR.CaXT9ZEz.js} +1 -1
  44. package/web/_astro/{blockDiagram-GPEHLZMM.DJ3r6SdD.js → blockDiagram-GPEHLZMM.Cnv3IsW9.js} +1 -1
  45. package/web/_astro/{c4Diagram-AAUBKEIU.BkzpXBQs.js → c4Diagram-AAUBKEIU.VO_hjv9n.js} +1 -1
  46. package/web/_astro/channel.DrtdR7d_.js +1 -0
  47. package/web/_astro/{chunk-2J33WTMH.DI7UanTc.js → chunk-2J33WTMH.BOunhbrU.js} +1 -1
  48. package/web/_astro/{chunk-4BX2VUAB.C2uLhAlQ.js → chunk-4BX2VUAB.Brg-Gmb2.js} +1 -1
  49. package/web/_astro/{chunk-55IACEB6.KwNI2kxL.js → chunk-55IACEB6.BqF9dxiC.js} +1 -1
  50. package/web/_astro/{chunk-727SXJPM.CHZUthkg.js → chunk-727SXJPM.CEIGJZdc.js} +1 -1
  51. package/web/_astro/{chunk-AQP2D5EJ.DLr4QNJo.js → chunk-AQP2D5EJ.BxXI0bx9.js} +1 -1
  52. package/web/_astro/{chunk-FMBD7UC4.B1G8WrnE.js → chunk-FMBD7UC4.CveXCF83.js} +1 -1
  53. package/web/_astro/{chunk-ND2GUHAM.CzsA-SkD.js → chunk-ND2GUHAM.DwKjp403.js} +1 -1
  54. package/web/_astro/{chunk-QZHKN3VN.DAvBQYli.js → chunk-QZHKN3VN.DgwjHrXx.js} +1 -1
  55. package/web/_astro/{classDiagram-4FO5ZUOK.Cddmz8Ze.js → classDiagram-4FO5ZUOK.BcVv8Qmo.js} +1 -1
  56. package/web/_astro/{classDiagram-v2-Q7XG4LA2.Cddmz8Ze.js → classDiagram-v2-Q7XG4LA2.BcVv8Qmo.js} +1 -1
  57. package/web/_astro/{cose-bilkent-S5V4N54A.CKEu7KRX.js → cose-bilkent-S5V4N54A.28xfMBER.js} +1 -1
  58. package/web/_astro/{cynefin-OW5HDTMX.-B4Cy_Vl.js → cynefin-OW5HDTMX.BAFHBcJj.js} +1 -1
  59. package/web/_astro/{dagre-BM42HDAG.bLxFvI-t.js → dagre-BM42HDAG.DzR6wa9Z.js} +1 -1
  60. package/web/_astro/{diagram-2AECGRRQ.DAHU0t5h.js → diagram-2AECGRRQ.IpFlr4yd.js} +1 -1
  61. package/web/_astro/{diagram-5GNKFQAL.DFciwCNk.js → diagram-5GNKFQAL.DGNU2pOL.js} +1 -1
  62. package/web/_astro/{diagram-KO2AKTUF.BvH0dGId.js → diagram-KO2AKTUF.D_wP6t4w.js} +1 -1
  63. package/web/_astro/{diagram-LMA3HP47.BgVlskRO.js → diagram-LMA3HP47.B0DMC97s.js} +1 -1
  64. package/web/_astro/{diagram-OG6HWLK6.BpurMISo.js → diagram-OG6HWLK6.DQXmNEBs.js} +1 -1
  65. package/web/_astro/{erDiagram-TEJ5UH35.SDj5bUMU.js → erDiagram-TEJ5UH35.BZ0VPjjp.js} +1 -1
  66. package/web/_astro/{flowDiagram-I6XJVG4X.Bm5U58FE.js → flowDiagram-I6XJVG4X.zu5gJs9Z.js} +1 -1
  67. package/web/_astro/{ganttDiagram-6RSMTGT7.CnMnds77.js → ganttDiagram-6RSMTGT7.DYy6LDqD.js} +1 -1
  68. package/web/_astro/{gitGraphDiagram-PVQCEYII.BQUwwyWo.js → gitGraphDiagram-PVQCEYII.C6c_wPdO.js} +1 -1
  69. package/web/_astro/index.C4tUn4AU.css +1 -0
  70. package/web/_astro/{infoDiagram-5YYISTIA.BiSKdORH.js → infoDiagram-5YYISTIA.C3bQPQl8.js} +1 -1
  71. package/web/_astro/{ishikawaDiagram-YF4QCWOH.Br69sBTI.js → ishikawaDiagram-YF4QCWOH.Cc1D58oG.js} +1 -1
  72. package/web/_astro/{journeyDiagram-JHISSGLW.C39WX1W8.js → journeyDiagram-JHISSGLW.CY51-lNM.js} +1 -1
  73. package/web/_astro/{kanban-definition-UN3LZRKU.DppWcbSX.js → kanban-definition-UN3LZRKU.D_3v92y6.js} +1 -1
  74. package/web/_astro/{linear.DeivTDuc.js → linear.C6BrJ38s.js} +1 -1
  75. package/web/_astro/{mermaid.core.Dixrjrnj.js → mermaid.core.DO9lF20B.js} +4 -4
  76. package/web/_astro/{mindmap-definition-RKZ34NQL.BWIQ2MWG.js → mindmap-definition-RKZ34NQL.BMiM91P6.js} +1 -1
  77. package/web/_astro/{pieDiagram-4H26LBE5.vvtHpfT7.js → pieDiagram-4H26LBE5.CcgIgRlR.js} +1 -1
  78. package/web/_astro/{quadrantDiagram-W4KKPZXB.9c-T6qCy.js → quadrantDiagram-W4KKPZXB.CM1CzrHl.js} +1 -1
  79. package/web/_astro/{requirementDiagram-4Y6WPE33.9ZuRw-kn.js → requirementDiagram-4Y6WPE33.CQvQ1E8r.js} +1 -1
  80. package/web/_astro/{sankeyDiagram-5OEKKPKP.CTIWteEl.js → sankeyDiagram-5OEKKPKP.D-b1ONCV.js} +1 -1
  81. package/web/_astro/{sequenceDiagram-3UESZ5HK.DEvu4vLL.js → sequenceDiagram-3UESZ5HK.BQzFGYtH.js} +1 -1
  82. package/web/_astro/{stateDiagram-AJRCARHV.Bxvsgk-_.js → stateDiagram-AJRCARHV.DiCukZ7I.js} +1 -1
  83. package/web/_astro/{stateDiagram-v2-BHNVJYJU.CVuog5yY.js → stateDiagram-v2-BHNVJYJU.4Iut-DMk.js} +1 -1
  84. package/web/_astro/{timeline-definition-PNZ67QCA.CpPItB3E.js → timeline-definition-PNZ67QCA.BKQiLF24.js} +1 -1
  85. package/web/_astro/{vennDiagram-CIIHVFJN.C7eKaLRK.js → vennDiagram-CIIHVFJN.CyeSCofx.js} +1 -1
  86. package/web/_astro/{wardleyDiagram-YWT4CUSO.DWXHT_CW.js → wardleyDiagram-YWT4CUSO.B140ei48.js} +1 -1
  87. package/web/_astro/{xychartDiagram-2RQKCTM6.DOsrNQOF.js → xychartDiagram-2RQKCTM6.DjPyVoO1.js} +1 -1
  88. package/web/index.html +2 -2
  89. package/config/rules/structure/scratch-evidence-pointer.yaml +0 -35
  90. package/web/_astro/channel.CYWRkoDI.js +0 -1
  91. package/web/_astro/index.CKtaGArK.css +0 -1
@@ -2,7 +2,7 @@
2
2
  description: Run a task — full pipeline (precheck→implement→test→review→approve→verify→record→done) or single-step (implement)
3
3
  requires: [cli:spur, local-fs]
4
4
  role: coder
5
- argument-hint: "<wbs> [--mode <full|implement>] [--agent <inline|auto|name>] [--auto] [--next] [--wrap] [--continue] [--worktree [<name>]] [--no-summary]"
5
+ argument-hint: "<wbs> [--mode <full|implement>] [--agent <inline|auto|name>] [--auto] [--next] [--wrap] [--wrap-pr] [--continue] [--worktree [<name>]] [--no-summary]"
6
6
  allowed-tools: ["Bash", "Read", "Write", "Edit", "Skill"]
7
7
  ---
8
8
 
@@ -19,7 +19,8 @@ Wraps the **sp:spur-dev** and **sp:code-implementation** skills.
19
19
  | `--agent` `<inline\|auto\|name>` | Who runs the model-bearing stages. omit and explicit `--agent inline` resolve identically (task 0687): eligible stages dispatch once to a native subagent with host-session fallback (0508 eligibility); otherwise every stage executes in the invoking session. `auto` or a name keeps subprocess dispatch.. The opt-in `fleet` selector (0942) maps the run to `executor: 'fleet'` so `agent.run` stages dispatch through the fleet control plane (ADR-126) instead of a subprocess. | omit |
20
20
  | `--auto` | Skip objective HITL confirmations. | off |
21
21
  | `--next` | Chain-to-completion via the next-router. | off |
22
- | `--wrap` | Run the wrap hop after the main step. The `--agent` selector is preserved into the `/sp:dev-wrap <wbs>` handoff when supplied; omission remains omission. The wrap hop is workflow-backed and reports its trigger-3 subprocess override. | off |
22
+ | `--wrap` | Run the wrap hop after the main step. The `--agent` selector is preserved into the `/sp:dev-wrap <wbs>` handoff when supplied; omission remains omission. The wrap hop is workflow-backed and reports its trigger-3 subprocess override. Mutually exclusive with `--wrap-pr`. | off |
23
+ | `--wrap-pr` | Run the wrap hop after the main step, commit close-out writes, push the worktree branch to remote origin, and open a Pull Request targeting the base ref (WT-PR). Mutually exclusive with `--wrap`. Full mode only; requires `--worktree` or a dedicated non-base branch. | off |
23
24
  | `--continue` | Resume an interrupted task from its checkpoint. | off |
24
25
  | `--worktree` `[<name>]` | Run the task pipeline in an isolated git worktree; FF-merge on success, retain on failure. Bare `--worktree` creates a fresh tree; `--worktree <name>` adopts an existing worktree by name/path/branch. Full mode only. | off |
25
26
  | `--no-summary` | Skip the measured execution summary (per-stage time, wait, tool calls, total / non-cached tokens) printed after a full-mode run. | off (summary printed) |
@@ -28,7 +29,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
28
29
 
29
30
  ## Usage
30
31
 
31
- /sp:dev-run <wbs> [--mode <full|implement>] [--agent <inline|auto|name>] [--auto] [--next] [--wrap] [--continue] [--worktree [<name>]] [--no-summary]
32
+ /sp:dev-run <wbs> [--mode <full|implement>] [--agent <inline|auto|name>] [--auto] [--next] [--wrap] [--wrap-pr] [--continue] [--worktree [<name>]] [--no-summary]
32
33
 
33
34
  ## Implementation
34
35
 
@@ -64,6 +65,10 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
64
65
  `.spur/run/<wbs>-question.md` and exits 0 — the pipeline's `escalate` hop surfaces the question,
65
66
  the operator answers via `spur workflow continue --answer-text`, and the guard appends the Q/A
66
67
  pair to this transcript before re-entering implement, where the agent reads it and resumes.
68
+ - `--wrap-pr` (run wrap hop, push branch, and create PR) — runs the wrap hop on `$BRANCH`, commits close-out
69
+ writes, pushes the branch to `origin`, and opens a Pull Request targeting `$BASE_REF`
70
+ (`WT-PR`, execution-worktree-landing.md). Mutually exclusive with `--wrap`: passing both exits 2. Full mode only;
71
+ requires `--worktree` or execution on a dedicated non-base branch (refuses execution directly on `main`).
67
72
 
68
73
  `--worktree` `[<name>]` (run the task's pipeline in an isolated git worktree — FF-merge onto the
69
74
  base ref on full success, retain intact on any failure/halt/non-FF; bare form creates a fresh tree,
@@ -2,7 +2,7 @@
2
2
  description: Run a batch of tasks through their pipelines in dependency-correct order — resolve a set, topo-sort, run each via task-pipeline.yaml, emit a batch report
3
3
  requires: [cli:spur, local-fs]
4
4
  role: planner
5
- argument-hint: "--tasks <selector> [--feature <id>] [--mode <sequential|parallel|auto>] [--concurrency <n>] [--keep-going] [--auto] [--agent <inline|auto|name>] [--json] [--wrap] [--next] [--continue] [--worktree [<name>]] [--no-summary] [--defer-gate]"
5
+ argument-hint: "--tasks <selector> [--feature <id>] [--mode <sequential|parallel|auto>] [--concurrency <n>] [--keep-going] [--auto] [--agent <inline|auto|name>] [--json] [--wrap] [--wrap-pr] [--next] [--continue] [--worktree [<name>]] [--no-summary] [--defer-gate]"
6
6
  allowed-tools: ["Bash", "Read", "Skill"]
7
7
  ---
8
8
 
@@ -21,7 +21,8 @@ Wraps the **sp:spur-dev** skill.
21
21
  | `--auto` | Skip objective HITL gates, and treat the batch as unattended: `--auto` implies `--keep-going` (a failed task is `failed`, its in-batch dependents `skipped`, independents keep running). | off |
22
22
  | `--agent` `<inline\|auto\|name>` | Who runs each task's pipeline stages. Interactive sequential omit/`inline` uses the host-session driver with unified inline semantics (task 0687 — see below). `auto`, a name, parallel mode, and headless invocation use subprocesses; `auto` is resolved **once per batch** — the first run's implement `result.executor` is pinned for every later task, and only a `failed-agent` ending re-resolves it, exactly once (1318 R2/R3). The opt-in `fleet` selector (0942) maps each task run to `executor: 'fleet'` so `agent.run` stages dispatch through the fleet control plane (ADR-126) instead of a subprocess. | omit |
23
23
  | `--json` | Emit structured JSON. | off |
24
- | `--wrap` | Run the wrap hop **once for the batch** over the `done` subset only (Step 6 of execution-batch.md): `vars.feature` is passed only when every frozen task is `done`/`cancelled`; an empty done subset skips the wrap with a reason. The `--agent` selector is preserved into the `/sp:dev-wrap` handoff when supplied; omission remains omission. | off |
24
+ | `--wrap` | Run the wrap hop **once for the batch** over the `done` subset only (Step 6 of execution-batch.md): `vars.feature` is passed only when every frozen task is `done`/`cancelled`; an empty done subset skips the wrap with a reason. The `--agent` selector is preserved into the `/sp:dev-wrap` handoff when supplied; omission remains omission. Mutually exclusive with `--wrap-pr`. | off |
25
+ | `--wrap-pr` | Run the wrap hop **once for the batch** over the `done` subset, commit close-out writes, push the worktree branch to remote origin, and open a Pull Request targeting the base ref (WT-PR). Mutually exclusive with `--wrap`. Requires `--worktree` or a dedicated non-base branch. | off |
25
26
  | `--next` | Chain-to-completion via the next-router. | off |
26
27
  | `--continue` | Resume an interrupted batch. | off |
27
28
  | `--worktree` `[<name>]` | Run the batch in an isolated git worktree; FF-merge on success, retain on failure. Bare `--worktree` creates a fresh tree; `--worktree <name>` adopts an existing worktree by name/path/branch. | off |
@@ -34,7 +35,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
34
35
  ## Usage
35
36
 
36
37
  ```
37
- /sp:dev-runall --tasks <selector> [--feature <id>] [--mode <sequential|parallel|auto>] [--concurrency <n>] [--keep-going] [--auto] [--agent <inline|auto|name>] [--json] [--wrap] [--next] [--continue] [--worktree [<name>]] [--no-summary] [--defer-gate]
38
+ /sp:dev-runall --tasks <selector> [--feature <id>] [--mode <sequential|parallel|auto>] [--concurrency <n>] [--keep-going] [--auto] [--agent <inline|auto|name>] [--json] [--wrap] [--wrap-pr] [--next] [--continue] [--worktree [<name>]] [--no-summary] [--defer-gate]
38
39
  ```
39
40
 
40
41
  Flags: `--tasks <selector>` (required — explicit WBS list, status pseudo-list, `feature:<id>`,
@@ -57,7 +58,9 @@ unattended, so it also implies `--keep-going`), `--agent <inline|auto|name>`
57
58
  `auto` or a name is merged into each per-task `vars.agent` and `vars.implementAgent`; `fleet` maps each task run to `executor: 'fleet'` instead (fleet dispatch, 0942); parallel mode
58
59
  retains isolated subprocesses, ADR-047), `--json` (emit the
59
60
  report as JSON), `--wrap` (trigger
60
- `wrapup-pipeline.yaml` after the batch completes), `--next`
61
+ `wrapup-pipeline.yaml` after the batch completes; mutually exclusive with `--wrap-pr`), `--wrap-pr`
62
+ (run batch wrap hop, commit close-out writes, push worktree branch to remote origin, and open a Pull Request
63
+ targeting the base ref; mutually exclusive with `--wrap`), `--next`
61
64
  (chain each task to terminal status, then run the wrap hop **once for the batch** — see below),
62
65
  `--worktree` `[<name>]` (run the batch in an isolated git worktree —
63
66
  FF-merge onto the base ref on full success, retain intact on any failure/halt/non-FF; bare form
@@ -41,16 +41,6 @@ See `sp:code-verification` § Shippable readiness gate.
41
41
 
42
42
  - Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
43
43
  - `Skill(skill="sp:code-verification", args="verify $ARGUMENTS")`
44
- - **Residual sweep (F96 R1, post-record since 0987):** after `task verdict` derives
45
- `.spur/run/<wbs>-verdict.json` and `spur task record` has flipped the verdict-proven R/AC boxes,
46
- run `spur task residual <wbs> scan` + `fold` (observe-only; folds the verdict's `residual-sweep` check,
47
- PASS → PARTIAL when a blocking residual exists) — under every `--fix` mode — then, only on a
48
- downgrade, re-run `spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json` so Testing
49
- carries the final verdict. Same order as the pipeline `done` state's record close (0983): scanning before
50
- record reads unticked-but-proven boxes and folds a clean PASS to PARTIAL. When the task reaches
51
- `done` through `--next`, run `spur task residual <wbs> settle` (best-effort). On a folded PARTIAL: the bounded remediation loop has
52
- already run — a residual-failed task is routed to router C6 (HITL STOP), never another
53
- automatic fix loop.
54
44
 
55
45
  **Flags:**
56
46
 
@@ -73,8 +73,3 @@ Without `--fix all`, shippable is not evaluated (optional note: use `--fix all`
73
73
  - Batch orchestration: `Skill(skill="sp:spur-dev", args="verifyall $ARGUMENTS")`
74
74
  - Per-task verification (inner): `Skill(skill="sp:code-verification", args="verify <wbs> $SHARED_FLAGS")`
75
75
  - Shippable gate: once after the batch (same skill § Shippable readiness gate)
76
- - **Residual sweep (F96 R1, per task, post-record since 0987):** same contract as
77
- `/sp:dev-verify` — after each task's verdict artifact is derived and `spur task record` has
78
- flipped its verdict-proven boxes, run `spur task residual <wbs> scan` + `fold` (under every
79
- `--fix` mode), and re-record only on a downgrade; on reaching `done` via `--next`, run
80
- `spur task residual <wbs> settle`.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.4.31",
3
+ "version": "0.4.34",
4
4
  "description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics."
5
5
  }
@@ -84,9 +84,7 @@ not have and work you were not asked to do.
84
84
  prerequisite. If the target genuinely cannot proceed without it, stop and say so — a blocked task
85
85
  is a cheap finding; a two-task diff costs the reverts.
86
86
  - **Flip the target's `## Plan` boxes as each step completes.** They are this pass's progress
87
- ledger, and the record-time residual sweep treats an *unchecked* Plan box as blocking: it
88
- downgrades the verdict to PARTIAL and closes the `done` gate
89
- (`docs/design/task-residual-sweep.md`), which costs a remediation cycle and a manual re-record.
87
+ ledger.
90
88
  Leave every finished step ticked through `spur task update <wbs> --section Plan --from-file`, and
91
89
  if you deliberately skipped one, say so in the Solution change map.
92
90
 
@@ -161,12 +161,10 @@ Evidence: @gobing-ai/ts-llm-jsonl-importer `src/mappers.ts` line 481 — omp cal
161
161
  ```
162
162
 
163
163
  Use this form ONLY when the evidence genuinely lives outside `spur`'s working tree (a `@gobing-ai/ts-*`
164
- source under `~/xprojects/ts-libs`, or a gitignored `.spur/run/**` artifact). `checkLineAnchors`
165
- classifies it as external and never raises `L4.stale-line-anchor` for it (R1). Do NOT use it for a file
166
- that lives in this repo — in-repo evidence MUST use the repo-relative backtick form
167
- `` `path:line` `` / `` `path:start-end` ``, and citing it in the external form still reports (R2).
164
+ source under `~/xprojects/ts-libs`, or a gitignored `.spur/run/**` artifact). In-repo evidence uses the
165
+ repo-relative backtick form `` `path:line` `` / `` `path:start-end` ``.
168
166
 
169
- **Concrete anchors (0804 R9):** existing `file:line`s only, never globs, always repo-root-relative — a basename is `L4.anchor-unresolved` at the `--as done` gate (`references/verdict-schema.md`).
167
+ **Concrete anchors:** existing `file:line`s only, never globs or basenames, always repo-root-relative (`references/verdict-schema.md`).
170
168
 
171
169
  ### Step 5 — Acceptance Criteria guard
172
170
 
@@ -275,7 +273,7 @@ completion gate (`PARTIAL`/`FAIL` route the pipeline to `failed`).
275
273
  Assemble the evidence and **emit the canonical verdict artifact** — verification writes no task
276
274
  section (F92 0593 R1). Under the pipeline **you** write
277
275
  `.spur/run/<wbs>-verify-answer.txt` (0726 R3: host `expectFile`, never captured/overwritten); a
278
- deterministic shell step lints it and derives `.spur/run/<wbs>-verdict.json`, and `record`
276
+ deterministic shell step derives `.spur/run/<wbs>-verdict.json`, and `record`
279
277
  transcribes `## Testing` from it.
280
278
 
281
279
  **Standalone** (`/sp:dev-verify` outside the pipeline), write the artifact yourself, then invoke
@@ -284,40 +282,14 @@ the deterministic Testing writer `spur task record` (section authorship never ha
284
282
  ```bash
285
283
  # write .spur/run/<wbs>-verdict.json (shape in references/verdict-schema.md), then:
286
284
  spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json # renders ## Testing, flips proven boxes
287
- # F96 residual sweep (observe-only): scan + fold AFTER record, under every --fix mode (0987).
288
- spur task residual <wbs> scan
289
- spur task residual <wbs> fold
290
- # Downgrade only: re-record so Testing carries the final (folded) verdict.
291
- [ "$(jq -r .verdict .spur/run/<wbs>-verdict.json)" = PASS ] \
292
- || spur task record <wbs> --verdict-file .spur/run/<wbs>-verdict.json
293
285
  ```
294
286
 
295
- > **Residual fold (F96).** `scan` reads `.spur/run/` artifacts and the post-record task file and
296
- > writes `residuals.json` + `residual-report.md`; `fold` rewrites the verdict artifact's
297
- > `residual-sweep` check in place (PASS → PARTIAL when a blocking residual exists), and the
298
- > downgrade-only re-record transcribes it — a manual verify cannot certify what the pipeline would
299
- > reject. The sweep runs after `record` (same order as the pipeline, 0983/0987): before it, a
300
- > verdict-proven box is still unticked and a clean PASS would fold to PARTIAL. The sweep is the
301
- > `spur task residual` verb (no plugin script to resolve). When the task reaches `done` through
302
- > `--next`, run `spur task residual <wbs> settle` (files the follow-up task; best-effort).
303
-
304
287
  > **Corrections: the answer file is the source of truth.** `spur task record` re-transcribes
305
288
  > `## Testing` from the verdict artifact — direct `--section Testing` writes are futile. Fix
306
289
  > `.spur/run/<wbs>-verify-answer.txt` → `spur task verdict <wbs> --from-answer <file>` → re-record.
307
290
 
308
- > **Scenario-key carry-forward (standalone `--force` re-verifies).** When you author a fresh
309
- > verdict artifact for a task whose `## Testing` already carries feature scenario-title rows
310
- > (`Scenario: <title>` / `AC-N` keys with MET status), **copy those rows into the new artifact**
311
- > keyed the same way — record re-transcribes `## Testing` wholesale, so a fresh artifact keyed by
312
- > bare `R1`-style ids drops the scenario keys `spur feature check` needs for satisfaction
313
- > (`L4.scenario-unverified` regresses; 0921/D63). Since 0936, `record` warns on stderr (exit 0)
314
- > for each dropped MET-matched scenario key and when the new rows match no feature scenario —
315
- > treat those warnings as a re-key instruction, not noise.
316
-
317
- > **Keying rule for feature-linked tasks (1086/1089 re-audits).** Key AC rows by the exact feature
318
- > scenario title (`R1 — …`): feature `Scenario:` titles are declared identities and satisfy L4
319
- > scenario matching directly. Bare `AC1` fails `ac-identity` on Gherkin AC sections, and checklist
320
- > labels truncate at the first colon (a `(req: …)` suffix), so the task's own AC title may not resolve.
291
+ > **Keying rule for feature-linked tasks.** Key AC rows by the exact feature scenario title
292
+ > (`R1 — …`) or `AC-N`, so `record` can tick the aliased AC line.
321
293
 
322
294
  > **Do not write `## Review` directly, ever.** The `## Review` section is owned by the
323
295
  > `review` coordinator (`/sp:dev-review` → `sp:super-reviewer`), which merges
@@ -358,20 +330,18 @@ Verdict: PASS
358
330
  ```
359
331
 
360
332
  The per-requirement traceability table MUST use `| Req | Status | Evidence |` (exactly this header, no `R#`/`R`/`Requirement` variant — `Status` in column 2 — and no extra columns between Req and Status). The Acceptance Criteria table MUST use `| AC | Status | Evidence Type | Evidence |`.
361
- The answer MUST carry exactly one top-level `Confidence: HIGH|MEDIUM|LOW` line (ADR-141): the lint *derives* the level from your own rows and rejects a mismatch (`confidence-missing` / `-duplicate` / `-mismatch`), so state the level your evidence earns — `HIGH` needs every AC row MET on `test`/`command`, a citation-only row makes it `MEDIUM`. Full rule: [verdict-schema](references/verdict-schema.md).
362
- The answer MUST cite a source for external API/library claims in Requirement/AC evidence cells: a cell asserting a scoped-package (`@scope/name`), `node_modules/`, semver-version (`x.y.z`), or backticked function-call (`` `name(args)` ``) claim is rejected with `evidence-citation` unless the SAME cell carries a citation — a repo `path:line(-end)` (backticked or bare), the external named-origin form (@origin `path` line N), or a URL. Cross-cell references ("receipt above") do not count; marker-free receipts ("bun test 398 pass / 0 fail") need no citation.
333
+ Cite a source for external API/library claims in the SAME evidence cell (repo `path:line`, the external named-origin form, or a URL) — reviewer-enforced, not linted.
363
334
  **MUST NOT:** place a `Severity` column between `Req` and `Status`. The parser tolerates variants
364
335
  as defense-in-depth; this contract is canonical.
365
336
 
366
337
  Under the pipeline, the verifier owns the answer file `.spur/run/<wbs>-verify-answer.txt` (0726
367
338
  R3): `Verdict: PARTIAL` first, append one row at a time, replace the verdict line only when all
368
- rows are certified — interruptions leave lintable partial rows; retries fill only missing IDs.
369
- Host: `spur task verdict --from-answer` lints the answer file, then derives the verdict +
370
- `spur task check` (R9). Vocabularies,
371
- rejection classes, and the AC identity rule: `references/verdict-schema.md`. Sections follow the
339
+ rows are certified — interruptions leave usable partial rows; retries fill only missing IDs.
340
+ Host: `spur task verdict --from-answer` derives the verdict from the answer file, then runs
341
+ `spur task check` (R9). Vocabularies and the AC identity rule: `references/verdict-schema.md`. Sections follow the
372
342
  Step 10 contract.
373
343
 
374
- **Standalone** (outside the pipeline — no host lint/derive step), write the answer file and
344
+ **Standalone** (outside the pipeline — no host derive step), write the answer file and
375
345
  artifact yourself; shape and field-by-field contract in
376
346
  [references/verdict-schema.md](references/verdict-schema.md):
377
347
 
@@ -40,38 +40,6 @@ interface VerifyVerdict {
40
40
  }
41
41
  ```
42
42
 
43
- ## Answer confidence is derived and cross-checked (ADR-141, superseding F511 for answers)
44
-
45
- A verify answer carries exactly one top-level `Confidence: HIGH|MEDIUM|LOW` line — conventionally
46
- right after `Verdict:`, and legal anywhere at top level. The label is **not** a self-assessment: the
47
- lint recomputes it from the answer's own rows and rejects a disagreement.
48
-
49
- | Derived | When the answer's rows say so |
50
- | --- | --- |
51
- | `LOW` | the verdict is not PASS, or any requirement/AC row is PARTIAL/UNMET |
52
- | `HIGH` | PASS, and every AC row is MET on executable evidence (`test`/`command`; compounds allowed) |
53
- | `MEDIUM` | PASS with every AC MET, but at least one row rests on `static-ref`, `manual-review`, `llm-judge` or `N/A` |
54
-
55
- Rejections (`spur task verdict --from-answer`, exit 1, no artifact): `confidence-missing`,
56
- `confidence-duplicate`, `confidence-mismatch` — the last names both the stated and the derived level
57
- plus the clause the rows turn on. Derivation lives once, in
58
- `packages/app/src/services/answer-confidence.ts`; the review lane uses the same module for its own
59
- dispositions.
60
-
61
- Still retired and not revived by this: **verdict artifacts** carry no `confidence` field (the answer
62
- stays the record of truth, and a test pins the field's absence), feature-verification receipts keep
63
- no level (ADR-131, 1196), no operator `ackLowConfidence`-style var exists, and history-anatomy
64
- findings carry no per-finding grade. A verifier that can write a PASS can still write a wrong
65
- `HIGH` — which is exactly why the gate derives the level instead of trusting it.
66
-
67
- **A review run carries two answer artifacts, one `Confidence:` line each (1254).** The `## Review`
68
- section states the disposition-derived level (`deriveReviewConfidence`); the captured answer handed
69
- to `spur task verdict --from-answer` states the evidence-derived level (`deriveVerifyConfidence`)
70
- under the table above and carries exactly one `Confidence:` line. The two legitimately disagree — a
71
- PASS with executable AC and one carried P4 is section `MEDIUM`, answer `HIGH` — so the captured
72
- answer must not repeat the section's line (`confidence-duplicate` rejects the whole answer). The
73
- review stage's prompt owns that instruction; this schema owns the shape it must produce.
74
-
75
43
  ## Compatibility alias: `scenario` row key
76
44
 
77
45
  Task 0410 hardened the verdict reader. Producers SHOULD use the canonical `id` field for every
@@ -81,17 +49,7 @@ as a compatibility alias for the row identifier, with these rules:
81
49
  - Row with `id` only → canonical; accepted as-is.
82
50
  - Row with `scenario` only → accepted; normalized to `{ id: scenario, … }`.
83
51
  - Row with both `id` and `scenario` where they are EQUAL → `id` is authoritative; accepted.
84
- - Row with both `id` and `scenario` where they DIFFER or either value is not a string → **rejected**
85
- (conflict); the rejected row
86
- count and invalid fields surface as a bounded `L4.malformed-verdict-artifact` warning naming the
87
- task WBS and artifact path.
88
- - Row missing both `id` and `scenario`, or missing `status`, or not an object → rejected and warned.
89
-
90
- Empty `requirements` / `acceptanceCriteria` arrays are valid and produce no warning. The required
91
- `requirements` array being absent, either coverage field being a non-array value, a missing artifact,
92
- malformed JSON, and a non-object JSON root are distinct diagnostic outcomes. Each emits one bounded
93
- `L4.malformed-verdict-artifact` warning per task/artifact whose message names the failure mode;
94
- optional `acceptanceCriteria` may remain absent.
52
+ - Row with both `id` and `scenario` where they DIFFER, or a row missing both → ignored.
95
53
 
96
54
  Canonical producers and docs continue to use `id`. The `scenario` alias exists so older or
97
55
  third-party verdict emitters keyed on scenario titles are not silently dropped.
@@ -144,65 +102,28 @@ For answer files, emit a matching parseable table:
144
102
 
145
103
  **Authoring contract under the pipeline (0726 R3).** The verifier owns the answer file: write
146
104
  `Verdict: PARTIAL` first, append one complete row at a time, and replace the first verdict line only
147
- after every row is certified. `spur task verdict --from-answer` lints the file before deriving the
148
- verdict and rejects, with row-level diagnostics: missing/duplicate/unknown requirement IDs,
149
- AC ids that do not resolve to one accepted identity — a task AC checklist label or its declared
150
- `AC-N`/checklist-token alias, or a linked feature scenario title, in the ac-style-guide forms
151
- (exact/bare title, `Scenario:` prefix, bracket tags, `AC-N`); paraphrases and ambiguous aliases
152
- fail — invalid status (`MET | PARTIAL | UNMET` for requirements;
153
- `N/A` additionally allowed for AC), invalid evidence type (`test | command | static-ref |
154
- manual-review | llm-judge | n/a`, or a `+` compound), and empty evidence. Evidence cells that assert an
155
- external API/library claim without a same-cell citation are rejected with `evidence-citation` (see
156
- "Source citations for external claims" below). Interrupted runs keep the
157
- rows that pass the lint and complete only the missing IDs on retry.
158
-
159
- **Feature-credited AC ids are narrower than the lint's accepted set (task 0966 finding).** A row keyed
160
- by a bare checklist ordinal (`AC1`) passes the `spur task verdict` answer lint — it resolves to the task's AC
161
- checklist label — but `feature-check.rowMatchesScenario` credits a linked feature scenario only by the
162
- scenario's normalized title or its `AC-N` ordinal alias. Such a row therefore carries a PASS verdict
163
- while crediting no scenario, and the feature's `verifying → done` gate denies with
164
- `L4.scenario-unverified` / `L4.verdict-rows-match-no-scenario`. When the task has a linked feature,
165
- key each AC row `AC-N` (1-based scenario ordinal, hyphenated) or by the exact scenario title.
166
- A scenario-keyed row (`R3 — <title>`) ticks the task AC box whose line aliases that scenario
167
- (`- [ ] AC1 — R3 — <title>`) during `spur task record` (0996); a scenario key no AC line aliases
168
- ticks nothing, so alias every graduated scenario on its AC line.
169
-
170
- **Concrete anchors only (task 0804 R9).** An evidence anchor must be a concrete existing `file:line`
171
- (or `file:start-end`) path. A glob or directory summary (`src/services/*.ts`, `the retry
172
- classifiers in task-pipeline.yaml`) is not an anchor: expand it into the specific cited files/ranges
173
- the run actually verified. Since 0804 R9 the checker ignores complete parsed citation spans before
174
- scanning for subjects, so a citation's filename (including snake_case paths) can never become a
175
- false subject — a real absent symbol, nonexistent file, or invalid range still reports.
176
-
177
- ## Basename-only anchors are unresolved anchors (task 1110 R1)
178
-
179
- `spur task verdict --from-answer` accepts the citation *shape*, but the `--as done` gate resolves
180
- every Testing/Solution anchor against the repo root. A basename citation — `decision-events.ts:83`,
181
- `task.test.ts:42` — reports `L4.anchor-unresolved` at **error** and blocks
182
- `spur task update <wbs> done`, because the gate cannot tell which file the row meant. Write the
183
- repo-root-relative form from the first pass:
105
+ after every row is certified. `spur task verdict --from-answer` derives the verdict from that file;
106
+ nothing lints the rows, so their accuracy is the verifier's responsibility. Vocabularies: status
107
+ `MET | PARTIAL | UNMET` (`N/A` additionally allowed for AC); evidence type `test | command |
108
+ static-ref | manual-review | llm-judge | n/a`, or a `+` compound. Interrupted runs keep the rows
109
+ already written and complete only the missing IDs on retry.
110
+
111
+ **Key AC rows so `record` can tick them.** A scenario-keyed row (`R3 — <title>`, `AC-N`, or the exact
112
+ scenario title) ticks the task AC box whose line aliases that scenario (`- [ ] AC1 — R3 — <title>`)
113
+ during `spur task record` (0996); a key no AC line aliases ticks nothing.
114
+
115
+ **Concrete anchors only.** Cite a concrete existing repo-root-relative `file:line` (or
116
+ `file:start-end`), never a glob, directory summary or basename. Nothing resolves anchors
117
+ mechanically — a reviewer who cannot open the cited line treats the row as unproven.
184
118
 
185
119
  - Right: `packages/app/src/decision/decision-events.ts:83`, `apps/cli/tests/commands/task/verdict.test.ts:42`
186
120
  - Wrong: `decision-events.ts:83`, `../services/foo.ts:12`, `@gobing-ai/ts-x/src/persistence.ts:108`
187
121
  (a scoped package is never repo-relative — use the external named-origin form below)
188
122
 
189
- The pipeline's implement stage also runs a scoped `spur task migrate-anchors --wbs <wbs>` pass
190
- before the proof capture (task 1109), but it qualifies **unique** basenames only: an ambiguous
191
- basename (two tracked files share it) is reported and left untouched, and line drift and
192
- `L4.anchor-subject-mismatch` are never repaired by that pass — those remain the author's rows.
193
-
194
- A **workspace-relative** path fails the same way, and is the easier mistake to make because the
195
- command it came from is real. `(cd apps/cli && bun test tests/commands/builder/pr.test.ts)` is the
196
- right way to run the suite, but `tests/commands/builder/pr.test.ts` does not resolve from the repo
197
- root, so the AC-coverage guard reports `missing: <AC> — <path>` and refuses `done` (observed
198
- 2026-10-16, task 1215 — the repair was a fresh verify pass over the whole answer). Cite both halves:
199
- the workspace-rooted command you ran, then the repo-root-relative anchor of the file it names
200
- (`apps/cli/tests/commands/builder/pr.test.ts`). One anchor per cited file per cell is enough.
201
-
202
123
  ## Source citations for external claims (task 1070)
203
124
 
204
125
  A Requirement/AC evidence cell that asserts an external API/library claim must carry a verifiable
205
- citation in the SAME cell, or lint rejects the row with `evidence-citation` (blocking derivation).
126
+ citation in the SAME cell. Nothing machine-checks this — the reviewer enforces it.
206
127
 
207
128
  - Claim markers (closed set): a scoped-package mention (`@scope/name`), a `node_modules/` reference,
208
129
  a semver version claim (`x.y.z`), or a backticked function-call-shaped token (`` `name(args)` ``).
@@ -212,27 +133,6 @@ citation in the SAME cell, or lint rejects the row with `evidence-citation` (blo
212
133
  - The rule is cell-local: a citation in another row or a "receipt above" cross-reference does not
213
134
  satisfy it. Marker-free receipts (test counts, reviewed-log notes) need no citation. The check is
214
135
  presence-only — which citation proves which claim is not deterministically decidable.
215
- - The same two predicates (`hasClaimMarker` / `hasCitationForm` in
216
- `packages/app/src/services/verify-answer-lint.ts`) gate the review report's findings table through
217
- `spur task residual <wbs> review-gate` as the blocking `review-contract` category — one definition of
218
- "external claim" and one set of accepted citation forms for both paths.
219
-
220
- ## Hedged evidence is rejected on MET rows
221
-
222
- A MET row asserts the requirement is satisfied; evidence that hedges ("the guard likely prevents
223
- the leak") contradicts the assertion the row is making. The lint rejects such rows with
224
- `evidence-hedged`, naming the detected phrase, with two remedies: state the deterministic fact
225
- with a concrete anchor, or downgrade the row to PARTIAL (which is what suspected-but-unproven
226
- behavior actually is).
227
-
228
- - Detected phrases (closed set, word-anchored, case-insensitive): `likely`, `unlikely`,
229
- `probably`, `presumably`, `apparently`, `seems/seeming/seemingly to`, `appears to`. Modal verbs
230
- (`might`/`may`/`could`/`should`) are deliberately out of set — they are constant in remediation
231
- prose and would drown the signal.
232
- - Only MET rows are scanned. Hedging a gap in an UNMET row ("the stale path likely still loads
233
- the old bundle") is honest reporting and stays clean.
234
- - Citation spans are stripped before scanning, so a filename or test name containing a hedge
235
- word (`likely-match.test.ts`) cannot fire.
236
136
 
237
137
  ## Checks evidence
238
138
 
@@ -245,14 +145,13 @@ Wave C verification can emit the following additive `checks[]` rows:
245
145
  | `evidence-rule-pass` | All behavior-bearing AC rows had executable evidence or were explicitly non-behavioral. |
246
146
  | `evidence-rule-failed` | One or more MET behavior-bearing AC rows lacked `test` / `command` evidence and were downgraded to PARTIAL. |
247
147
  | `cli-golden-path-present` | CLI-surface tasks supplied, or failed to supply, one golden-path command evidence row. |
248
- | `residual-sweep` | Post-verdict residual scan (F96): `fail` when blocking leftovers exist (P1–P3 findings, added diff markers, unchecked boxes); evidence lists blocking/deferrable/advisory/housekeeping counts plus blocking and deferrable item ids. A `fail` downgrades an otherwise-PASS verdict to PARTIAL via the fold step. |
249
148
 
250
149
  ## How the gate reads it
251
150
 
252
151
  In `task-pipeline.yaml` the `review` state writes this artifact: `spur task verdict <wbs>
253
- --from-answer` lints the review answer and derives `.spur/run/<wbs>-verdict.json`. A fold step then
254
- writes `.spur/run/<wbs>-review.status` = PASS only when the typed verdict is PASS, the artifact's own
255
- `verdict` is PASS (`jq -r '.verdict // empty'`) and `spur task residual <wbs> review-gate` is clean.
152
+ --from-answer` derives `.spur/run/<wbs>-verdict.json` from the review answer. A fold step then
153
+ writes `.spur/run/<wbs>-review.status` = PASS only when the typed verdict is PASS and the artifact's
154
+ own `verdict` is PASS (`jq -r '.verdict // empty'`).
256
155
  The `review → done` guard reads that status **and** the approval decision point's token:
257
156
 
258
157
  ```yaml
@@ -316,7 +316,7 @@ spur task check <wbs> --json
316
316
  ```
317
317
 
318
318
  Must return `pass: true` with 0 errors. Warnings may be acceptable on meta tasks
319
- (e.g. `prose-prerequisite-unlisted`, `uncovered-task-scenario`).
319
+ (e.g. `uncovered-task-scenario`).
320
320
 
321
321
  ## Output
322
322
 
@@ -119,13 +119,6 @@ token, deterministic).
119
119
  | C3 | A5/A6 when Testing empty/N/A **and** verify would fail for missing tests — only if prior implement claims code exists | Coverage/test signal: `bun test` fail attributed to task paths OR explicit "insufficient tests" in prior verify verdict artifact `.spur/run/<wbs>-verdict.json` | test fail / coverage gap | `/sp:dev-unit <wbs> --auto` | continue |
120
120
  | C4 | A3/A5/A6 when operator or task tags mention rules, OR `spur rule run` last report dirty in `.spur/` if present | `spur rule run` (default project preset) non-zero with findings | rule findings | **HITL STOP** — print rule summary; suggest `/sp:rule-scan` or `rule-add`/`rule-refine` (do not auto-author rules) | continue |
121
121
  | C5 | A6 only | Existing `.spur/run/<wbs>-verdict.json` with FAIL and findings pointing at coverage | verdict artifact | `/sp:dev-unit <wbs>` then re-verify on next invocation (`--once` friendly) | `/sp:dev-verify …` |
122
- | C6 | A4/A5 | `.spur/run/<wbs>-verdict.json` has a failing (PARTIAL/FAIL) `residual-sweep` check — residual blockers survived the pipeline sweep (F96) | folded verdict artifact | **HITL STOP** — print `.spur/run/<wbs>-residual-report.md` and the recovery command `/sp:dev-run <wbs>`; never auto-dispatch a fix (repeating the loop unattended burns quota without new information) | continue |
123
-
124
- **C-row precedence note (F96):** C6 outranks C2/C3/C5 for the same task — a residual-sweep failure
125
- means the workspace holds unfinished task residue, so fixall/unit reruns would either clean it
126
- unintentionally or re-certify a folded verdict. C6 fires before any fix/unit dispatch; recovery is
127
- the operator re-running the pipeline (`/sp:dev-run <wbs>`), which re-enters the normal
128
- gate ⇄ remediate budget.
129
122
 
130
123
  **Explicit non-probes in v1:** no freeform chat history; no always-on full `bun run test` for every
131
124
  call; no git dirtiness as a route (optional advisory print only).
@@ -562,12 +562,7 @@ schema before emitting.
562
562
 
563
563
  **Pass the deterministic task check.** Each `acceptance_criteria` bullet must be an exact feature
564
564
  scenario title (L4.uncovered-task-scenario); add task-local checks as prose after the bullets, not
565
- as extra bullets. No section body may use `HITL`, `merge event`, `content-gate`, `GATED`, or
566
- `capstone` as standalone words in any case (L4.gate-language) — dotted action kinds such as
567
- `hitl.confirm` are fine, a bare `hitl` count is not; ambiguous words (`approval`, `approved`,
568
- `merged`) warn only with a gating cue (`until`, `after`, `once`, `before`, `pending`, `blocked`,
569
- `wait for`, `requires`) in the same sentence, so plain composition prose stays silent — say
570
- "operator answer" / "accepted" instead, and keep enum values out of that list too.
565
+ as extra bullets.
571
566
 
572
567
  **The order sidecar.** Also emit the private task-order sidecar at
573
568
  `.spur/run/<runId>-idea-task-order.json`: a JSON array (one entry per batch item) of
@@ -25,7 +25,7 @@ Decisions resolve first-wins across three layers:
25
25
  | `registered` | folders listed in config `decisions.paths` | Operator-added catalogs |
26
26
  | `shared` | `decisions/` under the bundled config root | Shipped catalogs (`config/decisions/` in-repo) |
27
27
 
28
- The bundled shared catalog ships `task-semantic-risk`, `failure-class`,
28
+ The bundled shared catalog ships `failure-class`,
29
29
  `gate-evidence`, `idea-recommendation`, `needs-design`, `anatomy-validation-verdict` and
30
30
  `maker-liveness` (the last served only by `spur decision status --probe`; no workflow references
31
31
  it). Layers win **per file basename** (a project `gates.yaml` replaces the shipped `gates.yaml`
@@ -84,8 +84,7 @@ row lands in `system_events` beside `decision.end`, on the same `run_id`, so the
84
84
  **Scoring one.** `decisions.outcomeMap` in config (project or global layer) holds Spur's reading of
85
85
  Spur's own artifacts — per decision id, which recorded outcomes count as correct for each served
86
86
  value (`String(value)` keys, so a yes/no decision uses `"true"`/`"false"`). The shipped defaults
87
- score `failure-class` (`fix` → `fixed`, `stop` → `not-fixed`) and `task-semantic-risk`
88
- (`"false"` → `none`/`p4`/`p3`, `"true"` → `p1`/`p2`).
87
+ score `failure-class` (`fix` → `fixed`, `stop` → `not-fixed`).
89
88
 
90
89
  `spur decision status --reliability` then reports, per (decision × maker) group:
91
90
 
@@ -237,9 +236,7 @@ guards: [decision/lifecycle.md](decision/lifecycle.md) §1, §3.
237
236
 
238
237
  ```bash
239
238
  spur decision list --json | jq -r '.[].id'
240
- spur decision show task-semantic-risk # inspect contract before serving
241
- spur decision run task-semantic-risk --param wbs=1093 \
242
- --evidence .spur/run/1093-diffstat.json --evidence docs/tasks/1093_*.md --json
239
+ spur decision show failure-class # inspect contract before serving
243
240
  spur decision run failure-class --param wbs=1093 \
244
241
  --evidence .spur/run/<runId>-test-output.txt # redacted evidence -> instructions
245
242
  spur decision status --json | jq '.loadErrors' # audit catalog health
@@ -256,32 +256,6 @@ the active tasks folder (or `--folder`).
256
256
  | `--folder <path>` | Custom tasks folder. |
257
257
  | `--json` | Machine-readable report envelope. |
258
258
 
259
- ## `migrate-anchors`
260
-
261
- Qualify in-repo evidence anchors to repo-relative paths across the task corpus. Run
262
- `--dry-run` first: unambiguous matches are reported in `qualified`, multiple matches in `ambiguous`
263
- without rewriting, and schema-incompatible files in `skipped`. The write path uses the planning
264
- service rather than raw file edits.
265
-
266
- **`done_reason` scratch pointers are retargeted** (task 1140, ADR-131): a `.spur/run/<wbs>-verdict.json`
267
- or `.spur/run/<wbs>/verdict.json` substring becomes `.spur/memory/evidence/<wbs>-verdict.json` when
268
- that copy exists, else `tracked Testing section (scratch verdict not retained)` when Testing is
269
- non-empty; otherwise the value is left unchanged and reported in `doneReasonUnresolved`. Each
270
- `doneReasons` row carries `kind` (`absolute-path` | `durable-evidence` | `tracked-testing`). This is
271
- the repair for the `no-scratch-verdict-pointer` rule.
272
-
273
- **`--wbs <wbs>` scopes the pass to one task file** (task 1109 R1) — the wbs is resolved through the
274
- task locator and exactly that file is scanned, so the pipeline's implement stage can auto-repair a
275
- task's unique basename anchors without the corpus-wide pass rewriting unrelated files (the unscoped
276
- apply rewrote 119 on 2026-10-07). An unknown wbs exits `1` with an actionable message and writes
277
- nothing. Ambiguous basenames are still reported and left untouched in scoped mode.
278
-
279
- ```bash
280
- spur task migrate-anchors --dry-run --json
281
- spur task migrate-anchors --json
282
- spur task migrate-anchors --wbs 1109 --json # one task file only
283
- ```
284
-
285
259
  ## `resolve <file-path>`
286
260
 
287
261
  Map a file path to its **owning task** — returns the WBS + task file. Strategies, in order: direct
@@ -454,7 +428,6 @@ spur task sections <wbs> <init|add|list> [name] [--folder] [--json]
454
428
  spur task list [--status <s>] [--phase <p>] [--parent <wbs>] [--feature <id>] [--folder] [--json]
455
429
  spur task refresh [--folder] [--json]
456
430
  spur task migrate [--dry-run] [--folder] [--json]
457
- spur task migrate-anchors [--wbs <wbs>] [--dry-run] [--json]
458
431
  spur task refresh-roster <wbs> [--folder] [--json]
459
432
  spur task batch-create --file <path> [--skip-ready | --agent <selector>] [--folder] [--json]
460
433
  spur task record <wbs> [--verdict-file <p>] [--solution-from-diff] [--transition <s>] [--folder] [--json]
@@ -466,7 +439,6 @@ spur task path <wbs> [--folder] [--json]
466
439
  spur task run-link <wbs> [--source <src>] [--run-id <id>] [--json]
467
440
  spur task scaffold-tests <wbs> [--file <path>] [--folder] [--json]
468
441
  spur task gate <wbs> <run|recheck|light|deferred|status> [--cmd <c>] [--probe-cmd <c>] [--run-id <id>]
469
- spur task residual <wbs> <scan|review-gate|fold|settle|report> [--root <dir>] [--tmp-dir <dir>] [--folder]
470
442
  spur task diffstat <wbs>
471
443
  ```
472
444
 
@@ -72,11 +72,16 @@ mode; `batch-create` surfaces per-child `warnings` rows (`[{"wbs", "warnings"}]`
72
72
  when non-empty) in `--json` and prints `<wbs>: <warning>` lines to stderr in human mode;
73
73
  `update --section` section writes carried this advisory already.
74
74
 
75
+ When an advisory fires, split the task instead of growing it: decompose into smaller tasks before
76
+ pipeline execution (execution-workflow.md, "Split oversized tasks before pipeline execution").
77
+ `create --requirements/--plan` and `batch-create` body fields exist to author the split tasks'
78
+ content up front — not to accumulate more into one oversized task.
79
+
75
80
  ## Verb map
76
81
 
77
82
  | Verb | Purpose | Key flags |
78
83
  | ---- | ------- | --------- |
79
- | `create <title>` | Allocate a new task (race-safe WBS) | `--feature <id>` `--no-reopen` `--parent <wbs>` `--template <variant>` `--dedupe-within <s>` `--allow-duplicate-name` `--skip-ready` `--agent <selector>` `--folder` `--json` |
84
+ | `create <title>` | Allocate a new task (race-safe WBS) | `--feature <id>` `--no-reopen` `--parent <wbs>` `--template <variant>` `--requirements <text>` `--plan <text>` `--dedupe-within <s>` `--allow-duplicate-name` `--skip-ready` `--agent <selector>` `--folder` `--json` |
80
85
  | `show <wbs>` | Print one task's frontmatter + body; section-filtered or summary mode (1325) | `--section <name>` `--sections <csv>` `--summary` `--folder` `--json` |
81
86
  | `update <wbs> [status]` | Lifecycle transition, section replace, **or** frontmatter set | `--section <name> --from-file <path>` `--assignee <spec-id>` (exclusive with `--section`) `--feature <id>` `--no-reopen` `--priority <p>` `--ac-numbering task-local` `--ac-altitude <a>` `--estimate-hours <n>` `--no-lifecycle` `--force-done` `--reason <text>` `--provenance-bypass` `--verdict-dir <path>` `--folder` `--json` |
82
87
  | `deps <wbs> <op> [values...]` | Mutate `dependencies[]` frontmatter array (ops: `set`, `add`, `remove`, `clear`) | `--folder` `--json` |
@@ -84,7 +89,6 @@ when non-empty) in `--json` and prints `<wbs>: <warning>` lines to stderr in hum
84
89
  | `list` | List tasks, filtered | `--status <s>` `--phase <p>` `--parent <wbs>` `--feature <id>` `--folder` `--json` |
85
90
  | `refresh` | Re-scan the corpus and report counts (**`kanban.md` retired** — web Task Kanban is SSOT) | `--folder` `--json` |
86
91
  | `migrate` | One-time A17 corpus normalization pass | `--dry-run` `--folder` `--json` |
87
- | `migrate-anchors` | Qualify in-repo evidence anchors to repo-relative paths (0583 R1–R3); `--wbs` scopes to one task file (1109 R1); retargets scratch `done_reason` verdict pointers (1140) | `--wbs` `--dry-run` `--json` |
88
92
  | `refresh-roster <wbs>` | Regenerate a parent task's sub-task roster block in `## Plan` | `--folder` `--json` |
89
93
  | `batch-create` | Create many tasks from a validated JSON array | `--file <path>` `--skip-ready` `--agent <selector>` `--folder` `--json` |
90
94
  | `batch-plan <mode>` | Batch plan projection: `waves` / `order` (JSON on stdout; the batch driver's visible plan) | `--tasks <file>` `--concurrency <n>` |
@@ -100,13 +104,11 @@ when non-empty) in `--json` and prints `<wbs>: <warning>` lines to stderr in hum
100
104
  | `verifyall-aggregate` | Aggregate per-task verify outcomes into a batch verdict (NOT-STARTED excluded) | `--from-file <path>` `--json` |
101
105
  | `scaffold-tests <wbs>` | Generate BDD test stubs from task Acceptance Criteria | `--file <path>` `--folder` `--json` |
102
106
  | `gate <wbs> <mode>` | Task-pipeline quality gate (`run`, `recheck`, `light`, `deferred`, `status`); mode-specific exits and git-tree-keyed receipts (see `sp:spur-check`) | `--cmd <c>` `--probe-cmd <c>` `--run-id <id>` |
103
- | `residual <wbs> <step>` | F96 residual sweep step (`scan`, `review-gate`, `fold`, `settle`, `report`) | `--root <dir>` `--tmp-dir <dir>` `--folder` |
104
107
  | `diffstat <wbs>` | Write the triage diffstat artifact against the run base (fails safe to `sensitive: true`) | — |
105
108
 
106
109
  Use only the flags listed for the selected verb. `batch-plan` emits JSON without `--json`;
107
- `wrapup`, `gate`, `residual` and `diffstat` use their operation-specific stdout/artifact contracts.
108
- `run-link`, `verifyall-aggregate` and `migrate-anchors` accept `--json` but no `--folder`;
109
- `residual` accepts `--folder` but no `--json`. Do not append shared flags to every command.
110
+ `wrapup`, `gate` and `diffstat` use their operation-specific stdout/artifact contracts.
111
+ `run-link` and `verifyall-aggregate` accept `--json` but no `--folder`. Do not append shared flags to every command.
110
112
  General exit codes are `0` success, `1` error, `2` invalid usage; consult the operation contract
111
113
  for soft gate modes and specialized refusal codes.
112
114
 
@@ -198,7 +200,7 @@ refused (ready-set resolver and pipeline preflight), and a live dependent is rep
198
200
  reported, never rewritten.
199
201
 
200
202
  Writes that stay **permitted** on a `deprecated` task (each edits the record rather than declaring
201
- the work resumable): `spur task record`, `migrate-anchors` and verdict writes, and
203
+ the work resumable): `spur task record` and verdict writes, and
202
204
  `spur task update <wbs> --section <any>` — the section write lands and returns a freeze warning.
203
205
 
204
206
  **`--no-lifecycle`** suppresses lifecycle workflow *run record* creation (use during pipeline-driven