T-437: fold the CLI 2.1.177 re-probe into scope + acceptance

The init-cache/routing-table refresh and sessions/ registry
characterization are now explicit deliverables of T-437, not a
separate follow-up, with updated acceptance criteria.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 13:31:55 +02:00
co-authored by Claude Opus 4.8
parent 8f962226a0
commit 708d4c6f95
2 changed files with 128 additions and 0 deletions
+81
View File
@@ -5123,3 +5123,84 @@ So `/clear` deletes the transcript and respawns with the *same deterministic* `-
**Files a fix would touch:** `claude_pane.dart` (`_clearSession` 651-659, `_respawnWithSession` 680-703, exit-status handler ~423), `session_naming.dart` (`claudeLaunchArgs` 75, `clearSessionTranscript` 109-114, id derivation 68), `session_orchestrator.dart` (`_spawn` 219-283, `close`), `slash_commands.dart` (routing).
**Related:** T-268 (done built the delete-transcript-then-reuse-`--session-id` mechanism that just regressed), T-156 (clide-owned `/clear`), T-161 (`--resume` vs `--session-id` selection), D-77 (stream-json session model), D-75 (version-pinned coupling to CC internals — the risk this realizes).', NULL, '2026-06-15 11:12:40', '2026-06-15 11:12:40', '2026-06-15 11:12:40', NULL, '8d437ab6db22ffa01ac237821bf446c5', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCNYXXH5AAHZR7WV0550J3RC', 'description', '**Symptom.** Typing `/clear` in the primary Claude pane kills the session: the pane shows `claude exited (code 1) — /clear to restart` and the "Warming up — your conversation will appear here." banner, instead of clearing to a fresh empty conversation. Screenshot taken in workspace `/var/mnt/data/projects/settled-reach`.
**Environment.** `claude` CLI **2.1.177** (`~/.local/bin/claude`). The codebase''s init-probe cache and the last probe task only cover **2.1.175** the CLI has moved past what clide last characterized. This is almost certainly a CLI-version regression, not a clide code change.
**`/clear` code path (read-only trace, 2026-06-15):**
- `lib/builtin/claude/src/slash_commands.dart:42` `clear` is in `kClideOwnedCommands`; clide handles it natively (T-156), does not forward it.
- `lib/builtin/claude/src/claude_pane.dart:651-659` `_clearSession()`: primary pane `_respawnWithSession(primarySessionId(root), clearTranscript: true)`.
- `claude_pane.dart:680-703` `_respawnWithSession()`: kills the old session (`activeSessionOrchestrator.close(_orchId)`), then `clearSessionTranscript(...)`, then `_spawn()`.
- `lib/builtin/claude/src/session_naming.dart:109-114` `clearSessionTranscript()` deletes ONLY `~/.claude/projects/<munged-root>/<id>.jsonl` and the sidecar `<id>/` dir.
- `session_naming.dart:75` respawn uses `claudeLaunchArgs(id, resume: false)` = `[''--session-id'', <id>]`, where `<id>` is the **same deterministic `primarySessionId(root)`** (derived from the repo path, `session_naming.dart:68`).
- `session_naming.dart:72-74` (the load-bearing comment): "`--session-id` REFUSES an id that already exists (''Session ID … is already in use'')."
**Root cause (strong hypothesis see caveat).** T-268 built `/clear` on the assumption that the per-project transcript file (`<id>.jsonl` + sidecar) is the *only* thing the CLI uses to decide whether a `--session-id` is "in use". The current CLI tracks session ids in **additional** state beyond that transcript:
- `~/.claude/sessions/<pid>.json` a live-session registry. Confirmed contents (2.1.177): `{"pid":,"sessionId":"e7dad3cf-…","cwd":"/var/mnt/data/projects/clide","version":"2.1.177","status":"idle",}`. Keyed by PID, carries the clide session UUID + cwd.
- `~/.claude/history.jsonl` (2.8 MB, append-only).
So `/clear` deletes the transcript and respawns with the *same deterministic* `--session-id`, but the killed session''s id is still registered (the registry entry is keyed by the now-dead PID and is the CLI''s own state — clide''s purge doesn''t touch it, and an abrupt kill leaves no chance for the CLI to clean it). The new `claude` rejects the id as already-in-use and **exits 1 at startup validation, before any model turn**. Reusing a fixed deterministic id is inherently brittle against the CLI adding new id-tracking surfaces.
**Caveat not yet pinned.** The actual `claude` stderr was NOT captured: the pane only surfaces `exited (code 1)`, swallowing the CLI''s error string. The above is inferred from (a) the documented `--session-id` refusal, (b) the confirmed new registry, (c) the version gap. It must be confirmed against the real stderr before the fix is chosen. **That clide shows an opaque "code 1" with no underlying reason is itself a defect** (see fix #3).
**Fix directions (ranked):**
1. **Stop reusing a fixed `--session-id` on clear.** Mint a fresh id (as secondary panes already do) and persist it as the pane''s *current* primary id, decoupling "current primary session" from the path-derived default so cross-restart continuity (T-268''s goal) survives without colliding. Robust against any CLI-internal id tracking — the right long-term fix and aligns with D-75 (avoid version-pinned coupling to CC internals).
2. **Make the old id reusable before respawn:** graceful-shutdown the old process (SIGTERM, give the CLI a chance to clean its `sessions/<pid>.json`) and/or sweep `~/.claude/sessions/*.json` for entries whose `sessionId == target` before reuse. Fragile — reaches into CLI private state; D-75 caution.
3. **Surface `claude`''s stderr/exit reason in the pane** (and logs) so "code 1" is never opaque again. Do this regardless of 1/2 it''s what makes this diagnosable.
**Also:** re-probe the CLI for 2.1.177 and refresh the init cache / the slash-command routing table (T-410/T-411 territory) the `~/.claude/sessions/` registry is new behavior worth characterizing; other session-lifecycle assumptions may have shifted too.
**Diagnostic step for the fixer:**
1. Reproduce `/clear` in a primary pane with CLI 2.1.177.
2. Capture the spawned `claude`''s stderr/stdout on the failed respawn (the `--session-id <id>` invocation). Confirm whether it is "Session ID … is already in use" vs another error.
3. Inspect `~/.claude/sessions/*.json` immediately after the kill — does an entry with the target `sessionId` linger?
**Files a fix would touch:** `claude_pane.dart` (`_clearSession` 651-659, `_respawnWithSession` 680-703, exit-status handler ~423), `session_naming.dart` (`claudeLaunchArgs` 75, `clearSessionTranscript` 109-114, id derivation 68), `session_orchestrator.dart` (`_spawn` 219-283, `close`), `slash_commands.dart` (routing).
**Related:** T-268 (done built the delete-transcript-then-reuse-`--session-id` mechanism that just regressed), T-156 (clide-owned `/clear`), T-161 (`--resume` vs `--session-id` selection), D-77 (stream-json session model), D-75 (version-pinned coupling to CC internals — the risk this realizes).', '**Symptom.** Typing `/clear` in the primary Claude pane kills the session: the pane shows `claude exited (code 1) — /clear to restart` and the "Warming up — your conversation will appear here." banner, instead of clearing to a fresh empty conversation. Screenshot taken in workspace `/var/mnt/data/projects/settled-reach`.
**Environment.** `claude` CLI **2.1.177** (`~/.local/bin/claude`). The codebase''s init-probe cache and the last probe task only cover **2.1.175** the CLI has moved past what clide last characterized. This is almost certainly a CLI-version regression, not a clide code change.
**`/clear` code path (read-only trace, 2026-06-15):**
- `lib/builtin/claude/src/slash_commands.dart:42` `clear` is in `kClideOwnedCommands`; clide handles it natively (T-156), does not forward it.
- `lib/builtin/claude/src/claude_pane.dart:651-659` `_clearSession()`: primary pane `_respawnWithSession(primarySessionId(root), clearTranscript: true)`.
- `claude_pane.dart:680-703` `_respawnWithSession()`: kills the old session (`activeSessionOrchestrator.close(_orchId)`), then `clearSessionTranscript(...)`, then `_spawn()`.
- `lib/builtin/claude/src/session_naming.dart:109-114` `clearSessionTranscript()` deletes ONLY `~/.claude/projects/<munged-root>/<id>.jsonl` and the sidecar `<id>/` dir.
- `session_naming.dart:75` respawn uses `claudeLaunchArgs(id, resume: false)` = `[''--session-id'', <id>]`, where `<id>` is the **same deterministic `primarySessionId(root)`** (derived from the repo path, `session_naming.dart:68`).
- `session_naming.dart:72-74` (the load-bearing comment): "`--session-id` REFUSES an id that already exists (''Session ID … is already in use'')."
**Root cause (strong hypothesis see caveat).** T-268 built `/clear` on the assumption that the per-project transcript file (`<id>.jsonl` + sidecar) is the *only* thing the CLI uses to decide whether a `--session-id` is "in use". The current CLI tracks session ids in **additional** state beyond that transcript:
- `~/.claude/sessions/<pid>.json` a live-session registry. Confirmed contents (2.1.177): `{"pid":,"sessionId":"e7dad3cf-…","cwd":"/var/mnt/data/projects/clide","version":"2.1.177","status":"idle",}`. Keyed by PID, carries the clide session UUID + cwd.
- `~/.claude/history.jsonl` (2.8 MB, append-only).
So `/clear` deletes the transcript and respawns with the *same deterministic* `--session-id`, but the killed session''s id is still registered (the registry entry is keyed by the now-dead PID and is the CLI''s own state — clide''s purge doesn''t touch it, and an abrupt kill leaves no chance for the CLI to clean it). The new `claude` rejects the id as already-in-use and **exits 1 at startup validation, before any model turn**. Reusing a fixed deterministic id is inherently brittle against the CLI adding new id-tracking surfaces.
**Caveat not yet pinned.** The actual `claude` stderr was NOT captured: the pane only surfaces `exited (code 1)`, swallowing the CLI''s error string. The above is inferred from (a) the documented `--session-id` refusal, (b) the confirmed new registry, (c) the version gap. It must be confirmed against the real stderr before the fix is chosen. **That clide shows an opaque "code 1" with no underlying reason is itself a defect** (see fix #3).
**Fix directions (ranked):**
1. **Stop reusing a fixed `--session-id` on clear.** Mint a fresh id (as secondary panes already do) and persist it as the pane''s *current* primary id, decoupling "current primary session" from the path-derived default so cross-restart continuity (T-268''s goal) survives without colliding. Robust against any CLI-internal id tracking — the right long-term fix and aligns with D-75 (avoid version-pinned coupling to CC internals).
2. **Make the old id reusable before respawn:** graceful-shutdown the old process (SIGTERM, give the CLI a chance to clean its `sessions/<pid>.json`) and/or sweep `~/.claude/sessions/*.json` for entries whose `sessionId == target` before reuse. Fragile — reaches into CLI private state; D-75 caution.
3. **Surface `claude`''s stderr/exit reason in the pane** (and logs) so "code 1" is never opaque again. Do this regardless of 1/2 it''s what makes this diagnosable.
**Also:** re-probe the CLI for 2.1.177 and refresh the init cache / the slash-command routing table (T-410/T-411 territory) the `~/.claude/sessions/` registry is new behavior worth characterizing; other session-lifecycle assumptions may have shifted too.
**Diagnostic step for the fixer:**
1. Reproduce `/clear` in a primary pane with CLI 2.1.177.
2. Capture the spawned `claude`''s stderr/stdout on the failed respawn (the `--session-id <id>` invocation). Confirm whether it is "Session ID … is already in use" vs another error.
3. Inspect `~/.claude/sessions/*.json` immediately after the kill — does an entry with the target `sessionId` linger?
**Files a fix would touch:** `claude_pane.dart` (`_clearSession` 651-659, `_respawnWithSession` 680-703, exit-status handler ~423), `session_naming.dart` (`claudeLaunchArgs` 75, `clearSessionTranscript` 109-114, id derivation 68), `session_orchestrator.dart` (`_spawn` 219-283, `close`), `slash_commands.dart` (routing).
**Related:** T-268 (done built the delete-transcript-then-reuse-`--session-id` mechanism that just regressed), T-156 (clide-owned `/clear`), T-161 (`--resume` vs `--session-id` selection), D-77 (stream-json session model), D-75 (version-pinned coupling to CC internals — the risk this realizes).
---
**Folded-in scope (2026-06-15): CLI 2.1.177 re-probe part of this ticket, not a follow-up.**
Beyond the `/clear` fix, T-437 also owns bringing clide''s CLI characterization up to the running version:
- Re-run the stream-json `initialize` probe against `claude` **2.1.177** and refresh the per-version init cache (`~/.config/clide/claude/init-<version>.json`, T-151). The codebase was last probed at 2.1.175 (probe task + `kClideOwnedCommands`/routing assumptions).
- Refresh the slash-command routing table (T-410/T-411) from the new probe: re-confirm advertised vs TUI-only vs owned for 2.1.177, so nothing regresses to a raw harness error.
- Characterize the new `~/.claude/sessions/<pid>.json` live-session registry (fields, lifecycle: when written, updated, removed esp. whether a killed PID''s entry is cleaned). This directly informs which `/clear` fix is viable.
- Audit other session-lifecycle assumptions that may have drifted with the registry addition (resume/fork id handling, `--session-id` vs `--resume` selection).
**Acceptance (updated):** `/clear` clears the primary pane to an empty conversation on CLI 2.1.177 without exiting; `claude` stderr/exit reason is surfaced in the pane + logs; init cache + routing table refreshed for 2.1.177; the `sessions/` registry lifecycle documented in this ticket (or a D-record if it changes a decision).', NULL, '2026-06-15 11:30:26', '2026-06-15 11:30:26', '2026-06-15 11:30:26', NULL, '2ab7f67318159b7b9a8b26eeefa2ed8d', 2) ON CONFLICT(hash) DO NOTHING;
+47
View File
@@ -5729,3 +5729,50 @@ So `/clear` deletes the transcript and respawns with the *same deterministic* `-
**Files a fix would touch:** `claude_pane.dart` (`_clearSession` 651-659, `_respawnWithSession` 680-703, exit-status handler ~423), `session_naming.dart` (`claudeLaunchArgs` 75, `clearSessionTranscript` 109-114, id derivation 68), `session_orchestrator.dart` (`_spawn` 219-283, `close`), `slash_commands.dart` (routing).
**Related:** T-268 (done built the delete-transcript-then-reuse-`--session-id` mechanism that just regressed), T-156 (clide-owned `/clear`), T-161 (`--resume` vs `--session-id` selection), D-77 (stream-json session model), D-75 (version-pinned coupling to CC internals — the risk this realizes).', 'backlog', 'high', NULL, NULL, 'D-77', '2026-06-15 11:12:36', '2026-06-15 11:12:40', NULL, '4a25498623ea06f378d4f55ef1135c0f', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCNYXXH5AAHZR7WV0550J3RC', 'bug', NULL, '/clear kills the Claude session (exit 1) — respawn reuses a --session-id the CLI still tracks (2.1.177 regression)', '**Symptom.** Typing `/clear` in the primary Claude pane kills the session: the pane shows `claude exited (code 1) — /clear to restart` and the "Warming up — your conversation will appear here." banner, instead of clearing to a fresh empty conversation. Screenshot taken in workspace `/var/mnt/data/projects/settled-reach`.
**Environment.** `claude` CLI **2.1.177** (`~/.local/bin/claude`). The codebase''s init-probe cache and the last probe task only cover **2.1.175** the CLI has moved past what clide last characterized. This is almost certainly a CLI-version regression, not a clide code change.
**`/clear` code path (read-only trace, 2026-06-15):**
- `lib/builtin/claude/src/slash_commands.dart:42` `clear` is in `kClideOwnedCommands`; clide handles it natively (T-156), does not forward it.
- `lib/builtin/claude/src/claude_pane.dart:651-659` `_clearSession()`: primary pane `_respawnWithSession(primarySessionId(root), clearTranscript: true)`.
- `claude_pane.dart:680-703` `_respawnWithSession()`: kills the old session (`activeSessionOrchestrator.close(_orchId)`), then `clearSessionTranscript(...)`, then `_spawn()`.
- `lib/builtin/claude/src/session_naming.dart:109-114` `clearSessionTranscript()` deletes ONLY `~/.claude/projects/<munged-root>/<id>.jsonl` and the sidecar `<id>/` dir.
- `session_naming.dart:75` respawn uses `claudeLaunchArgs(id, resume: false)` = `[''--session-id'', <id>]`, where `<id>` is the **same deterministic `primarySessionId(root)`** (derived from the repo path, `session_naming.dart:68`).
- `session_naming.dart:72-74` (the load-bearing comment): "`--session-id` REFUSES an id that already exists (''Session ID … is already in use'')."
**Root cause (strong hypothesis see caveat).** T-268 built `/clear` on the assumption that the per-project transcript file (`<id>.jsonl` + sidecar) is the *only* thing the CLI uses to decide whether a `--session-id` is "in use". The current CLI tracks session ids in **additional** state beyond that transcript:
- `~/.claude/sessions/<pid>.json` a live-session registry. Confirmed contents (2.1.177): `{"pid":,"sessionId":"e7dad3cf-…","cwd":"/var/mnt/data/projects/clide","version":"2.1.177","status":"idle",}`. Keyed by PID, carries the clide session UUID + cwd.
- `~/.claude/history.jsonl` (2.8 MB, append-only).
So `/clear` deletes the transcript and respawns with the *same deterministic* `--session-id`, but the killed session''s id is still registered (the registry entry is keyed by the now-dead PID and is the CLI''s own state — clide''s purge doesn''t touch it, and an abrupt kill leaves no chance for the CLI to clean it). The new `claude` rejects the id as already-in-use and **exits 1 at startup validation, before any model turn**. Reusing a fixed deterministic id is inherently brittle against the CLI adding new id-tracking surfaces.
**Caveat not yet pinned.** The actual `claude` stderr was NOT captured: the pane only surfaces `exited (code 1)`, swallowing the CLI''s error string. The above is inferred from (a) the documented `--session-id` refusal, (b) the confirmed new registry, (c) the version gap. It must be confirmed against the real stderr before the fix is chosen. **That clide shows an opaque "code 1" with no underlying reason is itself a defect** (see fix #3).
**Fix directions (ranked):**
1. **Stop reusing a fixed `--session-id` on clear.** Mint a fresh id (as secondary panes already do) and persist it as the pane''s *current* primary id, decoupling "current primary session" from the path-derived default so cross-restart continuity (T-268''s goal) survives without colliding. Robust against any CLI-internal id tracking — the right long-term fix and aligns with D-75 (avoid version-pinned coupling to CC internals).
2. **Make the old id reusable before respawn:** graceful-shutdown the old process (SIGTERM, give the CLI a chance to clean its `sessions/<pid>.json`) and/or sweep `~/.claude/sessions/*.json` for entries whose `sessionId == target` before reuse. Fragile — reaches into CLI private state; D-75 caution.
3. **Surface `claude`''s stderr/exit reason in the pane** (and logs) so "code 1" is never opaque again. Do this regardless of 1/2 it''s what makes this diagnosable.
**Also:** re-probe the CLI for 2.1.177 and refresh the init cache / the slash-command routing table (T-410/T-411 territory) the `~/.claude/sessions/` registry is new behavior worth characterizing; other session-lifecycle assumptions may have shifted too.
**Diagnostic step for the fixer:**
1. Reproduce `/clear` in a primary pane with CLI 2.1.177.
2. Capture the spawned `claude`''s stderr/stdout on the failed respawn (the `--session-id <id>` invocation). Confirm whether it is "Session ID … is already in use" vs another error.
3. Inspect `~/.claude/sessions/*.json` immediately after the kill — does an entry with the target `sessionId` linger?
**Files a fix would touch:** `claude_pane.dart` (`_clearSession` 651-659, `_respawnWithSession` 680-703, exit-status handler ~423), `session_naming.dart` (`claudeLaunchArgs` 75, `clearSessionTranscript` 109-114, id derivation 68), `session_orchestrator.dart` (`_spawn` 219-283, `close`), `slash_commands.dart` (routing).
**Related:** T-268 (done built the delete-transcript-then-reuse-`--session-id` mechanism that just regressed), T-156 (clide-owned `/clear`), T-161 (`--resume` vs `--session-id` selection), D-77 (stream-json session model), D-75 (version-pinned coupling to CC internals — the risk this realizes).
---
**Folded-in scope (2026-06-15): CLI 2.1.177 re-probe part of this ticket, not a follow-up.**
Beyond the `/clear` fix, T-437 also owns bringing clide''s CLI characterization up to the running version:
- Re-run the stream-json `initialize` probe against `claude` **2.1.177** and refresh the per-version init cache (`~/.config/clide/claude/init-<version>.json`, T-151). The codebase was last probed at 2.1.175 (probe task + `kClideOwnedCommands`/routing assumptions).
- Refresh the slash-command routing table (T-410/T-411) from the new probe: re-confirm advertised vs TUI-only vs owned for 2.1.177, so nothing regresses to a raw harness error.
- Characterize the new `~/.claude/sessions/<pid>.json` live-session registry (fields, lifecycle: when written, updated, removed esp. whether a killed PID''s entry is cleaned). This directly informs which `/clear` fix is viable.
- Audit other session-lifecycle assumptions that may have drifted with the registry addition (resume/fork id handling, `--session-id` vs `--resume` selection).
**Acceptance (updated):** `/clear` clears the primary pane to an empty conversation on CLI 2.1.177 without exiting; `claude` stderr/exit reason is surfaced in the pane + logs; init cache + routing table refreshed for 2.1.177; the `sessions/` registry lifecycle documented in this ticket (or a D-record if it changes a decision).', 'backlog', 'high', NULL, NULL, 'D-77', '2026-06-15 11:12:36', '2026-06-15 11:30:26', NULL, 'e07a8de1900862cd38a0193aca4846e4', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);