auditor-lambda 0.2.8 → 0.2.10

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 (104) hide show
  1. package/README.md +6 -0
  2. package/audit-code-wrapper-lib.mjs +1 -1
  3. package/dist/adapters/eslint.js +9 -5
  4. package/dist/cli.d.ts +42 -1
  5. package/dist/cli.js +234 -63
  6. package/dist/extractors/bucketing.d.ts +4 -0
  7. package/dist/extractors/bucketing.js +6 -2
  8. package/dist/extractors/disposition.d.ts +4 -0
  9. package/dist/extractors/disposition.js +6 -2
  10. package/dist/extractors/fileInventory.js +24 -28
  11. package/dist/extractors/flows.d.ts +5 -0
  12. package/dist/extractors/flows.js +18 -38
  13. package/dist/extractors/pathPatterns.d.ts +10 -3
  14. package/dist/extractors/pathPatterns.js +109 -61
  15. package/dist/extractors/surfaces.d.ts +4 -0
  16. package/dist/extractors/surfaces.js +11 -11
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +2 -1
  19. package/dist/io/artifacts.d.ts +55 -40
  20. package/dist/io/artifacts.js +73 -110
  21. package/dist/io/json.js +52 -21
  22. package/dist/io/runArtifacts.d.ts +1 -1
  23. package/dist/io/runArtifacts.js +26 -3
  24. package/dist/orchestrator/advance.js +83 -62
  25. package/dist/orchestrator/autoFixExecutor.js +32 -15
  26. package/dist/orchestrator/flowCoverage.js +11 -5
  27. package/dist/orchestrator/flowPlanning.d.ts +7 -2
  28. package/dist/orchestrator/flowPlanning.js +46 -21
  29. package/dist/orchestrator/flowRequeue.js +28 -8
  30. package/dist/orchestrator/internalExecutors.js +12 -8
  31. package/dist/orchestrator/localCommands.d.ts +14 -0
  32. package/dist/orchestrator/localCommands.js +124 -0
  33. package/dist/orchestrator/planning.js +25 -3
  34. package/dist/orchestrator/requeue.js +11 -1
  35. package/dist/orchestrator/syntaxResolutionExecutor.js +60 -59
  36. package/dist/orchestrator/taskBuilder.d.ts +4 -2
  37. package/dist/orchestrator/taskBuilder.js +153 -52
  38. package/dist/orchestrator/unitBuilder.d.ts +3 -1
  39. package/dist/orchestrator/unitBuilder.js +24 -16
  40. package/dist/prompts/renderWorkerPrompt.d.ts +1 -1
  41. package/dist/prompts/renderWorkerPrompt.js +16 -8
  42. package/dist/providers/claudeCodeProvider.d.ts +4 -1
  43. package/dist/providers/claudeCodeProvider.js +8 -5
  44. package/dist/providers/localSubprocessProvider.d.ts +4 -0
  45. package/dist/providers/localSubprocessProvider.js +7 -2
  46. package/dist/providers/spawnLoggedCommand.d.ts +9 -1
  47. package/dist/providers/spawnLoggedCommand.js +77 -29
  48. package/dist/reporting/synthesis.d.ts +2 -0
  49. package/dist/reporting/synthesis.js +12 -9
  50. package/dist/supervisor/operatorHandoff.d.ts +1 -1
  51. package/dist/supervisor/operatorHandoff.js +56 -18
  52. package/dist/supervisor/runLedger.d.ts +1 -1
  53. package/dist/supervisor/runLedger.js +112 -5
  54. package/dist/supervisor/sessionConfig.js +10 -10
  55. package/dist/types/externalAnalyzer.d.ts +3 -0
  56. package/dist/types/flowCoverage.d.ts +5 -1
  57. package/dist/types/flowCoverage.js +5 -1
  58. package/dist/types/flows.d.ts +5 -1
  59. package/dist/types/flows.js +1 -1
  60. package/dist/types/runLedger.d.ts +5 -1
  61. package/dist/types/runLedger.js +6 -1
  62. package/dist/types/runtimeValidation.d.ts +12 -3
  63. package/dist/types/runtimeValidation.js +16 -1
  64. package/dist/types/sessionConfig.d.ts +15 -2
  65. package/dist/types/sessionConfig.js +15 -1
  66. package/dist/types/surfaces.d.ts +4 -1
  67. package/dist/types/surfaces.js +1 -1
  68. package/dist/types/workerSession.d.ts +9 -0
  69. package/dist/types/workerSession.js +5 -1
  70. package/dist/validation/artifacts.d.ts +1 -1
  71. package/dist/validation/artifacts.js +33 -20
  72. package/dist/validation/auditResults.d.ts +2 -2
  73. package/dist/validation/auditResults.js +7 -15
  74. package/dist/validation/basic.d.ts +9 -1
  75. package/dist/validation/basic.js +40 -3
  76. package/dist/validation/sessionConfig.d.ts +4 -2
  77. package/dist/validation/sessionConfig.js +62 -15
  78. package/docs/agent-integrations.md +31 -11
  79. package/docs/next-steps.md +21 -4
  80. package/docs/packaging.md +14 -0
  81. package/docs/product-direction.md +22 -0
  82. package/docs/production-launch-bar.md +2 -0
  83. package/docs/releasing.md +17 -0
  84. package/docs/remediation-baseline.md +75 -0
  85. package/docs/run-flow.md +23 -11
  86. package/docs/session-config.md +53 -6
  87. package/docs/supervisor.md +7 -0
  88. package/docs/workflow-refactor-brief.md +177 -0
  89. package/package.json +1 -1
  90. package/schemas/audit-code-v1alpha1.schema.json +1 -0
  91. package/schemas/audit_result.schema.json +4 -1
  92. package/schemas/audit_task.schema.json +3 -1
  93. package/schemas/coverage_matrix.schema.json +3 -3
  94. package/schemas/critical_flows.schema.json +6 -2
  95. package/schemas/file_disposition.schema.json +2 -2
  96. package/schemas/finding.schema.json +9 -4
  97. package/schemas/flow_coverage.schema.json +2 -2
  98. package/schemas/repo_manifest.schema.json +4 -4
  99. package/schemas/risk_register.schema.json +2 -2
  100. package/schemas/runtime_validation_report.schema.json +2 -2
  101. package/schemas/runtime_validation_tasks.schema.json +8 -2
  102. package/schemas/surface_manifest.schema.json +6 -3
  103. package/schemas/unit_manifest.schema.json +3 -2
  104. package/skills/audit-code/SKILL.md +5 -0
package/README.md CHANGED
@@ -11,6 +11,7 @@ Normal product usage should:
11
11
  - use the active conversation model by default
12
12
  - use project files and attached repository context by default
13
13
  - avoid manual paths, provider flags, and model-selection arguments
14
+ - keep semantic review with the active conversation agent by default
14
15
  - advance the audit automatically until it completes or no further automatic progress is possible
15
16
 
16
17
  ## Conversation Setup
@@ -86,6 +87,7 @@ This wrapper:
86
87
  - auto-builds `dist/` if it is missing
87
88
  - advances fresh worker sessions automatically until the audit completes or the remaining work requires imported results or an interactive provider
88
89
  - continues through provider-assisted audit review automatically when `.audit-artifacts/session-config.json` selects an interactive provider bridge
90
+ - keeps those provider bridges as fallback compatibility modes rather than the primary product path
89
91
  - emits `contract_version: "audit-code/v1alpha1"`
90
92
  - refreshes `.audit-artifacts/operator-handoff.json` and `.audit-artifacts/operator-handoff.md` with suggested evidence-import paths and continuation hints
91
93
 
@@ -160,6 +162,7 @@ Optional backend config:
160
162
  - use `audit-code` from the repository root only when you need the repo-local backend fallback
161
163
  - use omitted provider or `local-subprocess` for the safest deterministic fallback behavior
162
164
  - use `provider: "auto"` only when you want best-effort routing across installed backends
165
+ - treat explicit provider bridges as compatibility fallback, not as the intended owner of semantic review
163
166
 
164
167
  ## Implementation Next Steps
165
168
 
@@ -169,6 +172,7 @@ The next implementation work is tracked in:
169
172
 
170
173
  The short version is:
171
174
 
175
+ - realign review dispatch around the conversation-owned, non-overlapping lens-block workflow
172
176
  - prove the generated Codex, Claude Desktop, OpenCode, VS Code, and Antigravity guidance in real host flows
173
177
  - tighten the repo-local MCP-first bootstrap where host smoke tests expose friction
174
178
  - polish provider-assisted continuation and failure guidance
@@ -186,6 +190,8 @@ For GitHub Actions publication and npm Trusted Publishing setup, see `docs/relea
186
190
  ## Key Docs
187
191
 
188
192
  - `docs/product-direction.md`
193
+ - `docs/workflow-refactor-brief.md`
194
+ - `docs/remediation-baseline.md`
189
195
  - `docs/releasing.md`
190
196
  - `docs/production-readiness.md`
191
197
  - `docs/production-launch-bar.md`
@@ -2049,7 +2049,7 @@ async function installBootstrap(argv) {
2049
2049
 
2050
2050
  const sessionConfigPath = join(root, '.audit-artifacts', 'session-config.json');
2051
2051
  if (!(await fileExists(sessionConfigPath))) {
2052
- const defaultConfig = { provider: 'auto' };
2052
+ const defaultConfig = { provider: 'local-subprocess' };
2053
2053
  await mkdir(dirname(sessionConfigPath), { recursive: true });
2054
2054
  await writeFile(sessionConfigPath, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf8');
2055
2055
  results.push({ path: sessionConfigPath, mode: 'created' });
@@ -1,12 +1,16 @@
1
1
  import { normalizeGenericExternalResults } from "./normalizeExternal.js";
2
2
  const ESLINT_SEVERITY_ERROR = 2;
3
3
  const ESLINT_SEVERITY_WARNING = 1;
4
+ const ESLINT_SEVERITY_MAP = {
5
+ [ESLINT_SEVERITY_ERROR]: "medium",
6
+ [ESLINT_SEVERITY_WARNING]: "low",
7
+ };
4
8
  function mapSeverity(value) {
5
- if (value === ESLINT_SEVERITY_ERROR)
6
- return "medium";
7
- if (value === ESLINT_SEVERITY_WARNING)
8
- return "low";
9
- return "info";
9
+ // ESLint's JSON formatter emits 2 for errors and 1 for warnings.
10
+ if (typeof value !== "number") {
11
+ return "info";
12
+ }
13
+ return ESLINT_SEVERITY_MAP[value] ?? "info";
10
14
  }
11
15
  export function normalizeEslintJson(input) {
12
16
  return normalizeGenericExternalResults("eslint", input.flatMap((file) => (file.messages ?? []).map((message, index) => ({
package/dist/cli.d.ts CHANGED
@@ -1 +1,42 @@
1
- export declare function runSample(): Promise<void>;
1
+ import type { SessionConfig } from "./types/sessionConfig.js";
2
+ type UiMode = "visible" | "headless";
3
+ declare function getFlag(argv: string[], name: string, fallback?: string): string | undefined;
4
+ declare function hasFlag(argv: string[], name: string): boolean;
5
+ declare function getArtifactsDir(argv: string[]): string;
6
+ declare function getRootDir(argv: string[]): string;
7
+ declare function getBatchResultsDir(argv: string[]): string | undefined;
8
+ declare function getMaxRuns(argv: string[]): number;
9
+ declare function getAgentBatchSize(argv: string[], sessionConfig: SessionConfig): number;
10
+ declare function getParallelWorkers(argv: string[], sessionConfig: SessionConfig): number;
11
+ declare function getTimeoutMs(argv: string[], sessionConfig: SessionConfig): number;
12
+ declare function chunkArray<T>(arr: T[], size: number): T[][];
13
+ declare function getUiMode(argv: string[], fallback?: UiMode): UiMode;
14
+ declare function countLines(path: string): Promise<number>;
15
+ declare function looksLikeCliFlag(value: string | undefined): boolean;
16
+ export declare const cliTestUtils: {
17
+ defaults: {
18
+ rootDir: string;
19
+ artifactsDir: string;
20
+ maxRuns: number;
21
+ agentBatchSize: number;
22
+ parallelWorkers: number;
23
+ timeoutMs: number;
24
+ uiMode: UiMode;
25
+ };
26
+ getFlag: typeof getFlag;
27
+ hasFlag: typeof hasFlag;
28
+ getArtifactsDir: typeof getArtifactsDir;
29
+ getRootDir: typeof getRootDir;
30
+ getBatchResultsDir: typeof getBatchResultsDir;
31
+ getMaxRuns: typeof getMaxRuns;
32
+ getAgentBatchSize: typeof getAgentBatchSize;
33
+ getParallelWorkers: typeof getParallelWorkers;
34
+ getTimeoutMs: typeof getTimeoutMs;
35
+ chunkArray: typeof chunkArray;
36
+ getUiMode: typeof getUiMode;
37
+ looksLikeCliFlag: typeof looksLikeCliFlag;
38
+ countLines: typeof countLines;
39
+ };
40
+ export declare function runSample(argv?: string[]): Promise<void>;
41
+ export declare function runCli(argv: string[]): Promise<void>;
42
+ export {};
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { access, mkdir, readdir, rename } from "node:fs/promises";
2
2
  import { createReadStream } from "node:fs";
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
4
5
  import { buildRepoManifest } from "./extractors/fileInventory.js";
5
6
  import { buildFileDisposition } from "./extractors/disposition.js";
6
7
  import { buildCriticalFlowManifest } from "./extractors/flows.js";
@@ -13,6 +14,7 @@ import { loadArtifactBundle, writeCoreArtifacts, promoteFinalAuditReport, } from
13
14
  import { readJsonFile, writeJsonFile } from "./io/json.js";
14
15
  import { validateArtifactBundle } from "./validation/artifacts.js";
15
16
  import { validateAuditResults, formatAuditResultIssues, } from "./validation/auditResults.js";
17
+ import { prefixValidationIssues } from "./validation/basic.js";
16
18
  import { validateConfiguredProviderEnvironment, validateSessionConfig, } from "./validation/sessionConfig.js";
17
19
  import { buildAuditReportModel, renderAuditReportMarkdown, } from "./reporting/synthesis.js";
18
20
  import { deriveAuditState } from "./orchestrator/state.js";
@@ -28,78 +30,101 @@ import { LOCAL_SUBPROCESS_PROVIDER_NAME } from "./providers/constants.js";
28
30
  import { runAuditCodeMcpServer } from "./mcp/server.js";
29
31
  const ADVANCE_AUDIT_CONTRACT_VERSION = "audit-code/v1alpha1";
30
32
  const WORKER_RESULT_CONTRACT_VERSION = "audit-code-worker-result/v1alpha1";
31
- const DEFAULT_MAX_RUNS = 1000;
32
- const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
33
- const sampleFiles = [
33
+ const DIRECT_CLI_DEFAULTS = {
34
+ rootDir: ".",
35
+ artifactsDir: ".artifacts",
36
+ maxRuns: 1000,
37
+ agentBatchSize: 1,
38
+ parallelWorkers: 1,
39
+ timeoutMs: 30 * 60 * 1000, // 30 minutes
40
+ uiMode: "headless",
41
+ };
42
+ // Keep the sample-run payload explicit so the demo command is deterministic.
43
+ const SAMPLE_REPO_FILES = [
34
44
  { path: "src/api/auth.ts", size_bytes: 1240, hash: "abc123" },
35
45
  { path: "src/lib/session.ts", size_bytes: 980, hash: "def456" },
36
46
  { path: "infra/deploy.yml", size_bytes: 420, hash: "ghi789" },
37
47
  { path: "docs/notes.md", size_bytes: 300, hash: "doc111" },
38
48
  ];
49
+ function isLongFlagToken(value) {
50
+ return typeof value === "string" && value.startsWith("--");
51
+ }
52
+ // Read a long-form CLI flag while treating a following flag token as "missing".
39
53
  function getFlag(argv, name, fallback) {
40
54
  const index = argv.indexOf(name);
41
- if (index >= 0 && argv[index + 1])
42
- return argv[index + 1];
43
- return fallback;
55
+ if (index < 0)
56
+ return fallback;
57
+ const candidate = argv[index + 1];
58
+ if (!candidate || isLongFlagToken(candidate))
59
+ return fallback;
60
+ return candidate;
44
61
  }
62
+ // Boolean flags only care whether the token is present at all.
45
63
  function hasFlag(argv, name) {
46
64
  return argv.includes(name);
47
65
  }
66
+ function resolveFlagPath(argv, name, fallback) {
67
+ return resolve(getFlag(argv, name, fallback));
68
+ }
69
+ function normalizePositiveInteger(value) {
70
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
71
+ return undefined;
72
+ }
73
+ return Math.floor(value);
74
+ }
75
+ function parsePositiveIntegerFlag(argv, name) {
76
+ const raw = getFlag(argv, name);
77
+ if (raw === undefined) {
78
+ return undefined;
79
+ }
80
+ return normalizePositiveInteger(Number(raw));
81
+ }
48
82
  function getArtifactsDir(argv) {
49
- return resolve(getFlag(argv, "--artifacts-dir", ".artifacts"));
83
+ return resolveFlagPath(argv, "--artifacts-dir", DIRECT_CLI_DEFAULTS.artifactsDir);
50
84
  }
51
85
  function getRootDir(argv) {
52
- return resolve(getFlag(argv, "--root", "."));
86
+ return resolveFlagPath(argv, "--root", DIRECT_CLI_DEFAULTS.rootDir);
53
87
  }
54
88
  function getBatchResultsDir(argv) {
55
89
  const value = getFlag(argv, "--batch-results");
56
90
  return value ? resolve(value) : undefined;
57
91
  }
58
92
  function getMaxRuns(argv) {
59
- const raw = Number(getFlag(argv, "--max-runs", String(DEFAULT_MAX_RUNS)));
60
- return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : DEFAULT_MAX_RUNS;
93
+ return parsePositiveIntegerFlag(argv, "--max-runs") ?? DIRECT_CLI_DEFAULTS.maxRuns;
61
94
  }
62
95
  function getAgentBatchSize(argv, sessionConfig) {
63
- const fromArg = getFlag(argv, "--agent-batch-size");
64
- if (fromArg !== undefined) {
65
- const parsed = Number(fromArg);
66
- if (Number.isFinite(parsed) && parsed > 0)
67
- return Math.floor(parsed);
68
- }
69
- if (typeof sessionConfig.agent_task_batch_size === "number" && sessionConfig.agent_task_batch_size > 0) {
70
- return Math.floor(sessionConfig.agent_task_batch_size);
71
- }
72
- return 1;
96
+ return (parsePositiveIntegerFlag(argv, "--agent-batch-size") ??
97
+ normalizePositiveInteger(sessionConfig.agent_task_batch_size) ??
98
+ DIRECT_CLI_DEFAULTS.agentBatchSize);
73
99
  }
74
100
  function getParallelWorkers(argv, sessionConfig) {
75
- const fromArg = getFlag(argv, "--parallel");
76
- if (fromArg !== undefined) {
77
- const parsed = Number(fromArg);
78
- if (Number.isFinite(parsed) && parsed > 0)
79
- return Math.floor(parsed);
80
- }
81
- if (typeof sessionConfig.parallel_workers === "number" && sessionConfig.parallel_workers > 0) {
82
- return Math.floor(sessionConfig.parallel_workers);
83
- }
84
- return 1;
101
+ return (parsePositiveIntegerFlag(argv, "--parallel") ??
102
+ normalizePositiveInteger(sessionConfig.parallel_workers) ??
103
+ DIRECT_CLI_DEFAULTS.parallelWorkers);
85
104
  }
86
105
  function getTimeoutMs(argv, sessionConfig) {
87
- const fromArg = getFlag(argv, "--timeout");
88
- if (fromArg !== undefined) {
89
- const parsed = Number(fromArg);
90
- if (Number.isFinite(parsed) && parsed > 0)
91
- return Math.floor(parsed);
92
- }
93
- return sessionConfig.timeout_ms ?? DEFAULT_TIMEOUT_MS;
106
+ return (parsePositiveIntegerFlag(argv, "--timeout") ??
107
+ normalizePositiveInteger(sessionConfig.timeout_ms) ??
108
+ DIRECT_CLI_DEFAULTS.timeoutMs);
109
+ }
110
+ function getExplicitProvider(argv) {
111
+ return getFlag(argv, "--provider");
112
+ }
113
+ function resolveRunProviderName(argv, sessionConfig) {
114
+ return resolveFreshSessionProviderName(getExplicitProvider(argv) ?? LOCAL_SUBPROCESS_PROVIDER_NAME, sessionConfig);
94
115
  }
95
116
  function chunkArray(arr, size) {
117
+ const chunkSize = normalizePositiveInteger(size);
118
+ if (chunkSize === undefined) {
119
+ throw new Error("chunkArray size must be a positive integer.");
120
+ }
96
121
  const chunks = [];
97
- for (let i = 0; i < arr.length; i += size) {
98
- chunks.push(arr.slice(i, i + size));
122
+ for (let i = 0; i < arr.length; i += chunkSize) {
123
+ chunks.push(arr.slice(i, i + chunkSize));
99
124
  }
100
125
  return chunks;
101
126
  }
102
- function getUiMode(argv, fallback = "headless") {
127
+ function getUiMode(argv, fallback = DIRECT_CLI_DEFAULTS.uiMode) {
103
128
  const raw = getFlag(argv, "--ui");
104
129
  if (raw === "visible")
105
130
  return "visible";
@@ -144,18 +169,11 @@ async function emitEnvelope(params) {
144
169
  }
145
170
  function buildManualReviewBlocker(providerName) {
146
171
  return providerName === LOCAL_SUBPROCESS_PROVIDER_NAME
147
- ? "Automatic local-subprocess work is exhausted. Remaining audit tasks require explicit audit results or an interactive provider such as claude-code, opencode, or subprocess-template."
172
+ ? "Automatic backend steps are exhausted. Remaining semantic review now belongs to the active conversation agent. Review the dispatched files, write structured audit results, and ingest them with audit-code --results <file> or audit-code --batch-results <dir>. If you intentionally want a backend bridge instead, re-run audit-code with --provider auto, --provider claude-code, --provider opencode, --provider subprocess-template, or --provider vscode-task."
148
173
  : "Automatic work is exhausted. Remaining audit tasks require explicit audit results or an interactive provider.";
149
174
  }
150
- function prefixValidationIssues(prefix, issues) {
151
- return issues.map((issue) => ({
152
- path: issue.path.length === 0
153
- ? prefix
154
- : issue.path === prefix || issue.path.startsWith(`${prefix}.`)
155
- ? issue.path
156
- : `${prefix}.${issue.path}`,
157
- message: issue.message,
158
- }));
175
+ function shouldRunInlineExecutor(selectedExecutor) {
176
+ return selectedExecutor !== null && selectedExecutor !== "agent";
159
177
  }
160
178
  function buildBlockedAuditState(params) {
161
179
  return {
@@ -279,8 +297,24 @@ function buildWorkerFailureBlocker(workerResult) {
279
297
  : workerResult.summary;
280
298
  }
281
299
  function looksLikeCliFlag(value) {
282
- return typeof value === "string" && value.startsWith("--");
300
+ return isLongFlagToken(value);
283
301
  }
302
+ export const cliTestUtils = {
303
+ defaults: DIRECT_CLI_DEFAULTS,
304
+ getFlag,
305
+ hasFlag,
306
+ getArtifactsDir,
307
+ getRootDir,
308
+ getBatchResultsDir,
309
+ getMaxRuns,
310
+ getAgentBatchSize,
311
+ getParallelWorkers,
312
+ getTimeoutMs,
313
+ chunkArray,
314
+ getUiMode,
315
+ looksLikeCliFlag,
316
+ countLines,
317
+ };
284
318
  async function maybeArchiveLegacyPendingResults(auditResultsPath) {
285
319
  if (!auditResultsPath || basename(auditResultsPath) !== "worker_results_pending.json") {
286
320
  return undefined;
@@ -388,8 +422,8 @@ function isWorkerResult(value) {
388
422
  value.contract_version ===
389
423
  WORKER_RESULT_CONTRACT_VERSION);
390
424
  }
391
- export async function runSample() {
392
- const repoManifest = buildRepoManifest("sample-repo", sampleFiles);
425
+ export async function runSample(argv = process.argv) {
426
+ const repoManifest = buildRepoManifest("sample-repo", SAMPLE_REPO_FILES);
393
427
  const disposition = buildFileDisposition(repoManifest);
394
428
  const unitManifest = buildUnitManifest(repoManifest, disposition);
395
429
  const surfaceManifest = buildSurfaceManifest(repoManifest, disposition);
@@ -444,7 +478,7 @@ export async function runSample() {
444
478
  audit_results: sampleResults,
445
479
  audit_report: auditReport,
446
480
  });
447
- const artifactsDir = getArtifactsDir(process.argv);
481
+ const artifactsDir = getArtifactsDir(argv);
448
482
  await mkdir(artifactsDir, { recursive: true });
449
483
  await writeCoreArtifacts(artifactsDir, {
450
484
  repo_manifest: repoManifest,
@@ -466,7 +500,7 @@ async function cmdAdvanceAudit(argv) {
466
500
  const root = getRootDir(argv);
467
501
  const artifactsDir = getArtifactsDir(argv);
468
502
  const sessionConfig = await loadSessionConfig(artifactsDir);
469
- const providerName = resolveFreshSessionProviderName(getFlag(argv, "--provider"), sessionConfig);
503
+ const providerName = resolveRunProviderName(argv, sessionConfig);
470
504
  const batchResultsDir = getBatchResultsDir(argv);
471
505
  if (batchResultsDir && getFlag(argv, "--results")) {
472
506
  throw new Error("Use either --results <file> or --batch-results <dir>, not both.");
@@ -532,13 +566,14 @@ async function cmdRunToCompletion(argv) {
532
566
  const root = getRootDir(argv);
533
567
  const artifactsDir = getArtifactsDir(argv);
534
568
  const sessionConfig = await loadSessionConfig(artifactsDir);
535
- const provider = createFreshSessionProvider(getFlag(argv, "--provider"), sessionConfig);
569
+ const explicitProvider = getExplicitProvider(argv);
570
+ const provider = createFreshSessionProvider(explicitProvider ?? LOCAL_SUBPROCESS_PROVIDER_NAME, sessionConfig);
536
571
  const uiMode = getUiMode(argv, sessionConfig.ui_mode ?? "headless");
537
572
  const maxRuns = getMaxRuns(argv);
538
573
  const agentBatchSize = getAgentBatchSize(argv, sessionConfig);
539
574
  const parallelWorkers = getParallelWorkers(argv, sessionConfig);
540
575
  const timeoutMs = getTimeoutMs(argv, sessionConfig);
541
- const selfCliPath = resolve(process.argv[1] ?? "");
576
+ const selfCliPath = resolve(argv[1] ?? process.argv[1] ?? "");
542
577
  await mkdir(artifactsDir, { recursive: true });
543
578
  await ensureSupervisorDirs(artifactsDir);
544
579
  const batchResultsDir = getBatchResultsDir(argv);
@@ -646,6 +681,8 @@ async function cmdRunToCompletion(argv) {
646
681
  ],
647
682
  audit_results_path: blockAuditResultsPath,
648
683
  pending_audit_tasks_path: blockPendingTasksPath,
684
+ timeout_ms: timeoutMs,
685
+ max_retries: 0,
649
686
  };
650
687
  const blockPrompt = renderWorkerPrompt(blockTask);
651
688
  await writeWorkerTaskFiles(blockTask, blockPrompt, blockPaths, artifactsDir, blockPendingTasks);
@@ -716,7 +753,9 @@ async function cmdRunToCompletion(argv) {
716
753
  worker_command: [process.execPath, selfCliPath, "worker-run", "--task", slotPaths.taskPath],
717
754
  audit_results_path: slotAuditResultsPath,
718
755
  pending_audit_tasks_path: slotPendingTasksPath,
719
- skip_worker_command: true,
756
+ worker_command_mode: "deferred",
757
+ timeout_ms: timeoutMs,
758
+ max_retries: 0,
720
759
  };
721
760
  const slotPrompt = renderWorkerPrompt(slotTask);
722
761
  await writeWorkerTaskFiles(slotTask, slotPrompt, slotPaths, artifactsDir, group);
@@ -860,6 +899,124 @@ async function cmdRunToCompletion(argv) {
860
899
  runCount += 1;
861
900
  const runId = buildRunId(obligationId, runCount);
862
901
  const paths = getRunPaths(artifactsDir, runId);
902
+ if (shouldRunInlineExecutor(preferredExecutor)) {
903
+ await clearDispatchFiles(artifactsDir);
904
+ const startedAt = new Date().toISOString();
905
+ let workerResult;
906
+ try {
907
+ const result = await runAuditStep({
908
+ root,
909
+ artifactsDir,
910
+ preferredExecutor,
911
+ auditResultsPath,
912
+ runtimeUpdatesPath,
913
+ externalAnalyzerPath,
914
+ });
915
+ workerResult = {
916
+ contract_version: WORKER_RESULT_CONTRACT_VERSION,
917
+ run_id: runId,
918
+ obligation_id: obligationId,
919
+ status: result.progress_made ? "completed" : "no_progress",
920
+ progress_made: result.progress_made,
921
+ selected_executor: result.selected_executor,
922
+ artifacts_written: result.artifacts_written,
923
+ summary: result.progress_summary,
924
+ next_likely_step: result.next_likely_step,
925
+ errors: [],
926
+ };
927
+ }
928
+ catch (error) {
929
+ const message = error instanceof Error ? error.message : String(error);
930
+ workerResult = {
931
+ contract_version: WORKER_RESULT_CONTRACT_VERSION,
932
+ run_id: runId,
933
+ obligation_id: obligationId,
934
+ status: "failed",
935
+ progress_made: false,
936
+ selected_executor: preferredExecutor,
937
+ artifacts_written: [],
938
+ summary: `Inline executor failed for ${preferredExecutor}: ${message}`,
939
+ next_likely_step: decision.selected_obligation,
940
+ errors: [message],
941
+ };
942
+ }
943
+ await writeJsonFile(paths.resultPath, workerResult);
944
+ await writeJsonFile(paths.statusPath, {
945
+ run_id: runId,
946
+ status: workerResult.status,
947
+ execution_mode: "inline",
948
+ });
949
+ await appendRunLedgerEntry(artifactsDir, {
950
+ run_id: runId,
951
+ provider: provider.name,
952
+ obligation_id: obligationId,
953
+ selected_executor: workerResult.selected_executor,
954
+ status: workerResult.status,
955
+ started_at: startedAt,
956
+ ended_at: new Date().toISOString(),
957
+ result_path: paths.resultPath,
958
+ });
959
+ lastResult = workerResult;
960
+ if (workerResult.progress_made) {
961
+ anyProgress = true;
962
+ }
963
+ for (const artifact of workerResult.artifacts_written) {
964
+ artifactsWritten.add(artifact);
965
+ }
966
+ artifactsWritten.add("run-ledger.json");
967
+ if (externalAnalyzerPath)
968
+ pendingExternalAnalyzerPath = undefined;
969
+ if (auditResultsPath &&
970
+ pendingBatchAuditResults[0] === auditResultsPath &&
971
+ preferredExecutor === "result_ingestion_executor" &&
972
+ workerResult.status !== "failed" &&
973
+ workerResult.status !== "blocked") {
974
+ pendingBatchAuditResults.shift();
975
+ }
976
+ if (auditResultsPath)
977
+ pendingAuditResultsPath = undefined;
978
+ if (runtimeUpdatesPath)
979
+ pendingRuntimeUpdatesPath = undefined;
980
+ if (workerResult.status === "failed" ||
981
+ workerResult.status === "blocked" ||
982
+ workerResult.status === "no_progress") {
983
+ const bundleAfter = await loadArtifactBundle(artifactsDir);
984
+ const shouldBlock = workerResult.status === "failed" || workerResult.status === "blocked";
985
+ const state = shouldBlock
986
+ ? buildBlockedAuditState({
987
+ state: bundleAfter.audit_state ?? deriveAuditState(bundleAfter),
988
+ obligationId: workerResult.obligation_id,
989
+ executor: workerResult.selected_executor,
990
+ blocker: buildWorkerFailureBlocker(workerResult),
991
+ })
992
+ : bundleAfter.audit_state ?? deriveAuditState(bundleAfter);
993
+ if (shouldBlock) {
994
+ await writeCoreArtifacts(artifactsDir, {
995
+ ...bundleAfter,
996
+ audit_state: state,
997
+ });
998
+ }
999
+ await emitEnvelope({
1000
+ root,
1001
+ artifactsDir,
1002
+ bundle: shouldBlock
1003
+ ? { ...bundleAfter, audit_state: state }
1004
+ : bundleAfter,
1005
+ audit_state: state,
1006
+ selected_obligation: workerResult.obligation_id,
1007
+ selected_executor: workerResult.selected_executor,
1008
+ progress_made: anyProgress,
1009
+ artifacts_written: Array.from(shouldBlock
1010
+ ? new Set([...artifactsWritten, "audit_state.json"])
1011
+ : artifactsWritten),
1012
+ progress_summary: buildWorkerFailureBlocker(workerResult),
1013
+ next_likely_step: shouldBlock ? null : workerResult.next_likely_step,
1014
+ providerName: provider.name,
1015
+ });
1016
+ return;
1017
+ }
1018
+ continue;
1019
+ }
863
1020
  const pendingAuditTasks = preferredExecutor === "agent"
864
1021
  ? buildPendingAuditTasks(bundle).slice(0, agentBatchSize)
865
1022
  : undefined;
@@ -888,6 +1045,8 @@ async function cmdRunToCompletion(argv) {
888
1045
  pending_audit_tasks_path: pendingAuditTasksPath,
889
1046
  runtime_updates_path: runtimeUpdatesPath,
890
1047
  external_analyzer_results_path: externalAnalyzerPath,
1048
+ timeout_ms: timeoutMs,
1049
+ max_retries: 0,
891
1050
  };
892
1051
  const prompt = renderWorkerPrompt(task);
893
1052
  await writeWorkerTaskFiles(task, prompt, paths, artifactsDir, pendingAuditTasks);
@@ -1317,7 +1476,7 @@ async function main(argv) {
1317
1476
  const command = argv[2] ?? "sample-run";
1318
1477
  switch (command) {
1319
1478
  case "sample-run":
1320
- await runSample();
1479
+ await runSample(argv);
1321
1480
  return;
1322
1481
  case "advance-audit":
1323
1482
  await cmdAdvanceAudit(argv);
@@ -1367,7 +1526,19 @@ async function main(argv) {
1367
1526
  process.exitCode = 1;
1368
1527
  }
1369
1528
  }
1370
- await main(process.argv).catch((error) => {
1371
- console.error(error instanceof Error ? error.message : String(error));
1372
- process.exitCode = 1;
1373
- });
1529
+ export async function runCli(argv) {
1530
+ await main(argv).catch((error) => {
1531
+ console.error(error instanceof Error ? error.message : String(error));
1532
+ process.exitCode = 1;
1533
+ });
1534
+ }
1535
+ function isDirectCliExecution(argv) {
1536
+ const entryPath = argv[1];
1537
+ if (!entryPath) {
1538
+ return false;
1539
+ }
1540
+ return resolve(entryPath) === fileURLToPath(import.meta.url);
1541
+ }
1542
+ if (isDirectCliExecution(process.argv)) {
1543
+ await runCli(process.argv);
1544
+ }
@@ -4,4 +4,8 @@ export interface BucketAssignment {
4
4
  buckets: FileBucket[];
5
5
  rationale: string[];
6
6
  }
7
+ /**
8
+ * Buckets files using the shared extractor heuristics so intake stays
9
+ * consistent across OS-specific path separators and mixed-case manifests.
10
+ */
7
11
  export declare function bucketFile(path: string): BucketAssignment;
@@ -1,12 +1,16 @@
1
- import { isNodeModulesOrGit, isTestPath, isInterfacePath, isDataLayerPath, isSecuritySensitivePath, isConcurrencyPath, isScriptPath, isDeploymentConfigPath, isDocPath, isGeneratedPath, } from "./pathPatterns.js";
1
+ import { isNodeModulesOrGit, isTestPath, isInterfacePath, isDataLayerPath, isSecuritySensitivePath, isConcurrencyPath, isScriptPath, isDeploymentConfigPath, isDocPath, isGeneratedPath, normalizeExtractorPath, } from "./pathPatterns.js";
2
2
  function addBucket(buckets, rationale, bucket, reason) {
3
3
  if (!buckets.has(bucket)) {
4
4
  buckets.add(bucket);
5
5
  rationale.push(reason);
6
6
  }
7
7
  }
8
+ /**
9
+ * Buckets files using the shared extractor heuristics so intake stays
10
+ * consistent across OS-specific path separators and mixed-case manifests.
11
+ */
8
12
  export function bucketFile(path) {
9
- const normalized = path.toLowerCase();
13
+ const normalized = normalizeExtractorPath(path);
10
14
  const buckets = new Set();
11
15
  const rationale = [];
12
16
  if (isNodeModulesOrGit(normalized)) {
@@ -1,4 +1,8 @@
1
1
  import type { RepoManifest } from "../types.js";
2
2
  import type { FileDisposition, FileDispositionStatus } from "../types/disposition.js";
3
+ /**
4
+ * Applies shared path heuristics to mark files that should be excluded or
5
+ * down-scoped before audit planning begins.
6
+ */
3
7
  export declare function buildFileDisposition(repoManifest: RepoManifest): FileDisposition;
4
8
  export declare function isAuditExcludedStatus(status: FileDispositionStatus): boolean;
@@ -1,6 +1,6 @@
1
- import { isNodeModulesOrGit, isBuildOutput, isVendorPath, isBinaryArtifact, isLicensePath, isLockfilePath, isLogPath, isDocPath, } from "./pathPatterns.js";
1
+ import { isNodeModulesOrGit, isBuildOutput, isVendorPath, isBinaryArtifact, isLicensePath, isLockfilePath, isLogPath, isDocPath, normalizeExtractorPath, } from "./pathPatterns.js";
2
2
  function inferDisposition(path) {
3
- const normalized = path.toLowerCase();
3
+ const normalized = normalizeExtractorPath(path);
4
4
  if (isNodeModulesOrGit(normalized)) {
5
5
  return { path, status: "excluded", reason: "node_modules or .git excluded by convention." };
6
6
  }
@@ -35,6 +35,10 @@ function inferDisposition(path) {
35
35
  reason: "Default included source or config artifact.",
36
36
  };
37
37
  }
38
+ /**
39
+ * Applies shared path heuristics to mark files that should be excluded or
40
+ * down-scoped before audit planning begins.
41
+ */
38
42
  export function buildFileDisposition(repoManifest) {
39
43
  return {
40
44
  files: repoManifest.files.map((file) => inferDisposition(file.path)),