Invariants / DC-NODE-46

DC-NODE-46

DC derived enforced

Every ADMITTED ForgeTick yields either a structured refusal or a leader-schedule decision. No admitted tick may disappear, and none may report a reason that is not its own. (a) TYPED KES WINDOW: the slot's KES evolution index is consumed as a Result -- CoordinatorState::kes_period_for_slot_checked -> KesSlotError{BeforeOperationalCertificateStart, AfterOperationalCertificateEnd, PeriodArithmeticOverflow}, each carrying the SLOT BOUND an operator can act on, routed as ForgeRefused::KesWindow. The if let Some(kes_period) skip that silently consumed the whole forge attempt is removed. (b) ONE DEFINITION: the Option accessor kes_period_for_slot delegates to the checked form, so the two can never disagree about which slots are signable. (c) FAMILIES STAY SEPARABLE: slot-derivation, KES-window (three distinct reasons), tip/fence and leadership failures project to DISTINCT emitted discriminators -- never one collapsed reason. (d) HONEST OUTCOME: an admitted tick that was refused emits ForgeOutcome::Refused with its reason; no_tip_available is narrowed to a genuinely absent tip (it was previously a catch-all that reported a KES refusal while the node held a perfectly good tip). (e) NO STALE REASON: last_forge_refused is cleared on entry to the ForgeTick arm, so a tick with nothing of its own to report says so instead of re-emitting the previous tick's reason and tip operands.

Source

docs/clusters/PREPROD-LIVE-2-FORGE-READINESS/SLICE-LIVE-2b-forgetick-reachability-branch-table.md (B11, the sixth silent exit); docs/clusters/PREPROD-LIVE-2-FORGE-READINESS/SLICE-LIVE-2c-authoritative-forge-slot-wiring.md (part 3 error shape); docs/clusters/PREPROD-LIVE-2-FORGE-READINESS/SLICE-LIVE-2c-ACTIVATION-handoff.md.

Cluster
PREPROD-LIVE-2-FORGE-READINESS
Introduced in
PREPROD-LIVE-2c-ACTIVATION
Authority surface
GREEN forge-tick admissibility projection (operational evidence; never an acceptance signal)

Enforcement trace

Tests 6

  • kes_period_for_slot_checked_names_the_reason_and_the_slot_bound
  • the_option_accessor_never_disagrees_with_the_typed_one
  • the_naive_19_day_ahead_slot_was_never_refused_by_the_kes_window
  • ce_l2c_5_and_6_live_instant_derives_the_measured_slot_and_refuses_typed
  • ce_l2c_a5_a_refusal_never_outlives_its_own_tick
  • forge_skip_reason_projects_every_typed_refusal

Cross-references

Evidence notes

Opened AFTER decomposing run 4's own artifacts, which CORRECTED the SLICE-LIVE-2b code-read conclusion that B11 had fired. The operator op-cert starts at KES period 970; with slotsPerKESPeriod 129_600 and maxKESEvolutions 62, the naive 19-day-ahead slot 131_976_696 is absolute period 1018, evolution 48 -- comfortably INSIDE the window, so kes_period_for_slot returned Some(48) and the wrong slot was never refused there. Pinned as the_naive_19_day_ahead_slot_was_never_refused_by_the_kes_window. This makes DC-NODE-45 the load-bearing fix and DC-NODE-46 a defence-in-depth one, which is the opposite of how the branch table read it. The per-tick reset clause (e) was NARROWED by the mutation sweep: every path that does refuse overwrites the field, so the sticky harm is confined to the one path that records nothing -- which is precisely the record an operator reads when nothing is happening.

Evidence

  • Run 4 (2026-08-06, wire_smoke.jsonl): 354 admitted ForgeTicks emitted 354 forge_result records, all outcome=no_tip_available -- a catch-all that could not distinguish a fence refusal from an absent tip from a KES-window failure.