dsh-composer-ux 0.13.0 → 0.13.2

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,71 @@
2
2
 
3
3
  本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.13.2] — 2026-09-30(✕ 改成「收起」:结果不再被删;另给一个点两次的「丢弃」;结果框不再像浮窗)
6
+
7
+ 起因(用户原话):**「快捷指令面板和提示词优化面板在同一页面。现在它提示词优化是悬浮的特别是我点叉关闭之后居然恢复不了」**。
8
+
9
+ ### 1. ✕ = 收起,不再是丢弃
10
+
11
+ 0.12.0 起那个 ✕ 的语义是「丢弃」(tooltip 也这么写),用户真点了一次就发现**恢复不了** —— 一次真花了钱的
12
+ 优化结果不该因为点一下 ✕ 就没了。现在:
13
+
14
+ - ✕ 只把结果**收起**(内容照旧在内存与磁盘上),面板切回「快捷指令」那半;
15
+ - 切换按钮会写「上次的结果在这儿」,点它就能再展开;
16
+ - **新跑一轮(✨ / 重新优化)自动展开**,不会被收起状态挡住;
17
+ - **收起状态跨重启记住**:状态信封加了可选的 `hidden` 字段,**不升版本号、向后兼容** ——
18
+ 没收起时不写该字段(文件形状与 0.13.0/0.13.1 完全一致,降级回旧版也认得),老文件没有该字段 = 没收起。
19
+
20
+ ### 2. 新增「丢弃」(点两次)
21
+
22
+ 放在结果框标题行、✕ 左边,样式弱化:**第一次点只换成「点第二次丢弃」**(4 秒后自己复位),
23
+ 第二次点才真丢(清状态 + 删磁盘那份)。与「插入输入框」覆盖确认是同一套做法,不弹模态框。
24
+
25
+ ### 3. 结果框不再像"浮窗"
26
+
27
+ 去掉它自己的背景与圆角边框(只留一条细分隔线)—— 用户说的「提示词优化是悬浮的」指的就是
28
+ 面板里又叠了一张独立卡片。现在它看起来是面板里的一段。
29
+
30
+ ### 内部
31
+
32
+ - 新增变异 5 条(EE ✕ 又变回丢弃 / EF 丢弃不真清 / EG 收起也抢面板 / EH 收起不存盘 / EI 恢复不读收起),
33
+ **137/137 全部咬住**;`optimize-state.mjs` 加 §5b(收起落盘/兼容/非布尔值防御),
34
+ `panel-split-render.mjs` 加 §6(收起时不渲染结果框本体、不抢面板、切换按钮提示正确)。
35
+ - 测试从 **2190 条** 涨到 **2214 条**(22 套件,全绿)。
36
+
37
+ ## [0.13.1] — 2026-09-30(面板分两半:优化提示词 / 快捷指令二选一;修「展开后看不到 插入/重新优化/复制」)
38
+
39
+ 起因(用户原话):**「现在是点击提示词优化按钮才能展开优化输入框,我想要点开快捷指令分为两个部分:一部分是优化提示词部分,一部分是快捷指令部分。」**
40
+ 并附了一条真机发现的 bug:**「展开优化提示词内容之后我看不到复制和填入之类的按钮」**。
41
+
42
+ ### 改成什么样(开工前问清并确认过的三点)
43
+
44
+ - **默认展开「快捷指令」**,标题行的**三档档位与 ✨ 优化提示词按钮始终露在外面** —— 跑一次优化永远是一步,不必先展开。
45
+ - 中部**二选一**:`优化提示词`(结果框)或 `快捷指令`(分类标签 + 条目列表 + 底部计数),中间一个切换按钮(▸ / ▾)换着看。
46
+ - **点 ✨ 或结果框出现时自动切到「优化提示词」那半**,否则刚跑出来的东西会被自己藏在收起状态里;
47
+ 手动切回快捷指令不会被抢回去;点结果框的「✕」顺手切回快捷指令。
48
+
49
+ ### 修掉的 bug(用户报的那条)
50
+
51
+ 结果框原先和快捷指令列表**挤同一块固定高度**(面板 `max-height: min(60vh, 520px)` + `overflow: hidden`,
52
+ 而结果框自身没有滚动或高度上限):内容一长(条目多 + 成品多行 + 输入框 30vh)就把列表挤到 0,
53
+ 再继续把**自己底部那排按钮(插入输入框 / 重新优化 / 复制)顶出面板边界裁掉**。修法两条:
54
+
55
+ 1. 结果框拆成「**可滚内容区 + 钉在底部的按钮行**」(`dockBody` + `dockButtonsPinned`);
56
+ 2. 两半互斥、各自内部滚(`quickSectionBody` / `quickList` 都补上 `flex: 1 1 auto` + `min-height: 0`)。
57
+
58
+ 顺带一处实现改进:自动切换原本写在 `useEffect` 里,会**先渲染一帧"快捷指令"再切**(点 ✨ 会看到面板闪一下),
59
+ 而且 **SSR 里 effect 不跑**、渲染测试根本测不到 —— 改成 React 文档里"props 变化时同步调整 state"的渲染期写法,
60
+ 两边一起解决(这个决定是被渲染测试逼出来的:第一版这么写时新套件里 7 条全红,红的全是这一组)。
61
+
62
+ ### 内部
63
+
64
+ - 新增 `test/panel-split-render.mjs`(**20 条**,`react-dom/server` **真渲染**):默认展开哪半、两半互斥、
65
+ 三个按钮**在最后一个滚动容器之后**、跑的时候看得到「取消」、锚点为空不渲染。
66
+ - `client-registration.mjs` 新增 **2.0g 节(11 条)** 源码级护栏;两半规则抽成纯函数 `client/panel-sections.ts`。
67
+ - 测试从 **21 套件 2160 条**涨到 **22 套件 2190 条**;变异从 **128 条**涨到 **132 条,全部咬住**
68
+ (EA 默认那半 / EB 有结果也不切 / EC 内容区不再自己滚 / ED 切换按钮不再换另一半)。
69
+
5
70
  ## [0.13.0] — 2026-09-30(结果框重启恢复 + 逐轮元数据台账 + 只读查证工具 + 发版门禁三脚本 + 证据登记表)
