The slot scheduler runs a substitute pool. When a primary slot expires, the pool promotes the next available candidate and tries again. The audit trail from the 2026-06-14 verification run, checking that the new slot state machine was working correctly, shows the full sequence: id=51 promoted to id=53, id=53 to id=54, id=54 to id=55 (rejected), id=55 to id=58, then breach. Start to finish: three seconds. Each transition carries a reason. The breach at the end is complete information, not a log line requiring reconstruction.
Before the slot state machine shipped, the same cascade produced none of that.
That is the context for 20% autonomous success across five consecutive scheduled slots in 72 hours.
The shape of the failure
Five slots. One published, with human intervention before the alarm TTL. That counts as a success in the outcome log because the article landed, but it is not autonomous success. Four expirations.
Queue id=35 cancelled at 08:00 UTC on 2026-06-13. That was the third cancellation in 72 hours, after queue ids 36, 39, and 50 had missed the day before. Across all four expirations, the upstream failure mode was the same shape that B-016 had addressed earlier in the week. Four failures with the same shape is not a run of bad luck. It is either a gap in B-016’s coverage or a separate mechanism regenerating the same condition.
The 20% figure settled the question of whether to investigate or wait. Below 50% the system is not recovering, and below 30% is manual operation by another name. No reason to wait for a better sample.
What the substitute pool was doing
The substitute pool was present and firing. The problem was what it was consuming.
Queue id=37’s slot came up on 2026-06-13. schedule_sweep fired the publisher at 11:00:08Z. The publisher cancelled the row (note: publisher_cancelled_row), and the pool pulled the next available candidate. That candidate came from the 12:00 BST window. The pool had covered the 09:00 BST slot by consuming a future-scheduled row.
When 12:00 arrived, the pool had nothing to offer. The missed-slot alarm fired twice that morning: once for 09:00, once for 12:00. Both alarms were accurate. One primary failure had produced two cascade events.
The pool was not malfunctioning. It was doing exactly what it had been told: grab the next available row. The definition of “available” was the gap. Rows already committed to a future window were available by that definition, because nothing distinguished them from unscheduled work sitting in the queue.
Three fixes, three paths
SLA recovery shipped 2026-06-13 as three mechanisms, each closing a distinct failure path.
Sibling cancel. When a slot expires, sibling rows (same topic, same publication window) are cancelled immediately. Previously they stayed active and were available as substitute candidates. A sibling sharing the same upstream failure mode will produce the same breach if promoted. Cancelling on expiry removes that path before the pool tries it.
Slot fallback. The substitute pool now draws from adjacent unscheduled rows before reaching into future-committed windows. If nothing adjacent exists, future-scheduled rows remain available as a last resort. The pool can still exhaust, but it no longer depletes tomorrow’s supply as a first move. The follow-on fix the same afternoon corrected how the pool recurses when it does reach into future-scheduled rows, so the recursion terminates naturally rather than continuing past the last viable candidate.
Missed-slot alarm. The alarm was already firing, but as a post-hoc sweep without enough context for a decision. The rewrite moved it into the dispatcher. Each alarm payload now carries the queue id, the slot time, and the upstream cancellation reason. A human reading the alarm knows which slot expired and why, inside the TTL window. Not a log line to investigate; a notification to respond to.
Out of scope: automatic retry with backoff. Different failure mode, different risk surface. Named and closed.
The slot state machine
The three fixes addressed the mechanics of recovery. The slot state machine (B-020) addressed the visibility underneath it.
Before B-020, a slot existed only as a convention. When the pool promoted id=51 to id=53, no record linked them. When id=55 was rejected, the rejection was a queue-row event, not a transition in a named state machine. If someone asked how many candidates the pool had tried before the breach, the answer required querying queue-row events, filtering by timestamp, and inferring the connection. That inference is fallible.
B-020 made the slot a first-class entity with four explicit states: active, substituting, exhausted, breach. Each transition carries a reason. The lineage of substitutions lives on the slot record, not scattered across queue rows. When the verification run traced id=51 through five promotions and into breach, the entire chain was one self-describing record. The rejection of id=55 had a reason attached at the moment it was rejected, not inferred from a timestamp match.
The slot entity also provided a stable anchor for the G-L3 alias-map fix. The over-aggregation (matching platform tags against topic keys during deduplication) had blocked queue id=36 and made two other articles blockable-on-arrival on 2026-06-13. Topic-key derivation now ignores platform-tag matches at derivation time rather than filtering afterwards. That fix needed somewhere to attach its logic without adding another pass over queue rows. The slot gave it that.
What the numbers will say next week
SLA recovery is live. The slot state machine shipped the day after. There are enough scheduled slots in the next seven days to produce a meaningful sample.
The testable claim: autonomous success above 80%. Four out of five slots resolving without human input. Below that, the slot fallback ordering or the sibling-cancel scope is still wrong.
The slot state machine means that if the number is still 20%, the audit trail will show exactly which part of the recovery is not holding. That is different from the last 72 hours, where the audit trail showed only that the system had failed.
That is the output of making a slot a thing.



