@naswerks/engineering-loop 0.1.0 → 0.2.0

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.
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "name": "engineering-loop",
3
- "owner": { "name": "naswerks" },
3
+ "owner": {
4
+ "name": "naswerks"
5
+ },
4
6
  "metadata": {
5
7
  "description": "The engineering loop as a Claude Code plugin: docs-* (knowledge), spec-* (execution), init."
6
8
  },
@@ -8,8 +10,12 @@
8
10
  {
9
11
  "name": "naswerks",
10
12
  "description": "The engineering loop: docs-* knowledge loop, spec-* execution loop, and init for a fresh repository.",
11
- "version": "0.1.0",
12
- "source": "./"
13
+ "version": "0.2.0",
14
+ "source": {
15
+ "source": "npm",
16
+ "package": "@naswerks/engineering-loop",
17
+ "version": "0.2.0"
18
+ }
13
19
  }
14
20
  ]
15
21
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naswerks",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "The engineering loop: a knowledge loop (docs-*) and an execution loop (spec-*) for repositories driven by hosted agent sessions, plus init to make a repository ready for both.",
5
5
  "author": { "name": "naswerks" },
6
6
  "license": "MIT",
package/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ version is the one in `package.json` and `.claude-plugin/plugin.json`, which mus
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.2.0] - 2026-09-20
9
+
10
+ ### Changed
11
+
12
+ - The reading floor every seat reads is four documents plus the `_meta` trio: `patterns/code-organization.md`
13
+ (was `vertical-slice-anatomy.md` — it describes the layout a repository actually has and presumes no
14
+ pattern), `backend-patterns.md`, `frontend-patterns.md`, `testing.md`. `codegen.md` leaves the floor.
15
+ - The standard set a role reads on top of the floor is seven documents, each drafted by `init` only when the
16
+ repository shows the concern and each carrying a `doc-index.md` row either way: `codegen`,
17
+ `state-management`, `ui-style-guide`, `design-tokens` (the token authority, split out of the style guide),
18
+ `long-running-workflows` (split out of `background-work`), `realtime-events`, `background-work`.
19
+ `spec-child` names them by path and says an absent one has a row saying `not detected`.
20
+ - `docs/_meta/doc-index.md` § Role reading lists is the repository's reserved space: `Doc | what it gives
21
+ the seat | backend | frontend | mixed`. `spec-parent` copies a role's rows into every seed's `EXTRA DOCS`
22
+ line, so a team's own documents reach a seat as paths in its prompt rather than as an index to consult.
23
+ - `spec-pipeline` sizes every spec for one session before context compacts, with no target count;
24
+ `engineering-loop.md` says the same in place of a session range.
25
+ - `init doctor` fails a standard document that is absent without its `not detected` row, and any
26
+ Role-reading-lists row whose path does not exist.
27
+
28
+ ### Added
29
+
30
+ - Templates `code-organization.md`, `design-tokens.md`, `long-running-workflows.md`.
31
+
32
+ ### Removed
33
+
34
+ - The snapshot-stub pattern for the standard names: a repository names its documents with the standard
35
+ names directly; no pointer documents.
36
+
8
37
  ## [0.1.0] - 2026-09-20
9
38
 
10
39
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naswerks/engineering-loop",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "The engineering loop as a Claude Code plugin: a knowledge loop (docs-*), an execution loop (spec-*), and init for a fresh repository. The package root is the plugin root.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,4 +1,4 @@
1
- <!-- naswerks-loop: version=0.1.0 -->
1
+ <!-- naswerks-loop: version=0.2.0 -->
2
2
  # Docs Workflow
3
3
 
4
4
  > How knowledge flows through `docs/`: the loop, the folder rules, the templates, and the `docs-*` skills.
@@ -1,4 +1,4 @@
1
- <!-- naswerks-loop: version=0.1.0 -->
1
+ <!-- naswerks-loop: version=0.2.0 -->
2
2
  # The Engineering Loop — flow, seats, skills, and the ceremony
3
3
 
4
4
  > The quick intro to how work gets built with this loop: the two loops (`docs-*` knowledge, `spec-*`
@@ -170,7 +170,8 @@ diff.
170
170
  seat's own commit, so left alone it hands the NEXT seat a dirty tree. Goto 1.
171
171
 
172
172
  **Hard rules:** no commit/push without the relayed call; explicit staging, never `git add -A`, verified
173
- with `verify-staged`; codegen only through the command `patterns/codegen.md` names; component files as
173
+ with `verify-staged`; codegen only through the command `patterns/codegen.md` names (when the repo has
174
+ one); component files as
174
175
  `patterns/frontend-patterns.md` states; additive-only, never amend pushed commits; parallel sessions only
175
176
  when specs share no files — commits sequence regardless; seats run the pipeline's declared default model
176
177
  (allowlist-exact, set at creation), and an investigation-heavy seat may warrant a reasoning-heavier one.
@@ -37,10 +37,16 @@ docs/
37
37
  _meta/doc-index.md the menu, written LAST — every doc that exists + three repo slots:
38
38
  ## Role reading lists · ## Apps and their build commands · ## The evidence tools
39
39
  research/ working/ archive/ guides/ patterns/ infrastructure/ features/ each with a README.md
40
- patterns/vertical-slice-anatomy.md patterns/backend-patterns.md patterns/frontend-patterns.md
41
- patterns/testing.md patterns/codegen.md the floor — always drafted
42
- patterns/state-management.md patterns/ui-style-guide.md
43
- infrastructure/realtime-events.md infrastructure/background-work.md only when the scan finds the concern
40
+ patterns/code-organization.md patterns/backend-patterns.md
41
+ patterns/frontend-patterns.md patterns/testing.md the floor — always drafted; a repo
42
+ with no server side or no client side
43
+ gets an honest "not detected" doc
44
+ patterns/codegen.md patterns/state-management.md patterns/ui-style-guide.md
45
+ patterns/design-tokens.md patterns/long-running-workflows.md
46
+ infrastructure/realtime-events.md infrastructure/background-work.md
47
+ the standard set — drafted ONLY when
48
+ the scan finds the concern; every one
49
+ gets a doc-index row either way
44
50
  CLAUDE.md the Start-here stanza appended (created with only the stanza if absent)
45
51
  AGENTS.md the same stanza, only when the file already exists
46
52
  .claude/settings.json the plugin pin merged in (never clobbers existing keys)
@@ -49,6 +55,19 @@ AGENTS.md the same stanza, only when the file already e
49
55
  Eight folders, and the set is closed. Anything else already under `docs/` is left alone and reported as
50
56
  "outside the loop's shape — not touched" — never an error, never a queue entry.
51
57
 
58
+ **The standard set is shaped by what an engineering team usually has, and a team that lacks one of them
59
+ is told so, not handed a placeholder.** A concern the scan finds no evidence for is NOT drafted; its
60
+ `doc-index.md` § Role reading lists row says `not detected — no {library/mechanism} found`, and the
61
+ report lists it under "not in this codebase". A seat that later meets the absent path reads that row and
62
+ moves on. The floor four are the exception: every repository can answer "where the code lives", "how
63
+ the server side is built", "how the client side is built" and "how tests run" — even when the answer to
64
+ one of them is "no client side here" — so those are always written.
65
+
66
+ **The reserved space.** § Role reading lists in `doc-index.md` is the repository's own table: one row
67
+ per doc a role should read, standard or not. The coordinator copies a role's rows into every seat's
68
+ `EXTRA DOCS` line, so a team's own docs reach a seat as paths in its prompt. `init` seeds the standard
69
+ rows; the team adds its own, and can add a role column if its seats have kinds the loop does not ship.
70
+
52
71
  **Every template lives at the pack root under `templates/`** (`templates/docs/patterns/*.md`,
53
72
  `templates/docs/infrastructure/*.md`, `templates/docs/_meta/doc-index.md`, `templates/docs/readme-*.md`,
54
73
  `templates/claude-md-stanza.md`, `templates/settings-pin.json`). Under Claude Code the pack root is
@@ -91,9 +110,13 @@ not. `init` never overwrites, never reorders, never deletes.
91
110
  the only file init writes into a folder that already exists.
92
111
  2. `docs/_meta/docs-workflow.md` and `docs/_meta/engineering-loop.md` — byte copies of the pack's
93
112
  `references/*` (their first line is the version stamp; copy it with the file).
94
- 3. The five floor drafts from `templates/docs/patterns/*.md`, filled as below.
95
- 4. The conditional drafts — `state-management`, `ui-style-guide`, `realtime-events`, `background-work` —
96
- only where pass 3 found the concern.
113
+ 3. The four floor drafts (`code-organization`, `backend-patterns`, `frontend-patterns`, `testing`) from
114
+ `templates/docs/patterns/*.md`, filled as below.
115
+ 4. The standard-set drafts — `codegen`, `state-management`, `ui-style-guide`, `design-tokens`,
116
+ `long-running-workflows`, `realtime-events`, `background-work` — only where pass 3 found the concern.
117
+ Evidence per concern: a `generated/` folder or codegen config; a state library; a UI library; a tokens
118
+ file or token layer; a saga / workflow / state-machine mechanism; a realtime library on either side; a
119
+ queue, worker or scheduler.
97
120
  5. `docs/_meta/doc-index.md` from its template, LAST, listing every doc that now exists under the four
98
121
  living folders (drafted or repo-owned), the three repo slots filled from the scan.
99
122
  6. The Start-here stanza (`templates/claude-md-stanza.md`) appended to `CLAUDE.md` (created if absent)
@@ -138,8 +161,9 @@ FAIL, so a CI job or a control plane can call it.
138
161
  | each of the eight folders | missing | README missing | present |
139
162
  | `_meta/docs-workflow.md`, `_meta/engineering-loop.md` | missing, or no stamp on line 1 | stamp behind the pack's version | stamp equals it |
140
163
  | `_meta/doc-index.md` and its three slot sections | missing | a slot carries only the absent-line | filled |
141
- | the five floor docs | missing | `status=draft`, or an `<!-- init: -->` left in | `status=current` |
142
- | the four conditional docs | — | `status=draft` when present | present and current, or absent |
164
+ | the four floor docs | missing | `status=draft`, or an `<!-- init: -->` left in | `status=current` |
165
+ | the seven standard docs | absent AND no doc-index row saying `not detected` | `status=draft` when present; absent with its row | present and current, or absent with its row |
166
+ | every path a § Role reading lists row names | the row's path does not exist | — | resolves |
143
167
  | `CLAUDE.md` / `AGENTS.md` stanza · `.claude/settings.json` pin | — | missing | present |
144
168
  | `verify-staged` | — | not on PATH (the row carries the fallback) | resolvable |
145
169
  | every `docs/research/*/00-ignition-brief.md` | the five problems the control plane's parser emits (no `## The kick`; the kick has no blockquote; no `## The sequence`; the sequence holds no table; a row names no kind from `coordinator build fixit review retro witness docs-process`), or a spec a row names is missing from disk | — | clean |
@@ -157,7 +181,8 @@ state: the owner promotes each draft to `status=current` as they confirm it, sec
157
181
 
158
182
  - `init` is the front door of the pack; `docs-status` is the pulse after it. Run `docs-status` once the
159
183
  drafts are promoted to see the queue the way a session will.
160
- - The floor is always drafted, even in a repository with no frontend or no codegen — the reading floor
161
- must RESOLVE for every seat kind, and "No frontend detected — fill this in" is an honest doc.
184
+ - The floor four are always drafted, even in a repository with no frontend — the reading floor must
185
+ RESOLVE for every seat kind, and "No frontend detected — fill this in" is an honest doc. The standard
186
+ seven are drafted only on evidence; their absence is recorded, never papered over.
162
187
  - Counterpart skills: `spec-seat` (reads the floor), `spec-child` (reads the role rows), `spec-pipeline`
163
188
  (writes the brief `doctor` checks), `docs-write` / `docs-process` (the queue `doctor` reads).
@@ -56,13 +56,20 @@ for (const name of ['docs-workflow.md', 'engineering-loop.md']) {
56
56
  }
57
57
 
58
58
  // ── 4. the reading floor and the conditional docs ───────────────────────────────────────────────
59
- const FLOOR = ['patterns/vertical-slice-anatomy.md', 'patterns/backend-patterns.md', 'patterns/frontend-patterns.md', 'patterns/testing.md', 'patterns/codegen.md'];
60
- const CONDITIONAL = ['patterns/state-management.md', 'patterns/ui-style-guide.md', 'infrastructure/realtime-events.md', 'infrastructure/background-work.md'];
59
+ const FLOOR = ['patterns/code-organization.md', 'patterns/backend-patterns.md', 'patterns/frontend-patterns.md', 'patterns/testing.md'];
60
+ const STANDARD = ['patterns/codegen.md', 'patterns/state-management.md', 'patterns/ui-style-guide.md', 'patterns/design-tokens.md', 'patterns/long-running-workflows.md', 'infrastructure/realtime-events.md', 'infrastructure/background-work.md'];
61
+ const roleRows = (() => { const t = read(join(repo, 'docs', '_meta', 'doc-index.md')); return t === null ? null : sectionOf(t, '## Role reading lists'); })();
61
62
  for (const d of FLOOR) docRow(d, true);
