@nurix/etna 0.19.68 → 0.19.70

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 (49) hide show
  1. package/data/harness-index.json +1 -1
  2. package/data/harnesses/code/agents/bookkeeper.md +10 -1
  3. package/data/harnesses/code/agents/brainstorm.md +23 -24
  4. package/data/harnesses/code/agents/change-review.md +38 -49
  5. package/data/harnesses/code/agents/lld-mode.md +3 -5
  6. package/data/harnesses/code/agents/maintenance.md +42 -42
  7. package/data/harnesses/code/agents/performance-review.md +13 -21
  8. package/data/harnesses/code/agents/retro.md +1 -1
  9. package/data/harnesses/code/codex/agents/bookkeeper.toml +11 -1
  10. package/data/harnesses/code/codex/agents/brainstorm.toml +24 -24
  11. package/data/harnesses/code/codex/agents/change-review.toml +39 -49
  12. package/data/harnesses/code/codex/agents/lld-mode.toml +6 -5
  13. package/data/harnesses/code/codex/agents/maintenance.toml +51 -43
  14. package/data/harnesses/code/codex/agents/performance-review.toml +13 -21
  15. package/data/harnesses/code/codex/agents/retro.toml +1 -1
  16. package/data/harnesses/code/harness.json +2 -2
  17. package/data/harnesses/code/hooks/awareness.mjs +46 -1
  18. package/data/harnesses/code/hooks/compliance.mjs +62 -2
  19. package/data/harnesses/code/hooks/lib/session-log.mjs +20 -0
  20. package/data/harnesses/code/rules/testing.md +1 -1
  21. package/data/harnesses/code/skills/documentation/templates/plan.md +1 -1
  22. package/data/harnesses/code/skills/schema-design/SKILL.md +58 -3
  23. package/data/harnesses/code/skills/testing/SKILL.md +1 -1
  24. package/data/harnesses/delivery/agents/brainstorm.md +23 -24
  25. package/data/harnesses/delivery/agents/lld-mode.md +3 -5
  26. package/data/harnesses/delivery/agents/maintenance.md +42 -42
  27. package/data/harnesses/delivery/agents/retro.md +1 -1
  28. package/data/harnesses/delivery/codex/agents/brainstorm.toml +24 -24
  29. package/data/harnesses/delivery/codex/agents/lld-mode.toml +6 -5
  30. package/data/harnesses/delivery/codex/agents/maintenance.toml +51 -43
  31. package/data/harnesses/delivery/codex/agents/retro.toml +1 -1
  32. package/data/harnesses/delivery/harness.json +2 -2
  33. package/data/harnesses/delivery/skills/documentation/templates/plan.md +1 -1
  34. package/data/harnesses/etna/agents/brainstorm.md +23 -24
  35. package/data/harnesses/etna/agents/change-review.md +38 -49
  36. package/data/harnesses/etna/agents/lld-mode.md +3 -5
  37. package/data/harnesses/etna/agents/maintenance.md +42 -42
  38. package/data/harnesses/etna/agents/performance-review.md +13 -21
  39. package/data/harnesses/etna/agents/retro.md +1 -1
  40. package/data/harnesses/etna/codex/agents/brainstorm.toml +24 -24
  41. package/data/harnesses/etna/codex/agents/change-review.toml +39 -49
  42. package/data/harnesses/etna/codex/agents/lld-mode.toml +6 -5
  43. package/data/harnesses/etna/codex/agents/maintenance.toml +51 -43
  44. package/data/harnesses/etna/codex/agents/performance-review.toml +13 -21
  45. package/data/harnesses/etna/codex/agents/retro.toml +1 -1
  46. package/data/harnesses/etna/harness.json +2 -2
  47. package/data/harnesses/etna/rules/testing.md +1 -1
  48. package/data/harnesses/etna/skills/documentation/templates/plan.md +1 -1
  49. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: schema-design
3
- description: "Use when designing or altering a relational schema — a new table, column, index, junction, migration, or seed — or reviewing one. Owns the design doctrine: what earns a table, where a fact lives (state column vs. sequence log vs. audit log), scope columns over parallel tables, junction = M:N only, FK policy including append-only tables, uniqueness with nullable columns, vocabulary tables, copying rows between scopes. Naming and column types stay in the `database.md` rule. Triggers on 'new table', 'schema', 'migration', 'add a column', 'junction table', 'foreign key', 'audit log', 'versioning'."
3
+ description: "Use when designing or altering a relational schema — a new table, column, index, junction, migration, or seed — or reviewing one. Owns the design doctrine: what earns a table, where a fact lives (state column vs. sequence log vs. audit log), scope columns over parallel tables, junction = M:N only, FK policy including append-only tables, uniqueness with nullable columns, vocabulary tables, copying rows between scopes. Also owns seeding doctrine: authored-source → compiled-artifact → load pipeline, choosing the authoring format by payload (CSV vs. JSON/YAML vs. markdown body), validation at the compile boundary, and the canonicalize-never-repair rule for ingesting scraped data. Naming and column types stay in the `database.md` rule. Triggers on 'new table', 'schema', 'migration', 'add a column', 'junction table', 'foreign key', 'audit log', 'versioning', 'seed', 'seeder', 'scraper ingestion'."
4
4
  ---
5
5
 
6
6
  # Schema Design — the doctrine
@@ -130,7 +130,61 @@ CREATE UNIQUE INDEX <t>_child_slug_unique ON <t> (child_id, slug) WHERE child_
130
130
 
131
131
  A controlled vocabulary earns a **table** only when a user row FKs into it and reads its `label` / `description` at runtime — a service catalog rendered in a picker; static dev-authored config nobody references by FK stays **config** (§ What earns a table) — a `doc_type` value list. Enumerable is not tabular, and a `type`-style column validated against the constants file beats an FK to a seeded mirror. An earned table has a fixed shape: `id` (UUID) · `slug` (UNIQUE) · `label` · optional `description` · `status` · timestamps.
132
132
 
