auditor-lambda 0.2.8 → 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 (98) 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 +114 -64
  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/flowCoverage.js +11 -5
  26. package/dist/orchestrator/flowPlanning.d.ts +7 -2
  27. package/dist/orchestrator/flowPlanning.js +46 -21
  28. package/dist/orchestrator/flowRequeue.js +28 -8
  29. package/dist/orchestrator/internalExecutors.js +12 -8
  30. package/dist/orchestrator/planning.js +25 -3
  31. package/dist/orchestrator/requeue.js +11 -1
  32. package/dist/orchestrator/taskBuilder.d.ts +4 -2
  33. package/dist/orchestrator/taskBuilder.js +153 -52
  34. package/dist/orchestrator/unitBuilder.d.ts +3 -1
  35. package/dist/orchestrator/unitBuilder.js +24 -16
  36. package/dist/prompts/renderWorkerPrompt.d.ts +1 -1
  37. package/dist/prompts/renderWorkerPrompt.js +16 -8
  38. package/dist/providers/claudeCodeProvider.d.ts +4 -1
  39. package/dist/providers/claudeCodeProvider.js +8 -5
  40. package/dist/providers/localSubprocessProvider.d.ts +4 -0
  41. package/dist/providers/localSubprocessProvider.js +7 -2
  42. package/dist/providers/spawnLoggedCommand.d.ts +9 -1
  43. package/dist/providers/spawnLoggedCommand.js +77 -29
  44. package/dist/reporting/synthesis.d.ts +2 -0
  45. package/dist/reporting/synthesis.js +12 -9
  46. package/dist/supervisor/operatorHandoff.js +48 -18
  47. package/dist/supervisor/runLedger.d.ts +1 -1
  48. package/dist/supervisor/runLedger.js +112 -5
  49. package/dist/supervisor/sessionConfig.js +10 -10
  50. package/dist/types/externalAnalyzer.d.ts +3 -0
  51. package/dist/types/flowCoverage.d.ts +5 -1
  52. package/dist/types/flowCoverage.js +5 -1
  53. package/dist/types/flows.d.ts +5 -1
  54. package/dist/types/flows.js +1 -1
  55. package/dist/types/runLedger.d.ts +5 -1
  56. package/dist/types/runLedger.js +6 -1
  57. package/dist/types/runtimeValidation.d.ts +12 -3
  58. package/dist/types/runtimeValidation.js +16 -1
  59. package/dist/types/sessionConfig.d.ts +15 -2
  60. package/dist/types/sessionConfig.js +15 -1
  61. package/dist/types/surfaces.d.ts +4 -1
  62. package/dist/types/surfaces.js +1 -1
  63. package/dist/types/workerSession.d.ts +9 -0
  64. package/dist/types/workerSession.js +5 -1
  65. package/dist/validation/artifacts.d.ts +1 -1
  66. package/dist/validation/artifacts.js +33 -20
  67. package/dist/validation/auditResults.d.ts +2 -2
  68. package/dist/validation/auditResults.js +7 -15
  69. package/dist/validation/basic.d.ts +9 -1
  70. package/dist/validation/basic.js +40 -3
  71. package/dist/validation/sessionConfig.d.ts +4 -2
  72. package/dist/validation/sessionConfig.js +62 -15
  73. package/docs/agent-integrations.md +29 -9
  74. package/docs/next-steps.md +21 -4
  75. package/docs/packaging.md +14 -0
  76. package/docs/product-direction.md +22 -0
  77. package/docs/production-launch-bar.md +2 -0
  78. package/docs/releasing.md +17 -0
  79. package/docs/remediation-baseline.md +75 -0
  80. package/docs/run-flow.md +23 -11
  81. package/docs/session-config.md +50 -5
  82. package/docs/supervisor.md +7 -0
  83. package/docs/workflow-refactor-brief.md +177 -0
  84. package/package.json +1 -1
  85. package/schemas/audit_result.schema.json +4 -1
  86. package/schemas/audit_task.schema.json +3 -1
  87. package/schemas/coverage_matrix.schema.json +3 -3
  88. package/schemas/critical_flows.schema.json +6 -2
  89. package/schemas/file_disposition.schema.json +2 -2
  90. package/schemas/finding.schema.json +9 -4
  91. package/schemas/flow_coverage.schema.json +2 -2
  92. package/schemas/repo_manifest.schema.json +4 -4
  93. package/schemas/risk_register.schema.json +2 -2
  94. package/schemas/runtime_validation_report.schema.json +2 -2
  95. package/schemas/runtime_validation_tasks.schema.json +8 -2
  96. package/schemas/surface_manifest.schema.json +6 -3
  97. package/schemas/unit_manifest.schema.json +3 -2
  98. 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,19 +169,9 @@ 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 run the generated worker command to ingest them. 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
- }));
159
- }
160
175
  function buildBlockedAuditState(params) {
161
176
  return {
162
177
  ...params.state,
@@ -279,8 +294,24 @@ function buildWorkerFailureBlocker(workerResult) {
279
294
  : workerResult.summary;
280
295
  }
281
296
  function looksLikeCliFlag(value) {
282
- return typeof value === "string" && value.startsWith("--");
297
+ return isLongFlagToken(value);
283
298
  }
299
+ export const cliTestUtils = {
300
+ defaults: DIRECT_CLI_DEFAULTS,
301
+ getFlag,
302
+ hasFlag,
303
+ getArtifactsDir,
304
+ getRootDir,
305
+ getBatchResultsDir,
306
+ getMaxRuns,
307
+ getAgentBatchSize,
308
+ getParallelWorkers,
309
+ getTimeoutMs,
310
+ chunkArray,
311
+ getUiMode,
312
+ looksLikeCliFlag,
313
+ countLines,
314
+ };
284
315
  async function maybeArchiveLegacyPendingResults(auditResultsPath) {
285
316
  if (!auditResultsPath || basename(auditResultsPath) !== "worker_results_pending.json") {
286
317
  return undefined;
@@ -388,8 +419,8 @@ function isWorkerResult(value) {
388
419
  value.contract_version ===
389
420
  WORKER_RESULT_CONTRACT_VERSION);
390
421
  }
391
- export async function runSample() {
392
- const repoManifest = buildRepoManifest("sample-repo", sampleFiles);
422
+ export async function runSample(argv = process.argv) {
423
+ const repoManifest = buildRepoManifest("sample-repo", SAMPLE_REPO_FILES);
393
424
  const disposition = buildFileDisposition(repoManifest);
394
425
  const unitManifest = buildUnitManifest(repoManifest, disposition);
395
426
  const surfaceManifest = buildSurfaceManifest(repoManifest, disposition);
@@ -444,7 +475,7 @@ export async function runSample() {
444
475
  audit_results: sampleResults,
445
476
  audit_report: auditReport,
446
477
  });
447
- const artifactsDir = getArtifactsDir(process.argv);
478
+ const artifactsDir = getArtifactsDir(argv);
448
479
  await mkdir(artifactsDir, { recursive: true });
449
480
  await writeCoreArtifacts(artifactsDir, {
450
481
  repo_manifest: repoManifest,
@@ -466,7 +497,7 @@ async function cmdAdvanceAudit(argv) {
466
497
  const root = getRootDir(argv);
467
498
  const artifactsDir = getArtifactsDir(argv);
468
499
  const sessionConfig = await loadSessionConfig(artifactsDir);
469
- const providerName = resolveFreshSessionProviderName(getFlag(argv, "--provider"), sessionConfig);
500
+ const providerName = resolveRunProviderName(argv, sessionConfig);
470
501
  const batchResultsDir = getBatchResultsDir(argv);
471
502
  if (batchResultsDir && getFlag(argv, "--results")) {
472
503
  throw new Error("Use either --results <file> or --batch-results <dir>, not both.");
@@ -532,13 +563,14 @@ async function cmdRunToCompletion(argv) {
532
563
  const root = getRootDir(argv);
533
564
  const artifactsDir = getArtifactsDir(argv);
534
565
  const sessionConfig = await loadSessionConfig(artifactsDir);
535
- const provider = createFreshSessionProvider(getFlag(argv, "--provider"), sessionConfig);
566
+ const explicitProvider = getExplicitProvider(argv);
567
+ const provider = createFreshSessionProvider(explicitProvider ?? LOCAL_SUBPROCESS_PROVIDER_NAME, sessionConfig);
536
568
  const uiMode = getUiMode(argv, sessionConfig.ui_mode ?? "headless");
537
569
  const maxRuns = getMaxRuns(argv);
538
570
  const agentBatchSize = getAgentBatchSize(argv, sessionConfig);
539
571
  const parallelWorkers = getParallelWorkers(argv, sessionConfig);
540
572
  const timeoutMs = getTimeoutMs(argv, sessionConfig);
541
- const selfCliPath = resolve(process.argv[1] ?? "");
573
+ const selfCliPath = resolve(argv[1] ?? process.argv[1] ?? "");
542
574
  await mkdir(artifactsDir, { recursive: true });
543
575
  await ensureSupervisorDirs(artifactsDir);
544
576
  const batchResultsDir = getBatchResultsDir(argv);
@@ -646,6 +678,8 @@ async function cmdRunToCompletion(argv) {
646
678
  ],
647
679
  audit_results_path: blockAuditResultsPath,
648
680
  pending_audit_tasks_path: blockPendingTasksPath,
681
+ timeout_ms: timeoutMs,
682
+ max_retries: 0,
649
683
  };
650
684
  const blockPrompt = renderWorkerPrompt(blockTask);
651
685
  await writeWorkerTaskFiles(blockTask, blockPrompt, blockPaths, artifactsDir, blockPendingTasks);
@@ -716,7 +750,9 @@ async function cmdRunToCompletion(argv) {
716
750
  worker_command: [process.execPath, selfCliPath, "worker-run", "--task", slotPaths.taskPath],
717
751
  audit_results_path: slotAuditResultsPath,
718
752
  pending_audit_tasks_path: slotPendingTasksPath,
719
- skip_worker_command: true,
753
+ worker_command_mode: "deferred",
754
+ timeout_ms: timeoutMs,
755
+ max_retries: 0,
720
756
  };
721
757
  const slotPrompt = renderWorkerPrompt(slotTask);
722
758
  await writeWorkerTaskFiles(slotTask, slotPrompt, slotPaths, artifactsDir, group);
@@ -888,6 +924,8 @@ async function cmdRunToCompletion(argv) {
888
924
  pending_audit_tasks_path: pendingAuditTasksPath,
889
925
  runtime_updates_path: runtimeUpdatesPath,
890
926
  external_analyzer_results_path: externalAnalyzerPath,
927
+ timeout_ms: timeoutMs,
928
+ max_retries: 0,
891
929
  };
892
930
  const prompt = renderWorkerPrompt(task);
893
931
  await writeWorkerTaskFiles(task, prompt, paths, artifactsDir, pendingAuditTasks);
@@ -1317,7 +1355,7 @@ async function main(argv) {
1317
1355
  const command = argv[2] ?? "sample-run";
1318
1356
  switch (command) {
1319
1357
  case "sample-run":
1320
- await runSample();
1358
+ await runSample(argv);
1321
1359
  return;
1322
1360
  case "advance-audit":
1323
1361
  await cmdAdvanceAudit(argv);
@@ -1367,7 +1405,19 @@ async function main(argv) {
1367
1405
  process.exitCode = 1;
1368
1406
  }
1369
1407
  }
1370
- await main(process.argv).catch((error) => {
1371
- console.error(error instanceof Error ? error.message : String(error));
1372
- process.exitCode = 1;
1373
- });
1408
+ export async function runCli(argv) {
1409
+ await main(argv).catch((error) => {
1410
+ console.error(error instanceof Error ? error.message : String(error));
1411
+ process.exitCode = 1;
1412
+ });
1413
+ }
1414
+ function isDirectCliExecution(argv) {
1415
+ const entryPath = argv[1];
1416
+ if (!entryPath) {
1417
+ return false;
1418
+ }
1419
+ return resolve(entryPath) === fileURLToPath(import.meta.url);
1420
+ }
1421
+ if (isDirectCliExecution(process.argv)) {
1422
+ await runCli(process.argv);
1423
+ }
@@ -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)),
@@ -1,32 +1,28 @@
1
+ import { normalizeExtractorPath } from "./pathPatterns.js";
2
+ const LANGUAGE_BY_EXTENSION = {
3
+ ts: "typescript",
4
+ tsx: "typescript",
5
+ mts: "typescript",
6
+ cts: "typescript",
7
+ js: "javascript",
8
+ jsx: "javascript",
9
+ mjs: "javascript",
10
+ cjs: "javascript",
11
+ py: "python",
12
+ go: "go",
13
+ rs: "rust",
14
+ java: "java",
15
+ cs: "csharp",
16
+ json: "json",
17
+ yml: "yaml",
18
+ yaml: "yaml",
19
+ md: "markdown",
20
+ };
1
21
  function inferLanguage(path) {
2
- const ext = path.split(".").pop()?.toLowerCase();
3
- switch (ext) {
4
- case "ts":
5
- case "tsx":
6
- return "typescript";
7
- case "js":
8
- case "jsx":
9
- return "javascript";
10
- case "py":
11
- return "python";
12
- case "go":
13
- return "go";
14
- case "rs":
15
- return "rust";
16
- case "java":
17
- return "java";
18
- case "cs":
19
- return "csharp";
20
- case "json":
21
- return "json";
22
- case "yml":
23
- case "yaml":
24
- return "yaml";
25
- case "md":
26
- return "markdown";
27
- default:
28
- return "unknown";
29
- }
22
+ const normalized = normalizeExtractorPath(path);
23
+ const base = normalized.split("/").pop() ?? normalized;
24
+ const extension = base.includes(".") ? base.split(".").pop() ?? "" : "";
25
+ return LANGUAGE_BY_EXTENSION[extension] ?? "unknown";
30
26
  }
31
27
  export function buildRepoManifest(repositoryName, files) {
32
28
  return {
@@ -2,4 +2,9 @@ import type { RepoManifest } from "../types.js";
2
2
  import type { FileDisposition } from "../types/disposition.js";
3
3
  import type { CriticalFlowManifest } from "../types/flows.js";
4
4
  import type { SurfaceManifest } from "../types/surfaces.js";
5
+ /**
6
+ * Builds coarse critical-flow coverage from shared path heuristics. These
7
+ * bootstrap flows are intentionally conservative and should be reviewed when a
8
+ * repo uses unconventional naming or layout conventions.
9
+ */
5
10
  export declare function buildCriticalFlowManifest(repoManifest: RepoManifest, surfaceManifest: SurfaceManifest, disposition?: FileDisposition): CriticalFlowManifest;