@dr2rai/raid-canvas 0.1.0 → 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/dist/RaiBridge.d.ts.map +1 -1
- package/dist/RaiBridge.js +63 -3
- package/dist/RaiBridge.js.map +1 -1
- package/dist/RaidCanvas.d.ts +76 -0
- package/dist/RaidCanvas.d.ts.map +1 -0
- package/dist/RaidCanvas.js +635 -0
- package/dist/RaidCanvas.js.map +1 -0
- package/dist/X6Shapes.d.ts +9 -1
- package/dist/X6Shapes.d.ts.map +1 -1
- package/dist/X6Shapes.js +57 -18
- package/dist/X6Shapes.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/semanticRules.d.ts +55 -0
- package/dist/semanticRules.d.ts.map +1 -0
- package/dist/semanticRules.js +201 -0
- package/dist/semanticRules.js.map +1 -0
- package/package.json +10 -2
- package/src/RaiBridge.ts +76 -3
- package/src/RaidCanvas.tsx +875 -0
- package/src/X6Shapes.ts +66 -18
- package/src/index.ts +23 -0
- package/src/semanticRules.ts +237 -0
package/src/X6Shapes.ts
CHANGED
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
* - Cascais Heraldry design tokens.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { Graph, Node, Edge } from '@antv/x6';
|
|
12
|
+
import { Graph, Shape, Node, Edge } from '@antv/x6';
|
|
13
13
|
import type {
|
|
14
|
+
AimOntologyKind,
|
|
14
15
|
AimEdgeKind,
|
|
15
16
|
RaidNodeData,
|
|
16
17
|
RaidEdgeData,
|
|
17
18
|
OrthogonalPortId,
|
|
19
|
+
Bounds,
|
|
18
20
|
} from './types.js';
|
|
19
21
|
|
|
20
22
|
/**
|
|
@@ -105,9 +107,9 @@ export function registerAimShapes(): void {
|
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
// 1. AimUseCaseNode ('uc') — Ellipse with Net Gold border
|
|
108
|
-
|
|
110
|
+
Shape.Ellipse.define({
|
|
109
111
|
shape: 'aim-uc',
|
|
110
|
-
|
|
112
|
+
overwrite: true,
|
|
111
113
|
width: 140,
|
|
112
114
|
height: 70,
|
|
113
115
|
attrs: {
|
|
@@ -115,8 +117,6 @@ export function registerAimShapes(): void {
|
|
|
115
117
|
fill: CascaisPalette.ChalkWhite,
|
|
116
118
|
stroke: CascaisPalette.NetGold,
|
|
117
119
|
strokeWidth: 2,
|
|
118
|
-
rx: 70,
|
|
119
|
-
ry: 35,
|
|
120
120
|
class: 'aim-node aim-uc',
|
|
121
121
|
},
|
|
122
122
|
label: {
|
|
@@ -133,9 +133,9 @@ export function registerAimShapes(): void {
|
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
// 2. AimActivityNode ('act') — Rounded rectangle with Heraldic Green border
|
|
136
|
-
|
|
136
|
+
Shape.Rect.define({
|
|
137
137
|
shape: 'aim-act',
|
|
138
|
-
|
|
138
|
+
overwrite: true,
|
|
139
139
|
width: 150,
|
|
140
140
|
height: 60,
|
|
141
141
|
attrs: {
|
|
@@ -161,9 +161,9 @@ export function registerAimShapes(): void {
|
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
// 3. AimClassNode ('cls') — Compartmentalized class card
|
|
164
|
-
|
|
164
|
+
Shape.Rect.define({
|
|
165
165
|
shape: 'aim-cls',
|
|
166
|
-
|
|
166
|
+
overwrite: true,
|
|
167
167
|
width: 180,
|
|
168
168
|
height: 100,
|
|
169
169
|
markup: [
|
|
@@ -258,9 +258,9 @@ export function registerAimShapes(): void {
|
|
|
258
258
|
});
|
|
259
259
|
|
|
260
260
|
// 4. AimObjectNode ('obj') — Instance card with underlined title
|
|
261
|
-
|
|
261
|
+
Shape.Rect.define({
|
|
262
262
|
shape: 'aim-obj',
|
|
263
|
-
|
|
263
|
+
overwrite: true,
|
|
264
264
|
width: 160,
|
|
265
265
|
height: 80,
|
|
266
266
|
attrs: {
|
|
@@ -271,7 +271,7 @@ export function registerAimShapes(): void {
|
|
|
271
271
|
class: 'aim-node aim-obj',
|
|
272
272
|
},
|
|
273
273
|
label: {
|
|
274
|
-
text: '
|
|
274
|
+
text: 'instance: Type',
|
|
275
275
|
fill: CascaisPalette.TextPrimary,
|
|
276
276
|
fontSize: 12,
|
|
277
277
|
fontFamily: 'Inter, system-ui, -apple-system, sans-serif',
|
|
@@ -283,9 +283,9 @@ export function registerAimShapes(): void {
|
|
|
283
283
|
});
|
|
284
284
|
|
|
285
285
|
// 5. AimPersonNode ('per') — Person / Actor role card
|
|
286
|
-
|
|
286
|
+
Shape.Rect.define({
|
|
287
287
|
shape: 'aim-per',
|
|
288
|
-
|
|
288
|
+
overwrite: true,
|
|
289
289
|
width: 120,
|
|
290
290
|
height: 70,
|
|
291
291
|
attrs: {
|
|
@@ -311,9 +311,9 @@ export function registerAimShapes(): void {
|
|
|
311
311
|
});
|
|
312
312
|
|
|
313
313
|
// 6. AimEdge — Orthogonal Manhattan edge with rounded corners
|
|
314
|
-
Edge.define({
|
|
314
|
+
Shape.Edge.define({
|
|
315
315
|
shape: 'aim-edge',
|
|
316
|
-
|
|
316
|
+
overwrite: true,
|
|
317
317
|
router: {
|
|
318
318
|
name: 'manhattan',
|
|
319
319
|
args: {
|
|
@@ -509,8 +509,11 @@ function getEdgeStyling(kind: AimEdgeKind): Record<string, unknown> {
|
|
|
509
509
|
strokeWidth: 1.5,
|
|
510
510
|
strokeDasharray: '5,5',
|
|
511
511
|
targetMarker: {
|
|
512
|
-
name: '
|
|
513
|
-
|
|
512
|
+
name: 'block',
|
|
513
|
+
args: {
|
|
514
|
+
size: 8,
|
|
515
|
+
open: true,
|
|
516
|
+
},
|
|
514
517
|
},
|
|
515
518
|
};
|
|
516
519
|
|
|
@@ -573,3 +576,48 @@ function getEdgeStyling(kind: AimEdgeKind): Record<string, unknown> {
|
|
|
573
576
|
};
|
|
574
577
|
}
|
|
575
578
|
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Returns default Cartesian bounds for an instantiated AOAIM archetype.
|
|
582
|
+
*/
|
|
583
|
+
export function getDefaultNodeBounds(
|
|
584
|
+
kind: AimOntologyKind | string,
|
|
585
|
+
x: number = 100,
|
|
586
|
+
y: number = 100,
|
|
587
|
+
): Bounds {
|
|
588
|
+
switch (kind) {
|
|
589
|
+
case 'uc':
|
|
590
|
+
return { x, y, width: 140, height: 70 };
|
|
591
|
+
case 'act':
|
|
592
|
+
return { x, y, width: 150, height: 60 };
|
|
593
|
+
case 'cls':
|
|
594
|
+
return { x, y, width: 180, height: 110 };
|
|
595
|
+
case 'obj':
|
|
596
|
+
return { x, y, width: 160, height: 80 };
|
|
597
|
+
case 'per':
|
|
598
|
+
return { x, y, width: 120, height: 70 };
|
|
599
|
+
default:
|
|
600
|
+
return { x, y, width: 140, height: 60 };
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Returns a canonical default display name for an instantiated AOAIM archetype.
|
|
606
|
+
*/
|
|
607
|
+
export function getDefaultNodeName(kind: AimOntologyKind | string): string {
|
|
608
|
+
switch (kind) {
|
|
609
|
+
case 'uc':
|
|
610
|
+
return 'New UseCase';
|
|
611
|
+
case 'act':
|
|
612
|
+
return 'New Activity';
|
|
613
|
+
case 'cls':
|
|
614
|
+
return 'NewClass';
|
|
615
|
+
case 'obj':
|
|
616
|
+
return 'new Object';
|
|
617
|
+
case 'per':
|
|
618
|
+
return 'Actor';
|
|
619
|
+
default:
|
|
620
|
+
return 'Entity';
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* - 4-way orthogonal ports and Manhattan router integration.
|
|
8
8
|
* - Cascais Heraldry design tokens and theme styling.
|
|
9
9
|
* - Bidirectional RaiBridge for hydrating from and serializing to the aim-* SVG contract.
|
|
10
|
+
* - Anti-entropy semantic connection validation and wiring rules.
|
|
11
|
+
* - Reusable <RaidCanvas /> React component with Dnd and imperative control handle.
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
// Core Metamodel & SVG Contract Types
|
|
@@ -33,7 +35,28 @@ export {
|
|
|
33
35
|
configureAimGraph,
|
|
34
36
|
createAimNode,
|
|
35
37
|
createAimEdge,
|
|
38
|
+
getDefaultNodeBounds,
|
|
39
|
+
getDefaultNodeName,
|
|
36
40
|
} from './X6Shapes.js';
|
|
37
41
|
|
|
42
|
+
// Anti-Entropy Semantic Connection Rules
|
|
43
|
+
export {
|
|
44
|
+
SEMANTIC_RULES_MATRIX,
|
|
45
|
+
validateSemanticConnection,
|
|
46
|
+
getSemanticEdgeKind,
|
|
47
|
+
getSemanticEdgeStereotype,
|
|
48
|
+
getSemanticRuleDescription,
|
|
49
|
+
getAvailableStereotypes,
|
|
50
|
+
type SemanticRule,
|
|
51
|
+
type StereotypeOption,
|
|
52
|
+
} from './semanticRules.js';
|
|
53
|
+
|
|
38
54
|
// Bidirectional SVG <-> X6 Synchronization Bridge
|
|
39
55
|
export { RaiBridge } from './RaiBridge.js';
|
|
56
|
+
|
|
57
|
+
// Reusable React Canvas Component & Ref Handle
|
|
58
|
+
export {
|
|
59
|
+
RaidCanvas,
|
|
60
|
+
type RaidCanvasProps,
|
|
61
|
+
type RaidCanvasHandle,
|
|
62
|
+
} from './RaidCanvas.js';
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file semanticRules.ts
|
|
3
|
+
* @description Anti-entropy semantic connection validation and wiring rules
|
|
4
|
+
* for the AOAIM (Activity-Object-AI Model) graphical modeling contract.
|
|
5
|
+
*
|
|
6
|
+
* Enforces ontological integrity during edge creation:
|
|
7
|
+
* - 'per' -> 'uc' : 'association' («initiates», «owns» [0..1], «participates» [0..*])
|
|
8
|
+
* - 'per' -> 'act' : 'association' («executes»)
|
|
9
|
+
* - 'uc' -> 'uc' : 'dependency' («includes», «extends», «dependsOn»)
|
|
10
|
+
* - 'uc' -> 'act' : 'dependency' («includes»)
|
|
11
|
+
* - 'act' -> 'act' : 'association' («sequence» / process flow)
|
|
12
|
+
* - 'cls' -> 'cls' : 'association' («relatesTo»), 'generalization', 'composition', 'aggregation'
|
|
13
|
+
* - 'cls' -> 'obj' : 'dependency' («instantiates»)
|
|
14
|
+
* - 'obj' -> 'obj' : 'association' («link»)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { AimOntologyKind, AimEdgeKind } from './types.js';
|
|
18
|
+
|
|
19
|
+
export interface StereotypeOption {
|
|
20
|
+
readonly stereotype: string;
|
|
21
|
+
readonly defaultCardinality?: string;
|
|
22
|
+
readonly description: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SemanticRule {
|
|
26
|
+
readonly valid: boolean;
|
|
27
|
+
readonly defaultEdgeKind: AimEdgeKind;
|
|
28
|
+
readonly defaultStereotype: string;
|
|
29
|
+
readonly defaultCardinality?: string;
|
|
30
|
+
readonly availableStereotypes: readonly StereotypeOption[];
|
|
31
|
+
readonly description: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Ontological connection rules matrix.
|
|
36
|
+
* Key: `${sourceKind}->${targetKind}`
|
|
37
|
+
*/
|
|
38
|
+
export const SEMANTIC_RULES_MATRIX: Readonly<Record<string, SemanticRule>> = {
|
|
39
|
+
'per->uc': {
|
|
40
|
+
valid: true,
|
|
41
|
+
defaultEdgeKind: 'association',
|
|
42
|
+
defaultStereotype: '«initiates»',
|
|
43
|
+
description: 'Actor initiates, owns, or participates in UseCase',
|
|
44
|
+
availableStereotypes: [
|
|
45
|
+
{
|
|
46
|
+
stereotype: '«initiates»',
|
|
47
|
+
defaultCardinality: '1',
|
|
48
|
+
description: 'Initiating role triggering the UseCase flow',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
stereotype: '«owns»',
|
|
52
|
+
defaultCardinality: '0..1',
|
|
53
|
+
description: 'Ownership relationship representing responsible party (cardinality 0..1)',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
stereotype: '«participates»',
|
|
57
|
+
defaultCardinality: '0..*',
|
|
58
|
+
description: 'Participating role supporting the UseCase execution (cardinality 0..*)',
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
'per->act': {
|
|
63
|
+
valid: true,
|
|
64
|
+
defaultEdgeKind: 'association',
|
|
65
|
+
defaultStereotype: '«executes»',
|
|
66
|
+
description: 'Actor directly performs or executes Activity',
|
|
67
|
+
availableStereotypes: [
|
|
68
|
+
{
|
|
69
|
+
stereotype: '«executes»',
|
|
70
|
+
description: 'Actor performs this process step',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
stereotype: '«approves»',
|
|
74
|
+
description: 'Actor reviews or approves activity completion',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
'uc->uc': {
|
|
79
|
+
valid: true,
|
|
80
|
+
defaultEdgeKind: 'dependency',
|
|
81
|
+
defaultStereotype: '«includes»',
|
|
82
|
+
description: 'UseCase includes or extends sub-UseCase',
|
|
83
|
+
availableStereotypes: [
|
|
84
|
+
{
|
|
85
|
+
stereotype: '«includes»',
|
|
86
|
+
description: 'Mandatory sub-flow inclusion dependency',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
stereotype: '«extends»',
|
|
90
|
+
description: 'Optional conditional extension point',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
stereotype: '«dependsOn»',
|
|
94
|
+
description: 'Prerequisite functional dependency',
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
'uc->act': {
|
|
99
|
+
valid: true,
|
|
100
|
+
defaultEdgeKind: 'dependency',
|
|
101
|
+
defaultStereotype: '«includes»',
|
|
102
|
+
description: 'UseCase elaborates downflow process Activity',
|
|
103
|
+
availableStereotypes: [
|
|
104
|
+
{
|
|
105
|
+
stereotype: '«includes»',
|
|
106
|
+
description: 'Process activity required by UseCase',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
stereotype: '«triggers»',
|
|
110
|
+
description: 'UseCase execution triggers activity',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
'act->act': {
|
|
115
|
+
valid: true,
|
|
116
|
+
defaultEdgeKind: 'association',
|
|
117
|
+
defaultStereotype: '«sequence»',
|
|
118
|
+
description: 'Activity transitions to next process step',
|
|
119
|
+
availableStereotypes: [
|
|
120
|
+
{
|
|
121
|
+
stereotype: '«sequence»',
|
|
122
|
+
description: 'Sequential process transition',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
stereotype: '«branch»',
|
|
126
|
+
description: 'Conditional decision branch',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
'cls->cls': {
|
|
131
|
+
valid: true,
|
|
132
|
+
defaultEdgeKind: 'association',
|
|
133
|
+
defaultStereotype: '«relatesTo»',
|
|
134
|
+
description: 'Domain structural relationship between Classes',
|
|
135
|
+
availableStereotypes: [
|
|
136
|
+
{
|
|
137
|
+
stereotype: '«relatesTo»',
|
|
138
|
+
defaultCardinality: '1..*',
|
|
139
|
+
description: 'General domain association',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
stereotype: '«generalization»',
|
|
143
|
+
description: 'Inheritance classification (subclass is-a superclass)',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
stereotype: '«composition»',
|
|
147
|
+
defaultCardinality: '1',
|
|
148
|
+
description: 'Composite whole-part lifecycle binding',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
stereotype: '«aggregation»',
|
|
152
|
+
defaultCardinality: '0..*',
|
|
153
|
+
description: 'Shared aggregation relationship',
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
'cls->obj': {
|
|
158
|
+
valid: true,
|
|
159
|
+
defaultEdgeKind: 'dependency',
|
|
160
|
+
defaultStereotype: '«instantiates»',
|
|
161
|
+
description: 'Class specifies runtime Object instance',
|
|
162
|
+
availableStereotypes: [
|
|
163
|
+
{
|
|
164
|
+
stereotype: '«instantiates»',
|
|
165
|
+
description: 'Class defines schema for runtime instance',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
'obj->obj': {
|
|
170
|
+
valid: true,
|
|
171
|
+
defaultEdgeKind: 'association',
|
|
172
|
+
defaultStereotype: '«link»',
|
|
173
|
+
description: 'Runtime communication link between Objects',
|
|
174
|
+
availableStereotypes: [
|
|
175
|
+
{
|
|
176
|
+
stereotype: '«link»',
|
|
177
|
+
description: 'Runtime object collaboration message link',
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Validates whether an edge connection between source and target archetypes is ontologically allowed.
|
|
185
|
+
*/
|
|
186
|
+
export function validateSemanticConnection(
|
|
187
|
+
sourceKind: AimOntologyKind | string,
|
|
188
|
+
targetKind: AimOntologyKind | string,
|
|
189
|
+
): boolean {
|
|
190
|
+
if (!sourceKind || !targetKind) return false;
|
|
191
|
+
const key = `${sourceKind}->${targetKind}`;
|
|
192
|
+
return SEMANTIC_RULES_MATRIX[key]?.valid ?? false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Determines the canonical default relationship edge kind for a connected pair.
|
|
197
|
+
*/
|
|
198
|
+
export function getSemanticEdgeKind(
|
|
199
|
+
sourceKind: AimOntologyKind | string,
|
|
200
|
+
targetKind: AimOntologyKind | string,
|
|
201
|
+
): AimEdgeKind {
|
|
202
|
+
const key = `${sourceKind}->${targetKind}`;
|
|
203
|
+
return SEMANTIC_RULES_MATRIX[key]?.defaultEdgeKind ?? 'association';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Determines the canonical default stereotype annotation for a connected pair.
|
|
208
|
+
*/
|
|
209
|
+
export function getSemanticEdgeStereotype(
|
|
210
|
+
sourceKind: AimOntologyKind | string,
|
|
211
|
+
targetKind: AimOntologyKind | string,
|
|
212
|
+
): string {
|
|
213
|
+
const key = `${sourceKind}->${targetKind}`;
|
|
214
|
+
return SEMANTIC_RULES_MATRIX[key]?.defaultStereotype ?? '';
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Returns available ontological stereotypes and their default cardinalities for a pair.
|
|
219
|
+
*/
|
|
220
|
+
export function getAvailableStereotypes(
|
|
221
|
+
sourceKind: AimOntologyKind | string,
|
|
222
|
+
targetKind: AimOntologyKind | string,
|
|
223
|
+
): readonly StereotypeOption[] {
|
|
224
|
+
const key = `${sourceKind}->${targetKind}`;
|
|
225
|
+
return SEMANTIC_RULES_MATRIX[key]?.availableStereotypes ?? [];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Returns a human-readable description explaining the ontological relationship.
|
|
230
|
+
*/
|
|
231
|
+
export function getSemanticRuleDescription(
|
|
232
|
+
sourceKind: AimOntologyKind | string,
|
|
233
|
+
targetKind: AimOntologyKind | string,
|
|
234
|
+
): string {
|
|
235
|
+
const key = `${sourceKind}->${targetKind}`;
|
|
236
|
+
return SEMANTIC_RULES_MATRIX[key]?.description ?? 'Invalid ontological connection';
|
|
237
|
+
}
|