@nurix/etna 0.20.25 → 0.20.27

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 (75) hide show
  1. package/data/harness-index.json +1 -1
  2. package/data/harnesses/code/CLAUDE.md +4 -4
  3. package/data/harnesses/code/agents/bookkeeper.md +1 -1
  4. package/data/harnesses/code/agents/change-review.md +1 -1
  5. package/data/harnesses/code/agents/lld-mode.md +1 -1
  6. package/data/harnesses/code/agents/maintenance.md +7 -9
  7. package/data/harnesses/code/docs/structure.md +133 -71
  8. package/data/harnesses/code/harness.json +4 -4
  9. package/data/harnesses/code/hooks/awareness.mjs +0 -10
  10. package/data/harnesses/code/hooks/lib/ownership.mjs +4 -2
  11. package/data/harnesses/code/hooks/lib/sweep.mjs +4 -8
  12. package/data/harnesses/code/skills/documentation/SKILL.md +22 -11
  13. package/data/harnesses/code/skills/documentation/references/examples.md +29 -25
  14. package/data/harnesses/code/skills/documentation/references/frontmatter.md +3 -3
  15. package/data/harnesses/code/skills/documentation/references/style-guide.md +211 -292
  16. package/data/harnesses/code/skills/documentation/references/untemplated.md +4 -2
  17. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +104 -2
  18. package/data/harnesses/code/skills/documentation/templates/Readme.md +4 -3
  19. package/data/harnesses/code/skills/documentation/templates/bookkeeping.md +1 -1
  20. package/data/harnesses/code/skills/documentation/templates/docs-readme.md +15 -36
  21. package/data/harnesses/code/skills/documentation/templates/doctrine.md +81 -0
  22. package/data/harnesses/code/skills/documentation/templates/feature.md +63 -119
  23. package/data/harnesses/code/skills/documentation/templates/handover.md +174 -0
  24. package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +1 -1
  25. package/data/harnesses/code/skills/documentation/templates/package.md +49 -92
  26. package/data/harnesses/code/skills/documentation/templates/root-readme.md +103 -65
  27. package/data/harnesses/code/skills/documentation/templates/setup.md +138 -0
  28. package/data/harnesses/code/skills/documentation/templates/system.md +45 -107
  29. package/data/harnesses/delivery/agents/lld-mode.md +1 -1
  30. package/data/harnesses/delivery/agents/maintenance.md +7 -9
  31. package/data/harnesses/delivery/harness.json +2 -2
  32. package/data/harnesses/delivery/skills/documentation/SKILL.md +22 -11
  33. package/data/harnesses/delivery/skills/documentation/references/examples.md +29 -25
  34. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +3 -3
  35. package/data/harnesses/delivery/skills/documentation/references/style-guide.md +211 -292
  36. package/data/harnesses/delivery/skills/documentation/references/untemplated.md +4 -2
  37. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +104 -2
  38. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +4 -3
  39. package/data/harnesses/delivery/skills/documentation/templates/bookkeeping.md +1 -1
  40. package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +15 -36
  41. package/data/harnesses/delivery/skills/documentation/templates/doctrine.md +81 -0
  42. package/data/harnesses/delivery/skills/documentation/templates/feature.md +63 -119
  43. package/data/harnesses/delivery/skills/documentation/templates/handover.md +174 -0
  44. package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +1 -1
  45. package/data/harnesses/delivery/skills/documentation/templates/package.md +49 -92
  46. package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +103 -65
  47. package/data/harnesses/delivery/skills/documentation/templates/setup.md +138 -0
  48. package/data/harnesses/delivery/skills/documentation/templates/system.md +45 -107
  49. package/data/harnesses/etna/agents/change-review.md +1 -1
  50. package/data/harnesses/etna/agents/lld-mode.md +1 -1
  51. package/data/harnesses/etna/agents/maintenance.md +7 -9
  52. package/data/harnesses/etna/harness.json +2 -2
  53. package/data/harnesses/etna/skills/documentation/SKILL.md +22 -11
  54. package/data/harnesses/etna/skills/documentation/references/examples.md +29 -25
  55. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +3 -3
  56. package/data/harnesses/etna/skills/documentation/references/style-guide.md +211 -292
  57. package/data/harnesses/etna/skills/documentation/references/untemplated.md +4 -2
  58. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +104 -2
  59. package/data/harnesses/etna/skills/documentation/templates/Readme.md +4 -3
  60. package/data/harnesses/etna/skills/documentation/templates/bookkeeping.md +1 -1
  61. package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +15 -36
  62. package/data/harnesses/etna/skills/documentation/templates/doctrine.md +81 -0
  63. package/data/harnesses/etna/skills/documentation/templates/feature.md +63 -119
  64. package/data/harnesses/etna/skills/documentation/templates/handover.md +174 -0
  65. package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +1 -1
  66. package/data/harnesses/etna/skills/documentation/templates/package.md +49 -92
  67. package/data/harnesses/etna/skills/documentation/templates/root-readme.md +103 -65
  68. package/data/harnesses/etna/skills/documentation/templates/setup.md +138 -0
  69. package/data/harnesses/etna/skills/documentation/templates/system.md +45 -107
  70. package/lib/install/materialize.mjs +4 -12
  71. package/lib/install/plan.mjs +4 -11
  72. package/package.json +3 -2
  73. package/data/harnesses/code/skills/documentation/templates/structure.md +0 -71
  74. package/data/harnesses/delivery/skills/documentation/templates/structure.md +0 -71
  75. package/data/harnesses/etna/skills/documentation/templates/structure.md +0 -71
