@gobing-ai/spur 0.3.85 → 0.3.87

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 (139) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/pipeline-budgets.json +0 -25
  3. package/config/plugin-scripts.json +4 -5
  4. package/config/rules/boundary/env-var-hygiene.yaml +41 -0
  5. package/config/templates/feature/default.md +2 -0
  6. package/config/templates/task/brainstorm.md +2 -2
  7. package/config/templates/task/feature-impl.md +2 -2
  8. package/config/templates/task/issue.md +2 -2
  9. package/config/templates/task/meta.md +2 -2
  10. package/config/templates/task/review.md +2 -2
  11. package/config/templates/task/standard.md +2 -2
  12. package/config/transition-shims.json +1 -1
  13. package/config/workflow-candidates.json +19 -0
  14. package/config/workflows/feature-lifecycle.yaml +10 -2
  15. package/config/workflows/feature-verification.yaml +71 -0
  16. package/config/workflows/idea-pipeline.yaml +87 -39
  17. package/config/workflows/task-pipeline.yaml +43 -12
  18. package/config/workflows/wrapup-pipeline.yaml +70 -7
  19. package/package.json +9 -9
  20. package/plugins/sp/README.md +7 -7
  21. package/plugins/sp/commands/dev-idea.md +9 -2
  22. package/plugins/sp/commands/dev-refactor.md +33 -0
  23. package/plugins/sp/hooks/agent-hint.ts +5 -4
  24. package/plugins/sp/hooks/careful-guard.ts +3 -1
  25. package/plugins/sp/hooks/context-post-tool.ts +2 -1
  26. package/plugins/sp/hooks/context-session-start.ts +4 -3
  27. package/plugins/sp/hooks/context-session-stop.ts +2 -1
  28. package/plugins/sp/hooks/pi/guard-extension.ts +4 -3
  29. package/plugins/sp/hooks/task-write-guard.ts +4 -3
  30. package/plugins/sp/lib/idea-handoff.generated.mjs +260 -260
  31. package/plugins/sp/plugin.json +1 -1
  32. package/plugins/sp/references/roles.md +1 -1
  33. package/plugins/sp/scripts/daily-summary/daily-summary.mjs +13 -4
  34. package/plugins/sp/scripts/daily-summary/daily-summary.ts +6 -4
  35. package/plugins/sp/scripts/feature-sync-bounded.mjs +10 -2
  36. package/plugins/sp/scripts/feature-sync-bounded.ts +2 -1
  37. package/plugins/sp/scripts/idea-coverage-check.ts +168 -0
  38. package/plugins/sp/scripts/idea-handoff.mjs +6 -1
  39. package/plugins/sp/scripts/idea-handoff.ts +4 -1
  40. package/plugins/sp/scripts/inline-pipeline-parity-check.ts +115 -4
  41. package/plugins/sp/scripts/inline-run-setup.ts +195 -2
  42. package/plugins/sp/scripts/pr-reviewing.mjs +8 -1
  43. package/plugins/sp/scripts/pr-reviewing.ts +2 -1
  44. package/plugins/sp/scripts/quality-gate.mjs +8 -1
  45. package/plugins/sp/scripts/quality-gate.ts +2 -1
  46. package/plugins/sp/scripts/surface-drift-inventory.ts +1 -4
  47. package/plugins/sp/scripts/task-evidence-precheck.ts +2 -1
  48. package/plugins/sp/scripts/task-size-precheck.ts +6 -4
  49. package/plugins/sp/scripts/verify-answer-lint.ts +2 -1
  50. package/plugins/sp/scripts/workflow-step-profile.mjs +10 -2
  51. package/plugins/sp/scripts/workflow-step-profile.ts +2 -1
  52. package/plugins/sp/scripts/wrapup-steps.mjs +8 -1
  53. package/plugins/sp/scripts/wrapup-steps.ts +2 -1
  54. package/plugins/sp/skills/brainstorm/SKILL.md +4 -0
  55. package/plugins/sp/skills/code-refactoring/SKILL.md +155 -0
  56. package/plugins/sp/skills/code-refactoring/references/finding-schema.md +74 -0
  57. package/plugins/sp/skills/code-refactoring/references/fix-ladder.md +52 -0
  58. package/plugins/sp/skills/code-refactoring/references/focus-detection.md +44 -0
  59. package/plugins/sp/skills/code-refactoring/references/refactor-finding.schema.json +95 -0
  60. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +23 -16
  61. package/plugins/sp/skills/spur-cli/references/features/acceptance-criteria.md +4 -2
  62. package/plugins/sp/skills/spur-cli/references/features.md +6 -1
  63. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +2 -2
  64. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +3 -3
  65. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +1 -1
  66. package/plugins/sp/skills/spur-cli/references/workflows.md +8 -7
  67. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +24 -0
  68. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +4 -5
  69. package/plugins/sp/skills/spur-dev/references/dev-operations.md +18 -2
  70. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +1 -1
  71. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +22 -3
  72. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +2 -2
  73. package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +11 -1
  74. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +91 -1
  75. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +44 -1
  76. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +31 -0
  77. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +43 -0
  78. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +42 -0
  79. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +43 -0
  80. package/schemas/state-machine-workflow.schema.json +5 -0
  81. package/schemas/task-batch.schema.json +2 -2
  82. package/schemas/transition-flow-workflow.schema.json +5 -0
  83. package/spur.js +21106 -20669
  84. package/web/_astro/BoardApp.CJiqp5pS.js +1 -0
  85. package/web/_astro/{BoardApp.yW425dRZ.js → BoardApp.yBBcFXWP.js} +4 -4
  86. package/web/_astro/{TaskDetail.CGwJAinW.js → TaskDetail.DqFJbRFc.js} +1 -1
  87. package/web/_astro/{arc.B-qNXzSO.js → arc.DL-BpHoi.js} +1 -1
  88. package/web/_astro/{architectureDiagram-3BPJPVTR.Bdg-xiji.js → architectureDiagram-3BPJPVTR.9IdQYyDq.js} +1 -1
  89. package/web/_astro/{blockDiagram-GPEHLZMM.DFArg3Kp.js → blockDiagram-GPEHLZMM.BKsFCqTl.js} +1 -1
  90. package/web/_astro/{c4Diagram-AAUBKEIU.BkOLcjyx.js → c4Diagram-AAUBKEIU.DhwI0dh1.js} +1 -1
  91. package/web/_astro/channel.CX5453qQ.js +1 -0
  92. package/web/_astro/{chunk-2J33WTMH.DN3c20V4.js → chunk-2J33WTMH.B3QVmQ9S.js} +1 -1
  93. package/web/_astro/{chunk-4BX2VUAB.B64K0Ttd.js → chunk-4BX2VUAB.DBSuqs9F.js} +1 -1
  94. package/web/_astro/{chunk-55IACEB6.C-AJvNwa.js → chunk-55IACEB6.BSYTWAYD.js} +1 -1
  95. package/web/_astro/{chunk-727SXJPM.DMkr46uS.js → chunk-727SXJPM.cWVuxXfS.js} +1 -1
  96. package/web/_astro/{chunk-AQP2D5EJ.4_WGbI64.js → chunk-AQP2D5EJ.DpU_Ob3d.js} +1 -1
  97. package/web/_astro/{chunk-FMBD7UC4.cbFW_lVE.js → chunk-FMBD7UC4.BykFkyji.js} +1 -1
  98. package/web/_astro/{chunk-ND2GUHAM.CDW_-2O1.js → chunk-ND2GUHAM.DwgHlMdY.js} +1 -1
  99. package/web/_astro/{chunk-QZHKN3VN.BoYOt_yg.js → chunk-QZHKN3VN.CusXUGWM.js} +1 -1
  100. package/web/_astro/{classDiagram-4FO5ZUOK.BNT6XpHQ.js → classDiagram-4FO5ZUOK.fx0ObzkN.js} +1 -1
  101. package/web/_astro/{classDiagram-v2-Q7XG4LA2.BNT6XpHQ.js → classDiagram-v2-Q7XG4LA2.fx0ObzkN.js} +1 -1
  102. package/web/_astro/{cose-bilkent-S5V4N54A.CI1DQxR3.js → cose-bilkent-S5V4N54A.Z4HgOlsd.js} +1 -1
  103. package/web/_astro/{cynefin-OW5HDTMX.A8ARH61p.js → cynefin-OW5HDTMX.B5dIZHJu.js} +1 -1
  104. package/web/_astro/{dagre-BM42HDAG.u28ZmqwR.js → dagre-BM42HDAG.DT70Q_Yw.js} +1 -1
  105. package/web/_astro/{diagram-2AECGRRQ.Dx8JcrGc.js → diagram-2AECGRRQ.DqHA3XBF.js} +1 -1
  106. package/web/_astro/{diagram-5GNKFQAL.BXJUG9GY.js → diagram-5GNKFQAL.BmCem957.js} +1 -1
  107. package/web/_astro/{diagram-KO2AKTUF.BtlMuWqW.js → diagram-KO2AKTUF.sn0-hrE0.js} +1 -1
  108. package/web/_astro/{diagram-LMA3HP47.C4T7qaAy.js → diagram-LMA3HP47.BSHe9tVc.js} +1 -1
  109. package/web/_astro/{diagram-OG6HWLK6.D5HECE10.js → diagram-OG6HWLK6.DHIc-86k.js} +1 -1
  110. package/web/_astro/{erDiagram-TEJ5UH35.B_hMR3yw.js → erDiagram-TEJ5UH35.Bxayrs7v.js} +1 -1
  111. package/web/_astro/{flowDiagram-I6XJVG4X.BAmpcYl3.js → flowDiagram-I6XJVG4X.BkzoE_5I.js} +1 -1
  112. package/web/_astro/{ganttDiagram-6RSMTGT7.DV1bSWK-.js → ganttDiagram-6RSMTGT7.okT6CvTo.js} +1 -1
  113. package/web/_astro/{gitGraphDiagram-PVQCEYII.DxYKkKrJ.js → gitGraphDiagram-PVQCEYII.CJuYbhC7.js} +1 -1
  114. package/web/_astro/{infoDiagram-5YYISTIA.BAWY2xMb.js → infoDiagram-5YYISTIA.RqLy7nBo.js} +1 -1
  115. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CZssRn6V.js → ishikawaDiagram-YF4QCWOH.BwIcoagw.js} +1 -1
  116. package/web/_astro/{journeyDiagram-JHISSGLW.C--muARd.js → journeyDiagram-JHISSGLW.UB1VbWtH.js} +1 -1
  117. package/web/_astro/{kanban-definition-UN3LZRKU.D_QCK4et.js → kanban-definition-UN3LZRKU.AaxMKpTk.js} +1 -1
  118. package/web/_astro/{linear.DzrmTtZ0.js → linear.Nv_xOUjP.js} +1 -1
  119. package/web/_astro/{mermaid.core.Da03W3iu.js → mermaid.core.Bc4LqQgX.js} +4 -4
  120. package/web/_astro/{mindmap-definition-RKZ34NQL.6cy-8hR_.js → mindmap-definition-RKZ34NQL.oKUvU_qi.js} +1 -1
  121. package/web/_astro/{pieDiagram-4H26LBE5.C5rS1pdU.js → pieDiagram-4H26LBE5.DQk0oo03.js} +1 -1
  122. package/web/_astro/{quadrantDiagram-W4KKPZXB.w56GZZ6Q.js → quadrantDiagram-W4KKPZXB.BdDjESDa.js} +1 -1
  123. package/web/_astro/{requirementDiagram-4Y6WPE33.CipX3Pwu.js → requirementDiagram-4Y6WPE33.C2u9hUeH.js} +1 -1
  124. package/web/_astro/{sankeyDiagram-5OEKKPKP.C0VVzgJm.js → sankeyDiagram-5OEKKPKP.CDEoiJST.js} +1 -1
  125. package/web/_astro/{sequenceDiagram-3UESZ5HK.BX2dUUbF.js → sequenceDiagram-3UESZ5HK.D_hT_GAT.js} +1 -1
  126. package/web/_astro/{stateDiagram-AJRCARHV.ypCdgODQ.js → stateDiagram-AJRCARHV.DI8RYG0b.js} +1 -1
  127. package/web/_astro/{stateDiagram-v2-BHNVJYJU.In0baEtg.js → stateDiagram-v2-BHNVJYJU.Bkxz4DnP.js} +1 -1
  128. package/web/_astro/{timeline-definition-PNZ67QCA.CJN4Vkvl.js → timeline-definition-PNZ67QCA.DSY-kH3-.js} +1 -1
  129. package/web/_astro/{vennDiagram-CIIHVFJN.Cf8KkIPY.js → vennDiagram-CIIHVFJN.CpaDtuGr.js} +1 -1
  130. package/web/_astro/{wardleyDiagram-YWT4CUSO.DCZBo9xw.js → wardleyDiagram-YWT4CUSO.DujQWvo8.js} +1 -1
  131. package/web/_astro/{xychartDiagram-2RQKCTM6.Cm4v_MiJ.js → xychartDiagram-2RQKCTM6.DcM5Y4b9.js} +1 -1
  132. package/web/index.html +1 -1
  133. package/config/workflows/basic.yaml +0 -146
  134. package/config/workflows/docs-pipeline.yaml +0 -350
  135. package/config/workflows/feature-dev.yaml +0 -288
  136. package/plugins/sp/scripts/feature-dev-precheck.mjs +0 -146
  137. package/plugins/sp/scripts/feature-dev-precheck.ts +0 -238
  138. package/web/_astro/BoardApp.CHenHFia.js +0 -1
  139. package/web/_astro/channel.CbDHK5UQ.js +0 -1
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.3.85",
10
+ "version": "0.3.87",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -28,17 +28,6 @@
28
28
  "source": "Post-merge count (0607 R2: doc-sync + learning-capture consolidated, 2 -> 1). Real-run reading (R5): median 253s, max-sane 2319s (n=44). Budget = 60 min ceiling.",
