dsh-notify-say 0.4.51 → 0.4.52

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
@@ -3,6 +3,10 @@
3
3
  > 本文件由 `tools/release-build.ps1` 从开发提交自动生成,**请勿手工编辑**。
4
4
  > 只列面向使用者的变更(新增功能与修复),不含内部维护提交。
5
5
 
6
+ ## v0.4.52 — 2026-10-18
7
+
8
+ - fix: v0.4.52 —— 修 CI 红:发布包补 .gitattributes + 恢复 ps1 BOM
9
+
6
10
  ## v0.4.51 — 2026-10-18
7
11
 
8
12
  - fix: v0.4.51 —— 第四轮审阅 5 项(含一个 pnpm 误判的真 bug)
package/README.md CHANGED
@@ -330,7 +330,7 @@ npm run test:route # 需要 --import loader 的接线测试
330
330
  npm run test:audio-wire
331
331
  ```
332
332
 
333
- **403 条测试通过。** 绝大多数是纯逻辑测试,克隆仓库后 `npm test` 即可跑。
333
+ **405 条测试通过。** 绝大多数是纯逻辑测试,克隆仓库后 `npm test` 即可跑。
334
334
 
335
335
  少数用例需要真实的 DSH 宿主(用于验证 Cordis 上下文行为)。
336
336
  找不到宿主时它们会**自动 skip** —— 注意 skip 不等于通过。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-notify-say",
3
- "version": "0.4.51",
3
+ "version": "0.4.52",
4
4
  "description": "Desktop notifications for DSH Desktop that actually speak: Windows TTS out of the box (zero download), VOICEVOX voice packs optional, a selectable system-sound fallback, and an idle gate that waits for running subagents before saying the turn is done. Includes a settings-page GUI (sound source, per-event overrides, jump-back-to-session, cooldowns) and a self hot-reload for development.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -492,4 +492,63 @@ test('D17: README 如实说明检查更新也会联网', () => {
492
492
  // 也要说明失败不影响功能
493
493
  assert.match(README, /不影响通知|照常工作/,
494
494
  '应说明联网失败不影响通知与语音');
495
+ });
496
+ // ── D18: 所有 .ps1 必须带 UTF-8 BOM ─────────────────────────────────────
497
+ test('D18: PowerShell 脚本必须有 UTF-8 BOM(含维护者工具)', () => {
498
+ // ⚠️ 2026-10-18 我自己踩的坑:
499
+ //
500
+ // 用 Node 或 .NET 编辑 .ps1 时,`writeFileSync(..., 'utf8')` /
501
+ // `WriteAllText(..., UTF8Encoding($false))` 会**丢掉 BOM**。
502
+ // 而 PowerShell 5.1 在没有 BOM 时按系统 ANSI(中文系统是 GBK)解码,
503
+ // 于是文件里的中文变成乱码 → 语法错误 → 构建直接崩:
504
+ //
505
+ // Missing closing ')' in expression.
506
+ // master-voice.wav锛坉one 鍏滃簳锛?
507
+ //
508
+ // CI 里有 BOM 检查,但它只看**发布包里的** ps1 ——
509
+ // `tools/release-build.ps1` 与 `tools/release.ps1` 是维护者工具、不进发布包,
510
+ // 所以它们的 BOM 一直没人查,这次才崩在本地。
511
+ const bad = [];
512
+ const walk = (dir) => {
513
+ let entries = [];
514
+ try { entries = readdirSync(dir, { withFileTypes: true }); } catch { return; }
515
+ for (const e of entries) {
516
+ if (e.name === 'node_modules' || e.name.startsWith('.tmp')) continue;
517
+ const p = join(dir, e.name);
518
+ if (e.isDirectory()) { walk(p); continue; }
519
+ if (!e.name.toLowerCase().endsWith('.ps1')) continue;
520
+ try {
521
+ const buf = readFileSync(p);
522
+ const hasBom = buf.length >= 3 && buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf;
523
+ if (!hasBom) bad.push(p.slice(ROOT.length + 1));
524
+ } catch { /* 读不到就跳过 */ }
525
+ }
526
+ };
527
+ walk(ROOT);
528
+
529
+ assert.deepEqual(bad, [],
530
+ '这些 .ps1 没有 UTF-8 BOM —— PowerShell 5.1 会把中文读成乱码然后语法报错:\n'
531
+ + bad.join('\n'));
532
+ });
533
+
534
+ // ── D19: .gitattributes 必须随包分发 ────────────────────────────────────
535
+ test('D19: 发布包带 .gitattributes(否则 Windows 上 checkout 会改成 CRLF)', () => {
536
+ // 2026-10-18 实测:CI 跑在 windows-latest,公开仓库当时没有 .gitattributes,
537
+ // `actions/checkout` 按 autocrlf=true 把 .ps1 转成 CRLF,
538
+ // 而开发机是 LF → D16 在 CI 全红(同样的提交,字节不同)。
539
+ assert.ok(existsSync(join(ROOT, '.gitattributes')),
540
+ '插件目录应有自己的 .gitattributes,并随包分发');
541
+
542
+ const ga = readFileSync(join(ROOT, '.gitattributes'), 'utf8');
543
+ assert.match(ga, /\*\.ps1\s+text eol=lf/,
544
+ '.gitattributes 应把 .ps1 定为 LF');
545
+ assert.match(ga, /\*\.wav\s+binary/,
546
+ '音频必须标 binary,否则换行转换会损坏文件');
547
+
548
+ // 若这是开发目录,还要确认 release-build 把它列进白名单
549
+ if (hasReleaseBuild) {
550
+ const rb = readFileSync(RELEASE_BUILD, 'utf8');
551
+ assert.match(rb, /'\.gitattributes'/,
552
+ 'release-build 的 includeFiles 必须含 .gitattributes,否则不会进发布包');
553
+ }
495
554
  });