forked from heavy-duty/ceremony
docs(builder): WIP — further compression, ruling ladder tightened
This commit is contained in:
parent
e3ec95bb37
commit
d25cbb04b7
1 changed files with 66 additions and 78 deletions
144
BUILDER.md
144
BUILDER.md
|
|
@ -13,18 +13,17 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
adopts version epics, [RELEASES.md](RELEASES.md) governs the choice among
|
adopts version epics, [RELEASES.md](RELEASES.md) governs the choice among
|
||||||
release-window members.
|
release-window members.
|
||||||
- **Your own red head outranks a new claim.** Pick up a failing check at the
|
- **Your own red head outranks a new claim.** Pick up a failing check at the
|
||||||
head of a PR you authored before claiming another issue: a red head that
|
head of a PR you authored before claiming another issue, or it strands
|
||||||
owes no round and holds no conflict is otherwise nobody's next move, and
|
mergeable and unattended (#163). Record the failing check and its failure
|
||||||
the PR strands mergeable (#163). Record the failing check and its failure
|
|
||||||
class; rerun a clearly retryable infrastructure failure without changing
|
class; rerun a clearly retryable infrastructure failure without changing
|
||||||
code; return to the normal fix-round and worklog discipline when the
|
code; return to the normal fix-round and worklog discipline where the
|
||||||
failure belongs to the branch; leave visible evidence when a rerun cannot
|
failure belongs to the branch; leave visible evidence where a rerun cannot
|
||||||
be started or the cause is uncertain; never repeatedly rerun a
|
be started or the cause is uncertain; never repeatedly rerun a
|
||||||
deterministic branch failure without a corrective commit; hand off once
|
deterministic branch failure without a corrective commit; hand off once
|
||||||
the check is green and current-head approvals stand. Such a PR is **not
|
the check is green and current-head approvals stand. Such a PR is **not
|
||||||
parked**, whatever the round's verdict state says. Red and green are the
|
parked**, whatever the round's verdict state says. Red and green are the
|
||||||
review round's ruled terms below; how the engine detects a red head is
|
ruled terms of the review round below; how the engine detects a red head
|
||||||
crew's to describe, not this file's.
|
is crew's to describe, not this file's.
|
||||||
- **One build at a time**: at most one issue on which you are writing or
|
- **One build at a time**: at most one issue on which you are writing or
|
||||||
revising a deliverable, finished or released before you start new work.
|
revising a deliverable, finished or released before you start new work.
|
||||||
The rule counts build work in flight, not claims — a **parked** claim,
|
The rule counts build work in flight, not claims — a **parked** claim,
|
||||||
|
|
@ -45,20 +44,19 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
5. the claim is **held by directive** — triage or the operator stopped the
|
5. the claim is **held by directive** — triage or the operator stopped the
|
||||||
work, the direction names what the hold waits on, and only they end it.
|
work, the direction names what the hold waits on, and only they end it.
|
||||||
A hold ends the way it started, **on the labels**: where labels and
|
A hold ends the way it started, **on the labels**: where labels and
|
||||||
prose disagree the most recent queue-label event by the hold's owner
|
prose disagree, the most recent queue-label event by the hold's owner
|
||||||
governs, an operator being free to lift by label alone (#149, #151). So
|
governs, an operator being free to lift by label alone (#149, #151). So
|
||||||
read the issue's label events
|
read the label events (`gh api /repos/{owner}/{repo}/issues/{n}/timeline`),
|
||||||
(`gh api /repos/{owner}/{repo}/issues/{n}/timeline`), not only its
|
not only the comments, before standing down *or* standing up, and where
|
||||||
comments, before standing down *or* standing up; where you act on the
|
you act against stale prose say so in the claim, naming the events,
|
||||||
labels against stale prose, say so in the claim — name the events, their
|
their timestamps and their actor. Refusing to claim through the
|
||||||
timestamps and their actor, and invite the correction. Refusing to claim
|
contradiction is no resting place: where the events do not resolve it,
|
||||||
through the contradiction is no resting place either: where the events
|
say so on the issue and take the next `ready` issue.
|
||||||
do not resolve it, say so on the issue and pick the next `ready` issue.
|
|
||||||
Not parked: waiting on yourself, on CI (a red head is your own work; a
|
Not parked: waiting on yourself, on CI (a red head is your own work; a
|
||||||
pending one resolves without you), or for a good moment. An issue you have
|
pending one resolves without you), or for a good moment. An issue you have
|
||||||
simply stopped working on is abandoned, not parked — unassign and restore
|
simply stopped working on is abandoned, not parked — unassign and restore
|
||||||
`ready`. The rule counts work and not claims because parked claims are
|
`ready`. The rule counts work because parked claims are legitimately held
|
||||||
legitimately held beside the one active build (#15, #16, #73).
|
beside the one active build (#15, #16, #73).
|
||||||
|
|
||||||
## Claiming
|
## Claiming
|
||||||
|
|
||||||
|
|
@ -106,10 +104,9 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
- **`Closes #N` does not cross repos.** A PR in a different repo from its
|
- **`Closes #N` does not cross repos.** A PR in a different repo from its
|
||||||
authorizing issue says `Part of <owner>/<repo>#N`, sets `offsite`, and
|
authorizing issue says `Part of <owner>/<repo>#N`, sets `offsite`, and
|
||||||
comments the draft PR link on that issue in the same step. Triage closes
|
comments the draft PR link on that issue in the same step. Triage closes
|
||||||
that issue by hand once its acceptance criteria are met; at that handoff
|
that issue by hand once its acceptance criteria are met, and at that
|
||||||
the builder reports whether the PR merged or closed and clears `offsite`
|
handoff the builder reports whether the PR merged or closed and clears
|
||||||
in the same comment. The cross-repo merge never closes the authorizing
|
`offsite` in the same comment (#13, #16).
|
||||||
issue (#13, #16).
|
|
||||||
- **`Closes #N` does not survive a post-merge criterion.** Where the issue's
|
- **`Closes #N` does not survive a post-merge criterion.** Where the issue's
|
||||||
body states that a criterion can only be checked after the merge — a live
|
body states that a criterion can only be checked after the merge — a live
|
||||||
proof of a workflow trigger, a released-artifact check, anything whose
|
proof of a workflow trigger, a released-artifact check, anything whose
|
||||||
|
|
@ -117,10 +114,10 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
same-repo PR says `Refs #N` and triage closes by hand on the evidence. The
|
same-repo PR says `Refs #N` and triage closes by hand on the evidence. The
|
||||||
merge releases the claim: the issue moves to `post-merge`, the builder
|
merge releases the claim: the issue moves to `post-merge`, the builder
|
||||||
walks away, and triage owns verification and closure, returning it to
|
walks away, and triage owns verification and closure, returning it to
|
||||||
`ready` or minting a fresh issue where corrective work is needed, which
|
`ready` or minting a fresh issue for corrective work that any builder
|
||||||
any builder claims from current `main`. The issue body is what says so —
|
claims from current `main`. The issue body is what says so — you never
|
||||||
you never judge which issues qualify, and absent that instruction
|
judge which issues qualify, and absent that instruction `Closes #N` is the
|
||||||
`Closes #N` is the default (#151).
|
default (#151).
|
||||||
- On a `Refs #N` PR, never put a closing keyword (`close`, `closes`,
|
- On a `Refs #N` PR, never put a closing keyword (`close`, `closes`,
|
||||||
`closed`, `fix`, `fixes`, `fixed`, `resolve`, `resolves`, `resolved`)
|
`closed`, `fix`, `fixes`, `fixed`, `resolve`, `resolves`, `resolved`)
|
||||||
immediately before `#N` anywhere in the body, including the sentence
|
immediately before `#N` anywhere in the body, including the sentence
|
||||||
|
|
@ -140,12 +137,12 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
entries; wrapping one over continuation lines never counts against it. It
|
entries; wrapping one over continuation lines never counts against it. It
|
||||||
**ends with its issue citation**: one `(` group of `#N`, `repo#N` or
|
**ends with its issue citation**: one `(` group of `#N`, `repo#N` or
|
||||||
`owner/repo#N` separated by `, `, then `)`, then the final `.` and nothing
|
`owner/repo#N` separated by `, `, then `)`, then the final `.` and nothing
|
||||||
after it — `(#262).`, or `(#236, #250).` where an entry honestly lands
|
after it — `(#262).`, or `(#236, #250).` where an entry honestly lands two
|
||||||
two — and it need not name the fragment's own issue, which the filename
|
— and it need not name the fragment's own issue, which the filename
|
||||||
carries. The fragment guard reds a longer entry (#167) and an uncited one
|
carries. The guard reds a longer entry (#167) and an uncited one (#262)
|
||||||
(#262) alike. Never edit `CHANGELOG.md` for an entry: the release PR
|
alike. Never edit `CHANGELOG.md` for an entry: the release PR assembles
|
||||||
assembles the section from the fragments (#112), and the monotonic guard
|
the section from the fragments (#112), and the monotonic guard refuses
|
||||||
refuses anything that deletes a shipped heading.
|
anything that deletes a shipped heading.
|
||||||
- Follow the repo's conventions file and match the code you touch. Tests are
|
- Follow the repo's conventions file and match the code you touch. Tests are
|
||||||
not optional: the issue's test plan is the floor, not the ceiling.
|
not optional: the issue's test plan is the floor, not the ceiling.
|
||||||
- **A write-capable job gets a repo-owned script, not a third-party action.**
|
- **A write-capable job gets a repo-owned script, not a third-party action.**
|
||||||
|
|
@ -163,39 +160,32 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
|
|
||||||
## The review round
|
## The review round
|
||||||
|
|
||||||
(Read as `.ceremony/BUILDER.md` in a governed repo: repo-specific facts such
|
|
||||||
as the panel roster live in that repo's own CONTRIBUTING, and the shared
|
|
||||||
flow lives here.)
|
|
||||||
|
|
||||||
1. Mark ready-for-review; request **the whole panel**: the PR repo's
|
1. Mark ready-for-review; request **the whole panel**: the PR repo's
|
||||||
`panel[<your-login>]=` line if it defines one, else its `panel=` line,
|
`panel[<your-login>]=` line if it defines one, else its `panel=` line,
|
||||||
minus the author in either case (#224) — never the roster of the repo the
|
minus the author in either case (#224) — never the roster of the repo the
|
||||||
issue is in. That repo's `.github/labels.conf` governs over its
|
issue is in. That repo's `.github/labels.conf` governs over its
|
||||||
CONTRIBUTING roster, being what the state machine reads; where the PR
|
CONTRIBUTING roster, being what the state machine reads; where the PR
|
||||||
repo names no roster, ask triage on the authorizing issue before marking
|
repo names no roster, ask triage on the authorizing issue rather than
|
||||||
ready-for-review rather than guessing. You may request an off-panel
|
guessing. An off-panel reviewer may be requested, saying that their
|
||||||
reviewer, saying that their verdict is advisory and does not become
|
verdict is advisory and does not become required.
|
||||||
required.
|
|
||||||
**A review request requires a green check at the head**, and that binds
|
**A review request requires a green check at the head**, and that binds
|
||||||
you whether or not any engine enforces it: a red check is the author's
|
you whether or not any engine enforces it: a red check is the author's
|
||||||
own signal, not the panel's work, so fix it and push, then request. The
|
own signal, not the panel's work, so fix it and push, then request. The
|
||||||
one exception is a failure genuinely outside the PR — a runner outage, a
|
one exception is a failure genuinely outside the PR — a runner outage, a
|
||||||
flaky dependency, a failure already present on the default branch — and
|
flaky dependency, a failure already present on the default branch — and
|
||||||
only where the request says so explicitly and names the evidence ("the
|
only where the request says so explicitly and names the evidence ("the
|
||||||
same job fails identically on `origin/main` at `<sha>`"). Silence about a
|
same job fails identically on `origin/main` at `<sha>`"); silence about a
|
||||||
red check is what is prohibited; an argued exception shifts the burden to
|
red check is what is prohibited.
|
||||||
the author.
|
|
||||||
*Green* is a ruled term (operator, 2026-07-27), read in two steps,
|
*Green* is a ruled term (operator, 2026-07-27), read in two steps,
|
||||||
because a head carries more rollup entries than it has checks. **First
|
because a head carries more rollup entries than it has checks. **First
|
||||||
find the check's word at this head**: its newest entry by start time,
|
find the check's word at this head**: its newest entry by start time,
|
||||||
except that a `CANCELLED` entry is never the word while the same check
|
except that a `CANCELLED` entry is never the word while the same check
|
||||||
has a non-cancelled entry at that head. Date entries by start and not by
|
has a non-cancelled entry at that head. Date entries by start, not by
|
||||||
completion — a cancelled run outlives its replacement's start, so the
|
completion — a cancelled run outlives its replacement's start, so the
|
||||||
other reading picks the corpse. A check whose every entry at the head is
|
other reading picks the corpse. A check whose every entry at the head is
|
||||||
cancelled has not reported at all and stays not-green by the classes
|
cancelled has not reported and stays not-green by the classes below; that
|
||||||
below; that is a collapse, not a new class, and the gate partitions the
|
is a collapse and not a new class, the gate likewise dropping a cancelled
|
||||||
same way, dropping a cancelled entry only where its context keeps a
|
entry only where its context keeps a non-cancelled survivor (#139, #276).
|
||||||
non-cancelled survivor (#139, #276).
|
|
||||||
**Then classify that entry from its `conclusion`, never its `status`**,
|
**Then classify that entry from its `conclusion`, never its `status`**,
|
||||||
which can still disagree with it (#259). No conclusion at all is neither
|
which can still disagree with it (#259). No conclusion at all is neither
|
||||||
class: a configured run still in progress is not green, and waiting on it
|
class: a configured run still in progress is not green, and waiting on it
|
||||||
|
|
@ -228,10 +218,10 @@ flow lives here.)
|
||||||
head did not move — the round answered with argument or evidence, nothing
|
head did not move — the round answered with argument or evidence, nothing
|
||||||
pushed — do you re-request just the non-approvers, a standing approval
|
pushed — do you re-request just the non-approvers, a standing approval
|
||||||
already covering this exact head (#94). **The re-request carries the same
|
already covering this exact head (#94). **The re-request carries the same
|
||||||
green-check-at-head precondition as the first request**, argued exception
|
green-check-at-head precondition**, argued exception included: a fix push
|
||||||
included: a fix push whose check comes up red is your next fix, not the
|
whose check comes up red is your next fix, not the panel's. Prefer
|
||||||
panel's. Prefer verification over argument — where a reviewer doubts
|
verification over argument — where a reviewer doubts behavior, add the
|
||||||
behavior, add the test that settles it.
|
test that settles it.
|
||||||
3. Never dismiss a review, never merge, never mark your own work as passed.
|
3. Never dismiss a review, never merge, never mark your own work as passed.
|
||||||
A blocking point you disagree with is answered with evidence or escalated
|
A blocking point you disagree with is answered with evidence or escalated
|
||||||
in the PR; silence and force-forward are not options, and a panel
|
in the PR; silence and force-forward are not options, and a panel
|
||||||
|
|
@ -240,21 +230,20 @@ flow lives here.)
|
||||||
**A fix round may ride a draft**, and the draft changes nothing about who
|
**A fix round may ride a draft**, and the draft changes nothing about who
|
||||||
owes what. An engine may convert a PR back to draft when a round closes, so
|
owes what. An engine may convert a PR back to draft when a round closes, so
|
||||||
that mid-round saves stop firing CI on a ready PR; ceremony implements no
|
that mid-round saves stop firing CI on a ready PR; ceremony implements no
|
||||||
such conversion and this passage specifies none, but whoever meets a
|
such conversion, but whoever meets a mid-round draft reads it as a draft
|
||||||
mid-round draft reads it as a draft always read — the draft phase is yours
|
always read — the draft phase is yours and the panel cannot see it — while
|
||||||
and the panel cannot see it — while the round outranks the draft, so you
|
the round outranks the draft, so you still owe it whole, the fixes and the
|
||||||
still owe it whole, the fixes and the reply and the flip
|
reply and the flip ([LABELS.md](LABELS.md)'s `state:building` row, #205).
|
||||||
([LABELS.md](LABELS.md)'s `state:building` row, #205). **Ready-for-review is
|
**Ready-for-review is the act that ends the round, and it is the builder's
|
||||||
the act that ends the round, and it is the builder's alone**: the flip
|
alone**: the flip asserts that the round was answered whole, the one
|
||||||
asserts that the round was answered whole, the one judgement about a round
|
judgement about a round its author cannot delegate, so an engine may draft a
|
||||||
its author cannot delegate, so an engine may draft a PR but only the builder
|
PR but only the builder undrafts it. **Where a draft suppressed the checks,
|
||||||
undrafts it. **Where a draft suppressed the checks, green is proven at the
|
green is proven at the flip and the request still follows it**: marking
|
||||||
flip and the request still follows it**: marking ready is what runs the
|
ready is what runs the checks the draft held back, so the order is flip, let
|
||||||
checks the draft held back, so the order is flip, let the head answer, then
|
the head answer, then request — step 1's precondition, not a second one —
|
||||||
request — step 1's precondition, not a second one. Waiting there is
|
and waiting there is compliance, not a stall, which is why
|
||||||
compliance, not a stall, and `blocker:unrequested` does not fire while a
|
`blocker:unrequested` does not fire while a head's checks are pending or red
|
||||||
head's checks are pending or red, because the one blocker that demands an
|
(#236).
|
||||||
act has to know when the act is permitted (#236).
|
|
||||||
|
|
||||||
## The ruling ask
|
## The ruling ask
|
||||||
|
|
||||||
|
|
@ -289,21 +278,20 @@ The ladder is anchored to the current episode's `needs-ruling` **`labeled`
|
||||||
event**, not its `Default:` deadline or the last activity (#50 D13–D14):
|
event**, not its `Default:` deadline or the last activity (#50 D13–D14):
|
||||||
|
|
||||||
- **0–12h:** proceed when a still-clear, reversible default expires, and say
|
- **0–12h:** proceed when a still-clear, reversible default expires, and say
|
||||||
out loud that you did. A hard block waits.
|
out loud that you did; a hard block waits.
|
||||||
- **at 12h:** do not fire a stale default. Re-read it against what has landed
|
- **at 12h:** do not fire a stale default — re-read it against what has
|
||||||
and ask whether it still holds and whether reasonable doubt remains. If
|
landed, and where doubt has appeared, make it a hard block.
|
||||||
doubt has appeared, make it a hard block.
|
- **at 24h:** proceed regardless, **as a PR**: pick an option and state in
|
||||||
- **at 24h:** proceed regardless, **as a PR**. Pick an option and state in the
|
the PR body which way you went and what doubt remains. Nothing merges by
|
||||||
PR body which way you went and what doubt remains. Nothing merges by this;
|
this; the human still gates the merge.
|
||||||
the human still gates the merge.
|
- **past 24h:** hand the choice to triage, which picks the option, records
|
||||||
- **past 24h:** hand the choice to triage. Triage picks the option, records it
|
it as a decision, and remains accountable; the operator can overturn it at
|
||||||
as a decision, and remains accountable; the operator can overturn it at
|
|
||||||
merge.
|
merge.
|
||||||
|
|
||||||
A re-flag starts a fresh ladder. The ladder applies whatever `Default:` says,
|
A re-flag starts a fresh ladder. The ladder applies whatever `Default:` says,
|
||||||
including a hard block, and an active back-and-forth still climbs it. This is
|
including a hard block, and an active back-and-forth still climbs it — unlike
|
||||||
different from the 7-day nudge, which resets on real activity. The machine
|
the 7-day nudge, which resets on real activity. The machine observes both
|
||||||
observes both clocks but never sets, clears, or decides `needs-ruling`.
|
clocks but never sets, clears, or decides `needs-ruling`.
|
||||||
|
|
||||||
The label stays until agreement is *reached*, not until the maintainer
|
The label stays until agreement is *reached*, not until the maintainer
|
||||||
replies. The setter records the ruling, removes the label, and returns the
|
replies. The setter records the ruling, removes the label, and returns the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue