5.4 KiB
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): labels1, 2, 3, 9. A fixture for an equality rule needs near misses; digits alone are degenerate. cargo mutantsscored 8/8 on admission-rules but mutatescheck()andmatrix()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
InvalidFormatwrapped asUnavailable, 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 refusedIncompatibleResolution; it was closedFixedby the commit that implemented the ruling. - Old clients survived the rename. The pre-upgrade
eureka-statedecoded every response used afterwards, including receipts carryingLife, 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 fromb85cd5d7and re-anchored by content.basecannot say "main after X merges" (gap-depends-on-pins-revision, second half, still open as prose infirst). - 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
Lifefaculty. - 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.