Which fff frontend?
MCP server (fff-mcp)
has logs
Not applicable: this is deterministic incorrect output without a server error.
Description
Summary
multi_grep does not apply positive file constraints. It can therefore return matches outside the requested scope. Its documented OR behavior also collapses when any requested pattern has no match; the plain-grep fallback masks the zero result but returns only the first successful pattern.
Reproduced on fff-mcp 0.10.1; current main contains the same code path. I found no existing issue covering this behavior.
Sanitized reproduction
Use any indexed repository containing:
scope-a/one.txt alpha
scope-a/two.txt beta
scope-b/three.txt alpha
Positive directory constraint:
{
"patterns": ["alpha"],
"constraints": "scope-a/"
}
Expected: only scope-a/one.txt.
Actual: matches from both scopes. The same occurs with a positive glob or exact-file constraint. A negative constraint is applied correctly. Ordinary grep with the equivalent inline query (scope-a/ alpha) is scoped correctly.
OR control:
{
"patterns": ["alpha", "definitely_missing_token"],
"constraints": "scope-a/"
}
Expected: the alpha match, because patterns is documented as OR.
Actual: the core multi-pattern search returns zero, then the server reports a plain-grep fallback for one pattern. Because the fallback returns after the first successful pattern, it cannot preserve the union for a larger pattern set.
Root cause
In crates/fff-mcp/src/server.rs, multi_grep_inner parses the standalone constraints string with AiGrepConfig, then passes only parsed_constraints.constraints to the picker. A lone positive path/glob is retained as grep text rather than classified as a constraint, leaving the constraint slice empty. The fallback reconstructs an inline query correctly, but exits after the first successful pattern.
Impact
This is a silent scope violation: callers can believe a directory, glob, or exact-file restriction was enforced when it was not. Multi-pattern results can also be incomplete while appearing successful through fallback output.
Suggested regression tests
- Positive directory constraint
- Positive extension/glob constraint
- Positive exact-file constraint
- Negative constraint
- OR with one matching and one missing pattern
- OR with multiple matching patterns plus one missing pattern
A useful invariant is: multi_grep(patterns, constraint) must equal the deduplicated union of individually scoped grep calls for the same patterns and constraint.
Which fff frontend?
MCP server (
fff-mcp)has logs
Not applicable: this is deterministic incorrect output without a server error.
Description
Summary
multi_grepdoes not apply positive file constraints. It can therefore return matches outside the requested scope. Its documented OR behavior also collapses when any requested pattern has no match; the plain-grepfallback masks the zero result but returns only the first successful pattern.Reproduced on
fff-mcp 0.10.1; currentmaincontains the same code path. I found no existing issue covering this behavior.Sanitized reproduction
Use any indexed repository containing:
Positive directory constraint:
{ "patterns": ["alpha"], "constraints": "scope-a/" }Expected: only
scope-a/one.txt.Actual: matches from both scopes. The same occurs with a positive glob or exact-file constraint. A negative constraint is applied correctly. Ordinary
grepwith the equivalent inline query (scope-a/ alpha) is scoped correctly.OR control:
{ "patterns": ["alpha", "definitely_missing_token"], "constraints": "scope-a/" }Expected: the
alphamatch, becausepatternsis documented as OR.Actual: the core multi-pattern search returns zero, then the server reports a plain-
grepfallback for one pattern. Because the fallback returns after the first successful pattern, it cannot preserve the union for a larger pattern set.Root cause
In
crates/fff-mcp/src/server.rs,multi_grep_innerparses the standaloneconstraintsstring withAiGrepConfig, then passes onlyparsed_constraints.constraintsto the picker. A lone positive path/glob is retained as grep text rather than classified as a constraint, leaving the constraint slice empty. The fallback reconstructs an inline query correctly, but exits after the first successful pattern.Impact
This is a silent scope violation: callers can believe a directory, glob, or exact-file restriction was enforced when it was not. Multi-pattern results can also be incomplete while appearing successful through fallback output.
Suggested regression tests
A useful invariant is:
multi_grep(patterns, constraint)must equal the deduplicated union of individually scopedgrepcalls for the same patterns and constraint.