@gobing-ai/spur 0.3.99 → 0.4.0
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 +17 -0
- package/config/decisions/task-pipeline.yaml +55 -0
- package/config/plugin-scripts.json +10 -0
- package/config/rules/boundary/sp-runtime-path.yaml +2 -0
- package/config/rules/quality/coverage-gate.yaml +5 -3
- package/config/rules/strict/runtime-boundaries.yaml +11 -0
- package/config/rules/structure/protected-files.yaml +3 -0
- package/config/workflows/task-pipeline.yaml +178 -18
- package/package.json +9 -9
- package/plugins/sp/README.md +14 -1
- package/plugins/sp/agents/super-reviewer.md +25 -11
- package/plugins/sp/commands/dev-changelog.md +5 -4
- package/plugins/sp/commands/dev-review-session.md +12 -7
- package/plugins/sp/commands/dev-run.md +5 -2
- package/plugins/sp/commands/dev-runall.md +5 -2
- package/plugins/sp/hooks/agent-lifecycle.ts +155 -0
- package/plugins/sp/hooks/fleet-guest-stop.ts +180 -0
- package/plugins/sp/hooks/hooks.json +45 -1
- package/plugins/sp/hooks/pi/guard-extension.ts +21 -0
- package/plugins/sp/lib/history-anatomy.generated.mjs +5 -0
- package/plugins/sp/lib/idea-handoff.generated.mjs +34 -9
- package/plugins/sp/lib/inline-run.generated.d.mts +1 -0
- package/plugins/sp/lib/inline-run.generated.mjs +49 -19
- package/plugins/sp/lib/transcript.ts +160 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/history-anatomy-cache.mjs +5 -0
- package/plugins/sp/scripts/inline-run-setup.mjs +21 -20
- package/plugins/sp/scripts/inline-run-setup.ts +25 -31
- package/plugins/sp/scripts/residual-scan.mjs +2 -7
- package/plugins/sp/scripts/residual-scan.ts +7 -8
- package/plugins/sp/scripts/run-summary.mjs +286 -0
- package/plugins/sp/scripts/run-summary.ts +241 -0
- package/plugins/sp/scripts/session-timeline.mjs +234 -0
- package/plugins/sp/scripts/session-timeline.ts +152 -0
- package/plugins/sp/skills/code-verification/SKILL.md +5 -0
- package/plugins/sp/skills/fleet-join/SKILL.md +63 -0
- package/plugins/sp/skills/session-review/SKILL.md +46 -24
- package/plugins/sp/skills/spur-cli/SKILL.md +1 -0
- package/plugins/sp/skills/spur-cli/references/agent.md +108 -6
- package/plugins/sp/skills/spur-cli/references/decision.md +97 -0
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +22 -0
- package/plugins/sp/skills/spur-composer/SKILL.md +27 -1
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +28 -16
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +64 -7
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +14 -0
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +16 -4
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +32 -7
- package/plugins/sp/skills/spur-dev/references/planning-workflow.md +6 -0
- package/schemas/decision-catalog.schema.json +226 -0
- package/schemas/spur-config.schema.json +25 -0
- package/spur.js +7440 -2424
- package/web/_astro/BoardApp.Bzr4OXrW.js +324 -0
- package/web/_astro/{BoardApp.i4eh_fHA.js → BoardApp.VeoxxLBy.js} +1 -1
- package/web/_astro/{TaskDetail.C5Cu8LdB.js → TaskDetail.LAyR_Pvn.js} +1 -1
- package/web/_astro/{arc.Bu5XpBEz.js → arc.f4e0OYLg.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.9vHQTvhF.js → architectureDiagram-3BPJPVTR.SSIvxi-Z.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.Cn2Xl7D6.js → blockDiagram-GPEHLZMM.DSXIHOFf.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.7o0P_QDo.js → c4Diagram-AAUBKEIU.DG9Ubu85.js} +1 -1
- package/web/_astro/channel.CUFdtWhm.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.C3zZFsNt.js → chunk-2J33WTMH.C7QU88Qh.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.CNy_M7fO.js → chunk-4BX2VUAB.26Z94xBj.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.2TiPnLBL.js → chunk-55IACEB6.DYRiBkqw.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.5CGSyKAp.js → chunk-727SXJPM.D5Vfv5pe.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.w-ZIgfsK.js → chunk-AQP2D5EJ.DXHV47bN.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.BkcEyhKa.js → chunk-FMBD7UC4.D1suAfOs.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.mxKKbBG4.js → chunk-ND2GUHAM.D6BmdHEY.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.cyA0z9aT.js → chunk-QZHKN3VN.rnPU-Ak-.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.CqtUzwhX.js → classDiagram-4FO5ZUOK.CvEfXIo1.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.CqtUzwhX.js → classDiagram-v2-Q7XG4LA2.CvEfXIo1.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.BExPTopI.js → cose-bilkent-S5V4N54A.DkMisLSm.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.Bq2i10Cn.js → cynefin-OW5HDTMX.C77Q-pF6.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.By_HsOuv.js → dagre-BM42HDAG.YaV8ce27.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.BtU0b7hz.js → diagram-2AECGRRQ.CUyGEKge.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.D00ztMdT.js → diagram-5GNKFQAL.CRgd8dgj.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.DMVJWaUN.js → diagram-KO2AKTUF.Bmzys9hq.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.Cxqrjg5-.js → diagram-LMA3HP47.BvmJY4Lw.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.2lz_1B5h.js → diagram-OG6HWLK6.0hEhD30d.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.BVQEuJ3T.js → erDiagram-TEJ5UH35.Bjt8lrnm.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.Qlyo90ky.js → flowDiagram-I6XJVG4X.CJZTjRDV.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.DRwb8HHZ.js → ganttDiagram-6RSMTGT7._VqoVafc.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.YfoPthfS.js → gitGraphDiagram-PVQCEYII.CEDb7tVo.js} +1 -1
- package/web/_astro/index.Dg_3bOaJ.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.DvFREck1.js → infoDiagram-5YYISTIA.CgwifPpK.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.BzCj9Q0-.js → ishikawaDiagram-YF4QCWOH.B99wx2J1.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.BDMT_AFb.js → journeyDiagram-JHISSGLW.2hRwJbEo.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.D6Fh3gj9.js → kanban-definition-UN3LZRKU.BahJkKNC.js} +1 -1
- package/web/_astro/{linear.Dxw00fGQ.js → linear.DguUUe6V.js} +1 -1
- package/web/_astro/{mermaid.core.CsoxUWa0.js → mermaid.core.CvgfmqVr.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.CN8oeHLu.js → mindmap-definition-RKZ34NQL.B3qEA3x9.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.C7ADqQ_7.js → pieDiagram-4H26LBE5.FlWA-_ru.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.Cw9lKyHP.js → quadrantDiagram-W4KKPZXB.9bVn35X7.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.B1ni-z4q.js → requirementDiagram-4Y6WPE33.ChykIhct.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.BhexdjVr.js → sankeyDiagram-5OEKKPKP.Z2Y3hkYb.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.C3Rm7dpQ.js → sequenceDiagram-3UESZ5HK.J7JsHWDt.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.CkuMt27u.js → stateDiagram-AJRCARHV.DAPbiCSS.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.Dc_aazUA.js → stateDiagram-v2-BHNVJYJU.D2jvSi0q.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.ja7sUFhH.js → timeline-definition-PNZ67QCA.psW2ci29.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.BxIshX_K.js → vennDiagram-CIIHVFJN.DlILYVmg.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.DfHlC0sh.js → wardleyDiagram-YWT4CUSO.xNWwLJnn.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.DSnhHwCh.js → xychartDiagram-2RQKCTM6.EU_BuH7V.js} +1 -1
- package/web/board-runtime.json +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.BVp-LYi6.js +0 -322
- package/web/_astro/channel.6IFIKBhu.js +0 -1
- package/web/_astro/index.CbNz17Sx.css +0 -1
|
@@ -149,3 +149,20 @@ agent:
|
|
|
149
149
|
# extra workflow folders by concatenating them here (loader merge):
|
|
150
150
|
workflows:
|
|
151
151
|
paths: []
|
|
152
|
+
|
|
153
|
+
# Decision catalogs (feature P / ADR-134): the project layer is always
|
|
154
|
+
# `<cwd>/.spur/decisions` and the shared layer is the installed package's own
|
|
155
|
+
# `config/decisions`, so no config entry is needed to discover the shipped
|
|
156
|
+
# catalogs. `paths` registers extra catalog folders (absolute or
|
|
157
|
+
# project-relative); the first layer wins per file basename (ADR-113 style).
|
|
158
|
+
# `maker` selects the default DecisionMaker for every decision point, and
|
|
159
|
+
# `makers` overrides it per decision id. Built-in makers: typesafe, fm-local,
|
|
160
|
+
# laya-local (laya-local needs Apple Silicon). An unregistered name is a config
|
|
161
|
+
# error, never a silent fallback. Inspect the effective choice with
|
|
162
|
+
# `spur decision status`. `init` never overwrites this file — until you add the
|
|
163
|
+
# keys, the shipped catalog's maker applies (see `status`).
|
|
164
|
+
decisions:
|
|
165
|
+
paths: []
|
|
166
|
+
maker: typesafe
|
|
167
|
+
# makers:
|
|
168
|
+
# task-triage: laya-local
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
|
|
2
|
+
# Decision catalogs for the task pipeline (feature P / task 1092, ADR-134).
|
|
3
|
+
#
|
|
4
|
+
# These entries mirror the inline decide actions that ship in
|
|
5
|
+
# config/workflows/task-pipeline.yaml today — same questions, choices and
|
|
6
|
+
# fallbacks — so their reliability can be measured with `spur decision run`
|
|
7
|
+
# before feature P1 migrates the workflow actions onto them (design §3.5).
|
|
8
|
+
# No workflow references this catalog yet.
|
|
9
|
+
#
|
|
10
|
+
# Resolution: this file ships in the shared layer (the installed package's
|
|
11
|
+
# config/decisions/). A project can override it per basename through
|
|
12
|
+
# .spur/decisions/ or decisions.paths (first layer wins, ADR-113 style).
|
|
13
|
+
version: 1
|
|
14
|
+
|
|
15
|
+
defaults:
|
|
16
|
+
# ADR-125 value, kept over the upstream 0.7 default.
|
|
17
|
+
minConfidence: 0.8
|
|
18
|
+
|
|
19
|
+
decisions:
|
|
20
|
+
task-triage:
|
|
21
|
+
type: choice
|
|
22
|
+
description: Which verification lane does a green-gate diff deserve?
|
|
23
|
+
parameters:
|
|
24
|
+
wbs:
|
|
25
|
+
type: string
|
|
26
|
+
description: Task WBS the diff belongs to.
|
|
27
|
+
criteria:
|
|
28
|
+
low: Small, contained diff — the fast lane is enough.
|
|
29
|
+
standard: Ordinary diff — the standard verification lane applies.
|
|
30
|
+
high: Broad or risky diff — verify with high caution.
|
|
31
|
+
fallback: standard
|
|
32
|
+
|
|
33
|
+
failure-class:
|
|
34
|
+
type: choice
|
|
35
|
+
description: Is a failed quality gate fixable by the repair agent, or should the run stop?
|
|
36
|
+
parameters:
|
|
37
|
+
wbs:
|
|
38
|
+
type: string
|
|
39
|
+
description: Task WBS whose gate failed.
|
|
40
|
+
criteria:
|
|
41
|
+
fix: The failure looks fixable — send it to the repair agent.
|
|
42
|
+
stop: The failure is not mechanically fixable — stop the run for the operator.
|
|
43
|
+
fallback: fix
|
|
44
|
+
|
|
45
|
+
review-failure-class:
|
|
46
|
+
type: choice
|
|
47
|
+
description: Is a non-PASS review fixable by the repair agent, or should the run stop?
|
|
48
|
+
parameters:
|
|
49
|
+
wbs:
|
|
50
|
+
type: string
|
|
51
|
+
description: Task WBS whose review did not certify PASS.
|
|
52
|
+
criteria:
|
|
53
|
+
fix: The findings look fixable — send them to the repair agent.
|
|
54
|
+
stop: The findings are not mechanically fixable — stop the run for the operator.
|
|
55
|
+
fallback: fix
|
|
@@ -76,11 +76,21 @@
|
|
|
76
76
|
"contract": "standard",
|
|
77
77
|
"twin": "residual-scan.mjs"
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"rel": "run-summary.ts",
|
|
81
|
+
"contract": "standard",
|
|
82
|
+
"twin": "run-summary.mjs"
|
|
83
|
+
},
|
|
79
84
|
{
|
|
80
85
|
"rel": "script-root.ts",
|
|
81
86
|
"contract": "standard",
|
|
82
87
|
"twin": "script-root.mjs"
|
|
83
88
|
},
|
|
89
|
+
{
|
|
90
|
+
"rel": "session-timeline.ts",
|
|
91
|
+
"contract": "standard",
|
|
92
|
+
"twin": "session-timeline.mjs"
|
|
93
|
+
},
|
|
84
94
|
{
|
|
85
95
|
"rel": "task-diffstat.ts",
|
|
86
96
|
"contract": "standard",
|
|
@@ -24,6 +24,8 @@ exclude:
|
|
|
24
24
|
# legitimately contains `config/...` documentation / self-references — not
|
|
25
25
|
# runtime paths.
|
|
26
26
|
- "apps/cli/config/**"
|
|
27
|
+
# Desktop stage copies the same generated build-time asset payload beside each binary.
|
|
28
|
+
- "apps/desktop/resources/**"
|
|
27
29
|
rules:
|
|
28
30
|
- id: sp-runtime-path
|
|
29
31
|
description: >
|
|
@@ -2,9 +2,11 @@ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
|
|
|
2
2
|
# Coverage gate — per-file line coverage meets threshold from Bun's lcov output.
|
|
3
3
|
# Absorbed from ts-libs/.spur/rules/quality/coverage-gate.yaml, re-scoped to
|
|
4
4
|
# Spur's monorepo layout:
|
|
5
|
-
# - lcovPath kept at .coverage/lcov.info (Spur's `bun run test:coverage`
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# - lcovPath kept at .coverage/lcov.info (Spur's `bun run test:coverage`
|
|
6
|
+
# writes it via --coverage-dir=.coverage, and `bunfig.toml
|
|
7
|
+
# [test] coverage = true` means a plain `bun run test` writes the same
|
|
8
|
+
# artifact — so a TARGETED `bun test <file>` overwrites it with a partial
|
|
9
|
+
# tracefile, and this rule then judges that partial data)
|
|
8
10
|
# - include expanded to apps/** + packages/** (Spur tests cover both;
|
|
9
11
|
# ts-libs only covers packages/**)
|
|
10
12
|
# - threshold kept at 90 matching bunfig.toml coverageThreshold
|
|
@@ -32,6 +32,10 @@ rules:
|
|
|
32
32
|
- "**/tests/**"
|
|
33
33
|
- "**/*.test.ts"
|
|
34
34
|
|
|
35
|
+
# Electron Node adapter: ts-runtime's streaming handle uses Bun.spawn.
|
|
36
|
+
# Owns the detached process-group handle needed for startup cancellation and quit.
|
|
37
|
+
- "apps/desktop/src/server-process.ts"
|
|
38
|
+
|
|
35
39
|
# Low-level system primitives:
|
|
36
40
|
- "packages/app/src/services/quality-gate.ts" # gate runs `sh -c` with stdout+stderr merged onto ONE fd; ProcessExecutor captures streams separately and cannot reproduce the stream-order contract (task 1006 R1; mirrors the history-anatomy bundling exemptions)
|
|
37
41
|
|
|
@@ -60,16 +64,23 @@ rules:
|
|
|
60
64
|
- "packages/app/src/services/token-ledger-service.ts" # FD byte-window log tailing
|
|
61
65
|
- "packages/app/src/services/token-ledger-watcher.ts" # node:fs watch() live watcher
|
|
62
66
|
- "packages/app/src/services/project-registry.ts" # atomic projects.json persistence
|
|
67
|
+
- "packages/app/src/services/project-server-owner.ts" # atomic mkdir lifetime claim + unique-marker stale recovery; FileSystem has no exclusive mkdir primitive (1082)
|
|
63
68
|
- "packages/app/src/services/slash-commands-service.ts" # synchronous ~/.config/spur/slash_commands.json persistence (mirrors project-registry.ts)
|
|
64
69
|
- "packages/app/src/services/agent-usage-producer.ts" # atomic agent-usage snapshot write (tmp + rename, mirrors project-registry.ts; task 0892 R1)
|
|
65
70
|
- "packages/app/src/services/history-service.ts" # versioned analyze artifact + bounded-errors sidecar + latest.json symlink pointer (task 0474); ts-runtime FileSystem seam has no symlink, so the pointer uses node:fs directly (mirrors project-registry.ts persistence exemption)
|
|
66
71
|
- "packages/app/src/services/history-anatomy.ts" # deterministic history-anatomy cache core (task 1005 R2): fsync'd tmp+rename atomic publish, readdir digest scans and sync report reads must stay byte-stable; bundled standalone for the bare-node plugin twin (mirrors agent-usage-producer.ts / history-service.ts exemptions)
|
|
67
72
|
- "packages/app/src/observability/workflow-run-log-sink.ts" # sync FD append for mid-run tail-able all-in-one run log (task 0426 / feature D2); append() is sync from the observability bus
|
|
73
|
+
- "packages/app/src/observability/agent-run-log.ts" # same primitive as the sink above for the per-run agent stream (task 1076 R1, ADR-132); append() is sync from the agent service's own onOutput hook, and the byte cap needs the FD position it tracks
|
|
68
74
|
- "apps/cli/src/commands/workflow.ts" # FD byte-window tail of the mid-run run log for `workflow trace --follow` streaming (task 0428 / feature D2); readSync at offset over the observability sink's FDs
|
|
69
75
|
- "apps/web/src/modules/discover.ts" # Vite/Astro module scanner fallback under bun test
|
|
70
76
|
- "packages/app/src/services/quality-gate.ts" # gate artifacts (log/findings/receipt) written directly; merged-fd gate log and fsync-free atomic writes must stay byte-stable; bundled standalone for the bare-node plugin twin (task 1006 R1; mirrors history-anatomy.ts)
|
|
71
77
|
- "packages/app/src/services/run-storage.ts" # durable-evidence migration core (task 1025 R4): atomic tmp+rename byte copies with digest reread and atomic manifest publish must stay byte-stable (mirrors agent-usage-producer.ts / project-registry.ts exemptions)
|
|
72
78
|
|
|
79
|
+
# Electron Node adapters cannot load Bun runtime implementations; keep the
|
|
80
|
+
# synchronous existence/directory probes injected for unit testing (desktop contract).
|
|
81
|
+
- "apps/desktop/src/layout.ts"
|
|
82
|
+
- "apps/desktop/src/server-process.ts"
|
|
83
|
+
|
|
73
84
|
# Synchronous bootstrap & path resolution:
|
|
74
85
|
- "packages/config/src/bundled-config.ts" # sync bundledConfigRoot() directory walk
|
|
75
86
|
- "packages/config/src/loader.ts" # sync resolveConfigFile() / schema specifier lookup
|
|
@@ -37,6 +37,9 @@ rules:
|
|
|
37
37
|
# this rule's include scope — scanning generated copies only adds noise
|
|
38
38
|
# (e.g. `id: task-implement-transition` trips the sk- token shape).
|
|
39
39
|
- "apps/cli/config/"
|
|
40
|
+
# Desktop ships the same generated config payload beside each compiled binary.
|
|
41
|
+
# Its source remains outside this source-code rule, just like the CLI bundle.
|
|
42
|
+
- "apps/desktop/resources/"
|
|
40
43
|
# `apps/cli/plugins/` is the same kind of gitignored build:bundle output — a staged
|
|
41
44
|
# npm copy of `plugins/`, itself outside the include scope. Minified generated libs
|
|
42
45
|
# there trip the api-key shape (0976: HEAD's inline-run.generated.mjs fires too).
|
|
@@ -19,6 +19,21 @@
|
|
|
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
|
+
# Review-failure routing (session finding after 1088): `review` had no outgoing edge for a
|
|
31
|
+
# FAIL verdict, so a failing review could only be remediated by driving the graph by hand
|
|
32
|
+
# (re-entering `test` and hand-emitting rows). The review stage now derives
|
|
33
|
+
# `.spur/run/<wbs>-review.status` from its own answer file (fail-closed to FAIL), and a FAIL
|
|
34
|
+
# routes through `review-fail-triage` — the review-side twin of `test-fail-triage` (0943) —
|
|
35
|
+
# into the SAME bounded fix budget, so remediation stays on-graph and bounded.
|
|
36
|
+
#
|
|
22
37
|
# Vars (passed as a JSON object via `--vars`):
|
|
23
38
|
# wbs — task WBS (required)
|
|
24
39
|
# profile — "auto" skips HITL approve (R4)
|
|
@@ -36,7 +51,19 @@ kind: state-machine
|
|
|
36
51
|
name: task-pipeline
|
|
37
52
|
# 0772 R2: explicit identity tag. Set only after the proof failure-path tests
|
|
38
53
|
# passed; the engine treats unversioned external definitions as supported.
|
|
39
|
-
|
|
54
|
+
# v4 (session finding after 1088): the completion gate reads the verifier's confidence level and
|
|
55
|
+
# the graph routes a non-PASS review into bounded remediation — both are contract changes, so the
|
|
56
|
+
# identity moves with them.
|
|
57
|
+
# v5 (task 1077's inline run, 2026-10-06): the verify verdict action is explicitly `onError:
|
|
58
|
+
# continue`. `task verdict` exits non-zero on any non-PASS verdict BY DESIGN (1003 R2) — that is
|
|
59
|
+
# data for the verify guards, not a state failure. Under the engine's default 'fail' policy
|
|
60
|
+
# (`resolveOnErrorPolicy: action ?? workflowDefault ?? runOption ?? 'fail'`) the state sequence
|
|
61
|
+
# halted on that exit code and `lifecycle.fail('verify')` finalized the run before any transition
|
|
62
|
+
# guard was evaluated, which made the declared `verify → test-fix` "repairable non-PASS" lane
|
|
63
|
+
# UNREACHABLE: a non-PASS verify could only end the run failed. `test-fix` also gained the
|
|
64
|
+
# review-lane evidence projection (see its onEnter) so the repair hop is not fed an empty findings
|
|
65
|
+
# list when the failing hop was `review-fail-triage` rather than the quality gate.
|
|
66
|
+
version: "5"
|
|
40
67
|
description: "Standard task pipeline: precheck → implement → quality-gate (test/fix/recheck) → review → approve → verify → record → done"
|
|
41
68
|
# Task entity lifecycle (owned by task-lifecycle.yaml):
|
|
42
69
|
# normal: backlog → todo → wip → testing → done
|
|
@@ -149,6 +176,14 @@ vars:
|
|
|
149
176
|
# Escalation counter: .spur/run/<wbs>-escalation-count. Default 2 = two answered
|
|
150
177
|
# questions; a third pause routes to failed with a report note.
|
|
151
178
|
maxEscalations: "2"
|
|
179
|
+
# Operator acknowledgement of a LOW-confidence certification (session finding after 1088).
|
|
180
|
+
# The verify answer's `Confidence:` line is captured into the verdict artifact; a LOW (or
|
|
181
|
+
# absent) level fails the completion guards unless this is "true", because a PASS the
|
|
182
|
+
# verifier would not stand behind is an operator risk decision, not a mechanical one.
|
|
183
|
+
# Set per run: `--vars '{"ackLowConfidence":"true"}'` (and export it on the inline path).
|
|
184
|
+
# Deliberately NOT settable from the task file or the verifier's own answer: the point is
|
|
185
|
+
# that a second party, not the producer, accepts the residual uncertainty.
|
|
186
|
+
ackLowConfidence: ""
|
|
152
187
|
# Runtime-written, 0933: the escalate hop's file.read.into-var fills this from
|
|
153
188
|
# .spur/run/<wbs>-question.md; the hitl.input prompt below references it. Declared
|
|
154
189
|
# here (empty) so the static var-reference validator sees the template source.
|
|
@@ -438,6 +473,17 @@ states:
|
|
|
438
473
|
options:
|
|
439
474
|
command: >-
|
|
440
475
|
printf '%s\n' "$(( $(cat ".spur/run/$wbs-test-fix-attempt" 2>/dev/null || echo 0) + 1 ))" > ".spur/run/$wbs-test-fix-attempt"; [ -f ".spur/run/$wbs-verdict.json" ] && echo '--- verify verdict (remediation input, task 0703 R4) ---' >> ".spur/run/$wbs-test-gate.log" && cat ".spur/run/$wbs-verdict.json" >> ".spur/run/$wbs-test-gate.log"; [ -f ".spur/run/$wbs-residuals.json" ] && echo '--- residual artifact (F96 fix targets; deferrals go to residual-deferrals.json, P3/markers only) ---' >> ".spur/run/$wbs-test-gate.log" && cat ".spur/run/$wbs-residuals.json" >> ".spur/run/$wbs-test-gate.log"; exit 0
|
|
476
|
+
# Review-lane input (v5, task 1077 run): `review-fail-triage` routes a non-PASS review
|
|
477
|
+
# into this same bounded repair hop, but it stages no review evidence — the fixer then
|
|
478
|
+
# received a GREEN gate log and an empty findings list, so the review finding it exists
|
|
479
|
+
# to repair was invisible to it. Project the reviewer's answer into the same log the
|
|
480
|
+
# other lanes use, and only on the review lane (the decision file exists only after
|
|
481
|
+
# `review-fail-triage`). Own action, not an append to the one above: ADR-115's 800-char
|
|
482
|
+
# shell cap is already 602 chars there.
|
|
483
|
+
- kind: shell
|
|
484
|
+
options:
|
|
485
|
+
command: >-
|
|
486
|
+
[ -f ".spur/run/$wbs-review-failure-class.decision" ] && [ -f ".spur/run/$__runId-review-answer.txt" ] && echo '--- review verdict (remediation input, review lane) ---' >> ".spur/run/$wbs-test-gate.log" && cat ".spur/run/$__runId-review-answer.txt" >> ".spur/run/$wbs-test-gate.log"; exit 0
|
|
441
487
|
# R3 (0482): project the extracted gate anchors into a var so the dispatch input
|
|
442
488
|
# can NAME the failing file:line, not merely point at a log. A vars template cannot
|
|
443
489
|
# run a shell, so the read is an action, not an inline `$(cat ...)` substitution.
|
|
@@ -611,10 +657,43 @@ states:
|
|
|
611
657
|
# verify stamp marks review `completed` only when this marker equals the current digest;
|
|
612
658
|
# otherwise `skipped` (an honest downgrade, never a fake completed), and the bound
|
|
613
659
|
# `record` registration refuses a skipped review.
|
|
660
|
+
# Session finding after 1088: the review VERDICT is read straight out of the reviewer's
|
|
661
|
+
# own answer file by the review → * guards below, so this stage needs no extra artifact
|
|
662
|
+
# and no extra action (ADR-115 legibility cap).
|
|
614
663
|
- kind: shell
|
|
615
664
|
options:
|
|
616
665
|
command: 'mkdir -p .spur/run; printf "%s" "$proofDigest" > ".spur/run/$__runId-review-proof.digest"; exit 0'
|
|
617
666
|
|
|
667
|
+
# ── review-fail-triage (session finding after 1088) ────────────────────────
|
|
668
|
+
# A review that reports FAIL used to have no outgoing edge: the graph could not see the
|
|
669
|
+
# verdict and nothing consumed it, so remediating a failing review meant driving the
|
|
670
|
+
# states by hand. This state is the review-side twin of `test-fail-triage` (0943 R3):
|
|
671
|
+
# the deterministic classifier routes the failure into the SAME bounded fix budget
|
|
672
|
+
# (`.spur/run/<wbs>-test-fix-attempt` against `qualityGateMaxFixAttempts`), and the fix
|
|
673
|
+
# re-enters quality → review → verify on a freshly captured digest. The `decide` action
|
|
674
|
+
# itself always runs (the engine has no onEnter conditionals); with
|
|
675
|
+
# `workflow.decideDecisionMaker` off it degrades to its declared default.
|
|
676
|
+
- id: review-fail-triage
|
|
677
|
+
description: >-
|
|
678
|
+
Deterministic router for a review that did NOT certify PASS (session finding after 1088).
|
|
679
|
+
`decide review-failure-class` reads the reviewer's answer and the task spec and routes:
|
|
680
|
+
fix → the shared test-fix hop, stop → failed with terminalReason failed-check. A
|
|
681
|
+
missing/corrupt decision fails closed to failed-check.
|
|
682
|
+
onEnter:
|
|
683
|
+
- kind: decide
|
|
684
|
+
options:
|
|
685
|
+
id: review-failure-class
|
|
686
|
+
method: choice
|
|
687
|
+
question: >-
|
|
688
|
+
The review did not certify PASS (FAIL or PARTIAL). Is the finding fixable by the
|
|
689
|
+
repair agent, or should the run stop here for the operator?
|
|
690
|
+
choices: [fix, stop]
|
|
691
|
+
default: fix
|
|
692
|
+
evidence:
|
|
693
|
+
- .spur/run/${vars.__runId}-review-answer.txt
|
|
694
|
+
- ${vars.taskSpecPath}
|
|
695
|
+
resultFile: .spur/run/${vars.wbs}-review-failure-class.decision
|
|
696
|
+
|
|
618
697
|
- id: approve
|
|
619
698
|
description: >
|
|
620
699
|
Human-in-the-loop approval gate. Under `profile=auto` this state is never entered
|
|
@@ -675,8 +754,26 @@ states:
|
|
|
675
754
|
# (d) `spur task verdict` owns the answer lint (task 1003 R2) — the shell below
|
|
676
755
|
# fails closed when the verifier's answer is malformed, before any verdict artifact.
|
|
677
756
|
- kind: shell
|
|
757
|
+
# `task verdict` exits 1 on a non-PASS verdict by design (1003 R2). The `continue`
|
|
758
|
+
# policy keeps that exit code as recorded evidence (the action row is still `failed`)
|
|
759
|
+
# while letting the state finish its remaining actions and reach the guards below;
|
|
760
|
+
# without it the default 'fail' policy halts the run here and `verify → test-fix`
|
|
761
|
+
# (the declared bounded remediation lane) can never fire (v5, task 1077 run).
|
|
762
|
+
onError: continue
|
|
678
763
|
options:
|
|
679
764
|
command: "$spurBin task verdict $wbs --from-answer .spur/run/$wbs-verify-answer.txt"
|
|
765
|
+
# Session finding after 1088: the verifier's confidence level becomes a `confidence` check
|
|
766
|
+
# row (warn unless HIGH) and a gate-log line, so the level the completion guards enforce is
|
|
767
|
+
# visible in the artifact and the log — not only in the answer file. This is its own action
|
|
768
|
+
# because the proof-binding stamp below must stay the state's LAST action AND under the
|
|
769
|
+
# ADR-115 800-char shell cap.
|
|
770
|
+
- kind: shell
|
|
771
|
+
options:
|
|
772
|
+
command: >-
|
|
773
|
+
V=".spur/run/$wbs-verdict.json"; [ -f "$V" ] || exit 0;
|
|
774
|
+
jq --arg ack "$ackLowConfidence" '. + {checks: ((.checks // []) | map(select(.name != "confidence"))) + [{name: "confidence", status: (if (.confidence // "LOW") == "HIGH" 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";
|
|
775
|
+
printf 'confidence: %s (ack=%s)\n' "$(jq -r '.confidence // "LOW (absent)"' "$V")" "$ackLowConfidence" >> ".spur/run/$wbs-test-gate.log";
|
|
776
|
+
exit 0
|
|
680
777
|
# (e) one jq mutation binds the verdict to the proof digest (0703 R3; runId 0730 §B.2 /
|
|
681
778
|
# 0757 R4; definitionDigest 0759 R5; honest review stamp 0785 R4; soft action + hard guard).
|
|
682
779
|
- kind: shell
|
|
@@ -1018,21 +1115,73 @@ transitions:
|
|
|
1018
1115
|
description: Failure-class decision missing/corrupt — stop at failed.
|
|
1019
1116
|
guard:
|
|
1020
1117
|
kind: always
|
|
1021
|
-
# ── review
|
|
1022
|
-
#
|
|
1023
|
-
#
|
|
1024
|
-
#
|
|
1025
|
-
|
|
1118
|
+
# ── review-failure routing (session finding after 1088): the review-side twin of the
|
|
1119
|
+
# failure-class router above — stop first, then the shared attempt cap, then the fix lane,
|
|
1120
|
+
# then the fail-closed defense. The counter is the SAME one the quality-gate loop uses, so a
|
|
1121
|
+
# review FAIL cannot buy extra attempts and the iteration bound stays finite.
|
|
1122
|
+
- from: review-fail-triage
|
|
1123
|
+
to: failed
|
|
1124
|
+
terminalReason: failed-check
|
|
1125
|
+
description: Review failure class stop — the run terminates at failed, never bypassed.
|
|
1126
|
+
guard:
|
|
1127
|
+
kind: shell
|
|
1128
|
+
options:
|
|
1129
|
+
command: >-
|
|
1130
|
+
jq -e '.value == "stop"' ".spur/run/$wbs-review-failure-class.decision" >/dev/null 2>&1
|
|
1131
|
+
- from: review-fail-triage
|
|
1132
|
+
to: failed
|
|
1133
|
+
terminalReason: retry-exhausted
|
|
1134
|
+
description: Attempt cap reached — qualityGateMaxFixAttempts bounds the review repair lane.
|
|
1135
|
+
guard:
|
|
1136
|
+
kind: shell
|
|
1137
|
+
options:
|
|
1138
|
+
command: >-
|
|
1139
|
+
fix_attempts="$(cat .spur/run/$wbs-test-fix-attempt 2>/dev/null || echo 0)";
|
|
1140
|
+
test "$fix_attempts" -ge "$qualityGateMaxFixAttempts"
|
|
1141
|
+
- from: review-fail-triage
|
|
1142
|
+
to: test-fix
|
|
1143
|
+
description: Review failure class fix and under the cap — the shared bounded repair hop.
|
|
1144
|
+
guard:
|
|
1145
|
+
kind: shell
|
|
1146
|
+
options:
|
|
1147
|
+
command: >-
|
|
1148
|
+
jq -e '.value == "fix"' ".spur/run/$wbs-review-failure-class.decision" >/dev/null 2>&1
|
|
1149
|
+
# Defense: missing/corrupt review-failure decision — fail closed instead of silently repairing.
|
|
1150
|
+
- from: review-fail-triage
|
|
1151
|
+
to: failed
|
|
1152
|
+
terminalReason: failed-check
|
|
1153
|
+
description: Review-failure decision missing/corrupt — stop at failed.
|
|
1154
|
+
guard:
|
|
1155
|
+
kind: always
|
|
1156
|
+
# ── review routing: FAIL → bounded remediation; PASS → approve or the auto-skip (R4) ──
|
|
1157
|
+
# Declaration order matters and is FAIL-CLOSED: the two PASS edges each demand the reviewer's
|
|
1158
|
+
# own `Verdict: PASS` line, and the catch-all sends EVERYTHING ELSE (FAIL, a missing answer, an
|
|
1159
|
+
# unparseable one) into `review-fail-triage`. Before this, a FAIL review had no outgoing edge at
|
|
1160
|
+
# all — the graph could not see the verdict, so remediation meant driving states by hand
|
|
1161
|
+
# (session finding after 1088). The reviewer writes `Verdict: PASS|FAIL` in its answer; both
|
|
1162
|
+
# plain and bold forms are accepted. Under `profile=auto` the approve gate is skipped, so the
|
|
1163
|
+
# PASS+auto edge is tried first and the interactive PASS edge second.
|
|
1026
1164
|
- from: review
|
|
1027
1165
|
to: verify
|
|
1028
|
-
description: profile=auto — skip the human approval gate
|
|
1166
|
+
description: profile=auto and the review certified PASS — skip the human approval gate.
|
|
1029
1167
|
guard:
|
|
1030
1168
|
kind: shell
|
|
1031
1169
|
options:
|
|
1032
|
-
command:
|
|
1170
|
+
command: >-
|
|
1171
|
+
test "$profile" = auto &&
|
|
1172
|
+
grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt"
|
|
1033
1173
|
- from: review
|
|
1034
1174
|
to: approve
|
|
1035
|
-
description: Review
|
|
1175
|
+
description: Review certified PASS — gate on human approval before verification.
|
|
1176
|
+
guard:
|
|
1177
|
+
kind: shell
|
|
1178
|
+
options:
|
|
1179
|
+
command: grep -qiE '^[[:space:]]*\**Verdict:\** *PASS' ".spur/run/$__runId-review-answer.txt"
|
|
1180
|
+
- from: review
|
|
1181
|
+
to: review-fail-triage
|
|
1182
|
+
description: >-
|
|
1183
|
+
No PASS in the reviewer's answer (FAIL, PARTIAL, missing, or unparseable — fail closed) —
|
|
1184
|
+
classify the failure and route it into the bounded repair hop instead of dead-ending the run.
|
|
1036
1185
|
guard:
|
|
1037
1186
|
kind: always
|
|
1038
1187
|
|
|
@@ -1069,19 +1218,23 @@ transitions:
|
|
|
1069
1218
|
# The verify step emits .spur/run/<wbs>-verdict.json with a required proof block (task 0703 R3/R5).
|
|
1070
1219
|
# Only `verdict: PASS` PLUS a proof block whose digest — top level and every named stage — equals
|
|
1071
1220
|
# the captured `proofDigest` clears the gate to `record`; any non-PASS, a missing file, malformed
|
|
1072
|
-
# JSON, or missing/mismatched proof evidence does not.
|
|
1221
|
+
# JSON, or missing/mismatched proof evidence does not. The verifier's confidence level is part of
|
|
1222
|
+
# that certification (session finding after 1088): a PASS the verifier itself marked LOW — or left
|
|
1223
|
+
# unstated — clears the gate only when the operator accepted it with
|
|
1224
|
+
# `--vars '{"ackLowConfidence":"true"}'`. Declaration order: PASS+proof guard FIRST,
|
|
1073
1225
|
# then the bounded remediation route (R4), then the always catch-all so a PASS verdict with a
|
|
1074
1226
|
# missing/malformed proof block still terminates at `failed` instead of hanging the state.
|
|
1075
1227
|
- from: verify
|
|
1076
1228
|
to: record
|
|
1077
|
-
description: Verification verdict is PASS
|
|
1229
|
+
description: Verification verdict is PASS, its proof block names the captured digest on every stage, and any LOW confidence was operator-acknowledged — record results and proceed to done.
|
|
1078
1230
|
guard:
|
|
1079
1231
|
# (one jq -e predicate) PASS verdict; proof, quality-gate, review and verification digests
|
|
1080
|
-
# equal to proofDigest; review completed; matching run id and definition digest (0703 R5, 0785 R4)
|
|
1232
|
+
# equal to proofDigest; review completed; matching run id and definition digest (0703 R5, 0785 R4);
|
|
1233
|
+
# confidence HIGH/MEDIUM, or LOW/absent with the operator's ack (session finding after 1088).
|
|
1081
1234
|
kind: shell
|
|
1082
1235
|
options:
|
|
1083
1236
|
command: >-
|
|
1084
|
-
jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" '
|
|
1237
|
+
jq -e --arg d "$proofDigest" --arg r "$__runId" --arg dd "$__definitionDigest" --arg ack "$ackLowConfidence" '
|
|
1085
1238
|
.verdict == "PASS"
|
|
1086
1239
|
and (.proof.digest // "") == $d
|
|
1087
1240
|
and (.proof.stages.qualityGate.digest // "") == $d
|
|
@@ -1090,6 +1243,7 @@ transitions:
|
|
|
1090
1243
|
and (.proof.stages.verification.digest // "") == $d
|
|
1091
1244
|
and (.proof.runId // "") == $r
|
|
1092
1245
|
and (.proof.definitionDigest // "") == $dd
|
|
1246
|
+
and ((.confidence // "LOW") != "LOW" or $ack == "true")
|
|
1093
1247
|
' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
|
|
1094
1248
|
- from: verify
|
|
1095
1249
|
to: test-fix
|
|
@@ -1117,11 +1271,12 @@ transitions:
|
|
|
1117
1271
|
# ── done gate: record → done/failed gated on `spur task check` (ADR-026 amendment 2026-06-23)
|
|
1118
1272
|
# PLUS the proof-block re-assertion (task 0703 R5): the verdict artifact must still be PASS and
|
|
1119
1273
|
# still name the captured digest — a forged or mutated completion artifact fails closed here.
|
|
1274
|
+
# PLUS the confidence re-assertion (session finding after 1088): the same ack rule as verify →
|
|
1275
|
+
# record, re-read from the artifact so a mutation between the two boundaries cannot slip through.
|
|
1120
1276
|
# Declaration order: pass guard first.
|
|
1121
1277
|
- from: record
|
|
1122
1278
|
to: done
|
|
1123
|
-
description: Task check passed
|
|
1124
|
-
# (warn) 5 commands: named verdict + proof digest reads after the task check (legibility, 0874).
|
|
1279
|
+
description: Task check passed, the verdict proof block still names the captured digest, and any LOW confidence was acknowledged — certify done.
|
|
1125
1280
|
guard:
|
|
1126
1281
|
kind: shell
|
|
1127
1282
|
options:
|
|
@@ -1130,11 +1285,16 @@ transitions:
|
|
|
1130
1285
|
# the CLI's own target-aware `--no-lifecycle` backstop (F92 R3). No `#`
|
|
1131
1286
|
# comments inside the folded scalar: `>-` joins same-indent lines into
|
|
1132
1287
|
# one shell line.
|
|
1288
|
+
# Two logical commands, deliberately (ADR-115): the `task check` projection plus
|
|
1289
|
+
# ONE jq predicate re-asserting the whole completion contract — PASS verdict, the
|
|
1290
|
+
# captured proof digest, and the confidence rule (session finding after 1088).
|
|
1133
1291
|
command: >-
|
|
1134
1292
|
$spurBin task check $wbs --as done &&
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1293
|
+
jq -e --arg p "$proofDigest" --arg ack "$ackLowConfidence" '
|
|
1294
|
+
.verdict == "PASS"
|
|
1295
|
+
and ((.proof.digest // "") == $p)
|
|
1296
|
+
and ((.confidence // "LOW") != "LOW" or $ack == "true")
|
|
1297
|
+
' ".spur/run/$wbs-verdict.json" >/dev/null 2>&1
|
|
1138
1298
|
- from: record
|
|
1139
1299
|
to: failed
|
|
1140
1300
|
terminalReason: failed-check
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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",
|
|
@@ -57,14 +57,14 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@commander-js/extra-typings": "^14.0.0",
|
|
60
|
-
"@gobing-ai/ts-db": "^0.5.
|
|
61
|
-
"@gobing-ai/ts-ai-runner": "^0.5.
|
|
62
|
-
"@gobing-ai/ts-dual-workflow-engine": "^0.5.
|
|
63
|
-
"@gobing-ai/ts-infra": "^0.5.
|
|
64
|
-
"@gobing-ai/ts-llm-jsonl-importer": "^0.5.
|
|
65
|
-
"@gobing-ai/ts-rule-engine": "^0.5.
|
|
66
|
-
"@gobing-ai/ts-runtime": "^0.5.
|
|
67
|
-
"@gobing-ai/ts-utils": "^0.5.
|
|
60
|
+
"@gobing-ai/ts-db": "^0.5.16",
|
|
61
|
+
"@gobing-ai/ts-ai-runner": "^0.5.16",
|
|
62
|
+
"@gobing-ai/ts-dual-workflow-engine": "^0.5.16",
|
|
63
|
+
"@gobing-ai/ts-infra": "^0.5.16",
|
|
64
|
+
"@gobing-ai/ts-llm-jsonl-importer": "^0.5.16",
|
|
65
|
+
"@gobing-ai/ts-rule-engine": "^0.5.16",
|
|
66
|
+
"@gobing-ai/ts-runtime": "^0.5.16",
|
|
67
|
+
"@gobing-ai/ts-utils": "^0.5.16",
|
|
68
68
|
"@types/bun": "1.3.14",
|
|
69
69
|
"@types/figlet": "^1.7.0",
|
|
70
70
|
"@types/node-notifier": "8.0.5",
|
package/plugins/sp/README.md
CHANGED
|
@@ -273,6 +273,7 @@ plugins/sp/
|
|
|
273
273
|
├── commands/ # Slash-command wrappers — the SSOT (hand-editable thin wrappers; see Commands below)
|
|
274
274
|
├── agents/ # 4 specialist subagents (expert-spur, super-coder, super-planner, super-reviewer)
|
|
275
275
|
├── hooks/ # hooks.json + task-write-guard.{ts,test.ts} + context-{session-start,post-tool,session-stop}.ts
|
|
276
|
+
│ # + agent-lifecycle.{ts,test.ts} + fleet-guest-stop.{ts,test.ts} (fleet member/guest hooks)
|
|
276
277
|
│ # + careful-guard.{ts,test.ts} + context-hooks.test.ts + token-estimate.test.ts
|
|
277
278
|
│ # + shared policy modules: agent-hint.ts, destructive-policy.{ts,test.ts}, task-file-policy.{ts,test.ts}
|
|
278
279
|
│ # + pi/guard-extension.{ts,test.ts} (plugin.json `extensions.pi` entry point)
|
|
@@ -342,6 +343,7 @@ surface or run one workflow. All skills target the same five core platforms: `cl
|
|
|
342
343
|
| `reverse-engineering` | 1.1 | Codebase analysis / HLD generation / audit — depth-driven reverse engineering with orthogonal mode, focus, and format controls; backs `/sp:dev-reverse` |
|
|
343
344
|
| `issue-finding` | 2.0 | Session-log forensics — multi-source discovery, bottleneck ranking, optional topic focus, CLI-gated fix task generation; **legacy path** — superseded by `history-anatomy` for indexed reporting; backs no current command; directly invocable as sp:issue-finding |
|
|
344
345
|
| `conflict-finding` | 1.0 | Authority-aware semantic audit — four-pillar (source/task/feature/authority) conflict discovery, claim-specific authority resolution, reproducible evidence, confirmed owner-routed remediation; backs `/sp:dev-find-conflict` |
|
|
346
|
+
| `fleet-join` | 1.0 | Guest fleet occupancy — join as a live guest occupant, loop `spur agent wait --inbox` to pull work, reply through `spur message reply`, then leave; G73 (task 1081) |
|
|
345
347
|
| `next-feature` | 1.0 | Prompt-first feature frontier prioritizer — sync-first precondition, B3 actionability gate (cited, never restated), tiered rubric over measured signals, D1–D4 defect proposals conforming to the restructure map schema; backs `/sp:dev-find-next` |
|
|
346
348
|
| `pr-reviewing` | 1.0 | GitHub Codex PR review — PR prepare/reuse, `@codex review` request with per-HEAD dedupe, bounded polling, findings normalization, validated fix + re-review; spine SSOT `pr-review.yaml` + `scripts/pr-reviewing.ts`; backs `/sp:dev-pr-review` |
|
|
347
349
|
| `indexed-context` | 1.0 | Cross-agent project context — anatomy/learnings/pitfalls/buglog/memory in `.spur/context/`; hook-tracked token-ledger; graceful degradation on agents without hooks |
|
|
@@ -473,13 +475,16 @@ the agent provides an isolated context window.
|
|
|
473
475
|
#### 4. Hooks (`hooks/`)
|
|
474
476
|
|
|
475
477
|
Event-driven enforcement that runs automatically without user invocation. `hooks.json` registers
|
|
476
|
-
|
|
478
|
+
six handlers across seven events:
|
|
477
479
|
|
|
478
480
|
| Event | Matcher | Handler | Timeout |
|
|
479
481
|
| -------------- | ------------------------------------- | ---------------------------------------------- | ------- |
|
|
480
482
|
| `PreToolUse` | `Write\|Edit` | `superskill hook run sp task-write-guard` | 10s |
|
|
481
483
|
| `PostToolUse` | `Bash\|Grep\|Glob\|Read\|Write\|Edit` | `superskill hook run sp context-post-tool` | 10s |
|
|
482
484
|
| `SessionStart` | — | `superskill hook run sp context-session-start` | 15s |
|
|
485
|
+
| `SessionStart`, `UserPromptSubmit`, `Stop` | — | `superskill hook run sp agent-lifecycle` | 5s |
|
|
486
|
+
| `Notification` | `permission_prompt` | `superskill hook run sp agent-lifecycle` | 5s |
|
|
487
|
+
| `Stop` | — | `superskill hook run sp fleet-guest-stop` | 10s |
|
|
483
488
|
| `SessionEnd` | — | `superskill hook run sp context-session-stop` | 15s |
|
|
484
489
|
|
|
485
490
|
**Write guard.** The `PreToolUse` hook fires on every `Write`/`Edit` tool call and checks whether
|
|
@@ -493,6 +498,11 @@ estimates the token cost of each matched tool call and appends it to `.spur/cont
|
|
|
493
498
|
(with redaction of sensitive argument fields), `context-session-start` seeds the indexed-context
|
|
494
499
|
hint on first launch, and `context-session-stop` closes out the session record.
|
|
495
500
|
|
|
501
|
+
**Fleet hooks (1080/1081).** `agent-lifecycle` reports member state in the background via
|
|
502
|
+
`spur agent report --state working|idle|blocked` (a permission prompt is `blocked`) — only when
|
|
503
|
+
`SPUR_SPEC_ID` is set, so outside a fleet it makes no call. `fleet-guest-stop` delivers pending
|
|
504
|
+
inbox work to a session joined as a fleet guest at turn end; any other session passes through.
|
|
505
|
+
|
|
496
506
|
**Available but unwired:** `careful-guard.ts` ships in `hooks/` (with tests) as an opt-in
|
|
497
507
|
`PreToolUse` guard that asks before destructive shell commands (`rm -rf`, `DROP TABLE`,
|
|
498
508
|
`git push --force`, …) — it is **not** registered in `hooks.json`. Fail-open by contract; escape
|
|
@@ -511,6 +521,7 @@ hold `SKILL.md` and prompt-side companions only.
|
|
|
511
521
|
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
512
522
|
| `hooks/task-write-guard.ts` | Compatibility shim for older installs that still execute the script path directly. Forwards stdin to the stable PATH command `superskill hook run sp task-write-guard`, mirrors parseable PreToolUse decisions, and fails open if the runtime is unavailable. Performs no source-tree CLI lookup. |
|
|
513
523
|
| `hooks/context-*.ts` | Runtime for the three registered context hooks (session-start, post-tool, session-stop) — token-cost estimation + ledger append for `sp:indexed-context` |
|
|
524
|
+
| `hooks/{agent-lifecycle,fleet-guest-stop}.ts` | Fleet hooks (1080/1081): member lifecycle reports via `spur agent report`; turn-end inbox delivery to joined guests |
|
|
514
525
|
| `hooks/careful-guard.ts` | Opt-in destructive-command guard (unwired — see Hooks above) |
|
|
515
526
|
| `scripts/batch-preflight.ts` | Pure TABLE A STOP evaluation for `super-planner` — skip doomed pipeline launches without spawning a Skill subprocess; recovery hints map stuck statuses to a single `/sp:dev-*` hop |
|
|
516
527
|
| `scripts/workflow-step-profile.ts` | Thin glue over the generated lib bundle (`lib/step-profile.generated.mjs` from `packages/app/src/workflow/step-profile.ts`) — read-only step profile from `spur workflow trace`: per node and action-kind durations, idle gaps, session mode and `cacheHit` coverage, plus the ADR-115 cache-window flags `sp:spur-doctor` turns into workflow-optimization proposals |
|
|
@@ -518,6 +529,8 @@ hold `SKILL.md` and prompt-side companions only.
|
|
|
518
529
|
| `scripts/dogfood-testing/validate-report.ts` | Pure `validateReport(md)` — footer-mandatory + 7-check finalize-or-abort contract with stable error codes |
|
|
519
530
|
| `scripts/daily-summary/{daily-summary,logger}.ts` | ccusage + git-history orchestration helpers for `sp:daily-summary` |
|
|
520
531
|
| `scripts/task-diffstat.ts` | 0943 triage-lane diffstat producer — numstat + untracked scan vs the run base; writes `<wbs>-diffstat.json` with the sensitive-path flag; fails safe (sensitive) |
|
|
532
|
+
| `scripts/run-summary.ts` | Measured execution summary `/sp:dev-run` / `/sp:dev-runall` print by default (`--no-summary` skips) — windows the host transcript by `spur workflow progress` attempt timestamps; per stage/run time, wait, tool calls, total / non-cached tokens; `n/a` for subprocess windows |
|
|
533
|
+
| `scripts/session-timeline.ts` | Measured Time/Wait/Token evidence for `sp:session-review` — reads the active Claude Code transcript read-only, one segment per operator prompt, usage deduplicated by message id, tokens split total / non-cached; `{available:false}` exit 0 when no transcript |
|
|
521
534
|
| `scripts/commands/validate-flag-contracts.ts` | Mechanical consistency gate — compares flag claims across command files, flag-glossary, cross-cutting, dev-operations, and ADR; reports disagreements |
|
|
522
535
|
| `*.test.ts` | Unit suites — in `hooks/` for guards, in `tests/<skill>/` per ADR-031 pairing |
|
|
523
536
|
|