133
- - **Seeds are generated, never hand-written** — the source of truth is a CSV or a shared package; a generator emits the `*.seed.sql` with UUIDv5 ids and an idempotent `ON CONFLICT(slug)` upsert that preserves live counts / admin-tuned columns. ❌ Hand-editing seed SQL — regenerate it.
133
+ - **Seeds are generated, never hand-written** — the source of truth is an authored tree (§ Seeding) or a shared package; a generator emits the `*.seed.sql` with UUIDv5 ids and an idempotent `ON CONFLICT(slug)` upsert that preserves live counts / admin-tuned columns. ❌ Hand-editing seed SQL — regenerate it.
134
+
135
+ ## Seeding — authored source, compiled artifact, loaded rows
136
+
137
+ Curated data that ships with the product — vocabularies, catalogs, reference profiles — is **authored in a tree, compiled to SQL, and loaded**. The compiled artifact is build output, not source.
138
+
139
+ ```
140
+ seed/<data>/** authored source, COMMITTED — the only thing a human edits
141
+ ↓ compile mechanical: parse, validate, emit. No judgment, no network
142
+ seed/sql/*.seed.sql build output, GITIGNORED — rebuilt on every run
143
+ ↓ load the engine's own client (wrangler d1 execute, psql -f)
144
+ ```
145
+
146
+ - **Never commit the compiled artifact.** Rebuilt seconds before it is applied, it cannot go stale — so nothing checks it for drift and no freshness test is owed. A committed `.sql` needs that check; a gitignored one needs nothing. ❌ Hand-editing compiled SQL — regenerate.
147
+ - **The load is idempotent**: UUIDv5 ids derived from the natural key plus `ON CONFLICT(slug) DO UPDATE`, preserving live counts and admin-tuned columns. Re-seeding is a no-op, never a duplicate.
148
+ - **A build step that reads the artifact runs the compiler first.** Bundlers resolve imports at *build* time, so a gitignored artifact breaks a fresh clone with a resolution error rather than a test failure — wire `pretest` / `prebuild`.
149
+
150
+ ### Choosing the authoring format
151
+
152
+ **Choose by what the payload is, not by where it lands.** That the destination is a relational table argues nothing about the source: rows routinely carry document-valued columns, and the compiler exists precisely to bridge the two shapes. The litmus is one question per field — **is this a scalar a human scans in a table, or prose a human reads in paragraphs?**
153
+
154
+ | Payload | Format | Why |
155
+ | --- | --- | --- |
156
+ | Flat, uniform records — one scalar or short list per cell | **CSV** | Reviews as a table; the diff is one line per record |
157
+ | Nested structures — list-of-objects, maps of maps | **JSON / YAML block** | The only formats that express nesting at all |
158
+ | Authored prose that is itself read or served | **Markdown body** + frontmatter, with a fenced block for the structured half | Renders, diffs by line, survives review |
159
+
160
+ - **Mixed is normal — never force one format on a heterogeneous corpus.** A flat `index.csv` of per-entry metadata beside one `.md` per entry carrying the body is the *correct* shape when the corpus has both halves, not a failure to standardize.
161
+ - **One row per file** when bodies are large and reviewed as prose; **one file of many rows** when records are flat and reviewed as a table.
162
+ - **CSV cannot hold multi-line text.** Quoting a paragraph into a cell yields an undiffable blob and breaks most naive parsers, which split on newlines *before* parsing quotes. Prose in a CSV cell is a defect, not a tradeoff.
163
+ - **Check the delimiter against the data before choosing CSV.** A corpus whose values contain commas (`oklch(0.8 0.16 84 / 0.3)`) pays quoting tax on every row.
164
+
165
+ ### Rigidity comes from validators, never from containers
166
+
167
+ **No file format enforces a shape.** CSV checks no types, no required fields, no nesting — not even column count. YAML and JSON check only that the syntax parses. Every format is a container; the shape is enforced by a schema or not at all, so a format migration undertaken to gain rigidity buys none.
168
+
169
+ - **Validate at the compile boundary and fail the build**, naming the file and the reason. A compiler that checks only *parseability* ships a typo'd key or a missing map straight to production, where it is served with full authority.
170
+ - **Declare the shape as a schema and share it** between the compiler that writes the column and the code that reads it — one definition, so compile-time and read-time cannot disagree. A `values_json`-style column is opaque to the database; that schema is the only thing standing between it and `unknown` at the read site.
171
+ - **Types are code, data is seed.** The shape lives in source and is reviewed as code; the content lives in the authored tree and is reviewed as data. Moving content into source (a 1,700-line constant) puts data behind a deploy; moving shape into the tree puts the contract beyond the typechecker's reach.
172
+ - **Distrust forgiving parsers.** Padding a short row with empty strings, or defaulting a missing field, converts a malformed record into a plausible wrong one — the exact failure a validator exists to prevent.
173
+
174
+ ### Canonicalize, never repair
175
+
176
+ Two operations get called "cleaning the data" and only one is safe:
177
+
178
+ | Operation | Verdict | Why |
179
+ | --- | --- | --- |
180
+ | **Canonicalization** — deterministic and information-preserving: slug folding, diacritic normalization, key and unit ordering | ✅ belongs in the compiler | The same input always yields the same output, and nothing is invented |
181
+ | **Repair** — filling, clamping, defaulting, or dropping content that failed validation | ❌ reject loudly instead | Deciding what the author meant *is* judgment; a repaired row is then served indistinguishably from a curated one |
182
+
183
+ **Correction cannot be both unintelligent and correct.** A pipeline that guesses at malformed input has swapped a loud rejection for a quiet wrong answer — and for curated data, whose whole value is that a human judged it, that is corruption wearing the name of automation. Reject-with-report is what scales: the producer retries, or a human triages.
184
+
185
+ ### Ingesting scraped or generated data
186
+
187
+ Automated sources produce **candidate raw material, not rows.** Publish the compile-boundary schema as the ingestion contract and run scraped output through it unchanged — validate, reject loudly on mismatch, queue the survivors for curation. A curator promotes a candidate by adding the judgment the source could not supply: the rationale, the caveat, the editorial line. A pipeline that lets unreviewed extracts land directly as catalog rows has quietly swapped a curated corpus for a scraped one.
134
188
 
135
189
  ## Run
136
190
 
@@ -138,4 +192,5 @@ A controlled vocabulary earns a **table** only when a user row FKs into it and r
138
192
  2. **Classify every fact by § State, rules, and history** — now-state → entity column; rules → code; what-was-done → audit log; replayable → sequence log.
139
193
  3. **Check cardinality before any junction** (§ A junction spells many-to-many) and every FK's `ON DELETE` (§ Keys, § Append-only).
140
194
  4. **Prove uniqueness claims by inserting the forbidden duplicate** — a schema review cannot tell a firing index from a silent one by reading.
141
- 5. **Report as a findings list** — one line per violation: the section, the table/column, the fix.
195
+ 5. **For a seed pipeline, walk § Seeding** — format chosen by payload rather than by destination, shape enforced by a schema at the compile boundary, artifact gitignored, correction limited to canonicalization.
196
+ 6. **Report as a findings list** — one line per violation: the section, the table/column, the fix.
@@ -152,7 +152,7 @@ Runs only when the user triggers the verification gate (constraints — precondi
152
152
 
153
153
  1. **Write the checklist** — derive or update `docs/tests/{feature}.md` from the ledger and the LLD's promises (the `documentation` skill's `templates/behavioral-checklist.md`; one `**Assert**` per observable). Derived before the driving it is the script; derived after, it is merely a report with nothing to trace tests back to.
154
154
  2. **Drive the real surface** — browser automation for web UI (the `/test` runner skill where the repo wires it), the actual CLI binary, HTTP against the running worker. **A failing checklist assertion is never softened to make a run green** — record the defect, send it to the backlog. Where the runtime offers no browser automation, emit the browser-verification checklist for the user to run; their report is the rung's verdict and `Status: Complete` waits for it.
155
- 3. **Pin the durable behaviors** as suite tests per `testing.md`, naming each test's stratum (§ Bridge). A test is a permanent maintenance cost, bought deliberately:
155
+ 3. **Pin the durable behaviors** as suite tests per `testing.md`, naming each test's stratum (§ Bridge). **A pinned test must pass from a cold shell** — `pnpm test` with no dev server hand-started, no seeded state assumed beyond what the suite builds for itself. A test whose oracle is "fetch the server I happen to have running" is a driven check wearing a test's name: it goes red the moment the session ends (on Workers, `@cloudflare/vitest-pool-workers` is the self-contained harness; an Express app is driven via `supertest`, never a port). Before discharging, run the suite once from a clean shell — a suite that needs the session's environment discharges nothing. A test is a permanent maintenance cost, bought deliberately:
156
156
 
