Skip to content

grep_search reports "(no matches found)" for a nonexistent file — indistinguishable from a true no-match #282

Description

@initializ-mk

Observed (live, k8s-triage agent)

With the target file accidentally absent, the model ran:

{"pattern":"CrashLoopBackOff|Error|Failed","path":"pods.json"}

got (no matches found), and confidently answered "there are no crashing pods" — a wrong answer presented as a verified result. The correct signal was "that file doesn't exist."

Why

grep_search collapses several distinct situations into the same (no matches found) string (forge-core/tools/builtins/grep_search.go:135-144 on the ripgrep path, :269 on the Go fallback):

  • pattern genuinely absent from an existing file ✔️ (correct)
  • include: glob matching zero files
  • path: pointing at a file that does not exist (PathValidator.Resolve doesn't stat the final path — only the workspace/ fallback probe does)

An LLM cannot distinguish "searched and found nothing" from "searched nothing," and the resulting negative claims look authoritative.

Suggested fix

Stat the resolved path before searching: nonexistent → return an explicit (path not found: pods.json) (as a result string, not an error — models handle it better); zero-file glob → (no files matched include pattern). Keeps (no matches found) meaning exactly one thing.

Found while live-testing context compression (#241/#279); unrelated to compression itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions