@nurix/etna 0.19.20 → 0.19.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/data/harness-index.json +1 -1
  2. package/data/harnesses/code/.prettierignore +6 -0
  3. package/data/harnesses/code/CLAUDE.md +15 -14
  4. package/data/harnesses/code/agents/maintenance.md +1 -1
  5. package/data/harnesses/code/codex/agents/maintenance.toml +1 -1
  6. package/data/harnesses/code/harness.json +2 -2
  7. package/data/harnesses/code/skills/boundary/SKILL.md +1 -1
  8. package/data/harnesses/code/skills/brainstorm/SKILL.md +1 -1
  9. package/data/harnesses/code/skills/documentation/SKILL.md +64 -107
  10. package/data/harnesses/code/skills/documentation/references/examples.md +83 -7
  11. package/data/harnesses/code/skills/documentation/references/frontmatter.md +44 -0
  12. package/data/harnesses/code/skills/documentation/references/style-guide.md +44 -19
  13. package/data/harnesses/code/skills/documentation/references/untemplated.md +38 -0
  14. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +117 -0
  15. package/data/harnesses/code/skills/documentation/templates/Readme.md +31 -0
  16. package/data/harnesses/code/skills/documentation/templates/api-reference.md +20 -0
  17. package/data/harnesses/code/skills/documentation/templates/architecture-decision.md +121 -0
  18. package/data/harnesses/code/skills/documentation/templates/backlog.md +33 -0
  19. package/data/harnesses/code/skills/documentation/templates/changelog-entry.md +62 -0
  20. package/data/harnesses/code/skills/documentation/templates/changelog-index.md +41 -0
  21. package/data/harnesses/code/skills/documentation/templates/docs-readme.md +70 -0
  22. package/data/harnesses/code/skills/documentation/templates/domain-model.md +30 -0
  23. package/data/harnesses/code/skills/documentation/templates/environment-registry.md +15 -0
  24. package/data/harnesses/code/skills/documentation/templates/feature.md +149 -0
  25. package/data/harnesses/code/skills/documentation/templates/glossary.md +11 -0
  26. package/data/harnesses/code/skills/documentation/templates/memory-main.md +25 -0
  27. package/data/harnesses/code/skills/documentation/templates/migration-runbook.md +34 -0
  28. package/data/harnesses/code/skills/documentation/templates/non-goals.md +11 -0
  29. package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +36 -0
  30. package/data/harnesses/code/skills/documentation/templates/plan.md +64 -0
  31. package/data/harnesses/code/skills/documentation/templates/protected-files.md +37 -0
  32. package/data/harnesses/code/skills/documentation/templates/root-readme.md +104 -0
  33. package/data/harnesses/code/skills/documentation/templates/security-overview.md +27 -0
  34. package/data/harnesses/code/skills/documentation/templates/structure.md +65 -0
  35. package/data/harnesses/code/skills/documentation/templates/system-overview.md +32 -0
  36. package/data/harnesses/code/skills/documentation/templates/testing-strategy.md +29 -0
  37. package/data/harnesses/code/skills/workflow-mapper/SKILL.md +1 -1
  38. package/data/harnesses/discover/.prettierignore +6 -0
  39. package/data/harnesses/discover/CLAUDE.md +11 -12
  40. package/data/harnesses/discover/harness.json +2 -2
  41. package/data/harnesses/discover/tooling-recommendations.md +10 -10
  42. package/data/harnesses/discussion/.prettierignore +6 -0
  43. package/data/harnesses/discussion/harness.json +1 -1
  44. package/data/harnesses/etna/.prettierignore +6 -0
  45. package/data/harnesses/etna/CLAUDE.md +12 -11
  46. package/data/harnesses/etna/agents/maintenance.md +1 -1
  47. package/data/harnesses/etna/codex/agents/maintenance.toml +1 -1
  48. package/data/harnesses/etna/harness.json +2 -2
  49. package/data/harnesses/etna/skills/boundary/SKILL.md +1 -1
  50. package/data/harnesses/etna/skills/brainstorm/SKILL.md +1 -1
  51. package/data/harnesses/etna/skills/documentation/SKILL.md +64 -107
  52. package/data/harnesses/etna/skills/documentation/references/examples.md +83 -7
  53. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +44 -0
  54. package/data/harnesses/etna/skills/documentation/references/style-guide.md +44 -19
  55. package/data/harnesses/etna/skills/documentation/references/untemplated.md +38 -0
  56. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +117 -0
  57. package/data/harnesses/etna/skills/documentation/templates/Readme.md +31 -0
  58. package/data/harnesses/etna/skills/documentation/templates/api-reference.md +20 -0
  59. package/data/harnesses/etna/skills/documentation/templates/architecture-decision.md +121 -0
  60. package/data/harnesses/etna/skills/documentation/templates/backlog.md +33 -0
  61. package/data/harnesses/etna/skills/documentation/templates/changelog-entry.md +62 -0
  62. package/data/harnesses/etna/skills/documentation/templates/changelog-index.md +41 -0
  63. package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +70 -0
  64. package/data/harnesses/etna/skills/documentation/templates/domain-model.md +30 -0
  65. package/data/harnesses/etna/skills/documentation/templates/environment-registry.md +15 -0
  66. package/data/harnesses/etna/skills/documentation/templates/feature.md +149 -0
  67. package/data/harnesses/etna/skills/documentation/templates/glossary.md +11 -0
  68. package/data/harnesses/etna/skills/documentation/templates/memory-main.md +25 -0
  69. package/data/harnesses/etna/skills/documentation/templates/migration-runbook.md +34 -0
  70. package/data/harnesses/etna/skills/documentation/templates/non-goals.md +11 -0
  71. package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +36 -0
  72. package/data/harnesses/etna/skills/documentation/templates/plan.md +64 -0
  73. package/data/harnesses/etna/skills/documentation/templates/protected-files.md +37 -0
  74. package/data/harnesses/etna/skills/documentation/templates/root-readme.md +104 -0
  75. package/data/harnesses/etna/skills/documentation/templates/security-overview.md +27 -0
  76. package/data/harnesses/etna/skills/documentation/templates/structure.md +65 -0
  77. package/data/harnesses/etna/skills/documentation/templates/system-overview.md +32 -0
  78. package/data/harnesses/etna/skills/documentation/templates/testing-strategy.md +29 -0
  79. package/data/harnesses/etna/skills/workflow-mapper/SKILL.md +1 -1
  80. package/data/harnesses/hr/.prettierignore +6 -0
  81. package/data/harnesses/hr/CLAUDE.md +19 -23
  82. package/data/harnesses/hr/harness.json +2 -2
  83. package/data/harnesses/hr/skills/evaluator/SKILL.md +1 -1
  84. package/data/harnesses/hr/skills/interview-eval/SKILL.md +1 -1
  85. package/data/harnesses/kb-agi/.prettierignore +6 -0
  86. package/data/harnesses/kb-agi/CLAUDE.md +12 -12
  87. package/data/harnesses/kb-agi/harness.json +1 -1
  88. package/package.json +1 -1
  89. package/data/harnesses/code/skills/documentation/references/templates.md +0 -1091
  90. package/data/harnesses/etna/skills/documentation/references/templates.md +0 -1091
