Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -6428,3 +6428,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed)


450. **`prompt` emits `kind:"missing_credentials"` JSON on STDERR (not stdout), leaving stdout at 0 bytes — automation pattern `output=$(claw prompt hello --output-format json)` captures nothing on auth-absent failure; `doctor` correctly surfaces `auth.status:"warn"` with `api_key_present:false` but exposes no `prompt_ready:false` field that automation can check before invoking `prompt`** — dogfooded 2026-05-16 by Jobdori on `a35ee9a0` in response to Clawhip pinpoint nudge at `1505208225321062521`. Exact reproduction (isolated env, no creds, fresh git repo, HEAD `a35ee9a0`): `timeout 5 env -i HOME=$ISOLATED_HOME PATH=$PATH CLAW_CONFIG_HOME=$PROBE/.claw-cfg claw prompt hello --output-format json > stdout.txt 2> stderr.txt` → stdout = **0 bytes**, stderr = 195 bytes containing `{"error":"missing Anthropic credentials…","exit_code":1,"hint":null,"kind":"missing_credentials","type":"error"}`, exit code 1. Confirms Gaebal's `1505208553793781792` pinpoint that `prompt` timeout + zero bytes was the prior state — HEAD `a35ee9a0` now correctly exits 1 with `kind:"missing_credentials"` **but the envelope is still routed to stderr** (issue #447 class, same class as prior entries #422, #435). **Contrast with `doctor`:** `claw doctor --output-format json 2>/dev/null` succeeds to stdout with `checks[auth].status:"warn"`, `api_key_present:false`, `auth_token_present:false` — but the auth check has no `prompt_ready:false` field. Automation that gates on `doctor` before invoking `prompt` must re-derive readiness from `api_key_present && auth_token_present` — there is no single canonical boolean. **Three compound problems:** (a) **stdout-empty on `--output-format json` failure**: same class as #447; `prompt`'s error envelope goes to stderr, not stdout. The canonical automation idiom `if ! result=$(claw prompt "q" --output-format json); then echo "$result" | jq .kind; fi` sees `$result=""` on failure — the jq call gets nothing. All `--output-format json` error paths must route JSON to stdout per #447 contract; (b) **`doctor` missing `prompt_ready` field**: `doctor --output-format json` already knows auth is absent (`api_key_present:false`) but surfaces no derived `prompt_ready:bool` or `prompt_blocked_reason:string` field. Automation must infer readiness from `api_key_present || auth_token_present || legacy_*_present` — a 5-field OR across legacy fields that is fragile as auth mechanisms evolve. A single `prompt_ready:false` (with `prompt_blocked_reason:"auth_missing"`) inside the `auth` check would give downstream a stable contract; (c) **`claw prompt` with no auth does no preflight and fires straight at the API**: the preflight check that `doctor` runs (auth discovery) is not reused by `prompt` to emit a fast typed error before attempting the network call. Both Gaebal's pinpoint (prompt hanging silently on older HEAD) and the current behavior (prompt hitting auth gate after a brief API attempt) stem from the same root: prompt does not short-circuit at the point where `doctor` already knows auth is absent. If `doctor` can emit `kind:"doctor"` with `auth.status:"warn"` in ~20ms without a network call, `prompt` should emit `kind:"missing_credentials"` in the same window and output it to stdout. **Required fix shape:** (a) `prompt --output-format json` must write the `kind:"missing_credentials"` JSON envelope to **stdout**, not stderr — same fix as #447 for all error envelopes; (b) add `prompt_ready:bool` and `prompt_blocked_reason:string|null` to the `auth` check in `doctor --output-format json`; derive it as `api_key_present || auth_token_present || legacy_saved_oauth_present`; (c) `prompt` must run the credential preflight check (same codepath as doctor's auth check) before attempting any API call and emit `{"kind":"missing_credentials","prompt_blocked_reason":"auth_missing"}` on **stdout** with exit 1 if the check fails; (d) `--output-format json` stdout routing fix must cover: `prompt`, `session list` (cross-ref #449), `skills uninstall` (cross-ref #431), `resume` (cross-ref #435), `acp serve` (cross-ref #443) — the full `kind:"missing_credentials"` class; (e) regression test: `claw prompt hello --output-format json` with no creds writes JSON to stdout (0 bytes stderr), exits 1, `kind:"missing_credentials"`, in under 200ms (no network attempt). **Why this matters:** `prompt` is the primary consumer entry point. Auth-absent failure routing to stderr breaks every automation wrapper that captures `$(claw prompt ... --output-format json)`. The `doctor` preflight metadata gap means auth-readiness checks require parsing 5 legacy fields instead of reading one boolean. Cross-references #447 (all JSON error envelopes on stderr), #449 (session list hits auth gate), #431 (skills uninstall hits auth gate), #357 (auth gate on local ops cluster), #422 (exit-code parity). Source: Jobdori live dogfood, `a35ee9a0`, 2026-05-16.

453. **`bare_slash_command_guidance` (the "is a slash command" guard) only fires for `command_name` matched as a single bare token at `rust/crates/rusty-claude-cli/src/main.rs:1100-1149` — as soon as ANY positional argument follows a slash-command-named first token, the parser falls through to `CliAction::Prompt` and ships the entire argv string to Claude as a user prompt. The guard catches `claw cost`, `claw tokens`, `claw model`, `claw permissions`, `claw context`, `claw providers`, `claw history`, `claw release-notes`, `claw review`, `claw compact`, `claw cache` — but misses `claw cost list`, `claw tokens list`, `claw model openai/gpt-4`, `claw model list`, `claw permissions show`, `claw context show`, `claw providers list`, `claw history list`, `claw cache list`. Same pattern bites unrouted command shapes: `claw aliases`, `claw aliases list`, `claw profiles list`, `claw logs`, `claw settings` all fall through, even though they are obvious CLI discovery spellings** — dogfooded 2026-05-24 for the 06:00 Clawhip pinpoint nudge at message `1507986539538419863`, reproduced on local `./rust/target/debug/claw` `git_sha 003b739d` (origin/main `f8e1bb72`; the guard logic in `bare_slash_command_guidance` was last touched by the `#146` `config`/`diff` carve-out and is unchanged in `63ce483c..f8e1bb72` which are docs-only ROADMAP additions). Repros in a fully clean isolated environment (`HOME=/tmp/iso3/home` with `{}` settings, fresh `/tmp/iso3/proj` git-init'd workspace, `stdin=/dev/null`, `ANTHROPIC_*` env vars unset): bare `claw cost </dev/null` exits `1` with `[error-kind: unknown] error: `claw cost` is a slash command. …`; adding a single argument `claw cost list </dev/null` exits `1` with `[error-kind: missing_credentials] error: missing Anthropic credentials; …` — i.e. the **Anthropic provider** path is invoked because `"cost list"` was sent as a user prompt instead of being caught by the guard. Same observation for `claw model openai/gpt-4` (operator-natural typo for setting a model), `claw permissions show`, `claw context show`, and all the unrouted plural-noun spellings above. This is materially broader than #78/#145/#452: those filed `plugins` and `models` as **single missing `CliAction` variants**; the pinpoint here is the **guard itself** being shape-blind to subcommand args, so even commands whose bare form *is* correctly handled regress to prompt misdelivery the moment an operator types one more word — including `--model <alias>` confusion (`claw model openai/gpt-4`) which is an extremely natural typo given the existing `claw --model openai/gpt-4 prompt …` flag shape. **Why this is distinct from existing items:** #78/#145 covered `claw plugins` only; #452 covered `claw models*` only. #357 / #322 cover JSON envelope/stderr-prefix issues, not argv classification. The guard surface lives in `parse_subcommand` and `bare_slash_command_guidance` (`rust/crates/rusty-claude-cli/src/main.rs:1100-1149`) — no existing ROADMAP entry tracks the shape-blindness regression class across the guard. **Why it matters:** prompt misdelivery is the Clawhip top-of-list category. With credentials set, every operator/claw typo in this cluster burns provider tokens on a meaningless completion (e.g., sending `"cost list"` to Claude). Without credentials, the wrong-shaped `missing_credentials` envelope is even more confusing — operators see `missing Anthropic credentials` when they meant local cost inspection, and assume an auth bug rather than a CLI dispatch bug. The fix is also extremely localized: it lives in a single guard function. **Required fix shape:** (a) widen `bare_slash_command_guidance` to also fire from the subcommand-args parse arm: when the first positional token matches a known slash-command name and any additional args follow, emit a typed guard error (`"`claw cost list` is a slash command — `claw cost` does not accept extra arguments; use `claw --resume SESSION.jsonl /cost` instead"`) before falling through to `CliAction::Prompt`; (b) extend the guard's known-slash-command set to include the natural CLI discovery spellings that currently fall through entirely (`models`, `model`, `aliases`, `profiles`, `providers list`, `logs`, `settings`), even when there is no corresponding slash command — emit a typed `"unknown CLI subcommand"` error with `did_you_mean` suggestions (`--model <alias> prompt …`, `/models`, `/providers`, `claw config plugins list`) rather than dispatching to LLM prompt; (c) add a structured `kind:"argv_misroute_prevented"` JSON envelope so automation can distinguish guard rejection from auth failure; (d) add regression coverage in `parses_*` test family covering at least one extra-arg case per existing slash-command guard (`cost list`, `tokens list`, `model list`, `model openai/gpt-4`, `permissions show`, `context show`, `cache list`) plus the unrouted-noun cluster (`models list`, `aliases`, `profiles list`, `logs`), asserting every spelling resolves to a typed guard error and **never** to `CliAction::Prompt`. **Acceptance check (one-liner):** `env -u ANTHROPIC_API_KEY -u ANTHROPIC_AUTH_TOKEN claw model openai/gpt-4` should NOT exit with `missing_credentials`; it should exit with a typed CLI dispatch error mentioning `--model openai/gpt-4 prompt …` or `/model`. Source: gaebal-gajae dogfood follow-up for the 2026-05-24 06:00 Clawhip pinpoint nudge at message `1507986539538419863`.
Loading