@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
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.4.3",
10
+ "version": "0.4.5",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -32,8 +32,9 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
32
32
  # backstop: the two `cited-*` rules cover the citation half, and
33
33
  # `cited-api-claims-confidence` covers the level half. All are severity `info`,
34
34
  # and the category is deliberately NOT in `recommended-pre-check` — it surfaces
35
- # findings for review without reddening gates. To promote it to a gate, add
36
- # `- docs` to that preset's `extends` once the residual list is triaged.
35
+ # findings for review without reddening gates. The 2026-10-12 audit below settled
36
+ # the promotion question: the residual findings stay a review-surface concern
37
+ # (SECUA checklist), not a gate one — do not add `- docs` to that preset.
37
38
  include:
38
39
  - "docs/**/*.md"
39
40
  - "plugins/sp/skills/**/references/**/*.md"
@@ -1,5 +1,18 @@
1
1
  $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
2
  # Coverage gate — per-file line coverage meets threshold from Bun's lcov output.
3
+ #
4
+ # PROVENANCE (task 1203): since task 1203 the repository post-check scripts
5
+ # (`test-post-check`, `test-post-check:full`) validate canonical coverage
6
+ # certification BEFORE this rule evaluates: only a completed successful canonical
7
+ # full-suite run (`bun run test`, `test:coverage`, `test:full`) certifies
8
+ # .coverage/lcov.info (marker: .coverage/coverage-certification.json, written by
9
+ # scripts/commands/run-tests.ts --publish-coverage). Missing/pending/superseded/
10
+ # stale-tree/byte-mismatched artifacts fail the post-check with a
11
+ # `coverage-artifact:` diagnostic before per-file findings; recovery is rerunning
12
+ # `bun run test:full`. Running this rule directly via `spur rule run` outside the
13
+ # repository wrapper bypasses that certification wrapper and is outside this
14
+ # repository's certification contract. This rule and its evaluator are unchanged.
15
+ #
3
16
  # Absorbed from ts-libs/.spur/rules/quality/coverage-gate.yaml, re-scoped to
4
17
  # Spur's monorepo layout:
5
18
  # - lcovPath kept at .coverage/lcov.info (Spur's `bun run test:coverage`
@@ -4,12 +4,17 @@ $schema: "@gobing-ai/spur/schemas/preset.schema.json"
4
4
  #
5
5
  # Runs BEFORE tests (test-pre-check). Extends categories: typescript,
6
6
  # structure, boundary, surface, ui, strict (ui since bc267cc8, strict since
7
- # 79186391), and docs (sourced-api-claims, 2026-10-07). TSDoc exports run in
8
- # post-check alongside coverage-gate.
7
+ # 79186391), and docs (sourced-api-claims, 2026-10-07; pulled 2026-10-08 for
8
+ # finding noise — a 2026-10-14 restore was reverted; keep it out for now, see
9
+ # the marker line below). TSDoc exports run in post-check alongside
10
+ # coverage-gate.
9
11
  #
10
- # TEMPORARY (2026-10-08): `docs` removed from extends to unblock the gate —
11
- # restore it (add `- docs` back) once sourced-api-claims finding noise is
12
- # triaged. Recapture the raw-json-baseline fixtures in the same change.
12
+ # `docs/sourced-api-claims.yaml` (citation/level checks) stays OUT of this gate:
13
+ # severity info would not redden it, but the findings belong to the SECUA review
14
+ # surface — run that file ad hoc instead. Recapture the raw-json-baseline
15
+ # fixtures when touching this preset. (F511: the category's other file,
16
+ # `verdict-confidence.yaml`, was deleted with the asserted confidence machinery
17
+ # it backstopped.)
13
18
  name: recommended-pre-check
14
19
  extends:
15
20
  - typescript
@@ -18,3 +23,4 @@ extends:
18
23
  - surface
19
24
  - ui
20
25
  - strict
26
+ # - docs ## DO NOT ENABLE THIS LINE
@@ -70,6 +70,7 @@ rules:
70
70
  - "packages/app/src/services/token-ledger-service.ts" # FD byte-window log tailing
71
71
  - "packages/app/src/services/token-ledger-watcher.ts" # node:fs watch() live watcher
72
72
  - "packages/app/src/services/project-registry.ts" # atomic projects.json persistence
73
+ - "packages/app/src/services/project-process.ts" # port/pid probes moved verbatim out of project-registry.ts to break the registry↔stop import cycle (same exemption)
73
74
  - "packages/app/src/services/project-server-owner.ts" # atomic mkdir lifetime claim + unique-marker stale recovery; FileSystem has no exclusive mkdir primitive (1082)
74
75
  - "packages/app/src/services/slash-commands-service.ts" # synchronous ~/.config/spur/slash_commands.json persistence (mirrors project-registry.ts)
75
76
  - "packages/app/src/services/agent-usage-producer.ts" # atomic agent-usage snapshot write (tmp + rename, mirrors project-registry.ts; task 0892 R1)
@@ -82,6 +83,7 @@ rules:
82
83
  - "packages/app/src/services/quality-gate.ts" # gate artifacts (log/findings/receipt) written directly; merged-fd gate log and fsync-free atomic writes must stay byte-stable; bundled standalone for the bare-node plugin twin (task 1006 R1; mirrors history-anatomy.ts)
83
84
  - "packages/app/src/workflow/feature-verification-run.ts" # the pass opens the run's single merged log fd (`openSync(path,'a')`) and mkdirs the run dir beside the receipt writer, exactly as the plugin entry did before the move; the fd cannot be expressed through the FileSystem seam (task 1176 R2; same class as the quality-gate exemption above)
84
85
  - "packages/app/src/services/run-storage.ts" # durable-evidence migration core (task 1025 R4): atomic tmp+rename byte copies with digest reread and atomic manifest publish must stay byte-stable (mirrors agent-usage-producer.ts / project-registry.ts exemptions)
86
+ - "packages/app/src/services/durable-plane-ignore.ts" # .git/info/exclude append moved verbatim out of run-storage.ts to break an import cycle (same exemption)
85
87
 
86
88
  # Electron Node adapters cannot load Bun runtime implementations; keep the
87
89
  # synchronous existence/directory probes injected for unit testing (desktop contract).
@@ -91,6 +93,7 @@ rules:
91
93
  # Synchronous bootstrap & path resolution:
92
94
  - "packages/config/src/bundled-config.ts" # sync bundledConfigRoot() directory walk
93
95
  - "packages/config/src/loader.ts" # sync resolveConfigFile() / schema specifier lookup
96
+ - "packages/config/src/config-layers.ts" # sync resolveConfigLayers() existence probes moved verbatim out of loader.ts to break the loader↔executor-update cycle (same exemption)
94
97
  - "packages/config/src/executor-update.ts" # atomic single-entry config update (task 0797): O_EXCL lock, fsync'd tmp+rename commit, lstat symlink refusal, mode preservation — ts-runtime FileSystem seam has no lstat/fsync/chmod/O_EXCL
95
98
  - "packages/app/src/services/project-start.ts" # sync CLI binary path checks before daemon spawn
96
99
  - "apps/cli/src/commands/serve.ts" # sync resolveServeCwd() directory validation before server startup (task 0805 R2); mirrors task.ts sync-template exemption
@@ -10,9 +10,7 @@ include:
10
10
  - "apps/cli/src/commands/*.ts"
11
11
 
12
12
  exclude:
13
- # Not command files: stubs.ts is an empty module shim (consistency.test.ts
14
- # excludes it too); shared-options.ts is the option registry.
15
- - "apps/cli/src/commands/stubs.ts"
13
+ # Not a command file: shared-options.ts is the option registry.
16
14
  - "apps/cli/src/commands/shared-options.ts"
17
15
 
18
16
  rules:
@@ -147,6 +147,13 @@ _(Fill from package manifests / README — or during `sp:doc-evolve` customize.)
147
147
  **Done gate (minimum):** lint + tests clean; only intentional `git status` changes; no
148
148
  `--no-verify` / silent suppressions. Harness task done ⇒ real verify **PASS** when the pipeline ran.
149
149
 
150
+ **Gate scope:** the gate verifies code changes. Scribe commands — `/sp:dev-gitmsg`,
151
+ `/sp:dev-changelog`, `/sp:dev-handover`, `/sp:dev-job-dump` — produce text or a commit and run no
152
+ gate (lint, typecheck, tests) unless asked: `gitmsg --check <cmd>`, or `/sp:dev-gtd --no-push` for
153
+ gate → fix → commit. Commands that own a gate (`dev-run`, `dev-runall`, `dev-fixall`, `dev-gtd`,
154
+ `dev-fixgha`, `dev-unit`, `--check` loops) run exactly what their contract names — no extra
155
+ completion-gate pass on top.
156
+
150
157
  ---
151
158
 
152
159
  ## Spur CLI surface
@@ -51,6 +51,14 @@ vars:
51
51
  featureId: "X"
52
52
  spurBin: "spur"
53
53
  verificationCmd: "bun run spur-check-feature"
54
+ # Operator-declared confidence level; empty derives it from the pass (HIGH when the selected
55
+ # definition's own command exited 0 with an unchanged proof-input digest, MEDIUM under a caller
56
+ # `--cmd` override, LOW otherwise). The completion boundary refuses a PASS carrying no level or
57
+ # LOW unless the receipt records the acknowledgement below.
58
+ confidence: ""
59
+ # Operator acknowledgement of a LOW level. It rides the receipt, so the transition reads it from
60
+ # the evidence rather than from whatever flags a later command happens to pass.
61
+ ackLowConfidence: "false"
54
62
  __runId: ""
55
63
 
56
64
  states:
@@ -70,7 +78,7 @@ states:
70
78
  - kind: shell
71
79
  options:
72
80
  command: >-
73
- mkdir -p .spur/run; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/feature-verification-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/feature-verification-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; [ -f "$S" ] && "$RUNNER" "$S" verify --feature-id "$featureId" --run-id "$__runId" --spur-bin "$spurBin" || printf 'FAIL feature-verification failed closed — script not found — run superskill install sp --marketplace gobing-ai/spur\n' > ".spur/run/$__runId-feature-verification.status"; exit 0
81
+ mkdir -p .spur/run; eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/feature-verification-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/feature-verification-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; ACK=""; [ "$ackLowConfidence" = "true" ] && ACK="--ack-low-confidence"; [ -f "$S" ] && "$RUNNER" "$S" verify --feature-id "$featureId" --run-id "$__runId" --spur-bin "$spurBin" --confidence "$confidence" $ACK || printf 'FAIL feature-verification failed closed — script not found — run superskill install sp --marketplace gobing-ai/spur\n' > ".spur/run/$__runId-feature-verification.status"; exit 0
74
82
 
75
83
  - id: done
76
84
  description: Terminal — repo-wide checks passed and the receipt is bound.
@@ -64,6 +64,11 @@ states:
64
64
  Completed. Re-enterable (reopen with warning + mandatory History entry).
65
65
  - id: cancelled
66
66
  description: Terminal — abandoned.
67
+ - id: deprecated
68
+ description: >
69
+ Retained and frozen (ADR-137). Non-terminal: the record stays readable and
70
+ countable, nothing new may attach to it, and leaving it is explicit —
71
+ un-deprecate to todo, or cancelled once the task is removed.
67
72
 
68
73
  transitions:
69
74
  # Forward path: backlog → todo → wip → testing → done
@@ -157,3 +162,48 @@ transitions:
157
162
  description: Cancel task
158
163
  guard:
159
164
  kind: always
165
+
166
+ # Deprecate: any non-terminal-or-done state → deprecated (frozen, retained — ADR-137)
167
+ - from: backlog
168
+ to: deprecated
169
+ description: Deprecate task (frozen, retained)
170
+ guard:
171
+ kind: always
172
+ - from: todo
173
+ to: deprecated
174
+ description: Deprecate task (frozen, retained)
175
+ guard:
176
+ kind: always
177
+ - from: wip
178
+ to: deprecated
179
+ description: Deprecate task (frozen, retained)
180
+ guard:
181
+ kind: always
182
+ - from: testing
183
+ to: deprecated
184
+ description: Deprecate task (frozen, retained)
185
+ guard:
186
+ kind: always
187
+ - from: blocked
188
+ to: deprecated
189
+ description: Deprecate task (frozen, retained)
190
+ guard:
191
+ kind: always
192
+ - from: done
193
+ to: deprecated
194
+ description: Deprecate task (frozen, retained)
195
+ guard:
196
+ kind: always
197
+
198
+ # Exits out of deprecated: un-deprecate or remove only. Any other edge is
199
+ # undeclared and refused by the graph (ADR-135).
200
+ - from: deprecated
201
+ to: todo
202
+ description: Un-deprecate (mandatory History entry)
203
+ guard:
204
+ kind: always
205
+ - from: deprecated
206
+ to: cancelled
207
+ description: Remove deprecated task
208
+ guard:
209
+ kind: always
@@ -19,14 +19,6 @@
19
19
  # done guard closed, and re-records Testing before the failed edge); done settles
20
20
  # deferrals; failed renders the recovery report. No new state, edge, or model query.
21
21
  #
22
- # Confidence gate (session finding after 1088, task 1068 follow-up): the verify answer has
23
- # carried a `Confidence: HIGH|MEDIUM|LOW` line since 1068, and nothing read it — a PASS at
24
- # LOW confidence certified exactly like HIGH. The verify stamp now records a `confidence`
25
- # check row, and BOTH completion guards (verify → record, record → done) refuse a LOW (or
26
- # absent) level unless the run was launched with `--vars '{"ackLowConfidence":"true"}'`.
27
- # The acknowledgement is an operator decision, not a model one: it is the only way to
28
- # certify a verdict the verifier itself would not stand behind.
29
- #
30
22
  # Review-failure routing (session finding after 1088): `review` had no outgoing edge for a
31
23
  # FAIL verdict, so a failing review could only be remediated by driving the graph by hand
32
24
  # (re-entering `test` and hand-emitting rows). The review stage now derives
@@ -51,9 +43,8 @@ kind: state-machine
51
43
  name: task-pipeline
52
44
  # 0772 R2: explicit identity tag. Set only after the proof failure-path tests
53
45
  # passed; the engine treats unversioned external definitions as supported.
54
- # v4 (session finding after 1088): the completion gate reads the verifier's confidence level and
55
- # the graph routes a non-PASS review into bounded remediation — both are contract changes, so the
56
- # identity moves with them.
46
+ # v4 (session finding after 1088): the graph routes a non-PASS review into bounded remediation —
47
+ # a contract change, so the identity moves with it (the confidence half of v4 was retired at v7).
57
48
  # v5 (task 1077's inline run, 2026-10-06): the verify verdict action is explicitly `onError:
58
49
  # continue`. `task verdict` exits non-zero on any non-PASS verdict BY DESIGN (1003 R2) — that is
59
50
  # data for the verify guards, not a state failure. Under the engine's default 'fail' policy
@@ -63,14 +54,13 @@ name: task-pipeline
63
54
  # UNREACHABLE: a non-PASS verify could only end the run failed. `test-fix` also gained the
64
55
  # review-lane evidence projection (see its onEnter) so the repair hop is not fed an empty findings
65
56
  # list when the failing hop was `review-fail-triage` rather than the quality gate.
66
- # v6 (task 1134 run, 2026-10-09): the `confidence` check row now encodes the SAME policy as the two
67
- # completion guards instead of a stricter one of its own. It warned for every level below HIGH, so a
68
- # MEDIUM certification was admitted by both guards but recomputed as PARTIAL by the CLI done gate —
69
- # the artifact was self-inconsistent and `done` was refused with no named level to act on. The row
70
- # now warns only for an unacknowledged LOW (or absent) level, which is exactly what the guards
71
- # refuse; `packages/app/tests/workflow/task-pipeline-proof-chain.test.ts` pins the agreement for
72
- # HIGH/MEDIUM/LOW/absent × ack.
73
- version: "6"
57
+ # v7 (task 1207, F511): the asserted `Confidence: HIGH|MEDIUM|LOW` machinery is retired — the
58
+ # verifier's and reviewer's self-graded levels (re-imported from the cc anti-hallucination skill
59
+ # by task 1068) are no longer written, checked, or gated on; spur certifies on deterministic
60
+ # evidence (rows MET, proof digests, findings dispositioned). The `confidence` check row, the
61
+ # `ackLowConfidence` var, and the guards' LOW/absent clauses are gone; the derived
62
+ # feature-receipt confidence (ADR-131/1196) is a different family and stays.
63
+ version: "7"
74
64
  description: "Standard task pipeline: precheck → implement → quality-gate (test/fix/recheck) → review → approve → verify → record → done"
75
65
  # Task entity lifecycle (owned by task-lifecycle.yaml):
76
66
  # normal: backlog → todo → wip → testing → done
@@ -195,14 +185,6 @@ vars:
195
185
  # Escalation counter: .spur/run/<wbs>-escalation-count. Default 2 = two answered
196
186
  # questions; a third pause routes to failed with a report note.
197
187
  maxEscalations: "2"
198
- # Operator acknowledgement of a LOW-confidence certification (session finding after 1088).
199
- # The verify answer's `Confidence:` line is captured into the verdict artifact; a LOW (or
200
- # absent) level fails the completion guards unless this is "true", because a PASS the
201
- # verifier would not stand behind is an operator risk decision, not a mechanical one.
202
- # Set per run: `--vars '{"ackLowConfidence":"true"}'` (and export it on the inline path).
203
- # Deliberately NOT settable from the task file or the verifier's own answer: the point is
204
- # that a second party, not the producer, accepts the residual uncertainty.
205
- ackLowConfidence: ""
206
188
  # Runtime-written, 0933: the escalate hop's file.read.into-var fills this from
207
189
  # .spur/run/<wbs>-question.md; the hitl.input prompt below references it. Declared
208
190
  # here (empty) so the static var-reference validator sees the template source.
@@ -897,20 +879,6 @@ states:
897
879
  onError: continue
898
880
  options:
899
881
  command: "$spurBin task verdict $wbs --from-answer .spur/run/$wbs-verify-answer.txt"
900
- # Session finding after 1088: the verifier's confidence level becomes a `confidence` check
901
- # row and a gate-log line, so the level the completion guards enforce is visible in the
902
- # artifact and the log — not only in the answer file. v6 (task 1134 run): the row warns for
903
- # an unacknowledged LOW/absent level ONLY, matching the guards' ack rule; warning for
904
- # MEDIUM too made an admitted certification aggregate to PARTIAL (self-inconsistent artifact,
905
- # done refused). This is its own action because the proof-binding stamp below must stay the
906
- # state's LAST action AND under the ADR-115 800-char shell cap.
907
- - kind: shell
908
- options:
909
- command: >-
910
- V=".spur/run/$wbs-verdict.json"; [ -f "$V" ] || exit 0;
911
- jq --arg ack "$ackLowConfidence" '. + {checks: (((.checks // []) | map(select(.name != "confidence"))) + [{name: "confidence", status: (if ((.confidence // "LOW") != "LOW" or $ack == "true") then "pass" else "warn" end), evidence: ((.confidence // "LOW (absent from artifact)") + (if $ack == "true" then " (operator-acknowledged)" else "" end))}])}' "$V" > "$V.tmp" && mv "$V.tmp" "$V";
912
- printf 'confidence: %s (ack=%s)\n' "$(jq -r '.confidence // "LOW (absent)"' "$V")" "$ackLowConfidence" >> ".spur/run/$wbs-test-gate.log";
913
- exit 0
914
882
  # (e) one jq mutation binds the verdict to the proof digest (0703 R3; runId 0730 §B.2 /
915
883
  # 0757 R4; definitionDigest 0759 R5; honest review stamp 0785 R4; soft action + hard guard).
