auditor-lambda 0.3.30 → 0.3.33

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 (36) hide show
  1. package/README.md +2 -1
  2. package/audit-code-wrapper-lib.mjs +208 -198
  3. package/dist/cli.d.ts +5 -0
  4. package/dist/cli.js +65 -101
  5. package/dist/extractors/risk.js +6 -4
  6. package/dist/io/artifacts.d.ts +2 -0
  7. package/dist/io/artifacts.js +1 -0
  8. package/dist/io/toolingManifest.d.ts +1 -0
  9. package/dist/io/toolingManifest.js +1 -1
  10. package/dist/mcp/server.d.ts +71 -0
  11. package/dist/mcp/server.js +261 -222
  12. package/dist/orchestrator/artifactFreshness.d.ts +4 -0
  13. package/dist/orchestrator/artifactFreshness.js +45 -0
  14. package/dist/orchestrator/artifactMetadata.js +2 -51
  15. package/dist/orchestrator/dependencyMap.js +14 -0
  16. package/dist/orchestrator/internalExecutors.js +8 -0
  17. package/dist/orchestrator/staleness.js +2 -46
  18. package/dist/orchestrator/state.js +1 -1
  19. package/dist/orchestrator/syntaxResolutionExecutor.js +121 -13
  20. package/dist/orchestrator/unitBuilder.js +2 -1
  21. package/dist/providers/spawnLoggedCommand.js +71 -18
  22. package/dist/providers/types.d.ts +5 -0
  23. package/dist/quota/scheduler.js +10 -2
  24. package/dist/quota/state.js +6 -2
  25. package/dist/supervisor/operatorHandoff.js +1 -1
  26. package/dist/types/externalAnalyzer.d.ts +10 -0
  27. package/dist/types/sessionConfig.d.ts +1 -0
  28. package/dist/types/workerSession.js +1 -2
  29. package/dist/validation/artifacts.js +36 -0
  30. package/dist/validation/sessionConfig.js +4 -0
  31. package/package.json +1 -1
  32. package/schemas/audit_task.schema.json +2 -2
  33. package/schemas/risk_register.schema.json +1 -1
  34. package/schemas/unit_manifest.schema.json +2 -1
  35. package/scripts/postinstall.mjs +10 -41
  36. package/skills/audit-code/audit-code.prompt.md +5 -0
package/dist/cli.js CHANGED
@@ -87,6 +87,22 @@ function getOptionalBooleanFlag(argv, name) {
87
87
  }
88
88
  throw new Error(`${name} must be either true or false.`);
89
89
  }
90
+ function optionalBooleanEnv(value) {
91
+ if (value === "true")
92
+ return true;
93
+ if (value === "false")
94
+ return false;
95
+ return undefined;
96
+ }
97
+ export function resolveHostDispatchCapability(options) {
98
+ if (options.explicit !== undefined) {
99
+ return options.explicit;
100
+ }
101
+ if (options.sessionConfig.host_can_dispatch_subagents !== undefined) {
102
+ return options.sessionConfig.host_can_dispatch_subagents;
103
+ }
104
+ return optionalBooleanEnv((options.env ?? process.env).AUDIT_CODE_HOST_CAN_DISPATCH) ?? false;
105
+ }
90
106
  function toBase64Url(value) {
91
107
  return Buffer.from(value, "utf8").toString("base64url");
92
108
  }