@@ -1,12 +1,12 @@
1
1
  # hr — AI-Steering Evaluation harness
2
2
 
3
- This repo evaluates **how a person steered a Claude Code session** — for interview and hiring assessment. You read session transcripts (`.jsonl`) and produce a calibrated, evidence-anchored read on the candidate's ability to drive an AI coding agent.
3
+ This repo evaluates **how a person steered a Claude Code session** — for interview and hiring assessment. The harness reads session transcripts (`.jsonl`) and produces a calibrated, evidence-anchored read on the candidate's ability to drive an AI coding agent.
4
4
 
5
- You are the **evaluator**. The work is the `interview-eval` skill (its `rubric.md` holds the band anchors, gates, and session-type matrix; `extract_session.py` is the deterministic extractor; `TEMPLATE.md` holds the output shapes). This `CLAUDE.md` is the **policy** over that skill: the pipeline, the discipline that keeps scores honest, and the things you must never do.
5
+ The work is the `interview-eval` skill (its `rubric.md` holds the band anchors, gates, and session-type matrix; `extract_session.py` is the deterministic extractor; `TEMPLATE.md` holds the output shapes). This `CLAUDE.md` is the **policy** over that skill: the pipeline, the discipline that keeps scores honest, and the standing prohibitions.
6
6
 
7
- ## Two things you can evaluate
7
+ ## Two evaluation modes
8
8
 
9
- Pick the mode from what the user hands you:
9
+ Pick the mode from what the user hands over:
10
10
 
11
11
  - **Session steering** (`.jsonl` transcripts) — score how the candidate drove the agent. That is the `interview-eval` skill and the pipeline below; it is the default and the bulk of this file.
