@nurix/etna 0.14.0 → 0.15.2

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 (43) hide show
  1. package/README.md +28 -7
  2. package/bin/etna.js +58 -1
  3. package/data/harnesses/code/CLAUDE.md +11 -16
  4. package/data/harnesses/code/agents/brainstorm.md +13 -20
  5. package/data/harnesses/code/agents/change-review.md +5 -5
  6. package/data/harnesses/code/agents/harness-manager.md +49 -9
  7. package/data/harnesses/code/agents/maintenance.md +42 -5
  8. package/data/harnesses/code/agents/spec-mode.md +1 -1
  9. package/data/harnesses/code/harness.json +6 -0
  10. package/data/harnesses/code/hooks/hooks.json +41 -0
  11. package/data/harnesses/code/hooks/lib/redact.js +37 -0
  12. package/data/harnesses/code/hooks/post-commit.js +136 -0
  13. package/data/harnesses/code/hooks/post-tool-failure.js +136 -0
  14. package/data/harnesses/code/hooks/session-stop.js +207 -0
  15. package/data/harnesses/code/skills/boundary/SKILL.md +21 -3
  16. package/data/harnesses/code/skills/boundary/references/boundary-taxonomy.md +229 -161
  17. package/data/harnesses/code/skills/brainstorm/README.md +76 -227
  18. package/data/harnesses/code/skills/brainstorm/SKILL.md +78 -566
  19. package/data/harnesses/code/skills/brainstorm/harvest.md +26 -0
  20. package/data/harnesses/code/skills/brainstorm/templates/build.md +37 -0
  21. package/data/harnesses/code/skills/brainstorm/templates/decisions.md +12 -25
  22. package/data/harnesses/code/skills/brainstorm/templates/domain-model.md +25 -0
  23. package/data/harnesses/code/skills/brainstorm/templates/non-goals.md +2 -2
  24. package/data/harnesses/code/skills/brainstorm/templates/questions.md +18 -67
  25. package/data/harnesses/code/skills/brainstorm/templates/state.md +5 -5
  26. package/data/harnesses/code/skills/brainstorm/templates/tech.md +23 -0
  27. package/data/harnesses/code/skills/brainstorm/templates/thesis.md +21 -0
  28. package/data/harnesses/code/skills/distiller/SKILL.md +218 -0
  29. package/data/harnesses/code/skills/distiller/references/docs-mode.md +526 -0
  30. package/data/harnesses/code/skills/distiller/references/method.md +166 -0
  31. package/data/harnesses/code/skills/documentation/references/templates.md +78 -5
  32. package/data/harnesses/kb-agi/CLAUDE.md +1 -1
  33. package/data/harnesses/kb-agi/agents/kb-agi-init.md +2 -2
  34. package/data/harnesses/kb-agi/agents/kb-catch-stale.md +1 -1
  35. package/data/harnesses/kb-agi/agents/kb-find-gaps.md +2 -2
  36. package/data/harnesses/kb-agi/agents/kb-fix-links.md +1 -1
  37. package/data/harnesses/kb-agi/agents/kb-refresh-frontdoor.md +1 -1
  38. package/data/harnesses/kb-agi/agents/kb-refresh-summaries.md +1 -1
  39. package/data/harnesses/kb-agi/agents/kb-sync-metadata.md +1 -1
  40. package/data/harnesses/kb-agi/harness.json +6 -0
  41. package/package.json +1 -1
  42. package/data/harnesses/code/skills/brainstorm/greenfield.md +0 -99
  43. package/data/harnesses/code/skills/brainstorm/templates/inventory.md +0 -44
