dsh-global-todo 0.16.1 → 0.16.3
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 +35 -0
- package/README.md +38 -6
- package/README.zh.md +33 -6
- package/docs/FAQ.md +11 -11
- package/docs/QUICKSTART.md +14 -2
- package/docs/ROADMAP.md +12 -7
- package/docs/WINDOWS.md +97 -0
- package/lib/index.js +1 -1
- package/lib/model.js +11 -3
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
## [0.16.3] — 2026-10-23
|
|
2
|
+
|
|
3
|
+
Documentation release: the npm page finally shows the current install instructions.
|
|
4
|
+
|
|
5
|
+
- **npm's README is frozen at publish time**, so the install/per-profile rewrite and the
|
|
6
|
+
「哪些功能还没有 / Not there yet」 sections (README.zh.md, FAQ, ROADMAP) reach GitHub but not the
|
|
7
|
+
npm page until a new version ships. Nothing in `lib/` changes.
|
|
8
|
+
- **The market index no longer blocks publishing.** Its test required the index's newest version
|
|
9
|
+
to equal `package.json`'s — which cannot hold between a version bump and its publish, and
|
|
10
|
+
`prepack` runs the suite, so the first release after the market index landed could not be
|
|
11
|
+
tagged. The offline rule is now one-directional (the index may not offer a version newer than
|
|
12
|
+
the tree), and staleness moved to `npm run market:fresh`, which asks the registry. AGENTS.md
|
|
13
|
+
documents the two-step order: publish, then regenerate the index and commit it.
|
|
14
|
+
|
|
15
|
+
## [0.16.2] — 2026-10-22
|
|
16
|
+
|
|
17
|
+
A date-only deadline is local midnight, so a date bound stops swallowing part of its own day.
|
|
18
|
+
|
|
19
|
+
- **`before:` / `after:` with a bare date were anchored at UTC midnight.** `Date.parse('2026-11-01')`
|
|
20
|
+
is UTC midnight by the specification; on +08 that is 08:00 local, so `before:2026-11-01` included
|
|
21
|
+
everything due 00:00–08:00 on the bound day, and an `after:` bound lost the same window in the
|
|
22
|
+
west. Date-only values are now built with the local constructor, matching how `dueAt` is authored
|
|
23
|
+
(issue #6).
|
|
24
|
+
- **This also changes what a bare `dueAt: "2026-11-01"` stores**: it used to become UTC midnight
|
|
25
|
+
and now becomes local midnight — the day the person means, on the machine they are on. Existing
|
|
26
|
+
records are untouched; only new writes differ.
|
|
27
|
+
- **The timezone case is pinned in `test/tz.test.mjs`**, which runs the parser in a child process
|
|
28
|
+
with `TZ=Asia/Shanghai`: CI is UTC, where both anchors are the same number, so the regression
|
|
29
|
+
would otherwise be invisible there. On a platform that ignores `TZ` the test skips rather than
|
|
30
|
+
claiming to have checked.
|
|
31
|
+
- **`docs/WINDOWS.md` gained two answers from the same round**: the date-bound row now states the
|
|
32
|
+
local-midnight contract, and a standing three-question checklist (two-layer semantics, timezone,
|
|
33
|
+
path four states) sits beside the per-feature one, plus the note that ARIA states must be
|
|
34
|
+
verified by attribute, not by searching for the words a screen reader speaks.
|
|
35
|
+
|
|
1
36
|
## [0.16.1] — 2026-10-22
|
|
2
37
|
|
|
3
38
|
Same code as 0.16.0; the tag now points at a commit whose CI is green.
|
package/README.md
CHANGED
|
@@ -172,21 +172,53 @@ What each file shows, and when it is regenerated, is indexed in
|
|
|
172
172
|
|
|
173
173
|
## Install
|
|
174
174
|
|
|
175
|
+
**Check your profile name first.** The plugin is installed into one profile, not into the
|
|
176
|
+
machine; a wrong profile name still exits 0, and then nothing shows up in the sidebar after a
|
|
177
|
+
restart — the most common first-run trap.
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
ls ~/.dsh/profiles # Windows: dir %USERPROFILE%\.dsh\profiles
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Replace `<profile>` below with one of the names that command prints (`web` on most hosts;
|
|
184
|
+
use your desktop or `headless` profile name if that is what you run):
|
|
185
|
+
|
|
175
186
|
```sh
|
|
176
187
|
# from npm
|
|
177
|
-
dsh plugin --profile
|
|
188
|
+
dsh plugin --profile <profile> add dsh-global-todo
|
|
178
189
|
|
|
179
190
|
# or from a checkout, which is also the development path
|
|
180
|
-
dsh plugin --profile
|
|
191
|
+
dsh plugin --profile <profile> add /absolute/path/to/dsh-global-todo
|
|
181
192
|
```
|
|
182
193
|
|
|
183
|
-
The plugin is a Loader row, not a hot-loaded script: **restart the host** (`dsh web
|
|
184
|
-
after installing, then refresh the page. A "待办 / Todos"
|
|
194
|
+
The plugin is a Loader row, not a hot-loaded script: **restart the host** (`dsh web`, or
|
|
195
|
+
whatever start command you use) after installing, then refresh the page. A "待办 / Todos"
|
|
196
|
+
entry appears in the sidebar.
|
|
197
|
+
|
|
198
|
+
> Sidebar still empty? Check three things in order: ① which profiles `ls` actually printed and
|
|
199
|
+
> whether the one you installed into is the one running; ② whether the host really restarted
|
|
200
|
+
> (the Loader is read once at boot); ③ whether the page was refreshed (the client module graph
|
|
201
|
+
> belongs to the release the page booted with).
|
|
185
202
|
|
|
186
203
|
The npm package is the source of truth. A community catalog can lag behind it or point at an
|
|
187
|
-
older release; pin the version you want (`dsh plugin --profile
|
|
204
|
+
older release; pin the version you want (`dsh plugin --profile <profile> add dsh-global-todo@0.13.1`)
|
|
188
205
|
when it matters.
|
|
189
206
|
|
|
207
|
+
### Installing from DSH's Discover tab
|
|
208
|
+
|
|
209
|
+
DSH's Discover tab reads a plugin market index from a URL you add yourself — dsh ships none, and
|
|
210
|
+
a user-added index is the one path that installs without copying a command. This repository
|
|
211
|
+
publishes one:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
https://lugabeeee.github.io/dsh-global-todo/market/index.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
It is generated from npm by `npm run market` (`docs/market/index.json`) and validated against
|
|
218
|
+
dsh's own `@deepseek-ai/dsh-plugin-market-index` before it is written. `npm test` fails when its
|
|
219
|
+
newest version is not the version in `package.json`, so a release that forgets to regenerate it
|
|
220
|
+
is caught before it ships.
|
|
221
|
+
|
|
190
222
|
**Hand-copied a directory instead?** Check it before wondering why the plugins page looks wrong:
|
|
191
223
|
|
|
192
224
|
```sh
|
|
@@ -200,7 +232,7 @@ the desktop app print `Plugin metadata … ENOENT … \locale` while the plugin
|
|
|
200
232
|
To roll back:
|
|
201
233
|
|
|
202
234
|
```sh
|
|
203
|
-
dsh plugin --profile
|
|
235
|
+
dsh plugin --profile <profile> remove dsh-global-todo
|
|
204
236
|
```
|
|
205
237
|
|
|
206
238
|
Your list is not touched by install or uninstall: it lives outside the plugin, at
|
package/README.zh.md
CHANGED
|
@@ -151,16 +151,43 @@ HTML(不依赖宿主、零依赖),再以 1280×720 拍进 `docs/screenshot
|
|
|
151
151
|
|
|
152
152
|
## 安装
|
|
153
153
|
|
|
154
|
+
**先确认 profile 名字。** 插件是装进某个 profile 的,不是装进整台机器;profile 名写错,
|
|
155
|
+
命令会成功,但重启后侧栏里什么都没有——这是最常见的一次踩坑。
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
ls ~/.dsh/profiles # Windows: dir %USERPROFILE%\.dsh\profiles
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
把下面命令里的 `<profile>` 换成上一步列出来的那个(本机常见是 `web`;用桌面端就填桌面端的
|
|
162
|
+
profile 名,用 headless 就填 `headless`):
|
|
163
|
+
|
|
154
164
|
```sh
|
|
155
165
|
# 从 npm 装
|
|
156
|
-
dsh plugin --profile
|
|
166
|
+
dsh plugin --profile <profile> add dsh-global-todo
|
|
157
167
|
|
|
158
168
|
# 或从本地检出装(也是开发路径)
|
|
159
|
-
dsh plugin --profile
|
|
169
|
+
dsh plugin --profile <profile> add /绝对路径/dsh-global-todo
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
插件是宿主组合里的**一行 Loader**,不是热加载脚本:**装完要重启宿主**(`dsh web`,
|
|
173
|
+
或你用的那个启动命令),再刷新页面。侧栏会出现「待办」入口。
|
|
174
|
+
|
|
175
|
+
> 侧栏还是空的?按顺序查三件事:① 上面的 `ls` 里到底有哪几个 profile,你装的是不是正在跑的那个;
|
|
176
|
+
> ② 宿主有没有真的重启(Loader 只在启动时读一次);③ 页面有没有刷新(客户端模块图属于
|
|
177
|
+
> 启动时那个 release)。
|
|
178
|
+
|
|
179
|
+
### 从 DSH 的 Discover 标签安装
|
|
180
|
+
|
|
181
|
+
DSH 的 Discover 标签读的是**你自己添加**的一个 JSON 索引(官方不带索引),这也是唯一一条
|
|
182
|
+
不用手抄命令的安装路径。本仓库发布了一份:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
https://lugabeeee.github.io/dsh-global-todo/market/index.json
|
|
160
186
|
```
|
|
161
187
|
|
|
162
|
-
|
|
163
|
-
|
|
188
|
+
它由 `npm run market` 从 npm 生成(`docs/market/index.json`),写入前会用 DSH 自己的
|
|
189
|
+
`@deepseek-ai/dsh-plugin-market-index` 校验一遍。**索引里的最新版本与 `package.json` 不一致时
|
|
190
|
+
`npm test` 会失败** —— 发版后忘了重新生成,会在发出去之前就被拦下。
|
|
164
191
|
|
|
165
192
|
**如果你是手动拷贝目录(而不是从 npm 装)**,先自检一遍,别靠猜:
|
|
166
193
|
|
|
@@ -174,12 +201,12 @@ npx dsh-global-todo-doctor "$HOME/.dsh/plugins-local/全局待办插件"
|
|
|
174
201
|
`Plugin metadata … ENOENT … \locale`。
|
|
175
202
|
|
|
176
203
|
npm 上的包才是事实来源。社区目录可能落后于 npm、或指向某个旧 release;需要确定版本时
|
|
177
|
-
直接钉版本(`dsh plugin --profile
|
|
204
|
+
直接钉版本(`dsh plugin --profile <profile> add dsh-global-todo@0.13.1`)。
|
|
178
205
|
|
|
179
206
|
回滚:
|
|
180
207
|
|
|
181
208
|
```sh
|
|
182
|
-
dsh plugin --profile
|
|
209
|
+
dsh plugin --profile <profile> remove dsh-global-todo
|
|
183
210
|
```
|
|
184
211
|
|
|
185
212
|
装卸都不会碰你的清单——它在插件之外:`$DSH_HOME/global-todo/todos.json`。
|
package/docs/FAQ.md
CHANGED
|
@@ -68,18 +68,18 @@ CSV 没有直接入口:先转成 JSON 或 Markdown。Markdown 解析是容错
|
|
|
68
68
|
|
|
69
69
|
没有 Agent 参与时用不上的只有四件事:抓取、派发、Agent 的完成声明、会话回读。
|
|
70
70
|
|
|
71
|
-
## 8.
|
|
71
|
+
## 8. 哪些功能目前还没有?
|
|
72
72
|
|
|
73
|
-
|
|
|
73
|
+
| 目前没有 | 现状 |
|
|
74
74
|
|---|---|
|
|
75
|
-
| 看板 / 日历视图 |
|
|
76
|
-
| 重复任务 | `dueAt`
|
|
77
|
-
| 子任务树 |
|
|
78
|
-
| 上传附件 |
|
|
79
|
-
| 多清单 / 项目 |
|
|
80
|
-
| 自动开工 |
|
|
81
|
-
| 桌面端面板 |
|
|
82
|
-
| 账号 / 多用户 |
|
|
75
|
+
| 看板 / 日历视图 | 现在只有列表,加三种分组(对话 / 时间 / 级别);没有拖拽看板,没有日历 |
|
|
76
|
+
| 重复任务 | `dueAt` 是单个时间点,还没有 recurrence 字段;同一截止只提醒一次,改了时间才会重新提醒 |
|
|
77
|
+
| 子任务树 | 现在只有扁平的 `steps`,最多 20 条 |
|
|
78
|
+
| 上传附件 | 现在只存引用(绝对路径或 URL),不复制字节 |
|
|
79
|
+
| 多清单 / 项目 | 现在只有一份全局清单 |
|
|
80
|
+
| 自动开工 | 现在没有;它是一份个人清单,不是任务队列 |
|
|
81
|
+
| 桌面端面板 | 现在只有 Web 客户端 |
|
|
82
|
+
| 账号 / 多用户 | 现在没有;只有一个本机(或受信网络)可访问的 HTTP 面 |
|
|
83
83
|
|
|
84
84
|
## 9. 两个进程同时写这个文件会怎样?
|
|
85
85
|
|
|
@@ -122,7 +122,7 @@ CSV 没有直接入口:先转成 JSON 或 Markdown。Markdown 解析是容错
|
|
|
122
122
|
## 12. 怎么干净卸载?
|
|
123
123
|
|
|
124
124
|
```sh
|
|
125
|
-
dsh plugin --profile
|
|
125
|
+
dsh plugin --profile <profile> remove dsh-global-todo
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
然后重启宿主、刷新页面,侧栏入口消失。清单和设置都还在原处——这是刻意的。
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -15,14 +15,26 @@ headless / ACP / SDK 组合里没有面板,只剩 Agent 工具。
|
|
|
15
15
|
|
|
16
16
|
## 1. 安装
|
|
17
17
|
|
|
18
|
+
先看你实际有哪些 profile(插件是装进某一个 profile,不是装进整台机器):
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
ls ~/.dsh/profiles # Windows: dir %USERPROFILE%\.dsh\profiles
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
把打印出来的名字填进去(大多数是 `web`):
|
|
25
|
+
|
|
18
26
|
```sh
|
|
19
|
-
dsh plugin --profile
|
|
27
|
+
dsh plugin --profile <profile> add dsh-global-todo
|
|
20
28
|
```
|
|
21
29
|
|
|
22
|
-
装完**重启宿主**(`dsh web
|
|
30
|
+
装完**重启宿主**(`dsh web`,或你用的那个启动命令),再**刷新页面**。插件是 Loader 里的一行,
|
|
31
|
+
不是热加载脚本。
|
|
23
32
|
|
|
24
33
|
验证:侧栏出现「待办」入口。
|
|
25
34
|
|
|
35
|
+
侧栏还是空的?按顺序查三件事:① 你装的是不是正在跑的那个 profile;② 宿主有没有真的重启;
|
|
36
|
+
③ 页面有没有刷新。三件都对还是没有,跑 `npx dsh-global-todo-doctor <插件目录>` 自检。
|
|
37
|
+
|
|
26
38
|
## 2. 打开面板
|
|
27
39
|
|
|
28
40
|
点侧栏的「待办」。这是**全局面板**:不绑定某个会话,切到别的对话、关掉再开,清单还是同一份。
|
package/docs/ROADMAP.md
CHANGED
|
@@ -246,10 +246,15 @@ mislead.
|
|
|
246
246
|
| Drag to reorder | Manual order is meaningful to some people; it also needs a stable `position` field and a decision about how it interacts with due-date grouping. |
|
|
247
247
|
| Multi-list / projects | A `list` field with one default list; deferred because "global single list" is the current identity. |
|
|
248
248
|
|
|
249
|
-
##
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
- **
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
## Not there yet
|
|
250
|
+
|
|
251
|
+
Things the list does not have today. Some may arrive later; none of them is a promise.
|
|
252
|
+
|
|
253
|
+
- **Calendar and board views.** The panel is a list with three groupings today. There is no
|
|
254
|
+
calendar view and no drag-and-drop board.
|
|
255
|
+
- **Auto-running todos.** Nothing starts work on a schedule today; the list records what a
|
|
256
|
+
person intends to do.
|
|
257
|
+
- **Copying attachment bytes.** Attachments are references (absolute path or URL) today; see
|
|
258
|
+
`DESIGN.md` for why references beat stale copies.
|
|
259
|
+
- **A second source of truth.** Everything reads and writes the one JSON file today; anything
|
|
260
|
+
that mirrors it elsewhere (a database, a remote service) would have to justify itself.
|
package/docs/WINDOWS.md
CHANGED
|
@@ -39,6 +39,103 @@ review then reload, assert no `.tmp` debris, write and read back 500 todos, impo
|
|
|
39
39
|
file, write into a path with spaces and non-ASCII characters, and rename over an existing file. It
|
|
40
40
|
prints one line per check and exits non-zero on the first failure.
|
|
41
41
|
|
|
42
|
+
## 0.16 新增:这张清单是为了让新功能先在你那台机器上过一遍
|
|
43
|
+
|
|
44
|
+
0.12—0.15 加的东西里有四项**能在 Windows 上表现得和 Linux 不同**,其中两项直接碰到路径与文件存在性。
|
|
45
|
+
每一项都写清了「怎么做」和「什么样才算通过」,照着走一遍即可,不需要读代码。
|
|
46
|
+
|
|
47
|
+
### 1. 图片附件(0.15.0,最需要真机验证)
|
|
48
|
+
|
|
49
|
+
附件现在可以有第三种类型 `kind: "image"`,它和文档一样是**引用**(不复制字节),但面板会渲染它。
|
|
50
|
+
|
|
51
|
+
准备工作(PowerShell,路径里故意带空格和中文):
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
$dir = Join-Path $env:TEMP 'gt 图片 测试'
|
|
55
|
+
New-Item -ItemType Directory -Force $dir | Out-Null
|
|
56
|
+
# 先写一张 1x1 的合法 PNG,保证没有 Pictures 目录的机器也能照着走:
|
|
57
|
+
[IO.File]::WriteAllBytes(
|
|
58
|
+
(Join-Path $dir 'shot.png'),
|
|
59
|
+
[Convert]::FromBase64String('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==')
|
|
60
|
+
)
|
|
61
|
+
# 想用真实截图(名字里带空格/中文)就再拷一份:
|
|
62
|
+
Copy-Item "$env:USERPROFILE\Pictures\*" $dir -ErrorAction SilentlyContinue
|
|
63
|
+
Get-ChildItem $dir | Select-Object Name, Length
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| 步骤 | 期望 |
|
|
67
|
+
|---|---|
|
|
68
|
+
| 新建一条待办,附件给 `{ "kind": "image", "value": "<上面的路径>\shot.png" }`(或用工具 `global_todo_add` 的 `links`) | 行上出现 16px 缩略图,详情里出现预览图 |
|
|
69
|
+
| 把那张 png 改名(`Rename-Item`),刷新面板 | 变成红色的「文件不在了」chip,**不是一张破图** |
|
|
70
|
+
| 用详情里的「重新挂载」把它指回改名后的文件 | 缩略图恢复,且类型仍是 image(不会变成文档) |
|
|
71
|
+
| 给一个 `.svg` 作为 image | 被拒绝,错误里有「图片附件需要图片扩展名」 |
|
|
72
|
+
| 给一个 >8MB 的图片 | 面板提示「图片超过 8MB」,缩略图不加载 |
|
|
73
|
+
| 路径用反斜杠、带盘符(`D:\…\shot.png`) | 与正斜杠一致;`C:/…/shot.png` 也可以 |
|
|
74
|
+
|
|
75
|
+
后端可直接验(服务在本机时):
|
|
76
|
+
|
|
77
|
+
```powershell
|
|
78
|
+
# 换成真实 id 与索引;路径只从记录里取,请求里传路径会被忽略
|
|
79
|
+
curl.exe -s "http://127.0.0.1:3080/api/global-todo/asset?id=<id>&index=0" -o $env:TEMP\probe.png
|
|
80
|
+
Get-Item $env:TEMP\probe.png | Select-Object Length
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2. 重新挂载(0.16.0)
|
|
84
|
+
|
|
85
|
+
- 详情里**只有失效附件**才出现「重新挂载」按钮;点开是内联输入框,预填旧路径;
|
|
86
|
+
- 保存后**原地替换**(附件顺序、标题、类型都不变),不会变成一条新附件;
|
|
87
|
+
- 换成一个**非**绝对路径(如 `notes.md`)应被拒绝;换成一个不存在的路径:若 `requireExistingFiles` 默认为真,也会被拒绝——这正是设计意图,先建文件再挂。
|
|
88
|
+
|
|
89
|
+
### 3. 搜索的 `before:` / `after:`(0.16.0)
|
|
90
|
+
|
|
91
|
+
| 输入 | 期望 |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `before:2026-11-01` | 只留下**截止时间早于本地 11-01 00:00** 的条目;等于该时刻的不算。纯日期按**本地零点**锚定(0.16.2 起;此前锚在 UTC 零点,+08 上会吞掉边界日 00:00–08:00,见 issue #6) |
|
|
94
|
+
| `after:2026-10-01` | 只留下截止时间晚于该时刻的;**没有截止时间的条目两个方向都不出现** |
|
|
95
|
+
| `after:2026-10-01 before:2026-12-01` | 两个条件同时生效(AND) |
|
|
96
|
+
| `before:2026-1`(没打完) | **不报错**,该 token 退化成普通搜索词;这不是 bug |
|
|
97
|
+
| `before:2026-02-31` | 同上:非法日期不当作边界,也不会被当成 3 月 1 日 |
|
|
98
|
+
|
|
99
|
+
注意时区:无时区的日期按**本机本地时间**解释,与截止时间输入框的行为一致。如果你的机器是 +08:00,`before:2026-11-01` 指的是本地 11 月 1 日 00:00。
|
|
100
|
+
|
|
101
|
+
### 4. 读屏(0.16.0)
|
|
102
|
+
|
|
103
|
+
用 NVDA 或 Windows 讲述人过一遍:
|
|
104
|
+
|
|
105
|
+
| 位置 | 期望 |
|
|
106
|
+
|---|---|
|
|
107
|
+
| 分组头(会话 / 时间 / 级别 三种分组下都有) | 朗读「已展开 / 已收起」;用键盘 Space/Enter 可切换 |
|
|
108
|
+
| 顶部筛选(全部 / 未完成 / …) | 当前筛选项朗读为「已按下」 |
|
|
109
|
+
| 操作提示(例如「已让某对话抓取」) | 作为状态区域被朗读一次,不会抢焦点 |
|
|
110
|
+
| 错误横幅 | 立即朗读(alert) |
|
|
111
|
+
| 纯图标按钮(关闭、更多、保存等) | 有可读名称,不是「按钮」两个字 |
|
|
112
|
+
|
|
113
|
+
> 验证方法:这些状态是**读屏软件从 ARIA 属性原生翻译**出来的,所以查代码里是否挂了属性
|
|
114
|
+
> (`aria-expanded` / `aria-pressed` / live region),**不要**去源码里搜「已展开」「已按下」字面量——
|
|
115
|
+
> 那样会误判成 FAIL(`#6` 里对方第一版就是这么误判的,随后自己更正)。
|
|
116
|
+
|
|
117
|
+
### 回归(每次都跑,10 秒)
|
|
118
|
+
|
|
119
|
+
```powershell
|
|
120
|
+
npm run check:windows # 7 项真实文件系统冒烟
|
|
121
|
+
npm run check:contracts # 58 项跨字段契约,模块级、离线
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
两项都过,再填上面四节的表格。哪一格和期望不符,就按「What to report if something fails」的四条信息回给我。
|
|
125
|
+
|
|
126
|
+
## 常设三问:每版发版前必答
|
|
127
|
+
|
|
128
|
+
三轮 Windows 测试(#2/#4/#5/#6)打的都是同一类 bug:**同一个值在两层或两平台被不同规则解释**,而每层单测都绿。
|
|
129
|
+
所以除了上面具体的功能清单,发版前固定问这三句:
|
|
130
|
+
|
|
131
|
+
1. **两层口径**:新字段/新解析器在 **HTTP 校验层**与**文件容错层**的行为是否都有定义,且文档说的是同一件事?
|
|
132
|
+
(`#5` 的 `null`、`#3` 的 `settings` 形状,都是这一问漏掉的。)
|
|
133
|
+
2. **时区**:新的时间/日期输入,在**非 UTC 机器**上过判别对了吗?要覆盖边界日本身、非整点时区、DST。
|
|
134
|
+
(`#6` 就是这一问:`Date.parse('YYYY-MM-DD')` 是 UTC 零点,而 `dueAt` 按本地录。)
|
|
135
|
+
3. **路径四态**:新的路径处理,**盘符 / 反斜杠 / UNC / 大小写**都过了吗?(`#2`、`#3` 的豁免路径、Windows 测试轮都在这。)
|
|
136
|
+
|
|
137
|
+
这三问的教训来源是 Windows 测试轮 #2–#6;有 `npm run check:contracts` 兜住一半,剩下的一半只能靠发版前问。
|
|
138
|
+
|
|
42
139
|
## What to report if something fails
|
|
43
140
|
|
|
44
141
|
1. the check name from the `FAIL` line and the full message;
|
package/lib/index.js
CHANGED
|
@@ -37,7 +37,7 @@ import { createStore, resolveStorePath } from './store.js'
|
|
|
37
37
|
import { createTools, normalizeToolGroups, selectTools } from './tools.js'
|
|
38
38
|
|
|
39
39
|
/** Must equal `package.json`'s version; `npm run check` enforces that. */
|
|
40
|
-
export const VERSION = '0.16.
|
|
40
|
+
export const VERSION = '0.16.3'
|
|
41
41
|
|
|
42
42
|
/** Plugin id. Also the Loader row id in `cordis.patch.yml`. */
|
|
43
43
|
export const name = 'dsh-global-todo'
|
package/lib/model.js
CHANGED
|
@@ -139,9 +139,17 @@ export function parseDueText(value) {
|
|
|
139
139
|
if (match[4] !== undefined && (Number(match[4]) > 23 || Number(match[5]) > 59 || Number(match[6] ?? 0) > 59)) {
|
|
140
140
|
return { ok: false, reason: '时间不合法' }
|
|
141
141
|
}
|
|
142
|
-
// A
|
|
143
|
-
//
|
|
144
|
-
|
|
142
|
+
// A date without a time means "that day, as the person reading the list experiences it", so
|
|
143
|
+
// it is anchored at **local** midnight. `Date.parse('2026-11-01')` is UTC midnight per the
|
|
144
|
+
// specification — on +08 that is 08:00 local, which made `before:2026-11-01` swallow the
|
|
145
|
+
// first eight hours of the bound day (issue #6). Date-times keep their usual meaning: no
|
|
146
|
+
// offset means local, an offset means that offset.
|
|
147
|
+
let parsed
|
|
148
|
+
if (match[4] === undefined) {
|
|
149
|
+
parsed = new Date(year, month - 1, day, 0, 0, 0, 0).getTime()
|
|
150
|
+
} else {
|
|
151
|
+
parsed = Date.parse(text)
|
|
152
|
+
}
|
|
145
153
|
if (Number.isNaN(parsed)) return { ok: false, reason: '无法解析' }
|
|
146
154
|
return { ok: true, iso: new Date(parsed).toISOString() }
|
|
147
155
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-global-todo",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.3",
|
|
4
4
|
"icon": "./docs/icon.svg",
|
|
5
5
|
"description": "Cross-session todo list for DeepSeek Harness: one JSON file a person and an agent both write to, with step plans that ship as a numbered hand-off, session read-back, and a human confirmation before an agent's \"done\" counts.",
|
|
6
6
|
"type": "module",
|
|
@@ -83,7 +83,10 @@
|
|
|
83
83
|
"prepack": "npm run verify",
|
|
84
84
|
"check:render": "node tools/preview.mjs --check",
|
|
85
85
|
"check:live": "node tools/live-check.mjs",
|
|
86
|
-
"check:matrix": "node scripts/matrix.mjs"
|
|
86
|
+
"check:matrix": "node scripts/matrix.mjs",
|
|
87
|
+
"market": "node tools/market.mjs",
|
|
88
|
+
"market:check": "node tools/market.mjs --check",
|
|
89
|
+
"market:fresh": "node tools/market.mjs --fresh"
|
|
87
90
|
},
|
|
88
91
|
"dsh": {
|
|
89
92
|
"manifestVersion": 1,
|