decisions corpus consolidation has no owner — and after #610 the budget number stops reporting it #620

Closed
opened 2026-07-25 19:36:08 +02:00 by timothy · 2 comments
Owner

The concern

Nobody owns consolidating the decision corpus, and the one signal that used to nag about it is being replaced by a healthier-looking number that measures something different.

Two states, before and after #610

On main today (798ecd1f), the validator emits this on every run, local and CI:

::warning::decisions-validate: aggregate active-corpus is 6038 lines (budget 5600) — schedule a consolidation

438 over, and it had been firing continuously rather than as an event — a permanently-red ratchet, which provides no signal at all.

After #610 / PR #619 merges, the budget counts prose only, excluding YAML frontmatter, and the corpus reads 5228/5600 — under budget for the first time. PR #619 states this plainly and is right to: no knowledge was removed. It is a change of metric, not a consolidation.

So the warning goes quiet without the underlying condition changing. That is the actual risk this issue exists to name: a check that stops complaining because it started measuring something else reads, to a future session, exactly like a problem that got fixed.

Why this still matters once the number looks fine

  • ~168 records, some of which restate a sibling's rationale rather than adding to it.
  • Consolidation was deferred out of both #603 and #610 to "a separate issue" that did not exist until this one — so the deferral had no destination twice.
  • The post-#610 layout makes the work easier, not unnecessary: pruning becomes a per-file judgement instead of surgery inside a 3800-line file.

Sequencing

Do not start before #610 / PR #619 merges. It moves every record to records/<area>/<topic>.md and changes both the unit of consolidation and the metric. Starting earlier means doing the work twice.

Scope when picked up

  • Decide what the budget should mean post-split — a prose-line aggregate, a per-record ceiling, a per-area count, or retire it for something that measures redundancy rather than size. Whatever it is, it must be capable of going red again.
  • Identify genuine consolidation candidates: superseded-but-still-active clusters, records whose rationale restates a sibling, single-record areas that belong under a neighbour.
  • Check whether prose is the only copy before pruning it (docs.tracker-comment-retrofit). #610's own inventory found ~500 lines of non-record narrative a naive move would have deleted — that trap applies just as much to consolidation.
  • Anything actually removed goes through the lifecycle (archive with status: superseded/retired), never a silent line-delete — and now needs a Decisions-Edit: yes trailer (#609).
  • Taxonomy normalisation (sched vs scheduling, seven single-record areas, locking overlapping concurrency) is related but separate — #610 deliberately preserved keys verbatim because renaming a key changes identity and invalidates MemPalace's per-key drawers. Fold it in only if that's a deliberate decision, with its own record.

Non-goals

  • Making the budget blocking. Going over is a non-blocking ::warning:: by design (#520) and should stay that way — a size condition turning an unrelated PR red is a self-inflicted CI outage.
  • Reversing #610's metric change. Counting prose rather than frontmatter is the right measure; it just needs a threshold that reflects it.

Done-when

  • Budget re-baselined (or replaced) against the post-#610 layout, with a threshold that can actually go red again
  • A decision record captures what the new measure is and why, so the metric change is legible rather than inferred from a quiet warning
  • Consolidation candidates identified and either actioned or explicitly declined with rationale
  • Any pruning went through archive/supersession, not line-deletion — confirmed by the body-diff guard
  • Adversarial review passed
## The concern Nobody owns consolidating the decision corpus, and the one signal that used to nag about it is being replaced by a healthier-looking number that measures something different. ## Two states, before and after #610 **On `main` today** (`798ecd1f`), the validator emits this on every run, local and CI: ``` ::warning::decisions-validate: aggregate active-corpus is 6038 lines (budget 5600) — schedule a consolidation ``` 438 over, and it had been firing continuously rather than as an event — a permanently-red ratchet, which provides no signal at all. **After #610 / PR #619 merges**, the budget counts prose only, excluding YAML frontmatter, and the corpus reads **5228/5600 — under budget for the first time**. PR #619 states this plainly and is right to: *no knowledge was removed*. It is a change of **metric**, not a consolidation. So the warning goes quiet without the underlying condition changing. That is the actual risk this issue exists to name: a check that stops complaining because it started measuring something else reads, to a future session, exactly like a problem that got fixed. ## Why this still matters once the number looks fine - ~168 records, some of which restate a sibling's rationale rather than adding to it. - Consolidation was deferred out of **both** #603 and #610 to "a separate issue" that did not exist until this one — so the deferral had no destination twice. - The post-#610 layout makes the work *easier*, not unnecessary: pruning becomes a per-file judgement instead of surgery inside a 3800-line file. ## Sequencing **Do not start before #610 / PR #619 merges.** It moves every record to `records/<area>/<topic>.md` and changes both the unit of consolidation and the metric. Starting earlier means doing the work twice. ## Scope when picked up - Decide what the budget should *mean* post-split — a prose-line aggregate, a per-record ceiling, a per-area count, or retire it for something that measures redundancy rather than size. Whatever it is, it must be capable of going red again. - Identify genuine consolidation candidates: superseded-but-still-active clusters, records whose rationale restates a sibling, single-record areas that belong under a neighbour. - **Check whether prose is the only copy before pruning it** (`docs.tracker-comment-retrofit`). #610's own inventory found ~500 lines of non-record narrative a naive move would have deleted — that trap applies just as much to consolidation. - Anything actually removed goes through the lifecycle (archive with `status: superseded`/`retired`), never a silent line-delete — and now needs a `Decisions-Edit: yes` trailer (#609). - Taxonomy normalisation (`sched` vs `scheduling`, seven single-record areas, `locking` overlapping `concurrency`) is **related but separate** — #610 deliberately preserved keys verbatim because renaming a key changes identity and invalidates MemPalace's per-key drawers. Fold it in only if that's a deliberate decision, with its own record. ## Non-goals - Making the budget **blocking**. Going over is a non-blocking `::warning::` by design (#520) and should stay that way — a size condition turning an unrelated PR red is a self-inflicted CI outage. - Reversing #610's metric change. Counting prose rather than frontmatter is the right measure; it just needs a threshold that reflects it. ## Done-when - [x] Budget re-baselined (or replaced) against the post-#610 layout, with a threshold that can actually go red again - [x] A decision record captures what the new measure is and why, so the metric change is legible rather than inferred from a quiet warning - [x] Consolidation candidates identified and either actioned or explicitly declined with rationale - [x] Any pruning went through archive/supersession, not line-deletion — confirmed by the body-diff guard - [x] Adversarial review passed
timothy added the ci-cdpriority: medium labels 2026-07-25 19:36:08 +02:00
timothy changed title from decisions corpus is 438 lines over the aggregate budget — the validator warns on every run and nobody owns the consolidation to decisions corpus consolidation has no owner — and after #610 the budget number stops reporting it 2026-07-25 20:04:06 +02:00
timothy added the in-progress label 2026-07-26 00:26:33 +02:00
Author
Owner

Claiming — picked up as the top-ranked eligible backlog item by scripts/select-queue.sh (tier prio-medium, deps clear now that #610/PR #619 has merged, which was the stated sequencing gate).

Scanning for bundle-able siblings in the same subsystem (#621 structural parse check, #631 scripts/tests/ not run in CI) before scoping.

Claiming — picked up as the top-ranked eligible backlog item by `scripts/select-queue.sh` (tier `prio-medium`, deps clear now that #610/PR #619 has merged, which was the stated sequencing gate). Scanning for bundle-able siblings in the same subsystem (#621 structural parse check, #631 `scripts/tests/` not run in CI) before scoping.
Author
Owner

Closing record

Outcome: Shipped in PR #642 (merged). The aggregate corpus budget is retired, replaced by a per-record prose ceiling (--record-ceiling, default 60), both non-blocking. New decision record docs.corpus-size-signal.

Root cause / the premise had already expired. This issue was filed because the budget went quiet at 5228/5600 after #610 changed the metric — a check that stops complaining because it started measuring something else. Measured on main at f394d6ce it was 5658/5600, over budget and warning again — 3 hours 35 minutes later, the same evening, with nobody consolidating anything. So the answer was not to re-baseline: an aggregate over a monotonically growing corpus can only ratchet, which is the "permanently red, therefore no signal" state #542 re-baselined away from. Growth is not even a smooth rate to plan against — the corpus fell from 5089 to 5042 across four days, then gained 427 in one evening as two large records landed.

Decisions/conventions changed: added docs.corpus-size-signal. Also stopped counting the generated catalog in the total (189 of those 5658 lines): it gains one row per record and no consolidation can shrink it, which quietly made the metric partly a record count wearing a line-count costume, pointing readers at work that cannot be done.

Reusable knowledge — the calibration test took four versions, and the failures are the lesson:

assertion why it failed
v1 max(under) <= 60 < min(over) true by construction of the two lists it built
v2 a minimum gap width a ceiling of 200 also sits in a wide gap — it passed
v3 fraction band + "clear air" vs the nearest record above hostage to an unrelated record: one ordinary 62-line addition reddened it with the ceiling correctly placed, and the only remedy was to raise the ceiling — this very ratchet, as a hard failure in what #631 makes a blocking CI job
v4 p90 <= ceiling <= p95 ✅ scale-free; swept both ways (40/50/111/200 fail, 60/70/96 pass)

Two rules that outlive this metric: a guard test must depend only on the thing it guards, and a threshold over a growing population must be expressed in that population's own terms — a percentile, not a count and not a raw distance.

A third, learned the hard way: do not freeze a self-referential number in prose. This record's own line count was restated and wrong four times (62 → 68 → 88 → 92) as each correction changed it. Every self-count is now absent; the warning prints the live value. The candidate table is likewise labelled point-in-time, since the over-ceiling set moved during the PR's own review cycle.

Verification: mutation-verified throughout — re-adding the catalog to the total, making the ceiling inclusive, neutering main()'s ceiling report, bumping the default to 999999, and suppressing the trend notice each redden exactly their own test. Four independent cold review rounds; every historical figure in the record was independently reproduced by a reviewer (5658/189 at f394d6ce, 5228 at 8e84191a, the 3h35m interval, the 5089→5042→5469 series, 628 scaffolding lines, all candidate line counts). 225 tests green.

Deferred: two records remain flagged as genuine consolidation candidates — scan.projection-failure-sweep-guard (overlaps scan.zero-item-fetch-guard) and sched.weighted-shuffle (overlaps sched.weightedshuffle-editor). Merging records changes key identity and invalidates MemPalace's per-key drawers, so that is a call for the owning area, not a drive-by edit inside a metric change. The standing warning names them every run, which tracks them better than an issue nobody reads. An automated redundancy metric was rejected, not deferred: noisy, unfalsifiable, and it would fire hardest on the adjacent-but-distinct records the corpus exists to keep apart. Taxonomy normalisation stays out of scope for the same identity reason.

Docs updated: docs/decisions/records/docs/corpus-size-signal.md (new), docs/decisions/README.md (regenerated), docs/ci-cd.md, docs/decisions.md (the retired budget no longer reads as a live check).

## Closing record **Outcome:** Shipped in PR #642 (merged). The aggregate corpus budget is **retired**, replaced by a per-record prose ceiling (`--record-ceiling`, default 60), both non-blocking. New decision record `docs.corpus-size-signal`. **Root cause / the premise had already expired.** This issue was filed because the budget went quiet at 5228/5600 after #610 changed the metric — a check that stops complaining because it started measuring something else. Measured on `main` at `f394d6ce` it was **5658/5600, over budget and warning again — 3 hours 35 minutes later, the same evening**, with nobody consolidating anything. So the answer was not to re-baseline: an aggregate over a monotonically growing corpus can only ratchet, which is the "permanently red, therefore no signal" state #542 re-baselined away from. Growth is not even a smooth rate to plan against — the corpus *fell* from 5089 to 5042 across four days, then gained 427 in one evening as two large records landed. **Decisions/conventions changed:** added `docs.corpus-size-signal`. Also stopped counting the **generated catalog** in the total (189 of those 5658 lines): it gains one row per record and no consolidation can shrink it, which quietly made the metric partly a record *count* wearing a line-count costume, pointing readers at work that cannot be done. **Reusable knowledge — the calibration test took four versions, and the failures are the lesson:** | | assertion | why it failed | |---|---|---| | v1 | `max(under) <= 60 < min(over)` | true **by construction** of the two lists it built | | v2 | a minimum gap **width** | a ceiling of 200 also sits in a wide gap — it passed | | v3 | fraction band + "clear air" vs the nearest record above | **hostage to an unrelated record**: one ordinary 62-line addition reddened it with the ceiling correctly placed, and the only remedy was to *raise the ceiling* — this very ratchet, as a hard failure in what #631 makes a blocking CI job | | v4 | `p90 <= ceiling <= p95` | ✅ scale-free; swept both ways (40/50/111/200 fail, 60/70/96 pass) | Two rules that outlive this metric: **a guard test must depend only on the thing it guards**, and **a threshold over a growing population must be expressed in that population's own terms** — a percentile, not a count and not a raw distance. A third, learned the hard way: **do not freeze a self-referential number in prose.** This record's own line count was restated and wrong four times (62 → 68 → 88 → 92) as each correction changed it. Every self-count is now absent; the warning prints the live value. The candidate table is likewise labelled point-in-time, since the over-ceiling *set* moved during the PR's own review cycle. **Verification:** mutation-verified throughout — re-adding the catalog to the total, making the ceiling inclusive, neutering `main()`'s ceiling report, bumping the default to 999999, and suppressing the trend notice each redden exactly their own test. Four independent cold review rounds; every historical figure in the record was independently reproduced by a reviewer (5658/189 at `f394d6ce`, 5228 at `8e84191a`, the 3h35m interval, the 5089→5042→5469 series, 628 scaffolding lines, all candidate line counts). 225 tests green. **Deferred:** two records remain flagged as genuine consolidation candidates — `scan.projection-failure-sweep-guard` (overlaps `scan.zero-item-fetch-guard`) and `sched.weighted-shuffle` (overlaps `sched.weightedshuffle-editor`). Merging records changes `key` identity and invalidates MemPalace's per-key drawers, so that is a call for the owning area, not a drive-by edit inside a metric change. The standing warning names them every run, which tracks them better than an issue nobody reads. An automated redundancy metric was **rejected**, not deferred: noisy, unfalsifiable, and it would fire hardest on the adjacent-but-distinct records the corpus exists to keep apart. Taxonomy normalisation stays out of scope for the same identity reason. **Docs updated:** `docs/decisions/records/docs/corpus-size-signal.md` (new), `docs/decisions/README.md` (regenerated), `docs/ci-cd.md`, `docs/decisions.md` (the retired budget no longer reads as a live check).
timothy removed the in-progress label 2026-07-26 20:17:57 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: timothy/ersatztv#620