docs(fleet): ci-red is deployed engine — advance the stamp to crew@4da17c4

Refs #189 — the post-merge, triage-owned task, now reachable: heavy-duty/crew#64
merged at 4da17c49594c2d86bd3793fa3567846cbca38e90.

#190 wrote the ci-red wake into FLEET.md deliberately marked on paper, per this
file's convention for a spec that is not yet running, and left the reconciliation
stamp at crew@01fb49c because advancing it to a SHA that did not carry the wake
would be the drift #187 exists to remove. crew#64 has merged, so both halves flip:

- The stamp advances to crew@4da17c4, and every crew permalink in the file with
  it. A stamp and its evidence links naming different trees is worse than no
  stamp: the reader diffs the wrong engine and finds no drift because the tree
  they were pointed at is the one the prose was written against.
- The four on-paper markers go: the duty-order caveat, the ci-red bullet's
  parenthetical, the Build bullet's "once ci-red deploys", and the closing
  paper inventory — which now names one remaining paper wake, the notifier's
  needs-ruling queue, not two.

The Build bullet is not a pure marker removal. crew#64's last review round
changed what it has to say: the operator ruled the round gate a whitelist, so
the wake admits a green head OR one with no checks configured, and holds a red
head AND one whose check has not finished. Copying the old "never a round at a
red head" through the flip would have shipped a fresh inaccuracy on the same
commit that claims the file is reconciled. The ci-red bullet gains the matching
sentence from the other side: an unfinished check is not a red head and wakes
nothing, because nothing has failed yet.

Verified at the stamped SHA rather than assumed: duty.sh's header carries
attention → … → resume → ci-red → build (and says it is what this file is
reconciled against), shared/README.md's duty order matches, and notify.sh's
only label filter is still state:needs-human — which is what keeps the
remaining paper claim true.

18/18 test files pass; changelog_fragment_problem OK (it caught a 387-char
entry against the 300 bound, now split); shellcheck, actionlint self-ref and
git diff --check clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dan-claude-bot 2026-07-27 21:22:07 +00:00
parent e3820dbf9a
commit 45934b54a2
2 changed files with 38 additions and 27 deletions

View file

@ -10,7 +10,7 @@
> into [heavy-duty/crew](https://github.com/heavy-duty/crew) (private to the > into [heavy-duty/crew](https://github.com/heavy-duty/crew) (private to the
> org; the fleet can read it), the *mechanism* lives there and this file only > org; the fleet can read it), the *mechanism* lives there and this file only
> points at it. Last reconciled against the merged engine at > points at it. Last reconciled against the merged engine at
> [`heavy-duty/crew@01fb49c`](https://github.com/heavy-duty/crew/tree/01fb49cd717a0f4c83df286af86411c69e3c2363), > [`heavy-duty/crew@4da17c4`](https://github.com/heavy-duty/crew/tree/4da17c49594c2d86bd3793fa3567846cbca38e90),
> 2026-07-27 — a descriptive file with no reconciliation stamp gives the next > 2026-07-27 — a descriptive file with no reconciliation stamp gives the next
> reader nothing to diff, which is exactly how the #149 drift went unnoticed. > reader nothing to diff, which is exactly how the #149 drift went unnoticed.
@ -30,7 +30,7 @@ network path — GitHub is the only queue.
This table is the **as-built** bench — five boxes, two of them dual-role. It This table is the **as-built** bench — five boxes, two of them dual-role. It
is not the same thing as crew's is not the same thing as crew's
[`fleet.roster`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/fleet.roster), [`fleet.roster`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/fleet.roster),
whose own header declares it the **target** environment: seven single-role whose own header declares it the **target** environment: seven single-role
boxes, the dual-role claude and codex boxes each split into a builder and a boxes, the dual-role claude and codex boxes each split into a builder and a
reviewer member. The delta is exactly that split (plus each new box needing reviewer member. The delta is exactly that split (plus each new box needing
@ -49,13 +49,13 @@ second repo is a second thing to keep true — this one drifted (it said cron
ran `duty.sh` directly and gave the hygiene sweep its own cron line; crew's ran `duty.sh` directly and gave the hygiene sweep its own cron line; crew's
`duty.sh` records that separate line as the bug it fixed, sharing `duty.sh` records that separate line as the bug it fixed, sharing
`~/duty/work` unlocked). How a tick actually works — cron fires `~/duty/work` unlocked). How a tick actually works — cron fires
[`bin/tick.sh`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/shared/bin/tick.sh), [`bin/tick.sh`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/shared/bin/tick.sh),
the only cron target, which wraps the only cron target, which wraps
[`bin/duty.sh`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/shared/bin/duty.sh) [`bin/duty.sh`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/shared/bin/duty.sh)
in a non-blocking `flock` with one evidence line per boundary; the boot gate in a non-blocking `flock` with one evidence line per boundary; the boot gate
and crash recovery; the session runner; backlog hygiene self-scheduling and crash recovery; the session runner; backlog hygiene self-scheduling
inside the duty tick under the same lock — lives with the code: inside the duty tick under the same lock — lives with the code:
[`shared/README.md`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/shared/README.md) [`shared/README.md`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/shared/README.md)
is the map, provenance table included. Sessions stay stateless and is the map, provenance table included. Sessions stay stateless and
disposable — all state lives on the board (issues, PRs, labels) and in git disposable — all state lives on the board (issues, PRs, labels) and in git
branches; detection is the engine's, judgment is the session's. branches; detection is the engine's, judgment is the session's.
@ -73,7 +73,7 @@ What belongs here is what a wake *means*:
write surface the whole org, which no registry could bound: the drill's write surface the whole org, which no registry could bound: the drill's
containment interlock narrowed `repos.txt` and so confined triage and containment interlock narrowed `repos.txt` and so confined triage and
hygiene, but not review, the one module that submits verdicts. hygiene, but not review, the one module that submits verdicts.
[`lib/duty-review.sh`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/shared/lib/duty-review.sh) [`lib/duty-review.sh`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/shared/lib/duty-review.sh)
states the rule and implements the WARN. states the rule and implements the WARN.
- **One wake is registry-independent, by design: attention** (next section). - **One wake is registry-independent, by design: attention** (next section).
The registry bounds what a box goes *looking for*, not what is handed to The registry bounds what a box goes *looking for*, not what is handed to
@ -100,7 +100,7 @@ stated exception. An `attention` assignment is work handed to this identity
by name, and **the assignment is what carries the authorization** — there is by name, and **the assignment is what carries the authorization** — there is
nothing here for a repo list to scope, because the box is not choosing where nothing here for a repo list to scope, because the box is not choosing where
to look. to look.
[`lib/duty-attention.sh`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/shared/lib/duty-attention.sh) [`lib/duty-attention.sh`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/shared/lib/duty-attention.sh)
queries the cross-repo endpoint on purpose and says so in its header; a fix queries the cross-repo endpoint on purpose and says so in its header; a fix
that bounds this wake to the registry would re-create the #16 incident below. that bounds this wake to the registry would re-create the #16 incident below.
(Crew's `conf/repos-default.txt` header currently claims *every* duty module (Crew's `conf/repos-default.txt` header currently claims *every* duty module
@ -131,14 +131,13 @@ wake is no longer on paper: `duty-attention.sh` is deployed engine, and
`duty.sh` runs it first on every box, whatever its roles. `duty.sh` runs it first on every box, whatever its roles.
The engine's duty order is fleet-standard The engine's duty order is fleet-standard
([`bin/duty.sh`](https://github.com/heavy-duty/crew/blob/01fb49cd717a0f4c83df286af86411c69e3c2363/shared/bin/duty.sh)): ([`bin/duty.sh`](https://github.com/heavy-duty/crew/blob/4da17c49594c2d86bd3793fa3567846cbca38e90/shared/bin/duty.sh)):
**attention → triage signals → review queue → resume → ci-red → build → **attention → triage signals → review queue → resume → ci-red → build →
handoff → rebase → worktree hygiene → backlog hygiene (hourly)** — attention handoff → rebase → worktree hygiene → backlog hygiene (hourly)** — attention
role-independent and first, then each duty family the box's roles enable. role-independent and first, then each duty family the box's roles enable.
One position in that order is **on paper**: ci-red is Every position in that order is deployed engine at the stamped SHA:
[crew#64](https://github.com/heavy-duty/crew/pull/64)'s, unmerged at the [crew#64](https://github.com/heavy-duty/crew/pull/64) merged ci-red between
stamped SHA, where `duty.sh` still runs resume straight into build — it resume and build, and `duty.sh`'s own header carries the same order.
reads as deployed engine only once that PR merges.
The earlier form of this file folded handoff and rebase into the other The earlier form of this file folded handoff and rebase into the other
builder wakes; they are duties of their own. builder wakes; they are duties of their own.
@ -167,23 +166,30 @@ builder wakes; they are duties of their own.
— a session died between first push and PR creation. A branch whose PR — a session died between first push and PR creation. A branch whose PR
already **merged** is a post-merge wait, never resumed (#172, already **merged** is a post-merge wait, never resumed (#172,
incubator#55/#64). incubator#55/#64).
- **ci-red** (builders; **on paper** — crew#64's spec, unmerged at the - **ci-red** (builders): a non-draft PR of mine whose check at the current
stamped SHA): a non-draft PR of mine whose check at the current head is head is failing. Evaluated before the build wake, so a red PR of mine
failing. Evaluated before the build wake, so a red PR of mine outranks a outranks a new claim — repairing my own red head comes ahead of new work
new claim — repairing my own red head comes ahead of new work
(ceremony#163: full-panel approvals at the head, mergeable, stranded on (ceremony#163: full-panel approvals at the head, mergeable, stranded on
a transient failure no wake covered). A round owed at a red head is a transient failure no wake covered). A round owed at a red head is
excluded from the build wake below but reported rather than silent, and excluded from the build wake below but reported rather than silent, and
an unchanged red head goes quiet after one attempt, through the an unchanged red head goes quiet after one attempt, through the
`report_suppressed` path — suppressed, still said. How a red head is `report_suppressed` path — suppressed, still said. A check that has not
detected and kept quiet is the engine's mechanism, described in crew's finished is **not** a red head and wakes nothing here: nothing has failed
yet, so there is no investigation to launch. How a red head is detected
and kept quiet is the engine's mechanism, described in crew's
`shared/README.md`, not here. `shared/README.md`, not here.
- **Build**: a `ready` **unclaimed** issue (an assignee means mid-claim, not - **Build**: a `ready` **unclaimed** issue (an assignee means mid-claim, not
pickable), or a completed review round on my PR — a changes-request with pickable), or a completed review round on my PR — a changes-request with
no panel review request still outstanding; whole rounds, never single no panel review request still outstanding; whole rounds, never single
verdicts, and — once ci-red deploys — never a round at a red head: that verdicts, and never a round the check at its head does not support. The
head has already woken ci-red above, and the excluded round is reported, wake admits a **green** head, and a head with **no checks configured**
not swallowed. terminal, not transient, so holding there would retire the round rather
than delay it. It holds a **red** head (already woken ci-red above) and a
head whose check has **not finished** (opening the round there spends the
panel on a head that may go red — crew#45's measured cost — and it admits
itself a tick later once the check settles). Both holds are reported, not
swallowed, and they are reported *differently*: only one of them is the
author's own work to do.
- **Handoff**: a round of mine that converged — every panelist's latest - **Handoff**: a round of mine that converged — every panelist's latest
opinionated review approves the current head, no panel request opinionated review approves the current head, no panel request
outstanding, mergeable right now, `state:needs-human` not already set. outstanding, mergeable right now, `state:needs-human` not already set.
@ -248,10 +254,11 @@ The duty engine is crew's shared tree, one source deployed to every box;
makes the registry rule an operator decision rather than a sweep's. Specs makes the registry rule an operator decision rather than a sweep's. Specs
written in this file have a record of becoming engine: the attention wake written in this file have a record of becoming engine: the attention wake
and the reviewers' request sweep both started here as paper (the sweep's and the reviewers' request sweep both started here as paper (the sweep's
org-wide form was then retired by the 2026-07-25 scope ruling). Two are org-wide form was then retired by the 2026-07-25 scope ruling), and the
still on paper: the notifier's `needs-ruling` queue — at the stamped crew builders' ci-red wake above is the latest: written here as paper while
SHA, `notify.sh`'s only label filter is `state:needs-human` — and the crew#64 was open, engine at the stamped SHA. One is still on paper: the
builders' ci-red wake above, engine the moment crew#64 merges. notifier's `needs-ruling` queue — at that SHA, `notify.sh`'s only label
filter is `state:needs-human`.
### Conventions on the board ### Conventions on the board

View file

@ -8,8 +8,12 @@
of your own PR is picked up before claiming another issue, is never a of your own PR is picked up before claiming another issue, is never a
parked claim, and follows crew#17's recovery path (#189). parked claim, and follows crew#17's recovery path (#189).
- `FLEET.md` writes the ci-red wake into the duty order between resume - `FLEET.md` writes the ci-red wake into the duty order between resume
and build, marked on paper until crew#64 merges, with the and build, now as deployed engine rather than on paper: the
reconciliation stamp unchanged (#189). reconciliation stamp advances to the crew SHA carrying crew#64 (#189).
- `FLEET.md` describes the build wake's check gate as the engine
implements it: a green head, or one with no checks configured, opens a
round; a red head and an unfinished one are held and reported
separately (#189).
- `BUILDER.md` re-requests by head, not by verdict: a push while - `BUILDER.md` re-requests by head, not by verdict: a push while
answering a round stales every approval, so every panelist is answering a round stales every approval, so every panelist is
re-requested; only an unchanged head re-requests the non-approvers re-requested; only an unchanged head re-requests the non-approvers