Skip to content

glob answers 'No files matched' for a pattern whose every match it skipped, and never says it skipped #1874

Description

@how2how2how2-arch

Measured 2026-10-06 (cyc20261006-192020) on this checkout. glob filters every
match through _is_hidden_or_ignored and then reports the filtered result as if it
were the answer about the tree — and when the filter takes everything, it says the
pattern matched nothing:

# emrg/gui, a directory that really holds node_modules:
$ glob(pattern='node_modules/**/package.json', workdir='<repo>/emrg/gui')
No files matched pattern 'node_modules/**/package.json' in <repo>/emrg/gui

    matched 352 path(s) · kept 0 · skipped 352

$ glob(pattern='.git/config', workdir='<repo>')
No files matched pattern '.git/config' in <repo>

    matched 1 path(s) · kept 0 · skipped 1     (the file is there)

$ glob(pattern='**', workdir='<repo>/emrg/gui')
Found 293 matches for '**' in <repo>/emrg/gui:

    matched 18014 path(s) · kept 293 · skipped 17721

(matched/kept counted with the tool's own predicate, GlobTool._is_hidden_or_ignored.)

It is the class this repository keeps fixing: a reading that was not made is not a verdict

0 is the code that means measured and clean, and "No files matched" is the sentence
that means the tree has none. Here no search of those paths happened at all — the
policy dropped them — so the tool states a fact about the tree that it did not measure.
It is the same defect as grep's Found N matches counting context lines (issue
#1805), one step earlier: an answer an agent uses for "is this dependency installed?",
"is there a config file here?", "how many Python files does this project have?" —
answered 0 by the skip rather than by the tree.

The non-zero case is the same sentence with a smaller error: Found 293 matches is the
number left after the skip, presented as the number the tree holds. 18014 paths matched
that pattern.

The sibling tool already handles both halves

grep skips the same directories and does two things glob does not:

  • its description declares it — "cross-platform pattern search with automatic
    binary/hidden file skipping" — while glob's description says only "Results are capped
    at 500 matches, sorted by path", so the caller is not told a filter exists;
  • its count line names its subject — Found N matches for 'X' in <root> (searched M files): — so a reader can tell a filtered count from the count.

The remedy is real, and measured

The skip compares each path relative to the root it was given, so pointing workdir
at the directory that holds them reads them:

$ glob(pattern='config', workdir='<repo>/.git')      -> Found 1 matches for 'config' ...

A refusal that names a remedy nobody ran is worse than none, so this one is pinned by a
test that fails when the comparison stops being relative.

Acceptance

  • a pattern whose every match was skipped is not reported as No files matched
    without the number of paths the skip dropped, and the sentence says the skip — not the
    tree — is what answered;
  • the Found N line carries the same number, in the shape grep uses for its own
    subject, so a filtered count is not read as the count;
  • the remedy the refusal names is the measured one (workdir at the directory that holds
    them), and a test fails if the skip stops being relative to the workdir;
  • the tool description declares the skipping, as grep's does, and names workdir as
    the way to read inside a skipped directory;
  • each of those legs has a test that fails when its clause is removed, and a control that
    fails when the clause is printed for a pattern that skipped nothing.

Activity

  1. how2how2how2-arch commented on Oct 6, 2026

    @how2how2how2-arch
    CollaboratorAuthor

    Handled by #1875

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