Skip to content

[PR] Async storage backend: sweep foreign rows on latched re-ingest so the drift latch can release (#5415) - #5421

Open
ranxianglei wants to merge 4 commits into
masterfrom
2026-11-01_async-drift-latch-parity
Open

ranxianglei wants to merge 4 commits into
masterfrom
2026-11-01_async-drift-latch-parity

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Closes #5415

What & why

The sync sidecar learned from #5408 (fixed in #5409) that a full re-ingest must sweep foreign rows while the drift latch is held — otherwise a folded-resident save never retires the foreign row and the latch can never release. The async storage backend's twin (enqueueAsyncRecord) was left with completeLog: hasRawTail only, so a latched session on the async backend full-reingested through the queue on every save forever, logged a DIGEST-DRIFT ERROR every VERIFY_EVERY_INGESTS=20 ingests, and the unified store never converged back to the source of truth.

This ports the one-line parity into the async path.

Change

src/storage/shadow.ts — the async full-ingest fallback now passes:

{ completeLog: hasRawTail || this.driftedSessions.has(legacy.id) }

(was { completeLog: hasRawTail }). One line plus an explanatory comment mirroring the sync-sidecar rationale. The sync path (this.sync.ingestSession(...) at the top of record) is untouched — that was #5409's scope.

Self-contained on master: driftedSessions predates #5409 and the async path is byte-identical on master, so this neither depends on nor conflicts with the still-open #5409 (disjoint lines). It merges cleanly regardless of which lands first.

Behavior change (intended fix, disclosed)

While the drift latch is held, an async full re-ingest now runs with completeLog=true, so foreign rows are swept and the index converges onto the envelope view that load routing already serves under the latch (persist.ts lazySource → file when driftedSessions.has(id)). Unlatched sessions are unchanged — for them hasRawTail is false and driftedSessions.has(id) is also false, so completeLog stays exactly as before. No threshold / default / wire-format / persistence-version change.

Config surface

None. No new env var / config key / CLI flag.

Tests

New hermetic regression tests/issue5415-async-drift-latch.test.ts, mirroring B1 of tests/issue5408-frozen-recovery.test.ts against a real async-backend fixture (driven through the actual enqueueAsyncRecord path via UnifiedShadow.fromBackend):

  • positive gate: drift-latched folded save → foreign row swept out of the index;
  • negative gate: unlatched folded save → foreign row left untouched.

Verified locally: both pass with the fix; the positive gate fails without it (timed out waiting for latched folded save to run the authoritative-set sweep). Full-suite verdict comes from CI on the pushed head.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

查重结论(前置):重复。 本 PR 的核心一行改动与已合并进 master 的 PR #5420(commit b26ac0562)逐字等价,等价的回归测试也已经在 master 上。这是同一根因下晚到的第二份实现(两者提交仅相隔约 6 分钟),因此现在它和 master 冲突(GitHub 报 mergeable=dirty)。建议不合并、由你关闭;我已补 duplicate 标签并留此说明,按规范不自行关单。

为什么判为重复(以代码事实为准,不依赖 issue 编号口径):

八问:

  1. 是什么问题:异步存储后端在 drift-latch 持锁时不做权威集清扫,导致冻结会话永远无法自愈。(此问题已由 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 修掉。)
  2. 什么原因导致的:enqueueAsyncRecord 只传 completeLog: hasRawTail,持锁时恒为 false,每次 latched save 都走不完整视图、foreign row 永不清退。
  3. 影响范围与严重程度:异步后端上的 latched 会话索引收敛失败、foreign row 长期滞留——属 p1 一类(存储只增不减的失控增长)。但该影响已由 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 消除。
  4. 怎么修复的:把 sync 路径的「持锁提升」条件原样搬到 async 路径(completeLog = hasRawTail || driftedSessions.has(id))。[PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 已完成并合入。
  5. 是否有回归问题:无。本 PR 相对当前 master 的唯一净新增是一个改名克隆的测试文件;它想再改的那行已被 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 以等价形式占用,强行解冲突只是用等价文本替换等价文本,零行为收益,还会留下两份几乎一样的测试。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

收工判定:不建议合并(duplicate of #5420)。 按规范我不自行关闭 PR——请你在确认后关闭本 PR。若你更想保留本 PR 这份测试命名(issue5415…)而移除 #5420 那份,告诉我即可,那属于取舍、由你拍板。

标签:新增 duplicate(保留原有 pr)——理由:异步后端 drift-latch 收敛缺陷已由已合并的 #5420 修复,本 PR 为其代码级重复项。

@ranxianglei ranxianglei changed the title Async storage backend: sweep foreign rows on latched re-ingest so the drift latch can release (#5415) [PR] Async storage backend: sweep foreign rows on latched re-ingest so the drift latch can release (#5415) Nov 1, 2026
Hermetic async-backend fixture mirroring issue5408-frozen-recovery B1: a drift-latched folded save sweeps the foreign row out of the index (positive gate) while an unlatched folded save leaves it untouched (negative gate). Driven through the real enqueueAsyncRecord path and verified to fail without the fix.
@ranxianglei
ranxianglei force-pushed the 2026-11-01_async-drift-latch-parity branch from 18a88f6 to ac0f405 Compare November 11, 2026 01:56
@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-11-01_async-drift-latch-parity (178f7ae)

Latest build — install this exact version

npm install -g billion-context@0.0.9085-pr.5421.2e132fa

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
178f7ae billion-context@0.0.9085-pr.5421.2e132fa build
dc6d5a4 billion-context@0.0.9072-pr.5421.5cb28fe build
e510619 billion-context@0.0.9055-pr.5421.ee97218 build
ac0f405 billion-context@0.0.9040-pr.5421.f9027c5 build

Download artifact

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

Install instructions are refreshed on each push.

@ranxianglei ranxianglei added the duplicate This issue or pull request already exists label Nov 11, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

Conflict resolved, branch rebased onto current master, CI green on the new head. The substantive finding is unchanged from the 2026-11-01 screening comment: this PR is a duplicate of the fix already merged via PR #5420 / commit b26ac05625 (#5412). Details below.

What I did this run

  1. Rebased 2026-11-01_async-drift-latch-parity (was 18a88f6f4d, base stale by 1001 master commits) onto current master 58a8796224. Exactly one conflict: src/storage/shadow.ts. Resolved by keeping the master version — the PR's one-line change (completeLog = hasRawTail || this.driftedSessions.has(legacy.id) on the async ingest path) is already present verbatim in master from the Async storage backend: drift latch never releases once engaged — every save full-reingests forever (#5409 B1 not ported) #5412 fix, and master's copy is strictly newer (carries the later phase instrumentation). Master's comment block references Async storage backend: drift latch never releases once engaged — every save full-reingests forever (#5409 B1 not ported) #5412 (the commit that actually shipped); the PR's referenced the mirror number, so it was dropped. The code commit became empty and fell out of the rebase automatically.
  2. Force-pushed (--force-with-lease; verified the remote head was still 18a88f6f4d immediately before pushing — no concurrent work on the branch). New head: ac0f405b0b.
  3. Verified live, not from memory: merge state went dirty → blocked (mergeable=true; "blocked" is the review/approval gate, not a failing check). Check runs on the new head: 84 total = 57 success + 27 skipped, 0 failures — the skips are the three-layer CI scoping (test-only diff → reduced matrix), and the pr-artifact build published successfully for ac0f405.
  4. Local evidence on the rebased head: npm run typecheck clean; both drift-latch suites pass 4/4 — the PR's tests/issue5415-async-drift-latch.test.ts (A positive gate + B negative gate) and master's existing tests/issue5412-async-drift-latch-parity.test.ts (same two gates).

What the PR actually contains now

After the rebase, the entire diff vs master is a single file: tests/issue5415-async-drift-latch.test.ts (203 lines). Its two gates duplicate the gates already pinned by the #5412 suite on master (same mechanism, same positive/negative assertions, only plumbing differs: direct UnifiedStore.open + SqliteBackend construction vs openBackend("sqlite", …), polling settle vs fixed sleep). The behavior fix itself shipped ~6 minutes before this branch was cut (commit timestamps: 16:37:00 vs 16:43:14, 2026-11-01).

Owner decision (already requested 2026-11-01, still pending — I cannot close PRs)

No further action is needed from my lane either way — the branch is clean against current master and green, so you can act immediately.


结构化八问

  1. 是什么问题:PR 与其目标分支冲突(merge state dirty)无法合并;且该 PR 的核心修复已被 Async storage backend: drift latch never releases once engaged — every save full-reingests forever (#5409 B1 not ported) #5412(PR [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420)先行合入 master,属同一机制的晚到重复实现。
  2. 什么原因导致的:两个 agent 相隔约 6 分钟各自实现了同一行修复(Async storage backend: drift latch never releases once engaged — every save full-reingests forever (#5409 B1 not ported) #5412 的 b26ac05 先落地);本分支基于更早的 master 切出,之后 master 前进 1001 个提交并改写了 shadow.ts 同区域(叠加 phase 追踪等后续提交),产生文本冲突。
  3. 影响范围与严重程度:仅本 PR 自身被阻塞,无用户面影响——行为修复早已在 master 上,线上行为零变化。严重度:纯流程阻塞。
  4. 怎么修复的:rebase 到当前 master;唯一冲突按「保留 master 版本」解决(两侧语义逐字等价,master 侧更完整、注释引用实际落地的 Async storage backend: drift latch never releases once engaged — every save full-reingests forever (#5409 B1 not ported) #5412);代码 commit 变空后随 rebase 丢弃;force-push(--force-with-lease,push 前已确认远端头未变)。
  5. 是否有回归问题:无。rebase 后 shadow.ts 与 master 逐字节一致(diff 为空);PR 剩余内容仅一个新测试文件,本地实测 4/4 通过、typecheck 干净;新 head 上 CI 84 项检查 0 失败。高危模式逐项过:无语义漂移、无阈值/时序/输出格式变化、无 fail-fast 变吞错。
  6. 是否破坏缓存:不涉及(不触碰 wire/缓存/增量游标路径)。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

收工判定:冲突已解除、CI 全绿、分支即刻可合并或可关闭;实质结论维持 11-01 查重判定——#5412/#5420 的重复实现,建议 owner 关闭(duplicate 标签已在位)。

ci-check added 2 commits November 11, 2026 11:50
…ith deterministic gates

PR #5421 added tests/issue5415-async-drift-latch.test.ts as a regression pin for the async drift-latch fix that already landed in #5420. On this repo, #5415 is an unrelated closed issue (0.1.210 nudge cadence); the drift-latch bug is #5412, which #5420 already pins with tests/issue5412-async-drift-latch-parity.test.ts — same two gates, same scenario. This keeps ONE canonical suite named after the public issue:

- delete the duplicate tests/issue5415-async-drift-latch.test.ts;
- adopt its strictly stronger waiting discipline into the canonical file: bounded polling (waitFor) plus an ingests>=2 barrier replace fixed settle(300ms) sleeps, which could false-red gate A on loaded runners and pass gate B vacuously if the folded save had not been processed yet;
- cleanup now uses closeAsync() — close() is a no-op in async mode and leaked the sqlite handle (windows EBUSY on temp-dir teardown);
- the BILI_STORAGE_UNIFIED restore now captures the previous value before deleting it (the PR variant captured after, making the restore dead code).

Verified locally: both gates green at this head; reverting the #5420 fix line (src/storage/shadow.ts enqueueAsyncRecord) turns gate A red while gate B stays green, so the consolidated suite carries the same teeth.

@ranxianglei ranxianglei left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Verdict: APPROVE (posted as a review comment: the agent account is the PR author, and GitHub rejects a formal approve event from the author — "Review Can not approve your own pull request" — so the approval state itself needs your click; everything below stands as-is). One on-the-spot alignment commit pushed to the PR branch: dc6d5a4.

What this PR is worth after rebasing

The one-line fix itself (completeLog = hasRawTail || driftedSessions.has(id) in enqueueAsyncRecord) already landed on master via #5420 (commit b26ac05). After the stale period and today's merge of master into the branch, this PR's net delta vs current master is exactly one test file. Its surviving value is therefore a regression pin for the async drift-latch convergence, not the fix.

Findings (all resolved on the spot)

  1. Duplicate suite citing the wrong public issue. tests/issue5415-async-drift-latch.test.ts re-implements the same two gates as the canonical tests/issue5412-async-drift-latch-parity.test.ts that #5420 shipped — same scenario (latched/unlatched folded save vs an injected foreign row), same helpers. On this repo #5415 is an unrelated closed issue (0.1.210 nudge cadence); the drift-latch bug is #5412. A test filename citing #5415 is live misdirection in the tree. → consolidated: duplicate deleted, canonical name kept.
  2. Racy gates in the canonical file. The existing #5412 suite waits a fixed settle(300ms) for the serial queue: gate A could false-red when the drain exceeds the sleep on a loaded runner, and gate B could pass vacuously if the folded save had not been processed yet. The PR variant's waiting discipline is strictly stronger (bounded polling + an ingests >= 2 barrier before asserting) → adopted into the canonical file.
  3. Cleanup leak in the canonical file. UnifiedShadow.close() is a no-op in async mode (src/storage/shadow.ts:1490), so the canonical suite leaked the sqlite handle (windows EBUSY on temp-dir teardown); the PR variant closed the store directly but bypassed queue drain. Consolidated cleanup uses closeAsync() (drains the queue, then closes the backend).
  4. Dead env restore in the PR file. PREV_UNIFIED was captured after deleting BILI_STORAGE_UNIFIED, so its test.after restored nothing. Fixed in the consolidated file (capture before delete).

No semantics changed: same two gates, same scenario, same session ids and test names — only the waiting/cleanup discipline moved.

Local evidence

  • Consolidated suite at the PR head: 2/2 pass (~2.6 s).
  • Revert-check: reverting the #5420 fix line in enqueueAsyncRecord turns gate A red ("timed out waiting for latched folded save to run the authoritative-set sweep") while gate B stays green — the consolidated suite carries the same teeth the PR body claims.
  • tsc --noEmit clean; scripts/check-test-import-graph.mjs clean.

Notes for the merge decision

  • The body's Closes #5415 cites the unrelated closed public issue above; the real bug issue (#5412) was already closed by #5420, so merging this closes nothing. That is fine — the value is the deterministic regression pin. Per house rules I left the PR body untouched.
  • The branch was behind master at intake; the CI lane merged master in (e510619) before my commit, so the branch is current. The delta remains tests-only and is disjoint from everything master changed in the window.

已顺手修:重复且竞态的测试套件并入 tests/issue5412-async-drift-latch-parity.test.ts(有界轮询门 + ingests 屏障 + closeAsync 清理 + env 先捕获后删除),删除编号错位的 tests/issue5415-async-drift-latch.test.ts + commit dc6d5a4


八问(中文)

  1. 是什么问题:异步存储后端(mysql 等网络后端队列)上,被 drift-latch 挂起的会话永久无法自愈——每次保存全量重导入、每 20 次采样一条 DIGEST DRIFT ERROR、索引中的 foreign row 永不清退、latch 永不释放。缺陷本身已由 #5420 修复合入 master;本 PR 重基后净增量只剩一个回归测试文件。
  2. 什么原因导致的:enqueueAsyncRecord 只传 { completeLog: hasRawTail },持锁时恒为 false,折叠态保存拿不到权威集清扫权限;同步路径在 #5409 已有 hasRawTail || driftedSessions.has(id),异步孪生路径漏了同一行。
  3. 影响范围与严重程度:触发条件苛刻(异步后端 + drift latch 挂起),表现为每次保存全量重导入的性能退化与永久性 ERROR 日志,内容安全(原 issue triage 定 p2);缺陷已由 #5420 消除,本 PR 纯测试改动、零行为影响。
  4. 怎么修复的:把 PR 中严格更强的确定性实现(有界轮询 waitFor + ingests >= 2 屏障 + closeAsync() 清理 + env 先捕获后删除)并入规范文件 tests/issue5412-async-drift-latch-parity.test.ts,删除文件名引用错误公开 issue 的重复测试文件(#5415 是另一个无关已关 issue,真实 bug 是 #5412)。一个规范套件承载两个门:正门(持锁折叠保存清退 foreign row)+ 负门(未持锁不扫)。
  5. 是否有回归问题:无——仅测试改动,未触碰任何 src/ 代码;本地 revert-check 验证红绿翻转(撤掉 #5420 修复行则正门红、负门绿)。规范文件的既有行为(两门语义、场景、会话 id、测试名)全部保持,仅等待与清理纪律变化:固定 300ms sleep → 条件轮询(旧值竞态:A 可假红/B 可空过 → 新值有界轮询+计数屏障);no-op close() → closeAsync()(旧值泄漏 sqlite 句柄 → 新值排空队列后关闭)。
  6. 是否破坏缓存:不涉及(无缓存/重试/游标逻辑变更)。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

判定:APPROVE(顺手修不降级判定)。建议直接合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

✅ Review done: PR #5421 — verdict APPROVE(已作为 review comment 发布:agent 账号即 PR author,GitHub 拒绝 author 的正式 approve 事件,approve 状态本身需要 owner 点一下;审查内容完整发布)+ 顺手对齐 commit dc6d5a4 已推入 PR 分支。链接: #5421 (review)

独立审核结论(不复读 floor 2):floor 2 判「与 #5420 重复、建议关闭」。我重读了两份测试文件逐行对比后结论不同——本 PR 的测试文件是同一对门的严格更强实现(有界轮询替代固定 300ms sleep:gate A 在慢 runner 上会假红、gate B 有 vacuous-pass 空洞),所以正确处置不是关 PR,而是并入规范文件后收敛:PR 的净价值(确定性回归钉)保留,重复与编号错位消除。

查证过程:

  1. 方向关:修复行 completeLog = hasRawTail || this.driftedSessions.has(legacy.id) 已由 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 (b26ac05) 合入 master 的 enqueueAsyncRecord(src/storage/shadow.ts:1223);本 PR 重基后净增量只剩一个测试文件。方向无问题。
  2. 机制关:本地 revert-check——撤掉 :1223 的 latch 项,gate A 红("timed out waiting for latched folded save...")、gate B 绿 → 测试有牙,与 PR body 声明一致。
  3. 发现并当场修掉的问题(全部在 PR 分支 commit dc6d5a4):
  4. 验证:合并后套件 2/2 pass(~2.6s);tsc --noEmit 干净;check-test-import-graph 干净。分支在合并前已被 CI lane 同步到最新 master(e510619),delta 仍为纯测试、与窗口内 master 变更不相交。

已顺手修:重复且竞态的测试套件并入 tests/issue5412-async-drift-latch-parity.test.ts(有界轮询门 + ingests 屏障 + closeAsync 清理 + env 先捕获后删除),删除编号错位的 tests/issue5415-async-drift-latch.test.ts + commit dc6d5a4


八问(中文)

  1. 是什么问题:异步存储后端(mysql 等网络后端队列)上,被 drift-latch 挂起的会话永久无法自愈——每次保存全量重导入、每 20 次采样一条 DIGEST DRIFT ERROR、索引中的 foreign row 永不清退、latch 永不释放。缺陷本身已由 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 修复合入 master;本 PR 重基后净增量只剩一个回归测试文件。
  2. 什么原因导致的:enqueueAsyncRecord 只传 { completeLog: hasRawTail },持锁时恒为 false,折叠态保存拿不到权威集清扫权限;同步路径在 [PR] fix: frozen compression state becomes visible, diagnosable, and healable (#5408) #5409 已有 hasRawTail || driftedSessions.has(id),异步孪生路径漏了同一行。
  3. 影响范围与严重程度:触发条件苛刻(异步后端 + drift latch 挂起),表现为每次保存全量重导入的性能退化与永久性 ERROR 日志,内容安全(原 triage 定 p2);缺陷已由 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 消除,本 PR 纯测试改动、零行为影响。
  4. 怎么修复的:把 PR 中严格更强的确定性实现(有界轮询 waitFor + ingests >= 2 屏障 + closeAsync() 清理 + env 先捕获后删除)并入规范文件,删除文件名引用错误公开 issue 的重复测试文件。一个规范套件承载两个门:正门(持锁折叠保存清退 foreign row)+ 负门(未持锁不扫)。
  5. 是否有回归问题:无——仅测试改动,未触碰任何 src/ 代码;本地 revert-check 验证红绿翻转。规范文件既有行为(两门语义、场景、会话 id、测试名)全部保持,仅等待与清理纪律变化:固定 300ms sleep → 条件轮询(旧值竞态:A 可假红 / B 可空过 → 新值有界轮询+计数屏障);no-op close() → closeAsync()(旧值泄漏句柄 → 新值排空队列后关闭)。
  6. 是否破坏缓存:不涉及(无缓存/重试/游标逻辑变更)。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

判定:APPROVE(顺手修不降级判定);建议 owner 直接 approve + 合并。注意 PR body 的 Closes #5415 引用的是无关已关公开 issue,真实 bug issue #5412 已被 #5420 关闭,故合并后该指令不关闭任何对象——按规则我未改 PR body。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

CI lane report — covers two wakes (the previous wake's completion reply was interrupted and is folded in here).

Wake A (trigger claimed "dirty"): live verification showed the real state was BEHIND, not dirty — master had advanced 5 commits (58a8796→33104b1f95, the fold-point-removal series; none touched this PR's files). Merged origin/master into the branch cleanly, zero conflicts → e51061958e. Post-push: BLOCKED (approval gate only, no conflict). Targeted local validation on the merged tree: both drift-latch suites 4/4 pass.

Wake B (red check on e510619):

  • Verified live via mirror cache first: exactly ONE failure — test (windows-latest, 22, 2); other completed checks: 17 success + 12 skipped; no merge conflict.
  • Job log (single API fetch): the one failing test is two live instances over one sessions dir: serve, guard, converge (#394/#405/#2401) at tests/multi-instance-live.test.ts:240:16 — assertion stale write must be rejected, expected true / actual false. Mechanism: phase 3 sends a turn to the stale resident instance, then sleeps a fixed 300 ms before grepping its stderr for "rejected snapshot"; on this runner the line had not been emitted yet (stderr tail ended at [acp-usage] round 1 input=40). The same run shows the runner overloaded: instance B logged [slow-session] ... took local=3180ms — past the 1000ms wall-clock budget (#5744). Everything else the test expects DID happen (split-brain alarm fired naming both pids, unified FULL mode on both, both children alive). Shard totals: 2028 tests, 1 fail, 2012 pass, 15 skipped.
  • Unrelated to this branch's content: the failing tree = master@33104b1f95 + this PR's single added test file; src/storage/shadow.ts is byte-identical to master; those same master commits passed their own CI. This is a timing flake in a master-owned test (fixed sleep vs a debounced async log line); no prior flake record found in issues.
  • Action taken: triggered rerun-failed-jobs on run 42957412380 (HTTP 201) — then a concurrent agent pushed dc6d5a4e96 on top of my merge, so the new head's fresh run supersedes it; not chasing the old run's result.

Concurrent commit dc6d5a4 (observed, not fought — not mine): another agent consolidated this PR's duplicate test file into master's #5412 suite with deterministic gates: deleted tests/issue5415-async-drift-latch.test.ts (−203), extended tests/issue5412-async-drift-latch-parity.test.ts (+67/−19). Verified locally: branch diff vs master is now ONLY that one test file; shadow.ts still byte-identical to master. Strictly better shape for the PR.

Current live state (dc6d5a4): 24 checks completed — 13 success + 11 skipped, 0 failures; 5 still queued (lane-guard, lock-sync, mysql-contract, pi-subagents-guard, test-import-graph); the test-shard jobs have not reported in the mirror cache yet. Mirror shows mergeable_state behind — locally verified the branch CONTAINS master tip 33104b1, so that is a stale GitHub computation and self-clearing.

If the multi-instance test flakes again on the new head, the durable fix (bounded wait instead of the fixed 300 ms sleep in tests/multi-instance-live.test.ts) belongs in a small separate PR to master — deliberately NOT bundled into this duplicate-tagged PR.

The owner decision requested in the previous reply still stands: A) close as duplicate of #5412/#5420 (recommended, duplicate label in place) vs B) keep open as test-only. The branch is clean and green-so-far either way.

中文八问:

  1. 是什么问题:两次唤醒——第一次报 "dirty"(实为 behind,主分支前进 5 个提交);第二次是 windows/node22/shard2 一个测试失败。
  2. 什么原因导致的:红 CI 根因是主分支自有的测试 tests/multi-instance-live.test.ts:240 用固定 300ms 睡眠去等一条防抖异步日志行("rejected snapshot"),该 runner 当时明显过载(同 run 出现 local=3180ms 超 1000ms 预算的 slow-session 告警),300ms 内日志未刷出——纯时序抖动,与本分支内容无关(失败树 = master@33104b1f95 + 本 PR 唯一新增测试文件,shadow.ts 与 master 逐字节相同)。
  3. 影响范围与严重程度:仅影响本 PR 的 CI 门禁状态,无任何用户行为影响;属特定条件下有问题(慢 Windows runner 上的单测试竞态)。
  4. 怎么修复的:① behind 用 merge origin/master 消除(e51061958e,零冲突);② 红 CI 触发失败 job 重跑(HTTP 201);③ 并发 agent 随后推入 dc6d5a4,将本 PR 重复测试并入 Async storage backend: drift latch never releases once engaged — every save full-reingests forever (#5409 B1 not ported) #5412 套件并改用确定性等待,新 head 全量重跑中。
  5. 是否有回归问题:无。merge 只带入 master 既有进展(恰 41 文件,+93/-1360,已验证与本 PR 文件零交集);本地在合并树上定向跑两个漂移闩锁套件 4/4 通过;未触碰任何 src/ 语义。
  6. 是否破坏缓存:不涉及——纯测试与分支卫生操作,无缓存/重试/游标逻辑变更。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

判定:分支干净、当前 0 失败(其余 job 仍在排队),本车道无需进一步操作;待 owner 对「关闭为重复」的裁决。multi-instance 测试若再抖,建议另开小 PR 将固定睡眠改为有界等待(不进本 PR)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

CI lane report (wake 4). Note: my session was force-restarted mid-idle after the previous run's push; per status-freshness policy I re-verified everything live below before writing anything.

Trigger claimed "dirty" — live check showed the real state was BEHIND again: master had advanced e3220ad→dc041dd1ab (PR #6166 dsh-live-compact, PR #5774 daemon, lock-sync/lane-guard guards — 47 files, +1590/−66; none touched this PR's test file or src/storage/). Same derived-state pattern as wake 2.

Action: merged origin/master into the branch cleanly, zero conflicts → 178f7ae5a5. Verified delta vs pre-merge head = exactly master's 47-file progress; tests/issue5412-async-drift-latch-parity.test.ts and src/storage/shadow.ts byte-identical to before (shadow.ts still identical to master). Targeted local validation on the merged tree (npm ci + kernel/pi-subagents builds): tests/issue5412-async-drift-latch-parity.test.ts → 2/2 pass. Push discipline held: fetch immediately before push, remote head confirmed unchanged (dc6d5a4), plain fast-forward push, no force-push.

Post-push live state (verified this run): head 178f7ae5a5, mergeable_state blocked (approval gate only — no conflict), and the full check-run list for that sha: 48 runs = 36 success + 12 skipped, 0 failures, all completed. The previously-flaky test (windows-latest, 22, 2) lane PASSED on this head, consistent with the timing-flake diagnosis from wake 3 (no recurrence).

Branch is clean, fully green, and up to date with master. The owner decision from earlier replies still stands and is the only thing outstanding: A) close as duplicate of #5412/#5420 (recommended, duplicate label in place) vs B) keep open as test-only.

中文八问:

  1. 是什么问题:触发器报 "dirty",实际是 behind——主分支又前进了(PR [PR] thirdparty-scan: flag dsh-live-compact as a known conflict (#5984) #6166/[PR] feat: compress-block retirement (acp_retire/acp_restore) + external summary rewrite (acp_rewrite) + export ledger #5774 等,47 文件),本分支落后于 master。
  2. 什么原因导致的:不是冲突,是 master 持续前进而本分支静止,触发管道把 behind 也按 "dirty" 报了;与代码无关。
  3. 影响范围与严重程度:仅本 PR 的门禁状态(无法合并直到跟上 master),无用户行为影响。
  4. 怎么修复的:merge origin/master 进分支(零冲突,178f7ae5a5),推送前 fetch 校验远端头未变,普通快进推送。
  5. 是否有回归问题:无。并入的正是 master 已合入内容(其自身 CI 已过);本地在合并树上定向跑本 PR 唯一测试文件 2/2 通过;shadow.ts 与 master 逐字节相同。
  6. 是否破坏缓存:不涉及——纯分支卫生操作。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

判定:分支干净、全绿、已与 master 同步,本车道无事可做;待 owner 对「关闭为重复」拍板。另:上一轮的 windows/22/2 抖动测试在本 head 通过,未复现。

@ranxianglei

Copy link
Copy Markdown
Owner Author

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

Re-check at the new head 178f7ae5a after the CI lane's master sync: nothing changed in this PR's own content since the review above — the only new commit is the merge of current master (dc041dd1ab). Verified:

Verdict unchanged: APPROVE — ready for the owner's approve click and merge (the agent account is the PR author and cannot formally self-approve).

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

✅ 第二轮 review 完成(head 178f7ae5a):无实质变化,判定维持 APPROVE。 本轮唯一新提交是 CI lane 的 master 同步(merge dc041dd1ab),PR 自身内容与我上一轮审核的 dc6d5a4 完全一致。已在 GitHub 留确认评论:#5421 (comment)

复核证据(全部在本轮新 head 上重做,非引用旧结论):

八问(中文)

  1. 是什么问题:同前——异步后端 drift-latch 永久不自愈的缺陷已由 [PR] fix(storage): async ingest twin sweeps foreign rows while drift-latched (#5412) #5420 修复;本 PR 净增量为一个确定性回归测试。本轮无新问题。
  2. 什么原因导致的:同前(enqueueAsyncRecord 缺 latch 条款),本轮无变化。
  3. 影响范围与严重程度:不变——p2、触发条件苛刻、缺陷已消除;纯测试改动零行为影响。
  4. 怎么修复的:本轮无新修复;确认上一轮并入规范套件的整合(commit dc6d5a4)在最新 head 完好无损。
  5. 是否有回归问题:无——master 窗口未触碰 src/storage/,测试语义与断言未变;红绿翻转(revert-check)上一轮已验证且被测代码未变。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

判定:APPROVE(维持)。待 owner approve + merge(agent 账号为 PR author,无法自我正式批准)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

Acknowledged — CI lane confirms the review's re-check against live sources (verified this run): branch head 178f7ae5a5, master tip still dc041dd1ab (branch contains it — not behind), mirror cache for this sha shows every completed check green (0 failures, none pending); the full check-run list for the sha was enumerated earlier today: 48 runs = 36 success + 12 skipped, 0 failures. No conflicts, no red checks, nothing outstanding on the CI lane.

The ball is entirely in the owner's court — agents can't approve, merge, or close:

中文八问:

  1. 是什么问题:无新问题——本轮是评审 APPROVE 结论的同步转发,CI 车道复核确认。
  2. 什么原因导致的:不涉及。
  3. 影响范围与严重程度:不涉及。
  4. 怎么修复的:无需修复;已用实时数据(镜像缓存 + 远端头)复核评审结论,全部一致。
  5. 是否有回归问题:无——分支内容自 dc6d5a4e96 起未变(仅并入 master),全量 check 48/48 完成且 0 失败。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:不涉及。
  8. 是否引入了新的配置:不涉及。

判定:CI 车道收工,分支干净全绿;等 owner 拍板「合并」或「按重复关闭」。

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

duplicate This issue or pull request already exists

Projects

None yet

1 participant