dsh-disk-cleaner 1.6.0 → 1.6.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/README.md +49 -21
- package/lib/catalog.js +3 -3
- package/lib/client.js +2 -2
- package/lib/index.js +3 -2
- package/package.json +1 -1
- package/smoke.mjs +5 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<!-- badges -->
|
|
6
6
|
| | |
|
|
7
7
|
| --- | --- |
|
|
8
|
-
| **version** | `1.6.
|
|
8
|
+
| **version** | `1.6.2` |
|
|
9
9
|
| **DSH** | `0.2.1-rc.5`(开发与实测版本;用到 `plugins.bundle.config`、`settings.section`) |
|
|
10
10
|
| **license** | [MIT](LICENSE) |
|
|
11
11
|
| **Node** | `>= 22`(仅运行冒烟测试需要) |
|
|
@@ -76,7 +76,7 @@ Every path is built from this table — a caller selects an **id**, never a path
|
|
|
76
76
|
| `rewind-snapshots` | `session-*` folders under `%USERPROFILE%\.dsh\rewind-snapshots` | aged, 30 days | caution | a recent session stays restorable |
|
|
77
77
|
| `rotated-logs` | `*.old.log` and `*.log.N` files in the `logs` folders of the agent apps | aged, 3 days | safe | nothing reads a rotated file back |
|
|
78
78
|
| `qoder-old-versions` | version folders under `%LOCALAPPDATA%\Programs\Qoder\.qoder-versions` other than the one the launcher names | purge | caution | the launcher's `state.ini` names the build it runs; an unreadable one means nothing is removed |
|
|
79
|
-
| `orphan-app-data` | `%LOCALAPPDATA%\Tencent\QQGuild` -
|
|
79
|
+
| `orphan-app-data` | `%LOCALAPPDATA%\Tencent\QQGuild` - the QQGuild data folder | purge | caution | the whole folder is offered for deletion once no file in it has been written for 30 days |
|
|
80
80
|
| `app-data-caches` | Chromium caches under `%LOCALAPPDATA%` for Electron, DingTalk, JianyingPro and the WeChat devtools | aged, 7 days | caution | an app that still runs rewrites its cache constantly, so only a week-old tree qualifies |
|
|
81
81
|
| `office-update-cache` | `%LOCALAPPDATA%\Microsoft\Office\SolutionPackages` - update packages Office already applied | purge | caution | Office stages them before applying; nothing reads them back afterwards |
|
|
82
82
|
|
|
@@ -159,23 +159,31 @@ These are enforced in `lib/catalog.js` and must not be relaxed:
|
|
|
159
159
|
- `editor-builds` drops a build only when `bin\code.cmd` exists and names a different build that is also on disk; `old_x` goes only while `x` is still beside it.
|
|
160
160
|
- `database-backups` matches `.sqlite*.bak` by name only; the live `zotero.sqlite` is never a candidate.
|
|
161
161
|
- `qoder-old-versions` reads the launcher's `state.ini` for the build it runs; a missing or unparsable file, or a named build that is not on disk, removes nothing.
|
|
162
|
-
- `orphan-app-data`
|
|
162
|
+
- `orphan-app-data` is offered when the QQGuild folder exists and no file in it has been written in the last 30 days; the whole folder is then a full-delete target. It does not check shortcuts, uninstall entries, or Program Files.
|
|
163
163
|
- The directory Windows refuses to let an unelevated process write (`SoftwareDistribution\Download`) is labelled `elevation` and excluded from "reclaimable now". `C:\Windows\Temp` is **not** one of them on a default ACL: it grants `BUILTIN\Users` create and delete, so only EBUSY on a live file stops a delete there, which the age limit covers.
|
|
164
164
|
|
|
165
165
|
### Install
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
A catalog entry has been submitted to the curated [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) list, which powers **dshmarket → Discover** ([PR #12970](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/12970), pending review) — once it merges, search **dsh-disk-cleaner** there and install it in one click. Until then, use a direct install below.
|
|
168
|
+
|
|
169
|
+
Published on npm as [`dsh-disk-cleaner`](https://www.npmjs.com/package/dsh-disk-cleaner) — latest `1.6.2`:
|
|
168
170
|
|
|
169
171
|
```bash
|
|
170
172
|
npm i dsh-disk-cleaner
|
|
171
173
|
```
|
|
172
174
|
|
|
175
|
+
A prebuilt tarball is attached to the [v1.6.2 Release](https://github.com/stallenlu/dsh-disk-cleaner/releases/tag/v1.6.2); installing from it skips DSH's build-approval step:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
dsh plugin --profile <profile> add https://github.com/stallenlu/dsh-disk-cleaner/releases/download/v1.6.2/dsh-disk-cleaner-1.6.2.tgz
|
|
179
|
+
```
|
|
180
|
+
|
|
173
181
|
Then enable it in the profile — in `$DSH_PROFILE_DIR/package.json`:
|
|
174
182
|
|
|
175
183
|
```json
|
|
176
184
|
{
|
|
177
185
|
"dependencies": {
|
|
178
|
-
"dsh-disk-cleaner": "^1.
|
|
186
|
+
"dsh-disk-cleaner": "^1.6.2"
|
|
179
187
|
},
|
|
180
188
|
"dsh": {
|
|
181
189
|
"profile": {
|
|
@@ -196,7 +204,7 @@ The bundle's own `cordis.patch.yml` inserts the plugin row; no profile patch edi
|
|
|
196
204
|
### Development
|
|
197
205
|
|
|
198
206
|
```bash
|
|
199
|
-
node smoke.mjs #
|
|
207
|
+
node smoke.mjs # 85 assertions, zero dependencies
|
|
200
208
|
node --check lib/client.js # and lib/index.js, lib/catalog.js, lib/audit.js, lib/plan.js
|
|
201
209
|
```
|
|
202
210
|
|
|
@@ -225,6 +233,8 @@ What the smoke test deliberately does **not** cover: anything that walks a real
|
|
|
225
233
|
| A dry run reports what a real run frees | The 30-day rewind window reports 263 KB not 283 MB, and scan matches the dry run |
|
|
226
234
|
| Grouping and folding | The real `groupRows` runs out of the bundle against a mixed list: fixed order, per-section totals, an unknown group lands in "other", an empty section is the folded one. A click on a section head folds that section and only that one, and a folded section's rows drop out of bulk select |
|
|
227
235
|
| Visual layout | Checked by hand in the running Web UI. No browser automation here, so this one is a human check, not a test. |
|
|
236
|
+
| Agent tool returns a string matching its output schema | `node smoke.mjs` regression assertion (the 1.6.1 fix) |
|
|
237
|
+
| A real agent-tool delete invalidates the assessment cache | `node smoke.mjs` regression assertion (the 1.6.1 fix) |
|
|
228
238
|
|
|
229
239
|
### Implementation notes
|
|
230
240
|
|
|
@@ -248,20 +258,26 @@ What the smoke test deliberately does **not** cover: anything that walks a real
|
|
|
248
258
|
```
|
|
249
259
|
├─ package.json dsh.bundle.patch + dsh.client { platform: "web" }
|
|
250
260
|
├─ cordis.patch.yml - insert: id: dsh-disk-cleaner
|
|
251
|
-
├─ lib/index.js (
|
|
261
|
+
├─ lib/index.js (431) Host: HTTP route + disk_cleaner tool, same run() for both; reveal
|
|
252
262
|
├─ lib/catalog.js (1192) The 32 targets, measurePath / purgePath / resolveTargets / drives
|
|
253
263
|
├─ lib/audit.js (365) Read-only assessment, 10-minute cache, areaPaths, exposes no deletion
|
|
254
264
|
├─ lib/plan.js (150) Pure: measurements → ordered steps
|
|
255
|
-
├─ lib/client.js (
|
|
265
|
+
├─ lib/client.js (1493) Client half: slots, panel, preferences, zh/en dictionaries, CSS
|
|
256
266
|
├─ locale/{en,zh}.json Display metadata (meta.title / meta.description)
|
|
257
267
|
├─ icon.svg Plugin icon
|
|
258
268
|
├─ README.md This file
|
|
259
269
|
├─ LICENSE MIT
|
|
260
|
-
└─ smoke.mjs
|
|
270
|
+
└─ smoke.mjs 85 assertions, zero dependencies
|
|
261
271
|
```
|
|
262
272
|
|
|
263
273
|
Client-half slots: `sidebar.panellist` (order 50, disposed in settings-only mode), `main` (keyed by the package name), `settings.section` (order 30, disposed in sidebar-only mode), `plugins.bundle.config` (keyed by the package name).
|
|
264
274
|
|
|
275
|
+
### What's new
|
|
276
|
+
|
|
277
|
+
- **1.6.2** — Documentation only: the README, the in-source comment, the panel's zh/en explanations and the tool's note legend now describe `orphan-app-data` as it actually behaves (the QQGuild folder is offered for full deletion once no file in it has been written for 30 days), instead of claiming four independent signals and a two-year idle period. No behaviour change; the refreshed README ships in the npm package and the [v1.6.2 Release](https://github.com/stallenlu/dsh-disk-cleaner/releases/tag/v1.6.2) tarball.
|
|
278
|
+
- **1.6.1** — Fixed the `disk_cleaner` agent tool: `output.schema` now declares `type: 'string'`, matching the text `execute()` returns (previously every call was rejected by the host's output validator with `tool "disk_cleaner" returned invalid output: "value" must be an object`). A real delete through the agent tool now invalidates the assessment cache, the same way the panel's HTTP route does. Two regression assertions added; a prebuilt tarball ships on the [v1.6.1 Release](https://github.com/stallenlu/dsh-disk-cleaner/releases/tag/v1.6.1).
|
|
279
|
+
- **1.6.0** — The 32 targets are grouped under seven foldable headings.
|
|
280
|
+
|
|
265
281
|
---
|
|
266
282
|
|
|
267
283
|
<a id="中文"></a>
|
|
@@ -329,7 +345,7 @@ Client-half slots: `sidebar.panellist` (order 50, disposed in settings-only mode
|
|
|
329
345
|
| `rewind-snapshots` | `%USERPROFILE%\.dsh\rewind-snapshots` 下的 `session-*` 目录 | 保留期 30 天 | 注意 | 最近的会话仍然可以回滚 |
|
|
330
346
|
| `rotated-logs` | 各 agent 应用 `logs` 目录下的 `*.old.log` 与 `*.log.N` 文件 | 保留期 3 天 | 安全 | 轮转掉的日志不会被读回 |
|
|
331
347
|
| `qoder-old-versions` | `%LOCALAPPDATA%\Programs\Qoder\.qoder-versions` 下不是启动器所指的那个版本目录 | 全清 | 注意 | 启动器 `state.ini` 写明它跑哪个版本;读不到就一个都不删 |
|
|
332
|
-
| `orphan-app-data` | `%LOCALAPPDATA%\Tencent\QQGuild` ——
|
|
348
|
+
| `orphan-app-data` | `%LOCALAPPDATA%\Tencent\QQGuild` —— QQ 频道数据目录 | 全清 | 注意 | 目录内 30 天没有任何文件写入时,整个目录会被列为全清目标 |
|
|
333
349
|
| `app-data-caches` | `%LOCALAPPDATA%` 下 Electron、钉钉、剪映、微信开发者工具的 Chromium 缓存 | 保留期 7 天 | 注意 | 还在跑的程序会不停改写缓存,所以只有一周没动过的才算 |
|
|
334
350
|
| `office-update-cache` | `%LOCALAPPDATA%\Microsoft\Office\SolutionPackages` —— Office 已应用的更新暂存包 | 全清 | 注意 | Office 先暂存再应用,应用后没有东西会读回 |
|
|
335
351
|
|
|
@@ -411,23 +427,31 @@ Client-half slots: `sidebar.panellist` (order 50, disposed in settings-only mode
|
|
|
411
427
|
- `editor-builds` 只有在 `bin\code.cmd` 存在且指向另一份确实在磁盘上的构建时才删;`old_x` 也只有在 `x` 仍在旁边时才删。
|
|
412
428
|
- `database-backups` 只按名字匹配 `.sqlite*.bak`,正在用的 `zotero.sqlite` 永不成为候选。
|
|
413
429
|
- `qoder-old-versions` 从启动器的 `state.ini` 读出它实际运行哪个版本;文件缺失、解析不出、或它指的版本不在磁盘上,一律一个都不删。
|
|
414
|
-
- `orphan-app-data`
|
|
430
|
+
- `orphan-app-data` 的判据只有一条:QQGuild 目录存在,且目录内 30 天内没有任何文件被写入过,此时整个目录被列为全清目标。它不检查快捷方式、卸载项或 Program Files。
|
|
415
431
|
- 那个拒绝普通权限写入的 Windows 目录标为 `elevation`,并排除在「现在能回收」之外。
|
|
416
432
|
|
|
417
433
|
### 安装
|
|
418
434
|
|
|
419
|
-
|
|
435
|
+
已向精选目录 [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) 提交收录,它是 **dshmarket → 发现** 的数据源([PR #12970](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/12970),审核中)——合并后即可在 dshmarket 里搜索 **dsh-disk-cleaner** 一键安装。在那之前,用下面任一种直接安装方式。
|
|
436
|
+
|
|
437
|
+
已发布到 npm:[`dsh-disk-cleaner`](https://www.npmjs.com/package/dsh-disk-cleaner),最新版 `1.6.2`。
|
|
420
438
|
|
|
421
439
|
```bash
|
|
422
440
|
npm i dsh-disk-cleaner
|
|
423
441
|
```
|
|
424
442
|
|
|
443
|
+
[v1.6.2 Release](https://github.com/stallenlu/dsh-disk-cleaner/releases/tag/v1.6.2) 还附带一个预构建 tarball,从它安装可跳过 DSH 的构建授权步骤:
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
dsh plugin --profile <profile> add https://github.com/stallenlu/dsh-disk-cleaner/releases/download/v1.6.2/dsh-disk-cleaner-1.6.2.tgz
|
|
447
|
+
```
|
|
448
|
+
|
|
425
449
|
然后在 profile 里启用 —— 在 `$DSH_PROFILE_DIR/package.json`:
|
|
426
450
|
|
|
427
451
|
```json
|
|
428
452
|
{
|
|
429
453
|
"dependencies": {
|
|
430
|
-
"dsh-disk-cleaner": "^1.
|
|
454
|
+
"dsh-disk-cleaner": "^1.6.2"
|
|
431
455
|
},
|
|
432
456
|
"dsh": {
|
|
433
457
|
"profile": {
|
|
@@ -445,14 +469,10 @@ git clone https://github.com/stallenlu/dsh-disk-cleaner
|
|
|
445
469
|
|
|
446
470
|
bundle 自带的 `cordis.patch.yml` 会插入插件行,无需改 profile 的 patch。`link:` 依赖是符号链接,所以改 **client** 刷新页面即生效,改 **host**(`lib/index.js`)需要重新启用该 bundle 或重启 DSH。从 npm 装则是相反的一面:要升级就改版本号。
|
|
447
471
|
|
|
448
|
-
```bash
|
|
449
|
-
git clone https://github.com/stallenlu/dsh-disk-cleaner
|
|
450
|
-
```
|
|
451
|
-
|
|
452
472
|
### 开发
|
|
453
473
|
|
|
454
474
|
```bash
|
|
455
|
-
node smoke.mjs #
|
|
475
|
+
node smoke.mjs # 85 条断言,零依赖
|
|
456
476
|
node --check lib/client.js # 以及 lib/index.js、lib/catalog.js、lib/audit.js、lib/plan.js
|
|
457
477
|
```
|
|
458
478
|
|
|
@@ -481,6 +501,8 @@ node --check lib/client.js # 以及 lib/index.js、lib/catalog.js、li
|
|
|
481
501
|
| 预演报告的字节数等于真删能释放的字节数 | 30 天的回滚窗口报 263 KB 而不是 283 MB,且扫描结果与预演一致 |
|
|
482
502
|
| 分类与折叠 | 从 bundle 里取出真正的 `groupRows` 跑一组混合数据:顺序固定、按类合计、未知类别落到「其他」、空的类别是收起来的那个。点某一类的标题只折叠这一类,折叠里的行不参与批量选择 |
|
|
483
503
|
| 视觉排版 | 在运行中的 Web UI 里手工确认过。本环境没有浏览器自动化,所以这条是人眼检查,不是测试。 |
|
|
504
|
+
| agent 工具返回字符串且与 output.schema 一致 | `node smoke.mjs` 回归断言(1.6.1 修复) |
|
|
505
|
+
| agent 工具真删后评估缓存失效 | `node smoke.mjs` 回归断言(1.6.1 修复) |
|
|
484
506
|
|
|
485
507
|
### 实现要点
|
|
486
508
|
|
|
@@ -504,20 +526,26 @@ node --check lib/client.js # 以及 lib/index.js、lib/catalog.js、li
|
|
|
504
526
|
```
|
|
505
527
|
├─ package.json dsh.bundle.patch + dsh.client { platform: "web" }
|
|
506
528
|
├─ cordis.patch.yml - insert: id: dsh-disk-cleaner
|
|
507
|
-
├─ lib/index.js (
|
|
529
|
+
├─ lib/index.js (431) Host:HTTP 路由 + disk_cleaner 工具,共用同一个 run(),含 reveal
|
|
508
530
|
├─ lib/catalog.js (1192) 32 个目标,measurePath / purgePath / resolveTargets / drives
|
|
509
531
|
├─ lib/audit.js (365) 只读评估,10 分钟缓存,带 areaPaths,不暴露任何删除
|
|
510
532
|
├─ lib/plan.js (150) 纯函数:测量结果 → 有序步骤
|
|
511
|
-
├─ lib/client.js (
|
|
533
|
+
├─ lib/client.js (1493) Client 半面:slot、面板、偏好、zh/en 字典、CSS
|
|
512
534
|
├─ locale/{en,zh}.json 展示元数据(meta.title / meta.description)
|
|
513
535
|
├─ icon.svg 插件图标
|
|
514
536
|
├─ README.md 本文件
|
|
515
537
|
├─ LICENSE MIT
|
|
516
|
-
└─ smoke.mjs
|
|
538
|
+
└─ smoke.mjs 85 条断言,零依赖
|
|
517
539
|
```
|
|
518
540
|
|
|
519
541
|
Client 半面注册的 slot:`sidebar.panellist`(order 50,仅设置页模式下拆除)、`main`(以包名为 key)、`settings.section`(order 30,仅侧边栏模式下拆除)、`plugins.bundle.config`(以包名为 key)。
|
|
520
542
|
|
|
543
|
+
### 更新记录
|
|
544
|
+
|
|
545
|
+
- **1.6.2** — 仅文档修正:README、源码注释、面板中英文说明和工具里的注意码释义,现在都按真实行为描述 `orphan-app-data`(QQGuild 目录内 30 天没有文件写入时会被整目录列为可全清),不再声称「四条独立证据 / 两年未写」。行为不变;更新后的 README 也随 npm 包与 [v1.6.2 Release](https://github.com/stallenlu/dsh-disk-cleaner/releases/tag/v1.6.2) 的 tarball 一起发布。
|
|
546
|
+
- **1.6.1** — 修复了 `disk_cleaner` agent 工具:`output.schema` 现在声明 `type: 'string'`,与 `execute()` 返回的文本一致(此前每次调用都被宿主的输出校验器拒绝,报 `tool "disk_cleaner" returned invalid output: "value" must be an object`)。经由 agent 工具真删后也会让评估缓存失效,与面板的 HTTP 路径一致。新增两条回归断言;[v1.6.1 Release](https://github.com/stallenlu/dsh-disk-cleaner/releases/tag/v1.6.1) 附带预构建 tarball。
|
|
547
|
+
- **1.6.0** — 32 个目标按七个可折叠分组归类。
|
|
548
|
+
|
|
521
549
|
## License
|
|
522
550
|
|
|
523
551
|
[MIT](LICENSE)
|
package/lib/catalog.js
CHANGED
|
@@ -872,9 +872,9 @@ const CATALOG = [
|
|
|
872
872
|
roots: ['LOCALAPPDATA'],
|
|
873
873
|
paths: () => {
|
|
874
874
|
const guild = path.join(env('LOCALAPPDATA') ?? '', 'Tencent', 'QQGuild');
|
|
875
|
-
//
|
|
876
|
-
//
|
|
877
|
-
//
|
|
875
|
+
// The QQGuild data folder is offered for full deletion when it exists and no file
|
|
876
|
+
// inside it has been written in the last 30 days. Nothing else is checked - no
|
|
877
|
+
// shortcut, uninstall entry or Program Files probe. Keep the docs in step with this.
|
|
878
878
|
const recent = newestMtime(guild) > Date.now() - 30 * DAY;
|
|
879
879
|
return isDir(guild) && !recent ? [guild] : [];
|
|
880
880
|
},
|
package/lib/client.js
CHANGED
|
@@ -41,7 +41,7 @@ window.__ModuleLoader__.load({
|
|
|
41
41
|
'why_pending-update': '只清 {n} 天前的下载,避免删掉还没装的更新',
|
|
42
42
|
why_rollback: '每个插件/程序只留版本号最高的一份,其余是回滚副本',
|
|
43
43
|
why_superseded: '版本号不高于已装版本的更新包,装着的那份已经生效',
|
|
44
|
-
why_orphan: '
|
|
44
|
+
why_orphan: 'QQ 频道数据目录:目录内 30 天没有任何文件写入时会被整目录清除',
|
|
45
45
|
why_history: '每个会话的整文件备份,删了不影响会话本身',
|
|
46
46
|
why_duplicate: '内容完全相同的重复副本,保留最新那份',
|
|
47
47
|
'why_database-backup': '升级前的数据库副本,正在用的数据库还在旁边',
|
|
@@ -213,7 +213,7 @@ window.__ModuleLoader__.load({
|
|
|
213
213
|
'why_pending-update': 'only downloads older than {n} day(s), so a pending update survives',
|
|
214
214
|
why_rollback: 'only the highest version of each family stays; the rest are rollback copies',
|
|
215
215
|
why_superseded: 'the update package version is not above what is installed, so it is already applied',
|
|
216
|
-
why_orphan: 'the
|
|
216
|
+
why_orphan: 'the QQGuild data folder, deleted in full when no file in it has been written for 30 days',
|
|
217
217
|
why_history: 'a whole-file backup per session; removing it does not touch the session',
|
|
218
218
|
why_duplicate: 'an identical copy; the newest one is kept',
|
|
219
219
|
'why_database-backup': 'a copy made before an upgrade; the live database is beside it',
|
package/lib/index.js
CHANGED
|
@@ -210,7 +210,7 @@ const NOTE_MEANING = {
|
|
|
210
210
|
history: 'a backup snapshot of file edits that nothing reads back; the live state sits beside it',
|
|
211
211
|
duplicate: 'a byte-identical copy of a directory that is still present',
|
|
212
212
|
'database-backup': 'a copy of a database file taken before an upgrade; the live database is beside it',
|
|
213
|
-
orphan: 'the
|
|
213
|
+
orphan: 'the QQGuild data folder is deleted in full when no file in it has been written for 30 days',
|
|
214
214
|
};
|
|
215
215
|
|
|
216
216
|
const formatBytes = (bytes) => {
|
|
@@ -349,7 +349,7 @@ export function apply(ctx) {
|
|
|
349
349
|
additionalProperties: false,
|
|
350
350
|
},
|
|
351
351
|
output: {
|
|
352
|
-
schema: { type: '
|
|
352
|
+
schema: { type: 'string' },
|
|
353
353
|
render: (args, value) => [{ type: 'text', text: typeof value === 'string' ? value : JSON.stringify(value, null, 2) }],
|
|
354
354
|
},
|
|
355
355
|
timeoutMs: 300_000,
|
|
@@ -413,6 +413,7 @@ export function apply(ctx) {
|
|
|
413
413
|
if (ids === undefined || ids.length === 0) throw new Error('clean needs at least one target id');
|
|
414
414
|
const dryRun = args.confirm !== true;
|
|
415
415
|
const results = await clean(ids, { dryRun, drive: readDrive(args.drive) });
|
|
416
|
+
if (!dryRun) invalidateAudit();
|
|
416
417
|
const freed = results.reduce((sum, item) => sum + item.bytes, 0);
|
|
417
418
|
const files = results.reduce((sum, item) => sum + item.removed, 0);
|
|
418
419
|
const failed = results.reduce((sum, item) => sum + item.failed, 0);
|
package/package.json
CHANGED
package/smoke.mjs
CHANGED
|
@@ -260,6 +260,11 @@ check(
|
|
|
260
260
|
check('tool needs no id for overview', JSON.stringify(definition.parameters.required) === JSON.stringify(['action']));
|
|
261
261
|
check('tool description warns audit is read-only', /read-only: it never removes anything/.test(definition.description));
|
|
262
262
|
check('every effect is labelled', applied.every((label) => typeof label === 'string' && label.startsWith('dsh-disk-cleaner:')));
|
|
263
|
+
check('tool output schema matches its string reply', definition.output.schema.type === 'string' && typeof (await definition.execute({ action: 'overview' })) === 'string');
|
|
264
|
+
check('the read-only agent clean keeps the audit cache in sync', /if \(!dryRun\) invalidateAudit\(\);[\s\S]*const freed = results\.reduce/.test(index));
|
|
265
|
+
check('orphan target descriptions state the real 30-day rule, not four signals / two years',
|
|
266
|
+
/30 days/.test(catalog) && /30 days/.test(index) && /QQGuild data folder/.test(source) &&
|
|
267
|
+
!/four independent signals|over two years|no Start-menu shortcut|two years/.test(catalog + index + source));
|
|
263
268
|
|
|
264
269
|
const ids = [...catalog.matchAll(/^\s{4}id: '([a-z-]+)',$/gm)].map((m) => m[1]);
|
|
265
270
|
check('catalog has the documented 32 targets', ids.length === 32, `got ${ids.length}`);
|