auditor-lambda 0.3.29 → 0.3.32
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/audit-code-wrapper-lib.mjs +179 -171
- package/dist/cli.js +36 -7
- package/dist/extractors/risk.js +6 -4
- package/dist/io/artifacts.d.ts +2 -0
- package/dist/io/artifacts.js +1 -0
- package/dist/io/toolingManifest.d.ts +1 -0
- package/dist/io/toolingManifest.js +1 -1
- package/dist/mcp/server.d.ts +71 -0
- package/dist/mcp/server.js +252 -213
- package/dist/orchestrator/artifactFreshness.d.ts +4 -0
- package/dist/orchestrator/artifactFreshness.js +45 -0
- package/dist/orchestrator/artifactMetadata.js +2 -51
- package/dist/orchestrator/dependencyMap.js +14 -0
- package/dist/orchestrator/internalExecutors.js +8 -0
- package/dist/orchestrator/staleness.js +2 -46
- package/dist/orchestrator/state.js +1 -1
- package/dist/orchestrator/syntaxResolutionExecutor.js +121 -13
- package/dist/orchestrator/unitBuilder.js +2 -1
- package/dist/providers/spawnLoggedCommand.js +71 -18
- package/dist/providers/types.d.ts +5 -0
- package/dist/quota/scheduler.js +10 -2
- package/dist/quota/state.js +6 -2
- package/dist/types/externalAnalyzer.d.ts +10 -0
- package/dist/types/workerSession.js +1 -2
- package/dist/validation/artifacts.js +36 -0
- package/package.json +1 -1
- package/schemas/audit_task.schema.json +2 -2
- package/schemas/risk_register.schema.json +1 -1
- package/schemas/unit_manifest.schema.json +2 -1
- package/scripts/postinstall.mjs +18 -0
|
@@ -1371,6 +1371,18 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1371
1371
|
profile: {
|
|
1372
1372
|
writeAgents: true,
|
|
1373
1373
|
},
|
|
1374
|
+
async verify({ checks, assetPaths, collectVerifyCheck: collect }) {
|
|
1375
|
+
await collect(checks, 'codex_global_surface', async () => {
|
|
1376
|
+
const content = await readFile(assetPaths.agentsInstructionsPath, 'utf8');
|
|
1377
|
+
if (!content.includes('/audit-code')) {
|
|
1378
|
+
throw new Error(`AGENTS instructions do not reference /audit-code: ${assetPaths.agentsInstructionsPath}`);
|
|
1379
|
+
}
|
|
1380
|
+
return {
|
|
1381
|
+
summary: 'Codex uses the global skill surface with AGENTS fallback instructions.',
|
|
1382
|
+
path: assetPaths.agentsInstructionsPath,
|
|
1383
|
+
};
|
|
1384
|
+
});
|
|
1385
|
+
},
|
|
1374
1386
|
},
|
|
1375
1387
|
'claude-desktop': {
|
|
1376
1388
|
host: 'claude-desktop',
|
|
@@ -1394,6 +1406,85 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1394
1406
|
profile: {
|
|
1395
1407
|
writeClaudeDesktop: true,
|
|
1396
1408
|
},
|
|
1409
|
+
async verify({ checks, root, assetPaths, collectVerifyCheck: collect }) {
|
|
1410
|
+
const bundleManifestPath = join(
|
|
1411
|
+
root,
|
|
1412
|
+
'.audit-code',
|
|
1413
|
+
'install',
|
|
1414
|
+
'claude-desktop',
|
|
1415
|
+
'bundle',
|
|
1416
|
+
'manifest.json',
|
|
1417
|
+
);
|
|
1418
|
+
const bundleServerPath = join(
|
|
1419
|
+
root,
|
|
1420
|
+
'.audit-code',
|
|
1421
|
+
'install',
|
|
1422
|
+
'claude-desktop',
|
|
1423
|
+
'bundle',
|
|
1424
|
+
'server',
|
|
1425
|
+
'index.js',
|
|
1426
|
+
);
|
|
1427
|
+
|
|
1428
|
+
await collect(checks, 'claude_bundle_manifest', async () => {
|
|
1429
|
+
const manifest = await readJson(bundleManifestPath, 'Claude Desktop bundle manifest');
|
|
1430
|
+
if (manifest?.server?.entry_point !== 'server/index.js') {
|
|
1431
|
+
throw new Error(`Claude Desktop bundle manifest has an unexpected entry_point: ${manifest?.server?.entry_point ?? 'missing'}.`);
|
|
1432
|
+
}
|
|
1433
|
+
return {
|
|
1434
|
+
summary: 'Claude Desktop bundle manifest parsed successfully.',
|
|
1435
|
+
path: bundleManifestPath,
|
|
1436
|
+
};
|
|
1437
|
+
});
|
|
1438
|
+
await collect(checks, 'claude_connector_template', async () => {
|
|
1439
|
+
const connector = await readJson(
|
|
1440
|
+
assetPaths.claudeDesktopRemoteConnectorPath,
|
|
1441
|
+
'Claude Desktop remote connector template',
|
|
1442
|
+
);
|
|
1443
|
+
if (connector?.transport !== 'remote-mcp') {
|
|
1444
|
+
throw new Error(`Claude Desktop remote connector transport must be "remote-mcp", got ${connector?.transport ?? 'missing'}.`);
|
|
1445
|
+
}
|
|
1446
|
+
return {
|
|
1447
|
+
summary: 'Claude Desktop remote connector template parsed successfully.',
|
|
1448
|
+
path: assetPaths.claudeDesktopRemoteConnectorPath,
|
|
1449
|
+
};
|
|
1450
|
+
});
|
|
1451
|
+
await collect(checks, 'claude_dxt_archive', async () => ({
|
|
1452
|
+
summary: 'Claude Desktop .dxt bundle is present.',
|
|
1453
|
+
path: assetPaths.claudeDesktopDxtPath,
|
|
1454
|
+
size_bytes: await verifyZipFile(
|
|
1455
|
+
assetPaths.claudeDesktopDxtPath,
|
|
1456
|
+
'Claude Desktop .dxt bundle',
|
|
1457
|
+
),
|
|
1458
|
+
}));
|
|
1459
|
+
await collect(checks, 'claude_mcpb_archive', async () => ({
|
|
1460
|
+
summary: 'Claude Desktop .mcpb bundle is present.',
|
|
1461
|
+
path: assetPaths.claudeDesktopMcpbPath,
|
|
1462
|
+
size_bytes: await verifyZipFile(
|
|
1463
|
+
assetPaths.claudeDesktopMcpbPath,
|
|
1464
|
+
'Claude Desktop .mcpb bundle',
|
|
1465
|
+
),
|
|
1466
|
+
}));
|
|
1467
|
+
await collect(checks, 'claude_bundle_mcp', async () => {
|
|
1468
|
+
const probe = await probeMcpServer({
|
|
1469
|
+
label: 'Claude Desktop bundle server',
|
|
1470
|
+
command: process.execPath,
|
|
1471
|
+
args: [bundleServerPath],
|
|
1472
|
+
cwd: root,
|
|
1473
|
+
env: {
|
|
1474
|
+
AUDIT_CODE_REPO_ROOT: root,
|
|
1475
|
+
AUDIT_CODE_ARTIFACTS_DIR: join(root, '.audit-artifacts'),
|
|
1476
|
+
},
|
|
1477
|
+
});
|
|
1478
|
+
const toolNames = (probe.tools?.tools ?? []).map((tool) => tool.name);
|
|
1479
|
+
if (!toolNames.includes('start_audit')) {
|
|
1480
|
+
throw new Error('Claude Desktop bundle server did not expose the start_audit tool.');
|
|
1481
|
+
}
|
|
1482
|
+
return {
|
|
1483
|
+
summary: 'Claude Desktop bundle completed an MCP handshake.',
|
|
1484
|
+
tool_count: toolNames.length,
|
|
1485
|
+
};
|
|
1486
|
+
});
|
|
1487
|
+
},
|
|
1397
1488
|
},
|
|
1398
1489
|
opencode: {
|
|
1399
1490
|
host: 'opencode',
|
|
@@ -1416,6 +1507,23 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1416
1507
|
writeOpenCode: true,
|
|
1417
1508
|
writeAgents: true,
|
|
1418
1509
|
},
|
|
1510
|
+
async verify({ checks, assetPaths, collectVerifyCheck: collect }) {
|
|
1511
|
+
await collect(checks, 'opencode_config', async () => {
|
|
1512
|
+
const config = await readJson(assetPaths.opencodeConfigPath, 'OpenCode project config');
|
|
1513
|
+
if (config?.command?.['audit-code']) {
|
|
1514
|
+
throw new Error('OpenCode project config must not define command["audit-code"]; the slash command is global npm-installed state. Run "audit-code install --host opencode" to remove the stale local command.');
|
|
1515
|
+
}
|
|
1516
|
+
if (config?.mcp?.auditor) {
|
|
1517
|
+
throw new Error('OpenCode project config must not define mcp.auditor; the MCP server is supplied by the global npm-installed config. Run "audit-code install --host opencode" to remove the stale project-level MCP entry.');
|
|
1518
|
+
}
|
|
1519
|
+
assertOpenCodeAuditPermissionConfig(config?.permission, 'permission');
|
|
1520
|
+
assertOpenCodeAuditPermissionConfig(config?.agent?.auditor?.permission, 'agent.auditor.permission');
|
|
1521
|
+
return {
|
|
1522
|
+
summary: 'OpenCode project config has audit permissions; MCP server and /audit-code command are supplied by the global npm-installed config.',
|
|
1523
|
+
path: assetPaths.opencodeConfigPath,
|
|
1524
|
+
};
|
|
1525
|
+
});
|
|
1526
|
+
},
|
|
1419
1527
|
},
|
|
1420
1528
|
vscode: {
|
|
1421
1529
|
host: 'vscode',
|
|
@@ -1439,6 +1547,39 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1439
1547
|
writeVSCode: true,
|
|
1440
1548
|
writeCopilotInstructions: true,
|
|
1441
1549
|
},
|
|
1550
|
+
async verify({ checks, assetPaths, collectVerifyCheck: collect }) {
|
|
1551
|
+
await collect(checks, 'vscode_prompt', async () => {
|
|
1552
|
+
const content = await readFile(assetPaths.vscodePromptPath, 'utf8');
|
|
1553
|
+
if (!content.includes('name: audit-code')) {
|
|
1554
|
+
throw new Error(`VS Code prompt file is missing the expected frontmatter name: ${assetPaths.vscodePromptPath}`);
|
|
1555
|
+
}
|
|
1556
|
+
const { body: promptBody } = splitFrontmatter(content);
|
|
1557
|
+
const { body: sourceBody } = splitFrontmatter(await readFile(promptAssetPath, 'utf8'));
|
|
1558
|
+
if (promptBody !== sourceBody.trimStart()) {
|
|
1559
|
+
throw new Error(
|
|
1560
|
+
`VS Code prompt body is out of sync with the source prompt. Run "audit-code install --host vscode" or "audit-code install".`,
|
|
1561
|
+
);
|
|
1562
|
+
}
|
|
1563
|
+
return {
|
|
1564
|
+
summary: 'VS Code prompt file is present and uses the source prompt body.',
|
|
1565
|
+
path: assetPaths.vscodePromptPath,
|
|
1566
|
+
};
|
|
1567
|
+
});
|
|
1568
|
+
await collect(checks, 'vscode_mcp_config', async () => {
|
|
1569
|
+
const config = await readJson(assetPaths.vscodeMcpConfigPath, 'VS Code MCP config');
|
|
1570
|
+
const args = config?.servers?.auditor?.args;
|
|
1571
|
+
if (config?.servers?.auditor?.command !== 'node') {
|
|
1572
|
+
throw new Error(`VS Code MCP config must use node as the command, got ${config?.servers?.auditor?.command ?? 'missing'}.`);
|
|
1573
|
+
}
|
|
1574
|
+
if (!Array.isArray(args) || args[0] !== '${workspaceFolder}/.audit-code/install/run-mcp-server.mjs') {
|
|
1575
|
+
throw new Error(`VS Code MCP config must point at \${workspaceFolder}/.audit-code/install/${MCP_LAUNCHER_FILENAME}.`);
|
|
1576
|
+
}
|
|
1577
|
+
return {
|
|
1578
|
+
summary: 'VS Code MCP config parsed successfully.',
|
|
1579
|
+
path: assetPaths.vscodeMcpConfigPath,
|
|
1580
|
+
};
|
|
1581
|
+
});
|
|
1582
|
+
},
|
|
1442
1583
|
},
|
|
1443
1584
|
antigravity: {
|
|
1444
1585
|
host: 'antigravity',
|
|
@@ -1465,6 +1606,28 @@ const INSTALL_HOST_DEFINITIONS = {
|
|
|
1465
1606
|
writeAntigravity: true,
|
|
1466
1607
|
writeAgents: true,
|
|
1467
1608
|
},
|
|
1609
|
+
async verify({ checks, assetPaths, collectVerifyCheck: collect }) {
|
|
1610
|
+
await collect(checks, 'antigravity_skill', async () => {
|
|
1611
|
+
const content = await readFile(assetPaths.antigravitySkillPath, 'utf8');
|
|
1612
|
+
if (!content.includes('name: audit-code')) {
|
|
1613
|
+
throw new Error('Antigravity skill SKILL.md must contain "name: audit-code" in frontmatter.');
|
|
1614
|
+
}
|
|
1615
|
+
return {
|
|
1616
|
+
summary: 'Antigravity .agent/skills/audit-code/SKILL.md is present and valid.',
|
|
1617
|
+
path: assetPaths.antigravitySkillPath,
|
|
1618
|
+
};
|
|
1619
|
+
});
|
|
1620
|
+
await collect(checks, 'antigravity_guide', async () => {
|
|
1621
|
+
const content = await readFile(assetPaths.antigravityPlanningGuidePath, 'utf8');
|
|
1622
|
+
if (!content.includes(MCP_LAUNCHER_FILENAME) || !content.includes(INSTALLED_PROMPT_FILENAME)) {
|
|
1623
|
+
throw new Error(`Antigravity guide must reference both ${MCP_LAUNCHER_FILENAME} and ${INSTALLED_PROMPT_FILENAME}.`);
|
|
1624
|
+
}
|
|
1625
|
+
return {
|
|
1626
|
+
summary: 'Antigravity planning guide references the repo-local prompt asset and MCP launcher.',
|
|
1627
|
+
path: assetPaths.antigravityPlanningGuidePath,
|
|
1628
|
+
};
|
|
1629
|
+
});
|
|
1630
|
+
},
|
|
1468
1631
|
},
|
|
1469
1632
|
};
|
|
1470
1633
|
|
|
@@ -1505,6 +1668,13 @@ function getInstallProfile(host) {
|
|
|
1505
1668
|
return profile;
|
|
1506
1669
|
}
|
|
1507
1670
|
|
|
1671
|
+
export {
|
|
1672
|
+
INSTALL_HOST_ORDER as _INSTALL_HOST_ORDER,
|
|
1673
|
+
INSTALL_HOST_DEFINITIONS as _INSTALL_HOST_DEFINITIONS,
|
|
1674
|
+
getInstallHostKeys as _getInstallHostKeys,
|
|
1675
|
+
getInstallProfile as _getInstallProfile,
|
|
1676
|
+
};
|
|
1677
|
+
|
|
1508
1678
|
function buildHostCatalog({ root, host, assets }) {
|
|
1509
1679
|
return getInstallHostKeys(host)
|
|
1510
1680
|
.map((hostKey) => {
|
|
@@ -2028,177 +2198,15 @@ async function verifyInstalledBootstrap(argv) {
|
|
|
2028
2198
|
primary_path: hostEntry.primary_path,
|
|
2029
2199
|
}));
|
|
2030
2200
|
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
path: assetPaths.agentsInstructionsPath,
|
|
2041
|
-
};
|
|
2042
|
-
});
|
|
2043
|
-
break;
|
|
2044
|
-
case 'claude-desktop': {
|
|
2045
|
-
const bundleManifestPath = join(
|
|
2046
|
-
root,
|
|
2047
|
-
'.audit-code',
|
|
2048
|
-
'install',
|
|
2049
|
-
'claude-desktop',
|
|
2050
|
-
'bundle',
|
|
2051
|
-
'manifest.json',
|
|
2052
|
-
);
|
|
2053
|
-
const bundleServerPath = join(
|
|
2054
|
-
root,
|
|
2055
|
-
'.audit-code',
|
|
2056
|
-
'install',
|
|
2057
|
-
'claude-desktop',
|
|
2058
|
-
'bundle',
|
|
2059
|
-
'server',
|
|
2060
|
-
'index.js',
|
|
2061
|
-
);
|
|
2062
|
-
|
|
2063
|
-
await collectVerifyCheck(checks, 'claude_bundle_manifest', async () => {
|
|
2064
|
-
const manifest = await readJson(bundleManifestPath, 'Claude Desktop bundle manifest');
|
|
2065
|
-
if (manifest?.server?.entry_point !== 'server/index.js') {
|
|
2066
|
-
throw new Error(`Claude Desktop bundle manifest has an unexpected entry_point: ${manifest?.server?.entry_point ?? 'missing'}.`);
|
|
2067
|
-
}
|
|
2068
|
-
return {
|
|
2069
|
-
summary: 'Claude Desktop bundle manifest parsed successfully.',
|
|
2070
|
-
path: bundleManifestPath,
|
|
2071
|
-
};
|
|
2072
|
-
});
|
|
2073
|
-
await collectVerifyCheck(checks, 'claude_connector_template', async () => {
|
|
2074
|
-
const connector = await readJson(
|
|
2075
|
-
assetPaths.claudeDesktopRemoteConnectorPath,
|
|
2076
|
-
'Claude Desktop remote connector template',
|
|
2077
|
-
);
|
|
2078
|
-
if (connector?.transport !== 'remote-mcp') {
|
|
2079
|
-
throw new Error(`Claude Desktop remote connector transport must be "remote-mcp", got ${connector?.transport ?? 'missing'}.`);
|
|
2080
|
-
}
|
|
2081
|
-
return {
|
|
2082
|
-
summary: 'Claude Desktop remote connector template parsed successfully.',
|
|
2083
|
-
path: assetPaths.claudeDesktopRemoteConnectorPath,
|
|
2084
|
-
};
|
|
2085
|
-
});
|
|
2086
|
-
await collectVerifyCheck(checks, 'claude_dxt_archive', async () => ({
|
|
2087
|
-
summary: 'Claude Desktop .dxt bundle is present.',
|
|
2088
|
-
path: assetPaths.claudeDesktopDxtPath,
|
|
2089
|
-
size_bytes: await verifyZipFile(
|
|
2090
|
-
assetPaths.claudeDesktopDxtPath,
|
|
2091
|
-
'Claude Desktop .dxt bundle',
|
|
2092
|
-
),
|
|
2093
|
-
}));
|
|
2094
|
-
await collectVerifyCheck(checks, 'claude_mcpb_archive', async () => ({
|
|
2095
|
-
summary: 'Claude Desktop .mcpb bundle is present.',
|
|
2096
|
-
path: assetPaths.claudeDesktopMcpbPath,
|
|
2097
|
-
size_bytes: await verifyZipFile(
|
|
2098
|
-
assetPaths.claudeDesktopMcpbPath,
|
|
2099
|
-
'Claude Desktop .mcpb bundle',
|
|
2100
|
-
),
|
|
2101
|
-
}));
|
|
2102
|
-
await collectVerifyCheck(checks, 'claude_bundle_mcp', async () => {
|
|
2103
|
-
const probe = await probeMcpServer({
|
|
2104
|
-
label: 'Claude Desktop bundle server',
|
|
2105
|
-
command: process.execPath,
|
|
2106
|
-
args: [bundleServerPath],
|
|
2107
|
-
cwd: root,
|
|
2108
|
-
env: {
|
|
2109
|
-
AUDIT_CODE_REPO_ROOT: root,
|
|
2110
|
-
AUDIT_CODE_ARTIFACTS_DIR: join(root, '.audit-artifacts'),
|
|
2111
|
-
},
|
|
2112
|
-
});
|
|
2113
|
-
const toolNames = (probe.tools?.tools ?? []).map((tool) => tool.name);
|
|
2114
|
-
if (!toolNames.includes('start_audit')) {
|
|
2115
|
-
throw new Error('Claude Desktop bundle server did not expose the start_audit tool.');
|
|
2116
|
-
}
|
|
2117
|
-
return {
|
|
2118
|
-
summary: 'Claude Desktop bundle completed an MCP handshake.',
|
|
2119
|
-
tool_count: toolNames.length,
|
|
2120
|
-
};
|
|
2121
|
-
});
|
|
2122
|
-
break;
|
|
2123
|
-
}
|
|
2124
|
-
case 'opencode':
|
|
2125
|
-
await collectVerifyCheck(checks, 'opencode_config', async () => {
|
|
2126
|
-
const config = await readJson(assetPaths.opencodeConfigPath, 'OpenCode project config');
|
|
2127
|
-
if (config?.command?.['audit-code']) {
|
|
2128
|
-
throw new Error('OpenCode project config must not define command["audit-code"]; the slash command is global npm-installed state. Run "audit-code install --host opencode" to remove the stale local command.');
|
|
2129
|
-
}
|
|
2130
|
-
if (config?.mcp?.auditor) {
|
|
2131
|
-
throw new Error('OpenCode project config must not define mcp.auditor; the MCP server is supplied by the global npm-installed config. Run "audit-code install --host opencode" to remove the stale project-level MCP entry.');
|
|
2132
|
-
}
|
|
2133
|
-
assertOpenCodeAuditPermissionConfig(config?.permission, 'permission');
|
|
2134
|
-
assertOpenCodeAuditPermissionConfig(config?.agent?.auditor?.permission, 'agent.auditor.permission');
|
|
2135
|
-
return {
|
|
2136
|
-
summary: 'OpenCode project config has audit permissions; MCP server and /audit-code command are supplied by the global npm-installed config.',
|
|
2137
|
-
path: assetPaths.opencodeConfigPath,
|
|
2138
|
-
};
|
|
2139
|
-
});
|
|
2140
|
-
break;
|
|
2141
|
-
case 'vscode':
|
|
2142
|
-
await collectVerifyCheck(checks, 'vscode_prompt', async () => {
|
|
2143
|
-
const content = await readFile(assetPaths.vscodePromptPath, 'utf8');
|
|
2144
|
-
if (!content.includes('name: audit-code')) {
|
|
2145
|
-
throw new Error(`VS Code prompt file is missing the expected frontmatter name: ${assetPaths.vscodePromptPath}`);
|
|
2146
|
-
}
|
|
2147
|
-
const { body: promptBody } = splitFrontmatter(content);
|
|
2148
|
-
const { body: sourceBody } = splitFrontmatter(await readFile(promptAssetPath, 'utf8'));
|
|
2149
|
-
if (promptBody !== sourceBody.trimStart()) {
|
|
2150
|
-
throw new Error(
|
|
2151
|
-
`VS Code prompt body is out of sync with the source prompt. Run "audit-code install --host vscode" or "audit-code install".`,
|
|
2152
|
-
);
|
|
2153
|
-
}
|
|
2154
|
-
return {
|
|
2155
|
-
summary: 'VS Code prompt file is present and uses the source prompt body.',
|
|
2156
|
-
path: assetPaths.vscodePromptPath,
|
|
2157
|
-
};
|
|
2158
|
-
});
|
|
2159
|
-
await collectVerifyCheck(checks, 'vscode_mcp_config', async () => {
|
|
2160
|
-
const config = await readJson(assetPaths.vscodeMcpConfigPath, 'VS Code MCP config');
|
|
2161
|
-
const args = config?.servers?.auditor?.args;
|
|
2162
|
-
if (config?.servers?.auditor?.command !== 'node') {
|
|
2163
|
-
throw new Error(`VS Code MCP config must use node as the command, got ${config?.servers?.auditor?.command ?? 'missing'}.`);
|
|
2164
|
-
}
|
|
2165
|
-
if (!Array.isArray(args) || args[0] !== '${workspaceFolder}/.audit-code/install/run-mcp-server.mjs') {
|
|
2166
|
-
throw new Error(`VS Code MCP config must point at \${workspaceFolder}/.audit-code/install/${MCP_LAUNCHER_FILENAME}.`);
|
|
2167
|
-
}
|
|
2168
|
-
return {
|
|
2169
|
-
summary: 'VS Code MCP config parsed successfully.',
|
|
2170
|
-
path: assetPaths.vscodeMcpConfigPath,
|
|
2171
|
-
};
|
|
2172
|
-
});
|
|
2173
|
-
break;
|
|
2174
|
-
case 'antigravity':
|
|
2175
|
-
await collectVerifyCheck(checks, 'antigravity_skill', async () => {
|
|
2176
|
-
const content = await readFile(assetPaths.antigravitySkillPath, 'utf8');
|
|
2177
|
-
if (!content.includes('name: audit-code')) {
|
|
2178
|
-
throw new Error('Antigravity skill SKILL.md must contain "name: audit-code" in frontmatter.');
|
|
2179
|
-
}
|
|
2180
|
-
return {
|
|
2181
|
-
summary: 'Antigravity .agent/skills/audit-code/SKILL.md is present and valid.',
|
|
2182
|
-
path: assetPaths.antigravitySkillPath,
|
|
2183
|
-
};
|
|
2184
|
-
});
|
|
2185
|
-
await collectVerifyCheck(checks, 'antigravity_guide', async () => {
|
|
2186
|
-
const content = await readFile(assetPaths.antigravityPlanningGuidePath, 'utf8');
|
|
2187
|
-
if (!content.includes(MCP_LAUNCHER_FILENAME) || !content.includes(INSTALLED_PROMPT_FILENAME)) {
|
|
2188
|
-
throw new Error(`Antigravity guide must reference both ${MCP_LAUNCHER_FILENAME} and ${INSTALLED_PROMPT_FILENAME}.`);
|
|
2189
|
-
}
|
|
2190
|
-
return {
|
|
2191
|
-
summary: 'Antigravity planning guide references the repo-local prompt asset and MCP launcher.',
|
|
2192
|
-
path: assetPaths.antigravityPlanningGuidePath,
|
|
2193
|
-
};
|
|
2194
|
-
});
|
|
2195
|
-
break;
|
|
2196
|
-
default:
|
|
2197
|
-
checks.push({
|
|
2198
|
-
id: 'host_handler',
|
|
2199
|
-
status: 'error',
|
|
2200
|
-
summary: `No verification handler is implemented for host "${hostKey}".`,
|
|
2201
|
-
});
|
|
2201
|
+
const hostDefinition = INSTALL_HOST_DEFINITIONS[hostKey];
|
|
2202
|
+
if (hostDefinition?.verify) {
|
|
2203
|
+
await hostDefinition.verify({ checks, root, assetPaths, collectVerifyCheck });
|
|
2204
|
+
} else {
|
|
2205
|
+
checks.push({
|
|
2206
|
+
id: 'host_handler',
|
|
2207
|
+
status: 'error',
|
|
2208
|
+
summary: `No verification handler is implemented for host "${hostKey}".`,
|
|
2209
|
+
});
|
|
2202
2210
|
}
|
|
2203
2211
|
|
|
2204
2212
|
hostResults.push({
|
package/dist/cli.js
CHANGED
|
@@ -112,6 +112,21 @@ function quoteCommandArg(value) {
|
|
|
112
112
|
function renderCommand(argv) {
|
|
113
113
|
return argv.map((item) => quoteCommandArg(item)).join(" ");
|
|
114
114
|
}
|
|
115
|
+
function summarizeLaunchExit(result) {
|
|
116
|
+
if (result.accepted !== false && !result.error) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const parts = [
|
|
120
|
+
result.signal
|
|
121
|
+
? `signal ${result.signal}`
|
|
122
|
+
: `exit code ${result.exitCode ?? "unknown"}`,
|
|
123
|
+
result.command ? `command: ${result.command}` : null,
|
|
124
|
+
result.stdoutPath ? `stdout: ${result.stdoutPath}` : null,
|
|
125
|
+
result.stderrPath ? `stderr: ${result.stderrPath}` : null,
|
|
126
|
+
result.error ?? null,
|
|
127
|
+
].filter((part) => Boolean(part));
|
|
128
|
+
return parts.join("; ");
|
|
129
|
+
}
|
|
115
130
|
function taskResultPath(taskResultsDir, taskId) {
|
|
116
131
|
return join(taskResultsDir, artifactNameForId(taskId, "json"));
|
|
117
132
|
}
|
|
@@ -1548,6 +1563,12 @@ async function cmdRunToCompletion(argv) {
|
|
|
1548
1563
|
? outcome.reason.message
|
|
1549
1564
|
: String(outcome.reason));
|
|
1550
1565
|
}
|
|
1566
|
+
else if (outcome?.status === "fulfilled") {
|
|
1567
|
+
const launchExitSummary = summarizeLaunchExit(outcome.value);
|
|
1568
|
+
if (launchExitSummary) {
|
|
1569
|
+
launchErrorsByRunId.set(workerSlots[index].runId, launchExitSummary);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1551
1572
|
}
|
|
1552
1573
|
// Result ingestion is intentionally sequential even though agent launch
|
|
1553
1574
|
// was parallel. Writing to coverage_matrix.json is not atomic, so
|
|
@@ -1856,8 +1877,9 @@ async function cmdRunToCompletion(argv) {
|
|
|
1856
1877
|
}
|
|
1857
1878
|
const startedAt = new Date().toISOString();
|
|
1858
1879
|
let workerResult;
|
|
1880
|
+
let launchResult = null;
|
|
1859
1881
|
try {
|
|
1860
|
-
await provider.launch({
|
|
1882
|
+
launchResult = await provider.launch({
|
|
1861
1883
|
repoRoot: root,
|
|
1862
1884
|
runId,
|
|
1863
1885
|
obligationId,
|
|
@@ -1870,9 +1892,12 @@ async function cmdRunToCompletion(argv) {
|
|
|
1870
1892
|
timeoutMs,
|
|
1871
1893
|
});
|
|
1872
1894
|
const candidate = await readJsonFile(paths.resultPath);
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1895
|
+
if (isWorkerResult(candidate)) {
|
|
1896
|
+
workerResult = candidate;
|
|
1897
|
+
}
|
|
1898
|
+
else {
|
|
1899
|
+
const launchExitSummary = summarizeLaunchExit(launchResult);
|
|
1900
|
+
workerResult = {
|
|
1876
1901
|
contract_version: WORKER_RESULT_CONTRACT_VERSION,
|
|
1877
1902
|
run_id: runId,
|
|
1878
1903
|
obligation_id: obligationId,
|
|
@@ -1880,13 +1905,17 @@ async function cmdRunToCompletion(argv) {
|
|
|
1880
1905
|
progress_made: false,
|
|
1881
1906
|
selected_executor: preferredExecutor,
|
|
1882
1907
|
artifacts_written: [],
|
|
1883
|
-
summary:
|
|
1908
|
+
summary: launchExitSummary
|
|
1909
|
+
? `Worker did not emit a valid worker result after provider exit: ${launchExitSummary}`
|
|
1910
|
+
: "Worker did not emit a valid worker result.",
|
|
1884
1911
|
next_likely_step: decision.selected_obligation,
|
|
1885
1912
|
errors: ["Invalid worker result contract."],
|
|
1886
1913
|
};
|
|
1914
|
+
}
|
|
1887
1915
|
}
|
|
1888
1916
|
catch (error) {
|
|
1889
1917
|
const message = error instanceof Error ? error.message : String(error);
|
|
1918
|
+
const launchExitSummary = launchResult && summarizeLaunchExit(launchResult);
|
|
1890
1919
|
workerResult = {
|
|
1891
1920
|
contract_version: WORKER_RESULT_CONTRACT_VERSION,
|
|
1892
1921
|
run_id: runId,
|
|
@@ -1895,9 +1924,9 @@ async function cmdRunToCompletion(argv) {
|
|
|
1895
1924
|
progress_made: false,
|
|
1896
1925
|
selected_executor: preferredExecutor,
|
|
1897
1926
|
artifacts_written: [],
|
|
1898
|
-
summary: `Worker launch failed for ${preferredExecutor}: ${message}`,
|
|
1927
|
+
summary: `Worker launch failed for ${preferredExecutor}: ${launchExitSummary ?? message}`,
|
|
1899
1928
|
next_likely_step: decision.selected_obligation,
|
|
1900
|
-
errors: [message],
|
|
1929
|
+
errors: launchExitSummary ? [message, launchExitSummary] : [message],
|
|
1901
1930
|
};
|
|
1902
1931
|
await persistWorkerRunArtifacts(paths, workerResult, "provider-launch");
|
|
1903
1932
|
}
|
package/dist/extractors/risk.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const MAX_RISK_SCORE = 10;
|
|
1
2
|
export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerResults) {
|
|
2
3
|
const flowMap = new Map();
|
|
3
4
|
for (const flow of criticalFlows?.flows ?? []) {
|
|
@@ -30,12 +31,13 @@ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerR
|
|
|
30
31
|
if (externalHits > 0) {
|
|
31
32
|
signals.push("external_analyzer_signal");
|
|
32
33
|
}
|
|
34
|
+
const riskScore = (unit.risk_score ?? 0) +
|
|
35
|
+
flowHits +
|
|
36
|
+
externalHits +
|
|
37
|
+
(signals.includes("path_level_stateful_behavior") ? 1 : 0);
|
|
33
38
|
return {
|
|
34
39
|
unit_id: unit.unit_id,
|
|
35
|
-
risk_score: (
|
|
36
|
-
flowHits +
|
|
37
|
-
externalHits +
|
|
38
|
-
(signals.includes("path_level_stateful_behavior") ? 1 : 0),
|
|
40
|
+
risk_score: Math.min(MAX_RISK_SCORE, riskScore),
|
|
39
41
|
signals,
|
|
40
42
|
notes: [
|
|
41
43
|
"Initial heuristic risk scoring.",
|
package/dist/io/artifacts.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ type ArtifactPayloadMap = {
|
|
|
26
26
|
runtime_validation_tasks: RuntimeValidationTaskManifest;
|
|
27
27
|
runtime_validation_report: RuntimeValidationReport;
|
|
28
28
|
external_analyzer_results: ExternalAnalyzerResults;
|
|
29
|
+
syntax_resolution_status: unknown;
|
|
29
30
|
audit_results: AuditResult[];
|
|
30
31
|
audit_tasks: AuditTask[];
|
|
31
32
|
audit_plan_metrics: AuditPlanMetrics;
|
|
@@ -63,6 +64,7 @@ export declare const ARTIFACT_DEFINITIONS: {
|
|
|
63
64
|
readonly runtime_validation_tasks: ArtifactDefinition<"runtime_validation_tasks">;
|
|
64
65
|
readonly runtime_validation_report: ArtifactDefinition<"runtime_validation_report">;
|
|
65
66
|
readonly external_analyzer_results: ArtifactDefinition<"external_analyzer_results">;
|
|
67
|
+
readonly syntax_resolution_status: ArtifactDefinition<"syntax_resolution_status">;
|
|
66
68
|
readonly audit_results: ArtifactDefinition<"audit_results">;
|
|
67
69
|
readonly audit_tasks: ArtifactDefinition<"audit_tasks">;
|
|
68
70
|
readonly audit_plan_metrics: ArtifactDefinition<"audit_plan_metrics">;
|
package/dist/io/artifacts.js
CHANGED
|
@@ -40,6 +40,7 @@ export const ARTIFACT_DEFINITIONS = {
|
|
|
40
40
|
runtime_validation_tasks: jsonArtifact("runtime_validation_tasks.json", "execution"),
|
|
41
41
|
runtime_validation_report: jsonArtifact("runtime_validation_report.json", "execution"),
|
|
42
42
|
external_analyzer_results: jsonArtifact("external_analyzer_results.json", "execution"),
|
|
43
|
+
syntax_resolution_status: jsonArtifact("syntax_resolution_status.json", "execution"),
|
|
43
44
|
audit_results: ndjsonArtifact("audit_results.jsonl", "execution"),
|
|
44
45
|
audit_tasks: jsonArtifact("audit_tasks.json", "execution"),
|
|
45
46
|
audit_plan_metrics: jsonArtifact("audit_plan_metrics.json", "execution"),
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { ToolingManifest } from "../types/toolingManifest.js";
|
|
2
|
+
export declare const TOOLING_INPUTS: readonly ["audit-code.mjs", "audit-code-wrapper-lib.mjs", "package.json", "dist", "schemas", "skills/audit-code"];
|
|
2
3
|
export declare function buildToolingManifest(): Promise<ToolingManifest>;
|
|
@@ -3,7 +3,7 @@ import { readdir, readFile, stat } from "node:fs/promises";
|
|
|
3
3
|
import { dirname, join, relative, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
6
|
-
const TOOLING_INPUTS = [
|
|
6
|
+
export const TOOLING_INPUTS = [
|
|
7
7
|
"audit-code.mjs",
|
|
8
8
|
"audit-code-wrapper-lib.mjs",
|
|
9
9
|
"package.json",
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1 +1,72 @@
|
|
|
1
|
+
interface ServerOptions {
|
|
2
|
+
root: string;
|
|
3
|
+
artifactsDir: string;
|
|
4
|
+
}
|
|
5
|
+
interface JsonRpcRequest {
|
|
6
|
+
jsonrpc?: string;
|
|
7
|
+
id?: string | number | null;
|
|
8
|
+
method?: string;
|
|
9
|
+
params?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface JsonRpcResponse {
|
|
12
|
+
jsonrpc: "2.0";
|
|
13
|
+
id: string | number | null;
|
|
14
|
+
result?: unknown;
|
|
15
|
+
error?: {
|
|
16
|
+
code: number;
|
|
17
|
+
message: string;
|
|
18
|
+
data?: unknown;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
interface ToolCallContext {
|
|
22
|
+
root: string;
|
|
23
|
+
artifactsDir: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function parseContentLength(headerBlock: string): number;
|
|
26
|
+
interface ResourceRegistryEntry {
|
|
27
|
+
uri: string;
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
mimeType: string;
|
|
31
|
+
read: (context: ToolCallContext) => Promise<{
|
|
32
|
+
mimeType: string;
|
|
33
|
+
text: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export declare const resourceRegistry: ResourceRegistryEntry[];
|
|
37
|
+
interface PromptRegistryEntry {
|
|
38
|
+
name: string;
|
|
39
|
+
description: string;
|
|
40
|
+
arguments: Array<{
|
|
41
|
+
name: string;
|
|
42
|
+
required?: boolean;
|
|
43
|
+
description: string;
|
|
44
|
+
}>;
|
|
45
|
+
render: (args: Record<string, unknown> | undefined) => string;
|
|
46
|
+
}
|
|
47
|
+
export declare const promptRegistry: PromptRegistryEntry[];
|
|
48
|
+
/**
|
|
49
|
+
* Extract zero or more complete Content-Length framed messages from a buffer.
|
|
50
|
+
* Returns an array of parsed body strings and the remaining unconsumed buffer.
|
|
51
|
+
* On framing errors, emits a framing error response via `emit` and resets the buffer.
|
|
52
|
+
*/
|
|
53
|
+
export declare function extractFrames(buffer: Buffer, emit: (response: JsonRpcResponse) => void): {
|
|
54
|
+
bodies: string[];
|
|
55
|
+
remaining: Buffer<ArrayBufferLike>;
|
|
56
|
+
};
|
|
57
|
+
interface DispatchContext {
|
|
58
|
+
version: string;
|
|
59
|
+
defaults: ServerOptions;
|
|
60
|
+
shutdownRequested: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Dispatch a single JSON-RPC request and return the response(s) to send,
|
|
64
|
+
* plus updated shutdown state.
|
|
65
|
+
*/
|
|
66
|
+
export declare function dispatchRequest(request: JsonRpcRequest, ctx: DispatchContext): Promise<{
|
|
67
|
+
responses: JsonRpcResponse[];
|
|
68
|
+
shutdownRequested: boolean;
|
|
69
|
+
exit?: number;
|
|
70
|
+
}>;
|
|
1
71
|
export declare function runAuditCodeMcpServer(argv: string[]): Promise<void>;
|
|
72
|
+
export {};
|