@gobing-ai/spur 0.3.58 → 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.
Files changed (93) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +2 -2
  3. package/config/config.global.yaml +137 -0
  4. package/config/corpus-baseline.json +96 -8
  5. package/config/workflow-composition-baseline.json +1 -1
  6. package/config/workflows/wayfinder-resolution.yaml +4 -6
  7. package/package.json +9 -9
  8. package/plugins/README.md +5 -4
  9. package/plugins/sp/README.md +3 -3
  10. package/plugins/sp/agents/super-planner.md +1 -1
  11. package/plugins/sp/commands/dev-pr-review.md +1 -1
  12. package/plugins/sp/commands/dev-wrap.md +2 -2
  13. package/plugins/sp/commands/dev-wrapall.md +2 -2
  14. package/plugins/sp/plugin.json +1 -1
  15. package/plugins/sp/references/roles.md +12 -9
  16. package/plugins/sp/scripts/surface-drift-inventory.ts +51 -17
  17. package/plugins/sp/scripts/validate-commands.ts +11 -4
  18. package/plugins/sp/skills/code-verification/SKILL.md +1 -1
  19. package/plugins/sp/skills/code-verification/references/verdict-schema.md +1 -1
  20. package/plugins/sp/skills/issue-finding/SKILL.md +1 -1
  21. package/plugins/sp/skills/next-router/references/routing-table.md +1 -1
  22. package/plugins/sp/skills/pr-reviewing/SKILL.md +2 -2
  23. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +1 -1
  24. package/plugins/sp/skills/spur-cli/references/init.md +1 -1
  25. package/plugins/sp/skills/spur-cli/references/tasks/l3-guard-cheatsheet.md +1 -1
  26. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +1 -1
  27. package/plugins/sp/skills/spur-cli/references/workflows.md +4 -4
  28. package/plugins/sp/skills/spur-dev/SKILL.md +4 -4
  29. package/plugins/sp/skills/spur-dev/references/ac-style-guide.md +4 -4
  30. package/plugins/sp/skills/spur-dev/references/dev-operations.md +9 -9
  31. package/plugins/sp/skills/spur-dev/references/done-housekeeping.md +1 -1
  32. package/plugins/sp/skills/spur-dev/references/execution-batch.md +3 -3
  33. package/plugins/sp/skills/spur-dev/references/execution-workflow.md +1 -1
  34. package/plugins/sp/skills/spur-dev/references/feature-link-helper.md +3 -2
  35. package/plugins/sp/skills/spur-dev/references/gate-checklists.md +1 -1
  36. package/plugins/sp/skills/spur-dev/references/inline-pipeline-driver.md +5 -2
  37. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +2 -2
  38. package/schemas/spur-config.schema.json +1 -2
  39. package/spur.js +1381 -527
  40. package/web/_astro/BoardApp.BtRfVADq.js +1 -0
  41. package/web/_astro/BoardApp.CBIzcvqi.js +178 -0
  42. package/web/_astro/{TaskDetail.DHjEt5vl.js → TaskDetail.D2N60cfE.js} +1 -1
  43. package/web/_astro/{arc.XgRC1Ij_.js → arc.D-EfJJwf.js} +1 -1
  44. package/web/_astro/{architectureDiagram-3BPJPVTR.DOZWrfHc.js → architectureDiagram-3BPJPVTR.CgvTTzqp.js} +1 -1
  45. package/web/_astro/{blockDiagram-GPEHLZMM.ClQnCGf_.js → blockDiagram-GPEHLZMM.CnOohvvn.js} +1 -1
  46. package/web/_astro/{c4Diagram-AAUBKEIU.CKCtUD0Y.js → c4Diagram-AAUBKEIU.BFcBGUy_.js} +1 -1
  47. package/web/_astro/channel.kIu33Gui.js +1 -0
  48. package/web/_astro/{chunk-2J33WTMH.c7J8OHq5.js → chunk-2J33WTMH.C-6MR-XY.js} +1 -1
  49. package/web/_astro/{chunk-4BX2VUAB.C-A1Dv27.js → chunk-4BX2VUAB.BN4LP5AR.js} +1 -1
  50. package/web/_astro/{chunk-55IACEB6.C4kGGALB.js → chunk-55IACEB6.tUJ_CTtZ.js} +1 -1
  51. package/web/_astro/{chunk-727SXJPM.Bith2NHt.js → chunk-727SXJPM.BNCk-sxv.js} +1 -1
  52. package/web/_astro/{chunk-AQP2D5EJ.qeSXhsVY.js → chunk-AQP2D5EJ.BkpFIbNa.js} +1 -1
  53. package/web/_astro/{chunk-FMBD7UC4.DdQQnTAy.js → chunk-FMBD7UC4.DcSZ87PN.js} +1 -1
  54. package/web/_astro/{chunk-ND2GUHAM.BZYQVeZd.js → chunk-ND2GUHAM.BkLvHFFf.js} +1 -1
  55. package/web/_astro/{chunk-QZHKN3VN.BiUWwHaV.js → chunk-QZHKN3VN.HOdgszax.js} +1 -1
  56. package/web/_astro/{classDiagram-4FO5ZUOK.OGRhcldh.js → classDiagram-4FO5ZUOK.CWfRiY6b.js} +1 -1
  57. package/web/_astro/{classDiagram-v2-Q7XG4LA2.OGRhcldh.js → classDiagram-v2-Q7XG4LA2.CWfRiY6b.js} +1 -1
  58. package/web/_astro/{cose-bilkent-S5V4N54A.DxYklM_j.js → cose-bilkent-S5V4N54A.C6j4PxoN.js} +1 -1
  59. package/web/_astro/{dagre-BM42HDAG.BSb2dEbo.js → dagre-BM42HDAG.BATZG1II.js} +1 -1
  60. package/web/_astro/{diagram-2AECGRRQ.mOrItPK2.js → diagram-2AECGRRQ.B0f5yY6x.js} +1 -1
  61. package/web/_astro/{diagram-5GNKFQAL.C99r7J3C.js → diagram-5GNKFQAL.Bewupqv0.js} +1 -1
  62. package/web/_astro/{diagram-KO2AKTUF.BKbnisJO.js → diagram-KO2AKTUF.C23r1tB2.js} +1 -1
  63. package/web/_astro/{diagram-LMA3HP47.D8FJGo4V.js → diagram-LMA3HP47.DUErdBOR.js} +1 -1
  64. package/web/_astro/{diagram-OG6HWLK6.DVBs7n4Q.js → diagram-OG6HWLK6.BubmwAjb.js} +1 -1
  65. package/web/_astro/{erDiagram-TEJ5UH35.CddMTl4l.js → erDiagram-TEJ5UH35.BE_Qs5mv.js} +1 -1
  66. package/web/_astro/{flowDiagram-I6XJVG4X.B7WclnjQ.js → flowDiagram-I6XJVG4X.COWdbzon.js} +1 -1
  67. package/web/_astro/{ganttDiagram-6RSMTGT7.CRh7ggvz.js → ganttDiagram-6RSMTGT7.5EGYC4MK.js} +1 -1
  68. package/web/_astro/{gitGraphDiagram-PVQCEYII.du-L7V8A.js → gitGraphDiagram-PVQCEYII.bUUV7iEw.js} +1 -1
  69. package/web/_astro/index.Cestp9nh.css +1 -0
  70. package/web/_astro/{infoDiagram-5YYISTIA.CClGl9Px.js → infoDiagram-5YYISTIA.CbiInFvz.js} +1 -1
  71. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BuTETIPz.js → ishikawaDiagram-YF4QCWOH.CB7lrSsJ.js} +1 -1
  72. package/web/_astro/{journeyDiagram-JHISSGLW.Cyg1zCiE.js → journeyDiagram-JHISSGLW.rhGZgWt8.js} +1 -1
  73. package/web/_astro/{kanban-definition-UN3LZRKU.aH8eDXwX.js → kanban-definition-UN3LZRKU.DPeZD_lP.js} +1 -1
  74. package/web/_astro/{linear.paE_RY_i.js → linear.l60Nyp5b.js} +1 -1
  75. package/web/_astro/{mermaid.core.BhdKkI85.js → mermaid.core.DmtMJcmL.js} +4 -4
  76. package/web/_astro/{mindmap-definition-RKZ34NQL.aZNfv8Nx.js → mindmap-definition-RKZ34NQL.Cc47AcCn.js} +1 -1
  77. package/web/_astro/{pieDiagram-4H26LBE5.5psni0hC.js → pieDiagram-4H26LBE5.B8cN-S9g.js} +1 -1
  78. package/web/_astro/{quadrantDiagram-W4KKPZXB.DcGPGrFd.js → quadrantDiagram-W4KKPZXB.DY1FN89L.js} +1 -1
  79. package/web/_astro/{requirementDiagram-4Y6WPE33.BwPD2lzi.js → requirementDiagram-4Y6WPE33.CnM6VbV8.js} +1 -1
  80. package/web/_astro/{sankeyDiagram-5OEKKPKP.B3jGVk0l.js → sankeyDiagram-5OEKKPKP.B9DcGfNV.js} +1 -1
  81. package/web/_astro/{sequenceDiagram-3UESZ5HK.BdWsx3LW.js → sequenceDiagram-3UESZ5HK.ymxaNlAY.js} +1 -1
  82. package/web/_astro/{stateDiagram-AJRCARHV.DRpG4ClZ.js → stateDiagram-AJRCARHV.DDOJ3d8P.js} +1 -1
  83. package/web/_astro/{stateDiagram-v2-BHNVJYJU.Su0ML9Wo.js → stateDiagram-v2-BHNVJYJU.Ck0Nb_KY.js} +1 -1
  84. package/web/_astro/{timeline-definition-PNZ67QCA.Cg_Uv8A5.js → timeline-definition-PNZ67QCA.BNOvZwAN.js} +1 -1
  85. package/web/_astro/{vennDiagram-CIIHVFJN.DVouKT4b.js → vennDiagram-CIIHVFJN.D3k5ivSF.js} +1 -1
  86. package/web/_astro/{wardley-L42UT6IY.CexIVQli.js → wardley-L42UT6IY.BylaxVqn.js} +1 -1
  87. package/web/_astro/{wardleyDiagram-YWT4CUSO.ChSAzcvx.js → wardleyDiagram-YWT4CUSO.HLNtFUm9.js} +1 -1
  88. package/web/_astro/{xychartDiagram-2RQKCTM6.CN-Yp50J.js → xychartDiagram-2RQKCTM6.B-WooKSU.js} +1 -1
  89. package/web/index.html +2 -2
  90. package/web/_astro/BoardApp.CrusGeQ4.js +0 -1
  91. package/web/_astro/BoardApp.P8SRAD5Q.js +0 -179
  92. package/web/_astro/channel.CmK546kO.js +0 -1
  93. package/web/_astro/index.B4x8fe52.css +0 -1
