One open and one closed record, written by IncidentStore on Yggdrasil under
IDUNN_WRITE_FIXTURES=1 and read back by the_incident_fixture_is_what_idunn_reads.
Bifrost's reader tests copy this file. Builds.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The route-proof world's hand-built promotion is deleted: the world runs over
stub host programs, so Routing installs and proves the route for real and
every former promote_by_hand is a real step. The salvage fixtures of the old
B2 are not ported.
New tests pin each ruling under its own mutation: a full ledger still admits
and counts every survival actuation, first deployments are metered, a refused
preflight starts no private-mount unit and fails at once with the reopen time,
the actuation log slides, a clock step stalls nothing past one window, a
failed challenge ends the pass instead of losing a CAS, a proved challenge
clears the degradation, both storms are bounded, restarts are spaced,
counted in the mint and read from the target's own log (unreadable history no
longer stops crash recovery), and the v3 lift is pinned over golden bytes cut
with the 583b2a7 encoder, refusing a record that shows retired meters.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Soul found B1's rule sound and its transition unsafe. This makes the rule's
old inputs impossible to reintroduce a stuck state from.
- The control store's legacy lift owns the transition. A pre-B1 continuity
abort that issued an activation lifts with topology_reconciliation Pending,
so the one resolution demotes its own activation. A record already terminal
under the old rule is reopened at Starting, since a terminal record cannot
owe work. History lifts records as written. Before this, one resident
record of that shape failed validation and ControlSnapshot::read refused the
whole store, so Idunn could not boot.
- Supervision owns the Expected-only precondition. When its pre-restart
demotion fails it mints no continuity and writes next_restart_at_unix_millis
on the generation's ContinuityBackoff (attempts and window untouched), so it
neither restarts over an undemotable projection nor retries every tick.
- Boot reconciles once: a projected activation that exactly matches the
activation a failed continuity in history (or a resident terminal record)
issued is demoted. Nothing is adopted; an activation no admitted generation,
live transaction or failed issuer accounts for is reported and left alone.
New read-only CultCacheTopologyDriver::projected_activation.
- Unreadable history.cc fails closed. The continuity restart ceiling and the
consumed-command check no longer read an empty history; they stop, and the
fault is reported once while it lasts (ReportOnce). The undecodable-record
report is a pure function, pinned.
- docs/deployment-authority.md no longer says the projection never drifts.
Tests: legacy fixtures written by the 9001b58 encoder for the three abort
shapes (a second throwaway generator, see the fixtures README), driven through
the Engine; the seeded-transaction helper now takes a command kind and an
incumbent, and a Deploy carries a frozen-source receipt and a signed brake
release, so Deploy commit, Deploy pre- and post-fence aborts and a continuity
abort over an incumbent run through the real phase machine.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
One migration for the route-continuity foundation. No decision reads the new
state.
- ReadinessEvidence (OdinCorrelated | RouteProof) replaces the bare Odin Ready
receipt on both records. The class a target must collect is derived from its
Expected (ReadinessClass::of): a shared-infrastructure odin.verse-rendezvous
dependency means Odin-correlated, none means route-proof. It is not stored.
RouteProof evidence is refused for a target that declares Odin.
- Generation carries route supervision state (challenge times, failures,
degraded marker, actuation window) and continuity backoff. A new generation
inherits the actuation window and backoff and starts unobserved and
undegraded. route_repair_started_at stays readable.
- Transaction carries the current phase deadline (stamped by transition from
the plan's frozen durations) and lease adoption evidence.
- FailedAfterFencing names its recovery: RestartAdmitted, RestoreIncumbent
(the default for older records) or OperatorRequired{reason}.
- Every v2 generation lifts as Odin-correlated with its receipts unchanged;
v2 and v3 transactions lift through LegacyDeploymentTransaction. The boot
migration rewrites both, preserving stored_at, and history reads lift the
same way. The Legacy structs die when no older record can remain.
Fixtures under tests/fixtures/idunn-control-legacy are the bytes the 9001b58
encoder wrote for records built through its own constructors.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>