Skip to content

[PR] feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 Increment 1; supersedes erroneously closed #298 | feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 增量 1;接替误关的 #2981) - #4615

Open
ranxianglei wants to merge 11 commits into
masterfrom
2026-10-13_hostid-sidechannel

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Part of #2938 — Tier 1 增量 1(ingress 半边)。本 PR 接替 #2981:原 PR 基于 #2815 集成栈切出,栈合入 master(2026-10-13)后原 PR 被孤儿清理误关(未合并、无说明);因 base 分支已删,GitHub 拒绝重开(「state cannot be changed」),故以同一分支同一提交开此接替 PR——提交内容逐字未变,仅 rebase 到 master @ 146b34f(v0.1.206)并重新验证。

本 PR 做什么

把宿主侧稳定 tool-unit id 旁路通道引入请求管线(代理侧 ingress;尚不含 fold 语义):

  • src/hostid-channel.ts(新):_bili_toolcall_ids body 字段契约——无条件剥离(保留命名空间:prepare 路径会重新序列化 parsed 对象,任何残留值都会泄漏到上游 provider);marker 门控的消费;well-formed 门控(≤10k 非空字符串数组)+ 与 wire-neutral tool-unit 计数的一致性校验(与 affinity-neutral.ts 同一 walk,四线通用);任何失配 ⇒ 该请求整体忽略通道(honest degrade,永不劣于现状)。
  • src/server/handle.ts:body parse 处单一 chokepoint(v1internal 解包之后、chain-checkpoint 与所有 prepare 之前;剥离后按整个 body 形状重序列化——v1internal 时含外层 envelope——使 verbatim-forward 路径同样字节干净)+ runPrepare 内 latest-wins 持久化到 session.metadata.hostToolCallIds(absent/rejected 即清除——停止的插件不可能留下陈旧映射)。rebase 时新增一处适配:[bug] bili antigravity (#2115 / #2134) 真机实测必现 HTTP 400:CloudCode v1internal 请求/响应信封未拆包 + sessionId 恒为 FNV-1a 空串哈希 #3129 的 v1internal envelope 解包与本 chokepoint 同位冲突,解法 = 解包先、消费后(校验看到的是与 pipeline 相同的最终视图)。
  • src/plugin.ts:manifest 广告 capabilities.hostIdChannel: { bodyField, maxUnits }——插件必须 capability-gate 打戳(旧代理原样转发未知顶层字段 ⇒ 未 gate 的插件会把 id 列表泄漏给 provider)。
  • 测试:tests/hostid-channel.test.ts(17 单测:门控矩阵/四线计数/malformed/miscount/cap)+ tests/hostid-ingress-contract.test.ts(真代理+假上游,9 case × 4 线:字段永不上游、剥离后会话完好)+ tests/plugin-protocol.test.ts manifest 断言。
  • PLUGIN.md:协议小节(语义 + 强制 capability gate + 兼容性说明)。

行为变更(旧→新)

路径 旧 新 原因
任意 JSON body 带 _bili_toolcall_ids 的请求(含未标记第三方流量) 字段经 prepare 重序列化到达上游 provider 转发前无条件剥离 保留命名空间是安全不变量;旧行为是意外泄漏面
已标记插件请求携带 malformed/miscount 值 N/A(字段不存在) 剥离 + 该请求忽略通道,warn 日志一次 honest degrade

零 kernel 改动、零 config/env/CLI surface、无 golden 变化。wire fidelity:转发 body 除该保留字段外逐字节不变(契约测试钉住)。

验证(rebased head 本地定向;CI 跑全量矩阵)

typecheck clean;hostid+plugin-protocol 36/36;e2e-proxy-smoke+fold-reconcile 73/73。

增量 2:fold-reconciliation 认领路径(8b9d7db,已落地)

  • zipHostUnits():把入站 tool-unit 序列(四条 wire 上每个 call/result 块一条 CoreMessage,transcript 顺序)与频道列表逐位 zip;数量不符或出现重复 host id ⇒ 整请求诚实降级(undefined),绝不猜。
  • 新 Pass 1.25(位于 Pass 1 精确 toolCallId 与 Pass 1.5 twin 之间):缺失的 covered id,当其持久绑定(derived raw id → host id,每次 pass 由 fresh zip 累积进 session.metadata.hostIdBindings,上限 50 000 条、超限整体清空;插件每请求重戳,恢复 ≤1 请求)映射到一个在本轮频道中恰好出现一次且在缺失锚点中也恰好对应一个的 host id、且角色一致时认领。双重唯一性 + 角色门 = 错认护栏(owner rule 2026-10-12:hash 二等公民,但错认仍是最贵的失败)。
  • plan.byHost 计数 + drift 日志段 N by host id;所有早退路径带 byHost: 0。
  • 回归测试钉住 dsh plugin lane: the host already has a stable MessageId — a per-request identity side-channel would eliminate the #2396 family of fold-identity drift #2938 家族精确形状:id 重铸 + 文本改写同时让 Pass 0/1/1.5/2 全部失效时,频道认领全部 unit;无频道视图时行为与 legacy 字节级一致(负向断言);歧义/角色门场景一律拒绝。

本 head 验证:typecheck clean;定向 116/116(fold-reconcile / issue2938-hostid-claim / hostid-channel / plugin-protocol / e2e-proxy-smoke);全量矩阵 = 本 head 的 CI。

剩余增量(issue 保持打开)

  1. dsh-native capture(llm/stream waterfall → beforeSend body 注入,capability-gated 打戳)— 增量 3,需 @beicause 在其新版 dsh-llm build 上的运行时验证(投影后顺序对齐)。

按一 issue 一 PR 纪律(#2981 不可复活,本 PR 为其唯一在途形态),增量以标注 commit 追加到本分支;需要拆分请说。

ework-agent added 2 commits October 25, 2026 03:39
…_ONLY

Review fix for #2981: HostIdDecision is only referenced within
hostid-channel.ts (as consumeHostIdChannel's return type); the exported
name failed scripts/check-unused-exports.mjs (exit 1), which would fail
the ci.yml unused-exports job when this stack lands on master. Dropped
the leading export per the guard's own remediation; no consumer imports
it by name (typecheck + hostid/plugin-protocol suites re-run green).
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-13_hostid-sidechannel (ac5c0d6)

Latest build — install this exact version

npm install -g billion-context@0.0.6173-pr.4615.b59dad8

This exact version is immutable and reproducible. The rolling pr tag tracks the newest test build across all PRs.

Recent builds (commit → version)

commit version build
ac5c0d6 billion-context@0.0.6173-pr.4615.b59dad8 build
1580e4c billion-context@0.0.6088-pr.4615.d4096d2 build
130baf5 billion-context@0.0.5990-pr.4615.d0d221c build
82043b2 billion-context@0.0.5870-pr.4615.360b255 build
1f58294 billion-context@0.0.5803-pr.4615.ba28ad5 build
63b4e07 billion-context@0.0.5651-pr.4615.8a2b612 build
fa1ee96 billion-context@0.0.5595-pr.4615.ef54963 build
8b9d7db billion-context@0.0.5590-pr.4615.1fcb195 build
bd5d87e billion-context@0.0.5578-pr.4615.8cf0a3d build

Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr4615.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei ranxianglei changed the title feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 增量 1;接替误关的 #2981) [PR] feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 增量 1;接替误关的 #2981) Oct 24, 2026
@ranxianglei ranxianglei changed the title [PR] feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 增量 1;接替误关的 #2981) [PR] feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 Increment 1; supersedes erroneously closed #298 | feat: host-stable tool-unit id side channel — ingress half (#2938 Tier-1 增量 1;接替误关的 #2981) Oct 24, 2026
ci-check added 2 commits October 25, 2026 04:56
…increment 2)

Adds the claim side of the host-id side channel (owner rule 2026-10-12:
order-centric, hash second-class — a host self-minted id is a first-class
verification token, strictly stronger than same-content twin guessing):

- zipHostUnits(): zips the inbound tool-unit sequence (messages with a
  non-empty toolCallId, transcript order — one CoreMessage per call/result
  block on all four wires) against the channel list; any count mismatch or
  repeated host id degrades the whole request honestly (undefined), never
  guesses.
- fold-reconcile Pass 1.25 (between Pass 1 exact toolCallId and Pass 1.5
  twin): missing covered ids are claimed when their persisted binding
  (derived raw id -> host id, accumulated in session.metadata.hostIdBindings
  by reconcileFoldCoverage from each pass's fresh zip, capped at
  HOSTID_BINDINGS_CAP with clear-on-overflow) maps them to a host id that
  appears EXACTLY once in the fresh channel AND exactly once among the
  missing anchors, and the roles agree. Double-uniqueness + role gate =
  misattribution guard; ambiguity refuses all involved.
- plan.byHost counter + drift-log segment "N by host id"; early returns
  carry byHost: 0.

Tests: tests/issue2938-hostid-claim.test.ts (zip semantics + compound-drift
regression: id re-mint + reworded texts starve every content/hash pass,
channel claims all four units; negative gate without view is byte-identical
to legacy behavior; ambiguity and role-gate refusals). One existing
deepEqual result literal in tests/fold-reconcile.test.ts gained byHost: 0
(new contract field).
…ter-red (#4599)

master tip 146b34f is red on unused-exports for this exact finding (the #4545 train added this type-only export; the 4d34abf de-export sweep missed it). PR #4606 carries the canonical fix; per the few-line-fix coordination rule this branch carries the identical one-line de-export so its check matrix regains signal now. Drop this commit when rebasing onto master after #4606 merges.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

CI auto-fix lane(attempt 2/2):unused-exports 红已修,新 head fa1ee9605。

判定:继承性失败,非本 PR 引入。 master tip 146b34f27 自身即红在同一报错行(INTERNAL_ONLY src/agent/client-build-note.ts: ClientBuildCheck)——#4545 train 引入的 type-only export 被 4d34abfaf 的去导出清扫漏掉(#4599 盘点第 1 条)。本 PR diff 不触及该文件、base==master;已在不含本 PR 改动的干净 origin/master worktree 本地复现同一门禁输出确认。规范修复在途 = PR #4606(提交 1 同款去 export),owner 合并后各继承红 PR rebase 即绿。

按几行级小修调度纪律 + 风暴内 #4607/#4595/#4540/#4618 先例,本分支以独立标注 commit fa1ee9605 带上同一行去 export(让本 PR 检查矩阵立即恢复信号);#4606 合入后 rebase 时丢弃此 commit。本地门禁 ✓ unused-export gate: clean (6 waived)。

八问

  1. 是什么问题:CI unused-exports 门禁红——ClientBuildCheck 带 export 却只在本文件内使用(判 INTERNAL_ONLY)。
  2. 什么原因导致的:master 侧 born-red——[PR] dsh lane: note in-session when running an unverified @deepseek-ai/dsh client build (soft, exact-match) #4545 train 引入该 type-only 导出、4d34abfaf 去导出清扫遗漏;与本 PR 内容无关(纯继承)。
  3. 影响范围与严重程度:仅检查矩阵信号级(所有 rebase 到该 master 的 PR 都继承),非用户侧功能缺陷;严重程度低(CI 信号,非产品行为);本 PR 自身代码无此问题。
  4. 怎么修复的:去掉该 type 声明的前导 export(一行,type-only、零外部引用,全仓 grep + 门禁扫描双重确认);与规范修复 [PR] fix(ci): clear the two master-red gates in one branch — unused-exports (#4602) + the #3890 LIVE_FILES tripwire (#4604) #4606 提交 1 逐字同法。
  5. 是否有回归问题:无。去 export 不改变任何运行时行为(type-only 符号,打包器本就剥离类型);全仓无任何 import 引用它。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:没有。
  8. 是否引入了新的配置:没有。

收工判定:本 PR 侧唯一红条(unused-exports)已消除。若重触发后仍见 11 个 test 分片红,那是 #4599 盘点第 2 条 LIVE_FILES tripwire(继承,需 #1248 并发评审、归 #4606 集中修),不在本 PR 范围——等 #4606 合入后 rebase 即可全绿。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

CI auto-fix lane(attempt 1/2):本次转发是陈旧通知,当前 head 上的 unused-exports 已绿,无新改动可推。按 lane 规则(需设计决策/非小修)停手并给结论,不重复提交。

证据(git + GitHub API):

  • 转发指向 run 40127288294,其 head_sha = bd5d87e9e(created 2026-10-24T19:52Z)——该 commit 已落后当前 head 两个提交。run ID 40127288294 < 40132090189,时间上也早于我上一轮处理的 run。
  • 当前远程 head = fa1ee9605(上一轮推送的修复)。历史:fa1ee9605(de-export ClientBuildCheck)← 8b9d7dbbe(increment 2)← bd5d87e9e(de-export HostIdDecision)← 8b162ff40(PR 主体)← 146b34f27(master base)。
  • 在当前 head fa1ee9605 查 live check-runs:unused-exports = success;static-gates 与全部 guard(kernel / pi-subagents / lane / config-surface / docs-sync / version / lock-sync …)全绿。
  • 远端树第 32 行确为 type ClientBuildCheck = {(export 已去),与本地 node scripts/check-unused-exports.mjs → ✓ unused-export gate: clean (6 waived) 一致。

判定:报告的 unused-exports 红已被上一轮 fa1ee9605 覆盖,当前 head 该项为绿。本轮零改动,不重复推送。

八问

  1. 是什么问题:CI 转发报 unused-exports 红——但失败发生在旧 head bd5d87e9e,不是当前 head。
  2. 什么原因导致的:陈旧/乱序通知。bd5d87e9e 时 ClientBuildCheck 尚未去导出(继承自 master 的 born-red,CI Control Center: Centralized CI Failure Handling & Status Sync (Comment all CI issues here; do not open new issues) | CI 总控: CI 失败集中处理与状态同步(所有 CI 问题在此评论, 勿开新 issue) #4599 盘点第 1 条);该点已由 fa1ee9605 修复。
  3. 影响范围与严重程度:报告项本身已无影响(当前 head 绿)。真正残留的是 11 个 test 分片红——继承自 master 的 LIVE_FILES tripwire(CI Control Center: Centralized CI Failure Handling & Status Sync (Comment all CI issues here; do not open new issues) | CI 总控: CI 失败集中处理与状态同步(所有 CI 问题在此评论, 勿开新 issue) #4599 盘点第 2 条:tests/issue3890-parent-gone-confirm-drain.test.ts 未登记进 scripts/run-ci-tests.mjs → pretest SPAWN_RE 中止、零测试运行),非本 PR 引入。
  4. 怎么处置的:报告项已绿,不重复修。残留 test 分片红属需设计决策/非小修类——要 tests/claude-native.test.ts linux live-E2E subtests fail/hang in shared multi-agent sandboxes #1248 并发评审 + 归 [PR] fix(ci): clear the two master-red gates in one branch — unused-exports (#4602) + the #3890 LIVE_FILES tripwire (#4604) #4606 集中修,故按 lane 规则停手并给本结论,不在本分支硬改。
  5. 是否有回归问题:无。本轮零代码改动;fa1ee9605 只是 type-only 去导出(打包器本就剥离类型),不可能触发 test 分片的 pretest-harness 中止。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:没有。
  8. 是否引入了新的配置:没有。

收工判定:本 PR 侧 unused-exports 已绿(当前 head fa1ee9605)。剩余 11 个 test 分片红为继承性 LIVE_FILES tripwire,待 #4606 合入 + #1248 并发评审后 rebase 即解——不在本 auto-fix lane 范围。本 lane 到此为止。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

查重:不重复——本 PR 是 #2938 Tier-1 增量 1(ingress)的在途形态,接替被孤儿清理误关的 #2981(同分支同提交,非并列重复);diff 不触及 #4599 CI 总控域。

标签:dsh / scope/wiring / p3(功能类非缺陷;主车道 dsh、请求管道协议接线;increment 3 落地前无用户侧影响故 p3)。已保留原 pr 标。

审核结论

代码本身干净、测试有牙、可合;当前唯一红条是继承自 master 的 CI 基建红(#4599 第 2 条 LIVE_FILES tripwire),非本 PR 引入。 另有一处 PR 描述与实际 diff 的范围不符,合并前需补正。

独立验证(未照抄 issue 侧结论):

八问

  1. 是什么问题:把宿主侧稳定 tool-unit id 旁路通道引入请求管线(ingress 半边)+ fold-reconcile 精确 id 认领(increment 2)。
  2. 什么原因导致(需求侧):[Bug][Prime/Responses] provider switch rewrites composite tool IDs and reintroduces compressed history #2396 家族——模型切换重铸 tool-call id / reasoning 扁平化使 fold 身份对不上,只能靠内容启发式猜;宿主自带稳定 id 是 representation-invariant 的一等身份源(owner 规则 2026-10-12)。
  3. 影响范围与严重程度:功能类新增,无现存缺陷面。increment 3(dsh 打戳)未合入前无任何真实客户端带该字段 ⇒ 现状零行为变化;通道本身"有则更准、无则退 legacy"纯增益。p3(基础设施预埋)。
  4. 怎么实现:保留命名空间 _bili_toolcall_ids 无条件剥离(任何 prepare 之前,防泄漏上游)+ marker 门控消费(仅 x-bili-plugin)+ well-formed/miscount 校验(失配即整请求 honest degrade);latest-wins 持久化到 session,absent/rejected 即清除(停摆插件不留陈旧映射);fold-reconcile 新增 Pass 1.25 精确 host-id 认领,双唯一性门(一个 host id 同时撞两个消失 id 或两个新单元 ⇒ 双双拒认)+ role 门,歧义一律拒认(MESSAGE-IDENTITY.md:错配最贵)。
  5. 是否有回归:审过既有行为——(a) 转发 body 除剥离该字段外内容保持(契约测试捕获假上游真实收到的 body,断言字段名与 payload 均不出现、openai 会话 6 条消息剥离后完好);(b) 无 view 时 fold-reconcile 走纯 legacy(negative-control 钉住 byHost=0/claims=0);(c) 两 walk(raw wire vs prepared transcript)计数不一致 ⇒ zip 返 undefined ⇒ 整请求降级 legacy,绝不猜。高危模式逐项:无语义漂移、无 fail-fast 变吞错、无阈值/时序漂移,输出格式仅增 drift log 一行 N by host id。未发现回归。
  6. 是否破坏缓存:不涉及压缩触发/前缀缓存;新增仅 session.metadata.hostIdBindings(50k cap、溢出整清、absent/rejected 清除),纯附加、向后兼容。
  7. 是否改设计方向:没有——沿用既有 order-centric reconcile 阶梯,host-id 作为最强 channel 插在 Pass 1(id-exact)之后、twin pass 之前,不动消息身份教义。
  8. 是否引入新配置:零 config/env/CLI/golden。唯一新增持久化面 = session.metadata.hostIdBindings(见第 6 问),非配置项。

需处理项(合并门槛)

收工判定:代码可合、质量达标(测试有牙、双向门控齐全、wire fidelity 钉死)。当前不可直接合的唯一阻塞 = 继承性 CI 红(等 #4606/#4599)+ PR 描述范围补正;两者皆非本 PR 代码缺陷。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

结果(完成确认):本次 CI 转发(run 40127288294,head bd5d87e9e)是陈旧/乱序通知——该 head 已落后当前 head fa1ee9605 两个提交。经 git + GitHub API 核实:当前 head fa1ee9605 上 unused-exports 已绿(success)、全部 guard/static-gates 绿;远端树第 32 行确为去导出后的 type ClientBuildCheck = {,与本地门禁 ✓ unused-export gate: clean (6 waived) 一致。

处置:报告项已绿 → 本轮零代码改动、不重复推送(再推 = 空操作)。残留的 11 个 test 分片红为继承性 LIVE_FILES tripwire(#4599 盘点第 2 条,需 #1248 并发评审、归 #4606 集中修),属「需设计决策/非小修」,按 lane 规则停手并给结论。完整八问见上一条评论。本 lane 收工,#4615 侧无需再动。

ci-check added 7 commits October 25, 2026 10:09
master window commits 293ae65/de5e03659 bumped kernel/package.json to
0.0.165 without regenerating the lockfiles; lock-sync re-resolution then
rewrites the stale recorded versions (root 0.0.163, kernel 0.0.164) and
fails. Pure recorded-version sync via npm install --package-lock-only;
no dependency or semantic change.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant