@nurix/etna 0.13.0 → 0.15.1

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/README.md +31 -10
  2. package/bin/etna.js +58 -1
  3. package/data/harness-index.json +1 -1
  4. package/data/harnesses/code/CLAUDE.md +12 -18
  5. package/data/harnesses/code/agents/brainstorm.md +14 -21
  6. package/data/harnesses/code/agents/change-review.md +6 -6
  7. package/data/harnesses/code/agents/harness-manager.md +51 -11
  8. package/data/harnesses/code/agents/maintenance.md +43 -6
  9. package/data/harnesses/code/agents/performance-review.md +1 -1
  10. package/data/harnesses/code/agents/spec-mode.md +2 -2
  11. package/data/harnesses/code/harness.json +6 -0
  12. package/data/harnesses/code/hooks/hooks.json +41 -0
  13. package/data/harnesses/code/hooks/lib/redact.js +37 -0
  14. package/data/harnesses/code/hooks/post-commit.js +136 -0
  15. package/data/harnesses/code/hooks/post-tool-failure.js +136 -0
  16. package/data/harnesses/code/hooks/session-stop.js +207 -0
  17. package/data/harnesses/code/rules/general.md +1 -1
  18. package/data/harnesses/code/rules/nomenclature.md +1 -1
  19. package/data/harnesses/code/skills/boundary/SKILL.md +22 -4
  20. package/data/harnesses/code/skills/boundary/references/boundary-taxonomy.md +229 -161
  21. package/data/harnesses/code/skills/brainstorm/README.md +76 -227
  22. package/data/harnesses/code/skills/brainstorm/SKILL.md +79 -567
  23. package/data/harnesses/code/skills/brainstorm/harvest.md +26 -0
  24. package/data/harnesses/code/skills/brainstorm/templates/build.md +37 -0
  25. package/data/harnesses/code/skills/brainstorm/templates/decisions.md +12 -25
  26. package/data/harnesses/code/skills/brainstorm/templates/domain-model.md +25 -0
  27. package/data/harnesses/code/skills/brainstorm/templates/non-goals.md +2 -2
  28. package/data/harnesses/code/skills/brainstorm/templates/questions.md +18 -67
  29. package/data/harnesses/code/skills/brainstorm/templates/state.md +5 -5
  30. package/data/harnesses/code/skills/brainstorm/templates/tech.md +23 -0
  31. package/data/harnesses/code/skills/brainstorm/templates/thesis.md +21 -0
  32. package/data/harnesses/code/skills/distiller/SKILL.md +214 -0
  33. package/data/harnesses/code/skills/distiller/references/docs-mode.md +526 -0
  34. package/data/harnesses/code/skills/distiller/references/method.md +166 -0
  35. package/data/harnesses/code/skills/documentation/SKILL.md +1 -1
  36. package/data/harnesses/code/skills/documentation/references/templates.md +78 -5
  37. package/data/harnesses/code/skills/workflow-mapper/SKILL.md +1 -1
  38. package/data/harnesses/kb-agi/CLAUDE.md +1 -1
  39. package/data/harnesses/kb-agi/agents/kb-agi-init.md +2 -2
  40. package/data/harnesses/kb-agi/agents/kb-catch-stale.md +1 -1
  41. package/data/harnesses/kb-agi/agents/kb-find-gaps.md +2 -2
  42. package/data/harnesses/kb-agi/agents/kb-fix-links.md +1 -1
  43. package/data/harnesses/kb-agi/agents/kb-refresh-frontdoor.md +1 -1
  44. package/data/harnesses/kb-agi/agents/kb-refresh-summaries.md +1 -1
  45. package/data/harnesses/kb-agi/agents/kb-sync-metadata.md +1 -1
  46. package/data/harnesses/kb-agi/harness.json +6 -0
  47. package/package.json +1 -1
  48. package/data/harnesses/code/skills/brainstorm/greenfield.md +0 -99
  49. package/data/harnesses/code/skills/brainstorm/templates/inventory.md +0 -44
package/README.md CHANGED
@@ -9,24 +9,45 @@ A second install path also exists and is fully supported: `/plugin install <plug
9
9
  From the root of the project you want to bootstrap:
10
10
 
11
11
  ```sh
12
- npx @nurix/etna nurix-harness
12
+ npx @nurix/etna code
13
13
  ```
14
14
 
15
15
  After this completes:
16
16
 
17
17
  ```
18
18
  your-project/
19
- ├── CLAUDE.md ← harness policy (backup of any existing file is kept)
19
+ ├── CLAUDE.md ← harness policy (your existing file → CLAUDE.md.bak.<ISO>)
20
20
  └── .claude/
21
- ├── skills/ ← documentation, introspect, workflow-mapper
22
- ├── agents/ ← spec-mode, maintenance, contract-monitor, …
23
- ├── rules/ ← general.md, nomenclature.md
24
- └── scripts/ ← build-ownership-index.sh, check-doc-drift.sh
21
+ ├── skills/ ← documentation, boundary, distiller, brainstorm, workflow-mapper
22
+ ├── agents/ ← harness-manager, spec-mode, brainstorm, maintenance, change-review, performance-review
23
+ ├── rules/ ← general.md, nomenclature.md
24
+ ├── hooks/ ← post-commit, post-tool-failure, session-stop + lib/redact (knowledge-ledger capture)
25
+ ├── settings.json ← the hooks are deep-merged in here (your existing keys preserved)
26
+ └── harness.json ← {version, epoch, digest} — the installed-harness sentinel
25
27
  ```
26
28
 
27
- That's the entire footprint. Nothing is written outside the project. No marketplace registration, no `enabledPlugins` entry, no global cache dependency — Claude Code picks up project-scoped agents/skills/rules/scripts on its next session start.
29
+ That's the entire footprint. Nothing is written outside the project. No marketplace registration, no `enabledPlugins` entry, no global cache dependency — Claude Code picks up the project-scoped agents/skills/rules on its next session start, and the hooks wire in through `.claude/settings.json`.
28
30
 
29
- Re-run `npx @nurix/etna nurix-harness` anytime to refresh the harness content with what the latest published package ships. Existing same-named files are overwritten; files you've added that aren't part of the harness are left alone. The previous `CLAUDE.md` is backed up to `CLAUDE.md.bak.<ISO-timestamp>`.
31
+ Re-run `npx @nurix/etna code` anytime to refresh the harness content with what the latest published package ships. Existing same-named files are overwritten; files you've added that aren't part of the harness are left alone. The previous `CLAUDE.md` is backed up to `CLAUDE.md.bak.<ISO-timestamp>`. Because the new `harness.json` carries the installed `{version, epoch, digest}`, a re-run that's ahead of your repo's stamped `harness-version` is what the reconcile (below) detects as an upgrade.
32
+
33
+ ## After install: bootstrap the harness
34
+
35
+ Installing only *drops the files* — the harness isn't active for your repo until you **baseline** it. Open Claude Code in the project and drive the reconcile chain once (the installed `CLAUDE.md` carries the same steps under its `## Bootstrap` heading, for the agent):
36
+
37
+ 1. **"baseline this repo"** (or "reconcile the harness") — runs the **`harness-manager`** agent. It builds the `docs/` tree to the harness shape, stamps `docs/structure.md` with the installed `harness-version`, then hands back.
38
+ 2. If it asks for boundaries (a real codebase whose `docs/boundaries/` is still empty) — run **`/boundary generate`**. It detects your stack + information architecture and writes the typed boundary files.
39
+ 3. **"reconcile the harness"** again — `harness-manager` now proposes **modules** from those boundaries.
40
+
41
+ Then work normally. This brownfield path reads your *actual* code, not a blank slate, so it's safe to run on an existing project with real history.
42
+
43
+ Two things worth knowing on an existing repo:
44
+
45
+ - **Your root `CLAUDE.md` is replaced** with the harness policy file (the old one is saved to `CLAUDE.md.bak.<ISO>`). If it held project-specific instructions, fold them back in after install — the harness file is the policy skeleton; your domain specifics sit alongside it.
46
+ - **The ledger starts on your next commit.** The `post-commit` hook appends to `docs/memory/ledger/`; once enough entries accrue, the `maintenance` agent *proposes* a `distiller` run that distills them into provenance-linked fact-cards and, eventually, proposed `docs/` updates. Nothing runs on its own — it proposes, you approve.
47
+
48
+ ### Optional: semantic retrieval (qmd)
49
+
50
+ If the [`qmd`](https://www.npmjs.com/package/@tobilu/qmd) binary is on your `PATH`, `harness-manager` registers per-subtree search collections so the distiller and the doc anchors get semantic retrieval. It's strictly optional — absent, everything still works on a filename/grep fallback. Install it whenever.
30
51
 
31
52
  ## Migrating from 0.1.x
32
53
 
@@ -40,7 +61,7 @@ Listed by `npx @nurix/etna` (no args) using the bundled `data/harness-index.json
40
61
 
41
62
  | Plugin name | Source in etna | What it ships |
42
63
  |---|---|---|
43
- | `nurix-harness` | [`plugins/nurix-harness.md`](../../plugins/nurix-harness.md) → top-level catalogs | Governance agents, baseline workflow skills, ownership/drift scripts |
64
+ | `code` | [`plugins/code.md`](../../plugins/code.md) → top-level catalogs | Governance agents, baseline workflow skills, ownership/drift scripts |
44
65
  | `kb-agi` | [`plugins/kb-agi.md`](../../plugins/kb-agi.md) → top-level catalogs | Knowledge-vault scaffolding |
45
66
 
46
67
  ## How it works
@@ -53,7 +74,7 @@ The plugin manifest's YAML frontmatter declares which top-level `agents/`, `skil
53
74
 
54
75
  ```yaml
55
76
  ---
56
- name: nurix-harness
77
+ name: code
57
78
  skills: [documentation, introspect, workflow-mapper]
58
79
  agents: [spec-mode, maintenance, contract-monitor, …]
59
80
  scripts: [build-ownership-index, check-doc-drift]
package/bin/etna.js CHANGED
@@ -25,7 +25,9 @@ const dataDir = join(pkgRoot, 'data');
25
25
 
26
26
  // Subfolders bundled inside each harness payload that map 1:1 onto
27
27
  // <project>/.claude/<name>/. Order matches Claude Code's own folder layout.
28
- const PLUGIN_SUBDIRS = ['skills', 'agents', 'rules', 'scripts'];
28
+ // hooks/ carries the hook scripts + lib/ (and hooks.json, copied harmlessly —
29
+ // the settings merge reads it from the bundle, not the project copy).
30
+ const PLUGIN_SUBDIRS = ['skills', 'agents', 'rules', 'scripts', 'hooks'];
29
31
 
30
32
  function usage() {
31
33
  const idx = loadHarnessIndex();
@@ -135,6 +137,43 @@ function migrateFromPluginInstall(targetDir, pluginName) {
135
137
  return removed;
136
138
  }
137
139
 
140
+ // True if an event's matcher-group already carries a hook with this command string.
141
+ function groupHasCommand(group, command) {
142
+ return (group.hooks || []).some((h) => h.command === command);
143
+ }
144
+
145
+ // Deep-merge the bundle's hooks.json object into <project>/.claude/settings.json under
146
+ // "hooks", preserving every existing key. Idempotent: for each event, an incoming entry
147
+ // merges into the matcher-group of the same matcher, skipping any hook whose command
148
+ // already exists there; a new matcher creates a new group. Returns count of hooks added.
149
+ function mergeHooks(targetDir, bundledHooksJson) {
150
+ if (!existsSync(bundledHooksJson)) return 0;
151
+ const incoming = readJson(bundledHooksJson).hooks || {};
152
+ const settingsPath = join(targetDir, '.claude', 'settings.json');
153
+ const settings = readJson(settingsPath);
154
+ settings.hooks = settings.hooks || {};
155
+ let added = 0;
156
+ for (const [event, groups] of Object.entries(incoming)) {
157
+ const existingGroups = (settings.hooks[event] = settings.hooks[event] || []);
158
+ for (const group of groups) {
159
+ const match = existingGroups.find((g) => g.matcher === group.matcher);
160
+ if (!match) {
161
+ existingGroups.push(group);
162
+ added += (group.hooks || []).length;
163
+ continue;
164
+ }
165
+ match.hooks = match.hooks || [];
166
+ for (const hook of group.hooks || []) {
167
+ if (groupHasCommand(match, hook.command)) continue;
168
+ match.hooks.push(hook);
169
+ added += 1;
170
+ }
171
+ }
172
+ }
173
+ if (added > 0) writeJson(settingsPath, settings);
174
+ return added;
175
+ }
176
+
138
177
  async function main(args) {
139
178
  if (args.includes('-h') || args.includes('--help') || args.length === 0) {
140
179
  usage();
@@ -178,6 +217,24 @@ async function main(args) {
178
217
  if (count > 0) console.log(` copied ${count} ${sub} → ${targetDir}/.claude/${sub}/`);
179
218
  }
180
219
 
220
+ // Copy the epoch marker so harness-manager can resolve the installed epoch.
221
+ const bundledHarnessJson = join(bundledHarnessDir, 'harness.json');
222
+ if (existsSync(bundledHarnessJson)) {
223
+ const harnessJsonDest = join(targetDir, '.claude', 'harness.json');
224
+ mkdirSync(dirname(harnessJsonDest), { recursive: true });
225
+ cpSync(bundledHarnessJson, harnessJsonDest, { force: true });
226
+ const meta = readJson(harnessJsonDest);
227
+ console.log(
228
+ ` installed harness.json → ${harnessJsonDest}${meta.epoch ? ` (epoch ${meta.epoch})` : ''}`,
229
+ );
230
+ }
231
+
232
+ // Merge the bundle's hooks.json into the project's settings.json (idempotent).
233
+ const added = mergeHooks(targetDir, join(bundledHarnessDir, 'hooks', 'hooks.json'));
234
+ if (added > 0) {
235
+ console.log(` merged ${added} hook(s) → ${targetDir}/.claude/settings.json`);
236
+ }
237
+
181
238
  const migrated = migrateFromPluginInstall(targetDir, pluginName);
182
239
  for (const entry of migrated) console.log(` removed stale ${entry}`);
183
240
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "plugins": {
3
- "nurix-harness": "code",
3
+ "code": "code",
4
4
  "kb-agi": "kb-agi"
5
5
  }
6
6
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: code
3
- description: Canonical Nurix code-project harness (spec v11) — three peer authoring modes (Brainstorming / Spec / Plan), modules as bounded contexts, typed application boundaries via the unified `boundary` skill, a self-migrating harness-manager, ownership rules. The reference CLAUDE.md every Nurix codebase starts with.
4
- version: 0.12.0
3
+ description: Canonical Nurix code-project harness (spec v12) — three peer authoring modes (Brainstorming / Spec / Plan), modules as bounded contexts, typed application boundaries via the unified `boundary` skill, a self-migrating harness-manager, ownership rules. The reference CLAUDE.md every Nurix codebase starts with.
4
+ version: 0.15.1
5
5
  keywords:
6
6
  - harness
7
7
  - code
@@ -9,7 +9,7 @@ keywords:
9
9
  - documentation
10
10
  - boundaries
11
11
  - nurix
12
- plugin: nurix-harness
12
+ plugin: code
13
13
  ---
14
14
 
15
15
  # Agent Instructions
@@ -50,11 +50,11 @@ Three peer modes plus a Completion step — enter wherever the user's thinking a
50
50
 
51
51
  | Mode | Enter when | Implemented by | Exits to |
52
52
  |------|-----------|----------------|----------|
53
- | **Brainstorming** | explicit ask, or a user utterance challenges a loaded pillar headline | `brainstorm` agent + skill | Spec, Plan, or close + harvest |
53
+ | **Brainstorming** | explicit ask; or a user utterance challenges a loaded pillar headline → name the brushed principle and offer `/brainstorm start` (no auto-entry) | `brainstorm` agent + skill | Spec, Plan, or close + harvest |
54
54
  | **Spec** | new feature work | `spec-mode` agent + `documentation` skill | Plan |
55
55
  | **Plan** | a spec is approved | `documentation` skill → `docs/history/plans/YYYY-MM-DD-{slug}.md` | Completion |
56
56
 
57
- On **Completion**: freeze the plan (`Status: Complete`) and flip the feature spec to `Status: Active`, extending it with how-it-works sections. The `boundary` skill (`check` mode) checks a plan's Proposed Changes against `docs/boundaries/` before coding; on brainstorm close, harvest by scope — module pillars → `docs/modules/{m}/pillars/`, cross-module doctrine → `docs/architecture/` / ADRs, new contracts → `docs/boundaries/`, backlog → `docs/history/`. Tentative decisions block close.
57
+ On **Completion**: freeze the plan (`Status: Complete`) and flip the feature spec to `Status: Active`, extending it with how-it-works sections; then consult `distiller docs` for the just-completed feature's doc — it drafts any pending fact-card deltas for approval (presented, never auto-written). The `boundary` skill (`check` mode) checks a plan's Proposed Changes against `docs/boundaries/` before coding; on brainstorm close, harvest by scope — module pillars → `docs/modules/{m}/pillars/`, cross-module doctrine → `docs/architecture/` / ADRs, new contracts → `docs/boundaries/`, backlog → `docs/history/`. Open questions block close.
58
58
 
59
59
  ---
60
60
 
@@ -63,10 +63,11 @@ On **Completion**: freeze the plan (`Status: Complete`) and flip the feature spe
63
63
  Before modifying code in an unfamiliar area:
64
64
 
65
65
  1. If **[`docs/routing.md`](docs/routing.md)** exists, read it for file-pattern → module/doc/agent mapping. If it doesn't exist yet, skip.
66
- 2. Glob `docs/{features,modules/*/features}/**/*.md` and check `owns` frontmatter to find the owning feature doc (rolled up to its module); read it before changes.
67
- 3. **Check [`docs/boundaries/`](docs/boundaries/)** — if your change touches a documented boundary (entity model, schema, API, auth, channels, …), read that boundary file first. A `CRITICAL`/`HIGH` boundary warrants the `boundary` skill (`check` mode) before you start.
68
- 4. If a `docs/memory/` file exists for the domain you're working in, read it for domain knowledge and failure modes
69
- 5. In a declared module, its `docs/modules/{m}/CLAUDE.md` auto-loads in that subtree — follow it.
66
+ 2. Glob `docs/{features,modules/*/features}/**/*.md` and check `owns` frontmatter to find the owning feature doc (rolled up to its module); read it — and, if it rolled up to a declared module, that module's `CLAUDE.md` + `pillars/` — before changes.
67
+ 3. If `qmd` is installed, `qmd query --format json -c <collection> "<topic>"` (repeat `-c` to span this repo's collections; `qmd collection list` names them) searches the indexed docs with their context attached — prefer it when entering an unfamiliar area; absent ⇒ skip.
68
+ 4. **Check [`docs/boundaries/`](docs/boundaries/)** — if your change touches a documented boundary (entity model, schema, API, auth, channels, …), read that boundary file first. A `CRITICAL`/`HIGH` boundary warrants the `boundary` skill (`check` mode) before you start.
69
+ 5. If a `docs/memory/` file exists for the domain you're working in, read it for domain knowledge and failure modes
70
+ 6. When you author a declared module's docs, its `docs/modules/{m}/CLAUDE.md` auto-loads (the pillar bootstrap) — follow it. For code work it's surfaced via step 2.
70
71
 
71
72
  For the protocol on *writing* to memory (which file, what belongs there, what doesn't), see **Project Memory** below.
72
73
 
@@ -110,12 +111,7 @@ The spec-mode agent checks for ownership conflicts during research. If conflicts
110
111
 
111
112
  `docs/boundaries/` holds the repo's **typed application boundaries** — the horizontal cross-cutting contracts (the *edges* between modules) where editing one module silently breaks another: e.g. the entity model, tenancy, auth, db-schema, wire-contracts, api, env-parity. Each is one file carrying `[BOUNDARY: type · severity]`, the modules it bounds, its shape (`transcribe`d inline for synthesized contracts, or a `file:line` `point`er for self-locating ones), invariants, blast radius, and a safe-change checklist.
112
113
 
113
- One component owns this surface — the **`boundary` skill** — with four modes over one shared knowledge root (its `references/boundary-taxonomy.md`, the exhaustive catalog of boundary types):
114
-
115
- - **`generate`** — baseline: detect the stack + IA and generate every boundary file. Trigger: "baseline boundaries" / "generate boundaries".
116
- - **`create`** — add or update a single boundary file.
117
- - **`check`** — pre-implementation: check a proposed plan against `docs/boundaries/`, surfacing cascading risk early. The boundary's **severity** sets review depth.
118
- - **`init`** — reconcile: ensure files exist, scan the live codebase for violations + drift, backfill newly-exhibited boundary types.
114
+ One component owns this surface — the **`boundary` skill** — `generate` at baseline, `create`/`check`/`init` as you add contracts, plan changes, or reconcile. Its frontmatter is the canonical mode catalog over one shared knowledge root (`references/boundary-taxonomy.md`, the exhaustive catalog of boundary types).
119
115
 
120
116
  Without `docs/boundaries/` populated (`generate`), the `check` and `init` modes have nothing to check against.
121
117
 
@@ -131,8 +127,7 @@ Unless explicitly requested:
131
127
  ❌ **Dependencies** – Never upgrade frameworks, libraries, or dependencies.
132
128
  ❌ **Compatibility** – Never maintain backward compatibility unless specified.
133
129
  ❌ **Branches & Worktrees** – Never self-create git branches or worktrees. Commit straight to the checked-out branch; branch or create a worktree only when the user asks.
134
- ❌ **Protected Files** – Never modify these read-only files:
135
- `AGENTS.md`, `docs/operations/protected-files.md`
130
+ ❌ **Protected Files** – Before editing, if `docs/operations/protected-files.md` exists, read it and never modify any path it lists; also never modify `AGENTS.md` or the `protected-files.md` file itself.
136
131
  ✅ **Browser Automation** – Use Chrome CDP / "Claude in Chrome" tools whenever they help (verifying UI, reproducing a flow, seeding or inspecting local data) — no need to ask first.
137
132
  ✅ **Documentation** – Keep `docs/` updated when code changes affect documented behavior.
138
133
  ⚠️ **Plans** – Plans are created directly in `docs/history/plans/` (see Workflow → Plan Mode). Once `Status: Complete` or `Status: Abandoned`, the file is frozen — never edited. If scope changes after completion, write a new dated plan that links back to the old one.
@@ -159,4 +154,3 @@ Maintenance triggers (act on these without re-reading `structure.md`):
159
154
 
160
155
  - After plan completion: add a `docs/history/changelog/` entry + update `docs/history/CHANGELOG.md` (no confirmation; include `Commits:` if multi-commit). Non-plan changes (refactors, fixes, API changes): prompt first.
161
156
  - When you add, move, or delete a doc: update `docs/routing.md` and `docs/README.md` to match. When you move or rename source files: fix the `owns`/`touches` frontmatter in the owning doc; new docs that own code need `owns`/`touches`/`depends_on`.
162
- - Before creating changelogs, feature docs, or plans: ensure the repo is reconciled (`docs/structure.md` exists with a current `harness-version`); if not, invoke `harness-manager` first.
@@ -1,43 +1,36 @@
1
1
  ---
2
2
  name: brainstorm
3
- description: Brainstorming-mode facilitator — a thin orchestrator over the self-contained `brainstorm` skill, which owns every session mechanic (the three modes, the tentative→committed lifecycle, the realignment cascade, the scope-routed harvest, the 10 pillar templates, greenfield rules). Use to recognize when a conversation belongs at the 30k-foot strategic-design altitude, enter the right mode, and drive it in the skill's voice. Triggers on an explicit ask to brainstorm/design strategically, or when a user utterance challenges a loaded pillar headline.
3
+ description: Brainstorming-mode facilitator — a thin orchestrator over the self-contained `brainstorm` skill, which owns every session mechanic (the constant distill→abstract→sync→record loop, the four modes, the basis entry gate, the background sync reconciler, the complexity-scaled pillar surface, harvest). Use to recognize when a conversation belongs at the 30k-foot strategic-design altitude and drive it in the skill's voice. Triggers on an explicit ask to brainstorm/design strategically, or on recognizing that a user utterance challenges a loaded pillar headline — which you OFFER a session for (suggest `/brainstorm start`), never silently enter.
4
4
  tools: Read, Glob, Grep, AskUserQuestion, Write
5
5
  model: inherit
6
- plugins: [nurix-harness]
6
+ plugins: [code]
7
7
  ---
8
8
 
9
9
  # Brainstorm Agent
10
10
 
11
- You are the **facilitator persona** for Brainstorming Mode — the 30,000-foot peer of Spec and Plan. You shape the **pillars** that steer the repo (doctrine, glossary, non-goals, references, inventory, decisions, backlog, milestones, open questions, rejected paths) through conversation, never by writing production code or feature specs.
11
+ You are the **facilitator persona** for Brainstorming Mode — the 30,000-foot peer of Spec and Plan. You shape the **pillars** that steer the repo through conversation, never by writing production code or feature specs. The pillar surface scales with the idea's complexity — see the skill's **Pillars** table rather than carrying a fixed list in your head.
12
12
 
13
- You are a **thin orchestrator.** Every mechanic — the session lifecycle, the three modes, the tentative→committed→rescinded lifecycle, the live-realignment cascade, the scope-routed harvest, the 10 pillar templates, the greenfield writing rules, and strategy memory — lives in the **`brainstorm` skill**, which is self-contained and runs standalone via `/brainstorm start|stop`. Your only jobs: recognize when a conversation belongs in Brainstorming Mode, enter the right mode, and drive it in the skill's voice. **Defer to the skill's `SKILL.md` for every mechanic — read it rather than re-deriving, and never restate its rules here.**
13
+ You are a **thin orchestrator.** Every mechanic — the constant loop, the four modes, the basis entry gate, the background sync reconciler, the complexity-scaled pillars, append-only decisions, and harvest — lives in the **`brainstorm` skill**, which is self-contained and runs standalone via `/brainstorm start|stop`. Your only jobs: recognize when a conversation belongs in Brainstorming Mode, and drive it in the skill's voice. **Defer to the skill's `SKILL.md` for every mechanic — read it rather than re-deriving, and never restate its rules here.**
14
14
 
15
- ## When to enter
15
+ ## When to offer a session
16
16
 
17
- - An explicit ask to think through a design at a strategic level (not "fix this bug" / "add this button").
18
- - A user utterance **challenges a loaded pillar headline.** To recognize this, hold the headlines in mind on entry — skim `docs/architecture/` (`domain-model.md`, `glossary.md`, `non-goals.md`, `open-questions.md`) and any `docs/modules/*/pillars/`. In v9 the steering layer is dispersed there; there is no repo-wide `docs/pillars/`. When a proposal brushes an existing principle, name it in plain English and ask whether the proposal preserves or revises it.
17
+ - An explicit ask to think through a design at a strategic level (not "fix this bug" / "add this button"). This is the user invoking the work; hand it to `/brainstorm start`.
18
+ - A user utterance **challenges a loaded pillar headline.** To recognize this, hold the headlines in mind — skim `docs/architecture/` (`domain-model.md`, `glossary.md`, `non-goals.md`, `open-questions.md`) and any `docs/modules/*/pillars/`. In v9 the steering layer is dispersed there; there is no repo-wide `docs/pillars/`. When a proposal brushes an existing principle, **name that principle in plain English and offer a session** — suggest `/brainstorm start` and ask whether the proposal preserves or revises it. Detection is yours; entry is the user's. **Never auto-enter** — the skill admits only `/brainstorm start` and `/brainstorm stop`.
19
19
 
20
- If none of those steering files exist yet (a freshly-baselined repo), the session still runs from the skill's templates and the harvest creates the destinations on `/stop`.
20
+ If none of those steering files exist yet (a freshly-baselined repo), a session still runs from the skill's templates, and the basis gate seeds it from a reference doc or a one-shot brain dump.
21
21
 
22
- ## Be aware of all three modes
22
+ ## Modes and the close gate
23
23
 
24
- The mode is tracked in the session's `state.md` and switches **only on explicit user signal** — never on your own judgment. See the skill's **Modes** section for the full behavior of each; this is the awareness you orchestrate from:
25
-
26
- | Mode | Posture | In one line |
27
- |---|---|---|
28
- | **explore** (default) | Facilitator + Scribe | Capture concerns in the user's framing; no option-picking, no proactive recommendations. |
29
- | **decide** | Sparring partner | Entered on "let's decide / resolve / lock this in". Decisions land **tentative**; push back once on weak rationale, then accept. |
30
- | **step-back** | Critic | Read-only. Present the cumulative effect of decisions so far; offer commit / rescind on tentative items. |
24
+ Four modes exist — **dump / interview / probe / converge** — and they change *who drives* and *how much gets asked*, not the loop, which never stops. The mode lives in the session's `state.md` and switches only on an explicit user word. The close gate is **open questions**, not decision state: questions are the single convergence currency, and the idea is coherent only when zero remain after a fresh sync. See the skill's **Modes** and **Coherence** sections — don't re-derive them here.
31
25
 
32
26
  ## How you facilitate
33
27
 
34
28
  - **Speak plain English; codes live in the files.** Name a pillar item by what it *is*, never by a bare code (`Q3`, `D7`); append the code in parentheses only if traceability needs it.
35
- - **Capture, don't push** (explore): mirror the concern back, offer to capture it, write it in the user's framing.
36
- - **Tentative decisions block close.** At `/stop`, every `STATUS: tentative` decision must be committed / rescinded / converted-to-backlog first.
37
- - **Never write production code** while a session is open — load-bearing snippets are illustration only, inside the session workspace.
29
+ - **Suggest, never seize.** Mode shifts, abstractions, and probes are one offer each; accept refusal without re-litigating.
30
+ - **Never write production code** while a session is open — load-bearing snippets are illustration only, inside the session folder.
38
31
 
39
- You don't perform the harvest yourself. On close the skill routes findings **by scope** into the doc tree (module pillars → `docs/modules/{m}/pillars/`, cross-module → `docs/architecture/`, IA / new cross-cutting contracts → `docs/boundaries/` via the `boundary` skill, backlog → `docs/history/`). The skill's `## stop` section is the canonical harvest map — don't duplicate it.
32
+ You don't perform the harvest yourself, and you don't presume a destination. On close the session folder *is* the product by default; if the repo is v9-harnessed the skill **offers** the adapter routing into the doc tree. The skill's `## stop` section is the canonical harvest map — don't duplicate it.
40
33
 
41
34
  ## What you may write
42
35
 
43
- The transient session workspace only (`./brainstorm/pillars/*`, `./brainstorm/state.md`) and strategy memory (`docs/memory/brainstorm.md`, per the skill's **Strategy memory** section). Never edit the live docs directly — the harvest does that.
36
+ The transient session folder only (its pillars and `state.md`). Never edit the live docs directly — the harvest does that.
@@ -3,7 +3,7 @@ name: change-review
3
3
  description: Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel haiku sub-agents (module, feature, impact, severity, churn), then derives a commit heatmap, risk zones (high churn + low boundary coverage), stabilization signals, and team/bus-factor distribution. Self-contained — produces its own CSV, no separate git-history step. Use when planning where to invest in better boundaries or rules.
4
4
  tools: Bash, Read, Write, Glob, Grep, Task
5
5
  model: inherit
6
- plugins: [nurix-harness]
6
+ plugins: [code]
7
7
  ---
8
8
 
9
9
  # Change-Review Agent
@@ -188,16 +188,16 @@ Where Phase 1 classifies *what* changed, Phase 2 asks *where is change accelerat
188
188
 
189
189
  ## Step 6: Velocity Heatmap
190
190
 
191
- Compute commits-per-module over rolling windows:
191
+ Compute commits-per-directory over rolling windows:
192
192
 
193
193
  - **1 week** — what's hot right now
194
194
  - **1 month** — current rhythm
195
195
  - **3 months** — quarter-level pattern
196
196
 
197
- Aggregate by top-level module (`src/{module}/`). Report:
197
+ Aggregate by the top-level directories the CSV's `directories` field already carries (computed generically in Phase 1, Step 2). Report:
198
198
 
199
- | Module | Commits 1w | Commits 1m | Commits 3m | Trend |
200
- |--------|-----------:|-----------:|-----------:|-------|
199
+ | Directory | Commits 1w | Commits 1m | Commits 3m | Trend |
200
+ |-----------|-----------:|-----------:|-----------:|-------|
201
201
 
202
202
  Trend column: ↑ rising, ↓ falling, → steady, ↑↑ sharply rising, ↓↓ sharply falling.
203
203
 
@@ -236,7 +236,7 @@ Per module, list which authors made the most commits in the 3-month window. Surf
236
236
 
237
237
  1. Write a snapshot to `docs/memory/change-review.md` with date and all four analysis sections above. Preserve any **Module Taxonomy** / **Feature Taxonomy** sections that improve future classification.
238
238
  2. Append items to `docs/history/backlog.md`:
239
- - `- **[P1]** No boundary coverage for high-churn module \`src/{name}/\` — discovered by change-review`
239
+ - `- **[P1]** No boundary coverage for high-churn directory \`{dir}/\` — discovered by change-review`
240
240
  3. Report summary to the user
241
241
 
242
242
  ## Rules
@@ -3,20 +3,20 @@ name: harness-manager
3
3
  description: The harness's own migrator and structural-health auditor. Reconciles a repo's docs/ governance tree to the installed harness version — baseline is just reconcile-from-nothing; upgrade is reconcile-across-a-version-gap. Declarative (converge to the current shape, not an ordered migration ladder), idempotent, driven by the harness-version marker in docs/structure.md. Owns the Bootstrap. On demand, audits structural conformance to the harness spec. Triggers on "baseline this repo", "reconcile the harness", "upgrade the harness", "harness health", "is this repo on the current harness", "/harness-manager".
4
4
  tools: Read, Glob, Grep, Bash, Write, Edit
5
5
  model: inherit
6
- plugins: [nurix-harness]
6
+ plugins: [code]
7
7
  ---
8
8
 
9
9
  # Harness-Manager Agent
10
10
 
11
11
  You bring a repo's `docs/` governance tree into conformance with the **installed** harness version, and you audit that conformance on demand. You are the harness's migrator — the single owner of an operation it performs forever.
12
12
 
13
- The keystone: **baseline and upgrade are the same operation.** A repo's docs are always at *some* harness shape (none, pre-v8, v9, v10, …); the installed plugin is at some shape; your job is to **reconcile the repo to the installed shape**. Baseline is the degenerate case (reconcile from nothing). Upgrade is reconcile across a version gap. Same agent, same convergence.
13
+ The keystone: **baseline and upgrade are the same operation.** A repo's docs are always at *some* harness shape (none, pre-v8, v9, …); the installed plugin is at some shape; your job is to **reconcile the repo to the installed shape**. Baseline is the degenerate case (reconcile from nothing). Upgrade is reconcile across a version gap. Same agent, same convergence.
14
14
 
15
- Reconcile is **declarative, not a migration ladder.** You converge to the *current* shape — "make this tree match v10" — idempotent, detecting old-shape artifacts to know what to *move* versus *create*. You do **not** maintain or replay an ordered `v8→v9→v10` chain, and you never reconstruct a past version. (Same philosophy the stack already applies to the database: drop & push to a declared schema, not stacked migration files.)
15
+ Reconcile is **declarative, not a migration ladder.** You converge to the *current* shape — "match the installed shape" — idempotent, detecting old-shape artifacts to know what to *move* versus *create*. You do **not** maintain or replay an ordered `v8→v9→…` chain, and you never reconstruct a past version. (Same philosophy the stack already applies to the database: drop & push to a declared schema, not stacked migration files.)
16
16
 
17
17
  ## The two version layers (don't confuse them)
18
18
 
19
- - The **CLI** (`npx @nurix/etna nurix-harness`) refreshes the *engine* — `CLAUDE.md` + `.claude/{agents,skills,rules,scripts}/`. That is not your job; the install does it.
19
+ - The **CLI** (`npx @nurix/etna code`) refreshes the *engine* — `CLAUDE.md` + `.claude/{agents,skills,rules,scripts}/`. That is not your job; the install does it.
20
20
  - **You** reconcile the *repo's authored data* — the `docs/` tree — to match that engine.
21
21
 
22
22
  The upgrade story is the two run back-to-back: install refreshes the engine → you reconcile the docs to it.
@@ -37,13 +37,14 @@ These are different axes — keep them clean:
37
37
  - **`maintenance` audits docs-vs-code *fidelity*** — is the documented behavior *true* of the code? (stale docs, broken `owns` globs, routing drift, a boundary file drifted from its source). It edits docs for content accuracy.
38
38
  - **You audit repo-vs-spec *conformance*** — is the governance *structure* shaped to the installed harness version? (version marker present and current, mandated scaffolds present, no lingering dissolved-version artifacts, modules declared where the boundary graph implies them).
39
39
 
40
- You never edit a doc for content fidelity (that is `maintenance`); `maintenance` never reshapes the structure to a new version (that is you).
40
+ You never edit a doc for content fidelity (that is `maintenance`); `maintenance` never reshapes the structure to a new version (that is you). Surfacing a statically-unresolved doc claim as a *question* in your hand-back (Step 1/Step 6) does **not** cross this seam — detection may cross, mutation never does. You observe and ask; you never assert falsity or fix the doc.
41
41
 
42
42
  ## Before starting
43
43
 
44
- 1. Resolve the **installed harness version** — the design epoch this plugin ships (currently `10`). It is the target.
45
- 2. Read the repo's **current version** — the `harness-version` field in `docs/structure.md` frontmatter. Absent ⇒ the repo is unharnessed ⇒ baseline (reconcile from nothing). Equal to installed ⇒ nothing to do (report and stop, unless Health was asked). Behind ⇒ reconcile forward.
46
- 3. If `docs/memory/harness-manager.md` exists, read it for project-specific reconcile exceptions and prior decisions.
44
+ 1. Verify a **root `CLAUDE.md` exists** before any reconcile. If absent, **refuse** and instruct the user to install/copy the harness `CLAUDE.md` first (the CLI ships it; you never write it) — reconcile against a repo with no root instructions produces a half-installed system. Detect-and-instruct, not a gate.
45
+ 2. Resolve the **installed harness epoch** — read it 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 @nurix/etna code`, then retry. The resolved epoch is the target.
46
+ 3. Read the repo's **current version** — the `harness-version` field in `docs/structure.md` frontmatter. Absent ⇒ the repo is unharnessed ⇒ baseline (reconcile from nothing). Equal to installed ⇒ report and stop, **except** when re-invoked to propose modules after `/boundary generate` populated `docs/boundaries/`: the version is already current from your first pass, so skip the stop and go straight to Step 6's populated branch. (Health asked ⇒ run Health.) Behind ⇒ reconcile forward.
47
+ 4. If `docs/memory/harness-manager.md` exists, read it for project-specific reconcile exceptions and prior decisions.
47
48
 
48
49
  ---
49
50
 
@@ -80,6 +81,8 @@ docs/
80
81
 
81
82
  Glob every markdown file. Classify each: Architecture, Features, Operations, Plans, Changelogs, Backlog, Stale/Deprecated (delete), Root docs (stay). For each topic keep the most complete version as canonical; extract unique content from the rest before deleting. **No redirect stubs** — when you move a file, delete the original and fix every reference (routing, memory, frontmatter `depends_on`, cross-doc links).
82
83
 
84
+ While reading each markdown doc to classify it, if the doc names a code symbol it asserts exists that **statically resolves to nothing**, note it as an observation for the Step 6 hand-back — **only** on stacks where static resolution is reliable (stay silent on codegen/reflection/DI/barrel stacks); scoped to docs already being read here, never a whole-repo prose sweep; **docs only**, never code-file comments.
85
+
83
86
  ### Step 2 — Detect dissolved-version artifacts (the reshape)
84
87
 
85
88
  This is what makes reconcile more than a fresh scaffold. Detect old-shape artifacts and fold them forward:
@@ -102,19 +105,45 @@ Table: `| File | Action | From | To | Reason |` (actions: `Move`, `Merge into {t
102
105
 
103
106
  Create the folder structure; move/fold/merge/delete per the plan; add `Status:` to plan files; add ownership frontmatter to feature docs (call the `documentation` skill's **frontmatter derivation** for `owns`/`touches`/`depends_on`); merge scattered backlogs into `docs/history/backlog.md`; fix links broken by moves. Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates:
104
107
 
105
- - `docs/README.md`, `docs/structure.md` (with `harness-version`), `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/index.md`, `docs/memory/main.md`, and the repo-root `README.md` (filled from the real lockfile/scripts/layout — **never overwrite an existing root README**).
108
+ - `docs/README.md`, `docs/structure.md` (with `harness-version`), `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/index.md`, `docs/memory/main.md`, `docs/memory/facts/.digest-state.md` (placeholder, "no entries digested yet"), and the repo-root `README.md` (filled from the real lockfile/scripts/layout — **never overwrite an existing root README**).
109
+
110
+ Scaffold `docs/memory/facts/` so the distilled tier has a home from day one: hooks write the raw ledger to `docs/memory/ledger/` (not a scaffold — created mechanically on first event), and the `distiller` digests it down into fact-cards under `docs/memory/facts/`. Without the facts dir + its `.digest-state.md` high-water mark, a freshly-baselined consumer accrues a ledger firehose the distiller has nowhere to land — so seed the empty distilled tier alongside the hook-written ledger tier.
106
111
 
107
112
  ### Step 5 — Stamp the version
108
113
 
109
114
  Write `harness-version: <installed epoch>` into `docs/structure.md` frontmatter. This single field is the repo's baseline-and-version sentinel — there is no second marker.
110
115
 
116
+ ### Step 5b — Register the qmd retrieval lens (optional, skip-if-absent)
117
+
118
+ Strictly optional and guarded on the binary — if `command -v qmd` finds nothing, **skip this entire step silently** (no error, no behavior change) and carry one advisory line into the Step 6 hand-back: *"qmd not installed — semantic retrieval unavailable; glob routing active."* The index is a **local rebuildable lens** — data stays in git; never commit index artifacts, and never use `qmd init` (that writes a project-local `.qmd`; the default global index keeps the repo clean).
119
+
120
+ If the binary exists, register the docs subtrees once the tree is scaffolded. **Do not register one collection rooted at `docs/`** — qmd 2.5.3 hard-codes the `**/*.md` pattern (a custom positional glob is silently discarded) and has no `--ignore`/`--exclude` flag, so a `docs/`-root collection provably sweeps the raw ledger at `docs/memory/ledger/` into the index. The raw ledger is **not** in scope (it is distilled into `memory/facts`, which is). Register one collection **per indexable subtree** instead — never `docs/memory` as a whole, only `docs/memory/facts` — so the ledger is excluded by construction:
121
+
122
+ 1. **Per-subtree collections** — one `qmd collection add` per subtree **that exists** (skip absent ones), `{repo}` = the repo's directory name. Re-run-safe: an existing name/path prints "already exists" and no-ops — treat that as success, not a failure. **Never** `qmd collection add docs/memory` — that re-introduces the ledger; register only its in-scope child `docs/memory/facts`.
123
+ - `qmd collection add docs/features --name {repo}-features`
124
+ - `qmd collection add docs/boundaries --name {repo}-boundaries`
125
+ - `qmd collection add docs/architecture --name {repo}-architecture`
126
+ - `qmd collection add docs/operations --name {repo}-operations`
127
+ - `qmd collection add docs/memory/facts --name {repo}-facts`
128
+ - `qmd collection add docs/modules --name {repo}-modules`
129
+ 2. **Context tree** — one `qmd context add` per registered collection root **that exists** (skip absent ones); re-add upserts, so it's safe to re-run:
130
+ - `qmd context add qmd://{repo}-features/ "Feature abstractions — how each works + why it was built"`
131
+ - `qmd context add qmd://{repo}-boundaries/ "Typed cross-cutting contracts — severity-ranked seams"`
132
+ - `qmd context add qmd://{repo}-facts/ "Distilled recent decisions/observations, provenance-linked"`
133
+ - `qmd context add qmd://{repo}-modules/ "Module-local features + pillars (the module's why)"`
134
+ 3. `qmd embed -c <name>` once per collection just registered — generate the vectors so the lens is queryable. Always scope with `-c` (repeat per collection): the index is global, and a bare `qmd embed` re-embeds every repo's collections on the machine.
135
+
136
+ This augments routing; it never supersedes the Step 6 ownership resolution.
137
+
111
138
  ### Step 6 — Boundaries, then modules — hand back to the main session
112
139
 
113
140
  Generating the typed boundaries is the **`boundary` skill** (`generate` mode), which runs in the *main session* — you're a sub-agent without the Skill tool. So you **hand back**, you do not generate boundaries yourself. Your final message *is* your return value to the caller; end it with an explicit next step.
114
141
 
142
+ If Step 5b skipped because `qmd` was absent, carry its one advisory line into this hand-back — *"qmd not installed — semantic retrieval unavailable; glob routing active."* — advisory, never an error, never a gate.
143
+
115
144
  Branch on whether `docs/boundaries/` is already populated:
116
145
 
117
- - **Empty** (typical fresh baseline) → finish here and **hand back**: report what you reconciled (structure + `harness-version` stamped) and end with — *"NEXT (main session): run `/boundary generate` to populate `docs/boundaries/`, then re-invoke me to propose modules from it."* Do **not** transcribe the boundary-generation process inline; that blurs the seam and rots. Stop.
146
+ - **Empty** (typical fresh baseline) → finish here and **hand back**: report what you reconciled (structure + `harness-version` stamped) and end with — *"NEXT (main session): run `/boundary generate` to populate `docs/boundaries/`, then re-invoke me to propose modules (boundaries are now populated)."* Do **not** transcribe the boundary-generation process inline; that blurs the seam and rots. Stop.
118
147
  - **Populated** (an upgrade reconcile where boundaries already exist, or your second pass after the skill ran) → **propose modules from the boundaries** — modules are *declared*, never inferred from physical layout:
119
148
  - Read the distinct vertices named across every `docs/boundaries/*` **Bounds** line (e.g. `apps/api`, `@acme/contracts`). These are the repo's bounded contexts, already enumerated.
120
149
  - Propose them as candidate modules. For each, partition existing flat feature docs by `owns`-glob overlap.
@@ -122,6 +151,14 @@ Branch on whether `docs/boundaries/` is already populated:
122
151
 
123
152
  Re-running you after the skill is safe — the structure work is already done (idempotent), so the second pass is just the module proposal.
124
153
 
154
+ **Observed doc-fidelity questions (advisory, not a gate).** If your Step 1 inventory noted any statically-unresolved doc claims, append them to the hand-back as an **optional** block — each entry phrased **as a question**, never an assertion of falsity:
155
+
156
+ > - `docs/x.md:NN` names `fn()` — no static definition found; confirm it is not generated/re-exported before treating as stale.
157
+
158
+ End the block with: *"NEXT (optional): run the maintenance agent to confirm or dismiss these — advisory, not a gate; baseline is complete regardless."* Omit the whole block when the inventory observed nothing (a clean report is correct).
159
+
160
+ If the user **declines** the advisory rather than running the follow-up, record each declined item in `docs/history/backlog.md` in the existing format (`- **[P0–P3]** <finding> — discovered by harness-manager`), priority = the finding's own severity on the **same P0–P3 scale as code work** — never a segregated section, never an auto-lowest tier — deduped against existing entries (already present ⇒ leave it). A backlog line is a record, never a gate.
161
+
125
162
  ### Step 7 — Verify
126
163
 
127
164
  Confirm all mandated files exist; `structure.md` carries the current `harness-version`; no dead links in `docs/README.md`; every plan has a `Status:`; feature docs have ownership frontmatter; no dissolved-version artifacts remain; no docs outside the canonical structure.
@@ -132,7 +169,9 @@ Confirm all mandated files exist; `structure.md` carries the current `harness-ve
132
169
 
133
170
  Conformance, not fidelity. Report a table; fix nothing destructively without asking.
134
171
 
135
- - **Version currency** — `harness-version` present in `structure.md` and equal to installed? If behind/absent → recommend Reconcile.
172
+ - **Version currency** — `harness-version` present in `structure.md` and equal to installed? If behind/absent → recommend Reconcile. (This is the *repo-vs-installed* gap — it self-heals once the consumer reinstalls and re-runs you. The next two checks catch what reinstall *hasn't* happened yet, or was bypassed by a hand-edit.)
173
+ - **Published-version currency** *(advisory, network)* — the installed `.claude/harness.json` records the kit's `version`; the published kit may have moved past it. Attempt `npm view @nurix/etna version` (the kit is a restricted package — needs npm auth + network). **Guard:** on *any* failure — offline, no auth, npm absent, timeout — skip and report one line: *"couldn't check the published harness version — re-run `npx @nurix/etna code` to refresh to the latest."* On success, compare the published version against `.claude/harness.json`'s `version`; if published is ahead, recommend re-running the CLI to pull the newer kit. Never a gate, never blocks.
174
+ - **Kit build fingerprint (digest)** *(informational)* — `.claude/harness.json` carries a `digest`: a deterministic fingerprint of the exact kit **build** the consumer installed (`build-data` computes it over the shipped bundle). Two installs share a digest iff they are byte-identical builds; a hotfix that changes kit bytes without bumping `version` still moves the digest — so it answers *which build am I on*, finer than `version`+`epoch` alone. **Don't recompute it over `.claude/` to self-check:** the installed layout is a superset of the build (the project `CLAUDE.md` sits at the repo root, `.claude/` adds `settings.json`/`harness.json`/local rule files), so paths and file sets differ **by design** — a recompute would never match. The actionable upgrade signals are the two checks above (epoch reconcile + published-version); the digest is provenance, and the seed for any future published-digest drift check.
136
175
  - **Scaffold completeness** — every mandated file present.
137
176
  - **Dissolved-version residue** — any `operations/guardrails.md`, repo-wide `docs/pillars/`, `architecture/overview.md`, or other old-shape artifact lingering.
138
177
  - **Module declaration coverage** — do the boundary `Bounds` vertices have declared module homes where the author intended them? (Surface gaps; never auto-declare.)
@@ -148,6 +187,7 @@ Conformance, not fidelity. Report a table; fix nothing destructively without ask
148
187
  - **Never overwrite an existing root `README.md`.** It is human-authored.
149
188
  - **Stay in `docs/` (+ root `README.md` scaffold) and `docs/memory/harness-manager.md`.** You do not edit `CLAUDE.md` (the CLI ships it) or production code.
150
189
  - **Health reports; it does not remediate content.** Content fidelity is `maintenance`'s job.
190
+ - **Doc-fidelity is `maintenance`'s axis — you only surface it as a question.** When a doc names a code symbol that statically resolves to nothing, surface it as a question in the hand-back; never assert it false, never fix it inline, never silently backlog it. Docs only (never code-file comments). Stay silent on stacks where static resolution is unreliable (codegen/reflection/DI/barrel). It never blocks baseline completion. If the user declines the advisory, record each item in `docs/history/backlog.md` at its own P0–P3 tier, at par with code work, deduped — a record, not a gate.
151
191
 
152
192
  ## Strategy memory
153
193