From df9c56c44f09ac1448bea0dae12488f7959982e0 Mon Sep 17 00:00:00 2001 From: yu-sugimoto Date: Wed, 4 Mar 2026 14:19:49 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20dev=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=81=AE=E8=B5=B7=E5=8B=95=E5=A4=B1=E6=95=97=E6=99=82?= =?UTF-8?q?=E3=81=AB=E8=87=AA=E5=8B=95=E4=BF=AE=E6=AD=A3=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/worker-implement.py | 77 +++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/docker/worker-implement.py b/docker/worker-implement.py index 3a20a62..25a6e59 100644 --- a/docker/worker-implement.py +++ b/docker/worker-implement.py @@ -186,6 +186,47 @@ async def _process_messages(client: ClaudeSDKClient, phase: str) -> None: _emit_tool_detail(phase, block.name, json.dumps(block.input)) +async def kill_dev_servers(repo_dir: str) -> None: + """Kill any lingering dev server processes (node, vite, next, etc.).""" + for pattern in ["node", "vite", "next"]: + subprocess.run( + ["pkill", "-f", pattern], + capture_output=True, + ) + # Give processes time to terminate + await asyncio.sleep(2) + + +async def fix_with_claude(repo_dir: str, error_message: str) -> None: + """Use Claude to diagnose and fix the dev server launch failure.""" + options = ClaudeAgentOptions( + allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep"], + cwd=repo_dir, + max_turns=20, + max_budget_usd=1.5, + include_partial_messages=True, + ) + + async with ClaudeSDKClient(options=options) as client: + await client.query(f"""The dev server failed to start in the project at {repo_dir}. + +Here is the error output: + +``` +{error_message} +``` + +Please diagnose and fix the issue. Common causes include: +- Missing or incorrect dependencies (run `npm install` or similar) +- Build errors in the source code (syntax errors, import errors, type errors) +- Port conflicts (change the port configuration) +- Missing environment variables or config files + +Fix the code so the dev server can start successfully. Make minimal, targeted changes. +""") + await _process_messages(client, "implementing") + + async def launch_and_screenshot(repo_dir: str, screenshot_output: str) -> None: """Launch dev server and take screenshot in a single session. @@ -228,6 +269,13 @@ async def launch_and_screenshot(repo_dir: str, screenshot_output: str) -> None: """) await _process_messages(client, "screenshot") + # Verify screenshot was actually created + if not Path(screenshot_output).exists(): + raise RuntimeError( + f"Screenshot was not created at {screenshot_output}. " + "The dev server likely failed to start or the screenshot command failed." + ) + async def main() -> None: # Read environment variables @@ -320,8 +368,33 @@ async def main() -> None: emit_log("implementing", "Implementing design proposal") await implement_changes(repo_dir, proposal_plan) - # Launch + screenshot in a single session (shares dev server URL context) - await launch_and_screenshot(repo_dir, screenshot_path) + # Launch + screenshot with retry loop + max_retries = 2 # up to 3 total attempts + last_error = None + for attempt in range(max_retries + 1): + try: + await launch_and_screenshot(repo_dir, screenshot_path) + last_error = None + break # success + except Exception as e: + last_error = str(e) + if attempt < max_retries: + emit_log( + "implementing", + f"Dev server launch failed (attempt {attempt + 1}/{max_retries + 1}), attempting fix...", + detail=last_error, + ) + await kill_dev_servers(repo_dir) + await fix_with_claude(repo_dir, last_error) + else: + emit_log( + "implementing", + f"Dev server launch failed after {max_retries + 1} attempts, proceeding without screenshot", + detail=last_error, + ) + + if last_error: + emit_log("implementing", "WARNING: Could not launch dev server, screenshot may be missing") # Step 4: Generate cumulative patch (squash everything since base_branch) emit_log("uploading", "Generating cumulative patch") From e77a20d9928130d1bcc3cd5a63ea51af51e37ed1 Mon Sep 17 00:00:00 2001 From: yu-sugimoto Date: Wed, 4 Mar 2026 14:20:11 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat=20.dockerignore=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=BF=98=E3=82=8C=E3=81=A6=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..328bdc9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,38 @@ +# Node.js +frontend/node_modules/ +**/node_modules/ +npm-debug.log* +yarn-debug.log* + +# Python +**/__pycache__/ +*.py[cod] +backend/.venv/ +backend/.mypy_cache/ +backend/.ruff_cache/ +backend/.pytest_cache/ + +# Git +.git/ + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db + +# Temporary / build artifacts +tmp/ +*.log +.cache/ +dist/ +build/ + +# K8s configs (not needed in image) +k8s/ + +# Environment files +.env +.env.*