Skip to content

[Bug]: 压缩 Quality Gate 失败时仍会向模型暴露内部压缩规则,并可能导致不必要的上下文消耗 #444

Closed

Description

@WantexZard

Bug Description

当 ACP 的 compression quality gate 失败时,返回给模型的错误信息中仍然包含一些不必要的内部压缩机制和内部指令信息。

本次实际遇到的错误如下:

⚠️ COMPRESSION REJECTED — QUALITY GATE FAILURE

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 机制暴露给模型”。

Image

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。

希望确认:

  1. Quality Gate failure 在 ACP 1.18.1 中是否应该真正阻止 compression;
  2. 如果应该阻止,是否可以进一步精简 failure message;
  3. 如果 quality gate 本意只是质量提示而非阻断机制,则需要检查为什么实际显示为 COMPRESSION REJECTED。

Activity

  1. ranxianglei commented on Sep 20, 2026

    @ranxianglei
    Owner

    继续

  2. ranxianglei commented on Sep 20, 2026

    @ranxianglei
    Owner

    重启了继续

  3. ranxianglei commented on Sep 20, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 收到,已重启并继续处理。

    Triage 结论(Bug 类,三步审核通过)

    1. 复现/查证:确认存在。当前 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))。
    2. 层次判断:你点到的就是根因——不是"文案还能再短一点",而是"诊断/架构细节本不该进模型上下文"。fix: concise quality-gate rejection message (issue #396) #397 只解决了"重复注入整段 HOW TO COMPRESS 规则"这一层;本次残留的是更细粒度的内部指标与架构引用。修复方向:模型只见"为什么失败 + 怎么重试",完整诊断改走 ACP debug log。
    3. 方案评估:你的 Expected Behavior(知道为何失败 / 知道如何重试 / 简洁 / 不暴露 system prompt、内部规则、bypass 参数 / 详细诊断进 log)打到了核心,按此实现。

    正在改代码 + 补测试,完成后更新。

  4. ranxianglei commented on Sep 20, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [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": true
    • 移除 Gate layer: / rougeF1: / top20Recall: / threshold 配置等算法内部字段
    • 新增 coreReason():从 reason 里剥掉阈值/配置细节(同时兼容 L1 冒号形式与 L2 括号形式)
    • 完整诊断改为写入 ACP debug log(新增可选 logger 参数),不再注入模型上下文

    改后消息约 430 字符(原约 780),只保留「为什么失败 + 怎么重试」:

    ⚠️ COMPRESSION REJECTED — QUALITY GATE FAILURE
    
    Range: m00006–m00010
    Reason: Summary too short
    Original: ~36234 tokens · Summary: 670 chars · Retention: 0.46%
    
    Retry: write a more complete summary preserving critical details (file paths, decisions, exact values, errors), then call compress again on the same range. If you are confident the summary is adequate despite the metrics, pass "acknowledgeRisk": true.
    

    E2E 依赖的标记 COMPRESSION REJECTED / QUALITY GATE FAILURE 保留不变(fake-LLM server 靠它识别拒绝)。

    回答你的三个确认问题:

    1. 是否应该真正阻止压缩? 是。它是阻断式质量门(reject 时直接 throw,压缩不落盘),不是纯提示。
    2. 能否精简 failure message? 能,本次已完成。
    3. 若本意只是提示而非阻断? 不适用——它就是阻断机制,COMPRESSION REJECTED 命名准确,不存在"名字对不上机制"的问题。

    测试与验证:

    • 新增 4 个用例(无泄漏断言、coreReason 剥离、诊断入 log、无 logger 兜底);目标套件 19/19 通过;按规范做了变异验证(回退修复后 3 个新用例会失败)。
    • typecheck ✅ build ✅;全量 1294 通过 / 2 失败——那 2 个(tests/soft-block.test.ts、tests/inactive-block-decompress.test.ts)为环境预存问题(沙箱 /tmp 只读导致 mkdir 失败),在干净 HEAD 上同样复现,与本改动无关。

    未合并(合并由人工操作)。请 review PR #447。

  5. added a commit that references this issue on Sep 20, 2026
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

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions