@nurix/etna 0.19.33 → 0.19.35

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 (84) hide show
  1. package/data/harness-index.json +5 -1
  2. package/data/harnesses/code/CLAUDE.md +21 -11
  3. package/data/harnesses/code/harness.json +2 -2
  4. package/data/harnesses/code/rules/general.md +1 -0
  5. package/data/harnesses/code/rules/testing.md +1 -1
  6. package/data/harnesses/code/rules/verification.md +51 -0
  7. package/data/harnesses/code/skills/test-plan/SKILL.md +3 -3
  8. package/data/harnesses/delivery/.prettierignore +29 -0
  9. package/data/harnesses/delivery/.prettierrc.json +3 -0
  10. package/data/harnesses/delivery/.vscode/settings.json +19 -0
  11. package/data/harnesses/delivery/CLAUDE.md +123 -0
  12. package/data/harnesses/delivery/agents/brainstorm.md +144 -0
  13. package/data/harnesses/delivery/agents/data-generator.md +23 -0
  14. package/data/harnesses/delivery/agents/eval-runner.md +23 -0
  15. package/data/harnesses/delivery/agents/judge.md +23 -0
  16. package/data/harnesses/delivery/agents/lld-mode.md +56 -0
  17. package/data/harnesses/delivery/agents/maintenance.md +229 -0
  18. package/data/harnesses/delivery/agents/prompt-iterator.md +23 -0
  19. package/data/harnesses/delivery/agents/red-team.md +23 -0
  20. package/data/harnesses/delivery/agents/regression-runner.md +28 -0
  21. package/data/harnesses/delivery/agents/retro.md +46 -0
  22. package/data/harnesses/delivery/codex/agents/brainstorm.toml +142 -0
  23. package/data/harnesses/delivery/codex/agents/data-generator.toml +22 -0
  24. package/data/harnesses/delivery/codex/agents/eval-runner.toml +22 -0
  25. package/data/harnesses/delivery/codex/agents/judge.toml +22 -0
  26. package/data/harnesses/delivery/codex/agents/lld-mode.toml +52 -0
  27. package/data/harnesses/delivery/codex/agents/maintenance.toml +228 -0
  28. package/data/harnesses/delivery/codex/agents/prompt-iterator.toml +22 -0
  29. package/data/harnesses/delivery/codex/agents/red-team.toml +22 -0
  30. package/data/harnesses/delivery/codex/agents/regression-runner.toml +27 -0
  31. package/data/harnesses/delivery/codex/agents/retro.toml +45 -0
  32. package/data/harnesses/delivery/harness.json +11 -0
  33. package/data/harnesses/delivery/hooks/generate-ownership-index.mjs +148 -0
  34. package/data/harnesses/delivery/hooks/hooks.json +16 -0
  35. package/data/harnesses/delivery/rules/changelog.md +19 -0
  36. package/data/harnesses/delivery/rules/evals.md +23 -0
  37. package/data/harnesses/delivery/rules/model-tiers.md +18 -0
  38. package/data/harnesses/delivery/rules/nomenclature.md +34 -0
  39. package/data/harnesses/delivery/rules/prompting.md +23 -0
  40. package/data/harnesses/delivery/skills/brainstorm/README.md +56 -0
  41. package/data/harnesses/delivery/skills/brainstorm/SKILL.md +173 -0
  42. package/data/harnesses/delivery/skills/brainstorm/references/doctrine.md +98 -0
  43. package/data/harnesses/delivery/skills/brainstorm/references/harvest.md +86 -0
  44. package/data/harnesses/delivery/skills/brainstorm/references/session-schema.md +186 -0
  45. package/data/harnesses/delivery/skills/brainstorm/scripts/detector.mjs +460 -0
  46. package/data/harnesses/delivery/skills/cost-report/SKILL.md +24 -0
  47. package/data/harnesses/delivery/skills/documentation/SKILL.md +129 -0
  48. package/data/harnesses/delivery/skills/documentation/references/examples.md +279 -0
  49. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +44 -0
  50. package/data/harnesses/delivery/skills/documentation/references/style-guide.md +340 -0
  51. package/data/harnesses/delivery/skills/documentation/references/untemplated.md +38 -0
  52. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +140 -0
  53. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +31 -0
  54. package/data/harnesses/delivery/skills/documentation/templates/api-reference.md +20 -0
  55. package/data/harnesses/delivery/skills/documentation/templates/architecture-decision.md +121 -0
  56. package/data/harnesses/delivery/skills/documentation/templates/backlog.md +33 -0
  57. package/data/harnesses/delivery/skills/documentation/templates/changelog-entry.md +57 -0
  58. package/data/harnesses/delivery/skills/documentation/templates/changelog-index.md +41 -0
  59. package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +72 -0
  60. package/data/harnesses/delivery/skills/documentation/templates/domain-model.md +30 -0
  61. package/data/harnesses/delivery/skills/documentation/templates/environment-registry.md +15 -0
  62. package/data/harnesses/delivery/skills/documentation/templates/feature.md +149 -0
  63. package/data/harnesses/delivery/skills/documentation/templates/glossary.md +11 -0
  64. package/data/harnesses/delivery/skills/documentation/templates/memory-main.md +25 -0
  65. package/data/harnesses/delivery/skills/documentation/templates/migration-runbook.md +34 -0
  66. package/data/harnesses/delivery/skills/documentation/templates/non-goals.md +11 -0
  67. package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +36 -0
  68. package/data/harnesses/delivery/skills/documentation/templates/plan.md +64 -0
  69. package/data/harnesses/delivery/skills/documentation/templates/protected-files.md +37 -0
  70. package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +104 -0
  71. package/data/harnesses/delivery/skills/documentation/templates/security-overview.md +27 -0
  72. package/data/harnesses/delivery/skills/documentation/templates/structure.md +65 -0
  73. package/data/harnesses/delivery/skills/documentation/templates/system-overview.md +32 -0
  74. package/data/harnesses/delivery/skills/documentation/templates/testing-strategy.md +29 -0
  75. package/data/harnesses/delivery/skills/escalate/SKILL.md +25 -0
  76. package/data/harnesses/delivery/skills/prompt-eval/SKILL.md +22 -0
  77. package/data/harnesses/delivery/skills/prompt-library/SKILL.md +36 -0
  78. package/data/harnesses/delivery/skills/route/SKILL.md +21 -0
  79. package/data/harnesses/etna/CLAUDE.md +1 -1
  80. package/data/harnesses/etna/harness.json +2 -2
  81. package/data/harnesses/etna/rules/general.md +1 -0
  82. package/data/harnesses/etna/rules/testing.md +1 -1
  83. package/data/harnesses/hr/harness.json +1 -1
  84. package/package.json +1 -1
@@ -0,0 +1,279 @@
1
+ # Documentation Examples
2
+
3
+ Good vs bad examples showing the key differences.
4
+
5
+ ---
6
+
7
+ ## Example 1: Function Documentation
8
+
9
+ ### ❌ Bad: Full Implementation
10
+
11
+ ```markdown
12
+ ### mergeData
13
+
14
+ function mergeData(server, local, changes) { const result = {}; const serverMap = new Map(server.map((i) => [i.id, i])); // ... 30 more lines return result; }
15
+ ```
16
+
17
+ **Problems:** Will become obsolete, focuses on HOW not WHAT.
18
+
19
+ ### ✅ Good: Contract Only
20
+
21
+ ```markdown
22
+ ### `mergeData(serverData, localData, changes)`
23
+
24
+ **Goal:** Merge server data with local changes
25
+
26
+ **Input:**
27
+
28
+ - `serverData` (array) - Fresh from API
29
+ - `localData` (array) - Current state
30
+ - `changes` (object) - `{ added, updated, removed }`
31
+
32
+ **Output:** `{ merged: array, conflicts: array }`
33
+
34
+ **Merge Rules:**
35
+
36
+ - Server wins for conflicts
37
+ - Local additions preserved
38
+ - Local removals marked as intent
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Example 2: State Documentation
44
+
45
+ ### ❌ Bad: State Everywhere
46
+
47
+ ```markdown
48
+ ## Component State
49
+
50
+ const [items, setItems] = useState([]);
51
+
52
+ ## Hook State
53
+
54
+ { data: items, isLoading: loading, error: null }
55
+
56
+ ## Redux State
57
+
58
+ { items: [], loading: false, error: null }
59
+ ```
60
+
61
+ **Problems:** Documents transient state, repeats shapes.
62
+
63
+ ### ✅ Good: Persistence Points Only
64
+
65
+ ```markdown
66
+ ## State
67
+
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
+ }
75
+
76
+ **Storage:** localStorage `app_state`
77
+
78
+ **Backend:**
79
+
80
+ export const items = pgTable('items', {
81
+ id: text('id').primaryKey(),
82
+ data: jsonb('data'),
83
+ });
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Example 3: Changelog
89
+
90
+ ### ❌ Bad: Vague
91
+
92
+ ```markdown
93
+ # 2025-01-05 - Updates
94
+
95
+ ## Changes
96
+
97
+ - Updated editor
98
+ - Fixed bugs
99
+ - Improved performance
100
+
101
+ ## Files
102
+
103
+ - Various files in src/
104
+ ```
105
+
106
+ ### ✅ Good: Function-Level Detail
107
+
108
+ ```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)
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Example 4: Data Flow
150
+
151
+ ### ❌ Bad: Prose Description
152
+
153
+ ```markdown
154
+ When the page loads, the useAppInit hook calls the syncData function. This function first fetches data from the server using the API. Then it gets the local data from Redux. After that, it compares versions...
155
+ ```
156
+
157
+ ### ✅ Good: Diagram + Key Points
158
+
159
+ ```markdown
160
+ ## Data Flow
161
+
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
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Example 5: Architecture Decision revision
184
+
185
+ ### ❌ Bad: Supersession chain
186
+
187
+ ```
188
+ docs/architecture/decisions/
189
+ ├── AD-002-auth-keycloak.md (status: Superseded)
190
+ ├── AD-006-auth-better-auth.md (status: Superseded, "supersedes AD-002")
191
+ └── AD-011-auth-better-auth-v2.md (status: Accepted, "supersedes AD-006")
192
+ ```
193
+
194
+ **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.
195
+
196
+ ### ✅ Good: One subject, updated in place
197
+
198
+ ```
199
+ docs/architecture/decisions/
200
+ └── AD-002-auth.md (status: Accepted, last-updated bumped)
201
+ ```
202
+
203
+ ```markdown
204
+ ## Decision
205
+
206
+ We use Better Auth with one-shot credential issuance… ← current truth, no journey
207
+
208
+ …
209
+
210
+ ## Decision Changelog
211
+
212
+ - 2026-05-02 — Moved issuance to one-shot tokens because refresh-token theft
213
+ surfaced in review. Implemented by [plan](…). (Previously: long-lived refresh tokens.)
214
+ - 2026-03-18 — Replaced Keycloak with Better Auth because self-hosting cost
215
+ outweighed SSO needs. Implemented by [plan](…). (Previously: Keycloak.)
216
+ - 2026-01-10 — Initial decision accepted. Implemented by [plan](…).
217
+ ```
218
+
219
+ **Why it works:** The body answers "how does auth work and why" without archaeology; the tail preserves every reversal with its trigger; the rejected alternatives stay findable in the one file a reader actually opens.
220
+
221
+ ---
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
+
269
+ ## Quick Comparison
270
+
271
+ | Aspect | Bad | Good |
272
+ | ---------- | -------------------- | --------------------------- |
273
+ | Code | Full implementations | Signatures + contracts |
274
+ | State | Every occurrence | Persistence points only |
275
+ | Flows | Prose paragraphs | ASCII diagrams |
276
+ | Changelogs | "Updated X" | Function names + migrations |
277
+ | Decisions | New doc per revision | One AD per subject, updated in place |
278
+ | History | Narrated in the doc | Present-tense doc + dated record |
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.
@@ -0,0 +1,340 @@
1
+ # Documentation Style Guide
2
+
3
+ Writing rules for clear, maintainable documentation.
4
+
5
+ ---
6
+
7
+ ## Function Documentation
8
+
9
+ ### Signature Format
10
+
11
+ ```markdown
12
+ ### `functionName(param1, param2, options)`
13
+
14
+ **Goal:** One-line purpose
15
+
16
+ **Input:**
17
+
18
+ - `param1` (type) - Description
19
+ - `param2` (type, optional) - Description
20
+
21
+ **Output:** `{ field1, field2 }`
22
+
23
+ **Side Effects:** State updates, API calls, etc.
24
+ ```
25
+
26
+ ### Parameter Rules
27
+
28
+ - Name + type + one-line purpose
29
+ - Mark optional params with `(type, optional)`
30
+ - Nest object properties:
31
+ ```markdown
32
+ - `options` (object) - Configuration
33
+ - `options.retry` (boolean) - Enable retries
34
+ - `options.timeout` (number) - Timeout in ms
35
+ ```
36
+
37
+ ### Return Values
38
+
39
+ Always specify:
40
+
41
+ - Type: `Array<Object>`, `boolean`, `{ merged, changes }`
42
+ - Shape for objects/arrays
43
+ - Meaning: "True if sync successful"
44
+
45
+ ---
46
+
47
+ ## State Documentation
48
+
49
+ ### When to Document State
50
+
51
+ ✅ Do:
52
+
53
+ - Redux persistence (localStorage, IndexedDB)
54
+ - Database schemas
55
+ - API request/response shapes
56
+
57
+ ❌ Don't:
58
+
59
+ - Component-level state
60
+ - Derived/computed state
61
+ - Temporary UI state
62
+
63
+ ### Format
64
+
65
+ ````markdown
66
+ **Frontend (at persistence):**
67
+
68
+ ```json
69
+ {
70
+ "activeField": "value"
71
+ // "deprecated": null // UNUSED: dead key; kept so old persisted state rehydrates
72
+ }
73
+ ```
74
+
75
+ **Storage:** localStorage key `state_key`
76
+
77
+ **Backend:**
78
+
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
+ });
85
+ ```
86
+ ````
87
+
88
+ ### Mark Unused Keys
89
+
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
+
92
+ ```json
93
+ {
94
+ "active": [],
95
+ // "legacy": {} // UNUSED: dead key; kept for rehydrate compatibility
96
+ }
97
+ ```
98
+
99
+ ---
100
+
101
+ ## ASCII Diagrams
102
+
103
+ ### When to Use
104
+
105
+ - Data flows
106
+ - System architecture
107
+ - Component interactions
108
+ - Process flows
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
+
112
+ ### Pattern
113
+
114
+ ```
115
+ ┌─────────────────────────────────────────┐
116
+ │ TITLE │
117
+ ├─────────────────────────────────────────┤
118
+ │ │
119
+ │ ┌──────┐ ┌──────┐ ┌──────┐ │
120
+ │ │ A │────▶│ B │────▶│ C │ │
121
+ │ └──────┘ └──────┘ └──────┘ │
122
+ │ │ │ │
123
+ │ ▼ ▼ │
124
+ │ Detail Detail │
125
+ │ │
126
+ └─────────────────────────────────────────┘
127
+ ```
128
+
129
+ ### Characters
130
+
131
+ - Boxes: `┌─┐│└┘├┤┬┴┼`
132
+ - Arrows: `───▶` `◀───` `│▼` `│▲`
133
+ - Width: ~70 chars max
134
+
135
+ ### UI Wireframes
136
+
137
+ For screen layouts (not data flows), use these conventions:
138
+
139
+ ```
140
+ **Route:** `path/:id`
141
+ **Tab:** Tab Name
142
+
143
+ ┌────────────────────────────────────┐
144
+ │ Title [i]3 [Button]│
145
+ │ [i]Label [Tag1][Tag2][+Add] │
146
+ └────────────────────────────────────┘
147
+ ```
148
+
149
+ - `[text]` = clickable button/badge
150
+ - `[i]` = icon (followed by label or count)
151
+ - `v` / `^` = expand/collapse indicator
152
+ - Show each UI state (collapsed/expanded) as separate diagrams
153
+ - Include Route/Tab context above wireframe
154
+
155
+ ---
156
+
157
+ ## Code Examples
158
+
159
+ ### Rules
160
+
161
+ - Under 15 lines
162
+ - Show contracts, not implementations
163
+ - Use pseudocode for algorithms
164
+
165
+ ✅ Good:
166
+
167
+ ```javascript
168
+ // Critical: Balanced brace matching
169
+ function extract(json) {
170
+ // Track brace depth
171
+ // Ignore braces inside strings
172
+ // Return complete objects only
173
+ }
174
+ ```
175
+
176
+ ❌ Bad: Full 50-line implementation
177
+
178
+ (Worked example: [`examples.md`](examples.md) Example 1.)
179
+
180
+ ---
181
+
182
+ ## Writing Style
183
+
184
+ ### Voice
185
+
186
+ Use imperative/active:
187
+
188
+ - ✅ "Fetches data from server"
189
+ - ✅ "Returns array of objects"
190
+ - ❌ "This function is used to fetch"
191
+ - ❌ "An array is returned"
192
+
193
+ ### When Prose Adds Value
194
+
195
+ Prose is valuable for context that contracts can't capture:
196
+
197
+ | Use Prose For | Example |
198
+ | --- | --- |
199
+ | Section intros | "When the editor mounts, `useAppInit` is called with the `appId` from URL." |
200
+ | Non-obvious behavior | "The hook always fetches fresh data. There is no caching or version checking." |
201
+ | Design rationale | "Why parallel fetches? Each entity type is independent, reducing load time." |
202
+ | Edge cases | "If created then deleted before save, it's removed from `added[]` without adding to `removed[]`." |
203
+ | Limitations, stated as facts | "`useAppInit` is standalone — nothing in the mount path calls it." |
204
+ | Usage context | "Used to show 'Unsaved' badge, warn before navigation, enable save buttons." |
205
+
206
+ ### When to Avoid Prose
207
+
208
+ - Describing WHAT code does (use signatures instead)
209
+ - Step-by-step flows (use diagrams instead)
210
+ - Structured comparisons (use tables instead)
211
+
212
+ ### Conciseness
213
+
214
+ One line when possible:
215
+
216
+ - ✅ "Merge server data with local changes using version-based conflict resolution"
217
+ - ❌ "This function takes the data from the server and also takes the local data..."
218
+
219
+ ### Tables
220
+
221
+ Use for structured info:
222
+
223
+ ```markdown
224
+ | Parameter | Type | Description |
225
+ | --------- | ------ | -------------- |
226
+ | `data` | object | Fresh from API |
227
+ | `local` | object | Current state |
228
+ ```
229
+
230
+ ---
231
+
232
+ ## The Two Natures — Tense & History
233
+
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:
235
+
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.
237
+
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.
239
+
240
+ Strip this language from truth documents:
241
+
242
+ | ❌ Historical narration (belongs in a record) | ✅ Present-tense fact (belongs in the truth doc) |
243
+ | --- | --- |
244
+ | "Folded in from the `NuStack-X` repo (2026-06-12)." | "Vendor-connector catalogue; one subpath per vendor." |
245
+ | "Built 2026-06-14; shipped + verified 2026-06-13." | "`agentSessionWorkflow` runs an outer turn loop over `runAgentLoop`." |
246
+ | "The legacy worker was deleted in the 2026-06-14 fold." | "One worker interprets `WorkflowDefinition`." |
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 |
250
+ | "Read first: `docs/history/plans/2026-…-fold.md`" (routing) | "Read first: `docs/architecture/<current-truth-doc>.md`" |
251
+
252
+ Rules:
253
+
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/`.
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.
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.)
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.
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.
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
+
273
+ ---
274
+
275
+ ## Structure
276
+
277
+ ### Headers
278
+
279
+ ```markdown
280
+ # Document Title (H1 - once)
281
+
282
+ ## Major Section (H2)
283
+
284
+ ### Subsection (H3)
285
+
286
+ #### Detail (H4 - sparingly)
287
+ ```
288
+
289
+ **Headings are retrieval keys.** Search and agents retrieve sections out of context, and a bare `## State` reads identically across every feature doc. In long docs, qualify generic headings with the feature name — `## State — invoice-pdf`, `### Merge rules — data sync` — so a section stands alone when retrieved. Short docs whose H1 disambiguates can keep bare headings.
290
+
291
+ ### Standard Layout
292
+
293
+ ```markdown
294
+ # [Title]
295
+
296
+ **Goal:** One-line purpose
297
+
298
+ ## Architecture
299
+
300
+ [Diagram + explanation]
301
+
302
+ ## Key Functions
303
+
304
+ [Signatures and contracts]
305
+
306
+ ## State
307
+
308
+ [Persistence shapes]
309
+
310
+ ## Files
311
+
312
+ [Source file list]
313
+ ```
314
+
315
+ ### File References
316
+
317
+ Always end with:
318
+
319
+ ```markdown
320
+ ## Files
321
+
322
+ - `src/path/main.js` - Core logic
323
+ - `src/path/hooks.js` - React hooks
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Summary
329
+
330
+ | Aspect | Rule |
331
+ | ---------- | ------------------------------- |
332
+ | Functions | Always include signatures |
333
+ | Parameters | Type + purpose |
334
+ | Returns | Type + shape |
335
+ | State | Persistence points only |
336
+ | Diagrams | ASCII for all flows — docs only, never instruction files |
337
+ | Code | Under 15 lines, contracts only |
338
+ | Voice | Imperative/active |
339
+ | Mechanics | Inline-code identifiers; bold-assertion bullets |
340
+ | Length | Concise, one line when possible |