You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Land the impure half of dig-node#377 step 4 — the pass RUNNER — plus steps 6–8, which the parent PR names as children rather than deferrals.
The parent (#377, PR #379) landed everything that can be decided without I/O: the planner, the presence debounce, the spend builders, the scoped signer + OperatorWallet, the §25.7 switch, and mirror::pass::decide — a pure function over PassInputs. What is left is the part that touches a chain, a wallet, a clock and a socket.
Context
crates/dig-node-service/src/mirror/pass.rs — decide(&PassInputs) -> PassDecision is the whole decision. The runner's job is to GATHER PassInputs and EXECUTE PassDecision, not to re-decide anything.
crates/dig-node-service/src/mirror/signer.rs — MirrorSigner::sign(&MirrorSpends, &RecordedSpend). Do not relax that signature. A RecordedSpend is obtainable only from SpendJournal::begin, which is what makes "every unattended spend is recorded" structural rather than conventional. If the journal is awkward to construct at bring-up, make construction work.
SPEC.md §25.4 (pass order, reclaims first, fee = 0 fallback, in-flight suppression), §25.6 (DHT pointer + epoch rollover), §25.8 (the per-(store, root) state surface, still marked PENDING).
crates/dig-node-service/src/mirror/pass.rs's BondState doc records a vocabulary divergence step 6 must reconcile: §25.8 gives withheld a NARROWER meaning (Relayed provenance) and names a reclaiming state the enum has no variant for. Reconcile at the interface; do not quietly rename the enum to match.
Scope — four pieces, in this order
The runner. Start-up reconcile + round tick (dig_constants::MIRROR_ROUND_LENGTH_MS) + debounced presence deltas. Observe the Held set and dig_mirror_coin::list; call decide; execute reclaims first, then creates; audit begin → sign → broadcast → confirm; a process end with no outcome resolves to unresolved.
Step 7: dig-dht 0.12.1 → 0.15, attach unverified_mirror_coin_id at crates/dig-node-core/src/seams/dig_peer/dht.rs:423, re-announce on epoch rollover. §2.4b binds and the cascade is measured from the lock, never from the caret — dig-dht 0.13.0 took dig-nat 0.21 as a breaking bump, so check the dig-peer / dig-download / dig-peer-selector lines before assuming this is one line.
Step 8 — the §2.6 acceptance, which is what closes the parent. A person on a real machine: fund the wallet with $DIG, serve a .dig, watch the coin appear (dign spends, coin id resolvable on chain at the epoch's required amount — the schedule starts at 1.000 DIG per (store, root)), delete the .dig, watch the collateral return. Not a green suite.
Evidence
Simulator (chia-sdk-test) e2e for piece 1: a bond created for a Held capsule, the capsule removed, the coin reclaimed, the full amount back, and the audit ledger showing the whole lifecycle. Then the real-machine run for piece 4.
Task
Land the impure half of dig-node#377 step 4 — the pass RUNNER — plus steps 6–8, which the parent PR names as children rather than deferrals.
The parent (#377, PR #379) landed everything that can be decided without I/O: the planner, the presence debounce, the spend builders, the scoped signer +
OperatorWallet, the §25.7 switch, andmirror::pass::decide— a pure function overPassInputs. What is left is the part that touches a chain, a wallet, a clock and a socket.Context
crates/dig-node-service/src/mirror/pass.rs—decide(&PassInputs) -> PassDecisionis the whole decision. The runner's job is to GATHERPassInputsand EXECUTEPassDecision, not to re-decide anything.crates/dig-node-service/src/mirror/signer.rs—MirrorSigner::sign(&MirrorSpends, &RecordedSpend). Do not relax that signature. ARecordedSpendis obtainable only fromSpendJournal::begin, which is what makes "every unattended spend is recorded" structural rather than conventional. If the journal is awkward to construct at bring-up, make construction work.SPEC.md§25.4 (pass order, reclaims first,fee = 0fallback, in-flight suppression), §25.6 (DHT pointer + epoch rollover), §25.8 (the per-(store, root)state surface, still marked PENDING).crates/dig-node-service/src/mirror/pass.rs'sBondStatedoc records a vocabulary divergence step 6 must reconcile: §25.8 giveswithhelda NARROWER meaning (Relayedprovenance) and names areclaimingstate the enum has no variant for. Reconcile at the interface; do not quietly rename the enum to match.Scope — four pieces, in this order
dig_constants::MIRROR_ROUND_LENGTH_MS) + debounced presence deltas. Observe theHeldset anddig_mirror_coin::list; calldecide; execute reclaims first, then creates; auditbegin → sign → broadcast → confirm; a process end with no outcome resolves tounresolved.dig-node-control-interfaceand publish 0.25.0 before the node adopts it, then serve it and add thedignverb (the §8.6 CLI-parity drift test will demand it). Unblocks Drive the out-of-funds OS notification: the decision is built and tested but has no caller dig-app#300 and Activity tab auditing all automated spends, plus an hourly OS notification when out of DIG/XCH dig-app#289.unverified_mirror_coin_idatcrates/dig-node-core/src/seams/dig_peer/dht.rs:423, re-announce on epoch rollover. §2.4b binds and the cascade is measured from the lock, never from the caret — dig-dht 0.13.0 took dig-nat 0.21 as a breaking bump, so check the dig-peer / dig-download / dig-peer-selector lines before assuming this is one line..dig, watch the coin appear (dign spends, coin id resolvable on chain at the epoch's required amount — the schedule starts at 1.000 DIG per(store, root)), delete the.dig, watch the collateral return. Not a green suite.Evidence
Simulator (
chia-sdk-test) e2e for piece 1: a bond created for aHeldcapsule, the capsule removed, the coin reclaimed, the full amount back, and the audit ledger showing the whole lifecycle. Then the real-machine run for piece 4.Parent
#377 · epic https://github.com/DIG-Network/dig_ecosystem/issues/3166