@gobing-ai/spur 0.4.4 → 0.4.6
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.example.yaml +3 -4
- package/config/config.global.yaml +3 -4
- package/config/rules/docs/sourced-api-claims.yaml +3 -2
- package/config/rules/quality/coverage-gate.yaml +6 -4
- package/config/rules/recommended-pre-check.yaml +11 -9
- package/config/transition-shims.json +0 -14
- package/config/workflows/task-pipeline.yaml +31 -71
- package/package.json +1 -1
- package/plugins/sp/agents/super-reviewer.md +11 -27
- package/plugins/sp/commands/dev-review.md +1 -1
- package/plugins/sp/lib/inline-run.generated.mjs +3 -3
- package/plugins/sp/lib/residual-scan.generated.d.mts +0 -13
- package/plugins/sp/lib/residual-scan.generated.mjs +3 -47
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/commit-guard.mjs +49 -39
- package/plugins/sp/scripts/commit-guard.ts +60 -61
- package/plugins/sp/scripts/persist-out-check.mjs +28 -24
- package/plugins/sp/scripts/persist-out-check.ts +42 -33
- package/plugins/sp/scripts/residual-scan.mjs +5 -50
- package/plugins/sp/scripts/residual-scan.ts +4 -6
- package/plugins/sp/skills/code-verification/SKILL.md +1 -2
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +16 -35
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +4 -2
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +3 -1
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +3 -2
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +7 -11
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +7 -6
- package/spur.js +422 -431
- package/web/_astro/{BoardApp.hF0RAIrg.js → BoardApp.C5jnkkKP.js} +124 -124
- package/web/_astro/{BoardApp.Niubpe6z.js → BoardApp.CaNvQBD_.js} +1 -1
- package/web/_astro/{TaskDetail.DJpapt38.js → TaskDetail.DGKndhI8.js} +1 -1
- package/web/_astro/{arc.BgKcK0i8.js → arc.DHrwdg3G.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.ChP-Ig0V.js → architectureDiagram-3BPJPVTR.pvKpK1s5.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.BVaCBoeN.js → blockDiagram-GPEHLZMM.BQmRcZsS.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.CHSDpEO5.js → c4Diagram-AAUBKEIU.CCLjHeH1.js} +1 -1
- package/web/_astro/channel.C7wG9RxA.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.MYRcYVRa.js → chunk-2J33WTMH.DL6Yuoma.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.S5j22Zqa.js → chunk-4BX2VUAB.CzlyEI7l.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.gciRPvmZ.js → chunk-55IACEB6.B60EWxp1.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.CdqrSQkX.js → chunk-727SXJPM.c7v_fRLo.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.CyokdHT3.js → chunk-AQP2D5EJ.8BxLWdDc.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.Bg9KJhjW.js → chunk-FMBD7UC4.DmKuxGFT.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.1gxxI-vD.js → chunk-ND2GUHAM.1Zwd4mqV.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.DDEYtCKU.js → chunk-QZHKN3VN.BvYLu-A1.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.Ch3zi37T.js → classDiagram-4FO5ZUOK.CEqRt0WU.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.Ch3zi37T.js → classDiagram-v2-Q7XG4LA2.CEqRt0WU.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.D2q5AINI.js → cose-bilkent-S5V4N54A.C7JiUdj2.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.BA9kC2YT.js → cynefin-OW5HDTMX.B6mZ-1be.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.CHO08nRp.js → dagre-BM42HDAG.BuryfDy6.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.BfFQt0LW.js → diagram-2AECGRRQ.dao39YQM.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.CHMwMTe4.js → diagram-5GNKFQAL.lnGZe4At.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.BJ-7gK-w.js → diagram-KO2AKTUF.uWfhzEfT.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.C5xqcc0t.js → diagram-LMA3HP47.ppq8-198.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.C2pQjfrC.js → diagram-OG6HWLK6.CKSCqDt5.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35._FoNyxgC.js → erDiagram-TEJ5UH35.sFSf2yBN.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.B_ENkT2I.js → flowDiagram-I6XJVG4X.BJQjKLbz.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.B3q8h77C.js → ganttDiagram-6RSMTGT7.DAHKNj2N.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.QWZFDboZ.js → gitGraphDiagram-PVQCEYII.BlmzcW_O.js} +1 -1
- package/web/_astro/index.BCY1JJHd.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.Cs6eEc92.js → infoDiagram-5YYISTIA.DGhjaqsi.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BU9DJMHA.js → ishikawaDiagram-YF4QCWOH.gKIpgt6F.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.D35k6Jpe.js → journeyDiagram-JHISSGLW.DG3tmP0R.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.DBqcAT4m.js → kanban-definition-UN3LZRKU.CgHDSxkR.js} +1 -1
- package/web/_astro/{linear.D-LSNK8W.js → linear.BuGEpcuM.js} +1 -1
- package/web/_astro/{mermaid.core.CSruWVOa.js → mermaid.core.DBVqkWBp.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.BiFaUsfj.js → mindmap-definition-RKZ34NQL.D-kOcji9.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.D1KTKqb9.js → pieDiagram-4H26LBE5.BvGPwtZt.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.DBHflsMG.js → quadrantDiagram-W4KKPZXB.BKb_9FV6.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.hwX9CNdk.js → requirementDiagram-4Y6WPE33.Cx0fvD8v.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.DkI8mJiE.js → sankeyDiagram-5OEKKPKP.fatULi0W.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.DMz7jBDx.js → sequenceDiagram-3UESZ5HK.ChHyKqco.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.B6Ef2xJ1.js → stateDiagram-AJRCARHV.BdUpKWyj.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CgoaufB9.js → stateDiagram-v2-BHNVJYJU.fmJxqIm5.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.B3c8h1t-.js → timeline-definition-PNZ67QCA.BayDn5-V.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.BdHPAxAb.js → vennDiagram-CIIHVFJN.Bm2Aggwa.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.BrJXPPAj.js → wardleyDiagram-YWT4CUSO.DI75O-uG.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.CMH5yFsV.js → xychartDiagram-2RQKCTM6.DL90E7Q7.js} +1 -1
- package/web/index.html +2 -2
- package/config/rules/docs/verdict-confidence.yaml +0 -68
- package/web/_astro/channel.DkpvN2tD.js +0 -1
- package/web/_astro/index.BFyW13JJ.css +0 -1
|
@@ -66,10 +66,9 @@ bootstrap:
|
|
|
66
66
|
agent:
|
|
67
67
|
# `default` is the role used for `--agent auto` when the caller declares
|
|
68
68
|
# nothing (task 0542 R2 — the value domain moved from executor names to
|
|
69
|
-
# roles). A role id selects its tier's cheapest eligible executor;
|
|
70
|
-
# configured executor name
|
|
71
|
-
#
|
|
72
|
-
# naming both accepted sets.
|
|
69
|
+
# roles). A role id selects its tier's cheapest eligible executor; any
|
|
70
|
+
# other value fails. A configured executor name fails with a fix (use a
|
|
71
|
+
# role, and pin the executor with --agent <name>).
|
|
73
72
|
default: coder
|
|
74
73
|
|
|
75
74
|
# Role → tier map (SSOT: DEFAULT_AGENT_ROLES in packages/config, task 0572 /
|
|
@@ -35,10 +35,9 @@ version: "1.2"
|
|
|
35
35
|
agent:
|
|
36
36
|
# `default` is the role used for `--agent auto` when the caller declares
|
|
37
37
|
# nothing (task 0542 R2 — the value domain moved from executor names to
|
|
38
|
-
# roles). A role id selects its tier's cheapest eligible executor;
|
|
39
|
-
# configured executor name
|
|
40
|
-
#
|
|
41
|
-
# naming both accepted sets.
|
|
38
|
+
# roles). A role id selects its tier's cheapest eligible executor; any
|
|
39
|
+
# other value fails. A configured executor name fails with a fix (use a
|
|
40
|
+
# role, and pin the executor with --agent <name>).
|
|
42
41
|
default: coder
|
|
43
42
|
|
|
44
43
|
# Role → tier map. Resolution: role → tier → cheapest USABLE executor whose
|
|
@@ -32,8 +32,9 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
|
|
|
32
32
|
# backstop: the two `cited-*` rules cover the citation half, and
|
|
33
33
|
# `cited-api-claims-confidence` covers the level half. All are severity `info`,
|
|
34
34
|
# and the category is deliberately NOT in `recommended-pre-check` — it surfaces
|
|
35
|
-
# findings for review without reddening gates.
|
|
36
|
-
#
|
|
35
|
+
# findings for review without reddening gates. The 2026-10-12 audit below settled
|
|
36
|
+
# the promotion question: the residual findings stay a review-surface concern
|
|
37
|
+
# (SECUA checklist), not a gate one — do not add `- docs` to that preset.
|
|
37
38
|
include:
|
|
38
39
|
- "docs/**/*.md"
|
|
39
40
|
- "plugins/sp/skills/**/references/**/*.md"
|
|
@@ -12,14 +12,16 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
|
|
|
12
12
|
# `bun run test:full`. Running this rule directly via `spur rule run` outside the
|
|
13
13
|
# repository wrapper bypasses that certification wrapper and is outside this
|
|
14
14
|
# repository's certification contract. This rule and its evaluator are unchanged.
|
|
15
|
+
# Launcher children write isolated LCOV; canonical publication is exclusive and
|
|
16
|
+
# accepts only that run's complete records. Noncanonical launcher runs cannot
|
|
17
|
+
# overwrite the certified tracefile. Bare `bun test` still bypasses the launcher.
|
|
15
18
|
#
|
|
16
19
|
# Absorbed from ts-libs/.spur/rules/quality/coverage-gate.yaml, re-scoped to
|
|
17
20
|
# Spur's monorepo layout:
|
|
18
21
|
# - lcovPath kept at .coverage/lcov.info (Spur's `bun run test:coverage`
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# tracefile, and this rule then judges that partial data)
|
|
22
|
+
# publishes it after a completed run; bare TARGETED `bun test <file>` can
|
|
23
|
+
# still overwrite it with partial data, which the repository provenance
|
|
24
|
+
# wrapper refuses before this rule runs)
|
|
23
25
|
# - include expanded to apps/** + packages/** (Spur tests cover both;
|
|
24
26
|
# ts-libs only covers packages/**)
|
|
25
27
|
# - threshold kept at 90 matching bunfig.toml coverageThreshold
|
|
@@ -4,16 +4,17 @@ $schema: "@gobing-ai/spur/schemas/preset.schema.json"
|
|
|
4
4
|
#
|
|
5
5
|
# Runs BEFORE tests (test-pre-check). Extends categories: typescript,
|
|
6
6
|
# structure, boundary, surface, ui, strict (ui since bc267cc8, strict since
|
|
7
|
-
# 79186391), and docs (sourced-api-claims, 2026-10-07
|
|
8
|
-
#
|
|
7
|
+
# 79186391), and docs (sourced-api-claims, 2026-10-07; pulled 2026-10-08 for
|
|
8
|
+
# finding noise — a 2026-10-14 restore was reverted; keep it out for now, see
|
|
9
|
+
# the marker line below). TSDoc exports run in post-check alongside
|
|
10
|
+
# coverage-gate.
|
|
9
11
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# `
|
|
15
|
-
#
|
|
16
|
-
# contract). Recapture the raw-json-baseline fixtures in the same change.
|
|
12
|
+
# `docs/sourced-api-claims.yaml` (citation/level checks) stays OUT of this gate:
|
|
13
|
+
# severity info would not redden it, but the findings belong to the SECUA review
|
|
14
|
+
# surface — run that file ad hoc instead. Recapture the raw-json-baseline
|
|
15
|
+
# fixtures when touching this preset. (F511: the category's other file,
|
|
16
|
+
# `verdict-confidence.yaml`, was deleted with the asserted confidence machinery
|
|
17
|
+
# it backstopped.)
|
|
17
18
|
name: recommended-pre-check
|
|
18
19
|
extends:
|
|
19
20
|
- typescript
|
|
@@ -22,3 +23,4 @@ extends:
|
|
|
22
23
|
- surface
|
|
23
24
|
- ui
|
|
24
25
|
- strict
|
|
26
|
+
# - docs ## DO NOT ENABLE THIS LINE
|
|
@@ -7,20 +7,6 @@
|
|
|
7
7
|
"file": "packages/app/src/services/agent-service.ts",
|
|
8
8
|
"keepsWorking": "a bare coding-agent binary name (codex, omp, claude with no matching agent.executors entry) remains a valid --agent value during the role transition, with a one-time warning emitted by warnBareBinaryOnce",
|
|
9
9
|
"removalCondition": "no bare-binary --agent value remains in docs/, config/workflows/, or plugins/sp/ (scan for --agent <binary-name> usages against agent.executors names)"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"id": "spec-without-executor-field",
|
|
13
|
-
"wbs": "0537",
|
|
14
|
-
"file": "apps/cli/src/commands/agent.ts",
|
|
15
|
-
"keepsWorking": "a pre-existing agent spec carrying only type (no executor field) still drains: --agent <specId> falls back to the spec's coding-agent type instead of resolving a missing executor",
|
|
16
|
-
"removalCondition": "every spec under .spur/agents/ records an executor field (scan .spur/agents/*.yaml for the key; re-materialize the demo team first)"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"id": "agent-default-executor",
|
|
20
|
-
"wbs": "0542",
|
|
21
|
-
"file": "packages/app/src/services/agent-service.ts",
|
|
22
|
-
"keepsWorking": "a configured executor name in agent.default still resolves during the transition, warned once by warnAgentDefaultExecutorOnce; the value domain moved to roles (recommended default: coder)",
|
|
23
|
-
"removalCondition": "no agent.default value names an agent.executors entry (scan .spur/config.yaml and config/config.example.yaml against the agent.executors names)"
|
|
24
10
|
}
|
|
25
11
|
]
|
|
26
12
|
}
|
|
@@ -19,14 +19,6 @@
|
|
|
19
19
|
# done guard closed, and re-records Testing before the failed edge); done settles
|
|
20
20
|
# deferrals; failed renders the recovery report. No new state, edge, or model query.
|
|
21
21
|
#
|
|
22
|
-
# Confidence gate (session finding after 1088, task 1068 follow-up): the verify answer has
|
|
23
|
-
# carried a `Confidence: HIGH|MEDIUM|LOW` line since 1068, and nothing read it — a PASS at
|
|
24
|
-
# LOW confidence certified exactly like HIGH. The verify stamp now records a `confidence`
|
|
25
|
-
# check row, and BOTH completion guards (verify → record, record → done) refuse a LOW (or
|
|
26
|
-
# absent) level unless the run was launched with `--vars '{"ackLowConfidence":"true"}'`.
|
|
27
|
-
# The acknowledgement is an operator decision, not a model one: it is the only way to
|
|
28
|
-
# certify a verdict the verifier itself would not stand behind.
|
|
29
|
-
#
|
|
30
22
|
# Review-failure routing (session finding after 1088): `review` had no outgoing edge for a
|
|
31
23
|
# FAIL verdict, so a failing review could only be remediated by driving the graph by hand
|
|
32
24
|
# (re-entering `test` and hand-emitting rows). The review stage now derives
|
|
@@ -51,9 +43,8 @@ kind: state-machine
|
|
|
51
43
|
name: task-pipeline
|
|
52
44
|
# 0772 R2: explicit identity tag. Set only after the proof failure-path tests
|
|
53
45
|
# passed; the engine treats unversioned external definitions as supported.
|
|
54
|
-
# v4 (session finding after 1088): the
|
|
55
|
-
#
|
|
56
|
-
# identity moves with them.
|
|
46
|
+
# v4 (session finding after 1088): the graph routes a non-PASS review into bounded remediation —
|
|
47
|
+
# a contract change, so the identity moves with it (the confidence half of v4 was retired at v7).
|
|
57
48
|
# v5 (task 1077's inline run, 2026-10-06): the verify verdict action is explicitly `onError:
|
|
58
49
|
# continue`. `task verdict` exits non-zero on any non-PASS verdict BY DESIGN (1003 R2) — that is
|
|
59
50
|
# data for the verify guards, not a state failure. Under the engine's default 'fail' policy
|
|
@@ -63,14 +54,13 @@ name: task-pipeline
|
|
|
63
54
|
# UNREACHABLE: a non-PASS verify could only end the run failed. `test-fix` also gained the
|
|
64
55
|
# review-lane evidence projection (see its onEnter) so the repair hop is not fed an empty findings
|
|
65
56
|
# list when the failing hop was `review-fail-triage` rather than the quality gate.
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
|
|
73
|
-
version: "6"
|
|
57
|
+
# v7 (task 1207, F511): the asserted `Confidence: HIGH|MEDIUM|LOW` machinery is retired — the
|
|
58
|
+
# verifier's and reviewer's self-graded levels (re-imported from the cc anti-hallucination skill
|
|
59
|
+
# by task 1068) are no longer written, checked, or gated on; spur certifies on deterministic
|
|
60
|
+
# evidence (rows MET, proof digests, findings dispositioned). The `confidence` check row, the
|
|
61
|
+
# `ackLowConfidence` var, and the guards' LOW/absent clauses are gone; the derived
|
|
62
|
+
# feature-receipt confidence (ADR-131/1196) is a different family and stays.
|
|
63
|
+
version: "7"
|
|
74
64
|
description: "Standard task pipeline: precheck → implement → quality-gate (test/fix/recheck) → review → approve → verify → record → done"
|
|
75
65
|
# Task entity lifecycle (owned by task-lifecycle.yaml):
|
|
76
66
|
# normal: backlog → todo → wip → testing → done
|
|
@@ -195,14 +185,6 @@ vars:
|
|
|
195
185
|
# Escalation counter: .spur/run/<wbs>-escalation-count. Default 2 = two answered
|
|
196
186
|
# questions; a third pause routes to failed with a report note.
|
|
197
187
|
maxEscalations: "2"
|
|
198
|
-
# Operator acknowledgement of a LOW-confidence certification (session finding after 1088).
|
|
199
|
-
# The verify answer's `Confidence:` line is captured into the verdict artifact; a LOW (or
|
|
200
|
-
# absent) level fails the completion guards unless this is "true", because a PASS the
|
|
201
|
-
# verifier would not stand behind is an operator risk decision, not a mechanical one.
|
|
202
|
-
# Set per run: `--vars '{"ackLowConfidence":"true"}'` (and export it on the inline path).
|
|
203
|
-
# Deliberately NOT settable from the task file or the verifier's own answer: the point is
|
|
204
|
-
# that a second party, not the producer, accepts the residual uncertainty.
|
|
205
|
-
ackLowConfidence: ""
|
|
206
188
|
# Runtime-written, 0933: the escalate hop's file.read.into-var fills this from
|
|
207
189
|
# .spur/run/<wbs>-question.md; the hitl.input prompt below references it. Declared
|
|
208
190
|
# here (empty) so the static var-reference validator sees the template source.
|
|
@@ -897,20 +879,6 @@ states:
|
|
|
897
879
|
onError: continue
|
|
898
880
|
options:
|
|
899
881
|
command: "$spurBin task verdict $wbs --from-answer .spur/run/$wbs-verify-answer.txt"
|
|
900
|
-
# Session finding after 1088: the verifier's confidence level becomes a `confidence` check
|
|
901
|
-
# row and a gate-log line, so the level the completion guards enforce is visible in the
|
|
902
|
-
# artifact and the log — not only in the answer file. v6 (task 1134 run): the row warns for
|
|
903
|
-
# an unacknowledged LOW/absent level ONLY, matching the guards' ack rule; warning for
|
|
904
|
-
# MEDIUM too made an admitted certification aggregate to PARTIAL (self-inconsistent artifact,
|
|
905
|
-
# done refused). This is its own action because the proof-binding stamp below must stay the
|
|
906
|
-
# state's LAST action AND under the ADR-115 800-char shell cap.
|
|
907
|
-
- kind: shell
|
|
908
|
-
options:
|
|
909
|
-
command: >-
|
|
910
|
-
V=".spur/run/$wbs-verdict.json"; [ -f "$V" ] || exit 0;
|
|
911
|
-
jq --arg ack "$ackLowConfidence" '. + {checks: (((.checks // []) | map(select(.name != "confidence"))) + [{name: "confidence", status: (if ((.confidence // "LOW") != "LOW" or $ack == "true") then "pass" else "warn" end), evidence: ((.confidence // "LOW (absent from artifact)") + (if $ack == "true" then " (operator-acknowledged)" else "" end))}])}' "$V" > "$V.tmp" && mv "$V.tmp" "$V";
|
|
912
|
-
printf 'confidence: %s (ack=%s)\n' "$(jq -r '.confidence // "LOW (absent)"' "$V")" "$ackLowConfidence" >> ".spur/run/$wbs-test-gate.log";
|
|
913
|
-
exit 0
|
|
914
882
|
# (e) one jq mutation binds the verdict to the proof digest (0703 R3; runId 0730 §B.2 /
|
|
915
883
|
# 0757 R4; definitionDigest 0759 R5; honest review stamp 0785 R4; soft action + hard guard).
|
|
916
884
|
- kind: shell
|
|
@@ -1312,16 +1280,15 @@ transitions:
|
|
|
1312
1280
|
# re-enters quality → review → verify on a fresh digest. Before 1088 a FAIL review had no
|
|
1313
1281
|
# outgoing edge at all; before 1122 a PASS-with-findings cost a full re-certification cycle per
|
|
1314
1282
|
# attempt (knowledge-kit 0210/0213). The reviewer writes `Verdict: PASS|FAIL` in its answer;
|
|
1315
|
-
# both plain and bold forms are accepted.
|
|
1316
|
-
#
|
|
1317
|
-
#
|
|
1318
|
-
#
|
|
1319
|
-
# behind (same policy as the verify confidence gate). Review stays advisory: verify certifies.
|
|
1283
|
+
# both plain and bold forms are accepted. (F511: the v4-era PASS confidence grading — the
|
|
1284
|
+
# reviewer's self-stated HIGH/MEDIUM/LOW level and its `ackLowConfidence` escape hatch — was
|
|
1285
|
+
# retired; a PASS with no open P1-P3 finding is what the gate reads.) Review stays advisory:
|
|
1286
|
+
# verify certifies.
|
|
1320
1287
|
# Under `profile=auto` the approve gate is skipped, so the PASS+auto edge is tried first and the
|
|
1321
1288
|
# interactive PASS edge second.
|
|
1322
1289
|
- from: review
|
|
1323
1290
|
to: verify
|
|
1324
|
-
description: profile=auto, the review certified a
|
|
1291
|
+
description: profile=auto, the review certified a PASS with no open P1-P3 finding — skip the human approval gate.
|
|
1325
1292
|
guard:
|
|
1326
1293
|
kind: shell
|
|
1327
1294
|
options:
|
|
@@ -1329,23 +1296,22 @@ transitions:
|
|
|
1329
1296
|
test "$profile" = auto &&
|
|
1330
1297
|
grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt" &&
|
|
1331
1298
|
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)" &&
|
|
1332
|
-
[ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin"
|
|
1299
|
+
[ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
|
|
1333
1300
|
- from: review
|
|
1334
1301
|
to: approve
|
|
1335
|
-
description: Review certified a
|
|
1302
|
+
description: Review certified a PASS with no open P1-P3 finding — gate on human approval before verification.
|
|
1336
1303
|
guard:
|
|
1337
1304
|
kind: shell
|
|
1338
1305
|
options:
|
|
1339
1306
|
command: >-
|
|
1340
1307
|
grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt" &&
|
|
1341
1308
|
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/residual-scan.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/residual-scan.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)" &&
|
|
1342
|
-
[ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin"
|
|
1309
|
+
[ -f "$S" ] && "$RUNNER" "$S" review-gate "$wbs" --spur-bin "$spurBin" >&2
|
|
1343
1310
|
- from: review
|
|
1344
1311
|
to: review-fail-triage
|
|
1345
1312
|
description: >-
|
|
1346
|
-
No certified PASS without an open P1-P3 finding (FAIL, PARTIAL, missing, unparseable,
|
|
1347
|
-
PASS whose review-gate check found an open P1-P3 row
|
|
1348
|
-
HIGH/MEDIUM — or left ungraded — without the operator's ackLowConfidence; fail closed) —
|
|
1313
|
+
No certified PASS without an open P1-P3 finding (FAIL, PARTIAL, missing, unparseable, or
|
|
1314
|
+
a PASS whose review-gate check found an open P1-P3 row; fail closed) —
|
|
1349
1315
|
classify the failure and route it into the bounded repair hop instead of dead-ending the run.
|
|
1350
1316
|
guard:
|
|
1351
1317
|
kind: always
|
|
@@ -1383,23 +1349,21 @@ transitions:
|
|
|
1383
1349
|
# The verify step emits .spur/run/<wbs>-verdict.json with a required proof block (task 0703 R3/R5).
|
|
1384
1350
|
# Only `verdict: PASS` PLUS a proof block whose digest — top level and every named stage — equals
|
|
1385
1351
|
# the captured `proofDigest` clears the gate to `record`; any non-PASS, a missing file, malformed
|
|
1386
|
-
# JSON, or missing/mismatched proof evidence does not.
|
|
1387
|
-
#
|
|
1388
|
-
#
|
|
1389
|
-
#
|
|
1390
|
-
#
|
|
1391
|
-
# missing/malformed proof block still terminates at `failed` instead of hanging the state.
|
|
1352
|
+
# JSON, or missing/mismatched proof evidence does not. (F511: the v4-era LOW/absent-confidence
|
|
1353
|
+
# clause and its `ackLowConfidence` escape hatch were retired.) Declaration order: PASS+proof
|
|
1354
|
+
# guard FIRST, then the bounded remediation route (R4), then the always catch-all so a PASS
|
|
1355
|
+
# verdict with a missing/malformed proof block still terminates at `failed` instead of hanging
|
|
1356
|
+
# the state.
|
|
1392
1357
|
- from: verify
|
|
1393
1358
|
to: record
|
|
1394
|
-
description: Verification verdict is PASS
|
|
1359
|
+
description: Verification verdict is PASS and its proof block names the captured digest on every stage — record results and proceed to done.
|
|
1395
1360
|
guard:
|
|
1396
1361
|
# (one jq -e predicate) PASS verdict; proof, quality-gate, review and verification digests
|
|
1397
|
-
# equal to proofDigest; review completed; matching run id and definition digest (0703 R5, 0785 R4)
|
|
1398
|
-
# confidence HIGH/MEDIUM, or LOW/absent with the operator's ack (session finding after 1088).
|
|
1362
|
+
# equal to proofDigest; review completed; matching run id and definition digest (0703 R5, 0785 R4).
|
|
1399
1363
|
kind: shell
|
|
1400
1364
|
options:
|
|
1401
1365
|
command: >-
|
|
1402
|
-
jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest"
|
|
1366
|
+
jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" '
|
|
1403
1367
|
.verdict == "PASS"
|
|
1404
1368
|
and (.proof.digest // "") == $d
|
|
1405
1369
|
and (.proof.stages.qualityGate.digest // "") == $d
|
|
@@ -1408,7 +1372,6 @@ transitions:
|
|
|
1408
1372
|
and (.proof.stages.verification.digest // "") == $d
|
|
1409
1373
|
and (.proof.runId // "") == $r
|
|
1410
1374
|
and (.proof.definitionDigest // "") == $dd
|
|
1411
|
-
and ((.confidence // "LOW") != "LOW" or $ack == "true")
|
|
1412
1375
|
' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
|
|
1413
1376
|
- from: verify
|
|
1414
1377
|
to: test-fix
|
|
@@ -1436,12 +1399,10 @@ transitions:
|
|
|
1436
1399
|
# ── done gate: record → done/failed gated on `spur task check` (ADR-026 amendment 2026-06-23)
|
|
1437
1400
|
# PLUS the proof-block re-assertion (task 0703 R5): the verdict artifact must still be PASS and
|
|
1438
1401
|
# still name the captured digest — a forged or mutated completion artifact fails closed here.
|
|
1439
|
-
# PLUS the confidence re-assertion (session finding after 1088): the same ack rule as verify →
|
|
1440
|
-
# record, re-read from the artifact so a mutation between the two boundaries cannot slip through.
|
|
1441
1402
|
# Declaration order: pass guard first.
|
|
1442
1403
|
- from: record
|
|
1443
1404
|
to: done
|
|
1444
|
-
description: Task check passed
|
|
1405
|
+
description: Task check passed and the verdict proof block still names the captured digest — certify done.
|
|
1445
1406
|
guard:
|
|
1446
1407
|
kind: shell
|
|
1447
1408
|
options:
|
|
@@ -1451,14 +1412,13 @@ transitions:
|
|
|
1451
1412
|
# comments inside the folded scalar: `>-` joins same-indent lines into
|
|
1452
1413
|
# one shell line.
|
|
1453
1414
|
# Two logical commands, deliberately (ADR-115): the `task check` projection plus
|
|
1454
|
-
# ONE jq predicate re-asserting the whole completion contract — PASS verdict
|
|
1455
|
-
# captured proof digest
|
|
1415
|
+
# ONE jq predicate re-asserting the whole completion contract — PASS verdict and the
|
|
1416
|
+
# captured proof digest.
|
|
1456
1417
|
command: >-
|
|
1457
1418
|
$spurBin task check $wbs --as done &&
|
|
1458
|
-
jq -e --arg p "$proofDigest"
|
|
1419
|
+
jq -e --arg p "$proofDigest" '
|
|
1459
1420
|
.verdict == "PASS"
|
|
1460
1421
|
and ((.proof.digest // "") == $p)
|
|
1461
|
-
and ((.confidence // "LOW") != "LOW" or $ack == "true")
|
|
1462
1422
|
' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
|
|
1463
1423
|
- from: record
|
|
1464
1424
|
to: failed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
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",
|
|
@@ -200,7 +200,6 @@ shallower.
|
|
|
200
200
|
**Scope:** <wbs diff | path glob>
|
|
201
201
|
**Dimensions:** functional, security, efficiency, correctness, usability, architecture
|
|
202
202
|
**Verdict:** PASS | PARTIAL | FAIL
|
|
203
|
-
**Confidence:** HIGH | MEDIUM | LOW
|
|
204
203
|
##### Findings (ranked)
|
|
205
204
|
|
|
206
205
|
| # | Priority | Dimension | Finding | Location | Disposition |
|
|
@@ -226,30 +225,14 @@ FAIL, PARTIAL, a missing line, a line split across two lines — routes the run
|
|
|
226
225
|
`review-fail-triage` and its bounded repair hop. Keep it on one line, in that shape, in every
|
|
227
226
|
review answer; never restate it as prose only.
|
|
228
227
|
|
|
229
|
-
**
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
-
|
|
237
|
-
- `LOW` — the verdict rests on unverified assumptions that could plausibly flip it; name them.
|
|
238
|
-
|
|
239
|
-
A missing line, a level outside the enum, or a `HIGH` the rows do not earn turns an otherwise usable
|
|
240
|
-
PASS into a refused one: consumer repositories gate the review answer artifact and every level it
|
|
241
|
-
claims, exactly as they gate the verify answer. This is a contract change — review answers written
|
|
242
|
-
before it were never asked for a level, so pre-adoption artifacts read as debt, not defects.
|
|
243
|
-
|
|
244
|
-
**Machine-checked at the gate.** The pipeline's own review PASS edges enforce the line before verify:
|
|
245
|
-
`residual-scan review-gate` reads the recorded `### Review` body, and a missing, duplicated or
|
|
246
|
-
out-of-enum level becomes a **blocking** `review-contract` item — `review → verify` stops and the run
|
|
247
|
-
enters `review-fail-triage` with the bounded repair hop, exactly as an open P1–P3 row does. The gate
|
|
248
|
-
checks the recorded section's presence and vocabulary; the same scanner grades the answer passed
|
|
249
|
-
by both PASS edges and refuses a `LOW` (or ungraded) PASS unless the operator sets
|
|
250
|
-
`ackLowConfidence` exactly to `true` (task 1204 — the same policy the verify
|
|
251
|
-
chain enforces), so whether a level is *earned* stays a judgement call (see the earning rule above):
|
|
252
|
-
the report must still argue it.
|
|
228
|
+
**No confidence line (F511, task 1207).** Review reports do not state, and no gate reads, an
|
|
229
|
+
asserted `Confidence: HIGH | MEDIUM | LOW`. A model that can write a PASS can write `HIGH`, so the
|
|
230
|
+
gate grades what is checkable instead: the recorded section's presence and vocabulary, and the
|
|
231
|
+
findings disposition — an open P1–P3 row blocks the edge exactly as before. What a reviewer would
|
|
232
|
+
formerly have compressed into a level belongs in the report body: name the evidence gaps and the
|
|
233
|
+
assumptions explicitly, so a reader can re-check them. (The derived confidence family is
|
|
234
|
+
untouched: feature-verification receipts under ADR-131, the decision subsystem threshold, and
|
|
235
|
+
history-anatomy reading.)
|
|
253
236
|
|
|
254
237
|
**Source citations for external claims (one claim contract, 2026-10-12).** A Finding cell or a
|
|
255
238
|
Functional Traceability `Evidence` cell that asserts an external API/library claim carries a
|
|
@@ -260,8 +243,9 @@ answer's rule verbatim, owned by
|
|
|
260
243
|
for external claims — claim markers and accepted forms are defined once there and are not restated
|
|
261
244
|
here. The findings table's `Location` column does not stand in for it: `Location` anchors the
|
|
262
245
|
finding's subject, not the claim's source. Cell-free receipts (test counts, reviewed-log notes)
|
|
263
|
-
assert no external claim and need no citation. An uncited external claim is an assumption
|
|
264
|
-
|
|
246
|
+
assert no external claim and need no citation. An uncited external claim is an assumption: name it
|
|
247
|
+
as an explicit gap in the report body (above), so a reader can re-check it.
|
|
248
|
+
|
|
265
249
|
|
|
266
250
|
**Machine-checked at the gate (findings table).** `residual-scan review-gate` applies the same two
|
|
267
251
|
predicates to every finding row: a Finding cell carrying one of the verify lint's claim markers with
|
|
@@ -43,7 +43,7 @@ Put the target first: a bare token after `--worktree` is read as the worktree na
|
|
|
43
43
|
- **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)
|
|
44
44
|
- **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).
|
|
45
45
|
- 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.
|
|
46
|
-
- **Answer contract (pipeline dispatches).** The captured review answer (`.spur/run/<runId>-review-answer.txt`) must carry exactly one `Verdict: PASS|FAIL` line
|
|
46
|
+
- **Answer contract (pipeline dispatches).** The captured review answer (`.spur/run/<runId>-review-answer.txt`) must carry exactly one `Verdict: PASS|FAIL` line; the PASS edges grep it before the review gate runs. No confidence line exists and none is graded (F511, task 1207): model-asserted confidence is not verification — the gate's job is the findings disposition, and an open P1–P3 finding blocks the edge on its own.
|
|
47
47
|
- **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.
|
|
48
48
|
- **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.
|
|
49
49
|
- `--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.
|