@@ -7,7 +7,7 @@
7
7
  "plugins": [
8
8
  {
9
9
  "name": "sp",
10
- "version": "0.3.58",
10
+ "version": "0.3.61",
11
11
  "source": "./plugins/sp"
12
12
  }
13
13
  ]
@@ -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.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.1"
11
+ version: "1.2"
12
12
  name: my-project
13
13
 
14
14
  # ── Portable bootstrap (consumed by @gobing-ai/ts-infra
@@ -0,0 +1,137 @@
1
+ # Spur GLOBAL configuration — `~/.config/spur/config.yaml`
2
+ #
3
+ # Seeded here by `spur init` on first run (never overwritten once it exists — you
4
+ # own this file). It is the DEFAULT layer: every project's `.spur/config.yaml` is
5
+ # merged OVER it, so a project config only needs to carry its delta.
6
+ #
7
+ # Merge contract (A4 / config 1.2):
8
+ # - Both layers are validated by the SAME schema; each legitimately carries a subset.
9
+ # - The merge is total and automatic: project layer wins over global, key by key.
10
+ # - Validation runs ONCE, on the merged result — a partial entry here is a legal
11
+ # merge fragment, never a legal config on its own.
12
+ # - `agent.executors` merges by `name`: a project restating `- name: omp` with a
13
+ # different `model` overrides just that field and keeps the rest from here.
14
+ #
15
+ # Only machine-wide keys belong in this file. Project-shaped keys — `name`,
16
+ # `bootstrap`, `rules`, `redaction`, `tasks`, `features`, `agent.team` — resolve
17
+ # against a project's own folder structure and must stay in `.spur/config.yaml`.
18
+
19
+ $schema: "@gobing-ai/spur/schemas/spur-config.schema.json"
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
+
25
+ agent:
26
+ # `default` is the role used for `--agent auto` when the caller declares
27
+ # nothing (task 0542 R2 — the value domain moved from executor names to
28
+ # roles). A role id selects its tier's cheapest eligible executor; a
29
+ # configured executor name still resolves during the transition with a
30
+ # one-time warning (shim agent-default-executor); any other value fails
31
+ # naming both accepted sets.
32
+ default: coder
33
+
34
+ # Role → tier map. Resolution: role → tier → cheapest USABLE executor whose
35
+ # tier >= the role's tier, climbing the ladder across gaps. Keep at least one
36
+ # usable executor at or above each rung or that role fails loudly at dispatch.
37
+ # Stage floors (stage-registry model_policy): changelog=cheap;
38
+ # implement/test/wrap/review/refine/brainstorm=standard;
39
+ # verify/dogfood=capable-1; plan=capable-2. A stage's fallback ladder
40
+ # (auth / resource-exhaustion / gate-fail) only advances when a higher rung
41
+ # has a usable executor — an empty rung turns a quota failure into a hang.
42
+ #
43
+ # The vocabulary is CLOSED (task 0536): re-tier or re-stage these four, never
44
+ # invent a fifth — a config naming any other key fails at load naming the
45
+ # accepted four. A project may override per-field in its own `.spur/config.yaml`;
46
+ # restate only what you change.
47
+ #
48
+ # ADR-078: THIS TABLE IS THE SSOT. `DEFAULT_AGENT_ROLES` in
49
+ # `packages/config/src/index.ts` is a byte-identical fallback that applies only
50
+ # when no config layer supplies `agent.roles` at all (the CF-safe core must
51
+ # resolve roles with no filesystem). The two must stay byte-identical — a
52
+ # fallback that differed would turn a missing config file into a silent
53
+ # behavior change. `plugins/sp/tests/roles.test.ts` R9 gates all three
54
+ # projections (this table, the constant, and `plugins/sp/references/roles.md`).
55
+ roles:
56
+ scribe:
57
+ tier: cheap
58
+ stages: [changelog]
59
+ coder:
60
+ tier: standard
61
+ stages: [implement, test, wrap]
62
+ reviewer:
63
+ tier: capable-1
64
+ stages: [verify, review, dogfood]
65
+ planner:
66
+ tier: capable-2
67
+ stages: [plan, refine, brainstorm]
68
+
69
+ # Canonical coding-agent ids (ts-ai-runner DISPLAY_ORDER, 0.4.8+):
70
+ # claude, codex, gemini, pi, omp, opencode, antigravity-cli,
71
+ # openclaw, hermes, grok
72
+ # Grok auth: non-empty XAI_API_KEY and/or ~/.grok/auth.json (no CLI
73
+ # auth-status verb).
74
+
75
+ # Named executor profiles (ADR-033 / 0343). Each pairs a canonical agent with
76
+ # an explicit model override and an explicit capability tier.
77
+ # `model` is pinned on every entry: omitting it defers to the agent CLI's own
78
+ # default, which drifts with CLI upgrades and account state — pin what your
79
+ # CLI would resolve today (`grok models`, omp config.yml modelRoles.default,
80
+ # ~/.codex/config.toml, ~/.claude.json). The ids below are working examples,
81
+ # not vendor defaults — re-pin for your accounts.
82
+ #
83
+ # Pairing philosophy (operator guidance, 2026-08): a `native` pair — a vendor's
84
+ # model served by that vendor's own CLI (gpt-5.6-* via codex, claude-*-5 via
85
+ # claude, grok-4.6 via grok, gemini-3.x via agy) — consistently outperforms the
86
+ # same model routed through a third-party CLI, and belongs at the capable rungs.
87
+ # `portable` models (glm-5.x, deepseek-v4-*, …) are provider-agnostic and best
88
+ # carried by omp or pi at the cheap/standard rungs. The ladder below mixes both
89
+ # classes on purpose; measure pairings with the history plane before promoting
90
+ # a portable model into a capable rung.
91
+ # Live tiers: cheap | standard | capable-1 | capable-2 | capable-3
92
+ # (1=low quality within capable, 3=high). DECLARE tier — inference never
93
+ # invents capable-2/3. Stage routing starts on the cheapest executor whose
94
+ # tier >= min_tier; same exact tier ties break by array order.
95
+ # Legacy bare `capable` is accepted at runtime as synonym for capable-1.
96
+ #
97
+ # Because this is the global layer, a project that wants one different model
98
+ # writes only `- name: omp` + `model: …` — the agent and tier come from here.
99
+ executors:
100
+ # cheap rung is optional: with none declared, scribe-role work starts one
101
+ # rung up at the cheapest standard executor. Add one when transcript-heavy
102
+ # mechanical commands (changelog/gitmsg/handover) get noisy on cost.
103
+ # - name: minimax
104
+ # agent: omp
105
+ # model: minimax/MiniMax-M3
106
+ # tier: cheap
107
+ - name: omp
108
+ agent: omp
109
+ model: opencode/deepseek-v4-flash
110
+ tier: standard
111
+ - name: pi
112
+ agent: pi
113
+ model: "k3"
114
+ tier: capable-1
115
+ - name: grok
116
+ agent: grok
117
+ model: grok-4.6
118
+ tier: capable-2
119
+ - name: claude
120
+ agent: claude
121
+ model: k3
122
+ tier: capable-3
123
+ - name: codex
124
+ agent: codex
125
+ model: gpt-5.6
126
+ tier: capable-3
127
+
128
+ # `workflows.paths` is deliberately NOT set here. Its values are search paths
129
+ # resolved against a project's own root (0639 classifies it project-relative), so
130
+ # a machine-wide value would point every project at a directory that mostly does
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 .spur/workflows/wayfinder-resolution.yaml > .spur/run/wayfinder/$wbs-workflow-check.txt",
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
- # `.spur/workflows/` is the runtime read path in every layout — a symlink to
68
- # config/workflows/ inside the Spur monorepo, a real directory in a seeded
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 .spur/workflows/wayfinder-resolution.yaml > .spur/run/wayfinder/$wbs-workflow-check.txt"
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: 'rm -f .spur/run/wayfinder/$wbs-resolution-verdict.txt'
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.58",
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",
@@ -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.41",
57
- "@gobing-ai/ts-ai-runner": "^0.4.41",
58
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.41",
59
- "@gobing-ai/ts-infra": "^0.4.41",
60
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.41",
61
- "@gobing-ai/ts-rule-engine": "^0.4.41",
62
- "@gobing-ai/ts-runtime": "^0.4.41",
63
- "@gobing-ai/ts-utils": "^0.4.41",
56
+ "@gobing-ai/ts-db": "^0.4.42",
57
+ "@gobing-ai/ts-ai-runner": "^0.4.42",
58
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.42",
59
+ "@gobing-ai/ts-infra": "^0.4.42",
60
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.42",
61
+ "@gobing-ai/ts-rule-engine": "^0.4.42",
62
+ "@gobing-ai/ts-runtime": "^0.4.42",
63
+ "@gobing-ai/ts-utils": "^0.4.42",
64
64
  "@types/bun": "1.3.14",
