auditor-lambda 0.10.3 → 0.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/audit-code-wrapper-build.mjs +198 -0
  2. package/audit-code-wrapper-install-hosts.mjs +1140 -0
  3. package/audit-code-wrapper-io.mjs +155 -0
  4. package/audit-code-wrapper-legacy.mjs +125 -0
  5. package/audit-code-wrapper-lib.mjs +22 -1806
  6. package/audit-code-wrapper-opencode.mjs +255 -0
  7. package/dispatch/merge-results.mjs +5 -3
  8. package/dispatch/validate-result.mjs +2 -2
  9. package/dist/adapters/coverageSummary.js +6 -2
  10. package/dist/adapters/normalizeExternal.js +16 -1
  11. package/dist/adapters/npmAudit.js +20 -9
  12. package/dist/adapters/semgrep.js +26 -1
  13. package/dist/cli/advanceAuditCommand.d.ts +1 -0
  14. package/dist/cli/advanceAuditCommand.js +95 -0
  15. package/dist/cli/args.js +2 -3
  16. package/dist/cli/auditStep.js +2 -2
  17. package/dist/cli/cleanup.d.ts +11 -1
  18. package/dist/cli/cleanup.js +25 -5
  19. package/dist/cli/cleanupCommand.d.ts +1 -0
  20. package/dist/cli/cleanupCommand.js +24 -0
  21. package/dist/cli/dispatch.d.ts +55 -31
  22. package/dist/cli/dispatch.js +298 -241
  23. package/dist/cli/dispatchStatusCommand.d.ts +1 -0
  24. package/dist/cli/dispatchStatusCommand.js +68 -0
  25. package/dist/cli/explainTaskCommand.d.ts +1 -0
  26. package/dist/cli/explainTaskCommand.js +33 -0
  27. package/dist/cli/importExternalAnalyzerCommand.d.ts +1 -0
  28. package/dist/cli/importExternalAnalyzerCommand.js +20 -0
  29. package/dist/cli/ingestResultsCommand.d.ts +1 -0
  30. package/dist/cli/ingestResultsCommand.js +34 -0
  31. package/dist/cli/intakeCommand.d.ts +1 -0
  32. package/dist/cli/intakeCommand.js +17 -0
  33. package/dist/cli/lineIndex.js +19 -12
  34. package/dist/cli/nextStepCommand.d.ts +139 -0
  35. package/dist/cli/nextStepCommand.js +281 -234
  36. package/dist/cli/planCommand.d.ts +1 -0
  37. package/dist/cli/planCommand.js +16 -0
  38. package/dist/cli/prepareDispatchCommand.d.ts +1 -0
  39. package/dist/cli/prepareDispatchCommand.js +25 -0
  40. package/dist/cli/quotaCommand.d.ts +1 -0
  41. package/dist/cli/quotaCommand.js +56 -0
  42. package/dist/cli/requeueCommand.d.ts +1 -0
  43. package/dist/cli/requeueCommand.js +10 -0
  44. package/dist/cli/runToCompletion.js +451 -412
  45. package/dist/cli/sampleRunCommand.d.ts +1 -0
  46. package/dist/cli/sampleRunCommand.js +93 -0
  47. package/dist/cli/statusCommand.js +1 -1
  48. package/dist/cli/steps.js +4 -1
  49. package/dist/cli/submitPacketCommand.js +16 -15
  50. package/dist/cli/synthesizeCommand.d.ts +1 -0
  51. package/dist/cli/synthesizeCommand.js +15 -0
  52. package/dist/cli/updateRuntimeValidationCommand.d.ts +1 -0
  53. package/dist/cli/updateRuntimeValidationCommand.js +16 -0
  54. package/dist/cli/validateCommand.d.ts +1 -0
  55. package/dist/cli/validateCommand.js +41 -0
  56. package/dist/cli/validateResultCommand.d.ts +1 -0
  57. package/dist/cli/validateResultCommand.js +63 -0
  58. package/dist/cli/validateResultsCommand.d.ts +1 -0
  59. package/dist/cli/validateResultsCommand.js +31 -0
  60. package/dist/cli/workerRunCommand.d.ts +15 -1
  61. package/dist/cli/workerRunCommand.js +40 -4
  62. package/dist/cli.d.ts +3 -2
  63. package/dist/cli.js +21 -628
  64. package/dist/coverage.js +7 -3
  65. package/dist/extractors/analyzers/css.js +2 -2
  66. package/dist/extractors/analyzers/html.js +2 -2
  67. package/dist/extractors/analyzers/python.js +2 -2
  68. package/dist/extractors/analyzers/registry.js +17 -36
  69. package/dist/extractors/analyzers/treeSitter.d.ts +10 -1
  70. package/dist/extractors/analyzers/treeSitter.js +28 -6
  71. package/dist/extractors/analyzers/typescript.js +104 -85
  72. package/dist/extractors/browserExtension.js +4 -1
  73. package/dist/extractors/designAssessment.js +21 -21
  74. package/dist/extractors/fsIntake.js +35 -11
  75. package/dist/extractors/graph.js +17 -7
  76. package/dist/extractors/graphManifestEdges/cargo.d.ts +4 -0
  77. package/dist/extractors/graphManifestEdges/cargo.js +107 -0
  78. package/dist/extractors/graphManifestEdges/go.d.ts +5 -0
  79. package/dist/extractors/graphManifestEdges/go.js +151 -0
  80. package/dist/extractors/graphManifestEdges/index.d.ts +8 -0
  81. package/dist/extractors/graphManifestEdges/index.js +11 -0
  82. package/dist/extractors/graphManifestEdges/jsonc.d.ts +3 -0
  83. package/dist/extractors/graphManifestEdges/jsonc.js +97 -0
  84. package/dist/extractors/graphManifestEdges/maven.d.ts +3 -0
  85. package/dist/extractors/graphManifestEdges/maven.js +73 -0
  86. package/dist/extractors/graphManifestEdges/packageJson.d.ts +19 -0
  87. package/dist/extractors/graphManifestEdges/packageJson.js +204 -0
  88. package/dist/extractors/graphManifestEdges/pnpm.d.ts +2 -0
  89. package/dist/extractors/graphManifestEdges/pnpm.js +42 -0
  90. package/dist/extractors/graphManifestEdges/pyproject.d.ts +3 -0
  91. package/dist/extractors/graphManifestEdges/pyproject.js +83 -0
  92. package/dist/extractors/graphManifestEdges/toml.d.ts +4 -0
  93. package/dist/extractors/graphManifestEdges/toml.js +68 -0
  94. package/dist/extractors/graphManifestEdges/typescript.d.ts +3 -0
  95. package/dist/extractors/graphManifestEdges/typescript.js +56 -0
  96. package/dist/extractors/graphManifestEdges/workspace.d.ts +10 -0
  97. package/dist/extractors/graphManifestEdges/workspace.js +72 -0
  98. package/dist/extractors/graphManifestEdges/yaml.d.ts +3 -0
  99. package/dist/extractors/graphManifestEdges/yaml.js +59 -0
  100. package/dist/extractors/graphManifestEdges/yamlPaths.d.ts +4 -0
  101. package/dist/extractors/graphManifestEdges/yamlPaths.js +89 -0
  102. package/dist/extractors/graphPythonImports.js +4 -20
  103. package/dist/extractors/pathPatterns.js +3 -13
  104. package/dist/io/artifacts.d.ts +1 -2
  105. package/dist/io/artifacts.js +8 -4
  106. package/dist/io/runArtifacts.d.ts +8 -2
  107. package/dist/io/runArtifacts.js +103 -69
  108. package/dist/io/toolingManifest.js +2 -1
  109. package/dist/orchestrator/advance.js +36 -0
  110. package/dist/orchestrator/artifactFreshness.d.ts +1 -1
  111. package/dist/orchestrator/artifactFreshness.js +1 -1
  112. package/dist/orchestrator/artifactMetadata.js +5 -5
  113. package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
  114. package/dist/orchestrator/auditTaskUtils.js +8 -12
  115. package/dist/orchestrator/autoFixExecutor.js +40 -26
  116. package/dist/orchestrator/dependencyMap.js +1 -1
  117. package/dist/orchestrator/executorResult.d.ts +33 -0
  118. package/dist/orchestrator/executors.d.ts +7 -0
  119. package/dist/orchestrator/executors.js +24 -0
  120. package/dist/orchestrator/fileAnchors.js +42 -29
  121. package/dist/orchestrator/fileIntegrity.js +6 -1
  122. package/dist/orchestrator/flowCoverage.js +1 -2
  123. package/dist/orchestrator/flowPlanning.js +8 -4
  124. package/dist/orchestrator/graphEnrichmentExecutor.js +67 -45
  125. package/dist/orchestrator/ingestionExecutors.js +9 -1
  126. package/dist/orchestrator/intakeExecutors.d.ts +0 -4
  127. package/dist/orchestrator/intakeExecutors.js +24 -14
  128. package/dist/orchestrator/localCommands.d.ts +1 -0
  129. package/dist/orchestrator/localCommands.js +10 -17
  130. package/dist/orchestrator/nextStep.js +3 -1
  131. package/dist/orchestrator/requeueCommand.js +4 -0
  132. package/dist/orchestrator/reviewPacketGraph.js +50 -18
  133. package/dist/orchestrator/reviewPackets.js +10 -8
  134. package/dist/orchestrator/runtimeCommand.js +35 -7
  135. package/dist/orchestrator/runtimeValidationUpdate.js +6 -0
  136. package/dist/orchestrator/selectiveDeepening/highRiskClean.js +3 -2
  137. package/dist/orchestrator/selectiveDeepening/lensVerification.js +44 -18
  138. package/dist/orchestrator/staleness.js +3 -3
  139. package/dist/orchestrator/state.js +1 -1
  140. package/dist/orchestrator/syntaxResolutionExecutor.js +17 -24
  141. package/dist/orchestrator/synthesisExecutors.js +1 -0
  142. package/dist/orchestrator/taskBuilder.js +5 -4
  143. package/dist/providers/claudeCodeProvider.js +5 -2
  144. package/dist/providers/opencodeProvider.js +4 -1
  145. package/dist/quota/discoveredLimits.js +3 -3
  146. package/dist/quota/headerExtraction.js +5 -2
  147. package/dist/quota/headerExtractors/claudeCodeHeaderExtractor.js +3 -0
  148. package/dist/quota/headerExtractors/index.js +3 -3
  149. package/dist/quota/index.d.ts +3 -1
  150. package/dist/quota/index.js +3 -0
  151. package/dist/reporting/findingRanks.d.ts +3 -0
  152. package/dist/reporting/findingRanks.js +24 -0
  153. package/dist/reporting/mergeFindings.js +1 -24
  154. package/dist/reporting/synthesis.d.ts +3 -1
  155. package/dist/reporting/synthesis.js +30 -6
  156. package/dist/reporting/synthesisNarrativePrompt.js +3 -0
  157. package/dist/reporting/workBlocks.js +1 -14
  158. package/dist/supervisor/operatorHandoff.js +2 -6
  159. package/dist/supervisor/runLedger.js +30 -41
  160. package/dist/types/activeDispatch.d.ts +31 -0
  161. package/dist/types/activeDispatch.js +2 -0
  162. package/dist/types.d.ts +21 -4
  163. package/dist/types.js +24 -16
  164. package/dist/validation/artifacts.js +3 -0
  165. package/dist/validation/auditResults.js +8 -2
  166. package/package.json +2 -2
  167. package/schemas/audit_findings.schema.json +5 -1
  168. package/schemas/audit_plan_metrics.schema.json +1 -1
  169. package/schemas/audit_result.schema.json +5 -6
  170. package/schemas/audit_task.schema.json +1 -4
  171. package/schemas/blind_spot_register.schema.json +1 -1
  172. package/schemas/coverage_matrix.schema.json +2 -8
  173. package/schemas/finding.schema.json +1 -16
  174. package/schemas/flow_coverage.schema.json +2 -8
  175. package/schemas/graph_bundle.schema.json +31 -0
  176. package/schemas/lens.schema.json +7 -0
  177. package/schemas/review_packets.schema.json +6 -17
  178. package/schemas/step_contract.schema.json +8 -2
  179. package/schemas/unit_manifest.schema.json +1 -4
  180. package/scripts/postinstall.mjs +4 -3
  181. package/skills/audit-code/audit-code.prompt.md +3 -4
  182. package/dist/extractors/graphManifestEdges.d.ts +0 -12
  183. package/dist/extractors/graphManifestEdges.js +0 -1135
