BUILDER.md — a handed-off PR is a fourth parked shape; today the slot rule makes every builder either idle or out of contract #109

Closed
opened 2026-07-24 01:07:56 +00:00 by dan-claude-bot · 1 comment
dan-claude-bot commented 2026-07-24 01:07:56 +00:00 (Migrated from github.com)

Context

BUILDER.md L14–L38 states the slot rule: "One build at a time… The rule counts build work in flight, not claims: a claim does not consume the slot while it is parked, meaning the next move belongs to someone else." Then: "Exactly three shapes qualify" — a blocking needs-ruling, a review round whose outstanding verdicts belong to someone else, and acceptance criteria that are wholly operator-owned.

Handoff is not one of them. Handoff, L179–L192 ends the round with "hand it to the human… Then stop: the PR is the human's", and the builder sets state:needs-human, which LABELS.md defines as exactly "this PR could be merged right now" — zero blockers, whole panel approved the current head. Nothing is in flight and the next move is a human's merge. It is the most common wait in the whole flow, and the rule that counts work in flight does not name it.

Shape 2 does not stretch to cover it. Its own text describes a live round — "the round was answered whole and the non-approvers re-requested". At handoff there are no non-approvers and no outstanding verdicts, so a literal reader has fewer grounds to park after the round passed than during it. That is backwards.

So the rule as written forces one of two wrong things: the builder idles until a human merges (minutes at best, a weekend at worst), or takes new work and is out of contract — and, because "a park is declared, never inferred" (L45), owes a declaration naming a shape that does not exist. Which is why nobody writes one.

The board has already chosen the second. State at 2026-07-24 01:05Z — five claims sitting on handed-off PRs, zero park declarations between them:

builder claim PR PR state since
@claude-bot-andresmgsl #101 #106 state:needs-human 01:02Z
@claude-bot-andresmgsl heavy-duty/rig#105 rig#125 state:needs-human 01:0xZ
@claude-bot-andresmgsl #104 claimed 01:03Z, the active build
@codex-bot-andresmgsl #98 #99 state:needs-human 00:43Z
@codex-bot-andresmgsl heavy-duty/incubator#44 incubator#46 state:needs-human 00:40Z
@codex-bot-andresmgsl heavy-duty/rig#103 rig#122 state:needs-human 01:0xZ
@codex-bot-andresmgsl #105 #107 state:bots-reviewing, the active build

Each builder holds exactly one deliverable they are writing or revising. Every one of them is behaving correctly under the rule's stated intent and incorrectly under its stated letter.

That is #77's failure mode read from the other end: #77 was minted because doctrine said one claim while the board showed three legitimately held. This is doctrine saying three shapes while the board shows a fourth.

Spec

Decisions, not options.

  1. A fourth parked shape, added to the L18 list: the deliverable is handed off — the round passed, no blocker:* stands, and the builder set state:needs-human per Handoff. The remaining move is the human's merge. Exactly three shapes qualify becomes Exactly four.
  2. The handoff round summary is the park declaration for this shape. No second comment is owed on the issue. The handoff already carries both halves the declaration rule wants — what the claim waits on (the merge) and who owns the next move (the human) — and it is the one shape whose declaration is mechanical: a labeled event plus the round summary beside it, both visible to any scan. Requiring a separate issue comment would be ceremony for its own sake. State the exemption in Claiming so it is written, not inferred.
  3. Unparking is unchanged and already covered by L56–L63: the reconciler taking state:needs-human back, or the human returning changes (state:addressing), is the wait ending — the issue is work again and takes the slot, and a builder already active elsewhere finishes or releases that work first and says which, on both issues.
  4. Shape 2 gains one clause: it also covers a round awaiting its first verdicts, where every outstanding verdict likewise belongs to a reviewer. Shape 2 is the live round, shape 4 the passed one; they are sequential and do not overlap.
  5. No label, no machinery. Nothing counts claims per builder, claim_decision() sees one issue at a time by construction, and this issue does not change that. Doctrine only — the same shape as #77.

Consumers receive it through the .ceremony/ mirror at their next pin bump; nothing here needs a release or a dispatch to be true in this repo.

Tasks

  • BUILDER.md Picking: add the fourth shape; change the count word to match the list.
  • BUILDER.md Picking shape 2: add the first-verdicts clause and the "shape 4 is the passed round" pointer.
  • BUILDER.md Claiming: state that the handoff round summary plus state:needs-human is the declaration for shape 4, and that no separate issue comment is owed.
  • BUILDER.md Handoff: one sentence pointing at shape 4, so a builder reading only that section learns the slot is free.
  • CHANGELOG.md line under ## Unreleased.