65
65
  "@types/figlet": "^1.7.0",
66
66
  "@types/node-notifier": "8.0.5",
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[".spur/workflows/<br/>YAML workflow definitions"]
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 `.spur/workflows/task-pipeline.yaml`, and runs `spur workflow run` with HITL surfacing
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 ships workflow YAMLs under `.spur/workflows/`.
355
- Each pipeline owns one lifecycle phase:
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
  | ------------------------ | --------------------------------- | --------------------------------- | ------------- |
@@ -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[".spur/workflows/<br/>YAML workflow definitions"]
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 `.spur/workflows/task-pipeline.yaml`, and runs
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 ships workflow YAMLs under `.spur/workflows/`. Each
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 `.spur/workflows/task-pipeline.yaml` via `spur workflow run --async`
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; `.spur/workflows/pr-review.yaml` is the SSOT
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 .spur/workflows/wrapup-pipeline.yaml` is the only implementation; there is no inline wrap driver.
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 .spur/workflows/wrapup-pipeline.yaml --vars "$VARS" [--dry-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 .spur/workflows/wrapup-pipeline.yaml` is the only implementation; there is no inline wrap driver.
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 .spur/workflows/wrapup-pipeline.yaml --vars "$VARS" [--dry-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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp",
3
- "version": "0.3.58",
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 `DEFAULT_AGENT_ROLES` in `packages/config/src/index.ts` (task 0572 / ADR-061) — this
14
- file is the agent/human-facing view plus the plugin-owned command→role mapping. **Layer 2** maps
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 0572 / ADR-061): the tier/stages half of the block below is a generated view
42
- of DEFAULT_AGENT_ROLES in packages/config/src/index.ts — edit that constant, not this file.
43
- plugins/sp/tests/roles.test.ts (R9) fails the suite on any drift between the two. The
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 with
102
- `DEFAULT_AGENT_ROLES` (R9, 0572): the table above must equal the code SSOT byte-for-byte on
103
- id/tier/stages. When the table and the registry disagree, fix the table or the registry — never the
104
- test. When the table and `DEFAULT_AGENT_ROLES` disagree, fix the constant (or regenerate this view).
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.