@gobing-ai/spur 0.4.2 → 0.4.4

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 (168) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/decisions/maker-liveness.yaml +39 -0
  3. package/config/plugin-scripts.json +0 -4
  4. package/config/rules/README.md +1 -0
  5. package/config/rules/docs/sourced-api-claims.yaml +56 -12
  6. package/config/rules/docs/verdict-confidence.yaml +68 -0
  7. package/config/rules/quality/coverage-gate.yaml +13 -0
  8. package/config/rules/recommended-pre-check.yaml +6 -2
  9. package/config/rules/strict/runtime-boundaries.yaml +10 -0
  10. package/config/rules/surface/check-cli-surface.yaml +1 -3
  11. package/config/script-placement-baseline.json +1 -19
  12. package/config/templates/AGENTS.md +7 -0
  13. package/config/workflows/feature-lifecycle.yaml +46 -1
  14. package/config/workflows/feature-verification.yaml +20 -1
  15. package/config/workflows/task-lifecycle.yaml +50 -0
  16. package/config/workflows/task-pipeline.yaml +15 -9
  17. package/package.json +10 -10
  18. package/plugins/sp/README.md +22 -16
  19. package/plugins/sp/agents/super-reviewer.md +46 -0
  20. package/plugins/sp/bunfig.toml +8 -5
  21. package/plugins/sp/commands/dev-changelog.md +1 -1
  22. package/plugins/sp/commands/dev-gitmsg.md +6 -2
  23. package/plugins/sp/commands/dev-handover.md +1 -0
  24. package/plugins/sp/commands/dev-job-dump.md +2 -1
  25. package/plugins/sp/commands/dev-refine.md +14 -2
  26. package/plugins/sp/commands/dev-refineall.md +7 -1
  27. package/plugins/sp/commands/dev-review.md +1 -0
  28. package/plugins/sp/hooks/careful-guard.ts +1 -1
  29. package/plugins/sp/hooks/context-post-tool.ts +7 -427
  30. package/plugins/sp/hooks/context-session-start.ts +5 -213
  31. package/plugins/sp/hooks/context-session-stop.ts +5 -191
  32. package/plugins/sp/hooks/pi/guard-extension.ts +6 -5
  33. package/plugins/sp/hooks/task-write-guard.ts +1 -1
  34. package/plugins/sp/{hooks → lib}/agent-hint.ts +1 -1
  35. package/plugins/sp/lib/context-post-tool.ts +432 -0
  36. package/plugins/sp/lib/context-session-start.ts +214 -0
  37. package/plugins/sp/lib/context-session-stop.ts +196 -0
  38. package/plugins/sp/lib/dogfood-pipeline.ts +265 -0
  39. package/plugins/sp/lib/dogfood-report.ts +278 -0
  40. package/plugins/sp/lib/history-anatomy.generated.mjs +18 -18
  41. package/plugins/sp/lib/idea-handoff.generated.mjs +91 -91
  42. package/plugins/sp/lib/inline-run-app.ts +40 -0
  43. package/plugins/sp/lib/inline-run.generated.d.mts +3 -3
  44. package/plugins/sp/lib/inline-run.generated.mjs +1425 -212
  45. package/plugins/sp/lib/plan-projection.generated.d.mts +150 -0
  46. package/plugins/sp/lib/plan-projection.generated.mjs +623 -9
  47. package/plugins/sp/lib/quality-gate.generated.d.mts +1 -0
  48. package/plugins/sp/lib/quality-gate.generated.mjs +13809 -13969
  49. package/plugins/sp/lib/residual-scan.generated.d.mts +20 -1
  50. package/plugins/sp/lib/residual-scan.generated.mjs +120 -25
  51. package/plugins/sp/lib/run-summary-core.ts +34 -370
  52. package/plugins/sp/lib/step-profile.generated.mjs +8 -8
  53. package/plugins/sp/lib/transcript.ts +37 -228
  54. package/plugins/sp/plugin.json +1 -1
  55. package/plugins/sp/scripts/batch-plan.mjs +619 -11
  56. package/plugins/sp/scripts/batch-preflight.mjs +57 -13
  57. package/plugins/sp/scripts/batch-preflight.ts +35 -295
  58. package/plugins/sp/scripts/commit-guard.mjs +6 -6
  59. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +127 -108
  60. package/plugins/sp/scripts/daily-summary/daily-summary.ts +111 -104
  61. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.mjs +13 -12
  62. package/plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts +7 -265
  63. package/plugins/sp/scripts/dogfood-testing/validate-report.mjs +7 -4
  64. package/plugins/sp/scripts/dogfood-testing/validate-report.ts +6 -272
  65. package/plugins/sp/scripts/feature-verification-steps.mjs +20 -125
  66. package/plugins/sp/scripts/feature-verification-steps.ts +57 -181
  67. package/plugins/sp/scripts/history-anatomy-cache.mjs +19 -19
  68. package/plugins/sp/scripts/idea-handoff.mjs +2 -2
  69. package/plugins/sp/scripts/inline-run-dispatch.mjs +25 -24
  70. package/plugins/sp/scripts/inline-run-dispatch.ts +1 -21
  71. package/plugins/sp/scripts/inline-run-setup.mjs +164 -137
  72. package/plugins/sp/scripts/inline-run-setup.ts +1 -21
  73. package/plugins/sp/scripts/persist-out-check.mjs +5 -5
  74. package/plugins/sp/scripts/pr-reviewing.mjs +13 -13
  75. package/plugins/sp/scripts/quality-gate.mjs +13730 -13887
  76. package/plugins/sp/scripts/residual-scan.mjs +129 -31
  77. package/plugins/sp/scripts/residual-scan.ts +16 -13
  78. package/plugins/sp/scripts/run-summary.mjs +166 -112
  79. package/plugins/sp/scripts/run-summary.ts +7 -5
  80. package/plugins/sp/scripts/script-root.mjs +6 -6
  81. package/plugins/sp/scripts/session-timeline.mjs +62 -35
  82. package/plugins/sp/scripts/task-diffstat.mjs +19 -9
  83. package/plugins/sp/scripts/task-diffstat.ts +8 -39
  84. package/plugins/sp/scripts/workflow-step-profile.mjs +12 -12
  85. package/plugins/sp/scripts/wrapup-drift-probe.mjs +9 -9
  86. package/plugins/sp/scripts/wrapup-steps.mjs +25 -25
  87. package/plugins/sp/skills/code-implementation/SKILL.md +7 -1
  88. package/plugins/sp/skills/code-verification/references/secu-review.md +2 -1
  89. package/plugins/sp/skills/code-verification/references/verdict-schema.md +4 -0
  90. package/plugins/sp/skills/dogfood-testing/SKILL.md +2 -2
  91. package/plugins/sp/skills/next-feature/SKILL.md +1 -1
  92. package/plugins/sp/skills/next-router/SKILL.md +3 -1
  93. package/plugins/sp/skills/next-router/references/routing-table.md +9 -3
  94. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
  95. package/plugins/sp/skills/source-driven-development/SKILL.md +7 -4
  96. package/plugins/sp/skills/spur-cli/references/builder.md +3 -2
  97. package/plugins/sp/skills/spur-cli/references/decision.md +32 -7
  98. package/plugins/sp/skills/spur-cli/references/features.md +46 -5
  99. package/plugins/sp/skills/spur-cli/references/tasks.md +24 -4
  100. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +8 -1
  101. package/plugins/sp/skills/spur-dev/references/dev-operations.md +37 -11
  102. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +1 -1
  103. package/plugins/sp/skills/spur-dev/references/execution-batch.md +19 -6
  104. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +22 -0
  105. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +14 -0
  106. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +4 -2
  107. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +49 -12
  108. package/schemas/section-matrix.schema.json +3 -2
  109. package/spur.js +66591 -73262
  110. package/web/_astro/{BoardApp.B3GQZvj8.js → BoardApp.Niubpe6z.js} +1 -1
  111. package/web/_astro/{BoardApp.BT7L2kSb.js → BoardApp.hF0RAIrg.js} +150 -150
  112. package/web/_astro/TaskDetail.DJpapt38.js +1 -0
  113. package/web/_astro/{arc.vaT7tPOB.js → arc.BgKcK0i8.js} +1 -1
  114. package/web/_astro/{architectureDiagram-3BPJPVTR.DRMmTjkN.js → architectureDiagram-3BPJPVTR.ChP-Ig0V.js} +1 -1
  115. package/web/_astro/{blockDiagram-GPEHLZMM.cla0LO_q.js → blockDiagram-GPEHLZMM.BVaCBoeN.js} +1 -1
  116. package/web/_astro/{c4Diagram-AAUBKEIU.D4YAIBKn.js → c4Diagram-AAUBKEIU.CHSDpEO5.js} +1 -1
  117. package/web/_astro/channel.DkpvN2tD.js +1 -0
  118. package/web/_astro/{chunk-2J33WTMH.BrSJbMRZ.js → chunk-2J33WTMH.MYRcYVRa.js} +1 -1
  119. package/web/_astro/{chunk-4BX2VUAB.CuLMgKF5.js → chunk-4BX2VUAB.S5j22Zqa.js} +1 -1
  120. package/web/_astro/{chunk-55IACEB6.zkvgu54F.js → chunk-55IACEB6.gciRPvmZ.js} +1 -1
  121. package/web/_astro/{chunk-727SXJPM.DxWkACh8.js → chunk-727SXJPM.CdqrSQkX.js} +1 -1
  122. package/web/_astro/{chunk-AQP2D5EJ.42XrmIlH.js → chunk-AQP2D5EJ.CyokdHT3.js} +1 -1
  123. package/web/_astro/{chunk-FMBD7UC4.Bao2wMK9.js → chunk-FMBD7UC4.Bg9KJhjW.js} +1 -1
  124. package/web/_astro/{chunk-ND2GUHAM.BhydojD1.js → chunk-ND2GUHAM.1gxxI-vD.js} +1 -1
  125. package/web/_astro/{chunk-QZHKN3VN.CmZ82g-H.js → chunk-QZHKN3VN.DDEYtCKU.js} +1 -1
  126. package/web/_astro/{classDiagram-4FO5ZUOK.Blr83Gt_.js → classDiagram-4FO5ZUOK.Ch3zi37T.js} +1 -1
  127. package/web/_astro/{classDiagram-v2-Q7XG4LA2.Blr83Gt_.js → classDiagram-v2-Q7XG4LA2.Ch3zi37T.js} +1 -1
  128. package/web/_astro/{cose-bilkent-S5V4N54A.qmfv0SPn.js → cose-bilkent-S5V4N54A.D2q5AINI.js} +1 -1
  129. package/web/_astro/{cynefin-OW5HDTMX.BtELhXPR.js → cynefin-OW5HDTMX.BA9kC2YT.js} +1 -1
  130. package/web/_astro/{dagre-BM42HDAG.AWmaAvXo.js → dagre-BM42HDAG.CHO08nRp.js} +1 -1
  131. package/web/_astro/{diagram-2AECGRRQ.DdH34KDi.js → diagram-2AECGRRQ.BfFQt0LW.js} +1 -1
  132. package/web/_astro/{diagram-5GNKFQAL.BmNPix1k.js → diagram-5GNKFQAL.CHMwMTe4.js} +1 -1
  133. package/web/_astro/{diagram-KO2AKTUF.BNQd_Ppo.js → diagram-KO2AKTUF.BJ-7gK-w.js} +1 -1
  134. package/web/_astro/{diagram-LMA3HP47.BAPgDi0e.js → diagram-LMA3HP47.C5xqcc0t.js} +1 -1
  135. package/web/_astro/{diagram-OG6HWLK6.DZ4zyLdC.js → diagram-OG6HWLK6.C2pQjfrC.js} +1 -1
  136. package/web/_astro/{erDiagram-TEJ5UH35.Q1TySMmw.js → erDiagram-TEJ5UH35._FoNyxgC.js} +1 -1
  137. package/web/_astro/{flowDiagram-I6XJVG4X.BXhFBicG.js → flowDiagram-I6XJVG4X.B_ENkT2I.js} +1 -1
  138. package/web/_astro/{ganttDiagram-6RSMTGT7.vHSgcuo2.js → ganttDiagram-6RSMTGT7.B3q8h77C.js} +1 -1
  139. package/web/_astro/{gitGraphDiagram-PVQCEYII.Bi1f73C7.js → gitGraphDiagram-PVQCEYII.QWZFDboZ.js} +1 -1
  140. package/web/_astro/index.BFyW13JJ.css +1 -0
  141. package/web/_astro/{infoDiagram-5YYISTIA.DPvXZEWm.js → infoDiagram-5YYISTIA.Cs6eEc92.js} +1 -1
  142. package/web/_astro/{ishikawaDiagram-YF4QCWOH.Cz829fsV.js → ishikawaDiagram-YF4QCWOH.BU9DJMHA.js} +1 -1
  143. package/web/_astro/{journeyDiagram-JHISSGLW.enRnB9Me.js → journeyDiagram-JHISSGLW.D35k6Jpe.js} +1 -1
  144. package/web/_astro/{kanban-definition-UN3LZRKU.DnTNk6d2.js → kanban-definition-UN3LZRKU.DBqcAT4m.js} +1 -1
  145. package/web/_astro/{linear.BzGnBwNL.js → linear.D-LSNK8W.js} +1 -1
  146. package/web/_astro/{mermaid.core.CSbTpIVz.js → mermaid.core.CSruWVOa.js} +4 -4
  147. package/web/_astro/{mindmap-definition-RKZ34NQL.DGJDy8zT.js → mindmap-definition-RKZ34NQL.BiFaUsfj.js} +1 -1
  148. package/web/_astro/{pieDiagram-4H26LBE5.HSPdi5_8.js → pieDiagram-4H26LBE5.D1KTKqb9.js} +1 -1
  149. package/web/_astro/{quadrantDiagram-W4KKPZXB.6Gv8mz2Y.js → quadrantDiagram-W4KKPZXB.DBHflsMG.js} +1 -1
  150. package/web/_astro/{requirementDiagram-4Y6WPE33.CnBCtFwa.js → requirementDiagram-4Y6WPE33.hwX9CNdk.js} +1 -1
  151. package/web/_astro/{sankeyDiagram-5OEKKPKP.5M8VWAu8.js → sankeyDiagram-5OEKKPKP.DkI8mJiE.js} +1 -1
  152. package/web/_astro/{sequenceDiagram-3UESZ5HK.DN41XN-U.js → sequenceDiagram-3UESZ5HK.DMz7jBDx.js} +1 -1
  153. package/web/_astro/{stateDiagram-AJRCARHV.ErOO3W8j.js → stateDiagram-AJRCARHV.B6Ef2xJ1.js} +1 -1
  154. package/web/_astro/{stateDiagram-v2-BHNVJYJU.B_ZHICM-.js → stateDiagram-v2-BHNVJYJU.CgoaufB9.js} +1 -1
  155. package/web/_astro/{timeline-definition-PNZ67QCA.CWdosr07.js → timeline-definition-PNZ67QCA.B3c8h1t-.js} +1 -1
  156. package/web/_astro/{vennDiagram-CIIHVFJN.BHzYjNV5.js → vennDiagram-CIIHVFJN.BdHPAxAb.js} +1 -1
  157. package/web/_astro/{wardleyDiagram-YWT4CUSO.h8x4IwPX.js → wardleyDiagram-YWT4CUSO.BrJXPPAj.js} +1 -1
  158. package/web/_astro/{xychartDiagram-2RQKCTM6.RTapW2X8.js → xychartDiagram-2RQKCTM6.CMH5yFsV.js} +1 -1
  159. package/web/index.html +2 -2
  160. package/web/spur_logo.svg +1 -1
  161. package/config/proportional-route-table.ts +0 -155
  162. package/plugins/sp/scripts/daily-summary/logger.ts +0 -28
  163. package/web/_astro/TaskDetail.Cxov1_N_.js +0 -1
  164. package/web/_astro/channel.D4nG9YLf.js +0 -1
  165. package/web/_astro/index.BhSwN8yY.css +0 -1
  166. /package/plugins/sp/{hooks → lib}/context-owner.ts +0 -0
  167. /package/plugins/sp/{hooks → lib}/destructive-policy.ts +0 -0
  168. /package/plugins/sp/{hooks → lib}/task-file-policy.ts +0 -0
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.4.2",
10
+ "version": "0.4.4",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -0,0 +1,39 @@
1
+ $schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
2
+ # Liveness probe catalog (feature P11, docs/design/decision-observability-and-adoption.md §3.4).
3
+ #
4
+ # `maker-liveness` is served by exactly one caller: `spur decision status --probe`,
5
+ # which asks it once per distinct registered effective maker to prove the maker
6
+ # answers *now* rather than inferring health from configuration. No workflow may
7
+ # reference this id — a decision whose answer classifies nothing real has no place
8
+ # in a run, and `spur decision status --reliability` would otherwise count probe
9
+ # runs as adoption evidence.
10
+ #
11
+ # The probe writes no `decision_logs` row and emits no `decision.*` event, so these
12
+ # runs never enter the recorded evidence the same report displays next to them.
13
+ #
14
+ # Resolution: this file ships in the shared layer (the installed package's
15
+ # config/decisions/). A project can override it per basename through
16
+ # .spur/decisions/ or decisions.paths (first layer wins, ADR-113 style). Replacing it
17
+ # with a catalog that omits the id makes `--probe` fail loudly before any maker call.
18
+ version: 1
19
+
20
+ defaults:
21
+ # Deliberately not the 0.7 upstream / 0.8 catalog floor. minConfidence gates
22
+ # whether an *answer* is accepted; the probe asks whether the *maker* answered.
23
+ # Under a 0.8 floor a live maker reporting 0.6 would fall back and the probe would
24
+ # report "not working" for a backend that is working. A maker that never answered
25
+ # (no-backend, timeout, error) falls back regardless of this value.
26
+ minConfidence: 0
27
+
28
+ decisions:
29
+ maker-liveness:
30
+ type: choice
31
+ # Rendered as the question when the caller passes no `instructions`: the probe
32
+ # always does pass one, so this description is the fallback wording, not the
33
+ # probe prompt.
34
+ description: >
35
+ Liveness probe. Answer `ok` if this maker can serve a decision right now.
36
+ criteria:
37
+ ok: The maker answered the question it was asked.
38
+ unclear: The maker could not answer.
39
+ fallback: unclear
@@ -22,10 +22,6 @@
22
22
  "contract": "standard",
23
23
  "twin": "daily-summary/daily-summary.mjs"
24
24
  },
25
- {
26
- "rel": "daily-summary/logger.ts",
27
- "contract": "repo-only"
28
- },
29
25
  {
30
26
  "rel": "dogfood-testing/detect-pipeline-driving.ts",
31
27
  "contract": "standard",
@@ -17,6 +17,7 @@ install or to ts-libs.
17
17
  | `surface` | `surface/` | CLI surface consistency (registerXxxCommand wiring, --json serialization) |
18
18
  | `migration` | `migration/` | Transitional helpers for the regex → `rg` evaluator move (`rg-dialect`) |
19
19
  | `ui` | `ui/` | Web UI seam boundaries (import seam, daisyUI class leak) |
20
+ | `docs` | `docs/` | Sourced API/library claims in markdown — citation anchor + HIGH/MEDIUM/LOW level. Advisory (`info`), and deliberately **not** in a preset: see the file header for its calibration audit and the one-line promotion step. |
20
21
 
21
22
  ## Presets
22
23
 
@@ -9,22 +9,43 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
9
9
  # gate runs --fail-on warning, so this rule surfaces findings for review without
10
10
  # reddening gates — changed-file enforcement happens in SECUA review).
11
11
  #
12
+ # Calibration audit (2026-10-12, `spur rule run --file … --json`, unsuppressed):
13
+ # the category was pulled from `recommended-pre-check` on 2026-10-08 for "finding
14
+ # noise" — 593 findings. The audit split them 580 `cited-version-strings` /
15
+ # 13 `cited-api-claims`, and 579 of the 580 were false positives on two shapes
16
+ # that are not external claims at all: a document's own version
17
+ # (`docs/00_ADR.md:5` → `version: 1.69.0`), a section number in a heading
18
+ # (`docs/04_DESIGN.md:116` → `### 1.0.1 Shared option registry`) and a
19
+ # `§`-numbered cross-reference (`docs/00_ADR.md:1118` → `§1.2.1`). All three are
20
+ # excluded by the pattern below — the first two on the line's shape, the third on
21
+ # the token itself. The remaining source was a stale exclude list that stopped at
22
+ # `docs/tasks4/` while the active corpus folder is `docs/tasks5/`, which alone
23
+ # produced 226 findings; it is now one `docs/tasks*/**` glob. 593 → 330 after those
24
+ # two fixes, then 277 once the `§` shape was excluded too — the residual are
25
+ # version-pinned package claims that genuinely lack a same-line anchor, and they
26
+ # stay visible rather than suppressed.
27
+ #
12
28
  # The semantic contract — every external API/library claim carries a source
13
29
  # citation (URL or path:line) AND a confidence level (HIGH/MEDIUM/LOW) — is
14
30
  # owned by the sp-source-driven-development skill and verified in SECUA review
15
- # (code-verification secu-review checklist). Generic "supports/requires" prose
16
- # is deliberately out of scope here: in this corpus it is structural writing,
17
- # not external API assertion, and would drown the signal.
31
+ # (code-verification secu-review checklist). These rules are its deterministic
32
+ # backstop: the two `cited-*` rules cover the citation half, and
33
+ # `cited-api-claims-confidence` covers the level half. All are severity `info`,
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.
18
37
  include:
19
38
  - "docs/**/*.md"
20
39
  - "plugins/sp/skills/**/references/**/*.md"
21
40
  exclude:
22
41
  # Legacy task archives are historical records — retro-citing ~900 closed
23
- # lines is make-work; the tripwire targets active authoring surfaces.
24
- - "docs/tasks/"
25
- - "docs/tasks2/"
26
- - "docs/tasks3/"
27
- - "docs/tasks4/"
42
+ # lines is make-work; the tripwire targets active authoring surfaces. One glob
43
+ # rather than the literal tasks/…tasks4/ list that let the active folder through.
44
+ # The trailing `/**` is load-bearing: `docs/tasks*/` ends as a pattern segment
45
+ # tested against `x.md`, so the anchored matcher binds nothing and the fragment
46
+ # fallback strips the `*` down to `docs/tasks/` — which is why that form
47
+ # silently excluded nothing (measured 2026-10-12).
48
+ - "docs/tasks*/**"
28
49
  - "drizzle/**"
29
50
  - "**/node_modules/**"
30
51
  rules:
@@ -41,10 +62,15 @@ rules:
41
62
  config:
42
63
  mode: forbid
43
64
  # Fire when the line has NO citation anchor (no URL, no path:line) AND
44
- # contains a semver-ish token. Lookarounds exclude IPs (127.0.0.1) and
45
- # longer dotted numerics; fenced-code lines are out of regex reach —
46
- # that residual noise is why this is warning, not error.
47
- pattern: "^(?!.*(?:https?://|(?:[\\w.-]+/)+[\\w.-]+:\\d+)).*(?<![\\d.])\\d+\\.\\d+\\.\\d+(?!\\.\\d)"
65
+ # contains a semver-ish token. Lookarounds exclude IPs (127.0.0.1),
66
+ # longer dotted numerics, a heading's section number (`### 1.0.1 Title`),
67
+ # a document-version metadata line (`version: 1.69.0`) and a `§`-numbered
68
+ # section reference (`§7.3.1`) — none of which is an external claim;
69
+ # fenced-code lines are out of regex reach — that residual noise is why
70
+ # this is info, not warning. The `§` guard sits on the token itself, not on
71
+ # the line, so a line carrying both a section reference and a real version
72
+ # still fires on the version.
73
+ pattern: "^(?!.*(?:https?://|(?:[\\w.-]+/)+[\\w.-]+:\\d+))(?!\\s*#{1,6}\\s+\\d+\\.\\d+\\.\\d+)(?!\\s*[\\w-]+:\\s*\\d+\\.\\d+\\.\\d+\\s*$).*(?<![\\d.§])\\d+\\.\\d+\\.\\d+(?!\\.\\d)"
48
74
  - id: cited-api-claims
49
75
  description: >
50
76
  A markdown line making a time- or version-anchored external API claim
@@ -58,3 +84,21 @@ rules:
58
84
  config:
59
85
  mode: forbid
60
86
  pattern: "^(?!.*(?:https?://|(?:[\\w.-]+/)+[\\w.-]+:\\d+)).*\\b(?:deprecated (?:since|in|as of)|introduced in|added in|available since|stable since)\\b"
87
+ - id: cited-api-claims-confidence
88
+ description: >
89
+ A markdown line making a time- or version-anchored external API claim
90
+ ("deprecated since 1.2", "introduced in v3", "available since 0.9") must
91
+ also state its confidence level — HIGH, MEDIUM or LOW — so a reader can
92
+ tell a checked fact from model memory; contract in
93
+ sp-source-driven-development. Pairs with `cited-api-claims`, which covers
94
+ the citation half: a line missing both halves reports once per rule,
95
+ deliberately, because each missing half is its own defect.
96
+ severity: info
97
+ evaluator:
98
+ type: regex
99
+ config:
100
+ mode: forbid
101
+ # Fires on a claim line carrying no uppercase level token. The verbs match
102
+ # `cited-api-claims` exactly, so the two rules never disagree about which
103
+ # lines are claims.
104
+ pattern: "^(?!.*\\b(?:HIGH|MEDIUM|LOW)\\b).*\\b(?:deprecated (?:since|in|as of)|introduced in|added in|available since|stable since)\\b"
@@ -0,0 +1,68 @@
1
+ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
+ # Verdict-confidence rules (report corpus) — a committed verification record that states
3
+ # a machine `Verdict:` line must also state the verifier's confidence, so a reader can
4
+ # tell a PASS the verifier stands behind from one it would not.
5
+ #
6
+ # Contract owners: `Confidence: HIGH|MEDIUM|LOW` is specified for verify answers by
7
+ # plugins/sp/skills/code-verification/SKILL.md (one `Verdict: PASS|PARTIAL|FAIL` line, one
8
+ # `Confidence:` line, then the traceability tables) and for review reports by
9
+ # plugins/sp/agents/super-reviewer.md. Both are already enforced for pipeline answers —
10
+ # packages/app/src/services/verify-answer-lint.ts (`confidence-missing`,
11
+ # `confidence-value`, and the coherence pair `confidence-unwarranted` /
12
+ # `confidence-understated`) plus the verify stamp in config/workflows/task-pipeline.yaml —
13
+ # but no rule read the standalone report documents agents commit under `docs/`. This file
14
+ # is that backstop: the same three-level vocabulary, checked at the document level.
15
+ #
16
+ # Shape: one file-spanning forbidden match (`multiline: true` hands the evaluator the whole
17
+ # document and the negative lookahead spans the newline) instead of line counting. The
18
+ # lookahead demands a valid level, so a hedge (`Confidence: mostly`) reads as missing too.
19
+ # The verdict prefix requires the closed `PASS|PARTIAL|FAIL` value on its own line, which is
20
+ # what separates a record from prose: docs/reports/i31/0912-workflow-baseline.md:84 and
21
+ # i31/1107-runall-p1-pilot.md:9 both open a bolded *conclusion* sentence
22
+ # ("**Verdict: `partial — INSUFFICIENT_EVIDENCE retained`.**") and are not this contract.
23
+ #
24
+ # Severity `info`, and deliberately not in a preset — the same calibration choice the `docs`
25
+ # category makes for sourced claims: findings surface for review without reddening gates
26
+ # (`recommended-pre-check` runs `--fail-on warning`). To promote it, add `- docs` to that
27
+ # preset's `extends` once the residual is triaged.
28
+ #
29
+ # Calibration (2026-10-13, `spur rule run --file config/rules/docs/verdict-confidence.yaml
30
+ # --json`, unsuppressed): 3 findings over the 91 documents the include globs matched at that
31
+ # timestamp (29 under docs/reports/, 62 under docs/plans/), all three the hole this closes —
32
+ # docs/reports/2026-09-12-i21-verifyall.md:3,
33
+ # docs/reports/2026-10-01-E71-force-verification.md:3 and
34
+ # docs/reports/g61-verifyall-2026-09-12.md:3 each open `Verdict: PASS` and state no
35
+ # confidence level anywhere in the document. They stay visible rather than suppressed:
36
+ # retro-fitting a level into a historical record would invent the verifier's own claim.
37
+ # Both directions were controlled in the same run: a scratch report holding
38
+ # `Verdict: PASS` + `Confidence: HIGH` is not flagged, and the same file with
39
+ # `Confidence: mostly` is.
40
+ #
41
+ # Include is deliberately the report corpus. `docs/plans/*brainstorm*.md` states confidence
42
+ # as prose with its rationale (`**Confidence: HIGH.** All primitives … are verified present`,
43
+ # 61 such lines across 18 plans) — a different, human-facing contract that a
44
+ # level-only vocabulary check would drown in false positives, and those plans carry no
45
+ # machine verdict line to anchor on.
46
+ include:
47
+ - "docs/reports/**/*.md"
48
+ - "docs/plans/**/*.md"
49
+ exclude:
50
+ - "docs/tasks*/**"
51
+ rules:
52
+ - id: verdict-line-confidence-missing
53
+ description: >
54
+ A committed verification record that asserts a machine verdict line
55
+ (`Verdict: PASS|PARTIAL|FAIL`) must follow it with the verifier's confidence level —
56
+ `Confidence: HIGH|MEDIUM|LOW` — so a reader can tell a verdict the verifier stands
57
+ behind from one it would not. Contract in sp-code-verification (verify answers) and
58
+ sp-super-reviewer (review reports); a missing level is a lint failure for pipeline
59
+ answers (`confidence-missing`), and this rule is the backstop for the reports those
60
+ surfaces do not read.
61
+ severity: info
62
+ evaluator:
63
+ type: regex
64
+ config:
65
+ mode: forbid
66
+ multiline: true
67
+ flags: "i"
68
+ pattern: "^[ \\t]*\\**Verdict\\**:\\**[ \\t]*(?:PASS|PARTIAL|FAIL)\\**[ \\t]*\\n(?:[ \\t]*\\n)*(?![ \\t]*\\**Confidence\\**:\\**[ \\t]*\\**(?:HIGH|MEDIUM|LOW)\\**[ \\t]*\\.?[ \\t]*$)"
@@ -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`
@@ -8,8 +8,12 @@ $schema: "@gobing-ai/spur/schemas/preset.schema.json"
8
8
  # post-check alongside coverage-gate.
9
9
  #
10
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.
11
+ # restore it (add `- docs` back) once sourcing-claim finding noise is triaged.
12
+ # The category now holds two files and both residuals must be triaged first:
13
+ # `docs/sourced-api-claims.yaml` (advisory citation/level checks on claim lines) and
14
+ # `docs/verdict-confidence.yaml` (a machine `Verdict:` report must state its
15
+ # HIGH/MEDIUM/LOW level; 3 historical reports under docs/reports/ predate the
16
+ # contract). Recapture the raw-json-baseline fixtures in the same change.
13
17
  name: recommended-pre-check
14
18
  extends:
15
19
  - typescript
@@ -38,6 +38,12 @@ rules:
38
38
 
39
39
  # Low-level system primitives:
40
40
  - "packages/app/src/services/quality-gate.ts" # gate runs `sh -c` with stdout+stderr merged onto ONE fd; ProcessExecutor captures streams separately and cannot reproduce the stream-order contract (task 1006 R1; mirrors the history-anatomy bundling exemptions)
41
+ # The feature-verification pass runs one long command with stdout+stderr merged onto the
42
+ # run's single log fd and a 4 h ceiling (the frozen contract from task 0915: `safe argv
43
+ # spawn, timeout and status handling`). ProcessExecutor captures the two streams separately
44
+ # and exposes no timeout, so it cannot reproduce either half (task 1176 R2; same class as
45
+ # the quality-gate exemption above).
46
+ - "packages/app/src/workflow/feature-verification-run.ts"
41
47
 
42
48
  - id: no-direct-fs-io
43
49
  description: "Prefer ts-runtime's FileSystem seam for fs IO."
@@ -64,6 +70,7 @@ rules:
64
70
  - "packages/app/src/services/token-ledger-service.ts" # FD byte-window log tailing
65
71
  - "packages/app/src/services/token-ledger-watcher.ts" # node:fs watch() live watcher
66
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)
67
74
  - "packages/app/src/services/project-server-owner.ts" # atomic mkdir lifetime claim + unique-marker stale recovery; FileSystem has no exclusive mkdir primitive (1082)
68
75
  - "packages/app/src/services/slash-commands-service.ts" # synchronous ~/.config/spur/slash_commands.json persistence (mirrors project-registry.ts)
69
76
  - "packages/app/src/services/agent-usage-producer.ts" # atomic agent-usage snapshot write (tmp + rename, mirrors project-registry.ts; task 0892 R1)
@@ -74,7 +81,9 @@ rules:
74
81
  - "apps/cli/src/commands/workflow.ts" # FD byte-window tail of the mid-run run log for `workflow trace --follow` streaming (task 0428 / feature D2); readSync at offset over the observability sink's FDs
75
82
  - "apps/web/src/modules/discover.ts" # Vite/Astro module scanner fallback under bun test
76
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)
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)
77
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)
78
87
 
79
88
  # Electron Node adapters cannot load Bun runtime implementations; keep the
80
89
  # synchronous existence/directory probes injected for unit testing (desktop contract).
@@ -84,6 +93,7 @@ rules:
84
93
  # Synchronous bootstrap & path resolution:
85
94
  - "packages/config/src/bundled-config.ts" # sync bundledConfigRoot() directory walk
86
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)
87
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
88
98
  - "packages/app/src/services/project-start.ts" # sync CLI binary path checks before daemon spawn
89
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:
@@ -16,32 +16,14 @@
16
16
  "reason": "Keep (budget exemption; reviewed W4) (plan \u00a72)",