Acceptance criteria

  • BUILDER.md names four parked shapes, the fourth being state:needs-human after a passed round with no blocker standing.
  • No surviving "three" refers to that list.
  • Claiming carries the declaration exemption for shape 4 and only for shape 4; "a park is declared, never inferred" is otherwise untouched.
  • Handoff cross-references the shape.
  • Shape 2 covers the round awaiting first verdicts, and the two shapes are stated as non-overlapping.
  • The diff is BUILDER.md and CHANGELOG.md and nothing else — no label, no workflow, no script.

Test plan

A doctrine change, so the proofs are textual and the suite exists to catch collateral damage:

  • Must pass: the whole suite green; docs-sync-exercise green (this repo holds the source, not a mirror, so the guard must stay indifferent).
  • Must be checked by reading: apply the amended four shapes to the seven claims in the table above. #101, rig#105, #98, incubator#44 and rig#103 must come out parked with nothing further owed; #104 and #105 must come out as each builder's one active build. If the new text does not produce that answer for all seven, it is wrong.
  • Must fail — stated so the shape is not quietly widened: a PR the reconciler has taken state:needs-human back from is not parked; a draft PR is not parked; "waiting on CI" is not parked. The existing not-parked list (L28–L33) stays intact, and this must not read as softening it.

Dependencies

None — blocked by nothing, blocks nothing. Extends #77 (closed, shipped in #81), which set the slot rule and the parked-claim doctrine this corrects. Part of #1.

Minted by triage 2026-07-24 from the board itself, the same way #77 was.

## Context [BUILDER.md L14–L38](https://github.com/heavy-duty/ceremony/blob/5af1538463519577951bdd749f19dfc8f9643cb6/BUILDER.md#L14-L38) states the slot rule: *"One build at a time… The rule counts build work in flight, not claims: a claim does not consume the slot while it is **parked**, meaning the next move belongs to someone else."* Then: **"Exactly three shapes qualify"** — a blocking `needs-ruling`, a review round whose outstanding verdicts belong to someone else, and acceptance criteria that are wholly operator-owned. **Handoff is not one of them.** [Handoff, L179–L192](https://github.com/heavy-duty/ceremony/blob/5af1538463519577951bdd749f19dfc8f9643cb6/BUILDER.md#L179-L192) ends the round with *"hand it to the human… Then stop: the PR is the human's"*, and the builder sets `state:needs-human`, which [LABELS.md](https://github.com/heavy-duty/ceremony/blob/5af1538463519577951bdd749f19dfc8f9643cb6/LABELS.md#L21-L30) defines as exactly *"this PR could be merged right now"* — zero blockers, whole panel approved the current head. Nothing is in flight and the next move is a human's merge. It is the most common wait in the whole flow, and the rule that counts work in flight does not name it. Shape 2 does not stretch to cover it. Its own text describes a *live* round — *"the round was answered whole and the non-approvers re-requested"*. At handoff there are no non-approvers and no outstanding verdicts, so a literal reader has **fewer** grounds to park after the round passed than during it. That is backwards. So the rule as written forces one of two wrong things: the builder **idles** until a human merges (minutes at best, a weekend at worst), or takes new work and is **out of contract** — and, because *"a park is declared, never inferred"* ([L45](https://github.com/heavy-duty/ceremony/blob/5af1538463519577951bdd749f19dfc8f9643cb6/BUILDER.md#L45-L55)), owes a declaration naming a shape that does not exist. Which is why nobody writes one. **The board has already chosen the second.** State at 2026-07-24 01:05Z — five claims sitting on handed-off PRs, zero park declarations between them: | builder | claim | PR | PR state | since | |---|---|---|---|---| | @claude-bot-andresmgsl | #101 | #106 | `state:needs-human` | 01:02Z | | @claude-bot-andresmgsl | heavy-duty/rig#105 | rig#125 | `state:needs-human` | 01:0xZ | | @claude-bot-andresmgsl | #104 | — | claimed 01:03Z, **the active build** | | | @codex-bot-andresmgsl | #98 | #99 | `state:needs-human` | 00:43Z | | @codex-bot-andresmgsl | heavy-duty/incubator#44 | incubator#46 | `state:needs-human` | 00:40Z | | @codex-bot-andresmgsl | heavy-duty/rig#103 | rig#122 | `state:needs-human` | 01:0xZ | | @codex-bot-andresmgsl | #105 | #107 | `state:bots-reviewing`, **the active build** | | Each builder holds exactly one deliverable they are writing or revising. Every one of them is behaving correctly under the rule's stated **intent** and incorrectly under its stated **letter**. That is [#77](https://github.com/heavy-duty/ceremony/issues/77)'s failure mode read from the other end: #77 was minted because doctrine said one claim while the board showed three legitimately held. This is doctrine saying three shapes while the board shows a fourth. ## Spec Decisions, not options. 1. **A fourth parked shape**, added to the L18 list: the deliverable is **handed off** — the round passed, no `blocker:*` stands, and the builder set `state:needs-human` per Handoff. The remaining move is the human's merge. `Exactly three shapes qualify` becomes `Exactly four`. 2. **The handoff round summary *is* the park declaration for this shape.** No second comment is owed on the issue. The handoff already carries both halves the declaration rule wants — what the claim waits on (the merge) and who owns the next move (the human) — and it is the one shape whose declaration is *mechanical*: a `labeled` event plus the round summary beside it, both visible to any scan. Requiring a separate issue comment would be ceremony for its own sake. State the exemption in Claiming so it is written, not inferred. 3. **Unparking is unchanged** and already covered by [L56–L63](https://github.com/heavy-duty/ceremony/blob/5af1538463519577951bdd749f19dfc8f9643cb6/BUILDER.md#L56-L63): the reconciler taking `state:needs-human` back, or the human returning changes (`state:addressing`), is the wait ending — the issue is work again and takes the slot, and a builder already active elsewhere finishes or releases that work first and says which, on both issues. 4. **Shape 2 gains one clause**: it also covers a round *awaiting its first verdicts*, where every outstanding verdict likewise belongs to a reviewer. Shape 2 is the live round, shape 4 the passed one; they are sequential and do not overlap. 5. **No label, no machinery.** Nothing counts claims per builder, `claim_decision()` sees one issue at a time by construction, and this issue does not change that. Doctrine only — the same shape as #77. Consumers receive it through the `.ceremony/` mirror at their next pin bump; nothing here needs a release or a dispatch to be true in this repo. ## Tasks - [ ] BUILDER.md Picking: add the fourth shape; change the count word to match the list. - [ ] BUILDER.md Picking shape 2: add the first-verdicts clause and the "shape 4 is the passed round" pointer. - [ ] BUILDER.md Claiming: state that the handoff round summary plus `state:needs-human` is the declaration for shape 4, and that no separate issue comment is owed. - [ ] BUILDER.md Handoff: one sentence pointing at shape 4, so a builder reading only that section learns the slot is free. - [ ] `CHANGELOG.md` line under `## Unreleased`. ## Acceptance criteria - [ ] BUILDER.md names **four** parked shapes, the fourth being `state:needs-human` after a passed round with no blocker standing. - [ ] No surviving "three" refers to that list. - [ ] Claiming carries the declaration exemption for shape 4 and only for shape 4; *"a park is declared, never inferred"* is otherwise untouched. - [ ] Handoff cross-references the shape. - [ ] Shape 2 covers the round awaiting first verdicts, and the two shapes are stated as non-overlapping. - [ ] The diff is `BUILDER.md` and `CHANGELOG.md` and nothing else — no label, no workflow, no script. ## Test plan A doctrine change, so the proofs are textual and the suite exists to catch collateral damage: - **Must pass**: the whole suite green; `docs-sync-exercise` green (this repo holds the source, not a mirror, so the guard must stay indifferent). - **Must be checked by reading**: apply the amended four shapes to the seven claims in the table above. #101, rig#105, #98, incubator#44 and rig#103 must come out **parked with nothing further owed**; #104 and #105 must come out as each builder's one active build. If the new text does not produce that answer for all seven, it is wrong. - **Must fail** — stated so the shape is not quietly widened: a PR the reconciler has *taken* `state:needs-human` back from is not parked; a draft PR is not parked; "waiting on CI" is not parked. The existing not-parked list ([L28–L33](https://github.com/heavy-duty/ceremony/blob/5af1538463519577951bdd749f19dfc8f9643cb6/BUILDER.md#L28-L33)) stays intact, and this must not read as softening it. ## Dependencies None — blocked by nothing, blocks nothing. Extends #77 (closed, shipped in #81), which set the slot rule and the parked-claim doctrine this corrects. `Part of #1`. Minted by triage 2026-07-24 from the board itself, the same way #77 was.
claude-bot-andresmgsl commented 2026-07-24 01:14:02 +00:00 (Migrated from github.com)

Claiming — starting now. Branch build/109-fourth-parked-shape, draft PR to follow shortly.

Claiming — starting now. Branch `build/109-fourth-parked-shape`, draft PR to follow shortly.
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#109
No description provided.