62
- for (const d of CONDITIONAL) docRow(d, false);
63
+ for (const d of STANDARD) docRow(d, false);
63
64
  function docRow(relPath, required) {
64
65
  const text = read(join(repo, 'docs', relPath));
65
- if (text === null) { row(required ? 'FAIL' : 'ok', `docs/${relPath}`, required ? 'missing' : 'absent (drafted only when the scan finds the concern)'); return; }
66
+ if (text === null) {
67
+ if (required) { row('FAIL', `docs/${relPath}`, 'missing'); return; }
68
+ const rowText = roleRows === null ? null : roleRows.split('\n').find((l) => l.includes(relPath));
69
+ if (rowText && /not detected/i.test(rowText)) row('ok', `docs/${relPath}`, 'absent, and doc-index says why (not detected)');
70
+ else row('FAIL', `docs/${relPath}`, 'absent with no doc-index row saying it was not detected — a seat meeting this path has no answer');
71
+ return;
72
+ }
66
73
  const meta = /<!-- meta:[^>]*status=([a-z]+)/.exec(text);
67
74
  if (!meta) row('DEGRADE', `docs/${relPath}`, 'no <!-- meta --> line');
68
75
  else if (meta[1] === 'draft') row('DEGRADE', `docs/${relPath}`, 'status=draft — scanned, not decided');
@@ -70,6 +77,17 @@ function docRow(relPath, required) {
70
77
  if (/<!-- init:/.test(text)) row('DEGRADE', `docs/${relPath}`, 'an <!-- init: --> instruction was left in the file');
71
78
  }
72
79
 
80
+ // ── 4b. every path a Role reading lists row names resolves ─────────────────────────────────────
81
+ if (roleRows !== null) {
82
+ for (const line of roleRows.split('\n').filter((l) => l.trim().startsWith('|') && !/^\|\s*-/.test(l.trim()) && !/^\|\s*Doc\s*\|/i.test(l.trim()))) {
83
+ for (const m of line.matchAll(/`((?:patterns|infrastructure|guides|features)\/[A-Za-z0-9_.-]+\.md)`|\]\((?:\.\.\/)?((?:patterns|infrastructure|guides|features)\/[A-Za-z0-9_.-]+\.md)\)/g)) {
84
+ const p = m[1] || m[2];
85
+ if (/not detected/i.test(line)) continue;
86
+ row(existsSync(join(repo, 'docs', p)) ? 'ok' : 'FAIL', `doc-index row: docs/${p}`, existsSync(join(repo, 'docs', p)) ? '' : 'the row names a path that does not exist');
87
+ }
88
+ }
89
+ }
90
+
73
91
  // ── 5. CLAUDE.md / AGENTS.md stanza, settings pin ───────────────────────────────────────────────
74
92
  for (const name of ['CLAUDE.md', 'AGENTS.md']) {
75
93
  const text = read(join(repo, name));
@@ -34,16 +34,24 @@ apply** (`spec-seat`, Step 0). This list is for a build seat working from a spec
34
34
 
35
35
  ## Role — the adds, on top of spec-seat's Step 0 floor
36
36
 
37
+ The loop's standard docs, by path. **Read every one that exists for your role.** One that is absent was
38
+ not detected by `init` — `docs/_meta/doc-index.md` § Role reading lists carries a row saying so — and is
39
+ not a missing-file finding. `patterns/codegen.md` is read by any seat that touches a generated folder.
40
+
37
41
  | Role | Adds |
38
42
  |---|---|
39
- | **frontend** | `patterns/state-management.md` · `patterns/ui-style-guide.md` · `infrastructure/realtime-events.md` (the poke/refetch concept trips sessions up — read it even for "pure UI" work) · plus your role's rows in `docs/_meta/doc-index.md` § Role reading lists |
40
- | **backend** | `infrastructure/realtime-events.md` (the poke/refetch concept trips sessions up — read it even for "pure API" work) · `infrastructure/background-work.md` as the task warrants · plus your role's rows in `docs/_meta/doc-index.md` § Role reading lists |
41
- | **mixed** | **NOT every set by default** — read the adds for the surfaces your spec ACTUALLY touches, decided at recon once you have read the spec. **This is the default role and it covers every surface with no role of its own** — a surface the repo names only in `docs/_meta/doc-index.md` § Role reading lists (a sidecar, a CLI, a worker) reads the row there; docs work needs nothing beyond the Step 0 floor |
43
+ | **frontend** | `patterns/state-management.md` · `patterns/ui-style-guide.md` · `patterns/design-tokens.md` · `infrastructure/realtime-events.md` (the poke/refetch concept trips sessions up — read it even for "pure UI" work) · `patterns/codegen.md` when the client consumes generated types |
44
+ | **backend** | `infrastructure/realtime-events.md` (the poke/refetch concept trips sessions up — read it even for "pure API" work) · `infrastructure/background-work.md` · `patterns/long-running-workflows.md` as the task warrants · `patterns/codegen.md` when the server side emits generated code |
45
+ | **mixed** | **NOT every set by default** — read the adds for the surfaces your spec ACTUALLY touches, decided at recon once you have read the spec. **This is the default role and it covers every surface with no role of its own** — a CLI, a sidecar, a worker project; docs work needs nothing beyond the Step 0 floor |
46
+
47
+ **This repository's own docs reach you as paths too, not as an index to consult:** the coordinator copies
48
+ your role's rows from `docs/_meta/doc-index.md` § Role reading lists into your prompt's `EXTRA DOCS` line.
49
+ Read those the same way. If your prompt carries no `EXTRA DOCS` line, read that section yourself once and
50
+ say in your PLAN TLDR which rows you took.
42
51
 
43
52
  A role is *which docs does this build session read* — nothing else. Jobs are SEAT KINDS, not roles:
44
53
  `docs-process` is a session type of its own, and a spec that touches a surface with no role of its own is
45
- `mixed` with that surface's row. A doc-index row that says "no X detected" is an honest answer from `init`:
46
- that concern is not in this repo yet, and there is nothing to read for it.
54
+ `mixed` with that surface's rows.
47
55
 
48
56
  ## Recon — the build seat's first act
49
57
 
@@ -32,13 +32,14 @@ hand-testing what shipped. Everything else that a human does hand-cranked, you d
32
32
 
33
33
  ## Read first
34
34
 
35
- **Step 0 — the same floor every seat reads, all eight.** You verify every seat's work, so you start
36
- from the context they build in. A coordinator that has not read `testing.md` cannot judge a receipt; one
37
- that has not read `codegen.md` cannot spot a hand-written generated file.
35
+ **Step 0 — the same floor every seat reads, all seven, plus every standard doc this repository has.**
36
+ You verify every seat's work, so you start from the context they build in. A coordinator that has not
37
+ read `testing.md` cannot judge a receipt; one that has not read `codegen.md` (when the repo has one)
38
+ cannot spot a hand-written generated file.
38
39
 
39
40
  `_meta/doc-index.md` · `_meta/docs-workflow.md` · `_meta/engineering-loop.md` ·
40
- `patterns/vertical-slice-anatomy.md` · `patterns/backend-patterns.md` · `patterns/frontend-patterns.md` ·
41
- `patterns/testing.md` · `patterns/codegen.md`
41
+ `patterns/code-organization.md` · `patterns/backend-patterns.md` · `patterns/frontend-patterns.md` ·
42
+ `patterns/testing.md` — then every doc `doc-index.md` § Role reading lists carries a path for.
42
43
 
43
44
  **Step 1 — the effort**, in order:
44
45
 
@@ -113,9 +114,12 @@ read the board and answer on first receipt rather than spending a round-trip.
113
114
  defect even when it works: there are then two sources for one contract and only one of them gets
114
115
  corrected.
115
116
 
116
- **Pick the docs:** the role floor is settled (`spec-seat`'s Step 0 + `spec-child`'s role table) and
117
- **extras are YOUR call per task** — scan `docs/_meta/doc-index.md` for the quick decision. When in
118
- doubt, seed the doc: a seat reading one extra doc is cheaper than a seat guessing.
117
+ **Pick the docs:** the floor and the loop's standard docs are settled (`spec-seat`'s Step 0 +
118
+ `spec-child`'s role table). **This repository's own docs are yours to seed, by path, every time:** copy
119
+ the seat's role rows from `docs/_meta/doc-index.md` § Role reading lists into the prompt's `EXTRA DOCS`
120
+ line — a seat follows a path in its prompt and does not reliably follow an index. Then add the extras
121
+ the task itself warrants. When in doubt, seed the doc: a seat reading one extra doc is cheaper than a
122
+ seat guessing.
119
123
 
120
124
  **The seed-retirement rule:** each new seed restates ONLY what OVERRIDES a default (every seat
121
125
  re-acquires the defaults from the skill + umbrella from scratch) and DROPS what merely confirms them.
@@ -368,7 +372,7 @@ so read them as run-time obligations, not close-out ones:
368
372
  branch-deletion backstop. The fence fires on the commands a careful seat runs to PROVE its work.
369
373
  - Seats never edit `project-status.md` or memory files; never run `docs-write` unprompted; respect the
370
374
  umbrella's out-of-scope list; codegen only through the command `patterns/codegen.md` § Running codegen
371
- names; component files laid out as `patterns/frontend-patterns.md` § Component files states. Run the
375
+ names (when the repo has one); component files laid out as `patterns/frontend-patterns.md` § Component files states. Run the
372
376
  suite lanes SERIALLY.
373
377
  - Cross-slice changes (touching a shipped spec's files) need your explicit approval and get recorded as
374
378
  a departure. Additive-only; never amend pushed commits.
@@ -440,7 +444,8 @@ Pipeline context: {umbrella path} (settled decisions — don't relitigate) + {pr
440
444
  (READ-ONLY, coordinator-owned — prior rows, deferred findings, and process incidents are your contract).
441
445
 
442
446
  EXTRA DOCS for this task (beyond your role's floor — read them):
443
- {the coordinator's picks from doc-index.md}
447
+ {this repository's rows for the role, copied from doc-index.md § Role reading lists, by path}
448
+ {the coordinator's task-specific picks}
444
449
 
445
450
  PRIOR SPECS ARE SHIPPED at {hash} — build against their ACTUAL shapes:
446
451
  {bullet the real endpoints, contracts, helpers-to-reuse, caveats, and coordinator-adopted requirements
@@ -102,9 +102,12 @@ other; an identity or authorization plane that is trustworthy per-slice and forg
102
102
  ordinary correctness: null and error paths, concurrency, data loss, exception swallowing.
103
103
 
104
104
  **Lens 2 — the patterns, and the language.** Read the diff against `patterns/backend-patterns.md`,
105
- `patterns/frontend-patterns.md`, `patterns/vertical-slice-anatomy.md`, `patterns/testing.md`,
106
- `patterns/codegen.md` — and against ordinary good practice in the language, which no pattern doc covers
107
- exhaustively.
105
+ `patterns/frontend-patterns.md`, `patterns/code-organization.md`, `patterns/testing.md`, and every
106
+ standard doc the repository has (`patterns/codegen.md`, `patterns/state-management.md`,
107
+ `patterns/ui-style-guide.md`, `patterns/design-tokens.md`, `infrastructure/realtime-events.md`,
108
+ `infrastructure/background-work.md`, `patterns/long-running-workflows.md` — those that exist) plus the
109
+ rows in `docs/_meta/doc-index.md` § Role reading lists — and against ordinary good practice in the
110
+ language, which no pattern doc covers exhaustively.
108
111
 
109
112
  **A pattern break is not automatically a defect.** There are legitimate reasons to depart. Your job is
110
113
  that **every departure is IDENTIFIED and its reason stated** — an intentional break with a recorded reason
@@ -61,20 +61,24 @@ Then recon the tree: `git rev-parse HEAD`, `git status --porcelain`, `git branch
61
61
 
62
62
  | Doc | What it gives you |
63
63
  |---|---|
64
- | `patterns/vertical-slice-anatomy.md` | where a feature's files go, every stack the repo has |
64
+ | `patterns/code-organization.md` | where the code lives and where a new piece goes, every stack the repo has |
65
65
  | `patterns/backend-patterns.md` | how the server side is built here |
66
66
  | `patterns/frontend-patterns.md` | how the client side is built here |
67
67
  | `patterns/testing.md` | how to write and RUN the suites — including the run protocol |
68
- | `patterns/codegen.md` | what is generated and how; never hand-write a generated folder |
69
68
 
70
69
  **That is the default set, required regardless of role** —
71
70
  `docs/_meta/doc-index.md` · `docs/_meta/docs-workflow.md` · `docs/_meta/engineering-loop.md` ·
72
- `patterns/vertical-slice-anatomy.md` · `patterns/backend-patterns.md` · `patterns/frontend-patterns.md` ·
73
- `patterns/testing.md` · `patterns/codegen.md`
71
+ `patterns/code-organization.md` · `patterns/backend-patterns.md` · `patterns/frontend-patterns.md` ·
72
+ `patterns/testing.md`
74
73
  <!-- A control plane may read this line + list as its preset hint (it looks for "default set" and "role" on
75
74
  one line, then collects the backticked paths until a blank line). Keep the phrase and the list
76
75
  contiguous, or the hint silently empties. -->
77
76
 
77
+ **On top of the floor, your job skill names the loop's standard docs for your role by path, and your
78
+ prompt's `EXTRA DOCS` line names this repository's own.** Read every one that exists. A standard doc that
79
+ is absent was not detected by `init` — `docs/_meta/doc-index.md` § Role reading lists carries a row
80
+ saying so — and is not a missing-file finding.
81
+
78
82
  A doc marked `status=draft` in its meta line was scanned by `init`, not decided by the repo's owners —
79
83
  read it as the starting point it is, and treat a rule it states without a cited source as a question for
80
84
  your PLAN TLDR, not a law.
@@ -365,8 +369,8 @@ doorbell with no follow-through**; if you receive one bare, retry anyway and say
365
369
  echo text — the deny layer matches text, not parsed verbs.
366
370
  - Prefer native read/glob/grep tools for reads; a shell read flows with its row like any other
367
371
  non-boundary call.
368
- - **Codegen only through the command `patterns/codegen.md` § Running codegen names** — never hand-write a
369
- generated folder.
372
+ - **Codegen only through the command `patterns/codegen.md` § Running codegen names** (when the repo has
373
+ one) — never hand-write a generated folder.
370
374
  - **Never improvise a qualifying path in.** If a push parks and the remedy you can think of is touching a
371
375
  `docs/working/` file or the tracker to satisfy a predicate, that is fabricating a receipt. Raise a
372
376
  `## MID-BUILD QUESTION` and price the options; do not execute it and do not invent a way around it.
@@ -21,12 +21,11 @@
21
21
 
22
22
  | Doc | When to read |
23
23
  |-----|-------------|
24
- | [vertical-slice-anatomy](../patterns/vertical-slice-anatomy.md) | **Where a feature's files go**, per stack, and the new-feature checklist |
24
+ | [code-organization](../patterns/code-organization.md) | **Where the code lives and where a new piece goes** — the folder shape as it is, per stack, and the add-a-feature checklist |
25
25
  | [backend-patterns](../patterns/backend-patterns.md) | **How the server side is built here** — data layer, API layer, write paths, registration |
26
26
  | [frontend-patterns](../patterns/frontend-patterns.md) | **How the client side is built here** — architecture rules, component kinds and files, state, styling |
27
27
  | [testing](../patterns/testing.md) | **How to write and RUN the suites** — the lanes and their exact commands, the run protocol, what to test where, the controls discipline |
28
- | [codegen](../patterns/codegen.md) | **What is generated and by which command** — never hand-write a generated file |
29
- <!-- init: add rows for state-management and ui-style-guide when they were drafted. -->
28
+ <!-- init: add rows for codegen, state-management, ui-style-guide, design-tokens and long-running-workflows when they were drafted; the hook for each ends "(draft — scanned, not decided)". -->
30
29
 
31
30
  ## Infrastructure — what runs UNDER THE HOOD
32
31
 
@@ -49,15 +48,22 @@
49
48
 
50
49
  ## Role reading lists
51
50
 
52
- The adds a build seat reads on top of the floor every seat reads (`spec-seat` Step 0). `spec-child`
53
- names the generic docs; this section is where THIS repository adds its own rows per role.
54
-
55
- | Role | Adds |
56
- |---|---|
57
- | **backend** | <!-- init: `infrastructure/realtime-events.md` when drafted, else "no realtime library detected"; `infrastructure/background-work.md` when drafted, else "no queue or worker detected" --> |
58
- | **frontend** | <!-- init: `patterns/state-management.md` when drafted, else "no state library detected"; `patterns/ui-style-guide.md` when drafted, else "no UI library detected"; `infrastructure/realtime-events.md` as above --> |
59
- | **mixed** | reads the rows above for the surfaces the spec touches; <!-- init: one row per surface the scan found that has no role of its own (a CLI, a sidecar, a worker project): "`{path to its doc, or the folder}` — {what it is}" --> |
60
- <!-- repo rows go here: a surface this repository has that the generic docs do not cover -->
51
+ The docs a build seat reads on top of the floor every seat reads (`spec-seat` Step 0). The `spec-child`
52
+ skill names the loop's standard docs by path; this table is the repository's reserved space — one row per
53
+ doc, saying which roles read it. The coordinator copies a role's rows into every seat's seed as
54
+ `EXTRA DOCS`, so a seat sees paths, not this index. Add a row for any doc of your own a role should read;
55
+ add a role column if your seats have kinds the loop does not ship.
56
+
57
+ | Doc | What it gives the seat | backend | frontend | mixed |
58
+ |---|---|---|---|---|
59
+ <!-- init: one row per standard doc the scan found evidence for and drafted (codegen, state-management,
60
+ ui-style-guide, design-tokens, realtime-events, background-work, long-running-workflows), with the
61
+ roles that read it marked `x` (realtime-events: backend + frontend; state-management, ui-style-guide,
62
+ design-tokens: frontend; background-work, long-running-workflows: backend; codegen: any seat that
63
+ touches a generated folder). One row per standard doc NOT drafted, in the form
64
+ "| `patterns/state-management.md` | not detected — no state library found | | | |" so a seat that
65
+ meets the absent path knows why. `mixed` reads the rows for the surfaces its spec touches. -->
66
+ <!-- repo rows go here: a doc this repository has that the loop's standard set does not name -->
61
67
 
62
68
  ## Apps and their build commands
63
69
 
@@ -32,11 +32,13 @@
32
32
 
33
33
  ## Long-running workflows
34
34
 
35
- <!-- init: scan — a saga / orchestration / state-machine base class, a job with stages.
36
- fill — the shape (stages, per-item progress, exactly-once stage transitions and what guarantees them,
37
- progress reporting to the client), one REAL workflow as the example, then `### Rules`.
38
- absent — "No multi-stage workflow detected — fill this in when one appears: how stages chain, how a
39
- stage transition happens exactly once, how progress is reported." -->
35
+ Snapshot — multi-stage work (stages, per-item progress, exactly-once transitions) is the authority of
36
+ [long-running-workflows](../patterns/long-running-workflows.md) when the repo has one; this page is the
37
+ transport it runs on.
38
+
39
+ <!-- init: fill — one sentence naming the workflow mechanism (from long-running-workflows.md when drafted).
40
+ absent — "No multi-stage workflow detected — every background job here is single-stage; fill this in
41
+ when one appears." -->
40
42
 
41
43
  ## Gotchas
42
44
 
@@ -50,4 +52,4 @@
50
52
  |------|---------|
51
53
 
52
54
  ## Lineage
53
- - **Related** — [backend-patterns](../patterns/backend-patterns.md) · [realtime-events](realtime-events.md)
55
+ - **Related** — [backend-patterns](../patterns/backend-patterns.md) · [realtime-events](realtime-events.md) · [long-running-workflows](../patterns/long-running-workflows.md)
@@ -93,4 +93,4 @@
93
93
  absent — "| (none detected) | fill this in: the base entity, the data context, the composition root |" -->
94
94
 
95
95
  ## Lineage
96
- - **Related** — [vertical-slice-anatomy](vertical-slice-anatomy.md) · [testing](testing.md) · [codegen](codegen.md)
96
+ - **Related** — [code-organization](code-organization.md) · [testing](testing.md) · [codegen](codegen.md)
@@ -1,20 +1,24 @@
1
- # Vertical Slice Anatomy
1
+ # Code Organization
2
2
 
3
- > Where to place each piece when building a feature in this repository. Last verified {today}.
3
+ > Where the code lives and where a new piece goes — the folder shape this repository actually uses, per
4
+ > stack, and the checklist for adding a feature to it. Last verified {today}.
4
5
  <!-- meta: type=pattern; status=draft; verified={today}; lineage=0 -->
5
6
  <!-- naswerks-loop: draft; scanned={files} -->
6
7
 
7
8
  ---
8
9
 
9
- ## Feature structure
10
+ ## The shape
10
11
 
11
12
  <!-- init: scan — the folder layout two deep for every stack (Features/, src/app/, apps/*, packages/*,
12
- cmd/, internal/, lib/), and ONE existing feature per stack.
13
- fill — one ASCII tree per stack showing a REAL feature as it exists, side by side when there are
14
- two, with a comment per folder saying what goes there; then one sentence per stack on what lives
15
- OUTSIDE a feature (shared infrastructure, cross-cutting stores).
16
- absent — "No feature layout detected — fill this in: where a feature's files go, per stack, as a
17
- tree copied from a real one." -->
13
+ cmd/, internal/, lib/, a layered src/{Domain,Application,Infrastructure}), and ONE existing feature or
14
+ module per stack.
15
+ fill — name the organization as it IS (vertical slices, layers, packages in a monorepo, a flat
16
+ module tree — whatever the folders say), then one ASCII tree per stack showing a REAL feature/module
17
+ as it exists, side by side when there are two, with a comment per folder saying what goes there; then
18
+ one sentence per stack on what lives OUTSIDE a feature (shared infrastructure, cross-cutting code).
19
+ Do not describe a pattern the folders do not show.
20
+ absent — "No code layout detected — fill this in: where a feature's or module's files go, per
21
+ stack, as a tree copied from a real one." -->
18
22
 
19
23
  ```
20
24
  {stack A} {stack B, if any}
@@ -25,22 +29,22 @@
25
29
  ## The kinds of file, and their roles
26
30
 
27
31
  <!-- init: scan — the kinds the trees above show (endpoint / model / query / service; page / component /
28
- store; command / handler).
32
+ store; command / handler; a module's public surface).
29
33
  fill — a table `Kind | Role | Where | Owns` with one row per kind.
30
34
  absent — "No kinds detected — fill this in: each kind of file a feature holds, and what it owns." -->
31
35
 
32
36
  | Kind | Role | Where | Owns |
33
37
  |------|------|-------|------|
34
38
 
35
- ## Checklist: new feature
39
+ ## Checklist: adding a feature
36
40
 
37
41
  <!-- init: scan — the trees above, the registration points (composition root, router, module list), the
38
42
  test conventions in patterns/testing.md § What to test where.
39
43
  fill — an ordered `- [ ]` checklist per stack: create X in {path} (one line on what it must extend
40
44
  or implement), register it in {file}, add the route/handler in {file}, add the tests the testing doc
41
45
  names for each kind, run the build. Each item is a real path.
42
- absent — "- [ ] No feature layout detected — fill this in: the ordered steps that add a feature,
43
- each naming its file." -->
46
+ absent — "- [ ] No layout detected — fill this in: the ordered steps that add a feature, each naming
47
+ its file." -->
44
48
 
45
49
  ### {stack A}
46
50
 
@@ -53,7 +57,7 @@
53
57
  ## Gotchas
54
58
 
55
59
  <!-- init: scan — CONTRIBUTING.md, CLAUDE.md, AGENTS.md, lint rules that fire on layout (import
56
- boundaries, dependency-cruiser, ArchUnit-style rules).
60
+ boundaries, dependency-cruiser, ArchUnit-style rules, banned-symbol lists).
57
61
  fill — one `### Gotcha:` per written-down layout rule, citing its source file.
58
62
  absent — "No layout gotchas written down yet — fill this in the first time one bites." -->
59
63
 
@@ -0,0 +1,62 @@
1
+ # Design Tokens
2
+
3
+ > The token authority: which colour, spacing and typography tokens exist, what each means, and how
4
+ > component CSS consumes them. Component usage (which class for which job) lives in
5
+ > [ui-style-guide](ui-style-guide.md). Last verified {today}.
6
+ <!-- meta: type=pattern; status=draft; verified={today}; lineage=0 -->
7
+ <!-- naswerks-loop: draft; scanned={files} -->
8
+
9
+ ---
10
+
11
+ ## Overview
12
+
13
+ <!-- init: scan — a tokens/theme file (a CSS file defining --* custom properties, a tailwind/daisyui
14
+ theme block, a design-system package), the global stylesheet, how themes are switched.
15
+ fill — two to four sentences: the token system, the library that emits it, how a theme is selected.
16
+ absent — this doc is only drafted when a tokens file or a UI library with a token layer is found. -->
17
+
18
+ ## Token reference
19
+
20
+ <!-- init: fill — one table per family (`Token | CSS variable | Purpose | When to use`): brand, base /
21
+ surface, status; each row read from the tokens file, never invented.
22
+ absent — "No token definitions found — fill this in." -->
23
+
24
+ ### Brand
25
+
26
+ | Token | CSS variable | Purpose | When to use |
27
+ |-------|-------------|---------|-------------|
28
+
29
+ ### Base / surface
30
+
31
+ | Token | CSS variable | Purpose | When to use |
32
+ |-------|-------------|---------|-------------|
33
+
34
+ ### Status
35
+
36
+ | Token | CSS variable | Purpose | When to use |
37
+ |-------|-------------|---------|-------------|
38
+
39
+ ## Consuming tokens in component CSS
40
+
41
+ <!-- init: scan — how existing component styles reference tokens (var(--…), a theme() helper, a mixin).
42
+ fill — the ONE rule in this repo's form ("use `var(--…)` directly; express opacity with `color-mix`;
43
+ never a literal colour"), a fenced example copied from a real stylesheet, and the dead forms to grep for
44
+ if the library moved majors.
45
+ absent — "No token consumption found in component styles — fill this in." -->
46
+
47
+ ## Rules
48
+
49
+ <!-- init: scan — a style lint, a stylesheet rule spec, a CONTRIBUTING note.
50
+ fill — bold-lead imperative bullets, each citing its source when written down; the loop supplies one:
51
+ "**A stylesheet never names a colour** — every value is a token or a mix over one, so a skin or a dark
52
+ mode needs no per-component work."
53
+ absent — the one loop-supplied bullet, then "- No further token rules found written down — fill this
54
+ in." -->
55
+
56
+ ## Key Files
57
+
58
+ | File | Purpose |
59
+ |------|---------|
60
+
61
+ ## Lineage
62
+ - **Related** — [ui-style-guide](ui-style-guide.md) · [frontend-patterns](frontend-patterns.md)
@@ -89,4 +89,4 @@
89
89
  absent — "| (none detected) | fill this in: the app config, the routes, the shared components |" -->
90
90
 
91
91
  ## Lineage
92
- - **Related** — [vertical-slice-anatomy](vertical-slice-anatomy.md) · [testing](testing.md) · [codegen](codegen.md) · [backend-patterns](backend-patterns.md)
92
+ - **Related** — [code-organization](code-organization.md) · [testing](testing.md) · [codegen](codegen.md) · [backend-patterns](backend-patterns.md)
@@ -0,0 +1,63 @@
1
+ # Long-Running Workflows
2
+
3
+ > How multi-stage work is orchestrated in this repository: the stages, per-item progress, exactly-once
4
+ > transitions, and how progress reaches the client. The transport it runs on is
5
+ > [background-work](../infrastructure/background-work.md). Last verified {today}.
6
+ <!-- meta: type=pattern; status=draft; verified={today}; lineage=0 -->
7
+ <!-- naswerks-loop: draft; scanned={files} -->
8
+
9
+ ---
10
+
11
+ ## Overview
12
+
13
+ <!-- init: scan — a saga / orchestration / workflow / state-machine base class or library (a saga
14
+ framework, a durable-functions style runtime, a job with named stages), the entities that record
15
+ stage state.
16
+ fill — two to four sentences: what a workflow is here, what guarantees it makes, and which features
17
+ use it.
18
+ absent — this doc is only drafted when a multi-stage workflow mechanism is found. -->
19
+
20
+ ## The shape
21
+
22
+ <!-- init: fill — an ASCII diagram of one REAL workflow (trigger, stages, the transition that starts the
23
+ next stage, completion), then the base classes / tables that hold it.
24
+ absent — "No workflow found to diagram — fill this in with the first one." -->
25
+
26
+ ```
27
+ {trigger} -> stage 1 -> stage 2 -> ... -> complete
28
+ ```
29
+
30
+ ## Exactly-once transitions
31
+
32
+ <!-- init: scan — the code that decides a stage is done (a TryComplete, a row lock, a compare-and-set, an
33
+ idempotency key).
34
+ fill — what guarantees a stage transition happens once, with the real symbol named; what happens on a
35
+ retry; who owns the transition.
36
+ absent — "No transition guard found — fill this in: how a stage completes exactly once under
37
+ concurrency." -->
38
+
39
+ ## Per-item progress and failure
40
+
41
+ <!-- init: fill — how an item starts, completes and fails inside a stage; what a stuck item looks like and
42
+ who reaps it; how progress is reported (an event, a poke, a row).
43
+ absent — "No per-item tracking found — fill this in." -->
44
+
45
+ ## Creating a new workflow — checklist
46
+
47
+ <!-- init: fill — an ordered `- [ ]` list: the base class to extend, the stage events or handlers to add,
48
+ the registration, the tests the testing doc names (the concurrency test especially).
49
+ absent — "- [ ] No workflow mechanism detected — fill this in when one appears." -->
50
+
51
+ ## Rules
52
+
53
+ <!-- init: scan — comments on the base class, CONTRIBUTING notes.
54
+ fill — bold-lead imperative bullets citing their source.
55
+ absent — "- No workflow rules found written down — fill this in." -->
56
+
57
+ ## Key Files
58
+
59
+ | File | Purpose |
60
+ |------|---------|
61
+
62
+ ## Lineage
63
+ - **Related** — [background-work](../infrastructure/background-work.md) · [backend-patterns](backend-patterns.md) · [testing](testing.md)
@@ -70,4 +70,4 @@
70
70
  |------|---------|
71
71
 
72
72
  ## Lineage
73
- - **Related** — [frontend-patterns](frontend-patterns.md) · [vertical-slice-anatomy](vertical-slice-anatomy.md)
73
+ - **Related** — [frontend-patterns](frontend-patterns.md) · [code-organization](code-organization.md)
@@ -100,4 +100,4 @@ A test that cannot go red is a green light with a test's name on it. For every p
100
100
  absent — "| (none detected) | fill this in: the runner config, the shared fixtures, the CI workflow |" -->
101
101
 
102
102
  ## Lineage
103
- - **Related** — [backend-patterns](backend-patterns.md) · [frontend-patterns](frontend-patterns.md) · [vertical-slice-anatomy](vertical-slice-anatomy.md)
103
+ - **Related** — [backend-patterns](backend-patterns.md) · [frontend-patterns](frontend-patterns.md) · [code-organization](code-organization.md)
@@ -1,7 +1,7 @@
1
1
  # UI Style Guide
2
2
 
3
3
  > Which class or component to reach for, for which job, and the composition rules that keep screens
4
- > consistent — plus the design tokens and how to consume them. Last verified {today}.
4
+ > consistent. The tokens themselves are the authority of [design-tokens](design-tokens.md). Last verified {today}.
5
5
  <!-- meta: type=pattern; status=draft; verified={today}; lineage=0 -->
6
6
  <!-- naswerks-loop: draft; scanned={files} -->
7
7
 
@@ -52,12 +52,13 @@ Every data-driven page handles four states: **loading**, **error**, **empty**, *
52
52
 
53
53
  ## Tokens
54
54
 
55
- <!-- init: scan — a tokens/theme file, a global stylesheet, the UI library's token variables.
56
- fill — a table `Token | CSS variable | Purpose | When to use` for brand, base and status tokens,
57
- then the ONE consumption rule for component CSS (use `var(--…)` tokens, never a literal colour; how to
58
- express opacity), and the dead forms to grep for if the library moved majors.
59
- absent — "No design tokens detected — fill this in: the colour and spacing tokens and how component
60
- CSS consumes them." -->
55
+ Snapshot — the token authority is [design-tokens](design-tokens.md): which tokens exist, what each
56
+ means, and the one rule for consuming them in component CSS. This page names the class for the job; that
57
+ page names the value behind the class.
58
+
59
+ <!-- init: fill — one sentence naming the token family this UI library exposes (from design-tokens.md when
60
+ drafted). absent — "No design tokens detected — the classes above are the whole vocabulary; fill this in
61
+ if a token layer appears." -->
61
62
 
62
63
  ## Forms
63
64
 
@@ -73,4 +74,4 @@ Every data-driven page handles four states: **loading**, **error**, **empty**, *
73
74
  |---------|-------|
74
75
 
75
76
  ## Lineage
76
- - **Related** — [frontend-patterns](frontend-patterns.md)
77
+ - **Related** — [frontend-patterns](frontend-patterns.md) · [design-tokens](design-tokens.md)
@@ -2,8 +2,8 @@
2
2
 
3
3
  Conventions to FOLLOW when writing code. Prescriptive: truth is by decision, so a mismatch between a
4
4
  pattern doc and the code is usually a code problem to flag, not a doc to rewrite. Every seat reads the
5
- floor (`vertical-slice-anatomy`, `backend-patterns`, `frontend-patterns`, `testing`, `codegen`)
6
- before it writes a line; a doc marked `status=draft` was scanned by `init`, not decided — promote it as
5
+ floor (`code-organization`, `backend-patterns`, `frontend-patterns`, `testing`) before it writes a
6
+ line, and its role's docs on top of it; a doc marked `status=draft` was scanned by `init`, not decided — promote it as
7
7
  you confirm each section.
8
8
 
9
9
  A README in this folder is never a queue entry.