17
17
  "exempt": true
18
18
  },
19
- "plugins/sp/scripts/feature-verification-steps.ts": {
20
- "kinds": ["budget"],
21
- "reason": "Keep (ADR-119 receipt writer; budget exemption) (plan \u00a72)",
22
- "exempt": true
23
- },
24
19
  "plugins/sp/scripts/wrapup-drift-probe.ts": {
25
20
  "kinds": ["budget", "corpus-parse"],
26
21
  "reason": "Keep (glue over capture file; budget exemption) (plan \u00a72)",
27
22
  "exempt": true
28
23
  },
29
24
  "plugins/sp/scripts/daily-summary/daily-summary.ts": {
30
- "kinds": ["budget", "db-import"],
31
- "reason": "Keep (daily-summary/, plan \u00a72); read-only history-health query via dynamic bun:sqlite import (task 1018)"
32
- },
33
- "plugins/sp/scripts/dogfood-testing/detect-pipeline-driving.ts": {
34
25
  "kinds": ["budget"],
35
- "reason": "Keep (dogfood-testing/, plan \u00a72)"
36
- },
37
- "plugins/sp/scripts/dogfood-testing/validate-report.ts": {
38
- "kinds": ["budget"],
39
- "reason": "Keep (dogfood-testing/, plan \u00a72)"
40
- },
41
- "plugins/sp/hooks/context-post-tool.ts": {
42
- "kinds": ["budget"],
43
- "reason": "Keep: ADR-129 core (budget exemption) (plan \u00a72)",
44
- "exempt": true
26
+ "reason": "Keep (daily-summary/, plan \u00a72); read-only history-health reads via the app service (task 1178)"
45
27
  },
46
28
  "plugins/sp/hooks/pi/guard-extension.ts": {
47
29
  "kinds": ["budget"],
@@ -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
@@ -9,7 +9,7 @@
9
9
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
10
10
  kind: state-machine
11
11
  name: feature-lifecycle
12
- version: "2"
12
+ version: "3"
13
13
  description: >
14
14
  Feature lifecycle FSM (design §2.3, §5.1, DD-13). States are the canonical
15
15
  FeatureStatus vocabulary; transitions encode the §2.3 graph including the
@@ -64,6 +64,11 @@ states:
64
64
  description: Completed and verified.
65
65
  - id: cancelled
66
66
  description: Terminal — abandoned.
67
+ - id: deprecated
68
+ description: >
69
+ Retained and frozen (ADR-136). Non-terminal: the record stays readable and
70
+ countable, nothing may attach new work to it, and leaving it is explicit —
71
+ un-deprecate to active, or cancelled once the feature is removed.
67
72
 
68
73
  transitions:
69
74
  # Forward path: backlog → active → verifying → done
@@ -142,3 +147,43 @@ transitions:
142
147
  description: Cancel feature
143
148
  guard:
144
149
  kind: always
150
+
151
+ # Deprecate: any non-terminal-or-done state → deprecated (frozen, retained — ADR-136)
152
+ - from: backlog
153
+ to: deprecated
154
+ description: Deprecate feature (frozen, retained)
155
+ guard:
156
+ kind: always
157
+ - from: active
158
+ to: deprecated
159
+ description: Deprecate feature (frozen, retained)
160
+ guard:
161
+ kind: always
162
+ - from: verifying
163
+ to: deprecated
164
+ description: Deprecate feature (frozen, retained)
165
+ guard:
166
+ kind: always
167
+ - from: blocked
168
+ to: deprecated
169
+ description: Deprecate feature (frozen, retained)
170
+ guard:
171
+ kind: always
172
+ - from: done
173
+ to: deprecated
174
+ description: Deprecate feature (frozen, retained)
175
+ guard:
176
+ kind: always
177
+
178
+ # Exits out of deprecated: un-deprecate or remove only. Any other edge is
179
+ # undeclared and refused by the graph (ADR-135).
180
+ - from: deprecated
181
+ to: active
182
+ description: Un-deprecate (mandatory History entry)
183
+ guard:
184
+ kind: always
185
+ - from: deprecated
186
+ to: cancelled
187
+ description: Remove deprecated feature
188
+ guard:
189
+ kind: always
@@ -10,6 +10,17 @@
10
10
  #
11
11
  # Run: spur workflow run feature-verification.yaml --vars '{"featureId":"D63"}'
12
12
  #
13
+ # No project-side override is required (task 1185, A33). Since the pass moved into the
14
+ # application (1176 / efd78f058) the bundled definition owns it end to end, so a
15
+ # project-layer copy of this file (plus a rooted port under `.spur/scripts/`) is a
16
+ # leftover — the port was written against an entry export contract that has since
17
+ # changed. Remove the override so this definition applies, or migrate the port to the
18
+ # current app-owned operation `runFeatureVerification` (the generated inline bundle's
19
+ # export). If a stale consumer is still reached, feature-lifecycle's `verifying` entry
20
+ # names it: the override path, the consumer script, the export it requires that the
21
+ # shipped entry no longer provides, and the entry path. Reinstalling or upgrading the
22
+ # plugin cannot supply a retired export — only the two remedies above can.
23
+ #
13
24
  # Shape: verify -> done | failed. The onEnter step runs the standard script
14
25
  # `feature-verification-steps.ts` (no public CLI verb, D63 task 0915): it
15
26
  # resolves this very definition for the verifier identity (name, source path,
@@ -40,6 +51,14 @@ vars:
40
51
  featureId: "X"
41
52
  spurBin: "spur"
42
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"
43
62
  __runId: ""
44
63
 
45
64
  states:
@@ -59,7 +78,7 @@ states:
59
78
  - kind: shell
60
79
  options:
61
80
  command: >-
62
- 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
63
82
 
64
83
  - id: done
65
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
@@ -1312,11 +1312,16 @@ transitions:
1312
1312
  # re-enters quality → review → verify on a fresh digest. Before 1088 a FAIL review had no
1313
1313
  # outgoing edge at all; before 1122 a PASS-with-findings cost a full re-certification cycle per
1314
1314
  # 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.
1315
+ # both plain and bold forms are accepted. Since 1204 a PASS must also be GRADED: the reviewer
1316
+ # states `Confidence: HIGH|MEDIUM|LOW` (verify-chain semantics, 1068), HIGH/MEDIUM cross the
1317
+ # PASS edges unadorned, and LOW or an absent line needs the operator's `ackLowConfidence` —
1318
+ # otherwise the PASS falls to the catch-all like any other verdict the reviewer would not stand
1319
+ # behind (same policy as the verify confidence gate). Review stays advisory: verify certifies.
1320
+ # Under `profile=auto` the approve gate is skipped, so the PASS+auto edge is tried first and the
1321
+ # interactive PASS edge second.
1317
1322
  - from: review
1318
1323
  to: verify
1319
- description: profile=auto, the review certified PASS, and no open P1-P3 review finding — skip the human approval gate.
1324
+ description: profile=auto, the review certified a HIGH/MEDIUM-confidence PASS (LOW/absent needs ackLowConfidence) with no open P1-P3 finding — skip the human approval gate.
1320
1325
  guard:
1321
1326
  kind: shell
1322
1327
  options:
@@ -1324,23 +1329,24 @@ transitions:
1324
1329
  test "$profile" = auto &&
1325
1330
  grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt" &&
1326
1331
  eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)" &&
1327
- [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
1332
+ [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" --review-answer ".spur/run/$__runId-review-answer.txt" >&2
1328
1333
  - from: review
1329
1334
  to: approve
1330
- description: Review certified PASS with no open P1-P3 review finding — gate on human approval before verification.
1335
+ description: Review certified a HIGH/MEDIUM-confidence PASS (LOW/absent needs ackLowConfidence) with no open P1-P3 finding — gate on human approval before verification.
1331
1336
  guard:
1332
1337
  kind: shell
1333
1338
  options:
1334
1339
  command: >-
1335
1340
  grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt" &&
1336
1341
  eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)" &&
1337
- [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
1342
+ [ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" --review-answer ".spur/run/$__runId-review-answer.txt" >&2
1338
1343
  - from: review
1339
1344
  to: review-fail-triage
1340
1345
  description: >-
1341
- 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.
1346
+ No certified PASS without an open P1-P3 finding (FAIL, PARTIAL, missing, unparseable, a
1347
+ PASS whose review-gate check found an open P1-P3 row, or a PASS the reviewer graded below
1348
+ HIGH/MEDIUM — or left ungraded — without the operator's ackLowConfidence; fail closed) —
1349
+ classify the failure and route it into the bounded repair hop instead of dead-ending the run.
1344
1350
  guard:
1345
1351
  kind: always
1346
1352
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
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.22",
61
- "@gobing-ai/ts-ai-runner": "^0.5.22",
62
- "@gobing-ai/ts-dual-workflow-engine": "^0.5.22",
63
- "@gobing-ai/ts-infra": "^0.5.22",
64
- "@gobing-ai/ts-llm-jsonl-importer": "^0.5.22",
65
- "@gobing-ai/ts-rule-engine": "^0.5.22",
66
- "@gobing-ai/ts-runtime": "^0.5.22",
67
- "@gobing-ai/ts-utils": "^0.5.22",
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",