Repository navigation
[PR] fix(#4438): stop dsh auto-review side requests from corrupting the main session (false rebase wipe + skipped clamp → permanent 400) - #4453
Conversation
… checkpoint-framing quotes from triggering rebases Incident (v0.1.204, dsh web profile + Cherry Studio gateway): an UNSTAMPED dsh auto-review request (fixed REVIEW_POLICY system + one freshly-flattened history blob, no tools) arrived on a session already sticky-bound to dsh by earlier main turns. Every isolation gate keyed on the LIVE x-bili-plugin header missed it, so it rode the raw main session key through the full pipeline: its blob quoted an old compaction checkpoint mid-text, which false-positived the #2432 native-compaction rebase (0/112 ids retained -> total refs/blocks/fold-state wipe), and its tiny usage sample clobbered the usage-grade baseline the #453 output clamp anchors on (676541 -> 127497) — max_tokens stayed 384000 against real inputs past the window edge, producing permanent upstream 400s. - side-request.ts: new isDshAutoReviewRequest() shape detector (fixed REVIEW_POLICY system prefix + exactly one user entry + no tools), version-pinned like DSH_TITLE_SYSTEM_PREFIX (#2503). - handle.ts: review shape joins sideRequestLike and rides the #388 stateless side passthrough on every wire — no refs/blocks, no rebase detection, no usage settle (relay useRewriter gate keeps side responses off the ledger). Gate is asymmetric by design: identity side requires the LIVE dsh stamp (unstamped reviews already key verbatim there); lane side accepts dsh evidence = live stamp OR sticky session binding — the sticky leg is what catches the incident's unstamped extension traffic. - dsh-compaction-guard.ts: carriesDshLocalCompactionSummary now requires the standalone-checkpoint shape (message STARTS with the preamble or the open tag); framing QUOTED mid-message no longer counts — per the file's version-pin doctrine, template drift degrades to a miss, never a false positive that wipes a live session. Behavior change (disclosed): dsh auto-review requests that used to fork onto persisted |sub:<fp> sessions (#1916/#2203) now ride the stateless passthrough regardless of stamping. The forked lane had no functional value (each review re-serializes the whole blob, so ref ids churn and nothing ever folds) and #3681 showed it overflowing its own window. Tests: new tests/issue4438-dsh-review-lane-isolation.test.ts (unit both directions + e2e incident repro: unstamped review on a sticky-bound folded session leaves refs/boundary/baseline intact and forwards byte-exact); tests/issue2432-dsh-local-compaction.test.ts carrier pins flipped to the standalone contract; tests/dsh-persona-fingerprint.test.ts rewritten from the superseded fork contract to the stateless-passthrough contract on all four wires; side-lane-invariants allowlist extended with justification. Fixes #4438
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g [email protected]This exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr4453.tgz
npm install -g packageInstall instructions are refreshed on each push. |
(ai: vllm-qwen/qwen3.8-27b) 查重:不重复。 独立扫了 open issue + open PR(约 50 个在途):没有第二个条目触碰 dsh auto-review 的车道隔离。最近的邻居都不重叠——#4409(claude 无头 subagent 分裂,不同客户端、不同机制)、#4452(网关吞掉 400 报文后溢出校准环收不到数据,本 PR 已在正文中声明另行跟踪)。与 PR 正文的家族分析(#3712/#3722/#3681/#1916 族)方向一致,我按 diff 独立复核。 标签:bug / dsh / scope/wiring / p1(aux 流量与主会话的隔离缺口属协议接线层;后果是会话硬砖、永久 400,按 2026-10-19 规则定 p1)。 审核进行中:正在逐段读全量 diff(3 个 src 文件 + 4 个测试文件)、核对管道顺序(rebase 检测 vs side-lane 判定的先后)、跑定向测试;CI test 分片还在跑。结论会按结构化八问单独回复。 |
…passthrough tests/dsh-persona-continuity.test.ts still pinned the superseded fork behavior (review request mints a |sub: session) that this PR replaces: the openai-lane e2e now asserts no fork minted, main session requests/refs untouched, 200 verbatim forward. The gated real-dsh twin (e2e-native-dsh-persona scenario B) flips its acceptance from forks>=1 to zero forks for the same reason. Resolver-level unit blocks are unchanged by design: the resolver itself still forks a discontinuous shape — only the wiring keeps auto-review blobs off it.
(ai: vllm-qwen/qwen3.8-27b) CI caught one file my local targeted run missed: Fixed in
Local evidence at |
Cosmetic follow-up on b306aa6: six header lines carried a stray leading space, inconsistent with the rest of the file's column-0 // block. No content change.
(ai: vllm-qwen/qwen3.8-27b) CI verdict on the current head One transparency note on branch history: between my push and the CI run, an additive cosmetic commit Nothing further from my side — the PR is ready for human review/merge whenever. |
(ai: vllm-qwen/qwen3.8-27b) PR review 结论(独立审 diff,不复用 #4438 侧结论;本地定向验证 + CI 全量)。 审核中发现并已在分支上修复的问题(重要):首推的 head 上 CI 三个 test shard 全红,同一根因——
修复后逐 shard 验证:本地 4/4 + typecheck clean;CI 全绿。 独立核验过的关键点(对代码逐行钉过,不是转述 PR 描述):
结构化八问
残余(代码内已注明):零证据全新会话(无 stamp、无绑定、无折叠块)落到完整管道——该状态下无害(#2432 门需要 active blocks);DSH 未来若改 REVIEW_POLICY 前缀措辞,检测器按版本钉死纪律降级为 miss(同 #2503),但缺陷 B 已独立堵掉,完整砖链不会复发。相邻校准饥饿缺口跟踪于 #4452,正确未并入。 收工判定:head |
Closes #4438
查重: 与 #3712/#3722 同属 native-compaction rebase 机制家族,但触发面不同(本单是 aux 请求的车道隔离缺口把 review 请求放进主管道,#3712 是真实 checkpoint 落地后的恢复质量)、后果不同(本单经 usage clobber 跳过 #453 clamp → 会话硬砖;#3712 是压缩能力软退化);#3681(closed)症状不同(review 车道自身超窗)。相关家族:#1916/#2203(persona fork 设计,本 PR 部分取代)、#2156/#2160、#2503(title sidecar 先例)、#388(side passthrough 契约)。
问题(人话版)
DSH 的自动审查扩展在每次执行工具前发一个「审查请求」(固定 REVIEW_POLICY system + 一条拍平的历史快照 user 消息,复用主会话 id)。在 bili 0.1.204 + DSH 0.2.1-rc.2(web profile, openai wire)上,这样一个请求就能把整个会话砖掉:之后每个主请求都带 max_tokens=384000 撞上游 400,永不恢复。三个叠加缺陷,同一失败域(aux 流量与主会话的隔离):
A — 车道隔离缺口(根因)。rebase 资格判定读的是粘性
session.metadata.pluginAgent(prepare-openai.ts 的 resolveLaneDecisions 输入),而所有 persona-fork / side-passthrough 身份门读的是实时x-bili-pluginheader(session-id.tsdshPersonaFingerprintApplies)。一个不带 header 的 auto-review 请求落在已绑定 dsh 的会话上时:所有 fork/passthrough 门全部错过(verbatim 主 key、走完整管道),rebase 门却仍然生效(粘性绑定给出 dsh profile)。B — checkpoint 框架误报。
carriesDshLocalCompactionSummary原来匹配「新 user 消息任意位置出现<compacted-summary>」。审查快照在自己的 FILTERED_HISTORY 段里引用了更早一次真实落地的 checkpoint 框架 → guard 把「0/112 covered ids retained + checkpoint framing」当成真实 compaction 落地 →reconcileNativeCompactionBoundary清空了全部 refs/blocks/fold 状态;模型当时挂起的 compress 调用随之 none-resolved 失败。C — usage clobber 跳过 #453 clamp。主车道上的审查响应正常结算 usage,把会话的 usage-grade baseline 从 676541 覆盖成 127497;rebase 后又叠加 chars/4 本地估算低估(≥65K),输入估计 ≤ ~633K ⇒ cap ≥ 384K ≥ 请求的 384000 ⇒ clamp no-op ⇒ #3438 把完整 384000 恢复出去 ⇒ 永久 400。算术钉死:同会话 rebase 前
384000 -> 338207与 est=676541、5% margin 精确吻合——缺掉的那次 clamp 就是致命步骤。修法(仅 host 侧,不动 kernel/)
isDshAutoReviewRequest—— 版本钉死的 REVIEW_POLICY 前缀(已从 DSH 0.2.1-rc.2lib/index.js:20确认字面量)+ 无 tools + 恰好一条非 system 消息。接入两条腿、证据不对称:身份腿要求实时 dsh stamp(保证带 stamp 的 review 不再走旧 |sub: fork 路径);车道腿接受实时 stamp 或粘性绑定(接住无 stamp 的扩展流量——即事故形态——同时非 dsh agent 不受影响,allowlist 测试钉住)。命中即走 标题生成等侧请求污染主会话状态:prepareAnthropic 缺 isTitleGen 守卫、快照无条件覆盖、survivedCount 每请求空转 #388 side passthrough:verbatim 转发、kernel 状态不碰、不跑 rebase 检测、不结算 usage(side 响应走 undefined session——relay useRewriter 门,proxy 模式 SSE 出站不 strip 模型 emit 的渲染标签(openai/anthropic wire)— #457 分析发现的同类遗漏 #460/nudge: no-usage recovery leaves stale reference after network or 5xx failure #1595 既有契约)、不污染 nudge。行为变更披露(Deliverable #4)
带 stamp 的 dsh auto-review 请求:旧行为 = fork 到持久化
|sub:<fp>persona 会话(#1916/#2203 设计);新行为 = 一律 stateless side passthrough(无论是否带 stamp)。原因:每次 review blob 都是新鲜序列化、id 全换 → 持久状态零折叠收益;#3681 证明 review 车道自身会超窗;统一处理不再依赖不可靠的 stamping。主轮行为不变(检测器要求 no-tools + 单消息形状;负例测试钉住「多轮历史引用 policy 文本」仍走完整管道)。Config surface: 无。kernel-change: 无。
测试
本地定向(绿):tests/issue4438-dsh-review-lane-isolation.test.ts(新增:检测器双向 truth-table、aux-snapshot carrier 双向 pin、e2e 事故复现——无 stamp review 落在粘性绑定的已折叠会话上:无 boundary/conflict、refs+baseline 原样、无 |sub: 铸造、逐字节 verbatim 转发、事后主轮健康且 fold 存活;带 stamp 变体;负例)、tests/issue2432-dsh-local-compaction.test.ts(carrier 双向翻转)、tests/dsh-persona-fingerprint.test.ts(四条 wire 上的契约由 #1916/#2203 fork 改写为 #4438 stateless)、tests/side-lane-invariants.test.ts、title-sidecar/side-lane 套件 —— 93/93 pass;typecheck clean。全量回归看 CI。
残余(代码内已注明):零证据全新会话(无 stamp、无绑定、无折叠块)落到完整管道——在该状态下无害(#2432 门需要 active blocks)。
相邻已知缺口(不并入本 PR,另行跟踪):网关把 400 报文改写成通用错误体时,溢出校准环收不到任何数据(#4093/#4090 均依赖报文里的 stated counts)→ 见 #4452。