@gobing-ai/spur 0.3.24 → 0.3.25

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 (61) hide show
  1. package/config/config.example.yaml +74 -31
  2. package/config/templates/AGENTS.md +1 -0
  3. package/config/workflows/docs-pipeline.yaml +9 -0
  4. package/config/workflows/idea-pipeline.yaml +78 -18
  5. package/package.json +9 -9
  6. package/schemas/spur-config.schema.json +4 -4
  7. package/schemas/task-batch.schema.json +12 -0
  8. package/spur.js +1643 -460
  9. package/web/_astro/{BoardApp.Cuna9Z5I.js → BoardApp.DH9wI8y7.js} +72 -72
  10. package/web/_astro/BoardApp.DZiwQCP7.js +1 -0
  11. package/web/_astro/{TaskDetail.Bso6Ccoa.js → TaskDetail.Dsk9DnGY.js} +1 -1
  12. package/web/_astro/{arc.BpfaYkuC.js → arc.Biv8k-OR.js} +1 -1
  13. package/web/_astro/{architectureDiagram-3BPJPVTR.Bsc64OWC.js → architectureDiagram-3BPJPVTR.BrtW5Sn7.js} +1 -1
  14. package/web/_astro/{blockDiagram-GPEHLZMM.CgrqZDLK.js → blockDiagram-GPEHLZMM.CTpFZJhW.js} +1 -1
  15. package/web/_astro/{c4Diagram-AAUBKEIU.5ROHxpqD.js → c4Diagram-AAUBKEIU._ZJj9H0G.js} +1 -1
  16. package/web/_astro/channel.Ih1_8SAH.js +1 -0
  17. package/web/_astro/{chunk-2J33WTMH.BIuSLWP4.js → chunk-2J33WTMH.DD9mDiEM.js} +1 -1
  18. package/web/_astro/{chunk-4BX2VUAB.u-fSGnxt.js → chunk-4BX2VUAB.ENDQu3TH.js} +1 -1
  19. package/web/_astro/{chunk-55IACEB6.pL62Yh8J.js → chunk-55IACEB6.DLpJf8Xp.js} +1 -1
  20. package/web/_astro/{chunk-727SXJPM.Cxy6KODj.js → chunk-727SXJPM.BR6vsvIV.js} +1 -1
  21. package/web/_astro/{chunk-AQP2D5EJ.D2XUILVx.js → chunk-AQP2D5EJ.DGOBzXM6.js} +1 -1
  22. package/web/_astro/{chunk-FMBD7UC4.DNnV20jb.js → chunk-FMBD7UC4.DrghnRtZ.js} +1 -1
  23. package/web/_astro/{chunk-ND2GUHAM.Cc-L-_6y.js → chunk-ND2GUHAM.BqIqI3oO.js} +1 -1
  24. package/web/_astro/{chunk-QZHKN3VN.Bw_kp1ef.js → chunk-QZHKN3VN.CJ2RJt0K.js} +1 -1
  25. package/web/_astro/{classDiagram-4FO5ZUOK.CoE-GIzM.js → classDiagram-4FO5ZUOK.Qu1p6crX.js} +1 -1
  26. package/web/_astro/{classDiagram-v2-Q7XG4LA2.CoE-GIzM.js → classDiagram-v2-Q7XG4LA2.Qu1p6crX.js} +1 -1
  27. package/web/_astro/{cose-bilkent-S5V4N54A.CDsPYTeJ.js → cose-bilkent-S5V4N54A.7VrRetJ0.js} +1 -1
  28. package/web/_astro/{dagre-BM42HDAG.BUw8fm5M.js → dagre-BM42HDAG.r4lTyJXQ.js} +1 -1
  29. package/web/_astro/{diagram-2AECGRRQ.Bx3Ndc4x.js → diagram-2AECGRRQ.DahExuaR.js} +1 -1
  30. package/web/_astro/{diagram-5GNKFQAL.DZOACNsA.js → diagram-5GNKFQAL.B-dSm3op.js} +1 -1
  31. package/web/_astro/{diagram-KO2AKTUF.BVmZqHXi.js → diagram-KO2AKTUF.CQGlKa6a.js} +1 -1
  32. package/web/_astro/{diagram-LMA3HP47.Dhw7Sl9e.js → diagram-LMA3HP47.CJ6nomD-.js} +1 -1
  33. package/web/_astro/{diagram-OG6HWLK6.xOqh3zFz.js → diagram-OG6HWLK6.ijGl68sM.js} +1 -1
  34. package/web/_astro/{erDiagram-TEJ5UH35.VX6HV9QU.js → erDiagram-TEJ5UH35.DBAe2Iin.js} +1 -1
  35. package/web/_astro/{flowDiagram-I6XJVG4X.D5tzv1nF.js → flowDiagram-I6XJVG4X.z3iXF6Ku.js} +1 -1
  36. package/web/_astro/{ganttDiagram-6RSMTGT7.bRb0hclW.js → ganttDiagram-6RSMTGT7.DP2ouiRt.js} +1 -1
  37. package/web/_astro/{gitGraphDiagram-PVQCEYII.BrXfUWT_.js → gitGraphDiagram-PVQCEYII.DizVfgVG.js} +1 -1
  38. package/web/_astro/index.D3Y4Q0mx.css +1 -0
  39. package/web/_astro/{infoDiagram-5YYISTIA.LIQUmEkh.js → infoDiagram-5YYISTIA.BPTTgL0f.js} +1 -1
  40. package/web/_astro/{ishikawaDiagram-YF4QCWOH.BMMwawXt.js → ishikawaDiagram-YF4QCWOH.CXdMa4-b.js} +1 -1
  41. package/web/_astro/{journeyDiagram-JHISSGLW.F7Rw6EQ6.js → journeyDiagram-JHISSGLW.ChSKZ-1j.js} +1 -1
  42. package/web/_astro/{kanban-definition-UN3LZRKU.BnZBa0gE.js → kanban-definition-UN3LZRKU.DUUlW-km.js} +1 -1
  43. package/web/_astro/{linear.DamosLmv.js → linear.AzHrSiEQ.js} +1 -1
  44. package/web/_astro/{mermaid.core.BjIs-rhV.js → mermaid.core.BajX78G7.js} +4 -4
  45. package/web/_astro/{mindmap-definition-RKZ34NQL.CAJpo14X.js → mindmap-definition-RKZ34NQL.BmdUHcac.js} +1 -1
  46. package/web/_astro/{pieDiagram-4H26LBE5.AcbGV8z3.js → pieDiagram-4H26LBE5.Dh59Ur2v.js} +1 -1
  47. package/web/_astro/{quadrantDiagram-W4KKPZXB.DFHo7-vl.js → quadrantDiagram-W4KKPZXB.D2qYQmFj.js} +1 -1
  48. package/web/_astro/{requirementDiagram-4Y6WPE33.ZcAUCpFg.js → requirementDiagram-4Y6WPE33.DW5nnrHl.js} +1 -1
  49. package/web/_astro/{sankeyDiagram-5OEKKPKP.B3jEuSva.js → sankeyDiagram-5OEKKPKP.CMl1PJrk.js} +1 -1
  50. package/web/_astro/{sequenceDiagram-3UESZ5HK.Cpz6c_VX.js → sequenceDiagram-3UESZ5HK.U5dq1PA0.js} +1 -1
  51. package/web/_astro/{stateDiagram-AJRCARHV.g_pKql00.js → stateDiagram-AJRCARHV.zrt55DVx.js} +1 -1
  52. package/web/_astro/{stateDiagram-v2-BHNVJYJU.DFINnXL2.js → stateDiagram-v2-BHNVJYJU.CKBGQ0dG.js} +1 -1
  53. package/web/_astro/{timeline-definition-PNZ67QCA.D0m2aZaf.js → timeline-definition-PNZ67QCA.CKAlx9rU.js} +1 -1
  54. package/web/_astro/{vennDiagram-CIIHVFJN.Cyk_24V8.js → vennDiagram-CIIHVFJN.Bgt1eF06.js} +1 -1
  55. package/web/_astro/{wardley-L42UT6IY.CW7JQlsX.js → wardley-L42UT6IY.BF02aioC.js} +1 -1
  56. package/web/_astro/{wardleyDiagram-YWT4CUSO.CkaxqiW8.js → wardleyDiagram-YWT4CUSO.C94wxcnJ.js} +1 -1
  57. package/web/_astro/{xychartDiagram-2RQKCTM6.DJorKgMY.js → xychartDiagram-2RQKCTM6.BwK7SRoW.js} +1 -1
  58. package/web/index.html +2 -2
  59. package/web/_astro/BoardApp.DSSZTsSW.js +0 -1
  60. package/web/_astro/channel.DKzvLld2.js +0 -1
  61. package/web/_astro/index.BRj8-zmo.css +0 -1