12
12
  - **Code-project quality** (one or more repos / paths) — score the project the candidate produced. For a *set* of projects, follow the **`code-eval-batcher`** rule (it fans the `evaluator` skill across them and ranks the result); for a single project, invoke the `evaluator` skill directly. The session-steering discipline below does not apply to this mode — the skill and the rule are self-contained.
@@ -15,13 +15,13 @@ Pick the mode from what the user hands you:
15
15
 
16
16
  ## The one rule above all others
17
17
 
18
- **You score the human, not the model.** Claude writing clean code earns the candidate nothing; Claude writing buggy code costs them nothing — _unless_ the candidate's prompt caused it or they failed to catch it. Reward the prompt that set the agent up, the verification that caught its mistake, the redirect that pulled it off a bad path. Turn count, prompt length, and verbosity are **not** quality — precision, judgment, and verification are. Re-read this before every scoring pass.
18
+ **Score the human, not the model.** Claude writing clean code earns the candidate nothing; Claude writing buggy code costs them nothing — _unless_ the candidate's prompt caused it or they failed to catch it. Reward the prompt that set the agent up, the verification that caught its mistake, the redirect that pulled it off a bad path. Turn count, prompt length, and verbosity are **not** quality — precision, judgment, and verification are. Re-read this before every scoring pass.
19
19
 
20
20
  ---
21
21
 
22
22
  ## Step 0 — first run
23
23
 
24
- If the `interview-eval` skill isn't resolvable (no `.claude/skills/interview-eval/`), this project isn't set up — tell the user to run `npx --yes @nurix/etna --name=hr` (or point you at the skill) before continuing. Confirm `python3` is on PATH; the extractor is stdlib-only and needs nothing else.
24
+ If the `interview-eval` skill isn't resolvable (no `.claude/skills/interview-eval/`), this project isn't set up — tell the user to run `npx --yes @nurix/etna --name=hr` (or point at an existing copy of the skill) before continuing. Confirm `python3` is on PATH; the extractor is stdlib-only and needs nothing else.
25
25
 
26
26
  ## Step 1 — intake interview
27
27
 
@@ -35,35 +35,31 @@ Keep it to those. Carry the answers forward; don't re-interview per session.
35
35
 
36
36
  ## Step 2 — run the pipeline (delegate to `interview-eval`)
37
37
 
38
- For each candidate, invoke the `interview-eval` skill. It owns the mechanics; your job is to drive it and hold the discipline below. The flow it runs:
38
+ For each candidate, invoke the `interview-eval` skill. It owns the mechanics; this policy drives it and holds the discipline below. The flow it runs:
39
39
 
40
- ```
41
- Extract → python3 extract_session.py SESSION.jsonl --out <out_dir>/<slug>/ --json
42
- │ → read the FULL evidence pack before scoring; open raw .jsonl around any turn you quote
43
- Classify → dominant session type (greenfield / feature / debugging / refactor / ops / research / review)
44
- │ → sets which dimensions are primary / secondary / N/A
45
- Score → 9 dimensions × 0–5 absolute bands, ≥2 quoted turn cites each; gates; green flags
46
- │ → <out_dir>/<slug>/{report.md, scorecard.yaml}
47
- Roll up → if >1 session: dimension trends + consistency + one calibrated level
48
- → <out_dir>/candidate-rollup.md
49
- ```
40
+ | Step | Mechanics | Output |
41
+ | --- | --- | --- |
42
+ | **Extract** | `python3 extract_session.py SESSION.jsonl --out <out_dir>/<slug>/ --json` — read the FULL evidence pack before scoring; open raw `.jsonl` around any quoted turn | evidence pack in `<out_dir>/<slug>/` |
43
+ | **Classify** | dominant session type (greenfield / feature / debugging / refactor / ops / research / review) | which dimensions are primary / secondary / N/A |
44
+ | **Score** | 9 dimensions × 0–5 absolute bands, ≥2 quoted turn cites each; gates; green flags | `<out_dir>/<slug>/{report.md, scorecard.yaml}` |
45
+ | **Roll up** | if >1 session: dimension trends + consistency + one calibrated level | `<out_dir>/candidate-rollup.md` |
50
46
 
51
47
  After the rollup, **always produce a one-page candidate brief** (verdict + level, the standout evidence, the single biggest risk, and 3–4 interview follow-ups that would confirm or kill that risk). That brief is the deliverable a hiring manager reads first.
52
48
 
53
49
  ## Step 3 — calibration discipline (non-negotiable)
54
50
 
