archgraph-argo 0.1.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/LICENSE +201 -0
- package/README.md +115 -0
- package/argo/package.json +8 -0
- package/argo/rules/intent-architecture-global-rule.md +45 -0
- package/argo/schema/ImplementationToCodingHandoff.schema.json +252 -0
- package/argo/schema/ImplementationToIntentTraceProposal.schema.json +180 -0
- package/argo/schema/IntentToImplementationHandoff.schema.json +75 -0
- package/argo/schema/SystemArchitecture.schema.json +378 -0
- package/argo/schema/archimate3.2.pdf +0 -0
- package/argo/scripts/ARCHITECTURE.md +57 -0
- package/argo/scripts/archimate32-rules.js +12301 -0
- package/argo/scripts/argo-mcp-server.js +629 -0
- package/argo/scripts/argo-paths.js +77 -0
- package/argo/scripts/ensureArgoHarnessEnvironment.js +340 -0
- package/argo/scripts/generateArchitectureDiffPlantuml.js +466 -0
- package/argo/scripts/graph-rag/ARCHITECTURE.md +192 -0
- package/argo/scripts/graph-rag/canonicalProjectionAuthority.js +45 -0
- package/argo/scripts/graph-rag/defaultSemanticRetrieval.js +969 -0
- package/argo/scripts/graph-rag/embeddingQualificationGate.js +59 -0
- package/argo/scripts/graph-rag/externalProductionConfig.js +74 -0
- package/argo/scripts/graph-rag/liveEmbeddingIndexGate.js +129 -0
- package/argo/scripts/graph-rag/liveEmbeddingNeo4jBoundary.js +137 -0
- package/argo/scripts/graph-rag/liveEmbeddingProviderClient.js +49 -0
- package/argo/scripts/graph-rag/liveEmbeddingProviderConfig.js +481 -0
- package/argo/scripts/graph-rag/mutationEmbeddingVectorLifecycle.js +1261 -0
- package/argo/scripts/graph-rag/neo4jNativeRetrieval.js +37 -0
- package/argo/scripts/graph-rag/productionGraphRagRuntime.js +1624 -0
- package/argo/scripts/graph-rag/semantic-persistence/ARCHITECTURE.md +51 -0
- package/argo/scripts/graph-rag/semantic-persistence/productionSemanticBackfill.js +241 -0
- package/argo/scripts/graph-rag/semantic-persistence/productionSemanticCheckpointStore.js +99 -0
- package/argo/scripts/graph-rag/semantic-persistence/productionSemanticNeo4jAdapter.js +149 -0
- package/argo/scripts/graph-rag/semantic-persistence/productionSemanticProjectionStore.js +171 -0
- package/argo/scripts/graph-rag/semanticOperatorError.js +38 -0
- package/argo/scripts/graph-rag/semanticOperatorJourney.js +459 -0
- package/argo/scripts/graph-rag/semanticReadinessAttestationStore.js +398 -0
- package/argo/scripts/graph-rag/systemMetadataCommandAdapter.js +269 -0
- package/argo/scripts/graph-semantics.js +220 -0
- package/argo/scripts/neo4j-system-architecture-store.js +777 -0
- package/argo/scripts/repositoryArgoEnvironment.js +101 -0
- package/argo/scripts/runArchitectureTests.js +583 -0
- package/argo/scripts/semanticOperatorJourneyCli.js +91 -0
- package/argo/scripts/syncSystemArchitectureToNeo4j.js +67 -0
- package/argo/scripts/systemarchitecture-mcp-server.js +2965 -0
- package/argo/scripts/test-executors/_template.js +58 -0
- package/argo/scripts/test-executors/default.js +199 -0
- package/argo/scripts/validateStageHandoff.js +459 -0
- package/argo/scripts/validateSystemArchitecture.js +254 -0
- package/argo/scripts/validateTraceProposal.js +181 -0
- package/argo/scripts/validator-mcp-server.js +377 -0
- package/argo/skills/argo-init/SKILL.md +110 -0
- package/bin/argo-deploy.js +12 -0
- package/install-argo.ps1 +112 -0
- package/package.json +28 -0
- package/vendor/neo4j-driver-6.2.0.tgz +0 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// Shared graph-semantics validation for SystemArchitecture.
|
|
2
|
+
// Used by both validateSystemArchitecture.js (full validation) and
|
|
3
|
+
// systemarchitecture-mcp-server.js (mutation-path validation).
|
|
4
|
+
//
|
|
5
|
+
// This module eliminates the duplicate validateGraphSemantics implementations.
|
|
6
|
+
// All callers get identical core checks; ArchiMate endpoint matrix and view
|
|
7
|
+
// element limits are parameterized so the full validator can check everything
|
|
8
|
+
// while the mutation path only checks what changed.
|
|
9
|
+
|
|
10
|
+
const {
|
|
11
|
+
elementTypeMetadata,
|
|
12
|
+
relationshipCategoryByType,
|
|
13
|
+
validateRelationshipEndpointTypes,
|
|
14
|
+
} = require('./archimate32-rules');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Core graph-semantics checks that are always identical for all callers.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} document - parsed SystemArchitecture JSON
|
|
20
|
+
* @param {string[]} errors - error accumulator
|
|
21
|
+
*/
|
|
22
|
+
function validateGraphSemantics(document, errors) {
|
|
23
|
+
if (!document || typeof document !== 'object') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const elements = Array.isArray(document.elements) ? document.elements : [];
|
|
28
|
+
const relationships = Array.isArray(document.relationships) ? document.relationships : [];
|
|
29
|
+
const views = Array.isArray(document.views) ? document.views : [];
|
|
30
|
+
const elementById = new Map();
|
|
31
|
+
const relationshipById = new Map();
|
|
32
|
+
|
|
33
|
+
// --- elements: identity, type, parent ---
|
|
34
|
+
for (const element of elements) {
|
|
35
|
+
if (!element || typeof element !== 'object') {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (elementById.has(element.id)) {
|
|
39
|
+
errors.push(`elements contains duplicate id '${element.id}'`);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
elementById.set(element.id, element);
|
|
43
|
+
if (!elementTypeMetadata.has(element.type)) {
|
|
44
|
+
errors.push(`elements '${element.id}' uses unsupported ArchiMate element type '${element.type}'`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const element of elements) {
|
|
49
|
+
if (!element || typeof element !== 'object' || !element.parent) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!elementById.has(element.parent)) {
|
|
53
|
+
errors.push(`elements '${element.id}' references missing parent '${element.parent}'`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// --- relationships: identity, type, endpoints, statement ---
|
|
58
|
+
for (const relationship of relationships) {
|
|
59
|
+
if (!relationship || typeof relationship !== 'object') {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (relationshipById.has(relationship.id)) {
|
|
63
|
+
errors.push(`relationships contains duplicate id '${relationship.id}'`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
relationshipById.set(relationship.id, relationship);
|
|
67
|
+
if (!relationshipCategoryByType.has(relationship.type)) {
|
|
68
|
+
errors.push(`relationships '${relationship.id}' uses unsupported ArchiMate relationship type '${relationship.type}'`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const source = elementById.get(relationship.source_id);
|
|
72
|
+
if (!source) {
|
|
73
|
+
errors.push(`relationships '${relationship.id}' references missing source_id '${relationship.source_id}'`);
|
|
74
|
+
} else if (relationship.source_name !== source.name) {
|
|
75
|
+
errors.push(`relationships '${relationship.id}' source_name '${relationship.source_name}' does not match element '${relationship.source_id}' name '${source.name}'`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const target = elementById.get(relationship.target_id);
|
|
79
|
+
if (!target) {
|
|
80
|
+
errors.push(`relationships '${relationship.id}' references missing target_id '${relationship.target_id}'`);
|
|
81
|
+
} else if (relationship.target_name !== target.name) {
|
|
82
|
+
errors.push(`relationships '${relationship.id}' target_name '${relationship.target_name}' does not match element '${relationship.target_id}' name '${target.name}'`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const expectedStatement = source && target
|
|
86
|
+
? `${source.name} --(${relationship.type})--> ${target.name}`
|
|
87
|
+
: undefined;
|
|
88
|
+
if (expectedStatement && relationship.statement !== expectedStatement) {
|
|
89
|
+
errors.push(`relationships '${relationship.id}' statement must be '${expectedStatement}'`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// --- views: topology, membership, endpoint co-occurrence ---
|
|
94
|
+
const topLevelViews = views.filter(view => view && typeof view === 'object' && !view.parent_element_id);
|
|
95
|
+
if (topLevelViews.length !== 1) {
|
|
96
|
+
errors.push(`views must contain exactly one top-level view named 'SystemArchitecture'; found ${topLevelViews.length}`);
|
|
97
|
+
} else if (topLevelViews[0].view_name !== 'SystemArchitecture') {
|
|
98
|
+
errors.push(`top-level view '${topLevelViews[0].view_id}' view_name must be 'SystemArchitecture'`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const elementIdsIncludedInViews = new Set();
|
|
102
|
+
const relationshipIdsIncludedInViews = new Set();
|
|
103
|
+
for (const view of views) {
|
|
104
|
+
if (!view || typeof view !== 'object') {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (!view.parent_element_id && view.view_name !== 'SystemArchitecture') {
|
|
108
|
+
errors.push(`views '${view.view_id}' must declare parent_element_id unless it is the top-level SystemArchitecture view`);
|
|
109
|
+
}
|
|
110
|
+
if (view.parent_element_id) {
|
|
111
|
+
const parent = elementById.get(view.parent_element_id);
|
|
112
|
+
if (!parent) {
|
|
113
|
+
errors.push(`views '${view.view_id}' references missing parent_element_id '${view.parent_element_id}'`);
|
|
114
|
+
} else if (view.parent_element_name && view.parent_element_name !== parent.name) {
|
|
115
|
+
errors.push(`views '${view.view_id}' parent_element_name '${view.parent_element_name}' does not match element '${view.parent_element_id}' name '${parent.name}'`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const includedElementIds = new Set(view.included_elements || []);
|
|
119
|
+
for (const elementId of view.included_elements || []) {
|
|
120
|
+
elementIdsIncludedInViews.add(elementId);
|
|
121
|
+
if (!elementById.has(elementId)) {
|
|
122
|
+
errors.push(`views '${view.view_id}' references missing included element '${elementId}'`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
for (const relationshipId of view.included_relationships || []) {
|
|
126
|
+
relationshipIdsIncludedInViews.add(relationshipId);
|
|
127
|
+
const rel = relationshipById.get(relationshipId);
|
|
128
|
+
if (!rel) {
|
|
129
|
+
errors.push(`views '${view.view_id}' references missing included relationship '${relationshipId}'`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (!includedElementIds.has(rel.source_id)) {
|
|
133
|
+
errors.push(`views '${view.view_id}' includes relationship '${relationshipId}' but not source element '${rel.source_id}'`);
|
|
134
|
+
}
|
|
135
|
+
if (!includedElementIds.has(rel.target_id)) {
|
|
136
|
+
errors.push(`views '${view.view_id}' includes relationship '${relationshipId}' but not target element '${rel.target_id}'`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for (const element of elements) {
|
|
142
|
+
if (element && typeof element === 'object' && !elementIdsIncludedInViews.has(element.id)) {
|
|
143
|
+
errors.push(`elements '${element.id}' must be included in at least one view`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const relationship of relationships) {
|
|
148
|
+
if (relationship && typeof relationship === 'object' && !relationshipIdsIncludedInViews.has(relationship.id)) {
|
|
149
|
+
errors.push(`relationships '${relationship.id}' must be included in at least one view`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Validate ArchiMate 3.2 endpoint type matrix for relationships.
|
|
156
|
+
*
|
|
157
|
+
* @param {object} document - parsed SystemArchitecture JSON
|
|
158
|
+
* @param {string[]} errors - error accumulator
|
|
159
|
+
* @param {object} [options]
|
|
160
|
+
* @param {string[]} [options.touchedRelationshipIds] - if provided, only these
|
|
161
|
+
* relationships are checked; if omitted/empty, ALL relationships are checked
|
|
162
|
+
*/
|
|
163
|
+
function validateArchiMateEndpointMatrix(document, errors, options = {}) {
|
|
164
|
+
const elementById = new Map(
|
|
165
|
+
(document.elements || []).map(element => [element.id, element]),
|
|
166
|
+
);
|
|
167
|
+
const relationshipIdSet =
|
|
168
|
+
Array.isArray(options.touchedRelationshipIds) && options.touchedRelationshipIds.length > 0
|
|
169
|
+
? new Set(options.touchedRelationshipIds)
|
|
170
|
+
: undefined;
|
|
171
|
+
|
|
172
|
+
for (const relationship of document.relationships || []) {
|
|
173
|
+
if (relationshipIdSet && !relationshipIdSet.has(relationship.id)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const source = elementById.get(relationship.source_id);
|
|
177
|
+
const target = elementById.get(relationship.target_id);
|
|
178
|
+
errors.push(...validateRelationshipEndpointTypes(relationship, source, target));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Validate that each view contains at most 15 included_elements.
|
|
184
|
+
* included_relationships do not consume this quota.
|
|
185
|
+
*
|
|
186
|
+
* @param {object} document - parsed SystemArchitecture JSON
|
|
187
|
+
* @param {string[]} errors - error accumulator
|
|
188
|
+
* @param {object} [options]
|
|
189
|
+
* @param {string[]} [options.touchedViewIds] - if provided, only these views
|
|
190
|
+
* are checked; if omitted/empty, ALL views are checked
|
|
191
|
+
*/
|
|
192
|
+
function validateViewElementLimits(document, errors, options = {}) {
|
|
193
|
+
const touchedViewIdSet =
|
|
194
|
+
Array.isArray(options.touchedViewIds) && options.touchedViewIds.length > 0
|
|
195
|
+
? new Set(options.touchedViewIds)
|
|
196
|
+
: undefined;
|
|
197
|
+
const MAX_INCLUDED_ELEMENTS = 15;
|
|
198
|
+
|
|
199
|
+
for (const view of document.views || []) {
|
|
200
|
+
if (!view) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (touchedViewIdSet && !touchedViewIdSet.has(view.view_id)) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const elementCount = Array.isArray(view.included_elements) ? view.included_elements.length : 0;
|
|
207
|
+
if (elementCount > MAX_INCLUDED_ELEMENTS) {
|
|
208
|
+
errors.push(
|
|
209
|
+
`views '${view.view_id}' must contain at most ${MAX_INCLUDED_ELEMENTS} elements; found ${elementCount}. ` +
|
|
210
|
+
'Split the content into layered sub-views before adding more elements.',
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = {
|
|
217
|
+
validateGraphSemantics,
|
|
218
|
+
validateArchiMateEndpointMatrix,
|
|
219
|
+
validateViewElementLimits,
|
|
220
|
+
};
|