Repository navigation
fix(core): share compression cache for equivalent model selectors - #15318
Conversation
|
Thanks for the PR — and for filing #15197 first with the reproduction attached. That is the right order, and it made this gate quick to run. Template looks good ✓ — every required heading is present, including the Chinese section. Problem: observed, not theoretical. #15197 carries an executed source-level reproduction that calls the real Direction: aligned, and the codebase already agrees with it. Size: core path touched ( Approach: this is the minimal change, and it matches what I would have written from the title alone. Reusing the existing predicate instead of introducing a second identity scheme is the right instinct — a new normalizer here would have given the function two competing notions of "same route". Deleting Risk: no high-risk path match (Stage 1e clean). The real risk here is evidentiary rather than structural, and I want to flag it up front because it decides what happens next: the fork CI is sitting at Moving on to code review. 🔍 中文说明感谢贡献——也感谢先提交 #15197 并附上复现。这个顺序是对的,也让本次准入检查很快就能完成。 模板完整 ✓——所有必需小标题都在,包含中文部分。 问题: 是已观测到的 bug,不是理论性加固。#15197 附上了已执行的源码级复现:调用真实的 方向: 对齐,而且代码库本身已经认同这个方向。自 #13432/#13876 起, 规模: 触及核心路径( 方案: 这是最小改动,也和我仅看标题时会写的方案一致。复用既有判定谓词、而不是引入第二套身份方案,是正确的取舍——在这里新写一个归一化函数会让同一个函数里出现两种互相竞争的"同一路由"定义。直接删除 风险: 未命中高风险路径(Stage 1e 干净)。这里真正的风险是证据层面的,而非结构层面的,我想先说明,因为它决定后续走向:fork 的 CI 处于 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewIndependent proposal first. From the title and the "why" alone, before reading the diff: the picker persists provider-qualified selectors, the gate compares them against a bare model ID, so the fix has to compare resolved routes rather than strings — and the authority on when a selector maps back to the main generator is the send layer's The load-bearing claim holds. Everything rests on
And the shared path really goes through that resolver: It fails toward cold, never toward false sharing. There is exactly one divergence between the two conditions. When No new evaluation path, no new throw. Static regression sweep. CI never ran, so I walked every existing test that could flip instead of trusting a green suite:
So the only behavior that changes is the intended one: equivalent spellings of the main route regain sharing, genuinely distinct model/auth/endpoint stay cold. New test well-formedness. I can't execute it, so I checked it against the fixtures it uses: Two non-blocking notes. The diagnostic string is still CI test evidenceThe PR's own CI has not executed. All three
Not verified, and why:
Sandboxed verification would settle this: 中文说明代码审查先写独立方案。 只看标题和"为什么需要"、未读 diff 时我的方案是:选择器保存的是带提供商限定的值,而门控拿它和裸模型 ID 比较,所以修复必须比较解析后的路由而非字符串;而"某个选择器何时映射回主 generator"的权威判定在发送层的 关键论断成立。 一切都取决于"
并且共享路径确实经过该解析器: 失败方向偏向冷路径,绝不会误共享。 两个条件只有一处差异:当 没有新增求值路径,也没有新增抛错。 静态回归排查。 由于 CI 从未运行,我逐个走查了所有可能翻转的既有测试,而不是依赖一个绿色套件:
因此唯一发生变化的行为就是预期中的那个:主路由的不同拼写恢复共享资格,而真正不同的模型/认证/端点仍走冷路径。 新测试的形式正确性。 我无法执行它,所以对照它使用的 fixture 做了核查: 两点非阻塞意见。 诊断字符串仍是 CI 测试证据本 PR 自己的 CI 没有执行。head SHA 上三个由 未验证项及原因:
沙箱验证可以定论: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Confidence: 3/5 — the code is clean and I could not break it, but nothing has executed it, so approving now would attest to test results that do not exist. Stepping back. My independent proposal and this diff are the same change, which is the strongest signal I have that the approach is right rather than merely plausible. The five production lines delete a string comparison and substitute a predicate that the same function already computes and already trusts for budget sizing — so this is less "new behavior" than "removing an inconsistency between two checks that were answering the same question differently." I verified the predicate against So why not approve? Because the honest answer to "did I verify it works?" is no. I am deliberately not emitting a deferred-approval marker here. The PR's CI runs are already completed (as What unblocks this: a maintainer approves the pending workflow run on ⏸️ Deferring to the maintainer. Reason, specifically: this is a core-path behavioral change ( 中文说明信心:3/5 — 代码是干净的,我没能找到破坏它的方式,但没有任何东西执行过它,所以现在批准等于为一个并不存在的测试结果背书。 退一步看整体。我的独立方案与这个 diff 是同一个改动,这是我能拿到的最强信号——说明方案是对的,而不只是听起来合理。这 5 行生产代码删掉了一个字符串比较,换成同一个函数本就计算、且本就用于预算定窗而信任的谓词;所以这与其说是"新行为",不如说是"消除了同一函数里两处对同一问题给出不同答案的判断之间的不一致"。我把该谓词与 那为什么不批准?因为对"我验证过它能工作吗"这个问题,诚实的回答是没有。 我特意没有在这里输出延迟批准标记。该 PR 的 CI 运行已经完成(结论是 解除阻塞的条件: 维护者批准 ⏸️ 转交维护者处理。 具体原因:这是核心路径的行为改动( — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed. Suggestions are inline.
2 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- skip-reason diagnostic names only a model mismatch (packages/core/src/services/chatCompressionService.ts:957) — already reported (comment 6377909324)
- stale design-doc gate bullet still stating the deleted string-equality rule (docs/design/chat-compression-cache-sharing.md:15,40) — already reported (comment 6377909324)
Not reviewed: build-and-test — no CI check exercised this diff: 75 of 82 checks at the reviewed SHA are skipped and the 14 successes are bot orchestration (no build, lint, typecheck or unit-test job ran; the fork's real workflows sit at action_required). packages/core was built and fully tested locally instead, with zero net-new failures against the merge base, but the dependent packages/cli suite never ran because its build OOMs identically on the merge base.
Not explored to full depth (tool budget reached): "agent 1c": reading encodeAuxModelSelector / shareableAuxSelector (packages/cli/src/ui/opentui/dialog-data.ts:534-542) to confirm whether an empty \0 pin survives int…; "agent 6b": executing the new it.each cases — npx vitest run src/services/chatCompressionService.test.ts in packages/core was stopped by the repo's globalSetup guard ….
Not reviewed: reverse audit — stopped before round 4 by the review time budget.
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
本轮确认的 2 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查(原文为英文):build-and-test — no CI check exercised this diff: 75 of 82 checks at the reviewed SHA are skipped and the 14 successes are bot orchestration (no build, lint, typecheck or unit-test job ran; the fork's real workflows sit at action_required). packages/core was built and fully tested locally instead, with zero net-new failures against the merge base, but the dependent packages/cli suite never ran because its build OOMs identically on the merge base.
未探索到全部深度(达到工具调用预算):"agent 1c":reading encodeAuxModelSelector / shareableAuxSelector (packages/cli/src/ui/opentui/dialog-data.ts:534-542) to confirm whether an empty \0 pin survives int…;"agent 6b":executing the new it.each cases — npx vitest run src/services/chatCompressionService.test.ts in packages/core was stopped by the repo's globalSetup guard …。
未审查:反向审计——评审时间预算不足,未能开始第 4 轮。
— qwen3.8-max via Qwen Code /review (v0.26.0)
The window guard compared the compaction selector to the main model by string, so a provider-qualified or endpoint-pinned selector naming the main model paid the whole-history slimming estimate and discarded it, because the cache-sharing path posts the history unslimmed. Key the guard on the same route predicate the budget logic uses (extracted as onMainRoute), and pin the qualified/pinned main-route equivalence with per-model resolution tests that fail if the send-layer terms drift.
…t-compaction-cache
|
Refreshed the branch with current main (head |
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed. Suggestions are inline.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- stale design-doc gate bullet restating the deleted string-equality rule (docs/design/chat-compression-cache-sharing.md:15,40) — already reported (comment 6377909324)
Not reviewed: reverse audit — stopped before round 1 by the review time budget.
Test Plan (not a blocker): 298 tests passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 3571 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 17,424 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 844 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 3346 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed.
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:反向审计——评审时间预算不足,未能开始第 1 轮。
Test Plan(非阻断):298 tests passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 3571 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 17,424 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 844 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed; 3346 passed — this review observed 38630, 2816, 45751, 1028, 2278, 650, 13245 passed。
— qwen3.8-max via Qwen Code /review (v0.26.1)
…ssion cache The sideQueryOnMainRoute re-read happens after the window guard, so a window-forced downgrade to the main model keeps the shared path; hoisting the assignment flips the downgrade case to the cold path and no test caught it. Add the downgrade-under-sharing case with a registry window of 1 token and correct the two design-doc lines that still restated the deleted string-equality rule.
…t-compaction-cache
…t-compaction-cache
|
merge-ready — 33/33 scripted assertions passed (0 failed) at head 中文摘要结论:merge-ready,33/33 脚本断言通过。 A/B 结论:核心论断承重。用真实 两点需要澄清(非阻塞):
findings:无阻塞项。两条 Suggestion(谓词提取、诊断文案)见正文。 未覆盖范围:真实提供商缓存命中/延迟/费用(issue 自身也不主张)、CLI 全量套件(PR 自己的 CI 已跑 Central claim and A/BThe PR's claim: a compaction selector that routes to the main model (provider-qualified, or endpoint-pinned at the main base URL) should regain compression cache sharing, while a genuinely different model, auth type or endpoint stays cold. Both arms run
Every shared cell also posted the unslimmed history ahead of the directive, and both C9/C10 are listed as harness-only on purpose: the harness feeds raw selectors into a stubbed Corrections to the prior review roundThe stage-3 findings were written against R2-1 axis 1 (empty pin) and axis 2 (multi-NUL) are not reachable.
The predicate and the send layer agree on all four. So the two copies cannot drift on those axes through any settings value — only a future edit to one side can, which is exactly the maintenance argument R2-1 makes, and it survives. C10 flipping in the harness is a harness artifact and is not claimed as a product behaviour. FindingsNo blocking findings. Two suggestions: S1 (Suggestion, pre-existing): the predicate is a hand-maintained copy of the send layer's condition. R2-1's proposed extraction ( S2 (Suggestion, pre-existing wording): the skip diagnostic still says Mutation matrixIndependent third tree at head; runner
The report claims per-guard coverage only, and the control row shows the harness can kill: 12 named tests go red. The first M9 I wrote only deleted a debug line and survived; that row was discarded and re-run as the behavioural mutation above, which is why the matrix is trustworthy at all. Survivor adjudication — both are dead clauses, not coverage gaps. For M8c the instrumented run shows Vacuity check. The PR's own new tests are not vacuous: run against base source they fail exactly 3 cases ( Gates
Not covered
MethodologyThree detached worktrees from this clone: head Evidence— DeepSeek-V4.1-Flash-1017 via Qwen Code /verify-pr (v0.26.4; skill c5273cc80df5) |
|
Qwen Code review did not complete successfully. Qwen review exited with status 1. A transient error is retried automatically; if you are seeing this, retry with |
doudouOUC
left a comment
There was a problem hiding this comment.
EN
Thanks for updating the design wording to match the route-based behavior. One documentation requirement is still open at b2c8b648: docs/design/chat-compression-cache-sharing.md:15 updates the English design, but the head does not contain docs/design/chat-compression-cache-sharing.zh-CN.md, and the document has no reciprocal language links below its title.
docs/design/README.md:35-42 explicitly requires adding the missing translation when updating an existing single-language design. Please add the complete zh-CN counterpart in this PR, link the English and Chinese versions immediately below both titles, and keep the new model/auth-type/endpoint eligibility wording aligned in both versions.
中文
感谢同步更新设计文档中的路由判定说明。当前 b2c8b648 还有一项文档要求未满足:docs/design/chat-compression-cache-sharing.md:15 修改了英文设计,但当前 head 中不存在 docs/design/chat-compression-cache-sharing.zh-CN.md,且文档标题下方没有双向语言链接。
docs/design/README.md:35-42 明确要求:更新已有的单语言设计文档时,应在同一变更中补齐缺失的译文并保持两个版本一致。请在本 PR 中补充完整的 zh-CN 版本,在两个文档标题下方分别添加英文/中文双向链接,并确保新的模型、认证类型和端点缓存资格说明在两个版本中保持一致。
The design doc was English-only when this PR updated its eligibility wording; docs/design/README.md requires completing the missing translation in the same change. Add the full zh-CN version with the route-based model/auth-type/endpoint wording aligned, and reciprocal language links below both titles.
|
@doudouOUC Done — the complete zh-CN counterpart is added at |
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
Not reviewed: reverse audit — stopped before round 1 by the review time budget.
Not reviewed: verification — the verifier shard was refused by the review time budget, so this round's carried finding posts unverified.
Not reviewed: verification and reverse audit — neither the verifier nor the reverse auditor was launched with a prompt this skill builds — the posted findings were ruled on, and the misses the rest of the review left were hunted, if at all, without the briefs this skill certifies against.
— [unverified] tag when the loop ended — the verifier never ruled on them, and they are not confirmed.
Test Plan (not a blocker): 298 tests passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 3571 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 17,424 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 844 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 3346 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed.
中文说明
仅完成部分审查,审查缺口已披露。
未审查(原文为英文):reverse audit — stopped before round 1 by the review time budget.
未审查(原文为英文):verification — the verifier shard was refused by the review time budget, so this round's carried finding posts unverified.
未审查:验证与反向审计——验证 agent 与反向审计 agent 都没有用本 skill 构建的 prompt 启动——发布的发现即便被裁定过、评审其余部分遗漏的问题即便被搜寻过,也都缺失了本 skill 用以认证的 brief。
— [unverified] 标记——验证者从未对它们作出裁决,它们不算已确认。
Test Plan(非阻断):298 tests passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 3571 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 17,424 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 844 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed; 3346 passed — this review observed 19226, 2067, 39835, 2349, 306, 14150 passed。
— deepseek-v4.1-flash-1017 via Qwen Code /review (v0.26.6)
|
For the assigned reviewers (@yiliang114 @wenshao) — the current head
If anything else is blocking from your side, happy to address it; otherwise an approve + merge whenever convenient would be much appreciated — happy to help with any follow-up in a separate PR (e.g. the R2-1 predicate extraction wenshao suggested keeping as a follow-up). |
|
|
|
@qwen-code /review --timeout=360 |
|
@qwen-code Retrying the request from #15318 (comment) — the previous attempt failed to process. Summary unchanged: head |
|
@wenshao Sorry to ping again — it looks like your agent run failed twice at its final step: once at the end of the full verification report on We did try re-mentioning the bot as the footer suggests (the two If it saves a step: your verification already reads as complete, the only change since |
|
|
…t-compaction-cache
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R2-1
onMainRoutehand-maintained copy of the send-layer main-route predicate (packages/core/src/services/chatCompressionService.ts:772) — already reported (comment 4372321036, thread resolved)
Not reviewed: reverse audit — stopped before round 1 by the review time budget.
Test Plan (not a blocker): 298 tests passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 3571 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 17,424 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 844 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 3346 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed.
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:反向审计——评审时间预算不足,未能开始第 1 轮。
Test Plan(非阻断):298 tests passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 3571 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 17,424 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 844 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed; 3346 passed — this review observed 19578, 2092, 40967, 2361, 355, 14821 passed。
— deepseek-v4.1-flash-1017@fda99a87 via Qwen Code /review (v0.26.7)
|
@yiliang114 as assignee, a quick summary now that this PR is fully green at |
|
从验证侧的复核已完成,所有声明均已对照实时状态核实。以下是公开回复: Confirming from the verification side — nothing is blocking from my side at the current head
R2-1 stays a deferred, non-blocking suggestion as discussed — its thread is still open, but thread resolution is not part of the merge gate. 中文摘要从验证侧确认:当前 head |
|
@wenshao Thank you for the thorough re-verification — that closes every open question on this side. Since your verification already covers everything a review would: would you convert that conclusion into one of the two formal approvals on this head? The second we'll ask of @yiliang114 or @doudouOUC. |
|
Conclusion unchanged, but it no longer covers the review head — my round ran on The added surface between those two commits is documentation only, and I verified that at blob level rather than by reading the diff stat:
The PR's only own commit after my round is On the current head, CI is fully green: all eight Two things I want to be precise about rather than quietly helpful:
The one unresolved thread is still R2-1, a Suggestion. My round's finding on it stands: the two divergent axes it names (empty pin, multi-NUL) cannot reach 中文说明结论不变,但已不覆盖当前评审 head——我这轮在 两者之间的新增面只有文档,而且是按 blob 逐文件核对的,不是看 diffstat:
我这一轮结束后 PR 自己的唯一提交是新增中文设计文档,该区间其余内容都是 当前 head 的 CI 全绿:8 个 Linux 单测分片、Lint & Static、Test (ubuntu-latest)、Integration (no-AK)、web-shell E2E Smoke、OpenTUI no-flicker gate、Managed Agent gate。 两点我要说清而不是含糊带过:
唯一未解决线程仍是 R2-1(Suggestion)。我这轮的判定维持:它指出的两个分歧轴(空 pin、多 NUL)经真实 — DeepSeek-V4.1-Flash-1017 via Qwen Code /verify-pr (v0.26.4) |
|
Understood — thanks for the blob-level re-verification and the precise verdict/approval distinction. The formal approvals then rest with the human reviewers on |
|
@doudouOUC following up on this one for review when you have a window. Where things stand on head
The functional change stays concentrated in the compression service's main-route predicate extraction; the rest is tests. Happy to walk through any part of the diff. |
|
One correction to the summary above, because it cites my round: The change is not a predicate extraction. That distinction is exactly the open R2-1 thread, so a reviewer reading this for the first time should see "local predicate introduced, duplication retained", not "duplication removed". Extraction is what R2-1 suggests and what has not been done here. It does not change my verdict, and I want to be clear that it is not a request for a code change in this PR: I verified that the two copies agree on every input reachable through 中文说明对上面那段总结做一处更正,因为它引用了我的验证结论: 这个改动不是「谓词提取」。 这个区别正是未解决的 R2-1 线程说的内容,所以第一次读这个 PR 的评审者应当理解为「引入本地谓词、保留重复」,而不是「消除重复」。提取才是 R2-1 建议的做法,本 PR 没有做。 这不改变我的判定,也不是要求在本 PR 里改代码:我实测过两份副本在所有可经 — DeepSeek-V4.1-Flash-1017 via Qwen Code /verify-pr (v0.26.4) |
|
Understood, and thanks for catching it before a reviewer reads the thread cold — the "predicate extraction" wording in my summary was wrong. For the record: this PR introduces |
|
merge-ready — 85/85 scripted assertions passed (0 failed) at head 中文摘要结论:merge-ready,85/85 条脚本断言通过(0 条失败)。本轮是第二轮:三个代码/测试文件的 blob 与上一轮验证过的 head( A/B 结论:核心论断承重。用真实 两端一致性:另用真实 findings:无阻塞项。一条描述修正(上述 C17),一条既有且方向安全的保守失败(端点 pin 不匹配时门控判冷、发送层落到主生成器)。 未覆盖范围:真实提供商缓存命中/延迟/费用;合并树上的复跑(只做了树级比对:合并无冲突,且被改文件在合并树里就是 head 与 main 两侧改动的组合);上一轮"死子句"观察未重测。 Previous round statusRound 1 ran at
The gap round 1 left open — its round predated the zh-CN design counterpart — is closed: Central claim and A/BThe PR's claim: a compaction selector that routes to the main model — provider-qualified ( Both arms run the real Witness:
The 4 target flips are Every shared cell in both arms posted the unslimmed history (
CorrectionsTo the PR description, not to the code. The evidence table says "Default or bare main model: 1 / 0 before and after". That holds when the main model is registered under the session's auth type ( The two-ends table below is the measurement behind that statement. A cold gate on a main route ( Witness: FindingsNo blocking findings. F1 (Suggestion — description accuracy). Narrow the "default or bare main model is unchanged" line to "a selector that the send layer routes to the main generator". Evidence: F2 (informational, pre-existing). An endpoint pin that the registry cannot match ( Mutation matrixIndependent runs of the two suites that pin this behaviour (
Final tree state after the matrix: Every row's expectation was fixed before the run from the PR's own claims; Not covered
MethodologymacOS arm64 host, Node 22.23.4, vitest 3.2.7. Two detached worktrees at Evidence |
qqqys
left a comment
There was a problem hiding this comment.
APPROVE — reviewed at head 4c698c473a742931ca826e6d38f8d95a552c956e. No blocking correctness, security, data-loss, regression, or compatibility issue found.
Prior findings
No Critical was ever filed on this PR, so there is no historical blocker to re-verify. For the record, all four bot findings across four rounds were Suggestion-level: R1-1 and R1-2 were ruled fixed by the reviewer that filed them, R2-2 likewise, and R2-1 (the onMainRoute predicate being a hand-maintained copy of the send layer's condition) was deferred to #16473 under the bot's own adjudication. The one human review (@doudouOUC, COMMENTED at b2c8b648) raised a documentation requirement rather than a code defect — the missing zh-CN counterpart and the reciprocal language links — and that is satisfied at this head: docs/design/chat-compression-cache-sharing.zh-CN.md is added, [English] | [简体中文] sits immediately below both titles, and the eligibility bullet reads the same way in both languages ("routes to the main model — the resolved model, auth type, and endpoint match the main generator"). @wenshao's APPROVE is current at this same head per latestOpinionatedReviews.
What I verified in the code at this head
The whole change is one widening — canShareCache and the compaction-window gate both move from the string comparison effectiveCompactionModel === config.getModel() to the route predicate onMainRoute(...) — so the load-bearing question is whether that predicate agrees with the send layer it claims to mirror. It does, and on two of its three terms it is not a copy at all:
- The resolution half is the identical call.
onMainRoutedoesresolveModelId(model, buildModelIdContext(config))(chatCompressionService.ts:774);resolveForModeldoesthis.resolveModelSelector(requested.model), andresolveModelSelectoris a one-line private wrapper whose entire body isresolveModelId(model, buildModelIdContext(this.config))(baseLlmClient.ts:1071-1073). Same function, same context constructor — these cannot drift. - The comparison targets are the same object. The service's
contentGeneratorConfigisconfig.getContentGeneratorConfig()(chatCompressionService.ts:535), which is exactly whatresolveForModelreads asmainGeneratorConfigformainAuthTypeandmainBaseUrl(baseLlmClient.ts:854-856, compared at:862-864). So the authType and endpoint-pin terms compare against the same values the send layer compares against. - The pin split agrees for the format that is actually produced.
splitModelBaseUrlcuts at the first\0and returns the remainder asbaseUrl(baseLlmClient.ts:61-70); the service'sselector.split('\0')yields the same pair for the single-pinauthType:id\0<declaredBaseUrl>shapegetCompactionModel()carries (#12760), which is also the idiom the pre-existing guard body already used at:795.
The post-guard re-read is load-bearing, not decorative. effectiveCompactionModel is a let (:745) and the guard reassigns it to config.getModel() when the compaction window is too small (:820), so sideQueryOnMainRoute = onMainRoute(effectiveCompactionModel) at :829 genuinely observes the downgrade — that is what makes a window-forced fallback share the cache and take the main route's budgetWindow/reactiveContextCeiling instead of a compactionModelWindow that was never set. usesMainModel has no remaining reader anywhere in the file, so deleting it leaves no stale gate.
Skipping the window guard on an equivalent selector is the correct consequence, not a lost check. When onMainRoute is true the side query is sent to the main content generator, so the main model's window is the governing one and it is what budgetWindow resolves to via reactiveContextCeiling (:860-862); measuring a registry window for a request that never leaves the main route would only risk a spurious downgrade. The guard's own body is unchanged, and its if (resolved) gate means an unresolvable selector still measures nothing and downgrades nothing.
The divergence I looked for and found is in the conservative direction, and pre-dates this PR. For a selector that resolveModelId cannot resolve, resolveForModel falls back to the main generator (its requestModel defaults to config.getModel()), while onMainRoute returns false because it compares the raw string. That yields no cache sharing and a guard that resolves nothing — the safe side — and it is byte-for-byte the behaviour of the old inline predicate, which computed the same three terms, so this PR neither introduces nor widens it. It is the R2-1 family already deferred to #16473.
The tests pin the equivalence at the layer that owns it. baseLlmClient.test.ts adds two cases that drive the real resolveForModel and assert resolved.contentGenerator is the main generator (toBe, not a shape match) for openai:main-model and for openai:main-model\0<mainBaseUrl>, with mockCreateContentGenerator asserted uncalled — so the widening rests on the send layer's own answer rather than on a re-stated copy of its condition. chatCompressionService.test.ts adds the shared-path case plus the two controls that matter: still slims for a genuinely distinct compaction model (the guard still fires when the route really differs) and shares the cache after the window guard downgrades a distinct compaction model (the post-guard re-read).
CI
62 checks pass or are intentionally skipped at this head, including Lint & Static and Test (ubuntu-latest, Node 22.x). The only two non-pass entries are a pending Select the Managed Agent tier and route in the review workflow, started by the approval that landed moments ago; neither gates this change and I did not wait on them.
|
Released in v0.27.1. |





What this PR does
Explicitly selecting the current model for compaction keeps the existing cache-sharing eligibility when the resolved model, auth type and exact endpoint are unchanged. The cache gate and its diagnostic now use the same existing route comparison as compression sizing. Different routes retain the cold path, and the settings documentation explains the eligibility boundary.
Full preflight is incomplete; the validation limits and upstream control results are recorded below.
Why it's needed
The model picker saves provider-qualified selections. Comparing those selections directly with the bare main-model ID sent equivalent selections down the cold summarizer path, even when the send layer returned the exact same generator and configuration. This change restores prefix-sharing eligibility; it does not promise provider cache hits or latency/cost savings.
Reviewer Test Plan
How to verify
Use a cache-supported provider, an authoritative provider-reported prompt-token count, and sufficient context space. Compare default and bare selections with an explicitly qualified current-model selection and a matching endpoint pin. All four should attempt the shared request and preserve the main system instruction, tool declarations and history. Changing the model, auth type or endpoint must remain cold. Existing missing/estimated usage, disabled cache, insufficient headroom, payload overflow, cancellation and shared-request fallback cases should remain unchanged.
Evidence (Before & After)
Source-level reproduction against upstream main
8666ab091f765e294da86b5b2b15abbec0270982called real compression logic with controlled Config accessors and deterministic model I/O. Separate real-resolver controls confirmed exact generator/config identity for the equivalent selectors.The integrated seven-case regression matrix failed exactly the two affected selectors before the production change. Afterward, 288 focused compression/client/side-query tests passed. Independent Astra xhigh verification reran those suites and the original ten-case reproduction/resolver controls: 298 tests passed. Independent review found no issues. Root build, bundle, typecheck, focused ESLint and Prettier checks passed. The built CLI version smoke test returned
0.26.0. The preflight attempt completed clean install, formatting, repository lint, build and typecheck. The final serve-bundle check also passed. Outside-sandbox workspace testing completed four workspaces (3571 passed); partial CLI output recorded 17,424 passed, 33 failed and 107 skipped before the run was stopped after confirmed host/runtime defects. All 33 failures reproduce with identical test names on pristine upstream (844 passed, 33 failed, 2 skipped in those eight files). The script stage completed its pinned Node/Bun matrices and then reported 3346 passed, 2 failed and 79 skipped; both failures also reproduce upstream. Remaining CLI files and subsequent workspace suites are unrun. Full preflight is not green.N/A for a visual demo: this change affects an internal request path. No interactive or live-provider run is claimed; global
qwenwas unavailable, so the repository-permitted test-script fallback was used.Tested on
Environment
Node.js 24.7.0, pnpm 11.24.0, Vitest 3.2.7. Validation is tied to the reviewed patch on base
8666ab091f765e294da86b5b2b15abbec0270982. At the pre-publication check, main23ddc5abb26bec32aad918e82b5faa0372f14c06had no changes to the three touched files or the reviewed source/policy dependencies; this PR preserves the tested base. Verified with preinstalled Command Line Tools Git 2.54.0. The system Git wrapper remains license-gated and is still reached by fixtures that omit PATH. Bash 3.2 lacks mapfile, and Node 24.7 fails a standalone symlink-deletion probe. No agreement or system setting was changed.Risk & Scope
Linked Issues
Fixes #15197.
中文说明
本 PR 做了什么
当解析后的模型、认证类型和精确端点保持不变时,显式选择当前模型作为压缩模型仍保留原有的缓存共享资格。缓存门控及其诊断信息复用压缩预算已有的路由判定。不同路由继续使用冷路径,设置文档也说明了这一边界。
完整 preflight 尚未完成,下文明确列出验证限制及未修改上游的对照结果。
为什么需要
模型选择器保存带提供商限定的选择值。原来将其与主模型的裸 ID 直接比较,导致等价选择进入冷摘要路径,即使实际发送层返回完全相同的生成器和配置对象。本改动恢复前缀共享资格,不保证提供商缓存命中,也不主张延迟或费用收益。
审阅测试计划
如何验证
使用支持缓存共享的提供商、提供商真实上报的输入 token 锚点和充足上下文空间。比较默认值、主模型裸 ID、限定了认证类型的当前模型选择和带匹配端点 pin 的选择。这四种情况都应尝试共享请求,保留主系统指令、工具定义及历史。改变模型、认证类型或端点时应继续使用冷路径。已有的缺失/估算 usage、禁用缓存、上下文空间不足、载荷溢出、取消及共享请求失败降级行为应保持不变。
证据(修改前后)
在上游 main
8666ab091f765e294da86b5b2b15abbec0270982上进行源码级复现:使用受控 Config 访问器和确定性模型 I/O 调用真实压缩逻辑。另以真实解析器确认等价选择返回完全相同的生成器和配置对象。新增的七项回归矩阵在修改生产代码前仅有两个目标选择失败。修改后,压缩、客户端及 side-query 三个目标套件的 288 项测试通过。独立 Astra xhigh 验证重新执行了这些套件及原始十项复现/解析器控制,共 298 项通过;独立审查未发现问题。全仓 build、bundle、typecheck、目标 ESLint 及 Prettier 检查通过,构建后的 CLI 版本检查输出
0.26.0。preflight 尝试已完成干净安装、格式化、全仓 lint、build 和 typecheck,最终 serve-bundle 检查也通过。沙箱外完成四个工作区共 3571 项测试;CLI 部分输出记录 17,424 项通过、33 项失败、107 项跳过,在确认宿主运行时问题后停止。全部 33 项失败都在未修改的上游源码中以相同测试名称复现(对应八个文件共 844 项通过、33 项失败、2 项跳过)。脚本阶段的固定 Node/Bun 矩阵通过,随后脚本测试共 3346 项通过、2 项失败、79 项跳过;两项失败也在上游复现。剩余 CLI 文件及后续工作区套件未运行,不将完整 preflight 称为全绿。可视化演示不适用:本改动涉及内部请求路径。不主张交互式或真实提供商验证;由于没有全局
qwen,使用仓库允许的测试脚本降级复现。测试环境
Node.js 24.7.0、pnpm 11.24.0、Vitest 3.2.7,验证基于
8666ab091f765e294da86b5b2b15abbec0270982上的已审查补丁。提交前核查的主线23ddc5abb26bec32aad918e82b5faa0372f14c06未修改本次三个文件及已审查的源码/规则依赖,本 PR 保留经过测试的基线。使用预装的 Command Line Tools Git 2.54.0 验证。不传 PATH 的测试夹具仍会调用受 Xcode 许可限制的系统 Git 包装器。Bash 3.2 缺少 mapfile,Node 24.7 的独立符号链接删除探针也失败。未接受协议,也未修改系统设置。风险与范围
关联 Issue
Fixes #15197。