auditor-lambda 0.3.40 → 0.3.41
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 +20 -2
- package/dist/cli/args.d.ts +59 -0
- package/dist/cli/args.js +244 -0
- package/dist/cli/dispatch.d.ts +80 -0
- package/dist/cli/dispatch.js +528 -0
- package/dist/cli/prompts.d.ts +18 -0
- package/dist/cli/prompts.js +130 -0
- package/dist/cli/steps.d.ts +29 -0
- package/dist/cli/steps.js +30 -0
- package/dist/cli/waveManifest.d.ts +40 -0
- package/dist/cli/waveManifest.js +41 -0
- package/dist/cli/workerResult.d.ts +18 -0
- package/dist/cli/workerResult.js +42 -0
- package/dist/cli.d.ts +2 -22
- package/dist/cli.js +160 -973
- package/dist/extractors/browserExtension.d.ts +1 -3
- package/dist/extractors/browserExtension.js +2 -2
- package/dist/extractors/designAssessment.d.ts +1 -3
- package/dist/extractors/disposition.d.ts +2 -1
- package/dist/extractors/disposition.js +3 -0
- package/dist/extractors/flows.d.ts +1 -3
- package/dist/extractors/flows.js +2 -2
- package/dist/extractors/graph.d.ts +1 -2
- package/dist/extractors/graph.js +4 -326
- package/dist/extractors/graphManifestEdges.d.ts +1 -1
- package/dist/extractors/graphPathUtils.d.ts +1 -1
- package/dist/extractors/graphPythonImports.d.ts +3 -0
- package/dist/extractors/graphPythonImports.js +326 -0
- package/dist/extractors/risk.d.ts +1 -2
- package/dist/extractors/surfaces.d.ts +1 -3
- package/dist/extractors/surfaces.js +2 -2
- package/dist/io/artifacts.d.ts +1 -5
- package/dist/io/artifacts.js +1 -1
- package/dist/io/runArtifacts.js +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/orchestrator/advance.d.ts +1 -0
- package/dist/orchestrator/advance.js +8 -5
- package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
- package/dist/orchestrator/auditTaskUtils.js +27 -0
- package/dist/orchestrator/fileAnchors.d.ts +1 -1
- package/dist/orchestrator/fileIntegrity.d.ts +7 -0
- package/dist/orchestrator/fileIntegrity.js +41 -0
- package/dist/orchestrator/flowCoverage.d.ts +1 -1
- package/dist/orchestrator/flowPlanning.d.ts +1 -1
- package/dist/orchestrator/flowRequeue.d.ts +1 -1
- package/dist/orchestrator/internalExecutors.d.ts +3 -1
- package/dist/orchestrator/internalExecutors.js +23 -5
- package/dist/orchestrator/nextStep.d.ts +2 -1
- package/dist/orchestrator/nextStep.js +1 -1
- package/dist/orchestrator/planning.d.ts +1 -1
- package/dist/orchestrator/requeueCommand.d.ts +1 -1
- package/dist/orchestrator/reviewPackets.d.ts +1 -1
- package/dist/orchestrator/reviewPackets.js +21 -113
- package/dist/orchestrator/runtimeValidation.d.ts +1 -1
- package/dist/orchestrator/taskBuilder.d.ts +1 -1
- package/dist/orchestrator/taskBuilder.js +1 -12
- package/dist/orchestrator/unionFind.d.ts +7 -0
- package/dist/orchestrator/unionFind.js +32 -0
- package/dist/orchestrator/unitBuilder.d.ts +2 -2
- package/dist/orchestrator/unitBuilder.js +4 -18
- package/dist/prompts/renderWorkerPrompt.js +18 -1
- package/dist/providers/claudeCodeProvider.d.ts +4 -4
- package/dist/providers/claudeCodeProvider.js +9 -3
- package/dist/providers/constants.d.ts +1 -1
- package/dist/providers/constants.js +1 -1
- package/dist/providers/index.d.ts +1 -2
- package/dist/providers/index.js +5 -4
- package/dist/providers/localSubprocessProvider.d.ts +2 -2
- package/dist/providers/localSubprocessProvider.js +1 -1
- package/dist/providers/opencodeProvider.d.ts +4 -4
- package/dist/providers/opencodeProvider.js +7 -2
- package/dist/providers/spawnLoggedCommand.d.ts +3 -1
- package/dist/providers/spawnLoggedCommand.js +21 -0
- package/dist/providers/subprocessTemplateProvider.d.ts +4 -4
- package/dist/providers/subprocessTemplateProvider.js +8 -3
- package/dist/providers/vscodeTaskProvider.d.ts +3 -4
- package/dist/providers/vscodeTaskProvider.js +2 -2
- package/dist/quota/discoveredLimits.js +1 -1
- package/dist/quota/hostLimits.d.ts +1 -2
- package/dist/quota/hostLimits.js +4 -46
- package/dist/quota/index.d.ts +18 -15
- package/dist/quota/index.js +4 -9
- package/dist/quota/scheduler.d.ts +1 -3
- package/dist/quota/scheduler.js +1 -2
- package/dist/reporting/synthesis.d.ts +1 -2
- package/dist/reporting/synthesis.js +2 -0
- package/dist/reporting/workBlocks.d.ts +1 -2
- package/dist/supervisor/operatorHandoff.js +1 -1
- package/dist/supervisor/runLedger.d.ts +1 -1
- package/dist/supervisor/runLedger.js +2 -2
- package/dist/supervisor/sessionConfig.d.ts +1 -1
- package/dist/supervisor/sessionConfig.js +1 -3
- package/dist/types/reviewPlanning.d.ts +1 -1
- package/dist/types/workerSession.d.ts +6 -0
- package/dist/validation/artifacts.d.ts +1 -1
- package/dist/validation/artifacts.js +1 -1
- package/dist/validation/auditResults.d.ts +1 -1
- package/dist/validation/auditResults.js +1 -1
- package/dist/validation/sessionConfig.d.ts +2 -3
- package/dist/validation/sessionConfig.js +2 -3
- package/package.json +4 -2
- package/scripts/postinstall.mjs +0 -1
- package/dist/io/json.d.ts +0 -10
- package/dist/io/json.js +0 -142
- package/dist/providers/types.d.ts +0 -33
- package/dist/providers/types.js +0 -1
- package/dist/quota/compositeQuotaSource.d.ts +0 -7
- package/dist/quota/compositeQuotaSource.js +0 -20
- package/dist/quota/errorParsers/claudeCodeErrorParser.d.ts +0 -6
- package/dist/quota/errorParsers/claudeCodeErrorParser.js +0 -39
- package/dist/quota/errorParsers/genericErrorParser.d.ts +0 -9
- package/dist/quota/errorParsers/genericErrorParser.js +0 -7
- package/dist/quota/errorParsers/index.d.ts +0 -5
- package/dist/quota/errorParsers/index.js +0 -12
- package/dist/quota/errorParsing.d.ts +0 -7
- package/dist/quota/errorParsing.js +0 -69
- package/dist/quota/fileLock.d.ts +0 -6
- package/dist/quota/fileLock.js +0 -64
- package/dist/quota/learnedQuotaSource.d.ts +0 -7
- package/dist/quota/learnedQuotaSource.js +0 -25
- package/dist/quota/limits.d.ts +0 -16
- package/dist/quota/limits.js +0 -77
- package/dist/quota/quotaSource.d.ts +0 -12
- package/dist/quota/quotaSource.js +0 -1
- package/dist/quota/slidingWindow.d.ts +0 -4
- package/dist/quota/slidingWindow.js +0 -28
- package/dist/quota/state.d.ts +0 -15
- package/dist/quota/state.js +0 -148
- package/dist/quota/types.d.ts +0 -67
- package/dist/quota/types.js +0 -1
- package/dist/reporting/rootCause.d.ts +0 -10
- package/dist/reporting/rootCause.js +0 -146
- package/dist/types/disposition.d.ts +0 -9
- package/dist/types/disposition.js +0 -1
- package/dist/types/flows.d.ts +0 -17
- package/dist/types/flows.js +0 -1
- package/dist/types/graph.d.ts +0 -22
- package/dist/types/graph.js +0 -1
- package/dist/types/risk.d.ts +0 -9
- package/dist/types/risk.js +0 -1
- package/dist/types/runLedger.d.ts +0 -17
- package/dist/types/runLedger.js +0 -6
- package/dist/types/sessionConfig.d.ts +0 -79
- package/dist/types/sessionConfig.js +0 -15
- package/dist/types/surfaces.d.ts +0 -15
- package/dist/types/surfaces.js +0 -1
- package/dist/validation/basic.d.ts +0 -13
- package/dist/validation/basic.js +0 -46
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { ArtifactBundle } from "../io/artifacts.js";
|
|
2
|
-
import type { AuditState } from "../types/auditState.js";
|
|
2
|
+
import type { AuditObligation, AuditState } from "../types/auditState.js";
|
|
3
3
|
export interface NextStepDecision {
|
|
4
4
|
state: AuditState;
|
|
5
5
|
selected_obligation: string | null;
|
|
6
6
|
selected_executor: string | null;
|
|
7
7
|
reason: string;
|
|
8
8
|
}
|
|
9
|
+
export declare function findObligation(obligations: AuditObligation[]): AuditObligation | undefined;
|
|
9
10
|
export declare function decideNextStep(bundle: ArtifactBundle): NextStepDecision;
|
|
@@ -14,7 +14,7 @@ const PRIORITY = [
|
|
|
14
14
|
"runtime_validation_current",
|
|
15
15
|
"synthesis_current",
|
|
16
16
|
];
|
|
17
|
-
function findObligation(obligations) {
|
|
17
|
+
export function findObligation(obligations) {
|
|
18
18
|
for (const id of PRIORITY) {
|
|
19
19
|
const item = obligations.find((o) => o.id === id);
|
|
20
20
|
if (item && (item.state === "missing" || item.state === "stale")) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CoverageMatrix, RepoManifest, UnitManifest } from "../types.js";
|
|
2
|
-
import type { FileDisposition } from "
|
|
2
|
+
import type { FileDisposition } from "@audit-tools/shared";
|
|
3
3
|
import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
|
|
4
4
|
export declare function initializeCoverageFromPlan(repoManifest: RepoManifest, unitManifest: UnitManifest, disposition: FileDisposition, externalAnalyzerResults?: ExternalAnalyzerResults): CoverageMatrix;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
|
|
2
2
|
import type { CoverageMatrix } from "../types.js";
|
|
3
3
|
import type { FlowCoverageManifest } from "../types/flowCoverage.js";
|
|
4
|
-
import type { CriticalFlowManifest } from "
|
|
4
|
+
import type { CriticalFlowManifest } from "@audit-tools/shared";
|
|
5
5
|
export declare function buildRequeuePayload(matrix: CoverageMatrix, criticalFlows?: CriticalFlowManifest, flowCoverage?: FlowCoverageManifest, externalAnalyzerResults?: ExternalAnalyzerResults): {
|
|
6
6
|
task_count: number;
|
|
7
7
|
file_task_count: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AuditTask } from "../types.js";
|
|
2
2
|
import type { AuditPlanMetrics, ReviewPacket } from "../types/reviewPlanning.js";
|
|
3
|
-
import type { GraphBundle } from "
|
|
3
|
+
import type { GraphBundle } from "@audit-tools/shared";
|
|
4
4
|
export declare const ESTIMATED_TOKENS_PER_LINE = 4;
|
|
5
5
|
export declare const ESTIMATED_PACKET_PROMPT_TOKENS = 900;
|
|
6
6
|
export declare function estimateTaskGroupTokens(tasks: AuditTask[]): number;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { isRecord } from "@audit-tools/shared";
|
|
3
|
+
import { LENS_ORDER, priorityRank, sortLenses } from "./auditTaskUtils.js";
|
|
4
|
+
import { UnionFind } from "./unionFind.js";
|
|
3
5
|
const DEFAULT_MAX_TASKS_PER_PACKET = 0;
|
|
4
6
|
const DEFAULT_TARGET_PACKET_LINES = 8000;
|
|
5
7
|
export const ESTIMATED_TOKENS_PER_LINE = 4;
|
|
@@ -57,24 +59,9 @@ const BROAD_ANALYZER_OWNERSHIP_ROOTS = new Set([
|
|
|
57
59
|
"spec",
|
|
58
60
|
"specs",
|
|
59
61
|
]);
|
|
60
|
-
function priorityRank(priority) {
|
|
61
|
-
switch (priority) {
|
|
62
|
-
case "high":
|
|
63
|
-
return 3;
|
|
64
|
-
case "medium":
|
|
65
|
-
return 2;
|
|
66
|
-
case "low":
|
|
67
|
-
default:
|
|
68
|
-
return 1;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
62
|
function normalizePriority(priority) {
|
|
72
63
|
return priority ?? "low";
|
|
73
64
|
}
|
|
74
|
-
function sortLenses(lenses) {
|
|
75
|
-
const set = new Set(lenses);
|
|
76
|
-
return LENS_ORDER.filter((lens) => set.has(lens));
|
|
77
|
-
}
|
|
78
65
|
function lineCountForPath(task, path, lineIndex) {
|
|
79
66
|
return task.file_line_counts?.[path] ?? lineIndex?.[path] ?? 0;
|
|
80
67
|
}
|
|
@@ -102,9 +89,6 @@ function buildTaskGroups(tasks) {
|
|
|
102
89
|
function normalizeGraphPath(path) {
|
|
103
90
|
return path.replace(/\\/g, "/").replace(/^\.\//, "").toLowerCase();
|
|
104
91
|
}
|
|
105
|
-
function isRecord(value) {
|
|
106
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
107
|
-
}
|
|
108
92
|
function collectGraphEdges(graphBundle) {
|
|
109
93
|
if (!graphBundle?.graphs) {
|
|
110
94
|
return [];
|
|
@@ -255,33 +239,16 @@ function groupsOverlap(a, b) {
|
|
|
255
239
|
}
|
|
256
240
|
return false;
|
|
257
241
|
}
|
|
258
|
-
function
|
|
259
|
-
const
|
|
260
|
-
const parent = new Map(groupKeys.map((key) => [key, key]));
|
|
242
|
+
function unionFindFromGroups(groups, graphEdges) {
|
|
243
|
+
const uf = new UnionFind(groups.keys());
|
|
261
244
|
const fileToGroupKeys = buildFileToGroupKeys(groups);
|
|
262
245
|
const degreeIndex = buildGraphDegreeIndex(graphEdges);
|
|
263
|
-
function find(key) {
|
|
264
|
-
const current = parent.get(key) ?? key;
|
|
265
|
-
if (current === key)
|
|
266
|
-
return key;
|
|
267
|
-
const root = find(current);
|
|
268
|
-
parent.set(key, root);
|
|
269
|
-
return root;
|
|
270
|
-
}
|
|
271
|
-
function union(a, b) {
|
|
272
|
-
const rootA = find(a);
|
|
273
|
-
const rootB = find(b);
|
|
274
|
-
if (rootA === rootB)
|
|
275
|
-
return;
|
|
276
|
-
const [keep, move] = rootA.localeCompare(rootB) <= 0 ? [rootA, rootB] : [rootB, rootA];
|
|
277
|
-
parent.set(move, keep);
|
|
278
|
-
}
|
|
279
246
|
for (const keys of fileToGroupKeys.values()) {
|
|
280
247
|
const [first, ...rest] = [...keys].sort((a, b) => a.localeCompare(b));
|
|
281
248
|
if (!first)
|
|
282
249
|
continue;
|
|
283
250
|
for (const key of rest) {
|
|
284
|
-
union(first, key);
|
|
251
|
+
uf.union(first, key);
|
|
285
252
|
}
|
|
286
253
|
}
|
|
287
254
|
for (const edge of graphEdges) {
|
|
@@ -295,11 +262,15 @@ function buildGraphConnectedComponentIndex(groups, graphEdges) {
|
|
|
295
262
|
}
|
|
296
263
|
for (const fromKey of fromGroups) {
|
|
297
264
|
for (const toKey of toGroups) {
|
|
298
|
-
union(fromKey, toKey);
|
|
265
|
+
uf.union(fromKey, toKey);
|
|
299
266
|
}
|
|
300
267
|
}
|
|
301
268
|
}
|
|
302
|
-
return
|
|
269
|
+
return uf;
|
|
270
|
+
}
|
|
271
|
+
function buildGraphConnectedComponentIndex(groups, graphEdges) {
|
|
272
|
+
const uf = unionFindFromGroups(groups, graphEdges);
|
|
273
|
+
return new Map([...groups.keys()].map((key) => [key, uf.find(key)]));
|
|
303
274
|
}
|
|
304
275
|
function subsystemRootForPath(path) {
|
|
305
276
|
const segments = normalizeGraphPath(path).split("/").filter(Boolean);
|
|
@@ -435,39 +406,18 @@ function isCargoManifestPath(path) {
|
|
|
435
406
|
function isMavenPomPath(path) {
|
|
436
407
|
return normalizeGraphPath(path).split("/").at(-1) === "pom.xml";
|
|
437
408
|
}
|
|
438
|
-
function
|
|
439
|
-
const segments = normalizeGraphPath(path).split("/").filter(Boolean);
|
|
440
|
-
if (!isTypescriptProjectConfigPath(path) || segments.length < 2) {
|
|
441
|
-
return undefined;
|
|
442
|
-
}
|
|
443
|
-
return segments.slice(0, -1).join("/");
|
|
444
|
-
}
|
|
445
|
-
function goModuleRoot(path) {
|
|
446
|
-
const segments = normalizeGraphPath(path).split("/").filter(Boolean);
|
|
447
|
-
if (!isGoModuleManifestPath(path) || segments.length < 2) {
|
|
448
|
-
return undefined;
|
|
449
|
-
}
|
|
450
|
-
return segments.slice(0, -1).join("/");
|
|
451
|
-
}
|
|
452
|
-
function cargoModuleRoot(path) {
|
|
409
|
+
function configFileRoot(path, predicate) {
|
|
453
410
|
const segments = normalizeGraphPath(path).split("/").filter(Boolean);
|
|
454
|
-
if (!
|
|
455
|
-
return undefined;
|
|
456
|
-
}
|
|
457
|
-
return segments.slice(0, -1).join("/");
|
|
458
|
-
}
|
|
459
|
-
function mavenModuleRoot(path) {
|
|
460
|
-
const segments = normalizeGraphPath(path).split("/").filter(Boolean);
|
|
461
|
-
if (!isMavenPomPath(path) || segments.length < 2) {
|
|
411
|
+
if (!predicate(path) || segments.length < 2) {
|
|
462
412
|
return undefined;
|
|
463
413
|
}
|
|
464
414
|
return segments.slice(0, -1).join("/");
|
|
465
415
|
}
|
|
466
416
|
function moduleConfigRoot(path) {
|
|
467
|
-
return (
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
417
|
+
return (configFileRoot(path, isTypescriptProjectConfigPath) ??
|
|
418
|
+
configFileRoot(path, isGoModuleManifestPath) ??
|
|
419
|
+
configFileRoot(path, isCargoManifestPath) ??
|
|
420
|
+
configFileRoot(path, isMavenPomPath));
|
|
471
421
|
}
|
|
472
422
|
function analyzerOwnershipRoot(path) {
|
|
473
423
|
const root = normalizeGraphPath(path).replace(/\/+$/, "");
|
|
@@ -860,52 +810,10 @@ function chunkPacketTasks(tasks, options) {
|
|
|
860
810
|
return chunks;
|
|
861
811
|
}
|
|
862
812
|
function mergeGraphConnectedGroups(groups, graphEdges) {
|
|
863
|
-
const
|
|
864
|
-
const parent = new Map(groupKeys.map((key) => [key, key]));
|
|
865
|
-
const fileToGroupKeys = buildFileToGroupKeys(groups);
|
|
866
|
-
const degreeIndex = buildGraphDegreeIndex(graphEdges);
|
|
867
|
-
function find(key) {
|
|
868
|
-
const current = parent.get(key) ?? key;
|
|
869
|
-
if (current === key)
|
|
870
|
-
return key;
|
|
871
|
-
const root = find(current);
|
|
872
|
-
parent.set(key, root);
|
|
873
|
-
return root;
|
|
874
|
-
}
|
|
875
|
-
function union(a, b) {
|
|
876
|
-
const rootA = find(a);
|
|
877
|
-
const rootB = find(b);
|
|
878
|
-
if (rootA === rootB)
|
|
879
|
-
return;
|
|
880
|
-
const [keep, move] = rootA.localeCompare(rootB) <= 0 ? [rootA, rootB] : [rootB, rootA];
|
|
881
|
-
parent.set(move, keep);
|
|
882
|
-
}
|
|
883
|
-
for (const keys of fileToGroupKeys.values()) {
|
|
884
|
-
const [first, ...rest] = [...keys].sort((a, b) => a.localeCompare(b));
|
|
885
|
-
if (!first)
|
|
886
|
-
continue;
|
|
887
|
-
for (const key of rest) {
|
|
888
|
-
union(first, key);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
for (const edge of graphEdges) {
|
|
892
|
-
if (!isPacketExpansionEdge(edge, degreeIndex)) {
|
|
893
|
-
continue;
|
|
894
|
-
}
|
|
895
|
-
const fromGroups = fileToGroupKeys.get(normalizeGraphPath(edge.from));
|
|
896
|
-
const toGroups = fileToGroupKeys.get(normalizeGraphPath(edge.to));
|
|
897
|
-
if (!fromGroups || !toGroups) {
|
|
898
|
-
continue;
|
|
899
|
-
}
|
|
900
|
-
for (const fromKey of fromGroups) {
|
|
901
|
-
for (const toKey of toGroups) {
|
|
902
|
-
union(fromKey, toKey);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
}
|
|
813
|
+
const uf = unionFindFromGroups(groups, graphEdges);
|
|
906
814
|
const merged = new Map();
|
|
907
|
-
for (const key of
|
|
908
|
-
const root = find(key);
|
|
815
|
+
for (const key of groups.keys()) {
|
|
816
|
+
const root = uf.find(key);
|
|
909
817
|
const current = merged.get(root) ?? [];
|
|
910
818
|
current.push(...(groups.get(key) ?? []));
|
|
911
819
|
merged.set(root, current);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UnitManifest } from "../types.js";
|
|
2
2
|
import type { FlowCoverageManifest } from "../types/flowCoverage.js";
|
|
3
|
-
import type { CriticalFlowManifest } from "
|
|
3
|
+
import type { CriticalFlowManifest } from "@audit-tools/shared";
|
|
4
4
|
import type { RuntimeValidationReport, RuntimeValidationTaskManifest } from "../types/runtimeValidation.js";
|
|
5
5
|
export declare function discoverRuntimeValidationCommand(root: string): Promise<string[] | undefined>;
|
|
6
6
|
export declare function buildRuntimeValidationTasks(params: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
|
|
2
2
|
import type { AuditTask, CoverageMatrix, Lens } from "../types.js";
|
|
3
|
-
import type { CriticalFlowManifest } from "
|
|
3
|
+
import type { CriticalFlowManifest } from "@audit-tools/shared";
|
|
4
4
|
export interface UnitLineIndex {
|
|
5
5
|
[path: string]: number;
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { claimFlowReviewBlocks } from "./flowPlanning.js";
|
|
2
2
|
import { isTrivialAuditPath } from "./trivialAudit.js";
|
|
3
|
-
import { LENS_ORDER } from "./
|
|
3
|
+
import { LENS_ORDER, priorityRank } from "./auditTaskUtils.js";
|
|
4
4
|
import { isTestPath, normalizeExtractorPath, } from "../extractors/pathPatterns.js";
|
|
5
5
|
function taskPriority(hasExternalSignal, lens, isCriticalFlow = false) {
|
|
6
6
|
if (isCriticalFlow) {
|
|
@@ -17,17 +17,6 @@ function taskPriority(hasExternalSignal, lens, isCriticalFlow = false) {
|
|
|
17
17
|
}
|
|
18
18
|
return lens === "security" || lens === "data_integrity" ? "medium" : "low";
|
|
19
19
|
}
|
|
20
|
-
function priorityRank(priority) {
|
|
21
|
-
switch (priority) {
|
|
22
|
-
case "high":
|
|
23
|
-
return 3;
|
|
24
|
-
case "medium":
|
|
25
|
-
return 2;
|
|
26
|
-
case "low":
|
|
27
|
-
default:
|
|
28
|
-
return 1;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
20
|
function pickAnalyzerLens(category) {
|
|
32
21
|
const normalized = category.toLowerCase();
|
|
33
22
|
if (normalized.includes("security") ||
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export class UnionFind {
|
|
2
|
+
parent;
|
|
3
|
+
constructor(keys) {
|
|
4
|
+
this.parent = new Map([...keys].map((key) => [key, key]));
|
|
5
|
+
}
|
|
6
|
+
find(key) {
|
|
7
|
+
const current = this.parent.get(key) ?? key;
|
|
8
|
+
if (current === key)
|
|
9
|
+
return key;
|
|
10
|
+
const root = this.find(current);
|
|
11
|
+
this.parent.set(key, root);
|
|
12
|
+
return root;
|
|
13
|
+
}
|
|
14
|
+
union(a, b) {
|
|
15
|
+
const rootA = this.find(a);
|
|
16
|
+
const rootB = this.find(b);
|
|
17
|
+
if (rootA === rootB)
|
|
18
|
+
return;
|
|
19
|
+
const [keep, move] = rootA.localeCompare(rootB) <= 0 ? [rootA, rootB] : [rootB, rootA];
|
|
20
|
+
this.parent.set(move, keep);
|
|
21
|
+
}
|
|
22
|
+
groups() {
|
|
23
|
+
const result = new Map();
|
|
24
|
+
for (const key of this.parent.keys()) {
|
|
25
|
+
const root = this.find(key);
|
|
26
|
+
const group = result.get(root) ?? [];
|
|
27
|
+
group.push(key);
|
|
28
|
+
result.set(root, group);
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Lens, RepoManifest, UnitManifest } from "../types.js";
|
|
2
|
-
import type { FileDisposition } from "
|
|
3
|
-
export
|
|
2
|
+
import type { FileDisposition } from "@audit-tools/shared";
|
|
3
|
+
export { LENS_ORDER, sortLenses } from "./auditTaskUtils.js";
|
|
4
4
|
export declare function deriveRequiredLensesForPath(path: string, options?: {
|
|
5
5
|
isBrowserExtensionProject?: boolean;
|
|
6
6
|
}): Lens[];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { deriveBrowserExtensionLensesForPath, hasBrowserExtensionManifestFile, inferBrowserExtensionUnitKind, } from "../extractors/browserExtension.js";
|
|
2
2
|
import { bucketFile } from "../extractors/bucketing.js";
|
|
3
|
-
import { isAuditExcludedStatus } from "../extractors/disposition.js";
|
|
3
|
+
import { buildDispositionMap, isAuditExcludedStatus } from "../extractors/disposition.js";
|
|
4
4
|
import { pathTokens, normalizeExtractorPath } from "../extractors/pathPatterns.js";
|
|
5
|
+
import { sortLenses } from "./auditTaskUtils.js";
|
|
5
6
|
const LENS_MAP = {
|
|
6
7
|
runtime: ["correctness", "maintainability", "tests", "observability"],
|
|
7
8
|
interface: ["correctness", "security", "reliability", "tests", "observability"],
|
|
@@ -76,22 +77,7 @@ function inferUnitId(path, kind) {
|
|
|
76
77
|
}
|
|
77
78
|
return `${kind}-${path.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
78
79
|
}
|
|
79
|
-
export
|
|
80
|
-
"security",
|
|
81
|
-
"correctness",
|
|
82
|
-
"reliability",
|
|
83
|
-
"data_integrity",
|
|
84
|
-
"performance",
|
|
85
|
-
"operability",
|
|
86
|
-
"config_deployment",
|
|
87
|
-
"observability",
|
|
88
|
-
"maintainability",
|
|
89
|
-
"tests",
|
|
90
|
-
];
|
|
91
|
-
function sortLenses(lenses) {
|
|
92
|
-
const set = new Set(lenses);
|
|
93
|
-
return LENS_ORDER.filter((lens) => set.has(lens));
|
|
94
|
-
}
|
|
80
|
+
export { LENS_ORDER, sortLenses } from "./auditTaskUtils.js";
|
|
95
81
|
function applyExtensionLensGuards(path, lenses) {
|
|
96
82
|
const n = path.toLowerCase();
|
|
97
83
|
if (n.endsWith(".schema.json") || n.endsWith(".schema.ts")) {
|
|
@@ -142,7 +128,7 @@ function inferCriticalFlows(files, requiredLenses) {
|
|
|
142
128
|
export function buildUnitManifest(repoManifest, disposition) {
|
|
143
129
|
const units = new Map();
|
|
144
130
|
const isBrowserExtensionProject = hasBrowserExtensionManifestFile(repoManifest);
|
|
145
|
-
const dispositionMap =
|
|
131
|
+
const dispositionMap = buildDispositionMap(disposition);
|
|
146
132
|
for (const file of repoManifest.files) {
|
|
147
133
|
const status = dispositionMap.get(file.path);
|
|
148
134
|
if (file.excluded || (status && isAuditExcludedStatus(status))) {
|
|
@@ -2,6 +2,20 @@ import { usesDeferredWorkerCommand, } from "../types/workerSession.js";
|
|
|
2
2
|
function renderArgv(task) {
|
|
3
3
|
return JSON.stringify(task.worker_command);
|
|
4
4
|
}
|
|
5
|
+
function renderAccessSection(access) {
|
|
6
|
+
const lines = ["", "## File access"];
|
|
7
|
+
if (access.read_paths.length > 0) {
|
|
8
|
+
lines.push(`Read: ${access.read_paths.join(", ")}`);
|
|
9
|
+
}
|
|
10
|
+
if (access.write_paths.length > 0) {
|
|
11
|
+
lines.push(`Write: ${access.write_paths.join(", ")}`);
|
|
12
|
+
}
|
|
13
|
+
if (access.forbidden_patterns && access.forbidden_patterns.length > 0) {
|
|
14
|
+
lines.push(`Forbidden: ${access.forbidden_patterns.join(", ")}`);
|
|
15
|
+
}
|
|
16
|
+
lines.push("Do not read or write files outside these paths.");
|
|
17
|
+
return lines;
|
|
18
|
+
}
|
|
5
19
|
export function renderWorkerPrompt(task) {
|
|
6
20
|
const commandArgv = renderArgv(task);
|
|
7
21
|
if (task.preferred_executor === "agent" && task.audit_results_path) {
|
|
@@ -12,7 +26,7 @@ export function renderWorkerPrompt(task) {
|
|
|
12
26
|
`Read: ${tasksPath}`,
|
|
13
27
|
"Scope: review only the tasks listed in the Read file. Do not add tasks,",
|
|
14
28
|
"edit source files, remediate findings, run unrelated audits, or write result_path.",
|
|
15
|
-
"
|
|
29
|
+
"Use host Read and Grep tools for source inspection. Do not use shell search commands.",
|
|
16
30
|
"For each listed task: read the assigned file_paths under the specified lens,",
|
|
17
31
|
"using targeted reads/searches where they give complete enough evidence without loading unrelated context,",
|
|
18
32
|
"and emit exactly one AuditResult object with:",
|
|
@@ -34,6 +48,9 @@ export function renderWorkerPrompt(task) {
|
|
|
34
48
|
else {
|
|
35
49
|
lines.push("After writing audit_results_path, execute worker_command from task.json exactly.", "The worker command ingests audit_results_path and writes result_path.", `Command: ${commandArgv}`);
|
|
36
50
|
}
|
|
51
|
+
if (task.access) {
|
|
52
|
+
lines.push(...renderAccessSection(task.access));
|
|
53
|
+
}
|
|
37
54
|
return lines.join("\n");
|
|
38
55
|
}
|
|
39
56
|
return [
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { FreshSessionProvider, LaunchFreshSessionInput } from "
|
|
2
|
-
import type { ClaudeCodeConfig } from "../types/sessionConfig.js";
|
|
1
|
+
import type { FreshSessionProvider, LaunchFreshSessionInput, ClaudeCodeConfig, OpenTokenConfig } from "@audit-tools/shared";
|
|
3
2
|
import { spawnLoggedCommand } from "./spawnLoggedCommand.js";
|
|
4
3
|
export declare const ACTIVE_CLAUDE_CODE_SESSION_MESSAGE: string;
|
|
5
4
|
export declare class ClaudeCodeProvider implements FreshSessionProvider {
|
|
6
5
|
name: string;
|
|
7
6
|
private readonly config;
|
|
7
|
+
private readonly opentoken;
|
|
8
8
|
private readonly launchCommand;
|
|
9
|
-
constructor(config?: ClaudeCodeConfig, launchCommand?: typeof spawnLoggedCommand);
|
|
10
|
-
launch(input: LaunchFreshSessionInput): Promise<import("
|
|
9
|
+
constructor(config?: ClaudeCodeConfig, launchCommand?: typeof spawnLoggedCommand, opentoken?: OpenTokenConfig);
|
|
10
|
+
launch(input: LaunchFreshSessionInput): Promise<import("@audit-tools/shared").LaunchFreshSessionResult>;
|
|
11
11
|
}
|
|
@@ -6,10 +6,12 @@ export const ACTIVE_CLAUDE_CODE_SESSION_MESSAGE = "claude-code provider cannot b
|
|
|
6
6
|
export class ClaudeCodeProvider {
|
|
7
7
|
name = "claude-code";
|
|
8
8
|
config;
|
|
9
|
+
opentoken;
|
|
9
10
|
launchCommand;
|
|
10
|
-
constructor(config = {}, launchCommand = spawnLoggedCommand) {
|
|
11
|
+
constructor(config = {}, launchCommand = spawnLoggedCommand, opentoken = {}) {
|
|
11
12
|
this.config = config;
|
|
12
13
|
this.launchCommand = launchCommand;
|
|
14
|
+
this.opentoken = opentoken;
|
|
13
15
|
}
|
|
14
16
|
async launch(input) {
|
|
15
17
|
if (process.env.CLAUDECODE) {
|
|
@@ -17,14 +19,18 @@ export class ClaudeCodeProvider {
|
|
|
17
19
|
}
|
|
18
20
|
const prompt = await readFile(input.promptPath, "utf8");
|
|
19
21
|
const command = this.config.command ?? "claude";
|
|
22
|
+
const promptFlag = this.config.prompt_flag ?? "-p";
|
|
20
23
|
const args = [
|
|
21
|
-
|
|
24
|
+
promptFlag,
|
|
22
25
|
prompt,
|
|
23
26
|
...(this.config.extra_args ?? []),
|
|
24
27
|
...(this.config.dangerously_skip_permissions
|
|
25
28
|
? ["--dangerously-skip-permissions"]
|
|
26
29
|
: []),
|
|
27
30
|
];
|
|
28
|
-
return await this.launchCommand(command, args, input
|
|
31
|
+
return await this.launchCommand(command, args, input, undefined, {
|
|
32
|
+
opentoken: this.opentoken.enabled,
|
|
33
|
+
opentokenCommand: this.opentoken.command,
|
|
34
|
+
});
|
|
29
35
|
}
|
|
30
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { LOCAL_SUBPROCESS_PROVIDER_NAME } from "@audit-tools/shared";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { LOCAL_SUBPROCESS_PROVIDER_NAME } from "@audit-tools/shared";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { FreshSessionProvider } from "
|
|
2
|
-
import type { ResolvedProviderName, SessionConfig } from "../types/sessionConfig.js";
|
|
1
|
+
import type { FreshSessionProvider, ResolvedProviderName, SessionConfig } from "@audit-tools/shared";
|
|
3
2
|
export declare function resolveFreshSessionProviderName(name: string | undefined, sessionConfig?: SessionConfig, options?: {
|
|
4
3
|
env?: NodeJS.ProcessEnv;
|
|
5
4
|
commandExists?: (command: string) => boolean;
|
package/dist/providers/index.js
CHANGED
|
@@ -64,6 +64,7 @@ export function resolveFreshSessionProviderName(name, sessionConfig = {}, option
|
|
|
64
64
|
}
|
|
65
65
|
export function createFreshSessionProvider(name, sessionConfig = {}) {
|
|
66
66
|
const providerName = resolveFreshSessionProviderName(name, sessionConfig);
|
|
67
|
+
const opentoken = sessionConfig.opentoken ?? {};
|
|
67
68
|
if (providerName === "local-subprocess" &&
|
|
68
69
|
(name ?? sessionConfig.provider) === "auto") {
|
|
69
70
|
process.stderr.write("audit-code: auto provider resolved to local-subprocess — no capable agent provider detected. " +
|
|
@@ -77,16 +78,16 @@ export function createFreshSessionProvider(name, sessionConfig = {}) {
|
|
|
77
78
|
if (!sessionConfig.subprocess_template?.command_template?.length) {
|
|
78
79
|
throw new Error("subprocess-template provider requires session-config.json with subprocess_template.command_template.");
|
|
79
80
|
}
|
|
80
|
-
return new SubprocessTemplateProvider(sessionConfig.subprocess_template);
|
|
81
|
+
return new SubprocessTemplateProvider(sessionConfig.subprocess_template, undefined, opentoken);
|
|
81
82
|
case "claude-code":
|
|
82
|
-
return new ClaudeCodeProvider(sessionConfig.claude_code);
|
|
83
|
+
return new ClaudeCodeProvider(sessionConfig.claude_code, undefined, opentoken);
|
|
83
84
|
case "opencode":
|
|
84
|
-
return new OpenCodeProvider(sessionConfig.opencode);
|
|
85
|
+
return new OpenCodeProvider(sessionConfig.opencode, opentoken);
|
|
85
86
|
case "vscode-task":
|
|
86
87
|
if (!sessionConfig.vscode_task?.command_template?.length) {
|
|
87
88
|
throw new Error("vscode-task provider requires session-config.json with vscode_task.command_template.");
|
|
88
89
|
}
|
|
89
|
-
return new VSCodeTaskProvider(sessionConfig.vscode_task);
|
|
90
|
+
return new VSCodeTaskProvider(sessionConfig.vscode_task, opentoken);
|
|
90
91
|
default:
|
|
91
92
|
throw new Error(`Unknown provider: ${providerName}`);
|
|
92
93
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { FreshSessionProvider, LaunchFreshSessionInput } from "
|
|
1
|
+
import type { FreshSessionProvider, LaunchFreshSessionInput } from "@audit-tools/shared";
|
|
2
2
|
import { spawnLoggedCommand } from "./spawnLoggedCommand.js";
|
|
3
3
|
export declare const MISSING_WORKER_COMMAND_MESSAGE = "local-subprocess provider requires task.worker_command.";
|
|
4
4
|
export declare class LocalSubprocessProvider implements FreshSessionProvider {
|
|
5
5
|
name: string;
|
|
6
6
|
private readonly launchCommand;
|
|
7
7
|
constructor(launchCommand?: typeof spawnLoggedCommand);
|
|
8
|
-
launch(input: LaunchFreshSessionInput): Promise<import("
|
|
8
|
+
launch(input: LaunchFreshSessionInput): Promise<import("@audit-tools/shared").LaunchFreshSessionResult>;
|
|
9
9
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readJsonFile } from "
|
|
1
|
+
import { readJsonFile } from "@audit-tools/shared";
|
|
2
2
|
import { spawnLoggedCommand } from "./spawnLoggedCommand.js";
|
|
3
3
|
export const MISSING_WORKER_COMMAND_MESSAGE = "local-subprocess provider requires task.worker_command.";
|
|
4
4
|
export class LocalSubprocessProvider {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { FreshSessionProvider, LaunchFreshSessionInput } from "
|
|
2
|
-
import type { OpenCodeConfig } from "../types/sessionConfig.js";
|
|
1
|
+
import type { FreshSessionProvider, LaunchFreshSessionInput, OpenCodeConfig, OpenTokenConfig } from "@audit-tools/shared";
|
|
3
2
|
export declare class OpenCodeProvider implements FreshSessionProvider {
|
|
4
3
|
name: string;
|
|
5
4
|
private readonly config;
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
private readonly opentoken;
|
|
6
|
+
constructor(config?: OpenCodeConfig, opentoken?: OpenTokenConfig);
|
|
7
|
+
launch(input: LaunchFreshSessionInput): Promise<import("@audit-tools/shared").LaunchFreshSessionResult>;
|
|
8
8
|
}
|
|
@@ -22,14 +22,19 @@ function quoteCmdArg(value) {
|
|
|
22
22
|
export class OpenCodeProvider {
|
|
23
23
|
name = "opencode";
|
|
24
24
|
config;
|
|
25
|
-
|
|
25
|
+
opentoken;
|
|
26
|
+
constructor(config = {}, opentoken = {}) {
|
|
26
27
|
this.config = config;
|
|
28
|
+
this.opentoken = opentoken;
|
|
27
29
|
}
|
|
28
30
|
async launch(input) {
|
|
29
31
|
const prompt = await readFile(input.promptPath, "utf8");
|
|
30
32
|
const baseCommand = this.config.command ?? "opencode";
|
|
31
33
|
const baseArgs = ["run", prompt, ...(this.config.extra_args ?? [])];
|
|
32
34
|
const resolved = resolveOpenCodeSpawnCommand(baseCommand, baseArgs);
|
|
33
|
-
return await spawnLoggedCommand(resolved.command, resolved.args, input
|
|
35
|
+
return await spawnLoggedCommand(resolved.command, resolved.args, input, undefined, {
|
|
36
|
+
opentoken: this.opentoken.enabled,
|
|
37
|
+
opentokenCommand: this.opentoken.command,
|
|
38
|
+
});
|
|
34
39
|
}
|
|
35
40
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { createWriteStream } from "node:fs";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
-
import type { LaunchFreshSessionInput, LaunchFreshSessionResult } from "
|
|
3
|
+
import type { LaunchFreshSessionInput, LaunchFreshSessionResult } from "@audit-tools/shared";
|
|
4
4
|
interface SpawnLoggedCommandOptions {
|
|
5
5
|
createWriteStream?: typeof createWriteStream;
|
|
6
6
|
spawn?: typeof spawn;
|
|
7
7
|
killGraceMs?: number;
|
|
8
|
+
opentoken?: boolean;
|
|
9
|
+
opentokenCommand?: string;
|
|
8
10
|
}
|
|
9
11
|
export declare function spawnLoggedCommand(command: string, args: string[], input: LaunchFreshSessionInput, env?: Record<string, string>, options?: SpawnLoggedCommandOptions): Promise<LaunchFreshSessionResult>;
|
|
10
12
|
export {};
|
|
@@ -6,6 +6,22 @@ const FORCE_KILL_GRACE_MS = 1_000;
|
|
|
6
6
|
function formatCommand(command, args) {
|
|
7
7
|
return [command, ...args].join(" ");
|
|
8
8
|
}
|
|
9
|
+
function quoteCmdArg(value) {
|
|
10
|
+
if (/^[A-Za-z0-9_./:=@+-]+$/.test(value))
|
|
11
|
+
return value;
|
|
12
|
+
return `"${value.replace(/(["^&|<>%])/g, "^$1")}"`;
|
|
13
|
+
}
|
|
14
|
+
function applyOpenTokenWrap(command, args, opentokenCommand, platform = process.platform) {
|
|
15
|
+
if (platform === "win32") {
|
|
16
|
+
const shell = process.env.ComSpec ?? "cmd.exe";
|
|
17
|
+
const inner = [command, ...args].map(quoteCmdArg).join(" ");
|
|
18
|
+
return {
|
|
19
|
+
command: shell,
|
|
20
|
+
args: ["/d", "/s", "/c", `${opentokenCommand} wrap ${inner}`],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return { command: opentokenCommand, args: ["wrap", command, ...args] };
|
|
24
|
+
}
|
|
9
25
|
// On Windows `command` must be the resolved .cmd / .exe path because `spawn`
|
|
10
26
|
// does not consult PATH for executables without a shell. Callers should use
|
|
11
27
|
// `platformCommand()` (scripts/smoke-packaged-audit-code.mjs) or similar to
|
|
@@ -14,6 +30,11 @@ export async function spawnLoggedCommand(command, args, input, env, options = {}
|
|
|
14
30
|
const openWriteStream = options.createWriteStream ?? createWriteStream;
|
|
15
31
|
const spawnProcess = options.spawn ?? spawn;
|
|
16
32
|
const killGraceMs = options.killGraceMs ?? FORCE_KILL_GRACE_MS;
|
|
33
|
+
if (options.opentoken) {
|
|
34
|
+
const wrapped = applyOpenTokenWrap(command, args, options.opentokenCommand ?? "opentoken");
|
|
35
|
+
command = wrapped.command;
|
|
36
|
+
args = wrapped.args;
|
|
37
|
+
}
|
|
17
38
|
return await new Promise((resolve, reject) => {
|
|
18
39
|
const stdoutLog = openWriteStream(input.stdoutPath, { flags: "a" });
|
|
19
40
|
const stderrLog = openWriteStream(input.stderrPath, { flags: "a" });
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { FreshSessionProvider, LaunchFreshSessionInput } from "
|
|
2
|
-
import type { SubprocessTemplateConfig } from "../types/sessionConfig.js";
|
|
1
|
+
import type { FreshSessionProvider, LaunchFreshSessionInput, SubprocessTemplateConfig, OpenTokenConfig } from "@audit-tools/shared";
|
|
3
2
|
export declare class SubprocessTemplateProvider implements FreshSessionProvider {
|
|
4
3
|
name: string;
|
|
5
4
|
private readonly config;
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
private readonly opentoken;
|
|
6
|
+
constructor(config: SubprocessTemplateConfig, name?: string, opentoken?: OpenTokenConfig);
|
|
7
|
+
launch(input: LaunchFreshSessionInput): Promise<import("@audit-tools/shared").LaunchFreshSessionResult>;
|
|
8
8
|
}
|