@gobing-ai/spur 0.4.3 → 0.4.5

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 (119) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/rules/docs/sourced-api-claims.yaml +3 -2
  3. package/config/rules/quality/coverage-gate.yaml +13 -0
  4. package/config/rules/recommended-pre-check.yaml +11 -5
  5. package/config/rules/strict/runtime-boundaries.yaml +3 -0
  6. package/config/rules/surface/check-cli-surface.yaml +1 -3
  7. package/config/templates/AGENTS.md +7 -0
  8. package/config/workflows/feature-verification.yaml +9 -1
  9. package/config/workflows/task-lifecycle.yaml +50 -0
  10. package/config/workflows/task-pipeline.yaml +31 -65
  11. package/package.json +10 -10
  12. package/plugins/sp/agents/super-reviewer.md +11 -24
  13. package/plugins/sp/commands/dev-changelog.md +1 -1
  14. package/plugins/sp/commands/dev-gitmsg.md +6 -2
  15. package/plugins/sp/commands/dev-handover.md +1 -0
  16. package/plugins/sp/commands/dev-job-dump.md +2 -1
  17. package/plugins/sp/commands/dev-refine.md +14 -2
  18. package/plugins/sp/commands/dev-refineall.md +7 -1
  19. package/plugins/sp/commands/dev-review.md +1 -0
  20. package/plugins/sp/lib/history-anatomy.generated.mjs +18 -18
  21. package/plugins/sp/lib/idea-handoff.generated.mjs +91 -91
  22. package/plugins/sp/lib/inline-run.generated.mjs +233 -277
  23. package/plugins/sp/lib/plan-projection.generated.mjs +62 -38
  24. package/plugins/sp/lib/quality-gate.generated.d.mts +1 -0
  25. package/plugins/sp/lib/quality-gate.generated.mjs +13793 -13966
  26. package/plugins/sp/lib/residual-scan.generated.mjs +20 -34
  27. package/plugins/sp/lib/step-profile.generated.mjs +8 -8
  28. package/plugins/sp/plugin.json +1 -1
  29. package/plugins/sp/scripts/batch-plan.mjs +62 -40
  30. package/plugins/sp/scripts/batch-preflight.mjs +34 -12
  31. package/plugins/sp/scripts/commit-guard.mjs +6 -6
  32. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +26 -28
  33. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +11 -11
  34. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +4 -4
  35. package/plugins/sp/scripts/feature-verification-steps.mjs +15 -4
  36. package/plugins/sp/scripts/feature-verification-steps.ts +29 -1
  37. package/plugins/sp/scripts/history-anatomy-cache.mjs +19 -19
  38. package/plugins/sp/scripts/idea-handoff.mjs +2 -2
  39. package/plugins/sp/scripts/inline-run-dispatch.mjs +2 -2
  40. package/plugins/sp/scripts/inline-run-setup.mjs +20 -20
  41. package/plugins/sp/scripts/persist-out-check.mjs +5 -5
  42. package/plugins/sp/scripts/pr-reviewing.mjs +13 -13
  43. package/plugins/sp/scripts/quality-gate.mjs +13715 -13884
  44. package/plugins/sp/scripts/residual-scan.mjs +24 -38
  45. package/plugins/sp/scripts/residual-scan.ts +4 -6
  46. package/plugins/sp/scripts/run-summary.mjs +15 -15
  47. package/plugins/sp/scripts/script-root.mjs +6 -6
  48. package/plugins/sp/scripts/session-timeline.mjs +16 -16
  49. package/plugins/sp/scripts/task-diffstat.mjs +8 -8
  50. package/plugins/sp/scripts/workflow-step-profile.mjs +12 -12
  51. package/plugins/sp/scripts/wrapup-drift-probe.mjs +9 -9
  52. package/plugins/sp/scripts/wrapup-steps.mjs +25 -25
  53. package/plugins/sp/skills/code-verification/SKILL.md +1 -2
  54. package/plugins/sp/skills/code-verification/references/verdict-schema.md +11 -32
  55. package/plugins/sp/skills/next-router/SKILL.md +3 -1
  56. package/plugins/sp/skills/next-router/references/routing-table.md +9 -3
  57. package/plugins/sp/skills/spur-cli/references/tasks.md +24 -4
  58. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +8 -1
  59. package/plugins/sp/skills/spur-dev/references/dev-operations.md +37 -11
  60. package/plugins/sp/skills/spur-dev/references/execution-batch.md +6 -3
  61. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +7 -11
  62. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +4 -2
  63. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +29 -8
  64. package/schemas/section-matrix.schema.json +3 -2
  65. package/spur.js +24597 -32769
  66. package/web/_astro/{BoardApp.5IIl2O-z.js → BoardApp.Niubpe6z.js} +1 -1
  67. package/web/_astro/{BoardApp.Drnx-KeM.js → BoardApp.hF0RAIrg.js} +112 -112
  68. package/web/_astro/TaskDetail.DJpapt38.js +1 -0
  69. package/web/_astro/{arc.j2EVkYVd.js → arc.BgKcK0i8.js} +1 -1
  70. package/web/_astro/{architectureDiagram-3BPJPVTR.DZWSFqEG.js → architectureDiagram-3BPJPVTR.ChP-Ig0V.js} +1 -1
  71. package/web/_astro/{blockDiagram-GPEHLZMM.DE6GpXCN.js → blockDiagram-GPEHLZMM.BVaCBoeN.js} +1 -1
  72. package/web/_astro/{c4Diagram-AAUBKEIU.DoVR1G6B.js → c4Diagram-AAUBKEIU.CHSDpEO5.js} +1 -1
  73. package/web/_astro/channel.DkpvN2tD.js +1 -0
  74. package/web/_astro/{chunk-2J33WTMH.Do6-Gbyf.js → chunk-2J33WTMH.MYRcYVRa.js} +1 -1
  75. package/web/_astro/{chunk-4BX2VUAB.BYV1HGHx.js → chunk-4BX2VUAB.S5j22Zqa.js} +1 -1
  76. package/web/_astro/{chunk-55IACEB6.CvI1zkrc.js → chunk-55IACEB6.gciRPvmZ.js} +1 -1
  77. package/web/_astro/{chunk-727SXJPM.DNGSCRlX.js → chunk-727SXJPM.CdqrSQkX.js} +1 -1
  78. package/web/_astro/{chunk-AQP2D5EJ.DXhhgT5z.js → chunk-AQP2D5EJ.CyokdHT3.js} +1 -1
  79. package/web/_astro/{chunk-FMBD7UC4.dzkRKP2u.js → chunk-FMBD7UC4.Bg9KJhjW.js} +1 -1
  80. package/web/_astro/{chunk-ND2GUHAM.DujGLeEf.js → chunk-ND2GUHAM.1gxxI-vD.js} +1 -1
  81. package/web/_astro/{chunk-QZHKN3VN.BWtIT3ZU.js → chunk-QZHKN3VN.DDEYtCKU.js} +1 -1
  82. package/web/_astro/{classDiagram-4FO5ZUOK.DyApg0Nn.js → classDiagram-4FO5ZUOK.Ch3zi37T.js} +1 -1
  83. package/web/_astro/{classDiagram-v2-Q7XG4LA2.DyApg0Nn.js → classDiagram-v2-Q7XG4LA2.Ch3zi37T.js} +1 -1
  84. package/web/_astro/{cose-bilkent-S5V4N54A.DJQB-u_l.js → cose-bilkent-S5V4N54A.D2q5AINI.js} +1 -1
  85. package/web/_astro/{cynefin-OW5HDTMX.bi3D_siV.js → cynefin-OW5HDTMX.BA9kC2YT.js} +1 -1
  86. package/web/_astro/{dagre-BM42HDAG.C-f7TrRg.js → dagre-BM42HDAG.CHO08nRp.js} +1 -1
  87. package/web/_astro/{diagram-2AECGRRQ.DrPfjHQB.js → diagram-2AECGRRQ.BfFQt0LW.js} +1 -1
  88. package/web/_astro/{diagram-5GNKFQAL.C9S4WUHO.js → diagram-5GNKFQAL.CHMwMTe4.js} +1 -1
  89. package/web/_astro/{diagram-KO2AKTUF.Dzzye8QH.js → diagram-KO2AKTUF.BJ-7gK-w.js} +1 -1
  90. package/web/_astro/{diagram-LMA3HP47.DX-LRiof.js → diagram-LMA3HP47.C5xqcc0t.js} +1 -1
  91. package/web/_astro/{diagram-OG6HWLK6.Z-kAKwIz.js → diagram-OG6HWLK6.C2pQjfrC.js} +1 -1
  92. package/web/_astro/{erDiagram-TEJ5UH35.D6dyClSv.js → erDiagram-TEJ5UH35._FoNyxgC.js} +1 -1
  93. package/web/_astro/{flowDiagram-I6XJVG4X.Cx3q2cxD.js → flowDiagram-I6XJVG4X.B_ENkT2I.js} +1 -1
  94. package/web/_astro/{ganttDiagram-6RSMTGT7.DU3gH6CT.js → ganttDiagram-6RSMTGT7.B3q8h77C.js} +1 -1
  95. package/web/_astro/{gitGraphDiagram-PVQCEYII.ISmCnJ87.js → gitGraphDiagram-PVQCEYII.QWZFDboZ.js} +1 -1
  96. package/web/_astro/index.BFyW13JJ.css +1 -0
  97. package/web/_astro/{infoDiagram-5YYISTIA.DR6_iNOK.js → infoDiagram-5YYISTIA.Cs6eEc92.js} +1 -1
  98. package/web/_astro/{ishikawaDiagram-YF4QCWOH.D7wY-ZGA.js → ishikawaDiagram-YF4QCWOH.BU9DJMHA.js} +1 -1
  99. package/web/_astro/{journeyDiagram-JHISSGLW.DkP9-WK8.js → journeyDiagram-JHISSGLW.D35k6Jpe.js} +1 -1
  100. package/web/_astro/{kanban-definition-UN3LZRKU.wtgY98M2.js → kanban-definition-UN3LZRKU.DBqcAT4m.js} +1 -1
  101. package/web/_astro/{linear.CI6djNi7.js → linear.D-LSNK8W.js} +1 -1
  102. package/web/_astro/{mermaid.core.CuQPxS8b.js → mermaid.core.CSruWVOa.js} +4 -4
  103. package/web/_astro/{mindmap-definition-RKZ34NQL.5HNIEG7R.js → mindmap-definition-RKZ34NQL.BiFaUsfj.js} +1 -1
  104. package/web/_astro/{pieDiagram-4H26LBE5.CchhDFjE.js → pieDiagram-4H26LBE5.D1KTKqb9.js} +1 -1
  105. package/web/_astro/{quadrantDiagram-W4KKPZXB.PYXXJPSJ.js → quadrantDiagram-W4KKPZXB.DBHflsMG.js} +1 -1
  106. package/web/_astro/{requirementDiagram-4Y6WPE33.cUQuNAKU.js → requirementDiagram-4Y6WPE33.hwX9CNdk.js} +1 -1
  107. package/web/_astro/{sankeyDiagram-5OEKKPKP.BO7MnRIA.js → sankeyDiagram-5OEKKPKP.DkI8mJiE.js} +1 -1
  108. package/web/_astro/{sequenceDiagram-3UESZ5HK.D9bElyD6.js → sequenceDiagram-3UESZ5HK.DMz7jBDx.js} +1 -1
  109. package/web/_astro/{stateDiagram-AJRCARHV.DhGdRz7I.js → stateDiagram-AJRCARHV.B6Ef2xJ1.js} +1 -1
  110. package/web/_astro/{stateDiagram-v2-BHNVJYJU.5GvLeAoL.js → stateDiagram-v2-BHNVJYJU.CgoaufB9.js} +1 -1
  111. package/web/_astro/{timeline-definition-PNZ67QCA.LtAT9haM.js → timeline-definition-PNZ67QCA.B3c8h1t-.js} +1 -1
  112. package/web/_astro/{vennDiagram-CIIHVFJN.DRth1yLA.js → vennDiagram-CIIHVFJN.BdHPAxAb.js} +1 -1
  113. package/web/_astro/{wardleyDiagram-YWT4CUSO.h9MlZfcr.js → wardleyDiagram-YWT4CUSO.BrJXPPAj.js} +1 -1
  114. package/web/_astro/{xychartDiagram-2RQKCTM6.DHqy9DYA.js → xychartDiagram-2RQKCTM6.CMH5yFsV.js} +1 -1
  115. package/web/index.html +2 -2
  116. package/web/spur_logo.svg +1 -1
  117. package/web/_astro/TaskDetail.Ci4LNn9S.js +0 -1
  118. package/web/_astro/channel.DmdDxGsq.js +0 -1
  119. package/web/_astro/index.Do2lLdgo.css +0 -1
@@ -79,7 +79,7 @@ each would be scope creep for one-liner procedures.
79
79
  | 6 | plan | `dev-plan` | `Skill()` | inline driver (`idea-pipeline`) or async workflow | `"<description>" [--feature <id>] [--parent <feature-id>] [--skip-design] [--agent <inline\|auto\|name>] [--auto]` |
80
80
  | 7 | docs | _(no thin wrapper)_ | `Skill()` | `sp:doc-evolve` | `"<change description>"` |
81
81
  | 8 | changelog | `dev-changelog` | `inline` | git log + conventional-commit grouping | `[<file>] [--since <ref>] [--until <ref>] [--version <ver>]` |
82
- | 9 | gitmsg | `dev-gitmsg` | `inline` | bounded diff capture → concern grouping → conventional commit | `[--commit] [--squash] [--all] [--scope <path>]` |
82
+ | 9 | gitmsg | `dev-gitmsg` | `inline` | bounded diff capture → concern grouping → conventional commit | `[--commit] [--squash] [--all] [--scope <path>] [--check <cmd>]` |
83
83
  | 10 | fixall | `dev-fixall` | `inline` | lint + test fix loop | `[<validation-command>] [--max-retry <n>] [--scope <path>] [--gate-log <path>] [--findings <anchors>]` |
