@nurix/etna 0.20.34 → 0.20.36

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 (160) hide show
  1. package/data/catalog/rules/changelog.md +1 -1
  2. package/data/harness-index.json +1 -1
  3. package/data/harnesses/code/CLAUDE.md +4 -4
  4. package/data/harnesses/code/agents/brainstorm.md +2 -2
  5. package/data/harnesses/code/agents/lld-mode.md +2 -2
  6. package/data/harnesses/code/agents/maintenance.md +17 -17
  7. package/data/harnesses/code/codex/agents/brainstorm.toml +6 -2
  8. package/data/harnesses/code/codex/agents/lld-mode.toml +2 -2
  9. package/data/harnesses/code/codex/agents/maintenance.toml +18 -17
  10. package/data/harnesses/code/docs/README.md +9 -17
  11. package/data/harnesses/code/docs/history/CHANGELOG.md +19 -18
  12. package/data/harnesses/code/docs/structure.md +60 -45
  13. package/data/harnesses/code/harness.json +2 -2
  14. package/data/harnesses/code/hooks/compliance.mjs +8 -2
  15. package/data/harnesses/code/hooks/lib/sweep.mjs +3 -2
  16. package/data/harnesses/code/rules/changelog.md +1 -1
  17. package/data/harnesses/code/skills/brainstorm/SKILL.md +4 -3
  18. package/data/harnesses/code/skills/brainstorm/references/harvest.md +1 -2
  19. package/data/harnesses/code/skills/design/SKILL.md +3 -2
  20. package/data/harnesses/code/skills/design/references/content.md +1 -1
  21. package/data/harnesses/code/skills/design/references/existing-apps.md +1 -1
  22. package/data/harnesses/code/skills/design/references/microcopy.md +126 -0
  23. package/data/harnesses/code/skills/documentation/SKILL.md +91 -142
  24. package/data/harnesses/code/skills/documentation/references/examples.md +35 -62
  25. package/data/harnesses/code/skills/documentation/references/frontmatter.md +7 -7
  26. package/data/harnesses/code/skills/documentation/references/source-comments.md +19 -0
  27. package/data/harnesses/code/skills/documentation/references/style-guide.md +21 -7
  28. package/data/harnesses/code/skills/documentation/references/untemplated.md +7 -6
  29. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +178 -38
  30. package/data/harnesses/code/skills/documentation/templates/Readme.md +68 -41
  31. package/data/harnesses/code/skills/documentation/templates/acceptance-criteria.md +10 -18
  32. package/data/harnesses/code/skills/documentation/templates/api-reference.md +7 -2
  33. package/data/harnesses/code/skills/documentation/templates/architecture-decision.md +5 -5
  34. package/data/harnesses/code/skills/documentation/templates/backlog.md +2 -2
  35. package/data/harnesses/code/skills/documentation/templates/behavioral-checklist.md +9 -16
  36. package/data/harnesses/code/skills/documentation/templates/bookkeeping.md +2 -2
  37. package/data/harnesses/code/skills/documentation/templates/changelog-entry.md +1 -1
  38. package/data/harnesses/code/skills/documentation/templates/changelog-index.md +21 -29
  39. package/data/harnesses/code/skills/documentation/templates/docs-readme.md +2 -2
  40. package/data/harnesses/code/skills/documentation/templates/doctrine.md +2 -2
  41. package/data/harnesses/code/skills/documentation/templates/domain-model.md +9 -4
  42. package/data/harnesses/code/skills/documentation/templates/environment-registry.md +6 -1
  43. package/data/harnesses/code/skills/documentation/templates/feature.md +4 -4
  44. package/data/harnesses/code/skills/documentation/templates/glossary.md +6 -1
  45. package/data/harnesses/code/skills/documentation/templates/handover.md +16 -16
  46. package/data/harnesses/code/skills/documentation/templates/implementation-map.md +9 -4
  47. package/data/harnesses/code/skills/documentation/templates/journal.md +2 -2
  48. package/data/harnesses/code/skills/documentation/templates/memory-main.md +2 -2
  49. package/data/harnesses/code/skills/documentation/templates/non-goals.md +7 -2
  50. package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +6 -1
  51. package/data/harnesses/code/skills/documentation/templates/package.md +4 -8
  52. package/data/harnesses/code/skills/documentation/templates/plan.md +5 -11
  53. package/data/harnesses/code/skills/documentation/templates/protected-files.md +6 -1
  54. package/data/harnesses/code/skills/documentation/templates/root-readme.md +4 -4
  55. package/data/harnesses/code/skills/documentation/templates/security-overview.md +8 -3
  56. package/data/harnesses/code/skills/documentation/templates/setup.md +6 -6
  57. package/data/harnesses/code/skills/documentation/templates/system-overview.md +11 -6
  58. package/data/harnesses/code/skills/documentation/templates/system.md +1 -1
  59. package/data/harnesses/code/skills/documentation/templates/testing-strategy.md +10 -5
  60. package/data/harnesses/code/skills/documentation/templates/ux-behavior.md +13 -2
  61. package/data/harnesses/code/skills/testing/SKILL.md +1 -1
  62. package/data/harnesses/delivery/CLAUDE.md +1 -1
  63. package/data/harnesses/delivery/agents/brainstorm.md +2 -2
  64. package/data/harnesses/delivery/agents/lld-mode.md +2 -2
  65. package/data/harnesses/delivery/agents/maintenance.md +17 -17
  66. package/data/harnesses/delivery/codex/agents/brainstorm.toml +6 -2
  67. package/data/harnesses/delivery/codex/agents/lld-mode.toml +2 -2
  68. package/data/harnesses/delivery/codex/agents/maintenance.toml +18 -17
  69. package/data/harnesses/delivery/harness.json +2 -2
  70. package/data/harnesses/delivery/rules/changelog.md +1 -1
  71. package/data/harnesses/delivery/skills/brainstorm/SKILL.md +4 -3
  72. package/data/harnesses/delivery/skills/brainstorm/references/harvest.md +1 -2
  73. package/data/harnesses/delivery/skills/documentation/SKILL.md +91 -142
  74. package/data/harnesses/delivery/skills/documentation/references/examples.md +35 -62
  75. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +7 -7
  76. package/data/harnesses/delivery/skills/documentation/references/source-comments.md +19 -0
  77. package/data/harnesses/delivery/skills/documentation/references/style-guide.md +21 -7
  78. package/data/harnesses/delivery/skills/documentation/references/untemplated.md +7 -6
  79. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +178 -38
  80. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +68 -41
  81. package/data/harnesses/delivery/skills/documentation/templates/acceptance-criteria.md +10 -18
  82. package/data/harnesses/delivery/skills/documentation/templates/api-reference.md +7 -2
  83. package/data/harnesses/delivery/skills/documentation/templates/architecture-decision.md +5 -5
  84. package/data/harnesses/delivery/skills/documentation/templates/backlog.md +2 -2
  85. package/data/harnesses/delivery/skills/documentation/templates/behavioral-checklist.md +9 -16
  86. package/data/harnesses/delivery/skills/documentation/templates/bookkeeping.md +2 -2
  87. package/data/harnesses/delivery/skills/documentation/templates/changelog-entry.md +1 -1
  88. package/data/harnesses/delivery/skills/documentation/templates/changelog-index.md +21 -29
  89. package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +2 -2
  90. package/data/harnesses/delivery/skills/documentation/templates/doctrine.md +2 -2
  91. package/data/harnesses/delivery/skills/documentation/templates/domain-model.md +9 -4
  92. package/data/harnesses/delivery/skills/documentation/templates/environment-registry.md +6 -1
  93. package/data/harnesses/delivery/skills/documentation/templates/feature.md +4 -4
  94. package/data/harnesses/delivery/skills/documentation/templates/glossary.md +6 -1
  95. package/data/harnesses/delivery/skills/documentation/templates/handover.md +16 -16
  96. package/data/harnesses/delivery/skills/documentation/templates/implementation-map.md +9 -4
  97. package/data/harnesses/delivery/skills/documentation/templates/journal.md +2 -2
  98. package/data/harnesses/delivery/skills/documentation/templates/memory-main.md +2 -2
  99. package/data/harnesses/delivery/skills/documentation/templates/non-goals.md +7 -2
  100. package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +6 -1
  101. package/data/harnesses/delivery/skills/documentation/templates/package.md +4 -8
  102. package/data/harnesses/delivery/skills/documentation/templates/plan.md +5 -11
  103. package/data/harnesses/delivery/skills/documentation/templates/protected-files.md +6 -1
  104. package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +4 -4
  105. package/data/harnesses/delivery/skills/documentation/templates/security-overview.md +8 -3
  106. package/data/harnesses/delivery/skills/documentation/templates/setup.md +6 -6
  107. package/data/harnesses/delivery/skills/documentation/templates/system-overview.md +11 -6
  108. package/data/harnesses/delivery/skills/documentation/templates/system.md +1 -1
  109. package/data/harnesses/delivery/skills/documentation/templates/testing-strategy.md +10 -5
  110. package/data/harnesses/delivery/skills/documentation/templates/ux-behavior.md +13 -2
  111. package/data/harnesses/etna/CLAUDE.md +2 -2
  112. package/data/harnesses/etna/agents/brainstorm.md +2 -2
  113. package/data/harnesses/etna/agents/lld-mode.md +2 -2
  114. package/data/harnesses/etna/agents/maintenance.md +17 -17
  115. package/data/harnesses/etna/codex/agents/brainstorm.toml +6 -2
  116. package/data/harnesses/etna/codex/agents/lld-mode.toml +2 -2
  117. package/data/harnesses/etna/codex/agents/maintenance.toml +18 -17
  118. package/data/harnesses/etna/harness.json +2 -2
  119. package/data/harnesses/etna/rules/changelog.md +1 -1
  120. package/data/harnesses/etna/skills/brainstorm/SKILL.md +4 -3
  121. package/data/harnesses/etna/skills/brainstorm/references/harvest.md +1 -2
  122. package/data/harnesses/etna/skills/documentation/SKILL.md +91 -142
  123. package/data/harnesses/etna/skills/documentation/references/examples.md +35 -62
  124. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +7 -7
  125. package/data/harnesses/etna/skills/documentation/references/source-comments.md +19 -0
  126. package/data/harnesses/etna/skills/documentation/references/style-guide.md +21 -7
  127. package/data/harnesses/etna/skills/documentation/references/untemplated.md +7 -6
  128. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +178 -38
  129. package/data/harnesses/etna/skills/documentation/templates/Readme.md +68 -41
  130. package/data/harnesses/etna/skills/documentation/templates/acceptance-criteria.md +10 -18
  131. package/data/harnesses/etna/skills/documentation/templates/api-reference.md +7 -2
  132. package/data/harnesses/etna/skills/documentation/templates/architecture-decision.md +5 -5
  133. package/data/harnesses/etna/skills/documentation/templates/backlog.md +2 -2
  134. package/data/harnesses/etna/skills/documentation/templates/behavioral-checklist.md +9 -16
  135. package/data/harnesses/etna/skills/documentation/templates/bookkeeping.md +2 -2
  136. package/data/harnesses/etna/skills/documentation/templates/changelog-entry.md +1 -1
  137. package/data/harnesses/etna/skills/documentation/templates/changelog-index.md +21 -29
  138. package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +2 -2
  139. package/data/harnesses/etna/skills/documentation/templates/doctrine.md +2 -2
  140. package/data/harnesses/etna/skills/documentation/templates/domain-model.md +9 -4
  141. package/data/harnesses/etna/skills/documentation/templates/environment-registry.md +6 -1
  142. package/data/harnesses/etna/skills/documentation/templates/feature.md +4 -4
  143. package/data/harnesses/etna/skills/documentation/templates/glossary.md +6 -1
  144. package/data/harnesses/etna/skills/documentation/templates/handover.md +16 -16
  145. package/data/harnesses/etna/skills/documentation/templates/implementation-map.md +9 -4
  146. package/data/harnesses/etna/skills/documentation/templates/journal.md +2 -2
  147. package/data/harnesses/etna/skills/documentation/templates/memory-main.md +2 -2
  148. package/data/harnesses/etna/skills/documentation/templates/non-goals.md +7 -2
  149. package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +6 -1
  150. package/data/harnesses/etna/skills/documentation/templates/package.md +4 -8
  151. package/data/harnesses/etna/skills/documentation/templates/plan.md +5 -11
  152. package/data/harnesses/etna/skills/documentation/templates/protected-files.md +6 -1
  153. package/data/harnesses/etna/skills/documentation/templates/root-readme.md +4 -4
  154. package/data/harnesses/etna/skills/documentation/templates/security-overview.md +8 -3
  155. package/data/harnesses/etna/skills/documentation/templates/setup.md +6 -6
  156. package/data/harnesses/etna/skills/documentation/templates/system-overview.md +11 -6
  157. package/data/harnesses/etna/skills/documentation/templates/system.md +1 -1
  158. package/data/harnesses/etna/skills/documentation/templates/testing-strategy.md +10 -5
  159. package/data/harnesses/etna/skills/documentation/templates/ux-behavior.md +13 -2
  160. package/package.json +2 -2
@@ -1,87 +1,86 @@
1
1
  ---
2
2
  name: documentation
3
- description: "Use when creating or substantively editing ANY markdown doc — invoke BEFORE writing. Templates + style authority for technical docs: LLDs, ADs, plans, changelogs, READMEs, runbooks. Owns the tense rule: truth docs state the present; history only in dated records. Baselining is the maintenance agent."
3
+ description: "Use when creating or substantively editing ANY markdown doc — invoke BEFORE writing. Genre registry, templates and style authority for technical docs: LLDs, ADs, plans, changelogs, READMEs, runbooks. Owns the tense rule: truth docs state the present; history only in dated records. Baselining is the maintenance agent."
4
4
  ---
5
5
 
6
6
  # Technical Documentation Skill
7
7
 
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.
8
+ This skill writes one document at a time: the genre registry says what kind of document it is, a template gives its shape, the style guide its prose, and `doc-lint` checks the mechanical half. It does not baseline, audit or reconcile a repo's doc tree; that is the `maintenance` agent, which calls this skill once per document it scaffolds.
9
9
 
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.
10
+ ## Load order
11
11
 
12
- ---
13
-
14
- ## Where a file's documentation lives
12
+ 1. This file.
13
+ 2. Your genre's row in [`templates/Readme.md`](templates/Readme.md) § Registry, then the template that row names.
14
+ 3. [`references/style-guide.md`](references/style-guide.md) § The model and § Labels before writing prose; the rest of it only for the section you are writing.
15
+ 4. [`references/frontmatter.md`](references/frontmatter.md) when you write or change frontmatter keys beyond `type:` and `description:`.
16
+ 5. Only for their own tasks: [`references/untemplated.md`](references/untemplated.md) (no registry row fits), [`references/instruction-style.md`](references/instruction-style.md) (instruction files), [`references/source-comments.md`](references/source-comments.md) (source-file comments), [`references/examples.md`](references/examples.md) (worked good and bad examples).
15
17
 
