archgraph-argo 0.26.2 → 0.28.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 +127 -57
- package/argo/.env.example +181 -163
- package/argo/plugins/argo-wakeup.js +29 -27
- package/argo/rules/archgraph.instructions.md +189 -187
- package/argo/schema/schema-bundle.config.json +22 -0
- package/argo/schema/schema-bundle.rules.json +12229 -0
- package/argo/scripts/agentSearchDiagnose.js +410 -407
- package/argo/scripts/argo-mcp-server.js +122 -9
- package/argo/scripts/ensureArgoHarnessEnvironment.js +14 -0
- package/argo/scripts/external-graph-query.js +162 -0
- package/argo/scripts/graph-rag/defaultSemanticRetrieval.js +0 -13
- package/argo/scripts/graph-rag/liveEmbeddingProviderConfig.js +9 -61
- package/argo/scripts/graph-semantics.js +363 -227
- package/argo/scripts/runArchitectureTests.js +591 -583
- package/argo/scripts/schema-bundle.js +932 -0
- package/argo/scripts/systemarchitecture-mcp-server.js +758 -110
- package/argo/scripts/validateSystemArchitecture.js +262 -253
- package/argo/scripts/validator-mcp-server.js +1 -1
- package/argo/scripts/workspace-write-guard.js +144 -0
- package/argo/skills/argo-init/SKILL.md +7 -9
- package/argo/skills/ea-human-reconcile/SKILL.md +40 -39
- package/cordis.patch.yml +15 -6
- package/dsh-argo-wakeup/index.js +17 -17
- package/dsh-argo-workspace/index.js +227 -141
- package/install-argo.ps1 +336 -206
- package/package.json +57 -53
|
@@ -1,254 +1,263 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} = require('./graph-semantics.js');
|
|
22
|
-
|
|
23
|
-
function main() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
getWorkspaceRoot,
|
|
6
|
+
} = require('./argo-paths.js');
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
loadSchemaBundleAndOntology,
|
|
10
|
+
} = require('./schema-bundle.js');
|
|
11
|
+
|
|
12
|
+
const repoRoot = getWorkspaceRoot();
|
|
13
|
+
const graphRelativePath = path.join('design', 'KG', 'SystemArchitecture.json');
|
|
14
|
+
const graphPath = path.join(repoRoot, graphRelativePath);
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
validateGraphSemantics,
|
|
18
|
+
validateArchiMateEndpointMatrix,
|
|
19
|
+
validateViewElementLimits,
|
|
20
|
+
validateAttributeContracts,
|
|
21
|
+
} = require('./graph-semantics.js');
|
|
22
|
+
|
|
23
|
+
function main() {
|
|
24
|
+
let bundle;
|
|
25
|
+
let ontology;
|
|
26
|
+
try {
|
|
27
|
+
({ bundle, ontology } = loadSchemaBundleAndOntology(repoRoot));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
fail(String(error && error.message ? error.message : error));
|
|
30
|
+
}
|
|
31
|
+
const schema = bundle.schemaDocument;
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(graphPath)) {
|
|
34
|
+
fail('System architecture file is missing at design/KG/SystemArchitecture.json');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const document = parseJson(graphPath, 'design/KG/SystemArchitecture.json');
|
|
38
|
+
const errors = [];
|
|
39
|
+
|
|
40
|
+
if (ontology.bundleValidation && ontology.bundleValidation.status === 'failed') {
|
|
41
|
+
for (const error of ontology.bundleValidation.errors) {
|
|
42
|
+
errors.push(`schema bundle: ${error}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
validateAgainstSchema(document, schema, '#', errors, schema);
|
|
46
|
+
validateGraphSemantics(document, errors, ontology);
|
|
47
|
+
validateAttributeContracts(document, errors, ontology);
|
|
48
|
+
validateArchiMateEndpointMatrix(document, errors, { ontology });
|
|
49
|
+
validateViewElementLimits(document, errors, { ontology });
|
|
50
|
+
|
|
51
|
+
if (errors.length > 0) {
|
|
52
|
+
console.error(`SystemArchitecture validation failed [schema: ${bundle.kind} / ${ontology.language}]:`);
|
|
53
|
+
for (const error of errors) {
|
|
54
|
+
console.error(`- ${error}`);
|
|
55
|
+
}
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log(`SystemArchitecture validation passed for: design/KG/SystemArchitecture.json [schema: ${bundle.kind} / ${ontology.language}]`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function parseJson(filePath, label) {
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
65
|
+
} catch (error) {
|
|
66
|
+
fail(`Failed to parse ${label}: ${String(error)}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function validateAgainstSchema(value, schemaNode, pointer, errors, rootSchema) {
|
|
71
|
+
if (!schemaNode || typeof schemaNode !== 'object') {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const resolvedSchema = schemaNode.$ref ? resolveRef(schemaNode.$ref, rootSchema, errors, pointer) : schemaNode;
|
|
76
|
+
if (!resolvedSchema) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (resolvedSchema.const !== undefined && !isDeepStrictEqual(value, resolvedSchema.const)) {
|
|
81
|
+
errors.push(`${pointer} must equal ${JSON.stringify(resolvedSchema.const)}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (resolvedSchema.enum && !resolvedSchema.enum.some(option => isDeepStrictEqual(option, value))) {
|
|
86
|
+
errors.push(`${pointer} must be one of: ${resolvedSchema.enum.map(option => JSON.stringify(option)).join(', ')}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (resolvedSchema.type !== undefined) {
|
|
91
|
+
validateType(value, resolvedSchema.type, pointer, errors);
|
|
92
|
+
if (!typeMatches(value, resolvedSchema.type)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (typeof resolvedSchema.minLength === 'number') {
|
|
98
|
+
if (typeof value !== 'string' || value.length < resolvedSchema.minLength) {
|
|
99
|
+
errors.push(`${pointer} must be at least ${resolvedSchema.minLength} character(s) long`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (typeof resolvedSchema.maxLength === 'number') {
|
|
104
|
+
if (typeof value !== 'string' || value.length > resolvedSchema.maxLength) {
|
|
105
|
+
errors.push(`${pointer} must be at most ${resolvedSchema.maxLength} character(s) long`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (resolvedSchema.pattern) {
|
|
110
|
+
const matcher = new RegExp(resolvedSchema.pattern);
|
|
111
|
+
if (typeof value !== 'string' || !matcher.test(value)) {
|
|
112
|
+
errors.push(`${pointer} must match pattern ${JSON.stringify(resolvedSchema.pattern)}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (typeof resolvedSchema.minimum === 'number') {
|
|
117
|
+
if (typeof value !== 'number' || value < resolvedSchema.minimum) {
|
|
118
|
+
errors.push(`${pointer} must be >= ${resolvedSchema.minimum}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (typeof resolvedSchema.maximum === 'number') {
|
|
123
|
+
if (typeof value !== 'number' || value > resolvedSchema.maximum) {
|
|
124
|
+
errors.push(`${pointer} must be <= ${resolvedSchema.maximum}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof resolvedSchema.minItems === 'number') {
|
|
129
|
+
if (!Array.isArray(value) || value.length < resolvedSchema.minItems) {
|
|
130
|
+
errors.push(`${pointer} must contain at least ${resolvedSchema.minItems} item(s)`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (typeof resolvedSchema.maxItems === 'number') {
|
|
135
|
+
if (!Array.isArray(value) || value.length > resolvedSchema.maxItems) {
|
|
136
|
+
errors.push(`${pointer} must contain at most ${resolvedSchema.maxItems} item(s)`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (resolvedSchema.uniqueItems === true && Array.isArray(value)) {
|
|
141
|
+
const seen = new Set();
|
|
142
|
+
value.forEach((entry, index) => {
|
|
143
|
+
const serialized = JSON.stringify(entry);
|
|
144
|
+
if (seen.has(serialized)) {
|
|
145
|
+
errors.push(`${pointer}[${index}] must be unique within ${pointer}`);
|
|
146
|
+
} else {
|
|
147
|
+
seen.add(serialized);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (resolvedSchema.type === 'object') {
|
|
153
|
+
validateObject(value, resolvedSchema, pointer, errors, rootSchema);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (resolvedSchema.type === 'array') {
|
|
158
|
+
validateArray(value, resolvedSchema, pointer, errors, rootSchema);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function validateObject(value, schemaNode, pointer, errors, rootSchema) {
|
|
163
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const properties = schemaNode.properties || {};
|
|
168
|
+
const required = Array.isArray(schemaNode.required) ? schemaNode.required : [];
|
|
169
|
+
|
|
170
|
+
for (const key of required) {
|
|
171
|
+
if (!(key in value)) {
|
|
172
|
+
errors.push(`${pointer} is missing required property '${key}'`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (schemaNode.additionalProperties === false) {
|
|
177
|
+
for (const key of Object.keys(value)) {
|
|
178
|
+
if (!(key in properties)) {
|
|
179
|
+
errors.push(`${pointer} contains unsupported property '${key}'`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (const [key, propertySchema] of Object.entries(properties)) {
|
|
185
|
+
if (key in value) {
|
|
186
|
+
validateAgainstSchema(value[key], propertySchema, `${pointer}.${key}`, errors, rootSchema);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function validateArray(value, schemaNode, pointer, errors, rootSchema) {
|
|
192
|
+
if (!Array.isArray(value)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (schemaNode.items) {
|
|
197
|
+
value.forEach((entry, index) => {
|
|
198
|
+
validateAgainstSchema(entry, schemaNode.items, `${pointer}[${index}]`, errors, rootSchema);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function validateType(value, expectedType, pointer, errors) {
|
|
204
|
+
if (!typeMatches(value, expectedType)) {
|
|
205
|
+
const printableType = Array.isArray(expectedType) ? expectedType.join(' or ') : expectedType;
|
|
206
|
+
errors.push(`${pointer} must be of type ${printableType}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function typeMatches(value, expectedType) {
|
|
211
|
+
if (Array.isArray(expectedType)) {
|
|
212
|
+
return expectedType.some(candidate => typeMatches(value, candidate));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
switch (expectedType) {
|
|
216
|
+
case 'object':
|
|
217
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
218
|
+
case 'array':
|
|
219
|
+
return Array.isArray(value);
|
|
220
|
+
case 'string':
|
|
221
|
+
return typeof value === 'string';
|
|
222
|
+
case 'number':
|
|
223
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
224
|
+
case 'integer':
|
|
225
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
226
|
+
case 'boolean':
|
|
227
|
+
return typeof value === 'boolean';
|
|
228
|
+
case 'null':
|
|
229
|
+
return value === null;
|
|
230
|
+
default:
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function resolveRef(ref, rootSchema, errors, pointer) {
|
|
236
|
+
if (!ref.startsWith('#/')) {
|
|
237
|
+
errors.push(`${pointer} uses unsupported $ref '${ref}'`);
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const segments = ref.slice(2).split('/');
|
|
242
|
+
let current = rootSchema;
|
|
243
|
+
for (const segment of segments) {
|
|
244
|
+
if (!current || typeof current !== 'object' || !(segment in current)) {
|
|
245
|
+
errors.push(`${pointer} references missing schema path '${ref}'`);
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
current = current[segment];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return current;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isDeepStrictEqual(left, right) {
|
|
255
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function fail(message) {
|
|
259
|
+
console.error(`SystemArchitecture validation failed: ${message}`);
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
|
|
254
263
|
main();
|
|
@@ -26,7 +26,7 @@ const SCRIPT_CANDIDATES = {
|
|
|
26
26
|
const TOOLS = [
|
|
27
27
|
{
|
|
28
28
|
name: 'validateSystemArchitecture',
|
|
29
|
-
description: 'Validate design/KG/SystemArchitecture.json against .argo/schema
|
|
29
|
+
description: 'Validate design/KG/SystemArchitecture.json against the workspace-resolved schema bundle (the default ArchiMate 3.2 schema, or the repository\'s own .argo/schema) and Argo graph rules.',
|
|
30
30
|
inputSchema: {
|
|
31
31
|
type: 'object',
|
|
32
32
|
properties: {},
|