Repository navigation
Conversation
Block rm targets outside the project (/, ~, .., absolute paths), the project root itself, bare wildcards at the root, .git/.autoforge, unverifiable $VAR/`cmd` targets and --no-preserve-root. Every rm in a compound command is checked and preceding cd commands are tracked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Use the claude_code system prompt preset with our role appended - Declare the features MCP server transport type explicitly (stdio) - Allow overriding max_turns via AUTOFORGE_MAX_TURNS - Log SystemMessage and ResultMessage (turns, cost, error stops) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔍 QA report: ✅ PassedTester: Barbara (cubefarm agent, in a fresh session) · Round: 1 · Author: Ken Every item from #2 is either done or deliberately skipped with a reason. The preset system prompt, stdio MCP type, AUTOFORGE_MAX_TURNS, SystemMessage/ResultMessage logging, MCP fail-fast and the mcp<2 pin all work as described in my independent probes. The new rm validator blocks every listed dangerous case without breaking normal in-project deletes, and ruff, mypy and pytest show no regressions against master (the 24 mypy errors and 21 pytest failures are the same on master). Non-blocking follow-ups: brace expansion (
🧪 Commands run
No browser screenshots were taken in this round. Posted by cubefarm · merges automatically once GitHub's checks pass |
Closes #2
Goes through the SDK alignment and security items in #2. Some were already fixed on
master, some are done here, and the rest I skipped on purpose (reasons below).Changes
#1 Version pinning:
claude-agent-sdk>=0.1.39,<0.2.0was already on master. Addedmcp>=1.0.0,<2.0.0to both requirements files.mcponly came in through the SDK, so a fresh install picked up mcp 2.x. 2.x renamedFastMCP, andpython -m mcp_server.feature_mcpcrashed on import (ModuleNotFoundError: No module named 'mcp.server.fastmcp'). I reproduced this in a fresh venv.#2 System prompt preset (
client.py): now{"type": "preset", "preset": "claude_code", "append": <our role>}instead of a plain string that replaced Claude Code's built-in prompt.#3 Message types (
agent.py):run_agent_sessionnow also handles:SystemMessage: prints the subtype;initis skipped as noise.ResultMessage: prints subtype, turn count and cost. On an error stop (e.g.error_max_turns, API failure) it also prints theerrors/resultdetail.This is logging only; the return status and retry flow are unchanged. (
ErrorMessage/ProgressMessagedon't exist in the Python SDK.rate_limit_eventis already handled by the existingMessageParseErrorretry.)#4 MCP type: added
"type": "stdio"to the features server.#8 Configurable max_turns: a new
AUTOFORGE_MAX_TURNSenv var (positive integer) overrides the per-agent-type defaults (300/100/300). An invalid value is ignored with a warning.#9 MCP readiness (
mcp_server/feature_mcp.py): at startup the lifespan now runsSELECT COUNT(*) FROM features. If init, migration or that query fails, it prints[feature_mcp] FATAL: could not initialize feature database for PROJECT_DIR=...: <error>to stderr and exits. Before, the agent got a cryptic "Database not initialized" error on every tool call.#10
rmhardening (security.py): newvalidate_rm_command, run on everyrmin the command string (including after&&/;/|).Blocked:
/,/*,~,~/x,..,../x,src/../.., absolute paths elsewhere.,./)*,.*).gitand.autoforge$VARor`cmd`expansion--no-preserve-rootIt also follows
cdin the same command, socd .. && rm -rf projandcd / && rm -rf tmpare blocked. Aftercd $Xorcd -the target can't be checked, sormis blocked there.Still allowed:
rm -rf node_modules,rm -rf dist/*,rm *.log,cd src && rm -rf old,rm -rf .autoforge/tmp.Not changed (deliberately)
(input, tool_use_id, context), the same asHookCallbackinclaude_agent_sdk.types. The current signature is correct, andcontextis optional anyway.PreToolUseandPreCompactcover what we need today.rewind_files().Verification
python test_security.py: 205 passed, 0 failed. That includes the newtest_validate_rm(33 direct cases plus 3 run through the hook with a project context).python test_security_integration.py: all passed.pytest test_client.py test_dependency_resolver.py test_rate_limit_utils.py: 55 passed.ruff check .: clean.mypy .: no new errors. Theclient.py"unused type: ignore" oneffort=was already on master.initializeand createdfeatures.db. With a broken one (.autoforgeas a file) it printed the FATAL line and exited.Assumptions / notes
claude_codepreset is much longer than the old one-line prompt. Very small local models (Ollama) may notice the extra tokens. It's still the SDK-recommended setup, so I didn't add a per-provider special case.AutoForgeAI/autoforgereturned 403 for this account, so the branch is on thearkaccessfork. This is a cross-repo PR.🤖 Generated with Claude Code