Repository navigation
fix: sanitize inflated relay usage reports + suppress empty-range growth nudges (#476) - #477
ranxianglei wants to merge 1 commit into
Conversation
📦 Built Plugin ArtifactBranch: Option A — Install from npm PR tag (recommended)opencode plugin opencode-acp@pr-477 --globalEach push to this PR publishes a new version under the Option B — Install from GitHubopencode plugin "github:ranxianglei/opencode-acp#2026-10-06_usage-inflation-nudge-fix" --globalOption C — Download artifact
tar xzf opencode-acp-pr477.tgz
cp -r package/dist ~/.cache/opencode/packages/opencode-acp@latest/node_modules/opencode-acp/dist
This comment is automatically updated on each push. |
[bot] 🏷 结论先行:不建议合并。 CI 红(Node 24 job:13 个既有测试失败,Node 22 随之取消)。我没有只信 CI——已本地复现全部失败并逐点隔离出根因:13 个回归全部由本 PR 自己的三处改动引入,不是环境抖动。PR 自己新增的 19 个测试是过的;问题在于它改变了既有行为却没有对齐既有回归测试。 方向上先给一个提醒(对应原 bug #476,外部用户实测):#476 测到的是稳态 1.76–2.05× 上游虚高。而本 PR 标题主打的 AC1/AC2「sanitize inflated usage」对这种稳态场景基本无效(详见第 6 问);真正堵住事故症状的是 AC3(零区间抑制)+ AC4(错误提示)。下面按七问展开。 1. 是什么问题 2. 什么原因导致的 3. 怎么修复的
4. 是否有回归问题 —— 有,且阻断性(13 个既有测试)
5. 是否破坏缓存 6. 是否改了设计方向 / 方案是否打到核心 7. 是否引入新配置 收工判定:不可合并。 待作者处理三件事:
第 1、2 点方向明确,你确认后我就接手改并走双 agent 评审再交你合并;第 3 点是设计取舍,等你拍板。以上均基于本地复现与逐点隔离验证,未跑全量套件(交由 CI)。 |
Closes #476
Problem
A third-party OpenAI-compatible gateway reported prompt usage at 1.76–2.05× reality (measured per-request payload comparison in #476). ACP inherited that number verbatim as
prePruneTokens/currentTokens, which:growthSinceBaseline→ growth nudges injected with zero actionable ranges (candidateCount=0) in sessions whose visible context was entirely compressed-block summaries;endId mNNNNN is not available — likely consumed by an existing block.→ retry loop (single step 15m02s in the incident).Both defects verified in code before implementing (see triage comments on #476).
Changes
lib/usage-sanity.ts:resolveCurrentUsage(state, messages, logger?)cross-turn inflation detector. Fires only when the reported usage jumps >1.5× while the local chars/4 payload estimate jumps ≤1.5× (both estimates ≥ 5000-token floor); on detection it returns the re-estimated size and logsWARN Relay usage inflation detected — re-estimating context size. Honest reports pass through unchanged; baseline pair{reported, estimated}persisted as new optionalSessionState.usageSanity(old state files load fine; detection skips one turn until seeded).isContextOverLimits(lib/messages/inject/utils.ts),prePruneTokens+postTokens(lib/hooks.ts).lib/messages/inject/inject.ts: newnoRangesAtAllflag (zero compressible AND zero protected messages) OR-ed intonothingToCompress; new audit reasonno_compressible_ranges. This closes the one remaining hole: all other zero-ranges combinations were already covered byallProtected/allInProtectedZone/allBelowMin.lib/compress/search.ts:buildBoundaryRecoveryHintnow enumerates the actual contiguous free spans instead of a first–last window.Behavior changes (old → new)
prePruneTokens/postTokens/currentTokensall_protected,in_protected_zone,below_effective_floor,no_executable_candidatesno_compressible_ranges/compactnoticeCurrent visible: first–last (N msgs). … Call acp_status() to see which blocks consumed which IDs, then retry with valid IDs.Free ranges: <contiguous spans, cap 8 (+N more)>. K active compressed blocks. Retry with IDs inside the free ranges.usageSanity {reported, estimated}appendedKnown accepted limitation (documented in module docstring): a one-shot inflation that then holds steady passes the jump gate. An absolute reported-vs-estimated check was deliberately NOT added because chars/4 undercounts CJK up to ~4× and would false-positive on honest CJK-heavy sessions.
Verification
tests/usage-sanity.test.ts(10),tests/nudge-no-ranges-suppression.test.ts(3, multi-turn with side-effect assertions per §5.7),tests/boundary-recovery-hint.test.ts(6) — all pass.npm run typecheckclean. Global suite left to CI.