@gobing-ai/spur 0.3.20 → 0.3.23

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 (66) hide show
  1. package/config/rules/typescript/prefer-accessible-role-for-button-queries.yaml +31 -0
  2. package/config/templates/docs/00_ADR.md +25 -15
  3. package/config/templates/docs/01_PRD.md +12 -7
  4. package/config/templates/docs/02_ROADMAP.md +16 -8
  5. package/config/templates/docs/03_ARCHITECTURE.md +12 -5
  6. package/config/templates/docs/04_DESIGN.md +26 -8
  7. package/config/templates/docs/05_FEATURES.md +18 -7
  8. package/config/templates/docs/99_PROJECT_CONSTITUTION.md +427 -33
  9. package/config/workflows/task-pipeline.yaml +6 -2
  10. package/config/workflows/wrapup-pipeline.yaml +4 -7
  11. package/package.json +1 -1
  12. package/schemas/spur-config.schema.json +13 -0
  13. package/spur.js +7816 -6774
  14. package/web/_astro/BoardApp.LygxZgOy.js +1 -0
  15. package/web/_astro/{BoardApp.DfUXxULJ.js → BoardApp.b8HvN_Uy.js} +82 -82
  16. package/web/_astro/{TaskDetail.CWHJA-V_.js → TaskDetail.BRr8ebLd.js} +1 -1
  17. package/web/_astro/{arc.B64JH2Yw.js → arc.D9I3ghf3.js} +1 -1
  18. package/web/_astro/{architectureDiagram-3BPJPVTR.CNsf8RqK.js → architectureDiagram-3BPJPVTR.B60VjZ82.js} +1 -1
  19. package/web/_astro/{blockDiagram-GPEHLZMM.B5L6Sdtp.js → blockDiagram-GPEHLZMM.B8xiXsGb.js} +1 -1
  20. package/web/_astro/{c4Diagram-AAUBKEIU.D2LUWzto.js → c4Diagram-AAUBKEIU.D8Q9jRJZ.js} +1 -1
  21. package/web/_astro/channel.BToTp7Lu.js +1 -0
  22. package/web/_astro/{chunk-2J33WTMH.BDCK4a2A.js → chunk-2J33WTMH.BVcogAuP.js} +1 -1
  23. package/web/_astro/{chunk-4BX2VUAB.DRG-P5ln.js → chunk-4BX2VUAB.pDodeppW.js} +1 -1
  24. package/web/_astro/{chunk-55IACEB6.BF6dAaDw.js → chunk-55IACEB6.5dYLJxJn.js} +1 -1
  25. package/web/_astro/{chunk-727SXJPM.GT8NEsK6.js → chunk-727SXJPM.C6GTI_n6.js} +1 -1
  26. package/web/_astro/{chunk-AQP2D5EJ.C6g9Ixyp.js → chunk-AQP2D5EJ.kgDX41bQ.js} +1 -1
  27. package/web/_astro/{chunk-FMBD7UC4.37t3ZahP.js → chunk-FMBD7UC4.CSnAi74r.js} +1 -1
  28. package/web/_astro/{chunk-ND2GUHAM.CIMe94Tp.js → chunk-ND2GUHAM.qQ8ldUUT.js} +1 -1
  29. package/web/_astro/{chunk-QZHKN3VN.BDk4vBSo.js → chunk-QZHKN3VN.PzPFlVri.js} +1 -1
  30. package/web/_astro/{classDiagram-4FO5ZUOK.BkZHAH5J.js → classDiagram-4FO5ZUOK.C7RulRYW.js} +1 -1
  31. package/web/_astro/{classDiagram-v2-Q7XG4LA2.BkZHAH5J.js → classDiagram-v2-Q7XG4LA2.C7RulRYW.js} +1 -1
  32. package/web/_astro/{cose-bilkent-S5V4N54A.-vmutMeo.js → cose-bilkent-S5V4N54A.Dw4HZHnT.js} +1 -1
  33. package/web/_astro/{dagre-BM42HDAG.YTN__ph-.js → dagre-BM42HDAG.MmGbZWM_.js} +1 -1
  34. package/web/_astro/{diagram-2AECGRRQ.CpwYXr6h.js → diagram-2AECGRRQ.DugWYvZC.js} +1 -1
  35. package/web/_astro/{diagram-5GNKFQAL.BLW_nNiA.js → diagram-5GNKFQAL.BL7D0BMi.js} +1 -1
  36. package/web/_astro/{diagram-KO2AKTUF.BTFC9CYM.js → diagram-KO2AKTUF.B9GQMjwM.js} +1 -1
  37. package/web/_astro/{diagram-LMA3HP47.CWXHZTYF.js → diagram-LMA3HP47.CbHPvhbu.js} +1 -1
  38. package/web/_astro/{diagram-OG6HWLK6.4DO1knJK.js → diagram-OG6HWLK6.Bx6GcKpw.js} +1 -1
  39. package/web/_astro/{erDiagram-TEJ5UH35.eWFFCa1s.js → erDiagram-TEJ5UH35._sHJgXD7.js} +1 -1
  40. package/web/_astro/{flowDiagram-I6XJVG4X.Qnt78_UD.js → flowDiagram-I6XJVG4X.D305L8m4.js} +1 -1
  41. package/web/_astro/{ganttDiagram-6RSMTGT7.CMqioE2G.js → ganttDiagram-6RSMTGT7.qjJ4kX00.js} +1 -1
  42. package/web/_astro/{gitGraphDiagram-PVQCEYII.DIHrO_gc.js → gitGraphDiagram-PVQCEYII.D-t4MzVO.js} +1 -1
  43. package/web/_astro/index.CmVh0AUD.css +1 -0
  44. package/web/_astro/{infoDiagram-5YYISTIA.DbzNXZsX.js → infoDiagram-5YYISTIA.WwSNIljZ.js} +1 -1
  45. package/web/_astro/{ishikawaDiagram-YF4QCWOH.C34rBvEh.js → ishikawaDiagram-YF4QCWOH.EWsUYdpd.js} +1 -1
  46. package/web/_astro/{journeyDiagram-JHISSGLW.B4Y56hm8.js → journeyDiagram-JHISSGLW.CqKE9hNP.js} +1 -1
  47. package/web/_astro/{kanban-definition-UN3LZRKU.CbkLbGD-.js → kanban-definition-UN3LZRKU.BDCCufoa.js} +1 -1
  48. package/web/_astro/{linear.CJu-zQ8Y.js → linear.CyHEakPy.js} +1 -1
  49. package/web/_astro/{mermaid.core.Cg8FpcnS.js → mermaid.core.B-9P_KDH.js} +4 -4
  50. package/web/_astro/{mindmap-definition-RKZ34NQL.CUS8uIx4.js → mindmap-definition-RKZ34NQL.bCxpjW2r.js} +1 -1
  51. package/web/_astro/{pieDiagram-4H26LBE5.DLoKfxBO.js → pieDiagram-4H26LBE5.x_CRiGMu.js} +1 -1
  52. package/web/_astro/{quadrantDiagram-W4KKPZXB.C4gJNQom.js → quadrantDiagram-W4KKPZXB.CnbQkwo7.js} +1 -1
  53. package/web/_astro/{requirementDiagram-4Y6WPE33.BsiW5Ob5.js → requirementDiagram-4Y6WPE33.CfeJKVEP.js} +1 -1
  54. package/web/_astro/{sankeyDiagram-5OEKKPKP.k6qljwMr.js → sankeyDiagram-5OEKKPKP.COYpTQlG.js} +1 -1
  55. package/web/_astro/{sequenceDiagram-3UESZ5HK.Bx0G-FfT.js → sequenceDiagram-3UESZ5HK.DVzoeimO.js} +1 -1
  56. package/web/_astro/{stateDiagram-AJRCARHV.CRbr10-B.js → stateDiagram-AJRCARHV.BVL5te9q.js} +1 -1
  57. package/web/_astro/{stateDiagram-v2-BHNVJYJU.iDwcqAkR.js → stateDiagram-v2-BHNVJYJU.C_x1GbV0.js} +1 -1
  58. package/web/_astro/{timeline-definition-PNZ67QCA.p4S9tDNI.js → timeline-definition-PNZ67QCA.DtZPbOJL.js} +1 -1
  59. package/web/_astro/{vennDiagram-CIIHVFJN.DgzRFt8Y.js → vennDiagram-CIIHVFJN.pexoUOut.js} +1 -1
  60. package/web/_astro/{wardley-L42UT6IY.DUFfR4J1.js → wardley-L42UT6IY.DLG5pKRN.js} +1 -1
  61. package/web/_astro/{wardleyDiagram-YWT4CUSO.BgE4haqE.js → wardleyDiagram-YWT4CUSO.CnYrM4tH.js} +1 -1
  62. package/web/_astro/{xychartDiagram-2RQKCTM6.BnitKCz8.js → xychartDiagram-2RQKCTM6.kBrlce_Y.js} +1 -1
  63. package/web/index.html +2 -2
  64. package/web/_astro/BoardApp.Bwxdbc0J.js +0 -1
  65. package/web/_astro/channel.DTWaHQwD.js +0 -1
  66. package/web/_astro/index.Bg28MlvM.css +0 -1
@@ -3,63 +3,457 @@ name: Project Constitution
3
3
  doc: 99_PROJECT_CONSTITUTION
4
4
  owns: PROCESS — how the key files are maintained
5
5
  authority: authoritative-on-process
6
- version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
6
+ version: 1.3.0
7
+ created_at: {{init-date}}
8
+ updated_at: {{init-date}}
9
+ edit_rules: 99 §6.8
10
+ sync: [T7]
11
+ read_before: editing any numbered doc above
9
12
  ---
10
13
 
11
14
  # Project Constitution — How to Organize the Project
12
15
 
13
- > **This is a template.** Spur's own constitution at
14
- > [docs/99_PROJECT_CONSTITUTION.md](https://github.com/gobing-ai/spur/blob/main/docs/99_PROJECT_CONSTITUTION.md)
15
- > is the canonical version. Copy the full content there into this file for a real project, then
16
- > localize the Lessons section (§8) and the tool-binding column (§3).
17
-
18
16
  ## 1. What this is & what this is not
19
17
 
20
18
  This is the **constitution** for the project's key files: an accumulated, machine-maintained set
21
19
  of rules and lessons for running the same file structure across different projects and
22
- cooperating with multiple coding agents (Claude Code, Codex, Gemini CLI, pi, Antigravity,
23
- OpenCode, OpenClaw, ...).
20
+ cooperating with multiple coding agents (Claude Code, Codex, Gemini CLI, pi, omp, Antigravity,
21
+ OpenCode, OpenClaw, Hermes, Grok, ...).
24
22
 
25
23
  - One copy lives in every project at `docs/99_PROJECT_CONSTITUTION.md`.
26
24
  - It is **byte-identical across projects** except the Lessons sections (§8) and the tool-binding
27
25
  column (§3). When it improves in one project, propagate to the others — forks are drift.
28
26
  - It contains **zero project-specific facts** — no project command names, package names, feature
29
- states, or decisions. Project facts live in the numbered docs this file governs.
27
+ states, or decisions. Project facts live in the numbered docs this file governs. If you find a
28
+ project fact here, that itself is drift: move it to its owning doc.
29
+
30
+ This is **not** a project review summary, a technical review list, or a product-design
31
+ reflection.
32
+
33
+ Audience: humans and coding agents equally. Every rule below is written to be checkable — an
34
+ agent should be able to verify compliance mechanically, not interpret intent.
30
35
 
31
36
  ## 2. Authority model
32
37
 
38
+ Two axes that cannot collide:
39
+
33
40
  | Axis | Question | Winner |
34
41
  |------|----------|--------|
35
42
  | **Content** | What is true about the project? | Lower number wins: `00_ADR` is binding on *decisions*; `01_PRD` is authoritative on *scope*; `02`–`05` are derived |
36
43
  | **Process** | How are the key files maintained? | **This file** |
37
44
 
38
- ## 3. Doc map
45
+ They cannot conflict because this file holds no project content (§1 rule 3).
46
+
47
+ **Why this file is numbered 99, not 00:** "lower number wins" is a *content* rule, and this file
48
+ plays on the other axis. The out-of-band number is the visible signal that the constitution sits
49
+ outside the content chain — renumbering it into the chain (e.g. as `00`) would re-entangle the
50
+ two axes and force a renumber of every content doc, invalidating the dense web of cross-pointers
51
+ (`03 §12`-style references baked into append-only ADR text) for a purely aesthetic gain. Do not
52
+ renumber.
53
+
54
+ **Content conflict rule:** when two docs disagree, fix the **authoritative** doc first (with a
55
+ dated amendment if it is append-only), then the derived doc, then `AGENTS.md` — and flag the
56
+ drift in the commit message or task. Never average two conflicting statements into a third.
57
+
58
+ ## 3. Shared tools
59
+
60
+ Tools are bound by **role**; roles are permanent, bindings evolve. This table is the only
61
+ project-variable section besides Lessons — update the binding when the toolchain migrates.
62
+
63
+ | Role | Current binding | Notes |
64
+ |------|-----------------|-------|
65
+ | Spec lifecycle — tasks | _(project tool — e.g. `spur task` or a task CLI)_ | Task files are tool-owned; edit through the tool, never the Write tool |
66
+ | Spec lifecycle — features | _(project tool — e.g. `spur feature` or a feature CLI)_ | Same tool-owned rule |
67
+ | Delivery harness | _(project harness — e.g. `spur`)_ | Quality gates are self-hosted through it where possible |
68
+ | Agent-facing wrappers | per-project plugin dir (e.g. `plugins/sp/`) | **Fat Skills, thin others:** skills are the SSOT for agent-facing behavior and may be arbitrarily rich; slash commands and subagents are thin wrappers of skills (every agent supports skills; command/subagent support varies) |
69
+
70
+ ## 4. Common file layout
71
+
72
+ ### 4.1 The doc map (canonical template)
73
+
74
+ Each project's `AGENTS.md` embeds an instantiated copy of this table (§4.4). A fact lives in
75
+ **one** doc; other docs link to it, never restate it.
76
+
77
+ | Doc | Owns the question | Authority | Read / edit when |
78
+ |-----|-------------------|-----------|------------------|
79
+ | `docs/00_ADR.md` | **WHY** — which cross-cutting decision was made, and the one-line reason | **Authoritative** (wins all content) | Read before any structural change; add a dated entry before diverging from a decision |
80
+ | `docs/01_PRD.md` | **WHAT** — product vision, users, scope (in / out / deferred) | **Authoritative on scope** | Read before adding a command/feature; edit when scope changes |
81
+ | `docs/02_ROADMAP.md` | **WHEN** — phases, current vs deferred, sequencing | Derived | Read to place work in a phase; edit when phase status changes |
82
+ | `docs/03_ARCHITECTURE.md` | **HOW** — module boundaries, data flow, runtime model, invariants, rationale-in-depth | Derived (ADR wins) | Read before cross-module/seam/schema work; edit when boundaries or mechanisms change |
83
+ | `docs/04_DESIGN.md` | **SURFACE** — concrete shapes: every CLI command, flag, config key, env var, table, DTO; **index over `docs/design/<slug>.md`** (§4.5) | Derived | Read/edit when changing a command, flag, env var, or schema — same commit |
84
+ | `docs/05_FEATURES.md` | **STATUS** — feature decomposition + state (✅ done / 🔶 partial / ⏳ planned / 💤 deferred); **index over `docs/features/<id>_<slug>.md`** (§4.5) | Derived | Read to find a feature's state; edit when a feature's status changes |
85
+ | `docs/99_PROJECT_CONSTITUTION.md` | **PROCESS** — how the files above are maintained | **Authoritative on process** | Read before editing any doc above; edit per §6.8 |
86
+ | `AGENTS.md` (repo root) | **ENTRY** — how agents work in this repo: stack, commands, gates, conventions + the instantiated doc map | Derived (from 99 + 00/01/04) | Read first every session; regenerate factual blocks from code (§6.7) |
87
+
88
+ **Routing — put each fact in its owning doc, link from the rest:**
89
+
90
+ - Decision + one-line reason → `00`. Rationale/mechanism in depth → `03`.
91
+ - Scope (in/out/deferred) → `01`. Mechanism / data flow / invariants → `03`.
92
+ - Command/flag/config/schema/DTO shapes → `04`. Phase timing → `02`. Feature status → `05`.
93
+ - If you are writing *how it's built* or *why* inside `00`/`01`/`02`, it belongs in `03`/`04`.
94
+
95
+ ### 4.2 Working layers (outside the authority chain)
96
+
97
+ | Location | Purpose | Rules |
98
+ |----------|---------|-------|
99
+ | `docs/plans/YYYY-MM-DD-<topic>.md` | Dated working documents: research, triage, design discussions, decision records-in-progress | They **record**, they do not **govern**. Once concluded, immutable except dated correction sections. Decisions they reach must be promoted into `00`–`05` to take effect |
100
+ | `docs/tasks/` | Task files | Tool-owned (§3). Never edited with raw file writes |
101
+ | other `docs/` folders | Optional scratch (analysis, refactor notes, ...) | Nothing in the authority chain may depend on them |
102
+
103
+ `docs/design/` and `docs/features/` are **not** scratch — they are the satellite layers of `04` and
104
+ `05` and are governed by §4.5.
105
+
106
+ ### 4.3 Standard frontmatter (the doc's machine-readable contract)
107
+
108
+ Every numbered doc (`00`–`05`, and `99` itself) opens with YAML frontmatter carrying its doc-map
109
+ row plus bookkeeping — so an agent learns the doc's contract from the file head without loading
110
+ the doc map, and tooling can validate it:
111
+
112
+ ```yaml
113
+ ---
114
+ doc: 03_ARCHITECTURE
115
+ owns: HOW — module boundaries, data flow, runtime model, invariants
116
+ authority: derived # authoritative | authoritative-on-scope | authoritative-on-process | derived
117
+ version: 1.1.0
118
+ derived_from: [00_ADR, 01_PRD] # omit for 00
119
+ owner: <name>
120
+ updated_at: YYYY-MM-DD
121
+ read_before: cross-module, seam, or schema work
122
+ edit_rules: 99 §6.4
123
+ sync: [T1] # §5 trigger IDs that obligate touching this doc
124
+ ---
125
+ ```
126
+
127
+ Rules:
128
+
129
+ 1. The frontmatter **is** the instantiated copy of this file's §4.1 row — `owns`/`authority`
130
+ must match it verbatim in meaning; the §7 audit checks this. On mismatch, §4.1 wins.
131
+ 2. `edit_rules` points to the owning §6 subsection — rules are never restated in frontmatter
132
+ (pointers over prose, §6.0).
133
+ 3. Bump `version` (minor) on any substantive edit; always refresh `updated_at` in the same edit.
134
+ A doc whose `updated_at` predates a change it should reflect is drift — repair per §7.
135
+ 4. Frontmatter replaces the legacy bold header block (`**Version:** …` lines); a doc carrying
136
+ both is drift.
137
+ 5. Doc **bodies do not restate** their own authority or the conflict rule ("when this conflicts
138
+ with the ADR, the ADR wins") — frontmatter `authority` and §2 own that. Preamble
139
+ restatements are drift.
140
+
141
+ ### 4.4 AGENTS.md synchronization
142
+
143
+ - `AGENTS.md` is the **per-project instantiation**: the §4.1 table (instantiated), plus
144
+ project-specific stack, commands, verification gates, and conventions.
145
+ - This file is the canonical template; when §4.1 or §5 changes here, re-sync `AGENTS.md` in the
146
+ same change.
147
+ - `AGENTS.md` may **add** project facts; it may never **contradict** the numbered docs. On
148
+ contradiction, the numbered doc wins — fix `AGENTS.md`.
149
+
150
+ ### 4.5 Index + satellite docs (`04`/`05` and their folders)
151
+
152
+ Two derived docs are **index pages** over a folder of per-item **satellite** files. The index holds
153
+ the headline rows + pointers; each satellite holds one item's detail. This keeps the index readable
154
+ (loaded every session) while detail scales without bloating it.
155
+
156
+ | Index doc | Satellite folder | Satellite file name | Satellite ownership |
157
+ |-----------|------------------|---------------------|---------------------|
158
+ | `docs/04_DESIGN.md` | `docs/design/` | `docs/design/<slug>.md` | Hand-maintained derived doc (§6.5) |
159
+ | `docs/05_FEATURES.md` | `docs/features/` | `docs/features/<feature-id>_<slug>.md` | **Tool-owned** (§3 — `spur feature`/`ftree`); satellites *and* the index region are written by the tool, never by raw file writes |
160
+
161
+ Rules (both axes):
162
+
163
+ 1. **The index is the single entry point.** A reader starts at `04`/`05`; every satellite is
164
+ reachable from exactly one index row. A satellite with no index row, or an index row with no
165
+ satellite, is drift (§7 audit).
166
+ 2. **One item per satellite.** `<slug>` (design) / `<feature-id>_<slug>` (features) is the grep
167
+ anchor (§6.0 rule 6) — stable once chosen; renaming is a rename of the file *and* its index row in
168
+ the same change.
169
+ 3. **Detail lives only in the satellite; the index carries pointer + status only.** The index never
170
+ restates a satellite's body (§6.0 rule 2). For `05`, a row is `<id> <status> <name> → pointer`;
171
+ for `04`, an index row names the surface area and points at its `docs/design/<slug>.md`.
172
+ 4. **The index is regenerable for `05`** (tool-written) and **hand-curated for `04`** — but in both
173
+ cases the satellite is the source of truth and the index is derived from it. Never edit `05`'s
174
+ generated index region by hand; never let a `04` index row diverge from its satellite.
175
+ 5. **Edit order is fixed (§5 T9): detail first, then index.** Write/update the satellite, then update
176
+ the index row — in the **same change**. Updating the index before the detail exists creates a
177
+ pointer to nothing; the reverse leaves the detail unindexed. For tool-owned features, "update the
178
+ index" is running the tool's refresh (e.g. `spur feature refresh`), not a manual edit.
179
+
180
+ ## 5. Sync triggers — same-commit obligations
181
+
182
+ The root cause of stale key files is *unsynchronized success*: code ships, docs don't hear about
183
+ it. Each trigger below has a stable ID (referenced by doc frontmatter `sync:` lists, §4.3) and
184
+ names the docs that must be touched **in the same commit / same change**:
185
+
186
+ | ID | When this happens | Touch (same change) |
187
+ |----|-------------------|---------------------|
188
+ | T1 | New cross-cutting decision, or reversal of one | `00` **first** (dated entry), then `03` mechanism, `01` if scope shifts |
189
+ | T2 | A code change would contradict an existing ADR | **Stop.** Add the superseding/amending ADR entry first — never silently diverge |
190
+ | T3 | Command, flag, config key, env var, schema, or DTO added/changed | `04` + the `AGENTS.md` surface block |
191
+ | T4 | A feature ships or changes state | its `05` row; a new `01` scope row if it is new surface |
192
+ | T5 | A phase completes, reorders, or gains items | `02` (update the bullet to the *real, shipped name* of the deliverable) |
193
+ | T6 | Scope added / cut / deferred | `01`; placement in `02` |
194
+ | T7 | The doc map or process changes | this file → re-sync `AGENTS.md` (§4.4) → propagate to sibling projects |
195
+ | T8 | A multi-wave batch is planned | schedule "doc sync" as an **explicit work item** — same-commit discipline does not survive on memory alone |
196
+ | T9 | A design or feature item is added/changed | the satellite **first** (`docs/design/<slug>.md` or `docs/features/<id>_<slug>.md`), **then** its index row in `04`/`05` — same change (§4.5 rule 5) |
197
+
198
+ ## 6. Edit principles per file
199
+
200
+ ### 6.0 Writing rules (all key files)
201
+
202
+ Token economy is a design goal: these files are read by LLM agents at session start, every
203
+ session, across every project — a redundant sentence is paid for thousands of times. Precise
204
+ **and** concise; precision wins when they conflict.
205
+
206
+ 1. Declarative, information-dense sentences. No filler, no marketing adjectives, no hedging, no
207
+ narrative buildup.
208
+ 2. A fact lives once — link or point (`see 03 §12`) instead of restating, both in-file and
209
+ cross-file. Restatement is the largest token sink in a doc system, bigger than any tone rule.
210
+ 3. Tables for enumerable facts; prose only where reasoning is needed.
211
+ 4. Front-load: rule first, elaboration after — readers (human or agent) may only take the head.
212
+ 5. Define a term once, then reuse it verbatim. Synonyms read as new concepts to a machine.
213
+ 6. Headings and IDs (`ADR-NNN`, `T1`–`T8`, `§6.x`, feature rows) are grep targets and
214
+ cross-reference anchors — never rename casually.
215
+ 7. **Concise never beats correct.** If brevity creates ambiguity, add the missing words: tokens
216
+ saved in reading are lost many times over in a misexecuted run.
217
+
218
+ These rules are stated once, here. Per-file sections below and doc frontmatter inherit them via
219
+ pointer — restating them per file would violate rule 2.
220
+
221
+ ### 6.1 `docs/00_ADR.md`
222
+
223
+ Entry template:
224
+
225
+ ```markdown
226
+ ## ADR-NNN: <Decision title, outcome-shaped>
227
+
228
+ **Status:** Accepted | Accepted (design) | Superseded by ADR-MMM | Skipped · **Date:** YYYY-MM-DD
229
+
230
+ **Decision.** <What was decided — the smallest complete statement of the choice.>
231
+
232
+ **Why.** <One line. The single strongest reason.>
233
+
234
+ **Detail:** <pointer into 03/04/plans — depth never lives here.>
235
+ ```
236
+
237
+ 1. **One decision per entry.** If a draft contains a principle *and* a deferred design *and* a
238
+ mechanism choice *and* implementation tips — split it: decision(s) here, mechanism in `03`,
239
+ shapes in `04`, tips nowhere (they are implementation guidance, not decisions).
240
+ 2. **ADR = decision + one-line reason.** No Zod patterns, no lock details, no code idioms.
241
+ 3. **Append-only.** Never renumber, never delete, never rewrite history. Corrections are dated
242
+ `**Amendment (YYYY-MM-DD)**` blocks inside the entry; reversals are **new entries** that name
243
+ what they supersede, while the old entry's Status becomes `Superseded by ADR-MMM`.
244
+ 4. **Numbering:** next free integer, one sequence per repo. A burned/skipped number gets a stub
245
+ entry (`Status: Skipped`) so the gap is audit-clean and never reused.
246
+ 5. **`Accepted (design)`** means decided but not built — readers must be able to tell decided
247
+ from shipped.
248
+ 6. **Before any code that contradicts an ADR:** the superseding entry lands first (§5 row 2).
249
+ 7. **Retrofit rule:** the entry template binds **new entries and amendments only**. Historical
250
+ entries are never restructured to match it — append-only beats stylistic consistency. The
251
+ non-entry preamble is normal editable text.
252
+ 8. **Amendments record the decision delta.** An `**Amendment**` block records *what changed about the
253
+ decision* — the new choice and its one-line reason — plus a `Detail:` pointer for mechanism.
254
+ Implementation file paths, detailed semantics, and multi-paragraph rationale belong in `03`/`04`,
255
+ not in the amendment body. If an amendment would carry more than a few lines of non-decision text,
256
+ the mechanism has leaked in; link it instead of inlining it.
257
+
258
+ ### 6.2 `docs/01_PRD.md`
259
+
260
+ 1. Owns vision, users, principles, scope. **No mechanism** (→ `03`), **no timing** (→ `02`),
261
+ **no shapes** (→ `04`).
262
+ 2. **Every shipped surface has a scope row.** When a command/capability ships, its row enters
263
+ the in-scope table in the same change — shipped-but-unlisted is the most common drift.
264
+ 3. Scope states are explicit: *in (committed)* / *supporting* / *deferred (needs design
265
+ reconfirmation)* / *out of scope*. A deferred item carries the condition that would
266
+ reactivate it.
267
+ 4. Surface beyond the committed set is **not ported/built speculatively** — re-confirm the need
268
+ first and record the evidence pointer (a dated plans doc, usage data) in the entry that
269
+ admits it.
270
+ 5. **Scope tables carry membership only** — no delivery-status columns (`05` owns status; a
271
+ status column in `01` is a guaranteed drift magnet). Likewise, quantitative gate values
272
+ (coverage thresholds, etc.) live with their enforcement config — point to the gate, never
273
+ restate the numbers.
274
+
275
+ ### 6.3 `docs/02_ROADMAP.md`
276
+
277
+ 1. Derived: it may **sequence** facts from `00`/`01`/`05` but never introduce new ones.
278
+ 2. Every phase has a goal sentence, checkbox items, and an explicit **Exit:** criterion.
279
+ 3. Markers: `[x]` done · `[~]` partial · `[ ]` pending. `[x]`/`[~]` carry a one-line evidence
280
+ note (what shipped, where).
281
+ 4. When a deliverable lands under a different name than planned, rewrite the bullet to the real
282
+ name — a roadmap that tracks dead names reads as undelivered work.
283
+ 5. Phases gate on the previous one. Insert sub-phases (`1.5`) rather than renumbering existing
284
+ ones.
285
+
286
+ ### 6.4 `docs/03_ARCHITECTURE.md`
287
+
288
+ 1. Describes the **current** architecture. Future/accepted designs are allowed only in sections
289
+ explicitly titled `(accepted design — ADR-NNN; not yet built)`.
290
+ 2. Owns module boundaries, data flow, runtime model, invariants, and rationale-in-depth. Not
291
+ schemas/signatures (code and `04`), not decisions (`00`).
292
+ 3. Write invariants as **enforceable statements** — phrased so a constraint rule or a reviewer
293
+ can check them mechanically.
294
+ 4. When a migration replaces a mechanism (parser, dispatcher, bootstrap), update the module
295
+ descriptions in the same change — stale module lists survive multiple releases unnoticed.
296
+ 5. On conflict with `00`: the ADR wins; fix here and flag.
297
+
298
+ ### 6.5 `docs/04_DESIGN.md` + `docs/design/<slug>.md`
299
+
300
+ `04` is the **index page** over the `docs/design/` satellites (§4.5). The index carries the surface
301
+ map + pointers; each `docs/design/<slug>.md` holds one surface area's detailed design.
302
+
303
+ 1. **Same-commit rule:** any change to a command, flag, config key, env var, table, or DTO
304
+ updates `04` (and its satellite) in that commit (§5 T3/T9). In batch planning, doc sync is an
305
+ explicit scheduled item.
306
+ 2. **Detail-first edit order (§4.5 rule 5 / T9):** write or update the `docs/design/<slug>.md`
307
+ satellite first, then update its `04` index row — never the reverse. A new surface area gets a
308
+ new satellite + a new index row in the same change.
309
+ 3. Prefer **generated** artifacts over hand-maintained ones (e.g. OpenAPI from the contract);
310
+ never hand-write what can be derived — and never let a derivable artifact be edited by hand.
311
+ 4. Shapes only. Rationale lives in `00`/`03`. **Behavioral notes are shapes** ("resolving zero
312
+ rules exits 1" — keep); justifications are not ("...because a silent gate is the worst
313
+ failure mode" — cut, or point to `00`/`03`). This applies to satellites too — they hold
314
+ *detailed shapes*, not rationale.
315
+ 5. Command signatures are **transcribed from the code registrations**, never from memory or from
316
+ an older doc revision — a signature is a factual block in the §6.7 sense.
317
+ 6. The index never restates a satellite's body (§6.0 rule 2): an `04` row names the surface area,
318
+ its status, and points at `docs/design/<slug>.md`. `<slug>` is a stable grep anchor (§6.0 rule 6).
319
+
320
+ ### 6.6 `docs/05_FEATURES.md` + `docs/features/<feature-id>_<slug>.md`
321
+
322
+ `05` is the **index page** over the `docs/features/` satellites (§4.5). Both the satellites and `05`'s
323
+ generated index region are **tool-owned** (§3 — `spur feature`/`ftree`): edit through the tool, never
324
+ with raw file writes.
325
+
326
+ 1. One index row per deliverable, each with a concrete **acceptance** check, status from the legend
327
+ (✅ done · 🔶 partial · ⏳ planned · 💤 deferred), and a pointer to its
328
+ `docs/features/<feature-id>_<slug>.md` satellite.
329
+ 2. The satellite + its index row change in the **same change** that ships or re-scopes the feature
330
+ (§5 T4/T9).
331
+ 3. **Detail-first edit order (§4.5 rule 5 / T9):** update the feature satellite first (via the tool),
332
+ then refresh the index (e.g. `spur feature refresh`) — never hand-edit the generated index region,
333
+ and never update the index ahead of the detail.
334
+ 4. **Never trust a row you have not verified.** Before citing or building on a status, check it
335
+ against code — status rows rot silently in both directions (done-but-⏳ and ⏳-but-claimed).
336
+ 5. `05` keeps headline rows + pointers; the full decomposition lives in the satellite files.
337
+ `<feature-id>` is the stable grep anchor (§6.0 rule 6); renaming is a tool operation, not a raw
338
+ edit.
339
+
340
+ ### 6.7 `AGENTS.md`
341
+
342
+ 1. Factual blocks that mirror code — the command surface, the workspace layout, tool versions —
343
+ are **regenerated from code**, never edited from memory. Verify with the actual registrations
344
+ (e.g. list the CLI's registered nouns/verbs) before writing the block.
345
+ 2. Keep it lean: link to the owning doc instead of restating its facts. `AGENTS.md` repeats only
346
+ what an agent needs in the first 30 seconds of a session.
347
+ 3. Surfaces that are decided-but-unbuilt are flagged as planned with their ADR pointer, and
348
+ marked "do not invoke as if they exist".
349
+ 4. Re-synced whenever this file changes the map or process (§4.4).
350
+
351
+ ### 6.8 This file (`99`)
352
+
353
+ 1. **No project facts** — ever (§1). Tool bindings (§3) and Lessons (§8) are the only
354
+ project-variable content.
355
+ 2. Structure and principles change only on operator request; Lessons sections are
356
+ machine-appendable per the §8 protocol without asking.
357
+ 3. When this file improves in one project, **propagate the improvement to sibling projects** —
358
+ it is one constitution with N copies, not N constitutions.
359
+
360
+ ## 7. Drift control
361
+
362
+ **Drift** = reality (code, shipped behavior) disagreeing with what a key file says, or two key
363
+ files disagreeing with each other.
364
+
365
+ **Repair protocol** (always this order):
366
+
367
+ 1. Fix the **authoritative** doc — for append-only files, by dated amendment, never rewriting.
368
+ 2. Then the derived docs that restate or sequence it.
369
+ 3. Then `AGENTS.md`.
370
+ 4. Flag what drifted and why in the commit message / task — a silent fix hides the systemic
371
+ cause.
372
+
373
+ **Audit cadence:** at every phase exit, and before designing any large batch, run the drift
374
+ audit:
375
+
376
+ - [ ] List the real CLI/tool surface from code; diff against `AGENTS.md`'s surface block and
377
+ `00`'s committed-surface entries.
378
+ - [ ] For every `05` row marked ✅/🔶, spot-check the acceptance against code; for every ⏳, check
379
+ it didn't quietly ship.
380
+ - [ ] For every shipped surface, confirm a `01` scope row exists.
381
+ - [ ] Check `02`'s current phase bullets name things that actually exist (no dead names).
382
+ - [ ] Check `03`'s module descriptions against the real file tree of each app/package.
383
+ - [ ] Confirm `04` covers every command/flag/config/schema that exists.
384
+ - [ ] For `04`/`05` (§4.5): every index row points to an existing satellite, and every satellite
385
+ (`docs/design/<slug>.md`, `docs/features/<id>_<slug>.md`) has exactly one index row — no orphan
386
+ satellites, no dangling pointers.
387
+ - [ ] Confirm `AGENTS.md`'s doc map matches §4.1 of this file.
388
+ - [ ] Confirm each doc's frontmatter matches its §4.1 row and its `updated_at` is plausible
389
+ against recent commits (§4.3).
390
+
391
+ Findings are repaired via the protocol above, and anything systemic becomes a Lesson (§8) — or,
392
+ if it recurs, a new rule in §6.
393
+
394
+ ## 8. Lessons learned per file
395
+
396
+ **Append protocol (machine-maintained):**
397
+
398
+ - Format: `- [YYYY-MM-DD] <project>: <lesson — what went wrong / what to do instead>`
399
+ - Threshold is **low** — when in doubt, append. Check for an existing equivalent first; bump its
400
+ date instead of duplicating.
401
+ - **Promotion rule:** a lesson that recurs or hardens into practice is promoted into a §6 rule
402
+ (or a §5 trigger) and removed from this section. Lessons are the inbox; §5/§6 are the law.
403
+ Promotion is the only sanctioned deletion.
404
+ - Lessons carry project provenance because this file is copied across projects — a lesson from
405
+ one project is a warning, not yet a law, for the others.
406
+
407
+ ### Lessons for `docs/00_ADR.md`
408
+
409
+ _(empty — add lessons as the project evolves)_
410
+
411
+ ### Lessons for `docs/01_PRD.md`
412
+
413
+ _(empty — add lessons as the project evolves)_
414
+
415
+ ### Lessons for `docs/02_ROADMAP.md`
416
+
417
+ _(empty — add lessons as the project evolves)_
418
+
419
+ ### Lessons for `docs/03_ARCHITECTURE.md`
420
+
421
+ _(empty — add lessons as the project evolves)_
422
+
423
+ ### Lessons for `docs/04_DESIGN.md`
424
+
425
+ _(empty — add lessons as the project evolves)_
426
+
427
+ ### Lessons for `docs/05_FEATURES.md`
428
+
429
+ _(empty — add lessons as the project evolves)_
430
+
431
+ ### Lessons for `AGENTS.md`
39
432
 
40
- | Doc | Owns the question | Authority |
41
- |-----|-------------------|-----------|
42
- | `00_ADR.md` | **WHY** — decisions + one-line reason | Authoritative (wins all) |
43
- | `01_PRD.md` | **WHAT** — product vision, scope | Authoritative on scope |
44
- | `02_ROADMAP.md` | **WHEN** — phases, sequencing | Derived |
45
- | `03_ARCHITECTURE.md` | **HOW** — module boundaries, data flow | Derived |
46
- | `04_DESIGN.md` | **SURFACE** — commands, flags, schemas | Derived |
47
- | `05_FEATURES.md` | **STATUS** — feature decomposition + state | Derived |
48
- | `99_PROJECT_CONSTITUTION.md` | **PROCESS** — how files are maintained | Authoritative on process |
433
+ _(empty add lessons as the project evolves)_
49
434
 
50
- ## 4. Sync triggers
435
+ ### Lessons for this file (`99`)
51
436
 
52
- When a change touches one of these, the listed doc MUST be updated in the **same commit**:
437
+ _(empty add lessons as the project evolves)_
53
438
 
54
- | ID | Trigger | Doc(s) |
55
- |----|---------|--------|
56
- | T1 | New cross-cutting decision (entry = decision + one-line reason; amendment = decision delta only — mechanism goes in `03`/`04`, not the amendment) | `00` first, then `03` mechanism |
57
- | T3 | Command/flag/config/schema/DTO added/changed | `04` + `AGENTS.md` |
58
- | T4 | Feature ships or changes state | `05` row |
59
- | T6 | Scope added / cut / deferred | `01` |
439
+ ## 9. Bootstrapping a new project
60
440
 
61
- ## 5. Lessons
441
+ Checklist to instantiate this structure in a fresh repo:
62
442
 
63
- | Date | Lesson |
64
- |------|--------|
65
- | 1970-01-01 | _(empty add lessons as the project evolves)_ |
443
+ 1. Copy this file verbatim to `docs/99_PROJECT_CONSTITUTION.md`; empty the §8 lessons of
444
+ other projects' entries or keep them as inherited warnings (recommended: keep).
445
+ 2. Update §3 bindings if the new project's toolchain differs.
446
+ 3. Create `docs/00_ADR.md` with the §4.3 frontmatter and `ADR-001` recording the founding
447
+ decision (stack, structure, the why).
448
+ 4. Create `docs/01_PRD.md`: vision paragraph, users, principles table, scope tables (in /
449
+ supporting / deferred / out).
450
+ 5. Create `docs/02_ROADMAP.md` with Phase 0 and its exit criterion.
451
+ 6. Create `docs/03_ARCHITECTURE.md`: topology, dependency boundary, runtime model — current
452
+ state only.
453
+ 7. Create `docs/04_DESIGN.md` (may start near-empty) and `docs/05_FEATURES.md` (legend + first
454
+ rows).
455
+ 8. Create root `AGENTS.md`: instantiated §4.1 doc map, stack/layout, commands, verification
456
+ gate, conventions. Symlink `CLAUDE.md` (and equivalents) to it.
457
+ 9. Wire the §3 tools (spec lifecycle, harness) per their own docs.
458
+ 10. First-session rule for any agent: read `AGENTS.md` → this file → `00`/`01` before touching
459
+ anything.
@@ -164,12 +164,16 @@ states:
164
164
  description: >
165
165
  Record pipeline results into the task file via `spur task record` —
166
166
  Testing/Review from the verdict, Solution backfilled from git diff as a
167
- safety net, optional transition to testing. A single verb replaces the
168
- previous ~50 lines of embedded shell (0108; ADR-022).
167
+ safety net, optional transition to testing. Post-record step conditionally syncs
168
+ feature status if `feature_id` is present, or appends an orphan link proposal
169
+ to the run report if absent (task 0328 / ADR-0322).
169
170
  onEnter:
170
171
  - kind: shell
171
172
  options:
172
173
  command: "${vars.spurBin} task record ${vars.wbs} --solution-from-diff --transition testing"
174
+ - kind: shell
175
+ options:
176
+ command: 'FID=$(${vars.spurBin} task show ${vars.wbs} --json 2>/dev/null | jq -r ".feature_id // .frontmatter.feature_id // empty"); if [ -n "$FID" ]; then ${vars.spurBin} feature sync "$FID" --json; else echo "Orphan task ${vars.wbs} — no feature_id linked; proposal: consider linking to a parent feature." >> .spur/run/${vars.wbs}-report.txt; fi'
173
177
 
174
178
  - id: done
175
179
  description: >
@@ -117,16 +117,13 @@ states:
117
117
 
118
118
  - id: feature-transition
119
119
  description: >
120
- If vars.feature is set, advance the feature through the legal forward path of
121
- the feature-lifecycle FSM via `spur feature advance` (task 0180 F9c / ADR-029).
122
- The verb walks backlog active verifying done idempotently, verifying the
123
- observed status after every hop, and returns a per-hop trail. Replaces the prior
124
- ~20-line inline shell ladder; the verb now owns the multi-hop walk + legal-edge
125
- enforcement. Task statuses are NOT mutated.
120
+ If vars.feature is set, derive and sync feature status with linked task states via
121
+ `spur feature sync` (task 0328 / ADR-0322).
122
+ Replaces prior unconditional `spur feature advance` with conservative status sync.
126
123
  onEnter:
127
124
  - kind: shell
128
125
  options:
129
- command: '${vars.spurBin} feature advance ${vars.feature} --json'
126
+ command: '${vars.spurBin} feature sync ${vars.feature} --json'
130
127
 
131
128
  - id: branch-cleanup
132
129
  description: >
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/spur",
3
- "version": "0.3.20",
3
+ "version": "0.3.23",
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",
@@ -126,6 +126,11 @@
126
126
  "type": "string",
127
127
  "minLength": 1,
128
128
  "description": "Opaque model override passed straight to the agent (e.g. zai//glm-5.2). Applied only when the user passes no explicit --model."
129
+ },
130
+ "tier": {
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."
129
134
  }
130
135
  }
131
136
  }
@@ -257,6 +262,14 @@
257
262
  "active": {
258
263
  "type": "string",
259
264
  "description": "Default folder for `spur task create`. Default: docs/tasks."
265
+ },
266
+ "severity": {
267
+ "type": "object",
268
+ "description": "Rule severity overrides map by code (error | warning | off).",
269
+ "additionalProperties": {
270
+ "type": "string",
271
+ "enum": ["error", "warning", "off"]
272
+ }
260
273
  }
261
274
  }
262
275
  },