Skip to content

Commit 43eac4d

Browse files
committed
ROADMAP ultraworkers#113: /session switch/fork/delete unsupported from --resume; no claw session CLI subcommand; REPL-only programmatic gap
Dogfooded 2026-04-18 on main HEAD 8b25daf from /tmp/cdJJ. Test matrix: /session list → works (structured JSON) /session switch s → 'unsupported resumed slash command' /session fork foo → 'unsupported resumed slash command' /session delete s → 'unsupported resumed slash command' /session delete s --force → 'unsupported resumed slash command' claw session delete s → Prompt fallthrough (ultraworkers#108), 'missing credentials' from LLM error path Help documents ALL session verbs as one unified capability: /session [list|switch <session-id>|fork [branch-name]|delete <session-id> [--force]] Summary: 'List, switch, fork, or delete managed local sessions' Implementation: main.rs:10618 parser builds SlashCommand::Session{action, target} for every subverb. All parse successfully. main.rs:2908-2925 dedicated /session list handler. Only one. main.rs:2936-2940+ catch-all: SlashCommand::Session {..} | SlashCommand::Plugins {..} | ... => Err(format_unsupported_resumed_slash_command(...)) main.rs:3963 SlashCommand::Session IS handled in LiveCli REPL path — switch/fork/delete implemented for interactive mode. runtime/session_control.rs:131+ SessionStore::resolve_reference, delete_managed_session, fork_managed_session all exist. grep 'claw session\b' main.rs → zero matches. No CLI subcommand. Gap: backing code exists, parser understands verbs, REPL handler wired — ONLY the --resume dispatch path lacks switch/fork/delete plumbing, and there's no claw session CLI subcommand as programmatic alternative. A claw orchestrating session lifecycle at scale has three options: a) start interactive REPL (impossible without TTY) b) manual .claw/sessions/ rm/cp (bypasses bookkeeping, breaks with ultraworkers#112's proposed locking) c) stick to /session list + /clear, accept missing verbs Fix shape (~130 lines): - /session switch <id> in run_resume_command (~25 lines) - /session fork [branch] in run_resume_command (~30 lines) - /session delete <id> [--force] in run_resume_command (~30), --force required without TTY - claw session <verb> CLI subcommand (~40) - --help: annotate which session verbs are resume-safe vs REPL-only - regression tests per verb x (CLI / slash-via-resume) Joins Unplumbed-subsystem (ultraworkers#78, ultraworkers#96, ultraworkers#100, ultraworkers#102, ultraworkers#103, ultraworkers#107, ultraworkers#109, ultraworkers#111) as 9th declared-but-not-delivered surface. Joins Session- handling (ultraworkers#93, ultraworkers#112) as 3rd member. Cross-cluster with Silent- flag on help-vs-impl mismatch. Natural bundles: ultraworkers#93 + ultraworkers#112 + ultraworkers#113 — session-handling triangle (semantic / concurrency / management API) ultraworkers#78 + ultraworkers#111 + ultraworkers#113 — declared-but-not-delivered triangle with three flavors: ultraworkers#78 fails-noisy (CLI variant → Prompt fallthrough) ultraworkers#111 fails-quiet (slash → wrong handler) ultraworkers#113 no-handler-at-all (slash → unsupported-resumed) Filed in response to Clawhip pinpoint nudge 1494887723818029156 in #clawcode-building-in-public.
1 parent 8b25daf commit 43eac4d

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

ROADMAP.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,3 +3335,75 @@ ear], /color [scheme], /effort [low|medium|high], /fast, /summary, /tag [label],
33353335
**Blocker.** None. Advisory locking is a well-worn pattern; `fs2` crate is already in the Rust ecosystem. Domain error mapping is additive. The architectural decision is whether to serialize at the save boundary (simpler, some perf cost) or implement a full MVCC-style session store (far more work, out of scope).
33363336
33373337
**Source.** Jobdori dogfood 2026-04-18 against `/tmp/cdII` on main HEAD `a049bd2` in response to Clawhip pinpoint nudge at `1494880177099116586`. Joins **truth-audit / diagnostic-integrity** (#80–#87, #89, #100, #102, #103, #105, #107, #109, #110) — the error message lies about what actually happened (file vanished via concurrent rename, not intrinsic absence). Joins **Session handling** as a new micro-cluster (only existing member was #93 — reference-resolution semantics). Natural bundle: **#93 + #112** — session semantic correctness (reference resolution + concurrent-modification error clarity). Adjacent to **#104** (two-paths-diverge export) on the session-file-handling axis: #104 says the two export paths disagree on filename; #112 says concurrent session-file writers race with no advisory lock. Together session-handling has filename-semantic + concurrency gaps that the test suite should cover. Session tally: ROADMAP #112.
3338+
3339+
113. **`/session switch`, `/session fork`, and `/session delete` are registered by the parser (produce `SlashCommand::Session { action, target }`), documented in `--help` as first-class session-management verbs, but dispatch in `run_resume_command` implements ONLY `/session list` with a dedicated handler at `main.rs:2908` — every other `Session { .. }` variant falls through to the "unsupported resumed slash command" bucket at `main.rs:2936`. There is also no `claw session <verb>` CLI subcommand: `claw session delete s` falls through to Prompt dispatch per #108. Net effect: claws can enumerate sessions via `/session list`, but CANNOT programmatically switch, fork, or delete — those are REPL-interactive only, with no `--output-format json`-compatible alternative and no `claw session ...` CLI equivalent. Help advertises the capability universally; implementation surfaces it only in the REPL** — dogfooded 2026-04-18 on main HEAD `8b25daf` from `/tmp/cdJJ`. Full test matrix: `/session list` works from `--resume` (returns structured JSON), `/session switch s` / `/session fork foo` / `/session delete s` / `/session delete s --force` all return `{"type":"error","error":"unsupported resumed slash command"}`.
3340+
3341+
**Concrete repro.**
3342+
```
3343+
$ cd /tmp/cdJJ && git init -q .
3344+
$ # ... set up session at .claw/sessions/<bucket>/s.jsonl ...
3345+
3346+
$ for cmd in "list" "switch s" "fork foo" "delete s" "delete s --force"; do
3347+
> result=$(claw --resume s --output-format json /session $cmd 2>&1 | head -c 100)
3348+
> echo "/session $cmd → $result"
3349+
> done
3350+
/session list → {"kind":"session_list","sessions":["s"],"active":"s"}
3351+
/session switch s → {"type":"error","error":"unsupported resumed slash command",...}
3352+
/session fork foo → {"type":"error","error":"unsupported resumed slash command",...}
3353+
/session delete s → {"type":"error","error":"unsupported resumed slash command",...}
3354+
/session delete s --force → {"type":"error","error":"unsupported resumed slash command",...}
3355+
3356+
# No CLI subcommand either — falls through per #108:
3357+
$ claw session delete s
3358+
error: missing Anthropic credentials ... # Prompt-fallthrough, not session handler
3359+
3360+
# Help documents all session verbs as if they are universally available:
3361+
$ claw --help | grep /session
3362+
/session [list|switch <session-id>|fork [branch-name]|delete <session-id> [--force]]
3363+
List, switch, fork, or delete managed local sessions
3364+
# "List, switch, fork, or delete" — three of four are REPL-only.
3365+
```
3366+
3367+
**Trace path.**
3368+
- `rust/crates/rusty-claude-cli/src/main.rs:10618` — parser builds `SlashCommand::Session { action, target }` for every subverb. All variants parse successfully.
3369+
- `rust/crates/rusty-claude-cli/src/main.rs:2908-2925` — dedicated `/session list` handler:
3370+
```rust
3371+
SlashCommand::Session { action: Some(ref act), .. } if act == "list" => {
3372+
let sessions = list_managed_sessions().unwrap_or_default();
3373+
// ... returns structured JSON with sessions[] and active ...
3374+
}
3375+
```
3376+
Only `list` is implemented.
3377+
- `rust/crates/rusty-claude-cli/src/main.rs:2936-2940+` — catch-all:
3378+
```rust
3379+
SlashCommand::Session { .. }
3380+
| SlashCommand::Plugins { .. }
3381+
// ... many other variants ...
3382+
=> Err(format_unsupported_resumed_slash_command(...)),
3383+
```
3384+
`switch` / `fork` / `delete` (and their arguments) are all lumped into this bucket.
3385+
- `rust/crates/rusty-claude-cli/src/main.rs:3963` — `SlashCommand::Session { action, target }` is HANDLED in the `LiveCli::handle_repl_command` path (REPL mode). Interactive-only implementations exist for `switch` / `fork` / `delete` — they just never made it into the `--resume` dispatch.
3386+
- `rust/crates/runtime/src/session_control.rs:131+` — `SessionStore::resolve_reference`, `delete_managed_session`, `fork_managed_session` are all implemented at the runtime level. The backing code exists. The `--resume` flow simply does not call it for anything except `list`.
3387+
- `grep -rn "claw session\b" rust/crates/rusty-claude-cli/src/main.rs` — zero matches. There is no top-level `claw session` subcommand. `claw session <verb>` falls through to the Prompt dispatch arm (#108).
3388+
3389+
**Why this is specifically a clawability gap.**
3390+
1. *Declared universally, delivered partially.* `--help` shows all four verbs as one unified capability. Help is the only place a claw discovers what's possible. The help line is technically true for the REPL but misleading for automated / `--output-format json` consumers.
3391+
2. *No programmatic alternative.* There is no `claw session switch s` / `claw session fork foo` / `claw session delete s` CLI subcommand. A claw orchestrating session lifecycle at scale has three options: (a) start an interactive REPL (impossible without a TTY), (b) manually touch `.claw/sessions/` with `rm` / `cp` (bypasses claw's internal bookkeeping), (c) stick to `/session list` + `/clear` and accept the missing verbs.
3392+
3. *Runtime implementation is already there.* `SessionStore::delete_managed_session`, `SessionStore::fork_managed_session`, `SessionStore::resolve_reference` all exist in `session_control.rs`. The CLI just doesn't call them from the `--resume` dispatch path. Pure plumbing gap — parallel to #78 (plugins CLI route never wired) and #111 (providers slash dispatches to wrong handler).
3393+
4. *Joins the declared-but-not-as-declared cluster* (#78, #96, #111) — session verbs are registered and parsed but three of four are un-dispatchable from machine-readable surfaces. Different flavor than #78 (wrong fallthrough) or #111 (wrong handler); this is "no handler registered at all for the resume dispatch path."
3394+
5. *REPL is not accessible to claws.* A claw running `claw` without a TTY (CI, background task, another claw's subprocess) gets the REPL startup banner and immediately exits (or hangs on stdin). There is no automated way to invoke the REPL-only verbs.
3395+
6. *Manual filesystem fallback breaks session bookkeeping.* A claw that `rm`s a `.jsonl` file directly bypasses any hypothetical future cleanup-of-rotated-logs, bucket-lock release (per #112's proposed locking), or managed-session index updates. The forward-looking fix for #112 (advisory locks) would make manual `rm` even more fragile.
3396+
3397+
**Fix shape — implement the missing verbs in `run_resume_command` + add a `claw session <verb>` CLI subcommand.**
3398+
1. *Implement `/session switch <id>` in `run_resume_command`.* Call `SessionStore::resolve_reference(id)` + load + validate workspace + return new `ResumeCommandOutcome` with `{kind: "session_switched", from: ..., to: ...}`. ~25 lines.
3399+
2. *Implement `/session fork [branch-name]`.* Call `SessionStore::fork_managed_session` + return `{kind: "session_fork", parent_id, new_id, branch_name}`. ~30 lines.
3400+
3. *Implement `/session delete <id> [--force]`.* Call `SessionStore::delete_managed_session` (honoring `--force` to skip confirmation). Return `{kind: "session_deleted", deleted_id, backup_path?}`. ~30 lines. `--force` is required without a TTY since confirmation stdin prompts are non-answerable.
3401+
4. *Add `claw session <verb>` CLI subcommand.* Parse at `parse_args` before the Prompt fallthrough. Route to the same handlers. Provides a cleaner entry point than slash-via-`--resume`. ~40 lines.
3402+
5. *Update help to document what works from --resume vs REPL-only.* Currently the slash-command docs don't annotate which verbs are resume-compatible. Add `[resume-safe]` markers per subverb. ~5 lines.
3403+
6. *Regression tests.* One per verb × (CLI subcommand / slash-via-resume). Validate structured JSON output shape. Assert `/session delete s` without `--force` in non-TTY returns a structured `confirmation_required` error rather than blocking on stdin.
3404+
3405+
**Acceptance.** `claw --resume s --output-format json /session delete old-id --force` exits with `{kind: "session_deleted", ...}` instead of "unsupported resumed slash command." `claw session fork <id> feature-branch` works as a top-level CLI subcommand. `claw --help` clearly annotates which session verbs are programmatically accessible vs REPL-only. Zero "REPL-only" features are advertised as universally available without that marker.
3406+
3407+
**Blocker.** None. Backing `SessionStore` methods all exist (`delete_managed_session`, `fork_managed_session`, `resolve_reference`). This is dispatch-plumbing + CLI-parser wiring. Total ~130 lines + tests.
3408+
3409+
**Source.** Jobdori dogfood 2026-04-18 against `/tmp/cdJJ` on main HEAD `8b25daf` in response to Clawhip pinpoint nudge at `1494887723818029156`. Joins **Unplumbed-subsystem / declared-but-not-delivered** (#78, #96, #100, #102, #103, #107, #109, #111) as the ninth surface where spec advertises capability the implementation doesn't deliver on the machine-readable path. Joins **Session-handling** (#93, #112) — with #113, this cluster now covers reference-resolution semantics + concurrent-modification + programmatic management gap. Cross-cluster with **Silent-flag / documented-but-unenforced** (#96–#101, #104, #108, #111) on the help-vs-implementation-mismatch axis. Natural bundle: **#93 + #112 + #113** — session-handling triangle covering every axis (semantic / concurrency / management API). Also **#78 + #111 + #113** — declared-but-not-delivered triangle showing three distinct flavors: #78 fails-noisy (CLI variant → Prompt fallthrough), #111 fails-quiet (slash → wrong handler), **#113** no-handler-at-all (slash → unsupported-resumed error). Session tally: ROADMAP #113.

0 commit comments

Comments
 (0)