docs: add proposal intake
All checks were successful
CI / test (pull_request) Successful in 3m49s
CI / release-exercise (pull_request) Successful in 25s
CI / self-guards (pull_request) Successful in 21s
CI / action-exercise (pull_request) Successful in 20s
CI / docs-sync-exercise (pull_request) Successful in 20s
labels / labels (pull_request) Successful in 22s
Refs guard / refs-not-closing (pull_request) Successful in 20s

This commit is contained in:
codex-bot-andresmgsl 2026-08-25 12:15:47 +00:00
parent 484eb79623
commit bb984de133
14 changed files with 89 additions and 82 deletions

View file

@ -1,19 +0,0 @@
# Light on purpose: discussions are where ambiguity is ALLOWED — a form
# that demands rigor at the door defeats the room's purpose (issue #24,
# decision 4). If these prompts fight the flow in practice, delete them
# before adding fields to them.
body:
- type: textarea
attributes:
label: What's the itch?
description: >-
Vague is fine — a bug, an idea, a "we should…". Triage turns this
into work (or an answer); you don't have to.
validations:
required: false
- type: textarea
attributes:
label: What would "done" feel like?
description: Optional — a sketch of the outcome, if you can already see it.
validations:
required: false

View file

@ -1,15 +0,0 @@
# Light on purpose — same reasoning as ideas.yml (issue #24, decision 4):
# optional prompts only, delete before hardening.
body:
- type: textarea
attributes:
label: What's the question?
description: Ask it plainly — context and links help, none are required.
validations:
required: false
- type: textarea
attributes:
label: What have you tried or read already?
description: Optional — saves the answerer a lap.
validations:
required: false

View file

@ -1,13 +1,12 @@
# The new-issue interception (issue #24, decision 1): interception over # The new-issue interception (issue #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
# issue" click shows the discussion link first; that auto-suggest is native # issue" click shows the proposal route first; that auto-suggest is native
# GitHub behavior, no automation needed. # forge behavior, no automation needed.
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Ideas, bugs, questions — start a Discussion - name: Ideas, bugs, questions — file a Proposal
url: https://github.com/heavy-duty/ceremony/discussions url: https://forgejo.heavyduty.builders/heavy-duty/ceremony/issues/new?template=proposal.yml
about: >- about: >-
Humans (and agents) never file issues here — discussions are where Anyone may file a proposal. Triage converts it into a work issue or
intent lives. Triage converges every discussion to an outcome, and refuses it with reasons; only triage mints work issues (TRIAGE.md).
only triage mints issues (TRIAGE.md).

34
.github/ISSUE_TEMPLATE/proposal.yml vendored Normal file
View file

@ -0,0 +1,34 @@
# This intake form applies no labels: queue labels are triage's explicit act
# (LABELS.md), and the issue-flow sweep catches non-triage authors, so the form
# must not pre-judge the proposal's queue state (#24 D2).
name: Proposal (anyone)
description: >-
Share an idea, bug, question, or rough "we should…" for triage to convert
into work or refuse with reasons.
body:
- type: markdown
attributes:
value: >-
Proposals are the low-bar intake door. Say what you noticed and why it
might matter; triage will decide whether it becomes a work issue.
- type: textarea
id: noticed
attributes:
label: What did you notice?
description: A rough idea, bug, question, or "we should…" is enough.
validations:
required: true
- type: textarea
id: why-it-matters
attributes:
label: Why might it matter?
description: Optional — describe the impact or opportunity if you can.
validations:
required: false
- type: textarea
id: known-context
attributes:
label: What do you already know?
description: Optional — add links, examples, constraints, or prior art.
validations:
required: false

View file

@ -6,8 +6,8 @@
# that (issue #24, decision 2). # that (issue #24, decision 2).
name: Work order (triage only) name: Work order (triage only)
description: >- description: >-
The issue contract (TRIAGE.md) as a form. Only triage mints issues — The issue contract (TRIAGE.md) as a form. Only triage mints work issues —
everyone else starts a Discussion. Triage may still compose by hand when everyone else files a proposal. Triage may still compose by hand when
the form fights it: `gh issue create --body-file` bypasses forms and stays the form fights it: `gh issue create --body-file` bypasses forms and stays
legitimate for the triage identity. legitimate for the triage identity.
body: body:
@ -25,7 +25,7 @@ body:
attributes: attributes:
label: Context label: Context
description: >- description: >-
Why this exists, with links — the discussion it came from, the code Why this exists, with links — the proposal it came from, the code
it touches (permalinks at a pinned SHA, so line references cannot it touches (permalinks at a pinned SHA, so line references cannot
rot), prior art in sibling repos. rot), prior art in sibling repos.
validations: validations:

View file

@ -14,7 +14,7 @@ reviewer here"). That one word is your whole onboarding:
| you are the… | read | your job in one line | | you are the… | read | your job in one line |
|---|---|---| |---|---|---|
| **triage** agent | [TRIAGE.md](TRIAGE.md) | turn discussions into buildable issues — or refuse well; you are the only door issues come through | | **triage** agent | [TRIAGE.md](TRIAGE.md) | turn proposals into buildable work issues — or refuse well; you are the only door work issues come through |
| **builder** agent | [BUILDER.md](BUILDER.md) | turn one `ready` issue into one PR that meets its acceptance criteria | | **builder** agent | [BUILDER.md](BUILDER.md) | turn one `ready` issue into one PR that meets its acceptance criteria |
| **reviewer** agent | [REVIEWER.md](REVIEWER.md) | verdicts on PRs — approve or request-changes, converge, hand to the human | | **reviewer** agent | [REVIEWER.md](REVIEWER.md) | verdicts on PRs — approve or request-changes, converge, hand to the human |
@ -23,7 +23,7 @@ are the shared state machine, and misusing one lies to every other agent on
the board. the board.
**Not told a role?** Infer it from the task: asked to review a PR → reviewer; **Not told a role?** Infer it from the task: asked to review a PR → reviewer;
asked to implement an issue → builder; asked to process discussions or the asked to implement an issue → builder; asked to process proposals or the
backlog → triage. Still ambiguous → ask before acting. Do not free-lance backlog → triage. Still ambiguous → ask before acting. Do not free-lance
across roles in one session: a builder reviewing its own PR, or a reviewer across roles in one session: a builder reviewing its own PR, or a reviewer
pushing fixes, breaks the separation the pipeline depends on. pushing fixes, breaks the separation the pipeline depends on.
@ -31,13 +31,13 @@ pushing fixes, breaks the separation the pipeline depends on.
## The pipeline you are part of ## The pipeline you are part of
``` ```
discussion ──▶ triage ──▶ issue ──▶ build ──▶ review ──▶ human merge ──▶ release proposal ──▶ triage ──▶ work issue ──▶ build ──▶ review ──▶ human merge ──▶ release
(anyone) (agent) (queue) (agent) (agents) (human) (ceremony) (anyone) (agent) (queue) (agent) (agents) (human) (ceremony)
``` ```
Two rules bind every role: Two rules bind every role:
- **Only triage mints issues.** Found work? Open or extend a discussion. - **Only triage mints work issues.** Found work? File or extend a proposal.
- **Only humans merge.** Convergence ends at `state:needs-human`, never at - **Only humans merge.** Convergence ends at `state:needs-human`, never at
a merge button. a merge button.

View file

@ -140,7 +140,7 @@ triage bug, and the move is to say so on the issue, not to guess.
its red-flag profile are in REVIEWER.md §What you review against, item 2 its red-flag profile are in REVIEWER.md §What you review against, item 2
(#216). (#216).
- **Scope discipline: the PR does the issue — whole, and nothing else.** - **Scope discipline: the PR does the issue — whole, and nothing else.**
Adjacent problems go to a discussion, or a comment on the relevant issue; Adjacent problems go to a proposal, or a comment on the relevant issue;
you do not mint issues — nobody but triage does — and you do not fix you do not mint issues — nobody but triage does — and you do not fix
drive-by findings in the same PR. drive-by findings in the same PR.

View file

@ -10,22 +10,22 @@ the two is a bug.
Work moves through one pipeline, and every stage has an owner: Work moves through one pipeline, and every stage has an owner:
``` ```
discussion ──▶ triage ──▶ issue ──▶ build ──▶ review ──▶ human merge ──▶ release proposal ──▶ triage ──▶ work issue ──▶ build ──▶ review ──▶ human merge ──▶ release
(anyone) (agent) (queue) (agent) (agents) (human) (ceremony) (anyone) (agent) (queue) (agent) (agents) (human) (ceremony)
``` ```
- **Discussions are where intent lives.** Anyone — human or agent — who has an - **Proposals are where intent lives.** Anyone — human or agent — who has an
idea, a bug, a question, or a "we should…" opens a **discussion**, not an idea, a bug, a question, or a "we should…" files a **proposal**, not a work
issue. Discussions are allowed to be vague; that is what they are for. issue. Proposals are allowed to be vague; that is what they are for.
- **Issues are minted only by triage.** Nobody else writes issues — not - **Work issues are minted only by triage.** Nobody else writes work issues —
humans, not builders, not reviewers. An issue is a work order with a quality not humans, not builders, not reviewers. A work issue is a work order with a quality
bar (the issue contract in [TRIAGE.md](TRIAGE.md)), and the bar holds bar (the issue contract in [TRIAGE.md](TRIAGE.md)), and the bar holds
because exactly one role is accountable for it. An issue that appears because exactly one role is accountable for it. An issue that appears
through any other door gets `needs-triage` and is normalized or converted through any other door gets `needs-triage` and is normalized or converted
back into a discussion. back into a proposal.
- **Builders turn one issue into one PR.** [BUILDER.md](BUILDER.md). - **Builders turn one issue into one PR.** [BUILDER.md](BUILDER.md).
- **Reviewers converge on a verdict.** [REVIEWER.md](REVIEWER.md). - **Reviewers converge on a verdict.** [REVIEWER.md](REVIEWER.md).
- **Humans decide twice**: in the discussion (what is worth doing, and any - **Humans decide twice**: in the proposal (what is worth doing, and any
call triage escalates back) and at the merge (whether it ships). Everything call triage escalates back) and at the merge (whether it ships). Everything
between those two points is agent work by default. between those two points is agent work by default.
- **Merging a release PR ships it** — the release ceremony this repo's - **Merging a release PR ships it** — the release ceremony this repo's
@ -62,7 +62,7 @@ panel-minus-author, and three is what it currently comes to, not a second
rule. Builders and triage default to different models so the issue contract rule. Builders and triage default to different models so the issue contract
is honestly exercised — a spec gap should surface as a question on the is honestly exercised — a spec gap should surface as a question on the
issue, not be silently filled by shared priors. Humans (`andres`) decide in issue, not be silently filled by shared priors. Humans (`andres`) decide in
discussions and merge; the roster is config, not doctrine — swapping a proposals and merge; the roster is config, not doctrine — swapping a
vendor is an edit to this table (and to `panel=` in vendor is an edit to this table (and to `panel=` in
`.github/labels.conf` once #10 lands), nothing more. `.github/labels.conf` once #10 lands), nothing more.
@ -143,7 +143,8 @@ A governed repo (box, rig, cast, incubator, …) therefore carries:
- the **`scope:*` label set** (`.github/labels.conf` + `.github/labeler.yml`), - the **`scope:*` label set** (`.github/labels.conf` + `.github/labeler.yml`),
- the **drill meaning** (`drills/README.md`), - the **drill meaning** (`drills/README.md`),
- the repo's own code conventions; - the repo's own code conventions;
- **Discussions enabled**, so the triage door exists. - **An intake door is open**: install the proposal form and `needs-triage`
flow, or use a forge-native intake surface.
One pin governs both the machinery and the doctrine: the ref a repo's One pin governs both the machinery and the doctrine: the ref a repo's
workflows call is the ref its `.ceremony/` mirror is verified against. workflows call is the ref its `.ceremony/` mirror is verified against.

View file

@ -136,7 +136,7 @@ The earlier form of this file folded handoff and rebase into the other
builder wakes; they are duties of their own. builder wakes; they are duties of their own.
- **Triage signals**, per registry repo: `needs-triage` issues, - **Triage signals**, per registry repo: `needs-triage` issues,
queue-unlabeled strays, discussions without triage's voice, unread queue-unlabeled strays, proposals without triage's voice, unread
`@`-mentions (their own session), and `blocked` issues whose named blockers `@`-mentions (their own session), and `blocked` issues whose named blockers
have all landed — a lead the session verifies, never a label the engine have all landed — a lead the session verifies, never a label the engine
flips. Backlog hygiene (stale claims, label invariants) runs hourly, flips. Backlog hygiene (stale claims, label invariants) runs hourly,

View file

@ -51,7 +51,7 @@ strips it on sight).
| Label | Color | Means | Set by | | Label | Color | Means | Set by |
|---|---|---|---| |---|---|---|---|
| `needs-triage` | `#FBCA04` | an issue that did not come through triage — it owes normalization or conversion back to a discussion | anyone who spots one; cleared by triage | | `needs-triage` | `#FBCA04` | a proposal or stray issue that did not come through triage — it owes normalization into work or a reasoned refusal | anyone who spots one; cleared by triage |
| `ready` | `#0E8A16` | triaged, spec complete, unblocked — a builder can start now and succeed | triage | | `ready` | `#0E8A16` | triaged, spec complete, unblocked — a builder can start now and succeed | triage |
| `claimed` | `#1D76DB` | a builder owns it: assignee set, a draft PR expected shortly | the claiming builder | | `claimed` | `#1D76DB` | a builder owns it: assignee set, a draft PR expected shortly | the claiming builder |
| `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 |
@ -242,4 +242,4 @@ full-board reconcile. The sweep warns when the core taxonomy declares a label
the repository lacks. The same workflow reconciles issue-flow labels on issue the repository lacks. The same workflow reconciles issue-flow labels on issue
events and during the scheduled sweep. Default GitHub labels (`duplicate`, events and during the scheduled sweep. Default GitHub labels (`duplicate`,
`invalid`, `question`, `wontfix`, `help wanted`, `good first issue`) are `invalid`, `question`, `wontfix`, `help wanted`, `good first issue`) are
deleted at bootstrap — a `question` is a discussion, not an issue. deleted at bootstrap — a `question` belongs in a proposal, not a work issue.

View file

@ -123,9 +123,9 @@ saw Y" outranks one that says "this looks like it might".
## 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,
above it, in a discussion where humans had their say. If you think the above it, in a proposal where humans had their say. If you think the
spec itself is wrong, say so with reasons — as a comment pointing at the spec itself is wrong, say so with reasons — as a comment pointing at the
discussion, while still reviewing the implementation against the spec as proposal, while still reviewing the implementation against the spec as
written. Spec changes go through triage, not through a review round. written. Spec changes go through triage, not through a review round.
- **Merge, or tell the builder to merge.** Convergence hands the PR to a - **Merge, or tell the builder to merge.** Convergence hands the PR to a
human; only humans merge. human; only humans merge.

View file

@ -1,22 +1,24 @@
# TRIAGE.md — the triage role # TRIAGE.md — the triage role
You are the only door issues come through. Humans and agents open **discussions**; You are the only door work issues come through. Humans and agents file
you decide what becomes work and set the quality builders and reviewers receive. **proposals**; you decide what becomes work and set the quality builders and
reviewers receive.
## Why this door exists ## Why this door exists
Discussions may be ambiguous; issues may not: a builder must be able to execute Proposals may be ambiguous; work issues may not: a builder must be able to
one **without asking anything**. One accountable role keeps builders from guessing. execute one **without asking anything**. One accountable role keeps builders
from guessing.
## Your inputs ## Your inputs
- **Every open discussion** in the repo you serve. - **Every open proposal** in the repo you serve.
- **Stray issues** — anything filed directly, by anyone. Label it - **Stray issues** — anything filed directly, by anyone. Label it
`needs-triage`, then either bring it up to contract (below) or convert its `needs-triage`, then either bring it up to contract (below) or convert its
substance back into a discussion and close it, saying why. Route the work substance into a proposal and close it, saying why. Route the work
without shaming the filer. without shaming the filer.
## For each discussion, converge on exactly one outcome ## For each proposal, converge on exactly one outcome
1. **Answer.** The question has an answer, the bug is not one, the idea is 1. **Answer.** The question has an answer, the bug is not one, the idea is
already shipped or tracked. Link the code, doc, or issue; mark answered. already shipped or tracked. Link the code, doc, or issue; mark answered.
@ -32,9 +34,9 @@ one **without asking anything**. One accountable role keeps builders from guessi
[BUILDER.md's canonical ruling template](BUILDER.md#the-ruling-ask), [BUILDER.md's canonical ruling template](BUILDER.md#the-ruling-ask),
including its options, recommendation, blocked/continues statement, and including its options, recommendation, blocked/continues statement, and
reversible-only default rules (#50 D12D13). reversible-only default rules (#50 D12D13).
The discussion is where humans decide; wait there. When the decision The proposal is where humans decide; wait there. When the decision
blocks something already on the board — an existing issue, or minted work 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 a proposal'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. 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**, 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 name what it waits on, and set `attention` so the assignee's ack is visible
@ -61,7 +63,7 @@ one **without asking anything**. One accountable role keeps builders from guessi
This is not a substitute for minting work or for `needs-ruling`. 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 proposal is not.
5. **Accept.** It justifies work → mint the issue(s). The contract below is 5. **Accept.** It justifies work → mint the issue(s). The contract below is
the bar. the bar.
@ -71,7 +73,7 @@ Every issue you mint carries, in this order:
- **A title that names the deliverable** — "lib/version.sh — one version - **A title that names the deliverable** — "lib/version.sh — one version
abstraction, two backends", never "improve version handling". abstraction, two backends", never "improve version handling".
- **Context**: why this exists, with links — the discussion it came from, - **Context**: why this exists, with links — the proposal it came from,
the code it touches (permalinks at a pinned SHA, so line references cannot the code it touches (permalinks at a pinned SHA, so line references cannot
rot), prior art in sibling repos. rot), prior art in sibling repos.
- **The spec**: decisions made, not options listed. If the spec still has an - **The spec**: decisions made, not options listed. If the spec still has an
@ -159,4 +161,4 @@ Repositories that adopt version epics follow [RELEASES.md](RELEASES.md).
- Assign a builder — builders pick and claim ([BUILDER.md](BUILDER.md)). - Assign a builder — builders pick and claim ([BUILDER.md](BUILDER.md)).
- Make the human's decisions (outcome 3 exists for those), or soften a - Make the human's decisions (outcome 3 exists for those), or soften a
refusal into a vague issue to avoid saying no. refusal into a vague issue to avoid saying no.
- Mint an issue to "discuss" something — that is a discussion. - Mint a work issue to explore an idea — file a proposal instead.

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

@ -0,0 +1,3 @@
### Changed
- Replace the unavailable intake rule with a proposal form that triage converts into work or refuses with reasons (#247).

View file

@ -851,15 +851,16 @@ published release.
## Adopting the agent team flow ## Adopting the agent team flow
The team flow (discussion → triage → issue → build → review → human The team flow (proposal → triage → work issue → build → review → human
merge) is **optional per repo and separable from the release ceremony**: merge) is **optional per repo and separable from the release ceremony**:
a repo can adopt release-only and take the team flow later — incubator's a repo can adopt release-only and take the team flow later — incubator's
initial posture (#16). The model is this repo's own initial posture (#16). The model is this repo's own
[CONTRIBUTING](../CONTRIBUTING.md) ("How the other repos use this"); [CONTRIBUTING](../CONTRIBUTING.md) ("How the other repos use this");
this is the checklist: this is the checklist:
- [ ] **Enable Discussions** — the triage door exists or the pipeline - [ ] **Open the intake door** — install `proposal.yml` and the automatic
has no intake. `needs-triage` flow. A repo whose forge provides Discussions may keep
them as its intake door and point `config.yml`'s contact link there.
- [ ] **Vendor the doctrine**: run `docs-sync --fix` (#19) to materialize - [ ] **Vendor the doctrine**: run `docs-sync --fix` (#19) to materialize
`.ceremony/{AGENTS,TRIAGE,BUILDER,REVIEWER,LABELS}.md` `.ceremony/{AGENTS,TRIAGE,BUILDER,REVIEWER,LABELS}.md`
byte-identical to this repo at the pinned ref — plus the generated byte-identical to this repo at the pinned ref — plus the generated
@ -893,7 +894,8 @@ this is the checklist:
`workflow_dispatch` once ([above](#labels-automation)), or the hand `workflow_dispatch` once ([above](#labels-automation)), or the hand
commands in [LABELS.md](../LABELS.md). commands in [LABELS.md](../LABELS.md).
- [ ] **State the single-writer rule** in the repo's own docs: only - [ ] **State the single-writer rule** in the repo's own docs: only
triage mints issues; everyone else opens discussions. triage mints work issues; anyone may file a proposal, which triage
converts or refuses.
### The pin-bump procedure ### The pin-bump procedure