Skip to content

fix: preserve LCM history across session rotation#396

Merged
jalehman merged 2 commits into
mainfrom
josh/fix-session-rotation-history
Apr 11, 2026
Merged

fix: preserve LCM history across session rotation#396
jalehman merged 2 commits into
mainfrom
josh/fix-session-rotation-history

Conversation

@jalehman

@jalehman jalehman commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

What

This PR fixes two regressions in LCM bootstrap handling when a session JSONL file rotates. It preserves the full rotated transcript for existing conversations and removes the automatic purge path so session-file changes no longer delete persisted history.

Why

Production logs and DB inspection showed that session-file rotation was deleting messages and summaries from stable conversations, which broke incremental compaction, confused /compact, and violated the lossless contract. Existing data surgery is separate, but future rotations need to stop causing data loss.

Changes

  • Replay full rotated transcript for existing sessions
  • Remove purge-on-rotation bootstrap path
  • Preserve summaries, lineage, and context items
  • Add regression coverage for non-destructive rotation handling
  • Assert rotation imports only missing tail messages

Testing

  • npx vitest run test/engine.test.ts -t "rotation|bootstrapMaxTokens|reconciles missing tail messages|conversation already has messages"
  • npx vitest run test/engine.test.ts
  • Expected: rotation bootstrap tests pass and full engine test file stays green

Session-file rotation was purging the existing conversation and then reseeding it through the normal first-bootstrap cap. That left only a small suffix of the rotated transcript in LCM, which in turn made assembly fall back to live context while incremental compaction and manual compaction still evaluated the truncated persisted state.

Treat rotation reseeds as full transcript replacements instead of first-time bootstraps so LCM keeps coverage parity with the live session. Add a regression test that uses a tiny bootstrapMaxTokens value and verifies a rotated transcript is replayed in full.

Regeneration-Prompt: |
  User reported that a live lossless-claw session showed enormous actual context usage, but incremental compaction and /compact both believed the conversation was comfortably under target. Logs showed the session repeatedly falling back to live context while compaction decisions reported rawTokensOutsideTail=0.

  Trace the mismatch through bootstrap, assemble, and compaction. The key production clue is a session-file rotation event followed by an initial import that only reloaded a tiny suffix of a much larger rotated transcript. Preserve the intended first-bootstrap cap for genuinely new conversations, but do not reapply that cap when a known conversation is being reseeded after session-file rotation. In that case, replay the full rotated transcript so persisted LCM coverage matches the live session again. Add a focused regression test that would fail if rotation reseeds were trimmed by bootstrapMaxTokens.
Remove the automatic bootstrap purge path that deleted persisted conversation data whenever the session file path changed. Rotation now only invalidates the stored bootstrap checkpoint and reconciles forward from the existing conversation state, preserving messages, summaries, lineage, and context items.

Update the rotation regression tests to assert that existing conversation state survives file changes and that only the missing tail messages are imported after rotation.

Regeneration-Prompt: |
  Lossless Claw should never delete persisted conversation history just because
  the backing session JSONL file path changes. We already traced a production
  data-loss incident to the rotation handling added in PR #366: on file-path
  mismatch, bootstrap hard-deleted messages, summaries, context items, lineage,
  and telemetry, then rebuilt from the new file. The earlier fix kept the full
  rotated transcript during reseed, but that still left an automatic destructive
  purge in the code, which violates the product contract that lossless is
  lossless unless the user explicitly invokes a destructive command.

  Remove the purge-on-rotation behavior entirely while keeping rotation
  detection/logging. Treat a rotated file as another transcript source for the
  same conversation: invalidate the old bootstrap checkpoint and reconcile from
  the persisted conversation state so only genuinely missing tail messages are
  imported. Preserve existing summaries and context items. Update regression
  tests to prove that file rotation does not wipe conversation history and does
  not reapply the first-bootstrap budget cap to an existing conversation.
@jalehman jalehman merged commit ae60ef7 into main Apr 11, 2026
2 checks passed
@jalehman jalehman deleted the josh/fix-session-rotation-history branch April 11, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant