docs(spec): section 26 prover loop spawn, four controls, kill switch (#3265) - #627
Merged
Merged
Conversation
…l switch (dig_ecosystem#3265) Normative SPEC.md section 26 locking the shape of the PR that spawns the reward prover loop, before any implementer touches it: - the spawn site (server.rs after spawn_claim_driver_from_config) and the three-function seam mirrored from rewards_claim/driver.rs, with the closed ProverDriverRefusal set - rewards-prover.json: exactly three keys, every default stated (enabled=false under a compile-time assertion, mode=dryRun, standard_fee_mojos=0 refuses), a refused-not-clamped fee maximum, a corrupt marker that is never default() - control 2: the spawn-time line and its exact figures (24 bundles/day, 192 actions/day, FeeBudget::daily_limit_for, 0.24 XCH/day = 87.6 XCH/year at 0.01 XCH, 192 removals/day -> ~1.3 days, 96 churns/day -> ~2.6 days), and the arithmetically false 96/1.3 pairing named so it is never printed - control 3: DryRunChainPort contract, dry-run write bounds never touch the live store, log-only visibility stated as a 0.12.0 wire limitation - control 4: two tasks one watch channel, sentinel file + config re-read every 60 s, the wedged-reachability argument and its spawn_blocking precondition, Stopped is durable and one-way, no RPC method - cycle honesty: CycleOutcome so a cycle that cannot see never completes, absent seams fault ChainSourceUnavailable, NotConsulted while the inventory is undetermined, chain-derived counters never local (dig_ecosystem#3274) - the required periodicity/kill-switch test shapes and the composed-system gate that alone releases PROVER_LIVE_MODE_RELEASED - sequencing: controls first, then #3292, #3421, #3422, #3423, gate, release Docs only. No source, no dependency, no version change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MichaelTaylor3d
marked this pull request as ready for review
September 27, 2026 11:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds SPEC.md §26 — Reward prover loop: the spawn, the four controls, and the kill switch (DIG-Network/dig_ecosystem#3265), plus a one-sentence cross-reference in §5. Docs only: no source, no dependency, no version change.
Written against tip
69c793a7and the publisheddig-rewards-coin0.8.0 /dig-rpc-protocol0.12.0 sources. Every clause either cites the code that already satisfies it or is marked (target) and listed in §26.14 with the ticket that lands it.The locked shape, in one paragraph
Spawn from
serve_with_shutdownright after the claim spawn, through adecide → spawn_if → from_configseam mirrored fromrewards_claim/driver.rs(shape only — the claim config'sdefault_enabled() == trueis explicitly the trap, §26.3 cl. 6). Config is<state_dir>/rewards-prover.jsonwith exactly three keys:enabled(default false, under aconst _: () = assert!so the default cannot flip silently),mode(dryRundefault |live),standard_fee_mojos(default0= refuse; above 0.1 XCH = refuse, never clamp). The node never writes the file. Spawn prints ONE warn line with the §6.3-derived figures (24 bundles/day, 192 actions/day,FeeBudget::daily_limit_for(fee), 0.24 XCH/day = 87.6 XCH/year at 0.01 XCH, 192 removals/day → ~1.3 days, 96 churns/day → ~2.6 days) per funded distributor. Dry-run is aDryRunChainPortdecorator that logs and never calls the inner writes, runs the scheduler against a scratch bound store, and is log-only (0.12.0 cannot carry a mode). The kill switch is two tokio tasks on onewatchchannel: a switch task that ticksheartbeat_tick, re-readsenabled+<state_dir>/rewards-prover.STOPevery 60 s and flips the sender; a cycle task thatselect!s the receiver against the cycle so a wedged cycle is dropped immediately — no RPC method.Stoppedis durable until process restart. A cycle whose seam is absent faults (CycleOutcome, never advanceslast_cycle_completed_at); while the inventory is undetermineddig.getRewardProverStatusanswersHalf::NotConsulted; money counters are chain-derived, never local. Live mode is refused untilPROVER_LIVE_MODE_RELEASEDis flipped by a one-line PR citing the composed-system gate, which follows #3292, #3421, #3422, #3423.Hard truth the section states
At this tip a spawned loop faults
ChainSourceUnavailableon every cycle (chain_port.rs:77-97). The controls are verifiable now; distribution is not. The section orders the port work AFTER the controls and makes "spawns, reports Idle, distributes nothing" unrepresentable (§26.9 cl. 9).Decider questions (for the orchestrator, not settled here)
Half::NotConsulted(locked, node-side only) vs a whole-call error vs a new wire field (protocol lane).PROVER_LIVE_MODE_RELEASEDtripwire — a code constant flipped only by the gate verdict (locked).Verification
git ls-files --eol SPEC.md→ LF in/out; 15 new headings; 21(target)markers; cross-reference at §5 line 1095.Refs: DIG-Network/dig_ecosystem#3265, #3274, #3261, #3292, #3421, #3422, #3423.
🤖 Generated with Claude Code