@gobing-ai/spur 0.4.14 → 0.4.16

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 (121) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.global.yaml +21 -8
  3. package/config/decisions/executor.yaml +53 -0
  4. package/config/decisions/task-pipeline.yaml +44 -28
  5. package/config/pipeline-budgets.json +0 -14
  6. package/config/workflow-candidates.json +18 -0
  7. package/config/workflows/feature-lifecycle.yaml +9 -16
  8. package/config/workflows/idea-pipeline.yaml +158 -740
  9. package/config/workflows/task-pipeline.yaml +66 -54
  10. package/config/workflows/wrapup-pipeline.yaml +91 -623
  11. package/package.json +11 -10
  12. package/plugins/sp/README.md +9 -5
  13. package/plugins/sp/agents/expert-spur.md +3 -0
  14. package/plugins/sp/agents/super-planner.md +5 -1
  15. package/plugins/sp/agents/super-reviewer.md +43 -12
  16. package/plugins/sp/commands/dev-fixall.md +7 -2
  17. package/plugins/sp/commands/dev-idea.md +15 -6
  18. package/plugins/sp/commands/dev-plan.md +1 -1
  19. package/plugins/sp/commands/dev-pr-review.md +6 -6
  20. package/plugins/sp/commands/dev-run.md +3 -0
  21. package/plugins/sp/commands/dev-runall.md +6 -3
  22. package/plugins/sp/commands/dev-verify.md +1 -1
  23. package/plugins/sp/commands/dev-wrap.md +1 -1
  24. package/plugins/sp/commands/dev-wrapall.md +4 -4
  25. package/plugins/sp/plugin.json +1 -1
  26. package/plugins/sp/skills/code-implementation/SKILL.md +8 -8
  27. package/plugins/sp/skills/code-improvement/SKILL.md +3 -3
  28. package/plugins/sp/skills/code-review/references/verification-before-completion.md +5 -4
  29. package/plugins/sp/skills/code-verification/SKILL.md +4 -4
  30. package/plugins/sp/skills/code-verification/references/verdict-schema.md +27 -11
  31. package/plugins/sp/skills/functional-review/SKILL.md +1 -1
  32. package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
  33. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  34. package/plugins/sp/skills/pr-reviewing/SKILL.md +36 -18
  35. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +2 -1
  36. package/plugins/sp/skills/spur-check/SKILL.md +1 -1
  37. package/plugins/sp/skills/spur-cli/SKILL.md +23 -2
  38. package/plugins/sp/skills/spur-cli/references/agent.md +12 -0
  39. package/plugins/sp/skills/spur-cli/references/builder.md +2 -2
  40. package/plugins/sp/skills/spur-cli/references/decision/lifecycle.md +166 -0
  41. package/plugins/sp/skills/spur-cli/references/decision.md +146 -16
  42. package/plugins/sp/skills/spur-cli/references/features.md +19 -0
  43. package/plugins/sp/skills/spur-cli/references/rules.md +2 -0
  44. package/plugins/sp/skills/spur-cli/references/tasks.md +14 -1
  45. package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +1 -1
  46. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +3 -2
  47. package/plugins/sp/skills/spur-cli/references/workflows.md +9 -0
  48. package/plugins/sp/skills/spur-composer/SKILL.md +20 -1
  49. package/plugins/sp/skills/spur-dev/SKILL.md +16 -16
  50. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +2 -1
  51. package/plugins/sp/skills/spur-dev/references/cross-cutting.md +2 -2
  52. package/plugins/sp/skills/spur-dev/references/decision-points.md +97 -0
  53. package/plugins/sp/skills/spur-dev/references/dev-operations.md +18 -18
  54. package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +1 -1
  55. package/plugins/sp/skills/spur-dev/references/execution-batch.md +19 -10
  56. package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +4 -4
  57. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +41 -29
  58. package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +34 -2
  59. package/plugins/sp/skills/spur-dev/references/execution-worktree-setup.md +4 -4
  60. package/plugins/sp/skills/spur-dev/references/flag-glossary.md +3 -3
  61. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +3 -2
  62. package/plugins/sp/skills/spur-dev/references/glossary.md +12 -3
  63. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +7 -6
  64. package/plugins/sp/skills/spur-doctor/SKILL.md +23 -0
  65. package/plugins/sp/skills/wayfinder/SKILL.md +11 -1
  66. package/spur.js +25617 -24290
  67. package/web/_astro/{BoardApp.Bjdp3XWV.js → BoardApp.CC7Mwswv.js} +65 -65
  68. package/web/_astro/{BoardApp.DCDZxLlQ.js → BoardApp.mWyrWCAR.js} +1 -1
  69. package/web/_astro/{TaskDetail.B3vBxynO.js → TaskDetail.CtAXuiv8.js} +1 -1
  70. package/web/_astro/{arc.DcuHTB_T.js → arc.Duf4u60i.js} +1 -1
  71. package/web/_astro/{architectureDiagram-3BPJPVTR.ClOFWBON.js → architectureDiagram-3BPJPVTR.JoymtqxN.js} +1 -1
  72. package/web/_astro/{blockDiagram-GPEHLZMM.otYyr7Zb.js → blockDiagram-GPEHLZMM.BvmhcioC.js} +1 -1
  73. package/web/_astro/{c4Diagram-AAUBKEIU.BCjpc9LP.js → c4Diagram-AAUBKEIU.CfaWkgoQ.js} +1 -1
  74. package/web/_astro/channel.DtEPXXcH.js +1 -0
  75. package/web/_astro/{chunk-2J33WTMH.D5Wpnpt_.js → chunk-2J33WTMH.B7uR02cD.js} +1 -1
  76. package/web/_astro/{chunk-4BX2VUAB.DkQGtWNz.js → chunk-4BX2VUAB.SwiEauYR.js} +1 -1
  77. package/web/_astro/{chunk-55IACEB6.B7dqjAip.js → chunk-55IACEB6.6ZRCK8PO.js} +1 -1
  78. package/web/_astro/{chunk-727SXJPM.BDQvnKE2.js → chunk-727SXJPM.Cxra_G3N.js} +1 -1
  79. package/web/_astro/{chunk-AQP2D5EJ.D92doBX5.js → chunk-AQP2D5EJ.Cxd7gZeX.js} +1 -1
  80. package/web/_astro/{chunk-FMBD7UC4.C968oI5G.js → chunk-FMBD7UC4.DCLhFkVc.js} +1 -1
  81. package/web/_astro/{chunk-ND2GUHAM.AkkYC1bY.js → chunk-ND2GUHAM.B9AmKcv6.js} +1 -1
  82. package/web/_astro/{chunk-QZHKN3VN.sCc-rKKo.js → chunk-QZHKN3VN.DOjCvl6S.js} +1 -1
  83. package/web/_astro/{classDiagram-4FO5ZUOK.pOQ9u0mY.js → classDiagram-4FO5ZUOK.BMiT_mNf.js} +1 -1
  84. package/web/_astro/{classDiagram-v2-Q7XG4LA2.pOQ9u0mY.js → classDiagram-v2-Q7XG4LA2.BMiT_mNf.js} +1 -1
  85. package/web/_astro/{cose-bilkent-S5V4N54A.CRaeD6FY.js → cose-bilkent-S5V4N54A.mLBCEGjI.js} +1 -1
  86. package/web/_astro/{cynefin-OW5HDTMX.BiCPBu54.js → cynefin-OW5HDTMX.CjDAY0qn.js} +1 -1
  87. package/web/_astro/{dagre-BM42HDAG.C1-q3vkT.js → dagre-BM42HDAG._G_sP8fP.js} +1 -1
  88. package/web/_astro/{diagram-2AECGRRQ.BSVOv30O.js → diagram-2AECGRRQ.39OcfSuz.js} +1 -1
  89. package/web/_astro/{diagram-5GNKFQAL.CHMkjJ-V.js → diagram-5GNKFQAL.D7v_eNC4.js} +1 -1
  90. package/web/_astro/{diagram-KO2AKTUF.CKY9M564.js → diagram-KO2AKTUF.Da1x-lhg.js} +1 -1
  91. package/web/_astro/{diagram-LMA3HP47.B9yNJiTP.js → diagram-LMA3HP47.C8EnzbEb.js} +1 -1
  92. package/web/_astro/{diagram-OG6HWLK6.Dk8AUGsk.js → diagram-OG6HWLK6.DPnBj69F.js} +1 -1
  93. package/web/_astro/{erDiagram-TEJ5UH35.BQHR89TZ.js → erDiagram-TEJ5UH35.CXMu2TIh.js} +1 -1
  94. package/web/_astro/{flowDiagram-I6XJVG4X.oNkWVgoK.js → flowDiagram-I6XJVG4X.ZklePVtQ.js} +1 -1
  95. package/web/_astro/{ganttDiagram-6RSMTGT7.Kz2U2nu9.js → ganttDiagram-6RSMTGT7.BhYOkdqk.js} +1 -1
  96. package/web/_astro/{gitGraphDiagram-PVQCEYII.DHIZ_wPq.js → gitGraphDiagram-PVQCEYII.CADyX8a1.js} +1 -1
  97. package/web/_astro/{infoDiagram-5YYISTIA.D0NJLcv9.js → infoDiagram-5YYISTIA.BsdmwjHt.js} +1 -1
  98. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CFEfTWRG.js → ishikawaDiagram-YF4QCWOH.CzjZ3Crd.js} +1 -1
  99. package/web/_astro/{journeyDiagram-JHISSGLW.Dc7IE7I4.js → journeyDiagram-JHISSGLW.Bxj-ZH_t.js} +1 -1
  100. package/web/_astro/{kanban-definition-UN3LZRKU.D5v0xO9k.js → kanban-definition-UN3LZRKU.Cbg3wVvX.js} +1 -1
  101. package/web/_astro/{linear.wR5KzXnE.js → linear.DJNUrBI9.js} +1 -1
  102. package/web/_astro/{mermaid.core.BDQ2FoPd.js → mermaid.core.DVHQV3SF.js} +4 -4
  103. package/web/_astro/{mindmap-definition-RKZ34NQL.W6_INsia.js → mindmap-definition-RKZ34NQL.DyomosRU.js} +1 -1
  104. package/web/_astro/{pieDiagram-4H26LBE5.61ihbgkK.js → pieDiagram-4H26LBE5.DajtFknN.js} +1 -1
  105. package/web/_astro/{quadrantDiagram-W4KKPZXB.B5lEpFLo.js → quadrantDiagram-W4KKPZXB.Bjq6SjGe.js} +1 -1
  106. package/web/_astro/{requirementDiagram-4Y6WPE33.CmhVBVX0.js → requirementDiagram-4Y6WPE33.ubBVqGLP.js} +1 -1
  107. package/web/_astro/{sankeyDiagram-5OEKKPKP.D7Vvj9Wf.js → sankeyDiagram-5OEKKPKP.I4q46xd-.js} +1 -1
  108. package/web/_astro/{sequenceDiagram-3UESZ5HK.B1vPLixM.js → sequenceDiagram-3UESZ5HK.DsCgZIa8.js} +1 -1
  109. package/web/_astro/{stateDiagram-AJRCARHV.BnACmrGi.js → stateDiagram-AJRCARHV.DcYjYSqT.js} +1 -1
  110. package/web/_astro/{stateDiagram-v2-BHNVJYJU.CW4pnmc3.js → stateDiagram-v2-BHNVJYJU.Dt8yPqiS.js} +1 -1
  111. package/web/_astro/{timeline-definition-PNZ67QCA.CkzMCPnC.js → timeline-definition-PNZ67QCA.0YTkoa5F.js} +1 -1
  112. package/web/_astro/{vennDiagram-CIIHVFJN.CY4aNdAR.js → vennDiagram-CIIHVFJN.BNl0l1hs.js} +1 -1
  113. package/web/_astro/{wardleyDiagram-YWT4CUSO.BtoU9UFk.js → wardleyDiagram-YWT4CUSO.BYSX6cfn.js} +1 -1
  114. package/web/_astro/{xychartDiagram-2RQKCTM6._9ijUUAs.js → xychartDiagram-2RQKCTM6.DzxxpixK.js} +1 -1
  115. package/web/index.html +1 -1
  116. package/worker/laya_worker.py +219 -0
  117. package/config/workflows/feature-verification.yaml +0 -98
  118. package/config/workflows/pr-review.yaml +0 -209
  119. package/config/workflows/wayfinder-resolution.yaml +0 -302
  120. package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +0 -30
  121. package/web/_astro/channel.qgOLXjI_.js +0 -1
