auditor-lambda 0.10.2 → 0.10.7
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-build.mjs +198 -0
- package/audit-code-wrapper-install-hosts.mjs +1140 -0
- package/audit-code-wrapper-io.mjs +155 -0
- package/audit-code-wrapper-legacy.mjs +125 -0
- package/audit-code-wrapper-lib.mjs +17 -1801
- package/audit-code-wrapper-opencode.mjs +256 -0
- package/dispatch/merge-results.mjs +5 -3
- package/dispatch/validate-result.mjs +2 -2
- package/dist/adapters/coverageSummary.js +6 -2
- package/dist/adapters/normalizeExternal.js +16 -1
- package/dist/adapters/npmAudit.js +20 -9
- package/dist/adapters/semgrep.js +26 -1
- package/dist/cli/advanceAuditCommand.d.ts +1 -0
- package/dist/cli/advanceAuditCommand.js +95 -0
- package/dist/cli/args.js +1 -2
- package/dist/cli/auditStep.js +2 -2
- package/dist/cli/cleanup.d.ts +11 -1
- package/dist/cli/cleanup.js +25 -5
- package/dist/cli/cleanupCommand.d.ts +1 -0
- package/dist/cli/cleanupCommand.js +24 -0
- package/dist/cli/dispatch.d.ts +55 -31
- package/dist/cli/dispatch.js +298 -241
- package/dist/cli/dispatchStatusCommand.d.ts +1 -0
- package/dist/cli/dispatchStatusCommand.js +68 -0
- package/dist/cli/explainTaskCommand.d.ts +1 -0
- package/dist/cli/explainTaskCommand.js +33 -0
- package/dist/cli/importExternalAnalyzerCommand.d.ts +1 -0
- package/dist/cli/importExternalAnalyzerCommand.js +20 -0
- package/dist/cli/ingestResultsCommand.d.ts +1 -0
- package/dist/cli/ingestResultsCommand.js +34 -0
- package/dist/cli/intakeCommand.d.ts +1 -0
- package/dist/cli/intakeCommand.js +17 -0
- package/dist/cli/lineIndex.js +19 -12
- package/dist/cli/mergeAndIngestCommand.js +68 -26
- package/dist/cli/nextStepCommand.d.ts +139 -0
- package/dist/cli/nextStepCommand.js +281 -232
- package/dist/cli/planCommand.d.ts +1 -0
- package/dist/cli/planCommand.js +16 -0
- package/dist/cli/prepareDispatchCommand.d.ts +1 -0
- package/dist/cli/prepareDispatchCommand.js +25 -0
- package/dist/cli/quotaCommand.d.ts +1 -0
- package/dist/cli/quotaCommand.js +56 -0
- package/dist/cli/requeueCommand.d.ts +1 -0
- package/dist/cli/requeueCommand.js +10 -0
- package/dist/cli/runToCompletion.js +451 -412
- package/dist/cli/sampleRunCommand.d.ts +1 -0
- package/dist/cli/sampleRunCommand.js +93 -0
- package/dist/cli/statusCommand.js +1 -1
- package/dist/cli/steps.js +4 -1
- package/dist/cli/submitPacketCommand.js +16 -15
- package/dist/cli/synthesizeCommand.d.ts +1 -0
- package/dist/cli/synthesizeCommand.js +15 -0
- package/dist/cli/updateRuntimeValidationCommand.d.ts +1 -0
- package/dist/cli/updateRuntimeValidationCommand.js +16 -0
- package/dist/cli/validateCommand.d.ts +1 -0
- package/dist/cli/validateCommand.js +41 -0
- package/dist/cli/validateResultCommand.d.ts +1 -0
- package/dist/cli/validateResultCommand.js +63 -0
- package/dist/cli/validateResultsCommand.d.ts +1 -0
- package/dist/cli/validateResultsCommand.js +31 -0
- package/dist/cli/workerRunCommand.d.ts +15 -1
- package/dist/cli/workerRunCommand.js +40 -4
- package/dist/cli.d.ts +3 -2
- package/dist/cli.js +21 -628
- package/dist/coverage.js +7 -3
- package/dist/extractors/analyzers/css.js +2 -2
- package/dist/extractors/analyzers/html.js +2 -2
- package/dist/extractors/analyzers/python.js +2 -2
- package/dist/extractors/analyzers/registry.js +17 -36
- package/dist/extractors/analyzers/treeSitter.d.ts +10 -1
- package/dist/extractors/analyzers/treeSitter.js +28 -6
- package/dist/extractors/analyzers/typescript.js +104 -85
- package/dist/extractors/browserExtension.js +4 -1
- package/dist/extractors/designAssessment.js +21 -21
- package/dist/extractors/fsIntake.js +34 -10
- package/dist/extractors/graph.js +17 -7
- package/dist/extractors/graphManifestEdges/cargo.d.ts +4 -0
- package/dist/extractors/graphManifestEdges/cargo.js +107 -0
- package/dist/extractors/graphManifestEdges/go.d.ts +5 -0
- package/dist/extractors/graphManifestEdges/go.js +151 -0
- package/dist/extractors/graphManifestEdges/index.d.ts +8 -0
- package/dist/extractors/graphManifestEdges/index.js +11 -0
- package/dist/extractors/graphManifestEdges/jsonc.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/jsonc.js +97 -0
- package/dist/extractors/graphManifestEdges/maven.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/maven.js +73 -0
- package/dist/extractors/graphManifestEdges/packageJson.d.ts +19 -0
- package/dist/extractors/graphManifestEdges/packageJson.js +204 -0
- package/dist/extractors/graphManifestEdges/pnpm.d.ts +2 -0
- package/dist/extractors/graphManifestEdges/pnpm.js +42 -0
- package/dist/extractors/graphManifestEdges/pyproject.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/pyproject.js +83 -0
- package/dist/extractors/graphManifestEdges/toml.d.ts +4 -0
- package/dist/extractors/graphManifestEdges/toml.js +68 -0
- package/dist/extractors/graphManifestEdges/typescript.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/typescript.js +56 -0
- package/dist/extractors/graphManifestEdges/workspace.d.ts +10 -0
- package/dist/extractors/graphManifestEdges/workspace.js +72 -0
- package/dist/extractors/graphManifestEdges/yaml.d.ts +3 -0
- package/dist/extractors/graphManifestEdges/yaml.js +59 -0
- package/dist/extractors/graphManifestEdges/yamlPaths.d.ts +4 -0
- package/dist/extractors/graphManifestEdges/yamlPaths.js +89 -0
- package/dist/extractors/graphPythonImports.js +4 -20
- package/dist/extractors/pathPatterns.js +3 -13
- package/dist/io/artifacts.d.ts +1 -1
- package/dist/io/artifacts.js +4 -1
- package/dist/io/runArtifacts.d.ts +8 -2
- package/dist/io/runArtifacts.js +103 -69
- package/dist/io/toolingManifest.js +2 -1
- package/dist/orchestrator/advance.js +36 -0
- package/dist/orchestrator/artifactFreshness.d.ts +1 -1
- package/dist/orchestrator/artifactFreshness.js +1 -1
- package/dist/orchestrator/artifactMetadata.js +5 -5
- package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
- package/dist/orchestrator/auditTaskUtils.js +8 -12
- package/dist/orchestrator/autoFixExecutor.js +40 -26
- package/dist/orchestrator/dependencyMap.js +1 -1
- package/dist/orchestrator/executorResult.d.ts +33 -0
- package/dist/orchestrator/executors.d.ts +7 -0
- package/dist/orchestrator/executors.js +24 -0
- package/dist/orchestrator/fileAnchors.js +42 -29
- package/dist/orchestrator/fileIntegrity.js +6 -1
- package/dist/orchestrator/flowCoverage.js +1 -2
- package/dist/orchestrator/flowPlanning.js +8 -4
- package/dist/orchestrator/graphEnrichmentExecutor.js +67 -45
- package/dist/orchestrator/ingestionExecutors.js +9 -1
- package/dist/orchestrator/intakeExecutors.d.ts +0 -4
- package/dist/orchestrator/intakeExecutors.js +24 -14
- package/dist/orchestrator/localCommands.d.ts +1 -0
- package/dist/orchestrator/localCommands.js +10 -17
- package/dist/orchestrator/nextStep.js +3 -1
- package/dist/orchestrator/requeueCommand.js +4 -0
- package/dist/orchestrator/reviewPacketGraph.js +50 -18
- package/dist/orchestrator/reviewPackets.js +10 -8
- package/dist/orchestrator/runtimeCommand.js +35 -7
- package/dist/orchestrator/runtimeValidationUpdate.js +6 -0
- package/dist/orchestrator/selectiveDeepening/highRiskClean.js +3 -2
- package/dist/orchestrator/selectiveDeepening/lensVerification.js +44 -18
- package/dist/orchestrator/staleness.js +3 -3
- package/dist/orchestrator/state.js +1 -1
- package/dist/orchestrator/syntaxResolutionExecutor.js +17 -24
- package/dist/orchestrator/synthesisExecutors.js +1 -0
- package/dist/orchestrator/taskBuilder.js +5 -4
- package/dist/providers/claudeCodeProvider.js +4 -1
- package/dist/providers/opencodeProvider.js +4 -1
- package/dist/quota/discoveredLimits.js +3 -3
- package/dist/quota/headerExtraction.js +5 -2
- package/dist/quota/headerExtractors/claudeCodeHeaderExtractor.js +3 -0
- package/dist/quota/headerExtractors/index.js +3 -3
- package/dist/quota/index.d.ts +3 -1
- package/dist/quota/index.js +3 -0
- package/dist/reporting/findingIdentity.d.ts +21 -0
- package/dist/reporting/findingIdentity.js +72 -0
- package/dist/reporting/findingRanks.d.ts +3 -0
- package/dist/reporting/findingRanks.js +24 -0
- package/dist/reporting/mergeFindings.js +1 -24
- package/dist/reporting/synthesis.d.ts +3 -1
- package/dist/reporting/synthesis.js +36 -7
- package/dist/reporting/synthesisNarrativePrompt.js +3 -0
- package/dist/reporting/workBlocks.js +1 -14
- package/dist/supervisor/operatorHandoff.js +2 -6
- package/dist/supervisor/runLedger.js +30 -41
- package/dist/types/activeDispatch.d.ts +31 -0
- package/dist/types/activeDispatch.js +2 -0
- package/dist/types.d.ts +21 -4
- package/dist/types.js +24 -16
- package/dist/validation/artifacts.js +3 -0
- package/dist/validation/auditResults.js +8 -2
- package/package.json +2 -2
- package/schemas/audit_findings.schema.json +5 -1
- package/schemas/audit_plan_metrics.schema.json +1 -1
- package/schemas/audit_result.schema.json +5 -6
- package/schemas/audit_task.schema.json +1 -4
- package/schemas/blind_spot_register.schema.json +1 -1
- package/schemas/coverage_matrix.schema.json +2 -8
- package/schemas/finding.schema.json +3 -17
- package/schemas/flow_coverage.schema.json +2 -8
- package/schemas/graph_bundle.schema.json +31 -0
- package/schemas/lens.schema.json +7 -0
- package/schemas/review_packets.schema.json +6 -17
- package/schemas/step_contract.schema.json +8 -2
- package/schemas/unit_manifest.schema.json +1 -4
- package/scripts/postinstall.mjs +3 -1
- package/skills/audit-code/audit-code.prompt.md +2 -3
- package/dist/extractors/graphManifestEdges.d.ts +0 -12
- package/dist/extractors/graphManifestEdges.js +0 -1135
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
import { graphEdge, normalizeGraphPath, resolveCandidate } from "../graphPathUtils.js";
|
|
3
|
+
import { stripYamlComment, unquoteYamlScalar } from "./yaml.js";
|
|
4
|
+
export const YAML_PATH_REFERENCE_LINK_CONFIDENCE = 0.8;
|
|
5
|
+
export const YAML_CONFIG_EXTENSIONS = [".yaml", ".yml", ".json", ".toml"];
|
|
6
|
+
function isYamlSourcePath(path) {
|
|
7
|
+
const lower = normalizeGraphPath(path).toLowerCase();
|
|
8
|
+
return lower.endsWith(".yaml") || lower.endsWith(".yml");
|
|
9
|
+
}
|
|
10
|
+
function looksLikeConfigFilePath(value) {
|
|
11
|
+
if (!value.includes("/"))
|
|
12
|
+
return false;
|
|
13
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(value))
|
|
14
|
+
return false;
|
|
15
|
+
if (value.startsWith("/"))
|
|
16
|
+
return false;
|
|
17
|
+
const lower = value.toLowerCase();
|
|
18
|
+
return YAML_CONFIG_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
19
|
+
}
|
|
20
|
+
function extractYamlScalarValues(content) {
|
|
21
|
+
const values = [];
|
|
22
|
+
for (const rawLine of content.split(/\r?\n/)) {
|
|
23
|
+
const withoutComment = stripYamlComment(rawLine);
|
|
24
|
+
const trimmed = withoutComment.trim();
|
|
25
|
+
if (trimmed.length === 0)
|
|
26
|
+
continue;
|
|
27
|
+
let rawValue;
|
|
28
|
+
// key: value
|
|
29
|
+
const keyValueMatch = /^[^:[\]{}]+:\s+(.+)$/.exec(trimmed);
|
|
30
|
+
if (keyValueMatch?.[1]) {
|
|
31
|
+
rawValue = keyValueMatch[1].trim();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
// - value (list item)
|
|
35
|
+
const listItemMatch = /^-\s+(.+)$/.exec(trimmed);
|
|
36
|
+
if (listItemMatch?.[1]) {
|
|
37
|
+
rawValue = listItemMatch[1].trim();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!rawValue)
|
|
41
|
+
continue;
|
|
42
|
+
const value = unquoteYamlScalar(rawValue);
|
|
43
|
+
if (looksLikeConfigFilePath(value)) {
|
|
44
|
+
values.push(value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return values;
|
|
48
|
+
}
|
|
49
|
+
function resolveYamlPathReference(fromPath, specifier, pathLookup) {
|
|
50
|
+
const normalized = normalizeGraphPath(specifier.replace(/^\.\//, ""));
|
|
51
|
+
if (normalized.length === 0)
|
|
52
|
+
return undefined;
|
|
53
|
+
// Try as repo-root-relative first (many YAML configs use repo-root paths)
|
|
54
|
+
const repoRootTarget = resolveCandidate(normalized, pathLookup);
|
|
55
|
+
if (repoRootTarget)
|
|
56
|
+
return repoRootTarget;
|
|
57
|
+
// Fallback: relative to the YAML file's directory
|
|
58
|
+
const fromDir = posix.dirname(normalizeGraphPath(fromPath));
|
|
59
|
+
if (fromDir !== ".") {
|
|
60
|
+
const dirRelative = posix.join(fromDir, normalized);
|
|
61
|
+
const dirTarget = resolveCandidate(dirRelative, pathLookup);
|
|
62
|
+
if (dirTarget)
|
|
63
|
+
return dirTarget;
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
export function extractYamlPathReferenceEdges(fromPath, content, pathLookup) {
|
|
68
|
+
if (!isYamlSourcePath(fromPath))
|
|
69
|
+
return [];
|
|
70
|
+
const values = extractYamlScalarValues(content);
|
|
71
|
+
if (values.length === 0)
|
|
72
|
+
return [];
|
|
73
|
+
const edges = [];
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
for (const value of values) {
|
|
76
|
+
const target = resolveYamlPathReference(fromPath, value, pathLookup);
|
|
77
|
+
if (!target || target === fromPath || seen.has(target))
|
|
78
|
+
continue;
|
|
79
|
+
seen.add(target);
|
|
80
|
+
edges.push(graphEdge({
|
|
81
|
+
from: fromPath,
|
|
82
|
+
to: target,
|
|
83
|
+
kind: "yaml-path-reference-link",
|
|
84
|
+
confidence: YAML_PATH_REFERENCE_LINK_CONFIDENCE,
|
|
85
|
+
reason: `YAML file references path '${value}'.`,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
return edges;
|
|
89
|
+
}
|
|
@@ -83,7 +83,7 @@ function pythonLogicalLines(content) {
|
|
|
83
83
|
const continued = stripped.endsWith("\\");
|
|
84
84
|
const line = continued ? stripped.slice(0, -1).trimEnd() : stripped;
|
|
85
85
|
pending = pending.length > 0 ? `${pending} ${line}` : line;
|
|
86
|
-
parenDepth
|
|
86
|
+
parenDepth = Math.max(0, parenDepth + pythonParenDelta(line));
|
|
87
87
|
if (!continued && parenDepth <= 0) {
|
|
88
88
|
logicalLines.push(pending.replace(/\s+/g, " ").trim());
|
|
89
89
|
pending = "";
|
|
@@ -337,26 +337,10 @@ export function extractPythonImportEdges(fromPath, content, pathLookup) {
|
|
|
337
337
|
continue;
|
|
338
338
|
}
|
|
339
339
|
const moduleSpecifier = fromImportMatch[1] ?? "";
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const importedNames = splitPythonImportList(fromImportMatch[2] ?? "")
|
|
344
|
-
.map(stripPythonAlias)
|
|
345
|
-
.filter((name) => name !== "*" && isPythonIdentifier(name));
|
|
346
|
-
const submoduleTargets = importedNames
|
|
347
|
-
.map((name) => appendPythonImportedSpecifier(moduleSpecifier, name))
|
|
348
|
-
.map((specifier) => ({
|
|
349
|
-
specifier,
|
|
350
|
-
target: resolvePythonModuleSpecifier(fromPath, specifier, pathLookup),
|
|
351
|
-
}))
|
|
352
|
-
.filter((item) => item.target);
|
|
353
|
-
if (submoduleTargets.length > 0) {
|
|
354
|
-
for (const { specifier, target } of submoduleTargets) {
|
|
355
|
-
addPythonImportEdge(edges, fromPath, target, "python-from-import", specifier);
|
|
356
|
-
}
|
|
357
|
-
continue;
|
|
340
|
+
const rawNames = splitPythonImportList(fromImportMatch[2] ?? "").map(stripPythonAlias);
|
|
341
|
+
for (const { specifier, target } of resolvePythonFromImportTargets(fromPath, moduleSpecifier, rawNames, pathLookup)) {
|
|
342
|
+
addPythonImportEdge(edges, fromPath, target, "python-from-import", specifier);
|
|
358
343
|
}
|
|
359
|
-
addPythonImportEdge(edges, fromPath, resolvePythonModuleSpecifier(fromPath, moduleSpecifier, pathLookup), "python-from-import", moduleSpecifier);
|
|
360
344
|
}
|
|
361
345
|
return edges;
|
|
362
346
|
}
|
|
@@ -204,7 +204,7 @@ export function isGeneratedTestArtifactPath(normalized) {
|
|
|
204
204
|
return splitSegments(normalized).some((segment) => segment.startsWith(".test-") && segment.endsWith("-artifacts"));
|
|
205
205
|
}
|
|
206
206
|
export function isAuditArtifactPath(normalized) {
|
|
207
|
-
return
|
|
207
|
+
return hasSegment(normalized, ".audit-artifacts");
|
|
208
208
|
}
|
|
209
209
|
export function isTestPath(normalized) {
|
|
210
210
|
const segments = splitSegments(normalized);
|
|
@@ -259,20 +259,10 @@ export function isSurfacePath(normalized) {
|
|
|
259
259
|
hasToken(normalized, ["cli"]));
|
|
260
260
|
}
|
|
261
261
|
export function isBackgroundSurfacePath(normalized) {
|
|
262
|
-
return hasToken(normalized,
|
|
262
|
+
return hasToken(normalized, CONCURRENCY_KEYWORDS);
|
|
263
263
|
}
|
|
264
264
|
export function isNetworkSurfacePath(normalized) {
|
|
265
|
-
return
|
|
266
|
-
hasToken(normalized, [
|
|
267
|
-
"route",
|
|
268
|
-
"routes",
|
|
269
|
-
"controller",
|
|
270
|
-
"controllers",
|
|
271
|
-
"handler",
|
|
272
|
-
"handlers",
|
|
273
|
-
"endpoint",
|
|
274
|
-
"endpoints",
|
|
275
|
-
]));
|
|
265
|
+
return hasSegment(normalized, "api") || hasToken(normalized, INTERFACE_KEYWORDS);
|
|
276
266
|
}
|
|
277
267
|
export function isBillingPath(normalized) {
|
|
278
268
|
return hasToken(normalized, BILLING_KEYWORDS);
|
package/dist/io/artifacts.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { DesignAssessment } from "../types/designAssessment.js";
|
|
|
12
12
|
import type { AnalyzerCapabilityRecord } from "../types/analyzerCapability.js";
|
|
13
13
|
import type { AuditScopeManifest } from "../types/auditScope.js";
|
|
14
14
|
import type { ToolingManifest } from "../types/toolingManifest.js";
|
|
15
|
-
import type { ActiveDispatchState } from "../
|
|
15
|
+
import type { ActiveDispatchState } from "../types/activeDispatch.js";
|
|
16
16
|
type ArtifactPayloadMap = {
|
|
17
17
|
repo_manifest: RepoManifest;
|
|
18
18
|
file_disposition: FileDisposition;
|
package/dist/io/artifacts.js
CHANGED
|
@@ -149,8 +149,11 @@ export async function promoteFinalAuditReport(params, options = {}) {
|
|
|
149
149
|
try {
|
|
150
150
|
await copy(join(params.artifactsDir, "audit-findings.json"), join(params.repoRoot, "audit-findings.json"), { force: true });
|
|
151
151
|
}
|
|
152
|
-
catch {
|
|
152
|
+
catch (error) {
|
|
153
153
|
// audit-findings.json is optional output; absence must not fail promotion.
|
|
154
|
+
// Log so operators can distinguish a partial promotion from a clean one.
|
|
155
|
+
warn(`audit-code: could not promote audit-findings.json to ${join(params.repoRoot, "audit-findings.json")}: ` +
|
|
156
|
+
(error instanceof Error ? error.message : String(error)));
|
|
154
157
|
}
|
|
155
158
|
try {
|
|
156
159
|
await remove(params.artifactsDir, { recursive: true, force: true });
|
|
@@ -21,6 +21,12 @@ export declare function getRunPaths(artifactsDir: string, runId: string): RunPat
|
|
|
21
21
|
export declare function ensureSupervisorDirs(artifactsDir: string): Promise<void>;
|
|
22
22
|
export declare function writeWorkerTaskFiles(task: WorkerTask, prompt: string, paths: RunPaths, artifactsDir: string, currentTasks?: AuditTask[], options?: {
|
|
23
23
|
updateDispatch?: boolean;
|
|
24
|
+
}, log?: {
|
|
25
|
+
event: (name: string, data: Record<string, unknown>) => void;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
export declare function writeDispatchBatchFiles(artifactsDir: string, runs: DispatchBatchRun[], currentTasks: AuditTask[], log?: {
|
|
28
|
+
event: (name: string, data: Record<string, unknown>) => void;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
export declare function clearDispatchFiles(artifactsDir: string, log?: {
|
|
31
|
+
event: (name: string, data: Record<string, unknown>) => void;
|
|
24
32
|
}): Promise<void>;
|
|
25
|
-
export declare function writeDispatchBatchFiles(artifactsDir: string, runs: DispatchBatchRun[], currentTasks: AuditTask[]): Promise<void>;
|
|
26
|
-
export declare function clearDispatchFiles(artifactsDir: string): Promise<void>;
|
package/dist/io/runArtifacts.js
CHANGED
|
@@ -19,16 +19,19 @@ export const PACKET_SCHEMA_FILENAMES = [
|
|
|
19
19
|
"finding.schema.json",
|
|
20
20
|
"audit_task.schema.json",
|
|
21
21
|
];
|
|
22
|
+
async function copySchemaFiles(targetDir, entries) {
|
|
23
|
+
await mkdir(targetDir, { recursive: true });
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
await writeFile(join(targetDir, entry.name), await readFile(entry.srcPath, "utf8"), "utf8");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
22
28
|
/**
|
|
23
29
|
* Copy {@link PACKET_SCHEMA_FILENAMES} into `targetDir` under their canonical
|
|
24
30
|
* filenames, making the AuditResult schema reachable from a dispatch run's
|
|
25
31
|
* `task-results/` directory.
|
|
26
32
|
*/
|
|
27
33
|
export async function writePacketSchemaFiles(targetDir, pkgRoot) {
|
|
28
|
-
await
|
|
29
|
-
for (const name of PACKET_SCHEMA_FILENAMES) {
|
|
30
|
-
await writeFile(join(targetDir, name), await readFile(join(pkgRoot, "schemas", name), "utf8"), "utf8");
|
|
31
|
-
}
|
|
34
|
+
await copySchemaFiles(targetDir, PACKET_SCHEMA_FILENAMES.map(name => ({ srcPath: join(pkgRoot, "schemas", name), name })));
|
|
32
35
|
}
|
|
33
36
|
const CURRENT_TASK_FILENAME = "current-task.json";
|
|
34
37
|
const CURRENT_PROMPT_FILENAME = "current-prompt.md";
|
|
@@ -87,10 +90,11 @@ async function writeDispatchSchemaFiles(artifactsDir) {
|
|
|
87
90
|
// Ensure the dispatch dir exists: this is now written before the pointer
|
|
88
91
|
// files (which formerly created it), and parallel-slot dispatch may reach
|
|
89
92
|
// here before the canonical dispatch has run.
|
|
90
|
-
await
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
await copySchemaFiles(dispatchDir, [
|
|
94
|
+
{ srcPath: auditResultSchemaPath, name: CURRENT_SCHEMA_FILENAME },
|
|
95
|
+
{ srcPath: auditResultsSchemaPath, name: CURRENT_RESULTS_SCHEMA_FILENAME },
|
|
96
|
+
{ srcPath: findingSchemaPath, name: CURRENT_FINDING_SCHEMA_FILENAME },
|
|
97
|
+
]);
|
|
94
98
|
}
|
|
95
99
|
function renderSingleTaskFallbackPrompt(task, auditTask) {
|
|
96
100
|
const commandArgv = JSON.stringify(task.worker_command);
|
|
@@ -135,68 +139,88 @@ async function writeSingleTaskFallbackFiles(artifactsDir, task, currentTasks) {
|
|
|
135
139
|
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_SINGLE_TASK_FILENAME), firstTask);
|
|
136
140
|
await writeFile(join(artifactsDir, "dispatch", CURRENT_SINGLE_TASK_PROMPT_FILENAME), renderSingleTaskFallbackPrompt(task, firstTask), "utf8");
|
|
137
141
|
}
|
|
138
|
-
export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir, currentTasks, options = {}) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
142
|
+
export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir, currentTasks, options = {}, log) {
|
|
143
|
+
try {
|
|
144
|
+
await mkdir(paths.runDir, { recursive: true });
|
|
145
|
+
await writeJsonFile(paths.taskPath, task);
|
|
146
|
+
await writeFile(paths.promptPath, prompt, "utf8");
|
|
147
|
+
await writeJsonFile(paths.statusPath, {
|
|
148
|
+
run_id: task.run_id,
|
|
149
|
+
status: "dispatched",
|
|
150
|
+
});
|
|
151
|
+
// The result schema files are always required by the worker, regardless of
|
|
152
|
+
// whether this run owns the shared "current dispatch" pointer files.
|
|
153
|
+
await writeDispatchSchemaFiles(artifactsDir);
|
|
154
|
+
// Parallel-slot dispatch passes updateDispatch:false so each slot does NOT
|
|
155
|
+
// clobber the shared current-task / current-prompt / current-tasks pointers
|
|
156
|
+
// (only the single canonical dispatch should own them). The default path
|
|
157
|
+
// (updateDispatch unset/true) refreshes those pointers and the single-task
|
|
158
|
+
// fallback.
|
|
159
|
+
const updateDispatch = options.updateDispatch !== false;
|
|
160
|
+
if (!updateDispatch) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_TASK_FILENAME), task);
|
|
164
|
+
await writeFile(join(artifactsDir, "dispatch", CURRENT_PROMPT_FILENAME), prompt, "utf8");
|
|
165
|
+
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_TASKS_FILENAME), currentTasks ?? []);
|
|
166
|
+
await writeSingleTaskFallbackFiles(artifactsDir, task, currentTasks);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
log?.event("dispatch_io_error", {
|
|
170
|
+
run_id: task.run_id ?? null,
|
|
171
|
+
function: "writeWorkerTaskFiles",
|
|
172
|
+
error: String(err),
|
|
173
|
+
});
|
|
174
|
+
throw err;
|
|
157
175
|
}
|
|
158
|
-
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_TASK_FILENAME), task);
|
|
159
|
-
await writeFile(join(artifactsDir, "dispatch", CURRENT_PROMPT_FILENAME), prompt, "utf8");
|
|
160
|
-
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_TASKS_FILENAME), currentTasks ?? []);
|
|
161
|
-
await writeSingleTaskFallbackFiles(artifactsDir, task, currentTasks);
|
|
162
176
|
}
|
|
163
|
-
export async function writeDispatchBatchFiles(artifactsDir, runs, currentTasks) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
177
|
+
export async function writeDispatchBatchFiles(artifactsDir, runs, currentTasks, log) {
|
|
178
|
+
try {
|
|
179
|
+
const summary = {
|
|
180
|
+
contract_version: "audit-code-dispatch/v1alpha1",
|
|
181
|
+
mode: "parallel-batch",
|
|
182
|
+
run_count: runs.length,
|
|
183
|
+
current_tasks_path: join(artifactsDir, "dispatch", CURRENT_TASKS_FILENAME),
|
|
184
|
+
runs,
|
|
185
|
+
};
|
|
186
|
+
const promptLines = [
|
|
187
|
+
"# audit-code parallel dispatch",
|
|
188
|
+
"",
|
|
189
|
+
`This batch launched ${runs.length} deferred review run(s).`,
|
|
190
|
+
"Each run keeps its own task.json, prompt.md, result.json, and status.json under .audit-artifacts/runs/<run_id>/.",
|
|
191
|
+
"Use current-tasks.json for the combined task list. The per-run files below are operational references for launched workers; do not read per-run prompt or schema files unless debugging a failed dispatch.",
|
|
192
|
+
"",
|
|
193
|
+
"Runs:",
|
|
194
|
+
...runs.flatMap((run) => [
|
|
195
|
+
`- ${run.run_id}`,
|
|
196
|
+
` task: ${run.task_path}`,
|
|
197
|
+
` prompt (worker-owned; do not read during normal orchestration): ${run.prompt_path}`,
|
|
198
|
+
` result: ${run.result_path}`,
|
|
199
|
+
` status: ${run.status_path}`,
|
|
200
|
+
...(run.audit_results_path
|
|
201
|
+
? [` audit results: ${run.audit_results_path}`]
|
|
202
|
+
: []),
|
|
203
|
+
...(run.pending_audit_tasks_path
|
|
204
|
+
? [` pending tasks: ${run.pending_audit_tasks_path}`]
|
|
205
|
+
: []),
|
|
206
|
+
]),
|
|
207
|
+
"",
|
|
208
|
+
];
|
|
209
|
+
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_TASK_FILENAME), summary);
|
|
210
|
+
await writeFile(join(artifactsDir, "dispatch", CURRENT_PROMPT_FILENAME), promptLines.join("\n"), "utf8");
|
|
211
|
+
await writeJsonFile(join(artifactsDir, "dispatch", CURRENT_TASKS_FILENAME), currentTasks);
|
|
212
|
+
await writeDispatchSchemaFiles(artifactsDir);
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
log?.event("dispatch_io_error", {
|
|
216
|
+
run_id: "batch",
|
|
217
|
+
function: "writeDispatchBatchFiles",
|
|
218
|
+
error: String(err),
|
|
219
|
+
});
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
198
222
|
}
|
|
199
|
-
export async function clearDispatchFiles(artifactsDir) {
|
|
223
|
+
export async function clearDispatchFiles(artifactsDir, log) {
|
|
200
224
|
const targets = [
|
|
201
225
|
CURRENT_TASK_FILENAME,
|
|
202
226
|
CURRENT_PROMPT_FILENAME,
|
|
@@ -207,7 +231,17 @@ export async function clearDispatchFiles(artifactsDir) {
|
|
|
207
231
|
CURRENT_RESULTS_SCHEMA_FILENAME,
|
|
208
232
|
CURRENT_FINDING_SCHEMA_FILENAME,
|
|
209
233
|
];
|
|
210
|
-
|
|
211
|
-
|
|
234
|
+
try {
|
|
235
|
+
for (const name of targets) {
|
|
236
|
+
await rm(join(artifactsDir, "dispatch", name), { force: true });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
log?.event("dispatch_io_error", {
|
|
241
|
+
run_id: "clear",
|
|
242
|
+
function: "clearDispatchFiles",
|
|
243
|
+
error: String(err),
|
|
244
|
+
});
|
|
245
|
+
throw err;
|
|
212
246
|
}
|
|
213
247
|
}
|
|
@@ -44,7 +44,8 @@ async function readPackageVersion() {
|
|
|
44
44
|
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
45
45
|
return typeof packageJson.version === "string" ? packageJson.version : null;
|
|
46
46
|
}
|
|
47
|
-
catch {
|
|
47
|
+
catch (error) {
|
|
48
|
+
process.stderr.write(`[audit-code] readPackageVersion: failed to read/parse ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
48
49
|
return null;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { decideNextStep, findObligation } from "./nextStep.js";
|
|
2
3
|
import { deriveAuditState } from "./state.js";
|
|
3
4
|
import { computeArtifactMetadata } from "./artifactMetadata.js";
|
|
@@ -36,8 +37,12 @@ function formatExecutorFailure(selectedExecutor, selectedObligation, error) {
|
|
|
36
37
|
cause: error instanceof Error ? error : undefined,
|
|
37
38
|
});
|
|
38
39
|
}
|
|
40
|
+
function createCorrelationId() {
|
|
41
|
+
return randomUUID().replace(/-/g, "").slice(0, 8);
|
|
42
|
+
}
|
|
39
43
|
export async function advanceAudit(bundle, options = {}) {
|
|
40
44
|
const log = options.runLogger ?? RunLogger.disabled();
|
|
45
|
+
const correlationId = createCorrelationId();
|
|
41
46
|
const decision = decideNextStep(bundle);
|
|
42
47
|
const forcedExecutor = options.preferredExecutor ?? null;
|
|
43
48
|
const selectedExecutor = forcedExecutor ?? decision.selected_executor;
|
|
@@ -47,6 +52,7 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
47
52
|
log.event({
|
|
48
53
|
phase: "advance",
|
|
49
54
|
kind: "obligation",
|
|
55
|
+
correlationId,
|
|
50
56
|
obligation: selectedObligation ?? undefined,
|
|
51
57
|
note: decision.reason,
|
|
52
58
|
});
|
|
@@ -74,6 +80,7 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
74
80
|
log.event({
|
|
75
81
|
phase: "advance",
|
|
76
82
|
kind: "executor_start",
|
|
83
|
+
correlationId,
|
|
77
84
|
obligation: selectedObligation ?? undefined,
|
|
78
85
|
note: selectedExecutor,
|
|
79
86
|
});
|
|
@@ -85,6 +92,7 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
85
92
|
break;
|
|
86
93
|
}
|
|
87
94
|
case "structure_executor":
|
|
95
|
+
// root is intentionally optional: present → buildGraphBundleFromFs, absent → manifest-only buildGraphBundle
|
|
88
96
|
run = await runStructureExecutor(bundle, options.root);
|
|
89
97
|
break;
|
|
90
98
|
case "graph_enrichment_executor":
|
|
@@ -147,7 +155,32 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
147
155
|
run = runSyntaxResolutionExecutor(bundle, root);
|
|
148
156
|
break;
|
|
149
157
|
}
|
|
158
|
+
// `agent` is a host-delegation executor: its review tasks are dispatched
|
|
159
|
+
// to the active LLM agent (or a worker) and ingested via
|
|
160
|
+
// result_ingestion_executor — advanceAudit cannot complete them
|
|
161
|
+
// deterministically. Callers (next-step / run-to-completion) route it
|
|
162
|
+
// through host delegation before reaching here; if it is dispatched into
|
|
163
|
+
// advanceAudit directly it falls through to the default branch, which
|
|
164
|
+
// returns a no-progress "selected but not yet dispatched" handoff rather
|
|
165
|
+
// than throwing. An explicit case keeps the registry⇄switch invariant
|
|
166
|
+
// (executor-registry-sync) honest about agent being handled here.
|
|
167
|
+
case "agent":
|
|
150
168
|
default: {
|
|
169
|
+
log.event({
|
|
170
|
+
phase: "advance",
|
|
171
|
+
kind: "error",
|
|
172
|
+
correlationId,
|
|
173
|
+
obligation: selectedObligation ?? undefined,
|
|
174
|
+
note: `Unrecognized executor: ${selectedExecutor}`,
|
|
175
|
+
});
|
|
176
|
+
log.event({
|
|
177
|
+
phase: "advance",
|
|
178
|
+
kind: "executor_end",
|
|
179
|
+
correlationId,
|
|
180
|
+
obligation: selectedObligation ?? undefined,
|
|
181
|
+
note: selectedExecutor,
|
|
182
|
+
duration_ms: Date.now() - executorStartedAt,
|
|
183
|
+
});
|
|
151
184
|
const state = deriveAuditState(bundle);
|
|
152
185
|
state.last_executor = selectedExecutor;
|
|
153
186
|
state.last_obligation = selectedObligation ?? undefined;
|
|
@@ -170,6 +203,7 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
170
203
|
log.event({
|
|
171
204
|
phase: "advance",
|
|
172
205
|
kind: "executor_end",
|
|
206
|
+
correlationId,
|
|
173
207
|
obligation: selectedObligation ?? undefined,
|
|
174
208
|
note: selectedExecutor,
|
|
175
209
|
duration_ms: Date.now() - executorStartedAt,
|
|
@@ -178,6 +212,7 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
178
212
|
log.event({
|
|
179
213
|
phase: "advance",
|
|
180
214
|
kind: "scope",
|
|
215
|
+
correlationId,
|
|
181
216
|
obligation: selectedObligation ?? undefined,
|
|
182
217
|
note: plannedScope.mode === "delta"
|
|
183
218
|
? `delta since ${plannedScope.since}: ${plannedScope.seed_files.length} changed + ${plannedScope.expanded_files.length} neighbors; full audit advised before release`
|
|
@@ -188,6 +223,7 @@ export async function advanceAudit(bundle, options = {}) {
|
|
|
188
223
|
log.event({
|
|
189
224
|
phase: "advance",
|
|
190
225
|
kind: "artifact_write",
|
|
226
|
+
correlationId,
|
|
191
227
|
obligation: selectedObligation ?? undefined,
|
|
192
228
|
artifact,
|
|
193
229
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare function stableStringify(value: unknown): string;
|
|
2
2
|
export declare function normalizeForMetadataHash(artifactName: string, value: unknown): unknown;
|
|
3
3
|
export declare function hashArtifactValue(artifactName: string, value: unknown): string;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function buildArtifactDependenciesMap(): Record<string, string[]>;
|
|
@@ -42,7 +42,7 @@ export function hashArtifactValue(artifactName, value) {
|
|
|
42
42
|
.update(stableStringify(normalizeForMetadataHash(artifactName, value)))
|
|
43
43
|
.digest("hex");
|
|
44
44
|
}
|
|
45
|
-
export function
|
|
45
|
+
export function buildArtifactDependenciesMap() {
|
|
46
46
|
const reverse = {};
|
|
47
47
|
for (const [upstream, downstreamList] of Object.entries(ARTIFACT_DEPENDENTS_MAP)) {
|
|
48
48
|
reverse[upstream] ??= [];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { getArtifactValue } from "../io/artifacts.js";
|
|
3
|
-
import {
|
|
4
|
-
const
|
|
3
|
+
import { buildArtifactDependenciesMap, hashArtifactValue, stableStringify, } from "./artifactFreshness.js";
|
|
4
|
+
const ARTIFACT_DEPENDENCIES_MAP = buildArtifactDependenciesMap();
|
|
5
5
|
function computeDependencyFirstOrder(artifactNames) {
|
|
6
6
|
const target = new Set(artifactNames);
|
|
7
7
|
const ordered = [];
|
|
@@ -13,7 +13,7 @@ function computeDependencyFirstOrder(artifactNames) {
|
|
|
13
13
|
if (temporary.has(artifactName))
|
|
14
14
|
return;
|
|
15
15
|
temporary.add(artifactName);
|
|
16
|
-
const dependencies = (
|
|
16
|
+
const dependencies = (ARTIFACT_DEPENDENCIES_MAP[artifactName] ?? [])
|
|
17
17
|
.filter((dependencyName) => target.has(dependencyName))
|
|
18
18
|
.sort();
|
|
19
19
|
for (const dependencyName of dependencies) {
|
|
@@ -49,7 +49,7 @@ export function computeArtifactStateSignature(bundle) {
|
|
|
49
49
|
export function computeArtifactMetadata(bundle, previous, updatedArtifacts = []) {
|
|
50
50
|
const artifacts = {};
|
|
51
51
|
const updated = new Set(updatedArtifacts);
|
|
52
|
-
const presentArtifacts = Object.keys(
|
|
52
|
+
const presentArtifacts = Object.keys(ARTIFACT_DEPENDENCIES_MAP).filter((artifactName) => artifactName !== "artifact_metadata.json" &&
|
|
53
53
|
present(bundle, artifactName));
|
|
54
54
|
const orderedArtifacts = computeDependencyFirstOrder(presentArtifacts);
|
|
55
55
|
for (const artifactName of orderedArtifacts) {
|
|
@@ -64,7 +64,7 @@ export function computeArtifactMetadata(bundle, previous, updatedArtifacts = [])
|
|
|
64
64
|
continue;
|
|
65
65
|
}
|
|
66
66
|
const contentHash = hashArtifactValue(artifactName, value);
|
|
67
|
-
const dependencyRevisions = Object.fromEntries((
|
|
67
|
+
const dependencyRevisions = Object.fromEntries((ARTIFACT_DEPENDENCIES_MAP[artifactName] ?? [])
|
|
68
68
|
.filter((dependencyName) => dependencyName !== "artifact_metadata.json")
|
|
69
69
|
.sort()
|
|
70
70
|
.map((dependencyName) => [
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { AuditTask, Lens } from "../types.js";
|
|
2
|
+
/** Lens ordering for task prioritization, derived from {@link LENS_REGISTRY}
|
|
3
|
+
* (sorted ascending by `order_weight`). Deriving this from the registry ensures
|
|
4
|
+
* every lens — including `architecture`, which was previously absent from the
|
|
5
|
+
* hardcoded array — is automatically included when added to the registry. */
|
|
2
6
|
export declare const LENS_ORDER: Lens[];
|
|
3
7
|
export declare function priorityRank(priority: AuditTask["priority"]): number;
|
|
4
8
|
export declare function sortLenses(lenses: Iterable<Lens>): Lens[];
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"observability",
|
|
10
|
-
"maintainability",
|
|
11
|
-
"tests",
|
|
12
|
-
];
|
|
1
|
+
import { LENS_REGISTRY } from "../types.js";
|
|
2
|
+
/** Lens ordering for task prioritization, derived from {@link LENS_REGISTRY}
|
|
3
|
+
* (sorted ascending by `order_weight`). Deriving this from the registry ensures
|
|
4
|
+
* every lens — including `architecture`, which was previously absent from the
|
|
5
|
+
* hardcoded array — is automatically included when added to the registry. */
|
|
6
|
+
export const LENS_ORDER = [...LENS_REGISTRY]
|
|
7
|
+
.sort((a, b) => a.order_weight - b.order_weight)
|
|
8
|
+
.map((d) => d.id);
|
|
13
9
|
export function priorityRank(priority) {
|
|
14
10
|
switch (priority) {
|
|
15
11
|
case "high":
|