@formicoidea/labre-framework-bpmn 0.31.0 → 0.33.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/actions.d.ts +213 -0
- package/dist/actions.js +467 -0
- package/dist/background.d.ts +2 -0
- package/dist/background.js +158 -0
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +567 -0
- package/dist/consts.d.ts +157 -3
- package/dist/consts.js +192 -3
- package/dist/descriptor.d.ts +8 -3
- package/dist/descriptor.js +6 -3
- package/dist/element-renderer.d.ts +10 -4
- package/dist/element-renderer.js +14 -55
- package/dist/element-view.d.ts +100 -8
- package/dist/element-view.js +249 -30
- package/dist/export.d.ts +277 -0
- package/dist/export.js +1802 -0
- package/dist/facts.d.ts +48 -0
- package/dist/facts.js +127 -0
- package/dist/import.d.ts +44 -0
- package/dist/import.js +1440 -0
- package/dist/index.d.ts +14 -1
- package/dist/index.js +46 -1
- package/dist/interchange.d.ts +109 -0
- package/dist/interchange.js +191 -0
- package/dist/morph.d.ts +61 -0
- package/dist/morph.js +118 -0
- package/dist/node/node-renderer.d.ts +0 -9
- package/dist/node/node-renderer.js +294 -17
- package/dist/pool-hit.d.ts +98 -0
- package/dist/pool-hit.js +130 -0
- package/dist/presets.d.ts +114 -0
- package/dist/presets.js +232 -0
- package/dist/profiles.d.ts +2 -0
- package/dist/profiles.js +189 -0
- package/dist/roles.d.ts +96 -0
- package/dist/roles.js +410 -0
- package/dist/rules.d.ts +199 -0
- package/dist/rules.js +1539 -0
- package/dist/templates/index.js +116 -9
- package/dist/toolbar/bpmn-menu.d.ts +6 -21
- package/dist/toolbar/bpmn-menu.js +6 -173
- package/dist/toolbar/bpmn-senior-button.js +8 -2
- package/dist/toolbar/config.d.ts +27 -2
- package/dist/toolbar/config.js +86 -2
- package/dist/toolbar/icons.d.ts +67 -0
- package/dist/toolbar/icons.js +141 -0
- package/dist/toolbar/senior-tool.js +1 -0
- package/dist/translations.d.ts +16 -0
- package/dist/translations.js +20 -0
- package/dist/view.d.ts +18 -0
- package/dist/view.js +95 -7
- package/package.json +2 -2
package/dist/roles.js
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/** Role ids, keyed by the `kind` used at the creation sites. */
|
|
2
|
+
export const BPMN_ROLE = {
|
|
3
|
+
// The umbrella over the three families that ARE the process: events,
|
|
4
|
+
// activities and gateways. Never stamped, like the three families under it.
|
|
5
|
+
flowObject: 'bpmn:flow-object',
|
|
6
|
+
// Events: the family, the two starts and the two ends, and the leaves the
|
|
7
|
+
// descriptive profile draws under each.
|
|
8
|
+
event: 'bpmn:event',
|
|
9
|
+
startEvent: 'bpmn:start-event',
|
|
10
|
+
startEventMessage: 'bpmn:message-start-event',
|
|
11
|
+
startEventTimer: 'bpmn:timer-start-event',
|
|
12
|
+
endEvent: 'bpmn:end-event',
|
|
13
|
+
endEventMessage: 'bpmn:message-end-event',
|
|
14
|
+
endEventTerminate: 'bpmn:terminate-end-event',
|
|
15
|
+
// Activities.
|
|
16
|
+
activity: 'bpmn:activity',
|
|
17
|
+
task: 'bpmn:task',
|
|
18
|
+
taskUser: 'bpmn:user-task',
|
|
19
|
+
taskService: 'bpmn:service-task',
|
|
20
|
+
subProcess: 'bpmn:sub-process',
|
|
21
|
+
callActivity: 'bpmn:call-activity',
|
|
22
|
+
// Gateways. `gateway-exclusive` keeps the word order it shipped with — it is
|
|
23
|
+
// written in documents already — while its sibling takes the spec's own
|
|
24
|
+
// ("parallel gateway"). An id in a stored document is not a naming
|
|
25
|
+
// convention: it is a value, and renaming it would orphan every process that
|
|
26
|
+
// carries it.
|
|
27
|
+
gateway: 'bpmn:gateway',
|
|
28
|
+
gatewayExclusive: 'bpmn:gateway-exclusive',
|
|
29
|
+
gatewayParallel: 'bpmn:parallel-gateway',
|
|
30
|
+
// Data — a family of its own, never a flow object.
|
|
31
|
+
data: 'bpmn:data',
|
|
32
|
+
dataObject: 'bpmn:data-object',
|
|
33
|
+
dataStore: 'bpmn:data-store',
|
|
34
|
+
// The two artifacts: a note on the picture, and a lasso round part of it.
|
|
35
|
+
textAnnotation: 'bpmn:text-annotation',
|
|
36
|
+
group: 'bpmn:group',
|
|
37
|
+
// The frame.
|
|
38
|
+
pool: 'bpmn:pool',
|
|
39
|
+
// The connecting objects.
|
|
40
|
+
sequenceFlow: 'bpmn:sequence-flow',
|
|
41
|
+
messageFlow: 'bpmn:message-flow',
|
|
42
|
+
association: 'bpmn:association',
|
|
43
|
+
};
|
|
44
|
+
const _everyRoleIsMapped = true;
|
|
45
|
+
void _everyRoleIsMapped;
|
|
46
|
+
/** i18n key stem of a role id: `bpmn:start-event` → `com.labre.bpmn.role.start-event`. */
|
|
47
|
+
const roleKey = (id) => `com.labre.bpmn.role.${id.slice('bpmn:'.length)}`;
|
|
48
|
+
const FLOW_OBJECT_DEFS = [
|
|
49
|
+
/**
|
|
50
|
+
* The FLOW OBJECT — the one word BPMN itself uses for "a thing the process
|
|
51
|
+
* does", and the parent of the three families under it.
|
|
52
|
+
*
|
|
53
|
+
* Never stamped, like the three families it covers: no palette entry writes
|
|
54
|
+
* `bpmn:flow-object` and none ever will. It exists so a rule can say the thing
|
|
55
|
+
* the notation says. A sequence flow chains flow objects; a step must be
|
|
56
|
+
* reachable from the start; both sentences are about events, activities AND
|
|
57
|
+
* gateways at once, and without this role each of them would have to enumerate
|
|
58
|
+
* the three — three triplets where BPMN has one word, and a fourth family
|
|
59
|
+
* (nobody has asked for one) silently missing from every rule that forgot to
|
|
60
|
+
* grow its list.
|
|
61
|
+
*
|
|
62
|
+
* ## What it deliberately does NOT cover
|
|
63
|
+
*
|
|
64
|
+
* `bpmn:data`, `bpmn:text-annotation` and `bpmn:pool` stay outside, each for
|
|
65
|
+
* the reason its own block gives: the paperwork is not the work, commentary is
|
|
66
|
+
* never evidence, and the frame is not an artefact drawn in it. That
|
|
67
|
+
* exclusion is the whole value of the word — "a sequence flow chains flow
|
|
68
|
+
* objects" is only worth saying because a data object is not one.
|
|
69
|
+
*
|
|
70
|
+
* Pure static data, and nothing is written to a document: an element carries
|
|
71
|
+
* the role its palette entry stamped (`bpmn:task`), and the walk from it up to
|
|
72
|
+
* `bpmn:flow-object` happens in `roleIsA`, at evaluation time, out of this
|
|
73
|
+
* table. A process drawn yesterday gains the parent the moment it is opened,
|
|
74
|
+
* with no migration and nothing backfilled.
|
|
75
|
+
*/
|
|
76
|
+
{
|
|
77
|
+
id: BPMN_ROLE.flowObject,
|
|
78
|
+
kind: 'node',
|
|
79
|
+
labelKey: roleKey(BPMN_ROLE.flowObject),
|
|
80
|
+
labelFallback: 'Flow object',
|
|
81
|
+
},
|
|
82
|
+
// The three families. None of them is ever STAMPED on an element — the palette
|
|
83
|
+
// always says which event, which activity, which gateway — and that is the
|
|
84
|
+
// point: they exist so a rule can be written once about "an event" and stay
|
|
85
|
+
// written when the full pack adds the message and timer ones under them.
|
|
86
|
+
{
|
|
87
|
+
id: BPMN_ROLE.event,
|
|
88
|
+
parent: BPMN_ROLE.flowObject,
|
|
89
|
+
kind: 'node',
|
|
90
|
+
labelKey: roleKey(BPMN_ROLE.event),
|
|
91
|
+
labelFallback: 'Event',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: BPMN_ROLE.startEvent,
|
|
95
|
+
parent: BPMN_ROLE.event,
|
|
96
|
+
kind: 'node',
|
|
97
|
+
labelKey: roleKey(BPMN_ROLE.startEvent),
|
|
98
|
+
labelFallback: 'Start event',
|
|
99
|
+
},
|
|
100
|
+
// The two TRIGGERED starts. Children of the plain start event and not
|
|
101
|
+
// siblings of it: "the process starts here" is true of all three, and a rule
|
|
102
|
+
// about where a process begins must not have to enumerate the triggers.
|
|
103
|
+
{
|
|
104
|
+
id: BPMN_ROLE.startEventMessage,
|
|
105
|
+
parent: BPMN_ROLE.startEvent,
|
|
106
|
+
kind: 'node',
|
|
107
|
+
labelKey: roleKey(BPMN_ROLE.startEventMessage),
|
|
108
|
+
labelFallback: 'Message start event',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: BPMN_ROLE.startEventTimer,
|
|
112
|
+
parent: BPMN_ROLE.startEvent,
|
|
113
|
+
kind: 'node',
|
|
114
|
+
labelKey: roleKey(BPMN_ROLE.startEventTimer),
|
|
115
|
+
labelFallback: 'Timer start event',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: BPMN_ROLE.endEvent,
|
|
119
|
+
parent: BPMN_ROLE.event,
|
|
120
|
+
kind: 'node',
|
|
121
|
+
labelKey: roleKey(BPMN_ROLE.endEvent),
|
|
122
|
+
labelFallback: 'End event',
|
|
123
|
+
},
|
|
124
|
+
// ...and the two ends that do something on the way out.
|
|
125
|
+
{
|
|
126
|
+
id: BPMN_ROLE.endEventMessage,
|
|
127
|
+
parent: BPMN_ROLE.endEvent,
|
|
128
|
+
kind: 'node',
|
|
129
|
+
labelKey: roleKey(BPMN_ROLE.endEventMessage),
|
|
130
|
+
labelFallback: 'Message end event',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: BPMN_ROLE.endEventTerminate,
|
|
134
|
+
parent: BPMN_ROLE.endEvent,
|
|
135
|
+
kind: 'node',
|
|
136
|
+
labelKey: roleKey(BPMN_ROLE.endEventTerminate),
|
|
137
|
+
labelFallback: 'Terminate end event',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: BPMN_ROLE.activity,
|
|
141
|
+
parent: BPMN_ROLE.flowObject,
|
|
142
|
+
kind: 'node',
|
|
143
|
+
labelKey: roleKey(BPMN_ROLE.activity),
|
|
144
|
+
labelFallback: 'Activity',
|
|
145
|
+
},
|
|
146
|
+
// The plain task — one unit of work, done by someone or something unnamed.
|
|
147
|
+
{
|
|
148
|
+
id: BPMN_ROLE.task,
|
|
149
|
+
parent: BPMN_ROLE.activity,
|
|
150
|
+
kind: 'node',
|
|
151
|
+
labelKey: roleKey(BPMN_ROLE.task),
|
|
152
|
+
labelFallback: 'Task',
|
|
153
|
+
},
|
|
154
|
+
// The two typed tasks, under the plain one: they are tasks that also say WHO
|
|
155
|
+
// performs them. A rule about the work applies to all three; a rule about
|
|
156
|
+
// human hand-offs reads only the first.
|
|
157
|
+
{
|
|
158
|
+
id: BPMN_ROLE.taskUser,
|
|
159
|
+
parent: BPMN_ROLE.task,
|
|
160
|
+
kind: 'node',
|
|
161
|
+
labelKey: roleKey(BPMN_ROLE.taskUser),
|
|
162
|
+
labelFallback: 'User task',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
id: BPMN_ROLE.taskService,
|
|
166
|
+
parent: BPMN_ROLE.task,
|
|
167
|
+
kind: 'node',
|
|
168
|
+
labelKey: roleKey(BPMN_ROLE.taskService),
|
|
169
|
+
labelFallback: 'Service task',
|
|
170
|
+
},
|
|
171
|
+
// Sub-process and call activity are activities but NOT tasks: a task is
|
|
172
|
+
// atomic and these two stand for a whole process each — one defined inline,
|
|
173
|
+
// one defined elsewhere and reused. Filing them under `bpmn:task` would make
|
|
174
|
+
// "every task is one unit of work" false.
|
|
175
|
+
{
|
|
176
|
+
id: BPMN_ROLE.subProcess,
|
|
177
|
+
parent: BPMN_ROLE.activity,
|
|
178
|
+
kind: 'node',
|
|
179
|
+
labelKey: roleKey(BPMN_ROLE.subProcess),
|
|
180
|
+
labelFallback: 'Sub-process',
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: BPMN_ROLE.callActivity,
|
|
184
|
+
parent: BPMN_ROLE.activity,
|
|
185
|
+
kind: 'node',
|
|
186
|
+
labelKey: roleKey(BPMN_ROLE.callActivity),
|
|
187
|
+
labelFallback: 'Call activity',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: BPMN_ROLE.gateway,
|
|
191
|
+
parent: BPMN_ROLE.flowObject,
|
|
192
|
+
kind: 'node',
|
|
193
|
+
labelKey: roleKey(BPMN_ROLE.gateway),
|
|
194
|
+
labelFallback: 'Gateway',
|
|
195
|
+
},
|
|
196
|
+
// The exclusive (XOR) gateway and the parallel (AND) one. Same diamond, and
|
|
197
|
+
// the marker inside is the only thing that tells them apart on the canvas —
|
|
198
|
+
// which is exactly why the marker must not be what a rule reads.
|
|
199
|
+
{
|
|
200
|
+
id: BPMN_ROLE.gatewayExclusive,
|
|
201
|
+
parent: BPMN_ROLE.gateway,
|
|
202
|
+
kind: 'node',
|
|
203
|
+
labelKey: roleKey(BPMN_ROLE.gatewayExclusive),
|
|
204
|
+
labelFallback: 'Exclusive gateway',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: BPMN_ROLE.gatewayParallel,
|
|
208
|
+
parent: BPMN_ROLE.gateway,
|
|
209
|
+
kind: 'node',
|
|
210
|
+
labelKey: roleKey(BPMN_ROLE.gatewayParallel),
|
|
211
|
+
labelFallback: 'Parallel gateway',
|
|
212
|
+
},
|
|
213
|
+
];
|
|
214
|
+
/**
|
|
215
|
+
* Data — the paperwork, not the work.
|
|
216
|
+
*
|
|
217
|
+
* A family of its own, parent-less like the pool: a data object is never
|
|
218
|
+
* executed, never has a duration and is never on the happy path, so a rule
|
|
219
|
+
* written about the flow objects must not fall on it. The two leaves are the
|
|
220
|
+
* only distinction BPMN itself draws here — a data OBJECT lives and dies with
|
|
221
|
+
* the process instance, a data STORE outlives it.
|
|
222
|
+
*/
|
|
223
|
+
const DATA_DEFS = [
|
|
224
|
+
{
|
|
225
|
+
id: BPMN_ROLE.data,
|
|
226
|
+
kind: 'node',
|
|
227
|
+
labelKey: roleKey(BPMN_ROLE.data),
|
|
228
|
+
labelFallback: 'Data',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
id: BPMN_ROLE.dataObject,
|
|
232
|
+
parent: BPMN_ROLE.data,
|
|
233
|
+
kind: 'node',
|
|
234
|
+
labelKey: roleKey(BPMN_ROLE.dataObject),
|
|
235
|
+
labelFallback: 'Data object',
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: BPMN_ROLE.dataStore,
|
|
239
|
+
parent: BPMN_ROLE.data,
|
|
240
|
+
kind: 'node',
|
|
241
|
+
labelKey: roleKey(BPMN_ROLE.dataStore),
|
|
242
|
+
labelFallback: 'Data store',
|
|
243
|
+
},
|
|
244
|
+
];
|
|
245
|
+
/**
|
|
246
|
+
* The two artifacts — what the author drew ON the picture rather than IN it.
|
|
247
|
+
*
|
|
248
|
+
* Both parent-less and childless, and not siblings of each other either: they
|
|
249
|
+
* are not flow objects, not data and not frames, and the one thing every rule
|
|
250
|
+
* in this framework must agree on is that commentary is never evidence.
|
|
251
|
+
* Declared all the same, so a reader (and the audit) can tell an annotation
|
|
252
|
+
* from an unnamed rectangle somebody left behind.
|
|
253
|
+
*
|
|
254
|
+
* The GROUP is parent-less for a second reason, which is the spec's own: BPMN
|
|
255
|
+
* 2.0.2 §10.4 exempts it from every connection and containment constraint there
|
|
256
|
+
* is. It cannot be attached to a sequence or message flow, it is not bounded by
|
|
257
|
+
* the pool or lane it overlaps, and it may straddle several pools at once. A
|
|
258
|
+
* role under `bpmn:pool` or under any flow-object family would have made all
|
|
259
|
+
* three of those false by inheritance — the tree is where that exemption is
|
|
260
|
+
* written down.
|
|
261
|
+
*
|
|
262
|
+
* It is deliberately NOT the parent of the annotation, nor a child of it: one
|
|
263
|
+
* says something about a region, the other says something about a thing, and a
|
|
264
|
+
* rule about either must not fall on the other.
|
|
265
|
+
*/
|
|
266
|
+
const ARTIFACT_DEFS = [
|
|
267
|
+
{
|
|
268
|
+
id: BPMN_ROLE.textAnnotation,
|
|
269
|
+
kind: 'node',
|
|
270
|
+
labelKey: roleKey(BPMN_ROLE.textAnnotation),
|
|
271
|
+
labelFallback: 'Text annotation',
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
id: BPMN_ROLE.group,
|
|
275
|
+
kind: 'node',
|
|
276
|
+
labelKey: roleKey(BPMN_ROLE.group),
|
|
277
|
+
labelFallback: 'Group',
|
|
278
|
+
},
|
|
279
|
+
];
|
|
280
|
+
// The pool: the participant's own lane, the frame the flow objects are drawn in.
|
|
281
|
+
// Parent-less, like `wardley:map` — a rule written on the flow objects must
|
|
282
|
+
// never match the pool that holds them.
|
|
283
|
+
const POOL_DEFS = [
|
|
284
|
+
{
|
|
285
|
+
id: BPMN_ROLE.pool,
|
|
286
|
+
kind: 'node',
|
|
287
|
+
labelKey: roleKey(BPMN_ROLE.pool),
|
|
288
|
+
labelFallback: 'Pool',
|
|
289
|
+
},
|
|
290
|
+
];
|
|
291
|
+
/**
|
|
292
|
+
* The two connecting objects.
|
|
293
|
+
*
|
|
294
|
+
* Neither specialises the other, and there is deliberately no `bpmn:flow`
|
|
295
|
+
* parent: a sequence flow stays inside one pool and orders the work, a message
|
|
296
|
+
* flow crosses between pools and carries nothing but the message. They are two
|
|
297
|
+
* different sentences, and a rule about one must never fall on the other.
|
|
298
|
+
*/
|
|
299
|
+
const FLOW_DEFS = [
|
|
300
|
+
/**
|
|
301
|
+
* The sequence flow, pre-authorised as a typed edge by `docs/adr/0010`.
|
|
302
|
+
*
|
|
303
|
+
* Tier 1 of that ADR is generic — `source` is the subject of the role's verb,
|
|
304
|
+
* `target` its object — and tier 2 is this `direction` block: the verb is "is
|
|
305
|
+
* followed by", so the source is what happens FIRST and the target is what
|
|
306
|
+
* comes next. That is the whole of what makes an arrow on this canvas a
|
|
307
|
+
* statement the author made rather than a by-product of which end their finger
|
|
308
|
+
* landed on first, and it is what the hover reveal reads back with the `bpmn`
|
|
309
|
+
* flag off.
|
|
310
|
+
*/
|
|
311
|
+
{
|
|
312
|
+
id: BPMN_ROLE.sequenceFlow,
|
|
313
|
+
kind: 'edge',
|
|
314
|
+
labelKey: roleKey(BPMN_ROLE.sequenceFlow),
|
|
315
|
+
labelFallback: 'Sequence flow',
|
|
316
|
+
direction: {
|
|
317
|
+
verbKey: `${roleKey(BPMN_ROLE.sequenceFlow)}.verb`,
|
|
318
|
+
verbFallback: 'is followed by',
|
|
319
|
+
gestureHintKey: `${roleKey(BPMN_ROLE.sequenceFlow)}.gesture`,
|
|
320
|
+
gestureHintFallback: 'Drag from what happens first to what follows.',
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
/**
|
|
324
|
+
* The message flow — RESERVED.
|
|
325
|
+
*
|
|
326
|
+
* Declared in the vocabulary and stamped by nothing: the lean pack ships no
|
|
327
|
+
* creation tool for it, and the full pack adds one next session. It is written
|
|
328
|
+
* down now rather than later because the vocabulary is the one thing a stored
|
|
329
|
+
* document points at: an id declared today reads correctly whenever it is
|
|
330
|
+
* first written, whereas an id invented after the fact has to be reconciled
|
|
331
|
+
* with whatever the intervening months stamped.
|
|
332
|
+
*
|
|
333
|
+
* Its verb is its own — a message flow says nothing about ORDER, only about
|
|
334
|
+
* who told whom — which is precisely why it is not a child of the sequence
|
|
335
|
+
* flow.
|
|
336
|
+
*/
|
|
337
|
+
{
|
|
338
|
+
id: BPMN_ROLE.messageFlow,
|
|
339
|
+
kind: 'edge',
|
|
340
|
+
labelKey: roleKey(BPMN_ROLE.messageFlow),
|
|
341
|
+
labelFallback: 'Message flow',
|
|
342
|
+
direction: {
|
|
343
|
+
verbKey: `${roleKey(BPMN_ROLE.messageFlow)}.verb`,
|
|
344
|
+
verbFallback: 'sends a message to',
|
|
345
|
+
gestureHintKey: `${roleKey(BPMN_ROLE.messageFlow)}.gesture`,
|
|
346
|
+
gestureHintFallback: 'Drag from the participant that sends the message to the one that receives it.',
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
/**
|
|
350
|
+
* The association — the line that ties an annotation or a data object to the
|
|
351
|
+
* work it is about.
|
|
352
|
+
*
|
|
353
|
+
* Declared WITHOUT a `direction`, and that is the whole point of it. Tier 1 of
|
|
354
|
+
* `docs/adr/0010` says an edge role names a relation with a VERB, source the
|
|
355
|
+
* subject and target the object; an association names no relation and has no
|
|
356
|
+
* verb. "This note is about that task" reads identically from either end, and
|
|
357
|
+
* the spec agrees: an association is undirected unless it carries data, which
|
|
358
|
+
* the descriptive profile does not.
|
|
359
|
+
*
|
|
360
|
+
* The consequence is deliberate and is the reason to write it down here: the
|
|
361
|
+
* hover reveal shows its LABEL and no sentence, and the "reverse direction"
|
|
362
|
+
* toolbar entry has nothing to offer — because there is no direction to be
|
|
363
|
+
* wrong about, so there is none to fix.
|
|
364
|
+
*/
|
|
365
|
+
{
|
|
366
|
+
id: BPMN_ROLE.association,
|
|
367
|
+
kind: 'edge',
|
|
368
|
+
labelKey: roleKey(BPMN_ROLE.association),
|
|
369
|
+
labelFallback: 'Association',
|
|
370
|
+
},
|
|
371
|
+
];
|
|
372
|
+
const DEFS = [
|
|
373
|
+
...FLOW_OBJECT_DEFS,
|
|
374
|
+
...DATA_DEFS,
|
|
375
|
+
...ARTIFACT_DEFS,
|
|
376
|
+
...POOL_DEFS,
|
|
377
|
+
...FLOW_DEFS,
|
|
378
|
+
];
|
|
379
|
+
// Null prototype: this is a lookup table keyed by ids that may one day come
|
|
380
|
+
// from host-supplied packs, so `defs['toString']` must not resolve.
|
|
381
|
+
export const BPMN_ROLES = Object.assign(Object.create(null), Object.fromEntries(DEFS.map(def => [def.id, def])));
|
|
382
|
+
/**
|
|
383
|
+
* The legacy `kind` discriminant → the role it means.
|
|
384
|
+
*
|
|
385
|
+
* `kind` STAYS: it is persisted, it drives the renderer and it is what the
|
|
386
|
+
* palette writes. What it is not, from today, is the semantic authority — the
|
|
387
|
+
* ROLE is. The two are posted side by side at every creation site, the way
|
|
388
|
+
* Wardley already does it, and this table is the single place that says which
|
|
389
|
+
* kind means which role. Total over {@link BpmnNodeKind} by its type, so a new
|
|
390
|
+
* kind cannot land without being given a meaning.
|
|
391
|
+
*/
|
|
392
|
+
export const BPMN_ROLE_OF_KIND = {
|
|
393
|
+
startEvent: BPMN_ROLE.startEvent,
|
|
394
|
+
startEventMessage: BPMN_ROLE.startEventMessage,
|
|
395
|
+
startEventTimer: BPMN_ROLE.startEventTimer,
|
|
396
|
+
endEvent: BPMN_ROLE.endEvent,
|
|
397
|
+
endEventMessage: BPMN_ROLE.endEventMessage,
|
|
398
|
+
endEventTerminate: BPMN_ROLE.endEventTerminate,
|
|
399
|
+
task: BPMN_ROLE.task,
|
|
400
|
+
taskUser: BPMN_ROLE.taskUser,
|
|
401
|
+
taskService: BPMN_ROLE.taskService,
|
|
402
|
+
subProcess: BPMN_ROLE.subProcess,
|
|
403
|
+
callActivity: BPMN_ROLE.callActivity,
|
|
404
|
+
gatewayExclusive: BPMN_ROLE.gatewayExclusive,
|
|
405
|
+
gatewayParallel: BPMN_ROLE.gatewayParallel,
|
|
406
|
+
dataObject: BPMN_ROLE.dataObject,
|
|
407
|
+
dataStore: BPMN_ROLE.dataStore,
|
|
408
|
+
textAnnotation: BPMN_ROLE.textAnnotation,
|
|
409
|
+
group: BPMN_ROLE.group,
|
|
410
|
+
};
|
package/dist/rules.d.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { EndpointTriplet, ValidationRule } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
/**
|
|
3
|
+
* BPMN validation rules — the descriptive profile, as DATA (backlog item B6).
|
|
4
|
+
*
|
|
5
|
+
* NOTE ON NUMBERING: that "B6" is the BACKLOG item this file delivers. The
|
|
6
|
+
* **B1**–**B21** headings below are RULE numbers, a different space entirely,
|
|
7
|
+
* and the two collide on one token. Every in-file cross-reference means the rule
|
|
8
|
+
* number; the backlog item is named nowhere else.
|
|
9
|
+
*
|
|
10
|
+
* DATA owned by the framework, versioned per rule: the engine
|
|
11
|
+
* (`@labre/affine-block-surface`) knows how to evaluate a FAMILY, never a
|
|
12
|
+
* concrete rule, so adding a BPMN rule is adding an entry to the array at the
|
|
13
|
+
* bottom of this file. Registered from the flag-gated `BpmnViewExtension`, so
|
|
14
|
+
* switching the `bpmn` flag off removes the rules with the rest of the tooling
|
|
15
|
+
* — processes already drawn keep rendering, they simply stop being checked
|
|
16
|
+
* (`docs/adr/0009`).
|
|
17
|
+
*
|
|
18
|
+
* ## Every rule is read off the SPEC, and cites where
|
|
19
|
+
*
|
|
20
|
+
* The page references below are to **BPMN 2.0.2 (OMG / ISO-IEC 19510)**, which
|
|
21
|
+
* the PO supplied. They are not decoration: three rules in the first draft of
|
|
22
|
+
* this pack fired on diagrams the specification explicitly sanctions, and the
|
|
23
|
+
* only thing that caught them was reading the normative text rather than the
|
|
24
|
+
* folklore.
|
|
25
|
+
*
|
|
26
|
+
* ## And every rule now DECLARES where its authority comes from
|
|
27
|
+
*
|
|
28
|
+
* The citations above used to live in these comments alone, which meant the UI
|
|
29
|
+
* could not tell a conformance defect from a house style: a Labre convention
|
|
30
|
+
* presented to an architect as a norm violation is the finding an external
|
|
31
|
+
* review will not forgive. {@link ValidationRule.provenance} promotes the
|
|
32
|
+
* distinction to data — `standard` for a normative MUST with its page,
|
|
33
|
+
* `recommendation` for a SHOULD or an industry linter, `labre-convention` for
|
|
34
|
+
* ours — and the violation bubble says which.
|
|
35
|
+
*
|
|
36
|
+
* Two rules here are `labre-convention` and neither pretends otherwise:
|
|
37
|
+
* {@link sequenceFlowSelfLoop} and {@link untypedFlow}. The first exists as a
|
|
38
|
+
* separate rule BECAUSE of this field: it was a clause of B1, whose matrix is
|
|
39
|
+
* p.95, and one rule cannot honestly declare two provenances — see B1a.
|
|
40
|
+
*
|
|
41
|
+
* ## Why BPMN is the framework that needed five families
|
|
42
|
+
*
|
|
43
|
+
* A Wardley map is judged element by element: where a thing sits, which way an
|
|
44
|
+
* arrow points. A process is judged by its JOINTS. Every question below is about
|
|
45
|
+
* a relation, a count of relations, the frames two ends sit in, or the graph the
|
|
46
|
+
* relations build — which is why four of the five families arrived with the
|
|
47
|
+
* engine work that preceded this file, and why none of them names BPMN.
|
|
48
|
+
*
|
|
49
|
+
* - `relation-endpoints` (B1–B5) — WHAT a link may run between, and how many
|
|
50
|
+
* times. The grammar.
|
|
51
|
+
* - `edge-degree` (B6–B10, B16–B19) — HOW MANY links arrive at and leave one
|
|
52
|
+
* symbol. The half no per-link rule can express: nothing is wrong with any
|
|
53
|
+
* single arrow, the mistake is the count.
|
|
54
|
+
* - `edge-locality` (B11–B12) — WHICH POOL each end sits in. The swimlane
|
|
55
|
+
* question, and the one where the two ends carry identical roles in the legal
|
|
56
|
+
* case and the illegal one.
|
|
57
|
+
* - `role-count` (B14–B15, B20) — what one pool must CONTAIN, and only when it
|
|
58
|
+
* already contains the other half of the pair.
|
|
59
|
+
* - `reachability` (B13) — can you get there from the start. The graph question.
|
|
60
|
+
* - `label-presence` (B21) — does the symbol carry a name at all.
|
|
61
|
+
*
|
|
62
|
+
* ## The industry linters, and where we deliberately differ
|
|
63
|
+
*
|
|
64
|
+
* The inventory was triangulated against **bpmnlint** (the bpmn-js ecosystem's
|
|
65
|
+
* linter, the one a BPMN practitioner will already have met),
|
|
66
|
+
* bpmn-visualization-js and JointJS. Where a bpmnlint rule reads the same
|
|
67
|
+
* normative sentence we do, the id and the wording are chosen so a user
|
|
68
|
+
* recognises it; where we are quieter, the rule comment says why in its own
|
|
69
|
+
* paragraph. Two of theirs are NOT adopted:
|
|
70
|
+
*
|
|
71
|
+
* - **`no-implicit-start`** (ERROR there). It contradicts p.238: a Process is not
|
|
72
|
+
* required to contain a Start Event, and a flow object with no incoming
|
|
73
|
+
* sequence flow is then a legitimate parallel start (p.245). We sided with the
|
|
74
|
+
* specification — that decision is what
|
|
75
|
+
* {@link ReachabilityDef.implicitRoots} implements, and adopting the
|
|
76
|
+
* linter's rule would have meant shipping the two in contradiction.
|
|
77
|
+
* - **any overlap / readability rule.** The engine's pair-wise budget is pinned
|
|
78
|
+
* by the Wardley bench, which asserts that `wardley.overlapping-artefacts` is
|
|
79
|
+
* the ONLY registered `no-overlap` rule — a second one triggers the
|
|
80
|
+
* spatial-index obligation. That is a piece of engine work with its own
|
|
81
|
+
* measurements, not a line of data, so it is a backlog item and not this file.
|
|
82
|
+
*
|
|
83
|
+
* ## Severity: `warning` almost everywhere, `audit` where the spec allows the
|
|
84
|
+
* shape, and `blocking-overridable` nowhere
|
|
85
|
+
*
|
|
86
|
+
* The same promise `wardley/rules.ts:30` makes, for the same reason: NOTHING
|
|
87
|
+
* downstream implements a blocking level — no gesture is refused anywhere in
|
|
88
|
+
* this library — so shipping the value would be data claiming an effect that
|
|
89
|
+
* does not exist. Several of these are normative MUSTs and would sit there; they
|
|
90
|
+
* move in one line each, in `profiles.ts`, the day the gesture refusal lands.
|
|
91
|
+
*
|
|
92
|
+
* Five rules are declared `audit` on their own — `bpmn.activity-dead-end`,
|
|
93
|
+
* `bpmn.fake-join`, `bpmn.implicit-split`, `bpmn.single-blank-start` and
|
|
94
|
+
* `bpmn.unlabeled-step` — because in each case the specification sanctions the
|
|
95
|
+
* shape they report, or the diagram is merely unfinished. They are NUANCES for
|
|
96
|
+
* the conformance panel, never warnings on the canvas, and every one of them is
|
|
97
|
+
* quieter than the corresponding bpmnlint level on purpose.
|
|
98
|
+
*
|
|
99
|
+
* The severities declared here are the DESCRIPTIVE posture; `bpmn.sketch` — the
|
|
100
|
+
* default — demotes every one of them to `audit`, so the drawing hand is never
|
|
101
|
+
* argued with until someone asks for the stricter profile. See `profiles.ts`.
|
|
102
|
+
*
|
|
103
|
+
* ## What the whole file stays silent about
|
|
104
|
+
*
|
|
105
|
+
* A process drawn before the roles existed carries no role on anything, so it is
|
|
106
|
+
* never evaluated and never says a word (PRD principle 8). A process drawn
|
|
107
|
+
* before anybody added a pool has no frame for B11–B15 and B20 to be about, and those
|
|
108
|
+
* six are silent by construction.
|
|
109
|
+
*
|
|
110
|
+
* ## One thing the `relation-endpoints` family cannot say
|
|
111
|
+
*
|
|
112
|
+
* The ALPHABET of a `relation-endpoints` rule is derived from the roles its
|
|
113
|
+
* sanctioned triplets name. That is what makes the family proportionate — an end
|
|
114
|
+
* outside the alphabet takes the whole link out of the conversation, so a flow
|
|
115
|
+
* drawn onto a sticky note is a draft and not a finding — and it is also its one
|
|
116
|
+
* limit: **a framework cannot name a role it wants to REJECT without sanctioning
|
|
117
|
+
* a sentence for it.**
|
|
118
|
+
*
|
|
119
|
+
* Three normative prohibitions are therefore SILENCE rather than findings today:
|
|
120
|
+
*
|
|
121
|
+
* - "an Artifact MUST NOT be the source or target of a Sequence Flow" (p.65) and
|
|
122
|
+
* "a Sequence Flow connects Events, Activities and Gateways" (p.95) — a
|
|
123
|
+
* sequence flow dropped on a text annotation or a data object goes unjudged;
|
|
124
|
+
* - the Message Flow Connection Rules table (p.41–42), which lists what a
|
|
125
|
+
* message may run between and then says "Thus, Lane, Gateway, Data Object,
|
|
126
|
+
* Group, and Text Annotation are not listed in the table" — a gateway is
|
|
127
|
+
* named by no message sentence, so it is outside B2's alphabet.
|
|
128
|
+
*
|
|
129
|
+
* Reported to the engine author rather than worked around here: a triplet
|
|
130
|
+
* written to widen an alphabet without meaning what it says would be exactly the
|
|
131
|
+
* data-that-lies this platform refuses everywhere else. The corpus pins the
|
|
132
|
+
* silence explicitly (`corpus.unit.spec.ts`), so it stays a known limit rather
|
|
133
|
+
* than an assumption.
|
|
134
|
+
*
|
|
135
|
+
* ## The engine fields this pack asked for, and now uses
|
|
136
|
+
*
|
|
137
|
+
* Six of the rules below were authored against defs that did not exist when they
|
|
138
|
+
* were written, and `claude/bpmn-engine-v2` (#145) landed all six:
|
|
139
|
+
* `RoleCountDef.ifPresent` and `.exact`, `EdgeDegreeDef.forbidPattern` and
|
|
140
|
+
* `.eitherMin`, `ReachabilityDef.implicitRoots`, and the `label-presence`
|
|
141
|
+
* family. Every one of the rules below is registered and live.
|
|
142
|
+
*
|
|
143
|
+
* Two of them are worth knowing about at the call site:
|
|
144
|
+
*
|
|
145
|
+
* - `forbidPattern` carries its OWN {@link RuleMessage} inside the pattern
|
|
146
|
+
* rather than in a slot beside the other bounds, because a forbidden zone is
|
|
147
|
+
* not a bound that failed and its sentence never reads like one;
|
|
148
|
+
* - `label-presence` reads the subject's OWN `text`. A framework whose artefacts
|
|
149
|
+
* are named by a separate element beside them is asking a different question,
|
|
150
|
+
* and this family cannot answer it. BPMN names its steps in place, so it can.
|
|
151
|
+
*/
|
|
152
|
+
/**
|
|
153
|
+
* `eitherMin` was also shipped, and this pack deliberately does not use it.
|
|
154
|
+
*
|
|
155
|
+
* It and `forbidPattern: { maxIn: 1, maxOut: 1 }` select exactly the same set of
|
|
156
|
+
* nodes — the engine ships a test asserting they agree across the whole degree
|
|
157
|
+
* space — so {@link gatewayMustBranch} could be written either way. It is
|
|
158
|
+
* written as a forbidden zone because that is what its SENTENCE says: "this
|
|
159
|
+
* gateway neither splits nor merges" describes a shape the diagram has, not a
|
|
160
|
+
* count it is missing, and the data reads best when it says what the message
|
|
161
|
+
* says. Nothing is wrong with the other reading; a rule simply has to pick one.
|
|
162
|
+
*/
|
|
163
|
+
/**
|
|
164
|
+
* The one sanctioned sentence of a sequence flow: a flow object is followed by a
|
|
165
|
+
* flow object (p.95 — "a Sequence Flow connects Events, Activities and
|
|
166
|
+
* Gateways").
|
|
167
|
+
*
|
|
168
|
+
* Written on `bpmn:flow-object` rather than on the three families under it, which
|
|
169
|
+
* is what makes it ONE triplet instead of nine: `roleIsA` resolves it for every
|
|
170
|
+
* event, activity and gateway, and for whatever the descriptive profile adds
|
|
171
|
+
* under them later.
|
|
172
|
+
*
|
|
173
|
+
* Exported so a test asserts THIS table rather than a copy of it, and so B4
|
|
174
|
+
* declares the same alphabet it judges neutral links against without restating
|
|
175
|
+
* it — see {@link untypedFlow}.
|
|
176
|
+
*/
|
|
177
|
+
export declare const BPMN_SEQUENCE_MATRIX: readonly EndpointTriplet[];
|
|
178
|
+
/**
|
|
179
|
+
* The pack, whole: twenty-two rules, all registered, all live.
|
|
180
|
+
*
|
|
181
|
+
* Eight of them were authored ahead of the engine and sat in a held-out array
|
|
182
|
+
* for one review cycle, because two would have been actively WRONG meanwhile —
|
|
183
|
+
* an engine with no `ifPresent` reads B14/B15 as the unconditional "every pool
|
|
184
|
+
* holds a start event" the specification review removed, which fires on a
|
|
185
|
+
* conformant black-box pool. `claude/bpmn-engine-v2` (#145) landed every field
|
|
186
|
+
* they asked for, so the array is gone and the split with it.
|
|
187
|
+
*
|
|
188
|
+
* The twenty-second is B1a, and it is not a new REQUIREMENT: the no-self-loop
|
|
189
|
+
* clause left B1 so that each of the two could declare its own provenance
|
|
190
|
+
* honestly. Nothing new fires, nothing new is said, and the two i18n keys are
|
|
191
|
+
* the ones the clause already shipped.
|
|
192
|
+
*
|
|
193
|
+
* Every one of the twenty-two declares {@link ValidationRule.provenance}:
|
|
194
|
+
* twelve `standard`, each with its page; eight `recommendation`, each naming a
|
|
195
|
+
* linter or the sentence the specification merely permits; two
|
|
196
|
+
* `labre-convention`. Nothing here is `organization` — that source is reserved
|
|
197
|
+
* for the org profiles the PRD names, and no framework declares one yet.
|
|
198
|
+
*/
|
|
199
|
+
export declare const BPMN_RULES: readonly ValidationRule[];
|