@@ -0,0 +1 @@
1
+ export declare function runSample(argv?: string[]): Promise<void>;
@@ -0,0 +1,93 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { buildRepoManifest } from "../extractors/fileInventory.js";
3
+ import { buildFileDisposition } from "../extractors/disposition.js";
4
+ import { buildCriticalFlowManifest } from "../extractors/flows.js";
5
+ import { buildSurfaceManifest } from "../extractors/surfaces.js";
6
+ import { buildUnitManifest } from "../orchestrator/unitBuilder.js";
7
+ import { buildFlowCoverage } from "../orchestrator/flowCoverage.js";
8
+ import { buildRuntimeValidationTasks } from "../orchestrator/runtimeValidation.js";
9
+ import { initializeCoverageFromPlan } from "../orchestrator/planning.js";
10
+ import { writeCoreArtifacts } from "../io/artifacts.js";
11
+ import { buildAuditReportModel, renderAuditReportMarkdown, } from "../reporting/synthesis.js";
12
+ import { deriveAuditState } from "../orchestrator/state.js";
13
+ import { getArtifactsDir } from "./args.js";
14
+ const SAMPLE_REPO_FILES = [
15
+ { path: "src/api/auth.ts", size_bytes: 1240, hash: "abc123" },
16
+ { path: "src/lib/session.ts", size_bytes: 980, hash: "def456" },
17
+ { path: "infra/deploy.yml", size_bytes: 420, hash: "ghi789" },
18
+ { path: "docs/notes.md", size_bytes: 300, hash: "doc111" },
19
+ ];
20
+ export async function runSample(argv = process.argv) {
21
+ const repoManifest = buildRepoManifest("sample-repo", SAMPLE_REPO_FILES);
22
+ const disposition = buildFileDisposition(repoManifest);
23
+ const unitManifest = buildUnitManifest(repoManifest, disposition);
24
+ const surfaceManifest = buildSurfaceManifest(repoManifest, disposition);
25
+ const criticalFlows = buildCriticalFlowManifest(repoManifest, surfaceManifest, disposition);
26
+ const coverage = initializeCoverageFromPlan(repoManifest, unitManifest, disposition);
27
+ const sampleResults = [
28
+ {
29
+ task_id: "src-api:security:src/api/auth.ts:1-100",
30
+ unit_id: unitManifest.units[0]?.unit_id ?? "sample-unit",
31
+ pass_id: "pass:security",
32
+ lens: "security",
33
+ agent_role: "security-auditor",
34
+ file_coverage: [{ path: "src/api/auth.ts", total_lines: 100 }],
35
+ findings: [],
36
+ notes: ["Sample result ingestion path."],
37
+ requires_followup: false,
38
+ },
39
+ ];
40
+ const flowCoverage = buildFlowCoverage(criticalFlows, coverage);
41
+ const runtimeValidationTasks = buildRuntimeValidationTasks({
42
+ unitManifest,
43
+ criticalFlows,
44
+ flowCoverage,
45
+ command: ["npm", "test"],
46
+ });
47
+ const runtimeValidationReport = {
48
+ results: runtimeValidationTasks.tasks.map((task) => ({
49
+ task_id: task.id,
50
+ status: "confirmed",
51
+ summary: "Sample runtime validation completed.",
52
+ evidence: [],
53
+ notes: [],
54
+ })),
55
+ };
56
+ const auditReport = renderAuditReportMarkdown(buildAuditReportModel({
57
+ results: sampleResults,
58
+ unitManifest,
59
+ criticalFlows,
60
+ coverageMatrix: coverage,
61
+ runtimeValidationReport,
62
+ }));
63
+ const auditState = deriveAuditState({
64
+ repo_manifest: repoManifest,
65
+ file_disposition: disposition,
66
+ unit_manifest: unitManifest,
67
+ surface_manifest: surfaceManifest,
68
+ critical_flows: criticalFlows,
69
+ flow_coverage: flowCoverage,
70
+ coverage_matrix: coverage,
71
+ runtime_validation_tasks: runtimeValidationTasks,
72
+ runtime_validation_report: runtimeValidationReport,
73
+ audit_results: sampleResults,
74
+ audit_report: auditReport,
75
+ });
76
+ const artifactsDir = getArtifactsDir(argv);
77
+ await mkdir(artifactsDir, { recursive: true });
78
+ await writeCoreArtifacts(artifactsDir, {
79
+ repo_manifest: repoManifest,
80
+ file_disposition: disposition,
81
+ unit_manifest: unitManifest,
82
+ surface_manifest: surfaceManifest,
83
+ critical_flows: criticalFlows,
84
+ flow_coverage: flowCoverage,
85
+ coverage_matrix: coverage,
86
+ runtime_validation_tasks: runtimeValidationTasks,
87
+ runtime_validation_report: runtimeValidationReport,
88
+ audit_results: sampleResults,
89
+ audit_report: auditReport,
90
+ audit_state: auditState,
91
+ });
92
+ console.log(JSON.stringify({ audit_state: auditState, artifacts_dir: artifactsDir }, null, 2));
93
+ }
@@ -17,7 +17,7 @@ export async function cmdStatus(argv) {
17
17
  }
18
18
  }
19
19
  if (!auditState) {
20
- console.error("No audit_state.json found; no active audit in this artifacts directory.");
20
+ console.log(JSON.stringify({ status: 'no_active_audit', error: 'No audit_state.json found; no active audit in this artifacts directory.' }, null, 2));
21
21
  process.exitCode = 1;
22
22
  return;
23
23
  }
package/dist/cli/steps.js CHANGED
@@ -23,9 +23,12 @@ export async function writeCurrentStep(params) {
23
23
  repo_root: params.repoRoot,
24
24
  artifacts_dir: params.artifactsDir,
25
25
  artifact_paths: {
26
+ // Caller-supplied paths are merged first so the canonical, computed
27
+ // step/prompt locations always win — a caller (or step config) must not be
28
+ // able to repoint the host at a different current-step.json / -prompt.md.
29
+ ...params.artifactPaths,
26
30
  current_step: stepPath,
27
31
  current_prompt: promptPath,
28
- ...params.artifactPaths,
29
32
  },
30
33
  ...(params.access ? { access: params.access } : {}),
31
34
  };
@@ -4,6 +4,14 @@ import { readJsonFile, writeJsonFile } from "@audit-tools/shared";
4
4
  import { validateAuditResults, formatAuditResultIssues } from "../validation/auditResults.js";
5
5
  import { DISPATCH_RESULT_MAP_FILENAME, resolveRunScopedArg, loadDispatchResultMap, entriesByTaskId, } from "./dispatch.js";
6
6
  import { fromBase64Url, getArtifactsDir, getFlag, readStdinText } from "./args.js";
7
+ function findingKey(f) {
8
+ return [
9
+ (f.lens ?? "").trim().toLowerCase(),
10
+ (f.category ?? "").trim().toLowerCase(),
11
+ (f.title ?? "").trim().toLowerCase(),
12
+ f.affected_files?.[0]?.path ?? "",
13
+ ].join("|");
14
+ }
7
15
  export async function cmdSubmitPacket(argv) {
8
16
  const runId = resolveRunScopedArg(argv, "--run-id", "--run-id-b64");
9
17
  const packetId = resolveRunScopedArg(argv, "--packet-id", "--packet-id-b64");
@@ -107,13 +115,7 @@ export async function cmdSubmitPacket(argv) {
107
115
  const existing = JSON.parse(await readFile(other.result_path, "utf8"));
108
116
  if (existing?.findings) {
109
117
  for (const f of existing.findings) {
110
- const key = [
111
- (f.lens ?? "").trim().toLowerCase(),
112
- (f.category ?? "").trim().toLowerCase(),
113
- (f.title ?? "").trim().toLowerCase(),
114
- f.affected_files?.[0]?.path ?? "",
115
- ].join("|");
116
- existingFindingKeys.add(key);
118
+ existingFindingKeys.add(findingKey(f));
117
119
  }
118
120
  }
119
121
  }
@@ -122,13 +124,7 @@ export async function cmdSubmitPacket(argv) {
122
124
  let dupCount = 0;
123
125
  for (const result of payload) {
124
126
  for (const f of result.findings ?? []) {
125
- const key = [
126
- (f.lens ?? "").trim().toLowerCase(),
127
- (f.category ?? "").trim().toLowerCase(),
128
- (f.title ?? "").trim().toLowerCase(),
129
- f.affected_files?.[0]?.path ?? "",
130
- ].join("|");
131
- if (existingFindingKeys.has(key)) {
127
+ if (existingFindingKeys.has(findingKey(f))) {
132
128
  dupCount++;
133
129
  }
134
130
  }
@@ -137,12 +133,17 @@ export async function cmdSubmitPacket(argv) {
137
133
  process.stderr.write(`[submit-packet] Warning: ${dupCount} finding(s) appear to duplicate findings from other packets in this run.\n`);
138
134
  }
139
135
  const entryByTaskId = entriesByTaskId(packetEntries);
136
+ const submittedAt = new Date().toISOString();
140
137
  for (const result of payload) {
141
138
  const entry = entryByTaskId.get(result.task_id);
142
139
  if (!entry) {
143
140
  throw new Error(`Internal error: no result path for accepted task '${result.task_id}'.`);
144
141
  }
145
- await writeJsonFile(entry.result_path, result);
142
+ await writeJsonFile(entry.result_path, {
143
+ ...result,
144
+ run_id: runId,
145
+ submitted_at: submittedAt,
146
+ });
146
147
  }
147
148
  const findingCount = payload.reduce((sum, result) => sum + result.findings.length, 0);
148
149
  console.log(JSON.stringify({
@@ -0,0 +1 @@
1
+ export declare function cmdSynthesize(argv: string[]): Promise<void>;
@@ -0,0 +1,15 @@
1
+ import { runAuditStep } from "./auditStep.js";
2
+ import { getArtifactsDir, getRootDir } from "./args.js";
3
+ export async function cmdSynthesize(argv) {
4
+ const artifactsDir = getArtifactsDir(argv);
5
+ const result = await runAuditStep({
6
+ root: getRootDir(argv),
7
+ artifactsDir,
8
+ preferredExecutor: "synthesis_executor",
9
+ });
10
+ console.log(JSON.stringify({
11
+ artifacts_dir: artifactsDir,
12
+ selected_executor: result.selected_executor,
13
+ progress_summary: result.progress_summary,
14
+ }, null, 2));
15
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdUpdateRuntimeValidation(argv: string[]): Promise<void>;
@@ -0,0 +1,16 @@
1
+ import { runAuditStep } from "./auditStep.js";
2
+ import { getArtifactsDir, getFlag, getRootDir } from "./args.js";
3
+ export async function cmdUpdateRuntimeValidation(argv) {
4
+ const artifactsDir = getArtifactsDir(argv);
5
+ const result = await runAuditStep({
6
+ root: getRootDir(argv),
7
+ artifactsDir,
8
+ preferredExecutor: "runtime_validation_update_executor",
9
+ runtimeUpdatesPath: getFlag(argv, "--updates"),
10
+ });
11
+ console.log(JSON.stringify({
12
+ artifacts_dir: artifactsDir,
13
+ selected_executor: result.selected_executor,
14
+ progress_summary: result.progress_summary,
15
+ }, null, 2));
16
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdValidate(argv: string[]): Promise<void>;
@@ -0,0 +1,41 @@
1
+ import { loadArtifactBundle } from "../io/artifacts.js";
2
+ import { prefixValidationIssues } from "@audit-tools/shared";
3
+ import { validateArtifactBundle } from "../validation/artifacts.js";
4
+ import { validateConfiguredProviderEnvironment, validateSessionConfig, } from "../validation/sessionConfig.js";
5
+ import { resolveFreshSessionProviderName, } from "../providers/index.js";
6
+ import { getSessionConfigPath, readSessionConfigFile, } from "../supervisor/sessionConfig.js";
7
+ import { getArtifactsDir } from "./args.js";
8
+ export async function cmdValidate(argv) {
9
+ const artifactsDir = getArtifactsDir(argv);
10
+ const bundle = await loadArtifactBundle(artifactsDir);
11
+ const sessionConfigPath = getSessionConfigPath(artifactsDir);
12
+ const rawSessionConfig = await readSessionConfigFile(artifactsDir);
13
+ const artifactIssues = validateArtifactBundle(bundle);
14
+ const sessionConfigIssues = rawSessionConfig === undefined
15
+ ? []
16
+ : prefixValidationIssues("session_config", validateSessionConfig(rawSessionConfig));
17
+ const providerIssues = rawSessionConfig === undefined || sessionConfigIssues.length > 0
18
+ ? []
19
+ : prefixValidationIssues("session_config", await validateConfiguredProviderEnvironment(rawSessionConfig));
20
+ const issues = [
21
+ ...artifactIssues,
22
+ ...sessionConfigIssues,
23
+ ...providerIssues,
24
+ ];
25
+ const resolvedProvider = rawSessionConfig === undefined
26
+ ? "local-subprocess"
27
+ : sessionConfigIssues.length > 0
28
+ ? null
29
+ : resolveFreshSessionProviderName(undefined, rawSessionConfig);
30
+ console.log(JSON.stringify({
31
+ artifacts_dir: artifactsDir,
32
+ session_config_path: sessionConfigPath,
33
+ session_config_present: rawSessionConfig !== undefined,
34
+ resolved_provider: resolvedProvider,
35
+ artifact_issue_count: artifactIssues.length,
36
+ session_config_issue_count: sessionConfigIssues.length + providerIssues.length,
37
+ issue_count: issues.length,
38
+ issues,
39
+ }, null, 2));
40
+ process.exitCode = issues.length > 0 ? 1 : 0;
41
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdValidateResult(argv: string[]): Promise<void>;
@@ -0,0 +1,63 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { readJsonFile } from "@audit-tools/shared";
4
+ import { validateAuditResults } from "../validation/auditResults.js";
5
+ import { loadDispatchResultMap } from "./dispatch.js";
6
+ import { fromBase64Url, getArtifactsDir, getFlag, taskResultPath } from "./args.js";
7
+ export async function cmdValidateResult(argv) {
8
+ const rawRunId = getFlag(argv, "--run-id");
9
+ const runIdB64 = getFlag(argv, "--run-id-b64");
10
+ const rawTaskId = getFlag(argv, "--task-id");
11
+ const artifactsDirB64 = getFlag(argv, "--artifacts-dir-b64");
12
+ const runId = rawRunId ?? (runIdB64 ? fromBase64Url(runIdB64) : undefined);
13
+ const taskIdB64 = getFlag(argv, "--task-id-b64");
14
+ const taskId = rawTaskId ?? (taskIdB64 ? fromBase64Url(taskIdB64) : undefined);
15
+ const artifactsDir = artifactsDirB64
16
+ ? resolve(fromBase64Url(artifactsDirB64))
17
+ : getArtifactsDir(argv);
18
+ if (!runId || !taskId) {
19
+ throw new Error("validate-result requires --run-id and --task-id (or --run-id-b64/--task-id-b64)");
20
+ }
21
+ const runDir = join(artifactsDir, "runs", runId);
22
+ const taskResultsDir = join(runDir, "task-results");
23
+ const resultMap = await loadDispatchResultMap(runDir);
24
+ const resultPath = resultMap?.entries.find((entry) => entry.task_id === taskId)?.result_path ??
25
+ taskResultPath(taskResultsDir, taskId);
26
+ const tasksPath = join(runDir, "pending-audit-tasks.json");
27
+ let raw;
28
+ try {
29
+ raw = await readFile(resultPath, "utf8");
30
+ }
31
+ catch {
32
+ console.error(`File not found: ${resultPath}`);
33
+ process.exitCode = 1;
34
+ return;
35
+ }
36
+ let obj;
37
+ try {
38
+ obj = JSON.parse(raw);
39
+ }
40
+ catch (e) {
41
+ console.error(`Invalid JSON: ${e.message}`);
42
+ process.exitCode = 1;
43
+ return;
44
+ }
45
+ let allTasks = [];
46
+ try {
47
+ allTasks = await readJsonFile(tasksPath);
48
+ }
49
+ catch { /* may not exist */ }
50
+ const matchingTasks = allTasks.filter(t => t.task_id === taskId);
51
+ const lineIndex = matchingTasks[0]?.file_line_counts ?? {};
52
+ const issues = validateAuditResults([obj], matchingTasks, { lineIndex });
53
+ const errors = issues.filter(i => i.severity === "error");
54
+ if (errors.length === 0) {
55
+ console.log(`✓ valid: ${taskId}`);
56
+ }
57
+ else {
58
+ console.error(`✗ invalid: ${taskId}`);
59
+ for (const e of errors)
60
+ console.error(` ${e.path}: ${e.message}`);
61
+ process.exitCode = 1;
62
+ }
63
+ }
@@ -0,0 +1 @@
1
+ export declare function cmdValidateResults(argv: string[]): Promise<void>;
@@ -0,0 +1,31 @@
1
+ import { readJsonFile } from "@audit-tools/shared";
2
+ import { resolve } from "node:path";
3
+ import { loadArtifactBundle } from "../io/artifacts.js";
4
+ import { validateAuditResults } from "../validation/auditResults.js";
5
+ import { buildLineIndex } from "./lineIndex.js";
6
+ import { getArtifactsDir, getFlag, getRootDir } from "./args.js";
7
+ export async function cmdValidateResults(argv) {
8
+ const artifactsDir = getArtifactsDir(argv);
9
+ const resultsPath = getFlag(argv, "--results");
10
+ if (!resultsPath) {
11
+ throw new Error("validate-results requires --results <file>");
12
+ }
13
+ const bundle = await loadArtifactBundle(artifactsDir);
14
+ const lineIndex = bundle.repo_manifest
15
+ ? await buildLineIndex(getRootDir(argv), bundle.repo_manifest)
16
+ : undefined;
17
+ const auditResults = await readJsonFile(resultsPath);
18
+ const issues = validateAuditResults(auditResults, bundle.audit_tasks ?? [], {
19
+ lineIndex,
20
+ });
21
+ const errors = issues.filter((issue) => issue.severity === "error");
22
+ const warnings = issues.filter((issue) => issue.severity === "warning");
23
+ console.log(JSON.stringify({
24
+ artifacts_dir: artifactsDir,
25
+ results_path: resolve(resultsPath),
26
+ warning_count: warnings.length,
27
+ error_count: errors.length,
28
+ issues,
29
+ }, null, 2));
30
+ process.exitCode = errors.length > 0 ? 1 : 0;
31
+ }
@@ -1 +1,15 @@
1
- export declare function cmdWorkerRun(argv: string[]): Promise<void>;
1
+ import { readJsonFile, writeJsonFile } from "@audit-tools/shared";
2
+ import { runAuditStep } from "./auditStep.js";
3
+ /**
4
+ * Injectable IO + step seam for cmdWorkerRun. Production uses the real
5
+ * @audit-tools/shared helpers and runAuditStep; tests override individual
6
+ * members to drive failure paths (e.g. a writeJsonFile that throws on the
7
+ * first call and succeeds on the fallback) without module-level mocking,
8
+ * which the project's `node --import tsx/esm --test` runner cannot do.
9
+ */
10
+ export interface WorkerRunDeps {
11
+ readJsonFile: typeof readJsonFile;
12
+ writeJsonFile: typeof writeJsonFile;
13
+ runAuditStep: typeof runAuditStep;
14
+ }
15
+ export declare function cmdWorkerRun(argv: string[], deps?: WorkerRunDeps): Promise<void>;
@@ -4,7 +4,13 @@ import { runAuditStep } from "./auditStep.js";
4
4
  import { buildLineIndexForPaths } from "./lineIndex.js";
5
5
  import { WORKER_RESULT_CONTRACT_VERSION, formatAuditResultValidationError } from "./workerResult.js";
6
6
  import { getFlag, looksLikeCliFlag } from "./args.js";
7
- export async function cmdWorkerRun(argv) {
7
+ const defaultWorkerRunDeps = {
8
+ readJsonFile,
9
+ writeJsonFile,
10
+ runAuditStep,
11
+ };
12
+ export async function cmdWorkerRun(argv, deps = defaultWorkerRunDeps) {
13
+ const { readJsonFile, writeJsonFile, runAuditStep } = deps;
8
14
  const taskPath = getFlag(argv, "--task");
9
15
  if (!taskPath) {
10
16
  throw new Error("worker-run requires --task <path>");
@@ -31,8 +37,16 @@ export async function cmdWorkerRun(argv) {
31
37
  const issues = validateAuditResults(auditResults, pendingTasks, {
32
38
  lineIndex: await buildLineIndexForPaths(task.repo_root, pendingTasks.flatMap((item) => item.file_paths)),
33
39
  });
34
- const errors = issues.filter((issue) => issue.severity === "error");
35
- const warnings = issues.filter((issue) => issue.severity === "warning");
40
+ const errors = [];
41
+ const warnings = [];
42
+ for (const issue of issues) {
43
+ if (issue.severity === "error") {
44
+ errors.push(issue);
45
+ }
46
+ else {
47
+ warnings.push(issue);
48
+ }
49
+ }
36
50
  if (warnings.length > 0) {
37
51
  process.stderr.write(`audit-results validation: ${warnings.length} warning(s):\n` +
38
52
  formatAuditResultIssues(warnings) +
@@ -80,7 +94,29 @@ export async function cmdWorkerRun(argv) {
80
94
  errors: [error instanceof Error ? error.message : String(error)],
81
95
  };
82
96
  }
83
- await writeJsonFile(task.result_path, workerResult);
97
+ try {
98
+ await writeJsonFile(task.result_path, workerResult);
99
+ }
100
+ catch (writeError) {
101
+ const writeFailedResult = {
102
+ contract_version: WORKER_RESULT_CONTRACT_VERSION,
103
+ run_id: task.run_id,
104
+ obligation_id: task.obligation_id,
105
+ status: "failed",
106
+ progress_made: false,
107
+ selected_executor: task.preferred_executor,
108
+ artifacts_written: [],
109
+ summary: `Worker result could not be persisted to ${task.result_path}: ${writeError instanceof Error ? writeError.message : String(writeError)}`,
110
+ next_likely_step: task.obligation_id,
111
+ errors: [writeError instanceof Error ? writeError.message : String(writeError)],
112
+ };
113
+ process.stderr.write(`[workerRunCommand] Failed to write result to ${task.result_path}: ${writeError instanceof Error ? writeError.message : String(writeError)}\n`);
114
+ // Best-effort second attempt with the degraded result.
115
+ await writeJsonFile(task.result_path, writeFailedResult);
116
+ console.log(JSON.stringify(writeFailedResult, null, 2));
117
+ process.exitCode = 1;
118
+ return;
119
+ }
84
120
  console.log(JSON.stringify(workerResult, null, 2));
85
121
  if (workerResult.status === "failed") {
86
122
  process.exitCode = 1;
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { getFlag, hasFlag, getArtifactsDir, getRootDir, warnIfNotGitRepo, getBatchResultsDir, getMaxRuns, getAgentBatchSize, getParallelWorkers, getTimeoutMs, chunkArray, getUiMode, looksLikeCliFlag, countLines } from "./cli/args.js";
1
+ import { getFlag, hasFlag, getArtifactsDir, getRootDir, getBatchResultsDir, getMaxRuns, getAgentBatchSize, getParallelWorkers, getTimeoutMs, chunkArray, getUiMode, looksLikeCliFlag, countLines, warnIfNotGitRepo } from "./cli/args.js";
2
+ import { runSample } from "./cli/sampleRunCommand.js";
3
+ export { runSample };
2
4
  export declare const cliTestUtils: {
3
5
  defaults: {
4
6
  rootDir: string;
@@ -24,5 +26,4 @@ export declare const cliTestUtils: {
24
26
  countLines: typeof countLines;
25
27
  warnIfNotGitRepo: typeof warnIfNotGitRepo;
26
28
  };
27
- export declare function runSample(argv?: string[]): Promise<void>;
28
29
  export declare function runCli(argv: string[]): Promise<void>;