55
51
  - **Evidence or it didn't happen.** Every band cites real `U<n>` turns with short verbatim quotes. "Seems thorough" is not a finding.
56
- - **Absolute bands, not a curve.** Score each session against `rubric.md`'s anchors. With multiple candidates you may _report_ relative ranking, but each band is assigned absolutely.
52
+ - **Absolute bands, not a curve.** Score each session against `rubric.md`'s anchors. With multiple candidates, relative ranking may be _reported_ — but each band is assigned absolutely.
57
53
  - **Exclude harness noise.** API 529s / connection drops are Anthropic-side — never penalize them. Tool-permission prompts and model slips the human then caught are not candidate failures. Distinguish a sharp early interrupt (good) from thrash (bad) by reading the surrounding turns.
58
54
  - **Gates require human direction.** A gate fires only on confirmed _unsafe steering_ the human directed or ratified (pasted a live secret, approved a destructive op unchecked, knowingly shipped broken output) — not on a model mistake. Verify the auto-detected red-flag leads against the transcript before firing one.
59
55
  - **Charity with a spine.** Read terse prompts and typos in the best plausible light, but never invent verification or judgment the transcript doesn't show.
60
56
 
61
- ## What you do _not_ do
57
+ ## Standing prohibitions
62
58
 
63
- - **You don't decide the hire.** You produce a level and a brief; the human decides. Frame the level as a calibrated lens, never a verdict.
64
- - **You don't mutate the source transcripts.** The skill is read-only over `.jsonl`; you only write into `out_dir`.
65
- - **You don't score Claude's code quality as if it were the candidate's.** If the agent proposed the good design and the human only assented, say so — that's weaker judgment than originating it.
66
- - **You don't fabricate a score from thin evidence.** A one-turn fragment or an empty/corrupt transcript gets a stub that says so and defers to the rollup — not an invented band.
59
+ - **The hire decision stays with the human.** The output is a level and a brief; frame the level as a calibrated lens, never a verdict.
60
+ - **Source transcripts are never mutated.** The skill is read-only over `.jsonl`; writes land only in `out_dir`.
61
+ - **Claude's code quality is never scored as the candidate's.** If the agent proposed the good design and the human only assented, say so — that's weaker judgment than originating it.
62
+ - **A score is never fabricated from thin evidence.** A one-turn fragment or an empty/corrupt transcript gets a stub that says so and defers to the rollup — not an invented band.
67
63
 
68
64
  Every output lands under `out_dir` and is plain markdown/YAML — reviewable, quotable, and reversible.
69
65
 
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "harness": "hr",
3
3
  "name": "hr",
4
- "version": "0.1.7",
4
+ "version": "0.1.8",
5
5
  "files": [
6
6
  ".prettierignore",
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
- "digest": "2fd45f5d45d3"
10
+ "digest": "b547d3ca2c1b"
11
11
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: evaluator
3
- description: Apply a generic production-readiness + product-quality rubric to a single software project. Takes a repo reference + an output directory, writes a per-project workspace (`<out_dir>/<project>/` containing `README.md`, `scorecard.yaml`, and a flat `raw/` directory where every file is named `<sub-criterion>-<artifact>.ext` — e.g. `raw/code-quality-semgrep-quality.json`, `raw/maintainability-deptry.json`), and returns the workspace path. The scorecard is a YAML with 8 sub-criterion blocks (4 Code + 4 Product, 12.5 pts each = 100 pts), a 0–5 score + evidence + data per item, gates triggered, and `total` / `available` / `normalized`. Bands are **absolute** per-signal thresholds declared in each recipe. The skill scores exactly one project and is unaware of any caller, cohort, or cross-project comparison. Triggers on "evaluate this project", "score this repo against the rubric", "run the evaluator on <path>".
3
+ description: "Apply a production-readiness + product-quality rubric to a single software project. Takes a repo + output dir; writes a per-project workspace (README, `scorecard.yaml`, flat `raw/`) scoring 8 sub-criteria (4 Code + 4 Product) to /100 with evidence and gates. Scores one project, no cohort."
4
4
  ---
5
5
 
6
6
  # Evaluator
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: interview-eval
3
- description: Evaluate how well a person steered a Claude Code session — the human's prompting, decomposition, verification, debugging, course-correction, and engineering judgment — from one or more session transcripts (.jsonl). Built for interview/hiring assessment of engineers using AI coding agents. Takes 1+ Claude Code session `.jsonl` files (or a directory of them) plus an output directory; writes a per-session `report.md` + `scorecard.yaml`, and (for multiple sessions) a `candidate-rollup.md`. Scores 9 weighted dimensions on a 0–5 band scale against absolute anchors in `rubric.md`, normalizes to /100, maps to a steering level (Exemplary / Strong / Competent / Developing / Weak), applies hard-cap gates for unsafe behavior, and anchors every score to quoted turns. It judges the HUMAN'S steering, not Claude's code. Triggers on "evaluate this Claude Code session", "score how the candidate steered Claude", "judge these session transcripts", "how good is this person's prompting", "assess AI-pairing skill from a session log", or a `.jsonl` transcript handed over for review.
3
+ description: "Score how a human steered a Claude Code session — prompting, decomposition, verification, debugging, judgment — from `.jsonl` transcripts. For interview/hiring assessment of engineers using AI coding agents; writes a per-session report + scorecard plus a rollup. Judges the human, not the code."
4
4
  ---
5
5
 
6
6
  # interview-eval
@@ -10,3 +10,9 @@ yarn.lock
10
10
 
11
11
  # Harness-managed agent/skill definitions (installed under .claude/)
12
12
  .claude
13
+
14
+ # Source catalogs — authored markdown; prettier collapses template/example blocks
15
+ skills
16
+ rules
17
+ agents
18
+ harness
@@ -1,12 +1,12 @@
1
1
  # Knowledge vault — router
2
2
 
3
- This repo is a flat Obsidian vault you read on the reader's behalf. What it's about, what a note is, how links resolve, and who may write what live in one place: [`meta/contract.md`](meta/contract.md) — read it before writing anything. You are the **router**: you establish what brings the user, then follow the **ask** path (read the vault and answer) or the **contribute** path (help them add to it).
3
+ This repo is a flat Obsidian vault, read on the reader's behalf. What it's about, what a note is, how links resolve, and who may write what live in one place: [`meta/contract.md`](meta/contract.md) — read it before writing anything. This file is the **router**: establish what brings the user, then follow the **ask** path (read the vault and answer) or the **contribute** path (help them add to it).
4
4
 
5
5
  ---
6
6
 
7
7
  ## Step 0 — first run
8
8
 
9
- If `meta/contract.md` is missing, the vault isn't initialized. Conduct the **identity interview** yourself with `AskUserQuestion` (the agents can't ask questions):
9
+ If `meta/contract.md` is missing, the vault isn't initialized. Conduct the **identity interview** in the main session with `AskUserQuestion` (the agents can't ask questions):
10
10
 
11
11
  1. What is this vault called, and what is it about? (one sentence)
12
12
  2. Who reads it? Up to four reader types — for each: a short name, what they come for, and a default answer depth (crisp / working / deep).
@@ -20,8 +20,8 @@ Then dispatch the **kb-init** agent with the answers verbatim, and continue once
20
20
 
21
21
  Establish two things from the **first message** when it already says them; interview only for what's missing:
22
22
 
23
- - **Path.** A question → *ask*. Something to add ("here are my notes from…", "we decided X") → *contribute*. A blank arrival ("hi", just looking around) → ask both questions with `AskUserQuestion`: what brings you (ask / contribute), and which reader type from `meta/genres/` fits.
24
- - **Genre** is a soft prior on the reader, never a gate: consult the matching `meta/genres/` template when you know it, use plain working depth when you don't, and ask at most once — only when the depth of the answer genuinely turns on it.
23
+ - **Path.** A question → *ask*. Something to add ("here are my notes from…", "we decided X") → *contribute*. A blank arrival ("hi", just looking around) → ask both questions with `AskUserQuestion`: what brings them (ask / contribute), and which reader type from `meta/genres/` fits.
24
+ - **Genre** is a soft prior on the reader, never a gate: consult the matching `meta/genres/` template when the genre is known, use plain working depth when it isn't, and ask at most once — only when the depth of the answer genuinely turns on it.
25
25
 
26
26
  Carry both through the session; don't re-interview on follow-ups.
27
27
 
@@ -29,34 +29,34 @@ Carry both through the session; don't re-interview on follow-ups.
29
29
 
30
30
  ## The ask path — read-only
31
31
 
32
- Your only write on this path is the session log. Never edit a note.
32
+ The only write on this path is the session log. **Never edit a note.**
33
33
 
34
34
  1. **Enter** via [`meta/index.md`](meta/index.md) — the lane matching the question's intent — and the genre template's "Start from" pointers.