916
884
  - kind: shell
@@ -1312,11 +1280,15 @@ transitions:
1312
1280
  # re-enters quality → review → verify on a fresh digest. Before 1088 a FAIL review had no
1313
1281
  # outgoing edge at all; before 1122 a PASS-with-findings cost a full re-certification cycle per
1314
1282
  # attempt (knowledge-kit 0210/0213). The reviewer writes `Verdict: PASS|FAIL` in its answer;
1315
- # both plain and bold forms are accepted. Under `profile=auto` the approve gate is skipped, so
1316
- # the PASS+auto edge is tried first and the interactive PASS edge second.
1283
+ # both plain and bold forms are accepted. (F511: the v4-era PASS confidence grading — the
1284
+ # reviewer's self-stated HIGH/MEDIUM/LOW level and its `ackLowConfidence` escape hatch — was
1285
+ # retired; a PASS with no open P1-P3 finding is what the gate reads.) Review stays advisory:
1286
+ # verify certifies.
1287
+ # Under `profile=auto` the approve gate is skipped, so the PASS+auto edge is tried first and the
1288
+ # interactive PASS edge second.
1317
1289
  - from: review
1318
1290
  to: verify
1319
- description: profile=auto, the review certified PASS, and no open P1-P3 review finding — skip the human approval gate.
1291
+ description: profile=auto, the review certified a PASS with no open P1-P3 finding — skip the human approval gate.
1320
1292
  guard:
1321
1293
  kind: shell
1322
1294
  options:
@@ -1327,7 +1299,7 @@ transitions:
1327
1299
  [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
1328
1300
  - from: review
1329
1301
  to: approve
1330
- description: Review certified PASS with no open P1-P3 review finding — gate on human approval before verification.
1302
+ description: Review certified a PASS with no open P1-P3 finding — gate on human approval before verification.
1331
1303
  guard:
1332
1304
  kind: shell
1333
1305
  options:
@@ -1339,8 +1311,8 @@ transitions:
1339
1311
  to: review-fail-triage
1340
1312
  description: >-
1341
1313
  No certified PASS without an open P1-P3 finding (FAIL, PARTIAL, missing, unparseable, or
1342
- a PASS whose review-gate check found an open P1-P3 row — fail closed) — classify the
1343
- failure and route it into the bounded repair hop instead of dead-ending the run.
1314
+ a PASS whose review-gate check found an open P1-P3 row; fail closed) —
1315
+ classify the failure and route it into the bounded repair hop instead of dead-ending the run.
1344
1316
  guard:
1345
1317
  kind: always
1346
1318
 
@@ -1377,23 +1349,21 @@ transitions:
1377
1349
  # The verify step emits .spur/run/<wbs>-verdict.json with a required proof block (task 0703 R3/R5).
1378
1350
  # Only `verdict: PASS` PLUS a proof block whose digest — top level and every named stage — equals
1379
1351
  # the captured `proofDigest` clears the gate to `record`; any non-PASS, a missing file, malformed
1380
- # JSON, or missing/mismatched proof evidence does not. The verifier's confidence level is part of
1381
- # that certification (session finding after 1088): a PASS the verifier itself marked LOW — or left
1382
- # unstated — clears the gate only when the operator accepted it with
1383
- # `--vars '{"ackLowConfidence":"true"}'`. Declaration order: PASS+proof guard FIRST,
1384
- # then the bounded remediation route (R4), then the always catch-all so a PASS verdict with a
1385
- # missing/malformed proof block still terminates at `failed` instead of hanging the state.
1352
+ # JSON, or missing/mismatched proof evidence does not. (F511: the v4-era LOW/absent-confidence
1353
+ # clause and its `ackLowConfidence` escape hatch were retired.) Declaration order: PASS+proof
1354
+ # guard FIRST, then the bounded remediation route (R4), then the always catch-all so a PASS
1355
+ # verdict with a missing/malformed proof block still terminates at `failed` instead of hanging
1356
+ # the state.
1386
1357
  - from: verify
1387
1358
  to: record
1388
- description: Verification verdict is PASS, its proof block names the captured digest on every stage, and any LOW confidence was operator-acknowledged — record results and proceed to done.
1359
+ description: Verification verdict is PASS and its proof block names the captured digest on every stage — record results and proceed to done.
1389
1360
  guard:
1390
1361
  # (one jq -e predicate) PASS verdict; proof, quality-gate, review and verification digests
1391
- # equal to proofDigest; review completed; matching run id and definition digest (0703 R5, 0785 R4);
1392
- # confidence HIGH/MEDIUM, or LOW/absent with the operator's ack (session finding after 1088).
1362
+ # equal to proofDigest; review completed; matching run id and definition digest (0703 R5, 0785 R4).
1393
1363
  kind: shell
1394
1364
  options:
1395
1365
  command: >-
1396
- jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" --arg ack "$ackLowConfidence" '
1366
+ jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" '
1397
1367
  .verdict == "PASS"
