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.
Files changed (54) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +115 -0
  3. package/argo/package.json +8 -0
  4. package/argo/rules/intent-architecture-global-rule.md +45 -0
  5. package/argo/schema/ImplementationToCodingHandoff.schema.json +252 -0
  6. package/argo/schema/ImplementationToIntentTraceProposal.schema.json +180 -0
  7. package/argo/schema/IntentToImplementationHandoff.schema.json +75 -0
  8. package/argo/schema/SystemArchitecture.schema.json +378 -0
  9. package/argo/schema/archimate3.2.pdf +0 -0
  10. package/argo/scripts/ARCHITECTURE.md +57 -0
  11. package/argo/scripts/archimate32-rules.js +12301 -0
  12. package/argo/scripts/argo-mcp-server.js +629 -0
  13. package/argo/scripts/argo-paths.js +77 -0
  14. package/argo/scripts/ensureArgoHarnessEnvironment.js +340 -0
  15. package/argo/scripts/generateArchitectureDiffPlantuml.js +466 -0
  16. package/argo/scripts/graph-rag/ARCHITECTURE.md +192 -0
  17. package/argo/scripts/graph-rag/canonicalProjectionAuthority.js +45 -0
  18. package/argo/scripts/graph-rag/defaultSemanticRetrieval.js +969 -0
  19. package/argo/scripts/graph-rag/embeddingQualificationGate.js +59 -0
  20. package/argo/scripts/graph-rag/externalProductionConfig.js +74 -0
  21. package/argo/scripts/graph-rag/liveEmbeddingIndexGate.js +129 -0
  22. package/argo/scripts/graph-rag/liveEmbeddingNeo4jBoundary.js +137 -0
  23. package/argo/scripts/graph-rag/liveEmbeddingProviderClient.js +49 -0
  24. package/argo/scripts/graph-rag/liveEmbeddingProviderConfig.js +481 -0
  25. package/argo/scripts/graph-rag/mutationEmbeddingVectorLifecycle.js +1261 -0
  26. package/argo/scripts/graph-rag/neo4jNativeRetrieval.js +37 -0
  27. package/argo/scripts/graph-rag/productionGraphRagRuntime.js +1624 -0
  28. package/argo/scripts/graph-rag/semantic-persistence/ARCHITECTURE.md +51 -0
  29. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticBackfill.js +241 -0
  30. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticCheckpointStore.js +99 -0
  31. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticNeo4jAdapter.js +149 -0
  32. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticProjectionStore.js +171 -0
  33. package/argo/scripts/graph-rag/semanticOperatorError.js +38 -0
  34. package/argo/scripts/graph-rag/semanticOperatorJourney.js +459 -0
  35. package/argo/scripts/graph-rag/semanticReadinessAttestationStore.js +398 -0
  36. package/argo/scripts/graph-rag/systemMetadataCommandAdapter.js +269 -0
  37. package/argo/scripts/graph-semantics.js +220 -0
  38. package/argo/scripts/neo4j-system-architecture-store.js +777 -0
  39. package/argo/scripts/repositoryArgoEnvironment.js +101 -0
  40. package/argo/scripts/runArchitectureTests.js +583 -0
  41. package/argo/scripts/semanticOperatorJourneyCli.js +91 -0
  42. package/argo/scripts/syncSystemArchitectureToNeo4j.js +67 -0
  43. package/argo/scripts/systemarchitecture-mcp-server.js +2965 -0
  44. package/argo/scripts/test-executors/_template.js +58 -0
  45. package/argo/scripts/test-executors/default.js +199 -0
  46. package/argo/scripts/validateStageHandoff.js +459 -0
  47. package/argo/scripts/validateSystemArchitecture.js +254 -0
  48. package/argo/scripts/validateTraceProposal.js +181 -0
  49. package/argo/scripts/validator-mcp-server.js +377 -0
  50. package/argo/skills/argo-init/SKILL.md +110 -0
  51. package/bin/argo-deploy.js +12 -0
  52. package/install-argo.ps1 +112 -0
  53. package/package.json +28 -0
  54. package/vendor/neo4j-driver-6.2.0.tgz +0 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Custom Test Executor Template
3
+ *
4
+ * Copy this file to `.argo/scripts/test-executors/` with a descriptive name
5
+ * (e.g., `docker.js`, `cloud-run.js`) and implement the required interface.
6
+ *
7
+ * Each executor module must export:
8
+ * name: string — human-readable identifier for logging
9
+ * canHandle(acceptanceCriteria, workspaceRoot): boolean
10
+ * execute(acceptanceCriteria, workspaceRoot): Promise<{exitCode, stdout, stderr}>
11
+ * getCommandPreview(acceptanceCriteria, workspaceRoot): string | null (optional)
12
+ *
13
+ * Auto-discovery: any .js/.cjs/.mjs file in this directory is loaded automatically.
14
+ * Custom executors are tried BEFORE the built-in default executor.
15
+ * If canHandle() returns false, the next executor is tried.
16
+ */
17
+
18
+ const name = 'my-custom-executor';
19
+
20
+ /**
21
+ * Return true if this executor can handle the given acceptanceCriteria.
22
+ * The acceptanceCriteria is the raw value from the architecture graph's testcase.
23
+ *
24
+ * Example criteria formats this executor might handle:
25
+ * - "docker://my-image:tag /tests/run.sh"
26
+ * - "https://ci.example.com/jobs/..."
27
+ * - "cloud-function://us-central1/my-test"
28
+ */
29
+ function canHandle(acceptanceCriteria, workspaceRoot) {
30
+ // TODO: implement your matching logic
31
+ // Example: return acceptanceCriteria.startsWith('docker://');
32
+ return false;
33
+ }
34
+
35
+ /**
36
+ * Return a human-readable command preview for logging.
37
+ * Return null if no preview is available.
38
+ */
39
+ function getCommandPreview(acceptanceCriteria, workspaceRoot) {
40
+ // TODO: return a readable command string
41
+ return `[${name}] ${acceptanceCriteria}`;
42
+ }
43
+
44
+ /**
45
+ * Execute the test and return {exitCode, stdout, stderr}.
46
+ * exitCode: 0 = pass, non-zero = fail, null = execution error
47
+ */
48
+ async function execute(acceptanceCriteria, workspaceRoot) {
49
+ // TODO: implement your execution logic
50
+ // Example: spawn a Docker container, call a cloud API, etc.
51
+ return {
52
+ exitCode: 1,
53
+ stdout: '',
54
+ stderr: `${name}: not implemented`,
55
+ };
56
+ }
57
+
58
+ module.exports = { name, canHandle, execute, getCommandPreview };
@@ -0,0 +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 };