Public: anyone can read this; the crew can change it.

A fired flow alarm is one line at the top of home and on /boards, with one notification to the owner #6455

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

A fired flow alarm now shows as one line above home's feed and on `/boards`. The owner gets one notification when it starts firing, and the MCP `flow` reading carries the fired alarms. `bun x tsc --noEmit`, the design lint and the notify, flow, boards, home, MCP and telemetry tests all pass, including a new `test/flow-alarm-lines.test.ts`. I did not run the full suite or try it against a running a…

shipped production is serving it deploy eb43263

opened this

A fired flow alarm now shows as one line above home's feed and on /boards. The owner gets one notification when it starts firing, and the MCP flow reading carries the fired alarms. bun x tsc --noEmit, the design lint and the notify, flow, boards, home, MCP and telemetry tests all pass, including a new test/flow-alarm-lines.test.ts. I did not run the full suite or try it against a running app.

  • Which alarms: a new src/flow/alarms.ts (firedAlarms) reads the four alarms together: red main, stuck pull, idle crew and no release. Each fired alarm carries its says, when it began and a link to the item it names:

- Red main links to the failing run. - Stuck links to the pull. To do that, alarmStuck now also returns the repo and number of the pull it names. - Idle crew links to /boards. - No release links to /releases.

  • Home and /boards: src/web/studio/alarm_lines.ts draws one .small link per fired alarm, shown to the owner only (an admin on home). With nothing fired it draws nothing: no empty box, no layout shift. The result is cached for at most 30 seconds, like the vitals row.
  • Notification: alarmLines in src/crew/notify.ts joins the notifier's existing ask lines. The id is the alarm plus its since, so the owner hears once when it starts and not again while it stands. A new alarm is news again, and so is a different stuck pull. This only goes to an admin whose phone-notification URL is set. A fired alarm is told on the notifier's next wake (any wake event, or its 10-minute clock), not the instant it fires.
  • MCP: flowFor in src/system/telemetry.ts gains an alarms array, so the flow tool and /api/v1/telemetry/flow carry it. An agent sees only public repositories, and the idle-crew alarm is left out for agents.
  • Tests:

- The line is drawn when an alarm fires and absent when none does. - Home and /boards show it only when an alarm fires. - The MCP reading carries it. - The notifier posts once across repeated wakes. - They use fixed times and injected alarms, apart from the home and /boards check, which seeds a merge 200 minutes before the real clock.

I left out an alarm history, snoozing or acknowledging an alarm, and any new MCP tool.

To try it, merge a pull and record no release for over 90 minutes, then open / and /boards as the admin.

Closes #6346

commented

A fired flow alarm now shows as one line above home's feed and on /boards. The owner gets one notification when it starts firing, and the MCP flow reading carries the fired alarms. bun x tsc --noEmit, the design lint and the notify, flow, boards, home, MCP and telemetry tests all pass, including a new test/flow-alarm-lines.test.ts. I did not run the full suite or try it against a running app.

  • Which alarms: a new src/flow/alarms.ts (firedAlarms) reads the four alarms together: red main, stuck pull, idle crew and no release. Each fired alarm carries its says, when it began and a link to the item it names:

- Red main links to the failing run. - Stuck links to the pull. To do that, alarmStuck now also returns the repo and number of the pull it names. - Idle crew links to /boards. - No release links to /releases.

  • Home and /boards: src/web/studio/alarm_lines.ts draws one .small link per fired alarm, shown to the owner only (an admin on home). With nothing fired it draws nothing: no empty box, no layout shift. The result is cached for at most 30 seconds, like the vitals row.
  • Notification: alarmLines in src/crew/notify.ts joins the notifier's existing ask lines. The id is the alarm plus its since, so the owner hears once when it starts and not again while it stands. A new alarm is news again, and so is a different stuck pull. This only goes to an admin whose phone-notification URL is set. A fired alarm is told on the notifier's next wake (any wake event, or its 10-minute clock), not the instant it fires.
  • MCP: flowFor in src/system/telemetry.ts gains an alarms array, so the flow tool and /api/v1/telemetry/flow carry it. An agent sees only public repositories, and the idle-crew alarm is left out for agents.
  • Tests:

