Skip to content

fix(agent-runtime): never wipe chat history on compaction - #1176

Open
nordicnode wants to merge 1 commit into
CodebuffAI:mainfrom
nordicnode:oss/compaction-wipe-1166
Open

fix(agent-runtime): never wipe chat history on compaction#1176
nordicnode wants to merge 1 commit into
CodebuffAI:mainfrom
nordicnode:oss/compaction-wipe-1166

Conversation

@nordicnode

Copy link
Copy Markdown

Summary

Two verified paths could replace the model's entire context with nothing (issue #1166, from the "Model losing all chat history instead of compacting" reports):

  • /compact with an empty model response — the replacement summary was built from fullResponse without an emptiness check, and a silent empty stop yields no recovery chunk, so the whole history was replaced by a single message carrying nothing. Now the replacement only happens when the model actually produced a summary; otherwise the history is kept (the forced next step retries) and a warning is logged. On the new main this guard is already present (coupled trigger + empty/think-only guards) — this branch keeps it and adds the remaining mechanism below.
  • Summary identity by content — a user message quoting the summary markers matched isConversationSummary, so findLast picked the quote over the real summary and the real summary was neither re-parsed nor kept: every earlier turn vanished at the next compaction. Summaries are now stamped with a CONVERSATION_SUMMARY tag and recognized by provenance; a legacy fallback requires the full envelope (open+close tag, header, <historical_memory>) so pre-tag summaries still fold in. The context-pruner's inlined copy — which matched the bare tag alone, wiping memory on any message that merely mentioned the tag — gets the same treatment, closing the parity test's second deliberate divergence.

Regression tests for both mechanisms, including the exact steal shape (tag + header quote with no memory block) and the legacy-envelope case. The parity test now asserts BOTH implementations keep a tag-mentioning user message.

Validation

Re-run on the new main after the history rewrite:

  • bun test packages/agent-runtime/src/__tests__/compact-history.test.ts packages/agent-runtime/src/__tests__/context-pruner-parity.test.ts packages/agent-runtime/src/__tests__/main-prompt.test.ts — 55 pass, 0 fail

Fixes #1166


Replaces #1167 — auto-closed when the repo history was force-pushed (the original commits no longer exist in the new history). Rebased onto the new main per the maintainer's request; picking the review up here.

Two verified paths replaced the model's entire context with nothing:

1. /compact built its replacement summary from fullResponse without
   checking it was non-empty. A silent empty stop (finish part with a
   real reason, no content) yields no recovery chunk, so the whole
   history was replaced by a single message whose summary carried
   nothing — every earlier turn gone. Guard the replacement on
   fullResponse.trim() and keep the history (the forced next step
   retries the summary) when the model returned nothing.

2. Compaction identified its own summary by content: a user message
   containing <conversation_summary> and the header sentence. A user
   message quoting those markers (asking about this very mechanism,
   pasting a summary back) matched, findLast picked it over the real
   summary, and the real summary was then neither re-parsed nor kept —
   every earlier turn vanished at the next compaction. The inlined
   copy in the context-pruner matched the bare tag alone, so a message
   merely mentioning the tag wiped memory there too.

   Stamp summaries with a CONVERSATION_SUMMARY tag and recognize them
   by provenance; keep a legacy fallback requiring the full envelope
   (open+close tag, header, <historical_memory>) so pre-tag summaries
   still fold in. The pruner's tag-alone match — the parity test's
   deliberate divergence — closes: a bare tag mention no longer
   qualifies in either implementation.

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

Labels

None yet

1 participant