@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
@@ -0,0 +1,31 @@
1
+ $schema: "@gobing-ai/spur/schemas/rule-file.schema.json"
2
+ # Forbid getByLabelText queries on button accessible names in web component tests.
3
+ #
4
+ # WHY: HTML `<button>` elements are non-labellable per WHATWG HTML spec. In DOM Testing
5
+ # Library, `getByLabelText` queries elements associated with `<label>` tags. When used to
6
+ # query a `<button>` with an `aria-label` attribute, it works when happy-dom DOM state is
7
+ # fresh, but throws `TestingLibraryElementError: element associated with this label is non-labellable`
8
+ # when running in full multi-file test suites on CI (e.g. Linux runners).
9
+ # Real incident: CI-only failure in apps/web/tests/modules/task-kanban/components.test.tsx on 2026-07-24.
10
+ #
11
+ # FIX: Use `getByRole('button', { name: '...' })` or `getByRole('button', { name: /.../ })`,
12
+ # which queries the W3C accessible name provided by `aria-label`.
13
+ include:
14
+ - "apps/web/tests/**/*.test.ts"
15
+ - "apps/web/tests/**/*.test.tsx"
16
+ exclude:
17
+ - "**/node_modules/**"
18
+ - "**/dist/**"
19
+
20
+ rules:
21
+ - id: prefer-accessible-role-for-button-queries
22
+ description: >
23
+ Do not query button accessible names with `getByLabelText` in web React tests.
24
+ `<button>` elements are non-labellable per WHATWG spec, causing timing-dependent
25
+ CI failures when tests run sequentially in a single process.
26
+ Use `getByRole('button', { name: ... })` instead.
27
+ severity: warning
28
+ evaluator:
29
+ type: rg
30
+ config:
31
+ pattern: "getByLabelText\\(['\"]Sort "
@@ -4,29 +4,39 @@ doc: 00_ADR
4
4
  owns: WHY — which cross-cutting decision was made, and the one-line reason
5
5
  authority: authoritative
6
6
  version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
7
+ owner: _(project owner)_
8
+ updated_at: {{init-date}}
9
+ read_before: any structural change
10
+ edit_rules: 99 §6.1
11
+ sync: [T1, T2]
9
12
  ---
10
13
 
11
14
  # Architecture Decision Records
12
15
 
13
- > Authoritative on **decisions**. Lower number wins — this doc overrides all others on decisions.
14
- > Each entry is append-only; supersession is by a new dated entry, never by editing an old one.
15
- > Only real cross-cutting decisions belong here — not implementation notes, not feature status, not
16
- > how-to guidance. Entries that grow past decision + reason are carrying mechanism that belongs in
17
- > `03`/`04`; link it instead of inlining it.
16
+ ## ADR-001 Adopt this doc structure
18
17
 
19
- ## ADR-001 (example) Adopt this doc structure
18
+ **Status:** Accepted · **Date:** {{init-date}}
20
19
 
21
- - **Date:** 1970-01-01
22
- - **Status:** accepted
23
- - **Context:** Project needs a single source of truth for decisions and scope.
24
- - **Decision:** Adopt the Spur doc structure (`00`–`05` + `99` constitution).
25
- - **Reason:** Separates WHY (`00`) from WHAT (`01`) from HOW (`03`/`04`) — one fact, one home.
20
+ **Decision.** Adopt the Spur doc structure (`00`–`05` + `99` constitution).
21
+
22
+ **Why.** Separates WHY (`00`) from WHAT (`01`) from HOW (`03`/`04`) one fact, one home.
23
+
24
+ **Detail:** `docs/99_PROJECT_CONSTITUTION.md` §4.1.
26
25
 
27
26
  <!--
28
- Add new ADRs here. Copy the entry shape above (Date, Status, Context, Decision, Reason).
27
+ Add new ADRs here. Entry shape (per 99 §6.1):
28
+
29
+ ## ADR-NNN: <Decision title, outcome-shaped>
30
+
31
+ **Status:** Accepted | Accepted (design) | Superseded by ADR-MMM | Skipped · **Date:** YYYY-MM-DD
32
+
33
+ **Decision.** <What was decided — the smallest complete statement of the choice.>
34
+
35
+ **Why.** <One line. The single strongest reason.>
36
+
37
+ **Detail:** <pointer into 03/04/plans — depth never lives here.>
38
+
29
39
  A decision that reverses a prior ADR adds a new entry that says "supersedes ADR-NNN".
30
40
  An Amendment records the decision delta + one-line reason — not the mechanism. Implementation
31
41
  paths, detailed semantics, and multi-paragraph rationale belong in 03/04, not in the amendment.
