Surfaced by the anvil-fork harness in #691, and it is an unfinished item from #682 rather than a new discovery.
The gap in #682
#682 listed in scope: "Decide the retry_action fallback for non-Denied faults, which bypasses the table and drops."
#688 closed #682 without addressing it. The classification table and classify_denied are in crates/cow-venue, but retry_action is in videre-sdk, a different repo, so it was out of the diff and the item was missed.
It still reads:
VenueFault::UnknownVenue
| VenueFault::InvalidBody(_)
| VenueFault::Unsupported
| VenueFault::Denied(_)
| VenueFault::InvalidReceipt
| VenueFault::ReceiptMismatch => RetryAction::Drop,
Why it matters
The fork run reaches Post, submits, and the venue returns a receipt that does not match the order it sent. retry_action maps that to Drop, and the commitment is removed permanently:
poll commitment:0xf39f...:0x8a86... -> Post
submit dropped commitment commitment:0xf39f...:0x8a86... permanently: receipt mismatch
The order was valid, the generator posted it, and the conditional order is intact on chain. The commitment is gone anyway, and only a re-registration brings it back.
By #688's own rule this is wrong
#688 established the line: a commitment mints a fresh order from the same handler, salt and static input on every poll, so only inputs fixed at registration justify removing it.
A receipt mismatch is a fact about the venue's response, not about the registration. An orderbook bug, a truncated response or a deployment mid-rollout would delete every commitment that submits during the window. InvalidReceipt is the same class.
Denied(_) also appears in this arm, though it is unreachable in the CoW path because run.rs routes a denial to classify_denied first. It should not be left as a drop for a venue that does not.
Note on the trigger
The mismatch in the fork run comes from orderbook-mock answering with a synthetic uid rather than one derived from the order, so the venue check is behaving correctly there.
That is a mock limitation, but it is exactly the shape a real venue defect would take, which is why it is worth classifying deliberately rather than dropping.
Scope
- Reclassify the receipt faults in
videre_sdk::keeper::retry_action: a venue-shaped fault should back off, not remove.
- Decide
UnknownVenue, InvalidBody and Unsupported in the same pass; InvalidBody is arguably registration-fixed and may keep its drop.
- Cross-repo, so it carries a videre pin bump into shepherd.
Done when
AI Assistance: Claude Code used for the analysis.
Surfaced by the anvil-fork harness in #691, and it is an unfinished item from #682 rather than a new discovery.
The gap in #682
#682 listed in scope: "Decide the
retry_actionfallback for non-Deniedfaults, which bypasses the table and drops."#688 closed #682 without addressing it. The classification table and
classify_deniedare incrates/cow-venue, butretry_actionis invidere-sdk, a different repo, so it was out of the diff and the item was missed.It still reads:
Why it matters
The fork run reaches
Post, submits, and the venue returns a receipt that does not match the order it sent.retry_actionmaps that toDrop, and the commitment is removed permanently:The order was valid, the generator posted it, and the conditional order is intact on chain. The commitment is gone anyway, and only a re-registration brings it back.
By #688's own rule this is wrong
#688 established the line: a commitment mints a fresh order from the same handler, salt and static input on every poll, so only inputs fixed at registration justify removing it.
A receipt mismatch is a fact about the venue's response, not about the registration. An orderbook bug, a truncated response or a deployment mid-rollout would delete every commitment that submits during the window.
InvalidReceiptis the same class.Denied(_)also appears in this arm, though it is unreachable in the CoW path becauserun.rsroutes a denial toclassify_deniedfirst. It should not be left as a drop for a venue that does not.Note on the trigger
The mismatch in the fork run comes from
orderbook-mockanswering with a synthetic uid rather than one derived from the order, so the venue check is behaving correctly there.That is a mock limitation, but it is exactly the shape a real venue defect would take, which is why it is worth classifying deliberately rather than dropping.
Scope
videre_sdk::keeper::retry_action: a venue-shaped fault should back off, not remove.UnknownVenue,InvalidBodyandUnsupportedin the same pass;InvalidBodyis arguably registration-fixed and may keep its drop.Done when
AI Assistance: Claude Code used for the analysis.