@nurix/etna 0.19.43 → 0.19.44
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/bin/etna.js +33 -6
- package/data/harness-index.json +1 -1
- package/data/harnesses/apollo/agents/maintenance.md +3 -1
- package/data/harnesses/apollo/harness.json +2 -2
- package/data/harnesses/apollo/skills/boundary/SKILL.md +3 -1
- package/data/harnesses/apollo/skills/documentation/SKILL.md +2 -0
- package/data/harnesses/apollo/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/apollo/skills/documentation/templates/bookkeeping.md +18 -0
- package/data/harnesses/apollo/skills/documentation/templates/journal.md +13 -0
- package/data/harnesses/apollo/skills/documentation/templates/plan.md +3 -0
- package/data/harnesses/apollo/skills/test-plan/SKILL.md +2 -0
- package/data/harnesses/code/agents/bookkeeper.md +27 -0
- package/data/harnesses/code/agents/maintenance.md +3 -1
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/hooks/awareness.mjs +370 -0
- package/data/harnesses/code/hooks/check-bookkeeping-clean.mjs +19 -0
- package/data/harnesses/code/hooks/check-changelog-presence.mjs +48 -0
- package/data/harnesses/code/hooks/check-completion-integrity.mjs +68 -0
- package/data/harnesses/code/hooks/check-ownership.mjs +22 -0
- package/data/harnesses/code/hooks/compliance.mjs +332 -0
- package/data/harnesses/code/hooks/hooks.json +16 -10
- package/data/harnesses/code/hooks/lib/frozen.mjs +58 -0
- package/data/harnesses/code/hooks/lib/ownership.mjs +223 -0
- package/data/harnesses/code/hooks/lib/state.mjs +156 -0
- package/data/harnesses/code/skills/boundary/SKILL.md +3 -1
- package/data/harnesses/code/skills/documentation/SKILL.md +2 -0
- package/data/harnesses/code/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/code/skills/documentation/templates/bookkeeping.md +18 -0
- package/data/harnesses/code/skills/documentation/templates/journal.md +13 -0
- package/data/harnesses/code/skills/documentation/templates/plan.md +3 -0
- package/data/harnesses/code/skills/test-plan/SKILL.md +2 -0
- package/data/harnesses/delivery/agents/maintenance.md +3 -1
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/skills/documentation/SKILL.md +2 -0
- package/data/harnesses/delivery/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/delivery/skills/documentation/templates/bookkeeping.md +18 -0
- package/data/harnesses/delivery/skills/documentation/templates/journal.md +13 -0
- package/data/harnesses/delivery/skills/documentation/templates/plan.md +3 -0
- package/data/harnesses/etna/agents/maintenance.md +3 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/boundary/SKILL.md +3 -1
- package/data/harnesses/etna/skills/documentation/SKILL.md +2 -0
- package/data/harnesses/etna/skills/documentation/templates/Readme.md +2 -0
- package/data/harnesses/etna/skills/documentation/templates/bookkeeping.md +18 -0
- package/data/harnesses/etna/skills/documentation/templates/journal.md +13 -0
- package/data/harnesses/etna/skills/documentation/templates/plan.md +3 -0
- package/package.json +2 -2
- package/data/harnesses/code/hooks/generate-ownership-index.mjs +0 -148
package/bin/etna.js
CHANGED
|
@@ -162,16 +162,32 @@ function migrateFromPluginInstall(targetDir, pluginName) {
|
|
|
162
162
|
// Hook scripts shipped by earlier harness versions (the legacy memory-ledger tier) and since retired.
|
|
163
163
|
// mergeHooks is additive, so an upgrade must explicitly remove both the stale settings.json
|
|
164
164
|
// entries pointing at these and the leftover script files they reference.
|
|
165
|
-
const RETIRED_HOOKS = [
|
|
165
|
+
const RETIRED_HOOKS = [
|
|
166
|
+
'session-stop.js',
|
|
167
|
+
'post-tool-failure.js',
|
|
168
|
+
'post-commit.js',
|
|
169
|
+
'generate-ownership-index.mjs', // folded into awareness.mjs — unretired, the index would inject twice
|
|
170
|
+
];
|
|
166
171
|
|
|
167
172
|
// Remove settings.json hook entries and .claude/hooks/ files for retired hook scripts.
|
|
168
|
-
|
|
173
|
+
// Bundle-aware: a name on the retired list is skipped while THIS bundle still ships it —
|
|
174
|
+
// several harnesses share the list, and they retire the same script at different versions.
|
|
175
|
+
function retireOldHooks(targetDir, bundledHarnessDir) {
|
|
169
176
|
const removed = [];
|
|
177
|
+
const bundledHooksDir = join(bundledHarnessDir, 'hooks');
|
|
178
|
+
const stillShipped = new Set(
|
|
179
|
+
existsSync(bundledHooksDir)
|
|
180
|
+
? readdirSync(bundledHooksDir, { withFileTypes: true })
|
|
181
|
+
.filter((e) => e.isFile())
|
|
182
|
+
.map((e) => e.name)
|
|
183
|
+
: [],
|
|
184
|
+
);
|
|
185
|
+
const retired = RETIRED_HOOKS.filter((name) => !stillShipped.has(name));
|
|
170
186
|
const settingsPath = join(targetDir, '.claude', 'settings.json');
|
|
171
187
|
if (existsSync(settingsPath)) {
|
|
172
188
|
const settings = readJson(settingsPath);
|
|
173
189
|
const isRetired = (h) =>
|
|
174
|
-
|
|
190
|
+
retired.some((name) => (h.command || '').includes(`/hooks/${name}`));
|
|
175
191
|
let pruned = 0;
|
|
176
192
|
for (const [event, groups] of Object.entries(settings.hooks || {})) {
|
|
177
193
|
for (const group of groups) {
|
|
@@ -187,7 +203,7 @@ function retireOldHooks(targetDir) {
|
|
|
187
203
|
removed.push(`${pruned} retired hook entr${pruned === 1 ? 'y' : 'ies'} in settings.json`);
|
|
188
204
|
}
|
|
189
205
|
}
|
|
190
|
-
for (const name of
|
|
206
|
+
for (const name of retired) {
|
|
191
207
|
const file = join(targetDir, '.claude', 'hooks', name);
|
|
192
208
|
if (existsSync(file)) {
|
|
193
209
|
rmSync(file, { force: true });
|
|
@@ -296,11 +312,22 @@ function groupHasCommand(group, command) {
|
|
|
296
312
|
// already exists there; a new matcher creates a new group. Returns count of hooks added.
|
|
297
313
|
function mergeHooks(targetDir, bundledHooksJson) {
|
|
298
314
|
if (!existsSync(bundledHooksJson)) return 0;
|
|
299
|
-
const
|
|
315
|
+
const bundled = readJson(bundledHooksJson);
|
|
316
|
+
const incoming = bundled.hooks || {};
|
|
300
317
|
const settingsPath = join(targetDir, '.claude', 'settings.json');
|
|
301
318
|
const settings = readJson(settingsPath);
|
|
302
319
|
settings.hooks = settings.hooks || {};
|
|
303
320
|
let added = 0;
|
|
321
|
+
// Harness-shipped permission defaults (e.g. Edit/Write on docs/** flow without prompts —
|
|
322
|
+
// the deny hooks still hard-block frozen/protected paths underneath). Additive, idempotent.
|
|
323
|
+
for (const rule of bundled.permissions?.allow || []) {
|
|
324
|
+
settings.permissions = settings.permissions || {};
|
|
325
|
+
const allowList = (settings.permissions.allow = settings.permissions.allow || []);
|
|
326
|
+
if (!allowList.includes(rule)) {
|
|
327
|
+
allowList.push(rule);
|
|
328
|
+
added += 1;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
304
331
|
for (const [event, groups] of Object.entries(incoming)) {
|
|
305
332
|
const existingGroups = (settings.hooks[event] = settings.hooks[event] || []);
|
|
306
333
|
for (const group of groups) {
|
|
@@ -504,7 +531,7 @@ async function installHarness(harnessName, harnesses) {
|
|
|
504
531
|
|
|
505
532
|
// Retire hooks earlier harness versions shipped before merging, so the additive merge
|
|
506
533
|
// never resurrects an entry pointing at a script this bundle no longer carries.
|
|
507
|
-
for (const r of retireOldHooks(targetDir)) notices.push(`removed ${r}`);
|
|
534
|
+
for (const r of retireOldHooks(targetDir, bundledHarnessDir)) notices.push(`removed ${r}`);
|
|
508
535
|
|
|
509
536
|
// Merge the bundle's hooks.json into the project's settings.json (idempotent).
|
|
510
537
|
const added = mergeHooks(targetDir, join(bundledHarnessDir, 'hooks', 'hooks.json'));
|
package/data/harness-index.json
CHANGED
|
@@ -115,7 +115,7 @@ For unowned code paths:
|
|
|
115
115
|
|
|
116
116
|
### Step 6: Report & update tracking
|
|
117
117
|
|
|
118
|
-
1. Update `docs/structure.md` Health Log with today's date and summary — **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.
|
|
118
|
+
1. Update `docs/structure.md` Health Log with today's date and summary — **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.
|
|
119
119
|
2. Update `docs/memory/maintenance.md` with last review date, stale docs fixed, unowned paths, backlog items created.
|
|
120
120
|
3. Report findings: stale docs, broken ownership, unowned code, architecture drift, backlog health.
|
|
121
121
|
|
|
@@ -137,6 +137,7 @@ docs/
|
|
|
137
137
|
├── features/ # Feature specs — the only first-class doc unit (flat; ownership in each doc's `owns:` frontmatter)
|
|
138
138
|
│ └── {group}/ # browse-only subfolder for grouping; NEVER a module; may carry a Readme.md
|
|
139
139
|
├── operations/ # Setup, development, deployment, CI/CD
|
|
140
|
+
│ └── bookkeeping.md # the shared doc-sync work queue (hook-appended, bookkeeper-drained, walled at commit) — author-created, never scaffolded; treat rows as live work, never as drift
|
|
140
141
|
├── research/ # In-progress brainstorm sessions ({topic}-brainstorm/; legacy -brainstorming/) + standing research; Readme.md is the index
|
|
141
142
|
│ └── {topic}-brainstorm/ # created by the `brainstorm` skill; moves to history/brainstorms/ on a passed harvest
|
|
142
143
|
├── history/
|
|
@@ -144,6 +145,7 @@ docs/
|
|
|
144
145
|
│ ├── changelog/ # Individual entries (YYYY-MM-DD-{three-words}.md; written at commit time)
|
|
145
146
|
│ ├── plans/ # Implementation plans (Status field required)
|
|
146
147
|
│ ├── migrations/ # One-shot migration/upgrade runbooks (YYYY-MM-DD-{slug}.md; outcome-stamped then frozen)
|
|
148
|
+
│ ├── journal.md # Append-only mid-execution knowledge capture (one line per fact; resolves by landing in its owning doc) — author-created, never scaffolded
|
|
147
149
|
│ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
|
|
148
150
|
│ ├── research/ # Deep-research records ({topic}/ — README.md synthesis + findings.md + sources.md); frozen, cited, owns no code
|
|
149
151
|
│ └── backlog.md ✱ # Tracked work items by priority (P0-P3)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"harness": "apollo",
|
|
3
3
|
"name": "apollo",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.2",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierignore",
|
|
7
7
|
".prettierrc.json",
|
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
"docs/history/backlog.md",
|
|
15
15
|
"docs/memory/main.md"
|
|
16
16
|
],
|
|
17
|
-
"digest": "
|
|
17
|
+
"digest": "3c2fc6ad2e82"
|
|
18
18
|
}
|
|
@@ -61,9 +61,11 @@ The packs are a floor, not a fence: report any contract that passes the ships-gr
|
|
|
61
61
|
|
|
62
62
|
**BLOCK** = any CRITICAL. HIGH findings yield **PASS WITH AMENDMENTS** — fold the amendments into the plan before coding. Order amendments sequencing-first: many violations dissolve by reordering steps (expand-then-contract, migrate-before-code) rather than changing what ships — prefer that fix, drawn from the entry's safe-change sequence.
|
|
63
63
|
|
|
64
|
+
6. **Record the verdict in the plan's `Gates:` line.** Rewrite only your own segment, to exactly `Boundary: passed YYYY-MM-DD` (PASS, or PASS WITH AMENDMENTS once the amendments are folded) or `Boundary: blocked YYYY-MM-DD` (BLOCK). The compliance hook greps these exact forms — implementation edits stay blocked while the segment reads `pending`. A plan with no `Gates:` line predates the format; add the line rather than skipping the write-back.
|
|
65
|
+
|
|
64
66
|
## Rules
|
|
65
67
|
|
|
66
|
-
- **Read-only.** You never edit the plan, the code, or any doc
|
|
68
|
+
- **Read-only, one exception.** You never edit the plan's content, the code, or any doc — the user folds your amendments into the plan. The single write you own is the plan's `Gates:` line (step 6), your segment only.
|
|
67
69
|
- **Verify in source.** Never flag from plan text alone — read both sides of every finding and cite them: code as `file:line`, doctrine as the doc path.
|
|
68
70
|
- **No other side, no violation.** An intersection with no traced consumer and no doctrine behind it isn't a violation — it's a **new edge**: report it in its own section with the hardening its mechanism prescribes (version the cache key now, make the enum append-only now), so the fragile edge is born safe.
|
|
69
71
|
- **A clean report is valid.** Zero violations means say so — the coverage table is the evidence it was checked, not skipped. Don't pad findings.
|
|
@@ -73,6 +73,8 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
73
73
|
| Testing strategy | [`templates/testing-strategy.md`](templates/testing-strategy.md) |
|
|
74
74
|
| Behavioral checklist for one feature (`docs/tests/{feature}.md`) | [`templates/behavioral-checklist.md`](templates/behavioral-checklist.md) — the verification gate's driving script, and the source its suite tests are drawn from |
|
|
75
75
|
| Recurring procedure/setup | [`templates/operations-procedure.md`](templates/operations-procedure.md) |
|
|
76
|
+
| Capture mid-execution knowledge (`docs/history/journal.md`) | [`templates/journal.md`](templates/journal.md) (record — append-only; a row resolves by landing in its owning doc) |
|
|
77
|
+
| Bookkeeping work queue (`docs/operations/bookkeeping.md`) | [`templates/bookkeeping.md`](templates/bookkeeping.md) — machine-read row grammar; appended by hooks and sessions, drained by the `bookkeeper` agent, walled at Stop and commit |
|
|
76
78
|
| One-shot migration/upgrade | [`templates/migration-runbook.md`](templates/migration-runbook.md) (record) |
|
|
77
79
|
| Add to protected files | [`templates/protected-files.md`](templates/protected-files.md) |
|
|
78
80
|
| Create/update root README | [`templates/root-readme.md`](templates/root-readme.md) |
|
|
@@ -16,6 +16,7 @@ One file per template. Every template is either a **truth document** (states cur
|
|
|
16
16
|
| Testing strategy | [testing-strategy.md](testing-strategy.md) | Truth |
|
|
17
17
|
| Behavioral checklist | [behavioral-checklist.md](behavioral-checklist.md) | Truth |
|
|
18
18
|
| Operations procedure | [operations-procedure.md](operations-procedure.md) | Truth |
|
|
19
|
+
| Bookkeeping ledger | [bookkeeping.md](bookkeeping.md) | Truth (work queue) |
|
|
19
20
|
| Protected files | [protected-files.md](protected-files.md) | Truth |
|
|
20
21
|
| Project root README | [root-readme.md](root-readme.md) | Truth |
|
|
21
22
|
| docs/README.md (doc index) | [docs-readme.md](docs-readme.md) | Truth |
|
|
@@ -23,6 +24,7 @@ One file per template. Every template is either a **truth document** (states cur
|
|
|
23
24
|
| Plan | [plan.md](plan.md) | Record |
|
|
24
25
|
| Changelog entry | [changelog-entry.md](changelog-entry.md) | Record |
|
|
25
26
|
| Migration runbook | [migration-runbook.md](migration-runbook.md) | Record |
|
|
27
|
+
| Journal | [journal.md](journal.md) | Record (append-only) |
|
|
26
28
|
| CHANGELOG master index | [changelog-index.md](changelog-index.md) | Record index (append-only) |
|
|
27
29
|
| Backlog | [backlog.md](backlog.md) | Record (append-only) |
|
|
28
30
|
| Memory (main agent) | [memory-main.md](memory-main.md) | Record (append-only ledger) |
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Bookkeeping ledger (docs/operations/bookkeeping.md)
|
|
2
|
+
|
|
3
|
+
Truth document with an unusual lifecycle: a **work queue**, not an archive. Rows are appended mechanically by the awareness hook (`auto:`) and deliberately by working sessions (`note:`), drained by the `bookkeeper` agent, and walled at Stop and commit — a commit is possible only when every row is resolved (deleted) or converted to `waived:`. What survives in git — `waived:` and `needs-session:` rows — is exactly what a PR reviewer should see.
|
|
4
|
+
|
|
5
|
+
The row grammar is machine-read by the hooks and CI; keep it exact. A `waived:` row's `expires=` date is enforced: CI honors the waiver until the date, then fails. `waived:` rows whose finding kind is `dead-glob` double as the dead-glob allowlist.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
# Bookkeeping
|
|
9
|
+
|
|
10
|
+
The shared work queue keeping documentation and code in sync — rows are appended mechanically (auto:) and by working sessions (note:), drained by the bookkeeper agent, and walled at commit: a commit is possible only when every row is resolved or waived. Row grammar and lifecycle: the behavioral-hooks feature doc. A `waived:` row carries `expires=` and is PR-reviewable history.
|
|
11
|
+
|
|
12
|
+
- auto: YYYY-MM-DD · {finding-kind} · {description} → {action} | sid={session_id} tp={transcript_path} ts={ISO}
|
|
13
|
+
- note: YYYY-MM-DD · {area} · {one-line context only the session holds} → lands-in: {owning doc | backlog | memory} | sid=… tp=… ts=…
|
|
14
|
+
- needs-session: YYYY-MM-DD · {what the bookkeeper could not ground} → main session resolves | refs={original row ts}
|
|
15
|
+
- waived: YYYY-MM-DD · {what is deferred} · reason: {why} → expires=YYYY-MM-DD
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Finding kinds for `auto:`: `dead-glob` · `doc-implicated` · `doc-lint` · `header-missing` · `index-row-missing` · `boundary-scan-suggested` · `doc-placement`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Journal (docs/history/journal.md)
|
|
2
|
+
|
|
3
|
+
Record — append-only. Use for: durable mid-execution knowledge — a fact discovered while building that some owning doc will eventually carry, captured the moment it exists so it survives the session. A row is resolved by landing in its owning doc: the row is deleted and the changelog entry cites it. The file stays short by construction; a journal that only grows is a queue nobody drains.
|
|
4
|
+
|
|
5
|
+
One line per fact. Never narrative, never progress notes (progress lives in the plan), never user preferences (those go to the runtime's memory store).
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
# Journal
|
|
9
|
+
|
|
10
|
+
Append-only capture of mid-execution knowledge — one line per fact, written the moment it exists, resolved by landing in its owning doc (delete the row, cite it in the changelog entry). Format: `YYYY-MM-DD · <area> · <one-line fact> → lands-in: <owning doc | backlog | memory>`
|
|
11
|
+
|
|
12
|
+
- YYYY-MM-DD · {area} · {one-line fact} → lands-in: {owning doc | backlog | memory}
|
|
13
|
+
```
|
|
@@ -4,10 +4,13 @@ Record. Use for: every implementation plan. Plans are created here directly with
|
|
|
4
4
|
|
|
5
5
|
The `boundary` skill parses the **Proposed Changes** sections to check boundary impact before execution, and the `test-plan` skill writes a **Test Obligations** section into the plan at the same gate. Keep that structure stable — section headings and bullet shape are load-bearing for the parsers, and the Test Obligations table is the ledger the verification gate discharges before the plan may reach `Status: Complete`.
|
|
6
6
|
|
|
7
|
+
The **`Gates:`** line is machine-read: the compliance hook greps exactly the forms below, and implementation edits are blocked while a segment reads `pending`. Each gate skill rewrites only its own segment when it runs — `boundary` to `Boundary: passed YYYY-MM-DD` or `Boundary: blocked YYYY-MM-DD`; `test-plan` to `Test-plan: written YYYY-MM-DD (N rows)`. Never hand-edit the line to skip a gate.
|
|
8
|
+
|
|
7
9
|
```
|
|
8
10
|
# {Feature Name}
|
|
9
11
|
|
|
10
12
|
**Status:** Draft | In Progress | Complete | Abandoned
|
|
13
|
+
**Gates:** Boundary: pending · Test-plan: pending
|
|
11
14
|
**Spec:** [docs/features/{feature}.md](../../features/{feature}.md)
|
|
12
15
|
**Started:** YYYY-MM-DD
|
|
13
16
|
**Completed:** YYYY-MM-DD <!-- fill when status flips to Complete -->
|
|
@@ -73,6 +73,8 @@ An e2e obligation (a scenario in the project's e2e tree per `testing.md`) is ear
|
|
|
73
73
|
|
|
74
74
|
A behavior with no obligation is stated too, with the reason (compiler-guarded, covered by an existing test) — an empty cell reads as "not yet analyzed"; an explicit "none — compiler-guarded" reads as "checked."
|
|
75
75
|
|
|
76
|
+
6. **Record the write in the plan's `Gates:` line.** Rewrite only your own segment, to exactly `Test-plan: written YYYY-MM-DD (N rows)` where N is the ledger's row count. The compliance hook greps this exact form. A plan with no `Gates:` line predates the format; add the line rather than skipping the write-back.
|
|
77
|
+
|
|
76
78
|
## Rules
|
|
77
79
|
|
|
78
80
|
- **Manifest only.** You write the Test Obligations section into the plan and a chat summary. You write **no** test files and **no** `docs/tests/` checklist — those are verification-gate-time and Completion-time, owned by others.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bookkeeper
|
|
3
|
+
description: Drains docs/operations/bookkeeping.md — performs mechanical fixes (owns: globs, header comments, doc-lint findings, index rows), expands note: rows into doc edits, marks rows resolved. Dispatched by the main session at turn end or commit time; never self-triggers. Triggers on "drain the bookkeeping queue", "dispatch the bookkeeper", "/bookkeeper".
|
|
4
|
+
tools: Read, Glob, Grep, Edit, Write, Bash, Skill
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Bookkeeper Agent
|
|
9
|
+
|
|
10
|
+
You drain the shared work queue at `docs/operations/bookkeeping.md`. Each row is one finding; your job is to resolve it — by doing the work it names — and delete the row. You are the asynchronous half of the harness's enforcement loop: the detector appends rows silently, you drain them, and the Stop/commit walls hold until the queue is clean or waived.
|
|
11
|
+
|
|
12
|
+
## Source-of-truth order — the repo first, the transcript last
|
|
13
|
+
|
|
14
|
+
Ground every edit in this ladder, in order. Never invent content; a fact you cannot ground is a fact you do not write.
|
|
15
|
+
|
|
16
|
+
1. **`auto:` rows are recomputable from code + docs on any machine — fix directly.** A `dead-glob` row: read the owning doc, find where the files went (`git log --follow`, glob search), update its `owns:` frontmatter. A `header-missing` row: add the file-path header comment in the file's native comment syntax. A `doc-lint` row: fix the finding, or add `<!-- doc-lint-disable: id -->` with a reason beside it when the flagged text is deliberate. An `index-row-missing` row: add the doc's row to `docs/README.md`. A `doc-implicated` row: 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.
|
|
17
|
+
2. **`note:` rows — expand strictly from the stated context.** The one-line context after the area is everything the session chose to hand you; land it in the destination the row names (`lands-in:` an owning doc, the backlog, or memory), written in that document's genre.
|
|
18
|
+
3. **A thin note, same machine only** — read a timestamp-anchored window of the transcript JSONL at the row's `tp=` path around its `ts=` stamp (never the whole file). The stamp is best-effort and dead on other clones — expected; treat an unreadable or missing transcript as "no window".
|
|
19
|
+
4. **Still ungrounded** — replace the row with a `needs-session:` row (`- needs-session: {date} · {what you could not ground} → main session resolves | refs={original ts}`) and stop working that row.
|
|
20
|
+
|
|
21
|
+
## Rules
|
|
22
|
+
|
|
23
|
+
- **Never edit frozen records** — committed changelog entries, `Status: Complete|Abandoned` plans, outcome-stamped runbooks. A finding that seems to require one gets a `needs-session:` row instead.
|
|
24
|
+
- **Every touched doc goes through the `documentation` skill's rules** — present tense, two-natures, no history narration in truth documents.
|
|
25
|
+
- **Resolution = deletion.** A finished row is removed from the queue, not annotated. Only `waived:` conversions (a reason plus `expires=YYYY-MM-DD`) and `needs-session:` rows survive your pass.
|
|
26
|
+
- **Never waive on your own judgment** — waiving is the main session's (or the user's) call; your outcomes are fixed, landed, or `needs-session:`.
|
|
27
|
+
- **Report by row**: one line each — the row, the outcome (fixed / landed in {doc} / needs-session), and the files touched. The main session relays this; keep it terse.
|
|
@@ -115,7 +115,7 @@ For unowned code paths:
|
|
|
115
115
|
|
|
116
116
|
### Step 6: Report & update tracking
|
|
117
117
|
|
|
118
|
-
1. Update `docs/structure.md` Health Log with today's date and summary — **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.
|
|
118
|
+
1. Update `docs/structure.md` Health Log with today's date and summary — **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.
|
|
119
119
|
2. Update `docs/memory/maintenance.md` with last review date, stale docs fixed, unowned paths, backlog items created.
|
|
120
120
|
3. Report findings: stale docs, broken ownership, unowned code, architecture drift, backlog health.
|
|
121
121
|
|
|
@@ -137,6 +137,7 @@ docs/
|
|
|
137
137
|
├── features/ # Feature specs — the only first-class doc unit (flat; ownership in each doc's `owns:` frontmatter)
|
|
138
138
|
│ └── {group}/ # browse-only subfolder for grouping; NEVER a module; may carry a Readme.md
|
|
139
139
|
├── operations/ # Setup, development, deployment, CI/CD
|
|
140
|
+
│ └── bookkeeping.md # the shared doc-sync work queue (hook-appended, bookkeeper-drained, walled at commit) — author-created, never scaffolded; treat rows as live work, never as drift
|
|
140
141
|
├── research/ # In-progress brainstorm sessions ({topic}-brainstorm/; legacy -brainstorming/) + standing research; Readme.md is the index
|
|
141
142
|
│ └── {topic}-brainstorm/ # created by the `brainstorm` skill; moves to history/brainstorms/ on a passed harvest
|
|
142
143
|
├── history/
|
|
@@ -144,6 +145,7 @@ docs/
|
|
|
144
145
|
│ ├── changelog/ # Individual entries (YYYY-MM-DD-{three-words}.md; written at commit time)
|
|
145
146
|
│ ├── plans/ # Implementation plans (Status field required)
|
|
146
147
|
│ ├── migrations/ # One-shot migration/upgrade runbooks (YYYY-MM-DD-{slug}.md; outcome-stamped then frozen)
|
|
148
|
+
│ ├── journal.md # Append-only mid-execution knowledge capture (one line per fact; resolves by landing in its owning doc) — author-created, never scaffolded
|
|
147
149
|
│ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
|
|
148
150
|
│ ├── research/ # Deep-research records ({topic}/ — README.md synthesis + findings.md + sources.md); frozen, cited, owns no code
|
|
149
151
|
│ └── backlog.md ✱ # Tracked work items by priority (P0-P3)
|