32
- -->
42
+ -->
@@ -4,14 +4,15 @@ doc: 01_PRD
4
4
  owns: WHAT — product vision, users, scope (in / out / deferred)
5
5
  authority: authoritative-on-scope
6
6
  version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
7
+ owner: _(project owner)_
8
+ updated_at: {{init-date}}
9
+ read_before: adding a command or feature
10
+ edit_rules: 99 §6.2
11
+ sync: [T1, T4, T6]
9
12
  ---
10
13
 
11
14
  # Product Requirements Document
12
15
 
13
- > Authoritative on **scope**. In-scope vs out-of-scope vs deferred lives here and nowhere else.
14
-
15
16
  ## 1. Vision
16
17
 
17
18
  _(One sentence: what this product is and who it is for.)_
@@ -28,10 +29,14 @@ _(One sentence: what this product is and who it is for.)_
28
29
 
29
30
  - _(capability the product delivers)_
30
31
 
31
- ### Out of scope
32
+ ### Supporting
32
33
 
33
- - _(explicitly excluded capability prevents scope creep)_
34
+ - _(capability that enables an in-scope item but is not user-facing)_
34
35
 
35
36
  ### Deferred
36
37
 
37
- - _(capability intentionally postponed — not a commitment)_
38
+ - _(capability intentionally postponed — not a commitment; carry the condition that would reactivate it)_
39
+
40
+ ### Out of scope
41
+
42
+ - _(explicitly excluded capability — prevents scope creep)_
@@ -4,19 +4,27 @@ doc: 02_ROADMAP
4
4
  owns: WHEN — phases, current vs deferred, sequencing
5
5
  authority: derived
6
6
  version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
7
+ derived_from: [00_ADR, 01_PRD]
8
+ owner: _(project owner)_
9
+ updated_at: {{init-date}}
10
+ read_before: placing work in a phase
11
+ edit_rules: 99 §6.3
12
+ sync: [T5]
9
13
  ---
10
14
 
11
15
  # Roadmap
12
16
 
13
- > Derived from `01_PRD` (scope) and `00_ADR` (decisions). Edit when phase status changes.
14
-
15
17
  ## Phases
16
18
 
17
- | Phase | Status | Items |
18
- |-------|--------|-------|
19
- | Phase 0 — Foundation | ✅ done | _(list the real, shipped deliverable names)_ |
20
- | Phase 1 — _(name)_ | ⏳ planned | _(items)_ |
19
+ | Phase | Status | Items | Exit criterion |
20
+ |-------|--------|-------|----------------|
21
+ | Phase 0 — Foundation | ✅ done | _(list the real, shipped deliverable names)_ | _(what must be true to exit)_ |
22
+ | Phase 1 — _(name)_ | ⏳ planned | _(items)_ | _(what must be true to exit)_ |
21
23
 
22
24
  **Status legend:** ✅ done · 🔶 partial · ⏳ planned · 💤 deferred
25
+
26
+ <!--
27
+ Markers: [x] done · [~] partial · [ ] pending. [x]/[~] carry a one-line evidence note.
28
+ When a deliverable lands under a different name than planned, rewrite the bullet to the real name.
29
+ Insert sub-phases (1.5) rather than renumbering existing ones.
30
+ -->
@@ -4,14 +4,16 @@ doc: 03_ARCHITECTURE
4
4
  owns: HOW — module boundaries, data flow, runtime model, invariants
5
5
  authority: derived
6
6
  version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
7
+ derived_from: [00_ADR, 01_PRD]
8
+ owner: _(project owner)_
9
+ updated_at: {{init-date}}
10
+ read_before: cross-module, seam, or schema work
11
+ edit_rules: 99 §6.4
12
+ sync: [T1]
9
13
  ---
10
14
 
11
15
  # Architecture
12
16
 
13
- > Derived (ADR wins). Read before cross-module/seam/schema work; edit when boundaries or mechanisms change.
14
-
15
17
  ## 1. Module map
16
18
 
17
19
  ```
@@ -24,4 +26,9 @@ _(Describe the primary data path: input → processing → output. Name the seam
24
26
 
25
27
  ## 3. Invariants
26
28
 
27
- - _(state or property that always holds — the thing tests should protect)_
29
+ - _(state or property that always holds — phrased so a constraint rule or reviewer can check it mechanically)_
30
+
31
+ <!--
32
+ Describes the CURRENT architecture only. Future/accepted designs go in sections explicitly
33
+ titled "(accepted design — ADR-NNN; not yet built)". On conflict with 00, the ADR wins; fix here.
34
+ -->
@@ -1,17 +1,29 @@
1
1
  ---
2
2
  name: Design
3
3
  doc: 04_DESIGN
4
- owns: SURFACE — concrete shapes: every CLI command, flag, config key, env var, table, DTO
4
+ owns: SURFACE — concrete shapes: every CLI command, flag, config key, env var, table, DTO; index over docs/design/
5
5
  authority: derived
6
6
  version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
7
+ derived_from: [00_ADR, 01_PRD]
8
+ owner: _(project owner)_
9
+ updated_at: {{init-date}}
10
+ read_before: changing a command, flag, env var, or schema
11
+ edit_rules: 99 §6.5
12
+ sync: [T3, T9]
9
13
  ---
10
14
 
11
15
  # Design
12
16
 
13
- > Derived. Concrete shapes every command, flag, config key, env var, schema, and DTO. Edit when
14
- > a surface changes.
17
+ > **Index page** over `docs/design/` satellites (99 §4.5). Each surface area gets a
18
+ > `docs/design/<slug>.md` satellite; this index carries the surface map + pointers.
19
+ > Edit order: satellite first, then index row — same change (T9).
20
+
21
+ ## UI/UX boundary
22
+
23
+ Repository-root `DESIGN.md` owns all UI/UX design, including visual language, design tokens,
24
+ components, layout, interaction, accessibility, and responsive behavior. Read and update it for UI
25
+ work; keep this document focused on non-UI surface design. If `DESIGN.md` is absent, follow the
26
+ project's established UI conventions rather than adding UI guidance here.
15
27
 
16
28
  ## 1. CLI commands
17
29
 
@@ -19,12 +31,18 @@ updated_at: 1970-01-01T00:00:00.000Z
19
31
  _(command) <positional> [--flag <value>] [--json]
20
32
  ```
21
33
 
22
- | Command | Description |
23
- |---------|-------------|
24
- | _(command)_ | _(one-line description)_ |
34
+ | Command | Description | Design doc |
35
+ |---------|-------------|------------|
36
+ | _(command)_ | _(one-line description)_ | `docs/design/_(slug)_.md` |
25
37
 
26
38
  ## 2. Configuration keys
27
39
 
28
40
  | Key | Type | Default | Description |
29
41
  |-----|------|---------|-------------|
30
42
  | _(key)_ | _(type)_ | _(default)_ | _(description)_ |
43
+
44
+ <!--
45
+ Shapes only — rationale lives in 00/03. Behavioral notes are shapes ("resolving zero rules exits 1"
46
+ — keep); justifications are not ("...because a silent gate is the worst failure mode" — cut).
47
+ Transcribe command signatures from the code registrations, never from memory.
48
+ -->
@@ -1,16 +1,22 @@
1
1
  ---
2
2
  name: Features
3
3
  doc: 05_FEATURES
4
- owns: STATUS — feature decomposition + state
4
+ owns: STATUS — feature decomposition + state; index over docs/features/
5
5
  authority: derived
6
6
  version: 1.0.0
7
- created_at: 1970-01-01T00:00:00.000Z
8
- updated_at: 1970-01-01T00:00:00.000Z
7
+ derived_from: [00_ADR, 01_PRD]
8
+ owner: _(project owner)_
9
+ updated_at: {{init-date}}
10
+ read_before: finding a feature's state
11
+ edit_rules: 99 §6.6
12
+ sync: [T4, T9]
9
13
  ---
10
14
 
11
15
  # Features
12
16
 
13
- > Derived. Feature status roll-up. Edit when a feature's status changes.
17
+ > **Index page** over `docs/features/` satellites (99 §4.5). Both the satellites and this index's
18
+ > generated region are **tool-owned** (e.g. `spur feature`/`ftree`); edit through the tool, never
19
+ > with raw file writes. Edit order: satellite first, then refresh index (T9).
14
20
 
15
21
  ## Status legend
16
22
 
@@ -18,6 +24,11 @@ updated_at: 1970-01-01T00:00:00.000Z
18
24
 
19
25
  ## Feature tree
20
26
 
21
- | ID | Feature | Status | Parent | Notes |
22
- |----|---------|--------|--------|-------|
23
- | F1 | _(root feature)_ | ⏳ planned | — | _(one-line scope)_ |
27
+ | ID | Feature | Status | Parent | Notes | Satellite |
28
+ |----|---------|--------|--------|-------|-----------|
29
+ | F1 | _(root feature)_ | ⏳ planned | — | _(one-line scope)_ | `docs/features/F1__(slug)_.md` |
30
+
31
+ <!--
32
+ Never trust a row you have not verified — check status against code before citing or building on it.
33
+ One item per satellite; <feature-id> is the stable grep anchor. Renaming is a tool operation.
34
+ -->