@shgroup/dsh-serenity-hooks 1.56.1 → 1.56.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/README.md +1 -1
- package/dsh.plugin.json +2 -2
- package/lib/index.js +35 -5
- package/lib/invariant.d.ts +26 -1
- package/lib/invariant.js +85 -4
- package/lib/ontology/engine.d.ts +8 -0
- package/package.json +2 -2
package/README.md
CHANGED
package/dsh.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.56.
|
|
3
|
+
"version": "1.56.2",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
|
-
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/handyman/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1
|
|
5
|
+
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/handyman/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1 与 0.2.0-rc.1(双档,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.7-rc.1"
|
|
8
8
|
},
|
package/lib/index.js
CHANGED
|
@@ -5710,7 +5710,13 @@ function turtleToOnto(r) {
|
|
|
5710
5710
|
const td = {};
|
|
5711
5711
|
for (const s of stmts) {
|
|
5712
5712
|
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#subClassOf") td.superTypes = [...td.superTypes || [], stripDefaultPrefix(i2q(String(s.object), prefixes))];
|
|
5713
|
-
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#label"
|
|
5713
|
+
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#label") {
|
|
5714
|
+
td.label = String(s.object);
|
|
5715
|
+
td.description = String(s.object);
|
|
5716
|
+
} else if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#comment") {
|
|
5717
|
+
td.comment = String(s.object);
|
|
5718
|
+
if (td.label === void 0) td.description = String(s.object);
|
|
5719
|
+
}
|
|
5714
5720
|
if (s.predicate === SR + "rigidity") td.rigidity = String(s.object);
|
|
5715
5721
|
if (s.predicate === SR + "identity") td.identity = [...td.identity || [], String(s.object)];
|
|
5716
5722
|
if (s.predicate === SR + "dependsOn") td.dependsOn = [...td.dependsOn || [], stripDefaultPrefix(i2q(String(s.object), prefixes))];
|
|
@@ -5742,6 +5748,8 @@ function turtleToOnto(r) {
|
|
|
5742
5748
|
for (const s of stmts) {
|
|
5743
5749
|
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#domain") rd.domain = stripDefaultPrefix(i2q(String(s.object), prefixes));
|
|
5744
5750
|
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#range") rd.range = stripDefaultPrefix(i2q(String(s.object), prefixes));
|
|
5751
|
+
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#label") rd.label = String(s.object);
|
|
5752
|
+
if (s.predicate === "http://www.w3.org/2000/01/rdf-schema#comment") rd.comment = String(s.object);
|
|
5745
5753
|
if (s.predicate === SR + "cardinality") rd.cardinality = String(s.object);
|
|
5746
5754
|
}
|
|
5747
5755
|
onto.relations[name] = rd;
|
|
@@ -5751,7 +5759,14 @@ function turtleToOnto(r) {
|
|
|
5751
5759
|
const astmts = subjectMap.get(anode) || [];
|
|
5752
5760
|
const ad = { rule: "" };
|
|
5753
5761
|
for (const as_ of astmts) {
|
|
5754
|
-
if (as_.predicate === SR + "description"
|
|
5762
|
+
if (as_.predicate === SR + "description") ad.description = String(as_.object);
|
|
5763
|
+
else if (as_.predicate === "http://www.w3.org/2000/01/rdf-schema#label") {
|
|
5764
|
+
ad.label = String(as_.object);
|
|
5765
|
+
if (ad.description === void 0) ad.description = String(as_.object);
|
|
5766
|
+
} else if (as_.predicate === "http://www.w3.org/2000/01/rdf-schema#comment") {
|
|
5767
|
+
ad.comment = String(as_.object);
|
|
5768
|
+
if (ad.description === void 0) ad.description = String(as_.object);
|
|
5769
|
+
}
|
|
5755
5770
|
if (as_.predicate === SR + "rule") ad.rule = String(as_.object);
|
|
5756
5771
|
if (as_.predicate === SR + "axiomType") ad.type = String(as_.object);
|
|
5757
5772
|
}
|
|
@@ -6846,6 +6861,19 @@ function printLlmReviewHints(onto, issues) {
|
|
|
6846
6861
|
if (typeNames.length > 0) emit(` [L4] Review types: ${typeNames.join(", ")} — are there missing distinctions?\n`);
|
|
6847
6862
|
if ((onto.axioms || []).map((a) => a.description || a.rule).join("; ")) emit(` [L5] Axioms reference concepts — review if all referenced entities are defined\n`);
|
|
6848
6863
|
}
|
|
6864
|
+
/**
|
|
6865
|
+
* Markdown **表格单元**转义(`explain` 的类型表用)。
|
|
6866
|
+
*
|
|
6867
|
+
* 🔴 为什么必须有:描述是**任意散文**,而表格行由 `|` 分列、由换行断行 ⇒
|
|
6868
|
+
* - 描述里出现 `|`(本容器实测有:`sr:identity` 一类规则句、A45 探针注释都带)
|
|
6869
|
+
* ⇒ **当场多切一列**,整表错位;
|
|
6870
|
+
* - 描述跨多行 ⇒ **断行**,表格结构直接散架。
|
|
6871
|
+
* 两处都是"看着还能读、其实已经错位"的形态 ⇒ 在**唯一出口**统一处理,不指望作者自律。
|
|
6872
|
+
*/
|
|
6873
|
+
function mdCell(v) {
|
|
6874
|
+
if (v === void 0 || v === "") return "-";
|
|
6875
|
+
return v.replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
6876
|
+
}
|
|
6849
6877
|
function cmdExplain(args) {
|
|
6850
6878
|
if (args.length === 0) throw new MsmError("PARAMETER_MISSING", "user", "explain requires a file path", { validArgs: ["<path>"] }, "Usage: ontology explain <path>");
|
|
6851
6879
|
const filePath = args[0];
|
|
@@ -6856,9 +6884,9 @@ function cmdExplain(args) {
|
|
|
6856
6884
|
if (onto.imports && onto.imports.length > 0) emit(`Imports: ${onto.imports.join(", ")}\n`);
|
|
6857
6885
|
const types = merged.types || {};
|
|
6858
6886
|
emit(`\n### Types (${Object.keys(types).length})\n\n`);
|
|
6859
|
-
emit("| Type | SuperTypes | Rigidity | Properties |\n");
|
|
6860
|
-
emit("
|
|
6861
|
-
for (const [name, td] of Object.entries(types)) emit(`| ${name} | ${(td.superTypes || []).join(", ") || "-"} | ${td.rigidity || "-"} | ${td.properties ? Object.keys(td.properties).join(", ") : "-"} |\n`);
|
|
6887
|
+
emit("| Type | SuperTypes | Rigidity | Properties | Description |\n");
|
|
6888
|
+
emit("|------|-----------|----------|------------|-------------|\n");
|
|
6889
|
+
for (const [name, td] of Object.entries(types)) emit(`| ${name} | ${(td.superTypes || []).join(", ") || "-"} | ${td.rigidity || "-"} | ${td.properties ? Object.keys(td.properties).join(", ") : "-"} | ${mdCell(td.description)} |\n`);
|
|
6862
6890
|
const relations = merged.relations || {};
|
|
6863
6891
|
if (Object.keys(relations).length > 0) {
|
|
6864
6892
|
emit(`\n### Relations\n\n`);
|
|
@@ -7195,6 +7223,8 @@ function cmdReview(args) {
|
|
|
7195
7223
|
types: Object.entries(types).map(([n, t]) => ({
|
|
7196
7224
|
name: n,
|
|
7197
7225
|
description: t.description,
|
|
7226
|
+
label: t.label,
|
|
7227
|
+
comment: t.comment,
|
|
7198
7228
|
superTypes: t.superTypes,
|
|
7199
7229
|
rigidity: t.rigidity,
|
|
7200
7230
|
identity: t.identity,
|
package/lib/invariant.d.ts
CHANGED
|
@@ -10,6 +10,29 @@
|
|
|
10
10
|
* 返回不一致项列表(空 = 通过)。
|
|
11
11
|
*/
|
|
12
12
|
export declare function verifyToolConsistency(manifestPath: string, registeredTools: readonly string[]): string[];
|
|
13
|
+
/**
|
|
14
|
+
* 把「声明面散文」钉成可判(v1.56.2,2026-10-12)。
|
|
15
|
+
*
|
|
16
|
+
* 🔴 **为什么需要它**:同一形状的漏改本仓已经犯过**三次** ——
|
|
17
|
+
* - v1.31.0 加 `im-bridge`:两个包的 `description` 仍写「10 个工具」且不含它;
|
|
18
|
+
* - v1.52.0 加 `ontology`:`package.json` 的 description 仍写「12 个工具」、`dsh.plugin.json`
|
|
19
|
+
* 的收尾用**位置指代**("后三个按条件出现")而被追加项**当场改指**、`README.md` 缺行;
|
|
20
|
+
* - **v1.54.0 加 `serenity-skill-creator`**:`package.json` 的 description 仍写「13 个工具」
|
|
21
|
+
* (且清单里没有它)、**两份 `README.md` 的 §3.1 标题**仍写「十二个工具」。
|
|
22
|
+
* v1.52.1 当时写下的判据是「后三处只能靠纪律」—— **本版起改为机械钉**:纪律已被三次证伪。
|
|
23
|
+
*
|
|
24
|
+
* 被判的三处(都是**装包的人最先看到的**,也都没有别的钉子):
|
|
25
|
+
* ① `contributes.tools.length === REGISTERED_TOOLS.length`;
|
|
26
|
+
* ② **两份** `description` 都含正确的**总数**(`N 个工具`)—— 防"数错";
|
|
27
|
+
* ③ **两份** `description` 都含**每一个**工具名 —— 防"数对了、名单漏了"(v1.54.0 的形态)。
|
|
28
|
+
* ⚠️ 判据刻意**不要求**工具名出现在特定的逗号分隔段里(散文的排布是人的事,一钉就碎);
|
|
29
|
+
* 「后三个按条件出现」这句话由 `CONDITIONAL_TOOL_COUNT` + **顺序约定**保证**永远为真**
|
|
30
|
+
* (见 `REGISTERED_TOOLS` 的注释),**不需要**逐句解析。
|
|
31
|
+
*
|
|
32
|
+
* @param manifestPath dsh.plugin.json 路径
|
|
33
|
+
* @param readmePaths 需要一并被判的 README 路径(仓库根 + 包内两份;缺文件即报)
|
|
34
|
+
*/
|
|
35
|
+
export declare function assertManifestProse(manifestPath: string, readmePaths: readonly string[]): string[];
|
|
13
36
|
/**
|
|
14
37
|
* 包级不变量:本插件注册的工具集合(与 dsh.plugin.json contributes.tools 一致)。
|
|
15
38
|
*
|
|
@@ -35,4 +58,6 @@ export declare function verifyToolConsistency(manifestPath: string, registeredTo
|
|
|
35
58
|
* `review`(C 档,调引擎 `compliance`)/`index`(调 P1 的生成器)/`status` ⇒ **14**。
|
|
36
59
|
* 同规格:**条件可见与否不影响这里列它**(本常量 = "插件**具备**的工具面")。
|
|
37
60
|
*/
|
|
38
|
-
export declare const REGISTERED_TOOLS: readonly ["container_fs", "container_trajectory", "dashboard", "container_git", "msm", "praxis", "handyman", "localstore", "container_admin", "im-bridge", "acc-diag", "diagram"
|
|
61
|
+
export declare const REGISTERED_TOOLS: readonly ["container_fs", "container_trajectory", "dashboard", "container_git", "msm", "praxis", "ontology", "serenity-skill-creator", "handyman", "localstore", "container_admin", "im-bridge", "acc-diag", "diagram"];
|
|
62
|
+
/** 条件出现的工具数(`REGISTERED_TOOLS` 的**末段**;`assertManifestProse` 用) */
|
|
63
|
+
export declare const CONDITIONAL_TOOL_COUNT = 3;
|
package/lib/invariant.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
1
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
//#region src/invariant.ts
|
|
3
4
|
/**
|
|
@@ -32,6 +33,84 @@ function verifyToolConsistency(manifestPath, registeredTools) {
|
|
|
32
33
|
return issues;
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
36
|
+
* 把「声明面散文」钉成可判(v1.56.2,2026-10-12)。
|
|
37
|
+
*
|
|
38
|
+
* 🔴 **为什么需要它**:同一形状的漏改本仓已经犯过**三次** ——
|
|
39
|
+
* - v1.31.0 加 `im-bridge`:两个包的 `description` 仍写「10 个工具」且不含它;
|
|
40
|
+
* - v1.52.0 加 `ontology`:`package.json` 的 description 仍写「12 个工具」、`dsh.plugin.json`
|
|
41
|
+
* 的收尾用**位置指代**("后三个按条件出现")而被追加项**当场改指**、`README.md` 缺行;
|
|
42
|
+
* - **v1.54.0 加 `serenity-skill-creator`**:`package.json` 的 description 仍写「13 个工具」
|
|
43
|
+
* (且清单里没有它)、**两份 `README.md` 的 §3.1 标题**仍写「十二个工具」。
|
|
44
|
+
* v1.52.1 当时写下的判据是「后三处只能靠纪律」—— **本版起改为机械钉**:纪律已被三次证伪。
|
|
45
|
+
*
|
|
46
|
+
* 被判的三处(都是**装包的人最先看到的**,也都没有别的钉子):
|
|
47
|
+
* ① `contributes.tools.length === REGISTERED_TOOLS.length`;
|
|
48
|
+
* ② **两份** `description` 都含正确的**总数**(`N 个工具`)—— 防"数错";
|
|
49
|
+
* ③ **两份** `description` 都含**每一个**工具名 —— 防"数对了、名单漏了"(v1.54.0 的形态)。
|
|
50
|
+
* ⚠️ 判据刻意**不要求**工具名出现在特定的逗号分隔段里(散文的排布是人的事,一钉就碎);
|
|
51
|
+
* 「后三个按条件出现」这句话由 `CONDITIONAL_TOOL_COUNT` + **顺序约定**保证**永远为真**
|
|
52
|
+
* (见 `REGISTERED_TOOLS` 的注释),**不需要**逐句解析。
|
|
53
|
+
*
|
|
54
|
+
* @param manifestPath dsh.plugin.json 路径
|
|
55
|
+
* @param readmePaths 需要一并被判的 README 路径(仓库根 + 包内两份;缺文件即报)
|
|
56
|
+
*/
|
|
57
|
+
function assertManifestProse(manifestPath, readmePaths) {
|
|
58
|
+
const manifest = readPluginManifest(manifestPath);
|
|
59
|
+
if (!manifest) return [`manifest not found or invalid: ${manifestPath}`];
|
|
60
|
+
const tools = manifest.contributes?.tools ?? [];
|
|
61
|
+
const n = tools.length;
|
|
62
|
+
const issues = [];
|
|
63
|
+
if (n !== REGISTERED_TOOLS.length) issues.push(`contributes.tools 有 ${n} 项,而 REGISTERED_TOOLS 有 ${REGISTERED_TOOLS.length} 项(两侧必须同长)`);
|
|
64
|
+
const pkgPath = resolve(dirname(manifestPath), "package.json");
|
|
65
|
+
const surfaces = [];
|
|
66
|
+
if (existsSync(pkgPath)) try {
|
|
67
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
68
|
+
surfaces.push({
|
|
69
|
+
where: "package.json description",
|
|
70
|
+
text: pkg.description ?? ""
|
|
71
|
+
});
|
|
72
|
+
} catch {
|
|
73
|
+
issues.push(`package.json 无法解析:${pkgPath}`);
|
|
74
|
+
}
|
|
75
|
+
else issues.push(`package.json 不存在:${pkgPath}`);
|
|
76
|
+
surfaces.push({
|
|
77
|
+
where: "dsh.plugin.json description",
|
|
78
|
+
text: manifest.description ?? ""
|
|
79
|
+
});
|
|
80
|
+
for (const s of surfaces) {
|
|
81
|
+
if (!s.text.includes(`${n} 个工具`)) issues.push(`${s.where} 未声明工具总数「${n} 个工具」(防"数错")`);
|
|
82
|
+
const absent = tools.filter((t) => !s.text.includes(t));
|
|
83
|
+
if (absent.length) issues.push(`${s.where} 的名单缺 ${absent.length} 项:${absent.join(", ")}(防"数对了、名单漏了")`);
|
|
84
|
+
}
|
|
85
|
+
const cn = [
|
|
86
|
+
"零",
|
|
87
|
+
"一",
|
|
88
|
+
"二",
|
|
89
|
+
"三",
|
|
90
|
+
"四",
|
|
91
|
+
"五",
|
|
92
|
+
"六",
|
|
93
|
+
"七",
|
|
94
|
+
"八",
|
|
95
|
+
"九",
|
|
96
|
+
"十"
|
|
97
|
+
];
|
|
98
|
+
const countCn = n <= 10 ? cn[n] : n < 20 ? `十${cn[n - 10]}` : `二十${n === 20 ? "" : cn[n - 20]}`;
|
|
99
|
+
for (const p of readmePaths) {
|
|
100
|
+
if (!existsSync(p)) {
|
|
101
|
+
issues.push(`README 不存在:${p}`);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const m = readFileSync(p, "utf-8").match(/^###\s*3\.1\s*(\S+?)个工具/m);
|
|
105
|
+
if (!m) {
|
|
106
|
+
issues.push(`${p} 里找不到 §3.1 的「…个工具」标题(形态已变 ⇒ 钉子也要跟着改)`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (m[1] !== countCn) issues.push(`${p} 的 §3.1 标题写「${m[1]}个工具」,应为「${countCn}个工具」(工具数已 ${n})`);
|
|
110
|
+
}
|
|
111
|
+
return issues;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
35
114
|
* 包级不变量:本插件注册的工具集合(与 dsh.plugin.json contributes.tools 一致)。
|
|
36
115
|
*
|
|
37
116
|
* v1.31.1 修正:v1.31.0 新增 `im-bridge`(条件可见)时**漏改此处与清单**——两侧同错 →
|
|
@@ -63,14 +142,16 @@ const REGISTERED_TOOLS = [
|
|
|
63
142
|
"container_git",
|
|
64
143
|
"msm",
|
|
65
144
|
"praxis",
|
|
145
|
+
"ontology",
|
|
146
|
+
"serenity-skill-creator",
|
|
66
147
|
"handyman",
|
|
67
148
|
"localstore",
|
|
68
149
|
"container_admin",
|
|
69
150
|
"im-bridge",
|
|
70
151
|
"acc-diag",
|
|
71
|
-
"diagram"
|
|
72
|
-
"ontology",
|
|
73
|
-
"serenity-skill-creator"
|
|
152
|
+
"diagram"
|
|
74
153
|
];
|
|
154
|
+
/** 条件出现的工具数(`REGISTERED_TOOLS` 的**末段**;`assertManifestProse` 用) */
|
|
155
|
+
const CONDITIONAL_TOOL_COUNT = 3;
|
|
75
156
|
//#endregion
|
|
76
|
-
export { REGISTERED_TOOLS, verifyToolConsistency };
|
|
157
|
+
export { CONDITIONAL_TOOL_COUNT, REGISTERED_TOOLS, assertManifestProse, verifyToolConsistency };
|
package/lib/ontology/engine.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ interface PropertyDef {
|
|
|
56
56
|
}
|
|
57
57
|
interface TypeDef {
|
|
58
58
|
description?: string;
|
|
59
|
+
label?: string;
|
|
60
|
+
comment?: string;
|
|
59
61
|
superTypes?: string[];
|
|
60
62
|
rigidity?: "rigid" | "anti-rigid" | "semi-rigid";
|
|
61
63
|
identity?: string[];
|
|
@@ -64,6 +66,8 @@ interface TypeDef {
|
|
|
64
66
|
axioms?: string[];
|
|
65
67
|
}
|
|
66
68
|
interface RelationDef {
|
|
69
|
+
label?: string;
|
|
70
|
+
comment?: string;
|
|
67
71
|
domain?: string;
|
|
68
72
|
range?: string;
|
|
69
73
|
cardinality?: string;
|
|
@@ -76,6 +80,10 @@ interface RelationDef {
|
|
|
76
80
|
}
|
|
77
81
|
interface AxiomDef {
|
|
78
82
|
description?: string;
|
|
83
|
+
/** `rdfs:label`(与 `description` 分开存;description 仍以 `sr:description` 优先) */
|
|
84
|
+
label?: string;
|
|
85
|
+
/** `rdfs:comment` */
|
|
86
|
+
comment?: string;
|
|
79
87
|
rule: string;
|
|
80
88
|
type?: string;
|
|
81
89
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.56.
|
|
4
|
-
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:
|
|
3
|
+
"version": "1.56.2",
|
|
4
|
+
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/handyman/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1 与 0.2.0-rc.1(双档)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|