Merge pull request 'docs: adopt upstream 0.6.1 and 0.6.2 doctrine' (#233) from codex-bot-andresmgsl/ceremony:build/229-upstream-doctrine into main
Some checks failed
CI / test (push) Failing after 3m31s
CI / release-exercise (push) Has been skipped
CI / self-guards (push) Successful in 19s
CI / action-exercise (push) Successful in 18s
CI / docs-sync-exercise (push) Successful in 18s
release / release (push) Successful in 19s

Reviewed-on: #233
Reviewed-by: claude-bot-andresmgsl <andres+1@heavyduty.builders>
Reviewed-by: kimi-bot-andresmgsl <andres+4@heavyduty.builders>
Reviewed-by: glm-bot-andresmgsl <andres+5@heavyduty.builders>
This commit is contained in:
andres 2026-08-22 22:16:23 +00:00
commit 4f887a756f
4 changed files with 70 additions and 29 deletions

View file

@ -33,7 +33,10 @@ triage bug, and the move is to say so on the issue, not to guess.
re-requests posted, by head and not by verdict (steps 12). A red check re-requests posted, by head and not by verdict (steps 12). A red check
at the head takes it out of this shape: the next move is yours; at the head takes it out of this shape: the next move is yours;
3. every remaining acceptance criterion is operator-owned, stated so by 3. every remaining acceptance criterion is operator-owned, stated so by
triage on the issue; triage on the issue. **An operator-owned remainder parks the claim and
never the handoff**: this shape is reached only from the far side of
shape 4, because it is the state finishing the work puts you in and
would otherwise excuse the handoff it should follow (#336);
4. it is **handed off** — round passed, no `blocker:*` standing, 4. it is **handed off** — round passed, no `blocker:*` standing,
`state:needs-human` set per Handoff, the merge the human's. Shapes 2 `state:needs-human` set per Handoff, the merge the human's. Shapes 2
and 4 are sequential and never overlap; and 4 are sequential and never overlap;
@ -174,7 +177,9 @@ such as the panel roster live in that repo's own CONTRIBUTING.)
blocking (#139, #276). **Then classify that entry by `conclusion`, never blocking (#139, #276). **Then classify that entry by `conclusion`, never
`status`**, which can disagree with it (#259). No conclusion is not `status`**, which can disagree with it (#259). No conclusion is not
green: a configured run in progress is waited on, and waiting is green: a configured run in progress is waited on, and waiting is
compliance, not a stall. Cancelled or stale is not green, *stale* being a compliance, not a stall — the wait is the **request's**, and never a
reason to withhold the declaration that a round was answered (step 2).
Cancelled or stale is not green, *stale* being a
superseded head's check, which a head-scoped rollup never shows. Skipped superseded head's check, which a head-scoped rollup never shows. Skipped
or neutral is green, those being deliberate "passed / not applicable" or neutral is green, those being deliberate "passed / not applicable"
conclusions. No checks configured is green — the third ruled case, not an conclusions. No checks configured is green — the third ruled case, not an
@ -200,8 +205,19 @@ such as the panel roster live in that repo's own CONTRIBUTING.)
head, and its mechanism is crew's to describe (#94). **The re-request head, and its mechanism is crew's to describe (#94). **The re-request
carries the same green-check-at-head precondition**, argued exception carries the same green-check-at-head precondition**, argued exception
included: a fix push whose check comes up red is your next fix, not the included: a fix push whose check comes up red is your next fix, not the
panel's. Prefer verification over argument — add the test that settles panel's. **Where an engine mediates the request, that precondition binds
the doubt. the engine's act and not yours**: declaring a round answered is not
requesting the panel, so declare it as soon as the round's fixes are
pushed and stop. The engine holds the request while the head is pending
or red, so an early declaration cannot produce an early request while a
withheld one is indistinguishable from a session that died (#330).
**Never wait on an event you have no wake for** — where the engine is
what observes the check settling, the wait is the engine's to keep
(#330). **Never block on a producer you cannot prove alive either**:
where a job signals its own completion, that signal is the wake and the
finished output is read afterwards, because a follow on a file nothing is
writing cannot tell *not yet* from *never* (#336). Prefer verification
over argument — add the test that settles the doubt.
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
@ -218,8 +234,9 @@ may draft a PR but only the builder undrafts it. **Where a draft suppressed
the checks, green is proven at the flip and the request still follows it** — the checks, green is proven at the flip and the request still follows it** —
marking ready runs the checks the draft held back, so the order is flip, let marking ready runs the checks the draft held back, so the order is flip, let
the head answer, then request, step 1's precondition and not a second one. the head answer, then request, step 1's precondition and not a second one.
Waiting there is compliance, and `blocker:unrequested` does not fire while a Waiting there is compliance — again the request's wait, not the
head's checks are pending or red (#236). declaration's — and `blocker:unrequested` does not fire while a head's
checks are pending or red (#236).
## The ruling ask ## The ruling ask

View file

@ -97,14 +97,13 @@ table repeats it (#104).
## Doctrine conventions ## Doctrine conventions
The vendored role files — `AGENTS.md`, `TRIAGE.md`, `BUILDER.md`, The vendored role files — the set [`docs/VENDORED.txt`](docs/VENDORED.txt)
`REVIEWER.md`, `LABELS.md`, and `RELEASES.md` — state each normative rule declares — state each normative rule completely, keep at most one sentence of
completely, keep at most one sentence of why, and cite its record only with a why, and cite its record only with a bare parenthetical such as `(#N)`,
bare parenthetical such as `(#N)`, `(#N D3)`, or `(#N, #M)`. Incident `(#N D3)`, or `(#N, #M)`. Incident narrative — timestamps, actors, quoted
narrative — timestamps, actors, quoted comments, measured counts, and links to comments, measured counts, and links to specific comments — belongs in that
specific comments — belongs in that record. If a rule cannot be followed record. If a rule cannot be followed without chasing its cite, the rule is
without chasing its cite, the rule is under-stated: fix the statement, not the under-stated: fix the statement, not the citation. (#280)
citation. (#280)
Normative text in those files does not cite issues from other repositories. Normative text in those files does not cite issues from other repositories.
Consumers read the vendored bytes outside this organization's context, and a Consumers read the vendored bytes outside this organization's context, and a
@ -119,21 +118,12 @@ every session. (#280)
## How the other repos use this ## How the other repos use this
Two consumption modes, split by what has a runtime: Two consumption modes, split by what has a runtime: **machinery by
reference**, fetched at run time from the ref a caller pins, and **doctrine
- **Machinery is consumed by reference.** Workflows and actions are fetched as a mirror** — the set [`docs/VENDORED.txt`](docs/VENDORED.txt) declares,
by GitHub at run time from the ref the caller pins — no copy exists in the vendored at `.ceremony/` and held to the pin by a guard (issue #19). The
consumer. [README](README.md) states both modes in full, and why they differ; what
- **Doctrine is consumed as a machine-verified mirror.** A document's only follows is only what they leave a governed repo to carry.
"runtime" is an agent reading the working tree of the repo it stands in —
a doc that requires a cross-repo fetch before it governs is a doc that
sometimes goes unread. So the agent-facing set — **AGENTS.md, TRIAGE.md,
BUILDER.md, REVIEWER.md, LABELS.md, RELEASES.md** — is vendored into each governed
repo at **`.ceremony/`**, byte-identical to this repo at the pinned ref,
by the sync tool (issue #19). A CI guard diffs the mirror against the pin
on every PR: hand-editing a vendored file, or bumping the pin without
re-syncing, goes red. It is a copy that cannot drift — which is the only
kind of copy this org allows.
A governed repo (box, rig, cast, incubator, …) therefore carries: A governed repo (box, rig, cast, incubator, …) therefore carries:

View file

@ -86,6 +86,37 @@ edges rather than merely appending membership at the sink. It follows that
every `ready` issue is a gate member. `epic` and `post-merge` issues are exempt every `ready` issue is a gate member. `epic` and `post-merge` issues are exempt
because neither is claimable (#292). because neither is claimable (#292).
A member that lands `post-merge` releases nothing: that exemption is about
claimability, while a `post-merge` issue is still open and an open predecessor
holds its successors, so every successor declaring on it stays held and the
window stops advancing along that edge (#329).
**When a member reaches `post-merge` and any open declaration names it, triage
splits the remainder**: mint a fresh issue carrying the outstanding criteria
verbatim, naming its owner and its wake condition and citing the original, then
close the original on what it delivered. Triage owns this because only triage
mints issues and `post-merge` is its completion queue (#329).
**The release edge is the original's close, never the remainder's.** Each
successor's declaration names the original's number, so closing the new issue
releases nothing (#329).
**Split only when an open declaration names the issue.** The trigger is a check
rather than a judgement — run the blocker parse over every open `blocked` body
and see whether this number appears — because an issue that strands nothing is
`post-merge` working as intended (#329).
**Never close work out from under a builder.** Where the original is assigned,
`claimed`, or carrying an open PR, amend its body to hand the outstanding
criteria to the new issue and let its holder close it, so the release edge above
is reached without taking the work from them (#329).
**Do not instead teach the blocker parse that `post-merge` counts as landed.**
That promotes a successor while its predecessor still owes acceptance criteria,
inverts a parser whose deliberate error direction is to hold or flag a reference
it cannot read rather than release it, and needs label data a reference-state
lookup does not carry (#329).
The operator may declare a parallel track at init when its footprint is The operator may declare a parallel track at init when its footprint is
disjoint from the primary window: another repository, another artifact, or disjoint from the primary window: another repository, another artifact, or
provably non-overlapping clusters. The declaration names the boundary and any provably non-overlapping clusters. The declaration names the boundary and any

3
changelog.d/229.md Normal file
View file

@ -0,0 +1,3 @@
### Changed
- Forge consumers now receive the upstream 0.6.1 and 0.6.2 doctrine for vendored-set routing, review-round signalling, operator-owned remainders, producer liveness, and post-merge release edges (#229).