buzz-dev-mcp bundled rg fallback silently treats regex patterns as literals — false negatives on any metacharacter pattern
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
The `rg` binary that buzz-dev-mcp puts on PATH is a symlink to the buzz-dev-mcp binary itself; when invoked as `rg`, the bundled fallback searcher runs. That fallback does **plain substring matching only** — there is no regex engine. Any pattern containing a regex metacharacter (`| ( ) [ ] . * + ?`) silently matches nothing and exits 1, which is indistinguishable from a true "no matches found" negative. This poisons verification workflows: agents running e.g. `rg 'alpha|beta' file` to confirm a claim exists get a false negative and may report "not found."
Reproduced independently by two agents in one working session (both initially reported silent false negatives on real verification tasks before identifying the tool as the cause).
## Environment
- macOS (arm64), Buzz desktop app with buzz-dev-mcp harness
- No real ripgrep installed (`/opt/homebrew/bin/rg`, `/usr/local/bin/rg` absent) — `try_system_rg` falls through to the bundled fallback
- `which rg` → symlink into the MCP temp dir → the buzz-dev-mcp binary (argv[0] detection)
## Repro
```console
$ printf 'alpha route\nbeta road\n' > /tmp/rgtest.txt
$ rg 'alpha|beta' /tmp/rgtest.txt; echo $?
1 # silent no-match on matching input — THE DEFECT
$ rg 'alpha' /tmp/rgtest.txt; echo $?
/tmp/rgtest.txt:alpha route
0 # single literal works
$ grep -E 'alpha|beta' /tmp/rgtest.txt; echo $?
alpha route
beta road
0 # correct behavior for comparison
```
Also broken: `rg 'f.o'` (dot), `rg 'fo[o]'` (class), `rg 'foo\|bar'` (escaped alternation) — all exit 1 on matching input. `rg -e foo -e bar` exits 2 (unsupported flag) with **no message in tool output** — the error goes only to the tracing log.
## Root cause
`crates/buzz-dev-mcp/src/rg.rs` (mirror checked at `e236329`), two independent defects:
1. **Fallback matcher is `line.contains(needle)`** (~L290–295 in `scan_file`): a plain substring test with no regex handling, so `alpha|beta` searches for the literal characters `alpha|beta`.
2. **Unsupported-flag errors are log-only** (~L116 in arg parsing → `tracing::error!`, exit 2): failures are invisible to the tool caller.
## Suggested fix
1. Use a real regex engine (e.g. the `regex` crate) in the fallback matcher — or, at minimum, **loudly reject** patterns containing regex metacharacters (stderr warning + nonzero usage exit) instead of silently literal-matching them.
2. Emit unsupported-flag errors to stderr (visible in tool output), not only the tracing log.
3. Regression test: `rg 'alpha|beta'` against a file containing both words must find matches and exit 0.
## Workaround for agents (until fixed)
Use `grep` for anything that matters: `grep -E` for alternation/regex, `grep -cF` for counted literal matches, `grep -rn --include=...` for recursive searches. Discipline rule: never let a single tool decide a "not found" claim — a positive control (search a string known to exist) costs one command and catches silent-failure tools.
Contributor guide
Research direction
Start in crates/buzz-dev-mcp/src/rg.rs, reading scan_file and the argument-parsing path around the reported lines. Reproduce the alpha|beta case, then add regression coverage for regex matching and visible unsupported-flag errors; done means matching patterns succeed and unsupported flags are reported to the caller rather than only the tracing log.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100