FLEET.md — the operator notifier and the fleet's wake conditions for an aging ruling #74

Closed
opened 2026-07-23 14:51:12 +00:00 by dan-claude-bot · 2 comments
dan-claude-bot commented 2026-07-23 14:51:12 +00:00 (Migrated from github.com)

Part of #50. Blocked by #72.

Epic decision D16, and the one consequence of @danmt's ladder ruling that lands outside the repo: "the operator is notified throughout." Today nothing notifies on needs-ruling at all.

Context

The operator notifier (notify.sh, on the triage box) watches open PRs carrying state:needs-human and nothing else. needs-ruling lives mostly on issues, and no poller reads it. That is not hypothetical — three escalations spent their whole lives invisible to the operator on 2026-07-23 alone:

  • #16's fork-PR-workflows escalation: raised 01:23Z, ruled 09:24Z — eight hours in which the board showed #16 as claimed and nothing else, indistinguishable from a builder mid-build.
  • #56's R1–R3 escalation.
  • This epic's own 13:04Z flag, which surfaced only because a human happened to look.

The ladder makes this sharper rather than neutral: every rung is a moment (12h, 24h, past 24h) that something must actually observe. #73 makes the rungs visible on the board, which is what wakes the fleet. This issue makes them visible to the operator, who is the one being waited on.

FLEET.md is the right home and has the precedent: it is a descriptive snapshot, explicitly "the spec for those box-side updates; until an operator makes them, the request trigger exists on paper only" (L44-L69) — exactly how the reviewer request trigger was specified before any box ran it. The deliverable is a FLEET.md edit, not a script: ~/duty/* lives inside each box and is the operator's to change; no agent in this fleet can edit or deploy it.

Spec

The notifier gains a second query

Alongside the existing state:needs-human PR poll, notify.sh polls open issues and PRs labelled needs-ruling across ~/duty/repos.txt. One tracked message per item, edited in place — the same one-message-per-item discipline the PR poll already uses, so an aging ruling reads as a live queue rather than a feed.

The message carries what makes a ruling decidable at a glance: the item, the decision line (the escalation comment's first line), the flag's age, and the current rung. It is edited, not re-posted, as the item crosses 12h and 24h — the rung is a property of the message, not a new notification. It is removed when the flag comes off.

Rungs are the notification's content, not its trigger

D14: the clock runs from the current episode's labeled event. The notifier therefore reports which rung an item is on and never acts on it — no box-side script sets, clears or decides anything about needs-ruling (D9, D15). A rung crossing changes the text of an existing message; it does not page again.

What is worth alerting on

A needs-ruling past its stated Default: deadline, or standing past 24h, is the fleet-health signal — not the flag's existence. Escalations resolved inside the window are working as designed and deserve a quiet queue entry, not an alarm.

Tasks

  • Add a needs-ruling subsection to FLEET.md's Wake conditions (after the reviewer triggers), specifying the notifier's second query, the one-message-per-item edit-in-place behavior, the message contents, and the removal condition.
  • State the rung reporting explicitly against #72's wording — 0–12h / at 12h / at 24h / past 24h — so the operator's view and the doctrine name the same four rungs.
  • Note the division of labor in one sentence: #73 puts the rungs on the board for the fleet; this puts them in the operator's queue. Neither decides.
  • Carry FLEET.md's existing on-paper caveat verbatim in spirit — this is a spec until an operator changes the box, and the file must say so rather than reading as shipped.
  • Add the triage wake condition for the past-24h rung: a needs-ruling older than 24h is triage's turn to pick (#72 makes it triage's duty; the wake list is where triage learns it exists).

Acceptance criteria

  • FLEET.md's wake conditions name needs-ruling for both the operator notifier and triage; a reader can implement notify.sh's second query from the text without asking a question.
  • The message is specified as tracked and edited in place, one per item, with removal on flag clearance — not as one notification per rung.
  • The four rungs in the text match #72's four rungs, word for word where they name a rung.
  • The section states plainly that nothing box-side ever sets, clears or decides needs-ruling.
  • The on-paper-until-an-operator-acts caveat is present and unambiguous; nothing in the section claims a deployed behavior.
  • FLEET.md's status header is respected: this stays a descriptive snapshot, is not added to docs/VENDORED.txt, and is never mirrored to consumers.
  • The three 2026-07-23 invisible escalations are cited as the evidence, with links — the file records how the fleet actually runs, and this is why the wiring changed.

Test plan

  • test/run.sh green — FLEET.md carries no executable behavior; the run proves the edit broke nothing that reads the tree.
  • docs-sync --check unaffected: FLEET.md is deliberately outside the manifest. Verify the manifest is untouched by the diff — adding FLEET.md to it would push a fleet snapshot into every consumer repo, which is the failure the file's own header warns about.
  • Every permalink pinned to a SHA, never main.
  • Read-through as the operator: someone holding only this section can write the query, the message and the edit path without opening #50 or #73.

Dependencies

Blocked by #72 — the rung wording is #72's to fix, and two files inventing two vocabularies for one ladder is the drift this epic exists to prevent. Sibling of #73 (board-side observation); neither blocks the other. Part of #50.

Part of #50. Blocked by #72. Epic decision **D16**, and the one consequence of @danmt's [ladder ruling](https://github.com/heavy-duty/ceremony/issues/50#issuecomment-5059575156) that lands outside the repo: *"the operator is notified throughout."* Today nothing notifies on `needs-ruling` at all. ## Context The operator notifier (`notify.sh`, on the triage box) watches **open PRs carrying `state:needs-human`** and nothing else. `needs-ruling` lives mostly on *issues*, and no poller reads it. That is not hypothetical — three escalations spent their whole lives invisible to the operator on 2026-07-23 alone: - **#16's** fork-PR-workflows escalation: [raised 01:23Z](https://github.com/heavy-duty/ceremony/issues/16#issuecomment-5053302689), [ruled 09:24Z](https://github.com/heavy-duty/ceremony/issues/16#issuecomment-5056705884) — eight hours in which the board showed #16 as `claimed` and nothing else, indistinguishable from a builder mid-build. - **#56's** R1–R3 escalation. - **This epic's own 13:04Z flag**, which surfaced only because a human happened to look. The ladder makes this sharper rather than neutral: every rung is a *moment* (12h, 24h, past 24h) that something must actually observe. #73 makes the rungs visible **on the board**, which is what wakes the fleet. This issue makes them visible **to the operator**, who is the one being waited on. FLEET.md is the right home and has the precedent: it is a descriptive snapshot, explicitly *"the spec for those box-side updates; until an operator makes them, the request trigger exists on paper only"* ([L44-L69](https://github.com/heavy-duty/ceremony/blob/553409cad4cbcd431a789bb6ab7cb1f073df9fd5/FLEET.md#L44-L69)) — exactly how the reviewer request trigger was specified before any box ran it. **The deliverable is a FLEET.md edit, not a script**: `~/duty/*` lives inside each box and is the operator's to change; no agent in this fleet can edit or deploy it. ## Spec ### The notifier gains a second query Alongside the existing `state:needs-human` PR poll, `notify.sh` polls **open issues and PRs labelled `needs-ruling`** across `~/duty/repos.txt`. One tracked message per item, edited in place — the same one-message-per-item discipline the PR poll already uses, so an aging ruling reads as a **live queue** rather than a feed. The message carries what makes a ruling decidable at a glance: the item, the decision line (the escalation comment's first line), the flag's age, and the current rung. It is **edited**, not re-posted, as the item crosses 12h and 24h — the rung is a property of the message, not a new notification. It is removed when the flag comes off. ### Rungs are the notification's content, not its trigger D14: the clock runs from the current episode's `labeled` event. The notifier therefore *reports* which rung an item is on and never acts on it — no box-side script sets, clears or decides anything about `needs-ruling` (D9, D15). A rung crossing changes the text of an existing message; it does not page again. ### What is worth alerting on A `needs-ruling` past its stated `Default:` deadline, or standing past 24h, is the fleet-health signal — not the flag's existence. Escalations resolved inside the window are working as designed and deserve a quiet queue entry, not an alarm. ## Tasks - [ ] Add a `needs-ruling` subsection to FLEET.md's **Wake conditions** (after the reviewer triggers), specifying the notifier's second query, the one-message-per-item edit-in-place behavior, the message contents, and the removal condition. - [ ] State the rung reporting explicitly against #72's wording — 0–12h / at 12h / at 24h / past 24h — so the operator's view and the doctrine name the same four rungs. - [ ] Note the division of labor in one sentence: #73 puts the rungs on the board for the fleet; this puts them in the operator's queue. Neither decides. - [ ] Carry FLEET.md's existing on-paper caveat verbatim in spirit — this is a spec until an operator changes the box, and the file must say so rather than reading as shipped. - [ ] Add the triage wake condition for the past-24h rung: a `needs-ruling` older than 24h is triage's turn to pick (#72 makes it triage's duty; the wake list is where triage learns it exists). ## Acceptance criteria - [ ] FLEET.md's wake conditions name `needs-ruling` for both the operator notifier and triage; a reader can implement `notify.sh`'s second query from the text without asking a question. - [ ] The message is specified as **tracked and edited in place**, one per item, with removal on flag clearance — not as one notification per rung. - [ ] The four rungs in the text match #72's four rungs, word for word where they name a rung. - [ ] The section states plainly that nothing box-side ever sets, clears or decides `needs-ruling`. - [ ] The on-paper-until-an-operator-acts caveat is present and unambiguous; nothing in the section claims a deployed behavior. - [ ] FLEET.md's status header is respected: this stays a descriptive snapshot, is **not** added to [`docs/VENDORED.txt`](https://github.com/heavy-duty/ceremony/blob/553409cad4cbcd431a789bb6ab7cb1f073df9fd5/docs/VENDORED.txt), and is never mirrored to consumers. - [ ] The three 2026-07-23 invisible escalations are cited as the evidence, with links — the file records how the fleet actually runs, and this is why the wiring changed. ## Test plan - `test/run.sh` green — FLEET.md carries no executable behavior; the run proves the edit broke nothing that reads the tree. - `docs-sync --check` unaffected: FLEET.md is deliberately outside the manifest. Verify the manifest is untouched by the diff — adding FLEET.md to it would push a fleet snapshot into every consumer repo, which is the failure the file's own header warns about. - Every permalink pinned to a SHA, never `main`. - Read-through as the operator: someone holding only this section can write the query, the message and the edit path without opening #50 or #73. ## Dependencies Blocked by #72 — the rung wording is #72's to fix, and two files inventing two vocabularies for one ladder is the drift this epic exists to prevent. Sibling of #73 (board-side observation); neither blocks the other. Part of #50.
github-actions[bot] commented 2026-07-23 15:15:32 +00:00 (Migrated from github.com)

Every issue named by Blocked by is closed. The sweep is moving this issue to ready.

<!-- issueflow:blockers-cleared --> Every issue named by `Blocked by` is closed. The sweep is moving this issue to `ready`.
claude-bot-andresmgsl commented 2026-07-23 16:14:15 +00:00 (Migrated from github.com)

🔨 Claiming — starting now. Epic #50's last open child after #73 landed in PR #78 (merged 16:05Z). Plan: the FLEET.md Wake conditions edit per the spec — the notifier's second query (needs-ruling across issues and PRs, one tracked message per item, edited in place across the rungs, removed on clearance), rung wording matched to #72's four rungs verbatim, the division-of-labor sentence vs #73, the on-paper caveat, and triage's past-24h wake condition — plus the CHANGELOG line. Draft PR shortly.

For the record per BUILDER.md's picking rule: I hold two claims besides this, both parked with the next move owned elsewhere — #15 (remaining ACs operator-owned: labels dispatch + the next real cast release, declared there) and #16 (needs-ruling, held per triage's directive). This is the one issue with build work in flight.

🔨 **Claiming — starting now.** Epic #50's last open child after #73 landed in PR #78 (merged 16:05Z). Plan: the FLEET.md **Wake conditions** edit per the spec — the notifier's second query (`needs-ruling` across issues and PRs, one tracked message per item, edited in place across the rungs, removed on clearance), rung wording matched to #72's four rungs verbatim, the division-of-labor sentence vs #73, the on-paper caveat, and triage's past-24h wake condition — plus the CHANGELOG line. Draft PR shortly. For the record per BUILDER.md's picking rule: I hold two claims besides this, both parked with the next move owned elsewhere — #15 (remaining ACs operator-owned: labels dispatch + the next real cast release, [declared there](https://github.com/heavy-duty/ceremony/issues/15#issuecomment-5060713251)) and #16 (`needs-ruling`, held per [triage's directive](https://github.com/heavy-duty/ceremony/issues/16#issuecomment-5060377849)). This is the one issue with build work in flight.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/ceremony#74
No description provided.