auditor-lambda 0.2.6 → 0.2.9
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 +29 -7
- package/audit-code-wrapper-lib.mjs +1605 -330
- package/dist/adapters/eslint.js +9 -5
- package/dist/cli.d.ts +42 -1
- package/dist/cli.js +192 -80
- package/dist/coverage.d.ts +2 -2
- package/dist/coverage.js +5 -5
- 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 +15 -2
- package/dist/extractors/fileInventory.js +24 -28
- package/dist/extractors/flows.d.ts +5 -0
- package/dist/extractors/flows.js +25 -39
- package/dist/extractors/pathPatterns.d.ts +13 -3
- package/dist/extractors/pathPatterns.js +116 -53
- package/dist/extractors/risk.js +7 -1
- 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 +59 -44
- package/dist/io/artifacts.js +80 -120
- package/dist/io/json.d.ts +2 -0
- package/dist/io/json.js +65 -19
- package/dist/io/runArtifacts.d.ts +2 -1
- package/dist/io/runArtifacts.js +44 -7
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +579 -0
- package/dist/orchestrator/advance.js +84 -56
- package/dist/orchestrator/dependencyMap.js +9 -13
- package/dist/orchestrator/executors.js +7 -2
- 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 +29 -9
- package/dist/orchestrator/internalExecutors.d.ts +2 -1
- package/dist/orchestrator/internalExecutors.js +130 -69
- package/dist/orchestrator/planning.js +25 -3
- package/dist/orchestrator/requeue.js +20 -5
- 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/taskBuilder.d.ts +4 -2
- package/dist/orchestrator/taskBuilder.js +153 -52
- package/dist/orchestrator/trivialAudit.js +8 -5
- 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 +19 -10
- 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/mergeFindings.js +0 -11
- package/dist/reporting/synthesis.d.ts +26 -21
- package/dist/reporting/synthesis.js +97 -61
- package/dist/reporting/workBlocks.d.ts +12 -3
- package/dist/reporting/workBlocks.js +124 -70
- package/dist/supervisor/operatorHandoff.js +48 -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 +6 -0
- 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 +13 -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/types.d.ts +4 -7
- 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 +71 -114
- 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 +67 -38
- package/docs/artifacts.md +16 -56
- package/docs/bootstrap-install.md +60 -30
- package/docs/contract.md +22 -205
- package/docs/next-steps.md +76 -44
- package/docs/packaging.md +27 -3
- package/docs/product-direction.md +22 -0
- package/docs/production-launch-bar.md +4 -2
- package/docs/production-readiness.md +9 -5
- package/docs/releasing.md +98 -0
- package/docs/remediation-baseline.md +75 -0
- package/docs/run-flow.md +23 -11
- package/docs/session-config.md +50 -5
- package/docs/supervisor.md +7 -0
- package/docs/workflow-refactor-brief.md +177 -0
- package/package.json +4 -1
- package/schemas/audit_result.schema.json +8 -7
- 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 +3 -3
- 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 +16 -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
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { decideNextStep } from "./nextStep.js";
|
|
2
2
|
import { deriveAuditState } from "./state.js";
|
|
3
3
|
import { computeArtifactMetadata } from "./artifactMetadata.js";
|
|
4
|
-
import { runIntakeExecutor, runStructureExecutor, runPlanningExecutor, runResultIngestionExecutor, runRuntimeValidationUpdateExecutor, runSynthesisExecutor, runExternalAnalyzerImportExecutor, } from "./internalExecutors.js";
|
|
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,58 +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
|
-
|
|
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);
|
|
82
110
|
}
|
|
83
111
|
const metadata = computeArtifactMetadata(run.updated, bundle.artifact_metadata);
|
|
84
112
|
const metadataBundle = { ...run.updated, artifact_metadata: metadata };
|
|
@@ -12,7 +12,7 @@ export const ARTIFACT_DEPENDENCY_MAP = {
|
|
|
12
12
|
"requeue_tasks.json",
|
|
13
13
|
"runtime_validation_tasks.json",
|
|
14
14
|
"runtime_validation_report.json",
|
|
15
|
-
"
|
|
15
|
+
"audit-report.md",
|
|
16
16
|
],
|
|
17
17
|
"file_disposition.json": [
|
|
18
18
|
"unit_manifest.json",
|
|
@@ -26,7 +26,7 @@ export const ARTIFACT_DEPENDENCY_MAP = {
|
|
|
26
26
|
"requeue_tasks.json",
|
|
27
27
|
"runtime_validation_tasks.json",
|
|
28
28
|
"runtime_validation_report.json",
|
|
29
|
-
"
|
|
29
|
+
"audit-report.md",
|
|
30
30
|
],
|
|
31
31
|
"unit_manifest.json": [
|
|
32
32
|
"risk_register.json",
|
|
@@ -34,13 +34,13 @@ export const ARTIFACT_DEPENDENCY_MAP = {
|
|
|
34
34
|
"audit_tasks.json",
|
|
35
35
|
"runtime_validation_tasks.json",
|
|
36
36
|
"requeue_tasks.json",
|
|
37
|
-
"
|
|
37
|
+
"audit-report.md",
|
|
38
38
|
],
|
|
39
39
|
"surface_manifest.json": [
|
|
40
40
|
"critical_flows.json",
|
|
41
41
|
"risk_register.json",
|
|
42
42
|
"runtime_validation_tasks.json",
|
|
43
|
-
"
|
|
43
|
+
"audit-report.md",
|
|
44
44
|
],
|
|
45
45
|
"critical_flows.json": [
|
|
46
46
|
"flow_coverage.json",
|
|
@@ -49,7 +49,7 @@ export const ARTIFACT_DEPENDENCY_MAP = {
|
|
|
49
49
|
"requeue_tasks.json",
|
|
50
50
|
"runtime_validation_tasks.json",
|
|
51
51
|
"runtime_validation_report.json",
|
|
52
|
-
"
|
|
52
|
+
"audit-report.md",
|
|
53
53
|
],
|
|
54
54
|
"audit_results.jsonl": [
|
|
55
55
|
"coverage_matrix.json",
|
|
@@ -57,26 +57,22 @@ export const ARTIFACT_DEPENDENCY_MAP = {
|
|
|
57
57
|
"requeue_tasks.json",
|
|
58
58
|
"runtime_validation_tasks.json",
|
|
59
59
|
"runtime_validation_report.json",
|
|
60
|
-
"
|
|
61
|
-
"root_cause_clusters.json",
|
|
62
|
-
"synthesis_report.json",
|
|
60
|
+
"audit-report.md",
|
|
63
61
|
],
|
|
64
62
|
"coverage_matrix.json": [
|
|
65
63
|
"flow_coverage.json",
|
|
66
64
|
"requeue_tasks.json",
|
|
67
65
|
"runtime_validation_tasks.json",
|
|
68
66
|
"runtime_validation_report.json",
|
|
69
|
-
"
|
|
67
|
+
"audit-report.md",
|
|
70
68
|
],
|
|
71
69
|
"flow_coverage.json": [
|
|
72
70
|
"requeue_tasks.json",
|
|
73
71
|
"runtime_validation_tasks.json",
|
|
74
72
|
"runtime_validation_report.json",
|
|
75
|
-
"
|
|
73
|
+
"audit-report.md",
|
|
76
74
|
],
|
|
77
75
|
"runtime_validation_report.json": [
|
|
78
|
-
"
|
|
79
|
-
"root_cause_clusters.json",
|
|
80
|
-
"synthesis_report.json",
|
|
76
|
+
"audit-report.md",
|
|
81
77
|
],
|
|
82
78
|
};
|
|
@@ -20,14 +20,19 @@ export const EXECUTOR_REGISTRY = [
|
|
|
20
20
|
description: "Ingest available audit result artifacts and refresh dependent coverage artifacts.",
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
id: "
|
|
23
|
+
id: "runtime_validation_executor",
|
|
24
24
|
obligation_ids: ["runtime_validation_current"],
|
|
25
25
|
description: "Merge runtime validation evidence updates when provided.",
|
|
26
26
|
},
|
|
27
|
+
{
|
|
28
|
+
id: "runtime_validation_update_executor",
|
|
29
|
+
obligation_ids: [],
|
|
30
|
+
description: "Merge imported runtime validation evidence updates.",
|
|
31
|
+
},
|
|
27
32
|
{
|
|
28
33
|
id: "synthesis_executor",
|
|
29
34
|
obligation_ids: ["synthesis_current"],
|
|
30
|
-
description: "
|
|
35
|
+
description: "Render the final deterministic Markdown audit report.",
|
|
31
36
|
},
|
|
32
37
|
{
|
|
33
38
|
id: "external_analyzer_import_executor",
|
|
@@ -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[];
|
|
@@ -3,33 +3,58 @@ const DEFAULT_FLOW_LENS_PRIORITY = [
|
|
|
3
3
|
"reliability",
|
|
4
4
|
"correctness",
|
|
5
5
|
];
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
6
|
+
function lensPathKey(lens, path) {
|
|
7
|
+
return `${lens}:${path}`;
|
|
8
|
+
}
|
|
9
|
+
function flowLensPriority(lens) {
|
|
10
|
+
const index = DEFAULT_FLOW_LENS_PRIORITY.indexOf(lens);
|
|
11
|
+
return index >= 0 ? index : DEFAULT_FLOW_LENS_PRIORITY.length;
|
|
12
|
+
}
|
|
13
|
+
export function claimFlowReviewBlocks(criticalFlows, pendingByLens, assigned) {
|
|
14
|
+
const candidates = [];
|
|
12
15
|
for (const flow of criticalFlows.flows) {
|
|
13
|
-
const
|
|
16
|
+
const flowPaths = [...new Set(flow.paths)].sort((a, b) => a.localeCompare(b));
|
|
17
|
+
const desiredLenses = flow.concerns
|
|
18
|
+
.filter((concern) => DEFAULT_FLOW_LENS_PRIORITY.includes(concern))
|
|
19
|
+
.sort((a, b) => flowLensPriority(a) - flowLensPriority(b));
|
|
14
20
|
for (const lens of desiredLenses) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
const pendingPaths = pendingByLens.get(lens);
|
|
22
|
+
if (!pendingPaths || pendingPaths.size === 0) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const filePaths = flowPaths.filter((path) => pendingPaths.has(path));
|
|
26
|
+
if (filePaths.length === 0) {
|
|
20
27
|
continue;
|
|
21
28
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
unit_id: `flow:${flow.id}`,
|
|
25
|
-
pass_id: `flow-pass:${lens}`,
|
|
29
|
+
candidates.push({
|
|
30
|
+
flow_id: flow.id,
|
|
26
31
|
lens,
|
|
27
|
-
file_paths:
|
|
28
|
-
rationale: `Flow-aware audit for critical flow "${flow.id}" (${flow.paths.length} file${flow.paths.length === 1 ? "" : "s"}) under the ${lens} lens.`,
|
|
32
|
+
file_paths: filePaths,
|
|
29
33
|
});
|
|
30
|
-
seenTaskIds.add(taskId);
|
|
31
|
-
existingSignatures.add(signature);
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
|
-
|
|
36
|
+
candidates.sort((a, b) => {
|
|
37
|
+
const sizeDelta = b.file_paths.length - a.file_paths.length;
|
|
38
|
+
if (sizeDelta !== 0)
|
|
39
|
+
return sizeDelta;
|
|
40
|
+
const lensDelta = flowLensPriority(a.lens) - flowLensPriority(b.lens);
|
|
41
|
+
if (lensDelta !== 0)
|
|
42
|
+
return lensDelta;
|
|
43
|
+
return a.flow_id.localeCompare(b.flow_id);
|
|
44
|
+
});
|
|
45
|
+
const blocks = [];
|
|
46
|
+
for (const candidate of candidates) {
|
|
47
|
+
const unclaimedPaths = candidate.file_paths.filter((path) => !assigned.has(lensPathKey(candidate.lens, path)));
|
|
48
|
+
if (unclaimedPaths.length === 0) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
for (const path of unclaimedPaths) {
|
|
52
|
+
assigned.add(lensPathKey(candidate.lens, path));
|
|
53
|
+
}
|
|
54
|
+
blocks.push({
|
|
55
|
+
...candidate,
|
|
56
|
+
file_paths: unclaimedPaths,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return blocks;
|
|
35
60
|
}
|
|
@@ -10,7 +10,17 @@ function isLens(value) {
|
|
|
10
10
|
"tests",
|
|
11
11
|
"operability",
|
|
12
12
|
"config_deployment",
|
|
13
|
-
].includes(value);
|
|
13
|
+
].includes(String(value));
|
|
14
|
+
}
|
|
15
|
+
function getExternalSignalPaths(externalAnalyzerResults) {
|
|
16
|
+
const results = Array.isArray(externalAnalyzerResults?.results)
|
|
17
|
+
? externalAnalyzerResults.results
|
|
18
|
+
: [];
|
|
19
|
+
return new Set(results
|
|
20
|
+
.map((item) => item && typeof item.path === "string" && item.path.length > 0
|
|
21
|
+
? item.path
|
|
22
|
+
: null)
|
|
23
|
+
.filter((path) => path !== null));
|
|
14
24
|
}
|
|
15
25
|
function taskPriority(hasExternalSignal, lens) {
|
|
16
26
|
if (hasExternalSignal &&
|
|
@@ -19,8 +29,8 @@ function taskPriority(hasExternalSignal, lens) {
|
|
|
19
29
|
}
|
|
20
30
|
return hasExternalSignal ? "medium" : "low";
|
|
21
31
|
}
|
|
22
|
-
function fileStillNeedsLens(
|
|
23
|
-
const record =
|
|
32
|
+
function fileStillNeedsLens(coverageByPath, path, lens) {
|
|
33
|
+
const record = coverageByPath.get(path);
|
|
24
34
|
if (!record || record.audit_status === "excluded") {
|
|
25
35
|
return false;
|
|
26
36
|
}
|
|
@@ -28,21 +38,31 @@ function fileStillNeedsLens(coverageMatrix, path, lens) {
|
|
|
28
38
|
}
|
|
29
39
|
export function buildFlowRequeueTasks(criticalFlows, flowCoverage, coverageMatrix, externalAnalyzerResults) {
|
|
30
40
|
const flowMap = new Map(criticalFlows.flows.map((flow) => [flow.id, flow]));
|
|
41
|
+
const coverageByPath = new Map(coverageMatrix.files.map((file) => [file.path, file]));
|
|
31
42
|
const tasks = [];
|
|
32
43
|
const seen = new Set();
|
|
33
|
-
const externalPaths =
|
|
44
|
+
const externalPaths = getExternalSignalPaths(externalAnalyzerResults);
|
|
34
45
|
for (const record of flowCoverage.flows) {
|
|
35
46
|
const flow = flowMap.get(record.flow_id);
|
|
36
47
|
if (!flow) {
|
|
37
48
|
continue;
|
|
38
49
|
}
|
|
39
|
-
const
|
|
50
|
+
const requiredLenses = Array.isArray(record.required_lenses)
|
|
51
|
+
? record.required_lenses.filter((lens) => typeof lens === "string")
|
|
52
|
+
: [];
|
|
53
|
+
const completedLenses = new Set(Array.isArray(record.completed_lenses)
|
|
54
|
+
? record.completed_lenses.filter((lens) => typeof lens === "string")
|
|
55
|
+
: []);
|
|
56
|
+
const missingLenses = requiredLenses.filter((lens) => !completedLenses.has(lens));
|
|
57
|
+
const flowPaths = Array.isArray(flow.paths)
|
|
58
|
+
? flow.paths.filter((path) => typeof path === "string")
|
|
59
|
+
: [];
|
|
40
60
|
for (const lensName of missingLenses) {
|
|
41
61
|
if (!isLens(lensName)) {
|
|
42
|
-
|
|
62
|
+
throw new Error(`buildFlowRequeueTasks encountered unsupported lens "${String(lensName)}" for flow ${record.flow_id}.`);
|
|
43
63
|
}
|
|
44
|
-
for (const path of
|
|
45
|
-
if (!fileStillNeedsLens(
|
|
64
|
+
for (const path of flowPaths) {
|
|
65
|
+
if (!fileStillNeedsLens(coverageByPath, path, lensName)) {
|
|
46
66
|
continue;
|
|
47
67
|
}
|
|
48
68
|
const signature = `${flow.id}|${lensName}|${path}`;
|
|
@@ -57,7 +77,7 @@ export function buildFlowRequeueTasks(criticalFlows, flowCoverage, coverageMatri
|
|
|
57
77
|
pass_id: `flow-requeue:${lensName}`,
|
|
58
78
|
lens: lensName,
|
|
59
79
|
file_paths: [path],
|
|
60
|
-
rationale: `
|
|
80
|
+
rationale: `Mandatory audit coverage is still missing for critical flow ${flow.id} at ${path} under the ${lensName} lens.`,
|
|
61
81
|
priority: taskPriority(hasExternalSignal, lensName),
|
|
62
82
|
tags: hasExternalSignal
|
|
63
83
|
? ["critical_flow_followup", "external_analyzer_signal"]
|
|
@@ -9,8 +9,9 @@ export interface ExecutorRunResult {
|
|
|
9
9
|
}
|
|
10
10
|
export declare function runIntakeExecutor(bundle: ArtifactBundle, root: string): Promise<ExecutorRunResult>;
|
|
11
11
|
export declare function runStructureExecutor(bundle: ArtifactBundle): ExecutorRunResult;
|
|
12
|
-
export declare function runPlanningExecutor(bundle: ArtifactBundle, lineIndex?: Record<string, number>): ExecutorRunResult
|
|
12
|
+
export declare function runPlanningExecutor(bundle: ArtifactBundle, root: string, lineIndex?: Record<string, number>): Promise<ExecutorRunResult>;
|
|
13
13
|
export declare function runResultIngestionExecutor(bundle: ArtifactBundle, results: AuditResult[]): ExecutorRunResult;
|
|
14
|
+
export declare function runRuntimeValidationExecutor(bundle: ArtifactBundle, root: string): Promise<ExecutorRunResult>;
|
|
14
15
|
export declare function runRuntimeValidationUpdateExecutor(bundle: ArtifactBundle, updates: RuntimeValidationReport): ExecutorRunResult;
|
|
15
16
|
export declare function runSynthesisExecutor(bundle: ArtifactBundle, results?: AuditResult[]): ExecutorRunResult;
|
|
16
17
|
export declare function runExternalAnalyzerImportExecutor(bundle: ArtifactBundle, externalResults: ExternalAnalyzerResults): ExecutorRunResult;
|