Skip to content

[finding] git-merge-regen.mjs's .gitattributes reader matches merge=os-regen with a word boundary, admitting rows routed to a different driver #15701

Description

@claude

Observation-class finding, filed unassigned and ungraded — domain:*, priority and type are triage's.

Surfaced while repairing the other .gitattributes reader, the one in scripts/pm/os-regen-merge.sh
(card #15497, PR #15700). That repair left this file alone on purpose: its reader is not a shared copy
of the same construction, and it already skips comment lines, so it was out of that card's fence. This
is the residue.

The defect

scripts/git-merge-regen.mjs, in reconcileAttributes, selects the routed rows with:

    .filter((l) => l.trim() && !l.trim().startsWith('#'))
    .filter((l) => /\bmerge=os-regen\b/.test(l))
    .map((l) => l.trim().split(/\s+/)[0]);

The comment-line filter is right. The word boundary is the loose part: \b after the final n
matches before any non-word character, so a row routed to a different driver whose name merely starts
with os-regen is admitted as if it were routed to this one.

Measured (node 22, this repo's own regex):

"x merge=os-regen"     true
"x merge=os-regen-v2"  true     (a DIFFERENT driver)
"x merge=os-regen.2"   true     (a DIFFERENT driver)
"x merge=os-regenX"    false

And what git says the second row actually routes to (git 2.43.0, scratch repo, .gitattributes
containing exactly x merge=os-regen-v2):

$ git check-attr merge -- x
x: merge: os-regen-v2

git routes x to os-regen-v2; this reader counts x among the os-regen paths.

What it would do

reconcileAttributes holds .gitattributes equal to REGEN_ARTIFACTS in both directions. A row
routed to a sibling driver would therefore be reported as mapped to merge=os-regen but not declared in regen-artifacts.mjs — a red naming a rule that is not the rule the row breaks, on a path this driver
does not own. Declaring the path in the table to make the gate green would be the wrong repair, and it
is the repair the message asks for.

Why it is worth a row even though nothing is wrong today

Latent, not live: no merge=os-regen-prefixed sibling driver exists, so on today's file the reader
answers correctly. Verified at the same time as the sibling repair — node scripts/git-merge-regen.mjs --self-test prints .gitattributes and regen-artifacts.mjs agree on 18 path(s), agreeing exactly with
the repaired shell reader and with the 18 rows in the file.

The reason to record it is that the latent case has a plausible spelling. Attribute values are
whitespace-delimited tokens, so merge=os-regen-v2 is exactly how a second generation of this driver
would be introduced alongside the first — which is the day both readers are consulted and only one of
them is right.

The shape the repair would take

Anchor the attribute as a whitespace-delimited token rather than with \b, which is what the shell
reader now does after the sibling repair:

/(^|[ \t])merge=os-regen([ \t]|$)/

Whoever takes it should pin it in git-merge-regen.mjs's own --self-test with a fixture
.gitattributes carrying a sibling-driver row, and should prove the assertion can fail by ablation —
this repo measures only a minority of its self-tests as demonstrably non-vacuous, so an assertion that
passes on an empty population is not worth adding.

Dedup

/search/issues is refused by the egress proxy by design, so this was one targeted issue search over
open and closed cards. It returned 21 results — non-empty, which is its own firing control — and
they are the merge=os-regen family: the phantom-pathspec card being repaired, the MIXED-routing and
MIXED-conflict cards, the driver-registration and sharding cards, and the SKILL path-list drift card.
None of them names this mechanism (the reader's word-boundary match); the closest, the drift card, is
about a hand-copied list rather than about either reader.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions