Commit Graph

1097 Commits

Author SHA1 Message Date
TheArchitectit d8c57ed317 feat: API timeout config, Retry-After header support, and configurable retry
- Add TimeoutConfig to HTTP client builder with connect_timeout (30s)
  and request_timeout (5min) defaults, configurable via
  CLAW_API_CONNECT_TIMEOUT and CLAW_API_REQUEST_TIMEOUT env vars
- Add with_timeout() builder to both AnthropicClient and
  OpenAiCompatClient for per-client timeout configuration
- Parse Retry-After header on 429 responses and use it to override
  exponential backoff delay when present
- Add ApiTimeoutConfig to runtime config with apiTimeout settings
  in ~/.claw/settings.json (connectTimeout, requestTimeout, maxRetries)
- Add retry_after field to ApiError::Api for propagating rate limit
  backoff hints through the retry pipeline
2026-06-02 15:30:22 -05:00
Sam Lamrabte e8c8ef1142 Harden permission enforcement against sandbox bypasses
Close two ways the permission system could be bypassed:

- Workspace path traversal: normalize `.`/`..` lexically before the
  boundary prefix comparison so paths like `/workspace/../../etc` can no
  longer escape the sandbox. Fixed in both the runtime enforcer and the
  duplicate check in the tools PowerShell path classifier.
- read-only mode no longer trusts the leading token alone: reject shell
  metacharacters (chaining/substitution/redirect/pipe/subshell), drop
  interpreters and build drivers (python/node/ruby/cargo/rustc) from the
  allow-list, gate `git` to non-mutating subcommands, and reject `find`
  actions that execute or delete.

