mirror of
https://github.com/ultraworkers/claw-code.git
synced 2026-04-27 06:57:37 +08:00
roadmap: #258 filed
This commit is contained in:
parent
fe7f449de6
commit
1c50d946e4
14
ROADMAP.md
14
ROADMAP.md
@ -16829,3 +16829,17 @@ Dogfooded 2026-04-26 11:30 KST immediately after #256 landed. The OMX session `c
|
||||
Concrete failure mode: completed sessions become false-positive stale work. Operators have to manually capture the pane, verify commit/push/test status, and kill the session. This creates alert fatigue and can mask real stuck sessions. It is distinct from #253 context compaction and #239 branch leases: the missing primitive is stale-monitor lifecycle integration between tmux pane state, OMX workflow state, and git/event completion receipts.
|
||||
|
||||
Required fix shape: clawhip stale detection should classify sessions as `complete-idle` when (a) the associated OMX/Codex workflow state is terminal, (b) the pane contains a final status block with commit/pushed/tests/blocker none, or (c) a matching git event has landed for the session branch after the prompt started. For `complete-idle`, clawhip should auto-suppress stale alerts and optionally auto-retire/kill the tmux session after a grace period, emitting a compact cleanup receipt instead of repeated stale warnings. Acceptance: after a session lands a commit and marks workflow complete, no further stale alerts are emitted for that tmux session; it is either auto-killed or reported once as completed and retired. **Status:** Open. Filed as ROADMAP-only dogfood pinpoint from the 2026-04-26 02:30 UTC nudge; live cleanup performed by killing `clawcode-issue-256-tool-use-result-contiguity` after verifying branch clean at `56f7f2e6`.
|
||||
|
||||
## Pinpoint #258 — `--allowedTools ""` (empty value) silently coerces to zero-tool agent with no warning, joining the silent-fallback / silent-coercion family at the CLI parse boundary
|
||||
|
||||
Dogfooded 2026-04-26 11:32 KST on `feat/jobdori-168c-emission-routing` at HEAD `a3f5a83` (post-#257 fast-forward verification onto gaebal-gajae's clawhip-stale-monitor pinpoint). Reproduction: `claw --allowedTools "" --output-format json -p "test"` accepts the empty value with zero warnings/errors and proceeds to dispatch — there is no diagnostic event distinguishing "operator typed `--allowedTools \"\"` by accident" from "operator wants every tool disabled." The CLI parse arm at `rust/crates/rusty-claude-cli/src/main.rs:979` accepts whatever the next argv slot contains, including `""`, and pushes it into `allowed_tool_values`. The wrapper `normalize_allowed_tools` at `main.rs:1826` checks `values.is_empty()` (returns `None` when zero `--allowedTools` flags were passed entirely) but does not check whether each individual `value` is empty/whitespace-only, so the empty string flows into `current_tool_registry()?.normalize_allowed_tools(values)` at `rust/crates/tools/src/lib.rs:192`. There the `for value in values` loop applies `value.split(|ch: char| ch == ',' || ch.is_whitespace()).filter(|token| !token.is_empty())` which yields zero tokens for `""`, the inner `for token in ...` loop never executes, the unsupported-tool error path is skipped, and the function returns `Ok(Some(BTreeSet::new()))` — a `Some(empty)` distinct from the omit-the-flag-entirely `None` case. Downstream, `tool_registry.definitions(allowed_tools)` at `lib.rs:248` filters every spec/runtime/plugin tool by `allowed_tools.is_none_or(|allowed| allowed.contains(...))`, and because `allowed.contains(...)` returns false for every name against an empty set, the agent receives **zero tools** — no read_file, no write_file, no bash, no grep, no glob, no MCP, no plugins. The agent boots fully, the wire request is dispatched normally (no early return), and the model receives the user prompt with an empty tool list and either hallucinates without tools or stalls when it tries to call one — meanwhile the operator sees no signal that they've just asked for a tool-less agent.
|
||||
|
||||
Gap. The CLI parse layer treats `--allowedTools ""` as semantically equivalent to "explicitly enumerate zero tools" rather than as "operator passed a malformed empty value." This is silent-empty-coercion at the CLI parse boundary: the input string was clearly an accident (no shell idiom passes an intentional empty argument that means the same as explicitly disabling everything), but the parser, the registry, and the dispatcher all fail to surface a single diagnostic. The behavior compounds with #201/#202/#203/#206/#207/#208 (silent-fallback at the provider boundary) and #213 (silent-zero-coercion on cached_tokens) at a structurally distinct layer — the CLI parse layer rather than the provider boundary.
|
||||
|
||||
Cluster delta: joins the silent-fallback / silent-drop / silent-strip / silent-coercion sibling-shape cluster at the CLI-parse-boundary axis, extending it across one more structural layer. Distinct from #213's silent-zero-coercion (response-side wire deserialization) by being request-side CLI input parse, distinct from #211's silent-misnomer (parameter rename) by being empty-value-acceptance rather than name-mismatch, and distinct from #29's silent fallback (provider routing) by being a tool-allowlist permissive-vs-restrictive boundary rather than a provider-routing fallback. Does NOT found a new cluster (per #253 context-budget discipline preferring extension over founding).
|
||||
|
||||
Required fix shape: (a) in `normalize_allowed_tools` (`rusty-claude-cli/src/main.rs:1826`), reject empty/whitespace-only values with a typed `AllowedToolsParseError::EmptyValue { flag_position }` returning a non-zero exit and an actionable error message ("--allowedTools requires at least one tool name; pass `--allowedTools none` to explicitly disable all tools, or omit the flag to enable all"); (b) introduce an explicit `none` literal token (or `--allowedTools=none` / `--no-tools`) for the legitimate "every tool disabled" use case so the empty-string accident is structurally distinct from the intentional-disable; (c) emit a `CliFlagWarning` structured event when `--output-format json` is active so downstream consumers can surface the diagnostic; (d) add tests covering `[""]`, `[" "]`, `["", "read"]`, `["read", ""]`, and the new `["none"]` literal. Acceptance: `claw --allowedTools "" -p "x"` exits non-zero with a typed error; `claw --allowedTools none -p "x"` proceeds with explicit zero-tool intent; existing `claw --allowedTools read,glob -p "x"` and `claw -p "x"` (no flag) behaviors are preserved.
|
||||
|
||||
Security relevance: the inverse failure mode (empty `--disallowedTools` or empty deny-list silently permitting all tools) is the exact shape upstream PR claw-code#2806 attempted to address (empty-config permission fallback safety, opened+closed within 3min on 2026-04-26). #258 catalogues the symmetric allow-list side at the CLI flag layer rather than the config layer, complementing the upstream PR's config-layer focus.
|
||||
|
||||
**Status:** Open. No source code changed. Filed 2026-04-26 11:32 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `a3f5a83` (post-#257 fast-forward verification). Cluster delta: silent-fallback-family extension (no new cluster founded, per #253 context-budget discipline). Smaller-scope by design (matches #253/#254/#257's discipline). Sibling: #201/#202/#203/#206/#207/#208/#213 (silent-fallback-family) at the provider boundary; #258 extends the family to the CLI parse boundary as the first member where the silent-coercion happens before any wire dispatch. Linked to upstream PR claw-code#2806 (empty-config permission fallback safety) as the symmetric config-layer half of the same anti-pattern.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user