Skip to content

[PR] feat: add compress.preserveRecentTurns and protectUserMessages (#4593) - #4620

Open
ranxianglei wants to merge 21 commits into
masterfrom
2026-10-25_turn-retention-user-protection
Open

ranxianglei wants to merge 21 commits into
masterfrom
2026-10-25_turn-retention-user-protection

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

kernel-change: #4593 requests two protection mechanisms the host side cannot express: (1) per-turn retention is POSITIONAL — the window slides forward with every new user message, so it cannot ride permanent BLOCKED-ref identity decisions (aged-out messages would stay blocked forever, or force per-turn BLOCKED→numeric migration = prefix-cache churn); it belongs in the kernel's per-turn-recomputed soft zone; (2) user-message hard exclusion must ride the shared isMessageProtected predicate so every consumer (ref assignment, unit projection, report, absorb/ccr guards) stays in sync automatically.

Closes #4592

What

Two opt-in keys under compress, both off by default:

  • preserveRecentTurns?: number — the last N turns (turn = user message → next user message) join the soft-protected zone alongside preserveRecentMessages/Tokens/latest-user pin. Strict window: starts AT a user-message boundary, never mid-turn. Consecutive user messages count as ONE boundary; summary carriers are not boundaries.
  • protectUserMessages?: boolean — every user text message hard-excluded (BLOCKED refs, never advertised as compressible), same semantics as protectedTools. Host-injected runtime-context user messages are covered too (deliberate conservative default: over-protection costs ratio, under-protection loses instructions).

Submitted-range behavior (per the author's in-thread refinement — filter, don't reject):

Config surface

  • New: compress.preserveRecentTurns (number, default off/0), compress.protectUserMessages (boolean, default off/unset)
  • Why the existing surface cannot express them: preserveRecentMessages/Tokens are count/token proxies that slice MID-TURN (the exact gap the issue documents: DSH turns span 40+ messages); protectedTools matches tool paths only, never plain user text
  • Override semantics: per-field global → provider → model cascade, identical to sibling keys (NOT injectTool-style base-only); an explicit off at any tier wins (?? merge)
  • Compat: both optional; unset = byte-identical behavior to before (defaultConfig untouched → golden wire-contract/kernel.json unchanged)
  • Docs: CONFIGURATION.md en+zh updated (table rows + deterministic behavior spec: reject / filter+receipt / priority order)

Behavior decisions (flagged per owner policy)

  1. Preflight overflow relaxation (preflight fail-fast × soft-protection livelock: over-window payload with nothing foldable outside the protected zone 502s forever #330) zeroes preserveRecentMessages/Tokens but deliberately does NOT touch preserveRecentTurns: folding user instructions under overflow defeats the feature, so an unresolvable overflow fails loudly instead of silently dropping instructions. protectUserMessages is hard and was never relaxed.
  2. Tool descriptions unchanged: the compress tool prompt is golden-pinned (defaultPrompts) and sits in the cache-stable request prefix; the new semantics are carried by receipt warnings + acp_status ⚠ flags instead of editing load-bearing prompt text.
  3. Strict turn window: starts at a user boundary rather than the issue's literal formula, which would have over-protected the non-user tail of one extra turn.

Tests

查重: 不重复(open+closed issues/PRs searched, EN+CN keywords, no match)

Kernel version: acp-kernel 0.0.163 → 0.0.164 (branch rebased onto master, where acp-kernel is at 0.0.163; single bump for this change set, CI-enforced)

@ranxianglei ranxianglei changed the title feat: add compress.preserveRecentTurns and protectUserMessages (#4593) [PR] feat: add compress.preserveRecentTurns and protectUserMessages (#4593) Oct 24, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

查重: 不重复。 独立检索 open+closed issues/PRs(preserveRecentTurns / protectUserMessages / turn retention / user message protection / 「按轮保留」多组关键词):唯一相关条目是功能请求本身(GitHub #4592 / ework #4593)与本 PR,无其他实现尝试或同机制在途工作。

标签: scope/kernel, dsh(主改动面在 kernel 保护层;DSH 是驱动场景,机制本身通用)。功能类 PR 不打 bug、不评缺陷严重度。

说明:这是本 daemon 另一会话(ework #4593 工作区)完成的实现 PR,正文无 ework-agent-pr 标记,按规程做独立全量 review(不复读 issue 侧结论)。

先报一个已确认的硬伤:PR 正文写 Closes #4593——GitHub 上 #4593 是「zcode 风控问题」,与本 PR 无关(功能请求在 GitHub 上是 #4592,#4593 是 ework 侧编号)。按现状合并会误关那个无关的 zcode issue。我会在 review 中顺手把 PR 描述里的引用改对(agent 自产文本,非用户输入),随后给出完整八问结论。

review 进行中:正在拉分支核对代码、跑定向测试、查 CI。

@ranxianglei
ranxianglei force-pushed the 2026-10-25_turn-retention-user-protection branch from d791f53 to 22f6e21 Compare October 24, 2026 21:29
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-25_turn-retention-user-protection (6fe4a86)

Latest build — install this exact version

npm install -g [email protected]

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
6fe4a86 [email protected] build
967512a [email protected] build
e9544c1 [email protected] build
ffe1895 [email protected] build
e08e9fa [email protected] build
fa2fc54 [email protected] build
9df2264 [email protected] build
e204c60 [email protected] build
4003fca [email protected] build
22f6e21 [email protected] build

Download artifact

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

Install instructions are refreshed on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

冲突已解决。 PR #4620 分支落后 master 约 497 个提交,rebase 到当前 master(146b34f2)后冲突清零,已 force-push(lease 锁定原 tip d791f53)。GitHub 现显示 mergeable=True、无文本冲突(mergeable_state=blocked 是等人工 review,非冲突)。

结构化八问

  1. 是什么问题:不是代码缺陷——PR 分支切自旧 master,master 持续前进后两分支在同一区域分叉,产生文本冲突(dirty),需要 rebase 对齐当前 master。

  2. 什么原因导致的:master 自 PR 切出以来 kernel 版本从 0.0.151 走到 0.0.163(其间 12 次 bump),并改动了本 PR 也触碰的 protected.ts / unit-projection.ts / config.ts / preflight.ts;合并时同区域两侧都有改动 → 文本冲突。

  3. 影响范围与严重程度:仅影响本 PR 能否合入,无用户侧影响(两个新键默认关)。严重度低,纯维护性 rebase。

  4. 怎么修复的:把 PR 的 2 个提交 rebase 到当前 master,按「意图并集」解 4 处冲突,未丢任何一侧逻辑:

  5. 是否有回归问题:rebase 本身未引入回归——本地定向验证全绿:typecheck 干净、build 成功、136 条定向测试通过(新 zcode risk control issue | zcode风控问题 #4593 套件 + message-protection / protect-recent / protected-content / protected-latest / protected-paths / protected-virtual-paths + unit-projection 一致性 [Bug] recommend/apply 对同一区间的 turn-integrity 判定永久不一致:acp_status 反复推荐的区间被 apply 侧整段拒绝(0.1.196,Range would split N turn(s) at the protected-zone boundary) #3236 + recent-pair-integrity [Bug] neverPreserveRecentTools splits tool-call/result pairs at protected boundary, causing upstream 400 invalid_request_error #2886 + host compress-settings 级联)、verif 子语言守卫通过;每处冲突都是意图并集。全量裁决以推送头部的远程 CI 为准。

  6. 是否破坏缓存:否。两键默认关(defaultConfig 未动、golden wire-contract/kernel.json 不变),未设置时逐字节等同旧行为;rebase 未触碰任何缓存相关逻辑。

  7. 是否改了设计方向:否。纯 rebase,完整保留 PR 原有设计(opt-in compress 键挂在共享 isMessageProtected 谓词 + 每轮软保护区),无架构转向。kernel 部分仍按 Kernel Boundary 走人工 review。

  8. 是否引入了新的配置:是(PR 自身内容,现已干净落在 master 上)——compress.preserveRecentTurns(number,默认 off/0)与 compress.protectUserMessages(boolean,默认 off/unset),均可选,未设置 = 行为不变。

判定:冲突清零、分支已 rebase 到当前 master 并 force-push,本地定向验证绿;待 CI 全量 + 人工 review(kernel 变更保持人工把关)。

ci-check added 2 commits October 25, 2026 06:01
kernel-change: per-turn retention window + hard protection for user
messages requested in #4593 — the host side cannot express either:
turn boundaries are positional (slide per user message, incompatible
with permanent BLOCKED-ref identity decisions) and user-message
hard exclusion needs to ride the shared isMessageProtected predicate
so every consumer (refs, projection, report, absorb/ccr guards)
stays in sync automatically.

- turn-retention.ts: computeTurnRetention — visible user-message
  boundaries (consecutive users = one, summary carriers excluded),
  strict window starting AT the (N+1)-th-from-last boundary
- recommend.ts: Rule 4 unions the retention suffix into the soft
  zone (partial overlap = existing #3953 carve + warning, full
  containment = zone fatal)
- protected.ts: protectUserMessages hard-excludes user text
  messages (BLOCKED refs); compress.ts gate extended so the
  predicate actually runs
- unit-projection.ts: warnings/fatal attribute causes (last-N-turns
  retention vs classic recent zone vs protectUserMessages)
- config.ts: validateConfig checks; types.ts optional fields
  (defaultConfig untouched -> golden wire-contract stays stable)
- version 0.0.151 -> 0.0.152
Config surface (owner-gated mapping, per-tier like siblings):
- compress.preserveRecentTurns?: number (0/unset = off): last N turns
  (turn = user message -> next user message) join the soft-protected
  zone; submitted ranges crossing the boundary are carved with an
  auditable warning, fully-contained ranges are rejected
- compress.protectUserMessages?: boolean (unset = false): every user
  text message hard-excluded (BLOCKED refs, never advertised), same
  semantics as protectedTools

- parseCompressSettings: finite >= 0 number (explicit 0 = off) and
  strict boolean validation; COMPRESS_SETTING_FIELDS updated
- mergeCompress/applyCompressSettings: per-field global -> provider
  -> model cascade with ?? (an explicit off at any tier wins)
- preflight overflow relaxation deliberately does NOT touch
  preserveRecentTurns: folding user instructions defeats the feature,
  so unresolvable overflow fails loudly instead
- CONFIGURATION.md en+zh: table rows + deterministic behavior spec
  (reject / filter+receipt / priority order)
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

查重:不重复 —— 本条为 CI 自动修复车道(attempt 1/2、2/2 合并交付),四条红已逐条分账并对照 #4599 总控核实,无新立项。

CI 四条红全部已在分支修复并推送,新 head e204c60d1(共 4 个独立标注 commit)。本地复验:config-surface-guard ✓、docs-sync(generate 后零漂移)✓、lock-sync(根 + kernel 两个 lockfile 幂等)✓、unused-exports(clean, 6 waived)✓。

修复分账

红 归属 修法
config-surface-guard 本 PR 两个新键只被手写进 CONFIGURATION 的生成区块,种子没登记 → website/config-reference/compress.yaml 补 cw.prtt / cw.pum 两条种子(EN+ZH desc/site 齐全)
docs-sync 本 PR 同根因:重新生成时手写行被删 → 补种子后跑 node tools/gen-config-docs.mjs generate 正规重生成四个文件(CONFIGURATION.md / .zh-CN.md、website/main.js、website/docs/index.html)
lock-sync 本 PR kernel 版本 bump 提交(0.0.163→0.0.164)漏同步 lockfile → 用 CI 同款命令 npm install --package-lock-only 补齐两个 npm 根:package-lock.json(1 行)+ kernel/package-lock.json(2 行,attempt 2 发现)
unused-exports 继承 master 红 ClientBuildCheck INTERNAL_ONLY,与 master head 146b34f27 逐字节同一报错(#4599 盘点第 1 条,#4545 train 去导出清扫遗漏)。按几行级小修纪律在分支内独立 commit 去掉前导 export(与 #4606 提交 1 / #4603 同法);全仓 grep 零外部引用。#4606 合入后 rebase 时直接丢弃此 commit

八问

  1. 是什么问题:PR 检查矩阵四条门禁红——两条是「新增配置键没走种子生成流程」,一条是「版本 bump 没同步 lockfile」,一条是继承 master 既有的 unused-exports 红。
  2. 什么原因导致的:CONFIGURATION 表格是带「do not hand-edit」标记的生成块,作者直接手写了 2 行进生成区而未在 website/config-reference/*.yaml 登记种子(config-surface-guard 与 docs-sync 各自从两个方向抓住它);kernel bump 提交漏跑两个 npm 根的 lockfile 同步;unused-exports 根因在 master 侧(见上表)。
  3. 影响范围与严重程度:仅本 PR 的检查信号,用户侧零功能影响(两个键默认 off,功能行为未动)。
  4. 怎么修复的:原则是「补登记 + 官方工具链重生成」,不手改生成文件;lockfile 用 CI 同款命令再生成;继承红按舰队先例一词修复并标注 rebase 时丢弃。
  5. 是否有回归问题:逐项审过——文档重生成 diff 仅含这两个键的行(其余 303 条种子输出不变);lockfile 合计 3 行纯版本号变化;去 export 无任何外部引用且类型编译期擦除、无运行时影响。文档措辞披露(旧→新):① 默认列 off → off (unset)(对齐仓库既有惯例,如 nudgeModelDecided);② kernel 版本下限从 Env 列移入描述文本——Env 列由种子的 env 字段生成,本来就无法表达版本下限,作者原写法放错了列;版本号同步修正为 rebase 后的 acp-kernel ≥ 0.0.164(原手写值 0.0.152 是旧基线下的,已失效)。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:没有。
  8. 是否引入新的配置:没有新增——这两个键本身就是本 PR 的功能(zcode risk control issue | zcode风控问题 #4593 线已批),本轮只是把它们的文档登记补齐。

预期残留红:重触发后 11 个 test 分片仍会命中继承的 LIVE_FILES tripwire(#4599 盘点第 2 条:tests/issue3890-parent-gone-confirm-drain.test.ts 未登记,分片跑测试前即退出)——该修复集中在 #4606,按舰队先例本分支不夹带重复小修;#4606 合入后本分支 rebase 即全绿(届时一并丢弃上面那个去 export 的重复 commit)。

结论:点名的四条门禁本地验证全绿、已推送,等 CI 重触发;剩余红均属 #4606 工作流,非本 PR 代码问题。本车道收工。

ci-check added 2 commits October 25, 2026 06:28
…ior; floor fractional preserveRecentTurns

Review fixes for the turn-retention feature (review of this PR):

- types.ts / turn-retention.ts / recommend.ts: three comments still
  described the abandoned design (ANY overlap rejected). The implemented
  behavior is two-tier: partial overlap carves at the boundary with an
  auditable receipt, full containment rejects. Also corrected the
  window-start wording in types.ts (the boundary itself is included).
- turn-retention.ts: floor fractional N. The host floors at parse time,
  but acp-kernel ships standalone — a direct-API fractional value would
  index boundaries[] fractionally and silently degrade to off.
- unit-projection.ts: zone error wording uses the effective (floored) N.
- tests: fractional-N case (1.9 -> window of 1 turn).
…carrier-exclusion wording and kernel version refs

Review fixes for the turn-retention feature (review of this PR):

- The two new compress keys were added to COMPRESS_SETTING_FIELDS and to
  the generated index tables by hand, but their seeds were missing from
  website/config-reference/*.yaml — both the config-surface-guard and the
  docs-sync CI jobs fail on that. Add the seeds (cw.prturns / cw.pum) and
  regenerate all derived artifacts through tools/gen-config-docs.mjs.
  Regeneration also corrects the hand-edited table rows: the Env column
  is for BILI_* env vars (these keys have none), so it renders '—'.
- Detail sections claimed summary carriers are role system; the actual
  exclusion is by SUMMARY_HEADER text prefix on user-role messages
  (tool results never match on role). Fix en+zh wording to match the
  code (kernel/src/protected.ts isUserTextMessage).
- Kernel version refs 0.0.152 -> 0.0.164: the branch was rebased onto
  master, where acp-kernel is at 0.0.163, so this change ships as
  0.0.164 (CI-enforced version discipline).
@ranxianglei
ranxianglei force-pushed the 2026-10-25_turn-retention-user-protection branch from e204c60 to 9df2264 Compare October 24, 2026 22:36
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

Review 结论:修复 + rebase 后可合并(等新 head 9df226499 的远程 CI 转绿;合并由 owner 执行)。

先说我在 PR 分支上直接做的四类事(均已 push,独立标注 commit):

  1. Rebase 到最新 master。分支基于 fe5ba59,master 已前进约 30 个提交(Failed compression invocations are never folded back for reclamation, and the context keeps ballooning under the weight | 失败的压缩调用永远不会被折叠回收,上下文被压缩残渣越撑越大 #4289/Accident re-anchor debris is unrecoverable: the overlay island lands mid-turn, and the turn-split guard means the orphan | 事故重锚碎屑无法回收:覆盖岛落在 turn 中段,turn-split 守卫让孤另一半永远折不了 #4348 failed/aged-compress 豁免、After model switch / client-side history rewrite, all message identities (content hashes) are replaced: ACP numbers re-m | 切模型/客户端重写历史后,消息身份(内容哈希)全部更换:acp 编号重铸、折叠覆盖大规模重挂、死 ref、churn 区临时膨胀重折 #4316、modelContextLimit / outputHeadroomMaxPct on the provider route root are silently ineffective (inert keys, zero warnings) | provider 路由根上的 modelContextLimit / outputHeadroomMaxPct 静默无效(惰性键、零告警) #3675 config-surface guard 等),4 个文件冲突(kernel/package.json、kernel/src/protected.ts、kernel/src/unit-projection.ts、src/config.ts)按「意图并集」解决;kernel 版本号随 master 现状从 PR 原来的 0.0.151→0.0.152 改为 0.0.163→0.0.164(CI 强制的版本纪律)。
  2. 修真缺陷 ×2(commit 2244abeba):
    • 三处注释仍描述已废弃的设计(「任何重叠 → 拒绝」),与实现的两级行为不符(部分重叠 → 边界裁出 + 可审计回执;完全包含 → 拒绝)——types.ts / turn-retention.ts / recommend.ts 全部改写为两级语义,顺带修正 types.ts 窗口起点 off-by-one 表述(边界消息本身在保护区内);
    • 分数 preserveRecentTurns(如 1.5):宿主侧 parse 时 floor 了,但 acp-kernel 是独立发布的包——直接 API 调用传分数值会 fractionally index boundaries[],静默退化成 off。kernel 侧现在也 Math.floor,补回归测试(1.9 → 1 轮窗口)。
  3. 修必然 CI 红 ×2(commit 9df226499):
    • 两个新 key 进了 COMPRESS_SETTING_FIELDS 和手写的生成表,但 website/config-reference/compress.yaml 没有种子——config-surface-guard 和 docs-sync 两道 CI 门禁必红。已补种子(cw.prturns / cw.pum)并用 tools/gen-config-docs.mjs 重新生成全部派生产物(两版 MD 索引表、website/main.js、docs/index.html);再生成同时纠正了手写行的 Env 列(该列只放 BILI_* env var,这两个 key 没有 → 「—」);
    • 文档与代码事实不符:protectUserMessages 对摘要载体的排除机制实际是「文本以 SUMMARY_HEADER 开头的 user-role 消息」(工具结果按 role 不匹配),原文写成 role system——en+zh 已改准;kernel 版本引用 0.0.152→0.0.164(en+zh+代码注释共 6 处)。
  4. 修 PR body:Closes #4593 → Closes #4592(GitHub zcode risk control issue | zcode风控问题 #4593 是不相关的 zcode 风控 issue,功能请求是 [feature] compress: Add preserveRecentTurns (per-turn retention) and protectUserMessages (hard protection for user messa | [feature] compress: 增加 preserveRecentTurns(按轮保留)与 protectUserMessages(user 消息硬保护) #4592,原样合入会误关错单);同步 kernel 版本号与测试数(12→13)。正文其余内容保留未动。

结构化八问

  1. 是什么问题:功能请求(mzbgf,GitHub [feature] compress: Add preserveRecentTurns (per-turn retention) and protectUserMessages (hard protection for user messa | [feature] compress: 增加 preserveRecentTurns(按轮保留)与 protectUserMessages(user 消息硬保护) #4592 / ework zcode risk control issue | zcode风控问题 #4593)——DSH 式长轮次(一轮横跨 40+ 条工具消息)用条数型保留(preserveRecentMessages)要么截在轮中间要么过度保留,且用户指令被折进模型自写摘要后无法再逐字核对。新增 compress 下两个 opt-in 键:preserveRecentTurns(最近 N 轮软保护)、protectUserMessages(user 文本硬保护)。
  2. 什么原因导致的:非缺陷修复,是能力缺口——既有保留机制全是条数/token 代理,缺「轮」这个单位;硬排除谓词只认 tool path,不认纯 user 文本。方案方向正确且必要:轮窗口逐轮滑动,必须每轮重算,不能进永久 BLOCKED-ref 身份决策(否则老消息永久钉死或触发 prefix-cache churn)。
  3. 影响范围与严重程度:纯增量功能,两键默认关;unset = 行为字节级不变(defaultConfig 未动 → golden wire-contract/kernel.json 不变)。仅显式开启的用户受影响。对存量用户零影响。
  4. 怎么修复的:实现本身遵循 issue 线程拍板(filter-don't-reject 两级、overflow 放松刻意不清此键、tool 描述不动以保缓存稳定前缀、最深层 cascade);我修的是:注释/代码脱节 ×3、分数 N 静默失效、文档种子缺失(CI 必红)、载体排除措辞失实、issue 编号指错。
  5. 是否有回归问题:触碰路径逐项审过——flag off 时 fold 行为、ref 分配、recommend、zone fatal 报错文本均与 legacy 一致(kernel 测试钉住 legacy fold + 零警告;fatal 文本 off 时逐字相同,已对照 master 源码验证)。assignRefsNode 门扩展为纯增量;COMPRESS_SETTING_FIELDS 并集保住 master 侧 COMPRESS_SETTING_FIELDS is missing externalSummary — this field, when placed at the route root, is silently ignored with | COMPRESS_SETTING_FIELDS 漏了 externalSummary — 该字段写在路由根仍静默无效且无告警 #3876 externalSummary 等新增字段;与 master 侧 Failed compression invocations are never folded back for reclamation, and the context keeps ballooning under the weight | 失败的压缩调用永远不会被折叠回收,上下文被压缩残渣越撑越大 #4289/Accident re-anchor debris is unrecoverable: the overlay island lands mid-turn, and the turn-split guard means the orphan | 事故重锚碎屑无法回收:覆盖岛落在 turn 中段,turn-split 守卫让孤另一半永远折不了 #4348 的 failed/aged-compress 豁免共存安全(域不相交,合并后 isMessageProtected 顺序验证过)。一处有意的文字漂移必须披露:功能 OFF 时,carve-out 回执警告里的括号说明从 (recent/last-user zone) 变为 (the last N messages and/or the most recent user message)(点名实际生效的 regime,多 regime 叠加时才可审计)。旧串无任何测试断言(grep 确认仅注释提及);警告是每次调用的回执文本,不是 wire-stable 字节,无缓存影响。
  6. 是否破坏缓存:否。tool 描述/prompt 未动(golden-pinned defaultPrompts);摘要载体豁免保住 tier distillation;positional 窗口每轮重算正是为避免 BLOCKED 迁移 churn。
  7. 是否改了设计方向:否。软区(computeProtectedRefs 并集)+ 硬谓词(isMessageProtected 共享路径)贴合 [Bug] recommend/apply 对同一区间的 turn-integrity 判定永久不一致:acp_status 反复推荐的区间被 apply 侧整段拒绝(0.1.196,Range would split N turn(s) at the protected-zone boundary) #3236 单一投影纪律与 [Bug] compress range straddling the protected latest user message: summary of the reply is anchored BEFORE that user message (causal order inversion) #3953 裁切机制,无架构转向。
  8. 是否引入新配置:是——compress.preserveRecentTurns(number,默认 off/0)与 compress.protectUserMessages(boolean,默认 off/unset);global→provider→model 逐字段最深层生效,显式 off 在任一层即胜出(?? 合并,与兄弟键一致);无 env var;CONFIGURATION.md en+zh + website 种子已同步。

测试有效性(④):kernel 13 个测试有牙(精确块构成 deepEqual、精确 ref 值如 BLOCKED/m00001..m00005、warning/error 正则、defaults-off 负守护),能抓住 filter↔reject 回归与审计归因丢失;host 侧 4 个钉住 cascade/显式 false 胜出/parse 边界(0=off、3.7→3 floor、strict boolean 拒 "yes"/1)。本地定向全绿:kernel 保护族 76 + recommend 族 41 + turn-retention 13、bili compress-settings 47、verif-subset-guard(compress.ts 在 Tier-A 守护清单内)2/2、config-surface-guard ✓、docs-sync 幂等 ✓、typecheck ✓、build ✓。全量套件按纪律交远程 CI——新 head 的 CI 正在跑,转绿后我会补一行确认。

判定:可合并(CI 绿后)。合并请 owner 执行:#4620

ci-check added 2 commits October 25, 2026 06:53
…ync gate)

The rebase bumped kernel/package.json to 0.0.164 but the kernel's own
lockfile (standalone acp-kernel identity, #2092) still recorded 0.0.163 —
the lock-sync CI job diffs the regenerated kernel/package-lock.json and
fails on that drift. (The original branch had the same latent drift from
its 0.0.151 -> 0.0.152 bump.)
….164 (lock-sync gate)

Follow-up to the kernel/package-lock.json sync: the root lockfile also
carries the file:-link's recorded version under packages."kernel", which
the rebase bump to 0.0.164 left at 0.0.163 — the lock-sync job's root
regen diffs exactly that line.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

CI 状态更新(新 head e08e9fafe):除一处继承自 master 的红之外全绿。

  1. lock-sync 红 = 我的 rebase 引入,已修(两个小 commit):kernel bump 到 0.0.164 时漏同步了两处锁文件版本记录——kernel/package-lock.json(standalone acp-kernel 身份自己的 lock,acp-kernel 并入billion-context并保持相对独立 #2092)和根 package-lock.json 里 file:-link 的 packages."kernel".version 行。原分支的 0.0.151→0.0.152 bump 同样带着这个潜在漂移(当时 CI 还 pending 没暴露)。已在 fa2fc5463 + e08e9fafe 修掉,本地按 CI 同款步骤复现验证过,现在该 lane 绿。
  2. unused-exports 红 = 继承性失败,不是本 PR 的问题:master head 146b34f27 上本地 worktree 复现同一报错行(INTERNAL_ONLY src/agent/client-build-note.ts: ClientBuildCheck)。CI Control Center: Centralized CI Failure Handling & Status Sync (Comment all CI issues here; do not open new issues) | CI 总控: CI 失败集中处理与状态同步(所有 CI 问题在此评论, 勿开新 issue) #4599 总控里已有同签名记录([PR] fix: stamp bili.log lines with the system local time | 日志时间改用系统本地时间 #4537/[PR] fix(overflow): recognize the DashScope input-length-range 400 so the probe path can arm #4263/[PR] fix: persist each committed preflight fold so a dead marathon leaves durable progress (#3978) #4046 都报过),修复在 [PR] fix(ci): drop the unused export of ClientBuildCheck #4603;我按协调纪律在 CI Control Center: Centralized CI Failure Handling & Status Sync (Comment all CI issues here; do not open new issues) | CI 总控: CI 失败集中处理与状态同步(所有 CI 问题在此评论, 勿开新 issue) #4599 补了一行本 PR 的记录,未开新 issue。[PR] fix(ci): drop the unused export of ClientBuildCheck #4603 合入后重触发即全绿。

当前判定不变:可合并——本 PR 自身所有 lane(含 kernel-guard / docs-sync / config-surface-guard / lock-sync / build)全绿,仅剩继承红等 master 侧 #4603。合并请 owner 执行:#4620

ci-check and others added 12 commits October 25, 2026 10:09
…ment

#4316 PR3/3 (restampRefsToLedger) re-homes citation numbers once on every
full-mode cold load; goldens pinning exact ref numbers are born-red. Re-pin
the 7 storage-lane tests (engine-proofs x6 + orphan-recovery x1) modulo that
renumbering — zero production code touched.

- golden-storage-drive.ts: per-turn citation-normalized digest (shaCiteNorm)
  and state digest modulo stripOneTimeAlignment (stateDigestAligned); the
  deep-sort helper is hoisted into golden-canonical.ts for sharing.
- corrupt-index-child.ts: new stripOneTimeAlignment normalizer — strips the
  refLedgerAligned stamp and re-homes refs onto canonical raw-id order so a
  clean full-mode read and the legacy fallback load compare equal.
- storage-engine-proofs.test.ts: wire legs assert shaCiteNorm equality vs
  the legacy restart leg and the committed goldens; state legs assert
  stateDigestAligned; rollback leg now spells BILI_STORAGE_UNIFIED=legacy
  explicitly (#3818 flip: absent resolves to full, deleting the env would
  vacate the legacy path).
- storage-orphan-recovery.test.ts: pins the content-addressable
  byRaw->byRef round-trip instead of a counter-era m00003 literal.
- golden/storage-render/*.json regenerated with shaCiteNorm/stateDigestAligned.

Converges the master-red storage-lane family (#4599 plan A, owner directive).
…dger parity masks

The #4316 one-time renumbering restamped messageRefs but left
state.tokenSnapshot keyed by the OLD refs, so post-restart bodies
carried stale per-message token counts (1.3K vs 1.4K) and the
full-mode-restart wire drifted off the legacy baseline (#4599).

persist.ts: two-pass remap (stage moves, delete old keys, then write
new keys) so entries whose new ref collides with another move's old
ref survive; fires only when superseded refs exist.

Aligned normalizer (corrupt-index-child.ts): the cacheLedger's
segment bookkeeping (be/bl/bs, unfinalized tail line), the derived
agg block, and per-line miss-attribution (prov/seam) are restart
experience, not content — no-restart and restart legs legitimately
differ there. Masked in the aligned view only; raw digests keep
full accounting. Goldens regenerated (stateDigest + aligned).

storage-engine-proofs 12/12, golden-storage-render 5/5 locally.
…persisted state (#4599)

The fork-survival test asserted immediately after the compress tool
response, but the fold lands in the live session state asynchronously
(#3573 replay semantics). Slow CI runners persisted the pre-fold state
('0 block(s) (compressions=0)' cold load) and the deepEqual diverged.
Bounded 5s wait on the in-memory fold; fast machines exit on the first
iteration. Product semantics unchanged.
The #4316 cold-load alignment reads the unified sidecar; its ingest of
just-flushed records completes asynchronously. Slow runners compared
the pre-ingest state and saw refLedgerAligned missing while the fold
itself had landed. Poll (bounded 5s) until the loaded state carries
the flag; fast machines exit on the first probe.
Git-for-Windows autocrlf checks the bundled .md posts out with CRLF;
the exact-match '---' fences then failed to parse and every post lost
its title/excerpt/date frontmatter (Windows CI: 'bundled meet-bili post
found' assertion). Normalize CRLF to LF inside parseFrontmatter when
the fence is CRLF-shaped; LF content is byte-identical as before.
Regression test with a CRLF fixture.
… storage mode (#4599)

The #4316 cold-load alignment sets refLedgerAligned only when the
unified store is available; config-clean machines (CI runners) run
legacy mode where it is an honest skip. The test asserted the flag
unconditionally, so every shard carrying this file was born-red on CI
while unified-config machines passed. Expectation now mirrors
store.replicasAvailable(); verified 49/49 in BOTH modes locally.
ranxianglei and others added 3 commits October 26, 2026 09:42
The ci-check lane's expectation change (c496cfb) exposed a real Windows
bug: stripInheritedProxy builds inlineEnv as a spread copy of process.env,
which keeps the original key casing (ComSpec) — Windows env vars are
case-insensitive but plain objects are not. planClientSpawn's exact
env.COMSPEC probe then missed it and silently degraded every wrapped spawn
to the bare-name 'cmd.exe' fallback (verified by repro on a real win32 box:
childEnv.COMSPEC=undefined while process.env.COMSPEC was set).

Fix: probe COMSPEC/ComSpec/comspec in planClientSpawn and planDshSpawn.
Verified on real Windows (Node 22): launcher-opencode-inline + fix-679 +
dsh-refresh 37/37; host tsc clean, 35 pass / 2 win32-skips.
…OMSPEC case-probe

c496cfb re-derived the win32 expectation from ambient process.env, which
still mismatches production: Node's process.env member access is
case-insensitive on Windows while the child env handed to the planner is a
plain object whose key keeps the OS casing (ComSpec), so the exact
env.COMSPEC probe fell through to the bare-name fallback. The assertion now
derives from the child's OWN captured env/options and probes
COMSPEC/ComSpec/comspec exactly like planClientSpawn does post-dfeea8a11 —
self-contained under any concurrent-test env churn in single-process CI
shards — and additionally pins windowsVerbatimArguments=true on the wrap.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

1 participant