0036: A release is promoted by a person, through five named checks that block only what would ship something wrong
- Status: Accepted (backfilled 2026-10-06: records a decision already built)
- Date: 2026-10-06
- Related: 0011 (Orion lands work on develop; the release is a different decision)
Contextβ
Orion lands work on develop without a person. Promoting develop to
main and publishing a release is different: it is public and hard to take
back, and whether to do it is the one decision the branch model reserves for
a person. "Thorough verification" means nothing as a gate unless the checks
are named, and a gate that refuses for everything trains people to bypass it.
Decisionβ
Five named checks (internal/promote), each from a real way a release
goes wrong. Anything that would publish something wrong blocks; anything
merely worth knowing warns:
| Check | |
|---|---|
| Every ticket in the version is Done | warns: unfinished tickets roll forward |
| Every shipped ticket has a release note, and notes and tickets agree | blocks on a Done ticket with no note; warns on the rest |
develop is green on the exact commit being promoted | blocks |
No pull requests are about to land on develop | blocks |
| Every commit in the range belongs to a ticket | warns: it fires on real work, and is meant to be looked at, not obeyed |
A ceremony, not a decision. orion release ship automates what happens
around the person's decision, in a fixed order where each step is a safe
place to stop: preflight, promotion pull request, CI, Slack approval, merge,
then tag, build and publish. Only the last two cannot be undone, which is
why they come last. Every step, including every refusal, is logged.
The watch cannot reach it, structurally rather than by a flag: the only
path to shipping is the release command, and orion watch runs work and
collect and nothing else. TestWatchHasNoPathToShipping pins it.
The publishing verb must be named. A bare orion release prints usage
and exits non-zero; ship publishes, and two more verbs stay reserved and
unwired, so a typo lands on usage, not on a public tag.
Consequencesβ
- A release is always a person's decision, with the evidence in front of them.
- Check 5 warns on most real releases; that is intended.
--betacuts a prerelease fromdevelopwith no promotion, and never publishes it where stable users upgrade from.
Alternatives rejectedβ
- Release from the watch when a milestone completes. An unattended loop must not be able to cut a public release.
- Block on every check. People learn to bypass a gate that refuses for everything.
- A CI workflow instead of a command. It would need personal access
tokens the operator's own authenticated
ghalready has.