mirror of
https://github.com/instructkr/claude-code.git
synced 2026-05-13 17:36:44 +00:00
Compare commits
18 Commits
docs/roadm
...
docs/roadm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b4c2c6e3d | ||
|
|
8e24f3049e | ||
|
|
71d8e7b925 | ||
|
|
19947545e2 | ||
|
|
f7b2d8d6fe | ||
|
|
6f92e54dc0 | ||
|
|
31d9198a02 | ||
|
|
5eb1d7d824 | ||
|
|
3b03375e69 | ||
|
|
0f9e8915be | ||
|
|
ab95b75fcd | ||
|
|
ee44ff984d | ||
|
|
2ab26df4bd | ||
|
|
a2a38df9b8 | ||
|
|
fd90c9fe67 | ||
|
|
cca6f6829c | ||
|
|
c77d1a87e1 | ||
|
|
ee41b266d3 |
10
ROADMAP.md
10
ROADMAP.md
@@ -6286,3 +6286,13 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
|
||||
344. **Resume-safe `/config help --output-format json` is treated as an unsupported config section instead of a structured config-section discovery surface** — dogfooded 2026-04-29 for the 18:30 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `a510f734`. Running `./rust/target/debug/claw --resume latest /config help --output-format json` wrote no stdout bytes and emitted stderr JSON: `{"command":"/config help","error":"Unsupported /config section 'help'. Use env, hooks, model, or plugins.\n Usage /config [env|hooks|model|plugins]\n\n/config\n Summary Inspect Claude config files or merged sections\n Usage /config [env|hooks|model|plugins]\n Category Config\n Resume Supported with --resume SESSION.jsonl","type":"error"}`. The same shape appears for natural discovery forms such as `/config list` and `/config show`, while bare `/config --output-format json` succeeds and returns config-file data. The config surface is therefore resume-supported, but its section discovery/help path is only available as a human-formatted error string on stderr, with no structured `sections[]`, no `help` alias, and no typed `unsupported_section` metadata. This is distinct from #342's missing slash-command index and #343's dead-end suggestion: the pinpoint is a command-specific subcommand/section discovery contract for an otherwise working resume-safe command. **Required fix shape:** (a) make `/config help` or `/config sections` resume-safe and return stdout JSON containing supported sections such as `env`, `hooks`, `model`, and `plugins`; (b) for unsupported config sections, emit a typed JSON envelope with `kind:"error"` or equivalent plus `code:"unsupported_config_section"`, `section`, and structured `supported_sections[]`; (c) keep human usage text optional, not the only machine-readable recovery path; (d) add regression coverage proving `/config help --output-format json` or its canonical replacement exposes structured section metadata and that `/config list`/`show` errors include structured supported-section guidance. **Why this matters:** config inspection is a control-plane surface. Claws should not have to intentionally trigger an error and scrape prose to learn which config sections can be inspected under `--resume`; section discovery needs the same machine-readable contract as the config payload itself. Source: gaebal-gajae dogfood follow-up for the 18:30 nudge on rebuilt `./rust/target/debug/claw` `a510f734`.
|
||||
345. **Resume-safe `/config env|hooks|model|plugins --output-format json` accepts different section names but returns the same generic config-file summary for every section** — dogfooded 2026-04-29 for the 19:00 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `a510f734`. Running `./rust/target/debug/claw --resume latest /config env --output-format json`, `/config hooks`, `/config model`, and `/config plugins` all wrote stdout JSON successfully and no stderr, but each response had the same top-level shape and values: `kind:"config"`, `cwd`, `files[]`, `loaded_files:1`, and `merged_keys:1`. None of the outputs included the requested `section`, section-specific keys, hook/model/plugin/env data, `section_missing`, `section_empty`, or truncation metadata; the `env`, `hooks`, `model`, and `plugins` arguments appear to be accepted while producing an indistinguishable generic config summary. This is distinct from #344's missing config-section discovery/help path: the pinpoint here is that the advertised section-specific entrypoints do not produce section-specific machine-readable payloads once invoked. **Required fix shape:** (a) include a `section` field in `/config <section> --output-format json` responses; (b) return section-specific structured payloads for `env`, `hooks`, `model`, and `plugins`, with explicit empty/missing states when applicable; (c) preserve the config-file provenance summary separately from the requested section content so callers can tell what was inspected; (d) add regression coverage proving the four supported sections produce distinguishable JSON contracts and do not silently collapse to the bare `/config` summary. **Why this matters:** config inspection is used to diagnose model, hook, plugin, and env lifecycle issues. If every supported section returns the same generic file list, claws cannot tell whether a section is empty, unsupported, redacted, or simply ignored, and config troubleshooting remains prose/error archaeology instead of structured state inspection. Source: gaebal-gajae dogfood follow-up for the 19:00 nudge on rebuilt `./rust/target/debug/claw` `a510f734`.
|
||||
346. **Top-level `agents show <name> --output-format json` accepts a natural agent-detail request but falls back to generic help JSON instead of returning the selected agent or a typed unsupported-detail error** — dogfooded 2026-04-29 for the 20:00 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `c6c01bea`. Running `./rust/target/debug/claw agents list --output-format json` returned a valid stdout JSON inventory with `kind:"agents"`, `action:"list"`, and an `agents[]` entry named `analyst`. Immediately running `./rust/target/debug/claw agents show analyst --output-format json` returned success on stdout but did not return the `analyst` detail object; instead it returned generic help-shaped JSON: `{"action":"help","kind":"agents","unexpected":"show analyst","usage":{"direct_cli":"claw agents [list|help]","slash_command":"/agents [list|help]",...}}`. Both stderr streams were empty. The command therefore accepts a natural detail-inspection spelling, recognizes it only as `unexpected`, and hides the absence of an agent-detail surface behind a successful help fallback rather than a typed `unsupported_agents_action` / `agent_detail_unavailable` error. This is distinct from #328 and #329: those cover source/provenance mismatch and slash `/agents` inventory flattening, while this pinpoint is the missing top-level agent detail/inspection contract after inventory discovery succeeds. **Required fix shape:** (a) either implement `agents show <name> --output-format json` returning the selected agent's structured fields and provenance, or return a non-success typed JSON error with `code:"unsupported_agents_action"`, `requested_action:"show"`, and `supported_actions:["list","help"]`; (b) include `agent_name` and whether the name exists in the current inventory when rejecting detail inspection; (c) avoid `action:"help"` success envelopes for unsupported subcommands because they make failed detail inspection look like intentional help output; (d) add regression coverage proving `agents show analyst --output-format json` does not silently collapse to generic help when `analyst` exists in `agents list`. **Why this matters:** claws discover agents first, then need to inspect a chosen agent before delegation. If the natural detail command returns successful generic help instead of a selected-agent payload or typed unsupported-action error, automation cannot distinguish typo, unsupported detail view, missing agent, or successful help request without comparing unrelated inventory output. Source: gaebal-gajae dogfood follow-up for the 20:00 nudge on rebuilt `./rust/target/debug/claw` `c6c01bea`; earlier false hang hypotheses for `mcp help` and `agents list` were closed after bounded repros succeeded.
|
||||
347. **Top-level `mcp show <missing-server> --output-format json` reports a missing server as `status:"ok"` instead of a typed not-found/error status** — dogfooded 2026-04-29 for the 20:30 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `ee41b266`. After rebuilding and verifying the binary provenance, running `./rust/target/debug/claw mcp show does-not-exist --output-format json` returned stdout JSON with `{"action":"show","config_load_error":null,"found":false,"kind":"mcp","message":"server `does-not-exist` is not configured","server_name":"does-not-exist","status":"ok"}` and no stderr. `found:false` is useful, but pairing it with `status:"ok"` makes the command-level outcome ambiguous: a missing requested server is not an OK inspection result for automation that needs to distinguish successful detail retrieval from a not-found lookup. This is distinct from #327's MCP source-list mismatch and the invalid #2874/#2879/#2880 hang/nondeterminism hypotheses that were closed after bounded repros. **Required fix shape:** (a) return a typed not-found status such as `status:"not_found"` or `kind:"error"` plus `code:"mcp_server_not_found"` while preserving `server_name` and optional `available_servers[]`; (b) document whether `found:false` objects are considered success or error and keep that convention consistent across text and JSON modes; (c) ensure process exit semantics match the JSON status contract or expose a separate `exit_ok`/`lookup_status` field; (d) add regression coverage proving missing-server lookup is distinguishable from successful server detail retrieval without parsing the human `message`. **Why this matters:** MCP inspection is a control-plane diagnostic. If a missing server returns `status:"ok"`, claws can silently treat a failed lookup as healthy MCP state unless they special-case `found:false`, which defeats the purpose of a clear machine-readable status field. Source: gaebal-gajae dogfood follow-up for the 20:30 nudge on rebuilt `./rust/target/debug/claw` `ee41b266`.
|
||||
348. **Top-level `plugins list --output-format json` returns plugin inventory only as a prose `message` string instead of structured `plugins[]` entries** — dogfooded 2026-04-29 for the 21:00 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `cca6f682`. Running `./rust/target/debug/claw plugins list --output-format json` repeatedly returned valid stdout JSON with `{"action":"list","kind":"plugin","message":"Plugins\n example-bundled v0.1.0 disabled\n sample-hooks v0.1.0 disabled","reload_runtime":false,"target":null}` and no stderr. The actual plugin names, versions, and enabled/disabled states are present only inside the human-formatted `message` table; there is no `plugins[]` array, no per-plugin `name`, `version`, `enabled`, `source`, `load_error`, or lifecycle/action metadata. This is distinct from #325's broad help JSON opacity and the config/MCP/agent items: the affected surface is plugin lifecycle inventory, where automation needs a structured list before enabling, disabling, updating, or uninstalling plugins. **Required fix shape:** (a) add `plugins[]` with stable per-plugin fields such as `name`, `version`, `enabled`, `source`, `configured`, `load_status`, and optional `error`; (b) keep `message` only as a human summary, not the sole inventory payload; (c) expose counts and truncation metadata if the list can be large; (d) add regression coverage proving `plugins list --output-format json` can be parsed without scraping the prose message and that disabled/enabled state survives as booleans/enums. **Why this matters:** plugin lifecycle management is a control-plane path. If the JSON inventory is just a text table, claws must scrape spacing-sensitive prose before deciding whether a plugin is installed, disabled, broken, or safe to mutate. Source: gaebal-gajae dogfood follow-up for the 21:00 nudge on rebuilt `./rust/target/debug/claw` `cca6f682`.
|
||||
349. **Top-level `plugins show <name> --output-format json` returns success-shaped JSON for an unsupported plugin action instead of a typed unsupported-action error** — dogfooded 2026-04-29 for the 21:30 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `a2a38df9`. After rebuilding and verifying the binary provenance, repeated bounded runs of `./rust/target/debug/claw plugins show does-not-exist --output-format json` returned stdout JSON with `{"action":"show","kind":"plugin","message":"Unknown /plugins action 'show'. Use list, install, enable, disable, uninstall, or update.","reload_runtime":false,"target":"does-not-exist"}` and no stderr. The command therefore reports the requested unsupported action as the top-level `action:"show"` and exits successfully while hiding the failure class inside a human `message`; it does not provide `status:"unsupported_action"`, `code:"plugin_action_unsupported"`, or structured `supported_actions[]`. This is distinct from #348's prose-only plugin inventory schema: #348 covers `plugins list` payload shape, while this pinpoint covers unsupported plugin action classification and recovery metadata. **Required fix shape:** (a) return a typed stdout JSON error or explicit non-ok status for unsupported plugin actions, with `requested_action`, `supported_actions`, and `target` fields; (b) do not label the primary `action` as the unsupported requested verb unless a separate `status`/`code` makes the failure unambiguous; (c) keep the human message optional and avoid making it the only way to detect the unsupported action; (d) add regression coverage proving `plugins show foo --output-format json` is machine-classifiable as unsupported without scraping prose. **Why this matters:** plugin lifecycle automation follows action/status fields. If an unsupported mutation/inspection verb returns success-shaped JSON and only says "Unknown" in prose, claws can treat a failed preflight as a valid plugin show result and continue toward unsafe lifecycle actions. Source: gaebal-gajae dogfood follow-up for the 21:30 nudge on rebuilt `./rust/target/debug/claw` `a2a38df9`; invalid hang PR #2885 was closed after repeated bounded repros returned stdout JSON.
|
||||
350. **Top-level `plugins enable <missing-plugin> --output-format json` hangs with zero stdout/stderr instead of returning a typed plugin-not-found or unsupported-target response** — dogfooded 2026-04-29 for the 22:00 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `ee44ff98`. After rebuilding and verifying the binary provenance, repeated bounded runs of `timeout 8 ./rust/target/debug/claw plugins enable does-not-exist --output-format json` exited `124` with `stdout=0` and `stderr=0`; a third sample was still stuck until killed. In the same rebuilt binary, `plugins list --output-format json` returned promptly with the known plugin inventory payload, proving the plugin top-level surface is reachable and narrowing the hang to missing-plugin lifecycle mutation. This is distinct from #348's prose-only list inventory and #349's unsupported `plugins show` success-shaped JSON: #350 covers a supported lifecycle verb (`enable`) against an absent target, where the CLI should be able to fail fast before any plugin runtime work. **Required fix shape:** (a) validate the target plugin against the discovered/configured inventory before invoking enable-side effects; (b) return bounded stdout JSON such as `kind:"plugin"`, `action:"enable"`, `status:"not_found"` or `kind:"error"`, `code:"plugin_not_found"`, `plugin`, and optional `available_plugins[]`; (c) add internal timeout/diagnostic metadata for plugin lifecycle operations so registry or hook stalls do not produce silent zero-byte hangs; (d) add regression coverage proving `plugins enable does-not-exist --output-format json` returns a typed JSON outcome within a deterministic budget and does not mutate plugin state. **Why this matters:** enable/disable/update/uninstall are destructive control-plane actions. A missing or stale plugin name must fail safely and machine-readably; otherwise claws cannot preflight plugin lifecycle operations, distinguish typo from loader deadlock, or recover without killing a hung process. Source: gaebal-gajae dogfood follow-up for the 22:00 nudge on rebuilt `./rust/target/debug/claw` `ee44ff98`.
|
||||
351. **Top-level `plugins disable <missing-plugin> --output-format json` sends the JSON error envelope to stderr only, leaving stdout empty** — dogfooded 2026-04-29 for the 22:30 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `0f9e8915`. After rebuilding and verifying the binary provenance, repeated bounded runs of `timeout 8 ./rust/target/debug/claw plugins disable does-not-exist --output-format json` exited `1` with `stdout=0` and `stderr=113`; stderr contained JSON (`{"error":"plugin `does-not-exist` is not installed or discoverable","hint":null,"kind":"unknown","type":"error"}`), but stdout was empty. In the same rebuilt binary, `plugins list --output-format json` returned stdout JSON promptly with the known plugin inventory payload, proving the plugin command surface is reachable. This is distinct from #350's missing-target `plugins enable` zero-byte timeout: the disable path fails fast, but its JSON-mode error envelope is routed to stderr and uses generic `kind:"unknown"`/`type:"error"` instead of a plugin-specific stdout outcome. **Required fix shape:** (a) define and consistently document whether JSON mode emits machine-readable envelopes on stdout, stderr, or both for nonzero exits; (b) return a plugin-specific typed error with `kind:"plugin"` or `domain:"plugin"`, `action:"disable"`, `status:"not_found"` or `code:"plugin_not_found"`, `plugin`, and optional `available_plugins[]`; (c) keep stdout/stderr placement consistent across plugin lifecycle verbs so callers do not need per-action stream heuristics; (d) add regression coverage proving `plugins disable does-not-exist --output-format json` produces a typed plugin-not-found JSON contract on the documented stream. **Why this matters:** disable is a recovery/control-plane operation. A stale plugin name should be a structured, domain-specific not-found result on a predictable stream; otherwise claws that read stdout JSON for normal responses and stderr for human diagnostics must special-case this lifecycle failure. Source: gaebal-gajae dogfood follow-up for the 22:30 nudge on rebuilt `./rust/target/debug/claw` `0f9e8915`; invalid hang PR #2891 was closed after repeated bounded repros returned exit 1 with JSON on stderr.
|
||||
352. **Top-level `plugins update <missing-plugin> --output-format json` sends a generic JSON error envelope to stderr only, leaving stdout empty** — dogfooded 2026-04-29 for the 23:00 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `5eb1d7d8`. After rebuilding and verifying the binary provenance, repeated bounded runs of `timeout 8 ./rust/target/debug/claw plugins update does-not-exist --output-format json` exited `1` with `stdout=0` and `stderr=97`; stderr contained JSON (`{"error":"plugin `does-not-exist` is not installed","hint":null,"kind":"unknown","type":"error"}`), but stdout was empty. In the same rebuilt binary, `plugins list --output-format json` returned stdout JSON promptly with the known plugin inventory payload. This is distinct from #350's missing-target `plugins enable` zero-byte timeout and parallel to #351's `plugins disable` stderr-only JSON envelope: update fails fast, but the JSON-mode error lives on stderr only and uses generic `kind:"unknown"`/`type:"error"` instead of a plugin-specific not-found contract. **Required fix shape:** (a) define and consistently document stdout/stderr placement for JSON-mode lifecycle errors; (b) return a plugin-specific typed error with `kind:"plugin"` or `domain:"plugin"`, `action:"update"`, `status:"not_found"` or `code:"plugin_not_found"`, `plugin`, and optional `available_plugins[]`; (c) share missing-target error-envelope behavior across disable/update/uninstall and reconcile it with enable's timeout path; (d) add regression coverage proving `plugins update does-not-exist --output-format json` produces a typed plugin-not-found JSON contract on the documented stream. **Why this matters:** update is a maintenance/control-plane operation often run in automation. A stale plugin name should produce a predictable, domain-specific not-found result, not require callers to special-case stderr-only generic error envelopes after explicitly requesting JSON. Source: gaebal-gajae dogfood follow-up for the 23:00 nudge on rebuilt `./rust/target/debug/claw` `5eb1d7d8`; invalid hang PR #2894 was closed after repeated bounded repros returned exit 1 with JSON on stderr.
|
||||
353. **Top-level `plugins uninstall <missing-plugin> --output-format json` sends a generic JSON error envelope to stderr only, leaving stdout empty** — dogfooded 2026-04-29 for the 23:30 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `6f92e54d`. After rebuilding and verifying the binary provenance, repeated bounded runs of `timeout 8 ./rust/target/debug/claw plugins uninstall does-not-exist --output-format json` exited `1` with `stdout=0` and `stderr=97`; stderr contained JSON (`{"error":"plugin `does-not-exist` is not installed","hint":null,"kind":"unknown","type":"error"}`), but stdout was empty. In the same rebuilt binary, `plugins list --output-format json` returned stdout JSON promptly with the known plugin inventory payload. This is distinct from #350's missing-target `plugins enable` zero-byte timeout and parallel to #351/#352 for disable/update: uninstall fails fast, but the JSON-mode error lives on stderr only and uses generic `kind:"unknown"`/`type:"error"` instead of a plugin-specific not-found contract. **Required fix shape:** (a) define and consistently document stdout/stderr placement for JSON-mode lifecycle errors; (b) return a plugin-specific typed error with `kind:"plugin"` or `domain:"plugin"`, `action:"uninstall"`, `status:"not_found"` or `code:"plugin_not_found"`, `plugin`, and optional `available_plugins[]`; (c) share missing-target error-envelope behavior across disable/update/uninstall and reconcile it with enable's timeout path; (d) add regression coverage proving `plugins uninstall does-not-exist --output-format json` produces a typed plugin-not-found JSON contract on the documented stream. **Why this matters:** uninstall is the most destructive plugin lifecycle action. A stale plugin name should produce a predictable, domain-specific not-found result before cleanup hooks or loader work, not require callers to special-case stderr-only generic error envelopes after explicitly requesting JSON. Source: gaebal-gajae dogfood follow-up for the 23:30 nudge on rebuilt `./rust/target/debug/claw` `6f92e54d`; invalid hang PR #2897 was closed after repeated bounded repros returned exit 1 with JSON on stderr.
|
||||
354. **Top-level `memory list` and `memory help` with `--output-format json` hang with zero stdout/stderr instead of returning bounded memory inventory/help or a typed unavailable response** — dogfooded 2026-04-30 for the 00:00 nudge on current `origin/main` / rebuilt `./rust/target/debug/claw` with embedded `git_sha` `19947545`. After rebuilding and verifying the binary provenance, bounded runs of `timeout 8 ./rust/target/debug/claw memory list --output-format json` produced `stdout=0` and `stderr=0`; the first sample exited `124` and the second sample was still stuck until killed. A follow-up sanity check of `timeout 8 ./rust/target/debug/claw memory help --output-format json` also exited `124` with `stdout=0` and `stderr=0`, so the issue is broader than list inventory: even the memory help path can hang silently in JSON mode. This is distinct from prior plugin lifecycle stream/status items: the affected surface is memory command introspection, where claws need safe local help/inventory before reading or mutating memory. **Required fix shape:** (a) make `memory help` and `memory list --output-format json` return bounded local JSON without requiring external/authenticated backing store availability; (b) return stdout JSON with `kind:"memory"`, `action:"help"|"list"`, `status`, usage or `entries[]`, source/provenance, counts, and truncation metadata; (c) if credentials/config/backing store are missing or slow, return a typed JSON unavailable/config/timeout error instead of hanging; (d) add regression coverage proving both `memory help --output-format json` and `memory list --output-format json` return machine-readable outcomes within a deterministic budget. **Why this matters:** memory is a core clawability surface. If even help/list can hang silently with no bytes, agents cannot tell whether memory is empty, unavailable, remote-auth blocked, or deadlocked, and any higher-level recall/debug flow stalls at the first introspection step. Source: gaebal-gajae dogfood follow-up for the 00:00 nudge on rebuilt `./rust/target/debug/claw` `19947545`.
|
||||
|
||||
374. **`/sandbox --output-format json` has an ambiguous `active: false` vs `filesystem_active: true` combination with no `active_mode` discriminator; `fallback_reason` is prose only with no structured `{required_capability, platform, remedy}` fields** — dogfooded 2026-04-30 by Jobdori on `8e24f304`. Running `/sandbox --output-format json` on macOS aarch64 returns: `{"active":false,"filesystem_active":true,"supported":false,"enabled":true,"fallback_reason":"namespace isolation unavailable (requires Linux with `unshare`)"}`. Two issues: (1) `active: false` and `filesystem_active: true` appear contradictory — if filesystem sandboxing is active, why is `active: false`? There is no `active_mode` field explaining that `active` means "full namespace sandbox" while `filesystem_active` means "workspace-only filesystem sandbox". An orchestrator checking `if active { sandboxed } else { unsandboxed }` would incorrectly conclude the session is unsandboxed when filesystem restrictions are actually in effect. (2) `fallback_reason` is a prose string "namespace isolation unavailable (requires Linux with `unshare`)". A programmatic actor wanting to know what capability is missing and how to fix it must parse prose. **Required fix shape:** (a) add `active_mode: "none" | "filesystem_only" | "namespace" | "full"` to unambiguously describe the current isolation level; (b) when `active: false` but `filesystem_active: true`, document that this means `active_mode: "filesystem_only"`; (c) replace or supplement `fallback_reason` prose with `fallback: {missing_capability: "linux_namespaces", platform_required: "linux", remedy: "run on Linux with unshare support"}` structured object; (d) add regression coverage confirming `active_mode` is one of the four canonical values. Source: Jobdori live dogfood, mengmotaHost, `8e24f304`, 2026-04-30.
|
||||
|
||||
Reference in New Issue
Block a user