Appendix A - 15. Cron-alerts gate
The Structure of Cron-alerts gate — its shape at a glance:
The gate reads the alert channel and the ack log; an unresolved HIGH alert refuses the dispatch tools outright, and only a terminal ack or a resolving dispatch clears it.
flowchart LR
Alerts[(Alert channel)] --> Gate{Unresolved HIGH?}
Acks[(Ack log)] --> Gate
Gate -->|yes| Refuse([Refuse dispatch tools])
Gate -->|no| Allow([Dispatch permitted])
Refuse -->|resolving dispatch acks| Allow
Accessible description: the gate reads the alert channel and the ack log; an unresolved HIGH alert refuses the dispatch tools, and dispatch is permitted only when no HIGH alert is unresolved — an alert-resolving dispatch auto-acks and clears the gate.
Projected from the catalogue entry lifecycle-and-observability / Cron-alerts gate.
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — A gate that blocks new orchestrator work-dispatch while an unresolved HIGH-severity cron alert exists, forcing the orchestrator to ack or resolve it before piling more work onto a possibly-broken substrate.
Motivation
The cron substrate (merge-train, tombstoning, retries) can break silently. If the orchestrator keeps dispatching new work on top of a broken substrate, it piles work into a system that cannot land it, compounding the mess. The failure is dispatching into a known-broken substrate, and it recurs whenever cron breaks and the orchestrator doesn't stop.
Applicability
- An alert channel (append-only) fed by the typed event bus, with a severity scale.
- An ack log with terminal states (
ACK/RESOLVE/BYPASS_AUDIT). - The dispatch tools wired to consult it; a gate nothing checks is not a gate.
- A resolution path that is itself EXEMPT, or the gate deadlocks the fix.
Structure
The Structure diagram appears at the top of this page.
Sample Code
The gate promotes an observability signal into a blocking barrier: an unresolved HIGH alert refuses the dispatch tools until a terminal ack clears it. Deadlock-freedom is designed in — the resolving path is exempt, so the gate can always be cleared.
def unresolved_high(alerts, acks) -> list[str]:
"""A HIGH alert with no terminal ack still blocks."""
terminal = {a.alert_id for a in acks if a.state in {"ACK", "RESOLVE", "BYPASS_AUDIT"}}
return [a.id for a in alerts if a.severity == "HIGH" and a.id not in terminal]
def gate_dispatch(tool: str, alerts, acks) -> int:
EXEMPT = {"resolve-alert", "ack-alert"} # the resolution path must never be blocked
blocking = unresolved_high(alerts, acks)
if blocking and tool not in EXEMPT:
print(f"REFUSED: '{tool}' blocked by unresolved HIGH alerts {blocking} — ack or resolve first")
return 1
return 0
Consequences
- A stuck/unackable alert deadlocks dispatch. Mitigated by EXEMPT tools + the resolves-alert path + a recovery playbook, but a mis-wired gate can wedge the orchestrator.
- It depends on correct severity tagging. A mis-tagged HIGH over-blocks; a mis-tagged LOW under- blocks. The gate inherits the alert producer's accuracy.
- The bypass ack is a hole.
BYPASS_AUDITclears the gate for a human (logged), which can paper over a real break. - Session-start poll is discipline. The block is mechanical once seen, but seeing it depends on the orchestrator honoring the poll.
Example use within DocAble
- The cron-alerts channel (an append-only alerts log) + acks log.
- The session-start poll discipline; the dispatch block on unresolved HIGH alerts.
- The alert-resolving dispatch (
--resolves-alert, auto-ack + dispatch fix).
Related Patterns
- Consumer — reads typed-event-bus: alerts are derived events promoted to a gate.
- Layer — a dispatch-time health gate, upstream of all new work — the health-driven analogue of brief-linting's structural dispatch gate.
- Counterpart — the acks log is the resolution record that the gate reads to decide whether a HIGH alert still blocks.