dsh-plugin-windows-guard 0.2.0 → 0.2.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
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.2] - 2026-09-10
4
+
5
+ - 修复:L3 重定向拦截对命令中部 `> file.json` 的漏放(锚点逻辑缺口),现覆盖任意位置的 `>` 重定向写结构化文件;
6
+ - 修复:`windows_encode_fix` 对「UTF-8 BOM 存在但主体非合法 UTF-8」的文件改报明确的「无法判定编码」错误,不再走崩溃报错路径;
7
+ - 修复:移除对 `.gd`(Godot)扩展名的误拦截;
8
+ - 自检:selfcheck 版本断言改为通用格式校验(不再硬编码具体版本号);
9
+ - 文档:README 同步拦截能力与工具行为描述;相关插件表格修复断行。
10
+
11
+ ## [0.2.1] - 2026-08-29
12
+
13
+ - 文档:首屏前置「255 个真实会话」钩子;安装节改为单行 dsh plugin add 命令并去掉作者本机绝对路径;新增「装完你会看到什么」与徽章行;
14
+ - 元数据:keywords 补长尾词(mojibake/write-guard 等,15 → 20);
15
+ - 新增英文版 README.en.md 与双语切换行。
3
16
  ## [0.2.0] - 2026-08-29
4
17
 
5
18
  - **合并 `dsh-plugin-pwsh-guard` 全部主动防护能力(该插件同日删除,本插件为唯一后继)**:
package/README.en.md ADDED
@@ -0,0 +1,207 @@
1
+ <p align="center">
2
+ <img src="docs/banner.svg" alt="dsh-plugin-windows-guard banner" width="100%">
3
+ </p>
4
+
5
+ # dsh-plugin-windows-guard
6
+
7
+ ![npm version](https://img.shields.io/npm/v/dsh-plugin-windows-guard)
8
+ ![npm downloads](https://img.shields.io/npm/dm/dsh-plugin-windows-guard)
9
+ ![License](https://img.shields.io/github/license/Pasumao/dsh-plugin-windows-guard)
10
+ ![Stars](https://img.shields.io/github/stars/Pasumao/dsh-plugin-windows-guard?style=social)
11
+ ![AI Assisted](https://img.shields.io/badge/AI-Assisted-8A2BE2)
12
+
13
+ [中文](./README.md) | **English**
14
+
15
+ The DeepSeek Harness (dsh) **Windows pitfall-guard plugin** — **high-frequency
16
+ pitfalls distilled from 255 real session archives**, with two capability
17
+ layers: guidelines (skills) + proactive protection (hooks/tools):
18
+
19
+ - **Guideline layer** (since 0.1.0): two self-contained skills auto-loaded by
20
+ scenario — preventive rules for "getting it right the first time";
21
+ - **Proactive protection layer** (since 0.2.0, merged from
22
+ `dsh-plugin-pwsh-guard`, which has since been deleted): automatic mojibake
23
+ detection hints for pwsh results, dangerous write-command interception, and
24
+ encoding diagnosis/repair tools.
25
+
26
+ Zero runtime dependencies, zero build.
27
+
28
+ ## Features
29
+
30
+ ### Guideline layer: two auto-loaded skills
31
+
32
+ Split into two self-contained skills by trigger scenario (the
33
+ `<available_skills>` catalog auto-loads the body when the description
34
+ matches):
35
+
36
+ ### `windows-enc` — Encoding and PowerShell parsing (command/file-content errors)
37
+
38
+ | Section | Content | Source incidents (historical records) |
39
+ |---|---|---|
40
+ | 1 Environment fact card | pwsh 5.1/7 differences, `-Command` as a single argv with no shell escaping layer, OutputEncoding pinned, exit codes are authoritative | stderr misjudgment (git red progress, NativeCommandError) |
41
+ | 2 Three encoding iron rules | always read with `-Encoding UTF8`; write structured files with `WriteAllText(UTF8Encoding($false))`; BOM check / transcoding command templates | GBK misdecoding (`鎻掍欢`/`鈥?`), BOM corrupting package.json (startup incident #2), UTF-16 corruption |
42
+ | 3 Quoting and escaping quick reference | PS `''` escaping (backslash doesn't work), double-quote interpolation, `node -e`/`python -c` quoting hell → write a temp file | `SyntaxError: unterminated string literal`, quoting-nesting failures confirmed in testing |
43
+ | 4 Three mojibake "don'ts" | mojibake signature table (`鈥?`/`??OK??`/`\uFFFD`) + don't guess / don't quote it / re-read first | `??OK??`, `??? skill ????` mojibake treated as the answer |
44
+
45
+ ### `windows-sys` — System environment (troubleshooting)
46
+
47
+ | Section | Content | Source incidents |
48
+ |---|---|---|
49
+ | 1 Paths and filesystem | MAX_PATH/long paths, paths with spaces, EACCES/EBUSY file locks, junctions and `link:` realpath, path formats | `EACCES: realpath '...sock'`, deeply nested npm-cache paths |
50
+ | 2 Processes and ports | `netstat` port lookup, `Stop-Process`/`taskkill`, check before kill | port 3080/39090 conflicts, orphan processes |
51
+ | 3 Cross-platform misc | CRLF traps, `.cmd` script host/ExecutionPolicy, time zones, case sensitivity | novel-file CRLF checks, run.bat chcp 65001 |
52
+
53
+ ### Proactive protection layer (since 0.2.0, every layer switchable, all on by default)
54
+
55
+ | Layer | Mechanism | Effect |
56
+ |---|---|---|
57
+ | L2 | `tools/post-execute` listener | when a `pwsh` tool result shows GBK misdecoding / an FFFD flood / Chinese turned into question marks, automatically appends a `[windows-guard]` fix hint after the result (no interruption, the result body is never rewritten) |
58
+ | L3 | `tools/pre-execute` listener | intercepts commands that write JSON/YAML/TOML via `Set-Content`/`Add-Content`/`Out-File` without `-Encoding`, and `>` redirection into structured files (including mid-command `> file.json` anchor positions); denies them and offers the correct `[System.IO.File]::WriteAllText(...)` form |
59
+ | L4 | `windows_encode_detect` / `windows_encode_fix` tools | file encoding diagnosis (BOM/UTF-8/GBK/UTF-16 + confidence) and repair (→ UTF-8 without BOM, automatic `.windowsguard.bak` backup); `dryRun` diagnoses without writing; when the encoding cannot be determined (e.g. a BOM is present but the body is not valid UTF-8) it returns a clear error instead of crashing |
60
+
61
+ > History: the original pwsh-guard L1 system-prompt section is **no longer
62
+ > injected** — it has been replaced by the guideline skills above (loaded on
63
+ > demand, saving always-on tokens).
64
+
65
+ ## Configuration
66
+
67
+ Everything in `cordis.patch.yml` is switchable (all on by default):
68
+
69
+ ```yaml
70
+ - insert:
71
+ - id: dsh-plugin-windows-guard
72
+ name: dsh-plugin-windows-guard
73
+ config:
74
+ enabled: true # master switch (false = keep only the guideline skills, degrading to the pure-guideline 0.1.0 form)
75
+ postCheck: true # L2 pwsh-result mojibake detection + hint
76
+ preCheck: true # L3 dangerous write-command interception
77
+ detectTools: true # L4 encoding diagnosis/repair tools
78
+ ```
79
+
80
+ ## Installation
81
+
82
+ ```powershell
83
+ # npm (recommended)
84
+ dsh plugin --profile web add dsh-plugin-windows-guard
85
+ # or GitHub
86
+ dsh plugin --profile web add github:Pasumao/dsh-plugin-windows-guard
87
+ ```
88
+
89
+ Restart `dsh web` after installing for it to take effect. The package ships
90
+ its own `cordis.patch.yml` mount line, applied automatically — no manual
91
+ config edits needed; see the Configuration section for the switches.
92
+
93
+ Install from source (local development / debugging):
94
+
95
+ ```bash
96
+ git clone https://github.com/Pasumao/dsh-plugin-windows-guard.git
97
+ cd dsh-plugin-windows-guard # the directory can live anywhere (e.g. your plugins collection dir)
98
+ npm install
99
+ # Mount into the profile as a link: dependency:
100
+ # add to the profile's package.json dependencies
101
+ # "dsh-plugin-windows-guard": "link:<your-plugins-dir>/dsh-plugin-windows-guard"
102
+ # and add it to dsh.profile.bundles (or insert manually via cordis.patch.yml)
103
+ # then pnpm install + restart dsh web
104
+ ```
105
+
106
+ ## What you'll see after installation
107
+
108
+ - when `pwsh` tool output contains mojibake (`鈥?`/`鎻掍欢`/`锟斤拷`), a
109
+ `[windows-guard]` fix hint is appended to the end of the result;
110
+ - dangerous write commands such as `Set-Content`/`Add-Content`/`Out-File`
111
+ writing JSON/YAML/TOML without `-Encoding` are denied outright; `>`
112
+ redirection into structured files (including mid-command `> file.json`)
113
+ is intercepted too, with the
114
+ correct `[System.IO.File]::WriteAllText(...)` form attached;
115
+ - the tool list gains `windows_encode_detect` / `windows_encode_fix`
116
+ (encoding diagnosis and repair);
117
+ - the skill catalog gains the `windows-enc` / `windows-sys` pitfall-guard
118
+ guideline skills.
119
+
120
+ ## Usage
121
+
122
+ No configuration needed after installation. When the model runs into a
123
+ Windows command/encoding/mojibake/path/process/port task,
124
+ `skill({ name: "windows-enc" | "windows-sys" })` auto-loads the matching
125
+ guideline; you can also ask the model to load a skill manually to read the
126
+ full text.
127
+
128
+ ```text
129
+ User: Read D:\dsh\config\comfy_prompt.json and check the config
130
+ Model: Before reading, follow the guideline and use Get-Content -Encoding UTF8...
131
+ ```
132
+
133
+ ```text
134
+ User: Fix config.json for me, JSON.parse throws an error
135
+ Model: first windows_encode_detect on config.json → "utf-8-bom (confidence high)"
136
+ → windows_encode_fix config.json → converted to UTF-8 without BOM (backup .windowsguard.bak)
137
+ → verify that JSON parsing now passes
138
+ ```
139
+
140
+ ```powershell
141
+ # The model is told (via the guideline skills), and this kind of command is
142
+ # blocked by L3 with the correct form given:
143
+ # Set-Content -Path data.json -Value $json ← deny (PS5.1 writes UTF-16LE/BOM)
144
+ # [System.IO.File]::WriteAllText("data.json", $json, [System.Text.UTF8Encoding]::new($false)) ← correct
145
+ ```
146
+
147
+ ### Why split into two skills (design notes)
148
+
149
+ - **Always-on catalog cost**: two descriptions (~300 tokens) barely grows;
150
+ - **Trigger precision**: `windows-enc` covers "command/file-content errors"
151
+ (encoding/escaping/mojibake), `windows-sys` covers "system environment
152
+ troubleshooting" (paths/processes/ports/cross-platform) — clean boundaries,
153
+ no interference between them;
154
+ - **Body text halved on demand**: Windows "content error" tasks no longer
155
+ load the entire "system environment" section;
156
+ - Reserved for future topics (WSL/winget/containers…) to be folded into
157
+ `windows-sys` extensions.
158
+
159
+ ## Implementation notes
160
+
161
+ - Guidelines are registered via `ctx.skills.register` (the official skill
162
+ subsystem), with content as the SKILL.md body;
163
+ - L2/L3 use `ctx.on('tools/post-execute' | 'tools/pre-execute')`; L4 uses
164
+ `ctx.tools.register` (raw definition shape); no `@deepseek-ai/*` runtime
165
+ packages are imported (with link: realpath resolution, external dependencies
166
+ cannot be resolved from the plugin directory);
167
+ - L2 only applies to the tool named `pwsh` with successful results; L3 only
168
+ intercepts the narrow patterns guaranteed to corrupt writes — reads and
169
+ writes with explicit `-Encoding` pass through; the mojibake vocabulary is
170
+ based on measurements from historical sessions (11/12 positive/negative
171
+ cases passed);
172
+ - Requires `Node ≥22.5` (`TextDecoder('gbk')` needs full-icu, which official
173
+ builds include by default);
174
+ - Changes to skill bodies/tools/guards require a dsh restart (the host reads
175
+ the skills/ directory when applying plugins);
176
+ - Every layer's registration has a ctx capability guard: if any layer is
177
+ unavailable it degrades gracefully with a warning — the plugin never fails
178
+ to mount.
179
+
180
+ ## Related plugins
181
+
182
+ This plugin is part of **Pasumao's dsh plugin ecosystem**. Published plugins
183
+ that work well together:
184
+
185
+ | Plugin (npm) | GitHub | Description |
186
+ |---|---|---|
187
+ | [dsh-notify](https://www.npmjs.com/package/dsh-notify) | [GitHub](https://github.com/Pasumao/dsh-plugin-notify) | Native Windows notifications + system tray |
188
+ | [dsh-plugin-choice-refresh](https://www.npmjs.com/package/dsh-plugin-choice-refresh) | [GitHub](https://github.com/Pasumao/dsh-plugin-choice-refresh) | Choice enhancements: regenerate / more options |
189
+ | [dsh-plugin-dev-kb](https://www.npmjs.com/package/dsh-plugin-dev-kb) | [GitHub](https://github.com/Pasumao/dsh-plugin-dev-kb) | Plugin development knowledge base (full official docs mirror + skills) |
190
+ | [dsh-plugin-image-tools](https://www.npmjs.com/package/dsh-plugin-image-tools) | [GitHub](https://github.com/Pasumao/dsh-plugin-image-tools) | Image choice cards + inline reply images + blind-model image intake |
191
+ | [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) | [GitHub](https://github.com/Pasumao/dsh-plugin-table-zoom) | Floating viewer for long chat tables + one-click Markdown copy |
192
+ | [dsh-plugin-workbench](https://www.npmjs.com/package/dsh-plugin-workbench) | [GitHub](https://github.com/Pasumao/dsh-plugin-workbench) | VS Code-style file explorer + editable preview |
193
+ | [dsh-plugin-context-trim](https://www.npmjs.com/package/dsh-plugin-context-trim) | [GitHub repo](https://github.com/Pasumao/dsh-plugin-context-trim) | Per-session injection gate: trim skills / tools / prompt sections per session |
194
+
195
+ > For the rest of the series see [Pasumao · dsh plugins](https://github.com/Pasumao) —
196
+ > a ⭐ on GitHub is always appreciated.
197
+
198
+ ## AI-generated disclosure
199
+
200
+ Part of the code and documentation was AI-assisted (DeepSeek Harness), all
201
+ human-reviewed and verified against real sessions (the mojibake word list was
202
+ validated on historical sessions, 11/12 positives/negatives; L3 interception
203
+ rules were hand-checked one by one).
204
+
205
+ ## License
206
+
207
+ [MIT](./LICENSE)
package/README.md CHANGED
@@ -1,8 +1,19 @@
1
+ <p align="center">
2
+ <img src="docs/banner.svg" alt="dsh-plugin-windows-guard banner" width="100%">
3
+ </p>
4
+
1
5
  # dsh-plugin-windows-guard
2
6
 
3
- DeepSeek Harness (dsh) 的 **Windows 环境防坑插件**:守则(skill)+ 主动防护(hooks/工具)。
7
+ ![npm version](https://img.shields.io/npm/v/dsh-plugin-windows-guard)
8
+ ![npm downloads](https://img.shields.io/npm/dm/dsh-plugin-windows-guard)
9
+ ![License](https://img.shields.io/github/license/Pasumao/dsh-plugin-windows-guard)
10
+ ![Stars](https://img.shields.io/github/stars/Pasumao/dsh-plugin-windows-guard?style=social)
11
+ ![AI Assisted](https://img.shields.io/badge/AI-Assisted-8A2BE2)
12
+
13
+ [**中文**](./README.md) | [English](./README.en.md)
4
14
 
5
- 把本机 255 个会话归档里反复出现的 Windows 高频坑,沉淀成两层能力:
15
+ DeepSeek Harness (dsh) 的 **Windows 环境防坑插件**——**源自 255 个真实会话归档的
16
+ 高频踩坑**,守则(skill)+ 主动防护(hooks/工具)两层能力:
6
17
 
7
18
  - **守则层**(0.1.0 起):两个自包含 skill 按场景自动加载——「一次写对」的预防性守则;
8
19
  - **主动防护层**(0.2.0 起,自 `dsh-plugin-pwsh-guard` 合并,该插件已删除):
@@ -38,8 +49,8 @@ DeepSeek Harness (dsh) 的 **Windows 环境防坑插件**:守则(skill)+
38
49
  | 层 | 机制 | 作用 |
39
50
  |---|---|---|
40
51
  | L2 | `tools/post-execute` 监听 | `pwsh` 工具结果出现 GBK 误解码/FFFD 洪水/中文变问号时,自动在结果后附加 `[windows-guard]` 修复提示(不中断、不改写结果本体) |
41
- | L3 | `tools/pre-execute` 监听 | 拦截「不带 -Encoding 的 `Set-Content`/`Add-Content`/`Out-File` 写 JSON/YAML/TOML/GD」与「`>` 重定向写结构化文件」命令,deny 并给出 `[System.IO.File]::WriteAllText(...)` 正确写法 |
42
- | L4 | `windows_encode_detect` / `windows_encode_fix` 工具 | 文件编码诊断(BOM/UTF-8/GBK/UTF-16 + 置信度)与修复(→ UTF-8 无 BOM,自动备份 `.windowsguard.bak`);`dryRun` 只诊断不写入 |
52
+ | L3 | `tools/pre-execute` 监听 | 拦截「不带 -Encoding 的 `Set-Content`/`Add-Content`/`Out-File` 写 JSON/YAML/TOML」与「`>` 重定向写结构化文件」(含命令中部 `> file.json` 等锚点位置),deny 并给出 `[System.IO.File]::WriteAllText(...)` 正确写法 |
53
+ | L4 | `windows_encode_detect` / `windows_encode_fix` 工具 | 文件编码诊断(BOM/UTF-8/GBK/UTF-16 + 置信度)与修复(→ UTF-8 无 BOM,自动备份 `.windowsguard.bak`);`dryRun` 只诊断不写入;无法判定编码(如 BOM 存在但主体非合法 UTF-8)时返回明确错误而非报错崩溃 |
43
54
 
44
55
  > 历史:原 pwsh-guard 的 L1 系统提示词段**不再注入**——由上面的守则技能取代
45
56
  > (按需加载、更省常驻 token)。
@@ -62,21 +73,39 @@ DeepSeek Harness (dsh) 的 **Windows 环境防坑插件**:守则(skill)+
62
73
  ## 安装
63
74
 
64
75
  ```powershell
65
- # 本地 link 开发(本仓库):
66
- git clone https://github.com/Pasumao/dsh-plugin-windows-guard.git D:\dsh\plugins\dsh-plugin-windows-guard
67
- # 1. profile package.json dependencies 加
68
- # "dsh-plugin-windows-guard": "link:D:/dsh/plugins/dsh-plugin-windows-guard"
69
- # 2. 加入 dsh.profile.bundles(或 cordis.patch.yml 手动 insert)
70
- cd C:\Users\18303\.dsh\profiles\web
71
- pnpm install
72
- node D:\dsh\scripts\check-profile.mjs # 自检 [PASS] 再重启
73
- powershell -NoProfile -ExecutionPolicy Bypass -File D:\dsh\scripts\restart-dsh.ps1
74
-
75
- # npm 分发安装(发布后):
76
- npm install dsh-plugin-windows-guard --prefix C:\Users\18303\.dsh\profiles\web
77
- # 并在 profile 包/补丁中挂载,其余同上
76
+ # npm(推荐)
77
+ dsh plugin --profile web add dsh-plugin-windows-guard
78
+ # GitHub
79
+ dsh plugin --profile web add github:Pasumao/dsh-plugin-windows-guard
78
80
  ```
79
81
 
82
+ 装完重启 `dsh web` 即生效。包自带 `cordis.patch.yml` 挂载行,自动应用,
83
+ 无需手动改配置;配置开关见「配置」节。
84
+
85
+ 源码安装(本地开发 / 调试):
86
+
87
+ ```bash
88
+ git clone https://github.com/Pasumao/dsh-plugin-windows-guard.git
89
+ cd dsh-plugin-windows-guard # 目录放在任意位置(如你的插件收集目录)
90
+ npm install
91
+ # 以 link: 依赖挂载进 profile:
92
+ # profile 的 package.json dependencies 加
93
+ # "dsh-plugin-windows-guard": "link:<你的插件目录>/dsh-plugin-windows-guard"
94
+ # 并加入 dsh.profile.bundles(或 cordis.patch.yml 手动 insert)
95
+ # 之后 pnpm install + 重启 dsh web
96
+ ```
97
+
98
+ ## 装完你会看到什么
99
+
100
+ - `pwsh` 工具输出出现乱码(`鈥?`/`鎻掍欢`/`锟斤拷`)时,结果末尾自动附加
101
+ `[windows-guard]` 修复提示;
102
+ - 不带 `-Encoding` 的 `Set-Content`/`Add-Content`/`Out-File` 写 JSON/YAML/TOML
103
+ 等危险写命令被直接拦截(deny),`>` 重定向写结构化文件(含命令中部的
104
+ `> file.json`)同样拦截,并附 `[System.IO.File]::WriteAllText(...)`
105
+ 正确写法;
106
+ - 工具列表多出 `windows_encode_detect` / `windows_encode_fix`(编码诊断与修复);
107
+ - 技能目录多出 `windows-enc` / `windows-sys` 两个防坑守则技能。
108
+
80
109
  ## 使用
81
110
 
82
111
  安装后无需任何配置。模型遇到 Windows 命令/编码/乱码/路径/进程/端口任务时,
@@ -123,11 +152,24 @@ npm install dsh-plugin-windows-guard --prefix C:\Users\18303\.dsh\profiles\web
123
152
 
124
153
  ## 相关插件
125
154
 
126
- 已发布插件互相引用(更多 DSH 插件生态):
155
+ 本插件属于 **Pasumao 的 dsh 插件生态**,同系列已发布插件可搭配使用:
156
+
157
+ | 插件(npm) | GitHub | 说明 |
158
+ |---|---|---|
159
+ | [dsh-notify](https://www.npmjs.com/package/dsh-notify) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-notify) | Windows 原生通知 + 系统托盘 |
160
+ | [dsh-plugin-choice-refresh](https://www.npmjs.com/package/dsh-plugin-choice-refresh) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-choice-refresh) | 选择增强:重新生成选项 / 更多选项 |
161
+ | [dsh-plugin-dev-kb](https://www.npmjs.com/package/dsh-plugin-dev-kb) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-dev-kb) | 插件开发知识库(官方文档完整镜像 + 技能) |
162
+ | [dsh-plugin-image-tools](https://www.npmjs.com/package/dsh-plugin-image-tools) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-image-tools) | 图片选择卡 + 回复内嵌图片 + 盲模型收图 |
163
+ | [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-table-zoom) | 聊天长表格浮窗查看 + 一键复制 Markdown |
164
+ | [dsh-plugin-workbench](https://www.npmjs.com/package/dsh-plugin-workbench) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-workbench) | VS Code 风格文件浏览器 + 可编辑预览 |
165
+ | [dsh-plugin-context-trim](https://www.npmjs.com/package/dsh-plugin-context-trim) | [GitHub 仓库](https://github.com/Pasumao/dsh-plugin-context-trim) | 会话注入门控:skill / tool / 提示词段落按会话裁剪 |
166
+ > 本系列其余插件见 [Pasumao · dsh 插件](https://github.com/Pasumao);觉得好用欢迎到 GitHub 点 ⭐。
167
+
168
+ ## AI 生成声明
169
+
170
+ 代码与文档由 AI 辅助生成(DeepSeek Harness),均经人工审查与实测验证
171
+ (乱码词表基于历史会话实测,11/12 正/负例通过;L3 拦截规则逐条人工核验)。
172
+
173
+ ## License
127
174
 
128
- - [dsh-plugin-workbench](https://www.npmjs.com/package/dsh-plugin-workbench) — VS Code 风格工作区文件浏览器 + 可编辑预览
129
- - [dsh-notify](https://www.npmjs.com/package/dsh-notify) — agent 停止/出错的 Windows 原生通知 + 托盘图标
130
- - [dsh-plugin-image-tools](https://www.npmjs.com/package/dsh-plugin-image-tools) — 图片选择卡 / 回复内嵌图片 / 聊天图片放大
131
- - [dsh-plugin-dev-kb](https://www.npmjs.com/package/dsh-plugin-dev-kb) — dsh 官方文档完整 Markdown 镜像(插件开发知识库)
132
- - [dsh-plugin-choice-refresh](https://www.npmjs.com/package/dsh-plugin-choice-refresh) — 选择卡「重新生成选项」/「更多选项」
133
- - [dsh-plugin-table-zoom](https://www.npmjs.com/package/dsh-plugin-table-zoom) — 聊天表格浮窗查看 + 一键复制 Markdown
175
+ [MIT](./LICENSE)
package/lib/encode.js CHANGED
@@ -183,9 +183,13 @@ export function fixToUtf8NoBom(path, opts = {}) {
183
183
  const diag = detectEncoding(buf)
184
184
  let text
185
185
  switch (diag.encoding) {
186
- case 'utf-8-bom':
187
- text = strictUtf8(buf.subarray(3)).text
186
+ case 'utf-8-bom': {
187
+ // BOM 主体若不是合法 UTF-8,无法判定编码——明确报错,不写文件不备份。
188
+ const body = strictUtf8(buf.subarray(3))
189
+ if (!body.ok) throw new Error(`无法判定编码(有 UTF-8 BOM 但主体不是合法 UTF-8),不执行写入:${path}`)
190
+ text = body.text
188
191
  break
192
+ }
189
193
  case 'utf-16le':
190
194
  case 'utf-16be':
191
195
  case 'utf-32le':
package/lib/index.js CHANGED
@@ -127,8 +127,8 @@ export async function postCheckHandler(exec, result, next) {
127
127
  // L3:pre-execute 危险写拦截(自 pwsh-guard 合并)
128
128
  // ---------------------------------------------------------------------------
129
129
 
130
- /** 结构文件扩展名(写坏会直接炸解析)。 */
131
- const STRUCTURED_EXT = /\.(json|ya?ml|toml|gd|lock)\b/i
130
+ /** 结构文件扩展名(写坏会直接炸解析)。不含 .gd:Godot 文件与 dsh 场景无关,属误杀源。 */
131
+ const STRUCTURED_EXT = /\.(json|ya?ml|toml|lock)\b/i
132
132
 
133
133
  /**
134
134
  * pre-execute 拦截:检测「确定会写坏文件」的 PowerShell 命令。
@@ -150,15 +150,14 @@ export function checkDangerousWrite(command) {
150
150
  ].join('\n')
151
151
  }
152
152
  }
153
- // 裸重定向写结构化文件(> file.json 等)
154
- if (/>>?\s*["']?[^"'\s]+\.(json|ya?ml|toml|gd)(?:["']|$)/i.test(command)) {
155
- const leading = /^>>?\s*["']?[^"'\s]+\.(json|ya?ml|toml|gd)/i.exec(command)
156
- if (leading) {
157
- return [
158
- `PowerShell 的 > 重定向默认按 UTF-16LE(5.1)编码写入,会破坏结构化文件。`,
159
- `请改用 [System.IO.File]::WriteAllText(path, content, (New-Object System.Text.UTF8Encoding($false))) 或 Out-File -Encoding utf8NoBOM。`,
160
- ].join('\n')
161
- }
153
+ // 裸重定向写结构化文件(> file.json 等):外层无锚点检测命中即拦截,
154
+ // 不要求重定向位于命令开头(原内层 ^ 锚点会漏放命令中部的 > file.json)。
155
+ // 仅对结构化扩展名生效,避免扩大误杀面。
156
+ if (/>>?\s*["']?[^"'\s]+\.(json|ya?ml|toml|lock)(?:["']|$)/i.test(command)) {
157
+ return [
158
+ `PowerShell 的 > 重定向默认按 UTF-16LE(5.1)编码写入,会破坏结构化文件。`,
159
+ `请改用 [System.IO.File]::WriteAllText(path, content, (New-Object System.Text.UTF8Encoding($false))) 或 Out-File -Encoding utf8NoBOM。`,
160
+ ].join('\n')
162
161
  }
163
162
  // Get-Content 读 UTF-8 文件不给 -Encoding(提示但放行:英文文件无害,交给 post-check)
164
163
  return undefined
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-plugin-windows-guard",
3
3
  "description": "DeepSeek Harness (dsh) Windows 环境防坑插件:两个防坑 skill(windows-enc/windows-sys:编码/转义/路径/进程/乱码预防规则)+ 三层主动防护(pwsh 结果乱码检测提示、危险写命令拦截、windows_encode_detect/fix 编码诊断修复工具)。零运行时依赖,零构建。",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -13,6 +13,7 @@
13
13
  "skills",
14
14
  "cordis.patch.yml",
15
15
  "README.md",
16
+ "README.en.md",
16
17
  "CHANGELOG.md",
17
18
  "scripts"
18
19
  ],
@@ -42,7 +43,12 @@
42
43
  "encoding",
43
44
  "utf-8",
44
45
  "gbk",
45
- "bom"
46
+ "bom",
47
+ "mojibake",
48
+ "garbled-text",
49
+ "powershell-guard",
50
+ "write-guard",
51
+ "hook"
46
52
  ],
47
53
  "license": "MIT",
48
54
  "homepage": "https://github.com/Pasumao/dsh-plugin-windows-guard#readme",
@@ -26,11 +26,11 @@ function t(name, fn) {
26
26
  }
27
27
 
28
28
  // ---- package 完整性 ----
29
- t('package.json name/main/patch 一致', () => {
29
+ t('package.json name/main/patch 一致 + 版本号合法', () => {
30
30
  assert.equal(pkg.name, 'dsh-plugin-windows-guard')
31
31
  assert.equal(pkg.main, 'lib/index.js')
32
32
  assert.ok(pkg.dsh?.bundle?.patch, '应有 bundle patch')
33
- assert.equal(pkg.version, '0.2.0', '版本应为 0.2.0')
33
+ assert.ok(typeof pkg.version === 'string' && /^\d+\.\d+\.\d+$/.test(pkg.version), `版本号应为非空 semver:${pkg.version}`)
34
34
  })
35
35
 
36
36
  // ---- 技能文件:拆分后的两个技能 ----