Skip to content

fix(claude): explain missing-transcript resume failures; add t3 session audit|reset - #52

Open
DanielGGordon wants to merge 1 commit into
mainfrom
t3code/fix-message-send-failure
Open

fix(claude): explain missing-transcript resume failures; add t3 session audit|reset#52
DanielGGordon wants to merge 1 commit into
mainfrom
t3code/fix-message-send-failure

Conversation

@DanielGGordon

Copy link
Copy Markdown
Owner

Problem

Sending in a Claude thread whose persisted resume cursor points at a transcript that no longer exists on this host failed with only "Claude runtime stream failed." The real cause — Claude Code's No conversation found with session ID: <id> — was emitted one event earlier and then overwritten by the generic stream-exit error, so the thread gave no hint at what was missing or how to recover. Found on prod thread 89de3af4… ("Second Brain Architecture Review"); an audit of the prod DB shows 72 non-deleted Claude threads (43 unarchived, mostly claude-import-* from another machine) in the same state.

Changes

Adapter (ClaudeAdapter.ts, claudeSessionTranscript.ts)

  • Recognise the CLI's missing-transcript result error and emit a runtime error that names the session id, the expected ~/.claude/projects/<encoded cwd>/<id>.jsonl path, and the two ways out (restore the file and resend, or t3 session reset <threadId>). Detail payload carries reason: "resume_transcript_missing".
  • Keep that explanation through the subsequent stream exit instead of replacing it with "Claude runtime stream failed."
  • The resume cursor is deliberately not cleared — the transcript may still be recoverable from the machine the conversation ran on.

CLI (cli/session.ts, shared cli/offlineRuntime.ts)

  • t3 session audit [--json] [--include-deleted] [--all] [--projects-dir] — lists every Claude thread whose transcript is missing (or relocated under a different project folder) with lifecycle, title, cwd, session id and the exact path to restore. Read-only.
  • t3 session reset <threadId> [--yes] — prints the current cursor (so it can be restored by hand) and only clears it with --yes.
  • Both run offline against the state DB and are safe while the server is serving (WAL; the server re-reads bindings on every session start). The offline runtime layer that was private to t3 import is now shared.

Docs: README feature bullet, AGENTS.md ops section.

Verification

  • tsgo --noEmit clean; vp lint clean; vp fmt --check clean.
  • New tests: claudeSessionTranscript.test.ts (encoding, error parsing, message), cli/session.test.ts (binding → target, lifecycle, row formatting), ClaudeAdapter.test.ts ("explains a resume whose transcript is missing and keeps that explanation on stream exit").
  • Full apps/server suite: 1777 passed; the single failure (server.test.ts > preserves structured workspace rpc failures) is pre-existing and fails identically on main.
  • Ran t3 session audit against the live prod DB: 137 Claude threads with cursors → 65 present, 0 relocated, 72 missing, ~4s. t3 session reset dry run verified to leave the row untouched; on a thread with no cursor it reports "nothing to reset".

🤖 Generated with Claude Code

…ion audit|reset`

Sending in a Claude thread whose persisted resume cursor points at a transcript
that no longer exists on this host (imported from another machine, host
reprovisioned) failed with the generic "Claude runtime stream failed." The
actual cause — the CLI's `No conversation found with session ID: <id>` — was
emitted one event earlier and then overwritten, so the thread gave no hint at
what was missing or how to recover.

Adapter: recognise the CLI's missing-transcript result, emit a runtime error
that names the session id and the expected `~/.claude/projects/<cwd>/<id>.jsonl`
path plus the two ways out (restore the file, or `t3 session reset`), and keep
that message through the subsequent stream exit instead of replacing it. The
resume cursor is deliberately left intact so the transcript can still be
restored from wherever the conversation ran.

CLI: `t3 session audit` lists every Claude thread whose transcript is missing
(or relocated) with the path to restore; `t3 session reset <threadId>` prints
the current cursor and, only with `--yes`, clears it so the thread starts a
fresh Claude session. Both run offline against the state DB and are safe while
the server is serving (WAL; bindings are re-read on every session start). The
offline CLI runtime layer previously private to `t3 import` is shared.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Aug 25, 2026
@DanielGGordon

DanielGGordon commented Aug 25, 2026

Copy link
Copy Markdown
Owner Author

Test deployment

This branch is running on test slot 7448 with a copy of the prod threads (so the stale-cursor threads are there to try).

Pairing link: https://15.204.108.12:7448/pair#token=9DHXVHVUCX8R
(one-time, short expiry — if it's stale, re-mint on the server with node scripts/test-status.ts --pair 7448)

To see the change: open a Claude thread whose transcript is missing (e.g. "Install Cursor CLI" or any claude-import-… thread for DanCode / gphotos-to-constant-contact) and send anything. Instead of "Claude runtime stream failed." the thread now shows which ~/.claude/projects/…/<session>.jsonl is missing and the two ways out (restore the file, or t3 session reset <threadId>).

CLI, from the worktree on the server:

node apps/server/src/bin.ts session audit            # read-only list of affected threads + paths to restore
node apps/server/src/bin.ts session reset <threadId> # dry run; add --yes to actually clear the cursor

Slot: external 7448 ⇄ loopback 3778.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant