Public: anyone can read this; the crew can change it.
A release tick not heard from for 60 minutes fires one release_quiet flow alarm #11890
Reviewed pull #11898 at its head: ticked New src/flow/alarm_release_quiet.ts, shaped like src/flow/alarm_silent.ts: reads lastBeat(db) from src/keeper/beat.ts and now (passed in). No beat for 60 minutes fires one alarm. On a forge that has released before, never having had a beat fires it too. Its words say when the tick was last heard and its reason, using agoWords. A fresh beat clears it.; It joins firedAlarms in src/flow/alarms.ts, so home, the notifier and the MCP flow tool carry it with no new tool.; New test test/alarm-release-quiet.test.ts: 59 min quiet gives nothing; 61 min gives one alarm naming the time and reason; a new beat clears it. Each case fails without the module.; bun x tsc --noEmit and the touched tests pass..
Intent: production falling behind main is said when the release tick itself goes quiet (v1 list item 2, #11507; replaces #11675's alarm half).
Done looks like:
src/flow/alarm_release_quiet.ts, shaped likesrc/flow/alarm_silent.ts: readslastBeat(db)fromsrc/keeper/beat.tsandnow(passed in). No beat for 60 minutes fires one alarm. On a forge that has released before, never having had a beat fires it too. Its words say when the tick was last heard and its reason, usingagoWords. A fresh beat clears it.firedAlarmsinsrc/flow/alarms.ts, so home, the notifier and the MCPflowtool carry it with no new tool.test/alarm-release-quiet.test.ts: 59 min quiet gives nothing; 61 min gives one alarm naming the time and reason; a new beat clears it. Each case fails without the module.bun x tsc --noEmitand the touched tests pass.Files: src/flow/alarm_release_quiet.ts (new), src/flow/alarms.ts, test/alarm-release-quiet.test.ts (new). Risks: one bounded query only; no change to src/keeper/beat.ts beyond what it already exports.