Repository navigation
[design/bug] DSH auto-review 与主会话共用 session 持续制造 CACHE SEAM;建议拆分为可压缩的 derived review lane #2203
Copy link
Copy link
Closed
Labels
Description
Description *
main-agent traffic 和 auxiliary-review traffic 被错误地建模成了同一条 session/cache lineage。
本 issue 建议不要再次采用 “识别 auto-review 后直接 side-passthrough” 的方案,而是将 auto-review 建模为:
main session 的 derived child/review lane:状态隔离,但仍然经过 bili,并保留独立压缩能力。
Environment
- billion-context: 0.1.185
- DSH: 0.2.0-rc.2
- DSH Web profile
@deepseek-ai/dsh-experimental-auto-reviewenabled- billion-context native DSH plugin
- Windows
- reproduced session:
session-a215f0cf-648a-4134-ab96-0b4aa8691429
Observed behavior
在该 session 中,bili dashboard 当时显示大约:
requests: 19
input: ~641K
cached: ~315K
cumulative hit: ~49%
CACHE SEAM: ~189K × 10
compressionCount: 0
active blocks: 0
这里最关键的是:
compressionCount = 0
active blocks = 0
也就是说:
这些 CACHE SEAM 在 bili 做任何 compression 之前就已经出现了。
因此这次现象不能解释为 fold 修改历史造成的 cache invalidation。
Request sequence
实际请求呈现出非常规律的两种形态。
Main-agent requests
主 Agent 的 history 持续正常增长,例如:
13 msgs
16 msgs
19 msgs
22 msgs
25 msgs
28 msgs
31 msgs
...
其 system prompt 大约:
~13.9K chars
主 Agent 请求在稳定阶段通常具有较好的 cache hit,例如:
~77–94%+
Auto-review requests
但每次工具调用附近都会插入一个完全不同形态的请求:
2 wire messages
即:
system: REVIEW_POLICY
user: reviewUserText(snapshot)
在 bili processTurn 侧基本表现为:
1 core message
system prompt 大约:
~3.9K chars
这些 review request 经常出现:
cache hit = 0%
What bili sees
因为 main agent 和 reviewer 共用同一个 session id,bili 实际看到的是类似:
13 msgs
↓
2 msgs <- auto-review
↓
16 msgs
↓
2 msgs <- auto-review
↓
19 msgs
↓
2 msgs
↓
22 msgs
↓
2 msgs
...
即:
13 -> 2 -> 16 -> 2 -> 19 -> 2 -> 22 -> 2 -> ...
从 byte-level prefix/cache lineage 的角度,这并不是:
old history + new turn
而是不断在两个完全不同的 request families 之间切换。
因此 seam detector 合理地观察到:
main lineage
↓
review lineage
↓
main lineage
并持续记录 CACHE SEAM。
问题在于:
这些 seam 被记在了 main conversation 的 session trajectory 中。
Why this matters
这不仅仅是 dashboard 的统计不好看。
当两种 traffic 共用同一 session 时,理论上或已经在既有问题中观察到的受影响状态包括:
- cache ledger
- CACHE SEAM trajectory
- usage baseline
- lastInputTokens
- nudge baseline
- refs
- remembered snapshot
- lastMessages
- orphan-GC visibility
- compression state bookkeeping
即使其中一些状态现在已经有局部 guard,session identity 本身仍然没有被正确拆分。
对于 cache accounting 来说尤其明显:
main-agent request
和:
auto-review request
根本不是同一条 prefix chain,却被当成同一个 session 的相邻调用进行 cache continuity 分析。
This is NOT a compression-configuration problem
我测试时使用的 compression 配置包括较高的 nudge interval / context threshold,但当前 reproduction 中:
compressionCount = 0
因此修改下面这些参数都不能解决根因:
compress.maxContextLimit
compress.nudgeGrowthTokens
compress.tiers
preserveRecentTokens
preserveRecentMessages
因为问题发生在第一次 fold 之前。
Relation to existing issues
这个问题与以下 issue 同属一个问题族:
#1307
#1307 已经证明:
- DSH auto-review 使用主 session id;
- review 请求表现为 request: 2 msgs / processTurn: 1 msgs;
- review request 可以破坏 remembered snapshot;
- 随后的 plugin-path compress 可能无法 anchor。
当前 0.1.185 reproduction 的 request shape 与 #1307 一致。
#1309 / #1314
这两个 issue 已经讨论:
- auxiliary request isolation
- auto-review
- side-request semantics
- reviewer 自身的上下文成本
- host-side structured review input
所以本 issue 不是重新报告 “review request exists”。
本 issue 聚焦的是一个当前仍然可观察的残留:
review traffic 和 main traffic 仍然共享同一个 bili cache/session lineage,因此会持续污染 main session 的 CACHE SEAM 和 cache accounting。
Why #1431 / #1861 are not the desired final design
曾经有两个相关 PR:
- #1431
- #1861
它们的方向基本是:
detect auto-review
↓
side-passthrough
↓
do not touch bili kernel state
这种方案确实可以防止 reviewer 污染 main session。
但它的代价是:
reviewer no longer participates in bili compression
这也是后来这些 PR 被关闭时指出的问题:
让 auto-review 直接穿过、不压缩,不是最终设计目标。
我同意这个判断。
因此这里建议的不是重新引入 side-passthrough,而是把请求身份拆成两个 lane。
Proposed design
1. Treat auto-review as a derived child session
逻辑上:
main conversation
|
+-- derived auxiliary/review session
例如:
session-main-123
└── review:dsh-auto-review
二者可以保留 parent-child relation,但必须分别维护:
cache ledger
cache seam trajectory
refs
nudge
usage baseline
snapshot
lastMessages
orphan-GC state
compression blocks
也就是说:
main lane != review lane
2. Reviewer must still go through bili
这里与 side-passthrough 的关键区别是:
NOT:
auto-review
↓
detect
↓
bypass bili
而应该是:
auto-review
↓
detect / classify
↓
derived review session
↓
normal bili pipeline
这样 reviewer 未来仍然可以拥有:
- independent compression
- independent cache accounting
- search_context
- decompress
- CCR / retrieval
- observability
同时不会破坏 main conversation。
3. Preferred host signal
最干净的方案是 DSH 明确告诉 bili:
this request is auxiliary review traffic.
例如:
x-bili-request-class: auxiliary-review
x-bili-parent-conversation: <main-session-id>
x-bili-plugin-agent: dsh-auto-review
bili 可以据此创建或解析:
parent session:
session-main
child lane:
session-main / dsh-auto-review
而不是继续使用完全相同的 session state object。
4. Temporary bili-side compatibility
在 DSH 还没有实现显式 header 之前,bili 已经有足够稳定的信息识别 auto-review,例如:
- fixed REVIEW_POLICY
- one synthetic review user message
- no normal main-agent tool surface
- stable DSH review persona/signature
短期可以:
detect DSH auto-review
↓
route to derived review lane
但不要:
detect DSH auto-review
↓
side-passthrough
这可以先解决 session/cache lineage 污染,同时不给 reviewer compression 这条路线封死。
Reviewer compression itself
还有第二层问题。
当前 DSH auto-review 基本构造为:
system:
REVIEW_POLICY
user:
ENVIRONMENT
PROJECT_INSTRUCTIONS
FILTERED_HISTORY
PENDING_ACTION
其中 FILTERED_HISTORY 被重新序列化进一个巨大的单条 user message。
从 bili 的角度看,review request 实际只有一个巨大的 message。
因此即使把 reviewer 独立成 child session,当前形态仍然不利于 ACP compression:
one huge synthetic message
没有正常的 message-level ranges 可以 fold。
5. Keep FILTERED_HISTORY structured
更理想的是 DSH 将 reviewer 输入保持为结构化 history,例如:
system:
REVIEW_POLICY
history item 1
history item 2
history item 3
...
history item N
user:
PENDING_ACTION
或者:
REVIEW_POLICY
+ filtered structured projection of main session
+ PENDING_ACTION
而不是把全部历史重新 stringify 成一条字符串。
这样 review lane 才能真正获得:
- stable prefix caching
- message-level compression ranges
- recent-history preservation
- old-history folding
- search/decompress
- incremental growth
6. Filtering semantics can remain host-owned
这并不要求 reviewer 必须看到 main Agent 的全部原始历史。
DSH 仍然可以继续决定:
- 哪些 assistant messages 保留;
- 哪些 tool calls 保留;
- 是否排除 tool results;
- 哪些 project instructions 可见;
- 哪些 source attribution 可见。
关键区别只是:
filtered history as structured messages
而不是:
filtered history as one giant serialized blob
这样不会要求 bili 重新实现 DSH 的 review policy。
Expected behavior after fix
修复后:
Main session
应该只看到:
13 -> 16 -> 19 -> 22 -> 25 -> ...
而不再看到:
13 -> 2 -> 16 -> 2 -> 19 -> 2 ...
auto-review 不应再增加 main session 的:
CACHE SEAM
cache miss accounting
usage baseline
nudge state
refs
snapshot changes
Review session
应该单独看到:
review 1
review 2
review 3
...
并拥有自己的:
cache hit rate
CACHE SEAM
compression count
blocks
usage
nudge
如果 DSH 后续采用结构化 history,那么 review lane 自己应该能逐渐形成稳定 prefix,并在需要时独立压缩。
Suggested acceptance criteria
修复可以用下面这些条件验收:
1. 开启 DSH Auto Review 后,main bili session 不再出现:
N msgs -> 2 msgs -> N+... msgs
2. auto-review request 不再增加 main session 的 CACHE SEAM。
3. reviewer 有自己的 derived session / lane identity。
4. main conversation cache hit 恢复为正常 append-only conversation 的水平。
5. reviewer 仍通过 bili,而不是 raw passthrough。
6. main lane 与 review lane 的:
refs
nudge
usage
snapshot
orphan-GC
compression blocks
相互独立。
7. 如果 reviewer history 已结构化,review lane 可以正常:
compress
search_context
decompress
8. Web UI 最好能显示类似:
Main session
└── DSH auto-review
方便诊断 parent/child relation。
Why I think this is the correct abstraction
现在的问题本质并不是:
"How do we detect a side request?"
而是:
"How do we represent multiple LLM request lineages
that belong to one user-facing conversation?"
DSH main Agent 和 DSH auto-review:
- 属于同一个高层 user session;
- 但不是同一个 prompt lineage;
- 也不应该共享一套 compression/cache state。
因此更自然的模型应该是:
user conversation
|
+-- main-agent lane
|
+-- auto-review lane
而不是:
one session id
|
+-- every LLM request mixed together
Related
- #1307
- #1309
- #1314
- #1431 (closed)
- #1861 (closed)
---
这版我认为维护者是能直接看懂的,而且它有一个重要优势:**没有只报“缓存低”这种症状,而是把现象、证据、与旧 issue 的区别、为什么旧修法不合适、建议的新抽象和验收标准都给出来了。**
尤其一定要保留这一组证据:
```text
CACHE SEAM ×10
compressionCount = 0
active blocks = 0
### bili version *
0.1.185
### Usage mode *
Plugin native (bili plugin install …, runs inside the host process)
### Client and version *
dsh 0.2.0-rc.2
### Operating system *
Windows 11
### Upstream and model *
gemini-3.8-flash
### Compression-related config (optional)
```yaml
Log excerpt (strongly recommended)
/acp or acp_status output (optional)
Reactions are currently unavailable
Activity
ranxianglei commentedon Oct 5, 2026
[bot] 🏷 已收到。先给审核结论(对照 master
e5a0066de源码与测试逐条核过),再列需要你补的证据。1. 查重与机制现状:你提的核心抽象已经在 master 上(v0.1.181 起)
本 issue 不是 #1307/#1309/#1314 的重复——那一条线(快照护栏 #1312 → 根治讨论 #1309/#1314 → 两个 passthrough PR #1431/#1861 均关闭未合并,master 上已确认无 #1861 marker 代码残留)最终落地的方案正是你描述的抽象:「拆身份,不绕管线」——persona fingerprint 拆分(PR #1956,#1916 lineage),v0.1.181 起已发版:
x-bili-plugin: dsh时,session key 从纯 conversation id 变为「id + system 提示词指纹」:主 agent 的 system 锚定原 key(kernel anchor 语义),auto-review 的固定REVIEW_POLICYsystem 落到自己的会话<id>|sub:<fp>(src/server.ts:2189-2213、src/session-id.ts的dshPersonaFingerprintApplies)。tests/dsh-persona-fingerprint.test.ts钉死(真实 proxy e2e:主轮锚定 raw key → review 形状 fork 到|sub:<fp>→ 连续 review 复用同一 fork 会话 → 主会话计数/快照不变 → conversations map 单值纪律),并经 feat: side-lane regression hardening — pure lane gates, truth tables, canaries, CI lane guard (#2170) #2175 加固(泳道判定真值表 + runtime canary + CI lane guard)。所以「passthrough 不是终态」的判断与仓库最终走向一致;本 issue 的真正增量是 (a) 你在 0.1.185 上仍观察到未拆分,(b) 验收标准 8(UI 树形)。
2. 关键判断:你的复现说明 fork 在你的环境里没触发——这才是待查的根因
你的 dashboard 显示 19 个请求全在同一 session(13→2→16→2 交错、seams×10 记在 main 上)。若拆分生效,dashboard 会是两行:main(约 9 请求、无 seam)+ 一行
|sub:<fp>(web 列表是平铺的,|sub:行会独立出现,不会合并进主行)。而 fork 代码确认包含在 v0.1.185 内(git tag --contains核过),因此你的环境里必有某个条件让谓词漏掉。候选按可能性排序:x-bili-plugin: dsh:拆分谓词要求这个 marker(KDD#9 白名单纪律)。若你 dsh 版本/profile 里 classifyRisk 走另一条 LLM 调用路径、不打插件头,fork 不发生。protocol === "google"时 keying 是 verbatim 的(src/server.ts:2195-2196,personaSystemText 对 google 也取空串)。如果你的 gemini-3.8-flash 端点说的是 Google 原生协议而非 OpenAI 兼容,拆分完全不会触发。3. 需要你补的证据(任一组即可定位)
GET /__bili/status的 JSON——看versionvsdiskVersion/stale(直接裁决候选 1);或/acp面板的 staleness 行。~/.local/state/billion-context/bili.log里任一 2-msg 请求附近的日志行(processTurn: 1 msgs/request: 2 msgs)——[session-…]前缀里有没有|sub:?/__bili/sessions(或 web sessions 页)清单里有没有 id 以|sub:结尾的行?/v1/chat/completions)还是 google-native?4. 方案评估(逐项)
x-bili-request-class):长期方向成立(与 [跟进] 辅助请求(auto-review/classifier)需统一隔离策略——与 #1075 冲突,需 owner 拍板 #1309/[design] 辅助请求的会话身份判定与审查请求自身的压缩 —— #1312 止血后的根治方向 #1314 讨论过的 host-marker 方向同族),但建议暂缓:① 属新增协议/config surface,按仓库配置面纪律需 owner 拍板并映射到既有机制;② 需 DSH 侧配合(跨仓工作);③ 一个具体陷阱——现有x-bili-plugin-agent+SIDE_REQUEST_AGENTS集合的语义是「side request = passthrough」,把 "auxiliary-review" 塞进去正好走到本 issue 反对的路径上;要做,语义必须是「命名子 lane」而不是「side request」。先弄清指纹为何在你环境失手,再看它是否真的必要——指纹路线今天零宿主改动即可工作。|sub:行与主行并列。这是小的 bili 侧改动,值得做(见下)。5. 建议的下一步(明确建议,非选择题)
|sub:lane 显示为父会话的子项(+ 可选在 fork 上记录显式 derivedFrom 链接,对齐 [pi plugin] Prime RLM inline 派生子会话在代理模式下零继承:搜不到也解压不了父会话压缩块(billion-context-pi#531 同场景) #1333 derived-session 模式);② dsh e2e golden lane(tests/e2e/e2e-native-dsh.test.ts)目前没有任何 review/fork 用例,只有单元级 server 测试钉住该行为,补一个端到端形状用例。证据一到我就继续在这个线程推进。
kettly1260 commentedon Oct 6, 2026
@ranxianglei 我按上面的 4 组证据查完了,已经能进一步定位。
结论:不是 stale runtime,也不是 google-native;实际缺口是 DSH persona fingerprint 没有覆盖 Responses wire。
GET /__bili/status:
{
"version": "0.1.185",
"diskVersion": "0.1.185",
"stale": false
}
而且发生问题时的生产日志逐行明确为 [v=0.1.185],因此可排除旧内嵌运行时。
复现 session:
session-a215f0cf-648a-4134-ab96-0b4aa8691429
protocol = responses
clientHint = dsh
upstream = https://ai.sample.com
实际日志:
forward POST -> https:///v1/responses
因此不是 google native。
同一安装环境中 Anthropic DSH 已经存在正常 persona fork:
session-53c1f292-0108-4957-81c8-565abfe11366
session-53c1f292-0108-4957-81c8-565abfe11366|sub:1e893fddc811aa5b
说明 |sub: 机制在本机确实可以工作。
但所有 DSH Responses 会话都仍是 raw session id,没有对应 |sub:。
直接核对 v0.1.185/src/server.ts 后,原因似乎就在当前分支逻辑:
const personaSystemText = protocol === "openai"
? openaiSystemTextForPersona(...)
: protocol === "anthropic"
? systemTextsForSplit.join("\n\n")
: "";
dshPersona && subagentNamespace(...) 也只出现在 anthropic 和 openai conversation 分支。
Responses 分支走的是 instructionsFingerprintApplies(req.headers),而 src/session-id.ts 中这个 allowlist 只覆盖 Codex / Claude-over-Responses,并不包括 DSH。
因此对:
x-bili-plugin: dsh
protocol: responses
当前代码实际上不会执行 DSH persona split。
这与实测完全吻合。相同 raw session 中 system 在两种 persona 之间反复切换:
[fold-reconcile] system prompt changed (3859 -> 13927 chars)
...
[fold-reconcile] system prompt changed (13927 -> 3859 chars)
reviewer:
processTurn: 1 msgs
request: 2 msgs
input ~= 18K-20K
cached = 0
main agent:
processTurn: 69 msgs ...
input ~= 70K
cache hit ~= 90-96%
两者都继续记录在:
session-a215f0cf-648a-4134-ab96-0b4aa8691429
所以我认为 #2203 现在可以从 design discussion 收敛成一个更具体的 parity bug:
DSH persona fingerprint is implemented for OpenAI chat / Anthropic, but not for Responses wire.
建议修复:
Responses + dshPersona 也用 subagentNamespace(..., body.instructions);
同步扩展 rawPersonaIdentity/personaForked;
同步扩展 designNamespaced canary;
给 tests/dsh-persona-fingerprint.test.ts 增加 Responses parity e2e: main raw key -> review |sub: -> repeated review same fork -> main state unchanged。
Google-native 可以作为另一个 parity gap 处理;本次生产复现明确是 /v1/responses。
所以当前不需要新增 host header,也不需要重新设计 derived lane;现有 persona-fingerprint 设计只需要补齐 DSH Responses wire。
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 四组证据非常关键——定位完全正确,已修复。PR: #2232 (Closes #2203)
1. 是什么问题
DSH auto-review 与主会话共用同一 conversation id,而 bili 在 Responses wire 上没有做 persona-fingerprint 分裂——review 请求(固定 REVIEW_POLICY instructions + 新拼装的扁平 blob)在主会话内部走完整管道,持续踩踏主会话的 remembered snapshot / nudge baseline,制造 CACHE SEAM、压缩永不触发。
2. 什么原因导致的
persona-fingerprint 机制本身(v0.1.181 起随 #1916/#1307 上线)只实现了 OpenAI-chat / Anthropic 两条 wire。Responses wire 的 identity 分支走
instructionsFingerprintApplies(),其 allowlist 只含 codex / claude-over-Responses,不含 dsh → 所有 dsh/v1/responses流量落进 verbatim、按 raw id 键控。你的证据链依次排除了 stale runtime(status+日志版本号)、google-native(日志明确/v1/responses)、机制失效(同机 anthropic fork 正常产生|sub:),正好钉死这个 parity gap;根因在 host 侧身份解析,不在 kernel。3. 怎么修复的
parity 补齐,不引入新机制(与你的结论一致:不需要新 host header,也不需要 derived-lane 重设计):
|| (dshPersona && !sideRequestLike)→ review 请求经subagentNamespace(id, instructions)落到<id>|sub:<fp>(这条 wire 的 system carrier 是instructions,对应 openai 的 system message / anthropic 的 system block;kernel 锚定语义不变:首个 system 占 raw key,空 instructions 非锚定);stableSystemAnchorverbatim 分支排除 dsh(!dshPersona)——dsh 从不 stampx-bili-plugin-agent,operator 开启 anchoring 时会吞掉分裂([Feature] Optimize the cache by reorganizing the context. #1085 设计:插件请求本就不参与 anchoring);rawPersonaIdentity扩展到 responses——否则 fork 会以 raw id 记录、从主会话手里抢走 conversations map 条目(Subagent first token stalls 1-2min: withSessionLock covers full forward + slow flash upstream first byte #970/[bug] dsh:side request 先到会抢走 persona 锚点,主会话被 fork 到 |sub:<fp>,原生 compress 永久失败 #2156 同类问题);personaNamespace=true豁免标记。修复后 review 会话拥有独立状态、可独立压缩;主会话前缀保持 byte-stable。
4. 是否有回归问题
逐项审过既有行为:codexTurn trusted-turn 路径未动;codex/claude-over-Responses 指纹逻辑未动(纯 OR 追加);opencode/grok 等非 allowlist 客户端仍 verbatim;side request(小预算+无 tools)仍按原样经
sideRequestLike走 side lane;anthropic/openai lane 未动;google-native 未动(见第 6 问)。唯一有意行为变更:stableSystemAnchor开启时,dsh-responses 旧走 anchored verbatim 路径、新走 persona split——这正是修复方向本身。定向测试 33/33 绿(dsh-persona-fingerprint 全量 + e2e-stable-system-anchor + codex-turn-isolation + side-lane truth-table/invariants + e2e-session-identity),全量回归交给 CI。5. 是否破坏缓存
这正是对缓存的修复:分裂后 review 不再打断主会话前缀——你日志里 cached=0 的 review 请求从此落在自己的 fork 会话,主会话命中率回到 90%+。缓存失效策略(去重键/游标/重试)均未受影响。
6. 是否改了设计方向
没有。这是对现有 persona-fingerprint 设计(KDD#9)的 wire parity 补齐,不是 issue 提议的 derived-lane 重构,也没有引入显式 host header。google-native wire 是同一机制族的剩余面(identity ternary 的 google 分支同样没有 dsh case);按 allowlist 纪律(需流量证据才准入),等出现真实的 dsh-google-native 流量再补,在本 issue 跟踪(同机制同失败域,不另立项)。
7. 是否引入了新的配置
无。无新 env/config/默认值。
回归测试:
tests/dsh-persona-fingerprint.test.ts新增 responses-lane e2e(真实代理管道:main 锚定 raw key → review fork 到|sub:<fp>→ 重复 review 复用同一 fork → 主会话 stats/snapshot/conversations-map 条目全部不变 → 无 instructions 辅助调用 ride raw key)。stash 验证:未修复代码上该测试失败,修复后通过。判定:待 CI 绿灯后合并。合并后请在生产环境复核:dashboard 应出现
<id>(主会话,前缀干净)与<id>|sub:<fp>(review,独立压缩计数)两行独立条目。test: pin the dsh-responses side-lane cells for the #2203 parity fix …
test: pin responses-wire side-request persona boundary (#2203, lane-g…
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 收工状态:CI 25/25 全绿,待人工合并。
PR #2232(分支
2026-10-06_dsh-responses-persona-fork,head21ce73108)最终栈:980fd4e96核心修复:DSH persona fingerprint 补齐 Responses wire(src/server.ts 身份判定 + src/session-id.ts 文档注释 + tests/dsh-persona-fingerprint.test.ts 新增 Responses parity e2e)7af68e4adlane-guard 要求的 truth-table 扩展(responses 协议格 + dsh auto-review 形状不触发 side-lane 的钉死)c3661fff2side-lane 不变量 (E)(并行会话已推入同分支的提交)21ce73108drive-by 小修(见下)Drive-by 小修(独立机制,已立项 #2236):
tests/pi-subagent-registry.test.ts的单槽 fake-Pi Map 会吞掉 #2186(wirePiSubagents,pi.ts:939)注册的第二个session_starthandler,导致 #2185 的 factory-wiring 测试自 #2209 合入起在 master 上红(pristine base bd33b11 复现,与本 PR diff 无关)。修法:fake 改为 per-event handler 数组 + fire-all,与真实 host 的多播行为对齐;本地 10/10,CI 上此前红的三个 test matrix job 由此转绿。注意:存在并行修复 PR #2237(Closes #2234,同一根因同一修法),已在 #2236 交叉引用——owner 二选一即可;若 #2237 先合,#2232 rebase 时直接丢弃该 commit,无内容损失。验证清单:typecheck 干净;定向套件 33/33 + pi-subagent-registry 10/10;stash 证明(新 e2e 在未修改代码上失败、修复后通过);CI 全矩阵 25/25 绿(含 lane-guard、dsh plugin lane、全部 real-client lane)。
合并后请验证(升级下一版本后看 dashboard):① 主会话行保持 raw
<id>,review 请求落到独立的<id>|sub:<fp>行;② 主会话不再出现 CACHE SEAM;③ 主会话 compressionCount 恢复正常累积。有异常随时回帖。合并判定留给 owner:#2232
fix: dsh persona fingerprint parity for the Responses wire (#2203)
test: pin the dsh-responses side-lane cells for the #2203 parity fix …
test: pin responses-wire side-request persona boundary (#2203, lane-g…
ranxianglei commentedon Oct 6, 2026
检测下master是否已经彻底修复这个问题
fix: dsh persona fingerprint parity for the Responses wire (#2203)
test: pin the dsh-responses side-lane cells for the #2203 parity fix …
test: pin responses-wire side-request persona boundary (#2203, lane-g…
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 检测结论:master(c4ae70796)尚未彻底修复——Responses wire 缺口仍在,PR #2232 已 rebase 到最新 master 并与其后的 #2247 设计对齐。
检测过程(全部基于当前 master,非 PR 分支):
src/server.ts身份判定三元组的 Responses 分支仍只查instructionsFingerprintApplies(allowlist 仅 codex/claude)+ plain-proxy 的 stableSystemAnchor;无 dsh 条款。rawPersonaIdentity仍只覆盖 openai/anthropic。即x-bili-plugin: dsh走/v1/responses依旧 verbatim 落在 raw session id——本 issue 的生产复现路径原样存在。AssertionError: 'review request landed on its own forked session');同文件其余 7 个测试(openai/anthropic lane、[bug] dsh:side request 先到会抢走 persona 锚点,主会话被 fork 到 |sub:<fp>,原生 compress 永久失败 #2156 anchor 竞争、allowlist pin)全过——说明 anthropic/openai 的 persona fork 健康,缺的正是 responses wire。PR #2232 现状(head
370e1493e):rebase 到 c4ae707 后把 responses lane 对齐到 #2247 同一机制(dshPersonaNamespace:review blob fork 到|sub:<fp>、model switch 迁移锚点、无 instructions 非锚定)——原方案用的 kernelsubagentNamespace会在 responses wire 上重新引入 #2241 的 model-switch fork 问题,故弃用。drive-by commit 已丢弃(对应修复已经由 #2235 独立进 master)。本地 typecheck 干净 + 定向 48/48(含 #2247 的 continuity 套件与全部相邻身份套件)。CI 快 job 已全部绿(lane-guard、dsh plugin lane、real-client lanes、e2e、theorem),test matrix 与 windows registry 在跑。合并判定留给 owner:#2232
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 补充:PR #2232(head
370e1493e)CI 已 25/25 全绿(含 lane-guard、dsh plugin lane、real dsh headless profile lane、全部 real-client lanes、test matrix 四格、hermetic registry 双平台)。待人工合并:#2232ranxianglei commentedon Oct 7, 2026
现在再检查 检测下master是否已经彻底修复这个问题
fix: dsh persona fingerprint parity for the Responses wire (#2203)
test: pin the dsh-responses side-lane cells for the #2203 parity fix …
test: pin responses-wire side-request persona boundary (#2203, lane-g…
fix: adopt #2271's personaNamespace rename in the dsh-responses clause (
ranxianglei commentedon Oct 7, 2026
[bot] 🏷 重新检测完成(master
86191d6ac,v0.1.187 之后):尚未彻底修复。Responses wire 上的 dsh persona 分叉仍然缺失,修复目前只存在于未合并的 PR #2232。检测方法与证据(两条独立证据链)
代码审查(origin/master
src/server.tsidentity 三元组,Responses 分支):codexTurn → stableSystemAnchor(plain-proxy) → instructionsFingerprintApplies → verbatim;instructionsFingerprintApplies的 allowlist(src/session-id.ts)仍只覆盖 codex / claude-over-Responses,不含 dsh;rawPersonaIdentity仍只有 openai/anthropic 两个 case。x-bili-plugin: dshover/v1/responses依旧按 raw id verbatim 记账 —— 与生产复现路径完全一致。实测(pristine master worktree @
86191d6ac,跑本 PR 的回归测试tests/dsh-persona-fingerprint.test.ts):7/8 通过,唯一失败就是e2e responses lane #2203,断言AssertionError: 'review request landed on its own forked session'—— 与上一轮在 c4ae707 上的结果一致。openai/anthropic 两个 lane 的 persona fork 测试均通过,说明其他 wire 没问题,缺口只在 Responses。master 这段时间的相关进展(方向对,但没覆盖到本问题):
personaNamespace并扩展到 codex / claude-over-Responses 的 instructions lane;两者都不触碰 dsh-over-Responses 这个格子。
PR #2232 状态:已按你的要求在今日重新 rebase 到当前 master(
86191d6ac),并适配 #2271 的重命名——新 Responses 子句现在调用泛化后的personaNamespace(...)(与 anthropic/openai/codex-instructions 三个 lane 同一机制),另修了 rebase 带入的一行缩进漂移。新 head31adfb4d7:typecheck 干净、定向套件 48/48、pristine master 上该 e2e 仍失败(证明是真实回归测试)、CI 正在跑。diff 收敛为 src/server.ts 三处 hunk + session-id.ts 文档注释 + 3 个测试文件。结论:合并 #2232 后此问题才算彻底修复(google-native wire 的同类缺口仍按 KDD#9 evidence-per-client 纪律留在本 issue 跟踪,需该 host/wire 形状的流量证据后再启用)。CI 全绿我会再报一次。
ranxianglei commentedon Oct 7, 2026
[bot] 🏷 CI 跟进:PR #2232 新 head
31adfb4d7(rebase 到 master86191d6ac+ #2271 重命名适配)全矩阵 27/27 通过,含 lane-guard、e2e、hermetic registry(ubuntu+windows)、real-client 各 lane、4 组 test matrix。当前状态小结:
<id>|sub:<fp>,模型切换走 anchor 迁移不分叉);等人工合并即可收工。
Merge pull request #2232 from ranxianglei/2026-10-06_dsh-responses-pe…
fix: key dsh personas on the google lane like the other wires (#2730)
fix(ranxianglei#4438): route dsh auto-review requests off the main se…