100 lines
5.4 KiB
Markdown
100 lines
5.4 KiB
Markdown
# 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.
|