Compaction: preserve tail sections when reserved suffix exceeds cap

When suffix.length >= maxChars, slice(0, maxChars) kept the head (preserved
turns) and dropped the tail (workspace rules, diagnostics). Use slice(-maxChars)
to preserve the critical tail instead.

Made-with: Cursor
This commit is contained in:
Pandadadadazxf 2026-03-14 08:40:38 +08:00 committed by Josh Lehman
parent 4cb14e17cd
commit 637d7b4728
No known key found for this signature in database
GPG Key ID: D141B425AC7F876B
2 changed files with 20 additions and 1 deletions

View File

@ -329,6 +329,24 @@ describe("compaction-safeguard summary budgets", () => {
expect(capped).toContain("None.\n\n## Tool Failures");
expect(capped).not.toMatch(/None\.## Tool Failures/);
});
it("preserves tail sections when suffix exceeds cap (workspace rules, diagnostics over preserved turns)", () => {
const criticalTail =
"\n\n## Tool Failures\n- exec: failed\n\n<read-files>\nfoo.ts\n</read-files>\n\n" +
"<workspace-critical-rules>\n## Session Startup\nRead AGENTS.md\n</workspace-critical-rules>";
const preservedTurns =
"## Recent turns preserved verbatim\n- User: x\n- Assistant: y\n" +
"x".repeat(MAX_COMPACTION_SUMMARY_CHARS);
const oversizedSuffix = preservedTurns + criticalTail;
const capped = capCompactionSummaryPreservingSuffix("short body", oversizedSuffix);
expect(capped.length).toBeLessThanOrEqual(MAX_COMPACTION_SUMMARY_CHARS);
expect(capped).toContain("<workspace-critical-rules>");
expect(capped).toContain("## Tool Failures");
expect(capped).toContain("<read-files>");
expect(capped).toContain("## Session Startup");
});
});
describe("computeAdaptiveChunkRatio", () => {

View File

@ -270,7 +270,8 @@ function capCompactionSummaryPreservingSuffix(
return capCompactionSummary(`${summaryBody}${suffix}`, maxChars);
}
if (suffix.length >= maxChars) {
return suffix.slice(0, maxChars);
// Preserve tail (workspace rules, diagnostics) over head (preserved turns).
return suffix.slice(-maxChars);
}
const bodyBudget = Math.max(0, maxChars - suffix.length);
const cappedBody = capCompactionSummary(summaryBody, bodyBudget);