@@ -112,6 +128,21 @@ function quoteCommandArg(value) {
112
128
  function renderCommand(argv) {
113
129
  return argv.map((item) => quoteCommandArg(item)).join(" ");
114
130
  }
131
+ function summarizeLaunchExit(result) {
132
+ if (result.accepted !== false && !result.error) {
133
+ return null;
134
+ }
135
+ const parts = [
136
+ result.signal
137
+ ? `signal ${result.signal}`
138
+ : `exit code ${result.exitCode ?? "unknown"}`,
139
+ result.command ? `command: ${result.command}` : null,
140
+ result.stdoutPath ? `stdout: ${result.stdoutPath}` : null,
141
+ result.stderrPath ? `stderr: ${result.stderrPath}` : null,
142
+ result.error ?? null,
143
+ ].filter((part) => Boolean(part));
144
+ return parts.join("; ");
145
+ }
115
146
  function taskResultPath(taskResultsDir, taskId) {
116
147
  return join(taskResultsDir, artifactNameForId(taskId, "json"));
117
148
  }
@@ -520,50 +551,6 @@ function mergeAndIngestCommand(artifactsDir, runId) {
520
551
  artifactsDir,
521
552
  ]);
522
553
  }
523
- function renderCapabilityCheckPrompt(params) {
524
- const yesCommand = nextStepCommand(params.root, params.artifactsDir, [
525
- "--host-can-dispatch-subagents",
526
- "true",
527
- ]);
528
- const noCommand = nextStepCommand(params.root, params.artifactsDir, [
529
- "--host-can-dispatch-subagents",
530
- "false",
531
- ]);
532
- return [
533
- "# audit-code capability check",
534
- "",
535
- "Decide one thing from the active toolset: does this host expose a callable subagent/delegation tool for source-code review, such as `task`, Agent, or an equivalent built-in subagent call?",
536
- "",
537
- "Do not run shell commands to answer this. Do not inspect packet prompts, schemas, or backend command catalogs.",
538
- "",
539
- "**If auditor MCP tools are available** (preferred — no shell required):",
540
- "",
541
- "Call `auditor_report_capability` with:",
542
- "- `can_dispatch_subagents: true` if the `task` tool or equivalent subagent dispatch is available",
543
- "- `can_dispatch_subagents: false` if not",
544
- "- Optionally `can_restrict_subagent_tools: true` and/or `can_select_subagent_model: true`",
545
- "- If the host documents or exposes a hard cap on simultaneously active subagents, include `max_active_subagents`.",
546
- "",
547
- "Read the `prompt_content` field in the tool response and follow it.",
548
- "",
549
- "**Fallback — if auditor MCP tools are not available:**",
550
- "",
551
- "If callable subagents are available, run:",
552
- "",
553
- ` ${yesCommand}`,
554
- "",
555
- "If callable subagents are not available, run:",
556
- "",
557
- ` ${noCommand}`,
558
- "",
559
- "If the host can also restrict tools per subagent or select models per subagent, add the matching `--host-can-restrict-subagent-tools true` or `--host-can-select-subagent-model true` flags to the same command. Omit those flags when unsure.",
560
- "",
561
- "If the host has a known active-subagent ceiling, add `--host-max-active-subagents <n>` to the same command. For Codex Desktop, use 6.",
562
- "",
563
- "After the command writes the next step, read and follow only its `prompt_path`.",
564
- "",
565
- ].join("\n");
566
- }
567
554
  function renderDispatchReviewPrompt(params) {
568
555
  const mergeCommand = mergeAndIngestCommand(params.artifactsDir, params.activeReviewRun.run_id);
569
556
  const continueCommand = nextStepCommand(params.root, params.artifactsDir);
@@ -573,32 +560,21 @@ function renderDispatchReviewPrompt(params) {
573
560
  const toolsLine = params.hostCanRestrictSubagentTools
574
561
  ? "Restrict review subagents to read/search plus the packet submit command named in their prompt. Do not give them source edit/write tools."
575
562
  : "Do not ask the user about per-subagent tool restrictions; this host did not report a callable restriction facility.";
576
- const runId = params.activeReviewRun.run_id;
577
563
  const dispatchDataLines = params.dispatchQuotaPath
578
564
  ? [
579
- "**If auditor MCP tools are available** (preferred):",
565
+ "Read these generated files unless the current tool response already included equivalent `dispatch_plan_entries` and `dispatch_quota` fields:",
580
566
  "",
581
- "The dispatch plan entries are in the `dispatch_plan_entries` field of the tool response that returned this step. The wave schedule is in the `dispatch_quota` field.",
567
+ ` Dispatch plan: ${params.dispatchPlanPath}`,
568
+ ` Dispatch quota: ${params.dispatchQuotaPath}`,
582
569
  "",
583
- "Use the `wave_size` from `dispatch_quota`. If `cooldown_until` is non-null, wait until that timestamp before starting the first wave.",
570
+ "Use the `wave_size` from the quota data. If `cooldown_until` is non-null, wait until that timestamp before starting the first wave.",
584
571
  "",
585
- "`dispatch_quota.host_concurrency_limit` records any detected hard host cap that contributed to `wave_size`.",
572
+ "`host_concurrency_limit` records any detected hard host cap that contributed to `wave_size`.",
586
573
  "",
587
574
  "For each wave: use the `task` tool (or equivalent subagent dispatch) to launch up to `wave_size` subagents in parallel (one per entry), wait for all to finish, then start the next wave.",
588
- "",
589
- "**Fallback — if auditor MCP tools are not available:** Read both of these files:",
590
- "",
591
- ` Dispatch plan: ${params.dispatchPlanPath}`,
592
- ` Dispatch quota: ${params.dispatchQuotaPath}`,
593
- "",
594
- "Apply the same wave logic from the quota file.",
595
575
  ]
596
576
  : [
597
- "**If auditor MCP tools are available** (preferred):",
598
- "",
599
- "The dispatch plan entries are in the `dispatch_plan_entries` field of the tool response that returned this step.",
600
- "",
601
- "**Fallback — if auditor MCP tools are not available:** Read this dispatch plan JSON:",
577
+ "Read this generated dispatch plan unless the current tool response already included equivalent `dispatch_plan_entries`:",
602
578
  "",
603
579
  ` ${params.dispatchPlanPath}`,
604
580
  "",
@@ -622,9 +598,7 @@ function renderDispatchReviewPrompt(params) {
622
598
  "",
623
599
  "**After all waves complete:**",
624
600
  "",
625
- "If auditor MCP tools are available, call `auditor_merge_and_ingest` with `{ run_id: \"" + runId + "\" }`, then call `auditor_continue_audit` and follow the `prompt_content` in the response.",
626
- "",
627
- "Fallback — if auditor MCP tools are not available, run exactly:",
601
+ "Run exactly:",
628
602
  "",
629
603
  ` ${mergeCommand}`,
630
604
  "",
@@ -1170,6 +1144,10 @@ async function cmdNextStep(argv) {
1170
1144
  console.log(JSON.stringify(step, null, 2));
1171
1145
  return;
1172
1146
  }
1147
+ const hostCanDispatch = resolveHostDispatchCapability({
1148
+ explicit: hostCanDispatchSubagents,
1149
+ sessionConfig,
1150
+ });
1173
1151
  const result = await runDeterministicForNextStep({
1174
1152
  root,
1175
1153
  artifactsDir,
@@ -1211,35 +1189,7 @@ async function cmdNextStep(argv) {
1211
1189
  console.log(JSON.stringify(step, null, 2));
1212
1190
  return;
1213
1191
  }
1214
- if (hostCanDispatchSubagents === undefined) {
1215
- const yesCommand = nextStepCommand(root, artifactsDir, [
1216
- "--host-can-dispatch-subagents",
1217
- "true",
1218
- ]);
1219
- const noCommand = nextStepCommand(root, artifactsDir, [
1220
- "--host-can-dispatch-subagents",
1221
- "false",
1222
- ]);
1223
- const step = await writeCurrentStep({
1224
- artifactsDir,
1225
- stepKind: "capability_check",
1226
- status: "ready",
1227
- runId: result.activeReviewRun.run_id,
1228
- allowedCommands: [yesCommand, noCommand],
1229
- stopCondition: "Run exactly one next-step command with an explicit host dispatch capability.",
1230
- repoRoot: root,
1231
- artifactPaths: {
1232
- active_review_task: result.activeReviewRun.task_path,
1233
- active_review_prompt: result.activeReviewRun.prompt_path,
1234
- pending_audit_tasks: result.activeReviewRun.pending_audit_tasks_path ?? null,
1235
- single_task_prompt: join(artifactsDir, "dispatch", "current-single-task-prompt.md"),
1236
- },
1237
- prompt: renderCapabilityCheckPrompt({ root, artifactsDir }),
1238
- });
1239
- console.log(JSON.stringify(step, null, 2));
1240
- return;
1241
- }
1242
- if (!hostCanDispatchSubagents) {
1192
+ if (!hostCanDispatch) {
1243
1193
  const singleTaskPromptPath = join(artifactsDir, "dispatch", "current-single-task-prompt.md");
1244
1194
  const workerCommand = renderCommand(result.activeReviewRun.worker_command);
1245
1195
  const step = await writeCurrentStep({
@@ -1284,7 +1234,7 @@ async function cmdNextStep(argv) {
1284
1234
  mergeCommand,
1285
1235
  continueCommand,
1286
1236
  ],
1287
- stopCondition: "Dispatch every packet, call auditor_merge_and_ingest once, then call auditor_continue_audit.",
1237
+ stopCondition: "Dispatch every packet, run merge-and-ingest once, then run next-step.",
1288
1238
  repoRoot: root,
1289
1239
  artifactPaths: {
1290
1240
  dispatch_plan: dispatch.dispatch_plan_path,
@@ -1548,6 +1498,12 @@ async function cmdRunToCompletion(argv) {
1548
1498
  ? outcome.reason.message
1549
1499
  : String(outcome.reason));
1550
1500
  }
1501
+ else if (outcome?.status === "fulfilled") {
1502
+ const launchExitSummary = summarizeLaunchExit(outcome.value);
1503
+ if (launchExitSummary) {
1504
+ launchErrorsByRunId.set(workerSlots[index].runId, launchExitSummary);
1505
+ }
1506
+ }
1551
1507
  }
1552
1508
  // Result ingestion is intentionally sequential even though agent launch
1553
1509
  // was parallel. Writing to coverage_matrix.json is not atomic, so
@@ -1856,8 +1812,9 @@ async function cmdRunToCompletion(argv) {
1856
1812
  }
1857
1813
  const startedAt = new Date().toISOString();
1858
1814
  let workerResult;
1815
+ let launchResult = null;
1859
1816
  try {
1860
- await provider.launch({
1817
+ launchResult = await provider.launch({
1861
1818
  repoRoot: root,
1862
1819
  runId,
1863
1820
  obligationId,
@@ -1870,9 +1827,12 @@ async function cmdRunToCompletion(argv) {
1870
1827
  timeoutMs,
1871
1828
  });
1872
1829
  const candidate = await readJsonFile(paths.resultPath);
1873
- workerResult = isWorkerResult(candidate)
1874
- ? candidate
1875
- : {
1830
+ if (isWorkerResult(candidate)) {
1831
+ workerResult = candidate;
1832
+ }
1833
+ else {
1834
+ const launchExitSummary = summarizeLaunchExit(launchResult);
1835
+ workerResult = {
1876
1836
  contract_version: WORKER_RESULT_CONTRACT_VERSION,
1877
1837
  run_id: runId,
1878
1838
  obligation_id: obligationId,
@@ -1880,13 +1840,17 @@ async function cmdRunToCompletion(argv) {
1880
1840
  progress_made: false,
1881
1841
  selected_executor: preferredExecutor,
1882
1842
  artifacts_written: [],
1883
- summary: "Worker did not emit a valid worker result.",
1843
+ summary: launchExitSummary
1844
+ ? `Worker did not emit a valid worker result after provider exit: ${launchExitSummary}`
1845
+ : "Worker did not emit a valid worker result.",
1884
1846
  next_likely_step: decision.selected_obligation,
1885
1847
  errors: ["Invalid worker result contract."],
1886
1848
  };
1849
+ }
1887
1850
  }
1888
1851
  catch (error) {
1889
1852
  const message = error instanceof Error ? error.message : String(error);
1853
+ const launchExitSummary = launchResult && summarizeLaunchExit(launchResult);
1890
1854
  workerResult = {
1891
1855
  contract_version: WORKER_RESULT_CONTRACT_VERSION,
1892
1856
  run_id: runId,
@@ -1895,9 +1859,9 @@ async function cmdRunToCompletion(argv) {
1895
1859
  progress_made: false,
1896
1860
  selected_executor: preferredExecutor,
1897
1861
  artifacts_written: [],
1898
- summary: `Worker launch failed for ${preferredExecutor}: ${message}`,
1862
+ summary: `Worker launch failed for ${preferredExecutor}: ${launchExitSummary ?? message}`,
1899
1863
  next_likely_step: decision.selected_obligation,
1900
- errors: [message],
1864
+ errors: launchExitSummary ? [message, launchExitSummary] : [message],
1901
1865
  };
1902
1866
  await persistWorkerRunArtifacts(paths, workerResult, "provider-launch");
1903
1867
  }
@@ -1,3 +1,4 @@
1
+ const MAX_RISK_SCORE = 10;
1
2
  export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerResults) {
2
3
  const flowMap = new Map();
3
4
  for (const flow of criticalFlows?.flows ?? []) {
@@ -30,12 +31,13 @@ export function buildRiskRegister(unitManifest, criticalFlows, externalAnalyzerR
30
31
  if (externalHits > 0) {
31
32
  signals.push("external_analyzer_signal");
32
33
  }
34
+ const riskScore = (unit.risk_score ?? 0) +
35
+ flowHits +
36
+ externalHits +
37
+ (signals.includes("path_level_stateful_behavior") ? 1 : 0);
33
38
  return {
34
39
  unit_id: unit.unit_id,
35
- risk_score: (unit.risk_score ?? 0) +
36
- flowHits +
37
- externalHits +
38
- (signals.includes("path_level_stateful_behavior") ? 1 : 0),
40
+ risk_score: Math.min(MAX_RISK_SCORE, riskScore),
39
41
  signals,
40
42
  notes: [
41
43
  "Initial heuristic risk scoring.",
@@ -26,6 +26,7 @@ type ArtifactPayloadMap = {
26
26
  runtime_validation_tasks: RuntimeValidationTaskManifest;
27
27
  runtime_validation_report: RuntimeValidationReport;
28
28
  external_analyzer_results: ExternalAnalyzerResults;
29
+ syntax_resolution_status: unknown;
29
30
  audit_results: AuditResult[];
30
31
  audit_tasks: AuditTask[];
31
32
  audit_plan_metrics: AuditPlanMetrics;
@@ -63,6 +64,7 @@ export declare const ARTIFACT_DEFINITIONS: {
63
64
  readonly runtime_validation_tasks: ArtifactDefinition<"runtime_validation_tasks">;
64
65
  readonly runtime_validation_report: ArtifactDefinition<"runtime_validation_report">;
65
66
  readonly external_analyzer_results: ArtifactDefinition<"external_analyzer_results">;
67
+ readonly syntax_resolution_status: ArtifactDefinition<"syntax_resolution_status">;
66
68
  readonly audit_results: ArtifactDefinition<"audit_results">;
67
69
  readonly audit_tasks: ArtifactDefinition<"audit_tasks">;
68
70
  readonly audit_plan_metrics: ArtifactDefinition<"audit_plan_metrics">;
@@ -40,6 +40,7 @@ export const ARTIFACT_DEFINITIONS = {
40
40
  runtime_validation_tasks: jsonArtifact("runtime_validation_tasks.json", "execution"),
41
41
  runtime_validation_report: jsonArtifact("runtime_validation_report.json", "execution"),
42
42
  external_analyzer_results: jsonArtifact("external_analyzer_results.json", "execution"),
43
+ syntax_resolution_status: jsonArtifact("syntax_resolution_status.json", "execution"),
43
44
  audit_results: ndjsonArtifact("audit_results.jsonl", "execution"),
44
45
  audit_tasks: jsonArtifact("audit_tasks.json", "execution"),
45
46
  audit_plan_metrics: jsonArtifact("audit_plan_metrics.json", "execution"),
@@ -1,2 +1,3 @@
1
1
  import type { ToolingManifest } from "../types/toolingManifest.js";
2
+ export declare const TOOLING_INPUTS: readonly ["audit-code.mjs", "audit-code-wrapper-lib.mjs", "package.json", "dist", "schemas", "skills/audit-code"];
2
3
  export declare function buildToolingManifest(): Promise<ToolingManifest>;
@@ -3,7 +3,7 @@ import { readdir, readFile, stat } from "node:fs/promises";
3
3
  import { dirname, join, relative, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
6
- const TOOLING_INPUTS = [
6
+ export const TOOLING_INPUTS = [
7
7
  "audit-code.mjs",
8
8
  "audit-code-wrapper-lib.mjs",
9
9
  "package.json",
@@ -1 +1,72 @@
1
+ interface ServerOptions {
2
+ root: string;
3
+ artifactsDir: string;
4
+ }
5
+ interface JsonRpcRequest {
6
+ jsonrpc?: string;
7
+ id?: string | number | null;
8
+ method?: string;
9
+ params?: Record<string, unknown>;
10
+ }
11
+ interface JsonRpcResponse {
12
+ jsonrpc: "2.0";
13
+ id: string | number | null;
14
+ result?: unknown;
15
+ error?: {
16
+ code: number;
17
+ message: string;
18
+ data?: unknown;
19
+ };
20
+ }
21
+ interface ToolCallContext {
22
+ root: string;
23
+ artifactsDir: string;
24
+ }
25
+ export declare function parseContentLength(headerBlock: string): number;
26
+ interface ResourceRegistryEntry {
27
+ uri: string;
28
+ name: string;
29
+ description: string;
30
+ mimeType: string;
31
+ read: (context: ToolCallContext) => Promise<{
32
+ mimeType: string;
33
+ text: string;
34
+ }>;
35
+ }
36
+ export declare const resourceRegistry: ResourceRegistryEntry[];
37
+ interface PromptRegistryEntry {
38
+ name: string;
39
+ description: string;
40
+ arguments: Array<{
41
+ name: string;
42
+ required?: boolean;
43
+ description: string;
44
+ }>;
45
+ render: (args: Record<string, unknown> | undefined) => string;
46
+ }
47
+ export declare const promptRegistry: PromptRegistryEntry[];
48
+ /**
49
+ * Extract zero or more complete Content-Length framed messages from a buffer.
50
+ * Returns an array of parsed body strings and the remaining unconsumed buffer.
51
+ * On framing errors, emits a framing error response via `emit` and resets the buffer.
52
+ */
53
+ export declare function extractFrames(buffer: Buffer, emit: (response: JsonRpcResponse) => void): {
54
+ bodies: string[];
55
+ remaining: Buffer<ArrayBufferLike>;
56
+ };
57
+ interface DispatchContext {
58
+ version: string;
59
+ defaults: ServerOptions;
60
+ shutdownRequested: boolean;
61
+ }
62
+ /**
63
+ * Dispatch a single JSON-RPC request and return the response(s) to send,
64
+ * plus updated shutdown state.
65
+ */
66
+ export declare function dispatchRequest(request: JsonRpcRequest, ctx: DispatchContext): Promise<{
67
+ responses: JsonRpcResponse[];
68
+ shutdownRequested: boolean;
69
+ exit?: number;
70
+ }>;
1
71
  export declare function runAuditCodeMcpServer(argv: string[]): Promise<void>;
72
+ export {};