From 5d4327d20884c08985e3a525716bbed545f0f39d Mon Sep 17 00:00:00 2001 From: Alfonso Sastre Date: Thu, 3 Sep 2026 23:51:47 +0200 Subject: [PATCH] glob: match against the full path, not just the basename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit find -name only compares a pattern against a file's basename, so any pattern containing "/" — "**/*.lex", "src/*", "lex/specs/**" — could never match anything: find silently reported "no files found" instead of erroring, giving no signal anything was wrong. Found live during today's 4-agent pipeline run (audited via LEX_PERSIST_TRACE, #99): every agent that tried "**/*.lex" got "no files found" despite matching files existing, and had to fall back to directory + non-recursive "*" to find anything. -path matches against the full path find is already walking (BSD and GNU find both apply it without FNM_PATHNAME, so "*" matches "/" too), which handles the recursive-glob and nested-prefix forms models actually send while still behaving identically to -name for a plain slash-free pattern like "*.lex" — verified directly: "**/*.lex" over a tree with nested files under src/ now finds all of them, where it previously found none. Co-Authored-By: Claude Sonnet 5 --- src/tools/standard/glob.lex | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tools/standard/glob.lex b/src/tools/standard/glob.lex index ffa9b34..3e3823f 100644 --- a/src/tools/standard/glob.lex +++ b/src/tools/standard/glob.lex @@ -16,12 +16,20 @@ fn params() -> s.ModelSchema { { title: "GlobArgs", description: "Find files matching a pattern", fields: [s.required_str("pattern", []), s.optional(s.required_str("directory", []))] } } +# `-name` matches only a file's basename, so any pattern containing "/" — +# "**/*.lex", "src/*", "lex/specs/**" — can never match anything: find +# silently reports no results instead of erroring, so the caller has no +# signal anything went wrong. `-path` matches against the full path find is +# already walking (BSD and GNU find both apply it without FNM_PATHNAME, so +# "*" matches "/" too), which handles the recursive-glob and nested-prefix +# forms models actually send while still behaving identically to `-name` +# for a plain slash-free pattern like "*.lex". fn execute(args :: jv.Json) -> [net, io, proc] Result[jv.Json, e.Errors] { match util.field_str(args, "pattern") { None => Err(e.single("", "missing_field", "pattern is required")), Some(pattern) => { let dir := util.field_str_or(args, "directory", ".") - match proc.run("find", [dir, "-name", pattern, "-type", "f"]) { + match proc.run("find", [dir, "-path", pattern, "-type", "f"]) { Err(msg) => Err(e.single("", "proc_error", msg)), Ok(out) => { let result := if str.is_empty(out.stdout) {