Skip to content

[PR] fix: clear compress-failure accounting on rebase; exempt post-rebase stale-ref from the model breaker (#5984) - #5985

Closed
ranxianglei wants to merge 1 commit into
masterfrom
2026-11-09_rebase-compress-breaker
Closed

ranxianglei wants to merge 1 commit into
masterfrom
2026-11-09_rebase-compress-breaker

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

What & why

After a host-native compaction rebase, the model is repeatedly steered into a compress call that must fail, and after three such failures the circuit breaker arms a hard stop that then hides the only recovery path — the model dead-ends ("circuit breaker says stop") and gives up compressing for the round.

Two defects on the rebase path, both confirmed by reading the code:

  1. Failure accounting survives the rebase. A native-compaction rebase restarts the ref space (resetSessionCompression resets state and pins refs at a floor), but it did not clear the two compress-failure accounting fields that live on session metadata — the #2146 consecutive-failure breaker streak (compressFailStreak) and the #847 exact-spec repeat guard (compressFailKeys). Those were cleared only on a successful compress. So a pre-rebase streak could carry across the generation break and arm mid-loop on the new refs.

  2. The post-rebase stale-ref storm arms a dead-end. While the model still carries its pre-rebase refs in its own persisted history, its compress calls resolve to "every ref is unknown". Each advanced the model-failure breaker; at three, the armed receipt drops the rebase note, scrubs the acp_status recovery guidance, and orders "do not poll acp_status" — i.e. it removes the exact step that would let the model out. This is the reported "circuit breaker says stop".

Note: within a single turn the status line's highest and compressibleRanges come from the same processTurn result (internally consistent), so this is not a same-turn mix-up — it's temporal: the model acts on hints it retained from its own history across the rebase.

Fixes

  • Rebase clears failure accounting (root-cause fix): resetSessionCompression now deletes both keys; it runs inside reconcileNativeCompactionBoundary, the single choke point every rebase funnels through (openai/codex/responses/google/anthropic prepare paths). The key names move to session.ts so both modules share one source of truth (stream already imports session; no new import cycle).
  • Post-rebase stale-ref is proxy-caused, not a model failure: noteCompressLoopFailure treats a stale-ref failure inside a 30-min post-rebase grace window as caused by bili's own rebase and does NOT advance the model-failure breaker — returning "" keeps the non-armed recovery cluster (rebase note + current-refs snapshot + kernel acp_status guidance) visible until one success clears everything. Non-stale causes (parse / covered-by-block / content-changed) still count even right after a rebase. No threshold or breaker wording changes.

Behavior change (old → new)

  • Rebase now clears the compress-failure streak + exact-spec guard. Old: they survived the boundary and carried into the new generation. New: dropped at rebase. Reason: the ref space they describe no longer exists.
  • Post-rebase (≤30 min) stale-ref failures no longer advance the model breaker. Old: counted toward the 3-strike arm. New: skipped while in the grace window. Reason: the proxy itself invalidated those refs; punishing the model for acting on them dead-ends the recovery path. Bounded so a genuine loop still arms once the grace elapses.

Tests

New tests/issue5984-rebase-breaker.test.ts (6 cases): rebase clears both keys; no-boundary guard leaves them untouched; post-rebase stale-ref never arms; plus three guards pinning unchanged behavior (no-rebase still arms at 3, grace elapsed arms at 3, non-stale causes still arm). All pass. Existing breaker/rebase suites (issue2146, issue2592, issue2432-breaker-awareness, issue4812, issue847, issue3126, issue2432-dsh-local-compaction, issue2117, issue1933, issue1502, issue1820, compress-observability) all green locally. Full-suite verdict = remote CI.

Typecheck clean. No kernel/ / pi-subagents/ touch.

Closes #5984

@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-11-09_rebase-compress-breaker (436d391)

Latest build — install this exact version

npm install -g billion-context@0.0.8907-pr.5985.f8034aa

This exact version is immutable and reproducible. The rolling pr tag tracks the newest test build across all PRs.

Recent builds (commit → version)

commit version build
436d391 billion-context@0.0.8907-pr.5985.f8034aa build
c36686c billion-context@0.0.8704-pr.5985.b9100c5 build

Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr5985.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei ranxianglei changed the title fix: clear compress-failure accounting on rebase; exempt post-rebase stale-ref from the model breaker (#5984) [PR] fix: clear compress-failure accounting on rebase; exempt post-rebase stale-ref from the model breaker (#5984) Nov 8, 2026
@ranxianglei ranxianglei added bug Something isn't working p1 scope/kernel labels Nov 8, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

已按 [PR] 审核流程处理(不重做):拉取分支 2026-11-09_rebase-compress-breaker @ c36686c,逐行核对代码、验证既有行为、本地定向跑测试。结论:修复方向正确、最小化、无回归;CI 当前仍 pending,转绿后可人工合入。

结构化八问

  1. 是什么问题:host-native compaction rebase 之后,模型被反复引导去做必然失败的 compress;连续三次触发熔断(dsh内部问题 出现这个错误后,重启dsh可以发消息 但陷入无限压缩失败 #2146),而熔断回执会删掉 rebase 提示、屏蔽 acp_status 恢复指引并命令"别查 acp_status"——恰好掐死唯一出口,模型当轮死锁放弃压缩(即报告的"circuit breaker says stop")。

  2. 什么原因导致的:两层根因,非表面现象。(a) rebase 重启 ref 空间(resetSessionCompression 重置 state + pin refs 到 floor),但没清掉两个挂在 metadata 上的失败记账字段——compressFailStreak(dsh内部问题 出现这个错误后,重启dsh可以发消息 但陷入无限压缩失败 #2146 熔断连击)与 compressFailKeys(出现持续压缩失败,无法自动恢复 #847 精确规格重复守卫);它们只在 compress 成功时清除,pre-rebase 的连击会跨代存活。(b) 模型自己持久化历史里还留着 pre-rebase 旧 ref,其 compress 调用必然解析为"全部 unknown",每次都推进模型熔断计数到三次。

  3. 影响范围与严重程度:任何经历 host-native compaction rebase 的会话,在模型消化完旧 ref 之前都会踩中。严重度 p1——rebase 后本应可用的压缩能力被熔断直接掐断,属"核心承诺失灵"档。

  4. 怎么修复的:两处根因修复,均在决策点/源头,非症状层过滤。① rebase 唯一 choke point(reconcileNativeCompactionBoundary → resetSessionCompression)删除两个记账键——ref 空间已不存在,记账作废;键名上移到 session.ts 作单一事实源(stream 本就 import session,无新环)。② noteCompressLoopFailure 把"post-rebase ≤30min 宽限窗内的 stale-ref 失败"判为 bili 自身 rebase 所致,不推进模型熔断计数,返回 "" 使非熔断恢复簇(rebaseNote + currentRefsSnapshot + kernel acp_status 指引)保持可见且不被 scrub。非 stale 原因(parse / covered-by-block / content-changed)照常计数。

  5. 是否有回归问题:审过既有行为,无回归。逐项核查:

    • resetSessionCompression 全仓仅一个调用点(reconcile),行为变更精确限定在 rebase 路径,不外溢;
    • nativeCompactionAt 全仓仅一个写点(reset 内),withinRebaseGrace 依赖它可靠判定"最近 rebase"成立;
    • 出现持续压缩失败,无法自动恢复 #847 守卫刻意保持活跃(仅软提示 [Repeat-failure guard],非死锁源),只豁免 dsh内部问题 出现这个错误后,重启dsh可以发消息 但陷入无限压缩失败 #2146 硬停——最小化裁切正确;
    • 阈值(COMPRESS_LOOP_THRESHOLD=3)、decay(10min)、熔断措辞均未变;
    • 两种压缩模式(plugin/proxy)都推过:豁免由 kernel 错误文本("every ref is unknown")驱动,两模式一致;30min 有界,真循环出窗后照常熔断。
    • 相关套件本地全绿:issue2146 / 847 / 2432×2 / 2592 / 3126 / 4812 / 1820 / compress-observability 共 72 项 pass,fail 0;typecheck 干净(exit 0)。
  6. 是否破坏缓存:不涉及。改的是失败记账元数据与出站回执文本,不触碰 prefix cache / KV / 增量游标 / 去重键失效策略。

  7. 是否改了设计方向:不涉及架构转向。属既有 dsh内部问题 出现这个错误后,重启dsh可以发消息 但陷入无限压缩失败 #2146/出现持续压缩失败,无法自动恢复 #847 熔断机制的边界修正——把"proxy 自身造成的 stale-ref"从"模型失败"里区分出来。

  8. 是否引入了新的配置:无 env/config/默认值新增。REBASE_STALE_GRACE_MS = 30min 硬编码,与 COMPRESS_LOOP_* 同一 config-surface 纪律(刻意不开放配置面)。

行为变更披露(old → new)

  • rebase 现在清除 compressFailStreak + compressFailKeys(旧:跨边界存活带入新一代)。原因:它们描述的 ref 空间已不存在。
  • post-rebase ≤30min 内 stale-ref 失败不再推进模型熔断(旧:计入三次熔断)。原因:这些 ref 是 proxy 自己作废的,惩罚模型会死锁恢复路径;有界,出窗后真循环仍会熔断。

测试有效性:新增 6 例含正负双向。另做一次"拔牙"验证——临时把豁免条件置假,test B 立即以 issue 原文 do not poll acp_status 的 CIRCUIT BREAKER 熔断失败,证明测试真实复现症状而非恒真断言;还原后全绿。

CI 状态(live 核过):pending —— 3 个 test shard in_progress,静态门禁 34 项全绿,无失败;我未能从 CI 拿到最终绿。本地定向 78 项(6 新 + 72 关联)+ typecheck 干净作为佐证,最终裁决以远程 CI 为准。

合入判定:代码/行为层面通过,建议 CI 转绿后人工合入。不建议 auto-merge(§7.4:改了模型可见回执内容 = wire/message-shape,且动了 session 状态元数据 → 人工档)。标签 bug/p1/scope/kernel 已齐且恰当,无需调整。本次未发现需另立 issue 的独立缺陷。

…stale-ref from the model breaker

A host-native compaction rebase restarts the ref space but left two
compress-failure accounting fields on the session — the #2146 consecutive-
failure breaker streak and the #847 exact-spec repeat guard — which are only
cleared on a successful compress. Two consequences:

1. A pre-rebase failure streak could carry across the generation break and arm
   mid-loop on the new refs.
2. The stale-ref failures that are inevitable while the model still carries its
   pre-rebase refs in its own persisted history armed the breaker after three;
   the armed hard-stop receipt then scrubs the acp_status recovery guidance —
   the only way out — leaving the model dead-ended ("circuit breaker says stop").

Fixes:
- resetSessionCompression now clears both keys at the single choke point every
  rebase funnels through (reconcileNativeCompactionBoundary); the key names move
  to session.ts so both modules share one source of truth.
- noteCompressLoopFailure treats a stale-ref failure inside a 30-min post-rebase
  grace window as proxy-caused (bili itself rebased) and does not advance the
  model-failure breaker, keeping the non-armed recovery hints visible until one
  success clears everything. Non-stale causes still count even right after a
  rebase; no threshold or breaker wording changes.

Behavior change (old -> new):
- rebase now clears the compress-failure streak + exact-spec guard (they
  previously survived the boundary).
- post-rebase (<=30 min) stale-ref failures no longer advance the model breaker
  (they previously did, arming at 3).

Closes #5984
@ranxianglei
ranxianglei force-pushed the 2026-11-09_rebase-compress-breaker branch from c36686c to 436d391 Compare November 10, 2026 06:56
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

Merge conflict resolved & pushed. Rebased the PR onto the current master head and force-pushed the result.

  • Old head c36686cbcf → new head 436d391d6e, on origin/master @ 4dea18eabf (single commit, parent == master head, so the branch is now a clean fast-forward over master — conflict gone by construction).
  • Only ONE textual conflict existed: the ./session.js import line in src/stream.ts:6. Resolved as the union of both sides — kept master's truncatedUpstreamOf and the PR's COMPRESS_LOOP_KEY / FAIL_STREAK_KEY. Verified by grep that all three symbols are exported by src/session.ts and actually used in src/stream.ts (no dangling import).
  • src/session.ts auto-merged; the new test file applied cleanly. Diff vs master is exactly the PR's 3 files (no stray changes).
  • Local targeted validation on the new base: typecheck clean (exit 0); the PR's own 6 tests pass; the 5 directly-related neighbor suites (issue2146/issue847/issue2592/issue2432-breaker-awareness/issue2432-dsh-local-compaction) = 38/38 pass — confirming none of master's 314 intervening commits interact semantically with this fix. Full-suite verdict = remote CI.
  • Force-push used --force-with-lease pinned to the exact prior SHA, so it would have safely aborted if any concurrent agent had moved the branch (none had).

结构化八问

  1. 是什么问题:PR [PR] fix: clear compress-failure accounting on rebase; exempt post-rebase stale-ref from the model breaker (#5984) #5985 与其 base 冲突(dirty)——PR 停在旧 master base 上,master 已前进 314 个提交,导致无法合并。
  2. 什么原因导致的:PR 是单提交 c36686c,基于旧 base 848f59b996 切出;此后 master 前进 314 提交,其中对 src/stream.ts 的 ./session.js import 行有改动(master 侧加了 truncatedUpstreamOf),与 PR 对同一行的改动(加 COMPRESS_LOOP_KEY/FAIL_STREAK_KEY)发生文本冲突。
  3. 影响范围与严重程度:仅阻塞本 PR 的合并路径,不影响任何运行时行为。属"合并被卡"型阻塞,非功能缺陷。
  4. 怎么修复的:rebase 到当前 master 头;唯一冲突(import 行)取两侧并集——同时保留双方新增的符号,而非任一侧丢弃另一侧;push 前用 lease 钉死原 SHA 防并发覆盖。
  5. 是否有回归问题:无。typecheck 干净;PR 自带 6 项 + 5 个直接相关邻居套件共 44 项全过;diff 相对 master 恰好只有 PR 的 3 个文件,无夹带。高危模式逐项过:无语义漂移、无阈值/时序/输出格式变化(本次仅动 import 行,PR 自身行为变更已在 floor 3 审核披露且未变)。
  6. 是否破坏缓存:不涉及。冲突消解未触碰任何缓存/重试/游标/去重键失效策略;PR 本就不碰缓存面。
  7. 是否改了设计方向:不涉及。纯机械冲突消解,PR 的修复设计(floor 3 已审)保持不变。
  8. 是否引入了新的配置:无。rebase 不新增任何 env/config/默认值;PR 原本也没有(REBASE_STALE_GRACE_MS 硬编码,刻意不开配置面)。

收工判定:冲突已解决并推送,分支现直接落在当前 master 头之上,合并状态应转干净。镜像 check 缓存此刻仍是旧 c36686c 的 stale 快照(checks 显示 skipped 是因先前 dirty 状态被跳过,不代表新头结果)——CI 将在新头 436d391d6e 上重跑,以远程 CI 为最终裁决。按 §7.4(wire/message-shape + session 元数据)建议 CI 转绿后人工合入,不 auto-merge。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

@ranxianglei ranxianglei left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: posted as a review comment because GitHub blocks self-approval of one's own PR; the verdict below stands.

(ai: vllm-qwen/qwen3.8-27b)

Verdict: APPROVE — clean, correct, well-scoped root-cause fix. Independently re-derived from the diff (not from the issue's own analysis).

What I checked

  • Direction (issue #5984). After a host-native compaction rebase the ref space restarts at m00001, but the status line mixed a pre-rebase compressibleRanges span with the post-rebase highest, so the model copied a range that can never resolve → 3 guaranteed unknown failures → breaker arms → the armed receipt scrubs the very acp_status recovery guidance that is the only exit. The PR attacks that mechanism, not the symptom.
  • Fix A — rebase clears failure accounting. resetSessionCompression (src/session.ts:1731) now deletes both COMPRESS_LOOP_KEY (compressFailStreak, #2146 streak) and FAIL_STREAK_KEY (compressFailKeys, #847 guard). Verified resetSessionCompression has exactly ONE src caller — reconcileNativeCompactionBoundary (src/session.ts:1808, call at :1820) — reached only from the prepare/rebase paths (anthropic/google/openai/responses) and gated on nativeCompactionBoundary.pendingRebase === true. So the clear fires ONLY on a genuine rebase, never on an unrelated reset. Also confirmed these are the ONLY two compress-failure accounting fields on session metadata (completeness — no third survivor).
  • Fix B — post-rebase stale-ref ≠ model failure. noteCompressLoopFailure (src/stream.ts:332) derives freshCause first; when it starts with "stale-ref" AND withinRebaseGrace (≤30 min since nativeCompactionAt) it logs and returns "" WITHOUT advancing the streak. Verified reachability: compressFailureCause (src/stream.ts:441) returns "stale-ref — …" for the exact every ref is unknown to this session text. Verified nativeCompactionAt has a single writer (session.ts:1796), so withinRebaseGrace cannot false-trigger from any other path. Verified the receipt (src/stream.ts:1522-1524) selects the full recovery cluster (rebaseNote + currentRefsSnapshot + …) precisely when loopGuard === "" — returning "" is exactly what keeps the exit visible instead of the armed "do not poll acp_status" paragraph.
  • No silent regression from skipping the streak write. acp_status's compressLastFailureCause (src/acp-status.ts:273) feeds only the armed-breaker annotation block; a pure stale-ref-during-grace never arms, so dropping the write loses nothing. Non-stale causes (parse / covered / content-changed) still advance normally inside the grace window. Hoisting freshCause before the streak read is behavior-preserving for the non-exempted path — compressFailureCause is pure over (errs, metadata[METADATA_DRIFT_ESCALATED]), independent of the streak.
  • Tests (tests/issue5984-rebase-breaker.test.ts, 6 cases). Real functions exercised (reconcileNativeCompactionBoundary, noteCompressLoopFailure); positive+negative per gate — A: rebase clears both keys / no-boundary leaves them untouched; B: grace exempts / no-rebase still arms-at-3 / grace-elapsed arms-at-3 / non-stale arms-at-3. Assertions have teeth (each fails if its mechanism regresses); not tautological.
  • Conventions & hygiene. No kernel/ or pi-subagents/ touch (so no kernel authz gate applies). REBASE_STALE_GRACE_MS = 30min is hardcoded like the existing COMPRESS_LOOP_* constants (config-surface discipline — no new knob invented). ctx.log used, not console.error; no as any; comments match this file's established why-with-issue-ref style. Diff is tight (+180/−15, every line on-purpose, no lockfile/whitespace churn). Behavior drift disclosed in the PR body (old→new ×2).
  • CI. Mirror cache for head 436d391: 15 success / 15 skipped / 0 failed — green.

One considered trade-off (not a defect, no action): compressFailureCause lumps rebase-killed refs, typos, and pruned gaps under one stale-ref label, so a genuine typo'd ref within 30 min of a rebase is also exempted from the breaker. That is the intended, deliberately-bounded cost of the fix — right after a rebase the model's persisted history is dominated by dead pre-rebase refs, so attribution to the proxy is overwhelmingly correct; exposure is capped at the 30-min window and non-stale causes still arm immediately. Acknowledged and acceptable as designed.

No small findings to fix on the spot; no decision items.


结构化八问(供人工复核)

  1. 是什么问题: 宿主原生压缩触发 rebase 后,压缩失败计数没有清零;模型沿用旧 ref 必然失败、连续三次熔断;而熔断回执又把唯一能救场的 acp_status 恢复指引抹掉,模型本轮彻底放弃压缩(死锁)。
  2. 什么原因导致的: rebase 重启了 ref 空间(resetSessionCompression),但两个失败会计字段(#2146 streak / #847 guard)历史上只在「成功压缩」时清,跨代残留;同时把「ref 全部 unknown」一律记成模型失败,未区分「是 bili 自己 rebase 弄死的旧 ref」。
  3. 影响范围与严重程度: 仅「宿主原生压缩 + rebase」路径触发(plugin native 模式,如 dsh/codex/omp 的 /compact);命中后本轮压缩完全放弃。属体验级死锁,非数据丢失——特定条件下有问题。
  4. 怎么修复的: ① 在 rebase 唯一咽喉点 resetSessionCompression 里删掉两个会计键(它们描述的 ref 空间已不存在);② rebase 后 30 分钟宽限期内,stale-ref 失败判为代理自身所致、不推进模型断路器,返回空串让恢复提示簇(rebaseNote + currentRefsSnapshot + acp_status 指引)保持可见,直到一次成功清空全部。
  5. 是否有回归问题: 逐项审过既有行为——非 stale 原因(parse/covered/content-changed)在宽限期内照常计数;无 rebase / 宽限过期仍按 3 次熔断;无 pending boundary 不做任何清理;freshCause 提前求值对非豁免路径纯函数无副作用;跳过写 streak 不影响 acp_status(其 lastCause 只在 armed 分支使用,纯 stale-ref 宽限内不会 armed)。高危模式过一遍:无语义漂移、无 fail-fast 变吞错、阈值/时序/输出格式均未变(COMPRESS_LOOP_THRESHOLD=3 / DECAY=10min 原样保留,只新增独立的 30min 宽限常量)。
  6. 是否破坏缓存: 不涉及——改动仅在失败回执文案与元数据会计,不动 KV/prefix 缓存、重试游标、去重键。
  7. 是否改了设计方向: 不涉及架构转向;只是在既有断路器机制上加一条「代理自因」归因旁路 + rebase 时清会计,边界与数据流不变。
  8. 是否引入了新的配置: 无新 env/config/CLI —— REBASE_STALE_GRACE_MS(30min)为硬编码常量,与既有 COMPRESS_LOOP_* 同风格,符合配置面纪律。

判定:可合。 根因修复、测试有牙、diff 干净、无 kernel 触碰、CI 绿。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷

Reviewed GitHub PR #5985 → verdict: APPROVE.

End-to-end review, independently re-derived from the diff (not copied from issue #5984): read the full diff (src/session.ts, src/stream.ts, new test file), traced both fixes against their real code paths, checked test teeth, the regression surface, house conventions, and CI.

  • Fix A — resetSessionCompression (src/session.ts:1731) now clears both compress-failure accounting keys (compressFailStreak dsh内部问题 出现这个错误后,重启dsh可以发消息 但陷入无限压缩失败 #2146, compressFailKeys 出现持续压缩失败,无法自动恢复 #847). Its ONLY src caller is reconcileNativeCompactionBoundary (session.ts:1808), gated on pendingRebase === true and reached only from the prepare/rebase paths → fires only on a genuine rebase, never an unrelated reset. Confirmed these are the only two such fields (completeness).
  • Fix B — noteCompressLoopFailure (stream.ts:332) exempts a stale-ref failure inside a 30-min post-rebase grace: returns "" without advancing the model breaker. Verified cause reachability (stream.ts:441 returns "stale-ref — …" for the exact kernel text), nativeCompactionAt has a single writer so the grace can't false-trigger, and returning "" is precisely what keeps the recovery cluster (rebaseNote + currentRefsSnapshot) visible instead of the armed "do not poll acp_status" paragraph (stream.ts:1522-1524). Skipping the streak write loses nothing — acp_status's lastCause only matters when armed, which pure stale-ref-during-grace never reaches.
  • Tests (tests/issue5984-rebase-breaker.test.ts, 6 cases): real functions exercised, positive+negative per gate, assertions have teeth (each fails if its mechanism regresses); not tautological.
  • Conventions/hygiene: no kernel/·pi-subagents/ touch (so no authz gate); REBASE_STALE_GRACE_MS=30min hardcoded like the existing COMPRESS_LOOP_* (no new config knob); tight diff (+180/−15, every line on-purpose, no lockfile churn); behavior drift disclosed old→new in the PR body.
  • CI head 436d391: 15 success / 15 skipped / 0 failed — green.

Verdict posted as a formal review comment on the PR — GitHub blocks self-approval of one's own PR (422 on the APPROVE event), so the identical APPROVE verdict went out as a COMMENT review: #5985 (review)

No small findings to fix on the spot; no 🔶 需要决策 items.

结构化八问(中文,供人工复核)

  1. 是什么问题: rebase 后压缩失败计数没清零;模型沿用旧 ref 必然连续三次熔断,而熔断回执又把唯一的 acp_status 恢复指引抹掉,本轮压缩彻底放弃(死锁)。
  2. 什么原因: rebase 重启了 ref 空间,但两个失败会计字段历史上只在「成功压缩」时清(跨代残留);同时把「ref 全部 unknown」一律记成模型失败,没区分这是 bili 自己 rebase 弄死的旧 ref。
  3. 影响范围与严重程度: 仅「宿主原生压缩 + rebase」路径(plugin native 模式)触发;命中后本轮压缩完全放弃——体验级死锁,非数据丢失,特定条件下有问题。
  4. 怎么修复的: ① 在 rebase 唯一咽喉点 resetSessionCompression 删掉两个会计键(其描述的 ref 空间已不存在);② rebase 后 30 分钟宽限内 stale-ref 失败判为代理自身所致、不推进断路器、返回空串让恢复提示簇保持可见直到一次成功清空。
  5. 是否有回归问题: 无。非 stale 原因(parse/covered/content-changed)在宽限内照常计数;无 rebase / 宽限过期仍按 3 次熔断;freshCause 提前求值对非豁免路径纯函数无副作用;跳过写 streak 不影响 acp_status;阈值(3)/时序(10min decay)/输出格式均未变。
  6. 是否破坏缓存: 不涉及——改动仅在失败回执文案与元数据会计,不动 KV/prefix 缓存、重试游标、去重键。
  7. 是否改了设计方向: 不涉及架构转向;只在既有断路器机制上加一条「代理自因」归因旁路 + rebase 时清会计,边界与数据流不变。
  8. 是否引入了新的配置: 无新 env/config/CLI —— REBASE_STALE_GRACE_MS(30min) 为硬编码常量,与既有 COMPRESS_LOOP_* 同风格,符合配置面纪律。

判定:可合。 根因修复、测试有牙、diff 干净、无 kernel 触碰、CI 绿。

⚠️ 关于「在协调 issue 报一行」:提供的材料里定位不到具体的协调 issue(open issues 按标题/正文检索均无 review-coordination 追踪帖)。为避免发错线程我没有猜测投递;若指定该协调 issue 的编号,我立即补上一行结论。

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

Projects

None yet

1 participant