yarramate 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.1.1",
3
+ "version": "0.3.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 .yarramate/integrations/likec4/prototype",
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",
@@ -17,6 +17,9 @@
17
17
  "items": {
18
18
  "$ref": "#/$defs/diagnostic"
19
19
  }
20
+ },
21
+ "counted": {
22
+ "$ref": "#/$defs/counted"
20
23
  }
21
24
  },
22
25
  "allOf": [
@@ -30,6 +33,7 @@
30
33
  "required": ["ok"]
31
34
  },
32
35
  "then": {
36
+ "required": ["counted"],
33
37
  "properties": {
34
38
  "diagnostics": {
35
39
  "maxItems": 0
@@ -46,6 +50,17 @@
46
50
  }
47
51
  ],
48
52
  "$defs": {
53
+ "counted": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["documents", "concepts", "relationships", "states"],
57
+ "properties": {
58
+ "documents": { "type": "integer", "minimum": 0 },
59
+ "concepts": { "type": "integer", "minimum": 0 },
60
+ "relationships": { "type": "integer", "minimum": 0 },
61
+ "states": { "type": "integer", "minimum": 0 }
62
+ }
63
+ },
49
64
  "diagnostic": {
50
65
  "type": "object",
51
66
  "additionalProperties": false,
@@ -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
  }
@@ -34,7 +34,7 @@
34
34
  "const": "error"
35
35
  },
36
36
  "code": {
37
- "enum": ["YMLC101", "YMLC102", "YMLC103", "YMLC104", "YMLC105", "YMLC106"]
37
+ "enum": ["YMLC101", "YMLC102", "YMLC103", "YMLC104", "YMLC105", "YMLC106", "YMLC107", "YMLC108", "YMLC109", "YMLC110"]
38
38
  },
39
39
  "message": {
40
40
  "type": "string",
@@ -41,6 +41,7 @@
41
41
  },
42
42
  "path": {
43
43
  "type": "string",
44
+ "description": "Repository-relative path resolved from the CLI working directory. Parent traversal, absolute paths, and backslashes are rejected.",
44
45
  "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$"
45
46
  },
46
47
  "subjectIdentity": {
@@ -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
@@ -161,6 +190,9 @@ yarramate view <projection.yaml> .yarramate/workspace.yaml
161
190
  yarramate compare <from-state> <to-state> .yarramate/workspace.yaml
162
191
  yarramate evidence <evidence.yaml> .yarramate/workspace.yaml
163
192
  yarramate reconcile .yarramate/workspace.yaml
193
+ yarramate-likec4 map --sync \
194
+ .yarramate/integrations/likec4/subject-mapping.yaml \
195
+ .yarramate/workspace.yaml
164
196
  ```
165
197
 
166
198
  Treat exit `0` as successful execution, `1` as correctness diagnostics, and