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.
- package/LICENSE +201 -201
- package/argo/package.json +8 -8
- package/argo/schema/ImplementationToCodingHandoff.schema.json +251 -251
- package/argo/schema/ImplementationToIntentTraceProposal.schema.json +180 -180
- package/argo/schema/IntentToImplementationHandoff.schema.json +74 -74
- package/argo/schema/SystemArchitecture.schema.json +378 -378
- package/argo/schema/archimate3.2.md +7153 -7153
- package/argo/scripts/archimate32-rules.js +12301 -12301
- package/argo/scripts/generateArchitectureDiffPlantuml.js +466 -466
- package/argo/scripts/graph-rag/ARCHITECTURE.md +192 -192
- package/argo/scripts/graph-rag/canonicalProjectionAuthority.js +45 -45
- package/argo/scripts/graph-rag/embeddingQualificationGate.js +59 -59
- package/argo/scripts/graph-rag/externalProductionConfig.js +74 -74
- package/argo/scripts/graph-rag/liveEmbeddingProviderClient.js +49 -49
- package/argo/scripts/graph-rag/neo4jNativeRetrieval.js +37 -37
- package/argo/scripts/graph-rag/semantic-persistence/ARCHITECTURE.md +51 -51
- package/argo/scripts/graph-rag/semantic-persistence/productionSemanticCheckpointStore.js +99 -99
- package/argo/scripts/graph-rag/semantic-persistence/productionSemanticProjectionStore.js +171 -171
- package/argo/scripts/graph-rag/semanticOperatorError.js +38 -38
- package/argo/scripts/graph-rag/semanticOperatorJourney.js +459 -459
- package/argo/scripts/graph-rag/semanticReadinessAttestationStore.js +398 -398
- package/argo/scripts/graph-rag/systemMetadataCommandAdapter.js +269 -269
- package/argo/scripts/graph-semantics.js +220 -220
- package/argo/scripts/repositoryArgoEnvironment.js +101 -101
- package/argo/scripts/runArchitectureTests.js +583 -583
- package/argo/scripts/semanticOperatorJourneyCli.js +91 -91
- package/argo/scripts/syncSystemArchitectureToNeo4j.js +66 -66
- package/argo/scripts/test-executors/_template.js +58 -58
- package/argo/scripts/test-executors/default.js +199 -199
- package/argo/scripts/validateStageHandoff.js +458 -458
- package/argo/scripts/validateSystemArchitecture.js +253 -253
- package/argo/scripts/validateTraceProposal.js +181 -181
- package/bin/argo-deploy.js +12 -12
- package/install-argo.ps1 +27 -8
- package/package.json +1 -1
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
const path = require('node:path');
|
|
2
|
-
const {
|
|
3
|
-
semanticOperatorErrorPayload,
|
|
4
|
-
} = require('./graph-rag/semanticOperatorError.js');
|
|
5
|
-
const {
|
|
6
|
-
getWorkspaceRoot,
|
|
7
|
-
} = require('./argo-paths.js');
|
|
8
|
-
|
|
9
|
-
async function runSemanticOperatorCommand({ command, options = {}, journey }) {
|
|
10
|
-
if (!journey) {
|
|
11
|
-
throw new TypeError('journey is required');
|
|
12
|
-
}
|
|
13
|
-
if (command === 'init') return journey.startNewProject(options);
|
|
14
|
-
if (command === 'backfill') return journey.runExplicitBackfill(options);
|
|
15
|
-
if (command === 'readiness') return journey.verifyReadiness(options);
|
|
16
|
-
if (command === 'query') return journey.query(options);
|
|
17
|
-
if (command === 'snapshot') return journey.readFullSnapshot();
|
|
18
|
-
throw new Error(`Unknown semantic operator command: ${command}`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function runCliProcess({
|
|
22
|
-
argv = [],
|
|
23
|
-
dependencies = {},
|
|
24
|
-
stdout = process.stdout,
|
|
25
|
-
stderr = process.stderr,
|
|
26
|
-
} = {}) {
|
|
27
|
-
const command = argv[0];
|
|
28
|
-
const parsedOptions = parseOptions(argv.slice(1));
|
|
29
|
-
const repositoryRoot = dependencies.repositoryRoot
|
|
30
|
-
|| getWorkspaceRoot();
|
|
31
|
-
const options = {
|
|
32
|
-
...parsedOptions,
|
|
33
|
-
approvedConfigurationRequest: {
|
|
34
|
-
repositoryRoot,
|
|
35
|
-
useCase: 'production-semantic-query',
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
const {
|
|
39
|
-
createDefaultProductionSemanticOperatorJourney,
|
|
40
|
-
} = require('./systemarchitecture-mcp-server.js');
|
|
41
|
-
const createSemanticOperatorJourney = dependencies.createSemanticOperatorJourney
|
|
42
|
-
|| createDefaultProductionSemanticOperatorJourney;
|
|
43
|
-
try {
|
|
44
|
-
const journey = await createSemanticOperatorJourney({ repositoryRoot });
|
|
45
|
-
const result = await runSemanticOperatorCommand({ command, options, journey });
|
|
46
|
-
stdout.write(`${JSON.stringify(result)}\n`);
|
|
47
|
-
return { exitCode: 0, result };
|
|
48
|
-
} catch (error) {
|
|
49
|
-
const result = {
|
|
50
|
-
status: 'failed',
|
|
51
|
-
error: semanticOperatorErrorPayload(error),
|
|
52
|
-
};
|
|
53
|
-
stderr.write(`${JSON.stringify(result)}\n`);
|
|
54
|
-
return { exitCode: 1, result };
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function main(argv = process.argv.slice(2)) {
|
|
59
|
-
const outcome = await runCliProcess({ argv });
|
|
60
|
-
process.exitCode = outcome.exitCode;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function parseOptions(args) {
|
|
64
|
-
const options = {};
|
|
65
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
66
|
-
const argument = args[index];
|
|
67
|
-
if (argument === '--automatic-backfill') options.automaticBackfillOptIn = true;
|
|
68
|
-
else if (argument === '--explicit-opt-in') options.explicitOptIn = true;
|
|
69
|
-
else if (argument === '--resume') options.resume = true;
|
|
70
|
-
else if (argument === '--request-json') {
|
|
71
|
-
index += 1;
|
|
72
|
-
return JSON.parse(args[index]);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return options;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (require.main === module) {
|
|
79
|
-
main().catch(error => {
|
|
80
|
-
process.stderr.write(`${JSON.stringify({
|
|
81
|
-
status: 'failed',
|
|
82
|
-
error: semanticOperatorErrorPayload(error),
|
|
83
|
-
})}\n`);
|
|
84
|
-
process.exit(1);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
module.exports = {
|
|
89
|
-
runCliProcess,
|
|
90
|
-
runSemanticOperatorCommand,
|
|
91
|
-
};
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
const {
|
|
3
|
+
semanticOperatorErrorPayload,
|
|
4
|
+
} = require('./graph-rag/semanticOperatorError.js');
|
|
5
|
+
const {
|
|
6
|
+
getWorkspaceRoot,
|
|
7
|
+
} = require('./argo-paths.js');
|
|
8
|
+
|
|
9
|
+
async function runSemanticOperatorCommand({ command, options = {}, journey }) {
|
|
10
|
+
if (!journey) {
|
|
11
|
+
throw new TypeError('journey is required');
|
|
12
|
+
}
|
|
13
|
+
if (command === 'init') return journey.startNewProject(options);
|
|
14
|
+
if (command === 'backfill') return journey.runExplicitBackfill(options);
|
|
15
|
+
if (command === 'readiness') return journey.verifyReadiness(options);
|
|
16
|
+
if (command === 'query') return journey.query(options);
|
|
17
|
+
if (command === 'snapshot') return journey.readFullSnapshot();
|
|
18
|
+
throw new Error(`Unknown semantic operator command: ${command}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function runCliProcess({
|
|
22
|
+
argv = [],
|
|
23
|
+
dependencies = {},
|
|
24
|
+
stdout = process.stdout,
|
|
25
|
+
stderr = process.stderr,
|
|
26
|
+
} = {}) {
|
|
27
|
+
const command = argv[0];
|
|
28
|
+
const parsedOptions = parseOptions(argv.slice(1));
|
|
29
|
+
const repositoryRoot = dependencies.repositoryRoot
|
|
30
|
+
|| getWorkspaceRoot();
|
|
31
|
+
const options = {
|
|
32
|
+
...parsedOptions,
|
|
33
|
+
approvedConfigurationRequest: {
|
|
34
|
+
repositoryRoot,
|
|
35
|
+
useCase: 'production-semantic-query',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
const {
|
|
39
|
+
createDefaultProductionSemanticOperatorJourney,
|
|
40
|
+
} = require('./systemarchitecture-mcp-server.js');
|
|
41
|
+
const createSemanticOperatorJourney = dependencies.createSemanticOperatorJourney
|
|
42
|
+
|| createDefaultProductionSemanticOperatorJourney;
|
|
43
|
+
try {
|
|
44
|
+
const journey = await createSemanticOperatorJourney({ repositoryRoot });
|
|
45
|
+
const result = await runSemanticOperatorCommand({ command, options, journey });
|
|
46
|
+
stdout.write(`${JSON.stringify(result)}\n`);
|
|
47
|
+
return { exitCode: 0, result };
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const result = {
|
|
50
|
+
status: 'failed',
|
|
51
|
+
error: semanticOperatorErrorPayload(error),
|
|
52
|
+
};
|
|
53
|
+
stderr.write(`${JSON.stringify(result)}\n`);
|
|
54
|
+
return { exitCode: 1, result };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function main(argv = process.argv.slice(2)) {
|
|
59
|
+
const outcome = await runCliProcess({ argv });
|
|
60
|
+
process.exitCode = outcome.exitCode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parseOptions(args) {
|
|
64
|
+
const options = {};
|
|
65
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
66
|
+
const argument = args[index];
|
|
67
|
+
if (argument === '--automatic-backfill') options.automaticBackfillOptIn = true;
|
|
68
|
+
else if (argument === '--explicit-opt-in') options.explicitOptIn = true;
|
|
69
|
+
else if (argument === '--resume') options.resume = true;
|
|
70
|
+
else if (argument === '--request-json') {
|
|
71
|
+
index += 1;
|
|
72
|
+
return JSON.parse(args[index]);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return options;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (require.main === module) {
|
|
79
|
+
main().catch(error => {
|
|
80
|
+
process.stderr.write(`${JSON.stringify({
|
|
81
|
+
status: 'failed',
|
|
82
|
+
error: semanticOperatorErrorPayload(error),
|
|
83
|
+
})}\n`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
runCliProcess,
|
|
90
|
+
runSemanticOperatorCommand,
|
|
91
|
+
};
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
const {
|
|
2
|
-
DEFAULT_GRAPH_PATH,
|
|
3
|
-
getNeo4jConfig,
|
|
4
|
-
syncArchitectureToNeo4j,
|
|
5
|
-
verifyArchitectureSync,
|
|
6
|
-
} = require('./neo4j-system-architecture-store.js');
|
|
7
|
-
|
|
8
|
-
async function main() {
|
|
9
|
-
const args = parseArgs(process.argv.slice(2));
|
|
10
|
-
const architecturePath = args.architecturePath || DEFAULT_GRAPH_PATH;
|
|
11
|
-
const config = getNeo4jConfig({
|
|
12
|
-
database: args.database,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const result = args.verifyOnly
|
|
16
|
-
? await verifyArchitectureSync({ architecturePath, ...config })
|
|
17
|
-
: await syncArchitectureToNeo4j({ architecturePath, ...config });
|
|
18
|
-
|
|
19
|
-
const verification = args.verifyOnly ? result : result.verification;
|
|
20
|
-
if (!verification.matches) {
|
|
21
|
-
console.error('Neo4j sync verification failed.');
|
|
22
|
-
console.error(JSON.stringify(verification, null, 2));
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const output = {
|
|
27
|
-
mode: args.verifyOnly ? 'verify' : 'sync',
|
|
28
|
-
architecturePath,
|
|
29
|
-
database: config.database,
|
|
30
|
-
databaseProvision: verification.databaseProvision || (result && result.databaseProvision) || null,
|
|
31
|
-
uri: config.uri,
|
|
32
|
-
counts: verification.actual,
|
|
33
|
-
matches: verification.matches,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
console.log(JSON.stringify(output, null, 2));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function parseArgs(argv) {
|
|
40
|
-
const args = {};
|
|
41
|
-
|
|
42
|
-
for (let index = 0; index < argv.length; index += 1) {
|
|
43
|
-
const token = argv[index];
|
|
44
|
-
if (token === '--verify') {
|
|
45
|
-
args.verifyOnly = true;
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
if (token === '--architecture-path') {
|
|
49
|
-
args.architecturePath = argv[index + 1];
|
|
50
|
-
index += 1;
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
if (token === '--database') {
|
|
54
|
-
args.database = argv[index + 1];
|
|
55
|
-
index += 1;
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
throw new Error(`Unsupported argument: ${token}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return args;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
main().catch(error => {
|
|
65
|
-
console.error(String(error && error.stack ? error.stack : error));
|
|
66
|
-
process.exit(1);
|
|
1
|
+
const {
|
|
2
|
+
DEFAULT_GRAPH_PATH,
|
|
3
|
+
getNeo4jConfig,
|
|
4
|
+
syncArchitectureToNeo4j,
|
|
5
|
+
verifyArchitectureSync,
|
|
6
|
+
} = require('./neo4j-system-architecture-store.js');
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const args = parseArgs(process.argv.slice(2));
|
|
10
|
+
const architecturePath = args.architecturePath || DEFAULT_GRAPH_PATH;
|
|
11
|
+
const config = getNeo4jConfig({
|
|
12
|
+
database: args.database,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const result = args.verifyOnly
|
|
16
|
+
? await verifyArchitectureSync({ architecturePath, ...config })
|
|
17
|
+
: await syncArchitectureToNeo4j({ architecturePath, ...config });
|
|
18
|
+
|
|
19
|
+
const verification = args.verifyOnly ? result : result.verification;
|
|
20
|
+
if (!verification.matches) {
|
|
21
|
+
console.error('Neo4j sync verification failed.');
|
|
22
|
+
console.error(JSON.stringify(verification, null, 2));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const output = {
|
|
27
|
+
mode: args.verifyOnly ? 'verify' : 'sync',
|
|
28
|
+
architecturePath,
|
|
29
|
+
database: config.database,
|
|
30
|
+
databaseProvision: verification.databaseProvision || (result && result.databaseProvision) || null,
|
|
31
|
+
uri: config.uri,
|
|
32
|
+
counts: verification.actual,
|
|
33
|
+
matches: verification.matches,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
console.log(JSON.stringify(output, null, 2));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function parseArgs(argv) {
|
|
40
|
+
const args = {};
|
|
41
|
+
|
|
42
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
43
|
+
const token = argv[index];
|
|
44
|
+
if (token === '--verify') {
|
|
45
|
+
args.verifyOnly = true;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (token === '--architecture-path') {
|
|
49
|
+
args.architecturePath = argv[index + 1];
|
|
50
|
+
index += 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (token === '--database') {
|
|
54
|
+
args.database = argv[index + 1];
|
|
55
|
+
index += 1;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Unsupported argument: ${token}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return args;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
main().catch(error => {
|
|
65
|
+
console.error(String(error && error.stack ? error.stack : error));
|
|
66
|
+
process.exit(1);
|
|
67
67
|
});
|
|
@@ -1,58 +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 };
|
|
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 };
|