auditor-lambda 0.10.2 → 0.10.7

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 (186) hide show
  1. package/audit-code-wrapper-build.mjs +198 -0
  2. package/audit-code-wrapper-install-hosts.mjs +1140 -0
  3. package/audit-code-wrapper-io.mjs +155 -0
  4. package/audit-code-wrapper-legacy.mjs +125 -0
  5. package/audit-code-wrapper-lib.mjs +17 -1801
  6. package/audit-code-wrapper-opencode.mjs +256 -0
  7. package/dispatch/merge-results.mjs +5 -3
  8. package/dispatch/validate-result.mjs +2 -2
  9. package/dist/adapters/coverageSummary.js +6 -2
  10. package/dist/adapters/normalizeExternal.js +16 -1
  11. package/dist/adapters/npmAudit.js +20 -9
  12. package/dist/adapters/semgrep.js +26 -1
  13. package/dist/cli/advanceAuditCommand.d.ts +1 -0
  14. package/dist/cli/advanceAuditCommand.js +95 -0
  15. package/dist/cli/args.js +1 -2
  16. package/dist/cli/auditStep.js +2 -2
  17. package/dist/cli/cleanup.d.ts +11 -1
  18. package/dist/cli/cleanup.js +25 -5
  19. package/dist/cli/cleanupCommand.d.ts +1 -0
  20. package/dist/cli/cleanupCommand.js +24 -0
  21. package/dist/cli/dispatch.d.ts +55 -31
  22. package/dist/cli/dispatch.js +298 -241
  23. package/dist/cli/dispatchStatusCommand.d.ts +1 -0
  24. package/dist/cli/dispatchStatusCommand.js +68 -0
  25. package/dist/cli/explainTaskCommand.d.ts +1 -0
  26. package/dist/cli/explainTaskCommand.js +33 -0
  27. package/dist/cli/importExternalAnalyzerCommand.d.ts +1 -0
  28. package/dist/cli/importExternalAnalyzerCommand.js +20 -0
  29. package/dist/cli/ingestResultsCommand.d.ts +1 -0
  30. package/dist/cli/ingestResultsCommand.js +34 -0
  31. package/dist/cli/intakeCommand.d.ts +1 -0
  32. package/dist/cli/intakeCommand.js +17 -0
  33. package/dist/cli/lineIndex.js +19 -12
  34. package/dist/cli/mergeAndIngestCommand.js +68 -26
  35. package/dist/cli/nextStepCommand.d.ts +139 -0
  36. package/dist/cli/nextStepCommand.js +281 -232
  37. package/dist/cli/planCommand.d.ts +1 -0
  38. package/dist/cli/planCommand.js +16 -0
  39. package/dist/cli/prepareDispatchCommand.d.ts +1 -0
  40. package/dist/cli/prepareDispatchCommand.js +25 -0
  41. package/dist/cli/quotaCommand.d.ts +1 -0
  42. package/dist/cli/quotaCommand.js +56 -0
  43. package/dist/cli/requeueCommand.d.ts +1 -0
  44. package/dist/cli/requeueCommand.js +10 -0
  45. package/dist/cli/runToCompletion.js +451 -412
  46. package/dist/cli/sampleRunCommand.d.ts +1 -0
  47. package/dist/cli/sampleRunCommand.js +93 -0
  48. package/dist/cli/statusCommand.js +1 -1
  49. package/dist/cli/steps.js +4 -1
  50. package/dist/cli/submitPacketCommand.js +16 -15
  51. package/dist/cli/synthesizeCommand.d.ts +1 -0
  52. package/dist/cli/synthesizeCommand.js +15 -0
  53. package/dist/cli/updateRuntimeValidationCommand.d.ts +1 -0
  54. package/dist/cli/updateRuntimeValidationCommand.js +16 -0
  55. package/dist/cli/validateCommand.d.ts +1 -0
  56. package/dist/cli/validateCommand.js +41 -0
  57. package/dist/cli/validateResultCommand.d.ts +1 -0
  58. package/dist/cli/validateResultCommand.js +63 -0
  59. package/dist/cli/validateResultsCommand.d.ts +1 -0
  60. package/dist/cli/validateResultsCommand.js +31 -0
  61. package/dist/cli/workerRunCommand.d.ts +15 -1
  62. package/dist/cli/workerRunCommand.js +40 -4
  63. package/dist/cli.d.ts +3 -2
  64. package/dist/cli.js +21 -628
  65. package/dist/coverage.js +7 -3
  66. package/dist/extractors/analyzers/css.js +2 -2
  67. package/dist/extractors/analyzers/html.js +2 -2
  68. package/dist/extractors/analyzers/python.js +2 -2
  69. package/dist/extractors/analyzers/registry.js +17 -36
  70. package/dist/extractors/analyzers/treeSitter.d.ts +10 -1
  71. package/dist/extractors/analyzers/treeSitter.js +28 -6
  72. package/dist/extractors/analyzers/typescript.js +104 -85
  73. package/dist/extractors/browserExtension.js +4 -1
  74. package/dist/extractors/designAssessment.js +21 -21
  75. package/dist/extractors/fsIntake.js +34 -10
  76. package/dist/extractors/graph.js +17 -7
  77. package/dist/extractors/graphManifestEdges/cargo.d.ts +4 -0
  78. package/dist/extractors/graphManifestEdges/cargo.js +107 -0
  79. package/dist/extractors/graphManifestEdges/go.d.ts +5 -0
  80. package/dist/extractors/graphManifestEdges/go.js +151 -0
  81. package/dist/extractors/graphManifestEdges/index.d.ts +8 -0
  82. package/dist/extractors/graphManifestEdges/index.js +11 -0
  83. package/dist/extractors/graphManifestEdges/jsonc.d.ts +3 -0
  84. package/dist/extractors/graphManifestEdges/jsonc.js +97 -0
  85. package/dist/extractors/graphManifestEdges/maven.d.ts +3 -0
  86. package/dist/extractors/graphManifestEdges/maven.js +73 -0
  87. package/dist/extractors/graphManifestEdges/packageJson.d.ts +19 -0
  88. package/dist/extractors/graphManifestEdges/packageJson.js +204 -0
  89. package/dist/extractors/graphManifestEdges/pnpm.d.ts +2 -0
  90. package/dist/extractors/graphManifestEdges/pnpm.js +42 -0
  91. package/dist/extractors/graphManifestEdges/pyproject.d.ts +3 -0
  92. package/dist/extractors/graphManifestEdges/pyproject.js +83 -0
  93. package/dist/extractors/graphManifestEdges/toml.d.ts +4 -0
  94. package/dist/extractors/graphManifestEdges/toml.js +68 -0
  95. package/dist/extractors/graphManifestEdges/typescript.d.ts +3 -0
  96. package/dist/extractors/graphManifestEdges/typescript.js +56 -0
  97. package/dist/extractors/graphManifestEdges/workspace.d.ts +10 -0
  98. package/dist/extractors/graphManifestEdges/workspace.js +72 -0
  99. package/dist/extractors/graphManifestEdges/yaml.d.ts +3 -0
  100. package/dist/extractors/graphManifestEdges/yaml.js +59 -0
  101. package/dist/extractors/graphManifestEdges/yamlPaths.d.ts +4 -0
  102. package/dist/extractors/graphManifestEdges/yamlPaths.js +89 -0
  103. package/dist/extractors/graphPythonImports.js +4 -20
  104. package/dist/extractors/pathPatterns.js +3 -13
  105. package/dist/io/artifacts.d.ts +1 -1
  106. package/dist/io/artifacts.js +4 -1
  107. package/dist/io/runArtifacts.d.ts +8 -2
  108. package/dist/io/runArtifacts.js +103 -69
  109. package/dist/io/toolingManifest.js +2 -1
  110. package/dist/orchestrator/advance.js +36 -0
  111. package/dist/orchestrator/artifactFreshness.d.ts +1 -1
  112. package/dist/orchestrator/artifactFreshness.js +1 -1
  113. package/dist/orchestrator/artifactMetadata.js +5 -5
  114. package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
  115. package/dist/orchestrator/auditTaskUtils.js +8 -12
  116. package/dist/orchestrator/autoFixExecutor.js +40 -26
  117. package/dist/orchestrator/dependencyMap.js +1 -1
  118. package/dist/orchestrator/executorResult.d.ts +33 -0
  119. package/dist/orchestrator/executors.d.ts +7 -0
  120. package/dist/orchestrator/executors.js +24 -0
  121. package/dist/orchestrator/fileAnchors.js +42 -29
  122. package/dist/orchestrator/fileIntegrity.js +6 -1
  123. package/dist/orchestrator/flowCoverage.js +1 -2
  124. package/dist/orchestrator/flowPlanning.js +8 -4
  125. package/dist/orchestrator/graphEnrichmentExecutor.js +67 -45
  126. package/dist/orchestrator/ingestionExecutors.js +9 -1
  127. package/dist/orchestrator/intakeExecutors.d.ts +0 -4
  128. package/dist/orchestrator/intakeExecutors.js +24 -14
  129. package/dist/orchestrator/localCommands.d.ts +1 -0
  130. package/dist/orchestrator/localCommands.js +10 -17
  131. package/dist/orchestrator/nextStep.js +3 -1
  132. package/dist/orchestrator/requeueCommand.js +4 -0
  133. package/dist/orchestrator/reviewPacketGraph.js +50 -18
  134. package/dist/orchestrator/reviewPackets.js +10 -8
  135. package/dist/orchestrator/runtimeCommand.js +35 -7
  136. package/dist/orchestrator/runtimeValidationUpdate.js +6 -0
  137. package/dist/orchestrator/selectiveDeepening/highRiskClean.js +3 -2
  138. package/dist/orchestrator/selectiveDeepening/lensVerification.js +44 -18
  139. package/dist/orchestrator/staleness.js +3 -3
  140. package/dist/orchestrator/state.js +1 -1
  141. package/dist/orchestrator/syntaxResolutionExecutor.js +17 -24
  142. package/dist/orchestrator/synthesisExecutors.js +1 -0
  143. package/dist/orchestrator/taskBuilder.js +5 -4
  144. package/dist/providers/claudeCodeProvider.js +4 -1
  145. package/dist/providers/opencodeProvider.js +4 -1
  146. package/dist/quota/discoveredLimits.js +3 -3
  147. package/dist/quota/headerExtraction.js +5 -2
  148. package/dist/quota/headerExtractors/claudeCodeHeaderExtractor.js +3 -0
  149. package/dist/quota/headerExtractors/index.js +3 -3
  150. package/dist/quota/index.d.ts +3 -1
  151. package/dist/quota/index.js +3 -0
  152. package/dist/reporting/findingIdentity.d.ts +21 -0
  153. package/dist/reporting/findingIdentity.js +72 -0
  154. package/dist/reporting/findingRanks.d.ts +3 -0
  155. package/dist/reporting/findingRanks.js +24 -0
  156. package/dist/reporting/mergeFindings.js +1 -24
  157. package/dist/reporting/synthesis.d.ts +3 -1
  158. package/dist/reporting/synthesis.js +36 -7
  159. package/dist/reporting/synthesisNarrativePrompt.js +3 -0
  160. package/dist/reporting/workBlocks.js +1 -14
  161. package/dist/supervisor/operatorHandoff.js +2 -6
  162. package/dist/supervisor/runLedger.js +30 -41
  163. package/dist/types/activeDispatch.d.ts +31 -0
  164. package/dist/types/activeDispatch.js +2 -0
  165. package/dist/types.d.ts +21 -4
  166. package/dist/types.js +24 -16
  167. package/dist/validation/artifacts.js +3 -0
  168. package/dist/validation/auditResults.js +8 -2
  169. package/package.json +2 -2
  170. package/schemas/audit_findings.schema.json +5 -1
  171. package/schemas/audit_plan_metrics.schema.json +1 -1
  172. package/schemas/audit_result.schema.json +5 -6
  173. package/schemas/audit_task.schema.json +1 -4
  174. package/schemas/blind_spot_register.schema.json +1 -1
  175. package/schemas/coverage_matrix.schema.json +2 -8
  176. package/schemas/finding.schema.json +3 -17
  177. package/schemas/flow_coverage.schema.json +2 -8
  178. package/schemas/graph_bundle.schema.json +31 -0
  179. package/schemas/lens.schema.json +7 -0
  180. package/schemas/review_packets.schema.json +6 -17
  181. package/schemas/step_contract.schema.json +8 -2
  182. package/schemas/unit_manifest.schema.json +1 -4
  183. package/scripts/postinstall.mjs +3 -1
  184. package/skills/audit-code/audit-code.prompt.md +2 -3
  185. package/dist/extractors/graphManifestEdges.d.ts +0 -12
  186. package/dist/extractors/graphManifestEdges.js +0 -1135
@@ -3,7 +3,7 @@ import { isAbsolute, relative, resolve } from "node:path";
3
3
  import { posix } from "node:path";
4
4
  import { buildDispositionMap, isAuditExcludedStatus } from "./disposition.js";
5
5
  import { extractChromeExtensionManifestEdges, extractHtmlResourceEdges, } from "./browserExtension.js";
6
- import { extractCargoWorkspaceMemberEdges, extractGoWorkspaceModuleEdges, extractMavenModuleEdges, extractPackageEntrypointEdges, extractPackageScriptEdges, extractPyprojectTestpathLinks, extractTypescriptProjectReferenceEdges, extractWorkspacePackageEdges, extractYamlPathReferenceEdges, isCargoManifestPath, isGoWorkspaceManifestPath, isMavenPomPath, isPyprojectPath, } from "./graphManifestEdges.js";
6
+ import { extractCargoWorkspaceMemberEdges, extractGoWorkspaceModuleEdges, extractMavenModuleEdges, extractPackageEntrypointEdges, extractPackageScriptEdges, extractPyprojectTestpathLinks, extractTypescriptProjectReferenceEdges, extractWorkspacePackageEdges, extractYamlPathReferenceEdges, isCargoManifestPath, isGoWorkspaceManifestPath, isMavenPomPath, isPyprojectPath, } from "./graphManifestEdges/index.js";
7
7
  import { graphEdge, graphLookupKey, isPytestConftestPath, normalizeGraphPath, resolveCandidate, resolveReferenceLiteral, resolveSpecifier, SOURCE_EXTENSIONS, STRING_LITERAL_PATTERN, } from "./graphPathUtils.js";
8
8
  import { extractPythonImportEdges } from "./graphPythonImports.js";
9
9
  import { isTestPath, normalizeExtractorPath } from "./pathPatterns.js";
@@ -307,12 +307,13 @@ export async function buildGraphBundleFromFs(repoManifest, root, disposition, op
307
307
  * its top-two-segment module root, suggesting shared module ownership.
308
308
  */
309
309
  function extractHeuristicContainerEdges(filePath) {
310
- const parts = filePath.split("/");
310
+ const normalizedPath = normalizeGraphPath(filePath);
311
+ const parts = normalizedPath.split("/");
311
312
  if (parts.length <= 2)
312
313
  return [];
313
314
  return [
314
315
  graphEdge({
315
- from: filePath,
316
+ from: normalizedPath,
316
317
  to: `${parts[0]}/${parts[1]}`,
317
318
  kind: EDGE_KIND.heuristicContainer,
318
319
  direction: "undirected",
@@ -389,9 +390,15 @@ function logGraphExtractionMetric(graphs) {
389
390
  const edgeCount = graphs.imports.length +
390
391
  graphs.calls.length +
391
392
  graphs.references.length +
392
- graphs.routes.length;
393
+ graphs.routes.length +
394
+ graphs.heuristics.length;
393
395
  const nodes = new Set();
394
- for (const edge of [...graphs.imports, ...graphs.calls, ...graphs.references]) {
396
+ for (const edge of [
397
+ ...graphs.imports,
398
+ ...graphs.calls,
399
+ ...graphs.references,
400
+ ...graphs.heuristics,
401
+ ]) {
395
402
  nodes.add(edge.from);
396
403
  nodes.add(edge.to);
397
404
  }
@@ -404,6 +411,7 @@ function logGraphExtractionMetric(graphs) {
404
411
  graphs.calls,
405
412
  graphs.references,
406
413
  graphs.routes,
414
+ graphs.heuristics,
407
415
  ].filter((edges) => edges.length > 0).length;
408
416
  process.stderr.write(`[audit-code] graph: built bundle — ${nodes.size} nodes, ${edgeCount} edges across ${graphTypeCount} graph type(s)\n`);
409
417
  }
@@ -413,6 +421,7 @@ export function buildGraphBundle(repoManifest, disposition, options = {}) {
413
421
  calls: [],
414
422
  references: [],
415
423
  routes: [],
424
+ heuristics: [],
416
425
  };
417
426
  const dispositionMap = buildDispositionMap(disposition);
418
427
  const pathLookup = buildPathLookup(repoManifest, dispositionMap);
@@ -421,8 +430,8 @@ export function buildGraphBundle(repoManifest, disposition, options = {}) {
421
430
  if (file.excluded || (status && isAuditExcludedStatus(status))) {
422
431
  continue;
423
432
  }
424
- acc.imports.push(...extractHeuristicContainerEdges(file.path));
425
- acc.imports.push(...extractHeuristicAuthSessionEdges(file.path, repoManifest, dispositionMap));
433
+ acc.heuristics.push(...extractHeuristicContainerEdges(file.path));
434
+ acc.heuristics.push(...extractHeuristicAuthSessionEdges(file.path, repoManifest, dispositionMap));
426
435
  const content = options.fileContents?.[file.path];
427
436
  const fileRoutes = [];
428
437
  if (content) {
@@ -446,6 +455,7 @@ export function buildGraphBundle(repoManifest, disposition, options = {}) {
446
455
  calls: uniqueSortedEdges(acc.calls),
447
456
  references: uniqueSortedEdges(acc.references),
448
457
  routes: uniqueSortedRoutes(acc.routes),
458
+ heuristics: uniqueSortedEdges(acc.heuristics),
449
459
  };
450
460
  logGraphExtractionMetric(graphs);
451
461
  return { graphs };
@@ -0,0 +1,4 @@
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
+ import { WorkspacePattern } from "./workspace.js";
3
+ export declare function cargoWorkspacePatterns(content: string): WorkspacePattern[];
4
+ export declare function extractCargoWorkspaceMemberEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
@@ -0,0 +1,107 @@
1
+ import { graphEdge, isCargoManifestPath } from "../graphPathUtils.js";
2
+ import { addWorkspacePattern, normalizeWorkspacePattern, workspacePatternMatchesManifest } from "./workspace.js";
3
+ import { stripTomlComment, tomlArrayIsClosed, tomlStringArrayValues } from "./toml.js";
4
+ const CARGO_WORKSPACE_MEMBER_EDGE_CONFIDENCE = 0.87;
5
+ export function cargoWorkspacePatterns(content) {
6
+ const patterns = [];
7
+ let currentSection;
8
+ let collectingKey;
9
+ let collectedValue = "";
10
+ const flushCollectedValue = () => {
11
+ if (!collectingKey) {
12
+ return;
13
+ }
14
+ for (const value of tomlStringArrayValues(collectedValue)) {
15
+ addWorkspacePattern(patterns, collectingKey === "exclude" ? `!${value}` : value);
16
+ }
17
+ collectingKey = undefined;
18
+ collectedValue = "";
19
+ };
20
+ for (const rawLine of content.split(/\r?\n/)) {
21
+ const withoutComment = stripTomlComment(rawLine);
22
+ const trimmed = withoutComment.trim();
23
+ if (trimmed.length === 0) {
24
+ continue;
25
+ }
26
+ const sectionMatch = /^\[([^\]]+)\]\s*$/.exec(trimmed);
27
+ if (sectionMatch?.[1]) {
28
+ if (collectingKey) {
29
+ flushCollectedValue();
30
+ }
31
+ currentSection = sectionMatch[1].trim();
32
+ continue;
33
+ }
34
+ if (collectingKey) {
35
+ collectedValue = `${collectedValue}\n${trimmed}`;
36
+ if (tomlArrayIsClosed(collectedValue)) {
37
+ flushCollectedValue();
38
+ }
39
+ continue;
40
+ }
41
+ if (currentSection !== "workspace") {
42
+ continue;
43
+ }
44
+ const arrayMatch = /^(members|exclude)\s*=\s*(.+)$/.exec(trimmed);
45
+ if (!arrayMatch?.[1] || !arrayMatch[2]) {
46
+ continue;
47
+ }
48
+ const value = arrayMatch[2].trim();
49
+ if (!value.startsWith("[")) {
50
+ continue;
51
+ }
52
+ collectingKey = arrayMatch[1];
53
+ collectedValue = value;
54
+ if (tomlArrayIsClosed(collectedValue)) {
55
+ flushCollectedValue();
56
+ }
57
+ }
58
+ if (collectingKey) {
59
+ flushCollectedValue();
60
+ }
61
+ return patterns;
62
+ }
63
+ export function extractCargoWorkspaceMemberEdges(fromPath, content, pathLookup) {
64
+ if (!isCargoManifestPath(fromPath)) {
65
+ return [];
66
+ }
67
+ const rawPatterns = cargoWorkspacePatterns(content);
68
+ if (rawPatterns.length === 0) {
69
+ return [];
70
+ }
71
+ const positivePatterns = [];
72
+ const negativePatterns = [];
73
+ for (const { pattern, negated } of rawPatterns) {
74
+ const normalized = normalizeWorkspacePattern(fromPath, pattern);
75
+ if (!normalized) {
76
+ continue;
77
+ }
78
+ if (negated) {
79
+ negativePatterns.push(normalized);
80
+ }
81
+ else {
82
+ positivePatterns.push(normalized);
83
+ }
84
+ }
85
+ const edges = [];
86
+ for (const pattern of positivePatterns) {
87
+ for (const target of pathLookup.values()) {
88
+ if (target === fromPath || !isCargoManifestPath(target)) {
89
+ continue;
90
+ }
91
+ if (!workspacePatternMatchesManifest(pattern, target, "Cargo.toml")) {
92
+ continue;
93
+ }
94
+ if (negativePatterns.some((negativePattern) => workspacePatternMatchesManifest(negativePattern, target, "Cargo.toml"))) {
95
+ continue;
96
+ }
97
+ edges.push(graphEdge({
98
+ from: fromPath,
99
+ to: target,
100
+ kind: "cargo-workspace-member-link",
101
+ confidence: CARGO_WORKSPACE_MEMBER_EDGE_CONFIDENCE,
102
+ reason: `Cargo workspace pattern '${pattern}' includes member manifest '${target}'.`,
103
+ }));
104
+ }
105
+ }
106
+ return edges;
107
+ }
@@ -0,0 +1,5 @@
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
+ export declare const GO_WORKSPACE_MODULE_EDGE_CONFIDENCE = 0.87;
3
+ export declare function stripGoLineComment(line: string): string;
4
+ export declare function splitGoWorkspaceSpecifiers(value: string): string[];
5
+ export declare function extractGoWorkspaceModuleEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
@@ -0,0 +1,151 @@
1
+ import { posix } from "node:path";
2
+ import { scanStringAware } from "@audit-tools/shared";
3
+ import { graphEdge, normalizeGraphPath, isGoModuleManifestPath, isGoWorkspaceManifestPath } from "../graphPathUtils.js";
4
+ export const GO_WORKSPACE_MODULE_EDGE_CONFIDENCE = 0.87;
5
+ const GO_SCAN_OPTIONS = {
6
+ quoteChars: ['"', "`"],
7
+ // Backtick raw strings do not honour backslash escapes.
8
+ escapedQuotes: ['"'],
9
+ };
10
+ export function stripGoLineComment(line) {
11
+ let commentIndex;
12
+ scanStringAware(line, GO_SCAN_OPTIONS, {
13
+ onUnquoted(char, i) {
14
+ if (char === "/" && line[i + 1] === "/") {
15
+ commentIndex = i;
16
+ return false;
17
+ }
18
+ },
19
+ });
20
+ return commentIndex !== undefined ? line.slice(0, commentIndex) : line;
21
+ }
22
+ function unquoteGoWorkspaceSpecifier(value) {
23
+ const trimmed = value.trim();
24
+ if (trimmed.length < 2) {
25
+ return trimmed;
26
+ }
27
+ if (trimmed[0] === '"' && trimmed.at(-1) === '"') {
28
+ try {
29
+ const parsed = JSON.parse(trimmed);
30
+ return typeof parsed === "string" ? parsed.trim() : trimmed;
31
+ }
32
+ catch {
33
+ return trimmed.slice(1, -1).trim();
34
+ }
35
+ }
36
+ if (trimmed[0] === "`" && trimmed.at(-1) === "`") {
37
+ return trimmed.slice(1, -1).trim();
38
+ }
39
+ return trimmed;
40
+ }
41
+ export function splitGoWorkspaceSpecifiers(value) {
42
+ const specifiers = [];
43
+ let tokenStart;
44
+ // Use scanStringAware to correctly skip over quoted string content, and
45
+ // detect whitespace-delimited token boundaries in unquoted regions.
46
+ // Quoted tokens are captured from the opening quote (tokenStart) through
47
+ // the closing quote (flushed on the next whitespace event), so that
48
+ // unquoteGoWorkspaceSpecifier sees the delimiters and can strip them.
49
+ scanStringAware(value, GO_SCAN_OPTIONS, {
50
+ onQuoteOpen(_q, i) {
51
+ tokenStart ??= i; // quoted token begins at the opening quote
52
+ },
53
+ onUnquoted(char, i) {
54
+ if (/\s/.test(char)) {
55
+ if (tokenStart !== undefined) {
56
+ const specifier = unquoteGoWorkspaceSpecifier(value.slice(tokenStart, i));
57
+ if (specifier.length > 0) {
58
+ specifiers.push(specifier);
59
+ }
60
+ tokenStart = undefined;
61
+ }
62
+ }
63
+ else {
64
+ tokenStart ??= i;
65
+ }
66
+ },
67
+ });
68
+ // Flush final token (no trailing whitespace).
69
+ if (tokenStart !== undefined) {
70
+ const specifier = unquoteGoWorkspaceSpecifier(value.slice(tokenStart));
71
+ if (specifier.length > 0) {
72
+ specifiers.push(specifier);
73
+ }
74
+ }
75
+ return specifiers;
76
+ }
77
+ function goWorkspaceUseSpecifiers(content) {
78
+ const specifiers = [];
79
+ let inUseBlock = false;
80
+ for (const rawLine of content.split(/\r?\n/)) {
81
+ const trimmed = stripGoLineComment(rawLine).trim();
82
+ if (trimmed.length === 0) {
83
+ continue;
84
+ }
85
+ if (inUseBlock) {
86
+ const closeIndex = trimmed.indexOf(")");
87
+ const body = closeIndex >= 0 ? trimmed.slice(0, closeIndex).trim() : trimmed;
88
+ specifiers.push(...splitGoWorkspaceSpecifiers(body));
89
+ if (closeIndex >= 0) {
90
+ inUseBlock = false;
91
+ }
92
+ continue;
93
+ }
94
+ const useMatch = /^use(?:\s+(.+)|\s*)$/.exec(trimmed);
95
+ if (!useMatch) {
96
+ continue;
97
+ }
98
+ let body = useMatch[1]?.trim() ?? "";
99
+ if (!body.startsWith("(")) {
100
+ specifiers.push(...splitGoWorkspaceSpecifiers(body));
101
+ continue;
102
+ }
103
+ body = body.slice(1).trim();
104
+ const closeIndex = body.indexOf(")");
105
+ if (closeIndex >= 0) {
106
+ specifiers.push(...splitGoWorkspaceSpecifiers(body.slice(0, closeIndex).trim()));
107
+ }
108
+ else {
109
+ specifiers.push(...splitGoWorkspaceSpecifiers(body));
110
+ inUseBlock = true;
111
+ }
112
+ }
113
+ return specifiers;
114
+ }
115
+ function resolveGoWorkspaceModuleReference(fromPath, specifier, pathLookup) {
116
+ const normalizedSpecifier = normalizeGraphPath(specifier);
117
+ if (normalizedSpecifier.length === 0 ||
118
+ normalizedSpecifier.startsWith("/") ||
119
+ /^[a-z][a-z0-9+.-]*:/i.test(normalizedSpecifier)) {
120
+ return undefined;
121
+ }
122
+ const workspaceDir = posix.dirname(normalizeGraphPath(fromPath));
123
+ const target = workspaceDir === "."
124
+ ? normalizedSpecifier
125
+ : posix.join(workspaceDir, normalizedSpecifier);
126
+ const direct = pathLookup.get(target.toLowerCase());
127
+ if (direct && isGoModuleManifestPath(direct)) {
128
+ return direct;
129
+ }
130
+ return pathLookup.get(posix.join(target, "go.mod").toLowerCase());
131
+ }
132
+ export function extractGoWorkspaceModuleEdges(fromPath, content, pathLookup) {
133
+ if (!isGoWorkspaceManifestPath(fromPath)) {
134
+ return [];
135
+ }
136
+ const edges = [];
137
+ for (const specifier of goWorkspaceUseSpecifiers(content)) {
138
+ const target = resolveGoWorkspaceModuleReference(fromPath, specifier, pathLookup);
139
+ if (!target) {
140
+ continue;
141
+ }
142
+ edges.push(graphEdge({
143
+ from: fromPath,
144
+ to: target,
145
+ kind: "go-workspace-module-link",
146
+ confidence: GO_WORKSPACE_MODULE_EDGE_CONFIDENCE,
147
+ reason: `Go workspace use directive '${specifier}' resolves to module '${target}'.`,
148
+ }));
149
+ }
150
+ return edges;
151
+ }
@@ -0,0 +1,8 @@
1
+ export { isCargoManifestPath, isGoWorkspaceManifestPath, isMavenPomPath, isPyprojectPath, } from "../graphPathUtils.js";
2
+ export { extractPackageEntrypointEdges, extractPackageScriptEdges, extractWorkspacePackageEdges } from "./packageJson.js";
3
+ export { extractCargoWorkspaceMemberEdges } from "./cargo.js";
4
+ export { extractTypescriptProjectReferenceEdges } from "./typescript.js";
5
+ export { extractGoWorkspaceModuleEdges } from "./go.js";
6
+ export { extractMavenModuleEdges } from "./maven.js";
7
+ export { extractPyprojectTestpathLinks } from "./pyproject.js";
8
+ export { extractYamlPathReferenceEdges } from "./yamlPaths.js";
@@ -0,0 +1,11 @@
1
+ // Re-exported for the graph builder, which imports these manifest predicates
2
+ // from here for historical reasons; the canonical definitions live in
3
+ // graphPathUtils.
4
+ export { isCargoManifestPath, isGoWorkspaceManifestPath, isMavenPomPath, isPyprojectPath, } from "../graphPathUtils.js";
5
+ export { extractPackageEntrypointEdges, extractPackageScriptEdges, extractWorkspacePackageEdges } from "./packageJson.js";
6
+ export { extractCargoWorkspaceMemberEdges } from "./cargo.js";
7
+ export { extractTypescriptProjectReferenceEdges } from "./typescript.js";
8
+ export { extractGoWorkspaceModuleEdges } from "./go.js";
9
+ export { extractMavenModuleEdges } from "./maven.js";
10
+ export { extractPyprojectTestpathLinks } from "./pyproject.js";
11
+ export { extractYamlPathReferenceEdges } from "./yamlPaths.js";
@@ -0,0 +1,3 @@
1
+ export declare function stripJsonComments(content: string): string;
2
+ export declare function removeTrailingJsonCommas(content: string): string;
3
+ export declare function parseJsoncObject(content: string): Record<string, unknown> | undefined;
@@ -0,0 +1,97 @@
1
+ import { scanStringAware } from "@audit-tools/shared";
2
+ const JSON_SCAN_OPTIONS = { quoteChars: ['"'], escapedQuotes: ['"'] };
3
+ export function stripJsonComments(content) {
4
+ let result = "";
5
+ let inString = false;
6
+ let escaped = false;
7
+ for (let index = 0; index < content.length; index++) {
8
+ const char = content[index];
9
+ const next = content[index + 1];
10
+ if (inString) {
11
+ result += char;
12
+ if (escaped) {
13
+ escaped = false;
14
+ }
15
+ else if (char === "\\") {
16
+ escaped = true;
17
+ }
18
+ else if (char === '"') {
19
+ inString = false;
20
+ }
21
+ continue;
22
+ }
23
+ if (char === '"') {
24
+ inString = true;
25
+ result += char;
26
+ continue;
27
+ }
28
+ if (char === "/" && next === "/") {
29
+ while (index < content.length && content[index] !== "\n") {
30
+ index++;
31
+ }
32
+ if (index < content.length) {
33
+ result += content[index];
34
+ }
35
+ continue;
36
+ }
37
+ if (char === "/" && next === "*") {
38
+ index += 2;
39
+ while (index < content.length &&
40
+ !(content[index] === "*" && content[index + 1] === "/")) {
41
+ if (content[index] === "\n") {
42
+ result += "\n";
43
+ }
44
+ index++;
45
+ }
46
+ if (index < content.length) {
47
+ index++;
48
+ }
49
+ continue;
50
+ }
51
+ result += char;
52
+ }
53
+ return result;
54
+ }
55
+ export function removeTrailingJsonCommas(content) {
56
+ let result = "";
57
+ let pos = 0;
58
+ scanStringAware(content, JSON_SCAN_OPTIONS, {
59
+ onQuoteOpen(_q, i) {
60
+ result += content.slice(pos, i + 1);
61
+ pos = i + 1;
62
+ },
63
+ onQuoteClose(_q, i) {
64
+ result += content.slice(pos, i + 1);
65
+ pos = i + 1;
66
+ },
67
+ onUnquoted(char, i) {
68
+ if (char === ",") {
69
+ let lookahead = i + 1;
70
+ while (/\s/.test(content[lookahead] ?? "")) {
71
+ lookahead++;
72
+ }
73
+ if (content[lookahead] === "}" || content[lookahead] === "]") {
74
+ // Flush up to (not including) the comma; skip it.
75
+ result += content.slice(pos, i);
76
+ pos = i + 1;
77
+ }
78
+ }
79
+ },
80
+ });
81
+ // Flush anything after the last event.
82
+ result += content.slice(pos);
83
+ return result;
84
+ }
85
+ export function parseJsoncObject(content) {
86
+ let parsed;
87
+ try {
88
+ parsed = JSON.parse(removeTrailingJsonCommas(stripJsonComments(content)));
89
+ }
90
+ catch {
91
+ return undefined;
92
+ }
93
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
94
+ return undefined;
95
+ }
96
+ return parsed;
97
+ }
@@ -0,0 +1,3 @@
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
+ export declare const MAVEN_MODULE_EDGE_CONFIDENCE = 0.87;
3
+ export declare function extractMavenModuleEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
@@ -0,0 +1,73 @@
1
+ import { posix } from "node:path";
2
+ import { graphEdge, normalizeGraphPath, isMavenPomPath } from "../graphPathUtils.js";
3
+ export const MAVEN_MODULE_EDGE_CONFIDENCE = 0.87;
4
+ function stripXmlComments(content) {
5
+ return content.replace(/<!--[\s\S]*?-->/g, "");
6
+ }
7
+ function decodeXmlText(value) {
8
+ return value
9
+ .replace(/&lt;/g, "<")
10
+ .replace(/&gt;/g, ">")
11
+ .replace(/&quot;/g, "\"")
12
+ .replace(/&apos;/g, "'")
13
+ .replace(/&amp;/g, "&");
14
+ }
15
+ function mavenModuleSpecifiers(content) {
16
+ const specifiers = [];
17
+ const withoutComments = stripXmlComments(content);
18
+ const modulesPattern = /<modules(?:\s[^>]*)?>([\s\S]*?)<\/modules>/gi;
19
+ let modulesMatch;
20
+ while ((modulesMatch = modulesPattern.exec(withoutComments))) {
21
+ const body = modulesMatch[1] ?? "";
22
+ const modulePattern = /<module(?:\s[^>]*)?>([\s\S]*?)<\/module>/gi;
23
+ let moduleMatch;
24
+ while ((moduleMatch = modulePattern.exec(body))) {
25
+ const specifier = decodeXmlText(moduleMatch[1] ?? "").trim();
26
+ if (specifier.length > 0) {
27
+ specifiers.push(specifier);
28
+ }
29
+ }
30
+ }
31
+ return specifiers;
32
+ }
33
+ function resolveMavenModuleReference(fromPath, specifier, pathLookup) {
34
+ const normalizedSpecifier = normalizeGraphPath(specifier);
35
+ if (normalizedSpecifier.length === 0 ||
36
+ normalizedSpecifier.startsWith("/") ||
37
+ /^[a-z][a-z0-9+.-]*:/i.test(normalizedSpecifier)) {
38
+ return undefined;
39
+ }
40
+ const manifestDir = posix.dirname(normalizeGraphPath(fromPath));
41
+ const target = manifestDir === "."
42
+ ? normalizedSpecifier
43
+ : posix.join(manifestDir, normalizedSpecifier);
44
+ const normalizedTarget = normalizeGraphPath(target);
45
+ if (normalizedTarget === ".." || normalizedTarget.startsWith("../")) {
46
+ return undefined;
47
+ }
48
+ const direct = pathLookup.get(normalizedTarget.toLowerCase());
49
+ if (direct && isMavenPomPath(direct)) {
50
+ return direct;
51
+ }
52
+ return pathLookup.get(posix.join(normalizedTarget, "pom.xml").toLowerCase());
53
+ }
54
+ export function extractMavenModuleEdges(fromPath, content, pathLookup) {
55
+ if (!isMavenPomPath(fromPath)) {
56
+ return [];
57
+ }
58
+ const edges = [];
59
+ for (const specifier of mavenModuleSpecifiers(content)) {
60
+ const target = resolveMavenModuleReference(fromPath, specifier, pathLookup);
61
+ if (!target || target === fromPath) {
62
+ continue;
63
+ }
64
+ edges.push(graphEdge({
65
+ from: fromPath,
66
+ to: target,
67
+ kind: "maven-module-link",
68
+ confidence: MAVEN_MODULE_EDGE_CONFIDENCE,
69
+ reason: `Maven module '${specifier}' resolves to module manifest '${target}'.`,
70
+ }));
71
+ }
72
+ return edges;
73
+ }
@@ -0,0 +1,19 @@
1
+ import type { GraphEdge } from "@audit-tools/shared";
2
+ import { WorkspacePattern } from "./workspace.js";
3
+ export declare const PACKAGE_ENTRYPOINT_EDGE_CONFIDENCE = 0.9;
4
+ export declare const PACKAGE_SCRIPT_EDGE_CONFIDENCE = 0.88;
5
+ export declare const WORKSPACE_PACKAGE_EDGE_CONFIDENCE = 0.86;
6
+ export declare const PACKAGE_SCRIPT_REFERENCE_PATTERN: RegExp;
7
+ export declare function packageEntrypointCandidates(content: string): Array<{
8
+ field: string;
9
+ specifier: string;
10
+ }>;
11
+ export declare function resolvePackageEntrypoint(packagePath: string, specifier: string, pathLookup: Map<string, string>): string | undefined;
12
+ export declare function extractPackageEntrypointEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
13
+ export declare function packageScriptCandidates(content: string): Array<{
14
+ script: string;
15
+ specifier: string;
16
+ }>;
17
+ export declare function extractPackageScriptEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];
18
+ export declare function packageWorkspacePatterns(content: string): WorkspacePattern[];
19
+ export declare function extractWorkspacePackageEdges(fromPath: string, content: string, pathLookup: Map<string, string>): GraphEdge[];