Summary
dexdo status's next field for an opened, unaccepted-probe deal prints:
next=seller_advance_probe_after_timeout command="keep dexdo seller running for {deal}; it calls TokenContract.advance() after PROBE_WINDOW" reason=buyer_silent_probe
This strongly implies pure timeout-based silence-equals-consent, which matches what TokenContract.advance() actually allows on-chain (TokenContract.sol: require(block.timestamp >= _prepaidTime + advanceWindow, ...) — no delivery check at all, by design, per the contract's own doc comment: "After SETTLE_WINDOW of buyer silence... accept the probe").
The CLI's actual driver (crates/dexdo/src/seller/advance.rs::drive_advance) does not do this. It gates on real delivered tokens first:
tokio::time::sleep(windows.probe).await;
loop {
if billed_ticks(delivered.load(Ordering::Acquire), tick_size) >= 1 {
break; // requires >=1 REAL delivered token
}
if delivery_done.load(Ordering::Acquire) || deal_closed(chain, token_contract).await {
return Ok(0);
}
tokio::time::sleep(windows.settle).await; // otherwise loops forever, silently
}
chain.accept_probe(token_contract).await?;
If the buyer never sends a single real inference request through the gateway (for any reason — their own bug, they gave up, they're just testing), this loop sleeps indefinitely with zero log output, making a perfectly healthy, correctly-running seller process indistinguishable from a hung/broken one from the outside. last_advance_unix in dexdo status --json never advances, across any number of seller restarts, for as long as the buyer stays silent.
There is no exposed dexdo subcommand to call advance() directly, bypassing this gate — checked dexdo --help in full, only dexdo seller's embedded daemon logic can trigger it. So the seller has no way to ever force settlement on a deal the buyer opened, funded, and then abandoned, even though the underlying contract explicitly supports exactly that scenario (silence-after-timeout = consent).
This is very likely a deliberate anti-abuse safeguard (protecting the buyer from being charged for content never actually delivered) rather than a pure bug — but the mismatch between it and the CLI's own status message cost significant debugging time to trace to source, since every symptom (healthy process, reachable gateway, zero log output, frozen last_advance_unix) looks identical to a genuinely hung/crashed process.
Environment
- dexdo 0.0.12 (SHA256-verified) and 0.0.14 (fresh download, checksum-verified)
- Network: Shellnet, post the 2026-07-17 restart
- OS: Windows 11
Repro
- Open/fund any deal as seller (real buyer match,
opened=true).
- Don't send a real request through the gateway as that buyer.
- Wait well past
PROBE_WINDOW (180s) — even hours.
dexdo status --json shows last_advance_unix frozen at the funding time indefinitely, probe_accepted=false, with next.action=seller_advance_probe_after_timeout still printed as if it will resolve on its own.
- Restarting the seller process does not change this — it resumes cleanly (
readiness=resumed_funded_tc) but the advance loop restarts in the same blocked state.
Ask
- Is the delivery-gate intentional (anti-abuse) or an oversight?
- If intentional, could
dexdo status's next message be corrected to not imply pure timeout-based resolution, and/or could the seller log something (even at DEBUG) while waiting in this loop, so it's distinguishable from a genuinely hung process?
- Is there any seller-side recourse at all for a deal the buyer opened/funded and then never sent traffic to?
Summary
dexdo status'snextfield for an opened, unaccepted-probe deal prints:This strongly implies pure timeout-based silence-equals-consent, which matches what
TokenContract.advance()actually allows on-chain (TokenContract.sol:require(block.timestamp >= _prepaidTime + advanceWindow, ...)— no delivery check at all, by design, per the contract's own doc comment: "After SETTLE_WINDOW of buyer silence... accept the probe").The CLI's actual driver (
crates/dexdo/src/seller/advance.rs::drive_advance) does not do this. It gates on real delivered tokens first:If the buyer never sends a single real inference request through the gateway (for any reason — their own bug, they gave up, they're just testing), this loop sleeps indefinitely with zero log output, making a perfectly healthy, correctly-running seller process indistinguishable from a hung/broken one from the outside.
last_advance_unixindexdo status --jsonnever advances, across any number of seller restarts, for as long as the buyer stays silent.There is no exposed
dexdosubcommand to calladvance()directly, bypassing this gate — checkeddexdo --helpin full, onlydexdo seller's embedded daemon logic can trigger it. So the seller has no way to ever force settlement on a deal the buyer opened, funded, and then abandoned, even though the underlying contract explicitly supports exactly that scenario (silence-after-timeout = consent).This is very likely a deliberate anti-abuse safeguard (protecting the buyer from being charged for content never actually delivered) rather than a pure bug — but the mismatch between it and the CLI's own status message cost significant debugging time to trace to source, since every symptom (healthy process, reachable gateway, zero log output, frozen
last_advance_unix) looks identical to a genuinely hung/crashed process.Environment
Repro
opened=true).PROBE_WINDOW(180s) — even hours.dexdo status --jsonshowslast_advance_unixfrozen at the funding time indefinitely,probe_accepted=false, withnext.action=seller_advance_probe_after_timeoutstill printed as if it will resolve on its own.readiness=resumed_funded_tc) but the advance loop restarts in the same blocked state.Ask
dexdo status'snextmessage be corrected to not imply pure timeout-based resolution, and/or could the seller log something (even at DEBUG) while waiting in this loop, so it's distinguishable from a genuinely hung process?