@shgroup/dsh-serenity-hooks 1.56.1 → 1.56.3
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 +948 -167
- package/lib/invariant.d.ts +26 -1
- package/lib/invariant.js +85 -4
- package/lib/ontology/engine.d.ts +60 -1
- package/lib/ontology/viz.d.ts +138 -0
- package/package.json +2 -2
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
|
}
|
|
@@ -86,7 +94,53 @@ interface OntologyDefinition {
|
|
|
86
94
|
types?: Record<string, TypeDef>;
|
|
87
95
|
relations?: Record<string, RelationDef>;
|
|
88
96
|
axioms?: AxiomDef[];
|
|
97
|
+
/** 个体(`a <本文件已声明的类>`)。图要画它们,故收进模型(2026-10-13 S142)。 */
|
|
98
|
+
instances?: InstanceDef[];
|
|
89
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* 一个个体:`:trapFalseGreen a :KnownTrap ; sr:trapName "…"`。
|
|
102
|
+
*
|
|
103
|
+
* 🔴 **判据刻意是"`a` 指向的类是【本文件已声明的类】**",不是"任何非 owl:* 的东西" ——
|
|
104
|
+
* 后者会把 `rdfs:domain :A`、`sr:imports`、甚至**外部实体**全误认成个体
|
|
105
|
+
* (viz 侧实测:`dsh-serenity-plugin-development/skill.ttl` 有 13 个真个体,
|
|
106
|
+
* 而宽松判据会捞回一堆假货)。
|
|
107
|
+
*
|
|
108
|
+
* 标签取用顺序(`label` 一个字段,兼容既有 `description`):
|
|
109
|
+
* `rdfs:label` → `sr:trapName` / `sr:name` → **第一条字面量谓语**(如 `sr:signature`)。
|
|
110
|
+
* 最后那条是 2026-10-13 加的:实测 `:KnownTrap` 的 7 个个体**既无 `rdfs:label` 也无 `sr:name`**,
|
|
111
|
+
* 只有 `sr:trapName`/`sr:signature` ⇒ 不兜底的话图上 7 个方块全是裸 id。
|
|
112
|
+
*/
|
|
113
|
+
interface InstanceDef {
|
|
114
|
+
id: string;
|
|
115
|
+
ofClass: string;
|
|
116
|
+
label?: string;
|
|
117
|
+
}
|
|
118
|
+
type TkKind = "qname" | "iri" | "a" | "literal" | "number" | "boolean" | "prefix" | "base" | "dot" | "semi" | "comma" | "lbracket" | "rbracket" | "lparen" | "rparen" | "eof";
|
|
119
|
+
interface Tk {
|
|
120
|
+
kind: TkKind;
|
|
121
|
+
value: string;
|
|
122
|
+
pos: number;
|
|
123
|
+
datatype?: string;
|
|
124
|
+
lang?: string;
|
|
125
|
+
}
|
|
126
|
+
declare function tokenizeTurtle(input: string): {
|
|
127
|
+
tokens: Tk[];
|
|
128
|
+
errors: string[];
|
|
129
|
+
};
|
|
130
|
+
interface Triple {
|
|
131
|
+
subject: string;
|
|
132
|
+
predicate: string;
|
|
133
|
+
object: string | number | boolean;
|
|
134
|
+
objectType: "iri" | "literal" | "blank";
|
|
135
|
+
objectDatatype?: string;
|
|
136
|
+
}
|
|
137
|
+
interface TurtleParseResult {
|
|
138
|
+
prefixes: Map<string, string>;
|
|
139
|
+
triples: Triple[];
|
|
140
|
+
errors: string[];
|
|
141
|
+
}
|
|
142
|
+
declare function parseTurtle(raw: string): TurtleParseResult;
|
|
143
|
+
declare function turtleToOnto(r: TurtleParseResult): OntologyDefinition;
|
|
90
144
|
type ExprNode = PropAccessNode | LiteralNode | FuncCallNode | QuantifierNode | BinaryOpNode | UnaryOpNode | ImplicationNode | ParensNode;
|
|
91
145
|
interface PropAccessNode {
|
|
92
146
|
kind: "propAccess";
|
|
@@ -137,6 +191,11 @@ interface ParensNode {
|
|
|
137
191
|
expr: ExprNode;
|
|
138
192
|
pos: number;
|
|
139
193
|
}
|
|
194
|
+
declare function loadOntoFile(filePath: string): {
|
|
195
|
+
onto: OntologyDefinition;
|
|
196
|
+
raw: string;
|
|
197
|
+
};
|
|
198
|
+
declare function loadOntoFileWithImports(filePath: string, visited?: Set<string>): OntologyDefinition;
|
|
140
199
|
interface CheckIssue {
|
|
141
200
|
check: string;
|
|
142
201
|
severity: "error" | "warning";
|
|
@@ -165,4 +224,4 @@ export interface OntologyRunResult {
|
|
|
165
224
|
* 以及把 `code !== 0` 翻成响亮的回执(引擎的 stderr 文案**逐字保留**,不重写)。
|
|
166
225
|
*/
|
|
167
226
|
export declare function runOntologyCli(argv: string[], opts?: OntologyRunOptions): OntologyRunResult;
|
|
168
|
-
export { MsmError, validateOnto, type OntologyDefinition, type CheckIssue, type ExprNode };
|
|
227
|
+
export { MsmError, validateOnto, tokenizeTurtle, parseTurtle, turtleToOnto, loadOntoFile, loadOntoFileWithImports, type OntologyDefinition, type CheckIssue, type ExprNode, type TypeDef, type RelationDef, type AxiomDef, type InstanceDef, type PropertyDef };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
interface OntoModel {
|
|
2
|
+
file: string;
|
|
3
|
+
prefixes: Map<string, string>;
|
|
4
|
+
base: string | null;
|
|
5
|
+
/** 本体自身元信息 */
|
|
6
|
+
meta: {
|
|
7
|
+
label?: string;
|
|
8
|
+
comment?: string;
|
|
9
|
+
version?: string;
|
|
10
|
+
imports: string[];
|
|
11
|
+
};
|
|
12
|
+
classes: ClassDef[];
|
|
13
|
+
relations: RelationDef[];
|
|
14
|
+
axioms: AxiomDef[];
|
|
15
|
+
instances: InstanceDef[];
|
|
16
|
+
/** 没认出来的主语 a 类型(fail-loud 计数) */
|
|
17
|
+
unknownTypes: string[];
|
|
18
|
+
}
|
|
19
|
+
interface ClassDef {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
comment: string;
|
|
23
|
+
rigidity: "rigid" | "anti-rigid" | "semi-rigid" | null;
|
|
24
|
+
identity: string[];
|
|
25
|
+
properties: {
|
|
26
|
+
name: string;
|
|
27
|
+
type: string;
|
|
28
|
+
cardinality: string;
|
|
29
|
+
}[];
|
|
30
|
+
parents: string[];
|
|
31
|
+
}
|
|
32
|
+
interface RelationDef {
|
|
33
|
+
id: string;
|
|
34
|
+
label: string;
|
|
35
|
+
comment: string;
|
|
36
|
+
domain: string | null;
|
|
37
|
+
range: string | null;
|
|
38
|
+
cardinality: string;
|
|
39
|
+
isObject: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface AxiomDef {
|
|
42
|
+
id: string;
|
|
43
|
+
rule: string;
|
|
44
|
+
type: string;
|
|
45
|
+
comment: string;
|
|
46
|
+
/** 规则文本里提到、且**本文件确实声明了**的类型名(用于连边) */
|
|
47
|
+
mentions: string[];
|
|
48
|
+
}
|
|
49
|
+
interface InstanceDef {
|
|
50
|
+
id: string;
|
|
51
|
+
ofClass: string | null;
|
|
52
|
+
label: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* `OntoModel` 的**唯一来源 = 引擎的解析器**(2026-10-13 S142)。
|
|
56
|
+
*
|
|
57
|
+
* 🔴 这里**不解析任何 Turtle** —— 只把引擎的 `OntologyDefinition` **翻译**成本文件的
|
|
58
|
+
* 渲染模型。原 viz 自带的手写解析器已整块删除:它实测错三类
|
|
59
|
+
* (只认具名式公理 ⇒ 8/16 文件公理数归零;`sr:identity` 只认括号形 ⇒ 18 处假阳;
|
|
60
|
+
* 从不读 `sr:description` ⇒ 公理正文丢失)。引擎两种写法都认 ⇒ 三类**自动消失**。
|
|
61
|
+
*
|
|
62
|
+
* 需引擎侧先满足两件事(已随 82e740f 落地):导出 `loadOntoFile`/类型;模型收 `instances`。
|
|
63
|
+
*/
|
|
64
|
+
declare function fromEngine(file: string, absPath: string): OntoModel;
|
|
65
|
+
interface Box {
|
|
66
|
+
id: string;
|
|
67
|
+
kind: "class" | "relation" | "axiom" | "import" | "instance" | "self";
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
w: number;
|
|
71
|
+
h: number;
|
|
72
|
+
title: string;
|
|
73
|
+
lines: string[];
|
|
74
|
+
fill: string;
|
|
75
|
+
}
|
|
76
|
+
interface Edge {
|
|
77
|
+
from: string;
|
|
78
|
+
to: string;
|
|
79
|
+
label: string;
|
|
80
|
+
kind: "relation" | "axiom" | "instance" | "import";
|
|
81
|
+
/** 该边**竖直通道**的 x(由布局分配,逐条错开 —— 否则同源多边会叠在一条线上) */
|
|
82
|
+
channelX?: number;
|
|
83
|
+
/** 标签落点(放在**进入目标的那段水平线**上方 ⇒ 每条边落点不同,不互相压) */
|
|
84
|
+
labelAt?: [number, number];
|
|
85
|
+
/** 该边是否绕行(右→左或跨多列):发射器据此走上方弧线 */
|
|
86
|
+
detour?: boolean;
|
|
87
|
+
}
|
|
88
|
+
interface Layout {
|
|
89
|
+
boxes: Box[];
|
|
90
|
+
edges: Edge[];
|
|
91
|
+
width: number;
|
|
92
|
+
height: number;
|
|
93
|
+
notes: string[];
|
|
94
|
+
}
|
|
95
|
+
declare function layout(model: OntoModel, opts: {
|
|
96
|
+
axioms: boolean;
|
|
97
|
+
instances: boolean;
|
|
98
|
+
imports: boolean;
|
|
99
|
+
}): Layout;
|
|
100
|
+
/**
|
|
101
|
+
* 纯文本版(**任何通道都能看** —— 不依赖图像输入、不依赖浏览器)。
|
|
102
|
+
*
|
|
103
|
+
* 🔴 为什么必要:本模型的当前路由**未声明图像输入**,`diagram` 出的 PNG 贴不进对话
|
|
104
|
+
* (工具会降级落盘)。没有这个视图,我就只能让 owner 去开文件 —— 那等于没"给他看效果"。
|
|
105
|
+
* 形态 = **按带分组的方框清单 + 关系列表**(XML 树状),保留结构信息、丢掉空间信息。
|
|
106
|
+
*/
|
|
107
|
+
declare function toText(model: OntoModel, L: Layout, opts: {
|
|
108
|
+
axioms: boolean;
|
|
109
|
+
}): string;
|
|
110
|
+
/**
|
|
111
|
+
* **DOT(Graphviz)** —— 机械生成的**严谨**通路(推荐)。
|
|
112
|
+
*
|
|
113
|
+
* ## 为什么把布局交给 Graphviz
|
|
114
|
+
* 手写的分层布局能满足"不重叠",但**边绕行 / 标签避让 / 交叉最小化**是图布局的成熟难题,
|
|
115
|
+
* Graphviz 的 `dot` 引擎专做这件事(分层 DAG、`splines=ortho` 正交走线、自动避让节点)。
|
|
116
|
+
* 我们的职责于是收缩成一件事:**把本体忠实地翻译成 DOT**(节点/边/分组/样式),
|
|
117
|
+
* 布局交给引擎 —— 这正是"机械生成 + 可读性好"的正解。
|
|
118
|
+
*
|
|
119
|
+
* ## 输出约束(**只出确定性的东西**)
|
|
120
|
+
* - 节点 id 用**下标**(`n0`/`n1`…)而不是本体名 —— 本体名里有 `:`、`.`、`/`,
|
|
121
|
+
* 直接当 DOT id 需要转义且容易踩坑;真实名字放进 `label`。
|
|
122
|
+
* - 每条语句顺序固定 ⇒ 同一份 `.ttl` **永远出同一份 DOT**(判据 S↑)。
|
|
123
|
+
* - 不写 `pos=`(那是引擎的输出,不是输入)⇒ 可重复生成。
|
|
124
|
+
*/
|
|
125
|
+
declare function toDot(model: OntoModel, opts: {
|
|
126
|
+
axioms: boolean;
|
|
127
|
+
instances: boolean;
|
|
128
|
+
imports: boolean;
|
|
129
|
+
}): string;
|
|
130
|
+
declare function toDiagramSource(model: OntoModel, L: Layout, opts: {
|
|
131
|
+
axioms?: boolean;
|
|
132
|
+
instances?: boolean;
|
|
133
|
+
}): string;
|
|
134
|
+
declare function toSvg(model: OntoModel, L: Layout, opts: {
|
|
135
|
+
axioms: boolean;
|
|
136
|
+
}): string;
|
|
137
|
+
declare function toHtml(model: OntoModel, L: Layout, svg: string): string;
|
|
138
|
+
export { fromEngine, layout, toSvg, toHtml, toText, toDot, toDiagramSource, type OntoModel };
|
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.3",
|
|
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",
|