Skip to content

emrg: a guard can be dropped from the pointable-at-a-tree table and every leg stays green #2704

Closed

Description

@pm25coder

What the file does

tests/test_a_tree_reading_guard_names_its_tree.py holds one convention of this repository's scripts/check-*.py family: a guard that reads a working tree says which tree answered, and a guard pointed at a tree it read nothing from must refuse (rc 2) with a reason rather than print a clean verdict (rc 0).

Two tables say which guard can be pointed at a tree, and how:

  • POINTABLE_AT_A_TREE — seven members, each mapping a guard to the argument that points it at a tree: check-citation-resolves.py (() — a positional), check-staged-inverse.py (--repo), and check-retry-bounds.py, check_unbound_reads.py, check-undefined-names.py, check-workflows.py, check-gui-package-refs.py (all --root).
  • TAKES_A_TREE_ARGUMENT — two members, check-citation-resolves.py (()) and check-staged-inverse.py (--repo): the guards whose tree is their argument, so the leg that asks about the default root can run them with no flags at all.

A row in POINTABLE_AT_A_TREE is what puts a guard in front of the empty-tree leg, which is the only place the family's "an empty tree is not a clean one" rule is asked of it.

What is observed

Deleting exactly one row from POINTABLE_AT_A_TREE — leaving the guard everywhere else it appears, including TAKES_A_TREE_ARGUMENT — and running the whole file:

row deleted from POINTABLE_AT_A_TREE its pointing argument whole file
check-staged-inverse.py --repo 9 passed — every leg green
check-citation-resolves.py positional 9 passed — every leg green
check-retry-bounds.py --root 1 failed, 8 passed
check-workflows.py --root 1 failed, 8 passed
(nothing deleted) — 9 passed

So two of the table's seven members can be removed from it and nothing fails. The two that survive belong to different eras — check-staged-inverse.py joined with the staged-inverse guard, check-citation-resolves.py predates it — which makes this the table's shape rather than one addition's mistake.

Why no leg misses them

test_every_guard_advertising_a_root_flag_is_accounted_for derives its subject by asking each guard's own --help and keeping the guards whose text matches --root. Both survivors' pointing argument is something else: a positional (usage: check-citation-resolves.py [-h] [root]) and --repo. The leg never looks at them, so it cannot miss what it never asks about.

The other legs cannot see a deletion either, and each for its own reason:

  • test_a_guard_pointed_at_a_tree_it_read_nothing_from_refuses_to_pass iterates the table, so a deleted row is simply not asked — a shorter table is still a passing one. Its companion assertion set(POINTABLE_AT_A_TREE) - _tree_reading_buckets() also shrinks with the table, so the deletion makes less to check, never more.
  • test_a_guard_that_takes_a_tree_defaults_to_the_tree_it_stands_in and test_the_guard_that_takes_a_tree_names_the_tree_it_was_given iterate TAKES_A_TREE_ARGUMENT, which still has both guards, so they keep asking the guards other questions and stay green.
  • test_every_guard_in_the_family_is_classified asks about the four classification buckets, which do not include POINTABLE_AT_A_TREE; the guard is still classified in its bucket, so nothing moves.

Both directions of the table are therefore unfenced for those two members: nothing fails when a row goes, and nothing fails when a guard that could be pointed at a tree is never added.

Expected

Removing a member from the pointable table is a change to what the file measures, so it must fail and name the guard it stopped measuring. Adding a guard that can be pointed at a tree, and not adding it, must fail too.

Acceptance

  1. Deleting any single row of POINTABLE_AT_A_TREE fails exactly one leg, and the failure names the guard. All seven rows, one arm each, each followed by a byte-identical restore.
  2. A guard that admits a pointing argument and is in neither table fails, naming it and saying which table to add it to. A legitimate guard added properly stays silent — a leg that pins today's seven names instead of deriving them is the literal-pin defect this repository has paid for six times and is not acceptable.
  3. A guard whose --help cannot be read, or that is not on disk, is a loud failure naming it — never a skip, and never read as a pass.
  4. The two tables' member counts, before and after.

Fix shape

Derive the membership; do not write a second list. The file already owns both derivations it needs:

  • TAKES_A_TREE_ARGUMENT's members are pointable by the table's own docstring — their tree is their argument — so set(TAKES_A_TREE_ARGUMENT) <= set(POINTABLE_AT_A_TREE) is a fact about the file's own classification, needs no vocabulary, and is exactly the fence missing over the two survivors above.
  • --help already answers the other half, and the account-for leg already runs it: a guard's pointing flag is a flag its own --help advertises. Today the table's second column is prose nothing measures — if a guard renames or drops the flag its row names, that is found by the empty-tree leg crashing into an argparse error, not by a leg asking the question.

Together they cover all seven rows: five are --root and already paid for by the account-for leg, and the two survivors are TAKES_A_TREE_ARGUMENT members. A metavar vocabulary (matching ROOT/TREE/PATH in the help text) is not the derivation to use: check-citation-resolves.py's positional is spelled lowercase root with no metavar, while check-issue-links.py advertises --repo REPO that takes a GitHub slug and no tree, so a word list would both miss the first and wrongly claim the second.

Activity

  1. pm25coder commented on Nov 4, 2026

    @pm25coder
    CollaboratorAuthor

    Handled by #2705

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions