archgraph-argo 0.10.43 → 0.10.44

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.
Files changed (35) hide show
  1. package/LICENSE +201 -201
  2. package/argo/package.json +8 -8
  3. package/argo/schema/ImplementationToCodingHandoff.schema.json +251 -251
  4. package/argo/schema/ImplementationToIntentTraceProposal.schema.json +180 -180
  5. package/argo/schema/IntentToImplementationHandoff.schema.json +74 -74
  6. package/argo/schema/SystemArchitecture.schema.json +378 -378
  7. package/argo/schema/archimate3.2.md +7153 -7153
  8. package/argo/scripts/archimate32-rules.js +12301 -12301
  9. package/argo/scripts/generateArchitectureDiffPlantuml.js +466 -466
  10. package/argo/scripts/graph-rag/ARCHITECTURE.md +192 -192
  11. package/argo/scripts/graph-rag/canonicalProjectionAuthority.js +45 -45
  12. package/argo/scripts/graph-rag/embeddingQualificationGate.js +59 -59
  13. package/argo/scripts/graph-rag/externalProductionConfig.js +74 -74
  14. package/argo/scripts/graph-rag/liveEmbeddingProviderClient.js +49 -49
  15. package/argo/scripts/graph-rag/neo4jNativeRetrieval.js +37 -37
  16. package/argo/scripts/graph-rag/semantic-persistence/ARCHITECTURE.md +51 -51
  17. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticCheckpointStore.js +99 -99
  18. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticProjectionStore.js +171 -171
  19. package/argo/scripts/graph-rag/semanticOperatorError.js +38 -38
  20. package/argo/scripts/graph-rag/semanticOperatorJourney.js +459 -459
  21. package/argo/scripts/graph-rag/semanticReadinessAttestationStore.js +398 -398
  22. package/argo/scripts/graph-rag/systemMetadataCommandAdapter.js +269 -269
  23. package/argo/scripts/graph-semantics.js +220 -220
  24. package/argo/scripts/repositoryArgoEnvironment.js +101 -101
  25. package/argo/scripts/runArchitectureTests.js +583 -583
  26. package/argo/scripts/semanticOperatorJourneyCli.js +91 -91
  27. package/argo/scripts/syncSystemArchitectureToNeo4j.js +66 -66
  28. package/argo/scripts/test-executors/_template.js +58 -58
  29. package/argo/scripts/test-executors/default.js +199 -199
  30. package/argo/scripts/validateStageHandoff.js +458 -458
  31. package/argo/scripts/validateSystemArchitecture.js +253 -253
  32. package/argo/scripts/validateTraceProposal.js +181 -181
  33. package/bin/argo-deploy.js +12 -12
  34. package/install-argo.ps1 +27 -8
  35. package/package.json +1 -1
