From 41b9afb3f897417e5dd041fa58229cc79c677c14 Mon Sep 17 00:00:00 2001 From: tobwen <1864057+tobwen@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:56:28 +0100 Subject: [PATCH 1/5] feat: add percentage support for contextLimit configuration Allow contextLimit to accept percentage strings (e.g. "40%") to specify a percentage of the model's context window instead of fixed values. Values are rounded and clamped between 0 and 100. --- dcp.schema.json | 6 +++++- lib/config.ts | 15 +++++++++------ lib/messages/inject.ts | 31 +++++++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/dcp.schema.json b/dcp.schema.json index 28019dd0..080d5863 100644 --- a/dcp.schema.json +++ b/dcp.schema.json @@ -110,7 +110,7 @@ "description": "Tool names that should be protected from automatic pruning" }, "contextLimit": { - "description": "When session tokens exceed this limit, a compress nudge is injected (\"model\" uses the active model's context limit)", + "description": "When session tokens exceed this limit, a compress nudge is injected (\"model\" uses the active model's context limit, \"X%\" uses percentage of the model's context window)", "default": 100000, "oneOf": [ { @@ -119,6 +119,10 @@ { "type": "string", "enum": ["model"] + }, + { + "type": "string", + "pattern": "^\\d+(?:\\.\\d+)?%$" } ] } diff --git a/lib/config.ts b/lib/config.ts index e2e6da61..5e2fa563 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -27,7 +27,7 @@ export interface ToolSettings { nudgeEnabled: boolean nudgeFrequency: number protectedTools: string[] - contextLimit: number | "model" + contextLimit: number | "model" | `${number}%` } export interface Tools { @@ -290,13 +290,16 @@ function validateConfigTypes(config: Record): ValidationError[] { }) } if (tools.settings.contextLimit !== undefined) { - if ( - typeof tools.settings.contextLimit !== "number" && - tools.settings.contextLimit !== "model" - ) { + const isValidNumber = typeof tools.settings.contextLimit === "number" + const isModelString = tools.settings.contextLimit === "model" + const isPercentString = + typeof tools.settings.contextLimit === "string" && + tools.settings.contextLimit.endsWith("%") + + if (!isValidNumber && !isModelString && !isPercentString) { errors.push({ key: "tools.settings.contextLimit", - expected: 'number | "model"', + expected: 'number | "model" | "${number}%"', actual: JSON.stringify(tools.settings.contextLimit), }) } diff --git a/lib/messages/inject.ts b/lib/messages/inject.ts index f1b56025..8a989f3e 100644 --- a/lib/messages/inject.ts +++ b/lib/messages/inject.ts @@ -13,6 +13,20 @@ import { getFilePathsFromParameters, isProtected } from "../protected-file-patte import { getLastUserMessage, isMessageCompacted } from "../shared-utils" import { getCurrentTokenUsage } from "../strategies/utils" +function parsePercentageString(value: string, total: number): number | undefined { + if (!value.endsWith("%")) return undefined + const percent = parseFloat(value.slice(0, -1)) + + if (isNaN(percent)) { + return undefined + } + + const roundedPercent = Math.round(percent) + const clampedPercent = Math.max(0, Math.min(100, roundedPercent)) + + return Math.round((clampedPercent / 100) * total) +} + // XML wrappers export const wrapPrunableTools = (content: string): string => { return ` @@ -54,9 +68,22 @@ Context management was just performed. Do NOT use the ${toolName} again. A fresh const resolveContextLimit = (config: PluginConfig, state: SessionState): number | undefined => { const configLimit = config.tools.settings.contextLimit - if (configLimit === "model") { - return state.modelContextLimit + + if (typeof configLimit === "string") { + if (configLimit.endsWith("%")) { + if (state.modelContextLimit === undefined) { + return undefined + } + return parsePercentageString(configLimit, state.modelContextLimit) + } + + if (configLimit === "model") { + return state.modelContextLimit + } + + return undefined } + return configLimit } From 40592b00705914f1b538383b9ec1c66e59747e62 Mon Sep 17 00:00:00 2001 From: Spoon <212802214+spoons-and-mirrors@users.noreply.github.com> Date: Fri, 6 Feb 2026 16:57:34 +0100 Subject: [PATCH 2/5] prompt: prune one word change --- lib/prompts/prune.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prompts/prune.md b/lib/prompts/prune.md index be18b009..97c239f4 100644 --- a/lib/prompts/prune.md +++ b/lib/prompts/prune.md @@ -4,7 +4,7 @@ THE PRUNABLE TOOLS LIST A `` section surfaces in context showing outputs eligible for removal. Each line reads `ID: tool, parameter (~token usage)` (e.g., `20: read, /path/to/file.ts (~1500 tokens)`). Reference outputs by their numeric ID - these are your ONLY valid targets for pruning. THE WAYS OF PRUNE -`prune` is surgical excision - eliminating noise (irrelevant or unhelpful outputs), superseded information (older outputs replaced by newer data), or wrong targets (you accessed something that turned out to be irrelevant). Use it to keep your context lean and focused. +`prune` is surgical deletion - eliminating noise (irrelevant or unhelpful outputs), superseded information (older outputs replaced by newer data), or wrong targets (you accessed something that turned out to be irrelevant). Use it to keep your context lean and focused. BATCH WISELY! Pruning is most effective when consolidated. Don't prune a single tiny output - accumulate several candidates before acting. From 21ac0ee0c3c616ddab99c531af0e048e7b3c00e7 Mon Sep 17 00:00:00 2001 From: Daniel Smolsky Date: Fri, 6 Feb 2026 14:00:26 -0500 Subject: [PATCH 3/5] chore: update default contextLimit to 60% --- README.md | 6 +++--- lib/config.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eef2f56f..4ee3132e 100644 --- a/README.md +++ b/README.md @@ -105,10 +105,10 @@ DCP uses its own config file: > "nudgeEnabled": true, > "nudgeFrequency": 10, > // Token limit at which the model begins actively -> // compressing session context. Best kept around 40% of +> // compressing session context. Best kept around 40-60% of > // the model's context window to stay in the "smart zone". -> // Set to "model" to use the model's full context window. -> "contextLimit": 100000, +> // Accepts: number, "model", or "X%" (percentage of model's context window) +> "contextLimit": "60%", > // Additional tools to protect from pruning > "protectedTools": [], > }, diff --git a/lib/config.ts b/lib/config.ts index 5e2fa563..92ccbf3e 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -505,7 +505,7 @@ const defaultConfig: PluginConfig = { nudgeEnabled: true, nudgeFrequency: 10, protectedTools: [...DEFAULT_PROTECTED_TOOLS], - contextLimit: 100000, + contextLimit: "60%", }, distill: { permission: "allow", From cec4f66998584469f003040d21ce3cbb85d7bb22 Mon Sep 17 00:00:00 2001 From: Daniel Smolsky Date: Fri, 6 Feb 2026 14:04:45 -0500 Subject: [PATCH 4/5] breaking: remove "model" option from contextLimit --- README.md | 2 +- dcp.schema.json | 8 ++------ lib/config.ts | 7 +++---- lib/messages/inject.ts | 4 ---- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4ee3132e..cb17205f 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ DCP uses its own config file: > // Token limit at which the model begins actively > // compressing session context. Best kept around 40-60% of > // the model's context window to stay in the "smart zone". -> // Accepts: number, "model", or "X%" (percentage of model's context window) +> // Accepts: number or "X%" (percentage of model's context window) > "contextLimit": "60%", > // Additional tools to protect from pruning > "protectedTools": [], diff --git a/dcp.schema.json b/dcp.schema.json index 080d5863..e25f09b1 100644 --- a/dcp.schema.json +++ b/dcp.schema.json @@ -110,16 +110,12 @@ "description": "Tool names that should be protected from automatic pruning" }, "contextLimit": { - "description": "When session tokens exceed this limit, a compress nudge is injected (\"model\" uses the active model's context limit, \"X%\" uses percentage of the model's context window)", - "default": 100000, + "description": "When session tokens exceed this limit, a compress nudge is injected (\"X%\" uses percentage of the model's context window)", + "default": "60%", "oneOf": [ { "type": "number" }, - { - "type": "string", - "enum": ["model"] - }, { "type": "string", "pattern": "^\\d+(?:\\.\\d+)?%$" diff --git a/lib/config.ts b/lib/config.ts index 92ccbf3e..1c9e87da 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -27,7 +27,7 @@ export interface ToolSettings { nudgeEnabled: boolean nudgeFrequency: number protectedTools: string[] - contextLimit: number | "model" | `${number}%` + contextLimit: number | `${number}%` } export interface Tools { @@ -291,15 +291,14 @@ function validateConfigTypes(config: Record): ValidationError[] { } if (tools.settings.contextLimit !== undefined) { const isValidNumber = typeof tools.settings.contextLimit === "number" - const isModelString = tools.settings.contextLimit === "model" const isPercentString = typeof tools.settings.contextLimit === "string" && tools.settings.contextLimit.endsWith("%") - if (!isValidNumber && !isModelString && !isPercentString) { + if (!isValidNumber && !isPercentString) { errors.push({ key: "tools.settings.contextLimit", - expected: 'number | "model" | "${number}%"', + expected: 'number | "${number}%"', actual: JSON.stringify(tools.settings.contextLimit), }) } diff --git a/lib/messages/inject.ts b/lib/messages/inject.ts index 8a989f3e..3f0c60b1 100644 --- a/lib/messages/inject.ts +++ b/lib/messages/inject.ts @@ -77,10 +77,6 @@ const resolveContextLimit = (config: PluginConfig, state: SessionState): number return parsePercentageString(configLimit, state.modelContextLimit) } - if (configLimit === "model") { - return state.modelContextLimit - } - return undefined } From 451fc76e93e5ae9dfc82dc716823b8414998f1d0 Mon Sep 17 00:00:00 2001 From: Daniel Smolsky Date: Fri, 6 Feb 2026 15:48:47 -0500 Subject: [PATCH 5/5] chore: default compress permission to deny --- README.md | 4 ++-- lib/config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cb17205f..6460527d 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ DCP uses its own config file: > }, > // Collapses a range of conversation content into a single summary > "compress": { -> // Permission mode: "ask" (prompt), "allow" (no prompt), "deny" (tool not registered) -> "permission": "ask", +> // Permission mode: "deny" (tool not registered), "ask" (prompt), "allow" (no prompt) +> "permission": "deny", > // Show summary content as an ignored message notification > "showCompression": false, > }, diff --git a/lib/config.ts b/lib/config.ts index 1c9e87da..1a60307f 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -511,7 +511,7 @@ const defaultConfig: PluginConfig = { showDistillation: false, }, compress: { - permission: "ask", + permission: "deny", showCompression: false, }, prune: {