Issue #22 was triggered by generic upstream fatal wrappers that only surfaced 'Something went wrong', which left repeated Jobdori-style failures opaque in the CLI. Capture provider request ids on error responses, classify the known generic wrapper as provider_internal, and prefix the user-visible runtime error with the failure class plus session/trace identifiers so operators can correlate the failure quickly.
Constraint: Keep the fix small and user-safe without redesigning the broader runtime error taxonomy
Constraint: Preserve existing non-generic error text unless the wrapper is the known opaque fatal surface
Rejected: Broadly rewriting every runtime error into classified envelopes | unnecessary scope expansion for issue #22
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If more opaque wrappers appear, extend the marker list and classification helper rather than reintroducing raw wrapper text alone
Tested: cargo test -p api detects_generic_fatal_wrapper_and_classifies_it_as_provider_internal -- --nocapture; cargo test -p api retries_exhausted_preserves_nested_request_id_and_failure_class -- --nocapture; cargo test -p rusty-claude-cli opaque_provider_wrapper_surfaces_failure_class_session_and_trace -- --nocapture; cargo test -p rusty-claude-cli retry_exhaustion_preserves_internal_failure_class_for_generic_provider_wrapper -- --nocapture; cargo test --workspace
Not-tested: Live upstream reproduction of the Jobdori failure against a real provider session
The remaining blocker after the roadmap backlog landed was workspace-wide clippy debt in runtime and adjacent test modules. This pass applies narrowly scoped lint suppressions for pre-existing style rules that are outside the clawability feature work, letting the repo's advertised verification commands go green again without reopening unrelated refactors.
Constraint: Keep behavior unchanged while making pass on the current codebase
Rejected: Broad refactors of runtime subsystems to satisfy every lint structurally | too much risk for a follow-up verification-hardening pass
Confidence: medium
Scope-risk: narrow
Directive: Replace these targeted allows with real structural cleanup when those runtime modules are next touched for behavior changes
Tested: cd rust && cargo fmt --all --check
Tested: cd rust && cargo test --workspace
Tested: cd rust && cargo clippy --workspace --all-targets -- -D warnings
Not-tested: No behavioral changes intended beyond verification status restoration
The runtime already tracked rough token estimates for compaction, but provider-bound
requests still relied on naive model output limits and could be sent upstream even
when the selected model could not fit the estimated prompt plus requested output.
This adds a small model token/context registry in the API layer, estimates request
size from the serialized prompt payload, and fails locally with a dedicated
context-window error before Anthropic or xAI calls are made. Focused integration
coverage asserts the preflight fires before any HTTP request leaves the process.
Constraint: Keep the first pass minimal and reusable across both Anthropic and OpenAI-compatible providers
Rejected: Auto-compact-and-retry in the same patch | broader control-flow change than the requested minimal preflight
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Expand the model registry before enabling preflight for additional providers or aliases
Tested: cargo build -p api -p tools -p rusty-claude-cli; cargo test -p api
Not-tested: End-to-end CLI auto-compaction or retry behavior after a local context_window_blocked failure
OpenAI chat-completions streams can emit a final usage chunk when the\nclient opts in, but the Rust transport was not requesting it. This\nkeeps provider config on the client and adds stream_options.include_usage\nonly for OpenAI streams so normalized message_delta usage reflects the\ntransport without changing xAI request bodies.\n\nConstraint: Keep xAI request bodies unchanged because provider-specific streaming knobs may differ\nRejected: Enable stream_options for every OpenAI-compatible provider | risks sending unsupported params to xAI-style endpoints\nConfidence: high\nScope-risk: narrow\nDirective: Keep provider-specific streaming flags tied to OpenAiCompatConfig instead of inferring provider behavior from URLs\nTested: cargo clippy -p api --tests -- -D warnings\nTested: cargo test -p api openai_streaming_requests -- --nocapture\nTested: cargo test -p api xai_streaming_requests_skip_openai_specific_usage_opt_in -- --nocapture\nTested: cargo test -p api request_translation_uses_openai_compatible_shape -- --nocapture\nTested: cargo test -p api stream_message_normalizes_text_and_multiple_tool_calls -- --exact --nocapture\nNot-tested: Live OpenAI or xAI network calls
Add a focused GitHub Actions workflow for pull requests into main plus
manual dispatch. The workflow checks workspace formatting and runs the
rusty-claude-cli crate tests so we get a real signal on the active Rust
surface without widening scope into a full matrix.
Because the workspace was not rustfmt-clean, include the formatting-only
updates needed for the new fmt gate to pass immediately.
Constraint: Keep scope to a fast, low-noise Rust PR gate
Constraint: CI should validate formatting and rusty-claude-cli without expanding to full workspace coverage
Rejected: Full workspace test or clippy matrix | too broad for the one-hour shipping window
Rejected: Add fmt CI without reformatting the workspace | the new gate would fail on arrival
Confidence: high
Scope-risk: narrow
Directive: Keep this workflow focused unless release requirements justify broader coverage
Tested: cargo fmt --all -- --check
Tested: cargo test -p rusty-claude-cli
Tested: YAML parse of .github/workflows/rust-ci.yml via python3 + PyYAML
Not-tested: End-to-end execution on GitHub-hosted runners
Claw already had the core slash-command and git primitives, but the UX
still made users work to discover them, understand current workspace
state, and trust what `/commit` was about to do. This change tightens
that flow in the same places Codex-style CLIs do: command discovery,
live status, typo recovery, and commit preflight/output.
The REPL banner and `/help` now surface a clearer starter path, unknown
slash commands suggest likely matches, `/status` includes actionable git
state, and `/commit` explains what it is staging and committing before
and after the model writes the Lore message. I also cleared the
workspace's existing clippy blockers so the verification lane can stay
fully green.
Constraint: Improve UX inside the existing Rust CLI surfaces without adding new dependencies
Rejected: Add more slash commands first | discoverability and feedback were the bigger friction points
Rejected: Split verification lint fixes into a second commit | user requested one solid commit
Confidence: high
Scope-risk: moderate
Directive: Keep slash discoverability, status reporting, and commit reporting aligned so `/help`, `/status`, and `/commit` tell the same workflow story
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace
Not-tested: Manual interactive REPL session against live Anthropic/xAI endpoints
The Rust API layer rejected thinking-enabled responses because it only recognized text and tool_use content blocks. This commit extends the response and SSE parser types to accept reasoning-style content blocks and deltas, with regression coverage for both non-streaming and streaming responses.
Constraint: Keep parsing compatible with existing text and tool-use message flows
Rejected: Deserialize unknown content blocks into an untyped catch-all | would weaken protocol coverage and test precision
Confidence: high
Scope-risk: narrow
Directive: Keep new protocol variants covered at the API boundary so downstream code can make explicit choices about preservation vs. ignoring
Tested: cargo test -p api thinking -- --nocapture
Not-tested: Live API traffic from a real thinking-enabled model
The Rust Agent tool only persisted queued metadata, so delegated work never actually ran. This change wires Agent into a detached background conversation path with isolated runtime, API client, session state, restricted tool subsets, and file-backed lifecycle/result updates.
Constraint: Keep the tool entrypoint in the tools crate and avoid copying the upstream TypeScript implementation
Rejected: Spawn an external claw process | less aligned with the requested in-process runtime/client design
Rejected: Leave execution in the CLI crate only | would keep tools::Agent as a metadata-only stub
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Tool subset mappings are curated guardrails; revisit them before enabling recursive Agent access or richer agent definitions
Tested: cargo build --release --manifest-path rust/Cargo.toml
Tested: cargo test --manifest-path rust/Cargo.toml
Not-tested: Live end-to-end background sub-agent run against Anthropic API credentials
The Rust Agent tool only persisted queued metadata, so delegated work never actually ran. This change wires Agent into a detached background conversation path with isolated runtime, API client, session state, restricted tool subsets, and file-backed lifecycle/result updates.
Constraint: Keep the tool entrypoint in the tools crate and avoid copying the upstream TypeScript implementation
Rejected: Spawn an external claw process | less aligned with the requested in-process runtime/client design
Rejected: Leave execution in the CLI crate only | would keep tools::Agent as a metadata-only stub
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Tool subset mappings are curated guardrails; revisit them before enabling recursive Agent access or richer agent definitions
Tested: cargo build --release --manifest-path rust/Cargo.toml
Tested: cargo test --manifest-path rust/Cargo.toml
Not-tested: Live end-to-end background sub-agent run against Anthropic API credentials
The REPL now wraps rustyline::Editor instead of maintaining a custom raw-mode
input stack. This preserves the existing LineEditor surface while delegating
history, completion, and interactive editing to a maintained library. The CLI
argument parser and /model command path also normalize shorthand model names to
our current canonical Anthropic identifiers.
Constraint: User requested rustyline 15 specifically for the CLI editor rewrite
Constraint: Existing LineEditor constructor and read_line API had to remain stable
Rejected: Keep extending the crossterm-based editor | custom key handling and history logic were redundant with rustyline
Rejected: Resolve aliases only for --model flags | /model would still diverge from CLI startup behavior
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep model alias normalization centralized in main.rs so CLI flag parsing and /model stay in sync
Tested: cargo check --workspace
Tested: cargo test --workspace
Tested: cargo build --workspace
Tested: cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Interactive manual terminal validation of Shift+Enter behavior across terminal emulators
The REPL now wraps rustyline::Editor instead of maintaining a custom raw-mode
input stack. This preserves the existing LineEditor surface while delegating
history, completion, and interactive editing to a maintained library. The CLI
argument parser and /model command path also normalize shorthand model names to
our current canonical Anthropic identifiers.
Constraint: User requested rustyline 15 specifically for the CLI editor rewrite
Constraint: Existing LineEditor constructor and read_line API had to remain stable
Rejected: Keep extending the crossterm-based editor | custom key handling and history logic were redundant with rustyline
Rejected: Resolve aliases only for --model flags | /model would still diverge from CLI startup behavior
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep model alias normalization centralized in main.rs so CLI flag parsing and /model stay in sync
Tested: cargo check --workspace
Tested: cargo test --workspace
Tested: cargo build --workspace
Tested: cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Interactive manual terminal validation of Shift+Enter behavior across terminal emulators
Extended thinking needed to travel end-to-end through the API,
runtime, and CLI so the client can request a thinking budget,
preserve streamed reasoning blocks, and present them in a
collapsed text-first form. The implementation keeps thinking
strictly opt-in, adds a session-local toggle, and reuses the
existing flag/slash-command/reporting surfaces instead of
introducing a new UI layer.
Constraint: Existing non-thinking text/tool flows had to remain backward compatible by default
Constraint: Terminal UX needed a lightweight collapsed representation rather than an interactive TUI widget
Rejected: Heuristic CLI-only parsing of reasoning text | brittle against structured stream payloads
Rejected: Expanded raw thinking output by default | too noisy for normal assistant responses
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep thinking blocks structurally separate from answer text unless the upstream API contract changes
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test -q
Not-tested: Live upstream thinking payloads against the production API contract
Extended thinking needed to travel end-to-end through the API,
runtime, and CLI so the client can request a thinking budget,
preserve streamed reasoning blocks, and present them in a
collapsed text-first form. The implementation keeps thinking
strictly opt-in, adds a session-local toggle, and reuses the
existing flag/slash-command/reporting surfaces instead of
introducing a new UI layer.
Constraint: Existing non-thinking text/tool flows had to remain backward compatible by default
Constraint: Terminal UX needed a lightweight collapsed representation rather than an interactive TUI widget
Rejected: Heuristic CLI-only parsing of reasoning text | brittle against structured stream payloads
Rejected: Expanded raw thinking output by default | too noisy for normal assistant responses
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep thinking blocks structurally separate from answer text unless the upstream API contract changes
Tested: cargo fmt --all; cargo clippy --workspace --all-targets -- -D warnings; cargo test -q
Not-tested: Live upstream thinking payloads against the production API contract