@gobing-ai/spur 0.4.15 → 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.
- package/.claude-plugin/marketplace.json +1 -1
- package/config/config.global.yaml +21 -8
- package/config/decisions/executor.yaml +53 -0
- package/config/decisions/task-pipeline.yaml +44 -28
- package/config/workflows/task-pipeline.yaml +66 -54
- package/package.json +11 -10
- package/plugins/sp/README.md +1 -1
- package/plugins/sp/agents/expert-spur.md +3 -0
- package/plugins/sp/agents/super-planner.md +5 -1
- package/plugins/sp/agents/super-reviewer.md +43 -12
- package/plugins/sp/commands/dev-fixall.md +7 -2
- package/plugins/sp/commands/dev-idea.md +6 -1
- package/plugins/sp/commands/dev-run.md +3 -0
- package/plugins/sp/commands/dev-runall.md +6 -3
- package/plugins/sp/commands/dev-verify.md +1 -1
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/skills/code-implementation/SKILL.md +8 -8
- package/plugins/sp/skills/code-improvement/SKILL.md +3 -3
- package/plugins/sp/skills/code-review/references/verification-before-completion.md +5 -4
- package/plugins/sp/skills/code-verification/SKILL.md +4 -4
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +27 -11
- package/plugins/sp/skills/functional-review/SKILL.md +1 -1
- package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
- package/plugins/sp/skills/spur-check/SKILL.md +1 -1
- package/plugins/sp/skills/spur-cli/SKILL.md +23 -2
- package/plugins/sp/skills/spur-cli/references/agent.md +12 -0
- package/plugins/sp/skills/spur-cli/references/decision/lifecycle.md +166 -0
- package/plugins/sp/skills/spur-cli/references/decision.md +146 -16
- package/plugins/sp/skills/spur-cli/references/features.md +12 -0
- package/plugins/sp/skills/spur-cli/references/rules.md +2 -0
- package/plugins/sp/skills/spur-cli/references/tasks.md +13 -0
- package/plugins/sp/skills/spur-cli/references/workflows/authoring-workflows.md +1 -1
- package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +3 -2
- package/plugins/sp/skills/spur-cli/references/workflows.md +9 -0
- package/plugins/sp/skills/spur-composer/SKILL.md +20 -1
- package/plugins/sp/skills/spur-dev/SKILL.md +16 -16
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +2 -2
- package/plugins/sp/skills/spur-dev/references/decision-points.md +97 -0
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +8 -8
- package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +1 -1
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +13 -3
- package/plugins/sp/skills/spur-dev/references/execution-parallel-isolation.md +4 -4
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +41 -29
- package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +33 -0
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +3 -3
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +3 -2
- package/plugins/sp/skills/spur-dev/references/glossary.md +12 -3
- package/plugins/sp/skills/spur-doctor/SKILL.md +23 -0
- package/spur.js +7378 -6052
- package/web/_astro/{BoardApp.Bjdp3XWV.js → BoardApp.CC7Mwswv.js} +65 -65
- package/web/_astro/{BoardApp.DCDZxLlQ.js → BoardApp.mWyrWCAR.js} +1 -1
- package/web/_astro/{TaskDetail.B3vBxynO.js → TaskDetail.CtAXuiv8.js} +1 -1
- package/web/_astro/{arc.DcuHTB_T.js → arc.Duf4u60i.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.ClOFWBON.js → architectureDiagram-3BPJPVTR.JoymtqxN.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.otYyr7Zb.js → blockDiagram-GPEHLZMM.BvmhcioC.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.BCjpc9LP.js → c4Diagram-AAUBKEIU.CfaWkgoQ.js} +1 -1
- package/web/_astro/channel.DtEPXXcH.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.D5Wpnpt_.js → chunk-2J33WTMH.B7uR02cD.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DkQGtWNz.js → chunk-4BX2VUAB.SwiEauYR.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.B7dqjAip.js → chunk-55IACEB6.6ZRCK8PO.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.BDQvnKE2.js → chunk-727SXJPM.Cxra_G3N.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.D92doBX5.js → chunk-AQP2D5EJ.Cxd7gZeX.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.C968oI5G.js → chunk-FMBD7UC4.DCLhFkVc.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.AkkYC1bY.js → chunk-ND2GUHAM.B9AmKcv6.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.sCc-rKKo.js → chunk-QZHKN3VN.DOjCvl6S.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.pOQ9u0mY.js → classDiagram-4FO5ZUOK.BMiT_mNf.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.pOQ9u0mY.js → classDiagram-v2-Q7XG4LA2.BMiT_mNf.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.CRaeD6FY.js → cose-bilkent-S5V4N54A.mLBCEGjI.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BiCPBu54.js → cynefin-OW5HDTMX.CjDAY0qn.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.C1-q3vkT.js → dagre-BM42HDAG._G_sP8fP.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.BSVOv30O.js → diagram-2AECGRRQ.39OcfSuz.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.CHMkjJ-V.js → diagram-5GNKFQAL.D7v_eNC4.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.CKY9M564.js → diagram-KO2AKTUF.Da1x-lhg.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.B9yNJiTP.js → diagram-LMA3HP47.C8EnzbEb.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.Dk8AUGsk.js → diagram-OG6HWLK6.DPnBj69F.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BQHR89TZ.js → erDiagram-TEJ5UH35.CXMu2TIh.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.oNkWVgoK.js → flowDiagram-I6XJVG4X.ZklePVtQ.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.Kz2U2nu9.js → ganttDiagram-6RSMTGT7.BhYOkdqk.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.DHIZ_wPq.js → gitGraphDiagram-PVQCEYII.CADyX8a1.js} +1 -1
- package/web/_astro/{infoDiagram-5YYISTIA.D0NJLcv9.js → infoDiagram-5YYISTIA.BsdmwjHt.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.CFEfTWRG.js → ishikawaDiagram-YF4QCWOH.CzjZ3Crd.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.Dc7IE7I4.js → journeyDiagram-JHISSGLW.Bxj-ZH_t.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.D5v0xO9k.js → kanban-definition-UN3LZRKU.Cbg3wVvX.js} +1 -1
- package/web/_astro/{linear.wR5KzXnE.js → linear.DJNUrBI9.js} +1 -1
- package/web/_astro/{mermaid.core.BDQ2FoPd.js → mermaid.core.DVHQV3SF.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.W6_INsia.js → mindmap-definition-RKZ34NQL.DyomosRU.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.61ihbgkK.js → pieDiagram-4H26LBE5.DajtFknN.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.B5lEpFLo.js → quadrantDiagram-W4KKPZXB.Bjq6SjGe.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.CmhVBVX0.js → requirementDiagram-4Y6WPE33.ubBVqGLP.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.D7Vvj9Wf.js → sankeyDiagram-5OEKKPKP.I4q46xd-.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.B1vPLixM.js → sequenceDiagram-3UESZ5HK.DsCgZIa8.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.BnACmrGi.js → stateDiagram-AJRCARHV.DcYjYSqT.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CW4pnmc3.js → stateDiagram-v2-BHNVJYJU.Dt8yPqiS.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.CkzMCPnC.js → timeline-definition-PNZ67QCA.0YTkoa5F.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.CY4aNdAR.js → vennDiagram-CIIHVFJN.BNl0l1hs.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.BtoU9UFk.js → wardleyDiagram-YWT4CUSO.BYSX6cfn.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6._9ijUUAs.js → xychartDiagram-2RQKCTM6.DzxxpixK.js} +1 -1
- package/web/index.html +1 -1
- package/worker/laya_worker.py +219 -0
- package/web/_astro/channel.qgOLXjI_.js +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spur-cli-decision
|
|
3
|
-
description: "spur-cli noun reference: operate `spur decision` as the read/serve surface over the decision catalog - list registered decisions, show one served contract (parameters, criteria vocabulary, effective maker), run a decision to a served outcome (never writes a workflow resultFile), and status the catalog layers with per-maker readiness marks (registered, configured, recorded, probed). Backed by @gobing-ai/ts-ai-decision
|
|
3
|
+
description: "spur-cli noun reference: operate `spur decision` as the read/serve surface over the decision catalog - list registered decisions, show one served contract (parameters, criteria vocabulary, effective maker), run a decision to a served outcome (never writes a workflow resultFile), and status the catalog layers with per-maker readiness marks (registered, configured, recorded, probed). Backed by the @gobing-ai/ts-ai-decision hub; with no reachable backend every decision serves its declared fallback. Lifecycle (author, evaluate, triage, tune) lives in decision/lifecycle.md."
|
|
4
4
|
see_also:
|
|
5
5
|
- spur-cli
|
|
6
6
|
---
|
|
@@ -25,14 +25,16 @@ Decisions resolve first-wins across three layers:
|
|
|
25
25
|
| `registered` | folders listed in config `decisions.paths` | Operator-added catalogs |
|
|
26
26
|
| `shared` | `decisions/` under the bundled config root | Shipped catalogs (`config/decisions/` in-repo) |
|
|
27
27
|
|
|
28
|
-
The bundled shared catalog ships `task-
|
|
28
|
+
The bundled shared catalog ships `task-semantic-risk`, `failure-class`,
|
|
29
29
|
`gate-evidence`, `idea-recommendation`, `needs-design`, `anatomy-validation-verdict` and
|
|
30
30
|
`maker-liveness` (the last served only by `spur decision status --probe`; no workflow references
|
|
31
|
-
it).
|
|
31
|
+
it). Layers win **per file basename** (a project `gates.yaml` replaces the shipped `gates.yaml`
|
|
32
|
+
whole); the same id in two winning files of different basenames is a `duplicateIds` catalog error.
|
|
32
33
|
|
|
33
34
|
**Config keys** (under `decisions:` in the global `~/.config/spur/config.yaml` or project `.spur/config.yaml`):
|
|
34
35
|
`paths` (extra catalog folders forming the `registered` layer), `maker` (default DecisionMaker
|
|
35
|
-
for every decision point), `makers` (per-decision-id overrides)
|
|
36
|
+
for every decision point), `makers` (per-decision-id overrides), `log` (`full` | `metadata` | `off`,
|
|
37
|
+
how much of each served decision the ledger keeps). An unregistered maker name is a
|
|
36
38
|
config error, never a silent fallback (design §3.6).
|
|
37
39
|
|
|
38
40
|
## Verb map
|
|
@@ -43,6 +45,7 @@ config error, never a silent fallback (design §3.6).
|
|
|
43
45
|
| `show <id>` | One served contract: type, parameters, criteria, fallback, minConfidence, effective maker + source | `--json` |
|
|
44
46
|
| `run <id>` | Serve one outcome (closed vocabulary; **never writes a resultFile**) | `--param <pairs...>`, `--evidence <files...>`, `--maker <name>`, `--json` |
|
|
45
47
|
| `status` | Sectioned readiness report: one status line, errors, aligned `Makers` and `Decisions` tables (registration, configuration source, recorded evidence), `Catalog` block | `--probe`, `--reliability [--since <iso>]`, `--json` |
|
|
48
|
+
| `outcome <invocation-id>` | Record what actually happened after a served decision — acceptance is not accuracy (task 1263). First write wins | `<outcome>`, `--review-severity <wbs>`, `--gate-status <run-id>`, `--source <text>`, `--json` |
|
|
46
49
|
|
|
47
50
|
All verbs support `--json` (bare payload) and `--json-envelope` (`{ok, data|error}` envelope,
|
|
48
51
|
ADR-091). Failure output for `--json` commands uses the canonical error envelope only under
|
|
@@ -51,6 +54,62 @@ ADR-091). Failure output for `--json` commands uses the canonical error envelope
|
|
|
51
54
|
**Exit codes:** `status` exits 1 on any catalog load error or maker-config error; `show` exits 1 on unknown id; `list` exits 0
|
|
52
55
|
(design §3.4 — load errors surface via `status`) except for an invalid `--layer` value (exit 1).
|
|
53
56
|
Error envelopes use `NOT_FOUND` for an unknown id and `VALIDATION_FAILED` for every other caller mistake.
|
|
57
|
+
`outcome` exits 1 for an unknown invocation id (there is no decision to score) and 2 for a malformed
|
|
58
|
+
outcome (it must match `^[a-z0-9-]{1,32}$`) or for naming zero/several outcome sources.
|
|
59
|
+
|
|
60
|
+
## Acceptance versus accuracy (`outcome` + `--reliability`)
|
|
61
|
+
|
|
62
|
+
`decision.end` says **what was answered**; it never says whether the answer was right. A maker can
|
|
63
|
+
be accepted on every call and still add no information: `review-failure-class` answered its own
|
|
64
|
+
fallback 15/15 times at confidence 1.0 before task 1262 retired it. Tuning `minConfidence`, choosing
|
|
65
|
+
a maker, or judging a shadow maker therefore needs (value, outcome) pairs.
|
|
66
|
+
|
|
67
|
+
**Recording one.** A decide step now writes the invocation's ledger key into its result row
|
|
68
|
+
(`invocationId`, task 1263 R1) — the same id the `decision.*` events and the `decision_logs` row
|
|
69
|
+
carry. Once the outcome is known, record it:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# an explicit label (lowercase slug): what a human or a later check observed
|
|
73
|
+
spur decision outcome <invocation-id> fixed --source "quality gate recheck"
|
|
74
|
+
# derived from a task's Review findings: the worst finding, resolved rows included (p1-p4, or none)
|
|
75
|
+
spur decision outcome <invocation-id> --review-severity 1263
|
|
76
|
+
# derived from a gate visit: PASS -> fixed, anything else (or a missing token) -> not-fixed
|
|
77
|
+
spur decision outcome <invocation-id> --gate-status <run-id>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
First write wins: a replay exits 0 with `recorded: false` and the outcome that already stands. The
|
|
81
|
+
row lands in `system_events` beside `decision.end`, on the same `run_id`, so the report joins it by
|
|
82
|
+
`invocationId`.
|
|
83
|
+
|
|
84
|
+
**Scoring one.** `decisions.outcomeMap` in config (project or global layer) holds Spur's reading of
|
|
85
|
+
Spur's own artifacts — per decision id, which recorded outcomes count as correct for each served
|
|
86
|
+
value (`String(value)` keys, so a yes/no decision uses `"true"`/`"false"`). The shipped defaults
|
|
87
|
+
score `failure-class` (`fix` → `fixed`, `stop` → `not-fixed`) and `task-semantic-risk`
|
|
88
|
+
(`"false"` → `none`/`p4`/`p3`, `"true"` → `p1`/`p2`).
|
|
89
|
+
|
|
90
|
+
`spur decision status --reliability` then reports, per (decision × maker) group:
|
|
91
|
+
|
|
92
|
+
| Field | Meaning |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `samples`, `accepted`, `acceptedRate` | `decision.end` rows; acceptance only |
|
|
95
|
+
| `outcomes` | recorded outcomes by label over those samples |
|
|
96
|
+
| `accuracy` | correct accepted answers ÷ accepted answers **with an outcome**; null when the decision has no map entry or no accepted sample recorded one |
|
|
97
|
+
| `fallbackAccuracy` | the same ratio over fallback (`source: default`) samples |
|
|
98
|
+
|
|
99
|
+
`accuracy: null` is deliberate: an unmapped decision or an unobserved one is unknown, never zero.
|
|
100
|
+
Acceptance and accuracy answer different questions — a high `acceptedRate` with `accuracy: null`
|
|
101
|
+
means "the maker answered and we have not looked at whether it was right yet".
|
|
102
|
+
|
|
103
|
+
**Reading a sampled maker.** Sampled makers report unanimity, not calibration: with two options,
|
|
104
|
+
2-of-3 agreement is ~0.08 confidence and the 0.8 floor only accepts when every sample agreed
|
|
105
|
+
(ts-libs `docs/design/llm-agent-decision-backend.md` § Confidence granularity). A 1.0 confidence on
|
|
106
|
+
that kind of maker therefore means "the samples agreed", not "the answer is calibrated".
|
|
107
|
+
|
|
108
|
+
**Retuning `minConfidence` from the report.** Read a group's `accuracy` and `fallbackAccuracy`
|
|
109
|
+
together with `fallbacks` by reason. Accepted-but-wrong answers point at raising the floor (or
|
|
110
|
+
changing the maker); fallbacks that were right point at lowering it. Change the floor in the
|
|
111
|
+
catalog entry (or `defaults.minConfidence`), record the new samples, and compare the same two
|
|
112
|
+
numbers — never one of them alone.
|
|
54
113
|
|
|
55
114
|
## Readiness marks (`status`, feature P11)
|
|
56
115
|
|
|
@@ -77,6 +136,57 @@ error surfaced as fallback, declined — is still a **successful serve** (exit 0
|
|
|
77
136
|
**before** the backend: unknown id, unknown parameter, missing required parameter, type-invalid
|
|
78
137
|
parameter, unregistered `--maker`, unreadable evidence file.
|
|
79
138
|
|
|
139
|
+
## Executor failure rescue (`executor-failure-class`)
|
|
140
|
+
|
|
141
|
+
The agent executor escalates on `FAILURE_RULES` matches only (`packages/app/src/services/failure-classification.ts`).
|
|
142
|
+
A failure no rule matches — a reworded rate limit, "credits depleted", a proxy error body — ends
|
|
143
|
+
the run as a task defect until somebody adds a regex. `executor-failure-class` covers that residue:
|
|
144
|
+
`resource-exhaustion` / `auth` / `task-defect`, fallback `task-defect`, `minConfidence: 0.85`
|
|
145
|
+
(a false `resource-exhaustion` costs a failover attempt; a false `task-defect` equals today's
|
|
146
|
+
behaviour, so uncertainty must resolve downward).
|
|
147
|
+
|
|
148
|
+
**It ships off.** `workflows.executorFailureDecisionMaker: true` is the opt-in; without it the executor
|
|
149
|
+
makes no model call and the context carries no rescue seam at all. Turning it on is an operator
|
|
150
|
+
call backed by replay evidence (`spur decision run executor-failure-class --evidence <tail>` over
|
|
151
|
+
real unmatched tails), not a default.
|
|
152
|
+
|
|
153
|
+
The rescue runs only when every deterministic check declined: non-zero exit without a timeout
|
|
154
|
+
signal, `undefined` from `classifyDispatch`, no permission-denial evidence (a denial stays terminal),
|
|
155
|
+
no confirmed quota event, and non-blank output. It sees the failure text **redacted first, then
|
|
156
|
+
tailed** to 4096 characters — tailing first could cut a secret at the boundary and send the
|
|
157
|
+
fragment off-box, so never reorder that.
|
|
158
|
+
|
|
159
|
+
**Evidence leaves the machine with a hosted maker.** The tail is failure output from whatever the
|
|
160
|
+
agent printed, so a hosted maker (`clef`) sees it. Two consequences:
|
|
161
|
+
|
|
162
|
+
- Prefer a **probability-native** maker for this id (`decisions.makers.executor-failure-class`):
|
|
163
|
+
sampled makers accept only on unanimity (ts-libs `docs/design/llm-agent-decision-backend.md`
|
|
164
|
+
§ Confidence granularity), so the 0.85 floor does not grade them.
|
|
165
|
+
- `laya-local` keeps the evidence on-box (it needs Apple Silicon, and since task 1262 R1 the bundled
|
|
166
|
+
CLI ships its worker, so `workerScript` resolves without a source checkout).
|
|
167
|
+
|
|
168
|
+
Every rescue is attributed `caller: executor` with the failing run's id, so it shows up in
|
|
169
|
+
`decision.*` events, `decision_logs` and `spur decision status --reliability` with no extra work.
|
|
170
|
+
To promote recurring text into a deterministic rule, list the accepted rescues:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
sqlite3 .spur/spur.db "
|
|
174
|
+
SELECT o.decision_id, json_extract(o.payload_json, '$.data.outcome') AS answer,
|
|
175
|
+
json_extract(s.payload_json, '$.data.workflowName') AS workflow, o.run_id
|
|
176
|
+
FROM system_events o
|
|
177
|
+
JOIN system_events s
|
|
178
|
+
ON s.event_name = 'decision.start'
|
|
179
|
+
AND json_extract(s.payload_json, '$.data.invocationId')
|
|
180
|
+
= json_extract(o.payload_json, '$.data.invocationId')
|
|
181
|
+
WHERE o.event_name = 'decision.end'
|
|
182
|
+
AND json_extract(o.payload_json, '$.data.caller') = 'executor'
|
|
183
|
+
AND json_extract(o.payload_json, '$.data.source') = 'model'
|
|
184
|
+
ORDER BY o.occurred_at DESC;"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Add the `FAILURE_RULES` entry by hand, with a test — the rescue stays the safety net for what the
|
|
188
|
+
table still misses.
|
|
189
|
+
|
|
80
190
|
## Parameters and evidence
|
|
81
191
|
|
|
82
192
|
`--param k=v` is repeatable and validated against the decision's declared parameters: values for
|
|
@@ -95,23 +205,41 @@ keys). An unreadable evidence file exits 1 before any backend call.
|
|
|
95
205
|
Makers resolve `flag → config-decision → config-default → catalog-decision → catalog-default`;
|
|
96
206
|
`decision show` reports the effective maker as `{name, source}` with that source precedence
|
|
97
207
|
(operator config outranks the shipped catalog because only the machine owner knows which backends
|
|
98
|
-
exist there). The final `catalog-default` maker is the hub built-in `typesafe
|
|
99
|
-
|
|
100
|
-
`
|
|
208
|
+
exist there). The final `catalog-default` maker is the hub built-in `typesafe`, a **hosted** maker
|
|
209
|
+
that needs `TYPESAFE_API_KEY`. Without a reachable backend `run` still exits 0 with the declared
|
|
210
|
+
fallback (`source: default`, reason `no-backend`), which is why it is usable in tests and scripts
|
|
211
|
+
with no model access — the outcome is deterministic, not model-judged.
|
|
212
|
+
|
|
213
|
+
**Available makers:** the four upstream built-ins (`typesafe`, `fm-local`, `laya-local`,
|
|
214
|
+
`llm-agent`) plus Spur's hosted `clef` (Cloudflare Workers AI via `@gobing-ai/ts-decision-clef`).
|
|
215
|
+
|
|
216
|
+
- `llm-agent` samples an installed coding agent: by default the first installed tier-1 agent, 3
|
|
217
|
+
one-shot samples, accepted only when every sample agrees. Spur passes it no driver options, so
|
|
218
|
+
each ask costs several agent runs; name it per decision (`decisions.makers.<id>`) rather than as
|
|
219
|
+
the project-wide `decisions.maker`.
|
|
220
|
+
- `clef` registers only when both `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_AUTH_TOKEN` are set in
|
|
221
|
+
the environment; without them it is absent from `registeredMakers`, so naming it in config or
|
|
222
|
+
`--maker` is a config error, never a silent fallback. Its model defaults to `clef-flash` (a
|
|
223
|
+
catalog `model` selects `clef`).
|
|
224
|
+
|
|
225
|
+
## Workflow consumption
|
|
101
226
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
`
|
|
227
|
+
Workflows consume a decision through the catalog-reference `decide` action
|
|
228
|
+
(`{id, decision, params?, evidence? | instructions?, resultFile}`); the inline
|
|
229
|
+
`question`/`method`/`default` form is deprecated. `workflows.decideDecisionMaker` (default off)
|
|
230
|
+
gates model calls there — off, every `decide` serves its fallback. `hitl.confirm`/`hitl.select`
|
|
231
|
+
with `decision: {mode: evidence, …}` route through `gate-evidence` under the separate
|
|
232
|
+
`workflows.hitlDecisionMaker` switch (default off — the gate defers to the operator, or under
|
|
233
|
+
`profile=auto` to its declared fallback). Neither switch affects `spur decision run`. Shape, adoption classes and
|
|
234
|
+
guards: [decision/lifecycle.md](decision/lifecycle.md) §1, §3.
|
|
108
235
|
|
|
109
236
|
## Examples
|
|
110
237
|
|
|
111
238
|
```bash
|
|
112
239
|
spur decision list --json | jq -r '.[].id'
|
|
113
|
-
spur decision show task-
|
|
114
|
-
spur decision run task-
|
|
240
|
+
spur decision show task-semantic-risk # inspect contract before serving
|
|
241
|
+
spur decision run task-semantic-risk --param wbs=1093 \
|
|
242
|
+
--evidence .spur/run/1093-diffstat.json --evidence docs/tasks/1093_*.md --json
|
|
115
243
|
spur decision run failure-class --param wbs=1093 \
|
|
116
244
|
--evidence .spur/run/<runId>-test-output.txt # redacted evidence -> instructions
|
|
117
245
|
spur decision status --json | jq '.loadErrors' # audit catalog health
|
|
@@ -124,7 +252,9 @@ spur decision status --json | jq '.makers[] | {name, registered, recorded: .evid
|
|
|
124
252
|
|
|
125
253
|
- Design: `docs/design/decision-catalog.md` (§2 catalog authoring, §3.4 CLI surface),
|
|
126
254
|
`docs/design/decision-observability-and-adoption.md` (§3.4 reliability report, §3.4.1 readiness view)
|
|
127
|
-
-
|
|
255
|
+
- Lifecycle: [decision/lifecycle.md](decision/lifecycle.md) (create, wire, evaluate, triage, enhance)
|
|
256
|
+
- Hub: `@gobing-ai/ts-ai-decision`, version pinned by the root `workspaces.catalog` (`DecisionService`,
|
|
257
|
+
catalog schema, maker registry)
|
|
128
258
|
- App service: `packages/app/src/decision/decision-service.ts` (makers, `probeMaker`),
|
|
129
259
|
`packages/app/src/decision/decision-status-readiness.ts` (readiness marks, probe loop)
|
|
130
260
|
- Shipped catalogs: `config/decisions/*.yaml`
|
|
@@ -285,6 +285,18 @@ spur feature sync H2 --folder docs/custom-tasks --json # non-default tasks fol
|
|
|
285
285
|
`{ featureId, from, to, reason, requiresConfirm?, gateBlocked?, gateFindings?, hops? }`.
|
|
286
286
|
- **Exit codes:** `0` success (including NOOP), `1` error, `2` invalid usage (no id and no `--all`).
|
|
287
287
|
|
|
288
|
+
## Lifecycle playbook
|
|
289
|
+
|
|
290
|
+
| Stage | How | Gate / evidence |
|
|
291
|
+
| --- | --- | --- |
|
|
292
|
+
| **Create** | `spur feature create <name> [--parent <id>]`; place it MECE in the tree ([features/hierarchy-mece.md](features/hierarchy-mece.md)) | `spur feature check <id> --json` exits 0 |
|
|
293
|
+
| **Evaluate** | AC quality ([features/acceptance-criteria.md](features/acceptance-criteria.md)), [traceability](#traceability-habits), roadmap fit ([features/roadmap-priority.md](features/roadmap-priority.md)) | `sp:spur-doctor` report cites `check` rows |
|
|
294
|
+
| **Triage** | Structural finding → `check --fix`; stale roster → `refresh`; status drift → `sync --dry-run` then `sync` | `check` clean; `sync --dry-run` empty |
|
|
295
|
+
| **Enhance** | `update --section` for AC/scope; `move --dry-run` before re-parenting a subtree | Every task still links to a live AC |
|
|
296
|
+
|
|
297
|
+
- A feature is a capability, not a work list; tasks own execution.
|
|
298
|
+
- Re-parent with `move`, never by renaming IDs by hand.
|
|
299
|
+
|
|
288
300
|
## What this skill is NOT
|
|
289
301
|
|
|
290
302
|
- **Not the planning loop.** Intake → create → AC generation → check-loop → decomposition →
|
|
@@ -22,6 +22,8 @@ Operating the gate well is a full lifecycle — not just running it. This skill
|
|
|
22
22
|
| **Run & fix** | Gate the diff, interpret findings, self-correct, re-run until green | this file |
|
|
23
23
|
| **Author** | Add a constraint by writing a new rule when a standard/anti-pattern emerges | [rules/authoring-rules.md](rules/authoring-rules.md) |
|
|
24
24
|
| **Fine-tune** | Dial in quality: severity, glob scoping, exemptions, preset `disable`/`overrides`, layering | [rules/fine-tuning.md](rules/fine-tuning.md) |
|
|
25
|
+
| **Evaluate** | `spur rule trace --last <n> --json` for hit rates and noise; `spur rule list --preset <name> --json` for what is enforced | this file, [rules/operations.md](rules/operations.md) |
|
|
26
|
+
| **Triage** | Start from `spur rule trace <run-id> --json`: false positive → scope/exempt; true positive → fix the code, never the rule | [rules/fine-tuning.md](rules/fine-tuning.md) |
|
|
25
27
|
| **Validate & extend** | Validate files/presets, smoke-test, add custom evaluators/resolvers/formatters | [rules/validation-and-extension.md](rules/validation-and-extension.md) |
|
|
26
28
|
|
|
27
29
|
## When to use
|
|
@@ -359,6 +359,19 @@ spur task path 0040 --json
|
|
|
359
359
|
basename-WBS fallback. Exit `1` when no task owns the path.
|
|
360
360
|
- `path <wbs>` is the inverse — absolute task file path for a WBS.
|
|
361
361
|
|
|
362
|
+
## Lifecycle playbook
|
|
363
|
+
|
|
364
|
+
| Stage | How | Gate / evidence |
|
|
365
|
+
| --- | --- | --- |
|
|
366
|
+
| **Create** | `spur task create <title> --feature <id>` ([Creating tasks](#creating-tasks)), then fill sections ([tasks/section-editing.md](tasks/section-editing.md)) | `spur task check <wbs> --json` exits 0 |
|
|
367
|
+
| **Evaluate** | Readiness matrix ([check --json](#the-readiness-matrix--check---json)); `--precheck` before a pipeline run | `sp:spur-doctor` report cites the check rows |
|
|
368
|
+
| **Triage** | Structural finding → `check --fix`; L3 refusal → [tasks/l3-guard-cheatsheet.md](tasks/l3-guard-cheatsheet.md); batch admission → `spur task preflight <wbs> --json` | Re-run `check` until clean |
|
|
369
|
+
| **Enhance** | Replace one section from a temp file; batch refinement through `/sp:dev-refineall --feature <id> --auto` | Same `check` passes; AC still traces to the feature |
|
|
370
|
+
|
|
371
|
+
- One deliverable per task; split rather than stack ACs from two features.
|
|
372
|
+
- Every AC is observable and verifiable by a named command or file, never by self-report.
|
|
373
|
+
- Status moves only through `update`/`record`; never hand-edit frontmatter.
|
|
374
|
+
|
|
362
375
|
## What this skill is NOT
|
|
363
376
|
|
|
364
377
|
- **Not the pipeline.** Driving a task through `task-pipeline.yaml`, HITL surfacing, and
|
|
@@ -138,7 +138,7 @@ Spur's host additionally registers (`registerSpurBuiltins`, `packages/app/src/wo
|
|
|
138
138
|
|
|
139
139
|
| Kind | Capability |
|
|
140
140
|
| ---- | ---------- |
|
|
141
|
-
| Action | `agent.run` (model call via `spur agent run`; `executor: 'fleet'` dispatches into the agent fleet), `decide` (
|
|
141
|
+
| Action | `agent.run` (model call via `spur agent run`; `executor: 'fleet'` dispatches into the agent fleet), `decide` (catalog reference `{id, decision, params?, evidence? \| instructions?, resultFile}` → a schemaVersion-1 row; gated by `workflows.decideDecisionMaker`, fallback row when off; the inline `question`/`method`/`default` form is deprecated, and a shell `spur decision run` bypasses the switch — see [decision lifecycle](../decision/lifecycle.md)), `command.gate`, `rule.check`, `doctor.probe`, `proof.fingerprint`, `run.artifact`, `file.exists`, `file.read`, `file.read.into-var`, `http.request`, `hitl.confirm`, `hitl.select`, `hitl.input`, `shell` (streaming) |
|
|
142
142
|
| Guard | `shell` (env-aware), `contract-violation` |
|
|
143
143
|
|
|
144
144
|
Order matters for both guards and conditions: **the first that passes wins.** Put the discriminating
|
|
@@ -53,8 +53,9 @@ when the run count justifies it. One or zero → **descriptive procedure**; say
|
|
|
53
53
|
| "Retry until the gate passes", "loop until clean" | workflow — bounded loop is the engine's job |
|
|
54
54
|
| "Pause for approval, continue later / in another session" | workflow — HITL resume needs a run record |
|
|
55
55
|
| "Every night", "for each task in the batch", unattended | workflow — replay + record |
|
|
56
|
-
| "Then check whether it looks right and decide" | prose — the
|
|
57
|
-
| "It depends what the diff says" | prose —
|
|
56
|
+
| "Then check whether it looks right and decide" | prose — unless the answer is a closed set with a safe default; then a catalog `decide` step |
|
|
57
|
+
| "It depends what the diff says" | prose — unless a deterministic floor routes first and a catalog decision refines it (task-triage pattern) |
|
|
58
|
+
| "Classify the failure, then fix or stop" | workflow — a `decide` row the guard reads ([decision points](../../../spur-dev/references/decision-points.md)) |
|
|
58
59
|
| Runs once, then the situation has changed | prose — a checklist, not a definition |
|
|
59
60
|
| One operator, in-session, watching each step | prose — the trace has no second reader |
|
|
60
61
|
|
|
@@ -422,6 +422,15 @@ a **pipeline** (validate → dry-run → read trace → refine). It also covers
|
|
|
422
422
|
extending the engine with custom actions/guards. It does not execute the orchestrated *work* itself —
|
|
423
423
|
the workflow's actions (`shell`, custom runners) do that; this skill builds and operates the workflow.
|
|
424
424
|
|
|
425
|
+
## Lifecycle playbook
|
|
426
|
+
|
|
427
|
+
| Stage | How | Gate / evidence |
|
|
428
|
+
| --- | --- | --- |
|
|
429
|
+
| **Create** | [Fit gate](#decide-it-is-a-workflow-at-all--before-the-mode), then the composer ladder (ephemeral → `.spur/workflows/` → shared); author per [workflows/authoring-workflows.md](workflows/authoring-workflows.md) | `spur workflow validate <file> --json` clean |
|
|
430
|
+
| **Evaluate** | Dry-run, then a real run; `spur workflow profile <workflow> --json` and `cost` for measured spend | [Composition measures](#composition-measures-and-the-advisory-0615) within budget |
|
|
431
|
+
| **Triage** | `spur workflow trace <run-id> --json` → the failing node; [workflows/operations.md](workflows/operations.md) for HITL/continue/cancel | Re-run reaches the node and passes |
|
|
432
|
+
| **Enhance** | Tune from measured evidence ([workflows/workflow-fit-and-tuning.md](workflows/workflow-fit-and-tuning.md)); judgement steps adopt a catalog `decide` ([decision/lifecycle.md](decision/lifecycle.md) §3) | Before/after `profile` pair |
|
|
433
|
+
|
|
425
434
|
## Gotchas
|
|
426
435
|
|
|
427
436
|
1. **`kind` is required for transition-flow, optional for state-machine.** A missing `kind` silently
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spur-composer
|
|
3
|
-
description: "Select, compose and tune spur artifacts — tasks, features, rules, workflows, agent specs and project Board modules. Owns workflow catalog selection, the ephemeral→project→shared ladder, ADR-115 budgets, trace-driven rule tuning and applying accepted sp:spur-doctor proposals. Triggers: compose a workflow, tune a rule, add a Board module."
|
|
3
|
+
description: "Select, compose and tune spur artifacts — tasks, features, rules, workflows, decisions, agent specs and project Board modules. Owns workflow catalog selection, the ephemeral→project→shared ladder, ADR-115 budgets, trace-driven rule tuning and applying accepted sp:spur-doctor proposals. Triggers: compose a workflow, tune a rule, add a Board module."
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
version: 1.0.0
|
|
6
6
|
metadata:
|
|
@@ -49,6 +49,7 @@ its own output and never runs a recurring loop — evaluation is the doctor's jo
|
|
|
49
49
|
| feature | Apply accepted rows through `spur feature update --section --from-file`; keep acceptance criteria in Gherkin | [../spur-cli/references/features.md](../spur-cli/references/features.md) |
|
|
50
50
|
| rule | The trace-driven tuning loop (§ Rule tuning loop) | [../spur-cli/references/rules.md](../spur-cli/references/rules.md) · [fine-tuning](../spur-cli/references/rules/fine-tuning.md) |
|
|
51
51
|
| workflow | Catalog selection, the composition ladder, and the ADR-115 budgets (§ below) | [../spur-cli/references/workflows.md](../spur-cli/references/workflows.md) · [operations](../spur-cli/references/workflows/operations.md) |
|
|
52
|
+
| decision | Select an existing id, place new entries up the layer ladder, tune maker/criteria from reliability evidence, adopt in workflows by class (§ Decision composition) | [../spur-cli/references/decision.md](../spur-cli/references/decision.md) · [lifecycle](../spur-cli/references/decision/lifecycle.md) |
|
|
52
53
|
| agent spec | Read through `spur agent list --specs`; fleet member specs are derived in memory from `agent.fleet` (never written to `.spur/agents/`) | [../spur-cli/references/agent.md](../spur-cli/references/agent.md) |
|
|
53
54
|
| board module | Declare under `bootstrap.modules`, gated by the serve preflight (§ Board module composition) | [../spur-cli/references/serve.md](../spur-cli/references/serve.md) |
|
|
54
55
|
|
|
@@ -144,6 +145,24 @@ Start from trace evidence, never from a guess:
|
|
|
144
145
|
5. `spur rule run` on the affected inputs (constitution T11 — affected inputs, not a corpus sweep).
|
|
145
146
|
6. Trace again and compare. A tuning with no trace pair behind it is a preference.
|
|
146
147
|
|
|
148
|
+
## Decision composition
|
|
149
|
+
|
|
150
|
+
Same select → compose → tune shape, applied to the decision catalog
|
|
151
|
+
([lifecycle](../spur-cli/references/decision/lifecycle.md)):
|
|
152
|
+
|
|
153
|
+
1. **Classify first.** keep-deterministic, rescue-only, adopt or keep-human (lifecycle §1). Only
|
|
154
|
+
adopt and rescue-only become a catalog entry.
|
|
155
|
+
2. **Select.** `spur decision list --json`; reuse an id whose criteria fit.
|
|
156
|
+
3. **Compose up the ladder.** `.spur/decisions/<file>.yaml` (project) → `config/decisions/` (shared,
|
|
157
|
+
recorded operator consent + `build:bundle`). A project file shadows the shipped file of the same
|
|
158
|
+
basename whole.
|
|
159
|
+
4. **Tune from evidence.** Labelled `spur decision run --maker <name>` fixtures, then
|
|
160
|
+
`spur decision status --reliability --json`; one lever per pass (lifecycle §6). The maker
|
|
161
|
+
override goes in operator config, never the shipped catalog.
|
|
162
|
+
5. **Adopt in a workflow.** One catalog-reference `decide` step per change, validated with
|
|
163
|
+
`spur workflow validate` and `spur workflow run --dry-run`; the fallback must stay safe with
|
|
164
|
+
`workflows.decideDecisionMaker` off.
|
|
165
|
+
|
|
147
166
|
## Applying doctor proposals
|
|
148
167
|
|
|
149
168
|
`sp:spur-doctor` ([../spur-doctor/SKILL.md](../spur-doctor/SKILL.md)) returns a proposal table;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spur-dev
|
|
3
|
-
description: 'The thin orchestration spine for the planning→execution lifecycle: intake, feature-check/batch-create gates, the execution pipeline (precheck→implement→
|
|
3
|
+
description: 'The thin orchestration spine for the planning→execution lifecycle: intake, feature-check/batch-create gates, the execution pipeline (precheck→implement→gate⇄remediate→review→done), catalog decision points, HITL gating. Dispatches competency skills; never inlines them. Triggers: "run the pipeline", "drive this task", "plan a feature end to end", "continue the pipeline run", or operating the full lifecycle.'
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: spur
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.2"
|
|
8
8
|
platforms: "claude-code,codex,openclaw,opencode,antigravity"
|
|
9
9
|
interactions:
|
|
10
10
|
- pipeline
|
|
@@ -23,11 +23,9 @@ metadata:
|
|
|
23
23
|
execution_steps:
|
|
24
24
|
- precheck
|
|
25
25
|
- implement
|
|
26
|
-
-
|
|
26
|
+
- gate
|
|
27
|
+
- remediate
|
|
27
28
|
- review
|
|
28
|
-
- approve
|
|
29
|
-
- verify
|
|
30
|
-
- record
|
|
31
29
|
- done
|
|
32
30
|
openclaw:
|
|
33
31
|
emoji: "🔄"
|
|
@@ -80,7 +78,7 @@ Full procedure: **[references/planning-workflow.md](references/planning-workflow
|
|
|
80
78
|
|
|
81
79
|
```
|
|
82
80
|
pick task (spur task list --json)
|
|
83
|
-
→ interactive omit/inline:
|
|
81
|
+
→ interactive omit/inline: spur workflow run … executor=host → perform each returned work item
|
|
84
82
|
→ explicit/headless executor: spur workflow run task-pipeline.yaml --vars '{"wbs":"<wbs>"}'
|
|
85
83
|
→ on HITL pause: surface to operator; resume the selected driver from the paused state
|
|
86
84
|
```
|
|
@@ -88,7 +86,7 @@ pick task (spur task list --json)
|
|
|
88
86
|
The pipeline (`kind: state-machine`) runs the work loop:
|
|
89
87
|
|
|
90
88
|
```
|
|
91
|
-
precheck → implement[
|
|
89
|
+
precheck → implement[⇄escalate(HITL)] → gate[⇄remediate] → review → done | failed
|
|
92
90
|
```
|
|
93
91
|
|
|
94
92
|
**Escalation contract (0933).** The implement agent may pause on an operator question: it writes
|
|
@@ -97,6 +95,10 @@ run. Resume with `spur workflow continue --answer-text <answer>` — the guard a
|
|
|
97
95
|
`.spur/run/<wbs>-escalation.md` and re-enters implement (transcript via `--escalation-file`).
|
|
98
96
|
`maxEscalations` (default 2) bounds the loop; exhausted or empty answer → `failed`. Implement only.
|
|
99
97
|
|
|
98
|
+
**Decision points.** Lane, failure class, review failure class and approval are recorded
|
|
99
|
+
`spur decision` answers with deterministic fallbacks, read by the next guard. Report the row; never
|
|
100
|
+
re-judge it: **[references/decision-points.md](references/decision-points.md)**.
|
|
101
|
+
|
|
100
102
|
Full procedure: **[references/execution-workflow.md](references/execution-workflow.md)**.
|
|
101
103
|
Host executor: `spur workflow run` with `executor=host` → work item → `spur workflow continue`.
|
|
102
104
|
|
|
@@ -112,9 +114,6 @@ Read this `SKILL.md` plus your mode's files below before the first dispatch; eve
|
|
|
112
114
|
|
|
113
115
|
`--mode auto` reads as sequential-inline until § 2.4a resolves it.
|
|
114
116
|
|
|
115
|
-
Byte budgets for these sums live in `plugins/sp/tests/bootstrap-budget.test.ts`
|
|
116
|
-
(`BOOTSTRAP_BUDGETS_BYTES`, task 1128); the test fails the build when a mode's bootstrap grows.
|
|
117
|
-
|
|
118
117
|
## Step routing
|
|
119
118
|
|
|
120
119
|
Each step delegates to a CLI verb and is documented in exactly one reference file. Read the
|
|
@@ -133,8 +132,9 @@ reference for the half you're operating; do not duplicate its content here.
|
|
|
133
132
|
| Task selection | execution | `spur task list` | [execution-workflow.md](references/execution-workflow.md) |
|
|
134
133
|
| Pipeline run | execution | `spur workflow run` / `spur workflow continue` | [execution-workflow.md](references/execution-workflow.md) |
|
|
135
134
|
| Implement (dispatch) | execution | `sp:code-implementation` | competency skill — the spine dispatches, does not inline |
|
|
136
|
-
|
|
|
137
|
-
| Review
|
|
135
|
+
| Gate / remediate | execution | `spur task gate` + `sp:dev-fixall` | [execution-workflow.md](references/execution-workflow.md) |
|
|
136
|
+
| Review (dispatch) | execution | `sp:dev-review` → `sp:code-verification` + `sp:functional-review` + `sp:code-improvement` | competency skills — the spine dispatches, does not inline |
|
|
137
|
+
| Decision points | execution | `spur decision status` (+ `show`, `run`) | [decision-points.md](references/decision-points.md) |
|
|
138
138
|
| Operation catalog | execution | `sp:dev-*` operations | [dev-operations.md](references/dev-operations.md) (spine dispatch table) |
|
|
139
139
|
| Continue | execution | `spur feature update` / `refresh` | [execution-workflow.md](references/execution-workflow.md) |
|
|
140
140
|
| Batch run | execution | `sp:super-planner` + `spur workflow run` | [execution-batch.md](references/execution-batch.md) |
|
|
@@ -193,8 +193,8 @@ CLI does.
|
|
|
193
193
|
you ship corrupted corpus.
|
|
194
194
|
2. **One writer per evidence section (F92 0593 R1).** `## Solution` is authored by the
|
|
195
195
|
implement step; `## Review` by the review coordinator (`/sp:dev-review`); `## Testing` by the
|
|
196
|
-
deterministic `record`
|
|
197
|
-
bare — fallback-only, never an overwrite). During execution, do not hand-edit another stage's
|
|
196
|
+
deterministic `spur task record` close in `done` from the verdict artifact (it backfills
|
|
197
|
+
`## Review` only when bare — fallback-only, never an overwrite). During execution, do not hand-edit another stage's
|
|
198
198
|
section.
|
|
199
199
|
3. **Resolve task IDs through the CLI.** Read a known WBS with `spur task show <wbs> --json`; it
|
|
200
200
|
returns metadata, full content, and `filePath` across configured task folders. Use `spur task
|
|
@@ -226,7 +226,7 @@ section adds per-file content summaries and items with no single step (glossary,
|
|
|
226
226
|
five gates (feature-check, batch-create, precheck, review, verify).
|
|
227
227
|
- [references/section-batching.md](references/section-batching.md) — the evidence-section
|
|
228
228
|
**one-writer protocol** (F92 0593 R1/R2): implement owns `Solution`, the review coordinator owns
|
|
229
|
-
`Review`, deterministic `record` owns `Testing`; skills query `spur task sections` /
|
|
229
|
+
`Review`, the deterministic `spur task record` close owns `Testing`; skills query `spur task sections` /
|
|
230
230
|
`spur task check` instead of static section tables.
|
|
231
231
|
- [references/ac-style-guide.md](references/ac-style-guide.md) — BDD scenario authoring:
|
|
232
232
|
R-numbering, the two AC tiers, scenario-title stability, Gherkin template usage.
|
|
@@ -181,14 +181,14 @@ spawned step resolves to `agent.default` (step 2) or the YAML literal (step 3).
|
|
|
181
181
|
|
|
182
182
|
`task-pipeline.yaml` declares a separate `implementAgent` var. The `implement` state's `agent.run`
|
|
183
183
|
step reads `${vars.implementAgent}` instead of `${vars.agent}`, so an operator can pin the
|
|
184
|
-
implement hop to one executor while review
|
|
184
|
+
implement hop to one executor while the remediate and review hops keep the default agent:
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
187
|
# Pin implement to a specific executor; other hops keep agent.default / YAML literal
|
|
188
188
|
--vars '{"implementAgent":"omp-zai"}'
|
|
189
189
|
```
|
|
190
190
|
|
|
191
|
-
All other `agent.run` steps (
|
|
191
|
+
All other `agent.run` steps (remediate, review) read `${vars.agent}`. `implementAgent`
|
|
192
192
|
applies **only** to the implement hop. **The `--agent` flag forwards into BOTH `agent` and
|
|
193
193
|
`implementAgent`** at the execution-batch boundary (§3.2), so a pinned `--agent X` reaches every
|
|
194
194
|
hop including implement. To pin ONLY implement to a different executor while other hops keep the
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decision-points
|
|
3
|
+
description: "The lifecycle's catalog decision points: which workflow state asks which `spur decision` id, its fallback, the row it writes and the guard that reads it — plus the rules for consuming, diagnosing and adding one."
|
|
4
|
+
see_also:
|
|
5
|
+
- spur-dev
|
|
6
|
+
- execution-workflow
|
|
7
|
+
- spur-cli
|
|
8
|
+
- spur-composer
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Decision points
|
|
12
|
+
|
|
13
|
+
A **decision point** is a closed-vocabulary judgment the workflow asks through `spur decision`
|
|
14
|
+
instead of through an agent's prose. It names a catalog id, carries a deterministic fallback, and
|
|
15
|
+
writes a schemaVersion-1 row (`value`, `source: model|default`, `degraded`, `confidence`,
|
|
16
|
+
`confidenceLevel`, `reason`) that the next guard or projection reads. The verb catalog, maker
|
|
17
|
+
resolution and the authoring lifecycle live in `sp:spur-cli`
|
|
18
|
+
([decision.md](../../spur-cli/references/decision.md),
|
|
19
|
+
[decision/lifecycle.md](../../spur-cli/references/decision/lifecycle.md)); this file is the
|
|
20
|
+
lifecycle's map of where each one sits.
|
|
21
|
+
|
|
22
|
+
## Inventory
|
|
23
|
+
|
|
24
|
+
| Workflow · state | Decision id | Values (fallback) | Row | Consumer |
|
|
25
|
+
| --- | --- | --- | --- | --- |
|
|
26
|
+
| task-pipeline · `gate` | `task-triage` | low · standard · high (`standard`) | `.spur/run/<wbs>-triage.decision` | lane projection → `<wbs>-mode.txt` → review focus. Runs only after the deterministic floor (caller `mode`, sensitive path, > 400 lines) has not already pinned the lane |
|
|
27
|
+
| task-pipeline · `gate` | `failure-class` | fix · stop (`fix`) | `.spur/run/<wbs>-failure-class.decision` | red gate: `stop` → `failed`, `fix` → `remediate` (under the attempt cap) |
|
|
28
|
+
| task-pipeline · `review` | `review-failure-class` | fix · stop (`fix`) | `.spur/run/<wbs>-review-failure-class.decision` | non-PASS review: `stop` → `failed`, `fix` → `remediate` (same cap) |
|
|
29
|
+
| task-pipeline · `review` | `gate-evidence` (approval `hitl.confirm`) | yes · no · defer (`defer`) | `.spur/run/<wbs>-approval.status` (APPROVED · DENIED) | `done` requires APPROVED; DENIED → `failed` (`cancelled`) |
|
|
30
|
+
| idea-pipeline · discovery | `idea-recommendation` | proceed · reshape · drop · unknown (`unknown`) | `.spur/run/<runId>-idea-recommendation.decision` | rescue only: consulted when the awk parse says `unknown`; only a `source: model` answer is projected |
|
|
31
|
+
| idea-pipeline · discovery | `needs-design` | design · skip (`design`) | `.spur/run/<runId>-idea-needs-design.decision` | rescue only: used when the report's boolean is missing; anything but a model `skip` keeps `design` |
|
|
32
|
+
| idea-pipeline · `idea-eval`, `design-approval` | `gate-evidence` | yes · no · defer (`defer`) | `__hitlAnswer` → `<runId>-idea-eval-answer.txt` etc. | a deferred answer is a denial there |
|
|
33
|
+
| wrapup-pipeline · `branch-cleanup` | `gate-evidence` | yes · no · defer (`defer`) | `branchCleanupStatus` | consent record only; wrap-up performs no git operation |
|
|
34
|
+
| history-anatomy · validate | `anatomy-validation-verdict` | PASS · FAIL (`FAIL`) | shell `spur decision run` (not a `decide` row) | rescue for an unparseable validation verdict; a deterministic FAIL is never overturned |
|
|
35
|
+
|
|
36
|
+
`maker-liveness` is served only by `spur decision status --probe`. `spur decision list --json` is
|
|
37
|
+
the live inventory; when it and this table disagree, the CLI wins and this table is stale.
|
|
38
|
+
|
|
39
|
+
## Switches
|
|
40
|
+
|
|
41
|
+
- **`workflows.decideDecisionMaker`** (default off) gates every `decide` action. Off, the action
|
|
42
|
+
makes no model call and writes the fallback row (`source: default`). The pipeline still routes:
|
|
43
|
+
a red gate is `fix` and goes to the bounded repair, the lane is `standard`.
|
|
44
|
+
- **`workflows.hitlDecisionMaker`** (default off) gates the evidence-mode HITL gates. Off,
|
|
45
|
+
interactive gates ask the operator; under `profile=auto` the gate's answer is deferred, which
|
|
46
|
+
task-pipeline treats as no objection and idea-pipeline treats as a denial.
|
|
47
|
+
- **`spur decision run` ignores both switches.** A workflow that shells out to it calls a model
|
|
48
|
+
even with the switches off. That is why the typed `decide` action is the preferred form.
|
|
49
|
+
|
|
50
|
+
## Rules for the lifecycle
|
|
51
|
+
|
|
52
|
+
1. **Read the row; never re-judge it.** When a run reports `failed`, `remediate` or a lane, the
|
|
53
|
+
reason is the recorded `.decision` row or the approval token. Quote its `value`, `source` and
|
|
54
|
+
`reason`. Do not overrule a `stop` by hand-driving `remediate`, and do not treat a `source:
|
|
55
|
+
default` row as a model verdict.
|
|
56
|
+
2. **A fallback row is a real outcome.** `source: default` (switch off, `no-backend`, low
|
|
57
|
+
confidence, invalid answer) is what the run acted on. Report it as degraded, not as an error.
|
|
58
|
+
3. **Outside a pipeline, ask the catalog.** For a question a catalog id already owns (is this
|
|
59
|
+
red gate fixable? which lane does this diff need?), run `spur decision show <id>` and then
|
|
60
|
+
`spur decision run <id> --param … --evidence … --json` instead of improvising an answer. Never
|
|
61
|
+
let a `spur decision run` answer substitute for a gate the workflow owns.
|
|
62
|
+
4. **Recurring judgment → a decision point, not prose.** A judgment that has a closed set of
|
|
63
|
+
answers and a safe default, recurs across runs, and currently lives in an agent prompt or a
|
|
64
|
+
`case` over free text belongs in a catalog entry plus a `decide` step. Author it through the
|
|
65
|
+
decision lifecycle (decision/lifecycle.md) and `sp:spur-composer`. A new shared catalog id
|
|
66
|
+
needs recorded operator consent (composition ladder §7) and `build:bundle`.
|
|
67
|
+
5. **Keep deterministic floors first.** A decision point rescues or refines a deterministic
|
|
68
|
+
check; it never replaces one. task-triage runs after the sensitive-path/size floor, and the
|
|
69
|
+
idea-pipeline decides run after the parse they rescue.
|
|
70
|
+
|
|
71
|
+
## Reporting a run
|
|
72
|
+
|
|
73
|
+
After a task-pipeline run settles, `/sp:dev-run`, `/sp:dev-runall` and `sp:super-planner` report
|
|
74
|
+
its decision points under the execution summary, one line per row, plus the approval token:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
for f in .spur/run/<wbs>-{triage,failure-class,review-failure-class}.decision; do
|
|
78
|
+
[ -f "$f" ] && jq -r --arg f "${f##*/}" '"\($f): \(.value) — \(.source // (if .degraded then "default" else "model" end)) \(.backend // "-") \(.reason)"' "$f"
|
|
79
|
+
done
|
|
80
|
+
printf 'approval: %s\n' "$(cat .spur/run/<wbs>-approval.status 2>/dev/null || echo none)"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Rows outlive their run: a row's presence does not prove this run reached that state (the run's
|
|
84
|
+
trace does). Rows written before `source` existed carry only `degraded`; the fallback above reads it.
|
|
85
|
+
|
|
86
|
+
## Diagnosis
|
|
87
|
+
|
|
88
|
+
| Question | Evidence |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| Why did this run take that route? | The row file in the table above; `spur workflow trace <run-id> --json` |
|
|
91
|
+
| Is a maker serving at all? | `spur decision status --probe` |
|
|
92
|
+
| How reliable is a decision in practice? | `spur decision status --reliability [--since <date>] --json` — per decision × maker: samples, acceptedRate, fallbacks by reason, median confidence, p50/p95 latency |
|
|
93
|
+
| Which runs asked it? | Board → Decisions tab (`decision_logs`) |
|
|
94
|
+
| Is the catalog healthy? | `spur decision status --json` → `loadErrors`, `makers[]` |
|
|
95
|
+
|
|
96
|
+
A decision whose rows are almost all `source: default` while its switch is on has a maker
|
|
97
|
+
problem, not a workflow problem. Hand it to `sp:spur-doctor`, which owns the proposal.
|