@@ -1,13 +1,18 @@
1
- # Spur project configuration for spur-new
2
- # Generated by `spur init`
1
+ # Spur project configuration example
2
+ # Seeded by `spur init` as ~/.config/spur/config.yaml on first run (never overwritten).
3
+ # Copy / adapt into a project as `.spur/config.yaml`.
3
4
 
4
5
  $schema: "@gobing-ai/spur/schemas/spur-config.schema.json"
5
- version: "1"
6
- name: spur-new
6
+ # Config schema version (string). Current recommended: "1.1".
7
+ # "1" remains accepted; there is no hard migrator yet. Prefer "1.1" for new projects
8
+ # so editors and operators know the file targets the ADR-033 + planning shape.
9
+ version: "1.1"
10
+ name: my-project
7
11
 
8
12
  # ── Portable bootstrap (consumed by @gobing-ai/ts-infra runNodeApplication) ──
9
13
  # Shared across spur and (future) spur-server. Keys map 1:1 to ts-infra's
10
14
  # LoggingOptions / TelemetryOptions / database / SchedulerOptions.
15
+ # Not validated by spurConfigSchema (bootstrap is owned by runNodeApplication).
11
16
  bootstrap:
12
17
  logging:
13
18
  enabled: true
@@ -28,40 +33,65 @@ bootstrap:
28
33
  scheduler:
