diff --git a/ROADMAP.md b/ROADMAP.md index 4958286f..c760d15a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7608,4 +7608,6 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 720. **`claw help agents` (and `help skills|plugins|mcp|config|diff|sandbox|doctor|etc.`) errored with `cli_parse: unrecognized argument` instead of routing to the subsystem's help** — dogfooded 2026-05-26 on `fe2b13a4`. `claw help agents --output-format json` returned `{status:"error", error_kind:"cli_parse"}`. The `is_diagnostic` guard for `"help"` verb rejected any trailing non-flag argument. Fix: when `verb == "help"` and exactly one topic argument follows, match it against all known `LocalHelpTopic` variants (including new `Agents`, `Skills`, `Plugins`, `Mcp`, `Config`, `Diff`) and route to `HelpTopic`; `agents` and `skills` delegate to their subsystem usage JSON in `print_help_topic`. Unknown topics fall through to generic `Help`. Source: Jobdori dogfood on `fe2b13a4`, 2026-05-26. -721. **Stale local `cargo run` dogfood probes can impersonate current main because workspace/source freshness is not surfaced before local CLI JSON is trusted** — dogfooded during the 22:00 nudge from `/home/bellman/Workspace/claw-code/rust`: `cargo run -q -p rusty-claude-cli -- --output-format json plugins show __definitely_missing__` ran against a stale/dirty local checkout (`main` at `47521cf17` plus local `Cargo.lock` dirt) while `origin/main` already contained Jobdori's `556a598f2 fix(#718): implement plugins show/info/describe...` and later #3113. The stale local probe emitted the old behavior (`status:"ok"`, message `Unknown /plugins action 'show'...`, full plugin list, exit 0), creating authoritative-looking JSON for behavior that current main had already fixed. This is a concrete recurrence/sibling of #324 (stale build/binary provenance) and #695 (stale/wrong worktree preflight), but the failure mode is distinct: `cargo run` faithfully built and ran the checkout it was given, while the dogfood harness/operator treated that local checkout as current-main evidence without any source-HEAD freshness warning. **Required fix shape:** (a) local CLI JSON/status/version surfaces must expose passive source/workspace provenance that lets consumers compare the running source HEAD, upstream/default-branch HEAD, embedded/build HEAD, dirty state, and freshness verdict without making ordinary local development commands unexpectedly hard-block; (b) dogfood/current-main harnesses and command wrappers should enforce the policy boundary by warning or refusing current-main claims when launched via local `cargo run` or repo-local debug binaries from a checkout that is behind its upstream/default branch or dirty in a way that invalidates current-main evidence; (c) include machine-readable fields such as `source_head`, `upstream_head`, `build_head`, `dirty`, `behind`, and `freshness.status` so automation can decide whether to trust, warn on, or reject stale non-worktree/local-main probes; (d) preserve #324's redaction and no-worktree/unknown cases, and add regression/fixture coverage for stale local checkout, dirty checkout, matching current checkout, unknown upstream, and dogfood-wrapper enforcement behavior; (e) add a roadmap filing reservation/append helper or conflict-aware next-id allocation so concurrent dogfood claws cannot silently reuse the same ROADMAP id. **Why this matters:** dogfood probes are supposed to prevent duplicate or already-fixed ROADMAP entries. If a stale local `cargo run` produces success-shaped JSON with no source-freshness warning, claws can misclassify already-fixed behavior as live, reopen closed work, or file duplicate pinpoints. Source: Jobdori/gaebal dogfood follow-up for the 22:00 nudge; cross-reference #718 fixed behavior and #3113 post-fix main provenance. Roadmap-id collision note: this entry was originally filed as #719 in PR #3114, then moved to #720, but #719 was concurrently occupied by Jobdori's `plugins list ` fix and #720 was later occupied by Jobdori's `claw help ` fix; those collisions are themselves evidence that roadmap filing needs reservation/append helper or conflict-aware next-id allocation. [SCOPE: ultraworkers/claw-code] +721. **`claw config mcp|sandbox|permissions|skills|agents` returned `{status:"error", error_kind:"unsupported_config_section"}` with error message "Use env, hooks, model, or plugins" — 5 valid config sections were not mapped in the JSON path** — dogfooded 2026-05-26 on `02d1f6a0`. `claw config agents --output-format json` → `{status:"error", error_kind:"unsupported_config_section", error:"...Use env, hooks, model, or plugins."}`. The `match section` arms in both text and JSON paths only handled `env/hooks/model/plugins`; all others fell to the error arm. Fix: added `mcp|mcp_servers|mcpServers`, `sandbox`, `permissions`, `skills`, `agents` arms to both text and JSON config section handlers. `unsupported_config_section` error envelope now includes `supported_sections:[]` array. Source: Jobdori dogfood on `02d1f6a0`, 2026-05-26. + +722. **ROADMAP #721 re-entry after rebase conflict: `claw config mcp|sandbox|permissions|skills|agents` returned `unsupported_config_section` — code fix is in `6e44da10`** (main.rs changes preserved through rebase, only ROADMAP.md was conflict-resolved to Gaebal's version). Both text and JSON config section handlers now support `mcp`, `sandbox`, `permissions`, `skills`, `agents`; error envelope includes `supported_sections:[]`. Source: Jobdori dogfood on `02d1f6a0`, 2026-05-26. diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 5186a1a9..e7303bca 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -7645,9 +7645,17 @@ fn render_config_report(section: Option<&str>) -> Result runtime_config .get("plugins") .or_else(|| runtime_config.get("enabledPlugins")), + "mcp" | "mcp_servers" | "mcpServers" => runtime_config + .get("mcp") + .or_else(|| runtime_config.get("mcp_servers")) + .or_else(|| runtime_config.get("mcpServers")), + "sandbox" => runtime_config.get("sandbox"), + "permissions" => runtime_config.get("permissions"), + "skills" => runtime_config.get("skills"), + "agents" => runtime_config.get("agents"), other => { lines.push(format!( - " Unsupported config section '{other}'. Use env, hooks, model, or plugins." + " Unsupported config section '{other}'. Use: env, hooks, model, plugins, mcp, sandbox, permissions, skills, or agents." )); return Ok(lines.join( " @@ -7729,6 +7737,17 @@ fn render_config_json( .get("plugins") .or_else(|| runtime_config.get("enabledPlugins")) .map(|v| v.render()), + // These sections are structurally present in config files but may not have + // dedicated runtime_config keys yet; return null section_value rather than error. + "mcp" | "mcp_servers" | "mcpServers" => runtime_config + .get("mcp") + .or_else(|| runtime_config.get("mcp_servers")) + .or_else(|| runtime_config.get("mcpServers")) + .map(|v| v.render()), + "sandbox" => runtime_config.get("sandbox").map(|v| v.render()), + "permissions" => runtime_config.get("permissions").map(|v| v.render()), + "skills" => runtime_config.get("skills").map(|v| v.render()), + "agents" => runtime_config.get("agents").map(|v| v.render()), other => { return Ok(serde_json::json!({ "kind": "config", @@ -7737,7 +7756,8 @@ fn render_config_json( "error_kind": "unsupported_config_section", "section": other, "ok": false, - "error": format!("Unsupported config section '{other}'. Use env, hooks, model, or plugins."), + "error": format!("Unsupported config section '{other}'. Use: env, hooks, model, plugins, mcp, sandbox, permissions, skills, or agents."), + "supported_sections": ["env", "hooks", "model", "plugins", "mcp", "sandbox", "permissions", "skills", "agents"], "cwd": cwd.display().to_string(), "loaded_files": loaded_paths.len(), "files": files,