@nurix/etna 0.19.22 → 0.19.24
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/README.md +6 -5
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/.vscode/settings.json +9 -0
- package/data/harnesses/code/CLAUDE.md +16 -1
- package/data/harnesses/code/agents/brainstorm.md +11 -11
- package/data/harnesses/code/agents/change-review.md +4 -4
- package/data/harnesses/code/agents/maintenance.md +4 -3
- package/data/harnesses/code/agents/retro.md +45 -0
- package/data/harnesses/code/codex/agents/brainstorm.toml +11 -11
- package/data/harnesses/code/codex/agents/change-review.toml +4 -5
- package/data/harnesses/code/codex/agents/maintenance.toml +2 -1
- package/data/harnesses/code/codex/agents/retro.toml +43 -0
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/rules/database.md +29 -1
- package/data/harnesses/code/skills/documentation/SKILL.md +1 -0
- package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +3 -1
- package/data/harnesses/code/skills/documentation/templates/refinement-ledger.md +33 -0
- package/data/harnesses/code/skills/documentation/templates/structure.md +2 -0
- package/data/harnesses/code/skills/test-plan/SKILL.md +82 -0
- package/data/harnesses/discover/.vscode/settings.json +9 -0
- package/data/harnesses/discover/harness.json +1 -1
- package/data/harnesses/discussion/.vscode/settings.json +9 -0
- package/data/harnesses/discussion/harness.json +2 -2
- package/data/harnesses/discussion/rules/artifacts.md +1 -1
- package/data/harnesses/discussion/rules/method.md +2 -0
- package/data/harnesses/etna/.vscode/settings.json +9 -0
- package/data/harnesses/etna/CLAUDE.md +2 -0
- package/data/harnesses/etna/agents/brainstorm.md +11 -11
- package/data/harnesses/etna/agents/change-review.md +4 -4
- package/data/harnesses/etna/agents/maintenance.md +4 -3
- package/data/harnesses/etna/codex/agents/brainstorm.toml +11 -11
- package/data/harnesses/etna/codex/agents/change-review.toml +4 -5
- package/data/harnesses/etna/codex/agents/maintenance.toml +2 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/documentation/SKILL.md +1 -0
- package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +3 -1
- package/data/harnesses/etna/skills/documentation/templates/refinement-ledger.md +33 -0
- package/data/harnesses/etna/skills/documentation/templates/structure.md +2 -0
- package/data/harnesses/hr/.vscode/settings.json +9 -0
- package/data/harnesses/hr/harness.json +2 -2
- package/data/harnesses/kb-agi/.vscode/settings.json +9 -0
- package/data/harnesses/kb-agi/harness.json +1 -1
- package/lib/codex/README.md +17 -7
- package/lib/codex/agents-md.mjs +85 -6
- package/lib/codex/hooks.mjs +25 -1
- package/lib/codex/index.mjs +4 -3
- package/lib/codex/plugin-manifest.mjs +9 -3
- package/lib/codex/subagents.mjs +2 -2
- package/lib/codex/validate-codex-agents.mjs +126 -0
- package/package.json +2 -2
- package/lib/codex/gen-agents.mjs +0 -157
package/README.md
CHANGED
|
@@ -25,19 +25,20 @@ After this completes:
|
|
|
25
25
|
```
|
|
26
26
|
your-project/
|
|
27
27
|
├── CLAUDE.md ← harness policy (non-git repo: existing file → CLAUDE.md.bak.<ISO>)
|
|
28
|
+
├── AGENTS.md ← Codex: CLAUDE.md byte-for-byte + a generated Codex runtime adapter
|
|
28
29
|
├── .prettierrc.json ← markdown formatting (proseWrap: never)
|
|
29
30
|
├── .prettierignore
|
|
30
31
|
├── .vscode/settings.json ← editor settings (markdown formatter on save)
|
|
31
32
|
└── .claude/
|
|
32
|
-
├── skills/ ← documentation, boundary, brainstorm, workflow-mapper
|
|
33
|
+
├── skills/ ← documentation, boundary, brainstorm, workflow-mapper, design
|
|
33
34
|
├── agents/ ← lld-mode, brainstorm, maintenance, change-review, performance-review
|
|
34
|
-
├── rules/ ← general.md, frontend.md, express.md, nomenclature.md, database.md,
|
|
35
|
+
├── rules/ ← general.md, frontend.md, express.md, nomenclature.md, database.md, testing.md, pnpm.md
|
|
35
36
|
├── hooks/ ← generate-ownership-index (SessionStart)
|
|
36
37
|
├── settings.json ← the hook is deep-merged in here (your existing keys preserved)
|
|
37
|
-
└── harness.json ← {version, digest} — the installed-harness sentinel
|
|
38
|
+
└── harness.json ← {version, digest, owned} — the installed-harness sentinel
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
Alongside the Claude tree, the installer projects the **Codex** artifacts so the repo also works under OpenAI Codex: `AGENTS.md` (above), `.agents/skills/` (a mirror of `.claude/skills/`, Codex's skill-scan path), and `.codex/agents/*.toml` + `.codex/hooks.json` (its subagents and SessionStart hook). Nothing is written outside the project. No marketplace registration, no `enabledPlugins` entry, no global cache dependency — Claude Code picks up the project-scoped agents/skills/rules on its next session start (and Codex reads `AGENTS.md` + `.agents/` + `.codex/`), and the hooks wire in through `.claude/settings.json`.
|
|
41
42
|
|
|
42
43
|
Re-run `npx --yes @nurix/etna --name=code` anytime to refresh the harness content with what the latest published package ships. Existing same-named files are overwritten; files you've added that aren't part of the harness are left alone. In a git repo the previous `CLAUDE.md` is overwritten in place (recover it with `git checkout CLAUDE.md`); outside a git repo it's backed up to `CLAUDE.md.bak.<ISO-timestamp>`. Because the new `harness.json` carries the installed `{version, digest}`, a re-run whose **major** version is ahead of your repo's stamped `harness-version` is what the reconcile (below) detects as a structural upgrade.
|
|
43
44
|
|
|
@@ -95,7 +96,7 @@ agents: [brainstorm, change-review, lld-mode, maintenance, performance-review]
|
|
|
95
96
|
|
|
96
97
|
- **Owned, by location** — hooks, scripts (and any unlisted, harness-specific agents) live inside the harness folder (`harness/<name>/{agents,hooks,scripts}/`). No list — membership is presence in the folder, exactly how a Claude Code plugin ships them. Shared governance agents are listed instead (above) and resolved from the `agents/` catalog, local-first; a harness can still drop its own copy beside it to override one by name.
|
|
97
98
|
|
|
98
|
-
`scripts/build-data.js` (run by `prepack`) resolves the listed skills/rules/agents from the catalogs (local-first), copies any unlisted harness-owned agents plus the harness's `hooks/` and `scripts/` wholesale into `data/harnesses/<folder>/`; a listed skill/rule/agent that doesn't exist is a hard error. The marketplace channel (`.github/scripts/publish.mjs`) reads the same harness folder
|
|
99
|
+
`scripts/build-data.js` (run by `prepack`) resolves the listed skills/rules/agents from the catalogs (local-first), copies any unlisted harness-owned agents plus the harness's `hooks/` and `scripts/` wholesale into `data/harnesses/<folder>/`; a listed skill/rule/agent that doesn't exist is a hard error. The marketplace channel (`.github/scripts/publish.mjs`) reads the same harness folder and resolves the listed skills/rules/agents the same local-first way — but the two channels' **footprints differ**: the marketplace plugin carries no root policy, and its Codex surface is skills + hooks only (Codex custom agents ship through this CLI). The installer (`bin/etna.js`) reads from the bundle at install time; no GitHub fetch at runtime.
|
|
99
100
|
|
|
100
101
|
## Building / contributing
|
|
101
102
|
|
package/data/harness-index.json
CHANGED
|
@@ -6,5 +6,14 @@
|
|
|
6
6
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
7
|
"editor.formatOnSave": true,
|
|
8
8
|
"editor.wordWrap": "on"
|
|
9
|
+
},
|
|
10
|
+
// Hide harness-authoring scaffolding from the file explorer
|
|
11
|
+
"files.exclude": {
|
|
12
|
+
".claude": true,
|
|
13
|
+
".vscode": true,
|
|
14
|
+
".agents": true,
|
|
15
|
+
".codex": true,
|
|
16
|
+
"**/node_modules": true,
|
|
17
|
+
"**/apollo.service.json": true
|
|
9
18
|
}
|
|
10
19
|
}
|
|
@@ -35,7 +35,8 @@ Three peer modes plus a Completion step — enter wherever the user's thinking a
|
|
|
35
35
|
|
|
36
36
|
1. Freeze the plan — `Status: Complete`, fill the Completed date. The file is now frozen.
|
|
37
37
|
2. Flip the feature LLD to `status: active`; extend it in place with the how-it-works sections; confirm its `owns:` globs against the actual code.
|
|
38
|
-
3. The `boundary`
|
|
38
|
+
3. The `boundary` and `test-plan` skills must already have gated this plan before its first implementation step — see Ownership, Boundaries & Documentation.
|
|
39
|
+
4. Derive/update the behavioral checklist at `docs/tests/{feature}.md` via the `documentation` skill (a truth document — present-tense, referencing the LLD's promises, restating no intent), then run the affected test suite + the project's e2e smoke gate and record the results in the changelog entry.
|
|
39
40
|
|
|
40
41
|
**On Brainstorm Close** (when a session ends, not when a plan completes): close + harvest is the skill's `stop` procedure — converge, a user-approved harvest manifest, apply, then a uselessness test; conclusions disperse by scope (architecture docs, decision records, backlog), the record moves from `docs/research/{topic}-brainstorm/` to `docs/history/brainstorms/{topic}/`, and the user decides whether the moved folder is deleted or committed.
|
|
41
42
|
|
|
@@ -62,6 +63,10 @@ Boundaries are **diagnosed, not documented** — the `boundary` skill derives th
|
|
|
62
63
|
|
|
63
64
|
**Invoke the `boundary` skill after a plan is approved and before its first implementation step.** It parses the plan's Proposed Changes, reads the touched source, traces the consumers on the other side, and reports severity-ranked violations with suggested amendments and a pass/block verdict — in chat, read-only. Fold the amendments into the plan before coding. For non-plan edits in contract-heavy code (db schema, wire envelopes, auth, events, env/config), run the same diagnostic scoped to the diff.
|
|
64
65
|
|
|
66
|
+
### Test obligations — specify before implementing
|
|
67
|
+
|
|
68
|
+
**After `boundary` passes and its amendments are folded, invoke the `test-plan` skill** — same plan gate, ordered second. It derives the tests the plan owes from its Proposed Changes and the owning LLD, and writes a **Test Obligations** section into the plan (one row per promised behavior: layer · target file · oracle · fixtures). It writes no test files — the tests land *with* the code at implementation time (the suite-first guardrail), and the manifest is the checklist that work satisfies. This makes obligations survive dispatch to an executor that sees only the plan file, and lets a later doc-health pass prove the tests match the promises. On a boundary **BLOCK** it does not run — re-plan first. The three-moment split (gate → implementation → Completion checklist), the layer rules, and the e2e altitude gate live in the skill.
|
|
69
|
+
|
|
65
70
|
### Documentation — close the loop
|
|
66
71
|
|
|
67
72
|
- **Every markdown document goes through the `documentation` skill.** Before creating or substantively editing any `.md` document — a doc, a README, an index, a record — invoke the `documentation` skill and apply its templates and `references/style-guide.md`: truth documents stay present-tense; history lives only in `docs/history/` records.
|
|
@@ -88,6 +93,16 @@ When recording a learning, ask: _is this true of this project, or true of this u
|
|
|
88
93
|
|
|
89
94
|
---
|
|
90
95
|
|
|
96
|
+
## Refinement Ledger
|
|
97
|
+
|
|
98
|
+
A commit marks the user's behavioral verification of the work, and the committing session is the last holder of the refinement context that produced it — asks, iterations, rejections, skill outcomes, discoveries. That context is captured at commit time and distilled on demand:
|
|
99
|
+
|
|
100
|
+
- **Every non-mechanical commit appends one ledger block** to `docs/history/ledger/YYYY-MM.md`, staged inside the commit it describes — whatever tool or session performs the commit. Block format, required fields, and the closed exemption list are the `documentation` skill's `templates/refinement-ledger.md`; the failure fields (rejected attempts, overridden skill output) and verbatim taste quotes are required, not optional — the ledger's value concentrates there.
|
|
101
|
+
- **Append-only journal, never a truth doc** — blocks are immutable once committed; a correction is a new block. The ledger is never cleaned up or reconciled, and doc-health passes skip it by genre.
|
|
102
|
+
- **Distillation is the `retro` agent** — run on demand (before a brainstorm or LLD, before a new project, after a refinement arc), it converts accumulated blocks into a typed punch list (doc content, doc structure, skill evolution, pins, harness rules), appends actionable items to the backlog, and proposes only — application runs through the normal documentation loop.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
91
106
|
## Out-of-Scope Discovery
|
|
92
107
|
|
|
93
108
|
When a plan's implementation surfaces work that is important but outside the plan's scope:
|
|
@@ -110,19 +110,19 @@ Stop is facilitator-orchestrated because approval belongs to the user; you execu
|
|
|
110
110
|
fork, every fragment, the consolidated source of truth. Return the manifest body for approval.
|
|
111
111
|
2. **Apply** (only after the facilitator reports approval; set `Status: approved` then work).
|
|
112
112
|
Read **both sides** of every destination before writing — the destination's current content is
|
|
113
|
-
a contract, not a blank page. Format each artifact via the `documentation` skill
|
|
114
|
-
where
|
|
115
|
-
manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
113
|
+
a contract, not a blank page. Format each artifact via the `documentation` skill;
|
|
114
|
+
where the runtime can't invoke it, fall back to your own formatting **and record which path ran
|
|
115
|
+
in the manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
116
116
|
report exactly what applied and stop — the folder stays visibly unfinished and the user
|
|
117
117
|
restarts; never resume silently from a half-applied state.
|
|
118
|
-
3. **Uselessness test.** Spawn a **fresh, context-free cold reader**
|
|
119
|
-
|
|
120
|
-
and the instruction to reconstruct the
|
|
121
|
-
branches. Grade its reconstruction against the
|
|
122
|
-
manifest (`Result: fail`, named gaps), and the fixes
|
|
123
|
-
requiring fresh approval. Pass → record it. If the
|
|
124
|
-
facilitator must dispatch the cold reader — you,
|
|
125
|
-
cold-read.
|
|
118
|
+
3. **Uselessness test.** Spawn a **fresh, context-free cold reader** — an independent subagent
|
|
119
|
+
that inherits none of this session's context — whose prompt contains only the allowed-path list
|
|
120
|
+
(the manifest's destinations — never the session folder) and the instruction to reconstruct the
|
|
121
|
+
design: thesis, commitments, reasoning, declined branches. Grade its reconstruction against the
|
|
122
|
+
ledger and thesis. Gaps → record them in the manifest (`Result: fail`, named gaps), and the fixes
|
|
123
|
+
re-enter as a new manifest `Round` requiring fresh approval. Pass → record it. If the runtime
|
|
124
|
+
offers no subagent dispatch, report that the facilitator must dispatch the cold reader — you,
|
|
125
|
+
having read the folder, can no longer cold-read.
|
|
126
126
|
4. **Move.** Run `--gate=move`. When clean: delete `ops/` entirely, `git mv` the folder to
|
|
127
127
|
`docs/history/brainstorms/{topic}/`, set state `Status: harvested`, update both indexes
|
|
128
128
|
(`docs/research/Readme.md` row out, `docs/history/brainstorms/Readme.md` row in). End your
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: change-review
|
|
3
|
-
description: Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel
|
|
3
|
+
description: Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel low-cost subagents (module, feature, impact, severity, churn), then derives a commit heatmap, risk zones (high churn in contract-heavy code), stabilization signals, and team/bus-factor distribution. Self-contained — produces its own CSV, no separate git-history step. Use when planning where to invest in review focus or rules.
|
|
4
4
|
tools: Bash, Read, Write, Glob, Grep, Task
|
|
5
5
|
model: inherit
|
|
6
6
|
---
|
|
@@ -11,7 +11,7 @@ You analyze code-change velocity over time to find risk zones — where change i
|
|
|
11
11
|
|
|
12
12
|
You work in two phases:
|
|
13
13
|
|
|
14
|
-
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel
|
|
14
|
+
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel low-cost subagents. You do this yourself; there is no separate agent that hands you a CSV.
|
|
15
15
|
2. **Analyze** — read that CSV and derive the velocity heatmap, risk zones, stabilization signals, and team distribution.
|
|
16
16
|
|
|
17
17
|
## Parameters
|
|
@@ -82,7 +82,7 @@ Build a registry of objects:
|
|
|
82
82
|
|
|
83
83
|
Split the commit registry into batches of `batch_size` commits each.
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
Dispatch one **independent subagent per batch** on the **cheapest capable tier** — classification is mechanical, so the lowest-cost model that can follow the output format is the right one. Cap concurrency at **5 batches in parallel**; each subagent is context-isolated and returns only its rows. If the runtime offers no subagent dispatch, classify the batches inline yourself.
|
|
86
86
|
|
|
87
87
|
Before building the prompt template, check if `docs/memory/change-review.md` contains **Module Taxonomy** and **Feature Taxonomy** sections. If yes, inject their content into the `{MODULE_TAXONOMY}` and `{FEATURE_TAXONOMY}` placeholders below. If no memory file exists, use these generic fallbacks:
|
|
88
88
|
|
|
@@ -243,7 +243,7 @@ Per module, list which authors made the most commits in the 3-month window. Surf
|
|
|
243
243
|
## Rules
|
|
244
244
|
|
|
245
245
|
- Never modify source code — read-only except for writing the output CSV, `docs/memory/change-review.md`, and `docs/history/backlog.md`
|
|
246
|
-
-
|
|
246
|
+
- Run all classification subagents on the cheapest capable tier to minimize cost; they are independent and context-isolated
|
|
247
247
|
- Always report progress: "Dispatching batch 1-5 of 12..." etc.
|
|
248
248
|
- If git commands fail (bad branch, bad date range), stop and report the error clearly
|
|
249
249
|
- Pipe characters in commit messages must be replaced with dashes before writing to CSV
|
|
@@ -138,11 +138,12 @@ docs/
|
|
|
138
138
|
├── history/
|
|
139
139
|
│ ├── CHANGELOG.md # Master changelog index
|
|
140
140
|
│ ├── changelog/ # Individual entries
|
|
141
|
+
│ ├── ledger/ # Refinement Ledger — append-only per-commit refinement journal (YYYY-MM.md; written at commit time, NOT scaffolded empty)
|
|
141
142
|
│ ├── plans/ # Implementation plans (Status field required)
|
|
142
143
|
│ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
|
|
143
144
|
│ └── backlog.md # Tracked work items by priority (P0-P3)
|
|
144
145
|
├── memory/ # index.md, main.md, {agent}.md — project knowledge + per-agent strategy memory
|
|
145
|
-
└── tests/ #
|
|
146
|
+
└── tests/ # Behavioral test checklists ({feature}.md, step → **Assert**), derived at plan Completion via the `documentation` skill; author-maintained, present only when test docs exist
|
|
146
147
|
```
|
|
147
148
|
|
|
148
149
|
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).
|
|
@@ -151,7 +152,7 @@ There is **no `docs/routing.md`**, **no `docs/modules/{m}/`**, **no `docs/pillar
|
|
|
151
152
|
|
|
152
153
|
### Step B1 — Inventory and classify
|
|
153
154
|
|
|
154
|
-
Glob every markdown file. Classify each: Architecture, Features, Operations, Plans, Changelogs, Backlog, Brainstorm records (stay), 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 (cross-doc links, memory files). Anything already under `docs/research/{topic}-brainstorm/` (or legacy `-brainstorming/`) or `docs/history/brainstorms/{topic}/` is a **design record** — leave it in place untouched; never reclassify its contents as Architecture/Stale or relocate them.
|
|
155
|
+
Glob every markdown file. Classify each: Architecture, Features, Operations, Tests (behavioral checklists — stay), Plans, Changelogs, Backlog, Brainstorm records (stay), 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 (cross-doc links, memory files). Anything already under `docs/research/{topic}-brainstorm/` (or legacy `-brainstorming/`) or `docs/history/brainstorms/{topic}/` is a **design record** — leave it in place untouched; never reclassify its contents as Architecture/Stale or relocate them.
|
|
155
156
|
|
|
156
157
|
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 Part A audit — **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.
|
|
157
158
|
|
|
@@ -200,7 +201,7 @@ Re-running you is safe — the structure work is idempotent, so a second pass is
|
|
|
200
201
|
## Rules
|
|
201
202
|
|
|
202
203
|
- **Never delete feature docs** — only update or flag for review.
|
|
203
|
-
- **Never modify `docs/history/plans
|
|
204
|
+
- **Never modify `docs/history/plans/`, `docs/history/changelog/`, or `docs/history/ledger/`** (frozen/append-only records — ledger blocks are written only at commit time, distilled only by the `retro` agent).
|
|
204
205
|
- **Preserve existing doc structure and formatting** when updating.
|
|
205
206
|
- **When in doubt, create a backlog item** rather than making a wrong update.
|
|
206
207
|
- **Be specific:** include file paths, line numbers, and what changed.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: retro
|
|
3
|
+
description: Session-distillation agent for the Refinement Ledger. Reads the append-only per-commit blocks under `docs/history/ledger/` accumulated since its last run and distills the refinement delta — what user-driven iteration added that the one-shot build lacked — into a typed punch list of doc-content gaps, doc-structure moves (missing doc / mothership split / merge), skill-evolution findings backed by survived-vs-overridden counts, unpinned discoveries needing an enforced artifact (test, token, guardrail, schema), and cross-project harness rules. Proposes only — actionable items land in the backlog, never applied directly. Run on demand: before a brainstorm or LLD session, before starting a new project, or after a refinement arc. Triggers on "run retro", "distill the ledger", "refinement retro", "/retro".
|
|
4
|
+
tools: Read, Glob, Grep, Bash, Write, Edit
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Retro — Refinement Ledger distillation
|
|
9
|
+
|
|
10
|
+
You distill refinement history into documentation and harness feedback. Your input is the Refinement Ledger — the append-only journal of per-commit blocks written at commit time under `docs/history/ledger/` (block format and field rules: the `documentation` skill's `templates/refinement-ledger.md`). Your output is a short, typed punch list; every finding cites the blocks that evidence it. You propose — you never apply.
|
|
11
|
+
|
|
12
|
+
## Before starting
|
|
13
|
+
|
|
14
|
+
1. Read `docs/memory/retro.md` if it exists — its opening `Last run:` stamp is your last-distilled marker (run date + last block seen); below it live prior skill-efficacy tallies and suppressed findings. No file ⇒ first run ⇒ distill the whole ledger.
|
|
15
|
+
2. Collect the input set: every block after the marker across `docs/history/ledger/*.md`. Empty set ⇒ report "nothing to distill since {date}" in one line, refresh the `Last run:` stamp, and stop — never manufacture findings.
|
|
16
|
+
3. Read `docs/memory/` for cross-reference: a ledger discovery that also appears in memory is confirmed knowledge; a memory entry with no ledger trace is itself a promotion candidate.
|
|
17
|
+
|
|
18
|
+
## Distill
|
|
19
|
+
|
|
20
|
+
Classify every finding into exactly one bucket. Work from the blocks — recurrence and explicit fields, never vibes.
|
|
21
|
+
|
|
22
|
+
1. **Doc content** — a truth doc is missing what refinement had to rediscover or invent: a `Discovered:` fact with no documented home, or `ux`/`taste` entries absent from the owning feature doc. Name the doc, the missing content, the evidencing blocks.
|
|
23
|
+
2. **Doc structure** — the doc *set* is wrong: a class of entries with no home doc (candidate new doc); one doc absorbing entries across unrelated surfaces (candidate split); docs that always co-change (candidate merge). Derive surface clustering from the blocks' `surface` values against the union of feature-doc `owns:` globs (glob `docs/features/`).
|
|
24
|
+
3. **Skill evolution** — tally each skill's `Skills:` verdicts across the blocks: invoked / survived / overridden, override reasons aggregated. A skill overridden in most of its invocations is a finding. A refinement class recurring ≥3 times with no skill invoked is a candidate new skill.
|
|
25
|
+
4. **Pin** — a `Pin: none — candidate:` entry that recurs, or any block whose `Ask` carries a user taste quote or explicit approval with no enforced artifact guarding the behavior. Output the exact pin (test, token, guardrail, schema) and where it goes.
|
|
26
|
+
5. **Harness rule** — a discovery true across projects, not of this repo (tooling collisions, platform ceilings, auth toil). Route to the shared rule file it belongs in.
|
|
27
|
+
|
|
28
|
+
## Report & record
|
|
29
|
+
|
|
30
|
+
1. Report in chat, ≤2 pages: a four-line scoreboard (blocks distilled · discoveries pinned vs unpinned · skill table: invoked/survived · dominant refinement class), then the punch list — each item `bucket · finding (one sentence) · evidence (block refs) · proposed action (one sentence)`. More than 12 findings ⇒ keep the top 12 by recurrence and state the tail count.
|
|
31
|
+
2. Append the actionable items to `docs/history/backlog.md` as `- **[P0–P3]** {finding} — discovered by retro`, priority by severity, deduped against existing entries.
|
|
32
|
+
3. Update `docs/memory/retro.md` (create on first write). The file **always opens with a human-legible stamp**, refreshed on **every** run — including a nothing-to-distill run — so anyone browsing `docs/memory/` sees at a glance when retro last ran and how far it read:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Last run: {YYYY-MM-DD} · {N} blocks distilled (through {ledger-file} / {last block heading}) · {M} findings → backlog
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Below the stamp: updated skill-efficacy tallies and findings the user declined (suppressed, not re-raised), as dated entries `## YYYY-MM-DD — {topic}`.
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
|
|
42
|
+
- **Evidence or silence** — no finding without block citations; a clean report is valid.
|
|
43
|
+
- **Propose, never apply** — you never edit truth docs, skills, rules, code, or ledger blocks; application runs through the normal documentation loop in the main session.
|
|
44
|
+
- **The ledger is immutable input** — never rewrite, renumber, or "clean up" blocks, whatever their quality; a malformed block is at most a finding against the committing procedure.
|
|
45
|
+
- **Respect suppressions** in `docs/memory/retro.md` — a declined finding is recorded once, never re-raised every run.
|
|
@@ -107,19 +107,19 @@ Stop is facilitator-orchestrated because approval belongs to the user; you execu
|
|
|
107
107
|
fork, every fragment, the consolidated source of truth. Return the manifest body for approval.
|
|
108
108
|
2. **Apply** (only after the facilitator reports approval; set `Status: approved` then work).
|
|
109
109
|
Read **both sides** of every destination before writing — the destination's current content is
|
|
110
|
-
a contract, not a blank page. Format each artifact via the `documentation` skill
|
|
111
|
-
where
|
|
112
|
-
manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
110
|
+
a contract, not a blank page. Format each artifact via the `documentation` skill;
|
|
111
|
+
where the runtime can't invoke it, fall back to your own formatting **and record which path ran
|
|
112
|
+
in the manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
113
113
|
report exactly what applied and stop — the folder stays visibly unfinished and the user
|
|
114
114
|
restarts; never resume silently from a half-applied state.
|
|
115
|
-
3. **Uselessness test.** Spawn a **fresh, context-free cold reader**
|
|
116
|
-
|
|
117
|
-
and the instruction to reconstruct the
|
|
118
|
-
branches. Grade its reconstruction against the
|
|
119
|
-
manifest (`Result: fail`, named gaps), and the fixes
|
|
120
|
-
requiring fresh approval. Pass → record it. If the
|
|
121
|
-
facilitator must dispatch the cold reader — you,
|
|
122
|
-
cold-read.
|
|
115
|
+
3. **Uselessness test.** Spawn a **fresh, context-free cold reader** — an independent subagent
|
|
116
|
+
that inherits none of this session's context — whose prompt contains only the allowed-path list
|
|
117
|
+
(the manifest's destinations — never the session folder) and the instruction to reconstruct the
|
|
118
|
+
design: thesis, commitments, reasoning, declined branches. Grade its reconstruction against the
|
|
119
|
+
ledger and thesis. Gaps → record them in the manifest (`Result: fail`, named gaps), and the fixes
|
|
120
|
+
re-enter as a new manifest `Round` requiring fresh approval. Pass → record it. If the runtime
|
|
121
|
+
offers no subagent dispatch, report that the facilitator must dispatch the cold reader — you,
|
|
122
|
+
having read the folder, can no longer cold-read.
|
|
123
123
|
4. **Move.** Run `--gate=move`. When clean: delete `ops/` entirely, `git mv` the folder to
|
|
124
124
|
`docs/history/brainstorms/{topic}/`, set state `Status: harvested`, update both indexes
|
|
125
125
|
(`docs/research/Readme.md` row out, `docs/history/brainstorms/Readme.md` row in). End your
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# dropped Claude tools: Bash, Read, Write, Glob, Grep, Task
|
|
2
2
|
name = "change-review"
|
|
3
|
-
description = "Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel
|
|
3
|
+
description = "Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel low-cost subagents (module, feature, impact, severity, churn), then derives a commit heatmap, risk zones (high churn in contract-heavy code), stabilization signals, and team/bus-factor distribution. Self-contained — produces its own CSV, no separate git-history step. Use when planning where to invest in review focus or rules."
|
|
4
4
|
developer_instructions = '''
|
|
5
|
-
|
|
6
5
|
# Change-Review Agent
|
|
7
6
|
|
|
8
7
|
You analyze code-change velocity over time to find risk zones — where change is accelerating or decelerating, and whether review attention matches the risk. You answer: "where should the tech lead invest review focus or rules next?"
|
|
9
8
|
|
|
10
9
|
You work in two phases:
|
|
11
10
|
|
|
12
|
-
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel
|
|
11
|
+
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel low-cost subagents. You do this yourself; there is no separate agent that hands you a CSV.
|
|
13
12
|
2. **Analyze** — read that CSV and derive the velocity heatmap, risk zones, stabilization signals, and team distribution.
|
|
14
13
|
|
|
15
14
|
## Parameters
|
|
@@ -80,7 +79,7 @@ Build a registry of objects:
|
|
|
80
79
|
|
|
81
80
|
Split the commit registry into batches of `batch_size` commits each.
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
Dispatch one **independent subagent per batch** on the **cheapest capable tier** — classification is mechanical, so the lowest-cost model that can follow the output format is the right one. Cap concurrency at **5 batches in parallel**; each subagent is context-isolated and returns only its rows. If the runtime offers no subagent dispatch, classify the batches inline yourself.
|
|
84
83
|
|
|
85
84
|
Before building the prompt template, check if `docs/memory/change-review.md` contains **Module Taxonomy** and **Feature Taxonomy** sections. If yes, inject their content into the `{MODULE_TAXONOMY}` and `{FEATURE_TAXONOMY}` placeholders below. If no memory file exists, use these generic fallbacks:
|
|
86
85
|
|
|
@@ -241,7 +240,7 @@ Per module, list which authors made the most commits in the 3-month window. Surf
|
|
|
241
240
|
## Rules
|
|
242
241
|
|
|
243
242
|
- Never modify source code — read-only except for writing the output CSV, `docs/memory/change-review.md`, and `docs/history/backlog.md`
|
|
244
|
-
-
|
|
243
|
+
- Run all classification subagents on the cheapest capable tier to minimize cost; they are independent and context-isolated
|
|
245
244
|
- Always report progress: "Dispatching batch 1-5 of 12..." etc.
|
|
246
245
|
- If git commands fail (bad branch, bad date range), stop and report the error clearly
|
|
247
246
|
- Pipe characters in commit messages must be replaced with dashes before writing to CSV
|
|
@@ -135,6 +135,7 @@ docs/
|
|
|
135
135
|
├── history/
|
|
136
136
|
│ ├── CHANGELOG.md # Master changelog index
|
|
137
137
|
│ ├── changelog/ # Individual entries
|
|
138
|
+
│ ├── ledger/ # Refinement Ledger — append-only per-commit refinement journal (YYYY-MM.md; written at commit time, NOT scaffolded empty)
|
|
138
139
|
│ ├── plans/ # Implementation plans (Status field required)
|
|
139
140
|
│ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
|
|
140
141
|
│ └── backlog.md # Tracked work items by priority (P0-P3)
|
|
@@ -197,7 +198,7 @@ Re-running you is safe — the structure work is idempotent, so a second pass is
|
|
|
197
198
|
## Rules
|
|
198
199
|
|
|
199
200
|
- **Never delete feature docs** — only update or flag for review.
|
|
200
|
-
- **Never modify `docs/history/plans
|
|
201
|
+
- **Never modify `docs/history/plans/`, `docs/history/changelog/`, or `docs/history/ledger/`** (frozen/append-only records — ledger blocks are written only at commit time, distilled only by the `retro` agent).
|
|
201
202
|
- **Preserve existing doc structure and formatting** when updating.
|
|
202
203
|
- **When in doubt, create a backlog item** rather than making a wrong update.
|
|
203
204
|
- **Be specific:** include file paths, line numbers, and what changed.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# dropped Claude tools: Read, Glob, Grep, Bash, Write, Edit
|
|
2
|
+
name = "retro"
|
|
3
|
+
description = "Session-distillation agent for the Refinement Ledger. Reads the append-only per-commit blocks under `docs/history/ledger/` accumulated since its last run and distills the refinement delta — what user-driven iteration added that the one-shot build lacked — into a typed punch list of doc-content gaps, doc-structure moves (missing doc / mothership split / merge), skill-evolution findings backed by survived-vs-overridden counts, unpinned discoveries needing an enforced artifact (test, token, guardrail, schema), and cross-project harness rules. Proposes only — actionable items land in the backlog, never applied directly. Run on demand: before a brainstorm or LLD session, before starting a new project, or after a refinement arc. Triggers on \"run retro\", \"distill the ledger\", \"refinement retro\", \"/retro\"."
|
|
4
|
+
developer_instructions = '''
|
|
5
|
+
# Retro — Refinement Ledger distillation
|
|
6
|
+
|
|
7
|
+
You distill refinement history into documentation and harness feedback. Your input is the Refinement Ledger — the append-only journal of per-commit blocks written at commit time under `docs/history/ledger/` (block format and field rules: the `documentation` skill's `templates/refinement-ledger.md`). Your output is a short, typed punch list; every finding cites the blocks that evidence it. You propose — you never apply.
|
|
8
|
+
|
|
9
|
+
## Before starting
|
|
10
|
+
|
|
11
|
+
1. Read `docs/memory/retro.md` if it exists — its opening `Last run:` stamp is your last-distilled marker (run date + last block seen); below it live prior skill-efficacy tallies and suppressed findings. No file ⇒ first run ⇒ distill the whole ledger.
|
|
12
|
+
2. Collect the input set: every block after the marker across `docs/history/ledger/*.md`. Empty set ⇒ report "nothing to distill since {date}" in one line, refresh the `Last run:` stamp, and stop — never manufacture findings.
|
|
13
|
+
3. Read `docs/memory/` for cross-reference: a ledger discovery that also appears in memory is confirmed knowledge; a memory entry with no ledger trace is itself a promotion candidate.
|
|
14
|
+
|
|
15
|
+
## Distill
|
|
16
|
+
|
|
17
|
+
Classify every finding into exactly one bucket. Work from the blocks — recurrence and explicit fields, never vibes.
|
|
18
|
+
|
|
19
|
+
1. **Doc content** — a truth doc is missing what refinement had to rediscover or invent: a `Discovered:` fact with no documented home, or `ux`/`taste` entries absent from the owning feature doc. Name the doc, the missing content, the evidencing blocks.
|
|
20
|
+
2. **Doc structure** — the doc *set* is wrong: a class of entries with no home doc (candidate new doc); one doc absorbing entries across unrelated surfaces (candidate split); docs that always co-change (candidate merge). Derive surface clustering from the blocks' `surface` values against the union of feature-doc `owns:` globs (glob `docs/features/`).
|
|
21
|
+
3. **Skill evolution** — tally each skill's `Skills:` verdicts across the blocks: invoked / survived / overridden, override reasons aggregated. A skill overridden in most of its invocations is a finding. A refinement class recurring ≥3 times with no skill invoked is a candidate new skill.
|
|
22
|
+
4. **Pin** — a `Pin: none — candidate:` entry that recurs, or any block whose `Ask` carries a user taste quote or explicit approval with no enforced artifact guarding the behavior. Output the exact pin (test, token, guardrail, schema) and where it goes.
|
|
23
|
+
5. **Harness rule** — a discovery true across projects, not of this repo (tooling collisions, platform ceilings, auth toil). Route to the shared rule file it belongs in.
|
|
24
|
+
|
|
25
|
+
## Report & record
|
|
26
|
+
|
|
27
|
+
1. Report in chat, ≤2 pages: a four-line scoreboard (blocks distilled · discoveries pinned vs unpinned · skill table: invoked/survived · dominant refinement class), then the punch list — each item `bucket · finding (one sentence) · evidence (block refs) · proposed action (one sentence)`. More than 12 findings ⇒ keep the top 12 by recurrence and state the tail count.
|
|
28
|
+
2. Append the actionable items to `docs/history/backlog.md` as `- **[P0–P3]** {finding} — discovered by retro`, priority by severity, deduped against existing entries.
|
|
29
|
+
3. Update `docs/memory/retro.md` (create on first write). The file **always opens with a human-legible stamp**, refreshed on **every** run — including a nothing-to-distill run — so anyone browsing `docs/memory/` sees at a glance when retro last ran and how far it read:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Last run: {YYYY-MM-DD} · {N} blocks distilled (through {ledger-file} / {last block heading}) · {M} findings → backlog
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Below the stamp: updated skill-efficacy tallies and findings the user declined (suppressed, not re-raised), as dated entries `## YYYY-MM-DD — {topic}`.
|
|
36
|
+
|
|
37
|
+
## Rules
|
|
38
|
+
|
|
39
|
+
- **Evidence or silence** — no finding without block citations; a clean report is valid.
|
|
40
|
+
- **Propose, never apply** — you never edit truth docs, skills, rules, code, or ledger blocks; application runs through the normal documentation loop in the main session.
|
|
41
|
+
- **The ledger is immutable input** — never rewrite, renumber, or "clean up" blocks, whatever their quality; a malformed block is at most a finding against the committing procedure.
|
|
42
|
+
- **Respect suppressions** in `docs/memory/retro.md` — a declined finding is recorded once, never re-raised every run.
|
|
43
|
+
'''
|
|
@@ -4,6 +4,34 @@ Fixed conventions for relational schemas — table/column/index **names**, the *
|
|
|
4
4
|
|
|
5
5
|
Written for SQLite / Cloudflare D1 + Drizzle (the concrete types below). The **names and key vocabulary are engine-agnostic** — a Postgres project keeps the same column names and semantics with native types (`uuid`, `timestamptz`, `boolean`).
|
|
6
6
|
|
|
7
|
+
## What earns a table
|
|
8
|
+
|
|
9
|
+
A table is the most expensive home for data — it costs a migration to change its shape, a join to read, and a mirror to keep in sync. Default to **not** a table. A concept earns its own table only when it needs at least one property in the left column; lacking all of them, the data belongs in the cheaper home on the right.
|
|
10
|
+
|
|
11
|
+
| A table is earned by… | Lacking all of these, the data belongs in… |
|
|
12
|
+
| -------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
13
|
+
| identity minted at **runtime** | — |
|
|
14
|
+
| variation **per tenant / user** | — |
|
|
15
|
+
| **independent addressing** — queried, indexed, or FK'd in isolation | a **JSON column** on its parent row |
|
|
16
|
+
| **concurrency-safe** writes — racing writers must not clobber a shared blob | — |
|
|
17
|
+
| a **DB-enforced invariant** — immutability trigger, unique, atomic boundary | — |
|
|
18
|
+
| dev-authored, published on deploy, identical for every tenant | **config / a constants file**, validated at build |
|
|
19
|
+
| exactly recomputable from other rows | a **cache** (KV / edge), recomputed on demand |
|
|
20
|
+
| process state that is dead once the request completes | a **log or workflow engine**, never the domain DB |
|
|
21
|
+
| owned by another system-of-record | a **reference column** — store the id, not the data |
|
|
22
|
+
|
|
23
|
+
Each routing rule is one question:
|
|
24
|
+
|
|
25
|
+
- **Static vocabulary or a fixed graph → config, not a table.** Dev-authored, same for every tenant, never FK'd at runtime ⇒ a constants file validated at build, surfaced in code as a constant/type. Reifying it into tables plus a seed makes the file and the tables a two-copy sync problem. The refined boundary is § Vocabulary / lookup tables.
|
|
26
|
+
- **History → one immutable log + a mutable head.** Never shatter versioning into per-entity `*_revisions` / `*_revision_sections` tables. Snapshot the coherent set once into an append-only versions table; current state is a derived projection of the newest entry. _Test: is this table just "old rows of that table"? → collapse it into the snapshot._
|
|
27
|
+
- **Process state is not domain state.** _Test: if it were deleted the instant the request finished, would a product feature break? No ⇒ it is a log line or a workflow-engine concern._
|
|
28
|
+
- **Derived output is a cache, not truth.** _Test: is it exactly recomputable from other rows + code? Yes ⇒ recompute and cache; never persist as first-class state._
|
|
29
|
+
- **Un-addressed detail is a column.** _Test: is this row ever SELECTed / JOINed / FK'd alone? No ⇒ it is a JSON field on its parent._
|
|
30
|
+
- **Another system's record → keep the pointer.** _Test: does a specialized service already own this — chat, telemetry, object store? ⇒ store its id, not a copy._
|
|
31
|
+
- **A surviving table names the invariant it buys.** Each kept structure pays for one guarantee — content-addressed immutable rows buy reproducibility, a monotonic sequence buys ordering/sync, an atomic write boundary buys multi-row atomicity. Drop the requirement and the table drops with it; keep the requirement and the structure is the price a blob cannot pay.
|
|
32
|
+
|
|
33
|
+
Table count tracks **requirements, not domain richness** — a rich domain does not entitle a schema to a table per noun.
|
|
34
|
+
|
|
7
35
|
## Keys & the shared vocabulary
|
|
8
36
|
|
|
9
37
|
Three column roles are fixed across every table and every project:
|
|
@@ -33,6 +61,6 @@ Reference columns name what they point at: `<entity>_id` for a UUID-PK reference
|
|
|
33
61
|
|
|
34
62
|
## Vocabulary / lookup tables
|
|
35
63
|
|
|
36
|
-
A controlled
|
|
64
|
+
A controlled vocabulary earns a **table** only when a user row FKs into it and reads its `label` / `description` at runtime; a controlled vocabulary that is static, dev-authored config nobody references by FK stays **config** (§ What earns a table) — enumerable is not the same as tabular, and a `type`-style column validated against the constants file is preferred over an FK to a seeded mirror. When a table is earned, it follows a fixed shape: `id` (UUID) · `slug` (UNIQUE) · `label` · optional `description` · `status` · timestamps.
|
|
37
65
|
|
|
38
66
|
- **Seeds are generated, never hand-written** — the source of truth is a CSV or a shared package; a generator emits the `*.seed.sql` with UUIDv5 ids and an idempotent `ON CONFLICT(slug)` upsert that preserves live counts / admin-tuned columns. Hand-editing seed SQL is ❌ — regenerate it.
|
|
@@ -61,6 +61,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
61
61
|
| Document feature/module (LLD) | [`templates/feature.md`](templates/feature.md) |
|
|
62
62
|
| Document data flow / state / Redux | [`templates/feature.md`](templates/feature.md) — they are sections of the feature doc |
|
|
63
63
|
| Create/update changelog | [`templates/changelog-entry.md`](templates/changelog-entry.md) (record) |
|
|
64
|
+
| Record per-commit refinement (ledger block) | [`templates/refinement-ledger.md`](templates/refinement-ledger.md) (record — written at commit time, distilled by the `retro` agent) |
|
|
64
65
|
| Create/update plan | [`templates/plan.md`](templates/plan.md) (record) |
|
|
65
66
|
| Record/revise architecture decision | [`templates/architecture-decision.md`](templates/architecture-decision.md) — one AD per subject; revisions update it in place |
|
|
66
67
|
| System at a glance | [`templates/system-overview.md`](templates/system-overview.md) |
|
|
@@ -11,7 +11,8 @@ const RULES = [
|
|
|
11
11
|
{ id: 'progress-marker', severity: 'block', scope: 'truth', pattern: /\bphases?\s+\d[^.\n]{0,40}\b(complete|done)\b|\b(build|implementation) (is )?(\d+%|partially) (complete|done)\b/i, message: 'progress marker — progress lives in the plan/backlog record' },
|
|
12
12
|
{ id: 'temporal-hedge', severity: 'warn', scope: 'truth', pattern: /\bnot yet\b|\bfor now\b|\bcurrently\b|\bstill (unsupported|missing|pending|unimplemented|in progress)\b/i, message: 'temporal hedge — state the fact without "currently / not yet / for now"' },
|
|
13
13
|
{ id: 'predecessor-frame', severity: 'warn', scope: 'truth', pattern: /\bpreviously\b|\bthe old \w+\b|\blegacy \w+ (was|is)\b/i, message: 'predecessor framing — describe the one current design' },
|
|
14
|
-
|
|
14
|
+
// docs/tests/ behavioral checklists use `- [ ]` as test-step notation (step → **Assert**), not progress tracking — exempt that one folder from this rule; every other truth doc still bans checkboxes.
|
|
15
|
+
{ id: 'status-glyph', severity: 'warn', scope: 'truth', exempt: /(^|\/)docs\/tests\//, pattern: /(^|\s)(✅|⏳|- \[[ x]\])/u, message: 'status glyph / checklist in a truth doc — tracking belongs in a record' },
|
|
15
16
|
{ id: 'date-in-truth-doc', severity: 'warn', scope: 'truth', pattern: /\b20\d{2}-\d{2}-\d{2}\b/, message: 'date in a truth doc — only the AD Decision Changelog and structure.md Health Log tails carry dates' },
|
|
16
17
|
];
|
|
17
18
|
|
|
@@ -71,6 +72,7 @@ function lintFile(path, findings) {
|
|
|
71
72
|
|
|
72
73
|
for (const rule of RULES) {
|
|
73
74
|
if (rule.scope !== scope || disabled.has(rule.id)) continue;
|
|
75
|
+
if (rule.exempt && rule.exempt.test(path)) continue;
|
|
74
76
|
for (const { n, line } of lines) {
|
|
75
77
|
if (!rule.pattern.test(line)) continue;
|
|
76
78
|
if (line.includes(`doc-lint-disable: ${rule.id}`) || new RegExp(`doc-lint-disable:[^>]*\\b${rule.id}\\b`).test(line)) continue;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Refinement Ledger
|
|
2
|
+
|
|
3
|
+
Record. Use for: the append-only per-commit journal of session refinement — one block per non-mechanical commit, written by the committing agent at commit time and staged **inside the commit it describes**. Blocks are immutable once committed: never edited, renumbered, or reconciled; a correction is a new block referencing the old. The ledger is exempt from doc-health passes by genre — it is history and can never be "wrong".
|
|
4
|
+
|
|
5
|
+
Monthly files: `docs/history/ledger/YYYY-MM.md`, created on first block — the folder is never scaffolded empty. Distillation is the `retro` agent's job; this template owns only the capture format.
|
|
6
|
+
|
|
7
|
+
## Block format
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
### {YYYY-MM-DD} · {surface} — {one-line outcome}
|
|
11
|
+
- **Ask:** {what the user asked, compressed — taste and preference statements quoted verbatim}
|
|
12
|
+
- **Iterations:** {N} · rejected: {what was rejected and why} | none
|
|
13
|
+
- **Skills:** {skill}@{version} — survived | partially survived | overridden ({why, briefly}) | none used
|
|
14
|
+
- **Change:** {added/changed X, which does Y, because Z — behavior first, mechanism second}
|
|
15
|
+
- **Discovered:** {non-obvious fact learned by running the product — environment quirk, platform ceiling, seam behavior, dependency constraint} | none
|
|
16
|
+
- **Class:** {one or more keywords — suggestive vocabulary, not a closed enum; see Field rules}
|
|
17
|
+
- **Pin:** {enforced artifact written in this commit: test / token / guardrail / schema} | none — candidate: {what should hold it}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Field rules
|
|
21
|
+
|
|
22
|
+
- **Every field present; "none" stated explicitly.** An absent field is a template violation. Sessions assert success by default — the required `rejected:` and `overridden` entries are the counterweight; an honestly empty failure field is information too.
|
|
23
|
+
- **`surface`** uses the repo's ownership vocabulary — the owning feature doc's topic or an `owns:` path stem — so the ledger is queryable per surface.
|
|
24
|
+
- **`Ask` quotes taste verbatim.** The user's preference wording is the one thing no skill can infer and no rebuild recovers; the ledger is its durable home.
|
|
25
|
+
- **`Skills` records efficacy honestly** — survived / partially survived / overridden with a reason. These verdicts are the raw data the `retro` agent aggregates into skill-evolution findings; sanitizing them into success stories destroys the mechanism's value.
|
|
26
|
+
- **`Discovered` holds what only running the product teaches.** If it was learned in use, it is recorded here the same day — this field feeds the pin candidates.
|
|
27
|
+
- **`Class` is a suggestive vocabulary, not a closed enum.** Tag with one or more keywords, preferring an existing term over a synonym so the `retro` agent can cluster; coin a new one when nothing fits — a recurring coinage is itself retro signal that the vocabulary (or the doc set) is missing a category. Suggested keywords: `ux` · `ui` · `visual` · `taste` · `layout` · `motion` · `interaction` · `copy` · `a11y` · `responsiveness` · `navigation` · `state` · `structure` · `architecture` · `seam` · `contract` · `schema` · `data` · `content` · `seed` · `performance` · `caching` · `resilience` · `error-handling` · `security` · `auth` · `observability` · `logging` · `testing` · `tooling` · `dependency` · `ops` · `deploy` · `env` · `ci` · `i18n` · `docs`.
|
|
28
|
+
- **`Pin` closes the loop:** the enforced artifact written in this commit, or the named candidate for the `retro` agent to flag. A taste-verified behavior with `Pin: none` and no candidate is a template smell.
|
|
29
|
+
- **Out-of-session commits** (the committing session did not do the work): fill what the diff and conversation evidence support; mark the rest `unknown — committed out-of-session`.
|
|
30
|
+
|
|
31
|
+
## Exemptions (closed list)
|
|
32
|
+
|
|
33
|
+
No block for: release/bot commits, harness installs and bumps, lockfile-only changes, pure renames/moves, and ledger housekeeping itself. Everything else gets a block, however short.
|
|
@@ -30,6 +30,7 @@ Each topic has one canonical location. Read from here, not from plans or changel
|
|
|
30
30
|
| Testing strategy | `docs/tests/` | strategy.md |
|
|
31
31
|
| Historical plans | `docs/history/plans/` | YYYY-MM-DD-name.md |
|
|
32
32
|
| Change records | `docs/history/changelog/` | Individual entries |
|
|
33
|
+
| Refinement Ledger | `docs/history/ledger/` | YYYY-MM.md (append-only, written at commit time) |
|
|
33
34
|
| Migration runbooks | `docs/history/migrations/` | YYYY-MM-DD-name.md |
|
|
34
35
|
| Deep-research artifacts | `docs/history/research/{topic}/` | README.md + findings.md + sources.md |
|
|
35
36
|
| Brainstorm design records | `docs/research/{topic}-brainstorm/` (active; legacy `-brainstorming/`) → `docs/history/brainstorms/{topic}/` (harvested; user deletes or commits) | thesis.md + forks.md + ledger.md + state.md |
|
|
@@ -51,6 +52,7 @@ Every doc is a **truth document** (states current absolutes, topic-named, update
|
|
|
51
52
|
- `docs/tests/`: Testing strategy and test docs. Present when the repo has a test posture worth documenting.
|
|
52
53
|
- `docs/history/plans/`: Records. Must have `Status:` field. Never modify after completion.
|
|
53
54
|
- `docs/history/changelog/`: Records. Append-only.
|
|
55
|
+
- `docs/history/ledger/`: Records. The Refinement Ledger — an append-only per-commit refinement journal (monthly `YYYY-MM.md` files) written by the committing agent, each block staged inside the commit it describes; block format is the `documentation` skill's `templates/refinement-ledger.md`, distillation is the `retro` agent. Blocks are immutable — never edited, never reconciled; the folder is never scaffolded empty.
|
|
54
56
|
- `docs/history/migrations/`: Records. One-shot migration/upgrade runbooks — authored before execution, outcome-stamped and frozen after.
|
|
55
57
|
- `docs/history/research/{topic}/`: Deep-research artifacts — the dumped output of a research pass, one folder per topic (conventionally `README.md` synthesis + `findings.md` verified claims & citations + `sources.md`). A point-in-time, cited record — **not** a living authority doc: it owns no code (no `owns:` frontmatter) and is never edited to "stay current." A spec/plan links to it for grounding; a new question gets a new topic folder.
|
|
56
58
|
- `docs/research/{topic}-brainstorm/` → `docs/history/brainstorms/{topic}/`: Brainstorm design records — the Brainstorming-Mode session for a topic (working surface `thesis.md` + `forks.md` + `ledger.md` + `state.md` + `basis/` + `fragments/`, plus an untracked `ops/` capture layer deleted at stop), written by the `brainstorm` skill and its twin agent. An active session lives under `docs/research/` (legacy folders carry the older `-brainstorming/` suffix); on a **passed harvest** it **moves** to `docs/history/brainstorms/` — the completion marker — and the **user decides whether the moved folder is deleted or committed** as provenance. Each of the two folders carries a `Readme.md` index (the skill reads it at start instead of scanning). Author-created (never scaffolded empty), one folder per design conversation. Owns no code (no `owns:` frontmatter); the harvest routes its conclusions into `architecture/`/`features/`/`history/`. (Distinct from `docs/history/research/{topic}/` above — that is a frozen deep-research record, not a brainstorm session.)
|