auditor-lambda 0.2.5 → 0.2.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 (71) hide show
  1. package/README.md +35 -7
  2. package/audit-code-wrapper-lib.mjs +1612 -331
  3. package/dist/cli.js +397 -38
  4. package/dist/coverage.d.ts +2 -2
  5. package/dist/coverage.js +5 -5
  6. package/dist/extractors/disposition.js +10 -1
  7. package/dist/extractors/flows.js +7 -1
  8. package/dist/extractors/pathPatterns.d.ts +3 -0
  9. package/dist/extractors/pathPatterns.js +15 -0
  10. package/dist/extractors/risk.js +7 -1
  11. package/dist/io/artifacts.d.ts +6 -6
  12. package/dist/io/artifacts.js +14 -17
  13. package/dist/io/json.d.ts +2 -0
  14. package/dist/io/json.js +15 -0
  15. package/dist/io/runArtifacts.d.ts +3 -1
  16. package/dist/io/runArtifacts.js +20 -5
  17. package/dist/mcp/server.d.ts +1 -0
  18. package/dist/mcp/server.js +579 -0
  19. package/dist/orchestrator/advance.js +9 -2
  20. package/dist/orchestrator/dependencyMap.js +9 -13
  21. package/dist/orchestrator/executors.js +7 -2
  22. package/dist/orchestrator/flowRequeue.d.ts +2 -2
  23. package/dist/orchestrator/flowRequeue.js +16 -3
  24. package/dist/orchestrator/internalExecutors.d.ts +2 -1
  25. package/dist/orchestrator/internalExecutors.js +129 -48
  26. package/dist/orchestrator/requeue.js +10 -4
  27. package/dist/orchestrator/requeueCommand.js +15 -2
  28. package/dist/orchestrator/resultIngestion.d.ts +2 -1
  29. package/dist/orchestrator/resultIngestion.js +26 -6
  30. package/dist/orchestrator/runtimeValidation.d.ts +7 -2
  31. package/dist/orchestrator/runtimeValidation.js +61 -49
  32. package/dist/orchestrator/runtimeValidationUpdate.js +2 -4
  33. package/dist/orchestrator/state.js +28 -14
  34. package/dist/orchestrator/taskBuilder.js +4 -2
  35. package/dist/orchestrator/trivialAudit.d.ts +4 -0
  36. package/dist/orchestrator/trivialAudit.js +49 -0
  37. package/dist/prompts/renderWorkerPrompt.js +6 -2
  38. package/dist/providers/spawnLoggedCommand.js +17 -0
  39. package/dist/reporting/mergeFindings.js +3 -11
  40. package/dist/reporting/rootCause.js +92 -9
  41. package/dist/reporting/synthesis.d.ts +25 -22
  42. package/dist/reporting/synthesis.js +92 -59
  43. package/dist/reporting/workBlocks.d.ts +12 -3
  44. package/dist/reporting/workBlocks.js +124 -70
  45. package/dist/supervisor/sessionConfig.js +4 -2
  46. package/dist/types/flows.d.ts +2 -0
  47. package/dist/types/runtimeValidation.d.ts +2 -1
  48. package/dist/types.d.ts +8 -6
  49. package/dist/validation/auditResults.d.ts +5 -2
  50. package/dist/validation/auditResults.js +335 -43
  51. package/docs/agent-integrations.md +38 -29
  52. package/docs/artifacts.md +18 -51
  53. package/docs/bootstrap-install.md +60 -30
  54. package/docs/contract.md +25 -117
  55. package/docs/field-trial-bug-report.md +237 -0
  56. package/docs/next-steps.md +59 -44
  57. package/docs/packaging.md +13 -3
  58. package/docs/production-launch-bar.md +2 -2
  59. package/docs/production-readiness.md +9 -5
  60. package/docs/releasing.md +81 -0
  61. package/docs/session-config.md +20 -1
  62. package/docs/usage.md +22 -0
  63. package/package.json +4 -1
  64. package/schemas/audit_result.schema.json +4 -5
  65. package/schemas/audit_task.schema.json +10 -0
  66. package/schemas/runtime_validation_report.schema.json +1 -1
  67. package/skills/audit-code/SKILL.md +11 -2
  68. package/skills/audit-code/audit-code.prompt.md +11 -10
  69. package/schemas/merged_findings.schema.json +0 -19
  70. package/schemas/root_cause_clusters.schema.json +0 -28
  71. package/schemas/synthesis_report.schema.json +0 -61
@@ -1,8 +1,8 @@
1
- import type { CoverageFileRecord, CoverageMatrix, Lens, ReviewedLineRange } from "./types.js";
1
+ import type { CoverageFileRecord, CoverageMatrix, FileCoverageRecord, Lens } from "./types.js";
2
2
  export declare function createCoverageMatrix(paths: string[]): CoverageMatrix;
3
3
  export declare function markExcludedPath(matrix: CoverageMatrix, path: string, classificationStatus: string): void;
4
4
  export declare function applyUnitCoverage(matrix: CoverageMatrix, path: string, unitId: string, requiredLenses: Lens[]): void;
5
- export declare function applyReviewedRanges(matrix: CoverageMatrix, reviewedRanges: ReviewedLineRange[]): void;
5
+ export declare function applyFileCoverage(matrix: CoverageMatrix, fileCoverage: FileCoverageRecord[]): void;
6
6
  export declare function findUncoveredFiles(matrix: CoverageMatrix): CoverageFileRecord[];
7
7
  export declare function buildRequeueTargets(matrix: CoverageMatrix): Array<{
8
8
  path: string;
package/dist/coverage.js CHANGED
@@ -32,13 +32,13 @@ export function applyUnitCoverage(matrix, path, unitId, requiredLenses) {
32
32
  ...new Set([...record.required_lenses, ...requiredLenses]),
33
33
  ];
34
34
  }
35
- export function applyReviewedRanges(matrix, reviewedRanges) {
36
- for (const range of reviewedRanges) {
37
- const record = matrix.files.find((file) => file.path === range.path);
35
+ export function applyFileCoverage(matrix, fileCoverage) {
36
+ for (const coverage of fileCoverage) {
37
+ const record = matrix.files.find((file) => file.path === coverage.path);
38
38
  if (!record || record.audit_status === "excluded")
39
39
  continue;
40
- if (range.lens && !record.completed_lenses.includes(range.lens)) {
41
- record.completed_lenses.push(range.lens);
40
+ if (coverage.lens && !record.completed_lenses.includes(coverage.lens)) {
41
+ record.completed_lenses.push(coverage.lens);
42
42
  }
43
43
  }
44
44
  for (const file of matrix.files) {
@@ -1,4 +1,4 @@
1
- import { isNodeModulesOrGit, isBuildOutput, isVendorPath, isBinaryArtifact, isDocPath, } from "./pathPatterns.js";
1
+ import { isNodeModulesOrGit, isBuildOutput, isVendorPath, isBinaryArtifact, isLicensePath, isLockfilePath, isLogPath, isDocPath, } from "./pathPatterns.js";
2
2
  function inferDisposition(path) {
3
3
  const normalized = path.toLowerCase();
4
4
  if (isNodeModulesOrGit(normalized)) {
@@ -17,6 +17,15 @@ function inferDisposition(path) {
17
17
  reason: "Non-source binary-like artifact.",
18
18
  };
19
19
  }
20
+ if (isLogPath(normalized)) {
21
+ return { path, status: "generated", reason: "Runtime log artifact." };
22
+ }
23
+ if (isLicensePath(normalized)) {
24
+ return { path, status: "doc_only", reason: "License file is not auditable code." };
25
+ }
26
+ if (isLockfilePath(normalized)) {
27
+ return { path, status: "generated", reason: "Lockfile excluded from code audit scope." };
28
+ }
20
29
  if (isDocPath(normalized)) {
21
30
  return { path, status: "doc_only", reason: "Documentation artifact." };
22
31
  }
@@ -94,6 +94,7 @@ export function buildCriticalFlowManifest(repoManifest, surfaceManifest, disposi
94
94
  entrypoints: [entry],
95
95
  paths,
96
96
  concerns: inferConcerns(paths),
97
+ confidence: paths.length > 1 ? "high" : "low",
97
98
  notes: [
98
99
  "Heuristic critical-flow inference from detected surfaces and related paths.",
99
100
  ],
@@ -108,9 +109,14 @@ export function buildCriticalFlowManifest(repoManifest, surfaceManifest, disposi
108
109
  entrypoints: [path],
109
110
  paths: relatedPaths(path, availablePaths),
110
111
  concerns: ["data_integrity", "reliability"],
112
+ confidence: "high",
111
113
  notes: ["Heuristic data-evolution flow."],
112
114
  });
113
115
  }
114
116
  }
115
- return { flows: dedupeFlows(flows) };
117
+ const deduped = dedupeFlows(flows);
118
+ return {
119
+ flows: deduped,
120
+ fallback_required: deduped.length === 0 || deduped.some((flow) => flow.confidence === "low"),
121
+ };
116
122
  }
@@ -7,6 +7,9 @@ export declare function isNodeModulesOrGit(normalized: string): boolean;
7
7
  export declare function isBuildOutput(normalized: string): boolean;
8
8
  export declare function isVendorPath(normalized: string): boolean;
9
9
  export declare function isBinaryArtifact(normalized: string): boolean;
10
+ export declare function isLogPath(normalized: string): boolean;
11
+ export declare function isLicensePath(normalized: string): boolean;
12
+ export declare function isLockfilePath(normalized: string): boolean;
10
13
  export declare function isDocPath(normalized: string): boolean;
11
14
  export declare function isTestPath(normalized: string): boolean;
12
15
  export declare function isInterfacePath(normalized: string): boolean;
@@ -21,6 +21,21 @@ export function isBinaryArtifact(normalized) {
21
21
  normalized.endsWith(".pdf") ||
22
22
  normalized.endsWith(".zip"));
23
23
  }
24
+ export function isLogPath(normalized) {
25
+ return normalized.endsWith(".log") || normalized.includes("stdout.log") || normalized.includes("stderr.log");
26
+ }
27
+ export function isLicensePath(normalized) {
28
+ const base = normalized.split(/[/\\]/).pop() ?? normalized;
29
+ return base === "license" || base.startsWith("license.");
30
+ }
31
+ export function isLockfilePath(normalized) {
32
+ return (normalized.endsWith("package-lock.json") ||
33
+ normalized.endsWith("pnpm-lock.yaml") ||
34
+ normalized.endsWith("yarn.lock") ||
35
+ normalized.endsWith("cargo.lock") ||
36
+ normalized.endsWith("composer.lock") ||
37
+ normalized.endsWith("go.sum"));
38
+ }
24
39
  export function isDocPath(normalized) {
25
40
  return normalized.endsWith(".md") || normalized.startsWith("docs/");
26
41
  }
@@ -19,6 +19,9 @@ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerR
19
19
  signals.push("writes_or_persistence");
20
20
  if (unit.required_lenses.includes("config_deployment"))
21
21
  signals.push("operational_surface");
22
+ if (unit.files.some((path) => /(write|save|persist|lock|cache|retry|open|sync|refresh)/i.test(path))) {
23
+ signals.push("path_level_stateful_behavior");
24
+ }
22
25
  const flowHits = unit.files.reduce((sum, path) => sum + (flowMap.get(path) ?? 0), 0);
23
26
  if (flowHits > 0) {
24
27
  signals.push("critical_flow_member");
@@ -29,7 +32,10 @@ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerR
29
32
  }
30
33
  return {
31
34
  unit_id: unit.unit_id,
32
- risk_score: (unit.risk_score ?? 0) + flowHits + externalHits,
35
+ risk_score: (unit.risk_score ?? 0) +
36
+ flowHits +
37
+ externalHits +
38
+ (signals.includes("path_level_stateful_behavior") ? 1 : 0),
33
39
  signals,
34
40
  notes: [
35
41
  "Initial heuristic risk scoring.",
@@ -26,9 +26,7 @@ export interface ArtifactBundle {
26
26
  audit_results?: AuditResult[];
27
27
  audit_tasks?: AuditTask[];
28
28
  requeue_tasks?: AuditTask[];
29
- merged_findings?: unknown;
30
- root_cause_clusters?: unknown;
31
- synthesis_report?: unknown;
29
+ audit_report?: string;
32
30
  audit_state?: AuditState;
33
31
  artifact_metadata?: ArtifactMetadataManifest;
34
32
  }
@@ -49,9 +47,7 @@ export declare const ARTIFACT_FILE_TO_BUNDLE_KEY: {
49
47
  readonly "audit_results.jsonl": "audit_results";
50
48
  readonly "audit_tasks.json": "audit_tasks";
51
49
  readonly "requeue_tasks.json": "requeue_tasks";
52
- readonly "merged_findings.json": "merged_findings";
53
- readonly "root_cause_clusters.json": "root_cause_clusters";
54
- readonly "synthesis_report.json": "synthesis_report";
50
+ readonly "audit-report.md": "audit_report";
55
51
  readonly "audit_state.json": "audit_state";
56
52
  readonly "artifact_metadata.json": "artifact_metadata";
57
53
  };
@@ -59,3 +55,7 @@ export declare function getArtifactValue(bundle: ArtifactBundle, artifactName: s
59
55
  export declare function loadArtifactBundle(root: string): Promise<ArtifactBundle>;
60
56
  export declare function writeCoreArtifacts(root: string, bundle: ArtifactBundle): Promise<void>;
61
57
  export declare function cleanupIntermediateArtifacts(root: string): Promise<string[]>;
58
+ export declare function promoteFinalAuditReport(params: {
59
+ artifactsDir: string;
60
+ repoRoot: string;
61
+ }): Promise<void>;
@@ -1,6 +1,6 @@
1
- import { unlink } from "node:fs/promises";
1
+ import { cp, rm, unlink } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { writeJsonFile, readOptionalJsonFile, readOptionalNdjsonFile, writeNdjsonFile, } from "./json.js";
3
+ import { writeJsonFile, readOptionalJsonFile, readOptionalNdjsonFile, readOptionalTextFile, writeNdjsonFile, writeTextFile, } from "./json.js";
4
4
  export const ARTIFACT_FILE_TO_BUNDLE_KEY = {
5
5
  "repo_manifest.json": "repo_manifest",
6
6
  "file_disposition.json": "file_disposition",
@@ -18,9 +18,7 @@ export const ARTIFACT_FILE_TO_BUNDLE_KEY = {
18
18
  "audit_results.jsonl": "audit_results",
19
19
  "audit_tasks.json": "audit_tasks",
20
20
  "requeue_tasks.json": "requeue_tasks",
21
- "merged_findings.json": "merged_findings",
22
- "root_cause_clusters.json": "root_cause_clusters",
23
- "synthesis_report.json": "synthesis_report",
21
+ "audit-report.md": "audit_report",
24
22
  "audit_state.json": "audit_state",
25
23
  "artifact_metadata.json": "artifact_metadata",
26
24
  };
@@ -51,9 +49,7 @@ export async function loadArtifactBundle(root) {
51
49
  bundle.audit_results = await readOptionalNdjsonFile(`${root}/audit_results.jsonl`);
52
50
  bundle.audit_tasks = await readOptionalJsonFile(`${root}/audit_tasks.json`);
53
51
  bundle.requeue_tasks = await readOptionalJsonFile(`${root}/requeue_tasks.json`);
54
- bundle.merged_findings = await readOptionalJsonFile(`${root}/merged_findings.json`);
55
- bundle.root_cause_clusters = await readOptionalJsonFile(`${root}/root_cause_clusters.json`);
56
- bundle.synthesis_report = await readOptionalJsonFile(`${root}/synthesis_report.json`);
52
+ bundle.audit_report = await readOptionalTextFile(`${root}/audit-report.md`);
57
53
  bundle.audit_state = await readOptionalJsonFile(`${root}/audit_state.json`);
58
54
  bundle.artifact_metadata = await readOptionalJsonFile(`${root}/artifact_metadata.json`);
59
55
  return bundle;
@@ -91,20 +87,13 @@ export async function writeCoreArtifacts(root, bundle) {
91
87
  await writeJsonFile(`${root}/audit_tasks.json`, bundle.audit_tasks);
92
88
  if (bundle.requeue_tasks)
93
89
  await writeJsonFile(`${root}/requeue_tasks.json`, bundle.requeue_tasks);
94
- if (bundle.merged_findings)
95
- await writeJsonFile(`${root}/merged_findings.json`, bundle.merged_findings);
96
- if (bundle.root_cause_clusters)
97
- await writeJsonFile(`${root}/root_cause_clusters.json`, bundle.root_cause_clusters);
98
- if (bundle.synthesis_report)
99
- await writeJsonFile(`${root}/synthesis_report.json`, bundle.synthesis_report);
90
+ if (bundle.audit_report !== undefined)
91
+ await writeTextFile(`${root}/audit-report.md`, bundle.audit_report);
100
92
  if (bundle.audit_state)
101
93
  await writeJsonFile(`${root}/audit_state.json`, bundle.audit_state);
102
94
  if (bundle.artifact_metadata)
103
95
  await writeJsonFile(`${root}/artifact_metadata.json`, bundle.artifact_metadata);
104
96
  }
105
- // Intermediate files deleted after synthesis completes. The final outputs
106
- // (synthesis_report.json, merged_findings.json, root_cause_clusters.json,
107
- // audit_state.json) are retained.
108
97
  const INTERMEDIATE_ARTIFACTS = [
109
98
  "repo_manifest.json",
110
99
  "file_disposition.json",
@@ -123,6 +112,8 @@ const INTERMEDIATE_ARTIFACTS = [
123
112
  "audit_tasks.json",
124
113
  "requeue_tasks.json",
125
114
  "artifact_metadata.json",
115
+ "audit_state.json",
116
+ "audit-report.md",
126
117
  ];
127
118
  export async function cleanupIntermediateArtifacts(root) {
128
119
  const deleted = [];
@@ -137,3 +128,9 @@ export async function cleanupIntermediateArtifacts(root) {
137
128
  }
138
129
  return deleted;
139
130
  }
131
+ export async function promoteFinalAuditReport(params) {
132
+ const source = join(params.artifactsDir, "audit-report.md");
133
+ const destination = join(params.repoRoot, "audit-report.md");
134
+ await cp(source, destination, { force: true });
135
+ await rm(params.artifactsDir, { recursive: true, force: true });
136
+ }
package/dist/io/json.d.ts CHANGED
@@ -6,3 +6,5 @@ export declare function readNdjsonFile<T>(path: string): Promise<T[]>;
6
6
  export declare function readOptionalJsonFile<T>(path: string): Promise<T | undefined>;
7
7
  export declare function readOptionalNdjsonFile<T>(path: string): Promise<T[] | undefined>;
8
8
  export declare function writeNdjsonFile(path: string, values: unknown[]): Promise<void>;
9
+ export declare function readOptionalTextFile(path: string): Promise<string | undefined>;
10
+ export declare function writeTextFile(path: string, value: string): Promise<void>;
package/dist/io/json.js CHANGED
@@ -94,3 +94,18 @@ export async function writeNdjsonFile(path, values) {
94
94
  }
95
95
  await writeFile(path, values.map((v) => JSON.stringify(v)).join("\n") + "\n", "utf8");
96
96
  }
97
+ export async function readOptionalTextFile(path) {
98
+ try {
99
+ return await readFile(path, "utf8");
100
+ }
101
+ catch (error) {
102
+ if (isFileMissingError(error)) {
103
+ return undefined;
104
+ }
105
+ throw new Error(`Failed to read ${path}: ${errorMessage(error)}`);
106
+ }
107
+ }
108
+ export async function writeTextFile(path, value) {
109
+ await mkdir(dirname(path), { recursive: true });
110
+ await writeFile(path, value, "utf8");
111
+ }
@@ -1,3 +1,4 @@
1
+ import type { AuditTask } from "../types.js";
1
2
  import type { WorkerTask } from "../types/workerSession.js";
2
3
  export interface RunPaths {
3
4
  runDir: string;
@@ -11,4 +12,5 @@ export interface RunPaths {
11
12
  export declare function buildRunId(obligationId: string | null, index: number): string;
12
13
  export declare function getRunPaths(artifactsDir: string, runId: string): RunPaths;
13
14
  export declare function ensureSupervisorDirs(artifactsDir: string): Promise<void>;
14
- export declare function writeWorkerTaskFiles(task: WorkerTask, prompt: string, paths: RunPaths, artifactsDir: string): Promise<void>;
15
+ export declare function writeWorkerTaskFiles(task: WorkerTask, prompt: string, paths: RunPaths, artifactsDir: string, currentTasks?: AuditTask[]): Promise<void>;
16
+ export declare function clearDispatchFiles(artifactsDir: string): Promise<void>;
@@ -1,6 +1,10 @@
1
- import { mkdir, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
1
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
3
4
  import { writeJsonFile } from "./json.js";
5
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
6
+ const packageRoot = resolve(moduleDir, "..", "..");
7
+ const auditResultSchemaPath = join(packageRoot, "schemas", "audit_result.schema.json");
4
8
  export function buildRunId(obligationId, index) {
5
9
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
6
10
  const obligation = (obligationId ?? "terminal").replace(/[^a-zA-Z0-9_-]/g, "-");
@@ -20,11 +24,9 @@ export function getRunPaths(artifactsDir, runId) {
20
24
  }
21
25
  export async function ensureSupervisorDirs(artifactsDir) {
22
26
  await mkdir(join(artifactsDir, "dispatch"), { recursive: true });
23
- await mkdir(join(artifactsDir, "worker-results"), { recursive: true });
24
- await mkdir(join(artifactsDir, "worker-logs"), { recursive: true });
25
27
  await mkdir(join(artifactsDir, "runs"), { recursive: true });
26
28
  }
27
- export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir) {
29
+ export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir, currentTasks) {
28
30
  await mkdir(paths.runDir, { recursive: true });
29
31
  await writeJsonFile(paths.taskPath, task);
30
32
  await writeFile(paths.promptPath, prompt, "utf8");
@@ -34,4 +36,17 @@ export async function writeWorkerTaskFiles(task, prompt, paths, artifactsDir) {
34
36
  });
35
37
  await writeJsonFile(join(artifactsDir, "dispatch", "current-task.json"), task);
36
38
  await writeFile(join(artifactsDir, "dispatch", "current-prompt.md"), prompt, "utf8");
39
+ await writeJsonFile(join(artifactsDir, "dispatch", "current-tasks.json"), currentTasks ?? []);
40
+ await writeFile(join(artifactsDir, "dispatch", "audit-result.schema.json"), await readFile(auditResultSchemaPath, "utf8"), "utf8");
41
+ }
42
+ export async function clearDispatchFiles(artifactsDir) {
43
+ const targets = [
44
+ "current-task.json",
45
+ "current-prompt.md",
46
+ "current-tasks.json",
47
+ "audit-result.schema.json",
48
+ ];
49
+ for (const name of targets) {
50
+ await rm(join(artifactsDir, "dispatch", name), { force: true });
51
+ }
37
52
  }
@@ -0,0 +1 @@
1
+ export declare function runAuditCodeMcpServer(argv: string[]): Promise<void>;