Adds regression tests for both holes. The pre-existing, unrelated
worker_boot git-metadata test failure is not affected by this change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 13:26:39 +02:00
YeonGyu-Kim ac5b19dee1
fix: interactive_only hint omits --resume for non-resume-safe commands (#829)
Commands like /commit, /pr, /issue, /bughunter, /ultraplan are
interactive-only and NOT resume-safe. Previously the generic
interactive_only error always suggested 'claw --resume SESSION.jsonl
/commit', which would just re-trigger interactive_only.

Fix: check commands::resume_supported_slash_commands() in the
SlashCommand::Ok(Some(cmd)) arm. Resume-safe commands get the full
--resume suggestion; non-resume-safe commands only say 'Start claw'.

Also update two existing unit tests whose assertions checked for the old
'interactive-only' substring (now 'interactive_only:' prefix).

Two new integration tests:
- non_resume_safe_interactive_only_hint_omits_resume_suggestion
- resume_safe_interactive_only_hint_includes_resume_suggestion

572 tests pass, 1 pre-existing worker_boot failure unrelated.
2026-05-29 16:55:57 +09:00
YeonGyu-Kim 187aebd74f
fix: /approve and /deny outside REPL emit interactive_only error_kind (#828)
/approve, /yes, /deny, /no (and /y, /n) are valid REPL-only slash
commands. Outside the REPL they were falling through to
format_unknown_direct_slash_command -> error_kind:unknown_slash_command.

Fix: intercept them in the SlashCommand::Unknown arm and emit
interactive_only: prefix so classify_error_kind returns the correct kind.

One new test: approve_deny_outside_repl_emits_interactive_only (covers
/approve, /yes, /deny, /no)

572 tests pass, 1 pre-existing worker_boot failure unrelated.
2026-05-29 16:36:54 +09:00
YeonGyu-Kim 9d05573f24
fix: unknown slash command emits unknown_slash_command error_kind (#827)
Both direct-slash CLI path (claw /boguscommand) and resume slash path
(claw --resume session /boguscommand) previously emitted error_kind:unknown
(opaque fallback). Machine consumers could not distinguish unrecognized
slash commands from other error classes.

Fix:
- format_unknown_direct_slash_command: prefix with 'unknown_slash_command:'
- format_unknown_slash_command (resume path): prefix with 'unknown_slash_command:'
- Add classifier arm for 'unknown_slash_command:' prefix

One new regression test: direct_unknown_slash_command_emits_typed_error_kind
Uses the direct-slash CLI path (no session load needed; reproducible on CI).

572 tests pass, 1 pre-existing worker_boot failure unrelated.
2026-05-29 16:00:37 +09:00
YeonGyu-Kim d47b015100
fix: unknown single-word subcommand emits command_not_found (#825/#826)
Single-word all-alpha/dash tokens that don't match any known subcommand
now always emit command_not_found (with or without fuzzy suggestions).

Multi-word cases fall through to CliAction::Prompt (natural language
prompt passthrough like 'claw explain this' must still work). The
multi-word gap is documented as ROADMAP #826 (known limitation).

Tests:
- unknown_subcommand_json_emits_command_not_found (new)
- unknown_subcommand_text_emits_command_not_found_on_stderr (new)
- unknown_subcommand_typo_with_suggestions_json_emits_command_not_found (new)
- multi_word_unknown_subcommand_falls_through_to_prompt_826 (documents gap)

572 tests pass, 1 pre-existing worker_boot failure unrelated.
2026-05-29 14:58:07 +09:00
YeonGyu-Kim 70d64be033
fix: unknown single-word subcommand emits command_not_found instead of missing_credentials (#825)
When looks_like_subcommand_typo fires on a single word with no close
fuzzy matches, the fallthrough reached CliAction::Prompt → provider
startup → misleading missing_credentials error.

Fix: always return Err with command_not_found: prefix from the typo
guard (with or without suggestions). Added command_not_found classifier
arm in classify_error_kind. Unified existing unknown_subcommand kind
under command_not_found in #825.

Three new regression tests in output_format_contract.rs:
- unknown_subcommand_json_emits_command_not_found
- unknown_subcommand_text_emits_command_not_found_on_stderr
- unknown_subcommand_typo_with_suggestions_json_emits_command_not_found

Updated pre-existing unit test assertion (starts_with → contains) and
classifier unit test (unknown_subcommand → command_not_found).

572 tests pass, 1 pre-existing worker_boot failure unrelated.
2026-05-29 14:37:29 +09:00
YeonGyu-Kim de7edd5bb1
fix: suppress config deprecation stderr in JSON mode globally (#824)
Add SUPPRESS_CONFIG_WARNINGS_STDERR AtomicBool flag in runtime/config.rs
and expose suppress_config_warnings_for_json_mode() via runtime crate.

In main.rs, scan raw argv for --output-format json before parse_args
and activate the flag so no settings-load warnings reach stderr on any
JSON-mode surface (status, sandbox, system-prompt, mcp list, skills list,
agents list, --resume /config*, etc.).

Text-mode surfaces are unaffected; prose deprecation warnings continue
to appear on stderr.

All 572+ tests pass (one pre-existing worker_boot failure unrelated).
2026-05-29 14:00:32 +09:00
YeonGyu-Kim b4b1ba10f6
fix: route all JSON-mode abort envelopes to stdout (#819 #820 #823) (#3197)
* fix: route all JSON-mode abort envelopes to stdout (#819 #820 #823)

All handled errors in --output-format json mode now write the structured
abort envelope to stdout (rc=1) and keep stderr empty. Previously the
top-level error handler and resume_session JSON branches used eprintln!
which sent the envelope to stderr, breaking machine consumers that read
stdout for command payloads.

Surfaces fixed:
- Top-level abort handler (main.rs): export --session <missing>,
  session <subcommand>, prompt (no text), unknown subcommand fallthrough,
  flag errors, and all other run() failures
- resume_session JSON branches: session load errors, unsupported commands,
  parse errors, command execution errors

Test changes: updated 24 failing contract tests to assert JSON envelopes
on stdout. Added stderr-clean assertions where appropriate. 70 contract
tests pass (was 68; 2 additional from regression coverage).

ROADMAP: #819 (export session-not-found), #820 (interactive_only class),
#823 (missing prompt)

* style: cargo fmt on main.rs after eprintln->println fix

* fix(tests): fmt + update compact_output test for stdout abort envelope routing

* fix(tests): update resume_slash_commands stub test for stdout envelope routing
2026-05-29 13:30:35 +09:00
Bellman 0800d7ae88
Route plugins list JSON parse errors to stdout (#3194) 2026-05-28 22:35:58 +09:00
Bellman 9494e3c26f
Suppress config warnings on JSON local surfaces (#3192) 2026-05-28 20:34:18 +09:00
Bellman 89e7f415a9
Avoid duplicate config warnings for JSON consumers (#3190)
JSON config output already carries collected config diagnostics in warnings[], so prose stderr emission must be reserved for text/local paths. Lazy permission-mode default resolution prevents an earlier config load from leaking the same deprecation before the JSON renderer runs.\n\nConstraint: ROADMAP #815 requires text mode to keep human stderr warnings while JSON config/list suppresses duplicate app-level config prose.\nRejected: Filtering all stderr in JSON mode | would hide cargo/compiler or unrelated diagnostics outside the app config warning path.\nConfidence: high\nScope-risk: narrow\nDirective: Keep load_collecting_warnings side-effect-free; use load() for human stderr emission.\nTested: cargo fmt; cargo test -p rusty-claude-cli --test output_format_contract config_json_reports_deprecations_structurally_without_stderr_duplicate_815; cargo test -p rusty-claude-cli --test output_format_contract; manual target/debug/claw JSON config fixture.\nNot-tested: cargo clippy -p rusty-claude-cli --all-targets -- -D warnings is blocked by pre-existing runtime dead_code/trident warnings.
2026-05-28 18:09:59 +09:00
Bellman b7ea04661a
test: cover doctor help JSON flag order (#3185) 2026-05-28 14:34:19 +09:00
Bellman 73d8d6e638
Keep doctor help machine-discoverable locally (#3184)
Doctor help was already on the local help path in current source, but the exact #702 dogfood surface lacked a focused guard and the JSON help envelope was still too prose-oriented for wrappers. Strengthen the JSON contract while preserving text help.\n\nConstraint: Preserve unrelated dirty rust/Cargo.lock from prior #701 work.\nRejected: Starting runtime/provider/session to inspect doctor semantics | help must be local and credential-free.\nConfidence: high\nScope-risk: narrow\nDirective: Keep doctor help routed through parse_local_help_action and print_help_topic; do not call run_doctor for --help.\nTested: cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract doctor_help -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract help -- --nocapture; cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo check --manifest-path rust/Cargo.toml -p rusty-claude-cli; timeout 5s cargo run -q --bin claw -- --output-format json doctor --help; timeout 5s cargo run -q --bin claw -- doctor --help.\nNot-tested: full workspace test suite.
2026-05-28 13:31:39 +09:00
Petter Reinholdtsen 1d516be779 fix: recover from llama.cpp context overflow and reqwest SSE decode failures
Extend auto-compaction error detection to handle additional error patterns
from llama.cpp backends: 'Context size has been exceeded',
'exceed_context_size_error', 'exceeds the available context size'. Also
recover from reqwest 'error decoding response body' errors — some
llama.cpp instances return a non-SSE plaintext HTTP 500 on context overflow,
causing the SSE deserializer to fail.

Add dynamic threshold adaptation: parse server-reported context window
size from error messages (e.g., '(81920 tokens)') and set the auto-
compaction trigger at 70% of that value. This replaces the need for a
hardcoded threshold, adapting automatically to any backend's limits.

This patch was developed with assistance from OpenCode and local Qwen 3.6
API server.
2026-05-27 16:57:59 +02:00
YeonGyu-Kim 87b7e74770 fix(#806): plugins show <not-found> in text mode returned empty success instead of error 2026-05-27 22:34:10 +09:00
Bellman ae6a207d4e
fix(#3129): handle trailing json format for diff errors (#3161)
Keep malformed diff invocations with trailing JSON format flags on the parser error path and lock the contract with focused output-format regressions.

Constraint: Do not touch tracked .omx state files.

Rejected: Repeating direct binary smoke loops | local auth/provider configuration intercepts those invocations and obscures parser behavior.

Confidence: high

Scope-risk: narrow

Tested: git diff --check; cargo fmt --check; cargo test -p rusty-claude-cli diff_extra_args_have_typed_error_kind_and_hint_766 --test output_format_contract; cargo test -p rusty-claude-cli diff_trailing_json_after_malformed_args_is_bounded_json_3129 --test output_format_contract; cargo test -p rusty-claude-cli diff_non_git_dir_has_error_kind_and_hint_801 --test output_format_contract
2026-05-27 21:57:26 +09:00
YeonGyu-Kim efd34c151a fix(#805): skills show <not-found> in text mode silently returned empty success instead of error 2026-05-27 21:05:41 +09:00
YeonGyu-Kim 2c3c0f60e7 fix(#804): agents/skills show <name> <extra> in text mode returned wrong error instead of unexpected_extra_args 2026-05-27 20:05:39 +09:00
YeonGyu-Kim bad1b97f8e fix(#803): agents/skills/plugins list --flag in text mode silently returned empty success 2026-05-27 19:38:31 +09:00
YeonGyu-Kim fcebf64468 fix(#802): four resume-mode and broad-cwd error envelopes now include hint field 2026-05-27 19:04:15 +09:00
YeonGyu-Kim 53953a8157 fix(#801): diff non-git-dir error envelope now includes error_kind, hint, and message fields 2026-05-27 18:34:58 +09:00
YeonGyu-Kim 6ee67d6c61 test: add unit test coverage for invalid_history_count and unknown_option classifier arms
Two classifier arms had no corresponding assert_eq! in
test_classify_error_kind_returns_correct_discriminants: invalid_history_count
(both prefix and contains paths) and unknown_option (#790). Now 49/39 = full
coverage of all classify_error_kind return values.
2026-05-27 18:05:33 +09:00
YeonGyu-Kim efb1542a39 fix: empty-prompt error now returns non-null hint via newline-delimited usage string
claw '' and claw '   ' returned empty_prompt + hint:null because the
error message had no newline delimiter. Added usage hint. 61 CLI
contract tests pass.
2026-05-27 16:34:37 +09:00
YeonGyu-Kim bff370003b fix: plugins extra-arg errors now return non-null hint via newline-delimited usage string
Parity with #791 (config extra-arg fix). The plugins arg parser emitted
'unexpected extra arguments after claw plugins show ...' with no newline
delimiter, so split_error_hint returned None. Added usage hint after newline.
60 CLI contract tests pass.
2026-05-27 15:04:03 +09:00
YeonGyu-Kim 9976585f87 fix(#796): agents/skills show <name> <extra> returned wrong not-found instead of unexpected_extra_args 2026-05-27 14:07:04 +09:00
YeonGyu-Kim 18b4cee5fd fix(#795): skill_not_found and unsupported_skills_action now return non-null hints via fallback table 2026-05-27 13:34:09 +09:00
YeonGyu-Kim 491f179a03 fix(#794): plugins install not-found path returns typed plugin_source_not_found instead of unknown+null 2026-05-27 13:08:14 +09:00
YeonGyu-Kim 57a57ef771 fix(#793): plugins list --flag silent success + uninstall not-found hint:null 2026-05-27 12:34:35 +09:00
YeonGyu-Kim abfa2e4cf7 fix(#792): agents/skills list --flag silently returned empty success; now returns unknown_option error 2026-05-27 11:39:44 +09:00
YeonGyu-Kim 93a159dca5 fix(#791): config extra-arg errors now return non-null hint via \n-delimited usage string 2026-05-27 11:04:50 +09:00
YeonGyu-Kim 9968a27e92 fix(#790): system-prompt unknown-option errors now return typed unknown_option kind + non-null hint 2026-05-27 10:36:12 +09:00
YeonGyu-Kim e4c3c1aa80 fix(#789): agents show and plugins show not-found now exit 1; parity with skills (#788) and mcp (#68) 2026-05-27 10:07:51 +09:00
YeonGyu-Kim abdbf61acf fix(#788): skills show not-found emitted duplicate JSON error envelope; use exit(1) instead of Err propagation 2026-05-27 09:36:11 +09:00
YeonGyu-Kim 113145a42a fix(#787): --resume with directory path returns session_path_is_directory kind + hint; wire fallback_hint_for_error_kind into both resume error emission sites 2026-05-27 09:06:28 +09:00
YeonGyu-Kim 22b423b651 fix(#786): dump-manifests --manifests-dir missing-value errors now return typed missing_flag_value kind + non-null hint 2026-05-27 08:39:11 +09:00
YeonGyu-Kim 87f4334728 fix(#785): add unknown_subcommand classifier arm for unknown subcommand: prose prefix 2026-05-27 08:36:41 +09:00
YeonGyu-Kim e628b4bb68 fix(#784): export --output missing-value and extra-positional errors now return typed error_kind + non-null hint 2026-05-27 08:07:32 +09:00
YeonGyu-Kim 81fe0ccbb7 fix(#783): init JSON envelope now includes hint and already_initialized fields for orchestrator parity 2026-05-27 08:04:15 +09:00
YeonGyu-Kim 32c9276fdb fix(#782): acp unsupported invocation now returns non-null hint with newline-delimited remediation text 2026-05-27 07:37:26 +09:00
YeonGyu-Kim 16c1117af6 fix(#781): sub-classify api_auth_error/api_rate_limit_error from api_http_error; add fallback_hint_for_error_kind for hint-less API errors 2026-05-27 07:34:57 +09:00
YeonGyu-Kim d9844cfe8d fix(#780): classifier arm ordering bug — legacy_session_no_workspace_binding and no_managed_sessions shadowed by generic session_load_failed arm 2026-05-27 05:34:49 +09:00
YeonGyu-Kim 364e7909f4 fix(#779): resumed /skills invocation returns interactive_only error_kind + non-null hint 2026-05-27 05:09:07 +09:00
YeonGyu-Kim fded4f6b11 fix(#778): doctor check JSON objects now include hint field with stable remediation text for warn/fail checks 2026-05-27 05:07:02 +09:00
YeonGyu-Kim e02030364d fix(#777): resumed /plugins mutations return interactive_only error_kind + non-null hint instead of unknown+null 2026-05-27 04:44:06 +09:00
YeonGyu-Kim 2684737d9e fix(#776): resume command errors now return typed error_kind + non-null hint (invalid_history_count, session action errors) 2026-05-27 04:39:43 +09:00
YeonGyu-Kim 028998d040 test(#775): integration tests for #769-#771 interactive-only guards and #774 hint fields; fix stale classifier unit test string 2026-05-27 04:03:52 +09:00
YeonGyu-Kim c760a49c47 fix(#774): agents/plugins/mcp unknown-subcommand errors now include non-null hint 2026-05-27 03:37:00 +09:00
YeonGyu-Kim 727a1ea4a3 fix(#773): config --output-format json now surfaces deprecation warnings in warnings[] array instead of only stderr text 2026-05-27 03:05:14 +09:00
YeonGyu-Kim 212f0b2ad4 fix(#772): slash command aliases now resolve to canonical forms in interactive_only guidance 2026-05-27 02:37:17 +09:00
YeonGyu-Kim bf212b986d fix(#771): init rejects extra args; usage/stats/fork return interactive_only instead of credential check 2026-05-27 02:33:55 +09:00
YeonGyu-Kim 3a1d88386c fix(#770): cost/clear/memory/ultraplan/model with args now return interactive_only instead of falling to credential check 2026-05-27 02:10:41 +09:00
YeonGyu-Kim 9e1be05634 fix(#769): claw session <arg> now returns interactive_only instead of falling to credential check 2026-05-27 02:05:14 +09:00
YeonGyu-Kim b778d4e3d4 fix(#768): --resume non-slash trailing arg now has error_kind:invalid_resume_argument + hint 2026-05-27 01:35:46 +09:00
YeonGyu-Kim 89735dbd33 fix(#766): claw diff extra args now classified as unexpected_extra_args with hint; track #767 session subcommand gap 2026-05-27 01:33:24 +09:00
YeonGyu-Kim d29a8e216b fix(#765): login/logout removed_subcommand now has error_kind + non-null hint 2026-05-27 01:28:35 +09:00
YeonGyu-Kim 4ea255ca6a fix(#764): config_parse_error now populates hint field via Display newline delimiter 2026-05-27 01:23:00 +09:00
YeonGyu-Kim c86dc73d8c fix(#763): config JSON parse errors now classify as config_parse_error 2026-05-27 01:16:04 +09:00
YeonGyu-Kim 88ce181031 test(#762): classify_error_kind now covers all 23 classifier arms (was 8 of 23) 2026-05-27 00:33:11 +09:00
YeonGyu-Kim d83de563c1 fix(#761): mcp server_not_found and skill_not_found envelopes now include hint field 2026-05-27 00:03:53 +09:00
YeonGyu-Kim 7fa81b5dae fix(#760): agent_not_found and plugin_not_found envelopes now include hint field 2026-05-26 23:36:30 +09:00
YeonGyu-Kim ef31328aab fix(#759): validate_model_syntax error strings now use newline separator so hint is non-null 2026-05-26 23:04:04 +09:00
YeonGyu-Kim b8b3af6fc9 fix(#758): --cwd, --date, --session missing-value errors now use missing_flag_value prefix + hint 2026-05-26 22:34:18 +09:00
YeonGyu-Kim 02d77ae1f1 fix(#757): --permission-mode invalid and --allowedTools missing now emit typed error_kind and hint 2026-05-26 22:04:00 +09:00
YeonGyu-Kim 4df146188f fix+test(#756): missing/invalid flag-value errors now emit typed error_kind and non-null hint 2026-05-26 21:37:28 +09:00
YeonGyu-Kim 0e8a449ea9 fix+test(#755): -p consumes exactly one token; flags after prompt text now parse normally 2026-05-26 21:27:39 +09:00
YeonGyu-Kim c70312bd04 fix(#754): missing_credentials hint now newline-delimited so JSON hint field is non-null 2026-05-26 21:23:03 +09:00
YeonGyu-Kim e93271356f fix+test(#753): claw -p (no arg) parity with #750: error_kind:missing_prompt with non-null hint 2026-05-26 20:46:27 +09:00
YeonGyu-Kim cfc26729cf fix(#752): cli_parse unrecognized-arg errors now emit non-null hint for all subcommands 2026-05-26 20:41:12 +09:00
YeonGyu-Kim ddc71b5620 test(#751): regression guard for #750 prompt no-arg error_kind and hint contract 2026-05-26 20:05:34 +09:00
YeonGyu-Kim ac925ed41c fix(#750): claw prompt (no arg) now emits error_kind:missing_prompt with non-null hint 2026-05-26 20:03:14 +09:00
YeonGyu-Kim 2dfb7af66e fix+test(#749): compact interactive-only hint now non-null; extend compact JSON test for hint contract 2026-05-26 19:38:09 +09:00
YeonGyu-Kim 3975f2b3ab fix(#748): mcp unknown subcommand now emits error_kind:unknown_mcp_action matching agents/plugins parity 2026-05-26 19:35:55 +09:00
YeonGyu-Kim 04eb661e57 test(#747): regression guard for #745 bare slash command hint contract (issue/pr/commit) 2026-05-26 19:06:59 +09:00
YeonGyu-Kim 18e7744e42 fix(#746): non-TTY interactive-only error populates hint field via newline split 2026-05-26 19:04:56 +09:00
YeonGyu-Kim 3c5459a33b fix(#745): bare slash command guidance adds newline before hint; claw issue/pr/commit etc now have non-null hint 2026-05-26 18:36:21 +09:00
YeonGyu-Kim 92e053a133 test(#744): regression guard for #741 config unsupported-section hint contract 2026-05-26 18:06:35 +09:00
YeonGyu-Kim 1d5db5f77d fix(#743): plugins help --output-format json now emits usage envelope matching agents/mcp/skills help shape; resolves #420 2026-05-26 18:04:04 +09:00
YeonGyu-Kim 2036f0bd4c test(#742): add git-fixture test for diff changed_file_count dedup; fixes unreachable branch in #740 coverage 2026-05-26 17:41:02 +09:00
YeonGyu-Kim 6e78c1fc8b fix(#741): config unsupported_config_section error now populates hint field; list/show/help verbs get usage hint 2026-05-26 17:38:02 +09:00
YeonGyu-Kim 5d072d21e9 test(#740): diff JSON contract test now asserts changed_file_count field behavior per #733 2026-05-26 16:45:02 +09:00
YeonGyu-Kim d5f0d6ed3e fix(#739): skills unknown-subcommand JSON path no longer emits double error envelope; help action not propagated as Err 2026-05-26 16:38:17 +09:00
YeonGyu-Kim 4c3cb0f347 fix(#738): interactive-only slash command error adds newline before hint; hint field now non-null with remediation text 2026-05-26 16:06:38 +09:00
YeonGyu-Kim c592313d9a test(#737): add boot_preflight details non-null-value regression guard to output_format_contract 2026-05-26 15:05:00 +09:00
YeonGyu-Kim ad982d20c2 fix(#736): boot_preflight doctor details[] null-value entries: add double-space separator to Required binary, Last failed boot, MCP/Plugin eligible format strings 2026-05-26 14:33:18 +09:00
YeonGyu-Kim b3242e8c04 fix(#735): classify_error_kind: /compact and other interactive-only slash commands now emit error_kind:interactive_only not unknown 2026-05-26 14:08:53 +09:00
YeonGyu-Kim d4494a8aeb fix(#734): agents/plugins show not-found envelopes gain message field; parity with skills show 2026-05-26 13:34:36 +09:00
YeonGyu-Kim cc86f54d65 fix(#701): doctor JSON details[] now {key,value} objects; prose preserved as details_prose[]; acceptance check passes 2026-05-26 13:10:05 +09:00
YeonGyu-Kim db80c9b96e fix(#733): diff JSON adds changed_file_count; run git diff --name-only for staged+unstaged and deduplicate into BTreeSet 2026-05-26 13:05:44 +09:00
YeonGyu-Kim 4c16a42f39 fix(#732): status JSON allowed_tools.entries:null→[] when unrestricted; callers can use .entries|length without null guard 2026-05-26 12:36:13 +09:00
YeonGyu-Kim 29dcd478a0 fix(#731): sandbox JSON status:error→warn when filesystem sandbox active but namespace unsupported (macOS degraded state) 2026-05-26 12:05:11 +09:00
YeonGyu-Kim 425d94ee43 fix(#730): add path field to plugins list/show JSON; completes path-discoverability trio (agents #728, skills #729, plugins #730) 2026-05-26 11:38:48 +09:00
YeonGyu-Kim 8f44ad308d fix(#729): add path field to skills list/show JSON; SkillSummary parity with AgentSummary (#728) 2026-05-26 11:32:53 +09:00
YeonGyu-Kim fa29909f05 fix(#728): add path field to agents list/show JSON; AgentSummary now stores on-disk .toml path from discovery loop 2026-05-26 11:09:46 +09:00
YeonGyu-Kim 9757fef8a7 fix(#727): add has_upstream bool to branch_freshness JSON to disambiguate fresh:null-no-upstream from fresh:null-unknown 2026-05-26 10:34:28 +09:00
YeonGyu-Kim a0c6c8ba53 fix(#726): classify legacy_session_no_workspace_binding error_kind in export path 2026-05-26 10:04:32 +09:00
YeonGyu-Kim d8a6109085 docs(#721/#722): re-add ROADMAP entry for config section expansion after rebase conflict 2026-05-26 08:06:11 +09:00
YeonGyu-Kim 02d1f6a04d fix(#720): claw help <topic> now routes to subsystem help instead of cli_parse error; add Agents/Skills/Plugins/Mcp/Config/Diff help topics 2026-05-26 07:36:50 +09:00
YeonGyu-Kim fe2b13a46a fix(#719): plugins list <filter> now applies substring filter on plugin id, matching agents/skills parity 2026-05-26 07:03:22 +09:00
YeonGyu-Kim 556a598f2d fix(#718): implement plugins show/info/describe command with not-found error, parity with agents/skills show 2026-05-26 06:33:52 +09:00
YeonGyu-Kim 8d80f2ffe7 test(#717): add contract tests for agents show not-found and agents list filter in output_format_contract 2026-05-26 06:04:23 +09:00
Bellman 8280f66aa1
Warn before unwritable git metadata blocks worker commits (#3112)
Use git rev-parse --git-dir so startup preflight follows worktree .git indirections to the real metadata directory, then check directory permission metadata without creating probe files. Add a regression that verifies both the warning kind and structured event path for a read-only external gitdir.

Constraint: ROADMAP #695 requires early startup/worktree diagnostics without destructive writes or broad sandbox redesign.

Rejected: write-probe detection | it mutates git metadata during a diagnostic path.

Confidence: high

Scope-risk: narrow

Directive: Keep startup preflight warnings non-destructive and structured by warning kind/path.

Tested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p runtime startup_preflight -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p runtime worker_boot -- --nocapture; cargo check --manifest-path rust/Cargo.toml --workspace

Not-tested: full cargo test --manifest-path rust/Cargo.toml --workspace
2026-05-26 05:01:39 +08:00
YeonGyu-Kim a0b375c157 fix(#717): implement agents show/info/describe and list filter commands, mirror skills handler parity 2026-05-26 05:36:27 +09:00
YeonGyu-Kim 98f8926998 fix(#716): align 5 resume-path error JSON envelopes from legacy type:error shape to standard kind/action/status/error_kind/exit_code contract 2026-05-26 05:04:50 +09:00
YeonGyu-Kim 76c8d4801e
Merge pull request #3110 from Yeachan-Heo/fix/issue-693-analog-phase-error
Fix claw-analog bootstrap phase drift errors
2026-05-26 04:39:36 +09:00
YeonGyu-Kim 4b8731ba11 fix(#715): add action+status fields to resume-path json responses: compact/clear/cost/stats/history/session_exists/session_delete/memory/restored 2026-05-26 04:35:46 +09:00
Yeachan-Heo 789ea9aac8 Reject drifted claw-analog bootstrap phases
The analog RAG/bootstrap formatter already rejected missing and literal unknown phases, but still accepted arbitrary phase strings. Keep the parser aligned with the runtime/service contract by allowlisting the known emitted phases and returning the existing typed error shape with received value and field context when drift appears.

Constraint: Scope is limited to claw-analog bootstrap/RAG phase parsing for ROADMAP #693.
Rejected: Preserve arbitrary non-empty phases | would continue hiding producer/parser phase drift.
Confidence: high
Scope-risk: narrow
Directive: Update KNOWN_RAG_BOOTSTRAP_PHASES when claw-rag-service deliberately adds a new response phase.
Tested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p claw-analog rag_response -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p claw-analog -- --nocapture; cargo check --manifest-path rust/Cargo.toml -p claw-analog; cargo check --manifest-path rust/Cargo.toml --workspace; git diff --check
Not-tested: Full workspace cargo test; remote CI
2026-05-25 19:33:37 +00:00
Yeachan-Heo 45dc4f6ff0 Stabilize JSON action contract for local CLI surfaces
Guard the local/no-credential JSON command sweep so future additions fail fast when action is absent or empty.

Constraint: ROADMAP #710-#713 fixed most JSON surfaces; #714 dogfood sweep found remaining help and sandbox gaps.

Rejected: Schema redesign for help output | outside the action-field contract scope.

Confidence: high

Scope-risk: narrow

Directive: Keep --output-format json envelopes carrying a stable non-empty action on every local CLI surface.

Tested: cargo fmt --manifest-path rust/Cargo.toml --all; cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract -- --nocapture; cargo check --manifest-path rust/Cargo.toml -p rusty-claude-cli; git diff --check

Not-tested: full workspace cargo test
2026-05-25 19:06:16 +00:00
YeonGyu-Kim 7037d84d52 fix(#714): add action:help to top-level help json, render_export_help_json, render_help_topic_json, and resume repl help json 2026-05-26 04:03:34 +09:00
YeonGyu-Kim 7d6b2044d5 fix(#713): add missing action fields to acp and config json responses; acp->status, config bare->list, config section->show 2026-05-26 03:32:02 +09:00
YeonGyu-Kim fdde5e45cf fix(#712): add missing action fields to doctor/status/bootstrap-plan/dump-manifests json responses 2026-05-26 03:02:57 +09:00
YeonGyu-Kim bae0099c7c fix(#711): add missing action fields to version/system-prompt/export/init json responses; add contract test assertions 2026-05-26 02:33:26 +09:00
YeonGyu-Kim 42c17bc4bf
Merge pull request #3108 from Yeachan-Heo/fix/issue-335-session-created-at-ms
Expose created_at_ms in session list JSON
2026-05-26 02:15:40 +09:00
YeonGyu-Kim f8a901c2a5 fix(#710): diff --output-format json adds missing action:diff and working_directory fields to both ok and error branches 2026-05-26 02:07:46 +09:00
Yeachan-Heo a30624d6d4 Expose creation time in session list metadata
Preserve session-list consumers from depending on encoded session IDs by carrying persisted creation timestamps through managed summaries and JSON detail output, with an ID timestamp fallback only for legacy metadata that lacks created_at_ms.\n\nConstraint: ROADMAP #335 requires created_at_ms in session_details with the same millisecond unit as updated_at_ms.\nRejected: Making callers parse session IDs | undocumented ID structure is brittle and was the issue being fixed.\nRejected: Session storage redesign | scope is limited to detail metadata propagation and legacy compatibility.\nConfidence: high\nScope-risk: narrow\nDirective: Keep ID timestamp parsing fallback-only; persisted session_meta.created_at_ms remains the source of truth when present.\nTested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo check --manifest-path rust/Cargo.toml --workspace; cargo build --manifest-path rust/Cargo.toml --workspace; cargo test --manifest-path rust/Cargo.toml --workspace; cargo clippy --manifest-path rust/Cargo.toml -p runtime -p rusty-claude-cli --all-targets\nNot-tested: live interactive /session list against a real provider-backed REPL
2026-05-25 17:06:08 +00:00
YeonGyu-Kim 8f8eb41e0f fix(#709): remove duplicate status:ok keys from render_agents_report_json and render_skill_install_report_json; silent overwrite risk in serde_json json! macro 2026-05-26 01:32:37 +09:00
YeonGyu-Kim 47c0226a61 fix(#708): skills show/info/describe responses now emit action:show instead of action:list; remove duplicate status key from render_skills_report_json 2026-05-26 01:05:07 +09:00
YeonGyu-Kim 26a50d918b
Merge pull request #3107 from Yeachan-Heo/fix/issue-698-config-warning-dedup
test: cover config warning dedup for inventory commands
2026-05-26 00:41:39 +09:00
YeonGyu-Kim 401f6b152c fix(#707): init test temp_dir combines AtomicU64 counter+nanos to prevent same-process parallel test collisions 2026-05-26 00:36:07 +09:00
Yeachan-Heo 1b5a9b02c2 test: cover config warning dedup for inventory commands
Add a CLI contract proving plugins list and mcp list emit a deprecated enabledPlugins warning only once per process after config warning dedup landed. Covers ROADMAP #698.
2026-05-25 15:30:48 +00:00
YeonGyu-Kim dedad14ae4 fix(#706): skills show <name> returns error+exit1 when skill not found; classify_error_kind covers skill_not_found from prose message 2026-05-26 00:04:39 +09:00
YeonGyu-Kim f84799c8ef fix: auto_compact runs before every iteration break, including terminal no-tool turns; closes #3106 2026-05-25 23:59:04 +09:00
YeonGyu-Kim 732007da8e fix(#705): add estimated_cost_usd_num (float) to usage JSON alongside string field; doc entry filed 2026-05-25 23:33:14 +09:00
YeonGyu-Kim 8f809d9a9e fix(#704): DiagnosticCheck.json_value now emits stable snake_case id field; doctor checks addressable without scraping name prose 2026-05-25 23:04:06 +09:00
YeonGyu-Kim 1a6f54b970 fix(#703): plugins list JSON now has summary:{total,enabled,disabled,load_failures}; drop reload_runtime/target from list response in both top-level and resume paths 2026-05-25 22:34:20 +09:00
YeonGyu-Kim 1555785294
Merge pull request #3104 from Yeachan-Heo/fix/issue-702-allowed-tools-ci
Stabilize allowedTools rejection contract in CI
2026-05-25 22:03:40 +09:00
YeonGyu-Kim 2f9429cbf0 fix: slash-command guard errors now emit error_kind:interactive_only instead of unknown; covers memory, permissions, review, and any bare_slash_command_guidance path 2026-05-25 22:02:30 +09:00
Yeachan-Heo 4daefc7bd5 Stabilize allowedTools rejection contract in CI
Serialize the allowedTools rejection tests with the existing environment/current-directory test guards so full parallel cargo test runs cannot observe a transient project config or cwd from another test while building the tool registry.\n\nConstraint: Post-merge Rust build workflow run 26399647443 failed only in the full cargo test job while the focused test passed locally.\nRejected: Changing allowedTools parser output | the product contract remains correct and focused reproduction preserves the expected unsupported-tool error.\nConfidence: high\nScope-risk: narrow\nDirective: Keep this as test isolation only; do not bundle inventory provenance or ROADMAP work into this follow-up.\nTested: cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli tests::rejects_unknown_allowed_tools -- --exact --nocapture; cargo test --verbose -p rusty-claude-cli --bin claw; cargo test --verbose; cargo fmt --check; cargo check --workspace --locked; cargo build --workspace --locked\nNot-tested: GitHub Actions rerun before opening PR
2026-05-25 12:55:53 +00:00
YeonGyu-Kim 5bca9ef039
Merge pull request #3103 from Yeachan-Heo/fix/issue-702-inventory-provenance
Fix #702 inventory provenance schema
2026-05-25 21:10:18 +09:00
YeonGyu-Kim b8eca2a68e fix(#349): plugins unknown action emits status:error + error_kind:unknown_plugins_action + exit 1 instead of status:ok with prose 2026-05-25 21:08:14 +09:00
Yeachan-Heo 566992c331 Unify inventory provenance for generic parsers
Expose a stable source object on agent and skill inventory entries with the same id/label/detail_label keys while preserving skill origin for compatibility.\n\nConstraint: ROADMAP #702 scope only; keep existing skills origin field for compatibility.\nRejected: Rename agent source to origin | would break existing agents consumers and still require per-resource branching during migration.\nConfidence: high\nScope-risk: narrow\nDirective: Future inventory resources should expose provenance through source.id, source.label, and source.detail_label.\nTested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p commands renders_skills_reports_as_json -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract -- --nocapture; cargo build --manifest-path rust/Cargo.toml --workspace --locked; git diff --check\nNot-tested: full cargo test --manifest-path rust/Cargo.toml --workspace
2026-05-25 12:05:50 +00:00
YeonGyu-Kim 36b36267ec fix(#458): add status:ok to config JSON envelope; unknown section now emits status:error + error_kind:unsupported_config_section 2026-05-25 20:33:36 +09:00
YeonGyu-Kim ee24ff2d83
Merge pull request #3102 from Yeachan-Heo/fix/issue-696-compact-nontty
Fix compact non-TTY hang
2026-05-25 19:41:27 +09:00
Yeachan-Heo 9e6f753640 Fail closed for compact without an interactive session
Route bare compact invocations to a typed interactive-only error before prompt/provider startup so non-TTY JSON probes terminate predictably. Keep the existing resume-session /compact path as the supported automation surface.\n\nConstraint: ROADMAP pinpoint #696 requires no spinner/hang for closed stdin and --output-format json.\nRejected: Broad help-schema rewrites | #699/#700/#701 are outside this PR scope.\nConfidence: high\nScope-risk: narrow\nDirective: Do not route bare slash-command names through the prompt fallback when they require a session.\nTested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test compact_output compact_subcommand_ -- --nocapture; cargo build --manifest-path rust/Cargo.toml --workspace; cargo build --manifest-path rust/Cargo.toml --workspace --locked; timeout probes for compact JSON/text with stdin closed.\nNot-tested: Full workspace test suite.
2026-05-25 10:37:12 +00:00
YeonGyu-Kim de2e32c5d4 fix: skills install nonexistent path emits skill_not_found error kind with descriptive message; classify_error_kind adds skill_not_found branch 2026-05-25 19:34:25 +09:00
YeonGyu-Kim 9d1998b3fd test(#458/#700/#701/#702): add status:ok assertions for help/bootstrap-plan/export-help contracts; add diff/export JSON shape tests 2026-05-25 19:07:03 +09:00
YeonGyu-Kim 181b12f0a9 fix: mcp show <nonexistent> now returns status:error + error_kind:server_not_found + exit 1; extend ok:false gate to also check status:error 2026-05-25 18:34:43 +09:00
YeonGyu-Kim 47521cf178 fix(#701): add detail_entries structured key/value to doctor check JSON; booleans/ints emitted as JSON scalars 2026-05-25 18:02:03 +09:00
YeonGyu-Kim f9e98a2634 fix(#700): add status:ok to all help JSON envelopes; rename session_list kind to sessions with action:list 2026-05-25 17:05:28 +09:00
YeonGyu-Kim eb7c14c4ae fix(#458): add status:ok to bootstrap-plan JSON envelope; all 12 JSON surfaces now have uniform status field 2026-05-25 16:34:33 +09:00
YeonGyu-Kim 11a6e081a2 fix(#458): add status field to export and diff JSON envelopes 2026-05-25 16:07:16 +09:00
Bellman 16604a111b
fix(#458): add status assertions to skills/agents JSON envelope tests
Adds test coverage asserting status:ok in skills list, agents list, skills install, skills help, and agents help JSON envelopes. Status fields themselves were already landed in 0581894b and cc1462a7; this PR adds the regression test assertions that were missing. Duplicate status keys in json! macros are benign (serde_json takes last value) but harmless given all tests pass.
2026-05-25 15:35:40 +09:00
YeonGyu-Kim cc1462a7f8 fix(#458): add status:ok to skills install JSON envelope (missed in previous sweep) 2026-05-25 15:30:22 +09:00
YeonGyu-Kim f2a90228fb fix: doctor boot preflight detail shows Some(false) for trust_gate_allowed; use Display instead of Debug 2026-05-25 15:21:15 +09:00
YeonGyu-Kim 0581894b7e fix(#458): add status:ok to agents and skills list JSON envelopes; all 9 subcommands now pass uniform status check 2026-05-25 15:02:25 +09:00
YeonGyu-Kim 5b79413e87 fix(#458): add status field to version/init/system-prompt JSON envelopes; all 9 subcommands now have uniform status field 2026-05-25 14:36:12 +09:00
YeonGyu-Kim 85e736c73f fix: add status field to sandbox JSON envelope (ok/warn/error derived from enabled+active+supported) 2026-05-25 14:34:00 +09:00
YeonGyu-Kim b64df99134 fix(#698): dedup config deprecation warnings per process; add tempfile dev-dep to runtime crate (fixes pre-existing test compile error) 2026-05-25 14:11:37 +09:00
YeonGyu-Kim c345ce6d02 fix: mcp/agents/skills help envelopes set ok:false + status:error on unknown subcommand; exit 1 propagates correctly 2026-05-25 13:50:51 +09:00
YeonGyu-Kim 91a0681ae9 fix(#697): agents unknown subcommand exits 1 with typed error; plugins remove aliases uninstall and errors on not-found 2026-05-25 13:39:23 +09:00