168 records -> docs/decisions/records/<area>/<topic>.md (163 active, 23 dirs) and docs/decisions/archive/<area>/<topic>.md (5 archived). The filename IS the key, so one-active-record-per-key becomes a filesystem property rather than a validator check, and supersession becomes a `git mv`. WHY: the monolith was a concurrency problem before an aesthetic one. A 3,900-line append target made parallel sessions collide -- PR #605 and PR #614 both hit append-vs-append conflicts during routine rebases, and hand-resolving those inside the corpus is exactly the operation the rationale-rewrite guard exists to police. HOW IT IS VERIFIED: a ~170-file diff cannot be meaningfully read, so correctness does not rest on reading it. The parser was taught BOTH formats first, so the body-diff guard parses the old form at the merge-base and the new form at head -- the migration validates itself, no bypass. The proof is a field-level equivalence harness: 168 records before and after, zero lost, zero gained, zero field mismatches, zero rationale bodies differing. Reviewers should scrutinise the harness; it is the actual evidence. What measuring caught that reading would not have: - ~500 lines sit OUTSIDE any record -- decisions.md's lifecycle schema and each topic file's preamble, mostly the only copy. Source files are kept and stripped, never deleted. They also cannot be filed per-area: topic files hold several areas and 4 of 23 areas span several files. - Archive discovery was a non-recursive glob; after the split it found ZERO archived records, surfacing as four bogus "supersedes points to unknown key" errors rather than an obvious failure. - ~32 live docs point into the corpus BY DATE, which the split dangles. Each stripped file now ends with a generated "Records formerly in this file" index, which also rescues the identical breadcrumbs in old issue comments. - decisions.md's "In this file:" list was 97 same-file anchor bullets that the split makes WRONG, not merely stale. Dropped; the generated index replaces them with links that resolve. The equivalence harness now runs against a checked-in FIXTURE, not the live corpus. The earlier version migrated the real tree, which made it a one-shot: the moment the migration landed there was nothing left to move and the tests failed for reasons unrelated to the code. A fixture keeps them testing the SCRIPT rather than the repo's current state. Keys preserved verbatim, warts included: `sched` (12) and `scheduling` (1) remain two directories for one concept. Renaming a key is not a move -- it changes identity, breaks the equivalence proof, and invalidates MemPalace's per-key drawers. Taxonomy normalisation is separate work. refs #610
3.3 KiB
key, title, status, since, supersedes, superseded-by, rule, signals, mechanics
| key | title | status | since | supersedes | superseded-by | rule | signals | mechanics |
|---|---|---|---|---|---|---|---|---|
| docs.tracker-comment-retrofit | 2026-07-21 — Check the worked issue before the decision corpus; a closed tracker's comments need no retrofit (#524) | active | 2026-07-21 | none | none | When the knowledge exporter flags an over-cap tracker issue and excludes it from ingestion, triage its comments instead of assuming a retrofit is owed — and for each decision-shaped item check the **worked issue first**, because a tracker session comment is by construction a précis of the fuller closing record posted on the issue it narrates. Applied to #237 (111 comments) this yielded **zero** records, so server-management#642's "a fact found only in a #237 comment" retrieval row has no valid subject and its interim target (an already-migrated record) is permanent. | tracker retrofit, over-cap issue exclusion, worked-issue-first, tracker-is-not-a-knowledge-store, #237 comment history · paths: `docs/tracker-retrofit-triage-237.md` · issues: #524, #237, #520, #521, server-management#642 | `docs/tracker-retrofit-triage-237.md` — method, per-comment classification table, totals, and the one candidate that was raised and disproved |
Why the worked-issue-first ordering is the load-bearing part. The session protocol that produced #237's log required each session to post its full closing record on the issue it actually worked, and then summarize across issues on the tracker. The tracker entry is therefore the lossy copy. A comment that looks like a unique source is nearly always a précis of a primary the exporter already indexes — so the instinct "the tracker is excluded, therefore its knowledge is orphaned" inverts the real dependency. Checking the corpus first and the worked issue second wastes the effort; the reverse order settles most items in one lookup.
Worked example. Comment [106/111] recorded that #497's music-video metadata reconcile deliberately
excludes Guids (not eager-loaded by GetOrAdd, so reconciling would duplicate-insert every scan) and
Directors (not add-persisted for MusicVideoMetadata). Genuinely decision-shaped, and genuinely
absent from the decision corpus — it survives a corpus-only check and looks like a retrofit target.
Issue #497's own closing comment states both exclusions with fuller reasoning, and the exporter
ingests it as 497.md. One worked-issue lookup disposes of it.
Scope of the claim — deliberately narrow. The coverage test was applied to decision-shaped
items only. Items classified as cross-cutting lore were classified but not coverage-checked, and
that bucket is not empty: two facts from comment [109/111] were found to have no home anywhere —
scripts/e2e-local.sh's readiness probe hanging on a reused config dir, and the troubleshooting
playback API's inability to exercise channel branding. Both were swept into the handoff lore by this
PR. So the correct statement is "no decision-shaped orphans," not "no orphans"; a tracker triage
that skips the lore bucket will leave real knowledge on the floor.
A zero result is a legitimate outcome, not evidence the triage was done wrong. What would change the answer is a tracker whose sessions did not also write per-issue closing records — one where the tracker genuinely was the primary rather than the narration layer.