# Wall-E MCP Supervisor Health

CTM serves Wall-E to coding agents through the provider-native `wall-e` MCP stdio bridge. The bridge proxies JSON-RPC to the local Wall-E daemon at `127.0.0.1:3457/mcp`; when the daemon is down it asks the CTM supervisor at `127.0.0.1:3456/api/start/walle` to start it.

## Startup Contract

Wall-E MCP startup has two separate readiness contracts:

- **CTM supervisor readiness**: `/api/start/walle` and `/api/restart/walle` only return success after the daemon answers MCP `initialize`, answers `tools/list`, exposes `walle_memory_status`, and successfully runs `tools/call` for `walle_memory_status`. Spawning a process is not enough.
- **Provider stdio readiness**: the provider-native stdio bridge must not fail MCP `initialize` or `tools/list` just because the daemon is still starting. If CTM cannot make the daemon ready, stdio enters a degraded MCP mode that exposes only `walle_memory_status`.

This prevents the recurring failure where Codex/Claude remove the `wall-e` MCP server during handshake because `127.0.0.1:3457` briefly refused connections after CTM restart.

In degraded stdio mode:

- `initialize` returns a valid Wall-E MCP serverInfo object with `degraded: true`;
- `tools/list` returns only `walle_memory_status`;
- `resources/list`, `resources/templates/list`, and `prompts/list` return empty lists;
- `tools/call` for `walle_memory_status` returns structured health with `mode: "stdio-degraded"` and the daemon/CTM ports;
- other tool calls return an MCP tool error result instead of a JSON-RPC handshake error.

The embedded brain DB fallback remains opt-in through `WALLE_MCP_EMBEDDED_DB=1`. Normal provider traffic should go through the daemon so there is one owner for SQLite, live connectors, CTM session context, and telemetry.

## Native Dependency Preflight

Wall-E uses native SQLite modules (`better-sqlite3` and `sqlite-vec`). After a Node upgrade, those modules can fail before Wall-E can bind the HTTP/MCP port. A stale `walle.pid` then turns into a generic `ECONNREFUSED` unless CTM diagnoses the start failure.

Before every supervised Wall-E start or restart, CTM now runs a preflight in the same Node binary that will launch Wall-E:

- load `better-sqlite3`;
- open an in-memory database and run `PRAGMA quick_check`;
- load `sqlite-vec` into that database;
- classify failures as `native_dependency_abi_mismatch`, `native_dependency_missing`, `native_dependency_load_failed`, or `native_dependency_check_timeout`.

For rebuildable failures CTM runs:

```sh
npm rebuild better-sqlite3 sqlite-vec
```

Then it repeats the preflight. CTM only spawns Wall-E after the second check passes.

### Shared `node_modules` Guard

The rebuild path is only safe when the Wall-E checkout owns its own
`wall-e/node_modules` directory. A worktree may symlink
`wall-e/node_modules` to the primary checkout to save install time; that is
fine while every process uses the same Node runtime, but it is unsafe for
native auto-repair. If a Node 26 worktree rebuilds the primary checkout's
`better_sqlite3.node`, the primary Node 25 daemon can no longer load it; if the
primary daemon then rebuilds, the worktree breaks. The symptom is an apparent
compile/load loop where the binary alternates between two `NODE_MODULE_VERSION`
values.

CTM now inspects `wall-e/node_modules` before automatic install/rebuild. If the
directory resolves outside the current Wall-E checkout, native dependency
failures are reported as diagnostics but CTM refuses to mutate the shared
install. The correct fixes are:

- run the worktree with the same Node binary as the owner checkout; or
- install isolated Wall-E dependencies in that worktree so its native addon
  build belongs to that worktree.

## Operator Behavior

This flow does not require restarting the CTM primary process. A provider MCP bridge or the CTM UI can call `/api/start/walle`; the supervisor will repair native modules when possible and start only the Wall-E daemon.

If repair fails, CTM exposes structured status:

- `/api/services/status` includes `walle.code`, `walle.error`, `walle.native_dependency`, `walle.last_start_error`, and `walle.mcp_ready`;
- proxied Wall-E routes return a 502 JSON body with the same diagnostic fields instead of only `connect ECONNREFUSED`;
- the stdio MCP bridge reports the CTM start failure through degraded `walle_memory_status` whenever the MCP method can be degraded safely.

If CTM spawns Wall-E but MCP never becomes ready, `/api/start/walle` returns HTTP 503 with `code: "walle_mcp_ready_timeout"` and the failed readiness probe details. That is intentionally different from a successful process start: the client needs tools, not just a PID.

## MCP Smoke Test

After recovery, verify the daemon rather than only the process:

1. `POST /mcp` with `initialize`.
2. `POST /mcp` with `tools/list`.
3. `POST /mcp` with `tools/call` for `walle_memory_status`.

All three must succeed before declaring Wall-E MCP reachable.

For provider startup resilience, also test the daemon-down path with self-heal disabled. The stdio bridge should still answer `initialize`, `tools/list`, and `tools/call walle_memory_status` without opening `wall-e-brain.db`.
