dsh-workplan 1.5.1 → 1.6.0
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 +267 -2
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/client.js +256 -54
- package/lib/host.js +1 -1
- package/lib/plan.js +112 -8
- package/lib/runtime.js +207 -23
- package/package.json +1 -1
- package/src/client.ts +253 -57
- package/src/host.ts +1 -1
- package/src/plan.ts +110 -8
- package/src/runtime.ts +201 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,234 @@
|
|
|
1
|
+
## 1.6.0 — 2026-10-29
|
|
2
|
+
|
|
3
|
+
**「会话终止」收敛版**。用户截图圈出 `session-7129faea-d4bd-4ed5-a081-769496e07ceb`:
|
|
4
|
+
这一轮对话早就结束了(没有任何东西在跑),面板红圈的分组仍写着**「进行中」**,卡片还停在
|
|
5
|
+
「预算用完,可续跑」。本次让**宿主会话生命周期**成为「到底有没有在跑」的唯一事实源,并把
|
|
6
|
+
该结论落成新的独立阶段 `ended` / 独立分组「已结束」,同时修掉回放路径上把失败写入计为完成的
|
|
7
|
+
第二个打架点。
|
|
8
|
+
|
|
9
|
+
### 事故与根因
|
|
10
|
+
|
|
11
|
+
事故会话的关键事实(来自会话日志回放):
|
|
12
|
+
|
|
13
|
+
1. 插件**只订阅 `agent/pre-step`**(`src/host.ts:286`),`turn/end`、`session/event`、
|
|
14
|
+
`session/disposed` 一个都不消费 → **会话结束这件事对插件不可见**;
|
|
15
|
+
2. 计划阶段只由「派发动作」写入(`executing` / `paused` / `blocked` …),派发结束后
|
|
16
|
+
再没有任何代码把它改回来,于是阶段永久停在被最后一次派发写下的值;
|
|
17
|
+
3. 唯一存在的兜底只覆盖一种情形:**从未派发**且 `pending` 超过 10 分钟才改判 `cancelled`
|
|
18
|
+
(`src/runtime.ts` 的 `STALE_PENDING_MS` 分支),对「派发过、会话结束」完全无效;
|
|
19
|
+
4. 客户端把**除 done 以外的一切阶段**都塞进「进行中」组
|
|
20
|
+
(分组条件只有 `planPhaseOf(...) !== 'done'`)→ `paused` / `blocked` / `pending` /
|
|
21
|
+
`executing` / `degraded` 全部显示成「进行中」;
|
|
22
|
+
5. 回放路径 `reconstructFromSession` 见到 `dsh_workplan_update` 调用就 `applyStatus`,
|
|
23
|
+
**忽略宿主 `tool/result` 的 `message.isError`** → 该会话里一次失败的写入被记成完成
|
|
24
|
+
(面板显示 7/12,真实完成 6/12),刷新前后又一次「数据源打架」。
|
|
25
|
+
|
|
26
|
+
结论:这是**插件缺陷**,不是上游缺失——宿主侧 `turn/start` / `turn/end`(含
|
|
27
|
+
`aborted.reason.kind` 的 `user` / `parent` / `hook` / `disposed`)事件齐全且已落盘。
|
|
28
|
+
|
|
29
|
+
### 改动
|
|
30
|
+
|
|
31
|
+
- **`src/runtime.ts`**
|
|
32
|
+
- 新增并导出 `sessionTurnState(session)`:从会话日志末尾向前扫最近 200 条
|
|
33
|
+
(`TURN_BOUNDARY_SCAN`),先遇 `turn/start` ⇒ 这一轮还开着,先遇 `turn/end` ⇒
|
|
34
|
+
已结束并带出 `reason.kind` 与 `aborted` 子原因;扫不到 ⇒ `unknown`(**绝不猜**)。
|
|
35
|
+
读日志而不是加事件订阅:日志既是实时事实也是回放事实,实时与刷新后必然同源。
|
|
36
|
+
- `serialisePlan()`(实时与回放共用的唯一出口)在既有的过期 `pending` 兜底之后、
|
|
37
|
+
不变量自检之前收敛:`planPhase` 不是 `done` / `cancelled` 且这一轮已结束 ⇒
|
|
38
|
+
阶段改为 `ended`,原阶段写进 `suspendedPhase`,并附带 `endReason` /
|
|
39
|
+
`endReasonDetail` / `endedAt`。**`done` 不参与改写**(否则直接违反不变量 I8)。
|
|
40
|
+
- **`turn/end` 不等于「取消」或「完成」**:一轮结束后可以随时续跑,因此只把
|
|
41
|
+
「没有东西在跑」这件事表达出来,不动 `record.phase`——用户说「继续」、日志出现
|
|
42
|
+
新的 `turn/start` 后,下一份载荷自然回到原派发阶段,无反向迁移逻辑。
|
|
43
|
+
- 回放改为**先登记、后定案**:`tool/call` 只记 `callId → 参数`,等配对
|
|
44
|
+
`tool/result` 到达才采纳;`message.isError === true` 丢弃,无结果同样不采纳
|
|
45
|
+
(保守优先于乐观)。跨计划的迟到结果按 `planId` 拒绝,不污染新计划。
|
|
46
|
+
- **`src/client.ts`**
|
|
47
|
+
- 新增阶段 `ended`(中「已结束,可续跑」/ 英「Ended (resumable)」)与**第三个独立分组
|
|
48
|
+
「已结束」**,位置在「进行中」与「已完成」之间;分组、组头计数、卡片胶囊继续共用
|
|
49
|
+
`planPhaseOf` 单一结论。
|
|
50
|
+
- 新增 `phaseLabel()`:徽标两段式表达「终态 + 原阶段」(如
|
|
51
|
+
「已结束,可续跑 · 预算用完,可续跑」「已结束,可续跑 · 卡住了」),
|
|
52
|
+
不再用一个词暗示还在跑,也不丢「停在哪儿」这个关键信息。
|
|
53
|
+
- 「已结束」组保留「需处理」角标(判定用后端下发的 `suspendedPhase`),
|
|
54
|
+
组头按 `endedAt` 排序(最近结束在前);有进行中/已结束计划时「已完成」组默认收起。
|
|
55
|
+
- 图表口径随之改名:环图为「未结束 / 已完成」,柱图为「未结束计划的完成度」,
|
|
56
|
+
已结束但未完成的计划一并计入「未结束」。
|
|
57
|
+
- 新增 `.dsh-wp-group--ended` 样式:灰点、**不脉冲**——「没有东西在跑」不允许用动画表达。
|
|
58
|
+
- **版本**:`1.5.2 → 1.6.0`(minor)。载荷新增字段、客户端新增分组,属**向后兼容的对外
|
|
59
|
+
扩展**而非纯 bugfix:旧客户端读新载荷只会忽略 `ended` 相关字段并把计划当 `pending`,
|
|
60
|
+
不会崩溃,但**看不到「已结束」**,所以建议同步升级。
|
|
61
|
+
|
|
62
|
+
### 测试(新增 17 条,全部可复跑)
|
|
63
|
+
|
|
64
|
+
- `tests/session-end-convergence.test.ts`(12 条,后端/载荷级):正常结束、异常中断
|
|
65
|
+
(`aborted/user`)、进程级中断(`aborted/disposed`)、**正在跑不误判**、全部完成仍是
|
|
66
|
+
`done` 且无不变量违规、结束后说「继续」阶段回退、刷新幂等、双会话隔离、
|
|
67
|
+
扫描上限返回 `unknown`、回放只采纳成功写入(isError / 无结果 / 成功三态)。
|
|
68
|
+
- `tests/ended-group.test.ts`(5 条,渲染级):`ended` 计划只进「已结束」组、组名不再出现
|
|
69
|
+
「进行中」、徽标两段式、卡住的计划仍报「需处理」、无 `ended` 时不渲染空组、
|
|
70
|
+
「已完成」组折叠规则。
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
npm test # 137 tests / 137 pass / 0 fail
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 验证方式(任何人都可复跑)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# 1) 完整回归(含本次新增的 17 条用例)
|
|
80
|
+
cd /Users/open/Documents/Stocks/plugins/dsh-workplan && npm test
|
|
81
|
+
# 2) 只跑本次的两个新用例文件
|
|
82
|
+
node --test dist-tests/tests/session-end-convergence.test.js dist-tests/tests/ended-group.test.js
|
|
83
|
+
# 3) 面板验收(人工):打开一个「已结束、未完成」的会话,
|
|
84
|
+
# 任务进度面板应把它放在「已结束」组,徽标写「已结束,可续跑 · …」;
|
|
85
|
+
# 说一句「继续」后,同一张卡应回到「进行中」。
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 兼容与升级
|
|
89
|
+
|
|
90
|
+
- 已装 1.5.x 的用户:升级后刷新页面即可,「已结束」组立即生效;
|
|
91
|
+
- 若面板在升级后仍显示「进行中」:先确认宿主版本已把 `turn/end` 落盘(1.6.0 依赖它,
|
|
92
|
+
未落盘时会保持原判定而不是误判),再确认浏览器已加载新 `client.js`。
|
|
93
|
+
|
|
94
|
+
## 1.5.2 — 2026-10-29
|
|
95
|
+
|
|
96
|
+
**「完成语义」统一版**。用户截图圈出一张 `14/14` 全部做完、环形进度 `100%` 的计划卡,
|
|
97
|
+
右侧状态胶囊却写「正在收尾」,而且这张卡仍留在「进行中」组。本次把**进度**与**状态**
|
|
98
|
+
收敛到同一个事实源,并把状态矩阵里同一根因的 8 类矛盾一并修掉。
|
|
99
|
+
|
|
100
|
+
### 事故与根因
|
|
101
|
+
|
|
102
|
+
截图会话为 `session-c3852c31-f6cd-4fc5-8cff-d8a3932e9feb`。事件回放显示:
|
|
103
|
+
|
|
104
|
+
1. 最后一次派发在预算用尽时结束,结果消息落盘为 `12/14 done、phase: paused`;
|
|
105
|
+
2. 之后主 Agent 直接调用 `dsh_workplan_update`,把剩余 `T13`、`T14` 标为 done
|
|
106
|
+
(会话里两次工具调用,`seq 263` / `seq 269`),**没有再发生任何派发轮次**;
|
|
107
|
+
3. `updateStatus` 用 `planPhase(statuses)` 重算 phase,而 `planPhase` 以
|
|
108
|
+
「结果消息是否已落盘(`resultSeen`)」为终态闸门 → 全部完成后仍返回 `integrating`;
|
|
109
|
+
4. 结果消息只在派发轮次末尾写入,走 update 工具的路径**永远不会**写它,
|
|
110
|
+
于是 phase 永久停在 `integrating`,`stats.progress` 已经是 `100`;
|
|
111
|
+
5. `serialisePlan` 又优先信任内存里的 `record.phase`,而回放 `reconstructFromSession`
|
|
112
|
+
用 `resultSeen = true` 重算出 `done` —— 同一条记录「刷新前正在收尾、刷新后已完成」;
|
|
113
|
+
6. 客户端还有三套独立的「是否完成」判断:环形进度看 `percent >= 100`、
|
|
114
|
+
「都做完了」看 `done === total`、状态胶囊看 `phase`,三者可以各说各话。
|
|
115
|
+
|
|
116
|
+
因此这不是文案问题,而是**完成事实有两个事实源**(计数 vs. 副作用闸门)。
|
|
117
|
+
|
|
118
|
+
### 改动
|
|
119
|
+
|
|
120
|
+
- **`src/plan.ts`**
|
|
121
|
+
- `planPhase()`:所有子任务 `done` 时**恒返回 `done`**,不再看 `resultSeen`
|
|
122
|
+
(参数保留以兼容既有调用,标注为历史遗留);`integrating` 仅作为旧载荷的
|
|
123
|
+
兼容取值存在。
|
|
124
|
+
- 新增 `reconcilePhase(phase, statuses)`:终态只由计数决定;`done` / `integrating`
|
|
125
|
+
这类「由计数派生」的旧值一律重算;`paused` / `cancelled` / `blocked` / `degraded`
|
|
126
|
+
保留各自的事实来源。
|
|
127
|
+
- `deriveAggregates()`:未全部完成时总进度**封顶 99**(`Math.min(99, raw)`),
|
|
128
|
+
杜绝「11 done + 1 blocked@95 → 总体进度 100」。
|
|
129
|
+
- `applyStatus()`:`in_progress` 的 `progress` 夹紧到 `99`,「正在做」不允许自称 100%。
|
|
130
|
+
- `aggregateInvariantViolations(snapshot, phase?)`:新增
|
|
131
|
+
**I8**(`done === total` 必须 `phase === 'done'`,双向)、
|
|
132
|
+
**I9**(全部完成必须 100%,未全部完成不得 >= 100)、
|
|
133
|
+
**I10**(`in_progress` 不得 `progress >= 100`)。
|
|
134
|
+
- **`src/runtime.ts`**
|
|
135
|
+
- `serialisePlan()`:`phase` 改为 `reconcilePhase(record.phase ?? 派生值, statuses)`;
|
|
136
|
+
载荷在存在不变量违背时附带 `violations` 数组,便于定位而不是静默显示。
|
|
137
|
+
- `updateStatus()`:改为 `reconcilePhase(record.phase, record.statuses)`
|
|
138
|
+
—— 截图矛盾的直接入口。
|
|
139
|
+
- 派发尾部:终态晋升不再依赖「结果消息写入」这一副作用,同样走 `reconcilePhase`。
|
|
140
|
+
- 回放 `reconstructFromSession()`:paused/cancelled 覆盖之后统一 `reconcilePhase`,
|
|
141
|
+
保证**刷新前后同源**。
|
|
142
|
+
- `cancelPlan()`:计划已全部完成时改为 no-op(返回 `alreadyDone: true`),
|
|
143
|
+
消除「100% + 已取消」。
|
|
144
|
+
- 预算到点分支:若此刻已经全部完成,记 `done` 而不是 `paused`(防御性,正常循环下不可达)。
|
|
145
|
+
- **`src/client.ts`**(自包含 bundle,不能 import `plan.ts`,故在客户端复刻同一语义)
|
|
146
|
+
- 三个唯一算式:`planPercent(done, total)`、`planPhaseOf(rawPhase, counts)`、
|
|
147
|
+
`planWeightedPercent(stats, counts)`;卡片环、徽章、分组、分组环、阶段条、
|
|
148
|
+
会话内联卡、`rank`、`liveBars` 全部改走它们。
|
|
149
|
+
- 新增文案:`helpWaitActive`(等这一步做完,再继续下一项)、
|
|
150
|
+
`helpNoPlan`(还没有安排任何工作)、`nowRemaining`(还剩 {n} 项)。
|
|
151
|
+
- **测试**
|
|
152
|
+
- 新增 `tests/phase-percent-invariant.test.ts`(13 例):终态语义、计数封顶、
|
|
153
|
+
I8/I9 双向、update 补完最后一项、空更新不回退、取消已完成计划、
|
|
154
|
+
客户端渲染旧载荷。
|
|
155
|
+
- 新增 `tests/completion-semantics.test.ts`(8 例):`in_progress@100` 夹紧、
|
|
156
|
+
I10、单任务执行中不再宣布完成、部分完成「还剩 N 项」、0/0 降级不说完成、
|
|
157
|
+
阶段条只按 done 计宽度、阶段卡与「现在」同口径、0% 未开始不再标 active。
|
|
158
|
+
- 更新 `tests/plan.test.ts`、`tests/workplan-budget-pause.test.ts` 里把
|
|
159
|
+
「全部完成后停在进行中」当期望值的断言;`tests/derived-counts.test.ts`
|
|
160
|
+
的 blocked 用例期望改为 99。
|
|
161
|
+
- **版本**:`1.5.1 → 1.5.2`(patch,修正完成语义,不新增对外接口)。
|
|
162
|
+
|
|
163
|
+
### 同类矛盾(来自 `docs/state-progress-matrix.md`)
|
|
164
|
+
|
|
165
|
+
| 编号 | 现象 | 本次 |
|
|
166
|
+
| --- | --- | --- |
|
|
167
|
+
| C1 | 100% + 「正在收尾」+ 留在「进行中」 | 已修 |
|
|
168
|
+
| C2 | 执行中却写「没有下一步,这件事已完成」 | 已修 |
|
|
169
|
+
| C5 | 部分完成却写「还没开始」 | 已修 |
|
|
170
|
+
| C7 | 阶段条把 blocked 算作已触达(环 50%、条 100%) | 已修 |
|
|
171
|
+
| C8 | 允许 `in_progress + 100%` | 已修 |
|
|
172
|
+
| C9 | 阶段行说「正在做」、阶段卡说「还没开始」 | 已修 |
|
|
173
|
+
| C11 | 0/0 降级计划也说「这件事已完成」 | 已修 |
|
|
174
|
+
| C12 | 同屏两个互斥的「现在」 | 已修 |
|
|
175
|
+
| C13 | 0% 未开始的卡标 `data-state="active"` | 已修 |
|
|
176
|
+
| C3 | 已取消的卡在前端被过滤,用户看不到(与 `dsh_workplan_cancel` 描述文案不一致) | 未改:既有设计,`tests/client-render.test.ts` 明确断言不渲染;记录待与工具描述统一 |
|
|
177
|
+
| C10 | stale pending 被序列化成 cancelled,而回放返回 `pending + stale:true` | 未改:记录为下一步 |
|
|
178
|
+
| C14 | `planning` 是死枚举 | 未改:记录为清理项 |
|
|
179
|
+
|
|
180
|
+
### 验证
|
|
181
|
+
|
|
182
|
+
- `npm run build` → exit 0;`npm run check`(`tsc --noEmit`)→ exit 0。
|
|
183
|
+
- `npm test` → **120/120 通过**,0 fail(原 99 + 新增 13 + 8)。
|
|
184
|
+
- `node scripts/repro-phase-percent-integrating.mjs --expect-fixed` → 7/7 PASS,
|
|
185
|
+
`payload.phase = done`、`stats = { total: 2, done: 2, progress: 100 }`、
|
|
186
|
+
徽章「已完成」、`live = done`、`replay = done`、无 `violations`。
|
|
187
|
+
(同一脚本不带参数运行现在会 3 条 FAIL —— 这是旧 bug 已不存在、修复生效的证据。)
|
|
188
|
+
- 版本一致性 7 处:`package.json`、`package-lock.json` 两处、`src/host.ts`、
|
|
189
|
+
`lib/host.js`、`dist/host.js`、本文件顶部,全部 `1.5.2`。
|
|
190
|
+
- 本次**未重启 DSH 服务**:`lib/*.js`(host 侧)在 DSH 进程下次启动时才加载;
|
|
191
|
+
`client.js` 随页面刷新生效。
|
|
192
|
+
|
|
193
|
+
### 发布
|
|
194
|
+
|
|
195
|
+
- 两个渠道、同一份制品(2026-10-29 13:22–13:25 +08:00 实测,发布已完成):
|
|
196
|
+
- git:`https://github.com/abbaababa/dsh-workplan.git` 的 annotated tag `v1.5.2` → `666b0fe`;
|
|
197
|
+
- npm:公共 registry `https://registry.npmjs.org/dsh-workplan` 的 `1.5.2`(`dist-tags.latest`)。
|
|
198
|
+
- **状态**:
|
|
199
|
+
- `git push origin main` → `b0e0b76..666b0fe main -> main`(快进,exit 0);
|
|
200
|
+
- `git push origin v1.5.2` → `* [new tag] v1.5.2 -> v1.5.2`(exit 0);
|
|
201
|
+
- 远端复核(`git ls-remote`):`refs/heads/main` = `666b0fee483b…`,
|
|
202
|
+
`refs/tags/v1.5.2` = `155c601c73d7…` → `^{}` = `666b0fee483b…`;
|
|
203
|
+
- `npm publish ./dsh-workplan-1.5.2.tgz --access public --ignore-scripts`
|
|
204
|
+
(在 `git worktree add --detach /tmp/dsh-wp-1.5.2 v1.5.2` 的干净快照上先 `npm pack`,
|
|
205
|
+
再发布该 `.tgz`,22 个文件全部取自 tag 提交)→ `+ dsh-workplan@1.5.2`(exit 0);
|
|
206
|
+
- `https://registry.npmjs.org/dsh-workplan/1.5.2` → **HTTP 200**,
|
|
207
|
+
`time['1.5.2']` = `2026-10-29T05:24:48.346Z`(13:24:48 +08:00),`dist-tags.latest` = `1.5.2`;
|
|
208
|
+
- 消费者视角:空白目录 `npm i dsh-workplan@1.5.2` →
|
|
209
|
+
`meta = {"name":"dsh-workplan","version":"1.5.2",…}`(22 个文件)。
|
|
210
|
+
- **已发布制品的校验值**(registry 实测,与本地 `.tgz` 逐字节一致):
|
|
211
|
+
- npm `shasum`(SHA-1):`2159024d69c05b3aeeefd5e7ff2f208ec05c67a2`
|
|
212
|
+
- npm `integrity`(SHA-512 SRI):`sha512-sY7UgT09JwfRFe61HKCOCH7wLz0xbdAxyLla3WO8xoyZ/T6Yxb6H/IqRFf9LEX9EsnW7+z4jcHICms6RKPmTzQ==`
|
|
213
|
+
- 本地 `.tgz` SHA-256:`4482f202d098bbaec35051e54440d0d2be6e0099b6d6606e3c582b88e1aee9fa`
|
|
214
|
+
(269 264 字节,解包 888 135 字节,22 个文件)
|
|
215
|
+
- 发布顺序:先分支、后标签、再 npm,避免出现「远端有 tag 而 npm 没有」的半发布态。
|
|
216
|
+
- registry 传播延迟实测约 45 秒(直连 404×3 → 200)。
|
|
217
|
+
- **CI 说明**:tag 提交 `666b0fe` 的 verify 运行 `40823115340` 为 failure——20 个用例在
|
|
218
|
+
Node 22 上被 `cancelledByParent`(`Promise resolution is still pending but the event loop
|
|
219
|
+
has already resolved`),与 1.5.1 / 1.5.0 / 1.4.3 的推送运行失败原因完全相同(各 20 条),
|
|
220
|
+
属**既有 CI 缺陷**,与本次改动无关,也不影响制品(测试不入包)。根因是运行时把轮次预算/
|
|
221
|
+
空闲计时器 `unref` 掉后,Node 22 在事件循环清空时取消挂起的测试。已在
|
|
222
|
+
`9f0de34`(只改 `tests/` 两个文件,`git diff v1.5.2 -- . ':!tests' ':!docs' ':!scripts'` 为空)
|
|
223
|
+
用「测试期间持有一个 ref 句柄、`after` 钩子释放」修掉;对应运行 `40823694198` 全绿。
|
|
224
|
+
- 命令原文与发布后验证:见 `docs/release-record-1.5.2-20261029.md`。
|
|
225
|
+
|
|
226
|
+
### 回滚
|
|
227
|
+
|
|
228
|
+
- 升级前四个文件的副本:`.backups/pre-1.5.2-20261029-125724/`
|
|
229
|
+
(`package.json`、`package-lock.json`、`CHANGELOG.md`、`src/host.ts`)。
|
|
230
|
+
- 回滚后必须重新 `npm run build`;运行中的 DSH 进程不会自动重载 `lib/host.js`。
|
|
231
|
+
|
|
1
232
|
## 1.5.1 — 2026-10-28
|
|
2
233
|
|
|
3
234
|
**「先看这三句」与「分步进度」位置对换的补丁版**。用户以截图圈出展开态计划卡里的这两个板块,
|
|
@@ -19,14 +250,48 @@
|
|
|
19
250
|
- `npm test` → **99/99 通过**(0 fail)。
|
|
20
251
|
- 7 处版本一致性检查 → `[PASS] 7 处版本均为 1.5.1`(`package.json`、`package-lock.json` 两处、
|
|
21
252
|
`src/host.ts`、`lib/host.js`、`dist/host.js`、`CHANGELOG.md` 顶部)。
|
|
22
|
-
-
|
|
23
|
-
|
|
253
|
+
- 提交 `fbe467b`(2026-10-28 22:27:53 +08:00)与 annotated tag `v1.5.1`
|
|
254
|
+
(taggerdate 2026-10-28 22:28:51 +08:00)已就绪并**已对外发布**(见下「发布」)。
|
|
255
|
+
- 本次**未重启 DSH 服务**;运行实例里的界面换序靠刷新页面触发(客户端 bundle 热重载)。
|
|
256
|
+
|
|
257
|
+
### 发布
|
|
258
|
+
|
|
259
|
+
- 两个渠道、同一份制品:
|
|
260
|
+
- git:`https://github.com/abbaababa/dsh-workplan.git` 的 annotated tag `v1.5.1` → `fbe467b`;
|
|
261
|
+
- npm:公共 registry `https://registry.npmjs.org/dsh-workplan` 的 `1.5.1`(`dist-tags.latest`)。
|
|
262
|
+
- **状态(2026-10-28 22:46–22:50 +08:00 实测,发布已完成)**:
|
|
263
|
+
- `git push origin refs/heads/main` → `db74d44..fbe467b main -> main`(快进,exit 0);
|
|
264
|
+
- `git push origin refs/tags/v1.5.1` → `* [new tag] v1.5.1 -> v1.5.1`(exit 0);
|
|
265
|
+
- 远端复核(`git ls-remote`,独立网络查询):`refs/heads/main` = `fbe467b4a632…`,
|
|
266
|
+
`refs/tags/v1.5.1` = `120dc2cb…` → `^{}` = `fbe467b4a632…`,本地 `ahead/behind` = `0/0`;
|
|
267
|
+
- `npm publish --ignore-scripts`(在 `git worktree add --detach … v1.5.1` 的干净快照上执行)
|
|
268
|
+
→ `+ dsh-workplan@1.5.1`(exit 0);
|
|
269
|
+
- `https://registry.npmjs.org/dsh-workplan/1.5.1` → **HTTP 200**,`time['1.5.1']` =
|
|
270
|
+
`2026-10-28T14:49:36.697Z`(22:49:36 +08:00),`dist-tags.latest` = `1.5.1`;
|
|
271
|
+
- 消费者视角:空白目录 `npm i dsh-workplan@1.5.1 --prefer-online` → 装到 1.5.1
|
|
272
|
+
(22 个文件,`client.js` 138 195 字节,`lib/host.js` 内 `version: '1.5.1'`)。
|
|
273
|
+
- **已发布制品的校验值**(registry 实测,与本地 `.tgz` 逐字节一致):
|
|
274
|
+
- npm `shasum`(SHA-1):`a6f35bd1b3d2630e3a2cf9e9555b58e51b20eaba`
|
|
275
|
+
- npm `integrity`(SHA-512 SRI):`sha512-AmpYMx55Y0ea2tAc14C4V7t/Pxrho+9nZXZqxz7JtdPYvFRyxS+wzEIUCfATRgq5cogT22lTSf0pEwUYOlgdqw==`
|
|
276
|
+
- 说明:同一份内容在原工作树打包时 `shasum` 为 `ecb39f0…`、在干净 `git worktree` 快照上为
|
|
277
|
+
`a6f35bd1…`,差异只来自 tar 记录的 mtime;**22 个文件的 blob 哈希与 tag `v1.5.1` 逐一相同**
|
|
278
|
+
(`checked 22 / mismatch 0`,另 44 个未随包发布的仓库文件按 `files` 白名单正确排除)。
|
|
279
|
+
实际发布的是干净快照这一份,故以上两行为准。
|
|
280
|
+
- 发布顺序:先分支、后标签、再 npm,避免出现「远端有 tag 而 npm 没有」的半发布态。
|
|
281
|
+
- registry 有约 60–90 秒传播延迟(22:48:58、22:49:20 直连仍 404,22:49:41 转 200);
|
|
282
|
+
该窗口内 `npm i` 需加 `--prefer-online` 绕过本地元数据缓存。
|
|
283
|
+
- 命令原文、失败分支、发布后验证与回滚:见 `docs/release-record-1.5.1-20261028.md`。
|
|
24
284
|
|
|
25
285
|
### 回滚
|
|
26
286
|
|
|
27
287
|
- 升级前四个文件的副本:`.backups/pre-1.5.1-20261028-221343/`
|
|
28
288
|
(`package.json`、`package-lock.json`、`CHANGELOG.md`、`src/host.ts`)。
|
|
29
289
|
- 回滚后必须重新 `npm run build`;运行中的进程不会自动重载 `lib/host.js`。
|
|
290
|
+
- 已推送(远端已有 `fbe467b` 与 `v1.5.1`):`git push origin :refs/tags/v1.5.1` 删远端标签,
|
|
291
|
+
`git revert fbe467b` 回退提交(不要 `push --force` 改远端 `main` 历史)。
|
|
292
|
+
- 已发布到 npm:先用 `npm deprecate dsh-workplan@1.5.1 "回滚说明"` 引导用户;确需撤销时
|
|
293
|
+
`npm unpublish dsh-workplan@1.5.1 --force`——受 npm 官方 unpublish 政策约束(可撤销时间窗口、
|
|
294
|
+
「有包依赖时不可撤销」),执行前核对 `npm unpublish --help` 与 npm 官方文档。
|
|
30
295
|
|
|
31
296
|
## 1.5.0 — 2026-10-28
|
|
32
297
|
|
package/README.en.md
CHANGED
|
@@ -53,7 +53,7 @@ dsh plugin --profile web add "$(pwd)"
|
|
|
53
53
|
4. Open **Task progress** in the sidebar:
|
|
54
54
|
|
|
55
55
|
- five headline numbers: **tasks / work items / done / in progress / blocked**;
|
|
56
|
-
- plan cards grouped into **In progress** and **Completed**, each with a completion rate;
|
|
56
|
+
- plan cards grouped into **In progress**, **Ended** and **Completed**, each with a completion rate. **Ended** means the turn has stopped (nothing is running) while the plan is still unfinished; the card also says where it stopped (budget spent / stuck / not started) and resuming is one sentence away;
|
|
57
57
|
- expand any plan to see per-stage progress and who owns each work item.
|
|
58
58
|
|
|
59
59
|
Every number is derived from the same task state — the panel can no longer claim "0 in progress" while the list below shows work running. That inconsistency is exactly what 1.4.3 fixed.
|
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ dsh plugin --profile web add "$(pwd)"
|
|
|
57
57
|
4. 点左侧栏的**「任务进度」**,就能看到:
|
|
58
58
|
|
|
59
59
|
- 顶部五个数字:**几个任务 / 分配了多少件工作 / 做好了 / 正在做 / 卡住了**;
|
|
60
|
-
-
|
|
60
|
+
- 计划卡:分「进行中」「已结束」「已完成」三组,右上角是完成率。「已结束」= 这一轮已经停了(没有东西在跑)但计划还没做完,卡片会写清停在哪儿(预算用完 / 卡住了 / 还没开始),说一句「继续」即可接着推进;
|
|
61
61
|
- 展开任意计划:每个阶段的进度、每件具体工作由哪个部门负责、当前状态。
|
|
62
62
|
|
|
63
63
|
5. 进度数字背后的每一行,都来自同一份任务状态——**不会再出现「显示 0 个正在做、但下面明明写着正在做」这种自相矛盾**(1.4.3 专门修的就是这个,见下文)。
|