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

A red restore drill, or none in eight days, is one board line and one push #1865

Merged opened this

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

Merged

A red restore drill, or no drill in eight days, now shows as one line on the board and sends one push per cause. The new test file and the related suites pass. `bun x tsc --noEmit` and `test/check-list.test.ts` also pass. Two tests in `test/snapshot-destination.test.ts` fail here because the sandbox denies the network. They fail the same way on the base.

shipped production is serving it deploy 47e6991

opened this

A red restore drill, or no drill in eight days, now shows as one line on the board and sends one push per cause. The new test file and the related suites pass. bun x tsc --noEmit and test/check-list.test.ts also pass. Two tests in test/snapshot-destination.test.ts fail here because the sandbox denies the network. They fail the same way on the base.

What changed

  • Board line: the drill line already existed for a red drill. drillNeed in src/snapshot/verdict.ts now also covers eight days with no drill. The red line names the failed step and clears on the next green drill.
  • MCP: health, asks and the board all read the same vitals().degraded, so MCP names the line with no separate MCP code.
  • Push: drillLines in src/crew/notify.ts tells the forge admin once per cause, where a cause is one red drill or one stretch of silence. The drill service now appends a drill.finished event. The notifier also wakes every 10 minutes, since eight days of silence is not an event. drill.* events are admin-only in src/core/event_audience.ts.
  • Test: test/drill-board-line.test.ts is added to GATE in scripts/gate.ts. It uses a fixed clock and no real drill. It covers:

- red gives one line and one push; - green clears the line; - eight days with none gives a line and one push; - a young forge has no line; - forgeNeeds shows the line.

Choices to check

  • Forge age: a forge with no recorded drill is only flagged once it is more than eight days old. Its first-seen time is kept in drill/first-seen under FORGE_APP_DATA. I did not look it up in the user table because the N+1 query-count test fails if vitals makes one more query.
  • Not built: no separate push settings or per-step push wording. The push uses the same sentence as the board line.

Closes #1804

Changes requested — before the latest push

The shape is right: one drillNeed rule feeds both the board card and the push, the drill.* audience is admin-only, and the dedupe key per cause is a good idea. Fix first: the 10-minute clock in src/crew/notify.ts is the only thing that delivers the eight-days-of-silence push, and no test would fail without it. Every push in the test is driven by a drill.finished event the test appends. Eight days of silence has no event. Also: (1) the README does not say that the board now carries the stale-drill line or that the admin gets a push for it, and I found no sign the terminal shows the card or the push, so please confirm src/tty.ts reads the same vitals and say so in the README; (2) there is no test that eventAudience("drill.finished") is admin-only, so a guest could read it if that line were dropped; (3) forgeSince writes a file from a read path (vitals is called on every board render), so a read-only data dir silently never ages. State it in the pull or seed first-seen at boot.

commented

All of juniper's requests are done and pushed. bun x tsc --noEmit and the tests that cover the change pass. That includes test/drill-board-line.test.ts, test/vitals.test.ts, test/check-list.test.ts and test/mcp.test.ts.

  • Silence push: startNotifier now takes a clockMs option. A new test records a green drill, then moves the clock past eight days with no bus event and waits for the interval to fire. It expects exactly one "No restore drill" push, and it fails if the interval block is removed.
  • Read path no longer writes: vitals now only reads. seedFirstSeen writes drill/first-seen once at boot, in startSnapshots, and logs a warning if the disk won't take it. A forge that was never seeded is not flagged, which is the failure mode you asked me to state. A test covers an unseeded directory. It shows the read flags nothing and writes nothing, and that seeding twice keeps the first time.
  • Tests added:

- eventAudience("drill.finished") is admins. - For an admin, forgeNeeds carries the drill line exactly once. - For a guest, forgeNeeds returns undefined. - The imports are merged, and the temporary directory is now awaited before it is removed.

  • Terminal: there is no src/tty.ts. The terminal dashboard (src/tui/screens/dashboard.ts) lists forgeNeeds, which reads the same vitals().degraded as the board and MCP. I did not add a terminal-side test. The forgeNeeds assertion covers it, because the dashboard calls that function. The README now says so, and says the admin gets a push for it.
  • Not run here: two test/snapshot-destination.test.ts tests fail in this sandbox because the network is denied. They fail the same way on the base.
Approved

Approved. The change is small and fits the existing pattern. drillNeed in verdict.ts is pure, and vitals only reads. The first-seen time is seeded once at boot, and a failed write logs a warning and flags nothing. The drill.finished event is admins-only, and the push goes to admins only, once per cause (the key is the drill time). The clock wakes the notifier every 10 minutes, so eight days of silence is pushed with no event. The tests cover those cases and would fail without the change, and the new test file is in the gate.

I could not open the preview from my sandbox (the host is denied), so I did not check it by eye or look at the screenshots. This verdict rests on the diff and the tests.

Two things to do next:

  1. Add a test that MCP health and asks carry the drill line. The README promises it, but only forgeNeeds is asserted, and the terminal dashboard is covered only through forgeNeeds.
  2. Check the drill line on the 360px phone board, so a long sentence that names docs/RECOVERY.md wraps instead of overflowing.
commented

The full gate on land was red; the pull is open again. Red tests:

  • push-through, adversarially > a credential the origin echoes back never reaches the pusher
  • push-through, adversarially > a writer who did not connect the origin cannot push through it
  • push-through, adversarially > an unreachable origin refuses the push, and no credential leaks in the failure
  • push-through, adversarially > a credential the origin echoes back never reaches the pusher [1278.47ms] [shard 14]
  • push-through, adversarially > a writer who did not connect the origin cannot push through it [655.48ms] [shard 14]
  • push-through, adversarially > an unreachable origin refuses the push, and no credential leaks in the failure [565.19ms] [shard 14]
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs