@nurix/etna 0.19.20 → 0.19.22
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.
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/.prettierignore +6 -0
- package/data/harnesses/code/CLAUDE.md +15 -14
- package/data/harnesses/code/agents/maintenance.md +1 -1
- package/data/harnesses/code/codex/agents/maintenance.toml +1 -1
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/skills/boundary/SKILL.md +1 -1
- package/data/harnesses/code/skills/brainstorm/SKILL.md +1 -1
- package/data/harnesses/code/skills/documentation/SKILL.md +64 -107
- package/data/harnesses/code/skills/documentation/references/examples.md +83 -7
- package/data/harnesses/code/skills/documentation/references/frontmatter.md +44 -0
- package/data/harnesses/code/skills/documentation/references/style-guide.md +44 -19
- package/data/harnesses/code/skills/documentation/references/untemplated.md +38 -0
- package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +117 -0
- package/data/harnesses/code/skills/documentation/templates/Readme.md +31 -0
- package/data/harnesses/code/skills/documentation/templates/api-reference.md +20 -0
- package/data/harnesses/code/skills/documentation/templates/architecture-decision.md +121 -0
- package/data/harnesses/code/skills/documentation/templates/backlog.md +33 -0
- package/data/harnesses/code/skills/documentation/templates/changelog-entry.md +62 -0
- package/data/harnesses/code/skills/documentation/templates/changelog-index.md +41 -0
- package/data/harnesses/code/skills/documentation/templates/docs-readme.md +70 -0
- package/data/harnesses/code/skills/documentation/templates/domain-model.md +30 -0
- package/data/harnesses/code/skills/documentation/templates/environment-registry.md +15 -0
- package/data/harnesses/code/skills/documentation/templates/feature.md +149 -0
- package/data/harnesses/code/skills/documentation/templates/glossary.md +11 -0
- package/data/harnesses/code/skills/documentation/templates/memory-main.md +25 -0
- package/data/harnesses/code/skills/documentation/templates/migration-runbook.md +34 -0
- package/data/harnesses/code/skills/documentation/templates/non-goals.md +11 -0
- package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +36 -0
- package/data/harnesses/code/skills/documentation/templates/plan.md +64 -0
- package/data/harnesses/code/skills/documentation/templates/protected-files.md +37 -0
- package/data/harnesses/code/skills/documentation/templates/root-readme.md +104 -0
- package/data/harnesses/code/skills/documentation/templates/security-overview.md +27 -0
- package/data/harnesses/code/skills/documentation/templates/structure.md +65 -0
- package/data/harnesses/code/skills/documentation/templates/system-overview.md +32 -0
- package/data/harnesses/code/skills/documentation/templates/testing-strategy.md +29 -0
- package/data/harnesses/code/skills/workflow-mapper/SKILL.md +1 -1
- package/data/harnesses/discover/.prettierignore +6 -0
- package/data/harnesses/discover/CLAUDE.md +11 -12
- package/data/harnesses/discover/harness.json +2 -2
- package/data/harnesses/discover/tooling-recommendations.md +10 -10
- package/data/harnesses/discussion/.prettierignore +6 -0
- package/data/harnesses/discussion/harness.json +1 -1
- package/data/harnesses/etna/.prettierignore +6 -0
- package/data/harnesses/etna/CLAUDE.md +12 -11
- package/data/harnesses/etna/agents/maintenance.md +1 -1
- package/data/harnesses/etna/codex/agents/maintenance.toml +1 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/boundary/SKILL.md +1 -1
- package/data/harnesses/etna/skills/brainstorm/SKILL.md +1 -1
- package/data/harnesses/etna/skills/documentation/SKILL.md +64 -107
- package/data/harnesses/etna/skills/documentation/references/examples.md +83 -7
- package/data/harnesses/etna/skills/documentation/references/frontmatter.md +44 -0
- package/data/harnesses/etna/skills/documentation/references/style-guide.md +44 -19
- package/data/harnesses/etna/skills/documentation/references/untemplated.md +38 -0
- package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +117 -0
- package/data/harnesses/etna/skills/documentation/templates/Readme.md +31 -0
- package/data/harnesses/etna/skills/documentation/templates/api-reference.md +20 -0
- package/data/harnesses/etna/skills/documentation/templates/architecture-decision.md +121 -0
- package/data/harnesses/etna/skills/documentation/templates/backlog.md +33 -0
- package/data/harnesses/etna/skills/documentation/templates/changelog-entry.md +62 -0
- package/data/harnesses/etna/skills/documentation/templates/changelog-index.md +41 -0
- package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +70 -0
- package/data/harnesses/etna/skills/documentation/templates/domain-model.md +30 -0
- package/data/harnesses/etna/skills/documentation/templates/environment-registry.md +15 -0
- package/data/harnesses/etna/skills/documentation/templates/feature.md +149 -0
- package/data/harnesses/etna/skills/documentation/templates/glossary.md +11 -0
- package/data/harnesses/etna/skills/documentation/templates/memory-main.md +25 -0
- package/data/harnesses/etna/skills/documentation/templates/migration-runbook.md +34 -0
- package/data/harnesses/etna/skills/documentation/templates/non-goals.md +11 -0
- package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +36 -0
- package/data/harnesses/etna/skills/documentation/templates/plan.md +64 -0
- package/data/harnesses/etna/skills/documentation/templates/protected-files.md +37 -0
- package/data/harnesses/etna/skills/documentation/templates/root-readme.md +104 -0
- package/data/harnesses/etna/skills/documentation/templates/security-overview.md +27 -0
- package/data/harnesses/etna/skills/documentation/templates/structure.md +65 -0
- package/data/harnesses/etna/skills/documentation/templates/system-overview.md +32 -0
- package/data/harnesses/etna/skills/documentation/templates/testing-strategy.md +29 -0
- package/data/harnesses/etna/skills/workflow-mapper/SKILL.md +1 -1
- package/data/harnesses/hr/.prettierignore +6 -0
- package/data/harnesses/hr/CLAUDE.md +19 -23
- package/data/harnesses/hr/harness.json +2 -2
- package/data/harnesses/hr/skills/evaluator/SKILL.md +1 -1
- package/data/harnesses/hr/skills/interview-eval/SKILL.md +1 -1
- package/data/harnesses/kb-agi/.prettierignore +6 -0
- package/data/harnesses/kb-agi/CLAUDE.md +12 -12
- package/data/harnesses/kb-agi/harness.json +1 -1
- package/package.json +1 -1
- package/data/harnesses/code/skills/documentation/references/templates.md +0 -1091
- package/data/harnesses/etna/skills/documentation/references/templates.md +0 -1091
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: documentation
|
|
3
|
-
description:
|
|
3
|
+
description: Invoke BEFORE creating or substantively editing ANY markdown doc. 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.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Technical Documentation Skill
|
|
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. Breaking changes belong in changelogs only, not module docs.
|
|
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.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Present tense, always
|
|
15
|
+
|
|
16
|
+
**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.
|
|
17
|
+
|
|
18
|
+
| ❌ Strip this | ✅ Write this |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| "Build Sequence phases 0–4 are complete." | Nothing — progress lives in the plan/backlog record |
|
|
21
|
+
| "There is no standalone `skills/components/` — treat any reference to it as stale." | Nothing — fix the references; state only the present design |
|
|
22
|
+
| "Folded in from the `NuStack-X` repo (2026-06-12)." | "Vendor-connector catalogue; one subpath per vendor." |
|
|
23
|
+
| "was X, now Y", "the old worker", "Phase 2 softened this", "v1 → v2" | The current fact, with no predecessor named |
|
|
24
|
+
|
|
25
|
+
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.
|
|
26
|
+
|
|
27
|
+
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.
|
|
11
28
|
|
|
12
29
|
---
|
|
13
30
|
|
|
@@ -25,10 +42,10 @@ Every document is exactly one of two things. Decide which before writing a word
|
|
|
25
42
|
|
|
26
43
|
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.
|
|
27
44
|
|
|
28
|
-
- **Truth documents never narrate history
|
|
45
|
+
- **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.
|
|
29
46
|
- **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.
|
|
30
|
-
- **
|
|
31
|
-
- **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 — never
|
|
47
|
+
- **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.
|
|
48
|
+
- **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.)
|
|
32
49
|
|
|
33
50
|
**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.
|
|
34
51
|
|
|
@@ -36,51 +53,43 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
36
53
|
|
|
37
54
|
---
|
|
38
55
|
|
|
39
|
-
##
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
├─ "Create/update root README" ────▶ Project Root README Template
|
|
77
|
-
│
|
|
78
|
-
├─ "Create/update plan" ───────────▶ Plan Template (record)
|
|
79
|
-
│
|
|
80
|
-
├─ "Update existing doc" ──────────▶ Preserve existing structure
|
|
81
|
-
│
|
|
82
|
-
└─ No template matches ────────────▶ Co-Authoring Workflow (below)
|
|
83
|
-
```
|
|
56
|
+
## Routing
|
|
57
|
+
|
|
58
|
+
| Request | Route |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| Baseline / reconcile docs | `maintenance` agent (baseline mode) — it calls this skill per template |
|
|
61
|
+
| Document feature/module (LLD) | [`templates/feature.md`](templates/feature.md) |
|
|
62
|
+
| Document data flow / state / Redux | [`templates/feature.md`](templates/feature.md) — they are sections of the feature doc |
|
|
63
|
+
| Create/update changelog | [`templates/changelog-entry.md`](templates/changelog-entry.md) (record) |
|
|
64
|
+
| Create/update plan | [`templates/plan.md`](templates/plan.md) (record) |
|
|
65
|
+
| Record/revise architecture decision | [`templates/architecture-decision.md`](templates/architecture-decision.md) — one AD per subject; revisions update it in place |
|
|
66
|
+
| System at a glance | [`templates/system-overview.md`](templates/system-overview.md) |
|
|
67
|
+
| Domain model | [`templates/domain-model.md`](templates/domain-model.md) |
|
|
68
|
+
| Glossary | [`templates/glossary.md`](templates/glossary.md) |
|
|
69
|
+
| Non-goals | [`templates/non-goals.md`](templates/non-goals.md) |
|
|
70
|
+
| Catalog the API surface | [`templates/api-reference.md`](templates/api-reference.md) |
|
|
71
|
+
| Document env vars / config | [`templates/environment-registry.md`](templates/environment-registry.md) |
|
|
72
|
+
| Security / threat model | [`templates/security-overview.md`](templates/security-overview.md) |
|
|
73
|
+
| Testing strategy | [`templates/testing-strategy.md`](templates/testing-strategy.md) |
|
|
74
|
+
| Recurring procedure/setup | [`templates/operations-procedure.md`](templates/operations-procedure.md) |
|
|
75
|
+
| One-shot migration/upgrade | [`templates/migration-runbook.md`](templates/migration-runbook.md) (record) |
|
|
76
|
+
| Add to protected files | [`templates/protected-files.md`](templates/protected-files.md) |
|
|
77
|
+
| Create/update root README | [`templates/root-readme.md`](templates/root-readme.md) |
|
|
78
|
+
| Scaffold a standard doc (docs index, `structure.md`, CHANGELOG, backlog, memory) | [`templates/Readme.md`](templates/Readme.md) — the index names each scaffold file |
|
|
79
|
+
| Derive/update a feature doc's `owns:` | [`references/frontmatter.md`](references/frontmatter.md) |
|
|
80
|
+
| Update existing doc | § Editing an existing doc (below) |
|
|
81
|
+
| Instruction file (`CLAUDE.md`, a rule, an agent, skill prose) | Not these templates — every-load prose stays lean: assertion—reason bullets, tables over diagrams, no ASCII; the present-tense rule still applies |
|
|
82
|
+
| **No template matches** | [`references/untemplated.md`](references/untemplated.md) — shape decisions + the co-authoring workflow |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Editing an existing doc
|
|
87
|
+
|
|
88
|
+
"Substantive" = anything beyond typo, link, or formatting fixes. On a substantive edit:
|
|
89
|
+
|
|
90
|
+
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.
|
|
91
|
+
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).
|
|
92
|
+
3. **Stamp and re-derive.** A substantive feature-doc update bumps `last-reviewed:`; if the documented scope moved, update `owns:` ([`references/frontmatter.md`](references/frontmatter.md)).
|
|
84
93
|
|
|
85
94
|
---
|
|
86
95
|
|
|
@@ -104,62 +113,7 @@ User request
|
|
|
104
113
|
|
|
105
114
|
## Frontmatter Derivation
|
|
106
115
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
### When to run
|
|
110
|
-
|
|
111
|
-
- **Baseline / reconcile** — for every feature doc whose code paths aren't yet declared in its `owns:` frontmatter (the `maintenance` agent (baseline mode) calls this)
|
|
112
|
-
- **New feature doc** — when creating a doc via the Feature template, project its `owns:` globs
|
|
113
|
-
- **Doc update** — when the documented scope changes, update the doc's `owns:` globs
|
|
114
|
-
|
|
115
|
-
### How to derive the frontmatter
|
|
116
|
-
|
|
117
|
-
A feature doc's launch-map frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body.
|
|
118
|
-
|
|
119
|
-
**1. `owns:`** (the path scope)
|
|
120
|
-
|
|
121
|
-
Read the doc's content. Extract every source file path it references (file listings, function locations, component paths). Group them into the narrowest glob patterns that cover all referenced files without overlapping another doc's `owns:` globs at equal specificity. A doc may own several globs.
|
|
122
|
-
|
|
123
|
-
| Doc references | Glob |
|
|
124
|
-
| ------------------------------------ | ------------------------- |
|
|
125
|
-
| Multiple files under one directory | `src/feature/**` |
|
|
126
|
-
| Specific files in a shared directory | List each file explicitly |
|
|
127
|
-
| A single entry-point file | The exact file path |
|
|
128
|
-
|
|
129
|
-
Glob each pattern against the codebase; drop any that match nothing.
|
|
130
|
-
|
|
131
|
-
**2. `module:`**
|
|
132
|
-
|
|
133
|
-
The single bounded-context label this feature belongs to, or omit it for a cross-cutting feature that belongs to no single context. A module is a label, not a folder — features sharing a `module:` value are what ties that module to code (a filter over the generated ownership index).
|
|
134
|
-
|
|
135
|
-
**3. `keywords:` & `status:`**
|
|
136
|
-
|
|
137
|
-
`keywords:` are the discovery terms topic→doc lookup rides. `status:` is `active`, `draft`, or `deprecated` — it steers the model toward live docs and away from draft/deprecated ones.
|
|
138
|
-
|
|
139
|
-
A doc's dependencies on other docs are expressed inline in its prose (links); cross-cutting contracts are diagnosed by the `boundary` skill from source, not persisted.
|
|
140
|
-
|
|
141
|
-
### Rules
|
|
142
|
-
|
|
143
|
-
- One canonical doc per path. A doc's `owns:` globs must not overlap another doc's at equal specificity — the narrower glob wins; equal-specificity overlap is an ownership conflict to resolve.
|
|
144
|
-
- Use glob patterns for directories, explicit paths for individual files. Don't list paths that don't exist in the codebase.
|
|
145
|
-
- When a doc covers a deep feature with sub-specs (e.g., `editor/`), each sub-spec owns its own globs — don't duplicate a path across siblings.
|
|
146
|
-
- For baseline/reconcile with many docs, use parallel sub-agents to read source and propose `owns:` globs.
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## Co-Authoring Workflow
|
|
151
|
-
|
|
152
|
-
For docs that don't match templates:
|
|
153
|
-
|
|
154
|
-
**Stage 1: Context Gathering**
|
|
155
|
-
|
|
156
|
-
- Ask: Audience? Purpose? Existing format?
|
|
157
|
-
- Have user dump all context, then ask 5-10 clarifying questions
|
|
158
|
-
|
|
159
|
-
**Stage 2: Structure & Draft**
|
|
160
|
-
|
|
161
|
-
- Propose section structure, draft section by section
|
|
162
|
-
- User indicates changes (don't edit directly — learn their style)
|
|
116
|
+
A feature doc carries ownership frontmatter — `owns:` (required), `module:` (optional), `keywords:` (required), `status:` (required), optional `last-reviewed:`. Deriving it from code and keeping it accurate is [`references/frontmatter.md`](references/frontmatter.md) — every feature-doc create or update, and the `maintenance` agent's baseline pass, route there.
|
|
163
117
|
|
|
164
118
|
---
|
|
165
119
|
|
|
@@ -167,6 +121,9 @@ For docs that don't match templates:
|
|
|
167
121
|
|
|
168
122
|
| File | Use For |
|
|
169
123
|
| --- | --- |
|
|
170
|
-
| `
|
|
124
|
+
| `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 |
|
|
171
125
|
| `references/style-guide.md` | Writing rules, formatting conventions, the two-natures tense rules |
|
|
126
|
+
| `references/frontmatter.md` | Deriving a feature doc's `owns:` / `module:` / `keywords:` / `status:` from code |
|
|
127
|
+
| `references/untemplated.md` | How to write a document no template covers (nature, placement, shape) + the co-authoring workflow |
|
|
172
128
|
| `references/examples.md` | Good vs bad documentation examples |
|
|
129
|
+
| `scripts/doc-lint.mjs` | Mechanical checks over written docs (tense narration, dates, stubs, redirects) — run over changed docs before finishing |
|
|
@@ -21,11 +21,15 @@ function mergeData(server, local, changes) { const result = {}; const serverMap
|
|
|
21
21
|
```markdown
|
|
22
22
|
### `mergeData(serverData, localData, changes)`
|
|
23
23
|
|
|
24
|
-
**Goal:** Merge server data with local changes
|
|
24
|
+
**Goal:** Merge server data with local changes
|
|
25
|
+
|
|
26
|
+
**Input:**
|
|
25
27
|
|
|
26
28
|
- `serverData` (array) - Fresh from API
|
|
27
29
|
- `localData` (array) - Current state
|
|
28
|
-
- `changes` (object) - `{ added, updated, removed }`
|
|
30
|
+
- `changes` (object) - `{ added, updated, removed }`
|
|
31
|
+
|
|
32
|
+
**Output:** `{ merged: array, conflicts: array }`
|
|
29
33
|
|
|
30
34
|
**Merge Rules:**
|
|
31
35
|
|
|
@@ -61,11 +65,22 @@ const [items, setItems] = useState([]);
|
|
|
61
65
|
```markdown
|
|
62
66
|
## State
|
|
63
67
|
|
|
64
|
-
**Frontend (at persistence):**
|
|
68
|
+
**Frontend (at persistence):**
|
|
69
|
+
|
|
70
|
+
{
|
|
71
|
+
"data": [],
|
|
72
|
+
"changes": { "added": [], "updated": [], "removed": [] }
|
|
73
|
+
// "cache": {} // UNUSED: dead key; kept so old persisted state rehydrates
|
|
74
|
+
}
|
|
65
75
|
|
|
66
76
|
**Storage:** localStorage `app_state`
|
|
67
77
|
|
|
68
|
-
**Backend:**
|
|
78
|
+
**Backend:**
|
|
79
|
+
|
|
80
|
+
export const items = pgTable('items', {
|
|
81
|
+
id: text('id').primaryKey(),
|
|
82
|
+
data: jsonb('data'),
|
|
83
|
+
});
|
|
69
84
|
```
|
|
70
85
|
|
|
71
86
|
---
|
|
@@ -144,9 +159,23 @@ When the page loads, the useAppInit hook calls the syncData function. This funct
|
|
|
144
159
|
```markdown
|
|
145
160
|
## Data Flow
|
|
146
161
|
|
|
147
|
-
┌─────────────────────────────────────────┐
|
|
148
|
-
|
|
149
|
-
|
|
162
|
+
┌─────────────────────────────────────────┐
|
|
163
|
+
│ DATA SYNC │
|
|
164
|
+
├─────────────────────────────────────────┤
|
|
165
|
+
│ │
|
|
166
|
+
│ ┌──────┐ ┌──────┐ ┌──────┐ │
|
|
167
|
+
│ │Server│────▶│Merge │────▶│Redux │ │
|
|
168
|
+
│ │ API │ │ │ │Store │ │
|
|
169
|
+
│ └──────┘ └──────┘ └──────┘ │
|
|
170
|
+
│ │ │
|
|
171
|
+
│ ▼ │
|
|
172
|
+
│ Version Check │
|
|
173
|
+
│ │
|
|
174
|
+
└─────────────────────────────────────────┘
|
|
175
|
+
|
|
176
|
+
**Trigger:** `useAppInit()` on page load
|
|
177
|
+
|
|
178
|
+
**Version Rule:** Match → local wins, Mismatch → server wins
|
|
150
179
|
```
|
|
151
180
|
|
|
152
181
|
---
|
|
@@ -191,6 +220,52 @@ We use Better Auth with one-shot credential issuance… ← current truth, no
|
|
|
191
220
|
|
|
192
221
|
---
|
|
193
222
|
|
|
223
|
+
## Example 6: Stripping history from a truth doc
|
|
224
|
+
|
|
225
|
+
The move agents fumble: deleting narration is only half the job — the story must land in a record.
|
|
226
|
+
|
|
227
|
+
### ❌ Bad: The journey narrated in place
|
|
228
|
+
|
|
229
|
+
```markdown
|
|
230
|
+
## Export Pipeline
|
|
231
|
+
|
|
232
|
+
The exporter was extracted from the legacy `reports` worker (2026-06-02) and
|
|
233
|
+
now lives in `src/export/`. Phases 0–2 of the rewrite are complete; streaming
|
|
234
|
+
output is not yet implemented. Treat any reference to `reports/export.js` as
|
|
235
|
+
stale — it was superseded by `src/export/run.js`.
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### ✅ Good: Present-tense truth doc + a dated record carrying the story
|
|
239
|
+
|
|
240
|
+
The feature doc states only what is:
|
|
241
|
+
|
|
242
|
+
```markdown
|
|
243
|
+
## Export Pipeline
|
|
244
|
+
|
|
245
|
+
`src/export/run.js` renders every export format from one job queue. Output is
|
|
246
|
+
buffered per job (streaming is out of scope — see `docs/history/backlog.md`).
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
And the change-story goes to `docs/history/changelog/2026-06-02-export-extraction.md`:
|
|
250
|
+
|
|
251
|
+
```markdown
|
|
252
|
+
# 2026-06-02 — Export pipeline extracted
|
|
253
|
+
|
|
254
|
+
## Summary
|
|
255
|
+
|
|
256
|
+
Extracted export logic from the `reports` worker into `src/export/`.
|
|
257
|
+
|
|
258
|
+
## Changes
|
|
259
|
+
|
|
260
|
+
### Removed
|
|
261
|
+
|
|
262
|
+
- `reports/export.js` — replaced by `src/export/run.js`; all callers repointed.
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**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.
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
194
269
|
## Quick Comparison
|
|
195
270
|
|
|
196
271
|
| Aspect | Bad | Good |
|
|
@@ -200,4 +275,5 @@ We use Better Auth with one-shot credential issuance… ← current truth, no
|
|
|
200
275
|
| Flows | Prose paragraphs | ASCII diagrams |
|
|
201
276
|
| Changelogs | "Updated X" | Function names + migrations |
|
|
202
277
|
| Decisions | New doc per revision | One AD per subject, updated in place |
|
|
278
|
+
| History | Narrated in the doc | Present-tense doc + dated record |
|
|
203
279
|
| Length | 100+ lines | 20-40 lines |
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Frontmatter Derivation — feature-doc ownership
|
|
2
|
+
|
|
3
|
+
Load when: creating a feature doc, updating one whose documented scope moved, or running a baseline/reconcile pass over many docs.
|
|
4
|
+
|
|
5
|
+
When creating or updating a feature doc, derive its **`owns:` frontmatter** — the code-path globs it is canonical for — from the source the doc describes. Code ownership lives in each feature doc's `owns:` frontmatter (the SessionStart hook unions them into the injected ownership index); there is no hand-maintained ownership map.
|
|
6
|
+
|
|
7
|
+
## When to run
|
|
8
|
+
|
|
9
|
+
- **Baseline / reconcile** — for every feature doc whose code paths aren't yet declared in its `owns:` frontmatter (the `maintenance` agent (baseline mode) calls this)
|
|
10
|
+
- **New feature doc** — when creating a doc via the [Feature template](../templates/feature.md), project its `owns:` globs
|
|
11
|
+
- **Doc update** — when the documented scope changes, update the doc's `owns:` globs
|
|
12
|
+
|
|
13
|
+
## How to derive the frontmatter
|
|
14
|
+
|
|
15
|
+
A feature doc's ownership frontmatter is `owns:` (required), `module:` (optional), `keywords:` (required), and `status:` (required). An optional `last-reviewed:` date (stamped whenever the doc is substantively reviewed or updated) gives the `maintenance` agent a staleness signal to rank its audits by — it is tooling metadata, never narrated in the body.
|
|
16
|
+
|
|
17
|
+
**1. `owns:`** (the path scope)
|
|
18
|
+
|
|
19
|
+
Read the doc's content. Extract every source file path it references (file listings, function locations, component paths). Group them into the narrowest glob patterns that cover all referenced files without overlapping another doc's `owns:` globs at equal specificity. A doc may own several globs.
|
|
20
|
+
|
|
21
|
+
| Doc references | Glob |
|
|
22
|
+
| ------------------------------------ | ------------------------- |
|
|
23
|
+
| Multiple files under one directory | `src/feature/**` |
|
|
24
|
+
| Specific files in a shared directory | List each file explicitly |
|
|
25
|
+
| A single entry-point file | The exact file path |
|
|
26
|
+
|
|
27
|
+
Glob each pattern against the codebase. At `status: active`, drop any that match nothing; at `status: draft`, projected globs may match nothing yet — confirm them against real code when the doc flips to `active`.
|
|
28
|
+
|
|
29
|
+
**2. `module:`**
|
|
30
|
+
|
|
31
|
+
The single bounded-context label this feature belongs to, or omit it for a cross-cutting feature that belongs to no single context. A module is a label, not a folder — features sharing a `module:` value are what ties that module to code (a filter over the generated ownership index).
|
|
32
|
+
|
|
33
|
+
**3. `keywords:` & `status:`**
|
|
34
|
+
|
|
35
|
+
`keywords:` are the discovery terms topic→doc lookup rides. `status:` is `active`, `draft`, or `deprecated` — it steers the model toward live docs and away from draft/deprecated ones.
|
|
36
|
+
|
|
37
|
+
A doc's dependencies on other docs are expressed inline in its prose (links); cross-cutting contracts are diagnosed by the `boundary` skill from source, not persisted.
|
|
38
|
+
|
|
39
|
+
## Rules
|
|
40
|
+
|
|
41
|
+
- One canonical doc per path. A doc's `owns:` globs must not overlap another doc's at equal specificity — the narrower glob wins; equal-specificity overlap is an ownership conflict to resolve.
|
|
42
|
+
- Use glob patterns for directories, explicit paths for individual files. At `active`, never list paths that don't exist in the codebase; a `draft`'s projected paths are confirmed at `active`.
|
|
43
|
+
- When a doc covers a deep feature with sub-specs (e.g., `editor/`), each sub-spec owns its own globs — don't duplicate a path across siblings.
|
|
44
|
+
- For baseline/reconcile with many docs, use parallel sub-agents to read source and propose `owns:` globs.
|
|
@@ -11,10 +11,16 @@ Writing rules for clear, maintainable documentation.
|
|
|
11
11
|
```markdown
|
|
12
12
|
### `functionName(param1, param2, options)`
|
|
13
13
|
|
|
14
|
-
**Goal:** One-line purpose
|
|
14
|
+
**Goal:** One-line purpose
|
|
15
|
+
|
|
16
|
+
**Input:**
|
|
15
17
|
|
|
16
18
|
- `param1` (type) - Description
|
|
17
|
-
- `param2` (type, optional) - Description
|
|
19
|
+
- `param2` (type, optional) - Description
|
|
20
|
+
|
|
21
|
+
**Output:** `{ field1, field2 }`
|
|
22
|
+
|
|
23
|
+
**Side Effects:** State updates, API calls, etc.
|
|
18
24
|
```
|
|
19
25
|
|
|
20
26
|
### Parameter Rules
|
|
@@ -62,34 +68,33 @@ Always specify:
|
|
|
62
68
|
```json
|
|
63
69
|
{
|
|
64
70
|
"activeField": "value"
|
|
65
|
-
// "deprecated": null // UNUSED:
|
|
71
|
+
// "deprecated": null // UNUSED: dead key; kept so old persisted state rehydrates
|
|
66
72
|
}
|
|
67
73
|
```
|
|
68
|
-
````
|
|
69
74
|
|
|
70
75
|
**Storage:** localStorage key `state_key`
|
|
71
76
|
|
|
72
77
|
**Backend:**
|
|
73
78
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
id
|
|
77
|
-
data
|
|
78
|
-
// old
|
|
79
|
-
}
|
|
79
|
+
```ts
|
|
80
|
+
export const table = pgTable('table', {
|
|
81
|
+
id: text('id').primaryKey(),
|
|
82
|
+
data: jsonb('data'),
|
|
83
|
+
// old: text('old'), // UNUSED: dead column; nothing reads it
|
|
84
|
+
});
|
|
80
85
|
```
|
|
81
|
-
|
|
82
86
|
````
|
|
83
87
|
|
|
84
88
|
### Mark Unused Keys
|
|
85
89
|
|
|
86
|
-
Always comment deprecated/unused fields:
|
|
90
|
+
Always comment deprecated/unused fields. The annotation states why the field is dead _now_ — never where it went, what replaced it, or when it will be removed (no "Remove in v3", no "Migrated to newField"; that is history narration, § The Two Natures below):
|
|
91
|
+
|
|
87
92
|
```json
|
|
88
93
|
{
|
|
89
94
|
"active": [],
|
|
90
|
-
// "legacy": {} // UNUSED:
|
|
95
|
+
// "legacy": {} // UNUSED: dead key; kept for rehydrate compatibility
|
|
91
96
|
}
|
|
92
|
-
|
|
97
|
+
```
|
|
93
98
|
|
|
94
99
|
---
|
|
95
100
|
|
|
@@ -102,6 +107,8 @@ Always comment deprecated/unused fields:
|
|
|
102
107
|
- Component interactions
|
|
103
108
|
- Process flows
|
|
104
109
|
|
|
110
|
+
**Docs only.** Diagrams belong in documents read on demand (feature docs, ADs, operations). Instruction files — `CLAUDE.md`, rules, agent definitions, `SKILL.md` prose — never carry them: they load on every turn or every invocation, and a table or a sentence carries the same information at a fraction of the tokens.
|
|
111
|
+
|
|
105
112
|
### Pattern
|
|
106
113
|
|
|
107
114
|
```
|
|
@@ -168,6 +175,8 @@ function extract(json) {
|
|
|
168
175
|
|
|
169
176
|
❌ Bad: Full 50-line implementation
|
|
170
177
|
|
|
178
|
+
(Worked example: [`examples.md`](examples.md) Example 1.)
|
|
179
|
+
|
|
171
180
|
---
|
|
172
181
|
|
|
173
182
|
## Writing Style
|
|
@@ -191,7 +200,7 @@ Prose is valuable for context that contracts can't capture:
|
|
|
191
200
|
| Non-obvious behavior | "The hook always fetches fresh data. There is no caching or version checking." |
|
|
192
201
|
| Design rationale | "Why parallel fetches? Each entity type is independent, reducing load time." |
|
|
193
202
|
| Edge cases | "If created then deleted before save, it's removed from `added[]` without adding to `removed[]`." |
|
|
194
|
-
|
|
|
203
|
+
| Limitations, stated as facts | "`useAppInit` is standalone — nothing in the mount path calls it." |
|
|
195
204
|
| Usage context | "Used to show 'Unsaved' badge, warn before navigation, enable save buttons." |
|
|
196
205
|
|
|
197
206
|
### When to Avoid Prose
|
|
@@ -224,7 +233,7 @@ Use for structured info:
|
|
|
224
233
|
|
|
225
234
|
Every document is a **truth document** (states current absolutes, updated in place) or a **record** (dated account of activity, frozen or append-only) — see `SKILL.md` § The Two Natures. The tense rules follow directly:
|
|
226
235
|
|
|
227
|
-
**Truth documents describe the present, not the past.** Everything outside `docs/history/` states what the system _is_ and how it works _today_. It must not narrate how it got there. The journey — the dates, the migrations — lives **only** in records (`docs/history/`: changelog, plans, migrations).
|
|
236
|
+
**Truth documents describe the present, not the past.** Everything outside `docs/history/` states what the system _is_ and how it works _today_. It must not narrate how it got there. The journey — the dates, the migrations — lives **only** in records (`docs/history/`: changelog, plans, migrations). Three sanctioned exceptions: `docs/memory/` is the agent's own dated ledger; an AD's **Decision Changelog** tail carries that decision's dated revision history; and `docs/structure.md`'s **Health Log** tail carries the maintenance agent's tooling-stamped audit rows. In both tail bridges the body stays current-truth-only — head is truth, tail is provenance.
|
|
228
237
|
|
|
229
238
|
**Records are never edited to match the present.** A frozen plan stays wrong-in-hindsight; a changelog entry describes what shipped as it shipped. A scope change gets a new dated record that links back.
|
|
230
239
|
|
|
@@ -236,16 +245,31 @@ Strip this language from truth documents:
|
|
|
236
245
|
| "Built 2026-06-14; shipped + verified 2026-06-13." | "`agentSessionWorkflow` runs an outer turn loop over `runAgentLoop`." |
|
|
237
246
|
| "The legacy worker was deleted in the 2026-06-14 fold." | "One worker interprets `WorkflowDefinition`." |
|
|
238
247
|
| "ex-`@nurix/mcp-runtime`, M9 Phase C; was X, now Y." | "MCP client runtime, wired into `agentTriggerWorkflow`." |
|
|
248
|
+
| "Build Sequence phases 0–4 are complete." | Nothing — progress lives in the plan/backlog record; the doc describes what exists |
|
|
249
|
+
| "There is no standalone `skills/components/` — treat any reference to it as stale." | Nothing — delete or repoint the stale references; state only the present design |
|
|
239
250
|
| "Read first: `docs/history/plans/2026-…-fold.md`" (routing) | "Read first: `docs/architecture/<current-truth-doc>.md`" |
|
|
240
251
|
|
|
241
252
|
Rules:
|
|
242
253
|
|
|
243
|
-
- **No dates in truth documents
|
|
254
|
+
- **No dates and no progress narration in truth documents.** Nothing about _when_ something shipped, was verified, folded, or was removed — and no completion markers either: no "phases 0–4 are complete", no per-item `✅ shipped` / `⏳ pending`. Progress tracking is a **record's** job (the plan, the backlog); a truth document describes what exists, as if it had always been so.
|
|
255
|
+
- **No stale-reference tripwires.** Never write "X is gone — treat references to X as stale"; that is a redirect doc compressed into one sentence. Delete or repoint every stale reference instead (same rule as the **No redirect docs** rule in `SKILL.md` § The Two Natures) and state only the present fact.
|
|
256
|
+
- **No version or phase framing.** A bare `v1`/`v2` as a label, "Phase 1/2", "the old X", "supersedes the earlier" — there is one design; describe it without its predecessors. (A version naming an external present-tense fact stays: a schema literal like `design-tokens/v2`, a dependency pin like `@0.14.0`.)
|
|
257
|
+
- **Temporal hedges are progress markers in prose.** "currently", "not yet", "still", "for now" smuggle a ⏳ into a truth document — state the fact without the hedge ("the hook is standalone; nothing in the mount path calls it") and let the backlog record carry the intention.
|
|
258
|
+
- **A published artifact's own version surface is external fact.** Release notes and upgrade guides for a shipped package may use version framing (`v1 → v2`) — that is the artifact's public contract, not the doc narrating its own past. They live beside the artifact or under `docs/operations/`, never in `docs/features/` or `docs/architecture/`.
|
|
244
259
|
- **Cite the AD for the _why_, never the _when_.** `Provenance: AD-002` is good (it points to the decision rationale). "Decided in AD-002 and shipped 2026-06-13" is not.
|
|
245
|
-
- **Routing/index docs point only to truth documents.** A row whose
|
|
260
|
+
- **Routing/index docs point only to truth documents as a topic's authority.** A row whose "read first" target for a topic is a historical plan or changelog is a redirect-for-history — repoint it to the current truth doc, or drop the row. (An index _of the records themselves_ — a History section listing `plans/`, `changelog/` — is sanctioned: that indexes records, it doesn't route a topic.)
|
|
246
261
|
- **When a doc changes because the system changed, the change-story goes in `docs/history/` (a changelog entry), and the truth document simply becomes correct in present tense.** Never leave the diff narrated in place.
|
|
247
262
|
- **A decision that moves is an edit, not a new document.** Rewrite the AD's affected sections to the new truth and append the revision to its Decision Changelog — never mint a parallel doc and never leave the old choice narrated in the body.
|
|
248
263
|
|
|
264
|
+
Worked example of the strip-and-relocate move: [`examples.md`](examples.md) Example 6.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Mechanics
|
|
269
|
+
|
|
270
|
+
- Inline-code every identifier, filename, command, and config key.
|
|
271
|
+
- Bullet rules take the form "**bold assertion** — explanation."
|
|
272
|
+
|
|
249
273
|
---
|
|
250
274
|
|
|
251
275
|
## Structure
|
|
@@ -309,7 +333,8 @@ Always end with:
|
|
|
309
333
|
| Parameters | Type + purpose |
|
|
310
334
|
| Returns | Type + shape |
|
|
311
335
|
| State | Persistence points only |
|
|
312
|
-
| Diagrams | ASCII for all flows
|
|
336
|
+
| Diagrams | ASCII for all flows — docs only, never instruction files |
|
|
313
337
|
| Code | Under 15 lines, contracts only |
|
|
314
338
|
| Voice | Imperative/active |
|
|
339
|
+
| Mechanics | Inline-code identifiers; bold-assertion bullets |
|
|
315
340
|
| Length | Concise, one line when possible |
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Writing an Untemplated Document
|
|
2
|
+
|
|
3
|
+
Load when: no template in [`templates/`](../templates/Readme.md) matches the document being written — a design note, a comparison, an investigation writeup, an index, a reference sheet, anything the Routing table sends to "no template matches".
|
|
4
|
+
|
|
5
|
+
A template is a pre-made set of shape decisions. With no template, make the same decisions explicitly, in this order.
|
|
6
|
+
|
|
7
|
+
## 1. Decide the nature — truth or record
|
|
8
|
+
|
|
9
|
+
Every document is exactly one (`SKILL.md` § The Two Natures). Ask: *when reality changes, is this file rewritten, or is it frozen?*
|
|
10
|
+
|
|
11
|
+
- Rewritten in place → **truth document**. Topic-named (`kebab-case.md`), lives outside `docs/history/`, present tense throughout — the iron rule in `SKILL.md` § Present tense, always.
|
|
12
|
+
- Frozen or append-only → **record**. Date-named (`YYYY-MM-DD-slug.md`), lives in `docs/history/` — inside an existing subfolder where it fits (an investigation or research writeup → `history/research/{topic}/`); a genuinely new category of record needs a `docs/structure.md` folder-rule row in the same change, never an invented folder.
|
|
13
|
+
|
|
14
|
+
When a draft wants to be both — the current state *and* the story of getting there — split it: the state becomes a truth document, the story becomes a record that links to it. Never mix the natures in one body.
|
|
15
|
+
|
|
16
|
+
## 2. Place and name it
|
|
17
|
+
|
|
18
|
+
- `docs/structure.md` is the placement authority — match the document's topic to its folder map before inventing a location.
|
|
19
|
+
- **One canonical home per topic.** If a document on the topic already exists, extend it; a second document on the same topic is drift waiting to happen. Link, don't copy.
|
|
20
|
+
- A new topic *folder* gets a `Readme.md` landing page that introduces and indexes it.
|
|
21
|
+
|
|
22
|
+
## 3. Shape it
|
|
23
|
+
|
|
24
|
+
- **Open with the goal.** The first line under the H1 states what the document is for and who reads it — a reader (or agent) landing here cold decides in one sentence whether to keep reading.
|
|
25
|
+
- **Headings are retrieval keys.** Sections get pulled out of context by search and agents; qualify generic headings with the topic (`## Merge rules — data sync`, not `## Rules`) so each stands alone.
|
|
26
|
+
- **Tables for enumerable facts, prose for judgment.** One row per item; anything needing a *because* lives in prose around the table, never inside a cell.
|
|
27
|
+
- **Every section earns its place.** No empty stubs — omit what has nothing real to say; write an explicit "None" only where the absence itself is information.
|
|
28
|
+
- **Cite sources and link neighbours.** If the document mentions a concept another document owns, link it; if it draws on code, name the files.
|
|
29
|
+
|
|
30
|
+
## 4. Write it in the house style
|
|
31
|
+
|
|
32
|
+
`references/style-guide.md` carries the rules: present tense with no history narration, progress markers, or stale-reference tripwires (§ The Two Natures); imperative/active voice; code examples under 15 lines showing contracts, not implementations; ASCII diagrams in docs only; inline-code every identifier, filename, command, and config key.
|
|
33
|
+
|
|
34
|
+
## 5. With a human in the loop — the co-authoring workflow
|
|
35
|
+
|
|
36
|
+
**Stage 1 — context gathering.** Ask: audience? purpose? existing format to match? Have the user dump all the context they hold, then ask 5–10 clarifying questions before proposing anything.
|
|
37
|
+
|
|
38
|
+
**Stage 2 — structure & draft.** Propose the section structure from §1–3 above, then draft section by section. The user indicates changes — learn their style from their edits; don't silently rewrite them.
|