@@ -0,0 +1,166 @@
1
+ # Distillation Method — the algorithm spec
2
+
3
+ The shared knowledge root for the `distiller` skill. Every mode reads this file.
4
+ It carries the four mechanisms the distiller runs, the fact-card format, and the
5
+ high-water-mark protocol.
6
+
7
+ **These methods are stolen, not invented.** Each is sourced to its primary paper
8
+ with an arXiv id — provenance matters here of all places. Embed them faithfully;
9
+ do not paraphrase the retention signal away.
10
+
11
+ ---
12
+
13
+ ## The four methods
14
+
15
+ ### 1. Surprisal filter — *what to keep* (Nemori, arXiv:2508.03341)
16
+
17
+ Present the LLM with **(a)** a summary of the *current* fact-set, and **(b)** the
18
+ new undigested ledger entries. Keep only what is **surprising** relative to
19
+ (a) — what the existing knowledge would **not** have predicted. Predictable ⇒
20
+ dropped.
21
+
22
+ No importance scores. No emotional tags. No templates. **Prediction error is the
23
+ only retention signal.**
24
+
25
+ > **First run, empty fact-set.** With nothing to predict against, "predictable" =
26
+ > mechanical routine — e.g. a bare commit echo, or a transient exit-1 with no
27
+ > lesson attached. Keep decisions, reversals, discovered constraints, and
28
+ > failures with a cause worth remembering. Drop the rote.
29
+
30
+ **Surprisal sources are not only ledger entries.** The ledger is the *default*
31
+ stream, but the retention signal is prediction error wherever it lives. On a
32
+ commit-less or thin-ledger project — where the ledger holds only droppable
33
+ mechanical entries — the decision record carries the surprise instead:
34
+ `docs/architecture/adr/**` (each accepted ADR is, by construction, a decision the
35
+ prior knowledge would not have predicted) and `docs/memory/brainstorm.md`
36
+ (reversals, owner pronouncements, discovered constraints). Treat these as
37
+ input (b) alongside any ledger entries; the filter (keep the surprising, drop the
38
+ predictable) is unchanged. Provenance then points at the ADR file or brainstorm
39
+ section rather than a ledger `#HH:MM`.
40
+
41
+ (Independently corroborated by Honcho's "Dream" — same prediction-error
42
+ retention, arrived at separately.)
43
+
44
+ ### 2. Fact-card representation — *non-lossy EDUs* (EMem, arXiv:2511.17208)
45
+
46
+ Each survivor becomes **ONE atomic, self-contained statement** — an Elementary
47
+ Discourse Unit (EDU). Entity names normalized; the minimal context needed to
48
+ stand alone baked into the sentence itself. Each card carries **provenance**: the
49
+ ledger entries and/or commits it derives from.
50
+
51
+ This is **decomposition, not summarization.** No information is destroyed; one
52
+ survivor may decompose into several cards; everything stays auditable back to the
53
+ raw ledger.
54
+
55
+ ### 3. Reconciliation — *consistency* (Mem0, arXiv:2504.19413)
56
+
57
+ For each candidate card, retrieve the existing facts' **semantic neighbors**,
58
+ then decide one of:
59
+
60
+ - **ADD** — genuinely new fact; write a new card.
61
+ - **UPDATE** — refines/extends a known fact; edit the existing card in place,
62
+ extend its provenance.
63
+ - **SUPERSEDE** — contradicts/replaces a known fact; invalidate the old, write
64
+ the new (see §4).
65
+ - **NOOP** — already known; write nothing.
66
+
67
+ Neighbor retrieval: `qmd query --format json -c {repo}-facts "<statement>"`
68
+ (scope with `-c`, one collection) — **only when the `{repo}-facts` collection
69
+ exists** (`qmd collection list` shows it). The gate is the collection, not the
70
+ binary: a present qmd whose facts collection has never been built (first run)
71
+ returns nothing useful. **Fallback when the collection is missing** — qmd absent,
72
+ *or* present but `{repo}-facts` not yet built: filename / grep similarity over
73
+ `docs/memory/facts/*.md` (slug overlap + entity-name grep), and note in the
74
+ report that reconciliation ran without semantic retrieval.
75
+
76
+ ### 4. Bi-temporal supersession — *never delete* (Zep/Graphiti, arXiv:2501.13956)
77
+
78
+ Superseding **never deletes.** On the **old** card, set `invalid_from:` (the date
79
+ it stopped being true) and `superseded_by:` (the new fact's id), and **leave the
80
+ file in place.** Write the **new** card with today's `valid_from:`. The old fact
81
+ stays queryable as history; nothing vanishes.
82
+
83
+ This is the *valid-time* axis of a bi-temporal model — a fact is true within
84
+ `[valid_from, invalid_from)`; transaction time is the git history of the file.
85
+
86
+ #### Self-contained reversal — *both cards in one pass*
87
+
88
+ `SUPERSEDE` (§3) assumes the old fact already lives as a card. But a single input
89
+ can state a reversal whole — "X was decided, then reversed to Y" in one sentence
90
+ (e.g. brainstorm.md: *single-tenant → multi-tenant, same session*; or an ADR
91
+ whose **Options Considered** (the `documentation` §10 ADR template's
92
+ rejected-alternatives section) names a path "proposed and reversed within the
93
+ brainstorm"). Here there is no pre-existing X card to invalidate — both X and Y
94
+ arrive together.
95
+
96
+ Emit **two cards in one pass**:
97
+
98
+ 1. A **born-invalid historical card for X** — the superseded decision. Write it
99
+ with `valid_from:` (when X was decided, if known, else the input date),
100
+ `invalid_from:` (when it was reversed — the same date, for an in-session
101
+ reversal), and `superseded_by:` pointing at Y's fact-id. It is created already
102
+ carrying its own death so the reversal stays auditable.
103
+ 2. A **live card for Y** — the decision that won. `valid_from:` the reversal date,
104
+ `invalid_from: null`, `superseded_by: null`.
105
+
106
+ Both share the input's provenance (the one ADR / brainstorm line). This is the
107
+ ADD-side mirror of SUPERSEDE: SUPERSEDE invalidates a card that already exists;
108
+ the self-contained reversal *manufactures* the invalidated card so the
109
+ abandoned-X history is recorded rather than silently dropped.
110
+
111
+ ---
112
+
113
+ ## Fact-card format (`docs/memory/facts/{kebab-slug}.md`)
114
+
115
+ ```markdown
116
+ ---
117
+ id: fact-{slug}
118
+ valid_from: YYYY-MM-DD
119
+ invalid_from: null # set on supersession — never delete the file
120
+ superseded_by: null # fact-id
121
+ entities: [qmd, anchors, maintenance]
122
+ provenance: [ledger/YYYY-MM-DD--{actor}.md#HH:MM, commit abc123]
123
+ ---
124
+ One atomic, self-contained statement of the fact, entities normalized.
125
+ ```
126
+
127
+ - `id` — `fact-{slug}`, the slug matching the filename.
128
+ - `valid_from` — the date the fact became true (the entry/commit date, or the
129
+ distill date if no better signal).
130
+ - `invalid_from` — `null` until superseded; then the date it stopped being true.
131
+ **Never delete the file** to express invalidity — set this field.
132
+ - `superseded_by` — `null`, or the `fact-id` of the card that replaced it.
133
+ - `entities` — normalized names the fact concerns (used by the grep fallback and
134
+ by retrieval).
135
+ - `provenance` — the ledger entries (`ledger/YYYY-MM-DD--{actor}.md#HH:MM`) and
136
+ commits this card decomposes from. Must resolve back to raw.
137
+ - The body — exactly one atomic, self-contained statement. Entities normalized,
138
+ context baked in, so the card stands alone.
139
+
140
+ ---
141
+
142
+ ## High-water-mark protocol (`docs/memory/facts/.digest-state.md`)
143
+
144
+ The mark is what makes the distiller idempotent. Frontmatter records, **per
145
+ actor**, the last-digested ledger file and entry timestamp.
146
+
147
+ ```markdown
148
+ ---
149
+ # per-actor high-water mark — last ledger entry digested into facts
150
+ last_digested:
151
+ joyjeet-sarkar: { file: ledger/2026-06-04--joyjeet-sarkar.md, entry: "00:31" }
152
+ claude: { file: ledger/2026-06-08--claude.md, entry: "14:32" }
153
+ ---
154
+ High-water mark for the facts distiller. Read first, advanced last.
155
+ ```
156
+
157
+ **Protocol:**
158
+
159
+ 1. **Read it first.** Absent ⇒ start of history — digest every ledger entry.
160
+ 2. Process only entries **newer** than each actor's mark.
161
+ 3. **Advance it last** — only after every card is written. Last, so a crash
162
+ mid-run causes a re-digest (safe — reconciliation NOOPs the already-written
163
+ cards) rather than a silent skip of un-digested entries.
164
+
165
+ A second run immediately after a successful one finds nothing past the mark and
166
+ is a clean NOOP.
@@ -77,7 +77,7 @@ Use for: defining which folder owns which topic and how docs are maintained.
77
77
 
78
78
  ```
79
79
  ---
80
- harness-version: 10
80
+ harness-version: 12
81
81
  ---
82
82
 
83
83
  # Documentation Structure
@@ -124,7 +124,7 @@ Plan (Status: Draft) → Implementation → Feature Doc or Architecture Update
124
124
  <!-- Updated by maintenance agent -->
125
125
  | Date | Review Summary |
126
126
  | ---- | -------------- |
127
- | {today} | Initial baseline — v9 structure established |
127
+ | {today} | Initial baseline — v{harness-version} structure established |
128
128
  ```
129
129
 
130
130
  ---
@@ -142,12 +142,15 @@ touches:
142
142
  - src/shared/utils/feature-helper.js
143
143
  depends_on:
144
144
  - docs/architecture/system-design.md
145
+ anchors:
146
+ - "qmd query: feature-name persistence shape"
145
147
  ---
146
148
  ```
147
149
 
148
150
  - `owns`: Glob patterns for files this feature doc is the canonical reference for
149
151
  - `touches`: Files this feature interacts with but doesn't own
150
152
  - `depends_on`: Other docs that must be read for full context
153
+ - `anchors` (optional): A list of qmd queries (or `#docid`s) that re-resolve to the code/facts this doc abstracts as they move; anchors are retrieval context plus a drift tripwire, never a contract — an anchor that returns nothing IS the drift signal, nothing auto-rewrites from an anchor result, and the doc's prose stays the human-owned abstraction. They detect **doc-area drift** (the subject moving or vanishing from the corpus), not a pure code rename — the query also matches the doc's own prose, so a rename that leaves the text unchanged won't shift the result; code-symbol drift is the maintenance named-referent check's job, and anchors complement it rather than replace it. Resolved via `qmd query --format json -c <collection>` against this repo's collections; absent qmd ⇒ anchors are inert (no error). Never required on any doc. The feature and boundary templates ship the exemplar, but `anchors:` may appear on any living doc the maintenance anchor-drift check globs — `docs/features/`, `docs/boundaries/`, `docs/architecture/`, and `docs/operations/` — so the convention and the check stay one mental model.
151
154
 
152
155
  ---
153
156
 
@@ -240,8 +243,17 @@ description: Shared knowledge accumulated across agent sessions. All agents shou
240
243
  ## Documentation Baseline
241
244
 
242
245
  - **Baselined:** {today}
243
- - **Structure:** v9 (architecture, features, operations, history, memory; + boundaries/, modules/, tests/ when present)
244
- - **Spec version:** v9
246
+ - **Structure:** v{harness-version} (architecture, features, operations, history, memory; + boundaries/, modules/, tests/ when present)
247
+ - **Spec version:** v{harness-version}
248
+ <!-- v{harness-version} resolves to the installed design epoch — read it from `.claude/harness.json` (`epoch`) / `docs/structure.md` frontmatter (`harness-version`); never hardcode a literal version here. -->
249
+
250
+ ## Knowledge Tiers
251
+
252
+ Memory is a gradient — volume falls, signal rises, one hop down each tier. Tiers describe themselves here even before they fill:
253
+
254
+ - **Ledger** (`docs/memory/ledger/`) — raw, high-volume dump tier. Hooks append every decision/action/observation/failure as it happens (one day-file per actor). The firehose, rarely read directly.
255
+ - **Fact-cards** (`docs/memory/facts/`) — distilled, provenance-linked atomic facts, written by the distiller (`facts` mode) from undigested ledger entries. `.digest-state.md` holds the high-water mark.
256
+ - **This index** — the curated read tier: the learnings list below, distilled from the colder tiers and hand-appended.
245
257
 
246
258
  ## Learnings
247
259
 
@@ -272,6 +284,8 @@ Append entries below, oldest at bottom. Format:
272
284
  Memory file initialized during documentation baseline.
273
285
  ```
274
286
 
287
+ > The per-day event **ledger** (`docs/memory/ledger/`) is *not* a baseline scaffold — hooks create its day-files mechanically on first event. See **§12 Memory ledger entry** for its format.
288
+
275
289
  ---
276
290
 
277
291
  ## 5. Boundary File (docs/boundaries/{boundary}.md)
@@ -321,6 +335,11 @@ When mapping a boundary (the `boundary` skill's `generate`/`create` job — this
321
335
  One file per boundary in `docs/boundaries/`. The `boundary` skill emits typed files using its boundary taxonomy; this is the generic fallback shape.
322
336
 
323
337
  ```markdown
338
+ ---
339
+ anchors: # optional — see §3 frontmatter reference
340
+ - "qmd query: store slice rehydration fallback"
341
+ ---
342
+
324
343
  # {Boundary Name}
325
344
 
326
345
  [BOUNDARY: {type} · {severity}] <!-- type from the Application Boundary Scale; severity CRITICAL | HIGH | MED | LOW -->
@@ -329,7 +348,8 @@ One file per boundary in `docs/boundaries/`. The `boundary` skill emits typed fi
329
348
 
330
349
  ## Shape
331
350
  <!-- `transcribe`: a synthesized contract with no single code home (composed store tree, API envelope, the IA entity model, tenancy) — written inline, canonical here.
332
- `point`: a self-locating shape (DB schema, route table) — a `file:line` pointer + invariants. Never copy a self-locating shape; it rots on the next change. -->
351
+ `point`: a self-locating shape (DB schema, route table) — a `file:line` pointer + invariants. Never copy a self-locating shape; it rots on the next change.
352
+ greenfield/pre-code `point` (contract decided, no code yet — e.g. boundary generate after a brainstorm): there's no file:line to point at, so instead (a) record the decided conventions inline here, (b) add a `planned <path>` line naming where the canonical source will land (e.g. `planned packages/api/src/db/schema.ts`), and (c) mark this row `point*` in the README index. Converts to (or gains) a real file:line pointer when the module lands. README index footnote: "* point-mode boundary whose pointer lands at implementation". -->
333
353
 
334
354
  ## Invariants
335
355
  <!-- The rules that must hold across the boundary. -->
@@ -357,6 +377,8 @@ touches:
357
377
  - src/shared/state/feature.js
358
378
  depends_on:
359
379
  - docs/features/related-feature.md
380
+ anchors: # optional — see §3 frontmatter reference
381
+ - "qmd query: wire envelope invariants"
360
382
  ---
361
383
  ```
362
384
 
@@ -874,3 +896,54 @@ src/
874
896
  The baseline audit **does** scaffold the project root README when missing. The risk this template guards against — template-shaped placeholders that look abandoned — is mitigated by the writing rules above: fill every section with concrete details from the repo (real package manager from the lockfile, real scripts, real layout, real status). Skip sections that genuinely don't apply rather than leaving stubs.
875
897
 
876
898
  **Never overwrite an existing root README** during a baseline. If one is present — even sparse or outdated — leave it untouched. Treat updates to a pre-existing root README as a separate, explicit request.
899
+
900
+ ---
901
+
902
+ ## 12. Memory ledger entry (docs/memory/ledger/YYYY-MM-DD--{actor}.md)
903
+
904
+ Use for: the raw, high-volume **dump tier** of the knowledge gradient — every decision, action, observation, and failure, appended as it happens. Hooks write it mechanically; humans rarely read it directly. It is the raw input to distillation: the durable `docs/memory/` files (index, main, agent) are the curated read tier; this is the firehose they're distilled from.
905
+
906
+ ### File grain
907
+
908
+ One file per day **per actor**: `docs/memory/ledger/YYYY-MM-DD--{actor}.md`. `actor` is `git config user.name` lowercased and kebab-slugged; fall back to `$USER`, then `agent`. Because two actors working the same day write to different files, the ledger is **append-only without merge conflicts** — no shared file to contend over, no lock, no last-writer-wins.
909
+
910
+ ### Day-file header
911
+
912
+ Written once, on the first event of a given day-file:
913
+
914
+ ```
915
+ # Ledger — YYYY-MM-DD — {actor}
916
+ Append-only event ledger. Raw input to distillation — see docs/memory/.
917
+ ```
918
+
919
+ ### Entry shape
920
+
921
+ One block per event, 1–5 lines. Never the full tool I/O — one line of `what`, optionally one of `why`. `why` and `refs` are omitted when empty.
922
+
923
+ ```
924
+ ## HH:MM · {actor} · {repo}@{branch}
925
+ - type: decision | action | observation | failure
926
+ - what: <one line>
927
+ - why: <one line — optional>
928
+ - refs: <commit hashes / file paths / session id — optional>
929
+ ```
930
+
931
+ ### Examples
932
+
933
+ ```
934
+ ## 14:02 · jane-doe · etna@dev
935
+ - type: action
936
+ - what: task "bump structure scaffold to harness v11", 6 turns, 1 file edited
937
+ - refs: session a1b2c3d4 · 1 files
938
+
939
+ ## 14:09 · jane-doe · etna@dev
940
+ - type: failure
941
+ - what: deploy script rejected auth header Authorization: [redacted:api-key]
942
+ - why: stale key in .env.local — rotated, see docs/operations/setup.md
943
+ ```
944
+
945
+ ### Rules
946
+
947
+ - **Append, never edit.** The ledger records what was true when written; corrections go in a later entry, not by rewriting an old one.
948
+ - **Secrets are redacted on write.** The privacy filter replaces secret shapes with `[redacted:{kind}]` (e.g. `[redacted:api-key]`, `[redacted:bearer]`, `[redacted:pem]`) before any line is appended — never paste a raw token in by hand either.
949
+ - **Don't curate here.** Patterns worth keeping get promoted to `docs/memory/main.md` (or an agent file) during distillation; the ledger stays a raw, lossy-by-volume dump.
@@ -13,7 +13,7 @@ keywords:
13
13
  plugin: kb-agi
14
14
  ---
15
15
 
16
- # nuStack Knowledge Hub — router
16
+ # NuStack Knowledge Hub — router
17
17
 
18
18
  This repo is a flat Obsidian vault that you read on the user's behalf. It's the bridge from the front (positioning, claims) to the back (product and service specs); detailed execution lives downstream in the service repos.
19
19
 
@@ -151,7 +151,7 @@ Upkeep is run by the kb-agi agents (invoked by name); there is no `meta/goals/`
151
151
  ````markdown
152
152
  # genre — Sales
153
153
 
154
- The reader is positioning nuStack to someone else: a prospect, a partner, a teammate who needs the pitch. They want the claim and the proof behind it, not the implementation.
154
+ The reader is positioning NuStack to someone else: a prospect, a partner, a teammate who needs the pitch. They want the claim and the proof behind it, not the implementation.
155
155
 
156
156
  **Default depth.** Start crisp. Lead with the answer in one or two sentences — what we can do, what makes it different — then offer the supporting detail rather than front-loading it. Go deeper only when the question reaches for it ("how exactly…", "what's underneath…").
157
157
 
@@ -213,7 +213,7 @@ This is a living index. It is hand-maintained today and kept fresh by the `kb-re
213
213
  ---
214
214
 
215
215
  ## "I want to understand the product"
216
- _What nuStack is, what it can do, the claims and their proof._
216
+ _What NuStack is, what it can do, the claims and their proof._
217
217
 
218
218
  - _populated on migration_
219
219
 
@@ -6,7 +6,7 @@ model: inherit
6
6
  plugins: [kb-agi]
7
7
  ---
8
8
 
9
- You are the **kb-catch-stale** goal-agent for the nuStack knowledge hub. One job: surface notes that have drifted out of date.
9
+ You are the **kb-catch-stale** goal-agent for the NuStack knowledge hub. One job: surface notes that have drifted out of date.
10
10
 
11
11
  **Read first:** `meta/guidance.md` (the note model, `maturity` + `canonical` hints) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
12
12
 
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: kb-find-gaps
3
- description: Audits the nuStack vault for missing notes — diffs each folder's metadata.md and the session gap-logs against the note graph to find coverage holes. Use when asked to find gaps, check coverage, or "what's missing". Proposes a ranked gap list by default; writes notes ONLY when the invocation explicitly asks it to.
3
+ description: Audits the NuStack vault for missing notes — diffs each folder's metadata.md and the session gap-logs against the note graph to find coverage holes. Use when asked to find gaps, check coverage, or "what's missing". Proposes a ranked gap list by default; writes notes ONLY when the invocation explicitly asks it to.
4
4
  tools: Read, Grep, Glob, Bash
5
5
  model: inherit
6
6
  plugins: [kb-agi]
7
7
  ---
8
8
 
9
- You are the **kb-find-gaps** goal-agent for the nuStack knowledge hub. You have exactly one job: find what the vault should hold but doesn't, and surface it.
9
+ You are the **kb-find-gaps** goal-agent for the NuStack knowledge hub. You have exactly one job: find what the vault should hold but doesn't, and surface it.
10
10
 
11
11
  ## First, read the contract
12
12
 
@@ -6,7 +6,7 @@ model: inherit
6
6
  plugins: [kb-agi]
7
7
  ---
8
8
 
9
- You are the **kb-fix-links** goal-agent for the nuStack knowledge hub. One job: keep the note graph sound — no dead links, no orphans.
9
+ You are the **kb-fix-links** goal-agent for the NuStack knowledge hub. One job: keep the note graph sound — no dead links, no orphans.
10
10
 
11
11
  **Read first:** `meta/guidance.md` (the note model) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
12
12
 
@@ -6,7 +6,7 @@ model: inherit
6
6
  plugins: [kb-agi]
7
7
  ---
8
8
 
9
- You are the **kb-refresh-frontdoor** goal-agent for the nuStack knowledge hub. One job: keep the entry points pointing at the right notes.
9
+ You are the **kb-refresh-frontdoor** goal-agent for the NuStack knowledge hub. One job: keep the entry points pointing at the right notes.
10
10
 
11
11
  **Read first:** `meta/guidance.md` (the note model, `canonical` hint) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
12
12
 
@@ -6,7 +6,7 @@ model: inherit
6
6
  plugins: [kb-agi]
7
7
  ---
8
8
 
9
- You are the **kb-refresh-summaries** goal-agent for the nuStack knowledge hub. One job: keep summary notes current with the raw material beneath them.
9
+ You are the **kb-refresh-summaries** goal-agent for the NuStack knowledge hub. One job: keep summary notes current with the raw material beneath them.
10
10
 
11
11
  **Read first:** `meta/guidance.md` (the note model, the `maturity` ladder) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
12
12
 
@@ -6,7 +6,7 @@ model: inherit
6
6
  plugins: [kb-agi]
7
7
  ---
8
8
 
9
- You are the **kb-sync-metadata** goal-agent for the nuStack knowledge hub. One job: keep folder `metadata.md` files honest.
9
+ You are the **kb-sync-metadata** goal-agent for the NuStack knowledge hub. One job: keep folder `metadata.md` files honest.
10
10
 
11
11
  **Read first:** `meta/guidance.md` (the note model + the fixed `metadata.md` shape) — the contract that governs you. The procedure below is this agent's full, self-contained definition.
12
12
 
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "kb-agi",
3
+ "version": "0.10.0",
4
+ "epoch": null,
5
+ "digest": "8973cf3a762d"
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nurix/etna",
3
- "version": "0.14.0",
3
+ "version": "0.15.2",
4
4
  "description": "Bootstrap a project with a Nurix harness — installs a Claude Code plugin from the nurixlabs/skills marketplace and drops the harness's CLAUDE.md at the project root.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,99 +0,0 @@
1
- # Greenfield writing doctrine
2
-
3
- > **The reader has no past.** They've never seen an earlier version of the system, never heard of the alternative you considered, never knew about the repo you were going to fold in. Write for them.
4
-
5
- For projects with nothing built yet — no production deploys, no users, no legacy code — architecture docs describe the system as it **will be**, in present tense. The temptation to narrate the design journey ("we considered X, chose Y, dropped Z") produces documents full of phantoms — references to things the reader has no way to imagine.
6
-
7
- These rules apply equally to the first draft and to subsequent edits. After every design decision, the architecture doc should look as though the chosen option was always the plan.
8
-
9
- ---
10
-
11
- ## The rule
12
-
13
- Describe what the system **is** (or will be — same thing in greenfield). Never describe what it isn't, used to be, replaces, supersedes, or is migrating from.
14
-
15
- There is no past tense in a doc for software that doesn't exist yet.
16
-
17
- ---
18
-
19
- ## Banned patterns
20
-
21
- | Don't write | Why it's wrong | Write instead |
22
- |---|---|---|
23
- | "X replaces Y" / "X supersedes Y" | Reader doesn't know Y. | "X is the [role]." |
24
- | "Previously planned" / "originally proposed" / "we used to" | There is no previous. | Describe the current plan. |
25
- | "What was dropped" / "What we ruled out" sections | Only useful when readers carry a stale model. | Move reasoning to `decisions.md` if load-bearing; otherwise delete. |
26
- | `~~strike-through~~` text | Tracks edits for live readers; pollutes fresh docs. | Delete the struck text. Keep the surviving prose. |
27
- | "ex-Foo", "from ex-Bar" annotations on packages | Repo-fold bookkeeping. | Just name the package. |
28
- | "Folded into monorepo" / `import-legacy.sh` / migration scripts | Migration mechanic, not architecture. | Describe the monorepo as the steady state. |
29
- | "v1 vs v2" / "future migration target" | Implies one is becoming the other. | Describe v1. Phase-2 ideas can be a "future scope" subsection without "migration" framing. |
30
- | "(existing — `~/dev/foo`)" / "no build needed" markers | Differentiates from non-existing; in greenfield everything is to-build. | Just list the service. |
31
- | "There is no foo_table" / "we don't have a foo service" | Reader didn't expect one. | Don't mention it. |
32
- | "Per Decision-N resolution" inline citations on every paragraph | Architecture doc isn't a decision log. | Plain prose. One cross-ref per section, only when the *why* is non-obvious. |
33
- | "Resolved (was: open question)" / "(retired)" markers | Edit-history bookkeeping. | Delete — the resolution **is** the doc now. |
34
- | "What this kills" / "Trade-off accepted" headings | Decision-capture format leaking into architecture. | Keep these in `decisions.md` only. |
35
- | "We no longer X" / "X is no longer needed" | Reader had no expectation that X existed. | Don't mention X. |
36
- | "Renamed from foo to bar" / "(formerly known as …)" | The rename doesn't matter — only the current name does. | Use the current name. |
37
-
38
- ---
39
-
40
- ## Smell-words grep
41
-
42
- `stop` runs this automatically. Manual invocation:
43
-
44
- ```sh
45
- grep -rEni \
46
- 'replaces|supersedes|superseded|previously|formerly|originally proposed|what was dropped|fully retired|~~|ex-[a-z-]+|folded in|import-legacy|migration target|migrate from|no longer|we used to|resolved per|renamed from|formerly known' \
47
- plan/
48
- ```
49
-
50
- In a clean greenfield architecture doc, this should return no hits in `01–NN` numbered docs.
51
-
52
- Hits **are** acceptable in:
53
- - `decisions.md` — scoped to a specific decision-capture entry.
54
- - `rejected.md` — scoped to a rejected alternative.
55
- - `references.md` — describing external prior art.
56
- - Commit messages and PR descriptions.
57
- - `./plan/sources/` — copies of input documents (not authored under these rules).
58
-
59
- ---
60
-
61
- ## Where the past DOES belong
62
-
63
- - `decisions.md` — alternatives + why the chosen option won, **only** when the reasoning isn't obvious from the architecture itself.
64
- - `rejected.md` — paths considered and rejected.
65
- - `references.md` — external prior art.
66
- - Commit messages, PR descriptions — what changed and why; lives in git, not docs.
67
-
68
- These are the only four places. Architecture docs (`01-foo.md`, `02-bar.md`, ...) are present-tense.
69
-
70
- ---
71
-
72
- ## What's still allowed (don't over-correct)
73
-
74
- - **Forward planning that names a phase** ("ships in M7 so the bus already knows about `lead.created` when CRM sync arrives") — describes a positive future, not a past.
75
- - **Constraint statements** ("we accept a 5-second tile lag for predictable server load") — current tradeoffs, stated as facts. Live in `decisions.md`, not architecture.
76
- - **Cross-refs** ("see `04 §4.3`") — pointers, not history.
77
- - **Negative assertions about external systems** ("the upstream service has no native fan-in") — describing a real third-party limitation is fine.
78
- - **Future-scope subsections** ("Phase 2 considerations") — labelled clearly, not framed as migrations.
79
-
80
- ---
81
-
82
- ## Before merging an architecture doc, ask
83
-
84
- 1. If a brand-new collaborator read this section cold, would they need to know about the alternative I'm comparing to? If no, delete the comparison.
85
- 2. Does the section read as present-tense description, or as a story of "we went from X to Y"? Rewrite the story form.
86
- 3. Are there strike-throughs? Delete them.
87
- 4. Does an open-questions list still contain resolved items? Move them to `decisions.md` and drop from the list.
88
- 5. Are there inline "(per Decision-X)" citations sprinkled through the prose? Strip — keep at most one cross-ref per section.
89
-
90
- ---
91
-
92
- ## Why this matters
93
-
94
- A greenfield doc that reads like a migration guide signals two things to a new reader:
95
-
96
- 1. **There is hidden context I don't have.** Every "previously" / "replaces" makes them wonder what they're missing.
97
- 2. **The author is still in the middle of deciding.** Strike-throughs and "(resolved)" markers feel provisional.
98
-
99
- Both undermine the doc's authority. A clean greenfield doc reads as an act of architecture, not an act of revision.
@@ -1,44 +0,0 @@
1
- # Inventory
2
-
3
- This file is the **authoritative list of components in scope** — services, repos, packages, databases, external integrations. It answers the question "what are we actually building?" and stops the team from inventing services that already exist or "folding in" things that should stay separate.
4
-
5
- The inventory is grouped by category (application monorepo, edge services, shared packages, managed externals, reference-only prior art). Each entry carries a **status**:
6
-
7
- - **build** — in scope, we're constructing this in this project.
8
- - **external** — managed elsewhere (third-party SaaS, another team's service). We integrate with it but don't own it.
9
- - **reference** — prior art we read or copy patterns from but do not deploy.
10
-
11
- Do **not** mark items as "retired", "deprecated", or "previously planned" — if it's not being built or used, omit it. (See the greenfield doctrine.) The inventory describes the steady state, not the history of how the steady state was arrived at.
12
-
13
- When scope changes (a service moves from "build" to "external", a non-goal flips to a build, a planned component gets dropped), update this file immediately and run a semantic sweep across plan docs.
14
-
15
- ---
16
-
17
- ## A. Application monorepo
18
-
19
- | Name | Status | Notes |
20
- |---|---|---|
21
- | (example: `apps/gateway`) | build | (one-line role) |
22
- | (example: `apps/web`) | build | (one-line role) |
23
-
24
- ## B. Edge services
25
-
26
- | Name | Status | Notes |
27
- |---|---|---|
28
-
29
- ## C. Shared packages
30
-
31
- | Name | Status | Notes |
32
- |---|---|---|
33
-
34
- ## D. Managed externals
35
-
36
- | Name | Status | Notes |
37
- |---|---|---|
38
- | (example: Temporal Cloud) | external | (one-line — what we use it for) |
39
-
40
- ## E. Reference / prior art
41
-
42
- | Name | Status | Notes |
43
- |---|---|---|
44
- | (example: `~/dev/vibe/foo-poc`) | reference | (what pattern we borrow from it) |