29
34
  enabled: false # CLI is run-once; no scheduler
30
35
 
31
- # ── Server runtime (env-backed: PORT / HOST override; consumed by spur serve) ──
32
- server:
33
- port: 3000 # env: PORT
34
- host: localhost # env: HOST
35
- openBrowser: true # spur serve only; skip with --no-open
36
- webDistPath: null # S5 local static asset path
37
- # ── Spur app section (validated by a local zod schema — UNCHANGED keys) ──
36
+ # ── Spur app section (validated by spurConfigSchema in @gobing-ai/spur-config) ──
37
+ # Server runtime (port/host/openBrowser) is env-backed via PORT/HOST — not a
38
+ # project-config key. See design §2.2.
38
39
  agent:
39
- # `default` is the executor selector for `--agent auto` (resolved as an executor
40
- # name first, then a legacy agent name). Keep it simple, or define richer profiles:
40
+ # `default` is the executor selector for `--agent auto` when stage-registry
41
+ # routing does not apply (or as a fallback). Resolved as an executor name
42
+ # first, then a legacy agent name.
41
43
  default: omp
44
+
42
45
  # Canonical coding-agent ids (ts-ai-runner DISPLAY_ORDER, 0.4.8+):
43
46
  # claude, codex, gemini, pi, omp, opencode, antigravity-cli, openclaw, hermes, grok
44
47
  # Grok auth: non-empty XAI_API_KEY and/or ~/.grok/auth.json (no CLI auth-status verb).
45
- # Named executor profiles: pair a canonical agent with an optional opaque model
46
- # override. Referenced by name from `default` and `default-by-phase`.
47
- # executors:
48
- # - name: omp
49
- # agent: omp
50
- # - name: omp-zai
51
- # agent: omp
52
- # model: zai//glm-5.2
53
- # - name: claude
54
- # agent: claude
55
- # - name: grok
56
- # agent: grok
57
- # # model: grok-… # optional; passed as grok -m <model>
58
- # Per-phase auto routing — a MAP of dev phase → executor selector. A configured
59
- # phase mapping is authoritative: a broken mapping fails fast (unknown executor →
60
- # exit 2; unusable agent → exit 1) and does NOT fall back to `default`.
48
+
49
+ # Named executor profiles (ADR-033 / 0343). Each pairs a canonical agent with
50
+ # an optional opaque model override and an explicit capability tier.
51
+ # Live tiers: cheap | standard | capable-1 | capable-2 | capable-3
52
+ # (1=low quality within capable, 3=high). DECLARE tier — inference never
53
+ # invents capable-2/3. Stage routing starts on the cheapest executor whose
54
+ # tier >= min_tier; same exact tier ties break by array order.
55
+ # Legacy bare `capable` is accepted at runtime as synonym for capable-1.
56
+ executors:
57
+ - name: omp
58
+ agent: omp
59
+ tier: standard
60
+ # - name: omp-zai
61
+ # agent: omp
62
+ # model: zai/glm-5.2
63
+ # tier: standard
64
+ - name: grok
65
+ agent: grok
66
+ tier: capable-2
67
+ - name: claude
68
+ agent: claude
69
+ tier: capable-3
70
+ - name: codex
71
+ agent: codex
72
+ tier: capable-3
73
+ # - name: pi
74
+ # agent: pi
75
+ # tier: capable-1
76
+
77
+ # `default-by-phase` is a deprecated backward-compat shim (ADR-033). Prefer
78
+ # executor `tier` + stage-registry model_policy. When present, a matching
79
+ # phase mapping is still authoritative (fail-fast; no fall back to default)
80
+ # and shadows stage routing for that phase.
61
81
  # default-by-phase:
