Skip to content

fix(code/search): forgive glob-shaped pattern — list files instead of looping the search forever#1949

Merged
joelteply merged 1 commit into
canaryfrom
fix/code-search-glob-forgiveness
Jul 8, 2026
Merged

fix(code/search): forgive glob-shaped pattern — list files instead of looping the search forever#1949
joelteply merged 1 commit into
canaryfrom
fix/code-search-glob-forgiveness

Conversation

@joelteply

Copy link
Copy Markdown
Contributor

Glass-boxed live: a local 14B on a SWE task fired code/search(pattern="**/*.py") twelve times in a row and
never advanced to read/edit. Root cause: it conflates code/search (grep file CONTENTS — pattern is the search
TERM, file_glob filters files) with code/glob (find files BY name). A glob in pattern greps contents for the
literal text "**/*.py" → 0 matches → the model retries the identical call and stalls. This is the same class of
confusing-tool-contract bug as the code/edit edit_mode-as-"any" fix (#1946): a 14B can't infer the two-param
split, so the tool must meet it halfway.

Fix: when pattern looks like a file glob (*/? + a path-glob shape, conservative so a real content regex like
foo.*bar / fn .*Params is NOT misclassified — unit-tested) and no file_glob was given, do what it MEANT —
run the glob and return the matching FILE paths as results, plus a one-line note on the correct shape. One call now
makes progress instead of looping. Strictly-better for the detected case (which otherwise always returns 0); the
normal grep path (real term, or file_glob set) is untouched, so no regression is possible.

Behavior-validation (persona reads→edits) is PENDING a stable coder lane: this session's heavy core-reboot churn
left the local llama-server 500ing "Compute error" on restart, which blocks all evals (separate infra issue, being
left to stabilize). Unit test green; logic is opt-in on a currently-useless case. [[px-persona-experience-tools-as-good-ux]]

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo

…of looping the search forever

Glass-boxed live: a local 14B on a SWE task fired `code/search(pattern="**/*.py")` twelve times in a row and
never advanced to read/edit. Root cause: it conflates code/search (grep file CONTENTS — `pattern` is the search
TERM, `file_glob` filters files) with code/glob (find files BY name). A glob in `pattern` greps contents for the
literal text "**/*.py" → 0 matches → the model retries the identical call and stalls. This is the same class of
confusing-tool-contract bug as the code/edit `edit_mode`-as-"any" fix (#1946): a 14B can't infer the two-param
split, so the tool must meet it halfway.

Fix: when `pattern` looks like a file glob (`*`/`?` + a path-glob shape, conservative so a real content regex like
`foo.*bar` / `fn .*Params` is NOT misclassified — unit-tested) and no `file_glob` was given, do what it MEANT —
run the glob and return the matching FILE paths as results, plus a one-line note on the correct shape. One call now
makes progress instead of looping. Strictly-better for the detected case (which otherwise always returns 0); the
normal grep path (real term, or file_glob set) is untouched, so no regression is possible.

Behavior-validation (persona reads→edits) is PENDING a stable coder lane: this session's heavy core-reboot churn
left the local llama-server 500ing "Compute error" on restart, which blocks all evals (separate infra issue, being
left to stabilize). Unit test green; logic is opt-in on a currently-useless case. [[px-persona-experience-tools-as-good-ux]]

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
@joelteply joelteply merged commit daee780 into canary Jul 8, 2026
1 check passed
@joelteply joelteply deleted the fix/code-search-glob-forgiveness branch July 8, 2026 23:41
joelteply added a commit that referenced this pull request Jul 9, 2026
…er paths — the two barriers past the search-loop (#1951)

Glass-boxed live (loop-perception PR #1950 got the 14B PAST the search-loop and hammering code/edit; these are the
two walls it then hit):

1. edit_mode shape: it sent `edit_mode:"append"` (bare variant string) and, later, the fields flat at top level with
   no edit_mode at all. EditMode is a serde-tagged enum, so both 400'd at deserialize. Fix: `edit_mode` accepts a
   Value; `normalize_edit_mode` tries the strict tagged object first (unchanged), then a bare mode string, then
   INFERS the mode from which top-level fields are present (search/replace→search_replace, content→append, etc.),
   failing LOUD and naming the missing field (never a silent no-op → false-zero). Same "meet the model halfway"
   forgiveness as code/search #1949; strict callers are untouched, so no regression.

2. placeholder path: it wrote `file_path:"<path_to_blueprints.py>"` — echoing the schema's angle-bracket placeholder
   instead of the concrete path it had already seen in its search results. `reject_placeholder_path` fails loud on
   `<...>`/`path_to`/`your_file` templates and points at the real value ("use the path from your search results, e.g.
   src/flask/blueprints.py") instead of a confusing file-not-found.

VALIDATED live: with these, the inference path fires (she now sends content/search flat and the mode resolves) — the
remaining 0-diff is purely the placeholder path, which now fails loud with guidance instead of silently. Unit-tested
(strict/bare/inferred/loud-missing; placeholder-vs-real). The rails are now maximally forgiving; what's left past
this is base-model COHERENCE (it has the real path in memory but writes the template) — the Devstral lever, not more
tool fixes. [[px-persona-experience-tools-as-good-ux]] [[built-to-teach-lesser-tuned-intelligences-win]]


Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant