Keep the turns a repair cuts, and hand them back to the session
Truncating the transcript is the mechanical fix, but the turns being cut are the work itself. Losing the conversation that produced a morning's changes is most of the damage, and a session that resumes with a hole in its memory is barely resumed - it has no idea what it just did or what it was asked. So --apply now writes the dropped turns out as <session>.recovered-<stamp>.md, a readable record of what was asked, what was answered and what was run, and appends the same text back to the truncated transcript as a single note. Tool results are deliberately excluded: they are most of a transcript by volume and the least useful part of a summary. The note is a user entry marked isMeta - the marker Claude Code already uses for its own local-command caveats, meaning context rather than something to answer - and carries no message.id, so it cannot recreate the previous_message_id condition being repaired. Verified on the real corrupted transcript: 1921 lines in, 1813 kept plus the note, chained to the last good assistant uuid, no id on the message, and the file reads back as healthy. The generated digest recovers the actual instruction that was lost in the incident, which is the thing that made this worth doing. --no-reinject writes the markdown but leaves the session alone.
This commit is contained in:
@@ -339,8 +339,8 @@ API Error: 400 diagnostics.previous_message_id: must be the `id` from a
|
||||
prior /v1/messages response (starts with `msg_`)
|
||||
```
|
||||
|
||||
There is no supported way back from that. The only fix is to truncate the
|
||||
transcript to the last message Anthropic issued, losing every turn after it:
|
||||
There is no supported way back from that. The transcript has to be rolled back
|
||||
to the last message Anthropic issued:
|
||||
|
||||
```bash
|
||||
claude-mode repair-session # list transcripts here and their state
|
||||
@@ -348,8 +348,29 @@ claude-mode repair-session <session-id> # show what it would cut
|
||||
claude-mode repair-session <session-id> --apply
|
||||
```
|
||||
|
||||
It backs the original up first, and refuses to touch a transcript that was
|
||||
written to in the last 90 seconds, since that belongs to a session still alive.
|
||||
### The cut turns are not thrown away
|
||||
|
||||
Truncating is the mechanical fix, but the turns being cut are the work itself —
|
||||
losing the conversation that produced a morning's changes is most of the damage,
|
||||
and a session that resumes with a hole in its memory is barely resumed at all.
|
||||
So `--apply` does three things before it deletes anything:
|
||||
|
||||
1. **Backs up** the original as `<session>.jsonl.pre-repair-backup-<stamp>`.
|
||||
2. **Writes the dropped turns out** as `<session>.recovered-<stamp>.md` — a
|
||||
readable record of what was asked, what was answered, and what was run. Tool
|
||||
*results* are left out; they are most of a transcript by volume and the least
|
||||
useful part of a summary.
|
||||
3. **Hands them back to the session** as a single appended note, so the agent
|
||||
that resumes knows what it just did.
|
||||
|
||||
That note is a `user` entry marked `isMeta` — the same marker Claude Code uses
|
||||
for its own local-command caveats, meaning "context, not something to answer".
|
||||
Critically it carries **no `message.id`**, so it cannot re-create the very
|
||||
condition being repaired. `--no-reinject` writes the Markdown but leaves the
|
||||
session untouched.
|
||||
|
||||
It refuses to touch a transcript written to in the last 90 seconds, since that
|
||||
one belongs to a session still alive.
|
||||
|
||||
This is why a switch now asks before it writes rather than reporting afterwards.
|
||||
So restart affected sessions — and `claude-mode sessions --restart` will do it
|
||||
|
||||
Reference in New Issue
Block a user