6
71
 
7
72
  > 起因:用户拿社区插件 [WestFox-AwA/dsh-prompt-optimizer](https://github.com/WestFox-AwA/dsh-prompt-optimizer)
package/README.en.md CHANGED
@@ -188,10 +188,14 @@ edited in settings; the JSON output contract is always appended and cannot be ov
188
188
  | Read-only tool fence (including symlinks) / every cap / out-of-bounds rejection | `node test/optimize-tools.mjs` (66 checks against a **real temporary directory**) |
189
189
  | Tool-loop message shape / round cap / exceptions must degrade | same file, section 6 (a fake `llm.stream` drives the whole loop; `role:'tool'` and `toolCallId` are asserted) |
190
190
  | Tool path: off by default, fires only when enabled, **prose after lookups falls back**, no cwd ⇒ no tool at all | `test/quick-commands.mjs` 5g (13 checks) |
191
- | Mutation guards really bite, and **the *named* test must be the one going red** | `npm run test:mutations`: **128/128 bite** |
191
+ | Mutation guards really bite, and **the *named* test must be the one going red** | `npm run test:mutations`: **137/137 bite** |
192
+ | 0.13.2: `✕` collapses (result kept) + a two-click 丢弃 | `node test/panel-split-render.mjs` §6, mutations EE–EI |
193
+ | Panel split + pinned result-box buttons (0.13.1) | `node test/panel-split-render.mjs` (20 checks, real `react-dom/server` render) |
192
194
  | Release gates | `npm run gates` (tag target / packed file list / docs drift) |
193
195
  | Three-platform CI | GitHub Actions: ubuntu / windows / macos × Node 20 |
194
196
 
197
+ > 0.13.1 split the panel into「优化提示词 / 快捷指令」halves with one toggle between them, and pinned the result
198
+
195
199
  ### Not verified (design intent, or verified on one machine only)
196
200
 
197
201
  | Gap | Note |
package/README.md CHANGED
@@ -134,7 +134,7 @@ dsh plugin --profile web add <你克隆或解压出来的目录>
134
134
  - **逐条流式,而且每条都已通过校验**:宿主边收边扫,把**已经闭合、且引文在你原话里逐字存在**的条目一条条推过来;对不上的走 `dropped` 如实记账。所以框里出现的每一条都是"成品里可能出现的那条",不会先闪一下再消失。成品要等整段输出到齐、逐条校验装配完才存在,由最后的 `done` 一次给出。
135
135
  - **「插入输入框」由你决定何时写回**:覆盖全文(`Ctrl+Z` 可还原),斜杠命令前缀(`/goal`)原样拼回。**若你在优化期间改过输入框**,第一次点只提示、第二次点才覆盖 —— 不静默吃掉你刚写的内容。
136
136
  - **「重新优化」= 用框里那一轮的原文再跑一轮**(不是拿输入框现在的内文:那时你多半已经把成品插进去了);你手改过框里的成品时会先提示一次。
137
- - **「取消」/ `Esc` 在跑的时候 = 中止并保留已生成的部分**:条目流水留着,成品如实留空(取消时它本来就不存在)。空闲时 `Esc` = 关面板;结果框的「✕」只收起结果框,输入框里已插入的内容不受影响;**面板关掉不会清空结果框** —— 一次优化是真花了钱的,不该因为你点了一下别处就没了。
137
+ - **「取消」/ `Esc` 在跑的时候 = 中止并保留已生成的部分**:条目流水留着,成品如实留空(取消时它本来就不存在)。空闲时 `Esc` = 关面板;结果框的「✕」**只收起**(0.13.2 起结果留着,点面板那一半就能再展开);输入框里已插入的内容不受影响;**面板关掉不会清空结果框** —— 一次优化是真花了钱的,不该因为你点了一下别处就没了。
138
138
  - **0.12.0 起默认携带会话上下文**(设置里可关):优化时会把当前会话最近的往来
139
139
  (**你的话与工作 AI 的话各取最近 4 条**、共约 1600 字)一并交给模型 —— "它那个也顺手改一下"
140
140
  这种离开上文就没意义的短句,只有带上上文才能猜对"它"指谁。三条边界写死在提示词里:
@@ -143,7 +143,48 @@ dsh plugin --profile web add <你克隆或解压出来的目录>
143
143
  - **0.12.0 起有记忆链**:你把成品插进输入框、改了几处、又点一次优化时,宿主会把**上一版成品**
144
144
  一起给模型(截断 1500 字),它只需围绕变化点调整、不必从零重写(你已确认过的地方不会被改回去)。
145
145
  不带的三种情况:同一段原文重跑(同文重试)、草稿就是上一轮成品(对成品重跑)、上一轮失败/取消;“重新优化”只在你手改过框里成品时才带。
146
+ - **面板分两半(0.13.1)**:中部现在是「**优化提示词**」(结果框)与「**快捷指令**」(分类 + 条目列表)**二选一**,
147
+ 中间一个切换按钮(▸ / ▾)换着看;打开面板**默认展开快捷指令**,标题行的**三档档位与 ✨ 按钮始终露在外面**
148
+ —— 所以「跑一次优化」永远是一步,不必先展开。**点 ✨ 会自己切到优化那半**(否则结果被藏在收起的一半里,
149
+ 看起来像没反应);手动切回快捷指令不会被抢回去;点结果框的「✕」会顺手切回快捷指令。
150
+ - **修掉「展开后看不到按钮」(0.13.1)**:以前结果框和快捷指令列表**挤同一块固定高度**,结果框一长
151
+ (条目多 + 成品多行)就把列表挤没、再把自己底部的**「插入输入框 / 重新优化 / 复制」顶出面板边界被裁掉**。
152
+ 现在两半互斥、各自内部滚,而且结果框拆成「可滚内容区 + **钉在底部的按钮行**」—— 面板再矮也不裁那排按钮。
146
153
  - **优化只从「快捷指令」面板进**(0.12.0 起):工具行只有一枚「快捷指令」按钮,点开面板再点「✨ 优化提示词」。
154
+
155
+ #### 0.13.2:✕ = 收起(结果留着),另给一个「丢弃」
156
+
157
+ > 起因(用户原话):**「现在它提示词优化是悬浮的特别是我点叉关闭之后居然恢复不了」**。
158
+
159
+ - **✕ 改成「收起」**:结果不再被删,只是标记成"先别显示";面板切回「快捷指令」那半,切换按钮写
160
+ 「上次的结果在这儿」,点它就能再展开(按钮 tooltip 明确写「结果留着」)。
161
+ - **新增「丢弃」**(结果框标题行里、✕ 左边,样式弱化):**点两次才真丢**(第一次换成「点第二次丢弃」,
162
+ 4 秒后自己复位),丢掉时才清状态 + 删磁盘那份。
163
+ - **收起状态跨重启记住**(用户选的 A):状态信封加了一个可选的 `hidden`,**不升版本号** ——
164
+ 没收起时不写这个字段,文件形状与 0.13.0/0.13.1 完全一致,降级回旧版也认得;老文件没有该字段 = 没收起。
165
+ - **新跑一轮(✨ / 重新优化)会自动把框显示出来**,不会被收起状态挡住。
166
+ - **结果框不再画成一张独立卡片**(去掉自己的背景与圆角边框,只留一条细分隔线)——
167
+ 这就是用户说的"悬浮"观感:它现在看起来是面板里的一段,而不是浮在上面的小窗。
168
+
169
+ #### 实机(0.13.1,2026-09-30 重启后当场核过)
170
+
171
+ **① 中部是「快捷指令」那半(默认)**:分类标签 + 条目列表 + 底部计数;标题行始终有「快捷指令 + 普通/高级/极端 + ✨ 优化提示词」,
172
+ 中间的切换按钮是 `▸ 优化提示词`,右侧写明另一半的状态(这里写的是「上次的结果在这儿」):
173
+
174
+ ![快捷指令那半](https://raw.githubusercontent.com/fangwen9527/dsh-composer-ux/v0.13.1/docs/panel-split-quick-0.13.1.png)
175
+
176
+ **② 点切换按钮 → 换成「优化提示词」那半**(列表收起,`▾` + 「点此回到快捷指令」):结果框里是条目流水、可编辑成品与记账行,
177
+ **底部那排「插入输入框 / 重新优化 / 复制」完整可见** —— 这正是 0.13.1 修的 bug:以前结果框一长,这排按钮会被面板裁掉:
178
+
179
+ ![优化提示词那半:三个按钮都在](https://raw.githubusercontent.com/fangwen9527/dsh-composer-ux/v0.13.1/docs/panel-split-optimize-0.13.1.png)
180
+
181
+ **③ 面板已经到了自己的高度上限(约 60vh),按钮依然在**:成品输入框右侧出现自己的滚动条,内容区滚而按钮不动 ——
182
+ 这就是"两半互斥 + 结果框拆成可滚区 + 钉底按钮行"的现场效果:
183
+
184
+ ![触到高度上限时按钮仍在](https://raw.githubusercontent.com/fangwen9527/dsh-composer-ux/v0.13.1/docs/panel-split-capped-0.13.1.png)
185
+
186
+ > 说明:面板里那份结果是**用户自己跑的一次优化**(`go/deepseek-flash`,用时 9.7 秒,7 条补全),不是我为了截图新花的调用;
187
+ > 截图时也没有改动它(没点「插入输入框」、没点 ✕,只切换了两半、开关了面板)。
147
188
  0.11.1 曾试过在工具行加一枚独立的「✨ 优化」按钮(点一下 = 开面板 + 立刻开跑),用户看到实机后明确否掉 ——
148
189
  「我让你集合到快捷指令里的提示词优化按钮里」,于是 0.12.0 删掉它,回到单一入口。
149
190
  - **秒表**:面板主按钮与结果框都显示已等待秒数,结束时报「用时 x.x 秒」。**边界如实说**:阶段只能到"等待模型响应" —— 更细的进度由逐条流水本身给出(它就是"它在干活"的证据)。
@@ -451,6 +492,7 @@ Windows 上 DSH 给模型的终端工具是 **PowerShell**(工具名 `pwsh`)
451
492
  |---|---|
452
493
  | 结果框持久化:原子写 / 损坏隔离 / 版本信封 / 净化边界 | `node test/optimize-state.mjs`(69 条,含真路由 `GET/POST` 往返与"太大拒写");变异 DL/DM/DN/DO/DP/DQ |
453
494
  | 重启后恢复的接线(只在框空着时恢复、去抖存盘、开关关掉不发请求) | 同上第 6 节(源码级断言 —— 组件行为在浏览器里,本仓测不到) |
495
+ | **面板分两半 + 结果框按钮钉底**(0.13.1) | `node test/panel-split-render.mjs`(20 条,`react-dom/server` **真渲染**:默认展开哪半、两半互斥、三个按钮在滚动区之外)+ `client-registration.mjs` 2.0g 节(11 条源码级) |
454
496
  | 台账只记元数据、不落原文 | `node test/optimize-ledger.mjs`(50 条)+ `test/quick-commands.mjs` 5e 节:真路由跑一轮后**在磁盘上的台账文件里搜不到草稿里那个独特的词** |
455
497
  | 台账的原因消毒(模型给的引文不再被写进磁盘) | 同上;变异 DH(去掉消毒立刻红) |
456
498
  | 台账轮转 / 逐行容错 / 清空 | `node scripts/recap.mjs` 真进程跑:`--last` / `--session` / `--json` / `--clear` 与坏行计数都在 `test/optimize-ledger.mjs` 第 6 节 |
@@ -458,7 +500,7 @@ Windows 上 DSH 给模型的终端工具是 **PowerShell**(工具名 `pwsh`)
458
500
  | 工具循环的消息形状 / 轮次封顶 / 异常必须降级 | 同上第 6 节(假 llm 驱动整条循环,逐条检查 `role:'tool'` 与 `toolCallId`) |
459
501
  | 工具路径:默认关、开了才派、**查完吐散文必须回落**、拿不到工作目录就不派 | `test/quick-commands.mjs` 5g 节(13 条,真路由 + 假 llm) |
460
502
  | 工具读到的内容不进台账 | 同 5g 节:断言台账里只有工具名与次数、没有读到的文件内容 |
461
- | 变异守卫真的会咬人,且**必须是指定的那条测试变红** | `npm run test:mutations`:**128 条全部咬住**(判据是 `red.some(line => line.includes(item.expect))`,不是"有红就行") |
503
+ | 变异守卫真的会咬人,且**必须是指定的那条测试变红** | `npm run test:mutations`:**137 条全部咬住**(判据是 `red.some(line => line.includes(item.expect))`,不是"有红就行") |
462
504
  | 发布门禁三条判据 | `npm run gates` 全过;`check:tag` 实测 `v0.12.0` 的 tag 名与所指提交里的版本一致 |
463
505
  | 三平台 CI | GitHub Actions:ubuntu / windows / macos × Node 20(`npm ci → typecheck → build → test → check:pack → check:docs`) |
464
506
 
@@ -467,7 +509,10 @@ Windows 上 DSH 给模型的终端工具是 **PowerShell**(工具名 `pwsh`)
467
509
  | 缺口 | 说明 |
468
510
  |---|---|
469
511
  | **效果(最重要的一条)** | 我们**没有任何受控评估** —— 没有留出集、没有 A/B、没有成本基线。"这样优化之后模型做得更好"在本仓里没有一条证据,只是设计意图。上游花钱做过一次,结论是"没测出差别",所以这一格必须留空。 |
470
- | **0.13.0 的真机(实机)行为** | ①重启恢复、②台账落盘、⑤只读工具这三块**只在测试与假 llm 里跑过**,没有在真实 DSH 里点过。真机验收要等重启后做(重启由用户执行);0.12.0 那 5 张截图是上一版的实机证据,**不覆盖新功能**。 |
512
+ | **0.13.0 的真机(实机)行为** | ①重启恢复、②台账落盘、⑤只读工具这三块**只在测试与假 llm 里跑过**,没有在真实 DSH 里点过(0.12.0 那 5 张截图也不覆盖新功能)。 |
513
+ | 0.13.2 的「✕ = 收起 / 丢弃 / 收起跨重启」 | `test/panel-split-render.mjs` 第 6 节(**真渲染**:收起时不渲染结果框本体、自动切换不抢面板)+ 变异 EE/EF/EG/EH/EI → **真机待重启后验**(本人 2026-09-30 报的就是这条) |
514
+ | 0.13.1 的面板分半 | ✅ **有真机证据**:2026-09-30 08:14 重启后当场验过「默认哪半、切换按钮换半、跑完自动切到优化半、**到了高度上限按钮仍在**」
515
+ (三张截图见上面「实机(0.13.1)」);但**没验**"没有结果框时首次打开"的默认态(那要开一次干净的会话),这条只有渲染测试罩着。 |
471
516
  | 只读工具的收益与成本 | 真实项目里派工具能省多少来回、多花多少 token 与时间,**没有数据**。默认关闭正是因为这份不确定。 |
472
517
  | "工具内容不会被当成引文"在真实模型上的表现 | 结构上成立(`quote` 必须逐字命中用户原话,否则逐条丢弃,有测试)。但模型会不会因此产出更差的结果,**没测**。 |
473
518
  | **原子写的原子性本身** | 单线程测试观测不到"写到一半";只有"不留临时文件"这条卫生断言,**没有变异证明**(已在提交信息里写明,不假装验过)。 |
@@ -588,9 +633,9 @@ node build.mjs # 产出 lib/index.js + lib/client.js
588
633
  # ⚠️ 宿主半会**内联** schemastery / cosmokit:
589
634
  # 优先用 DSH 检出里的 vendor 副本,检出不在时退到 node_modules
590
635
  # 里同版本的 npm 包(两者逐字节相同)——CI 上走的就是退路
591
- npm test # 21 个套件;当前 2160 passed, 0 failed(2026-09-29 实测;CI 三平台同样全绿)
636
+ npm test # 22 个套件;当前 2214 passed, 0 failed(2026-09-29 实测;CI 三平台同样全绿)
592
637
  # 走 scripts/run-tests.mjs:顺带把"多少套件/多少条"记进 test/.last-run.json
593
- npm run test:mutations # 手动跑:变异测试,证明那套护栏真的在咬人(128 条,须单独跑)
638
+ npm run test:mutations # 手动跑:变异测试,证明那套护栏真的在咬人(137 条,须单独跑)
594
639
  # 同样记录结果,供下面的文档门禁核对
595
640
  npm run gates # 发版门禁三条一起跑:tag 指向 / 包内容 / 文档数字
596
641
  npm run check:tag # ① tag 名里的版本 == 该 tag 所指提交里的 package.json 版本