fix: isolate scheduled wake dispatches - #349
Conversation
Overlap suppression was audit-invisible: tick() advanced and persisted next-fire for a suppressed entry and logged "overlap-suppressed", but wrote nothing to InvocationState. Three due slots with one execution left state byte-identical to a schedule that only had one slot due, so clawdash and `claw api schedule` rendered a coalescing schedule as perfectly healthy. That misses requirement 5 of #347 (state must stay auditable for each fire slot), and it starts to bite once a runner wake budget can exceed the schedule cadence. - add cumulative `suppressed_slots` + `last_suppressed_at` to InvocationState, persisted in the same state write that advances next-fire so a completing wake cannot erase the record - include the dropped slot timestamp in the scheduler log line - note coalesced slots on the clawdash schedule card - drop Run()'s unreachable `case <-s.stopCtx.Done()` select arm; stopCancel() is only reached from Run()'s own ctx.Done branch, which returns immediately after. stopCtx itself stays, since FireNow uses it to cancel in-flight manual fires at shutdown. go test ./... , go vet ./... , go test -race -count=20 ./cmd/claw-api, and git diff --check all pass.
|
Pushed two scoped corrections to this branch (2c8ec25) after independent adversarial review. Full review notes are in the talking-stick room; summary here. No correctness bug found. Verified independently rather than trusting CI: Correction 1 — coalesced slots were audit-invisible (requirement 5 of #347).
The suppression itself is correct and intended — the gap was that it left no operator-visible trace. Fix keeps the existing model rather than inventing a new one:
This matters specifically because #346 gives Hermes a 2-minute budget, which exceeds many cron cadences and makes coalescing an ordinary occurrence rather than an edge case. Correction 2 — dead select arm. Withdrawn finding, recorded for honesty. I first measured "6 due slots produce 1 dispatch" and was going to report it as a regression. It is not one. Master's Verification on the updated branch: |
Summary
Boundary
This stays entirely in claw-api scheduler transport/state. It adds no runner prompt behavior, downstream wrapper, or cllama feature. PR #346 remains draft and should depend on this fairness correction before extending a Hermes wake budget.
Verification
git diff --checkDOCKER_HOST=unix:///tmp/clawdapus-no-docker.sock go test -count=1 ./...DOCKER_HOST=unix:///tmp/clawdapus-no-docker.sock go vet ./...go test -race -count=20 ./cmd/claw-apiCloses #347