Docs hygiene: enforce in /alignment, add eng-council Documentation seat and beyond-scope notes

This commit is contained in:
2026-06-14 23:57:39 +03:00
parent 6fc8c29b50
commit de9dbf3ec8
3 changed files with 79 additions and 28 deletions
+22 -3
View File
@@ -126,9 +126,28 @@ Review all changes in scope. If changes span multiple patterns below, apply all
apply migrations; destructive actions (delete, revert, reset) confirm; storage failures apply migrations; destructive actions (delete, revert, reset) confirm; storage failures
warn rather than silently lose data. warn rather than silently lose data.
13. **Self-containment**: documentation and comments must not add pointers that require an 13. **Documentation hygiene** (the docs are maintained artifacts; keep them at altitude):
external repository to follow. Knowledge gets captured locally (`docs/spec/`, - **Self-containment**: documentation and comments must not add pointers that require an
`docs/architecture/`), not linked out. external repository to follow. Knowledge gets captured locally (`docs/spec/`,
`docs/architecture/`), not linked out.
- **Matter-of-fact, as rule #6 demands of comments**: docs state _what the design is_ +
the standing _why_, never the build narration (`this bit us`, `we chose X over Y`,
`resolves the former divergence`, `council resolution recorded`). A decision is recorded
by stating its resulting rule, not the story of reaching it.
- **No stale-prone constructs** — three things rot the moment the code moves:
- **TS code blocks that copy current implementation.** A snippet mirroring a real
module goes stale on its next rename. An illustrative _shape_ sketch is fine; a copy
of specific current code is a finding — replace it with a navigation map (`file →
role`) or the rule it demonstrates.
- **Positional sub-section cross-refs.** Cite a doc by a stable identifier — the file
(`spec §07`, `arch 02`) or a named section / quoted rule — never a positional
sub-section number (`arch 07 §4`) that renumbers when a section is inserted above it.
Applies to code comments too.
- **Volatile exact counts.** Test counts, file/LOC counts, and one-off timings churn
daily and read as stale within a week. State the qualitative fact ("seconds of layout
on a large dataset"), not the measured number. The only homes for exact figures are
`docs/exploration/` records (frozen by definition) and `docs/codebase-metrics.md` (the
deliberately-tracked trend).
14. **User-facing copy**: keep user-visible strings centralized and written for users (sentence 14. **User-facing copy**: keep user-visible strings centralized and written for users (sentence
case, active voice, no "please", no exclamation marks in errors). If/when an i18n layer case, active voice, no "please", no exclamation marks in errors). If/when an i18n layer
+7
View File
@@ -108,6 +108,13 @@ or a major new section was added that should be discoverable. Not for minor addi
- **Code walkthroughs**: prose that restates the code; goes stale on any rename. (Navigation - **Code walkthroughs**: prose that restates the code; goes stale on any rename. (Navigation
maps that list file roles are fine.) maps that list file roles are fine.)
- **TS code blocks that copy current implementation**: a snippet mirroring a real module
rots on its next rename. An illustrative _shape_ sketch is fine; for real code, point to
the file (navigation map) or state the rule it demonstrates.
- **Stale-prone references**: positional sub-section cross-refs (`arch 07 §4` renumbers when
a section is inserted — cite the file `arch 07` or a named section) and exact counts
(test/file/LOC counts, one-off timings — state the qualitative fact; `codebase-metrics.md`
owns the tracked numbers).
- **Obvious-from-code patterns**: if reading the file makes it clear, don't add docs. - **Obvious-from-code patterns**: if reading the file makes it clear, don't add docs.
- **Session-specific context**: current task details, debugging steps taken. - **Session-specific context**: current task details, debugging steps taken.
- **Speculative patterns**: only document conventions confirmed across multiple instances. - **Speculative patterns**: only document conventions confirmed across multiple instances.
+50 -25
View File
@@ -1,6 +1,6 @@
--- ---
name: eng-council name: eng-council
description: Convene the engineering council — an evidence-grounded review of codebase structure, consistency, layering altitude, and subtraction (what should be deleted). Modes - whole-codebase sweep (milestone boundary or backfill), refactor review, new-functionality review, and a pre-build consult. Auto-invoke only the consult mode - before introducing a new module/store/modal/service/hook shape, ask the council for the canonical shape and what already exists to reuse. All other modes run on demand. description: Convene the engineering council — an evidence-grounded review of codebase structure, consistency, layering altitude, subtraction (what should be deleted), and documentation altitude. Modes - whole-codebase sweep (milestone boundary or backfill), refactor review, new-functionality review, and a pre-build consult. Auto-invoke only the consult mode - before introducing a new module/store/modal/service/hook shape, ask the council for the canonical shape and what already exists to reuse. All other modes run on demand.
disable-model-invocation: false disable-model-invocation: false
--- ---
@@ -8,9 +8,18 @@ disable-model-invocation: false
The structural counterpart to `/council`. The design council guards what the user sees; The structural counterpart to `/council`. The design council guards what the user sees;
the engineering council guards the shape of the codebase — structure, consistency, the engineering council guards the shape of the codebase — structure, consistency,
altitude, and above all **net growth**. `/alignment` reviews a diff in isolation and can't altitude, documentation, and above all **net growth**. `/alignment` reviews a diff in
see cross-cutting drift: parallel patterns forming, near-duplicate helpers, modules isolation and can't see cross-cutting drift: parallel patterns forming, near-duplicate
outgrowing their responsibility. This skill exists to see that whole picture. helpers, modules outgrowing their responsibility, docs accreting a move-by-move log. This
skill exists to see that whole picture.
**The lens is wider than the diff — on purpose.** `/alignment` stays inside the change and
parks anything else as a `// TODO:`. The engineering council is the opposite: it reviews
the change _from altitude_, and is expected to lift its eyes to what surrounds it and
record improvement opportunities it notices outside the reviewed lines. A review that finds
nothing beyond its own diff has stayed too close to the ground. Those observations are
**noted, not fixed** (see Beyond-scope notes in the report) — surfacing them is the value;
the user triages.
**Seats are evidence lenses, not personas.** The design council works because every seat **Seats are evidence lenses, not personas.** The design council works because every seat
quotes a real corpus. There is no external canon for software structure, so a seat here is quotes a real corpus. There is no external canon for software structure, so a seat here is
@@ -37,14 +46,17 @@ encoded in the report format instead:
Run **sequentially, in this order, in this session** — no subagent fan-out. Later seats Run **sequentially, in this order, in this session** — no subagent fan-out. Later seats
consume earlier findings (Subtraction needs Consistency's verdict on which variant is consume earlier findings (Subtraction needs Consistency's verdict on which variant is
canonical before deciding which duplicate dies). canonical before deciding which duplicate dies; Documentation runs last so it can check the
docs against what the other seats actually found — a doc describing a shape Consistency says
no longer exists is stale).
| Seat | Question | Evidence it gathers | | Seat | Question | Evidence it gathers |
| --------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ----------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Structure** | Is the dependency picture still the documented one? | `npx madge --circular --extensions ts,tsx src` (cycles); `npx madge --json src` for fan-in/fan-out outliers; grep for layer leaks (`docs/architecture/00-overview.md` defines the layers — core imports nothing from app; only infrastructure touches browser APIs). Oversized modules: files ≫ their peers' size doing > 1 job. | | **Structure** | Is the dependency picture still the documented one? | `npx madge --circular --extensions ts,tsx src` (cycles); `npx madge --json src` for fan-in/fan-out outliers; grep for layer leaks (`docs/architecture/00-overview.md` defines the layers — core imports nothing from app; only infrastructure touches browser APIs). Oversized modules: files ≫ their peers' size doing > 1 job. |
| **Consistency** | How many shapes does each _kind_ of thing have? | Line up all instances of a kind (modals, stores, services, hooks, confirm flows, persistence subscribers) side by side. Count distinct shapes; name the canonical one; list divergers. Divergence is only visible in the line-up — never judge an instance alone. | | **Consistency** | How many shapes does each _kind_ of thing have? | Line up all instances of a kind (modals, stores, services, hooks, confirm flows, persistence subscribers) side by side. Count distinct shapes; name the canonical one; list divergers. Divergence is only visible in the line-up — never judge an instance alone. |
| **Altitude** | Is logic at the layer where it's cheapest to test? | Testable logic stuck in components that belongs in `src/core/` or stores (the testing philosophy in `AGENTS.md` is the canon: core hardest, components lightest). Spec operations outside core. Duplicated derivations that should be a store selector. | | **Altitude** | Is logic at the layer where it's cheapest to test? | Testable logic stuck in components that belongs in `src/core/` or stores (the testing philosophy in `AGENTS.md` is the canon: core hardest, components lightest). Spec operations outside core. Duplicated derivations that should be a store selector. |
| **Subtraction** | What can be deleted? | `npx knip` (dead exports, unused files/deps); `npx jscpd src --min-tokens 50` (duplication); grep for abstractions with a single implementation, re-implementations of an existing utility, props/options/branches no caller exercises, spec'd-then-abandoned remnants. Consumes all prior seats' findings. | | **Subtraction** | What can be deleted? | `npx knip` (dead exports, unused files/deps); `npx jscpd src --min-tokens 50` (duplication); grep for abstractions with a single implementation, re-implementations of an existing utility, props/options/branches no caller exercises, spec'd-then-abandoned remnants. Consumes all prior seats' findings. |
| **Documentation** | Do the docs hold a structured general picture, or accrete a move-by-move log? | Doc sizes & growth (`wc -l docs/architecture/*.md`; the `codebase-metrics.md` trend). Grep `docs/` for decision-log narration (`this bit us`, `we chose`/`we decided`, `supersed`, `resolves the former`, `previously`, `council resolution recorded`, one-off measurements) and for per-instance worked examples that re-illustrate a principle already stated generally or restate code. Embedded TS blocks that copy current code (vs. illustrative shape-sketches). Sections > 50 lines (doc-update's own bar). Stale-prone refs: line/file/test counts, positional sub-section cross-refs (`arch 07 §4`) that renumber, one-off timings. **Docs-vs-code drift:** a doc describing a shape the other seats found no longer exists. The bar (from `/doc-update`): docs state _what the design is_ + the standing _why_ at a stable altitude — not how the build arrived there. |
Tool notes: `madge`, `knip`, `jscpd` are **not** project dependencies — run via `npx`, Tool notes: `madge`, `knip`, `jscpd` are **not** project dependencies — run via `npx`,
treat output as evidence, not verdict (knip false-positives on entry points and dynamic treat output as evidence, not verdict (knip false-positives on entry points and dynamic
@@ -65,8 +77,9 @@ divergence whose rationale is recorded nowhere is itself a finding.
### Sweep — whole codebase ### Sweep — whole codebase
For: milestone boundaries, the one-off backfill, "how healthy are we?" on demand. For: milestone boundaries, the one-off backfill, "how healthy are we?" on demand.
**Never on a schedule.** Scope: all of `src/` (+ `styles/` for the Structure seat). All **Never on a schedule.** Scope: all of `src/` (+ `styles/` for the Structure seat, `docs/`
four seats. Output: the full report (format below) **plus a metrics snapshot row** for the Documentation seat). All five seats. Output: the full report (format below) **plus a
metrics snapshot row**
appended to `docs/codebase-metrics.md` (create on first sweep): appended to `docs/codebase-metrics.md` (create on first sweep):
``` ```
@@ -80,8 +93,9 @@ The trend line is the point — accretion becomes visible instead of felt.
For: a landed or in-progress refactor (`git diff` / `git diff --staged`). Scope: changed For: a landed or in-progress refactor (`git diff` / `git diff --staged`). Scope: changed
files **plus their one-hop import neighborhood** (importers and imports) — drift is only files **plus their one-hop import neighborhood** (importers and imports) — drift is only
visible relative to neighbors. Seats: Consistency and Subtraction always; Structure if visible relative to neighbors. Seats: Consistency and Subtraction always; Structure if
imports moved. Center question: did this refactor _reduce_ the number of shapes, or add imports moved; Documentation if the change touched a doc or makes one stale. Center
variant N+1? (Deletion rule 4 applies with full force.) question: did this refactor _reduce_ the number of shapes, or add variant N+1? (Deletion
rule 4 applies with full force.)
### New-functionality review ### New-functionality review
@@ -89,7 +103,9 @@ For: a new feature in the diff. Scope: changed files + one-hop neighborhood. Sea
Consistency (does it follow the canonical shape for its kind?), Altitude (is the logic in Consistency (does it follow the canonical shape for its kind?), Altitude (is the logic in
core/stores, not the component?), Subtraction (does it re-implement an existing utility? core/stores, not the component?), Subtraction (does it re-implement an existing utility?
does every prop/option/branch have a caller?), Structure if a new module or dependency does every prop/option/branch have a caller?), Structure if a new module or dependency
appeared (a new dependency needs the same justification `/alignment` demands). appeared (a new dependency needs the same justification `/alignment` demands), Documentation
if the feature added or should have added docs (and whether what it added stays at altitude,
not a move-by-move log).
### Consult — before writing code ### Consult — before writing code
@@ -103,17 +119,26 @@ what the new work might make deletable. Two paragraphs, no report scaffolding.
For sweep and review modes: For sweep and review modes:
1. **Verdict** — two or three sentences: overall shape, the one thing to act on first. 1. **Verdict** — two or three sentences: overall shape, the one thing to act on first.
2. **Findings** — per seat, each finding: `file:line`, the evidence, the proposed fix, 2. **Findings** — per seat (Structure, Consistency, Altitude, Subtraction, Documentation),
net LOC delta. Skip seats with nothing to say in one line, not zero. each finding: `file:line`, the evidence, the proposed fix, net LOC delta. Skip seats
3. **Remove** — the mandatory section (deletion rule 2). with nothing to say in one line, not zero.
4. **Net delta** — total LOC delta if all findings were accepted. 3. **Beyond-scope notes** — improvement opportunities the review noticed _outside_ the
5. **Rules discovered** — recurring patterns worth making law (see Close the loop). reviewed change: a shape worth revisiting elsewhere, a doc drifting, an abstraction
forming across files the diff didn't touch. Noted with `file:line` and a one-line why,
**not fixed here** — the user triages. Expected to be non-empty in a healthy review; an
empty one means either a pristine codebase or a council that stayed too close to the diff.
4. **Remove** — the mandatory section (deletion rule 2).
5. **Net delta** — total LOC delta if all findings were accepted.
6. **Rules discovered** — recurring patterns worth making law (see Close the loop).
**Fix vs. propose:** mechanical, behavior-preserving removals (dead exports, unused files, **Fix vs. propose:** mechanical, behavior-preserving removals (dead exports, unused files,
unreferenced props) — fix directly, keep `npm run typecheck` + `npm test` green. unreferenced props) — fix directly, keep `npm run typecheck` + `npm test` green. Trimming
Structural findings (merge two shapes, move logic across layers, kill an abstraction) — decision-log narration from a doc back to the matter-of-fact bar is the documentation
propose with the evidence; they're the user's call. Out-of-scope observations get a equivalent of a behavior-preserving removal — fix directly. Structural findings (merge two
`// TODO:` breadcrumb at the code site, same rule as `/alignment`. shapes, move logic across layers, kill an abstraction, restructure or consolidate a doc) —
propose with the evidence; they're the user's call. An in-scope out-of-place observation
gets a `// TODO:` breadcrumb at the code site (same rule as `/alignment`); a beyond-scope
one goes in the Beyond-scope notes section so it surfaces rather than scattering as TODOs.
## Close the loop ## Close the loop