Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions scripts/check_pr_perimeter.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,10 +717,25 @@ def check_assertion(
r"\b(?:editer|modifier|toucher|ouvrir|créer|creer|ajouter|changer|mettre\s+à\s+jour|mettre\s+a\s+jour|update|edit|modify|touch|open|create|add|change)\b",
re.IGNORECASE,
)
# A named file as it would appear in a body: backticked path, bare basename
# A named referent as it would appear in a body: backticked path, backticked
# DOTTED SYMBOL (`pick_idle_grain.upsert_orphans_comment`), bare basename
# (.py/.cs/.yml/.json/.md/.ipynb/.sh), or a known scripts/<x>.py shape.
#
# #13610 residual (measured 2026-09-02, po-2024): the tail class was
# `[A-Za-z0-9]+`, which excludes the underscore. A dotted symbol -- the most
# common way a French technical body points at code -- was therefore NOT a
# named referent, and the FN-safety branch kept the rouge on the FOUNDING
# sentence of #13539, whose referent was named but named as a SYMBOL:
# « L'upsert vit dans `pick_idle_grain.upsert_orphans_comment` ; le
# generaliser demanderait d'editer un fichier deja porteur de deux PRs »
# The boundary this drew was arbitrary AND invisible: `pick_idle_grain.upsert`
# passed while `pick_idle_grain.upsert_orphans` rouged, on the sole strength
# of one underscore -- two spellings of the same code reference, opposite
# verdicts. Widening the tail to `\w+` removes the inversion. It does NOT
# touch the deliberate FN-safety choice of #13612: an ANONYMOUS referent
# ("editer un fichier", nothing named on the line) still keeps the rouge.
_NAMED_FILE_BODY = re.compile(
r"(?:`([^`]+\.[A-Za-z0-9]+)`|" # backticked: `pick_idle_grain.py`
r"(?:`([^`]+\.\w+)`|" # backticked: `pick_idle_grain.py`, `mod.fn_name`
r"\b([\w./-]+\.(?:py|cs|yml|yaml|json|md|ipynb|ts|js|sh|toml|cfg|ini))\b)" # bare basename
)
# A cited threshold ("< 15 fichiers", ">= 10 fichiers") quotes a rule, it does
Expand Down
104 changes: 104 additions & 0 deletions scripts/tests/test_check_pr_perimeter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2865,6 +2865,110 @@ def test_13610_predicate_unit_unanimous():
) is False # named file IS in scope


# ---------------------------------------------------------------------------
# #13610 residual (2026-09-02, measured by po-2024) -- the referent is named,
# but named as a SYMBOL, not as a file. The tail class of _NAMED_FILE_BODY was
# `[A-Za-z0-9]+`, which excludes the underscore; a dotted symbol was therefore
# not recognized as a named referent, and the FN-safety branch kept the rouge
# on the FOUNDING sentence of #13539 itself. The boundary was arbitrary AND
# invisible: the same code reference passed or rouged on the sole strength of
# one underscore. The pair below is the proof -- the first test alone would be
# satisfied by simply disabling the guard, which is why the positive control
# and the anonymous-referent control are pinned alongside it.
# ---------------------------------------------------------------------------

# The two rows of the #13610 table, verbatim in shape: same sentence, same
# referent, one underscore apart.
_SYMBOL_SHAPE = (
"L'upsert vit dans `pick_idle_grain.{symbole}` ; le generaliser "
"demanderait d'editer un fichier deja porteur de deux PRs ouvertes "
"de la meme lane"
)


def test_13610_symbol_referent_without_underscore_passes():
"""Table row 1: `pick_idle_grain.upsert` -- passed even before the fix.
Pinned so a future tightening of the tail class cannot silently take it
back, which would re-open the inversion from the other side."""
line = _SYMBOL_SHAPE.format(symbole="upsert")
problems = check_assertion(FILES_13610, line)
assert problems == [], (
"a dotted symbol without underscore must not rouge; got: "
+ repr(problems)
)


def test_13610_symbol_referent_with_underscore_passes():
"""Table row 2: `pick_idle_grain.upsert_orphans` -- ROUGED before the fix,
on the sole strength of the underscore. This is the regression the
residual names."""
line = _SYMBOL_SHAPE.format(symbole="upsert_orphans")
problems = check_assertion(FILES_13610, line)
assert problems == [], (
"a dotted symbol with an underscore must not rouge -- the underscore "
"is not a semantic boundary; got: " + repr(problems)
)


def test_13610_founding_sentence_of_13539_passes():
"""The sentence of #13539 that founded the whole thread. Its referent was
named all along -- named as a symbol. Acceptance line 1 of #13610."""
line = _SYMBOL_SHAPE.format(symbole="upsert_orphans_comment")
problems = check_assertion(FILES_13610, line)
assert problems == [], (
"the founding sentence of #13539 must pass the guard; got: "
+ repr(problems)
)


def test_13610_symbol_widening_keeps_positive_control_rouge():
"""Acceptance line 2 of #13610, stated as a PAIR with the three tests
above: widening the tail class must NOT extinguish the positive control.
A fix that made the symbol cases pass by weakening the guard would pass
those three and fail this one -- which is the whole point of pinning it
here rather than relying on the older copy elsewhere in the file."""
problems = check_assertion(FILES_13610, "Cette PR ne touche qu'un fichier.")
assert problems, (
"the positive control must still rouge after the widening -- "
"3 files in the PR, assertion claims 1"
)


def test_13610_symbol_widening_keeps_anonymous_referent_rouge():
"""FN-safety, restated post-widening: widening WHAT counts as a named
referent must not turn an ANONYMOUS referent into a named one. #13612's
deliberate default-fail-loud on ambiguous shapes is untouched."""
line = (
"le generaliser demanderait d'editer un fichier deja porteur de "
"deux PRs ouvertes"
)
problems = check_assertion(FILES_13610, line)
assert problems, (
"an anonymous referent must keep the rouge after the widening"
)


def test_13610_symbol_predicate_unit_pair():
"""Direct unit test of the predicate on the two table rows, decoupled from
check_assertion so a pipeline change cannot mask a predicate regression --
same rationale as test_13610_predicate_unit_unanimous."""
files = FILES_13610
assert _word_form_is_indef_non_pr_subject(
_SYMBOL_SHAPE.format(symbole="upsert"), files
) is True
assert _word_form_is_indef_non_pr_subject(
_SYMBOL_SHAPE.format(symbole="upsert_orphans"), files
) is True
assert _word_form_is_indef_non_pr_subject(
_SYMBOL_SHAPE.format(symbole="upsert_orphans_comment"), files
) is True
# The widening is about the TAIL of a dotted referent, nothing else:
# an anonymous referent stays False.
assert _word_form_is_indef_non_pr_subject(
"editer un fichier quelque part", files
) is False


# ---------------------------------------------------------------------------
# #13637 -- carried-from-main files. GitHub's /pulls/N/files diffs base-tip ->
# head, so a branch that merged main gets main's own changes attributed to it
Expand Down
Loading