What to build
Optional follow-up to #19, deliberately kept out of that epic — schedules and the Ready sweep port ship without it.
The retired dispatcher backed off after failures: a failing issue waited before being retried, doubling per consecutive failure up to a 24h cap, derived from the persisted run history rather than a separate retry-state file that could drift. That behaviour was welded to one specific input field. Its natural generalization is the dedupe key from #15 — history joins on the key, so any wrapper that dispatches with a stable key gets backoff without doing anything.
Backoff stays in the runtime rather than moving into workflow bodies. A wrapper would otherwise need to read past run history, which the workflow context has no affordance for, and every wrapper would end up reimplementing the same window arithmetic.
Keep it minimal: the existing base/cap/doubling behaviour, keyed differently. Not a scheduling policy engine.
Acceptance criteria
Blocked by
What to build
Optional follow-up to #19, deliberately kept out of that epic — schedules and the Ready sweep port ship without it.
The retired dispatcher backed off after failures: a failing issue waited before being retried, doubling per consecutive failure up to a 24h cap, derived from the persisted run history rather than a separate retry-state file that could drift. That behaviour was welded to one specific input field. Its natural generalization is the dedupe key from #15 — history joins on the key, so any wrapper that dispatches with a stable key gets backoff without doing anything.
Backoff stays in the runtime rather than moving into workflow bodies. A wrapper would otherwise need to read past run history, which the workflow context has no affordance for, and every wrapper would end up reimplementing the same window arithmetic.
Keep it minimal: the existing base/cap/doubling behaviour, keyed differently. Not a scheduling policy engine.
Acceptance criteria
Blocked by