auditor-lambda 0.2.8 → 0.2.10
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 +6 -0
- package/audit-code-wrapper-lib.mjs +1 -1
- package/dist/adapters/eslint.js +9 -5
- package/dist/cli.d.ts +42 -1
- package/dist/cli.js +234 -63
- package/dist/extractors/bucketing.d.ts +4 -0
- package/dist/extractors/bucketing.js +6 -2
- package/dist/extractors/disposition.d.ts +4 -0
- package/dist/extractors/disposition.js +6 -2
- package/dist/extractors/fileInventory.js +24 -28
- package/dist/extractors/flows.d.ts +5 -0
- package/dist/extractors/flows.js +18 -38
- package/dist/extractors/pathPatterns.d.ts +10 -3
- package/dist/extractors/pathPatterns.js +109 -61
- package/dist/extractors/surfaces.d.ts +4 -0
- package/dist/extractors/surfaces.js +11 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/io/artifacts.d.ts +55 -40
- package/dist/io/artifacts.js +73 -110
- package/dist/io/json.js +52 -21
- package/dist/io/runArtifacts.d.ts +1 -1
- package/dist/io/runArtifacts.js +26 -3
- package/dist/orchestrator/advance.js +83 -62
- package/dist/orchestrator/autoFixExecutor.js +32 -15
- package/dist/orchestrator/flowCoverage.js +11 -5
- package/dist/orchestrator/flowPlanning.d.ts +7 -2
- package/dist/orchestrator/flowPlanning.js +46 -21
- package/dist/orchestrator/flowRequeue.js +28 -8
- package/dist/orchestrator/internalExecutors.js +12 -8
- package/dist/orchestrator/localCommands.d.ts +14 -0
- package/dist/orchestrator/localCommands.js +124 -0
- package/dist/orchestrator/planning.js +25 -3
- package/dist/orchestrator/requeue.js +11 -1
- package/dist/orchestrator/syntaxResolutionExecutor.js +60 -59
- package/dist/orchestrator/taskBuilder.d.ts +4 -2
- package/dist/orchestrator/taskBuilder.js +153 -52
- package/dist/orchestrator/unitBuilder.d.ts +3 -1
- package/dist/orchestrator/unitBuilder.js +24 -16
- package/dist/prompts/renderWorkerPrompt.d.ts +1 -1
- package/dist/prompts/renderWorkerPrompt.js +16 -8
- package/dist/providers/claudeCodeProvider.d.ts +4 -1
- package/dist/providers/claudeCodeProvider.js +8 -5
- package/dist/providers/localSubprocessProvider.d.ts +4 -0
- package/dist/providers/localSubprocessProvider.js +7 -2
- package/dist/providers/spawnLoggedCommand.d.ts +9 -1
- package/dist/providers/spawnLoggedCommand.js +77 -29
- package/dist/reporting/synthesis.d.ts +2 -0
- package/dist/reporting/synthesis.js +12 -9
- package/dist/supervisor/operatorHandoff.d.ts +1 -1
- package/dist/supervisor/operatorHandoff.js +56 -18
- package/dist/supervisor/runLedger.d.ts +1 -1
- package/dist/supervisor/runLedger.js +112 -5
- package/dist/supervisor/sessionConfig.js +10 -10
- package/dist/types/externalAnalyzer.d.ts +3 -0
- package/dist/types/flowCoverage.d.ts +5 -1
- package/dist/types/flowCoverage.js +5 -1
- package/dist/types/flows.d.ts +5 -1
- package/dist/types/flows.js +1 -1
- package/dist/types/runLedger.d.ts +5 -1
- package/dist/types/runLedger.js +6 -1
- package/dist/types/runtimeValidation.d.ts +12 -3
- package/dist/types/runtimeValidation.js +16 -1
- package/dist/types/sessionConfig.d.ts +15 -2
- package/dist/types/sessionConfig.js +15 -1
- package/dist/types/surfaces.d.ts +4 -1
- package/dist/types/surfaces.js +1 -1
- package/dist/types/workerSession.d.ts +9 -0
- package/dist/types/workerSession.js +5 -1
- package/dist/validation/artifacts.d.ts +1 -1
- package/dist/validation/artifacts.js +33 -20
- package/dist/validation/auditResults.d.ts +2 -2
- package/dist/validation/auditResults.js +7 -15
- package/dist/validation/basic.d.ts +9 -1
- package/dist/validation/basic.js +40 -3
- package/dist/validation/sessionConfig.d.ts +4 -2
- package/dist/validation/sessionConfig.js +62 -15
- package/docs/agent-integrations.md +31 -11
- package/docs/next-steps.md +21 -4
- package/docs/packaging.md +14 -0
- package/docs/product-direction.md +22 -0
- package/docs/production-launch-bar.md +2 -0
- package/docs/releasing.md +17 -0
- package/docs/remediation-baseline.md +75 -0
- package/docs/run-flow.md +23 -11
- package/docs/session-config.md +53 -6
- package/docs/supervisor.md +7 -0
- package/docs/workflow-refactor-brief.md +177 -0
- package/package.json +1 -1
- package/schemas/audit-code-v1alpha1.schema.json +1 -0
- package/schemas/audit_result.schema.json +4 -1
- package/schemas/audit_task.schema.json +3 -1
- package/schemas/coverage_matrix.schema.json +3 -3
- package/schemas/critical_flows.schema.json +6 -2
- package/schemas/file_disposition.schema.json +2 -2
- package/schemas/finding.schema.json +9 -4
- package/schemas/flow_coverage.schema.json +2 -2
- package/schemas/repo_manifest.schema.json +4 -4
- package/schemas/risk_register.schema.json +2 -2
- package/schemas/runtime_validation_report.schema.json +2 -2
- package/schemas/runtime_validation_tasks.schema.json +8 -2
- package/schemas/surface_manifest.schema.json +6 -3
- package/schemas/unit_manifest.schema.json +3 -2
- package/skills/audit-code/SKILL.md +5 -0
package/dist/io/artifacts.js
CHANGED
|
@@ -1,129 +1,92 @@
|
|
|
1
1
|
import { cp, rm, unlink } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
3
|
+
import { isFileMissingError, readOptionalJsonFile, readOptionalNdjsonFile, readOptionalTextFile, writeJsonFile, writeNdjsonFile, writeTextFile, } from "./json.js";
|
|
4
|
+
function jsonArtifact(fileName, phase) {
|
|
5
|
+
return {
|
|
6
|
+
fileName,
|
|
7
|
+
phase,
|
|
8
|
+
read: (path) => readOptionalJsonFile(path),
|
|
9
|
+
write: (path, value) => writeJsonFile(path, value),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function ndjsonArtifact(fileName, phase) {
|
|
13
|
+
return {
|
|
14
|
+
fileName,
|
|
15
|
+
phase,
|
|
16
|
+
read: (path) => readOptionalNdjsonFile(path),
|
|
17
|
+
write: (path, value) => writeNdjsonFile(path, value),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function textArtifact(fileName, phase) {
|
|
21
|
+
return {
|
|
22
|
+
fileName,
|
|
23
|
+
phase,
|
|
24
|
+
read: (path) => readOptionalTextFile(path),
|
|
25
|
+
write: (path, value) => writeTextFile(path, value),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export const ARTIFACT_DEFINITIONS = {
|
|
29
|
+
repo_manifest: jsonArtifact("repo_manifest.json", "intake"),
|
|
30
|
+
file_disposition: jsonArtifact("file_disposition.json", "intake"),
|
|
31
|
+
auto_fixes_applied: jsonArtifact("auto_fixes_applied.json", "intake"),
|
|
32
|
+
unit_manifest: jsonArtifact("unit_manifest.json", "analysis"),
|
|
33
|
+
graph_bundle: jsonArtifact("graph_bundle.json", "analysis"),
|
|
34
|
+
surface_manifest: jsonArtifact("surface_manifest.json", "analysis"),
|
|
35
|
+
critical_flows: jsonArtifact("critical_flows.json", "analysis"),
|
|
36
|
+
flow_coverage: jsonArtifact("flow_coverage.json", "analysis"),
|
|
37
|
+
risk_register: jsonArtifact("risk_register.json", "analysis"),
|
|
38
|
+
coverage_matrix: jsonArtifact("coverage_matrix.json", "execution"),
|
|
39
|
+
runtime_validation_tasks: jsonArtifact("runtime_validation_tasks.json", "execution"),
|
|
40
|
+
runtime_validation_report: jsonArtifact("runtime_validation_report.json", "execution"),
|
|
41
|
+
external_analyzer_results: jsonArtifact("external_analyzer_results.json", "execution"),
|
|
42
|
+
audit_results: ndjsonArtifact("audit_results.jsonl", "execution"),
|
|
43
|
+
audit_tasks: jsonArtifact("audit_tasks.json", "execution"),
|
|
44
|
+
requeue_tasks: jsonArtifact("requeue_tasks.json", "execution"),
|
|
45
|
+
audit_report: textArtifact("audit-report.md", "reporting"),
|
|
46
|
+
audit_state: jsonArtifact("audit_state.json", "supervisor"),
|
|
47
|
+
artifact_metadata: jsonArtifact("artifact_metadata.json", "supervisor"),
|
|
24
48
|
};
|
|
25
|
-
const
|
|
49
|
+
const ARTIFACT_ENTRIES = Object.entries(ARTIFACT_DEFINITIONS);
|
|
50
|
+
export const ARTIFACT_FILE_TO_BUNDLE_KEY = Object.fromEntries(ARTIFACT_ENTRIES.map(([key, definition]) => [definition.fileName, key]));
|
|
26
51
|
export function getArtifactValue(bundle, artifactName) {
|
|
27
|
-
const
|
|
28
|
-
const key = map[artifactName];
|
|
52
|
+
const key = ARTIFACT_FILE_TO_BUNDLE_KEY[artifactName];
|
|
29
53
|
return key ? bundle[key] : undefined;
|
|
30
54
|
}
|
|
31
55
|
export async function loadArtifactBundle(root) {
|
|
32
56
|
const bundle = {};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
bundle.risk_register = await readOptionalJsonFile(`${root}/risk_register.json`);
|
|
42
|
-
bundle.coverage_matrix = await readOptionalJsonFile(`${root}/coverage_matrix.json`);
|
|
43
|
-
bundle.runtime_validation_tasks =
|
|
44
|
-
await readOptionalJsonFile(`${root}/runtime_validation_tasks.json`);
|
|
45
|
-
bundle.runtime_validation_report =
|
|
46
|
-
await readOptionalJsonFile(`${root}/runtime_validation_report.json`);
|
|
47
|
-
bundle.external_analyzer_results =
|
|
48
|
-
await readOptionalJsonFile(`${root}/external_analyzer_results.json`);
|
|
49
|
-
bundle.audit_results = await readOptionalNdjsonFile(`${root}/audit_results.jsonl`);
|
|
50
|
-
bundle.audit_tasks = await readOptionalJsonFile(`${root}/audit_tasks.json`);
|
|
51
|
-
bundle.requeue_tasks = await readOptionalJsonFile(`${root}/requeue_tasks.json`);
|
|
52
|
-
bundle.audit_report = await readOptionalTextFile(`${root}/audit-report.md`);
|
|
53
|
-
bundle.audit_state = await readOptionalJsonFile(`${root}/audit_state.json`);
|
|
54
|
-
bundle.artifact_metadata = await readOptionalJsonFile(`${root}/artifact_metadata.json`);
|
|
57
|
+
const bundleRecord = bundle;
|
|
58
|
+
for (const entry of ARTIFACT_ENTRIES) {
|
|
59
|
+
const [key, definition] = entry;
|
|
60
|
+
const value = await definition.read(join(root, definition.fileName));
|
|
61
|
+
if (value !== undefined) {
|
|
62
|
+
bundleRecord[key] = value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
55
65
|
return bundle;
|
|
56
66
|
}
|
|
57
67
|
export async function writeCoreArtifacts(root, bundle) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (bundle.graph_bundle)
|
|
67
|
-
await writeJsonFile(`${root}/graph_bundle.json`, bundle.graph_bundle);
|
|
68
|
-
if (bundle.surface_manifest)
|
|
69
|
-
await writeJsonFile(`${root}/surface_manifest.json`, bundle.surface_manifest);
|
|
70
|
-
if (bundle.critical_flows)
|
|
71
|
-
await writeJsonFile(`${root}/critical_flows.json`, bundle.critical_flows);
|
|
72
|
-
if (bundle.flow_coverage)
|
|
73
|
-
await writeJsonFile(`${root}/flow_coverage.json`, bundle.flow_coverage);
|
|
74
|
-
if (bundle.risk_register)
|
|
75
|
-
await writeJsonFile(`${root}/risk_register.json`, bundle.risk_register);
|
|
76
|
-
if (bundle.coverage_matrix)
|
|
77
|
-
await writeJsonFile(`${root}/coverage_matrix.json`, bundle.coverage_matrix);
|
|
78
|
-
if (bundle.runtime_validation_tasks)
|
|
79
|
-
await writeJsonFile(`${root}/runtime_validation_tasks.json`, bundle.runtime_validation_tasks);
|
|
80
|
-
if (bundle.runtime_validation_report)
|
|
81
|
-
await writeJsonFile(`${root}/runtime_validation_report.json`, bundle.runtime_validation_report);
|
|
82
|
-
if (bundle.external_analyzer_results)
|
|
83
|
-
await writeJsonFile(`${root}/external_analyzer_results.json`, bundle.external_analyzer_results);
|
|
84
|
-
if (bundle.audit_results)
|
|
85
|
-
await writeNdjsonFile(`${root}/audit_results.jsonl`, bundle.audit_results);
|
|
86
|
-
if (bundle.audit_tasks)
|
|
87
|
-
await writeJsonFile(`${root}/audit_tasks.json`, bundle.audit_tasks);
|
|
88
|
-
if (bundle.requeue_tasks)
|
|
89
|
-
await writeJsonFile(`${root}/requeue_tasks.json`, bundle.requeue_tasks);
|
|
90
|
-
if (bundle.audit_report !== undefined)
|
|
91
|
-
await writeTextFile(`${root}/audit-report.md`, bundle.audit_report);
|
|
92
|
-
if (bundle.audit_state)
|
|
93
|
-
await writeJsonFile(`${root}/audit_state.json`, bundle.audit_state);
|
|
94
|
-
if (bundle.artifact_metadata)
|
|
95
|
-
await writeJsonFile(`${root}/artifact_metadata.json`, bundle.artifact_metadata);
|
|
68
|
+
const bundleRecord = bundle;
|
|
69
|
+
for (const entry of ARTIFACT_ENTRIES) {
|
|
70
|
+
const [key, definition] = entry;
|
|
71
|
+
const value = bundleRecord[key];
|
|
72
|
+
if (value !== undefined) {
|
|
73
|
+
await definition.write(join(root, definition.fileName), value);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
96
76
|
}
|
|
97
|
-
const INTERMEDIATE_ARTIFACTS = [
|
|
98
|
-
"repo_manifest.json",
|
|
99
|
-
"file_disposition.json",
|
|
100
|
-
"auto_fixes_applied.json",
|
|
101
|
-
"unit_manifest.json",
|
|
102
|
-
"graph_bundle.json",
|
|
103
|
-
"surface_manifest.json",
|
|
104
|
-
"critical_flows.json",
|
|
105
|
-
"flow_coverage.json",
|
|
106
|
-
"risk_register.json",
|
|
107
|
-
"coverage_matrix.json",
|
|
108
|
-
"runtime_validation_tasks.json",
|
|
109
|
-
"runtime_validation_report.json",
|
|
110
|
-
"external_analyzer_results.json",
|
|
111
|
-
"audit_results.jsonl",
|
|
112
|
-
"audit_tasks.json",
|
|
113
|
-
"requeue_tasks.json",
|
|
114
|
-
"artifact_metadata.json",
|
|
115
|
-
"audit_state.json",
|
|
116
|
-
"audit-report.md",
|
|
117
|
-
];
|
|
118
77
|
export async function cleanupIntermediateArtifacts(root) {
|
|
119
78
|
const deleted = [];
|
|
120
|
-
for (const
|
|
79
|
+
for (const [, definition] of ARTIFACT_ENTRIES) {
|
|
80
|
+
const path = join(root, definition.fileName);
|
|
121
81
|
try {
|
|
122
|
-
await unlink(
|
|
123
|
-
deleted.push(
|
|
82
|
+
await unlink(path);
|
|
83
|
+
deleted.push(definition.fileName);
|
|
124
84
|
}
|
|
125
|
-
catch {
|
|
126
|
-
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (isFileMissingError(error)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
throw error;
|
|
127
90
|
}
|
|
128
91
|
}
|
|
129
92
|
return deleted;
|
package/dist/io/json.js
CHANGED
|
@@ -3,6 +3,17 @@ import { dirname } from "node:path";
|
|
|
3
3
|
function errorMessage(error) {
|
|
4
4
|
return error instanceof Error ? error.message : String(error);
|
|
5
5
|
}
|
|
6
|
+
function ioError(action, path, error) {
|
|
7
|
+
return new Error(`Failed to ${action} ${path}: ${errorMessage(error)}`);
|
|
8
|
+
}
|
|
9
|
+
async function ensureParentDirectory(path) {
|
|
10
|
+
try {
|
|
11
|
+
await mkdir(dirname(path), { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw ioError("prepare parent directory", path, error);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
6
17
|
export function isFileMissingError(error) {
|
|
7
18
|
return (typeof error === "object" &&
|
|
8
19
|
error !== null &&
|
|
@@ -28,31 +39,41 @@ export async function readJsonFile(path) {
|
|
|
28
39
|
}
|
|
29
40
|
}
|
|
30
41
|
export async function writeJsonFile(path, value) {
|
|
31
|
-
await
|
|
32
|
-
|
|
42
|
+
await ensureParentDirectory(path);
|
|
43
|
+
try {
|
|
44
|
+
await writeFile(path, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw ioError("write", path, error);
|
|
48
|
+
}
|
|
33
49
|
}
|
|
34
50
|
export async function appendNdjsonFile(path, value) {
|
|
35
|
-
await
|
|
36
|
-
|
|
51
|
+
await ensureParentDirectory(path);
|
|
52
|
+
try {
|
|
53
|
+
await appendFile(path, JSON.stringify(value) + "\n", "utf8");
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw ioError("append", path, error);
|
|
57
|
+
}
|
|
37
58
|
}
|
|
38
59
|
export async function readNdjsonFile(path) {
|
|
39
60
|
try {
|
|
40
61
|
const content = await readFile(path, "utf8");
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
.map((line, index) => {
|
|
62
|
+
const values = [];
|
|
63
|
+
let sawContent = false;
|
|
64
|
+
for (const [index, line] of content.split(/\r?\n/).entries()) {
|
|
65
|
+
if (line.trim().length === 0) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
sawContent = true;
|
|
49
69
|
try {
|
|
50
|
-
|
|
70
|
+
values.push(JSON.parse(line));
|
|
51
71
|
}
|
|
52
72
|
catch (error) {
|
|
53
73
|
throw new Error(`Invalid NDJSON in ${path} at line ${index + 1}: ${errorMessage(error)}`);
|
|
54
74
|
}
|
|
55
|
-
}
|
|
75
|
+
}
|
|
76
|
+
return sawContent ? values : [];
|
|
56
77
|
}
|
|
57
78
|
catch (error) {
|
|
58
79
|
if (isFileMissingError(error)) {
|
|
@@ -87,12 +108,17 @@ export async function readOptionalNdjsonFile(path) {
|
|
|
87
108
|
}
|
|
88
109
|
}
|
|
89
110
|
export async function writeNdjsonFile(path, values) {
|
|
90
|
-
await
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
111
|
+
await ensureParentDirectory(path);
|
|
112
|
+
try {
|
|
113
|
+
if (values.length === 0) {
|
|
114
|
+
await writeFile(path, "", "utf8");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await writeFile(path, values.map((v) => JSON.stringify(v)).join("\n") + "\n", "utf8");
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
throw ioError("write", path, error);
|
|
94
121
|
}
|
|
95
|
-
await writeFile(path, values.map((v) => JSON.stringify(v)).join("\n") + "\n", "utf8");
|
|
96
122
|
}
|
|
97
123
|
export async function readOptionalTextFile(path) {
|
|
98
124
|
try {
|
|
@@ -106,6 +132,11 @@ export async function readOptionalTextFile(path) {
|
|
|
106
132
|
}
|
|
107
133
|
}
|
|
108
134
|
export async function writeTextFile(path, value) {
|
|
109
|
-
await
|
|
110
|
-
|
|
135
|
+
await ensureParentDirectory(path);
|
|
136
|
+
try {
|
|
137
|
+
await writeFile(path, value, "utf8");
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
throw ioError("write", path, error);
|
|
141
|
+
}
|
|
111
142
|
}
|
|
@@ -9,7 +9,7 @@ export interface RunPaths {
|
|
|
9
9
|
stderrPath: string;
|
|
10
10
|
statusPath: string;
|
|
11
11
|
}
|
|
12
|
-
export declare function buildRunId(obligationId: string | null, index: number): string;
|
|
12
|
+
export declare function buildRunId(obligationId: string | null, index: number, now?: Date): string;
|
|
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>;
|
package/dist/io/runArtifacts.js
CHANGED
|
@@ -5,9 +5,32 @@ import { writeJsonFile } from "./json.js";
|
|
|
5
5
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
6
6
|
const packageRoot = resolve(moduleDir, "..", "..");
|
|
7
7
|
const auditResultSchemaPath = join(packageRoot, "schemas", "audit_result.schema.json");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
function pad(value, size = 2) {
|
|
9
|
+
return String(value).padStart(size, "0");
|
|
10
|
+
}
|
|
11
|
+
function formatRunTimestamp(value) {
|
|
12
|
+
return [
|
|
13
|
+
pad(value.getUTCFullYear(), 4),
|
|
14
|
+
pad(value.getUTCMonth() + 1),
|
|
15
|
+
pad(value.getUTCDate()),
|
|
16
|
+
"T",
|
|
17
|
+
pad(value.getUTCHours()),
|
|
18
|
+
pad(value.getUTCMinutes()),
|
|
19
|
+
pad(value.getUTCSeconds()),
|
|
20
|
+
pad(value.getUTCMilliseconds(), 3),
|
|
21
|
+
"Z",
|
|
22
|
+
].join("");
|
|
23
|
+
}
|
|
24
|
+
function normalizeRunIdSegment(value) {
|
|
25
|
+
const normalized = (value ?? "terminal")
|
|
26
|
+
.trim()
|
|
27
|
+
.replace(/[^a-zA-Z0-9_-]+/g, "-")
|
|
28
|
+
.replace(/^-+|-+$/g, "");
|
|
29
|
+
return normalized.length > 0 ? normalized : "terminal";
|
|
30
|
+
}
|
|
31
|
+
export function buildRunId(obligationId, index, now = new Date()) {
|
|
32
|
+
const timestamp = formatRunTimestamp(now);
|
|
33
|
+
const obligation = normalizeRunIdSegment(obligationId);
|
|
11
34
|
return `${timestamp}_${obligation}_${String(index).padStart(3, "0")}`;
|
|
12
35
|
}
|
|
13
36
|
export function getRunPaths(artifactsDir, runId) {
|
|
@@ -4,6 +4,19 @@ import { computeArtifactMetadata } from "./artifactMetadata.js";
|
|
|
4
4
|
import { runIntakeExecutor, runStructureExecutor, runPlanningExecutor, runResultIngestionExecutor, runRuntimeValidationExecutor, runRuntimeValidationUpdateExecutor, runSynthesisExecutor, runExternalAnalyzerImportExecutor, } from "./internalExecutors.js";
|
|
5
5
|
import { runAutoFixExecutor } from "./autoFixExecutor.js";
|
|
6
6
|
import { runSyntaxResolutionExecutor } from "./syntaxResolutionExecutor.js";
|
|
7
|
+
function cloneState(state) {
|
|
8
|
+
return {
|
|
9
|
+
...state,
|
|
10
|
+
blockers: [...(state.blockers ?? [])],
|
|
11
|
+
obligations: state.obligations.map((obligation) => ({ ...obligation })),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function formatExecutorFailure(selectedExecutor, selectedObligation, error) {
|
|
15
|
+
const detail = error instanceof Error ? error.message : String(error ?? "unknown error");
|
|
16
|
+
return new Error(`advanceAudit ${selectedExecutor} failed while resolving ${selectedObligation ?? "the current obligation"}: ${detail}`, {
|
|
17
|
+
cause: error instanceof Error ? error : undefined,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
7
20
|
export async function advanceAudit(bundle, options = {}) {
|
|
8
21
|
const decision = decideNextStep(bundle);
|
|
9
22
|
const forcedExecutor = options.preferredExecutor ?? null;
|
|
@@ -12,9 +25,12 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
12
25
|
? `forced:${forcedExecutor}`
|
|
13
26
|
: decision.selected_obligation;
|
|
14
27
|
if (!selectedExecutor) {
|
|
15
|
-
const state =
|
|
16
|
-
|
|
17
|
-
state.last_obligation =
|
|
28
|
+
const state = cloneState(decision.state);
|
|
29
|
+
state.last_executor = bundle.audit_state?.last_executor ?? state.last_executor;
|
|
30
|
+
state.last_obligation =
|
|
31
|
+
selectedObligation ??
|
|
32
|
+
bundle.audit_state?.last_obligation ??
|
|
33
|
+
state.last_obligation;
|
|
18
34
|
return {
|
|
19
35
|
audit_state: state,
|
|
20
36
|
selected_obligation: selectedObligation,
|
|
@@ -27,65 +43,70 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
27
43
|
};
|
|
28
44
|
}
|
|
29
45
|
let run;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
46
|
+
try {
|
|
47
|
+
switch (selectedExecutor) {
|
|
48
|
+
case "intake_executor":
|
|
49
|
+
if (!options.root)
|
|
50
|
+
throw new Error("advanceAudit intake_executor requires root");
|
|
51
|
+
run = await runIntakeExecutor(bundle, options.root);
|
|
52
|
+
break;
|
|
53
|
+
case "structure_executor":
|
|
54
|
+
run = runStructureExecutor(bundle);
|
|
55
|
+
break;
|
|
56
|
+
case "planning_executor":
|
|
57
|
+
if (!options.root)
|
|
58
|
+
throw new Error("advanceAudit planning_executor requires root");
|
|
59
|
+
run = await runPlanningExecutor(bundle, options.root, options.lineIndex ?? {});
|
|
60
|
+
break;
|
|
61
|
+
case "result_ingestion_executor":
|
|
62
|
+
run = runResultIngestionExecutor(bundle, options.auditResults ?? bundle.audit_results ?? []);
|
|
63
|
+
break;
|
|
64
|
+
case "runtime_validation_executor":
|
|
65
|
+
if (!options.root)
|
|
66
|
+
throw new Error("advanceAudit runtime_validation_executor requires root");
|
|
67
|
+
run = await runRuntimeValidationExecutor(bundle, options.root);
|
|
68
|
+
break;
|
|
69
|
+
case "synthesis_executor":
|
|
70
|
+
run = runSynthesisExecutor(bundle, options.auditResults);
|
|
71
|
+
break;
|
|
72
|
+
case "runtime_validation_update_executor":
|
|
73
|
+
if (!options.runtimeValidationUpdates)
|
|
74
|
+
throw new Error("advanceAudit runtime_validation_update_executor requires runtimeValidationUpdates");
|
|
75
|
+
run = runRuntimeValidationUpdateExecutor(bundle, options.runtimeValidationUpdates);
|
|
76
|
+
break;
|
|
77
|
+
case "external_analyzer_import_executor":
|
|
78
|
+
if (!options.externalAnalyzerResults)
|
|
79
|
+
throw new Error("advanceAudit external_analyzer_import_executor requires externalAnalyzerResults");
|
|
80
|
+
run = runExternalAnalyzerImportExecutor(bundle, options.externalAnalyzerResults);
|
|
81
|
+
break;
|
|
82
|
+
case "auto_fix_executor":
|
|
83
|
+
if (!options.root)
|
|
84
|
+
throw new Error("advanceAudit auto_fix_executor requires root");
|
|
85
|
+
run = runAutoFixExecutor(bundle, options.root);
|
|
86
|
+
break;
|
|
87
|
+
case "syntax_resolution_executor":
|
|
88
|
+
if (!options.root)
|
|
89
|
+
throw new Error("advanceAudit syntax_resolution_executor requires root");
|
|
90
|
+
run = runSyntaxResolutionExecutor(bundle, options.root);
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
const state = deriveAuditState(bundle);
|
|
94
|
+
state.last_executor = selectedExecutor;
|
|
95
|
+
state.last_obligation = selectedObligation ?? undefined;
|
|
96
|
+
return {
|
|
97
|
+
audit_state: state,
|
|
98
|
+
selected_obligation: selectedObligation,
|
|
99
|
+
selected_executor: selectedExecutor,
|
|
100
|
+
progress_made: false,
|
|
101
|
+
artifacts_written: ["audit_state.json"],
|
|
102
|
+
progress_summary: `Executor ${selectedExecutor} is selected but not yet dispatched through advance-audit.`,
|
|
103
|
+
next_likely_step: selectedObligation,
|
|
104
|
+
updated_bundle: { ...bundle, audit_state: state },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw formatExecutorFailure(selectedExecutor, selectedObligation, error);
|
|
89
110
|
}
|
|
90
111
|
const metadata = computeArtifactMetadata(run.updated, bundle.artifact_metadata);
|
|
91
112
|
const metadataBundle = { ...run.updated, artifact_metadata: metadata };
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { join } from "node:path";
|
|
2
2
|
import { isAuditExcludedStatus } from "../extractors/disposition.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
catch (e) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
3
|
+
import { resolveNodeTool, runFirstAvailableCommand, } from "./localCommands.js";
|
|
4
|
+
function tryRunConfiguredFormatter(root, candidates) {
|
|
5
|
+
const result = runFirstAvailableCommand(root, candidates);
|
|
6
|
+
return result !== null && !result.error && result.exitCode === 0;
|
|
11
7
|
}
|
|
12
8
|
export function runAutoFixExecutor(bundle, root) {
|
|
13
9
|
if (!bundle.file_disposition) {
|
|
@@ -28,24 +24,45 @@ export function runAutoFixExecutor(bundle, root) {
|
|
|
28
24
|
extensions.has("js") ||
|
|
29
25
|
extensions.has("tsx") ||
|
|
30
26
|
extensions.has("jsx")) {
|
|
31
|
-
if (tryRunConfiguredFormatter(root,
|
|
27
|
+
if (tryRunConfiguredFormatter(root, [
|
|
28
|
+
...resolveNodeTool(root, join("node_modules", "prettier", "bin", "prettier.cjs"), ["--write", "."], "prettier --write ."),
|
|
29
|
+
{ command: "prettier", args: ["--write", "."], display: "prettier --write ." },
|
|
30
|
+
]))
|
|
32
31
|
executedTools.push("prettier");
|
|
33
|
-
if (tryRunConfiguredFormatter(root,
|
|
32
|
+
if (tryRunConfiguredFormatter(root, [
|
|
33
|
+
...resolveNodeTool(root, join("node_modules", "eslint", "bin", "eslint.js"), ["--fix", "."], "eslint --fix ."),
|
|
34
|
+
{ command: "eslint", args: ["--fix", "."], display: "eslint --fix ." },
|
|
35
|
+
]))
|
|
34
36
|
executedTools.push("eslint");
|
|
35
37
|
}
|
|
36
38
|
// Python
|
|
37
39
|
if (extensions.has("py")) {
|
|
38
|
-
if (tryRunConfiguredFormatter(root,
|
|
39
|
-
|
|
40
|
+
if (tryRunConfiguredFormatter(root, [
|
|
41
|
+
{ command: "black", args: ["."], display: "black ." },
|
|
42
|
+
{ command: "python", args: ["-m", "black", "."], display: "python -m black ." },
|
|
43
|
+
])) {
|
|
40
44
|
executedTools.push("black");
|
|
41
45
|
}
|
|
42
|
-
if (tryRunConfiguredFormatter(root,
|
|
46
|
+
if (tryRunConfiguredFormatter(root, [
|
|
47
|
+
{
|
|
48
|
+
command: "autopep8",
|
|
49
|
+
args: ["--in-place", "--recursive", "."],
|
|
50
|
+
display: "autopep8 --in-place --recursive .",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
command: "python",
|
|
54
|
+
args: ["-m", "autopep8", "--in-place", "--recursive", "."],
|
|
55
|
+
display: "python -m autopep8 --in-place --recursive .",
|
|
56
|
+
},
|
|
57
|
+
])) {
|
|
43
58
|
executedTools.push("autopep8");
|
|
44
59
|
}
|
|
45
60
|
}
|
|
46
61
|
// Go
|
|
47
62
|
if (extensions.has("go")) {
|
|
48
|
-
if (tryRunConfiguredFormatter(root,
|
|
63
|
+
if (tryRunConfiguredFormatter(root, [
|
|
64
|
+
{ command: "gofmt", args: ["-w", "."], display: "gofmt -w ." },
|
|
65
|
+
]))
|
|
49
66
|
executedTools.push("gofmt");
|
|
50
67
|
}
|
|
51
68
|
const resultsArtifact = {
|
|
@@ -10,11 +10,17 @@ function lensSetForFlow(concerns) {
|
|
|
10
10
|
return concerns.filter((concern) => allowed.includes(concern));
|
|
11
11
|
}
|
|
12
12
|
export function buildFlowCoverage(criticalFlows, coverageMatrix) {
|
|
13
|
+
const coverageByPath = new Map(coverageMatrix.files.map((file) => [file.path, file]));
|
|
13
14
|
const flows = criticalFlows.flows.map((flow) => {
|
|
14
|
-
const
|
|
15
|
+
const flowPaths = Array.isArray(flow.paths)
|
|
16
|
+
? flow.paths.filter((path) => typeof path === "string")
|
|
17
|
+
: [];
|
|
18
|
+
const required = lensSetForFlow(Array.isArray(flow.concerns)
|
|
19
|
+
? flow.concerns.filter((concern) => typeof concern === "string")
|
|
20
|
+
: []);
|
|
15
21
|
const completed = new Set();
|
|
16
|
-
for (const path of
|
|
17
|
-
const record =
|
|
22
|
+
for (const path of flowPaths) {
|
|
23
|
+
const record = coverageByPath.get(path);
|
|
18
24
|
if (!record || record.audit_status === "excluded") {
|
|
19
25
|
continue;
|
|
20
26
|
}
|
|
@@ -33,11 +39,11 @@ export function buildFlowCoverage(criticalFlows, coverageMatrix) {
|
|
|
33
39
|
: "pending";
|
|
34
40
|
return {
|
|
35
41
|
flow_id: flow.id,
|
|
36
|
-
paths:
|
|
42
|
+
paths: flowPaths,
|
|
37
43
|
required_lenses: required,
|
|
38
44
|
completed_lenses,
|
|
39
45
|
status,
|
|
40
|
-
notes: [`Derived from ${
|
|
46
|
+
notes: [`Derived from ${flowPaths.length} path(s).`],
|
|
41
47
|
};
|
|
42
48
|
});
|
|
43
49
|
return { flows };
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Lens } from "../types.js";
|
|
2
2
|
import type { CriticalFlowManifest } from "../types/flows.js";
|
|
3
|
-
export
|
|
3
|
+
export interface FlowReviewBlock {
|
|
4
|
+
flow_id: string;
|
|
5
|
+
lens: Lens;
|
|
6
|
+
file_paths: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function claimFlowReviewBlocks(criticalFlows: CriticalFlowManifest, pendingByLens: Map<Lens, Set<string>>, assigned: Set<string>): FlowReviewBlock[];
|