35
35
  2. **Search before declaring anything missing.** Grep the whole vault for the question's terms. Found by search but not reachable from the lanes → that's a **navigation gap** (the knowledge exists; the paths don't) — say so in the log. Truly absent → a **content gap**.
36
- 3. **Traverse** the `[[wikilinks]]` both ways — up toward summaries, down into detail. Lead with `canonical` notes; `canonical: false` is background. A `visibility: hidden` note may inform you only with explicit disclosure — never present it as the vault's position to an external-facing reader.
36
+ 3. **Traverse** the `[[wikilinks]]` both ways — up toward summaries, down into detail. Lead with `canonical` notes; `canonical: false` is background. A `visibility: hidden` note may inform an answer only with explicit disclosure — never present it as the vault's position to an external-facing reader.
37
37
  4. **Synthesize** at the genre's default depth, then follow the asker — deeper when they reach, compressed when they want the headline. Depth shapes the answer, never which notes exist.
38
38
  5. **Cite** the notes used. Before citing, check `meta/proposals/` for `status: open` items flagging those notes (stale, superseded, collision) — disclose any flag.
39
- 6. **Log the session** to `meta/sessions/` per its README — honestly, including whether you could answer. Only a search-verified miss is logged as a gap.
39
+ 6. **Log the session** to `meta/sessions/` per its README — honestly, including whether the vault could answer. Only a search-verified miss is logged as a gap.
40
40
 
41
- If the vault can't answer, say so plainly and log it. Never invent an answer the notes don't support.
41
+ If the vault can't answer, say so plainly and log it. **Never invent an answer the notes don't support.**
42
42
 
43
43
  **"Where is the knowledge gap?"** is a deliberate ask for the coverage goal, not a side effect: answer instantly from [`meta/gaps.md`](meta/gaps.md); if the ledger is stale against the vault (notes or sessions committed since it last changed) or the user wants a live sweep, dispatch **kb-audit** scoped to coverage and relay the refreshed ledger.
44
44
 
45
45
  ## The contribute path — the human steers
46
46
 
47
- The user is adding knowledge. You draft and place; they decide. Every write is theirs, and every write is a git commit.
47
+ The user is adding knowledge. Drafting and placement happen here; the human decides. Every write is theirs, and every write is a git commit.
48
48
 
49
49
  1. **Orient** with `meta/contract.md` (the note model, where things belong) and the target folder's `Readme.md`. For "what does the vault want next?", read `meta/gaps.md` and any unprocessed session logs.
50
50
  2. **Check for a rival before placing.** Search for an existing note on the topic. One exists → the human picks: extend it, supersede it (demote the old to `canonical: false` **in the same commit**), or link the new note as background.
51
- 3. **Draft per the contract** — one idea per note, light frontmatter, linked to its neighbours. Links form as you write.
51
+ 3. **Draft per the contract** — one idea per note, light frontmatter, linked to its neighbours. Links form during drafting.
52
52
 
53
53
  ---
54
54
 
55
55
  ## Upkeep — deliberate, never a side effect
56
56
 
57
57
  - **kb-audit** (six goals: coverage, descriptions, freshness, graph, entrances, shape) audits and writes a **proposal** to `meta/proposals/` plus the gap ledger — never canon. Run it when asked, whole or scoped.
58
- - **kb-apply** executes exactly one human-reviewed proposal — the only agent that writes canon. Never run it unprompted.
59
- - The derived graph `meta/_derived/graph.json` is regenerated by `node .claude/scripts/kb-export.mjs` — never hand-edited, by you or anyone.
58
+ - **kb-apply** executes exactly one human-reviewed proposal — the only agent that writes canon. **Never run it unprompted.**
59
+ - The derived graph `meta/_derived/graph.json` is regenerated by `node .claude/scripts/kb-export.mjs` — never hand-edited, by anyone.
60
60
 
61
61
  Everything is git-checked-in: any write is reviewable and reversible. When anything here seems to conflict with `meta/contract.md`, the contract wins.
62
62
 
@@ -7,5 +7,5 @@
7
7
  ".prettierrc.json",
8
8
  ".vscode/settings.json"
9
9
  ],
10
- "digest": "2fa1ac5b576c"
10
+ "digest": "4d6027a2ef49"
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nurix/etna",
3
- "version": "0.19.20",
3
+ "version": "0.19.22",
4
4
  "description": "Bootstrap a project with a Nurix harness — copies the harness's CLAUDE.md, skills, agents, rules, and hooks directly into the project from a bundled payload (no marketplace fetch, no network).",
5
5
  "type": "module",
6
6
  "bin": {