62
- # dev-run: omp-zai
82
+ # dev-run: omp
63
83
  # dev-review: claude
64
- # # dev-run: grok
84
+
85
+ # Declarative teams (feature M) — materialize with `spur team up <teamId>`.
86
+ # team:
87
+ # demo:
88
+ # name: "Demo Team"
89
+ # work_dir: ~/path/to/project
90
+ # members:
91
+ # - executor: claude
92
+ # purpose: "Lead — planning & review"
93
+ # - executor: omp
94
+ # purpose: "Implementer"
65
95
 
66
96
  rules:
67
97
  paths:
@@ -73,3 +103,16 @@ workflows:
73
103
 
74
104
  redaction:
75
105
  enabled: false
106
+
107
+ # ── Planning (design §2.1 / §9) ──
108
+ tasks:
109
+ active: docs/tasks
110
+ folders:
111
+ docs/tasks:
112
+ baseCounter: 0
113
+ label: Core
114
+ # severity:
115
+ # L3.plan-format: off # error | warning | off (known finding codes only)
116
+
117
+ features:
118
+ dir: docs/features
@@ -37,6 +37,7 @@ All product development work goes through the harness by default.
37
37
  | Plan a feature (intake → AC → tasks) | `/sp:dev-plan`, `/sp:dev-idea` | Freeform feature files without gates |
38
38
  | Drive one task end-to-end | `/sp:dev-run <wbs>` or **`sp:super-coder`** | Implement with no task / no pipeline |
39
39
  | Batch or parallel task runs | `/sp:dev-runall`, `/sp:dev-parallel` → **`sp:super-coder`** | Unordered multi-task thrash |
40
+ | Batch-refine tasks under a feature | `/sp:dev-refineall --feature <id> --auto` | Hand-looping `/sp:dev-refine` per WBS |
40
41
  | Multi-step corpus CLI (tasks/features/rules/workflows) | **`sp:expert-spur`** | Raw Write/Edit on corpus files |
41
42
  | Look up `spur` verbs / flags / `--json` | Skill **`sp:spur-cli`** | Inventing flags from memory |
42
43
  | Create/edit/list tasks or features | **`spur task` / `spur feature`** (`--section --from-file`) | Direct-writing task/feature corpus files |
@@ -65,6 +65,15 @@ states:
65
65
  - id: done
66
66
  description: Terminal — docs deliverable reviewed and recorded.
67
67
  onEnter:
68
+ # Done gate requires a PASS verdict artifact (no silent no-artifact allow).
69
+ # Docs-only pipelines do not run /sp:dev-verify; write a docs-only PASS stub
70
+ # then transition. Override path remains: --force-done --reason.
71
+ - kind: shell
72
+ options:
73
+ command: >
74
+ mkdir -p .spur/run &&
75
+ printf '%s\n' "{\"wbs\":\"${vars.wbs}\",\"verdict\":\"PASS\",\"source\":\"docs-pipeline\",\"requirements\":[{\"id\":\"docs-deliverable\",\"status\":\"MET\",\"evidence\":\"docs-pipeline record step\"}],\"acceptanceCriteria\":[],\"checks\":[{\"name\":\"docs-only\",\"status\":\"pass\",\"evidence\":\"docs-pipeline\"}]}"
76
+ > ".spur/run/${vars.wbs}-verdict.json"
68
77
  - kind: shell
69
78
  options:
70
79
  command: "${vars.spurBin} task update ${vars.wbs} done --no-lifecycle"
@@ -7,18 +7,24 @@
7
7
  # No state in this pipeline inlines another pipeline's state graph (no-nesting principle,
8
8
  # design §System Principles 4).
9
9
  #
