Repository navigation
Description
Environment
- bili / billion-context: 0.1.210 (commit 0e88a07)
- Host: linux 6.17.13-21-pve x64, single machine, multi-lane (omp + codex + hermes peers)
- Failure surface: omp agent runtime (ACP lane), model `litellm/step-5-preview-free` routed to `http://127.0.0.1:14001\`
- Storage: unified sqlite (
~/.local/share/billion-context/sessions/index.db, 559.2 MiB)
Symptom (user-visible)
```
Error: Retry budget exhausted after 10 retries: 502 context ~204011.2055699065 tokens exceeds
the model window 150000 (model=step-5-preview-free), with 0 compressible range(s) still visible
and preflight compression could not bring it under: the payload still exceeds the window after
preflight compression. The over-window payload was NOT forwarded. (type=server_error param=preflight_compress_failed)
```
Repeated across multiple sessions / runtimes. Also observed: `Auto-snapcompact cancelled`,
`Auto-shake found nothing eligible to drop; trying the next preferred compaction method`,
`Auto context-full maintenance cancelled`.
Evidence: the estimate is stored characters, not tokens
Query of `sessions.stats_json` for the offending session:
| field | value |
|---|---|
| `lastInputTokens` | 204046 |
| `localInputEstimate` | 204046 |
| `inputTokens` (real usage) | 83051 |
| messages / stored bytes | 116 / 196442 |
| `blocks` | 0 |
`196,442` is exactly the `Σ m.text.length` of the message set (chars). It matches `localInputEstimate` to the unit.
Source (`src/session.ts`):
```js
session.stats.localInputEstimate = estimateCoreMessagesUpper(processedMessages)
- countSystemAndToolsTokens(responsesDevContent ?? "", toolsOut)
- loadedToolTokens + imageReserve;
```
where
```js
function estimateCoreMessagesUpper(messages){ let chars=0; for(const m2 of messages) chars+=(m2.text??"").length; return chars }
```
and `defaultCountTokens() = cjkCount + Math.ceil((text.length - cjkCount)/4)`, i.e. tokens = chars/4 for ASCII. So the message term is charged ~4x. The `#553` comment at `src/preflight.ts:265-267` acknowledges this ("undercounts code/JSON replays by up to ~4x") — but that defense only applies when `unknownBaseline` is set for this request. `unknownBaseline` is not persisted in `stats_json` for this session, and `lastInputTokensSource` is unset, so the upper bound was written into `lastInputTokens`/`localInputEstimate` and is replayed as truth afterwards.
Evidence: it poisons future requests, not just this one
`stats_json` is persisted. Because `localInputEstimate` == `lastInputTokens` == 204046 is written to disk, every later request for that session starts from the inflated value; the session can never report a genuine size again unless a new `inputTokens` usage anchor overwrites it.
Fleet-wide count over 2420 sessions with stats: 53 sessions have estimate > 2x real usage. Worst offenders are `pfa-** sessions with estimate `1958197`/`1664643`/`1638612` and `inputTokens == 0`.
Second, independent defect: window resolution misses step-5 models
`CONTEXT_LIMIT_TABLE` in `dist/index.js` contains no `step-` entry (only `claude-`, `gpt-5`, `gpt-4.1`, `gpt-4o`/gpt-4-turbo, `o1`/`o3`, …). Therefore
```js
const native = ... ?? configuredWindow ?? peekWindow ?? lookupContextLimit(model);
```
falls through to `base.modelContextLimit`, whose default is `2e5` (`parseInt(env.ACP_MODEL_CONTEXT_LIMIT ?? `${fileConfig.modelContextLimit ?? 2e5}`, 10)`), and `effectiveWindow = 2e5 * nudge.maxContextLimitPct(.75) = 150000`.
The real window for `step-5-preview-free` (litellm `nvidia_nim/stepfun-ai/step-5-preview`) is 1048576, confirmed by the deployment config (`max_input_tokens` / card comment: "CONTEXT: card says 1,048,576 and the API actually enforces it") and by the models registry (`contextWindow=1048576`).
So a 2.4x overestimate is compared against a window that is ~7x too small, and the two defects compound into a hard, non-retryable `preflight_compress_failed`.
Suggested direction
- `unknownBaseline` should gate the char-upper-bound per request only; when the estimate is later written to `stats_json`, it should not be promoted into `lastInputTokens` as if it were a measured usage anchor. Either keep the pessimistic value in a separate field, or scale by the calibration factor `k̂` before persisting.
- `CONTEXT_LIMIT_TABLE` should either learn the window from the upstream `/models` response, or fail open (treat `lookupContextLimit() === undefined` as "unknown" rather than clamping to a 200k default) instead of clamping every non-Claude/OpenAI model to 150000.
Local mitigation applied (for the record)
- Per-route per-model `compress.modelContextLimit = 1048576` in `~/.config/billion-context/billion-context.json` (route keyed by origin `http://127.0.0.1:14001\`), plus `compress.maxContextLimit = "95%"`.
- omp `compaction.modelThresholds` for step-5 raised from 10% to 40% to compensate for the inflated threshold.
Not a substitute for the fix — but it stops the fleet-wide outage today.
Activity
ranxianglei commentedon Nov 1, 2026
(ai: qwen/qwen3.8-27b)
查重: 不重复。 按失败签名(
preflight_compress_failed/localInputEstimate/armFailureShrink)检索了 open+closed issue 与 PR:最接近的是 #4974/#5005(一次 ~10KB 辅助请求把会话基线钉在过小值 → doomed-byte-gate 413 活锁——同属会话计量域,但触发与症状方向相反:那是基线过小、本单是字符上界过大且落盘)和 #4146(单条巨型消息超蒸馏源预算 → 502,机制不同)。本单独立处理。标签: bug / omp / scope/wiring / p1(用户不可用类:错误窗口下会话被本地永久拒发、需人工配路由才恢复;幽灵基线还会污染同路由后续所有会话)。
Triage 结论(已在你报告的 v0.1.210@0e88a073 与当前 master 双树上核对代码):
armFailureShrink(relay.ts)在 relay 5xx/网络失败/熔断时把outboundPayloadBreakdown().armEstimate——以字符计数上界为地板(fix: arm emergency shrink on outbound payload size, not raw body (#1493) #1498-F1 有意为之,给内核 truncate 深度用)——写进lastInputTokens并markDirty落盘;localInputEstimate/contextTokens则是每次发送的常规盖章(fork 会话 lastInputTokens=0 时 preflight 退化为字符估算,大载荷被低估后不压缩直接裸转上游 #553 fail-closed 口径)。你说的「unknownBaseline 只按请求 gate」属实:unknownBaseline = anonymous && lastInputTokens <= 0,显式 id 会话根本进不了字符上界防护分支。CONTEXT_LIMIT_TABLE无step-*条目 → 落到modelContextLimit默认 2e5 × maxContextLimitPct(.75)= 150K,而 step-5-preview-free 真实窗口 1M,差 ~7x。字符上界落盘是放大器+持久化器,它做了两件坏事:(a) preflight 入口预算仍按幽灵锚定尺(entryTokens/overshootRatio → summary/round budget 抬升;DSH 分叉会话后触发大量 preflight overflow compress #2383 的 regime 选择已有 entryLocal 防护,但预算没有);(b) 把lastInputTokens > 0伪装成「有上游证据」,关掉了 [Bug] 新会话(无 usage 基线)preflight 把字符数当 token——折叠其实成功(2263796→1111212)却 fail-fast 502,上游实际只计费 540828 #3146/413 Deadlock: When an authenticated session exceeds the reservation window with zero collapsibles, the #3146 forwarding | 413 死锁:带身份会话超预留窗口且零可折叠时,#3146 转发门因 anonymous 条件不触发,会话从首条消息起永久不可用 #4185 设计的 forward-once 仲裁出口(该出口要求lastInputTokens <= 0)——于是错误窗口下永远本地 fail-fast,溢出学习反馈(armOverflowShrink)被饿死,系统无法自愈。两者复合成不可重试死循环;[Bug][preflight] Local 413 is forgotten when the baseline becomes an estimate, reopening oversized probes #3846 的本地拒绝记录再按 origin+model+limit 钉住整个作用域,跨会话传染(与你观察到的多会话/多运行时复发一致)。CONTEXT_LIMIT_TABLE的^step-→ 1M 条目(按你部署实测值;表内既有条目惯例,偏大猜错会按 [Question] deepseek-flash 被静态兜底表解析为 128k,真实窗口 1M —— 是有意设置,还是兜底表过期? #852 设计在首次上游溢出时自愈)。「lookup miss 视为 unknown 而非 2e5 默认」属全局默认值变更,是产品决策——我单独开 decision request 给你拍板,不擅自改。计划: 一个 PR(Closes #5500)含三处修复 + 回归测试(复现形状:毒化基线 + 小窗口 + 0 可折叠区间 → 修后走 forward-once 仲裁自愈而非死循环);默认值决策项另开 issue。开始动手,进展会在这里更新。
ranxianglei commentedon Nov 2, 2026
(ai: qwen/qwen3.8-27b)
已修复,PR: #5501 (Closes #5500)
做了什么
CONTEXT_LIMIT_TABLE增加{ match: /^step-/i, limit: 1_000_000 }(src/config.ts)——step 系模型不再因 lookup miss 落到 2e5 默认(你的部署配置与 models registry 均为 1048576;旧路径只给 ~150K 有效窗口)。currentTokens初始化、entryTokensfloor)现在与所有其他读者一致(任何一轮没有拿到 usage 报告的请求,都会把上下文分母放大 12–20×(nudge 读到 >1000% usage、假 EMERGENCY、基线冻结数分钟) #1839 kill-at-reader / emergency shrink / preflight 的本地估算用错了视图:超长会话(客户端历史 127 万,压缩后 outbound 仅 ~16 万)在上游失败无 usage report 时,bili 按原始历史估算 #1492 per-round floor):ESTIMATE-grade arm(arm emergency shrink on upstream failure to break relay-5xx deadlock #604 failure arm 持久化的 char-bound 上界)与 legacy 无 source 值不再 floor entry sizing——它们是 arming 量,不是测量值。usage/overflow-arm 锚点照常 floor;unknown-baseline(fork 会话 lastInputTokens=0 时 preflight 退化为字符估算,大载荷被低估后不压缩直接裸转上游 #553)regime 与 arm emergency shrink on upstream failure to break relay-5xx deadlock #604 kernel truncate rescue 消费者(prepareproviderInputTokens)不动。tests/issue5500-char-bound-poison.test.ts(5 例):表行+负向对照;entry budget 双向钉(Test Blind Spot Retrospective: Reinforcing Negative Assertion Discipline, Tightening Fake Upstream Strictness, Thin Inst | 测试盲区复盘:补反向断言纪律、假上游严格化、薄安装冒烟、形态矩阵与生命周期覆盖 #3617);e2e 走真实窗口解析链复现本 issue 形状(修复前 ≥400 fail-fast → 修复后干净 forward、零 summarization 调用);对照测试钉住"实测超窗仍被拒"(C2 不软化真实墙)。另立决策项(需 owner 拍板,非本 PR 范围):lookup miss 该当什么处理 —— decision request(GitHub 编号 5502,新建线程,与本线程镜像号 5502 无关,p1): #5502 — A 保持 2e5 默认+按证据长表(本 PR 走的路)/ B miss 视为 unknown、fail-open 让 overflow arm 学真墙 / C 从上游 /models 目录学窗口。推荐 A 先行、C 后续;B 是全局 fallback 默认变更(§7.4 owner 领地)。
八问
armFailureShrink(src/server/relay.ts:161)把 est = max(textEstimate, charUpper)+overhead 以 source="estimate"(legacy 为无 source)写入并 markDirty 落盘,preflightCompress entry 两处直接读该值、无 grade 检查——与其余读者的 任何一轮没有拿到 usage 报告的请求,都会把上下文分母放大 12–20×(nudge 读到 >1000% usage、假 EMERGENCY、基线冻结数分钟) #1839/emergency shrink / preflight 的本地估算用错了视图:超长会话(客户端历史 127 万,压缩后 outbound 仅 ~16 万)在上游失败无 usage report 时,bili 按原始历史估算 #1492 纪律不一致(逐读者审计后确认这是最后一个未过滤消费点)。行为变更披露(old→new):① 未显式配置的
^step-模型有效窗口:150000 → ≈786432(同一 headroom 系数作用于 field-verified 1048576;显式 per-route/per-model 配置优先级不变);② ESTIMATE-grade/无出处 baseline 下,preflight entry 不再用 lastInputTokens floor entryTokens/currentTokens 初始化(改按本请求实测定容);usage/overflow-arm 锚点不变。合并判定:CI 在此 head 转绿即可 review/merge。
fix: pin step-family window row to the field-enforced 1048576 wall (#…
ranxianglei commentedon Nov 2, 2026
(ai: vllm-qwen/qwen3.8-27b)
来源: PR #5501 分析 #5500 时发现
PR #5501 修复了缺陷 B 的两个 preflight ENTRY 读(
currentTokens初始化 /entryTokensfloor),但「除 entry 外该值的所有 reader 都已被 grade 纪律约束」的说法略过强——复查后还有两处读lastInputTokens未查lastInputTokensSource,属同一机制家族(缺 grade 纪律的 reader),记录在此跟踪,不单开 issue:src/request-membership.ts:70(probeRequestMembership,Bypass requests overwrite the main session's usage anchor, causing long sessions to permanently stop compressing. | 旁路请求覆盖主会话 usage 锚点,导致长会话永久停止压缩 #4805 membership needle 启发式):referenceScale = lastInputTokens > 0 ? lastInputTokens : needlePayloadUpper—— estimate-grade 中毒臂(char-bound,≈4× token 数)会把 mainScale 阈值抬高约 4×,needle 更新偏保守(软降级,不引发本 issue 的循环)。src/server/prepare-responses.ts:597(codex compact-intercept 伪造 usage body):total = Math.max(session.stats.lastInputTokens, est, 1)—— 中毒时伪造的 inputTokens 偏大,codex 下一轮真实请求会从它重算 ledger;窄路径(codex host + intercept mode + compact form)。二者都不喂 preflight entry sizing、都不触发本 issue 的 fail-fast 循环,故不属 #5501 范围。后续若修,建议与 #5501 同走 kill-at-reader 纪律(按 source gate),并补双向测试(#3617)。
fix: extend grade discipline to the remaining lastInputTokens readers (…
ranxianglei commentedon Nov 2, 2026
(ai: qwen/qwen3.8-27b)
复查指出的两处 reader 已独立审核完毕,另发现同类第三处;三处全部修复并折入 PR #5501(新提交
b263268f1,已推送)。本地定向测试全绿;新 head 的 CI 待镜像缓存收编(前一 headac098eeaa在镜像缓存为 17 success / 13 skipped / 0 failed)。审核结论(独立复核,非照单全收):
src/request-membership.ts:70(Bypass requests overwrite the main session's usage anchor, causing long sessions to permanently stop compressing. | 旁路请求覆盖主会话 usage 锚点,导致长会话永久停止压缩 #4805 membership needle)——存在,但危害程度被高估。 它的两个调用方都把stats.localInputEstimate作为payloadUpper传入——而 localInputEstimate 本身就是 char-bound 上界、与中毒臂同一口径——所以比值自归一化,复查所称「mainScale 阈值抬高约 4×」在当前行为下并不会实际发生。gate 的价值在漂移鲁棒性(防未来口径漂移)。照修(kill-at-reader + 回退到 needle 自身 per-request scale),且此点已在 PR body 里如实注明。src/server/prepare-responses.ts:597(codex compact-intercept 伪造 usage)——属实。 这里est是 chars/4 乐观口径而中毒标量是 char 计数口径,尺度不抵消;伪造 inputTokens 偏大约 4×,codex 从该 body 重算 ledger,会偏斜到下一次真实上报为止。已修:仅 usage/overflow-arm grade 的标量参与 max。src/session.ts的noteAbortedTurn。 char-bound 臂会污染 In pi, Esc triggers compression injection. | pi中esc会触发压缩注入 #5293 abort re-anchor flag:re-anchor 延迟约 4× 生长量,且 In 0.1.210, sessions with frequent interruptions barely trigger compression reminders — tokens accumulate to 330k before | 中断频繁的会话在 0.1.210 里压缩提醒几乎不触发,积到 33 万 token 才压一次 #5415 的债务记账(recovered = anchor − oldRef,按 char-bound 尺度算)会把幻影增长债务记进 nudge cadence。已修:不可信 meter 直接跳过盖章(其文档自己就有「zero/unknown meter carries no information: skip」,本次把「不可信」纳入同款判断)。relay.ts:1565—— log-only(只拼进 warn 字符串),无需修。八问:
lastInputTokensSourcegrade 纪律;我复核后确认共 3 处(含新发现 1 处),与 localInputEstimate persists the char-count upper bound (~4x char/token) and poisons every later request; with a small window preflight then reports "exceeds the model window" on a 2.4x-overestimate #5500 缺陷 B 同机制家族(estimate-grade 臂未被 grade 校验地读取)——均不触发原 fail-fast 循环,属软降级 / ledger 偏斜 / cadence 失真类。lastInputTokensSource ∈ {usage, overflow-arm}gate(与 preflight per-round floor 同一纪律);membership 处不通过时回退 needle 自身 per-request scale。按「一个机制一个 PR」政策折入 [PR] fix: refuse estimate-grade arms in preflight entry sizing; add step-family 1M window (#5500) #5501,不拆 follow-up。行为变更披露(旧→新):④ membership bar 参考尺度 = graded 标量(有则用),否则 needle 自身尺度(原为任意正标量优先)——legacy 无 source 会话的 needle 移动可能略不那么保守;⑤ codex forge
input_tokens = max(graded 标量, est, 1)(原为任意标量);⑥ abort re-anchor 只从 usage/overflow-arm meter 盖章(estimate-grade-only 会话退回纯增长式 nudge——那个臂本来就是假信息)。详见 PR body Round 2 节。另:分支上的 pin 提交
ac098eeaa(表行 1_000_000→1_048_576,对齐 field-enforced wall)已接受保留。结论:PR #5501 head
b263268f1完整覆盖 #5500 的缺陷 A(窗口表)、缺陷 B(preflight entry sizing)与本轮 3 处 reader;CI 在此 head 转绿即可 review/merge。ranxianglei commentedon Nov 2, 2026
这个是不配置上下文大小导致的问题吗
ranxianglei commentedon Nov 2, 2026
(ai: qwen/qwen3.8-27b)
一半是,一半不是。
与「没配置上下文大小」有关的部分(缺陷 A):你没给这条路由/模型配
modelContextLimit,bili 就走内置回退链(显式配置 → registry → 内置窗口表)。内置表缺 step 系模型的行,一路落到 env 默认 2e5 → 有效窗口约 150K(×0.75),而 step-5-preview-free 的真实窗口是 1M。你本地缓解时显式配了compress.modelContextLimit = 1048576就绕开了这一点——恰好印证了这条因果链。但严格说这不是「不配置就会坏」:正确的回退对已知模型就该给出正确值。它分两层:① 表缺行(#5501 已修:补^step-→ 1048576);② 表 miss 时该钉死 2e5 还是当「未知」处理——这是产品决策,已单独立了 decision request,等拍板。与你的配置无关的独立缺陷(缺陷 B):relay 出错(litellm 抖动)后,failure arm 把 char-bound 上界(约 4× token 数)写进
stats.lastInputTokens并持久化到 stats_json,污染之后每个请求(preflight 入站预算等)。注意:如果窗口正确解析成 1M,你报的那个循环根本不会发生——真实 payload 约 83K tokens ≪ 有效 ~850K,preflight 触发条件都不满足。是两个缺陷叠加才变成硬 fail-fast 循环:错误的 150K 墙制造了「超窗」误判,中毒臂又让后续请求一直带着虚高的数字。现状:PR #5501 新 head
b263268f1的 CI 已全部转绿(30 checks、0 failed)。升级到包含此修复的版本后,你本地那条显式modelContextLimit可以去掉(留着也无害——显式配置永远优先)。jiu-qiu-yu commentedon Nov 4, 2026
Additional evidence on 0.1.212, Windows / Pi / Responses path: the same estimate-grade transition can also trigger destructive-to-the-delivered-view emergency tool-output truncation, not only a preflight refusal. No conversation bodies, credentials, session IDs, or private repository content are included here.
Installed-code path
Both
dist/agent/opencode-native.jsanddist/agent/pi-native.jscontain:When
anchorStaleis true,effectiveTokenCountskips the measured usage branches. With no rebuild anchor or anonymous special case, it returnsMath.min(session.stats.localInputEstimate, payloadUpperNow)as estimate-grade.estimateCoreMessagesUppersums JS string lengths. The stale predicate itself does not compare request identity or whether the payload changed.Offline reproduction, not a replay of a real request
Extracted the six installed pure functions and their three constants into a Node VM (no plugin import, network, real session data, or configuration changes). Ran the same clearly synthetic 639673-character fixture through both installed bundles:
lastInputTokens=262850, sourceusage, and a matchinglastUsagePayloadUpper.effectiveTokenCount:{tokens:262850, source:"usage"}.noteOutboundContextEstimateswith{upperBound:639673, scaledText:262850, imageTokens:0, calibrated:true}.effectiveTokenCountwith the unchanged fixture:{tokens:639673, source:"estimate"}.lastInputTokensis still 262850; fixture hash is unchanged. Restoring measured-source metadata returns 262850 again.Both bundles produce the same result. This proves that the source transition can amplify the decision value without any message growth. It does not prove the exact operands for the real request below.
Observed runtime metadata
A measured input usage of 262850 was followed by a request with 1478 messages, 13.0 MiB inbound / 1020.3 KiB outbound, and
truncate=0. About 34 seconds later, with no intervening usage sample in the inspected metadata, another prepare with the same message count/inbound size used decision value 639673 and loggedtruncate=21; outbound fell to 413.7 KiB. Equal count/size is not proof of byte-identical request bodies; those bodies were deliberately not inspected.Configured/registered window was 500000, output limit 128000, default output-headroom cap 25%, hence effective input window 375000 and emergency threshold 356250. These are local settings, not an independent measurement of the upstream's limit.
A separate offline check of installed
truncateLargeToolOutputsconfirms that this emergency branch does not honorprotectedTools; its replacements are subsequently latched. Raising the window or disabling clipping is therefore not a measurement fix, and cannot restore already-clipped deliveries.Please include the usage → outbound estimate → repeated prepare → emergency-truncate chain in regression coverage, preserving conservative handling for genuinely changed or unknown payloads. I have not established that the currently open PR #5501 covers this emergency path, and have not installed an unreleased build or changed runtime limits.
fix: ride the calibrated per-send estimate on cycle-stale meters (#5500)
ranxianglei commentedon Nov 4, 2026
(ai: qwen/qwen3.8-27b)
查重:不重复。 同节点近亲 #5217/#5255(latch 在 BLOCKED sentinel ref 下存储、损坏无关工具参数)机制不同;#3691 是 latch 设计来源(已关)。本条是「freshness 降级 × char-bound 标度 × 破坏性消费方无证据门」三层叠加,与 #5500 缺陷 B 同机制家族,已并入 PR #5501(Round 3,commit 8222bc4)。
标签: 补打
pi(本轮证据来自 Pi/Responses 车道,与原omp并存);bug/scope/wiring/p1不变。独立复核(对 v0.1.212 tag 与 master 双树逐行核对,相关代码两树一致;你的离线提取法与结论均可复现):
usageAnchorCycleStale为 true 时effectiveTokenCount(src/server.ts:2869)跳过全部三个 measured 分支,落到min(localInputEstimate, raw upper)——char-bound 上界直接进入 kernel 计量。现场数字自洽:639673/262850 ≈ 2.43 chars/token,正是 char-count 量级;~34s 后无 usage 报告的第二次 prepare 就是 cycle-stale 触发点。truncateLargeToolOutputs(kernel/src/truncate-tools.ts)不仅不认config.protectedTools,连ALWAYS_PROTECTED_TOOLS(compress/acp_rule)与折叠路径整套isMessageProtected/latest-pairing 机制都不用——即使真实 ≥95% 溢出也会裁剪 load-bearing 的 ACP 管理元数据,违反 Kernel Boundary 规则 6(protected-tool hard exclusion)。state.emergencyTruncateLatch([Kernel Initiative] Transactional folding boundaries + wire byte fidelity (unified prefix cache fix #3938, kernel side) | [kernel 专项] 折叠边界事务化 + wire 字节保真(前缀缓存统一修复 #3938 内核侧) #3939③),直到下次成功折叠才清除——「raising window/disabling clipping cannot restore already-clipped deliveries」正确,已交付视图的损伤不可逆。分层: (a) freshness 降级本身是有意设计(#4383:报告停更时不许骑冻结锚点),不是缺陷;(b) 缺陷在 ride-on 标度选了 char-bound 上界(~2–4× 虚高),把安全会话推进破坏性阈值带;(c) 保护机制缺失是独立的 kernel 不变量违反。
处置:
contextEstimateTokens——同一 relay chokepoint 盖戳的 billing-caliber 每发估算(k̂ 有出处时缩放),正是staleSmallAnchorFallback自己降级类返回的同一个替换读数;再min(当前 payload 自身上界)封顶,永不超过今天 fail-closed 最坏值。[Bug] statusInputBaseline falls back to lastUsageGradeTokens instead of the calibrated local estimate — so one 4.7k side-request sample blocks folding for 4 hours | #1595 承诺的"改用本地估算"兜底在 statusInputBaseline 里没有实现,一次 4.7k 侧请求样本即可挡住折叠 4 小时 #4383 原症状保持修复(骑 150K ≠ 冻结的 4733);[Bug] 上游从不报告 usage 时 nudge 永不触发——上下文无界增长直到超窗(ChatGPT 登录态后端) #728 无锚点车道、usage/overflow-arm 分支、fresh-settle、host preflight 触发器全部字节级不动。ProcessTurnInput不携带证据等级 → 破坏性动作可对任何 grade 的证据执行;truncate 无视保护工具)→ 按 Kernel Boundary 规则 1+3 需 owner 批准,已立 #5693(p1 / scope:kernel / needs-decision;两子缺陷一个清单,选项 A/B/C,推荐 A)。行为变更披露(旧→新):无报告周期内 kernel 计量(nudge 档位 / 应急截断带 / terminal escape / absorb view)从
min(localInputEstimate, raw)(≈2–4× 虚高)→min(contextEstimateTokens, raw)(≈真实大小)。三个 #4383/#5134 回归断言随之从 char-bound 重钉到 calibrated 标度(同一 chokepoint 新鲜度,修正标度;其中一条的断言文案本来就写着 "its calibrated estimate wins"——现在名副其实)。回归覆盖(你要求的 usage → outbound estimate → repeated prepare → emergency-truncate 链已入 C7 e2e,含 teeth 验证:回退修复后该链复现 latch 损伤,修复后干净)+ C6a/b 双向钉(#3617)+ 四个不变标度对照 + C7-control(kernel 带本身未被动过)。本地定向全绿:issue5500 15/15、effectiveTokenCount 消费方批量 50/50、邻域批量 96/96、typecheck 干净;全量以 CI 为准。
八问
判定:host 侧修复在 PR #5501 head
8222bc415,CI 转绿即可 review/merge;kernel 侧残余由 #5693 单独拍板,不阻塞本 PR。ranxianglei commentedon Nov 5, 2026
是什么问题:上一轮请求没等到 usage 报告时,kernel 计量改骑 char-bound 上界(~2–4× 虚高),越过 0.95× 窗口的应急截断带,把安全会话的工具输出裁掉并 latch 进交付视图。
这个问题master还存在吗
ranxianglei commentedon Nov 5, 2026
(ai: qwen/qwen3.8-27b)
还在。 刚对当前 master HEAD(
8de4c37f8)重新核过:自上次审计的c9ba48566以来,相关文件(src/server.ts、src/session.ts、kernel/src/truncate-tools.ts、kernel/src/compress.ts)零变更——cycle-stale 路径逐行一致(anchorStale跳过全部三个 measured 分支后落到min(localInputEstimate, raw),server.ts:2883→2969),char-bound 虚高 + 越过 0.95× 应急截断带 + latch 进交付视图的整条链在 master 上原样存在。修复只在 PR #5501(head
8222bc415,C6),未合入;kernel 侧两个残余子缺陷(证据等级门 / truncate 无视保护工具)在 #5693 等拍板。master 何时消除该问题 = #5501 何时 merge。fix: refuse estimate-grade arms in preflight entry sizing; add step-f…
fix: pin step-family window row to the field-enforced 1048576 wall (#…
fix: extend grade discipline to the remaining lastInputTokens readers (…
fix: ride the calibrated per-send estimate on cycle-stale meters (#5500)
fix: refuse estimate-grade arms in preflight entry sizing; add step-f…
fix: pin step-family window row to the field-enforced 1048576 wall (#…
fix: extend grade discipline to the remaining lastInputTokens readers (…
fix: ride the calibrated per-send estimate on cycle-stale meters (#5500)