Skip to content

[PR] fix: preflight switches to digest folds mid-flight when the LLM path cannot close the gap within budget - #5678

Open
ranxianglei wants to merge 2 commits into
masterfrom
2026-11-04_preflight-adaptive-emergency
Open

ranxianglei wants to merge 2 commits into
masterfrom
2026-11-04_preflight-adaptive-emergency

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Nov 4, 2026 •

Copy link
Copy Markdown
Owner

Closes #5671

What & why

#5671 field log (dsh persona sub-session, v0.1.212): one sub-session ballooned to ~7.3x its window (5793 msgs / 24.9 MiB / ~7.2M tok vs a 983k window) with a highly fragmented fold pool (1312 viable ranges, largest ~18k tok). Preflight's entry-time emergency trigger (#2383) only fires above 19.2x overshoot, so this payload stayed on the slow LLM path: 32 rounds x one fold each removed only ~1% of the ideal per-fold mass, the 6.2M-token deficit was mathematically unclosable, and the invocation died with fail-fast 413 retryable=false. Every subsequent retry instant-413s against the same still-growing payload - three 413s at 04:29/05:45/06:13 in the log - and the session is lost forever.

This PR adds the missing middle of the convergence model: a second, budget-aware trigger point inside the round loop. When the largest summaryBudget viable ranges cannot close the remaining deficit by more than ADAPTIVE_EMERGENCY_SLACK (1.5x, covering #2682 re-fold amplification + estimator noise), the remainder of the invocation flips to the existing CPU-only deterministic-digest regime (#2383 mechanism, EMERGENCY_ROUND_CAP rounds). In the incident shape the flip lands in round 1 before any LLM call; fragment pools then converge in seconds instead of minutes-plus-failure.

The flip is monotonic per invocation (digests never re-expand content, so the bound stays true). It is gated on baselineKnown exactly like the #1841 futility gate: in the unknown-baseline regime the deficit counts raw chars while range.tokens carry calibrated estimates, and mixing those scales false-positives on payloads the LLM path can actually converge (regression caught by preflight-covered-ranges.test.ts).

Behavior changes (old -> new)

  1. Mid-loop digest switch (new). Old: the CPU-digest regime was decided once, at entry, only for >19.2x overshoot; baseline-known sessions between the raised coverage bound and 19.2x burned up to 32 LLM summary calls (~minutes) and then failed. New: they get CPU-digest-quality summaries when the LLM walk is provably doomed. Originals stay restorable via decompress; digest blocks carry their span refs.
  2. Deterministic doom answers 413, not 502. A pool hopeless in BOTH regimes (e.g. digest overhead alone >= window) now exits through the 模型压缩输出是输入的数倍 #1841 futility gate as deterministic exhaustion -> 413 retryable=false (+ local-refusal note, [Bug][preflight] Local 413 is forgotten when the baseline becomes an estimate, reopening oversized probes #3846) instead of 502 "budget exhausted after N rounds". Per Three issues found during real-model stress testing: WS passthrough can't connect — HTTP upstream is guaranteed to die; | 真模型压测发现的三个问题:WS 直通连不上 HTTP 上游必死、超限时死锁+紧急提示风暴、compress 激活本身太重 #3461's classification, status-driven headless hosts spin forever on 502 but stop on 413 - the same verdict class as every other "can never fit as-is" refusal ([Evidence] pi 车道切供应商(同 modelId)后 fold 不随会话迁移:裸上下文 2.23MB(≥298K est tokens)被 preflight 10 秒拒 3 次;账面 ≤157K 与裸水位背离 10.5h #2847/fix: doomed preflight rejection answers 413, not 502 (#2847) #2921/[Bug] 新会话(无 usage 基线)preflight 把字符数当 token——折叠其实成功(2263796→1111212)却 fail-fast 502,上游实际只计费 540828 #3146).

No change to: wire format, config surface, persistence format, kernel/, updater, cache behavior.

Config surface

None. ADAPTIVE_EMERGENCY_SLACK = 1.5 is an internal constant next to the other preflight bounds; no new env var or config key.

Duplicate screening

Not a duplicate (partially merged): the treadmill half of #5671 ("compressed but it won't come down" - active blocks accumulate monotonically while distillation never fires below the pressure threshold) is the same symptom+mechanism family as the compression-leak thread already tracked on the internal tracker - evidence cross-linked there (that thread holds the root-fix options, parked awaiting owner). This PR covers the NEW failure domain: mid-overshoot payloads whose fold pool is too fragmented for the LLM walk to converge within budget (searched open+closed issues/PRs for preflight 413 / fail-fast / unbounded sub-session growth - no existing thread).

Tests

…nnot close the gap within budget

Field evidence (#5671, dsh persona sub-session, v0.1.212): a session ballooned
to ~7.3x its window (5793 msgs / 24.9MiB / ~7.2M tok vs a 983k window) with a
highly fragmented fold pool (1312 viable ranges, largest ~18k tok). The entry
emergency trigger (#2383) only fires above 19.2x overshoot, so this payload
stayed on the slow LLM path: 32 rounds x one fold each removed ~1% of the
ideal per-fold mass, the 6.2M-token deficit was mathematically unclosable, and
the invocation died fail-fast 413 retryable=false - after which every retry
instant-413s and the session is lost forever.

Add a second, budget-aware trigger point inside the round loop: when the
largest summaryBudget viable ranges cannot close the remaining deficit by more
than ADAPTIVE_EMERGENCY_SLACK (1.5x, covering re-fold amplification + estimator
noise), flip the remainder of the invocation to the CPU-only deterministic-
digest regime (#2383 mechanism, EMERGENCY_ROUND_CAP rounds). The flip is
monotonic per invocation. Gated on baselineKnown exactly like the #1841
futility gate: in the unknown-baseline regime the deficit counts raw chars
while range.tokens carry calibrated estimates, and mixing those scales
false-positives on payloads the LLM path can actually converge.

Behavior changes (disclosed in the PR):
- baseline-known sessions between the coverage bound and 19.2x overshoot now
  get CPU-digest-quality summaries when the LLM walk is provably doomed;
  originals stay restorable via decompress. Previously such sessions burned up
  to 32 LLM calls (~minutes) and failed anyway.
- pools hopeless in BOTH regimes now exit through the #1841 futility gate as
  deterministic exhaustion and answer 413 retryable=false instead of 502
  "budget exhausted" - status-driven headless hosts stop spinning (#3461).

No new config surface. Tests: new tests/preflight-adaptive-emergency.test.ts
(both-directions pair per #3617); tests/preflight-round-budget.test.ts second
scenario re-scoped from "LLM budget exhaustion -> 502" to "deterministic doom
-> 413 non-retryable".
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-11-04_preflight-adaptive-emergency (3c9974e)

Latest build — install this exact version

npm install -g billion-context@0.0.8149-pr.5678.fd02bb6

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
3c9974e billion-context@0.0.8149-pr.5678.fd02bb6 build
57db2a4 billion-context@0.0.8144-pr.5678.a599ad8 build

Download artifact

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

Install instructions are refreshed on each push.

@ranxianglei ranxianglei changed the title fix: preflight switches to digest folds mid-flight when the LLM path cannot close the gap within budget [PR] fix: preflight switches to digest folds mid-flight when the LLM path cannot close the gap within budget Nov 4, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

查重: 不重复(独立核验)。open PR 里没有任何并行工作做「preflight 循环内切 digest」这件事——最接近的 #5679(storage drift 诊断)、#5676(嵌套折叠账本)机制与失败域都不同;本 PR 是 #5671「中幅超窗 + 碎片化折叠池」这个失败域的唯一实现。与 PR 正文的自查重结论一致。

标签: bug / dsh / scope/kernel / p1 —— 修的是 dsh 车道 preflight 压缩决策面的会话丢失缺陷(会话不可恢复类,按 owner 修订 2026-10-19 归 p1)。

评审进行中(PR #5678,分支 2026-11-04_preflight-adaptive-emergency,单 commit 57db2a4e3,基于最新 master、0 落后):

代码初判(细节随终稿):切换点位置正确(每轮 #1841 全池门之后、执行折叠之前),翻转单调(只 LLM→digest,构造上不可能反向),baselineKnown 门控与 #1841 同一纪律(未知基线制度下 deficit 用原始字符数而 range.tokens 是校准估算,混算会误杀能收敛的会话)。

@ranxianglei ranxianglei added bug Something isn't working dsh p1 scope/kernel labels Nov 4, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

PR #5678 评审结论(终稿) —— 代码、行为、测试、CI 全部独立核验完毕。

结构化八问

1. 是什么问题:payload 中幅超窗(低于 19.2x 紧急阈值)且可折叠池高度碎片化时,preflight 把整个 LLM 摘要预算烧在注定无效的折叠上再 fail-fast;headless 宿主对着失败判决无限重试,会话永久死亡(现场证据 #5671:~7.3x 窗口、1312 个碎片 range、32 轮只削掉理想质量的 <1%,之后 413/重试全灭)。

2. 什么原因导致的:入口紧急触发(#2383)和 #1841 futility gate 都按「理想折叠」定价——前者比全池质量对窗口,后者比全池对 deficit;但 walker 一次调用最多只能碰 summaryBudget(≤32)个 range。池子碎片化时出现夹缝:全池质量够(#1841 不触发)、top-N 质量不够(实际走不完),两个门都不开,循环空烧数分钟 LLM 调用后才失败。病因是「资格判定用的定价口径」与「walker 实际可达性」不一致,不是预算太小。

3. 影响范围与严重程度:基线已知、payload 落在「top-N 可达质量不足」到 19.2x 之间的会话——长 dsh persona 子会话是典型形状(历史长、工具碎片多)。修复前这类会话永久不可恢复(p1 类,已按此打标);修复后同一形状 CPU-only 收敛为 digest 折叠并正常转发,原文可 decompress 找回。

4. 怎么修复的:在 round loop 内加第二个预算感知触发点——每轮执行折叠前给「真实池子」定价:最大的 summaryBudget 个 viable range 的校准质量 × 1.5(#2682 re-fold 放大 + 估算噪声 slack)仍低于 deficit ⇒ LLM 路径结构性无解,本次调用剩余部分切到确定性 digest 制度(#2383 既有机制,round cap 提到 512)。翻转单调(构造上只 LLM→digest),baselineKnown 门控与 #1841 同纪律(未知基线制度下 deficit 用原始字符数、range.tokens 是校准估算,混算会误杀能收敛的会话)。我验证了边界数学:MAX_PREFLIGHT_ROUNDS == MAX_SUMMARY_CALLS_PER_PREFLIGHT == 16,两预算恒等,「walker ≤ summaryBudget folds」的上界成立;#1841 relax 后重置的是同一上限,不受影响;relax 探针在下一轮用含保护区的超集重算,不会提前判死。

5. 是否有回归问题:无。触碰路径的既有行为逐项清点:

6. 是否破坏缓存:不涉及缓存键/去重/增量游标;压缩使 fold 点之后的前缀缓存失效是所有压缩的固有代价,digest 块走 #2383 既有格式。

7. 是否改了设计方向:没有架构转向——把 #2383 既有的双制度模型加了一个触发点,同一决策面、同一数据流。

8. 是否引入了新的配置:无。ADAPTIVE_EMERGENCY_SLACK=1.5 是内部常量,刻意不暴露 env/config(与 FUTILITY_SLACK 同待遇)。

行为变更披露(old → new,均为 PR 正文已声明、我确认成立)

① 循环内 digest 切换(新增):基线已知、位于覆盖界到 19.2x 之间的会话,原先烧满至多 32 次 LLM 摘要调用(分钟级)后失败的,现在在 LLM 路径被证明无解时切 CPU-only digest 收敛并转发;原文可 decompress 恢复。
② 确定性无解的判决:502「budget exhausted after N rounds」→ 413 retryable=false(+ #3846 local-refusal 注记)。headless 宿主停止空转;与 #2847/#2921/#3146 同判决类。

测试有效性

新 e2e 是真服务器 + 真 kernel 管道 + mock upstream,双向断言有牙(#3617):C 场景若门被删/反转会因 LLM 调用出现或状态非 200 而红;D 场景若门过激会因摘要消失/digest 出现而红。round-budget 重定标(400→600 turns)合理:旧夹具恰好被本 PR 的新行为救活(钉住的就是新的预期行为),放大后双制度皆无解,继续钉 fail-fast 契约(413 + retryable=false + 零 LLM 调用)。一个非阻塞观察:1.5x 边界本身没有精确钉(两侧远端有钉),该阈值本质依赖估算器精度,不值得为此加脆弱夹具。

CI 备注

12:46Z 有一次批量重触发产生重复 run(重复的被自动取消)——同一模式在其他 SHA(12:58Z)也出现,属舰队级现象、与本 PR 无关;每个 workflow 在该 head 上均有成功运行。若分支保护因某个必需 context 解析到被取消的重复 run 而显示 blocked,重跑一次 checks 即可,无需代码动作。

判定

可合并——diff 最小(3 文件,每行都服务于本 PR 目的)、命名/注释符合仓库惯例、双向测试到位、本地+CI 双绿、行为变更均已披露。合并按规矩由你操作:#5678

@ranxianglei ranxianglei left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

评审结论:可合并(approve)。 独立核验通过——未照抄 issue 侧既有分析,自己重读了 diff、round loop、src/server.ts 状态映射与两套测试后才下结论。(本 PR 由同一账号提交,GitHub 不允许对自己账号的 PR 提交正式 approval,故以 review comment 形式留档;合并按规矩由 owner 操作。)

结构化八问

  1. 是什么问题:payload 中幅超窗(低于 #2383 的 19.2x 入口阈值)且可折叠池高度碎片化时,preflight 把整个 LLM 摘要预算烧在注定补不上 deficit 的折叠上再 fail-fast;headless 宿主对着失败判决无限重试,会话永久死亡(#5671 现场:~7.3x 窗口、1312 个碎片 range、32 轮只削掉 <1%,之后 413/重试全灭)。
  2. 什么原因导致的:入口触发(#2383)与 #1841 futility gate 都按「理想折叠 / 全池质量」定价,但 walker 一次调用最多只能碰 summaryBudget(≤32)个 range——碎片池在此出现夹缝:全池质量够(#1841 不开)、top-N 质量不够(实际走不完),两个门都不开,空烧数分钟 LLM 调用后才失败。根因是「资格判定的定价口径」≠「walker 的实际可达性」,不是预算太小。
  3. 影响范围与严重程度:基线已知、落在覆盖界到 19.2x 之间且池碎片化的会话(长 dsh persona 子会话是典型形状)。修复前这类会话永久不可恢复(p1);修复后同一形状 CPU-only digest 收敛并正常转发,原文可 decompress 找回。
  4. 怎么修复的:round loop 内加第二个预算感知触发点——每轮执行折叠前给「真实池子」定价:最大的 summaryBudget 个 viable range 的校准质量 × ADAPTIVE_EMERGENCY_SLACK(1.5,吸收 #2682 re-fold 放大 + 估算噪声)仍 < deficit ⇒ LLM 路径结构性无解,本次调用剩余部分切到确定性 digest 制度(#2383 既有机制,round cap 提到 512)。翻转单调(构造上只 LLM→digest),baselineKnown 门控与 #1841 同一纪律。
  5. 是否有回归:无。逐项清点触碰路径的既有行为:
    • #2383 入口触发(>19.2x 从第 0 轮 digest):代码路径未动 ✓
    • #1841 futility gate + zone-relaxation 探针:未动,新门严格在其下游 ✓
    • 能收敛的 payload 保 LLM 质量:新门只在「预算内完美折叠也补不上 deficit」时触发,数学上就是不可收敛集;scenario D 钉住负向(2.24x 整合池仍走 LLM、出真摘要、零 digest 产物)✓
    • 未知基线制度:baselineKnown 门控,字节级不变(preflight-covered-ranges 套件绿)✓
    • #2952 tier recovery 在 digest 模式排除:与入口触发的既有行为一致 ✓
    • 翻转在同一轮生效已核实:digest 决策 src/preflight.ts:2954(if (emergencyFold) { ... deterministicDigest(...) })读的是 live 变量,新门 src/preflight.ts:2354 在其上游先翻;for (... < effectiveRoundCap) 每轮重读 let,提到 512 生效。
  6. 是否破坏缓存:不涉及缓存键 / 去重 / 增量游标;fold 点之后的前缀失效是所有压缩的固有代价,digest 块走 #2383 既有格式。
  7. 是否改了设计方向:没有架构转向——给 #2383 既有的双制度模型加了一个触发点,同一决策面、同一数据流。
  8. 是否引入新配置:无。ADAPTIVE_EMERGENCY_SLACK=1.5 是内部常量(与 FUTILITY_SLACK 同待遇),刻意不暴露 env/config。

行为变更披露(old → new,均为 PR 正文已声明、我确认成立)

① 循环内 digest 切换(新增):基线已知、位于覆盖界到 19.2x 之间、LLM 被证无解的会话,原先烧满至多 32 次 LLM 摘要调用(分钟级)后失败 → 现切 CPU-only digest 收敛并转发;原文可 decompress 恢复。
② 确定性无解的判决:502「budget exhausted after N rounds」→ 413 retryable=false(+ #3846 local-refusal 注记)。映射已核对 src/server.ts:4478(f.kind==="exhausted" && f.deterministic && !payloadFitsWindow ? 413 : 502);headless 宿主停止空转,与 #2847/#2921/#3146 同判决类。这是有意的语义变更,非意外漂移。

测试有效性

新增 e2e 是真 server + 真 kernel 管道 + mock upstream,双向断言有牙(#3617):C 场景(碎片 ~8x)若门被删/反转会因出现 LLM 调用或状态非 200 而红;D 场景(整合 ~2.24x)若门过激会因摘要消失 / digest 出现而红。round-budget 重定标(400→600 turns)合理:旧夹具恰好被本 PR 的新行为救活(钉住的就是新的预期行为),放大后双制度皆无解,继续钉 fail-fast 契约(413 + retryable=false + 零 LLM 调用)。

顺手小修

已顺手修:tests/preflight-adaptive-emergency.test.ts:168 断言消息里的 issue 引用笔误 #5617→#5671(纯 message 字符串,零语义影响)+ commit 3c9974e6a。head 已从 57db2a4e3 移到 3c9974e6a,CI 会在新 head 上重跑。

判定

可合并——diff 最小(3 文件,每行都服务于本 PR)、命名/注释符合仓库惯例、双向测试到位、行为变更均已披露、无 kernel/ 改动(HARD RULE 不适用)。合并按规矩由你操作:#5678

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

评审完成:PR #5678 独立核验可合并(approve)——未照抄 floor 6,自己重读了 diff、round loop、src/server.ts:4478 状态映射与两套测试:机制成立(翻转单调、同轮生效于 src/preflight.ts:2354/2954、baselineKnown 门控与 #1841 同纪律)、双向 e2e 有牙、无 kernel/ 改动(HARD RULE 不适用);两处行为变更(循环内 digest 切换;确定性无解 502→413/retryable=false)均为有意且已披露。

已顺手修:tests/preflight-adaptive-emergency.test.ts:168 断言消息笔误 #5617→#5671(纯字符串,零语义),commit 3c9974e6a,head 已从 57db2a4e3→3c9974e6a(CI 在新 head 重跑)。GitHub 侧因同账号不能 approve 自己的 PR,评审以 comment-review 留档:#5678 (review) 。合并按规矩由你操作。

@ranxianglei

Copy link
Copy Markdown
Owner Author

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

复审确认(新 head 3c9974e6a):本轮是上一轮顺手修 typo 后 head 从 57db2a4e3→3c9974e6a 触发的自动重派。已核验 git diff 57db2a4e3..3c9974e6a 仅一行——tests/preflight-adaptive-emergency.test.ts:168 的断言消息字符串 #5617→#5671,零逻辑/语义变更;因此我上一条完整评审(结构化八问、行为变更披露、src/server.ts:4478 状态映射与双向 e2e 测试核实)对新 head 完全成立,不重复贴。

CI 在 3c9974e6a 上绿(30 checks:0 failed / 0 pending)。无 kernel/ 改动(HARD RULE 不适用)。

结论维持:可合并(approve)。 合并按规矩由 owner 操作:#5678

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

复审完成(新 head 3c9974e6a):本轮是上一轮 typo 修复后 head 移动的自动重派。已核验 git diff 57db2a4e3..3c9974e6a 仅一行测试断言消息字符串 #5617→#5671、零逻辑/语义变更,CI 在 3c9974e6a 上绿(0 failed / 0 pending)——结论维持可合并(approve)。完整评审见上一轮 comment-review;本轮已在 PR 留确认评论:#5678 (comment) 。合并按规矩由你操作。

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

bug Something isn't working dsh p1 scope/kernel

Projects

None yet

1 participant