@nurix/etna 0.18.0 → 0.18.2

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.
Files changed (118) hide show
  1. package/README.md +6 -5
  2. package/data/harness-index.json +1 -5
  3. package/data/harnesses/code/CLAUDE.md +8 -19
  4. package/data/harnesses/code/agents/brainstorm.md +3 -3
  5. package/data/harnesses/code/agents/change-review.md +13 -10
  6. package/data/harnesses/code/agents/harness-manager.md +15 -15
  7. package/data/harnesses/code/agents/maintenance.md +10 -3
  8. package/data/harnesses/code/agents/performance-review.md +5 -0
  9. package/data/harnesses/code/harness.json +1 -1
  10. package/data/harnesses/code/rules/general.md +40 -36
  11. package/data/harnesses/code/skills/boundary/SKILL.md +15 -42
  12. package/data/harnesses/code/skills/boundary/references/boundary-taxonomy.md +366 -304
  13. package/data/harnesses/code/skills/brainstorm/README.md +9 -9
  14. package/data/harnesses/code/skills/brainstorm/SKILL.md +15 -15
  15. package/data/harnesses/code/skills/brainstorm/harvest.md +3 -3
  16. package/data/harnesses/code/skills/brainstorm/templates/backlog.md +2 -2
  17. package/data/harnesses/code/skills/brainstorm/templates/build.md +6 -6
  18. package/data/harnesses/code/skills/brainstorm/templates/decisions.md +3 -3
  19. package/data/harnesses/code/skills/brainstorm/templates/doctrine.md +2 -2
  20. package/data/harnesses/code/skills/brainstorm/templates/domain-model.md +2 -2
  21. package/data/harnesses/code/skills/brainstorm/templates/glossary.md +2 -1
  22. package/data/harnesses/code/skills/brainstorm/templates/non-goals.md +3 -7
  23. package/data/harnesses/code/skills/brainstorm/templates/questions.md +6 -5
  24. package/data/harnesses/code/skills/brainstorm/templates/state.md +1 -8
  25. package/data/harnesses/code/skills/brainstorm/templates/tech.md +6 -6
  26. package/data/harnesses/code/skills/brainstorm/templates/thesis.md +2 -2
  27. package/data/harnesses/code/skills/distiller/SKILL.md +48 -177
  28. package/data/harnesses/code/skills/distiller/references/docs-mode.md +116 -343
  29. package/data/harnesses/code/skills/distiller/references/method.md +37 -109
  30. package/data/harnesses/code/skills/documentation/SKILL.md +9 -6
  31. package/data/harnesses/code/skills/documentation/references/examples.md +30 -61
  32. package/data/harnesses/code/skills/documentation/references/style-guide.md +59 -62
  33. package/data/harnesses/code/skills/documentation/references/templates.md +26 -34
  34. package/data/harnesses/code/skills/workflow-mapper/SKILL.md +32 -11
  35. package/data/harnesses/code/skills/workflow-mapper/references/patterns.md +1 -1
  36. package/data/harnesses/discover/CLAUDE.md +60 -113
  37. package/data/harnesses/discover/agents/api.md +11 -28
  38. package/data/harnesses/discover/agents/codebase.md +12 -30
  39. package/data/harnesses/discover/agents/community.md +9 -21
  40. package/data/harnesses/discover/agents/deployed-client-bundle.md +16 -67
  41. package/data/harnesses/discover/agents/distribution-artifacts.md +21 -59
  42. package/data/harnesses/discover/agents/docs.md +11 -20
  43. package/data/harnesses/discover/agents/infra-backend-fingerprint.md +28 -68
  44. package/data/harnesses/discover/agents/packages.md +12 -28
  45. package/data/harnesses/discover/agents/session.md +18 -50
  46. package/data/harnesses/discover/agents/website.md +9 -19
  47. package/data/harnesses/discover/agents/wire-capture.md +22 -72
  48. package/data/harnesses/discover/harness.json +1 -1
  49. package/data/harnesses/discover/rules/cartography-coverage.md +94 -0
  50. package/data/harnesses/discover/rules/cartography-flows.md +99 -0
  51. package/data/harnesses/discover/rules/cartography-ia.md +88 -0
  52. package/data/harnesses/discover/rules/cartography.md +109 -0
  53. package/data/harnesses/discover/rules/discovery.md +73 -182
  54. package/data/harnesses/discover/rules/evaluation.md +92 -98
  55. package/data/harnesses/discover/rules/ingestion.md +123 -322
  56. package/data/harnesses/discover/rules/self-correction.md +94 -107
  57. package/data/harnesses/discover/rules/tradecraft.md +201 -172
  58. package/data/harnesses/hr/CLAUDE.md +21 -51
  59. package/data/harnesses/hr/harness.json +1 -1
  60. package/data/harnesses/hr/skills/interview-eval/SKILL.md +23 -11
  61. package/data/harnesses/hr/skills/interview-eval/TEMPLATE.md +49 -29
  62. package/data/harnesses/hr/skills/interview-eval/rubric.md +30 -30
  63. package/data/harnesses/kb-agi/CLAUDE.md +8 -8
  64. package/data/harnesses/kb-agi/agents/kb-agi-init.md +31 -22
  65. package/data/harnesses/kb-agi/agents/kb-catch-stale.md +1 -1
  66. package/data/harnesses/kb-agi/agents/kb-find-gaps.md +1 -1
  67. package/data/harnesses/kb-agi/agents/kb-fix-links.md +1 -1
  68. package/data/harnesses/kb-agi/agents/kb-refresh-summaries.md +2 -2
  69. package/data/harnesses/kb-agi/agents/kb-sync-metadata.md +2 -2
  70. package/data/harnesses/kb-agi/harness.json +1 -1
  71. package/package.json +1 -1
  72. package/data/harnesses/code-fable/.prettierignore +0 -12
  73. package/data/harnesses/code-fable/.prettierrc.json +0 -3
  74. package/data/harnesses/code-fable/.vscode/settings.json +0 -10
  75. package/data/harnesses/code-fable/CLAUDE.md +0 -135
  76. package/data/harnesses/code-fable/agents/brainstorm.md +0 -35
  77. package/data/harnesses/code-fable/agents/change-review.md +0 -248
  78. package/data/harnesses/code-fable/agents/harness-manager.md +0 -181
  79. package/data/harnesses/code-fable/agents/maintenance.md +0 -115
  80. package/data/harnesses/code-fable/agents/performance-review.md +0 -218
  81. package/data/harnesses/code-fable/agents/spec-mode.md +0 -56
  82. package/data/harnesses/code-fable/harness.json +0 -12
  83. package/data/harnesses/code-fable/hooks/hooks.json +0 -27
  84. package/data/harnesses/code-fable/hooks/lib/redact.mjs +0 -35
  85. package/data/harnesses/code-fable/hooks/prompt-recall.mjs +0 -155
  86. package/data/harnesses/code-fable/hooks/session-reflect.mjs +0 -285
  87. package/data/harnesses/code-fable/rules/general.md +0 -79
  88. package/data/harnesses/code-fable/rules/nomenclature.md +0 -30
  89. package/data/harnesses/code-fable/rules/typescript.md +0 -19
  90. package/data/harnesses/code-fable/skills/boundary/SKILL.md +0 -76
  91. package/data/harnesses/code-fable/skills/boundary/references/boundary-taxonomy.md +0 -734
  92. package/data/harnesses/code-fable/skills/brainstorm/README.md +0 -136
  93. package/data/harnesses/code-fable/skills/brainstorm/SKILL.md +0 -135
  94. package/data/harnesses/code-fable/skills/brainstorm/harvest.md +0 -26
  95. package/data/harnesses/code-fable/skills/brainstorm/templates/backlog.md +0 -39
  96. package/data/harnesses/code-fable/skills/brainstorm/templates/build.md +0 -37
  97. package/data/harnesses/code-fable/skills/brainstorm/templates/decisions.md +0 -29
  98. package/data/harnesses/code-fable/skills/brainstorm/templates/doctrine.md +0 -31
  99. package/data/harnesses/code-fable/skills/brainstorm/templates/domain-model.md +0 -25
  100. package/data/harnesses/code-fable/skills/brainstorm/templates/glossary.md +0 -19
  101. package/data/harnesses/code-fable/skills/brainstorm/templates/milestones.md +0 -43
  102. package/data/harnesses/code-fable/skills/brainstorm/templates/non-goals.md +0 -21
  103. package/data/harnesses/code-fable/skills/brainstorm/templates/plan-doc.md +0 -61
  104. package/data/harnesses/code-fable/skills/brainstorm/templates/questions.md +0 -35
  105. package/data/harnesses/code-fable/skills/brainstorm/templates/references.md +0 -28
  106. package/data/harnesses/code-fable/skills/brainstorm/templates/rejected.md +0 -29
  107. package/data/harnesses/code-fable/skills/brainstorm/templates/state.md +0 -8
  108. package/data/harnesses/code-fable/skills/brainstorm/templates/tech.md +0 -23
  109. package/data/harnesses/code-fable/skills/brainstorm/templates/thesis.md +0 -21
  110. package/data/harnesses/code-fable/skills/distiller/SKILL.md +0 -219
  111. package/data/harnesses/code-fable/skills/distiller/references/docs-mode.md +0 -526
  112. package/data/harnesses/code-fable/skills/distiller/references/method.md +0 -166
  113. package/data/harnesses/code-fable/skills/documentation/SKILL.md +0 -125
  114. package/data/harnesses/code-fable/skills/documentation/references/examples.md +0 -193
  115. package/data/harnesses/code-fable/skills/documentation/references/style-guide.md +0 -288
  116. package/data/harnesses/code-fable/skills/documentation/references/templates.md +0 -865
  117. package/data/harnesses/code-fable/skills/workflow-mapper/SKILL.md +0 -430
  118. package/data/harnesses/code-fable/skills/workflow-mapper/references/patterns.md +0 -214
@@ -1,526 +0,0 @@
1
- # distiller · mode `docs` — facts → documentation deltas
2
-
3
- The shared knowledge root for this mode is still [`references/method.md`](method.md) —
4
- **read it first, in this mode too.** `docs` mode reuses its surprisal, EDU-decomposition,
5
- reconciliation (ADD/UPDATE/SUPERSEDE/NOOP), and bi-temporal vocabulary unchanged. This
6
- file is the *procedure* that sequences those mechanisms one hop further down the gradient:
7
- from `docs/memory/facts/` (warm, distilled cards) into proposed edits to `docs/` (the cold,
8
- human-owned SSoT). It NEVER writes a doc on its own — it **drafts and presents**; the human
9
- disposes (P7).
10
-
11
- > `facts` mode = inbox → cards. `docs` mode = cards → *presented* doc deltas. One component,
12
- > two modes, one algorithm root. distill② is the greenfield hop no surveyed tool has built
13
- > (prior art stops at index/retrieval); the discipline below is what keeps it from corrupting
14
- > documentation.
15
-
16
- ---
17
-
18
- ## The audit-trail invariant (the spine)
19
-
20
- Every rule here serves one invariant, because the load-bearing moment in this mode is the
21
- **human-approval moment**, and that moment is only trustworthy if the reviewer can
22
- mechanically check every claim:
23
-
24
- > **Two-way traceability.** Every drafted delta *line* names the fact-card(s) it decomposes
25
- > from (forward: delta → card). Every consumed card names the doc(s) it was digested into
26
- > (backward: card → delta). Every card already names the sessions/commits it came from
27
- > (`provenance`, from `facts` mode). The chain **doc-line → card → session/commit**
28
- > must resolve end to end with no orphan link. A delta line with no card, or a card marked
29
- > digested into a doc that does not contain its content, is a **defect**: the run fails its
30
- > acceptance check, the line is not presented.
31
-
32
- This mode introduces **no prose that is not a decomposition of a card** — decomposition-with-
33
- citation, exactly as `facts` mode decomposes inbox entries into cards. If the agent cannot
34
- cite a card for a sentence, that sentence is not written.
35
-
36
- ---
37
-
38
- ## Design lens: the six ways facts→docs corrupts documentation
39
-
40
- Designed **failure-modes-outward.** Every step below names the hole it closes; if a step
41
- seems heavy, trace it to the failure it prevents.
42
-
43
- | # | Failure mode | What it looks like | The protection that closes it |
44
- |---|---|---|---|
45
- | **F1** | **Invention** | The draft asserts something no card says — interpolated, generalized, or hallucinated prose. | Decomposition-never-invention: every line carries `[from: fact-…]`; a line with no card behind it is illegal and dropped (Step 3, Acceptance A2). |
46
- | **F2** | **Stale-card application** | A superseded/invalidated card is written into a doc as if current. | Bi-temporal gate: only `invalid_from: null` cards are eligible; superseded cards are skipped and named in the report (Step 2). |
47
- | **F3** | **Double digestion** | The same card is written into the same doc twice across runs. | `digested_into:` on the card is the idempotency mark — a (card, doc) pair already recorded is not re-drafted (Resolution 3, Step 2). |
48
- | **F4** | **Conflict steamrolling** | A card contradicts existing prose and the draft silently overwrites it. | Card-vs-prose conflicts become **D7 questions**, never edits (Resolution 2, Step 4). |
49
- | **F5** | **Pillar-drift absorption** | A card contradicting a doctrine/decision headline is quietly written into a doc, laundering a belief change. | Pillar escape valve: such a card emits a *propose-Brainstorming-Mode* item, never a doc edit (Resolution 4, Step 2.4). |
50
- | **F6** | **Partial-approval limbo** | Human approves 3 of 5 lines; the card is marked fully digested (losing 2) or fully un-digested (re-proposing 3). | Partial digestion: `digested_into:` records only the (card → doc) pairs *actually written*; declined lines → backlog (D10); the card recirculates only its un-applied content (Resolution 3, Step 6). |
51
-
52
- Two structural failures sit above these: **frozen-record corruption** (editing a pillar, a
53
- `Complete`/`Abandoned` plan, or changelog history — forbidden outright) and **axis merge**
54
- (folding distill② into maintenance — refused: reconcile owns *structure*, maintenance owns
55
- *docs-vs-code fidelity*, distill② owns the *facts→docs distillation* hop; three distinct axes,
56
- P19).
57
-
58
- ---
59
-
60
- ## Execution model
61
-
62
- Runs **in the main session.** No standing sub-agent, no daemon, no cron, no hook self-trigger
63
- (P6). The harness proposes; the user disposes. Invoked one of three ways, all human-gated:
64
-
65
- 1. The user asks (`distiller docs`, "distill the facts into docs", "draft pending doc deltas").
66
- 2. The **Completion flow** points at it (one router line in the kit `CLAUDE.md` — Resolution 5a).
67
- 3. The user accepts the **maintenance threshold proposal** (≥N undigested cards map to one doc — Resolution 5b).
68
-
69
- In every path the output is **a presented draft, never a written doc.** Nothing mutates a doc
70
- without an explicit human "yes" on that specific draft.
71
-
72
- ### Invocation shapes
73
-
74
- ```
75
- distiller docs # Completion default: resolve target from the active plan/spec
76
- distiller docs --feature <slug> # just-completed feature → resolve to its owning doc
77
- distiller docs --doc <path> # threshold path / direct: digest cards touching one named doc
78
- ```
79
-
80
- `docs` mode runs against **one target doc at a time** — the unit of a delta is a single doc.
81
- The Completion caller uses the bare/`--feature` form (it knows what just shipped); the
82
- threshold caller (maintenance) uses `--doc` (it knows which doc the cards piled up against).
83
- A card-first run may surface several single-doc deltas; each is presented and approved
84
- independently.
85
-
86
- ---
87
-
88
- ## Procedure (executable, numbered)
89
-
90
- > Each step names the failure mode(s) it closes. Ordering is load-bearing: the pillar check
91
- > precedes drafting (a belief-changing card never reaches the draft); the digestion mark is
92
- > written **last** (a crash re-presents rather than silently swallows — the mirror of `facts`
93
- > mode's "consume the digested entries last").
94
-
95
- ### 0. Read the roots
96
-
97
- Read [`method.md`](method.md) (surprisal / EDU / reconciliation / bi-temporal vocabulary) and
98
- this file. Confirm the target doc exists, or note that none does (Edge Case A).
99
-
100
- ### 1. Resolve the target doc, read the three roots in order
101
-
102
- 1. `method.md` (algorithm vocabulary).
103
- 2. The **target doc** — full current prose + its `owns`/`touches` frontmatter. This is the
104
- SSoT you are proposing to revise; you read it before you draft so conflicts surface as
105
- questions, not silent overwrites.
106
- - `--doc <path>` → that doc.
107
- - `--feature <slug>` / bare → the spec that just flipped to `Active` (Completion names it),
108
- or the feature doc whose `owns` glob covers the plan's Proposed-Changes paths. Glob
109
- `docs/{features,modules/*/features}/**/*.md`, match `owns` against changed paths.
110
- Architecture/operations docs have no `owns` — for those, fall to entity/semantic match.
111
- - No doc resolves → Edge Case A.
112
- 3. The **pillar headlines** — the doctrine pillar (`## Pn —` headlines) and the decisions
113
- pillar (`## Dn —` headlines) plus each one's one-line Principle/Decision statement. Read
114
- **every** decision headline except those marked superseded: a decision carrying a
115
- `Reversed by D-M` marker (or a legacy `Status: tentative`) is NOT a binding pillar headline
116
- and is skipped; absence of any status marker means the decision is live (the new
117
- append-only model has no `Status: committed` field — a live decision is simply one nothing
118
- has reversed). Headlines only, never the bodies — this is the conservative
119
- contradiction-check substrate (Resolution 4).
120
-
121
- ### 2. INPUT SELECTION — gather the cards "touching" the target (Resolution 1) — *closes F2, F3, F5*
122
-
123
- 1. **Structural retriever (always runs, qmd-independent).** Read every card in
124
- `docs/memory/facts/*.md`. A card *structurally touches* the target when its `provenance`
125
- paths or `entities` intersect the target's `owns`/`touches` globs — match defined precisely
126
- in Resolution 1.
127
- 2. **Semantic retriever (qmd, optional).** If `command -v qmd` succeeds, for the target's
128
- identity (title + each `owns` glob stem + any `anchors:` query) run
129
- `qmd query --format json -c {repo}-facts "<the doc's subject>"`. `{repo}` = repo dir name;
130
- scope with `-c` always; repeat `-c` per relevant `{repo}-*` facts collection (the set
131
- `qmd collection list` names). qmd absent ⇒ skip silently, note in the report that selection
132
- ran structural-only (changes recall, not correctness).
133
- 3. **Bi-temporal + digestion gate (F2, F3).** From the union, drop:
134
- - any card with `invalid_from` ≠ `null` (superseded — list as "skipped: superseded");
135
- - any card whose `digested_into:` already lists the target doc path (already consumed here);
136
- - any card whose `superseded_by:` chain leads to a live card already in the set (the live
137
- card wins; keep the superseded one out of drafting, keep its trail — Edge Case D).
138
- What remains is the **working card-set**.
139
- 4. **Partition the working card-set (F5):**
140
- - **pillar-conflicting** — cards in explicit headline-level conflict with a pillar/decision
141
- (Resolution 4). These NEVER become a doc edit; they route to the escape valve **before**
142
- drafting, so a belief-changing fact can never be laundered into prose.
143
- - **doc-bound** — everything else (most cards).
144
- A card can be both: handle both arms; do not let one suppress the other.
145
-
146
- ### 3. DELTA DRAFTING — classify, then decompose doc-bound cards (Resolution 2) — *closes F1, F4*
147
-
148
- First **surprisal-gate** each doc-bound card against the *doc* (method §1, retargeted): a card
149
- whose content the doc already states is predictable ⇒ **NOOP** — draft nothing, but still mark
150
- it digested on accept (Step 5; it is absorbed, so it must not re-surface forever). This is the
151
- only retention signal; no importance scores.
152
-
153
- For each surviving card, classify against existing prose — the card-vs-doc decision (method §3,
154
- retargeted), exactly one of:
155
-
156
- - **EXTEND** — adds behavior/rationale the doc lacks, no conflict → draft an additive line.
157
- - **REFINE** — sharpens an existing doc claim that is incomplete, not wrong → draft an in-place
158
- refinement (additive; never deletes prose).
159
- - **CONFLICT** — card and prose disagree on a matter of fact → **do not resolve.** Emit a D7
160
- question; draft the line only *conditionally*, gated on the answer (F4).
161
- - **ESCALATE** — contradicts a pillar headline → already routed to the valve in Step 2.4
162
- (Resolution 4); never drafted here.
163
- - **NOOP** — doc already states it → mark digested, draft nothing.
164
-
165
- For each EXTEND/REFINE card, decide which **allowed section** it informs (Resolution 2 fixes
166
- the allow-list) and draft the smallest faithful prose change. Every drafted line carries an
167
- inline provenance marker `[from: fact-<slug>]` for each contributing card. These markers are
168
- **scaffolding for the review moment, not final doc text** — stripped on accept (Step 5.1), so
169
- the human-owned prose stays clean. The durable forward-link survives as the card's
170
- `digested_into:` back-pointer.
171
-
172
- The output of this step is a **single presented delta document** (in chat, not written to
173
- disk):
174
-
175
- ```
176
- TARGET: docs/features/memory-capture.md
177
-
178
- ── PROPOSED DELTA ────────────────────────────────────────
179
- § Current Behavior (EXTEND)
180
- + The qmd retrieval lens is organized into per-subtree collections, with the
181
- memory inbox excluded from indexing by construction. [from: fact-qmd-optional-retrieval-lens]
182
-
183
- § Changelog entry (new — docs/history/changelog/2026-06-04-...md)
184
- ### Modified
185
- - capture-hook merge is now idempotent across re-install [from: fact-etna-hook-merge-idempotent]
186
-
187
- ── QUESTIONS (D7 phrasing — answer before accept) ────────
188
- Q1. docs/features/memory-capture.md §Current Behavior says the index spans all of
189
- docs/memory; fact-qmd-optional-retrieval-lens says the memory inbox is excluded.
190
- Confirm the doc is stale before I revise it — I will not overwrite it silently.
191
-
192
- ── PILLAR-CONFLICT ESCAPE (NOT a doc edit) ───────────────
193
- (see Resolution 4 — emitted as a propose-Brainstorming-Mode item, if any)
194
-
195
- ── DIGESTION PLAN (applied only on accept) ───────────────
196
- On accept I will set `digested_into:` on: fact-qmd-..., fact-etna-hook-..., and the
197
- NOOP'd cards already stated by the doc: fact-...
198
- ──────────────────────────────────────────────────────────
199
- ```
200
-
201
- ### 4. PRESENT and await disposition — never auto-write (locked default #4) — *the gate itself*
202
-
203
- Present the delta document in chat and **stop.** The agent does not edit the target doc, write
204
- the changelog, or touch any card frontmatter at this point. The human disposes:
205
-
206
- - **Accept (whole or per-line)** → Step 5.
207
- - **Accept with edits** → the human's edits are authored prose; apply them as doc text, but
208
- digestion-marking (Step 5) still records the contributing cards as evidence consumed (the
209
- human edited the *abstraction*; the *evidence* is unchanged). Lines the human deletes
210
- entirely → their sole-source cards are **not** marked digested (nothing landed for them).
211
- - **Decline** → Step 6 (backlog at par, D10).
212
- - **Blocked-on-question (CONFLICT)** → leave undigested; the question re-surfaces next run if
213
- unanswered. Not backlogged unless the user explicitly declines to engage it.
214
-
215
- ### 5. ON ACCEPT — write doc, write changelog, mark digestion LAST (Resolution 3) — *closes F3, F6*
216
-
217
- Apply in this order so a crash leaves the audit trail consistent (doc content exists before
218
- any card claims to have landed in it):
219
-
220
- 1. **Write the accepted prose into the target doc**, stripping the `[from: ...]` markers from
221
- the final text (review scaffolding; the doc's prose is the human-owned abstraction).
222
- Prefer handing approved lines to the **`documentation` skill**, which owns the
223
- feature/changelog templates — this mode carries no copy of them.
224
- 2. **Write the changelog entry** if the delta included one (via the `documentation` skill's
225
- Changelog template, `docs/history/changelog/`). Append-only; never edit an existing entry.
226
- 3. **Mark digestion LAST:** on each card that contributed an *accepted* line (and each NOOP'd
227
- card the doc already stated), append the target doc path (and changelog path, if it
228
- contributed there) to `digested_into:`. Marking last means a crash mid-write re-presents
229
- the delta rather than falsely claiming digestion.
230
-
231
- Cards STAY — `digested_into:` is the only mutation; bi-temporal rules from `method.md` still
232
- apply (a card is never deleted; supersession is `facts` mode's surface). The card is now both
233
- evidence-for-the-doc and a queryable audit record of *where its content went*.
234
-
235
- ### 6. ON DECLINE — backlog at par, deduped (D10) — *closes F6*
236
-
237
- Append the declined delta to `docs/history/backlog.md` at the finding's own P0–P3 severity
238
- (same scale as code work), deduped:
239
-
240
- ```
241
- - **[P2]** distiller-docs proposed updating docs/features/memory-capture.md §Current Behavior from fact-qmd-optional-retrieval-lens (declined) — discovered by distiller docs
242
- ```
243
-
244
- Dedupe by (target doc § section, contributing card-ids): if an identical pending item exists,
245
- leave it. Never a segregated section, never auto-lowest-tier (D10). Never block Completion.
246
- The declined cards stay undigested, so they re-surface next pass.
247
-
248
- ### 7. Report (in chat)
249
-
250
- Target doc; working-set cards; lines drafted and their cards; cards classified EXTEND / REFINE
251
- / NOOP / CONFLICT-question / ESCALATE / skipped-as-superseded; questions raised; pillar-conflict
252
- items verbatim; on accept — doc + changelog written and cards marked digested; on decline — the
253
- backlog line. If qmd was absent, the one advisory line that selection ran structural-only. A
254
- run where no undigested card touches the target is **valid**: say "no undigested cards touch
255
- {target}," do not pad — and **touch nothing**.
256
-
257
- ---
258
-
259
- ## The five resolutions
260
-
261
- ### Resolution 1 — INPUT SELECTION: what "touching" means, precisely
262
-
263
- A card **touches** the target doc iff it satisfies **either** retriever, and is not removed by
264
- the Step-2.3 gates. "Touching" is a **union of retrievers, intersected with eligibility** —
265
- broad capture, conservative gating.
266
-
267
- **(a) Structural intersection (exact, always evaluated).** True when ANY of:
268
-
269
- 1. **Provenance match (STRONG signal).** A `commit <sha>` entry in the card's `provenance`
270
- resolves to changed files (`git show --name-only <sha>` when the commit is local); a changed
271
- file under the target's `owns`/`touches` globs is a match. (`session <id>` entries carry no
272
- paths and do not participate; an ADR/brainstorm path matches the globs directly.) This is
273
- strong because the card derives from a commit that edited code the doc
274
- owns.
275
- 2. **Entity match (SUPPORTING signal).** A normalized name in the card's `entities` equals
276
- (case-insensitively, after kebab/camel normalization) a module/feature stem in an `owns`
277
- glob, the doc title, or a symbol the doc explicitly names. **Bare prose mentions do NOT
278
- count** — only declared ownership, so "touching" can't be triggered by a doc that merely
279
- discusses an entity it doesn't own.
280
-
281
- **(b) Semantic neighborhood (qmd, optional, recall-only).** A card returned by
282
- `qmd query -c {repo}-facts "<doc subject>"` within qmd's default result window. Semantic hits
283
- with **no** structural intersection are still candidates but flagged `[semantic-only]` in the
284
- delta — the link is associative, not provenance-grounded, so the reviewer treats it as
285
- lower-trust and may reject on link-strength alone.
286
-
287
- The candidate set is the **union** of (a) and (b); correctness rests on (a) (exact,
288
- deterministic, qmd-independent), (b) only raises recall. This is why the mode runs fully
289
- without qmd, and why the maintenance threshold (Resolution 5b) counts on (a) alone.
290
-
291
- A card may touch **several** docs (its entities span modules) — expected, handled by partial
292
- digestion (Resolution 3): the card is processed once per target doc, and `digested_into:`
293
- accumulates each doc it actually fed.
294
-
295
- ### Resolution 2 — DELTA DRAFTING RULES: what a fact may update, with provenance
296
-
297
- **Allow-list of writable targets** (a card may inform ONLY these):
298
-
299
- | Target | What a card may do | Why bounded here |
300
- |---|---|---|
301
- | **`## Current Behavior`** (feature doc) | Add/modify a sentence describing how the system works *today*, when a card reports a now-true behavior the section omits or contradicts. The primary target. | The "how it works now" section cards are evidence for. |
302
- | **`## Background`** — why-built metadata (feature doc) | Add a sentence of *why* a decision was made, when a card records a decision/constraint/reversal Background omits. | Cards carry the "why" the loop captured; Background is its home. |
303
- | **`## Architecture` / `## Key Functions`** (feature doc) | Additive correction only when a card names a concrete, code-anchored fact (a new function, a moved file). Prefer Current Behavior unless the card is structural. | Code-anchored structure, not prose. |
304
- | **A new changelog entry** in `docs/history/changelog/` (via `documentation` skill's Changelog template, `### Added`/`### Modified`/`### Removed`) | Draft a changelog line for a code change a card witnesses, when a plan just completed. | Append-only history; a *new* file, never an edit. |
305
-
306
- **Never writable by distill②** (hard stops): `## Goal`, `## Goals & Non-Goals`, `## Approach`,
307
- `## Open Questions`, `## State`, frontmatter `owns`/`touches`/`anchors` (maintenance/spec axis
308
- — P19), any **pillar** file, any **plan** (frozen), any **existing** changelog entry (frozen
309
- history), any **boundary** file. A card implying one of these needs a change becomes a
310
- **question** (below) or, for pillars, an **escape item** (Resolution 4).
311
-
312
- **Per-line provenance (the invariant, mechanized).** Every drafted line carries
313
- `[from: fact-<slug>]` for each contributing card. A line with no such tag is a **defect** — not
314
- presented (Acceptance A2). On accept the tag is stripped from the final doc prose (it was
315
- review scaffolding); the durable forward-link survives as `digested_into:` (Resolution 3) — so
316
- traceability is preserved without polluting human-owned prose.
317
-
318
- **Decomposition, never invention.** As in `facts` mode: one card may yield several doc lines;
319
- the agent rephrases the card's atomic statement into doc-fit prose but **adds no claim the card
320
- does not support.** When two cards are needed for one line, both ids attach. If doc-fit prose
321
- would require a fact in no card, that fact is *missing* — raise it as a gap in the report, do
322
- not invent it.
323
-
324
- **Conflict → question (D7 phrasing), never silent resolution.** When a card contradicts an
325
- existing sentence, the agent does NOT overwrite. It emits a D7 question — *"docs/x.md §S says
326
- A; fact-<slug> (from <provenance>) says B. Confirm the doc is stale before I revise it."* —
327
- and drafts the conflicting line only as a *conditional* proposal gated on the answer. Docs stay
328
- SSoT: the card is evidence for revision, the human decides.
329
-
330
- ### Resolution 3 — DIGESTION MARKING: `digested_into:` semantics
331
-
332
- On accept, each contributing (and each NOOP'd) card gains a `digested_into:` frontmatter list:
333
-
334
- ```yaml
335
- ---
336
- id: fact-qmd-optional-retrieval-lens
337
- valid_from: 2026-06-04
338
- invalid_from: null
339
- superseded_by: null
340
- digested_into: # ← added by docs mode, on accept, never on draft
341
- - docs/features/memory-capture.md
342
- - docs/history/changelog/2026-06-04-qmd-lens.md
343
- entities: [qmd, retrieval-lens, per-subtree-collections, inbox]
344
- provenance: [session e3c4a623, commit d262e18]
345
- ---
346
- ```
347
-
348
- A **flat list of doc paths** — the brief's shape. Track *which doc* a card landed in, not which
349
- sentence; whole-card-vs-target is the granularity, which keeps selection (Step 2.3) a simple
350
- list-membership test.
351
-
352
- Semantics:
353
-
354
- - **Absent / empty** ⇒ undigested ⇒ eligible for selection and counted by the maintenance
355
- threshold. The default state of a fresh `facts`-mode card.
356
- - **A list of doc paths** ⇒ the card's content has been decomposed into each listed doc — the
357
- backward audit link completing the two-way trace.
358
- - **Partial digestion (F6), keyed on whether THE CURRENT TARGET is listed.** A card may
359
- contribute to doc X yet have residual facts not placed elsewhere. Mark it
360
- `digested_into: [docs/X.md]` — digested into X, but **still selectable** for other targets,
361
- because selection drops a card only when the list already contains *the current target*. A
362
- card stays in circulation until every doc it touches has consumed it. No separate flag.
363
- Lines the human declined are not represented in the list (their cards recirculate); only
364
- *applied* content is recorded.
365
- - **One card, several docs** ⇒ the list grows **append-only across runs.** Each entry is
366
- independently meaningful; order is run-order. **Never rewrite or remove an entry** — a doc
367
- later reverted does not un-digest the card (the card *was* digested there at that transaction
368
- time; the doc's own git history records the revert). This mirrors `method.md`'s bi-temporal
369
- stance: the trail only grows.
370
- - **Supersession interaction (F2 + F4 seam).** If a digested card is later superseded by a
371
- `facts`-mode run, the *old* card keeps its `digested_into:` (it documents what the doc once
372
- said and why) AND gains `invalid_from:`/`superseded_by:` from the normal bi-temporal path.
373
- The *new* card is undigested → on the next `docs` run its content surfaces the now-stale doc
374
- prose as a **CONFLICT question** (Resolution 2), never an auto-rewrite. The trail shows: doc
375
- prose ← old card (now invalid) ← superseded_by → new card (pending). No link is ever broken.
376
-
377
- `digested_into:` is the **only** field `docs` mode writes on a card. It never edits the card's
378
- body, `provenance`, `entities`, or bi-temporal fields — those are `facts` mode's surface.
379
-
380
- ### Resolution 4 — PILLAR ESCAPE VALVE: "contradicts a pillar," conservatively
381
-
382
- **Definition (deliberately narrow).** A card *contradicts a pillar* iff its atomic statement is
383
- in **explicit, headline-level conflict** with a doctrine principle (`## Pn —` headline) or a
384
- live decision (`## Dn —` headline) — i.e. the card asserts X and the headline (or its one-line
385
- Principle/Decision statement) asserts not-X about the *same* subject. A decision counts as a
386
- binding headline unless it has been superseded: a `Reversed by D-M` marker (or a legacy
387
- `Status: tentative`) drops it from the substrate, and the reversing decision is the live
388
- headline in its place. The operative test: **could you point to the exact pillar headline the
389
- card negates?** If not, it is not a pillar contradiction.
390
-
391
- - ✅ Escapes: a card stating "the harness auto-runs the distiller on a cron" vs P6's "build no
392
- enforcement machinery / no cron" — direct negation of a headline claim. A card recording a
393
- reversal that negates a live decision headline — e.g. "modules auto-create at a
394
- flat→modules threshold" vs a live D-headline "the user sets module granularity."
395
- - ❌ Does NOT escape: a card that merely *touches a topic a pillar discusses*; adds nuance,
396
- scope, or an exception not contemplated by a pillar (normal doc evolution); is "in tension
397
- with the spirit"; or conflicts only with a pillar's **body** but not its headline (that is a
398
- normal doc CONFLICT question — D7 — or nothing). **Vibes do not escape.**
399
-
400
- If uncertain whether a conflict is headline-level, **do not escape** — treat it as a doc CONFLICT
401
- question or drop it. Rationale (the decision rule under uncertainty): a false-negative — a real
402
- conflict slips through as a question — is **recoverable** by the human in the review moment; a
403
- false-positive — a spurious brainstorm proposal — costs the operator a mode-entry decision and
404
- **erodes the valve's signal.** When unsure, the cheaper miss is the question.
405
-
406
- **Emission (P7 mode-entry instance — propose, never enter).** A pillar-conflicting card
407
- produces a **propose-Brainstorming-Mode item** in the PILLAR-CONFLICT block, never a doc edit
408
- and never an auto-entry into Brainstorming Mode:
409
-
410
- ```
411
- ── PILLAR-CONFLICT ESCAPE (NOT a doc edit) ───────────────
412
- fact-<slug> (from <provenance>) appears to contradict doctrine headline
413
- "P6 — the harness builds no enforcement machinery":
414
- card says: <the card's atomic statement>
415
- P6 headline: <the headline claim>
416
- This is a belief-level conflict, not a doc revision. Propose entering Brainstorming
417
- Mode to reconcile it? (I will not edit the pillar, and I have NOT digested this card
418
- into any doc.) [from: fact-<slug>, contradicts: P6]
419
- ```
420
-
421
- The conflicting card is **NOT marked digested** (it was not absorbed — it escaped) and **NOT
422
- backlogged** as a doc-delta (it awaits the brainstorm disposition). It stays undigested so the
423
- conflict re-surfaces until brainstorm resolves it (the recurrence *is* the dedupe). Distillation
424
- never quietly rewrites belief — the pillars are the human-owned headwater that *steers*;
425
- distill② may not silently change what they steer. (If a brainstorm later lands a pillar change
426
- plus a downstream doc edit, that doc edit re-enters this mode normally.)
427
-
428
- ### Resolution 5 — TRIGGER WIRING (P10: at most one line each)
429
-
430
- **(a) Completion-flow pointer — ONE router-grade line in the kit `CLAUDE.md` Completion step.**
431
- Added to the "On **Completion**" flow in `harness/code/CLAUDE.md` §Workflows. Terse, points,
432
- does not re-teach (the procedure lives in this file). Verbatim:
433
-
434
- > On Completion, after flipping the spec to `Active`, consult `distiller docs` for the just-completed feature's doc — it drafts any pending fact-card deltas for your approval (presented, never auto-written).
435
-
436
- **(b) Maintenance threshold — ONE line in `agents/maintenance.md` Step 7**, sibling to the
437
- existing inbox-distillation threshold (the `facts` analogue: ≥5 undigested *inbox entries*
438
- proposes a `facts` run). Verbatim:
439
-
440
- > **Docs-distillation threshold.** Per target doc, count undigested fact-cards (`invalid_from: null`, the doc's path not in their `digested_into:`) that **touch** it by Resolution 1's structural intersection (exact, qmd-independent). If **≥10** map to **one** doc, add one line to the report **proposing** a `distiller docs --doc <path>` run on that doc — propose only, never auto-run, no cron. Declined/ignored ⇒ the count keeps growing and the proposal reappears next pass; that recurrence is the dedupe, so never backlog the proposal itself.
441
-
442
- `N = 10` default (vs the inbox threshold's 5 — inbox entries are rare and rich; cards accrue per doc). "Touch" uses the
443
- **structural** retriever only (deterministic, no qmd dependency in the maintenance loop).
444
- Per-doc count, not repo-wide: the proposal names the one doc, so the run is already scoped. This
445
- lands as a proposal emitter only — maintenance does not run the distiller (P19: distinct axis).
446
-
447
- ---
448
-
449
- ## Edge cases
450
-
451
- **A. No target doc exists yet for a completed feature.** distill② does **not** create the
452
- feature doc — that is the Completion step's job (flip spec to `Active`) via the `documentation`
453
- skill. If the invocation finds no doc, the mode reports *"no target doc yet for {feature};
454
- create it via the spec flow first, then re-invoke `distiller docs`"* and stops. It never
455
- scaffolds a doc from cards alone — a doc born purely from distilled facts would have no
456
- human-authored abstraction (Background/Goal/Approach) and would violate docs-as-SSoT +
457
- decomposition-never-invention. Cards stay undigested; they'll be drafted once the doc exists. If
458
- the gap persists, backlog at par: `- **[P2]** Feature {slug} has {N} undigested cards but no owning doc — discovered by distiller docs`.
459
-
460
- **B. A card touching zero docs.** Not selected for any target — it stays undigested, queryable,
461
- counted toward no threshold. Normal and valid: not every fact belongs in a doc (a transient
462
- observation, a fact about an unowned path). **Never** force-fit into the nearest doc (that is
463
- invention). If maintenance reports many undigested cards touching *no* doc, that is an
464
- **unowned-code** signal for maintenance's existing unowned-path step, not a distill② action.
465
- Report it as a count (*"{N} cards touch no current doc"*); do not absorb it. No doc is touched.
466
-
467
- **C. A card touching a FROZEN record (a plan, an existing changelog entry, a pillar).** Never
468
- edited (hard stop). A card whose only relevant target is frozen:
469
- - if it *contradicts* a pillar headline → escape valve (Resolution 4);
470
- - if it reports a code change worth recording → draft a **new** changelog entry (append-only is
471
- allowed; editing an existing one is not);
472
- - otherwise → it touches a writable doc section instead, or touches zero docs (Edge Case B).
473
- The frozen file is never the write target.
474
-
475
- **D. Conflicting cards (two live cards disagree about the target's area).** distill② does not
476
- adjudicate which is true — that is `facts`-mode reconciliation's job (ADD/UPDATE/SUPERSEDE/NOOP,
477
- `method.md` §3). If two *live* (non-superseded) cards make contradictory claims about the same
478
- doc sentence, surface **both** as a single D7 question — *"fact-A says X, fact-B says Y about §S;
479
- these disagree — which holds? I will not draft a revision until the cards reconcile"* — and draft
480
- **neither** line. Suggest the user run `distiller facts` to reconcile first. If one card is
481
- already `superseded_by` the other, the live card wins and the superseded one is excluded from
482
- drafting (Step 2.3) but its trail is preserved. distill② never resolves a fact-vs-fact conflict
483
- by picking one — that crosses into fabricating belief.
484
-
485
- **E. A card hand-edited into the doc (accept-with-edits), then re-surfaces.** Because
486
- `digested_into:` was set on accept (Step 5.3) listing the target, selection (Step 2.3) drops the
487
- card on the next run — it is digested into that doc regardless of whether the landed prose is the
488
- agent's draft or the human's edit (the human edited the *abstraction*; the *evidence* is recorded
489
- either way). The card does not re-surface for that doc. Only if the human *deleted* a line
490
- entirely (so nothing landed for its sole-source card) does that card stay undigested and re-
491
- surface — which is correct: its content never reached the doc.
492
-
493
- **F. Disambiguation — prose-conflict vs pillar-conflict.** If a card collides with *both* a doc
494
- sentence and a pillar headline, the **pillar escape wins** (the heavier, more conservative path):
495
- emit the propose-Brainstorming-Mode item and do not draft the doc line, because the doc prose may
496
- itself be downstream of the belief now in question. Resolve the belief first, then let any
497
- resulting doc edit re-enter normally.
498
-
499
- ---
500
-
501
- ## Acceptance checks
502
-
503
- 1. **Presented, never auto-written.** A run produces a chat-presented draft and waits; no doc
504
- file changes until the human approves (locked default #4).
505
- 2. **Per-line provenance.** Every drafted prose line / changelog bullet carries a `[from: ...]`
506
- tag naming ≥1 source card; a line with no card behind it does not exist in the draft (F1).
507
- 3. **Digestion recorded + cards survive.** On approval, every consumed (incl. NOOP'd) card gains
508
- the target path in `digested_into:` and the file remains in `docs/memory/facts/` (F3); marking
509
- happens last, after the doc write.
510
- 4. **Pillar-contradicting card → brainstorm proposal, not a doc edit.** A planted card negating a
511
- doctrine/decision headline produces a propose-Brainstorming-Mode item and zero doc/pillar
512
- edits; it is neither digested nor backlogged (Resolution 4, F5).
513
- 5. **Conflict surfaces as a question.** A card disagreeing with doc prose yields a D7-phrased
514
- QUESTION, never a silent rewrite (Resolution 2, F4).
515
- 6. **Declined delta → backlog at par, deduped.** Declining produces one P-tiered backlog line
516
- interleaved with code items; a second decline adds nothing (D10).
517
- 7. **Docs without relevant cards untouched.** A doc no card touches is never opened or modified;
518
- a run with an empty working set reports "no undigested cards touch {target}" and changes
519
- nothing.
520
- 8. **Idempotent via the digestion mark.** An immediate re-run on the same doc finds its touching
521
- cards already `digested_into:` that doc and is a clean NOOP — the digestion mark is to `docs`
522
- mode what inbox consumption is to `facts` mode (F3).
523
- 9. **Trigger budget.** Exactly one line added to `CLAUDE.md` Completion; exactly one line added to
524
- maintenance Step 7. No procedure inlined into either (P10).
525
- 10. **Not autonomous.** No cron/daemon/hook; invoked by the Completion step, by accepting
526
- maintenance's threshold proposal, or by direct user request only (P6).