Skip to content

v0.1.4

Choose a tag to compare

@github-actions github-actions released this 31 Aug 06:57
· 11 commits to main since this release

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 零漂移」后自动出包。