Skip to content

[PR] fix(preflight): compare foldable mass to deficit on one calibrated scale (#3645) - #3650

Merged
ranxianglei merged 3 commits into
masterfrom
2026-10-18_preflight-calibrated-futility-gate
Oct 20, 2026
Merged

ranxianglei merged 3 commits into
masterfrom
2026-10-18_preflight-calibrated-futility-gate

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Problem

A session with a persisted matching-origin calibration factor k-hat > 1 can hit a non-retryable local 502 even though folding would have brought it back under the window. Two symptoms, one root cause — a unit mismatch between two token scales:

  1. The raw-range futility gate compared an uncalibrated foldable pool (kernel range.tokens) against a calibrated payload deficit (result.payloadEstimate - limit). With k-hat>1 the deficit is inflated x-k while the pool is not, so the gate declared a recoverable round "futile" and skipped every fold -> the over-window payload was never forwarded and tier recovery never got a chance.
  2. The post-fold fail-fast message quoted a raw rebuilt size while the fit decision used a calibrated size, so it claimed a sub-window number (~550759) "exceeds the model window 872000".

Root cause

Once a matching-origin k-hat is set (#1933 F1), applyEstimateCalibration scales the host's own estimate (payloadEstimate, the fit check, the pre-fold tokenCount) by k-hat, but the kernel's range.tokens pool stays on the raw count. The gate's two operands were on different scales.

Fix

  • src/preflight.ts: route the foldable pool through applyEstimateCalibration before comparing it to the deficit -- pre-walk gate, relaxed probe, mid-walk bail -- and in the log/failure text, so both sides share one scale. Folding a raw-mass range removes its mass from the text, so its calibrated saving is bounded by mass*k-hat; comparing mass*k-hat * slack < deficit is the unit-unified bound. Identity for k-hat=1 / absent / mismatched-origin keeps the 模型压缩输出是输入的数倍 #1841 uncalibrated path byte-identical.
  • src/server.ts: hoist the calibrated post-fold size so the fail-fast message quotes the same scale as the fit decision.

Behavior change (intended)

Before After
Calibrated (k-hat>1) session whose raw pool x slack < calibrated deficit -> skipped as "futile", bricked behind a non-retryable 502 Same session now proceeds to fold; recovers when the fold closes the gap
Fail-fast message quoted the raw post-fold size (could claim a sub-window number exceeds the window) Quotes the calibrated post-fold size, same scale as the fit decision

The uncalibrated path (k-hat=1 / absent / mismatched origin) is unchanged -- applyEstimateCalibration returns the raw value there.

Config surface

None. No new config field, env var, CLI flag, wire shape, or persistence format.

Tests

New tests/issue3645-calibrated-futility.test.ts:

Existing issue1841-preflight-futility and preflight-round-budget suites stay green locally. Full-suite verdict = remote CI.

Fixes #3645

…ale (#3645)

The raw-range futility gate compared an UNCALIBRATED foldable pool against a
CALIBRATED payload deficit. With a matching-origin k-hat > 1 the deficit is
inflated x-k while the kernel range.tokens pool is not, so a fold that would
bring the window back under the limit was declared futile and skipped, leaving
the session bricked behind a non-retryable 502.

- preflight.ts: route the foldable pool through applyEstimateCalibration before
  comparing it to the deficit (pre-walk gate, relaxed probe, mid-walk bail) and
  in the log/failure text, so both sides share one scale. Identity for
  k-hat=1 / absent / mismatched-origin keeps the #1841 uncalibrated path
  byte-identical.
- server.ts: hoist the calibrated post-fold size so the fail-fast message quotes
  the same scale as the fit decision, instead of claiming a sub-window raw number
  exceeds the window when k-hat > 1.

Regression: tests/issue3645-calibrated-futility.test.ts (calibrated case recovers;
uncalibrated control unchanged).

Fixes #3645
@ranxianglei ranxianglei changed the title fix(preflight): compare foldable mass to deficit on one calibrated scale (#3645) [PR] fix(preflight): compare foldable mass to deficit on one calibrated scale (#3645) Oct 18, 2026
@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-18_preflight-calibrated-futility-gate (8ede209)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.4299-pr.3650.36383f7

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-pr3650.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

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

查重: 不重复。 按失败签名(预检 futility gate 的未校准池 vs 校准 deficit 单位错配)检索 open/closed issue 与近期 PR:唯一同主题条目即本 PR 所修的 #3645 本身;相邻的 #3649(tier-recovery candidate search)机制不同(tier 恢复的候选搜索 vs raw-range gate 的单位),不构成重复。

开始独立审核(不照抄 issue 结论):已拉取分支 pr3650-review @ 99ab9c4,diff = src/preflight.ts(+16/-9)、src/server.ts(+7/-5)、新增 tests/issue3645-calibrated-futility.test.ts(222 行)。master 在 PR 之后前进了 4 个提交(#3618 dsh attach origin、#2950 persona-lineage ref guard),其中 #2950 触碰过 src/preflight.ts / src/server.ts 区域——正在核对热文件语义冲突、既有行为回归清单与测试有效性,随后按八问给结论。

awork added 2 commits October 18, 2026 13:01
…n log too (#3645)

Review follow-up on #3645: the 'preflight compressed N range(s)' info log mixed
scales — calibrated pre-fold tokenCount vs the RAW post-fold anchor
(session.stats.lastInputTokens), so for k̂>1 sessions the (A → B) pair no longer
diffs to the reported saving. Quote foldedCalibratedSize instead; meter-anchor
assignment is untouched.
…librated sessions (#3645)

Review follow-up on #3645: symptom 2 (fail-fast quoting the raw post-fold size)
had no regression test. New e2e case: k̂=2 with heavy summaries so the walk
exhausts deterministically (tiers off) with post-fold raw mass sub-window while
the calibrated mass stays over — asserts the quoted context figure is on the
calibrated (over-window) scale. Mutation-checked: fails on the pre-fix code
with the self-contradictory sub-window quote.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

Review 结论:可合(人工合并:https://github.com/ranxianglei/billion-context/pull/3650)——方向、机制、回归面已独立复核,并在 PR 分支补了两个 follow-up commit(见下)。同一结论也已回帖到原 bug 报告线程(#3645)。

结构化八问

  1. 是什么问题:带校准系数 k̂>1 的会话,负载超窗且明明还有可压内容时,bili 误判「压了也没用」整轮跳过压缩,返回不可重试的本地 502;报错还称「约 55 万 token 超过 87.2 万窗口」——一个低于窗口的数字被说成超窗,自相矛盾。
  2. 什么原因导致的:DSH: 切换模型后,preflight 在窗口远未满时提前触发压缩 #1933 F1 起,matching-origin 的 k̂ 存在时,宿主侧估计(payloadEstimate、fit 判定、pre-fold tokenCount)都按 k̂ 放大,但 kernel 的可压池 range.tokens 仍是原始计数。futility 门的两操作数不同标度(原始池 vs 校准后缺口),k̂>1 时缺口被放大 x-k 而池没有 → 可恢复轮被判「徒劳」;post-fold 报错文案同样混用了原始与校准两个数。
  3. 影响范围与严重程度:仅 matching-origin k̂>1、且「原始可压池 × 1.2 < 校准后缺口」的会话(高校准系数、贴窗/超窗场景,[Bug][preflight] Calibrated deficit vs uncalibrated foldable mass prematurely skips raw folds (0.1.199) #3645 的 DSH native 即此)。严重度:完全不可用(不可重试 502,只能手动缩上下文)。其余会话零影响。
  4. 怎么修复的:统一量纲——可压池在比较前走同一个 applyEstimateCalibration(前置门、relaxed probe、mid-walk 中止、日志/报错文案四处决策点全过一遍);把校准后的 post-fold 尺寸提升出来,让报错文案与 fit 判定引用同一标度。折掉原始质量 M 至多省 M×k̂ 校准 token,故 M×k̂×slack < deficit 是单位统一的界。k̂=1/缺失/origin 不匹配时 applyEstimateCalibration 原值返回,模型压缩输出是输入的数倍 #1841 路径不变。
  5. 是否有回归问题:无。触碰路径既有行为逐项清点:未校准 futility skip(issue1841 A/B 两例)绿;relaxed probe 与轮次预算(preflight-round-budget 2 例)绿;status 映射(429→503 / deterministic 超窗→413 / 其余 502)未动;meter anchor 赋值(preflight: one failed summarization call fails the whole turn with a non-retryable 502 and blocks the session #1987)未动;tier funnel 入口条件未动;wire 形状零变化(转发 payload/SSE/tool calls 均未动,只动本地决策与本地文案)。
  6. 是否破坏缓存:不涉及——前缀缓存、重试策略、增量游标、去重键、持久化格式均未触碰。
  7. 是否改了设计方向:不涉及——在既有校准设计内做单位统一,无架构转向。
  8. 是否引入新配置:不涉及——无新 env/config/CLI/wire/持久化面(diff 核实)。

Review 发现并已直接修掉(两个 additive commit,已推到 PR 分支)

  • 日志混标度(同一机制族):preflight compressed N range(s) info 日志原先混用校准前折叠数和原始 post-fold anchor,k̂>1 会话里 (A → B) 差值对不上报告的节省量 → 改引校准后 post-fold 尺寸(commit 7351fce8b)。行为变更披露:k̂≠1 会话该 info 日志第二个数从原始 anchor 变为校准值(纯日志,无功能影响)。
  • 症状 2 缺回归测试:新增 e2e case(commit 8ede209a5)——k̂=2 + summary 比源段更重,使压缩轮确定性耗尽(post-fold 原始质量低于窗口、校准质量仍超窗),断言报错引用的是超窗的校准数。变异验证过:把表达式临时换回旧写法,测试立即失败,失败输出正是自相矛盾的 sub-window 引用(约 21556 < 窗口 30000)——测试有牙。

一处 PR 描述需修正的细枝:PR 称「未校准路径不变」,严格说 fail-fast 引用的数从 lastInputTokens(棘轮 floor、不含图片)换成了「重建文本+wire 开销+图片」,有两个角落差异——anchor 陈旧偏高时、含图会话(差 imageTokens)。两处都让引用值更接近实际发出的大小,属同族改进而非回归,但按披露义务写明:旧值→新值如上,原因=引用「实际要发出去的」而不是 meter 的历史 floor。

验证证据:定向套件本地 8/8 通过;typecheck 干净;远程 CI 在新 head 8ede209a5 上全绿(全部 static gates + ubuntu/windows × node22/24 test shards,零失败)。与当前 master dry-run merge 无冲突;PR 显示 behind 是因 master 期间合入了 #3618/#2950,不构成合并障碍。

判定:可合,请人工合并。

@github-actions

Copy link
Copy Markdown
Contributor

📦 Merged Build Published

This merge to master was published as 0.0.639-master.80cbe28 (rolling master tag).

npm install -g billion-context@0.0.639-master.80cbe28  # this exact build
npm install -g billion-context@master  # always the newest merged build

npm view billion-context@master prints the current version at any time.

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.

[Bug][preflight] Calibrated deficit vs uncalibrated foldable mass prematurely skips raw folds (0.1.199)

1 participant