The CLI was using a flat cwd/.claw/sessions/ path without workspace
fingerprinting, while SessionStore::from_cwd() adds a hash subdirectory.
This mismatch meant the isolation machinery existed but wasn't actually
used by the main session management codepath.
Now sessions_dir() delegates to SessionStore::from_cwd(), ensuring all
session operations use workspace-fingerprinted directories.
Remove #[cfg(test)] gate from session_control module — SessionStore
is now available at runtime, not just in tests. Export SessionStore and
add workspace_sessions_dir() helper that creates fingerprinted session
directories per workspace root.
This is the #41 kill shot: parallel opencode serve instances will use
separate session namespaces based on workspace fingerprint instead of
sharing a global ~/.local/share/opencode/ store.
The CLI already uses cwd/.claw/sessions/ (sessions_dir()), and now
SessionStore::from_cwd() adds workspace hash isolation on top.
Global session store causes cross-worktree confusion in parallel lanes.
Added workspace_root field to session metadata and documented root cause
in ROADMAP.md.
Sterling reported 'json_error: no field input/input_tokens' still firing
despite existing serde(default) in types.rs. Root cause: SSE streaming
path had a separate deserialization site that didn't use the same defaults.
- Add serde(default) to sse.rs UsageEvent deserialization
- Add serde(default) to types.rs Usage struct fields (input_tokens, output_tokens)
- Add regression test with empty-usage JSON response in streaming context
The CLI already reframes direct preflight and provider oversized-request
errors, but retry-wrapped provider failures still fell back to the generic
retry-exhausted surface because the user-visible formatter keyed off the
safe failure class. Route formatting through nested context-window
detection so wrapped provider failures keep the same compact/reduce-scope
guidance.
Constraint: Keep the fix UX-scoped without widening broader failure classification behavior
Rejected: Reorder safe_failure_class for all RetriesExhausted errors | broader semantic change than needed for this issue
Confidence: high
Scope-risk: narrow
Directive: Keep context-window rendering keyed to nested error inspection so provider wrappers do not lose recovery guidance
Tested: cargo fmt --check; cargo test -p rusty-claude-cli context_window; cargo test -p api oversized
Not-tested: Full workspace test suite
Generic fatal wrapper handling already preserved safe classes and trace ids for single provider failures, but repeated retry exhaustion still surfaced as provider_internal. Classify generic wrapped RetriesExhausted failures as provider_retry_exhausted so Jobdori-style repeat failures stay distinguishable from one-off provider crashes, and keep the display logic clippy-clean.
Constraint: Keep the change minimal and preserve existing user-visible error wording outside retry-exhaustion classification
Rejected: Broadly rework all provider error taxonomy | unnecessary for the targeted opaque-wrapper regression
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep retry exhaustion distinct from single-shot provider_internal wrappers when the nested error is the same generic fatal wrapper
Tested: cargo test -p api detects_generic_fatal_wrapper_and_classifies_it_as_provider_internal
Tested: cargo test -p api retries_exhausted_preserves_nested_request_id_and_failure_class
Tested: cargo test -p rusty-claude-cli opaque_provider_wrapper_surfaces_failure_class_session_and_trace
Tested: cargo test -p rusty-claude-cli retry_exhaustion_uses_retry_failure_class_for_generic_provider_wrapper
Tested: cargo test --workspace
Tested: cargo fmt --check
Tested: cargo clippy --workspace --all-targets -- -D warnings
Not-tested: Live OpenClaw/Anthropic service failure telemetry outside the local test harness