Skip to content

[PR] fix: gate identity-orphan on a unique full-prefix replay | 修复 identity-orphan 对共享开场白匿名请求的误报 - #4279

Closed
yanhuojiyusheng wants to merge 1 commit into
ranxianglei:masterfrom
yanhuojiyusheng:2026-10-22_hermes-auxiliary-identity
Closed

yanhuojiyusheng wants to merge 1 commit into
ranxianglei:masterfrom
yanhuojiyusheng:2026-10-22_hermes-auxiliary-identity

Conversation

@yanhuojiyusheng

Copy link
Copy Markdown
Contributor

Closes #4278.

问题与根因

Hermes 车道出现 identity-orphan 误报(0.1.204,9c94476f-dirty):插件主请求正常进行,一个约 1.3 KiB、ua="hermes-agent"、无 bili 插件头的匿名 openai 请求在主回合结束约 0.1 秒后到达(task=标题生成 的辅助请求机制完全吻合,但日志无 task/system 字段,未坐实),用户内容是「你好」「你是谁」这类开场白,随后原会话被记为 identity-orphan。

根因在诊断判定本身:

  • neutral projection 去掉前导 system/developer 后,匿名辅助请求(标题生成 system + 一句开场白)与主会话可能只剩同一句用户输入;「你好」在日志中匹配到 33 个候选会话。
  • 旧 orphanSuspect 只比较候选深度位置上的 normalized tail fingerprint:不验证完整前缀、不要求候选唯一,不同会话同开场白甚至只有末句相同都会命中。
  • 长度门槛挡不住短开场白:24 的下限是序列化字符串长度,{"content":"你好","role":"user"} 已 30 字节;legacy MIN_NORM_LEAF_LEN = 32 不约束 neutral 路径。
  • 事件措辞把「内容相关」升级成确定的故障:client identity lost; their fold ledgers are now orphaned。而真实日志显示原会话告警后仍以原 conversation id 正常继续。

方案

只收紧诊断,不动 resolution/adoption(#1486 保持不变,仍然新 mint pfa-*):

  • orphanSuspect 候选必须同时满足:
    • identified 会话;
    • depth >= MIN_RESUME_PREFIX (8)(复用 resume 证据下限常量);
    • 在候选自己的 hash domain(hv2 neutral / hv1 raw)下,完整前缀的累积链 hash 一致——《chainHashes 逐步累积,hashes[depth-1] === entry.tailHash 等价于前缀逐字节一致》;
    • 匿名请求深度落在 append bound(ALIGN_TAIL_APPEND_MAX = 64)内;
    • 唯一候选——出现第二个候选即放弃记录。
  • 日志、conflict 事件与修复建议改为「possible identity loss」:匿名重放线索,不断言原客户端已停用原 ID、不断言 fold continuity lost,明确原会话状态保留、旧账本不清理。

取舍(诚实边界)

门槛提高后是保守漏报:不足 8 个中性轮次、前缀被改写、或匿名请求追加超过 64 turn 的真实身份丢失不再产生该诊断。只影响诊断覆盖面,不影响请求路由与状态恢复。

不采用

  • 不修改 Hermes 源码、不改 bili 的 hermes 插件(受限范围)。
  • 不给辅助请求注入主会话 ID:辅助请求的长期身份应同时表达归属与用途,只补 ID 会把标题任务混进主对话的压缩状态,另行考虑。
  • 不调整辅助请求路由:现有 side-request 分流(小预算 ≤200)在 orphan 检测之后才识别标题,且 Hermes 标题输出上限 512,本 PR 不动该顺序。
  • 不清理历史 identity-orphan 事件,旧条目按既定策略保留。

验证

基于 94f75cce(当前 upstream/master)验证,提交为 4b7d5cf:

  • 7 个相关 suite 83/83 通过:resolver 单测(共享开场白三类含长公共指令、不同前文同末句、depth 7 不报/8 报、多候选歧义、legacy hv1 raw 域、追加边界)+ mock proxy 集成(主→辅助→主流程无告警、messageRefs 无变化、原 ID 可继续;完整匿名重放仍记录一条事件且 compression 状态不变)。
  • npm run typecheck、npm run build、git diff --check 通过。
  • 真实客户端 E2E 未在本机运行;完整回归以远程 CI 为准。

- prefix-affinity.ts: orphanSuspect 候选必须 identified、depth >= MIN_RESUME_PREFIX(8)、在候选自身 hash domain(hv2 neutral / hv1 raw) 下累积前缀链 hash 一致、深度在 ALIGN_TAIL_APPEND_MAX(64) 内,且唯一;出现第二个候选不记录。移除只比较 normalized tail fingerprint 的旧判定。
- server/handle.ts: identity-orphan 事件与 warn 日志改为 verified full history prefix / possible identity loss; original session state retained,删除 client identity lost 与 fold continuity lost 的断言。
- conflict-watch.ts: identity-orphan 建议改为匿名重放线索,不再断定原客户端停用原 ID 或压缩连续性已断。
- tests: 共享开场白(你好/你是谁/你好啊?/长公共指令)、不同前文同末句、depth 7 边界与 8 通过、多候选歧义、legacy hv1 raw 域、跨协议重序列化、mock proxy 主→辅助→主无告警且原 ID 可继续、完整匿名重放仍记录。

Fixes ranxianglei#4278
@ranxianglei

Copy link
Copy Markdown
Owner

(ai: zhipuai-lb/glm-5.3)

已并入合并列车 #4525(master 6d7c587,合并方式 merge commit,提交保留原作者署名)。本 PR 关单收尾;若列车中对应提交出问题,回滚点为 #4525 单提交 revert。

感谢 @yanhuojiyusheng 的贡献——你的提交以原作者署名随列车进入 master(合并方式为 merge commit),仓库贡献者列表可见。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants