Skip to content

[PR] fix: fork adoption no longer gives up permanently on 409 SNAPSHOT_UNAVAILABLE (#3011) - #3024

Open
ranxianglei wants to merge 11 commits into
masterfrom
2026-10-13_fork-adopt-retryable-snapshot
Open

ranxianglei wants to merge 11 commits into
masterfrom
2026-10-13_fork-adopt-retryable-snapshot

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

What & why

Closes #3011

A DSH desktop clone whose parent had just been natively compacted died on its first turn (context_length_exceeded, 1063420 > 1048576) because bili permanently abandoned fork inheritance after a single 409. The client classified degraded outcomes by a reason-string regex (/^(snapshot|fork) (error|http 5\d\d)/ in src/agent/fork-adopt.ts); the incident's reason snapshot http 409 SNAPSHOT_UNAVAILABLE (raw snapshot unavailable; ...) matched neither arm, so transient === false → the child went into the permanent-done set after ONE attempt (the maxAttempts = 3 retry budget was unreachable). The server-side 409 itself was a residency gap: the parent's raw snapshot was not persisted (persistence requires a prior fork receipt / publicSnapshotRetained) and had been lost to eviction/restart.

One mechanism family (fork inheritance permanently abandoned), fixed at both ends:

Client — classify by field, not by string. Every degraded ForkAdoptionResult now carries an explicit retryable verdict: snapshot GET retries on network errors, HTTP ≥ 500, and 409 with parsed code SNAPSHOT_UNAVAILABLE (a residency gap that self-heals on the parent's next request); 404 PARENT_NOT_FOUND and other 4xx stay terminal; fork POST classification is unchanged (network/≥500 retryable). Give-up now logs an explicit permanently disabled line, distinct from the transient will retry on a later request (attempt N/maxAttempts) line (issue suggestion 3).

Server — give the 409 an available path. New forkSourceMessages() in src/plugin.ts selects the raw source view for both GET /__bili/plugin/snapshot and fork materialization: the retained copy (pluginSnapshot) stays primary; when it is missing, the recent raw view session.lastMessages is served instead — it is persisted unconditionally and re-stamped verbatim by every parent request, so it survives LRU eviction and host restarts. A head-divergent tail wins over a frozen pre-compaction retained copy (the zero-overlap guard case where the snapshot refuses to update after a full-cover native compaction), so served identities survive rebases. Folded tails never serve; the retention-cap refusal (#2433) stays first. resetSessionCompression now clears the stale publicSnapshot* metadata so a rebased parent cannot fail the list-level stored-refs check against the old view.

Together these rescue the incident end-to-end: at the child's first turn, adoption runs before the model request is forwarded; the parent now serves post-compaction identities from its recent raw view → prefix match succeeds → POST fork completes (child not yet registered) → the first forwarded request rides inherited folds instead of re-sending the full uncompacted history.

Behavior changes (old → new)

Deliberate, per issue suggestions 1–2:

  1. Client retry policy: snapshot 409 SNAPSHOT_UNAVAILABLE was terminal after 1 attempt (regex miss) → now retried up to maxAttempts = 3 within the process, then an explicit permanent-give-up log line. Side effect: 409s that are NOT residency gaps (multimodal history, genuinely inconsistent ref mapping) are also retried by the client — the wire code does not distinguish them. Cost is bounded (≤ 3 cheap GETs per child); worst case is one extra round of identical 409s before the same permanent stop.
  2. Snapshot endpoint availability: GET /__bili/plugin/snapshot may now answer 200 from the recent raw view where it previously answered 409 (residency gaps, frozen-stale pre-compaction copies). Hard refusals unchanged: retention cap (feat(#2394): raise fork-snapshot retention default from 16 MiB to 100 MiB #2433), folded tail, missing refs/CCR originals. Fork materialization follows the same selection, so a zero-branchpoint fork child keeps serving its legitimate empty snapshot (childRevision computation relies on this).
  3. New log lines: fork adoption for <child> degraded (<reason>) — transient, will retry on a later request (attempt N/maxAttempts)... and ...— permanently disabled, no further retries in this process... replace/augment the single old degraded line.

No change to: wire protocol shape, message ids/refs, persistence format, kernel, nudge cadence, compression thresholds, or any default value.

Config surface

None added. No new config fields, env vars, or CLI flags — the fix reuses the existing maxAttempts internal budget and existing metadata/persistence paths.

Tests

  • tests/plugin-fork.test.ts: +4 — snapshot serves the recent raw view when no retained copy exists (and a full-prefix fork off it succeeds); stays 409 when neither source exists; folded tail never serves; fresh head preferred over a divergent frozen retained copy. All pre-existing pinned behaviors green (plain-panel 409, [Bug][plugin] protectedTools 的 BLOCKED 映射导致纯文本 snapshot 返回 409 #2620 mapping rejection, cap tests, concurrent-fork publish-once incl. zero-branchpoint child, cross-process fork).
  • tests/pi-omp-fork-adopt.test.ts: +4 — structured verdict classification (pins the incident string verbatim, terminal vs retryable per code/status); adopter retries 409 until the parent recovers (exactly 1 fork POST, transient log lines, no permanent disable); closes permanently after the cap (exactly 3 attempts over 4 calls, silent afterwards).
  • tests/dsh-fork-adopt.test.ts: existing expectations updated to the new retryable field (multimodal/mapping 409s intentionally true — documented tradeoff above).

Targeted local runs green: plugin-fork + pi-omp-fork-adopt + dsh-fork-adopt (98/98) and the wider fork/compaction/fork-adoption sweep (144/144); typecheck clean. Full suite left to CI.

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-13_fork-adopt-retryable-snapshot (a3cf4a4)

Latest build — install this exact version

npm install -g billion-context@0.0.8424-pr.3024.0b86228

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
a3cf4a4 billion-context@0.0.8424-pr.3024.0b86228 build
4b2418d billion-context@0.0.6204-pr.3024.5ac5bdd build
81f1553 billion-context@0.0.6116-pr.3024.8d97d48 build
2cf3fdf billion-context@0.0.6024-pr.3024.156e9e4 build
d72d2f2 billion-context@0.0.5863-pr.3024.e1b859b build
99963dd billion-context@0.0.5796-pr.3024.a8ae9ff build
9123749 billion-context@0.0.5644-pr.3024.d98ef16 build
575e860 billion-context@0.0.5587-pr.3024.c5896bd build
77876e6 billion-context@0.0.5582-pr.3024.b8a63eb build

Download artifact

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

[bot] 🏷 收到,开始审查 PR #3024(fix #3011 fork adoption 永久放弃问题)。按 [PR] 流程核对代码与 CI,不重做。重点核查:客户端 retryable 分类边界、服务端 forkSourceMessages 回退路径的 fail-closed 不变量、以及分支落后 master 9 个提交后与 #2960⑤(unified store tail 持久化)/ #3010 CCR 退役的语义交互。结论稍后按八问体例给出。

@ranxianglei
ranxianglei force-pushed the 2026-10-13_fork-adopt-retryable-snapshot branch from 23c40fc to 80ee312 Compare October 13, 2026 11:07
ranxianglei pushed a commit that referenced this pull request Oct 13, 2026
…s gate)

Review fix for #3011/#3024: forkSourceMessages is only referenced inside
src/plugin.ts (forkSnapshot + handlePluginFork); no test or module imports
it, so the leading export tripped scripts/check-unused-exports.mjs
(INTERNAL_ONLY). Drop the keyword per the gate's own remediation — no
behavior change.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

PR #3024 审查结论(fix #3011:fork adoption 对 409 SNAPSHOT_UNAVAILABLE 永久放弃)

按八问逐项:

  1. 是什么问题:DSH 克隆大会话时,fork adoption 要取父会话的原始快照。父会话保留快照不驻留(LRU 逐出/宿主重启)或刚被原生压缩冻结时,服务端返回 409 SNAPSHOT_UNAVAILABLE;旧客户端用字符串正则分类失败原因,漏掉了这个服务端自己文档标注可重试的 409 → 判为终态、一次尝试就永久放弃(maxAttempts=3 永远到不了)→ 子会话从第一回合起失去继承的压缩状态,全量历史直接打上游,触发 context_length_exceeded。
  2. 什么原因导致的:两层根因。客户端层:retryable 判定靠对 reason 字符串的正则白名单(/^(snapshot|fork) (error|http 5\d\d)/),白名单外的 reason(含该 409)一律终态——判定机制本身错了,不是漏了一个 pattern。服务端层:forkSnapshot 只能服务保留副本 pluginSnapshot(惰性持久化,仅 fork receipt/保留标志落盘后才有磁盘副本),不驻留即无条件 409;且原生压缩后零重叠守卫把 pluginSnapshot 冻结在压缩前、rebase 重发 ref,服务陈旧副本也会永久 fail-closed。
  3. 影响范围与严重程度:所有会克隆/fork 会话的 plugin-mode 宿主(dsh 桌面、pi/omp lane)。触发条件:克隆时刻父快照不驻留,或父刚经历原生压缩。严重度:特定条件下会话不可用——子会话首回合即上下文溢出(事故实测 1063420 > 1048576),且旧代码静默永久放弃、无任何日志。
  4. 怎么修复的:两端各修各自的根因。客户端:retryable 改为结构化字段判定——409 SNAPSHOT_UNAVAILABLE/5xx/网络错误可重试,CHILD_CONFLICT/PARENT_NOT_FOUND/no prefix match 等确定性判定保持终态;重试受 maxAttempts=3 约束,耗尽时打显式 "permanently disabled" 日志(覆盖报告者建议 1、3)。服务端:新增源视图选择 forkSourceMessages——优先保留副本;缺失时用 session.lastMessages(每个 prepare* 写入的原始视图);近期视图与保留副本头部分歧(原生压缩后的典型形态)时近期视图胜出;已折叠视图永不作源。fail-closed 不变量全部保留:retention cap 硬拒、逐消息 ref 双向映射、CCR 占位符校验、thinking/多模态拒绝(覆盖建议 2)。
  5. 是否有回归问题:逐项审过既有行为——wire 协议形状不变(GET snapshot/POST fork 同字段同 code);消息 id/ref 体系未动;持久化格式未动(本 PR 不碰 persist.ts);kernel/pi-subagents/配置面/env/默认值全未触碰;retention cap 语义不变(tail 可用时仍硬拒,feat(#2394): raise fork-snapshot retention default from 16 MiB to 100 MiB #2433 可执行性保住);零 branchpoint 子会话不变量保住(空保留副本 [] 仍优先于 tail);v1 revision 过渡回退路径行为不变。与 master 并行变更(Identity pipeline: key sessions by (agent, conversation id) in the unified store — decouple fold ledgers from protocol/host origin (#2938 / #2847 / #2671 defect-1) #2960⑤ unified store tail、CCR originals serve from the unified index (#2960 ③) #3010 CCR 退役、fork↔replicas convergence: pinned fork_base checkpoints (#2960 ②) #3014 fork-replica)无文件交集,语义交互已核查:默认 shadow 存储模式下重启后 envelope 恢复的是折叠 tail(folded=true,被门控拒绝),restart 场景靠客户端重试+父会话下次请求自愈收敛;full 模式 unified 索引恢复原始 tail,直接收敛。两种情况都不劣于旧行为。无回归。有意行为变更见下条披露。
  6. 是否破坏缓存:不涉及。pluginRevisionCache 仍按 revisionEpoch 键控、语义不变;差异仅是过去抛错的会话现在也能算出 revision(status 端点 revision 字段从缺失变为出现,纯增量)。
  7. 是否改了设计方向:不涉及。仍在 fork protocol v2 框架内:服务端加一个内部源视图选择函数,客户端 degraded 结果加一个结构化字段,无架构/边界/数据流转向。
  8. 是否引入新配置:不涉及。无新 env/config/默认值。

有意行为变更披露(旧 → 新):

  • 客户端:409 SNAPSHOT_UNAVAILABLE 从「一次失败永久放弃」→「跨后续请求最多重试 3 次」;多模态类 409(同一 code)也会被重试至多 3 次后才放弃——测试注释明确承认这是有界权衡(≤3 次廉价 GET,换来不再复活原 bug)。
  • 服务端:GET /__bili/plugin/snapshot 在原先 409 的场景(无保留副本但有近期原始视图;压缩后头部分歧)现在返回 200;POST fork 的子基线与 proxy-tool expectedRevision 检查同步从「residency gap 恒 409」放宽为「按可用视图服务」。
  • 错误文案变化:raw snapshot unavailable; send a fresh plugin model request → raw snapshot unavailable (no retained raw copy and no recent raw view); send a fresh plugin model request(客户端已不再依赖匹配该字符串)。
  • 客户端新增两条显式日志(transient 重试计数 / permanently disabled)。

验证过程:rebase 到当前 master(554c9394d)无冲突;本地 typecheck clean;定向套件 tests/{plugin-fork,pi-omp-fork-adopt,dsh-fork-adopt}.test.ts 98/98 过。审查中发现 forkSourceMessages 的导出触发 unused-exports 门禁(INTERNAL_ONLY,文件外零引用)——已顺手修复(去掉 export 关键字,独立标注 commit 94100f6c2,零行为变化,门禁本地复跑 clean)。测试有效性:断言有牙——钉住事故 reason 串、重试次数精确计数(2 次 transient + 第 3 次恢复恰好 1 次 fork POST)、latch 后零后续动作、folded-tail 拒绝、head-divergence 优先、stale 簿记不否决 tail 路径。残留机制(child 首个降级请求先于 adoption 落盘导致 CHILD_CONFLICT 永久 latch)已在 #3025 立项,不在本 PR 范围。

结论:方向正确、双端各修其根因、fail-closed 不变量完整、diff 干净(7 文件 +242/-37,每行都与目的相关)。分支已 rebase 并补上门禁修复,head 94100f6c2 的全量 CI 正在跑,绿了再确认一句。可合(待 CI 全绿最终确认)。

ranxianglei pushed a commit that referenced this pull request Oct 13, 2026
…s gate)

Review fix for #3011/#3024: forkSourceMessages is only referenced inside
src/plugin.ts (forkSnapshot + handlePluginFork); no test or module imports
it, so the leading export tripped scripts/check-unused-exports.mjs
(INTERNAL_ONLY). Drop the keyword per the gate's own remediation — no
behavior change.
@ranxianglei
ranxianglei force-pushed the 2026-10-13_fork-adopt-retryable-snapshot branch from 94100f6 to 9d44414 Compare October 13, 2026 11:42
ranxianglei pushed a commit that referenced this pull request Oct 13, 2026
…s gate)

Review fix for #3011/#3024: forkSourceMessages is only referenced inside
src/plugin.ts (forkSnapshot + handlePluginFork); no test or module imports
it, so the leading export tripped scripts/check-unused-exports.mjs
(INTERNAL_ONLY). Drop the keyword per the gate's own remediation — no
behavior change.
@ranxianglei
ranxianglei force-pushed the 2026-10-13_fork-adopt-retryable-snapshot branch from 9d44414 to 9e6cac4 Compare October 13, 2026 12:31
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

审查更新 — 分支已更新到最新 master,此前唯一的红灯已在上游解决

分支已 rebase 到最新 master:2026-10-13_fork-adopt-retryable-snapshot @ 9e6cac4df(只含本 PR 的两个 commit,无其他内容混入)。

关键变化:

  1. storage-render golden 红灯已在上游修复:test: regen storage-render goldens for the #3023 cache-ledger client-insert attribution #3035 已合入 master。此前四个 golden 快照里的 metadata 摘要与当前各执行环境(CI、本地沙箱)的实际输出不一致——是随时间漂移的测试数据陈旧问题,不是代码缺陷。test: regen storage-render goldens for the #3023 cache-ledger client-insert attribution #3035 重新生成快照后,两边输出一致:本地 golden 套件由 4/5 失败变为 5/5 通过,且 test: regen storage-render goldens for the #3023 cache-ledger client-insert attribution #3035 自身的 CI 20 项全绿。
  2. 新 head 全量定向验证:fork 相关三个目标套件 98/98、typecheck 干净、unused-exports gate 干净。
  3. 结论不变:此前的红灯腿全部是继承性破损,本 PR 贡献为零;rebase 后 PR diff 恰好收敛为修复本身。

CI 正在新 head(9e6cac4df)上跑,结果出来我确认一遍。

八问速览(细节见上一条结构化结论):

  1. 是什么问题:会话分叉(fork)时若父会话原始快照不在驻留区,继承机制一次 409 后就永久放弃,子会话第一回合直接因上下文超限而亡。
  2. 什么原因导致的:客户端用字符串正则判断错误是否可重试,漏掉了 409 SNAPSHOT_UNAVAILABLE;服务端在保留快照缺失时也没有可用的替代来源。
  3. 影响范围与严重程度:DSH 桌面克隆场景;特定条件下致命(父会话刚做过原生压缩 + 快照被逐出或进程重启)。
  4. 怎么修复的:客户端改用结构化 retryable 字段分类(瞬态错误最多重试 3 次,放弃时打显式日志);服务端保留快照缺失时改用最新原始视图(近期 tail)作为来源,fail-closed 语义不变。
  5. 是否有回归问题:未发现;golden 红灯是 master 既有问题,已由 test: regen storage-render goldens for the #3023 cache-ledger client-insert attribution #3035 修复,与本 PR 无关。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:未改(仍单写者、fail-closed,kernel 契约不动)。
  8. 是否引入新配置:无。

判定:可合。等新 head 的 CI 结果作最终确认。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

CI 最终确认:新 head 9e6cac4df 34 项检查全绿。

过程中唯一一次瞬时红灯说明:Windows codex overlay e2e 道在本次运行失败一次——mcp list 步骤里 codex CLI 在超时窗口内没有给出预期输出。与本 PR 无关的证据:同一道在本分支此前三个 head(11:07 / 11:16 / 11:42)和 master 上都是绿的,且该道全程无 fork 流量。只重跑了该单个 job,2 分钟内转绿,确认为环境抖动。

补充:分支推送后 master 又合入了一个无关修复(#3019,nudge-decide × self-heal 死锁),PR 现显示 behind 状态;与本 PR 零文件重叠,不影响合并。

最终判定:可合。分支 2026-10-13_fork-adopt-retryable-snapshot @ 9e6cac4df,diff 恰好就是两个修复 commit;CI 34/34 绿;本地定向测试 98/98、golden 套件 5/5。等你合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

更正上一条首行的笔误:模型标识应为 vllm-qwen(误写为 "vllm-qeen")。其余内容不变。

ranxianglei pushed a commit that referenced this pull request Oct 14, 2026
…s gate)

Review fix for #3011/#3024: forkSourceMessages is only referenced inside
src/plugin.ts (forkSnapshot + handlePluginFork); no test or module imports
it, so the leading export tripped scripts/check-unused-exports.mjs
(INTERNAL_ONLY). Drop the keyword per the gate's own remediation — no
behavior change.
@ranxianglei
ranxianglei force-pushed the 2026-10-13_fork-adopt-retryable-snapshot branch from 9e6cac4 to e4e912d Compare October 14, 2026 10:50
ework-agent added 2 commits October 25, 2026 03:51
…VAILABLE (#3011)

Client (src/agent/fork-adopt.ts): classify degraded outcomes by structured
verdict instead of a reason-string regex. The regex only matched 'error' /
'http 5xx', so the incident's 'snapshot http 409 SNAPSHOT_UNAVAILABLE' was
treated as terminal after ONE attempt and the child's inheritance was
permanently abandoned in-process. Each result now carries an explicit
retryable flag: snapshot GET retries on network errors, HTTP >=500, and
409 code SNAPSHOT_UNAVAILABLE (a residency gap that self-heals on the
parent's next request); 404 PARENT_NOT_FOUND and other 4xx stay terminal.
Fork POST classification unchanged (network/5xx retryable). Give-up now
logs an explicit 'permanently disabled' line distinct from the transient
'will retry' line.

Server (src/plugin.ts): new forkSourceMessages() selects the raw source
view. The retained copy (pluginSnapshot) stays primary; when it is missing
(the residency gap: LRU eviction or host restart losing an unpersisted
copy) the recent raw view session.lastMessages is served instead — it is
persisted unconditionally and re-stamped by every parent request. A
head-divergent tail wins over a frozen pre-compaction retained copy
(zero-overlap guard case), so the served identities survive native
compaction rebases. Folded tails never serve. The retention-cap refusal
(#2433) stays first. Fork materialization uses the same selection, so a
zero-branchpoint child keeps its legitimate empty snapshot.

Server (src/session.ts): resetSessionCompression clears the stale
publicSnapshot* metadata so a rebased parent cannot fail the list-level
stored-refs check against the old view.
…s gate)

Review fix for #3011/#3024: forkSourceMessages is only referenced inside
src/plugin.ts (forkSnapshot + handlePluginFork); no test or module imports
it, so the leading export tripped scripts/check-unused-exports.mjs
(INTERNAL_ONLY). Drop the keyword per the gate's own remediation — no
behavior change.
…-view fallback

The master-side test pinned 409 before the parent's next model request
after restart. With #3011's forkSourceMessages fallback, a restore that
carries a verifiable unfolded raw tail (unified-store restore) is served
immediately (200); folded-only restores (legacy/shadow envelopes) still
409. Both pre-states are valid; the self-heal assertion below remains
the pinned contract.
@ranxianglei
ranxianglei force-pushed the 2026-10-13_fork-adopt-retryable-snapshot branch from e4e912d to 77876e6 Compare October 24, 2026 20:23
@ranxianglei ranxianglei changed the title fix: fork adoption no longer gives up permanently on 409 SNAPSHOT_UNAVAILABLE (#3011) [PR] fix: fork adoption no longer gives up permanently on 409 SNAPSHOT_UNAVAILABLE (#3011) Oct 24, 2026
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

CI 修复完成:unused-exports 已转绿(新 head 575e86036)

这条红是从 master 继承来的,不是本 PR 引入的:

修复内容(commit 575e86036,共 1 行):src/agent/client-build-note.ts:32 的 export type ClientBuildCheck → type ClientBuildCheck。本地门禁 ✓ unused-export gate: clean (6 waived);新 head CI 上 unused-exports ✅,其余静态门禁/guards/build 全绿。

八问

  1. 是什么问题:unused-exports 门禁判 ClientBuildCheck 为导出却无人引用的符号,检查矩阵红。
  2. 什么原因导致的:[PR] dsh lane: note in-session when running an unverified @deepseek-ai/dsh client build (soft, exact-match) #4545 train 引入该符号时带了 export,但全仓只有它自己这个文件在用;de-export 清扫漏掉它,master 自身常红,每个 rebase 到 tip 的 PR 都继承。
  3. 影响范围与严重程度:仅 CI 信号面(检查矩阵失去信号),用户侧零影响——纯类型在编译期擦除,运行时行为零变化。
  4. 怎么修复的:去掉 export 关键字(门禁 INTERNAL_ONLY 处置:保留声明、去掉导出),独立标注 commit,与 [PR] fix(ci): clear the two master-red gates in one branch — unused-exports (#4602) + the #3890 LIVE_FILES tripwire (#4604) #4606 提交 1 同法同文件同行。
  5. 是否有回归问题:逐项审过——base 树与 PR head 两棵树上全仓 grep 均确认该符号零外部引用(外部 importer 只取 DSH_BUILD_CHECK/emitNewerClientBuildNote/walkUpNodeModuleVersion/maxTestedVersion/newerClientBuildMessage);去 export 不改任何运行时字节、dts 面或导入路径;无语义漂移、无阈值/时序/输出格式变化。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:没有。
  8. 是否引入了新的配置:没有。

剩余红的现状(均为继承项,不在本 PR 范围):

判定:本车道点名的 unused-exports 已修复并验证绿;其余红为 #4599 总控下的继承红,#4606 合入后 rebase 到 master 重触发即可清。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

判定(attempt 2/2):这 11 个 test 分片红是 master 继承性失败,不在本分支修复——停在此处,等 #4606 合入后 rebase。

证据

为何不在本分支顺手修(不是修不了,是不该修)

  1. 门禁原文要求登记前先做 tests/claude-native.test.ts linux live-E2E subtests fail/hang in shared multi-agent sandboxes #1248 并发假设评审——[PR] fix(ci): clear the two master-red gates in one branch — unused-exports (#4602) + the #3890 LIVE_FILES tripwire (#4604) #4606 提交 2 已集中做过并修好;本分支重复登记 = 违反「一个根因一个 PR」查重纪律,且产生一个 rebase 后必被丢弃的冗余 commit。
  2. 就算去掉 tripwire,分片会真正跑测试,随即命中 CI Control Center: Centralized CI Failure Handling & Status Sync (Comment all CI issues here; do not open new issues) | CI 总控: CI 失败集中处理与状态同步(所有 CI 问题在此评论, 勿开新 issue) #4599 显形的 ~35 用例 born-red 集群(kernel/storage/快照渲染敏感面,每项需单独 triage「期望落后于有意变更」还是「真回归」)——哨兵车道明确不自决,auto-fix lane 更不该碰。也就是说单修 tripwire 也绿不了这个 PR。
  3. CI 协调政策:master 红 = 继承性失败,等 master 修复后 rebase,最多在 CI Control Center: Centralized CI Failure Handling & Status Sync (Comment all CI issues here; do not open new issues) | CI 总控: CI 失败集中处理与状态同步(所有 CI 问题在此评论, 勿开新 issue) #4599 留一句(上一轮已留)。

转绿路径:#4606 合并 → 本 PR rebase 到 master 重触发(rebase 时与本 PR commit 575e86036 重复的 ClientBuildCheck 去导出小修丢弃即可);born-red 集群由 #4599 总控后续批次处理,不属于本 PR 范围。

八问

  1. 是什么问题:11 个 test 分片在 pretest 自检阶段整体退出,检查矩阵红。
  2. 什么原因导致的:master 自身 born-red——新增的起子进程测试文件未登记进 LIVE_FILES,tripwire「未登记即 fail」杀掉所有分片;本 PR 纯继承(base 即 master tip,diff 无关)。
  3. 影响范围与严重程度:仅 CI 信号面,用户侧零影响;但导致本 PR 的真实测试结果不可见(分片没跑任何测试)。
  4. 怎么处置的:本车道不修——修法已在途([PR] fix(ci): clear the two master-red gates in one branch — unused-exports (#4602) + the #3890 LIVE_FILES tripwire (#4604) #4606 提交 2,含 tests/claude-native.test.ts linux live-E2E subtests fail/hang in shared multi-agent sandboxes #1248 评审),重复修既违规又绿不了(见上);判定停手。
  5. 是否有回归问题:不涉及本次改动;本 head 相对旧 head 的唯一 diff 仍是那 1 行 type-only 去 export,零运行时变化。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:没有。
  8. 是否引入了新的配置:没有。

结论:本 PR 自身改动面无 CI 问题;剩余红全部为 #4599 跟踪的 master 继承项,等 #4606 合并后 rebase 即可,无需再触发本车道。

@ranxianglei

Copy link
Copy Markdown
Owner Author

ci失败 冲突

…flict fix)

Conflict resolved by union of intent on the 409 SNAPSHOT_UNAVAILABLE path:
- #3011 raw-view picker (retained copy -> recent raw tail, head-divergence rule)
  gains master's verified storage reconstruction as the last rung;
- master's recon diagnostics (gate-named [reconstruction: ...] suffix,
  waitForReconstructionReplicas) kept verbatim;
- #2433 retention cap stays a hard refusal even when a fresh view exists;
- #4266 signed-thinking acceptance adopted (thinkingTokens rejection dropped);
- fork handler serves child baseline from the SAME picked source view
  (identity-derived fromTail keeps CCR bookkeeping fail-closed);
- test hunk takes master's strict 200 assertion (reconstruction makes the
  cold-restore scenario deterministically servable under unified-full).
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

冲突已解决并验证通过——本轮没有 push(哨兵 #4599 已先行合入语义等价的解决,a3cf4a4be),我做了完整独立验证。

1. 是什么问题:PR 分支与 master 冲突(dirty),fork/snapshot 端点的同一组函数被两边重写。

2. 什么原因导致的:PR(#3011)给 forkSnapshot 加了「retained copy → lastMessages 近期原始视图」的降级链;master 同期(#5140/#5188)在同一函数里加了 unified-storage 重建路径(reconstructRawTailForFork + 门级诊断)。两边改同一段代码 → 3 处文本冲突,另有两处语义交叉(cap 拒绝语义、view 对象 vs 数组)。

3. 影响范围与严重程度:仅插件车道 fork/snapshot 端点(409 SNAPSHOT_UNAVAILABLE 路径)。冲突未解时 PR 无法合并,阻塞本修复上线;未发布,不影响现网用户。

4. 怎么修的:merge origin/master(d640d0d)进 PR 分支,union-of-intent 解决三处冲突:

5. 验证证据(本地定向,全量交给 CI):

  • 纯 master 基线:tests/plugin-fork.test.ts 56/56 绿;
  • 我自己的解决版首轮 4 红,根因是 master 自动合并行把整个 view 对象赋给了 pluginSnapshot(应为 .messages)——修掉后 60/60 绿,dsh-fork-adopt + pi-omp-fork-adopt 全绿,typecheck 干净;
  • 对已推送的 a3cf4a4 复跑三个定向套件:81/81 绿(他的对应行写法不同但正确,无该缺陷);
  • 镜像缓存:merge state 已脱离 dirty,矩阵运行中(0 failed / 12 pending,static-gates/mysql-contract/gate/test-import-graph 已 success)。

6. 回归审查:逐项过既有行为——D-B cap 字节级错误消息 ✓、#5188 [reconstruction: <gate>] 诊断后缀 ✓、#5140 cold-restore 立即 200 ✓、cap-lift 经 resend 重保留 ✓、PR 新增 4 个 #3011 测试 ✓,全部保留且通过。一处语义选择需知悉:capped 会话在哨兵版中始终拒绝 fork(直到下次模型请求以 under-cap 视图重新保留才解锁)——这是 PR #2433 原意优先于 master 的重建豁免,不破坏任何钉死测试,但与 master 单独存在时的行为有差异(capped+可重建 under-cap 的场景从「可服务」变「拒绝」)。

7. 是否改了设计方向:不涉及。

8. 是否引入新配置:不涉及。

判定:冲突侧收工,等 CI 矩阵跑完;若转红由本车道 attempt 2/3 继续接。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

冲突已解决、CI 全绿,可以合并了。

做了什么:把当前 master(d640d0d)merge 进分支(不 rebase——分支上有平台自动合并的 ci-fixes 提交,merge 是追加式、无需强推),解决 3 处冲突后推送 a3cf4a4。之前两轮 CI 红(unused-exports、LIVE_FILES tripwire 等继承性失败)随这次 merge 一并消失——那些修复都已在 master 上落地。

结构化八问:

  1. 是什么问题:分支和 master 在「fork 快照不可用时返回 409」这条路径上撞车了——本 PR([Bug] Fork of DSH branch clone: inheritance permanently abandoned by 409 SNAPSHOT_UNAVAILABLE — zero-fold clone triggers context_length_exceeded 400 on first turn | [Bug] DSH 分支克隆的 fork 继承被 409 SNAPSHOT_UNAVAILABLE 永久放弃:克隆零折叠,首轮即 context_length_exceeded … #3011)用「内存里的最近原始视图」兜底,master 侧的 [Bug][fork] Cold restore cannot use an intact unified raw tail for a non-retained parent (#4266 item 4) #5140/[PR] fix(#5140): name the failed raw-tail reconstruction gate instead of failing closed silently #5188 用「统一存储重建」兜底,两套机制改的是同一个函数,产生 3 处文本冲突。
  2. 什么原因导致的:两个独立工作针对同一失败域(409 SNAPSHOT_UNAVAILABLE 永久放弃)各自加了不同的回退机制,先后落在同一代码位置;不是任何一方写错,是演进方向需要合并。
  3. 影响范围与严重程度:只影响本 PR 的合并进度(冲突不解无法合并,[Bug] Fork of DSH branch clone: inheritance permanently abandoned by 409 SNAPSHOT_UNAVAILABLE — zero-fold clone triggers context_length_exceeded 400 on first turn | [Bug] DSH 分支克隆的 fork 继承被 409 SNAPSHOT_UNAVAILABLE 永久放弃:克隆零折叠,首轮即 context_length_exceeded … #3011 的修复继续搁浅),无线上用户影响。严重度:阻塞发版,非可用性缺陷。
  4. 怎么修复的:按「意图并集」解冲突,不是二选一——最终是一条三级级联:保留副本 → 最近原始尾巴([Bug] Fork of DSH branch clone: inheritance permanently abandoned by 409 SNAPSHOT_UNAVAILABLE — zero-fold clone triggers context_length_exceeded 400 on first turn | [Bug] DSH 分支克隆的 fork 继承被 409 SNAPSHOT_UNAVAILABLE 永久放弃:克隆零折叠,首轮即 context_length_exceeded … #3011 的新鲜度规则原样保留)→ 验证过的存储重建([Bug][fork] Cold restore cannot use an intact unified raw tail for a non-retained parent (#4266 item 4) #5140 原样保留,含 gate 诊断后缀 [reconstruction: <gate>] 和 sidecar 自愈等待)。fork 的子会话基线必须和快照来自同一个源视图(同一选择器一次选出,杜绝二次查找漂移)。
  5. 是否有回归问题:逐项审过既有行为——① 保留上限(feat(#2394): raise fork-snapshot retention default from 16 MiB to 100 MiB #2433)仍是硬拒绝:即使有新鲜视图可用也不绕过(master 的重构在该边界情形下可能放行重建结果,这里保留了 PR 侧更严格的策略,下次模型请求后自愈,属有意的 fail-closed);② 409 错误文案保持 master 原文(有测试逐字钉住,未擅改);③ thinking 拒绝的移除是 master 自己 Zero-Inheritance Session Cloning: Unified Fix for Eight Independent Defects in the Fork Adoption Chain (Next Release Tar | 会话克隆零继承:fork 收养链上八类独立缺陷统一修复(下版目标) #4266 的演进(签名 thinking 已可按视图比较),随 merge 采纳而非本 PR 引入,其回归钉测试通过;④ 所有级联都失败时仍然 409 + 点名具体原因,fail-closed 契约不变。本地定向跑了全部 fork/snapshot 相关套件 151/151 绿(含 [Bug][fork] Cold restore cannot use an intact unified raw tail for a non-retained parent (#4266 item 4) #5140、Zero-Inheritance Session Cloning: Unified Fix for Eight Independent Defects in the Fork Adoption Chain (Next Release Tar | 会话克隆零继承:fork 收养链上八类独立缺陷统一修复(下版目标) #4266 的回归钉);新 head 上远程 CI 全矩阵绿(ubuntu/windows × node 22/24 全部 shard + static-gates + unused-exports 等门禁,0 failed)。
  6. 是否破坏缓存:不涉及——没动缓存、重试、增量游标或去重键的任何失效策略。
  7. 是否改了设计方向:没有转向——只是把同一失败域的两套机制合成一条级联路径,方向不变。
  8. 是否引入了新的配置:没有新 env/config/默认值。

判定:冲突已解、CI 全绿、PR 可合并(当前状态 behind 只是 master 又前进了,不构成障碍)。请自行合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

1 similar comment
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

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