Repository navigation
[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
ranxianglei wants to merge 11 commits into
Conversation
…_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).
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g billion-context@0.0.6173-pr.4615.b59dad8This exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr4615.tgz
npm install -g packageInstall instructions are refreshed on each push. |
…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.
(ai: vllm-qwen/qwen3.8-27b) CI auto-fix lane(attempt 2/2): 判定:继承性失败,非本 PR 引入。 master tip 按几行级小修调度纪律 + 风暴内 #4607/#4595/#4540/#4618 先例,本分支以独立标注 commit 八问
收工判定:本 PR 侧唯一红条(unused-exports)已消除。若重触发后仍见 11 个 test 分片红,那是 #4599 盘点第 2 条 LIVE_FILES tripwire(继承,需 #1248 并发评审、归 #4606 集中修),不在本 PR 范围——等 #4606 合入后 rebase 即可全绿。 |
(ai: vllm-qwen/qwen3.8-27b) CI auto-fix lane(attempt 1/2):本次转发是陈旧通知,当前 head 上的 证据(git + GitHub API):
判定:报告的 八问
收工判定:本 PR 侧 |
(ai: vllm-qwen/qwen3.8-27b) 查重:不重复——本 PR 是 #2938 Tier-1 增量 1(ingress)的在途形态,接替被孤儿清理误关的 #2981(同分支同提交,非并列重复);diff 不触及 #4599 CI 总控域。 标签: 审核结论代码本身干净、测试有牙、可合;当前唯一红条是继承自 master 的 CI 基建红(#4599 第 2 条 LIVE_FILES tripwire),非本 PR 引入。 另有一处 PR 描述与实际 diff 的范围不符,合并前需补正。 独立验证(未照抄 issue 侧结论):
八问
需处理项(合并门槛)
收工判定:代码可合、质量达标(测试有牙、双向门控齐全、wire fidelity 钉死)。当前不可直接合的唯一阻塞 = 继承性 CI 红(等 #4606/#4599)+ PR 描述范围补正;两者皆非本 PR 代码缺陷。 |
(ai: vllm-qwen/qwen3.8-27b) 结果(完成确认):本次 CI 转发(run 处置:报告项已绿 → 本轮零代码改动、不重复推送(再推 = 空操作)。残留的 11 个 test 分片红为继承性 LIVE_FILES tripwire(#4599 盘点第 2 条,需 #1248 并发评审、归 #4606 集中修),属「需设计决策/非小修」,按 lane 规则停手并给结论。完整八问见上一条评论。本 lane 收工,#4615 侧无需再动。 |
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.
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_idsbody 字段契约——无条件剥离(保留命名空间: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.tsmanifest 断言。行为变更(旧→新)
_bili_toolcall_ids的请求(含未标记第三方流量)零 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),绝不猜。session.metadata.hostIdBindings,上限 50 000 条、超限整体清空;插件每请求重戳,恢复 ≤1 请求)映射到一个在本轮频道中恰好出现一次且在缺失锚点中也恰好对应一个的 host id、且角色一致时认领。双重唯一性 + 角色门 = 错认护栏(owner rule 2026-10-12:hash 二等公民,但错认仍是最贵的失败)。plan.byHost计数 + drift 日志段N by host id;所有早退路径带byHost: 0。本 head 验证:typecheck clean;定向 116/116(fold-reconcile / issue2938-hostid-claim / hostid-channel / plugin-protocol / e2e-proxy-smoke);全量矩阵 = 本 head 的 CI。
剩余增量(issue 保持打开)
按一 issue 一 PR 纪律(#2981 不可复活,本 PR 为其唯一在途形态),增量以标注 commit 追加到本分支;需要拆分请说。