acp-kernel 0.0.99-pr.490.346 → 0.0.99-pr.490.347
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/DESIGN.md
CHANGED
|
@@ -262,7 +262,7 @@ Copyright protects _expression_, not ideas, methods, or algorithms (17 USC §102
|
|
|
262
262
|
|
|
263
263
|
### 8.1 First-user-message pin
|
|
264
264
|
|
|
265
|
-
The session's **first user message survives prune when it is covered by an active block — unless dropping it cannot lose the guarantee the pin exists for.** In `rebuildMessages` (`src/prune.ts`) the pin check runs _before_ the covered-by-active-block check, but a covered pin yields when another user message still survives behind it (`firstUserDropSafe`: the earliest non-covered, non-rendered-summary message after the pin must itself be a user). In that case the fold applies fully: the covered first user drops like any other covered message, and the rebuilt wire opens with the surviving user (with the rendered summary anchored in front of it, re-voiced or stripped downstream per mode). Only the _first_ user message is pinned — later covered user messages are pruned normally.
|
|
265
|
+
The session's **first user message survives prune when it is covered by an active block — unless dropping it cannot lose the guarantee the pin exists for.** In `rebuildMessages` (`src/prune.ts`) the pin check runs _before_ the covered-by-active-block check, but a covered pin yields when another user message still survives behind it (`firstUserDropSafe`: the earliest non-covered, non-rendered-summary message after the pin must itself be a plain user text core — the only shape the downstream orphan-stripping passes cannot remove). In that case the fold applies fully: the covered first user drops like any other covered message, and the rebuilt wire opens with the surviving user (with the rendered summary anchored in front of it, re-voiced or stripped downstream per mode). Only the _first_ user message is pinned — later covered user messages are pruned normally.
|
|
266
266
|
|
|
267
267
|
- **Why:** strict providers reject conversations with no user message (e.g., Anthropic requires the conversation to start from the user role). The pin guarantees the rebuilt wire retains at least one user message whenever the input had one. Deliberate since prune's first implementation (v0.0.2) — the ordering of the two checks is part of the contract, not incidental. The original unconditional form was an over-guarantee: it pinned the _specific_ first message rather than the property "a user leads". Once a covered message became the view's first user — the client trimmed earlier history before resending, or the fold targeted the opening message directly — the pin defeated coverage forever: the block stayed active while its payload re-sent itself verbatim every turn, reporting success (billion-context#1869). The conditional yield restores coverage for exactly those shapes while preserving the guarantee everywhere else.
|
|
268
268
|
- **Residual limitation (deliberate):** if no user message survives behind the covered pin (e.g. `[U1-covered, A1, U2-covered…]` where only assistant/tool cores remain), the pin holds and the fold of that range is a no-op on the wire — shipping a non-user-leading frame would reject strict providers, which outweighs the compression gain. Consumers should treat "folded the opening message and nothing user-shaped remains" as a known degenerate case.
|
package/dist/index.js
CHANGED
|
@@ -214,7 +214,7 @@ function firstUserDropSafe(messages, firstUserIndex, coveredBases) {
|
|
|
214
214
|
const message = messages[i];
|
|
215
215
|
if (isCovered(message.id, coveredBases)) continue;
|
|
216
216
|
if (isRenderedSummaryMessage(message)) continue;
|
|
217
|
-
return message.role === "user";
|
|
217
|
+
return message.role === "user" && message.contentType === "text";
|
|
218
218
|
}
|
|
219
219
|
return false;
|
|
220
220
|
}
|