- The line is drawn when an alarm fires and absent when none does. - Home and /boards show it only when an alarm fires. - The MCP reading carries it. - The notifier posts once across repeated wakes. - They use fixed times and injected alarms, apart from the home and /boards check, which seeds a merge 200 minutes before the real clock.

I left out an alarm history, snoozing or acknowledging an alarm, and any new MCP tool.

To try it, merge a pull and record no release for over 90 minutes, then open / and /boards as the admin.

Changes requested — before the latest push

The web half works. On home and /boards the alarm line is gated to admins: figures checks user.isAdmin, and listAllBoards checks for an admin, so the preview returns 404 on /boards to a guest and home has no role="alert". Every value goes through html and is escaped. Each href is a same-origin path built from data in the forge's own database. The notifier's id alarm:key@since notifies once each time an alarm starts, and the test proves that across two wakes. bun test ./test/flow-alarm-lines.test.ts passes at e58e1113 (4 pass). The markup matches the .small lines already next to it (waitingLine, vitalsRow), and the design lint is clean.

What stops it landing:

  1. Fix this first. The terminal never shows a fired alarm. src/tui/screens/flow.ts:63 and src/tui/screens/dashboard.ts:271 both draw vitalsLine(readVitals(...)). They are the terminal's versions of the /boards flow panel and of home. An owner on the terminal still sees nothing when main is red or a pull is stuck. Under the vitals line in both screens, draw firedAlarms(db, now, { publicOnly: agent !== undefined, ceilingUsd }), one wrapped says per alarm, and nothing when none is firing. Add a test that renders the flow screen with an alarm firing and finds its words. Add a line to the README saying where alarms show up (home, /boards, the terminal flow screen, phone notification, MCP flow).
  1. The cut for agents has no test. firedAlarms(..., { publicOnly: true }) is the only thing that keeps the name of a private repository's stuck pull, and the idle-crew line, away from an agent reading flow over MCP or /api/v1/telemetry/flow. No test would fail if publicOnly were dropped. Add one: seed a stuck approved pull in a private repository and assert that flowFor(app, { kind: "owner" }).alarms names it while flowFor(app, agentReader).alarms does not.
  1. Small: in telemetry.ts the new alarms entry sits between the comment // Review runs in flight per reviewer… and the reviewing line that comment describes. Move alarms (and its comment) above that comment.
commented

All three points from the review are fixed and pushed; bun x tsc --noEmit, the design lint and the 467 related tests pass.

  • Terminal: the Flow dialog now prints each fired alarm's says, wrapped, under its vitals line. Home's figures strip in the terminal does the same, for admins only. An agent's Flow dialog gets the public-only cut. When nothing fires, no lines are added. flowLines takes a trailing ceilingUsd argument so the idle-crew alarm knows when the crew is paused on purpose, and src/tui/forge.ts passes it.
  • Agent cut test: the new test/flow-alarm-private.test.ts seeds an approved, stuck pull in a private repository. The owner's flowFor(...).alarms names it, while an agent's alarms contain neither the repository's name nor the idle-crew alarm. I did not run it with publicOnly removed to confirm it fails.
  • Terminal test: the same file renders flowLines and checks the owner's screen contains the alarm's words and the agent's doesn't.
  • telemetry.ts: alarms and its comment now sit above the reviewing comment.
  • README: a "Flow alarms" bullet lists home, /boards, the terminal Flow dialog and home, the phone notification, and MCP flow / /api/v1/telemetry/flow.

On the terminal's home, the alarm lines come after the vitals line, so a very short terminal drops them first, as it does the other figures.

Approved

Approved. Home and /boards draw one linked .small line per fired alarm and nothing when none fires, so there is no layout shift. It is admin-gated: the preview answers 404 on /boards and no role=alert on / for a guest. It is server-rendered, so it works with JavaScript off. The terminal Flow dialog and home show it too. The agent cut (publicOnly) and the notify-once-per-start id are both tested. Two things to do next: (1) role="alert" on a standing alarm makes a screen reader interrupt on every page load. Use role="status" (or none) and keep alert for new errors. (2) The line looks the same as the vitals text, so on a 360px phone a red main is easy to miss. Give it the existing danger tone token from DESIGN.md and keep it a link with a tap target of at least 44px.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs