auditor-lambda 0.3.40 → 0.3.41

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 (148) hide show
  1. package/audit-code-wrapper-lib.mjs +20 -2
  2. package/dist/cli/args.d.ts +59 -0
  3. package/dist/cli/args.js +244 -0
  4. package/dist/cli/dispatch.d.ts +80 -0
  5. package/dist/cli/dispatch.js +528 -0
  6. package/dist/cli/prompts.d.ts +18 -0
  7. package/dist/cli/prompts.js +130 -0
  8. package/dist/cli/steps.d.ts +29 -0
  9. package/dist/cli/steps.js +30 -0
  10. package/dist/cli/waveManifest.d.ts +40 -0
  11. package/dist/cli/waveManifest.js +41 -0
  12. package/dist/cli/workerResult.d.ts +18 -0
  13. package/dist/cli/workerResult.js +42 -0
  14. package/dist/cli.d.ts +2 -22
  15. package/dist/cli.js +160 -973
  16. package/dist/extractors/browserExtension.d.ts +1 -3
  17. package/dist/extractors/browserExtension.js +2 -2
  18. package/dist/extractors/designAssessment.d.ts +1 -3
  19. package/dist/extractors/disposition.d.ts +2 -1
  20. package/dist/extractors/disposition.js +3 -0
  21. package/dist/extractors/flows.d.ts +1 -3
  22. package/dist/extractors/flows.js +2 -2
  23. package/dist/extractors/graph.d.ts +1 -2
  24. package/dist/extractors/graph.js +4 -326
  25. package/dist/extractors/graphManifestEdges.d.ts +1 -1
  26. package/dist/extractors/graphPathUtils.d.ts +1 -1
  27. package/dist/extractors/graphPythonImports.d.ts +3 -0
  28. package/dist/extractors/graphPythonImports.js +326 -0
  29. package/dist/extractors/risk.d.ts +1 -2
  30. package/dist/extractors/surfaces.d.ts +1 -3
  31. package/dist/extractors/surfaces.js +2 -2
  32. package/dist/io/artifacts.d.ts +1 -5
  33. package/dist/io/artifacts.js +1 -1
  34. package/dist/io/runArtifacts.js +1 -1
  35. package/dist/mcp/server.js +1 -1
  36. package/dist/orchestrator/advance.d.ts +1 -0
  37. package/dist/orchestrator/advance.js +8 -5
  38. package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
  39. package/dist/orchestrator/auditTaskUtils.js +27 -0
  40. package/dist/orchestrator/fileAnchors.d.ts +1 -1
  41. package/dist/orchestrator/fileIntegrity.d.ts +7 -0
  42. package/dist/orchestrator/fileIntegrity.js +41 -0
  43. package/dist/orchestrator/flowCoverage.d.ts +1 -1
  44. package/dist/orchestrator/flowPlanning.d.ts +1 -1
  45. package/dist/orchestrator/flowRequeue.d.ts +1 -1
  46. package/dist/orchestrator/internalExecutors.d.ts +3 -1
  47. package/dist/orchestrator/internalExecutors.js +23 -5
  48. package/dist/orchestrator/nextStep.d.ts +2 -1
  49. package/dist/orchestrator/nextStep.js +1 -1
  50. package/dist/orchestrator/planning.d.ts +1 -1
  51. package/dist/orchestrator/requeueCommand.d.ts +1 -1
  52. package/dist/orchestrator/reviewPackets.d.ts +1 -1
  53. package/dist/orchestrator/reviewPackets.js +21 -113
  54. package/dist/orchestrator/runtimeValidation.d.ts +1 -1
  55. package/dist/orchestrator/taskBuilder.d.ts +1 -1
  56. package/dist/orchestrator/taskBuilder.js +1 -12
  57. package/dist/orchestrator/unionFind.d.ts +7 -0
  58. package/dist/orchestrator/unionFind.js +32 -0
  59. package/dist/orchestrator/unitBuilder.d.ts +2 -2
  60. package/dist/orchestrator/unitBuilder.js +4 -18
  61. package/dist/prompts/renderWorkerPrompt.js +18 -1
  62. package/dist/providers/claudeCodeProvider.d.ts +4 -4
  63. package/dist/providers/claudeCodeProvider.js +9 -3
  64. package/dist/providers/constants.d.ts +1 -1
  65. package/dist/providers/constants.js +1 -1
  66. package/dist/providers/index.d.ts +1 -2
  67. package/dist/providers/index.js +5 -4
  68. package/dist/providers/localSubprocessProvider.d.ts +2 -2
  69. package/dist/providers/localSubprocessProvider.js +1 -1
  70. package/dist/providers/opencodeProvider.d.ts +4 -4
  71. package/dist/providers/opencodeProvider.js +7 -2
  72. package/dist/providers/spawnLoggedCommand.d.ts +3 -1
  73. package/dist/providers/spawnLoggedCommand.js +21 -0
  74. package/dist/providers/subprocessTemplateProvider.d.ts +4 -4
  75. package/dist/providers/subprocessTemplateProvider.js +8 -3
  76. package/dist/providers/vscodeTaskProvider.d.ts +3 -4
  77. package/dist/providers/vscodeTaskProvider.js +2 -2
  78. package/dist/quota/discoveredLimits.js +1 -1
  79. package/dist/quota/hostLimits.d.ts +1 -2
  80. package/dist/quota/hostLimits.js +4 -46
  81. package/dist/quota/index.d.ts +18 -15
  82. package/dist/quota/index.js +4 -9
  83. package/dist/quota/scheduler.d.ts +1 -3
  84. package/dist/quota/scheduler.js +1 -2
  85. package/dist/reporting/synthesis.d.ts +1 -2
  86. package/dist/reporting/synthesis.js +2 -0
  87. package/dist/reporting/workBlocks.d.ts +1 -2
  88. package/dist/supervisor/operatorHandoff.js +1 -1
  89. package/dist/supervisor/runLedger.d.ts +1 -1
  90. package/dist/supervisor/runLedger.js +2 -2
  91. package/dist/supervisor/sessionConfig.d.ts +1 -1
  92. package/dist/supervisor/sessionConfig.js +1 -3
  93. package/dist/types/reviewPlanning.d.ts +1 -1
  94. package/dist/types/workerSession.d.ts +6 -0
  95. package/dist/validation/artifacts.d.ts +1 -1
  96. package/dist/validation/artifacts.js +1 -1
  97. package/dist/validation/auditResults.d.ts +1 -1
  98. package/dist/validation/auditResults.js +1 -1
  99. package/dist/validation/sessionConfig.d.ts +2 -3
  100. package/dist/validation/sessionConfig.js +2 -3
  101. package/package.json +4 -2
  102. package/scripts/postinstall.mjs +0 -1
  103. package/dist/io/json.d.ts +0 -10
  104. package/dist/io/json.js +0 -142
  105. package/dist/providers/types.d.ts +0 -33
  106. package/dist/providers/types.js +0 -1
  107. package/dist/quota/compositeQuotaSource.d.ts +0 -7
  108. package/dist/quota/compositeQuotaSource.js +0 -20
  109. package/dist/quota/errorParsers/claudeCodeErrorParser.d.ts +0 -6
  110. package/dist/quota/errorParsers/claudeCodeErrorParser.js +0 -39
  111. package/dist/quota/errorParsers/genericErrorParser.d.ts +0 -9
  112. package/dist/quota/errorParsers/genericErrorParser.js +0 -7
  113. package/dist/quota/errorParsers/index.d.ts +0 -5
  114. package/dist/quota/errorParsers/index.js +0 -12
  115. package/dist/quota/errorParsing.d.ts +0 -7
  116. package/dist/quota/errorParsing.js +0 -69
  117. package/dist/quota/fileLock.d.ts +0 -6
  118. package/dist/quota/fileLock.js +0 -64
  119. package/dist/quota/learnedQuotaSource.d.ts +0 -7
  120. package/dist/quota/learnedQuotaSource.js +0 -25
  121. package/dist/quota/limits.d.ts +0 -16
  122. package/dist/quota/limits.js +0 -77
  123. package/dist/quota/quotaSource.d.ts +0 -12
  124. package/dist/quota/quotaSource.js +0 -1
  125. package/dist/quota/slidingWindow.d.ts +0 -4
  126. package/dist/quota/slidingWindow.js +0 -28
  127. package/dist/quota/state.d.ts +0 -15
  128. package/dist/quota/state.js +0 -148
  129. package/dist/quota/types.d.ts +0 -67
  130. package/dist/quota/types.js +0 -1
  131. package/dist/reporting/rootCause.d.ts +0 -10
  132. package/dist/reporting/rootCause.js +0 -146
  133. package/dist/types/disposition.d.ts +0 -9
  134. package/dist/types/disposition.js +0 -1
  135. package/dist/types/flows.d.ts +0 -17
  136. package/dist/types/flows.js +0 -1
  137. package/dist/types/graph.d.ts +0 -22
  138. package/dist/types/graph.js +0 -1
  139. package/dist/types/risk.d.ts +0 -9
  140. package/dist/types/risk.js +0 -1
  141. package/dist/types/runLedger.d.ts +0 -17
  142. package/dist/types/runLedger.js +0 -6
  143. package/dist/types/sessionConfig.d.ts +0 -79
  144. package/dist/types/sessionConfig.js +0 -15
  145. package/dist/types/surfaces.d.ts +0 -15
  146. package/dist/types/surfaces.js +0 -1
  147. package/dist/validation/basic.d.ts +0 -13
  148. package/dist/validation/basic.js +0 -46
@@ -1,7 +1,5 @@
1
1
  import type { Lens, RepoManifest } from "../types.js";
2
- import type { FileDisposition } from "../types/disposition.js";
3
- import type { GraphBundle, GraphEdge } from "../types/graph.js";
4
- import type { SurfaceRecord } from "../types/surfaces.js";
2
+ import type { FileDisposition, GraphBundle, GraphEdge, SurfaceRecord } from "@audit-tools/shared";
5
3
  export declare const BROWSER_EXTENSION_HEURISTIC_NOTE = "Chrome extension manifest and HTML asset references were resolved deterministically from local paths; verify unusual dynamic registration manually.";
6
4
  export declare function isBrowserExtensionManifestPath(path: string): boolean;
7
5
  export declare function extractChromeExtensionManifestEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
@@ -1,5 +1,5 @@
1
1
  import { posix } from "node:path";
2
- import { isAuditExcludedStatus } from "./disposition.js";
2
+ import { buildDispositionMap, isAuditExcludedStatus } from "./disposition.js";
3
3
  import { graphEdge, normalizeGraphPath, resolveCandidate, } from "./graphPathUtils.js";
4
4
  export const BROWSER_EXTENSION_HEURISTIC_NOTE = "Chrome extension manifest and HTML asset references were resolved deterministically from local paths; verify unusual dynamic registration manually.";
5
5
  const CHROME_EXTENSION_BACKGROUND_EDGE = "chrome-extension-background-link";
@@ -334,7 +334,7 @@ export function buildBrowserExtensionSurfacesFromGraph(graphBundle, disposition)
334
334
  const references = Array.isArray(graphBundle?.graphs.references)
335
335
  ? graphBundle.graphs.references
336
336
  : [];
337
- const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
337
+ const dispositionMap = buildDispositionMap(disposition);
338
338
  const surfaces = [];
339
339
  const seen = new Set();
340
340
  for (const edge of references) {
@@ -1,8 +1,6 @@
1
1
  import type { UnitManifest } from "../types.js";
2
+ import type { GraphBundle, CriticalFlowManifest, RiskRegister } from "@audit-tools/shared";
2
3
  import type { DesignAssessment } from "../types/designAssessment.js";
3
- import type { GraphBundle } from "../types/graph.js";
4
- import type { CriticalFlowManifest } from "../types/flows.js";
5
- import type { RiskRegister } from "../types/risk.js";
6
4
  export declare function buildDesignAssessment(params: {
7
5
  unitManifest: UnitManifest;
8
6
  graphBundle: GraphBundle;
@@ -1,8 +1,9 @@
1
1
  import type { RepoManifest } from "../types.js";
2
- import type { FileDisposition, FileDispositionStatus } from "../types/disposition.js";
2
+ import type { FileDisposition, FileDispositionStatus } from "@audit-tools/shared";
3
3
  /**
4
4
  * Applies shared path heuristics to mark files that should be excluded or
5
5
  * down-scoped before audit planning begins.
6
6
  */
7
7
  export declare function buildFileDisposition(repoManifest: RepoManifest): FileDisposition;
8
+ export declare function buildDispositionMap(disposition?: FileDisposition): Map<string, FileDispositionStatus>;
8
9
  export declare function isAuditExcludedStatus(status: FileDispositionStatus): boolean;
@@ -75,6 +75,9 @@ export function buildFileDisposition(repoManifest) {
75
75
  files: repoManifest.files.map((file) => inferDisposition(file.path)),
76
76
  };
77
77
  }
78
+ export function buildDispositionMap(disposition) {
79
+ return new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
80
+ }
78
81
  export function isAuditExcludedStatus(status) {
79
82
  return (status === "excluded" ||
80
83
  status === "generated" ||
@@ -1,7 +1,5 @@
1
1
  import type { RepoManifest } from "../types.js";
2
- import type { FileDisposition } from "../types/disposition.js";
3
- import type { CriticalFlowManifest } from "../types/flows.js";
4
- import type { SurfaceManifest } from "../types/surfaces.js";
2
+ import type { FileDisposition, CriticalFlowManifest, SurfaceManifest } from "@audit-tools/shared";
5
3
  /**
6
4
  * Builds coarse critical-flow coverage from shared path heuristics. These
7
5
  * bootstrap flows are intentionally conservative and should be reviewed when a
@@ -1,4 +1,4 @@
1
- import { isAuditExcludedStatus } from "./disposition.js";
1
+ import { buildDispositionMap, isAuditExcludedStatus } from "./disposition.js";
2
2
  import { EXTRACTOR_HEURISTIC_NOTE, isAsyncTaskPath, isBillingPath, isIdentityPath, isSecuritySensitivePath, isTestPath, isDataLayerPath, isConcurrencyPath, isInterfacePath, isDeploymentConfigPath, normalizeExtractorPath, } from "./pathPatterns.js";
3
3
  function inferConcerns(paths) {
4
4
  const concerns = new Set();
@@ -65,7 +65,7 @@ function dedupeFlows(flows) {
65
65
  * repo uses unconventional naming or layout conventions.
66
66
  */
67
67
  export function buildCriticalFlowManifest(repoManifest, surfaceManifest, disposition) {
68
- const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
68
+ const dispositionMap = buildDispositionMap(disposition);
69
69
  const availablePaths = repoManifest.files
70
70
  .map((file) => file.path)
71
71
  .filter((path) => {
@@ -1,7 +1,6 @@
1
1
  import type { RepoManifest } from "../types.js";
2
- import type { FileDisposition } from "../types/disposition.js";
2
+ import type { FileDisposition, GraphBundle } from "@audit-tools/shared";
3
3
  import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
4
- import type { GraphBundle } from "../types/graph.js";
5
4
  export interface BuildGraphBundleOptions {
6
5
  fileContents?: Record<string, string>;
7
6
  externalAnalyzerResults?: ExternalAnalyzerResults;
@@ -1,10 +1,11 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { isAbsolute, relative, resolve } from "node:path";
3
3
  import { posix } from "node:path";
4
- import { isAuditExcludedStatus } from "./disposition.js";
4
+ import { buildDispositionMap, isAuditExcludedStatus } from "./disposition.js";
5
5
  import { extractChromeExtensionManifestEdges, extractHtmlResourceEdges, } from "./browserExtension.js";
6
6
  import { extractCargoWorkspaceMemberEdges, extractGoWorkspaceModuleEdges, extractMavenModuleEdges, extractPackageEntrypointEdges, extractPackageScriptEdges, extractPyprojectTestpathLinks, extractTypescriptProjectReferenceEdges, extractWorkspacePackageEdges, extractYamlPathReferenceEdges, isCargoManifestPath, isGoWorkspaceManifestPath, isMavenPomPath, isPyprojectPath, } from "./graphManifestEdges.js";
7
7
  import { graphEdge, graphLookupKey, normalizeGraphPath, resolveCandidate, } from "./graphPathUtils.js";
8
+ import { extractPythonImportEdges, isPythonSourcePath, } from "./graphPythonImports.js";
8
9
  import { isTestPath, normalizeExtractorPath } from "./pathPatterns.js";
9
10
  const MAX_GRAPH_SOURCE_BYTES = 512 * 1024;
10
11
  const SOURCE_LANGUAGES = new Set([
@@ -40,8 +41,6 @@ const SOURCE_EXTENSIONS = [
40
41
  ".java",
41
42
  ".cs",
42
43
  ];
43
- const PYTHON_SOURCE_EXTENSIONS = [".py", ".pyi"];
44
- const PYTHON_PACKAGE_INDEX_FILES = ["__init__.py", "__init__.pyi"];
45
44
  const TYPESCRIPT_TYPE_CONTRACT_EXTENSIONS = [
46
45
  ".ts",
47
46
  ".tsx",
@@ -339,327 +338,6 @@ function extractImportBindings(fromPath, content, pathLookup) {
339
338
  }
340
339
  return bindings;
341
340
  }
342
- function isPythonSourcePath(path) {
343
- const normalized = normalizeGraphPath(path).toLowerCase();
344
- return PYTHON_SOURCE_EXTENSIONS.some((extension) => normalized.endsWith(extension));
345
- }
346
- function stripPythonLineComment(line) {
347
- let quote;
348
- let escaped = false;
349
- for (let index = 0; index < line.length; index++) {
350
- const char = line[index];
351
- if (escaped) {
352
- escaped = false;
353
- continue;
354
- }
355
- if (quote) {
356
- if (char === "\\") {
357
- escaped = true;
358
- continue;
359
- }
360
- if (char === quote) {
361
- quote = undefined;
362
- }
363
- continue;
364
- }
365
- if (char === "'" || char === '"') {
366
- quote = char;
367
- continue;
368
- }
369
- if (char === "#") {
370
- return line.slice(0, index);
371
- }
372
- }
373
- return line;
374
- }
375
- function pythonParenDelta(line) {
376
- let quote;
377
- let escaped = false;
378
- let delta = 0;
379
- for (const char of line) {
380
- if (escaped) {
381
- escaped = false;
382
- continue;
383
- }
384
- if (quote) {
385
- if (char === "\\") {
386
- escaped = true;
387
- continue;
388
- }
389
- if (char === quote) {
390
- quote = undefined;
391
- }
392
- continue;
393
- }
394
- if (char === "'" || char === '"') {
395
- quote = char;
396
- continue;
397
- }
398
- if (char === "(") {
399
- delta += 1;
400
- }
401
- else if (char === ")") {
402
- delta -= 1;
403
- }
404
- }
405
- return delta;
406
- }
407
- function pythonLogicalLines(content) {
408
- const logicalLines = [];
409
- let pending = "";
410
- let parenDepth = 0;
411
- for (const rawLine of content.split(/\r?\n/)) {
412
- const stripped = stripPythonLineComment(rawLine).trim();
413
- if (stripped.length === 0) {
414
- continue;
415
- }
416
- if (pending.length === 0 && !/^(?:import|from)\s+/i.test(stripped)) {
417
- continue;
418
- }
419
- const continued = stripped.endsWith("\\");
420
- const line = continued ? stripped.slice(0, -1).trimEnd() : stripped;
421
- pending = pending.length > 0 ? `${pending} ${line}` : line;
422
- parenDepth += pythonParenDelta(line);
423
- if (!continued && parenDepth <= 0) {
424
- logicalLines.push(pending.replace(/\s+/g, " ").trim());
425
- pending = "";
426
- parenDepth = 0;
427
- }
428
- }
429
- if (pending.length > 0) {
430
- logicalLines.push(pending.replace(/\s+/g, " ").trim());
431
- }
432
- return logicalLines;
433
- }
434
- function unwrapPythonImportList(value) {
435
- let trimmed = value.trim();
436
- if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
437
- trimmed = trimmed.slice(1, -1).trim();
438
- }
439
- return trimmed;
440
- }
441
- function splitPythonImportList(value) {
442
- const items = [];
443
- let current = "";
444
- let quote;
445
- let escaped = false;
446
- let parenDepth = 0;
447
- for (const char of unwrapPythonImportList(value)) {
448
- if (escaped) {
449
- current += char;
450
- escaped = false;
451
- continue;
452
- }
453
- if (quote) {
454
- current += char;
455
- if (char === "\\") {
456
- escaped = true;
457
- }
458
- else if (char === quote) {
459
- quote = undefined;
460
- }
461
- continue;
462
- }
463
- if (char === "'" || char === '"') {
464
- current += char;
465
- quote = char;
466
- continue;
467
- }
468
- if (char === "(") {
469
- parenDepth += 1;
470
- current += char;
471
- continue;
472
- }
473
- if (char === ")") {
474
- parenDepth -= 1;
475
- current += char;
476
- continue;
477
- }
478
- if (char === "," && parenDepth === 0) {
479
- const item = current.trim();
480
- if (item.length > 0) {
481
- items.push(item);
482
- }
483
- current = "";
484
- continue;
485
- }
486
- current += char;
487
- }
488
- const item = current.trim();
489
- if (item.length > 0) {
490
- items.push(item);
491
- }
492
- return items;
493
- }
494
- function stripPythonAlias(value) {
495
- return value.replace(/\s+as\s+[A-Za-z_]\w*$/i, "").trim();
496
- }
497
- function isPythonIdentifier(value) {
498
- return /^[A-Za-z_]\w*$/.test(value);
499
- }
500
- function isPythonAbsoluteModuleSpecifier(value) {
501
- return /^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/.test(value);
502
- }
503
- function isPythonRelativeModuleSpecifier(value) {
504
- return /^\.+(?:[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)?$/.test(value);
505
- }
506
- function isPythonModuleSpecifier(value) {
507
- return (isPythonAbsoluteModuleSpecifier(value) ||
508
- isPythonRelativeModuleSpecifier(value));
509
- }
510
- function pythonModulePath(specifier) {
511
- return specifier.split(".").filter(Boolean).join("/");
512
- }
513
- function resolvePythonPathCandidate(candidate, pathLookup) {
514
- const normalized = normalizeGraphPath(candidate).replace(/\/+$/, "");
515
- if (normalized.length === 0 || normalized === "." || normalized === "..") {
516
- return undefined;
517
- }
518
- return resolveCandidate(normalized, pathLookup);
519
- }
520
- function pythonPathMatchesModule(path, modulePath) {
521
- const normalizedPath = normalizeGraphPath(path).toLowerCase();
522
- const normalizedModulePath = normalizeGraphPath(modulePath).toLowerCase();
523
- return (PYTHON_SOURCE_EXTENSIONS.some((extension) => {
524
- const moduleFile = `${normalizedModulePath}${extension}`;
525
- return (normalizedPath === moduleFile ||
526
- normalizedPath.endsWith(`/${moduleFile}`));
527
- }) ||
528
- PYTHON_PACKAGE_INDEX_FILES.some((indexFile) => {
529
- const packageFile = posix.join(normalizedModulePath, indexFile);
530
- return (normalizedPath === packageFile ||
531
- normalizedPath.endsWith(`/${packageFile}`));
532
- }));
533
- }
534
- function commonDirectoryPrefixLength(left, right) {
535
- const leftParts = normalizeGraphPath(left).split("/").filter(Boolean);
536
- const rightParts = normalizeGraphPath(right).split("/").filter(Boolean);
537
- let count = 0;
538
- while (count < leftParts.length &&
539
- count < rightParts.length &&
540
- leftParts[count].toLowerCase() === rightParts[count].toLowerCase()) {
541
- count += 1;
542
- }
543
- return count;
544
- }
545
- function resolvePythonAbsoluteModuleSpecifier(fromPath, specifier, pathLookup) {
546
- const modulePath = pythonModulePath(specifier);
547
- const direct = resolvePythonPathCandidate(modulePath, pathLookup);
548
- if (direct) {
549
- return direct;
550
- }
551
- const matches = [...new Set(pathLookup.values())].filter((path) => isPythonSourcePath(path) && pythonPathMatchesModule(path, modulePath));
552
- if (matches.length === 1) {
553
- return matches[0];
554
- }
555
- if (matches.length === 0) {
556
- return undefined;
557
- }
558
- const fromDir = posix.dirname(normalizeGraphPath(fromPath));
559
- const scored = matches
560
- .map((target) => ({
561
- target,
562
- score: commonDirectoryPrefixLength(fromDir, posix.dirname(normalizeGraphPath(target))),
563
- }))
564
- .sort((a, b) => b.score - a.score || a.target.localeCompare(b.target));
565
- const bestScore = scored[0]?.score ?? 0;
566
- const bestMatches = scored.filter((item) => item.score === bestScore);
567
- if (bestScore > 0 && bestMatches.length === 1) {
568
- return bestMatches[0].target;
569
- }
570
- const srcMatches = matches.filter((target) => normalizeGraphPath(target).toLowerCase().startsWith("src/"));
571
- return srcMatches.length === 1 ? srcMatches[0] : undefined;
572
- }
573
- function resolvePythonRelativeModuleSpecifier(fromPath, specifier, pathLookup) {
574
- const match = /^(\.+)(.*)$/.exec(specifier);
575
- if (!match) {
576
- return undefined;
577
- }
578
- const level = match[1].length;
579
- const remainder = match[2] ?? "";
580
- let baseDir = posix.dirname(normalizeGraphPath(fromPath));
581
- for (let index = 1; index < level; index++) {
582
- const next = posix.dirname(baseDir);
583
- if (next === baseDir) {
584
- return undefined;
585
- }
586
- baseDir = next;
587
- }
588
- const modulePath = pythonModulePath(remainder);
589
- const candidate = modulePath.length > 0 ? posix.join(baseDir, modulePath) : baseDir;
590
- return resolvePythonPathCandidate(candidate, pathLookup);
591
- }
592
- function resolvePythonModuleSpecifier(fromPath, specifier, pathLookup) {
593
- if (isPythonRelativeModuleSpecifier(specifier)) {
594
- return resolvePythonRelativeModuleSpecifier(fromPath, specifier, pathLookup);
595
- }
596
- if (isPythonAbsoluteModuleSpecifier(specifier)) {
597
- return resolvePythonAbsoluteModuleSpecifier(fromPath, specifier, pathLookup);
598
- }
599
- return undefined;
600
- }
601
- function appendPythonImportedSpecifier(moduleSpecifier, importedName) {
602
- return moduleSpecifier.endsWith(".")
603
- ? `${moduleSpecifier}${importedName}`
604
- : `${moduleSpecifier}.${importedName}`;
605
- }
606
- function addPythonImportEdge(edges, fromPath, target, kind, specifier) {
607
- if (!target || target === fromPath) {
608
- return;
609
- }
610
- edges.push(graphEdge({
611
- from: fromPath,
612
- to: target,
613
- kind,
614
- confidence: IMPORT_EDGE_CONFIDENCE,
615
- reason: `Resolved Python import specifier '${specifier}'.`,
616
- }));
617
- }
618
- function extractPythonImportEdges(fromPath, content, pathLookup) {
619
- if (!isPythonSourcePath(fromPath)) {
620
- return [];
621
- }
622
- const edges = [];
623
- for (const line of pythonLogicalLines(content)) {
624
- const importMatch = /^import\s+(.+)$/i.exec(line);
625
- if (importMatch) {
626
- for (const rawSpecifier of splitPythonImportList(importMatch[1] ?? "")) {
627
- const specifier = stripPythonAlias(rawSpecifier);
628
- if (!isPythonAbsoluteModuleSpecifier(specifier)) {
629
- continue;
630
- }
631
- addPythonImportEdge(edges, fromPath, resolvePythonModuleSpecifier(fromPath, specifier, pathLookup), "python-import", specifier);
632
- }
633
- continue;
634
- }
635
- const fromImportMatch = /^from\s+([.\w]+)\s+import\s+(.+)$/i.exec(line);
636
- if (!fromImportMatch) {
637
- continue;
638
- }
639
- const moduleSpecifier = fromImportMatch[1] ?? "";
640
- if (!isPythonModuleSpecifier(moduleSpecifier)) {
641
- continue;
642
- }
643
- const importedNames = splitPythonImportList(fromImportMatch[2] ?? "")
644
- .map(stripPythonAlias)
645
- .filter((name) => name !== "*" && isPythonIdentifier(name));
646
- const submoduleTargets = importedNames
647
- .map((name) => appendPythonImportedSpecifier(moduleSpecifier, name))
648
- .map((specifier) => ({
649
- specifier,
650
- target: resolvePythonModuleSpecifier(fromPath, specifier, pathLookup),
651
- }))
652
- .filter((item) => item.target);
653
- if (submoduleTargets.length > 0) {
654
- for (const { specifier, target } of submoduleTargets) {
655
- addPythonImportEdge(edges, fromPath, target, "python-from-import", specifier);
656
- }
657
- continue;
658
- }
659
- addPythonImportEdge(edges, fromPath, resolvePythonModuleSpecifier(fromPath, moduleSpecifier, pathLookup), "python-from-import", moduleSpecifier);
660
- }
661
- return edges;
662
- }
663
341
  function extractImportEdges(fromPath, content, pathLookup) {
664
342
  const edges = [];
665
343
  for (const { pattern, kind } of IMPORT_PATTERNS) {
@@ -1239,7 +917,7 @@ function extractPytestConftestLinks(pathLookup) {
1239
917
  }
1240
918
  export async function buildGraphBundleFromFs(repoManifest, root, disposition, options = {}) {
1241
919
  const rootPath = resolve(root);
1242
- const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
920
+ const dispositionMap = buildDispositionMap(disposition);
1243
921
  const fileContents = {};
1244
922
  await Promise.all(repoManifest.files.map(async (file) => {
1245
923
  const status = dispositionMap.get(file.path);
@@ -1267,7 +945,7 @@ export function buildGraphBundle(repoManifest, disposition, options = {}) {
1267
945
  const calls = [];
1268
946
  const references = [];
1269
947
  const routes = [];
1270
- const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
948
+ const dispositionMap = buildDispositionMap(disposition);
1271
949
  const pathLookup = buildPathLookup(repoManifest, dispositionMap);
1272
950
  for (const file of repoManifest.files) {
1273
951
  const status = dispositionMap.get(file.path);
@@ -1,4 +1,4 @@
1
- import type { GraphEdge } from "../types/graph.js";
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
2
  export declare function extractPackageEntrypointEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
3
3
  export declare function extractPackageScriptEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
4
4
  export declare function isGoWorkspaceManifestPath(path: string): boolean;
@@ -1,4 +1,4 @@
1
- import type { GraphEdge } from "../types/graph.js";
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
2
  export declare function normalizeGraphPath(path: string): string;
3
3
  export declare function graphLookupKey(path: string): string;
4
4
  export declare function resolveCandidate(candidate: string, pathLookup: Map<string, string>): string | undefined;
@@ -0,0 +1,3 @@
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
+ export declare function isPythonSourcePath(path: string): boolean;
3
+ export declare function extractPythonImportEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];