Skip to content

[PR] fix: overflow-stated counts steer local fold targets immediately (provisional estimator bias) (#5373) - #5382

Open
ranxianglei wants to merge 2 commits into
masterfrom
2026-11-01_overflow-stated-bias
Open

ranxianglei wants to merge 2 commits into
masterfrom
2026-11-01_overflow-stated-bias

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Closes #5373

What this changes

After an overflow 400, bili now RETAINS the upstream-stated payload count as a provisional estimator scale for that route (stats.overflowBias, persisted), and every local judgment on that route (preflight trigger, fold mass/target, relay overhead, output clamp ×3 lanes) picks its factor through one new selector util.effectiveCalibration: ring-published k̂ when applicable to the decision route, else the retained bias, else absent (today's raw behavior). The armed preflight comparator additionally exits on the calibrated round text when a factor applies, so a rescue fold stops at est × k̂ ≤ budget instead of burning an unsatisfiable floor comparison.

Why: on a fresh overflow-only session (the incident's resume-miss sub-session, no usage history) the ring can never publish while every forward keeps overflowing — publication needs ≥2 agreeing samples on one origin+model slot that any foreign settle clobbers — so local judgments stayed raw-estimate calibre forever and each forward re-400'd: a permanent loop. The first overflow's stated counts are high-confidence measurements (three mutually consistent numbers in one body); using them immediately is what breaks the loop. Algebraically identical to the issue's proposed bias = max(bias, stated/estimate) divisor on the fold target.

Safety gates:

Also in this PR (same incident evidence):

Behavior change (old → new)

Tests

tests/issue5373-overflow-bias.test.ts: unit gates for effectiveCalibration/calibrationOriginApplies (incl. the mismatch guard, clamp band, model/origin gates) + e2e through the real pipeline with a billing mock (DeepSeek-shaped 400s): mechanism (bias retained at first arm, ring discipline intact) and regression (the grown turn fits on its INITIAL forward with bounded fold work; learning completes by turn 2). Targeted suites green locally on the rebased head: 104 tests across the #3900/#3450/#1987/#2313/#1839/#2029/#1492/#2484/cjk-context-overflow/fold-anchor-doctrine/fix-arm-headroom-clamp families; full suite on CI.

查重: 不重复 — #3900 (closed, fixed in 0.1.201 via #4093) is the same upstream signature predating this variant; #4079 (open hub) covers over-window forwards reaching upstream, this is its compression-lane variant where the LOCAL TARGET itself is wrong; #5278/#5291/#5296 are the output-clamp safety-buffer family (the clamp never fired in the incident); #3450 is the stated-WINDOW facet (this PR is the stated-PAYLOAD-COUNT facet and preserves #3450's pinned netting behavior).

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-11-01_overflow-stated-bias (2409888)

Latest build — install this exact version

npm install -g billion-context@0.0.9118-pr.5382.f2be328

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
2409888 billion-context@0.0.9118-pr.5382.f2be328 build
fa6fe4b billion-context@0.0.9056-pr.5382.861f3ad build
afabce9 billion-context@0.0.7602-pr.5382.a00d147 build

Download artifact

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

Install instructions are refreshed on each push.

@ranxianglei ranxianglei changed the title fix: overflow-stated counts steer local fold targets immediately (provisional estimator bias) (#5373) [PR] fix: overflow-stated counts steer local fold targets immediately (provisional estimator bias) (#5373) Oct 31, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

Reviewed PR #5382 (head afabce9, 1 commit, 11 files, +599/−28, no kernel/, branch current with master / 0 behind). Full-diff read of all 11 files + caller-consistency sweep + regression enumeration. Verdict below.

查重(独立判定,不复读 issue 结论):不重复。 本 PR 的机制是「第一次 overflow 就把上游声明的 payload 计数保留成一条 provisional 每路由估算偏差,让本地折叠判断立刻按它走,直到 ring 发布后由 ring 取代」。这与它引用的既有工作机制不同:#3450 是 stated-WINDOW 面(arm baseline 钉在 ceiling),这里是 stated-PAYLOAD-COUNT 面(steer fold target),且用 mismatch guard 保住了 #3450 的 burn-and-net;#3900 是把单次样本喂进 ring(要 ≥2 一致才发布),这里是在发布前就立即 steer。同一起事故家族、不同失败面 → 符合「同症状同 issue、不同机制可分」的口径。方向关通过:这是疏不是堵——修掉的是「本地判断在环里永远停在 raw calibre」这个产生现象的机制,而不是把 400 挡住。

八问

  1. 是什么问题:全新会话(典型是 resume-miss 派生的子会话,没有 usage 历史)如果流量全是 overflow,bili 学到的估算缩放 k̂ 永远发不出去——发布要同一 origin+model 槽位上 ≥2 个一致样本,而任何 sidecar settle 都会清掉这个单槽位——于是每次转发都用偏低的 raw 估算去判 fit/fold,每个 forward 都再撞一次 400,形成永久 overflow 死循环;武装救援比较器在 clamp arm 下还不可满足,每轮把整条折叠阶梯烧空。
  2. 什么原因导致的:根因 = ring 的发布规则(≥2 一致 + 单槽位)在「每个 forward 都在 overflow」期间不可达,所以第一次 overflow 自带的高置信声明计数(一个 400 body 里三个互相一致的数)只被拿去 seed ring,从未被立即用来 steer 本地判断。因果分层:症状(永久 400) ← 机制(本地判断卡在 raw calibre) ← 根因(声明计数被挡在一个永远到不了的发布阈值后面)。
  3. 影响范围与严重程度:受影响面 = 「本地估算系统性低估」的路由上的全新 overflow-only 会话(CJK-heavy payload、声明 completion reserve 吃掉一部分窗口)。严重度 = p1 可用性类:该会话完全无法推进(永久 400),直到碰巧有一个 usage 样本把 ring 发出去。有正常 usage 历史的健康会话不受影响(它们正常发布 ring,bias 只是 fallback)。
  4. 怎么修复的:把第一次 overflow 的声明 payload 计数保留成一条 provisional 每路由偏差(ratio = stated/local-est,clamp 到 [0.25,4],origin+model 门跟 ring 一样,加 mismatch guard 处理 ≥4×/≤¼ 视图不匹配形状)。新增选择器 util.effectiveCalibration 出因子:路由适用的 ring k̂ 优先,否则用保留的 bias,否则 absent(raw)。五个本地决策点(preflight trigger、fold mass/target、relay overhead、output-clamp ×3 lanes)全部改走它;武装 preflight 比较器在有因子适用时额外用校准后的 round-text 提前退出。ring 一旦发布即取代 bias。附带:原本静默的学习路径现在 log accept/reject 原因;post-fold summary 行改成引用自己这行的端点算节省量(不再出现 "~0 tokens saved (913329 → 875788)")。
  5. 是否有回归问题:审了 diff 触碰的每一处既有行为:
    • ring 因子应用(原 currentCalibrationFactor+applyEstimateCalibration 模式,5 处)→ 换成 effectiveCalibration:纯 ring 情形逐条核对为行为保持(origin 不匹配时新旧都退 raw;匹配时都给 ringK),其余纯增量;grep 确认 util.ts 之外已无残留 currentCalibrationFactor( 计算点,无漏网决策点。
    • 武装 preflight 比较器三元 armedBaseline && !armedFactorApplies ? decisionTokens : roundText:无因子与非武装两条路径字节级保持,只有 armed+factor 这一格变(即本次修复目标)。
    • post-fold log 行:仅日志措辞,meter 字段(auto-fold sharp edges: a sub-floor autoFoldTargetTokens causes a fold storm, and externalSummary.* file edits do not take effect until a PUT /__bili/config #3444 backoff 消费的那个)未动。
    • ingest 日志:同款 gate 条件的 early-return 重构,仅加日志。
      高危模式逐项过:无 fail-fast→吞错;无新阈值(band 值从 cache-ledger.ts 原样上提,未发明新数);无 wire shape 变化;无 cache-key/dedup/游标失效。净回归:未发现。
  6. 是否破坏缓存:否。前缀缓存键、去重键、增量游标、消息身份全部未触碰。bias 只改变恢复轮折叠多深(更靠前折 → 那一轮 summarize 调用/延迟+成本更高),是有意的 availability-over-performance 自愈合,不是缓存稳定破坏;稳定前缀仍字节稳定。
  7. 是否改了设计方向:无架构转向。扩展既有 DSH: 切换模型后,preflight 在窗口远未满时提前触发压缩 #1933/[BUG] acp-proxy upstream HTTP 400: Request with 1,198,269 tokens exceeds the model's 1,048,576 token limit, consistently | [BUG] acp-proxy upstream HTTP 400:请求 1,198,269 tokens 超过模型上限 1,048,576,一直复现——是插件压缩未生效,还是 DSH 的问题? #3900 校准机制,加一个「provisional immediate bias」fallback 且让位于 ring——同一数据流、同一套门(origin/model/clamp)、同一持久化纪律(compaction 边界随 ring 一起 reset)。只加一个内部 stats 字段;无 config surface、无 env var、kernel 未碰。
  8. 是否引入了新的配置:无。无新 config key/env var/默认值。overflowBias 是内部、逐字段校验、持久化的 stats 字段(corrupt→absent→raw);provider calibration.disabled/max 策略在保留时被尊重(既有 surface)。

行为变更披露(旧→新):OLD:overflow 后本地判断停在 raw calibre,直到 ring 发布(≥2 一致、未被清)——在全新 overflow-only 会话上实际等于永远发不出 ⇒ 永久 400;武装救援烧完整阶梯。NEW:第一次 overflow 就用 clamp(stated/est,[0.25,4]) steer 同 origin 同 model 的判断,直到 ring 取代;武装救援在校准停止点退出。后果:愈合轮前置折更深(恢复轮 summarize 调用/成本上升)——有意自愈合。视图不匹配(≥4×/≤¼)情形不变(mismatch guard 保住 master 的 burn-and-net,e2e #3450 T1 覆盖)。

测试有效性(④):新文件 tests/issue5373-overflow-bias.test.ts(357 行)是真测试而非假测试——unit gate 双向断言(clamp band、origin gate、model gate、mismatch guard 双向、ring 优先级)满足 #3617 gate discipline;e2e 有牙:断言 grown-turn 每个 forward billed ≤ TARGET(= judging limit),unfixed 代码会 bill 超窗从而被抓到;hermetic/deterministic 无 timing flake。

CI:static-gates / mysql-contract / version-guard 已绿;全量 test 矩阵(ubuntu/windows × node 22/24 × 5 shards)仍在跑,目前 0 failed。mergeable_state=blocked 是因为必填 check 还在 pending,非冲突非继承红(base 0 behind)。按本地测试纪律,全量回归交给 CI,我未本地重复跑(diffs 逐文件静态审过 + 一致性 grep + 读测试评有效性)。

合并判定:方向正确(疏)、回归未发现、测试有牙、diff 干净(单 commit 11 文件全部与本 PR 目的相关,无 lockfile/generated churn)、行为变更已披露。待全量 test 矩阵转绿即可合;当前证据下我判断可合。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

Reviewed this against master (base e209109 = current tip, mergeable). Two notes:

  1. Corrected the issue reference. It said Fixes #5383, but Successful compression can end the turn when its summary contains FAILED #5383 is the owner's v0.1.210 regression placeholder — merging would auto-close that tracker and leave the actual bug open. Changed it to Fixes #5386. Rest of the body (incl. Related: #4856) untouched.

  2. Verified the change is correct and minimal. proxyToolResultFailed() now keys off the first non-empty status line at all five sites in src/loop/core.ts; genuine failures ([Compression FAILED: / [decompress FAILED: / [absorb FAILED:) carry FAILED on line 1, so recovery is unchanged. Both new tests route through the real proxy-side compress path (x-bili-plugin-compression: proxy → pluginMode=false) and arm visibilityMarkers:false; the FAILED-in-summary case is a genuine regression test (1 upstream call pre-fix → 2 post-fix).

Tracking CI on this head — completed gates green, test shards still running. Full verdict will come from remote CI on the pushed head.

@ranxianglei
ranxianglei force-pushed the 2026-11-01_overflow-stated-bias branch 2 times, most recently from 6494d6e to fa6fe4b Compare November 11, 2026 04:16
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

Conflict resolved and pushed. The PR branch (2026-11-01_overflow-stated-bias) was a single commit based on a ~10-day-old master; master had advanced 200+ commits and touched the same hot files, which is what made the merge dirty. I rebased the commit onto current master (twice — master moved again mid-run, landing the final head on 33104b1f), resolving only import-line conflicts each round, then force-pushed the rebased head fa6fe4b8fa.

What the resolutions were (all mechanical, union-of-intent):

Live state verified this run: PR mergeable: true, merge state blocked (no longer dirty — waiting on checks/branch protection), CI running on fa6fe4b8fa (29 success / 15 skipped / 11 in progress / 0 failed at time of check). Note: the mirror check-cache had not been refreshed since 2026-11-05, so per status-freshness policy I confirmed the live state with single one-shot API reads rather than asserting from cache. Full-suite verdict comes from CI on the pushed head.


中文八问(结构化结论)

  1. 是什么问题:PR [PR] fix: overflow-stated counts steer local fold targets immediately (provisional estimator bias) (#5373) #5382(overflow-stated bias 修复)与 master 冲突(merge state dirty),无法合并——分支基于约 10 天前的旧 master,期间 master 前进 200+ 提交且改到了同一批热文件。
  2. 什么原因导致的:分支基线过旧。冲突全部集中在 import 行:master 侧新增了 throttle 相关导入、Remove the compressAtFoldPoint feature — it reorders resent history and caused an authorship-misattribution incident in a live session #6132/[PR] remove: the experimental compressAtFoldPoint feature — fold-point relocation (v1 #5471 + unreleased v2 #5949), #6132 #6150 又删掉了 makeFoldPointReasoningDroppable 的导出与引用,与本 PR 在同一行区间做了不同修改。
  3. 影响范围与严重程度:仅本 PR 的可合并性;对任何用户行为无影响(我的操作不改变 PR 内容本身,diff stat 前后完全一致:11 文件 +599/−28)。
  4. 怎么修复的:把单个 PR 提交 rebase 到当前 master(master 中途又前进了一轮,最终落在 33104b1f 之上),两轮共解决 5 处 import 冲突,按「union of intent」处置——保留 master 的导入集、换入 PR 的 effectiveCalibration;随后 grep 验证无残留旧符号引用,typecheck/build 干净,定向测试套件 75/75 全绿后 force-push。
  5. 是否有回归问题:无。解决只动了 import 列表,未触碰任何逻辑行;既有行为未被本次操作改变。全量回归由推送头部的 CI 把关(当前 29 成功 / 11 进行中 / 0 失败)。
  6. 是否破坏缓存:不涉及——本次操作未触碰任何缓存/重试/游标逻辑。
  7. 是否改了设计方向:不涉及——纯合并冲突消解,无架构或数据流变化。
  8. 是否引入了新的配置:不涉及——无新增 env/config/默认值。

收工判定:冲突已解、分支已推、状态已转干净(blocked = 等 CI/保护规则),等待 CI 全绿后即可走人工合并。

ci-check added 2 commits November 11, 2026 17:00
A fresh overflow-only session (resume-miss sub-session, no usage history) could never publish the calibration ring while every forward kept overflowing: publication needs >=2 agreeing samples on one origin+model slot that any foreign settle clobbers, and the armed prefold comparator could not fit-exit under a clamped arm. Local judgments therefore stayed raw-estimate calibre forever and each forward re-400'd — a permanent loop (incident 2026-10-31, dsh lane).

- armOverflowShrink retains clamp(stated/local-est, [0.25, 4]) per origin+model as stats.overflowBias (persisted, validated on restore); a ratio outside the band flags the record 'mismatched' (the stated count describes payload bili does not hold, #3450 shape) and such a record does not steer.

- new util.effectiveCalibration picks the factor allowed to steer THIS route: ring k-hat when applicable to the decision origin, else the un-mismatched bias, else absent; all application sites (trigger, preflight mass/target, relay overhead, output clamp x3 lanes) now use it.

- the armed preflight comparator exits on the calibrated round text when a factor applies (folds until est*k <= budget instead of burning an unsatisfiable floor comparison); legacy behavior when no factor applies.

- ingest/settle/arm now log accept/reject reasons (the learning path was silent before, which made the incident undiagnosable from production logs).

- the post-fold summary line quotes savings from its own endpoints instead of the floor-clamped meter ('~0 tokens saved (913329 -> 875788)' can no longer happen); the meter field itself is unchanged (consumed by the #3444 backoff gate).

Tests: tests/issue5373-overflow-bias.test.ts (unit gates for effectiveCalibration/calibrationOriginApplies incl. the mismatch guard; e2e mechanism + regression through DeepSeek-shaped overflows with a billing mock).
An unclamped overflow arm (measured count already above the stated ceiling —
declared window wider than the provider's real one) keeps master's raw-scale
fit judgments in preflight. Applying the provisional bias there declares an
unfoldable payload over-limit; the walk books a non-materializable
emergency-truncate credit and the #1987 anchor then clobbers the
upstream-measured arm baseline (source flips to 'estimate'), breaking the
#1195 B passthrough contract. The armed-comparator carve-out gets the same
clamped-arm restriction so a ring-published factor cannot take an unclamped
arm off its floored path either.
@ranxianglei
ranxianglei force-pushed the 2026-11-01_overflow-stated-bias branch from fa6fe4b to 2409888 Compare November 11, 2026 10:34
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

结论先行:本轮现场核验确认——PR #5382 当前没有合并冲突,无需 rebase、无需 push。 任务标注的「merge state: dirty」是过期/瞬时检测标签;实时状态是 mergeable_state=blocked(等必填 check),不是 dirty(冲突)。

本轮证据(全部现场核验,非记忆):

  • 活跃 master = dc041dd1ab,PR head = 2409888faf(git ls-remote 与 GitHub API 双重确认,base.ref=master)。
  • git rev-list --count prbranch..master = 0 ⇒ master 是分支直系祖先 ⇒ 可 fast-forward ⇒ 数学上不可能产生冲突。
  • git merge-tree --write-tree <head> <master> 直接产出干净合并树,无任何冲突标记。
  • GitHub API 实时返回 mergeable: true / mergeable_state: blocked。
  • 本地工作分支已 == 远端 head(2409888faf),无内容差。

为何会触发: floor 13(今日 04:28Z)前一轮 CI 工程师已解过一次真冲突(当时分支基于约 10 天前的旧 master);此后分支又被重新落到当前 master dc041dd1ab 之上,并于其上叠了第二个提交 2409888faf(#1195 B,今日 10:29Z)。现在分支 = 「当前 master + 两个线性提交」的干净堆叠,故无冲突。自动检测在 push 后 mergeability 重算窗口内读到瞬时状态,遂按模板标成 dirty 派发。

本轮动作:零改动、零 rebase、零 push。 理由:rebase 到已是祖先的 master 是空操作(up-to-date,不改任何 SHA);强推同一 SHA 属无谓重写,会白白再触发一轮全量 CI、浪费算力,且可能与并行处理本分支的其他 agent 抢分支。前提(存在冲突)经三重独立验证为假——如实报告比盲目执行破坏性 force-push 更安全。

当前 CI(非红项): 截至镜像 check 缓存快照(sha 2409888faf),30 项中 15 skip / 3 success / 12 in_progress / 0 failure。test 矩阵各 shard 仍在跑;static-gates(ubuntu-24)、mysql-contract 绿;hermetic/e2e 车道按设计 skip。全量回归以推送头部的 CI 为准;本轮无红项需修。

中文八问

  1. 是什么问题:被当作「上游 PR 冲突(dirty)」派发的自动修复任务;复核后确认该 PR 并不存在合并冲突,它已是当前 master 之上的干净线性堆叠。
  2. 什么原因导致的:dirty 标签来自过期/瞬时检测快照。本 PR 今早已由前一轮 CI(floor 13) rebase 过,其后又落到最新 master dc041dd1ab 并新增 使用pi 压缩后就提示prompt is too long #1195 B 提交,使分支始终贴着 master、无分叉。
  3. 影响范围与严重程度:仅本 PR 可合并性判断;对用户行为零影响(本轮未改任何代码,全 PR diff stat:11 文件 +629/−28,未触 kernel/)。严重度:无(误报)。
  4. 怎么修复的:无需修复。遵循「先验活再动手」:用祖先关系(rev-list)、GitHub mergeable:true、git merge-tree 干净树三条独立途径交叉确认无冲突后,判定 rebase 为空操作,遂不执行破坏性 push。
  5. 是否有回归问题:无。本轮零代码改动,不可能引入回归。
  6. 是否破坏缓存:不涉及——未触碰任何缓存/重试/游标逻辑。
  7. 是否改了设计方向:不涉及——纯状态核验,无架构或数据流变化。
  8. 是否引入了新的配置:不涉及——无新增 env/config/默认值。

收工判定:无冲突可解、无红项可修;分支为当前 master 之上的干净 fast-forward 栈,mergeable:true,卡在「等必填 CI 全绿 + 人工合并」。CI 车道本轮无需进一步动作;若后续 test 矩阵转红,再由对应红项触发单独处理。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

2 similar comments
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant