From a699630bbc49552fa747e9c0fabba24598fec77a Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 1 Oct 2026 14:38:13 +0200 Subject: [PATCH] eureka-substrate postmortem: seven cuts, the mind upgraded live, what Soul found Co-Authored-By: Claude Opus 5.5 --- docs/eureka-substrate-postmortem.md | 100 ++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 docs/eureka-substrate-postmortem.md diff --git a/docs/eureka-substrate-postmortem.md b/docs/eureka-substrate-postmortem.md new file mode 100644 index 0000000..c71717b --- /dev/null +++ b/docs/eureka-substrate-postmortem.md @@ -0,0 +1,100 @@ +# eureka-substrate postmortem (cuts 2026-10-01) + +The campaign fixed the mind's correctness core that the first typed Eureka +campaign (idunn-watchdog) tripped over: keys too long to resolve, key errors +reported as outages, report heads compared by spelling, findings that could +not defer to a cut, an unchecked `depends_on`, a stewardship ritual nobody +needed, and a faculty still named `MindSteward`. Target: +`docs/eureka-substrate-target.md`; map: `docs/eureka-substrate-map.md`. The +campaign stays open as the standing home of substrate gaps (ruling `gap-home`). + +## What landed + +| Cut | Repo | Merge / commit | Soul passes | +|---|---|---|---| +| merge-epiphany-main (0a) | Epiphany | `2bf39eef` | 1, holds | +| merge-huginn-main (0b) | Huginn | `922e6194` | 1, holds | +| leaf-key-bound | Epiphany | `ef956685` | 1, 2 Lows deferred | +| huginn-pin-and-refusals | Huginn | `b85cd5d7` | 2 | +| huginn-admission-rules | Huginn | `107552dc` | 2 | +| ops-mind-upgrade | gamecult-ops | `1f4cb12e`, `0dd1a1a3` | 1 | +| skill-recipes | Eureka | `e7567333`, `243182cc` | 2 | + +Live: Huginn `107552dc` serves `eureka` on Yggdrasil since 12:00:59 UTC +(14:00:59 CEST). Before and after the flip, 346 documents and 108 receipts. +The read-back test on a scratch copy of the cold copy validated and re-keyed +all 346 documents and withdrew 45 long-keyed resolutions. The first admission +with a local key over 64 bytes went in at 12:15:10 UTC, so rollback is now +restoring `/var/backups/huginn-upgrade/107552dc…/mind.redb`, not a flip. + +Closed with it: six substrate gaps (`gap-unresolvable-finding-key`, +`gap-sha-identity-literal`, `gap-defer-finding-to-cut`, +`gap-depends-on-pins-revision`, `gap-stewardship-ceremony`, +`gap-faculty-enum-name`), and the seven idunn-watchdog findings that the key +bound had left stuck in force (three Fixed, four Deferred to the follow-ups +already carrying them). + +## Soul's ledger + +10 verdicts, 14 findings: 8 Fixed, 3 Deferred (to `leaf-bound-hygiene` and +`leaf-typed-prepare`), 3 Recorded. No Blocker or High. Every finding was in +the tests or the prose, none in shipped behaviour, which says the cuts were +small enough for Hands to get right and the suites were not yet strict enough +to prove it: + +- The read-back test first proved one withdrawal and skipped refusals + (`readback-tolerates-refusal`). Rebuilt, it censused the whole mind and + became the deploy's gate. That gate is the most valuable artefact of the + campaign. +- Exact-match rules were pinned with fixtures that cannot tell exact from + prefix (`dep-near-miss`) or case (`dep-case`): labels `1, 2, 3, 9`. A + fixture for an equality rule needs near misses; digits alone are degenerate. +- `cargo mutants` scored 8/8 on admission-rules but mutates `check()` and + `matrix()` whole, so the score defended no individual rule. Soul's hand + mutants that were functions of the input (prefix in one direction, length + compare, case fold) found what the tool could not. +- The docs pass left a recipe steering Self to the stewardship step the + operator had dropped (`stale-steward-recipe`). Deleting a rule from code does + not delete the prose that teaches it; the docs cut needs its own grep for + every consumer of the dropped step, not only its name. + +## What the campaign itself proved about the substrate + +- **The bug bit its own fix.** Self's first attempt to close two findings of + the pin cut was refused `InvalidFormat` wrapped as `Unavailable`, the very + defect the cut was fixing. Admitting a resolution had to wait for the deploy. + Any campaign that fixes the mind's admission runs on the unfixed mind until + the upgrade; plan resolutions after it. +- **A finding cannot be `Answered`.** Closing the self-dependency fork by its + ruling was refused `IncompatibleResolution`; it was closed `Fixed` by the + commit that implemented the ruling. +- **Old clients survived the rename.** The pre-upgrade `eureka-state` decoded + every response used afterwards, including receipts carrying `Life`, because + the receipt digest excludes provenance. Not every kind was exercised through + the old client. +- **The cold-copy-then-read-back pattern worked as designed**: build, record + counts, stop, copy, prove on a scratch copy, flip, recount, view every + document. Total downtime was about three minutes. + +## What went wrong in the running of it + +- A merge was run with `git merge -F -` (stdin), which git rejected; the + following push was a no-op and the worktree was removed anyway. Nothing was + lost because the branch was pushed, but the chain should have stopped on the + failed merge. Write merge messages to a file. +- The admission-rules spec's line anchors were taken at `133324a7`; Hands + branched from `b85cd5d7` and re-anchored by content. `base` cannot say + "main after X merges" (`gap-depends-on-pins-revision`, second half, still + open as prose in `first`). +- Self decided the self-dependency fork as a Defaulted ruling on proportion + rather than asking. The operator may overturn `eureka-substrate:ruling:self-dep`. + +## Open + +- Fresh-session check: the Rehydrate block and recipes in a new session, which + also loads the swapped client and its `Life` faculty. +- 15 substrate gaps in force under `eureka-substrate` (verify stopgap, + landing records, faculty attribution, mutation triage field, and others). +- Leftovers to clean: `~/huginn-readback-107552dc…` and + `~/huginn-build/107552dc…` on Yggdrasil; the client clone in the session + scratchpad. Keep the cold copy until the operator retires it.