Detached from #398 as the one arm of that issue that is not gated on the nullisLabs fork deployment.
Verdict::Post carries next_poll_timestamp as a u64, using 0 as a sentinel for "no next poll". Model it as Option<u64> so the absent case is typed rather than a magic value that a caller can arithmetic on by accident.
Scope
crates/composable-cow/src/sweep.rs: the Verdict::Post construction and every read of next_poll_timestamp. Follows #538 in this file, so it lands in the same wave while the file is open under its current name, before #540 renames it.
Why now
The rest of #398, the ComposableCoW poll wire swap and the LegacyRevertAdapter deletion, cannot proceed until the fork is deployed somewhere, so #398 stays in M4 labelled blocked. This sliver has no such gate and is cheap, so it rides with the #538 pass rather than waiting on the fork.
Acceptance criteria
next_poll_timestamp is Option<u64>, None replaces the 0 sentinel, and no caller compares against or computes on 0 to mean absent.
Detached from #398 as the one arm of that issue that is not gated on the nullisLabs fork deployment.
Verdict::Postcarriesnext_poll_timestampas au64, using0as a sentinel for "no next poll". Model it asOption<u64>so the absent case is typed rather than a magic value that a caller can arithmetic on by accident.Scope
crates/composable-cow/src/sweep.rs: theVerdict::Postconstruction and every read ofnext_poll_timestamp. Follows #538 in this file, so it lands in the same wave while the file is open under its current name, before #540 renames it.Why now
The rest of #398, the ComposableCoW poll wire swap and the
LegacyRevertAdapterdeletion, cannot proceed until the fork is deployed somewhere, so #398 stays in M4 labelled blocked. This sliver has no such gate and is cheap, so it rides with the #538 pass rather than waiting on the fork.Acceptance criteria
next_poll_timestampisOption<u64>,Nonereplaces the0sentinel, and no caller compares against or computes on0to mean absent.