Repository navigation
Description
Summary
A compressed long-running DSH desktop session was forked through the host UI. The child replayed thousands of raw messages without inheriting the parent's billion-context fold state, entered multi-minute emergency preflight, disconnected after approximately five minutes, and subsequent retries consistently failed locally with 413.
Related: #3011 (DSH fork adoption failure), #3025 (retroactive adoption conflict), #3978 (long preflight + client disconnect), #4079 (overflow/recovery tracking), #4082 (request-scoped attribution).
Important distinction from #3011: we did NOT find a fork adoption ... degraded, snapshot-409, or successful-adoption log for this child. A 409 root cause is NOT established here. Please investigate silent skipping of the adoption entry path as well as recovery after interrupted preflight.
Environment / version caveat
- Windows, DSH desktop, native billion-context plugin, OpenAI Codex Responses lane.
- Model:
gpt-6.1-sol; reported window: 744000. - Incident proxy logs:
v0.1.202. - Installed bundle inspected later:
0.1.203; upstream master also inspected atc87185a05a44ecccc225f96f92089e8f309fb1d9. - We have not recovered the incident-time native-plugin bundle; current-source suspicions below are NOT presented as a proven 0.1.202 stack trace.
- Parent/child IDs, usernames, business content, credentials and full transcripts are deliberately omitted.
Verified evidence
- The DSH child session header has
isSeeded: trueand the correctparentSession. The host copies the source event prefix into the new session (buildForkSeed->agents.create). HostSessionreally exposes.header;requestHeader()is a different, folded model-request-header API and should not replace that branch metadata. - The last successful inherited model call had
totalTokens: 155439. - Read-only inspection of bili's persisted SQLite state found:
- Parent: 174 blocks / 151 active at investigation time (parent had later activity; these counts are NOT claimed to be the exact branch-time counts).
- Child: exactly 1 block / 1 active,
parent_session_id = NULL,fork_point_seq = NULL, no fork-receipt metadata. - The child's only block was
b1, created during its own emergency preflight form02870–m02924, not an inherited parent block.
- Child's first proxy request:
processTurn: 8359 msgs; estimated context2242367tokens. This is a local estimate, not upstream measured billing. - No
fork adoptionlog was found in the inspected incident log. That is an observation, not proof that a particular skip predicate fired.
Sanitized incident timeline (UTC)
2026-10-21T17:00:58.421Z child: stamped type:"message" on 785 type-less input item(s)
2026-10-21T17:01:06.364Z child: processTurn: 8359 msgs
2026-10-21T17:01:06.674Z child: context 2242367 tokens reached preflight target 744000; preflight compressing before forward
2026-10-21T17:01:16.187Z preflight: round 1/32 ... 405 viable range(s)
2026-10-21T17:04:04.973Z compress requested m02870–m02924
2026-10-21T17:04:13.935Z compressed ... 1 block(s), ~35259 tokens saved; b1 summary 19955ch
2026-10-21T17:04:21.672Z preflight: round 2/32
2026-10-21T17:05:55.332Z preflight: summarization aborted: client disconnected
2026-10-21T17:06:05.118Z child: preflight aborted ... not forwarding
2026-10-21T17:06:08.209Z persist: cold-loaded child ... 8353 ref(s), 1 block(s) (1 active)
2026-10-21T17:06:18.808Z preflight fail-fast 413 (retryable=false): payload core text alone is ~5742630 bytes ... >= ~765684 tokens vs model window 744000 ... NOT forwarded
Further retries produced the same local rejection with 5742677 / 5742724 / 5742771 bytes. No model request succeeded in this child. The byte-density figures are lower bounds, NOT exact tokenizer counts.
Current-source suspicion: attribution and fork discovery use different identity paths
In src/agent/dsh-native.ts at the master commit above:
attributionOf(ctx)first usessidScope.getStore()populated fromllm/streamrequestoptions.sessionId(Why did it spike to several M tokens: after dsh attribution was lost, requests bypassed bili and were sent directly, ren | 为什么会涨到几 M tokens:dsh 归因丢失后请求绕过 bili 直发,压缩与护栏全部失效 #4082).forkChildOf(ctx)ONLY usesctx.agents?.currentInitiator?.()?.session, catches exceptions and returns undefined, and silently returns when the session/header is missing.maybeForkAdoptBeforeSendthen silently returns when the child cannot be discovered. Other silent skips include toolsReady/body/base/side-shaped-request checks.
Thus a correctly identified proxy conversation does not imply that fork-parent discovery ran. A request with a valid scoped session ID but missing/cleared ambient initiator can take the normal compression lane while skipping adoption entirely. This fits the observed absence of adoption logs, but we have not reproduced that exact scope condition in the incident.
Other relevant current-state finding: parent metadata currently has publicSnapshotTextComparable: false (snapshot ~28.5 MB). Current snapshot code would refuse opaque/multimodal comparison. We do not claim that flag had the same value at branch time or that a snapshot request/409 actually occurred.
Expected behavior
Fork a previously compressed session without unfolding its entire raw history, or explicitly stop admission with a useful, recoverable explanation when inheritance cannot be established. A failed/aborted emergency preflight should not leave the child in a retry -> immediate-413 loop with no usable recovery path.
Requested investigation / acceptance tests
- Carry explicit branch identity with the request scope, or resolve the scoped session ID to validated host branch metadata; do not rely solely on ambient
currentInitiator()for fork discovery. - Add structured diagnostics for EVERY skipped fork-adoption gate, distinguishing not-a-fork from missing attribution/session/header and protocol/snapshot rejection.
- Do not silently degrade a large compressed parent into an uncompressed child when that history cannot fit. Preserve the safe overflow guard, but provide an actionable recovery/adoption path.
- Verify retry semantics for temporarily unavailable snapshots and
CHILD_CONFLICTafter a first degraded request (related issues above). - Test interrupted preflight: persist progress and allow a subsequent request to resume shrinking rather than repeatedly fail-fast without further progress.
- Regression matrix: normal fork; parent cold-load/eviction; valid request-scoped ID + absent ambient initiator; opaque/multimodal history; fork through a fold boundary; client disconnect mid-preflight and retry.
No live sessions, compression DB, host services, or business configuration were modified during this investigation. No full transcript/database is attached for privacy reasons. Please treat the missing inheritance + preflight/retry chain as confirmed and the exact adoption-entry skip as still requiring instrumentation/reproduction.
Activity
ranxianglei commentedon Oct 21, 2026
(ai: vllm-qwen/qwen3.8-27b)
查重:重复处理——本 issue 的两个侧面都归入既有家族,按先来后到并入后关闭本帖,补充信息已写入先到 issue。
probeForEvidence+ doomed-probe 在真正折叠开始前就返回终态 413,「无基线+超窗+有可压 range」会话被永久搁浅),归入 [Bug] Excessive preflight compression time on ultra-large contexts; client mid-disconnect causes repeated request forwar | [Bug] 超大上下文 preflight 压缩耗时过长,客户端中途断开导致请求反复无法转发 #3978/Mid-session wire/dialect switch sends one request far beyond the declared window (upstream ContextWindowExceededError); no send-time size guard #3872 失败域,落点([Bug] Fork adoption server-side completion window: After the child session's first degraded request is committed, POST fork is permanently latched by 409 CHILD_CONFLICT, preventing retroactive adoption | [Bug] fork adoption 服务端完成窗口:子会话首条降级请求落地后,POST fork… #3025 checklist 还是并入 [Bug] Excessive preflight compression time on ultra-large contexts; client mid-disconnect causes repeated request forwar | [Bug] 超大上下文 preflight 压缩耗时过长,客户端中途断开导致请求反复无法转发 #3978)在等 owner 拍板。我这边用你的事故做了独立复核(见下),证据已补到 [Bug] Excessive preflight compression time on ultra-large contexts; client mid-disconnect causes repeated request forwar | [Bug] 超大上下文 preflight 压缩耗时过长,客户端中途断开导致请求反复无法转发 #3978。标签:bug / dsh / scope/wiring / p1(缺陷;DSH 宿主车道;主面是客户端接入层的 fork 判定接线,preflight 侧已在 #3978/scope 域内跟踪;后果 = 会话彻底不可用,按 2026-10-19 修订属 p1 不降档)。
代码级复核(v0.1.202 逐行核对,master 对照)
侧面一:你的怀疑方向成立,且比「currentInitiator 缺失」更结构化。 master 上 DSH native 车道有两条身份解析路径,且不同源:请求归属判定(
attributionOf,src/agent/dsh-native.ts:1162)优先用 #4082 的请求作用域 sid(AsyncLocalStorage,由 dshllm/stream瀑布写入),ambientcurrentInitiator()只是回落;而 fork 发现(forkChildOf,:1208-1220)只读 ambientcurrentInitiator().session,拿不到 header 元数据就静默返回 undefined。事故版本 v0.1.202 还没有 #4082(sidScope 是其后才进的),两条路径当时同源——所以当时要么是整条请求 ambient initiator 缺失(那归属也会失败、走匿名车道),要么命中了后面的某个静默门。无论哪条,maybeForkAdoptBeforeSend(v0.1.202 :1090 / master :1242)的五道前置门——toolsReady、child 发现、body 解析、side-shaped body、base URL——全部零日志零标记,这就是「事故日志里连一行 degraded 都没有」的直接原因:不是某条 409 被吞,而是根本没走到 adoption。这正对应你的验收测试 2。另外你提到的父会话publicSnapshotTextComparable:false(~28.5MB 快照)说明即便 adoption 走到快照端点也会命中 opaque 门(#3025-C6,方向待 owner 拍板)——这条也已在 #3011 登记为 C6 的又一现场佐证。侧面二:数字与代码完全对得上。 413 守卫的阈值是
max(2MB, 窗口×7.5):744000×7.5=5,580,000 < 5,742,630,且 ceil(5742630/7.5)=765,684 ≥ 744000——你的日志逐字节吻合。关键顺序细节(v0.1.202 src/server.ts ~:3383-3424):preflight 返回compressedRanges>0后,代码先把lastInputTokens写成 estimate 源(:3393-3394),然后才检查 client abort 并「not forwarding」早退——所以一次被中断的 preflight 会把 estimate 计量器持久化下来;之后每次重试都满足probeForEvidence(estimate 源 ⇒ baselineFloor=0)⇒ 原始 payload doomed 检查 ⇒ 直接终态 413,一次折叠都不尝试。首条请求能逃过守卫只是因为全新子会话 lastInputTokens=0。注意:#3978 的持久化修复(PR #4046,每轮 fold 落盘)治不了这个重试侧终态判决——那是另一个机制点(有可压 range 时不应在折叠前判死),与 floor 16 的记录一致,等 owner 定落点后一并修。处置
ranxianglei commentedon Oct 21, 2026
(ai: vllm-qwen/qwen3.8-27b)
关闭结论:duplicate of #3011。 本票 part 1(DSH native fork adoption 入口被静默跳过、零痕迹)与 #3011 同症状(fork 丢失折叠继承 → 零折叠子会话),属新机制实例,已登记为 #3025 清单 C10;part 2(preflight 中断后子会话陷入重复本地 413)已在 #3011 floor 16 记录、并归 #3978 失败域,处置位置待 owner 拍板。按「同症状 = 一个 issue、先来后到」规则,本票以 duplicate 关闭,补充信息均已写入先到的条目。
交付:PR #4223(无决策依赖部分,已开) — #4223 :给 DSH native adoption 入口的每一道跳过门加结构化诊断日志(log-only,零行为变更)。C10b 身份路由扩展需 owner 拍板,未含在内(选项在 #3011 线程)。
结构化八问
currentInitiator())与请求归属用的身份(Why did it spike to several M tokens: after dsh attribution was lost, requests bypassed bili and were sent directly, ren | 为什么会涨到几 M tokens:dsh 归因丢失后请求绕过 bili 直发,压缩与护栏全部失效 #4082 scoped sid)不在同一条路由上,initiator 不可用时 seeded 子会话被无声跳过、不留痕迹;② 中断的 preflight 在 abort 返回前已把 estimate-source meter 写回会话状态,后续请求因此进入 probeForEvidence 分支,raw-payload doomed 检查(核心字节数 > max(2MB, 窗口×7.5))在任何 fold 尝试之前直接判终端 413,形成 livelock。本票事故字节数与该公式精确吻合(~5742630B ≥ ~765684 tok vs 窗口 744000)。[dsh-client]记录,不进任何客户端或模型可见路径。本票验收测试的去向
#1 → C10b(待拍板);#2 → C10a(本 PR 已实现);#3/#5 → #3978 域(floor 4/5 已有持久化修复 #4046,重试侧判定仍在讨论);#4 → #3011 C6/C7 域;#6 → 既有回归矩阵 + 本 PR 测试覆盖。
标签:bug、dsh、scope/wiring、p1(已打)+ duplicate(随后补上)。现在执行关闭。若你认为某个机制没被上述映射覆盖,请附细节重开。
abworks-dev commentedon Oct 23, 2026
(ai: openai/gpt-6.1-sol)
Scoped-discovery fix submitted as #4424: when the ambient session is absent, resolve the existing request-scoped session ID through agents.get and validate the returned ID before applying the unchanged seeded-fork lineage gates. The regression runs through the real llm/stream waterfall; the original helper fails it, and the fix passes 25 targeted attribution/fork tests. Typecheck/build passed. The broader native suite has an explicitly disclosed Windows rmSync EPERM cleanup failure. This addresses C10b alongside the diagnostic-only #4223; parent snapshot availability/opaque-content and interrupted-preflight recovery are not claimed fixed by this PR. No private session data was uploaded.
fix: name every skipped dsh fork-adoption entry gate instead of retur…
fix(dsh): restore typecheck after sidScope->dispatchScope rename left…
fix(dsh): read dispatchScope in the #4215 fork-blind log — orphaned s…
fix: name every skipped dsh fork-adoption entry gate instead of retur…
fix(agent/dsh): decode content-encoded bodies in fork-adoption and re…