The 2026-04-22 nightly-dream-cycle learning
(.agents/learnings/2026-04-22-close-loop-citation-gate-deadlock.md) lists
three corrective actions for the chicken-and-egg promotion deadlock that
silently zeroed throughput for weeks:
1. Split admission gates by path — DONE (b69a00f)
2. Parameterize shared helpers (requireCitations bool) — DONE (b69a00f)
3. Fail loudly if ingested > 0 && promoted == 0 — this commit
Prior to this commit, scripts/nightly-dream-cycle.sh reported both numbers
in the summary but never asserted their relationship, so the deadlock
surfaced only in downstream metrics (sigma=0, escape_velocity=false) —
exactly the "quietly posting another zero-throughput status issue" pattern
the learning warns against.
Changes:
- scripts/check-dream-throughput.sh (new): standalone gate consuming
'ao flywheel close-loop --json'. Exits 1 on the deadlock pattern
(added > 0 && promoted == 0), 0 on healthy / no-op, 2 on bad input.
Uses the same pattern as the sibling check-compile-*.sh gates.
- scripts/nightly-dream-cycle.sh: invokes the gate after the summary
artifacts are written (so uploads still succeed) and exits non-zero
when a stall is detected. NIGHTLY_DREAM_STRICT=0 downgrades to warn
for diagnostic runs. The summary.json grows a
close_loop.throughput_stalled bool; the summary.md renders a banner
above the stage table when the stall fires, so the auto-filed
"Nightly dream cycle status" issue leads with it.
- tests/scripts/check-dream-throughput.bats (new): 8 cases covering
healthy, empty-run, deadlock, missing input, no-arg, non-integer
input, and missing keys.
Verified locally against all 8 cases via direct bash invocation
(bats is not available in this environment); shell syntax validated
with 'bash -n' on both scripts.