Skip to content

Releases: HaoyueQin/dsh-diff-stat

v0.1.6

Choose a tag to compare

@github-actions github-actions released this 02 Sep 07:35

dsh-diff-stat v0.1.6

Eighth release. The turn summary card's review expansion survives streaming: while the next turn's answer streams in, every file's review diff — most visibly the last, dispatch-joined one — stays open instead of flickering shut, a stale or failed window preparation falls back to raw hunks, and the join feeding the card becomes a pure module whose identity-stable cache contract is pinned by a new CI check.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Fixes / 修复

  • Review diffs stay open while the next turn streams: the card's expanded review closed the instant the next turn produced a streaming chunk. The per-turn dispatch join keyed its cache fast path on the chat snapshot object identity — which every chunk rebuilds — so the join re-extracted per chunk, the merge re-cloned every entry, and the review gate's exact-identity check failed again on each chunk. The fingerprint now keys on what actually identifies an unchanged tree: the turn coordinate, the node keys, and the node identities behind them (the stock assembler reuses undirty contexts' nodes), so the joined list — and every hunk identity under it — stays stable across the stream.
  • A stale or failed window falls back to raw hunks: the expanded review rendered nothing while its context-boosting host read was in flight, and a failed read (binary file, a file being rewritten by the live turn) blanked it permanently — the retry guard treated the failure as done. The render now falls back to the raw hunks with window-relative gutter numbers until a fresh window lands (restoring the module's own documented design), and failed reads stay retryable instead of pinned.
  • The review self-heals after real re-settlements: the prepare effect keys on the file list's identity as well, so a genuine re-fold (history pagination, republished turn data) re-prepares stale entries in place instead of waiting for a manual re-toggle.

Infrastructure / 基建

  • The dispatch join becomes a pure module with a pinned cache contract: the join and its fingerprint cache move out of the component into src/client/turn-join.ts (no React, no runtime value imports), and scripts/check-turn-join.mjs (pnpm check:join) pins the contract in six scenarios — repeated joins over an unchanged tree return the same array with the same hunk identities; changed nodes, changed key sets, changed turn coordinates and first extractions miss correctly; non-tool-call nodes and missing keys hold stable placeholder positions. Wired into both CI and the release workflow.

Full Changelog: v0.1.5...v0.1.6


中文说明

第八个版本。主线一处行为修复:轮末汇总卡的审查展开在下一轮流式期间保持打开——此前任意一个流式 chunk 都会把已展开的审查 diff 顶掉(最后一个文件——run_code 派生合并的那个——最明显,点开瞬间即关闭并反复闪烁),并伴随两处配套增强与一条基建固化。

流式期间审查不再闪关:卡片的派生合并(PTC join)缓存快路径错把「聊天快照对象身份」当缓存键,而流式期间每个 chunk 都会重建快照对象——于是每个 chunk 都全量重提取,合并层再整体克隆,审查渲染门的严格身份比对(prepared 条目的输入须为该文件当下 hunk 列表)逐 chunk 失配。指纹现改键于真正刻画「树未变」的事实:轮坐标、节点键、节点身后的节点身份(stock 装配器只重建 dirty 上下文的节点)——合并结果与其下所有 hunk 身份在整个流式期间稳定。

陈旧/失败的展开窗口回退原始 hunks:展开时上下文增强的宿主读取在途期间渲染为空;读取失败(二进制、文件正被进行中的轮改写)则永久空白——重试守卫把失败条目当作已完成。现在渲染回退到原始 hunks(窗口相对编号)直至新窗口落地(恢复该模块自己文档声明的设计),失败的读取保持可重试。

真实重结算后审查自愈:prepare effect 的依赖加入文件列表身份,分页重折叠、轮数据重发布等真实变化会原地重新准备失效条目,无需手动再点一次「审查」。

基建:join 与指纹缓存提取为纯模块 src/client/turn-join.ts(无 React、无运行时值导入),scripts/check-turn-join.mjspnpm check:join)以六个场景钉死缓存契约——未变树上重复 join 返回同一数组与同一 hunk 身份;节点变化、键集变化、轮号变化与首次提取正确 miss;非 tool-call 节点与缺失键按位占位。已接入 CI 与发布工作流。

验证pnpm typecheckpnpm check:alignpnpm check:joinpnpm build 全绿;修复提交的 CI(run 33603662099)全绿;发布 tag 经工作流校验「tag 名 == package.json 版本」「lib 零漂移」并新增 check:join 关卡后自动出包(run 33604312805 全绿)。


v0.1.5

Choose a tag to compare

@github-actions github-actions released this 01 Sep 07:08

dsh-diff-stat v0.1.5

Seventh release. The diff surfaces learn line-number gutters — the file peek numbers its lines and the diff window pins every hunk to its real position in the current file — plus a separated sticky path header, three presentation fixes (the undo button no longer clips at the card edge, the phantom horizontal scrollbar is gone, the review diff matches the peek width), and the supported harness matrix extends to 0.1.2-alpha.3.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • Line-number gutters: the file peek numbers its lines 1..N; the diff window resolves each hunk's numbering basis from ONE cached fenced read — the post-image locate for hunks with content, the old side's leading shared context for deletion-only hunks, a free 1 for settled wire creates/overwrites. Deleted rows read the old side, context/added rows the new side, changed rows carry the reference accent bars, and the number column is sticky-left while long lines scroll beneath it. A hunk that cannot be located (host absent, drifted file, over budget) numbers window-relatively 1..N — the gutter always renders, and never invents positions it cannot prove.
  • Separated sticky path header: the file path no longer blends into the numbered rows — it sits in its own bordered strip above the body (the inline peek's top-bar presentation), pinned to the pane top while a long diff scrolls, with the name itself sticky-left over horizontal scrolling.

Fixes / 修复

  • The undo button stays inside the card: the card header declared width: 100% next to its horizontal padding, and the harness ships no global border-box reset — under content-box sizing the header's padding box overflowed the card by 20px, the flex content area ran to the overflow:hidden clip edge, and the auto-margin undo button rendered flush against it, slicing the last glyph (撤销). The redundant width is dropped and box-sizing: border-box pinned.
  • No more phantom horizontal scrollbar: every diff row sized min-width: 100% under content-box, so each row plus its horizontal padding overflowed the scroll pane by a constant 16px — the pane carried a scrollbar even when the diff lines were short.
  • The review diff matches the peek width: the turn card indented the expanded diff 30px from the left, so reviewing and peeking the same file stacked two panes of visibly different widths. Both are children of the same file-row block sharing the right edge; the inset is dropped and the diff spans the peek width exactly.

Infrastructure / 基建

  • Supported harness matrix extends to 0.1.2-alpha.3: client-runtime, ui-slots, the tool.call.toolview and conversation.chat.turnTail slot contracts, the uiConversation event registry, and the wire FsDiffMeta are diff-free between alpha.2 and alpha.3 — verified item by item against the tag diff, zero code adaptation. The align check gains gutter-numbering invariants (replacement, insertion, and gapped hunks across located and relative bases).

Full Changelog: v0.1.4...v0.1.5


中文说明

第七个版本。主线:行号槽路径头分隔条与三处展示修复,支持矩阵延展至 0.1.2-alpha.3

行号槽:文件视图按 1..N 编号;diff 窗口把每个 hunk 钉到当前文件中的真实位置——展开窗口只做一次缓存围栏读取(prepareDiffWindow,与上下文增强合并):有内容的 hunk 唯一匹配后像定位,纯删除 hunk 锚定旧侧前导共享上下文,已结算的 wire 创建/覆盖免定位(后像即整个文件,基准为 1),超预算 hunk 跳过定位。删除行读旧侧号码(红)、上下文/新增行读新侧号码,变更行带左缘色条;号码列 sticky-left,横向滚动长行时恒在。无法定位的 hunk(host 缺席、文件已被再改动、超预算)退回窗口内 1..N 相对编号——行号槽始终渲染,但绝不报无法证实的号。对齐行携带各侧行索引(del 仅 oldIdx、add 仅 newIdx、ctx 双带),check:align 新增编号不变量断言(替换/插入/带 gap,定位与相对两种基准)。

路径头分隔条:diff 窗口顶部的文件名此前混在行号行中,现独立为带底边的分隔条(与内嵌查看顶栏同款:三等字色、磨砂底);长 diff 竖向滚动时钉在窗口顶部,横向滚动时文件名钉在左侧——对应内嵌查看「顶栏始终可见」的行为。

展示修复:①撤销按钮裁字——.headerwidth:100% 加水平内边距在 harness 无全局 border-box 重置的环境下按 content-box 外溢 20px,flex 行可用区顶到卡片 overflow:hidden 剪裁边,margin-left:auto 的撤销按钮被竖切最后一字;去掉冗余宽度并钉 box-sizing: border-box(对齐 stock 逐元素声明惯例)。②幻影横向滚动条——每行 min-width:100% 加内边距按 content-box 恒溢出滚动容器 16px,短内容也常驻滚动条;border-box 根除。③审查与打开等宽——轮末卡展开 diff 曾有 30px 左缩进,同一文件的审查与内嵌查看堆叠出两种宽度;缩进移除,两者同列同宽。

验证pnpm typecheckpnpm check:alignpnpm build 全绿;发布 tag 经 CI 校验「tag 名 == package.json 版本」与「lib 零漂移」后自动出包(run 33480646569 全绿)。


v0.1.4

Choose a tag to compare

@github-actions github-actions released this 31 Aug 06:57

dsh-diff-stat v0.1.4

Sixth release. The collapsed row's file link now fits like the stock client — shrink-to-fit with a real ellipsis (the old rule pinned the path box at 340px, and its display: inline-flex silently disabled text-overflow, so truncation was always a hard clip). A multi-pass third-party review then hardened the unsafe edges: undo now judges create-vs-overwrite on turn-start existence snapshots (session-scoped, full-tree, truncated-reads-unverified), the inline badge and the diff window share one arithmetic, PTC dispatch records route to their turn reliably, and the committed lib builds byte-stable on any machine.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • Undo is snapshot-guarded end to end: the host captures a turn-start file-existence snapshot (existence only, never bytes) with session-scoped keys (cwd, session, turn) — two sessions can share one workspace and turn numbers restart per session. The capture walks the full tree (node_modules/.git skipped, the 100k-file cap the only bound) and is idempotent per turn (a window reload re-running the start match no longer re-captures at a later time). Anything truncated or unlistable reads unverified, never create — undo can no longer delete a file that pre-existed the turn. Reads are capped: files.read takes only the display head, undo refuses files beyond a 32 MiB gate, oversized request bodies answer 413 exactly once, and concurrent history replays merge per key.
  • Badge and window share one arithmetic: a terminator-only change ("a\n""a") is line-equal under the LCS yet rendered as a lone gap row with +0 −0 — it now counts one deletion plus one addition in both the badge and the window, and the detector bails above the alignment budget so neither drifts. An empty creation (write '' to a new file) counts one added line instead of +0 −0. LCS results are memoized per side pair (the badge and the window align the same hunk up to four times at the 1200-line budget), and paths merge on a normalized key (\\ and ./ forms collapse into one row, first-seen spelling kept for display).
  • PTC / Code Dispatch routing: wire dispatch records carry no turn coordinate — the accumulator now learns rootCallId → Turn from tool/call matches and routes each record to its turn; the fold seeds from the engine-routed Context id (the runtime Location index resolves a window-start record to session, so Location alone had nothing to say exactly when it mattered). The dead string-arguments branch is removed — both supported kernel generations carry arguments as an object, and its hunks double-counted with the chat-tree join — dispatch records now contribute PTC evidence only, and the root learn-table evicts LRU instead of clearing every mapping at the cap.
  • The row file link fits like stock alpha.2: .linkFit reduces to the single override flex: 0 1 auto — width = min(content, free line width), a real ellipsis when the line runs out, the +N −M badge stays adjacent, and the click target still ends where the path text ends (the row's empty remainder stays the expand/collapse toggle).

Fixes / 修复

  • Accessible summary card header: the header becomes a div with button semantics — the undo button inside the old <button> header was invalid nested-button HTML that broke screen readers and keyboard navigation.
  • Context boost anchors only on a unique fragment: with duplicated content (a snippet copied across a template) the boosted builder wrapped the wrong region; a fragment appearing more than once now stays unboosted.
  • Glass bridge validated before invoke: any window code could dispatch a same-named event or clobber the global — a partial shape threw on .version far from the source while the old bridge stayed un-cleaned (silent glass failure). The global and event detail now pass a structural guard first.
  • Hardened host calls: fetchWithTimeout keeps the module-owned timeout over any caller signal, and a failed host probe retries on the next call (host routes appear on hot reload). The file peek stores error message keys, so a locale switch re-renders in the new language; duplicated implementations and dead CSS dropped.

Infrastructure / 基建

  • Byte-stable committed lib: bundled node_modules modules carried ABSOLUTE //#region paths of the build machine, so a rebuild on any other checkout differed byte-for-byte — breaking the committed-lib contract and the CI lib-diff gate. A renderChunk pass now normalizes region labels under the project root (verified: zero absolute paths remain); committed artifacts rebuilt.
  • CI / release guards: branch/path filters with superseded-run cancellation; the release workflow asserts the pushed tag matches package.json version; the tarball is picked with an exactly-one regex that now admits dotted prerelease segments (and would otherwise mis-pick 0.10.x over 0.9.x); CI paths gain lib/**.
  • Packaging hygiene: dsh-atomic-write joins peerDependencies (the host half imports it and the bundle externals it — a harness without it crashed instead of degrading); engines declares the node floor; .gitattributes pins committed lib bundles as binary so the byte-stable diff survives Windows checkouts.
  • Tests: new assertion blocks cover the pagination-boundary dispatch routing and fold, the create/overwrite classifier, the unique-fragment anchor, path-key merging, and terminator-only arithmetic — including skipped directories (both separators, several depths), empty creations, .git-safe classification (.gitignore as a filename stays create), truncated snapshots, and over-budget terminators.
  • Docs: the supported harness matrix extends to 0.1.2-alpha.2 (slot contracts, wire meta, and session events re-verified item by item); READMEs gain hand-drawn SMIL banner and demo SVGs, the GitStock activity chart, and a sync with the fenced API surface.

Full Changelog: v0.1.3...v0.1.4


中文说明

第六个版本。两条主线:行内文件链接截断修复多轮第三方评审驱动的安全加固

链接修复:折叠行上的路径链接曾同时踩两个坑——flex: nonemax-width: 340px 定宽帽(340px 是早期 badge 置行尾时代的遗留,布局改造后未清理),宽度恒为 min(内容, 340px),窗口再宽也截断;display: inline-flex 又使按钮成为 flex 容器,text-overflow 为非继承属性、不作用于匿名 flex item,省略号从未渲染过,一直是硬裁切。现 .linkFit 收敛为单条 flex: 0 1 auto,对齐 stock alpha.2 上游的 shrink-to-fit 设计:宽度 = min(内容宽, 剩余行宽),窄行让位给 +N −M 徽标并出真省略号,点击目标止于路径文本,行剩余区域仍归展开切换。

undo 撤销守卫:此前 undo 以「wire 记录无旧文本」判定 create 并直接删除,多轮评审发现一串可误删既有文件的路径——回合起点快照(仅存在性、绝不落字节)成为判定基准:键升级为会话级(双会话共享工作区、回合号各自重起时不再串档);捕获遍历全树(跳过 node_modules/.git,仅受 10 万文件上限约束)且按回合幂等(窗口重载重放 start 匹配不再二次捕获);凡截断、目录不可列、junction/symlink 项一律降级为 unverified,绝不判 create——undo 从此不可能删除回合前就存在的文件。读取侧同步设限:files.read 只读展示头部、undo 拒绝 32 MiB 以上文件、超限请求体精确应答一次 413、并发历史重放按键合并。

徽标与算术统一 / PTC 路由:行尾仅换行符变化("a\n""a")在 LCS 下行等价,曾渲染为 +0 −0 的孤立空隙行,现徽标与窗口一致计为 +1 −1;空文件创建(write '')计一行新增;LCS 按侧对记忆化;路径按归一化键合并(\\./ 形态收敛为一行)。PTC 子调用记录按 rootCallId 归位到所属回合,fold 以引擎路由的 Context id 播种(分页窗口从中途开始也能认领轮末卡);死代码 string-args 分支移除(其 hunk 会与工具树 join 重复计数),学习表改 LRU 淘汰。

基建:提交 lib 实现字节稳定(bundle 内 region 标签由构建机绝对路径归一化为项目相对路径,跨机器重建逐字节一致,CI 的 lib-diff 门禁恢复意义);CI/发版增加守卫(tag 与 package.json 版本一致性断言、tarball 恰一匹配正则支持 prerelease、分支/路径过滤与超驰取消);dsh-atomic-write 补进 peerDependencies、engines 声明 node 下限、.gitattributes 将提交 lib 钉为 binary;对齐器新增多组断言(路由/fold、create-overwrite 分类、唯一片段锚定、路径合并、terminator 算术、.git/node_modules 分类、截断快照、超预算 terminator);README 文档面更新(支持矩阵延展至 0.1.2-alpha.2、SMIL banner 与演示 SVG、GitStock 活跃图、围栏 API 同步)。

验证pnpm typecheckpnpm check:alignpnpm build 全绿;发布 tag 经 CI 校验「tag 名 == package.json 版本」与「lib 零漂移」后自动出包。


v0.1.3

Choose a tag to compare

@github-actions github-actions released this 28 Aug 09:54

dsh-diff-stat v0.1.3

Fifth release. One built bundle now serves two harness kernel generations — 0.1.1-rc.2 and 0.1.2-alpha.1. The alpha release deleted the client-runtime package, dropped the presentation view envelope, and renamed the conversation event service; the plugin rebased its data sources onto the wire layer (the tools' persisted result meta), so every feature — inline badges, the aligned diff window, the per-turn summary card, PTC joins, undo — keeps working unchanged on both, verified against a live instance of each generation.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • One build, two kernel generations: the built bundle is down to exactly one kernel module dependency (@deepseek-ai/dsh-client-ui-primitives, present in both kernels' static platform table). The append-surface predicate is inlined (byte-identical in both cores), settled diff hunks are read from the wire meta that both generations persist on the tool/result event (FsDiffMeta, byte-identical), and the conversation event registry / chat-snapshot hook resolve either generation's shape at runtime — waiting on cordis's internal/service event when the provider has not applied yet.
  • PTC stays first-class: the newer kernel stopped rendering diff cards for dispatch sub-calls entirely; this plugin keeps the argument-fallback diff and the chat tool-tree join, so Code Dispatch turns still get inline badges and the summary card on both generations.
  • Verified on both generations: live instances of each kernel (npm CLI on 0.1.1-rc.2, source CLI on 0.1.2-alpha.1) — inline badges (+19 −0, +1 −0), the summary card (2 files changed +20 −0 with undo), diff windows and the host fenced API all pass with zero plugin console errors. On 0.1.1-rc.2 the settled data source was verified identical by kernel source (the old resultView was itself derived from the same meta, so replayed history agrees).

Fixes / 修复

  • peerDependencies repaired: the runtime entry's range satisfied neither target prerelease (semver admits a prerelease only under a same-tuple comparator — both 0.1.1-rc.2 and 0.1.2-alpha.1 evaluated false) while the package no longer exists in 0.1.2-alpha.1 and the bundle stopped importing it. The entry is dropped; the remaining dsh peers carry prerelease-aware bounds anchored at 0.1.1-rc.1 / 0.1.2, verified with semver against both generations and future stable releases.
  • One-line diagnostic while waiting: if the host roster contains neither conversation-event provider, the wait logs once instead of leaving a silently missing turn summary card.
  • Docs: the README states the compile-time type baseline (0.1.1-rc.2 devDependencies) and that newer-kernel compatibility rests on runtime shape checks — a future wire-field rename cannot pass tsc unnoticed. Stale result-view wording replaced by the wire-meta data source.

Infrastructure / 基建

  • lib consistency gate unchanged: the committed lib/ still builds byte-identical on CI (git diff --exit-code -- lib/), so github: installs keep shipping exactly what the sources build.
  • Vendored ToolRow stylesheet refreshed to the 0.1.2-alpha.1 chrome (content font-size axis with fixed fallbacks that degrade gracefully on 0.1.1-rc.2).
  • Known upstream issue (not this plugin): on 0.1.2-alpha.1 the stock client's rewindMarkedSeqsOfChat crashes on long legacy sessions (input dock error). Reproduced with this plugin removed — a kernel-side projection bug on old session data; inline badges and the summary card are unaffected. Worth an upstream report.

Full Changelog: v0.1.2...v0.1.3


中文说明

第五个版本。本版核心是同一构建产物同时适配两个内核世代:harness 0.1.2-alpha.1 删除了 client-runtime 包、废弃了呈现视图信封(callView/resultView)、把会话事件服务从 conversationEvents 改名 uiConversation,并将工具卡改为从原始事件派生。插件把数据源整体下移到 wire 层——两版内核的 edit/write 工具都会把应用后 hunk(FsDiffMeta)持久化在 tool/result 事件的 meta 上且该结构逐字节一致——因此徽标、对齐 diff 窗、轮末汇总卡、PTC join 与撤销在两版上行为完全一致。

实现要点:①追加面谓词本地内联(两版 core 实现逐字节相同),产物对内核动态模块表的依赖收敛到两版静态平台表共有的 @deepseek-ai/dsh-client-ui-primitives;②会话事件注册表运行时双探测(uiConversation.events / conversationEvents),提供方未就绪时挂 cordis internal/service 事件等待——不能把另一代不存在的服务名写进 inject,那会 pending 整个 fiber;③turnTail 组件同时接受新版 useChat 与旧版 useSession 标准prop,快照探测兼容旧版 .chat 嵌套与新版直达形态;④PTC 子调用在 0.1.2-alpha.1 的 stock 行为是不再渲染 diff 卡,本插件的参数兜底 diff 与工具树 join 成为独有能力,两版均保留。

验证:两个内核世代各起真实实例(0.1.1-rc.2 用 npm CLI、0.1.2-alpha.1 用内核源码 CLI)实测——行内徽标(+19 −0 / +1 −0)、轮末卡(「2 个文件已更改 +20 −0」含撤销)、diff 窗展开、host 围栏 API 全部通过,插件相关 console 错误为零。0.1.1-rc.2 侧的 settled 数据源同一性经内核源码核对(旧版 resultView 本就派生自同一 meta),历史回放同样成立。

已知边界0.1.2-alpha.1 的 stock 客户端对长历史会话存在 rewindMarkedSeqsOfChat 自身崩溃(输入坞报错)——已做无插件对照实验确认与插件无关,属内核对旧会话数据的投影 bug,建议向上游反馈;徽标与轮末卡不受影响。


v0.1.2

Choose a tag to compare

@github-actions github-actions released this 26 Aug 10:22

dsh-diff-stat v0.1.2

Fourth release. The per-turn summary card now survives a session reload. The Web client opens every session on a tail page (the last 50 message boundaries), and a turn whose turn/start lies outside that window used to publish no diff-stat turn data — the card silently vanished on older turns in production (short clean sessions were unaffected, which made it look environment-dependent). The accumulator now folds its engine matches — the same pattern the stock turn-tail uses — so a window-truncated turn publishes whatever the window holds, and older history pages enlarge the fold as they arrive.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • Turn card survives window truncation: the conversation window loads only the last 50 message boundaries (PAGE_MESSAGES), and a turn whose start is outside that window reached the accumulator with update matches only — the engine runs no start/update for those, the definition's state stayed unset, and buildLocationData returned null, so no diff-stat data and no card. buildLocationData now folds the context's matches (the same best-effort pattern the stock turn-tail's tailData uses), recovering the card for truncated turns; a call whose tool/call settled outside the window cannot contribute, and prepending older pages enlarges the fold automatically.
  • One derivation, no drift: the engine's incremental update path and the window fold share a single applyUpdateState function, so both derive identical data by construction — no second state machine to keep in sync.

Fixes / 修复

  • Window-truncated turns publish their card again: root edit/write turns reopened on a tail page (production norm: long sessions, page refresh, session reopen) previously showed no summary card while the tail row rendered empty (even the stock produced-files chip was data-starved). Root mutations accumulate as before; a windowed turn publishes whatever settled inside the window, in settlement order with the same seq filter.
  • Empty-data turns stay uncarded: a turn with no change tool calls and no code dispatch still publishes empty facts, so the claim decision (and the stock fall-through) behaves exactly as before.
  • Edge: residual events at the window start publish their own (partial) turn data, keyed by the event's authoritative turn field — never mislabeled.

Infrastructure / 基建

  • No new check-script assertions: the fold lives in the module that value-imports the runtime (isAppendSurfaceEvent), which the alignment check script cannot import directly (known limitation, §5-11). The fix is verified against real production sessions: the reported session's turn 1/2 cards restored, the PTC windowed turn restored, live turns unchanged, zero console errors.
  • Known boundary: a PTC turn whose run_code root blocks were themselves window-truncated cannot join its dispatch sub-calls (the chat tool tree is truncated the same way); standard mode is fully recovered.

中文说明

第四个版本。本版修复了「轮末文件变更汇总卡在生产环境的历史轮次上不显示」的根因:Web 打开/刷新会话时只加载最后 50 条消息边界PAGE_MESSAGES)作为窗口,窗口起点落在某轮 turn/start 之外时,累积器(diff-stat)只有该轮的 update 匹配、引擎不执行 start/update → context.state 缺省 → buildLocationData 返回 null → diff-stat turn data 不发布 → 轮末卡静默消失(干净短会话窗口覆盖全程,不受影响——所以此前表现得像「环境相关」)。修复后 buildLocationData 改为从 context 的 matches 折叠推导(与 stock turn-tail 的 tailData 同款模式):窗口裁剪的轮次也能发布窗口内推导的数据,上滚加载旧窗口时自动补全。

本次排查同时闭环了多轮实测:生产环境插件与本地构建逐字节一致(排除版本漂移)、R1 行内徽标始终正常(排除客户端加载)、live 抓包确认参数与 view 形态(排除数据形态问题)、浏览器 fiber 探针直接对比了修复前后 diff-stat turn data(UNDEF → 含真实 hunk)与卡片 DOM。

已知边界:①裁剪轮显示的是窗口内「尽力而为」的变更集合,工具调用配对在窗口外时无法补全;②PTC 历史轮若其 run_code 根块同样被窗口裁剪,卡依赖的工具树 join 为空(标准模式已完整恢复);③折叠逻辑位于含 runtime 值导入的模块,check 脚本无法直接覆盖(已记录,组件级测试为后续项)。


v0.1.1

Choose a tag to compare

@github-actions github-actions released this 26 Aug 06:25

dsh-diff-stat v0.1.1

Third release. Long diff lines are readable again — the horizontal scrollbar the window always promised now actually appears — and the diff width follows the chat column instead of a fixed 720px cap, so the desktop harness's user-resizable conversation column is honored. Every finding of a full line-by-line review is closed too: fence-API link-swap hardening, display-layer BOM handling, fetch timeouts, i18n consistency, memoized card stats, and a deterministic release tarball selection.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • Long lines are fully readable again: the diff window's scroll container carried width: max-content, which made it as wide as its widest line — no scrollbar ever appeared and long rows were clipped silently by the rounded shell. The container now follows its parent and each row carries the content width instead, so the horizontal scrollbar appears and the add/del row tint tracks the line tail while scrolling.
  • Diff width tracks the chat column: the turn card's review diff dropped its 720px pixel cap — the surface is a block-level child of the column, so it follows --dsh-chat-content-width (the desktop harness lets the user resize that column to 40–95%; sidebars and narrow windows shrink it too). Standard 748px dsh web layout is pixel-identical to before (698px), verified against long rows and the flex chain.
  • Theme-adaptive file silhouettes: the neutral file icon's fold highlight uses currentColor at 35% instead of a hardcoded white stroke that vanished on light themes.

Fixes / 修复

  • Path link tooltip: a truncated path on the inline edit/write row now shows its full text on hover (title), matching the turn card's file name.
  • Per-render LCS cost removed: the turn card recomputed every file's diff statistics on each render; they are now memoized per file list — one DP pass per file (parity with the mutation row).
  • i18n consistency: the file preview's hardcoded Chinese strings route through the diff-stat dictionary; the never-used whenGlassReady export was removed with its whole surface.
  • Argument-key parity: callTimeDiffs for write now accepts the path argument key as a fallback (the row's path extraction already did) — a write schema variant can no longer produce a diff-less card.
  • Dispatch dedupe precision: code-dispatch sub-call dedupe is keyed by rootCallId + subCallId instead of the sub id alone, so equal sub ids under different roots stay distinct.
  • Event-shape guard: a tool/result with an empty content array returns instead of throwing; dispatch isError semantics align with the official childResult (only an explicit true counts as errored).
  • Fence-API link-swap hardening: the host read/write sequence re-verifies realpath after the read and before the destructive undo step — a symlink swapped in mid-flight is rejected (bytes already read are never returned) instead of landing elsewhere.
  • BOM in the display layer only: files.read strips a leading UTF-8 BOM for rendering so the first diff line carries no invisible U+FEFF; undo paths keep the original bytes byte-for-byte.
  • Fetch timeout: fence-API calls abort after 10s — a hung host no longer leaves a pane in "loading" forever.
  • Deterministic release assets: the release workflow selects the versioned tarball by name shape (dsh-diff-stat-<version>.tgz) instead of trusting directory order.

Infrastructure / 基建

  • Check-script coverage: the alignment check gained write argument-key fallback assertions for both file_path and path shapes, so the parity fix cannot regress.

中文说明

第三个版本。本版把「长行截断」从根上修掉,diff 宽度改为跟随会话列(不再固定 720px),并逐条闭环了整库代码审查的每一项发现:

  • 长行完整可读:diff 窗的滚动容器此前带 width: max-content,容器自身被最宽的行撑开——滚动条永远不出现,长行被圆角外壳静默裁剪。现容器恢复跟随父级,行宽只在行上生效;横向滚动条正常出现,+/− 染色在滚动时铺到行尾。
  • diff 宽度跟随会话列:轮末卡审查 diff 不再有 720px 像素上限——作为消息列的块级子元素,宽度跟随 --dsh-chat-content-width(desktop 壳允许用户把会话列调到 40–95%,侧边栏插件开合与窄窗同样自适应)。标准 dsh web 的 748px 布局与旧版逐像素一致(698px),已用超长行与 flex 链路实测验证。
  • 文件图标主题自适应:中性文件轮廓的折角高亮由硬编码白描边(浅色主题下不可见)改为 currentColor 35% 透明度。

修复

  • 行内 edit/write 行的路径被省略后 hover 可见全文(title),与轮末卡文件名一致。
  • 轮末卡每渲染重算各文件 diff 统计 → 按文件列表记忆化(每文件一趟 DP,与接管行口径对齐)。
  • 内嵌查看的硬编码中文改走 diff-stat 字典;未被使用的 whenGlassReady 导出整体删除。
  • callTimeDiffs 的 write 分支兜底 path 参数键(行摘要早已如此)——参数键变体不再产生无 diff 的卡片。
  • code-dispatch 子调用去重键由 subCallId 改为 rootCallId+subCallId:不同 root 下的相同子 id 不再互相误伤。
  • tool/result 内容为空数组时安全返回而非抛错;dispatch 的 isError 语义与官方 childResult 对齐(仅显式 true 视为失败)。
  • 围栏 API 链接交换加固:host 读取后、撤销写前复验 realpath——中途被替换的符号链接被整体拒绝(已读字节绝不返回),而不是落到别处。
  • BOM 只在显示层剥离files.read 渲染前剥首部 UTF-8 BOM(首行不再带隐形 U+FEFF);撤销路径保留原字节。
  • 请求超时:围栏 API 调用 10s 中止——host 挂起不再让面板永久转圈。
  • 构建产物确定性:发布工作流按名称形态选择版本化 tarball(dsh-diff-stat-<version>.tgz),不依赖目录排序。

基建

  • 检查脚本新增 write 参数键兜底断言(file_pathpath 两种形态),防止对齐修复回退。

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Aug 16:06

dsh-diff-stat v0.1.0

Second release. One shared LCS arithmetic for badge, body and footer, full coverage for the minimal preset's str_replace_editor, a summary card for pure Code-Mode turns, real file context around PTC fragments, and a self-contained build — plus fixes for a render-loop freeze and Explorer's reveal action.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • One arithmetic — badge, body, footer: the inline badge and the window footer now count the real changed lines from the same LCS walk the diff renders — locator/context lines shared by both sides count nowhere, so a +6 −4 badge can no longer open as two green rows. Running rows keep the argument estimate; settled rows switch to the exact result-view hunks.
  • Minimal preset & str_replace_editor: the minimal preset's editor joins the takeover keys — its create / str_replace / insert commands map to the same hunk shapes over path / old_str / new_str / file_text (the read-only view renders through the row body as before).
  • Code-Mode turns get their card: dispatch sub-calls carry no turn coordinate, so a pure Code-Mode turn never showed a summary card. The accumulator flags run_code turns, and the card joins their files from the stock chat tool tree — the tool-call nodes fold every dispatch into its root call's subCalls — merged with native files for display and undo.
  • Real file context for PTC fragments: argument-derived hunks are marked by object identity; on expand the booster reads the file through the fenced API (LRU-cached), locates the fragment's post-image and rebuilds it with up to ±3 shared lines per side. Best-effort — unlocatable fragments render bare, and totals are unaffected.
  • Aligned diff window: both sides are LCS-aligned before rendering — shared lines become ±3 context around each change, untouched runs fold into , the window scrolls instead of collapsing, and the footer counts exactly the rendered rows.

Fixes / 修复

  • Render-loop freeze on Code-Mode turns: reviewing a second file froze the page beyond refresh. Three identity hazards chained into an endless render loop — the chain select rebuilt its match array every render, the join selector returned a fresh array under uSES's Object.is equality, and the boost effect keyed on churning state. The select is now memoized per published data, the selector returns the snapshot itself with extraction in a memo, and the boost effect keys on user interaction only; native-only turns never wrote state, which is why they were immune.
  • "Reveal in Explorer" opened the default view: spawn's array form re-escapes the embedded quotes of explorer's /select,"<path>" syntax, and explorer — seeing a mangled argument — falls back silently. Both openers pass their literal command line through the shell now, with quote and % rejected up front (cmd expands %VAR% inside quotes).
  • UTF-8 read-cap boundary: files.read's 512 KiB cap could cut mid-sequence and turn the truncated tail into U+FFFD; the cap now slices at the last complete sequence boundary.
  • npm script-shell pin moved to the user npmrc (a repo file broke Linux CI); Windows checkout paths are translated for the build.

Infrastructure / 基建

  • Self-contained build (build!): the checkout-coupled bash + junction pipeline is gone — one tsdown run builds both halves, every dependency resolves inside the project, and lib/ stays committed for github: direct installs. CI verifies typecheck, the diff-alignment assertions and a committed-lib freshness gate; the release workflow attaches a versioned tarball plus the fixed-name dsh-diff-stat.tgz.
  • Check-script coverage: 15 assertion groups now cover the aligner, the badge arithmetic, the PTC join, the context booster, the editor command mapping and the turnTail claim decision — pure functions live in the zero-dependency turn-merge module so the script can reach them directly.

中文说明

第二个版本。本版把「数字与渲染一致」做成硬约束,并把覆盖面补齐到极简预设与纯 Code-Mode 轮:

  • 同一套算术——徽标、正文、页脚:行内徽标与窗口页脚改为统计真实变更行数(与渲染共用同一趟 LCS),两侧共同的定位/上下文行不再计数——「+6 −4 展开只有两行绿」的口径分裂从根上消除;运行中保持参数预估,结算后精确。
  • 极简预设与 str_replace_editor:极简预设的编辑器加入接管键,create / str_replace / insertpath / old_str / new_str / file_text 映射为同样的 hunk 形态(只读 view 照旧走行体渲染)。
  • 纯 Code-Mode 轮也有汇总卡:dispatch 子调用没有轮坐标,此前纯 PTC 轮从不显示轮末卡;现在聚合器标记 run_code 轮,卡片从 stock 会话工具树 join 出其文件(tool-call 节点已按 rootCallId 折叠 subCalls),与原生文件合并展示并参与撤销。
  • PTC 片段的真实文件上下文:参数来源的 hunk 按对象身份标记;展开时经围栏 API(LRU 缓存)读取文件、定位片段 after 形态并以每侧至多 ±3 行共享行重建。尽力而为:无法定位的片段保持原样,统计不受影响。
  • 对齐 diff 窗口:渲染前两侧 LCS 对齐——共同行作 ±3 上下文、未变更折叠 、窗口滚动替代折叠,页脚与正文完全同源。

修复

  • Code-Mode 轮点第二个文件的「审查」导致页面卡死且刷新无效——三重身份不稳定链成无限渲染循环(链 select 每渲染重建数组、join selector 在 uSES 的 Object.is 相等下返回新数组、boost effect 依赖抖动状态);现 select 按发布数据记忆化、selector 返回快照自身并在 memo 中提取、boost 只由用户交互触发。纯原生轮不写状态,因此免疫。
  • 「在资源管理器中显示」只打开默认视图——spawn 数组形式会再转义 /select,"<path>" 的引号导致 explorer 静默回退;两个打开器改为 shell 字面量传参,并预先拒绝引号与 %(cmd 在引号内展开 %VAR%)。
  • files.read 的 512 KiB 截断可能切断 UTF-8 序列产生 U+FFFD;现按最后完整序列边界截取。
  • npm script-shell 固定迁移到用户 npmrc(仓库内文件曾破坏 Linux CI);Windows 检出路径已转换。

基建

  • 自包含构建(build!:移除依赖 harness 检出的 bash + junction 构建链——一次 tsdown 构建双端,全部依赖落在项目内,lib/ 入库支持 github: 直装;CI 校验 typecheck、diff 对齐断言与入库 lib 的新鲜度门,release 工作流附加版本号 tarball 与固定名 dsh-diff-stat.tgz
  • 检查脚本覆盖:15 组断言覆盖对齐引擎、徽标算术、PTC join、上下文增强、编辑器命令映射与 turnTail 认领决策(纯函数集中于零依赖的 turn-merge 模块,脚本可直接触达)。

v0.0.1

Choose a tag to compare

@github-actions github-actions released this 25 Aug 09:57

dsh-diff-stat v0.0.1

First release. Inline +N −M diff badges on edit/write tool rows, a per-turn file change summary card with review / undo / open-with actions, scroll-windowed diffs with LCS context folding, and an optional frosted-glass integration with deepseek-harness-background.

Install / 安装

# from npm / 从 npm 安装
dsh plugin --profile web add dsh-diff-stat

# or from GitHub / 或从 GitHub 安装
dsh plugin --profile web add github:HaoyueQin/dsh-diff-stat

Uninstall:

dsh plugin --profile web remove dsh-diff-stat

Highlights / 亮点

  • R1 — Inline diff badges: takes over the stock edit/write rows (keyed lower-priority shadow; uninstall restores stock automatically). Running rows show an argument-derived estimate; settled rows switch to exact result-view hunks. Click a row to expand a scroll-windowed unified diff.
  • R2 — Per-turn summary card: a collapsible "N files changed +X −Y" bar at each turn tail; expands to per-file rows with per-type icons, ±lines, review / open | ▾ split button, and an inline height-capped file preview. Same-file edits merge within a turn.
  • PTC / Code Dispatch fallback: nested sub-calls carry no wire diff views; the plugin derives call-time diffs from the tools' own presentCall semantics. rootCallId+subCallId dedup keeps replays from double-counting.
  • Undo: reverts a turn's files to their pre-turn state via reverse uniqueness-checked hunk peeling; deletes files the turn created; rejects drifted files atomically.
  • Context folding: each hunk's sides are LCS-aligned before rendering — shared lines become ±3 context around the change and untouched runs fold into . Badge and footer totals stay full-scope.
  • Frosted glass (optional): when deepseek-harness-background is installed, every plugin surface joins its unified glass recipe (diff window / file preview / row IN-OUT card in token mode, turn summary card in fill mode). Without it the stock opaque look is untouched — graceful degradation, zero dependencies.
  • Host half (optional): a same-origin fenced API serves files.read / undo / open-with with realpath containment, symlink rejection, UTF-8 round-trip validation and atomic writes. Absent host half hides the dependent buttons.

Fixes / 修复

  • Publish turn Location data under the definition's own kind, so history replay no longer stalls the conversation pipe.
  • Claim the conversation.chat.turnTail chain ahead of ui-deliverables (priority −1, first-wins).
  • Render the open menu through a portal out of the card's overflow: hidden clip.
  • Re-register glass surfaces on bridge hot reload (persistent dsh-background-glass:ready subscription).

Infrastructure / 基建

  • lib/ committed for github: direct installs; prepack rebuilds host + client before npm pack.
  • CI (ci.yml): push/PR builds a pinned deepseek-harness checkout, then typecheck / diff-alignment / committed-lib freshness gate.
  • Release (release.yml): pushing a v* tag runs the same verification, packs, and attaches both a versioned tarball and a fixed-name dsh-diff-stat.tgz to the GitHub Release.

中文说明

首个版本。核心能力:

  • 行内 +N −M 徽标(R1):接管 stock 的 edit/write 工具行,运行中用参数推导预估、结算后切换为 resultView 精确值;点击行展开限高滚动的 unified diff。
  • 轮末汇总卡(R2):每轮尾部折叠条「N 个文件已更改 +X −Y」,展开逐文件行(分类型图标 · ±行数 · 审查 · 打开|▾),点「打开」内嵌限高文件预览;同文件多次编辑合并。
  • PTC / Code Dispatch 兜底:嵌套子调用没有 wire diff 视图,插件按工具自身语义从参数推导调用时 diff,rootCallId+subCallId 去重防重放双计。
  • 撤销:hunk 链倒序唯一性回剥,删除本轮新建文件,漂移拒绝写入,原子提交。
  • 上下文折叠:展开前 hunk 两侧做行级 LCS 对齐,共同行作 ±3 上下文、更远未变更折叠为 ;徽标与页脚统计保持全量口径。
  • 可选毛玻璃:安装 deepseek-harness-background 后全部表面并入其共享玻璃配方(diff 窗 / 文件预览 / IN-OUT 卡 token 模式,轮末卡 fill 模式);未安装时保持原样,零依赖优雅降级。
  • 可选 host 半:同源围栏 API 提供 files.read / undo / open-with(realpath 包含、拒绝符号链接、UTF-8 回环校验、原子写);缺席时相关按钮自动隐藏。

修复:turn Location 数据按定义自身 kind 发布(历史回放不再卡住);turnTail 链以 priority −1 先于 ui-deliverables 认领;打开菜单经 portal 渲染避免被卡片裁剪;毛玻璃桥热重载后自动重新注册。

基建lib/ 入库支持 GitHub 直装,prepack 保证发布前重建;CI 校验 typecheck / diff 对齐 / lib 与源码一致;推 v* tag 自动构建并把版本号 tarball 与固定名 dsh-diff-stat.tgz 附到 GitHub Release。