84
84
  | 11 | handover | `dev-handover` | `inline` | structured doc generation | `"<blocker description>"` |
85
85
  | 11a | job-dump | `dev-job-dump` | `Skill()` | `sp:spur-dev` (`job-dump`) | `--file <path>` |
@@ -250,7 +250,8 @@ check receipt (`receipt.runId === runId`), otherwise `n/a (<reason>)`. Any value
250
250
  checklist** against target sections (read codebases, ADRs, dependent WBS, dogfood evidence as
251
251
  needed). If any item fails, synthesize and rewrite via CLI-gated section updates until all pass
252
252
  (or surface a blocked Q&A with a concrete question). Outcome vocabulary: `refined` (wrote) |
253
- `ready` (checklist already met, no write — optional alias of refined with zero writes) | `failed`.
253
+ `ready` (checklist already met, no write — optional alias of refined with zero writes) |
254
+ `cancelled` (issue triage found no valid issue — see `premises`) | `failed`.
254
255
  Prefer reporting `refined` when any section changed; if checklist already fully met, emit:
255
256
 
256
257
  ```
@@ -295,6 +296,17 @@ check receipt (`receipt.runId === runId`), otherwise `n/a (<reason>)`. Any value
295
296
  list`, `spur task list --status wip --json`) are recorded in References/Design.
296
297
  - **Scope** — the work is not already done, and not owned by another task.
297
298
 
299
+ **Issue triage.** When the task bundles several issues (findings, defects, R-items with their
300
+ proposed fixes), judge each one separately as `valid` (reproduced or confirmed in the current
301
+ tree), `already-fixed`, `owned-elsewhere` (name the WBS) or `invalid` (premise false). An issue
302
+ that is not `valid` is removed **with everything that exists only for it**: its Background
303
+ paragraph, R-items, Design/Solution notes, Plan steps and ACs. Renumber nothing that other
304
+ tasks or feature scenarios cite; leave a gap instead. Each removal is one correction-record
305
+ line. When **no** issue stays valid, do not rewrite the task. Record the triage in the
306
+ correction block, then `spur task update <wbs> cancelled --json`, and report outcome
307
+ `cancelled`. Cancelling is not demotion; it is valid only within the backlog/todo status scope
308
+ above.
309
+
298
310
  Contradictions are corrected in **this** refine (rewrite the claim, or re-point the design at
299
311
  ground truth), never deferred to the implementer. `--depth ready` exists so a downstream agent
300
312
  does not re-derive the analysis; a frozen design built on a false premise is the worst
