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.
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_searchcollapses several distinct situations into the same(no matches found)string (forge-core/tools/builtins/grep_search.go:135-144on the ripgrep path,:269on the Go fallback):include:glob matching zero filespath:pointing at a file that does not exist (PathValidator.Resolve doesn't stat the final path — only theworkspace/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.