Compare commits

...

15 Commits

Author SHA1 Message Date
Yeachan-Heo 63f4865c8d docs(roadmap): add config section parse kind drift 2026-05-21 05:31:13 +00:00
Yeachan-Heo 4639a5820c docs(roadmap): add config env unsupported flag hang 2026-05-21 05:01:10 +00:00
Yeachan-Heo 24ccc6e0d2 docs(roadmap): add broad-cwd override flag scope gap 2026-05-21 04:31:14 +00:00
Yeachan-Heo 06517490e6 docs(roadmap): add dangerous flag diagnostic scope gap 2026-05-21 04:01:41 +00:00
Yeachan-Heo 88c4412a93 docs(roadmap): add compact trailing flag hang gap 2026-05-21 03:31:25 +00:00
Yeachan-Heo 5665ca1581 docs(roadmap): add missing allowedTools value hang gap 2026-05-21 03:01:16 +00:00
Yeachan-Heo aacabdfb89 docs(roadmap): add missing permission-mode value hang gap 2026-05-21 02:01:00 +00:00
Yeachan-Heo 41a17e26ca docs(roadmap): add missing model value hang gap 2026-05-21 01:30:58 +00:00
Yeachan-Heo ce9ae27f39 docs(roadmap): add missing output-format value hang gap 2026-05-21 01:01:05 +00:00
Yeachan-Heo 62f5ab5611 docs(roadmap): add invalid output-format hang gap 2026-05-21 00:31:09 +00:00
Yeachan-Heo 918f8f709d docs(roadmap): add config env type validation gap 2026-05-21 00:00:53 +00:00
Yeachan-Heo 0bbe19eb7a docs(roadmap): add config env secret redaction gap 2026-05-20 23:31:55 +00:00
Yeachan-Heo fbd2f01347 docs(roadmap): add config model type silent ignore 2026-05-20 23:01:22 +00:00
Yeachan-Heo 07a12d4cf3 docs(roadmap): add binary overwrite misreported create 2026-05-20 22:30:53 +00:00
Yeachan-Heo ea29fbeb44 docs(roadmap): add whole-file structured patch amplification 2026-05-20 22:00:40 +00:00
+30
View File
@@ -6579,3 +6579,33 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)
511. **`grep_search` collects every file and every matching content line before applying `head_limit`, so a small requested result can still scan/read/store an unbounded workspace worth of data** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 21:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@02f2887`. Code inspection: `grep_search_impl` first calls `collect_search_files(&base_path)?`, which walks the entire tree into a `Vec<PathBuf>` with no ignored-dir policy, file-count cap, or early stop. For every candidate it then does `fs::read_to_string(&file_path)` with no per-file size guard (unlike `read_file`'s 10MB max) and, for `output_mode == "content"`, pushes every matched/context line into `content_lines`. Only after the full traversal does it call `apply_limit(filenames, input.head_limit, input.offset)` and later `apply_limit(content_lines, head_limit, offset)`. The default limit is 250 output items, but it is not an execution budget: a repo with huge generated text files or thousands of matches still pays full read/regex/memory cost before returning 250 lines. **Required fix shape:** (a) stream search results and stop once `offset + head_limit` content lines/files have been collected, while continuing only if `count` mode explicitly needs totals; (b) add skip dirs/file-size guards shared with `glob_search` (`.git`, `node_modules`, `target`, etc.) and binary detection; (c) expose `truncated:true`, `files_scanned`, `files_skipped_size`, and `matches_seen` metadata; (d) add regression fixtures with a huge file and many matches proving `head_limit:1` does not read/accumulate the entire workspace. **Why this matters:** grep is a read-only diagnostic primitive. `head_limit` currently protects only the final JSON size, not runtime CPU/memory or accidental context blowups, so common searches in generated/vendor-heavy repos can look like tool hangs even when the caller asked for one line. Source: gaebal-gajae dogfood response to Clawhip message `1506763474955403414` on 2026-05-20.
512. **`glob_search` traverses and stores all matches before truncating to 100, then sorts them by metadata, so `truncated:true` still means the full workspace scan already happened** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 21:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@0864f39`. Code inspection: `glob_search_impl` expands brace patterns, derives a walk root, then runs `WalkDir::new(&walk_root).filter_entry(...)` and pushes every matching file into `matches`. Only after all patterns and all entries are exhausted does it sort the entire `matches` vector by `fs::metadata(path).modified()` and compute `truncated = matches.len() > 100`, then `take(100)` for output. The ignored-dir list helps common vendor dirs, but there is no max traversal count, max match count, timeout/deadline, or early stop once enough results are known. A broad pattern like `**/*` in a generated workspace can collect/sort/stat tens or hundreds of thousands of paths just to return 100 names. **Required fix shape:** (a) add execution budgets for glob traversal (`max_entries_scanned`, `max_matches_collected`, optional deadline); (b) stream/top-k results instead of collecting every match before truncation, or make `sort_by_mtime` opt-in when exact newest-100 is required; (c) return `entries_scanned`, `matches_seen`, `truncated_reason`, and `ignored_dirs` metadata; (d) share traversal budget primitives with `grep_search` so read-only discovery tools fail/degrade consistently; (e) add a regression with >1000 generated files proving `glob_search` returns promptly without storing/sorting every match when capped. **Why this matters:** glob is a safe-looking read-only discovery tool, but broad globs in large repos are a common source of startup friction and apparent hangs. Output truncation alone is not enough; the work done before truncation must also be bounded and observable. Source: gaebal-gajae dogfood response to Clawhip message `1506771028834123986` on 2026-05-20.
513. **`make_patch` is not a diff hunk generator; it emits the entire old file as removed lines plus the entire new file as added lines, so `structured_patch` itself can double the output size for every write/edit** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 22:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@b3b9eb2`. Code inspection: `runtime/src/file_ops.rs::make_patch(original, updated)` builds one `StructuredPatchHunk` by iterating `for line in original.lines() { lines.push(format!("-{line}")); }` and then `for line in updated.lines() { lines.push(format!("+{line}")); }`; `old_lines` and `new_lines` are the full line counts. This means the supposedly structured patch is a whole-file delete+whole-file add, not a minimal/contextual diff. Combined with #509's full `content`/`original_file` fields, editing a 1MB file can return: full original file, full new file, and a `structured_patch` containing full original+full new again. Even after removing raw content fields, `structured_patch` would still be an output-amplification bug unless it becomes a real bounded diff. **Required fix shape:** (a) replace `make_patch` with a real line diff/hunk algorithm that emits only changed hunks plus configurable context; (b) cap patch lines/bytes with `patch_truncated`, `omitted_hunks`, and full old/new byte counts; (c) for full-file rewrites, return a summary (`rewrite:true`, changed line counts, previews) rather than every line; (d) add regressions for one-line edit in a 10k-line file proving patch output is O(changed lines + context), not O(file size). **Why this matters:** structured patches are the right contract for coding tools, but a whole-file pseudo-patch creates the same context-window blowup as raw file echoes while looking machine-friendly. Review/debug loops need concise, truthful diffs. Source: gaebal-gajae dogfood response to Clawhip message `1506778574143754422` on 2026-05-20.
514. **`write_file` silently overwrites existing binary/non-UTF8 files while reporting them as creates because the previous-file read uses `fs::read_to_string(...).ok()` and drops decode/errors** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 22:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@ea29fbe`. Code inspection: `runtime/src/file_ops.rs::write_file` enforces only the new content byte length, resolves the destination, then does `let original_file = fs::read_to_string(&absolute_path).ok();`. Any read error — file missing, permission denied, directory race, or existing binary/non-UTF8 content — is collapsed to `None`. The function then creates parents and `fs::write(&absolute_path, content)?`. Because `kind` is computed as `if original_file.is_some() { "update" } else { "create" }`, overwriting a binary file is reported as a create with no warning and no binary guard. `read_file` has binary detection; `write_file` does not apply it before clobbering existing files. **Required fix shape:** (a) distinguish `NotFound` from other read/decode errors instead of using `.ok()`; (b) if the destination exists and is not valid UTF-8 or appears binary, require an explicit `overwrite_binary:true` / `force:true` flag or return `kind:"binary_overwrite_refused"`; (c) report `existed:true` based on metadata, not successful UTF-8 decoding; (d) preserve structured diff only for text files; (e) add regressions for overwriting a binary file and a permission-denied/unreadable file proving the tool does not silently treat them as creates. **Why this matters:** write tools are allowed to create/update source artifacts, but silently clobbering a binary asset or unreadable file is data-lossy and misleading. The model/operator needs to know whether a file existed and whether a safe text diff is possible before replacement. Source: gaebal-gajae dogfood response to Clawhip message `1506786124176293919` on 2026-05-20.
515. **Config `model` values are parsed with `JsonValue::as_str` and otherwise silently ignored, so non-string model config falls back to defaults with no error or warning** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 23:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@07a12d4`, following Jobdori's config-loader diagnostic sweep. Code inspection: after validation/merge, `ConfigLoader::load` builds `RuntimeFeatureConfig { model: parse_optional_model(&merged_value), ... }`. `parse_optional_model` is `root.as_object().and_then(|object| object.get("model")).and_then(JsonValue::as_str).map(ToOwned::to_owned)`. If a config file contains `{"model": 123}`, `{"model": null}`, `{"model": ["opus"]}`, or an object, `parse_optional_model` returns `None` exactly as if no model key existed. Other config fields use typed helpers that return `ConfigError::Parse` on wrong types (`permissions.defaultMode`, plugin fields, hooks, etc.), so `model` is an outlier. **Required fix shape:** (a) replace `parse_optional_model -> Option<String>` with `Result<Option<String>, ConfigError>`; (b) when `model` exists but is not a non-empty string, emit `ConfigError::Parse` or a structured warning with path/key/type; (c) run the same model-syntax validator used for `--model` and env model values so config, env, and CLI flag agree; (d) expose `model_source`, `model_raw`, and validation diagnostics in status/config JSON; (e) add regressions for numeric/null/array/object model values proving they are not silently treated as missing. **Why this matters:** model selection is control-plane state. A typo like `model: ["opus"]` should not silently revert to the default model while status appears healthy; that creates prompt misdelivery and cost surprises that are hard to attribute back to config. Source: gaebal-gajae dogfood response to Clawhip message `1506793682257580144` on 2026-05-20.
516. **`config env --output-format json` prints raw environment secret values from config files, including API-key-shaped entries, instead of redacting sensitive keys** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 23:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@fbd2f01` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Reproduction in a clean temp workspace: create `.claw.json` with `{"env":{"ANTHROPIC_API_KEY":"sk-SECRET-should-not-print","SAFE":"ok"}}`, then run `claw config env --output-format json`. The command exits 0 and emits `section_value` containing the raw `ANTHROPIC_API_KEY` value unchanged while also showing benign keys like `SAFE`. This makes the config-inspection surface unsafe to paste into issue reports, Discord, CI logs, or support threads. **Required fix shape:** (a) redact values for sensitive key patterns (`*_API_KEY`, `*_TOKEN`, `*_SECRET`, `PASSWORD`, `AUTH`, etc.) in both JSON and text config inspection output; (b) preserve enough metadata for debugging (`redacted:true`, maybe `value_present:true`, source file, key name) without exposing bytes; (c) keep non-sensitive env values visible; (d) add a `--show-secrets`/`--unsafe-show-secrets` escape hatch only if explicitly confirmed and never enabled by default; (e) add regression coverage for `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, token/password variants, and safe keys. **Why this matters:** `config env` is exactly the surface operators use when debugging configuration. If it dumps credentials by default, the first support/debug paste can leak provider keys. Automation-friendly JSON must be safer than prose, not a secret exfiltration footgun. Source: gaebal-gajae dogfood response to Clawhip message `1506801223465046210` on 2026-05-20.
517. **`config env --output-format json` accepts and reports non-string env values instead of validating that environment variables are strings** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 00:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@0bbe19e` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Reproduction in a clean temp workspace: create `.claw.json` with `{"env":{"SAFE":123}}`, then run `claw config env --output-format json`. The command exits 0 and emits `section_value:{"SAFE":123}`. Runtime environment variables cannot be numeric/array/object/null values; any later application step must stringify, ignore, or fail elsewhere. This is inconsistent with the stricter config helpers for hooks/plugins/provider fallbacks and with the model-type gap recorded in #515. **Required fix shape:** (a) validate `env` config as a string map during config load/section inspection; (b) for non-string values, return a typed parse/config diagnostic naming the file/key/type, or preserve partial success with `invalid_env:[{key, reason}]` while excluding the bad key from resolved env; (c) keep `config env` JSON machine-usable by returning only string values plus explicit invalid-entry metadata; (d) combine with #516 secret redaction so valid secret strings are redacted and invalid secret-shaped keys do not leak values; (e) add regressions for numeric, boolean, null, array, and object env values. **Why this matters:** config inspection should reflect values that can actually be exported. Accepting JSON-native non-string values as env config makes status/config look healthy while leaving the eventual runtime behavior ambiguous and brittle for automation. Source: gaebal-gajae dogfood response to Clawhip message `1506808785480454194` on 2026-05-21.
518. **Unsupported `--output-format` values (`xml`, `yaml`, etc.) enter silent runtime/config paths and time out with zero output instead of failing at CLI parse time** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 00:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@918f8f7` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes with an otherwise valid `.claw.json`: `claw config env --output-format xml`, `claw config env --output-format yaml`, and `claw status --output-format xml` each timed out after 6s with `stdout=0` and `stderr=0`. The documented output formats are `text|json`; unsupported values should be rejected before any runtime/config work begins. **Required fix shape:** (a) validate `--output-format` centrally during argument parsing; (b) accept only documented enum values (`text`, `json` unless more are implemented); (c) return bounded `kind:"cli_parse"` / `kind:"invalid_output_format"` diagnostics naming the unsupported value and supported values; (d) ensure the error obeys the JSON-output contract if a valid JSON mode was selected before the invalid value position, otherwise text stderr is fine; (e) add clean-home timeout-guarded regressions for `status --output-format xml`, `config env --output-format yaml`, `--output-format xml version`, and duplicate/late output-format placements. **Why this matters:** output format is a machine-contract selector. If a typo in that selector turns into a zero-byte hang, wrappers cannot distinguish parse failure from runtime deadlock and will often retry or kill healthy automation. Source: gaebal-gajae dogfood response to Clawhip message `1506816322795732993` on 2026-05-21.
519. **`--output-format` without a value hangs silently on real subcommands instead of returning a missing-value CLI parse error** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 01:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@62f5ab5` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes: `claw status --output-format`, `claw config env --output-format`, and `claw version --output-format` each timed out after 6s with `stdout=0` and `stderr=0`. A control probe `claw --output-format status` returned a bounded `cli_parse` unknown-option error, proving the parser can fail fast in some malformed placements but not when the flag is trailing/missing an argument after a recognized command. **Required fix shape:** (a) parse `--output-format` as an option that requires a value in all command positions; (b) if the next token is absent, return bounded `kind:"cli_parse"` or `kind:"missing_option_value"` naming `--output-format` and supported values; (c) if the next token is present but unsupported, combine with #518's enum validation; (d) add clean-home regressions for `status --output-format`, `config env --output-format`, `version --output-format`, and prefix form `--output-format` alone, all with elapsed-time guards; (e) ensure JSON error routing remains deterministic when a valid JSON mode was not selected. **Why this matters:** a missing value after a machine-output selector is a simple syntax error. Turning it into a zero-byte timeout makes wrappers classify a typo as a dead runtime and causes pointless retries/kills. Source: gaebal-gajae dogfood response to Clawhip message `1506823873176535133` on 2026-05-21.
520. **`--model` without a value hangs silently after recognized subcommands instead of returning a missing-value CLI parse error** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 01:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@ce9ae27` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes: `claw status --model`, `claw version --model`, and `claw config env --model` each timed out after 6s with `stdout=0` and `stderr=0`. A control probe `claw --model status` returned a bounded `cli_parse` unknown-option error, so the parser/runtime only fails fast for some malformed placements while trailing model-option arity is swallowed into the command path. This is the model-selector sibling of #519's missing `--output-format` value hang. **Required fix shape:** (a) parse `--model` as an option requiring a following value wherever global flags are accepted; (b) if absent, return bounded `kind:"cli_parse"` or `kind:"missing_option_value"` naming `--model` and accepted forms/aliases; (c) if present, continue to apply existing syntax validation (#128/#424/#426 family); (d) add clean-home elapsed-time regressions for `status --model`, `version --model`, `config env --model`, bare `--model`, and valid `--model opus status`; (e) ensure JSON/text error routing remains deterministic. **Why this matters:** model selection controls cost/provider/routing. A missing model argument is a simple syntax error; turning it into a zero-byte timeout makes wrappers and users diagnose a dead runtime instead of a bad command line. Source: gaebal-gajae dogfood response to Clawhip message `1506831427013181570` on 2026-05-21.
521. **`--permission-mode` without a value hangs silently after recognized subcommands instead of returning a missing-value CLI parse error** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 02:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@41a17e2` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes: `claw status --permission-mode`, `claw version --permission-mode`, and `claw config env --permission-mode` each timed out after 6s with `stdout=0` and `stderr=0`. A control probe `claw --permission-mode status` returned a bounded `cli_parse` unknown-option error. This is the permission-selector sibling of #519 (`--output-format`) and #520 (`--model`): recognized-command trailing global options are not enforcing required argument arity. **Required fix shape:** (a) parse `--permission-mode` as an option requiring a following value wherever global flags are accepted; (b) if absent, return bounded `kind:"cli_parse"` or `kind:"missing_option_value"` naming `--permission-mode` and supported modes; (c) if present but unsupported, return the existing unsupported-mode diagnostic before runtime startup; (d) add clean-home elapsed-time regressions for `status --permission-mode`, `version --permission-mode`, `config env --permission-mode`, bare `--permission-mode`, and valid `--permission-mode read-only status`; (e) consider a centralized required-value table for all global flags to close this family at once. **Why this matters:** permission mode controls write/delete authority. A missing permission argument should be a deterministic parse error, not a zero-byte hang that makes operators think the CLI or runtime is wedged. Source: gaebal-gajae dogfood response to Clawhip message `1506838972062761041` on 2026-05-21.
522. **`--allowedTools` without a value hangs silently after recognized subcommands instead of returning a missing-value CLI parse error** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 02:30/03:00 UTC nudges on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@aacabdf` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes: `claw status --allowedTools`, `claw version --allowedTools`, and `claw config env --allowedTools` each timed out after 6s with `stdout=0` and `stderr=0`. A control probe `claw --allowedTools status` returned a bounded `cli_parse` unknown-option error. This extends the trailing required-value family already captured for `--output-format` (#519), `--model` (#520), and `--permission-mode` (#521). **Required fix shape:** (a) parse `--allowedTools` as an option requiring a following value wherever it is accepted; (b) if absent, return bounded `kind:"cli_parse"` or `kind:"missing_option_value"` naming `--allowedTools` and the expected comma/list syntax; (c) if present, validate/normalize the tool list before runtime startup; (d) add clean-home elapsed-time regressions for `status --allowedTools`, `version --allowedTools`, `config env --allowedTools`, bare `--allowedTools`, and valid list forms; (e) preferably centralize required-argument metadata for every global option so this class closes once instead of flag-by-flag. **Why this matters:** allowed-tools constrains tool authority. A missing value should never look like a runtime deadlock; wrappers need deterministic parse errors before starting model/session machinery. Source: gaebal-gajae dogfood response to Clawhip messages `1506846526276763658` and `1506854073998118922` on 2026-05-21.
523. **`--compact` after recognized non-prompt subcommands hangs silently instead of being rejected as unsupported flag placement/scope** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 03:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@5665ca1` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes: `claw status --compact`, `claw version --compact`, and `claw config env --compact` each timed out after 6s with `stdout=0` and `stderr=0`. A control probe `claw --compact status` returned a bounded `cli_parse` unknown-option error. Unlike #519-#522, `--compact` is a boolean flag, not a missing-value case; the gap is that trailing global/prompt-only flags after recognized subcommands are swallowed into a path that waits silently instead of either applying or rejecting the flag. Help documents `--compact` as "text mode only; useful for piping" for one-shot prompt output, not as a status/config/version modifier. **Required fix shape:** (a) define per-command accepted global/late flags and reject unsupported trailing flags before runtime startup; (b) for `status`, `version`, and `config`, return bounded `kind:"cli_parse"` / `kind:"unsupported_flag_for_command"` with the offending flag and supported alternatives; (c) if `--compact` is intended to be global, make it a no-op or documented mode for these commands, but never hang; (d) add clean-home elapsed-time regressions for `status --compact`, `version --compact`, `config env --compact`, valid prompt compact forms, and prefix/late placements; (e) close this alongside the option-arity family by centralizing command-specific flag metadata. **Why this matters:** `--compact` is a piping/automation affordance. If users add it to diagnostic commands and get a zero-byte timeout, compact output becomes a source of apparent runtime deadlocks rather than lower-noise automation. Source: gaebal-gajae dogfood response to Clawhip message `1506861625829752852` on 2026-05-21.
524. **`--dangerously-skip-permissions` is accepted after non-mutating diagnostic subcommands and changes their reported permission mode, so a capability-escalation flag can be silently treated as relevant control-plane state for `status`/`version`/`config`/`doctor`/`sandbox` instead of being scoped to prompt/runtime execution** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 04:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@88c4412` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes with a minimal `.claw.json`: `claw status --dangerously-skip-permissions` exits 0 and reports `Permission mode danger-full-access`; `claw version --dangerously-skip-permissions`, `claw config env --dangerously-skip-permissions`, `claw doctor --dangerously-skip-permissions`, and `claw sandbox --dangerously-skip-permissions` also exit 0. Prefix form `claw --dangerously-skip-permissions status` behaves the same. This flag is documented as “Skip all permission checks” and is meaningful for model/tool execution, not read-only diagnostics like version/config/status. Accepting it everywhere makes diagnostic output look like an authority escalation happened and gives wrappers no way to detect accidental dangerous flag bleed-through from prompt invocations into health checks. **Required fix shape:** (a) define command-specific acceptance for capability-changing flags; (b) reject `--dangerously-skip-permissions` on non-executing diagnostics (`version`, `status`, `config`, `doctor`, `sandbox`, maybe `system-prompt`) with bounded `kind:"unsupported_flag_for_command"`, or explicitly mark it ignored with `ignored_flags` metadata and never report `danger-full-access` for non-execution commands; (c) keep the flag valid only for prompt/REPL/runtime paths where permission checks actually apply; (d) add clean-home regressions for both trailing and prefix placement across diagnostics and valid prompt usage; (e) ensure status distinguishes configured/default permission mode from an execution override. **Why this matters:** permission-mode reporting is a control-plane trust signal. If a dangerous runtime escape hatch is silently accepted by local diagnostics, users and orchestrators can misread a harmless status probe as running under danger-full-access, or fail to catch dangerous flag leakage before executing real tool work. Source: gaebal-gajae dogfood response to Clawhip message `1506869175522693160` on 2026-05-21.
525. **`--allow-broad-cwd` is accepted after normal diagnostic subcommands even when the current directory is not broad, and `status` reports `danger-full-access`, so a broad-directory bypass flag silently bleeds into unrelated health/config surfaces instead of being scoped to the broad-cwd guard** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 04:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@0651749` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes from a narrow temp workspace with a minimal `.claw.json`: `claw status --allow-broad-cwd`, `claw version --allow-broad-cwd`, `claw doctor --allow-broad-cwd`, `claw sandbox --allow-broad-cwd`, and prefix `claw --allow-broad-cwd status` all exit 0; `status` reports `Permission mode danger-full-access`. `claw config env --allow-broad-cwd` is worse: it timed out after 6s with `stdout=0`/`stderr=0`, showing the same trailing-flag swallowing path can still hit a silent hang on one config subcommand. `--allow-broad-cwd` exists to explicitly bypass the broad-cwd safety guard when running from `/`, `$HOME`, `/tmp`, etc.; it should not be a no-op/permission-shaped accepted flag on `version`, `doctor`, `sandbox`, or config inspection from an ordinary project directory. **Required fix shape:** (a) scope `--allow-broad-cwd` to the broad-cwd preflight only and expose it in diagnostics as `broad_cwd_override:true` only when the cwd is actually broad; (b) reject it on non-broad cwd or non-workspace-executing diagnostics with bounded `kind:"unsupported_flag_for_command"` / `kind:"unnecessary_broad_cwd_override"`; (c) never let this flag affect or appear as `permission_mode`; (d) fix the `config env --allow-broad-cwd` trailing-flag hang with the same command-specific flag metadata used for #523/#524; (e) add clean-home regressions for narrow cwd, `/`, `$HOME`, and `/tmp` across `status`, `doctor`, `config env`, and valid prompt/resume paths. **Why this matters:** broad-cwd override is a blast-radius escape hatch. If automation accidentally carries it into every diagnostic call, the CLI should either ignore it with explicit metadata or reject it, not make status look like a danger-full-access runtime nor hang a config probe. Source: gaebal-gajae dogfood response to Clawhip message `1506876721666719805` on 2026-05-21.
526. **`config env` swallows unsupported trailing runtime/session flags into a zero-byte hang while sibling diagnostics reject the same flags with `cli_parse`, so config inspection has a unique prompt-fallback/argument-drain bug** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 05:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@24ccc6e` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes from a minimal temp workspace compared the same unsupported trailing flags across `status`, `version`, `config env`, `doctor`, and `sandbox`. For `--resume`, `--max-turns`, `--continue`, and `--verbose`, the non-config diagnostics all returned bounded `cli_parse` errors like `unrecognized argument '--resume' for subcommand 'status'`. But `claw config env --resume`, `claw config env --max-turns`, `claw config env --continue`, and `claw config env --verbose` each timed out after 6s with `stdout=0`/`stderr=0`. This is the same family as #525's `config env --allow-broad-cwd` hang, but the broader sweep shows `config env` is the outlier parser path for multiple unsupported runtime/session flags, not just one safety override. **Required fix shape:** (a) give `config env` and all `config <section>` forms the same strict trailing-argument validation as `status`/`doctor`/`sandbox`; (b) reject unsupported flags before any config/runtime fallback with `kind:"cli_parse"` / `kind:"unsupported_flag_for_command"`, echoing the offending flag and valid config options; (c) centralize config-subcommand argument parsing so `config env`, `config model`, `config hooks`, and `config plugins` cannot drift; (d) add clean-home elapsed-time regressions for `config env --resume`, `--max-turns`, `--continue`, `--verbose`, `--allow-broad-cwd`, and a valid `config env --output-format json`; (e) audit whether the same hang exists for `config model/hooks/plugins` and close it in the same parser fix. **Why this matters:** `config env` is a support/debug surface users paste into issue reports. Unsupported flags should fail fast and visibly; a zero-byte hang makes config troubleshooting look like startup deadlock and hides the actual CLI typo. Source: gaebal-gajae dogfood response to Clawhip message `1506884276522848317` on 2026-05-21.
527. **`config model/hooks/plugins` reject unsupported trailing flags with `kind:"unknown"` while sibling commands use `kind:"cli_parse"`, and `config env` hangs on the same flags, so config-section argument errors have three different contracts** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 05:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@4639a58` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Clean-home probes with `.claw.json` containing `model`, `env`, `hooks`, and `plugins`: `claw config model --resume`, `config model --verbose`, `config model --continue`, and the same flags for `config hooks`/`config plugins` all return nonzero bounded errors, but the discriminator is `[error-kind: unknown] error: unexpected extra arguments after \`claw config <section>\``. In the same parser family, `status`/`version`/`doctor`/`sandbox` report `[error-kind: cli_parse] unrecognized argument ... for subcommand ...`, while `config env` still zero-byte hangs on the same flags (#526). This means automation cannot switch on one stable error kind for a simple bad argument: it sees `cli_parse`, `unknown`, or timeout depending only on which config section was requested. **Required fix shape:** (a) route every `config <section>` extra-argument failure through the same CLI-parse error constructor as other subcommands; (b) reserve `kind:"unknown"` for truly unclassified internal failures, never deterministic parser errors; (c) give `config env` the same bounded path instead of the hang in #526; (d) include `command:"config"`, `section`, `unexpected_args`, and `supported_flags` in JSON/text diagnostics; (e) add regression coverage for `config env/model/hooks/plugins --resume|--verbose|--continue` verifying exit nonzero, bounded output, and `kind:"cli_parse"` or `kind:"unsupported_flag_for_command"` consistently. **Why this matters:** config inspection is a core support surface. If identical typo/flag-placement errors produce three contracts, wrappers have to special-case config sections and users see random-looking behavior instead of a clear command-line mistake. Source: gaebal-gajae dogfood response to Clawhip message `1506891824852242513` on 2026-05-21.