dsh-request-doctor 0.14.5 → 0.15.0

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  **产品名称**:request-doctor(请求急救员)
4
4
  **产品标识**:request-doctor
5
- **版本**:0.14.5
5
+ **版本**:0.15.0
6
6
 
7
7
  ---
8
8
 
@@ -1,7 +1,7 @@
1
1
  # 软件设计说明
2
2
 
3
3
  **产品名称**:request-doctor(请求急救员)
4
- **版本**:0.14.5
4
+ **版本**:0.15.0
5
5
  **编制依据**:GB/T 8567-2006《计算机软件文档编制规范》6.2
6
6
 
7
7
  ---
@@ -1,7 +1,7 @@
1
1
  # 软件测试报告
2
2
 
3
3
  **产品名称**:request-doctor(请求急救员)
4
- **版本**:0.14.5
4
+ **版本**:0.15.0
5
5
  **编制依据**:GB/T 8567-2006《计算机软件文档编制规范》6.6;GB/T 8566-2007 验证与确认过程
6
6
 
7
7
  ---
@@ -62,14 +62,16 @@
62
62
  | `test/client-half.test.mjs` | 11 | 客户端半:模块身份、注入声明、apply 注册、组件能渲染 |
63
63
  | `test/diagnostics.test.mjs` | 3 | 快照可选写入:不配置不写盘、突发合并、坏路径不致命 |
64
64
  | `test/restart-notice.test.mjs` | 3 |
65
+ | `test/give-up-advice.test.mjs` | 5 | 不重试的类别各有可照做的建议,未知类别不编造 |
66
+ | `test/allow-route.test.mjs` | 4 | 授权路由:路径声明、坏请求体 400、空 spec 200 失败、正常放行 |
65
67
  | `test/install-remote.test.mjs` | 2 | 远程安装的前置拒绝:非注册表名、缺 profile,均不触网 |
66
68
  | `test/install-branches.test.mjs` | 4 | 安装分支:已存在就地修、非注册表名、缺 profile、授权被拒 |
67
69
  | `test/install-refusal.test.mjs` | 6 | 安装的四条失败路径:空参数、未备好、缺 profile、装不上 |
68
- | `test/allow-version.test.mjs` | 6 | 放行:版本必填、缺管理器拒绝、成功只调一次、失败如实报、请求体解析 |
70
+ | `test/allow-version.test.mjs` | 8 | 放行:版本必填、缺管理器拒绝、成功只调一次、失败如实报、请求体解析 |
69
71
  | `test/panel-blocked.test.mjs` | 7 | 冲突判定:审计兼容却被拒装、清单形状解析、给 allow 动作 |
70
72
  | `test/panel-briefs.test.mjs` | 6 | 界面摘要:按名索引、只送可见行、缺数据不抛、不污染诊断 |
71
73
  | `test/verdict-report.test.mjs` | 29 | why 与 list:判定、理由、环境摘要、自动扫描、分组、缺口、按形态给建议 | 缺导出判为需要重启;其它失败不误判;多次累积不覆盖 |
72
- | **合计** | **226** | **全部通过** |
74
+ | **合计** | **237** | **全部通过** |
73
75
 
74
76
  执行结果:
75
77
 
@@ -223,13 +225,13 @@
223
225
 
224
226
  ### 7.2 分文件执行结果
225
227
 
226
- 36 个测试文件逐个单独执行,每个都有用例且全部通过,不存在因导入失败而静默跳过的文件。用例数分布:compat.test.mjs 17、plugin.test.mjs 15、compat-env.test.mjs 14、classify.test.mjs 13,其余按职能分散,合计 226。
228
+ 38 个测试文件逐个单独执行,每个都有用例且全部通过,不存在因导入失败而静默跳过的文件。用例数分布:compat.test.mjs 17、plugin.test.mjs 15、compat-env.test.mjs 14、classify.test.mjs 13,其余按职能分散,合计 237。
227
229
  ## 8 覆盖率实测
228
230
 
229
231
  用 Node 自带的 `--experimental-test-coverage` 跑一遍,作为「分支有没有被真的走一遍」的证据。这不替代对断言质量的判断,只说明哪些代码从未被执行。
230
232
 
231
233
  ```
232
- all files 行 84.86% 分支 75.35% 函数 84.87%
234
+ all files 行 85.16% 分支 75.56% 函数 85.41%
233
235
  ```
234
236
 
235
237
  分支覆盖率最低的两个模块是 `plugin-discovery.js`(55.38%)与 `version-repair.js`(47.47%)。它们的未覆盖部分集中在真实文件系统与插件管理器的交互上,需要构造更完整的替身才能走到,本轮未做。
@@ -1,7 +1,7 @@
1
1
  # 软件安装部署说明
2
2
 
3
3
  **产品名称**:request-doctor(请求急救员)
4
- **版本**:0.14.5
4
+ **版本**:0.15.0
5
5
  **编制依据**:GB/T 8567-2006《计算机软件文档编制规范》6.7
6
6
 
7
7
  ---
@@ -1,7 +1,7 @@
1
1
  # 软件用户手册
2
2
 
3
3
  **产品名称**:request-doctor(请求急救员)
4
- **版本**:0.14.5
4
+ **版本**:0.15.0
5
5
  **编制依据**:GB/T 8567-2006《计算机软件文档编制规范》6.5