@@ -1,199 +1,199 @@
1
- /**
2
- * Default Test Executor — file-extension-based execution.
3
- *
4
- * This is the built-in executor that handles the original acceptanceCriteria format:
5
- * a workspace-relative script path, optionally with a pytest node-id selector.
6
- *
7
- * Custom executors can be added to this directory; they are auto-discovered by
8
- * runArchitectureTests.js. Each executor module must export:
9
- * name: string
10
- * canHandle(acceptanceCriteria, workspaceRoot): boolean
11
- * execute(acceptanceCriteria, workspaceRoot): Promise<{exitCode, stdout, stderr}>
12
- * getCommandPreview(acceptanceCriteria, workspaceRoot): string | null (optional)
13
- */
14
-
15
- const { execFile } = require('child_process');
16
- const fs = require('fs');
17
- const path = require('path');
18
- const { promisify } = require('util');
19
-
20
- const {
21
- getWorkspaceRoot,
22
- } = require('../argo-paths.js');
23
-
24
- const execFileAsync = promisify(execFile);
25
-
26
- const PYTHON_EXECUTABLE = resolvePythonExecutable();
27
- const TEST_TIMEOUT_MS = readPositiveInteger(process.env.ARGO_TEST_TIMEOUT_MS, 120000);
28
-
29
- const SUPPORTED_EXTENSIONS = new Set(['.js', '.cjs', '.mjs', '.py', '.ps1', '.cmd', '.bat']);
30
-
31
- const DISALLOWED_PATTERNS = [
32
- /[\r\n]/,
33
- /[|&;<>]/,
34
- /^['"].*['"]$/,
35
- /^(?:npm|pnpm|yarn|npx|node|python|py|powershell|pwsh|cmd|bash|sh)\b/i,
36
- ];
37
-
38
- // --- Exported interface ---
39
-
40
- const name = 'default';
41
-
42
- /**
43
- * The default executor handles acceptanceCriteria that are workspace-relative
44
- * script file paths (optionally with ::pytest_node_id selectors).
45
- */
46
- function canHandle(acceptanceCriteria) {
47
- if (!acceptanceCriteria) return false;
48
-
49
- for (const pattern of DISALLOWED_PATTERNS) {
50
- if (pattern.test(acceptanceCriteria)) return false;
51
- }
52
-
53
- const parsed = parseCriteria(acceptanceCriteria);
54
- const ext = path.extname(parsed.scriptRelativePath).toLowerCase();
55
- if (!SUPPORTED_EXTENSIONS.has(ext)) return false;
56
-
57
- if (parsed.selector && ext !== '.py') return false;
58
-
59
- return true;
60
- }
61
-
62
- function getCommandPreview(acceptanceCriteria) {
63
- const parsed = parseCriteria(acceptanceCriteria);
64
- if (parsed.selector) {
65
- return formatCommand('python', ['-m', 'pytest', buildPytestNodeId(parsed)]);
66
- }
67
-
68
- const ext = path.extname(parsed.scriptRelativePath).toLowerCase();
69
- switch (ext) {
70
- case '.js': case '.cjs': case '.mjs':
71
- return formatCommand(process.execPath, [parsed.displayPath || parsed.scriptRelativePath]);
72
- case '.py':
73
- return formatCommand('python', [parsed.scriptRelativePath]);
74
- case '.ps1':
75
- return formatCommand('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', parsed.scriptRelativePath]);
76
- case '.cmd': case '.bat':
77
- return formatCommand(parsed.scriptRelativePath, []);
78
- default:
79
- return formatCommand(parsed.scriptRelativePath, []);
80
- }
81
- }
82
-
83
- async function execute(acceptanceCriteria, workspaceRoot) {
84
- const parsed = parseCriteria(acceptanceCriteria);
85
- const scriptPath = path.join(workspaceRoot, ...parsed.scriptRelativePath.split('/'));
86
-
87
- if (!fs.existsSync(scriptPath)) {
88
- return {
89
- exitCode: null,
90
- stdout: '',
91
- stderr: `test script not found: ${acceptanceCriteria}`,
92
- };
93
- }
94
-
95
- if (parsed.selector) {
96
- return runPythonPytestNodeId(parsed, workspaceRoot);
97
- }
98
-
99
- const ext = path.extname(scriptPath).toLowerCase();
100
- switch (ext) {
101
- case '.js': case '.cjs': case '.mjs':
102
- return runCommand(process.execPath, [scriptPath], workspaceRoot, parsed.fragment
103
- ? { ARGO_TESTCASE_ANCHOR: parsed.fragment }
104
- : undefined);
105
- case '.py':
106
- return runCommand(PYTHON_EXECUTABLE, [scriptPath], workspaceRoot);
107
- case '.ps1':
108
- return runCommand('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath], workspaceRoot);
109
- case '.cmd': case '.bat':
110
- return runCommand(scriptPath, [], workspaceRoot);
111
- default:
112
- return runCommand(scriptPath, [], workspaceRoot);
113
- }
114
- }
115
-
116
- // --- Internal helpers ---
117
-
118
- function parseCriteria(value) {
119
- const [pathAndFragment, ...selectorParts] = value.split('::');
120
- const hashIndex = pathAndFragment.indexOf('#');
121
- const scriptRelativePath = hashIndex >= 0 ? pathAndFragment.slice(0, hashIndex) : pathAndFragment;
122
- const fragment = hashIndex >= 0 ? pathAndFragment.slice(hashIndex + 1).trim() : undefined;
123
- return {
124
- scriptRelativePath: normalizePath(scriptRelativePath),
125
- displayPath: normalizePath(pathAndFragment),
126
- fragment,
127
- selector: selectorParts.length > 0 ? selectorParts.join('::').trim() : undefined,
128
- };
129
- }
130
-
131
- function buildPytestNodeId(criteria) {
132
- return criteria.selector
133
- ? `${criteria.scriptRelativePath}::${criteria.selector}`
134
- : criteria.scriptRelativePath;
135
- }
136
-
137
- async function runPythonPytestNodeId(criteria, cwd) {
138
- return runCommand(PYTHON_EXECUTABLE, ['-m', 'pytest', buildPytestNodeId(criteria)], cwd);
139
- }
140
-
141
- async function runCommand(command, args, cwd, extraEnv = undefined) {
142
- try {
143
- const { stdout, stderr } = await execFileAsync(command, args, {
144
- cwd,
145
- windowsHide: true,
146
- maxBuffer: 1024 * 1024 * 10,
147
- timeout: TEST_TIMEOUT_MS,
148
- env: extraEnv ? { ...process.env, ...extraEnv } : process.env,
149
- });
150
- return { exitCode: 0, stdout: stdout.trim(), stderr: stderr.trim() };
151
- } catch (error) {
152
- const timedOut = error && (error.killed || error.signal === 'SIGTERM' || error.code === 'ETIMEDOUT');
153
- return {
154
- exitCode: typeof error.code === 'number' ? error.code : 1,
155
- stdout: String(error.stdout || '').trim(),
156
- stderr: timedOut
157
- ? `Command timed out after ${TEST_TIMEOUT_MS}ms: ${formatCommand(command, args)}`
158
- : String(error.stderr || error.message || error).trim(),
159
- };
160
- }
161
- }
162
-
163
- function resolvePythonExecutable() {
164
- const workspaceRoot = getWorkspaceRoot();
165
-
166
- const candidates = process.platform === 'win32'
167
- ? [
168
- path.join(workspaceRoot, '.venv', 'Scripts', 'python.exe'),
169
- path.join(workspaceRoot, 'venv', 'Scripts', 'python.exe'),
170
- ]
171
- : [
172
- path.join(workspaceRoot, '.venv', 'bin', 'python'),
173
- path.join(workspaceRoot, 'venv', 'bin', 'python'),
174
- ];
175
-
176
- for (const candidate of candidates) {
177
- if (fs.existsSync(candidate)) return candidate;
178
- }
179
- return 'python';
180
- }
181
-
182
- function readPositiveInteger(value, fallback) {
183
- const parsed = Number.parseInt(String(value || ''), 10);
184
- return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
185
- }
186
-
187
- function normalizePath(value) {
188
- return String(value).replace(/\\/g, '/').replace(/^\.\//, '').trim();
189
- }
190
-
191
- function formatCommand(command, args) {
192
- return [quote(command), ...args.map(quote)].join(' ');
193
- }
194
-
195
- function quote(value) {
196
- return /\s/.test(value) ? `"${value}"` : value;
197
- }
198
-
199
- module.exports = { name, canHandle, execute, getCommandPreview };
1
+ /**
2
+ * Default Test Executor — file-extension-based execution.
3
+ *
4
+ * This is the built-in executor that handles the original acceptanceCriteria format:
5
+ * a workspace-relative script path, optionally with a pytest node-id selector.
6
+ *
7
+ * Custom executors can be added to this directory; they are auto-discovered by
8
+ * runArchitectureTests.js. Each executor module must export:
9
+ * name: string
10
+ * canHandle(acceptanceCriteria, workspaceRoot): boolean
11
+ * execute(acceptanceCriteria, workspaceRoot): Promise<{exitCode, stdout, stderr}>
12
+ * getCommandPreview(acceptanceCriteria, workspaceRoot): string | null (optional)
13
+ */
14
+
15
+ const { execFile } = require('child_process');
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const { promisify } = require('util');
19
+
20
+ const {
21
+ getWorkspaceRoot,
22
+ } = require('../argo-paths.js');
23
+
24
+ const execFileAsync = promisify(execFile);
25
+
26
+ const PYTHON_EXECUTABLE = resolvePythonExecutable();
27
+ const TEST_TIMEOUT_MS = readPositiveInteger(process.env.ARGO_TEST_TIMEOUT_MS, 120000);
28
+
29
+ const SUPPORTED_EXTENSIONS = new Set(['.js', '.cjs', '.mjs', '.py', '.ps1', '.cmd', '.bat']);
30
+
31
+ const DISALLOWED_PATTERNS = [
32
+ /[\r\n]/,
33
+ /[|&;<>]/,
34
+ /^['"].*['"]$/,
35
+ /^(?:npm|pnpm|yarn|npx|node|python|py|powershell|pwsh|cmd|bash|sh)\b/i,
36
+ ];
37
+
38
+ // --- Exported interface ---
39
+
40
+ const name = 'default';
41
+
42
+ /**
43
+ * The default executor handles acceptanceCriteria that are workspace-relative
44
+ * script file paths (optionally with ::pytest_node_id selectors).
45
+ */
46
+ function canHandle(acceptanceCriteria) {
47
+ if (!acceptanceCriteria) return false;
48
+
49
+ for (const pattern of DISALLOWED_PATTERNS) {
50
+ if (pattern.test(acceptanceCriteria)) return false;
51
+ }
52
+
53
+ const parsed = parseCriteria(acceptanceCriteria);
54
+ const ext = path.extname(parsed.scriptRelativePath).toLowerCase();
55
+ if (!SUPPORTED_EXTENSIONS.has(ext)) return false;
56
+
57
+ if (parsed.selector && ext !== '.py') return false;
58
+
59
+ return true;
60
+ }
61
+
62
+ function getCommandPreview(acceptanceCriteria) {
63
+ const parsed = parseCriteria(acceptanceCriteria);
64
+ if (parsed.selector) {
65
+ return formatCommand('python', ['-m', 'pytest', buildPytestNodeId(parsed)]);
66
+ }
67
+
68
+ const ext = path.extname(parsed.scriptRelativePath).toLowerCase();
69
+ switch (ext) {
70
+ case '.js': case '.cjs': case '.mjs':
71
+ return formatCommand(process.execPath, [parsed.displayPath || parsed.scriptRelativePath]);
72
+ case '.py':
73
+ return formatCommand('python', [parsed.scriptRelativePath]);
74
+ case '.ps1':
75
+ return formatCommand('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', parsed.scriptRelativePath]);
76
+ case '.cmd': case '.bat':
77
+ return formatCommand(parsed.scriptRelativePath, []);
78
+ default:
79
+ return formatCommand(parsed.scriptRelativePath, []);
80
+ }
81
+ }
82
+
83
+ async function execute(acceptanceCriteria, workspaceRoot) {
84
+ const parsed = parseCriteria(acceptanceCriteria);
85
+ const scriptPath = path.join(workspaceRoot, ...parsed.scriptRelativePath.split('/'));
86
+
87
+ if (!fs.existsSync(scriptPath)) {
88
+ return {
89
+ exitCode: null,
90
+ stdout: '',
91
+ stderr: `test script not found: ${acceptanceCriteria}`,
92
+ };
93
+ }
94
+
95
+ if (parsed.selector) {
96
+ return runPythonPytestNodeId(parsed, workspaceRoot);
97
+ }
98
+
99
+ const ext = path.extname(scriptPath).toLowerCase();
100
+ switch (ext) {
101
+ case '.js': case '.cjs': case '.mjs':
102
+ return runCommand(process.execPath, [scriptPath], workspaceRoot, parsed.fragment
103
+ ? { ARGO_TESTCASE_ANCHOR: parsed.fragment }
104
+ : undefined);
105
+ case '.py':
106
+ return runCommand(PYTHON_EXECUTABLE, [scriptPath], workspaceRoot);
107
+ case '.ps1':
108
+ return runCommand('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath], workspaceRoot);
109
+ case '.cmd': case '.bat':
110
+ return runCommand(scriptPath, [], workspaceRoot);
111
+ default:
112
+ return runCommand(scriptPath, [], workspaceRoot);
113
+ }
114
+ }
115
+
116
+ // --- Internal helpers ---
117
+
118
+ function parseCriteria(value) {
119
+ const [pathAndFragment, ...selectorParts] = value.split('::');
120
+ const hashIndex = pathAndFragment.indexOf('#');
121
+ const scriptRelativePath = hashIndex >= 0 ? pathAndFragment.slice(0, hashIndex) : pathAndFragment;
122
+ const fragment = hashIndex >= 0 ? pathAndFragment.slice(hashIndex + 1).trim() : undefined;
123
+ return {
124
+ scriptRelativePath: normalizePath(scriptRelativePath),
125
+ displayPath: normalizePath(pathAndFragment),
126
+ fragment,
127
+ selector: selectorParts.length > 0 ? selectorParts.join('::').trim() : undefined,
128
+ };
129
+ }
130
+
131
+ function buildPytestNodeId(criteria) {
132
+ return criteria.selector
133
+ ? `${criteria.scriptRelativePath}::${criteria.selector}`
134
+ : criteria.scriptRelativePath;
135
+ }
136
+
137
+ async function runPythonPytestNodeId(criteria, cwd) {
138
+ return runCommand(PYTHON_EXECUTABLE, ['-m', 'pytest', buildPytestNodeId(criteria)], cwd);
139
+ }
140
+
141
+ async function runCommand(command, args, cwd, extraEnv = undefined) {
142
+ try {
143
+ const { stdout, stderr } = await execFileAsync(command, args, {
144
+ cwd,
145
+ windowsHide: true,
146
+ maxBuffer: 1024 * 1024 * 10,
147
+ timeout: TEST_TIMEOUT_MS,
148
+ env: extraEnv ? { ...process.env, ...extraEnv } : process.env,
149
+ });
150
+ return { exitCode: 0, stdout: stdout.trim(), stderr: stderr.trim() };
151
+ } catch (error) {
152
+ const timedOut = error && (error.killed || error.signal === 'SIGTERM' || error.code === 'ETIMEDOUT');
153
+ return {
154
+ exitCode: typeof error.code === 'number' ? error.code : 1,
155
+ stdout: String(error.stdout || '').trim(),
156
+ stderr: timedOut
157
+ ? `Command timed out after ${TEST_TIMEOUT_MS}ms: ${formatCommand(command, args)}`
158
+ : String(error.stderr || error.message || error).trim(),
159
+ };
160
+ }
161
+ }
162
+
163
+ function resolvePythonExecutable() {
164
+ const workspaceRoot = getWorkspaceRoot();
165
+
166
+ const candidates = process.platform === 'win32'
167
+ ? [
168
+ path.join(workspaceRoot, '.venv', 'Scripts', 'python.exe'),
169
+ path.join(workspaceRoot, 'venv', 'Scripts', 'python.exe'),
170
+ ]
171
+ : [
172
+ path.join(workspaceRoot, '.venv', 'bin', 'python'),
173
+ path.join(workspaceRoot, 'venv', 'bin', 'python'),
174
+ ];
175
+
176
+ for (const candidate of candidates) {
177
+ if (fs.existsSync(candidate)) return candidate;
178
+ }
179
+ return 'python';
180
+ }
181
+
182
+ function readPositiveInteger(value, fallback) {
183
+ const parsed = Number.parseInt(String(value || ''), 10);
184
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
185
+ }
186
+
187
+ function normalizePath(value) {
188
+ return String(value).replace(/\\/g, '/').replace(/^\.\//, '').trim();
189
+ }
190
+
191
+ function formatCommand(command, args) {
192
+ return [quote(command), ...args.map(quote)].join(' ');
193
+ }
194
+
195
+ function quote(value) {
196
+ return /\s/.test(value) ? `"${value}"` : value;
197
+ }
198
+
199
+ module.exports = { name, canHandle, execute, getCommandPreview };