@@ -0,0 +1,138 @@
1
+ # Setup (docs/operations/setup.md)
2
+
3
+ Truth document, operations genre (`type: operations`). Use for: **the one-time path from a fresh machine to a first verified run.** It covers what the repo is built on, prerequisites, install, env files, local services, the first commands, proof that it works, and the failures a fresh clone hits. There is **one per repo**, always named `setup.md`, and it is a mandated scaffold. The root README's only setup content is a Destinations row linking it.
4
+
5
+ It is distinct from `local-development.md`, the daily loop: watch modes, resetting state, per-package traps, the inner test cycle. Setup runs once per machine. Local development runs every session. Setup ends by handing off to it, and neither copies the other. Deploying is `deployment.md`.
6
+
7
+ Required: **Goal**, **Stack**, **Prerequisites**, **Install**, **First run**, **Verify**. Optional, included only with real content: the audience fork, **Before cloning**, **Environment files**, **Local services**, **Reset**, **Common failures**.
8
+
9
+ ### Writing rules
10
+
11
+ - **Never write a version a file already pins.** Each row names the pinning file (`.nvmrc`, `package.json` `engines` / `packageManager`, `rust-toolchain.toml`, `go.mod`) and the command that checks it. A typed number is a second source that drifts on the next bump.
12
+ - **Stack is one row per layer.** Give the technology, what it is for in this repo, and where its version is pinned. Why it was chosen belongs to `docs/architecture/`, linked once. Don't repeat the dependency list: the manifests are the roster.
13
+ - **One path, from the lockfile.** `pnpm-lock.yaml` gives pnpm, `yarn.lock` gives yarn, otherwise npm. Say how it is activated (`corepack enable`). Never write "or npm / yarn". Give a per-OS variant only where the commands really differ.
14
+ - **Traps before commands.** Anything a fresh clone hits before the first command goes in Before cloning, not halfway down the steps: LFS, submodules, a required stub file, an access grant, a credential that has to be requested.
15
+ - **Copy-paste runnable, one action per step, each with its expected outcome.** Run non-interactively where the tool allows it, so an agent can execute the step unchanged. "It should work now" is never a step.
16
+ - **Script first, then document.** If a bootstrap script or task exists, it is the step, and the doc carries only the judgment around it. A setup sequence run often with no script gets a script.
17
+ - **Env files as a table, never a variable dump.** One row per file: where it is copied from, what must be filled, where the values come from, whether it is required to boot. The variable contract is the example file and the code's env type, linked and never copied. Secret values never appear.
18
+ - **Destructive commands state their blast radius where they appear:** what is deleted or truncated, whether it prompts, and the flag that skips the prompt.
19
+ - **Verification is observable:** a health probe and its expected status, a URL and what it shows, a seeded login, a doctor command and its output, or the test command passing from a cold shell.
20
+ - **Common failures are keyed by the exact error text,** followed by the cause and the fix, where the fix is a command or a file edit. Append a failure only once it has been root-caused, never as speculation.
21
+ - **Per-package divergence is a subsection of this file.** A unit whose setup differs gets a `### {unit}` block under First run, or a row linking its own procedure. It never gets a second setup doc.
22
+
23
+ ### Template
24
+
25
+ ```markdown
26
+ ---
27
+ type: operations
28
+ ---
29
+
30
+ # Setup
31
+
32
+ **Goal:** take a fresh machine from clone to a verified first run of {what runs: e.g. "the product Worker on :{port} and the web shell on :{port}, signed in as the dev fixture"}. Done once per machine; the daily loop is [`local-development.md`]({local-development}.md).
33
+
34
+ {Optional audience fork: "Only running {the CLI / one package}? Stop after Install and see [`{procedure}`]({path})."}
35
+
36
+ ## Stack
37
+
38
+ | Layer | Technology | For | Version pinned by |
39
+ | --- | --- | --- | --- |
40
+ | {Runtime} | {Node} | {what runs on it} | [`.nvmrc`](../../.nvmrc) |
41
+ | {Server} | {framework · data layer} | {what it serves} | [`{package.json}`](../../{path}/package.json) |
42
+ | {Client} | {framework · build tool · styling} | {which surfaces} | [`{package.json}`](../../{path}/package.json) |
43
+ | {Tests} | {runners} | {unit · e2e} | {manifest} |
44
+
45
+ Why these were chosen: [{system overview}](../architecture/{overview}.md).
46
+
47
+ ## Prerequisites
48
+
49
+ | Tool | Version from | Check |
50
+ | --- | --- | --- |
51
+ | {Node} | [`.nvmrc`](../../.nvmrc) | `node -v` |
52
+ | {pnpm} | `packageManager` in [`package.json`](../../package.json), via `corepack enable` | `pnpm -v` |
53
+ | {Docker / Rust / wrangler / …} | {pinning file, or "any current"} | `{command}` |
54
+
55
+ - **Access:** {repo, secrets store, cloud account, registry token, and who grants each}.
56
+
57
+ ## Before cloning ← delete if none
58
+
59
+ - **{Trap}:** {what a fresh clone hits and the one command that clears it, e.g. `git lfs install`, `git submodule update --init`}.
60
+
61
+ ## Install
62
+
63
+ \`\`\`bash
64
+ git clone {url} && cd {repo}
65
+ corepack enable
66
+ {pm} install # expect: {what a clean install ends with}
67
+ \`\`\`
68
+
69
+ ## Environment files ← delete if none
70
+
71
+ | File | Copy from | Fill | Values come from | Required to boot |
72
+ | --- | --- | --- | --- | --- |
73
+ | `{path/.dev.vars}` | `{path/.dev.vars.example}` | {keys, or "every blank"} | {vault, the owner, a generated local value} | {yes / no} |
74
+
75
+ The contract is [`{example file or typed Env}`](../../{path}). Read it before concluding a value is missing. {Which of these files are gitignored.}
76
+
77
+ ## Local services ← delete if none
78
+
79
+ | Service | Start | Port | Ready when |
80
+ | --- | --- | --- | --- |
81
+ | {local DB / emulator} | `{command}` | {port} | `{probe}` returns {expected} |
82
+
83
+ ## First run
84
+
85
+ 1. Prepare local state.
86
+
87
+ \`\`\`bash
88
+ {pm} --filter {unit} {migrate-and-seed} # expect: {output}
89
+ \`\`\`
90
+
91
+ 2. Start the {backend}.
92
+
93
+ \`\`\`bash
94
+ {pm} --filter {unit} {dev:server} # expect: listening on :{port}
95
+ \`\`\`
96
+
97
+ 3. Start the {frontend / CLI}.
98
+
99
+ \`\`\`bash
100
+ {pm} --filter {unit} {dev} # expect: {URL}
101
+ \`\`\`
102
+
103
+ 4. Open `{http://localhost:port}` and {sign in as `{seeded user}` / reach `{first screen}`}.
104
+
105
+ ## Verify
106
+
107
+ - `{curl -fsS http://localhost:{port}/{health}}` returns `200` {and `{body}`}.
108
+ - `{doctor or status command}` reports {expected}. ← keep whichever exists
109
+ - `{pm} {test}` passes from this cold shell ({expected tail}).
110
+
111
+ ## Reset ← delete if none
112
+
113
+ | Command | Deletes | Prompts? |
114
+ | --- | --- | --- |
115
+ | `{pm} {reset-script}` | {local state at `{path}`} | {yes; `{FORCE=1}` skips / no} |
116
+
117
+ ## Common failures
118
+
119
+ - **`{exact error text}`.** {Cause.} Fix: `{command or file edit}`.
120
+
121
+ ## Next
122
+
123
+ The daily loop and its per-package traps: [`local-development.md`]({local-development}.md). Deploying: [`deployment.md`](deployment.md). Standing rules: [`CLAUDE.md`](../../CLAUDE.md).
124
+ ```
125
+
126
+ ### Baseline scaffolding behavior
127
+
128
+ The baseline scaffolds `docs/operations/setup.md` when it is missing and the repo has a lockfile and at least one runnable root script. It fills each section from the repo:
129
+
130
+ - **Stack:** from the workspace manifests, one row per layer.
131
+ - **Prerequisites:** from the pinning files.
132
+ - **Install and First run:** from the root README's getting-started block (if one exists) and the root scripts.
133
+ - **Environment files:** from every `*.example` / `.dev.vars.example` in the workspace.
134
+ - **Verify:** from a health route, a doctor command or the test script.
135
+
136
+ It leaves Common failures empty until a failure is root-caused, and it drops every section it cannot fill concretely.
137
+
138
+ **It never overwrites an existing `setup.md`.** If the repo already has a first-run procedure under another name, the baseline proposes the rename with a `note:` row and does not create a second file.
@@ -1,143 +1,81 @@
1
1
  # System Documentation (docs/architecture/systems/{system}.md)
2
2
 
3
- Truth document. Use for: **one machine that spans packages** — exactly how it works, end to end, in one place. One file per machine, named for the machine (`docs/architecture/systems/update-engine.md`). It states the machine's model and its whole path: what enters it, every stage it passes through, what it writes, what re-drives it when it stalls, and what a reader sees at the far end.
3
+ Truth document. Use for: **one machine that spans packages**, which a person cannot point at — the walk, the egress, the ingest, the settlement, a gate, a sweep, a door an agent calls. One file per machine, named for the machine. A thing a person navigates to is a feature document, even when it owns tables; a unit of distribution is a package document.
4
4
 
5
- **A system document's globs win by specificity.** Its `owns:` names the subtrees and exact files the machine is made of — `packages/studio/src/server/execution/**`, `packages/ui/src/shared/harnessVocabulary.ts` — and those are narrower than the package document's `packages/studio/**`, so the system takes them and the package keeps the residue. That is the whole mechanism: **the package document is the residual owner and the system document is the specific one**, and nothing needs to be subtracted by hand. A machine confined to one package still gets a system document if the machine is the thing worth stating; it is the *narrower glob* that makes it a system, not the package count.
5
+ **A document is read by people, and its footer is for the agent** (`references/style-guide.md` § Owning documents — the body and the footer). A system document explains a machine to a person: what it is for, why it is split where it is split, how it behaves from the outside, what it guarantees at the far end, what re-drives it when it stalls. Its stages, tables, routes, frames, bindings and files are the code graph's (`docs/architecture/systems/knowledge-layer.md`), not a hand-typed tour. The body names code only at a cross-cutting seam another machine or feature would not find from its own files.
6
6
 
7
- **Two rules bind the globs.** Neither genre may claim a path another document claims at **equal specificity** — equal-specificity overlap is an ownership conflict to resolve before either document ships. And every glob **matches at least one file on disk** at `status: active`; projected globs are permitted only at `draft` and are confirmed when the document flips. Because a system's `owns:` list is long and hand-assembled, re-glob it whenever the machine's code moves — a stale entry here silently un-owns real code back to the package document, which does not describe it.
7
+ **A system document's deepest layer is the machine's behaviour across packages** (`references/style-guide.md` § Shape — the model first, the detail after): the order it runs in, the sequence and state diagrams at role level, the invariant that holds at each place where parts meet, and what re-drives a stall. That layer is earned because no single file shows a cross-package flow. It stops before per-function steps, tables, columns and routes.
8
8
 
9
- **How this differs from its neighbours — and the mistake this template exists to prevent.** A **feature** document covers one capability or one page a person names and owns that surface's globs. A **package** document covers one unit of distribution and owns what is left of its tree. A **system** document covers a *machine*: something with an entry, stages, state and an outcome, which a person does not open and cannot point at. **The failure mode is a system document written as a giant feature document** — a tour of screens and what each button does, at ten times a feature doc's length. The test is mechanical: if the subject can be named by an address a person navigates to, it is a feature; if it can be named only as a verb over the product's own nouns — the walk, the egress, the ingest, the settlement — it is a system. A system document says what a surface *renders from* and links to the feature document for what the surface looks like; it never describes the surface.
9
+ **A system document's globs win by specificity.** Its `owns:` names the subtrees and exact files the machine is made of, narrower than the package glob. Two documents never claim a path at equal specificity; every glob matches a file on disk at `status: active`.
10
10
 
11
- **Required vs optional.** Required in every system document: the **frontmatter**, the **opening statement** (what the machine is, then what this document states end to end), the **boundary paragraph** (what this document does not restate, and which document holds each part), the **machine diagram**, at least one **stage section**, **Files**, and **Related**. Everything else is optional. Do not add a section because it seems owed — a stage the machine does not have is a section that will be filled with something untrue.
11
+ **Sharp, bulleted, labelled with noun phrases** (`references/style-guide.md` § Labels). The opening paragraph defines the machine; everything after it is bullets under noun-phrase headings, each bullet a bold noun-phrase label followed by one or two sentences.
12
12
 
13
- System documents are long by nature, because the point is that the whole machine is in one place — roughly 300 to 1000 lines. Length is earned by stages, never by restating a neighbour: every paragraph that could have been a link to the document that owns it is the genre's characteristic waste.
13
+ **Sections:** the frontmatter and the opening paragraph (the machine defined in its first sentence, what enters, what it leaves behind) are required. Then:
14
+
15
+ | Section | When |
16
+ | --- | --- |
17
+ | `Scope` | required. What this document does not decide, and which document does — subjects with owners, never bare links |
18
+ | `Flow` | required |
19
+ | `Decisions` | once any choice was made that the code cannot explain, including why this is one machine and not two |
20
+ | `Promises` | required |
21
+ | `Gaps` | only when there is one |
22
+ | `For the agent` | required |
23
+
24
+ Nothing else. The lint rules of the feature template apply. Sixty to a hundred and sixty lines.
14
25
 
15
26
  ```yaml
16
27
  ---
17
- owns: # required — the machine's subtrees and exact files; narrower than the package glob
28
+ type: system # required tooling key
29
+ status: active # required — draft = the machine as a whole does not run
30
+ objects: [run, run ledger, settlement] # required — the objects this machine owns or moves
31
+ owns: # required until the graph computes ownership — narrower than the package glob
18
32
  - packages/{pkg}/src/{machine}/**
19
- - packages/{pkg}/src/routes/{machine}.ts
20
- - packages/{other}/src/shared/{machine}Vocabulary.ts
21
- keywords: [machine name, its nouns, its verbs] # required — discovery terms: the machine's own vocabulary, the table and route names
22
- status: active # required — active | draft | deprecated
23
- applies: # optional — the decisions and doctrine this machine is BOUND by (obligation, not a bibliography)
33
+ applies: # optional — decisions and doctrine this machine is BOUND by
24
34
  - docs/architecture/decisions/AD-0NN-{slug}.md
25
- - docs/architecture/common/{doctrine}.md
26
- type: system # required tooling key — genre stamp; preserve on edits, never narrate
27
35
  ---
28
36
  ```
29
37
 
30
- > A system document carries no `module:` — a machine that spans packages belongs to no single
31
- > bounded context, and labelling it with one asserts a boundary it crosses by definition.
32
- > `last-reviewed:` is optional tooling metadata: preserve it, never narrate it.
33
-
34
38
  ```
35
39
  # {The machine}
36
40
 
37
- {One paragraph that defines the machine in its own first sentence — bold the term being defined —
38
- then says what this document states, in the order the body states it. The enumeration is the
39
- contract: a reader who wants one stage finds it by reading this sentence. Where the machine's
40
- purpose is easier stated as an outcome, lead with `**Goal:**` and one sentence instead.}
41
-
42
- {One paragraph: the boundary. What this document does **not** restate, and which document holds
43
- each part — the neighbouring systems, the package documents whose residue this sits inside, the
44
- feature documents that render from it, the common-plane doctrine it obeys, the decision records
45
- behind its shape. Name each with a link and the subject it holds. This paragraph is what keeps the
46
- document from growing into its neighbours.}
47
-
48
- ```text
49
- {The machine diagram. One fenced block, drawn as the thing flows — entry at the top or left,
50
- each stage a box or a labelled arrow, the durable writes named, the re-drive path shown returning.
51
- Label the arrows with what crosses them, not with verbs. This is the picture a reader holds while
52
- reading the rest, so it carries the machine's real names — routes, tables, classes, files — and
53
- not generic boxes.}
54
- ```
55
-
56
- {Optional, and worth its line whenever the body names paths: "Every path below is relative to
57
- `packages/{pkg}/src/{dir}/` unless it names another package."}
41
+ {The machine defined in its first sentence — bold the term — then what it takes in, what it leaves behind, and what a reader sees at the far end. Plain words.}
58
42
 
59
- {Optional: a reading order for a long document — "§ X is the data; § Y is the code that reads it;
60
- § Z is what re-drives it" — where the section list is not self-evidently a sequence.}
43
+ ## Scope
61
44
 
62
- ## The shape
45
+ - **Covers:** {what this machine decides}
46
+ - **Not here:** {subject} — {owning document}; {subject} — {owning document}
63
47
 
64
- {Optional. Where the machine has parts a reader must hold at once before any stage makes sense,
65
- name them in one table before the stages begin.}
48
+ ## Flow
66
49
 
67
- | Part | Where | What it holds |
68
- | --- | --- | --- |
69
- | {Entry} | `routes/{x}.ts` | {thin, tenancy first} |
70
- | {Ledger} | `{machine}/ledger.ts` | {the durable row} |
50
+ ### {Stage as a noun phrase — e.g. "Intake", "Settlement", "Re-drive"}
71
51
 
72
- ## {Stage sections — one per stage, in the order the machine runs them}
52
+ - **{Noun-phrase label}:** {what starts it or what it does at this step, as a person would describe it; what it writes that outlives it; what it refuses.}
73
53
 
74
- {The body, and the only genre where the section order is decided for you: the machine's own order.
75
- Entry, then each stage, then what is written durably, then what re-drives a stalled one, then what
76
- reads the result. Name each section for its stage in the product's own vocabulary. Within a
77
- section, state the mechanism and its reason: what the code does, what it refuses, and why it
78
- refuses that rather than something else. Tables for rosters (routes, columns, frames, states,
79
- bindings); prose for a rule and the defect it prevents. Never paste an implementation — a
80
- signature, a state list, a wire shape, a table's columns.}
54
+ {A role-level sequence or state diagram where the stages cross packages.}
81
55
 
82
- ## Tests
56
+ ## Decisions
83
57
 
84
- {Optional. What proves this machine, and what each suite pins — a `Suite | Pins` table. Include it
85
- where the machine has a suite of its own; omit the heading where the coverage lives in the package
86
- documents' suites.}
58
+ - **{The decision as a noun phrase}:** {why; the alternative only where a reader would reach for it.}
87
59
 
88
- ## Files
60
+ ## Promises
89
61
 
90
- | Path | Role |
91
- | --- | --- |
92
- | `packages/{pkg}/src/{machine}/{file}.ts` | {what it holds, by name — the exports a reader is looking for} |
62
+ - **{Noun-phrase label}:** {a checkable guarantee or refusal; what holds at the far end; what a stalled run gets.}
93
63
 
94
- {One row per file this document owns — the roster is the `owns:` list, made readable. Close with
95
- the inverse: "Read here, owned elsewhere:" naming the paths the body describes but another document
96
- claims, each with the document that claims it. That closing line is what stops a system document
97
- from quietly annexing the code it reads.}
64
+ ## Gaps
98
65
 
99
- ## Related
66
+ - **{Noun-phrase label}:** {what is missing and what it would take.}
100
67
 
101
- - [AD-0NN — {the ruling}](../decisions/AD-0NN-{slug}.md) — {the decision behind this shape, the options weighed}
102
- - [`{neighbour}.md`]({neighbour}.md) — {the machine on the other side of this seam}
103
- - [`{feature}.md`](../../features/{feature}.md) — {what a person sees of this machine}
104
- - [`{doctrine}.md`](../common/{doctrine}.md) — {the cross-cutting contract this machine answers to}
105
- ```
68
+ ## For the agent
106
69
 
107
- ### The boundary paragraph is the genre's load-bearing section
108
-
109
- Systems overlap: they share tables, call each other, and render into the same surfaces. Without a
110
- paragraph that names the seams, two system documents describe the same stage from two angles and
111
- drift apart on the first change — and a reader has no way to tell which is authoritative. So the
112
- boundary paragraph is not a courtesy list of related reading; it is the statement of what this
113
- document is *not*, written specifically enough that a later editor can tell where to put a fact.
114
- Write it as a list of subjects with their owners — "the coordinator's tables, alarm and drive claim
115
- are `harness.md`; a run's ledger row and settlement are `generation-runs.md`" — never as bare
116
- links.
117
-
118
- ### Marking what is decided and unbuilt
119
-
120
- Where the machine has a stage that is decided and not built — a predicate that selects but never
121
- acts, a column that is written and never read, a door with no caller — wrap the prose in a marker
122
- so the gap is machine-findable and its evidence travels with it:
70
+ - **Objects:** {…}
71
+ - **Code roots:** {…} — directories, one per package the machine spans
72
+ - **Seams:** {…} by name
73
+ - **Checklist:** `tests/{system}.md`
74
+ - **See also:** {neighbour}: {why}
123
75
 
76
+ No tables, routes or symbol rosters — those are the graph's.
124
77
  ```
125
- <!-- UNBUILT:START — {what is decided, where it is decided (an AD § or an owner ruling), and the
126
- source evidence that it is not built: the function with no caller, the route that is not mounted,
127
- the value written and never read} -->
128
- {the prose describing the unbuilt stage, and what runs in its place}
129
- <!-- UNBUILT:END -->
130
- ```
131
-
132
- **State what runs instead.** A machine with a hole in it still works somehow, and the workaround is
133
- the fact a reader needs. **A design decided *against* carries no marker** — a marker means the work
134
- is owed and absent, so using one for a rejected design turns the register of debt into a register
135
- of opinions.
136
78
 
137
- ### `status: draft` on a system
79
+ ### Marking what is decided and unbuilt
138
80
 
139
- A system document is `draft` when the **machine as a whole** does not run — the code is on disk and
140
- nothing reaches it. Say so in the first section, in plain words, with the evidence: which halves
141
- exist, which do not, and what a reader who invokes it actually observes. A scoped gap in a working
142
- machine is not a draft: the document stays `active` and takes an UNBUILT marker at the stage that
143
- has the hole.
81
+ Where a stage is decided and not built, wrap its bullets in `<!-- UNBUILT:START — {what, where decided, the evidence it is not built} -->` … `<!-- UNBUILT:END -->` and say under Promises what runs instead. A design decided *against* carries no marker.
@@ -33,7 +33,7 @@ Parse these from the user's prompt; use the default when unstated.
33
33
 
34
34
  1. If `./docs/memory/change-review.md` exists, read it for historical velocity snapshots, prior risk-zone flags, known concentration risks, and the project's **Module Taxonomy** / **Feature Taxonomy**.
35
35
  2. If a CSV from a prior run already exists at the project root (`change-review-YYYY-MM-DD.csv`), prefer it as input and **skip Phase 1** — re-classify only when the requested window changed.
36
- 3. Build the ownership map from feature `owns:` frontmatter — consult the injected ownership index (`glob → doc · module · keywords · status`), or glob `docs/features/**/*.md` and read each doc's `owns:` globs — to map churn to owning feature docs and their `module:` labels.
36
+ 3. Build the ownership map from feature `owns:` frontmatter — consult the injected ownership index (`glob → doc · module · objects · status`), or glob `docs/features/**/*.md` and read each doc's `owns:` globs — to map churn to owning feature docs and their `module:` labels.
37
37
 
38
38
  ---
39
39
 
@@ -21,7 +21,7 @@ Map the documentation landscape — what exists, what is adjacent, how detailed
21
21
  2. Locate the repo's feature-doc layer from `structure.md` — the standard shape is `./docs/features/`, but a repo may document components under their own subject folders. Read that layer's index if it has one; otherwise glob for docs carrying `owns:` frontmatter
22
22
  3. If `./docs/memory/lld-mode.md` exists (or the legacy `./docs/memory/spec-mode.md`), read it for feature doc inventory, ownership conflict zones, and lessons from previous research
23
23
  4. Read 1-2 existing feature LLDs from that layer to calibrate format and depth
24
- 5. Consult the **injected ownership index** (the generated `glob → doc · module · keywords · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. It is the source of truth for what code paths are already owned. If the index isn't present in context, glob the docs tree (excluding `docs/history/`) and read the `owns:` frontmatter of every doc that declares it.
24
+ 5. Consult the **injected ownership index** (the generated `glob → doc · module · objects · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. It is the source of truth for what code paths are already owned. If the index isn't present in context, glob the docs tree (excluding `docs/history/`) and read the `owns:` frontmatter of every doc that declares it.
25
25
 
26
26
  ## What You Research
27
27
 
@@ -95,8 +95,6 @@ Run `git log --since="2 weeks ago" --name-only --pretty=format:"%h %s"` to find
95
95
 
96
96
  **Unowned paths.** Compare the repo's actual top-level source directories (derive them — the top-level dirs that contain code, or the roots named across the `owns:` globs; do not assume `src/`) against the `owns:` map. Report directories no `owns:` glob covers.
97
97
 
98
- **Stale greenfield self-label.** If `structure.md` asserts the repo is greenfield — _"No source code or feature docs exist yet"_ or similar — **but a real source tree exists** (the derived source roots above are non-empty, e.g. a populated `packages/` of real workspaces), the self-label has gone stale. Raise it as a question (e.g. `structure.md says "No source code exists yet" but packages/ holds 5 workspaces — confirm the greenfield label should be retired`).
99
-
100
98
  **Architecture drift.** Grep `docs/architecture/` for file-path references. Verify referenced paths still exist. Remove or update stale references.
101
99
 
102
100
  **Backlog health.** Read `docs/history/backlog.md`. Report items older than 30 days. Count pending by priority.
@@ -117,7 +115,7 @@ For an unowned code **region**, append: `- **[P2]** No feature doc owns \`{dir}/
117
115
 
118
116
  ### Step 6: Report & update tracking
119
117
 
120
- 1. Update `docs/structure.md` Health Log with today's date and summary — **append to the end**, never date-sorted into the middle. Rows are positional: one may say "the row above is…", and an inserted row silently breaks that reference. A Health Log entry is a **generated row, not a narrative essay**: one line — date · counts (stale docs fixed, dead globs, unowned paths, backlog items created) · links to anything that needs a human.
118
+ 1. Append today's row to `docs/history/health-log.md` — **append to the end**, never date-sorted into the middle. Rows are positional: one may say "the row above is…", and an inserted row silently breaks that reference. A Health Log entry is a **generated row, not a narrative essay**: one line — date · counts (stale docs fixed, dead globs, unowned paths, backlog items created) · links to anything that needs a human.
121
119
  2. Update `docs/memory/maintenance.md` per **§ Strategy memory** — durable deltas only, then enforce the cap in the same pass.
122
120
  3. Report findings: stale docs, broken ownership, unowned code, architecture drift, backlog health.
123
121
 
@@ -132,7 +130,7 @@ Baseline mode converges the repo's `docs/` to the **installed** harness shape, t
132
130
  ```
133
131
  docs/
134
132
  ├── README.md ✱ # Documentation root — quick links, section index
135
- ├── structure.md ✱ # Authority map + frontmatter `harness-version` (you own this field)
133
+ ├── structure.md # Harness-owned authority map — the installer writes it on every refresh; you stamp only `harness-version`
136
134
  ├── architecture/ # Cross-module design + steering layer
137
135
  │ │ # domain-model, glossary, non-goals, references, open-questions
138
136
  │ └── decisions/ # Architecture Decisions (ADs — one per subject, updated in place; journey in each AD's Decision Changelog)
@@ -156,7 +154,7 @@ docs/
156
154
  └── tests/ # Behavioral test checklists ({feature}.md, step → **Assert**), derived at plan Completion via the `documentation` skill; author-maintained
157
155
  ```
158
156
 
159
- **✱ marks the five scaffolded files — the only paths a baseline creates, and the only shape signals.** Every **folder** in this tree is created on first use and is simply absent until it holds a file; git cannot track an empty directory, so a missing folder is never evidence of drift and is never scaffolded to satisfy the shape. Record its role in `docs/structure.md` instead.
157
+ **✱ marks the scaffolded files — the only paths a baseline creates, and the only shape signals.** `docs/structure.md` is not one of them: the installer owns it and rewrites it on every install or refresh, so a missing or hand-edited `structure.md` means the harness needs refreshing (`npx @nurix/etna`), never a scaffold from a template — and its body is never converged, only its `harness-version` field stamped. Every **folder** in this tree is created on first use and is simply absent until it holds a file; git cannot track an empty directory, so a missing folder is never evidence of drift and is never scaffolded to satisfy the shape. Its role is already in `docs/structure.md`; a repo's own notes about legacy folders go in `docs/README.md` § Notes for this repository.
160
158
 
161
159
  There is **no `docs/routing.md`**, **no `docs/modules/{m}/`**, **no `docs/pillars/`**, **no `docs/boundaries/`**. Code ownership lives in feature `owns:` frontmatter; a module is a `module:` label, not a folder; boundaries are diagnosed from source; brainstorm records live in `docs/research/` (active) and `docs/history/brainstorms/` (harvested).
162
160
 
@@ -192,7 +190,7 @@ B2 folds artifacts whose **shape dissolved** — a file in the wrong place or th
192
190
 
193
191
  | Nature | Genres | Treatment |
194
192
  | --- | --- | --- |
195
- | **Truth document** | features, ux, architecture, operations, `docs/tests/` checklists, `structure.md`, READMEs | **Converge in place.** These state what is true now, so rewriting them to the current schema is not revision, it is the genre working as designed. Add missing frontmatter keys, add missing required sections, rename keys the template renamed |
193
+ | **Truth document** | features, ux, architecture, operations, `docs/tests/` checklists, READMEs (never `structure.md`, which the installer owns) | **Converge in place.** These state what is true now, so rewriting them to the current schema is not revision, it is the genre working as designed. Add missing frontmatter keys, add missing required sections, rename keys the template renamed |
196
194
  | **Record** | plans, changelog entries, migration runbooks, brainstorm records | **Never rewritten.** A completed plan and a committed entry are frozen — immutability begins at commit, and a record edited to match a newer schema stops being evidence of what happened. Report non-conformance; repair only the **living index** that points at the record (an absent `docs/history/CHANGELOG.md` row is an index defect, not a record defect, and is backfilled with a note saying so) |
197
195
 
198
196
  **Never invent content to satisfy a field.** A frozen changelog entry missing `Skills:` is missing the *judgement* that field carries, and no later session holds it — writing one is fabrication wearing a schema's clothes. Report it, backlog the pattern if it recurs, and leave the entry alone. The same restraint applies to a truth document: a genre's new section that needs knowledge the repo does not contain is raised as a question, not filled with plausible prose.
@@ -203,9 +201,9 @@ B2 folds artifacts whose **shape dissolved** — a file in the wrong place or th
203
201
 
204
202
  Table: `| File | Action | From | To | Reason |` (actions: `Move`, `Merge into {target}`, `Delete`, `Keep`, `Create`, `Fold`). For a fresh baseline this is mostly `Create`; for an upgrade it is mostly `Fold`/`Move`. Ask once: **"Approve this reconcile?"** — you own this interaction (the `documentation` skill is a library and has none).
205
203
 
206
- On approval, execute: create the folder structure; move/fold/merge/delete per the plan; apply B2b's schema convergences to the truth documents (records are reported, never rewritten); add `Status:` to plan files; for each feature doc, derive and write its `owns:` globs (+ `module:` label + `keywords:`) from the source it describes, and each checklist's `verifies:` edge, by calling the `documentation` skill's **frontmatter derivation**; merge scattered backlogs into `docs/history/backlog.md`; fix links broken by moves.
204
+ On approval, execute: create the folder structure; move/fold/merge/delete per the plan; apply B2b's schema convergences to the truth documents (records are reported, never rewritten); add `Status:` to plan files; for each feature doc, derive and write its `owns:` globs (+ `module:` label + `objects:`) from the source it describes, and each checklist's `verifies:` edge, by calling the `documentation` skill's **frontmatter derivation**; merge scattered backlogs into `docs/history/backlog.md`; fix links broken by moves.
207
205
 
208
- Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates: `docs/structure.md` (with `harness-version`), `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`, and the repo-root `README.md` (filled from the real lockfile/scripts/layout — **never overwrite an existing root README**).
206
+ Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates: `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`, `docs/operations/setup.md` (when the repo has a lockfile and a runnable root script; **never a second first-run doc** — propose a rename with a `note:` row if one exists under another name), and the repo-root `README.md` (an outward opening in a user's terms from the charter and vision documents, then orientation and routing filled from the manifests, the ownership index and the root scripts — **never overwrite an existing root README**).
209
207
 
210
208
  ### Step B4 — Stamp the version
211
209
 
@@ -237,7 +235,7 @@ Apply the **§ Strategy memory** retirement procedure to `docs/memory/maintenanc
237
235
  - **Enforce the memory cap on every run** (§ Strategy memory) — you are its only writer, so no one else can do it.
238
236
  - **A clean report is valid** — do not invent issues.
239
237
  - **Declarative, idempotent.** Re-running baseline mode on a current repo reshapes nothing — a second pass is just the audit plus the module proposal. Converge to the current shape; never replay a version ladder; never reconstruct a past shape.
240
- - **Brownfield extraction (operator-ruled 2026-08-19).** When baseline mode meets a repo with a real source tree and few or no feature docs, the module *proposal* is not enough — run the extraction pass: produce feature docs for the recognized modules (docs/features/, full frontmatter: `owns:` · `module:` · `keywords:` · `status:` · `last-reviewed:` · `type: feature` · `derivation: "extracted (baseline YYYY-MM-DD, nustack graph + source read)"`), plus the architecture, tests, and operations layers. Use the `nustack-graph` skill where installed — localize through the index before reading; the docs record intent, the index answers facts. **Every extracted feature doc carries a `## History & Ownership` section** — top contributors with recency, churn posture, and bus-factor notes, dated "as of YYYY-MM-DD" (operator ruling: this section is mandatory in extraction output even though doc-lint flags dated narrative in truth docs; the findings are accepted for now, and a future harness version may retire the section in favor of live index pointers). `status:` is evidence-graded: `deprecated` only when history shows the area dead, never by guess. Scale by fan-out (one extraction lane per module, a completeness critic over the result) rather than one long cold read.
238
+ - **Brownfield extraction (operator-ruled 2026-08-19).** When baseline mode meets a repo with a real source tree and few or no feature docs, the module *proposal* is not enough — run the extraction pass: produce feature docs for the recognized modules (docs/features/, full frontmatter: `objects:` · `owns:` · `module:` · `status:` · `last-reviewed:` · `type: feature` · `derivation: "extracted (baseline YYYY-MM-DD, nustack graph + source read)"`), plus the architecture, tests, and operations layers. Use the `nustack-graph` skill where installed — localize through the index before reading; the docs record intent, the index answers facts. **Every extracted feature doc carries a `## History & Ownership` section** — top contributors with recency, churn posture, and bus-factor notes, dated "as of YYYY-MM-DD" (operator ruling: this section is mandatory in extraction output even though doc-lint flags dated narrative in truth docs; the findings are accepted for now, and a future harness version may retire the section in favor of live index pointers). `status:` is evidence-graded: `deprecated` only when history shows the area dead, never by guess. Scale by fan-out (one extraction lane per module, a completeness critic over the result) rather than one long cold read.
241
239
  - **Diagrams ride the baseline (operator-ruled 2026-08-24).** Whenever baseline mode produces or converges the architecture layer, draw two ASCII diagrams from the real source, each in its own fenced code block: (1) an **architecture diagram** in the system-design/architecture doc — the actual processes, entry points, and wire surfaces as boxes, the calls/queues/files between them as labelled arrows; (2) a **DB ER diagram** wherever the repo declares a relational schema (DDL, migrations, an ORM schema) — one box per table listing its key columns, FK edges drawn to the table they reference, cardinality on the edge; it lands in the domain-model doc, or `docs/architecture/data-model.md` when none exists. Box-drawing characters (`┌─┐│└┘├┤`), width ≤ 100 columns. Derived only from what the code declares — a diagram never invents a component the source does not show, and a repo with no relational schema gets **no** ER diagram rather than an imagined one. Diagrams are truth-document sections: later baselines and audits converge them in place like any other section.
242
240
  - **Tool tiers.** The SessionStart context names each manifest-declared tool with its tier; calibrate the run to it, never stall on it. **Present-fresh** (`Tool: nustack 0.9.0`): use it — localize every question through `nustack graph` before reading source, and never run an index step first: the family re-indexes a stale store before it answers, so the only freshness decision left is the deliberate `--no-refresh`. **Present-stale** (below the catalog minimum): still use it, but note the version gap and the upgrade command in the run report — a stale contract may lack answer shapes the skill assumes. **Absent** (`Tool: nustack MISSING`): fall back to the cold method (Glob/Grep/read), state in the run report that the tool was absent and give the install command — degraded output is acceptable, silent degradation is not.
243
241
  - **One sentinel.** `docs/structure.md` `harness-version` is the only baseline/version marker.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "harness": "etna",
3
3
  "name": "etna",
4
- "version": "1.5.26",
4
+ "version": "1.5.28",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
@@ -10,5 +10,5 @@
10
10
  "seeds": [],
11
11
  "tools": [],
12
12
  "docsRoot": "docs",
13
- "digest": "6448aac5edb5"
13
+ "digest": "6a10dd14cf28"
14
14
  }
@@ -7,7 +7,7 @@ description: "Use when creating or substantively editing ANY markdown doc — in
7
7
 
8
8
  **This skill is a template & generator library, not an orchestrator.** It supplies the templates, the frontmatter-derivation generator, and the co-authoring workflow that _agents_ call to produce individual docs. It does **not** baseline, audit, or reconcile a repo's doc tree — that is the **`maintenance` agent (baseline mode)**, which calls this skill for each template it scaffolds. Reach here to generate _one_ doc from a template; reach for the `maintenance` agent (baseline mode) to bring a whole repo into shape.
9
9
 
10
- Document contracts and architecture, not implementation details. Show function signatures and API shapes — never paste full implementations (they rot fast). Use ASCII diagrams over prose for flows. Only document state at persistence boundaries (Redux persistence, DB schemas, API shapes), not component-level or transient state. Mark deprecated fields with `// UNUSED:` comments stating why the field is dead now — never where it went or when it dies. Breaking changes belong in changelogs only, not module docs.
10
+ Document contracts and architecture, not implementation details. Signatures and API shapes belong in a reference document (an API reference, an environment registry); every other genre states design and promises and leaves mechanism to the code — never paste full implementations (they rot fast). A diagram sits beside the prose and never replaces it: ASCII for structure at rest, mermaid for behaviour over time (`references/style-guide.md` § Diagrams). Only document state at persistence boundaries (Redux persistence, DB schemas, API shapes), not component-level or transient state. Mark deprecated fields with `// UNUSED:` comments stating why the field is dead now — never where it went or when it dies. Breaking changes belong in changelogs only, not module docs.
11
11
 
12
12
  ---
13
13
 
@@ -42,9 +42,9 @@ Document contracts and architecture, not implementation details. Show function s
42
42
  | "Folded in from the `NuStack-X` repo (2026-06-12)." | "Vendor-connector catalogue; one subpath per vendor." |
43
43
  | "was X, now Y", "the old worker", "Phase 2 softened this", "v1 → v2" | The current fact, with no predecessor named |
44
44
 
45
- The journey — dates, migrations, progress, supersessions — lives only in records (`docs/history/`); when reality changes, a truth document simply becomes correct. The full strip-list and the record-side rules: [`references/style-guide.md`](references/style-guide.md) § The Two Natures — Tense & History.
45
+ The journey — dates, migrations, progress, supersessions — lives only in records (`docs/history/`); when reality changes, a truth document simply becomes correct. The full strip-list and the record-side rules: [`references/style-guide.md`](references/style-guide.md) § The Two Natures — tense and history.
46
46
 
47
- **A date in a truth document is a defect, and the list of exceptions is closed.** Not a softened preference: a truth document carries no dated line at all, because a date answers *when did this happen*, which is a record's question, and a reader who needs the answer is reading the wrong file. The four exceptions, and there are no others: the frontmatter's tooling keys (`last-reviewed:`, `last-updated:`, `rev:` — written by tooling, never by you), an Architecture Decision's **Decision Changelog** tail, `docs/structure.md`'s **Health Log** tail, and a dated path inside a link or code span, which is a *citation* of a record rather than a claim about the present.
47
+ **A date in a truth document is a defect, and the list of exceptions is closed.** Not a softened preference: a truth document carries no dated line at all, because a date answers *when did this happen*, which is a record's question, and a reader who needs the answer is reading the wrong file. The three exceptions, and there are no others: the frontmatter's tooling keys (`last-reviewed:`, `last-updated:`, `rev:` — written by tooling, never by you), an Architecture Decision's **Decision Changelog** tail, and a dated path inside a link or code span, which is a *citation* of a record rather than a claim about the present. The `maintenance` agent's Health Log is a record of its own (`docs/history/health-log.md`), not a tail on a truth document.
48
48
 
49
49
  **Cite a record by what it is, never by when it was.** `the dev reset runbook` links to the file; "the 2026-09-13 reset" states a date the reader must now keep in their head and that goes stale as soon as a second reset happens. The link carries the date in its path, where it belongs, and the prose stays true forever.
50
50
 
@@ -70,9 +70,14 @@ The two guarantees are complementary and both break on mixing: a reader holding
70
70
 
71
71
  - **Truth documents never narrate history** — the § Present tense, always rule above, applied to this nature. When the system changes, the change-story goes to `docs/history/` (a changelog entry) and the truth document simply becomes correct in present tense. When you find historical narration in a truth document, rewrite it to the present-tense fact and let the record carry the story.
72
72
  - **Records are never edited to match the present.** A completed plan stays wrong-in-hindsight; a changelog entry describes close-time state; a scope change gets a *new* dated record that links back, never an edit to a frozen one.
73
- - **Two sanctioned bridges — head is truth, tail is provenance.** An **Architecture Decision (AD)** ends with a **Decision Changelog** (for a decision, the journey — what each revision reversed and what triggered it — is part of the reasoning), and `docs/structure.md` ends with the maintenance agent's **Health Log** (tooling-stamped audit rows, the structural cousin of `last-reviewed:`). In both, the body stays current-truth-only; the tail carries the dates. No other truth document carries dated history.
73
+ - **Two sanctioned bridges — head is truth, tail is provenance.** An **Architecture Decision (AD)** ends with a **Decision Changelog** (for a decision, the journey — what each revision reversed and what triggered it — is part of the reasoning), and the `maintenance` agent's **Health Log** lives in `docs/history/health-log.md`, an append-only record. The AD body stays current-truth-only; the tail carries the dates. No other truth document carries dated history. `docs/structure.md` is harness-owned — written whole by the installer, never edited by hand or by a skill; only its `harness-version` frontmatter is stamped, by the `maintenance` agent.
74
+ - **Indexes describe directories, never files.** `docs/README.md` — the top-level index of the documentation folder — is a description of its directories: one entry per folder saying what the folder holds, who reads it and how its files are named. It carries no file list and no file tree: not a per-file row, not a `├──` tree of files, not a tree at all — `docs/structure.md` is the one place the tree lives, as the authority on placement. The same holds for a `README.md` / `Readme.md` at any level of `docs/`. `ls` is the roster, and the ownership index is how a document is found for a path. A per-file row has to be edited on every add, rename and retirement, so the index's history records roster churn instead of what the index said, and a reader cannot tell when the index itself changed. The only files an index may link are the mandated scaffolds (`structure.md`, `operations/setup.md`, `history/CHANGELOG.md`, `history/backlog.md`, `memory/main.md`) and a sibling folder's own `Readme.md`. `scripts/doc-lint.mjs` blocks the rest as `index-lists-files`, and blocks a tree drawn in a folder index as `index-file-tree`. An inverse (which checklists verify a feature, which docs a folder holds) is generated, never written.
74
75
  - **Truth documents cite records for the _why_, never the _when_.** `Provenance: AD-002` is good; "decided in AD-002 and shipped 2026-06-13" is not. Routing/index docs point only to truth documents as a topic's authority — never a plan or changelog entry as the "read first" source. (An index _of the records themselves_ — a History section listing `plans/`, `changelog/` — is sanctioned.)
75
76
 
77
+ **A document is intent and promises; facts are the graph's.** An owning document (feature, package, system) answers why the product is shaped this way and what it promises, and names the objects it designs in `objects:`. Every computable fact — a table's columns and vocabularies, a foreign key and its delete rule, which function writes which column, which route sits behind which guard, which code a refusal answers, which file holds what — is the code graph's to compute (`docs/architecture/systems/knowledge-layer.md`), and a hand-typed copy of it is the defect this rule removes: it reads as authoritative and is wrong the day the code moves. Mechanism stays in the code, reasons stay in the document, and the document points by object and symbol name, never by line number. `doc-lint` blocks the retired mechanism sections in an owning document (`mechanism-section`) and an owning document without `objects:`. `keywords:` is not a key: an object's name is its discovery term. **The body is scanned by people** — sharp bullets under noun-phrase headings, each a bold noun-phrase label, a colon, then one or two plain sentences; code named only where a person types or sees it, or at a cross-cutting seam the graph would not lead a reader to (a middleware, a gate, a hook, a shared store); every other pointer in the closing **For the agent** footer. The owning genres read Scope · Flows (Flow for a system, Usage for a package) · Decisions · Promises · Gaps · For the agent (`references/style-guide.md` § Labels, § Owning documents — the body and the footer; `doc-lint` warns `body-identifier`, `clause-label` and `second-person`).
78
+
79
+ **Every document that explains is written from the outside in, and every sentence passes the stability test.** Open on the question and its boundary, then the model with its numbered principles, then the parts and how they relate, then each part's decisions — and stop at the genre's deepest layer: decisions for doctrine, cross-package behaviour for a system, the public contract for a package, the full user-facing behaviour for a feature. A sentence that would have to change when a function is renamed, a file moves, or a route, column or error code changes is the code's, not the document's. The code is the authority on *what*; the document is the authority on *why*, and a disagreement on *why* is a defect to raise. **Every heading and every bold bullet label is a noun phrase** — it names; it has no verb, so it carries no tense, person or voice ("Decisions", never "What was decided"; "Organization user:", never "You already belong to an organization:"), and the sentence after it is third person ("user lands…", never "you land…"). The layers, the test, the label rule and the per-genre depth table are [`references/style-guide.md`](references/style-guide.md) § Shape — the model first, the detail after, and § Labels.
80
+
76
81
  **No empty stubs.** Never leave a template section as an empty placeholder — omit any section with nothing real to say (each template declares its required core; everything else is optional). Write an explicit "None" only where the absence itself is information (e.g., a plan's Cross-Module Contracts Affected, an LLD's Ownership Conflicts). An empty table stub reads as "not yet researched"; an omitted section reads as "doesn't apply" — keep those meanings distinct.
77
82
 
78
83
  **No redirect docs.** When moving a doc to a new location, delete the old file entirely. Update all references (cross-doc links, memory files) to point to the new path. Never leave a stub file that says "Moved to X" — redirect docs rot, clutter the repo, and create false search hits.
@@ -87,6 +92,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
87
92
  | Document feature/module (LLD) | [`templates/feature.md`](templates/feature.md) |
88
93
  | Document data flow / state / Redux | [`templates/feature.md`](templates/feature.md) — they are sections of the feature doc |
89
94
  | Document a workspace package (`docs/architecture/packages/{package}.md`) | [`templates/package.md`](templates/package.md) — the **residual** owner of `packages/{name}/**`: its manifest, build, entry, layout and every behavior no system or feature doc claims at higher specificity |
95
+ | Document one concern the platform handles everywhere (`docs/architecture/common/{concern}.md`) — authentication, storage, the API protocol | [`templates/doctrine.md`](templates/doctrine.md) — the design and its principles, no mechanism; owns no code, and surfaces bind to it through `applies:` |
90
96
  | Document one system spanning packages (`docs/architecture/systems/{system}.md`) | [`templates/system.md`](templates/system.md) — one machine end to end; its `owns:` names the machine's subtrees, narrower than the package glob, so it wins by specificity. Not a screen — a system doc written as a giant feature doc is the mistake it prevents |
91
97
  | Create/update changelog entry | [`templates/changelog-entry.md`](templates/changelog-entry.md) (record — one per unit of work; carries the refinement fields, frozen inside its commit, distilled by the `retro` agent) |
92
98
  | Create/update plan | [`templates/plan.md`](templates/plan.md) (record) |
@@ -102,14 +108,16 @@ The two guarantees are complementary and both break on mixing: a reader holding
102
108
  | What a person sees and can do on a surface (UX behavior) | [`templates/ux-behavior.md`](templates/ux-behavior.md) — decides observable behavior BEFORE the code; per-surface in `docs/features/{surface}-ux.md` owning the component globs, cross-cutting in `docs/architecture/`. Not the checklist, which only verifies it |
103
109
  | Behavioral checklist for one feature (`docs/tests/{feature}.md`) | [`templates/behavioral-checklist.md`](templates/behavioral-checklist.md) — the verification gate's driving script, and the source its suite tests are drawn from |
104
110
  | Acceptance criteria for one capability (`docs/acceptance/{capability}.md`) | [`templates/acceptance-criteria.md`](templates/acceptance-criteria.md) — the promises the built product must keep, as stable `AC-n` keyed assert lines verification surfaces parse as claims |
105
- | Recurring procedure/setup | [`templates/operations-procedure.md`](templates/operations-procedure.md) |
111
+ | Machine setup / first run / stack (one per repo, `docs/operations/setup.md`) | [`templates/setup.md`](templates/setup.md) |
112
+ | Recurring procedure (develop, deploy, rotate, diagnose) | [`templates/operations-procedure.md`](templates/operations-procedure.md) |
106
113
  | Cold-start build order (implementation map) | [`templates/implementation-map.md`](templates/implementation-map.md) — authored by the executing session at build start, updated in place as waves complete |
107
114
  | Capture mid-execution knowledge (`docs/history/journal.md`) | [`templates/journal.md`](templates/journal.md) (record — append-only; a row resolves by landing in its owning doc) |
108
115
  | Bookkeeping work queue (`docs/operations/bookkeeping.md`) | [`templates/bookkeeping.md`](templates/bookkeeping.md) — machine-read row grammar; appended by hooks and sessions, drained by the `bookkeeper` agent, walled at Stop and commit |
109
116
  | One-shot migration/upgrade | [`templates/migration-runbook.md`](templates/migration-runbook.md) (record) |
117
+ | Hand-over at the end of an unattended or multi-session build (`docs/history/handovers/YYYY-MM-DD-{slug}.md`) | [`templates/handover.md`](templates/handover.md) (record) — a decision queue, an undo manual and a resume file: a verdict token and scoreboard, the acts only the owner can take today, everything that left the repository with its exact undo, a ten-minute path to seeing it work, every ruling taken on the owner's behalf with its authority and how to overturn it; then the successor half — proof, state re-provable by command, open loops, discoveries |
110
118
  | Add to protected files | [`templates/protected-files.md`](templates/protected-files.md) |
111
- | Create/update root README | [`templates/root-readme.md`](templates/root-readme.md) |
112
- | Scaffold a standard doc (docs index, `structure.md`, CHANGELOG, backlog, memory) | [`templates/Readme.md`](templates/Readme.md) — the index names each scaffold file |
119
+ | Create/update root README (outward opening in a user's terms, then orientation and routing for the team and agents — no install, stack, tree or chrome) | [`templates/root-readme.md`](templates/root-readme.md) |
120
+ | Scaffold a standard doc (docs index, CHANGELOG, backlog, memory) | [`templates/Readme.md`](templates/Readme.md) — the index names each scaffold file; `structure.md` is the installer's, never scaffolded |
113
121
  | Derive/update an owning doc's `owns:` (feature, package, system) | [`references/frontmatter.md`](references/frontmatter.md) |
114
122
  | Update existing doc | § Editing an existing doc (below) |
115
123
  | Instruction file (`CLAUDE.md`, a rule, an agent, skill prose) | [`references/instruction-style.md`](references/instruction-style.md) — not these templates; every-load prose stays lean, and the present-tense rule still applies |
@@ -135,6 +143,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
135
143
  | Feature (LLD) | Truth | `kebab-case.md` | Living; `status:` `draft` → `active` → `deprecated` |
136
144
  | Package | Truth | `{package-folder}.md` | Living; `status:` as the feature doc |
137
145
  | System | Truth | `{machine}.md` | Living; `status:` as the feature doc |
146
+ | Doctrine | Truth | `{concern}.md` | Living; `status:` `draft` → `active` |
138
147
  | Architecture Decision | Truth | `AD-NNN-kebab-case.md` | Living; `Proposed` → `Accepted` → `Deprecated`; revisions rewrite the body + append to its Decision Changelog |
139
148
  | Steering docs (overview, domain model, glossary, non-goals, security, testing strategy) | Truth | fixed names | Living |
140
149
  | API reference / environment registry | Truth | fixed names | Living |
@@ -153,11 +162,13 @@ The two guarantees are complementary and both break on mixing: a reader holding
153
162
  **Frontmatter is compulsory on every document this skill authors** — `type:` (the genre) on every
154
163
  doc, plus the genre's own keys beside it; a document without its frontmatter fails the skill's
155
164
  contract and is not done. **There is no frontmatter-less genre.** A feature or UX doc carries the
156
- full set — `owns:` (required), `module:` (optional), `keywords:` (required), `status:` (required),
165
+ full set — `objects:` (required — the product objects the document designs), `owns:` (required until the graph computes ownership), `module:` (optional), `status:` (required),
157
166
  `applies:` (the architecture docs it obeys; omitted when none), optional `last-reviewed:`. A
158
167
  **package** doc (`docs/architecture/packages/`) and a **system** doc (`docs/architecture/systems/`)
159
168
  carry the same set minus `module:` — a package is already a bounded unit and a machine spanning
160
- packages belongs to no single context. A behavioral checklist (`docs/tests/`) carries
169
+ packages belongs to no single context. A **doctrine** doc (`docs/architecture/common/`)
170
+ carries `type: doctrine`, `status:` and `objects:` — no `owns:`, because doctrine governs code
171
+ without claiming it. A behavioral checklist (`docs/tests/`) carries
161
172
  `type: checklist` and `verifies:` — the doc whose promises it proves. An acceptance-criteria doc
162
173
  (`docs/acceptance/`) carries `type:` and `status:`.
163
174
 
@@ -175,9 +186,9 @@ update, and the `maintenance` agent's baseline pass, route there.
175
186
  | File | Use For |
176
187
  | --- | --- |
177
188
  | `templates/` | One file per template, indexed by [`Readme.md`](templates/Readme.md) — feature (LLD), changelog, plan, AD, steering docs, API reference, environment registry, operations procedure, migration runbook, protected files, READMEs, and the baseline scaffolds |
178
- | `references/style-guide.md` | Writing rules, formatting conventions, the two-natures tense rules |
189
+ | `references/style-guide.md` | The writing-style authority: the eight principles, depth per genre, the outside-in shape and stability test, noun-phrase labels and third-person voice, the owning document's body and footer, the two-natures tense rules, diagrams, headings, reference-document detail |
179
190
  | `references/instruction-style.md` | The style for instruction files (`CLAUDE.md`, rules, agents, skill prose) — the every-line test, armor vs. narration, voice, negative space |
180
- | `references/frontmatter.md` | Deriving a feature doc's `owns:` / `module:` / `keywords:` / `status:` from code |
191
+ | `references/frontmatter.md` | Deriving a feature doc's `objects:` / `owns:` / `module:` / `status:` from code |
181
192
  | `references/untemplated.md` | How to write a document no template covers (nature, placement, shape) + the co-authoring workflow |
182
193
  | `references/examples.md` | Good vs bad documentation examples |
183
194
  | `scripts/doc-lint.mjs` | Mechanical checks over written docs (tense narration, dates, stubs, redirects) — run over changed docs before finishing |