10
- # Shape: start -> discovery -> feature-create -> ac-generate -> feature-check
11
- # -> system-design (conditional: needs_design signal or --design)
10
+ # Shape: start -> discovery -> idea-eval -> feature-create -> ac-generate -> feature-check
11
+ # -> system-design (conditional: needs_design signal)
12
12
  # -> design-approval (taste HITL gate; not auto-clicked by --auto)
13
13
  # -> decompose -> batch-create -> handoff
14
+ # (idea-eval rejection -> cancelled)
14
15
  # (feature-check failure routes back to ac-generate; batch-create failure to decompose).
15
16
  #
16
17
  # Vars (passed as a JSON object via `--vars`):
17
18
  # idea — the idea text (required), e.g. --vars '{"idea":"add a --dry-run flag to dev-wrap"}'
18
19
  # profile — set --vars '{"profile":"auto"}' to skip objective HITL gates (feature-check, batch-create)
19
- # design — "auto" (default, signal-driven), "force" (--design), "skip" (--skip-design)
20
- # design_approved "true" only when the operator explicitly approved the design in-session;
20
+ # design — "auto" (default, signal-driven) or "skip" (--skip-design). No force path.
21
+ # Unified: skip also means omit per-task Design in batch-create (scaffold only;
22
+ # refine fills later). Default: decompose must author batch item `design`.
23
+ # design_approved — "true" when taste pre-cleared (CLI --approve-taste or alias --design-approved);
21
24
  # lets profile=auto route around the design-approval taste gate (default "false")
25
+ # idea_approved — "true" when taste pre-cleared (CLI --approve-taste or alias --idea-approved);
26
+ # lets profile=auto route around the idea-eval taste gate (default "false")
27
+ # CLI --approve-taste sets both design_approved and idea_approved to true.
22
28
  # spurBin — PATH-independent spur invocation (overridden by CLI at run start)
23
29
  # agent — agent for agent.run steps (default: omp)
24
30
  #
@@ -27,9 +33,9 @@
27
33
  "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
28
34
  kind: state-machine
29
35
  name: idea-pipeline
30
- description: "Idea to feature + AC + task batch: discovery, feature-create, ac-generate, feature-check, system-design, decompose, batch-create, handoff"
31
- # Worst legal auto path with advertised caps: start/discovery/feature/ac plus 2 AC retries,
32
- # design, one design rejection, decompose plus 2 batch retries, handoff ≈22 transitions.
36
+ description: "Idea to feature + AC + task batch: discovery, idea-eval, feature-create, ac-generate, feature-check, system-design, decompose, batch-create, handoff"
37
+ # Worst legal auto path with advertised caps: start/discovery/idea-eval/feature/ac plus 2 AC
38
+ # retries, design, one design rejection, decompose plus 2 batch retries, handoff ≈24 transitions.
33
39
  # Keep a small cushion so the explicit retry caps fail first, not the engine bound.
34
40
  iterationBound: 25
35
41
  initialState: start
@@ -42,9 +48,12 @@ vars:
42
48
  profile: "standard"
43
49
  design: "auto"
44
50
  design_approved: "false"
51
+ idea_approved: "false"
45
52
  featureId: ""
46
53
  __hitlAnswer: ""
47
54
  spurBin: "spur"
55
+ # R8 (0366): injected by WorkflowAppService.run(); stamps discovery artifact provenance.
56
+ __runId: ""
48
57
  agent: "omp"
49
58
  stepTimeoutMs: "600000"
50
59
 
@@ -62,7 +71,7 @@ states:
62
71
  command: "${vars.spurBin} agent doctor ${vars.agent}"
63
72
  - kind: shell
64
73
  options:
65
- command: 'mkdir -p .spur/run && rm -f .spur/run/idea-ac-retry-count .spur/run/idea-decompose-retry-count .spur/run/idea-feature-id.txt .spur/run/idea-ac-content.md .spur/run/idea-ac-done.txt .spur/run/idea-task-batch.json .spur/run/idea-batch-create.done .spur/run/idea-batch-create.failed'
74
+ command: 'mkdir -p .spur/run && { [ -f .spur/run/idea-eval-report.md ] || [ -f .spur/run/idea-needs-design.json ]; } && { a=".spur/run/idea-archive/$(date +%Y%m%d-%H%M%S)"; mkdir -p "$a"; mv -f .spur/run/idea-eval-report.md "$a/" 2>/dev/null; mv -f .spur/run/idea-needs-design.json "$a/" 2>/dev/null; } ; rm -f .spur/run/idea-ac-retry-count .spur/run/idea-decompose-retry-count .spur/run/idea-feature-id.txt .spur/run/idea-ac-content.md .spur/run/idea-ac-done.txt .spur/run/idea-task-batch.json .spur/run/idea-batch-create.done .spur/run/idea-batch-create.failed'
66
75
 
67
76
  - id: discovery
68
77
  description: >
@@ -70,24 +79,41 @@ states:
70
79
  and record a design summary. The brainstorm ALWAYS records a design summary
71
80
  ("nothing is too simple" pattern). The brainstorm also emits a needs_design
72
81
  boolean signal written to .spur/run/idea-needs-design.json — this determines
73
- whether the system-design state runs.
82
+ whether the system-design state runs. As its terminal artifact for the idea path,
83
+ brainstorm also emits the idea-evaluation report to .spur/run/idea-eval-report.md
84
+ (template: plugins/sp/skills/spur-dev/references/idea-evaluation.md).
74
85
  onEnter:
75
86
  - kind: agent.run
76
87
  options:
77
88
  agent: ${vars.agent}
78
- input: "Run sp:brainstorm for the idea: ${vars.idea}. The skill owns the approach-generation, design summary, and `needs_design` signal criteria; emit .spur/run/idea-needs-design.json ({\"needs_design\": true|false}) and the design summary per the skill's `Design Approval Gate` and `The needs_design signal` sections."
89
+ input: "Run sp:brainstorm for the idea: ${vars.idea}. The skill owns the approach-generation, design summary, and `needs_design` signal criteria; emit .spur/run/idea-needs-design.json ({\"needs_design\": true|false}) and the design summary per the skill's `Design Approval Gate` and `The needs_design signal` sections. Also emit the idea-evaluation report to .spur/run/idea-eval-report.md per plugins/sp/skills/spur-dev/references/idea-evaluation.md (urgency/necessity 0–5, premises, pros/cons, alternatives, enhanced idea, recommendation). At the END of the report, append a provenance footer block of the exact form: `---\\nrun_id: ${vars.__runId}\\ngenerated_at: <RFC3339 timestamp>\\n---` (omit the footer only if run_id is empty)."
79
90
  timeoutMs: ${vars.stepTimeoutMs}
80
91
 
92
+ - id: idea-eval
93
+ description: >
94
+ HITL taste gate. Discovery has produced the idea-evaluation report
95
+ (.spur/run/idea-eval-report.md) with urgency/necessity scores, premises,
96
+ pros/cons, and a recommendation. The operator reviews and approves or
97
+ rejects. This gate is NOT auto-clicked by --auto (taste gate, like
98
+ design-approval). Only routes around when vars.idea_approved=true
99
+ (explicit prior approval).
100
+ pause: true
101
+ onEnter:
102
+ - kind: hitl.confirm
103
+ options:
104
+ prompt: "Review the idea evaluation report (.spur/run/idea-eval-report.md). Approve to create a feature, or reject to cancel? (Reject creates no feature.)"
105
+
81
106
  - id: feature-create
82
107
  description: >
83
108
  Create a feature via spur feature create, or select an existing feature id.
84
109
  The agent writes the feature id to .spur/run/idea-feature-id.txt for subsequent
85
- states to read.
110
+ states to read. Prefer the enhanced idea from .spur/run/idea-eval-report.md as
111
+ context; do not overwrite vars.idea.
86
112
  onEnter:
87
113
  - kind: agent.run
88
114
  options:
89
115
  agent: ${vars.agent}
90
- input: "Create a feature for the idea: ${vars.idea}. Use 'spur feature create \"<name>\" --json' to create it. Write the feature id to .spur/run/idea-feature-id.txt. If an existing feature is appropriate, use its id instead."
116
+ input: "Create a feature for the idea: ${vars.idea}. Read .spur/run/idea-eval-report.md if present for the enhanced idea and scores. Use 'spur feature create \"<name>\" --json' to create it. Write the feature id to .spur/run/idea-feature-id.txt. If an existing feature is appropriate, use its id instead."
91
117
  expectFile: .spur/run/idea-feature-id.txt
92
118
  timeoutMs: ${vars.stepTimeoutMs}
93
119
  - kind: file.read.into-var
@@ -138,7 +164,7 @@ states:
138
164
  - id: system-design
139
165
  description: >
140
166
  Dispatch sp:sys-architecture to produce the system design. This state runs
141
- only when needs_design=true (or --design forces it). The agent creates ADR
167
+ only when needs_design=true (design=auto signal path). The agent creates ADR
142
168
  entries, architecture updates, and design satellites through constitution rules.
