feat: session recovery toolset (orphan detector + /recover)
Reconstructs session logs from Claude Code transcripts when a session crashes or is closed before /save. Two entry points: - /recover <uuid|latest> : manual, Claude-reviewed reconstruction - detect_orphaned_sessions.py : scheduled scan that auto-builds logs for substantive, unsaved, not-yet-recovered transcripts (banner-marked RECOVERED-UNVERIFIED), commits them, and posts a #bot-alerts FYI. recover_session.py is the shared engine: Python extracts the verbatim command/config/reference timeline; Ollama drafts prose-only narrative. Machine-local ledger (.claude/state/) prevents reprocessing. Reviewed: git add scoped to own files, ledger written only after successful push, per-uuid idempotency, --max cap for unattended runs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
84
.claude/commands/recover.md
Normal file
84
.claude/commands/recover.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Reconstruct a session log from a Claude Code transcript when a session crashed or was closed before `/save`.
|
||||
|
||||
Claude Code writes every session live to a transcript JSONL under `~/.claude/projects/<slug>/<uuid>.jsonl`. `/recover` distills one of those transcripts back into a normal session log in the `.claude/commands/save.md` format. This is the **manual, reviewed** path; the background detector (`detect_orphaned_sessions.py`) handles unattended auto-recovery.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
| Invocation | Action |
|
||||
|---|---|
|
||||
| `/recover <uuid>` | Reconstruct the session with that transcript uuid |
|
||||
| `/recover latest` | Reconstruct the newest transcript by mtime |
|
||||
| `/recover --list` | Show candidate orphans (runs the detector `--dry-run`) |
|
||||
|
||||
---
|
||||
|
||||
## Flow: `/recover --list`
|
||||
|
||||
Run the detector in scan-only mode and present the table to the user:
|
||||
|
||||
```bash
|
||||
py .claude/scripts/detect_orphaned_sessions.py --dry-run
|
||||
```
|
||||
|
||||
The table shows every past-idle, not-yet-processed transcript with its uuid, mtime, `substantive`/`saved`/`orphan` verdicts, classified scope, and the path a recovery would write to. Point the user at the rows where `orphan` is `YES` — those are unsaved substantive sessions. Nothing is written.
|
||||
|
||||
---
|
||||
|
||||
## Flow: `/recover <uuid>` or `/recover latest`
|
||||
|
||||
This is a **reviewed** recovery. Claude is the editor, not a passive writer.
|
||||
|
||||
1. **Generate the draft** (prints to stdout, writes nothing):
|
||||
|
||||
```bash
|
||||
py .claude/scripts/recover_session.py --uuid <uuid> --print
|
||||
```
|
||||
|
||||
(or `--latest`). The draft contains:
|
||||
- Ollama-drafted prose: Session Summary, Key Decisions, Problems Encountered, Pending / Incomplete Tasks.
|
||||
- Python-extracted verbatim evidence: Configuration Changes, Commands & Outputs, Reference Information, Infrastructure & Servers, Credentials & Secrets.
|
||||
- A `[RECOVERED -- UNVERIFIED]` banner and the canonical User block (from `whoami-block.sh`).
|
||||
|
||||
2. **Review the draft.** This is the point of the manual path:
|
||||
- Verify the **Commands / Config / Reference** appendix matches what actually happened and what the user intended. These are machine-extracted verbatim — confirm they are complete and not misleading.
|
||||
- Correct the **scope and slug**: the classifier is conservative and may land on `general` (or the wrong project/client) when work spanned several areas. Fix the target `session-logs/` directory accordingly.
|
||||
- Tighten the **topic** in the filename and the title.
|
||||
- Correct or rewrite the **Ollama prose** where it is imprecise. If Ollama was unreachable, write the prose sections yourself from the verbatim evidence.
|
||||
|
||||
3. **Write the final log.** Once verified, write the corrected markdown to the correct `session-logs/` path (client -> `clients/<slug>/session-logs/`, project -> `projects/<project>/session-logs/`, general -> root `session-logs/`), using the transcript's first-timestamp date: `YYYY-MM-DD-recovered-<topic>.md`. **Drop the UNVERIFIED banner** — by writing it yourself you have verified it.
|
||||
|
||||
4. **Sync:**
|
||||
|
||||
```bash
|
||||
bash .claude/scripts/sync.sh
|
||||
```
|
||||
|
||||
5. **Unseeded wiki check.** If the scope is a client or project with no `wiki/<type>/<slug>.md` article yet, suggest:
|
||||
|
||||
```
|
||||
[INFO] No wiki article for '<slug>' yet. Run /wiki-compile <type>:<slug> to seed it.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Difference from the automatic detector
|
||||
|
||||
| | `/recover` (this command) | `detect_orphaned_sessions.py` (background) |
|
||||
|---|---|---|
|
||||
| Trigger | Manual, on demand | Scheduled task (every few hours + at logon) |
|
||||
| Review | Claude reviews and corrects before writing | None — auto-writes unreviewed |
|
||||
| Banner | Removed once verified | Kept (`[RECOVERED -- UNVERIFIED]`) until a human reviews |
|
||||
| Scope/topic | Corrected by Claude | Whatever the classifier decided |
|
||||
| Output | Final, clean session log | Banner-marked draft committed for later review |
|
||||
|
||||
Use `/recover` when you know a specific session was lost and want a clean log. Let the detector catch the ones you forget.
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- `--auto` and `--json` modes on `recover_session.py` exist for the detector and for scripting; `/recover` uses `--print` so Claude always reviews before anything lands on disk.
|
||||
- The prose is Ollama-drafted from the transcript; the Commands/Config/Reference sections are extracted verbatim by Python. Never trust the prose for exact commands, IPs, credentials, paths, SHAs, or ticket IDs — read those from the verbatim sections.
|
||||
- Transcripts are per-machine. You can only recover sessions that ran on the machine you are on.
|
||||
Reference in New Issue
Block a user