@shgroup/dsh-serenity-hooks 1.56.2 → 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.
@@ -94,7 +94,53 @@ interface OntologyDefinition {
94
94
  types?: Record<string, TypeDef>;
95
95
  relations?: Record<string, RelationDef>;
96
96
  axioms?: AxiomDef[];
97
+ /** 个体(`a <本文件已声明的类>`)。图要画它们,故收进模型(2026-10-13 S142)。 */
98
+ instances?: InstanceDef[];
97
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;
98
144
  type ExprNode = PropAccessNode | LiteralNode | FuncCallNode | QuantifierNode | BinaryOpNode | UnaryOpNode | ImplicationNode | ParensNode;
99
145
  interface PropAccessNode {
100
146
  kind: "propAccess";
@@ -145,6 +191,11 @@ interface ParensNode {
145
191
  expr: ExprNode;
146
192
  pos: number;
147
193
  }
194
+ declare function loadOntoFile(filePath: string): {
195
+ onto: OntologyDefinition;
196
+ raw: string;
197
+ };
198
+ declare function loadOntoFileWithImports(filePath: string, visited?: Set<string>): OntologyDefinition;
148
199
  interface CheckIssue {
149
200
  check: string;
150
201
  severity: "error" | "warning";
@@ -173,4 +224,4 @@ export interface OntologyRunResult {
173
224
  * 以及把 `code !== 0` 翻成响亮的回执(引擎的 stderr 文案**逐字保留**,不重写)。
174
225
  */
175
226
  export declare function runOntologyCli(argv: string[], opts?: OntologyRunOptions): OntologyRunResult;
176
- 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,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.56.2",
3
+ "version": "1.56.3",
4
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": {