yarramate 0.1.1 → 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/README.md +19 -4
- package/assets/likec4/specification.likec4 +500 -0
- package/dist/adapters/likec4-cli.js +1 -1
- package/dist/adapters/likec4-export.js +14 -1
- package/dist/adapters/likec4-project.js +16 -2
- package/dist/cli-support.d.ts +1 -1
- package/dist/cli-support.js +1 -1
- package/dist/cli.js +30 -10
- package/dist/compiler.js +111 -0
- package/package.json +3 -2
- package/schema/yarramate-core-contract.schema.json +2 -0
- package/schema/yarramate-document.schema.json +29 -0
- package/skills/yarramate-architecture/references/native-authoring.md +30 -1
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# YarraMate
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/yarramate)
|
|
4
|
+
[](https://github.com/yarrasys/yarramate/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/yarrasys/yarramate/actions/workflows/codeql.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
3
8
|
YarraMate is a tool-neutral semantic architecture engine and guided
|
|
4
9
|
methodology. It turns architectural intent into deterministic, testable
|
|
5
10
|
context shared by people and agents.
|
|
@@ -94,8 +99,16 @@ pnpm docs:dev
|
|
|
94
99
|
|
|
95
100
|
## CLI
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
Install the published executable or invoke it directly with `npx`:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
npm install --global yarramate
|
|
106
|
+
yarramate --help
|
|
107
|
+
|
|
108
|
+
npx yarramate check .yarramate/workspace.yaml
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
When developing the repository, build and invoke the same executable surface:
|
|
99
112
|
|
|
100
113
|
```sh
|
|
101
114
|
pnpm build
|
|
@@ -117,7 +130,7 @@ For a local consumer test, create a package artifact:
|
|
|
117
130
|
|
|
118
131
|
```sh
|
|
119
132
|
pnpm pack --pack-destination /tmp/yarramate-package
|
|
120
|
-
npm install --global /tmp/yarramate-package/yarramate
|
|
133
|
+
npm install --global /tmp/yarramate-package/yarramate-*.tgz
|
|
121
134
|
yarramate --help
|
|
122
135
|
```
|
|
123
136
|
|
|
@@ -169,6 +182,8 @@ You do not need to provide a solution, formal proposal, or implementation.
|
|
|
169
182
|
|
|
170
183
|
Read [CONTRIBUTING.md](CONTRIBUTING.md) before proposing changes to native
|
|
171
184
|
semantics or stable interfaces. Report suspected vulnerabilities according to
|
|
172
|
-
[SECURITY.md](SECURITY.md).
|
|
185
|
+
[SECURITY.md](SECURITY.md). Participation is governed by the
|
|
186
|
+
[Code of Conduct](CODE_OF_CONDUCT.md), and help channels are described in
|
|
187
|
+
[SUPPORT.md](SUPPORT.md).
|
|
173
188
|
|
|
174
189
|
YarraMate is available under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
// YarraMate semantic profile for LikeC4.
|
|
2
|
+
//
|
|
3
|
+
// This vocabulary is ArchiMate-inspired but independently expressed. The tags
|
|
4
|
+
// encode semantic coordinates; element kinds carry the human-facing notation.
|
|
5
|
+
specification {
|
|
6
|
+
color motivationColor #E8D7F1
|
|
7
|
+
color strategyColor #F3E5AB
|
|
8
|
+
color businessColor #FFF1B8
|
|
9
|
+
color applicationColor #C9E7FF
|
|
10
|
+
color technologyColor #D8F0D2
|
|
11
|
+
color physicalColor #D5E8D4
|
|
12
|
+
color implementationColor #F5D5CB
|
|
13
|
+
color compositeColor #E6E6E6
|
|
14
|
+
color relationColor #5B6470
|
|
15
|
+
|
|
16
|
+
tag layerMotivation
|
|
17
|
+
tag layerStrategy
|
|
18
|
+
tag layerBusiness
|
|
19
|
+
tag layerApplication
|
|
20
|
+
tag layerTechnology
|
|
21
|
+
tag layerPhysical
|
|
22
|
+
tag layerImplementation
|
|
23
|
+
tag layerComposite
|
|
24
|
+
|
|
25
|
+
tag aspectActive
|
|
26
|
+
tag aspectBehavior
|
|
27
|
+
tag aspectPassive
|
|
28
|
+
|
|
29
|
+
// Adapter-owned deployment presentation kinds.
|
|
30
|
+
deploymentNode environment {
|
|
31
|
+
notation 'Environment'
|
|
32
|
+
style { color technologyColor }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
deploymentNode zone {
|
|
36
|
+
notation 'Zone'
|
|
37
|
+
style { color compositeColor }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
deploymentNode host {
|
|
41
|
+
notation 'Host'
|
|
42
|
+
style { color technologyColor }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
deploymentNode runtime {
|
|
46
|
+
notation 'Runtime'
|
|
47
|
+
style { color applicationColor }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── Motivation ────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
element stakeholder {
|
|
53
|
+
#layerMotivation
|
|
54
|
+
notation 'Stakeholder'
|
|
55
|
+
style { shape person; color motivationColor }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
element driver {
|
|
59
|
+
#layerMotivation
|
|
60
|
+
notation 'Driver'
|
|
61
|
+
style { color motivationColor }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
element assessment {
|
|
65
|
+
#layerMotivation
|
|
66
|
+
notation 'Assessment'
|
|
67
|
+
style { color motivationColor }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
element goal {
|
|
71
|
+
#layerMotivation
|
|
72
|
+
notation 'Goal'
|
|
73
|
+
style { color motivationColor }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
element outcome {
|
|
77
|
+
#layerMotivation
|
|
78
|
+
notation 'Outcome'
|
|
79
|
+
style { color motivationColor }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
element principle {
|
|
83
|
+
#layerMotivation
|
|
84
|
+
notation 'Principle'
|
|
85
|
+
style { color motivationColor }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
element requirement {
|
|
89
|
+
#layerMotivation
|
|
90
|
+
notation 'Requirement'
|
|
91
|
+
style { color motivationColor }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
element constraint {
|
|
95
|
+
#layerMotivation
|
|
96
|
+
notation 'Constraint'
|
|
97
|
+
style { color motivationColor }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
element meaning {
|
|
101
|
+
#layerMotivation
|
|
102
|
+
notation 'Meaning'
|
|
103
|
+
style { color motivationColor }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
element value {
|
|
107
|
+
#layerMotivation
|
|
108
|
+
notation 'Value'
|
|
109
|
+
style { color motivationColor }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ── Strategy ──────────────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
element resource {
|
|
115
|
+
#layerStrategy #aspectActive
|
|
116
|
+
notation 'Resource'
|
|
117
|
+
style { color strategyColor }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
element capability {
|
|
121
|
+
#layerStrategy #aspectBehavior
|
|
122
|
+
notation 'Capability'
|
|
123
|
+
style { color strategyColor }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
element valueStream {
|
|
127
|
+
#layerStrategy #aspectBehavior
|
|
128
|
+
notation 'Value stream'
|
|
129
|
+
style { color strategyColor }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
element courseOfAction {
|
|
133
|
+
#layerStrategy #aspectBehavior
|
|
134
|
+
notation 'Course of action'
|
|
135
|
+
style { color strategyColor }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── Business layer ────────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
element businessActor {
|
|
141
|
+
#layerBusiness #aspectActive
|
|
142
|
+
notation 'Business actor'
|
|
143
|
+
style { shape person; color businessColor }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
element businessRole {
|
|
147
|
+
#layerBusiness #aspectActive
|
|
148
|
+
notation 'Business role'
|
|
149
|
+
style { color businessColor }
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
element businessCollaboration {
|
|
153
|
+
#layerBusiness #aspectActive
|
|
154
|
+
notation 'Business collaboration'
|
|
155
|
+
style { color businessColor; multiple true }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
element businessInterface {
|
|
159
|
+
#layerBusiness #aspectActive
|
|
160
|
+
notation 'Business interface'
|
|
161
|
+
style { color businessColor }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
element businessProcess {
|
|
165
|
+
#layerBusiness #aspectBehavior
|
|
166
|
+
notation 'Business process'
|
|
167
|
+
style { color businessColor }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
element businessFunction {
|
|
171
|
+
#layerBusiness #aspectBehavior
|
|
172
|
+
notation 'Business function'
|
|
173
|
+
style { color businessColor }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
element businessInteraction {
|
|
177
|
+
#layerBusiness #aspectBehavior
|
|
178
|
+
notation 'Business interaction'
|
|
179
|
+
style { color businessColor }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
element businessEvent {
|
|
183
|
+
#layerBusiness #aspectBehavior
|
|
184
|
+
notation 'Business event'
|
|
185
|
+
style { color businessColor }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
element businessService {
|
|
189
|
+
#layerBusiness #aspectBehavior
|
|
190
|
+
notation 'Business service'
|
|
191
|
+
style { color businessColor }
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
element businessObject {
|
|
195
|
+
#layerBusiness #aspectPassive
|
|
196
|
+
notation 'Business object'
|
|
197
|
+
style { color businessColor }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
element contract {
|
|
201
|
+
#layerBusiness #aspectPassive
|
|
202
|
+
notation 'Contract'
|
|
203
|
+
style { color businessColor }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
element representation {
|
|
207
|
+
#layerBusiness #aspectPassive
|
|
208
|
+
notation 'Representation'
|
|
209
|
+
style { color businessColor }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
element product {
|
|
213
|
+
#layerBusiness #aspectPassive
|
|
214
|
+
notation 'Product'
|
|
215
|
+
style { color businessColor }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ── Application layer ─────────────────────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
element applicationComponent {
|
|
221
|
+
#layerApplication #aspectActive
|
|
222
|
+
notation 'Application component'
|
|
223
|
+
style { shape component; color applicationColor }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
element applicationCollaboration {
|
|
227
|
+
#layerApplication #aspectActive
|
|
228
|
+
notation 'Application collaboration'
|
|
229
|
+
style { color applicationColor; multiple true }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
element applicationInterface {
|
|
233
|
+
#layerApplication #aspectActive
|
|
234
|
+
notation 'Application interface'
|
|
235
|
+
style { color applicationColor }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
element applicationFunction {
|
|
239
|
+
#layerApplication #aspectBehavior
|
|
240
|
+
notation 'Application function'
|
|
241
|
+
style { color applicationColor }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
element applicationInteraction {
|
|
245
|
+
#layerApplication #aspectBehavior
|
|
246
|
+
notation 'Application interaction'
|
|
247
|
+
style { color applicationColor }
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
element applicationProcess {
|
|
251
|
+
#layerApplication #aspectBehavior
|
|
252
|
+
notation 'Application process'
|
|
253
|
+
style { color applicationColor }
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
element applicationEvent {
|
|
257
|
+
#layerApplication #aspectBehavior
|
|
258
|
+
notation 'Application event'
|
|
259
|
+
style { color applicationColor }
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
element applicationService {
|
|
263
|
+
#layerApplication #aspectBehavior
|
|
264
|
+
notation 'Application service'
|
|
265
|
+
style { color applicationColor }
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
element dataObject {
|
|
269
|
+
#layerApplication #aspectPassive
|
|
270
|
+
notation 'Data object'
|
|
271
|
+
style { shape storage; color applicationColor }
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ── Technology layer ──────────────────────────────────────────────────────
|
|
275
|
+
|
|
276
|
+
element node {
|
|
277
|
+
#layerTechnology #aspectActive
|
|
278
|
+
notation 'Node'
|
|
279
|
+
style { color technologyColor }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
element device {
|
|
283
|
+
#layerTechnology #aspectActive
|
|
284
|
+
notation 'Device'
|
|
285
|
+
style { color technologyColor }
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
element systemSoftware {
|
|
289
|
+
#layerTechnology #aspectActive
|
|
290
|
+
notation 'System software'
|
|
291
|
+
style { color technologyColor }
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
element technologyCollaboration {
|
|
295
|
+
#layerTechnology #aspectActive
|
|
296
|
+
notation 'Technology collaboration'
|
|
297
|
+
style { color technologyColor; multiple true }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
element technologyInterface {
|
|
301
|
+
#layerTechnology #aspectActive
|
|
302
|
+
notation 'Technology interface'
|
|
303
|
+
style { color technologyColor }
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
element path {
|
|
307
|
+
#layerTechnology #aspectActive
|
|
308
|
+
notation 'Path'
|
|
309
|
+
style { color technologyColor }
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
element communicationNetwork {
|
|
313
|
+
#layerTechnology #aspectActive
|
|
314
|
+
notation 'Communication network'
|
|
315
|
+
style { color technologyColor }
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
element technologyFunction {
|
|
319
|
+
#layerTechnology #aspectBehavior
|
|
320
|
+
notation 'Technology function'
|
|
321
|
+
style { color technologyColor }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
element technologyProcess {
|
|
325
|
+
#layerTechnology #aspectBehavior
|
|
326
|
+
notation 'Technology process'
|
|
327
|
+
style { color technologyColor }
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
element technologyInteraction {
|
|
331
|
+
#layerTechnology #aspectBehavior
|
|
332
|
+
notation 'Technology interaction'
|
|
333
|
+
style { color technologyColor }
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
element technologyEvent {
|
|
337
|
+
#layerTechnology #aspectBehavior
|
|
338
|
+
notation 'Technology event'
|
|
339
|
+
style { color technologyColor }
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
element technologyService {
|
|
343
|
+
#layerTechnology #aspectBehavior
|
|
344
|
+
notation 'Technology service'
|
|
345
|
+
style { color technologyColor }
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
element artifact {
|
|
349
|
+
#layerTechnology #aspectPassive
|
|
350
|
+
notation 'Artifact'
|
|
351
|
+
style { color technologyColor }
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ── Physical layer ────────────────────────────────────────────────────────
|
|
355
|
+
|
|
356
|
+
element equipment {
|
|
357
|
+
#layerPhysical #aspectActive
|
|
358
|
+
notation 'Equipment'
|
|
359
|
+
style { color physicalColor }
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
element facility {
|
|
363
|
+
#layerPhysical #aspectActive
|
|
364
|
+
notation 'Facility'
|
|
365
|
+
style { color physicalColor }
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
element distributionNetwork {
|
|
369
|
+
#layerPhysical #aspectActive
|
|
370
|
+
notation 'Distribution network'
|
|
371
|
+
style { color physicalColor }
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
element material {
|
|
375
|
+
#layerPhysical #aspectPassive
|
|
376
|
+
notation 'Material'
|
|
377
|
+
style { color physicalColor }
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ── Implementation and migration ─────────────────────────────────────────
|
|
381
|
+
|
|
382
|
+
element workPackage {
|
|
383
|
+
#layerImplementation #aspectBehavior
|
|
384
|
+
notation 'Work package'
|
|
385
|
+
style { color implementationColor }
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
element deliverable {
|
|
389
|
+
#layerImplementation #aspectPassive
|
|
390
|
+
notation 'Deliverable'
|
|
391
|
+
style { color implementationColor }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
element implementationEvent {
|
|
395
|
+
#layerImplementation #aspectBehavior
|
|
396
|
+
notation 'Implementation event'
|
|
397
|
+
style { color implementationColor }
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
element plateau {
|
|
401
|
+
#layerImplementation
|
|
402
|
+
notation 'Plateau'
|
|
403
|
+
style { color implementationColor }
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
element gap {
|
|
407
|
+
#layerImplementation
|
|
408
|
+
notation 'Gap'
|
|
409
|
+
style { color implementationColor }
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// ── Composite and relationship connectors ────────────────────────────────
|
|
413
|
+
|
|
414
|
+
element grouping {
|
|
415
|
+
#layerComposite
|
|
416
|
+
notation 'Grouping'
|
|
417
|
+
style { color compositeColor; border dashed }
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
element location {
|
|
421
|
+
#layerComposite
|
|
422
|
+
notation 'Location'
|
|
423
|
+
style { color compositeColor }
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
element andJunction {
|
|
427
|
+
#layerComposite
|
|
428
|
+
notation 'AND junction'
|
|
429
|
+
style { color compositeColor }
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
element orJunction {
|
|
433
|
+
#layerComposite
|
|
434
|
+
notation 'OR junction'
|
|
435
|
+
style { color compositeColor }
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ── Relationships ─────────────────────────────────────────────────────────
|
|
439
|
+
|
|
440
|
+
relationship composition {
|
|
441
|
+
description 'Strong whole-part relationship.'
|
|
442
|
+
color relationColor
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
relationship aggregation {
|
|
446
|
+
description 'Weak whole-part relationship.'
|
|
447
|
+
color relationColor
|
|
448
|
+
line dashed
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
relationship assignment {
|
|
452
|
+
description 'Allocation of responsibility, execution, or use.'
|
|
453
|
+
color relationColor
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
relationship realization {
|
|
457
|
+
description 'Implementation or fulfillment of a more abstract concept.'
|
|
458
|
+
color relationColor
|
|
459
|
+
line dashed
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
relationship serving {
|
|
463
|
+
description 'Functionality made available to another concept.'
|
|
464
|
+
color relationColor
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
relationship access {
|
|
468
|
+
description 'Use, creation, modification, or reading of passive structure.'
|
|
469
|
+
color relationColor
|
|
470
|
+
line dashed
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
relationship influence {
|
|
474
|
+
description 'Effect on a motivation concept.'
|
|
475
|
+
color relationColor
|
|
476
|
+
line dotted
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
relationship association {
|
|
480
|
+
description 'Semantically relevant connection not expressed more specifically.'
|
|
481
|
+
color relationColor
|
|
482
|
+
line dashed
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
relationship triggering {
|
|
486
|
+
description 'Temporal or causal precedence between behaviors or events.'
|
|
487
|
+
color relationColor
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
relationship flow {
|
|
491
|
+
description 'Transfer of information, value, goods, or another object.'
|
|
492
|
+
color relationColor
|
|
493
|
+
line dashed
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
relationship specialization {
|
|
497
|
+
description 'Concept is a more specific form of another concept.'
|
|
498
|
+
color relationColor
|
|
499
|
+
}
|
|
500
|
+
}
|
|
@@ -151,7 +151,7 @@ const publishGeneratedProject = (cwd, outputDirectory, input) => {
|
|
|
151
151
|
else {
|
|
152
152
|
mkdirSync(projectPath, { recursive: true });
|
|
153
153
|
}
|
|
154
|
-
const specificationSource = readFileSync(fileURLToPath(new URL('
|
|
154
|
+
const specificationSource = readFileSync(fileURLToPath(new URL('../../assets/likec4/specification.likec4', import.meta.url)));
|
|
155
155
|
const configSource = `${JSON.stringify({
|
|
156
156
|
$schema: 'https://likec4.dev/schemas/config.json',
|
|
157
157
|
name: input.projectName,
|
|
@@ -133,6 +133,10 @@ export function exportLikeC4(projection, mapping, kindMapping, options = {}) {
|
|
|
133
133
|
'constraints',
|
|
134
134
|
referencesFor(projection.claims, concept.id, 'yarramate/constraint/requires'),
|
|
135
135
|
],
|
|
136
|
+
[
|
|
137
|
+
'references',
|
|
138
|
+
referencesFor(projection.claims, concept.id, 'yarramate/reference/refers-to'),
|
|
139
|
+
],
|
|
136
140
|
], ' ');
|
|
137
141
|
if (description === undefined && metadata.length === 0) {
|
|
138
142
|
lines.push(` ${external} = ${kind} ${quote(name)}`);
|
|
@@ -159,6 +163,7 @@ export function exportLikeC4(projection, mapping, kindMapping, options = {}) {
|
|
|
159
163
|
if (source === undefined || target === undefined)
|
|
160
164
|
continue;
|
|
161
165
|
const name = valueFor(projection.claims, relationship.id, 'yarramate/relationship/name');
|
|
166
|
+
const description = valueFor(projection.claims, relationship.id, 'yarramate/relationship/description');
|
|
162
167
|
const metadata = metadataLines([
|
|
163
168
|
['yarramateId', relationship.id],
|
|
164
169
|
['yarramateKind', structural.predicate],
|
|
@@ -175,8 +180,16 @@ export function exportLikeC4(projection, mapping, kindMapping, options = {}) {
|
|
|
175
180
|
'content',
|
|
176
181
|
valueFor(projection.claims, relationship.id, 'yarramate/flow/content'),
|
|
177
182
|
],
|
|
183
|
+
[
|
|
184
|
+
'references',
|
|
185
|
+
referencesFor(projection.claims, relationship.id, 'yarramate/reference/refers-to'),
|
|
186
|
+
],
|
|
178
187
|
], ' ');
|
|
179
|
-
lines.push(` ${source} -[${externalRelationshipKind.get(structural.predicate) ?? kindId(structural.predicate)}]-> ${target}${name === undefined ? '' : ` ${quote(name)}`}${metadata.length === 0 ? '' : ' {'}`, ...
|
|
188
|
+
lines.push(` ${source} -[${externalRelationshipKind.get(structural.predicate) ?? kindId(structural.predicate)}]-> ${target}${name === undefined ? '' : ` ${quote(name)}`}${description === undefined && metadata.length === 0 ? '' : ' {'}`, ...(description === undefined
|
|
189
|
+
? []
|
|
190
|
+
: [` description ${quote(description)}`]), ...metadata, ...(description === undefined && metadata.length === 0
|
|
191
|
+
? []
|
|
192
|
+
: [' }']));
|
|
180
193
|
}
|
|
181
194
|
const viewId = identifier.test(projection.projection.split('@')[0] ?? '')
|
|
182
195
|
? projection.projection.split('@')[0]
|
|
@@ -73,7 +73,7 @@ const viewBody = ({ id, prepared, dynamic, deployment, }) => {
|
|
|
73
73
|
}
|
|
74
74
|
if (dynamic !== undefined) {
|
|
75
75
|
const claimsById = new Map(prepared.projection.claims.map((claim) => [claim.id, claim]));
|
|
76
|
-
const lines = dynamic.steps.
|
|
76
|
+
const lines = dynamic.steps.flatMap((step) => {
|
|
77
77
|
const structural = claimsById.get(step.relationship);
|
|
78
78
|
const source = externalByNative.get(structural.subject);
|
|
79
79
|
const target = 'ref' in structural.object
|
|
@@ -86,7 +86,21 @@ const viewBody = ({ id, prepared, dynamic, deployment, }) => {
|
|
|
86
86
|
(declaredTitle !== undefined && 'value' in declaredTitle.object
|
|
87
87
|
? declaredTitle.object.value
|
|
88
88
|
: undefined);
|
|
89
|
-
|
|
89
|
+
const declaredDescription = prepared.projection.claims.find((claim) => claim.subject === step.relationship &&
|
|
90
|
+
claim.predicate === 'yarramate/relationship/description' &&
|
|
91
|
+
'value' in claim.object);
|
|
92
|
+
const description = declaredDescription !== undefined &&
|
|
93
|
+
'value' in declaredDescription.object
|
|
94
|
+
? declaredDescription.object.value
|
|
95
|
+
: undefined;
|
|
96
|
+
const statement = ` ${source} -> ${target}${title === undefined ? '' : ` ${quote(title)}`}`;
|
|
97
|
+
return description === undefined
|
|
98
|
+
? [statement]
|
|
99
|
+
: [
|
|
100
|
+
`${statement} {`,
|
|
101
|
+
` description ${quote(description)}`,
|
|
102
|
+
' }',
|
|
103
|
+
];
|
|
90
104
|
});
|
|
91
105
|
const viewId = id ?? prepared.projection.projection.split('@')[0];
|
|
92
106
|
return [
|
package/dist/cli-support.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface CliResult {
|
|
|
5
5
|
readonly stderr: string;
|
|
6
6
|
}
|
|
7
7
|
export declare const isMainModule: (moduleUrl: string, entrypoint: string | undefined) => boolean;
|
|
8
|
-
export declare const usage = "Usage:\n yarramate init <directory>\n yarramate add <document.yaml> --id <id> --kind <kind> --name <name> [--status <status>] [--description <text>] [--owner <ref>] [--constraint <id>=<ref> ...] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate connect <document.yaml> --id <id> --kind <kind> --from <ref> --to <ref> [--name <name>] [--status <status>] [--mode <mode>] [--content <text>] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate check <source.yaml> [source.yaml ...] [--json]\n yarramate compile <source.yaml> [source.yaml ...]\n yarramate context <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate view <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate compare <from-state> <to-state> <source.yaml> [source.yaml ...]\n yarramate evidence <evidence.yaml> <source.yaml> [source.yaml ...]\n yarramate reconcile <workspace.yaml>\n";
|
|
8
|
+
export declare const usage = "Usage:\n yarramate init <directory>\n yarramate add <document.yaml> --id <id> --kind <kind> --name <name> [--status <status>] [--description <text>] [--owner <ref>] [--constraint <id>=<ref> ...] [--reference <id>=<ref> ...] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate connect <document.yaml> --id <id> --kind <kind> --from <ref> --to <ref> [--name <name>] [--description <text>] [--status <status>] [--mode <mode>] [--content <text>] [--reference <id>=<ref> ...] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate check <source.yaml> [source.yaml ...] [--json]\n yarramate compile <source.yaml> [source.yaml ...]\n yarramate context <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate view <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate compare <from-state> <to-state> <source.yaml> [source.yaml ...]\n yarramate evidence <evidence.yaml> <source.yaml> [source.yaml ...]\n yarramate reconcile <workspace.yaml>\n";
|
|
9
9
|
export declare const diagnosticJson: (diagnostics: unknown) => string;
|
|
10
10
|
export declare const checkResultJson: (ok: boolean, diagnostics: unknown) => string;
|
|
11
11
|
export declare const humanDiagnostics: (diagnostics: readonly Pick<Diagnostic, "path" | "line" | "column" | "code" | "message">[]) => string;
|
package/dist/cli-support.js
CHANGED
|
@@ -14,7 +14,7 @@ export const isMainModule = (moduleUrl, entrypoint) => {
|
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
|
-
export const usage = 'Usage:\n yarramate init <directory>\n yarramate add <document.yaml> --id <id> --kind <kind> --name <name> [--status <status>] [--description <text>] [--owner <ref>] [--constraint <id>=<ref> ...] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate connect <document.yaml> --id <id> --kind <kind> --from <ref> --to <ref> [--name <name>] [--status <status>] [--mode <mode>] [--content <text>] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate check <source.yaml> [source.yaml ...] [--json]\n yarramate compile <source.yaml> [source.yaml ...]\n yarramate context <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate view <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate compare <from-state> <to-state> <source.yaml> [source.yaml ...]\n yarramate evidence <evidence.yaml> <source.yaml> [source.yaml ...]\n yarramate reconcile <workspace.yaml>\n';
|
|
17
|
+
export const usage = 'Usage:\n yarramate init <directory>\n yarramate add <document.yaml> --id <id> --kind <kind> --name <name> [--status <status>] [--description <text>] [--owner <ref>] [--constraint <id>=<ref> ...] [--reference <id>=<ref> ...] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate connect <document.yaml> --id <id> --kind <kind> --from <ref> --to <ref> [--name <name>] [--description <text>] [--status <status>] [--mode <mode>] [--content <text>] [--reference <id>=<ref> ...] [--present-in <state-ref> ...] [--source <source.yaml> ...]\n yarramate check <source.yaml> [source.yaml ...] [--json]\n yarramate compile <source.yaml> [source.yaml ...]\n yarramate context <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate view <projection.yaml> <source.yaml> [source.yaml ...]\n yarramate compare <from-state> <to-state> <source.yaml> [source.yaml ...]\n yarramate evidence <evidence.yaml> <source.yaml> [source.yaml ...]\n yarramate reconcile <workspace.yaml>\n';
|
|
18
18
|
export const diagnosticJson = (diagnostics) => `${JSON.stringify({
|
|
19
19
|
format: 'yarramate/diagnostic-result/v1',
|
|
20
20
|
diagnostics,
|
package/dist/cli.js
CHANGED
|
@@ -301,6 +301,7 @@ const oneFlag = (flags, flag) => {
|
|
|
301
301
|
};
|
|
302
302
|
const hasRepeatedSingletonFlag = (flags) => [...flags.entries()].some(([flag, values]) => flag !== '--source' &&
|
|
303
303
|
flag !== '--constraint' &&
|
|
304
|
+
flag !== '--reference' &&
|
|
304
305
|
flag !== '--present-in' &&
|
|
305
306
|
values.length !== 1);
|
|
306
307
|
const appendBlockItem = (document, collection, item) => {
|
|
@@ -310,6 +311,20 @@ const appendBlockItem = (document, collection, item) => {
|
|
|
310
311
|
sequence.flow = false;
|
|
311
312
|
}
|
|
312
313
|
};
|
|
314
|
+
const identifiedReferences = (values) => {
|
|
315
|
+
const parsed = values.map((value) => {
|
|
316
|
+
const separator = value.indexOf('=');
|
|
317
|
+
return separator <= 0 || separator === value.length - 1
|
|
318
|
+
? undefined
|
|
319
|
+
: {
|
|
320
|
+
id: value.slice(0, separator),
|
|
321
|
+
ref: value.slice(separator + 1),
|
|
322
|
+
};
|
|
323
|
+
});
|
|
324
|
+
return parsed.some((reference) => reference === undefined)
|
|
325
|
+
? undefined
|
|
326
|
+
: parsed;
|
|
327
|
+
};
|
|
313
328
|
const runAdd = (options, cwd) => {
|
|
314
329
|
const parsed = parseFlags(options);
|
|
315
330
|
if (parsed === undefined) {
|
|
@@ -323,6 +338,7 @@ const runAdd = (options, cwd) => {
|
|
|
323
338
|
'--description',
|
|
324
339
|
'--owner',
|
|
325
340
|
'--constraint',
|
|
341
|
+
'--reference',
|
|
326
342
|
'--present-in',
|
|
327
343
|
'--source',
|
|
328
344
|
]);
|
|
@@ -336,16 +352,9 @@ const runAdd = (options, cwd) => {
|
|
|
336
352
|
if (id === undefined || kind === undefined || name === undefined) {
|
|
337
353
|
return { exitCode: 2, stdout: '', stderr: usage };
|
|
338
354
|
}
|
|
339
|
-
const constraints = (parsed.flags.get('--constraint') ?? [])
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
? undefined
|
|
343
|
-
: {
|
|
344
|
-
id: value.slice(0, separator),
|
|
345
|
-
ref: value.slice(separator + 1),
|
|
346
|
-
};
|
|
347
|
-
});
|
|
348
|
-
if (constraints.some((constraint) => constraint === undefined)) {
|
|
355
|
+
const constraints = identifiedReferences(parsed.flags.get('--constraint') ?? []);
|
|
356
|
+
const references = identifiedReferences(parsed.flags.get('--reference') ?? []);
|
|
357
|
+
if (constraints === undefined || references === undefined) {
|
|
349
358
|
return { exitCode: 2, stdout: '', stderr: usage };
|
|
350
359
|
}
|
|
351
360
|
try {
|
|
@@ -365,6 +374,7 @@ const runAdd = (options, cwd) => {
|
|
|
365
374
|
? {}
|
|
366
375
|
: { owner: oneFlag(parsed.flags, '--owner') }),
|
|
367
376
|
...(constraints.length === 0 ? {} : { constraints }),
|
|
377
|
+
...(references.length === 0 ? {} : { references }),
|
|
368
378
|
...(parsed.flags.get('--present-in') === undefined
|
|
369
379
|
? {}
|
|
370
380
|
: { presentIn: parsed.flags.get('--present-in') }),
|
|
@@ -417,9 +427,11 @@ const runConnect = (options, cwd) => {
|
|
|
417
427
|
'--from',
|
|
418
428
|
'--to',
|
|
419
429
|
'--name',
|
|
430
|
+
'--description',
|
|
420
431
|
'--status',
|
|
421
432
|
'--mode',
|
|
422
433
|
'--content',
|
|
434
|
+
'--reference',
|
|
423
435
|
'--present-in',
|
|
424
436
|
'--source',
|
|
425
437
|
]);
|
|
@@ -437,6 +449,10 @@ const runConnect = (options, cwd) => {
|
|
|
437
449
|
to === undefined) {
|
|
438
450
|
return { exitCode: 2, stdout: '', stderr: usage };
|
|
439
451
|
}
|
|
452
|
+
const references = identifiedReferences(parsed.flags.get('--reference') ?? []);
|
|
453
|
+
if (references === undefined) {
|
|
454
|
+
return { exitCode: 2, stdout: '', stderr: usage };
|
|
455
|
+
}
|
|
440
456
|
try {
|
|
441
457
|
const absolutePath = resolve(cwd, parsed.path);
|
|
442
458
|
const document = parseDocument(readFileSync(absolutePath, 'utf8'));
|
|
@@ -448,6 +464,9 @@ const runConnect = (options, cwd) => {
|
|
|
448
464
|
...(oneFlag(parsed.flags, '--name') === undefined
|
|
449
465
|
? {}
|
|
450
466
|
: { name: oneFlag(parsed.flags, '--name') }),
|
|
467
|
+
...(oneFlag(parsed.flags, '--description') === undefined
|
|
468
|
+
? {}
|
|
469
|
+
: { description: oneFlag(parsed.flags, '--description') }),
|
|
451
470
|
...(oneFlag(parsed.flags, '--status') === undefined
|
|
452
471
|
? {}
|
|
453
472
|
: { status: oneFlag(parsed.flags, '--status') }),
|
|
@@ -457,6 +476,7 @@ const runConnect = (options, cwd) => {
|
|
|
457
476
|
...(oneFlag(parsed.flags, '--content') === undefined
|
|
458
477
|
? {}
|
|
459
478
|
: { content: oneFlag(parsed.flags, '--content') }),
|
|
479
|
+
...(references.length === 0 ? {} : { references }),
|
|
460
480
|
...(parsed.flags.get('--present-in') === undefined
|
|
461
481
|
? {}
|
|
462
482
|
: { presentIn: parsed.flags.get('--present-in') }),
|
package/dist/compiler.js
CHANGED
|
@@ -376,6 +376,11 @@ function compileWorkspaceResolved(sources) {
|
|
|
376
376
|
])));
|
|
377
377
|
const qualifyReference = (documentId, reference) => reference.includes('#') ? reference : `${documentId}#${reference}`;
|
|
378
378
|
const architectureStateIds = new Set(documents.flatMap(({ value }) => (value.states ?? []).map((state) => `${value.id}#${state.id}`)));
|
|
379
|
+
const subjectIds = new Set(documents.flatMap(({ value }) => [
|
|
380
|
+
...(value.states ?? []).map((state) => `${value.id}#${state.id}`),
|
|
381
|
+
...value.concepts.map((concept) => `${value.id}#${concept.id}`),
|
|
382
|
+
...value.relationships.map((relationship) => `${value.id}#${relationship.id}`),
|
|
383
|
+
]));
|
|
379
384
|
const architectureStateAfter = new Map(documents.flatMap(({ value }) => (value.states ?? []).flatMap((state) => state.after === undefined
|
|
380
385
|
? []
|
|
381
386
|
: [
|
|
@@ -582,6 +587,36 @@ function compileWorkspaceResolved(sources) {
|
|
|
582
587
|
});
|
|
583
588
|
}
|
|
584
589
|
}
|
|
590
|
+
const seenReferenceIds = new Set();
|
|
591
|
+
for (const [referenceIndex, reference] of (concept.references ?? []).entries()) {
|
|
592
|
+
if (seenReferenceIds.has(reference.id)) {
|
|
593
|
+
const pointer = `/concepts/${index}/references/${referenceIndex}/id`;
|
|
594
|
+
const source = location(['concepts', index, 'references', referenceIndex, 'id'], pointer);
|
|
595
|
+
diagnostics.push({
|
|
596
|
+
severity: 'error',
|
|
597
|
+
code: 'YM309',
|
|
598
|
+
message: `Duplicate reference ID "${reference.id}"`,
|
|
599
|
+
path: input.path,
|
|
600
|
+
pointer,
|
|
601
|
+
line: source.line,
|
|
602
|
+
column: source.column,
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
seenReferenceIds.add(reference.id);
|
|
606
|
+
if (!subjectIds.has(qualifyReference(value.id, reference.ref))) {
|
|
607
|
+
const pointer = `/concepts/${index}/references/${referenceIndex}/ref`;
|
|
608
|
+
const source = location(['concepts', index, 'references', referenceIndex, 'ref'], pointer);
|
|
609
|
+
diagnostics.push({
|
|
610
|
+
severity: 'error',
|
|
611
|
+
code: 'YM308',
|
|
612
|
+
message: `Unresolved subject reference "${reference.ref}"`,
|
|
613
|
+
path: input.path,
|
|
614
|
+
pointer,
|
|
615
|
+
line: source.line,
|
|
616
|
+
column: source.column,
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
585
620
|
for (const [stateIndex, state] of (concept.presentIn ?? []).entries()) {
|
|
586
621
|
if (!architectureStateIds.has(qualifyReference(value.id, state))) {
|
|
587
622
|
const pointer = `/concepts/${index}/presentIn/${stateIndex}`;
|
|
@@ -599,6 +634,48 @@ function compileWorkspaceResolved(sources) {
|
|
|
599
634
|
}
|
|
600
635
|
}
|
|
601
636
|
for (const [index, relationship] of value.relationships.entries()) {
|
|
637
|
+
const seenReferenceIds = new Set();
|
|
638
|
+
for (const [referenceIndex, reference] of (relationship.references ?? []).entries()) {
|
|
639
|
+
if (seenReferenceIds.has(reference.id)) {
|
|
640
|
+
const pointer = `/relationships/${index}/references/${referenceIndex}/id`;
|
|
641
|
+
const source = location([
|
|
642
|
+
'relationships',
|
|
643
|
+
index,
|
|
644
|
+
'references',
|
|
645
|
+
referenceIndex,
|
|
646
|
+
'id',
|
|
647
|
+
], pointer);
|
|
648
|
+
diagnostics.push({
|
|
649
|
+
severity: 'error',
|
|
650
|
+
code: 'YM309',
|
|
651
|
+
message: `Duplicate reference ID "${reference.id}"`,
|
|
652
|
+
path: input.path,
|
|
653
|
+
pointer,
|
|
654
|
+
line: source.line,
|
|
655
|
+
column: source.column,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
seenReferenceIds.add(reference.id);
|
|
659
|
+
if (!subjectIds.has(qualifyReference(value.id, reference.ref))) {
|
|
660
|
+
const pointer = `/relationships/${index}/references/${referenceIndex}/ref`;
|
|
661
|
+
const source = location([
|
|
662
|
+
'relationships',
|
|
663
|
+
index,
|
|
664
|
+
'references',
|
|
665
|
+
referenceIndex,
|
|
666
|
+
'ref',
|
|
667
|
+
], pointer);
|
|
668
|
+
diagnostics.push({
|
|
669
|
+
severity: 'error',
|
|
670
|
+
code: 'YM308',
|
|
671
|
+
message: `Unresolved subject reference "${reference.ref}"`,
|
|
672
|
+
path: input.path,
|
|
673
|
+
pointer,
|
|
674
|
+
line: source.line,
|
|
675
|
+
column: source.column,
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
}
|
|
602
679
|
for (const [stateIndex, state] of (relationship.presentIn ?? []).entries()) {
|
|
603
680
|
const stateIdentity = qualifyReference(value.id, state);
|
|
604
681
|
if (!architectureStateIds.has(stateIdentity)) {
|
|
@@ -785,6 +862,18 @@ function compileWorkspaceResolved(sources) {
|
|
|
785
862
|
source: location(['concepts', index, 'constraints', constraintIndex, 'ref'], `/concepts/${index}/constraints/${constraintIndex}/ref`),
|
|
786
863
|
});
|
|
787
864
|
}
|
|
865
|
+
for (const [referenceIndex, reference] of (concept.references ?? []).entries()) {
|
|
866
|
+
claims.push({
|
|
867
|
+
id: `${subject}~reference-${reference.id}`,
|
|
868
|
+
subject,
|
|
869
|
+
predicate: 'yarramate/reference/refers-to',
|
|
870
|
+
object: {
|
|
871
|
+
ref: qualifyReference(value.id, reference.ref),
|
|
872
|
+
},
|
|
873
|
+
origin: 'declared',
|
|
874
|
+
source: location(['concepts', index, 'references', referenceIndex, 'ref'], `/concepts/${index}/references/${referenceIndex}/ref`),
|
|
875
|
+
});
|
|
876
|
+
}
|
|
788
877
|
for (const [stateIndex, state] of (concept.presentIn ?? []).entries()) {
|
|
789
878
|
const stateIdentity = qualifyReference(value.id, state);
|
|
790
879
|
claims.push({
|
|
@@ -819,6 +908,16 @@ function compileWorkspaceResolved(sources) {
|
|
|
819
908
|
source: location(['relationships', index, 'name'], `/relationships/${index}/name`),
|
|
820
909
|
});
|
|
821
910
|
}
|
|
911
|
+
if (relationship.description !== undefined) {
|
|
912
|
+
claims.push({
|
|
913
|
+
id: `${id}~description`,
|
|
914
|
+
subject: id,
|
|
915
|
+
predicate: 'yarramate/relationship/description',
|
|
916
|
+
object: { value: relationship.description },
|
|
917
|
+
origin: 'declared',
|
|
918
|
+
source: location(['relationships', index, 'description'], `/relationships/${index}/description`),
|
|
919
|
+
});
|
|
920
|
+
}
|
|
822
921
|
if (relationship.mode !== undefined) {
|
|
823
922
|
claims.push({
|
|
824
923
|
id: `${id}~mode`,
|
|
@@ -849,6 +948,18 @@ function compileWorkspaceResolved(sources) {
|
|
|
849
948
|
source: location(['relationships', index, 'status'], `/relationships/${index}/status`),
|
|
850
949
|
});
|
|
851
950
|
}
|
|
951
|
+
for (const [referenceIndex, reference] of (relationship.references ?? []).entries()) {
|
|
952
|
+
claims.push({
|
|
953
|
+
id: `${id}~reference-${reference.id}`,
|
|
954
|
+
subject: id,
|
|
955
|
+
predicate: 'yarramate/reference/refers-to',
|
|
956
|
+
object: {
|
|
957
|
+
ref: qualifyReference(value.id, reference.ref),
|
|
958
|
+
},
|
|
959
|
+
origin: 'declared',
|
|
960
|
+
source: location(['relationships', index, 'references', referenceIndex, 'ref'], `/relationships/${index}/references/${referenceIndex}/ref`),
|
|
961
|
+
});
|
|
962
|
+
}
|
|
852
963
|
for (const [stateIndex, state] of (relationship.presentIn ?? []).entries()) {
|
|
853
964
|
const stateIdentity = qualifyReference(value.id, state);
|
|
854
965
|
claims.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yarramate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Tool-neutral semantic architecture engine and guided methodology",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
26
|
+
"assets/likec4",
|
|
26
27
|
"schema",
|
|
27
28
|
"skills/yarramate-architecture",
|
|
28
29
|
"docs/CONSUMING-YARRAMATE.md"
|
|
@@ -78,7 +79,7 @@
|
|
|
78
79
|
"build": "tsc -p tsconfig.build.json",
|
|
79
80
|
"prepack": "pnpm build",
|
|
80
81
|
"docs:dev": "pnpm self:export:likec4 && likec4 serve .yarramate-out/likec4",
|
|
81
|
-
"format": "likec4 format
|
|
82
|
+
"format": "likec4 format assets/likec4",
|
|
82
83
|
"self:check": "pnpm build && node dist/cli.js check .yarramate/workspace.yaml",
|
|
83
84
|
"self:check:json": "pnpm build && node dist/cli.js check .yarramate/workspace.yaml --json",
|
|
84
85
|
"self:compile": "pnpm build && node dist/cli.js compile .yarramate/workspace.yaml",
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"deterministic-diagnostic-order",
|
|
93
93
|
"git-native-governance",
|
|
94
94
|
"globally-qualified-compiled-identities",
|
|
95
|
+
"identified-reference-integrity",
|
|
95
96
|
"no-partial-graph-on-error",
|
|
96
97
|
"portable-projection-selectors",
|
|
97
98
|
"source-located-diagnostics"
|
|
@@ -110,6 +111,7 @@
|
|
|
110
111
|
"architectural-quality",
|
|
111
112
|
"automatic-discovery",
|
|
112
113
|
"external-language-conformance",
|
|
114
|
+
"formal-workflow-semantics",
|
|
113
115
|
"state-scoped-claim-values"
|
|
114
116
|
]
|
|
115
117
|
}
|
|
@@ -100,6 +100,9 @@
|
|
|
100
100
|
"$ref": "#/$defs/constraint"
|
|
101
101
|
}
|
|
102
102
|
},
|
|
103
|
+
"references": {
|
|
104
|
+
"$ref": "#/$defs/identifiedReferences"
|
|
105
|
+
},
|
|
103
106
|
"presentIn": {
|
|
104
107
|
"$ref": "#/$defs/stateReferences"
|
|
105
108
|
}
|
|
@@ -118,6 +121,26 @@
|
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
},
|
|
124
|
+
"identifiedReference": {
|
|
125
|
+
"type": "object",
|
|
126
|
+
"additionalProperties": false,
|
|
127
|
+
"required": ["id", "ref"],
|
|
128
|
+
"properties": {
|
|
129
|
+
"id": {
|
|
130
|
+
"$ref": "#/$defs/id"
|
|
131
|
+
},
|
|
132
|
+
"ref": {
|
|
133
|
+
"$ref": "#/$defs/reference"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"identifiedReferences": {
|
|
138
|
+
"type": "array",
|
|
139
|
+
"minItems": 1,
|
|
140
|
+
"items": {
|
|
141
|
+
"$ref": "#/$defs/identifiedReference"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
121
144
|
"relationship": {
|
|
122
145
|
"type": "object",
|
|
123
146
|
"additionalProperties": false,
|
|
@@ -139,6 +162,9 @@
|
|
|
139
162
|
"name": {
|
|
140
163
|
"$ref": "#/$defs/nonEmptyText"
|
|
141
164
|
},
|
|
165
|
+
"description": {
|
|
166
|
+
"$ref": "#/$defs/nonEmptyText"
|
|
167
|
+
},
|
|
142
168
|
"mode": {
|
|
143
169
|
"enum": ["read", "write", "read-write", "unspecified"]
|
|
144
170
|
},
|
|
@@ -148,6 +174,9 @@
|
|
|
148
174
|
"status": {
|
|
149
175
|
"$ref": "#/$defs/lifecycleStatus"
|
|
150
176
|
},
|
|
177
|
+
"references": {
|
|
178
|
+
"$ref": "#/$defs/identifiedReferences"
|
|
179
|
+
},
|
|
151
180
|
"presentIn": {
|
|
152
181
|
"$ref": "#/$defs/stateReferences"
|
|
153
182
|
}
|
|
@@ -43,7 +43,11 @@ relationships:
|
|
|
43
43
|
kind: access
|
|
44
44
|
from: delivery-api
|
|
45
45
|
to: delivery-data
|
|
46
|
+
description: The API uses the governed record without maintaining a copy.
|
|
46
47
|
mode: read-write
|
|
48
|
+
references:
|
|
49
|
+
- id: residency-policy
|
|
50
|
+
ref: delivery-data
|
|
47
51
|
```
|
|
48
52
|
|
|
49
53
|
IDs are document-local and compile to `document-id#subject-id`. Cross-document
|
|
@@ -76,6 +80,29 @@ use association when no stronger semantic meaning is justified.
|
|
|
76
80
|
Ownership is one accountable reference, not approval workflow. Constraints are
|
|
77
81
|
identified references, not a policy engine or free-form metadata bag.
|
|
78
82
|
|
|
83
|
+
## Rationale and citations
|
|
84
|
+
|
|
85
|
+
Use `description` on either a concept or relationship for decided narrative
|
|
86
|
+
about that exact subject. Use an identified `references` entry when the
|
|
87
|
+
narrative depends on another concept or relationship and the citation must
|
|
88
|
+
remain checkable:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
description: Failure releases the lease and retains partial evidence.
|
|
92
|
+
references:
|
|
93
|
+
- id: failure-destination
|
|
94
|
+
ref: retry-pool
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Core checks the explicit target and local reference ID. It does not scan prose
|
|
98
|
+
for IDs or interpret descriptions as formal preconditions, postconditions, or
|
|
99
|
+
workflow rules.
|
|
100
|
+
|
|
101
|
+
For interaction flows, model steps that need identity as behavior concepts and
|
|
102
|
+
model normal or failure transitions as native relationships. A LikeC4 dynamic
|
|
103
|
+
view may order those projected relationships and display their descriptions;
|
|
104
|
+
the view does not become the workflow source of truth.
|
|
105
|
+
|
|
79
106
|
## Architecture states
|
|
80
107
|
|
|
81
108
|
```yaml
|
|
@@ -153,7 +180,9 @@ yarramate add .yarramate/architecture/main.yaml \
|
|
|
153
180
|
--id delivery-api --kind applicationComponent --name "Delivery API"
|
|
154
181
|
yarramate connect .yarramate/architecture/main.yaml \
|
|
155
182
|
--id api-realizes-service --kind realization \
|
|
156
|
-
--from delivery-api --to delivery-service
|
|
183
|
+
--from delivery-api --to delivery-service \
|
|
184
|
+
--description "The API implements the agreed delivery boundary" \
|
|
185
|
+
--reference decision-source=delivery-service
|
|
157
186
|
yarramate check .yarramate/workspace.yaml --json
|
|
158
187
|
yarramate compile .yarramate/workspace.yaml
|
|
159
188
|
yarramate context <projection.yaml> .yarramate/workspace.yaml
|