docs(609): correct the --no-merges rationale — merges are discouraged, not blocked

Review Low x2, both correct and both the stale-comment class:

The claim that prepush-rebase-check.sh forbids merging main into a PR branch is
false. That hook refuses a branch that is BEHIND origin/main; a merge makes
origin/main an ancestor, so the push is allowed. Merging main in is discouraged by
convention only. So --no-merges does cost a real false negative: an author who marks
ONLY a conflict-resolving merge commit gets a legitimate rewrite rejected. Keeping
--no-merges and stating the trade explicitly -- that failure is loud and costs one
extra commit, whereas honoring forge-composed merge bodies disables the guard
silently, which is #609 itself.

The module comment also still claimed a quoted example cannot arm the guard, which
contradicts the residual the decision record now states accurately. Aligned both, and
narrowed the record's Rule line from "some commit" to "some NON-MERGE commit" so the
stated contract matches the implementation.

No logic change -- comments, docstring, record prose and regenerated catalog only.

fixes #609

Decisions-Edit: yes
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-25 18:36:07 +02:00
co-authored by Claude Opus 5
parent cc9481f541
commit f00dfde0c5
3 changed files with 21 additions and 9 deletions
+6 -3
View File
@@ -3924,7 +3924,7 @@ owner's sweep **destroyed** the row the other library still served. This is the
## 2026-07-25 — The rationale-edit marker is a git trailer, not a substring anywhere in the commit range (#609)
`key: ci.decisions-edit-trailer` · `status: active` · `since: 2026-07-25` · `supersedes: none` · `superseded-by: none`
**Rule:** The body-diff exemption is armed by an affirmative `Decisions-Edit:` **git trailer** (`yes`/`true`/`1`, case-insensitive) on some commit in the PR's merge-base range — never by a substring search over the message text. A non-affirmative value (`no`) does not arm it, the retired `[decisions-edit]` substring arms nothing (the validator emits a `::warning::` nudge when it sees one without a trailer), and a git error leaves the guard ON.
**Rule:** The body-diff exemption is armed by an affirmative `Decisions-Edit:` **git trailer** (`yes`/`true`/`1`, case-insensitive, read with `unfold`) on some NON-MERGE commit in the PR's merge-base range — never by a substring search over the message text. A non-affirmative value (`no`) does not arm it, the retired `[decisions-edit]` substring arms nothing (the validator emits a `::warning::` nudge when it sees one without a trailer), and a git error leaves the guard ON.
**Signals:** decisions-edit, Decisions-Edit trailer, rationale-prose edit, body-diff guard, decisions_validate, vacuous gate, green no-op · paths: `scripts/decisions_validate.py`, `scripts/tests/test_decisions_validate.py` · issues: #609, #603, #521
**Mechanics:** `git log --no-merges --format='%(trailers:key=Decisions-Edit,valueonly,unfold)' <mb>..<head>`; `dv._edit_trailer_armed`
@@ -3948,8 +3948,11 @@ way to record a deliberate non-edit, must not read as consent.
**Three exactness requirements the naive trailer read still gets wrong** (all found in review, all
regression-tested). `--no-merges`: on a `pull_request` event `actions/checkout` lands on a synthetic
merge commit whose body the forge composes from the PR *description*, so without it a description
ending in an example marker arms a guard no author armed (merging main into a PR branch is separately
forbidden, so nothing author-written is skipped). `unfold`: a folded `Decisions-Edit: no` + continuation
ending in an example marker arms a guard no author armed. That exclusion is not free: merging main
into a PR branch is discouraged but not mechanically blocked (`prepush-rebase-check.sh` only refuses a
branch that is *behind* main, and a merge makes main an ancestor), so an author who marks ONLY such a
merge commit has a legitimate rewrite rejected — a LOUD failure costing one extra commit, deliberately
preferred over silently disabling the guard. `unfold`: a folded `Decisions-Edit: no` + continuation
` yes` otherwise yields two lines, and the continuation arms on its own — inverting the value the
author wrote. And resolving the marker **fails closed** on a git error, the one deliberate exception
to this module's fail-open posture: a fail-open marker lookup is #609 through a different door.