auditor-lambda 0.2.6 → 0.2.8
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/README.md +23 -7
- package/audit-code-wrapper-lib.mjs +1605 -330
- package/dist/cli.js +78 -16
- package/dist/coverage.d.ts +2 -2
- package/dist/coverage.js +5 -5
- package/dist/extractors/disposition.js +10 -1
- package/dist/extractors/flows.js +7 -1
- package/dist/extractors/pathPatterns.d.ts +3 -0
- package/dist/extractors/pathPatterns.js +15 -0
- package/dist/extractors/risk.js +7 -1
- package/dist/io/artifacts.d.ts +6 -6
- package/dist/io/artifacts.js +14 -17
- package/dist/io/json.d.ts +2 -0
- package/dist/io/json.js +15 -0
- package/dist/io/runArtifacts.d.ts +1 -0
- package/dist/io/runArtifacts.js +18 -4
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +579 -0
- package/dist/orchestrator/advance.js +9 -2
- package/dist/orchestrator/dependencyMap.js +9 -13
- package/dist/orchestrator/executors.js +7 -2
- package/dist/orchestrator/flowRequeue.js +1 -1
- package/dist/orchestrator/internalExecutors.d.ts +2 -1
- package/dist/orchestrator/internalExecutors.js +120 -63
- package/dist/orchestrator/requeue.js +9 -4
- package/dist/orchestrator/resultIngestion.js +5 -6
- package/dist/orchestrator/runtimeValidation.d.ts +7 -2
- package/dist/orchestrator/runtimeValidation.js +61 -49
- package/dist/orchestrator/runtimeValidationUpdate.js +2 -4
- package/dist/orchestrator/state.js +18 -13
- package/dist/orchestrator/trivialAudit.js +8 -5
- package/dist/prompts/renderWorkerPrompt.js +3 -2
- package/dist/reporting/mergeFindings.js +0 -11
- package/dist/reporting/synthesis.d.ts +25 -22
- package/dist/reporting/synthesis.js +92 -59
- package/dist/reporting/workBlocks.d.ts +12 -3
- package/dist/reporting/workBlocks.js +124 -70
- package/dist/types/flows.d.ts +2 -0
- package/dist/types/runtimeValidation.d.ts +2 -1
- package/dist/types.d.ts +4 -7
- package/dist/validation/auditResults.js +64 -99
- package/docs/agent-integrations.md +38 -29
- package/docs/artifacts.md +16 -56
- package/docs/bootstrap-install.md +60 -30
- package/docs/contract.md +22 -205
- package/docs/next-steps.md +59 -44
- package/docs/packaging.md +13 -3
- package/docs/production-launch-bar.md +2 -2
- package/docs/production-readiness.md +9 -5
- package/docs/releasing.md +81 -0
- package/package.json +4 -1
- package/schemas/audit_result.schema.json +4 -6
- package/schemas/runtime_validation_report.schema.json +1 -1
- package/skills/audit-code/SKILL.md +11 -2
- package/skills/audit-code/audit-code.prompt.md +5 -8
- package/schemas/merged_findings.schema.json +0 -19
- package/schemas/root_cause_clusters.schema.json +0 -28
- package/schemas/synthesis_report.schema.json +0 -61
package/dist/cli.js
CHANGED
|
@@ -7,14 +7,14 @@ import { buildCriticalFlowManifest } from "./extractors/flows.js";
|
|
|
7
7
|
import { buildSurfaceManifest } from "./extractors/surfaces.js";
|
|
8
8
|
import { buildUnitManifest } from "./orchestrator/unitBuilder.js";
|
|
9
9
|
import { buildFlowCoverage } from "./orchestrator/flowCoverage.js";
|
|
10
|
-
import { buildRuntimeValidationTasks,
|
|
10
|
+
import { buildRuntimeValidationTasks, } from "./orchestrator/runtimeValidation.js";
|
|
11
11
|
import { initializeCoverageFromPlan } from "./orchestrator/planning.js";
|
|
12
|
-
import { loadArtifactBundle, writeCoreArtifacts,
|
|
12
|
+
import { loadArtifactBundle, writeCoreArtifacts, promoteFinalAuditReport, } from "./io/artifacts.js";
|
|
13
13
|
import { readJsonFile, writeJsonFile } from "./io/json.js";
|
|
14
14
|
import { validateArtifactBundle } from "./validation/artifacts.js";
|
|
15
15
|
import { validateAuditResults, formatAuditResultIssues, } from "./validation/auditResults.js";
|
|
16
16
|
import { validateConfiguredProviderEnvironment, validateSessionConfig, } from "./validation/sessionConfig.js";
|
|
17
|
-
import {
|
|
17
|
+
import { buildAuditReportModel, renderAuditReportMarkdown, } from "./reporting/synthesis.js";
|
|
18
18
|
import { deriveAuditState } from "./orchestrator/state.js";
|
|
19
19
|
import { advanceAudit } from "./orchestrator/advance.js";
|
|
20
20
|
import { decideNextStep } from "./orchestrator/nextStep.js";
|
|
@@ -22,9 +22,10 @@ import { createFreshSessionProvider, resolveFreshSessionProviderName, } from "./
|
|
|
22
22
|
import { appendRunLedgerEntry } from "./supervisor/runLedger.js";
|
|
23
23
|
import { buildAuditCodeHandoff, writeAuditCodeHandoffArtifacts, } from "./supervisor/operatorHandoff.js";
|
|
24
24
|
import { getSessionConfigPath, loadSessionConfig, readSessionConfigFile, } from "./supervisor/sessionConfig.js";
|
|
25
|
-
import { buildRunId, ensureSupervisorDirs, getRunPaths, writeWorkerTaskFiles, } from "./io/runArtifacts.js";
|
|
25
|
+
import { clearDispatchFiles, buildRunId, ensureSupervisorDirs, getRunPaths, writeWorkerTaskFiles, } from "./io/runArtifacts.js";
|
|
26
26
|
import { renderWorkerPrompt } from "./prompts/renderWorkerPrompt.js";
|
|
27
27
|
import { LOCAL_SUBPROCESS_PROVIDER_NAME } from "./providers/constants.js";
|
|
28
|
+
import { runAuditCodeMcpServer } from "./mcp/server.js";
|
|
28
29
|
const ADVANCE_AUDIT_CONTRACT_VERSION = "audit-code/v1alpha1";
|
|
29
30
|
const WORKER_RESULT_CONTRACT_VERSION = "audit-code-worker-result/v1alpha1";
|
|
30
31
|
const DEFAULT_MAX_RUNS = 1000;
|
|
@@ -401,18 +402,35 @@ export async function runSample() {
|
|
|
401
402
|
pass_id: "pass:security",
|
|
402
403
|
lens: "security",
|
|
403
404
|
agent_role: "security-auditor",
|
|
404
|
-
|
|
405
|
-
{ path: "src/api/auth.ts", start: 1, end: 100, line_count: 100 },
|
|
406
|
-
],
|
|
405
|
+
file_coverage: [{ path: "src/api/auth.ts", total_lines: 100 }],
|
|
407
406
|
findings: [],
|
|
408
407
|
notes: ["Sample result ingestion path."],
|
|
409
408
|
requires_followup: false,
|
|
410
409
|
},
|
|
411
410
|
];
|
|
412
411
|
const flowCoverage = buildFlowCoverage(criticalFlows, coverage);
|
|
413
|
-
const runtimeValidationTasks = buildRuntimeValidationTasks(
|
|
414
|
-
|
|
415
|
-
|
|
412
|
+
const runtimeValidationTasks = buildRuntimeValidationTasks({
|
|
413
|
+
unitManifest,
|
|
414
|
+
criticalFlows,
|
|
415
|
+
flowCoverage,
|
|
416
|
+
command: ["npm", "test"],
|
|
417
|
+
});
|
|
418
|
+
const runtimeValidationReport = {
|
|
419
|
+
results: runtimeValidationTasks.tasks.map((task) => ({
|
|
420
|
+
task_id: task.id,
|
|
421
|
+
status: "confirmed",
|
|
422
|
+
summary: "Sample runtime validation completed.",
|
|
423
|
+
evidence: [],
|
|
424
|
+
notes: [],
|
|
425
|
+
})),
|
|
426
|
+
};
|
|
427
|
+
const auditReport = renderAuditReportMarkdown(buildAuditReportModel({
|
|
428
|
+
results: sampleResults,
|
|
429
|
+
unitManifest,
|
|
430
|
+
criticalFlows,
|
|
431
|
+
coverageMatrix: coverage,
|
|
432
|
+
runtimeValidationReport,
|
|
433
|
+
}));
|
|
416
434
|
const auditState = deriveAuditState({
|
|
417
435
|
repo_manifest: repoManifest,
|
|
418
436
|
file_disposition: disposition,
|
|
@@ -424,7 +442,7 @@ export async function runSample() {
|
|
|
424
442
|
runtime_validation_tasks: runtimeValidationTasks,
|
|
425
443
|
runtime_validation_report: runtimeValidationReport,
|
|
426
444
|
audit_results: sampleResults,
|
|
427
|
-
|
|
445
|
+
audit_report: auditReport,
|
|
428
446
|
});
|
|
429
447
|
const artifactsDir = getArtifactsDir(process.argv);
|
|
430
448
|
await mkdir(artifactsDir, { recursive: true });
|
|
@@ -439,7 +457,7 @@ export async function runSample() {
|
|
|
439
457
|
runtime_validation_tasks: runtimeValidationTasks,
|
|
440
458
|
runtime_validation_report: runtimeValidationReport,
|
|
441
459
|
audit_results: sampleResults,
|
|
442
|
-
|
|
460
|
+
audit_report: auditReport,
|
|
443
461
|
audit_state: auditState,
|
|
444
462
|
});
|
|
445
463
|
console.log(JSON.stringify({ audit_state: auditState, artifacts_dir: artifactsDir }, null, 2));
|
|
@@ -459,6 +477,9 @@ async function cmdAdvanceAudit(argv) {
|
|
|
459
477
|
artifactsDir,
|
|
460
478
|
batchDir: batchResultsDir,
|
|
461
479
|
});
|
|
480
|
+
if (result.selected_executor !== "agent") {
|
|
481
|
+
await clearDispatchFiles(artifactsDir);
|
|
482
|
+
}
|
|
462
483
|
await emitEnvelope({
|
|
463
484
|
root,
|
|
464
485
|
artifactsDir,
|
|
@@ -473,7 +494,7 @@ async function cmdAdvanceAudit(argv) {
|
|
|
473
494
|
providerName,
|
|
474
495
|
});
|
|
475
496
|
if (result.audit_state.status === "complete") {
|
|
476
|
-
await
|
|
497
|
+
await promoteFinalAuditReport({ artifactsDir, repoRoot: root });
|
|
477
498
|
}
|
|
478
499
|
return;
|
|
479
500
|
}
|
|
@@ -487,6 +508,9 @@ async function cmdAdvanceAudit(argv) {
|
|
|
487
508
|
runtimeUpdatesPath: getFlag(argv, "--updates"),
|
|
488
509
|
externalAnalyzerPath,
|
|
489
510
|
});
|
|
511
|
+
if (result.selected_executor !== "agent") {
|
|
512
|
+
await clearDispatchFiles(artifactsDir);
|
|
513
|
+
}
|
|
490
514
|
await emitEnvelope({
|
|
491
515
|
root,
|
|
492
516
|
artifactsDir,
|
|
@@ -501,7 +525,7 @@ async function cmdAdvanceAudit(argv) {
|
|
|
501
525
|
providerName,
|
|
502
526
|
});
|
|
503
527
|
if (result.audit_state.status === "complete") {
|
|
504
|
-
await
|
|
528
|
+
await promoteFinalAuditReport({ artifactsDir, repoRoot: root });
|
|
505
529
|
}
|
|
506
530
|
}
|
|
507
531
|
async function cmdRunToCompletion(argv) {
|
|
@@ -646,6 +670,7 @@ async function cmdRunToCompletion(argv) {
|
|
|
646
670
|
}
|
|
647
671
|
if (!preferredExecutor) {
|
|
648
672
|
const state = bundle.audit_state ?? decision.state;
|
|
673
|
+
await clearDispatchFiles(artifactsDir);
|
|
649
674
|
await emitEnvelope({
|
|
650
675
|
root,
|
|
651
676
|
artifactsDir,
|
|
@@ -666,7 +691,7 @@ async function cmdRunToCompletion(argv) {
|
|
|
666
691
|
providerName: provider.name,
|
|
667
692
|
});
|
|
668
693
|
if (state.status === "complete") {
|
|
669
|
-
await
|
|
694
|
+
await promoteFinalAuditReport({ artifactsDir, repoRoot: root });
|
|
670
695
|
}
|
|
671
696
|
return;
|
|
672
697
|
}
|
|
@@ -989,6 +1014,9 @@ async function cmdRunToCompletion(argv) {
|
|
|
989
1014
|
const bundle = await loadArtifactBundle(artifactsDir);
|
|
990
1015
|
const decision = decideNextStep(bundle);
|
|
991
1016
|
const state = bundle.audit_state ?? decision.state;
|
|
1017
|
+
if (state.status === "complete") {
|
|
1018
|
+
await clearDispatchFiles(artifactsDir);
|
|
1019
|
+
}
|
|
992
1020
|
await emitEnvelope({
|
|
993
1021
|
root,
|
|
994
1022
|
artifactsDir,
|
|
@@ -1236,6 +1264,31 @@ async function cmdValidate(argv) {
|
|
|
1236
1264
|
}, null, 2));
|
|
1237
1265
|
process.exitCode = issues.length > 0 ? 1 : 0;
|
|
1238
1266
|
}
|
|
1267
|
+
async function cmdValidateResults(argv) {
|
|
1268
|
+
const artifactsDir = getArtifactsDir(argv);
|
|
1269
|
+
const resultsPath = getFlag(argv, "--results");
|
|
1270
|
+
if (!resultsPath) {
|
|
1271
|
+
throw new Error("validate-results requires --results <file>");
|
|
1272
|
+
}
|
|
1273
|
+
const bundle = await loadArtifactBundle(artifactsDir);
|
|
1274
|
+
const lineIndex = bundle.repo_manifest
|
|
1275
|
+
? await buildLineIndex(getRootDir(argv), bundle.repo_manifest)
|
|
1276
|
+
: undefined;
|
|
1277
|
+
const auditResults = await readJsonFile(resultsPath);
|
|
1278
|
+
const issues = validateAuditResults(auditResults, bundle.audit_tasks ?? [], {
|
|
1279
|
+
lineIndex,
|
|
1280
|
+
});
|
|
1281
|
+
const errors = issues.filter((issue) => issue.severity === "error");
|
|
1282
|
+
const warnings = issues.filter((issue) => issue.severity === "warning");
|
|
1283
|
+
console.log(JSON.stringify({
|
|
1284
|
+
artifacts_dir: artifactsDir,
|
|
1285
|
+
results_path: resolve(resultsPath),
|
|
1286
|
+
warning_count: warnings.length,
|
|
1287
|
+
error_count: errors.length,
|
|
1288
|
+
issues,
|
|
1289
|
+
}, null, 2));
|
|
1290
|
+
process.exitCode = errors.length > 0 ? 1 : 0;
|
|
1291
|
+
}
|
|
1239
1292
|
async function cmdRequeue(argv) {
|
|
1240
1293
|
const artifactsDir = getArtifactsDir(argv);
|
|
1241
1294
|
const bundle = await loadArtifactBundle(artifactsDir);
|
|
@@ -1257,6 +1310,9 @@ async function cmdSynthesize(argv) {
|
|
|
1257
1310
|
progress_summary: result.progress_summary,
|
|
1258
1311
|
}, null, 2));
|
|
1259
1312
|
}
|
|
1313
|
+
async function cmdMcp(argv) {
|
|
1314
|
+
await runAuditCodeMcpServer(argv.slice(3));
|
|
1315
|
+
}
|
|
1260
1316
|
async function main(argv) {
|
|
1261
1317
|
const command = argv[2] ?? "sample-run";
|
|
1262
1318
|
switch (command) {
|
|
@@ -1293,15 +1349,21 @@ async function main(argv) {
|
|
|
1293
1349
|
case "validate":
|
|
1294
1350
|
await cmdValidate(argv);
|
|
1295
1351
|
return;
|
|
1352
|
+
case "validate-results":
|
|
1353
|
+
await cmdValidateResults(argv);
|
|
1354
|
+
return;
|
|
1296
1355
|
case "requeue":
|
|
1297
1356
|
await cmdRequeue(argv);
|
|
1298
1357
|
return;
|
|
1299
1358
|
case "synthesize":
|
|
1300
1359
|
await cmdSynthesize(argv);
|
|
1301
1360
|
return;
|
|
1361
|
+
case "mcp":
|
|
1362
|
+
await cmdMcp(argv);
|
|
1363
|
+
return;
|
|
1302
1364
|
default:
|
|
1303
1365
|
console.error(`Unknown command: ${command}`);
|
|
1304
|
-
console.error("Available commands: sample-run, advance-audit, run-to-completion, worker-run, import-external-analyzer, intake, plan, ingest-results, explain-task, update-runtime-validation, validate, requeue, synthesize");
|
|
1366
|
+
console.error("Available commands: sample-run, advance-audit, run-to-completion, worker-run, import-external-analyzer, intake, plan, ingest-results, explain-task, update-runtime-validation, validate, validate-results, requeue, synthesize, mcp");
|
|
1305
1367
|
process.exitCode = 1;
|
|
1306
1368
|
}
|
|
1307
1369
|
}
|
package/dist/coverage.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { CoverageFileRecord, CoverageMatrix,
|
|
1
|
+
import type { CoverageFileRecord, CoverageMatrix, FileCoverageRecord, Lens } from "./types.js";
|
|
2
2
|
export declare function createCoverageMatrix(paths: string[]): CoverageMatrix;
|
|
3
3
|
export declare function markExcludedPath(matrix: CoverageMatrix, path: string, classificationStatus: string): void;
|
|
4
4
|
export declare function applyUnitCoverage(matrix: CoverageMatrix, path: string, unitId: string, requiredLenses: Lens[]): void;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function applyFileCoverage(matrix: CoverageMatrix, fileCoverage: FileCoverageRecord[]): void;
|
|
6
6
|
export declare function findUncoveredFiles(matrix: CoverageMatrix): CoverageFileRecord[];
|
|
7
7
|
export declare function buildRequeueTargets(matrix: CoverageMatrix): Array<{
|
|
8
8
|
path: string;
|
package/dist/coverage.js
CHANGED
|
@@ -32,13 +32,13 @@ export function applyUnitCoverage(matrix, path, unitId, requiredLenses) {
|
|
|
32
32
|
...new Set([...record.required_lenses, ...requiredLenses]),
|
|
33
33
|
];
|
|
34
34
|
}
|
|
35
|
-
export function
|
|
36
|
-
for (const
|
|
37
|
-
const record = matrix.files.find((file) => file.path ===
|
|
35
|
+
export function applyFileCoverage(matrix, fileCoverage) {
|
|
36
|
+
for (const coverage of fileCoverage) {
|
|
37
|
+
const record = matrix.files.find((file) => file.path === coverage.path);
|
|
38
38
|
if (!record || record.audit_status === "excluded")
|
|
39
39
|
continue;
|
|
40
|
-
if (
|
|
41
|
-
record.completed_lenses.push(
|
|
40
|
+
if (coverage.lens && !record.completed_lenses.includes(coverage.lens)) {
|
|
41
|
+
record.completed_lenses.push(coverage.lens);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
for (const file of matrix.files) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNodeModulesOrGit, isBuildOutput, isVendorPath, isBinaryArtifact, isDocPath, } from "./pathPatterns.js";
|
|
1
|
+
import { isNodeModulesOrGit, isBuildOutput, isVendorPath, isBinaryArtifact, isLicensePath, isLockfilePath, isLogPath, isDocPath, } from "./pathPatterns.js";
|
|
2
2
|
function inferDisposition(path) {
|
|
3
3
|
const normalized = path.toLowerCase();
|
|
4
4
|
if (isNodeModulesOrGit(normalized)) {
|
|
@@ -17,6 +17,15 @@ function inferDisposition(path) {
|
|
|
17
17
|
reason: "Non-source binary-like artifact.",
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
if (isLogPath(normalized)) {
|
|
21
|
+
return { path, status: "generated", reason: "Runtime log artifact." };
|
|
22
|
+
}
|
|
23
|
+
if (isLicensePath(normalized)) {
|
|
24
|
+
return { path, status: "doc_only", reason: "License file is not auditable code." };
|
|
25
|
+
}
|
|
26
|
+
if (isLockfilePath(normalized)) {
|
|
27
|
+
return { path, status: "generated", reason: "Lockfile excluded from code audit scope." };
|
|
28
|
+
}
|
|
20
29
|
if (isDocPath(normalized)) {
|
|
21
30
|
return { path, status: "doc_only", reason: "Documentation artifact." };
|
|
22
31
|
}
|
package/dist/extractors/flows.js
CHANGED
|
@@ -94,6 +94,7 @@ export function buildCriticalFlowManifest(repoManifest, surfaceManifest, disposi
|
|
|
94
94
|
entrypoints: [entry],
|
|
95
95
|
paths,
|
|
96
96
|
concerns: inferConcerns(paths),
|
|
97
|
+
confidence: paths.length > 1 ? "high" : "low",
|
|
97
98
|
notes: [
|
|
98
99
|
"Heuristic critical-flow inference from detected surfaces and related paths.",
|
|
99
100
|
],
|
|
@@ -108,9 +109,14 @@ export function buildCriticalFlowManifest(repoManifest, surfaceManifest, disposi
|
|
|
108
109
|
entrypoints: [path],
|
|
109
110
|
paths: relatedPaths(path, availablePaths),
|
|
110
111
|
concerns: ["data_integrity", "reliability"],
|
|
112
|
+
confidence: "high",
|
|
111
113
|
notes: ["Heuristic data-evolution flow."],
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
|
-
|
|
117
|
+
const deduped = dedupeFlows(flows);
|
|
118
|
+
return {
|
|
119
|
+
flows: deduped,
|
|
120
|
+
fallback_required: deduped.length === 0 || deduped.some((flow) => flow.confidence === "low"),
|
|
121
|
+
};
|
|
116
122
|
}
|
|
@@ -7,6 +7,9 @@ export declare function isNodeModulesOrGit(normalized: string): boolean;
|
|
|
7
7
|
export declare function isBuildOutput(normalized: string): boolean;
|
|
8
8
|
export declare function isVendorPath(normalized: string): boolean;
|
|
9
9
|
export declare function isBinaryArtifact(normalized: string): boolean;
|
|
10
|
+
export declare function isLogPath(normalized: string): boolean;
|
|
11
|
+
export declare function isLicensePath(normalized: string): boolean;
|
|
12
|
+
export declare function isLockfilePath(normalized: string): boolean;
|
|
10
13
|
export declare function isDocPath(normalized: string): boolean;
|
|
11
14
|
export declare function isTestPath(normalized: string): boolean;
|
|
12
15
|
export declare function isInterfacePath(normalized: string): boolean;
|
|
@@ -21,6 +21,21 @@ export function isBinaryArtifact(normalized) {
|
|
|
21
21
|
normalized.endsWith(".pdf") ||
|
|
22
22
|
normalized.endsWith(".zip"));
|
|
23
23
|
}
|
|
24
|
+
export function isLogPath(normalized) {
|
|
25
|
+
return normalized.endsWith(".log") || normalized.includes("stdout.log") || normalized.includes("stderr.log");
|
|
26
|
+
}
|
|
27
|
+
export function isLicensePath(normalized) {
|
|
28
|
+
const base = normalized.split(/[/\\]/).pop() ?? normalized;
|
|
29
|
+
return base === "license" || base.startsWith("license.");
|
|
30
|
+
}
|
|
31
|
+
export function isLockfilePath(normalized) {
|
|
32
|
+
return (normalized.endsWith("package-lock.json") ||
|
|
33
|
+
normalized.endsWith("pnpm-lock.yaml") ||
|
|
34
|
+
normalized.endsWith("yarn.lock") ||
|
|
35
|
+
normalized.endsWith("cargo.lock") ||
|
|
36
|
+
normalized.endsWith("composer.lock") ||
|
|
37
|
+
normalized.endsWith("go.sum"));
|
|
38
|
+
}
|
|
24
39
|
export function isDocPath(normalized) {
|
|
25
40
|
return normalized.endsWith(".md") || normalized.startsWith("docs/");
|
|
26
41
|
}
|
package/dist/extractors/risk.js
CHANGED
|
@@ -19,6 +19,9 @@ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerR
|
|
|
19
19
|
signals.push("writes_or_persistence");
|
|
20
20
|
if (unit.required_lenses.includes("config_deployment"))
|
|
21
21
|
signals.push("operational_surface");
|
|
22
|
+
if (unit.files.some((path) => /(write|save|persist|lock|cache|retry|open|sync|refresh)/i.test(path))) {
|
|
23
|
+
signals.push("path_level_stateful_behavior");
|
|
24
|
+
}
|
|
22
25
|
const flowHits = unit.files.reduce((sum, path) => sum + (flowMap.get(path) ?? 0), 0);
|
|
23
26
|
if (flowHits > 0) {
|
|
24
27
|
signals.push("critical_flow_member");
|
|
@@ -29,7 +32,10 @@ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerR
|
|
|
29
32
|
}
|
|
30
33
|
return {
|
|
31
34
|
unit_id: unit.unit_id,
|
|
32
|
-
risk_score: (unit.risk_score ?? 0) +
|
|
35
|
+
risk_score: (unit.risk_score ?? 0) +
|
|
36
|
+
flowHits +
|
|
37
|
+
externalHits +
|
|
38
|
+
(signals.includes("path_level_stateful_behavior") ? 1 : 0),
|
|
33
39
|
signals,
|
|
34
40
|
notes: [
|
|
35
41
|
"Initial heuristic risk scoring.",
|
package/dist/io/artifacts.d.ts
CHANGED
|
@@ -26,9 +26,7 @@ export interface ArtifactBundle {
|
|
|
26
26
|
audit_results?: AuditResult[];
|
|
27
27
|
audit_tasks?: AuditTask[];
|
|
28
28
|
requeue_tasks?: AuditTask[];
|
|
29
|
-
|
|
30
|
-
root_cause_clusters?: unknown;
|
|
31
|
-
synthesis_report?: unknown;
|
|
29
|
+
audit_report?: string;
|
|
32
30
|
audit_state?: AuditState;
|
|
33
31
|
artifact_metadata?: ArtifactMetadataManifest;
|
|
34
32
|
}
|
|
@@ -49,9 +47,7 @@ export declare const ARTIFACT_FILE_TO_BUNDLE_KEY: {
|
|
|
49
47
|
readonly "audit_results.jsonl": "audit_results";
|
|
50
48
|
readonly "audit_tasks.json": "audit_tasks";
|
|
51
49
|
readonly "requeue_tasks.json": "requeue_tasks";
|
|
52
|
-
readonly "
|
|
53
|
-
readonly "root_cause_clusters.json": "root_cause_clusters";
|
|
54
|
-
readonly "synthesis_report.json": "synthesis_report";
|
|
50
|
+
readonly "audit-report.md": "audit_report";
|
|
55
51
|
readonly "audit_state.json": "audit_state";
|
|
56
52
|
readonly "artifact_metadata.json": "artifact_metadata";
|
|
57
53
|
};
|
|
@@ -59,3 +55,7 @@ export declare function getArtifactValue(bundle: ArtifactBundle, artifactName: s
|
|
|
59
55
|
export declare function loadArtifactBundle(root: string): Promise<ArtifactBundle>;
|
|
60
56
|
export declare function writeCoreArtifacts(root: string, bundle: ArtifactBundle): Promise<void>;
|
|
61
57
|
export declare function cleanupIntermediateArtifacts(root: string): Promise<string[]>;
|
|
58
|
+
export declare function promoteFinalAuditReport(params: {
|
|
59
|
+
artifactsDir: string;
|
|
60
|
+
repoRoot: string;
|
|
61
|
+
}): Promise<void>;
|
package/dist/io/artifacts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { unlink } from "node:fs/promises";
|
|
1
|
+
import { cp, rm, unlink } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { writeJsonFile, readOptionalJsonFile, readOptionalNdjsonFile, writeNdjsonFile, } from "./json.js";
|
|
3
|
+
import { writeJsonFile, readOptionalJsonFile, readOptionalNdjsonFile, readOptionalTextFile, writeNdjsonFile, writeTextFile, } from "./json.js";
|
|
4
4
|
export const ARTIFACT_FILE_TO_BUNDLE_KEY = {
|
|
5
5
|
"repo_manifest.json": "repo_manifest",
|
|
6
6
|
"file_disposition.json": "file_disposition",
|
|
@@ -18,9 +18,7 @@ export const ARTIFACT_FILE_TO_BUNDLE_KEY = {
|
|
|
18
18
|
"audit_results.jsonl": "audit_results",
|
|
19
19
|
"audit_tasks.json": "audit_tasks",
|
|
20
20
|
"requeue_tasks.json": "requeue_tasks",
|
|
21
|
-
"
|
|
22
|
-
"root_cause_clusters.json": "root_cause_clusters",
|
|
23
|
-
"synthesis_report.json": "synthesis_report",
|
|
21
|
+
"audit-report.md": "audit_report",
|
|
24
22
|
"audit_state.json": "audit_state",
|
|
25
23
|
"artifact_metadata.json": "artifact_metadata",
|
|
26
24
|
};
|
|
@@ -51,9 +49,7 @@ export async function loadArtifactBundle(root) {
|
|
|
51
49
|
bundle.audit_results = await readOptionalNdjsonFile(`${root}/audit_results.jsonl`);
|
|
52
50
|
bundle.audit_tasks = await readOptionalJsonFile(`${root}/audit_tasks.json`);
|
|
53
51
|
bundle.requeue_tasks = await readOptionalJsonFile(`${root}/requeue_tasks.json`);
|
|
54
|
-
bundle.
|
|
55
|
-
bundle.root_cause_clusters = await readOptionalJsonFile(`${root}/root_cause_clusters.json`);
|
|
56
|
-
bundle.synthesis_report = await readOptionalJsonFile(`${root}/synthesis_report.json`);
|
|
52
|
+
bundle.audit_report = await readOptionalTextFile(`${root}/audit-report.md`);
|
|
57
53
|
bundle.audit_state = await readOptionalJsonFile(`${root}/audit_state.json`);
|
|
58
54
|
bundle.artifact_metadata = await readOptionalJsonFile(`${root}/artifact_metadata.json`);
|
|
59
55
|
return bundle;
|
|
@@ -91,20 +87,13 @@ export async function writeCoreArtifacts(root, bundle) {
|
|
|
91
87
|
await writeJsonFile(`${root}/audit_tasks.json`, bundle.audit_tasks);
|
|
92
88
|
if (bundle.requeue_tasks)
|
|
93
89
|
await writeJsonFile(`${root}/requeue_tasks.json`, bundle.requeue_tasks);
|
|
94
|
-
if (bundle.
|
|
95
|
-
await
|
|
96
|
-
if (bundle.root_cause_clusters)
|
|
97
|
-
await writeJsonFile(`${root}/root_cause_clusters.json`, bundle.root_cause_clusters);
|
|
98
|
-
if (bundle.synthesis_report)
|
|
99
|
-
await writeJsonFile(`${root}/synthesis_report.json`, bundle.synthesis_report);
|
|
90
|
+
if (bundle.audit_report !== undefined)
|
|
91
|
+
await writeTextFile(`${root}/audit-report.md`, bundle.audit_report);
|
|
100
92
|
if (bundle.audit_state)
|
|
101
93
|
await writeJsonFile(`${root}/audit_state.json`, bundle.audit_state);
|
|
102
94
|
if (bundle.artifact_metadata)
|
|
103
95
|
await writeJsonFile(`${root}/artifact_metadata.json`, bundle.artifact_metadata);
|
|
104
96
|
}
|
|
105
|
-
// Intermediate files deleted after synthesis completes. The final outputs
|
|
106
|
-
// (synthesis_report.json, merged_findings.json, root_cause_clusters.json,
|
|
107
|
-
// audit_state.json) are retained.
|
|
108
97
|
const INTERMEDIATE_ARTIFACTS = [
|
|
109
98
|
"repo_manifest.json",
|
|
110
99
|
"file_disposition.json",
|
|
@@ -123,6 +112,8 @@ const INTERMEDIATE_ARTIFACTS = [
|
|
|
123
112
|
"audit_tasks.json",
|
|
124
113
|
"requeue_tasks.json",
|
|
125
114
|
"artifact_metadata.json",
|
|
115
|
+
"audit_state.json",
|
|
116
|
+
"audit-report.md",
|
|
126
117
|
];
|
|
127
118
|
export async function cleanupIntermediateArtifacts(root) {
|
|
128
119
|
const deleted = [];
|
|
@@ -137,3 +128,9 @@ export async function cleanupIntermediateArtifacts(root) {
|
|
|
137
128
|
}
|
|
138
129
|
return deleted;
|
|
139
130
|
}
|
|
131
|
+
export async function promoteFinalAuditReport(params) {
|
|
132
|
+
const source = join(params.artifactsDir, "audit-report.md");
|
|
133
|
+
const destination = join(params.repoRoot, "audit-report.md");
|
|
134
|
+
await cp(source, destination, { force: true });
|
|
135
|
+
await rm(params.artifactsDir, { recursive: true, force: true });
|
|
136
|
+
}
|
package/dist/io/json.d.ts
CHANGED
|
@@ -6,3 +6,5 @@ export declare function readNdjsonFile<T>(path: string): Promise<T[]>;
|
|
|
6
6
|
export declare function readOptionalJsonFile<T>(path: string): Promise<T | undefined>;
|
|
7
7
|
export declare function readOptionalNdjsonFile<T>(path: string): Promise<T[] | undefined>;
|
|
8
8
|
export declare function writeNdjsonFile(path: string, values: unknown[]): Promise<void>;
|
|
9
|
+
export declare function readOptionalTextFile(path: string): Promise<string | undefined>;
|
|
10
|
+
export declare function writeTextFile(path: string, value: string): Promise<void>;
|
package/dist/io/json.js
CHANGED
|
@@ -94,3 +94,18 @@ export async function writeNdjsonFile(path, values) {
|
|
|
94
94
|
}
|
|
95
95
|
await writeFile(path, values.map((v) => JSON.stringify(v)).join("\n") + "\n", "utf8");
|
|
96
96
|
}
|
|
97
|
+
export async function readOptionalTextFile(path) {
|
|
98
|
+
try {
|
|
99
|
+
return await readFile(path, "utf8");
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (isFileMissingError(error)) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
throw new Error(`Failed to read ${path}: ${errorMessage(error)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export async function writeTextFile(path, value) {
|
|
109
|
+
await mkdir(dirname(path), { recursive: true });
|
|
110
|
+
await writeFile(path, value, "utf8");
|
|
111
|
+
}
|
|
@@ -13,3 +13,4 @@ export declare function buildRunId(obligationId: string | null, index: number):
|
|
|
13
13
|
export declare function getRunPaths(artifactsDir: string, runId: string): RunPaths;
|
|
14
14
|
export declare function ensureSupervisorDirs(artifactsDir: string): Promise<void>;
|
|
15
15
|
export declare function writeWorkerTaskFiles(task: WorkerTask, prompt: string, paths: RunPaths, artifactsDir: string, currentTasks?: AuditTask[]): Promise<void>;
|
|
16
|
+
export declare function clearDispatchFiles(artifactsDir: string): Promise<void>;
|
package/dist/io/runArtifacts.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
3
4
|
import { writeJsonFile } from "./json.js";
|
|
5
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const packageRoot = resolve(moduleDir, "..", "..");
|
|
7
|
+
const auditResultSchemaPath = join(packageRoot, "schemas", "audit_result.schema.json");
|
|
4
8
|
export function buildRunId(obligationId, index) {
|
|
5
9
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
6
10
|
const obligation = (obligationId ?? "terminal").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
@@ -20,8 +24,6 @@ export function getRunPaths(artifactsDir, runId) {
|
|
|
20
24
|
}
|
|
21
25
|
export async function ensureSupervisorDirs(artifactsDir) {
|
|
22
26
|
await mkdir(join(artifactsDir, "dispatch"), { recursive: true });
|
|
23
|
-
await mkdir(join(artifactsDir, "worker-results"), { recursive: true });
|
|
24
|
-
await mkdir(join(artifactsDir, "worker-logs"), { recursive: true });
|
|
25
27
|
await mkdir(join(artifactsDir, "runs"), { recursive: true });
|
|
26
28
|
}
|
|
27
29
|
export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir, currentTasks) {
|
|
@@ -35,4 +37,16 @@ export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir, cu
|
|
|
35
37
|
await writeJsonFile(join(artifactsDir, "dispatch", "current-task.json"), task);
|
|
36
38
|
await writeFile(join(artifactsDir, "dispatch", "current-prompt.md"), prompt, "utf8");
|
|
37
39
|
await writeJsonFile(join(artifactsDir, "dispatch", "current-tasks.json"), currentTasks ?? []);
|
|
40
|
+
await writeFile(join(artifactsDir, "dispatch", "audit-result.schema.json"), await readFile(auditResultSchemaPath, "utf8"), "utf8");
|
|
41
|
+
}
|
|
42
|
+
export async function clearDispatchFiles(artifactsDir) {
|
|
43
|
+
const targets = [
|
|
44
|
+
"current-task.json",
|
|
45
|
+
"current-prompt.md",
|
|
46
|
+
"current-tasks.json",
|
|
47
|
+
"audit-result.schema.json",
|
|
48
|
+
];
|
|
49
|
+
for (const name of targets) {
|
|
50
|
+
await rm(join(artifactsDir, "dispatch", name), { force: true });
|
|
51
|
+
}
|
|
38
52
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runAuditCodeMcpServer(argv: string[]): Promise<void>;
|