From b0d0231ebf8b32c6b1f429eb614fe2185e4d62f2 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 25 Sep 2026 11:34:23 +0000 Subject: [PATCH] fix(agent): include the compaction boundary message in the summary The kept tail starts at max_ctx-1, but the summary window stopped one message earlier, so that turn was deleted from the session and never summarized. Co-authored-by: esadrianno --- src/core/agent.c | 4 +++- tests/test_agent.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/core/agent.c b/src/core/agent.c index 92bc6f0..251a060 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -92,7 +92,9 @@ static int compact_session_via_llm(const char *session_id, char *session_buf, si if (root) cJSON_Delete(root); return -1; } - int to_summarize_n = msg_count - max_ctx; + /* Tail keeps max_ctx-1 messages, so the summary must include index + * msg_count-max_ctx. Stopping one short drops that turn from SQLite. */ + int to_summarize_n = msg_count - max_ctx + 1; char *source_buf = malloc(SUMMARY_SOURCE_MAX); if (!source_buf) { cJSON_Delete(root); return -1; } source_buf[0] = '\0'; diff --git a/tests/test_agent.c b/tests/test_agent.c index 4b3b7e6..6c7ce09 100644 --- a/tests/test_agent.c +++ b/tests/test_agent.c @@ -366,7 +366,14 @@ static int test_session_persisted_after_exchange(void) } static int compaction_call_count; -static int compaction_init(const config_t *cfg) { (void)cfg; compaction_call_count = 0; return 0; } +static int compaction_source_has_boundary; +static int compaction_init(const config_t *cfg) +{ + (void)cfg; + compaction_call_count = 0; + compaction_source_has_boundary = 0; + return 0; +} static int compaction_chat(const provider_message_t *messages, size_t message_count, const provider_tool_def_t *tools, size_t tool_count, provider_response_t *response) { @@ -377,6 +384,9 @@ static int compaction_chat(const provider_message_t *messages, size_t message_co response->tool_calls_count = 0; compaction_call_count++; if (compaction_call_count == 1) { + const char *src = (message_count >= 2 && messages[1].content) ? messages[1].content : ""; + /* msg_10 is the index the summary window and the kept tail both skipped. */ + compaction_source_has_boundary = strstr(src, "msg_10\n") != NULL; response->content = strdup("Summary of earlier conversation."); return 0; } @@ -442,6 +452,8 @@ static int test_context_compaction_when_history_exceeds_max(void) } if (!found_summary) goto cleanup; if (!found_tail) goto cleanup; + /* Boundary message must be in the summary source; the tail starts at msg_11. */ + if (!compaction_source_has_boundary) goto cleanup; failed = 0; cleanup: config_free(cfg);