Announce this lane's ceremony to a phone, not only to a GitHub issue - #49
Conversation
`projects_v2_item` reached only `.github-private`. But a card moved on org project #2 — a Status drag, a Score edit — changes the board's RANKING, and front-desk-feed queries the board itself, so nothing that wakes the private projection wakes the feed. Measured 2026-08-30: the projection updated at 22:52 and desk.bounded.tools was still serving the 21:25 snapshot, a full cron slot behind and by construction up to an hour. That was merely stale until desk gained Web Push. Desk now sends a payload-less push on a board change and the service worker fetches the board to learn what the push was about, so an unwoken feed turns a stale page into a wrong notification: it says the board changed and hands the reader a board that has not. Worse than not notifying at all. Claim-issue: #44 Co-authored-by: Claude <noreply@anthropic.com>
…loses it The push comes from the first target's lane (front-desk-projection.yml is NOTIFY_WORKFLOW_REFS[0] in desk's src/oidc.js) and the board it points at is the second target's `feed` branch. This dispatches to both at once, so the fast lane can still notify before the slow one has published. front-desk-feed's publish.yml mints a broker token, queries the whole board, signs twice and force-pushes; it is not going to win that race. Fanning out here takes the skew from up to an hour down to the length of that job, which is all a sender can do — ordering two repos' Actions lanes is not something this Worker can express. Claim-issue: #44 Co-authored-by: Claude <noreply@anthropic.com>
|
Correction to this PR's body: the count is wrong. It says the guarantee held for "nine lanes out of eleven." An audit of every workflow containing The reasoning in the body still holds and the diff is unchanged; only the arithmetic was wrong. If anything it understated the case — an unmarked exception is worse when there are seven of them. Worth recording how it was wrong, because it is the same defect the ratchet in this PR exists to prevent: I counted by reading the lanes I already knew about, rather than by asking the filesystem which lanes open ceremonies. A hand-kept count drifts silently, and this one had drifted by six. The rest of the set is closed in .github#308 and .github-private#814, with desk#64 carrying all 19 allowlist entries. Generated by Claude Code |
…issue Measured 2026-08-31: a deploy ceremony here opened, waited its full window and reached no phone. infra#552 gave the seven infra ceremony lanes a push; this repo was not in that scope, so the only announcement was the notification issue the run opens — a GitHub notification, batched and routed wherever GitHub decides, against a window that can be as short as two minutes. Two gaps, and fixing either alone changes nothing: the lane had no notice step, and desk's NOTIFY_WORKFLOW_REFS did not carry it. Both close together. approve_url was a local shell variable, as it was in every infra lane before #552 — the notice reads steps.ceremony.outputs.approve_url, so without the echo it would send an empty URL and report "skipped" forever. No guard on the notice, because the ceremony above has none: this lane has no break-glass (infra#18), so if the ceremony ran, an approval is genuinely waiting. Non-fatal on every path — the gate is the Face ID, and a notice that failed to send must not fail a deploy that is otherwise authorized. THE RATCHET IS THE POINT. A test now reads the workflow FILES and asserts every lane containing authorize/start also notifies, before the wait, with approve_url published and id-token: write reachable. Reading files rather than a list of lane names means the next ceremony lane is covered the day it is added, not the day someone remembers. Mutation-tested, and the first pass was not evidence: two of four mutations were themselves broken (one missed because the id-token line carries a trailing comment). Redone, all four now go red. One found a real weakness — renaming the wait step made the ordering check silently skip itself, so a missing marker is now a failure rather than a reason to pass. 133 tests pass. Claim-issue: bounded-systems/infra#553 Co-authored-by: Claude <noreply@anthropic.com> Claim-issue: bounded-systems/.github#305
878959e to
0f5c5fa
Compare
Measured 2026-08-31: a deploy ceremony here opened, waited its full 15-minute window, and reached no phone.
infra#552 gave the seven infra ceremony lanes a push; this repo was not in that scope, so the only announcement was the notification issue the run opens — a GitHub notification, batched and routed wherever GitHub decides, against a window that can be as short as two minutes.
Two independent gaps, so fixing either alone changes nothing: the lane had no notice step, and desk's
NOTIFY_WORKFLOW_REFSdid not carry it. The desk half is merged (desk#64).approve_urlwas a local shell variable — as it was in every infra lane before #552. The notice readssteps.ceremony.outputs.approve_url, so without the echo it would post an empty URL and report "skipped" forever.No guard on the notice, because the ceremony above it has none: this lane has no break-glass (infra#18), so if the ceremony ran, an approval is genuinely waiting. Non-fatal on every path — the gate is the Face ID, and a notice that failed to send must not fail a deploy that is otherwise authorized.
The ratchet is the point
A test reads the workflow files and asserts every lane containing
authorize/startalso notifies, before the wait, withapprove_urlpublished andid-token: writereachable. Reading files rather than a list of lane names means the next ceremony lane is covered the day it is added, not the day someone remembers this test exists.Mutation-tested, and the first pass was not evidence
Four mutations. The first run reported two "surviving" — and both survivors were my mutations being broken, not the tests being weak. The
id-token: writeline carries a trailing comment, so a replace string requiring a newline straight afterwritenever matched; that check was never exercised at all.The other miss was real: renaming the wait step made
wait === -1, and the ordering check then silently skipped itself — passing while proving nothing. That is the same shape as the scaffolding-blind checks found repeatedly in this session, this time inside a test written specifically to prevent recurrence.wait === -1is now a failure rather than a skip.All four now go red: notice removed,
approve_urldropped,id-tokenbroken, wait step renamed.133 tests pass.
Pairs with
desk#64 (merged) · .github#308 · .github-private#814 · front-desk-scheduler#193
Claim-issue: bounded-systems/.github#305
🤖 Generated with Claude Code
https://claude.ai/code/session_01EmJrUXmQBxc6Gsf3Lqvp4f