Repository navigation
fix(bash): block repo-wide shell search in favour of code_search - #38
Merged
Merged
Conversation
… with an opt-in for exhaustive search Co-Authored-By: lemoncrow <302591943+lemoncrow-agent[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two instruction changes (#35, #37) asked Opus 5.5 to send repo searches to
code_search. The audit of sessions started after #37 shows the wording moved main sessions (6% → 27% of repo searches) but barely moved build agents (5% → 10%; Opus 5 was 15–18%). Build agents added a few code searches without giving upgrep: shell repo searches stayed at ~18.6 per 100 tool calls. Asking has stopped working, so this makes thebashtool enforce it.What
LemonCrow's
bashtool now refuses a recursive content search of the indexed repo (grep -r/-R,rg,git grepon the working tree), with a message that points tocode_searchand names what still runs. Applies to every command in a chain (cd x && grep -rn …,ls; rg …).Still runs, because the index can't answer it:
grepover named filesnode_modules,dist,.venv, …) and gitignored dirs (.closedloop-ai/, caches), judged by the worktree's own checkoutgit grep PAT origin/main,git grep PAT REV -- pathgit log | grep,cmd | rg) and searches whose output feeds a command (| xargs,$(…))rg -u/--no-ignore/--files$VARpaths,cd -): fails openEscape hatch:
code_searchis ranked and capped, so an exhaustive list of matches (e.g. every call site before a rename) needs real grep. Prefixing the command withLEMONCROW_SHELL_SEARCH=1runs it. The block message says so. Future audits can count how often agents reach for it.Only the MCP
bashtool passessearch_root, so otherclassify_commandcallers are unchanged. The worktree's repo is resolved to its main checkout, so.claude/worktrees/*searches are covered.Replay against real sessions
I replayed every
lc bashcommand from main and build-agent sessions since Sep 22 whose working directory still exists (6,301 commands) through the new guard:git grep -n X -- apps packages,grep -rn X apps/desktop scripts …).git grep … origin/main, and scratch/log searches.The first replay also caught
grep -rl … .closedloop-ai/campaigns(gitignored campaign state) being blocked; the gitignore check fixes that.Verification
tests/core/capabilities/tool_supervision/test_bash_exec_repo_search_block.py(41 cases): blocked shapes, every allowed shape above, worktree coverage, nosearch_root→ no block, and the MCPbashtool end to end (blocked result; opt-in prefix runs the real search).classify_command; ruff, black, mypy clean.After merge
Update the install, then rerun the audit after a few days of sessions: build-agent code-search share (10% now), how often the block fires, and how often agents use the opt-in prefix.