dsh-plugin-compat-check 0.1.5 → 0.1.7
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 +17 -28
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/index.js +1295 -550
- package/kernel/lib/api-semantics.mjs +223 -0
- package/kernel/lib/author-ci-budget.mjs +25 -0
- package/kernel/lib/author-ci-output.mjs +22 -0
- package/kernel/lib/author-ci-policy.mjs +6 -1
- package/kernel/lib/baseline.mjs +109 -38
- package/kernel/lib/catalog.mjs +11 -3
- package/kernel/lib/contracts.mjs +16 -1
- package/kernel/lib/execution-environment.mjs +52 -0
- package/kernel/lib/extract.mjs +57 -13
- package/kernel/lib/finding-guidance.mjs +6 -0
- package/kernel/lib/finding-review-store.mjs +11 -23
- package/kernel/lib/issue-report.mjs +2 -1
- package/kernel/lib/patch-mounts.mjs +232 -0
- package/kernel/lib/report-identity-worker.mjs +47 -26
- package/kernel/lib/report-identity.mjs +4 -3
- package/kernel/lib/report-service.mjs +118 -38
- package/kernel/lib/report.mjs +13 -17
- package/kernel/lib/source-analysis.mjs +258 -42
- package/kernel/lib/source-graph.mjs +353 -75
- package/kernel/lib/state-lock.mjs +206 -0
- package/kernel/lib/state-store.mjs +41 -30
- package/kernel/lib/static-input.mjs +111 -0
- package/kernel/lib/syntax.mjs +242 -20
- package/kernel/lib/upgrade-contract.mjs +1 -0
- package/kernel/lib/upgrade-input.mjs +9 -4
- package/kernel/lib/upgrade-preview.mjs +11 -15
- package/kernel/lib/upgrade-worker.mjs +10 -1
- package/kernel/lib/verdict.mjs +28 -5
- package/kernel/lib/version.mjs +2 -34
- package/kernel/lib/worker-analysis.mjs +74 -3
- package/kernel/rules/README.md +30 -208
- package/kernel/rules/dsh-0.2.1-rc.3-review.json +63 -0
- package/kernel/rules/dsh-api-catalog-0.2.1-rc.3.json +743 -0
- package/kernel/rules/severity.json +77 -0
- package/lib/client.js +4668 -3423
- package/lib/finding-guidance.js +6 -0
- package/lib/local-request.js +44 -0
- package/lib/report-contract.js +16 -1
- package/lib/upgrade-contract.js +1 -0
- package/package.json +10 -5
- package/scripts/prepublish-check.mjs +1 -22
- package/scripts/stage-contract.mjs +7 -0
- package/skill/SKILL.md +13 -12
package/lib/finding-guidance.js
CHANGED
|
@@ -53,6 +53,12 @@ export function nextSteps(finding) {
|
|
|
53
53
|
"在报告给出的源码位置核对服务读取及必需 inject 的作用域,并确认 absent 观测绑定同一 profile、DSH 版本与采样时间。",
|
|
54
54
|
"核对该服务的实际提供者及 loader 状态,补充相关功能操作结果;服务缺失的推断影响不等于业务失败已实测。",
|
|
55
55
|
];
|
|
56
|
+
case "api-argument-invalid":
|
|
57
|
+
case "api-option-unsupported":
|
|
58
|
+
return [
|
|
59
|
+
"按源码位置核对选项类型、枚举、实际传值和精确目标版本,查阅 evidence 中固定源码及归档摘要;方法存在或能力守卫不证明参数有效。",
|
|
60
|
+
"在独立目标会话核验草稿保留、替换或追加;本项仅是静态参数风险,不证明业务失败,也不自动修改或提交草稿。",
|
|
61
|
+
];
|
|
56
62
|
case "host-method-missing":
|
|
57
63
|
return [
|
|
58
64
|
"在报告给出的文件与行号核对实际方法调用、Context 绑定及能力守卫,检查是否存在报告尚未识别的兜底。",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** 本地信任栅栏:只有本机的 DSH 界面该读到这份数据。 */
|
|
2
|
+
export function isTrustedRequest(req) {
|
|
3
|
+
try {
|
|
4
|
+
const header = (name) => {
|
|
5
|
+
const value = Object.entries(req.headers || {}).find(
|
|
6
|
+
([key]) => key.toLowerCase() === name,
|
|
7
|
+
)?.[1];
|
|
8
|
+
if (value !== undefined && typeof value !== "string")
|
|
9
|
+
throw new Error("Invalid request header");
|
|
10
|
+
return value;
|
|
11
|
+
};
|
|
12
|
+
// A non-safelisted header also fences legacy browsers that omit both Origin
|
|
13
|
+
// and Fetch Metadata. It is a CSRF admission marker, never an auth secret.
|
|
14
|
+
if (header("x-dsh-compat-request") !== "1") return false;
|
|
15
|
+
const host = header("host") || "";
|
|
16
|
+
const origin = header("origin");
|
|
17
|
+
const hostOk = /^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i.test(host);
|
|
18
|
+
if (!hostOk) return false;
|
|
19
|
+
const peer = req.socket?.remoteAddress;
|
|
20
|
+
if (peer && !["127.0.0.1", "::1", "::ffff:127.0.0.1"].includes(peer))
|
|
21
|
+
return false;
|
|
22
|
+
const protocol = req.socket?.encrypted === true ? "https:" : "http:";
|
|
23
|
+
const expectedOrigin = new URL(`${protocol}//${host}`).origin;
|
|
24
|
+
const site = header("sec-fetch-site"),
|
|
25
|
+
mode = header("sec-fetch-mode"),
|
|
26
|
+
dest = header("sec-fetch-dest");
|
|
27
|
+
if (site !== undefined && site !== "same-origin") return false;
|
|
28
|
+
if (mode !== undefined && !["cors", "same-origin"].includes(mode))
|
|
29
|
+
return false;
|
|
30
|
+
if (dest !== undefined && !["", "empty"].includes(dest)) return false;
|
|
31
|
+
if (
|
|
32
|
+
origin !== undefined &&
|
|
33
|
+
(!/^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i.test(origin) ||
|
|
34
|
+
new URL(origin).origin !== expectedOrigin)
|
|
35
|
+
)
|
|
36
|
+
return false;
|
|
37
|
+
const referer = header("referer");
|
|
38
|
+
if (referer !== undefined && new URL(referer).origin !== expectedOrigin)
|
|
39
|
+
return false;
|
|
40
|
+
return true;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
package/lib/report-contract.js
CHANGED
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
export const REPORT_SCHEMA = 1;
|
|
10
10
|
export const REPORT_KIND = "plugin-compat-check/result";
|
|
11
11
|
export const ENVELOPE_KIND = "plugin-compat-check/report";
|
|
12
|
+
/** Escape untrusted single-line display text; callers supply layout newlines.
|
|
13
|
+
* JSON identities remain untouched. Visible escapes are safe to render again. */
|
|
14
|
+
export function terminalText(value) {
|
|
15
|
+
return String(value).replace(
|
|
16
|
+
/[\x00-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g,
|
|
17
|
+
(c) => "\\u" + c.charCodeAt(0).toString(16).padStart(4, "0"),
|
|
18
|
+
);
|
|
19
|
+
}
|
|
12
20
|
/** Reviewed catalogue bytes, not a promise of plugin business compatibility.
|
|
13
21
|
* Adding a version requires source verification, rule review and integration
|
|
14
22
|
* evidence; extraction alone must never extend this list. */
|
|
@@ -23,6 +31,11 @@ export const CATALOG_REFERENCES = Object.freeze([
|
|
|
23
31
|
file: "dsh-api-catalog-0.2.1-rc.2.json",
|
|
24
32
|
sha256: "90b4ae484ebc6660c53e5c9ad14ba657581534b30e8222c636c759e19587f743",
|
|
25
33
|
}),
|
|
34
|
+
Object.freeze({
|
|
35
|
+
version: "0.2.1-rc.3",
|
|
36
|
+
file: "dsh-api-catalog-0.2.1-rc.3.json",
|
|
37
|
+
sha256: "dd253bc418a787d881e402f3650857c2d8e7631b818927743a5f2b81104f25a5",
|
|
38
|
+
}),
|
|
26
39
|
]);
|
|
27
40
|
export function describeCatalog({
|
|
28
41
|
targetVersion = null,
|
|
@@ -103,7 +116,9 @@ function snapshotFinding(f) {
|
|
|
103
116
|
text(f.category) &&
|
|
104
117
|
severities.includes(f.severity) &&
|
|
105
118
|
certainties.includes(f.certainty) &&
|
|
106
|
-
nullableText(f.location)
|
|
119
|
+
nullableText(f.location) &&
|
|
120
|
+
(f.entryId === undefined || nullableText(f.entryId)) &&
|
|
121
|
+
(f.column === undefined || integer(f.column))
|
|
107
122
|
);
|
|
108
123
|
}
|
|
109
124
|
function checkedEntry(v) {
|
package/lib/upgrade-contract.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-compat-check",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Checks installed DSH plugins
|
|
3
|
+
"version": "0.1.7",
|
|
4
|
+
"description": "Checks installed DSH plugins and previews upgrade risks, with source locations, dependency views, review records and evidence limits. Includes a panel and agent tool.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"THIRD_PARTY_NOTICES.md"
|
|
34
34
|
],
|
|
35
35
|
"engines": {
|
|
36
|
-
"node": "^22.19.0 || >=24"
|
|
36
|
+
"node": "^22.19.0 || >=24",
|
|
37
|
+
"dsh": ">=0.2.0-rc.2"
|
|
37
38
|
},
|
|
38
39
|
"scripts": {
|
|
39
40
|
"prepack": "node scripts/stage-skill.mjs && node scripts/stage-contract.mjs && node scripts/stage-kernel.mjs",
|
|
@@ -50,7 +51,10 @@
|
|
|
50
51
|
"compatibility",
|
|
51
52
|
"health-check",
|
|
52
53
|
"cordis",
|
|
53
|
-
"agent-skills"
|
|
54
|
+
"agent-skills",
|
|
55
|
+
"static-analysis",
|
|
56
|
+
"dependency-analysis",
|
|
57
|
+
"upgrade"
|
|
54
58
|
],
|
|
55
59
|
"repository": {
|
|
56
60
|
"type": "git",
|
|
@@ -63,6 +67,7 @@
|
|
|
63
67
|
},
|
|
64
68
|
"dependencies": {
|
|
65
69
|
"@babel/parser": "7.29.9",
|
|
66
|
-
"semver": "7.7.3"
|
|
70
|
+
"semver": "7.7.3",
|
|
71
|
+
"yaml": "2.9.1"
|
|
67
72
|
}
|
|
68
73
|
}
|
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* `prepublishOnly` 钩子 —— 发布前把两类**不可挽回**的错误挡在门外。
|
|
4
|
-
*
|
|
5
|
-
* ## 为什么必须有它
|
|
6
|
-
*
|
|
7
|
-
* npm 发布是**公开且近乎不可撤回**的。而有两类错误一旦发出去就只能靠发新版弥补:
|
|
8
|
-
*
|
|
9
|
-
* ① **版本号与内核不一致**。版本的真源是 `lib/version.mjs`,但 `package.json`
|
|
10
|
-
* 只能写字面量(npm 只认字面量)。改了一处忘了另一处,发布出去的就是
|
|
11
|
-
* 「包的版本是 A、它自己 `--version` 报 B」—— 而这恰恰是这次发布的**主题**
|
|
12
|
-
* (见 docs/Plan.md §1、§6:「单版本」)。
|
|
13
|
-
*
|
|
14
|
-
* ② **测试没过就发**。`npm publish` 默认**不跑测试**。测试没过的包发出去,
|
|
15
|
-
* 用户拿到的是我们已知有问题的版本,而他还以为那是"刚发布的最新版"。
|
|
16
|
-
*
|
|
17
|
-
* ## 为什么不用 `npm test` 那种写法
|
|
18
|
-
*
|
|
19
|
-
* 这个包发布时人在**仓库里**(`plugin/` 的上一级就是仓库根),
|
|
20
|
-
* 所以能直接跑仓库的测试套件。但 `files` 字段里不含 `test/` ——
|
|
21
|
-
* 也就是说这个脚本**不能**假设测试文件在包内,必须从仓库根跑。
|
|
22
|
-
* 这正是"发布时必须从仓库检出里发"这条约束的技术原因。
|
|
23
|
-
*/
|
|
2
|
+
/** Local-only publication gate: source checkout, consistent version, successful tests and document checks. Never publishes. */
|
|
24
3
|
|
|
25
4
|
import { execFileSync } from 'node:child_process';
|
|
26
5
|
import fs from 'node:fs';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/** Keep host/browser presentation artifacts byte-reproducible from pure sources. */
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import { format, resolveConfig } from "prettier";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
const plugin = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."),
|
|
@@ -94,6 +95,12 @@ for (const item of [
|
|
|
94
95
|
source,
|
|
95
96
|
]);
|
|
96
97
|
}
|
|
98
|
+
// Format the complete generated artifact at its canonical generation boundary.
|
|
99
|
+
// A formatted client must remain byte-identical on every subsequent check.
|
|
100
|
+
next = await format(next, {
|
|
101
|
+
...(await resolveConfig(client)),
|
|
102
|
+
filepath: client,
|
|
103
|
+
});
|
|
97
104
|
outputs.unshift([client, next]);
|
|
98
105
|
for (const [file, value] of outputs) {
|
|
99
106
|
if (fs.existsSync(file) && fs.readFileSync(file, "utf8") === value) continue;
|
package/skill/SKILL.md
CHANGED
|
@@ -15,13 +15,13 @@ description: 当用户询问已安装DSH插件是否适配当前版本、升级
|
|
|
15
15
|
|
|
16
16
|
## 升级前对比
|
|
17
17
|
|
|
18
|
-
用户要比较当前与目标版本时,已注册工具优先调用 `compat_check({"upgradeTo":"0.2.1-rc.
|
|
18
|
+
用户要比较当前与目标版本时,已注册工具优先调用 `compat_check({"upgradeTo":"0.2.1-rc.3"})`,需要时指定实际 `profile`;当前版本由运行宿主解析,读取返回的 `upgradePreview`,普通 `report`、baseline/cache为null。没有工具时使用仓库 CLI 的独立预检模式,先明确 profile、当前精确版本和目标精确版本,再运行:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
node <repo>/bin/compat-check.mjs --nm <profile或node_modules目录> --dsh-version 0.2.
|
|
21
|
+
node <repo>/bin/compat-check.mjs --nm <profile或node_modules目录> --dsh-version 0.2.1-rc.2 --upgrade-to 0.2.1-rc.3 --json
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
此模式的 `--dsh-version` 是**当前精确版本**,`--upgrade-to` 是目标精确版本;当前已认证目录仅为 `0.2.0-rc.2
|
|
24
|
+
此模式的 `--dsh-version` 是**当前精确版本**,`--upgrade-to` 是目标精确版本;当前已认证目录仅为 `0.2.0-rc.2`、`0.2.1-rc.2`、`0.2.1-rc.3`。未知版本或版本范围返回 `status=unsupported-version`、退出3并标明未认证,不能用邻近目录替代。普通文本输出省略 `--json`;此模式不接受 `--quiet`、探针/启动参数、规则/目录覆盖、基线参数或故障报告,可带无操作的 `--no-baseline`。
|
|
25
25
|
|
|
26
26
|
JSON 使用独立的 `schemaVersion=1 / kind=plugin-compat-check/upgrade-preview`;读取 `currentReport`、`targetReport`、带插件身份的 `changes`、`summary` 与 `limitations`。它对**同一份已安装制品**做静态版本对比:不执行插件、不启动或升级宿主,不读取旁置/环境探针、profile豁免、基线或缓存,也不写状态。新增/恶化风险含致命项时退出2,其余新增/恶化风险退出1,无新增/恶化风险退出0;输入/扫描失败或未认证版本为3。保留提取不完整、coverage/vacuous和客户端未验证限制;0仍可能有未变化的旧问题。差异是目录与声明策略下的预测,不能据此认定升级后业务通过,也不能代替目标宿主的运行时与业务验收。
|
|
27
27
|
|
|
@@ -29,7 +29,7 @@ JSON 使用独立的 `schemaVersion=1 / kind=plugin-compat-check/upgrade-preview
|
|
|
29
29
|
|
|
30
30
|
普通报告的`dependencyGraph`只解释依赖和潜在传播:保留host/client/未知端、必需/可选/子作用域、候选提供者、loader禁用/未知状态及覆盖预算。提供声明不是实际提供证明,环或路径不是实测故障;不跨端补造提供者,不因未找到候选就说宿主缺服务,也不据此自动装包。
|
|
31
31
|
|
|
32
|
-
HTTP/tool envelope的`reviews`是独立人工记录,四种状态为pending/reviewed/false-positive/fixed。已复核、误报或已修复不消除内核发现、不隐藏新风险、不改变退出码/基线,也不授予compatibility豁免。记录绑定报告发布时的源码身份、目标/观察路径/模式、插件/DSH精确版本、工具/规则/目录及finding证据;变化后的needs-review必须重新核实,不能沿用旧误报/修复。只能按用户明确处置意图保存状态与依据,不因读到发现就自动标记已处理。坏文件/超限或busy
|
|
32
|
+
HTTP/tool envelope的`reviews`是独立人工记录,四种状态为pending/reviewed/false-positive/fixed。已复核、误报或已修复不消除内核发现、不隐藏新风险、不改变退出码/基线,也不授予compatibility豁免。记录绑定报告发布时的源码身份、目标/观察路径/模式、插件/DSH精确版本、工具/规则/目录及finding证据;变化后的needs-review必须重新核实,不能沿用旧误报/修复。只能按用户明确处置意图保存状态与依据,不因读到发现就自动标记已处理。坏文件/超限或busy须转述,不能覆盖或清空记录。基线与人工记录的崩溃孤锁须按仓库`docs/guide.md#本地状态锁恢复`操作:运行`node <repo>/bin/recover-lock.mjs <确切.lock路径>`检查,再用本次token显式确认。只有同用户/主机且系统证明持有PID不存在时才恢复;不按年龄、PID复用或“没有保存任务”猜测,不递归清理JSON、临时文件或恢复保护锁。旧/损坏基线保留原件,不比较或自动覆盖。
|
|
33
33
|
|
|
34
34
|
可选功能健康执行器仅在仓库`tools/functional-health.mjs`;默认review只审阅声明。普通兼容检查、健康记录导入及作者提供清单均不构成执行授权;不得自动添加执行开关。仅在用户已明确授权所选制品的安装、宿主/插件执行及HTTP/DOM测量后运行,必要时使用Chrome。声明与本地USTAR制品须校验SHA-256、包名/精确版本及DSH精确版本,预算为32项、请求/导航3秒、HTTP响应64KiB、整轮180秒;不接受作者脚本或跳过身份检查。私有profile不是OS沙箱,安装可能联网,不能借用用户账户/模型配置。
|
|
35
35
|
|
|
@@ -91,7 +91,7 @@ report_status=$?
|
|
|
91
91
|
|
|
92
92
|
## 输出怎么读
|
|
93
93
|
|
|
94
|
-
下面是当前仓库源码对固定合成夹具的可复现输出,运行命令为 `node bin/compat-check.mjs --nm test/fixtures/labels --dsh-version 0.2.1-rc.2 --no-baseline`,预期退出2
|
|
94
|
+
下面是当前仓库源码对固定合成夹具的可复现输出,运行命令为 `node bin/compat-check.mjs --nm test/fixtures/labels --dsh-version 0.2.1-rc.2 --no-baseline`,预期退出2。它用于解释报告字段,不代表真实插件业务验收;工具版本为0.1.7,实际发布与验收状态见仓库docs/current-state.json。
|
|
95
95
|
|
|
96
96
|
```text
|
|
97
97
|
插件数: 4 有运行时面: 否(方法级结论降为「疑似」)
|
|
@@ -99,7 +99,7 @@ report_status=$?
|
|
|
99
99
|
参考目录:0.2.1-rc.2 · SHA-256:90b4ae484ebc6660c53e5c9ad14ba657581534b30e8222c636c759e19587f743
|
|
100
100
|
目录认证范围:0.2.1-rc.2;仅核验内置目录字节及对应精确版本的集成;不代表业务验收或运行时观测。
|
|
101
101
|
|
|
102
|
-
工具版本: 0.1.
|
|
102
|
+
工具版本: 0.1.7 证据覆盖有限: 4 个插件
|
|
103
103
|
结论: 可用 2 部分可用 1 不兼容 1 (其中 2 个「可用」没有已验证调用,不等于业务通过)
|
|
104
104
|
|
|
105
105
|
不兼容 @label/broken-client@1.0.0
|
|
@@ -157,8 +157,7 @@ report_status=$?
|
|
|
157
157
|
但没有观测浏览器中的实际失败;方法缺失案例也可能依据运行时方法面和源码调用点,
|
|
158
158
|
推断「用户可能失去什么功能」。不要把这个方法案例当成所有发现都已有运行时观测。
|
|
159
159
|
**转述时必须保留这个限定**,不要说成"确定会消失"。
|
|
160
|
-
|
|
161
|
-
一个辅助函数里、早就兜住了,还 log 了降级行为。
|
|
160
|
+
能力helper的静态支持有边界;不能把旧提取器的历史误报当成当前规则或完整覆盖证明。
|
|
162
161
|
- 只有显式`impactBasis=measured`且有对应观测,才按实测转述,例如明确记录的loader FAILED/PENDING。缺少字段或没有标注“推断”均不能当成实测;损坏报告应报工具错误。
|
|
163
162
|
- **转述结论时带上 `--version` 报出的工具版本**(`--json` 里是 `toolVersion`)。
|
|
164
163
|
同一个插件在「规则表还没覆盖这个方法」和「已经覆盖」的两个版本下,
|
|
@@ -204,16 +203,18 @@ CI 里可以直接用:`0` 过,`1`/`2` 按你的策略处理,`3` 是**工
|
|
|
204
203
|
- 报结论时**给出可核对的依据**。API源码发现引用真实`file:line`;没有源码位置的loader/声明事实说明包身份及观测或声明来源,不补造行号。
|
|
205
204
|
|
|
206
205
|
|
|
207
|
-
|
|
206
|
+
`root` 缺项是未采样,不能称为不存在;`coverage.status=limited` 与 `vacuous` 必须转述。现代探针绑定 profile/DSH/采样时间;旧报告明确标为未绑定。解析、读取、资源上限等诊断会限制覆盖,完整性不足不更新基线。当前统计见仓库 `docs/current-state.json`;npm 包是插件,CLI 从仓库使用,根依赖尚未就绪时在授权范围内运行 `npm ci --ignore-scripts`。显式安装检查会执行目标插件,临时 profile 不是不可信代码隔离沙箱。
|
|
208
207
|
|
|
209
|
-
|
|
208
|
+
声明按目标DSH分流:从0.2.1-rc.1起优先自有`engines.dsh`,仅缺失该字段时回退官方peer;更旧目标保留旧peer规则与engines建议。非法字段、空/非法范围会报告风险;peer的workspace:^/~/*按当前DSH精确版本处理,engines的workspace不获放行。声明冲突为declared-incompatible及推断影响,不能写成实际加载失败;宿主也可能跳过不兼容bundle后继续启动。历史npm0.1.2使用旧算法;判断实际行为先核对安装包版本,是否公开发布以registry和Plan记录为准。
|
|
210
209
|
|
|
211
|
-
0.1.3
|
|
210
|
+
DSH 0.2.1-rc.3的UI入口为“左下角账号菜单 → 设置 → 内置插件 → 兼容性”。HMR撤销自有注册、计时器及诊断handle,卸载后不得发布新成功或写基线;worker按预算回收,不承诺立即停止。历史现场证据与当前源码分别核验,见仓库docs/current-state.json。
|
|
212
211
|
|
|
213
212
|
只读目标node_modules同级的独立`compatibility.json`,形如`{"sample@1.0.0":["0.2.1-rc.2"]}`。只有插件名、插件精确版本与DSH精确版本全匹配才豁免范围冲突;不使用包内兼容声明代替授权。无效记录整条忽略(其它有效记录仍用)并限制覆盖;缺文件为空豁免,可读性/JSON错误、非普通文件或超过64KiB则豁免未观测。不得代用户写豁免,豁免不绕过非法字段,也不证明API或业务成功。
|
|
214
213
|
|
|
215
|
-
普通体检中,CLI的`--dsh-version`及probe-boot采集值、宿主自己的DSH版本用于目录选择:DSH≥0.2.1-rc.
|
|
214
|
+
普通体检中,CLI的`--dsh-version`及probe-boot采集值、宿主自己的DSH版本用于目录选择:DSH≥0.2.1-rc.3使用独立rc.3目录,≥0.2.1-rc.2使用rc.2目录,其余/未知使用旧0.2.0-rc.2目录,显式`--catalog`优先。未知版本不猜声明,未来DSH未经认证。单独文件probe不自动补目标版本,需给`--dsh-version`。目录不等于运行时面。当前契约/验收/后续见仓库docs/Plan.md,统计见docs/current-state.json;公开安装以npm registry为准。
|
|
216
215
|
|
|
217
216
|
普通报告另有 `catalog`:目标版本、参考目录版本、SHA-256、selection、verified、certifiedVersions及warning。转述时同时给出目标与目录身份;fallback/override、未知身份和未认证提示不得省略,verified仅表示内置目录与已验收精确版本匹配,不是业务认证。内置目录摘要不符、同名插件重复安装(含alias及不同版本)会明确无法判定,不允许转述为无冲突;普通报告失败不推进基线。仓库YAML修复仅涉及锁文件等工具依赖,不属于npm插件运行时依赖。新目录治理流程见仓库 `docs/maintaining.md#api目录候选审查`。
|
|
218
217
|
|
|
219
218
|
对observationVersion=1探针始终校验采样时间:未来偏差最多5分钟(含边界),缺失/非法或超限时撤回该文件的服务及loader证据,不推断FAILED/PENDING或确定方法缺失;普通体检另保留24小时有效期及profile/DSH绑定。转述observation.notes中的原因,保留静态发现和待验证项,不修正原采样时间、不把时钟异常当插件不兼容;修复时钟/重采样后再显式刷新。旧未绑定报告仍只使用显式键,不能补造绑定。仓库CI依赖安全工具不属于npm运行时功能。
|
|
219
|
+
|
|
220
|
+
rc.3三处“更多”按全局面板/会话视图/右侧工具区分;浏览进入主插件列表,创建仅追加Cordis草稿,不发送。`startSession`复用空白会话;指定preset隔离,`whenDraftExists`默认keep并优先于旧clearPreviousDraft。入口折叠不等于未激活;名称目录没有变化也不证明行为相同。rc.3模型列表发现使用凭据门控,首次可等待/失败回退;不要为体检访问生产/models或发送模型请求。
|