docs: adopt upstream 0.6.1 and 0.6.2 doctrine #233

Merged
andres merged 4 commits from codex-bot-andresmgsl/ceremony:build/229-upstream-doctrine into main 2026-08-22 22:16:23 +00:00
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
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
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,
`state:needs-human` set per Handoff, the merge the human's. Shapes 2
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
`status`**, which can disagree with it (#259). No conclusion is not
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
or neutral is green, those being deliberate "passed / not applicable"
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
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
panel's. Prefer verification over argument — add the test that settles
the doubt.
panel's. **Where an engine mediates the request, that precondition binds
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.
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
@ -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** —
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.
Waiting there is compliance, and `blocker:unrequested` does not fire while a
head's checks are pending or red (#236).
Waiting there is compliance — again the request's wait, not the
declaration's — and `blocker:unrequested` does not fire while a head's
checks are pending or red (#236).
## The ruling ask

View file

@ -97,14 +97,13 @@ table repeats it (#104).
## Doctrine conventions
The vendored role files — `AGENTS.md`, `TRIAGE.md`, `BUILDER.md`,
`REVIEWER.md`, `LABELS.md`, and `RELEASES.md` — state each normative rule
completely, keep at most one sentence of why, and cite its record only with a
bare parenthetical such as `(#N)`, `(#N D3)`, or `(#N, #M)`. Incident
narrative — timestamps, actors, quoted comments, measured counts, and links to
specific comments — belongs in that record. If a rule cannot be followed
without chasing its cite, the rule is under-stated: fix the statement, not the
citation. (#280)
The vendored role files — the set [`docs/VENDORED.txt`](docs/VENDORED.txt)
declares — state each normative rule completely, keep at most one sentence of
why, and cite its record only with a bare parenthetical such as `(#N)`,
`(#N D3)`, or `(#N, #M)`. Incident narrative — timestamps, actors, quoted
comments, measured counts, and links to specific comments — belongs in that
record. If a rule cannot be followed without chasing its cite, the rule is
under-stated: fix the statement, not the citation. (#280)
Normative text in those files does not cite issues from other repositories.
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
Two consumption modes, split by what has a runtime:
- **Machinery is consumed by reference.** Workflows and actions are fetched
by GitHub at run time from the ref the caller pins — no copy exists in the
consumer.
- **Doctrine is consumed as a machine-verified mirror.** A document's only
"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.
Two consumption modes, split by what has a runtime: **machinery by
reference**, fetched at run time from the ref a caller pins, and **doctrine
as a mirror** — the set [`docs/VENDORED.txt`](docs/VENDORED.txt) declares,
vendored at `.ceremony/` and held to the pin by a guard (issue #19). The
[README](README.md) states both modes in full, and why they differ; what
follows is only what they leave a governed repo to carry.
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
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
disjoint from the primary window: another repository, another artifact, or
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).