better-dsh 0.2.2-c → 0.2.3-c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/docs/50_test-reports/2026-09-06-write/345/267/245/345/205/267sandbox/345/215/207/347/272/247/351/200/217/344/274/240bug/345/244/215/345/217/221/345/217/212/346/214/202/350/265/267-/344/272/213/344/273/266/346/212/245/345/221/212.md +133 -0
  2. package/docs/50_test-reports/2026-09-08-hashline-edit-E_RANGE_UNVERIFIED/350/267/250/350/275/256/344/274/232/350/257/235/351/224/256/345/244/261/346/225/210-/350/257/212/346/226/255/346/212/245/345/221/212.md +226 -0
  3. package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-local-test-report.md +44 -0
  4. package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-report.md +110 -0
  5. package/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
  6. package/docs/50_test-reports/v0.2.3b-hashline-content-locator/345/256/236/346/265/213/346/212/245/345/221/212.md +73 -0
  7. package/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
  8. package/lib/client/index.js +60 -51
  9. package/lib/index.d.ts +2 -3
  10. package/lib/index.js +1203 -1278
  11. package/package.json +2 -2
  12. package/docs/50_test-reports/v0.1.8d_artifacts/README.md +0 -138
  13. package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  14. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  15. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  16. package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +0 -592
  17. package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  18. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  19. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  20. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  21. package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  22. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  23. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  24. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  25. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  26. package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +0 -5
  27. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  28. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  29. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  30. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  31. package/docs/60_exploration-and-research/01-cordis-runtime/bun-compile-cordis-runtime-bootstrap-research.md +0 -536
  32. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-customization-and-override-mechanics.md +0 -418
  33. package/docs/60_exploration-and-research/01-cordis-runtime/cordis-research.md +0 -350
  34. package/docs/60_exploration-and-research/01-cordis-runtime/dsh-cordis-hotplug-mcp-patch-research.md +0 -265
  35. package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-profile-package-map.md +0 -186
  36. package/docs/60_exploration-and-research/02-dsh-webui/dsh-web-ui-slot-system-research.md +0 -310
  37. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-backend-data-inventory.md +0 -633
  38. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-strip-boundary-research.md +0 -300
  39. package/docs/60_exploration-and-research/02-dsh-webui/dsh-webui-wire-appendix.md +0 -3729
  40. package/docs/60_exploration-and-research/02-dsh-webui/web-frontend-composability-research.md +0 -191
  41. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/capture-live-turn.json +0 -1
  42. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/observed-endpoints.json +0 -224
  43. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/remote-inventory.json +0 -110954
  44. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/served-index-sample.html +0 -47
  45. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/session-events.json +0 -9411
  46. package/docs/60_exploration-and-research/02-dsh-webui/webui-wire-data/ws-frame-examples.json +0 -20
  47. package/docs/60_exploration-and-research/03-mobile-ios/dsh-mobile-spa-ios-input-experience-research.md +0 -160
  48. package/docs/60_exploration-and-research/03-mobile-ios/ios-chat-app-bridge-research.md +0 -324
  49. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-jsonl-mapping.md +0 -1532
  50. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode-failed.json +0 -46
  51. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode1.json +0 -1124
  52. package/docs/60_exploration-and-research/04-session-storage/alpha5-compaction-sample/episode2.json +0 -1240
  53. package/docs/60_exploration-and-research/05-dashr-dev/plugin-development.md +0 -148
  54. package/docs/60_exploration-and-research/05-dashr-dev/upstream-alignment.md +0 -102
  55. package/docs/60_exploration-and-research/README.md +0 -87
  56. package/docs/60_exploration-and-research/bun-compile-cordis-runtime-bootstrap-research.md +0 -348
  57. package/docs/60_exploration-and-research/cordis-research.md +0 -350
  58. package/docs/60_exploration-and-research/dsh-mobile-spa-ios-input-experience-research.md +0 -160
  59. package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +0 -186
  60. package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +0 -310
  61. package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +0 -300
  62. package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +0 -324
  63. package/docs/60_exploration-and-research/web-frontend-composability-research.md +0 -191
@@ -0,0 +1,73 @@
1
+ # v0.2.3b hashline-content-locator 实测报告
2
+
3
+ > 2026-09-08 · 环境:DSH 4999 dev 线(upstream checkout `0.1.3-alpha.2-82a5fd6-dirty`,
4
+ > `DSH_HOME=~/.workspaces/dashr/.dsh-test` 语义路径 `.dsh-test`),better-dsh vendored
5
+ > hashline 桥(change `2026-09-08-v0-2-3b-hashline-content-locator`)。
6
+ > 前置:诊断报告 `2026-09-08-hashline-edit-E_RANGE_UNVERIFIED跨轮会话键失效-诊断报告.md` §7。
7
+
8
+ ## 0. 一句话结论
9
+
10
+ 五项裁决全部落地并实测通过:served 账本去 session 化(schema v7,path 主键)、集中存储
11
+ `$DSH_HOME/storages/dsh-better-edit/`、verifyServedRange 内容快道、write 回放移除、失败文案
12
+ 修正。单测 12/12 新增全绿、全量 491 过 2 挂(挂项为先于本改动存在的上游类型漂移,stash 基线
13
+ 复跑证实);4999 真实 agent session 第一人称实测:write 只回确认信封(无锚点回放)、read 记账
14
+ 进中心库(served 表 `path,hashes,reported,updated_at`,无 session_id 列)、跨会话 edit 链路
15
+ 走通、全程无任何 `.dsh_better_edit` 点目录。
16
+
17
+ ## 1. 单元层(canonical,`npx vitest --run`)
18
+
19
+ - 新增 `test/hashline-store.spec.ts` **12/12 绿**:v7 中心库落位与无点目录断言、path 主键
20
+ upsert 合并、跨"会话"上下文免 read 取行(fork 模拟)、drift 标记随 path、v6→v7 迁移重建
21
+ ( handmade 旧库打开后 `session_id` 列消失、version=7)、TTL prune、verifyServedRange 六态
22
+ 矩阵(账本未见→内容快道通过;账本全知匹配→过;内部漂移→`E_RANGE_STALE`;账本洞→
23
+ `E_RANGE_UNSERVED`;单边账本→`E_RANGE_UNVERIFIED`;拒绝文案含"Read the file once…
24
+ resubmit the whole batch")。
25
+ - 全量:**491 passed / 2 failed**,2 挂项(`handlers/agent.ts` `snapshotEvents`、
26
+ `SessionHeader.isSeeded`)经 `git stash` 基线复跑**证实先于本改动存在**(上游 alpha.2 对齐
27
+ 类型漂移,非本 change 引入;tsc 同样仅此 3 条既有错)。
28
+
29
+ ## 2. 构建(monorepo 副本)
30
+
31
+ - rsync(AGENTS exclude 表)→ `pnpm --filter better-dsh exec tsdown` → **9 files 529.98 kB**,
32
+ `lib/index.js` 形态正确 → `tsx scripts/build-client.ts` → `lib/client/index.js`
33
+ 17.82 kB(md5 `a88850ec056aae943934adfdeb79347e`,client 半零改动)。
34
+ - **教训(新增坑,已亲历)**:直接以 `node_modules/.bin/tsdown` 裸跑(不经 pnpm workspace env)
35
+ 会产出 `.mjs` 形态(7 files),boot 即 `ERR_MODULE_NOT_FOUND lib/index.js`——**必须用
36
+ `pnpm --filter better-dsh exec tsdown`**;且 `--delete` rsync + tsdown clean 会连带重置副本
37
+ 配置与 lib(本次已重建,副本 package.json/tsdown.config 现与 canonical 一致)。
38
+
39
+ ## 3. 4999 第一人称实测(真实 agent session,CDP 驱动 GUI)
40
+
41
+ 工作区 `/home/u1`(GUI 工作区选择器未绑到 ws-probe,落在默认 home 桶——不影响断言),
42
+ 模型 DeepSeek-V4-Flash。三段剧本:
43
+
44
+ | 步 | 动作 | 断言 | 结果 |
45
+ |---|---|---|---|
46
+ | S1 | write 创建 `probe-v023b.md`(6 行规格内容) | write 结果**无** `--- Auto-read (hashline anchors) ---` 段,仅确认信封 | ✅(transcript 仅 "Produced probe-v023b.md") |
47
+ | S1 | read 全文 | 锚点记账进**中心库** | ✅ `.dsh-test/storages/dsh-better-edit/hash-store.sqlite`(+WAL)出现;served 表列 `path,hashes,reported,updated_at`,**无 session_id**;单行 `path=/home/u1/probe-v023b.md → ["Udx","nyO","zlr","DBc","Zuy","GTH"]` |
48
+ | S2(**新会话**,不同 session id,从未观察/读过该文件) | 直接 edit(锚点 zlr/zlr 来自 S1) | 旧代码此处必 `E_RANGE_UNVERIFIED` | ⚠️ 见 §4——被**宿主层另一道闸**前置拦截 |
49
+ | S2 | read 一次后同参数 edit | 成功落盘 | ✅ 文件第 3 行 = `beta line EDITED-BY-v0.2.3b-PROBE`;无任何 E_RANGE_* |
50
+
51
+ 存储探针:`/home/u1/.dsh_better_edit` **不存在** ✓(home 即 workspace,dot-dir 若仍会创建必然在此)。
52
+
53
+ ## 4. 实测发现:宿主 fs 观察策略是跨会话 edit 的另一道(设计内)闸
54
+
55
+ S2 盲 edit 返回 `[E_NOT_OBSERVED] The file has not been observed in this session
56
+ (read-before-write policy). Call read() first` ——这是 **`dsh-fs-observation-policy` 宿主插件**
57
+ 的 observed-state 守卫(owner=agent 会话的 WeakMap,read/write/edit 记版本),**不是** hashline
58
+ served 账本。定性:
59
+
60
+ - **保留**(user 裁决语义:"安全守卫在确认覆盖/见过"——read-before-edit 正是宿主层的"见过");
61
+ 本 change 的范围是把 hashline 层的**重复**session 账本拿掉,不是拆宿主守卫。
62
+ - 事故剧本(S1 write → fork 子会话 edit)在原线上之所以先报 hashline 错,是 fork 继承了观察态;
63
+ hashline 层修复后,**同进程 fork 续聊**的 edit 将直接由内容快道放行(fork 不再需要冗余 read)。
64
+ - 全新无关会话(如本 S2)盲 edit 被宿主拦——符合"读过才许改"的常理,非回归。
65
+
66
+ ## 5. 残留与移交
67
+
68
+ - 预置 guidance 覆盖目录现种子于 `storages/dsh-better-edit/`(ensurePresetGuidance 同目录)——
69
+ 与 store 同居一处,属可接受的组织形态。
70
+ - 旧 12 个 `<workspace>/.dsh_better_edit/` 弃置未删(TTL 语义自然清空;物理清理留 user 决定)。
71
+ - 4999 实例已停本探针产物:`/home/u1/probe-v023b.md` 与 `.scratch/ws-probe/` 已清理。
72
+ - **发布闸状态**:a 第一人称实测 ✅ → b 本报告 ✅ → **c user 明确确认放行 ⏳**(单次有效;
73
+ 未 commit、未 tag、未 publish)。
@@ -0,0 +1,156 @@
1
+ # upstream dsh npm 版本对账:prod 0.1.3-alpha.2 → 0.1.5-rc.2
2
+
3
+ > 生成时间:2026-09-10(本地时区)
4
+ > 数据源:npm registry(`@deepseek-ai/dsh`)元数据 + `upstream/deepseek-harness` git tag 对账
5
+ > 目标:回答「npm 上比 prod 更高的版本是什么、diff 有多大、对 prod 意味着什么」
6
+
7
+ ---
8
+
9
+ ## 〇、一句话结论
10
+
11
+ prod 当前跑 **`@deepseek-ai/dsh@0.1.3-alpha.2`**。npm 上比它高的版本是整条 **0.1.5 线**(`alpha.1 / alpha.2 / rc.1 / rc.2`,**0.1.4 从未发布,直接跳号**)。最高版本是 **`0.1.5-rc.2`**(挂在 `next` dist-tag,而 `latest` 还停在 `0.1.5-rc.1`)。
12
+
13
+ 这条 0.1.5 线是**大版本级聚合**:846 commits、3170 文件、约 10.4 万行新增。核心是 **Session 格式 v3 重写**(会话持久化契约变更,对 prod 是**破坏性升级,不可 drop-in**),外加 Electron 桌面打包、Sidebar/dockkit 重构、文件交付「present」工具、图渲染预览、模型默认值切换(DeepSeek V41 Flash)等一批功能。**升级 prod 前必须按 AGENTS.md §一/§二 走对齐轮,不能只换版本号。**
14
+
15
+ ---
16
+
17
+ ## 一、版本全景
18
+
19
+ npm registry 当前 dist-tags:
20
+
21
+ | dist-tag | 指向版本 |
22
+ |---|---|
23
+ | `latest` | 0.1.5-rc.1 |
24
+ | `next` | **0.1.5-rc.2**(最高) |
25
+ | `alpha` | 0.1.5-alpha.2 |
26
+
27
+ 比 prod(0.1.3-alpha.2)更高的版本,按发布顺序:
28
+
29
+ | 版本 | npm 发布时间 (UTC) | dist-tag |
30
+ |---|---|---|
31
+ | 0.1.5-alpha.1 | 2026-09-08 15:57 | — |
32
+ | 0.1.5-alpha.2 | 2026-09-09 14:41 | `alpha` |
33
+ | 0.1.5-rc.1 | 2026-09-10 03:12 | `latest` |
34
+ | **0.1.5-rc.2** | **2026-09-10 14:57** | `next` |
35
+
36
+ > 注意点:`latest` 并不指向最高版本(rc.1 vs rc.2);「最高版本」= `next` 上的 **0.1.5-rc.2**。0.1.4 未在 npm 出现过。
37
+
38
+ 对应 git tag(本地 `upstream/deepseek-harness`,已 fetch):
39
+
40
+ ```
41
+ dsh-v0.1.3-alpha.2 2026-09-07 19:45 +0800 ← prod 当前
42
+ dsh-v0.1.5-alpha.1 2026-09-08 23:25 +0800
43
+ dsh-v0.1.5-alpha.2 2026-09-09 22:13 +0800
44
+ dsh-v0.1.5-rc.1 2026-09-10 09:36 +0800
45
+ dsh-v0.1.5-rc.2 2026-09-10 21:50 +0800
46
+ ```
47
+
48
+ ---
49
+
50
+ ## 二、diff 规模
51
+
52
+ `dsh-v0.1.3-alpha.2 .. dsh-v0.1.5-rc.2`:
53
+
54
+ | 指标 | 值 |
55
+ |---|---|
56
+ | commits | **846** |
57
+ | 文件 | 3170 changed |
58
+ | 行 | +103,990 / −17,687 |
59
+ | 源码侧(排除 snapshots/tests) | 2474 文件,+68,818 / −13,973 |
60
+
61
+ 分段 commit 分布:
62
+
63
+ | 区间 | commits |
64
+ |---|---|
65
+ | 0.1.3-alpha.2 → 0.1.5-alpha.1 | 563(大头,聚合了 Session V3 与一堆 feature) |
66
+ | 0.1.5-alpha.1 → 0.1.5-alpha.2 | 262 |
67
+ | 0.1.5-alpha.2 → 0.1.5-rc.1 | 17 |
68
+ | 0.1.5-rc.1 → 0.1.5-rc.2 | 4(收尾/backport) |
69
+
70
+ ---
71
+
72
+ ## 三、依赖面变化(对 prod 直接可见)
73
+
74
+ prod 0.1.3-alpha.2 有 **71 个 dependencies**,0.1.5-rc.2 有 **72 个**。差异:
75
+
76
+ 1. **新增运行期包 `@deepseek-ai/dsh-tool-present`**(`packages/fs/tool-present`)——新「present」工具:把 agent 产出的文件以不可变交付卡片(download card)呈现,是文件交付特性的宿主半。
77
+ 2. `apps/cli` devDeps 新增 `@deepseek-ai/dsh-agent-loop`、`@deepseek-ai/dsh-agent-loop-testkit`(内部,不影响 prod 运行面)。
78
+ 3. 新增 client 包 `ui-deliverables`(`PresentRow` / `PresentedFileCard` / `present-open`),属 web shell 交付卡片 UI。
79
+ 4. 其余全部 `@deepseek-ai/*` 依赖整体从 `^0.1.3-alpha.2` 抬到 `^0.1.5-rc.2`(同版本号齐步,无个别漂移)。
80
+ 5. 底层 `cordis` / `schemastery` / `commander` / `js-yaml` 等版本**未变**(`cordis ^4.0.2`、`schemastery ^3.18.2` 等,与 0.1.3-alpha.2 相同)。
81
+
82
+ ---
83
+
84
+ ## 四、主要变更主题(按 prod 相关度排序)
85
+
86
+ ### 1. Session 格式 v3 重写(⚠ 破坏性,最高风险)
87
+ `session-log-v3` 工作线,是本次最大的变更块。要点:
88
+
89
+ - 会话身份 **V2 → V3 迁移**(`feat(session): add identity V2-to-V3 migration and writer skeleton`)。
90
+ - system prompt 表示为 **surface node zero**(`refactor(session): represent the system prompt as surface node zero`)。
91
+ - **canonical envelopes**、PTC durable vocabulary、in-history system prompt 表示、JSONL 跨进程写所有权(lease)。
92
+ - 大量 `session.v3.jsonl` 快照与 V2/V3 迁移覆盖面单测。
93
+
94
+ > **对 prod 的含义**:会话持久化契约改变。上一轮(0.1.3-alpha.2 对齐)已实测:上游 tag diff 会打到 `session-persistence-omp.ts` / `replay.ts` / store 的 handle+lease 契约(见 2026-09-08 对齐报告)。**0.1.5 的 V3 比 0.1.3 的 V2 更进一步,破坏面更大**,`better-dsh` / `omp-web` 这类桥接会话数据的插件必须重新对齐,不能 drop-in。
95
+
96
+ ### 2. Electron 桌面打包(对 3080 web 无直接作用)
97
+ Windows/macOS/Linux 构建、mac 签名+公证、Windows 签名、auto-update、IPC 性能优化。纯桌面宿主线,与本机 `dsh web`(3080)部署无关,但意味着上游发布面从此多一个桌面产物。
98
+
99
+ ### 3. Sidebar / dockkit 重构
100
+ - `dockkit` 可逆停靠引擎、pointer 交互。
101
+ - 全局 sidebar panel、tab 导航、live tab 标题 + 文件类型图标、末 tab 关闭规则、响应式右栏、全屏 shell。
102
+ - session-log 控制移入 header「更多」菜单。
103
+
104
+ ### 4. 文件交付「present」工具 + 文档预览
105
+ - 新 `dsh-tool-present` 包:不可变文件交付下载卡片、artifact 卡原生文件动作、workspace 文件操作。
106
+ - 可扩展文档预览、文本预览分页 tab、文件类型图标集、`ui-deliverables` client 卡。
107
+ - `feat(fs)`:bounded byte-range reads(fs-local / fs-e2b)、dual-face 文件 API。
108
+
109
+ ### 5. 图表 / Markdown 预览
110
+ Chat 代码块内预览 Mermaid / Graphviz / SVG / HTML fence,适配应用主题。
111
+
112
+ ### 6. LLM 模型默认值切换(⚠ 影响 prod 行为)
113
+ - Chat Completions 默认切到 **DeepSeek V41 Flash**(`feat(llm): default Chat Completions to DeepSeek V41 Flash`)。
114
+ - 保留 V4 模型、恢复 V4 Flash Vision Exp catalog 条目。
115
+ > prod 若升级,默认模型会跟着变;需确认是否期望。
116
+
117
+ ### 7. Feedback 对话框
118
+ `/feedback` 与 Dislike 统一为一个带分类的对话框 + toast。
119
+
120
+ ### 8. Subagent catalog
121
+ 记录并观察 parent-owned child catalog(子代理目录)。
122
+
123
+ ### 9. native system / node-addon-system
124
+ 包族改名 `node-addon-system`,预编译 Node-API flock、Landlock capability 子路径。**新增原生依赖面,升级安装需留意 prod 机上的原生构建/预编译匹配**(本机已有一处 zeromq allowBuilds 特例,见 AGENTS.md §二)。
125
+
126
+ ### 10. minimal profile 行为调整
127
+ - `str_replace_editor` 从 minimal profiles 移除。
128
+ - persistent bash 输出与 one-shot shell 契约对齐。
129
+ > 只影响 minimal profile,不影响 prod `web` profile 的默认工具集。
130
+
131
+ ### 11. 其它
132
+ - CLI:从 shipped 模板创建 profile。
133
+ - skills:Playwright 视频录制 GIF。
134
+ - 内部 CI/审查自动化(weighted PR approval、review owner 排名等)——与 prod 运行无关。
135
+
136
+ ---
137
+
138
+ ## 五、对 prod 升级的风险评估(简要)
139
+
140
+ | 风险项 | 级别 | 说明 |
141
+ |---|---|---|
142
+ | Session V3 格式迁移 | 🔴 高 | 会话持久化契约变更;`better-dsh`/`omp-web` 会话桥接面需重新对齐,先例(0.1.3 V2)已证实非 drop-in |
143
+ | 模型默认切 V41 Flash | 🟠 中 | 默认行为变化,需 user 确认是否接受 |
144
+ | 新原生依赖(node-addon-system) | 🟡 中低 | 安装面原生构建/预编译匹配;本机 pnpm strictDepBuilds/allowBuilds 需复核 |
145
+ | 新工具 `dsh-tool-present` | 🟡 中低 | 新工具进入 agent 运行时,需确认与现有工具/插件无 id 冲突 |
146
+ | Sidebar/dockkit UI 重构 | 🟢 低(功能面) | 纯增量 UI,但 better-dsh 的 mobile 手势/侧栏 patch 需复测是否仍对齐 |
147
+ | Electron 桌面 | ⚪ 无关 | 不影响 web 部署 |
148
+
149
+ ---
150
+
151
+ ## 六、建议
152
+
153
+ 1. 本次**只做对账、不做升级**:0.1.5 是聚合大版本,且含 Session V3 破坏性契约变更,不能当「换版本号」处理。
154
+ 2. 若后续要升级,按 AGENTS.md §一/§二走 **Dev/Test 1(4999 源码级)对齐轮**:切 `dsh-v0.1.5-rc.2` → 重放三处本地 patch(storeDir / unrun devDep / resolveRepositoryRoot)→ install/build → 插件契约对齐(重点 `session-persistence-omp.ts`/`replay.ts`/store 的 V3 handle+lease)→ tsc/单测 → 4999 第一人称实测 → 报告落 `docs/50_test-reports/` → user 确认 → 才动 prod 3080。
155
+ 3. 升级目标版本**首选 `0.1.5-rc.2`(`next`)而非 `latest`(rc.1)**,因为 rc.2 才是最高版本;但 rc 阶段仍建议等上游正式 stable 后再定。
156
+ 4. 升级前单独确认模型默认值(V41 Flash)是否要在 prod 生效。
@@ -69,7 +69,7 @@ const zh = {
69
69
  };
70
70
 
71
71
  //#endregion
72
- //#region \0dsh-css:/home/u1/workspaces/dashr/dashr/src/failover/client/FailoverRow.module.css.mjs
72
+ //#region \0dsh-css:/home/u1/workspaces/dashr/upstream/deepseek-harness/packages/better-dsh/better-dsh/src/failover/client/FailoverRow.module.css.mjs
73
73
  const css = "._440e1d7b_row {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 0;\n}\n\n._9865b509_title {\n font-weight: 600;\n font-size: 14px;\n}\n\n._3cfec826_slots {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n._70954771_slot {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._ba1fd839_slotLabel {\n min-width: 88px;\n flex-shrink: 0;\n font-size: 13px;\n color: var(--dsw-alias-text-secondary, #666);\n}\n\n._11c2662d_select {\n flex: 1;\n max-width: 280px;\n min-width: 0;\n}\n\n._b7c358f9_alert {\n color: var(--dsw-alias-danger, #c0392b);\n font-size: 12px;\n}\n";
74
74
  const tagId = "better-dsh/FailoverRow.module.css";
75
75
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
@@ -185,14 +185,12 @@ function FailoverRow({ catalog, loadConfig, save, t }) {
185
185
 
186
186
  //#endregion
187
187
  //#region src/mobile/gesture.ts
188
- /**
189
- * Resolved defaults — the `1706b81` constants (120 / viewport÷4 / 40 / 1.3 /
190
- * 768) plus the one addition, the velocity gate. A slow text-selection drag
191
- * runs ~0.13 px/ms; 0.15 px/ms filters those while any comfortable sweep
192
- * (0.4 px/ms and up) passes.
188
+ /** Resolved defaults — the `1706b81` constants (120 / viewport÷4 / 40 / 1.3)
189
+ * plus the one addition, the velocity gate. A slow text-selection drag runs
190
+ * ~0.13 px/ms; 0.15 px/ms filters those while any comfortable sweep (0.4
191
+ * px/ms and up) passes.
193
192
  */
194
193
  const DEFAULT_SWIPE_THRESHOLDS = {
195
- breakpoint: 768,
196
194
  swipeDistancePx: 40,
197
195
  dominanceRatio: 1.3,
198
196
  leftEdgeBandPx: 120,
@@ -200,16 +198,6 @@ const DEFAULT_SWIPE_THRESHOLDS = {
200
198
  swipeVelocityPxPerMs: .15
201
199
  };
202
200
  /**
203
- * Whether one completed gesture's viewport is in the gesture band.
204
- *
205
- * @param viewportWidth - viewport width at gesture time (px).
206
- * @param thresholds - resolved recognition thresholds (`.breakpoint`).
207
- * @returns `true` when `viewportWidth` is strictly below the breakpoint.
208
- */
209
- function isNarrowViewport(viewportWidth, thresholds) {
210
- return viewportWidth < thresholds.breakpoint;
211
- }
212
- /**
213
201
  * Whether a pointerdown may START a gesture — the source's pointerdown
214
202
  * gate, verbatim: with both panels closed, only the left band (X120) or
215
203
  * the right three quarters of the screen admit; with a panel open, any
@@ -275,7 +263,6 @@ function resolveMobileConfig(pageConfig) {
275
263
  const v = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
276
264
  return {
277
265
  enabled: true,
278
- breakpoint: n(pageConfig.breakpoint, DEFAULT_SWIPE_THRESHOLDS.breakpoint),
279
266
  swipeDistancePx: n(pageConfig.swipeDistancePx, DEFAULT_SWIPE_THRESHOLDS.swipeDistancePx),
280
267
  dominanceRatio: n(pageConfig.dominanceRatio, DEFAULT_SWIPE_THRESHOLDS.dominanceRatio),
281
268
  leftEdgeBandPx: n(pageConfig.leftEdgeBandPx, DEFAULT_SWIPE_THRESHOLDS.leftEdgeBandPx),
@@ -291,19 +278,32 @@ function readLeftCollapsed() {
291
278
  return document.querySelector("[data-sidebar-collapsed]") !== null;
292
279
  }
293
280
  /**
294
- * Better Sidebar's right-panel state, live off the body attribute the
295
- * plugin itself publishes (collapsed = closed). Read SYNCHRONOUSLY in the
296
- * handlers — a cached mirror lags the panel's own DOM write by a render,
297
- * and a close-swipe issued right after an open-swipe would misroute.
281
+ * The OFFICIAL right sidebar's state (0.1.5 ui-sidebar-right), read from
282
+ * AppFrame's TWO presentation facets, synchronously (a cached mirror lags
283
+ * the panel's own DOM write by a render, and a close-swipe issued right
284
+ * after an open-swipe would misroute):
285
+ *
286
+ * - `[data-rightbar-collapsed]` — the reserved GRID TRACK facet (present =
287
+ * zero-width right column). On phones (<768) the panel presents FULLSCREEN
288
+ * WITHOUT a track (`autoFullscreen` in SidebarRight), so this attribute
289
+ * alone misreads a panel that covers the whole frame as "closed" — the
290
+ * 2026-09-11 field bug: every close-swipe misrouted to open-left.
291
+ * - `[data-rightbar-fullscreen]` — the overlay facet (present = fullscreen
292
+ * presentation active, open by definition).
293
+ *
294
+ * Open = track reserved OR fullscreen overlay. On hosts before 0.1.5 both
295
+ * attributes never appear: closed, permanently — left gestures unaffected.
298
296
  */
299
297
  function readRightOpen() {
300
- return !document.body.hasAttribute("data-dsh-sidebar-collapsed");
298
+ const fullscreen = document.querySelector("[data-rightbar-fullscreen]") !== null;
299
+ const trackless = document.querySelector("[data-rightbar-collapsed]") !== null;
300
+ return fullscreen || !trackless;
301
301
  }
302
302
  /**
303
303
  * Whether a session is current — the plugin-side stand-in for the source's
304
- * `detailsSession !== undefined` guard (the right panel opens in a session
305
- * only). Better Sidebar's own shipped CSS keys off the same slot selector,
306
- * so it is load-bearing beyond this feature.
304
+ * `detailsSession !== undefined` guard (the right panel is a
305
+ * session-scoped surface; without a session its expand button is not
306
+ * rendered, so opening would be a no-op anyway).
307
307
  */
308
308
  function readSessionLive() {
309
309
  return document.querySelector("[data-slot=\"conversation.session.header\"]") !== null;
@@ -316,32 +316,38 @@ function readPanelState() {
316
316
  };
317
317
  }
318
318
  /**
319
- * Toggle Better Sidebar's right panel through its persistent DOM: the
320
- * plugin exposes no JS toggle on its client service (its open/close
321
- * reducer is store-internal), so the swipe reaches it the same way the
322
- * source did — clicking the LAST button of its always-rendered
323
- * `[data-dsh-toggle-cluster]` (the bottom-panel button precedes it and is
324
- * absent below the plugin's 768px narrow breakpoint). Absent cluster or
325
- * buttons: a no-op, never a crash.
319
+ * Drive the OFFICIAL right sidebar through its own controls (0.1.5
320
+ * ui-sidebar-right): opening clicks `[data-sidebar-right-expand]` (the
321
+ * conversation header corner button — the panel's own documented "way
322
+ * into a hidden panel", rendered exactly while collapsed with a session);
323
+ * closing clicks `[data-sidebar-right-toggle]` (the dock chrome toggle).
324
+ * The store action behind them (`setExpanded`/`toggleExpanded`) is
325
+ * slot-store-internal — cross-plugin imports are the hard boundary, so
326
+ * the native buttons ARE the sanctioned entry. Absent button (pre-0.1.5
327
+ * host, no session, or already in the target state): a no-op, never a
328
+ * crash.
326
329
  */
327
- function toggleBetterSidebar() {
328
- const buttons = document.querySelector("[data-dsh-toggle-cluster]")?.querySelectorAll("button");
329
- (buttons?.[buttons.length - 1])?.click();
330
+ function openRightPanel() {
331
+ document.querySelector("[data-sidebar-right-expand]")?.click();
332
+ }
333
+ function closeRightPanel() {
334
+ document.querySelector("[data-sidebar-right-toggle]")?.click();
330
335
  }
331
336
  /**
332
- * The narrow-viewport CSS: zero-width sidebar track under the breakpoint,
333
- * keyed to AppFrame's semantic attribute (survives class-hash churn).
334
- * Rendered with the breakpoint baked in (media queries cannot read JS
335
- * config); the tag carries the plugin-owned dataset so the loader's
336
- * style-claim machinery removes it on unload, like module CSS.
337
+ * The responsive CSS: zero-width sidebar track whenever upstream's layout
338
+ * has collapsed the sidebar, keyed PURELY to AppFrame's semantic
339
+ * attribute (survives class-hash churn). No width media query of our own
340
+ * (2026-09-11 ruling): upstream owns the auto-collapse threshold (1024
341
+ * today), and this rule simply takes the 56px rail they leave behind to
342
+ * zero. If upstream renames the attribute the rule stops matching and
343
+ * their native rail renders (benign degradation). The tag carries the
344
+ * plugin-owned dataset so the loader's style-claim machinery removes it
345
+ * on unload, like module CSS.
337
346
  */
338
- function mobileCss(breakpointPx) {
339
- const wide = Math.max(1, Math.floor(breakpointPx) - .02);
347
+ function mobileCss() {
340
348
  return [
341
- `@media (max-width: ${String(wide)}px) {`,
342
- ` [data-sidebar-collapsed] {`,
343
- ` grid-template-columns: 0px minmax(0, 1fr) 0px !important;`,
344
- ` }`,
349
+ `[data-sidebar-collapsed] {`,
350
+ ` grid-template-columns: 0px minmax(0, 1fr) 0px !important;`,
345
351
  `}`
346
352
  ].join("\n");
347
353
  }
@@ -361,7 +367,7 @@ function setupMobileLayout(ctx) {
361
367
  const tag = document.createElement("style");
362
368
  tag.dataset.plugin = "better-dsh";
363
369
  tag.dataset.pluginCss = styleTagId;
364
- tag.textContent = mobileCss(config.breakpoint);
370
+ tag.textContent = mobileCss();
365
371
  document.head.append(tag);
366
372
  const offLayout = ctx.inject(["layout"], (layoutCtx) => {
367
373
  const layout = layoutCtx.get("layout");
@@ -370,8 +376,10 @@ function setupMobileLayout(ctx) {
370
376
  const onPointerDown = (event) => {
371
377
  start = void 0;
372
378
  const viewport = window.innerWidth;
373
- if (!isNarrowViewport(viewport, config)) return;
374
- if (!admitsSwipeStart(event.clientX, viewport, readPanelState(), config)) return;
379
+ const coarsePointer = window.matchMedia?.("(pointer: coarse)").matches === true;
380
+ const panels = readPanelState();
381
+ if (!coarsePointer && !panels.leftCollapsed && !panels.rightOpen) return;
382
+ if (!admitsSwipeStart(event.clientX, viewport, panels, config)) return;
375
383
  start = {
376
384
  x: event.clientX,
377
385
  y: event.clientY,
@@ -389,7 +397,8 @@ function setupMobileLayout(ctx) {
389
397
  if (action === null) return;
390
398
  start = void 0;
391
399
  if (action === "open-left" || action === "close-left") layout.toggleSidebar();
392
- else toggleBetterSidebar();
400
+ else if (action === "open-right") openRightPanel();
401
+ else closeRightPanel();
393
402
  };
394
403
  const onPointerEnd = () => {
395
404
  start = void 0;
package/lib/index.d.ts CHANGED
@@ -549,7 +549,6 @@ interface WebTrustConfig {
549
549
  trustedPageAuthorities?: readonly string[];
550
550
  mobile?: {
551
551
  enabled?: boolean;
552
- breakpoint?: number;
553
552
  swipeDistancePx?: number;
554
553
  dominanceRatio?: number;
555
554
  leftEdgeBandPx?: number;
@@ -671,7 +670,7 @@ declare module '@deepseek-ai/cordis' {
671
670
  /**
672
671
  * Allow a listener to replace content in the DURABLE LOG COPY of one
673
672
  * `eval` sub-dispatch outcome before the bridge appends its
674
- * `tool/code-dispatch` event. `next()` keeps the content unchanged; a
673
+ * `tool/ptc-dispatch` event. `next()` keeps the content unchanged; a
675
674
  * listener may return replacement blocks (e.g. the spill policy's preview
676
675
  * + locator for an oversized text result). Scope-filtered dispatch
677
676
  * (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that
@@ -714,7 +713,7 @@ interface RunCellBridgeOptions {
714
713
  * in the module doc. Sub-calls ride the registry's exported staged scheduler
715
714
  * (`prepare`/`dispatch`/`finalize`/`finish`) under the native concurrency
716
715
  * contract; each sub-dispatch is logged for reconstruction
717
- * (`tool/code-dispatch-start` / `tool/code-dispatch`) while only the outer
716
+ * (`tool/ptc-dispatch-start` / `tool/ptc-dispatch`) while only the outer
718
717
  * curated result enters model history.
719
718
  * @param registry - the host tool registry (sub-calls go through its staged
720
719
  * scheduler, bindings cover its registered tools).