`PAYMENT_STAGE_TTL_MS = 24h` is shared across all stage kinds (`brief_access`, `classified_submission`, `signal_submission`). Per pbtc21's review on #802, the news cycle for signals is much shorter than the relevant horizon for briefs/classifieds, and the current TTL behaviour doesn't actually free anything for the agent.
Today
- After 24h, `purgeExpiredStagedRecords` marks the stage row `'expired'` (not deleted) so late settlements can still resolve.
- The `signals` row keeps `status='pending_payment'` until terminal reconcile (`failed` / `replaced` / `not_found` from the relay).
- Cooldown / daily-cap queries count `pending_payment` rows, so a stuck stage holds the agent's slot until a terminal verdict arrives — TTL alone doesn't help.
Proposal
- Per-kind TTL constant (signal_submission shorter — 1h or 2h is probably right; briefs/classifieds keep 24h).
- On TTL expiry for `signal_submission` specifically, call the discard hook (`discardSignalSubmission`) to delete the pending row, freeing the cooldown / daily-cap slot.
- Late-settlement path: if the relay confirms after the discard, the alarm sweep no-ops because the staged row is already `'discarded'`. The agent has by then re-staged or moved on.
Trade-off
Discard-on-TTL means a `signal_submission` that confirms on-chain after the TTL window will have its sBTC accepted but the signal won't be filed (the row is gone). The publisher / treasury keeps the sats, the agent has to re-file. This is acceptable because:
- Under a healthy relay, finalisation is seconds — the TTL expiry path is the slow / broken path.
- News cycle is short; a signal stuck for an hour is already largely useless.
Refs #802.
`PAYMENT_STAGE_TTL_MS = 24h` is shared across all stage kinds (`brief_access`, `classified_submission`, `signal_submission`). Per pbtc21's review on #802, the news cycle for signals is much shorter than the relevant horizon for briefs/classifieds, and the current TTL behaviour doesn't actually free anything for the agent.
Today
Proposal
Trade-off
Discard-on-TTL means a `signal_submission` that confirms on-chain after the TTL window will have its sBTC accepted but the signal won't be filed (the row is gone). The publisher / treasury keeps the sats, the agent has to re-file. This is acceptable because:
Refs #802.