16
- **In `docs/`, never in the file's comments** — and this skill is the half of that rule that makes it safe. A source file carries a repo-relative path header of two or three present-tense sentences and one third-person sentence above each non-obvious function; the shape is the harness's `CLAUDE.md` § File Structure, which is canonical and is not restated here. That header's `docs/…` path is also the file's edge into the knowledge graph: the header pointer names the document that speaks for the file, which is how ownership is computed ([`references/frontmatter.md`](references/frontmatter.md)). What lands **here** is everything that shape displaces: design rationale, the alternatives weighed, the measurement behind a constant, the reason an obvious-looking change is wrong.
18
+ ---
17
19
 
18
- **Cutting a comment is a move, not a deletion.** A claim taken out of a source file is owed one of two things before the cut is done, and the choice is per claim, not per file:
20
+ ## Writing one document
19
21
 
20
- | The claim is | What it earns |
21
- | --- | --- |
22
- | Worth keeping, and its doc does not state it | A section in the **owning feature doc** (the ownership index resolves which), carrying the claim and the argument for why the codebase is worse without it — never the comment's wording, which was written for a reader holding the code |
23
- | Already stated in its doc | Nothing — but you **open that doc and find the sentence** before saying so. An assumed duplicate is how a claim is lost |
24
- | History, a ticket or decision-record reference, a dated note, a divider, or narration of code that no longer exists | Nothing, and no record. A record lives in `docs/history/`; these are not claims about the present |
22
+ 1. **Find the genre.** Match the request against § Routing, then read that genre's registry row: nature, `type:`, location, required keys, required sections. No row fits ⇒ `references/untemplated.md`.
23
+ 2. **Find the existing document.** If a document on the topic already exists, extend it; a second document on one topic is drift. If the file is a frozen record (a plan at `Complete` or `Abandoned`, a committed changelog entry, an executed runbook), never edit it: write a new dated record that links back.
24
+ 3. **Place and name it** at the registry's location. `docs/structure.md` is the placement authority for anything the registry leaves open.
25
+ 4. **Write it from the template.** Keep the template's section names exactly; omit optional sections with nothing real to say. Write the body from the outside in (style guide § Shape), every heading and bold label a noun phrase, every sentence after a label third person. In a truth document, every sentence is present tense (§ The three natures).
26
+ 5. **Write the frontmatter.** `type:` from the registry, `description:` in at most 300 characters saying what the document settles and where its boundary sits, then the genre's required keys (`references/frontmatter.md` for each key's rules).
27
+ 6. **Run the lint** from the repo root on the repo-relative path: `node <skill>/scripts/doc-lint.mjs docs/features/sign-in.md` (or `--changed`). Fix every `[block]` finding; read every `[warn]` and fix it unless the judgment it flags is genuinely yours. A disable takes bare rule ids, `<!-- doc-lint-disable: id -->`, alone on its own line for the whole file with the reason in a second comment on the next line, or at the end of one line for that line only.
28
+ 7. **Edit, don't append, on a substantive change to an existing truth document.** Keep its section shape, shed any history narration, progress marker or stale tripwire in the sections you touch, bump `last-reviewed:`, update `objects:` if what it designs changed, and remove any retired key on the way through.
25
29
 
26
- **Count what you cut, and prove the cut was only comments.** A comment sweep states comment lines before and after per file, so a drop nobody accounted for is visible as a number rather than as a feeling. [`scripts/comment-strip.mjs`](scripts/comment-strip.mjs) turns that from a claim into a check: it strips comments from both revisions — honouring strings, template and character literals, regex literals, raw strings and JSX comment braces — and diffs what is left, so a sweep that quietly changed executable code cannot pass as a cleanup. `comment-strip.mjs --rev <before> --to <after> <paths…>` exits 0 for "no executable code changed" and 1 naming the file and the first diverging line. Run it over any pass that touches more than a handful of files; a sweep without it is an assertion.
30
+ ---
27
31
 
28
- **The mechanical half of the shape is checked, not remembered.** [`scripts/source-lint.mjs`](scripts/source-lint.mjs) `--changed` reports a header that names another path or none, a change whose added lines are over a quarter comments, and the four shapes the convention deletes outright — narration, ALL-CAPS emphasis, an over-long header, a comment block that has become a document. Block-severity findings must be fixed; the escape hatch is a `source-lint-disable: <id>` comment with the reason in a second comment beside it, and the only finding that legitimately takes one is a booby trap. The harness detector raises a bookkeeping row for the same condition, so an unfixed breach outlives the session that wrote it.
32
+ ## The three natures
29
33
 
30
- **Never convert a booby trap into a one-liner.** A comment whose subject is a danger on an edge that looks safe — a pinned dependency's limitation, a measurement that justifies a narrow allowlist, a two-clock interaction — is load-bearing where it sits, because the reader who needs it is mid-edit and will not go looking. Compress it if it rambles; do not relocate it. The tell is that the comment names a version, a measurement, or a condition under which it expires.
34
+ Every document is exactly one of three things, and the registry names which for every genre. Decide before writing a word: every other rule follows from the split.
31
35
 
32
- ---
36
+ | | **Truth** | **Record** | **Queue** |
37
+ | --- | --- | --- | --- |
38
+ | States | How the system is, now | What happened | Work not done yet |
39
+ | Named by | Topic: `auth.md`, `AD-003-persistence.md` | Date: `YYYY-MM-DD-slug.md` | A fixed name: `backlog.md`, `journal.md` |
40
+ | On change | Body rewritten in place | Frozen at its terminal status | A row appended, or a resolved row deleted |
41
+ | Read to | Act correctly today | Trace provenance, diagnose, audit | Pick up the next piece of work |
33
42
 
34
- ## Present tense, always
43
+ The guarantees break on mixing: a reader holding a truth document must never need history to interpret it, a reader holding a record must trust it was never rewritten, and a reader holding a queue must trust that every row in it is still open.
35
44
 
36
- **A document states what is — never how it got there, and never how far along it is.** Write as if the current design had always been the plan. This is the most-violated rule in the skill, so it sits at the top; it applies to every document written or edited through this skill, whatever the template.
45
+ - **Truth documents narrate no history.** When the system changes, the change-story goes to a changelog entry and the truth document simply becomes correct. Write as if the current design had always been the plan.
46
+ - **Records are never edited to match the present.** A completed plan stays wrong in hindsight; a scope change gets a new dated record that links back.
47
+ - **Queue rows are resolved by deletion.** A finished backlog item, a landed journal fact, a drained bookkeeping row is deleted, never marked done; the plan or changelog entry that did the work is the record.
48
+ - **One bridge: an Architecture Decision's Decision Changelog.** For a decision, the journey is part of the reasoning, so an AD ends with a dated, append-only tail while its body stays current. No other truth document carries dated history.
37
49
 
38
- | ❌ Strip this | ✅ Write this |
50
+ | ❌ Strip this from a truth document | ✅ Write this |
39
51
  | --- | --- |
40
- | "Build Sequence phases 0–4 are complete." | Nothing — progress lives in the plan/backlog record |
41
- | "There is no standalone `skills/components/` — treat any reference to it as stale." | Nothing — fix the references; state only the present design |
52
+ | "Build Sequence phases 0–4 are complete." | Nothing; progress lives in the plan or backlog |
53
+ | "There is no standalone `skills/components/` — treat any reference to it as stale." | Nothing; fix the references and state only the present design |
42
54
  | "Folded in from the `NuStack-X` repo (2026-06-12)." | "Vendor-connector catalogue; one subpath per vendor." |
43
55
  | "was X, now Y", "the old worker", "Phase 2 softened this", "v1 → v2" | The current fact, with no predecessor named |
44
56
 
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
-
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.
57
+ - **Dates:** a truth document carries no dated line. The exceptions are closed: the frontmatter's tooling keys (`last-reviewed:`, `last-updated:`, `rev:`, `harness-version:`), an AD's Decision Changelog, and a dated path inside a link or code span, which cites a record rather than claiming a date.
58
+ - **Citing a record:** by what it is, never by when it was. "The dev reset runbook" linked to the file stays true; "the 2026-09-13 reset" goes stale at the second reset.
59
+ - **Verification stamps:** "Driven 2026-09-13 · PASS" in a checklist is a dated event. The section states what must be true and which suite test guards it; that someone drove it belongs to the changelog entry of the unit that drove it.
48
60
 
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
-
51
- **A verification stamp is a record, not a status line.** "Driven 2026-09-13 · PASS" in a behavioural checklist is the clearest instance of this defect: it reads as documentation and is actually a dated event. The section states what must be true and which suite test guards it; *that* somebody drove it on a Tuesday belongs to the changelog entry of the unit that drove it, and staleness is then visible from something that re-checks itself — a pin that runs in CI — rather than from a date nobody re-stamped. A section with no automated guard says so in its trace, which is a stronger signal than an old date, because it cannot silently become wrong.
52
-
53
- The mechanical subset of these rules is checked by [`scripts/doc-lint.mjs`](scripts/doc-lint.mjs) — run it over changed docs before finishing. Block-severity findings must be fixed; `<!-- doc-lint-disable: <id> -->` with a reason beside it is the escape hatch. Two invocation traps: the disable comment takes **bare rule ids only** — prose inside the comment silently breaks the parse, so put the reason in a second comment beside it — and the script grades truth-vs-record scope by matching `docs/(history|research|memory)/` against **the path string it is given**, so always hand it a repo-root-relative path; linting a record from inside its own folder grades it as a truth document.
61
+ The full strip-list and the record-side rules: `references/style-guide.md` § The Two Natures — tense and history.
54
62
 
55
63
  ---
56
64
 
57
- ## The Two Natures
58
-
59
- Every document is exactly one of two things. Decide which before writing a word — every rule in this skill derives from the split.
60
-
61
- | | **Truth document** | **Record** |
62
- | --- | --- | --- |
63
- | States | Absolutes — how the system is, **now** | What happened — a dated account of activity |
64
- | Named by | Topic: `auth.md`, `AD-003-persistence.md` | Date: `YYYY-MM-DD-slug.md` (or append position) |
65
- | On change | Body rewritten in place the moment reality changes | Never edited — frozen at completion or append-only |
66
- | Read to | Act correctly today | Trace provenance, diagnose, audit |
67
- | Lives in | `docs/features/`, `docs/architecture/`, `docs/operations/`, `docs/tests/`, READMEs | `docs/history/` (plans, changelog, brainstorms, research, migrations), `docs/research/`, `docs/memory/` |
65
+ ## Truth documents
68
66
 
69
- The two guarantees are complementary and both break on mixing: a reader holding a **truth document** must never need history to interpret it; a reader holding a **record** must be able to trust it was never rewritten. So the natures never share a document body.
67
+ - **Intent and promises; facts are the graph's.** An owning document (feature, package, system) says 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, which function writes which column, which route sits behind which guard, which file holds what) is the code's, and a hand-typed copy is wrong the day the code moves. `doc-lint` blocks the retired mechanism sections (`mechanism-section`) and an owning document with no `objects:`.
68
+ - **Read by people, pointed at by the footer.** Sharp bullets under noun-phrase headings, each a bold label, a colon, one or two plain sentences; code named only where a person types or sees it, or at a cross-cutting seam; every other pointer in the closing **For the agent** footer (style guide § Owning documents — the body and the footer).
69
+ - **The stability test.** A sentence that would 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 on *why* (style guide § Shape).
70
+ - **Unbuilt work has one home per kind.** Decided design the code does not yet do sits in the body, wrapped in an `UNBUILT` marker; a shortfall in what is built is one bullet under Gaps; the work that would close either is a backlog row, which the document never tracks (style guide § The stability test).
71
+ - **No empty stubs.** Omit a section with nothing real to say. Write "None" only where the absence is itself information, such as a plan's Cross-Module Contracts Affected.
72
+ - **No redirect documents.** Moving a document deletes the old file and repoints every inbound link; a "Moved to X" stub rots and creates false search hits.
70
73
 
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
- - **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 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.
75
- - **Every document describes itself.** Its frontmatter carries `description:` — at most 300 characters, one or two present-tense sentences saying what the document settles and where its boundary sits (`references/frontmatter.md` § `description:`). That is the per-file account an index would otherwise keep, so an index names no file and no record: not a link, not a filename, not an ID row such as `AD-010`. A folder is browsed with `grep -m1 '^description:' <folder>/*.md`. `doc-lint` blocks a truth document or folder index without one (`description-missing`), one over 300 characters (`description-length`), and an index row that names a file or record (`index-names-records`).
76
- - **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.)
74
+ ### Indexes and descriptions
77
75
 
78
- **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`).
76
+ - **Every document describes itself** in its `description:`, so a folder is browsed with `grep -m1 '^description:' <folder>/*.md` and no index keeps a row per file.
77
+ - **A folder's `Readme.md` describes the folder:** what it holds, who reads it, how its files are named. No file list, no tree (`docs/structure.md` holds the one tree), no record IDs such as `AD-010`. Nothing appends to an index when a sibling file is added; the changelog guide, `docs/history/CHANGELOG.md`, is no exception.
78
+ - **The links an index may carry:** a sibling folder's `Readme.md`, the mandated scaffolds (`structure.md`, `operations/setup.md`, `history/CHANGELOG.md`, `history/backlog.md`, `history/journal.md`, `history/health-log.md`, `memory/main.md`), and the root `CLAUDE.md` and `AGENTS.md`. `doc-lint` blocks the rest under `docs/` as `index-lists-files`, a drawn tree as `index-file-tree`, a named file or record as `index-names-records`.
79
+ - **Routing documents point at truth.** A "read first" row names the topic's truth document, never a plan or changelog entry. An index of the records themselves (a History section naming `plans/` and `changelog/`) is sanctioned.
79
80
 
80
- **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.
81
+ ### Ownership today
81
82
 
82
- **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.
83
-
84
- **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.
83
+ A document names the objects it designs in `objects:`, and a source file names the document that speaks for it in its path header. The harness's ownership scan reads one edge today: the transitional `owns:` region glob on each feature, package, system and surface-owning UX document, the narrower glob winning. Write the header pointer anyway, so the scan can switch to it and to the object closure without a second pass over the code. Where a repository has no `docs/architecture/systems/knowledge-layer.md`, this skill and `references/frontmatter.md` are the whole authority on document–code edges. `docs/structure.md` is harness-owned: the installer writes it, and the `maintenance` agent stamps only its `harness-version`.
85
84
 
86
85
  ---
87
86
 
@@ -89,99 +88,49 @@ The two guarantees are complementary and both break on mixing: a reader holding
89
88
 
90
89
  | Request | Route |
91
90
  | --- | --- |
92
- | Baseline / reconcile docs | `maintenance` agent (baseline mode) — it calls this skill per template |
93
- | Document feature/module (LLD) | [`templates/feature.md`](templates/feature.md) |
94
- | Document data flow / state / Redux | [`templates/feature.md`](templates/feature.md) — they are sections of the feature doc |
95
- | 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 |
96
- | 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 the surfaces bound by it are the ones that design or touch the objects it governs |
97
- | Document one system spanning packages (`docs/architecture/systems/{system}.md`) | [`templates/system.md`](templates/system.md) — one machine end to end, the objects it owns or moves. Not a screen — a system doc written as a giant feature doc is the mistake it prevents |
98
- | 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) |
99
- | Create/update plan | [`templates/plan.md`](templates/plan.md) (record) |
100
- | Record/revise architecture decision | [`templates/architecture-decision.md`](templates/architecture-decision.md) — one AD per subject; revisions update it in place |
101
- | System at a glance | [`templates/system-overview.md`](templates/system-overview.md) |
102
- | Domain model | [`templates/domain-model.md`](templates/domain-model.md) |
103
- | Glossary | [`templates/glossary.md`](templates/glossary.md) |
104
- | Non-goals | [`templates/non-goals.md`](templates/non-goals.md) |
105
- | Catalog the API surface | [`templates/api-reference.md`](templates/api-reference.md) |
106
- | Document env vars / config | [`templates/environment-registry.md`](templates/environment-registry.md) |
107
- | Security / threat model | [`templates/security-overview.md`](templates/security-overview.md) |
108
- | Testing strategy | [`templates/testing-strategy.md`](templates/testing-strategy.md) |
109
- | 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 |
110
- | 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 |
111
- | 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 |
112
- | Machine setup / first run / stack (one per repo, `docs/operations/setup.md`) | [`templates/setup.md`](templates/setup.md) |
91
+ | Baseline / reconcile docs | `maintenance` agent (baseline mode); it calls this skill per template |
92
+ | Document a feature (LLD) | [`templates/feature.md`](templates/feature.md) |
93
+ | Document a feature's data flow or state | The feature doc's Flows (behaviour) and Promises (guarantees); a persisted shape belongs in the API reference (style guide § State at persistence points); component and transient state are not documented |
94
+ | Document a workspace package | [`templates/package.md`](templates/package.md), the residual owner of `packages/{name}/**` |
95
+ | Document one concern the platform handles everywhere (authentication, storage, the API protocol) | [`templates/doctrine.md`](templates/doctrine.md): design and principles, no mechanism, owns no code |
96
+ | Document one system spanning packages | [`templates/system.md`](templates/system.md): one machine end to end, never a giant feature doc |
97
+ | Record or revise an architecture decision | [`templates/architecture-decision.md`](templates/architecture-decision.md): one AD per subject, revised in place |
98
+ | Create or update a changelog entry | [`templates/changelog-entry.md`](templates/changelog-entry.md) (record; frozen inside its commit; no row in `CHANGELOG.md`) |
99
+ | Create or update a plan | [`templates/plan.md`](templates/plan.md) (record) |
100
+ | Steering docs: system overview, domain model, glossary, non-goals, security, testing strategy | The registry row's template |
101
+ | Catalog the API surface / the environment variables | [`templates/api-reference.md`](templates/api-reference.md) / [`templates/environment-registry.md`](templates/environment-registry.md) |
102
+ | What a person sees and can do on a surface | [`templates/ux-behavior.md`](templates/ux-behavior.md): decides observable behavior before the code; not the checklist, which only verifies it |
103
+ | Behavioral checklist for one feature | [`templates/behavioral-checklist.md`](templates/behavioral-checklist.md): the verification gate's driving script |
104
+ | Acceptance criteria for one capability | [`templates/acceptance-criteria.md`](templates/acceptance-criteria.md): stable `AC-n` lines |
105
+ | Machine setup, first run, stack | [`templates/setup.md`](templates/setup.md), one per repo |
113
106
  | Recurring procedure (develop, deploy, rotate, diagnose) | [`templates/operations-procedure.md`](templates/operations-procedure.md) |
114
- | 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 |
115
- | 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) |
116
- | 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 |
117
- | One-shot migration/upgrade | [`templates/migration-runbook.md`](templates/migration-runbook.md) (record) |
118
- | 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 |
119
- | Add to protected files | [`templates/protected-files.md`](templates/protected-files.md) |
120
- | 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) |
121
- | 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 |
122
- | Derive or update a document's frontmatter (`objects:`, the header pointers, the transitional `owns:`) | [`references/frontmatter.md`](references/frontmatter.md) |
123
- | Update existing doc | § Editing an existing doc (below) |
124
- | 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 |
125
- | Author or restructure a **skill** (fit, triggers, shape, anatomy, shipping) | The skill-authoring field guide — the `etna` repo (`nurixlabs/etna`), folder `docs/playbooks/skills/`, chapters `00`–`13`. **No etna checkout available ⇒ ask the user for access to the etna repo, or proceed from first principles** with [`references/instruction-style.md`](references/instruction-style.md) governing the prose. This row is the only place the playbook is referenced |
126
- | **No template matches** | [`references/untemplated.md`](references/untemplated.md) — shape decisions + the co-authoring workflow |
127
-
128
- ---
129
-
130
- ## Editing an existing doc
131
-
132
- "Substantive" = anything beyond typo, link, or formatting fixes. On a substantive edit:
133
-
134
- 1. **Determine the nature first.** A frozen record (a `Status: Complete`/`Abandoned` plan, a changelog entry, an executed runbook) is never edited — write a new dated record that links back.
135
- 2. **Preserve structure, not violations.** Keep the doc's existing section shape, but every section touched sheds history narration, progress markers, and stale tripwires on the way through (§ Present tense, always).
136
- 3. **Stamp and re-derive.** A substantive feature-doc update bumps `last-reviewed:`; if the objects it designs changed, update `objects:`, and remove any retired key on the way through ([`references/frontmatter.md`](references/frontmatter.md)).
137
-
138
- ---
139
-
140
- ## Naming & Lifecycle
141
-
142
- | Document | Nature | Name | Lifecycle |
143
- | --- | --- | --- | --- |
144
- | Feature (LLD) | Truth | `kebab-case.md` | Living; `status:` `draft` → `active` → `deprecated` |
145
- | Package | Truth | `{package-folder}.md` | Living; `status:` as the feature doc |
146
- | System | Truth | `{machine}.md` | Living; `status:` as the feature doc |
147
- | Doctrine | Truth | `{concern}.md` | Living; `status:` `draft` → `active` |
148
- | Architecture Decision | Truth | `AD-NNN-kebab-case.md` | Living; `Proposed` → `Accepted` → `Deprecated`; revisions rewrite the body + append to its Decision Changelog |
149
- | Steering docs (overview, domain model, glossary, non-goals, security, testing strategy) | Truth | fixed names | Living |
150
- | API reference / environment registry | Truth | fixed names | Living |
151
- | Operations procedure | Truth | `kebab-case.md` | Living |
152
- | Protected files | Truth | `protected-files.md` | Living |
153
- | Plan | Record | `YYYY-MM-DD-kebab-case.md` | Freezes at `Complete` / `Abandoned` |
154
- | Changelog entry | Record | `YYYY-MM-DD-kebab-case.md` | Frozen; master index append-only |
155
- | Migration runbook | Record | `YYYY-MM-DD-kebab-case.md` | Freezes once executed, outcome stamped |
156
- | Research | Record | in progress: `docs/research/{topic}/` · harvested: `docs/history/brainstorms/{topic}/` | Frozen at harvest |
157
- | Memory | Record | `{agent-name}.md` | Append-only dated ledger |
158
-
159
- ---
160
-
161
- ## Frontmatter
162
-
163
- **Frontmatter is compulsory on every document this skill authors**: `type:` (the genre) on every document, plus its genre's keys. There is no frontmatter-less genre. The keys follow the knowledge layer (`docs/architecture/systems/knowledge-layer.md` § Documents and code), and this skill stays in step with it:
164
-
165
- - **`objects:` is a document's edge into the graph:** the product objects it designs, by their register names. Feature, system, package, doctrine and UX documents carry it, with `type:` and `status:`; a feature may add `module:`.
166
- - **The code's edge is the source file's header pointer:** authored on the code's side, naming the document that holds the file's fuller account. Which document speaks for a path is computed from the pointers and the object closure, never typed into the document.
167
- - **`owns:` is transitional:** region globs only, kept solely because the harness's ownership scan still reads it, and removed everywhere in the change that switches the scan. Never a list of files.
168
- - **`applies:` is retired:** a document's governing doctrine is computed through the objects both name, and its Scope section names it for people.
169
- - **`verifies:` stays on a behavioral checklist:** the document whose promises it proves.
170
-
171
- Keys by genre, each key's rules, the retired keys, and the one rule the graph rests on (declare once, at the consuming end; generate every inverse) are [`references/frontmatter.md`](references/frontmatter.md). Every document create or update, and the `maintenance` agent's baseline pass, route there.
107
+ | Cold-start build order | [`templates/implementation-map.md`](templates/implementation-map.md), written by the executing session at build start |
108
+ | Capture a mid-execution fact / log doc-sync debt / log open work | [`templates/journal.md`](templates/journal.md) / [`templates/bookkeeping.md`](templates/bookkeeping.md) / [`templates/backlog.md`](templates/backlog.md) (queues) |
109
+ | One-shot migration | [`templates/migration-runbook.md`](templates/migration-runbook.md) (record) |
110
+ | Hand-over at the end of an unattended or multi-session build | [`templates/handover.md`](templates/handover.md) (record) |
111
+ | Protected files | [`templates/protected-files.md`](templates/protected-files.md) |
112
+ | Root README | [`templates/root-readme.md`](templates/root-readme.md): outward opening, then orientation and routing |
113
+ | Scaffold a standard doc (docs index, changelog guide, backlog, memory) | The registry's § Baseline scaffolds |
114
+ | Frontmatter keys (`objects:`, `verifies:`, the transitional `owns:`) | [`references/frontmatter.md`](references/frontmatter.md) |
115
+ | Source-file comments: what stays, what moves to a doc, proving a sweep | [`references/source-comments.md`](references/source-comments.md) |
116
+ | Instruction file (`CLAUDE.md`, a rule, an agent, skill prose) | [`references/instruction-style.md`](references/instruction-style.md): every-load prose stays lean; the present-tense rule still applies |
117
+ | Author or restructure a skill | The skill-authoring field guide in the etna repo (`nurixlabs/etna`), `docs/playbooks/skills/`. No etna checkout ⇒ ask the user for access, or proceed from first principles with `references/instruction-style.md` governing the prose |
118
+ | No template matches | [`references/untemplated.md`](references/untemplated.md) |
172
119
 
173
120
  ---
174
121
 
175
122
  ## Resources
176
123
 
177
- | File | Use For |
124
+ | File | Use for |
178
125
  | --- | --- |
179
- | `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 |
180
- | `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 |
181
- | `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 |
182
- | `references/frontmatter.md` | Frontmatter by genre, in step with the knowledge layer: `objects:`, the header pointer, the transitional `owns:`, the retired `applies:`, `verifies:` |
183
- | `references/untemplated.md` | How to write a document no template covers (nature, placement, shape) + the co-authoring workflow |
184
- | `references/examples.md` | Good vs bad documentation examples |
185
- | `scripts/doc-lint.mjs` | Mechanical checks over written docs (tense narration, dates, stubs, redirects) — run over changed docs before finishing |
186
- | `scripts/source-lint.mjs` | Mechanical checks over source **comments** (header path identity, the added-line comment ratio, narration, shouting) — run `--changed` before finishing any change that writes source |
187
- | `scripts/comment-strip.mjs` | The proof a comment sweep changed no executable code: strips comments from two revisions and diffs what is left. Exit 0 is the claim; exit 1 names the file and the first diverging line |
126
+ | `templates/Readme.md` | The genre registry: every genre's nature, `type:`, location, required keys and sections; `doc-lint` reads it |
127
+ | `templates/` | One template per genre the registry names |
128
+ | `references/style-guide.md` | The prose authority: the eight principles, depth per genre, the outside-in shape and stability test, labels and voice, owning documents, tense, diagrams, reference documents |
129
+ | `references/frontmatter.md` | Each frontmatter key's rules, the transitional `owns:`, the retired keys |
130
+ | `references/instruction-style.md` | The style for instruction files |
131
+ | `references/untemplated.md` | Writing a document no template covers, and co-authoring one with a person |
132
+ | `references/source-comments.md` | Source-file comments, and the scripts that check them |
133
+ | `references/examples.md` | Good and bad documentation, side by side |
134
+ | `scripts/doc-lint.mjs` | Mechanical checks over written docs: tense and history, dates, redirect stubs, frontmatter, the registry's keys and sections, index shape, owning-document body |
135
+ | `scripts/source-lint.mjs` | Mechanical checks over source comments; run `--changed` before finishing any change that writes source |
136
+ | `scripts/comment-strip.mjs` | Proof that a comment sweep changed no executable code |
@@ -6,7 +6,7 @@ Good vs bad examples showing the key differences.
6
6
 
7
7
  ## Example 1: Function Documentation
8
8
 
9
- ### ❌ Bad: Full Implementation
9
+ ### Bad: Full Implementation
10
10
 
11
11
  ```markdown
12
12
  ### mergeData
@@ -16,7 +16,7 @@ function mergeData(server, local, changes) { const result = {}; const serverMap
16
16
 
17
17
  **Problems:** Will become obsolete, focuses on HOW not WHAT.
18
18
 
19
- ### ✅ Good: Contract Only
19
+ ### Good: Contract Only
20
20
 
21
21
  ```markdown
22
22
  ### `mergeData(serverData, localData, changes)`
@@ -42,7 +42,7 @@ function mergeData(server, local, changes) { const result = {}; const serverMap
42
42
 
43
43
  ## Example 2: State Documentation
44
44
 
45
- ### ❌ Bad: State Everywhere
45
+ ### Bad: State Everywhere
46
46
 
47
47
  ```markdown
48
48
  ## Component State
@@ -60,10 +60,12 @@ const [items, setItems] = useState([]);
60
60
 
61
61
  **Problems:** Documents transient state, repeats shapes.
62
62
 
63
- ### ✅ Good: Persistence Points Only
63
+ ### Good: Persistence Points Only, in the API reference
64
+
65
+ Persisted shapes live in the API reference (`docs/architecture/api.md`), never in a feature document, where `## State` is a retired mechanism section.
64
66
 
65
67
  ```markdown
66
- ## State
68
+ ## Persisted shapes — items
67
69
 
68
70
  **Frontend (at persistence):**
69
71
 
@@ -87,7 +89,7 @@ export const items = pgTable('items', {
87
89
 
88
90
  ## Example 3: Changelog
89
91
 
90
- ### ❌ Bad: Vague
92
+ ### Bad: Vague
91
93
 
92
94
  ```markdown
93
95
  # 2025-01-05 - Updates
@@ -103,52 +105,25 @@ export const items = pgTable('items', {
103
105
  - Various files in src/
104
106
  ```
105
107
 
106
- ### ✅ Good: Function-Level Detail
108
+ ### Good: Behavior First, Refinement Context Kept
107
109
 
108
110
  ```markdown
109
- # 2025-01-05 - Version-Based Merge
110
-
111
- ## Summary
112
-
113
- Replaced change-tracking merge with version-based conflict resolution.
114
-
115
- ## Changes
116
-
117
- ### Added
118
-
119
- - `mergeAndDerive(server, local, versionsMatch, type)` in `src/utils/merge.js`
120
- - Purpose: Single-pass merge with change detection
121
- - Returns: `{ merged, changes }`
122
-
123
- ### Changed
124
-
125
- - `useDataSync()` in `src/hooks/useDataSync.js`
126
- - Changed: Now compares versions before merge
127
-
128
- ### Removed
129
-
130
- - `deriveChanges()` from `src/utils/derive.js`
131
- - Replaced by: Logic in `mergeAndDerive()`
132
-
133
- ## Breaking Changes
134
-
135
- ⚠️ **Merge behavior changed**
136
-
137
- - Old: Local changes always preserved
138
- - New: Local preserved only if versions match
139
-
140
- ## Files Changed
141
-
142
- - `src/hooks/useDataSync.js`
143
- - `src/utils/merge.js`
144
- - `src/utils/derive.js` (deleted)
111
+ # 2025-01-05 · data-sync — Local edits survive a sync only when versions match
112
+
113
+ - **Ask:** "stop silently overwriting my offline edits — I'd rather see a conflict than lose work"
114
+ - **Iterations:** 2 · rejected: last-write-wins by timestamp, because device clocks drift and the newer-looking write lost real edits
115
+ - **Skills:** documentation@3.18.0 — survived
116
+ - **Change:** sync now keeps a local edit only when its base version matches the server's, and surfaces a conflict otherwise, because a stale local copy was overwriting newer server state. Merge and change detection run in one pass (`mergeAndDerive`)
117
+ - **Discovered:** two tabs on one device share a version counter, so a conflict between them never surfaces [source: runtime-discovery]
118
+ - **Class:** data · resilience
119
+ - **Pin:** `tests/sync/merge.test.ts` — version-mismatch keeps the server copy and reports the conflict
145
120
  ```
146
121
 
147
122
  ---
148
123
 
149
124
  ## Example 4: Flow
150
125
 
151
- ### ❌ Bad: Mechanism narrated in a paragraph
126
+ ### Bad: Mechanism narrated in a paragraph
152
127
 
153
128
  ```markdown
154
129
  ## Data Flow
@@ -158,12 +133,12 @@ When the page loads, the useAppInit hook calls the syncData function. This funct
158
133
 
159
134
  **Problems:** names a hook, a function and a store that a rename would invalidate (the stability test); runs parallel cases together in one paragraph; gives a scanning reader no label to land on; "Data Flow" is a retired mechanism section.
160
135
 
161
- ### ✅ Good: Labelled bullets, a role-level diagram beside them
136
+ ### Good: Labelled bullets, a role-level diagram beside them
162
137
 
163
138
  ````markdown
164
139
  ## Flows
165
140
 
166
- ### Page load
141
+ ### Page load — item sync
167
142
 
168
143
  - **Fresh data:** the page fetches the server's copy and the local copy on every load; nothing is cached between visits.
169
144
  - **Matching versions:** local changes win and are kept.
@@ -186,7 +161,7 @@ sequenceDiagram
186
161
 
187
162
  ## Example 5: Architecture Decision revision
188
163
 
189
- ### ❌ Bad: Supersession chain
164
+ ### Bad: Supersession chain
190
165
 
191
166
  ```
192
167
  docs/architecture/decisions/
@@ -197,7 +172,7 @@ docs/architecture/decisions/
197
172
 
198
173
  **Problems:** Three files hold one subject; the reader must diff a chain to learn the current truth; two of the three are wrong-but-present (the same pathology as keeping `report_v1.sql` beside the live `report_v2.sql`); the reasoning that killed Keycloak is stranded in a dead file nobody opens.
199
174
 
200
- ### ✅ Good: One subject, updated in place
175
+ ### Good: One subject, updated in place
201
176
 
202
177
  ```
203
178
  docs/architecture/decisions/
@@ -228,7 +203,7 @@ We use Better Auth with one-shot credential issuance… ← current truth, no
228
203
 
229
204
  The move agents fumble: deleting narration is only half the job — the story must land in a record.
230
205
 
231
- ### ❌ Bad: The journey narrated in place
206
+ ### Bad: The journey narrated in place
232
207
 
233
208
  ```markdown
234
209
  ## Export Pipeline
@@ -239,7 +214,7 @@ output is not yet implemented. Treat any reference to `reports/export.js` as
239
214
  stale — it was superseded by `src/export/run.js`.
240
215
  ```
241
216
 
242
- ### ✅ Good: Present-tense truth doc + a dated record carrying the story
217
+ ### Good: Present-tense truth doc + a dated record carrying the story
243
218
 
244
219
  The feature doc states only what is:
245
220
 
@@ -253,17 +228,15 @@ buffered per job (streaming is out of scope — see `docs/history/backlog.md`).
253
228
  And the change-story goes to `docs/history/changelog/2026-06-02-export-extraction.md`:
254
229
 
255
230
  ```markdown
256
- # 2026-06-02 — Export pipeline extracted
257
-
258
- ## Summary
259
-
260
- Extracted export logic from the `reports` worker into `src/export/`.
261
-
262
- ## Changes
263
-
264
- ### Removed
265
-
266
- - `reports/export.js` — replaced by `src/export/run.js`; all callers repointed.
231
+ # 2026-06-02 · export — Export runs as its own pipeline, outside the reports worker
232
+
233
+ - **Ask:** "exports shouldn't stall the reports queue"
234
+ - **Iterations:** 1 · rejected: none
235
+ - **Skills:** none used
236
+ - **Change:** export jobs run in their own pipeline under `src/export/`, so a slow export no longer holds a reports slot; every caller of the old worker entry is repointed
237
+ - **Discovered:** none
238
+ - **Class:** architecture · performance
239
+ - **Pin:** none — candidate: a queue test that a long export leaves report jobs flowing
267
240
  ```
268
241
 
269
242
  **Why it works:** the truth doc needs no archaeology to act on; the dates, the predecessor, and the supersession live in a frozen record; the unbuilt part is a backlog pointer, not a "not yet" hedge; and no stale-reference tripwire survives because the references themselves were fixed.
@@ -277,7 +250,7 @@ Extracted export logic from the `reports` worker into `src/export/`.
277
250
  | Code | Full implementations | Signatures + contracts |
278
251
  | State | Every occurrence | Persistence points only |
279
252
  | Flows | Paragraphs naming functions | Labelled bullets in plain words, a role-level diagram beside them |
280
- | Changelogs | "Updated X" | Function names + migrations |
253
+ | Changelogs | "Updated X" | Behavior first, then the ask, rejections and what running it taught |
281
254
  | Decisions | New doc per revision | One AD per subject, updated in place |
282
255
  | History | Narrated in the doc | Present-tense doc + dated record |
283
256
  | Length | Padded with mechanism | The genre's own expectation; length is a signal, never a target |
@@ -2,11 +2,11 @@
2
2
 
3
3
  Load when: creating a document that carries frontmatter, updating one whose subject moved, or running a baseline or reconcile pass over many documents.
4
4
 
5
- This reference states how a document joins the knowledge graph, and it is kept in step with the machine that reads it: the knowledge layer (`docs/architecture/systems/knowledge-layer.md` in a repository that carries it; § Documents and code). Where this reference and that design disagree, the design is the authority and this file is the defect.
5
+ This reference states how a document joins the knowledge graph, and it is kept in step with the machine that reads it: the knowledge layer (`docs/architecture/systems/knowledge-layer.md` in a repository that carries it; § Documents and code). Where this reference and that design disagree, the design is the authority and this file is the defect; where a repository carries no such design, this file is the authority.
6
6
 
7
7
  ## The model
8
8
 
9
- A document names the product objects it designs. Every other edge between a document and the code is either authored on the code's side or computed, never typed into the document.
9
+ A document names the product objects it designs. Every other edge between a document and the code is either authored on the code's side or computed, never typed into the document. The harness's ownership scan reads one edge today, the transitional `owns:` region glob (§ `owns:`); principles 2 and 3 are the edges it switches to, and the header pointer is written now so the switch needs no second pass over the code.
10
10
 
11
11
  ### Principles
12
12
 
@@ -30,14 +30,14 @@ A document names the product objects it designs. Every other edge between a docu
30
30
  | Acceptance criteria | `type`, `description`, `status` |
31
31
  | Every other genre | `type`, `description`, plus its template's own keys |
32
32
 
33
- Tooling keys sit beside these on any genre: `rev:` (a generator's generation stamp), `slug:` (the identity key on generated documents, minted once, and in the repository the filename), and `last-reviewed:` (stamped on a substantive review, the `maintenance` agent's staleness signal). Sessions preserve them on edits and never narrate or inject them. The `maintenance` agent stamps `type:` where it is missing.
33
+ Tooling keys sit beside these on any genre: `rev:` (a generator's generation stamp), `slug:` (the identity key on generated documents, minted once, and in the repository the filename), `last-reviewed:` (stamped on a substantive review, the `maintenance` agent's staleness signal), `last-updated:` (an Architecture Decision's revision stamp, bumped with each Decision Changelog entry) and `harness-version:` (stamped on `docs/structure.md` by the `maintenance` agent). Sessions preserve them on edits, stamp `last-reviewed:` and `last-updated:` where their genre says so, and never narrate them. The `maintenance` agent stamps `type:` where it is missing.
34
34
 
35
35
  ## Keys
36
36
 
37
37
  ### `description:`
38
38
 
39
39
  - **Values:** one plain string of at most 300 characters on one line: what the document settles and where its boundary sits, in one or two third-person, present-tense sentences. "How a person signs in to NuStack — the web, command-line and desktop doors, the session each mints, and what a refused sign-in shows; enterprise single sign-on is its own document." The description does not open with "This document"; it carries no file list, no date and no status.
40
- - **Required on:** every truth document and every folder index; a record carries it wherever its template has frontmatter (a changelog entry's one-line summary is its row in `CHANGELOG.md`). A frozen record that predates the key is never edited to add it. Exempt: `docs/structure.md`, which the installer writes whole; `docs/operations/bookkeeping.md`, which the hooks write from a fixed header; and a tree a generator owns (`docs/dna/`, the product-dna skill's). A release note under `docs/operations/release-notes/` is a record, frozen at publication.
40
+ - **Required on:** every truth document and every folder index; a record carries it wherever its template has frontmatter (a changelog entry has none: its heading line is its summary). A frozen record that predates the key is never edited to add it. Exempt: `docs/structure.md`, which the installer writes whole; `docs/operations/bookkeeping.md`, which the hooks write from a fixed header; and a tree a generator owns (`docs/dna/`, the product-dna skill's). A release note under `docs/operations/release-notes/` is a record, frozen at publication.
41
41
  - **Reading:** it is how a folder is browsed without an index row per file: `grep -m1 '^description:' docs/features/*.md`. Tooling that lists documents shows it beside the path.
42
42
  - **Upkeep:** an edit that changes what a document settles updates its description in the same edit.
43
43
 
@@ -50,7 +50,7 @@ Tooling keys sit beside these on any genre: `rev:` (a generator's generation sta
50
50
 
51
51
  ### `status:`
52
52
 
53
- - **Values:** `active`, `draft` or `deprecated`. It steers a reader toward live documents.
53
+ - **Values:** `active`, `draft` or `deprecated`. It steers a reader toward live documents. An Architecture Decision keeps its own lifecycle, `Proposed`, `Accepted` or `Deprecated` (`templates/architecture-decision.md`).
54
54
 
55
55
  ### `module:`
56
56
 
@@ -72,8 +72,8 @@ Tooling keys sit beside these on any genre: `rev:` (a generator's generation sta
72
72
 
73
73
  | Key | Retired because | What replaces it |
74
74
  | --- | --- | --- |
75
- | `applies:` | A list of governing documents is a hand-kept copy of a relationship the graph computes through the objects both documents name, and it drifts the way any copy does | The objects the doctrine and the surface share, computed; for people, the document's Scope section names its governing doctrine and what each settles |
76
- | `keywords:` | An object's name and aliases are its discovery terms | `objects:` |
75
+ | `applies:` | A list of governing documents is a hand-kept copy of a relationship the graph computes through the objects both documents name, and it drifts the way any copy does | The objects the doctrine and the surface share, computed; for people, the document's Scope section (a UX document's Purpose) names its governing doctrine and what each settles |
76
+ | `keywords:` | An object's name and aliases are its discovery terms | `objects:`. The ownership scan still shows a document's `keywords:` in the index when it names no `objects:`, so removing the key without adding `objects:` empties that entry |
77
77
  | A file-level `owns:` list | The header pointers and the object closure compute it | Region globs only, until the scan switches (above) |
78
78
 
79
79
  An edit to a document that carries a retired key removes the key in the same edit.