Skip to content

refactor(#2607): remove compress.stripImages — default media folding replaces it - #2688

Merged
ranxianglei merged 6 commits into
masterfrom
2026-10-10_remove-strip-images
Oct 10, 2026
Merged

ranxianglei merged 6 commits into
masterfrom
2026-10-10_remove-strip-images

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Removes compress.stripImages / compress.stripImagesKeepRecent entirely. Default media folding (#2640) made the opt-in wire-side image strip redundant, and the strip itself was a turn-over-turn prompt-cache breaker on three of four wires: its sliding cutoff (len - keepRecent) moves the outgoing byte boundary every turn, so the cache forks at the most expensive content each round (only anthropic had the fold-anchored boundary). Media handling now has exactly one path: fold + archive + decompress({ imageRef }) recovery.

kernel-change: acp-kernel 0.0.113 → 0.0.114 — stripHistoricalImages (kernel/src/wire/strip-images.ts) was a public wire export that existed only for this removed host policy; no compression behavior changes.

Why now (evidence, not taste)

Changes

  • kernel: strip-images.ts deleted; wire barrel export removed; wire-google strip tests removed; version bump.
  • host: strip wiring + foldAnchoredCutoff + DEFAULT_STRIP_IMAGES_KEEP_RECENT removed (handle.ts, server.ts, compress-settings.ts). image-restore.ts keeps the always-on index/spill/decompress machinery — that is the default-fold recovery path.
  • config: fields dropped from type/whitelist/parser. Old configs are inert (keys ignored, no crash) and get a one-time [acp-config] … is INERT … was removed warning (warnInertStripImages, pattern of warnInertResignPassthrough).
  • docs: seeds + generated tables regenerated (231 i18n keys, coverage ok); EN/ZH prose sections replaced with removal notes; decompress tool texts no longer reference the flag.
  • tests: strip-images / strip-images-compact / strip-log-observability / strip-cutoff-anchor suites deleted; compress-settings cascade/parse cases removed; new strip-images-removal.test.ts pins the INERT notice (fires once, names the keys) and that clean configs stay silent.

Verification

  • kernel: 1264/1264
  • host: typecheck 0; fold-images-archive 3/3, compress-settings, image-restore, fix-781-summary-images, fix-488-multimodal 7/7, count-tokens, issue783-growth, e2e-plugin-grow-compress, strip-images-removal 2/2 — all green (bare env)
  • check:unused-exports clean; gen-config-docs check-coverage ok

Closes #2608

…replaces it

Default archivable-media folding (#2640) made the opt-in wire-side image
strip redundant, and the strip itself broke the prompt cache every turn on
three of four wires (sliding cutoff moves the byte boundary per turn; only
anthropic had the fold-anchored boundary). Media handling now has exactly
one path: fold + archive + decompress({ imageRef }) recovery.

- kernel: strip-images.ts (stripHistoricalImages) retired; wire barrel and
  wire-google tests updated; acp-kernel 0.0.113 -> 0.0.114
  (kernel-change: removing a public wire export that exists only for the
  removed host policy; no compression behavior changes)
- host: strip wiring, fold-anchored cutoff, and DEFAULT_STRIP_IMAGES_KEEP_RECENT
  removed from handle.ts/server.ts/compress-settings.ts; image-restore.ts keeps
  the always-on index + spill + decompress machinery (that is the default-fold
  recovery path, not the strip's)
- config: compress.stripImages / compress.stripImagesKeepRecent dropped from
  the type, whitelist, and parser; old configs get a one-time INERT warning
  (warnInertStripImages) instead of silent no-op
- docs: seeds + generated tables regenerated; EN/ZH prose sections replaced
  with removal notes; decompress error texts no longer reference the flag
- tests: strip-images / strip-images-compact / strip-log-observability /
  strip-cutoff-anchor suites deleted; compress-settings cascade/parse cases
  removed; new strip-images-removal.test.ts pins the INERT notice + silence

Closes #2608 (archival-failure-still-strips existed only on the strip path;
with the strip gone there is nothing to fail)
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-10_remove-strip-images (f880691)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.2903-pr.2688.46853b8

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

Option B — Download artifact

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

Install instructions are refreshed on each push.

Review nit from the PR review: the #618 note above prepareResponsesCompact
still described the removed conditional re-serialization ("forward the
re-serialized post-strip work instead so dropped images don't ride along").
With the strip gone the call always forwards bodyBuffer unchanged, so the
note now matches the code (byte-identical passthrough when no bili
compaction item is present).
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷

Review 完成:可合(等新 head 的 CI 全绿)。我拉了分支逐文件通读 diff、本地定向验证、并对最新 master 做了 rebase 检查。结论:方向正确、执行干净,未发现回归;顺手修了一个小问题(stale 注释)已推到 PR 分支。

验证证据

  • Diff 通读(27 文件,+139/-1919,单 commit):kernel 删除(strip-images.ts 236 行 + barrel export + 3 个测试套件)、host 接线移除(handle/server/compress-settings/image-restore)、config 字段移除 + 一次性 INERT 警告(warnInertStripImages,与 warnInertResignPassthrough 同模式)、docs EN/ZH + website i18n 再生成、测试(删 4 个 strip 套件、新增 strip-images-removal.test.ts 钉住「INERT 只报一次 + 干净配置静默」)。
  • 残留引用扫描(全仓 stripImages/stripHistoricalImages/foldAnchoredCutoff/coreMessagesFor):剩余命中全部是有意保留(docs 移除说明、INERT 警告代码、新测试、注释)。
  • 本地定向运行(PR head):kernel 套件 1264/1264;host typecheck 0 error;strip-images-removal 2/2、fold-images-archive 3/3、compress-settings、image-restore 合计 59/59;相邻图像管线套件(count-tokens / fix-781-summary-images / fix-488-multimodal / image-compress / issue1800 / issue1843 / issue2558 / issue857 / responses-tool-images)65/65;check:unused-exports clean。
  • Rebase 检查:master 比 PR base 只多一个 commit(fix(#2658): dsh native-compaction rebase fallback on anthropic/google lanes #2664 dsh-anthropic-google,3 文件与本 PR 零重叠);merge 模拟无冲突,合并后 head 上 typecheck + 含 fix(#2658): dsh native-compaction rebase fallback on anthropic/google lanes #2664 新测试的核心套件 65/65。
  • CI:旧 head a9fdc5374 除一条因我下方 push 取代而自动取消的 windows test job 外 28/29 全绿(kernel-guard、unused-exports、docs-coverage、config-surface-guard、docs-sync、全部 e2e lane 均绿);新 head 0fbb1af10 的全套 CI 正在跑。

顺手小修(独立标注 commit 0fbb1af10,已推 PR 分支)

既有行为回归清点(逐项)

既有行为 结论
可归档媒体默认折叠 + 折叠前归档 <state>/retrieve/img/<session>/ + decompress({imageRef}) 恢复(#2640) 不变 — fold-images-archive 3/3、image-restore 套件绿
不可归档媒体(远程 URL / fileData,#2609)钉在 wire 永不折叠 不变
图像索引常开(每请求 buildIncomingImageIndex、latest-wins、60s 驱逐节流) 不变(仅注释措辞更新)
count_tokens 路径 有意变更(仅影响曾开 stripImages 的用户):旧行为下 count_tokens 也按同一 cutoff 剥离「使计数贴近模型轮」;现无剥离,count_tokens 数原始 body —— 与新单一路径语义一致(模型轮现在也确实带着这些图发送)
responses-compact 转发路径 非 strip 用户字节级不变(旧代码 stripped.removed==0 时本就转发 bodyBuffer);strip 用户为预期行为变更
旧配置兼容 键被忽略、不崩溃、一次性 [acp-config] … INERT … 警告(按签名去重)— 新测试钉住
其余 compress 配置项 白名单/parser 只少这两个键,其他字段语义无漂移(compress-settings cascade 套件绿)

高危域点名核查:自动更新/自更新路径未触碰;版本与 lockfile — 仅 kernel/package.json 0.0.113→0.0.114(符合 kernel 边界版本纪律,PR 正文含 kernel-change 声明);dsh 相关未触碰;网络/代理未触碰。

结构化八问

  1. 是什么问题:不是缺陷修复而是冗余清除——默认媒体折叠(Archive-then-fold: default folding for archivable media (Closes #2607, Fixes #2609) #2640)落地后,可选的 wire 侧图像剥离(compress.stripImages)成为冗余,且其滑动 cutoff 每轮移动发出字节边界,在四条 wire 中的三条上逐轮破坏 prompt cache(仅 anthropic 有 stripImages 滑窗剥离的图片无恢复通道,且滑窗每轮击穿 prompt cache(billion-context-pi#593 同族缺口) #1995 折叠锚定修复)。
  2. 什么原因导致的:媒体处理历史上双路径并存(默认折叠 + 可选剥离);剥离的边界机制(len - keepRecent 滑动窗口)与 prefix-cache 稳定性天然冲突,而折叠成为默认后剥离的边际价值归零。
  3. 影响范围与严重程度:只影响显式开启 compress.stripImages 的用户(opt-in,默认 false)——失去折叠间的 wire 侧剥离,图片留在 wire 上直到被折叠(折叠即归档、可恢复);从未开启的用户零行为变化。严重度:对少数 opt-in 用户的有意行为变更,已文档化并带警告。
  4. 怎么修复的:单路径收敛——删 kernel 公共导出 stripHistoricalImages 及其接线、config 字段(type/whitelist/parser),旧配置转为惰性(一次性 INERT 警告指向文档移除说明),docs EN/ZH + website 替换为移除说明,删 strip 专属测试套件并以新测试钉住惰性通知契约。
  5. 是否有回归问题:无(逐项见上表;唯一有意变更是 count_tokens / strip 用户行为,已披露 old→new)。
  6. 是否破坏缓存:不破坏——反而消除了 strip 用户的逐轮破缓存机制;默认用户字节级不变。INERT 警告只在日志,不在 wire。
  7. 是否改了设计方向:媒体处理收敛到单一通路(fold + archive + decompress({ imageRef }) 恢复);配置面缩小两个键(移除而非新增/改名,PR 正文含 config-surface 说明,方向与 建议:compress.stripImages 默认开启——否则带图消息不可压缩会形成只升不降的输入地板撑爆上下文 #2607/Archive-then-fold: default folding for archivable media (Closes #2607, Fixes #2609) #2640 owner 拍板一致)。
  8. 是否引入新配置:无。移除两项,迁移方式=无需操作(键被忽略 + 一次性警告)。

补充:kernel 改动属 human-only review 层(碰了 kernel/ → 不可自动合并),需人工合并。Closes #2608 成立(该缺陷只存在于 strip 路径,strip 没了它自然消失)。

判定:可合 —— 待新 head 0fbb1af10 的 CI 全绿(进行中;旧 head 除被取代取消的那条外已全绿)。合并请由 @ranxianglei 本人执行。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷

CI 全绿确认:rebase 后的新 head 7d3a54d49(含 master 的 #2664/#2647 + 我推的注释小修 0fbb1af1)—— 29/29 lanes 全部 success,包括四个 test 矩阵 job(ubuntu/windows × node 22/24)、kernel-guard、unused-exports、docs-coverage、config-surface-guard、docs-sync 及全部 e2e lane。

之前 0fbb1af10 上四条 test job 显示 cancelled 是分支被 rebase 取代的正常行为,非失败。

最终判定维持:可合。合并请由 @ranxianglei 本人执行(kernel 改动属 human-only 层)。合并后 #2608 随之关闭。

@ranxianglei
ranxianglei merged commit 9d1b9d2 into master Oct 10, 2026
29 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

📦 Merged Build Published

This merge to master was published as 0.0.236-master.9d1b9d2 (rolling master tag).

npm install -g billion-context@0.0.236-master.9d1b9d2  # this exact build
npm install -g billion-context@master  # always the newest merged build

npm view billion-context@master prints the current version at any time.

ranxianglei pushed a commit that referenced this pull request Oct 10, 2026
…semantics

Supplement to 990cbe8 (which fixed only the tsc errors): under
post-#2688 semantics there is no wire-side image reduction left, so
the two tests that asserted the removed stripImages recovery path
(200 + reduced rebuilt body) fail at runtime with the forward-stage
413. Adapt them to assert the actual contract: over-budget rebuilt
bodies stop at stage=forward / request_too_large without touching
upstream, whether images sit in messages or tool outputs; the
admission-slot flow ends at the same forward guard once a slot is
released. Also fix reference/request-body-budget.md (en+zh), which
still told users to configure the removed compress.stripImages.

Verified locally: tsc --noEmit clean; node --import tsx --test
--test-concurrency=1 tests/image-request-budget.test.ts
tests/request-body-budget.test.ts -> 10/10 pass.
YunzhouLi-hub pushed a commit to YunzhouLi-hub/billion-context that referenced this pull request Oct 11, 2026
…-request-budget test

ranxianglei#2688 removed compress.stripImages/stripImagesKeepRecent from CompressSettings, but ranxianglei#2613's image-request-budget test (merged after ranxianglei#2688) still referenced them, breaking master typecheck. Drop the dead keys from the fixture config and the inert stripImages=false toggle line; keep every assertion intact (over-budget rebuilt request -> forward-stage 413, no upstream contact). Zero behavioral change.
ranxianglei added a commit that referenced this pull request Oct 11, 2026
…rebase (#2671)

Rebase onto master (47 commits) surfaced two machine-dependent seams and
one real timing bug:

1. Test hermeticity (storage-corpus / storage-unified / golden-storage-drive
   / web-sessions): these suites point SessionStore at the REPO corpus dirs
   or tmp dirs and assert on directory contents. On a developer machine
   whose real billion-context.json sets storage.unified=full (exactly the
   dogfood setup this PR exists to enable), the config-file tier leaked into
   every test that cleared the env expecting legacy: stray index.db files
   inside tests/golden/storage-corpus (breaking the no-orphans pin and being
   cpSync'd into downstream tmp dirs), sidecars inside web-sessions tmp dirs
   tripping the #1937/#2180 foreign-content alarms. Pin BILI_CONFIG_FILE to
   a missing tmp path and clear BILI_STORAGE_UNIFIED at module top of each
   suite — same pattern master's #2673 established for XDG state.

2. Eager storage-mode stamp: the kernel write chain may invoke the record
   builder on a later tick than the caller (serialized write chains, #2674).
   guardedBuild captured effectiveFileStorageMode() inside the deferred
   thunk, so a save enqueued under one mode could be STAMPED under whatever
   the env said when a background chain reached the build. Capture the stamp
   eagerly at enqueue time and thread it into buildRecord.

3. storage-render goldens regenerated (stateDigest + metadata section only;
   state/blockContents/stats sections unchanged): master #2688 removed
   compress.stripImages from the effective config, which is mirrored into
   persisted session metadata.effectiveConfig.

Battery: 69/69 (golden-storage-render, storage-corpus, storage-unified,
web-sessions, config-file-cache, config-surface-guard, admin-origin,
image-request-budget), tsc clean, unused-export gate clean (2 waived).
storage-unified passes even with a hostile BILI_STORAGE_UNIFIED=full
exported into the test process.
ranxianglei added a commit that referenced this pull request Oct 11, 2026
…rebase (#2671)

Rebase onto master (47 commits) surfaced two machine-dependent seams and
one real timing bug:

1. Test hermeticity (storage-corpus / storage-unified / golden-storage-drive
   / web-sessions): these suites point SessionStore at the REPO corpus dirs
   or tmp dirs and assert on directory contents. On a developer machine
   whose real billion-context.json sets storage.unified=full (exactly the
   dogfood setup this PR exists to enable), the config-file tier leaked into
   every test that cleared the env expecting legacy: stray index.db files
   inside tests/golden/storage-corpus (breaking the no-orphans pin and being
   cpSync'd into downstream tmp dirs), sidecars inside web-sessions tmp dirs
   tripping the #1937/#2180 foreign-content alarms. Pin BILI_CONFIG_FILE to
   a missing tmp path and clear BILI_STORAGE_UNIFIED at module top of each
   suite — same pattern master's #2673 established for XDG state.

2. Eager storage-mode stamp: the kernel write chain may invoke the record
   builder on a later tick than the caller (serialized write chains, #2674).
   guardedBuild captured effectiveFileStorageMode() inside the deferred
   thunk, so a save enqueued under one mode could be STAMPED under whatever
   the env said when a background chain reached the build. Capture the stamp
   eagerly at enqueue time and thread it into buildRecord.

3. storage-render goldens regenerated (stateDigest + metadata section only;
   state/blockContents/stats sections unchanged): master #2688 removed
   compress.stripImages from the effective config, which is mirrored into
   persisted session metadata.effectiveConfig.

Battery: 69/69 (golden-storage-render, storage-corpus, storage-unified,
web-sessions, config-file-cache, config-surface-guard, admin-origin,
image-request-budget), tsc clean, unused-export gate clean (2 waived).
storage-unified passes even with a hostile BILI_STORAGE_UNIFIED=full
exported into the test process.
@github-actions github-actions Bot mentioned this pull request Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

stripImages 在原图归档失败后仍剥离图片,imageRef 无法恢复

1 participant