1398
1368
  and (.proof.digest // "") == $d
1399
1369
  and (.proof.stages.qualityGate.digest // "") == $d
@@ -1402,7 +1372,6 @@ transitions:
1402
1372
  and (.proof.stages.verification.digest // "") == $d
1403
1373
  and (.proof.runId // "") == $r
1404
1374
  and (.proof.definitionDigest // "") == $dd
1405
- and ((.confidence // "LOW") != "LOW" or $ack == "true")
1406
1375
  ' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
1407
1376
  - from: verify
1408
1377
  to: test-fix
@@ -1430,12 +1399,10 @@ transitions:
1430
1399
  # ── done gate: record → done/failed gated on `spur task check` (ADR-026 amendment 2026-06-23)
1431
1400
  # PLUS the proof-block re-assertion (task 0703 R5): the verdict artifact must still be PASS and
1432
1401
  # still name the captured digest — a forged or mutated completion artifact fails closed here.
1433
- # PLUS the confidence re-assertion (session finding after 1088): the same ack rule as verify →
1434
- # record, re-read from the artifact so a mutation between the two boundaries cannot slip through.
1435
1402
  # Declaration order: pass guard first.
1436
1403
  - from: record
1437
1404
  to: done
1438
- description: Task check passed, the verdict proof block still names the captured digest, and any LOW confidence was acknowledged — certify done.
1405
+ description: Task check passed and the verdict proof block still names the captured digest — certify done.
1439
1406
  guard:
1440
1407
  kind: shell
1441
1408
  options:
@@ -1445,14 +1412,13 @@ transitions:
1445
1412
  # comments inside the folded scalar: `>-` joins same-indent lines into
1446
1413
  # one shell line.
1447
1414
  # Two logical commands, deliberately (ADR-115): the `task check` projection plus
1448
- # ONE jq predicate re-asserting the whole completion contract — PASS verdict, the
1449
- # captured proof digest, and the confidence rule (session finding after 1088).
1415
+ # ONE jq predicate re-asserting the whole completion contract — PASS verdict and the
1416
+ # captured proof digest.
1450
1417
  command: >-
1451
1418
  $spurBin task check $wbs --as done &&
1452
- jq -e --arg p "$proofDigest" --arg ack "$ackLowConfidence" '
1419
+ jq -e --arg p "$proofDigest" '
1453
1420
  .verdict == "PASS"
1454
1421
  and ((.proof.digest // "") == $p)
1455
- and ((.confidence // "LOW") != "LOW" or $ack == "true")
1456
1422
  ' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
1457
1423
  - from: record
1458
1424
  to: failed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
5
5
  "keywords": [
6
6
  "spur",
@@ -57,15 +57,15 @@
57
57
  },
58
58
  "devDependencies": {
59
59
  "@commander-js/extra-typings": "^14.0.0",
60
- "@gobing-ai/ts-db": "^0.5.24",
61
- "@gobing-ai/ts-ai-runner": "^0.5.24",
62
- "@gobing-ai/ts-dual-workflow-engine": "^0.5.24",
63
- "@gobing-ai/ts-infra": "^0.5.24",
64
- "@gobing-ai/ts-llm-jsonl-importer": "^0.5.24",
65
- "@gobing-ai/ts-rule-engine": "^0.5.24",
66
- "@gobing-ai/ts-runtime": "^0.5.24",
67
- "@gobing-ai/ts-utils": "^0.5.24",
68
- "@types/bun": "1.3.14",
60
+ "@gobing-ai/ts-db": "^0.5.28",
61
+ "@gobing-ai/ts-ai-runner": "^0.5.28",
62
+ "@gobing-ai/ts-dual-workflow-engine": "^0.5.28",
63
+ "@gobing-ai/ts-infra": "^0.5.28",
64
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.5.28",
65
+ "@gobing-ai/ts-rule-engine": "^0.5.28",
66
+ "@gobing-ai/ts-runtime": "^0.5.28",
67
+ "@gobing-ai/ts-utils": "^0.5.28",
68
+ "@types/bun": "1.4.3",
69
69
  "@types/figlet": "^1.7.0",
70
70
  "@types/node-notifier": "8.0.5",
71
71
  "commander": "^14.0.3",
@@ -200,7 +200,6 @@ shallower.
200
200
  **Scope:** <wbs diff | path glob>
201
201
  **Dimensions:** functional, security, efficiency, correctness, usability, architecture
202
202
  **Verdict:** PASS | PARTIAL | FAIL
203
- **Confidence:** HIGH | MEDIUM | LOW
204
203
  ##### Findings (ranked)
205
204
 
206
205
  | # | Priority | Dimension | Finding | Location | Disposition |
@@ -226,27 +225,14 @@ FAIL, PARTIAL, a missing line, a line split across two lines — routes the run
226
225
  `review-fail-triage` and its bounded repair hop. Keep it on one line, in that shape, in every
227
226
  review answer; never restate it as prose only.
228
227
 
229
- **The Confidence line is machine-read too (one confidence contract, 2026-10-12).** Every review
230
- report carries exactly one `Confidence: HIGH | MEDIUM | LOW` line, stated at the level the review can
231
- actually defend — the same enum and the same earning rule the verify answer uses
232
- ([verdict-schema.md](../skills/code-verification/references/verdict-schema.md) § Confidence level):
233
-
234
- - `HIGH` — every requirement row is `MET`, every finding carries a disposition, and the report cites
235
- its evidence. `HIGH` says the evidence needs no re-check.
236
- - `MEDIUM` — the verdict holds but evidence gaps remain; name them.
237
- - `LOW` — the verdict rests on unverified assumptions that could plausibly flip it; name them.
238
-
239
- A missing line, a level outside the enum, or a `HIGH` the rows do not earn turns an otherwise usable
240
- PASS into a refused one: consumer repositories gate the review answer artifact and every level it
241
- claims, exactly as they gate the verify answer. This is a contract change — review answers written
242
- before it were never asked for a level, so pre-adoption artifacts read as debt, not defects.
243
-
244
- **Machine-checked at the gate.** The pipeline's own review PASS edges enforce the line before verify:
245
- `residual-scan review-gate` reads the recorded `### Review` body, and a missing, duplicated or
246
- out-of-enum level becomes a **blocking** `review-contract` item — `review → verify` stops and the run
247
- enters `review-fail-triage` with the bounded repair hop, exactly as an open P1–P3 row does. The gate
248
- checks presence and vocabulary only: whether a level is *earned* stays a judgement call (see the
249
- earning rule above), so the report must still argue it.
228
+ **No confidence line (F511, task 1207).** Review reports do not state, and no gate reads, an
229
+ asserted `Confidence: HIGH | MEDIUM | LOW`. A model that can write a PASS can write `HIGH`, so the
230
+ gate grades what is checkable instead: the recorded section's presence and vocabulary, and the
231
+ findings disposition — an open P1–P3 row blocks the edge exactly as before. What a reviewer would
232
+ formerly have compressed into a level belongs in the report body: name the evidence gaps and the
233
+ assumptions explicitly, so a reader can re-check them. (The derived confidence family is
234
+ untouched: feature-verification receipts under ADR-131, the decision subsystem threshold, and
235
+ history-anatomy reading.)
250
236
 
251
237
  **Source citations for external claims (one claim contract, 2026-10-12).** A Finding cell or a
252
238
  Functional Traceability `Evidence` cell that asserts an external API/library claim carries a
@@ -257,8 +243,9 @@ answer's rule verbatim, owned by
257
243
  for external claims — claim markers and accepted forms are defined once there and are not restated
258
244
  here. The findings table's `Location` column does not stand in for it: `Location` anchors the
259
245
  finding's subject, not the claim's source. Cell-free receipts (test counts, reviewed-log notes)
260
- assert no external claim and need no citation. An uncited external claim is an assumption, so it
261
- caps the level the report can defend (above).
246
+ assert no external claim and need no citation. An uncited external claim is an assumption: name it
247
+ as an explicit gap in the report body (above), so a reader can re-check it.
248
+
262
249
 
263
250
  **Machine-checked at the gate (findings table).** `residual-scan review-gate` applies the same two
264
251
  predicates to every finding row: a Finding cell carrying one of the verify lint's claim markers with
@@ -26,5 +26,5 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
26
26
 
27
27
  ## Implementation
28
28
 
29
- Follow the inline procedure in [dev-operations.md](../skills/spur-dev/references/dev-operations.md#8-changelog) (changelog). This is a docs-only generator: run no quality gates (lint, tests, `spur-check`, rules, citation checks).
29
+ Follow the inline procedure in [dev-operations.md](../skills/spur-dev/references/dev-operations.md#8-changelog) (changelog). This is a docs-only generator: run no quality gates (`bun run gate`, lint, typecheck, tests, `spur-check`, rules, citation checks) — a generic "verify before finishing" rule does not apply here.
30
30
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Generate conventional commit message(s) from the current change set via one bounded gather call, optionally commit
3
3
  role: scribe
4
- argument-hint: "[--commit] [--squash] [--all] [--scope <path>]"
4
+ argument-hint: "[--commit] [--squash] [--all] [--scope <path>] [--check <cmd>]"
5
5
  allowed-tools: ["Bash", "Read"]
6
6
  ---
7
7
 
@@ -17,12 +17,13 @@ Implements an inline procedure — see [dev-operations.md](../skills/spur-dev/re
17
17
  | `--squash` | Collapse every concern into one message and one commit; implies `--commit`. | off |
18
18
  | `--all` | Widen the change set past the index to every change in the tree — unstaged **and untracked**. | off |
19
19
  | `--scope` `<path>` | Path filter on the change set; always wins over change-set auto-discovery. | the whole change set |
20
+ | `--check` `<cmd>` | Run `<cmd>` (e.g. `"bun run gate"`) once before committing; non-zero → commit nothing. | off |
20
21
 
21
22
  For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag-glossary.md).
22
23
 
23
24
  ## Usage
24
25
 
25
- /sp:dev-gitmsg [--commit] [--squash] [--all] [--scope <path>]
26
+ /sp:dev-gitmsg [--commit] [--squash] [--all] [--scope <path>] [--check <cmd>]
26
27
 
27
28
  ## Implementation
28
29
 
@@ -35,3 +36,6 @@ commit per concern, split automatically, so the operator is never asked to re-st
35
36
  `--squash` → one commit for everything. An empty index widens to the whole tree only on a
36
37
  message-only run, and says so; a committing run stops there and prints the exact `--all` re-run line
37
38
  instead of guessing.
39
+ No quality gate (`bun run gate`, lint, typecheck, tests, `spur-check`) runs unless `--check <cmd>`
40
+ names one — then it runs once, before any commit, and a failure commits nothing. Gate → auto-fix →
41
+ commit is `/sp:dev-gtd --no-push`.
@@ -24,4 +24,5 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
24
24
  ## Implementation
25
25
 
26
26
  Follow the inline procedure in [dev-operations.md](../skills/spur-dev/references/dev-operations.md#11-handover) (handover).
27
+ Run no quality gate (`bun run gate`, lint, typecheck, tests, `spur-check`); cite results already on record.
27
28
 
@@ -24,6 +24,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
24
24
  ## Implementation
25
25
 
26
26
  Follow [job-dump](../skills/spur-dev/references/dev-operations.md#11a-job-dump), using the shared
27
- handoff template to capture the current job and its remaining work.
27
+ handoff template to capture the current job and its remaining work. Run no quality gate
28
+ (`bun run gate`, lint, typecheck, tests, `spur-check`); copy existing gate results or write `not run`.
28
29
 
29
30
  Skill(skill="sp:spur-dev", args="job-dump $ARGUMENTS")
@@ -18,6 +18,14 @@ Wraps the **sp:spur-dev** skill. Three jobs:
18
18
  `standard` checks only that target sections are structurally complete. It never re-checks what
19
19
  they say. Use `ready` whenever the existing content itself is in doubt.
20
20
 
21
+ **Refine never writes `feature_id`.** It may *report* an orphan task in its result, but linking a
22
+ task to a feature is an operator decision with a lifecycle blast radius: `spur task update <wbs>
23
+ --feature <id>` reopens a `verifying` parent unless `--no-reopen` is passed. Route linking through
24
+ the opt-in [feature-link helper](../skills/spur-dev/references/feature-link-helper.md) (never
25
+ gate-time, never automatic, always confirmed) — observed 2026-10-13: the ready-preparation refine
26
+ that `spur task create` dispatches by default linked a fresh task to `P1` on its own and demoted
27
+ that feature `verifying → active`.
28
+
21
29
  ## Argument Flags
22
30
 
23
31
  | Flag | Description | Default |
@@ -47,9 +55,13 @@ implement without inventing design:
47
55
  1. Audit every existing claim against the current tree: facts, cited sources, fix soundness across
48
56
  all callers, test observability, environment, concurrent work, and scope.
49
57
  2. Correct what is wrong and record each change in a dated `**Refine corrections (<date>)**` block
50
- in Background.
58
+ in Background. When the task bundles several issues, triage each one. An issue that is invalid,
59
+ already fixed or owned elsewhere is removed together with its R-items, Design/Solution notes,
60
+ Plan steps and ACs. If no issue stays valid, cancel the task (`spur task update <wbs> cancelled`)
61
+ and report `cancelled` instead of promoting it.
51
62
  3. Run `spur task check <wbs> --as todo --json`, fill unset priority/estimate, and promote
52
- `backlog → todo`.
63
+ `backlog → todo`. If triage dropped issues, re-estimate and record old → new. Also record a
64
+ title that still names dropped scope; the CLI cannot rename a task.
53
65
  4. Report checklist rows `{id, pass, evidence}`.
54
66
 
55
67
  Refine targets `backlog`/`todo` tasks; a `wip`-or-later task needs explicit operator consent and is
@@ -54,7 +54,13 @@ not a bug.
54
54
  **Depth:** default `standard` keeps the cheap L3 SKIP gate under `--auto`. Use
55
55
  `--depth ready` when handing a feature to another implementer (frozen Design/Requirements/Plan),
56
56
  or when the tasks' existing content is in doubt; thread `--depth` into each per-task refine. Ready
57
- report rows add corrections count, status before → after, and failed checklist ids.
57
+ report rows add corrections count, dropped issues, status before → after, and failed checklist ids.
58
+ Each task's issues are triaged one by one: invalid ones are dropped with their fixes, and a task
59
+ with no valid issue left is `cancelled`. The ready report also proposes merges between overlapping
60
+ tasks, ordering or a shared step for complementary ones, and owning features for tasks without a
61
+ `feature_id`. It executes neither unless
62
+ `--description` names the task and action, for example
63
+ `--description "cancel 0273 and merge its issues into 0269; link 0260 and 0274 to G11"`.
58
64
 
59
65
  > **`--next` dropped** (feature H8, 2026-07-31). Batch-level chaining was a token bomb — each refine
60
66
  > hop is an LLM call, and a large feature means N refine chains fanned out at once. For batch