ADR 0042 — the approval is the checkpoint, not the second pair of hands
§2 said "never merge your own", written for people. Applied to an agent it produced a contradiction that surfaced immediately: an agent asked to merge cannot merge, because it authored what it is being asked to merge. So every merge here was either performed by the thing that wrote it, or not performed. Rejected the literal reading, because an operator clicking merge dozens of times without reading is not a checkpoint — it is the SHAPE of one, which is worse, since the record then claims a review that did not happen. Rejected dropping the rule, because the failure it prevents is not one an agent is less prone to. So the rule names what the checkpoint actually is: a person deciding, not a person clicking. Work may be merged by whoever wrote it once a human has explicitly approved that merge. What "explicit" excludes is the half that can rot, so it is enumerated: a standing permission cited forever, an instruction to do the work read as approval to merge it, silence, and the author's own judgement that it is ready. This narrows rather than relaxes. The obligation moves from who performs the merge to whether a person decided — a higher bar in the case the old wording permits, where a reviewer merges someone else's work without reading it. Synced, and verified by reading the rule back out of the live page rather than by trusting the publish.
This commit is contained in:
@@ -41,7 +41,7 @@ incident behind it is not written down, and the fix is to write it down, not to
|
|||||||
| **Never bypass the pipeline** | No manual database edit, no manual restart as a workaround. Fix the cause and deploy. A workaround that works is a workaround that is never removed, and the next person cannot tell the node from its declaration. |
|
| **Never bypass the pipeline** | No manual database edit, no manual restart as a workaround. Fix the cause and deploy. A workaround that works is a workaround that is never removed, and the next person cannot tell the node from its declaration. |
|
||||||
| **Never create a symlink** | A hand-made link caused production data loss through container volume resolution, and the judgement needed to make a safe exception is exactly the judgement unavailable at the moment it matters. **The mesh creates none at all** ([ADR 0018](../02-DECISIONS/0018-the-mesh-creates-no-symlinks.md), which supersedes [ADR 0011](../02-DECISIONS/0011-the-installer-owns-linking.md)). The links the installer still reconciles are a migration, not a permission. |
|
| **Never create a symlink** | A hand-made link caused production data loss through container volume resolution, and the judgement needed to make a safe exception is exactly the judgement unavailable at the moment it matters. **The mesh creates none at all** ([ADR 0018](../02-DECISIONS/0018-the-mesh-creates-no-symlinks.md), which supersedes [ADR 0011](../02-DECISIONS/0011-the-installer-owns-linking.md)). The links the installer still reconciles are a migration, not a permission. |
|
||||||
| **Never push directly to the main branch** | Branch, push, review, merge. Every merge is a human checkpoint, without exception — **including in this repository**. A documentation repository is not a lower tier of care; a decision record lands the same way a service does. |
|
| **Never push directly to the main branch** | Branch, push, review, merge. Every merge is a human checkpoint, without exception — **including in this repository**. A documentation repository is not a lower tier of care; a decision record lands the same way a service does. |
|
||||||
| **One change per pull request, and never merge your own** | Unrelated improvements bundled together cannot be reviewed or reverted separately. Self-merging removes the checkpoint that is the entire point. |
|
| **One change per pull request, and never merge unapproved work** | Unrelated improvements bundled together cannot be reviewed or reverted separately. And the checkpoint is **a person deciding, not a person clicking** — work may be merged by whoever wrote it once a human has explicitly approved *that merge*, and never on a standing permission, an instruction to do the work, silence, or the author's own judgement that it is ready. [ADR 0042](../02-DECISIONS/0042-approval-is-the-checkpoint.md) |
|
||||||
| **Never open a pull request unprompted** | A permissions list saying it is allowed is not a request. |
|
| **Never open a pull request unprompted** | A permissions list saying it is allowed is not a request. |
|
||||||
| **A failed step fails the job** | A sequence that continues past a failure does the next thing in the wrong place. Gate each step on the last. [ADR 0008](../02-DECISIONS/0008-a-failed-step-fails-the-job.md), and §5. |
|
| **A failed step fails the job** | A sequence that continues past a failure does the next thing in the wrong place. Gate each step on the last. [ADR 0008](../02-DECISIONS/0008-a-failed-step-fails-the-job.md), and §5. |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
---
|
||||||
|
status: accepted
|
||||||
|
date: 2026-08-26
|
||||||
|
deciders: jochen
|
||||||
|
reconstructed: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# 42. The approval is the checkpoint, not the second pair of hands
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
[§2](../00-META/how-we-build.md) reads *"one change per pull request, and never merge your
|
||||||
|
own"*, and gives the reason: *"self-merging removes the checkpoint that is the entire point."*
|
||||||
|
|
||||||
|
The rule was written for people. Applied literally to an agent it produces a contradiction
|
||||||
|
that surfaced immediately: an agent asked to merge cannot merge, because it authored what it
|
||||||
|
is being asked to merge. Every merge this repository has seen was therefore either performed
|
||||||
|
by the thing that wrote it, or not performed at all.
|
||||||
|
|
||||||
|
Stated by the operator: *"you are allowed to self-merge, after I've given you explicit
|
||||||
|
approval."*
|
||||||
|
|
||||||
|
## Considered options
|
||||||
|
|
||||||
|
1. **Read it literally.** An agent never merges; the operator merges by hand every time.
|
||||||
|
Rejected: it makes the operator a mechanical step rather than a reviewer, and a step
|
||||||
|
performed dozens of times without reading is not a checkpoint — it is the *shape* of one,
|
||||||
|
which is worse, because the record then claims a review that did not happen.
|
||||||
|
2. **Drop the rule for agents.** Rejected: the rule is right, and the failure it prevents —
|
||||||
|
work merged with nobody having looked — is not one an agent is less prone to.
|
||||||
|
3. **Name what the checkpoint actually is.** Chosen.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
**The checkpoint is a person deciding, not a person clicking.**
|
||||||
|
|
||||||
|
An agent may merge its own work **when a human has explicitly approved that merge**. The
|
||||||
|
approval is the review; the merge is bookkeeping that follows it.
|
||||||
|
|
||||||
|
Without an explicit approval, nothing changes: the agent does not merge, and
|
||||||
|
[§2](../00-META/how-we-build.md)'s *never open a pull request unprompted* continues to mean
|
||||||
|
that a permissions list is not a request.
|
||||||
|
|
||||||
|
**What "explicit" excludes**, because this is the half that can rot:
|
||||||
|
|
||||||
|
- A standing permission granted once and cited forever.
|
||||||
|
- An instruction to do the work, read as approval to merge it.
|
||||||
|
- Silence.
|
||||||
|
- The agent's own judgement that the work is ready.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- **The record must show which it was.** A merge performed on approval and a merge performed
|
||||||
|
unilaterally look identical afterwards, and the difference is the whole rule. Until the forge
|
||||||
|
can record an approval, the merge commit says so — which is weaker than a recorded review and
|
||||||
|
is stated here rather than left to be discovered.
|
||||||
|
- **Branch protection would make this structural instead of textual.** Required approvals turn
|
||||||
|
the rule into something the forge enforces. It cannot be set through the API on the forge
|
||||||
|
version in use, so this remains a rule held by intention — the condition
|
||||||
|
[§5](../00-META/how-we-build.md) exists to name.
|
||||||
|
- **The one-change-per-pull-request half is untouched**, and was broken twice on 2026-08-26.
|
||||||
|
Both breaches are recorded in the pull requests themselves rather than in a conversation.
|
||||||
|
- **This narrows a rule rather than relaxing one.** The obligation moves from *who performs the
|
||||||
|
merge* to *whether a person decided*, which is a higher bar in the case the original wording
|
||||||
|
actually permits: a reviewer who merges someone else's work without reading it satisfies the
|
||||||
|
old rule and fails this one.
|
||||||
|
|
||||||
|
## Sync
|
||||||
|
|
||||||
|
Run and verified 2026-08-26. §2 in the enforced page now reads *never merge unapproved work*,
|
||||||
|
confirmed by reading the rule back out of the live page rather than by trusting the publish —
|
||||||
|
the previous sync reported success and changed nothing.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [`how-we-build.md`](../00-META/how-we-build.md) §2 — the rule, now carrying this.
|
||||||
|
- [ADR 0008](0008-a-failed-step-fails-the-job.md) — the standard a checkpoint is held to: a
|
||||||
|
step that reports success without doing anything is the fault, not the shortcut.
|
||||||
Reference in New Issue
Block a user