You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
nudge 措辞本身太指令化。 gentle voice 开头即 "This is an efficiency nudge to compress early and keep context lean",结尾还附 💡 主动教模型把多个范围折叠进一次调用(kernel/src/nudge-text.ts:31,305),并列出现成的可压缩范围清单——对模型而言这不是「问题」而是「附带清单的指令」,不作为反而像忽视指令。
验证:单测 9/9、集成 4/4(yes 出指令 / no 不注入 / 垃圾回答不注入 / 关闭零差异)、回归对照套件绿、typecheck+build 在 rebase head 全绿;CI 全局把关中。另:全量跑测时在旧 base 上发现 tests/pi-subagent-registry.test.ts 一处失败,已在干净工作树复现确认与本改动无关,且上游 #2234 已修(rebase head 上绿),故不另行立项。
问句——作为决策 side call 末尾的 user message 注入(前缀就是会话已缓存的完整上下文):
[bili-compress-decision] Side-channel question — answer ONLY this. Do not continue your task, do not call any tools.
Given the conversation above exactly as it stands now, is compressing older consumed context NOW net-beneficial for the current task?
Reply with ONLY one line of JSON, nothing else:
{"compress": false}
or {"compress": true, "range": "mNNNNN-mNNNNN", "topic": "<short topic>"}
Rules: compress=true only if the task has clearly moved past the targeted content AND reclaiming it is worth more than keeping it verbatim. Prefer a span from the list below when one fits; otherwise cite any older span you can see in the ACP tags above. Do NOT perform the compression now — only answer.
Compressible spans (oldest first):
m00004–m00021 18 msgs 42.3K [tool 71% | text 29%]
m00022–m00035 14 msgs 18.9K [tool 55% | text 45%]
(span 列表最多列 8 个;没有预检测 span 时最后一行换成 No pre-detected compressible spans — judge from the ACP tags above.)
[bili-compress-directive] Compress NOW — this is a directive issued from your own decision above, not a suggestion.
Target span: m00004–m00021 (topic: "early API exploration"). Call your compress tool on exactly this span in this turn and write the summary per the compression rules. Do not widen or narrow the span unless it contains protected content — then trim to the unprotected part.
Activity
ranxianglei commentedon Oct 6, 2026
结论先行
这个功能值得做,我建议按 路线 A(proxy 侧信道决策调用) 实现:统计闸门触发时,proxy 不直接注入建议式 nudge,而是用当前会话已完全缓存的前缀向模型发一次超短输出的「是否该压缩」决策请求,拿到结构化结果后——要么注入带明确范围的指令式压缩指导,要么什么都不做。默认 OFF、双模式覆盖、emergency 路径绕过决策、无需改 kernel。开工前需要你拍板三件事(见文末)。
一、查重结论
无重复(open/closed 多组关键词检索均零命中)。与既有项的关系:
二、问题审核:批评成立,根因分两层
「注入 nudge 后 90% 无条件压缩」——我对照代码核实,根因大概率是两件事叠加:
kernel/src/nudge-text.ts:31,305),并列出现成的可压缩范围清单——对模型而言这不是「问题」而是「附带清单的指令」,不作为反而像忽视指令。你的方案针对的是 (2),(1) 可顺带解决:决策调用的措辞改为中性提问(「以当前任务为前提,现在压缩是否有净收益?」),指令感自然消失。
三、机制对比(已核代码,这决定可行性)
「决策提问」如何到达模型,有三条路线:
路线 A 的关键点:
{compress:bool, range?, topic?});解析失败/超时/畸形 → 一律视为「否」(绝不在垃圾数据上强压);模型提议的范围还要对照 kernel 实时的可压缩范围(turn.nudge.compressibleRanges)校验,live view 之外的 ref 拒收。通过后才注入指令文本(明确范围+主题指导,模型不再自选范围)。src/absorb.ts:82)。路线 A 引入新的 wire 行为类别,必须设计好超时/重试/失败语义、计费归属、日志隔离。这是本功能的主要架构成本,也是它进人工审查通道的原因。四、两个硬设计问题(我的实质保留意见)
(1) 失败兜底——压缩饥饿风险。 若决策链路长期失效(provider 报错、模型总返回畸形、或永远「否」),上下文将无界增长;今天的建议式 nudge 没有这个问题。必须有升级阶梯:N 次连续「否」或 M 次连续决策失败 → 回退旧版建议式 nudge(恢复现状);现有 emergencyNudge(usage-based)与 truncate.threshold 保持不变作最后防线。建议 N=3。
(2) 缓存锚点与统计隔离。 决策调用必须复刻主请求的 anthropic cache mark 布局(server.ts 的
anthropicCacheMarks路径),才能真正吃到缓存命中——这是「成本极低」承诺成立的关键;同时决策调用的 usage 不得计入主轮统计(cache-ledger/acp-usage),否则命中率报表失真;日志加独立[acp-decide]标记。模式覆盖(§6 双模式推演):已核实
src/server.ts:3969-3984—— nudge 在 plugin 和 proxy 两种模式都注入(plugin 模式下 agent 自带 ACP 工具但没有自己的 nudge 通道,proxy 侧 nudge 就是主动触发器,#451)。所以决策调用放在同一位置(willInjectNudge 将为真处)即可同时覆盖两模式。Emergency 路径(emergencyNudge/over-limit)不走决策调用——到限了时间 > 聪明,先问会浪费一个往返。不需要 kernel 变更:kernel 的 NudgeDecision 计算原样保留(仍由统计闸门决定「要不要问」),host 侧只替换「触发时做什么」。五、配置面草案(owner-gated,待你拍板,未动工)
沿三级级联 global→provider→model,
compress下最小面,全部可选,默认 OFF = 与今天逐字节一致:nudgeModelDecided(暂定名)nudgeDecisionMaxTokens内部常量不暴露:决策失败回退阈值(连续次数)、决策调用超时。为什么现有面表达不了:现有 nudge* 族只控制「频率/阈值」(growthFloor/Cap/min/max/injectNudge),没有「触发时如何行动」这一维度的字段;这是行为模式字段而非数值参数。env 镜像 + CONFIGURATION.md en/zh 按惯例随附。
六、风险与验收
七、请你拍板三件事
拍板后我立即开工:PR 引用本 issue(#2228)、走人工审查通道。批准前不动代码。
ranxianglei commentedon Oct 6, 2026
同意 先搞一个版本看看效果
ranxianglei commentedon Oct 6, 2026
收到,开工。路线 A 一期:默认 OFF(
compress.nudgeModelDecided)、双模式覆盖、emergency 绕过、失败兜底阶梯(N=3 连败回退建议式)、零 kernel 变更。完成后 PR 引用本 issue 并在此汇报。ranxianglei commentedon Oct 6, 2026
进度
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 进度汇报:v1 已开发完成,正在收尾。
已完成
src/nudge-decide.ts:决策提示词构造、严格 JSON 解析({"compress": true|false, "range"?, "topic"?},非法即失败、绝不乱压)、范围程序化裁定(模型建议的范围只有完整落在某个存活可压缩范围内才采纳,否则取最大存活范围)、自愈阶梯(连续 3 次硬失败后回退一次原有 advisory 并清零)。compress.nudgeModelDecided(bool,默认关)、compress.nudgeDecisionMaxTokens(number,默认 200),走既有三级 cascade;无新增 env var(彻底整治环境变了滥用,除非必要都走配置文件 #2030 纪律)。CONFIGURATION.md 中英文档已同步。进行中:刚把分支 rebase 到最新 master(无冲突),在 rebase 后的 head 上重跑定向验证,随后推分支开 PR。预计很快出 PR 链接。
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 v1 完成,PR 已开:**https://github.com/ranxianglei/billion-context/pull/2243**(分支
2026-10-06_nudge-model-decided,已 rebase 到最新 master,无冲突)。怎么用:配置里加
"compress": { "nudgeModelDecided": true }(可选"nudgeDecisionMaxTokens": 200)。开启后观察日志里的[acp-decide] ... outcome=yes/no/failed即可看到每次决策结果。结构化七问
compresscascade 下:compress.nudgeModelDecided(bool,默认 off)、compress.nudgeDecisionMaxTokens(number,默认 200,必须 >0);无新增 env var(彻底整治环境变了滥用,除非必要都走配置文件 #2030 纪律);CONFIGURATION.md 中英文档已同步。PR 含 config surface 专节。验证:单测 9/9、集成 4/4(yes 出指令 / no 不注入 / 垃圾回答不注入 / 关闭零差异)、回归对照套件绿、typecheck+build 在 rebase head 全绿;CI 全局把关中。另:全量跑测时在旧 base 上发现
tests/pi-subagent-registry.test.ts一处失败,已在干净工作树复现确认与本改动无关,且上游 #2234 已修(rebase head 上绿),故不另行立项。判定:可进入 review;建议合并前手动开
nudgeModelDecided: true跑一轮真实会话看[acp-decide]日志效果。docs: seed the two #2228 config fields in website/config-reference/co…
docs: correct stale header comment in nudge-decide.ts (#2243 review)
ranxianglei commentedon Oct 6, 2026
tier-1(温和增长/超阈值)arm 时先发一次决策 side call
这个是不是随着注入频率开启的 还是说每次请求都有
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 只随 nudge arm 频率,不是每次请求。side call 的触发点就是原来注入 advisory 的那个判断(
willInjectNudge && turn.nudge),没 arm 的请求连问都不问、零额外开销。具体分两种 arm:1. 增长型(温和增长)——有节奏门,约每 50K 增长一次
内核对同一 tier 有 cadence 门:
tokenCount - lastShownByTier[tier] >= growthFloor(flat 50K,可用nudgeGrowthTokens调)。关键点在 kernel/src/compress.ts:1038-1048——只要内核判定shouldInject=true就会打戳(lastShownByTier[tier] = tokenCount),不管宿主最终有没有真注入文本。所以模型答 "no" 那轮虽然什么都没注入,但节奏戳已经打上:下一轮不会立刻再问,要等新的 ~50K 可折叠增长才重新 arm。不存在 "no → 下轮再问 → no → …" 的连环问。2. 超阈值型(OVER-LIMIT,usage ≥ maxContextLimit)——压力分支绕过节奏门,arm 期间每个请求都会问
这是唯一需要留意的成本场景:上下文一直卡在阈值以上且模型持续答 "no" 时,每个请求都会发一次决策 side call,直到压下去(或降到阈值以下)。我认为这是合理语义而非缺陷——此时上下文真的在压力下,问题本身是悬而未决的,反复问直到解决是对的;而且每次问都走已缓存前缀、输出 ≤200 token、15s 超时封顶,单次成本很低。EMERGENCY 档(≥95%)完全不经过决策,直接走原 advisory + truncate 安全阀兜底。
如果你希望超阈值场景也加个"连续 N 次 no 后降频/停问"的节奏(比如宿主侧记一个 lastAsked),可以作为一个小 follow-up 加;v1 先保持"压力下每次必问"的简单语义,看真实跑下来这个成本是否值得管。
ranxianglei commentedon Oct 6, 2026
这个不需要问了 这时候就必须压缩了,模型没有权利跳过了
只有温和增长需要问
另外一个问题,问答提示词是什么 ?答案样板我看看
feat: model-decided nudge timing (compress.nudgeModelDecided, #2228)
fix: over-limit pressure arms never consult the model (#2228 ruling)
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 两点都处理完了,PR #2243 已更新(rebase 到最新 master,force-with-lease 推上去了)。
1. OVER-LIMIT 不再问模型 —— 已改
gate 从「tier===1 && !emergencyOverride」收紧为「tier===1 && overLimit !== 1 && !emergencyOverride」,四条 wire(anthropic/openai/google/responses)一致。现在只有温和增长型 tier-1 arm 走决策;超阈值/紧急压力分支和 tier≥2 蒸馏逐字节保留原 advisory,模型没有否决权。文档(en/zh)、模块头注释、PR 描述同步更新。
测试也重写了:原来的 e2e fixture 其实一直在打 OVER-LIMIT 分支(78% > 75%),正好是这次要禁掉的路径。新的温和增长 fixture 需要三轮才能确定性触发——因为 usage 报告滞后一轮(
settleUsageReport在每次响应后才落账):turn1 播种基线 → turn2 的报告把 turn3 的 prepare 推到 62.5%(<75% 超阈值线)且增长 60k ≥ 门槛。新增第 5 个场景专门钉住你的裁决:over-limit → 零 side call、advisory 立即注入。结果:e2e 5/5、单测 9/9、旧 nudge 回归对照 2/2、typecheck 干净。2. 问答提示词原文(
src/nudge-decide.ts,宿主拥有、非 kernel advisory)问句——作为决策 side call 末尾的 user message 注入(前缀就是会话已缓存的完整上下文):
(span 列表最多列 8 个;没有预检测 span 时最后一行换成
No pre-detected compressible spans — judge from the ACP tags above.)答案样板(解析器要求整条响应就是一个裸 JSON 对象,容忍 ```json 围栏;带任何散文即判 garbage → 本轮不注入):
模型答 yes 后,主请求里注入的指令长这样(范围由程序最终裁定:建议 span 只有完整落在某个存活可压缩范围内才采纳,否则取最大存活范围):
一个诚实的边界说明:OVER-LIMIT 路径注入的仍是原来的 advisory 文本("context limit reached, compress now + 可折叠范围清单"),不是上面的 directive 格式——那里模型没有选择权,所以直接给清单让它执行即可;真正的硬兜底还是 95% 的 truncate。如果你觉得超阈值场景也想要更强的指令措辞(比如 directive 同款格式),说一声我就加一个变体。
ranxianglei commentedon Oct 6, 2026
这个是否可以做思考动态降低?
feat: reduce extended thinking on the nudge decision side call (#2228)
ranxianglei commentedon Oct 6, 2026
[bot] 🏷 可以,已经做了——决策 side call 现在会动态降档思考,已推上 PR #2243(commit
9eec3fa92)。规则:只在客户端本次请求里真的开了思考旋钮时才降,没发的键绝不新增(wire 保真),且只动顶层请求字段——消息内容(包括带签名的思考块)逐字节不动:
thinking: {type:"enabled",…}thinking: {type:"disabled"}reasoning_effort: "high"reasoning_effort: "minimal"reasoning: {effort:"high"}reasoning: {effort:"minimal"}reasoning: {…}reasoning: {effort:"low"}generationConfig.thinkingConfig: {…}thinkingBudget: 0理由很简单:这个问题要的答案就是一行 JSON,extended thinking 只会把 200 token 的输出预算烧在推理上、再拖慢 arm 一拍;而且降档不影响缓存命中——这些是顶层字段,不在消息前缀里。
responses 用
"low"而不是"minimal":minimal不是所有 Responses 端点都认,low是通用下限。测试:e2e fixture 的客户端请求现在带
reasoning_effort:"high",三个走决策的场景都断言 side call 回来是"minimal"(16/16 绿,typecheck 干净)。文档 en/zh 同步。顺带说明一个边界:这个降档只作用于决策 side call,主请求的思考配置原样透传——主回复该思考多少还思考多少。
ranxianglei commentedon Oct 8, 2026
冲突
feat: model-decided nudge timing (compress.nudgeModelDecided, #2228)
fix: over-limit pressure arms never consult the model (#2228 ruling)
feat: reduce extended thinking on the nudge decision side call (#2228)
ranxianglei commentedon Oct 8, 2026
[bot] 🏷 冲突已解,PR #2243 重新可合并。
原因:master 前进了 ~45 个提交,其中 external-summary-surface 那条线给四个注入点的
withStagedCompressGuidance(...)加了第三个参数externalSummaryEnabled(config)(anthropic/openai/responses 三处;google 侧 master 保持两参),正好落在我重写的四个 nudge 块上 → 文本冲突 ×4。解法:取并集——保留我的三路决策结构(fallback / decide / legacy),把 master 的新参数合进我新增的每一处调用(directive 注入也带上了该参数,与 advisory 同链)。gate 逻辑、决策 side call、ladder 均未被上游改动触及,后两个 commit(over-limit 裁决 + 思考降档)自动干净重放。
验证(rebase head
92c8f5b53):typecheck 干净;定向测试 16/16(nudge-decide 9 + nudge-model-decided 5 + plugin-nudge-injection 2 回归对照)绿。期间环境重置过一次 node_modules(重装后复跑确认是环境问题不是代码问题)。已 force-with-lease 推上分支,GitHub 状态应为 clean。feat: model-decided nudge timing (compress.nudgeModelDecided, #2228)
docs: seed the two #2228 config fields in website/config-reference/co…
docs: correct stale header comment in nudge-decide.ts (#2243 review)
fix(summary): unwrap the data envelope on the model-decided nudge pat…