Invariants / DC-NODE-19

DC-NODE-19

DC derived declared

Single-producer forge-loop continuation after follow-link EOF. In an explicitly declared single-producer venue (VenueRole::SingleProducer) that has ALREADY entered the DC-NODE-18 extend state (ForgeMode::SingleProducerExtendOwnDurableSpine, reached only via DC-NODE-15 catch-up + an explicit venue-adoption-certificate promotion), a LoopState::Ending caused SOLELY by structural feed EOF (the Ade->relay follow link closing/draining) MUST NOT by itself terminate the forge loop; the loop continues forging successors on its OWN certified durable spine (each admitted via pump_block, DC-NODE-12). The continuation is FENCED to the certified single-producer run and FAILS CLOSED (no continuation; verbatim HaltCleanly / typed refusal, never a silent forge) if ANY hold: (1) not VenueRole::SingleProducer; (2) not ForgeMode::SingleProducerExtendOwnDurableSpine; (3) operator shutdown requested; (4) existing forge-validity bounds fail (off-epoch DC-EPOCH-03 / beyond forecast horizon DC-CONS-09 / KES-period invalid); (5) a competing chain was observed before EOF; (6) relay-producing evidence exists; (7) the venue certificate is absent or malformed -- the DC-NODE-18 SingleProducerFenceReason set plus the venue/mode/cert fence. NO numeric "max blind forges" cap (an artificial operator policy, not a Cardano semantic invariant); the certified-run fence + the existing BLUE bounds + operator shutdown bound it. RELOCATES the loop's termination authority off feed-liveness onto explicit operator shutdown / fatal error (the same move DC-NODE-09 made for the serve-listener lifetime) while PRESERVING DC-NODE-05's deeper invariant: the forge advances NO durable tip directly and run_node_sync -> pump_block remains the SOLE durable tip-advance authority, and available feed work still drains via SyncOnce before any ForgeTick (produce subordinate to the sync spine). The default VenueRole::Unknown venue takes the verbatim prior HaltCleanly-on-feed-end path. A loop-lifecycle refinement, NOT a fork-choice change -- DC-CONS-03 stays the sole follow/fork authority; the continuation never selects/reorders/prefers chains. Only a clean structural feed EOF is continued; a LoopState::Ending representing a real shutdown or a fatal source failure exits via Err/fail-fast and is NEVER continued. SCOPE: continuation only (don't-die-on-EOF); follow-link keep-alive / reconnect (OQ-KA) is a separate non-blocking cousin.

Source

docs/planning/single-producer-loop-continuation-after-feed-eof-invariants.md

Introduced in
TBD

Enforcement trace

Cross-references

Strengthened in

Evidence notes

CE-AF-6b, deferred from DC-NODE-18 (PHASE4-N-AF). DECLARED at /invariants (2026-06-08, user-approved framing); enforced only when the slice lands with ALL of: the GREEN plan_loop_step 5th-input totality gate (32-case, no wildcard); the certified-run continuation fence (the 7 fail-closed conditions in the statement, reusing the DC-NODE-18 SingleProducerFenceReason); replay-equivalence over a chain that includes successors forged AFTER a feed EOF (T-REC-03 two-clean-runs byte-identical + T-REC-05 kill/warm-start byte-identical); the verbatim VenueRole::Unknown halt-on-feed-end default preserved; and a committed sustained-past-k live transcript (CE-AF-6b: > k Ade blocks settle into the relay's ImmutableDB across >= 1 follow-link EOF, warm-start replay byte-identical; operator-gated on the rung1-auto C2-LOCAL harness). RED/GREEN-only, NO BLUE change (mirrors DC-NODE-18). DESIGN RESOLUTIONS (2026-06-08): OQ-19-2 no numeric cap, fence to the certified single-producer run; OQ-19-5 NEW rule (not a DC-NODE-05 mutation); OQ-19-6 explicit GREEN 5th planner input (no RED LoopState re-derivation). WORDING: scoped to a LoopState::Ending caused SOLELY by structural feed EOF -- a fatal source failure exits via Err/fail-fast and is never continued. AT CLOSE: strengthened_in += DC-NODE-19 on DC-NODE-05 (feed work still drains before forge; no direct durable tip advance), CN-NODE-02 (lifecycle owner = explicit operator shutdown / fatal error, not accidental feed EOF), T-REC-03 + T-REC-05 (replay equivalence now covers post-feed-end forged successors), and DC-NODE-18 (the proven extend state is now sustained); DC-CONS-03 explicitly untouched. OQ-KA (follow-link keep-alive/reconnect) stays a separate non-blocking cousin. OPEN at cluster-doc: OQ-19-1 (the cancellation-safe Idle wait under a dead feed -- a clock-tick wakeup so the forge cadence is not starved).