dsh-logicprobe 1.2.0 → 1.3.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.
- package/README.en-US.md +2 -2
- package/README.md +2 -2
- package/lib/types/uml.d.ts +293 -256
- package/lib/uml-tool.js +153 -145
- package/lib/uml.js +1812 -1748
- package/package.json +1 -1
- package/skills/logicprobe/SKILL.md +19 -0
- package/skills/logicprobe-concurrency/SKILL.md +1 -0
- package/skills/logicprobe-datamodel/SKILL.md +5 -0
- package/skills/logicprobe-structure/SKILL.md +1 -0
- package/skills/logicprobe-uml/SKILL.md +3 -0
- package/skills/logicprobe-uml/references/uml-modeling-guide.md +70 -2
- package/src/uml-tool.ts +11 -3
- package/src/uml.ts +94 -11
package/README.en-US.md
CHANGED
|
@@ -80,12 +80,12 @@ Any key starting with `_` — at any level: `_source`, `_verified`, `_extraction
|
|
|
80
80
|
|
|
81
81
|
`logicprobe_uml` draws a LogicModelV1 as UML. It also reads a hand-drawn UML diagram back into a model, reviews the modelling itself, and prints the label and comment conventions the parser accepts. It has four actions:
|
|
82
82
|
|
|
83
|
-
- **render**: model to diagram. Mermaid covers state, activity flowchart and sequence views. PlantUML covers state and sequence. Any construct the notation cannot express becomes a warning instead of a silent drop. PlantUML activity is refused, because that syntax cannot carry a graph with merges or cycles faithfully.
|
|
83
|
+
- **render**: model to diagram. Mermaid covers state, activity flowchart and sequence views. PlantUML covers state and sequence. Any construct the notation cannot express becomes a warning instead of a silent drop. PlantUML activity is refused, because that syntax cannot carry a graph with merges or cycles faithfully. The view follows the question, not the machine, so no tool picks it for you: declare the purpose with `intent` (`present` / `verify` / `fidelity`) and a pairing that cannot serve it is refused before any work (`UML_INTENT_UNSERVABLE`, `UML_VIEW_UNREPRESENTABLE`, `UML_INTENT_MISMATCH`). Omit `intent` and nothing changes.
|
|
84
84
|
- **parse**: diagram to model. It reads Mermaid and PlantUML state or activity diagrams, so a hand-drawn diagram can go straight into `logicprobe_verify`. Two inputs are refused because they cannot become a machine: a sequence diagram (a trace cannot reconstruct a machine), and any other Mermaid family (`classDiagram`, `erDiagram`, `gantt`, `mindmap`, …), which comes back as `errorCode: "UML_NOT_A_STATE_DIAGRAM"` naming the family.
|
|
85
85
|
- **review**: audits the modelling. It reports structural defects and documentation gaps. The structural defects are unreachable states, dead ends, ambiguous branches, self-loops with no exit, and duplicate transitions. The documentation gaps are a missing narrative, unbounded variables, states a reader cannot map back to code, and label drift between diagram and narrative. It also runs the fidelity check: it parses the diagram back into a model and reports every structural difference.
|
|
86
86
|
- **explain-labels**: prints the label spellings and ignored-line rules the parser applies (`directiveLines`, `acceptedLabelForms`, `renderedForm`, `ignoredLines`, `rules`), with no diagram needed. Reach for it when a hand-drawn diagram and a rendered one disagree; the CLI mirror is `uml-review --explain-labels`.
|
|
87
87
|
|
|
88
|
-
**A structure diagram is the dangerous case, because it parses.** A PlantUML component, package, class or deployment diagram declares no diagram kind, so the parser meets its keywords line by line. The arrows look like transitions, so `parse` returns a by-product model — now together with an error finding `UML_NOT_A_STATE_DIAGRAM`, `discardedConstructs` (every declaration it could not represent, with line and text), `discardedEdges` (the arrows misread as transitions) and `verdict: "fail"`. Read that as: **this file has no model and this diagram was not reviewed.** Do not feed the by-product to `logicprobe_verify` and call the result an architecture review. Structural checks over a real dependency graph (allowed-edge matrices, cycles, isolated nodes)
|
|
88
|
+
**A structure diagram is the dangerous case, because it parses.** A PlantUML component, package, class or deployment diagram declares no diagram kind, so the parser meets its keywords line by line. The arrows look like transitions, so `parse` returns a by-product model — now together with an error finding `UML_NOT_A_STATE_DIAGRAM`, `discardedConstructs` (every declaration it could not represent, with line and text), `discardedEdges` (the arrows misread as transitions) and `verdict: "fail"`. Read that as: **this file has no model and this diagram was not reviewed.** Do not feed the by-product to `logicprobe_verify` and call the result an architecture review. Structural checks over a real dependency graph (allowed-edge matrices, cycles, isolated nodes) belong to `logicprobe_structure_verify`, under Architecture and Dependency Review below.
|
|
89
89
|
|
|
90
90
|
Fidelity is the core of the feature. Generated diagrams carry `logicprobe:` comment directives for the initial state, the terminal states, aliases and variable kinds. Mermaid and PlantUML ignore those lines; the parser reads them. That is what makes the diagram-versus-model comparison exact.
|
|
91
91
|
|
package/README.md
CHANGED
|
@@ -78,12 +78,12 @@ logicprobe 核验声称与实物是否一致。事实类对着源码查。行为
|
|
|
78
78
|
|
|
79
79
|
`logicprobe_uml` 把一份 LogicModelV1 画成 UML,也可以把手绘的 UML 读回模型,还可以审查建模本身,或打印解析器接受的标签与注释口径。它有 4 个动作:
|
|
80
80
|
|
|
81
|
-
- **render**:模型 → 图。Mermaid 支持状态图、活动流程图、时序图;PlantUML 支持状态图与时序图。notation 表达不了的构造会变成 warning,不会被悄悄丢掉。PlantUML
|
|
81
|
+
- **render**:模型 → 图。Mermaid 支持状态图、活动流程图、时序图;PlantUML 支持状态图与时序图。notation 表达不了的构造会变成 warning,不会被悄悄丢掉。PlantUML 活动图直接拒绝,因为它的语法无法忠实承载带合流或环的图。视图由问题决定、不由模型决定,所以工具不替你选:用 `intent`(`present`/`verify`/`fidelity`)声明产物用途,服务不了的组合在开工之前就拒(`UML_INTENT_UNSERVABLE`、`UML_VIEW_UNREPRESENTABLE`、`UML_INTENT_MISMATCH`);不给 `intent` 则行为与从前完全一致。
|
|
82
82
|
- **parse**:图 → 模型。支持 Mermaid 与 PlantUML 的状态图、活动图,因此手绘的图也能送进 `logicprobe_verify` 验证。两类输入会被拒绝,因为它们无法变成状态机:时序图(迹无法重建机),以及**其它 Mermaid 图族**(`classDiagram`、`erDiagram`、`gantt`、`mindmap`…),返回 `errorCode: "UML_NOT_A_STATE_DIAGRAM"` 并点名该图族。
|
|
83
83
|
- **review**:审查建模。它报告两类问题。结构缺陷包括不可达状态、死端、歧义分支、无出口自环、重复迁移。文档缺口包括缺 narrative、变量无界、状态无可读标注、图与 narrative 标签漂移。它还会做保真度检查:把图重新解析回模型,任何结构性差异都报出来。
|
|
84
84
|
- **explain-labels**:打印解析器接受的标签写法与忽略行口径(`directiveLines`、`acceptedLabelForms`、`renderedForm`、`ignoredLines`、`rules`),不需要给图。手绘图与渲染图对不齐时先看它;命令行对应 `uml-review --explain-labels`。
|
|
85
85
|
|
|
86
|
-
**结构图是最危险的一类,因为它「能解析」。** PlantUML 的组件图 / 包图 / 类图 / 部署图不声明图类型,解析器会逐行碰上它的关键字。箭头看起来就是迁移,于是 `parse` 会返回一个副产品模型——但现在同时给出 error 级发现 `UML_NOT_A_STATE_DIAGRAM`、`discardedConstructs`(每条无法表达的声明及其行号与原文)、`discardedEdges`(被误读成迁移的箭头数),以及 `verdict: "fail"`。意思是:**这份文件没有被建模,这张图没有被审查。** 不要把那个副产品喂给 `logicprobe_verify`
|
|
86
|
+
**结构图是最危险的一类,因为它「能解析」。** PlantUML 的组件图 / 包图 / 类图 / 部署图不声明图类型,解析器会逐行碰上它的关键字。箭头看起来就是迁移,于是 `parse` 会返回一个副产品模型——但现在同时给出 error 级发现 `UML_NOT_A_STATE_DIAGRAM`、`discardedConstructs`(每条无法表达的声明及其行号与原文)、`discardedEdges`(被误读成迁移的箭头数),以及 `verdict: "fail"`。意思是:**这份文件没有被建模,这张图没有被审查。** 不要把那个副产品喂给 `logicprobe_verify` 当作架构审查结论。真正的依赖图检查(允许依赖矩阵、环、孤立节点)由 `logicprobe_structure_verify` 承担,见下方「架构与依赖审查」。
|
|
87
87
|
|
|
88
88
|
保真度是这套功能的核心。生成的图带有 `logicprobe:` 注释指令(init、终态、别名、变量类型),Mermaid 与 PlantUML 会忽略它们,而解析器会读取它们。因此「图 ↔ 模型」的比较是精确的。
|
|
89
89
|
|
package/lib/types/uml.d.ts
CHANGED
|
@@ -1,256 +1,293 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UML front end for LogicModelV1 — model a code flow as a UML diagram, then
|
|
3
|
-
* review the modelling itself.
|
|
4
|
-
*
|
|
5
|
-
* Two halves, one data flow:
|
|
6
|
-
*
|
|
7
|
-
* 1. `renderUml` turns a validated LogicModelV1 into Mermaid or PlantUML text
|
|
8
|
-
* (state machine, activity/flow, or sequence trace). The diagram is a
|
|
9
|
-
* *view*: it never invents structure the model does not have, and anything
|
|
10
|
-
* the notation cannot express is reported as a warning instead of being
|
|
11
|
-
* dropped silently.
|
|
12
|
-
* 2. `parseUml` reads that text back into a LogicModelV1, and `reviewUml`
|
|
13
|
-
* compares the two. That comparison is the point of the feature: a UML
|
|
14
|
-
* diagram of a code flow is itself a model, and a model can be wrong —
|
|
15
|
-
* ambiguous branches, dead ends, flows nobody can enter, symbols the
|
|
16
|
-
* source never names. A diagram that does not round-trip to the model it
|
|
17
|
-
* was drawn from is mis-modelled, and the review says so.
|
|
18
|
-
*
|
|
19
|
-
* Why the round trip is the fidelity check: rendering and parsing are inverse
|
|
20
|
-
* only if every construct survives the notation. The generated text carries
|
|
21
|
-
* `logicprobe:` directives (ignored by Mermaid/PlantUML renderers) that pin the
|
|
22
|
-
* initial state, the terminal states and any state id the notation cannot spell
|
|
23
|
-
* verbatim, so an exact comparison is possible rather than a fuzzy one.
|
|
24
|
-
*
|
|
25
|
-
* The review deliberately does NOT replace `logicprobe_verify`: it checks the
|
|
26
|
-
* modelling (structure the diagram claims, documentation coverage, notation
|
|
27
|
-
* fidelity), while S1-S8/A1-A14 check the machine's behaviour (guard
|
|
28
|
-
* exhaustiveness under real valuations, invariant paths, deadlock/liveness in
|
|
29
|
-
* the runtime state space). Findings name the engine check to run next.
|
|
30
|
-
*
|
|
31
|
-
* @module logicprobe-uml
|
|
32
|
-
*/
|
|
33
|
-
import { type HashSpec, type NarrativeCoverage, type ReportSchema, type Verdict } from './engine.js';
|
|
34
|
-
import type { GuardNode, LogicModelV1, UpdateSpec } from './engine.js';
|
|
35
|
-
export type UmlNotation = 'mermaid' | 'plantuml';
|
|
36
|
-
export type UmlDiagram = 'state' | 'activity' | 'sequence';
|
|
37
|
-
export declare const UML_NOTATIONS: readonly UmlNotation[];
|
|
38
|
-
export declare const UML_DIAGRAMS: readonly UmlDiagram[];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
export interface
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
*
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
*
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
*
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
|
|
256
|
-
|
|
1
|
+
/**
|
|
2
|
+
* UML front end for LogicModelV1 — model a code flow as a UML diagram, then
|
|
3
|
+
* review the modelling itself.
|
|
4
|
+
*
|
|
5
|
+
* Two halves, one data flow:
|
|
6
|
+
*
|
|
7
|
+
* 1. `renderUml` turns a validated LogicModelV1 into Mermaid or PlantUML text
|
|
8
|
+
* (state machine, activity/flow, or sequence trace). The diagram is a
|
|
9
|
+
* *view*: it never invents structure the model does not have, and anything
|
|
10
|
+
* the notation cannot express is reported as a warning instead of being
|
|
11
|
+
* dropped silently.
|
|
12
|
+
* 2. `parseUml` reads that text back into a LogicModelV1, and `reviewUml`
|
|
13
|
+
* compares the two. That comparison is the point of the feature: a UML
|
|
14
|
+
* diagram of a code flow is itself a model, and a model can be wrong —
|
|
15
|
+
* ambiguous branches, dead ends, flows nobody can enter, symbols the
|
|
16
|
+
* source never names. A diagram that does not round-trip to the model it
|
|
17
|
+
* was drawn from is mis-modelled, and the review says so.
|
|
18
|
+
*
|
|
19
|
+
* Why the round trip is the fidelity check: rendering and parsing are inverse
|
|
20
|
+
* only if every construct survives the notation. The generated text carries
|
|
21
|
+
* `logicprobe:` directives (ignored by Mermaid/PlantUML renderers) that pin the
|
|
22
|
+
* initial state, the terminal states and any state id the notation cannot spell
|
|
23
|
+
* verbatim, so an exact comparison is possible rather than a fuzzy one.
|
|
24
|
+
*
|
|
25
|
+
* The review deliberately does NOT replace `logicprobe_verify`: it checks the
|
|
26
|
+
* modelling (structure the diagram claims, documentation coverage, notation
|
|
27
|
+
* fidelity), while S1-S8/A1-A14 check the machine's behaviour (guard
|
|
28
|
+
* exhaustiveness under real valuations, invariant paths, deadlock/liveness in
|
|
29
|
+
* the runtime state space). Findings name the engine check to run next.
|
|
30
|
+
*
|
|
31
|
+
* @module logicprobe-uml
|
|
32
|
+
*/
|
|
33
|
+
import { type HashSpec, type NarrativeCoverage, type ReportSchema, type Verdict } from './engine.js';
|
|
34
|
+
import type { GuardNode, LogicModelV1, UpdateSpec } from './engine.js';
|
|
35
|
+
export type UmlNotation = 'mermaid' | 'plantuml';
|
|
36
|
+
export type UmlDiagram = 'state' | 'activity' | 'sequence';
|
|
37
|
+
export declare const UML_NOTATIONS: readonly UmlNotation[];
|
|
38
|
+
export declare const UML_DIAGRAMS: readonly UmlDiagram[];
|
|
39
|
+
/**
|
|
40
|
+
* What the caller is going to do with the artifact, declared up front.
|
|
41
|
+
*
|
|
42
|
+
* The view follows the question, not the machine, so the tool cannot pick it. What it
|
|
43
|
+
* can do is refuse a pairing that cannot serve the question — before the work, not as
|
|
44
|
+
* a finding after it.
|
|
45
|
+
*/
|
|
46
|
+
export type UmlIntent = 'present' | 'verify' | 'fidelity';
|
|
47
|
+
export declare const UML_INTENTS: readonly UmlIntent[];
|
|
48
|
+
/** The tool actions, for the entry check. `labels` is `action=explain-labels`. */
|
|
49
|
+
export type UmlIntentAction = 'render' | 'parse' | 'review' | 'labels';
|
|
50
|
+
export interface UmlRenderResult {
|
|
51
|
+
notation: UmlNotation;
|
|
52
|
+
diagram: UmlDiagram;
|
|
53
|
+
/** The diagram source; hand this to the user or a renderer as-is. */
|
|
54
|
+
primary: string;
|
|
55
|
+
warnings: string[];
|
|
56
|
+
}
|
|
57
|
+
export interface UmlParseResult {
|
|
58
|
+
notation: UmlNotation;
|
|
59
|
+
diagram: UmlDiagram;
|
|
60
|
+
model: LogicModelV1;
|
|
61
|
+
/**
|
|
62
|
+
* Display labels found in the diagram, keyed by state id. They are how a
|
|
63
|
+
* reader learns what a symbol means; a missing entry is an undocumented
|
|
64
|
+
* symbol, which the review reports.
|
|
65
|
+
*/
|
|
66
|
+
labels: Record<string, string>;
|
|
67
|
+
/**
|
|
68
|
+
* Declarations found in the text that LogicModelV1 cannot represent. A non-empty
|
|
69
|
+
* list means the parsed model is NOT this diagram: the text belongs to another
|
|
70
|
+
* diagram family (component, package, class, deployment, …), so whatever came
|
|
71
|
+
* out is a by-product of reading keywords the parser does not own.
|
|
72
|
+
*/
|
|
73
|
+
discardedConstructs: DiscardedConstruct[];
|
|
74
|
+
/**
|
|
75
|
+
* Arrows whose endpoints were declared by a discarded construct. They survive
|
|
76
|
+
* parsing as state transitions, which is exactly why they are counted out loud.
|
|
77
|
+
*/
|
|
78
|
+
discardedEdges: number;
|
|
79
|
+
warnings: string[];
|
|
80
|
+
}
|
|
81
|
+
/** One declaration the parser could not represent, with the source line that carried it. */
|
|
82
|
+
export interface DiscardedConstruct {
|
|
83
|
+
/** The construct keyword, lower-cased (`component`, `package`, `classDiagram`). */
|
|
84
|
+
construct: string;
|
|
85
|
+
/** 1-based line number in the diagram source. */
|
|
86
|
+
line: number;
|
|
87
|
+
/** The source line, trimmed. */
|
|
88
|
+
text: string;
|
|
89
|
+
}
|
|
90
|
+
export interface UmlFinding {
|
|
91
|
+
code: string;
|
|
92
|
+
severity: 'error' | 'warning' | 'info';
|
|
93
|
+
message: string;
|
|
94
|
+
states?: string[];
|
|
95
|
+
events?: string[];
|
|
96
|
+
transitions?: Array<{
|
|
97
|
+
from: string;
|
|
98
|
+
event: string;
|
|
99
|
+
to: string;
|
|
100
|
+
}>;
|
|
101
|
+
detail?: string;
|
|
102
|
+
/** Machine-readable context for the finding (ids, coverage, rule matches), same shape as the engine's findings. */
|
|
103
|
+
evidence?: Record<string, unknown>;
|
|
104
|
+
}
|
|
105
|
+
export interface UmlRoundTripReport {
|
|
106
|
+
notation: UmlNotation;
|
|
107
|
+
diagram: UmlDiagram;
|
|
108
|
+
ok: boolean;
|
|
109
|
+
/** Which published hash specification the two hashes follow (see references/hash-spec.md). */
|
|
110
|
+
hashSpec: HashSpec;
|
|
111
|
+
modelHash: string;
|
|
112
|
+
parsedHash: string;
|
|
113
|
+
diffs: string[];
|
|
114
|
+
warnings: string[];
|
|
115
|
+
}
|
|
116
|
+
export interface UmlReviewReport {
|
|
117
|
+
/** The review ran and produced this report. It does NOT mean the modelling passed — read `verdict`. */
|
|
118
|
+
ok: boolean;
|
|
119
|
+
ran: boolean;
|
|
120
|
+
verdict: Verdict;
|
|
121
|
+
verdictReason: string;
|
|
122
|
+
/** The versioned report contract this result follows. */
|
|
123
|
+
schema: ReportSchema;
|
|
124
|
+
source: 'model' | 'diagram' | 'model+diagram';
|
|
125
|
+
summary: {
|
|
126
|
+
errors: number;
|
|
127
|
+
warnings: number;
|
|
128
|
+
info: number;
|
|
129
|
+
states: number;
|
|
130
|
+
events: number;
|
|
131
|
+
transitions: number;
|
|
132
|
+
terminalStates: number;
|
|
133
|
+
reachableStates: number;
|
|
134
|
+
documentedStates: number;
|
|
135
|
+
};
|
|
136
|
+
findings: UmlFinding[];
|
|
137
|
+
roundTrip: UmlRoundTripReport | null;
|
|
138
|
+
/** Diagram display labels, when a diagram took part in the review. */
|
|
139
|
+
labels?: Record<string, string>;
|
|
140
|
+
/** Model parsed from the diagram, when a diagram was given (feed it to `logicprobe_verify`). */
|
|
141
|
+
model?: LogicModelV1;
|
|
142
|
+
/** Diagram rendered from the model, when only a model was given. */
|
|
143
|
+
primary?: string;
|
|
144
|
+
/** Paths of the `_`-prefixed metadata keys found in the supplied model, when it carried any. */
|
|
145
|
+
metadataKeys?: string[];
|
|
146
|
+
/** How much of the model the narrative documents; absent when there is no narrative. */
|
|
147
|
+
narrativeCoverage?: NarrativeCoverage;
|
|
148
|
+
/** Hashes of what was reviewed, in one place. */
|
|
149
|
+
hashes: {
|
|
150
|
+
hashSpec: HashSpec;
|
|
151
|
+
modelHash?: string;
|
|
152
|
+
parsedHash?: string;
|
|
153
|
+
};
|
|
154
|
+
/** Declarations the parser could not represent; a non-empty list fails the review. */
|
|
155
|
+
discardedConstructs?: DiscardedConstruct[];
|
|
156
|
+
/** Arrows whose endpoints came from a discarded construct. */
|
|
157
|
+
discardedEdges?: number;
|
|
158
|
+
warnings: string[];
|
|
159
|
+
nextSteps: string[];
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A UML front-end refusal. `code` lets the tool report *why* it refused instead of
|
|
163
|
+
* collapsing every refusal into a generic input error.
|
|
164
|
+
*/
|
|
165
|
+
export declare class UmlError extends Error {
|
|
166
|
+
readonly code: string;
|
|
167
|
+
constructor(message: string, code?: string);
|
|
168
|
+
}
|
|
169
|
+
/** Canonical guard text. Rendering wraps every composite node in parentheses, and the parser flattens same-operator chains, so render∘parse is the identity. */
|
|
170
|
+
export declare function guardText(node: GuardNode): string;
|
|
171
|
+
/**
|
|
172
|
+
* The `(notation, view)` cells this module can draw.
|
|
173
|
+
*
|
|
174
|
+
* PlantUML activity is the cell that does not exist: its activity syntax is a
|
|
175
|
+
* structured flowchart language, so a graph with merges or cycles needs a while/if
|
|
176
|
+
* reconstruction this module does not perform. Refusing is the honest outcome —
|
|
177
|
+
* quietly emitting a state diagram under an "activity" request would mislabel the
|
|
178
|
+
* model.
|
|
179
|
+
*/
|
|
180
|
+
export declare function assertUmlView(notation: UmlNotation, diagram: UmlDiagram): void;
|
|
181
|
+
/**
|
|
182
|
+
* Refuse, before any work, a request whose declared purpose the view cannot serve.
|
|
183
|
+
*
|
|
184
|
+
* Without an intent this changes nothing: the review still reports `UML019` when the
|
|
185
|
+
* fidelity check does not apply to the view it was given. With one, an impossible
|
|
186
|
+
* pairing is an error carrying a code, instead of a report about the wrong artifact —
|
|
187
|
+
* which is the failure this check exists to prevent.
|
|
188
|
+
*
|
|
189
|
+
* @param intent - the declared purpose, or `undefined` to leave the behaviour unchanged.
|
|
190
|
+
* @param action - which action is about to run.
|
|
191
|
+
* @param view - the requested `(notation, diagram)`, for the actions that have one.
|
|
192
|
+
*/
|
|
193
|
+
export declare function checkUmlIntent(intent: UmlIntent | undefined, action: UmlIntentAction, view?: {
|
|
194
|
+
notation: UmlNotation;
|
|
195
|
+
diagram: UmlDiagram;
|
|
196
|
+
}): void;
|
|
197
|
+
/**
|
|
198
|
+
* Render a LogicModelV1 as UML.
|
|
199
|
+
*
|
|
200
|
+
* Mermaid covers all three views; PlantUML covers state and sequence (see
|
|
201
|
+
* `assertUmlView` for why activity is refused).
|
|
202
|
+
*
|
|
203
|
+
* @param input - candidate LogicModelV1.
|
|
204
|
+
* @param notation - `mermaid` (default) or `plantuml`.
|
|
205
|
+
* @param diagram - `state` (default), `activity`, or `sequence`.
|
|
206
|
+
* @param maxSteps - cap on the sequence trace length.
|
|
207
|
+
* @param intent - what the diagram is for; a view that cannot serve it is refused first.
|
|
208
|
+
*/
|
|
209
|
+
export declare function renderUml(input: unknown, notation?: UmlNotation, diagram?: UmlDiagram, maxSteps?: number, intent?: UmlIntent): UmlRenderResult;
|
|
210
|
+
/** Parse a guard expression such as `(retry < 3 && armed == true)`. */
|
|
211
|
+
export declare function parseGuardText(text: string): GuardNode;
|
|
212
|
+
/** Parse a UML action clause such as `retry := retry + 1, armed := true`. */
|
|
213
|
+
export declare function parseUpdatesText(text: string, warnings: string[]): UpdateSpec[];
|
|
214
|
+
/**
|
|
215
|
+
* Findings a parse result carries on its own. A diagram from another family parses
|
|
216
|
+
* into something; without this finding that something is presented as a model of the
|
|
217
|
+
* file, which is a false guarantee of exactly the kind this plugin exists to prevent.
|
|
218
|
+
*/
|
|
219
|
+
export declare function parseFindings(parsed: UmlParseResult): UmlFinding[];
|
|
220
|
+
/** One accepted way of writing a state's meaning into a diagram label. */
|
|
221
|
+
export interface LabelForm {
|
|
222
|
+
form: string;
|
|
223
|
+
example: string;
|
|
224
|
+
note: string;
|
|
225
|
+
}
|
|
226
|
+
export interface LabelExplanation {
|
|
227
|
+
notation: UmlNotation;
|
|
228
|
+
/** The comment prefix a `logicprobe:` directive uses in this notation. */
|
|
229
|
+
directivePrefix: string;
|
|
230
|
+
directiveLines: Array<{
|
|
231
|
+
example: string;
|
|
232
|
+
meaning: string;
|
|
233
|
+
}>;
|
|
234
|
+
/** Accepted label spellings, in the order `documentedMeaning` accepts them. */
|
|
235
|
+
acceptedLabelForms: LabelForm[];
|
|
236
|
+
/** What the renderer itself writes, so a hand-edited diagram can match it. */
|
|
237
|
+
renderedForm: string;
|
|
238
|
+
ignoredLines: Array<{
|
|
239
|
+
pattern: string;
|
|
240
|
+
behaviour: string;
|
|
241
|
+
}>;
|
|
242
|
+
rules: string[];
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* What the front end expects of labels and comments, so "why does my hand-drawn diagram
|
|
246
|
+
* report label drift or ignored lines?" has a printed answer instead of a guess.
|
|
247
|
+
* `tests/uml/run.mjs` feeds every claim here back through the parser, so this text cannot
|
|
248
|
+
* drift away from the behaviour it describes.
|
|
249
|
+
*/
|
|
250
|
+
export declare function explainLabels(notation?: UmlNotation): LabelExplanation;
|
|
251
|
+
/**
|
|
252
|
+
* Parse a Mermaid or PlantUML diagram back into a LogicModelV1.
|
|
253
|
+
*
|
|
254
|
+
* State and activity diagrams carry the whole machine, so they parse into a
|
|
255
|
+
* complete model. Sequence diagrams do not: a trace shows the paths that were
|
|
256
|
+
* walked, not the branches that were not, so parsing one would silently prune
|
|
257
|
+
* the machine. That case is refused rather than approximated.
|
|
258
|
+
*
|
|
259
|
+
* @param text - diagram source.
|
|
260
|
+
* @param notation - `auto` (default) detects Mermaid vs PlantUML from the text.
|
|
261
|
+
*/
|
|
262
|
+
export declare function parseUml(text: string, notation?: UmlNotation | 'auto'): UmlParseResult;
|
|
263
|
+
/** Compare two machines by structure — the fidelity measure behind the round-trip check. */
|
|
264
|
+
export declare function diffModels(left: LogicModelV1, right: LogicModelV1): string[];
|
|
265
|
+
export interface UmlReviewOptions {
|
|
266
|
+
/** LogicModelV1 to review. Provide it, `diagram`, or both. */
|
|
267
|
+
model?: unknown;
|
|
268
|
+
/** Diagram text: reviewed on its own, or compared against `model` when both are given. */
|
|
269
|
+
diagram?: string;
|
|
270
|
+
notation?: UmlNotation | 'auto';
|
|
271
|
+
diagramKind?: UmlDiagram;
|
|
272
|
+
/** Render-and-reparse fidelity check (default true; only meaningful with a model). */
|
|
273
|
+
roundTrip?: boolean;
|
|
274
|
+
/** Cap on the sequence trace used for the fidelity check. */
|
|
275
|
+
maxSteps?: number;
|
|
276
|
+
/** What the review is for; a view that cannot serve it is refused before any work. */
|
|
277
|
+
intent?: UmlIntent;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Review a UML model of a code flow.
|
|
281
|
+
*
|
|
282
|
+
* Three inputs are possible and each answers a different question:
|
|
283
|
+
*
|
|
284
|
+
* - `model` only — "is this machine well-modelled?" The review checks the
|
|
285
|
+
* structure the diagram would draw, then renders and re-parses it to prove the
|
|
286
|
+
* diagram carries the machine faithfully (round trip).
|
|
287
|
+
* - `diagram` only — "what does this diagram actually say?" The diagram is parsed
|
|
288
|
+
* into a model, and that model is reviewed; nothing can be said about fidelity
|
|
289
|
+
* to a machine the caller did not provide.
|
|
290
|
+
* - both — "does this diagram match this model?" Any structural difference is a
|
|
291
|
+
* modelling defect and is reported both as round-trip diffs and as a finding.
|
|
292
|
+
*/
|
|
293
|
+
export declare function reviewUml(options: UmlReviewOptions): UmlReviewReport;
|