Skip to content

[PR] fix: make full-mode storage tests deterministic (#4004) - #4011

Open
ranxianglei wants to merge 6 commits into
masterfrom
2026-10-20_full-mode-persist-tests-4004
Open

ranxianglei wants to merge 6 commits into
masterfrom
2026-10-20_full-mode-persist-tests-4004

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Closes #4004

What / why

Under the #3818 default (storage.unified=full) reads go unified-first and the sqlite index is the authoritative carrier. Six long-standing persistence tests broke under that default — the four named in the issue plus two more on-disk-layout assertions in the same file:

Fix — align the tests with shipped reality (test-only, no production change)

The "is the index authoritative" question was already answered by #3818 shipping full mode as the default for the index to become the load path. The index row is minted record-id + payload together by bili, so serving it cannot misattribute; genuine index↔envelope drift is handled separately by driftedSessions (#3135④). Adding an id-consistency guard to the unified-first path (the issue's option b) would couple the authoritative read to the health of the redundant fallback copy — an availability regression with no safety gain. So:

  • Pin the four facet-A assertions to shadow mode (envelope = read path), where those guards actually fire — a small withShadowTempStore helper (proxy-persist) and a scoped env pin (issue2129).
  • Make the two facet-B layout assertions ignore the unified sidecar's index.db*.
  • Add one full-mode test pinning the authority semantic: an intact index row is served over a tampered legacy envelope (the inverse of the shadow guard, and it has teeth against a regression back to option-b).

Behavior-change disclosure (Issue-Work Deliverables rule 4)

No production behavior changes. The runtime already behaved exactly as the corrected tests assert; this only makes the stale shadow-era test expectations deterministic again under the new default. No config surface touched.

Verification

  • Rebased onto current master (e98ccda); clean (neither file was touched by the intervening commits).
  • tsc --noEmit clean; tests/proxy-persist.test.ts 24/24 and tests/issue2129-restart-measurement-state.test.ts 4/4 on the rebased head.
  • Full-suite verdict deferred to remote CI (local-testing discipline).

If option (b) was actually intended — the unified read also rejects on envelope-id mismatch even when the index is intact — say so and I'll reverse it; I don't believe that's the right semantics.

Kernel Boundary declaration

kernel-change: incidental lockfile metadata only — NO kernel source/config/semantic change. This PR's diff touches kernel/package-lock.json solely via the ci-fixes merge (dfadc21b3), which syncs recorded-version metadata (0.0.164→0.0.165) after master's kernel bumps 293ae6542/de5e03659 skipped lockfile regeneration (#2704 drift class; the repair that unblocks lock-sync on master tip cdac1c099). No change under kernel/src/**, no kernel/package.json version edit (already 0.0.165), no behavior impact. The matching root package-lock.json sync rides in the same merge.

Under the #3818 default (storage.unified=full) reads go unified-first and
the sqlite index is authoritative, which bypasses the envelope integrity
guards that four long-standing tests assert — so they failed non-deterministically
locally. Two more broke on the on-disk layout once index.db lands in the
sessions dir.

Align the tests with shipped reality instead of changing production code:
- Pin the envelope-guard assertions to shadow mode (envelope = read path),
  where those guards actually fire.
- Make the "exactly one top-level entry" layout assertions ignore the unified
  sidecar's index.db(+wal/shm).
- Add one full-mode test pinning the authority semantic: an intact index row
  serves over a tampered legacy envelope.

Test-only; no production behavior changes.
@ranxianglei ranxianglei changed the title fix: make full-mode storage tests deterministic (#4004) [PR] fix: make full-mode storage tests deterministic (#4004) Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-20_full-mode-persist-tests-4004 (6b4f28b)

Latest build — install this exact version

npm install -g billion-context@0.0.6129-pr.4011.ce77a0b

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
6b4f28b billion-context@0.0.6129-pr.4011.ce77a0b build
c9d9058 billion-context@0.0.6124-pr.4011.6cf6ca4 build
dbab850 billion-context@0.0.6107-pr.4011.542f1ac build
7b24b29 billion-context@0.0.6015-pr.4011.f7f0b7d build

Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr4011.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)

查重:不重复——#4011 是 #4004 的执行 PR,与在途其他 PR 无重叠。但审核发现一个关键事实:这个 PR 已被 master 上的 311c7968e(#4242 wave 3,提交信息明确列出 #4004)完整取代,建议直接关闭、不要合并。

标签:pr、bug、scope/ci、p3(测试基建问题,纯测试代码,零用户影响)。

先回答你上次「没看懂啥意思」的问题(option a vs b,白话版)

背景一句话:新默认(full 模式)下,会话状态以 sqlite 索引为准,JSON 文件退化成冗余备份。老测试断言的是「篡改 JSON 文件 → 必须被拒绝」,但 full 模式下读取根本不看 JSON,这个断言就失效了。两个选项:

  • 选项 a(本 PR 的做法):接受「索引说了算」,把这些断言挪到 shadow 模式(JSON 还是读取路径的模式)下测;
  • 选项 b:full 模式的读取路径上也加一道 id 交叉校验(索引好好的,但 JSON 的 id 对不上也拒绝)。

结论:维持选项 a,不需要反转。 理由一句话说清:索引行是 bili 把「记录 id + 内容」一起原子写进去的,直接从索引取不可能张冠李戴;而选项 b 是在权威读路径上依赖那份冗余备份的健康度——备份坏了会把本来能用的会话变成不可用,安全性却一分没涨。真正的「索引↔JSON 漂移」有专门通道(driftedSessions),不归这条读路径管。owner 实际落地的 wave 3 也是按选项 a 做的,两者一致。

为什么 PR 可以关:wave 3 做得更全

311c7968e 对同一组测试的处理严格覆盖并强于本 PR:

  1. tests/proxy-persist.test.ts 文件头一行钉死 BILI_STORAGE_UNIFIED = "legacy"——比本 PR 逐测试包 shadow helper 更干净(整个文件就是 envelope 层测试,facet A/B 一并解决);
  2. tests/issue2129-restart-measurement-state.test.ts 同样文件级 legacy 钉法;
  3. 新增更强的权威语义测试 storage-full-flip.test.ts「Storage wrap-up wave 3: Single source of truth for status fields + Orphan representability + Authoritative "full" resolu | 存储收尾第三波:状态字段单一事实源 + 孤儿可表示化 + full 权威定案 + 媒体 CAS 全量拆分 + 归零即删(#4192/#4216/#4004/#4069/#3987) #4242 ⑦ full mode serves the index when only the envelope id was tampered (storage full mode: loadSync serves the sqlite index and bypasses the envelope id-mismatch guard (#2671-era tests fail locally) #4004)」——显式钉 full 模式、含 sqlite 句柄正确关闭,比本 PR 的新测试更完整。

本地实测(node v22):干净 master 上三个相关文件全绿(proxy-persist 23/23、issue2129 4/4、storage-full-flip 10/10 含 ⑦);rebase 到当前 master 后的 PR head 反而是 23/24——PR 的新测试因文件头 legacy 钉法被压成 legacy 而确定性失败。即:合并前不 rebase 会带红,rebase 后则整份 diff 冗余且自伤。

原 CI 红的根因(不是竞态,是环境差异)

CI 所有测试文件经统一 preload(tests/preload-storage-baseline.mjs)钉死 BILI_STORAGE_UNIFIED=legacy。PR 的新测试依赖生产默认(full),于是:本地(无 preload)过、CI 全车道确定性红。另外 3 个 shadow 钉法测试开了真实 sqlite sidecar,teardown 删目录前没关句柄 → Windows EBUSY。wave 3 的文件级 legacy 钉法让这两个问题都不复存在(该文件不再开任何 sidecar)。

同一次 CI 里的其余红(#3769 rotation-hidden flake ×2 车道、plugin-bypass #920、一车道 exit-1 但无失败断言行)与本 PR 的两文件 diff 无关,属既有 flake 候选,不在此处置。

结构化八问

  1. 是什么问题:Storage wrap-up: 6 fixes + switch default mode to full (single PR) | 存储收尾六修 + 缺省模式翻 full(一个 PR 统一处理) #3818 切 full 默认后,6 个历史持久化测试对新默认不确定/失效;本 PR 把测试对齐到已发布行为(纯测试改动)。
  2. 什么原因导致的:读取路径从 JSON 换成索引优先后,旧断言仍打在 JSON 层;叠加 CI 全局 legacy 基线与生产默认不一致,使「依赖默认值」的测试本地绿、CI 红。
  3. 影响范围与严重程度:零用户影响(无生产代码变更);仓库层面 = 本 PR CI 红 + rebase 后新增一处确定性红。p3。
  4. 怎么修复的:已被 master 311c7968e 以更优形态修复(文件级模式钉法 + 独立 full 套件里更强的权威测试);本地验证三文件全绿。
  5. 是否有回归问题:本 PR 无回归(无运行时变更);wave 3 自身的 persist.ts 重构不在本 PR diff 内,由 Storage wrap-up wave 3: Single source of truth for status fields + Orphan representability + Authoritative "full" resolu | 存储收尾第三波:状态字段单一事实源 + 孤儿可表示化 + full 权威定案 + 媒体 CAS 全量拆分 + 归零即删(#4192/#4216/#4004/#4069/#3987) #4242 自己的 CI 把关。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:没有——确认已发布方向(索引权威、envelope 守卫保留在 shadow/legacy 层、真漂移走 driftedSessions)。
  8. 是否引入了新的配置:没有。

交付物

收工判定:PR #4011 可关闭、无需合并;全部修复已在 master 上。

@ranxianglei ranxianglei added bug Something isn't working p3 scope/ci labels Oct 23, 2026
ci-check added 4 commits October 26, 2026 10:19
master window commits 293ae65/de5e03659 bumped kernel/package.json to
0.0.165 without regenerating the lockfiles; lock-sync re-resolution then
rewrites the stale recorded versions (root 0.0.163, kernel 0.0.164) and
fails. Pure recorded-version sync via npm install --package-lock-only;
no dependency or semantic change.
… PR body

kernel-guard reads github.event.pull_request.body at event time; a body
edit alone does not re-run workflows. Empty commit carries no file change.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

查重:不重复。 按失败签名(lock-sync / kernel-guard + 具体错误行)检索 open+closed issue/PR:历史同类 lockfile 漂移修复(#2717/#3782/#4419/#4420)均已关闭;本轮漂移无在途修复条目(哨兵的 ci-fixes dfadc21b3 即本例的收敛修复,PR #4814 承载)。

本次唤醒处理了该分支连续两道门禁红(attempt 1/2 → 2/2),均已解决并实测:

① lock-sync 红(head dbab850)— 继承性失败,非本分支代码问题。 master 最近两次 kernel bump(293ae6542→0.0.164、de5e03659→0.0.165)跳过了 lockfile 再生:root package-lock.json 仍记 acp-kernel 0.0.163、kernel/package-lock.json 仍记 0.0.164,门禁按配方重解析必然改写这 3 行后红。master tip cdac1c099 自身即红(check 121427625628),凡从 master/ci-fixes merge 的分支全部继承。处置按 CI 协调政策「master 级失败收敛到 ci-fixes,不在自己分支重复修」:哨兵已推送同内容修复 dfadc21b3(纯 npm install --package-lock-only 再生;我本地复现一致并验证幂等——二次运行零 diff),我 merge 进本分支推送(c9d905818),lock-sync 转绿。

② kernel-guard 红(head c9d9058)— ①的直接后果。 merge ci-fixes 后 PR diff 触及 kernel/package-lock.json,触发 Kernel Boundary 规则(触及 kernel/** 的 PR 必须在正文声明 kernel-change:)。处置:PR 正文补「Kernel Boundary declaration」一节——如实声明这是顺带进来的 lockfile 记录版本元数据同步,无 kernel 源码/配置/语义变更、无版本号编辑——并推空提交(6b4f28b17)重跑 CI(仅改正文不会触发工作流)。新 head 上 kernel-guard 与 lock-sync 均已绿(实测 check-runs,50 个 run 全部归属新 head)。

八问:

  1. 是什么问题:分支上两道 CI 门禁红——lock-sync(lockfile 记录的版本号落后于 kernel/package.json 实际值)、kernel-guard(diff 触及 kernel/ 而正文缺声明)。都不是代码缺陷。
  2. 什么原因导致的:① master 的 kernel bump 提交跳过 lockfile 再生(package-lock.json version metadata lags package.json (bili 0.1.190 vs 0.1.191, kernel 0.0.112 vs 0.0.114) #2704 漂移类),master 自身红、被分支继承;② 修 ① 的 merge 把 kernel/package-lock.json 带进 diff,撞上 Kernel Boundary 声明规则。
  3. 影响范围与严重程度:① 所有从 master/ci-fixes merge 的分支 lock-sync 全红(挡住各 PR 合并;纯记录版本元数据,零运行时/用户影响);② 仅本 PR(缺声明)。程度:挡合并、不影响功能。
  4. 怎么修复的:① 修复收敛到 ci-fixes(哨兵 dfadc21b3,幂等已验证),merge 进本分支;② PR 正文补如实的 kernel-change 声明 + 空提交重跑。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 [PR] ci: converge master-CI fixes (persist restamp guard + lockfile version sync) (#4599) #4814(ci-fixes→master,含 dfadc21b3)在途等 owner 合并。
  5. 是否有回归问题:无。文件级变更仅两个 lockfile 共 3 行版本号(root 0.0.163→0.0.165;kernel 0.0.164→0.0.165 ×2)+ 一个空提交;依赖解析结果不变,任何运行时/持久化/wire 行为不受影响。本 PR 自身 diff 路径(两个测试文件)的既有行为未动。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:无。
  8. 是否引入了新的配置:无。

行为变更披露:无(纯 lock 元数据同步,旧值→新值仅为记录版本号,零语义变化)。

判定:CI 侧收工——新 head 6b4f28b17 上 kernel-guard + lock-sync 实测双绿,其余 test/static-gates shard 运行中(本提交无文件变更,上一 head 全套已绿)。注意:本线程 floor 4 的实质审核结论不变——本 PR 内容已被 master #4242 wave 3 完整取代且处理得更彻底,当时建议直接关闭、不要合并;本次 CI 修复只是解除门禁阻塞,不构成对合并的背书。关或合由 owner 拍板(agent 依政策不执行关闭)。

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

bug Something isn't working p3 scope/ci

Projects

None yet

Development

Successfully merging this pull request may close these issues.

storage full mode: loadSync serves the sqlite index and bypasses the envelope id-mismatch guard (#2671-era tests fail locally)

1 participant