@gobing-ai/spur 0.3.95 → 0.3.97
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/plugin-scripts.json +0 -54
- package/config/rules/boundary/sp-script-placement.yaml +19 -0
- package/config/rules/strict/runtime-boundaries.yaml +6 -0
- package/config/rules/structure/test-location.yaml +2 -0
- package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +1 -1
- package/config/rules/typescript/output-boundaries.yaml +15 -2
- package/config/script-placement-baseline.json +51 -0
- package/config/templates/AGENTS.md +3 -3
- package/config/workflows/feature-verification.yaml +1 -1
- package/config/workflows/history-anatomy.yaml +23 -11
- package/config/workflows/idea-pipeline.yaml +80 -85
- package/config/workflows/pr-review.yaml +18 -9
- package/config/workflows/task-pipeline.yaml +42 -95
- package/config/workflows/wrapup-pipeline.yaml +91 -38
- package/package.json +2 -2
- package/plugins/sp/README.md +14 -10
- package/plugins/sp/agents/super-reviewer.md +43 -18
- package/plugins/sp/commands/dev-fixgha.md +83 -0
- package/plugins/sp/commands/dev-gitmsg.md +8 -6
- package/plugins/sp/commands/dev-gtd.md +2 -2
- package/plugins/sp/commands/dev-idea.md +22 -12
- package/plugins/sp/commands/dev-job-dump.md +29 -0
- package/plugins/sp/commands/dev-job-resume.md +29 -0
- package/plugins/sp/commands/dev-plan.md +8 -9
- package/plugins/sp/commands/dev-review.md +22 -13
- package/plugins/sp/commands/dev-verifyall.md +1 -1
- package/plugins/sp/commands/spur-init.md +2 -2
- package/plugins/sp/lib/history-anatomy.generated.d.mts +112 -0
- package/plugins/sp/lib/history-anatomy.generated.mjs +686 -0
- package/plugins/sp/lib/idea-handoff.generated.mjs +5 -4
- package/plugins/sp/lib/inline-run.generated.d.mts +11 -0
- package/plugins/sp/lib/inline-run.generated.mjs +39 -13
- package/plugins/sp/lib/quality-gate.generated.d.mts +104 -0
- package/plugins/sp/lib/quality-gate.generated.mjs +445 -0
- package/plugins/sp/lib/residual-scan.generated.d.mts +63 -0
- package/plugins/sp/lib/residual-scan.generated.mjs +226 -0
- package/plugins/sp/lib/spur-bin.ts +36 -0
- package/plugins/sp/lib/step-profile.generated.d.mts +71 -0
- package/plugins/sp/lib/step-profile.generated.mjs +174 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +3 -3
- package/plugins/sp/scripts/feature-verification-steps.mjs +14 -1
- package/plugins/sp/scripts/feature-verification-steps.ts +14 -1
- package/plugins/sp/scripts/history-anatomy-cache.mjs +20 -19
- package/plugins/sp/scripts/history-anatomy-cache.ts +23 -928
- package/plugins/sp/scripts/inline-run-setup.mjs +85 -320
- package/plugins/sp/scripts/inline-run-setup.ts +104 -667
- package/plugins/sp/scripts/quality-gate.mjs +46 -24
- package/plugins/sp/scripts/quality-gate.ts +13 -659
- package/plugins/sp/scripts/residual-scan.mjs +179 -174
- package/plugins/sp/scripts/residual-scan.ts +125 -517
- package/plugins/sp/scripts/script-root.mjs +5 -1
- package/plugins/sp/scripts/script-root.ts +5 -1
- package/plugins/sp/scripts/workflow-step-profile.mjs +25 -17
- package/plugins/sp/scripts/workflow-step-profile.ts +21 -315
- package/plugins/sp/scripts/wrapup-drift-probe.mjs +8 -2
- package/plugins/sp/scripts/wrapup-drift-probe.ts +3 -2
- package/plugins/sp/scripts/wrapup-steps.mjs +72 -33
- package/plugins/sp/scripts/wrapup-steps.ts +128 -37
- package/plugins/sp/skills/code-improvement/SKILL.md +5 -4
- package/plugins/sp/skills/code-verification/SKILL.md +34 -9
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +3 -3
- package/plugins/sp/skills/functional-review/SKILL.md +7 -4
- package/plugins/sp/skills/functional-review/references/verdict-schema.md +1 -1
- package/plugins/sp/skills/history-anatomy/references/modes.md +2 -1
- package/plugins/sp/skills/next-feature/references/handoff-routing.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
- package/plugins/sp/skills/source-driven-development/SKILL.md +11 -0
- package/plugins/sp/skills/spur-cli/SKILL.md +3 -3
- package/plugins/sp/skills/spur-cli/references/agent.md +10 -10
- package/plugins/sp/skills/spur-cli/references/features.md +17 -6
- package/plugins/sp/skills/spur-cli/references/init.md +17 -16
- package/plugins/sp/skills/spur-cli/references/self.md +3 -2
- package/plugins/sp/skills/spur-cli/references/serve.md +10 -10
- package/plugins/sp/skills/spur-cli/references/tasks/section-editing.md +9 -5
- package/plugins/sp/skills/spur-cli/references/tasks/verbs.md +21 -6
- package/plugins/sp/skills/spur-cli/references/tasks.md +14 -8
- package/plugins/sp/skills/spur-cli/references/workflows.md +17 -14
- package/plugins/sp/skills/spur-dev/SKILL.md +2 -0
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +4 -3
- package/plugins/sp/skills/spur-dev/references/cross-cutting.md +14 -10
- package/plugins/sp/skills/spur-dev/references/decision-brief.md +1 -1
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +165 -75
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +7 -5
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +84 -39
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +8 -12
- package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +3 -3
- package/plugins/sp/skills/spur-dev/references/flag-glossary.md +40 -21
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +19 -19
- package/plugins/sp/skills/spur-dev/references/idea-evaluation.md +4 -3
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +72 -15
- package/plugins/sp/skills/spur-doctor/SKILL.md +1 -1
- package/plugins/sp/skills/sys-architecture/SKILL.md +3 -2
- package/spur.js +4461 -2085
- package/web/_astro/{BoardApp.Cpxntzad.js → BoardApp.Bmv5WkJ9.js} +1 -1
- package/web/_astro/BoardApp.vveLOdDq.js +322 -0
- package/web/_astro/{TaskDetail.C5bW4WGV.js → TaskDetail.IKc3uDYV.js} +1 -1
- package/web/_astro/{arc.CyjRvNMY.js → arc.C63Ufg35.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.B4lWRzJA.js → architectureDiagram-3BPJPVTR.CP8Hyldk.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.Be38USQ2.js → blockDiagram-GPEHLZMM.Bo_48MRA.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.DT9Fj5Qx.js → c4Diagram-AAUBKEIU.Ch61sw-O.js} +1 -1
- package/web/_astro/channel.BKCmJpWM.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.SeSBWLg5.js → chunk-2J33WTMH.CHpzS7xf.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.DoO4VE14.js → chunk-4BX2VUAB.DzMNNWIw.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.DrmTFA53.js → chunk-55IACEB6.BqPrDw_Q.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.Bi-TUb_V.js → chunk-727SXJPM.ZzBHhNw-.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.B-xp8Uhi.js → chunk-AQP2D5EJ.1_O_LLkx.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.DGWrDnUU.js → chunk-FMBD7UC4.GS4UHg7_.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM._BagvPDy.js → chunk-ND2GUHAM.BnqotN4g.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.VOboYWQ0.js → chunk-QZHKN3VN.Ghuh8zoJ.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.D_apfHS7.js → classDiagram-4FO5ZUOK.BW9vC3zg.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.D_apfHS7.js → classDiagram-v2-Q7XG4LA2.BW9vC3zg.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.DNLU_L-x.js → cose-bilkent-S5V4N54A.D6jNC0ti.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.D8borhV-.js → cynefin-OW5HDTMX.BOGoCs4L.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.Uc0lvjcV.js → dagre-BM42HDAG.8iU5VcWi.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.DDIxtDBo.js → diagram-2AECGRRQ.CVt88HwH.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.DVoDnD3H.js → diagram-5GNKFQAL.C9HxUUMl.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.CRubTJ-0.js → diagram-KO2AKTUF.4ywkQN3t.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.m9SeYcXQ.js → diagram-LMA3HP47.C48A6gpz.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.C6s2ZjV5.js → diagram-OG6HWLK6.DxFieQW4.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.nSzr5KTj.js → erDiagram-TEJ5UH35.CtjtQqYs.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.DrZcys16.js → flowDiagram-I6XJVG4X.C5zAiahU.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.Do4M1b-K.js → ganttDiagram-6RSMTGT7.D_L6zsny.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.BWc9oJ4l.js → gitGraphDiagram-PVQCEYII.Ignnrk3V.js} +1 -1
- package/web/_astro/index.CbNz17Sx.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.BIdOctFk.js → infoDiagram-5YYISTIA.DLv8-P5u.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.CV5SuG2t.js → ishikawaDiagram-YF4QCWOH.p0OTpwFO.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.CxE-rEJ-.js → journeyDiagram-JHISSGLW.CIaBt-DD.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.BPRdKWs_.js → kanban-definition-UN3LZRKU.DGySIntq.js} +1 -1
- package/web/_astro/{linear.zRsuuDTE.js → linear.BATV4RXu.js} +1 -1
- package/web/_astro/{mermaid.core.jAJTcMKc.js → mermaid.core.DzkwM3VX.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.BffJxfCr.js → mindmap-definition-RKZ34NQL.3piBRRzA.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.CacwWaE3.js → pieDiagram-4H26LBE5.DUNueLub.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.hXELD06-.js → quadrantDiagram-W4KKPZXB.9bihVbrt.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.DdEbPcqT.js → requirementDiagram-4Y6WPE33.CkjsC-YT.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.DgaDocKv.js → sankeyDiagram-5OEKKPKP.Dbq4vaoQ.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.B0KScnAu.js → sequenceDiagram-3UESZ5HK.BivrH99P.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.CV9M_WNc.js → stateDiagram-AJRCARHV.CqLQ1Vzz.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.BOAo74Et.js → stateDiagram-v2-BHNVJYJU.DvvoLD3b.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.CqqepUMe.js → timeline-definition-PNZ67QCA.B-KR78gv.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.DDqe4dOG.js → vennDiagram-CIIHVFJN.Ck0Eieb5.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.B3R9OPdO.js → wardleyDiagram-YWT4CUSO.CRfdd_do.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.B3SvgXpQ.js → xychartDiagram-2RQKCTM6.Ck_Jxk9C.js} +1 -1
- package/web/index.html +2 -2
- package/plugins/sp/lib/artifact-digest.generated.d.mts +0 -7
- package/plugins/sp/lib/artifact-digest.generated.mjs +0 -48
- package/plugins/sp/scripts/feature-sync-bounded.mjs +0 -301
- package/plugins/sp/scripts/feature-sync-bounded.ts +0 -481
- package/plugins/sp/scripts/idea-coverage-check.ts +0 -168
- package/plugins/sp/scripts/inline-pipeline-parity-check.ts +0 -298
- package/plugins/sp/scripts/record-feature-sync.mjs +0 -63
- package/plugins/sp/scripts/record-feature-sync.ts +0 -84
- package/plugins/sp/scripts/script-contract-check.ts +0 -506
- package/plugins/sp/scripts/stage-registry-adapter.ts +0 -1533
- package/plugins/sp/scripts/surface-drift-inventory.ts +0 -989
- package/plugins/sp/scripts/task-evidence-precheck.ts +0 -189
- package/plugins/sp/scripts/task-size-precheck.ts +0 -212
- package/plugins/sp/scripts/transition-shim-check.ts +0 -238
- package/plugins/sp/scripts/validate-commands.ts +0 -689
- package/plugins/sp/scripts/validate-flag-contracts.ts +0 -890
- package/plugins/sp/scripts/verify-answer-lint.ts +0 -549
- package/web/_astro/BoardApp.BxJuwD7I.js +0 -191
- package/web/_astro/channel.CI6N_tCg.js +0 -1
- package/web/_astro/index.CENnIEqT.css +0 -1
|
@@ -44,7 +44,7 @@ description: "Standard task pipeline: precheck → implement → quality-gate (t
|
|
|
44
44
|
# any non-terminal state may transition to cancelled.
|
|
45
45
|
# Guards:
|
|
46
46
|
# wip → testing: spur task check <wbs>
|
|
47
|
-
# testing → done: spur task check <wbs> --
|
|
47
|
+
# testing → done: spur task check <wbs> --as done, then PASS-verdict provenance
|
|
48
48
|
# Invalid: todo → testing, todo → done, and wip → done.
|
|
49
49
|
# Pipeline states below are orchestration states, not task statuses.
|
|
50
50
|
iterationBound: 20
|
|
@@ -163,12 +163,6 @@ vars:
|
|
|
163
163
|
# anchors directly in the /sp:dev-fixall input, so the fix agent starts AT the failing
|
|
164
164
|
# file:line instead of re-deriving it from a fresh gate run (0482 R3).
|
|
165
165
|
gateFindings: ""
|
|
166
|
-
# Max R-items in ## Requirements before size precheck fails (R2, task 0454).
|
|
167
|
-
# Override with `--vars '{"maxImplementReqs":"20"}'`.
|
|
168
|
-
maxImplementReqs: "10"
|
|
169
|
-
# Max checklist items under ## Plan before size precheck fails (R2, task 0454).
|
|
170
|
-
# Override with `--vars '{"maxImplementPlanItems":"32"}'`.
|
|
171
|
-
maxImplementPlanItems: "16"
|
|
172
166
|
# Diff-scope guard on the implement hop (R1, task 0487). When the target task
|
|
173
167
|
# body backticks at least one path, non-corpus changes outside those paths
|
|
174
168
|
# fail the step by name. New files beside a declared file are allowed. Empty
|
|
@@ -194,38 +188,19 @@ states:
|
|
|
194
188
|
options:
|
|
195
189
|
command: >-
|
|
196
190
|
S=plugins/sp/scripts/script-root.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp script-root.mjs 2>/dev/null)"; RUNNER=bun; case "$S" in *.mjs) RUNNER=node ;; esac; [ -f "$S" ] && "$RUNNER" "$S" --run-id "$__runId" --spur-bin "$spurBin" || echo "script-root failed closed — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 0
|
|
197
|
-
# (e) git-status hygiene advisory; never fails the run (0487 R6 / 0511 R1).
|
|
191
|
+
# (e) git-status hygiene advisory; never fails the run (0487 R6 / 0511 R1). 1007 R3:
|
|
192
|
+
# the F96 base-sha capture (0950) merged into this shell — original commands in order,
|
|
193
|
+
# then the one-time base commit capture; a resumed run keeps its original base so
|
|
194
|
+
# residual scans stay anchored to the same diff.
|
|
198
195
|
- kind: shell
|
|
199
196
|
options:
|
|
200
197
|
command: >-
|
|
201
|
-
D=$(git status --porcelain -- . ':(exclude)docs/tasks*' ':(exclude)docs/features' 2>/dev/null); [ -z "$D" ] || printf 'precheck: WARNING - working tree has uncommitted non-corpus changes — commit or stash before starting a new task:\n%s\n' "$D"; C=$(git status --porcelain -- ':(glob)docs/tasks*/**' 2>/dev/null); [ -z "$C" ] || printf 'precheck: NOTE - task corpus has uncommitted changes — review before staging with this task:\n%s\n' "$C"; exit 0
|
|
202
|
-
- kind: note
|
|
203
|
-
options:
|
|
204
|
-
# R4 task_run_links linkage (kind=pipeline) is written by a WorkflowService
|
|
205
|
-
# hook at run start — see the 0062 follow-up note; there is no link-writing
|
|
206
|
-
# CLI verb to call from a shell step, so it cannot live in pure YAML.
|
|
207
|
-
message: "Pipeline start for task ${vars.wbs}."
|
|
198
|
+
D=$(git status --porcelain -- . ':(exclude)docs/tasks*' ':(exclude)docs/features' 2>/dev/null); [ -z "$D" ] || printf 'precheck: WARNING - working tree has uncommitted non-corpus changes — commit or stash before starting a new task:\n%s\n' "$D"; C=$(git status --porcelain -- ':(glob)docs/tasks*/**' 2>/dev/null); [ -z "$C" ] || printf 'precheck: NOTE - task corpus has uncommitted changes — review before staging with this task:\n%s\n' "$C"; mkdir -p .spur/run; [ -f ".spur/run/$wbs-base.sha" ] || git rev-parse HEAD > ".spur/run/$wbs-base.sha"; exit 0
|
|
208
199
|
# (e) auto-profile feature reopen; exit 1 when reactivation fails (0723 R3).
|
|
209
200
|
- kind: shell
|
|
210
201
|
options:
|
|
211
202
|
command: >-
|
|
212
203
|
[ "$profile" = auto ] || exit 0; FID=$($spurBin task show $wbs --json 2>/dev/null | jq -r '.feature_id // .frontmatter.feature_id // empty' 2>/dev/null); [ -z "$FID" ] || $spurBin feature sync "$FID" --force 2>/dev/null || $spurBin feature update "$FID" active 2>/dev/null || { echo "precheck: FAIL - feature reactivation $FID failed — feature sync + feature update both errored" >&2; exit 1; }; exit 0
|
|
213
|
-
# (d) task-size-precheck.ts owns the check; shell only resolves it and fails closed (0454 R2 / 0723 R2).
|
|
214
|
-
- kind: shell
|
|
215
|
-
options:
|
|
216
|
-
command: >-
|
|
217
|
-
mkdir -p .spur/run; S=plugins/sp/scripts/task-size-precheck.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp task-size-precheck.ts 2>/dev/null)"; if [ -f "$S" ]; then bun "$S" "$wbs" --spur-bin "$spurBin" --max-reqs "$maxImplementReqs" --max-plan-items "$maxImplementPlanItems"; else echo "task-size-precheck failed closed — checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'." >&2; echo "FAIL" > ".spur/run/$wbs-precheck-size.status"; fi; exit 0
|
|
218
|
-
# (d) task-evidence-precheck.ts owns the check; shell only resolves it and fails closed (0726 R2).
|
|
219
|
-
- kind: shell
|
|
220
|
-
options:
|
|
221
|
-
command: >-
|
|
222
|
-
mkdir -p .spur/run; S=plugins/sp/scripts/task-evidence-precheck.ts; [ -f config/plugin-scripts.json -a -f "$S" ] || S="$(superskill script path sp task-evidence-precheck.ts 2>/dev/null)"; if [ -f "$S" ]; then bun "$S" "$wbs" --spur-bin "$spurBin"; else echo "task-evidence-precheck failed closed — checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'." >&2; echo "FAIL" > ".spur/run/$wbs-precheck-evidence.status"; fi; exit 0
|
|
223
|
-
# (e) F96 R1 (0950): capture the run's base commit once — a resumed or re-entered run
|
|
224
|
-
# keeps its original base so residual scans stay anchored to the same diff.
|
|
225
|
-
- kind: shell
|
|
226
|
-
options:
|
|
227
|
-
command: >-
|
|
228
|
-
mkdir -p .spur/run; [ -f ".spur/run/$wbs-base.sha" ] || git rev-parse HEAD > ".spur/run/$wbs-base.sha"; exit 0
|
|
229
204
|
# (e) route-reason lookup and routes log; proportional-routing tests locate it
|
|
230
205
|
# (0759 R1/R5 run-scoped artifact; 0804 R8 run-id safety — one line, no in-scalar `#`).
|
|
231
206
|
- kind: shell
|
|
@@ -439,7 +414,7 @@ states:
|
|
|
439
414
|
- kind: shell
|
|
440
415
|
options:
|
|
441
416
|
command: >-
|
|
442
|
-
|
|
417
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/quality-gate.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/quality-gate.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then "$RUNNER" "$S" run; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
|
|
443
418
|
|
|
444
419
|
- id: test-fix
|
|
445
420
|
description: >
|
|
@@ -454,19 +429,15 @@ states:
|
|
|
454
429
|
options:
|
|
455
430
|
command: >-
|
|
456
431
|
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 "test-fix: mutation policy forbids automatic code repair (run=$mutationPolicy, task=$TASK_POLICY) — gate failure preserved, no agent dispatched" >&2; exit 1; }
|
|
457
|
-
# (e) fixall attempt counter
|
|
432
|
+
# (e) fixall attempt counter, verdict hand-off and residual artifact in one log
|
|
433
|
+
# append shell (1007 R3: the two appends merged — original commands in order, exit 0).
|
|
434
|
+
# (d) F96 R3 (0950): dev-fixall treats residual items as fix targets and may defer
|
|
435
|
+
# P3/markers to residual-deferrals.json (see dev-fixall.md); fold already merged the
|
|
436
|
+
# anchors into <wbs>-test-gate.findings, this carries the structured artifact too.
|
|
458
437
|
- kind: shell
|
|
459
438
|
options:
|
|
460
439
|
command: >-
|
|
461
|
-
|
|
462
|
-
# (d) F96 R3 (0950): hand the residual list to the remediation loop — dev-fixall
|
|
463
|
-
# treats residual items as fix targets and may defer P3/markers to
|
|
464
|
-
# residual-deferrals.json (see dev-fixall.md). Fold already merged the anchors
|
|
465
|
-
# into <wbs>-test-gate.findings; this carries the structured artifact too.
|
|
466
|
-
- kind: shell
|
|
467
|
-
options:
|
|
468
|
-
command: >-
|
|
469
|
-
[ ! -f ".spur/run/$wbs-residuals.json" ] || { echo '--- residual artifact (F96 fix targets; deferrals go to residual-deferrals.json, P3/markers only) ---'; cat ".spur/run/$wbs-residuals.json"; } >> ".spur/run/$wbs-test-gate.log"; exit 0
|
|
440
|
+
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
|
|
470
441
|
# R3 (0482): project the extracted gate anchors into a var so the dispatch input
|
|
471
442
|
# can NAME the failing file:line, not merely point at a log. A vars template cannot
|
|
472
443
|
# run a shell, so the read is an action, not an inline `$(cat ...)` substitution.
|
|
@@ -522,7 +493,7 @@ states:
|
|
|
522
493
|
- kind: shell
|
|
523
494
|
options:
|
|
524
495
|
command: >-
|
|
525
|
-
|
|
496
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/quality-gate.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/quality-gate.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then "$RUNNER" "$S" recheck; else echo "quality gate failed closed — quality-gate script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf 'FAIL\n' > ".spur/run/$wbs-test-gate.status"; fi; exit 0
|
|
526
497
|
|
|
527
498
|
- id: triage
|
|
528
499
|
description: >-
|
|
@@ -542,7 +513,7 @@ states:
|
|
|
542
513
|
- kind: shell
|
|
543
514
|
options:
|
|
544
515
|
command: >-
|
|
545
|
-
|
|
516
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/task-diffstat.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/task-diffstat.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then "$RUNNER" "$S" --spur-bin "$spurBin"; else echo "task-diffstat failed closed — task-diffstat script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; printf '{"files":0,"insertions":0,"deletions":0,"paths":[],"sensitive":true}\n' > ".spur/run/$wbs-diffstat.json"; fi; exit 0
|
|
546
517
|
# (b)+(c) lane pre-guard BEFORE decide: a caller-set mode is projected verbatim (R2b);
|
|
547
518
|
# a sensitive path or >400 changed lines pins safety (R2c) and the decide result below
|
|
548
519
|
# is never consulted. A missing/malformed diffstat row (producer crashed or never ran,
|
|
@@ -568,18 +539,15 @@ states:
|
|
|
568
539
|
- .spur/run/${vars.wbs}-diffstat.json
|
|
569
540
|
- ${vars.taskSpecPath}
|
|
570
541
|
resultFile: .spur/run/${vars.wbs}-triage.decision
|
|
571
|
-
# (d) project the decision
|
|
572
|
-
#
|
|
573
|
-
#
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
command: >-
|
|
577
|
-
MF=".spur/run/$wbs-mode.txt"; [ -s "$MF" ] && exit 0; jq -r 'if .value == "low" then "fast" else empty end' ".spur/run/$wbs-triage.decision" 2>/dev/null > "$MF"; exit 0
|
|
578
|
-
# R5: append the triage route reason in the shared routes-log format.
|
|
542
|
+
# (d) project the decision, then append the triage route reason (1007 R3: the
|
|
543
|
+
# mode-fallback shell merged into the memory-append shell — original commands in
|
|
544
|
+
# order, the non-empty mode file is still never overridden; the append keeps the
|
|
545
|
+
# failure signal of the original pair). low → fast lane; anything else (standard/high,
|
|
546
|
+
# degraded default, missing row) leaves the mode empty → standard review path.
|
|
579
547
|
- kind: shell
|
|
580
548
|
options:
|
|
581
549
|
command: >-
|
|
582
|
-
|
|
550
|
+
MF=".spur/run/$wbs-mode.txt"; [ -s "$MF" ] || jq -r 'if .value == "low" then "fast" else empty end' ".spur/run/$wbs-triage.decision" 2>/dev/null > "$MF"; m="$(cat "$MF")"; 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:triage low lane","safety":"safety:triage deterministic-high","":"safety:triage standard lane"}[$m] // "safety:triage unrecognized mode" end')" >> .spur/memory/task-pipeline-routes.log
|
|
583
551
|
# (d) the resolved lane becomes the `mode` var for the triage → verify/review guards.
|
|
584
552
|
- kind: file.read.into-var
|
|
585
553
|
options:
|
|
@@ -622,7 +590,7 @@ states:
|
|
|
622
590
|
# through the executor registry, and the runner enforces (pre-dispatch,
|
|
623
591
|
# fail-closed) that a P0/P1 task's review resolves a DIFFERENT executor
|
|
624
592
|
# spec than the implement stage recorded in __agentRouting_implement.
|
|
625
|
-
input: /sp:dev-review ${vars.wbs} --auto
|
|
593
|
+
input: /sp:dev-review --tasks ${vars.wbs} --auto
|
|
626
594
|
# The captured review answer is the run's dispatch evidence (0823 R1):
|
|
627
595
|
# expectFile fails the step when no answer was captured. Quality stays with
|
|
628
596
|
# the review proof digest and the verify verdict.
|
|
@@ -704,24 +672,8 @@ states:
|
|
|
704
672
|
compareExecutorWith: implement
|
|
705
673
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
706
674
|
expectFile: .spur/run/${vars.wbs}-verify-answer.txt
|
|
707
|
-
#
|
|
708
|
-
#
|
|
709
|
-
# Hard action: a malformed answer halts the sequence here instead of
|
|
710
|
-
# poisoning the verdict parse downstream.
|
|
711
|
-
# (d) verify-answer-lint.ts owns the answer lint; shell only resolves it.
|
|
712
|
-
- kind: shell
|
|
713
|
-
options:
|
|
714
|
-
command: >-
|
|
715
|
-
LINT_SCRIPT="plugins/sp/scripts/verify-answer-lint.ts";
|
|
716
|
-
[ -f config/plugin-scripts.json -a -f "$LINT_SCRIPT" ] ||
|
|
717
|
-
LINT_SCRIPT="$(superskill script path sp verify-answer-lint.ts 2>/dev/null)";
|
|
718
|
-
if [ -z "$LINT_SCRIPT" ] || [ ! -f "$LINT_SCRIPT" ]; then
|
|
719
|
-
echo "verify-answer-lint: checker not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
720
|
-
exit 1;
|
|
721
|
-
fi;
|
|
722
|
-
bun "$LINT_SCRIPT" "$wbs"
|
|
723
|
-
--answer ".spur/run/$wbs-verify-answer.txt"
|
|
724
|
-
--spur-bin "$spurBin"
|
|
675
|
+
# (d) `spur task verdict` owns the answer lint (task 1003 R2) — the shell below
|
|
676
|
+
# fails closed when the verifier's answer is malformed, before any verdict artifact.
|
|
725
677
|
- kind: shell
|
|
726
678
|
options:
|
|
727
679
|
command: "$spurBin task verdict $wbs --from-answer .spur/run/$wbs-verify-answer.txt"
|
|
@@ -740,7 +692,7 @@ states:
|
|
|
740
692
|
`run.artifact` registration (0785 R3): the verify verdict is ledger-registered
|
|
741
693
|
against a freshly captured proof digest — including review-completion marker
|
|
742
694
|
evidence (0785 R4) — before any task record or status mutation. Post-record step
|
|
743
|
-
conditionally syncs feature status via
|
|
695
|
+
conditionally syncs feature status via `spur feature sync`
|
|
744
696
|
(task 0411 retry-suppression) if `feature_id` is present, or appends an orphan
|
|
745
697
|
link proposal to the run report if absent (task 0328 / ADR-0322). The post-record
|
|
746
698
|
residual sweep (0983) re-scans the task file after the verdict-proven box flips and
|
|
@@ -784,19 +736,17 @@ states:
|
|
|
784
736
|
resultFile: .spur/run/${vars.__runId}-record-transition.status
|
|
785
737
|
softFail: false
|
|
786
738
|
timeoutMs: 120000
|
|
787
|
-
# (d)
|
|
788
|
-
#
|
|
789
|
-
#
|
|
790
|
-
#
|
|
791
|
-
#
|
|
792
|
-
#
|
|
793
|
-
#
|
|
794
|
-
# inline chain cannot share one shell); resolution follows the standard in-repo-first,
|
|
795
|
-
# superskill-staged fallback used by every pipeline checker.
|
|
739
|
+
# (d) Best-effort `exit 0` — feature status sync is a follow-up, not a completion gate;
|
|
740
|
+
# `record → done` runs `spur task check`. 0931 R5: with deferFeatureSync "true" (parallel
|
|
741
|
+
# mode) the deferral note lands in the task report and the sync is skipped entirely, so
|
|
742
|
+
# task branches never touch feature corpus files; the batch orchestrator performs the
|
|
743
|
+
# deferred sync on the base ref. 1004 R4: the sync is a bare `feature sync` — repeated-
|
|
744
|
+
# BLOCKED suppression (0411) now lives in the feature sync service itself, so the shell
|
|
745
|
+
# resolves feature_id via jq and delegates without a helper script.
|
|
796
746
|
- kind: shell
|
|
797
747
|
options:
|
|
798
748
|
command: >-
|
|
799
|
-
|
|
749
|
+
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
|
|
800
750
|
# (d) F96 (0983): residual-scan.ts owns the sweep; shell only resolves it. The
|
|
801
751
|
# scan moved here from verify: it must read the task file AFTER `task record`
|
|
802
752
|
# flipped the verdict-proven Requirement/AC boxes (0692), or a proven-but-unticked
|
|
@@ -807,7 +757,7 @@ states:
|
|
|
807
757
|
- kind: shell
|
|
808
758
|
options:
|
|
809
759
|
command: >-
|
|
810
|
-
S=
|
|
760
|
+
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)"; if [ ! -f "$S" ]; then echo "residual-scan failed closed — scanner not found in plugins/sp/scripts/ nor staged — run 'superskill install sp --marketplace gobing-ai/spur'" >&2; exit 1; fi; "$RUNNER" "$S" scan "$wbs" --spur-bin "$spurBin" && "$RUNNER" "$S" fold "$wbs" --spur-bin "$spurBin"
|
|
811
761
|
# (e) F96 R5 (0983): a sweep downgrade must reach the task record — re-record from
|
|
812
762
|
# the FINAL (post-fold) artifact so Testing carries the downgraded verdict; a failed
|
|
813
763
|
# task must not retain a stale PASS Testing narrative. Soft (exit 0): the downgrade
|
|
@@ -833,7 +783,7 @@ states:
|
|
|
833
783
|
- kind: shell
|
|
834
784
|
options:
|
|
835
785
|
command: >-
|
|
836
|
-
S=
|
|
786
|
+
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)"; if [ -f "$S" ]; then "$RUNNER" "$S" settle "$wbs" --spur-bin "$spurBin" || echo "residual-settle failed — re-run: residual-scan settle $wbs" >&2; else echo "residual-scan not staged — settle skipped — re-run: residual-scan settle $wbs" >&2; fi; exit 0
|
|
837
787
|
# (c) command.gate owns the done transition with classified transient retry.
|
|
838
788
|
- kind: command.gate
|
|
839
789
|
options:
|
|
@@ -847,10 +797,9 @@ states:
|
|
|
847
797
|
resultFile: .spur/run/${vars.__runId}-done-transition.status
|
|
848
798
|
softFail: false
|
|
849
799
|
timeoutMs: 120000
|
|
850
|
-
- kind: note
|
|
851
|
-
options:
|
|
852
|
-
message: "Pipeline complete for task ${vars.wbs} (done gate cleared)."
|
|
853
800
|
# (e) advisory terminal checkpoint, one printf (0711 R1–R3; binding corrected 0784 R4).
|
|
801
|
+
# 1007 R3: the former done note ("Pipeline complete ...") is dropped — the checkpoint
|
|
802
|
+
# below is the terminal record.
|
|
854
803
|
- kind: shell
|
|
855
804
|
options:
|
|
856
805
|
command: >-
|
|
@@ -880,24 +829,22 @@ states:
|
|
|
880
829
|
- kind: shell
|
|
881
830
|
options:
|
|
882
831
|
command: >-
|
|
883
|
-
S=
|
|
832
|
+
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)"; if [ -f "$S" ]; then "$RUNNER" "$S" report "$wbs" --spur-bin "$spurBin" || echo "residual-report failed — re-run: residual-scan report $wbs" >&2; else echo "residual-scan not staged — report skipped — re-run: residual-scan report $wbs" >&2; fi; exit 0
|
|
884
833
|
|
|
885
834
|
- id: cancelled
|
|
886
835
|
description: Terminal — pipeline cancelled by operator at the approval gate (R1).
|
|
887
836
|
|
|
888
837
|
transitions:
|
|
889
|
-
# ── precheck: size
|
|
838
|
+
# ── precheck: task check --precheck (size + evidence + four-layer, 1002 R4) → implement; ──
|
|
839
|
+
# else → failed. The flag folds the two deleted precheck scripts into one fail-closed
|
|
840
|
+
# guard: any size/evidence/structural error exits 1 and the fallback edge terminates.
|
|
890
841
|
- from: precheck
|
|
891
842
|
to: implement
|
|
892
843
|
description: Deterministic size, evidence, and task checks are green — begin implementation.
|
|
893
|
-
# (warn) 5 commands: named size/evidence status reads + task check (legibility, 0874).
|
|
894
844
|
guard:
|
|
895
845
|
kind: shell
|
|
896
846
|
options:
|
|
897
|
-
command:
|
|
898
|
-
size_status="$(cat .spur/run/$wbs-precheck-size.status 2>/dev/null)";
|
|
899
|
-
evidence_status="$(cat .spur/run/$wbs-precheck-evidence.status 2>/dev/null)";
|
|
900
|
-
test "$size_status" = PASS && test "$evidence_status" = PASS && $spurBin task check $wbs
|
|
847
|
+
command: '$spurBin task check $wbs --precheck'
|
|
901
848
|
- from: precheck
|
|
902
849
|
to: failed
|
|
903
850
|
terminalReason: failed-check
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
# even under --auto (Iron Law #6: irreversible action -> surface to human).
|
|
15
15
|
#
|
|
16
16
|
# Shape: start -> task-resolve -> doc-sync -> learnings-validate -> learnings-append
|
|
17
|
+
# -> doc-tripwire (1037: repo-wide tripwire over the still-uncommitted wrap
|
|
18
|
+
# diff; repair also enters it; the task-resolve fast path does not)
|
|
17
19
|
# -> metrics-record
|
|
18
20
|
# -> feature-transition (conditional: if vars.feature set)
|
|
19
21
|
# -> feature-verify (post-transition feature check gate, 0915 F1)
|
|
@@ -25,10 +27,14 @@
|
|
|
25
27
|
# the same `repair` edge with a distinct invalid-learnings-shape status —
|
|
26
28
|
# expectFile proves existence, never shape — while empty/missing captures
|
|
27
29
|
# keep the soft skip by passing through to learnings-append;
|
|
30
|
+
# learnings-append and repair converge on doc-tripwire (1037), which runs
|
|
31
|
+
# docTripwireCmd — the repo-wide tripwires over the still-uncommitted wrap
|
|
32
|
+
# diff — before metrics-record; the task-resolve fast path never enters it;
|
|
28
33
|
# task-resolve with a VALIDATED empty list short-circuits to `skipped`;
|
|
29
34
|
# invalid wrap input, an unresolved/non-completed task, a failed metrics
|
|
30
|
-
# capture, a failed required sync,
|
|
31
|
-
# `failed` (0770) instead of being
|
|
35
|
+
# capture, a failed required sync, a failed repo-wide tripwire (1037), or
|
|
36
|
+
# a failed feature gate routes to `failed` (0770) instead of being
|
|
37
|
+
# absorbed by an always-defensive skip.
|
|
32
38
|
#
|
|
33
39
|
# Vars (passed as a JSON object via `--vars`):
|
|
34
40
|
# tasks — JSON array of WBS strings, passed as a JSON-encoded STRING value
|
|
@@ -80,7 +86,7 @@
|
|
|
80
86
|
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
81
87
|
kind: state-machine
|
|
82
88
|
name: wrapup-pipeline
|
|
83
|
-
version: "
|
|
89
|
+
version: "7"
|
|
84
90
|
description: "Post-execution wrap-up: doc-sync (doc drift + learning capture), metrics, feature-transition, branch-cleanup"
|
|
85
91
|
iterationBound: 10
|
|
86
92
|
initialState: start
|
|
@@ -105,6 +111,13 @@ vars:
|
|
|
105
111
|
# TRUSTED CONFIG ONLY — this string is executed via `sh -c` (same surface as
|
|
106
112
|
# task-pipeline's qualityGateCmd). Never interpolate untrusted input into it.
|
|
107
113
|
featureGateCmd: '$spurBin feature check "$feature"'
|
|
114
|
+
# Repo-wide tripwire over the wrap diff (1037): runs `bun run test-repo-wide`
|
|
115
|
+
# only when package.json declares the script, so other projects no-op. Callers
|
|
116
|
+
# can override it with --vars; an empty string disables the check (the hop
|
|
117
|
+
# still writes PASS).
|
|
118
|
+
# TRUSTED CONFIG ONLY — this string is executed via `sh -c` (same surface as
|
|
119
|
+
# featureGateCmd). Never interpolate untrusted input into it.
|
|
120
|
+
docTripwireCmd: 'if jq -e ''.scripts["test-repo-wide"]'' package.json >/dev/null 2>&1; then bun run test-repo-wide; fi'
|
|
108
121
|
__hitlAnswer: ""
|
|
109
122
|
|
|
110
123
|
states:
|
|
@@ -126,7 +139,8 @@ states:
|
|
|
126
139
|
- id: task-resolve
|
|
127
140
|
description: >
|
|
128
141
|
Validate the task list ONCE and evaluate closed proportional routing (0758
|
|
129
|
-
R1-R4).
|
|
142
|
+
R1-R4). When vars.feature is set, resolve also runs the feature pre-flight
|
|
143
|
+
(1033 R2). Validation (0770 + 0783): vars.tasks must be a JSON array of
|
|
130
144
|
canonical four-digit WBS strings — non-arrays, non-strings, whitespace or
|
|
131
145
|
other shapes are rejected, not trimmed — deduplicated in first-seen
|
|
132
146
|
order, with __runId present, and every member must resolve via `spur task
|
|
@@ -154,10 +168,8 @@ states:
|
|
|
154
168
|
options:
|
|
155
169
|
command: >-
|
|
156
170
|
mkdir -p .spur/run &&
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
160
|
-
node "$W" resolve;
|
|
171
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
|
|
172
|
+
"$RUNNER" "$S" resolve;
|
|
161
173
|
else
|
|
162
174
|
echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
163
175
|
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
|
|
@@ -174,13 +186,14 @@ states:
|
|
|
174
186
|
command: >-
|
|
175
187
|
if [ -n "$mode" ]; then
|
|
176
188
|
printf '%s\n' "$mode" > ".spur/run/$__runId-mode.txt";
|
|
177
|
-
elif [ -f config/plugin-scripts.json -a -f plugins/sp/scripts/wrapup-drift-probe.ts ]; then
|
|
178
|
-
bun plugins/sp/scripts/wrapup-drift-probe.ts;
|
|
179
|
-
elif W="$(superskill script path sp wrapup-drift-probe.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
180
|
-
node "$W";
|
|
181
189
|
else
|
|
182
|
-
|
|
183
|
-
|
|
190
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-drift-probe.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-drift-probe.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)";
|
|
191
|
+
if [ -f "$S" ]; then
|
|
192
|
+
"$RUNNER" "$S";
|
|
193
|
+
else
|
|
194
|
+
printf '{"clean":false,"reasons":["probe script not found"],"paths":[]}' > ".spur/run/$__runId-drift-probe.json";
|
|
195
|
+
printf '\n' > ".spur/run/$__runId-mode.txt";
|
|
196
|
+
fi;
|
|
184
197
|
fi
|
|
185
198
|
- kind: file.read.into-var
|
|
186
199
|
options:
|
|
@@ -201,10 +214,8 @@ states:
|
|
|
201
214
|
options:
|
|
202
215
|
command: >-
|
|
203
216
|
mkdir -p .spur/run .spur/memory &&
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
207
|
-
node "$W" route-reason;
|
|
217
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
|
|
218
|
+
"$RUNNER" "$S" route-reason;
|
|
208
219
|
else
|
|
209
220
|
echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
210
221
|
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
|
|
@@ -302,8 +313,8 @@ states:
|
|
|
302
313
|
capture that fails learnings-validate's shape gate (0986). The miss is
|
|
303
314
|
recorded to a run-scoped repair status — text distinguishing a narration-only
|
|
304
315
|
shape failure from the missing-file contract violation — and wrap-up proceeds
|
|
305
|
-
to metrics-record; the run log and
|
|
306
|
-
contract and the observed value.
|
|
316
|
+
through the doc-tripwire hop (1037) to metrics-record; the run log and
|
|
317
|
+
action trace already name the violated contract and the observed value.
|
|
307
318
|
onEnter:
|
|
308
319
|
- kind: shell
|
|
309
320
|
options:
|
|
@@ -316,6 +327,27 @@ states:
|
|
|
316
327
|
fi &&
|
|
317
328
|
exit 0
|
|
318
329
|
|
|
330
|
+
- id: doc-tripwire
|
|
331
|
+
description: >
|
|
332
|
+
Repo-wide tripwire over the wrap diff (1037): the doc-sync edits are still
|
|
333
|
+
uncommitted when wrap-up reaches a terminal success, and the repo-wide
|
|
334
|
+
tripwires (repo-wide-tests/) execute only inside spur-check-feature — once
|
|
335
|
+
a wrap edit is committed on a clean tree, the working-diff tests (e.g.
|
|
336
|
+
adr-supersession (e)) can no longer see it. Entered from learnings-append
|
|
337
|
+
and repair, before metrics or feature state mutate, it runs the trusted
|
|
338
|
+
`docTripwireCmd` and records PASS or FAIL to a run-scoped status file; the
|
|
339
|
+
action always exits 0 so status truth lives in the file (0783 R4). Only a
|
|
340
|
+
verified run writes PASS; an empty docTripwireCmd disables the check and
|
|
341
|
+
still writes PASS. The no-doc-sync fast path (task-resolve →
|
|
342
|
+
metrics-record) never enters this state.
|
|
343
|
+
onEnter:
|
|
344
|
+
- kind: shell
|
|
345
|
+
options:
|
|
346
|
+
command: >-
|
|
347
|
+
sh -c "$docTripwireCmd" &&
|
|
348
|
+
printf 'PASS\n' > ".spur/run/$__runId-wrapup-doc-tripwire.status" ||
|
|
349
|
+
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-doc-tripwire.status"
|
|
350
|
+
|
|
319
351
|
- id: metrics-record
|
|
320
352
|
description: >
|
|
321
353
|
Append one JSONL row per task to .spur/memory/wrapup-metrics.jsonl deterministically.
|
|
@@ -334,10 +366,8 @@ states:
|
|
|
334
366
|
options:
|
|
335
367
|
command: >-
|
|
336
368
|
mkdir -p .spur/run &&
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
340
|
-
node "$W" metrics;
|
|
369
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
|
|
370
|
+
"$RUNNER" "$S" metrics;
|
|
341
371
|
else
|
|
342
372
|
echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
343
373
|
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-metrics.status";
|
|
@@ -345,7 +375,8 @@ states:
|
|
|
345
375
|
|
|
346
376
|
- id: feature-transition
|
|
347
377
|
description: >
|
|
348
|
-
If vars.feature is set, sync feature status via
|
|
378
|
+
If vars.feature is set, sync feature status via `spur feature sync` (repeated-BLOCKED
|
|
379
|
+
suppression is built into the sync service, so no wrapper script is needed)
|
|
349
380
|
(0411). The shell terminates `exit 0` so artifacts already landed are never
|
|
350
381
|
discarded, but the outcome is truthful (0770 + 0783 R4): sync succeeds only
|
|
351
382
|
with a valid proposal matching vars.feature, no gateBlocked/requiresConfirm
|
|
@@ -368,10 +399,8 @@ states:
|
|
|
368
399
|
options:
|
|
369
400
|
command: >-
|
|
370
401
|
mkdir -p .spur/run &&
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
374
|
-
node "$W" feature-transition;
|
|
402
|
+
eval "$(jq -r 'if .mode=="source-repo" then "S="+@sh"\(.dir)/wrapup-steps.ts"+" RUNNER=bun" elif .mode=="installed" then "S="+@sh"\(.dir)/wrapup-steps.mjs"+" RUNNER=node" else empty end' ".spur/run/$__runId-script-root.json" 2>/dev/null)"; if [ -f "$S" ]; then
|
|
403
|
+
"$RUNNER" "$S" feature-transition;
|
|
375
404
|
else
|
|
376
405
|
echo "wrapup-steps failed closed — script not found — run 'superskill install sp --marketplace gobing-ai/spur'" >&2;
|
|
377
406
|
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-sync.status";
|
|
@@ -433,9 +462,10 @@ states:
|
|
|
433
462
|
- id: failed
|
|
434
463
|
description: >
|
|
435
464
|
Terminal — wrap-up failed (0770): invalid wrap input, an unresolved or
|
|
436
|
-
non-completed task, a failed metrics capture, a failed required sync,
|
|
437
|
-
a failed feature gate.
|
|
438
|
-
rows, route reason) are
|
|
465
|
+
non-completed task, a failed metrics capture, a failed required sync, a
|
|
466
|
+
failed repo-wide tripwire (1037), or a failed feature gate.
|
|
467
|
+
Already-written artifacts (learnings, metrics rows, route reason) are
|
|
468
|
+
preserved; nothing is rolled back.
|
|
439
469
|
|
|
440
470
|
transitions:
|
|
441
471
|
# ── start -> task-resolve ──
|
|
@@ -550,20 +580,43 @@ transitions:
|
|
|
550
580
|
guard:
|
|
551
581
|
kind: always
|
|
552
582
|
|
|
553
|
-
# ──
|
|
583
|
+
# ── doc-sync exits converge on the doc-tripwire hop (1037) before metrics ──
|
|
554
584
|
- from: learnings-append
|
|
555
|
-
to:
|
|
556
|
-
description: Learning capture appended (or soft-skipped) —
|
|
585
|
+
to: doc-tripwire
|
|
586
|
+
description: Learning capture appended (or soft-skipped) — run the repo-wide tripwire over the wrap diff.
|
|
557
587
|
guard:
|
|
558
588
|
kind: always
|
|
559
589
|
|
|
560
|
-
# ── repair: cheap path, no re-dispatch -> metrics-record ──
|
|
561
590
|
- from: repair
|
|
562
|
-
to:
|
|
563
|
-
description: Contract-violation repair recorded —
|
|
591
|
+
to: doc-tripwire
|
|
592
|
+
description: Contract-violation repair recorded — run the tripwire before metrics without re-dispatch.
|
|
564
593
|
guard:
|
|
565
594
|
kind: always
|
|
566
595
|
|
|
596
|
+
# ── doc-tripwire: repo-wide tripwire gate (1037) ──
|
|
597
|
+
# Declaration order matters: the FAIL edge is tried first so a failed tripwire
|
|
598
|
+
# can never be absorbed by the PASS edge; a missing status matches neither
|
|
599
|
+
# edge and follows the engine's no-match behavior for status-file states.
|
|
600
|
+
- from: doc-tripwire
|
|
601
|
+
to: failed
|
|
602
|
+
terminalReason: failed-check
|
|
603
|
+
description: >
|
|
604
|
+
Repo-wide tripwire FAILED on the still-uncommitted wrap diff (1037): an
|
|
605
|
+
edit the doc-sync stage made (e.g. an in-place historical ADR change)
|
|
606
|
+
violates a working-diff test. Learnings and docs already on disk stay
|
|
607
|
+
put; nothing is rolled back.
|
|
608
|
+
guard:
|
|
609
|
+
kind: shell
|
|
610
|
+
options:
|
|
611
|
+
command: 'test "$(cat .spur/run/$__runId-wrapup-doc-tripwire.status 2>/dev/null)" = FAIL'
|
|
612
|
+
- from: doc-tripwire
|
|
613
|
+
to: metrics-record
|
|
614
|
+
description: Repo-wide tripwire PASS (or the check disabled by an empty docTripwireCmd) — record metrics.
|
|
615
|
+
guard:
|
|
616
|
+
kind: shell
|
|
617
|
+
options:
|
|
618
|
+
command: 'test "$(cat .spur/run/$__runId-wrapup-doc-tripwire.status 2>/dev/null)" = PASS'
|
|
619
|
+
|
|
567
620
|
# ── metrics-record: fail edge, then conditional routing (feature → merge → done) ──
|
|
568
621
|
# Declaration order matters: the FAIL edge is tried first (0770), then
|
|
569
622
|
# feature-transition (if feature is set), then branch-cleanup (if merge=true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.97",
|
|
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",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"dev": "bun run src/index.ts",
|
|
50
50
|
"build": "bun run ../../scripts/spur-dev.ts build-cli",
|
|
51
51
|
"build:binaries": "bun run ../../scripts/spur-dev.ts build-binaries",
|
|
52
|
-
"build:bundle": "bun run ../../scripts/spur-dev.ts bundle-web && bun run ../../scripts/spur-dev.ts emit-board-types && bun build src/index.ts --target=bun --outfile spur.js && bun run ../../scripts/spur-dev.ts bundle-config config && bun run ../../scripts/spur-dev.ts bundle-plugins",
|
|
52
|
+
"build:bundle": "bun run ../../scripts/commands/bundle-plugin-lib.ts && bun run ../../scripts/spur-dev.ts bundle-web && bun run ../../scripts/spur-dev.ts emit-board-types && bun build src/index.ts --target=bun --outfile spur.js && bun run ../../scripts/spur-dev.ts bundle-config config && bun run ../../scripts/spur-dev.ts bundle-plugins",
|
|
53
53
|
"test": "bun test tests --coverage --coverage-dir=../../.coverage --pass-with-no-tests",
|
|
54
54
|
"typecheck": "tsc --noEmit",
|
|
55
55
|
"prepack": "bun run build:bundle",
|