27 KiB
Igneum Miner 0.3.6: the testnet adoption, staged 5 October 2026
Prepared by the integration agent on the morning of 5 October 2026 after the owner's decision. Nothing was deployed,
published or merged to master. The app and document work sits on branch testnet-adopt (pushed to origin), worktree
/Users/joshm/Projects/igneum-wt-adopt; the node work sits on the fork branch release-0.3.6 (local only; the fork
has no remote), worktree vendor/igneum-node-036. The cut is one command (section 4) after the inputs push of
section 3, which must come first.
0. The decision (owner, 5 October 2026)
The proposed testnet identity (docs/testnet/README.md) and the proposed fee floors and prover-gas table
(docs/analysis/base-fee-floor.md, spec 05 section 5.11) are ADOPTED as proposed. The three documents now say so;
the fork's FeeParams::CALIBRATED_V1 and TESTNET_PARAMS are unchanged from the proposal.
One rule the adoption added, so the live devnet is never forked by a node update: the devnet keeps its fee rules until a height switch says otherwise (section 5).
1. What is in
1a. The app repository (branch testnet-adopt, from origin/master 2054ae3 = the 0.3.5 cut)
| Merged | Branch head | What it carries | Conflicts and how they were resolved |
|---|---|---|---|
origin/testnet-prep |
beed743 (3 commits over e22068f) | docs/testnet/README.md, docs/analysis/base-fee-floor.md, spec 05 section 5.11, docs/plans/history-rewrite.md (G14, not acted on here), G13 signed build inputs (app/igneum-app/src/inputs.rs, igneum-ota-sign sign-inputs / verify-inputs, packaging/windows/push-inputs.sh, inputs-manifest.sh, node-source.pin, test-inputs-signing.sh, fetch-ci-artifacts.sh --sign-manifest, .github/workflows/windows.yml), tools/ci/check-workflow-shell.mjs, the testnet terms on the download section, site/wallet.html, the litepaper's app paragraph, the fast-time profile's fees object |
four generated site files. site/index.html: the dev-fee sentence of 0.3.5 kept, testnet-prep's #testnet-terms card and wallet link kept (both sides of the download section); the inlined journey block is regenerated. site/litepaper.html: 0.3.5's two-paragraph dev-fee text kept (it is the fuller one; testnet-prep's one-sentence version dropped), testnet-prep's MetaMask and Igneum Wallet paragraph kept. site/journey.json: 0.3.5's log kept (the feed is the newest 40 entries; testnet-prep's older entries had already aged out of it). site/sitemap.xml: both /miners and /wallet. Then node site/build.mjs |
On top of the merge, in the same branch:
| Change | Where |
|---|---|
| "proposed" to "adopted 5 October 2026" with the sign-off noted, and the per-network fee rule written in | docs/testnet/README.md, docs/analysis/base-fee-floor.md, docs/spec/05-fees-and-economics.md (section 5.10 and the parameter table) |
fees_v1_activation_daa: 0 added to the 60x fast-time profile (the fork's fast_time_60x_file_is_the_devnet_at_60x test wants every override field present) |
infra/fast-time/override-60x.json |
| this file | docs/plans/release-0.3.6.md |
1b. The node fork (branch release-0.3.6 in vendor/igneum-node-036, from release-0.3.5 20139145)
| Fork merge | Head | What it carries | Conflicts |
|---|---|---|---|
testnet-params (worktree vendor/igneum-node-testnet, forked from finality-fixes 6aa69a45) |
11e86144 | consensus/core/src/fees.rs (FeeParams, PgasTable, CALIBRATED_V1, PROTOTYPE), Params.fees and the override file's fees object, the testnet identity (igneum-testnet-1, chain id 4462, ports 268xx, the frozen genesis, FinalityParams::MAINNET, every switch at 0), the override file refused on the testnet, the execution layer reading the installed set (B_p, S_p, the intrinsic, modexp, the floors) |
consensus/core/src/config/params.rs: both methods kept (apply_env_pow_schedule from G12 and install_fee_params); the M31 comment on max_coinbase_payload_len kept. kaspad/src/daemon.rs: the 0.3.5 start-up block kept (environment schedule on devnet and simnet, install_pow_schedule, the digest line) and install_fee_params with its own print added after it |
On top of the merge, the fee height switch (section 5), in the same branch:
| Change | Where |
|---|---|
FeeParams::DEVNET and SIMNET = PROTOTYPE; TESTNET and MAINNET = CALIBRATED_V1. FeeSchedule { base, v1_activation_daa } with at(daa); install_fee_params(base, switch); fee_params_at(daa) replaces fee_params() |
consensus/core/src/fees.rs |
Params.fees_v1_activation_daa (devnet and simnet u64::MAX, testnet and mainnet 0), OverrideParams.fees_v1_activation_daa, the digest rule of section 5, four new or changed tests |
consensus/core/src/config/params.rs |
the switch and a fees object printed from the override file; the installed schedule printed with the network |
kaspad/src/daemon.rs |
shard_proving_gas_budget_at(daa) |
consensus/core/src/proving.rs |
every reader takes a DAA score; execute_segment picks the set by the block's DAA score and raises the carried base fees to its floors; the inspector carries the block's pgas table (modexp reads it); next_base_fee takes floor and denominator; the pool's add and select and every RPC quote use the tip's DAA score plus one; the shard plan uses the segment's; one new executor test |
igneum/exec/src/{config,executor,pgas,pool,proving,rpc,service}.rs |
On top of that, two more fork commits:
| Commit | What |
|---|---|
| cf369022 | DEV_FEE_ADDRESS = 0x7F45d7d7272e57639BeBb739A60B05bB2CD4C126, the release dev-fee payout address (testnet and mainnet; the project lead, 5 October 2026, EIP-55 checksum verified, on file at ~/.config/igneum/dev-fee-release.json); DEV_FEE_ADDRESS_DEVNET unchanged; the placeholder test replaced by the_release_address_pays_the_fee_outside_the_devnet (cargo test -p igneum-miner dev_fee: 5 passed). docs/design/miner-dev-fee.md updated on this branch |
| 2b6d23ef | the merge of fork miner-latency (section 2), the final tip of release-0.3.6 |
1c. What is out
| Branch | Why |
|---|---|
the app repository's local miner-latency (dd47ff3, worktree igneum-wt-latency: tools/miner-latency/run.mjs, docs/plans/miner-latency.md, two bench-log entries; never pushed to origin) |
not part of this task; it conflicts with testnet-adopt only in docs/bench-log.md (both appended entries) and can be merged at any time. The harness was run from that worktree for section 2 |
2. The miner-latency decision: IN
Fork miner-latency (0f88b6d6, vendor/igneum-node-latency, one commit over devnet-v4: the NewBlockTemplate
subscription in the miner, node-side template prewarm, workers switching without draining the batch, --poll-templates
and --job-ms) was merged on a side branch first (release-0.3.6-latency, worktree vendor/igneum-node-036-lat,
c07093ce) and landed on release-0.3.6 (2b6d23ef) only after both gates passed on the merged tree:
| Gate | Command | Result |
|---|---|---|
| Miner tests | cargo test -p igneum-miner on c07093ce |
ok: 15 passed, 0 failed |
| 3-node fast-time run | node tools/miner-latency/run.mjs --mode subscribe (from igneum-wt-latency, IGNEUMD and IGNEUM_MINER = the release build of c07093ce in vendor/igneum-node/target-036-lat/release, under the run lock, 08:11 to 08:16Z) |
3 nodes up (peers 2/1/1 throughout), 3 CPU miners at 2 threads for 295 s: 82 + 81 + 80 blocks accepted, 0 rejected; chain blocks 228, merged blue 15, merged red 0, tips mean 1.03 max 2, sinks agree; 236 to 241 template switches per miner, notified p50 14 to 16 ms, template p50 20 to 24 ms, switched p50 46 to 52 ms (p90 118 to 130 ms, max 194 to 372 ms); node prewarm 52 to 56 builds a minute, mean 3 to 4.5 ms; 1 to 2 stale submits per miner; no error, panic or WORKER FAULT line in any miner log |
| The dev fee through the new feed | node tools/dev-fee/run.mjs --secs 180 on the same binaries (two nodes, three stub miners, two at the default fee and one at --dev-fee 0, then igneum-miner payouts; 08:17 to 08:20Z) |
pass: miner-a found=327 fee=4, miner-b found=301 fee=4, control miner-c found=309 fee=0 (0 dev-fee block lines); payouts on both nodes: 938 blocks, the devnet dev address 8 blocks = the miners' counters, 1.27% of the fee-paying miners' blocks against the 1% expectation |
The conflicts (13 hunks in igneum/miner/src/main.rs, the 0.3.5 dev fee and X21 mismatch guard against the latency
rewrite of the template path) were resolved by keeping both sides: the feed takes the dev fee and requests one
template in 100 with it, as the 0.3.5 fetcher did; the continuous CPU loop carries the fee through Work.dev_fee
and counts fee blocks; the found path runs check_found into the mismatch guard; WorkEngine::Real holds the
day-keyed EpochRef of M30. The 3-node run above showed fee=0 on every miner: 243 blocks found at 1 in 100
templates expects about 2.4 fee blocks, and zero has a probability of about 9%, so the dev-fee harness was run as
the third gate; it showed the fee riding through the new feed (8 of 8 fee blocks on chain, the control at 0).
3. Test results, with the command
Every build ran through the main checkout's lock, /Users/joshm/Projects/igneum/tools/lock/with-lock.sh build, at
nice -n 19 with -j 4. The fork's builds used CARGO_TARGET_DIR=vendor/igneum-node/target-036, an APFS clone of
target-release (48 s to clone). The rustup cargo (1.99.0) on ~/.cargo/bin.
3a. The app repository (worktree igneum-wt-adopt)
| Check | Command | Result |
|---|---|---|
| Site | node site/build.mjs |
built: bench, journey (40 entries), index, litepaper, live, evidence, wallet, 404, miners (6 rows) |
| Links | node tools/ci/link-check.mjs |
324 internal links across 8 pages, 0 broken |
| Workflow shell | node tools/ci/check-workflow-shell.mjs |
self-test fires on the fixture; 11 run blocks in 2 workflows, 25 .ps1 files, 0 findings |
| Signed inputs | packaging/windows/test-inputs-signing.sh with igneum-ota-sign built from this tree (cargo build --release -j 4 --bin igneum-ota-sign, 8 s with the cloned target) |
16 passed, 0 failed: the four positive cases, the ten refusals (changed zip byte, changed manifest byte, changed unpacked file, unlisted file, missing file, wrong pin, short pin, another key, the embedded key against the throwaway signature, the two sign-time refusals), and the Mac's real OTA key verified by the key compiled into the app |
| Shell parses | bash -n on push-inputs.sh, fetch-ci-artifacts.sh, inputs-manifest.sh, test-inputs-signing.sh |
ok |
| JavaScript parses | node --check on tools/ci/check-workflow-shell.mjs, tools/ci/link-check.mjs, site/build.mjs |
ok |
PowerShell parse rule (no $var: inside double quotes) |
the 0.3.5 scanner over every tracked .ps1 and the PowerShell strings in ota.rs, jobrun.rs, jobbuild.rs |
the 3 baseline hits of 0.3.5 only (two comments in check-ps51.ps1 that quote the rule; ota.rs line 1190, the Mac helper's bash); testnet-prep changed no .ps1 |
3b. The node fork (worktree vendor/igneum-node-036)
| Fork tip | Command | Result |
|---|---|---|
| a11455e7 (testnet-params merged, the fee switch) | cargo test -p kaspa-consensus-core with IGNEUM_FAST_TIME_FILE=<igneum-wt-adopt>/infra/fast-time/override-60x.json (the fast-time test wants every override field; the main checkout's file predates fees) |
ok: 101 passed, 0 failed, 2 ignored (lib) + 7 (db_compat); among them igneum_testnet_identity, override_params_carry_the_fees, override_params_carry_the_fees_v1_activation, consensus_digest_keeps_the_0_3_5_value_until_the_fee_switch_is_set (pins 9409dedac4bf... for the devnet params), consensus_digest_covers_every_consensus_field_and_nothing_else (the fee switch in its list), test_genesis_hashes, fast_time_60x_file_is_the_devnet_at_60x; 07:41Z |
| a11455e7 | cargo test -p igneum-exec |
ok: 11 passed, 0 failed; among them the_fee_switch_meters_by_the_block_daa_score (a block below the switch meters 200 intrinsic pgas and keeps its base fees; the block at the switch meters 300 and its base fees jump to the v1 floors) and the bomb tests re-sized to fit both tables; 07:43Z |
| a11455e7 | cargo test -p kaspa-consensus --features igneum-pow -- finality |
ok: 8 passed, 0 failed (92 filtered), 125.9 s |
| a11455e7 | cargo test -p kaspa-consensus --features igneum-pow -- difficulty |
ok: 15 passed, 0 failed |
| a11455e7 | cargo test -p igneum-miner |
ok: 12 passed, 0 failed (the guard and dev-fee tests) |
c07093ce (miner-latency merged on the side branch release-0.3.6-latency, worktree vendor/igneum-node-036-lat, CARGO_TARGET_DIR=target-036-lat) |
cargo test -p igneum-miner |
ok: 15 passed, 0 failed (the 12 above and job_size_follows_the_target_ms, cpu_found_nonce_is_matched_to_its_own_work, worker_found_hash_is_matched_to_its_own_template) |
| c07093ce | 3-node fast-time run (section 2) | pass (section 2) |
| cf369022 (the release dev-fee address) | cargo test -p igneum-miner dev_fee |
ok: 5 passed |
| 2b6d23ef (the final tip: cf369022 plus the latency merge) | cargo test -p igneum-miner |
ok: 15 passed, 0 failed |
Not built here: the release binaries for the three platforms (section 4b).
4. The morning cut, in order
4a. The signed inputs come first (G13)
The workflow and push-inputs.sh changed as a pair. From this tree on, .github/workflows/windows.yml fetches
payload-inputs.json.sig from the downloads host and refuses to build until igneum-ota-sign verify-inputs embedded
accepts the manifest's signature, the zip's sha256, every unpacked file and the node commit pinned in
packaging/windows/node-source.pin in the commit it builds. The downloads host holds no signature today (0.3.5
pushed an unsigned inputs.json and a bare .sha256), and the pin in this tree still reads 6aa69a45 (the 0.3.4
node, written by the old script). So the FIRST push of the new workflow would fail at "payload inputs" unless the
inputs are pushed from this tree before the workflow runs:
cd /Users/joshm/Projects/igneum-wt-adopt
gh auth switch --user igneum-labs
packaging/windows/test-inputs-signing.sh # 16 of 16, with the real key at the end
IGNEUM_NODE_SRC=vendor/igneum-node-036 IGNEUM_WIN_RELEASE=<the 0.3.6 Windows release folder> \
packaging/windows/push-inputs.sh --deploy # signs payload-inputs.json, writes node-source.pin
git add packaging/windows/node-source.pin && git commit -m "inputs: pin node <commit> for 0.3.6"
What the workflow needs, and where it comes from:
| Need | Source |
|---|---|
DL_TOKEN repository secret |
already set for 0.3.5 (gh secret set DL_TOKEN < ~/.config/igneum/dl-token); the workflow fetches the zip, the manifest and the signature with it |
| the embedded public key | compiled into the app (app/igneum-app/src/manifest.rs); igneum-ota-sign embedded prints it; push-inputs.sh refuses to sign if ~/.config/igneum/ota-signing-key.pub is not that key |
~/.config/igneum/ota-signing-key (0600) and .pub |
the OTA key the apps already trust; signs the manifest on the Mac |
packaging/windows/node-source.pin |
written by push-inputs.sh, committed with the push; the runner compares it with the manifest's node_source_commit |
| the Windows node exes | IGNEUM_WIN_RELEASE names the folder with igneumd.exe and igneum-miner.exe built from the fork commit the pin names (the 0.3.6 cross-build; proto-cuda/windows-node/cross-build.sh as in 0.3.5) |
Then the update manifest is signed only on request: packaging/windows/fetch-ci-artifacts.sh --sign-manifest <run-id> --deploy after the run is green, which re-verifies the run's inputs artifact against the key and the pin at the
run's commit before publish-manifest.sh runs.
4b. The merge and the ship
From the MAIN checkout, on master, after 4a's pin commit is on testnet-adopt:
cd /Users/joshm/Projects/igneum
gh auth switch --user igneum-labs
git fetch origin && git checkout master && git pull --ff-only
git merge --ff-only origin/testnet-adopt # testnet-adopt contains master 2054ae3
node tools/ship-app.mjs --check # 0.3.5 in all 6 files
node tools/ship-app.mjs 0.3.6 \
--node vendor/igneum-node-036 \
--win-release <the 0.3.6 Windows release folder> \
--mac-release <the 0.3.6 Mac release folder> \
--notes "Testnet identity and the adopted fee table in the node (devnet unchanged until the fee switch), signed build inputs"
The 0.3.6 binaries are NOT built yet (this plan stops at the suites; section 3b says what was and was not built).
Build them from fork 2b6d23ef as 0.3.5's section 4a did: Mac cargo build --release -j 4 -p kaspad -p igneum-miner --features kaspad/igneum-pow with CARGO_TARGET_DIR=vendor/igneum-node/target-036 (the release build in
target-036-lat is of c07093ce, one commit short: no release dev-fee address); Windows through
proto-cuda/windows-node/cross-build.sh; Linux through infra/cross/build-linux.sh. The push to master triggers
windows.yml, which now verifies the inputs of 4a before it builds the app.
5. The devnet rollout of the fee floor: a height switch
The live devnet runs the prototype fee set (B_p 30,000,000, 1 gwei floors, intrinsic 200). A 0.3.6 node on the
devnet runs exactly that until told otherwise, so 0.3.5 and 0.3.6 nodes build and accept the same segments through
the whole rolling update. The adopted set reaches the devnet by fees_v1_activation_daa, the same pattern as
difficulty_v2_activation_daa (33,000, 4 October 2026):
| Step | What | Check |
|---|---|---|
| 1 | Ship 0.3.6 (section 4). Every node updates with the switch at its default, never. The consensus digest does not move (the fee fields enter the digest only once the switch or the set leaves the 0.3.5 state), so 0.3.5 and 0.3.6 peers keep handshaking | Consensus params digest: 9409dedac4bf... on a node with no override file, the same line 0.3.5 printed; the live devnet nodes (override file with the difficulty and finality switches) print their own unchanged value |
| 2 | Wait until every devnet node is on 0.3.6: the console's Machines card and the user agents in the peer list (igneumd/2.1.0-<0.3.6 fork commit>) |
no -20139145 user agent left |
| 3 | Pick the switch height: a DAA score at least 24 hours ahead (86,400 blocks), on a round number, announced in the engineering log and the app's update note | |
| 4 | Publish the switch with the other switches in the update manifest's consensus.override (packaging/ota/publish-manifest.sh --override '{"difficulty_v2_activation_daa": 33000, ..., "fees_v1_activation_daa": N}' --deploy), and add the line to every hand-run node's override file. The digest moves the moment a node restarts with it; a node that has not restarted is refused by those that have, which is why the restart must sweep every node before N |
Calibrated v1 fees from the override file: ... from DAA score N in every node's start-up log; one digest across the peer list |
| 5 | At N: the first chain block at or above N meters with v1 (intrinsic 300, B_p 120,000, S_p 30,000, modexp 10 + 1 per 10 bytes) and its base fees jump to 100 gwei per gas and 10,000 gwei per pgas. Nothing resets; history stays |
igneum_getBudgets returns provingGasLimit 120,000 and the two base fees at the floors; eth_getBlockByNumber of the switch block shows provingBaseFeePerGas 0x9184e72a000 |
| 6 | The prover's mirror of the table (proving/igneum-prove/core/src/config.rs, pgas.rs: prototype values at b7fca5a0) must carry v1 before N, or every shard statement after N differs from the node's plan. This is the one change this plan does not make; it re-cuts every fixture at S_p 30,000 and changes the guest program id |
the fixtures and the guest id in docs/analysis/base-fee-floor.md section 4 |
Why a switch and not a fresh chain: the devnet has 12 cloud nodes, three PCs and outside machines on it, with the
difficulty v2 rollout as the precedent that a height switch over a live chain works. Why not the override file's
fees object: that changes the rules of every block including the past, so a node restarted with it could not
replay its own history.
6. Open after this plan
| Item | State |
|---|---|
--netsuffix default 1 under --testnet |
one line in kaspad/src/args.rs, not done; igneumd --testnet --netsuffix 1 until then |
| the testnet genesis message | reads proposed, not final (the proposal's words, now part of the hashed genesis 52a3e6a9...). Adopted as computed. If the owner wants the words changed, it is one print_genesis_hashes run, new hash and merkle root in genesis.rs, test_genesis_hashes and the README, and it must happen before the first public node, never after |
| the prover's table mirror | section 5 step 6 |
| seed nodes, public RPC, the explorer, the app's testnet build | docs/testnet/README.md section 5, unchanged |
| G14 history rewrite | docs/plans/history-rewrite.md, merged as a plan, not acted on |
| the inputs push (4a) and the 0.3.6 binaries | not done here |
7. What the proving activation taught us (written on master, 5 October 2026, 08:45 BST)
Written 5 October 2026, 08:45 BST, while proving v0 went live on the devnet at DAA 84,100.
Must ship in 0.3.6
| Item | Why | Where |
|---|---|---|
The app sets IGNEUM_PROOF_VERIFIER for its node |
On 5 October no node on the network ran a verifier (verifier: Off on every app node and the seed). Spec 7.7 item 4: a producer without a verifier never includes a record, so proofs were stored and never paid. The Mac app was relaunched by hand with the variable; Windows apps cannot be. |
app/igneum-app/src/engine.rs node spawn: Mac and Linux point at the shipped igneum-prove-host; Windows points at a small wrapper exe that runs the WSL host (wsl -d Ubuntu-24.04 -- /opt/igneum/igneum-prove-host --mode verify ... with wslpath for the proof file). Until the wrapper exists, devnet Windows nodes run IGNEUM_PROOF_VERIFY=trust (devnet only, never testnet). |
Windows payload ships wsl2/bin/igneum-prove-host and igneum-prove-export |
The app's probe looks there first; today a PC needs the 20-minute WSL setup or a hand-installed /opt/igneum. The Linux binaries come from infra/cross/build-linux.sh (CUDA feature needs the CUDA toolchain in the cross image, else ship the CPU build and let setup-wsl.sh build the CUDA one). |
packaging/windows/make-payload.sh, Igneum-Miner.iss |
| The proving tile shows the verifier state | A node that relays but never includes should say so on the tile and on /live. |
app/igneum-app/src/state.rs, site/api/live.mjs (verifier is already in the observer report) |
| Rotation phase 2 | Branch rotation-2 (5317305): --dl-both, tools/logs.mjs --rotation, fresh-repo script. Plan: docs/plans/rotation-phase-2.md. |
|
Testnet parameters behind fees_v1_activation_daa |
Branch testnet-prep and the fork's testnet-params (agent in progress). |
Operational lessons from the activation (5 October 2026)
- Consensus override changes must land on every node at once: a hand node restarted early with a different
proving_v0_activation_daawas refused by every peer (digest handshake) and sat isolated at a lower height for 20 minutes. Order that works: publish the manifest override,update-nowto every app, wait for every app node to log the new parameters, then restart the hand nodes and the seed with the same file. scratchpad/restart-hand-nodes.shdied silently afterigneumd --version(the 0.3.5 binary exits 1 after printing) underset -e; the restart it reported never happened. Every restart script ends by printing the new pids and their start times.- Switching proving on needs no app restart:
POST <app.url>/api/prove {"on":true}(the jobprove-on-pc2-84100does this after installing the CUDA host into/opt/igneumfor the app's WSL user).
Instant jobs (5 October 2026)
the project lead: "why is it taking so long for pc2 and pc1s tasks to spin up? can we speed it up?". Before 0.3.6 every app polled
igneum-jobs.json every 10 minutes (CHECK_EVERY_S = 600), so a job published from the Mac waited up to 10 minutes
on each PC. The PCs have no inbound ports and one miner is off the LAN, so the fix is a wake signal the app pulls
over an outbound connection. Branch job-wake.
| Piece | What it does | Where |
|---|---|---|
| Wake endpoint | GET /wake?since=<stamp>: public (the apps hold no token), 30 a minute per IP, held up to 45 s, answers {stamp, at, added, changed, held_ms} the moment the stored stamp differs from since, else the unchanged stamp at the deadline. POST /r/<token>/wake {stamp, added} (the relay's auth) records a stamp. Rows in Neon relay_wake, created by the first POST. maxDuration 60 s. |
relay/api/wake.mjs, relay/lib/wake.mjs, relay/vercel.json, test relay/test/wake.test.mjs (fake database and clock; in CI's site job) |
| App waker | One thread per app long-polls the endpoint with the last stamp; a changed stamp sends Event::Wake and the engine fetches the jobs file at once (signature check unchanged). First reply seeds the stamp. Backoff 5, 15, 60 s while the relay is unreachable, 10 s floor between requests, a full hold when the relay has no stamp yet. One log line per wake, one when it falls back, one when it recovers. IGNEUM_APP_JOBS_WAKE_URL overrides the URL (set and empty: no waker). |
app/igneum-app/src/jobrun.rs (WakeState, wake_loop), unit tests for the stamp and backoff logic |
| Fallback poll | 2 minutes (was 10), the first poll still 40 to 60 s after start. An unchanged file is no longer logged on every poll. | jobrun.rs CHECK_EVERY_S |
| Publisher | After the live file verifies, --deploy POSTs the stamp (published_at plus 8 hex of the file's sha256) and the added id; the token goes in a header file, never on the command line; prints "woke the apps" or a one-line warning. |
packaging/ota/publish-jobs.sh wake_apps |
| Status | node tools/jobs.mjs status shows "woken +N s after the publish" per machine for a job a publish added. |
tools/jobs.mjs |
Expected latency, publish to job start: the relay re-reads the stamp every 2 s inside the hold, the app's curl returns at once, the engine fetches the file (two small downloads) and starts the job on its next tick. About 3 to 6 s when the app is mid-hold, plus up to 10 s if the app was inside its floor after an earlier reply; the 2-minute poll is the ceiling when the relay is down. Numbers below are measured, not estimated.
| Machine | Publish to started_at | Date | Source |
|---|---|---|---|
| PC 1 (ae432dc7) | TODO (measure with node tools/jobs.mjs status after the first 0.3.6 job) |
||
| PC 2 (1ccfe586) | TODO | ||
| Mac | TODO |
Not yet done on this branch: the relay deploy (relay/, by the owner; the /wake route and the 60 s maxDuration
go live with it, the relay_wake table appears on the first POST), the first live publish, and the Windows curl path
of the long-poll (curl.exe 8.x in System32; the 58 s --max-time was reviewed, not run).