Skip to content

Commit 8d7a2da

Browse files
sjarmakclaude
andcommitted
fix: remove tool call cap and shell allowlist from curator agent
- MAX_TOOL_CALLS: 40 → 200 (no artificial cap on exploration) - TASK_TIMEOUT_SEC: 600 → 900 (15 min for thorough exploration) - Remove ALLOWED_COMMANDS allowlist entirely — agent runs unrestricted (shlex.split misparses regex | as pipe, blocking legitimate rg patterns) - CLI mode already had --dangerously-skip-permissions The 40-call cap caused premature termination on 3/5 calibration tasks, dropping recall from 0.79 to 0.67 vs ContextBench human annotations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a064f78 commit 8d7a2da

File tree

1 file changed

+3
-46
lines changed

1 file changed

+3
-46
lines changed

scripts/context_retrieval_agent.py

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@
7070

7171
DEFAULT_MODEL = "claude-opus-4-6" # Strongest model for oracle generation
7272
MAX_TOKENS = 16384
73-
MAX_TOOL_CALLS = 40
73+
MAX_TOOL_CALLS = 200 # No artificial cap — let the agent explore fully
7474
TOOL_TIMEOUT_SEC = 30
75-
TASK_TIMEOUT_SEC = 600 # 10 minutes per task (Deep Search calls take 30-60s each)
75+
TASK_TIMEOUT_SEC = 900 # 15 minutes per task (thorough exploration)
7676
DEFAULT_CACHE_DIR = Path.home() / ".cache" / "ccb_repos"
7777

7878
BACKENDS = ("local", "deepsearch", "hybrid")
@@ -420,56 +420,13 @@ def execute_sourcegraph_search(query: str, sg: "SourcegraphClient" = None) -> st
420420
},
421421
]
422422

423-
# Allowlist for shell commands (security)
424-
ALLOWED_COMMANDS = {
425-
"grep", "rg", "find", "wc", "tree", "head", "tail",
426-
"sort", "uniq", "file", "dirname", "basename", "ls", "stat",
427-
"cat", "awk", "sed", "xargs", "echo", "true", "test",
428-
}
429-
430423
# ---------------------------------------------------------------------------
431424
# Tool execution
432425
# ---------------------------------------------------------------------------
433426

434427

435-
def _validate_shell_command(command: str) -> Optional[str]:
436-
"""Check that a shell command uses only allowed executables.
437-
438-
Returns an error message if blocked, None if OK.
439-
"""
440-
# Extract the first word (the executable)
441-
try:
442-
parts = shlex.split(command)
443-
except ValueError:
444-
parts = command.split()
445-
if not parts:
446-
return "Empty command"
447-
448-
# Handle pipes: check each segment
449-
segments = command.split("|")
450-
for seg in segments:
451-
seg = seg.strip()
452-
if not seg:
453-
continue
454-
try:
455-
seg_parts = shlex.split(seg)
456-
except ValueError:
457-
seg_parts = seg.split()
458-
if not seg_parts:
459-
continue
460-
exe = seg_parts[0]
461-
# Strip path prefix
462-
exe = os.path.basename(exe)
463-
if exe not in ALLOWED_COMMANDS:
464-
return f"Command '{exe}' is not in the allowlist: {sorted(ALLOWED_COMMANDS)}"
465-
return None
466-
467-
468428
def execute_run_shell(command: str, cwd: str = "") -> str:
469-
"""Execute a read-only shell command."""
470-
err = _validate_shell_command(command)
471-
if err:
472-
return f"BLOCKED: {err}"
429+
"""Execute a shell command. No allowlist — agent runs unrestricted."""
473430
try:
474431
result = subprocess.run(
475432
command, shell=True,

0 commit comments

Comments
 (0)