Skip to content

auto compress problem #1122

Closed
Closed

Description

@walsykerem

There is an issue here: when a context limit is selected, compression is performed successfully and consistently. However, if I set the limit to 70,000—aiming to keep the active context around 40,000—it usually works, but a problem arises when a task actually requires 80,000 tokens of context (e.g., for reading); the task fails because it keeps getting compressed halfway through. The system needs to handle compression autonomously when switching between different tasks—since everyone is running autonomous agents and we aren't working in environments where we have manual control, the compression process itself must operate autonomously to achieve maximum compression.

Activity

  1. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 Verified against the code and by running the real kernel decision logic (acp-kernel@0.0.82, pinned in this repo) against a synthetic ~78–80k-token history. Your diagnosis is right, and there's a concrete cause plus a workaround you can use today.

    What's happening (root cause, not symptom)

    compress.modelContextLimit currently plays two roles at once:

    1. Denominator for the pressure bands — usage = tokens / this value, and the nudge/truncate/emergency thresholds are fractions of it (src/compress-settings.ts).
    2. The hard wall for preflight compression — the proxy starts proactively folding your context before forwarding the moment the payload reaches this value (src/server.ts:3478), and if folding can't bring it under, the request fails with 502 and is never sent upstream.

    So when you set it to 70k on a model whose native window is larger, any task that legitimately needs ~80k of context is in direct conflict with the wall. I reproduced the decision behavior:

    Setup 80k payload Result
    modelContextLimit: 70000 (your config) usage 114% → EMERGENCY, compress forced every single turn preflight wall also crossed → old context folded mid-task or 502 fail-fast — exactly your "keeps getting compressed halfway through"
    modelContextLimit: 200000 (native) + maxContextLimit: "35%" usage 40% → normal OVER-LIMIT nudge, fires every turn until back under 35% payload forwarded as-is — nothing folded, no fail-fast; hard protection only engages near the true native edge

    The second row is the key: the kernel's pressure branch force-injects the compress nudge every turn while usage is above the band (no cadence gaps), so context gets pinned near your target autonomously — while a genuinely large read is allowed to breathe up to the real window instead of being crushed.

    This is the same mechanism documented in #736/#737 (operator-shrunk window → misleading fail-fast); the fix there was to name the shrunken window in the error. What you're asking for goes further: make the target and the wall independent.

    Workaround available today (no code change)

    Set the limit to the model's true native window and use maxContextLimit as your soft target:

    {
      "compress": {
        "modelContextLimit": 200000,
        "maxContextLimit": "35%",
        "emergencyThresholdPercent": "95%"
      }
    }

    (Numbers per your model — e.g. "35%" of 200k ≈ 70k active target; these keys are hot-reloadable via the web UI, and per-model overrides exist under routes.<url>.models.<name>.compress.)

    Behavior you get:

    • Small tasks stay small — below the band, zero compression happens.
    • Growth above the band is trimmed back down automatically each turn.
    • A big read (your 80k case) is forwarded intact; compression only kicks in to keep things bounded, never to reject the request.
    • The 502 fail-fast path is reserved for the only case that truly can't be served: payload beyond the model's actual window.

    Two caveats, both verified:

    • Keep maxContextLimit comfortably below emergencyThresholdPercent.
    • If your soft target is under 45% of the native window, the kernel logs a cosmetic validation warning (minContextLimitPct defaults to 0.45); I verified the over-band nudge path still fires correctly in that configuration.

    Optional follow-up (needs your call before I build)

    A first-class soft-target knob that formally separates the two roles — e.g. exposing minContextLimitPct and making the preflight wall independently configurable from the nudge-band denominator — would remove the workaround's caveats and make "keep context around N tokens, but allow bursts up to the native window" a named, documented setting rather than a ratio trick. Say the word and I'll spec/implement it as its own PR referencing this issue.

  2. walsykerem commented on Sep 22, 2026

    @walsykerem
    Author

    yes it's can be great.do pr!

  3. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 Done — PR is up: #1123

    It adds the one missing knob so the elastic recipe from my previous comment works without caveats:

    • compress.minContextLimit (number | string, e.g. 0.35 or "35%") → kernel nudge.minContextLimitPct. Unset = kernel default (0.45), so existing configs behave byte-identically; three-level cascade (global → provider → model) like every other compress field; hot-reloadable via the web UI.
    • Your full recipe becomes a documented, first-class setting (CONFIGURATION.md gains a "Soft target with elastic headroom" section, zh/en):
      { "compress": {
          "modelContextLimit": 200000,   // native window = hard wall only at the true edge
          "maxContextLimit": "35%",      // soft target ≈ 70k — forced nudge every turn above it
          "minContextLimit": "35%",      // required once under the kernel's 45% default
          "emergencyThresholdPercent": "95%" } }
    • Verified behaviorally against the real kernel decision code through bili's actual per-request config pipeline: with the knob set, an 80k payload on a 200k window (40%) triggers the every-turn nudge below the old 45% floor with no validation warning; a control test proves the warning exists without the knob. Also documented the two facts that matter for tuning: the pressure branch fires at maxContextLimit regardless of min, and modelContextLimit doubles as the hard preflight wall (fold-or-fail-fast) — which is exactly why it should stay at the native window for this pattern.

    Pre-flight on the rebased head (master @ v0.1.135): typecheck clean, 2199 tests pass / 0 fail, build OK. Diff is 7 files, all in scope. Merge stays with you.

  4. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    结束这个根本问题 优化思路 动机 如何实现

  5. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    简述这个根本问题 优化思路 动机 如何实现

  6. walsykerem commented on Sep 22, 2026

    @walsykerem
    Author

    A system that performs compression autonomously when switching to completely different tasks—instead of relying on specified numbers or percentages—could have been more optimized.

  7. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 简述如下(PR 已开好:#1123 ):

    根本问题

    compress.modelContextLimit 一个旋钮同时扮演两个角色:

    1. 使用率分母 —— 所有 nudge/truncate/emergency 阈值都是它的比例(usage = tokens / limit);
    2. 预检硬墙 —— 载荷一旦达到该值,代理在转发前主动折叠上下文(preflight),折叠后仍超出则 502 fail-fast,请求根本不发往上游。

    把它设到模型原生窗口以下(如 200k 模型设 70k),两个角色就互相打架:任何合法需要 80k 上下文的任务,要么中途被反复折叠、要么直接被拒。#1122 报的失败模式正是这个。根因不是压缩太激进,而是配置模型把「软成本目标」和「硬溢出边界」混在了一个字段里。

    动机

    自主 agent 同时要两件事:日常活跃上下文保持小(成本/延迟),但单个任务在确实需要时(读大文件等)能突发远超目标。单旋钮表达不了这种弹性;而且用户不在线盯着,压缩必须自主完成——钉在目标附近靠自动 nudge,大读取放行靠抬高硬墙。

    优化思路

    把两个角色分开:

    • modelContextLimit 回归本义 = 原生窗口,硬墙只在真实边缘生效;
    • maxContextLimit 当软目标——内核压力分支无节奏门控,越过即每轮强制 nudge,这正是把上下文钉在目标附近的机制;
    • 唯一缺口:内核 nudge.minContextLimitPct 默认 0.45,软目标低于它时每轮刷 min>max 校验警告,而 bili 没暴露这个值 → 补一个 minContextLimit 字段。已验证压力分支不受 min 门控,低目标照常触发。

    如何实现(PR #1123,7 文件,+141 −7)

    • src/config.ts:新增可选 minContextLimit?: number | string(比例或 "NN%",解析规则与 maxContextLimit 一致);
    • src/compress-settings.ts:三层级合并 pick + 映射到内核 nudge.minContextLimitPct;不设 = 内核默认 0.45,存量配置逐字节不变;
    • Web UI i18n + CONFIGURATION.md(zh/en 同步):新字段条目、modelContextLimit 硬墙双重角色说明、「软目标与弹性余量」配方章节;
    • 测试:3 个单元(parse/merge/映射)+ 2 个行为测试(走真实 resolveRequestConfig → 真实内核 processTurn:200k 窗口 40% 使用率、低于旧 45% floor 每轮触发且无警告;对照测试证明不设该字段时警告存在);
    • 两种压缩模式均不受影响(§6):纯 per-request Config 变换,不碰 wire shape / 工具注入 / acp_summary / preflight 逻辑;
    • 预检:typecheck clean、2199 pass / 0 fail、build OK。

    配方示例:

    { "compress": {
        "modelContextLimit": 200000,   // = 原生窗口,硬墙只在真实边缘
        "maxContextLimit": "35%",      // 软目标 ≈ 70k,越过每轮强制 nudge
        "minContextLimit": "35%",      // 低于内核默认 45% 时必须同步设置
        "emergencyThresholdPercent": "95%" } }

    效果:低于档位零压缩;高于档位每轮 nudge 直到回落;其间的较大读取原样转发;只有超过真实原生窗口的载荷才撞硬墙。

  8. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 Good direction to think about — let me lay out how it would actually work, where it helps, and where I'd push back, so @ranxianglei can decide if it's worth tracking.

    What "compress on task switch, no numbers" would require

    To compress because a task ended (rather than because usage crossed a band), the proxy would need to detect task boundaries. Realistically three options:

    1. Side-model segmentation — an extra LLM call classifies the history into task segments each turn. Cost + latency on every request, non-deterministic boundaries, and "is reading these 5 files part of the refactor or a separate task?" is genuinely ambiguous.
    2. Heuristics (topic shift, disjoint file sets, new user prompt) — brittle: real agent work interleaves read/edit/test constantly; false positives would fold live context out from under an active task, which is worse than the status quo.
    3. Agent-declared boundaries — the agent marks "task done" and asks for a checkpoint. Most reliable signal (the agent knows its own tasks), but it's no longer proxy-autonomous.

    Why I'd keep the numeric trigger anyway

    Thresholds aren't the problem — they're the stopping condition. A fully number-free compressor has no budget: compress until what? Usage bands give bounded cost, no mid-turn compression storms, and stable prefix caches. The interesting variable isn't when to compress; it's what to fold first. Today that policy is "oldest viable range" — a coarse approximation of "what's least useful now".

    What already exists (often overlooked)

    • Plugin mode: the agent can call compress voluntarily, right now. An agent that summarizes at a natural task boundary (end of a sub-goal, before switching files) gets exactly "compress on task switch" with zero proxy changes — it's a prompting/convention matter, not a mechanism gap.
    • Tiered summaries already preserve the load-bearing facts (decisions, paths, signatures) of finished work, so a new task can decompress/search_context back into the old one instead of keeping it raw.

    My recommendation

    Don't replace usage-based triggering; make the selection structure-aware:

    1. Kernel-side (real engineering, cross-repo): when picking ranges under pressure, prefer coherent segment boundaries (complete tool-call sequences / self-contained exchanges) over arbitrary oldest-N, so folds land at natural seams. Deterministic, testable, keeps the safe trigger.
    2. Agent-side (free, available today): document the "checkpoint-compress at task boundaries" pattern for plugin-mode agents.

    If you want option 1 tracked, say the word and I'll file a properly-scoped acp-kernel issue (with the #1122 source marker) — I'd rather not start that architectural work from an unreviewed suggestion.

  9. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    麻烦这个功能提交到内核,然后billion-context-pi也提交同一个issue,内核合并后本pr跟进

  10. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 已按指示立项,两个 issue 都带来源标记(来源: #1122 分析 "auto compress problem" 时发现):

    主 issue(内核):ranxianglei/acp-kernel#344
    feat: structure-aware range selection(压力压缩优先选连贯任务段边界)
    内容要点:

    • 现状定位到 recommendNode(buildCompressibleRanges → mergeRangesToThreshold),候选生成/排序只按位置与最小长度,无结构判断;
    • 提议:结构感知优先级——端点优先落在连贯段边界(完整 tool-call 序列 / 自洽交换 / tier summary 边界),不切开进行中的工具序列;纯启发式、确定性、可单测,明确不用 side-model 语义分割;
    • 触发条件完全不动(usage band / pressure 分支原样),只改候选顺序与切分点;
    • 附建议验收标准(进行中序列端点保护、自洽段历史回归不变、确定性钉死)。

    镜像 issue(pi):ranxianglei/billion-context-pi#501
    列出 pi 侧内核合并后的跟进清单:确认发布后精确 pin 升级、长多任务会话折叠边界验证、agent 侧决策路径评估、checkpoint-compress 约定文档。

    后续流程(内核合并后本 PR 跟进):

    1. 内核合并并发布 → npm view acp-kernel version 确认新版本已在 npm;
    2. 本仓库 bump acp-kernel 精确 pin(跨仓规则:先验证发布再动依赖);
    3. 回来在本线程更新 PR docs: correct compress soft-target guidance, drop minContextLimit knob #1123 的跟进状态。

    另说明:PR #1123(minContextLimit 软目标旋钮)与该功能相互独立,不依赖内核改动,现在就可以合并——如果你想先落这个,随时可以。

  11. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    你不是说问题主要是增加了maxContextLimit配置吗?为啥反而向内核提交了feat: structure-aware range selection(压力压缩优先选连贯任务段边界)

  12. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 这里其实是两条独立的线,我分开讲清楚:

    线 1 —— #1122 的原始 bug(已修完,PR #1123,与内核无关)
    你最开始报的问题:limit 设 70k、但任务需要 80k 时被反复压缩/失败。根因是 modelContextLimit 一个字段同时当「软目标分母」和「硬墙」。修复就是拆开它:modelContextLimit=原生窗口(硬墙)、maxContextLimit=软目标、新增 minContextLimit 消除告警。
    关键点:maxContextLimit/minContextLimit 这两个字段内核本来就有(nudge.maxContextLimitPct / nudge.minContextLimitPct),#1123 只是把它们从 billion-context 的配置层暴露出来。所以修 #1122 根本不需要向内核提任何东西,PR #1123 独立可合、测试全绿。

    线 2 —— 结构感知范围选择(acp-kernel#344),来自另一条评论
    这是 @walsycommunity 后来单独提的新想法(不是原始 bug):"切换完全不同任务时自主压缩,而不是靠数字/百分比"。我评估后建议的工程路径就是「结构感知范围选择」,并问你要不要立项跟踪。接着你的指示是:「麻烦这个功能提交到内核,然后 billion-context-pi 也提交同一个issue,内核合并后本pr跟进」——所以我按你说的把结构感知立成了 acp-kernel#344 + pi#501。

    两者不矛盾:

    如果你现在不想推进结构感知这个方向,我可以把 #344/#501 关掉或降级,只保留 #1123 合入即可——你来定。

  13. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    minContextLimit 不是应该从内核出吗?为什么内核无关 其他不是所有的配置都是内核出的吗 还是说这个配置是和agent相关的

    https://github.com/ranxianglei/billion-context-pi增加这个参数了吗

  14. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 两个问题分开答,第二个先纠正一下我之前的措辞。

    1. minContextLimit 到底该不该「从内核出」

    我上次说「与内核无关」是措辞不准,准确说法是:内核早就有这个字段,#1123 只补了宿主侧的暴露,所以内核零改动。这里其实是两层:

    • 内核层(acp-kernel):所有阈值旋钮都定义在内核的 Config 对象里并被内核消费——nudge.maxContextLimitPct、nudge.minContextLimitPct(默认 0.45)、nudge.emergencyThresholdPct、truncate.threshold……你的直觉对:这些配置确实都归内核。minContextLimitPct 内核里一直就有,还带校验(min>max 会告警)。
    • 宿主层(billion-context / pi / omp…):每个宿主有自己的用户可见配置 schema,把自己的 key 映射到内核字段。maxContextLimit 在 bili 里本来就有(→ nudge.maxContextLimitPct);缺的只是 minContextLimit 这个宿主侧 key + 映射行。docs: correct compress soft-target guidance, drop minContextLimit knob #1123 加的就是这一层,不碰内核。

    所以它不是 agent 专属,也不是要新造的内核能力——只是同一个内核旋钮在 bili 的配置面上之前没露出来。这也是为什么它能独立于内核、直接合。

    2. billion-context-pi 加了吗?

    没有。 PR #1123 只改了 ranxianglei/billion-context。而且我刚核对了 pi 的代码,它有同样的缺口:

    • pi 的 CompressSettings(src/config.ts)目前只暴露 maxContextLimit / emergencyThresholdPercent / nudgeGrowthTokens / minPressureBenefitTokens;
    • resolveConfig 相应地映射到 nudge.maxContextLimitPct 等,但没有任何 minContextLimit → nudge.minContextLimitPct。

    也就是说 pi 用户如果把软目标设到默认 45% 以下,会遇到和 #1122 一模一样的每轮校验告警,且无配置手段消除。

    建议:值得把同样的 minContextLimit 补进 pi(一个独立的小 PR,跨仓所以按规矩等你拍板)。要做的话我现在就开——你确认一声即可。

  15. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 补充一条:pi 的这个缺口我已经立项跟踪了 → ranxianglei/billion-context-pi#502 (带来源标记,指向 bili#1122/#1123)。

    目前只立了 issue、还没动 pi 的代码/PR——按你说的跨仓等你拍板。确认要做我就把 minContextLimit 镜像进 pi(config key + 映射 + 文档 + 测试,独立小 PR)。

  16. 15 remaining items

  17. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 你的记忆是对的,我上一条的公式错了,先纠正,再给理清楚后的完整关系(全部对着 acp-kernel@0.0.82 dist 实证)。

    先认错:「首次压缩 ≈ min% × 窗口」是错的

    我上条把 firstSightMassReady(L3278)当成了通用首压门槛。但它要求 baseline===0——而 baseline(lastPerMessageNudgeTokens)在第 1 轮结束后就被盖章为非零(nudgeNode L2864-2866),之后只有大幅收缩重置(L2859-2863,重置为当前值,仍非零)。所以那条路实际只在会话第 1 轮可达,不是日常路径。日常触发根本不走 min%。

    理清后的三层关系

    第一层:绝对增长层(日常主力,与窗口无关) —— 就是你记得的「nudge 决定的」:

    nudgeGrowthTokens = min(growthCap 50k, max(growthFloor 20k, round(窗口 × 0.05)))   // L3208-3217, 默认值 L352-356
    T1 nudge 触发 ⇔ 增长量 ≥ growthFloor 且 有效可压缩量 ≥ nudgeGrowthTokens          // L3279, L3304
    

    代入默认值:窗口 ≤400k → nudgeGrowth=20k、growthFloor=20k;窗口 ≥1M → 触顶 50k、growthFloor=22.5k。基准点 = 会话起点 / 上次 nudge 注入点 / 大收缩后。1M 窗口也是 5w 量级,200k 窗口也是 2w 量级——绝对值,被 50k 封顶,不随窗口放大。 你记得没错。

    第二层:百分比压力层(随窗口缩放):usage ≥ max%(默认 75%)→ 每轮强制 nudge;≥95% → 紧急截断。这层才和窗口成正比。

    第三层:百分比资格层(min%,边角料):只出现在两处——第 1 轮冷启动门票(L3278)、T2/T3 按块数升级的地板(L3282-3284)。不参与日常主路径。

    回归判定

    旧配置(limit=70k,默认档位) 配方(limit=原生 1M,max=min=35%)
    增长层 20k/20k 50k/22.5k(≥1M 窗口才变,封顶)
    强制区入口 52.5k(75%×70k) 350k(35%×1M,%可调)
    硬墙(bili preflight) 70k 1M

    行动项

    我上一条给的公式和文档里隐含的「onset≈min%×窗口」说法要撤掉,改成上面的三层模型。要我直接把 #1123 的 CONFIGURATION 章节按这个模型重写吗?

  18. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    撤销min相关参数 只留下衍生的max吧 并确保没有回归问题

  19. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 收到,执行方案如下,先报一个刚验证完的关键事实:

    关键验证:只留 max、设低于默认 45% 时会发生什么

    对着 acp-kernel@0.0.82 dist 查了 validateConfig(L395-399)和唯一调用点(L2669-2674):

    • 不阻断、不 clamp、不改阈值——只是每个 processTurn 打一条 console.warn:[acp-kernel] Config validation warnings: nudge.minContextLimitPct must not exceed nudge.maxContextLimitPct. Thresholds may not fire correctly.
    • 功能上确认无害:min 和 max 在代码里各自独立 gating(min 只管第 1 轮冷启动门票 + T2/T3 块数地板;max 只管强制区),没有任何逻辑依赖「区间非空」。所以 max=35% + 默认 min=45% 时行为完全正确,代价是每轮一条警告日志的噪音。
    • 这个噪音是内核既有行为(不是本 PR 引入),但配方会主动触发它——我会在 acp-kernel 立一个 issue 建议改成去重后只警告一次(带来源标记)。

    执行清单

    1. docs: correct compress soft-target guidance, drop minContextLimit knob #1123 重建为纯文档 PR:撤销全部代码改动(config 键、解析、i18n、两个测试文件),保留并重写 CONFIGURATION 配方章节——按纠正后的三层模型(绝对增长层 / 百分比压力层 / 百分比资格层)+ 只用现有 maxContextLimit 的配方;
    2. 无回归证明:新 head 上跑 typecheck + 全量测试 + build(纯文档改动,预期全绿,拿证据说话);
    3. pi#502 取消(min 镜像 PR 不再需要,分支已备好但未开,直接作废);
    4. 更新 PR docs: correct compress soft-target guidance, drop minContextLimit knob #1123 标题/正文/分支,完成后回帖报结果。

    开始动手,完成后回贴。

  20. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 已按你的决定执行完毕:min 相关代码全部撤销,只保留(已有的)max,PR 变成纯文档。

    交付

    • **新 PR:https://github.com/ranxianglei/billion-context/pull/1147**(docs-only,commit c2954f3)
      • modelContextLimit 条目补上「硬墙」第二角色说明;
      • 新增配方章节「软目标与弹性余量 (auto compress problem #1122)」:modelContextLimit=原生窗口 + 现有 maxContextLimit 管日常目标(% = 目标 ÷ 窗口),并按修正后的三层模型写清触发机制(增长层绝对值 / 压力层 % / 资格层内核默认值)。
    • 旧 PR docs: correct compress soft-target guidance, drop minContextLimit knob #1123 已关闭(留了说明评论):改头时发现 GitHub 的坑——删掉 head 分支后 PR 会永久脱离该 ref,重建同名分支也不会重新挂上,PR 对象冻结在旧 commit。所以关旧开新,新 PR 指向同一 commit。
    • pi#502 镜像取消(未开过 PR,分支丢弃)。
    • acp-kernel#346 已立项:min > max 时每轮 processTurn 刷一条 validation warning(日志噪音;功能无影响——两层管独立代码路径,已逐行验证)。建议按错误集合变化去重。

    无回归证明

    1. 零源码改动:PR diff 只有 2 个文档文件(+58/-2),config schema、wire、默认值全部未动——不存在行为回归的面。
    2. 新 head 全绿:typecheck ✅ / npm test ✅ 2245 pass 0 fail / build ✅(独立 worktree,基于当前 master 0a25e30)。
    3. 配置层面兜底:即使未来有人设 maxContextLimit < 45%(低于内核默认 min),功能也正确——pressure 区与 min 门控互不依赖,唯一代价是上面那条 warning 噪音(ZCode 会话消息丢失:接入 bili MITM 后,旧会话打开无消息、新会话切换后丢失 #346 处理)。

    一句话中文摘要:撤销了 minContextLimit 参数(只保留已有的 maxContextLimit),把修正后的压缩触发模型写成文档交付为新 PR #1147(纯文档零源码改动,测试全绿),可以合并。

  21. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner
    "maxContextLimit": "35%"       // 强制 nudge 区从 ≈ 70k 开始(= 目标 ÷ 原生窗口)
    

    这个本来就有??两个项目??

  22. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 对,两个项目本来就有,不是这次加的。git 证据:

    billion-context(bili)

    billion-context-pi

    • master 上同样有:src/config.ts:146(注释写明 Default: 0.75, Maps to kernel nudge.maxContextLimitPct),三级合并在 config.ts:499,测试覆盖在 tests/config.test.ts:52-58。

    所以这次的工作只是:把「max 本来就能当软目标用」这件事写进文档(配方:modelContextLimit=原生窗口 + maxContextLimit=目标÷窗口),之前那个 minContextLimit 新参数已按你的决定全部撤销。两项目现在都不需要任何代码改动即可用这套配方。

  23. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    pi版本的是否需要提交文档 如果需要你来提交

  24. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 需要,已提交:**https://github.com/ranxianglei/billion-context-pi/pull/509**(仅文档,2 个文件:CONFIGURATION.md / CONFIGURATION.zh-CN.md,+56/-2)

    判断依据:pi 的 CONFIGURATION.md 虽然逐个记录了 compress.maxContextLimit、emergencyThresholdPercent、nudgeGrowthTokens 和三级级联,但同样缺「软目标配方」——即 modelContextLimit 的分母角色说明 + 「分母保持真窗口、成本目标用 maxContextLimit 表达」的完整配方式和三层触发模型。不补的话,pi 用户会踩同一个坑。

    内容(与 bili PR #1147 同构,做了 pi 特化适配):

    1. modelContextLimit 条目补一句分母角色说明 + 指向新章节;
    2. 新章节「软目标与弹性余量 (auto compress problem #1122)」:误配故事(200k 模型设 70k → 强制 nudge ≈52.5k 起、有损截断 ≈66.5k,80k 合法任务中途被压死)、jsonc 配方(maxContextLimit: "35%" ≈ 70k/200k)、三层触发模型。

    pi 与 bili 的两处差异(已按 pi 实际情况写):

    • 没有硬墙说明——pi 无 HTTP 代理层,溢出保护是内核紧急截断(truncate.threshold ← emergencyThresholdPercent),不存在 preflight 502;
    • modelContextLimit 可不填——默认每轮跟随 Pi 实时模型目录(bili 上该字段是硬墙所在,必须填真窗口);
    • 增长层在 pi 上是常数步长:src/config.ts:553-555 把内核 growthFloor+growthCap 都钉到用户的 nudgeGrowthTokens(默认 50k),不像 bili 那样随窗口自适应——但同样是绝对 token、与分母无关,结论不变。

    Pre-flight:typecheck ✅ / build ✅ / tests 86 fail —— 已用 stash 对照验证:干净 master 基线是完全相同的 86 个环境性失败(本沙盒缺 pi host 相关环境),本 diff 零回归。

    一句话中文摘要:给 pi 版补了与 bili #1147 同构的软目标配方文档(纯文档、零行为变更、预检绿),PR #509 待你合并。

  25. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 这条已经处理完了(上一条回复可能你没看到,简短确认):

    **需要,已提交 → https://github.com/ranxianglei/billion-context-pi/pull/509**(刚核实:open、mergeable)

    • 纯文档,2 个文件(CONFIGURATION.md / CONFIGURATION.zh-CN.md,+56/-2),零代码零行为变更;
    • 内容 = 与 bili PR docs: correct compress soft-target guidance, drop minContextLimit knob #1147 同构的「软目标与弹性余量」配方 + modelContextLimit 分母角色说明,按 pi 实际特化(无硬墙/代理层、modelContextLimit 可省略默认跟随 Pi 模型目录、增长步长 = 常数 nudgeGrowthTokens);
    • Pre-flight:typecheck ✅ / build ✅ / tests 86 fail 与干净 master 基线完全一致(环境性,stash A/B 验证过)→ 零回归。

    待你合并即可。

  26. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    本 issue 除了配置还有其他问题吗?我记得已经单独提交 issue ?

  27. ranxianglei commented on Sep 22, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 是的,除了配置本身,#1122 分析中发现了 2 个独立问题,都已单独立项(带来源标记),且实现已在途:

    问题 跟踪 状态
    ① 每轮校验告警刷屏:软目标低于内核默认 45% 时,acp-kernel 每个 processTurn 刷一条 minContextLimitPct must not exceed maxContextLimitPct(功能无害,纯日志噪音) acp-kernel#346 + 修复 PR acp-kernel#347(同一错误集只告警一次) issue 开、修复 PR 开
    ② 压缩不感知任务边界——这才是 OP「切换任务时自主压缩」诉求的深层答案:触发条件保留 usage/growth 驱动(成本有界、无中途压缩风暴),改进放在压力下选哪些范围折叠:优先落在连贯任务段边界,不再从进行中的 tool-call 序列中间切开 acp-kernel#344 + 实现 PR acp-kernel#345(879/879 绿)+ pi 镜像 pi#501(等内核发版后 bump) issue 开、实现完成待合并

    刚才顺手清理的两处遗留(自查发现,透明起见报告):

    1. pi#502 / pi#503(暴露 compress.minContextLimit)已关闭 —— 这一对是在你「撤销min相关参数」决定之前开的(时间戳 10:39Z,另一会话实现完毕),与最终决定矛盾。已各留一条说明后关闭;若你认为仍需要该旋钮,重开即可。
    2. 我自己的两个文档 PR 里引用错了:docs: correct compress soft-target guidance, drop minContextLimit knob #1147 和 feat: add pi-package keyword so pi.dev gallery indexes billion-context (clean, un-bundled) #509 把结构感知压缩链到了 billion-context#344——那个其实是一个无关的已关闭窗口优先级 bug;正确指向是 acp-kernel#344。已补 commit 修正并推送(bili docs: correct compress soft-target guidance, drop minContextLimit knob #1147 @9d96177、pi feat: add pi-package keyword so pi.dev gallery indexes billion-context (clean, un-bundled) #509 @d22d21b)。

    一句话中文摘要:除配置外还有两个已单独立项的问题(内核告警刷屏 acp-kernel#346/#347、结构感知范围选择 acp-kernel#344/#345+pi#501),均已实现或修复在途;另关闭了与你撤销决定矛盾的过期 pi#502/#503,并修正了两个文档 PR 里的错误引用。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions