@gobing-ai/spur 0.4.31 → 0.4.34
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 +1 -4
- package/config/decisions/task-pipeline.yaml +1 -29
- package/config/rules/boundary/sp-runtime-path.yaml +0 -2
- package/config/rules/strict/runtime-boundaries.yaml +2 -12
- package/config/rules/structure/protected-files.yaml +0 -3
- package/config/rules/surface/check-cli-surface.yaml +1 -2
- package/config/workflow-candidates.json +1 -1
- package/config/workflows/idea-pipeline.yaml +1 -1
- package/config/workflows/task-pipeline.yaml +53 -185
- package/package.json +1 -1
- package/plugins/sp/agents/super-reviewer.md +18 -60
- package/plugins/sp/commands/dev-fixall.md +0 -7
- package/plugins/sp/commands/dev-review.md +1 -1
- package/plugins/sp/commands/dev-run.md +8 -3
- package/plugins/sp/commands/dev-runall.md +7 -4
- package/plugins/sp/commands/dev-verify.md +0 -10
- package/plugins/sp/commands/dev-verifyall.md +0 -5
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/skills/code-implementation/SKILL.md +1 -3
- package/plugins/sp/skills/code-verification/SKILL.md +11 -41
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +18 -119
- package/plugins/sp/skills/issue-finding/SKILL.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +0 -7
- package/plugins/sp/skills/spec-decomposition/references/decomposition.md +1 -6
- package/plugins/sp/skills/spur-cli/references/decision.md +3 -6
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +0 -28
- package/plugins/sp/skills/spur-cli/references/tasks.md +9 -7
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +5 -12
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +2 -3
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +4 -4
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +4 -5
- package/plugins/sp/skills/spur-dev/references/execution-batch-report.md +9 -5
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +4 -5
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +1 -1
- package/plugins/sp/skills/spur-dev/references/execution-worktree-landing.md +34 -0
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +14 -1
- package/spur.js +1437 -4409
- package/web/_astro/{BoardApp.CuCuw0lw.js → BoardApp.BzY_krKQ.js} +1 -1
- package/web/_astro/{BoardApp.BGGDrfHl.js → BoardApp.CIImQFjG.js} +3 -3
- package/web/_astro/{TaskDetail.DWXct9_X.js → TaskDetail.c48Pnba6.js} +1 -1
- package/web/_astro/{arc.BxG3NS1o.js → arc.CpU6Cddr.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.BxaiM2Hv.js → architectureDiagram-3BPJPVTR.CaXT9ZEz.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.DJ3r6SdD.js → blockDiagram-GPEHLZMM.Cnv3IsW9.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.BkzpXBQs.js → c4Diagram-AAUBKEIU.VO_hjv9n.js} +1 -1
- package/web/_astro/channel.DrtdR7d_.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.DI7UanTc.js → chunk-2J33WTMH.BOunhbrU.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.C2uLhAlQ.js → chunk-4BX2VUAB.Brg-Gmb2.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.KwNI2kxL.js → chunk-55IACEB6.BqF9dxiC.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.CHZUthkg.js → chunk-727SXJPM.CEIGJZdc.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.DLr4QNJo.js → chunk-AQP2D5EJ.BxXI0bx9.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.B1G8WrnE.js → chunk-FMBD7UC4.CveXCF83.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.CzsA-SkD.js → chunk-ND2GUHAM.DwKjp403.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.DAvBQYli.js → chunk-QZHKN3VN.DgwjHrXx.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.Cddmz8Ze.js → classDiagram-4FO5ZUOK.BcVv8Qmo.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.Cddmz8Ze.js → classDiagram-v2-Q7XG4LA2.BcVv8Qmo.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.CKEu7KRX.js → cose-bilkent-S5V4N54A.28xfMBER.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.-B4Cy_Vl.js → cynefin-OW5HDTMX.BAFHBcJj.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.bLxFvI-t.js → dagre-BM42HDAG.DzR6wa9Z.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.DAHU0t5h.js → diagram-2AECGRRQ.IpFlr4yd.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.DFciwCNk.js → diagram-5GNKFQAL.DGNU2pOL.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.BvH0dGId.js → diagram-KO2AKTUF.D_wP6t4w.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.BgVlskRO.js → diagram-LMA3HP47.B0DMC97s.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.BpurMISo.js → diagram-OG6HWLK6.DQXmNEBs.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.SDj5bUMU.js → erDiagram-TEJ5UH35.BZ0VPjjp.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.Bm5U58FE.js → flowDiagram-I6XJVG4X.zu5gJs9Z.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.CnMnds77.js → ganttDiagram-6RSMTGT7.DYy6LDqD.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.BQUwwyWo.js → gitGraphDiagram-PVQCEYII.C6c_wPdO.js} +1 -1
- package/web/_astro/index.C4tUn4AU.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.BiSKdORH.js → infoDiagram-5YYISTIA.C3bQPQl8.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.Br69sBTI.js → ishikawaDiagram-YF4QCWOH.Cc1D58oG.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.C39WX1W8.js → journeyDiagram-JHISSGLW.CY51-lNM.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.DppWcbSX.js → kanban-definition-UN3LZRKU.D_3v92y6.js} +1 -1
- package/web/_astro/{linear.DeivTDuc.js → linear.C6BrJ38s.js} +1 -1
- package/web/_astro/{mermaid.core.Dixrjrnj.js → mermaid.core.DO9lF20B.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.BWIQ2MWG.js → mindmap-definition-RKZ34NQL.BMiM91P6.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.vvtHpfT7.js → pieDiagram-4H26LBE5.CcgIgRlR.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.9c-T6qCy.js → quadrantDiagram-W4KKPZXB.CM1CzrHl.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.9ZuRw-kn.js → requirementDiagram-4Y6WPE33.CQvQ1E8r.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.CTIWteEl.js → sankeyDiagram-5OEKKPKP.D-b1ONCV.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.DEvu4vLL.js → sequenceDiagram-3UESZ5HK.BQzFGYtH.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.Bxvsgk-_.js → stateDiagram-AJRCARHV.DiCukZ7I.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CVuog5yY.js → stateDiagram-v2-BHNVJYJU.4Iut-DMk.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.CpPItB3E.js → timeline-definition-PNZ67QCA.BKQiLF24.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.C7eKaLRK.js → vennDiagram-CIIHVFJN.CyeSCofx.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.DWXHT_CW.js → wardleyDiagram-YWT4CUSO.B140ei48.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.DOsrNQOF.js → xychartDiagram-2RQKCTM6.DjPyVoO1.js} +1 -1
- package/web/index.html +2 -2
- package/config/rules/structure/scratch-evidence-pointer.yaml +0 -35
- package/web/_astro/channel.CYWRkoDI.js +0 -1
- package/web/_astro/index.CKtaGArK.css +0 -1
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
# captures and compares, digest-bound receipt preconditions, `run.artifact` verdict
|
|
26
26
|
# registration and the `verifiedOutcome` it fed — is gone; a PASS receipt is reused while
|
|
27
27
|
# the tree hash holds and invalidated when the tree moves. `done` closes on the verb's own
|
|
28
|
-
# target-aware `task check
|
|
28
|
+
# target-aware `task check`, not on a re-asserted digest.
|
|
29
29
|
#
|
|
30
30
|
# No operator pause lives in this file (D65 R10): the only pause is the host executor's
|
|
31
31
|
# `agent.run` transform (1232). `escalate` asks its question through the responder and the
|
|
@@ -131,9 +131,9 @@ vars:
|
|
|
131
131
|
# Project quality gate for the `gate` hop, overridable per project:
|
|
132
132
|
# `--vars '{"qualityGateCmd":"bun run lint && bun run test"}'`.
|
|
133
133
|
# INVARIANT (ADR-124, clarified 2026-10-07 by task 1111 R5): only the FULL tier writes PASS.
|
|
134
|
-
# Under the
|
|
135
|
-
# the "
|
|
136
|
-
# reported PASS without the
|
|
134
|
+
# Under the default incremental policy (`deferQualityGate`) the per-task token is DEFERRED and
|
|
135
|
+
# the "green full gate" invariant lives at FEATURE/BATCH scope (`spur feature verify`, the
|
|
136
|
+
# batch integration gate) — nothing is reported PASS without the full gate.
|
|
137
137
|
# TRUSTED CONFIG ONLY — `spur task gate` passes this to the project's gate command. Never
|
|
138
138
|
# interpolate untrusted operator/LLM input into qualityGateCmd (task 0436 SECUA residual).
|
|
139
139
|
# The gate observes, it does not mutate: `implement` already ran `$formatCmd` on its way out,
|
|
@@ -172,19 +172,15 @@ vars:
|
|
|
172
172
|
# anchors directly in the /sp:dev-fixall input, so the fix agent starts AT the failing
|
|
173
173
|
# file:line instead of re-deriving it from a fresh gate run (0482 R3).
|
|
174
174
|
gateFindings: ""
|
|
175
|
-
# 1319 R5: lint findings from the previous review visit, echoed into the review prompt on the
|
|
176
|
-
# inline retry. Empty on the happy path, so the prompt pays nothing when nothing is wrong.
|
|
177
|
-
reviewLint: ""
|
|
178
175
|
# The quality-gate mode this visit runs — `run` on the first gate visit of the run,
|
|
179
176
|
# `recheck` after a remediation hop, `deferred` under the opt-in batch policy. Written by
|
|
180
177
|
# the gate's own shell and projected into this var (args cannot branch) — D65 1239 R2.
|
|
181
178
|
gateMode: ""
|
|
182
|
-
# Review depth resolved from the lane
|
|
179
|
+
# Review depth resolved from the diffstat lane (0943 R1/R2): `functional` for the fast
|
|
183
180
|
# lane (requirement/AC traceability only — the reviewer's R → file:line table is what
|
|
184
181
|
# certifies, so the fast lane never drops the evidence), `all` for every other lane.
|
|
185
182
|
reviewFocus: ""
|
|
186
|
-
# Task spec path resolved at `gate` entry
|
|
187
|
-
# routing). `docs/tasks*` is a versioned input, not a run artifact.
|
|
183
|
+
# Task spec path resolved at `gate` entry. `docs/tasks*` is a versioned input, not a run artifact.
|
|
188
184
|
taskSpecPath: ""
|
|
189
185
|
# 0710 R4: task priority tier (P0..P4) extracted from the task frontmatter at `gate`
|
|
190
186
|
# entry. P0/P1 make the review distinct-executor policy apply; unknown/empty priority
|
|
@@ -196,13 +192,14 @@ vars:
|
|
|
196
192
|
# (default) = on; set to "off" to bypass:
|
|
197
193
|
# `--vars '{"implementScopeGuard":"off"}'`.
|
|
198
194
|
implementScopeGuard: ""
|
|
199
|
-
#
|
|
200
|
-
#
|
|
201
|
-
# `.spur/run/<wbs>-test-gate.status` —
|
|
202
|
-
# project gate ran green on this tree. The
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
deferQualityGate:
|
|
195
|
+
# Gate mode. "true" (default) = INCREMENTAL: `gate` runs lint, rules, typecheck of the touched
|
|
196
|
+
# workspaces and their dependents, the related tests, and the per-file coverage floor on the
|
|
197
|
+
# changed files, then writes `DEFERRED` or `FAIL` to `.spur/run/<wbs>-test-gate.status` —
|
|
198
|
+
# never `PASS`, because that token means the full project gate ran green on this tree. The
|
|
199
|
+
# full gate runs once per feature (`spur feature verify`) or batch (integration gate).
|
|
200
|
+
# "false" = FULL: every task pays the whole project gate; a stray `DEFERRED` fails the guards.
|
|
201
|
+
# `--vars '{"deferQualityGate":"false"}'`.
|
|
202
|
+
deferQualityGate: "true"
|
|
206
203
|
# 0931 R5: parallel batches defer the per-task feature sync so a task branch never
|
|
207
204
|
# touches feature files or docs/features/INDEX.md. When "true", the close's post-record
|
|
208
205
|
# shell appends a deferral note and skips the sync; the parallel batch orchestrator runs
|
|
@@ -222,8 +219,7 @@ states:
|
|
|
222
219
|
onEnter:
|
|
223
220
|
# (e) git-status hygiene advisory; never fails the run (0487 R6 / 0511 R1). 1007 R3:
|
|
224
221
|
# the F96 base-sha capture (0950) merged into this shell — original commands in order,
|
|
225
|
-
# then the one-time base commit capture; a resumed run keeps its original base
|
|
226
|
-
# residual scans stay anchored to the same diff.
|
|
222
|
+
# then the one-time base commit capture; a resumed run keeps its original base.
|
|
227
223
|
- kind: shell
|
|
228
224
|
options:
|
|
229
225
|
command: >-
|
|
@@ -357,15 +353,6 @@ states:
|
|
|
357
353
|
resultFile: .spur/run/${vars.__runId}-implement-format.status
|
|
358
354
|
softFail: true
|
|
359
355
|
timeoutMs: "${vars.stepTimeoutMs}"
|
|
360
|
-
# 1109 R3: qualify this task's unique basename anchors to repo-relative paths.
|
|
361
|
-
# Placement is load-bearing: it runs AFTER implement's mutations (and the format
|
|
362
|
-
# above) and BEFORE the gate reads the tree, so the receipt is keyed to the final
|
|
363
|
-
# tree. `--wbs` scopes the pass to this task's resolved file.
|
|
364
|
-
# Non-fatal (`; exit 0`): the done gate still reports anything left. Scope
|
|
365
|
-
# contract: task 1109 R5.
|
|
366
|
-
- kind: shell
|
|
367
|
-
options:
|
|
368
|
-
command: "$spurBin task migrate-anchors --wbs $wbs --json ; exit 0"
|
|
369
356
|
|
|
370
357
|
# ── escalate hop (operator-question pause, 0933) ──────────────────────────
|
|
371
358
|
# The implement agent paused on an operator question: it wrote
|
|
@@ -417,11 +404,10 @@ states:
|
|
|
417
404
|
# attempt counter and consults the tree-hash receipt), `recheck` after a remediation hop
|
|
418
405
|
# (probe-then-full), `deferred` under the opt-in batch policy.
|
|
419
406
|
#
|
|
420
|
-
# The
|
|
421
|
-
#
|
|
422
|
-
#
|
|
423
|
-
#
|
|
424
|
-
# their catalog fallback with no model call while `workflows.decideDecisionMaker` is off.
|
|
407
|
+
# The review lane is resolved deterministically from the diffstat (no model call); the
|
|
408
|
+
# gate's own failure class (catalog `failure-class`) drives the red-gate transitions and
|
|
409
|
+
# degrades to its catalog fallback with no model call while
|
|
410
|
+
# `workflows.decideDecisionMaker` is off.
|
|
425
411
|
- id: gate
|
|
426
412
|
display:
|
|
427
413
|
phase: test
|
|
@@ -429,15 +415,14 @@ states:
|
|
|
429
415
|
title: Run quality gate
|
|
430
416
|
description: >
|
|
431
417
|
Typed quality gate: resolve the task path/priority, produce the diffstat lane
|
|
432
|
-
evidence,
|
|
433
|
-
first), run `${vars.qualityGateCmd}` through `spur task gate <wbs> <mode>` under the
|
|
418
|
+
evidence, resolve the review depth from it deterministically, run `${vars.qualityGateCmd}` through `spur task gate <wbs> <mode>` under the
|
|
434
419
|
host-wide lock (tree-hash receipt reuse on the same tree), then classify a red gate
|
|
435
420
|
through `failure-class`. Writes the typed outcome to
|
|
436
421
|
`.spur/run/<runId>-gate.status` and the gate's own token to
|
|
437
422
|
`.spur/run/<wbs>-test-gate.status`; always a recorded outcome, never a state failure.
|
|
438
423
|
onEnter:
|
|
439
424
|
# (e) task path + priority resolution; fail-closed on an unresolvable spec (0751 R2,
|
|
440
|
-
# 0710 R4). The path is the
|
|
425
|
+
# 0710 R4). The path is the review's task spec and the priority is
|
|
441
426
|
# the review/executor distinctness input (0710 R4) — both are consumed downstream, so
|
|
442
427
|
# an unresolved path fails here instead of degrading the run silently.
|
|
443
428
|
- kind: shell
|
|
@@ -459,39 +444,19 @@ states:
|
|
|
459
444
|
options:
|
|
460
445
|
command: >-
|
|
461
446
|
$spurBin task diffstat "$wbs" --no-logo || { echo "task-diffstat failed closed — spur task diffstat exited $?" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; }; exit 0
|
|
462
|
-
# (b)+(c) lane
|
|
463
|
-
#
|
|
464
|
-
#
|
|
465
|
-
#
|
|
466
|
-
# the "never to fast" fail-safe is enforced at the guard, not by the projection.
|
|
447
|
+
# (b)+(c) deterministic lane: a caller-set mode is projected verbatim (R2b); a
|
|
448
|
+
# sensitive path or >400 changed lines pins safety (R2c); a change set touching only
|
|
449
|
+
# docs and tests takes the fast lane; everything else stays empty → standard review.
|
|
450
|
+
# A missing/malformed diffstat row pins safety — never fast. No model call.
|
|
467
451
|
- kind: shell
|
|
468
452
|
options:
|
|
469
453
|
command: >-
|
|
470
|
-
mkdir -p .spur/run; if [ -n "$mode" ]; then printf '%s\n' "$mode" > ".spur/run/$wbs-mode.txt"; exit 0; fi; DF=".spur/run/$wbs-diffstat.json"; if ! jq -e 'type == "object"' "$DF" >/dev/null 2>&1; then printf 'safety\n' > ".spur/run/$wbs-mode.txt"; exit 0; fi; jq -r 'if .sensitive == true or ((.insertions // 0) + (.deletions // 0)) > 400 then "safety" else empty end' "$DF" 2>/dev/null > ".spur/run/$wbs-mode.txt"; exit 0
|
|
471
|
-
# (d)
|
|
472
|
-
# behaviour beyond its diffstat? `false` projects the fast lane; `true` or the catalog
|
|
473
|
-
# fallback projects standard. Degrades to that fallback with no model call whenever
|
|
474
|
-
# workflows.decideDecisionMaker is off (the bundled catalog owns question, criteria and
|
|
475
|
-
# fallback), and `skipWhenEvidenceEmpty` keeps a missing diffstat from costing a call.
|
|
476
|
-
- kind: decide
|
|
477
|
-
options:
|
|
478
|
-
id: task-semantic-risk
|
|
479
|
-
decision: task-semantic-risk
|
|
480
|
-
params:
|
|
481
|
-
wbs: ${vars.wbs}
|
|
482
|
-
evidence:
|
|
483
|
-
- .spur/run/${vars.wbs}-diffstat.json
|
|
484
|
-
- ${vars.taskSpecPath}
|
|
485
|
-
skipWhenEvidenceEmpty: true
|
|
486
|
-
resultFile: .spur/run/${vars.wbs}-semantic-risk.decision
|
|
487
|
-
# (d) project the decision and append the route reason (1007 R3: the non-empty mode
|
|
488
|
-
# file is never overridden; the append keeps the failure signal of the original pair).
|
|
489
|
-
# `no` (a noul row stores the label, not a boolean) → fast lane; anything else (`yes`,
|
|
490
|
-
# degraded default, missing row) stays empty → the standard review path.
|
|
454
|
+
mkdir -p .spur/run; if [ -n "$mode" ]; then printf '%s\n' "$mode" > ".spur/run/$wbs-mode.txt"; exit 0; fi; DF=".spur/run/$wbs-diffstat.json"; if ! jq -e 'type == "object"' "$DF" >/dev/null 2>&1; then printf 'safety\n' > ".spur/run/$wbs-mode.txt"; exit 0; fi; jq -r 'if .sensitive == true or ((.insertions // 0) + (.deletions // 0)) > 400 then "safety" elif ((.paths // []) | length) > 0 and ((.paths // []) | all(test("[.](md|mdx|txt)$|(^|/)tests?/|[.](test|spec)[.][cm]?[jt]sx?$"))) then "fast" else empty end' "$DF" 2>/dev/null > ".spur/run/$wbs-mode.txt"; exit 0
|
|
455
|
+
# (d) append the route reason for the resolved lane.
|
|
491
456
|
- kind: shell
|
|
492
457
|
options:
|
|
493
458
|
command: >-
|
|
494
|
-
|
|
459
|
+
m="$(cat ".spur/run/$wbs-mode.txt" 2>/dev/null)"; RUN_ID="$__runId"; [ -n "$RUN_ID" ] || RUN_ID="pipeline-$wbs"; mkdir -p .spur/memory; printf '%s %s %s\n' "$RUN_ID" "$wbs" "$(jq -rn --arg m "$m" --arg c "$mode" 'if $c != "" then ($c + ":caller-set") else {"fast":"fast:docs/tests-only change","safety":"safety:deterministic-high","":"safety:standard lane"}[$m] // "safety:unrecognized mode" end')" >> .spur/memory/task-pipeline-routes.log
|
|
495
460
|
# (d) review depth from the resolved lane (D65 1239 R2): the fast lane reviews the
|
|
496
461
|
# requirement/AC traceability only — that table is the certification input, so the
|
|
497
462
|
# cheap lane never drops the evidence, it drops the SECUA/architecture passes.
|
|
@@ -593,14 +558,11 @@ states:
|
|
|
593
558
|
options:
|
|
594
559
|
command: >-
|
|
595
560
|
TASK_POLICY=$($spurBin task show "$wbs" --json | jq -er '.frontmatter.mutationPolicy // ([.content | scan("(?m)^mutationPolicy:[ \t]*([^ \r\n]+)[ \t]*$") | .[0]] | if length == 0 then "code" elif length == 1 then .[0] else "ambiguous" end)') || exit 1; [ "$mutationPolicy:$TASK_POLICY" = "code:code" ] || { echo "remediate: mutation policy forbids automatic code repair (run=$mutationPolicy, task=$TASK_POLICY) — gate failure preserved, no agent dispatched" >&2; exit 1; }
|
|
596
|
-
# (e) attempt counter
|
|
597
|
-
# (1007 R3: the two appends merged — original commands in order, exit 0).
|
|
598
|
-
# (d) F96 R3 (0950): dev-fixall treats residual items as fix targets and may defer
|
|
599
|
-
# P3/markers to residual-deferrals.json; this carries the structured artifact too.
|
|
561
|
+
# (e) attempt counter.
|
|
600
562
|
- kind: shell
|
|
601
563
|
options:
|
|
602
564
|
command: >-
|
|
603
|
-
printf '%s\n' "$(( $(cat ".spur/run/$wbs-test-fix-attempt" 2>/dev/null || echo 0) + 1 ))" > ".spur/run/$wbs-test-fix-attempt";
|
|
565
|
+
printf '%s\n' "$(( $(cat ".spur/run/$wbs-test-fix-attempt" 2>/dev/null || echo 0) + 1 ))" > ".spur/run/$wbs-test-fix-attempt"; exit 0
|
|
604
566
|
# Review-lane input: a non-PASS review status routes into this same bounded repair hop
|
|
605
567
|
# (1262 R6), but it stages no gate evidence — the fixer would receive a GREEN gate log
|
|
606
568
|
# and an empty findings list. Project the reviewer's answer into the same log the other
|
|
@@ -645,11 +607,10 @@ states:
|
|
|
645
607
|
# D65 1239 R2: `verify` merged into `review`. The reviewer's answer must carry the
|
|
646
608
|
# requirement/AC traceability table (`| Req | Status | Evidence |`, evidence = `file:line`
|
|
647
609
|
# or a named test/command) — sp:functional-review produces it and the answer contract owns
|
|
648
|
-
# the shape. `spur task verdict --from-answer`
|
|
610
|
+
# the shape. `spur task verdict --from-answer` derives PASS/PARTIAL/FAIL
|
|
649
611
|
# from the rows and writes the canonical `.spur/run/<wbs>-verdict.json` that `spur task
|
|
650
612
|
# record` consumes for box flips and `## Testing`; a review whose rows do not resolve (an
|
|
651
|
-
# UNMET requirement, a missing row, a bad AC identity) cannot derive PASS.
|
|
652
|
-
# residual check (1122) still blocks an open P1-P3 finding. Everything is folded into one
|
|
613
|
+
# UNMET requirement, a missing row, a bad AC identity) cannot derive PASS. Everything is folded into one
|
|
653
614
|
# status token the transitions read, so a non-PASS review routes into the bounded repair
|
|
654
615
|
# hop BEFORE `done` spends the close.
|
|
655
616
|
- id: review
|
|
@@ -661,22 +622,8 @@ states:
|
|
|
661
622
|
Three-dimensional code review via /sp:dev-review (functional requirements traceability
|
|
662
623
|
+ SECUA framework + architecture depth), findings written to `## Review`, then
|
|
663
624
|
deterministic certification: `spur task verdict --from-answer` over the reviewer's
|
|
664
|
-
own traceability table,
|
|
665
|
-
approval decision point. Cost at this decision point (1122): open P1-P3 review
|
|
666
|
-
findings block `done`; only P4 rows and DEFER-ed P3 rows are wrap residuals.
|
|
625
|
+
own traceability table, and the operator/maker approval decision point.
|
|
667
626
|
onEnter:
|
|
668
|
-
# 1319 R5(b)/Q9: surface the previous visit's verdict-lint findings for THIS visit's prompt.
|
|
669
|
-
# Empty on the first visit (and after a clean lint), capped so the prompt stays inside its
|
|
670
|
-
# composition budget, and it names the declared R/AC ids because the lint already does.
|
|
671
|
-
- kind: shell
|
|
672
|
-
options:
|
|
673
|
-
command: >-
|
|
674
|
-
mkdir -p .spur/run; L=".spur/run/$wbs-verdict-lint.txt"; O=".spur/run/$__runId-review-lint.txt";
|
|
675
|
-
if [ -s "$L" ]; then head -c 600 "$L" > "$O"; else : > "$O"; fi; exit 0
|
|
676
|
-
- kind: file.read.into-var
|
|
677
|
-
options:
|
|
678
|
-
path: .spur/run/${vars.__runId}-review-lint.txt
|
|
679
|
-
var: reviewLint
|
|
680
627
|
- kind: agent.run
|
|
681
628
|
options:
|
|
682
629
|
# 0710 R2: review always runs on a fresh session — no implementation-session
|
|
@@ -693,19 +640,12 @@ states:
|
|
|
693
640
|
# of the prompt. A report body ending with a `| WBS | Verdict | P1 | … |` summary and
|
|
694
641
|
# no per-requirement rows derives UNKNOWN and can never certify, which looped every
|
|
695
642
|
# run through review -> remediate.
|
|
696
|
-
#
|
|
697
|
-
#
|
|
698
|
-
#
|
|
699
|
-
# lanes and the fact that a single `Confidence:` line may only carry the second one.
|
|
700
|
-
# 1254: the prompt stays inside the 1000-char composition cap — the full
|
|
701
|
-
# contract (tables, vocabularies, the two confidence lanes, AC identity vs
|
|
702
|
-
# feature credit) is owned by `plugins/sp/agents/super-reviewer.md` Output Format,
|
|
703
|
-
# which this pointer names.
|
|
643
|
+
# The prompt stays inside the 1000-char composition cap — the full contract
|
|
644
|
+
# (tables, vocabularies) is owned by `plugins/sp/agents/super-reviewer.md`
|
|
645
|
+
# Output Format, which this pointer names.
|
|
704
646
|
input: >-
|
|
705
647
|
/sp:dev-review --tasks ${vars.wbs} --auto --focus ${vars.reviewFocus}
|
|
706
|
-
Answer contract: super-reviewer Output Format. Emit the
|
|
707
|
-
`## Review`: deriveReviewConfidence. Captured answer (`spur task verdict`) has one `Confidence: HIGH|MEDIUM|LOW`
|
|
708
|
-
line (deriveVerifyConfidence), never the section's disposition level.
|
|
648
|
+
Answer contract: super-reviewer Output Format. Emit the verdict tables, not a prose summary.
|
|
709
649
|
End with one `Verdict: PASS|PARTIAL|FAIL` line after
|
|
710
650
|
`| Req | Status | Evidence |` (one row per requirement; MET | PARTIAL | UNMET) and
|
|
711
651
|
`| AC | Status | Evidence Type | Evidence |` (one row per AC; MET | PARTIAL | UNMET | N/A).
|
|
@@ -714,12 +654,11 @@ states:
|
|
|
714
654
|
a declared `AC-N` alias; a linked scenario covers its task; a task-local criterion needs no feature credit.
|
|
715
655
|
Open P1-P3 blocks completion.
|
|
716
656
|
Also write it to `.spur/run/${vars.__runId}-review-cert.md`.
|
|
717
|
-
${vars.reviewLint}
|
|
718
657
|
# The captured review answer is the run's certification input (and the
|
|
719
658
|
# `task verdict` input below): expectFile fails the step when no answer landed.
|
|
720
659
|
answerFile: .spur/run/${vars.__runId}-review-answer.txt
|
|
721
660
|
expectFile: .spur/run/${vars.__runId}-review-answer.txt
|
|
722
|
-
# The reviewer WRITES this one itself (see (c2)); declared so the composition
|
|
661
|
+
# The reviewer WRITES this one itself (see (c2)); declared so the composition check can
|
|
723
662
|
# see the run path the prompt names (1233 R2).
|
|
724
663
|
inputs:
|
|
725
664
|
- path: .spur/run/${vars.__runId}-review-cert.md
|
|
@@ -737,51 +676,38 @@ states:
|
|
|
737
676
|
# (c2) The reviewer is asked to WRITE its canonical artifact to `-review-cert.md`, because
|
|
738
677
|
# the captured answer above is the agent's stdout: a reviewer that writes the artifact and
|
|
739
678
|
# then narrates its summary has the artifact overwritten by the narration, and the verdict
|
|
740
|
-
#
|
|
679
|
+
# derivation fails work that is actually complete (four such runs in the G74 batch, 2026-10-24).
|
|
741
680
|
# The agent-written cert wins; when it is absent or empty the captured answer is used, so
|
|
742
681
|
# this is a strict widening of accepted inputs, never a new failure mode.
|
|
743
682
|
- kind: shell
|
|
744
683
|
options:
|
|
745
684
|
command: >-
|
|
746
685
|
A=".spur/run/$__runId-review-answer.txt"; C=".spur/run/$__runId-review-cert.md"; [ -s "$C" ] || cp "$A" "$C" 2>/dev/null; exit 0
|
|
747
|
-
# (d) `spur task verdict` owns the
|
|
748
|
-
#
|
|
749
|
-
#
|
|
750
|
-
#
|
|
751
|
-
# record` consumes — and exits 1 on a non-PASS verdict BY DESIGN, which `softFail`
|
|
752
|
-
# records as the typed outcome the guards route. A lint failure (exit 1) is a failed
|
|
753
|
-
# certification, never a warning, and there is no grep fallback.
|
|
686
|
+
# (d) `spur task verdict` owns the verdict derivation (task 1003 R2). It writes
|
|
687
|
+
# `.spur/run/<wbs>-verdict.json` — the review verdict artifact `spur task record`
|
|
688
|
+
# consumes — and exits 1 on a non-PASS verdict BY DESIGN, which `softFail` records as
|
|
689
|
+
# the typed outcome the guards route.
|
|
754
690
|
- kind: command.gate
|
|
755
691
|
options:
|
|
756
692
|
id: review-verdict
|
|
757
693
|
executable: "${vars.spurBin}"
|
|
758
|
-
args: ["task", "verdict", "${vars.wbs}", "--from-answer", ".spur/run/${vars.__runId}-review-cert.md"
|
|
694
|
+
args: ["task", "verdict", "${vars.wbs}", "--from-answer", ".spur/run/${vars.__runId}-review-cert.md"]
|
|
759
695
|
resultFile: .spur/run/${vars.__runId}-review-verdict.status
|
|
760
696
|
softFail: true
|
|
761
|
-
#
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
# (e) one fold, one token: PASS requires the typed verdict PASS, the artifact's own
|
|
765
|
-
# PASS, and a clean review gate (open P1-P3 finding or an uncited claim blocks it).
|
|
697
|
+
# Derivation only (no `--replay`: the gate already ran the tests for this tree).
|
|
698
|
+
timeoutMs: "120000"
|
|
699
|
+
# (e) one fold, one token: PASS requires the typed verdict PASS and the artifact's own PASS.
|
|
766
700
|
# Fail-closed: any missing/corrupt input leaves FAIL, so the transitions can route a
|
|
767
701
|
# non-PASS review into remediation instead of dead-ending the run.
|
|
768
702
|
# Idempotent re-entry: the answer file is consumed as a stage input, so a second visit to
|
|
769
703
|
# this state has no answer to re-judge. An ABSENT answer is not new evidence against a
|
|
770
|
-
# PASS — the durable `<wbs>-verdict.json`
|
|
704
|
+
# PASS — the durable `<wbs>-verdict.json` still has to pass — so the
|
|
771
705
|
# run-scoped verdict status is consulted only when an answer is actually present (without
|
|
772
706
|
# this, re-entry overwrote a PASS with FAIL and closed the task's run as `failed`).
|
|
773
707
|
- kind: shell
|
|
774
708
|
options:
|
|
775
709
|
command: >-
|
|
776
|
-
mkdir -p .spur/run; S=FAIL; if [ ! -f ".spur/run/$__runId-review-answer.txt" -o "$(cat ".spur/run/$__runId-review-verdict.status" 2>/dev/null)" = PASS ]; then [ "$(jq -r '.verdict // empty' ".spur/run/$wbs-verdict.json" 2>/dev/null)" = PASS ] &&
|
|
777
|
-
# (d) record the review severity as the lane decision's outcome (1263 R3b): the
|
|
778
|
-
# question `task-semantic-risk` answered is "is this risky?", and the Review table's
|
|
779
|
-
# worst finding is the answer as observed. Resolved rows count (a fixed P2 was still
|
|
780
|
-
# risky). First write wins, so a later review visit changes nothing.
|
|
781
|
-
- kind: shell
|
|
782
|
-
options:
|
|
783
|
-
command: >-
|
|
784
|
-
[ -f ".spur/run/$wbs-semantic-risk.decision" ] || exit 0; ID="$(jq -r '.invocationId // empty' ".spur/run/$wbs-semantic-risk.decision" 2>/dev/null)"; [ -n "$ID" ] || exit 0; $spurBin decision outcome "$ID" --review-severity "$wbs" --source "task-pipeline review" --no-logo >/dev/null 2>&1; exit 0
|
|
710
|
+
mkdir -p .spur/run; S=FAIL; if [ ! -f ".spur/run/$__runId-review-answer.txt" -o "$(cat ".spur/run/$__runId-review-verdict.status" 2>/dev/null)" = PASS ]; then [ "$(jq -r '.verdict // empty' ".spur/run/$wbs-verdict.json" 2>/dev/null)" = PASS ] && S=PASS; fi; printf '%s\n' "$S" > ".spur/run/$wbs-review.status"; exit 0
|
|
785
711
|
# (d) Operator approval as a DECISION POINT, not a state (D65 1239 R1/R5, ADR-140
|
|
786
712
|
# item 5): interactively the operator responder answers; under `profile=auto` the
|
|
787
713
|
# declared binding answers (evidence status var, catalog fallback when the maker
|
|
@@ -805,21 +731,12 @@ states:
|
|
|
805
731
|
options:
|
|
806
732
|
command: >-
|
|
807
733
|
mkdir -p .spur/run; A=APPROVED; if [ "$profile" = auto ]; then [ "$__hitlAnswer" = no ] && A=DENIED; else [ "$__hitlAnswer" = yes ] || A=DENIED; fi; printf '%s\n' "$A" > ".spur/run/$wbs-approval.status"; exit 0
|
|
808
|
-
# 1319 R5(b): one inline re-review token, decided AFTER every fold above so deleting the
|
|
809
|
-
# stale cert/answer cannot make a fold read the previous visit's verdict. Run-scoped, so a
|
|
810
|
-
# stale file from an earlier run can never trigger a retry; `-retried` makes it once only.
|
|
811
|
-
# A second lint failure leaves the token NONE and routes to remediate exactly as today.
|
|
812
|
-
- kind: shell
|
|
813
|
-
options:
|
|
814
|
-
command: >-
|
|
815
|
-
if [ -s ".spur/run/$wbs-verdict-lint.txt" ] && [ ! -f ".spur/run/$__runId-review-lint-retried" ]; then touch ".spur/run/$__runId-review-lint-retried"; printf 'RETRY\n' > ".spur/run/$__runId-review-lint-retry"; rm -f ".spur/run/$__runId-review-cert.md" ".spur/run/$__runId-review-answer.txt"; else printf 'NONE\n' > ".spur/run/$__runId-review-lint-retry"; fi; exit 0
|
|
816
734
|
|
|
817
735
|
- id: done
|
|
818
736
|
description: >
|
|
819
737
|
Terminal — the task is closed deterministically. onEnter performs the close the
|
|
820
738
|
former `record` state owned: `spur task record` writes Testing/Review from the review
|
|
821
|
-
verdict and flips the requirement/AC boxes it proves,
|
|
822
|
-
leftover, and `spur task update <wbs> done --no-lifecycle` runs the verb's own
|
|
739
|
+
verdict and flips the requirement/AC boxes it proves, and `spur task update <wbs> done --no-lifecycle` runs the verb's own
|
|
823
740
|
target-aware `task check` as the completion gate — a task whose boxes or evidence do
|
|
824
741
|
not certify cannot reach the stored `done` status.
|
|
825
742
|
onEnter:
|
|
@@ -847,38 +764,6 @@ states:
|
|
|
847
764
|
options:
|
|
848
765
|
command: >-
|
|
849
766
|
if [ "$deferFeatureSync" = "true" ]; then echo "feature sync deferred to batch integration" >> ".spur/run/$wbs-report.txt"; else FID="$($spurBin task show $wbs --json 2>/dev/null | jq -r '(.feature_id // .frontmatter.feature_id) // empty' 2>/dev/null)"; if [ -n "$FID" ]; then $spurBin feature sync "$FID" --json || echo "feature sync failed — re-run: $spurBin feature sync $FID" >> ".spur/run/$wbs-report.txt"; else echo "Orphan task $wbs — no feature_id linked — proposal: consider linking to a parent feature." >> ".spur/run/$wbs-report.txt"; fi; fi; exit 0
|
|
850
|
-
# (d) F96 (0983): `spur task residual` owns the sweep; shell only sequences it. The
|
|
851
|
-
# scan runs AFTER `task record` flipped the verdict-proven boxes, or a proven-but-
|
|
852
|
-
# unticked box folds every good run to PARTIAL and the done gate is unreachable
|
|
853
|
-
# (0967). Any box still unchecked post-record stays blocking.
|
|
854
|
-
# ONE hard action (scan+fold): a scanner crash fails the close closed.
|
|
855
|
-
- kind: shell
|
|
856
|
-
options:
|
|
857
|
-
command: >-
|
|
858
|
-
$spurBin task residual "$wbs" scan --no-logo && $spurBin task residual "$wbs" fold --no-logo
|
|
859
|
-
# (e) F96 R5 (0983): a sweep downgrade must reach the task record — re-record from
|
|
860
|
-
# the FINAL (post-fold) artifact so Testing carries the downgraded verdict; a failed
|
|
861
|
-
# task must not retain a stale PASS Testing narrative. Soft (exit 0): the downgrade
|
|
862
|
-
# itself fails the re-assert below.
|
|
863
|
-
# 0980: --no-lifecycle for the same orphan reason as the main record command.
|
|
864
|
-
- kind: shell
|
|
865
|
-
options:
|
|
866
|
-
command: >-
|
|
867
|
-
verdict="$(jq -r .verdict .spur/run/$wbs-verdict.json 2>/dev/null)"; if [ -n "$verdict" ] && [ "$verdict" != PASS ]; then $spurBin task record $wbs --solution-from-diff --transition testing --no-lifecycle || echo "post-downgrade re-record failed — re-run: $spurBin task record $wbs" >&2; fi; exit 0
|
|
868
|
-
# (e) The completion contract, re-asserted after the sweep: a post-record residual
|
|
869
|
-
# downgrade must block the close (hard action, no `; exit 0`). The verdict artifact is
|
|
870
|
-
# the review's own evidence, not a re-captured digest — the old proof re-assertion is
|
|
871
|
-
# gone, the fail-closed check on the verdict it certifies is not.
|
|
872
|
-
- kind: shell
|
|
873
|
-
options:
|
|
874
|
-
command: 'jq -e ".verdict == \"PASS\"" .spur/run/$wbs-verdict.json >/dev/null'
|
|
875
|
-
# (d) F96 R4 (0950): `spur task residual` owns the settle.
|
|
876
|
-
# Soft best-effort (exit 0) — runs after certification and must never change
|
|
877
|
-
# the outcome; failure prints the re-run command.
|
|
878
|
-
- kind: shell
|
|
879
|
-
options:
|
|
880
|
-
command: >-
|
|
881
|
-
$spurBin task residual "$wbs" settle --no-logo || echo "residual-settle failed — re-run: spur task residual $wbs settle" >&2; exit 0
|
|
882
767
|
# (c) command.gate owns the done transition with classified transient retry. The verb
|
|
883
768
|
# runs its own target-aware `task check --as done` (the completion gate) before the
|
|
884
769
|
# status write, so a task that does not certify a `done` target never stores `done`.
|
|
@@ -921,13 +806,6 @@ states:
|
|
|
921
806
|
printf '\n## Escalation bound reached\n\nThe implement step asked an operator question %s times (bound %s) and ended without a resumable answer. Unanswered question:\n\n' "$n" "$maxEscalations" >> .spur/run/$wbs-report.txt;
|
|
922
807
|
cat .spur/run/$wbs-question.md >> .spur/run/$wbs-report.txt;
|
|
923
808
|
exit 0
|
|
924
|
-
# (d) F96 R5 (0950): `spur task residual` owns the report.
|
|
925
|
-
# Soft (exit 0): a run that exhausts its fix budget on residuals leaves the
|
|
926
|
-
# report + recovery line while the task stays `wip`.
|
|
927
|
-
- kind: shell
|
|
928
|
-
options:
|
|
929
|
-
command: >-
|
|
930
|
-
$spurBin task residual "$wbs" report --no-logo || echo "residual-report failed — re-run: spur task residual $wbs report" >&2; exit 0
|
|
931
809
|
|
|
932
810
|
transitions:
|
|
933
811
|
# ── precheck: task check --precheck (size + evidence + four-layer, 1002 R4) → implement; ──
|
|
@@ -1022,12 +900,12 @@ transitions:
|
|
|
1022
900
|
test "$(cat ".spur/run/$wbs-test-gate.status" 2>/dev/null)" = PASS
|
|
1023
901
|
- from: gate
|
|
1024
902
|
to: review
|
|
1025
|
-
description:
|
|
903
|
+
description: Incremental mode — the typed outcome is PASS and the gate wrote the DEFERRED (incremental) token.
|
|
1026
904
|
guard:
|
|
1027
905
|
kind: shell
|
|
1028
906
|
options:
|
|
1029
|
-
#
|
|
1030
|
-
#
|
|
907
|
+
# `DEFERRED` is accepted ONLY in incremental mode — in full mode ("false") a stray
|
|
908
|
+
# DEFERRED file fails the guard exactly like a corrupt one.
|
|
1031
909
|
command: >-
|
|
1032
910
|
test "$deferQualityGate" = "true" &&
|
|
1033
911
|
test "$(cat ".spur/run/$__runId-gate.status" 2>/dev/null)" = PASS &&
|
|
@@ -1104,16 +982,6 @@ transitions:
|
|
|
1104
982
|
kind: shell
|
|
1105
983
|
options:
|
|
1106
984
|
command: 'test "$(cat ".spur/run/$wbs-approval.status" 2>/dev/null)" = DENIED'
|
|
1107
|
-
# 1319 R5(c): one inline re-review when the answer LINT failed, before any remediate hop is
|
|
1108
|
-
# spent. Declared after the denial route and before `retry-exhausted` because a lint retry is
|
|
1109
|
-
# not a repair attempt (it does not consume the shared fix-attempt counter). First match wins.
|
|
1110
|
-
- from: review
|
|
1111
|
-
to: review
|
|
1112
|
-
description: The verdict lint rejected the answer's shape — re-issue the review prompt once with the lint findings instead of buying a remediate hop.
|
|
1113
|
-
guard:
|
|
1114
|
-
kind: shell
|
|
1115
|
-
options:
|
|
1116
|
-
command: 'test "$(cat ".spur/run/$__runId-review-lint-retry" 2>/dev/null)" = RETRY'
|
|
1117
985
|
- from: review
|
|
1118
986
|
to: failed
|
|
1119
987
|
terminalReason: retry-exhausted
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.34",
|
|
4
4
|
"description": "Spur CLI — local-first harness for mainstream coding agents: constraint checking, workflow orchestration, agent health, and history analytics. Bun-native; exposes the `spur` command.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"spur",
|
|
@@ -174,23 +174,18 @@ fails it. One explicit mapping, no transcription step anywhere downstream:
|
|
|
174
174
|
Severity words stay visible in the same cell — the mapping adds the machine-readable label, it does
|
|
175
175
|
not replace the semantics.
|
|
176
176
|
|
|
177
|
-
**Disposition column (1089, E71).** The findings table carries a `Disposition` cell
|
|
178
|
-
|
|
179
|
-
`
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
non-PASS review, so the `review-failure-class` decision routes it to `remediate` instead of `done`.
|
|
190
|
-
Open P1-P3 findings block `done`; fixing one invalidates the certified digest and re-runs
|
|
191
|
-
gate → review on a fresh digest. Only P4 rows and `DEFER`-ed P3 rows are wrap residuals — disposition the finding in
|
|
192
|
-
its cell now, while you hold the context, instead of leaving the cost to be rediscovered after a
|
|
193
|
-
full cycle.
|
|
177
|
+
**Disposition column (1089, E71).** The findings table carries a `Disposition` cell, and it is
|
|
178
|
+
your statement of each finding's state: `RESOLVED`/`FIXED`/`DONE` (optionally with the commit) for a
|
|
179
|
+
finding closed inside the same task, `DEFER(<reason>)` for a P3 you deliberately carry (never
|
|
180
|
+
P1/P2), `ACCEPTED` for a P4 observation you are not acting on, `OPEN` for one still live. Nothing
|
|
181
|
+
parses these rows — your `Verdict:` line is the only gate — so the two must agree: a table with an
|
|
182
|
+
open P1-P3 row carries a non-PASS verdict.
|
|
183
|
+
|
|
184
|
+
**Pipeline cost of an open finding (1122).** A non-PASS review routes through the
|
|
185
|
+
`review-failure-class` decision to `remediate` instead of `done`. Open P1-P3 findings block `done`;
|
|
186
|
+
fixing one invalidates the certified digest and re-runs gate → review on a fresh digest. Only P4 rows
|
|
187
|
+
and `DEFER`-ed P3 rows are wrap residuals — disposition the finding in its cell now, while you hold
|
|
188
|
+
the context, instead of leaving the cost to be rediscovered after a full cycle.
|
|
194
189
|
|
|
195
190
|
**Section-relative headings.** In WBS mode (standalone or pipeline) the report body is written
|
|
196
191
|
*into* the task's `### Review` section, so every heading inside it MUST be `####` or deeper. A
|
|
@@ -228,32 +223,10 @@ FAIL, PARTIAL, a missing line, a line split across two lines — routes the run
|
|
|
228
223
|
`review-failure-class` decision into the bounded `remediate` hop. Keep it on one line, in that shape, in every
|
|
229
224
|
review answer; never restate it as prose only.
|
|
230
225
|
|
|
231
|
-
**
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
| Derived | When the table says so |
|
|
237
|
-
| --- | --- |
|
|
238
|
-
| `LOW` | the verdict is not PASS, or an open (or undispositioned) P1–P3 row survives |
|
|
239
|
-
| `HIGH` | PASS with every finding closed (`RESOLVED` / `FIXED` / `DONE`) and no carried residual |
|
|
240
|
-
| `MEDIUM` | PASS with carried residuals only — `DEFER(...)`, `ACCEPTED`, or an open P4 |
|
|
241
|
-
|
|
242
|
-
Derivation: `packages/app/src/services/answer-confidence.ts` (shared with the verify answer). This
|
|
243
|
-
does not revive the retired self-grade: the level records **evidence composition** — what a reader
|
|
244
|
-
would otherwise have to re-derive from the rows — and the gate recomputes it rather than trusting it.
|
|
245
|
-
No verdict-artifact field, no receipt level, no per-finding grade, and no operator ack var exists
|
|
246
|
-
(ADR-138 stands for every other carrier). Evidence gaps still belong in the report body: name them,
|
|
247
|
-
then let the dispositions decide the level.
|
|
248
|
-
|
|
249
|
-
**Two artifacts, one `Confidence:` line each (1254).** The body you write into `### Review` states
|
|
250
|
-
the disposition-derived level above. When the pipeline also captures your final answer as the
|
|
251
|
-
certification input for `spur task verdict`, that text is a *second* artifact with a *different*
|
|
252
|
-
consumer, and it carries the **evidence-derived** level (`deriveVerifyConfidence`): PASS with every
|
|
253
|
-
AC row MET on executable evidence (`test`/`command`) is HIGH; a citation-only (`static-ref`),
|
|
254
|
-
`manual-review`, `llm-judge` or `N/A` AC is MEDIUM; a non-PASS verdict or any PARTIAL/UNMET row is
|
|
255
|
-
LOW. It ends with exactly one plain `Verdict: PASS|PARTIAL|FAIL` line preceded by both tables, in
|
|
256
|
-
this exact shape:
|
|
226
|
+
**The certification answer.** No `Confidence:` line exists on any carrier — name evidence gaps in
|
|
227
|
+
the report body instead. When the pipeline captures your final answer as the certification input
|
|
228
|
+
for `spur task verdict`, it ends with exactly one plain `Verdict: PASS|PARTIAL|FAIL` line preceded
|
|
229
|
+
by both tables, in this exact shape:
|
|
257
230
|
|
|
258
231
|
| Req | Status | Evidence |
|
|
259
232
|
| --- | --- | --- |
|
|
@@ -267,15 +240,10 @@ One row per declared requirement (`MET | PARTIAL | UNMET`, none omitted or merge
|
|
|
267
240
|
acceptance criterion (`MET | PARTIAL | UNMET | N/A`), with the evidence-type token alone in its own
|
|
268
241
|
cell — `test | command | static-ref | manual-review | llm-judge | n/a`, or a `+` compound when more
|
|
269
242
|
than one kind applies. Evidence cells cite a repo-root-relative `path:line` or a named test/command.
|
|
270
|
-
|
|
271
|
-
done projection (`L4.anchor-unresolved`); cite the owning source or a corpus artifact instead. AC
|
|
243
|
+
Cite the owning source or a corpus artifact, never a scratch path. AC
|
|
272
244
|
identities stay the task's own (checklist label, title, bold head, `Scenario:` prefix, bracket tag or
|
|
273
245
|
declared `AC-N` alias): a linked feature's scenario title covers the task that implements it, and a
|
|
274
246
|
task-local criterion is legal as-is — it needs no feature credit.
|
|
275
|
-
Never repeat the section's disposition-derived `Confidence:` line here: a second `Confidence:` line is
|
|
276
|
-
a `confidence-duplicate` rejection of the whole answer, and so is a level the rows do not derive. A
|
|
277
|
-
PASS with executable AC and one accepted P4 therefore certifies as `Confidence: HIGH` in the answer
|
|
278
|
-
while the section keeps `Confidence: MEDIUM`.
|
|
279
247
|
|
|
280
248
|
**Source citations for external claims (one claim contract, 2026-10-12).** A Finding cell or a
|
|
281
249
|
Functional Traceability `Evidence` cell that asserts an external API/library claim carries a
|
|
@@ -289,18 +257,8 @@ finding's subject, not the claim's source. Cell-free receipts (test counts, revi
|
|
|
289
257
|
assert no external claim and need no citation. An uncited external claim is an assumption: name it
|
|
290
258
|
as an explicit gap in the report body (above), so a reader can re-check it.
|
|
291
259
|
|
|
292
|
-
|
|
293
|
-
**Machine-checked at the gate (findings table).** `spur task residual <wbs> review-gate` applies the same two
|
|
294
|
-
predicates to every finding row: a Finding cell carrying one of the verify lint's claim markers with
|
|
295
|
-
no citation form becomes a **blocking** `review-contract` item, so `review → done` stops and the
|
|
296
|
-
run enters the `review-failure-class` decision. The `Location` column is deliberately not consulted as a citation —
|
|
297
|
-
that is the rule stated above, and a gate that accepted it would pass every row that has an anchor.
|
|
298
|
-
Functional Traceability `Evidence` cells stay reviewer-enforced (SECUA review): they are free prose
|
|
299
|
-
in a table the gate does not parse.
|
|
300
|
-
|
|
301
260
|
**No findings.** Never invent a defect to populate the table. Emit one substantive `P4 (advisory)`
|
|
302
|
-
row that states what was reviewed and what was found — placeholder cells (empty, `—`, `n/a`)
|
|
303
|
-
rejected by the checker, and so they should be:
|
|
261
|
+
row that states what was reviewed and what was found — placeholder cells (empty, `—`, `n/a`) tell a reader nothing:
|
|
304
262
|
|
|
305
263
|
```markdown
|
|
306
264
|
| # | Priority | Dimension | Finding | Location | Disposition |
|
|
@@ -30,13 +30,6 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
30
30
|
|
|
31
31
|
Follow the inline procedure in [dev-operations.md](../skills/spur-dev/references/dev-operations.md#10-fixall) (fixall). Pipeline signal: when `--gate-log` is set (the `remediate` hop), run no full gate — the `gate` state's recheck immediately after is the deciding run (R4, task 0483).
|
|
32
32
|
|
|
33
|
-
When dispatched from the pipeline's `remediate` hop (F96, task 0950), the gate log carries a
|
|
34
|
-
`residual artifact` block (`<wbs>-residuals.json`) and the findings file already
|
|
35
|
-
contains the merged residual anchors: treat those items as fix targets, in order,
|
|
36
|
-
alongside gate anchors. The fixer may write `.spur/run/<wbs>-residual-deferrals.json`
|
|
37
|
-
— one `{id, reason}` entry per item — but only for P3 findings or diff markers it
|
|
38
|
-
cannot fix inside the task; the done stage settles deferrals into follow-up tasks.
|
|
39
|
-
|
|
40
33
|
The `remediate` hop is entered only after a `fix` decision (`failure-class` on a red gate,
|
|
41
34
|
`review-failure-class` on a non-PASS review). A `stop` decision ends the run before this command
|
|
42
35
|
runs, so do not invoke it by hand to overrule a `stop`
|
|
@@ -44,7 +44,7 @@ Put the target first: a bare token after `--worktree` is read as the worktree na
|
|
|
44
44
|
- **WBS mode (per task target):** `Skill(skill="sp:functional-review", args="<wbs> $FLAGS")` + `Skill(skill="sp:code-verification", args="review <wbs> $FLAGS")` + `Skill(skill="sp:code-improvement", args="<wbs> $FLAGS")` (functional traceability + SECUA framework + architectural depth — each skill receives its one resolved WBS exactly once plus `$FLAGS` = `$ARGUMENTS` minus the selector (`--tasks`/`--feature`/`--scope` or positional) and its value, never the raw selector, and returns a review fragment only — F92 0593 R1)
|
|
45
45
|
- **Task fan-out (`--tasks` / `--feature`).** One WBS-mode review per task in the frozen set. Tasks in `backlog`/`todo`/`blocked` are reported NOT-STARTED and skipped (§ 3a outcome vocabulary); a per-task failure does not stop the remaining tasks. Each implemented task gets its own merged `## Review`; the run ends with a combined summary table (WBS, verdict, P1/P2 counts).
|
|
46
46
|
- Coordinator = this session. No `sp:super-reviewer` subagent is dispatched: act as the review coordinator defined in [agents/super-reviewer.md](../agents/super-reviewer.md) — merge the fragments per its Output Format (native `P1`–`P4` priority cells, section-relative headings) and, for every task target (standalone or pipeline), write that task's combined `## Review` via `spur task update <wbs> --section Review --from-file`. Path mode emits advisory output only.
|
|
47
|
-
- **Answer contract (pipeline dispatches).** The captured review answer (`.spur/run/<runId>-review-answer.txt`) must carry exactly one `Verdict: PASS|FAIL` line **and** the requirement traceability table `| Req | Status | Evidence |` (D65 1239: `verify` merged into `review`, so this answer is the pipeline's only verification record).
|
|
47
|
+
- **Answer contract (pipeline dispatches).** The captured review answer (`.spur/run/<runId>-review-answer.txt`) must carry exactly one `Verdict: PASS|FAIL` line **and** the requirement traceability table `| Req | Status | Evidence |` (D65 1239: `verify` merged into `review`, so this answer is the pipeline's only verification record). No `Confidence:` line exists; with an open P1–P3 finding the verdict must be non-PASS. `spur task verdict --from-answer` owns the parse — it writes the canonical `.spur/run/<wbs>-verdict.json` that `spur task record` reads for box flips and `## Testing`, and a non-zero exit fails the review stage; never re-implement the parse in shell. On a feature-linked task, key each AC row to its feature scenario (scenario title, `AC-N` alias, `(feature R<n>)` or `[R<n>]`) so `record` can tick the aliased AC line.
|
|
48
48
|
- **Path mode (per path target):** `Skill(skill="sp:code-verification", args="review <path> $FLAGS")` + `Skill(skill="sp:code-improvement", args="<path> $FLAGS")` (advisory SECUA quality + architectural depth — one normalized path forwarded once plus `$FLAGS`; performs no task mutation). Under `--scope <path>[,<path>]`: paths must exist (exit 2 otherwise), are normalized, duplicates dropped and nested paths collapse to the ancestor (`--scope apps,apps/cli` → `apps`); each surviving path gets a sub-review (Step 3p path scope), eligible for native-subagent dispatch per [dispatch-surface.md](../skills/parallel-execution/references/dispatch-surface.md); the coordinator merges the sub-reviews, runs **one** cross-path architecture pass (`sp:code-improvement` over the inter-path imports), and emits **one** advisory report. No task mutation.
|
|
49
49
|
- **Positional alias (deprecated).** A positional `<wbs|path>` is accepted for one release: a `^\d{4}$` token with a resolvable task behaves as `--tasks <wbs>`; an existing path as `--scope <path>`; otherwise exit 2. Print a deprecation warning naming the replacement selector; removal is a follow-up.
|
|
50
50
|
- `--triage`: after the review returns, run the triage protocol in [dev-operations.md § 2. review](../skills/spur-dev/references/dev-operations.md#2-review) **inline in this session** — the review skills and `sp:super-reviewer` stay report-only. With multiple targets, bucket the findings across all targets once (identical `file:line` findings deduped before bucketing). `Edit`/`Write` in `allowed-tools` exist only for these direct fixes.
|