diff --git a/ROADMAP.md b/ROADMAP.md index 824158c9..0988dfb3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6475,3 +6475,6 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 466. **Syntactically valid MCP config with a nonexistent command is reported as healthy/configured by `doctor`, `mcp`, and `status` instead of surfacing executable reachability as degraded** — dogfooded 2026-05-19 from the `#clawcode-building-in-public` 20:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with `./rust/target/debug/claw version --output-format json` reporting `git_sha:"25d663d"`. In a temp workspace containing only `.claw.json` with `mcpServers.broken.command:"/definitely/not/a/real/mcp-server"`, clean-home text probes showed `doctor` exits 0 with `Failures 0`, `Config Status ok`, and `Boot preflight ... mcp=true · servers 1`; `mcp` exits 0 and lists `broken stdio project /definitely/not/a/real/mcp-server --serve`; `status` exits 0 and reports `Boot preflight ... mcp=true plugins=true last_failed=none`. None of the three surfaces attempts even a cheap executable existence/PATH reachability check, so a server that cannot possibly launch is indistinguishable from a configured usable MCP server until the first runtime tool call fails. This is distinct from malformed-config degraded-mode items (#143/#144/#440): here the JSON shape is valid and the parser succeeds, but lifecycle readiness is false. **Required fix shape:** (a) add an MCP executable preflight pass that classifies each stdio server as `reachable:true|false|unknown` using absolute-path existence/executable-bit checks and PATH lookup for bare commands, without launching untrusted code; (b) expose per-server fields in `claw mcp` / JSON (`launch_status`, `command_exists`, `command_executable`, `path_resolution`, `error_kind:"mcp_command_not_found"`); (c) make `doctor` add an `mcp_reachability` check with `status:"warn"` or `"fail"` when any configured server command is missing; (d) make `status` distinguish `mcp_configured:true` from `mcp_reachable:false` instead of the current single `mcp=true`; (e) regression test with one valid `/bin/echo` server and one nonexistent absolute path proving partial status is reported. **Fresh mixed-PATH proof (21:00 UTC):** a temp config containing one PATH-resolvable server (`pathEcho.command:"echo"`) and one missing bare command (`missingBare.command:"definitely-not-a-real-mcp-bare-command-xyz"`) still made `mcp` list both as configured, `doctor` report `Failures 0` and `mcp=true · servers 2`, and `status` report `mcp=true` with no degraded marker. So the fix must handle both absolute paths and PATH lookup for bare commands, and it must preserve partial success (`echo` reachable, missingBare not found) instead of collapsing both into `configured`. **Why this matters:** MCP failures are often setup/path mistakes. If doctor says failures 0 and mcp=true while the command path does not exist, claws and users waste turns discovering the break only after a blocked tool call. Source: gaebal-gajae dogfood response to Clawhip messages `1506393539385491598` and `1506401088801083495` on 2026-05-19. + + +467. **Bare `claw plugins` / `claw plugin` returns the plugin inventory, but the natural explicit action `claw plugins list` / `claw plugin list` zero-byte hangs; singular/plural aliases are wired for the default action but not for the `list` subaction** — dogfooded 2026-05-19 from the `#clawcode-building-in-public` 21:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with `./rust/target/debug/claw version --output-format json` reporting `git_sha:"25d663d"`. In isolated clean `HOME`/`CLAW_CONFIG_HOME`, `plugins` and `plugin` each exited 0 and printed the two bundled plugins (`example-bundled`, `sample-hooks`) in text mode. But `plugins list` and `plugin list` each timed out after 8s with `stdout=0` and `stderr=0`. `plugins help` and `plugin help` also timed out, while direct `/plugins` and `/plugin` were rejected as interactive-only, showing that there are at least three parser paths for the same lifecycle namespace. This is a narrower current-main follow-up to the historical plugin route/help items (#78/#145/#348/#420/#454/#455): the route now exists for the default inventory, but adding the explicit canonical `list` action drops into a different non-returning path. **Required fix shape:** (a) normalize `plugin` and `plugins` aliases plus omitted action into one parser action before dispatch (`None` and `Some("list")` must be equivalent); (b) route `help` to static plugin help before plugin registry/lifecycle initialization; (c) add a deterministic timeout guard or typed `plugin_action_unavailable` envelope around plugin action dispatch so unsupported/misparsed actions cannot hang silently; (d) add clean-home regression coverage for `plugins`, `plugins list`, `plugin`, `plugin list`, `plugins help`, and `plugin help` in text and JSON modes, proving the first four produce the same inventory and help emits bounded usage. **Why this matters:** `list` is the most obvious plugin lifecycle action and is already the documented/discovery word from other lifecycle namespaces (`mcp list`, `agents list`, `skills list`). If bare inventory works but explicit list hangs, claws cannot safely choose between terse default and explicit action forms, and plugin support remains trial-and-error. Source: gaebal-gajae dogfood response to Clawhip message `1506408638883954768` on 2026-05-19.