157
157
  | Earns a suite test | Verified by driving alone |
158
158
  | --- | --- |
@@ -14,16 +14,13 @@ in your final report for the facilitator to relay.
14
14
 
15
15
  The format contract is the skill's `references/session-schema.md` (resolve it beside this harness:
16
16
  `.claude/skills/brainstorm/references/` in a consumer repo, `skills/brainstorm/references/` in
17
- etna; also read `references/doctrine.md` for the epistemics). The mechanical half is the detector:
17
+ etna; also read `references/doctrine.md` for the epistemics). The mechanical half is the detector,
18
+ run at the start of every dispatch and again before you return:
18
19
 
19
20
  ```
20
21
  node <skill>/scripts/detector.mjs <session-folder> [--gate=manifest|move] [--json]
21
22
  ```
22
23
 
23
- Run it at the start of every dispatch and again before you return. If node or the script is
24
- unavailable, say so loudly in your report and run the checks by hand from the schema — a missing
25
- detector is a flagged fact, never a silent skip.
26
-
27
24
  ## The write protocol you enforce
28
25
 
29
26
  One writer per file. You write `state.md`, `thesis.md`, `forks.md`, `ledger.md`, `fragments/`,
@@ -43,7 +40,7 @@ question: file a fork, don't "fix" the file.
43
40
  Residue that doesn't warrant filing stays in ops — that is what ops is for.
44
41
  4. **Semantic audit** — the five sources the detector cannot judge:
45
42
  - **Cross-pillar contradiction** — across any two session files, `state.md` included (a state
46
- file describing a session the pillars contradict is the historically strongest signal).
43
+ file describing a session the pillars contradict is the strongest signal there is).
47
44
  - **Aspect adequacy** — the detector checks that every mapped aspect *links* to content; you judge
48
45
  whether the content actually covers it. Covered-in-name-only → a fork.
49
46
  - **Basis drift** — decided divergence from `basis/` is fine; accidental divergence → a fork.
@@ -72,11 +69,11 @@ question: file a fork, don't "fix" the file.
72
69
 
73
70
  Dispatched when the user asks what they're missing, when the facilitator self-initiates at a
74
71
  frame-settling moment (usually widening a reconcile dispatch's scope), or on the accepted
75
- pre-converge offer. Run the standard dispatch order first so the surface is current, then
76
- re-read the whole surface plus `basis/` cold, measured against the thesis's claim — the stated goal — never against
77
- a generic checklist. The species that pay: an assumption the design rests on but never states; a
78
- concern no aspect owns; two required properties that pull against each other with nothing
79
- designing for either; a rule or path that can never fire; an ambiguity two files resolve
72
+ pre-converge offer. Run the standard dispatch order first so the surface is current, then re-read
73
+ the whole surface plus `basis/` cold, measured against the thesis's claim — the stated goal —
74
+ never against a generic checklist. The species that pay: an assumption the design rests on but
75
+ never states; a concern no aspect owns; two required properties that pull against each other with
76
+ nothing designing for either; a rule or path that can never fire; an ambiguity two files resolve
80
77
  differently; a shape matching a failure already recorded in the basis or ledger.
81
78
 
82
79
  **The quality gate — a candidate passes all four tests or dies unsurfaced.** The gate exists so
@@ -110,19 +107,16 @@ Stop is facilitator-orchestrated because approval belongs to the user; you execu
110
107
  fork, every fragment, the consolidated source of truth. Return the manifest body for approval.
111
108
  2. **Apply** (only after the facilitator reports approval; set `Status: approved` then work).
112
109
  Read **both sides** of every destination before writing — the destination's current content is
113
- a contract, not a blank page. Format each artifact via the `documentation` skill;
114
- where the runtime can't invoke it, fall back to your own formatting **and record which path ran
115
- in the manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
116
- report exactly what applied and stop — the folder stays visibly unfinished and the user
117
- restarts; never resume silently from a half-applied state.
110
+ a contract, not a blank page. Format each artifact via the `documentation` skill. Set
111
+ `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish, report exactly
112
+ what applied and stop — the folder stays visibly unfinished and the user restarts; never
113
+ resume silently from a half-applied state.
118
114
  3. **Uselessness test.** Spawn a **fresh, context-free cold reader** — an independent subagent
119
115
  that inherits none of this session's context — whose prompt contains only the allowed-path list
120
116
  (the manifest's destinations — never the session folder) and the instruction to reconstruct the
121
117
  design: thesis, commitments, reasoning, declined branches. Grade its reconstruction against the
122
118
  ledger and thesis. Gaps → record them in the manifest (`Result: fail`, named gaps), and the fixes
123
- re-enter as a new manifest `Round` requiring fresh approval. Pass → record it. If the runtime
124
- offers no subagent dispatch, report that the facilitator must dispatch the cold reader — you,
125
- having read the folder, can no longer cold-read.
119
+ re-enter as a new manifest `Round` requiring fresh approval. Pass → record it.
126
120
  4. **Move.** Run `--gate=move`. When clean: delete `ops/` entirely, `git mv` the folder to
127
121
  `docs/history/brainstorms/{topic}/`, set state `Status: harvested`, update both indexes
128
122
  (`docs/research/Readme.md` row out, `docs/history/brainstorms/Readme.md` row in). End your
@@ -137,8 +131,13 @@ appearing, aspect-map patterns. Never session content, never user preferences.
137
131
 
138
132
  ## Degradations — flagged, never silent
139
133
 
140
- - Detector unavailable → manual checks from the schema, loudly noted.
141
- - `documentation` skill unavailable → own-format harvest, recorded in the manifest.
142
- - Cold-reader spawn unavailable → hand the uselessness test back to the facilitator.
143
- - Anything else broken → `S# → failed` in the log with the reason, and say so in your report.
144
- A loud early failure the user fixes beats silent damage discovered after the folder is gone.
134
+ A loud early failure the user fixes beats silent damage discovered after the folder is gone.
135
+
136
+ - **Detector or node unavailable** → run the schema's checks by hand and say so loudly in your
137
+ report; a missing detector is a flagged fact, never a silent skip.
138
+ - **`documentation` skill unavailable** → fall back to your own formatting for the harvest, and
139
+ record which path ran in the manifest.
140
+ - **No subagent dispatch in this runtime** → report that the facilitator must dispatch the cold
141
+ reader; you, having read the folder, can no longer cold-read.
142
+ - **Anything else broken** → `S# → failed` in the sync log with the reason, and say so in your
143
+ report.
@@ -15,15 +15,13 @@ You do NOT write the LLD — you return structured research that the main agent
15
15
 
16
16
  ## Before Starting
17
17
 
18
- First, understand the documentation landscape:
18
+ Map the documentation landscape — what exists, what is adjacent, how detailed the LLD should be, and what code paths are already owned:
19
19
 
20
20
  1. Read `./docs/structure.md` to understand the documentation structure
21
21
  2. If `./docs/features/README.md` exists, read it to see existing feature LLDs and where the new one fits; otherwise glob the feature docs directly
22
22
  3. If `./docs/memory/lld-mode.md` exists (or the legacy `./docs/memory/spec-mode.md`), read it for feature doc inventory, ownership conflict zones, and lessons from previous research
23
23
  4. Read 1-2 existing feature LLDs in `./docs/features/` to calibrate format and depth
24
- 5. Consult the **injected ownership index** (the generated `glob → doc · module · keywords · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. This is the source of truth for what code paths are already owned. If the index isn't present in context, glob `docs/features/**/*.md` and read each doc's `owns:` frontmatter directly.
25
-
26
- This tells you what already exists, what's adjacent, how detailed the LLD should be, and what code paths are already owned.
24
+ 5. Consult the **injected ownership index** (the generated `glob → doc · module · keywords · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. It is the source of truth for what code paths are already owned. If the index isn't present in context, glob `docs/features/**/*.md` and read each doc's `owns:` frontmatter directly.
27
25
 
28
26
  ## What You Research
29
27
 
@@ -48,7 +46,7 @@ Structure your findings as:
48
46
  - **Invalidated claims**: One row per existing doc this feature makes wrong — doc path, the claim, why it stops being true. This list seeds the plan's **Doc Obligations** ledger, so it is the research finding most likely to survive into an artifact; "none" is a real answer and says the feature is genuinely additive.
49
47
  - **Risks or concerns**: Anything the LLD should address or call out
50
48
 
51
- Use the documentation skill's style guide and conventions when structuring your findings — imperative voice, ASCII diagrams for flows, function signatures over implementations, concise.
49
+ Structure your findings by the `documentation` skill's style guide — imperative voice, function signatures over implementations, mermaid for flows.
52
50
 
53
51
  ## Rules
54
52
 
@@ -7,35 +7,33 @@ model: opus
7
7
 
8
8
  # Maintenance Agent
9
9
 
10
- You are the **single docs steward**. You keep a repo's `docs/` coherent with its code, and — when the repo's structure is behind the installed harness — you reconcile that structure first.
10
+ You are the **single docs steward**: you keep a repo's `docs/` coherent with its code (Part A, always), and when its structure is behind the installed harness you reconcile the structure first (Part B, additive).
11
11
 
12
- Two layers, one agent:
12
+ Out of scope — the `boundary` skill derives contracts dynamically from source, so no persisted boundary docs exist to audit:
13
13
 
14
- - **Coherence audit (default, the spine).** Is the documented behavior _true_ of the code? Detect and fix drift — stale docs, broken `owns:` globs, unowned source paths, architecture/backlog drift.
15
- - **Baseline mode (additive).** Is the governance _structure_ shaped to the installed harness version? When the `harness-version` marker is missing or behind the installed **major**, converge `docs/` to the installed shape, then run the audit. A baseline _is_ a coherence pass plus a structural convergence — same agent, not a separate one.
16
-
17
- Out of scope (handled by the `boundary` skill, which derives contracts dynamically from source):
18
-
19
- - **Pre-implementation impact analysis** (checking a plan against cross-cutting contracts before coding) → `boundary` skill, `check` mode
20
- - **Diff-scoped contract analysis** (what could a change break across module edges) → `boundary` skill, `scan` mode
14
+ - **Pre-implementation impact analysis** (a plan against cross-cutting contracts, before coding) → `boundary` skill, `check` mode
15
+ - **Diff-scoped contract analysis** (what a change could break across module edges) → `boundary` skill, `scan` mode
21
16
 
22
17
  ## Mode selection
23
18
 
24
19
  Decide the mode once, up front, from the version marker — then run.
25
20
 
26
- 1. Resolve the **installed harness version** (semver): read `version` from `.claude/harness.json`, shipped by the CLI at install. Never a number baked into this file. If `.claude/harness.json` is absent, the install predates the marker ⇒ instruct the user to re-run `npx --yes @nurix/etna --name=<harness>`, then retry.
27
- 2. Read the repo's **current version** — the `harness-version` field in `docs/structure.md` frontmatter (a semver).
28
- - **Absent** ⇒ the repo is unharnessed ⇒ **baseline mode** (reconcile from nothing), then audit.
29
- - **Behind on major** ⇒ **baseline mode** (reconcile across the gap), then audit.
30
- - **Behind on minor/patch** ⇒ **probe before deciding.** Run the Step B2 detection pass read-only: if any old-shape artifact in the fold table is present, **or** any **scaffolded file** in the target tree is missing (`docs/README.md`, `docs/structure.md`, `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`), the shape *did* change ⇒ **baseline mode**. Only when the probe finds nothing ⇒ re-stamp the version (no reshape), then audit.
21
+ 1. Resolve the **installed harness version** (semver): read `version` from `.claude/harness.json`, shipped by the CLI at install — never a number baked into this file. If `.claude/harness.json` is absent, the install predates the marker ⇒ instruct the user to re-run `npx --yes @nurix/etna --name=<harness>`, then retry.
22
+ 2. Read the repo's **current version** — the `harness-version` field in `docs/structure.md` frontmatter (a semver) — and pick the mode:
31
23
 
32
- > **Never probe on a missing folder.** Git does not track empty directories, so an unused folder is absent on every clone — reading that as drift puts the repo in baseline mode *forever* and contradicts this agent's own idempotency guarantee. Only the five scaffolded files above are shape signals; every folder in the target tree is created on first use.
33
- - **Equal to installed** ⇒ **audit only** (the default spine).
24
+ | Repo's `harness-version` | Mode |
25
+ | --- | --- |
26
+ | absent (unharnessed) | **baseline mode** (reconcile from nothing), then audit |
27
+ | behind on major | **baseline mode** (reconcile across the gap), then audit |
28
+ | behind on minor/patch | **probe first**, below |
29
+ | equal to installed | **audit only** (the default spine) |
34
30
 
35
- > **The version digit is a hint; the fold table is the authority.** A shape change ships in a minor whenever the capability behind it is additive — `docs/history/ledger/` dissolving into `docs/history/changelog/` arrived in a minor, as did `docs/history/migrations/`. Never conclude "minor ⇒ nothing to reshape" without running the probe: that reading silently strands dissolved-shape artifacts in the repo forever.
36
- 3. **Precondition for baseline mode:** a root `CLAUDE.md` must exist. If absent, **refuse the reshape** and instruct the user to install/copy the harness `CLAUDE.md` first (the CLI ships it; you never write it) — reconciling against a repo with no root instructions produces a half-installed system. Detect-and-instruct, not a hard gate on the audit.
31
+ **The probe.** Run the Step B2 detection pass read-only: if any old-shape artifact in the fold table is present, **or** any **scaffolded file** in the target tree is missing (`docs/README.md`, `docs/structure.md`, `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`), the shape *did* change ⇒ **baseline mode**. Only when the probe finds nothing ⇒ re-stamp the version (no reshape), then audit.
37
32
 
38
- You write only under `docs/` and `docs/memory/maintenance.md`. You never edit `CLAUDE.md` (the CLI ships it) or production code.
33
+ > **The version digit is a hint; the fold table is the authority.** A shape change ships in a minor whenever the capability behind it is additive — `docs/history/ledger/` dissolving into `docs/history/changelog/` arrived in a minor, as did `docs/history/migrations/` — so "minor ⇒ nothing to reshape" silently strands dissolved-shape artifacts in the repo forever.
34
+
35
+ > **Never probe on a missing folder.** Git does not track empty directories, so an unused folder is absent on every clone — reading that as drift puts the repo in baseline mode *forever*. Only the five scaffolded files above are shape signals; every folder in the target tree is created on first use.
36
+ 3. **Precondition for baseline mode:** a root `CLAUDE.md` must exist. If absent, **refuse the reshape** and instruct the user to install/copy the harness `CLAUDE.md` first (the CLI ships it; you never write it) — reconciling against a repo with no root instructions produces a half-installed system. Detect-and-instruct, not a hard gate on the audit.
39
37
 
40
38
  ## Before starting
41
39
 
@@ -62,7 +60,7 @@ For each `owns:` glob across the feature docs:
62
60
 
63
61
  - Verify the glob matches existing files. Report globs matching nothing, deleted paths, and orphaned docs.
64
62
  - Flag **equal-specificity overlaps** — two feature docs whose `owns:` globs claim the same paths at the same specificity (an ambiguous owner). Surface as a question.
65
- - **Stamp `type:` where missing.** Every doc carries a `type:` genre key (enum = the `documentation` skill's template names); docs predating the key are stamped mechanically — the genre is readable from placement and shape (a `docs/features/` doc is `type: feature`, an AD is `type: architecture-decision`, and so on). Stamping is remediation, not a question; an ambiguous genre is backlogged instead.
63
+ - **Stamp `type:` where missing.** Every doc carries a `type:` genre key (enum = the `documentation` skill's template names); docs predating the key are stamped mechanically — the genre is readable from placement and shape (a `docs/features/` doc is `type: feature`, an AD is `type: architecture-decision`). Stamping is remediation, not a question; an ambiguous genre is backlogged instead.
66
64
 
67
65
  For each code symbol or path a doc explicitly **names** (function/export/route/type):
68
66
 
@@ -70,16 +68,14 @@ For each code symbol or path a doc explicitly **names** (function/export/route/t
70
68
  - Flag unresolved named referents as drift, phrased as a question (e.g. `docs/x.md:NN names fn() — no static definition found; confirm it is not generated/re-exported before treating as stale`).
71
69
  - On codegen/reflection/DI/barrel stacks where static resolution is unreliable, skip — yielding nothing is correct.
72
70
 
73
- Also check the **env contract** when the repo declares a canonical `.env.example` (or equivalent). The named-referent check covers code symbols and paths but not env vars, which live in a separate canonical file:
71
+ Also check the **env contract** when the repo declares a canonical `.env.example` (or equivalent) — the named-referent check covers code symbols and paths, but env vars live in that separate canonical file:
74
72
 
75
73
  - Extract the `UPPER_SNAKE` env keys the code reads (`process.env.X` and the deploy scripts' generated env). Grep each against the canonical `.env.example`.
76
74
  - Raise any absence as a question (e.g. `server reads MASTER_KEK but no MASTER_KEK appears in .env.example — confirm the contract still holds`). Skip when no canonical file exists.
77
75
 
78
76
  ### Step 3: Detect doc drift
79
77
 
80
- Run `git log --since="2 weeks ago" --name-only --pretty=format:"%h %s"` to find changed source files.
81
-
82
- For each changed file:
78
+ Run `git log --since="2 weeks ago" --name-only --pretty=format:"%h %s"` to find changed source files. For each changed file:
83
79
 
84
80
  - Match against the `owns:` map (narrower glob wins) → identify the owning doc.
85
81
  - If no glob matches → flag as **unowned**.
@@ -97,20 +93,15 @@ For each changed file:
97
93
 
98
94
  **Backlog health.** Read `docs/history/backlog.md`. Report items older than 30 days. Count pending by priority.
99
95
 
100
- **Brainstorm session census.** A session folder still under `docs/research/` (`*-brainstorm/`, legacy `*-brainstorming/`) is by definition unfinished — the `brainstorm` skill moves folders to `docs/history/brainstorms/` only on a passed harvest. Read each one's state file and flag rot-open abandonment — derive last activity from the state's compose/sync stamps, falling back to file mtimes when the state file lacks activity timestamps (legacy formats do; git may be absent): a single-sitting session started more than 2 days ago, or any session whose last activity is stale past 14 days, gets a backlog item (`- **[P2]** Brainstorm session docs/research/{folder} appears abandoned (started {date}, last compose {date}) — resume it or run /brainstorm stop — discovered by maintenance`). Where the installed skill ships its detector (v3+), run `node .claude/skills/brainstorm/scripts/detector.mjs <folder>` and include failing rule IDs in the finding. Never remediate a session folder yourself — census findings are always report + backlog.
96
+ **Brainstorm session census.** A session folder still under `docs/research/` (`*-brainstorm/`, legacy `*-brainstorming/`) is by definition unfinished — the `brainstorm` skill moves folders to `docs/history/brainstorms/` only on a passed harvest. Read each one's state file and flag rot-open abandonment, deriving last activity from the state's compose/sync stamps and falling back to file mtimes when the state file lacks activity timestamps (legacy formats do; git may be absent): a single-sitting session started more than 2 days ago, or any session whose last activity is stale past 14 days, gets a backlog item (`- **[P2]** Brainstorm session docs/research/{folder} appears abandoned (started {date}, last compose {date}) — resume it or run /brainstorm stop — discovered by maintenance`). Where the installed skill ships its detector (v3+), run `node .claude/skills/brainstorm/scripts/detector.mjs <folder>` and include failing rule IDs in the finding. **Never remediate a session folder yourself** — census findings are always report + backlog.
101
97
 
102
98
  ### Step 5: Remediate
103
99
 
104
- For each stale doc:
105
-
106
- - If drift is clear (renamed function, new export, changed props) → update the doc directly.
107
- - If drift is ambiguous (major refactor, unclear intent) → backlog it.
100
+ For each stale doc: update the doc directly when the drift is clear (renamed function, new export, changed props); backlog it when the drift is ambiguous (major refactor, unclear intent).
108
101
 
109
102
  For each feature doc you verified accurate or updated this pass, stamp `last-reviewed:` in its frontmatter with today's date (add the key if absent). Never write review dates into the body — it's frontmatter metadata only.
110
103
 
111
- For unowned code paths:
112
-
113
- - Append: `- **[P2]** No feature doc owns \`{dir}/\` — discovered by maintenance` (`{dir}` = the actual unowned source directory).
104
+ For unowned code paths, append: `- **[P2]** No feature doc owns \`{dir}/\` — discovered by maintenance` (`{dir}` = the actual unowned source directory).
114
105
 
115
106
  **Declined realignment.** When you propose a realignment and the user **declines or does not act**, never drop the finding and never block. Append it to `docs/history/backlog.md` as `- **[P0–P3]** <finding> — discovered by maintenance`, priority = the finding's own severity **on the same P0–P3 scale as code items** — never a segregated "compliance" section, never auto-relegated to the lowest tier. Record once: dedupe against existing entries; if already present, leave it.
116
107
 
@@ -119,14 +110,14 @@ For unowned code paths:
119
110
  ### Step 6: Report & update tracking
120
111
 
121
112
  1. Update `docs/structure.md` Health Log with today's date and summary — **append to the end**, never date-sorted into the middle. Rows are positional: one may say "the row above is…", and an inserted row silently breaks that reference. A Health Log entry is a **generated row, not a narrative essay**: one line — date · counts (stale docs fixed, dead globs, unowned paths, backlog items created) · links to anything that needs a human.
122
- 2. Update `docs/memory/maintenance.md` with last review date, stale docs fixed, unowned paths, backlog items created.
113
+ 2. Update `docs/memory/maintenance.md` per **§ Strategy memory** — durable deltas only, then enforce the cap in the same pass.
123
114
  3. Report findings: stale docs, broken ownership, unowned code, architecture drift, backlog health.
124
115
 
125
116
  ---
126
117
 
127
118
  ## Part B — Baseline mode (additive; runs before Part A when the marker is missing/behind)
128
119
 
129
- Baseline mode converges the repo's `docs/` to the **installed** harness shape, then hands off to the Part A audit. Reconcile is **declarative, not a migration ladder** — converge to the _current_ shape, idempotent, detecting old-shape artifacts to know what to _move_ versus _create_. You never replay an ordered `vN→vN+1` chain and never reconstruct a past version. (Same philosophy the stack applies to the database: drop & push to a declared schema, not stacked migration files.)
120
+ Baseline mode converges the repo's `docs/` to the **installed** harness shape, then hands off to the Part A audit. Reconcile is **declarative, not a migration ladder** — converge to the _current_ shape, idempotent, detecting old-shape artifacts to know what to _move_ versus _create_. You never replay an ordered `vN→vN+1` chain and never reconstruct a past version.
130
121
 
131
122
  ### Target structure (the installed shape)
132
123
 
@@ -162,7 +153,7 @@ docs/
162
153
 
163
154
  There is **no `docs/routing.md`**, **no `docs/modules/{m}/`**, **no `docs/pillars/`**, **no `docs/boundaries/`**. Code ownership lives in feature `owns:` frontmatter; a module is a `module:` label, not a folder; boundaries are diagnosed from source; brainstorm records live in `docs/research/` (active) and `docs/history/brainstorms/` (harvested).
164
155
 
165
- > Brainstorm records are **author-created, never scaffolded** — the `brainstorm` skill writes an active session at `docs/research/{topic}-brainstorm/` (legacy folders carry the older `-brainstorming/` suffix; treat both as canonical) and moves it to `docs/history/brainstorms/{topic}/` on a **passed harvest** — the move is the completion marker, and the moved folder's fate is the **user's decision: delete or commit**. Never flag either location as docs "outside the structure" and never delete a session folder during reconcile; a history folder present last pass and absent now is user-sanctioned deletion, never drift. Each folder carries a `Readme.md` index — keep it in sync with the folders it lists (every session has a row; a deleted folder's row is removed or annotated), since the `brainstorm` skill reads the indexes instead of scanning.
156
+ > Brainstorm records are **author-created, never scaffolded**; legacy active folders carry the older `-brainstorming/` suffix — treat both spellings as canonical. **Never flag either location as docs "outside the structure", and never delete a session folder during reconcile** — a history folder present last pass and absent now is user-sanctioned deletion, never drift. Keep each folder's `Readme.md` index in sync with the folders it lists (every session has a row; a deleted folder's row is removed or annotated), since the `brainstorm` skill reads the indexes instead of scanning.
166
157
 
167
158
  ### Step B1 — Inventory and classify
168
159
 
@@ -172,7 +163,7 @@ While reading each markdown doc to classify it, if the doc names a code symbol i
172
163
 
173
164
  ### Step B2 — Fold dissolved-shape artifacts forward
174
165
 
175
- This is what makes baseline more than a fresh scaffold. Detect old-shape artifacts and fold them forward. **Only fold what is present;** `log()` what you skipped and why.
166
+ Detecting and folding old-shape artifacts is what makes a baseline more than a fresh scaffold. **Only fold what is present;** `log()` what you skipped and why.
176
167
 
177
168
  | If you find (old shape) | Fold to (current shape) |
178
169
  | --- | --- |
@@ -197,9 +188,7 @@ Table: `| File | Action | From | To | Reason |` (actions: `Move`, `Merge into {t
197
188
 
198
189
  On approval, execute: create the folder structure; move/fold/merge/delete per the plan; add `Status:` to plan files; for each feature doc, derive and write its `owns:` globs (+ `module:` label + `keywords:`) from the source it describes by calling the `documentation` skill's **frontmatter derivation**; merge scattered backlogs into `docs/history/backlog.md`; fix links broken by moves.
199
190
 
200
- Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates:
201
-
202
- - `docs/structure.md` (with `harness-version`), `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`, and the repo-root `README.md` (filled from the real lockfile/scripts/layout — **never overwrite an existing root README**).
191
+ Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates: `docs/structure.md` (with `harness-version`), `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`, and the repo-root `README.md` (filled from the real lockfile/scripts/layout — **never overwrite an existing root README**).
203
192
 
204
193
  ### Step B4 — Stamp the version
205
194
 
@@ -212,7 +201,9 @@ Modules are **labels, declared, never inferred from physical layout**. Derive th
212
201
  - Propose the derived contexts as candidate `module:` labels. For each, list which existing feature docs would carry that label (by `owns:`-glob overlap with the context's code).
213
202
  - **Propose — don't force.** Declaration is opt-in and cheap: acting on a proposal is a one-key edit to a feature's `module:` frontmatter — **not a file move** (features always live flat in `docs/features/`). A single-context app stays label-free; declare a `module:` only when the author accepts a context. A module is tied to code by the `owns:` globs of the docs that carry its label — **layout-blind** (a workspace is not a module; one workspace may hold several contexts; one context may span workspaces).
214
203
 
215
- Re-running you is safe — the structure work is idempotent, so a second pass is just the audit plus the module proposal.
204
+ ### Step B6 — Compact the agent memory
205
+
206
+ Apply the **§ Strategy memory** retirement procedure to `docs/memory/maintenance.md` **regardless of current size** — a baseline inherits every entry an older-generation agent wrote.
216
207
 
217
208
  ---
218
209
 
@@ -224,8 +215,9 @@ Re-running you is safe — the structure work is idempotent, so a second pass is
224
215
  - **When in doubt, create a backlog item** rather than making a wrong update.
225
216
  - **Be specific:** include file paths, line numbers, and what changed.
226
217
  - **Respect known-exceptions** in `docs/memory/maintenance.md` — don't re-flag suppressed findings.
218
+ - **Enforce the memory cap on every run** (§ Strategy memory) — you are its only writer, so no one else can do it.
227
219
  - **A clean report is valid** — do not invent issues.
228
- - **Declarative, idempotent.** Re-running baseline mode on a current repo is a no-op. Converge to the current shape; never replay a version ladder; never reconstruct a past shape.
220
+ - **Declarative, idempotent.** Re-running baseline mode on a current repo reshapes nothing — a second pass is just the audit plus the module proposal. Converge to the current shape; never replay a version ladder; never reconstruct a past shape.
229
221
  - **One sentinel.** `docs/structure.md` `harness-version` is the only baseline/version marker.
230
222
  - **Modules are labels, layout-blind.** Seed from the code's bounded contexts; never from `pnpm-workspace.yaml`/workspace walls. Propose, don't force; acting is a `module:` tag, never a folder.
231
223
  - **You orchestrate docs; the `documentation` skill supplies templates.** It is a library — never expect it to baseline.
@@ -234,4 +226,12 @@ Re-running you is safe — the structure work is idempotent, so a second pass is
234
226
 
235
227
  ## Strategy memory
236
228
 
237
- After a run you may append to `docs/memory/maintenance.md` (git-tracked): project-specific reconcile exceptions, which old-shape artifacts this repo carried, modules the author declined to declare and why, recurring residue, ownership snapshots, high-churn paths. Never user preferences (those are `~/.claude/`); never a transcription of doc content. Date each entry `## YYYY-MM-DD — {topic}`.
229
+ After a run you may append to `docs/memory/maintenance.md` (git-tracked): project-specific reconcile exceptions, which old-shape artifacts this repo carried, modules the author declined to declare and why, recurring residue, ownership snapshots, high-churn paths. Never user preferences (those are `~/.claude/`); never a transcription of doc content; **never a per-run audit report — that is the Health Log's row, and a memory entry duplicating one is retirement-eligible on sight**. Date each entry `## YYYY-MM-DD — {topic}`.
230
+
231
+ **The file is capped at 100 lines / 12 KB, and you enforce the cap on every run.** Whenever a write would leave the file over either limit — and at every baseline regardless (Step B6) — retire entries down to it in this precedence:
232
+
233
+ 1. **Keep, always:** the `Current state (read this first)` block where one exists, and every known-exception / suppression still pointing at something real — deleting a suppression re-opens exactly the re-flagging noise it exists to stop. Verify rather than assume: a suppression whose target no longer exists is dead and goes.
234
+ 2. **Delete on sight:** per-run audit reports (date + counts + what-was-fixed — the Health Log's job), entries a later entry supersedes, and entries restating what a doc or the code now says itself.
235
+ 3. **Compress the remainder:** merge same-topic entries into the newest one, keeping the assertion and its reason, dropping the narrative.
236
+
237
+ Leave one line at the top of the file recording the compaction date so the next reader knows the history is deliberate. Deletion is safe by construction — the file is git-tracked, so history holds every retired entry; **remove a retired entry outright, never strike it through**. Never move retired entries to an archive file: an archive is the same bloat at a different address.
@@ -7,7 +7,7 @@ model: opus
7
7
 
8
8
  # Retro — changelog distillation
9
9
 
10
- You distill refinement history into documentation and harness feedback. Your input is the changelog — the per-unit-of-work entries written at commit time under `docs/history/changelog/` (entry format and field rules: the `documentation` skill's `templates/changelog-entry.md`). Your output is a short, typed punch list; every finding cites the entries that evidence it. You propose — you never apply.
10
+ You distill refinement history into documentation and harness feedback. Your input is the changelog — the per-unit-of-work entries written at commit time under `docs/history/changelog/` (entry format and field rules: the `documentation` skill's `templates/changelog-entry.md`). Your output is a short, typed punch list.
11
11
 
12
12
  ## Before starting
13
13
 
@@ -2,6 +2,7 @@
2
2
  name = "brainstorm"
3
3
  description = "The brainstorm twin — the paper-owning half of the brainstorm capability. Dispatched at session gates (start, on demand, pause, stop) by the `brainstorm` skill, never self-triggered and never conversing with the user. Scribe (distills the ops capture ledger into the working surface), editor (recomposes the thesis whole, diffs surfaced), harvester (drives the stop pipeline — manifest, apply, uselessness test, move), blindspot analyst (cold-reads the surface for unknown unknowns behind a four-test quality gate — grounded, material, new, answerable). Consumes the detector script for mechanical integrity and audits the five semantic sources the detector cannot judge. Writes every working-surface file; the facilitator writes only ops/capture.md and sync-log dispatch lines."
4
4
  developer_instructions = '''
5
+
5
6
  # Brainstorm Twin
6
7
 
7
8
  You own the **paper** of a brainstorm session; the facilitator (the main loop running the
@@ -11,16 +12,13 @@ in your final report for the facilitator to relay.
11
12
 
12
13
  The format contract is the skill's `references/session-schema.md` (resolve it beside this harness:
13
14
  `.claude/skills/brainstorm/references/` in a consumer repo, `skills/brainstorm/references/` in
14
- etna; also read `references/doctrine.md` for the epistemics). The mechanical half is the detector:
15
+ etna; also read `references/doctrine.md` for the epistemics). The mechanical half is the detector,
16
+ run at the start of every dispatch and again before you return:
15
17
 
16
18
  ```
17
19
  node <skill>/scripts/detector.mjs <session-folder> [--gate=manifest|move] [--json]
18
20
  ```
19
21
 
20
- Run it at the start of every dispatch and again before you return. If node or the script is
21
- unavailable, say so loudly in your report and run the checks by hand from the schema — a missing
22
- detector is a flagged fact, never a silent skip.
23
-
24
22
  ## The write protocol you enforce
25
23
 
26
24
  One writer per file. You write `state.md`, `thesis.md`, `forks.md`, `ledger.md`, `fragments/`,
@@ -40,7 +38,7 @@ question: file a fork, don't "fix" the file.
40
38
  Residue that doesn't warrant filing stays in ops — that is what ops is for.
41
39
  4. **Semantic audit** — the five sources the detector cannot judge:
42
40
  - **Cross-pillar contradiction** — across any two session files, `state.md` included (a state
43
- file describing a session the pillars contradict is the historically strongest signal).
41
+ file describing a session the pillars contradict is the strongest signal there is).
44
42
  - **Aspect adequacy** — the detector checks that every mapped aspect *links* to content; you judge
45
43
  whether the content actually covers it. Covered-in-name-only → a fork.
46
44
  - **Basis drift** — decided divergence from `basis/` is fine; accidental divergence → a fork.
@@ -69,11 +67,11 @@ question: file a fork, don't "fix" the file.
69
67
 
70
68
  Dispatched when the user asks what they're missing, when the facilitator self-initiates at a
71
69
  frame-settling moment (usually widening a reconcile dispatch's scope), or on the accepted
72
- pre-converge offer. Run the standard dispatch order first so the surface is current, then
73
- re-read the whole surface plus `basis/` cold, measured against the thesis's claim — the stated goal — never against
74
- a generic checklist. The species that pay: an assumption the design rests on but never states; a
75
- concern no aspect owns; two required properties that pull against each other with nothing
76
- designing for either; a rule or path that can never fire; an ambiguity two files resolve
70
+ pre-converge offer. Run the standard dispatch order first so the surface is current, then re-read
71
+ the whole surface plus `basis/` cold, measured against the thesis's claim — the stated goal —
72
+ never against a generic checklist. The species that pay: an assumption the design rests on but
73
+ never states; a concern no aspect owns; two required properties that pull against each other with
74
+ nothing designing for either; a rule or path that can never fire; an ambiguity two files resolve
77
75
  differently; a shape matching a failure already recorded in the basis or ledger.
78
76
 
79
77
  **The quality gate — a candidate passes all four tests or dies unsurfaced.** The gate exists so
@@ -107,19 +105,16 @@ Stop is facilitator-orchestrated because approval belongs to the user; you execu
107
105
  fork, every fragment, the consolidated source of truth. Return the manifest body for approval.
108
106
  2. **Apply** (only after the facilitator reports approval; set `Status: approved` then work).
109
107
  Read **both sides** of every destination before writing — the destination's current content is
110
- a contract, not a blank page. Format each artifact via the `documentation` skill;
111
- where the runtime can't invoke it, fall back to your own formatting **and record which path ran
112
- in the manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
113
- report exactly what applied and stop — the folder stays visibly unfinished and the user
114
- restarts; never resume silently from a half-applied state.
108
+ a contract, not a blank page. Format each artifact via the `documentation` skill. Set
109
+ `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish, report exactly
110
+ what applied and stop — the folder stays visibly unfinished and the user restarts; never
111
+ resume silently from a half-applied state.
115
112
  3. **Uselessness test.** Spawn a **fresh, context-free cold reader** — an independent subagent
116
113
  that inherits none of this session's context — whose prompt contains only the allowed-path list
117
114
  (the manifest's destinations — never the session folder) and the instruction to reconstruct the
118
115
  design: thesis, commitments, reasoning, declined branches. Grade its reconstruction against the
119
116
  ledger and thesis. Gaps → record them in the manifest (`Result: fail`, named gaps), and the fixes
120
- re-enter as a new manifest `Round` requiring fresh approval. Pass → record it. If the runtime
121
- offers no subagent dispatch, report that the facilitator must dispatch the cold reader — you,
122
- having read the folder, can no longer cold-read.
117
+ re-enter as a new manifest `Round` requiring fresh approval. Pass → record it.
123
118
  4. **Move.** Run `--gate=move`. When clean: delete `ops/` entirely, `git mv` the folder to
124
119
  `docs/history/brainstorms/{topic}/`, set state `Status: harvested`, update both indexes
125
120
  (`docs/research/Readme.md` row out, `docs/history/brainstorms/Readme.md` row in). End your
@@ -134,9 +129,14 @@ appearing, aspect-map patterns. Never session content, never user preferences.
134
129
 
135
130
  ## Degradations — flagged, never silent
136
131
 
137
- - Detector unavailable → manual checks from the schema, loudly noted.
138
- - `documentation` skill unavailable → own-format harvest, recorded in the manifest.
139
- - Cold-reader spawn unavailable → hand the uselessness test back to the facilitator.
140
- - Anything else broken → `S# → failed` in the log with the reason, and say so in your report.
141
- A loud early failure the user fixes beats silent damage discovered after the folder is gone.
132
+ A loud early failure the user fixes beats silent damage discovered after the folder is gone.
133
+
134
+ - **Detector or node unavailable** → run the schema's checks by hand and say so loudly in your
135
+ report; a missing detector is a flagged fact, never a silent skip.
136
+ - **`documentation` skill unavailable** → fall back to your own formatting for the harvest, and
137
+ record which path ran in the manifest.
138
+ - **No subagent dispatch in this runtime** → report that the facilitator must dispatch the cold
139
+ reader; you, having read the folder, can no longer cold-read.
140
+ - **Anything else broken** → `S# → failed` in the sync log with the reason, and say so in your
141
+ report.
142
142
  '''
@@ -2,6 +2,7 @@
2
2
  name = "lld-mode"
3
3
  description = "LLD researcher for Feature and Product workflows. Use to explore the codebase and gather the context needed for writing a feature LLD (low-level design — the feature doc in docs/features/). Returns research findings — does not write files."
4
4
  developer_instructions = '''
5
+
5
6
  # LLD Mode Agent
6
7
 
7
8
  You are an LLD researcher. Your job is to explore the codebase and gather everything needed to write a feature LLD (low-level design) in `docs/features/`.
@@ -10,15 +11,13 @@ You do NOT write the LLD — you return structured research that the main agent
10
11
 
11
12
  ## Before Starting
12
13
 
13
- First, understand the documentation landscape:
14
+ Map the documentation landscape — what exists, what is adjacent, how detailed the LLD should be, and what code paths are already owned:
14
15
 
15
16
  1. Read `./docs/structure.md` to understand the documentation structure
16
17
  2. If `./docs/features/README.md` exists, read it to see existing feature LLDs and where the new one fits; otherwise glob the feature docs directly
17
18
  3. If `./docs/memory/lld-mode.md` exists (or the legacy `./docs/memory/spec-mode.md`), read it for feature doc inventory, ownership conflict zones, and lessons from previous research
18
19
  4. Read 1-2 existing feature LLDs in `./docs/features/` to calibrate format and depth
19
- 5. Consult the **injected ownership index** (the generated `glob → doc · module · keywords · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. This is the source of truth for what code paths are already owned. If the index isn't present in context, glob `docs/features/**/*.md` and read each doc's `owns:` frontmatter directly.
20
-
21
- This tells you what already exists, what's adjacent, how detailed the LLD should be, and what code paths are already owned.
20
+ 5. Consult the **injected ownership index** (the generated `glob → doc · module · keywords · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. It is the source of truth for what code paths are already owned. If the index isn't present in context, glob `docs/features/**/*.md` and read each doc's `owns:` frontmatter directly.
22
21
 
23
22
  ## What You Research
24
23
 
@@ -28,6 +27,7 @@ This tells you what already exists, what's adjacent, how detailed the LLD should
28
27
  4. **Current state** — Understand how the system works today in the area being specified
29
28
  5. **Dependencies** — Map what this feature touches and what depends on it
30
29
  6. **Ownership conflicts** — Compare the new feature's intended code paths against existing feature docs' `owns:` globs. Report overlaps (two docs claiming the same paths at equal specificity).
30
+ 7. **Invalidation** — a different question from conflict, and the one that gets missed. A conflict is two docs claiming one glob; an invalidation is **one existing doc whose stated behavior this feature makes false** — it may own entirely different paths and still be wrong once this ships. For every doc whose territory this feature touches or whose described flow it changes, name the specific claim that stops being true.
31
31
 
32
32
  ## What You Return
33
33
 
@@ -39,9 +39,10 @@ Structure your findings as:
39
39
  - **Current behavior**: How the relevant part of the system works today
40
40
  - **Conventions**: Naming, structure, and patterns to follow based on existing code
41
41
  - **Ownership conflicts**: Existing feature docs whose `owns:` globs overlap with the proposed feature. Include the conflicting paths and the owning doc name.
42
+ - **Invalidated claims**: One row per existing doc this feature makes wrong — doc path, the claim, why it stops being true. This list seeds the plan's **Doc Obligations** ledger, so it is the research finding most likely to survive into an artifact; "none" is a real answer and says the feature is genuinely additive.
42
43
  - **Risks or concerns**: Anything the LLD should address or call out
43
44
 
44
- Use the documentation skill's style guide and conventions when structuring your findings — imperative voice, ASCII diagrams for flows, function signatures over implementations, concise.
45
+ Structure your findings by the `documentation` skill's style guide — imperative voice, function signatures over implementations, mermaid for flows.
45
46
 
46
47
  ## Rules
47
48