@nurix/etna 0.20.25 → 0.20.26
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 +4 -4
- package/data/harnesses/code/agents/bookkeeper.md +1 -1
- package/data/harnesses/code/agents/change-review.md +1 -1
- package/data/harnesses/code/agents/lld-mode.md +1 -1
- package/data/harnesses/code/agents/maintenance.md +7 -9
- package/data/harnesses/code/docs/structure.md +133 -71
- package/data/harnesses/code/harness.json +4 -4
- package/data/harnesses/code/hooks/awareness.mjs +0 -10
- package/data/harnesses/code/hooks/lib/ownership.mjs +4 -2
- package/data/harnesses/code/hooks/lib/sweep.mjs +4 -8
- package/data/harnesses/code/skills/documentation/SKILL.md +19 -8
- package/data/harnesses/code/skills/documentation/references/frontmatter.md +3 -3
- package/data/harnesses/code/skills/documentation/references/style-guide.md +70 -27
- package/data/harnesses/code/skills/documentation/references/untemplated.md +2 -1
- package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +87 -1
- package/data/harnesses/code/skills/documentation/templates/Readme.md +4 -3
- package/data/harnesses/code/skills/documentation/templates/bookkeeping.md +1 -1
- package/data/harnesses/code/skills/documentation/templates/docs-readme.md +15 -36
- package/data/harnesses/code/skills/documentation/templates/doctrine.md +82 -0
- package/data/harnesses/code/skills/documentation/templates/feature.md +31 -123
- package/data/harnesses/code/skills/documentation/templates/handover.md +174 -0
- package/data/harnesses/code/skills/documentation/templates/operations-procedure.md +1 -1
- package/data/harnesses/code/skills/documentation/templates/package.md +28 -94
- package/data/harnesses/code/skills/documentation/templates/root-readme.md +103 -65
- package/data/harnesses/code/skills/documentation/templates/setup.md +138 -0
- package/data/harnesses/code/skills/documentation/templates/system.md +25 -109
- package/data/harnesses/delivery/agents/lld-mode.md +1 -1
- package/data/harnesses/delivery/agents/maintenance.md +7 -9
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/skills/documentation/SKILL.md +19 -8
- package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +3 -3
- package/data/harnesses/delivery/skills/documentation/references/style-guide.md +70 -27
- package/data/harnesses/delivery/skills/documentation/references/untemplated.md +2 -1
- package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +87 -1
- package/data/harnesses/delivery/skills/documentation/templates/Readme.md +4 -3
- package/data/harnesses/delivery/skills/documentation/templates/bookkeeping.md +1 -1
- package/data/harnesses/delivery/skills/documentation/templates/docs-readme.md +15 -36
- package/data/harnesses/delivery/skills/documentation/templates/doctrine.md +82 -0
- package/data/harnesses/delivery/skills/documentation/templates/feature.md +31 -123
- package/data/harnesses/delivery/skills/documentation/templates/handover.md +174 -0
- package/data/harnesses/delivery/skills/documentation/templates/operations-procedure.md +1 -1
- package/data/harnesses/delivery/skills/documentation/templates/package.md +28 -94
- package/data/harnesses/delivery/skills/documentation/templates/root-readme.md +103 -65
- package/data/harnesses/delivery/skills/documentation/templates/setup.md +138 -0
- package/data/harnesses/delivery/skills/documentation/templates/system.md +25 -109
- package/data/harnesses/etna/agents/change-review.md +1 -1
- package/data/harnesses/etna/agents/lld-mode.md +1 -1
- package/data/harnesses/etna/agents/maintenance.md +7 -9
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/documentation/SKILL.md +19 -8
- package/data/harnesses/etna/skills/documentation/references/frontmatter.md +3 -3
- package/data/harnesses/etna/skills/documentation/references/style-guide.md +70 -27
- package/data/harnesses/etna/skills/documentation/references/untemplated.md +2 -1
- package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +87 -1
- package/data/harnesses/etna/skills/documentation/templates/Readme.md +4 -3
- package/data/harnesses/etna/skills/documentation/templates/bookkeeping.md +1 -1
- package/data/harnesses/etna/skills/documentation/templates/docs-readme.md +15 -36
- package/data/harnesses/etna/skills/documentation/templates/doctrine.md +82 -0
- package/data/harnesses/etna/skills/documentation/templates/feature.md +31 -123
- package/data/harnesses/etna/skills/documentation/templates/handover.md +174 -0
- package/data/harnesses/etna/skills/documentation/templates/operations-procedure.md +1 -1
- package/data/harnesses/etna/skills/documentation/templates/package.md +28 -94
- package/data/harnesses/etna/skills/documentation/templates/root-readme.md +103 -65
- package/data/harnesses/etna/skills/documentation/templates/setup.md +138 -0
- package/data/harnesses/etna/skills/documentation/templates/system.md +25 -109
- package/lib/install/materialize.mjs +4 -12
- package/lib/install/plan.mjs +4 -11
- package/package.json +3 -2
- package/data/harnesses/code/skills/documentation/templates/structure.md +0 -71
- package/data/harnesses/delivery/skills/documentation/templates/structure.md +0 -71
- package/data/harnesses/etna/skills/documentation/templates/structure.md +0 -71
package/data/harness-index.json
CHANGED
|
@@ -67,11 +67,11 @@ These four mechanisms work in tandem to keep the repo self-updating and to preve
|
|
|
67
67
|
|
|
68
68
|
### Ownership — route before editing
|
|
69
69
|
|
|
70
|
-
Which doc is canonical for which code paths is the **feature doc's own frontmatter**. A feature doc (in `docs/features/`) carries `owns:` (code-path globs — the only ownership key), `module:` (a bounded-context label, omitted when cross-cutting),
|
|
70
|
+
Which doc is canonical for which code paths is the **feature doc's own frontmatter**. A feature doc (in `docs/features/`) carries `objects:` (the product objects it designs — its discovery terms and its edge into the knowledge graph), `owns:` (code-path globs — the only ownership key, kept until the graph computes ownership), `module:` (a bounded-context label, omitted when cross-cutting), and `status:`. Code → doc ownership is the union of every feature doc's `owns:` globs, surfaced as the generated ownership index at session start. A module is tied to code by the `owns:` globs of the docs carrying its `module:` label — not a folder, not a separate map. Architecture docs describe cross-cutting patterns and own no files; operations docs describe procedures. Every doc carries `type:` — its genre, stamped by document generators or at authoring, read by tooling (UI grouping, protected-file mapping); the `maintenance` agent stamps it where missing. Like `last-reviewed:`, `rev:`, and `slug:`, it is tooling metadata: preserve it on edits, never inject or narrate it.
|
|
71
71
|
|
|
72
72
|
Before modifying code in an unfamiliar area:
|
|
73
73
|
|
|
74
|
-
1. Consult the **injected ownership index** (`glob → doc · module ·
|
|
74
|
+
1. Consult the **injected ownership index** (`glob → doc · module · objects · status`). Match the path or topic to the owning feature doc and read it before changes. (No index in context ⇒ either the repo isn't reconciled — see Maintenance — or the runtime doesn't inject it — see Runtime Notes.)
|
|
75
75
|
2. If a `docs/memory/` file exists for the domain, read it for domain knowledge and failure modes.
|
|
76
76
|
|
|
77
77
|
The `lld-mode` agent checks for ownership conflicts during LLD research — feature docs whose `owns:` globs overlap at equal specificity. Resolve them in the LLD before proceeding.
|
|
@@ -97,7 +97,7 @@ Boundaries are **diagnosed, not documented** — the `boundary` skill derives th
|
|
|
97
97
|
- **[override]** Keep `docs/` updated when code changes affect documented behavior. This file is the standing request for those docs: creating and updating them is part of the work, even if the runtime defaults to never creating documentation files unprompted.
|
|
98
98
|
- After plan completion **[override]**: write the `docs/history/changelog/` entry as a **draft** immediately, while the context is fresh — no confirmation needed — and append its `docs/history/CHANGELOG.md` row; the commit fills what the draft left open and freezes it. Non-plan work needs no separate prompt: every non-exempt commit carries its own entry (the `changelog` rule).
|
|
99
99
|
- When moving or renaming source files: update the `owns:` globs of the feature doc that owns them so the generated ownership index stays accurate. A new doc that owns code declares its paths in its own `owns:` frontmatter — there is no separate map to update.
|
|
100
|
-
- `docs/structure.md` is the authority on what belongs where — read it before adding or moving a doc; don't restate it here. One canonical source per topic — link, don't copy. Only `CLAUDE.md`, `AGENTS.md`, and `README.md` live at the repo root.
|
|
100
|
+
- `docs/structure.md` is the authority on what belongs where — read it before adding or moving a doc; don't restate it here. One canonical source per topic — link, don't copy. Only `CLAUDE.md`, `AGENTS.md`, and `README.md` live at the repo root — and the root `README.md` orients and routes (identity, how it works, a Map of units, rules that bite, where to go); install, stack and first run are `docs/operations/setup.md`, the tree is `docs/structure.md`'s.
|
|
101
101
|
|
|
102
102
|
> Agents and skills live under `.claude/agents/` and `.claude/skills/`. Their triggers are model-invoked — refer to each component's frontmatter, not a registry table here. Runtimes that can't invoke them natively: see Runtime Notes.
|
|
103
103
|
|
|
@@ -158,7 +158,7 @@ Defaults — ❌ prohibitions hold unless the user explicitly asks otherwise;
|
|
|
158
158
|
- ❌ **Dependencies** – Never upgrade pinned packages without asking; security patches and test-tooling installs at `latest` (`testing.md`) are exempt.
|
|
159
159
|
- ❌ **Compatibility** – Never maintain backward compatibility unless specified.
|
|
160
160
|
- ❌ **Branches & Worktrees [override]** – `dev` and `production` are merge-only. Work on a short-lived branch cut from `dev` (`feat/<slug>`, `fix/<slug>`, `docs/<slug>`; `hotfix/<slug>` off `production`), commit there, and open a pull request into `dev` (or `production` for a hotfix) — never commit to either long-lived branch, and never create a worktree. The branch is created when the first commit is due, not at session start. This replaces any built-in "branch first on the default branch" default: the branch is required, and it is never `main`.
|
|
161
|
-
- ❌ **Protected Files** – Once per session, if `docs/operations/protected-files.md` exists, read it and never modify any path it lists; never modify `AGENTS.md` (harness-regenerated) or `protected-files.md` itself.
|
|
161
|
+
- ❌ **Protected Files** – Once per session, if `docs/operations/protected-files.md` exists, read it and never modify any path it lists; never modify `AGENTS.md` or `docs/structure.md` (both harness-regenerated — the installer rewrites them on every refresh; the `maintenance` agent's `harness-version` stamp is the one write `structure.md` takes) or `protected-files.md` itself.
|
|
162
162
|
- ✅ **Browser Automation** – If the runtime provides browser automation, use it freely; no need to ask first. If it doesn't — or the executing agent can't hold the browser connection (see Runtime Notes) — return a browser-verification checklist (URLs, actions, expected outcomes) for the orchestrating session or the user to run.
|
|
163
163
|
- ✅ **Bookkeeping [override]** — dispatching outranks a runtime default that reserves sub-agents for explicit requests (§ Delegation), and `hooks/compliance.mjs` enforces it: Stop is blocked on unresolved rows unless the transcript carries a real `subagent_type: bookkeeper` record. Hooks append doc-debt rows to `docs/operations/bookkeeping.md`; three walls read it at three widths (Stop = your session's rows · commit = rows implicating staged files · CI = all), each re-verifying conditions at gate time. Dispatch the `bookkeeper` for your rows — **never drain `auto:`/`note:` rows in your own loop**, whichever agent you are: the drain is dispatched work at every nesting level (a sub-agent dispatches its own `bookkeeper` — § Delegation), and only `needs-session:` rows are yours to resolve directly. A drained row is **deleted**. The full grammar arrives in the deny message when a wall fires.
|
|
164
164
|
- ✅ **Session gate log** — a denial with no `resolved` line blocks Stop; resolution mechanics arrive in the block message. Never delete log lines.
|
|
@@ -21,7 +21,7 @@ Ground every edit in this ladder, in order. Never invent content; a fact you can
|
|
|
21
21
|
| `header-missing` | add the file-path header comment in the file's native comment syntax |
|
|
22
22
|
| `source-lint` | run `.claude/skills/documentation/scripts/source-lint.mjs <file>` and clear its BLOCK findings: a stale or absent header path is rewritten to the file's own repo-relative path, and `comment-ratio-added` — over a quarter of the lines the change added are comments — is cleared by moving the rationale into the owning doc and leaving one sentence per symbol. Never clear either with a `source-lint-disable`: the one comment that earns its length is a booby trap, and that one takes the disable with its reason beside it. The file-level `comment-ratio` warning is **not** yours — it grades density somebody else wrote, and rewriting an inherited file is a unit of work with an owner, not a queue drain |
|
|
23
23
|
| `doc-lint` | fix the finding, or add `<!-- doc-lint-disable: id -->` with a reason beside it when the flagged text is deliberate |
|
|
24
|
-
| `index-row-missing` |
|
|
24
|
+
| `index-row-missing` | a retired kind — delete the row. An index names folders, never files; a doc is found by `ls` and by the ownership index, not by a README row |
|
|
25
25
|
| `doc-implicated` | read the diff of the named source file (`git diff` / `git log -p`), and update the owning doc **only where the diff contradicts documented behavior**; if nothing documented changed, the row's resolution is deleting it |
|
|
26
26
|
| `package-rejected` | re-check the named manifest: the package no longer declared → delete the row; still declared → `needs-session:` — changing a package decision is the user's call, never yours |
|
|
27
27
|
| `frozen-record-edited` | re-check `git diff HEAD -- {path}`: clean again → delete the row; still modified → `needs-session:` — never revert another session's work |
|
|
@@ -33,7 +33,7 @@ Parse these from the user's prompt; use the default when unstated.
|
|
|
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**.
|
|
35
35
|
2. If a 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** — re-classify only when the requested window changed.
|
|
36
|
-
3. Build the ownership map from feature `owns:` frontmatter — consult the injected ownership index (`glob → doc · module ·
|
|
36
|
+
3. Build the ownership map from feature `owns:` frontmatter — consult the injected ownership index (`glob → doc · module · objects · status`), or glob `docs/features/**/*.md` and read each doc's `owns:` globs — to map churn to owning feature docs and their `module:` labels.
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
@@ -21,7 +21,7 @@ Map the documentation landscape — what exists, what is adjacent, how detailed
|
|
|
21
21
|
2. Locate the repo's feature-doc layer from `structure.md` — the standard shape is `./docs/features/`, but a repo may document components under their own subject folders. Read that layer's index if it has one; otherwise glob for docs carrying `owns:` frontmatter
|
|
22
22
|
3. If `./docs/memory/lld-mode.md` exists (or the legacy `./docs/memory/spec-mode.md`), read it for feature doc inventory, ownership conflict zones, and lessons from previous research
|
|
23
23
|
4. Read 1-2 existing feature LLDs from that layer to calibrate format and depth
|
|
24
|
-
5. Consult the **injected ownership index** (the generated `glob → doc · module ·
|
|
24
|
+
5. Consult the **injected ownership index** (the generated `glob → doc · module · objects · status` map — the union of every feature doc's `owns:` frontmatter) to build the ownership map. It is the source of truth for what code paths are already owned. If the index isn't present in context, glob the docs tree (excluding `docs/history/`) and read the `owns:` frontmatter of every doc that declares it.
|
|
25
25
|
|
|
26
26
|
## What You Research
|
|
27
27
|
|
|
@@ -95,8 +95,6 @@ Run `git log --since="2 weeks ago" --name-only --pretty=format:"%h %s"` to find
|
|
|
95
95
|
|
|
96
96
|
**Unowned paths.** Compare the repo's actual top-level source directories (derive them — the top-level dirs that contain code, or the roots named across the `owns:` globs; do not assume `src/`) against the `owns:` map. Report directories no `owns:` glob covers.
|
|
97
97
|
|
|
98
|
-
**Stale greenfield self-label.** If `structure.md` asserts the repo is greenfield — _"No source code or feature docs exist yet"_ or similar — **but a real source tree exists** (the derived source roots above are non-empty, e.g. a populated `packages/` of real workspaces), the self-label has gone stale. Raise it as a question (e.g. `structure.md says "No source code exists yet" but packages/ holds 5 workspaces — confirm the greenfield label should be retired`).
|
|
99
|
-
|
|
100
98
|
**Architecture drift.** Grep `docs/architecture/` for file-path references. Verify referenced paths still exist. Remove or update stale references.
|
|
101
99
|
|
|
102
100
|
**Backlog health.** Read `docs/history/backlog.md`. Report items older than 30 days. Count pending by priority.
|
|
@@ -117,7 +115,7 @@ For an unowned code **region**, append: `- **[P2]** No feature doc owns \`{dir}/
|
|
|
117
115
|
|
|
118
116
|
### Step 6: Report & update tracking
|
|
119
117
|
|
|
120
|
-
1.
|
|
118
|
+
1. Append today's row to `docs/history/health-log.md` — **append to the end**, never date-sorted into the middle. Rows are positional: one may say "the row above is…", and an inserted row silently breaks that reference. A Health Log entry is a **generated row, not a narrative essay**: one line — date · counts (stale docs fixed, dead globs, unowned paths, backlog items created) · links to anything that needs a human.
|
|
121
119
|
2. Update `docs/memory/maintenance.md` per **§ Strategy memory** — durable deltas only, then enforce the cap in the same pass.
|
|
122
120
|
3. Report findings: stale docs, broken ownership, unowned code, architecture drift, backlog health.
|
|
123
121
|
|
|
@@ -132,7 +130,7 @@ Baseline mode converges the repo's `docs/` to the **installed** harness shape, t
|
|
|
132
130
|
```
|
|
133
131
|
docs/
|
|
134
132
|
├── README.md ✱ # Documentation root — quick links, section index
|
|
135
|
-
├── structure.md
|
|
133
|
+
├── structure.md # Harness-owned authority map — the installer writes it on every refresh; you stamp only `harness-version`
|
|
136
134
|
├── architecture/ # Cross-module design + steering layer
|
|
137
135
|
│ │ # domain-model, glossary, non-goals, references, open-questions
|
|
138
136
|
│ └── decisions/ # Architecture Decisions (ADs — one per subject, updated in place; journey in each AD's Decision Changelog)
|
|
@@ -156,7 +154,7 @@ docs/
|
|
|
156
154
|
└── tests/ # Behavioral test checklists ({feature}.md, step → **Assert**), derived at plan Completion via the `documentation` skill; author-maintained
|
|
157
155
|
```
|
|
158
156
|
|
|
159
|
-
**✱ marks the
|
|
157
|
+
**✱ marks the scaffolded files — the only paths a baseline creates, and the only shape signals.** `docs/structure.md` is not one of them: the installer owns it and rewrites it on every install or refresh, so a missing or hand-edited `structure.md` means the harness needs refreshing (`npx @nurix/etna`), never a scaffold from a template — and its body is never converged, only its `harness-version` field stamped. Every **folder** in this tree is created on first use and is simply absent until it holds a file; git cannot track an empty directory, so a missing folder is never evidence of drift and is never scaffolded to satisfy the shape. Its role is already in `docs/structure.md`; a repo's own notes about legacy folders go in `docs/README.md` § Notes for this repository.
|
|
160
158
|
|
|
161
159
|
There is **no `docs/routing.md`**, **no `docs/modules/{m}/`**, **no `docs/pillars/`**, **no `docs/boundaries/`**. Code ownership lives in feature `owns:` frontmatter; a module is a `module:` label, not a folder; boundaries are diagnosed from source; brainstorm records live in `docs/research/` (active) and `docs/history/brainstorms/` (harvested).
|
|
162
160
|
|
|
@@ -192,7 +190,7 @@ B2 folds artifacts whose **shape dissolved** — a file in the wrong place or th
|
|
|
192
190
|
|
|
193
191
|
| Nature | Genres | Treatment |
|
|
194
192
|
| --- | --- | --- |
|
|
195
|
-
| **Truth document** | features, ux, architecture, operations, `docs/tests/` checklists, `structure.md`,
|
|
193
|
+
| **Truth document** | features, ux, architecture, operations, `docs/tests/` checklists, READMEs (never `structure.md`, which the installer owns) | **Converge in place.** These state what is true now, so rewriting them to the current schema is not revision, it is the genre working as designed. Add missing frontmatter keys, add missing required sections, rename keys the template renamed |
|
|
196
194
|
| **Record** | plans, changelog entries, migration runbooks, brainstorm records | **Never rewritten.** A completed plan and a committed entry are frozen — immutability begins at commit, and a record edited to match a newer schema stops being evidence of what happened. Report non-conformance; repair only the **living index** that points at the record (an absent `docs/history/CHANGELOG.md` row is an index defect, not a record defect, and is backfilled with a note saying so) |
|
|
197
195
|
|
|
198
196
|
**Never invent content to satisfy a field.** A frozen changelog entry missing `Skills:` is missing the *judgement* that field carries, and no later session holds it — writing one is fabrication wearing a schema's clothes. Report it, backlog the pattern if it recurs, and leave the entry alone. The same restraint applies to a truth document: a genre's new section that needs knowledge the repo does not contain is raised as a question, not filled with plausible prose.
|
|
@@ -203,9 +201,9 @@ B2 folds artifacts whose **shape dissolved** — a file in the wrong place or th
|
|
|
203
201
|
|
|
204
202
|
Table: `| File | Action | From | To | Reason |` (actions: `Move`, `Merge into {target}`, `Delete`, `Keep`, `Create`, `Fold`). For a fresh baseline this is mostly `Create`; for an upgrade it is mostly `Fold`/`Move`. Ask once: **"Approve this reconcile?"** — you own this interaction (the `documentation` skill is a library and has none).
|
|
205
203
|
|
|
206
|
-
On approval, execute: create the folder structure; move/fold/merge/delete per the plan; apply B2b's schema convergences to the truth documents (records are reported, never rewritten); add `Status:` to plan files; for each feature doc, derive and write its `owns:` globs (+ `module:` label + `
|
|
204
|
+
On approval, execute: create the folder structure; move/fold/merge/delete per the plan; apply B2b's schema convergences to the truth documents (records are reported, never rewritten); add `Status:` to plan files; for each feature doc, derive and write its `owns:` globs (+ `module:` label + `objects:`) from the source it describes, and each checklist's `verifies:` edge, by calling the `documentation` skill's **frontmatter derivation**; merge scattered backlogs into `docs/history/backlog.md`; fix links broken by moves.
|
|
207
205
|
|
|
208
|
-
Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates: `docs/
|
|
206
|
+
Scaffold missing mandated files **by calling the `documentation` skill for each template** — you orchestrate, the skill supplies templates: `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/main.md`, `docs/operations/setup.md` (when the repo has a lockfile and a runnable root script; **never a second first-run doc** — propose a rename with a `note:` row if one exists under another name), and the repo-root `README.md` (an outward opening in a user's terms from the charter and vision documents, then orientation and routing filled from the manifests, the ownership index and the root scripts — **never overwrite an existing root README**).
|
|
209
207
|
|
|
210
208
|
### Step B4 — Stamp the version
|
|
211
209
|
|
|
@@ -237,7 +235,7 @@ Apply the **§ Strategy memory** retirement procedure to `docs/memory/maintenanc
|
|
|
237
235
|
- **Enforce the memory cap on every run** (§ Strategy memory) — you are its only writer, so no one else can do it.
|
|
238
236
|
- **A clean report is valid** — do not invent issues.
|
|
239
237
|
- **Declarative, idempotent.** Re-running baseline mode on a current repo reshapes nothing — a second pass is just the audit plus the module proposal. Converge to the current shape; never replay a version ladder; never reconstruct a past shape.
|
|
240
|
-
- **Brownfield extraction (operator-ruled 2026-08-19).** When baseline mode meets a repo with a real source tree and few or no feature docs, the module *proposal* is not enough — run the extraction pass: produce feature docs for the recognized modules (docs/features/, full frontmatter: `
|
|
238
|
+
- **Brownfield extraction (operator-ruled 2026-08-19).** When baseline mode meets a repo with a real source tree and few or no feature docs, the module *proposal* is not enough — run the extraction pass: produce feature docs for the recognized modules (docs/features/, full frontmatter: `objects:` · `owns:` · `module:` · `status:` · `last-reviewed:` · `type: feature` · `derivation: "extracted (baseline YYYY-MM-DD, nustack graph + source read)"`), plus the architecture, tests, and operations layers. Use the `nustack-graph` skill where installed — localize through the index before reading; the docs record intent, the index answers facts. **Every extracted feature doc carries a `## History & Ownership` section** — top contributors with recency, churn posture, and bus-factor notes, dated "as of YYYY-MM-DD" (operator ruling: this section is mandatory in extraction output even though doc-lint flags dated narrative in truth docs; the findings are accepted for now, and a future harness version may retire the section in favor of live index pointers). `status:` is evidence-graded: `deprecated` only when history shows the area dead, never by guess. Scale by fan-out (one extraction lane per module, a completeness critic over the result) rather than one long cold read.
|
|
241
239
|
- **Diagrams ride the baseline (operator-ruled 2026-08-24).** Whenever baseline mode produces or converges the architecture layer, draw two ASCII diagrams from the real source, each in its own fenced code block: (1) an **architecture diagram** in the system-design/architecture doc — the actual processes, entry points, and wire surfaces as boxes, the calls/queues/files between them as labelled arrows; (2) a **DB ER diagram** wherever the repo declares a relational schema (DDL, migrations, an ORM schema) — one box per table listing its key columns, FK edges drawn to the table they reference, cardinality on the edge; it lands in the domain-model doc, or `docs/architecture/data-model.md` when none exists. Box-drawing characters (`┌─┐│└┘├┤`), width ≤ 100 columns. Derived only from what the code declares — a diagram never invents a component the source does not show, and a repo with no relational schema gets **no** ER diagram rather than an imagined one. Diagrams are truth-document sections: later baselines and audits converge them in place like any other section.
|
|
242
240
|
- **Tool tiers.** The SessionStart context names each manifest-declared tool with its tier; calibrate the run to it, never stall on it. **Present-fresh** (`Tool: nustack 0.9.0`): use it — localize every question through `nustack graph` before reading source, and never run an index step first: the family re-indexes a stale store before it answers, so the only freshness decision left is the deliberate `--no-refresh`. **Present-stale** (below the catalog minimum): still use it, but note the version gap and the upgrade command in the run report — a stale contract may lack answer shapes the skill assumes. **Absent** (`Tool: nustack MISSING`): fall back to the cold method (Glob/Grep/read), state in the run report that the tool was absent and give the install command — degraded output is acceptable, silent degradation is not.
|
|
243
241
|
- **One sentinel.** `docs/structure.md` `harness-version` is the only baseline/version marker.
|
|
@@ -1,74 +1,136 @@
|
|
|
1
|
-
# Documentation Structure
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
1
|
+
# Documentation Structure — Authority Map
|
|
2
|
+
|
|
3
|
+
This file is the authority on **what belongs where** in `docs/`: the folder map, naming, lifecycle, the doctrine every genre follows, and the decision table for adding a doc. Read it before adding or moving any documentation. Start reading from [`README.md`](README.md).
|
|
4
|
+
|
|
5
|
+
**This file is the harness's, not the project's.** The installer writes it on every install and refresh, so nothing in it describes one repository: a folder a repo does not use is simply absent on disk, and a repo's own notes — legacy folders kept as provenance, retired genres, local exceptions — live in [`README.md`](README.md) § Notes for this repository, never here. Hand edits are overwritten on the next refresh. The one field written in place is `harness-version` in the frontmatter, stamped by the `maintenance` agent after its baseline reconcile; its absence is what tells a session the repo has not been baselined against the installed harness.
|
|
6
|
+
|
|
7
|
+
One canonical source per topic — link, don't copy. Only `CLAUDE.md`, `AGENTS.md`, and `README.md` live at the repo root.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Folder map
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
docs/
|
|
15
|
+
├── README.md # Documentation root — the product in a paragraph, what each folder holds, and the repo's
|
|
16
|
+
│ # own notes. Describes directories, never files or a tree — `ls` is the roster
|
|
17
|
+
├── structure.md # This file — harness-owned authority map; `harness-version` stamped after baseline
|
|
18
|
+
├── architecture/ # The design layer, in four folders; Readme.md is its summary and names folders only
|
|
19
|
+
│ ├── packages/ # One `{package}.md` per project package: what it is, how it behaves. Carries
|
|
20
|
+
│ │ # `owns:` over `packages/<pkg>/**` RESIDUALLY — whatever no system or feature doc claims
|
|
21
|
+
│ ├── systems/ # One `{machine}.md` per machine spanning packages. Carries `owns:` over its
|
|
22
|
+
│ │ # subtrees; more specific than a package's glob
|
|
23
|
+
│ ├── common/ # The enterprise plane — one `{concern}.md` per concern the platform handles
|
|
24
|
+
│ │ # the same way everywhere. Owns no code
|
|
25
|
+
│ └── decisions/ # ADs — `AD-NNN-{slug}.md`, one per subject, updated in place; the journey lives in
|
|
26
|
+
│ # each file's Decision Changelog tail. Readme.md is the register: the current
|
|
27
|
+
│ # decision per subject and whether it is built
|
|
28
|
+
├── features/ # Feature docs — `{feature}.md`, one per thing a person points at (an address, a command
|
|
29
|
+
│ # family, a named control), cut by its objects (flat, no subfolders). One of three owning genres, beside
|
|
30
|
+
│ # `architecture/packages/` and `architecture/systems/`; ownership is `owns:` frontmatter
|
|
31
|
+
├── acceptance/ # Acceptance criteria — `{capability}.md`, stable `AC-n` assert lines. Owns no code
|
|
32
|
+
├── operations/ # Procedures — `setup.md` (the one-time first run, incl. the stack), then development, deployment, signing, rotation, diagnostics;
|
|
33
|
+
│ │ # one topic-named `{procedure}.md` each. Also holds bookkeeping.md, the shared
|
|
34
|
+
│ │ # doc-sync work queue (hook-appended, bookkeeper-drained, a drained row deleted)
|
|
35
|
+
│ ├── release-notes/ # One operator-facing note per release (`YYYY-MM-DD-vX.Y.Z.md`); its README.md indexes them
|
|
36
|
+
│ ├── issues/ # Local-tracker issue records (`type: issue`, `YYYY-MM-DD-{slug}.md`) — the
|
|
37
|
+
│ │ # `issue-bridge` skill's local pack; `status:` is the lifecycle
|
|
38
|
+
│ └── triage/ # Triage dossiers (`type: triage`, `YYYY-MM-DD-{slug}.md`) — one per investigated
|
|
39
|
+
│ # issue, written by the `issue-bridge` skill; owns no code, never a feature doc
|
|
40
|
+
├── tests/ # Behavioral test checklists (truth docs) — `{feature}.md`, step → **Assert**, named for
|
|
41
|
+
│ # the doc whose promises it proves. `ls docs/tests/` is the roster
|
|
42
|
+
├── research/ # Records — in-progress brainstorm sessions (`{topic}-brainstorm/`), standing-research
|
|
43
|
+
│ # folders (`{topic}/`) and loose standing-research notes (`{topic}.md`). Readme.md is the index
|
|
44
|
+
├── history/
|
|
45
|
+
│ ├── CHANGELOG.md # Master changelog index
|
|
46
|
+
│ ├── changelog/ # Individual changelog entries, `YYYY-MM-DD-{three-words}.md` (frozen at commit)
|
|
47
|
+
│ ├── plans/ # Dated implementation plans, `YYYY-MM-DD-{slug}.md` (Status: field; Complete/Abandoned = frozen)
|
|
48
|
+
│ ├── migrations/ # One-shot migration runbooks, `YYYY-MM-DD-{slug}.md` — authored ahead, outcome-stamped, frozen
|
|
49
|
+
│ ├── brainstorms/ # Harvested brainstorm sessions (`{topic}/`), kept as provenance; Readme.md is the index
|
|
50
|
+
│ ├── research/ # Deep-research records (`{topic}/` — README.md synthesis + findings.md + sources.md).
|
|
51
|
+
│ │ # Frozen, cited, owns no code. Distinct from research/ at the docs root
|
|
52
|
+
│ ├── health-log.md # The maintenance agent's append-only pass record, one generated row per pass
|
|
53
|
+
│ ├── journal.md # Append-only mid-execution knowledge capture, one line per fact; a line resolves by
|
|
54
|
+
│ │ # landing in its owning doc (delete the row, cite it in the changelog entry)
|
|
55
|
+
│ └── backlog.md # Tracked work items by priority (P0–P3)
|
|
56
|
+
└── memory/ # Project knowledge + per-agent strategy memory
|
|
57
|
+
├── main.md # Main-agent project memory
|
|
58
|
+
└── {agent}.md # One strategy-memory file per sub-agent that keeps one
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Doctrine every genre follows
|
|
62
|
+
|
|
63
|
+
- **`docs/architecture/`** is the design layer in four folders: **`packages/`** (one per project package — what it is and how it behaves), **`systems/`** (one per machine spanning packages), **`common/`** (the enterprise plane) and **`decisions/`** (the ADs, one per subject, updated in place, each journey confined to that file's Decision Changelog tail).
|
|
64
|
+
**`common/` and `decisions/` own no code; `packages/` and `systems/` do.** Ownership is a frontmatter fact, not a folder fact: it is the union of every `owns:` glob in `features/`, `architecture/packages/` and `architecture/systems/`, and the more specific glob wins — a feature's beats a system's, a system's beats a package's. **A package document is the residual owner of its tree**, so a package's exhaustive behavior spec is that document, not a feature doc.
|
|
65
|
+
**What earns which genre.** A project package earns a `packages/` document — one, always. A machine whose parts sit in several packages, which a reader asks about as one thing, earns a `systems/` document. A **feature** document exists for something a person points at — an address, a command family, a named control — and is cut by the objects it designs, never by the code's routers, tables, plans or packages; a machine nobody navigates to is a `systems/` document even when it owns tables, and a fragment whose central object is declared in a sibling merges into it. A concern handled the same way everywhere is `common/` and owns nothing — including the governing-decisions register (fixed product decisions `F-###`, baseline defaults `B-###`, external boundaries, out-of-scope), which is authored doctrine the `boundary` skill never persists to.
|
|
66
|
+
- **`history/research/` is not legacy — it is the installed deep-research genre**, one `{topic}/` folder per research pass in the three-file shape. A record is frozen and cited, owns no code, and is never edited to stay current; a new question gets a new topic folder. Entries that predate the three-file convention — a single file or a single-report folder — are kept as authored.
|
|
67
|
+
- **`docs/features/` is flat — every feature authority is a file, and no subfolder exists.** A subject too large for one file is two files, not a folder: the `owns:` frontmatter already states authority, and a nested doc is one the ownership scan and the index rows reach last.
|
|
68
|
+
- **`docs/research/`** holds records, not authorities: its standing-research folders and loose notes ground plans and decisions, and its `Readme.md` lists every folder so the `brainstorm` skill reads it instead of scanning.
|
|
69
|
+
- **`docs/tests/`** holds behavioral test checklists — one `{feature}.md` per surface, written as `- [ ] step` → `- [ ] **Assert**` (how to verify a feature's promised behavior). A checklist is written or updated **at the verification gate, before the driving** — it is the script the real surface is driven against and the menu the pinned suite tests are drawn from, so each behavior section closes with a `> Pinned:` line naming the test that guards it, `driven only` with the reason, or `none yet` with the test it owes. **No section carries a date** — the *event* of driving (its date, environment, evidence, a `FAIL` and the backlog item it raised) belongs to the changelog entry of the unit that drove it. A section a drive cannot reach says `not reachable — {what blocks it}` on its trace line until the blocker is gone. **The gate that drives a checklist maintains it** — retiring dead sections and repairing traces is part of the run, because a checklist owns no code and no ownership glob implicates it. The cross-system testing strategy is doctrine in `architecture/common/`. A checklist carries `type: checklist` plus `verifies:`, the doc(s) whose promises it proves; a target is legitimately a feature, a package or a system document, and several values are correct where one checklist proves promises two docs decide.
|
|
70
|
+
**`verifies:` is the load-bearing key, and the filename convention is not a substitute for it.** A same-named file is a coincidence no resolver can trust — it breaks the moment a checklist spans two docs or a feature is renamed. The inverse — which checklists cover a feature — is **generated, never listed in the feature doc**.
|
|
71
|
+
- **`docs/operations/bookkeeping.md`** is the shared doc-sync work queue — hooks append rows, the `bookkeeper` agent drains them, and the commit wall blocks while rows remain. It is **author-created, never scaffolded**, and its rows are **live work, never drift**: a drained row is deleted, so a fully drained file holds no rows at all. Read a waiver's referent before deleting it; deleting the record while the condition survives re-appends the finding as an `auto:` row that fails the wall the waiver passed.
|
|
72
|
+
- **`type:` is a required frontmatter key** on every doc that carries frontmatter — the genre stamp, its enum being the `documentation` skill's template names (`feature`, `architecture-decision`, `project-memory`, `ux`, `acceptance-criteria`, …). It is tooling metadata like `last-reviewed:` and `status:`: external tooling reads it, sessions **preserve it on edits** and never narrate it in the body. The `maintenance` agent stamps it on docs that lack it.
|
|
73
|
+
**No genre is frontmatter-less by policy; the gaps are the templates.** `architecture/common/**` carries `type: doctrine` with `status:` and `objects:` and no `owns:`, from the documentation skill's doctrine template. `architecture/Readme.md` carries no block, because its template ships none and a block is never manufactured on a doc whose template has none. `architecture/packages/**` and `architecture/systems/**` carry `type: package` / `type: system` with `objects:`, `owns:`, `status:` and optional `applies:`, because those genres own code and the ownership scan reads frontmatter. The `operations/` procedures carry a hand-authored `type: operations` block; the bookkeeping queue carries none. Docs written by a skill that ships a block (`issue-bridge`'s `type: issue` / `type: triage`) carry it.
|
|
74
|
+
- **The docs tree is a graph, and every edge is declared at the consuming end.** Three frontmatter keys carry it: `owns:` (doc → code), **`verifies:`** (checklist → the doc whose promises it proves), and **`applies:`** (a feature, package or system doc → the doctrine it is *bound by* — an obligation, deliberately not a bibliography, so a key that collected everything consulted would stop meaning anything). Every inverse is **generated** — `buildEdgeIndex()` in `.claude/hooks/lib/ownership.mjs`, injected at SessionStart beside the ownership index — and authoring one by hand is a defect: a parent that hand-lists its children doubles the staleness surface instead of halving it. `check-ownership` fails on an edge naming a doc that does not exist, waivable as `dangling-edge`. **`applies:` is reported, never inferred** — an obligation is an assertion only the consuming doc's author can make.
|
|
75
|
+
- **`docs/acceptance/` holds the acceptance-criteria genre** — one `kebab-case.md` per capability, written at specification time, before implementation, holding stable `AC-n` assert lines that verification surfaces parse as claims to grade the built product against; each file is keyed to the checklist sections that grade it. The folder is created on first use and never scaffolded. The `AC-n:` line grammar is load-bearing: the key sits at line start, exactly `AC-<number>:`, followed by the assert sentence — tables, emphasis-wrapped keys, and nested bullets break the parse.
|
|
76
|
+
- **The `ux` genre decides observable behavior; `docs/tests/` only verifies it.** A feature doc states what a feature is and which contracts it honours — all of which stay plausibly true through a rewrite of the surface — so a UX-behavior doc states what a person *observes*, and is written **before** the code. This repo holds no standalone `ux` document: what a person observes on a surface is a section of the feature doc that owns that surface's components and wire. A surface needing the genre gets `features/{surface}-ux.md` with real `owns:` over its unclaimed component globs — an `owns: []` doc nothing implicates is one no change reaches.
|
|
77
|
+
- **`docs/history/journal.md` is the temporary lane, and `docs/memory/` is not.** The journal holds mid-execution facts one line each, each resolved by landing in its owning doc; memory holds only per-agent strategy and project knowledge no single doc owns. A fact an owning doc will eventually carry goes to the journal, never to memory — memory has no drain, so what lands there stays until somebody distils it.
|
|
78
|
+
- **There is no `docs/history/sessions/`.** Per-session gate logs are machine-local, written by `.claude/hooks/lib/session-log.mjs` into `.claude/state/sessions/` (self-ignored), so they never enter `docs/` or git. A `docs/history/sessions/` folder is residue, not shape.
|
|
79
|
+
- **The repo-root `README.md` opens outward and turns inward.** What the product does, for whom and where it runs, in a user's terms; then, for the team and agents, how it works, a Map of top-level units with their owning doc, the rules that bite, where to go by intent, and at most four everyday commands. It carries no install, stack or tree — install and stack are `operations/setup.md`, the tree is this file's. Template: the `documentation` skill's `templates/root-readme.md`.
|
|
80
|
+
- **`docs/README.md` describes directories, never files.** One entry per folder: what it holds, who reads it, how its files are named — no per-file rows, no tree. It closes with the repository's own notes, the one place project-specific placement facts live.
|
|
81
|
+
- **`operations/setup.md` is the one first-run document**, fixed name, one per repo: stack by layer naming the pinning file, prerequisites, install, env files, first run, verification, failures by exact error text. Every other procedure is topic-named and recurring.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Lifecycle
|
|
86
|
+
|
|
87
|
+
- **Plans** (`history/plans/YYYY-MM-DD-{slug}.md`) carry a `Status:` field (`Draft` / `Ready` / `Active` / `Executed` / `Complete` / `Abandoned`). Once `Complete`/`Abandoned`, a plan is frozen — never edited; scope changes get a new dated plan that links back.
|
|
88
|
+
- **Migration runbooks** (`history/migrations/YYYY-MM-DD-{slug}.md`) are authored ahead of execution and record a one-shot infra/cutover procedure; once executed, the outcome is stamped into the file and it is frozen — a re-run gets a new dated runbook.
|
|
89
|
+
- **Changelog** entries land in `history/changelog/` and are indexed in `history/CHANGELOG.md`.
|
|
90
|
+
- **Backlog** items live in `history/backlog.md` under P0–P3 priorities (living, append-only).
|
|
91
|
+
- **Brainstorm sessions** are author-created by the `brainstorm` skill: an active session at `docs/research/{topic}-brainstorm/` (older folders carry the legacy `-brainstorming/` suffix; both are canonical), moved to `docs/history/brainstorms/{topic}/` on a passed harvest — the move is the completion marker, and the moved folder's fate (delete or commit) is the author's call. Never scaffolded empty; each folder carries a `Readme.md` index.
|
|
92
|
+
- **Source-of-truth audits** write nothing to `docs/`. The `polygraph` skill runs in two modes — **audit** on a named target (a doc, a feature, a folder, a code path) and **gate** at plan completion — and both keep their rows under `.claude/state/polygraph/{run}/`, machine-local, never tracked, deleted in the same turn as the report. What survives a run is the corrected document itself, the backlog rows it registered, and the plan's `Polygraph:` segment. Folders an earlier audit mode left behind are provenance a repo lists in its `README.md` notes, never a place anything writes.
|
|
93
|
+
- **Boundaries** are a plan-time diagnostic — the `boundary` skill reads contracts fresh from source; there is no persisted `boundaries/` tree.
|
|
94
|
+
- **Modules** are _declared labels_ (a `module:` key on a feature doc), never inferred from physical layout and never a folder. A feature always lives flat in `features/`.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Add-a-doc decision table
|
|
99
|
+
|
|
100
|
+
| You are adding… | It goes in… | Needs frontmatter? |
|
|
101
|
+
| --- | --- | --- |
|
|
102
|
+
| A feature document — something a person points at (an address, a command family, a named control), cut by the objects it designs | `features/` (flat) | Yes — `objects:`, `owns:`, `status:`, `type: feature` (+ optional `module:`, `applies:`, `last-reviewed:`) |
|
|
103
|
+
| A package's behavior document | `architecture/packages/<package>.md`, one per package | Yes — `type: package`, `objects:`, `owns:` (its tree, residually), `status:`, optional `applies:` |
|
|
104
|
+
| A system's behavior document | `architecture/systems/{system}.md`, one per machine | Yes — `type: system`, `objects:`, `owns:` (the machine's subtrees), `status:`, optional `applies:` |
|
|
105
|
+
| Cross-cutting design / steering | `architecture/common/` | No |
|
|
106
|
+
| An Architecture Decision (AD) | `architecture/decisions/` — one file per subject, updated in place; the journey lives in that file's Decision Changelog | Yes — `type: architecture-decision` (+ `title:`, `status:`, `created:`, `last-updated:`, `decision-owner:`, `tags:`) |
|
|
107
|
+
| One-time machine setup, first run, stack, prerequisites, env files | `operations/setup.md` — fixed name, one per repo, linked from the root README; a diverging package gets a `### {unit}` subsection, never a second first-run doc | Yes — `type: operations` |
|
|
108
|
+
| A recurring procedure (develop, deploy, rotate, diagnose, CI) | `operations/{procedure}.md` | Yes — `type: operations` |
|
|
109
|
+
| A tracker issue held in the repo | `operations/issues/YYYY-MM-DD-{slug}.md` (via the `issue-bridge` skill's local pack) | Yes — `type: issue`, `id:`, `status:`, `labels:`, `author:`, `created:`, `github:` |
|
|
110
|
+
| A triage dossier for an investigated issue | `operations/triage/YYYY-MM-DD-{slug}.md` (via the `issue-bridge` skill) | Yes — `type: triage`, `tracker:`, `issue:`, `date:`, `confidence:`. A dated working artifact: it never claims `owns:` and never masquerades as a feature doc |
|
|
111
|
+
| A behavioral test checklist | `tests/{feature}.md` | Yes — `type: checklist`, `verifies:` (the doc(s) whose promises it proves; several values are legitimate). No `owns:` — it owns no code. Truth doc, present-tense; written at the verification gate before the driving, each section carrying a `Pinned:` trace |
|
|
112
|
+
| What a person sees and can do on a surface (UX behavior) | `features/{surface}-ux.md` with `owns:` over that surface's unclaimed component globs; a section of the owning feature doc where the surface has one owner; `architecture/common/` when it is cross-cutting | Yes — `type: ux` (+ the feature-doc keys when it lives in `features/`) |
|
|
113
|
+
| Acceptance criteria for one capability | `acceptance/{capability}.md` — stable `AC-n` assert lines verification surfaces parse as claims; keys are never renumbered or reused, a retired criterion is marked retired in place | Yes — `type: acceptance-criteria`, `status:`; no `owns:` (owns no code) |
|
|
114
|
+
| An in-progress brainstorm session | `research/{topic}-brainstorm/` (via the `brainstorm` skill) | No |
|
|
115
|
+
| A source-of-truth audit | Nowhere in `docs/` — the `polygraph` skill (audit mode) corrects the target doc in place and keeps its rows under `.claude/state/polygraph/{run}/`, deleted with the report | No |
|
|
116
|
+
| An implementation plan | `history/plans/YYYY-MM-DD-{slug}.md` | No (but `Status:` required) |
|
|
117
|
+
| A one-shot migration runbook | `history/migrations/YYYY-MM-DD-{slug}.md` | No (authored ahead; outcome-stamped and frozen once executed) |
|
|
118
|
+
| A deep-research record | `history/research/{topic}/` — `README.md` synthesis + `findings.md` + `sources.md`; frozen and cited, owns no code, never edited to stay current (a new question gets a new topic folder) | No |
|
|
119
|
+
| A harvested brainstorm session | `history/brainstorms/{topic}/` (via the `brainstorm` skill's harvest) | No |
|
|
120
|
+
| A changelog entry | `history/changelog/` + index in `CHANGELOG.md` | No |
|
|
121
|
+
| A tracked work item | `history/backlog.md` | No |
|
|
122
|
+
| A doc-sync debt row | `operations/bookkeeping.md` (hook-appended; drained by the `bookkeeper` agent, deleted on drain) | No |
|
|
123
|
+
| A mid-execution fact worth keeping | `history/journal.md` (append-only; resolves by landing in its owning doc) | No |
|
|
124
|
+
| Agent strategy / project memory | `memory/` | Yes — `type: project-memory` on `main.md` |
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Harness version
|
|
129
|
+
|
|
130
|
+
`harness-version` in this file's frontmatter is the **single** baseline/version sentinel for a repo — the semver of the installed harness (`.claude/harness.json`) the `docs/` tree was last reconciled to. The installer ships this file without the field; the `maintenance` agent (baseline mode) stamps it after reconciling the tree, and a session whose installed version is ahead of the stamp — or that finds no stamp — dispatches that agent before anything else. There is no second marker.
|
|
131
|
+
|
|
132
|
+
---
|
|
69
133
|
|
|
70
134
|
## Health Log
|
|
71
135
|
|
|
72
|
-
|
|
73
|
-
| Date | Review Summary |
|
|
74
|
-
| ---- | -------------- |
|
|
136
|
+
The `maintenance` agent appends its pass record to [`history/health-log.md`](history/health-log.md) — an append-only record, kept out of this file, which it never otherwise edits.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "code",
|
|
3
3
|
"name": "code",
|
|
4
|
-
"version": "3.19.
|
|
4
|
+
"version": "3.19.4",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
8
|
-
".vscode/settings.json"
|
|
8
|
+
".vscode/settings.json",
|
|
9
|
+
"docs/structure.md"
|
|
9
10
|
],
|
|
10
11
|
"seeds": [
|
|
11
12
|
"docs/README.md",
|
|
12
|
-
"docs/structure.md",
|
|
13
13
|
"docs/history/CHANGELOG.md",
|
|
14
14
|
"docs/history/backlog.md",
|
|
15
15
|
"docs/memory/main.md",
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
}
|
|
26
26
|
],
|
|
27
27
|
"docsRoot": "docs",
|
|
28
|
-
"digest": "
|
|
28
|
+
"digest": "f3f36722fca1"
|
|
29
29
|
}
|
|
@@ -360,16 +360,6 @@ function detectorForFile(projectDir, rel, meta, rows) {
|
|
|
360
360
|
);
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
|
-
if (rel.startsWith(`${root}/features/`) && !readSafe(path.join(projectDir, root, "README.md")).includes(path.basename(rel))) {
|
|
364
|
-
rows.push(
|
|
365
|
-
formatAutoRow({
|
|
366
|
-
...meta,
|
|
367
|
-
kind: "index-row-missing",
|
|
368
|
-
description: `${rel} is not linked from ${root}/README.md`,
|
|
369
|
-
action: "add its row to the Features index",
|
|
370
|
-
})
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
363
|
return;
|
|
374
364
|
}
|
|
375
365
|
|
|
@@ -130,7 +130,7 @@ export function isOwningDocPath(projectDir, relPath) {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
// Scan the docs tree and return one entry per document that declares owns:.
|
|
133
|
-
// Shape: { doc (repo-relative, /-separated), owns[], module, keywords[], status }.
|
|
133
|
+
// Shape: { doc (repo-relative, /-separated), owns[], module, objects[], keywords[] (legacy, read only as a fallback), status }.
|
|
134
134
|
//
|
|
135
135
|
// OWNERSHIP IS A FRONTMATTER FACT, NOT A FOLDER FACT. This scanned `docs/features/` alone, which
|
|
136
136
|
// silently un-owned every path claimed by a genre living elsewhere — a `type: package` doc under
|
|
@@ -163,6 +163,7 @@ export function scanOwningDocs(projectDir) {
|
|
|
163
163
|
owns,
|
|
164
164
|
module: (field(block, "module") || "—").toString(),
|
|
165
165
|
keywords: asList(field(block, "keywords")),
|
|
166
|
+
objects: asList(field(block, "objects")),
|
|
166
167
|
status: (field(block, "status") || "active").toString().toLowerCase(),
|
|
167
168
|
});
|
|
168
169
|
}
|
|
@@ -194,7 +195,8 @@ export function buildIndex(projectDir) {
|
|
|
194
195
|
// of its globs makes the index grow with the dependency graph rather than the doc count: on a
|
|
195
196
|
// 42-keyword doc owning 15 paths the same 42 facts were repeated 15 times, and keywords
|
|
196
197
|
// outweighed the glob paths — the only part that routes — by more than four to one.
|
|
197
|
-
const
|
|
198
|
+
const terms = entry.objects.length ? entry.objects : entry.keywords;
|
|
199
|
+
const kw = terms.length ? `[${terms.join(", ")}]` : "[]";
|
|
198
200
|
lines.push(
|
|
199
201
|
`${entry.doc} · ${entry.module} · ${entry.status}\n ${kw}\n` +
|
|
200
202
|
entry.owns.map((glob) => ` ${glob}`).join("\n")
|
|
@@ -49,7 +49,7 @@ export function sourceLint(projectDir, rel) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// Verifier keys the detector no longer emits — swept when machine-raised, never taught to authors.
|
|
52
|
-
export const RETIRED_KINDS = ["doc-placement", "boundary-scan-suggested"];
|
|
52
|
+
export const RETIRED_KINDS = ["doc-placement", "boundary-scan-suggested", "index-row-missing"];
|
|
53
53
|
|
|
54
54
|
export const ROW_VERIFIERS = {
|
|
55
55
|
// "<rel> lacks its file-path header comment" — dead once the header is there (or the file is gone).
|
|
@@ -140,13 +140,9 @@ export const ROW_VERIFIERS = {
|
|
|
140
140
|
return docLint(projectDir, m[1]).length === 0;
|
|
141
141
|
},
|
|
142
142
|
|
|
143
|
-
// "<rel> is not linked from docs/README.md" —
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!m) return false;
|
|
147
|
-
if (!fs.existsSync(path.join(projectDir, m[1]))) return true;
|
|
148
|
-
return readSafe(path.join(projectDir, docsRoot(projectDir), "README.md")).includes(path.basename(m[1]));
|
|
149
|
-
},
|
|
143
|
+
// "<rel> is not linked from docs/README.md" — retired: an index names folders, never files
|
|
144
|
+
// (the documentation skill § Indexes name folders, never files), so nothing raises it.
|
|
145
|
+
"index-row-missing": (projectDir, body, ctx, row) => row.kind === "auto",
|
|
150
146
|
|
|
151
147
|
// "<rel> declares `<name>` (package-rejected)" — dead once the manifest drops the package
|
|
152
148
|
// or the table stops rejecting it.
|