143
169
  The design-approval state follows (taste gate).
144
170
  onEnter:
@@ -230,13 +256,47 @@ transitions:
230
256
  guard:
231
257
  kind: always
232
258
 
233
- # ── discovery -> feature-create ──
259
+ # ── discovery: auto-skip (profile=auto + idea_approved) OR enter idea-eval taste gate ──
260
+ # Declaration order: auto-skip FIRST (same pattern as system-design → design-approval).
261
+ # Without this edge, discovery always enters idea-eval (pause: true), rendering the prompt
262
+ # and persisting an avoidable pause before the in-state auto-skip guard can fire (0366 R4/R5).
234
263
  - from: discovery
235
264
  to: feature-create
236
- description: Discovery completecreate or select a feature.
265
+ description: profile=auto AND idea_approved=true skip idea-eval taste gate entirely.
266
+ guard:
267
+ kind: shell
268
+ options:
269
+ command: 'test "${vars.profile}" = auto && test "${vars.idea_approved}" = true'
270
+ - from: discovery
271
+ to: idea-eval
272
+ description: Discovery complete — gate on idea evaluation taste decision.
237
273
  guard:
238
274
  kind: always
239
275
 
276
+ # ── idea-eval: auto-skip (profile=auto + idea_approved) OR approve/reject HITL ──
277
+ # Declaration order: auto-skip FIRST (same pattern as system-design → design-approval).
278
+ - from: idea-eval
279
+ to: feature-create
280
+ description: profile=auto AND idea_approved=true — skip idea-eval taste gate.
281
+ guard:
282
+ kind: shell
283
+ options:
284
+ command: 'test "${vars.profile}" = auto && test "${vars.idea_approved}" = true'
285
+ - from: idea-eval
286
+ to: feature-create
287
+ description: Idea evaluation approved — create or select a feature.
288
+ guard:
289
+ kind: shell
290
+ options:
291
+ command: 'test "${vars.__hitlAnswer}" = yes'
292
+ - from: idea-eval
293
+ to: cancelled
294
+ description: Idea evaluation rejected or cancelled — no feature created.
295
+ guard:
296
+ kind: shell
297
+ options:
298
+ command: 'test "${vars.__hitlAnswer}" = no || test "${vars.__hitlAnswer}" = cancel'
299
+
240
300
  # ── feature-create -> ac-generate ──
241
301
  - from: feature-create
242
302
  to: ac-generate
@@ -250,14 +310,14 @@ transitions:
250
310
  # routes directly to the appropriate next state. Under interactive, the always fallback enters
251
311
  # the feature-check state whose onEnter hitl.confirm pauses for operator confirmation.
252
312
  #
253
- # Auto-skip 1: pass + design route → system-design
313
+ # Auto-skip 1: pass + design route → system-design (design=auto + needs_design != false)
254
314
  - from: ac-generate
255
315
  to: system-design
256
316
  description: "profile=auto, check passed, design route — run system design."
257
317
  guard:
258
318
  kind: shell
259
319
  options:
260
- command: 'test "${vars.profile}" = auto && ${vars.spurBin} feature check ${vars.featureId} --strict && (test "${vars.design}" = force || (test "${vars.design}" = auto && test "$(jq -r .needs_design .spur/run/idea-needs-design.json 2>/dev/null)" != false))'
320
+ command: 'test "${vars.profile}" = auto && ${vars.spurBin} feature check ${vars.featureId} --strict && test "${vars.design}" = auto && test "$(jq -r .needs_design .spur/run/idea-needs-design.json 2>/dev/null)" != false'
261
321
  # Auto-skip 2: pass + skip-design route → decompose
262
322
  - from: ac-generate
263
323
  to: decompose
@@ -297,7 +357,7 @@ transitions:
297
357
  guard:
298
358
  kind: shell
299
359
  options:
300
- command: 'test "${vars.__hitlAnswer}" = yes && ${vars.spurBin} feature check ${vars.featureId} --strict && (test "${vars.design}" = force || (test "${vars.design}" = auto && test "$(jq -r .needs_design .spur/run/idea-needs-design.json 2>/dev/null)" != false))'
360
+ command: 'test "${vars.__hitlAnswer}" = yes && ${vars.spurBin} feature check ${vars.featureId} --strict && test "${vars.design}" = auto && test "$(jq -r .needs_design .spur/run/idea-needs-design.json 2>/dev/null)" != false'
301
361
  - from: feature-check
