forked from heavy-duty/rig
chore: bump ceremony pin to 0.2.0
This commit is contained in:
parent
20438f09e8
commit
e22e0dd4a8
12 changed files with 361 additions and 62 deletions
|
|
@ -11,14 +11,78 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
- Respect dependency order: inside an epic, take the earliest unblocked
|
- Respect dependency order: inside an epic, take the earliest unblocked
|
||||||
unclaimed child. Between epics and strays, prefer the issue that unblocks
|
unclaimed child. Between epics and strays, prefer the issue that unblocks
|
||||||
the most other work.
|
the most other work.
|
||||||
- **One issue at a time.** Finish or release your claim before taking
|
- **One build at a time.** You hold at most one issue on which you are
|
||||||
another.
|
writing or revising a deliverable — finish or release that work before
|
||||||
|
starting new work. 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. Exactly five shapes qualify:
|
||||||
|
1. the issue carries `needs-ruling`, its escalation names a decider, and
|
||||||
|
its `Blocked:` line stops the remaining work;
|
||||||
|
2. the deliverable is in a review round where every outstanding verdict
|
||||||
|
belongs to someone else — either the round is awaiting its first
|
||||||
|
verdicts, or it was answered whole and the non-approvers re-requested
|
||||||
|
(the review round, steps 1–2). This is the *live* round; shape 4 is
|
||||||
|
the *passed* one — they are sequential and do not overlap;
|
||||||
|
3. every remaining acceptance criterion is operator-owned, stated as such
|
||||||
|
by triage on the issue;
|
||||||
|
4. the deliverable is **handed off** — the round passed, no `blocker:*`
|
||||||
|
stands, and you set `state:needs-human` per Handoff (below). The
|
||||||
|
remaining move is the human's merge.
|
||||||
|
5. the claim is **held by directive** — triage or the operator has told
|
||||||
|
you to stop, the direction names what the hold waits on, and that thing
|
||||||
|
is not yours to move. This is not "waiting for a good moment": somebody
|
||||||
|
else has decided the work must not proceed, and only they end it.
|
||||||
|
Not parked — these are what the rule defends against: waiting on
|
||||||
|
yourself, waiting on CI, or waiting for a good moment. An issue you have
|
||||||
|
simply stopped working on is not parked either — that is abandonment,
|
||||||
|
and its move is unchanged: unassign and restore `ready` (Claiming,
|
||||||
|
below).
|
||||||
|
The 2026-07-23 board is why the rule counts work and not claims: one
|
||||||
|
builder correctly held
|
||||||
|
[#15](https://github.com/heavy-duty/ceremony/issues/15) (`offsite`,
|
||||||
|
round answered whole, one verdict outstanding) and
|
||||||
|
[#16](https://github.com/heavy-duty/ceremony/issues/16) (`needs-ruling`
|
||||||
|
hard block, triage said hold) parked beside the one active build,
|
||||||
|
[#73](https://github.com/heavy-duty/ceremony/issues/73).
|
||||||
|
|
||||||
## Claiming
|
## Claiming
|
||||||
|
|
||||||
- Assign yourself, swap `ready` → `claimed`, and comment that you are
|
- Assign yourself, swap `ready` → `claimed`, and comment that you are
|
||||||
starting. The claim is a promise of a draft PR soon — a claim with no PR
|
starting. The claim is a promise of a draft PR soon — a claim with no PR
|
||||||
and no activity is what the staleness sweep reclaims.
|
and no activity is what the staleness sweep reclaims unless `offsite`
|
||||||
|
records that its PR lives in another repository.
|
||||||
|
- **A park is declared, never inferred.** When your claim enters a parked
|
||||||
|
shape (Picking, above), say so in a comment on that issue, naming what it
|
||||||
|
waits on and who owns the next move. No new label: the comment is
|
||||||
|
activity, so it feeds the same reclaim clock the `needs-ruling`
|
||||||
|
([#52](https://github.com/heavy-duty/ceremony/issues/52)) and `offsite`
|
||||||
|
([#68](https://github.com/heavy-duty/ceremony/issues/68)) exemptions
|
||||||
|
already guard — a parked claim nobody can name is an abandoned one.
|
||||||
|
Shape 4 alone is exempt from the separate comment: the handoff round
|
||||||
|
summary plus the `state:needs-human` write *is* its declaration — both
|
||||||
|
halves are already there, what the claim waits on (the merge) and who
|
||||||
|
owns the next move (the human), and both are visible to any scan as a
|
||||||
|
`labeled` event with the summary beside it. No second comment is owed
|
||||||
|
on the issue. Every other shape still declares as above.
|
||||||
|
- **Pick up `attention` before anything else.** On your claim, first post a
|
||||||
|
short pickup comment and remove `attention`; the removal is the ack. A
|
||||||
|
demand on a parked claim is usually its unpark, so take the slot back under
|
||||||
|
the existing rule below rather than leaving the demand parked. A demand
|
||||||
|
that *is* the park is different: the pickup comment is the declaration,
|
||||||
|
so one comment does both jobs, and the demand does not take the slot back.
|
||||||
|
- **A directed hold keeps its bookkeeping visible.** The PR carries `blocked`
|
||||||
|
with a comment naming what it waits on; the issue stays `claimed` and
|
||||||
|
carries `attention` until the builder acknowledges it. Nobody unassigns
|
||||||
|
the issue, and the 48-hour reclaim does not fire because the claim has an
|
||||||
|
open PR. Unparking follows the existing rule below.
|
||||||
|
- **Unparking is a claim like any other.** When the wait ends, the parked
|
||||||
|
issue is work again and takes the slot. If you are already active
|
||||||
|
elsewhere, finish or release that work first, and say which you did on
|
||||||
|
both issues — the slot is still one. Nothing counts claims per builder
|
||||||
|
and no reconciler path enforces any of this: `claim_decision()` sees one
|
||||||
|
issue at a time by construction, and no such machinery should be built
|
||||||
|
expecting it to have been specified here. The discipline is the
|
||||||
|
declaration, not a counter.
|
||||||
- **Abandoning is fine; ghosting is not.** If you stop, say where you got to,
|
- **Abandoning is fine; ghosting is not.** If you stop, say where you got to,
|
||||||
push the branch if it holds anything useful, unassign, and restore
|
push the branch if it holds anything useful, unassign, and restore
|
||||||
`ready`.
|
`ready`.
|
||||||
|
|
@ -26,15 +90,29 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
- Branch per issue; open the PR **as a draft early**, `Closes #N` in the
|
- Branch per issue; open the PR **as a draft early**, `Closes #N` in the
|
||||||
body. Drafts are invisible to the reviewer panel on purpose — the draft
|
body. `Closes #N` does not cross repos: when the PR is in a different repo
|
||||||
phase is yours.
|
from its authorizing issue, use `Part of <owner>/<repo>#N` instead, and
|
||||||
|
in the same step set `offsite` and comment on that issue with the draft PR
|
||||||
|
link as soon as the draft opens.
|
||||||
|
Triage closes the authorizing issue by hand when its acceptance criteria
|
||||||
|
are met; at that handoff the builder reports whether the cross-repo PR
|
||||||
|
merged or closed and clears `offsite` in the same comment. The cross-repo
|
||||||
|
merge never closes the authorizing issue. This codifies the linkage
|
||||||
|
builders already used on rig#112 and ceremony #13/#16 rather than adding a
|
||||||
|
new review obligation. Drafts are invisible to the reviewer panel on
|
||||||
|
purpose — the draft phase is yours.
|
||||||
- **The issue's acceptance criteria are your definition of done.** Reproduce
|
- **The issue's acceptance criteria are your definition of done.** Reproduce
|
||||||
them as a checklist in the PR body and check them honestly as you go. If
|
them as a checklist in the PR body and check them honestly as you go. If
|
||||||
one turns out to be wrong or unreachable, say so on the issue and get it
|
one turns out to be wrong or unreachable, say so on the issue and get it
|
||||||
amended by triage — do not silently ship less than the issue says.
|
amended by triage — do not silently ship less than the issue says.
|
||||||
- Every behavior change adds one line to `CHANGELOG.md` under
|
- Every behavior change writes one fragment, `changelog.d/<issue>.md`,
|
||||||
`## Unreleased` — insert **above** the heading below it, never over it
|
named for the authorizing issue (`<repo>-<issue>.md` when the work is
|
||||||
(the monotonic guard's whole reason to exist).
|
cross-repo) — the exact prose that will be published, nothing else: `- `
|
||||||
|
bullets, and in a grouped repo the `### Added` / `### Changed` /
|
||||||
|
`### Fixed` headings inside the fragment, creating a rarer kind only when
|
||||||
|
a change genuinely is one. Never edit `CHANGELOG.md` for an entry — the
|
||||||
|
release PR assembles the section from the fragments (#112); the monotonic
|
||||||
|
guard still refuses 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.
|
||||||
- **Scope discipline: the PR does the issue — whole, and nothing else.**
|
- **Scope discipline: the PR does the issue — whole, and nothing else.**
|
||||||
|
|
@ -49,16 +127,81 @@ triage bug, and the move is to say so on the issue, not to guess.
|
||||||
panel roster and any repo-specific flow notes live in that repo's own
|
panel roster and any repo-specific flow notes live in that repo's own
|
||||||
CONTRIBUTING; everything below is the shared flow.)
|
CONTRIBUTING; everything below is the shared flow.)
|
||||||
|
|
||||||
1. Mark ready-for-review; request **the whole panel** (the roster is in the
|
1. Mark ready-for-review; request **the whole panel**. The panel is the roster
|
||||||
repo's CONTRIBUTING).
|
of the repo the **PR** is in, minus you — never the roster of the repo the
|
||||||
|
issue is in. The PR repo's `.github/labels.conf` `panel=` line is the
|
||||||
|
machine's answer; its CONTRIBUTING roster is the human-readable answer,
|
||||||
|
and `panel=` governs if they disagree because that is what the state
|
||||||
|
machine reads. If the PR repo names no roster, ask triage on the
|
||||||
|
authorizing issue before marking ready-for-review; do not guess. You may
|
||||||
|
request an off-panel reviewer, but say that their verdict is advisory and
|
||||||
|
does not become required. On rig#112 this distinction mattered: requesting
|
||||||
|
codex and grok was correct for rig's panel even though ceremony's bench was
|
||||||
|
larger, and the doctrine had not said which roster governed.
|
||||||
2. **Wait for every verdict, then answer the round whole** — one reply
|
2. **Wait for every verdict, then answer the round whole** — one reply
|
||||||
covering every point, then push the fixes, then re-request exactly the
|
covering every point, then push the fixes, then re-request exactly the
|
||||||
reviewers who did not approve. Prefer verification over argument: when a
|
reviewers who did not approve. Prefer verification over argument: when a
|
||||||
reviewer doubts behavior, add the test that settles it.
|
reviewer doubts behavior, add the 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 — a maintainer can be asked for a ruling; silence and
|
in the PR — silence and force-forward are not options. A panel deadlock
|
||||||
force-forward are not options.
|
is one kind of human-owned decision; use the ruling ask below
|
||||||
|
([#50 D11](https://github.com/heavy-duty/ceremony/issues/50)).
|
||||||
|
|
||||||
|
## The ruling ask
|
||||||
|
|
||||||
|
Set `needs-ruling` whenever a decision belongs to a human: org policy,
|
||||||
|
published artifacts, secrets, prod, or any choice whose cost lands outside
|
||||||
|
the PR. A panel deadlock is one instance, not the definition. The builder is
|
||||||
|
the accountable flag-setter on a PR and consolidates the decision into one
|
||||||
|
comment rather than forwarding several reviewers' phrasings
|
||||||
|
([#50 D11](https://github.com/heavy-duty/ceremony/issues/50)).
|
||||||
|
|
||||||
|
Keep at most these five lines above the fold and put all other analysis
|
||||||
|
inside the fold. The field labels are fixed because the ruling machinery
|
||||||
|
checks for them ([#50 D12](https://github.com/heavy-duty/ceremony/issues/50)):
|
||||||
|
|
||||||
|
```text
|
||||||
|
🧭 needs-ruling — <the decision, one line>
|
||||||
|
Options: A — <one clause> B — <one clause>
|
||||||
|
Recommend: A, because <one clause>.
|
||||||
|
Blocked: <what stops; what continues meanwhile>
|
||||||
|
Default: <A at 2026-07-23T21:00Z if no ruling> | none — hard block
|
||||||
|
<details><summary>Analysis</summary>…everything else…</details>
|
||||||
|
```
|
||||||
|
|
||||||
|
The options must be exhaustive and mutually exclusive; more than three means
|
||||||
|
the question is not ready. `Recommend:` is mandatory — omitting it hands the
|
||||||
|
whole problem to the human. `Blocked:` names both what stops and what
|
||||||
|
continues. Write a timed `Default:` only when you are affirmatively confident
|
||||||
|
the decision is reversible inside the PR before merge. Unsure is not a tie:
|
||||||
|
it is a hard block. Published artifacts, secrets, prod, and org policy are
|
||||||
|
hard blocks by construction ([#50 D12–D13](https://github.com/heavy-duty/ceremony/issues/50)).
|
||||||
|
|
||||||
|
The ladder is anchored to the current episode's `needs-ruling` **`labeled`
|
||||||
|
event**, not its `Default:` deadline or the last activity
|
||||||
|
([#50 D13–D14](https://github.com/heavy-duty/ceremony/issues/50)):
|
||||||
|
|
||||||
|
- **0–12h:** proceed when a still-clear, reversible default expires, and say
|
||||||
|
out loud that you did. A hard block waits.
|
||||||
|
- **at 12h:** do not fire a stale default. Re-read it against what has landed
|
||||||
|
and ask whether it still holds and whether reasonable doubt remains. If
|
||||||
|
doubt has appeared, make it a hard block.
|
||||||
|
- **at 24h:** proceed regardless, **as a PR**. Pick an option and state in the
|
||||||
|
PR body which way you went and what doubt remains. Nothing merges by this;
|
||||||
|
the human still gates the merge.
|
||||||
|
- **past 24h:** hand the choice to triage. Triage picks the option, records it
|
||||||
|
as a decision, and remains accountable; the operator can overturn it at
|
||||||
|
merge.
|
||||||
|
|
||||||
|
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
|
||||||
|
different from the 7-day nudge, which resets on real activity. The machine
|
||||||
|
observes both clocks but never sets, clears, or decides `needs-ruling`.
|
||||||
|
|
||||||
|
The label stays until agreement is *reached*, not until the maintainer
|
||||||
|
replies. The setter records the ruling, removes the label, and returns the
|
||||||
|
item to its flow in the same comment ([LABELS.md](LABELS.md)).
|
||||||
|
|
||||||
## Handoff
|
## Handoff
|
||||||
|
|
||||||
|
|
@ -72,5 +215,6 @@ this is a release PR) — hand it to the human, in order:
|
||||||
|
|
||||||
The label write is optimistic — the reconciler validates it, and takes it
|
The label write is optimistic — the reconciler validates it, and takes it
|
||||||
back if the PR is not actually mergeable-right-now. Then stop: the PR is the
|
back if the PR is not actually mergeable-right-now. Then stop: the PR is the
|
||||||
human's. Address what comes back (`state:addressing`) and re-hand-off the
|
human's. The claim is now parked as shape 4 (Picking, above) — the handoff
|
||||||
same way.
|
you just posted is its declaration, and your build slot is free. Address
|
||||||
|
what comes back (`state:addressing`) and re-hand-off the same way.
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ the labels workflow's bootstrap dispatch (issue #10).
|
||||||
|
|
||||||
Two state machines share the taxonomy: the **PR machine** (proven in
|
Two state machines share the taxonomy: the **PR machine** (proven in
|
||||||
box/rig/cast, reconciled by machinery) and the **issue flow** (the
|
box/rig/cast, reconciled by machinery) and the **issue flow** (the
|
||||||
triage → build queue, doctrine-enforced today, machinery to follow —
|
triage → build queue, reconciled by the work-queue sweep). One rule joins
|
||||||
issue #18). One rule joins everything: **states are machine-owned, intent
|
everything: **states are machine-owned, intent
|
||||||
labels are hand-set** — a hand-moved state label is a lie waiting to happen,
|
labels are hand-set** — a hand-moved state label is a lie waiting to happen,
|
||||||
and the reconciler recomputes it from GitHub's own facts.
|
and the reconciler recomputes it from GitHub's own facts.
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ and the reconciler recomputes it from GitHub's own facts.
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `state:building` | `#FBCA04` | the builder — PR is a draft |
|
| `state:building` | `#FBCA04` | the builder — PR is a draft |
|
||||||
| `state:bots-reviewing` | `#1D76DB` | the reviewer panel to finish the round (a request is live) |
|
| `state:bots-reviewing` | `#1D76DB` | the reviewer panel to finish the round (a request is live) |
|
||||||
| `state:addressing` | `#D93F0B` | the builder — round complete without full approval, or nobody was asked, or a blocker is up |
|
| `state:addressing` | `#D93F0B` | the builder — round complete without full approval, or nobody was asked, or a blocker is up, or a ruling is pending |
|
||||||
| `state:needs-human` | `#8250DF` | the human — **this PR could be merged right now**: zero blockers, whole panel approved the current head |
|
| `state:needs-human` | `#8250DF` | the human — **this PR could be merged right now**: zero blockers, whole panel approved the current head |
|
||||||
|
|
||||||
`bots-reviewing` vs `addressing` is deliberate: staleness in the first means
|
`bots-reviewing` vs `addressing` is deliberate: staleness in the first means
|
||||||
|
|
@ -54,11 +54,11 @@ strips it on sight).
|
||||||
| `blocked` | `#6A737D` | waiting on another issue or PR (`Blocked by #N` in the body names it) | triage; anyone may correct it |
|
| `blocked` | `#6A737D` | waiting on another issue or PR (`Blocked by #N` in the body names it) | triage; anyone may correct it |
|
||||||
| `epic` | `#5319E7` | organizes other issues via a dependency-ordered task list; **builders never pick an epic** | triage |
|
| `epic` | `#5319E7` | organizes other issues via a dependency-ordered task list; **builders never pick an epic** | triage |
|
||||||
|
|
||||||
The invariant a board scan relies on: every open issue is either
|
The work-queue sweep enforces the invariant a board scan relies on: every open issue is either
|
||||||
`needs-triage`, `epic`, or carries exactly one of `ready` / `claimed` /
|
`needs-triage`, `epic`, or carries exactly one of `ready` / `claimed` /
|
||||||
`blocked`. A `claimed` issue with no open PR and no activity is what the
|
`blocked`. It flags conflicts rather than guessing intent. A `claimed` issue
|
||||||
staleness sweep will reclaim (issue #18); until that machinery exists,
|
with no open PR and no activity for 48 hours is reclaimed by the sweep: it
|
||||||
[TRIAGE.md](TRIAGE.md) owns the hygiene by hand.
|
comments, unassigns the stale owner, and restores `ready`.
|
||||||
|
|
||||||
## Cross-cutting (PRs and issues)
|
## Cross-cutting (PRs and issues)
|
||||||
|
|
||||||
|
|
@ -66,21 +66,117 @@ staleness sweep will reclaim (issue #18); until that machinery exists,
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `stale` | `#B60205` | no activity for 48h — sweep-managed, never hand-applied |
|
| `stale` | `#B60205` | no activity for 48h — sweep-managed, never hand-applied |
|
||||||
| `blocked` | `#6A737D` | (see above — same label serves PRs waiting on another PR/issue; legitimately quiet, the staleness sweep skips it) |
|
| `blocked` | `#6A737D` | (see above — same label serves PRs waiting on another PR/issue; legitimately quiet, the staleness sweep skips it) |
|
||||||
|
| `offsite` | `#CFD3D7` | issue deliverable is a PR in another repository; set by the builder with the draft link and cleared by the builder at handoff |
|
||||||
|
| `needs-ruling` | `#D4C5F9` | a human-owned decision is required; use BUILDER.md's ruling template and ladder. Set by triage or the builder; a state, not a signal — it clears on agreement, not on a reply |
|
||||||
|
| `attention` | `#D93F0B` | issue-only demand parked for the assignee; hand-set, and never written by the machine |
|
||||||
| `release` | `#0E8A16` | release flow, versioning, packaging work — and the ceremony PR itself |
|
| `release` | `#0E8A16` | release flow, versioning, packaging work — and the ceremony PR itself |
|
||||||
| `merge-next` | `#0E8A16` | head of the merge queue — merge this one next. Queue order is *intent*: never set by the reconciler, only cleared by it |
|
| `merge-next` | `#0E8A16` | head of the merge queue — merge this one next. Queue order is *intent*: never set by the reconciler, only cleared by it |
|
||||||
|
|
||||||
|
`needs-ruling` marks where the human's turn is when the pending thing is a
|
||||||
|
*decision*, not a merge ([#50 D1–D14](https://github.com/heavy-duty/ceremony/issues/50)).
|
||||||
|
It applies to any human-owned decision — org policy, published artifacts,
|
||||||
|
secrets, prod, or any choice whose cost lands outside the work. A panel
|
||||||
|
deadlock is one instance, not the definition (D11). It is not
|
||||||
|
`state:needs-human`: that label means exactly "this PR could be merged right
|
||||||
|
now", and the retired `state:needs-rebase` is the family's proof that a
|
||||||
|
label meaning two things lies about both. It is not a `blocker:*` either:
|
||||||
|
every blocker names work the *builder* owes, a ruling is owed by the human —
|
||||||
|
and the flag must live on issues too, where blockers do not exist. On issues
|
||||||
|
it coexists with the queue labels (the one-of-three invariant above ignores
|
||||||
|
it); its color is the light shade of `state:needs-human`'s, so the human
|
||||||
|
axis reads as one family. It is a state, not a signal: set only with the
|
||||||
|
[canonical escalation contract](BUILDER.md#the-ruling-ask) (D12). A bare
|
||||||
|
flag is noise. The comment carries exhaustive, mutually exclusive options
|
||||||
|
(at most three), a mandatory recommendation, what stops and what continues,
|
||||||
|
and either a default affirmatively known to be reversible inside the PR or
|
||||||
|
`none — hard block`. Unsure is a block; published artifacts, secrets, prod,
|
||||||
|
and org policy are hard blocks by construction (D13).
|
||||||
|
|
||||||
|
The ruling ladder runs from the current episode's `needs-ruling` **`labeled`
|
||||||
|
event** (D13–D14):
|
||||||
|
|
||||||
|
- **0–12h:** a clear, reversible decision may proceed when its stated default
|
||||||
|
expires, saying out loud that it did; anything with reasonable doubt waits
|
||||||
|
as a hard block.
|
||||||
|
- **at 12h:** the setter re-reads the default against what has landed and asks
|
||||||
|
whether it still holds and whether doubt remains. A stale default does not
|
||||||
|
fire; new doubt makes it a hard block.
|
||||||
|
- **at 24h:** the builder proceeds regardless, **as a PR**, stating the option
|
||||||
|
chosen and the doubt that remains. Nothing merges by this; the human still
|
||||||
|
gates the merge.
|
||||||
|
- **past 24h:** triage picks the option, records it as a decision, and remains
|
||||||
|
accountable. The operator may overturn it at merge.
|
||||||
|
|
||||||
|
A re-flag starts a new ladder. The rungs apply whatever `Default:` says,
|
||||||
|
including a hard block. Active discussion still climbs the ladder; by
|
||||||
|
contrast, the separate 7-day nudge resets on real activity. The machine
|
||||||
|
observes the rungs but never sets, clears, or decides `needs-ruling`.
|
||||||
|
|
||||||
|
The flag stays up until agreement is *reached* — a human reply alone does not
|
||||||
|
clear it — and its setter closes it out: records the ruling as a decision in
|
||||||
|
one comment, removes the label, and returns the item to its flow in that same
|
||||||
|
comment, never as a side effect. If the human disagrees that agreement was
|
||||||
|
reached, the label goes back on. The reconciler refuses `state:needs-human`
|
||||||
|
while it stands (the PR falls to `state:addressing` — the ball on the PR is
|
||||||
|
the builder's, who carries the ruling in), and the staleness sweep skips it,
|
||||||
|
because waiting on a human is legitimately quiet. Quiet, but not unwatched
|
||||||
|
(#52, both surfaces): a flag set with no escalation comment from its setter
|
||||||
|
is called out by the sweep — comment-only, scoped to the labeled event, the
|
||||||
|
label never removed — and a ruling with no real activity for 7 days draws a
|
||||||
|
comment-only nudge addressed to the decider, linking the escalation. The
|
||||||
|
nudge carries no marker on purpose: the comment is itself activity, so it
|
||||||
|
resets its own window and never repeats within a quiet week. Label churn is
|
||||||
|
not activity — the clock reads comments, reviews and commits, or the sweep
|
||||||
|
would reset itself.
|
||||||
|
|
||||||
|
`offsite` is issue-only and records that a claimed issue's deliverable lives
|
||||||
|
in another repository, where a closing reference cannot make a local open PR
|
||||||
|
visible to the sweep (#68). The builder sets it in the same step that posts
|
||||||
|
the cross-repo draft link, then clears it at handoff in the same comment that
|
||||||
|
reports whether that PR merged or closed. The machine reads the flag and
|
||||||
|
never writes it. It stops only the claim-reclaim clock: missing assignees are
|
||||||
|
still flagged, queue-label conflicts and missing queue state are still
|
||||||
|
repaired, and epic-completion and PR-side stale behavior are unchanged. The
|
||||||
|
sweep tells the assignee once when every visible cross-referenced PR has
|
||||||
|
closed; it only tells, and never clears the flag or changes the claim.
|
||||||
|
|
||||||
|
`attention` is issue-only and says a demand is parked on an issue for its
|
||||||
|
assignee. Anyone who needs that assignee's hands — triage, the operator, or a
|
||||||
|
sibling agent — sets it. The assignee alone clears it, as the first act of
|
||||||
|
pickup together with a short comment; that removal is the acknowledgement
|
||||||
|
and re-arms the flag for the next demand. If the session dies before the ack,
|
||||||
|
the still-visible flag launches the next pickup instead. An unanswered flag
|
||||||
|
is auditable evidence on the board.
|
||||||
|
|
||||||
|
The flag is additive: it composes with `ready`, `claimed`, or `blocked` and
|
||||||
|
with `needs-ruling`, and never substitutes for queue state. It pauses no
|
||||||
|
clock. Unlike `offsite` and `needs-ruling`, which make silence legitimate,
|
||||||
|
unanswered `attention` is exactly the silence the 48-hour reclaim should
|
||||||
|
take. It is hand-set doctrine only: nothing in `actions/` sets, clears,
|
||||||
|
reads, or validates it, and no reconciler enforces the assignee requirement.
|
||||||
|
An `attention` issue without an assignee is therefore a board bug, not a
|
||||||
|
demand; anyone may assign it or remove the flag.
|
||||||
|
|
||||||
|
The three signals are mutually distinct: `attention` means an assignee owes
|
||||||
|
a move; `needs-ruling` means a human owes a decision under
|
||||||
|
[the escalation contract and ladder](BUILDER.md#the-ruling-ask); and a bare
|
||||||
|
`@`-mention is an FYI that demands nothing and remains perfectly fine. A
|
||||||
|
demand that is itself a human decision carries `needs-ruling`, never both.
|
||||||
|
This distinction records the
|
||||||
|
[#16 missed-ruling incident](https://github.com/heavy-duty/ceremony/issues/16#issuecomment-5061051198)
|
||||||
|
and why the rejected mention poll is not returning: ordinary thread traffic
|
||||||
|
re-arms mentions, but only the writer can declare that a move is owed (#83).
|
||||||
|
|
||||||
## Scope — which surface? (PRs and issues, any number)
|
## Scope — which surface? (PRs and issues, any number)
|
||||||
|
|
||||||
All scopes share one calm color, `#C5DEF5` — scopes locate, states alert. The
|
All scopes share one calm color, `#C5DEF5` — scopes locate, states alert. The
|
||||||
set is per-repo (`.github/labels.conf`); PRs get theirs from changed paths via
|
set is per-repo: PRs get theirs from changed paths via actions/labeler, issues
|
||||||
actions/labeler, issues get theirs from triage. This repo's set:
|
get theirs from triage. This file never enumerates a set — it is mirrored
|
||||||
|
byte-identically into every governed repo, and any list it carried would be
|
||||||
| Label | Covers |
|
true in one repo and false in the rest (#104). The set for the repo you are
|
||||||
|---|---|
|
standing in lives in the two places that are true wherever you read them: its
|
||||||
| `scope:release-flow` | the reusable release workflow, decide, the doors |
|
`.github/labels.conf` (the definitions, one `name|color|description` row per
|
||||||
| `scope:guards` | changelog-armed / changelog-monotonic / drill-recorded |
|
scope) and its own `CONTRIBUTING.md`, beside the other repo-specific facts.
|
||||||
| `scope:labels` | the labels workflow, reconciler, this taxonomy |
|
|
||||||
| `scope:docs` | README doctrine, CONSUMERS.md, the role files |
|
|
||||||
|
|
||||||
## Issue types
|
## Issue types
|
||||||
|
|
||||||
|
|
@ -92,7 +188,8 @@ on a PR would say the same thing twice and drift.
|
||||||
|
|
||||||
The labels workflow (issue #10) recomputes PR state statelessly on PR events
|
The labels workflow (issue #10) recomputes PR state statelessly on PR events
|
||||||
plus a 15-minute advisory cron, and bootstraps this taxonomy idempotently on
|
plus a 15-minute advisory cron, and bootstraps this taxonomy idempotently on
|
||||||
manual dispatch. Issue-flow labels are doctrine-owned until #18 lands
|
manual dispatch. The sweep warns when the core taxonomy declares a label the
|
||||||
machinery for them. Default GitHub labels (`duplicate`, `invalid`,
|
repository lacks. The same workflow reconciles issue-flow labels on issue
|
||||||
`question`, `wontfix`, `help wanted`, `good first issue`) are deleted at
|
events and during the scheduled sweep. Default GitHub labels (`duplicate`,
|
||||||
bootstrap — a `question` is a discussion, not an issue.
|
`invalid`, `question`, `wontfix`, `help wanted`, `good first issue`) are
|
||||||
|
deleted at bootstrap — a `question` is a discussion, not an issue.
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,10 @@ The machine reads only your **verdict**; humans read your reasons.
|
||||||
|
|
||||||
In order of authority:
|
In order of authority:
|
||||||
|
|
||||||
1. **The issue's acceptance criteria** — the PR's `Closes #N` names your
|
1. **The issue's acceptance criteria** — the PR's `Closes #N`, or its
|
||||||
spec. Check every criterion; a PR that ships less than the issue says is
|
cross-repo `Part of <owner>/<repo>#N`, names your spec. Check every
|
||||||
a request-changes even if the code is beautiful.
|
criterion; a PR that ships less than the issue says is a request-changes
|
||||||
|
even if the code is beautiful.
|
||||||
2. **The repo's load-bearing constraints** — the rules bought with
|
2. **The repo's load-bearing constraints** — the rules bought with
|
||||||
incidents (in ceremony itself: issue #1's constraint list; in a governed
|
incidents (in ceremony itself: issue #1's constraint list; in a governed
|
||||||
repo: its own CONTRIBUTING plus ceremony's README). A change that
|
repo: its own CONTRIBUTING plus ceremony's README). A change that
|
||||||
|
|
@ -40,6 +41,22 @@ In order of authority:
|
||||||
test settles what a comment thread can't. A review that says "I ran X and
|
test settles what a comment thread can't. A review that says "I ran X and
|
||||||
saw Y" outranks one that says "this looks like it might".
|
saw Y" outranks one that says "this looks like it might".
|
||||||
|
|
||||||
|
## Where you review
|
||||||
|
|
||||||
|
- **A review request on you is your authorization** in any `heavy-duty` repo
|
||||||
|
and on any fleet member's fork. You need no separate permission and do not
|
||||||
|
wait for the repo to appear on a list: review is reversible
|
||||||
|
read-plus-comment work, and the requester already decided it should happen.
|
||||||
|
- **A request is authorization, not panel membership.** Convergence is
|
||||||
|
measured against the target repo's `panel=` roster minus the author. If you
|
||||||
|
are requested off-panel, post the verdict anyway and say in its body that
|
||||||
|
it is advisory; neither your silence nor your request-changes is a gate the
|
||||||
|
reconciler enforces. The nine-hour wait for kimi's off-panel verdict on
|
||||||
|
rig#112 showed why authorization and membership must not be conflated.
|
||||||
|
- **Being requested is a wake condition of its own.** It is how work in a
|
||||||
|
repo you have never heard of reaches you; a repo list finds only work in
|
||||||
|
repos somebody thought to list.
|
||||||
|
|
||||||
## What you do not do
|
## What you do not do
|
||||||
|
|
||||||
- **Re-litigate the spec.** The issue's decisions were made in triage and,
|
- **Re-litigate the spec.** The issue's decisions were made in triage and,
|
||||||
|
|
@ -64,7 +81,16 @@ saw Y" outranks one that says "this looks like it might".
|
||||||
- Convergence = every panel verdict approves the current head, no
|
- Convergence = every panel verdict approves the current head, no
|
||||||
`blocker:*` standing. Then the builder hands off (`state:needs-human`) and
|
`blocker:*` standing. Then the builder hands off (`state:needs-human`) and
|
||||||
the panel's job is done.
|
the panel's job is done.
|
||||||
- If a round exposes a disagreement **within the panel**, argue it in the PR
|
- Flag an unowned decision when it belongs to a human: org policy, published
|
||||||
with evidence until one side concedes or the builder escalates to the
|
artifacts, secrets, prod, or any choice whose cost lands outside the PR. A
|
||||||
maintainer for a ruling. Two reviewers pulling a builder in opposite
|
disagreement within the panel is one instance, not the definition
|
||||||
directions without resolution is a panel failure, not a builder failure.
|
([#50 D11](https://github.com/heavy-duty/ceremony/issues/50)). Argue a
|
||||||
|
panel disagreement in the PR with evidence until one side concedes or the
|
||||||
|
builder escalates; two reviewers pulling a builder in opposite directions
|
||||||
|
without resolution is a panel failure, not a builder failure.
|
||||||
|
`needs-ruling` is set by the **builder**, never by you: one accountable
|
||||||
|
flag-setter per PR hands the human one consolidated question. State the
|
||||||
|
unowned decision precisely enough for the builder to write
|
||||||
|
[the canonical ruling ask](BUILDER.md#the-ruling-ask), including what
|
||||||
|
stops and what continues ([#50 D12](https://github.com/heavy-duty/ceremony/issues/50);
|
||||||
|
[LABELS.md](LABELS.md)).
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,33 @@ is the failure this whole flow exists to prevent.
|
||||||
answers would let you write the issue — then stop and wait. Do not mint an
|
answers would let you write the issue — then stop and wait. Do not mint an
|
||||||
issue that carries the ambiguity forward; that just moves your job onto
|
issue that carries the ambiguity forward; that just moves your job onto
|
||||||
the builder.
|
the builder.
|
||||||
3. **Escalate.** The blocker is a *decision* only a human owns — scope,
|
3. **Escalate.** The pending thing is a decision only a human owns — org
|
||||||
money, product direction, breaking a public contract. Say precisely what
|
policy, published artifacts, secrets, prod, or any choice whose cost lands
|
||||||
the decision is, list the options with your recommendation, and name the
|
outside the work. A panel deadlock is one instance, not the definition
|
||||||
decider. The discussion is where humans decide; wait there.
|
([#50 D11](https://github.com/heavy-duty/ceremony/issues/50)). Say
|
||||||
|
precisely what the decision is, name the decider, and use
|
||||||
|
[BUILDER.md's canonical ruling template](BUILDER.md#the-ruling-ask),
|
||||||
|
including its options, recommendation, blocked/continues statement, and
|
||||||
|
reversible-only default rules ([#50 D12–D13](https://github.com/heavy-duty/ceremony/issues/50)).
|
||||||
|
The discussion is where humans decide; wait there. When the decision
|
||||||
|
blocks something already on the board — an existing issue, or minted work
|
||||||
|
a discussion's ruling gates — set `needs-ruling` on it too, so the board
|
||||||
|
shows where the human's turn is; the issue keeps its queue label.
|
||||||
|
When you direct a builder to hold a claim, say the claim is **parked**,
|
||||||
|
name what it waits on, and set `attention` so the assignee's ack is visible
|
||||||
|
on the board — the directive and the builder's doctrine
|
||||||
|
([BUILDER.md](BUILDER.md#claiming)) must use one word.
|
||||||
|
Past 24 hours from the current episode's `labeled` event, if the ruling
|
||||||
|
still stands and doubt remains, it is triage's duty to pick the option the
|
||||||
|
builder proceeds on, record that pick as a decision, and stay accountable
|
||||||
|
for it; the operator may overturn it at merge
|
||||||
|
([#50 D13–D14](https://github.com/heavy-duty/ceremony/issues/50)). You set
|
||||||
|
the flag, so you also close it out ([LABELS.md](LABELS.md)): judge when
|
||||||
|
agreement is reached, record the ruling as a decision in one comment,
|
||||||
|
remove the label, and return the issue to its flow in that same comment;
|
||||||
|
when that ruling or any directive or answered builder question delivers
|
||||||
|
the assignee's next move in prose, set `attention` in the same comment.
|
||||||
|
This is not a substitute for minting work or for `needs-ruling`.
|
||||||
4. **Decline.** Real idea, wrong repo or wrong time. Say why plainly, link
|
4. **Decline.** Real idea, wrong repo or wrong time. Say why plainly, link
|
||||||
where it belongs if anywhere, close. A refusal with reasons is a good
|
where it belongs if anywhere, close. A refusal with reasons is a good
|
||||||
outcome; a zombie discussion is not.
|
outcome; a zombie discussion is not.
|
||||||
|
|
@ -58,7 +81,9 @@ Every issue you mint carries, in this order:
|
||||||
the builder's definition of done and the reviewer's review spec, verbatim.
|
the builder's definition of done and the reviewer's review spec, verbatim.
|
||||||
- **Test plan**: what proves it, including the cases that must fail.
|
- **Test plan**: what proves it, including the cases that must fail.
|
||||||
- **Dependencies**: `Blocked by #N` / `Blocks #N`, and `Part of #E` when an
|
- **Dependencies**: `Blocked by #N` / `Blocks #N`, and `Part of #E` when an
|
||||||
epic organizes it.
|
epic organizes it. Name a cross-repo dependency the same way with its
|
||||||
|
repository qualified (`Blocked by repo#N` or `owner/repo#N`); the sweep
|
||||||
|
cannot resolve it, so triage verifies it and flips the issue by hand.
|
||||||
- **Labels**: type (`bug`/`enhancement`/`documentation`), `scope:*`, and
|
- **Labels**: type (`bug`/`enhancement`/`documentation`), `scope:*`, and
|
||||||
exactly one of `ready` / `blocked` (see [LABELS.md](LABELS.md)).
|
exactly one of `ready` / `blocked` (see [LABELS.md](LABELS.md)).
|
||||||
|
|
||||||
|
|
@ -75,13 +100,16 @@ dependency-ordered task list of child issues. Children reference the epic;
|
||||||
the epic's checklist is the progress view. Builders never pick the epic
|
the epic's checklist is the progress view. Builders never pick the epic
|
||||||
itself. Keep the checklist current — a stale epic misleads every scan.
|
itself. Keep the checklist current — a stale epic misleads every scan.
|
||||||
|
|
||||||
## Backlog hygiene (yours until #18 automates it)
|
## Backlog hygiene
|
||||||
|
|
||||||
- **Dedup before minting** — search issues *and* closed issues; extend or
|
- **Dedup before minting** — search issues *and* closed issues; extend or
|
||||||
reopen before duplicating.
|
reopen before duplicating.
|
||||||
- **Flip `blocked` → `ready`** when the named dependency lands.
|
- The issue-flow sweep flips `blocked` → `ready` when every named dependency
|
||||||
- **Reclaim abandoned claims**: `claimed` + no open PR + no activity →
|
lands, and flags a blocked issue whose dependency declaration is unreadable.
|
||||||
comment, unassign, restore `ready`.
|
- The sweep reclaims abandoned claims after 48 hours: `claimed` + no open PR
|
||||||
|
+ no activity → comment, unassign, restore `ready`.
|
||||||
|
- Automation never guesses intent. Resolve the conflict comments it leaves on
|
||||||
|
malformed queue states, and close or extend completed epics when nudged.
|
||||||
- **Close obsolete issues** with the reason and a link to what obsoleted
|
- **Close obsolete issues** with the reason and a link to what obsoleted
|
||||||
them. Every label on every open issue stays true; the board is only worth
|
them. Every label on every open issue stays true; the board is only worth
|
||||||
scanning if it does not lie.
|
scanning if it does not lie.
|
||||||
|
|
|
||||||
2
.github/DISCUSSION_TEMPLATE/ideas.yml
vendored
2
.github/DISCUSSION_TEMPLATE/ideas.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
# Copied from heavy-duty/ceremony@0.1.0 .github/DISCUSSION_TEMPLATE/ideas.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
# Copied from heavy-duty/ceremony@0.2.0 .github/DISCUSSION_TEMPLATE/ideas.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
||||||
# Light on purpose: discussions are where ambiguity is ALLOWED — a form
|
# Light on purpose: discussions are where ambiguity is ALLOWED — a form
|
||||||
# that demands rigor at the door defeats the room's purpose (heavy-duty/ceremony#24,
|
# that demands rigor at the door defeats the room's purpose (heavy-duty/ceremony#24,
|
||||||
# decision 4). If these prompts fight the flow in practice, delete them
|
# decision 4). If these prompts fight the flow in practice, delete them
|
||||||
|
|
|
||||||
2
.github/DISCUSSION_TEMPLATE/q-a.yml
vendored
2
.github/DISCUSSION_TEMPLATE/q-a.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
# Copied from heavy-duty/ceremony@0.1.0 .github/DISCUSSION_TEMPLATE/q-a.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
# Copied from heavy-duty/ceremony@0.2.0 .github/DISCUSSION_TEMPLATE/q-a.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
||||||
# Light on purpose — same reasoning as ideas.yml (heavy-duty/ceremony#24, decision 4):
|
# Light on purpose — same reasoning as ideas.yml (heavy-duty/ceremony#24, decision 4):
|
||||||
# optional prompts only, delete before hardening.
|
# optional prompts only, delete before hardening.
|
||||||
body:
|
body:
|
||||||
|
|
|
||||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
# Copied from heavy-duty/ceremony@0.1.0 .github/ISSUE_TEMPLATE/config.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
# Copied from heavy-duty/ceremony@0.2.0 .github/ISSUE_TEMPLATE/config.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
||||||
# The new-issue interception (heavy-duty/ceremony#24, decision 1): interception over
|
# The new-issue interception (heavy-duty/ceremony#24, decision 1): interception over
|
||||||
# instruction — prose alone has already proven insufficient everywhere else
|
# instruction — prose alone has already proven insufficient everywhere else
|
||||||
# in this org. With blank issues disabled and exactly one form, a "New
|
# in this org. With blank issues disabled and exactly one form, a "New
|
||||||
|
|
|
||||||
2
.github/ISSUE_TEMPLATE/work-order.yml
vendored
2
.github/ISSUE_TEMPLATE/work-order.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
# Copied from heavy-duty/ceremony@0.1.0 .github/ISSUE_TEMPLATE/work-order.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
# Copied from heavy-duty/ceremony@0.2.0 .github/ISSUE_TEMPLATE/work-order.yml (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
||||||
# The issue contract (.ceremony/TRIAGE.md "The issue contract") as a form, so every
|
# The issue contract (.ceremony/TRIAGE.md "The issue contract") as a form, so every
|
||||||
# minted issue lands with the same bones and a later parser (heavy-duty/ceremony#18) can key on
|
# minted issue lands with the same bones and a later parser (heavy-duty/ceremony#18) can key on
|
||||||
# stable section headings. Consistency, not a gate: the form applies no
|
# stable section headings. Consistency, not a gate: the form applies no
|
||||||
|
|
|
||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- Copied from heavy-duty/ceremony@0.1.0 .github/pull_request_template.md (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
<!-- Copied from heavy-duty/ceremony@0.2.0 .github/pull_request_template.md (heavy-duty/ceremony#24). Hand-maintained: no guard checks this against ceremony.
|
||||||
Short on purpose: a template longer than a small PR gets deleted by
|
Short on purpose: a template longer than a small PR gets deleted by
|
||||||
reflex, not read (heavy-duty/ceremony#24). One issue, one PR — draft while building. -->
|
reflex, not read (heavy-duty/ceremony#24). One issue, one PR — draft while building. -->
|
||||||
|
|
||||||
|
|
|
||||||
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
|
|
@ -9,7 +9,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
# changelog-monotonic compares HEAD against the merge base; a
|
# changelog-monotonic and changelog-assembled compare HEAD against
|
||||||
|
# the merge base; a
|
||||||
# checkout that cannot resolve it is a hard failure in CI, not
|
# checkout that cannot resolve it is a hard failure in CI, not
|
||||||
# a skip (a guard that can quietly stop guarding is the failure
|
# a skip (a guard that can quietly stop guarding is the failure
|
||||||
# shape these checks exist to refuse).
|
# shape these checks exist to refuse).
|
||||||
|
|
@ -51,18 +52,21 @@ jobs:
|
||||||
#
|
#
|
||||||
# changelog-armed: the version-keyed arming rule (rig#66; the
|
# changelog-armed: the version-keyed arming rule (rig#66; the
|
||||||
# unconditional form rig#44 reverted — this is its correct return).
|
# unconditional form rig#44 reverted — this is its correct return).
|
||||||
- uses: heavy-duty/ceremony/actions/changelog-armed@0.1.0
|
- uses: heavy-duty/ceremony/actions/changelog-armed@0.2.0
|
||||||
# changelog-monotonic: no shipped heading deleted or duplicated
|
# changelog-monotonic: no shipped heading deleted or duplicated
|
||||||
# (#98, box#122). Strict by default: an unresolvable base ref is red,
|
# (#98, box#122). Strict by default: an unresolvable base ref is red,
|
||||||
# never a quiet skip — hence the fetch-depth: 0 above.
|
# never a quiet skip — hence the fetch-depth: 0 above.
|
||||||
- uses: heavy-duty/ceremony/actions/changelog-monotonic@0.1.0
|
- uses: heavy-duty/ceremony/actions/changelog-monotonic@0.2.0
|
||||||
|
# changelog-assembled: a release's stamped section must exactly match
|
||||||
|
# the fragments it consumed. Vacuous on non-release PRs.
|
||||||
|
- uses: heavy-duty/ceremony/actions/changelog-assembled@0.2.0
|
||||||
# drill-recorded: a release version carries drills/<version>.md
|
# drill-recorded: a release version carries drills/<version>.md
|
||||||
# (rig's drill meaning: drills/README.md). Vacuous on -dev trees.
|
# (rig's drill meaning: drills/README.md). Vacuous on -dev trees.
|
||||||
- uses: heavy-duty/ceremony/actions/drill-recorded@0.1.0
|
- uses: heavy-duty/ceremony/actions/drill-recorded@0.2.0
|
||||||
# docs-sync: the .ceremony/ doctrine mirror is byte-identical to the
|
# docs-sync: the .ceremony/ doctrine mirror is byte-identical to the
|
||||||
# pin read from release.yml (ceremony#19) — a hand edit or a
|
# pin read from release.yml (ceremony#19) — a hand edit or a
|
||||||
# half-done pin bump goes red here.
|
# half-done pin bump goes red here.
|
||||||
- uses: heavy-duty/ceremony/actions/docs-sync@0.1.0
|
- uses: heavy-duty/ceremony/actions/docs-sync@0.2.0
|
||||||
|
|
||||||
# The install LIFECYCLE against a tree install.sh itself produced — the four
|
# The install LIFECYCLE against a tree install.sh itself produced — the four
|
||||||
# beats box and cast already run in CI (#106): install from this checkout,
|
# beats box and cast already run in CI (#106): install from this checkout,
|
||||||
|
|
|
||||||
2
.github/workflows/labels.yml
vendored
2
.github/workflows/labels.yml
vendored
|
|
@ -15,4 +15,4 @@ permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
jobs:
|
jobs:
|
||||||
labels:
|
labels:
|
||||||
uses: heavy-duty/ceremony/.github/workflows/labels.yml@0.1.0
|
uses: heavy-duty/ceremony/.github/workflows/labels.yml@0.2.0
|
||||||
|
|
|
||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -17,6 +17,6 @@ permissions:
|
||||||
issues: write # --label on that fallback PR rides the issues API
|
issues: write # --label on that fallback PR rides the issues API
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
uses: heavy-duty/ceremony/.github/workflows/release.yml@0.1.0
|
uses: heavy-duty/ceremony/.github/workflows/release.yml@0.2.0
|
||||||
with:
|
with:
|
||||||
version-source: file
|
version-source: file
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue