@nurix/etna 0.18.9 → 0.18.10
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.
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/CLAUDE.md +8 -9
- package/data/harnesses/code/agents/change-review.md +1 -1
- package/data/harnesses/code/agents/harness-manager.md +15 -12
- package/data/harnesses/code/agents/maintenance.md +12 -12
- package/data/harnesses/code/agents/spec-mode.md +3 -3
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/skills/distiller/references/docs-mode.md +7 -7
- package/data/harnesses/code/skills/documentation/SKILL.md +25 -31
- package/data/harnesses/code/skills/documentation/references/templates.md +58 -24
- package/package.json +1 -1
package/data/harness-index.json
CHANGED
|
@@ -44,12 +44,11 @@ On **Completion**: freeze the plan (`Status: Complete`) and flip the feature spe
|
|
|
44
44
|
|
|
45
45
|
Before modifying code in an unfamiliar area:
|
|
46
46
|
|
|
47
|
-
1.
|
|
48
|
-
2.
|
|
49
|
-
3. If
|
|
50
|
-
4. If
|
|
51
|
-
5.
|
|
52
|
-
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.
|
|
47
|
+
1. Read **[`docs/routing.md`](docs/routing.md)** — the single map of file-pattern/keyword → canonical doc + module. Match your path or topic to find the owning feature doc and its module; read that doc — and, if its row names a declared module, that module's `CLAUDE.md` + `pillars/` — before changes. (If `routing.md` doesn't exist yet, the repo isn't reconciled — see Bootstrap.)
|
|
48
|
+
2. 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.
|
|
49
|
+
3. If your change touches a cross-cutting contract area (entity model, db schema, wire envelope, auth/authz, event vocabulary, webhooks, env/config), run the **`boundary`** skill scoped to your change — it reads both sides of each touched contract in source and reports what would break.
|
|
50
|
+
4. If a `docs/memory/` file exists for the domain you're working in, read it for domain knowledge and failure modes
|
|
51
|
+
5. 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 1.
|
|
53
52
|
|
|
54
53
|
For the protocol on _writing_ to memory (which file, what belongs there, what doesn't), see **Project Memory** below.
|
|
55
54
|
|
|
@@ -83,9 +82,9 @@ When implementing a plan, if you discover work that is important but outside the
|
|
|
83
82
|
|
|
84
83
|
## Doc Ownership
|
|
85
84
|
|
|
86
|
-
Feature docs (in `docs/modules/{m}/features/`, or flat `docs/features/` if the module isn't declared)
|
|
85
|
+
Which doc is canonical for which code paths — and which module each path belongs to — is recorded in **[`docs/routing.md`](docs/routing.md)** (File-Pattern Routes), the single hand-maintained map. Feature docs (in `docs/modules/{m}/features/`, or flat `docs/features/` if the module isn't declared) carry **no** ownership frontmatter; their code paths are their routing row(s). A module is tied to code by its routing patterns (the Module column), not by aggregated globs. Architecture docs describe cross-cutting patterns and don't own specific files; operations docs describe procedures. The only frontmatter a living doc may carry is an optional `anchors:` block (a qmd drift tripwire, not ownership).
|
|
87
86
|
|
|
88
|
-
The spec-mode agent checks for ownership conflicts during research. If conflicts are found, address them in the spec before proceeding.
|
|
87
|
+
The spec-mode agent checks `routing.md` for ownership conflicts during research (overlapping patterns). If conflicts are found, address them in the spec before proceeding.
|
|
89
88
|
|
|
90
89
|
---
|
|
91
90
|
|
|
@@ -121,4 +120,4 @@ Unless explicitly requested:
|
|
|
121
120
|
Maintenance triggers (act on these without re-reading `structure.md`):
|
|
122
121
|
|
|
123
122
|
- 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.
|
|
124
|
-
- When you add, move, or delete a doc: update `docs/routing.md` to match. When you move or rename source files:
|
|
123
|
+
- When you add, move, or delete a doc: update `docs/routing.md` to match. When you move or rename source files: update the matching File-Pattern Route(s) in `docs/routing.md`; a new doc that owns code gets its row(s) there (no frontmatter).
|
|
@@ -33,7 +33,7 @@ The heatmap needs rolling 1w / 1m / 3m windows, so default `since` to 3 months e
|
|
|
33
33
|
|
|
34
34
|
1. If `./docs/memory/change-review.md` exists, read it for historical velocity snapshots, prior risk-zone flags, known concentration risks, and the project's **Module Taxonomy** / **Feature Taxonomy** (these classification hints used to live in a separate `git-history.md` memory file — they now live here).
|
|
35
35
|
2. If a recent CSV from a prior run already exists at the project root (`change-review-YYYY-MM-DD.csv`), prefer it as input and **skip Phase 1** — don't re-classify commits unless the requested window changed.
|
|
36
|
-
3.
|
|
36
|
+
3. Read `./docs/routing.md` File-Pattern Routes to map churn to owning feature docs (and their modules).
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
@@ -29,7 +29,7 @@ The upgrade story is the two run back-to-back: install refreshes the engine →
|
|
|
29
29
|
|
|
30
30
|
These are different axes — keep them clean:
|
|
31
31
|
|
|
32
|
-
- **`maintenance` audits docs-vs-code _fidelity_** — is the documented behavior _true_ of the code? (stale docs,
|
|
32
|
+
- **`maintenance` audits docs-vs-code _fidelity_** — is the documented behavior _true_ of the code? (stale docs, routing rows that match nothing, routing drift). It edits docs for content accuracy.
|
|
33
33
|
- **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 code's bounded contexts imply them).
|
|
34
34
|
|
|
35
35
|
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.
|
|
@@ -53,11 +53,11 @@ The target is the canonical structure below; converge the repo to it. For a fres
|
|
|
53
53
|
docs/
|
|
54
54
|
├── README.md # Documentation root — quick links, section index
|
|
55
55
|
├── structure.md # Authority map + frontmatter `harness-version` (you own this field)
|
|
56
|
-
├── routing.md # File-pattern → module / doc / agent map
|
|
56
|
+
├── routing.md # File-pattern → module / doc / agent map — the code-ownership SoT
|
|
57
57
|
├── architecture/ # Cross-module design + steering layer
|
|
58
58
|
│ │ # domain-model, glossary, non-goals, references, open-questions
|
|
59
59
|
│ └── adr/ # Architecture Decision Records (numbered, immutable)
|
|
60
|
-
├── features/ # Flat default — feature specs
|
|
60
|
+
├── features/ # Flat default — feature specs (ownership lives in routing.md, no frontmatter)
|
|
61
61
|
│ └── {feature}/ # subfolder for deep features
|
|
62
62
|
├── modules/ # Declared bounded contexts — NOT scaffolded empty; appear by declaration
|
|
63
63
|
│ └── {module}/ # CLAUDE.md + features/ + pillars/ (module-local doctrine, lazy)
|
|
@@ -73,7 +73,7 @@ docs/
|
|
|
73
73
|
|
|
74
74
|
### Step 1 — Inventory and classify
|
|
75
75
|
|
|
76
|
-
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
|
|
76
|
+
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 (`docs/routing.md`, memory, cross-doc links).
|
|
77
77
|
|
|
78
78
|
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.
|
|
79
79
|
|
|
@@ -88,6 +88,9 @@ This is what makes reconcile more than a fresh scaffold. Detect old-shape artifa
|
|
|
88
88
|
| repo-wide `docs/pillars/` | module-local `docs/modules/{m}/pillars/`; cross-module doctrine → `docs/architecture/` |
|
|
89
89
|
| `docs/architecture/overview.md` | split into `domain-model.md` / `glossary.md` / `non-goals.md` / `references.md` / `open-questions.md` |
|
|
90
90
|
| flat feature docs that belong to a declared module | `docs/modules/{m}/features/` |
|
|
91
|
+
| feature docs carrying `owns`/`touches`/`depends_on` frontmatter (legacy ownership) | migrate each into `docs/routing.md` File-Pattern rows (Pattern ← `owns`; Module ← its module or `—`; Canonical Doc ← the doc), then **strip the ownership frontmatter** from the doc — keep only an optional `anchors:` block if present |
|
|
92
|
+
| `docs/OWNERSHIP_INDEX.md` (legacy derived ownership index) | delete — ownership lives in `docs/routing.md` |
|
|
93
|
+
| no `docs/routing.md` (and the repo owns code) | scaffold it (Step 4) and populate from any legacy `owns`/index above |
|
|
91
94
|
| no `harness-version` in `structure.md` | stamp it (Step 5) |
|
|
92
95
|
|
|
93
96
|
Only fold what is present. `log()` what you skipped and why.
|
|
@@ -98,9 +101,9 @@ Table: `| File | Action | From | To | Reason |` (actions: `Move`, `Merge into {t
|
|
|
98
101
|
|
|
99
102
|
### Step 4 — Execute
|
|
100
103
|
|
|
101
|
-
Create the folder structure; move/fold/merge/delete per the plan; add `Status:` to plan files;
|
|
104
|
+
Create the folder structure; move/fold/merge/delete per the plan; add `Status:` to plan files; record each feature doc's code paths as `docs/routing.md` File-Pattern rows (call the `documentation` skill's **routing-map derivation**) and strip any legacy ownership frontmatter; 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:
|
|
102
105
|
|
|
103
|
-
- `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**).
|
|
106
|
+
- `docs/structure.md` (with `harness-version`), `docs/routing.md` (the code-ownership map — scaffold when the repo owns code), `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**).
|
|
104
107
|
|
|
105
108
|
Scaffold `docs/memory/facts/` so the distilled tier has a home from day one: the `session-reflect` hook appends session lessons to the per-actor inbox at `docs/memory/inbox/{actor}.md` (not a scaffold — created mechanically on first reflection), and the `distiller` digests that queue down into fact-cards under `docs/memory/facts/`, consuming the entries it digests (no high-water mark, no `.digest-state.md`). Without the facts dir, a freshly-baselined consumer accrues inbox entries the distiller has nowhere to land — so seed the empty distilled tier alongside the hook-written inbox tier.
|
|
106
109
|
|
|
@@ -130,10 +133,10 @@ This augments routing; it never supersedes the Step 6 ownership resolution.
|
|
|
130
133
|
|
|
131
134
|
### Step 6 — Module proposal
|
|
132
135
|
|
|
133
|
-
Modules are _declared_, never inferred from physical layout. Derive the repo's candidate bounded contexts directly from the code and docs: distinct wire surfaces (who owns routes/handlers), schema/data-access ownership, entry points and process units, plus any contexts `docs/architecture/` or
|
|
136
|
+
Modules are _declared_, never inferred from physical layout. Derive the repo's candidate bounded contexts directly from the code and docs: distinct wire surfaces (who owns routes/handlers), schema/data-access ownership, entry points and process units, plus any contexts `docs/architecture/` or `docs/routing.md` patterns already name.
|
|
134
137
|
|
|
135
|
-
- Propose the derived contexts as candidate modules. For each, partition existing flat feature docs by `
|
|
136
|
-
- **Propose — don't force.** Declaration is opt-in: a single-context app stays flat (so does a monolith whose contexts all share one kernel); declare `docs/modules/{m}/` only when the author accepts a context as a module. A module is tied to code by its `
|
|
138
|
+
- Propose the derived contexts as candidate modules. For each, partition existing flat feature docs by `docs/routing.md` pattern overlap (which docs' routing patterns fall inside the context's code).
|
|
139
|
+
- **Propose — don't force.** Declaration is opt-in: a single-context app stays flat (so does a monolith whose contexts all share one kernel); declare `docs/modules/{m}/` only when the author accepts a context as a module. A module is tied to code by its `docs/routing.md` patterns (recorded in the Module column), **layout-blind** — a workspace is not a module (one workspace may hold several contexts; one context may span workspaces). When a context is accepted, set the Module column on its routing rows.
|
|
137
140
|
|
|
138
141
|
If Step 5b skipped because `qmd` was absent, carry its one advisory line into the hand-back — _"qmd not installed — semantic retrieval unavailable; glob routing active."_ — advisory, never an error, never a gate.
|
|
139
142
|
|
|
@@ -149,7 +152,7 @@ If the user **declines** the advisory rather than running the follow-up, record
|
|
|
149
152
|
|
|
150
153
|
### Step 7 — Verify
|
|
151
154
|
|
|
152
|
-
Confirm all mandated files exist; `structure.md` carries the current `harness-version`; no dead links in `docs/structure.md`; every plan has a `Status:`; feature
|
|
155
|
+
Confirm all mandated files exist; `structure.md` carries the current `harness-version`; `docs/routing.md` exists and its File-Pattern rows cover the owned code paths; no dead links in `docs/structure.md`; every plan has a `Status:`; no feature doc carries `owns`/`touches`/`depends_on` frontmatter; no dissolved-version artifacts remain; no docs outside the canonical structure.
|
|
153
156
|
|
|
154
157
|
---
|
|
155
158
|
|
|
@@ -161,7 +164,7 @@ Conformance, not fidelity. Report a table; fix nothing destructively without ask
|
|
|
161
164
|
- **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 --name=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.
|
|
162
165
|
- **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` 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 (major-version reconcile + published-version); the digest is provenance, and the seed for any future published-digest drift check.
|
|
163
166
|
- **Scaffold completeness** — every mandated file present.
|
|
164
|
-
- **Dissolved-version residue** — any `operations/guardrails.md`, repo-wide `docs/pillars/`, `architecture/overview.md`, a persisted `docs/boundaries/` tree, or other old-shape artifact lingering.
|
|
167
|
+
- **Dissolved-version residue** — any `operations/guardrails.md`, `docs/OWNERSHIP_INDEX.md`, feature docs still carrying `owns`/`touches`/`depends_on` frontmatter, repo-wide `docs/pillars/`, `architecture/overview.md`, a persisted `docs/boundaries/` tree, or other old-shape artifact lingering.
|
|
165
168
|
- **Module declaration coverage** — do the repo's bounded contexts have declared module homes where the author intended them? (Surface gaps; never auto-declare.)
|
|
166
169
|
- **`docs/tests/` ownership** — present-with-content, or absent. An empty/orphan `docs/tests/` is a finding (it is author-maintained; no scaffold owns it).
|
|
167
170
|
|
|
@@ -169,7 +172,7 @@ Conformance, not fidelity. Report a table; fix nothing destructively without ask
|
|
|
169
172
|
|
|
170
173
|
- **Declarative, idempotent.** Re-running on a current repo is a no-op. Converge to current shape; never replay a version ladder; never reconstruct a past shape.
|
|
171
174
|
- **One sentinel.** `docs/structure.md` `harness-version` is the only baseline/version marker. Do not reintroduce a `docs/memory/index.md` "is-baselined" check.
|
|
172
|
-
- **Modules are declared, layout-blind.** Seed from the code's bounded contexts + `
|
|
175
|
+
- **Modules are declared, layout-blind.** Seed from the code's bounded contexts + `docs/routing.md` patterns; never from `pnpm-workspace.yaml`/workspace walls. Propose, don't force.
|
|
173
176
|
- **You orchestrate docs; the `documentation` skill supplies templates.** It is a library — you never expect it to baseline.
|
|
174
177
|
- **Never overwrite an existing root `README.md`.** It is human-authored.
|
|
175
178
|
- **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.
|
|
@@ -18,22 +18,22 @@ Out of scope (handled by the `boundary` skill, which derives contracts dynamical
|
|
|
18
18
|
|
|
19
19
|
1. If `./docs/memory/maintenance.md` exists, read it for last review state, ownership snapshots, high-churn paths, and known failure modes.
|
|
20
20
|
2. If `./docs/memory/boundary.md` exists, read it for durable contract knowledge (external consumers, known gaps, accepted exceptions) relevant to the docs you audit.
|
|
21
|
-
3.
|
|
21
|
+
3. Read `./docs/routing.md` — the code-ownership map (file-pattern → canonical doc + module). It is the ownership source of truth for this audit.
|
|
22
22
|
|
|
23
23
|
## Step 1: Build Ownership Map
|
|
24
24
|
|
|
25
25
|
1. Read `docs/structure.md` for the authority map
|
|
26
|
-
2.
|
|
27
|
-
3. Build a map:
|
|
26
|
+
2. Read `docs/routing.md` File-Pattern Routes
|
|
27
|
+
3. Build a map: pattern → owning doc + module (this IS the source of truth — there is no frontmatter to glob)
|
|
28
28
|
|
|
29
|
-
**Architecture-first fallback.** If
|
|
29
|
+
**Architecture-first fallback.** If `docs/routing.md` is absent or has no File-Pattern rows (a fresh-baseline repo can carry thousands of LOC and zero feature docs), drive this pass's ownership/drift surface off `docs/architecture/**` file-references instead — they become the **primary** ownership map for Steps 2–5. The routing map stays primary the moment any row appears — this is a fallback, not a replacement.
|
|
30
30
|
|
|
31
31
|
## Step 2: Validate Ownership
|
|
32
32
|
|
|
33
|
-
For each
|
|
33
|
+
For each File-Pattern row in `docs/routing.md`:
|
|
34
34
|
|
|
35
|
-
- Verify the
|
|
36
|
-
- Report
|
|
35
|
+
- Verify the pattern matches existing files
|
|
36
|
+
- Report patterns matching nothing, deleted paths, orphaned rows (doc no longer exists)
|
|
37
37
|
|
|
38
38
|
For each code symbol or path a doc explicitly **names** (function/export/route/type):
|
|
39
39
|
|
|
@@ -52,8 +52,8 @@ Run `git log --since="2 weeks ago" --name-only --pretty=format:"%h %s"` to find
|
|
|
52
52
|
|
|
53
53
|
For each changed file:
|
|
54
54
|
|
|
55
|
-
- Match against
|
|
56
|
-
- If no
|
|
55
|
+
- Match against the File-Pattern routes in `docs/routing.md` (narrower pattern wins) → identify the owning doc
|
|
56
|
+
- If no route matches → flag as unowned
|
|
57
57
|
- If owner exists → compare last modified dates (`git log -1 --format="%ci" -- <path>`), flag docs where code changed more recently (14-day threshold)
|
|
58
58
|
|
|
59
59
|
## Step 4: Check Routing Table Drift
|
|
@@ -64,7 +64,7 @@ If `./docs/routing.md` exists:
|
|
|
64
64
|
2. Check for new top-level source directories (the repo's actual source roots — derive them, never assume `src/`) not covered by any routing entry
|
|
65
65
|
3. Fix drift directly, or backlog if unclear
|
|
66
66
|
|
|
67
|
-
Also flag **unowned paths** — top-level source directories with no owning feature doc (no `
|
|
67
|
+
Also flag **unowned paths** — top-level source directories with no owning feature doc (no `docs/routing.md` pattern covers them).
|
|
68
68
|
|
|
69
69
|
Also catch a **stale greenfield self-label.** If `routing.md` (or `structure.md`) asserts the repo is greenfield — _"Greenfield. No source code or feature docs exist yet"_ or similar — **but a real source tree exists** (the derived source roots from this step's item 2 above, or Step 5's Unowned-code derivation, are non-empty, e.g. a populated `packages/` of real workspaces), the self-label has gone stale: the scaffold filled in but the doc still announces an empty repo. Raise it as a question (e.g. `routing.md says "No source code exists yet" but packages/ holds 5 workspaces — confirm the greenfield label should be retired`).
|
|
70
70
|
|
|
@@ -72,7 +72,7 @@ Also catch a **stale greenfield self-label.** If `routing.md` (or `structure.md`
|
|
|
72
72
|
|
|
73
73
|
**Architecture drift:** Grep `docs/architecture/` for file path references. Verify referenced paths still exist. Remove or update stale references.
|
|
74
74
|
|
|
75
|
-
**Unowned code:** Compare the repo's actual top-level source directories (derive them — the top-level dirs that contain code, or the roots named across `
|
|
75
|
+
**Unowned code:** Compare the repo's actual top-level source directories (derive them — the top-level dirs that contain code, or the roots named across `docs/routing.md` patterns; do not assume `src/`) against the File-Pattern routes in `docs/routing.md`. Report directories no routing pattern covers.
|
|
76
76
|
|
|
77
77
|
**Backlog health:** Read `docs/history/backlog.md`. Report items older than 30 days. Count pending by priority.
|
|
78
78
|
|
|
@@ -95,7 +95,7 @@ For unowned code paths:
|
|
|
95
95
|
2. Update `docs/memory/maintenance.md` with last review date, stale docs fixed, unowned paths, backlog items created
|
|
96
96
|
3. Report findings: stale docs, broken ownership, unowned code, architecture drift, backlog health
|
|
97
97
|
4. **Inbox-distillation threshold.** Count undigested inbox entries — `## ` entry blocks across `docs/memory/inbox/*.md` (the inbox is consume-on-digest, so every block present is undigested). If the count is **≥5**, add one line to the report **proposing** a `distiller` `facts` run — propose only, never auto-run, no cron. If the user declines or ignores it, do nothing: the count keeps growing and the proposal reappears next pass — that recurrence _is_ the dedupe, so never backlog it.
|
|
98
|
-
5. **Docs-distillation threshold.** Per target doc, count undigested fact-cards (`invalid_from: null`, the doc's path not in their `digested_into:`) that **touch** it by the structural intersection in `skills/distiller/references/docs-mode.md` Resolution 1 (provenance
|
|
98
|
+
5. **Docs-distillation threshold.** Per target doc, count undigested fact-cards (`invalid_from: null`, the doc's path not in their `digested_into:`) that **touch** it by the structural intersection in `skills/distiller/references/docs-mode.md` Resolution 1 (provenance ∩ the doc's `routing.md` patterns strong, entities ∩ declared-ownership supporting — qmd-independent). If **≥10** map to **one** doc, add one line to the report **proposing** a `distiller docs --doc <path>` run on that doc — propose only, never auto-run, no cron. Declined or ignored ⇒ the count keeps growing and the proposal reappears next pass; that recurrence _is_ the dedupe, so never backlog the proposal.
|
|
99
99
|
|
|
100
100
|
## Step 8: Refresh Index (Optional)
|
|
101
101
|
|
|
@@ -21,7 +21,7 @@ First, understand the documentation landscape:
|
|
|
21
21
|
2. If `./docs/features/README.md` exists, read it to see existing feature specs and where the new spec fits; otherwise glob the feature docs directly
|
|
22
22
|
3. If `./docs/memory/spec-mode.md` exists, read it for feature doc inventory, ownership conflict zones, and lessons from previous research
|
|
23
23
|
4. Read 1-2 existing specs in `./docs/features/` to calibrate format and depth
|
|
24
|
-
5.
|
|
24
|
+
5. Read `./docs/routing.md` (File-Pattern Routes) to build the ownership map — pattern → canonical doc + module. This is the source of truth for what code paths are already owned (feature docs carry no ownership frontmatter).
|
|
25
25
|
|
|
26
26
|
This tells you what already exists, what's adjacent, how detailed the spec should be, and what code paths are already owned.
|
|
27
27
|
|
|
@@ -32,7 +32,7 @@ This tells you what already exists, what's adjacent, how detailed the spec shoul
|
|
|
32
32
|
3. **Affected modules** — Identify what files, routes, components, and data flows are relevant
|
|
33
33
|
4. **Current state** — Understand how the system works today in the area being specified
|
|
34
34
|
5. **Dependencies** — Map what this feature touches and what depends on it
|
|
35
|
-
6. **Ownership conflicts** — Compare the new feature's intended code paths against existing `
|
|
35
|
+
6. **Ownership conflicts** — Compare the new feature's intended code paths against existing `docs/routing.md` patterns. Report overlaps.
|
|
36
36
|
|
|
37
37
|
## What You Return
|
|
38
38
|
|
|
@@ -43,7 +43,7 @@ Structure your findings as:
|
|
|
43
43
|
- **Affected modules**: Files, routes, components that will be involved
|
|
44
44
|
- **Current behavior**: How the relevant part of the system works today
|
|
45
45
|
- **Conventions**: Naming, structure, and patterns to follow based on existing code
|
|
46
|
-
- **Ownership conflicts**: Existing feature docs whose `
|
|
46
|
+
- **Ownership conflicts**: Existing feature docs whose `docs/routing.md` patterns overlap with the proposed feature. Include the conflicting paths and the owning doc name.
|
|
47
47
|
- **Risks or concerns**: Anything the spec should address or call out
|
|
48
48
|
|
|
49
49
|
Use the documentation skill's style guide and conventions when structuring your findings — imperative voice, ASCII diagrams for flows, function signatures over implementations, concise.
|
|
@@ -66,16 +66,16 @@ Read [`method.md`](method.md) (surprisal / EDU / reconciliation / bi-temporal vo
|
|
|
66
66
|
### 1. Resolve the target doc, read the three roots in order
|
|
67
67
|
|
|
68
68
|
1. `method.md` (algorithm vocabulary).
|
|
69
|
-
2. The **target doc** — full current prose +
|
|
69
|
+
2. The **target doc** — full current prose + the `docs/routing.md` patterns that map to it (the paths it owns). This is the SSoT you are proposing to revise; you read it before you draft so conflicts surface as questions, not silent overwrites.
|
|
70
70
|
- `--doc <path>` → that doc.
|
|
71
|
-
- `--feature <slug>` / bare → the spec that just flipped to `Active` (Completion names it), or the feature doc whose `
|
|
71
|
+
- `--feature <slug>` / bare → the spec that just flipped to `Active` (Completion names it), or the feature doc whose `docs/routing.md` pattern covers the plan's Proposed-Changes paths. Match the routing patterns against changed paths. Architecture/operations docs own no paths in routing — for those, fall to entity/semantic match.
|
|
72
72
|
- No doc resolves → Edge Case A.
|
|
73
73
|
3. The **pillar headlines** — the doctrine pillar (`## Pn —` headlines) and the decisions pillar (`## Dn —` headlines) plus each one's one-line Principle/Decision statement. Read **every** decision headline except those marked superseded: a decision carrying a `Reversed by D-M` marker (or a legacy `Status: tentative`) is NOT a binding pillar headline and is skipped; absence of any status marker means the decision is live (the new append-only model has no `Status: committed` field — a live decision is simply one nothing has reversed). Headlines only, never the bodies — this is the conservative contradiction-check substrate (Resolution 4).
|
|
74
74
|
|
|
75
75
|
### 2. INPUT SELECTION — gather the cards "touching" the target (Resolution 1) — _closes F2, F3, F5_
|
|
76
76
|
|
|
77
|
-
1. **Structural retriever (always runs, qmd-independent).** Read every card in `docs/memory/facts/*.md`. A card _structurally touches_ the target when its `provenance` paths or `entities` intersect the target's `
|
|
78
|
-
2. **Semantic retriever (qmd, optional).** If `command -v qmd` succeeds, for the target's identity (title + each
|
|
77
|
+
1. **Structural retriever (always runs, qmd-independent).** Read every card in `docs/memory/facts/*.md`. A card _structurally touches_ the target when its `provenance` paths or `entities` intersect the target's `docs/routing.md` patterns — match defined precisely in Resolution 1.
|
|
78
|
+
2. **Semantic retriever (qmd, optional).** If `command -v qmd` succeeds, for the target's identity (title + each routing-pattern stem + any `anchors:` query) run `qmd query --format json -c {repo}-facts "<the doc's subject>"`. `{repo}` = repo dir name; scope with `-c` always; repeat `-c` per relevant `{repo}-*` facts collection (the set `qmd collection list` names). qmd absent ⇒ skip silently, note in the report that selection ran structural-only (changes recall, not correctness).
|
|
79
79
|
3. **Bi-temporal + digestion gate (F2, F3).** From the union, drop:
|
|
80
80
|
- any card with `invalid_from` ≠ `null` (superseded — list as "skipped: superseded");
|
|
81
81
|
- any card whose `digested_into:` already lists the target doc path (already consumed here);
|
|
@@ -169,8 +169,8 @@ A card **touches** the target doc iff it satisfies **either** retriever, and is
|
|
|
169
169
|
|
|
170
170
|
**(a) Structural intersection (exact, always evaluated).** True when ANY of:
|
|
171
171
|
|
|
172
|
-
1. **Provenance match (STRONG signal).** A `commit <sha>` entry in the card's `provenance` resolves to changed files (`git show --name-only <sha>` when the commit is local); a changed file under the target's `
|
|
173
|
-
2. **Entity match (SUPPORTING signal).** A normalized name in the card's `entities` equals (case-insensitively, after kebab/camel normalization) a module/feature stem in
|
|
172
|
+
1. **Provenance match (STRONG signal).** A `commit <sha>` entry in the card's `provenance` resolves to changed files (`git show --name-only <sha>` when the commit is local); a changed file under the target's `docs/routing.md` patterns is a match. (`session <id>` entries carry no paths and do not participate; an ADR/brainstorm path matches the patterns directly.) This is strong because the card derives from a commit that edited code the doc owns.
|
|
173
|
+
2. **Entity match (SUPPORTING signal).** A normalized name in the card's `entities` equals (case-insensitively, after kebab/camel normalization) a module/feature stem in one of the target's `docs/routing.md` patterns, the doc title, or a symbol the doc explicitly names. **Bare prose mentions do NOT count** — only declared ownership (its routing patterns), so "touching" can't be triggered by a doc that merely discusses an entity it doesn't own.
|
|
174
174
|
|
|
175
175
|
**(b) Semantic neighborhood (qmd, optional, recall-only).** A card returned by `qmd query -c {repo}-facts "<doc subject>"` within qmd's default result window. Semantic hits with **no** structural intersection are still candidates but flagged `[semantic-only]` in the delta — the link is associative, not provenance-grounded, so the reviewer treats it as lower-trust and may reject on link-strength alone.
|
|
176
176
|
|
|
@@ -189,7 +189,7 @@ A card may touch **several** docs (its entities span modules) — expected, hand
|
|
|
189
189
|
| **`## Architecture` / `## Key Functions`** (feature doc) | Additive correction only when a card names a concrete, code-anchored fact (a new function, a moved file). Prefer Current Behavior unless the card is structural. | Code-anchored structure, not prose. |
|
|
190
190
|
| **A new changelog entry** in `docs/history/changelog/` (via `documentation` skill's Changelog template, `### Added`/`### Modified`/`### Removed`) | Draft a changelog line for a code change a card witnesses, when a plan just completed. | Append-only history; a _new_ file, never an edit. |
|
|
191
191
|
|
|
192
|
-
**Never writable by distill②** (hard stops): `## Goal`, `## Goals & Non-Goals`, `## Approach`, `## Open Questions`, `## State`,
|
|
192
|
+
**Never writable by distill②** (hard stops): `## Goal`, `## Goals & Non-Goals`, `## Approach`, `## Open Questions`, `## State`, the optional `anchors:` frontmatter (the only frontmatter a doc carries; ownership lives in `docs/routing.md` — maintenance/spec axis — P19), any **pillar** file, any **plan** (frozen), any **existing** changelog entry (frozen history), any **boundary** file. A card implying one of these needs a change becomes a **question** (below) or, for pillars, an **escape item** (Resolution 4).
|
|
193
193
|
|
|
194
194
|
**Per-line provenance (the invariant, mechanized).** Every drafted line carries `[from: fact-<slug>]` for each contributing card. A line with no such tag is a **defect** — not presented (Acceptance A2). On accept the tag is stripped from the final doc prose (it was review scaffolding); the durable forward-link survives as `digested_into:` (Resolution 3) — so traceability is preserved without polluting human-owned prose.
|
|
195
195
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: documentation
|
|
3
|
-
description: Template & generator library for technical docs — the skill agents call to produce a doc from a template. Use to (1) document a feature or module, (2) create or update a changelog entry, (3) document data flows or Redux state, (4) add to protected files, (5) record an architecture decision (ADR), (6) create or update the project root README, (7) create or update a plan, (8) derive
|
|
3
|
+
description: Template & generator library for technical docs — the skill agents call to produce a doc from a template. Use to (1) document a feature or module, (2) create or update a changelog entry, (3) document data flows or Redux state, (4) add to protected files, (5) record an architecture decision (ADR), (6) create or update the project root README, (7) create or update a plan, (8) derive the routing map (code path → canonical doc + module) for `docs/routing.md` from code, (9) scaffold a standard doc (README, structure.md, routing.md, CHANGELOG, backlog, memory) from its template, or (10) co-author any technical doc. Baselining / reconciling a repo's docs to the installed harness version is the **`harness-manager` agent** (which calls this skill for each template) — this skill does not orchestrate baseline. Triggers on "document this", "create docs", "update changelog", "add to protected files", "ADR", "architecture decision", "root README", "plan", "feature doc".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Technical Documentation Skill
|
|
7
7
|
|
|
8
|
-
**This skill is a template & generator library, not an orchestrator.** It supplies the templates, the
|
|
8
|
+
**This skill is a template & generator library, not an orchestrator.** It supplies the templates, the routing-map-derivation generator, and the co-authoring workflow that _agents_ call to produce individual docs. It does **not** baseline, audit, or reconcile a repo's doc tree — that is the **`harness-manager` agent**, which calls this skill for each template it scaffolds. Reach here to generate _one_ doc from a template; reach for `harness-manager` to bring a whole repo into shape.
|
|
9
9
|
|
|
10
10
|
Document contracts and architecture, not implementation details. Show function signatures and API shapes — never paste full implementations (they rot fast). Use ASCII diagrams over prose for flows. Only document state at persistence boundaries (Redux persistence, DB schemas, API shapes), not component-level or transient state. Mark deprecated fields with `// UNUSED:` comments. Breaking changes belong in changelogs only, not module docs.
|
|
11
11
|
|
|
12
|
-
**No redirect docs.** When moving a doc to a new location, delete the old file entirely. Update all references (routing
|
|
12
|
+
**No redirect docs.** When moving a doc to a new location, delete the old file entirely. Update all references (`docs/routing.md`, memory files, cross-doc links) to point to the new path. Never leave a stub file that says "Moved to X" — redirect docs rot, clutter the repo, and create false search hits.
|
|
13
13
|
|
|
14
14
|
**Present tense, current state only.** Active docs (everything outside `docs/history/`) describe the system _as it is now_ — what exists and how it works today. They never narrate how it got there: no migration/fold history, no dated "shipped/verified/built on YYYY-MM-DD" markers, no "ex-`@nurix/X`, folded 2026-06-12" provenance, no "was X → now Y" change journeys, no "removed/deleted in the <date> fold". The historical record — when and how things changed — lives **only** in `docs/history/` (changelog, plans, ADRs); `docs/memory/` is the agent's dated log and is likewise exempt. A doc may cite an ADR for the _why_ (the decision rationale), but must not narrate the _when/how it changed_. Routing/index docs point only to current authority docs — never to a historical plan or changelog as the "read first" source. When you find historical narration in an active doc, rewrite it to the present-tense fact and let `docs/history/` carry the story.
|
|
15
15
|
|
|
@@ -54,54 +54,48 @@ User request
|
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Routing-Map Derivation
|
|
58
58
|
|
|
59
|
-
When creating or updating a feature doc
|
|
59
|
+
When creating or updating a feature doc, derive its **`docs/routing.md` File-Pattern Routes row(s)** — the code paths it is canonical for — from the source the doc describes. Code ownership lives in `routing.md`, never in feature-doc frontmatter.
|
|
60
60
|
|
|
61
61
|
### When to run
|
|
62
62
|
|
|
63
|
-
- **Baseline
|
|
64
|
-
- **New feature doc** — when creating a doc via the Module
|
|
65
|
-
- **Doc update** — when
|
|
63
|
+
- **Baseline / reconcile** — for every feature doc whose code paths aren't yet mapped in `routing.md` (the `harness-manager` agent calls this)
|
|
64
|
+
- **New feature doc** — when creating a doc via the Feature/Module template, add its routing row(s)
|
|
65
|
+
- **Doc update** — when the documented scope changes, update the doc's routing row(s)
|
|
66
66
|
|
|
67
|
-
### How to derive
|
|
67
|
+
### How to derive a row
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
A routing row is `| Pattern | Module | Canonical Doc | Memory |`.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
**1. Pattern** (the path scope — the old `owns`)
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Read the doc's content. Extract every source file path it references (file listings, function locations, component paths). Group them into the narrowest glob patterns that cover all referenced files without overlapping another doc's pattern at equal specificity. A doc may need several rows.
|
|
74
|
+
|
|
75
|
+
| Doc references | Pattern |
|
|
74
76
|
| ------------------------------------ | ------------------------- |
|
|
75
77
|
| Multiple files under one directory | `src/feature/**` |
|
|
76
78
|
| Specific files in a shared directory | List each file explicitly |
|
|
77
79
|
| A single entry-point file | The exact file path |
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
**2. Identify `touches` patterns**
|
|
82
|
-
|
|
83
|
-
From the same source files the doc describes, find imports and calls to code outside the `owns` scope. These are files the feature uses but doesn't own.
|
|
81
|
+
Glob each pattern against the codebase; drop any that match nothing.
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
**2. Module**
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
- Utility functions from other modules
|
|
89
|
-
- Shared hooks the feature calls
|
|
90
|
-
- API route files the feature's frontend calls
|
|
85
|
+
The declared module the pattern belongs to (the `docs/modules/{m}/` it lives under), or `—` if the repo is flat. Rows sharing a Module value are what ties that module to code.
|
|
91
86
|
|
|
92
|
-
|
|
87
|
+
**3. Canonical Doc & Memory**
|
|
93
88
|
|
|
94
|
-
|
|
89
|
+
Canonical Doc = this doc's path (`features/…` when flat, `modules/{m}/features/…` when the module is declared). Memory = the `docs/memory/` file for the area, or `—`.
|
|
95
90
|
|
|
96
|
-
|
|
91
|
+
> The old `touches`/`depends_on` relationships are no longer recorded as ownership. A doc's dependencies on other docs are expressed inline in its prose (links); cross-cutting contracts are diagnosed by the `boundary` skill from source, not persisted.
|
|
97
92
|
|
|
98
93
|
### Rules
|
|
99
94
|
|
|
100
|
-
-
|
|
101
|
-
- Use glob patterns for directories, explicit paths for individual files
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
- For baseline audits with 10+ files needing frontmatter, use parallel sub-agents to read and analyze the source files
|
|
95
|
+
- One canonical doc per path. A pattern must not overlap another row at equal specificity — the narrower pattern wins; equal-specificity overlap is a conflict to resolve.
|
|
96
|
+
- Use glob patterns for directories, explicit paths for individual files. Don't list paths that don't exist in the codebase.
|
|
97
|
+
- When a doc covers a deep feature with sub-specs (e.g., `editor/`), each sub-spec gets its own row(s) — don't duplicate a path across siblings.
|
|
98
|
+
- For baseline/reconcile with many docs, use parallel sub-agents to read source and propose rows.
|
|
105
99
|
|
|
106
100
|
---
|
|
107
101
|
|
|
@@ -125,6 +119,6 @@ For docs that don't match templates:
|
|
|
125
119
|
|
|
126
120
|
| File | Use For |
|
|
127
121
|
| --- | --- |
|
|
128
|
-
| `references/templates.md` | docs/README.md, structure.md,
|
|
122
|
+
| `references/templates.md` | docs/README.md, structure.md, routing.md, scaffolds (CHANGELOG, backlog, memory), feature, changelog, plan, protected files, ADR, project root README templates |
|
|
129
123
|
| `references/style-guide.md` | Writing rules, formatting conventions |
|
|
130
124
|
| `references/examples.md` | Good vs bad documentation examples |
|
|
@@ -91,6 +91,7 @@ Each topic has one canonical location. Read from here, not from plans or changel
|
|
|
91
91
|
|
|
92
92
|
| Topic | Authority | Key Files |
|
|
93
93
|
| ----- | --------- | --------- |
|
|
94
|
+
| Code-path ownership (path → doc + module) | `docs/routing.md` | File-Pattern Routes |
|
|
94
95
|
| System architecture + steering | `docs/architecture/` | domain-model, glossary, non-goals, references, adr/ |
|
|
95
96
|
| Feature behavior | `docs/features/` (or `docs/modules/{m}/features/`) | {key files} |
|
|
96
97
|
| Declared modules (bounded contexts) | `docs/modules/{m}/` | `features/` + `pillars/` |
|
|
@@ -109,9 +110,10 @@ Plan (Status: Draft) → Implementation → Feature Doc or Architecture Update
|
|
|
109
110
|
|
|
110
111
|
## Folder Rules
|
|
111
112
|
|
|
112
|
-
- `docs/
|
|
113
|
+
- `docs/routing.md`: The single hand-maintained map from code paths (and keywords) to the canonical doc and module for each. Code ownership lives here, not in feature-doc frontmatter. Update it whenever you add/move/delete a doc or move/rename owned source.
|
|
114
|
+
- `docs/features/`: Living reference for implemented features. Carry **no** ownership frontmatter — a feature doc's code paths are declared by its row(s) in `docs/routing.md`. (An optional `anchors:` block — a qmd drift tripwire, see §3 — is the only frontmatter a doc may carry.)
|
|
113
115
|
- `docs/architecture/`: System-wide patterns and the cross-module steering layer (domain model, glossary, non-goals, references, ADRs). Update when cross-cutting concerns change.
|
|
114
|
-
- `docs/modules/{m}/`: Vertical bounded contexts, **declared** (not inferred from layout) and tied to code by their `
|
|
116
|
+
- `docs/modules/{m}/`: Vertical bounded contexts, **declared** (not inferred from layout) and tied to code by their `docs/routing.md` patterns (the Module column groups routes into modules). Each owns `features/` + module-local `pillars/` (doctrine, lazy). There is no repo-wide `docs/pillars/`. Worth declaring at ≥2 genuine bounded contexts; a single-context app stays flat under `docs/features/`.
|
|
115
117
|
- `docs/operations/`: How-to procedures for setup, development, and deployment. Update when workflows change.
|
|
116
118
|
- `docs/history/plans/`: Historical. Must have `Status:` field. Never modify after completion.
|
|
117
119
|
- `docs/history/changelog/`: Historical. Append-only.
|
|
@@ -127,28 +129,64 @@ Plan (Status: Draft) → Implementation → Feature Doc or Architecture Update
|
|
|
127
129
|
|
|
128
130
|
---
|
|
129
131
|
|
|
130
|
-
##
|
|
132
|
+
## 2.5 docs/routing.md (Code-Path Ownership Map)
|
|
131
133
|
|
|
132
|
-
Use for:
|
|
134
|
+
Use for: the single hand-maintained map from code paths (and keywords) to the canonical doc + module. This is the source of truth for code ownership — feature docs carry no ownership frontmatter. Scaffold it once any feature doc owns code.
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
# Routing
|
|
138
|
+
|
|
139
|
+
The single map from code paths (and keywords) to the doc that is canonical for them, and the module each belongs to. The source of truth for code-path ownership — feature docs carry no ownership frontmatter. Read this before touching unfamiliar code, then read the mapped doc.
|
|
140
|
+
|
|
141
|
+
> **One canonical doc per path.** When two patterns match the same path, the **narrower** pattern wins; an equal-specificity overlap is a conflict — resolve it before merging. Hand-maintained — there is no generator. Keep it in sync when you add/move/delete a doc or move/rename owned source.
|
|
142
|
+
|
|
143
|
+
## File-Pattern Routes
|
|
144
|
+
|
|
145
|
+
| Pattern | Module | Canonical Doc | Memory |
|
|
146
|
+
| ------- | ------ | ------------- | ------ |
|
|
147
|
+
| `src/auth/**` | auth | features/login.md | memory/main.md |
|
|
148
|
+
| `src/billing/**` | billing | modules/billing/features/invoicing.md | — |
|
|
149
|
+
|
|
150
|
+
- **Pattern** — the narrowest glob covering the files the doc is canonical for. A doc may have several rows.
|
|
151
|
+
- **Module** — the declared module the pattern belongs to, or `—` if the repo is flat (no module declared). Grouping rows by this column is how a module is tied to code.
|
|
152
|
+
- **Canonical Doc** — the one doc to read before changing matching files (`features/…` when flat, `modules/{m}/features/…` when the module is declared).
|
|
153
|
+
- **Memory** — the `docs/memory/` file with domain knowledge for this area, or `—`.
|
|
154
|
+
|
|
155
|
+
## Keyword Routes
|
|
156
|
+
|
|
157
|
+
| Keyword / topic | Canonical Doc |
|
|
158
|
+
| --------------- | ------------- |
|
|
159
|
+
| auth, login, SSO, refresh | features/login.md |
|
|
160
|
+
|
|
161
|
+
## Top-Level Folders
|
|
162
|
+
|
|
163
|
+
| Folder | Purpose | Doc |
|
|
164
|
+
| ------ | ------- | --- |
|
|
165
|
+
| `src/` | {what lives here} | {doc} |
|
|
166
|
+
|
|
167
|
+
## How to Add a Route
|
|
168
|
+
|
|
169
|
+
1. Add/extend a **File-Pattern Routes** row — narrowest pattern that doesn't overlap an existing row at equal specificity; set its Module (or `—`).
|
|
170
|
+
2. Add keyword row(s) for discoverability.
|
|
171
|
+
3. When you move/rename owned source, update the matching pattern(s) here — this map is hand-maintained.
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 3. Code-Path Ownership & Anchors
|
|
177
|
+
|
|
178
|
+
**Ownership.** A feature doc is the canonical reference for the code paths mapped to it in `docs/routing.md` (File-Pattern Routes). Feature docs declare ownership through their routing row(s), **not** through frontmatter. To find what a doc owns, read its rows in `routing.md`; to find the doc for a path, match the path against the patterns there (narrower wins). See the **routing-map derivation** in `SKILL.md` for turning code into routing rows.
|
|
179
|
+
|
|
180
|
+
**Anchors (optional — the only frontmatter a living doc may carry).** A doc may carry an `anchors:` block — a qmd drift tripwire, orthogonal to ownership:
|
|
133
181
|
|
|
134
182
|
```yaml
|
|
135
183
|
---
|
|
136
|
-
owns:
|
|
137
|
-
- src/feature-name/**
|
|
138
|
-
- app/feature-name/**
|
|
139
|
-
touches:
|
|
140
|
-
- src/shared/utils/feature-helper.js
|
|
141
|
-
depends_on:
|
|
142
|
-
- docs/architecture/system-design.md
|
|
143
184
|
anchors:
|
|
144
185
|
- "qmd query: feature-name persistence shape"
|
|
145
186
|
---
|
|
146
187
|
```
|
|
147
188
|
|
|
148
|
-
|
|
149
|
-
- `touches`: Files this feature interacts with but doesn't own
|
|
150
|
-
- `depends_on`: Other docs that must be read for full context
|
|
151
|
-
- `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 template ships the exemplar, but `anchors:` may appear on any living doc the maintenance anchor-drift check globs — `docs/features/`, `docs/architecture/`, and `docs/operations/` — so the convention and the check stay one mental model.
|
|
189
|
+
`anchors` is 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. `anchors:` may appear on any living doc the maintenance anchor-drift check globs — `docs/features/`, `docs/architecture/`, and `docs/operations/`.
|
|
152
190
|
|
|
153
191
|
---
|
|
154
192
|
|
|
@@ -294,17 +332,13 @@ The four research-derived sections (**Affected Modules**, **Conventions to Follo
|
|
|
294
332
|
|
|
295
333
|
```yaml
|
|
296
334
|
---
|
|
297
|
-
|
|
298
|
-
- src/feature-name/** # projected at Draft, confirmed at Active
|
|
299
|
-
touches:
|
|
300
|
-
- src/shared/state/feature.js
|
|
301
|
-
depends_on:
|
|
302
|
-
- docs/features/related-feature.md
|
|
303
|
-
anchors: # optional — see §3 frontmatter reference
|
|
335
|
+
anchors: # optional — the only frontmatter a feature doc may carry; see §3
|
|
304
336
|
- "qmd query: wire envelope invariants"
|
|
305
337
|
---
|
|
306
338
|
```
|
|
307
339
|
|
|
340
|
+
> This doc carries **no** ownership frontmatter. Declare the code paths it owns as File-Pattern Routes row(s) in `docs/routing.md` (§2.5) — projected at Draft, confirmed at Active.
|
|
341
|
+
|
|
308
342
|
```
|
|
309
343
|
# {Feature Name}
|
|
310
344
|
|
|
@@ -351,7 +385,7 @@ High-level shape of the solution. ASCII diagram if it helps. Implementation spec
|
|
|
351
385
|
|
|
352
386
|
## Ownership Conflicts
|
|
353
387
|
|
|
354
|
-
(From spec-mode research) Existing feature docs whose `
|
|
388
|
+
(From spec-mode research) Existing feature docs whose `docs/routing.md` patterns overlap with the projected scope. Resolve per row before the plan starts — leave nothing unresolved.
|
|
355
389
|
|
|
356
390
|
| Conflicting doc | Overlapping path(s) | Resolution |
|
|
357
391
|
|-----------------|---------------------|------------|
|
|
@@ -431,7 +465,7 @@ Sections fill in across the feature's lifecycle. No template swap — they accum
|
|
|
431
465
|
| --- | --- | --- |
|
|
432
466
|
| Status: Draft (design) | Goal, Goals & Non-Goals, Background, Approach, Open Questions, Risks | User interview |
|
|
433
467
|
| Status: Draft (research) | Affected Modules, Conventions to Follow, Current Behavior, Ownership Conflicts | spec-mode agent |
|
|
434
|
-
| Status: Draft → Active (implementation lands) | Architecture, Key Functions, State, Redux, Files;
|
|
468
|
+
| Status: Draft → Active (implementation lands) | Architecture, Key Functions, State, Redux, Files; `docs/routing.md` row(s) confirmed against real code | Main agent (from actual code) |
|
|
435
469
|
|
|
436
470
|
Resolved Open Questions can be summarized into Background; unresolved ones stay visible.
|
|
437
471
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nurix/etna",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.10",
|
|
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": {
|