6
6
 
7
7
  ---
@@ -1,7 +1,7 @@
1
1
  # 软件质量度量报告
2
2
 
3
3
  **产品名称**:request-doctor(请求急救员)
4
- **版本**:0.14.5
4
+ **版本**:0.15.0
5
5
  **度量标准**:GB/T 45717-2025《信息技术 软件测量 软件质量测量 自动化的源代码质量测度》
6
6
  **度量工具**:`tools/quality-measure.mjs`(本仓库自带,可复现)
7
7
 
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "standard": "GB/T 45717-2025 信息技术 软件测量 软件质量测量 自动化的源代码质量测度",
3
- "generatedAt": "2026-10-29T16:41:58.201Z",
3
+ "generatedAt": "2026-10-29T16:48:27.762Z",
4
4
  "scope": {
5
- "files": 36,
6
- "totalLines": 5412,
7
- "sourceLines": 3906,
8
- "commentLines": 1001
5
+ "files": 37,
6
+ "totalLines": 5442,
7
+ "sourceLines": 3924,
8
+ "commentLines": 1008
9
9
  },
10
10
  "measures": {
11
- "commentDensity": 25.63,
12
- "duplicationPercent": 4.96,
13
- "functionCount": 415,
11
+ "commentDensity": 25.69,
12
+ "duplicationPercent": 5,
13
+ "functionCount": 418,
14
14
  "maxComplexity": 10,
15
15
  "maxFunctionLines": 57,
16
16
  "maxFileLines": 500,
17
- "averageComplexity": 3.83
17
+ "averageComplexity": 3.82
18
18
  },
19
19
  "limits": {
20
20
  "maxComplexity": 10,
@@ -0,0 +1,18 @@
1
+ // 不重试的失败怎么向用户交代。
2
+ //
3
+ // TLS 证书、本机权限、配额、内容策略这些重试一百次也不会变,所以不重试是对的。
4
+ // 但「不重试」不等于「不解释」:用户需要知道这次是谁的问题、接下来自己能做什么。
5
+
6
+ const ADVICE = {
7
+ tls: '证书校验没过。换掉中间代理的自签证书,或让系统信任该根证书;重试不会有帮助。',
8
+ 'local-blocked': '本机权限、路径或磁盘空间不足。先把缺的权限或空间补上,重试才有意义。',
9
+ quota: '额度或频率到上限了。等额度恢复再发请求;这不是插件或网络的问题。',
10
+ policy: '内容被服务方的策略拦下了。改写提问再发;重试会得到同样的结果。',
11
+ image: '图片需要走转存才能发送。换一张图,或让客户端先完成转存。',
12
+ };
13
+
14
+ // @param {string} kind - 分类结果里的 kind。
15
+ // @returns {string|undefined} 一句话建议;没有对应建议时返回 undefined。
16
+ export function adviceFor(kind) {
17
+ return ADVICE[kind];
18
+ }
@@ -10,6 +10,7 @@
10
10
  // - 无进展:压缩/修历史连续两轮都没让问题前进,就不再无限重试。
11
11
  import { classifyModelFailure, computeDelay } from './classify.js';
12
12
  import { cancellableSleep } from './sleep.js';
13
+ import { adviceFor } from './give-up-advice.js';
13
14
 
14
15
  // 每个策略分到的预算倍数。鉴权类的重试更贵(要换凭据),给的次数更少。
15
16
  const STRATEGY_BUDGET = { auth: 'auth', 'history-repair': 'history', compact: 'normal' };
@@ -152,7 +153,7 @@ export function createModelRepair(input) {
152
153
  if (payload.signal?.aborted || lifetime.signal.aborted) return downstream;
153
154
 
154
155
  const decision = classifyModelFailure(payload.failure);
155
- if (!decision.clientCaused || decision.strategy === 'skip') return downstream;
156
+ if (!decision.clientCaused || decision.strategy === 'skip') return skipOut(decision, downstream, record);
156
157
 
157
158
  const key = `${payload.turn}:${payload.step}:${payload.provider}:${decision.kind}`;
158
159
  // 同一处只放一个重试进去。并发的那几个直接让下游收场,避免重试互相叠加。
@@ -165,7 +166,17 @@ export function createModelRepair(input) {
165
166
  }
166
167
  }
167
168
 
168
- // 依次过三关:本地修复成不成、还有没有进展、预算还剩不剩。
169
+
170
+ // 不重试的失败也要留痕:用户得知道这次是谁的问题、接下来能做什么。
171
+ function skipOut(decision, downstream, record) {
172
+ if (decision.strategy === 'skip') {
173
+ const note = adviceFor(decision.kind) ?? '这类失败重试也不会变,跳过修复';
174
+ record('skip', decision.kind + ': ' + note);
175
+ }
176
+ return downstream;
177
+ }
178
+
179
+ // 依次过三关:本地修复成不成、还有没有进展、预算还剩不剩。
169
180
  async function attempt(key, payload, decision, downstream) {
170
181
  if (!(await prepare(decision, payload))) {
171
182
  stats.modelSkips += 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-request-doctor",
3
- "version": "0.14.5",
3
+ "version": "0.15.0",
4
4
  "description": "自动修复客户端引起的请求失败,并让版本不匹配的 DSH 插件能装上、能跑起来。",
5
5
  "keywords": [
6
6
  "dsh-plugin",