Skip to content

Tell a number that names no issue here from a lookup that could not be made - #259

Merged
iderex merged 1 commit into
mainfrom
a-number-that-names-no-issue-here-108
Aug 31, 2026
Merged

Tell a number that names no issue here from a lookup that could not be made#259
iderex merged 1 commit into
mainfrom
a-number-that-names-no-issue-here-108

Conversation

@iderex

@iderex iderex commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

The issue this belongs to

Refs #108. It does not close it, and the reason is under "What this does not
cover" below.

What changed

The first update proposal this repository produced went red on pr-hygiene, and
not on the rule the exemption in that issue's earlier change was written for. This
is the repair.

Its body quotes upstream release notes. Those notes carry bare #<number>
references to issues on the repository they came from, issue_refs reads every
bare reference as one here because nothing in the text can say otherwise, and the
scope comparison then asked this repository for an issue that is not on it:

ok    names: 994 995 996 1004 1005 1007 1013 1014 1016 1017 3956 3995 4007 4019 4023 4037 4051 4061 4070 4080 4081 4085 4098 4102 4106

-- changed-paths-inside-scope
gh: Not Found (HTTP 404)
::error::Could not read issue #994. The scope comparison cannot be made, and this run will not pass in place of it.
::error::Process completed with exit code 1.

Failing closed there was right for the reason it was written and wrong because
it answered two questions with one word.
An outage read as an issue that
declares no scope is a pass nobody earned, which is what that branch exists
against. But a 404 is not an outage. It says the number names no issue on this
repository. "About somewhere else" and "cannot be read" are opposite statements,
and this is the same collapse the operations tree already names for a finding
placed about somewhere else against one that cannot be placed at all.

So the lookup now asks the cheapest question that separates them: after an issue
lookup fails, whether the repository itself answers. If it does, the route, the
token and the repository are fine and the number named nothing here, so it
declares no scope and the run says so once per number. If it does not, nothing was
learned about the number and the run refuses exactly as before, with a message
that now says which of the two it was. The second question is asked only on the
failure path, so a body naming twenty issues that exist is still twenty calls.

No rule is relaxed and nobody is exempted from anything by this. A body
quoting another repository's numbers already passed names-an-issue; what changes
is that the comparison underneath it no longer reads a definite answer as an
outage. It is not a widening of the author exemption, which stays where #108's
decision put it: by identity, on that one rule.

The failure this prevents

Every proposal red, forever, for a reason that has nothing to do with the update -
which is the exact failure the exemption was landed against, arriving one rule
further down. It reaches further than proposals: a person's body pasting the
output of a command that names another repository's issue hits the same 404, and
CONTRIBUTING.md asks for exactly that body, because the rule this repository puts
first is that a claim carries the command that produced it.

Evidence

At 662024f, three new fixtures beside the rules they hold, taking the two
answers as words so they judge without a network:

bash .github/pr-hygiene/hygiene.sh selftest ; echo "exit=$?"
...
== a number that names no issue here ==
ok    reads its scope: the issue answered
ok    declares no scope: the issue did not answer and the repository did
ok    refuses: neither answered, so nothing was learned about the number
...
Every fixture held. The rules the gate applies are the rules these fixtures ran.
exit=0

And the check run against the body that failed on the server, fetched and handed
to the same verb this repository's own workflow calls:

PR_NUMBER=256 PR_AUTHOR=dependabot[bot] GH_REPO=Flowfin/core \
PR_BODY_FILE=... CHANGED_PATHS_FILE=... bash .github/pr-hygiene/hygiene.sh check
-- names-an-issue
-- body-not-empty
-- changed-paths-inside-scope
      #994 names no issue on this repository, so it declares no scope. A body quoting another repository's release notes carries bare references to issues over there, and nothing in the text tells one from a reference here.
      ... one line per number ...
NOT MADE: no issue this pull request names declares a 'Scope:' line at column zero, so the changed paths were compared against nothing. This is a pass with no comparison behind it, and it is not a pass with one.
-- what this run did not read
Every rule this check owns passed.
exit=0

The guard refusing

Collapsing the two reasons back into one word, which is the state the run above
failed in:

-  if [ "$repository_answered" = "yes" ]; then
-    echo absent
-    return
-  fi
   echo unreadable

FAIL  declares no scope: the issue did not answer and the repository did
        expected: absent
        actual:   unreadable
::error::1 hygiene fixture(s) did not hold. The rules below are not the rules that were proven, so this run judges nothing.

and the same collapse taken through check against the real body refuses the run,
which is where this started.

The means

Shell, in the file the rule already lives in, for the reason CONTRIBUTING.md
gives: the logic of a check goes in a script beside the workflow with fixtures
proving each rule bites. The discrimination is factored into a function taking two
words rather than running the lookups itself, so the fixtures judge the rule
without a network - which is the same reason the other rules here take a document
on stdin.

What this does NOT cover

#108 is not closed by this. Its condition asks that a proposal run the same
checks as a pull request written by a person. The set of checks that ran on the
proposal is the same set, which is the half that is met; the hygiene check inside
that set was red for the reason above, and it will stay red on that proposal until
something re-runs it, which is not this change.

The mapping from a tool's exit code onto the two words is not fixtured, and
the function says so of itself. What the fixtures judge is the rule; whether gh
failing means what this file takes it to mean is read by a person.

A bare number that names no issue here still counts toward names-an-issue.
A body naming only foreign numbers passes that rule while naming nothing on this
board. That is unchanged by this and is a consequence of reading a bare reference
as local, which the rule's own documentation already sets out; narrowing it would
be a different change with a different argument.

Nothing here reads which numbers a body meant. Every bare reference is looked
up, and a repository that renumbers or a private issue the token cannot see would
answer the same way a foreign number does. The run prints one line per number so a
reader can see which were treated that way rather than being told a count.

No second reader. Nobody other than the author has read this change.

…e made

The first update proposal this repository produced went red on `pr-hygiene`, and
not on the rule the exemption was written for. Its body quotes upstream release
notes, those notes carry bare references to issues on the repository they came
from, and `issue_refs` reads every bare reference as one here because nothing in
the text can say otherwise. The scope comparison then asked this repository for
issue #994, got a 404, and refused:

    ok    names: 994 995 996 1004 1005 1007 1013 1014 1016 1017 3956 ...
    -- changed-paths-inside-scope
    gh: Not Found (HTTP 404)
    ::error::Could not read issue #994. The scope comparison cannot be made, and
    this run will not pass in place of it.

Failing closed there was right for the reason it was written - an outage read as
an issue declaring no scope is a pass nobody earned - and wrong because it
answered two questions with one word. A 404 says the number names no issue on
this repository. An outage says nothing was learned about the number at all. They
are opposite statements, and this is the collapse the operations tree already
names for a finding placed "about somewhere else" against one that "cannot be
placed".

So the lookup now asks the cheapest question that separates them: after an issue
lookup fails, whether the repository itself answers. If it does, the route, the
token and the repository are fine and the number named nothing here, so it
declares no scope and the run says so per number. If it does not, nothing was
learned and the run refuses exactly as before. The second question is asked only
on the failure path, so a body naming twenty issues is still twenty calls.

No rule is relaxed and no author is exempted from anything by this. A body
quoting another repository's numbers already passed `names-an-issue`; what
changes is that the comparison underneath it no longer reads a definite answer as
an outage.

Three fixtures hold the three verdicts, taking the two answers as words so they
judge without a network. Collapsing the two reasons back into one reddens the
middle fixture and the whole run with it:

    FAIL  declares no scope: the issue did not answer and the repository did
            expected: absent
            actual:   unreadable
    ::error::1 hygiene fixture(s) did not hold. The rules below are not the rules
    that were proven, so this run judges nothing.

Refs #108.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex
iderex merged commit 28b948f into main Aug 31, 2026
24 checks passed
@iderex
iderex deleted the a-number-that-names-no-issue-here-108 branch August 31, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant