dsh-model-everything 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.en-US.md +332 -0
- package/README.md +332 -3
- package/cordis.patch.yml +20 -0
- package/examples/README.md +48 -0
- package/examples/control-dispatcher.json +113 -0
- package/examples/control-dispatcher.overbudget.json +113 -0
- package/examples/ecommerce-data-model.json +185 -0
- package/examples/order-state-machine.after.json +116 -0
- package/examples/order-state-machine.before.json +101 -0
- package/examples/user-migration.after.json +29 -0
- package/examples/user-migration.before.json +29 -0
- package/gate/locale/en.json +6 -0
- package/gate/locale/zh.json +6 -0
- package/gate/package.json +5 -0
- package/lib/baseline.js +249 -0
- package/lib/compose-tool.js +80 -0
- package/lib/concurrency-tool.js +40 -0
- package/lib/concurrency.js +206 -0
- package/lib/data-engine.js +1141 -0
- package/lib/data-tool.js +87 -0
- package/lib/design-engine.js +1149 -0
- package/lib/design-tool.js +63 -0
- package/lib/engine.js +4343 -0
- package/lib/export-tool.js +78 -0
- package/lib/exporters.js +434 -0
- package/lib/gate.js +274 -0
- package/lib/granularity.js +237 -0
- package/lib/index.js +237 -0
- package/lib/json-value.js +18 -0
- package/lib/model-file.js +48 -0
- package/lib/option-shape.js +62 -0
- package/lib/report-diff-tool.js +63 -0
- package/lib/report-view.js +433 -0
- package/lib/structure-tool.js +91 -0
- package/lib/structure.js +711 -0
- package/lib/tool.js +94 -0
- package/lib/types/baseline.d.ts +65 -0
- package/lib/types/compose-tool.d.ts +7 -0
- package/lib/types/concurrency-tool.d.ts +8 -0
- package/lib/types/concurrency.d.ts +37 -0
- package/lib/types/data-engine.d.ts +211 -0
- package/lib/types/data-tool.d.ts +10 -0
- package/lib/types/design-engine.d.ts +215 -0
- package/lib/types/design-tool.d.ts +11 -0
- package/lib/types/engine.d.ts +494 -0
- package/lib/types/export-tool.d.ts +7 -0
- package/lib/types/exporters.d.ts +37 -0
- package/lib/types/gate.d.ts +91 -0
- package/lib/types/granularity.d.ts +106 -0
- package/lib/types/index.d.ts +45 -0
- package/lib/types/json-value.d.ts +21 -0
- package/lib/types/model-file.d.ts +7 -0
- package/lib/types/option-shape.d.ts +22 -0
- package/lib/types/report-diff-tool.d.ts +8 -0
- package/lib/types/report-view.d.ts +50 -0
- package/lib/types/structure-tool.d.ts +10 -0
- package/lib/types/structure.d.ts +152 -0
- package/lib/types/tool.d.ts +11 -0
- package/lib/types/uml-communication.d.ts +109 -0
- package/lib/types/uml-composite.d.ts +107 -0
- package/lib/types/uml-interaction-overview.d.ts +91 -0
- package/lib/types/uml-profile.d.ts +112 -0
- package/lib/types/uml-structure.d.ts +53 -0
- package/lib/types/uml-syntax.d.ts +296 -0
- package/lib/types/uml-timing.d.ts +152 -0
- package/lib/types/uml-tool.d.ts +12 -0
- package/lib/types/uml-usecase.d.ts +58 -0
- package/lib/types/uml.d.ts +303 -0
- package/lib/uml-communication.js +353 -0
- package/lib/uml-composite.js +442 -0
- package/lib/uml-interaction-overview.js +277 -0
- package/lib/uml-profile.js +373 -0
- package/lib/uml-structure.js +306 -0
- package/lib/uml-syntax.js +545 -0
- package/lib/uml-timing.js +974 -0
- package/lib/uml-tool.js +213 -0
- package/lib/uml-usecase.js +532 -0
- package/lib/uml.js +2110 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +128 -6
- package/skills/model-everything/SKILL.md +450 -0
- package/skills/model-everything/references/dsh-model-schema.md +437 -0
- package/skills/model-everything/references/gap-routing-guide.md +42 -0
- package/skills/model-everything/references/hash-spec.md +152 -0
- package/skills/model-everything/references/logic-verification-guide.md +422 -0
- package/skills/model-everything-datamodel/SKILL.md +130 -0
- package/skills/model-everything-datamodel/references/data-model-guide.md +84 -0
- package/skills/model-everything-datamodel/references/data-model-schema.md +128 -0
- package/skills/model-everything-design/SKILL.md +115 -0
- package/skills/model-everything-interleaving/SKILL.md +63 -0
- package/skills/model-everything-interleaving/SKILL.zh-CN.md +60 -0
- package/skills/model-everything-interleaving/references/concurrency-risk-guide.md +63 -0
- package/skills/model-everything-report-reading/SKILL.md +137 -0
- package/skills/model-everything-report-reading/references/reading-a-report.md +166 -0
- package/skills/model-everything-report-reading/references/reading-a-report.mmd +59 -0
- package/skills/model-everything-structure/SKILL.md +96 -0
- package/skills/model-everything-structure/references/structure-review-guide.md +201 -0
- package/skills/model-everything-uml/SKILL.md +60 -0
- package/skills/model-everything-uml/references/uml-modeling-guide.md +551 -0
- package/src/baseline.ts +288 -0
- package/src/compose-tool.ts +82 -0
- package/src/concurrency-tool.ts +44 -0
- package/src/concurrency.ts +254 -0
- package/src/data-engine.ts +1208 -0
- package/src/data-tool.ts +91 -0
- package/src/design-engine.ts +1263 -0
- package/src/design-tool.ts +68 -0
- package/src/engine.ts +4564 -0
- package/src/export-tool.ts +81 -0
- package/src/exporters.ts +399 -0
- package/src/gate.ts +330 -0
- package/src/granularity.ts +312 -0
- package/src/index.ts +289 -0
- package/src/json-value.ts +20 -0
- package/src/model-file.ts +49 -0
- package/src/option-shape.ts +64 -0
- package/src/report-diff-tool.ts +67 -0
- package/src/report-view.ts +483 -0
- package/src/structure-tool.ts +93 -0
- package/src/structure.ts +786 -0
- package/src/tool.ts +103 -0
- package/src/uml-communication.ts +428 -0
- package/src/uml-composite.ts +520 -0
- package/src/uml-interaction-overview.ts +321 -0
- package/src/uml-profile.ts +439 -0
- package/src/uml-structure.ts +317 -0
- package/src/uml-syntax.ts +764 -0
- package/src/uml-timing.ts +1106 -0
- package/src/uml-tool.ts +230 -0
- package/src/uml-usecase.ts +566 -0
- package/src/uml.ts +2139 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-granularity structure review: one architecture, several levels of detail.
|
|
3
|
+
*
|
|
4
|
+
* A module diagram and the repository-wide diagram it belongs to are two views of one
|
|
5
|
+
* fact, and nothing keeps them in step — the child grows a dependency the parent never
|
|
6
|
+
* had, or the parent keeps an arrow the child quietly stopped drawing. This module
|
|
7
|
+
* checks that a child diagram is a **refinement** of its declared parent:
|
|
8
|
+
*
|
|
9
|
+
* - every dependency the child draws between two nodes the parent also has must exist in
|
|
10
|
+
* the parent (nothing appears out of nowhere);
|
|
11
|
+
* - an edge the parent draws and the child does not must be *expanded* in the child, i.e.
|
|
12
|
+
* a child path must connect the same two ends;
|
|
13
|
+
* - the declared parent relation must be a forest, not a cycle.
|
|
14
|
+
*
|
|
15
|
+
* Every per-diagram structural check still runs, and its findings are tagged with the
|
|
16
|
+
* diagram they came from (`file`), so one report can carry several diagrams without the
|
|
17
|
+
* findings becoming anonymous.
|
|
18
|
+
*
|
|
19
|
+
* @module this plugin-granularity
|
|
20
|
+
*/
|
|
21
|
+
import { type Finding, type ReportSchema, type Verdict, type VerdictSummary } from './engine.js';
|
|
22
|
+
import { type StructureNotation } from './structure.js';
|
|
23
|
+
export interface GranularityDiagram {
|
|
24
|
+
/** Name of this level, e.g. `L2/motion` or `repo`. Referenced by a child's `parent`. */
|
|
25
|
+
name: string;
|
|
26
|
+
/** Diagram source text. */
|
|
27
|
+
diagram: string;
|
|
28
|
+
/** Name of the diagram this one refines; absent for a root. */
|
|
29
|
+
parent?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface GranularityOptions {
|
|
32
|
+
diagrams: GranularityDiagram[];
|
|
33
|
+
notation?: 'auto' | StructureNotation;
|
|
34
|
+
/** Optional dependency matrix, applied to every diagram. */
|
|
35
|
+
matrix?: unknown;
|
|
36
|
+
}
|
|
37
|
+
export interface GranularityEdgeRef {
|
|
38
|
+
from: string;
|
|
39
|
+
to: string;
|
|
40
|
+
line?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface GranularityPairSummary {
|
|
43
|
+
parent: string;
|
|
44
|
+
child: string;
|
|
45
|
+
parentNodes: number;
|
|
46
|
+
childNodes: number;
|
|
47
|
+
parentEdges: number;
|
|
48
|
+
childEdges: number;
|
|
49
|
+
/** Child edges whose endpoints both exist in the parent and which the parent also draws. */
|
|
50
|
+
inheritedEdges: number;
|
|
51
|
+
/** Child edges with at least one endpoint the parent does not have (the refinement's own detail). */
|
|
52
|
+
newEdges: number;
|
|
53
|
+
/** Parent edges with no direct child counterpart, but a child path connects the same ends. */
|
|
54
|
+
expandedEdges: GranularityEdgeRef[];
|
|
55
|
+
/** Parent edges with no direct counterpart and no connecting path — the refinement lost them. */
|
|
56
|
+
missingEdges: GranularityEdgeRef[];
|
|
57
|
+
/** Child edges between two parent nodes that the parent does not draw — invented dependencies. */
|
|
58
|
+
inventedEdges: GranularityEdgeRef[];
|
|
59
|
+
}
|
|
60
|
+
export interface GranularityDiagramSummary {
|
|
61
|
+
name: string;
|
|
62
|
+
parent?: string;
|
|
63
|
+
notation: StructureNotation;
|
|
64
|
+
nodes: number;
|
|
65
|
+
edges: number;
|
|
66
|
+
verdict: Verdict;
|
|
67
|
+
findings: number;
|
|
68
|
+
}
|
|
69
|
+
export interface GranularityReport {
|
|
70
|
+
ok: boolean;
|
|
71
|
+
ran: boolean;
|
|
72
|
+
verdict: Verdict;
|
|
73
|
+
verdictReason: string;
|
|
74
|
+
schema: ReportSchema;
|
|
75
|
+
diagrams: GranularityDiagramSummary[];
|
|
76
|
+
pairs: GranularityPairSummary[];
|
|
77
|
+
findings: Finding[];
|
|
78
|
+
summary: {
|
|
79
|
+
diagrams: number;
|
|
80
|
+
roots: number;
|
|
81
|
+
pairs: number;
|
|
82
|
+
nodes: number;
|
|
83
|
+
edges: number;
|
|
84
|
+
inventedEdges: number;
|
|
85
|
+
missingEdges: number;
|
|
86
|
+
expandedEdges: number;
|
|
87
|
+
errors: number;
|
|
88
|
+
warnings: number;
|
|
89
|
+
};
|
|
90
|
+
hashes: {
|
|
91
|
+
diagrams: Array<{
|
|
92
|
+
name: string;
|
|
93
|
+
hash: string;
|
|
94
|
+
}>;
|
|
95
|
+
};
|
|
96
|
+
warnings: string[];
|
|
97
|
+
nextSteps: string[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Review a set of structure diagrams with declared parent relations. Per-diagram
|
|
101
|
+
* structural checks run first; the cross-diagram refinement checks follow.
|
|
102
|
+
*/
|
|
103
|
+
export declare function reviewGranularity(options: GranularityOptions): GranularityReport;
|
|
104
|
+
/** Deterministic JSON of a granularity report's pair table, for a stable summary line. */
|
|
105
|
+
export declare function granularityDigest(pairs: GranularityPairSummary[]): string;
|
|
106
|
+
export type { VerdictSummary };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-model-everything — DeepSeek Harness native plugin for models and diagrams.
|
|
3
|
+
*
|
|
4
|
+
* It ships a skill set (one entry skill plus a skill per domain) and the tools that do
|
|
5
|
+
* the work: UML diagrams render, parse and review; state machines, protocols and composed
|
|
6
|
+
* machines are checked by running them; data models and migrations are checked by the same
|
|
7
|
+
* doctrine; concurrency claims are mined and routed; a verified model is exported to an
|
|
8
|
+
* external checker; a structure diagram is audited as a dependency graph; two reports are
|
|
9
|
+
* diffed against each other.
|
|
10
|
+
*
|
|
11
|
+
* Every tool carries its own description and every report says what it proves, so a model
|
|
12
|
+
* reaches for one the way it reaches for any other tool: by reading what it says it does.
|
|
13
|
+
* The plugin writes nothing into a session.
|
|
14
|
+
*
|
|
15
|
+
* The skills ship in this package's `skills/` directory and are registered at apply time
|
|
16
|
+
* into dsh's `ctx.skills` registry through the standard filesystem provider, so they appear
|
|
17
|
+
* in every session catalog without a manual copy step.
|
|
18
|
+
*
|
|
19
|
+
* Method, doctrine and per-domain detail live in the skills and their references, not here.
|
|
20
|
+
*
|
|
21
|
+
* @module dsh-model-everything
|
|
22
|
+
*/
|
|
23
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
24
|
+
import z from '@deepseek-ai/schemastery';
|
|
25
|
+
export declare const name = "dsh-model-everything";
|
|
26
|
+
export declare const inject: string[];
|
|
27
|
+
export type InteractionMode = 'ask' | 'auto' | 'follow-approval';
|
|
28
|
+
export interface Config {
|
|
29
|
+
/**
|
|
30
|
+
* How an offer to run a tool resolves: `ask` and `auto` are fixed, while `follow-approval`
|
|
31
|
+
* reads the session's approval policy per call. `resolveInteraction` is its only reader.
|
|
32
|
+
*
|
|
33
|
+
* There is deliberately no on/off key here. A row is switched off by the loader row that
|
|
34
|
+
* mounts it (`disabled`, or the plugin manager), which removes the tools and the skills
|
|
35
|
+
* together; a key that turned the tools off while the skills stayed would leave every skill
|
|
36
|
+
* naming a tool that is not there, which is worse than having no skill at all.
|
|
37
|
+
*/
|
|
38
|
+
interaction: InteractionMode;
|
|
39
|
+
}
|
|
40
|
+
export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
41
|
+
interaction: z<"ask" | "auto" | "follow-approval", "ask" | "auto" | "follow-approval", "defined">;
|
|
42
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
43
|
+
interaction: z<"ask" | "auto" | "follow-approval", "ask" | "auto" | "follow-approval", "defined">;
|
|
44
|
+
}>>, "plain">;
|
|
45
|
+
export declare function apply(ctx: Context, config: Config): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural mirror of the JSON value union the dsh tool registry accepts.
|
|
3
|
+
*
|
|
4
|
+
* `@deepseek-ai/dsh-tools` exported this type through the 0.1.x line and stopped
|
|
5
|
+
* exporting it in 0.2.x, where the same type now lives in
|
|
6
|
+
* `@deepseek-ai/dsh-util-values`. This package declares peer support for both
|
|
7
|
+
* lines, so it cannot import the type from either one without breaking the other
|
|
8
|
+
* build. Declaring the one-line union here keeps `npm run typecheck` green against
|
|
9
|
+
* both, and it costs nothing at runtime: every use is a type-only cast on a value
|
|
10
|
+
* this package already produced.
|
|
11
|
+
*
|
|
12
|
+
* Keep it structurally identical to the official type. A cast through `unknown` to
|
|
13
|
+
* this alias is only a way to satisfy `defineTool`'s return-type constraint; if the
|
|
14
|
+
* official union ever widens, this alias must widen with it.
|
|
15
|
+
*
|
|
16
|
+
* @module this plugin-json-value
|
|
17
|
+
*/
|
|
18
|
+
/** JSON-serializable value: null, boolean, number, string, or an array/object of those. */
|
|
19
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
20
|
+
[key: string]: JsonValue;
|
|
21
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Read and parse one JSON file. Formatting is irrelevant: whitespace, BOM and pretty printing all parse. */
|
|
2
|
+
export declare function readJsonFile(path: unknown, option: string, code: string): unknown;
|
|
3
|
+
/**
|
|
4
|
+
* Exactly one of the inline value and the file path. Both is ambiguous, neither is a missing
|
|
5
|
+
* argument, and each gets its own sentence so the caller knows which one to drop.
|
|
6
|
+
*/
|
|
7
|
+
export declare function oneOf(value: unknown, path: unknown, inlineName: string, pathName: string, code: string): unknown;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Option shapes at the tool boundary.
|
|
3
|
+
*
|
|
4
|
+
* A tool declares `type: 'json'` for an option, which accepts any JSON value, and the engine then reads
|
|
5
|
+
* it as the type it needs. A string where an array was expected threw `machinesInput.forEach is not a
|
|
6
|
+
* function` and `(options.migrationMappings ?? []).map is not a function` - raw TypeErrors with no code,
|
|
7
|
+
* which a caller cannot route on and which say nothing about which option was wrong.
|
|
8
|
+
*
|
|
9
|
+
* The suite pinned those as known gaps. This closes them the way the rest of the plugin reports a
|
|
10
|
+
* refusal: a code naming the family, and a message naming the option.
|
|
11
|
+
*/
|
|
12
|
+
/** A refusal the caller can route on: the domain's code, and what arrived. */
|
|
13
|
+
export declare class OptionShapeError extends Error {
|
|
14
|
+
readonly errorCode: string;
|
|
15
|
+
constructor(errorCode: string, message: string);
|
|
16
|
+
}
|
|
17
|
+
/** An option the engine reads with `.map`: a string or a number is not one. */
|
|
18
|
+
export declare function requireArrayOption(value: unknown, option: string, errorCode: string): void;
|
|
19
|
+
/** An option the engine reads with `Object.entries`: a string has entries, and they are not the ones meant. */
|
|
20
|
+
export declare function requireObjectOption(value: unknown, option: string, errorCode: string): void;
|
|
21
|
+
/** The refusal a tool returns for a shape it could not read. */
|
|
22
|
+
export declare function optionRefusal(error: unknown, errorCode: string): Record<string, unknown>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const REPORT_DIFF_TOOL_NAME = "report_diff";
|
|
2
|
+
/**
|
|
3
|
+
* Model-visible DSH tool that compares two reports of the same family — the accepted
|
|
4
|
+
* "violations must not increase" acceptance criterion, computed instead of eyeballed.
|
|
5
|
+
* A finding's identity is its check + code + machine-readable locator, so a reworded
|
|
6
|
+
* message reads as `changed`, and two runs over the same input add nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare const reportDiffTool: import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Rendering limits. Defaults are the shipped behaviour; tests pin them. */
|
|
2
|
+
export interface ReportViewOptions {
|
|
3
|
+
/** Maximum finding lines per check. Error findings are never dropped, only warnings are capped. */
|
|
4
|
+
maxFindingsPerCheck?: number;
|
|
5
|
+
/** Evidence is inlined for `error` findings only, truncated to this many characters. */
|
|
6
|
+
maxEvidenceChars?: number;
|
|
7
|
+
/** Include passing checks' bodies (default false: a passing check carries no actionable finding). */
|
|
8
|
+
includePassing?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Print the whole structured report instead of the body. This is the escape hatch for a
|
|
11
|
+
* caller that must hand the report to another tool verbatim — `report_diff`
|
|
12
|
+
* matches on check + code + evidence, so a body cannot stand in for the object.
|
|
13
|
+
*/
|
|
14
|
+
full?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Print one check in full: every finding, evidence included, without the per-check budget the
|
|
17
|
+
* digest applies. The digest truncates a check's warnings and tells the reader to ask for it by
|
|
18
|
+
* id; before this option existed that sentence named something the tools could not do, and the
|
|
19
|
+
* only way to see the lines was `full`, which returns the whole structured report.
|
|
20
|
+
*/
|
|
21
|
+
check?: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
type Record_ = Record<string, unknown>;
|
|
24
|
+
/** One normalized finding. `evidence` is kept because a finding's identity depends on it. */
|
|
25
|
+
export interface ViewFinding {
|
|
26
|
+
code: string;
|
|
27
|
+
severity: string;
|
|
28
|
+
message: string;
|
|
29
|
+
evidence?: Record_;
|
|
30
|
+
file?: string;
|
|
31
|
+
line?: number;
|
|
32
|
+
check?: string | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Normalize one raw finding. Unknown fields are ignored; a missing message renders as the code. */
|
|
35
|
+
export declare function toViewFinding(value: unknown, check?: string): ViewFinding;
|
|
36
|
+
/**
|
|
37
|
+
* The fact a finding states, as a comparable key. The verify/datamodel families report the
|
|
38
|
+
* same (state, event) fact from more than one check, so the key ignores which check said it;
|
|
39
|
+
* anything else falls back to code + message.
|
|
40
|
+
*/
|
|
41
|
+
export declare function factKey(finding: ViewFinding): string;
|
|
42
|
+
/**
|
|
43
|
+
* Render any this plugin result as the text a model reads.
|
|
44
|
+
*
|
|
45
|
+
* Order of recognition: a `checks[]` report, a flat `findings[]` report, a baseline delta,
|
|
46
|
+
* a payload result (`diagram`/`primary`), and finally compact JSON so an unrecognized shape
|
|
47
|
+
* is still readable rather than silently empty.
|
|
48
|
+
*/
|
|
49
|
+
export declare function renderReportText(value: unknown, options?: ReportViewOptions): string;
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const STRUCTURE_TOOL_NAME = "uml_structure_verify";
|
|
2
|
+
/**
|
|
3
|
+
* Model-visible DSH tool that audits a *structure* diagram — components, packages,
|
|
4
|
+
* classes, deployment nodes and the dependency arrows between them — against an
|
|
5
|
+
* optional dependency matrix. A structure diagram is not a state machine: this tool
|
|
6
|
+
* reads the graph the diagram actually draws, instead of refusing it (which is what
|
|
7
|
+
* `uml action=parse` does) or pretending the arrows are state transitions
|
|
8
|
+
* (which is what a false `ok` used to hide).
|
|
9
|
+
*/
|
|
10
|
+
export declare const umlStructureTool: import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structure-diagram review: a dependency graph is not a state machine.
|
|
3
|
+
*
|
|
4
|
+
* The state-machine front end (`uml.ts`) reads a component, package, class or
|
|
5
|
+
* deployment diagram as a *by-product* and says so (`UML_NOT_A_STATE_DIAGRAM`).
|
|
6
|
+
* This module reads the same text as what it actually is — a directed graph of
|
|
7
|
+
* nodes and dependency edges — and audits it against a declared dependency matrix.
|
|
8
|
+
*
|
|
9
|
+
* The checks are the structural ones a reader performs by eye and gets wrong:
|
|
10
|
+
* an isolated node nobody notices, an arrow whose endpoint was never declared, a
|
|
11
|
+
* dependency cycle, an edge that violates the allowed-dependency matrix, a child
|
|
12
|
+
* depending on its parent, and an edge the matrix says must exist but the diagram
|
|
13
|
+
* does not draw. Every finding names the rule id it hit, so the diagram and the
|
|
14
|
+
* source-side checker can be reconciled rule by rule.
|
|
15
|
+
*
|
|
16
|
+
* @module model-everything-structure
|
|
17
|
+
*/
|
|
18
|
+
import { type Finding, type ReportSchema, type Verdict, type VerdictSummary } from './engine.js';
|
|
19
|
+
export type StructureNotation = 'plantuml' | 'mermaid';
|
|
20
|
+
/** What a node declares itself to be. Containers hold other nodes; they are not dependencies. */
|
|
21
|
+
export type StructureNodeKind = 'component' | 'class' | 'interface' | 'actor' | 'database' | 'node' | 'package' | 'rectangle' | 'cloud' | 'queue' | 'unknown';
|
|
22
|
+
export interface StructureNode {
|
|
23
|
+
id: string;
|
|
24
|
+
/** Display label when the declaration carried one (`component "Order Service" as SVC`). */
|
|
25
|
+
label?: string;
|
|
26
|
+
kind: StructureNodeKind;
|
|
27
|
+
/** True when the node is a container (package/rectangle/frame): it owns members and carries no dependency of its own. */
|
|
28
|
+
container: boolean;
|
|
29
|
+
/** 1-based line of the declaration. Absent when the node was only ever named by an edge. */
|
|
30
|
+
line?: number;
|
|
31
|
+
declared: boolean;
|
|
32
|
+
/** Container id this node was declared inside, if any. */
|
|
33
|
+
parent?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface StructureEdge {
|
|
36
|
+
from: string;
|
|
37
|
+
to: string;
|
|
38
|
+
/** Arrow label, e.g. `read` in `PAY --> DRV : read`. */
|
|
39
|
+
label?: string;
|
|
40
|
+
line: number;
|
|
41
|
+
}
|
|
42
|
+
export interface StructureGraph {
|
|
43
|
+
notation: StructureNotation;
|
|
44
|
+
nodes: StructureNode[];
|
|
45
|
+
edges: StructureEdge[];
|
|
46
|
+
warnings: string[];
|
|
47
|
+
}
|
|
48
|
+
/** One dependency rule from the matrix document. */
|
|
49
|
+
export interface StructureRule {
|
|
50
|
+
id: string;
|
|
51
|
+
/** Node id or glob the rule applies to; absent = applies to every source. */
|
|
52
|
+
source?: string;
|
|
53
|
+
/** Permitted targets (glob or node id). Winning an allow match permits the edge. */
|
|
54
|
+
allow?: string[];
|
|
55
|
+
/** Forbidden targets. Deny always wins over allow. */
|
|
56
|
+
deny?: string[];
|
|
57
|
+
/** When true, at least one edge matching source→targets must exist (UML025). */
|
|
58
|
+
require?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface StructureLayer {
|
|
61
|
+
name: string;
|
|
62
|
+
/** Node ids or globs that belong to this layer. */
|
|
63
|
+
members: string[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The dependency matrix: the single source of truth a diagram is checked against.
|
|
67
|
+
* `default` decides the fate of an edge no rule mentions (`allow` = only explicit
|
|
68
|
+
* rules judge, `deny` = anything unlisted is a violation).
|
|
69
|
+
*/
|
|
70
|
+
export interface DependencyMatrix {
|
|
71
|
+
rules?: StructureRule[];
|
|
72
|
+
layers?: StructureLayer[];
|
|
73
|
+
default?: 'allow' | 'deny';
|
|
74
|
+
}
|
|
75
|
+
export interface StructureEdgeVerdict {
|
|
76
|
+
from: string;
|
|
77
|
+
to: string;
|
|
78
|
+
line: number;
|
|
79
|
+
/** Rule ids whose `source` matched this edge, whether they allowed or denied it. */
|
|
80
|
+
matchedRules: string[];
|
|
81
|
+
allowed: boolean;
|
|
82
|
+
/** `allow` (a rule permitted it), `default` (nothing judged it), `deny` (a rule forbade it), `unlisted` (default=deny and no rule matched). */
|
|
83
|
+
basis: 'allow' | 'default' | 'deny' | 'unlisted';
|
|
84
|
+
}
|
|
85
|
+
export interface StructureSummary {
|
|
86
|
+
nodes: number;
|
|
87
|
+
edges: number;
|
|
88
|
+
containers: number;
|
|
89
|
+
isolated: number;
|
|
90
|
+
dangling: number;
|
|
91
|
+
cycles: number;
|
|
92
|
+
disallowedEdges: number;
|
|
93
|
+
layerViolations: number;
|
|
94
|
+
missingExpectedEdges: number;
|
|
95
|
+
errors: number;
|
|
96
|
+
warnings: number;
|
|
97
|
+
rules: number;
|
|
98
|
+
}
|
|
99
|
+
export interface StructureReport {
|
|
100
|
+
/** The tool ran and produced this report; read `verdict` for the outcome. */
|
|
101
|
+
ok: boolean;
|
|
102
|
+
ran: boolean;
|
|
103
|
+
verdict: Verdict;
|
|
104
|
+
verdictReason: string;
|
|
105
|
+
/** The versioned report contract this result follows. */
|
|
106
|
+
schema: ReportSchema;
|
|
107
|
+
notation: StructureNotation;
|
|
108
|
+
graph: StructureGraph;
|
|
109
|
+
/** Per-edge matrix verdict, present only when a matrix was supplied. */
|
|
110
|
+
edgeVerdicts?: StructureEdgeVerdict[];
|
|
111
|
+
findings: Finding[];
|
|
112
|
+
summary: StructureSummary;
|
|
113
|
+
/** Hashes of the inputs this report is about: the diagram text, and the matrix when one was supplied. */
|
|
114
|
+
hashes: {
|
|
115
|
+
diagram: string;
|
|
116
|
+
matrix?: string;
|
|
117
|
+
};
|
|
118
|
+
warnings: string[];
|
|
119
|
+
nextSteps: string[];
|
|
120
|
+
}
|
|
121
|
+
/** A finding code in the structure family; the numbers continue the UML0xx series after UML019. */
|
|
122
|
+
export type StructureFindingCode = 'UML020_ISOLATED_NODE' | 'UML021_DANGLING_REFERENCE' | 'UML022_CYCLE' | 'UML023_DISALLOWED_EDGE' | 'UML024_LAYER_VIOLATION' | 'UML025_MISSING_EXPECTED_EDGE' | 'UML026_NO_NODES';
|
|
123
|
+
/**
|
|
124
|
+
* Parse a structure diagram (PlantUML component/package/class/deployment, Mermaid
|
|
125
|
+
* class diagram) into nodes and dependency edges.
|
|
126
|
+
*
|
|
127
|
+
* A structure diagram is *not* refused here: refusing is the state-machine front
|
|
128
|
+
* end's job (`parseUml`). This parser is the honest reading of the same text.
|
|
129
|
+
*/
|
|
130
|
+
export declare function parseStructure(text: string, notation?: 'auto' | StructureNotation): StructureGraph;
|
|
131
|
+
/** `*` matches any run of characters, `?` exactly one. Ids keep their own punctuation. */
|
|
132
|
+
export declare function globMatches(pattern: string, value: string): boolean;
|
|
133
|
+
export declare function validateMatrix(input: unknown): {
|
|
134
|
+
ok: true;
|
|
135
|
+
matrix: DependencyMatrix;
|
|
136
|
+
} | {
|
|
137
|
+
ok: false;
|
|
138
|
+
errors: string[];
|
|
139
|
+
};
|
|
140
|
+
/** Shortest directed cycle through the graph, as a node path with the start repeated. */
|
|
141
|
+
export declare function shortestCycle(nodes: string[], edges: StructureEdge[]): string[] | undefined;
|
|
142
|
+
export interface StructureReviewOptions {
|
|
143
|
+
/** Diagram text to review. */
|
|
144
|
+
diagram: string;
|
|
145
|
+
notation?: 'auto' | StructureNotation;
|
|
146
|
+
/** Dependency matrix: allowed/denied edges, layers, required edges. */
|
|
147
|
+
matrix?: unknown;
|
|
148
|
+
}
|
|
149
|
+
export declare function reviewStructure(options: StructureReviewOptions): StructureReport;
|
|
150
|
+
/** The finding codes this module can emit, for documentation and tests. */
|
|
151
|
+
export declare const STRUCTURE_FINDING_CODES: readonly StructureFindingCode[];
|
|
152
|
+
export type { VerdictSummary };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const MODEL_VERIFY_TOOL_NAME = "model_verify";
|
|
2
|
+
/**
|
|
3
|
+
* Model-visible DSH tool wrapping the bundled TypeScript verification engine.
|
|
4
|
+
* The model passes a LogicModelV1 object; the engine validates it and returns
|
|
5
|
+
* the 22-check report (S1-S8 structural, A1-A14), or a 26-check
|
|
6
|
+
* report when beforeModel is supplied (D1 behavioral preservation, D2
|
|
7
|
+
* invariant continuity, D3 regression delta, D4 deadlock/liveness regression).
|
|
8
|
+
* This is the dsh-native path: the model is built and run here, with no
|
|
9
|
+
* template to fill in by hand.
|
|
10
|
+
*/
|
|
11
|
+
export declare const modelVerifyTool: import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The communication diagram module.
|
|
3
|
+
*
|
|
4
|
+
* A communication diagram is a set of lifelines joined by links, with numbered messages
|
|
5
|
+
* travelling along the links. PlantUML has no communication-diagram type - the page is a
|
|
6
|
+
* 404 and the navigation lists none - but the drawing is expressible with the object
|
|
7
|
+
* diagram's vocabulary: objects for the lifelines, arrows for the links, and the sequence
|
|
8
|
+
* number in the arrow's label.
|
|
9
|
+
*
|
|
10
|
+
* That last point is why this family is *not* refused. An earlier version of the family
|
|
11
|
+
* table said neither notation spells the numbering or the link roles, so a parse would
|
|
12
|
+
* invent an order. The numbering is spelled - `C --> O : 1: create` carries both the link
|
|
13
|
+
* and the order - and the renderer writes it back the same way. What the notation cannot
|
|
14
|
+
* say is the *nesting* that a number like `1.1` implies (which message is a nested call of
|
|
15
|
+
* which), so the model keeps the number as the string the diagram wrote and makes no claim
|
|
16
|
+
* about the tree it suggests.
|
|
17
|
+
*
|
|
18
|
+
* @module model-everything-uml-communication
|
|
19
|
+
*/
|
|
20
|
+
import { type UmlNotation, type UmlFamilyModule, type UmlFamilyParse, type UmlFamilyRender, type UmlFamilyFinding } from './uml-syntax.js';
|
|
21
|
+
/**
|
|
22
|
+
* A message number as the diagram wrote it: `1`, `2`, `1.1`, `3a`.
|
|
23
|
+
*
|
|
24
|
+
* It is a string, not a number, and the module does not parse its structure. `1.1` reads as
|
|
25
|
+
* a nested call in UML, but that is a claim about the design; the diagram only draws a
|
|
26
|
+
* label, and inventing the call tree from a dotted string would be the sort of guess this
|
|
27
|
+
* plugin refuses to make elsewhere.
|
|
28
|
+
*/
|
|
29
|
+
export type CommunicationSequence = string;
|
|
30
|
+
export interface CommunicationLifeline {
|
|
31
|
+
id: string;
|
|
32
|
+
label?: string;
|
|
33
|
+
/** `:Name` in the drawing is a classifier, `Name` alone is an instance. */
|
|
34
|
+
classifier?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface CommunicationLink {
|
|
37
|
+
from: string;
|
|
38
|
+
to: string;
|
|
39
|
+
label?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface CommunicationMessage {
|
|
42
|
+
sequence: CommunicationSequence;
|
|
43
|
+
from: string;
|
|
44
|
+
to: string;
|
|
45
|
+
/** The message name and arguments, without the number. */
|
|
46
|
+
label?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A communication diagram as a model.
|
|
50
|
+
*
|
|
51
|
+
* `links` is what the diagram draws between lifelines; a message travels along one. The two
|
|
52
|
+
* are kept apart because a link with no message is a real thing to notice, and so is a
|
|
53
|
+
* message with no link to carry it.
|
|
54
|
+
*/
|
|
55
|
+
export interface CommunicationModelV1 {
|
|
56
|
+
schemaVersion: 1;
|
|
57
|
+
lifelines: CommunicationLifeline[];
|
|
58
|
+
links: CommunicationLink[];
|
|
59
|
+
messages: CommunicationMessage[];
|
|
60
|
+
/** Ids a message or link named that no declaration introduced. */
|
|
61
|
+
undeclared?: string[];
|
|
62
|
+
narrative?: {
|
|
63
|
+
lifelines?: Record<string, string>;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validate a candidate model and normalize it.
|
|
68
|
+
*
|
|
69
|
+
* A sequence number must be unique: two messages with the same number is not a style
|
|
70
|
+
* question, it is a diagram whose order has two answers.
|
|
71
|
+
*/
|
|
72
|
+
export declare function validateCommunicationModel(input: unknown): CommunicationModelV1;
|
|
73
|
+
/**
|
|
74
|
+
* Render a communication diagram as PlantUML.
|
|
75
|
+
*
|
|
76
|
+
* Objects for the lifelines, arrows for the links, and one arrow per message with its
|
|
77
|
+
* number in the label. A message whose lifelines have no declared link is still drawn -
|
|
78
|
+
* the notation allows it - and the review reports it rather than the renderer hiding it.
|
|
79
|
+
*
|
|
80
|
+
* @param input - candidate `CommunicationModelV1`.
|
|
81
|
+
* @param notation - only `plantuml` draws this family.
|
|
82
|
+
*/
|
|
83
|
+
export declare function renderCommunication(input: unknown, notation: UmlNotation): UmlFamilyRender;
|
|
84
|
+
/**
|
|
85
|
+
* Read a communication diagram back into a model.
|
|
86
|
+
*
|
|
87
|
+
* Hand-written text is read the same way the renderer writes it: `object` declarations are
|
|
88
|
+
* the lifelines, `--` arrows are the links, and an arrow whose label starts with a number
|
|
89
|
+
* and a colon is a message. A line that is neither is reported in `discardedConstructs`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function parseCommunication(text: string, notation: UmlNotation): UmlFamilyParse<CommunicationModelV1>;
|
|
92
|
+
export type CommunicationFindingCode = 'UML063_COMMUNICATION_NO_LIFELINES' | 'UML064_COMMUNICATION_LIFELINE_UNLINKED' | 'UML065_COMMUNICATION_MESSAGE_WITHOUT_LINK' | 'UML066_COMMUNICATION_UNDECLARED_ENDPOINT' | 'UML067_COMMUNICATION_SEQUENCE_DUPLICATE' | 'UML068_COMMUNICATION_UNDOCUMENTED';
|
|
93
|
+
export declare const COMMUNICATION_FINDING_CODES: readonly CommunicationFindingCode[];
|
|
94
|
+
/** Sequence numbers as they sort: `2` before `10`, `1.1` before `1.2`. */
|
|
95
|
+
declare function sequenceOrder(left: string, right: string): number;
|
|
96
|
+
/**
|
|
97
|
+
* What a reader would get wrong about a communication diagram.
|
|
98
|
+
*
|
|
99
|
+
* The checks are the ones the diagram exists to answer: is every lifeline reachable, does
|
|
100
|
+
* every message travel a link that was drawn, does any number appear twice, and is each
|
|
101
|
+
* participant named after something in the design. The order the numbers imply is *not*
|
|
102
|
+
* checked against the drawing order - the numbers are the order, and the drawing order is
|
|
103
|
+
* not a claim.
|
|
104
|
+
*/
|
|
105
|
+
export declare function reviewCommunicationModel(model: CommunicationModelV1, labels: Record<string, string>): UmlFamilyFinding[];
|
|
106
|
+
/** The communication family, as the engine's registry expects it. */
|
|
107
|
+
export declare const communicationModule: UmlFamilyModule<CommunicationModelV1>;
|
|
108
|
+
/** Sort two sequence numbers the way a reader reads them: `2` before `10`, `1.1` before `1.2`. */
|
|
109
|
+
export { sequenceOrder as communicationSequenceOrder };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composite structure diagram module.
|
|
3
|
+
*
|
|
4
|
+
* A composite structure diagram is a structured classifier seen from the inside: the parts
|
|
5
|
+
* it is made of, the ports on its boundary, and the connectors between them. That reads
|
|
6
|
+
* back out of the text, which is what separates this family from the profile.
|
|
7
|
+
*
|
|
8
|
+
* PlantUML has no composite-structure page, so the view is an approximation built from the
|
|
9
|
+
* deployment diagram's vocabulary: a nested element for the classifier, the nestable
|
|
10
|
+
* elements for its parts, `port`/`portin`/`portout` for the boundary, and the arrows for
|
|
11
|
+
* connectors. Nesting is spelled, port direction is spelled, and both connector ends are
|
|
12
|
+
* spelled - so the model survives the round trip. What the notation cannot say (a part's
|
|
13
|
+
* type, a port's required interface, a connector's name) stays out of the model rather
|
|
14
|
+
* than being invented on the way back.
|
|
15
|
+
*
|
|
16
|
+
* @module model-everything-uml-composite
|
|
17
|
+
*/
|
|
18
|
+
import { type UmlNotation, type UmlFamilyModule, type UmlFamilyParse, type UmlFamilyRender, type UmlFamilyFinding } from './uml-syntax.js';
|
|
19
|
+
/** One end of a connector: the classifier itself, one of its ports, or one of its parts. */
|
|
20
|
+
export type CompositeEndpoint = string;
|
|
21
|
+
/** The structured classifier being opened up. */
|
|
22
|
+
export interface CompositeSpec {
|
|
23
|
+
id: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
/** The keyword it is drawn with; `component` is the deployment diagram's default. */
|
|
26
|
+
kind: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CompositePart {
|
|
29
|
+
id: string;
|
|
30
|
+
label?: string;
|
|
31
|
+
}
|
|
32
|
+
export type CompositePortDirection = 'in' | 'out' | 'inout';
|
|
33
|
+
export interface CompositePort {
|
|
34
|
+
id: string;
|
|
35
|
+
/** `in` is `portin`, `out` is `portout`, `inout` is the bare `port`. */
|
|
36
|
+
direction: CompositePortDirection;
|
|
37
|
+
}
|
|
38
|
+
export interface CompositeConnector {
|
|
39
|
+
from: CompositeEndpoint;
|
|
40
|
+
to: CompositeEndpoint;
|
|
41
|
+
label?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A composite structure diagram as a model.
|
|
45
|
+
*
|
|
46
|
+
* `self` is the classifier. Ports and parts belong to it, and a connector endpoint names
|
|
47
|
+
* one of the three - the classifier itself, a port, or a part. The model has no nesting:
|
|
48
|
+
* a part of a part is a second diagram, which is how a reader keeps each view readable.
|
|
49
|
+
*/
|
|
50
|
+
export interface CompositeModelV1 {
|
|
51
|
+
schemaVersion: 1;
|
|
52
|
+
self: CompositeSpec;
|
|
53
|
+
parts: CompositePart[];
|
|
54
|
+
ports: CompositePort[];
|
|
55
|
+
connectors: CompositeConnector[];
|
|
56
|
+
/** Ids a connector named that no declaration introduced; the review reports them. */
|
|
57
|
+
undeclared?: string[];
|
|
58
|
+
narrative?: {
|
|
59
|
+
self?: string;
|
|
60
|
+
parts?: Record<string, string>;
|
|
61
|
+
ports?: Record<string, string>;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate a candidate model and normalize it.
|
|
66
|
+
*
|
|
67
|
+
* A port id and a part id may not collide: a connector endpoint is a bare name, so two
|
|
68
|
+
* declarations sharing one would make the drawing say two things at once.
|
|
69
|
+
*/
|
|
70
|
+
export declare function validateCompositeModel(input: unknown): CompositeModelV1;
|
|
71
|
+
/**
|
|
72
|
+
* Render a composite structure diagram as PlantUML.
|
|
73
|
+
*
|
|
74
|
+
* The classifier is drawn as a nested element, its parts inside it, its ports on its
|
|
75
|
+
* boundary, and the connectors after the block. The `self` directive carries the
|
|
76
|
+
* classifier's own id, because a nested element's closing brace is the only thing that
|
|
77
|
+
* says where its inside ends.
|
|
78
|
+
*
|
|
79
|
+
* @param input - candidate `CompositeModelV1`.
|
|
80
|
+
* @param notation - only `plantuml` draws this family; mermaid has no ports or connectors.
|
|
81
|
+
*/
|
|
82
|
+
export declare function renderComposite(input: unknown, notation: UmlNotation): UmlFamilyRender;
|
|
83
|
+
/**
|
|
84
|
+
* Read a composite structure diagram back into a model.
|
|
85
|
+
*
|
|
86
|
+
* Faithful to this module's renderer and tolerant of hand-written text: the classifier is
|
|
87
|
+
* the outermost block (named by the `compositeSelf` directive when the renderer wrote it),
|
|
88
|
+
* `port`/`portin`/`portout` lines are its ports, nestable declarations inside the block are
|
|
89
|
+
* its parts, and every arrow between two names is a connector. A construct the notation
|
|
90
|
+
* carries but this model does not - a nested block inside a part, a stereotype, a note - is
|
|
91
|
+
* reported in `discardedConstructs`, never dropped in silence.
|
|
92
|
+
*/
|
|
93
|
+
export declare function parseComposite(text: string, notation: UmlNotation): UmlFamilyParse<CompositeModelV1>;
|
|
94
|
+
export type CompositeFindingCode = 'UML057_COMPOSITE_NO_PARTS' | 'UML058_COMPOSITE_PORT_UNCONNECTED' | 'UML059_COMPOSITE_CONNECTOR_ENDPOINT_MISSING' | 'UML060_COMPOSITE_DUPLICATE_PART' | 'UML061_COMPOSITE_PORT_COLLISION' | 'UML062_COMPOSITE_UNDOCUMENTED';
|
|
95
|
+
export declare const COMPOSITE_FINDING_CODES: readonly CompositeFindingCode[];
|
|
96
|
+
/**
|
|
97
|
+
* What a reader would get wrong about a composite structure.
|
|
98
|
+
*
|
|
99
|
+
* The questions are the ones the diagram exists to answer: is anything inside, does every
|
|
100
|
+
* port lead somewhere, does every connector join two things that exist, and is each part
|
|
101
|
+
* and port named after something in the system rather than after its drawing position.
|
|
102
|
+
* Whether the decomposition is *right* is a question about the design, and this does not
|
|
103
|
+
* answer it.
|
|
104
|
+
*/
|
|
105
|
+
export declare function reviewCompositeModel(model: CompositeModelV1, labels: Record<string, string>): UmlFamilyFinding[];
|
|
106
|
+
/** The composite structure family, as the engine's registry expects it. */
|
|
107
|
+
export declare const compositeModule: UmlFamilyModule<CompositeModelV1>;
|