Summary
A close/clear path that swaps in a fresh 0-message session and saves with status=Closed triggers save()'s shrink detection (messages.len() < persist_state.messages_len) and checkpoints a full snapshot — overwriting the real transcript snapshot with an empty stub and deleting the journal. The later .bak rotation then captures the already-wiped state, so both copies end up empty and --resume shows an empty session.
Hit this in production 2026-08-05 on a 12-hour session (686 messages, 1.5MB snapshot). Daemon log forensics:
10:55:06 SESSION_PERSISTENCE save_mode=append messages=686 snapshot_bytes=1,539,899
10:55:38 SESSION_PERSISTENCE save_mode=snapshot messages=0 snapshot_bytes=600 status=Closed <- wipe
10:55:41 SESSION_PERSISTENCE load_done messages=0 <- resume sees nothing
Fix (ready on my fork — PR creation appears restricted on this repo)
Branch: https://github.com/dwillitzer/jcode/tree/fix/session-pre-wipe-guard (single commit, cherry-picks cleanly onto origin/master)
checkpoint_snapshot() gains a guard_snapshot_shrink() pre-step: when the in-memory transcript is empty but the on-disk snapshot exceeds 4KB, snapshot + journal are first copied to timestamped .pre-wipe-<ts>.json.bak / .jsonl.bak siblings.
- Never blocks the save — legitimate compaction shrinks are unaffected (guard requires empty; metadata stubs are under threshold)
- Backup names avoid
*.json so session scanners don't surface phantoms
- Emits
SESSION_PERSISTENCE phase=pre_wipe_backup for observability; backup failure logs and proceeds (fail-open)
- Recovery:
cp session_X.pre-wipe-<ts>.json.bak session_X.json
Includes two regression tests (wipe path produces byte-identical restorable backup with full recovery round-trip; small/compaction checkpoints produce no backups).
Related fixes on the same fork, happy to PR any/all if you enable PRs or prefer patches:
| Branch |
What |
fix/swarm-schema-anyof |
Top-level anyOf in the swarm tool schema breaks strict providers (Anthropic API rejects it); flattened to a plain object schema |
fix/swarm-worker-provider-pin |
Swarm worker spawns drop the openai-compatible:<profile> prefix, so workers lose the auth profile and fail; pins the full prefix through spawn (with tests) |
feat/prompt-cache-override |
supports_prompt_cache config override so openai-compatible profiles fronting Anthropic models emit cache_control breakpoints (verified ~92% cached-token hit rate through a claude-family proxy) |
fix/mcp-tool-name-sanitize |
MCP tool names with characters outside [a-zA-Z0-9_-] are rejected by provider APIs; sanitizes at registration. Also prefers configured judge models over hardcoded defaults |
All branches are single-purpose, based on current master (02439b4), and cherry-pick cleanly. If you'd rather receive these differently (git bundles, mailed patches, enabling PRs), say the word.
Summary
A close/clear path that swaps in a fresh 0-message session and saves with
status=Closedtriggerssave()'s shrink detection (messages.len() < persist_state.messages_len) and checkpoints a full snapshot — overwriting the real transcript snapshot with an empty stub and deleting the journal. The later.bakrotation then captures the already-wiped state, so both copies end up empty and--resumeshows an empty session.Hit this in production 2026-08-05 on a 12-hour session (686 messages, 1.5MB snapshot). Daemon log forensics:
Fix (ready on my fork — PR creation appears restricted on this repo)
Branch: https://github.com/dwillitzer/jcode/tree/fix/session-pre-wipe-guard (single commit, cherry-picks cleanly onto
origin/master)checkpoint_snapshot()gains aguard_snapshot_shrink()pre-step: when the in-memory transcript is empty but the on-disk snapshot exceeds 4KB, snapshot + journal are first copied to timestamped.pre-wipe-<ts>.json.bak/.jsonl.baksiblings.*.jsonso session scanners don't surface phantomsSESSION_PERSISTENCE phase=pre_wipe_backupfor observability; backup failure logs and proceeds (fail-open)cp session_X.pre-wipe-<ts>.json.bak session_X.jsonIncludes two regression tests (wipe path produces byte-identical restorable backup with full recovery round-trip; small/compaction checkpoints produce no backups).
Related fixes on the same fork, happy to PR any/all if you enable PRs or prefer patches:
fix/swarm-schema-anyofanyOfin the swarm tool schema breaks strict providers (Anthropic API rejects it); flattened to a plain object schemafix/swarm-worker-provider-pinopenai-compatible:<profile>prefix, so workers lose the auth profile and fail; pins the full prefix through spawn (with tests)feat/prompt-cache-overridesupports_prompt_cacheconfig override so openai-compatible profiles fronting Anthropic models emitcache_controlbreakpoints (verified ~92% cached-token hit rate through a claude-family proxy)fix/mcp-tool-name-sanitize[a-zA-Z0-9_-]are rejected by provider APIs; sanitizes at registration. Also prefers configured judge models over hardcoded defaultsAll branches are single-purpose, based on current
master(02439b4), and cherry-pick cleanly. If you'd rather receive these differently (git bundles, mailed patches, enabling PRs), say the word.