Skip to content

[PR] Add regression test: SQLite engine bootstrap reports failed+cooldown when a downloaded engine won't register - #3930

Merged
ranxianglei merged 5 commits into
masterfrom
2026-10-19_bootstrap-regfail-test
Oct 20, 2026
Merged

ranxianglei merged 5 commits into
masterfrom
2026-10-19_bootstrap-regfail-test

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

What & why

While verifying the bootstrap hardening cited in #3788 (mirror fallback, unloadable-cache retry, honest registration failure), I found the third one — commit 11e5bda, "download ok but registration fails → failed + cooldown instead of a lying downloaded" (src/storage/engine-bootstrap.ts:265) — has no regression test: the commit touched only engine-bootstrap.ts (+10/-1), and tests/storage-engine-bootstrap.test.ts covers every adjacent path (unloadable-cache retry #3135-5, sha512 quarantine, mirror fallback/exhaustion, timeout budget) except this one.

If this path regressed, the panel/status wire would show bootstrap=downloaded while no engine is actually loadable — users would believe unified storage is ready while silently running legacy-only, exactly the blind spot behind #3788-style reports.

Change

One hermetic test in tests/storage-engine-bootstrap.test.ts: serves a tarball whose bytes pass the pinned sha512 and extract cleanly but whose lib/index.js throws on require, then asserts:

  1. status = failed, detail = post-download registration failed
  2. the verified bytes remain on disk AND the cooldown marker (.bootstrap-failed.json) is written
  3. next boot (inFlight reset) returns cooldown with zero re-downloads (the Storage Subsystem Wrap-up Checklist (#3130 Review): Dropping the last tick upon self-disable; BILI_PERSIST=0 falsely triggering a "Storage Degraded" banner; storageMode stamp mismatched with the actual enabled mode; and 3 more (6 items total) | 存储子系统收尾清单… #3135-5 cache removal still happens, but the cooldown gates the ~11 MB fetch)

Verification

  • targeted local: node --import tsx --test tests/storage-engine-bootstrap.test.ts → 31/31 pass
  • npm run typecheck clean
  • full suite = remote CI on the pushed head

Fixes #3929
Found while working #3788 (来源: #3788 分析 SQLite unified storage degraded to legacy-only 时发现).

@ranxianglei ranxianglei changed the title Add regression test: SQLite engine bootstrap reports failed+cooldown when a downloaded engine won't register [PR] Add regression test: SQLite engine bootstrap reports failed+cooldown when a downloaded engine won't register Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-19_bootstrap-regfail-test (5b3f46b)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.4744-pr.3930.0502ea5

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-pr3930.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)

查重: 不重复 —— #3930 是 #3929(缺失回归测试)的唯一实现;open/closed issue 与 PR 检索均无其他条目为这条路径补测试。

标签: scope/storage + p3(SQLite 统一存储自举的回归测试缺口,纯测试新增,当前无外部影响)。

这是带 ework-agent-pr 标记的既有 agent PR,没有重做——拉分支核对了代码、独立审了方向与回归面、本地做了定向验证。

① 原 issue(#3929)方向关: 方向正确。修复 commit 11e5bda(+10/-1,src/storage/engine-bootstrap.ts:258-269)加了「下载成功但注册失败 → failed + 6h cooldown」契约,没带测试;同文件其余相邻路径(unloadable-cache 重下 #3135-5、sha512 隔离、mirror fallback/exhaustion、timeout budget)全有断言,唯独这条缺。PR 方案与 issue 逐项一致(一个 hermetic 测试、三条断言),范围干净。

② 回归审查: diff 只动 tests/storage-engine-bootstrap.test.ts(+40 行,单 commit,base = 当前 master 5121f45,无滞后)。既有行为清单 = 该文件其余 30 项断言(happy path/cache hit/unloadable cache 重下/sha512 隔离/cooldown skip+expiry/offline fail-safe/disabled knob/legacy short-circuit/unsupported platform/concurrent dedup/extractor×4/knob 优先级/mirror 三例/timeout budget×2/stale cache 自愈):全部未触碰,本地全绿。无高危模式(无语义漂移、无阈值/时序/输出格式变化)。

④ 测试有效性(有牙,实测): 我把 11e5bda 的修复 hunk 临时还原成修复前形态跑新测试,它立即在第一断言挂掉:registration failure must report failed, got {"status":"downloaded","detail":"linux-x64"} —— 正是 issue 描述的谎报 downloaded 回归;还原后恢复绿。不是恒真测试,路径真回归时一定抓得住。

验证:

  • 定向本地:node --import tsx --test tests/storage-engine-bootstrap.test.ts → 31/31 pass
  • npm run typecheck clean
  • 全量套件 = 推送 head 上的远程 CI: 正在跑(test lanes in progress),结果出来我再报一轮。

结构化八问:

  1. 是什么问题: SQLite 引擎自举「下载成功但引擎注册失败」这条路径(报 failed+cooldown 而非谎报 downloaded)没有回归测试钉住。
  2. 什么原因导致的: 修复 commit 是 review 热修,只改了源码(+10/-1),没留配套测试,契约裸露。
  3. 影响范围与严重程度: 当前无用户影响(修复已上线且工作正常);属回归风险敞口——若该路径回归,面板/status 会显示 bootstrap=downloaded 而实际没有任何可加载引擎,用户以为统一存储就绪、实际静默跑 legacy-only(SQLite unified storage degraded to legacy-only (bili v0.1.201, node v20.19.5, win32-x64) #3788 类盲区)。严重度: 内部实现/测试覆盖缺口。
  4. 怎么修复的: 加一个 hermetic 测试——tarball 字节过 sha512、解包干净,但 lib/index.js require 即抛错;断言 ① status=failed + detail=post-download registration failed ② 已验证字节留在磁盘且 .bootstrap-failed.json cooldown 标记写入 ③ 下一轮 boot(inFlight 重置)返回 cooldown 且零重下(Storage Subsystem Wrap-up Checklist (#3130 Review): Dropping the last tick upon self-disable; BILI_PERSIST=0 falsely triggering a "Storage Degraded" banner; storageMode stamp mismatched with the actual enabled mode; and 3 more (6 items total) | 存储子系统收尾清单… #3135-5 仍会移除不可加载缓存,但 cooldown 挡住 ~11 MB 抓取)。
  5. 是否有回归问题: 无。零代码改动;文件内其余 30 项既有行为未变且全绿。
  6. 是否破坏缓存: 不涉及——不触碰任何缓存/重试/增量游标逻辑。
  7. 是否改了设计方向: 不变。
  8. 是否引入新配置: 无。

判定: 代码审查层面可合(纯测试新增、diff 干净、测试有牙、base 无滞后);等远程 CI 全量绿后收工。

@ranxianglei
ranxianglei force-pushed the 2026-10-19_bootstrap-regfail-test branch from 1813157 to 973df8c Compare October 20, 2026 07:50
ranxianglei pushed a commit that referenced this pull request Oct 20, 2026
… flake, #1646/#3720 family)

Incidental CI-red fix for #3930: the test(windows-latest, node 22, shard 1) lane of the rebased head failed in tests/issue3399-cross-route-load.test.ts teardown with ENOTEMPTY on the bare recursive rmSync - a leftover holdout from the tmp-rm sweep (#1646/#1915/#3721). Unrelated to the bootstrap regression test added by this PR, which passed on the same lane.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

CI 跟进(第一轮回复后):

rebase: 审查期间 master 前进了(#3927 archive-jsonl、#3903 dsh-compression-protocol 合入,18 文件 +580/-38,与本 PR 零文件重叠)。分支已 rebase 到新 master(新 head 与我的本地 rebase 逐字节同树,已核对)。

CI 红了一条 lane,根因与本 PR 无关,已顺手修掉:

状态: 修复 commit 已推(973df8c55..e84984582,fast-forward),新 head 的全量 CI 正在跑,绿了我再报最终收工判定。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

CI 小插曲(透明记录):e84984582 那轮 39 条 lane 里 38 条全绿(含之前红的 windows node22 shard1——flake 修复生效),只剩 test (ubuntu-latest, node 24, shard 1) 一条:测试步骤跑了 ~50 分钟零日志流(兄弟 shard 都在 20 分钟内完成),判定为 runner 环境挂死而非代码失败。单 job cancel 与 run rerun 均无权限(404/403),已取消该轮并推了一个空 commit d2cb1e50a(树与 e84984582 逐字节相同)重触发全量矩阵。新轮绿了我报最终收工判定。

@ranxianglei
ranxianglei force-pushed the 2026-10-19_bootstrap-regfail-test branch from d2cb1e5 to 8679ada Compare October 20, 2026 12:26
ranxianglei pushed a commit that referenced this pull request Oct 20, 2026
… flake, #1646/#3720 family)

Incidental CI-red fix for #3930: the test(windows-latest, node 22, shard 1) lane of the rebased head failed in tests/issue3399-cross-route-load.test.ts teardown with ENOTEMPTY on the bare recursive rmSync - a leftover holdout from the tmp-rm sweep (#1646/#1915/#3721). Unrelated to the bootstrap regression test added by this PR, which passed on the same lane.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

已 rebase 到最新 master 并重新推送,等远程 CI。 状态更新:

本轮做了什么

  1. 分支 rebase 到最新 master 440c51146(干净,零文件重叠——本 PR 只碰 tests/storage-engine-bootstrap.test.ts 与 tests/issue3399-cross-route-load.test.ts)。顺手丢掉了上一轮纯为触发 CI 的空提交,最终历史只剩两个内容提交。新 head 8679adae7(force-with-lease,推前已核对远端无人动过分支)。
  2. 本地定向验证(rebase 后 head):
    • node --import tsx --test tests/storage-engine-bootstrap.test.ts tests/issue3399-cross-route-load.test.ts tests/tmp-rm.test.ts → 50/50 pass
    • 上一轮 CI 里红的 tests/verif-induction-append-stability.test.ts 本地实测 2/2 通过(原因见下)
    • typecheck:仅剩 1 个错误,且不来自本 PR(见下)

master 侧的两个变化影响本轮 CI 判断

  1. verif SMT 套件现在有求解器了:master 本轮把 z3-solver(^5.3.1) 加进了 devDependencies,verif/solve.ts 改为优先用进程内 WASM 求解器。本地实测:上一轮因 "no solver available" 挂掉的 induction 测试现在 0.9s 直接过。→ 上一轮的 3 条 verif 红 lane(induction / bug3676 / bug3691)本轮预计转绿(CI 同样走 npm ci 会装上 z3-solver)。
  2. master 自己带来的新红:src/storage/mysql.ts(30,78): Cannot find module 'mysql2/promise' —— MySQL 后端([PR] storage: MySQL backend — step 2 of the pluggable-storage plan (#3931) #3946,今日合入)import 了 mysql2 但 package.json 没声明该依赖,当前任何新 PR 的 typecheck 都会红。与本 PR 无关(diff 完全不碰 storage/mysql.ts),归属 [PR] storage: MySQL backend — step 2 of the pluggable-storage plan (#3931) #3946 工作流;测试型 PR 里混入依赖声明不合适,我不代修。若你看本 PR 时 typecheck 仍红即此因,[PR] storage: MySQL backend — step 2 of the pluggable-storage plan (#3931) #3946 侧修复落地后重触发一轮即净。

上一轮另外两条失败是纯 runner 环境噪声(日志流中断于行中、无 TAP 汇总、同批兄弟 shard 全部正常),本轮全新运行自然重跑。

等新 head 的 CI 全量结果出来,给最终结论(八问体例)。

awork and others added 3 commits October 20, 2026 20:32
11e5bda (#3818 review) made a download that succeeds but fails to
register report 'failed' + arm the cooldown instead of a lying
'downloaded', but shipped no regression test. Add one: a tarball whose
bytes pass sha512 and extract cleanly but whose lib/index.js throws on
require must yield status 'failed' with detail 'post-download
registration failed', write the cooldown marker, and gate the next boot
on 'cooldown' with zero re-downloads.
… flake, #1646/#3720 family)

Incidental CI-red fix for #3930: the test(windows-latest, node 22, shard 1) lane of the rebased head failed in tests/issue3399-cross-route-load.test.ts teardown with ENOTEMPTY on the bare recursive rmSync - a leftover holdout from the tmp-rm sweep (#1646/#1915/#3721). Unrelated to the bootstrap regression test added by this PR, which passed on the same lane.
…#3963 follow-up)

EngineBootstrapSpec gained the required minNodeMajor field when the node
floor gate landed; the fake 13.0.3 tarball spec now declares 22.
@ranxianglei
ranxianglei force-pushed the 2026-10-19_bootstrap-regfail-test branch from 8679ada to ce61b00 Compare October 20, 2026 12:33
…#3619 hermeticity)

The forced path passes the update-policy gate, which fetches the remote
policy document. The test's fetch stub rejected that URL and the count
assertion (2) never included it, so the case only passed when some earlier
state suppressed the fetch — #3963's new test files rebalanced the CI
shards and exposed it. Mock an empty (all-defaults) policy doc and expect
policy + packument + tarball = 3.
@ranxianglei
ranxianglei merged commit e01238e into master Oct 20, 2026
40 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

📦 Merged Build Published

This merge to master was published as 0.0.676-master.e01238e (rolling master tag).

npm install -g billion-context@0.0.676-master.e01238e  # 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.

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.

SQLite engine self-bootstrap: no regression test pins the download-ok-but-registration-failed contract

1 participant