soft3/audit/chain/the focus economy in the kernel — implementation receipt 2026-10-17.md

Receipt of the implementation of chain-economy (and the amended chain.md, chain-wire.md, chain-conformance.md §14) in crate/src/chain/. Branch soft3 feat/focus-economy on origin/main 518c2ae. Requirements stay in the specs; this file records what was built, what was run, and what was observed.

Stand: ~/cyber/soft3/.worktrees/focus-economy/ — soft3 on the branch; hemera release/0.4 7237a23; bbg master be5c5db (bbg#51, dimension version 4); tru master 1ea853e (tru#40, the epoch engine); lens feat/hemera-0.4 529adcb; zheng and nox release/0.4; cybergraph feat/durable-applications; foculus b28f0a2; mudra, tok master; strata, honeycrisp, tade, radio, neuron, inf, file, joy, trident default checkouts. bbg, tru, zheng, nox, cybergraph, foculus, mudra and tok still require cyber-hemera = "0.3" on their default branches and carry a one-line stand-local bump to "0.4" (the hemera 0.4 receipt's open item). Machine: M4 Max, 48 GB, shared with other agents' builds.

what landed

spec where what
§0 params.rs every economy constant; EpochClock { L, D, MIN_LOCK } — SPEC on the launch chains, a shortened clock only on dev/test nets (SOFT3_DEV_EPOCH=L:D:MIN_LOCK, ignored for pussy and bostrom)
§3.1 wallet/tx.rs, economy/mod.rs card_id, stake_key, focus_key, payout leaf/node/root, φ digest
§3.2 bbg_state.rs positions as bbg CardRecord { owner, particle, author, valence, since } (dimension version 4); stakes and the pool as raw balance keys; zero rows absent
§3.3 apply.rs kind 2 with amount > 0: native only (TxError::StakeToken), valence fixed while staked (TxError::Valence), amount + fee spendable, stake to stake_key, card created or since restarted; TxError::Box retired
§3.4–§3.5 wallet/tx.rs, chain/tx.rs, net/codec.rs, apply.rs kind 6 unlock (120 B body, 224 B), kind 7 payout (144 B body, 248 B); NSIG1 over the chain.md §2.1 statement, subject from; unlock after since + MIN_LOCK, partial or full (card deleted at 0), fee payable from what it returns; kinds 8–10 rejected
§2, §5 economy/settle.rs, economy/run.rs, engine.rs at every boundary block the state is frozen (Snapshot, keyed by block id) and the epoch's settlement starts on a worker thread; the block at boundary + D joins it (waits if unfinished, never guesses); results keyed by the two boundary ids, cached under $home/epochs/ (keyed by engine id and quadrature too)
§4.1 economy/weights.rs genesis weights from the genesis file at load, stored nowhere
§4.2–§4.4, §5.1 economy/focus.rs FocusEngine seam; the node runs tru's epoch engine (Tru, threads = cores − 1, ≤ 8); A_mid; the gradient integrated over k Gauss–Legendre nodes, k = 1 (the midpoint of §5.1) by default, k a parameter
§5.2–§5.6 economy/settle.rs Δs per card and side (a side switch is a decrease and an increase), active only, new-high rule with marks per axon side, ρ = 1, budget pool/4, 1 % cap, floor rounding, dust stays; payouts to the payout owner of G_E; marks rewritten; time[settle(E)] = hemera(D_EPOCH ‖ record) (198 B)
§6 apply.rs coinbase SUBSIDY − cut + fees, the pool takes cut; focus_bps(E) = min(5,000, isqrt(active · 10^8 / supply)) fixed at the end of each boundary block; conservation counts stakes and the pool; Σ stake keys = running total checked at every settlement block
§11 economy_api.rs, node/chain_routes.rs, node/chain_node.rs GET /epoch/{E}, /epochs, /focus, /focus/{particle}, /card/{id}, /cards/{neuron}, /economy; /status gains epoch, next-boundary, last-settled, focus-bps, pool, active-stake, total-stake, stake-keys-match, settlement-ok, focus-engine
CLI bin/soft3.rs soft3 chain tx --kind link --valence V --amount A, --kind unlock, --kind payout --payout OWNER
§10 economy/vectors.rs, conformance.rs chain-conformance §14 scenarios driven through apply::transition (no PoW), blessed

High-water marks and the economy scalars (focus_bps, stake totals, last_settled) are kernel state: pure functions of history, journaled with the block's undo, not committed; their effects reach state_root through the balances (payouts, coinbase) and time (the record).

tests

cargo test --release --no-default-features --features chain-conformance (in crate/, __CARGO_TEST_ROOT at the wrapper): 276 lib passed, 1 ignored (the cost measurement), 17 bin, 2 adversary, 1 mine e2e — 0 failed (lib was 263 on 518c2ae). 25 of the lib tests are the economy's.

Economy tests (chain::economy::*, chain::tests::economy::*):

  • §14 identities and integers exactly as the spec quotes them (card, stake key, focus key, payout leaf and node, φ digest of [2^59, 2^59]; focus_bps, cut, mark decay 998,077 / 500,047, budget division 333×3 and 10,000/250,000, epoch/settle);
  • the reference engine's adjoint against a finite difference; tru's digest equals hemera over tru's preimage; 1 and 8 threads bit-identical; quadrature k = 1 and 2;
  • new-high rule exact (x at mark = height is 0, one epoch of decay gives x/100, the other side's mark does not limit), linearity in stake (one author 100 vs 60 + 40), passive earns nothing, −1 on an absent axon does nothing, hedging pays only the side with a > 0;
  • engine end to end over five epochs: +1 on the dominant edge, a passive lock, −1 against a spreading edge, a ring, 20 zero-stake spam links, a payout owner change (paid to the owner of the snapshot), partial and full unlock, an unlock-and-relock on the same side (x of the relock < 1/20 of the first), the ring paid ≤ 1 % of its added stake;
  • determinism: a second node fed the blocks has every epoch record equal; a restart replays through the settlement cache to the same root and records;
  • reorgs: three blocks above the boundary reproduce the record; a fork below the boundary replaces it and changes the record; roots equal;
  • off the block path: with a slow engine, four blocks validated while the worker ran; settle(1) joined it;
  • 2,000 random blocks of locks, unlocks and payout changes: conservation and Σ stake keys at every height, settlements every 10 blocks;
  • the node surface: /epoch, /epochs, /focus, /card, /cards, /economy.

settlement cost (§7.2)

Measured with the ignored test settlement_cost_on_genesis_files on the real genesis files (~/.cache/cyber/genesis/*.tade, dimension version 4) through tru 1ea853e, epoch 1 = genesis weights plus 2,000 positions (half +1, half −1, stake ½ of the axon's genesis weight) on genesis axons:

graph axons particles φ*_0 (1 thread) settlement: φ*_E + gradient at A_mid + attribution, 1 thread same, 8 threads peak RSS
pussy 26,805 16,270 0.036 s 0.12 s 0.14 s —
bostrom 2,990,817 3,237,461 9.3 s 27.0 s 9.6 s 5.0 GB (incl. the 331 MB file decode)

Digests equal across thread counts (bostrom φ*_0 0b889535…, pussy 95606683…). Against SETTLE_BUDGET = 900 s the bostrom settlement is 33× under on one core and 94× under on eight; a node starting at the boundary has finished long before settle(E) an hour later. Genesis weights: bostrom Σ G 344,014,106,319,158, 282,860 frames at the floor, digest d5f6f23c…; pussy Σ G 41,802,483,829,015,338, 30 at the floor, digest 218a8775….

genesis under dimension version 4

soft3 genesis build rebuilt both files into /tmp: byte-identical to the cached files (pussy sha256 ec7aee79…, bostrom ffa3d6dd…; the chain ids do not move). Only the roots move:

state root block-0 id
pussy d48fee478584d248123c63e2ee6c56224f159c7dadbc625f4261f6af49130371 (v3 a3607987…) 73208ee2d43fbb0420119ceff23eab79e9d96921050e2a2137d0705c461852d4
bostrom fa0c2c9404a6eff04737ed7dfe11c63c1992b4820fdf039a55c6d2f103d7508d (v3 c50a6d84…) a13f0f627dae47a00fe50f7f9c538148345f52ab6200518e2360798c504fc3d5

Bostrom root: 73 s wall, 91 s user, 7.9 GB max RSS. The reports (*.tade.json) in ~/.cache/cyber/genesis/ were replaced; the files were not touched. conformance/chain-genesis.toml carries the new values; cyber/launch row 14 owes the same update.

conformance

soft3 conformance bless chain --genesis ~/.cache/cyber/genesis/pussy.tade: 54 entries, 28 moved (every state root and block-0 id: dimension version 4), 26 new under chain::economy@v1 and the pussy genesis entries (genesis weights, φ*_0 at 1 and 8 threads). soft3 conformance check chain green.

the fleet

nu scripts/chain-fleet.nu --bin crate/target/release/soft3 --threads 1 --secs 40 --epoch 6:3:9 --http-base 17980 --radio-base 17990 --keep (the --epoch flag is new: it exports SOFT3_DEV_EPOCH for the dev net and adds an economy step). GREEN, every scenario of the hemera receipt plus:

  • the depth-3 fork from 14 (main 17, fork 19) replaced the boundary block at 18 — a reorg across a boundary on four live nodes; every node moved to the fork and settled from its snapshot;
  • a staked link (soft3 chain tx --kind link --valence 1 --amount 10^9) mined at 21; the records of epochs 4 and 5 equal on all four nodes (0d7c586e…, 199931f0…; budgets 225 and 675, pool 900 → 2,700; paid 0 — the dev graph is that one axon, whose weight does not move a two-particle φ*); /cards shows the position, unlock at 30;
  • node 3 killed at 33, replayed from disk (through $home/epochs/), synced to 45, conserved.

Log /tmp/fe-genesis/fleet-1.log, artifacts /tmp/chain-fleet.9K8DTD.

findings for the owner and the spec

  1. The new-high rule does not bound a quiet-epoch recycler. Attribution scales x(c) by N/R, but pay = min(cap, ⌊B · x / X⌋) normalises by X: a relock that is the only earner of its epoch takes min(cap, B) however small its x. The blessed new-high scenario shows it: the first lock was paid 649,257, the relock under a mark two decays below the old height (99.6 % of it) 1,785,458. The bound left is the 1 % cap per settlement and the 7-day lock per cycle, not "the mark's decay" of §9. A fix that keeps everything else: cap on the new height, cap(c) = ⌊Δs · (N/R) · R_MAX_PPM / 10^6⌋ (or scale the budget by Σ x / Σ a⁺). Not implemented — a spec decision.
  2. Under J = D_KL(φ ‖ u), most new links lower syntropy. Stake on a minor edge spreads focus (∂J/∂A < 0) and earns nothing as +1; it earns as −1. On the test graphs the earners are +1 on dominant edges and −1 against minor ones. This is the spec's objective working as written; the owner should see it before launch (rewards.md §1 "pay for descent").
  3. The record's syntropy: i64 overflows on bostrom. J(φ*_0) is 9,886,742,015,786,730,065 at 2^60 (8.58 nats) > i64::MAX; the kernel saturates. tru's agent reports an amendment to i128 is coming; the record grows to 230 bytes then.
  4. Hedging pays. +1 and −1 of equal size on one axon leave A unchanged and the +1 side is paid as if it had added weight (§9 says "capital doubled for the same credit" — that is the behaviour; the credit is for no change of the graph).

Graph