Replies: 1 comment
Independent reproduction + self-hosted repair toolAffected: We hit the same orphan-spliced issue on 4 sessions in our install, all still on 0.1.2-rc.1. Each affected session ends with an Evidence (4 sessions, all on 0.1.2-rc.1)
Pre-repair Self-hosted repairWhile waiting for the upstream fix, I built a self-contained repair tool that lives outside the dsh package (no plugin install, no schema change). It does the same accounting the runtime does (uses dsh's own Verified end-to-end on all 4 sessions: dry-run → apply → re-run reports If anyone wants a copy of the tool while the upstream fix is in flight, happy to share. Suggested upstream fix (additive to the report above)
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Self-review update — correction of our own submitted bug report / 自我修正:对本人提交的 bug report 的修正 (2026-08-22)
agent/inbox/splicedis declared valid by the persistence layer and unreadable by the session history consumption path. That split — not the blank page — is the defect.What we originally claimed / 初版表述 (EN): the conversation UI hard-fails (blank paging) on orphan
agent/inbox/splicedops with no insert; no data loss on disk, total loss of UI access.What we now state / 现修正 (EN): upgraded to the log/state-machine layer — one log is declared valid by the persistence layer and unreadable by the session history consumption path; the inbox state machine's tolerance intent (visible in
applySplice) does not hold end-to-end; the split sits exactly on the post-incident recovery path, so a routine repair can silently produce a durably intact but unreadable session.初版表述(中文): 孤儿
agent/inbox/spliced撤回操作(无对应插入)导致对话 UI 渲染中断、分页空白;磁盘数据未丢,但 UI 完全无法访问。现修正(中文): 升级到日志/状态机层——同一份日志被持久化层判定合法、却被会话历史消费路径判定不可读;inbox 状态机的容错意图(
applySplice可见)未能端到端兑现;分裂恰好落在事故后恢复路径上,因此一次例行修复可能静默产出"数据完好但不可读"的会话。EN / English
Version note / 版本说明
Source references were verified on
@deepseek-ai/dsh0.1.0-rc.7and re-verified on0.1.1-rc.2— module internals unchanged, line numbers shifted:dsh-client-ui-conversation/lib/client.js:applySplicenow at:8558-8568(was:8103-8113).dsh-client-runtime/lib/client.js: the conversation fold/assembler now at:6358-6590(was:6345-6592); structural guards at:6543/:6567/:6568(was:6548/:6572/:6573); the history-error swallow now at:7414(was:7418-7419).Observed behavior
A session log containing an
agent/inbox/splicedevent withremovedCount > 0but no precedinginserted(an orphan removal) is accepted by the persistence layer —foldSurface()passes, seq stays contiguous, JSON is valid. The same log, consumed by the session history path, renders only up to the orphan op and returns empty pages for everything after — with no error surfaced (consumption errors are swallowed with a console-only log,dsh-client-runtime/lib/client.js:7418-7419).One log, two consumers, two verdicts: "valid" (persistence) and "unreadable" (history consumption). The blank-page symptom is real; the defect is the split itself.
State-machine mechanism (with source references)
applySplice(dsh-client-ui-conversation/lib/client.js:8103-8113) is written to be safe by default —removedCount ?? 0,pending.splice(...)against a possibly-empty array. An orphan removal is anticipated and tolerated at the reducer level.dsh-client-runtime/lib/client.js:6345-6592) guards structural violations only — duplicate starts (:6548), out-of-order appends (:6572), updates before a start (:6573) — with no guard for "removed identities that were never inserted."Impact scope (upgraded — log / session / business / recovery path)
removedCountto0by manual log editing).Expected behavior
The inbox state machine must have one semantics across all consumers: "removedCount against identities never inserted" must be a no-op everywhere (or surface a visible warning) — the reducer already does this, the consumption path must too. Data-layer strictness and consumption-layer tolerance must be aligned, and any alignment failure must surface as an error, never a silent blank.
Repro
agent/inbox/splicedcontainingremovedCount: 1and no matching insert (can be produced by truncating the log between an insert and its removal).removedCountto0→ rendering and paging fully restored.Environment
@deepseek-ai/dsh0.1.0-rc.6/0.1.0-rc.7@deepseek-ai/dsh0.1.1-rc.2Evidence (sanitized + source)
dsh-client-ui-conversation/lib/client.js:8103-8113—applySplice: intended tolerance (removedCount ?? 0, safe splice on empty pending).dsh-client-runtime/lib/client.js:6345-6592— consumption fold/assembler: structural guards only; no orphan-removal guard.dsh-client-runtime/lib/client.js:7418-7419— consumption errors are swallowed silently (console only).Authorship note: reproduced and documented by me in real-world usage; root-cause tracing and drafting assisted by AI; verification and publication by me. I have no engineering background — if any technical claim reads wrong, please call it out; I will re-verify against the toolchain and correct.
中文版 / ZH
版本说明
源码引用在
@deepseek-ai/dsh0.1.0-rc.7上验证,并在0.1.1-rc.2上重新验证——模块内部逻辑未变,行号有偏移:dsh-client-ui-conversation/lib/client.js:applySplice现位于:8558-8568(原:8103-8113)。dsh-client-runtime/lib/client.js:对话 fold/assembler 现位于:6358-6590(原:6345-6592);结构性守卫位于:6543/:6567/:6568(原:6548/:6572/:6573);历史错误吞掉现位于:7414(原:7418-7419)。现象
含有
agent/inbox/spliced事件(removedCount > 0、前面没有对应的inserted,即孤儿撤回)的会话日志,被持久化层接受——foldSurface()通过、seq 连续、JSON 合法。同一份日志,被会话历史消费路径处理时,只渲染到孤儿操作之前,其后全部空页——且无任何报错(消费错误被吞掉、仅 console,dsh-client-runtime/lib/client.js:7418-7419)。同一份日志、两个消费方、两种结论:"合法"(持久化)与"不可读"(历史消费)。空白页症状真实存在;缺陷是分裂本身。
状态机机制(附源码引用)
applySplice(dsh-client-ui-conversation/lib/client.js:8103-8113)按默认安全编写——removedCount ?? 0、对可能为空的数组做pending.splice(...)。孤儿撤回在 reducer 层是被预见并容忍的。dsh-client-runtime/lib/client.js:6345-6592)只守卫结构性违规——重复 start(:6548)、乱序追加(:6572)、start 之前 update(:6573)——对"撤回从未插入过的身份"没有任何守卫。影响范围(升级 —— 日志 / 会话 / 业务 / 恢复路径)
removedCount改为0)。期望行为
inbox 状态机必须在所有消费方上语义一致:"对从未插入过的身份执行 removedCount"在所有地方都应是空操作(或给出可见警告)——reducer 已经做到,消费路径也必须做到。数据层的严格与消费层的容错应当对齐,任何对齐失败必须以错误形式暴露,绝不允许静默空白。
复现步骤
agent/inbox/spliced(removedCount: 1、无匹配插入)的会话日志(在"插入"与"撤回"之间截断即可产生)。removedCount改为0→ 渲染与分页完全恢复。环境
@deepseek-ai/dsh0.1.0-rc.6/0.1.0-rc.7@deepseek-ai/dsh0.1.1-rc.2上验证证据(脱敏 + 源码)
dsh-client-ui-conversation/lib/client.js:8103-8113——applySplice:意图宽容(removedCount ?? 0、对空 pending 安全 splice)。dsh-client-runtime/lib/client.js:6345-6592—— 消费侧 fold/assembler:只有结构性守卫,没有孤儿撤回守卫。dsh-client-runtime/lib/client.js:7418-7419—— 消费错误被静默吞掉(仅 console)。Original report (archived for transparency) / 初版报告(归档保留)
EN
Observed behavior (original). After a session log is damaged/truncated (crash, manual repair, torn write), it can contain an
agent/inbox/splicedevent withremovedCount > 0but no precedinginserted. The persistence layer accepts the log, but the UI renders only up to the orphan op and "Load earlier" returns blank pages forever — with no error surfaced.Impact scope (original). Any user who repairs/recovers a session (or suffers a torn write) can end up with a session that looks openable but is effectively unreadable in the UI. No data loss on disk; total loss of UI access to the conversation. Applies to web UI and desktop shell alike.
中文
现象(初版)。 会话日志受损/被截断后,可能残留一个
agent/inbox/spliced事件:removedCount > 0但前面没有对应的inserted。持久化层接受这份日志,但 UI 只渲染到孤儿操作之前,"加载更早"永久空白,且没有任何报错。影响范围(初版)。 任何修复/恢复过会话(或遭遇写入中断)的用户,都可能得到一个"看着能打开、实际读不了"的会话。磁盘数据未丢,但 UI 完全无法访问该对话。Web UI 与桌面壳同样受影响。
署名 / About this report
EN: Reported by the OfferKuai (Offer快) Team — an AI startup building full-lifecycle job-application services, guided by the belief that "users need results, not repeated conversations." Founder: Zhaofeng (Yaming). We use DeepSeek Harness as part of our daily development workflow; this report is our way of contributing back to the ecosystem. Website: https://www.offerkuai.com/ | Contact: <contact@offerkuai.com>
ZH: 本报告由 OfferKuai(Offer快)团队提交 —— 一家专注 AI 全流程求职托管的创业团队,核心理念是「用户要的是结果,不是重复对话」。创始人:Zhaofeng(Yaming)。我们将 DeepSeek Harness 用于日常开发工作流,这份报告是我们对社区的回馈。官网:https://www.offerkuai.com/ | 联系:<contact@offerkuai.com>
————————————————————————————————————————————————
All reactions