## Implementation Plan: XML-RPC Bridge Crash Loop ### Changes Required #### 1. `devplacepy/services/xmlrpc/__init__.py` - **Line 32-37 (`_spawn()` method)**: Change `stderr=subprocess.DEVNULL` to `stderr=subprocess.PIPE`. - **After `_spawn()` (before the log line at line 38)**: Add a short sleep (0.5–1 second) then call `self._alive()`. If the process is dead, read `self._process.stderr` (decoded) and log the captured output along with the return code (from `self._process.returncode`). Then return without logging success. - **In `run_once()` (line 63-68)**: After detecting the process is not alive, log the exit code (`self._process.returncode`) and optionally any captured stderr that may have been stored, before respawning. #### 2. `devplacepy/services/xmlrpc/server.py` - **Lines 112-120 (`main()` function)**: Wrap the entire body (from the subprocess call through `serve_forever()`) in a `try/except` that catches `BaseException`, logs the exception traceback to stderr with a descriptive message, then calls `sys.exit(1)`. #### 3. Test / environment (if needed for verification) The project’s verification commands (`pip install -e .[dev] -q && make test-unit` and `pip install -q ruff && ruff check .`) may fail in restricted Python environments (PEP 668). To ensure the agent can run them reliably: - Create a temporary Python virtual environment (e.g., `python3 -m venv .venv && source .venv/bin/activate`). - Then run the verification commands inside that venv. ### Definition of Done The change is complete and correct when **all** of the following are true: - [ ] The two source files above have been modified as described. - [ ] In a clean copy of the repository, test and lint commands pass: - `make test-unit` (or `python -m pytest tests/ -x -q`, depending on the repo’s Makefile) succeeds with no failures. - `ruff check .` passes with no errors. - [ ] The modifications are minimal and do not alter the external API or introduce new imports beyond `logging`, `sys`, and `time` (already imported or standard library). - [ ] A manual review confirms that stderr is no longer silenced, and that a port conflict or internal exception in `main()` is logged and does not cause a silent crash.