Files
DeepSeek-TUI/docs/OPERATIONS_RUNBOOK.md
Hunter Bown 01df39d379 fix(session): engine adopts the host session id so fresh turns land in the resumed session (#5750)
* fix(session): engine adopts the host session id so fresh turns leave no orphan checkpoint

A fresh interactive launch claimed one session id in the App (per-session
Runtime store lock, turn-start crash checkpoint) while the engine minted a
second id in `Session::new`. `Op::SyncSession` only installed the App id
when the history was non-empty, so on the first turn the engine's
`SessionUpdated` re-keyed the App to the engine id, every later snapshot
and the completion commit used that id, and `checkpoints/<app id>.json`
(one user message, no reply) survived every completed turn. The next
`codewhale --continue` "recovered" that orphan instead of the real session,
promoted it to a permanent duplicate, and `codewhale sessions` filled with
one-message twins. After a kill -9 the same turn left two checkpoints.

Class fix at the boundary that resolves the session identity:

- `EngineConfig::session_id` — the interactive host passes
  `app.current_session_id` through `build_engine_config`, and `Engine::new`
  adopts it instead of a generated uuid (headless/exec/runtime-thread
  callers pass `None` and keep the generated id).
- `/clear` mints the next id in the App like `/new` already does, instead
  of handing the engine `session_id: None` and learning the id back from
  `SessionUpdated`.
- The `SessionUpdated` handler logs when the engine id ever diverges from
  the host id, so a future split is visible instead of silently re-keying
  persistence mid-session.

Related resume surfaces fixed alongside:

- `--continue` recovery is now `resolve_continue_session_id(workspace,
  interactive)`: a non-TTY `codewhale --continue` / `run --continue` no
  longer promotes and clears the crash checkpoint before failing the
  terminal check (the checkpoint stays for a real launch).
- Root `codewhale --resume <id>` / `-r` / `--session-id <id>` — advertised
  by docs/OPERATIONS_RUNBOOK.md — now exist on the dispatcher instead of
  being swallowed by the trailing prompt positional and forwarded as
  `--prompt "--resume <id>"` (clap exit 2). A startup prompt with `--resume`
  is rejected the same way `--continue` already is.

Regression tests (fail before, pass after):

- tui/ui/tests: `fresh_session_turn_lifecycle_leaves_no_orphan_checkpoint`
  walks turn-start checkpoint -> SessionUpdated -> completion commit
  against an isolated SessionManager and asserts zero checkpoints and one
  session file; `fresh_launch_engine_adopts_the_app_session_id`,
  `resumed_launch_keeps_the_loaded_session_id_for_the_engine`.
- core/engine/tests: `engine_adopts_host_owned_session_id_from_config`.
- lib.rs: `continue_without_interactive_terminal_leaves_checkpoint_for_a_real_launch`.
- cli: `parses_top_level_resume_flags_for_interactive_resume`,
  `top_level_resume_rejects_startup_prompt_and_conflicting_flags`.
- `/clear` unit test and the session-command cucumber step now assert the
  fresh App-owned id instead of `None`.

Signed-off-by: CodeWhale Bot <bot@codewhale.net>

* fix(cli): make ignored session flags loud, and lock the live-session test

Three review P2s. All three share a shape: the CLI accepted a session request
and then quietly did something else.

1. An empty resume id started a fresh session.

`codewhale --resume "$SESSION_ID"` with the variable unset gave Clap an empty
string, which trimmed to empty and was filtered to None. Nothing was forwarded,
so the user got a brand-new session while believing they had resumed one -- and
the mistake stayed invisible until the history they wanted was gone. It now
fails with a message that names the likely cause and points at --continue.

2. Root session flags were ignored when a subcommand was present.

--continue/--resume/--session-id only reach the TUI through the `command ==
None` branch; no subcommand handler reads them. `codewhale --resume abc exec
"..."` therefore started a fresh session that looked resumed. Rejected now,
with a pointer to the subcommand's own flag.

3. The store-level session test mutated process-global state unlocked.

`build_session_snapshot` calls `set_live_session`, which writes the global
LIVE_SESSIONS registry. The test did not take `lock_test_env` the way the
sibling live-session tests do, so it raced them under the default multi-thread
runner. That is a flake generator in a suite already fighting flakes.

  cargo nextest run -p codewhale-cli
  Summary [2.152s] 6 tests run: 6 passed (1 leaky), 305 skipped
    PASS tests::empty_resume_identifier_is_rejected_rather_than_starting_fresh

Signed-off-by: CodeWhale Bot <bot@codewhale.net>

---------

Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Co-authored-by: CodeWhale Bot <bot@codewhale.net>
2026-08-31 21:57:09 -07:00

3.7 KiB

codewhale Operations Runbook

This runbook covers practical debugging and incident response for the local CLI/TUI runtime.

Quick Triage

  1. Confirm binary + config:
    • cargo run -- --version
    • cat ~/.codewhale/config.toml (or inspect configured profile)
  2. Enable verbose logs:
    • RUST_LOG=codewhale_tui=debug cargo run
    • For HTTP retries/reconnects: RUST_LOG=codewhale_tui::client=debug cargo run
  3. Capture current state:
    • ls ~/.codewhale/sessions
    • ls ~/.codewhale/sessions/checkpoints
    • ls ~/.codewhale/tasks

Incident: Turn Hangs or Stream Stops

Symptoms:

  • TUI remains in loading state
  • partial assistant output with no completion

Checks:

  1. Inspect retry/health logs (codewhale_tui::client)
  2. Verify endpoint connectivity:
    • curl -sS https://api.deepseek.com/beta/models -H "Authorization: Bearer $DEEPSEEK_API_KEY"
  3. Confirm no local sandbox/permission deadlock in tool output

Actions:

  1. If a foreground shell command is running, press Ctrl+B to move it to the background (the turn keeps running and the command becomes a background job under /jobs); use Ctrl+C instead if you want to cancel the turn.
  2. If the command was started in the background, ask the assistant to use Bash with action: "cancel" and the returned process id.
  3. Use Esc or Ctrl+C to interrupt the current turn when you want to stop the request itself.
  4. Retry prompt; if still failing, restart TUI.
  5. On restart, verify the previous queued/in-flight runtime turn is shown as interrupted rather than left in a running state.

Incident: Network Outage / Offline Behavior

Expected behavior:

  • New prompts are queued while offline mode is active
  • Queue state persists to ~/.codewhale/sessions/checkpoints/offline_queue.json

Checks:

  1. Open queue in TUI: /queue list
  2. Confirm persisted queue file exists and updates timestamp

Actions:

  1. Restore connectivity
  2. Re-send queued entries (from /queue edit <n> + Enter, or normal input flow)
  3. Ensure queue file clears when queue is empty

Incident: Crash Recovery Needed

Expected behavior:

  • Checkpoint stored at ~/.codewhale/sessions/checkpoints/latest.json
  • Startup begins a fresh session unless --resume/--continue is supplied

Actions:

  1. Resume prior work explicitly via codewhale --resume <id> (alias codewhale resume <id>; codewhale --continue recovers the newest interrupted checkpoint for the workspace) or Ctrl+R in TUI
  2. If checkpoint inspection is needed, inspect latest.json for schema mismatch/details
  3. If schema is newer than binary supports, upgrade binary or remove stale checkpoint

Incident: Persistent State Schema Errors

Symptoms:

  • Errors like schema vX is newer than supported vY

Affected stores:

  • sessions (~/.codewhale/sessions/*.json)
  • runtime thread/turn/item records
  • tasks (~/.codewhale/tasks/tasks/*.json)

Actions:

  1. Confirm binary version and migration expectations
  2. Back up the state directory before editing
  3. Either:
    • run with a newer compatible binary, or
    • archive incompatible records and regenerate state

Incident: MCP/Tool Execution Failures

Checks:

  1. Validate ~/.codewhale/mcp.json schema and server command paths
  2. Confirm server process can start manually
  3. Check sandbox denials in TUI history / logs

Actions:

  1. Retry with required approvals (or YOLO only when appropriate)
  2. Temporarily disable failing MCP server and isolate issue
  3. Re-enable after verification with /mcp diagnostics

Post-Incident Checklist

  1. Preserve logs and relevant state files
  2. Record trigger, impact, and mitigation
  3. Add or update regression tests (retry/recovery/schema)
  4. Update this runbook and architecture docs if behavior changed