Skip to content

fix(responses): warn when stripping previous_response_id without rebuilding referenced history (#1954) - #1976

Merged
ranxianglei merged 2 commits into
masterfrom
2026-10-03_responses-chain-warn-1954
Oct 3, 2026
Merged

ranxianglei merged 2 commits into
masterfrom
2026-10-03_responses-chain-warn-1954

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

范围(Scope)

本 PR 为 #1954 落地 approach A —— 可见性改进,不修复 #1954。

#1954 的根因(bili 的 Responses adapter 是无状态重放压缩器,无法物化 previous_response_id 引用的历史)仍然存在;完整 chaining 支持另立 feature #1973。本 PR 只让「丢历史 + 仍返回 200」这件事不再静默。

行为(Behavior)

当删除一个非空 previous_response_id 时,两条路径现在各打一条 warn:

  • HTTP 路径:src/server.ts prepareResponses
  • loop adapter:src/loop/adapter-responses.ts buildRequest

告警条件只判断 id 本身是否非空,不判断显式 store:true —— 因为 Responses 默认存储响应,省略 store 时上游仍能按 id 解析被引用响应;仅看 store 会漏掉最常见情形。

转发字节不变:仍然删除 id、仍然转发、仍然返回 200。delta(增量)续接请求依旧会丢失其引用历史——本 PR 只是让这次丢失不再静默。

Config surface

无新增配置。ACP_KEEP_RESPONSE_ID 为既有变量,语义未变(=1 时保留 id 且不告警)。

行为变更披露(Behavior-change disclosure)

无既有可观察行为变化。唯一新增是一条 warn 日志行(此前该场景完全静默)。未改阈值 / 默认值 / 时序 / 输出格式 / wire shape。

测试

新增 tests/responses-previous-response-id.test.ts:

typecheck + 定向测试(responses-previous-response-id + loop-adapters)全绿,build 通过。

注:HTTP 端到端用例必须用 log:true 启动 server —— handler 的 log() 在 opts.log 为假时于 logMsg 提前返回,不会到达 logger 的 capture 钩子(见 src/server.ts logMsg)。这是本次调试定位到的测试侧不变量,已在用例中注释说明。

两个过渡方案(评估,未实现,交由维护者决策)

  1. 重写前拒绝:声明压缩通道不支持非空 previous_response_id,在会话更新 / 历史重写前拒绝这类请求。优点是不用猜 payload 是否为 delta;但会改变「full replay + id」这类当前已正确处理情形的兼容行为,需维护者明确选择并给迁移方式;错误信息应要求客户端重发完整 input/output 历史(而非仅去 id 重发原 delta)。属安全边界,非 chaining 支持。
  2. 原生语义旁路通道:保留原生 instructions/input/ID 与路由语义、不经 bili 上下文管理、需验证工具续接等行为。仅在重写流程末尾保留 ID 不等价于这个通道。尚未实现 / 验证。

两者都属行为变更 / 架构决策,建议并入 #1973 的设计讨论统一拍板。

关联:#1954(可见性,本 PR)、#1973(完整 chaining 支持)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 收到,开始 review PR #1976(direction gate → 回归 → 代码/测试/diff)。CI 已全绿(ubuntu/windows 22+24、release)。拉分支核对代码中,结论稍后按结构化七问给出。

@ranxianglei
ranxianglei force-pushed the 2026-10-03_responses-chain-warn-1954 branch from 1f2e4bc to 5d2299a Compare October 3, 2026 08:40
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-03_responses-chain-warn-1954 (5d2299a)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.1993-pr.1976.fcb8433

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

Option B — Download artifact

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

Install instructions are refreshed on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

Review 完成。结论:可合并(等剩余 CI test matrix 跑绿即可,预期无虞)。

审核过程

① 方向关(过):PR 与 owner 在 #1954 的拍板逐条吻合——approach A 只做可见性、不改转发字节、不修根因(chaining 归 #1973);warn 只判 id 非空不看 store(Responses 默认存储,只看 store 会漏最常见情形);覆盖两条路径;codex 措辞为「an observation, not a proof」。#1954 保持 open 正确。

② 回归审查(逐项过):

  • delete/forward/200 行为逐字节不变,唯一新增是一条 warn 日志行——无阈值/默认值/时序/wire shape 漂移;
  • ACP_KEEP_RESPONSE_ID=1 语义未变(保留 id 且静默);
  • 第三个 strip 点核查:src/reasoning-guard.ts:211(nextRoundBody)也删 previous_response_id,但其 rounds 2+ 以 [...origInput, ...replayTail] 全量重放语义重建、且位于 prepareResponses 已告警 strip 的下游——不是独立静默丢失路径,无需第四告警点,「两条路径」覆盖声明成立;
  • 测试注释里 log:true 不变量核实属实:src/server.ts:7255-7258 logMsg 在 opts.log 假时提前返回;生产默认 true(src/config.ts:1102),warn 默认可达 tee logger;
  • stale-base 冲突(本次 review 实际发现并修复的问题):分支切出后 master 前进了 11 个提交(DSH: 切换模型后,preflight 在窗口远未满时提前触发压缩 #1933 preflight calibration 等改了 src/server.ts 同一处 util import 行),GitHub mergeable_state=dirty 是真实冲突而非元数据过期。已 rebase 到当前 master:唯一冲突按双方意图 union 解决(master 的 applyEstimateCalibration/normalizeUpstreamOrigin + 本 PR 的 strippedResponseIdWarning)。rebase 后本地验证全绿:typecheck ✓、定向测试 42/42(responses-previous-response-id + loop-adapters)✓、build ✓,已推回更新 PR head(1f2e4bce → 5d2299a),现 mergeable: True。

③ 代码审查:新 helper src/util.ts:62 strippedResponseIdWarning(prevId: unknown): string | null——缺省/空串/非字符串返回 null,非空字符串返回点名该 id、带 #1954 出处与两条出路(补发完整历史 / ACP_KEEP_RESPONSE_ID=1)的告警文本。两个调用点都在既有 ACP_KEEP_RESPONSE_ID !== "1" 块内:算 warn → log → delete,顺序正确、无副作用。server 侧走 handler-scoped log("warn")(经 logMsg),adapter 侧直连 loggerLog("warn"),均符合仓库日志纪律。

④ 测试有效性(真测试,有牙):helper 边界值全覆盖;loop adapter 断言「恰好一条点名 id 的 warn」/「KEEP=1 保留且零 warn」/「缺省 no-op」;HTTP e2e 用真 startServer + mock SSE upstream 做 delta 续接(req1 seed + req2 带 id 省略 store)→ 断言转发体无 id、turn-1 secret 未被重建、恰好一条 #1954 warn;KEEP=1 变体断言 id 原样转发且静默。若未来有人删掉 warn 或改动 wire 行为,这些断言会失败。范围也正确:只钉住可见性边界,不测历史重建(那是 #1973)。

⑤ diff 整洁度(干净):6 文件 +306/-4,全部与本 PR 目的直接相关(2 个 strip 点 + helper + 测试 + CLIENTS.md/TECHNICAL-NOTES.md 文档),无无关改动、无空白噪音。文档内容与代码事实一致。

结构化七问

  1. 是什么问题:[Bug][Responses HTTP] 删除 previous_response_id 时未重建增量请求历史,导致上下文静默丢失 #1954 的可见性缺口——bili 剥离 previous_response_id 后转发 delta 续接请求却不重建被引用历史,上游丢光先前轮次仍返回 200,此前完全静默。本 PR 不修根因,只让丢失可观测。
  2. 什么原因导致的:bili 的 Responses adapter 是无状态重放压缩器,无 response-lineage 存储,无法物化 previous_response_id 引用的历史(根因仍在,完整支持由 feature [Feature][Responses] 支持原生 chaining(previous_response_id + store)——物化引用历史,消除 #1954 上下文丢失根因 #1973 跟踪);既有 strip 路径丢弃 id 时不打任何日志。
  3. 怎么修复的:在两个 strip 决策点各加一条点名 id 的 warn(纯 helper 判定「id 非空」),零 wire 字节变更——疏堵之辨上这是「让机制的已知边界显形」,不是掩盖。
  4. 是否有回归问题:无。上述既有行为逐项审计通过;stale-base 冲突已修复并本地复验(typecheck + 定向 42/42 + build 全绿)。
  5. 是否破坏缓存:不涉及。wire shape 未变,prefix cache / session 状态 / 去重键均未触碰。
  6. 是否改了设计方向:否。刻意维持「strip + forward」现状;两个过渡方案(重写前拒绝 / 原生语义旁路通道)明确留给 [Feature][Responses] 支持原生 chaining(previous_response_id + store)——物化引用历史,消除 #1954 上下文丢失根因 #1973 统一设计讨论,本 PR 不越界。
  7. 是否引入了新的配置:无。ACP_KEEP_RESPONSE_ID 为既有变量,语义未变(=1 保留 id 且不告警)。

CI 状态

旧 base 全绿;rebase 后新 head(5d2299a2)重跑中——build-artifact、e2e、codex/dsh/pi/opencode 各 lane、registry e2e (ubuntu)、image-billing、version-guard 已绿,剩标准 test matrix(ubuntu/windows node 22/24)与 registry windows 在跑。

判定:可合并。 方向、代码、测试、diff、文档全部核验通过,唯一的实际问题(stale base 冲突)已在 review 中修复。@ranxianglei 待剩余 CI 项转绿后可自行合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

补充:rebase 后的新 head(5d2299a2)CI 已全部跑完,15/15 checks 全绿(含 ubuntu/windows node 22/24 test matrix、registry e2e 双平台、codex/dsh/pi/opencode 各 lane、build-artifact)。PR 现处于可合并状态,@ranxianglei 可直接合并。

@ranxianglei
ranxianglei merged commit 6a9b6eb into master Oct 3, 2026
15 checks passed
@ranxianglei
ranxianglei deleted the 2026-10-03_responses-chain-warn-1954 branch October 15, 2026 05:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant