@gobing-ai/spur 0.3.60 → 0.3.61
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 +2 -2
- package/config/config.global.yaml +11 -7
- package/config/corpus-baseline.json +96 -8
- package/config/workflow-composition-baseline.json +1 -1
- package/config/workflows/wayfinder-resolution.yaml +4 -6
- package/package.json +1 -1
- package/plugins/README.md +5 -4
- package/plugins/sp/README.md +3 -3
- package/plugins/sp/agents/super-planner.md +1 -1
- package/plugins/sp/commands/dev-pr-review.md +1 -1
- package/plugins/sp/commands/dev-wrap.md +2 -2
- package/plugins/sp/commands/dev-wrapall.md +2 -2
- package/plugins/sp/plugin.json +1 -1
- package/plugins/sp/references/roles.md +12 -9
- package/plugins/sp/scripts/surface-drift-inventory.ts +51 -17
- package/plugins/sp/scripts/validate-commands.ts +11 -4
- package/plugins/sp/skills/code-verification/SKILL.md +1 -1
- package/plugins/sp/skills/code-verification/references/verdict-schema.md +1 -1
- package/plugins/sp/skills/issue-finding/SKILL.md +1 -1
- package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
- package/plugins/sp/skills/pr-reviewing/SKILL.md +2 -2
- package/plugins/sp/skills/spec-decomposition/references/decomposition.md +1 -1
- package/plugins/sp/skills/spur-cli/references/init.md +1 -1
- package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +1 -1
- package/plugins/sp/skills/spur-cli/references/workflows/operations.md +1 -1
- package/plugins/sp/skills/spur-cli/references/workflows.md +4 -4
- package/plugins/sp/skills/spur-dev/SKILL.md +4 -4
- package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +4 -4
- package/plugins/sp/skills/spur-dev/references/dev-operations.md +9 -9
- package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +1 -1
- package/plugins/sp/skills/spur-dev/references/execution-batch.md +3 -3
- package/plugins/sp/skills/spur-dev/references/execution-workflow.md +1 -1
- package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +3 -2
- package/plugins/sp/skills/spur-dev/references/gate-checklists.md +1 -1
- package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +5 -2
- package/plugins/sp/skills/spur-dev/references/planning-workflow.md +2 -2
- package/schemas/spur-config.schema.json +1 -1
- package/spur.js +203 -83
- package/web/_astro/BoardApp.BtRfVADq.js +1 -0
- package/web/_astro/{BoardApp.BJs3l7O8.js → BoardApp.CBIzcvqi.js} +100 -101
- package/web/_astro/{TaskDetail.B0l1uzsB.js → TaskDetail.D2N60cfE.js} +1 -1
- package/web/_astro/{arc.DPruHC3P.js → arc.D-EfJJwf.js} +1 -1
- package/web/_astro/{architectureDiagram-3BPJPVTR.CuOqAck6.js → architectureDiagram-3BPJPVTR.CgvTTzqp.js} +1 -1
- package/web/_astro/{blockDiagram-GPEHLZMM.Cxb7HDIA.js → blockDiagram-GPEHLZMM.CnOohvvn.js} +1 -1
- package/web/_astro/{c4Diagram-AAUBKEIU.Dw7wa-0S.js → c4Diagram-AAUBKEIU.BFcBGUy_.js} +1 -1
- package/web/_astro/channel.kIu33Gui.js +1 -0
- package/web/_astro/{chunk-2J33WTMH.MECQitzo.js → chunk-2J33WTMH.C-6MR-XY.js} +1 -1
- package/web/_astro/{chunk-4BX2VUAB.p3ofhIGE.js → chunk-4BX2VUAB.BN4LP5AR.js} +1 -1
- package/web/_astro/{chunk-55IACEB6.BmQGsPZP.js → chunk-55IACEB6.tUJ_CTtZ.js} +1 -1
- package/web/_astro/{chunk-727SXJPM.CwrK23OA.js → chunk-727SXJPM.BNCk-sxv.js} +1 -1
- package/web/_astro/{chunk-AQP2D5EJ.CUKI_QXp.js → chunk-AQP2D5EJ.BkpFIbNa.js} +1 -1
- package/web/_astro/{chunk-FMBD7UC4.7AtDgShM.js → chunk-FMBD7UC4.DcSZ87PN.js} +1 -1
- package/web/_astro/{chunk-ND2GUHAM.f_YJbTs3.js → chunk-ND2GUHAM.BkLvHFFf.js} +1 -1
- package/web/_astro/{chunk-QZHKN3VN.0q7V3gEg.js → chunk-QZHKN3VN.HOdgszax.js} +1 -1
- package/web/_astro/{classDiagram-4FO5ZUOK.C_hG3HMK.js → classDiagram-4FO5ZUOK.CWfRiY6b.js} +1 -1
- package/web/_astro/{classDiagram-v2-Q7XG4LA2.C_hG3HMK.js → classDiagram-v2-Q7XG4LA2.CWfRiY6b.js} +1 -1
- package/web/_astro/{cose-bilkent-S5V4N54A.vsaaaEMy.js → cose-bilkent-S5V4N54A.C6j4PxoN.js} +1 -1
- package/web/_astro/{dagre-BM42HDAG.BN7XFqQ4.js → dagre-BM42HDAG.BATZG1II.js} +1 -1
- package/web/_astro/{diagram-2AECGRRQ.ED6AfryZ.js → diagram-2AECGRRQ.B0f5yY6x.js} +1 -1
- package/web/_astro/{diagram-5GNKFQAL.Dxllzg8R.js → diagram-5GNKFQAL.Bewupqv0.js} +1 -1
- package/web/_astro/{diagram-KO2AKTUF.RuWppieD.js → diagram-KO2AKTUF.C23r1tB2.js} +1 -1
- package/web/_astro/{diagram-LMA3HP47.CL32Xn6s.js → diagram-LMA3HP47.DUErdBOR.js} +1 -1
- package/web/_astro/{diagram-OG6HWLK6.CUneEhqB.js → diagram-OG6HWLK6.BubmwAjb.js} +1 -1
- package/web/_astro/{erDiagram-TEJ5UH35.DI-92Lec.js → erDiagram-TEJ5UH35.BE_Qs5mv.js} +1 -1
- package/web/_astro/{flowDiagram-I6XJVG4X.69Aqa1FF.js → flowDiagram-I6XJVG4X.COWdbzon.js} +1 -1
- package/web/_astro/{ganttDiagram-6RSMTGT7.DdpClZpa.js → ganttDiagram-6RSMTGT7.5EGYC4MK.js} +1 -1
- package/web/_astro/{gitGraphDiagram-PVQCEYII.xqWfkvB4.js → gitGraphDiagram-PVQCEYII.bUUV7iEw.js} +1 -1
- package/web/_astro/index.Cestp9nh.css +1 -0
- package/web/_astro/{infoDiagram-5YYISTIA.B3G5sfKm.js → infoDiagram-5YYISTIA.CbiInFvz.js} +1 -1
- package/web/_astro/{ishikawaDiagram-YF4QCWOH.ahVNsoAQ.js → ishikawaDiagram-YF4QCWOH.CB7lrSsJ.js} +1 -1
- package/web/_astro/{journeyDiagram-JHISSGLW.PmFHLc-X.js → journeyDiagram-JHISSGLW.rhGZgWt8.js} +1 -1
- package/web/_astro/{kanban-definition-UN3LZRKU.Co1qOPTd.js → kanban-definition-UN3LZRKU.DPeZD_lP.js} +1 -1
- package/web/_astro/{linear.DoHZ-iRt.js → linear.l60Nyp5b.js} +1 -1
- package/web/_astro/{mermaid.core.DNRElYN2.js → mermaid.core.DmtMJcmL.js} +4 -4
- package/web/_astro/{mindmap-definition-RKZ34NQL.CdfJZidJ.js → mindmap-definition-RKZ34NQL.Cc47AcCn.js} +1 -1
- package/web/_astro/{pieDiagram-4H26LBE5.C1A8dby4.js → pieDiagram-4H26LBE5.B8cN-S9g.js} +1 -1
- package/web/_astro/{quadrantDiagram-W4KKPZXB.NmZqjG_c.js → quadrantDiagram-W4KKPZXB.DY1FN89L.js} +1 -1
- package/web/_astro/{requirementDiagram-4Y6WPE33.tY36zYtK.js → requirementDiagram-4Y6WPE33.CnM6VbV8.js} +1 -1
- package/web/_astro/{sankeyDiagram-5OEKKPKP.rOEGZYjo.js → sankeyDiagram-5OEKKPKP.B9DcGfNV.js} +1 -1
- package/web/_astro/{sequenceDiagram-3UESZ5HK.Dpnw3S9J.js → sequenceDiagram-3UESZ5HK.ymxaNlAY.js} +1 -1
- package/web/_astro/{stateDiagram-AJRCARHV.DGpvQ3Wz.js → stateDiagram-AJRCARHV.DDOJ3d8P.js} +1 -1
- package/web/_astro/{stateDiagram-v2-BHNVJYJU.CbwQdEfu.js → stateDiagram-v2-BHNVJYJU.Ck0Nb_KY.js} +1 -1
- package/web/_astro/{timeline-definition-PNZ67QCA.DAYUpUJT.js → timeline-definition-PNZ67QCA.BNOvZwAN.js} +1 -1
- package/web/_astro/{vennDiagram-CIIHVFJN.C7JCCd6-.js → vennDiagram-CIIHVFJN.D3k5ivSF.js} +1 -1
- package/web/_astro/{wardley-L42UT6IY.BGgwOH5_.js → wardley-L42UT6IY.BylaxVqn.js} +1 -1
- package/web/_astro/{wardleyDiagram-YWT4CUSO.oIZqzI2l.js → wardleyDiagram-YWT4CUSO.HLNtFUm9.js} +1 -1
- package/web/_astro/{xychartDiagram-2RQKCTM6.DohcJzqm.js → xychartDiagram-2RQKCTM6.B-WooKSU.js} +1 -1
- package/web/index.html +2 -2
- package/web/_astro/BoardApp.D8InuCYx.js +0 -1
- package/web/_astro/channel.XCf1DcsL.js +0 -1
- package/web/_astro/index.DJl2RAVZ.css +0 -1
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
# Copy / adapt into a project as `.spur/config.yaml`.
|
|
5
5
|
|
|
6
6
|
$schema: "@gobing-ai/spur/schemas/spur-config.schema.json"
|
|
7
|
-
# Config schema version (string). Current recommended: "1.
|
|
7
|
+
# Config schema version (string). Current recommended: "1.2".
|
|
8
8
|
# "1" remains accepted; there is no hard migrator yet. Prefer "1.1" for
|
|
9
9
|
# new projects so editors and operators know the file targets the ADR-033
|
|
10
10
|
# + planning shape.
|
|
11
|
-
version: "1.
|
|
11
|
+
version: "1.2"
|
|
12
12
|
name: my-project
|
|
13
13
|
|
|
14
14
|
# ── Portable bootstrap (consumed by @gobing-ai/ts-infra
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
|
|
19
19
|
$schema: "@gobing-ai/spur/schemas/spur-config.schema.json"
|
|
20
20
|
|
|
21
|
+
# Inert label (task 0649 R6 ruling): nothing branches on `version` today.
|
|
22
|
+
# Reunified at "1.2" across every shipped artifact (init stamp, JSON Schema).
|
|
23
|
+
version: "1.2"
|
|
24
|
+
|
|
21
25
|
agent:
|
|
22
26
|
# `default` is the role used for `--agent auto` when the caller declares
|
|
23
27
|
# nothing (task 0542 R2 — the value domain moved from executor names to
|
|
@@ -124,10 +128,10 @@ agent:
|
|
|
124
128
|
# `workflows.paths` is deliberately NOT set here. Its values are search paths
|
|
125
129
|
# resolved against a project's own root (0639 classifies it project-relative), so
|
|
126
130
|
# a machine-wide value would point every project at a directory that mostly does
|
|
127
|
-
# not exist. The
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
# workflows
|
|
132
|
-
#
|
|
133
|
-
|
|
131
|
+
# not exist. The key is present (the A4 goal names it among the shipped global
|
|
132
|
+
# defaults) but empty: `workflow list` falls back to default `.spur/workflows/`
|
|
133
|
+
# discovery, and the lifecycle adapter resolves bundled → project
|
|
134
|
+
# `.spur/workflows/` on its own (make-lifecycle-adapter.ts:24, two tiers since
|
|
135
|
+
# task 0648). Set paths per project when a project keeps workflows somewhere
|
|
136
|
+
# non-standard.
|
|
137
|
+
workflows: {}
|
|
@@ -447,6 +447,102 @@
|
|
|
447
447
|
"reason": "Accepted backlog: L4.orphan-scenarios",
|
|
448
448
|
"since": "2026-08-19"
|
|
449
449
|
},
|
|
450
|
+
{
|
|
451
|
+
"kind": "feature",
|
|
452
|
+
"id": "B1",
|
|
453
|
+
"code": "L4.dogfood-missing",
|
|
454
|
+
"severity": "warning",
|
|
455
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
456
|
+
"since": "2026-08-24"
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
"kind": "feature",
|
|
460
|
+
"id": "B3",
|
|
461
|
+
"code": "L4.dogfood-missing",
|
|
462
|
+
"severity": "warning",
|
|
463
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
464
|
+
"since": "2026-08-24"
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
"kind": "feature",
|
|
468
|
+
"id": "E5",
|
|
469
|
+
"code": "L4.dogfood-missing",
|
|
470
|
+
"severity": "warning",
|
|
471
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
472
|
+
"since": "2026-08-24"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"kind": "feature",
|
|
476
|
+
"id": "F",
|
|
477
|
+
"code": "L4.dogfood-missing",
|
|
478
|
+
"severity": "warning",
|
|
479
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
480
|
+
"since": "2026-08-24"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"kind": "feature",
|
|
484
|
+
"id": "F31",
|
|
485
|
+
"code": "L4.dogfood-missing",
|
|
486
|
+
"severity": "warning",
|
|
487
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
488
|
+
"since": "2026-08-24"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"kind": "feature",
|
|
492
|
+
"id": "F82",
|
|
493
|
+
"code": "L4.dogfood-missing",
|
|
494
|
+
"severity": "warning",
|
|
495
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
496
|
+
"since": "2026-08-24"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"kind": "feature",
|
|
500
|
+
"id": "G4",
|
|
501
|
+
"code": "L4.dogfood-missing",
|
|
502
|
+
"severity": "warning",
|
|
503
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
504
|
+
"since": "2026-08-24"
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
"kind": "feature",
|
|
508
|
+
"id": "H11",
|
|
509
|
+
"code": "L4.dogfood-missing",
|
|
510
|
+
"severity": "warning",
|
|
511
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
512
|
+
"since": "2026-08-24"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"kind": "feature",
|
|
516
|
+
"id": "I",
|
|
517
|
+
"code": "L4.dogfood-missing",
|
|
518
|
+
"severity": "warning",
|
|
519
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
520
|
+
"since": "2026-08-24"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"kind": "feature",
|
|
524
|
+
"id": "I4",
|
|
525
|
+
"code": "L4.dogfood-missing",
|
|
526
|
+
"severity": "warning",
|
|
527
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
528
|
+
"since": "2026-08-24"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"kind": "feature",
|
|
532
|
+
"id": "I5",
|
|
533
|
+
"code": "L4.dogfood-missing",
|
|
534
|
+
"severity": "warning",
|
|
535
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
536
|
+
"since": "2026-08-24"
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
"kind": "feature",
|
|
540
|
+
"id": "J",
|
|
541
|
+
"code": "L4.dogfood-missing",
|
|
542
|
+
"severity": "warning",
|
|
543
|
+
"reason": "Feature remains verifying; direct linked tasks touch self-referential workflow infrastructure, but no dogfood report exists. Accepted as pre-A4 corpus debt only; the strict feature completion gate still requires real dogfood evidence.",
|
|
544
|
+
"since": "2026-08-24"
|
|
545
|
+
},
|
|
450
546
|
{
|
|
451
547
|
"kind": "task",
|
|
452
548
|
"id": "0001",
|
|
@@ -12213,14 +12309,6 @@
|
|
|
12213
12309
|
"reason": "Accumulated anchor drift, surfaced for the first time by task 0583's content-matching rule. The cited lines resolve and are in bounds, but no longer name the requirement row's subject — a later task edited the file and pushed the anchor onto unrelated code. Spot-verified true positives (an import block cited for a component's hooks; a severity-parsing block cited for `runL4Rollup`). Repairing 1,300+ historical citations is its own campaign; the rule ships at warning severity until then (0583 R6).",
|
|
12214
12310
|
"since": "2026-08-18"
|
|
12215
12311
|
},
|
|
12216
|
-
{
|
|
12217
|
-
"kind": "task",
|
|
12218
|
-
"id": "0416",
|
|
12219
|
-
"code": "L4.stale-line-anchor",
|
|
12220
|
-
"severity": "warning",
|
|
12221
|
-
"reason": "Anchor written with an incomplete path; qualification migration (task 0583) owns the mechanical repair — see note § L4.stale-line-anchor.",
|
|
12222
|
-
"since": "2026-08-17"
|
|
12223
|
-
},
|
|
12224
12312
|
{
|
|
12225
12313
|
"kind": "task",
|
|
12226
12314
|
"id": "0416",
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
},
|
|
720
720
|
"collect:onEnter:1": {
|
|
721
721
|
"kind": "shell",
|
|
722
|
-
"invocation": "$spurBin workflow validate
|
|
722
|
+
"invocation": "$spurBin workflow validate wayfinder-resolution.yaml > .spur/run/wayfinder/$wbs-workflow-check.txt",
|
|
723
723
|
"stateEffect": "read",
|
|
724
724
|
"evidenceEffect": "write",
|
|
725
725
|
"disposition": "SIMPLE"
|
|
@@ -64,13 +64,11 @@ states:
|
|
|
64
64
|
- kind: shell
|
|
65
65
|
options:
|
|
66
66
|
command: "mkdir -p .spur/run/wayfinder && $spurBin task show $wbs --json > .spur/run/wayfinder/$wbs-input.json"
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# project. The previous `config/workflows/…` literal only resolved in the
|
|
70
|
-
# monorepo and hard-failed `collect` anywhere else.
|
|
67
|
+
# `wayfinder-resolution.yaml` uses the project→bundled resolver (tasks 0648/0650):
|
|
68
|
+
# a bare name falls back to the bundled tree; an explicit project path wins.
|
|
71
69
|
- kind: shell
|
|
72
70
|
options:
|
|
73
|
-
command: "$spurBin workflow validate
|
|
71
|
+
command: "$spurBin workflow validate wayfinder-resolution.yaml > .spur/run/wayfinder/$wbs-workflow-check.txt"
|
|
74
72
|
- kind: shell
|
|
75
73
|
options:
|
|
76
74
|
command: "$spurBin task check $wbs > .spur/run/wayfinder/$wbs-precheck.txt"
|
|
@@ -112,7 +110,7 @@ states:
|
|
|
112
110
|
onEnter:
|
|
113
111
|
- kind: shell
|
|
114
112
|
options:
|
|
115
|
-
command:
|
|
113
|
+
command: "rm -f .spur/run/wayfinder/$wbs-resolution-verdict.txt"
|
|
116
114
|
- kind: agent.run
|
|
117
115
|
options:
|
|
118
116
|
agent: ${vars.agent}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/spur",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.61",
|
|
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",
|
package/plugins/README.md
CHANGED
|
@@ -228,7 +228,7 @@ graph TB
|
|
|
228
228
|
subgraph "Corpus Layer"
|
|
229
229
|
CORPUS["docs/tasks/ + docs/features/<br/>Markdown planning corpus"]
|
|
230
230
|
RULES[".spur/rules/<br/>YAML constraint rules"]
|
|
231
|
-
WFS["
|
|
231
|
+
WFS["bundled workflows tree<br/>YAML workflow definitions"]
|
|
232
232
|
end
|
|
233
233
|
|
|
234
234
|
%% Command → Skill delegations
|
|
@@ -309,7 +309,7 @@ Tier 3 — Execution Layer (spur CLI + Guard Scripts)
|
|
|
309
309
|
|
|
310
310
|
1. User types `/sp:dev-run 0090`
|
|
311
311
|
2. **Command** delegates to `sp:spur-dev` skill (execution half)
|
|
312
|
-
3. **Skill** reads the task, loads
|
|
312
|
+
3. **Skill** reads the task, loads `task-pipeline.yaml`, and runs `spur workflow run` with HITL surfacing
|
|
313
313
|
4. **CLI** executes the workflow engine (`@gobing-ai/ts-dual-workflow-engine`), pauses at HITL gates, persists run state
|
|
314
314
|
5. Result: task driven through implement → check → fix → verify lifecycle
|
|
315
315
|
|
|
@@ -351,8 +351,9 @@ The **workflow** and **rule** engines have their own lifecycles (author → vali
|
|
|
351
351
|
|
|
352
352
|
## Workflow Pipelines
|
|
353
353
|
|
|
354
|
-
The plugin
|
|
355
|
-
|
|
354
|
+
The plugin references workflow YAMLs by bare name; the CLI resolves them through the
|
|
355
|
+
bundled tree (two-tier model, task 0648/0650) — a project-local override wins when
|
|
356
|
+
present, otherwise the bundled copy is used. Each pipeline owns one lifecycle phase:
|
|
356
357
|
|
|
357
358
|
| Workflow | Phase | Entry command | Status |
|
|
358
359
|
| ------------------------ | --------------------------------- | --------------------------------- | ------------- |
|
package/plugins/sp/README.md
CHANGED
|
@@ -509,7 +509,7 @@ graph TB
|
|
|
509
509
|
subgraph "Corpus layer"
|
|
510
510
|
CORPUS["docs/tasks/ + docs/features/<br/>markdown planning corpus"]
|
|
511
511
|
RULES[".spur/rules/<br/>YAML constraint rules"]
|
|
512
|
-
WFS["
|
|
512
|
+
WFS["bundled workflows tree<br/>YAML workflow definitions"]
|
|
513
513
|
end
|
|
514
514
|
|
|
515
515
|
CMD -->|"Skill(sp:spur-dev, ...)"| SKILL_DEV
|
|
@@ -557,7 +557,7 @@ graph TB
|
|
|
557
557
|
|
|
558
558
|
1. User types `/sp:dev-run 0090`.
|
|
559
559
|
2. **Command** delegates to `sp:spur-dev` skill (execution half).
|
|
560
|
-
3. **Skill** reads the task, loads
|
|
560
|
+
3. **Skill** reads the task, loads `task-pipeline.yaml`, and runs
|
|
561
561
|
`spur workflow run` with HITL surfacing.
|
|
562
562
|
4. **CLI** executes the workflow engine (`@gobing-ai/ts-dual-workflow-engine`), pauses at HITL gates,
|
|
563
563
|
persists run state.
|
|
@@ -575,7 +575,7 @@ graph TB
|
|
|
575
575
|
|
|
576
576
|
### Workflow pipelines
|
|
577
577
|
|
|
578
|
-
The plugin
|
|
578
|
+
The plugin references workflow YAMLs by bare name; the CLI resolves them through the bundled tree (two-tier model, task 0648/0650) — project-local overrides win when present. Each
|
|
579
579
|
pipeline owns one lifecycle phase:
|
|
580
580
|
|
|
581
581
|
| Workflow | Phase | Entry command |
|
|
@@ -78,7 +78,7 @@ You own the spaces **between** task runs:
|
|
|
78
78
|
- **Preflight (Step 2.5 / 3.0)** - before each pipeline launch, evaluate TABLE A STOP rows
|
|
79
79
|
(`batch-preflight.ts` or equivalent). Skip A2/A7/A8/A9; still **launch `task-pipeline.yaml`** for
|
|
80
80
|
ready WBS (never substitute a `dev-next` loop for the happy path).
|
|
81
|
-
- **Run each ready task** through
|
|
81
|
+
- **Run each ready task** through `task-pipeline.yaml` via `spur workflow run --async`
|
|
82
82
|
(Step 3). The command/script layer polls `spur workflow trace` to terminal state - polling is
|
|
83
83
|
transport, not planner reasoning (R3: the poll loop must not live in this agent's body; the planner
|
|
84
84
|
inspects the terminal verdict, not the poll iterations). Follow the
|
|
@@ -31,7 +31,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
31
31
|
|
|
32
32
|
- Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
|
|
33
33
|
- Delegate everything: `Skill(skill="sp:pr-reviewing", args="$ARGUMENTS")`. The skill owns mode
|
|
34
|
-
routing, finding triage, fix, and rules authoring;
|
|
34
|
+
routing, finding triage, fix, and rules authoring; `pr-review.yaml` is the SSOT
|
|
35
35
|
for the review spine's state order and guards; the staged `pr-reviewing.ts` is the
|
|
36
36
|
deterministic git/gh core every spine step shells out to.
|
|
37
37
|
- The external review goes through the GitHub PR and an `@codex review` comment only — never local
|
|
@@ -28,7 +28,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
28
28
|
## Implementation
|
|
29
29
|
|
|
30
30
|
- Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
|
|
31
|
-
- Wrap stays **workflow-backed** — `spur workflow run
|
|
31
|
+
- Wrap stays **workflow-backed** — `spur workflow run wrapup-pipeline.yaml` is the only implementation; there is no inline wrap driver.
|
|
32
32
|
- Resolve the executor **before** launching the workflow:
|
|
33
33
|
- `--agent <name>` → pass the name unchanged into `vars.agent`.
|
|
34
34
|
- `--agent auto` → tier-resolve a concrete executor first, then merge it into `vars.agent`.
|
|
@@ -42,7 +42,7 @@ AGENT=… # resolved above: agent.default for omitted, tier-resolved for auto, u
|
|
|
42
42
|
echo "execution surface: subprocess; reason: trigger 3 — durable auditable run record required; requested agent: <inline|auto|name>; executor: $AGENT"
|
|
43
43
|
VARS=$(jq -nc --arg tasks "[\"$WBS\"]" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
|
|
44
44
|
'{tasks:$tasks, agent:$agent, profile:$profile, merge:$merge}')
|
|
45
|
-
spur workflow run
|
|
45
|
+
spur workflow run wrapup-pipeline.yaml --vars "$VARS" [--dry-run]
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
The executor resolution is described in the bullets above; the snippet's `AGENT` variable carries
|
|
@@ -30,7 +30,7 @@ For shared semantics, see the [flag glossary](../skills/spur-dev/references/flag
|
|
|
30
30
|
## Implementation
|
|
31
31
|
|
|
32
32
|
- Apply the [inline-default execution-surface contract](../skills/spur-dev/references/cross-cutting.md#inline-default-execution-surface).
|
|
33
|
-
- Wrap stays **workflow-backed** — `spur workflow run
|
|
33
|
+
- Wrap stays **workflow-backed** — `spur workflow run wrapup-pipeline.yaml` is the only implementation; there is no inline wrap driver.
|
|
34
34
|
- Resolve the executor **before** launching the workflow:
|
|
35
35
|
- `--agent <name>` → pass the name unchanged into `vars.agent`.
|
|
36
36
|
- `--agent auto` → tier-resolve a concrete executor first, then merge it into `vars.agent`.
|
|
@@ -44,7 +44,7 @@ AGENT=… # resolved above: agent.default for omitted, tier-resolved for auto, u
|
|
|
44
44
|
echo "execution surface: subprocess; reason: trigger 3 — durable auditable run record required; requested agent: <inline|auto|name>; executor: $AGENT"
|
|
45
45
|
VARS=$(jq -nc --arg tasks "$TASKS" --arg feature "$FEATURE" --arg agent "$AGENT" --arg profile "$PROFILE" --arg merge "$MERGE" \
|
|
46
46
|
'{tasks:$tasks, feature:$feature, agent:$agent, profile:$profile, merge:$merge}')
|
|
47
|
-
spur workflow run
|
|
47
|
+
spur workflow run wrapup-pipeline.yaml --vars "$VARS" [--dry-run]
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
The executor resolution is described in the bullets above; the snippet's `AGENT` variable carries
|
package/plugins/sp/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.61",
|
|
4
4
|
"description": "Spur — a local-first harness engineering toolkit that wraps mainstream coding agents with constraint checking, workflow orchestration, and history analytics.",
|
|
5
5
|
"extensions": {
|
|
6
6
|
"pi": ["./hooks/pi/guard-extension.ts"]
|
|
@@ -10,8 +10,9 @@ see_also:
|
|
|
10
10
|
# Roles — the Layer-1 role-to-tier table
|
|
11
11
|
|
|
12
12
|
The executor-selection contract is two layers. **Layer 1 (this file)** projects *role → tier*;
|
|
13
|
-
its SSOT is `
|
|
14
|
-
|
|
13
|
+
its SSOT is `agent.roles` in `config/config.global.yaml` (task 0647 / ADR-078) — this file is the
|
|
14
|
+
agent/human-facing view plus the plugin-owned command→role mapping. `DEFAULT_AGENT_ROLES` in
|
|
15
|
+
`packages/config/src/index.ts` is the no-filesystem fallback and must remain identical. **Layer 2** maps
|
|
15
16
|
*tier → executor* and is owned by the operator in `.spur/config.yaml`. This file never names an
|
|
16
17
|
executor, a model, or a vendor — it declares only what tier a role's work needs, and the
|
|
17
18
|
operator's config decides which executor serves that tier.
|
|
@@ -38,9 +39,10 @@ collapse, named as people so they stay addressable in `--agent`.
|
|
|
38
39
|
|
|
39
40
|
## The table
|
|
40
41
|
|
|
41
|
-
<!-- PROJECTION (task
|
|
42
|
-
of
|
|
43
|
-
plugins/sp/tests/roles.test.ts (R9) fails the suite on any drift
|
|
42
|
+
<!-- PROJECTION (task 0647 / ADR-078): the tier/stages half of the block below is a generated view
|
|
43
|
+
of agent.roles in config/config.global.yaml — edit that SSOT, not this file.
|
|
44
|
+
plugins/sp/tests/roles.test.ts (R9) fails the suite on any three-way drift with the
|
|
45
|
+
DEFAULT_AGENT_ROLES no-filesystem fallback. The
|
|
44
46
|
`commands:` half is plugin data (command frontmatter is its SSOT). -->
|
|
45
47
|
|
|
46
48
|
```yaml
|
|
@@ -98,9 +100,10 @@ driving the external PR review and triaging its findings folds the `review` stag
|
|
|
98
100
|
|
|
99
101
|
**Consistency is a test, not a convention.** `plugins/sp/tests/roles.test.ts` parses this YAML and
|
|
100
102
|
asserts the tier-distinctness, command closure, stage-floor, and boundary invariants against the
|
|
101
|
-
real command directory, the real stage registry, and the real operator config — plus parity
|
|
102
|
-
`DEFAULT_AGENT_ROLES` (R9,
|
|
103
|
-
id/tier/stages. When the table and the registry disagree,
|
|
104
|
-
test. When the
|
|
103
|
+
real command directory, the real stage registry, and the real operator config — plus three-way parity
|
|
104
|
+
with `config/config.global.yaml` and `DEFAULT_AGENT_ROLES` (R9, 0647): the table above must equal the
|
|
105
|
+
shipped SSOT and no-filesystem fallback on id/tier/stages. When the table and the registry disagree,
|
|
106
|
+
fix the table or the registry — never the test. When the three role tables disagree, fix the shipped
|
|
107
|
+
SSOT first, then regenerate the projections.
|
|
105
108
|
A project may re-tier/re-stage a role at config time via `agent.roles` (closed vocabulary) — that
|
|
106
109
|
override never flows back into this file.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
3
|
* surface-drift-inventory — re-runnable drift inventory for `plugins/sp` and
|
|
4
|
-
* the tracked workflow-YAML SSOT tree
|
|
5
|
-
*
|
|
6
|
-
* (feature I3, task 0539 R1/R2).
|
|
4
|
+
* the tracked workflow-YAML SSOT tree against the live
|
|
5
|
+
* source-local `spur` CLI (feature I3, task 0539 R1/R2).
|
|
7
6
|
*
|
|
8
7
|
* Method (mechanical first, prose second — task 0539 Design):
|
|
9
8
|
* A. Plugin assertions: extract every `spur`-invocation (backticked spans, fenced
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
* in this repo — recorded unverified.
|
|
20
19
|
* D. Workflows: `spur workflow validate` (live engine, schema + semantic) and a
|
|
21
20
|
* `--dry-run` transition walk for all ten definitions; `.spur/workflows`
|
|
22
|
-
* symlink
|
|
21
|
+
* symlink is asserted absent (two-tier project→bundled model, task 0650).
|
|
23
22
|
*
|
|
24
23
|
* Output: markdown inventory on stdout-path via `--out`; exit 1 when any
|
|
25
24
|
* CONFIRMED mismatch remains (ok after repair); unverified entries never fail.
|
|
@@ -35,7 +34,6 @@ import {
|
|
|
35
34
|
mkdtempSync,
|
|
36
35
|
readdirSync,
|
|
37
36
|
readFileSync,
|
|
38
|
-
realpathSync,
|
|
39
37
|
rmSync,
|
|
40
38
|
writeFileSync,
|
|
41
39
|
} from 'node:fs';
|
|
@@ -130,6 +128,7 @@ interface Parsed {
|
|
|
130
128
|
}
|
|
131
129
|
|
|
132
130
|
const PLACEHOLDER = /^([<[{($#"'`]|…|\.\.\.)/;
|
|
131
|
+
const LEGACY_SELF_ALIASES = new Set(['init', 'migrate', 'serve', 'status']);
|
|
133
132
|
|
|
134
133
|
/** Normalize an asserted invocation span into nouns / verbs / flags. Null when it asserts nothing. */
|
|
135
134
|
export function parseInvocation(spanRaw: string): Parsed | null {
|
|
@@ -259,6 +258,32 @@ export function checkNounVerbFlags(
|
|
|
259
258
|
const root = surface([]);
|
|
260
259
|
for (const noun of nouns) {
|
|
261
260
|
if (noun === 'help' || /^(foo|bar|baz)$/.test(noun)) continue;
|
|
261
|
+
if (LEGACY_SELF_ALIASES.has(noun)) {
|
|
262
|
+
const self = surface(['self']);
|
|
263
|
+
const command = surface(['self', noun]);
|
|
264
|
+
const present = self.commands.includes(noun);
|
|
265
|
+
record(
|
|
266
|
+
`spur ${noun}`,
|
|
267
|
+
'help-capture(spur self; hidden root alias)',
|
|
268
|
+
present ? 'ok' : 'mismatch',
|
|
269
|
+
present
|
|
270
|
+
? `legacy alias; canonical self/${noun} command is present`
|
|
271
|
+
: `canonical self/${noun} command is absent`,
|
|
272
|
+
occ,
|
|
273
|
+
);
|
|
274
|
+
for (const f of flags) {
|
|
275
|
+
record(
|
|
276
|
+
`spur ${noun} ${f}`,
|
|
277
|
+
`help-capture(spur self ${noun}; hidden root alias)`,
|
|
278
|
+
present && command.flags.includes(f) ? 'ok' : 'mismatch',
|
|
279
|
+
command.flags.includes(f)
|
|
280
|
+
? 'flag present on canonical command'
|
|
281
|
+
: `flag absent (${command.flags.join(', ')})`,
|
|
282
|
+
occ,
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
262
287
|
if (!root.commands.includes(noun)) {
|
|
263
288
|
record(
|
|
264
289
|
`spur ${noun}`,
|
|
@@ -315,6 +340,10 @@ export function checkNounVerbFlags(
|
|
|
315
340
|
}
|
|
316
341
|
}
|
|
317
342
|
for (const verb of verbs) {
|
|
343
|
+
if (nouns.length === 0 && LEGACY_SELF_ALIASES.has(verb)) {
|
|
344
|
+
checkNounVerbFlags([verb], [], flags, occ);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
318
347
|
if (nouns.length === 0 && root.commands.includes(verb)) {
|
|
319
348
|
record(`spur ${verb}`, 'help-capture(root)', 'ok', 'root verb present', occ);
|
|
320
349
|
}
|
|
@@ -383,7 +412,10 @@ export function sweepPluginTrees(root: string = PLUGIN_ROOT): void {
|
|
|
383
412
|
const cells = line.split('|').map((c) => c.trim());
|
|
384
413
|
const lastCell = cells[cells.length - 2] ?? line;
|
|
385
414
|
if (first && first !== 'Verb' && first !== 'spur') {
|
|
386
|
-
|
|
415
|
+
const nounCommands = surface([refNoun]).commands;
|
|
416
|
+
if (nounCommands.includes(first)) {
|
|
417
|
+
checkNounVerbFlags([refNoun], [first], flagNames(lastCell), occ);
|
|
418
|
+
} else if (rootCommands.includes(first) || LEGACY_SELF_ALIASES.has(first)) {
|
|
387
419
|
checkNounVerbFlags([], [first], flagNames(lastCell), occ);
|
|
388
420
|
} else {
|
|
389
421
|
checkNounVerbFlags([refNoun], [first], flagNames(lastCell), occ);
|
|
@@ -611,7 +643,7 @@ const JSON_PROBES: string[][] = [
|
|
|
611
643
|
['agent', 'list', '--json'],
|
|
612
644
|
['agent', 'doctor', 'omp', '--json'],
|
|
613
645
|
['workflow', 'list', '--json'],
|
|
614
|
-
['workflow', 'validate', '
|
|
646
|
+
['workflow', 'validate', 'basic.yaml', '--json'],
|
|
615
647
|
['status', '--json'],
|
|
616
648
|
['team', 'status', '--json'],
|
|
617
649
|
['projects', 'list', '--json'],
|
|
@@ -758,18 +790,20 @@ export function sweepWorkflows(opts: { run?: CliRunner; wfDir?: string; link?: s
|
|
|
758
790
|
}
|
|
759
791
|
});
|
|
760
792
|
}
|
|
793
|
+
// Two-tier model (task 0648/0650): `.spur/workflows` is no longer a symlink and
|
|
794
|
+
// must not exist — the CLI resolves an explicit project path, then bundled fallback. Assert absence.
|
|
761
795
|
const link = opts.link ?? join(REPO_ROOT, '.spur', 'workflows');
|
|
762
|
-
let status: Row['status'] = '
|
|
763
|
-
let actual = '';
|
|
796
|
+
let status: Row['status'] = 'ok';
|
|
797
|
+
let actual = 'absent (two-tier project→bundled model, task 0650)';
|
|
764
798
|
try {
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
799
|
+
if (existsSync(link)) {
|
|
800
|
+
status = 'mismatch';
|
|
801
|
+
actual = 'still present — should be removed (task 0650 R3)';
|
|
802
|
+
}
|
|
769
803
|
} catch (e) {
|
|
770
|
-
actual = `
|
|
804
|
+
actual = `exists-check failed: ${String(e).slice(0, 120)}`;
|
|
771
805
|
}
|
|
772
|
-
record('.spur/workflows symlink', 'symlink-
|
|
806
|
+
record('.spur/workflows symlink', 'symlink-absent', status, actual, { file: '.spur/workflows', line: 1 });
|
|
773
807
|
}
|
|
774
808
|
|
|
775
809
|
// ─── Report ─────────────────────────────────────────────────────────────────
|
|
@@ -805,7 +839,7 @@ export function render(): string {
|
|
|
805
839
|
L.push(
|
|
806
840
|
"R1 scope: `plugins/sp/{commands,skills,scripts,hooks}` (tests/ and evals/ are the harness itself; agents/ prose is outside R1's named surface list).",
|
|
807
841
|
);
|
|
808
|
-
L.push('R2 scope: all workflow YAML via the
|
|
842
|
+
L.push('R2 scope: all workflow YAML via the bundled tree (two-tier project→bundled model since task 0648/0650).');
|
|
809
843
|
L.push('');
|
|
810
844
|
L.push('## Check methods');
|
|
811
845
|
L.push('');
|
|
@@ -825,7 +859,7 @@ export function render(): string {
|
|
|
825
859
|
L.push(
|
|
826
860
|
'| `workflow-validate` / `workflow-dry-run` | Live engine: schema+semantic validate; `--dry-run` transition walk |',
|
|
827
861
|
);
|
|
828
|
-
L.push('| `symlink-
|
|
862
|
+
L.push('| `symlink-absent` | `.spur/workflows` is asserted absent (two-tier project→bundled model, task 0650) |');
|
|
829
863
|
L.push('');
|
|
830
864
|
for (const [method, list] of byMethod) {
|
|
831
865
|
const mm = list.filter((r) => r.status === 'mismatch').length;
|
|
@@ -281,15 +281,22 @@ function checkTargetResolution(cmd: ParsedCommand, skillsDir: string, root: stri
|
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
// Workflow file refs —
|
|
285
|
-
|
|
284
|
+
// Workflow file refs — bare names (`spur workflow run <name>.yaml`, two-tier model
|
|
285
|
+
// 0648/0650) resolve against the bundled workflow-definition asset tree; legacy
|
|
286
|
+
// `.spur/workflows/<name>.yaml` paths are also caught as unification drift.
|
|
287
|
+
const wfDir = join(root, 'config', 'workflows');
|
|
288
|
+
const workflowRefs = [
|
|
289
|
+
...[...implSection.matchAll(/\.spur\/workflows\/([^\s)"\]]+\.yaml)/g)],
|
|
290
|
+
...[...implSection.matchAll(/spur workflow (?:run|validate) ([a-z0-9-]+\.yaml)/g)],
|
|
291
|
+
];
|
|
286
292
|
for (const ref of workflowRefs) {
|
|
287
|
-
const
|
|
293
|
+
const bare = (ref[1] ?? '').split('/').pop() ?? '';
|
|
294
|
+
const wfPath = join(wfDir, bare);
|
|
288
295
|
if (!existsSync(wfPath)) {
|
|
289
296
|
violations.push({
|
|
290
297
|
command: cmd.name,
|
|
291
298
|
gate: 'c',
|
|
292
|
-
message: `unresolved workflow file ${
|
|
299
|
+
message: `unresolved workflow file ${bare} (missing ${wfPath})`,
|
|
293
300
|
});
|
|
294
301
|
}
|
|
295
302
|
}
|
|
@@ -521,7 +521,7 @@ Do **not** use this skill for:
|
|
|
521
521
|
rubric.
|
|
522
522
|
- `plugins/sp/references/roles.md` — the Layer-1 role→tier table; this skill's verify/review modes
|
|
523
523
|
run under the `reviewer` role (0538 R4: this file points at roles.md, it does not restate tiers).
|
|
524
|
-
-
|
|
524
|
+
- `task-pipeline.yaml` — the `verify → record` gate that consumes the verdict.
|
|
525
525
|
- **`sp:spur-dev`** — the execution-half umbrella that drives the pipeline this skill gates.
|
|
526
526
|
- [references/code-improvement.md](references/code-improvement.md) — architecture-improvement lens
|
|
527
527
|
for module depth, seam placement, locality, coupling, and testability.
|
|
@@ -120,7 +120,7 @@ Wave C verification can emit the following additive `checks[]` rows:
|
|
|
120
120
|
|
|
121
121
|
## How the gate reads it
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
`task-pipeline.yaml`, transition `verify → record`:
|
|
124
124
|
|
|
125
125
|
```yaml
|
|
126
126
|
guard:
|
|
@@ -233,7 +233,7 @@ Also note **what worked well** so efficient patterns are preserved.
|
|
|
233
233
|
1. **Fix description** — documentation, skill reference, pipeline comment, hook, etc.
|
|
234
234
|
2. **Target location** — exact file path
|
|
235
235
|
- Skill guidance: `skills/<skill-name>/SKILL.md` or `references/<name>.md`
|
|
236
|
-
- Pipeline comments: runtime workflow
|
|
236
|
+
- Pipeline comments: runtime workflow resolves by bare name (`task-pipeline.yaml`)
|
|
237
237
|
- CLI reference: `skills/spur-cli/references/tasks/…`
|
|
238
238
|
3. **Proposed content** — text or code block to add
|
|
239
239
|
4. **Expected impact** — estimated time saved per future run
|
|
@@ -212,5 +212,5 @@ A6 → C5/C3 → unit first if verdict says so; else verify.
|
|
|
212
212
|
- Dev operations map: `plugins/sp/skills/spur-dev/references/dev-operations.md:37-56`
|
|
213
213
|
- `--next` chain on run: `plugins/sp/commands/dev-run.md:104-127`
|
|
214
214
|
- Refine skip-gate sections: `plugins/sp/skills/spur-dev/references/dev-operations.md:114-128`
|
|
215
|
-
- Task lifecycle wip→testing guard:
|
|
215
|
+
- Task lifecycle wip→testing guard: `task-lifecycle.yaml:48-54`
|
|
216
216
|
- Decision-brief format: `plugins/sp/skills/spur-dev/references/decision-brief.md`
|
|
@@ -39,7 +39,7 @@ that review effort happens on the PR, through Codex — not in the local session
|
|
|
39
39
|
sp:pr-reviewing (this skill — mode routing, triage, fix, rules)
|
|
40
40
|
│ deterministic spine, state order + guards:
|
|
41
41
|
▼
|
|
42
|
-
|
|
42
|
+
pr-review.yaml ← workflow SSOT (seeded by spur init; project-tunable)
|
|
43
43
|
│ every state resolves with `superskill script path` and shells out to:
|
|
44
44
|
▼
|
|
45
45
|
staged pr-reviewing.ts ← Bun entrypoint for the tested git/gh core
|
|
@@ -280,7 +280,7 @@ or review requests.
|
|
|
280
280
|
|
|
281
281
|
## Additional Resources
|
|
282
282
|
|
|
283
|
-
- **Workflow SSOT:**
|
|
283
|
+
- **Workflow SSOT:** `pr-review.yaml` (seeded by `spur init`; tune per project —
|
|
284
284
|
wait budget, `preReviewCmd`, dedupe policy)
|
|
285
285
|
- **Script source:** [scripts/pr-reviewing.ts](../../scripts/pr-reviewing.ts) — subcommand CLI
|
|
286
286
|
- **Tests:** [tests/pr-reviewing.test.ts](../../tests/pr-reviewing.test.ts) — stubbed git/gh suites
|