Repository navigation
fix: yield the first-user pin when dropping it cannot lose the user lead - #490
ranxianglei wants to merge 1 commit into
Conversation
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)In your adapter project: npm install acp-kernel@pr-490Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf acp-kernel-pr490.tgz
npm install ./packageThis comment is automatically updated on each push. |
The pin in rebuildMessages fired before the covered check unconditionally, so once a covered message became the view's first user (client trimmed earlier history before resending, or the fold targeted the opening message), its coverage was defeated forever: the block stayed active while its payload re-sent itself verbatim every turn, reporting success (billion-context#1869). The pin now yields only when another user message survives behind it (firstUserDropSafe: earliest non-covered, non-rendered-summary follower must be a user). Degenerate shapes where no user would lead keep today's behavior, documented in DESIGN.md \u00a78.1.
ac4571d to
e593fa8
Compare
[bot] 🏷 PR #490 review 完成 — 审的是最终 head e593fa8(注意:head 在我初审后从 ac4571d amend 过一次—— 结构化七问:
测试有效性:新/改写测试断言有牙(deepEqual 精确 id 序列;两遍 processTurn e2e 走完整管线含 syncBlocks,断言 payload 文本消失 + ref 稳定,正是 #1869 的复现路径;退化变体保住 #462 的 id/ref 稳定性覆盖)。diff 整洁:相对当前 master 仅 5 个文件(DESIGN.md、src/prune.ts、3 个测试文件),无版本/lock 连带变更。 判定:可合(按规矩由人合并)。Sequencing 提醒:kernel 先发 v0.0.100,之后 billion-context 升精确 pin 并落 Responses WS lane 回归测试。 |
|
设计内的 |
Fixes #489 (found while analyzing billion-context#1869)
What
rebuildMessagespinned the first user message unconditionally ahead of the covered check. Once a covered message became the view's first user (client trimmed earlier history before resending, or the fold targeted the opening message), its coverage was defeated forever:syncBlockskept the block active because the base id was still present pre-prune, so the folded payload re-sent itself verbatim every turn while every fold reported success.Behavior change (old → new)
firstUserDropSafe: earliest non-covered, non-rendered-summary follower must be roleuserAND contentTypetext— the only shape the downstream orphan-stripping passes cannot remove). The rebuilt wire then opens with that surviving user (rendered summary anchored in front, re-voiced/stripped downstream per mode).[U1-covered, A1, …], sole-user sessions) keep today's pin — shipping a non-user-leading frame would reject strict providers, which outweighs the compression gain. Documented as a residual limitation in DESIGN.md §8.1.This is a wire-shape change on purpose: frames lose only a previously-pinned covered message whose content an active block has summarized. No ref/id churn (byRef untouched, ids never re-issued), no summary-format change, no node-ordering change.
Why kernel-side
The producer of the bad bytes is the rebuild step; adapter-side detection could only deactivate the stale block (mask) while the payload still occupies context.
Pre-flight
npm run typecheckcleansrc/prune.js(121 tests) + issue-regression family (21), incl. the rewritten/added regression tests:tests/state-prune.test.ts: split into the degenerate-keep shape (assistant followers → pin holds), the new drop case (user follower → covered first user drops, with and without summary injection), and a stale-rendered-summary-copy case (host passes a previously-pruned view)tests/orphan-fixes.test.ts: assertion wording corrected to the conditional semantics (behavior of that fixture unchanged — degenerate shape)tests/issue1476-reid.test.ts: the old "pinned echo keeps id/ref" test now covers the pruned-across-passes path (#1869); added the degenerate-pin variant preserving the original id/ref-stability coverage (reconcile-live-ids (#459) re-numbers post-fold RESENDS as new instances: folded messages escape prune and re-inflate the wire (P0, breaks billion-context CI e2e on 0.0.96) #462)npm run build+npm run format:checkgreenSequencing
Kernel ships first (release v0.0.100 via the standard flow), then billion-context bumps its exact pin and lands the Responses WS lane regression test that reproduced this end-to-end.