Compare commits

..

1 Commits

Author SHA1 Message Date
YeonGyu-Kim
b51b73e8a0 docs(roadmap): add #364 — /cost returns no cost_usd; identical to /stats 2026-04-30 07:32:49 +09:00

View File

@@ -6291,4 +6291,4 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
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. 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`. 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`.
366. **`/diff --output-format json` returns raw unified diff text in `staged` and `unstaged` string fields instead of structured per-file change objects; no `files[]` array, no per-file `insertions`/`deletions` counts** — dogfooded 2026-04-30 by Jobdori on `a510f73`. Running `/diff --output-format json` with modified tracked files returns `{"kind":"diff","result":"changes","staged":"","unstaged":"diff --git a/ROADMAP.md b/ROADMAP.md\n@@ -1,3 +1,4 ..."}`. The `unstaged` and `staged` fields are raw unified diff format strings — potentially thousands of characters with `@@` hunk headers and `+`/`-` line markers. There is no `files[]` array, no per-file `path`, no `change_type` (`added`/`modified`/`deleted`/`renamed`), no `insertions`/`deletions` counts, and no `is_binary` flag. Automation wanting "which files changed?" must parse raw unified diff text, which requires a full diff parser and is brittle. Compounded by #363 (`/status` counts but no paths): neither command provides a clean `{path, change_type}` inventory. **Required fix shape:** (a) add `files[]` array with `{path, change_type, insertions, deletions, is_binary}` per file; (b) preserve raw diff in `staged`/`unstaged` as supplemental; (c) add `truncated: true` flag and `total_files_changed` count for large diffs; (d) add regression coverage ensuring `/diff --output-format json` with a modified tracked file returns at least one entry in `files[].path`. Source: Jobdori live dogfood, mengmotaHost, `a510f73`, 2026-04-30. 364. **`/cost --output-format json` returns token counts only with no `cost_usd`, `currency`, or per-type cost breakdown; output is identical to `/stats` except for the `kind` field** — dogfooded 2026-04-30 by Jobdori on `c6c01bea`. Running `./rust/target/debug/claw --output-format json --resume latest /cost` returns the exact same JSON blob as `/stats` with only `"kind":"cost"` differing. Neither `cost_usd`, `currency`, `cost_by_type`, `model_pricing`, nor any monetary figure appears in the response. A claw tracking spend has no way to get dollar amounts from this command. This is distinct from the broader issue in #360 covering all three commands: this entry specifically documents the `/cost` command's missing monetary contract as a standalone gap. **Required fix shape:** (a) `/cost --output-format json` must include `cost_usd` (float), `currency` (string, e.g. `"usd"`), and optionally `cost_breakdown: {input, output, cache_read, cache_write}` in USD; (b) if pricing is unavailable for the active model, return `cost_usd: null` with `pricing_available: false`; (c) separate `/cost`'s response schema from `/stats` so they have distinct required fields; (d) add regression coverage confirming `/cost` includes a `cost_usd` field (may be null but must be present). Source: Jobdori live dogfood, mengmotaHost, `c6c01bea`, 2026-04-30.