302
362
  to: decompose
303
363
  description: Feature check passed, skip-design route — go directly to decompose.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.24",
3
+ "version": "0.3.25",
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",
@@ -50,14 +50,14 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@commander-js/extra-typings": "^14.0.0",
53
- "@gobing-ai/ts-db": "^0.4.11",
54
- "@gobing-ai/ts-ai-runner": "^0.4.11",
55
- "@gobing-ai/ts-dual-workflow-engine": "^0.4.11",
56
- "@gobing-ai/ts-infra": "^0.4.11",
57
- "@gobing-ai/ts-llm-jsonl-importer": "^0.4.11",
58
- "@gobing-ai/ts-rule-engine": "^0.4.11",
59
- "@gobing-ai/ts-runtime": "^0.4.11",
60
- "@gobing-ai/ts-utils": "^0.4.11",
53
+ "@gobing-ai/ts-db": "^0.4.14",
54
+ "@gobing-ai/ts-ai-runner": "^0.4.14",
55
+ "@gobing-ai/ts-dual-workflow-engine": "^0.4.14",
56
+ "@gobing-ai/ts-infra": "^0.4.14",
57
+ "@gobing-ai/ts-llm-jsonl-importer": "^0.4.14",
58
+ "@gobing-ai/ts-rule-engine": "^0.4.14",
59
+ "@gobing-ai/ts-runtime": "^0.4.14",
60
+ "@gobing-ai/ts-utils": "^0.4.14",
61
61
  "@types/bun": "1.3.14",
62
62
  "@types/figlet": "^1.7.0",
63
63
  "@types/node-notifier": "8.0.5",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "version": {
14
14
  "type": "string",
15
- "description": "Config schema version. Currently '1'."
15
+ "description": "Config schema version (string, not integer). Current recommended: '1.1' (ADR-033 executor tiers + planning blocks). '1' remains accepted for backward compatibility."
16
16
  },
17
17
  "name": {
18
18
  "type": "string",
@@ -129,15 +129,15 @@
129
129
  },
130
130
  "tier": {
131
131
  "type": "string",
132
- "enum": ["cheap", "standard", "capable"],
133
- "description": "Capability tier for stage-registry adaptive model routing (ADR-033). A stage starts on the cheapest eligible executor meeting its model_policy min_tier and escalates along the fallback chain on objective signals."
132
+ "enum": ["cheap", "standard", "capable-1", "capable-2", "capable-3"],
133
+ "description": "Capability tier for stage-registry adaptive model routing (ADR-033, 0343). Live values: cheap | standard | capable-1 | capable-2 | capable-3 (1=low output quality, 3=high within the capable band). A stage starts on the cheapest eligible executor meeting its model_policy min_tier. Bare legacy `capable` is accepted at runtime (zod preprocess → capable-1) during the deprecation window but is not part of this editor enum."
134
134
  }
135
135
  }
136
136
  }
137
137
  },
138
138
  "default-by-phase": {
139
139
  "type": "object",
140
- "description": "Map of dev phase (e.g. dev-run, dev-review) to executor selector. A configured phase mapping is authoritative a broken mapping fails fast and does NOT fall back to `default`.",
140
+ "description": "DEPRECATED (ADR-033). Backward-compat map of dev phase (e.g. dev-run, dev-review) to executor selector. Prefer executor `tier` + stage-registry model_policy. When present, a matching phase mapping is still authoritative (fail-fast; no fall back to `default`) and shadows stage routing for that phase.",
141
141
  "additionalProperties": {
142
142
  "type": "string"
143
143
  }
@@ -22,6 +22,18 @@
22
22
  "type": "string",
23
23
  "description": "R-numbered requirement items (R1. R2. …) — a referenceable list."
24
24
  },
25
+ "design": {
26
+ "type": "string",
27
+ "description": "Pre-filled ### Design body (WHAT/WHY decision record). Default for plan/decompose unless --skip-design."
28
+ },
29
+ "plan": {
30
+ "type": "string",
31
+ "description": "Pre-filled ### Plan body (ordered checklist)."
32
+ },
33
+ "acceptance_criteria": {
34
+ "type": "string",
35
+ "description": "Pre-filled ### Acceptance Criteria body (Gherkin or checklist)."
36
+ },
25
37
  "feature_id": {
26
38
  "type": "string",
27
39
  "pattern": "^[A-Z][1-9]*$",