Repository navigation
[Bug]: 压缩 Quality Gate 失败时仍会向模型暴露内部压缩规则,并可能导致不必要的上下文消耗 #444
Description
Bug Description
当 ACP 的 compression quality gate 失败时,返回给模型的错误信息中仍然包含一些不必要的内部压缩机制和内部指令信息。
本次实际遇到的错误如下:
Range: m00006–m00010
Reason: Summary too short: 670 chars, 0.46% retention (threshold: 200 chars OR 0.5% retention)
Original: ~36234 tokens
Summary: 670 chars
Ratio: 216.3:1
Retention: 0.46%
Gate layer: L1-length
rougeF1: ?
top20Recall: ?
Retry: rewrite a more complete summary that preserves critical details (file paths, decisions, exact values, errors) and call compress again on the same range — the gate re-evaluates automatically. Full compression rules are already in your system prompt. If you are confident the summary is correct despite the metrics, add "acknowledgeRisk": true to bypass the quality gate on your next compress call.
相比上一次,这次错误信息已经明显缩短,但仍然存在内部信息暴露的问题。
例如:
- “Full compression rules are already in your system prompt”
- 明确告诉模型内部存在一套 system prompt 中的完整 compression rules
- 暴露
acknowledgeRisk: true这一内部质量门绕过机制 - 详细暴露 quality gate 的判断逻辑和具体阈值
- 将内部 compression retry 机制直接作为错误信息注入上下文
这些信息对于用户正常理解“为什么这次 compression 没有通过”并不是全部必要的。
尤其是在超长上下文中,这些错误信息会直接成为模型上下文的一部分,从而产生额外的 context consumption。
因此,这个问题不仅是 UI 错误信息过长,更涉及 compression failure 时向模型暴露内部实现细节的问题。
Expected Behavior
Compression Quality Gate 失败时:
- 模型应该能够知道 compression 为什么失败;
- 模型应该能够知道下一步应该如何重新生成 summary;
- 返回的信息应该尽可能简洁;
- 不应主动暴露 system prompt、内部 compression rules 或内部 bypass 参数;
- 不应因为错误处理本身向上下文中加入大量额外内容。
详细的诊断信息应该优先进入 debug log,而不是完整注入模型上下文。
Debug Context Logs
当前未获取完整 debug context log,附件提供了实际 compression failure 截图。Tool Call Details
这里真正希望修复的并不是“Quality Gate 为什么拒绝”,而是“Quality Gate 失败后,为什么还要把内部 compression instructions 和 bypass 机制暴露给模型”。
DCP Version
1.18.1
Opencode Version
1.18.29
Model
Other (specify in description)
Additional Context
本次环境:
OpenCode: 1.18.29
ACP: 1.18.1
本次 compression:
Range: m00006–m00010
Original: ~36234 tokens
Summary: 670 chars
Ratio: 216.3:1
Retention: 0.46%
Gate layer: L1-length
触发原因:
Summary too short: 670 chars, 0.46% retention
(threshold: 200 chars OR 0.5% retention)
截图见附件。
另外,我观察到 compression rejection 似乎不是每次都稳定发生,存在一定的间歇性。不过从本次日志来看,这一次的拒绝原因是明确的:summary retention 为 0.46%,低于 0.5% 的 L1 threshold。
希望确认:
- Quality Gate failure 在 ACP 1.18.1 中是否应该真正阻止 compression;
- 如果应该阻止,是否可以进一步精简 failure message;
- 如果 quality gate 本意只是质量提示而非阻断机制,则需要检查为什么实际显示为
COMPRESSION REJECTED。
Activity
ranxianglei commentedon Sep 20, 2026
继续
ranxianglei commentedon Sep 20, 2026
重启了继续
ranxianglei commentedon Sep 20, 2026
[bot] 🏷 收到,已重启并继续处理。
Triage 结论(Bug 类,三步审核通过)
lib/compress/quality-gate/rejection.ts:66的拒绝消息仍包含三处内部细节泄漏:"Full compression rules are already in your system prompt"—— 暴露"系统提示里有一套完整压缩规则"的内部架构;"to bypass the quality gate"—— 把acknowledgeRisk框定为"绕过质量门"的内部后门机制;Gate layer:/rougeF1:/top20Recall:三行算法内部指标 +Reason里由外部算法包带入的阈值配置(如(threshold: 200 chars OR 0.5% retention))。正在改代码 + 补测试,完成后更新。
ranxianglei commentedon Sep 20, 2026
[bot] 🏷
已修复,PR:**https://github.com/ranxianglei/opencode-acp/pull/447**(Closes #444)
审核结论:这是真实存在的残留问题,不是误报。#397 之前只移除了错误信息里整段嵌入的
HOW_TO_COMPRESS_RULES,但更细粒度的内部信息仍在泄漏——本次补的就是这一层。根因:quality gate 拒绝时,把诊断/架构细节直接拼进了返回给模型的 tool error。这些内容要么 system prompt 里已有、要么属于内部实现,在超长上下文里每次拒绝都会白白消耗 token。
具体修了什么(
lib/compress/quality-gate/rejection.ts+range.ts):Full compression rules are already in your system prompt.(暴露内部 prompt 结构)…to bypass the quality gate措辞(把一个文档化参数说成"绕过后门"),改为中性表述pass "acknowledgeRisk": trueGate layer:/rougeF1:/top20Recall:/ threshold 配置等算法内部字段coreReason():从 reason 里剥掉阈值/配置细节(同时兼容 L1 冒号形式与 L2 括号形式)改后消息约 430 字符(原约 780),只保留「为什么失败 + 怎么重试」:
E2E 依赖的标记
COMPRESSION REJECTED/QUALITY GATE FAILURE保留不变(fake-LLM server 靠它识别拒绝)。回答你的三个确认问题:
COMPRESSION REJECTED命名准确,不存在"名字对不上机制"的问题。测试与验证:
coreReason剥离、诊断入 log、无 logger 兜底);目标套件 19/19 通过;按规范做了变异验证(回退修复后 3 个新用例会失败)。tests/soft-block.test.ts、tests/inactive-block-decompress.test.ts)为环境预存问题(沙箱/tmp只读导致mkdir失败),在干净 HEAD 上同样复现,与本改动无关。未合并(合并由人工操作)。请 review PR #447。
Merge pull request #447 from ranxianglei/2026-09-20_quality-rejection…
fix: keep quality-gate rejection concise — strip internal details, lo…