@@ -64,6 +64,14 @@ no level (ADR-131, 1196), no operator `ackLowConfidence`-style var exists, and h
64
64
  findings carry no per-finding grade. A verifier that can write a PASS can still write a wrong
65
65
  `HIGH` — which is exactly why the gate derives the level instead of trusting it.
66
66
 
67
+ **A review run carries two answer artifacts, one `Confidence:` line each (1254).** The `## Review`
68
+ section states the disposition-derived level (`deriveReviewConfidence`); the captured answer handed
69
+ to `spur task verdict --from-answer` states the evidence-derived level (`deriveVerifyConfidence`)
70
+ under the table above and carries exactly one `Confidence:` line. The two legitimately disagree — a
71
+ PASS with executable AC and one carried P4 is section `MEDIUM`, answer `HIGH` — so the captured
72
+ answer must not repeat the section's line (`confidence-duplicate` rejects the whole answer). The
73
+ review stage's prompt owns that instruction; this schema owns the shape it must produce.
74
+
67
75
  ## Compatibility alias: `scenario` row key
68
76
 
69
77
  Task 0410 hardened the verdict reader. Producers SHOULD use the canonical `id` field for every
@@ -241,25 +249,33 @@ Wave C verification can emit the following additive `checks[]` rows:
241
249
 
242
250
  ## How the gate reads it
243
251
 
244
- `task-pipeline.yaml`, transition `verify → record`:
252
+ In `task-pipeline.yaml` the `review` state writes this artifact: `spur task verdict <wbs>
253
+ --from-answer` lints the review answer and derives `.spur/run/<wbs>-verdict.json`. A fold step then
254
+ writes `.spur/run/<wbs>-review.status` = PASS only when the typed verdict is PASS, the artifact's own
255
+ `verdict` is PASS (`jq -r '.verdict // empty'`) and `spur task residual <wbs> review-gate` is clean.
256
+ The `review → done` guard reads that status **and** the approval decision point's token:
245
257
 
246
258
  ```yaml
247
259
  guard:
248
260
  kind: shell
249
261
  options:
250
- command: 'test "$(jq -r .verdict .spur/run/${vars.wbs}-verdict.json)" = PASS'
262
+ command: >-
263
+ test "$(cat ".spur/run/$wbs-review.status" 2>/dev/null)" = PASS &&
264
+ test "$(cat ".spur/run/$wbs-approval.status" 2>/dev/null)" = APPROVED
251
265
  ```
252
266
 
253
- with a sibling `verify → failed` guarded on the negation. So a missing file, malformed JSON, or any
254
- non-`PASS` verdict routes the run to `failed` rather than `done` — the pipeline cannot certify
255
- completion without an explicit PASS artifact.
267
+ A missing file, malformed JSON or any non-`PASS` verdict leaves the status FAIL, which the
268
+ `review-failure-class` decision routes to `remediate` (`fix`) or `failed` (`stop`). The pipeline
269
+ cannot certify completion without an explicit PASS artifact.
256
270
 
257
271
  ## Lifecycle
258
272
 
259
- - **Written:** Step 9 of verify mode, *after* the verdict is final (never partially).
260
- - **Read:** by the workflow gate on the `verify → record` transition.
261
- - **Location:** `.spur/run/` (the run-scratch dir the pipeline's `record` step also uses).
262
- - **Lifetime:** per execution attempt; overwritten on the next verify of the same WBS.
273
+ - **Written:** by `spur task verdict` in the pipeline's `review` state, or by Step 9 of standalone
274
+ verify mode, *after* the verdict is final (never partially).
275
+ - **Read:** by the review fold and the `review → done` guard, then by `done`'s `spur task record`
276
+ close, which transcribes it.
277
+ - **Location:** `.spur/run/`.
278
+ - **Lifetime:** per execution attempt; overwritten on the next certification of the same WBS.
263
279
 
264
280
  ## Optional check severity (task 0592, feature F92)
265
281
 
@@ -304,6 +320,6 @@ The prose shape above is executed by a single runtime-validated contract:
304
320
  failure can never yield PASS.
305
321
  - A row-less artifact aggregates to UNKNOWN — a stored PASS that does not recompute to PASS
306
322
  (including a row-less PASS) is treated as non-PASS at the done gate. The done-transition choke
307
- point (`done-transition-guard.ts` `evaluateDoneTransition`) is the final authority; workflow JSON
308
- routing may select `verify → record/failed` but cannot weaken the final transition.
323
+ point (`done-transition-guard.ts` `evaluateDoneTransition`) is the final authority; workflow
324
+ routing may select `review → done/failed` but cannot weaken the final transition.
309
325
  - `--force-done --reason` on `spur task update <wbs> done` remains the sole auditable override.
@@ -295,7 +295,7 @@ Include the per-requirement traceability table in the report:
295
295
  **Under the pipeline**, `sp:functional-review` is a component of `/sp:dev-review`: it returns its
296
296
  fragment to the coordinator (`sp:super-reviewer` — the invoking session under `/sp:dev-review`),
297
297
  which writes the combined `## Review`. The
298
- `record` step transcribes only `## Testing` from the verdict artifact and backfills `## Review`
298
+ `done` state's `spur task record` close transcribes only `## Testing` from the verdict artifact and backfills `## Review`
299
299
  only when the section is bare (`sectionIsBare` guard, `task-section-bodies.ts`); it never overwrites the
300
300
  coordinator's authored Review. Keep the priority-table lead stable in the fragment so the L3 gate
301
301
  stays satisfied through `record` → `done`.
@@ -130,4 +130,4 @@ all core requirements MET → PASS
130
130
  | `VerifyVerdict` | `sp:code-verification` | Is the code SECUA-correct and AC-complete? | any core req/AC UNMET → FAIL; any blocker correctness/security → FAIL; any PARTIAL → PARTIAL; else PASS |
131
131
 
132
132
  A complete `/sp:dev-review --focus all` pipeline may produce both artifacts; they are consumed by
133
- the pipeline's `record` step and written to the task's `## Testing` section.
133
+ the `done` state's `spur task record` close and written to the task's `## Testing` section.
@@ -125,7 +125,7 @@ token, deterministic).
125
125
  means the workspace holds unfinished task residue, so fixall/unit reruns would either clean it
126
126
  unintentionally or re-certify a folded verdict. C6 fires before any fix/unit dispatch; recovery is
127
127
  the operator re-running the pipeline (`/sp:dev-run <wbs>`), which re-enters the normal
128
- verify → test-fix remediation budget.
128
+ gate ⇄ remediate budget.
129
129
 
130
130
  **Explicit non-probes in v1:** no freeform chat history; no always-on full `bun run test` for every
131
131
  call; no git dirtiness as a route (optional advisory print only).
@@ -39,19 +39,19 @@ invoking coding agent is the local orchestrator and implementer.
39
39
  ▼
40
40
  sp:pr-reviewing (this skill — mode routing, local-review dispatch, triage, fix)
41
41
  │ local route: pr-check --scan-only → git diff --name-only → /sp:dev-review
42
- │ Codex route: pr-review.yaml (check → precheck → open → review)
42
+ │ Codex route: pr-check → pr-open → pr-review → pr-status
43
43
  ▼
44
44
  `spur builder pr-<verb>` + `spur builder show-branches` ← tested git/gh core
45
45
  ```
46
46
 
47
- - **State order and guards** for the Codex route are defined once, in `pr-review.yaml`. Do not
48
- re-derive them in prose; when the YAML and this file disagree, the YAML wins and this file gets
49
- fixed.
50
47
  - **Deterministic work** (every git/gh call) goes through the four flat `spur builder pr-<verb>`
51
48
  commands and `spur builder show-branches` — never hand-rolled `gh` invocations that drift from
52
49
  the tested core.
50
+ - **Sequencing inside a verb** (preflight→hygiene, push→ensure, request→wait→collect) lives in
51
+ `runPrVerb`, not in this file. This skill orders the *verbs*; each verb owns its own ops, its
52
+ one-word verdict and its exit code.
53
53
  - **Model-bearing work** (the local review dispatch, finding triage, `fix` edits) is this skill's
54
- job and never enters the workflow machine.
54
+ job and never enters a deterministic verb.
55
55
 
56
56
  ## Modes and routing
57
57
 
@@ -61,7 +61,7 @@ Parse the first positional argument as the mode; default `status`.
61
61
  | --- | --- | --- |
62
62
  | `status` | direct CLI | `spur builder show-branches --base <b> --pr --format markdown`, with the report filtered to the current branch and its base, plus `spur builder pr-status --json` (PR number, CI, local changes, latest current-head review in `.review`). Read-only. |
63
63
  | `review` | local stack | `spur builder pr-check --base <b> --scan-only --json`; `BLOCK` stops, `WARN` is reported. Then `git diff --name-only <b>...HEAD` → `/sp:dev-review --scope <comma-joined paths> --focus <focus>`. An empty diff ends with "nothing to review". Posts nothing to GitHub. |
64
- | `review --codex` | `pr-review.yaml` | Run the spine with `mode=full`; `--force` → `mode=rerun`; `--no-wait` → `mode=submit`; `focus`/`baseBranch` passed as vars. States: check → precheck → open → review. `pending` is reported as pending, never failure. |
64
+ | `review --codex` | direct verb sequence | `spur builder pr-check --base <b> --json` → `pr-open --base <b> --json` → `pr-review --focus <focus> [--force] [--no-wait] --json` → `pr-status --json`. Each verb's verdict gates the next; `PENDING` is reported as pending, never failure. |
65
65
  | `fix` | direct verb + model work | Findings from the latest local review verdict, or from `spur builder pr-status --json` `.review` when the last review was Codex. Validate each finding against the code before editing; rejected findings are listed with a reason. Fix the legitimate ones, run the project gate, make one focused commit and push without force (`spur builder pr-open` handles a first push). |
66
66
 
67
67
  Retired modes print one notice line and run their replacement: `full` → `review --codex`;
@@ -125,17 +125,37 @@ Codex: clean | findings | pending | not requested | unavailable
125
125
 
126
126
  ## Review mode (--codex)
127
127
 
128
- Run `pr-review.yaml` as the single source of truth for the Codex spine — check → precheck → open →
129
- review. Never call `spur builder pr-review` in a way that bypasses the workflow's state order and
130
- guards.
128
+ Four verbs in order. Each one's `--status-file` verdict gates the next — stop at the first red
129
+ verdict and report it with the stage's JSON record; never run a later verb to "retry" an earlier
130
+ one, and never force-push around a rejected push.
131
131
 
132
132
  ```sh
133
- spur workflow run pr-review.yaml --vars '{"mode":"full","baseBranch":"<base>","focus":"<focus>"}'
133
+ spur builder pr-check --base "$base" --json --status-file .spur/run/pr-check.status
134
+ # PASS|WARN → continue (a WARN rides into the report). BLOCK|FAIL → stop.
135
+ # BLOCK = secrets/.env/conflict markers/private keys. FAIL = preflight (detached HEAD, dirty
136
+ # tree, gh unauthenticated, no GitHub remote, or the current branch *is* the base).
137
+
138
+ # Optional project fast check before spending a review request. Run it only when the project
139
+ # defines one; a red check stops here rather than reviewing code that fails its own gate.
140
+
141
+ spur builder pr-open --base "$base" --json --status-file .spur/run/pr-open.status
142
+ # FOUND|CREATED → continue. FAIL → stop (push rejected, no reviewable delta, PR create failed).
143
+
144
+ spur builder pr-review --focus "$focus" [--force] [--no-wait] \
145
+ --timeout 600 --interval 30 --json --status-file .spur/run/pr-review.status
146
+ # CLEAN|FINDINGS → collected. PENDING → pending, not failed. FAIL → stop.
147
+
148
+ spur builder pr-status --json # composite PR/CI/Codex report; read-only, never gates
134
149
  ```
135
150
 
136
- - `mode=full` by default; `--force` → `mode=rerun`; `--no-wait` → `mode=submit`.
137
- - The workflow's `pending` terminal state is **pending, not failed**: report the requested or
138
- in-flight state and collect later with `status`.
151
+ - **Flags from the invocation:** `--force` requests a fresh review of an already-reviewed HEAD;
152
+ `--no-wait` posts the request and returns `PENDING` without polling. Both are optional and
153
+ independent — pass each as its own argument. The default is request → wait → collect, with
154
+ per-HEAD dedupe.
155
+ - **`PENDING` is pending, not failed** (a wait timeout included): report the requested or in-flight
156
+ state and collect later with `status`.
157
+ - **`pr-review` owns request → wait → collect in one runtime** (`runPrVerb`), so there is no
158
+ separate request record to thread between steps.
139
159
  - When `--codex` is passed, the external review goes through the GitHub PR and an `@codex review`
140
160
  request only — never a local Codex CLI review. If GitHub Codex Code Review is unavailable, stop
141
161
  and report the setup/access problem; never silently fall back to a local review.
@@ -219,20 +239,18 @@ and nothing else.
219
239
 
220
240
  ## Platform notes
221
241
 
222
- - The skill, command and workflow YAML are platform-neutral; per-platform emission is owned by
223
- superskill. On platforms without a Skill tool, read this file and follow the protocol manually.
242
+ - The skill and command are platform-neutral; per-platform emission is owned by superskill. On
243
+ platforms without a Skill tool, read this file and follow the protocol manually.
224
244
  - Prerequisites: `git` for every path. `gh` authenticated with a GitHub remote wherever PR state is
225
245
  touched: `status` (its `pr-status` half — the `show-branches` topology runs on `git` alone, and
226
246
  its `--pr` enrichment only degrades with a warning), `review` (step 1's `pr-check --scan-only`),
227
- `review --codex` (the workflow's check/open/review states), and `fix` when it reads a Codex
247
+ `review --codex` (its `pr-check`/`pr-open`/`pr-review` verbs), and `fix` when it reads a Codex
228
248
  verdict or pushes through `pr-open`. The `git diff --name-only` scope, `/sp:dev-review`, and
229
249
  `fix`'s local-verdict edit/commit path need only `git`. The `--codex` path additionally needs
230
250
  GitHub Codex Code Review enabled for the repository.
231
251
 
232
252
  ## Additional Resources
233
253
 
234
- - **Workflow SSOT (Codex path):** `pr-review.yaml` (seeded by `spur init`; tune per project — wait
235
- budget, `preReviewCmd`, dedupe policy)
236
254
  - **Command source:** the four flat verbs `pr-status` / `pr-check` / `pr-open` / `pr-review` plus the
237
255
  read-only `show-branches` report — see `sp:spur-cli` `references/builder.md`
238
256
  - **Local review:** `/sp:dev-review` — its dimensions live in `sp:code-verification` and
@@ -563,7 +563,8 @@ schema before emitting.
563
563
  **Pass the deterministic task check.** Each `acceptance_criteria` bullet must be an exact feature
564
564
  scenario title (L4.uncovered-task-scenario); add task-local checks as prose after the bullets, not
565
565
  as extra bullets. No section body may use `HITL`, `merge event`, `content-gate`, `GATED`, or
566
- `capstone` as standalone words (L4.gate-language); ambiguous words (`approval`, `approved`,
566
+ `capstone` as standalone words in any case (L4.gate-language) — dotted action kinds such as
567
+ `hitl.confirm` are fine, a bare `hitl` count is not; ambiguous words (`approval`, `approved`,
567
568
  `merged`) warn only with a gating cue (`until`, `after`, `once`, `before`, `pending`, `blocked`,
568
569
  `wait for`, `requires`) in the same sentence, so plain composition prose stays silent — say
569
570
  "operator answer" / "accepted" instead, and keep enum values out of that list too.
@@ -92,7 +92,7 @@ preserved by construction. `recheck` stays the no-progress probe path for fix lo
92
92
 
93
93
  ## Composition
94
94
 
95
- - **Pipeline:** `sp:spur-dev` runs `run` at `test` and `recheck` at `test-recheck`; light mode
95
+ - **Pipeline:** `sp:spur-dev` runs `run` on the `gate` state's first visit and `recheck` on later visits (after `remediate`); light mode
96
96
  belongs to implement/fix edits, not to the gate state.
97
97
  - **Fix loops:** `/sp:dev-fixall --gate-log` consumes `<wbs>-test-gate.log` (and the bounded
98
98
  `<wbs>-test-gate.findings` anchors) after a red gate; it never writes receipts. A green fixall
@@ -50,7 +50,7 @@ Pick the noun, read its reference. Each Tier A and Tier B reference owns that no
50
50
  | **Tier B** | **self** | Self-management verbs: scaffold (`init`), project SDLC actions (`exec`), database maintenance (`maintain`), schema migrations (`migrate`), local web server (`serve`), status overview (`status`); `self init` runs post-scaffold validation probes & layout classification | [references/self.md](references/self.md) |
51
51
  | **Tier B** | **history** | Import agent histories, aggregate forensic artifacts, render reports, and run the checkpoint-resumed daily pipeline | [references/history.md](references/history.md) |
52
52
  | **Tier B** | **projects** | Manage the local multi-project registry and start/stop project servers | [references/projects.md](references/projects.md) |
53
- | **Tier B** | **decision** | Decision-catalog transport: list visible decisions, show a served contract, run a decision to a served outcome, audit catalog health | [references/decision.md](references/decision.md) |
53
+ | **Tier B** | **decision** | Decision catalog: list visible decisions, show a served contract, run a decision to a served outcome, audit catalog health and maker reliability; author and tune catalog entries | [references/decision.md](references/decision.md) |
54
54
  | **Tier C** | **help** | Commander-generated help command; not a Spur noun | Generated `--help` |
55
55
 
56
56
  **Execute-First Contract:** Load the noun reference first and execute Tier A or Tier B commands
@@ -69,6 +69,26 @@ Each noun's per-topic detail lives one level deeper under `references/<noun>/` (
69
69
  `references/tasks/verbs.md`, `references/tasks/section-editing.md`, `references/features/acceptance-criteria.md`,
70
70
  `references/rules/operations.md`, `references/workflows/authoring-workflows.md`).
71
71
 
72
+ ## Lifecycle playbooks
73
+
74
+ Authorable nouns carry a `## Lifecycle playbook` (rules: `## Lifecycle map`) in one shared stage
75
+ vocabulary — **Create → Evaluate → Triage → Enhance** — each row naming the command and the gate
76
+ that proves the stage, plus best practices. The playbook links the noun's subfiles; it never
77
+ restates them.
78
+
79
+ | Noun | Playbook |
80
+ | --- | --- |
81
+ | task | [references/tasks.md](references/tasks.md#lifecycle-playbook) |
82
+ | feature | [references/features.md](references/features.md#lifecycle-playbook) |
83
+ | rule | [references/rules.md](references/rules.md#lifecycle-map) |
84
+ | workflow | [references/workflows.md](references/workflows.md#lifecycle-playbook) |
85
+ | agent spec | [references/agent.md](references/agent.md#lifecycle-playbook-agent-specs) |
86
+ | decision | [references/decision/lifecycle.md](references/decision/lifecycle.md) |
87
+
88
+ Operational nouns (builder, message, self, history, projects) run verbs rather than author
89
+ artifacts, so they have no playbook. Cross-noun selection and composition live in
90
+ `sp:spur-composer`; read-only evaluation reports in `sp:spur-doctor`.
91
+
72
92
  ## When to use
73
93
 
74
94
  Use this skill to:
@@ -144,7 +164,8 @@ and spreading it; full contract in `docs/04_DESIGN.md` §1.0.1.
144
164
  - **[references/message.md](references/message.md)** - durable inter-agent messaging (`send`,
145
165
  `inbox`, `reply`, `watch`).
146
166
  - **[references/decision.md](references/decision.md)** - decision catalog (`list`, `show`, `run`,
147
- `status`); offline by default via the built-in `typesafe` maker.
167
+ `status`); with no reachable backend each decision serves its declared fallback. Authoring and
168
+ tuning: [references/decision/lifecycle.md](references/decision/lifecycle.md).
148
169
  - **[references/self.md](references/self.md)** - `spur self init|exec|maintain|migrate|serve|status` CLI verbs
149
170
  (the five legacy top-level nouns remain hidden aliases). `self init` runs post-scaffold init
150
171
  validation (Phase 1.5/1.6 probes).
@@ -400,6 +400,18 @@ failed drains marked the session poisoned. The next drain opens a fresh session.
400
400
  only. A settled (delivered) inbox message is never redelivered — resuming a session or resetting
401
401
  one never re-sends settled work; only never-started deliveries release and redeliver (0831/0834).
402
402
 
403
+ ## Lifecycle playbook (agent specs)
404
+
405
+ | Stage | How | Gate / evidence |
406
+ | --- | --- | --- |
407
+ | **Create** | Prefer an `agent.fleet.members` entry; hand-author `.spur/agents/<id>.yaml` only for a spec the fleet cannot express | `spur agent list --specs --json` shows the row with the intended `source` |
408
+ | **Evaluate** | `spur agent doctor [agent] --json` for the executor; `spur agent status --json` for the live process and member session | Executor ready; spec resolves |
409
+ | **Triage** | Run failed → `spur agent trace <runId> --json`; stuck occupant → `spur agent wait <specId> --until <state> --timeout <ms>`; supervisor unreachable → `spur self serve` | Lineage names the failing dispatch |
410
+ | **Enhance** | Change one field (executor, model, role) and re-run the same prompt | Compare the two `trace` records |
411
+
412
+ - The fleet declaration wins on an id clash; do not keep a same-id file "as a backup".
413
+ - Coordinate through `spur message` / `spur agent wait`, never terminal scraping.
414
+
403
415
  ## What this skill is NOT
404
416
 
405
417
  - **Not the dispatch decision.** *When* to use `spur agent run` vs a native subagent is the
@@ -80,7 +80,7 @@ spur builder pr-review --force --json # force a fresh review of
80
80
  ```
81
81
 
82
82
  Four flat verbs over the ops absorbed from `plugins/sp/scripts/pr-reviewing.ts` (script-absorption
83
- PR-7); driven by the `pr-review` workflow. Each composes existing ops and embeds their records in
83
+ PR-7); sequenced directly by `sp:pr-reviewing`. Each composes existing ops and embeds their records in
84
84
  one JSON object per verb: `pr-status` → the status object plus `review` (collect, or `null` with no
85
85
  PR); `pr-check` → `{ ok, verdict, preflight, hygiene }`; `pr-open` → `{ ok, verdict, push, pr }`;
86
86
  `pr-review` → `{ ok, verdict, request, findings }`.
@@ -94,7 +94,7 @@ PR); `pr-check` → `{ ok, verdict, preflight, hygiene }`; `pr-open` → `{ ok,
94
94
  explicit pin that no longer matches the PR head fails loud instead of reporting a moved commit.
95
95
  - **Deduping:** `pr-review` collects without a new request when the exact HEAD is already reviewed,
96
96
  and returns `PENDING` when a marked request is still in flight; `--force` requests a fresh review
97
- (`mode=rerun`). Never force-pushes.
97
+ of the current HEAD regardless. Never force-pushes.
98
98
 
99
99
  ```bash
100
100
  # deprecated alias, one release: maps the old op names to the verbs above
@@ -0,0 +1,166 @@
1
+ ---
2
+ name: spur-cli-decision-lifecycle
3
+ description: "spur decision lifecycle: author a catalog entry, wire it into a workflow, evaluate a maker with recorded evidence, triage fallbacks and catalog errors, and tune criteria, floors and makers."
4
+ see_also:
5
+ - spur-cli
6
+ - spur-composer
7
+ ---
8
+
9
+ # Decision lifecycle — create, evaluate, triage, enhance
10
+
11
+ The verb catalog is [../decision.md](../decision.md). This file is the per-noun procedure: how a
12
+ decision point is born, proven, diagnosed and improved. Contracts it links rather than restates:
13
+ [decision catalog design](../../../../../../docs/design/decision-catalog.md) (§3.1 SSOT, §3.2 layers,
14
+ §3.6 maker precedence) and
15
+ [decision observability](../../../../../../docs/design/decision-observability-and-adoption.md) (§3.4
16
+ reliability, §4 workflow audit, §5 staged adoption). The upstream format authority is the
17
+ `@gobing-ai/ts-ai-decision` README and its `schemas/decision-catalog.schema.json`.
18
+
19
+ ## 1. Decide it is a decision at all
20
+
21
+ A catalog decision is a **total classification**: a closed vocabulary, a declared fallback, and a
22
+ recorded outcome. Use the §4 audit classes before authoring anything:
23
+
24
+ | Class | Use when | Shape |
25
+ | --- | --- | --- |
26
+ | **keep-deterministic** | An exact check answers it (status file, exit code, count, regex) | No decision; a shell guard or rule |
27
+ | **rescue-only** | A deterministic parse answers most inputs; free-form output sometimes defeats it | Parse first, call the decision only on what the parse cannot classify |
28
+ | **adopt** | The input is judgement over prose/diff evidence and a safe default exists | Catalog-reference `decide` step |
29
+ | **keep-human** | It is an operator taste gate | `hitl.confirm`/`hitl.select`; opt-in `decision.mode: evidence` routes through `gate-evidence` |
30
+
31
+ A model is a regression wherever an exact check exists. A decision with no safe fallback is a gate,
32
+ not a decision.
33
+
34
+ ## 2. Create
35
+
36
+ 1. **Select first.** `spur decision list --json` across every layer; `spur decision show <id> --json`
37
+ on near matches. An existing id whose criteria fit is reused, never cloned under a new id.
38
+ 2. **Pick the layer** (the composer ladder, [spur-composer](../../../spur-composer/SKILL.md)):
39
+ scratch → `.spur/decisions/<file>.yaml` (project) → shared `config/decisions/<file>.yaml` (spur
40
+ repository only, recorded operator consent + `build:bundle`). Winners are chosen **per file
41
+ basename** before the hub loads, so a project file named like a shipped one replaces that whole
42
+ shipped file — copy every id you still need, or use a new basename.
43
+ 3. **Author the entry** (format version 1; unknown keys are rejected at every level):
44
+
45
+ ```yaml
46
+ version: 1
47
+ defaults:
48
+ minConfidence: 0.8 # repo convention for pipeline decisions; upstream default is 0.7
49
+ decisions:
50
+ review-scope: # ^[a-z][a-z0-9_-]*$ — stable id, it keys the ledger
51
+ type: choice # choice | score | noul
52
+ description: Which review depth does this diff need? # documentation only, never sent
53
+ parameters:
54
+ wbs:
55
+ type: string # string | number | boolean | enum | json
56
+ description: Task WBS the diff belongs to.
57
+ criteria: # choice: >= 2 labels, each label's meaning in one sentence
58
+ light: Docs-only or test-only diff with no runtime surface.
59
+ full: Any runtime, contract, schema or security-relevant change.
60
+ fallback: full # must be a declared label; the safe answer on any backend failure
61
+ ```
62
+
63
+ - A parameter with no `default` is **required**. `instructions` is reserved: it is the implicit
64
+ channel `--evidence` and workflow `evidence:` feed. Never declare it.
65
+ - `fallback` is the outcome on `no-backend`, `timeout`, `error` and `low-confidence`. Choose the
66
+ answer that is **safe when wrong** (`full`, `fix`, `defer`, `standard`), not the most common one.
67
+ - Leave `maker` out of shipped catalogs. Operator config outranks the catalog
68
+ (`flag → decisions.makers.<id> → decisions.maker → catalog`) because only the machine owner
69
+ knows which backends exist there.
70
+ - Spur's `DecisionService` resolves the effective maker as one name. Upstream maker chains
71
+ (`maker: [a, b]`) and `shadow` exist in the schema but are not surfaced by `decision show`
72
+ or `status` today; prove them with `run` before relying on them.
73
+ 4. **Gate it:** `spur decision status --json` must show no `loadErrors` / `duplicateIds` and exit 0;
74
+ `spur decision show <id> --json` must render the parameters, criteria and fallback you meant.
75
+
76
+ ## 3. Wire into a workflow (optional)
77
+
78
+ Use the catalog-reference `decide` form; the inline `question`/`method`/`default` form is
79
+ deprecated (composition lint and the runner warn once per site):
80
+
81
+ ```yaml
82
+ - kind: decide
83
+ options:
84
+ id: review-scope # step id; one resultFile per step
85
+ decision: review-scope # catalog id
86
+ params: { wbs: '${vars.wbs}' }
87
+ evidence: # redacted + bounded to 2000 chars, joined into instructions
88
+ - .spur/run/${vars.wbs}-diffstat.json
89
+ resultFile: .spur/run/${vars.wbs}-review-scope.decision
90
+ ```
91
+
92
+ - Guards read the schemaVersion-1 `resultFile` row (`value`, `source`, `degraded`, `confidence`).
93
+ Route on `source == "model"` only where a degraded fallback must be distinguishable.
94
+ - `workflows.decideDecisionMaker` gates the workflow action. Off (the default) → every `decide`
95
+ serves its fallback with no model call. `spur decision run` ignores the switch.
96
+ - `evidence` and `instructions` are mutually exclusive; `params.instructions` fails the action.
97
+ - Validate with `spur workflow validate <file> --json` and `spur workflow run <file> --dry-run`.
98
+
99
+ ## 4. Evaluate
100
+
101
+ Evidence before adoption — the S4a–c slices each landed only with recorded `run` evidence for the
102
+ effective maker (observability §5).
103
+
104
+ | Question | Evidence (read-only unless noted) |
105
+ | --- | --- |
106
+ | Does the contract say what I meant? | `spur decision show <id> --json` |
107
+ | Does the catalog load cleanly? | `spur decision status --json` → `ok`, `loadErrors`, `duplicateIds`, `errors` |
108
+ | Is the maker registered / configured / ever used? | `spur decision status` readiness marks (`ST`, `CONFIGURED BY`, `RECORDED`, `ACCEPTED`) |
109
+ | Does the maker answer right now? | `spur decision status --probe` (calls each effective maker once; writes nothing) |
110
+ | How well has it served? | `spur decision status --reliability [--since <iso>] --json` → per `decisionId × maker`: `samples`, `acceptedRate`, `fallbacks{reason}`, `medianConfidence`, p50/p95 duration |
111
+ | Does it classify known cases correctly? | `spur decision run <id> --param … --evidence <fixture> --json` per labelled fixture (records a ledger row) |
112
+
113
+ Build a small labelled fixture set — at least one clear case per label plus one ambiguous case — and
114
+ run it against each candidate maker with `--maker <name>`. Compare `value` to the label, not just
115
+ `source: model`: an accepted wrong answer is worse than a fallback.
116
+
117
+ **Read confidence per maker type.** Probability-native makers (`typesafe`, `laya-local`, `clef`)
118
+ return a model distribution. Sampled makers (`fm-local`) return agreement over k samples, so
119
+ `accepted` means "all samples agreed" and 1.0 is unanimity, not calibration. Choose a
120
+ probability-native maker where the floor must discriminate.
121
+
122
+ ## 5. Triage
123
+
124
+ | Symptom | Likely cause | Next step |
125
+ | --- | --- | --- |
126
+ | `status` exits 1, `loadErrors` names a file | Schema violation (unknown key, fallback not a declared label, bad `${params.*}` ref) | Fix the file; the whole catalog file is skipped until it loads |
127
+ | `duplicateIds` non-empty | Same id in two winning files of different basenames | Rename or delete one; any `run`/`decide` of that id fails meanwhile |
128
+ | `run` exits 1 | Caller mistake: unknown id, undeclared/missing/invalid param, unregistered `--maker`, unreadable evidence | Read the message; nothing reached a backend |
129
+ | `source: default`, `reason: no-backend` | Maker cannot be constructed (missing credentials, wrong host) | `status --probe`; set credentials or override `decisions.makers.<id>` |
130
+ | `reason: timeout` | Cold local model or unreachable host | Re-probe; prefer a warm or hosted maker for pipeline-critical ids |
131
+ | `reason: error` | Backend rejected the call or returned an invalid answer | Check `decision_logs.error`; on `typesafe`, parameterless decisions hit the known `state: null` 422 until the ts-libs bump (design §5) |
132
+ | `reason: low-confidence`, repeated | Criteria labels overlap, evidence is too thin, or a sampled maker disagrees with itself | Sharpen criteria (§6), add evidence, or switch to a probability-native maker |
133
+ | `RECORDED > 0`, `ACCEPTED 0` | Maker is wired but has never once succeeded | Treat as broken, not healthy; triage by `fallbacks` reason |
134
+ | Config names a maker `status` calls unregistered | Typo, or `clef` without `CLOUDFLARE_ACCOUNT_ID`/`CLOUDFLARE_AUTH_TOKEN` | Loud by design — fix the name or the environment |
135
+ | A `decide` step always degrades | `workflows.decideDecisionMaker` is off | Intended default; enable only after §4 evidence |
136
+
137
+ ## 6. Enhance
138
+
139
+ Tune one lever at a time and re-run the same fixture set; a change with no before/after evidence
140
+ pair is a preference.
141
+
142
+ | Lever | When | Where |
143
+ | --- | --- | --- |
144
+ | **Criteria wording** | Low confidence or wrong labels on clear cases | Make labels mutually exclusive and observable ("touches runtime code"), not evaluative ("risky") |
145
+ | **Evidence** | The model cannot see what decides the answer | Add or trim workflow `evidence` files; keep each well under the 2000-char bound |
146
+ | **Parameters** | The answer depends on a structured fact | Declare a typed parameter instead of burying it in evidence |
147
+ | **`minConfidence`** | Fallback rate is too high with correct answers, or too low with wrong ones | Per-decision field; lower only with fixture evidence that low-confidence answers were right |
148
+ | **Maker** | Reliability differs by backend | Operator config `decisions.makers.<id>` (not the shipped catalog) |
149
+ | **Fallback** | The safe-when-wrong answer changed | Change only with the owning workflow's guard reviewed in the same change |
150
+ | **Adoption class** | A deterministic parse now covers the input | Demote to rescue-only or keep-deterministic |
151
+
152
+ Never rename a shipped id: the ledger, Board Decisions tab and workflow `decision:` references all
153
+ key on it. Add a new id and retire the old one through the workflow change.
154
+
155
+ ## 7. Best practices
156
+
157
+ - **Determinism first, model second.** Every adopted decision keeps a deterministic route or a safe
158
+ fallback so the pipeline behaves identically with the switch off.
159
+ - **One question per id.** A decision that needs "and" in its description is two decisions.
160
+ - **Labels are a contract.** Guards and downstream shell read the label strings; treat a label
161
+ rename as a breaking change.
162
+ - **Probe is not evidence.** `--probe` proves liveness; only `--reliability` and labelled `run`
163
+ results prove quality, and the probe never writes the rows it would inflate.
164
+ - **Never route pipeline correctness on `maker-liveness`.** It serves only `status --probe`.
165
+ - **Measure before you migrate.** Land the catalog entry, gather `run` evidence, then adopt in a
166
+ workflow — one decision point per change.