29
29
  "decision": null
30
30
  },
31
- "docs-pipeline": {
32
- "modelQueries": 2,
33
- "wallClockMs": null,
34
- "tokenCostUsd": null,
35
- "source": "No fixture (0607 option a) and only dry/short runs recorded in history (max 1s, n=4) — wall-clock budget unenforced until a real docs-pipeline run exists. Query budget 2 matches the live workflow definition's query list ['draft','verify'] (added by task 0704; 0607 R3 recorded 1, which is stale against the definition). 0754 R6: FIX, not raise — the value was wrong against the definition, the workflow's declared query count did not change.",
36
- "decision": {
37
- "date": "2026-09-03",
38
- "wbs": "0754",
39
- "note": "align docs-pipeline.modelQueries to the live workflow definition's query list ['draft','verify']; not a measured-cost raise — the workflow's declared query count was already 2 (added by 0704); the budget was the stale side, not the workflow. Per D8 Decision 11."
40
- }
41
- },
42
31
  "pr-review": {
43
32
  "modelQueries": 0,
44
33
  "wallClockMs": null,
@@ -53,26 +42,12 @@
53
42
  "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
54
43
  "decision": null
55
44
  },
56
- "feature-dev": {
57
- "modelQueries": 2,
58
- "wallClockMs": null,
59
- "tokenCostUsd": null,
60
- "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
61
- "decision": null
62
- },
63
45
  "wayfinder-resolution": {
64
46
  "modelQueries": 2,
65
47
  "wallClockMs": null,
66
48
  "tokenCostUsd": null,
67
49
  "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
68
50
  "decision": null
69
- },
70
- "basic": {
71
- "modelQueries": 1,
72
- "wallClockMs": null,
73
- "tokenCostUsd": null,
74
- "source": "Coverage entry (0826 R2): the live definition's model-query count (extractResolvedWorkflowFacts, 2026-09-11). No real-run measurement yet: wall-clock and cost are unenforced until measured, never 0.",
75
- "decision": null
76
51
  }
77
52
  }
78
53
  }
@@ -26,11 +26,6 @@
26
26
  "contract": "standard",
27
27
  "twin": "dogfood-testing/validate-report.mjs"
28
28
  },
29
- {
30
- "rel": "feature-dev-precheck.ts",
31
- "contract": "standard",
32
- "twin": "feature-dev-precheck.mjs"
33
- },
34
29
  {
35
30
  "rel": "feature-sync-bounded.ts",
36
31
  "contract": "standard",
@@ -55,6 +50,10 @@
55
50
  "rel": "inline-run-setup.ts",
56
51
  "contract": "repo-only"
57
52
  },
53
+ {
54
+ "rel": "idea-coverage-check.ts",
55
+ "contract": "repo-only"
56
+ },
58
57
  {
59
58
  "rel": "inline-pipeline-parity-check.ts",
60
59
  "contract": "repo-only"
@@ -0,0 +1,41 @@
1
+ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
+ # Environment-variable hygiene — env access funnels through the config gateway (task 0902).
3
+ #
4
+ # Contract:
5
+ # - `@gobing-ai/ts-utils` (`packages/utils/src/env.ts` in ts-libs) is the single
6
+ # implementation source; `packages/config/src/index.ts` re-exports `getEnvVar` /
7
+ # `getEnvVars` / `setEnvVar` / `removeEnvVar` / `getAppOptions` as the app-side funnel,
8
+ # and NO file in this repo touches `process.env` directly — packages/config included.
9
+ # Env flows into the app as typed config or injected `env` records (ADR-027). Runtime
10
+ # options belong in `.spur/config.yaml` `bootstrap.options` via `getAppOptions`;
11
+ # dev-only knobs belong in consts.
12
+ # - Plugin scripts/hooks import the same functions from `@gobing-ai/ts-utils`; the
13
+ # `superskill script convert` `.mjs` twins bundle them in (self-contained on any
14
+ # install target).
15
+ # - `apps/web` uses `import.meta.env` (Vite browser plane) — not process env, never matches.
16
+ # - Which variables exist and who consumes them is documented in `.env.example`.
17
+ # (The former per-var lease table moved there; the rule now enforces the funnel,
18
+ # not a file-by-var inventory.)
19
+ #
20
+ # Scope: apps/**, packages/**, scripts/**, plugins/sp/** — src AND tests. No exclusions:
21
+ # even the gateway package itself is free of direct access.
22
+ include:
23
+ - "apps/**/src/**/*.{ts,tsx}"
24
+ - "apps/**/tests/**/*.{ts,tsx}"
25
+ - "packages/**/src/**/*.{ts,tsx}"
26
+ - "packages/**/tests/**/*.{ts,tsx}"
27
+ - "scripts/**/*.ts"
28
+ - "plugins/sp/**/*.ts"
29
+ rules:
30
+ - id: env-var-hygiene
31
+ description: >
32
+ No direct `process.env` or `Bun.env` access outside the packages/config gateway.
33
+ Read via `getEnvVar` (single var, undefined-only fallback), seed/compose via
34
+ `getEnvVars()` (live record — also the sanctioned form for setting/deleting
35
+ parent→child contract markers), or take an injected `env` record parameter.
36
+ Aliasing (`const env = process.env`) is caught too — it must touch `process.env`.
37
+ severity: error
38
+ evaluator:
39
+ type: rg
40
+ config:
41
+ pattern: "process\\.env|\\bBun\\.env\\b"
@@ -23,6 +23,8 @@ updated_at: "{{ CREATED_AT }}"
23
23
  ## Acceptance Criteria
24
24
 
25
25
  ```gherkin
26
+ # Keep the Feature: line (feature check L3.ac-bdd-error without it). Each Scenario: title is the
27
+ # identity key tasks reference verbatim ("- [ ] AC1 — <title>"); number R1, R2, …; never rename after tasks link.
26
28
  Feature: {{ NAME }}
27
29
 
28
30
  Scenario: Basic acceptance
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- Constraints the eventual direction must satisfy, if known. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Constraints the eventual direction must satisfy, if known. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Decision criteria or success checks for the brainstorm output. Keep empty if not applicable. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty if not applicable. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered list derived from the linked feature or refined task scope. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Derive from the linked feature or refined task scope. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Copy or derive real scenarios from the linked feature. Do not leave placeholder AC here. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Do not leave placeholder AC here. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered expectations for the fix. Include repro/expected behavior if it helps traceability. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Include repro/expected behavior if it helps traceability. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Given/When/Then regression scenario or checklist proving the bug is fixed. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Use a regression scenario proving the bug is fixed. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered expectations for the process/docs/chore outcome. Keep empty if not applicable. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Keep empty if not applicable. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Lightweight checklist or Given/When/Then if there is an observable completion condition. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty if not applicable. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -33,11 +33,11 @@ in the reviewed PR/commit/diff). Fix in priority order (P1 → P2 → …); re-r
33
33
 
34
34
  ### Requirements
35
35
 
36
- <!-- R-numbered fix requirements derived from the findings. Fill after triage/refinement. -->
36
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Fill after triage/refinement from the findings. -->
37
37
 
38
38
  ### Acceptance Criteria
39
39
 
40
- <!-- Checks that prove the findings were addressed. Keep empty until the review task becomes executable work. -->
40
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty until the review task becomes executable work. -->
41
41
 
42
42
  ### Q&A
43
43
 
@@ -23,11 +23,11 @@ updated_at: "{{ CREATED_AT }}"
23
23
 
24
24
  ### Requirements
25
25
 
26
- <!-- R-numbered list of what must be true when this task is complete. Keep empty until requirements are known. -->
26
+ <!-- One R-item per line, exactly `- [ ] R1. <text>` (checkbox + `R<n>.`); `spur task check` flags any other form. Keep empty until requirements are known. -->
27
27
 
28
28
  ### Acceptance Criteria
29
29
 
30
- <!-- Given/When/Then scenarios or a checklist derived from Requirements. Keep empty if this task has no objective AC yet. -->
30
+ <!-- Number items AC1, AC2, … (never R<n> — that is the Requirements namespace): `- [ ] AC1 — <feature scenario title without its R-number>` bullets or `Scenario: AC1 — <title>` blocks; add `(req: R<n>)` to bind a task requirement; task-only checks go in prose below, or set `ac_altitude: task-local`. Keep empty if this task has no objective AC yet. -->
31
31
 
32
32
  ### Q&A
33
33
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "note": "Transition-shim manifest (task 0541, feature B2). Each entry records one compatibility path marked @transition-shim(<id>) in source. Every field is required. The gate (bun run transition-shim-check, inside `spur-check`) is two-sided: an unregistered marker fails, and a listed entry whose marker is gone fails. Emptying this file is the definition of the transition being complete (docs/04_DESIGN.md §2.5). Removal conditions must be objectively checkable against the repository, not 'when convenient'. Shims are registered by the tasks that create them (0536/0537/0538/0542).",
2
+ "note": "Transition-shim manifest (task 0541, feature B2). Each entry records one compatibility path marked @transition-shim(<id>) in source. Every field is required. The gate (bun run transition-shim-check, in the feature-scoped `spur-check-feature` pass since task 0872) is two-sided: an unregistered marker fails, and a listed entry whose marker is gone fails. Emptying this file is the definition of the transition being complete (docs/04_DESIGN.md §2.5). Removal conditions must be objectively checkable against the repository, not 'when convenient'. Shims are registered by the tasks that create them (0536/0537/0538/0542).",
3
3
  "entries": [
4
4
  {
5
5
  "id": "agent-bare-binary-name",
@@ -0,0 +1,19 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "note": "Workflow graph-change promotion candidates (task 0873, feature D62; ADR-076 amendment). A candidate is shadow-run against recorded real-run inputs and is promoted into the canonical definition or deleted by its named deadline — never left as a standing parallel <name>2.yaml. `verdict` is null while pending and is filled by `bun scripts/spur-dev.ts promotion evaluate <id>`; `promotion check` (spur-check-feature) fails any candidate still present past its deadline, any unreferenced parallel definition in config/workflows/, and (0877 R8) any retired definition with real (non-dry) terminal runs lacking a recorded decision in `retirements[]`.",
4
+ "candidates": [],
5
+ "retirements": [
6
+ {
7
+ "name": "planning-pipeline",
8
+ "recordedBy": "0872 (ADR-072/075 composition-baseline pass 2dc86579a)",
9
+ "date": "2026-08-19",
10
+ "rationale": "Planning pipeline superseded by the task-pipeline planning stages; 3 real terminal runs retained in history."
11
+ },
12
+ {
13
+ "name": "task-pipeline2",
14
+ "recordedBy": "ADR-076 (commit 017ac7a30)",
15
+ "date": "2026-08-20",
16
+ "rationale": "Standing parallel definition deleted with the D5-N fixture promotion bar; 5 real terminal runs retained in history."
17
+ }
18
+ ]
19
+ }
@@ -37,6 +37,12 @@ states:
37
37
  description: >
38
38
  Feature verification work (DD-13). Makes verification derivable —
39
39
  listable, event-triggerable, assignable.
40
+ onEnter:
41
+ # Caller wiring (task 0880, ADR-119): entering verification RUNS the
42
+ # feature-scoped pass instead of only passively reading its status file.
43
+ - kind: shell
44
+ options:
45
+ command: '$spurBin workflow run feature-verification.yaml --vars "{\"featureId\":\"$featureId\"}"'
40
46
  - id: blocked
41
47
  description: Impediment; work suspended.
42
48
  - id: done
@@ -62,11 +68,13 @@ transitions:
62
68
  - from: verifying
63
69
  to: done
64
70
  description: >
65
- Feature verified — complete. Runs strict check (AC validated, traceability clean).
71
+ Feature verified — complete. Requires the feature-scoped verification pass
72
+ (ADR-119) to have recorded PASS, then strict check (AC validated,
73
+ traceability clean).
66
74
  guard:
67
75
  kind: shell
68
76
  options:
69
- command: '$spurBin feature check $featureId --strict --as done'
77
+ command: 'test "$(cat .spur/run/$featureId-feature-verification.status 2>/dev/null)" = PASS && $spurBin feature check $featureId --strict --as done'
70
78
 
71
79
  # Rework: verifying → active (mandatory History entry)
72
80
  - from: verifying
@@ -0,0 +1,71 @@
1
+ # Feature-scoped verification pass (ADR-119, feature D62, task 0872).
2
+ #
3
+ # Owns a lifecycle boundary no per-task graph owns: the repo-wide checks whose
4
+ # invariant spans the repository rather than a single task's diff — corpus
5
+ # consistency, contract baselines, dependency/schema drift, the frozen History
6
+ # surface, and the repo-wide test set. They run once per feature, deliberately
7
+ # the slow pass; `feature-lifecycle`'s verifying entry invokes this workflow (task
8
+ # 0880 caller wiring), and its verifying→done guard refuses to complete the
9
+ # feature until this pass records PASS (ADR-119 consequence: a feature is not
10
+ # done until it passes).
11
+ #
12
+ # Run: spur workflow run feature-verification.yaml --vars '{"featureId":"D62"}'
13
+ #
14
+ # Shape: verify -> done | failed. The shell action writes the verdict to
15
+ # `.spur/run/<featureId>-feature-verification.status` and always exits 0; the
16
+ # transition guard reads the status so a missing, corrupt or FAIL verdict routes
17
+ # to `failed` (fail-closed), never a silent PASS.
18
+ #
19
+ # Reliability (aligned with task-pipeline / ADR-043): no agent.run nodes; the
20
+ # verification command is a trusted config var executed via `sh -c` (same
21
+ # surface as task-pipeline's qualityGateCmd — never interpolate untrusted input).
22
+ "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
23
+ kind: state-machine
24
+ name: feature-verification
25
+ version: "1"
26
+ description: "Feature-scoped verification pass (ADR-119): runs the repo-wide check set once per feature and records PASS/FAIL. Invoked by feature-lifecycle's verifying entry."
27
+ iterationBound: 2
28
+ initialState: verify
29
+ terminalStates:
30
+ - done
31
+ - failed
32
+ failureStates:
33
+ - failed
34
+ vars:
35
+ featureId: "X"
36
+ spurBin: "spur"
37
+ verificationCmd: "bun run spur-check-feature"
38
+
39
+ states:
40
+ - id: verify
41
+ description: >
42
+ Run the repo-wide check set, record the verdict, always exit 0.
43
+ onEnter:
44
+ - kind: shell
45
+ options:
46
+ command: >-
47
+ mkdir -p .spur/run;
48
+ sh -c "$verificationCmd" > ".spur/run/$featureId-feature-verification.log" 2>&1
49
+ && printf 'PASS\n' > ".spur/run/$featureId-feature-verification.status"
50
+ || printf 'FAIL\n' > ".spur/run/$featureId-feature-verification.status";
51
+ exit 0
52
+
53
+ - id: done
54
+ description: Terminal — repo-wide checks passed.
55
+
56
+ - id: failed
57
+ description: Terminal — repo-wide checks failed or the verdict is missing/corrupt.
58
+
59
+ transitions:
60
+ - from: verify
61
+ to: done
62
+ description: Repo-wide checks passed — the feature-scoped verification pass records PASS.
63
+ guard:
64
+ kind: shell
65
+ options:
66
+ command: 'test "$(cat .spur/run/$featureId-feature-verification.status 2>/dev/null)" = PASS'
67
+ - from: verify
68
+ to: failed
69
+ description: Repo-wide checks failed (or the verdict is missing/corrupt) — stop at failed.
70
+ guard:
71
+ kind: always