igneum/scene
igneum-labs 2c58912211 Live proving feed: the page says when its shard states are stale, and a chain block with an empty plan reads "no shards in this block" (8 October 2026, main's order: the project lead wants to watch proving and shards in real time; a stale snapshot must read as stale). Reading of the day: /api/live's proven and paid states come from the Devnet 3 observer's own node on igneum-build-1 (igneum-observer-node-dn3, EVM 26850), not from hub-1; that node stopped crediting payouts at 23:57Z on 7 October (paidShards frozen at 7,304 while blocks carried 8,457 proof records by 03:00Z and hub-1 counted 11,861 by 08:56Z), and the page kept showing the paid total as fresh. site/lib/proving-health.mjs (tests known-failed first: "Cannot find module", then 10 green on build-2): stale when the observer's last status read is over 60 s old (status_at, new in the observer's live_state.proving), when the node's tip trails the newest block by over 300 DAA, or when blocks carried proof records in the last 10 minutes and no shard moved to verified or paid for 10 minutes (the blind-to-records class); a quiet chain is not stale for lack of credits. /api/live carries stale, stale_reason, status_age_s, tip_lag_daa, records_10m and last_change_at on proving (two more indexed readings; scene/feed-contract.json lists the keys; the recorded fixture carries them). /live: the Proven tile's line reads "proving feed stale: ..." in ember, else "... last credit N s ago"; the inspector's count adds "feed stale". Scene 2.0.7: a chain block whose plan is known (block.number set, carried as plan on the normalised block) and empty reads "no shards in this block"; loading and late stay for an unread plan (shard-words test, known-failed on 2.0.6). Gate: the health test joins the site unit-test line.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-08 09:12:56 +00:00
..
fixtures Live proving feed: the page says when its shard states are stale, and a chain block with an empty plan reads "no shards in this block" (8 October 2026, main's order: the project lead wants to watch proving and shards in real time; a stale snapshot must read as stale). Reading of the day: /api/live's proven and paid states come from the Devnet 3 observer's own node on igneum-build-1 (igneum-observer-node-dn3, EVM 26850), not from hub-1; that node stopped crediting payouts at 23:57Z on 7 October (paidShards frozen at 7,304 while blocks carried 8,457 proof records by 03:00Z and hub-1 counted 11,861 by 08:56Z), and the page kept showing the paid total as fresh. site/lib/proving-health.mjs (tests known-failed first: "Cannot find module", then 10 green on build-2): stale when the observer's last status read is over 60 s old (status_at, new in the observer's live_state.proving), when the node's tip trails the newest block by over 300 DAA, or when blocks carried proof records in the last 10 minutes and no shard moved to verified or paid for 10 minutes (the blind-to-records class); a quiet chain is not stale for lack of credits. /api/live carries stale, stale_reason, status_age_s, tip_lag_daa, records_10m and last_change_at on proving (two more indexed readings; scene/feed-contract.json lists the keys; the recorded fixture carries them). /live: the Proven tile's line reads "proving feed stale: ..." in ember, else "... last credit N s ago"; the inspector's count adds "feed stale". Scene 2.0.7: a chain block whose plan is known (block.number set, carried as plan on the normalised block) and empty reads "no shards in this block"; loading and late stay for an unread plan (shard-words test, known-failed on 2.0.6). Gate: the health test joins the site unit-test line. 2026-10-08 09:12:56 +00:00
feed-contract.json Live proving feed: the page says when its shard states are stale, and a chain block with an empty plan reads "no shards in this block" (8 October 2026, main's order: the project lead wants to watch proving and shards in real time; a stale snapshot must read as stale). Reading of the day: /api/live's proven and paid states come from the Devnet 3 observer's own node on igneum-build-1 (igneum-observer-node-dn3, EVM 26850), not from hub-1; that node stopped crediting payouts at 23:57Z on 7 October (paidShards frozen at 7,304 while blocks carried 8,457 proof records by 03:00Z and hub-1 counted 11,861 by 08:56Z), and the page kept showing the paid total as fresh. site/lib/proving-health.mjs (tests known-failed first: "Cannot find module", then 10 green on build-2): stale when the observer's last status read is over 60 s old (status_at, new in the observer's live_state.proving), when the node's tip trails the newest block by over 300 DAA, or when blocks carried proof records in the last 10 minutes and no shard moved to verified or paid for 10 minutes (the blind-to-records class); a quiet chain is not stale for lack of credits. /api/live carries stale, stale_reason, status_age_s, tip_lag_daa, records_10m and last_change_at on proving (two more indexed readings; scene/feed-contract.json lists the keys; the recorded fixture carries them). /live: the Proven tile's line reads "proving feed stale: ..." in ember, else "... last credit N s ago"; the inspector's count adds "feed stale". Scene 2.0.7: a chain block whose plan is known (block.number set, carried as plan on the normalised block) and empty reads "no shards in this block"; loading and late stay for an unread plan (shard-words test, known-failed on 2.0.6). Gate: the health test joins the site unit-test line. 2026-10-08 09:12:56 +00:00
feed-contract.md Chain scene 2.0.3: /live and the home fold paint on every push whatever the document's visibility says; the renderer, its palette and its feed contract move to one shared folder scene/ with byte-equal copies checked by the gate (7 October 2026, 15:2x UK) 2026-10-07 13:29:38 +00:00
live-dag.js Live proving feed: the page says when its shard states are stale, and a chain block with an empty plan reads "no shards in this block" (8 October 2026, main's order: the project lead wants to watch proving and shards in real time; a stale snapshot must read as stale). Reading of the day: /api/live's proven and paid states come from the Devnet 3 observer's own node on igneum-build-1 (igneum-observer-node-dn3, EVM 26850), not from hub-1; that node stopped crediting payouts at 23:57Z on 7 October (paidShards frozen at 7,304 while blocks carried 8,457 proof records by 03:00Z and hub-1 counted 11,861 by 08:56Z), and the page kept showing the paid total as fresh. site/lib/proving-health.mjs (tests known-failed first: "Cannot find module", then 10 green on build-2): stale when the observer's last status read is over 60 s old (status_at, new in the observer's live_state.proving), when the node's tip trails the newest block by over 300 DAA, or when blocks carried proof records in the last 10 minutes and no shard moved to verified or paid for 10 minutes (the blind-to-records class); a quiet chain is not stale for lack of credits. /api/live carries stale, stale_reason, status_age_s, tip_lag_daa, records_10m and last_change_at on proving (two more indexed readings; scene/feed-contract.json lists the keys; the recorded fixture carries them). /live: the Proven tile's line reads "proving feed stale: ..." in ember, else "... last credit N s ago"; the inspector's count adds "feed stale". Scene 2.0.7: a chain block whose plan is known (block.number set, carried as plan on the normalised block) and empty reads "no shards in this block"; loading and late stay for an unread plan (shard-words test, known-failed on 2.0.6). Gate: the health test joins the site unit-test line. 2026-10-08 09:12:56 +00:00
proof-core.js Chain scene 2.0.3: /live and the home fold paint on every push whatever the document's visibility says; the renderer, its palette and its feed contract move to one shared folder scene/ with byte-equal copies checked by the gate (7 October 2026, 15:2x UK) 2026-10-07 13:29:38 +00:00
README.md Chain scene 2.0.4: the box's height follows the lanes (onSize, autoHeight, the lane geometry in stats) (7 October 2026, 16:3x UK) 2026-10-07 13:58:33 +00:00
tokens.css Chain scene 2.0.3: /live and the home fold paint on every push whatever the document's visibility says; the renderer, its palette and its feed contract move to one shared folder scene/ with byte-equal copies checked by the gate (7 October 2026, 15:2x UK) 2026-10-07 13:29:38 +00:00

scene: the chain scene, once

The live devnet animation on the site's home fold and /live, and the miner app's "The chain, live" card and its Inspect view, are ONE renderer fed ONE JSON shape. This folder is the source; everything else is a copy or a reader.

File What it is Copies
live-dag.js EMBER 02 IgneumDag 2.0.4: lanes per vote key, parent curves, the selected chain, checkpoint bands, proof glow; the box height follows the lanes (onSize, autoHeight) site/live-dag.js, app/igneum-app/ui/live-dag.js
proof-core.js IgneumProof 2.0.0: the selected block's shards site/proof-core.js, app/igneum-app/ui/proof-core.js
tokens.css The fourteen palette tokens the two scripts read from :root, dark and light, the brand package's values the scene-tokens block in site/site.css and app/igneum-app/ui/app.css
feed-contract.md, feed-contract.json The feed shape, in words and as key lists read by tools/scene/feed-contract.mjs and the app's src/live.rs test
fixtures/live-2026-10-07.json One recorded /api/live?window=300 reply the parity, paint and contract tests

node tools/scene/sync.mjs writes the copies; --check is the gate line (byte-equal scripts, an equal token block, the token names defined nowhere else, a print block excepted); --self-test proves the check on known-failed cases first. A side (site or app) takes part once its live-dag.js copy exists; a release-* branch checks the app's copies only, because the release branches carry the site tree as it was when they were cut and the site deploys from master alone.

The one rule for the two surfaces

Same renderer, same tokens, same feed, same mount options: window: 60, fps: 60, poll: false, the page polls /api/live?window=300 every 2 s and pushes. What may differ is the box the scene sits in (the home hero is 500 px tall, /live 420 px, the app's card 220 px in compact mode and its Inspect view the /live height), and the app's viewpoint: its mine option names this machine's vote keys, so its own blocks glow and its lane reads YOUR KEY. That is an overlay on the same picture, never a second renderer, never a rewritten feed. The phone rule (30 s window, four lanes, bigger nodes) keys on the viewport width under 720 px, not on the canvas width: a 640 px hero on a laptop is not a phone.

The box's height follows the lanes (2.0.4): wanted height = top padding + axis padding + lanes shown times laneHeight (46 px, 40 on a phone, 26 compact; at most maxLanes 7, narrowLanes 4 on a phone, never under 2). The renderer calls onSize(heightPx, {lanes, laneHeight, narrow, compact}) whenever that changes and exposes getWantedHeight(); a page that lays out its own box sets its height from the callback. With autoHeight (on by default when the host set no CSS height on the canvas, forced either way by the option, never in compact mode) the renderer sets canvas.style.height itself and shows every lane up to the cap. Every current host sets a height (/live 420 px, the hero 500 px, the app's card 220 px and its Inspect view 420 px), so until a page opts in the frames are unchanged.

The tests (all in tools/ci/pre-push.sh)

Line What it proves
tools/scene/sync.mjs --self-test && --check the copies are the source, the tokens live once
tools/scene/paint-test.cjs a push paints with the document hidden, the observer silent and no animation frame (the blank /live of 7 October 2026)
node --test tools/scene/feed-contract.test.mjs the fixture validates; a rewritten miner, a float now, a stray key are refused
tools/scene/parity-remote.sh on build-2: the fixture through the site's /live and the app's UI, three frames each, pixel-equal apart from the app's lane label; a changed token fails first