@moonquake2004/dsh-doctor 0.3.3 → 0.3.4

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 CHANGED
@@ -8,7 +8,7 @@ Zero npm dependencies. One file. Runs anywhere `node` exists (`zstd` needed only
8
8
 
9
9
  ## Why
10
10
 
11
- dsh's plugin tree is "fragile by install": a dangling reference, a broken `file:` link, a duplicate entry id, or a corrupted session log can brick the profile at boot or stall the whole web server — and `--dump-config` never mounts the loader, so it passes on broken setups. This class of failure was consolidated in [dsh discussion #1496](https://github.com/deepseek-ai/deepseek-harness/discussions/1496) (Advisory: plugin-install path needs guardrails). `dsh-doctor` is the offline check that advisory calls for — 20 built-in checks mapped to 18 community reports, each verified with synthetic negative fixtures, plus a self-updating remote catalog of declarative pattern checks (v0.2.0).
11
+ dsh's plugin tree is "fragile by install": a dangling reference, a broken `file:` link, a duplicate entry id, or a corrupted session log can brick the profile at boot or stall the whole web server — and `--dump-config` never mounts the loader, so it passes on broken setups. This class of failure was consolidated in [dsh discussion #1496](https://github.com/deepseek-ai/deepseek-harness/discussions/1496) (Advisory: plugin-install path needs guardrails). `dsh-doctor` is the offline check that advisory calls for — 26 built-in checks (env/profile/session) mapped to 18 community reports, each verified with synthetic negative fixtures, plus a self-updating remote catalog of 5 declarative pattern checks.
12
12
 
13
13
  ## Usage
14
14
 
@@ -26,7 +26,7 @@ Exit codes (default mode): `0` = all pass · `1` = problems found (built-in chec
26
26
 
27
27
  With `--envelope` (doctor-contract mode): `0` = all pass · `1` = any WARN · `2` = any FAIL. The envelope follows the shared `dsh-doctor/v1` schema (`{ schema, generatedAt, profile, exitCode, summary, ok, checks:[{name,status,detail}] }`) so implementations are interchangeable for CI/marketplace use. Installed via npm, the CLI is also available as the `dsh-doctor` bin.
28
28
 
29
- ## Checks (20)
29
+ ## Checks (26 built-in + 5 catalog = 31)
30
30
 
31
31
  ### env
32
32
  | ID | Checks | Discussion |
@@ -113,7 +113,7 @@ The tool also watches its own npm version: each run compares the installed versi
113
113
 
114
114
  ## Remote check catalog (v0.2.0)
115
115
 
116
- The built-in 20 checks are compiled into the tool. The **catalog** is a second, self-updating layer: `plugin/checks.json` in this repo holds declarative rules (data, not code), and every installed instance picks up new rules automatically — no reinstall needed.
116
+ The built-in 26 checks are compiled into the tool. The **catalog** is a second, self-updating layer: `plugin/checks.json` in this repo holds declarative rules (data, not code), and every installed instance picks up new rules automatically — no reinstall needed.
117
117
 
118
118
  - **How it works**: each run tries to fetch `plugin/checks.json` from GitHub (3s timeout) → on success it's cached to `$DSH_HOME/.cache/dsh-doctor/checks.json` (TTL 6h) → on failure it falls back to the last-known-good cache, then to the bundled copy. New checks therefore arrive within ≤6h of being committed upstream.
119
119
  - **Safety**: rules are **read-only probes** executed by the built-in engine (`command-exists`, `path-*`, `json-valid`, `text-contains` / `text-not-contains`, `file-size-above`, `glob-count`). The remote payload can never run code — it can only add pattern checks.
@@ -141,7 +141,7 @@ Safety invariants: closed probe vocabulary (LLM output is data, never code), pro
141
141
 
142
142
  ## Also installable as a dsh plugin
143
143
 
144
- The tool ships as a proper dsh bundle (`plugin/`), so you can run the same checks (20 built-in + catalog rules) from inside the web UI:
144
+ The tool ships as a proper dsh bundle (`plugin/`), so you can run the same checks (26 built-in + 5 catalog rules) from inside the web UI:
145
145
 
146
146
  ```bash
147
147
  # install into a profile (works from a checkout or a published path)
package/README.zh.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## 为什么
8
8
 
9
- dsh 的插件树"装出来就是脆的":一个悬空引用、一个断掉的 `file:` 链接、一个重复的 entry id、一段损坏的会话日志,都能让 profile 在启动时直接挂掉或拖垮整个 web 服务器——而 `--dump-config` 从不挂载 loader,所以在坏配置上也"一切正常"。这类故障被汇总在 [dsh discussion #1496](https://github.com/deepseek-ai/deepseek-harness/discussions/1496)(Advisory:插件安装路径需要护栏)。`dsh-doctor` 就是这个护栏——**20 项内置检查**映射到 18 个社区报告,每一项都用合成负样例验证过;外加一个**自更新的远程检查目录**(声明式规则,v0.2.0 起)。
9
+ dsh 的插件树"装出来就是脆的":一个悬空引用、一个断掉的 `file:` 链接、一个重复的 entry id、一段损坏的会话日志,都能让 profile 在启动时直接挂掉或拖垮整个 web 服务器——而 `--dump-config` 从不挂载 loader,所以在坏配置上也"一切正常"。这类故障被汇总在 [dsh discussion #1496](https://github.com/deepseek-ai/deepseek-harness/discussions/1496)(Advisory:插件安装路径需要护栏)。`dsh-doctor` 就是这个护栏——**26 项内置检查**(env 7 / profile 11 / session 8)映射到 18 个社区报告,每一项都用合成负样例验证过;外加一个**自更新的远程检查目录**(声明式规则,v0.2.0 起)。
10
10
 
11
11
  ## 用法
12
12
 
@@ -21,7 +21,7 @@ node dsh-doctor.mjs --no-catalog # 不拉远程目录(只用内置副
21
21
 
22
22
  退出码:`0` = 全部通过 · `1` = 发现问题(内置检查 + 目录中 `severity: error` 的项)· warn 级目录失败不改退出码。
23
23
 
24
- ## 检查项(20 内置 + 4 目录)
24
+ ## 检查项(26 内置 + 5 目录)
25
25
 
26
26
  ### env
27
27
  | ID | 检查 | 对应讨论 |
@@ -106,7 +106,7 @@ The `dsh-doctor/v1` envelope (`--json --envelope`) is the machine-readable form
106
106
 
107
107
  ## 远程检查目录(v0.2.0,层 A)
108
108
 
109
- 内置 20 项检查编译在工具里。**目录**是第二层、自更新的:本仓库的 `plugin/checks.json` 放声明式规则(**规则是数据,不是代码**),所有已装实例自动获取新规则——无需重装。
109
+ 内置 26 项检查编译在工具里。**目录**是第二层、自更新的:本仓库的 `plugin/checks.json` 放声明式规则(**规则是数据,不是代码**),所有已装实例自动获取新规则——无需重装。
110
110
 
111
111
  - **工作机制**:每次运行尝试从 GitHub 拉 `plugin/checks.json`(3s 超时)→ 成功后缓存到 `$DSH_HOME/.cache/dsh-doctor/checks.json`(TTL 6h)→ 失败回退 last-known-good 缓存 → 再回退内置副本。新检查因此在上游提交后 ≤6h 内自动到达。
112
112
  - **安全性**:规则是**只读探测原语**,由内置引擎执行(`command-exists`、`path-*`、`json-valid`、`text-contains` / `text-not-contains`、`file-size-above`、`glob-count`)。远程内容永远无法执行代码——只能新增模式检查。
@@ -134,7 +134,7 @@ The `dsh-doctor/v1` envelope (`--json --envelope`) is the machine-readable form
134
134
 
135
135
  ## 也可作为 dsh 插件安装
136
136
 
137
- 工具以标准 dsh bundle 形态发布(`plugin/`),可以在 web UI 里跑同样的检查(20 内置 + 目录规则):
137
+ 工具以标准 dsh bundle 形态发布(`plugin/`),可以在 web UI 里跑同样的检查(26 内置 + 5 目录规则):
138
138
 
139
139
  ```bash
140
140
  # 装进 profile(checkout 或已发布路径均可)
package/client/client.js CHANGED
@@ -1,4 +1,4 @@
1
- window.__ModuleLoader__.load({ id: "dsh-doctor", factory: (require) => {
1
+ window.__ModuleLoader__.load({ id: "@moonquake2004/dsh-doctor", factory: (require) => {
2
2
  var module = { exports: {} }; var exports = module.exports;
3
3
  'use strict'
4
4
 
package/cordis.patch.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  # dsh bundle patch: inserts this plugin into a profile's layer stack.
2
2
  - insert:
3
3
  - id: dsh-doctor
4
- name: 'dsh-doctor'
4
+ name: '@moonquake2004/dsh-doctor'
package/dsh-doctor.mjs CHANGED
@@ -99,6 +99,11 @@ function report(section, id, ok, detail, fix, src) {
99
99
  results.push({ section, id, ok, detail, fix, src: src ?? 'builtin' });
100
100
  }
101
101
 
102
+ /** skip 状态(v1 词汇表 r5:#1719)——"不适用"而非"通过",必须带 reason(detail)。不计入 pass/fail,不翻退出码。 */
103
+ function reportSkip(section, id, detail, src) {
104
+ results.push({ section, id, ok: true, skip: true, detail, src: src ?? 'builtin' });
105
+ }
106
+
102
107
  /** 解析 --profile 参数:名字(如 web)→ $DSH_HOME/profiles/<name>;含路径分隔符/~/开头 → 直接当 profile 目录(契约 harness 传绝对路径)。 */
103
108
  function resolveProfile(name) {
104
109
  if (!name) throw new Error('无效 profile 名');
@@ -535,8 +540,9 @@ function checkProfile(name) {
535
540
  // P12:profile 内 bundle 版本 vs 运行 CLI 版本(#1719 v1.1 `installed_bundle` 候选)
536
541
  // web 设置「诊断」面板与 /dsh-doctor/run API 跑的是 profile 里装的 bundle;独立 CLI(checkout/npx)是另一个副本——
537
542
  // Layer-B 自更新只比 npm latest vs 运行模块,profile 内 bundle 落后/超前都不报警(dsh-win32/bundle 同坑,sjh9714 先发现的)。
538
- // 语义(#1719 合稿,sjh9714 四态分析):pass/warn 两态 + detail 注明条件——
539
- // manifest 未声明 = pass(CLI 独立运行);manifest 声明但 node_modules 缺失 = warn(manifest 撒谎,运行时从不加载);
543
+ // 语义(#1719 合稿,sjh9714 四态分析 + skip 修正):pass/warn/skip 三态 + detail 注明条件——
544
+ // manifest 未声明 = skip(无对比对象,pass 会让 CI 误判"已同步"——git_bash 同形);
545
+ // manifest 声明但 node_modules 缺失 = warn(manifest 撒谎,运行时从不加载);
540
546
  // 已装且版本一致 = pass;已装但版本分歧 = warn(detail 含 age-gate 提示,升级可能被 pnpm-workspace.yaml 的
541
547
  // minimumReleaseAgeExclude 年龄门暂缓一天,指令不再静默无效——sjh9714 实测)。
542
548
  try {
@@ -549,7 +555,7 @@ function checkProfile(name) {
549
555
  if (existsSync(p)) { bundlePkg = p; break; }
550
556
  }
551
557
  if (!listed && !bundlePkg) {
552
- report('profile', 'P12-bundle-version', true, 'profile 未声明也未安装 dsh-doctor bundle,跳过版本对比(CLI 独立运行)', undefined);
558
+ reportSkip('profile', 'P12-bundle-version', 'profile 未声明也未安装 dsh-doctor bundle——无对比对象(CLI 独立运行),skip 而非 pass(#1719 installed_bundle 合稿,sjh9714:pass 会让 CI 误判"已同步")');
553
559
  } else if (listed && !bundlePkg) {
554
560
  report('profile', 'P12-bundle-version', false, `profile 的 package.json 声明了 ${selfName} 依赖,但 node_modules 里没有对应包(manifest 与运行时不一致,web 面板/API 实际加载不到)`, `dsh plugin --profile ${name} install ${selfName}(或先移除该依赖再重装)`);
555
561
  } else {
@@ -1151,8 +1157,8 @@ async function run() {
1151
1157
  const bad = results.filter((r) => !r.ok && catalogSeverity.get(r.id) !== 'warn');
1152
1158
  if (jsonOut && process.argv.includes('--envelope')) {
1153
1159
  // v1 契约信封(dsh doctor 规格,zoahdev/doctor 对齐):status 小写 + 退出码 0/1/2
1154
- const st = (r) => (!r.ok ? (catalogSeverity.get(r.id) === 'warn' ? 'warn' : 'fail') : 'pass');
1155
- const summary = { pass: 0, warn: 0, fail: 0, skip: 0 }; // skip 常驻(v1 词汇表 r5:#1719),当前无平台作用域检查所以恒为 0
1160
+ const st = (r) => (r.skip ? 'skip' : (!r.ok ? (catalogSeverity.get(r.id) === 'warn' ? 'warn' : 'fail') : 'pass'));
1161
+ const summary = { pass: 0, warn: 0, fail: 0, skip: 0 }; // skip 常驻(v1 词汇表 r5:#1719),r5 后 P12 会在未装 bundle 时实际触发
1156
1162
  const checks = results.map((r) => { summary[st(r)]++; return { name: r.id, status: st(r), detail: r.detail }; });
1157
1163
  const exitCode = summary.fail > 0 ? 2 : summary.warn > 0 ? 1 : 0;
1158
1164
  console.log(JSON.stringify({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@moonquake2004/dsh-doctor",
3
- "version": "0.3.3",
4
- "description": "Offline diagnostic for DeepSeek Harness — 25 built-in + 5 catalog checks across env/profile/session (Layer A checks-as-data), self-update (Layer B), and a semi-automatic LLM observer (Layer C, --observe); Doctor panel in web UI settings.",
3
+ "version": "0.3.4",
4
+ "description": "Offline diagnostic for DeepSeek Harness — 26 built-in + 5 catalog checks across env/profile/session (Layer A checks-as-data), self-update (Layer B), and a semi-automatic LLM observer (Layer C, --observe); Doctor panel in web UI settings.",
5
5
  "main": "lib/index.js",
6
6
  "files": [
7
7
  "README.md",