Skip to content

compress 端点落在被 orphan-hiding 隐藏的失败 compress 调用上时整条区间被拒为 cannot be anchored(应吸附到相邻可见消息) #396

Closed

Description

@qiangu2020

现象

compress 区间的端点如果落在一个被 orphan-hiding 隐藏的失败 compress 调用上,整条区间会被拒为 cannot be anchored,即使区间里其余内容都可见、合法、超过最小体量。这个端点并没有被任何块消费,错误文本却说 "likely consumed by an existing block" / "message content changed",会误导模型。

环境

  • billion-context-pi 0.1.77(npm 包,未改动),宿主 Prime Agent 0.9.6(PI_ACP_FORK_HOST=1),模型 gpt-6-astra
  • 相关代码在 acp-kernel master 77b651a 上与 0.1.77 打包版一致:src/hide-consumed.ts KEEP_LAST_ORPHANED = 2;src/boundaries.ts resolveAnchorIndex 的 consumed 分支

复现(headless,两个回合)

回合 1:一次成功的 compress(建 b1),之后 4 次失败的 compress(前 3 次是 Total compressible content too small (… min 5000),第 4 次被 [ACP] PAUSED — 3 compress attempts already failed this turn 挡住)。留下 4 个无块 compress 调用 m00011 / m00013 / m00015 / m00017 及其结果。hideConsumedCompressCalls 只保留最近 2 个,m00011、m00013 被移出可见视图。

回合 2(新的 user 消息):compress m00011..m00028(区间内可见内容 > 5000 字符)→

Requested range(s) cannot be anchored (e.g. m00011..m00028) — the refs exist in this session's ref map, but the messages they point to are no longer in the visible context and no active block covers them: the message content changed (or the message was filtered out of the view) and now carries a new ref, leaving your old refs dangling. [diagnostics: session highest ref=m00028, unknown ranges in request=0/1, session history=1 compression(s), 1 block(s)] Run acp_status, then call the compress tool again using only the refs it reports.

同一回合 compress m00003..m00008 正常建出 b2(34.1K → 16.7K),说明问题只在端点。

机制

  1. m00011 在 messageRefs.byRef 里存在 → 不是 unknown。
  2. 它指向的消息被 hide-consumed 的 orphan 窗口藏掉,不在 indexByMessageId 里。
  3. 没有 active block 覆盖它 → activeOwnerAnchor 返回 null → 抛 BoundaryNotFoundError("consumed", …)。

被藏掉的只是一个无块、没有内容价值的失败 compress 调用,却让整条区间失效。

模型会用到这种 ref,是因为它在同一回合里亲眼见过这些调用(都是它自己刚发出的);orphan 窗口往后滑,调用就从视图消失了,但模型记住的 ref 在 byRef 里仍然合法。我们之前在 0.1.69 上做离线复现时也见过:acp_status 刚报告的可压区间,同一回合内因为窗口滑动变得无法锚定。

影响

单次看代价不大:白费一次 compress,报错引导模型跑 acp_status 后能恢复。但是:

建议(任选其一)

  1. resolveAnchorIndex:端点的 raw id 属于被 hide-consumed 隐藏的 orphan compress call/result 时,start 吸附到其后第一条可见消息,end 吸附到其前最后一条可见消息,返回 snapped 提示而不是抛错(和现有 "anchored to the active block covering it instead" 同一种处理)。
  2. hide-consumed 保留 refs 仍然可见的 orphan 调用,窗口只裁剪 refs 已失效的。
  3. 至少让 consumed 分支区分"被 orphan-hiding 隐藏"和"被块消费",给出准确原因。

相关:#220、#307。bcp 侧相关的日志误报:ranxianglei/billion-context-pi#532

Activity

  1. ranxianglei commented on Sep 25, 2026

    @ranxianglei
    Owner

    继续

  2. ranxianglei commented on Sep 25, 2026

    @ranxianglei
    Owner

    继续

  3. ranxianglei commented on Sep 25, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 进程此前因长时间无输出被强制重启了一次,现已恢复并继续。

    进展:已定位根因——src/boundaries.ts 的 resolveAnchorIndex 中,当端点 ref 存在于 byRef、但对应消息被 orphan-hiding 移出可见视图、且没有任何 block 覆盖它时,会落入 consumed 分支抛出误导性的 "likely consumed by an existing block"。计划采用 issue 建议的方案 1:此类端点吸附到相邻可见消息(start→其后第一条、end→其前最后一条)并返回 snapped 提示;无法吸附时回退为准确报错。正在补复现测试 + 实现,完成后回复结论与 PR 链接。

  4. ranxianglei commented on Sep 25, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 已修复,PR: #397 #397 (CI 运行中)

    审核结论(先审后改)

    • 复现/查证:确认问题属实。端点 ref 在 messageRefs.byRef 中存在、但消息被 hideConsumedCompressCalls 的 orphan 窗口(KEEP_LAST_ORPHANED=2)从可见列表移除后不在 indexByMessageId,又无 active block 覆盖 → resolveAnchorIndex 抛 BoundaryNotFoundError("consumed"),整条区间被拒;报错文案「likely consumed by an existing block」把原因归错了。
    • 层次判断:同一段代码同时服务两种必须相反处理的场景——
    • 方案:采用你标题里的方案 (1)(吸附),但加了必要前提——只有当端点 ref ∈ 本次隐藏路径记录的 hiddenOrphanRefs 时才吸附,否则维持原报错。start 向前吸附到下一个可见消息、end 向后吸附到上一个可见消息并返回 snapped 提示;若该方向无相邻可见消息,则给出准确报错。

    行为变更(按规范显式披露 旧→新)

    场景 旧 新
    端点落在被隐藏的孤儿调用上 整条区间拒为 cannot be anchored(原因误标) 端点吸附到相邻可见消息,区间继续 + snapped 警告
    孤儿端点该方向无邻居 cannot be anchored … consumed cannot be anchored … hidden orphan … no adjacent visible message … run acp_status(原因准确)
    #387 漂移/悬挂 ref 清晰 dangling 报错 不变

    需人工合并:本改动新增一个可选 state 字段 CompressionState.hiddenOrphanRefs?(旧持久化 state 无此字段 = 视为空,无需迁移),属 §7.3 状态结构变更,故不自动合并。请 owner 自行合并:#397

    验证:新增 tests/orphan-endpoint-snap.test.ts(6 例全过,含 #387 守卫 + 端到端 applyCompression);全量 1047 pass / 0 fail;typecheck、build 均绿。无 wire 格式变更、无新增依赖、不改 pipeline 节点顺序。

    一句话:修复了 compress 端点落在被隐藏的失败 compress 调用上时整条区间被误拒的问题(吸附到相邻可见消息,#387 语义保持不变),已提 PR #397,因涉及新增可选 state 字段需你手动合并。

  5. ranxianglei commented on Sep 25, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 补充:PR #397 的 CI 已全部通过(test / pr-validation / build-artifact 均 success),与本地 typecheck+test(1047/0)+build 一致,可放心合并:#397

  6. ranxianglei commented on Sep 25, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 先同步现状:实现侧已无待办。PR #397 当前状态 —— open、非 draft、mergeable=true、mergeable_state=clean(无冲突)、CI 四项全绿(test×2 / pr-validation / build-artifact)、无未处理的 review 或行内评论。修复本身已完成并交付。

    剩下唯一的一步是人工合并。按系统规则 Agent 不能合并任何 PR,需 owner 自行操作:#397 (页面点 Merge,或走 API)。我无法代合。

    如果你说的「继续」是指别的方向,请明确一下,我马上接着做,例如:

    告诉我具体要哪一项,我立即继续。

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions