auditor-lambda 0.2.6 → 0.2.9

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 (125) hide show
  1. package/README.md +29 -7
  2. package/audit-code-wrapper-lib.mjs +1605 -330
  3. package/dist/adapters/eslint.js +9 -5
  4. package/dist/cli.d.ts +42 -1
  5. package/dist/cli.js +192 -80
  6. package/dist/coverage.d.ts +2 -2
  7. package/dist/coverage.js +5 -5
  8. package/dist/extractors/bucketing.d.ts +4 -0
  9. package/dist/extractors/bucketing.js +6 -2
  10. package/dist/extractors/disposition.d.ts +4 -0
  11. package/dist/extractors/disposition.js +15 -2
  12. package/dist/extractors/fileInventory.js +24 -28
  13. package/dist/extractors/flows.d.ts +5 -0
  14. package/dist/extractors/flows.js +25 -39
  15. package/dist/extractors/pathPatterns.d.ts +13 -3
  16. package/dist/extractors/pathPatterns.js +116 -53
  17. package/dist/extractors/risk.js +7 -1
  18. package/dist/extractors/surfaces.d.ts +4 -0
  19. package/dist/extractors/surfaces.js +11 -11
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.js +2 -1
  22. package/dist/io/artifacts.d.ts +59 -44
  23. package/dist/io/artifacts.js +80 -120
  24. package/dist/io/json.d.ts +2 -0
  25. package/dist/io/json.js +65 -19
  26. package/dist/io/runArtifacts.d.ts +2 -1
  27. package/dist/io/runArtifacts.js +44 -7
  28. package/dist/mcp/server.d.ts +1 -0
  29. package/dist/mcp/server.js +579 -0
  30. package/dist/orchestrator/advance.js +84 -56
  31. package/dist/orchestrator/dependencyMap.js +9 -13
  32. package/dist/orchestrator/executors.js +7 -2
  33. package/dist/orchestrator/flowCoverage.js +11 -5
  34. package/dist/orchestrator/flowPlanning.d.ts +7 -2
  35. package/dist/orchestrator/flowPlanning.js +46 -21
  36. package/dist/orchestrator/flowRequeue.js +29 -9
  37. package/dist/orchestrator/internalExecutors.d.ts +2 -1
  38. package/dist/orchestrator/internalExecutors.js +130 -69
  39. package/dist/orchestrator/planning.js +25 -3
  40. package/dist/orchestrator/requeue.js +20 -5
  41. package/dist/orchestrator/resultIngestion.js +5 -6
  42. package/dist/orchestrator/runtimeValidation.d.ts +7 -2
  43. package/dist/orchestrator/runtimeValidation.js +61 -49
  44. package/dist/orchestrator/runtimeValidationUpdate.js +2 -4
  45. package/dist/orchestrator/state.js +18 -13
  46. package/dist/orchestrator/taskBuilder.d.ts +4 -2
  47. package/dist/orchestrator/taskBuilder.js +153 -52
  48. package/dist/orchestrator/trivialAudit.js +8 -5
  49. package/dist/orchestrator/unitBuilder.d.ts +3 -1
  50. package/dist/orchestrator/unitBuilder.js +24 -16
  51. package/dist/prompts/renderWorkerPrompt.d.ts +1 -1
  52. package/dist/prompts/renderWorkerPrompt.js +19 -10
  53. package/dist/providers/claudeCodeProvider.d.ts +4 -1
  54. package/dist/providers/claudeCodeProvider.js +8 -5
  55. package/dist/providers/localSubprocessProvider.d.ts +4 -0
  56. package/dist/providers/localSubprocessProvider.js +7 -2
  57. package/dist/providers/spawnLoggedCommand.d.ts +9 -1
  58. package/dist/providers/spawnLoggedCommand.js +77 -29
  59. package/dist/reporting/mergeFindings.js +0 -11
  60. package/dist/reporting/synthesis.d.ts +26 -21
  61. package/dist/reporting/synthesis.js +97 -61
  62. package/dist/reporting/workBlocks.d.ts +12 -3
  63. package/dist/reporting/workBlocks.js +124 -70
  64. package/dist/supervisor/operatorHandoff.js +48 -18
  65. package/dist/supervisor/runLedger.d.ts +1 -1
  66. package/dist/supervisor/runLedger.js +112 -5
  67. package/dist/supervisor/sessionConfig.js +10 -10
  68. package/dist/types/externalAnalyzer.d.ts +3 -0
  69. package/dist/types/flowCoverage.d.ts +5 -1
  70. package/dist/types/flowCoverage.js +5 -1
  71. package/dist/types/flows.d.ts +6 -0
  72. package/dist/types/flows.js +1 -1
  73. package/dist/types/runLedger.d.ts +5 -1
  74. package/dist/types/runLedger.js +6 -1
  75. package/dist/types/runtimeValidation.d.ts +13 -3
  76. package/dist/types/runtimeValidation.js +16 -1
  77. package/dist/types/sessionConfig.d.ts +15 -2
  78. package/dist/types/sessionConfig.js +15 -1
  79. package/dist/types/surfaces.d.ts +4 -1
  80. package/dist/types/surfaces.js +1 -1
  81. package/dist/types/workerSession.d.ts +9 -0
  82. package/dist/types/workerSession.js +5 -1
  83. package/dist/types.d.ts +4 -7
  84. package/dist/validation/artifacts.d.ts +1 -1
  85. package/dist/validation/artifacts.js +33 -20
  86. package/dist/validation/auditResults.d.ts +2 -2
  87. package/dist/validation/auditResults.js +71 -114
  88. package/dist/validation/basic.d.ts +9 -1
  89. package/dist/validation/basic.js +40 -3
  90. package/dist/validation/sessionConfig.d.ts +4 -2
  91. package/dist/validation/sessionConfig.js +62 -15
  92. package/docs/agent-integrations.md +67 -38
  93. package/docs/artifacts.md +16 -56
  94. package/docs/bootstrap-install.md +60 -30
  95. package/docs/contract.md +22 -205
  96. package/docs/next-steps.md +76 -44
  97. package/docs/packaging.md +27 -3
  98. package/docs/product-direction.md +22 -0
  99. package/docs/production-launch-bar.md +4 -2
  100. package/docs/production-readiness.md +9 -5
  101. package/docs/releasing.md +98 -0
  102. package/docs/remediation-baseline.md +75 -0
  103. package/docs/run-flow.md +23 -11
  104. package/docs/session-config.md +50 -5
  105. package/docs/supervisor.md +7 -0
  106. package/docs/workflow-refactor-brief.md +177 -0
  107. package/package.json +4 -1
  108. package/schemas/audit_result.schema.json +8 -7
  109. package/schemas/audit_task.schema.json +3 -1
  110. package/schemas/coverage_matrix.schema.json +3 -3
  111. package/schemas/critical_flows.schema.json +6 -2
  112. package/schemas/file_disposition.schema.json +2 -2
  113. package/schemas/finding.schema.json +9 -4
  114. package/schemas/flow_coverage.schema.json +2 -2
  115. package/schemas/repo_manifest.schema.json +4 -4
  116. package/schemas/risk_register.schema.json +2 -2
  117. package/schemas/runtime_validation_report.schema.json +3 -3
  118. package/schemas/runtime_validation_tasks.schema.json +8 -2
  119. package/schemas/surface_manifest.schema.json +6 -3
  120. package/schemas/unit_manifest.schema.json +3 -2
  121. package/skills/audit-code/SKILL.md +16 -2
  122. package/skills/audit-code/audit-code.prompt.md +5 -8
  123. package/schemas/merged_findings.schema.json +0 -19
  124. package/schemas/root_cause_clusters.schema.json +0 -28
  125. package/schemas/synthesis_report.schema.json +0 -61
@@ -3,22 +3,52 @@ import { join } from "node:path";
3
3
  import { writeJsonFile } from "../io/json.js";
4
4
  import { LOCAL_SUBPROCESS_PROVIDER_NAME } from "../providers/constants.js";
5
5
  export const CONFIG_ERROR_BLOCKER_PREFIX = "config-error:";
6
- function quoteShellPath(path) {
7
- return `"${path.replace(/"/g, '\\"')}"`;
6
+ const INCOMING_DIRNAME = "incoming";
7
+ const OPERATOR_HANDOFF_JSON_FILENAME = "operator-handoff.json";
8
+ const OPERATOR_HANDOFF_MARKDOWN_FILENAME = "operator-handoff.md";
9
+ const SESSION_CONFIG_FILENAME = "session-config.json";
10
+ const RUN_LEDGER_FILENAME = "run-ledger.json";
11
+ const AUDIT_TASKS_FILENAME = "audit_tasks.json";
12
+ const RUNTIME_VALIDATION_TASKS_FILENAME = "runtime_validation_tasks.json";
13
+ const BLOCKED_STATUS = "blocked";
14
+ const COMPLETE_STATUS = "complete";
15
+ const NOT_STARTED_STATUS = "not_started";
16
+ const NON_PENDING_OBLIGATION_STATES = new Set([
17
+ "present",
18
+ "satisfied",
19
+ ]);
20
+ const INTERACTIVE_PROVIDER_OPTIONS = [
21
+ "auto",
22
+ "claude-code",
23
+ "opencode",
24
+ "subprocess-template",
25
+ "vscode-task",
26
+ ];
27
+ function quoteShellPath(filePath) {
28
+ // The handoff renders a single shell argument, so the snippet only needs
29
+ // double-quote wrapping plus escaping embedded double quotes.
30
+ return `"${filePath.replace(/"/g, '\\"')}"`;
8
31
  }
9
32
  function buildPendingObligations(state) {
10
33
  return state.obligations
11
- .filter((item) => item.state !== "satisfied" && item.state !== "present")
34
+ .filter((item) => !NON_PENDING_OBLIGATION_STATES.has(item.state))
12
35
  .map((item) => item.id);
13
36
  }
37
+ function formatQuotedList(values) {
38
+ if (values.length === 1) {
39
+ return `"${values[0]}"`;
40
+ }
41
+ const head = values.slice(0, -1).map((value) => `"${value}"`).join(", ");
42
+ return `${head}, or "${values[values.length - 1]}"`;
43
+ }
14
44
  function buildSummary(status, providerName, fallbackSummary) {
15
- if (status === "complete") {
45
+ if (status === COMPLETE_STATUS) {
16
46
  return "No operator handoff is required. All known obligations are currently satisfied.";
17
47
  }
18
- if (status === "blocked") {
48
+ if (status === BLOCKED_STATUS) {
19
49
  return fallbackSummary;
20
50
  }
21
- if (status === "not_started") {
51
+ if (status === NOT_STARTED_STATUS) {
22
52
  return "The artifact bundle is not initialized yet. Run the wrapper from the repository root to create the initial audit artifacts.";
23
53
  }
24
54
  return providerName
@@ -26,10 +56,10 @@ function buildSummary(status, providerName, fallbackSummary) {
26
56
  : "Automatic work can continue. Re-run the same wrapper or inspect the listed artifacts if you need operator context.";
27
57
  }
28
58
  function buildSuggestedInputs(artifactsDir, status, isConfigError) {
29
- if (status !== "blocked" || isConfigError) {
59
+ if (status !== BLOCKED_STATUS || isConfigError) {
30
60
  return [];
31
61
  }
32
- const incomingDir = join(artifactsDir, "incoming");
62
+ const incomingDir = join(artifactsDir, INCOMING_DIRNAME);
33
63
  return [
34
64
  {
35
65
  flag: "--results",
@@ -49,20 +79,20 @@ function buildSuggestedInputs(artifactsDir, status, isConfigError) {
49
79
  ];
50
80
  }
51
81
  function buildSuggestedCommands(suggestedInputs, status) {
52
- if (status !== "blocked") {
82
+ if (status !== BLOCKED_STATUS) {
53
83
  return [];
54
84
  }
55
85
  return suggestedInputs.map((item) => `audit-code ${item.flag} ${quoteShellPath(item.suggested_path)}`);
56
86
  }
57
87
  function buildInteractiveProviderHint(status, providerName, sessionConfigPath, isConfigError) {
58
- if (status !== "blocked") {
88
+ if (status !== BLOCKED_STATUS) {
59
89
  return null;
60
90
  }
61
91
  if (isConfigError) {
62
92
  return `A project configuration issue is blocking the audit. Verify that --root points to the repository root containing a project file (package.json, go.mod, etc.), then run audit-code again.`;
63
93
  }
64
94
  const providerLabel = providerName ?? LOCAL_SUBPROCESS_PROVIDER_NAME;
65
- return `Current provider is ${providerLabel}. If you want the backend to continue through an interactive provider instead of importing results manually, set "provider" in ${sessionConfigPath} to "auto", "claude-code", "opencode", "subprocess-template", or "vscode-task", then run audit-code again from the repository root.`;
95
+ return `Current backend worker provider is ${providerLabel}. Remaining semantic review belongs to the active conversation agent by default. If you intentionally want the backend to continue through a compatibility bridge instead, configure ${sessionConfigPath} for ${formatQuotedList(INTERACTIVE_PROVIDER_OPTIONS)} and re-run audit-code with an explicit --provider value from the repository root.`;
66
96
  }
67
97
  function renderMarkdown(handoff) {
68
98
  const lines = [
@@ -115,18 +145,18 @@ function renderMarkdown(handoff) {
115
145
  }
116
146
  export function buildAuditCodeHandoff(params) {
117
147
  const isConfigError = params.isConfigError ?? false;
118
- const incomingDir = join(params.artifactsDir, "incoming");
148
+ const incomingDir = join(params.artifactsDir, INCOMING_DIRNAME);
119
149
  const artifactPaths = {
120
150
  incoming_dir: incomingDir,
121
- operator_handoff_json: join(params.artifactsDir, "operator-handoff.json"),
122
- operator_handoff_markdown: join(params.artifactsDir, "operator-handoff.md"),
123
- session_config: join(params.artifactsDir, "session-config.json"),
124
- run_ledger: join(params.artifactsDir, "run-ledger.json"),
151
+ operator_handoff_json: join(params.artifactsDir, OPERATOR_HANDOFF_JSON_FILENAME),
152
+ operator_handoff_markdown: join(params.artifactsDir, OPERATOR_HANDOFF_MARKDOWN_FILENAME),
153
+ session_config: join(params.artifactsDir, SESSION_CONFIG_FILENAME),
154
+ run_ledger: join(params.artifactsDir, RUN_LEDGER_FILENAME),
125
155
  audit_tasks: params.bundle.audit_tasks
126
- ? join(params.artifactsDir, "audit_tasks.json")
156
+ ? join(params.artifactsDir, AUDIT_TASKS_FILENAME)
127
157
  : null,
128
158
  runtime_validation_tasks: params.bundle.runtime_validation_tasks
129
- ? join(params.artifactsDir, "runtime_validation_tasks.json")
159
+ ? join(params.artifactsDir, RUNTIME_VALIDATION_TASKS_FILENAME)
130
160
  : null,
131
161
  };
132
162
  const suggestedInputs = buildSuggestedInputs(params.artifactsDir, params.state.status, isConfigError);
@@ -1,3 +1,3 @@
1
- import type { RunLedger, RunLedgerEntry } from "../types/runLedger.js";
1
+ import { type RunLedger, type RunLedgerEntry } from "../types/runLedger.js";
2
2
  export declare function loadRunLedger(artifactsDir: string): Promise<RunLedger>;
3
3
  export declare function appendRunLedgerEntry(artifactsDir: string, entry: RunLedgerEntry): Promise<void>;
@@ -1,20 +1,127 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdir, open, rename, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { RUN_LEDGER_STATUSES, } from "../types/runLedger.js";
1
5
  import { isFileMissingError, readJsonFile, writeJsonFile } from "../io/json.js";
6
+ const RUN_LEDGER_FILENAME = "run-ledger.json";
7
+ const RUN_LEDGER_LOCK_FILENAME = "run-ledger.lock";
8
+ const LOCK_RETRY_DELAY_MS = 20;
9
+ const LOCK_RETRY_LIMIT = 100;
10
+ const VALID_RUN_LEDGER_STATUSES = new Set(RUN_LEDGER_STATUSES);
2
11
  function ledgerPath(artifactsDir) {
3
- return `${artifactsDir}/run-ledger.json`;
12
+ return join(artifactsDir, RUN_LEDGER_FILENAME);
13
+ }
14
+ function ledgerLockPath(artifactsDir) {
15
+ return join(artifactsDir, RUN_LEDGER_LOCK_FILENAME);
16
+ }
17
+ function buildTempLedgerPath(artifactsDir) {
18
+ return join(artifactsDir, `${RUN_LEDGER_FILENAME}.${process.pid}.${randomUUID()}.tmp`);
19
+ }
20
+ function isRecord(value) {
21
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22
+ }
23
+ function isFileExistsError(error) {
24
+ return (typeof error === "object" &&
25
+ error !== null &&
26
+ "code" in error &&
27
+ error.code === "EEXIST");
28
+ }
29
+ function assertRunLedgerEntry(value, fieldPath) {
30
+ if (!isRecord(value)) {
31
+ throw new Error(`Invalid run ledger in ${fieldPath}: expected an object.`);
32
+ }
33
+ const requireString = (field) => {
34
+ const entry = value[field];
35
+ if (typeof entry !== "string" || entry.trim().length === 0) {
36
+ throw new Error(`Invalid run ledger in ${fieldPath}.${field}: expected a non-empty string.`);
37
+ }
38
+ return entry;
39
+ };
40
+ const requireNullableString = (field) => {
41
+ const entry = value[field];
42
+ if (entry === null) {
43
+ return null;
44
+ }
45
+ if (typeof entry !== "string" || entry.trim().length === 0) {
46
+ throw new Error(`Invalid run ledger in ${fieldPath}.${field}: expected a string or null.`);
47
+ }
48
+ return entry;
49
+ };
50
+ const status = value.status;
51
+ if (typeof status !== "string" ||
52
+ !VALID_RUN_LEDGER_STATUSES.has(status)) {
53
+ throw new Error(`Invalid run ledger in ${fieldPath}.status: expected one of ${Array.from(VALID_RUN_LEDGER_STATUSES).join(", ")}.`);
54
+ }
55
+ return {
56
+ run_id: requireString("run_id"),
57
+ provider: requireString("provider"),
58
+ obligation_id: requireNullableString("obligation_id"),
59
+ selected_executor: requireNullableString("selected_executor"),
60
+ status: status,
61
+ started_at: requireString("started_at"),
62
+ ended_at: requireString("ended_at"),
63
+ result_path: requireString("result_path"),
64
+ };
65
+ }
66
+ function parseRunLedger(value, path) {
67
+ if (!isRecord(value)) {
68
+ throw new Error(`Invalid run ledger in ${path}: expected an object.`);
69
+ }
70
+ if (!Array.isArray(value.runs)) {
71
+ throw new Error(`Invalid run ledger in ${path}: expected runs to be an array.`);
72
+ }
73
+ return {
74
+ runs: value.runs.map((entry, index) => assertRunLedgerEntry(entry, `${path}.runs[${index}]`)),
75
+ };
76
+ }
77
+ function sleep(ms) {
78
+ return new Promise((resolve) => setTimeout(resolve, ms));
79
+ }
80
+ async function acquireLedgerLock(artifactsDir) {
81
+ const lockPath = ledgerLockPath(artifactsDir);
82
+ await mkdir(artifactsDir, { recursive: true });
83
+ for (let attempt = 0; attempt < LOCK_RETRY_LIMIT; attempt += 1) {
84
+ try {
85
+ return await open(lockPath, "wx");
86
+ }
87
+ catch (error) {
88
+ if (!isFileExistsError(error)) {
89
+ throw error;
90
+ }
91
+ if (attempt === LOCK_RETRY_LIMIT - 1) {
92
+ throw new Error(`Timed out waiting to update ${ledgerPath(artifactsDir)} because ${lockPath} is locked.`);
93
+ }
94
+ await sleep(LOCK_RETRY_DELAY_MS);
95
+ }
96
+ }
97
+ throw new Error(`Failed to acquire lock for ${ledgerPath(artifactsDir)}.`);
4
98
  }
5
99
  export async function loadRunLedger(artifactsDir) {
100
+ const path = ledgerPath(artifactsDir);
6
101
  try {
7
- return await readJsonFile(ledgerPath(artifactsDir));
102
+ return parseRunLedger(await readJsonFile(path), path);
8
103
  }
9
104
  catch (error) {
10
105
  if (isFileMissingError(error)) {
106
+ // A missing run ledger just means no worker runs have been recorded yet.
11
107
  return { runs: [] };
12
108
  }
13
109
  throw error;
14
110
  }
15
111
  }
16
112
  export async function appendRunLedgerEntry(artifactsDir, entry) {
17
- const ledger = await loadRunLedger(artifactsDir);
18
- ledger.runs.push(entry);
19
- await writeJsonFile(ledgerPath(artifactsDir), ledger);
113
+ const lockHandle = await acquireLedgerLock(artifactsDir);
114
+ const path = ledgerPath(artifactsDir);
115
+ const tempPath = buildTempLedgerPath(artifactsDir);
116
+ try {
117
+ const ledger = await loadRunLedger(artifactsDir);
118
+ ledger.runs.push(entry);
119
+ await writeJsonFile(tempPath, ledger);
120
+ await rename(tempPath, path);
121
+ }
122
+ finally {
123
+ await lockHandle.close();
124
+ await rm(ledgerLockPath(artifactsDir), { force: true });
125
+ await rm(tempPath, { force: true }).catch(() => undefined);
126
+ }
20
127
  }
@@ -1,29 +1,29 @@
1
+ import { join } from "node:path";
1
2
  import { readOptionalJsonFile } from "../io/json.js";
3
+ import { formatValidationIssues, } from "../validation/basic.js";
2
4
  import { validateSessionConfig } from "../validation/sessionConfig.js";
3
5
  import { writeJsonFile } from "../io/json.js";
6
+ const SESSION_CONFIG_FILENAME = "session-config.json";
7
+ const DEFAULT_SESSION_CONFIG = { provider: "local-subprocess" };
4
8
  export function getSessionConfigPath(artifactsDir) {
5
- return `${artifactsDir}/session-config.json`;
9
+ return join(artifactsDir, SESSION_CONFIG_FILENAME);
6
10
  }
7
11
  export async function readSessionConfigFile(artifactsDir) {
8
12
  return await readOptionalJsonFile(getSessionConfigPath(artifactsDir));
9
13
  }
10
- function formatValidationIssues(configPath, issues) {
11
- const details = issues
12
- .map((issue) => `- ${issue.path}: ${issue.message}`)
13
- .join("\n");
14
- return `Invalid ${configPath}:\n${details}`;
14
+ function formatConfigValidationIssues(configPath, issues) {
15
+ return `Invalid ${configPath}:\n${formatValidationIssues(issues).replace(/^ /gm, "- ")}`;
15
16
  }
16
17
  export async function loadSessionConfig(artifactsDir) {
17
18
  const configPath = getSessionConfigPath(artifactsDir);
18
19
  const rawConfig = await readOptionalJsonFile(configPath);
19
20
  if (rawConfig === undefined) {
20
- const defaultConfig = { provider: "local-subprocess" };
21
- await writeJsonFile(configPath, defaultConfig);
22
- return defaultConfig;
21
+ await writeJsonFile(configPath, DEFAULT_SESSION_CONFIG);
22
+ return { ...DEFAULT_SESSION_CONFIG };
23
23
  }
24
24
  const issues = validateSessionConfig(rawConfig);
25
25
  if (issues.length > 0) {
26
- throw new Error(formatValidationIssues(configPath, issues));
26
+ throw new Error(formatConfigValidationIssues(configPath, issues));
27
27
  }
28
28
  return rawConfig;
29
29
  }
@@ -1,3 +1,4 @@
1
+ /** One normalized result imported from an external analyzer such as eslint or tsc. */
1
2
  export interface ExternalAnalyzerResultItem {
2
3
  id: string;
3
4
  category: string;
@@ -7,8 +8,10 @@ export interface ExternalAnalyzerResultItem {
7
8
  line_end?: number;
8
9
  summary: string;
9
10
  rule?: string;
11
+ /** Preserves the analyzer-native payload when consumers need original detail. */
10
12
  raw?: unknown;
11
13
  }
14
+ /** Imported analyzer output captured at a single generation time. */
12
15
  export interface ExternalAnalyzerResults {
13
16
  tool: string;
14
17
  generated_at?: string;
@@ -1,11 +1,15 @@
1
+ export declare const FLOW_COVERAGE_STATUSES: readonly ["pending", "partial", "complete"];
2
+ export type FlowCoverageStatus = (typeof FLOW_COVERAGE_STATUSES)[number];
3
+ /** Coverage for one critical flow across the lenses the audit expects to see. */
1
4
  export interface FlowCoverageRecord {
2
5
  flow_id: string;
3
6
  paths: string[];
4
7
  required_lenses: string[];
5
8
  completed_lenses: string[];
6
- status: "pending" | "partial" | "complete";
9
+ status: FlowCoverageStatus;
7
10
  notes?: string[];
8
11
  }
12
+ /** Aggregated flow coverage written beside the critical flow manifest. */
9
13
  export interface FlowCoverageManifest {
10
14
  flows: FlowCoverageRecord[];
11
15
  }
@@ -1 +1,5 @@
1
- export {};
1
+ export const FLOW_COVERAGE_STATUSES = [
2
+ "pending",
3
+ "partial",
4
+ "complete",
5
+ ];
@@ -1,11 +1,17 @@
1
+ export declare const FLOW_CONFIDENCE_LEVELS: readonly ["high", "low"];
2
+ export type FlowConfidenceLevel = (typeof FLOW_CONFIDENCE_LEVELS)[number];
3
+ /** A critical user or system flow that must be covered by the audit. */
1
4
  export interface CriticalFlow {
2
5
  id: string;
3
6
  name: string;
4
7
  entrypoints: string[];
5
8
  paths: string[];
6
9
  concerns: string[];
10
+ confidence?: FlowConfidenceLevel;
7
11
  notes?: string[];
8
12
  }
13
+ /** The set of critical flows inferred from intake artifacts. */
9
14
  export interface CriticalFlowManifest {
10
15
  flows: CriticalFlow[];
16
+ fallback_required?: boolean;
11
17
  }
@@ -1 +1 @@
1
- export {};
1
+ export const FLOW_CONFIDENCE_LEVELS = ["high", "low"];
@@ -1,13 +1,17 @@
1
+ export declare const RUN_LEDGER_STATUSES: readonly ["completed", "blocked", "failed", "no_progress"];
2
+ export type RunLedgerStatus = (typeof RUN_LEDGER_STATUSES)[number];
3
+ /** One persisted supervisor run entry, including the terminal worker outcome. */
1
4
  export interface RunLedgerEntry {
2
5
  run_id: string;
3
6
  provider: string;
4
7
  obligation_id: string | null;
5
8
  selected_executor: string | null;
6
- status: "completed" | "blocked" | "failed" | "no_progress";
9
+ status: RunLedgerStatus;
7
10
  started_at: string;
8
11
  ended_at: string;
9
12
  result_path: string;
10
13
  }
14
+ /** Append-only ledger used to explain how the audit advanced over time. */
11
15
  export interface RunLedger {
12
16
  runs: RunLedgerEntry[];
13
17
  }
@@ -1 +1,6 @@
1
- export {};
1
+ export const RUN_LEDGER_STATUSES = [
2
+ "completed",
3
+ "blocked",
4
+ "failed",
5
+ "no_progress",
6
+ ];
@@ -1,23 +1,33 @@
1
- export type RuntimeValidationKind = "unit-risk-check" | "critical-flow-check";
1
+ export declare const RUNTIME_VALIDATION_KINDS: readonly ["unit-risk-check", "critical-flow-check"];
2
+ export type RuntimeValidationKind = (typeof RUNTIME_VALIDATION_KINDS)[number];
3
+ export declare const RUNTIME_VALIDATION_PRIORITIES: readonly ["high", "medium", "low"];
4
+ export type RuntimeValidationPriority = (typeof RUNTIME_VALIDATION_PRIORITIES)[number];
5
+ export declare const RUNTIME_VALIDATION_STATUSES: readonly ["pending", "confirmed", "not_confirmed", "inconclusive", "not_required"];
6
+ export type RuntimeValidationStatus = (typeof RUNTIME_VALIDATION_STATUSES)[number];
7
+ /** A deterministic runtime check queued after static review highlights risk. */
2
8
  export interface RuntimeValidationTask {
3
9
  id: string;
4
10
  kind: RuntimeValidationKind;
5
11
  target_paths: string[];
6
12
  reason: string;
7
- priority: "high" | "medium" | "low";
13
+ priority: RuntimeValidationPriority;
14
+ command?: string[];
8
15
  suggested_checks?: string[];
9
16
  source_artifacts?: string[];
10
17
  }
18
+ /** Planner output for the runtime validation stage. */
11
19
  export interface RuntimeValidationTaskManifest {
12
20
  tasks: RuntimeValidationTask[];
13
21
  }
22
+ /** Result recorded after a runtime validation task runs or is intentionally skipped. */
14
23
  export interface RuntimeValidationResult {
15
24
  task_id: string;
16
- status: "pending" | "confirmed" | "not_confirmed" | "inconclusive";
25
+ status: RuntimeValidationStatus;
17
26
  summary: string;
18
27
  evidence?: string[];
19
28
  notes?: string[];
20
29
  }
30
+ /** Persisted runtime validation outcomes keyed by generated task id. */
21
31
  export interface RuntimeValidationReport {
22
32
  results: RuntimeValidationResult[];
23
33
  }
@@ -1 +1,16 @@
1
- export {};
1
+ export const RUNTIME_VALIDATION_KINDS = [
2
+ "unit-risk-check",
3
+ "critical-flow-check",
4
+ ];
5
+ export const RUNTIME_VALIDATION_PRIORITIES = [
6
+ "high",
7
+ "medium",
8
+ "low",
9
+ ];
10
+ export const RUNTIME_VALIDATION_STATUSES = [
11
+ "pending",
12
+ "confirmed",
13
+ "not_confirmed",
14
+ "inconclusive",
15
+ "not_required",
16
+ ];
@@ -1,5 +1,8 @@
1
- export type ProviderName = "auto" | "local-subprocess" | "subprocess-template" | "claude-code" | "opencode" | "vscode-task";
1
+ export declare const PROVIDER_NAMES: readonly ["auto", "local-subprocess", "subprocess-template", "claude-code", "opencode", "vscode-task"];
2
+ export type ProviderName = (typeof PROVIDER_NAMES)[number];
2
3
  export type ResolvedProviderName = Exclude<ProviderName, "auto">;
4
+ export declare const SESSION_UI_MODES: readonly ["visible", "headless"];
5
+ export type SessionUiMode = (typeof SESSION_UI_MODES)[number];
3
6
  export interface SubprocessTemplateConfig {
4
7
  command_template: string[];
5
8
  env?: Record<string, string>;
@@ -16,10 +19,20 @@ export interface VSCodeTaskConfig {
16
19
  command_template: string[];
17
20
  env?: Record<string, string>;
18
21
  }
22
+ export declare const PROVIDER_SECTION_KEYS: {
23
+ readonly "subprocess-template": "subprocess_template";
24
+ readonly "claude-code": "claude_code";
25
+ readonly opencode: "opencode";
26
+ readonly "vscode-task": "vscode_task";
27
+ };
28
+ /**
29
+ * Provider names use CLI-friendly hyphenation, while nested provider config
30
+ * sections stay snake_case because they serialize directly into JSON files.
31
+ */
19
32
  export interface SessionConfig {
20
33
  provider?: ProviderName;
21
34
  timeout_ms?: number;
22
- ui_mode?: "visible" | "headless";
35
+ ui_mode?: SessionUiMode;
23
36
  subprocess_template?: SubprocessTemplateConfig;
24
37
  claude_code?: ClaudeCodeConfig;
25
38
  opencode?: OpenCodeConfig;
@@ -1 +1,15 @@
1
- export {};
1
+ export const PROVIDER_NAMES = [
2
+ "auto",
3
+ "local-subprocess",
4
+ "subprocess-template",
5
+ "claude-code",
6
+ "opencode",
7
+ "vscode-task",
8
+ ];
9
+ export const SESSION_UI_MODES = ["visible", "headless"];
10
+ export const PROVIDER_SECTION_KEYS = {
11
+ "subprocess-template": "subprocess_template",
12
+ "claude-code": "claude_code",
13
+ opencode: "opencode",
14
+ "vscode-task": "vscode_task",
15
+ };
@@ -1,4 +1,6 @@
1
- export type SurfaceKind = "interface" | "background";
1
+ export declare const SURFACE_KINDS: readonly ["interface", "background"];
2
+ export type SurfaceKind = (typeof SURFACE_KINDS)[number];
3
+ /** Discovered execution surfaces that define where the product can be reached. */
2
4
  export interface SurfaceRecord {
3
5
  id: string;
4
6
  kind: SurfaceKind;
@@ -7,6 +9,7 @@ export interface SurfaceRecord {
7
9
  methods?: string[];
8
10
  notes?: string[];
9
11
  }
12
+ /** Intake output that summarizes externally reachable product surfaces. */
10
13
  export interface SurfaceManifest {
11
14
  surfaces: SurfaceRecord[];
12
15
  }
@@ -1 +1 @@
1
- export {};
1
+ export const SURFACE_KINDS = ["interface", "background"];
@@ -1,3 +1,9 @@
1
+ export declare const WORKER_COMMAND_MODES: readonly ["run", "deferred"];
2
+ export type WorkerCommandMode = (typeof WORKER_COMMAND_MODES)[number];
3
+ /**
4
+ * Worker tasks serialize directly to task.json, so their persisted field names
5
+ * intentionally stay snake_case for consistency across providers and bridges.
6
+ */
1
7
  export interface WorkerTask {
2
8
  contract_version: "audit-code-worker/v1alpha1";
3
9
  run_id: string;
@@ -11,7 +17,10 @@ export interface WorkerTask {
11
17
  pending_audit_tasks_path?: string;
12
18
  runtime_updates_path?: string;
13
19
  external_analyzer_results_path?: string;
20
+ worker_command_mode?: WorkerCommandMode;
21
+ /** @deprecated Prefer worker_command_mode: "deferred" for new task files. */
14
22
  skip_worker_command?: boolean;
15
23
  timeout_ms?: number;
16
24
  max_retries?: number;
17
25
  }
26
+ export declare function usesDeferredWorkerCommand(task: Pick<WorkerTask, "worker_command_mode" | "skip_worker_command">): boolean;
@@ -1 +1,5 @@
1
- export {};
1
+ export const WORKER_COMMAND_MODES = ["run", "deferred"];
2
+ export function usesDeferredWorkerCommand(task) {
3
+ return (task.worker_command_mode === "deferred" ||
4
+ task.skip_worker_command === true);
5
+ }
package/dist/types.d.ts CHANGED
@@ -28,10 +28,9 @@ export interface AuditUnit {
28
28
  export interface UnitManifest {
29
29
  units: AuditUnit[];
30
30
  }
31
- export interface ReviewedLineRange {
31
+ export interface FileCoverageRecord {
32
32
  path: string;
33
- start: number;
34
- end: number;
33
+ total_lines: number;
35
34
  pass_id: string;
36
35
  lens?: Lens;
37
36
  agent_role?: string;
@@ -94,11 +93,9 @@ export interface AuditResult {
94
93
  pass_id: string;
95
94
  lens: Lens;
96
95
  agent_role?: string;
97
- reviewed_ranges: Array<{
96
+ file_coverage: Array<{
98
97
  path: string;
99
- start: number;
100
- end: number;
101
- line_count: number;
98
+ total_lines: number;
102
99
  }>;
103
100
  findings: Finding[];
104
101
  notes?: string[];
@@ -1,3 +1,3 @@
1
1
  import type { ArtifactBundle } from "../io/artifacts.js";
2
- import type { ValidationIssue } from "./basic.js";
2
+ import { type ValidationIssue } from "./basic.js";
3
3
  export declare function validateArtifactBundle(bundle: ArtifactBundle): ValidationIssue[];