Refuse a removal the pull-request body never names - #198
Merged
Merged
Conversation
One merge on the default branch removed landed work on seven paths under a message describing a change to how one workflow pin is commented. A licence, a guard and four hundred lines of a document went and nothing was red, because every other check here reads what the tree became and a result that compiles and passes says nothing about what it replaced. #155 records that incident, and the decision it stood open on was taken on 2026-08-24: removing stays allowed, removing in silence ends. path-removed-without-being-named refuses a path the range takes out of the tree that the pull-request body never names. The repair is a sentence rather than putting the file back, and the message says so, because a rule that reads as forbidding removals is one somebody argues with instead of satisfying. This package is where the rule can live at all. Every other check reads a checkout; this one holds both ends of the range, which is what makes a removal visible. The boundaries are at the rule rather than left to be discovered. The source path of a move git reported as a rename is not judged, because the entry carries both paths and the change says where the content went. A move nothing reported as one is an ordinary removal here and has to be named, which is red for a reason a reader can act on. A path added and removed inside one branch never reaches the rule. And what the check can separate is a body that names the path from one that does not, never whether what it says is true. The guard was proved by deleting it. Removing the refusal site leaves three table cases and both tests over the message failing with the refusal not produced, and the coverage test saying nothing in the suite has seen the property bite; removing the one dispatch line leaves twelve failures including the skip. Each refusing case has a near neighbour that refuses nothing and differs by the body alone. Four cases that already existed removed a path under a body that never named it, so they now name it. The one field that separates each of them from a case refusing nothing is unchanged, and the sets they compare are still exactly one property. The template asks for the sentence where an author writes it, because a rule met for the first time at a red gate is a rule that reads as an obstacle. Means: Go, in the package that already holds both ends of the range and already reads the body, judged by the same table-driven harness the other rules use. It adds no language, no runtime and no dependency. Closes #155. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #155
What this changes
path-removed-without-being-namedrefuses a change that takes a tracked pathout of the tree when the pull-request body never names that path. Removing stays
allowed. Removing in silence is what ends, and the refusal message says so,
because a rule that reads as forbidding removals is a rule somebody argues with
instead of satisfying.
It lives in
internal/pullrequest/because that is the only place it can. Everyother check on this board reads a checkout: the record checks walk
experiments/, the invariants read tracked text, the prose rules read the bytesaround the words. All of them read what the tree became, and a result that
compiles and passes says nothing about what it replaced. This package holds both
ends of the range, which is what makes a removal visible at all.
The boundaries are written at the rule rather than left to be discovered. The
source path of a move that git reported as a rename is not judged, because the
entry carries both paths and the change already says where the content went. A
move nothing reported as one, which is what a rename made together with a
rewrite looks like, is an ordinary removal here and has to be named. A path
added and removed inside one branch never reaches the rule, because the range is
read from base to head. And the comparison asks whether the body carries the
path, never whether what it says about it is true.
Four cases that already existed removed a path under a body that never named it,
so those bodies now name it. The single field separating each of them from a
case that refuses nothing is unchanged, and each still refuses exactly its own
property.
.github/pull_request_template.mdasks for the sentence where an author writesit. A rule met for the first time at a red gate is a rule that reads as an
obstacle, and this one is one sentence away from satisfied.
Means: Go, in the package that already holds both ends of the range and already
reads the body, judged by the table-driven harness the other rules in it use. It
adds no language, no runtime and no dependency, and it needs no new reader,
because
read.goalready reports a removed path and reports a rename as oneentry carrying both paths.
What failure it prevents
The incident this issue records, exactly. A branch was cut from an older state
of the default branch and pushed on top of a newer one. The merge replaced seven
paths with what they had said earlier, taking a licence, a guard and four
hundred lines of a document, and the body described a change to how one workflow
pin is commented, because that is what its author believed the change did.
Nothing was red afterwards, because almost everything removed was prose and the
one test that went with it was the only thing reading the code path it covered.
What the rule converts is that a removal nobody wrote down becomes a removal
somebody had to write down. It cannot tell a true sentence from a false one, and
that bound is stated at the rule. It is worth having anyway, because the case
where nothing at all was written is the case that happened, and it is the case a
string comparison can separate.
What was run
At
43620deeadc6cd4f81f2467fc7c41bef7cde0b67, from the root of the checkout:The guard was proved by deleting it, at both places it can be lost. With the
refusal site disabled and nothing else changed:
and with the refusal site intact and the one dispatch line in
Judgeremovedinstead, which is the way a rule is lost while the store still declares it:
Both were restored and the suite above is the run after restoring them. Each
refusing case has a near neighbour that refuses nothing and differs from it by
the body alone, so what the fixtures prove is the rule rather than the diff.
This change removes no tracked path.
What this does not do
It does not ask whether the sentence in the body is true, or whether it is about
the removal at all. A body that names the path while claiming the opposite
passes, and so does one that names it for an unrelated reason. That is the same
bound the issue-reference rules in this package already carry, and a reviewer is
what stands behind the rest.
It does not see a removal that arrives without passing this gate. A direct push
is refused by the ruleset on the default branch, which requires a pull request,
and an edit made through the web interface or history rewritten on the branch is
outside what this reads. Those are named at the rule so a green run is not taken
for more than it is.
It does not restore anything. The six path groups this issue is also about were
restored earlier under the issues that argued them, and the per-path comparison
recording that is in this issue's own comments.
It does not narrow what may be removed. Nothing here forbids a removal, and the
existing rules over a record that was already on the branch are untouched: those
still refuse a removed or renamed record outright, for their own reason, and a
change doing that now refuses two properties rather than one.
This board has no second reader tonight. What stands in place of one is the
deliberate breaking of the guard at both sites above, the near neighbour beside
every refusing case, and the full suite at the pushed commit.