@@ -309,7 +321,10 @@ check receipt (`receipt.runId === runId`), otherwise `n/a (<reason>)`. Any value
309
321
  1. Run `spur task check <wbs> --as todo --json`. Any error means the task is not ready. Fix it,
310
322
  or report `failed`.
311
323
  2. Fill metadata that is still unset: `spur task update <wbs> --priority <P0–P3>` and
312
- `--estimate-hours <n>` (both `--json`). Never overwrite a value the operator set.
324
+ `--estimate-hours <n>` (both `--json`). Never overwrite a value the operator set. The one
325
+ exception is a triage that dropped issues: re-estimate the remaining scope and record
326
+ old → new in the correction block. The CLI cannot rename a task. When a drop leaves the title
327
+ naming removed scope, record that in the correction block as well.
313
328
  3. Promote `backlog → todo` idempotently with `spur task update <wbs> todo --json`, the same FSM
314
329
  transition `--next` uses. Create-time ready preparation skips its own promotion when the task
315
330
  is already `todo`, and next-router stops routing the task back to refine. Without `--next`,
@@ -341,9 +356,10 @@ check receipt (`receipt.runId === runId`), otherwise `n/a (<reason>)`. Any value
341
356
  3. Topo-sort by `dependencies[]` (Kahn, WBS-ascending tie-break). Cycle → abort entire batch before any refine. Out-of-set deps: `done` → allow; else → block subtree (same as runall).
342
357
  4. For each WBS in order: invoke single-task refine with shared flags **including `--depth`**. Under `--auto` + **`--depth standard`** (default), the per-task **L3 pre-synthesis SKIP gate** still applies. Under **`--depth ready`**, each task runs the implement-ready checklist (no L3-only SKIP). That includes the premises audit, the correction record and ready finalization, so a passing task leaves at `todo`.
343
358
  5. Failure policy: **stop-the-batch** (default) or `--keep-going` (skip in-batch dependents of a failed refine; continue independents).
344
- 6. Emit a batch report (markdown or `--json`) that records `depth` once at the header. Under `--depth ready`, each row also carries the corrections count, status before → after, and failed checklist ids.
345
- - **Per-task outcome vocabulary:** `refined` (synthesis wrote sections) | `SKIP` (already meets the active depth bar under `--auto`) | `failed` | `skipped` (dep failed under `--keep-going`) | `not-attempted` (halted) | `blocked` (unmet out-of-set dep).
346
- - **Batch verdict:** `clean` (all attempted tasks `refined` or `SKIP`) | `halted` (a failure stopped the batch) | `aborted` (cycle / unknown selector / empty set after filter).
359
+ 6. Emit a batch report (markdown or `--json`) that records `depth` once at the header. Under `--depth ready`, each row also carries the corrections count, dropped issues, status before → after, and failed checklist ids.
360
+ 7. **Cross-task proposals (`--depth ready` only).** After the per-task pass, list two kinds of proposals in the report: tasks whose remaining issues overlap another set member (same root cause or file set → name the merge target; tasks that only share a step, such as one upstream release, or that fix two layers of one failure → propose ordering or a shared step, not a merge), and tasks with no `feature_id` (name the candidate owning feature with evidence). These are proposals only. Refineall merges, cancels or links a task only when the operator's `--description` names that task and the action (e.g. `cancel 0273 and merge its issues into 0269; link 0260 to G11`). That explicit directive is the confirmation the [feature-link helper](feature-link-helper.md) requires. A merge moves the surviving issues with their fixes into the target through CLI section updates, records the merge in both tasks' correction blocks, then cancels the source. Run directives before the per-task pass, so each target is refined with its merged content.
361
+ - **Per-task outcome vocabulary:** `refined` (synthesis wrote sections) | `SKIP` (already meets the active depth bar under `--auto`) | `cancelled` (no valid issue left, or merged away by directive) | `failed` | `skipped` (dep failed under `--keep-going`) | `not-attempted` (halted) | `blocked` (unmet out-of-set dep).
362
+ - **Batch verdict:** `clean` (all attempted tasks `refined`, `SKIP` or `cancelled`) | `halted` (a failure stopped the batch) | `aborted` (cycle / unknown selector / empty set after filter).
347
363
  - **`--next` is not accepted** (dropped by feature H8, 2026-07-31 — see `plugins/sp/commands/dev-refineall.md` for the removal record). Chain execution explicitly: refineall, then `/sp:dev-runall --feature <id>`.
348
364
  - **`--auto` recommendation:** Batch refine without `--auto` requires per-task interactive Q&A and does not scale. Default operator path: `/sp:dev-refineall --feature <id> --auto`. For implement handoffs, or to re-audit a feature's filed tasks: `/sp:dev-refineall --feature <id> --auto --depth ready`.
349
365
  - **Delegation:** `Skill(skill="sp:spur-dev", args="refineall $ARGUMENTS")` → per task `Skill(skill="sp:spur-dev", args="refine <wbs> $SHARED_FLAGS")` (shared flags include `--depth` when set).
@@ -375,7 +391,7 @@ check receipt (`receipt.runId === runId`), otherwise `n/a (<reason>)`. Any value
375
391
  - **Behavior:**
376
392
  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.
377
393
  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`.
378
- 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.
394
+ 3. Fill every template section for this job; use `N/A` where inapplicable. Include uncommitted work and ownership, gate commands/results already on record (never run a gate to fill this — write `not run`), 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.
379
395
  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.
380
396
  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.
381
397
 
@@ -552,6 +568,14 @@ gate commands, pending questions and approval requirements.>
552
568
  These define their procedure directly in the command file. No `Skill()` delegation — the command
553
569
  is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent reasoning.
554
570
 
571
+ **Gate ownership.** A project quality gate (`bun run gate`, `spur-check`, lint, typecheck, tests,
572
+ rule runs) runs only where an operation's own contract names it: the pipeline `test` hop
573
+ (`run`/`runall`), `fixall`, `gtd`, `fixgha`, `unit`, and the `--check <cmd>` loops. The scribe
574
+ operations — `changelog`, `gitmsg`, `handover`, `job-dump` — produce text or a commit, not code, so
575
+ they run **no gate by default**, and a generic "verify before you finish" rule from `AGENTS.md` or
576
+ host instructions does not add one. An opt-in gate is explicit: `gitmsg --check <cmd>`, or
577
+ `/sp:dev-gtd [--no-push]` for gate → auto-fix → commit. Commit hooks still run as configured.
578
+
555
579
  ### 8. changelog
556
580
 
557
581
  - **Purpose:** Generate a structured changelog from git commits between two refs.
@@ -568,12 +592,12 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
568
592
  6. Emit: with `<file>`, insert the section into that file above its newest `## [` release heading (or after its title when none exists) and touch nothing else in the file; without `<file>`, print it to stdout.
569
593
  7. Self-check before emitting: every short hash in `<since>..<until>` appears exactly once. Fix any miss or duplicate; do not report a verdict.
570
594
  8. Reply in at most three lines: the range, bullet counts per category, and the output target.
571
- - **Invariants:** Output is derived from `git log` only. No quality gates — no lint/test/`spur-check`/rule runs, citation or manifest lookups, confidence ratings, or edits beyond the one inserted section. The file is left uncommitted.
595
+ - **Invariants:** Output is derived from `git log` only. No quality gates — no `bun run gate`/lint/typecheck/test/`spur-check`/rule runs, citation or manifest lookups, confidence ratings, or edits beyond the one inserted section. The file is left uncommitted.
572
596
 
573
597
  ### 9. gitmsg
574
598
 
575
599
  - **Purpose:** Generate conventional commit message(s) for the current change set — one gather call → concern grouping → one message per concern; optionally commit. Git + POSIX shell only; no helper script.
576
- - **Inputs:** `--scope <path>` (default: the whole change set) — path filter; an explicit `--scope` always wins over change-set auto-discovery. `--all` (default: off) — widen the change set past the index to every change in the tree: unstaged **and untracked** files. Omitted, the change set is the index only, which keeps pre-commit semantics stable. `--commit` (default: off) — commit the change set, one commit per concern. `--squash` (default: off) — collapse every concern into one message and one commit; implies `--commit`.
600
+ - **Inputs:** `--scope <path>` (default: the whole change set) — path filter; an explicit `--scope` always wins over change-set auto-discovery. `--check <cmd>` (default: off) — run `<cmd>` once as a pre-commit gate (step 5a). `--all` (default: off) — widen the change set past the index to every change in the tree: unstaged **and untracked** files. Omitted, the change set is the index only, which keeps pre-commit semantics stable. `--commit` (default: off) — commit the change set, one commit per concern. `--squash` (default: off) — collapse every concern into one message and one commit; implies `--commit`.
577
601
  - **Backing:** `inline` — one bounded gather call + concern grouping + conventional commit formatting.
578
602
  - **Behavior:**
579
603
 
@@ -631,6 +655,8 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
631
655
 
632
656
  5. **Report.** Print: one context line (branch; `linked worktree` when `--git-dir` ≠ `--git-common-dir` and the superproject line is empty), then each message in a fenced block. No per-file summaries, no restated diff. With neither `--commit` nor `--squash`, add one copy-paste `git commit` line per message and stop.
633
657
 
658
+ 5a. **Gate (`--check <cmd>` only) — one more Bash call.** Without `--check`, run no gate of any kind. With it, run `<cmd>` exactly once, verbatim, after the report: exit 0 → one `check PASS` line and continue; non-zero → print its last 30 lines and commit nothing. Never fix, retry, or widen the command — gate → fix → commit is `/sp:dev-gtd`.
659
+
634
660
  6. **Commit (`--commit` / `--squash`) — one more Bash call.** `--squash` implies `--commit`, so both together is just `--squash`. Refuse before touching the index when:
635
661
  - `## secret hits` is non-empty → print each `file: line`, commit nothing;
636
662
  - `--commit` would split (more than one group) and `## partially staged` is non-empty → splitting would widen those `git add -p` stagings to whole files; print the paths and commit nothing (`--squash` is allowed — it commits the index as staged).
@@ -649,7 +675,7 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
649
675
 
650
676
  Hooks stay enabled; a failing hook stops the run with its output — never `--no-verify`.
651
677
 
652
- - **Invariants:** Git and POSIX shell only — no helper script, no temp file. At most two Bash calls: gather, then (only when committing) commit. With neither `--commit` nor `--squash`, never runs `git commit` — message only. Neither flag commits across a secret hit, and `--commit` never splits across a partial staging. Without `--all` the change set is the index, so plain `/sp:dev-gitmsg` keeps pre-commit semantics; only `--all` reaches unstaged and untracked files, and only a committing run stages them. The empty-index widen is read-only and always announced — a committing run never widens its own scope. An explicit `--scope <path>` always bounds the change set, with or without `--all`. One bounded, context-free capture per run — never a second, wider read.
678
+ - **Invariants:** Git and POSIX shell only — no helper script, no temp file. At most two Bash calls: gather, then (only when committing) commit — three with `--check`. No quality gate (`bun run gate`, lint, typecheck, tests, `spur-check`) unless `--check` names one. With neither `--commit` nor `--squash`, never runs `git commit` — message only. Neither flag commits across a secret hit, and `--commit` never splits across a partial staging. Without `--all` the change set is the index, so plain `/sp:dev-gitmsg` keeps pre-commit semantics; only `--all` reaches unstaged and untracked files, and only a committing run stages them. The empty-index widen is read-only and always announced — a committing run never widens its own scope. An explicit `--scope <path>` always bounds the change set, with or without `--all`. One bounded, context-free capture per run — never a second, wider read.
653
679
 
654
680
  ### 10. fixall
655
681
 
@@ -796,4 +822,4 @@ is the procedure. The backing is a combination of git CLI, `spur` CLI, and agent
796
822
  `## Testing`, `## Review`), verdict files (`.spur/run/<wbs>-verdict.json`), diffs, and docs — by
797
823
  **path**, not by pasting their content into the handover body. The handover is a pointer document;
798
824
  restating content it can instead link to makes it stale the moment the source changes.
799
- - **Invariants:** The handover is honest — rejected approaches are recorded so the next agent doesn't retry them. The blocker is specific, not "it doesn't work."
825
+ - **Invariants:** The handover is honest — rejected approaches are recorded so the next agent doesn't retry them. The blocker is specific, not "it doesn't work." No quality gate runs — cite gate results already on record.
@@ -152,8 +152,8 @@ kickoff** — the driver never re-queries `spur task list` to recompute membersh
152
152
  | --- | --- | --- |
153
153
  | Explicit WBS list | `^[0-9, ]+$` | Split on comma; validate each token is a 4-digit WBS; collect the explicit set. (R1.1) |
154
154
  | `feature:<id>` (via `--tasks` or `--feature <id>`) | literal `feature:` prefix or `--feature` flag | `spur task list --feature <id> --json`; collect `wbs` from each row. The `--feature` flag is sugar that becomes `--tasks feature:<id>` at the command layer. (R1.3) |
155
- | `ready` | literal `ready` | Resolve the union of `spur task list --status todo --json` + `spur task list --status backlog --json`, drop tasks with open children (R1.5, umbrella-parent exclusion below), then keep only tasks whose every `dependencies[]` entry resolves to `status == done` (via `spur task show <dep> --json | jq '{wbs, status, dependencies, feature_id}'` — R5 metadata-only). Report each excluded task with its unmet dependency. (R1.4) |
156
- | Status pseudo-list | `todo` \| `backlog` \| `wip` \| `blocked` \| `testing` | `spur task list --status <value> --json`; collect `wbs` from each row. (R1.2) |
155
+ | `ready` | literal `ready` | Resolve the union of `spur task list --status todo --json` + `spur task list --status backlog --json`, drop tasks with open children (R1.5, umbrella-parent exclusion below), then keep only tasks whose every `dependencies[]` entry resolves to `status == done` (via `spur task show <dep> --json | jq '{wbs, status, dependencies, feature_id}'` — R5 metadata-only). Report each excluded task with its unmet dependency. A `deprecated` dependency is *not* satisfied (ADR-137: a frozen task never reads as `done`), so it keeps its dependents out of the ready set. (R1.4) |
156
+ | Status pseudo-list | `todo` \| `backlog` \| `wip` \| `blocked` \| `testing` | `spur task list --status <value> --json`; collect `wbs` from each row. (R1.2) `deprecated` is deliberately not a selector value: a frozen task has no pipeline hop to drive, so a batch is never built from that status (ADR-137; `/sp:dev-next` row A10 stops the same way). |
157
157
  | *(else)* | no match | Error: "unknown selector `<value>`" — list the valid forms and halt before running anything. |
158
158
 
159
159
  **Dedup:** an explicit list with a repeated WBS (`--tasks 0040,0040`) collapses to a single entry;
@@ -200,7 +200,9 @@ For each dependency edge to a task **outside** the frozen set, resolve its curre
200
200
  - status ≠ `done` → mark the dependent **blocked**. Transitively mark its in-set descendants blocked
201
201
  too (fixpoint propagation: any task depending on a blocked task is itself blocked). Exclude all
202
202
  blocked tasks from execution and record the unmet dependency + the blocked subtree for the report
203
- (R2.4). Independent (non-blocked) tasks in the set still run.
203
+ (R2.4). Independent (non-blocked) tasks in the set still run. **`deprecated` is not satisfied**
204
+ (ADR-137): a frozen task never reads as `done`, so the dependent blocks and the report names the
205
+ remedy — re-point the edge, or un-deprecate (`spur task update <dep> todo`).
204
206
 
205
207
  ### 2.4 Topological sort
206
208
 
@@ -277,6 +279,7 @@ node "$(superskill script path sp batch-preflight.mjs)" \
277
279
  | `action: skip` code **A2** | Do not launch; report `preflight-skip` + unmet deps (mirrors TABLE A2) |
278
280
  | `action: skip` code **A7** | Do not launch; report blocked (handover is operator-side) |
279
281
  | `action: skip` code **A8**/**A9** | Do not launch; already done / cancelled |
282
+ | `action: skip` code **DEPRECATED** | Do not launch; frozen and retained (ADR-137) — the reason line names the un-deprecate command. A deprecated WBS can reach preflight through an explicit `--tasks` list or a `feature:<id>` selector (`spur task list --feature` reports every linked row, whatever its status); the `ready` and status pseudo-lists exclude it |
280
283
 
281
284
  **Invariants:** Preflight never replaces the pipeline with a loop of `/sp:dev-next`. TABLES A/B/C
282
285
  remain SSOT in `next-router/references/routing-table.md`. Step 2.3 already pre-blocks many unmet
@@ -171,17 +171,13 @@ Two branches reach the bounded repair hop, not one (session finding after 1088):
171
171
  an on-graph, bounded path to remediation instead of dead-ending the run, and the fix re-enters
172
172
  quality → review → verify on a freshly captured proof digest.
173
173
 
174
- The completion gate also reads the verifier's confidence (session finding after 1088): the verify
175
- answer's `Confidence: HIGH|MEDIUM|LOW` line reaches the verdict artifact, and both `verify → record`
176
- and `record → done` refuse a `LOW` (or absent) level unless the run was launched with
177
- `--vars '{"ackLowConfidence":"true"}'`. A PASS the verifier would not stand behind is an operator
178
- risk decision, so it takes an operator acknowledgement — not a silent certification.
179
- The CLI-layer done gate (`done-transition-guard`, task 1068 R3) separately requires the artifact to *state* a
180
- level at all: a PASS artifact whose `confidence` is missing is denied there too, and a present but
181
- out-of-vocabulary value fails the read closed (`invalid confidence field`), so a hand-driven
182
- `task update <wbs> done` — which is how this pipeline itself reaches `done` (`--no-lifecycle`) —
183
- cannot certify a verdict that carries no confidence. `LOW` is accepted at that gate; the
184
- acknowledgement rule above stays the pipeline's.
174
+ The completion gate reads deterministic evidence only (F511, task 1207): both `verify → record` and
175
+ `record → done` check the proof digests in `.spur/run/<wbs>-verdict.json` — verdict PASS, matching
176
+ run/definition digests, review stage completed. No confidence is read, stated or acknowledged; the
177
+ asserted `Confidence:` line and the `ackLowConfidence` operator var were retired because a model
178
+ that can write a PASS can write `HIGH` — the grade verified nothing. What protects a hand-driven
179
+ `task update <wbs> done` is unchanged: the digests must match the run's captured proof, and the
180
+ review stage must actually be completed in the artifact.
185
181
 
186
182
  Agentic steps use the pure slash inputs declared by each YAML `agent.run` action (ADR-043). The
187
183
  workflow engine dispatches them; the interactive driver invokes their backing skills in-session.
@@ -225,8 +225,10 @@ the `feature:<id>` sets, resolved once and frozen.
225
225
 
226
226
  **Anchor:** `#flag-check`.
227
227
 
228
- Verification command a command iterates against (`dev-simplify`, `dev-refactor`). The command
228
+ Verification command a command iterates against (`dev-simplify`, `dev-refactor`, `dev-gitmsg`). The command
229
229
  establishes a baseline with it before the first change and re-runs it after each change.
230
+ `dev-gitmsg` uses it as a one-shot opt-in pre-commit gate: run once, non-zero commits nothing, no
231
+ fix loop. A command without `--check` in its contract runs no gate.
230
232
 
231
233
  ### `--focus <dims>` — constrain the operation to specific dimensions
232
234
 
@@ -462,7 +464,7 @@ Orthogonal to `--focus` (which _narrows_ domains) and to `--mode` on other comma
462
464
  | Value (refine family) | Bar | `--auto` SKIP behavior |
463
465
  | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
464
466
  | `standard` (default when omitted) | L3 structural completeness (not empty/placeholder; check-clean for target sections) | **SKIP** when no L3 findings on target sections |
465
- | `ready` | **Implement-ready** freeze: another agent can implement without inventing design (frozen names/APIs or explicit "no new API", anti-patterns, file targets, handoffs, out-of-scope) | **Do not SKIP** on L3-clean alone — audit existing claims, run the ready checklist, rewrite sections until the bar is met, then promote `backlog → todo` |
467
+ | `ready` | **Implement-ready** freeze: another agent can implement without inventing design (frozen names/APIs or explicit "no new API", anti-patterns, file targets, handoffs, out-of-scope) | **Do not SKIP** on L3-clean alone — audit existing claims, drop invalid issues with their fixes (cancel when none stays valid), run the ready checklist, rewrite sections until the bar is met, then promote `backlog → todo` |
466
468
 
467
469
  Default for refine stays `standard` so ordinary `refineall --auto` remains cheap. Use `ready` for
468
470
  multi-package / multi-agent handoffs, flaky-pipeline features where a wrong implement is costly, and
@@ -844,9 +844,10 @@ leave no `.spur/run/<wbs>-check-receipt.json`. The deciding artifacts are then
844
844
  1. **Drive the pipeline** for anything that must be certified: only a digest-bound full receipt
845
845
  satisfies a review/verify/record boundary (`sp-spur-check`), and the `test` hop owns the capture.
846
846
  2. **When a host-driven pass is unavoidable, say so in the verdict** — name the status file and gate
847
- log as the evidence and grade confidence `MEDIUM`. A `HIGH` claim needs re-runnable evidence from a
848
- checked path (the `sp-code-verification` ladder); claiming a receipt that was never written is the
849
- failure mode this note exists to prevent (observed across four A91 tasks, 2026-10-12).
847
+ log as the evidence, and mark the reliance explicitly in the evidence cell (a host-driven gate is
848
+ not re-runnable proof from a checked path; the `sp-code-verification` ladder is). Claiming a
849
+ receipt that was never written is the failure mode this note exists to prevent (observed across
850
+ four A91 tasks, 2026-10-12).
850
851
 
851
852
  **A mismatch names the drifted paths (R5).** At gate entry the pipeline snapshots the non-corpus tree
852
853
  state (`git status --porcelain=v1 -uall` plus `git diff --name-only HEAD`, excluding
@@ -922,8 +923,10 @@ verdict artifact exists (tasks 0617, 0619 — the clobbering spiral).
922
923
 
923
924
  ## Running the full gate (task 0872 / 1127 R7)
924
925
 
925
- The full gate legitimately runs 10-25 minutes. Two rules keep it from becoming a hazard (both
926
- violated once on 2026-10-10, aborting the run's own verification):
926
+ The full gate legitimately runs minutes, not seconds — measured 1.8-3.1 min for `bun run spur-check`
927
+ on an idle 10-core host (2026-10-13), and far longer when other agents' suites run concurrently.
928
+ Five rules keep it from becoming a hazard (the first two
929
+ were both violated once on 2026-10-10, aborting the run's own verification):
927
930
 
928
931
  - **Never wrap it in an external `timeout`, and never treat its runtime as a hang.** An outer bound
929
932
  that fires mid-suite leaves a half-finished suite behind while the caller believes it is gone.
@@ -936,6 +939,24 @@ violated once on 2026-10-10, aborting the run's own verification):
936
939
  - **Preserve a signal-induced receipt.** A cap-killed attempt leaves a red receipt that the next
937
940
  recheck's `no-progress` guard honours, so it reads as a genuine failure unless the receipt is kept
938
941
  under a distinct name and the run log says so.
942
+ - **Clear the killed attempt's process tree before re-running.** A cap-signalled gate leaves its
943
+ `bun test --test-worker` children alive: the parent dies, the workers keep burning ~100% CPU, and
944
+ each retry is slower than the last until the cap kills that one too and mints another leak.
945
+ Observed 2026-10-13: five leaked workers (ages 23 min, 37 min, 50 min, 2 h 17 m, 4 h 18 m) drove
946
+ consecutive attempts from the measured 1.8-3.1 min up to 13-40 min, and the real defect of the
947
+ session only became visible once they were cleared. Find them by age and cwd, then clear the tree
948
+ before the next run; leave a tree alone whose cwd is another session's live run:
949
+
950
+ ```bash
951
+ ps -Ao pid=,ppid=,etime=,%cpu=,command= | grep -E "run-tests\.ts|bun test --test-worker" | grep -v grep
952
+ kill -TERM <pid> <ppid>; sleep 4; kill -KILL <pid> <ppid> # escalate only if TERM is ignored
953
+ ```
954
+
955
+ - **One gate per tree.** Nothing serializes gate runs since task 1173 deleted the lock, so confirm
956
+ no live gate is already running in your tree before starting one: two suites in one tree contend
957
+ for CPU and for the shared fixtures, and the second one's result is uninterpretable. Measured
958
+ 2026-10-13: a duplicate gate launched into a tree already running another session's
959
+ `bun run spur-check` burned 40 min at the host cap and left an orphaned worker behind.
939
960
 
940
961
  > Historical (task 1127, removed in task 1173): these rules were once stated in terms of a host-wide
941
962
  > `full-gate.lock`. The lock mechanism was deleted (`refactor(gate): remove gate-lock mechanism and
@@ -957,14 +978,14 @@ Each item below cost a driver cycle to discover. They are contracts, not tips.
957
978
  `.spur/run/<wbs>-diffstat.json` and never on command output. Never the bare unguarded
958
979
  source-repo path form — the script-contract check forbids it on a shipped surface because it
959
980
  shadows the installed twin in a consumer.
960
- - **The verify answer grammar is exact.** One `Verdict:` line, one `Confidence:` line, then
981
+ - **The verify answer grammar is exact.** One `Verdict:` line, then
961
982
  `### Per-Requirement Traceability` (`| Req | Status | Evidence |`) and
962
983
  `### Acceptance Criteria Verification` (`| AC | Status | Evidence Type | Evidence |`). Requirement
963
984
  statuses are `MET | PARTIAL | UNMET`; AC statuses add `N/A`; every AC row id must match a declared
964
985
  scenario title verbatim, including its `(req: ...)` suffix. A `MET` row whose evidence hedges
965
986
  (`likely`, `probably`, `seems`, `appears`, `possibly`, `presumably`) is rejected as
966
- `evidence-hedged`, and a level the rows do not earn is rejected as `confidence-unwarranted` or
967
- `confidence-understated`. `spur task verdict` lints before writing, so a rejected answer leaves no
987
+ `evidence-hedged`. No `Confidence:` line exists (F511, task 1207) — legacy answers that carry one
988
+ parse with the value ignored. `spur task verdict` lints before writing, so a rejected answer leaves no
968
989
  artifact and exits non-zero.
969
990
  - **Harness tooling refuses direct task-file writes.** Resolve a merge conflict in a task file by
970
991
  choosing a git side, then applying the corpus delta through `spur task update` (for example
@@ -53,7 +53,7 @@
53
53
  "variant": {
54
54
  "type": "object",
55
55
  "additionalProperties": false,
56
- "description": "A variant may declare any subset of the 7 canonical statuses (enumerated below); an unknown status key is rejected.",
56
+ "description": "A variant may declare any subset of the 8 canonical statuses (enumerated below); an unknown status key is rejected.",
57
57
  "properties": {
58
58
  "backlog": { "$ref": "#/$defs/entry" },
59
59
  "todo": { "$ref": "#/$defs/entry" },
@@ -61,7 +61,8 @@
61
61
  "testing": { "$ref": "#/$defs/entry" },
62
62
  "blocked": { "$ref": "#/$defs/entry" },
63
63
  "done": { "$ref": "#/$defs/entry" },
64
- "cancelled": { "$ref": "#/$defs/entry" }
64
+ "cancelled": { "$ref": "#/$defs/entry" },
65
+ "deprecated": { "$ref": "#/$defs/entry" }
65
66
  }
66
67
  }
67
68
  }