@gobing-ai/spur 0.3.80 → 0.3.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/config/config.example.yaml +31 -18
- package/config/config.global.yaml +13 -11
- package/config/pipeline-budgets.json +34 -2
- package/config/plugin-scripts.json +25 -0
- package/config/rules/boundary/config-loading-ownership.yaml +0 -3
- package/config/rules/boundary/dao-boundary.yaml +4 -17
- package/config/rules/boundary/planning-folder-hardcode.yaml +0 -1
- package/config/rules/boundary/sp-no-vendor-refs.yaml +3 -2
- package/config/rules/boundary/sp-runtime-path.yaml +3 -14
- package/config/rules/quality/coverage-gate.yaml +3 -14
- package/config/rules/quality/tsdoc-exports.yaml +4 -7
- package/config/rules/strict/http-boundaries.yaml +5 -8
- package/config/rules/strict/runtime-boundaries.yaml +1 -5
- package/config/rules/structure/protected-files.yaml +9 -3
- package/config/rules/structure/test-focus-skip.yaml +0 -2
- package/config/rules/structure/test-location.yaml +0 -5
- package/config/rules/surface/check-cli-surface.yaml +3 -2
- package/config/rules/typescript/bun-tooling.yaml +5 -7
- package/config/rules/typescript/guarded-happy-dom-register.yaml +0 -2
- package/config/rules/typescript/happy-dom-teardown.yaml +0 -2
- package/config/rules/typescript/no-biome-suppressions.yaml +0 -2
- package/config/rules/typescript/no-debugger.yaml +0 -2
- package/config/rules/typescript/no-eslint-suppressions.yaml +0 -4
- package/config/rules/typescript/no-leaky-module-mocks.yaml +6 -13
- package/config/rules/typescript/no-module-scope-import-calls.yaml +0 -2
- package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +0 -3
- package/config/rules/typescript/no-unmocked-module-eval-side-effects.yaml +0 -3
- package/config/rules/typescript/output-boundaries.yaml +0 -3
- package/config/rules/typescript/prefer-accessible-role-for-button-queries.yaml +0 -3
- package/config/rules/ui/ui-import-boundary.yaml +1 -5
- package/config/templates/docs/99_PROJECT_CONSTITUTION.md +75 -13
- package/config/transition-shims.json +0 -7
- package/config/workflows/basic.yaml +4 -0
- package/config/workflows/docs-pipeline.yaml +13 -14
- package/config/workflows/feature-dev.yaml +20 -65
- package/config/workflows/history-anatomy.yaml +22 -1
- package/config/workflows/idea-pipeline.yaml +53 -97
- package/config/workflows/pr-review.yaml +21 -33
- package/config/workflows/task-pipeline.yaml +87 -330
- package/config/workflows/wayfinder-resolution.yaml +12 -26
- package/config/workflows/wrapup-pipeline.yaml +48 -189
- package/package.json +9 -9
- package/plugins/sp/README.md +12 -3
- package/plugins/sp/agents/expert-spur.md +41 -19
- package/plugins/sp/lib/idea-handoff.generated.d.mts +17 -0
- package/plugins/sp/lib/idea-handoff.generated.mjs +1301 -0
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/scripts/feature-dev-precheck.mjs +146 -0
- package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
- package/plugins/sp/scripts/idea-handoff.mjs +27 -0
- package/plugins/sp/scripts/idea-handoff.ts +44 -0
- package/plugins/sp/scripts/inline-run-setup.ts +69 -1
- package/plugins/sp/scripts/quality-gate.mjs +216 -0
- package/plugins/sp/scripts/quality-gate.ts +287 -0
- package/plugins/sp/scripts/surface-drift-inventory.ts +0 -2
- package/plugins/sp/scripts/task-size-precheck.ts +44 -16
- package/plugins/sp/scripts/verify-answer-lint.ts +17 -1
- package/plugins/sp/scripts/workflow-step-profile.mjs +319 -0
- package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
- package/plugins/sp/scripts/wrapup-steps.mjs +350 -0
- package/plugins/sp/scripts/wrapup-steps.ts +466 -0
- package/plugins/sp/skills/code-review/references/review-lenses.md +3 -0
- package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
- package/plugins/sp/skills/spec-decomposition/references/decomposition.md +29 -0
- package/plugins/sp/skills/spur-cli/SKILL.md +4 -8
- package/plugins/sp/skills/spur-cli/references/agent.md +44 -69
- package/plugins/sp/skills/spur-cli/references/message.md +30 -3
- package/plugins/sp/skills/spur-cli/references/projects.md +25 -1
- package/plugins/sp/skills/spur-cli/references/self.md +6 -5
- package/plugins/sp/skills/spur-cli/references/serve.md +8 -7
- package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
- package/plugins/sp/skills/spur-cli/references/workflows/operations.md +6 -3
- package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +57 -18
- package/plugins/sp/skills/spur-composer/SKILL.md +145 -0
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +10 -0
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +1 -1
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +4 -6
- package/plugins/sp/skills/spur-dev/references/glossary.md +1 -1
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +11 -1
- package/plugins/sp/skills/spur-dev/references/planning-workflow.md +24 -0
- package/plugins/sp/skills/spur-doctor/SKILL.md +138 -0
- package/plugins/sp/skills/taste-refactoring-api/README.md +43 -0
- package/plugins/sp/skills/taste-refactoring-api/SKILL.md +334 -0
- package/plugins/sp/skills/taste-refactoring-api/checklists/daily-api-review.md +71 -0
- package/plugins/sp/skills/taste-refactoring-api/examples/refactor-example.md +72 -0
- package/plugins/sp/skills/taste-refactoring-api/examples/review-template.md +93 -0
- package/plugins/sp/skills/taste-refactoring-api/references/api-refactoring-playbook.md +253 -0
- package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +79 -0
- package/plugins/sp/skills/taste-refactoring-api/references/research-basis.md +58 -0
- package/plugins/sp/skills/taste-refactoring-architect/README.md +26 -0
- package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +471 -0
- package/plugins/sp/skills/taste-refactoring-architect/checklists/daily-architecture-review.md +48 -0
- package/plugins/sp/skills/taste-refactoring-architect/examples/refactor-example.md +55 -0
- package/plugins/sp/skills/taste-refactoring-architect/examples/review-template.md +51 -0
- package/plugins/sp/skills/taste-refactoring-architect/references/architecture-refactoring-playbook.md +173 -0
- package/plugins/sp/skills/taste-refactoring-architect/references/research-basis.md +28 -0
- package/plugins/sp/skills/taste-refactoring-tests/README.md +28 -0
- package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +482 -0
- package/plugins/sp/skills/taste-refactoring-tests/checklists/daily-test-review.md +39 -0
- package/plugins/sp/skills/taste-refactoring-tests/examples/refactor-example.md +85 -0
- package/plugins/sp/skills/taste-refactoring-tests/examples/review-template.md +59 -0
- package/plugins/sp/skills/taste-refactoring-tests/references/research-basis.md +47 -0
- package/plugins/sp/skills/taste-refactoring-tests/references/test-refactoring-playbook.md +222 -0
- package/plugins/sp/skills/taste-refactoring-ui/README.md +12 -0
- package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +290 -0
- package/plugins/sp/skills/taste-refactoring-ui/checklists/daily-ui-review.md +72 -0
- package/plugins/sp/skills/taste-refactoring-ui/examples/review-template.md +51 -0
- package/plugins/sp/skills/taste-refactoring-ui/references/refactoring-ui-playbook.md +170 -0
- package/plugins/sp/skills/wayfinder/SKILL.md +2 -2
- package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +30 -0
- package/schemas/spur-config.schema.json +105 -85
- package/spur.js +44616 -43320
- package/web/_astro/BoardApp.D-WlxiN2.js +1 -0
- package/web/_astro/{BoardApp.CHQ1lycZ.js → BoardApp.D8bM9pKL.js} +97 -95
- package/web/_astro/{TaskDetail.GKfQJ60c.js → TaskDetail.BPRqgVUE.js} +1 -1
- package/web/_astro/{arc.DWEtA3Tx.js → arc.BPrPES3z.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.DB42oWmP.js → architectureDiagram-3BPJPVTR.qX_7q02P.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.rhv-zNQV.js → blockDiagram-GPEHLZMM.CUZfj5V7.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.Ci4-4VvY.js → c4Diagram-AAUBKEIU.CTaOr8hH.js} +1 -1
- package/web/_astro/channel.DGZaFHZx.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.Cc9veUgf.js → chunk-2J33WTMH.Dt-9wf3h.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.Bec9c4eI.js → chunk-4BX2VUAB.CTC2sdoN.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.DoV8S1iB.js → chunk-55IACEB6.DQcxt2_g.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.DwR-Qlyj.js → chunk-727SXJPM.DXFPSn-a.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.ND_a81WY.js → chunk-AQP2D5EJ.BCx3U4bT.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.Wv_jwG48.js → chunk-FMBD7UC4.DL2tJkdO.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.CXKXCMmp.js → chunk-ND2GUHAM.DZyflMro.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.nkaoNYQq.js → chunk-QZHKN3VN.CUI2mT09.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.cMQcVlQu.js → classDiagram-4FO5ZUOK.g4rX4Fr1.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.cMQcVlQu.js → classDiagram-v2-Q7XG4LA2.g4rX4Fr1.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.OaDJ7Mr2.js → cose-bilkent-S5V4N54A.CzWJLqp0.js} +1 -1
- package/web/_astro/{cynefin-OW5HDTMX.Chi8IphF.js → cynefin-OW5HDTMX.WgsvQeCR.js} +1 -1
- package/web/_astro/{cytoscape.esm.DzSz-X2X.js → cytoscape.esm.BB4DxJjf.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.CzK2t_Fp.js → dagre-BM42HDAG.Dzv6ngql.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.DRvxlVS7.js → diagram-2AECGRRQ.CpJ4a9rU.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.CnYvNdwA.js → diagram-5GNKFQAL.CzPlF_dq.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.CpLpMw5R.js → diagram-KO2AKTUF.TAkZNTcQ.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.JTb78qUA.js → diagram-LMA3HP47.uCjoKSag.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.Bk-1jDIb.js → diagram-OG6HWLK6.eMplIjoK.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.D8hN9GZq.js → erDiagram-TEJ5UH35.Bf7zoXGz.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.-6zQr6m5.js → flowDiagram-I6XJVG4X.B_bHj3gN.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.DboLQ9ca.js → ganttDiagram-6RSMTGT7.BasrHRMj.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.4tYvJKGR.js → gitGraphDiagram-PVQCEYII.C6iphq1x.js} +1 -1
- package/web/_astro/index.DayyIngm.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.Bd9rXpsB.js → infoDiagram-5YYISTIA.HXmDMhW4.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.CvMoaf67.js → ishikawaDiagram-YF4QCWOH.BSmW8NiU.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.Ccy1CA7y.js → journeyDiagram-JHISSGLW.DEQow5fo.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.0MaMqHNS.js → kanban-definition-UN3LZRKU.IVm9cTdc.js} +1 -1
- package/web/_astro/{linear.CHXgcIbN.js → linear.CrsM73_9.js} +1 -1
- package/web/_astro/{mermaid.core.Ca-kcelG.js → mermaid.core.CfBeDJls.js} +6 -6
- package/web/_astro/{mindmap-definition-RKZ34NQL.BUIDlHa0.js → mindmap-definition-RKZ34NQL.C3j60Y-0.js} +1 -1
- package/web/_astro/ordinal.BYWQX77i.js +1 -0
- package/web/_astro/{pieDiagram-4H26LBE5.2dX3CU1s.js → pieDiagram-4H26LBE5.B-aCMeEA.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.B3LBlRiv.js → quadrantDiagram-W4KKPZXB.Cib965yq.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.X12I2uNx.js → requirementDiagram-4Y6WPE33.D61cS4O-.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.BXohIHqx.js → sankeyDiagram-5OEKKPKP.GKF2qVPy.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.C37ZIUzg.js → sequenceDiagram-3UESZ5HK.DZnq8F2h.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.BRgz317z.js → stateDiagram-AJRCARHV.DXUFmdgM.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.7VYSXN9-.js → stateDiagram-v2-BHNVJYJU.BtHmhLEz.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.BVNz_HiN.js → timeline-definition-PNZ67QCA.Cy-WW2ln.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.CHVDkPX4.js → vennDiagram-CIIHVFJN.SLp5b9KI.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.EQQ_qT9v.js → wardleyDiagram-YWT4CUSO.Bww45mWV.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.DrAT9WoP.js → xychartDiagram-2RQKCTM6.DR4swI6a.js} +1 -1
- package/web/apple-touch-icon.png +0 -0
- package/web/favicon.ico +0 -0
- package/web/favicon.svg +17 -4
- package/web/icon-192.png +0 -0
- package/web/icon-512.png +0 -0
- package/web/index.html +2 -2
- package/web/site.webmanifest +31 -0
- package/web/spur_logo.svg +1 -0
- package/plugins/sp/skills/spur-cli/references/team.md +0 -145
- package/web/_astro/BoardApp.DV9kx0wo.js +0 -1
- package/web/_astro/channel.BAI6xLeV.js +0 -1
- package/web/_astro/index.Dcr_8fiK.css +0 -1
- package/web/_astro/ordinal.DBvzRdQf.js +0 -1
|
@@ -60,18 +60,10 @@ states:
|
|
|
60
60
|
onEnter:
|
|
61
61
|
- kind: shell
|
|
62
62
|
options:
|
|
63
|
+
# (e) 0825: 8 lines — task check + show capture the investigate input bundle in the
|
|
64
|
+
# same soft probe; show must stay verbatim (it IS the bundle downstream reads).
|
|
63
65
|
command: >-
|
|
64
|
-
mkdir -p .spur/run &&
|
|
65
|
-
set +e &&
|
|
66
|
-
$spurBin task check $wbs; check_rc=$?;
|
|
67
|
-
$spurBin task show $wbs --json > .spur/run/$__runId-wayfinder-input.json; show_rc=$?;
|
|
68
|
-
set -e &&
|
|
69
|
-
if [ "$check_rc" -eq 0 ] && [ "$show_rc" -eq 0 ]; then
|
|
70
|
-
printf 'PASS\n' > .spur/run/$__runId-wayfinder-precheck.status;
|
|
71
|
-
else
|
|
72
|
-
printf 'FAIL\n' > .spur/run/$__runId-wayfinder-precheck.status;
|
|
73
|
-
fi &&
|
|
74
|
-
exit 0
|
|
66
|
+
mkdir -p .spur/run; $spurBin task check $wbs; c=$?; $spurBin task show $wbs --json > .spur/run/$__runId-wayfinder-input.json && [ "$c" -eq 0 ] && printf 'PASS\n' > .spur/run/$__runId-wayfinder-precheck.status || printf 'FAIL\n' > .spur/run/$__runId-wayfinder-precheck.status; exit 0
|
|
75
67
|
- kind: note
|
|
76
68
|
options:
|
|
77
69
|
message: "Wayfinder resolution started for task ${vars.wbs} (mode=${vars.resolutionMode}, evidence=${vars.evidencePolicy}); no code implementation pipeline is permitted."
|
|
@@ -86,22 +78,10 @@ states:
|
|
|
86
78
|
# Declared Layer-1 role (0538 R2): routing reason beside the agent: pin.
|
|
87
79
|
role: planner
|
|
88
80
|
mode: text
|
|
81
|
+
# (e) 0825: bounded reference-reading prompt (260 chars) — the authoring contract
|
|
82
|
+
# lives in the skill reference sp:wayfinder references/pipeline-resolution.md.
|
|
89
83
|
input: >-
|
|
90
|
-
Resolve task ${vars.wbs}
|
|
91
|
-
local bundle `.spur/run/${vars.__runId}-wayfinder-input.json` and only local shell/file
|
|
92
|
-
reads plus the `spur` CLI; do not use network search or MCP tools. Do not
|
|
93
|
-
invoke task-pipeline.yaml, /sp:dev-run, /sp:dev-runall, or code implementation.
|
|
94
|
-
Read the task file, map its existing Requirements and Acceptance Criteria to the
|
|
95
|
-
existing Design/Plan/References, then author concise Solution, Testing, and Review
|
|
96
|
-
sections through `spur task update --section --from-file`. Preserve the research
|
|
97
|
-
boundary. Finish with a short summary and stop. Evidence policy: ${vars.evidencePolicy}.
|
|
98
|
-
|
|
99
|
-
Evidence-anchor contract (mandatory — 0299 R1 line-anchor rule): when the task's
|
|
100
|
-
evidence lives in a shared evidence file, anchor every Solution/Testing `file:line`
|
|
101
|
-
citation truthfully — resolve the section's real start line with
|
|
102
|
-
`grep -n "^## <wbs> " <evidence-file>` and cite that exact line. NEVER copy a line
|
|
103
|
-
number from another ticket's example; each WBS anchors to its own section. Before
|
|
104
|
-
finishing, re-read each cited line and confirm it names the requirement's subject.
|
|
84
|
+
Resolve wayfinder task ${vars.wbs} per the sp:wayfinder skill (references/pipeline-resolution.md). Mode ${vars.resolutionMode}; evidence policy ${vars.evidencePolicy}; bundle .spur/run/${vars.__runId}-wayfinder-input.json. Finish with a short summary and stop.
|
|
105
85
|
answerFile: .spur/run/${vars.__runId}-wayfinder-answer.md
|
|
106
86
|
expectFile: .spur/run/${vars.__runId}-wayfinder-answer.md
|
|
107
87
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
@@ -121,6 +101,8 @@ states:
|
|
|
121
101
|
# proof digest via taskFile; a silent miss would degrade the proof to tree-only.
|
|
122
102
|
- kind: shell
|
|
123
103
|
options:
|
|
104
|
+
# (e) 0825: 6 lines — fail-closed lookup feeds every downstream artifact name;
|
|
105
|
+
# folding a silent miss into the digest would fake tree coverage.
|
|
124
106
|
command: >-
|
|
125
107
|
set -e;
|
|
126
108
|
task_path="$($spurBin task path $wbs --json | jq -r '.path // .filePath // empty')";
|
|
@@ -155,6 +137,8 @@ states:
|
|
|
155
137
|
command: "$spurBin task verdict $wbs --from-answer .spur/run/$__runId-wayfinder-verify-answer.txt"
|
|
156
138
|
- kind: shell
|
|
157
139
|
options:
|
|
140
|
+
# (e) 0825: 6 lines — stamp shell freezes the proof digest + capture point into the
|
|
141
|
+
# verdict before it is registered; the closing guard compares against this stamp.
|
|
158
142
|
command: >-
|
|
159
143
|
V=".spur/run/$wbs-verdict.json";
|
|
160
144
|
if [ -f "$V" ] && [ -n "$proofDigest" ]; then
|
|
@@ -246,6 +230,8 @@ transitions:
|
|
|
246
230
|
guard:
|
|
247
231
|
kind: shell
|
|
248
232
|
options:
|
|
233
|
+
# (e) 0825: 5-line guard — approval + digest-bracket + verdict PASS must all hold
|
|
234
|
+
# before record; dropping any operand would let a stale proof auto-record.
|
|
249
235
|
command: >-
|
|
250
236
|
test "$approval" = auto &&
|
|
251
237
|
test -n "$proofDigest" &&
|
|
@@ -130,91 +130,36 @@ states:
|
|
|
130
130
|
- kind: note
|
|
131
131
|
options:
|
|
132
132
|
message: "Resolving task list: ${vars.tasks} (proportional mode: ${vars.mode})"
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
# __runId, an unresolved task, a failed or malformed lookup, or a task
|
|
137
|
-
# not at a completed status records FAIL (routed to `failed` by the first
|
|
138
|
-
# declared edge) and is never re-interpreted as an empty list by a later
|
|
139
|
-
# sibling guard. The normalized, deduplicated list is persisted
|
|
140
|
-
# run-scoped; the route writer, metrics, prompts, notes and guards only
|
|
141
|
-
# ever read that capture.
|
|
133
|
+
# (d) wrapup-steps.ts resolve owns task capture and status resolution (0824);
|
|
134
|
+
# the wrapper only locates it (monorepo first, registered twin under node) and
|
|
135
|
+
# fails closed, writing FAIL for the failed defense edge — never PASS.
|
|
142
136
|
- kind: shell
|
|
143
137
|
options:
|
|
144
138
|
command: >-
|
|
145
139
|
mkdir -p .spur/run &&
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
fi &&
|
|
151
|
-
REASON_FILE=".spur/run/$RUN_ID-route-reason.txt" &&
|
|
152
|
-
STATUS_FILE=".spur/run/$RUN_ID-wrapup-resolve.status" &&
|
|
153
|
-
TASKS_FILE=".spur/run/$RUN_ID-wrapup-tasks.json" &&
|
|
154
|
-
if ! printf '%s' "$tasks" | jq -e 'type == "array" and all(.[]; type == "string" and test("^[0-9]{4}$"))' > /dev/null 2>&1; then
|
|
155
|
-
echo "task-resolve: tasks must be a JSON array of canonical four-digit WBS strings (whitespace is rejected, not trimmed)" >&2;
|
|
156
|
-
echo "failed:tasks is not a JSON array of canonical four-digit WBS strings" > "$REASON_FILE";
|
|
157
|
-
printf 'FAIL\n' > "$STATUS_FILE";
|
|
140
|
+
if [ -f plugins/sp/scripts/wrapup-steps.ts ]; then
|
|
141
|
+
bun plugins/sp/scripts/wrapup-steps.ts resolve;
|
|
142
|
+
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
143
|
+
node "$W" resolve;
|
|
158
144
|
else
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
fi;
|
|
170
|
-
done;
|
|
171
|
-
if [ "$RESOLVE_RC" -eq 0 ]; then
|
|
172
|
-
printf 'PASS\n' > "$STATUS_FILE";
|
|
173
|
-
else
|
|
174
|
-
echo "failed:unresolved or non-completed task (see $TASKS_FILE)" > "$REASON_FILE";
|
|
175
|
-
printf 'FAIL\n' > "$STATUS_FILE";
|
|
176
|
-
fi;
|
|
177
|
-
fi;
|
|
178
|
-
exit 0
|
|
179
|
-
# Route reason writer (0758 R3/R4 run-attribution pins intact). Runs AFTER
|
|
180
|
-
# validation and reads ONLY the validated run-scoped capture — never raw
|
|
181
|
-
# vars.tasks (0783 R2/R5); the fixed-path fallback is gone because
|
|
182
|
-
# validation refuses an empty __runId above. A FAIL resolve exits without
|
|
183
|
-
# writing: the failed reason written by validation stands, and the skip
|
|
184
|
-
# reason can never mask it. A missing/corrupted capture yields N=-1 and
|
|
185
|
-
# no skipped claim; the failed defense edge owns the run.
|
|
145
|
+
echo "wrapup-steps failed closed — script not found — run 'superskill install sp'" >&2;
|
|
146
|
+
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-resolve.status";
|
|
147
|
+
fi
|
|
148
|
+
# (e) route-reason writer: one jq table lookup over the mode var over the
|
|
149
|
+
# validated capture; workflow-local routing glue (0824). Runs AFTER validation
|
|
150
|
+
# and reads ONLY .spur/run/<runId>-wrapup-tasks.json — never raw vars.tasks
|
|
151
|
+
# (0783 R2/R5). A FAIL resolve exits without writing: the failed reason written
|
|
152
|
+
# by validation stands, and the skip reason can never mask it. A missing or
|
|
153
|
+
# corrupted capture fails the jq lookup (no skipped claim can be invented);
|
|
154
|
+
# the failed defense edge owns the run.
|
|
186
155
|
- kind: shell
|
|
187
156
|
options:
|
|
188
157
|
command: >-
|
|
189
|
-
mkdir -p .spur/run .spur/memory
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
fi &&
|
|
195
|
-
REASON_FILE=".spur/run/$RUN_ID-route-reason.txt" &&
|
|
196
|
-
STATUS_FILE=".spur/run/$RUN_ID-wrapup-resolve.status" &&
|
|
197
|
-
TASKS_FILE=".spur/run/$RUN_ID-wrapup-tasks.json" &&
|
|
198
|
-
if [ "$(cat "$STATUS_FILE" 2>/dev/null)" = FAIL ]; then
|
|
199
|
-
exit 0;
|
|
200
|
-
fi &&
|
|
201
|
-
N=$(jq length "$TASKS_FILE" 2>/dev/null || echo -1) &&
|
|
202
|
-
if [ "$N" -eq 0 ]; then
|
|
203
|
-
echo "skipped:empty task list" > "$REASON_FILE";
|
|
204
|
-
elif [ "$mode" = "fast" ]; then
|
|
205
|
-
echo "fast:evidence complete+consistent" > "$REASON_FILE";
|
|
206
|
-
elif [ -z "$mode" ]; then
|
|
207
|
-
echo "safety:missing evidence (mode empty)" > "$REASON_FILE";
|
|
208
|
-
elif [ "$mode" = "unknown" ]; then
|
|
209
|
-
echo "safety:unknown evidence quality" > "$REASON_FILE";
|
|
210
|
-
elif [ "$mode" = "conflict" ]; then
|
|
211
|
-
echo "safety:conflicting evidence" > "$REASON_FILE";
|
|
212
|
-
else
|
|
213
|
-
echo "safety:unrecognized evidence (mode=$mode)" > "$REASON_FILE";
|
|
214
|
-
fi &&
|
|
215
|
-
printf '%s %s\n' "$RUN_ID" "$(cat "$REASON_FILE")"
|
|
216
|
-
>> .spur/memory/wrapup-routes.log &&
|
|
217
|
-
exit 0
|
|
158
|
+
mkdir -p .spur/run .spur/memory; RUN_ID="$__runId"; case "$RUN_ID" in '') echo "task-resolve: __runId is empty — refusing to write a route reason" >&2; exit 1 ;; esac;
|
|
159
|
+
REASON_FILE=".spur/run/$RUN_ID-route-reason.txt"; case "$(cat ".spur/run/$RUN_ID-wrapup-resolve.status" 2>/dev/null)" in FAIL) exit 0 ;; esac;
|
|
160
|
+
N=$(jq length ".spur/run/$RUN_ID-wrapup-tasks.json" 2>/dev/null);
|
|
161
|
+
jq -rn --arg m "$mode" --arg n "$N" 'if $n == "0" then "skipped:empty task list" else {"fast":"fast:evidence complete+consistent","":"safety:missing evidence (mode empty)","unknown":"safety:unknown evidence quality","conflict":"safety:conflicting evidence"}[$m] // "safety:unrecognized evidence (mode=\($m))" end' > "$REASON_FILE";
|
|
162
|
+
printf '%s %s\n' "$RUN_ID" "$(cat "$REASON_FILE")" >> .spur/memory/wrapup-routes.log
|
|
218
163
|
|
|
219
164
|
- id: doc-sync
|
|
220
165
|
description: >
|
|
@@ -227,6 +172,8 @@ states:
|
|
|
227
172
|
a non-empty capture before the append; append is best-effort soft (empty capture
|
|
228
173
|
skips without aborting wrap-up).
|
|
229
174
|
onEnter:
|
|
175
|
+
# (warn) free-form prompt: no /sp:doc-evolve command surface yet (ADR-043
|
|
176
|
+
# residual, 0607 R2 one-query merge); capture is bounded by expectFile.
|
|
230
177
|
- kind: agent.run
|
|
231
178
|
options:
|
|
232
179
|
agent: ${vars.agent}
|
|
@@ -245,6 +192,8 @@ states:
|
|
|
245
192
|
answerFile: .spur/run/${vars.__runId}-wrapup-learnings.md
|
|
246
193
|
expectFile: .spur/run/${vars.__runId}-wrapup-learnings.md
|
|
247
194
|
timeoutMs: ${vars.stepTimeoutMs}
|
|
195
|
+
# (warn) learnings append is intentionally soft (empty capture skips
|
|
196
|
+
# without aborting wrap-up, 0607 R2).
|
|
248
197
|
- kind: shell
|
|
249
198
|
options:
|
|
250
199
|
command: >-
|
|
@@ -270,40 +219,20 @@ states:
|
|
|
270
219
|
is UNKNOWN telemetry, never proof of completion; previously written valid rows
|
|
271
220
|
survive a failure.
|
|
272
221
|
onEnter:
|
|
222
|
+
# (d) wrapup-steps.ts metrics owns the JSONL row append (0824); the wrapper
|
|
223
|
+
# only locates it and fails closed — FAIL, never a silent skip.
|
|
273
224
|
- kind: shell
|
|
274
225
|
options:
|
|
275
226
|
command: >-
|
|
276
|
-
mkdir -p .spur/run
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
echo "metrics-record: run-scoped task capture missing, corrupted or non-canonical — refusing to record metrics" >&2;
|
|
282
|
-
printf 'FAIL\n' > "$STATUS_FILE";
|
|
227
|
+
mkdir -p .spur/run &&
|
|
228
|
+
if [ -f plugins/sp/scripts/wrapup-steps.ts ]; then
|
|
229
|
+
bun plugins/sp/scripts/wrapup-steps.ts metrics;
|
|
230
|
+
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
231
|
+
node "$W" metrics;
|
|
283
232
|
else
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
feat=$(printf '%s' "$task_json" | jq -r '.frontmatter.feature_id // .feature_id // ""');
|
|
288
|
-
stat=$(printf '%s' "$task_json" | jq -r '.frontmatter.status // .status // "unknown"');
|
|
289
|
-
verdict="UNKNOWN";
|
|
290
|
-
if [ -f ".spur/run/$wbs-verdict.json" ]; then
|
|
291
|
-
v=$(jq -r '.verdict // "UNKNOWN"' ".spur/run/$wbs-verdict.json" 2>/dev/null || true);
|
|
292
|
-
if [ -n "$v" ]; then verdict="$v"; fi;
|
|
293
|
-
fi;
|
|
294
|
-
ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ");
|
|
295
|
-
if ! jq -cn --arg wbs "$wbs" --arg feature_id "$feat" --arg status "$stat" --arg verdict "$verdict" --arg timestamp "$ts" '{wbs:$wbs, feature_id:$feature_id, status:$status, verdict:$verdict, timestamp:$timestamp}' >> .spur/memory/wrapup-metrics.jsonl; then
|
|
296
|
-
echo "metrics-record: metrics append failed for task $wbs — recording FAIL instead of claiming the row landed" >&2;
|
|
297
|
-
METRICS_RC=1;
|
|
298
|
-
fi;
|
|
299
|
-
else
|
|
300
|
-
echo "metrics-record: task $wbs lookup failed or was malformed — recording FAIL instead of silently omitting its metrics row" >&2;
|
|
301
|
-
METRICS_RC=1;
|
|
302
|
-
fi;
|
|
303
|
-
done;
|
|
304
|
-
if [ "$METRICS_RC" -eq 0 ]; then printf 'PASS\n' > "$STATUS_FILE"; else printf 'FAIL\n' > "$STATUS_FILE"; fi;
|
|
305
|
-
fi;
|
|
306
|
-
exit 0
|
|
233
|
+
echo "wrapup-steps failed closed — script not found — run 'superskill install sp'" >&2;
|
|
234
|
+
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-metrics.status";
|
|
235
|
+
fi
|
|
307
236
|
|
|
308
237
|
- id: feature-transition
|
|
309
238
|
description: >
|
|
@@ -320,94 +249,24 @@ states:
|
|
|
320
249
|
(the engine only enters this state when vars.feature is set) and fails
|
|
321
250
|
loud (dogfood 2026-08-15, feature I3).
|
|
322
251
|
onEnter:
|
|
323
|
-
#
|
|
324
|
-
#
|
|
325
|
-
#
|
|
326
|
-
#
|
|
327
|
-
# writes PASS
|
|
328
|
-
#
|
|
329
|
-
# the plain `spur feature sync` verb.
|
|
330
|
-
# R1 (0625): a feature transition that changed state may have left
|
|
331
|
-
# cross-task fallout the per-task fast gates never see. The
|
|
332
|
-
# affected-feature gate (featureGateCmd) runs after an applied sync OR a
|
|
333
|
-
# non-zero exit that may follow a partial multi-hop transition. It is a
|
|
334
|
-
# diagnostic only: a gate PASS can never convert a failed sync into
|
|
335
|
-
# success, and a gate FAIL fails the step (0770 failure routing).
|
|
336
|
-
# NOTE: do not add
|
|
337
|
-
# `#` comments INSIDE the folded shell string — YAML `>-` folds them onto
|
|
338
|
-
# the following statement line and comments it out.
|
|
252
|
+
# (d) wrapup-steps.ts feature-transition owns the bounded sync, observation
|
|
253
|
+
# and the gate (0824); the wrapper only locates it and fails closed. The
|
|
254
|
+
# script terminates exit 0 on every path so artifacts that already landed
|
|
255
|
+
# are never discarded; soft TERMINATION is not soft TRUTH — only a verified
|
|
256
|
+
# sync writes PASS (0783 R4). A gate PASS can never convert a failed sync
|
|
257
|
+
# into success, and a gate FAIL fails the step (0770 failure routing).
|
|
339
258
|
- kind: shell
|
|
340
259
|
options:
|
|
341
260
|
command: >-
|
|
342
261
|
mkdir -p .spur/run &&
|
|
343
|
-
if [ -
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
SYNC_OUTPUT=$(if [ -f plugins/sp/scripts/feature-sync-bounded.ts ]; then
|
|
348
|
-
bun plugins/sp/scripts/feature-sync-bounded.ts "$feature" --spur-bin "$spurBin" --json;
|
|
349
|
-
elif SYNC_MJS="$(superskill script path sp feature-sync-bounded.mjs 2>/dev/null)" && [ -f "$SYNC_MJS" ]; then
|
|
350
|
-
node "$SYNC_MJS" "$feature" --spur-bin "$spurBin" --json;
|
|
351
|
-
else
|
|
352
|
-
$spurBin feature sync "$feature" --json;
|
|
353
|
-
fi);
|
|
354
|
-
SYNC_RC=$?;
|
|
355
|
-
printf '%s\n' "$SYNC_OUTPUT";
|
|
356
|
-
OBSERVED=$($spurBin feature show "$feature" --json 2>/dev/null | jq -r '.status // .frontmatter.status // empty' 2>/dev/null || true);
|
|
357
|
-
if [ -z "$OBSERVED" ]; then OBSERVED=unreadable; fi;
|
|
358
|
-
APPLIED=unreadable;
|
|
359
|
-
SYNC_OK=0;
|
|
360
|
-
REASON="";
|
|
361
|
-
if [ "$SYNC_RC" -ne 0 ]; then
|
|
362
|
-
REASON="sync exited nonzero (rc=$SYNC_RC)";
|
|
363
|
-
elif ! printf '%s' "$SYNC_OUTPUT" | jq -e 'type == "object" and (.proposal | type == "object") and (.proposal.featureId | type == "string") and (.proposal.from | type == "string") and (.proposal.to | type == "string") and (.applied | type == "boolean")' > /dev/null 2>&1; then
|
|
364
|
-
REASON="malformed or unreadable sync result";
|
|
365
|
-
else
|
|
366
|
-
P_FROM=$(printf '%s' "$SYNC_OUTPUT" | jq -r '.proposal.from // ""');
|
|
367
|
-
P_TO=$(printf '%s' "$SYNC_OUTPUT" | jq -r '.proposal.to // ""');
|
|
368
|
-
APPLIED=$(printf '%s' "$SYNC_OUTPUT" | jq -r '.applied');
|
|
369
|
-
if [ "$(printf '%s' "$SYNC_OUTPUT" | jq -r '.proposal.featureId // ""')" != "$feature" ]; then
|
|
370
|
-
REASON="sync proposal does not match feature $feature";
|
|
371
|
-
elif [ "$(printf '%s' "$SYNC_OUTPUT" | jq -r '.proposal.gateBlocked // false')" = "true" ]; then
|
|
372
|
-
REASON="sync proposal is gate-blocked — a blocked sync is not a no-change success";
|
|
373
|
-
elif [ "$(printf '%s' "$SYNC_OUTPUT" | jq -r '.proposal.requiresConfirm // false')" = "true" ]; then
|
|
374
|
-
REASON="sync proposal requires operator confirmation";
|
|
375
|
-
elif [ "$APPLIED" = "true" ] && [ "$OBSERVED" != "$P_TO" ]; then
|
|
376
|
-
REASON="applied sync did not land on the proposal target (observed=$OBSERVED, to=$P_TO)";
|
|
377
|
-
elif [ "$APPLIED" = "false" ] && { [ "$P_FROM" != "$P_TO" ] || [ "$OBSERVED" != "$P_TO" ]; }; then
|
|
378
|
-
REASON="sync applied nothing without a from==to observed no-op (from=$P_FROM, to=$P_TO, observed=$OBSERVED)";
|
|
379
|
-
else
|
|
380
|
-
SYNC_OK=1;
|
|
381
|
-
fi;
|
|
382
|
-
fi;
|
|
383
|
-
GATE="skipped";
|
|
384
|
-
if [ "$APPLIED" = "true" ] || [ "$SYNC_RC" -ne 0 ]; then
|
|
385
|
-
echo "feature-transition: sync applied or failed after a possible partial transition for $feature — running feature gate: $featureGateCmd";
|
|
386
|
-
if sh -c "$featureGateCmd"; then
|
|
387
|
-
GATE="PASS";
|
|
388
|
-
echo "feature-transition: feature gate PASS for feature $feature";
|
|
389
|
-
else
|
|
390
|
-
GATE="FAIL";
|
|
391
|
-
echo "feature-transition: feature gate FAIL for feature $feature — inspect findings before reporting the transition complete" >&2;
|
|
392
|
-
fi;
|
|
393
|
-
else
|
|
394
|
-
echo "feature-transition: sync did not apply a transition (rc=$SYNC_RC, applied=$APPLIED) — feature gate skipped";
|
|
395
|
-
fi;
|
|
396
|
-
SYNC_STATUS="PASS";
|
|
397
|
-
if [ "$SYNC_OK" -ne 1 ] || [ "$GATE" = "FAIL" ]; then
|
|
398
|
-
SYNC_STATUS="FAIL";
|
|
399
|
-
echo "feature-transition: required synchronization failed for $feature — $REASON; gate=$GATE" >&2;
|
|
400
|
-
elif [ "$APPLIED" = "false" ]; then
|
|
401
|
-
echo "feature-transition: feature sync verified for $feature (from==to observed at $OBSERVED, gate=$GATE) — explicit no-change";
|
|
402
|
-
else
|
|
403
|
-
echo "feature-transition: feature sync verified for $feature (applied, observed=$OBSERVED, gate=$GATE)";
|
|
404
|
-
fi;
|
|
405
|
-
if [ "$SYNC_STATUS" = "PASS" ]; then
|
|
406
|
-
printf 'PASS\n' > ".spur/run/$__runId-wrapup-sync.status";
|
|
262
|
+
if [ -f plugins/sp/scripts/wrapup-steps.ts ]; then
|
|
263
|
+
bun plugins/sp/scripts/wrapup-steps.ts feature-transition;
|
|
264
|
+
elif W="$(superskill script path sp wrapup-steps.mjs 2>/dev/null)" && [ -f "$W" ]; then
|
|
265
|
+
node "$W" feature-transition;
|
|
407
266
|
else
|
|
267
|
+
echo "wrapup-steps failed closed — script not found — run 'superskill install sp'" >&2;
|
|
408
268
|
printf 'FAIL\n' > ".spur/run/$__runId-wrapup-sync.status";
|
|
409
|
-
fi
|
|
410
|
-
exit 0
|
|
269
|
+
fi
|
|
411
270
|
|
|
412
271
|
- id: branch-cleanup
|
|
413
272
|
description: >
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.82",
|
|
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",
|
|
@@ -53,14 +53,14 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@commander-js/extra-typings": "^14.0.0",
|
|
56
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
57
|
-
"@gobing-ai/ts-ai-runner": "^0.4.
|
|
58
|
-
"@gobing-ai/ts-dual-workflow-engine": "^0.4.
|
|
59
|
-
"@gobing-ai/ts-infra": "^0.4.
|
|
60
|
-
"@gobing-ai/ts-llm-jsonl-importer": "^0.4.
|
|
61
|
-
"@gobing-ai/ts-rule-engine": "^0.4.
|
|
62
|
-
"@gobing-ai/ts-runtime": "^0.4.
|
|
63
|
-
"@gobing-ai/ts-utils": "^0.4.
|
|
56
|
+
"@gobing-ai/ts-db": "^0.4.66",
|
|
57
|
+
"@gobing-ai/ts-ai-runner": "^0.4.66",
|
|
58
|
+
"@gobing-ai/ts-dual-workflow-engine": "^0.4.66",
|
|
59
|
+
"@gobing-ai/ts-infra": "^0.4.66",
|
|
60
|
+
"@gobing-ai/ts-llm-jsonl-importer": "^0.4.66",
|
|
61
|
+
"@gobing-ai/ts-rule-engine": "^0.4.66",
|
|
62
|
+
"@gobing-ai/ts-runtime": "^0.4.66",
|
|
63
|
+
"@gobing-ai/ts-utils": "^0.4.66",
|
|
64
64
|
"@types/bun": "1.3.14",
|
|
65
65
|
"@types/figlet": "^1.7.0",
|
|
66
66
|
"@types/node-notifier": "8.0.5",
|
package/plugins/sp/README.md
CHANGED
|
@@ -185,7 +185,7 @@ pipeline step.
|
|
|
185
185
|
|
|
186
186
|
```
|
|
187
187
|
plugins/sp/
|
|
188
|
-
├── skills/ # Domain knowledge + workflow docs (
|
|
188
|
+
├── skills/ # Domain knowledge + workflow docs (34 skills)
|
|
189
189
|
│ ├── brainstorm/ # Structured ideation workflow
|
|
190
190
|
│ │ ├── agents/openai.yaml
|
|
191
191
|
│ │ ├── examples/ideation-example.md
|
|
@@ -227,6 +227,8 @@ plugins/sp/
|
|
|
227
227
|
│ │ ├── features.md + features/{verbs, acceptance-criteria, roadmap-priority}.md
|
|
228
228
|
│ │ ├── rules.md + rules/{operations, authoring-rules, fine-tuning, validation-and-extension}.md
|
|
229
229
|
│ │ └── workflows.md + workflows/{operations, authoring-workflows, validation-and-extension}.md
|
|
230
|
+
│ ├── spur-composer/ # Cross-noun selection, composition ladder, rule tuning; applies doctor proposals
|
|
231
|
+
│ ├── spur-doctor/ # Read-only artifact evaluation → proposal table (backs spur-composer)
|
|
230
232
|
│ ├── spur-dev/ # Thin planning→execution orchestration spine
|
|
231
233
|
│ │ └── references/ # ac-style-guide, cross-cutting, decision-brief, dev-operations,
|
|
232
234
|
│ │ execution-batch, execution-workflow, feature-link-helper,
|
|
@@ -330,7 +332,13 @@ surface or run one workflow. All skills target the same five core platforms: `cl
|
|
|
330
332
|
| `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 |
|
|
331
333
|
| `history-anatomy` | 1.0 | Diagnostic interpretation owner over already-imported history — daily/ad-hoc mode contract, closed finding taxonomy, twelve-section report contract, `enrich`/`validate` rubrics; no workflow launch, no JSONL fallback, no corpus mutation |
|
|
332
334
|
| `session-review` | 1.1 | Inline review of the active coding-agent session — compact outcomes, evidence-backed resolved/open issue classification, proposal-only improvements, and next actions; no workflow, import, delegation, or mutation |
|
|
335
|
+
| `spur-composer` | 1.0 | Cross-noun composition — workflow catalog selection, the ephemeral→project→shared ladder, ADR-115 budgets, trace-driven rule tuning; applies accepted `spur-doctor` proposals through `spur` verbs; never judges its own output and never runs a recurring loop |
|
|
336
|
+
| `spur-doctor` | 1.0 | Cross-noun evaluation — read-only CLI evidence per noun (task/feature/rule/workflow/agent spec), reflection over `history-anatomy` findings through a closed action-class map, and a proposal table; writes nothing; diagnoses artifacts, not runtime environments (`spur agent doctor`'s job) |
|
|
333
337
|
| `redesign-web-ui` | 1.0 | Existing-UI visual upgrade — audit generic AI fingerprints, apply in-stack polish against `DESIGN.md` / live tokens, verify behavior and viewports; does not migrate frameworks |
|
|
338
|
+
| `taste-refactoring-api` | — | API design and refactoring for REST/HTTP, RPC/gRPC, GraphQL, and event contracts; compatibility, security, and migration review |
|
|
339
|
+
| `taste-refactoring-ui` | — | UI design and refactoring with visual hierarchy, typography, spacing, color, and interaction review |
|
|
340
|
+
| `taste-refactoring-architect` | — | Architecture review, simplification, and refactoring; boundary modeling, dependency reduction, and migration planning |
|
|
341
|
+
| `taste-refactoring-tests` | — | Test suite refactoring for failure sensitivity, regression detection, and assertion strength; eliminates brittle mocks |
|
|
334
342
|
|
|
335
343
|
#### Bounded coexistence and retirement gate — `sp:issue-finding` (HA-S1 0661)
|
|
336
344
|
|
|
@@ -488,12 +496,13 @@ hold `SKILL.md` and prompt-side companions only.
|
|
|
488
496
|
| `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` |
|
|
489
497
|
| `hooks/careful-guard.ts` | Opt-in destructive-command guard (unwired — see Hooks above) |
|
|
490
498
|
| `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 |
|
|
499
|
+
| `scripts/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 |
|
|
491
500
|
| `scripts/dogfood-testing/detect-pipeline-driving.ts` | Word-boundary detector for pipeline-driving testees (leading-space invariant) |
|
|
492
501
|
| `scripts/dogfood-testing/validate-report.ts` | Pure `validateReport(md)` — footer-mandatory + 7-check finalize-or-abort contract with stable error codes |
|
|
493
502
|
| `scripts/daily-summary/{daily-summary,logger}.ts` | ccusage + git-history orchestration helpers for `sp:daily-summary` |
|
|
494
503
|
| `scripts/feature-sync-bounded.ts` | Bounded retry-suppression wrapper for `spur feature sync` during batch/wrap-up runs — suppresses identical L4-blocked repeats |
|
|
495
504
|
| `scripts/stage-registry-adapter.ts` | dev-next golden-path adapter over the canonical stage registry — TABLE A/B/C resolution bridge for the status-aware facade |
|
|
496
|
-
| `scripts/task-size-precheck.ts` | Pipeline size precheck guard (R2)
|
|
505
|
+
| `scripts/task-size-precheck.ts` | Pipeline size precheck guard (R2) — evaluates R-item/Plan-count limits to PASS/FAIL |
|
|
497
506
|
| `scripts/validate-flag-contracts.ts` | Mechanical consistency gate — compares flag claims across command files, flag-glossary, cross-cutting, dev-operations, and ADR; reports disagreements |
|
|
498
507
|
| `*.test.ts` | Unit suites — in `hooks/` for guards, in `tests/<skill>/` per ADR-031 pairing |
|
|
499
508
|
|
|
@@ -527,7 +536,7 @@ graph TB
|
|
|
527
536
|
end
|
|
528
537
|
|
|
529
538
|
subgraph "Execution layer"
|
|
530
|
-
CLI["spur CLI<br/>task · feature · rule · workflow<br/>· agent · history ·
|
|
539
|
+
CLI["spur CLI<br/>task · feature · rule · workflow<br/>· agent · history · message"]
|
|
531
540
|
SCRIPT["hooks/task-write-guard.ts"]
|
|
532
541
|
end
|
|
533
542
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: expert-spur
|
|
3
3
|
description: |
|
|
4
|
-
Use PROACTIVELY for "create tasks for this feature", "update all task statuses", "audit task traceability", "create a feature with acceptance criteria", "harden the rule catalog", "author a batch of workflows", or "expert-spur". Multi-step corpus work across `spur task`, `feature`, `rule`,
|
|
4
|
+
Use PROACTIVELY for "create tasks for this feature", "update all task statuses", "audit task traceability", "create a feature with acceptance criteria", "harden the rule catalog", "author a batch of workflows", "compose a workflow", "tune a rule", "apply accepted doctor proposals", "evaluate spur artifact health", "reflect over history findings", or "expert-spur". Multi-step corpus work across `spur task`, `feature`, `rule`, `workflow`, and agent specs: batch creation, status sweeps, section campaigns, traceability audits, rule hardening, workflow authoring/refactoring, composition and tuning (sp:spur-composer), and evaluation/reflection proposal passes (sp:spur-doctor). For one deterministic operation, run the CLI directly. Recurring evolution loops and multi-agent coordination belong to sp:super-planner — never this agent.
|
|
5
5
|
|
|
6
6
|
<example>
|
|
7
7
|
Context: Batch task status update across a feature.
|
|
@@ -12,19 +12,23 @@ description: |
|
|
|
12
12
|
tools: [Read, Grep, Glob, Bash, Skill]
|
|
13
13
|
model: inherit
|
|
14
14
|
color: green
|
|
15
|
-
skills: [sp:spur-cli]
|
|
15
|
+
skills: [sp:spur-cli, sp:spur-composer, sp:spur-doctor]
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# Expert Spur
|
|
19
19
|
|
|
20
20
|
Thin specialist for multi-step Spur **corpus** work. The backend skill `sp:spur-cli` owns noun,
|
|
21
21
|
verb, flag, output, and exit semantics; this agent selects its task/feature/rule/workflow reference,
|
|
22
|
-
sequences operations, and evaluates each result before continuing.
|
|
22
|
+
sequences operations, and evaluates each result before continuing. Composition, tuning, evaluation
|
|
23
|
+
and reflection campaigns are method-backed by `sp:spur-composer` and `sp:spur-doctor`; their verbs
|
|
24
|
+
and flags still resolve through the `sp:spur-cli` references.
|
|
23
25
|
|
|
24
26
|
## Role
|
|
25
27
|
|
|
26
|
-
You are the Spur corpus steward: a specialist sequencer over `skill: sp:spur-cli`,
|
|
27
|
-
|
|
28
|
+
You are the Spur corpus steward: a specialist sequencer over `skill: sp:spur-cli`, backed by
|
|
29
|
+
`sp:spur-composer` (select, compose, tune, apply) and `sp:spur-doctor` (evaluate, reflect, propose).
|
|
30
|
+
You are not a second implementation of the CLI or lifecycle spine, not a coordinator, and not a
|
|
31
|
+
recurring loop.
|
|
28
32
|
|
|
29
33
|
## Scope
|
|
30
34
|
|
|
@@ -34,19 +38,28 @@ Use for:
|
|
|
34
38
|
- Cross-corpus traceability or structural audits.
|
|
35
39
|
- Rule catalog authoring, validation, execution, and hardening.
|
|
36
40
|
- Workflow fit decisions, authoring/refactoring, validation, dry-runs, and trace comparison.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
- Composition and tuning campaigns via `sp:spur-composer`: catalog selection, the composition
|
|
42
|
+
ladder, trace-driven rule tuning, and applying accepted doctor proposals.
|
|
43
|
+
- Evaluation and reflection campaigns via `sp:spur-doctor`: read-only evidence, history-finding
|
|
44
|
+
reflection, and a proposal table.
|
|
45
|
+
|
|
46
|
+
One bounded campaign per dispatch. Do not use for one CLI invocation. Do not use for
|
|
47
|
+
planning→implementation→verification lifecycle or batch task execution; `sp:spur-dev` owns that
|
|
48
|
+
orchestration. Recurring evolution loops and multi-agent coordination are not this agent's duty —
|
|
49
|
+
they hand off to `sp:super-planner` or a workflow (§ Hand-offs). The backend skill covers the other
|
|
40
50
|
CLI nouns for direct use, but they are not this corpus specialist's scope.
|
|
41
51
|
|
|
42
52
|
## Process
|
|
43
53
|
|
|
44
54
|
1. Load `plugins/sp/skills/spur-cli/SKILL.md` and the exact noun reference before invoking a verb.
|
|
45
|
-
2.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
2. For compose/tune/apply work, load `plugins/sp/skills/spur-composer/SKILL.md` first; for
|
|
56
|
+
evaluate/reflect/propose work, load `plugins/sp/skills/spur-doctor/SKILL.md` first. Follow the
|
|
57
|
+
owning skill's method; never restate it here.
|
|
58
|
+
3. Resolve and freeze the target set. Report ambiguity instead of guessing identifiers or flags.
|
|
59
|
+
4. Run the noun's read/check/validate path before mutation where available.
|
|
60
|
+
5. Mutate only through `spur`; parse `--json` output when the verb advertises it.
|
|
61
|
+
6. Inspect each result before the next dependent operation; stop on structural or validation failure.
|
|
62
|
+
7. Run affected-input checks after mutation (constitution T11): after task/feature batch writes,
|
|
50
63
|
run `spur task check <wbs>` / `spur feature check <id>` for each changed document and its
|
|
51
64
|
required linked evidence — not a corpus sweep. The explicit unsuppressed audit
|
|
52
65
|
(`spur task check --corpus --json`) is reserved for checker-policy changes (T10).
|
|
@@ -71,13 +84,19 @@ their runbook here.
|
|
|
71
84
|
- Reimplement CLI validation in prose or shell.
|
|
72
85
|
- Never drive the planning/execution lifecycle; do not run application implementation or task
|
|
73
86
|
pipelines through this agent.
|
|
87
|
+
- Drive a task batch through execution, chain campaigns into a recurring loop, or dispatch and
|
|
88
|
+
coordinate multiple agents — no batch driving, no recurring loops, no coordination dispatch here;
|
|
89
|
+
they hand off to `sp:super-planner` or a workflow.
|
|
90
|
+
- Use `spur agent loop` — a supervisor-internal, forbidden surface. Agent specs are read through
|
|
91
|
+
`spur agent list --specs`.
|
|
74
92
|
|
|
75
93
|
## Output Format
|
|
76
94
|
|
|
77
95
|
```markdown
|
|
78
96
|
## Spur Corpus Operations Report
|
|
79
97
|
|
|
80
|
-
**Noun(s):** task | feature | rule | workflow
|
|
98
|
+
**Noun(s):** task | feature | rule | workflow | agent spec
|
|
99
|
+
**Method:** corpus campaign | compose/tune (`sp:spur-composer`) | evaluate/reflect (`sp:spur-doctor`)
|
|
81
100
|
**Scope:** <resolved ids/files>
|
|
82
101
|
**Confidence:** HIGH | MEDIUM | LOW
|
|
83
102
|
|
|
@@ -95,11 +114,14 @@ their runbook here.
|
|
|
95
114
|
|
|
96
115
|
## Platform Notes
|
|
97
116
|
|
|
98
|
-
- Claude Code:
|
|
99
|
-
- Other platforms: invoke `sp
|
|
117
|
+
- Claude Code: load the bound skill the campaign needs — `Skill(skill="sp:spur-cli" | "sp:spur-composer" | "sp:spur-doctor", args="<query>")` — then Bash for `spur`.
|
|
118
|
+
- Other platforms: invoke the bound `sp:*` skill directly; the agent wrapper is optional.
|
|
100
119
|
|
|
101
|
-
##
|
|
120
|
+
## Hand-offs
|
|
102
121
|
|
|
103
|
-
|
|
122
|
+
This agent runs one bounded campaign per dispatch and reports. Batch driving of task pipelines,
|
|
123
|
+
recurring evolution loops, and multi-agent coordination are not dispatch duties here — hand them
|
|
124
|
+
to `sp:super-planner` or a workflow definition. If the operator explicitly asks for a follow-up
|
|
125
|
+
corpus dispatch, its surface contract is
|
|
104
126
|
[dispatch-surface.md](../skills/parallel-execution/references/dispatch-surface.md): native subagent
|
|
105
|
-
by default, `spur agent run` only on a named trigger
|
|
127
|
+
by default, `spur agent run` only on a named trigger — never `spur agent loop`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/commands/bundle-plugin-lib.ts — do not edit.
|
|
3
|
+
* Source of truth: packages/app/src/workflow/idea-handoff-cli.ts (task 0824).
|
|
4
|
+
*/
|
|
5
|
+
export declare interface IdeaHandoffCliEnv {
|
|
6
|
+
__runId?: string;
|
|
7
|
+
featureId?: string;
|
|
8
|
+
spurBin?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare interface IdeaHandoffCliOutcome {
|
|
11
|
+
exitCode: number;
|
|
12
|
+
result?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export declare function runIdeaHandoffCli(
|
|
15
|
+
env: IdeaHandoffCliEnv,
|
|
16
|
+
run?: (input: { runId: string; featureId: string; spurBin: string }) => Promise<unknown>,
|
|
17
|
+
): Promise<IdeaHandoffCliOutcome>;
|