diff --git a/devlog/2026-07-09_more-compression-candidates/REQ.md b/devlog/2026-07-09_more-compression-candidates/REQ.md new file mode 100644 index 0000000..68d60a9 --- /dev/null +++ b/devlog/2026-07-09_more-compression-candidates/REQ.md @@ -0,0 +1,50 @@ +# REQ: Increase max tool compression candidates from 5 to 15 + +## Background + +The context breakdown (shown when usage crosses the threshold) and the +tool-output reminder nudge both surface a list of "largest ranges" to the +model as compression candidates. + +Before this change: + +- `estimateContextComposition()` returned at most 10 message ranges and 5 + tool-output ranges. +- `injectCompressNudges()` sliced the top 5 from `largestRanges` when + building the tool-output reminder. + +Observation: the model was compressing too narrowly — frequently one +message per `compress` call — because only a handful of candidates were +visible at once. The compression philosophy in the system prompt asks the +model to cover "the largest range you can in a single call (aim for 20+ +messages)", but the candidate list did not back that up. + +## Requirement + +Surface more compression candidates so the model can pick larger ranges: + +1. `estimateContextComposition()`: + - `largestRanges`: 10 → **15** + - `largestToolRanges`: 5 → **15** +2. `injectCompressNudges()` tool-output reminder: + - `topRanges`: 5 → **15** + +Code and plain-text candidate lists (`largestCodeRanges`, +`largestMessageRanges`) stay at 5 — they are informational, not the +primary compression target. + +## Scope + +- `lib/messages/inject/utils.ts` (2 lines) +- `lib/messages/inject/inject.ts` (1 line) + +No config, no persisted-state, no prompt-template changes. + +## Why split from PR #80 + +This change was originally bundled into the `2026-07-09_summary-role-assistant` +branch (Bug 39: compression summary role). PR #80 is pending review and +cannot merge immediately, which blocks this independent improvement from +shipping. Splitting it into its own PR lets both move forward independently. + +issue #13 diff --git a/devlog/2026-07-09_more-compression-candidates/WORKLOG.md b/devlog/2026-07-09_more-compression-candidates/WORKLOG.md new file mode 100644 index 0000000..4228363 --- /dev/null +++ b/devlog/2026-07-09_more-compression-candidates/WORKLOG.md @@ -0,0 +1,32 @@ +# WORKLOG: more-compression-candidates + +## 2026-07-09 + +### Implementation + +Cherry-picked commit `ea7db98` from `2026-07-09_summary-role-assistant` +onto a fresh branch `2026-07-09_more-compression-candidates` based on +`master` (`b8fba7a`). + +Changes (3 lines across 2 files): + +- `lib/messages/inject/utils.ts:652` — `perMessage.slice(0, 10)` → + `slice(0, 15)` (`largestRanges`) +- `lib/messages/inject/utils.ts:653` — `perTool.slice(0, 5)` → + `slice(0, 15)` (`largestToolRanges`) +- `lib/messages/inject/inject.ts:214` — + `composition.largestRanges.slice(0, 5)` → `slice(0, 15)` + (`toolOutputReminder` top ranges) + +### Verification + +- `npm run typecheck` — clean +- `npm run build` — clean +- Tests — green on the source branch (no test changes in this slice) + +### Files + +- `lib/messages/inject/utils.ts` +- `lib/messages/inject/inject.ts` +- `devlog/2026-07-09_more-compression-candidates/REQ.md` +- `devlog/2026-07-09_more-compression-candidates/WORKLOG.md` diff --git a/lib/messages/inject/inject.ts b/lib/messages/inject/inject.ts index 67a83ab..75997c9 100644 --- a/lib/messages/inject/inject.ts +++ b/lib/messages/inject/inject.ts @@ -211,7 +211,7 @@ export const injectCompressNudges = ( const toolGrowth = composition.toolTokens - state.nudges.lastToolOutputNudgeTokens if (toolGrowth >= toolOutputThreshold) { const fmt = (n: number) => (n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n)) - const topRanges = composition.largestRanges.slice(0, 5).map((r) => `${r.ref} (${fmt(r.tokens)})`).join(", ") + const topRanges = composition.largestRanges.slice(0, 15).map((r) => `${r.ref} (${fmt(r.tokens)})`).join(", ") toolOutputReminder = `\n\n⚠️ ${fmt(toolGrowth)} new tool outputs accumulated (${fmt(composition.toolTokens)} total). Largest: ${topRanges}. Use compress tool to compress these ranges now.` state.nudges.lastToolOutputNudgeTokens = composition.toolTokens anchorsChanged = true diff --git a/lib/messages/inject/utils.ts b/lib/messages/inject/utils.ts index c8a5a5e..d28b124 100644 --- a/lib/messages/inject/utils.ts +++ b/lib/messages/inject/utils.ts @@ -649,8 +649,8 @@ export function estimateContextComposition( messageTokens, textTokens: Math.max(0, messageTokens - codeTokens), total: toolTokens + summaryTokens + messageTokens, - largestRanges: perMessage.slice(0, 10), - largestToolRanges: perTool.slice(0, 5), + largestRanges: perMessage.slice(0, 15), + largestToolRanges: perTool.slice(0, 15), largestCodeRanges: perCode.slice(0, 5), largestMessageRanges: perText.slice(0, 5), }