{"version":3,"file":"cli.mjs","names":["printHeader","printHeader","printHeader","printHeader","fs","ROOT_DEPENDENCY_FIELDS","path","fs","parseDependencyPath","path","fs","fs","path","path","fs","path","fs"],"sources":["../src/utils/format-utils.ts","../src/utils/print-summary.ts","../src/utils/print-details.ts","../src/utils/chart-renderer.ts","../src/utils/print-components.ts","../src/utils/print-patterns.ts","../src/utils/severity-format.ts","../src/utils/print-packages.ts","../src/utils/print-versus.ts","../src/utils/print-rules.ts","../src/utils/compliance.ts","../src/utils/version.ts","../src/utils/print-json.ts","../src/config/schema.ts","../src/config/loader.ts","../src/swc-parser/core/state.ts","../src/swc-parser/patterns/imports.ts","../src/swc-parser/utils/jsx-helpers.ts","../src/swc-parser/patterns/props.ts","../src/swc-parser/patterns/jsx.ts","../src/swc-parser/utils/matchers.ts","../src/swc-parser/patterns/variables.ts","../src/swc-parser/patterns/conditionals.ts","../src/swc-parser/patterns/collections.ts","../src/swc-parser/patterns/lazy-dynamic.ts","../src/swc-parser/patterns/advanced.ts","../src/swc-parser/core/visitor.ts","../src/swc-parser/core/report.ts","../src/swc-parser/index.ts","../src/utils/package-inventory.ts","../src/utils/package-distribution.ts","../src/utils/package-rules.ts","../src/utils/pattern-counter.ts","../src/utils/versus.ts","../src/utils/aggregator-core.ts","../src/utils/print-errors.ts","../src/utils/file-utils.ts","../src/lock-parser/lock-file-adapter.ts","../src/lock-parser/patterns/npm.ts","../src/lock-parser/patterns/pnpm.ts","../src/rules/shared.ts","../src/lock-parser/patterns/yarn.ts","../src/lock-parser/index.ts","../src/rules/file-rules.ts","../src/rules/script-rules.ts","../src/rules/package-field-rules.ts","../src/rules/engine-version.ts","../src/rules/codeowners.ts","../src/rules/evaluator.ts","../src/npm-registry/client.ts","../src/npm-registry/cache.ts","../src/npm-registry/enricher.ts","../src/config/overrides.ts","../src/commands/pipeline.ts","../src/commands/command-context.ts","../src/commands/scan.ts","../src/utils/print-compliance.ts","../src/utils/write-summary-file.ts","../src/commands/comply.ts","../src/cli.ts"],"sourcesContent":["/**\n * Format a number with thousand separators\n * @param num - Number to format\n * @returns Formatted string (e.g., 1,234,567)\n */\nexport function formatCount(num: number): string {\n  return num.toLocaleString();\n}\n\n/**\n * Format duration in seconds to a readable string\n * @param seconds - Duration in seconds\n * @returns Formatted string (e.g., 10.21s, 1.57s, 0.12s)\n */\nexport function formatDuration(seconds: number): string {\n  return `${seconds.toFixed(2)}s`;\n}\n\n/**\n * Format how far an upgrade candidate is past its age threshold\n * @returns Formatted string (e.g., \"40 days overdue\", \"1 day overdue\")\n */\nexport function formatDaysOverdue(\n  releasedDaysAgo: number,\n  thresholdDays: number,\n): string {\n  const overdue = releasedDaysAgo - thresholdDays;\n  return `${overdue} day${overdue === 1 ? '' : 's'} overdue`;\n}\n\n/**\n * Format how long until an upgrade candidate breaches its age threshold\n * @returns Formatted string (e.g., \"12 days remaining\", \"1 day remaining\")\n */\nexport function formatDaysRemaining(daysRemaining: number): string {\n  return `${daysRemaining} day${daysRemaining === 1 ? '' : 's'} remaining`;\n}\n\n/**\n * Join a list of items, showing only the first `limit` and summarizing the rest\n * @returns Formatted string (e.g., \"a, b and 3 other files\", \"a, b and 1 other file\")\n */\nexport function formatTruncatedList(\n  items: string[],\n  noun: string,\n  limit = 2,\n): string {\n  const shown = items.slice(0, limit).join(', ');\n  const rest = items.length - limit;\n  if (rest <= 0) return shown;\n  return `${shown} and ${rest} other ${noun}${rest === 1 ? '' : 's'}`;\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { AggregatedReport } from './aggregator';\nimport { formatCount } from './format-utils';\n\nfunction printHeader() {\n  console.log(chalk.green.bold('\\n📊 Summary\\n'));\n}\n\nexport function printSummary(aggregated: AggregatedReport) {\n  printHeader();\n\n  const table = new Table({\n    head: ['Metric', 'Count'],\n    style: {\n      head: ['cyan'],\n      border: ['gray'],\n    },\n  });\n\n  // Calculate external components only (filter out unknown and local)\n  const externalComponents = aggregated.topComponents.filter(\n    (comp) => comp.source !== 'unknown' && comp.source !== 'local',\n  ).length;\n\n  // Calculate total external package usage\n  const totalExternalUsage = aggregated.packageDistribution.reduce(\n    (sum, pkg) => sum + pkg.usageCount,\n    0,\n  );\n\n  table.push(\n    ['Files Analyzed', formatCount(aggregated.filesAnalyzed)],\n    // \"External Packages\" counted rows in packageDistribution, which used to\n    // mean \"packages with measured usage\". Since #78 that array is every\n    // package the repo owns, so the old label would now overcount what it\n    // claimed to describe.\n    ['Packages', formatCount(aggregated.packageDistribution.length)],\n    ['External Components', formatCount(externalComponents)],\n    ['Total Usages', formatCount(totalExternalUsage)],\n  );\n\n  console.log(table.toString());\n}\n","import chalk from 'chalk';\nimport type { AggregatedReport } from './aggregator';\nimport { formatCount } from './format-utils';\n\nfunction printHeader() {\n  console.log(chalk.cyan.bold('\\n📋 Details\\n'));\n}\n\nexport function printDetails(aggregated: AggregatedReport) {\n  printHeader();\n\n  console.log(\n    chalk.cyan(\n      `  Total usage patterns: ${formatCount(aggregated.totalUsagePatterns)}`,\n    ),\n  );\n\n  // Print each pattern type count\n  for (const pattern of aggregated.patternCounts) {\n    if (pattern.count > 0) {\n      console.log(\n        chalk.cyan(`  ${pattern.displayName}: ${formatCount(pattern.count)}`),\n      );\n    }\n  }\n}\n","import chalk from 'chalk';\nimport { formatCount } from './format-utils';\n\nexport interface ChartData {\n  label: string;\n  value: number;\n}\n\nexport interface ChartOptions {\n  maxWidth?: number;\n  showValues?: boolean;\n  barChar?: string;\n  emptyChar?: string;\n}\n\nexport function renderBarChart(data: ChartData[], options: ChartOptions = {}) {\n  const {\n    maxWidth = 50,\n    showValues = true,\n    barChar = '█',\n    emptyChar = '░',\n  } = options;\n\n  if (data.length === 0) {\n    console.log(chalk.gray('  No data to display'));\n    return;\n  }\n\n  // Find max value for scaling\n  const maxValue = Math.max(...data.map((d) => d.value));\n  if (maxValue === 0) {\n    console.log(chalk.gray('  All values are zero'));\n    return;\n  }\n\n  // Find longest label for alignment\n  const maxLabelLength = Math.max(...data.map((d) => d.label.length));\n\n  // Render each bar\n  for (const item of data) {\n    const percentage = item.value / maxValue;\n    const barLength = Math.round(percentage * maxWidth);\n    const emptyLength = maxWidth - barLength;\n\n    // Pad label\n    const paddedLabel = item.label.padEnd(maxLabelLength, ' ');\n\n    // Build bar\n    const bar =\n      chalk.green(barChar.repeat(barLength)) +\n      chalk.gray(emptyChar.repeat(emptyLength));\n\n    // Build value string\n    const valueStr = showValues ? ` ${formatCount(item.value)}` : '';\n\n    console.log(`${paddedLabel} ${bar}${valueStr}\\n`);\n  }\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { AggregatedReport, ComponentUsage } from './aggregator';\nimport { renderBarChart } from './chart-renderer';\n\nfunction printHeader() {\n  console.log(chalk.magenta.bold('\\n⚛️ Components\\n'));\n}\n\nexport function printComponents(\n  aggregated: AggregatedReport,\n  mode: 'table' | 'chart',\n) {\n  const components = aggregated.topComponents;\n\n  if (mode === 'table') {\n    printComponentsTable(components);\n  } else if (mode === 'chart') {\n    printComponentsChart(components);\n  }\n}\n\nfunction printComponentsTable(components: ComponentUsage[]) {\n  printHeader();\n\n  // Filter out unknown and local components - only show external packages\n  const externalComponents = components.filter(\n    (comp) => comp.source !== 'unknown' && comp.source !== 'local',\n  );\n\n  if (externalComponents.length === 0) {\n    console.log(chalk.gray('  No external components found'));\n    return;\n  }\n\n  const table = new Table({\n    head: ['Component', 'Package', 'Count'],\n    style: {\n      head: ['cyan'],\n      border: ['gray'],\n    },\n  });\n\n  externalComponents.forEach((comp) => {\n    table.push([comp.name, comp.source, comp.count.toString()]);\n  });\n\n  console.log(table.toString());\n}\n\nfunction printComponentsChart(components: ComponentUsage[]) {\n  printHeader();\n\n  // Filter out unknown and local components - only show external packages\n  const externalComponents = components.filter(\n    (comp) => comp.source !== 'unknown' && comp.source !== 'local',\n  );\n\n  if (externalComponents.length === 0) {\n    console.log(chalk.gray('  No external components found'));\n    return;\n  }\n\n  const data = externalComponents.map((comp) => ({\n    label: comp.name,\n    value: comp.count,\n  }));\n\n  renderBarChart(data, { maxWidth: 50 });\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { AggregatedReport, PatternCount } from './aggregator';\nimport { renderBarChart } from './chart-renderer';\n\nfunction printHeader() {\n  console.log(chalk.blue.bold('\\n🧩 Code Patterns\\n'));\n}\n\nexport function printPatterns(\n  aggregated: AggregatedReport,\n  mode: 'table' | 'chart',\n) {\n  const patterns = aggregated.patternCounts.filter((p) => p.count > 0);\n\n  if (mode === 'table') {\n    printPatternsTable(patterns);\n  } else if (mode === 'chart') {\n    printPatternsChart(patterns);\n  }\n}\n\nfunction printPatternsTable(patterns: PatternCount[]) {\n  printHeader();\n\n  if (patterns.length === 0) {\n    console.log(chalk.gray('  No patterns found'));\n    return;\n  }\n\n  const table = new Table({\n    head: ['Pattern', 'Count'],\n    style: {\n      head: ['cyan'],\n      border: ['gray'],\n    },\n  });\n\n  patterns.forEach((pattern) => {\n    table.push([pattern.displayName, pattern.count.toString()]);\n  });\n\n  console.log(table.toString());\n\n  // Show total patterns count\n  const totalPatterns = patterns.reduce((sum, p) => sum + p.count, 0);\n  console.log(chalk.gray(`\\nTotal: ${totalPatterns} patterns detected`));\n}\n\nfunction printPatternsChart(patterns: PatternCount[]) {\n  printHeader();\n\n  if (patterns.length === 0) {\n    console.log(chalk.gray('  No patterns found'));\n    return;\n  }\n\n  const data = patterns.map((pattern) => ({\n    label: pattern.displayName,\n    value: pattern.count,\n  }));\n\n  renderBarChart(data, { maxWidth: 50 });\n}\n","import chalk from 'chalk';\n\nexport type DisplaySeverity = 'error' | 'warn' | 'info' | 'success';\n\nconst ICONS: Record<DisplaySeverity, string> = {\n  error: '🔴',\n  warn: '🟡',\n  info: '🔵',\n  success: '🟢',\n};\n\nconst COLORS: Record<DisplaySeverity, (text: string) => string> = {\n  error: chalk.red,\n  warn: chalk.yellow,\n  info: chalk.blue,\n  success: chalk.green,\n};\n\n/** Colored-circle glyph for a severity — carries meaning without relying on ANSI color. */\nexport function severityIcon(severity: DisplaySeverity): string {\n  return ICONS[severity];\n}\n\n/** chalk color function for a severity, for text that needs coloring. */\nexport function severityColor(\n  severity: DisplaySeverity,\n): (text: string) => string {\n  return COLORS[severity];\n}\n\n/**\n * Resolves an explicit color-on/off override from CLI flags or the NO_COLOR\n * convention (https://no-color.org). Returns `undefined` when there's no\n * explicit signal, meaning chalk's own auto-detection should be left alone\n * (including its GitHub-Actions-aware detection of non-TTY streams).\n */\nexport function resolveColorLevel(opts: {\n  colorFlag?: boolean;\n  noColorEnv?: string;\n}): 0 | 1 | undefined {\n  if (opts.colorFlag === false) return 0;\n  if (opts.colorFlag === true) return 1;\n  if (opts.noColorEnv !== undefined) return 0;\n  return undefined;\n}\n\n// oxlint-disable-next-line no-control-regex -- matching the ANSI escape byte is the point\nconst ANSI_ESCAPE_PATTERN = /\\x1b\\[[0-9;]*m/g;\n\n/** Removes ANSI color escapes — for output destinations (files, PR comments) that can't render them. */\nexport function stripAnsi(text: string): string {\n  return text.replace(ANSI_ESCAPE_PATTERN, '');\n}\n\nfunction stripAnsiWrites(stream: NodeJS.WriteStream): void {\n  const originalWrite = stream.write.bind(stream);\n  stream.write = ((chunk: unknown, ...rest: unknown[]) => {\n    const stripped = typeof chunk === 'string' ? stripAnsi(chunk) : chunk;\n    return (originalWrite as (...args: unknown[]) => boolean)(\n      stripped,\n      ...rest,\n    );\n  }) as typeof stream.write;\n}\n\n/**\n * Beyond setting chalk's own level, this strips ANSI codes at the stream\n * boundary when color is explicitly disabled. hermex also prints through\n * cli-table3 and ora (whose spinner symbols come from log-symbols/yoctocolors)\n * — neither shares hermex's chalk instance or honors chalk.level, so mutating\n * chalk alone can't make NO_COLOR/--no-color hold for their output too.\n */\nexport function applyColorLevel(level: 0 | 1 | undefined): void {\n  if (level === undefined) return;\n  chalk.level = level;\n  if (level === 0) {\n    stripAnsiWrites(process.stdout);\n    stripAnsiWrites(process.stderr);\n  }\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { AggregatedReport, PackageDistribution } from './aggregator';\nimport type { RuleViolation } from '../rules/evaluator';\nimport type {\n  AvailableUpgrade,\n  ReleaseAgeEntry,\n  SemverBump,\n} from '../npm-registry/types';\nimport {\n  formatCount,\n  formatDaysOverdue,\n  formatDaysRemaining,\n} from './format-utils';\nimport { severityIcon, severityColor } from './severity-format';\n\nfunction printHeader() {\n  console.log(chalk.blueBright.bold('\\n📦 Packages\\n'));\n}\n\nexport function formatPackageName(\n  pkg: PackageDistribution,\n  banned?: RuleViolation,\n): string {\n  let prefix = '';\n  if (pkg.releaseAge?.deprecated) {\n    prefix += severityColor('error')('[DEPRECATED] ');\n  }\n  if (banned) {\n    prefix +=\n      banned.severity === 'error'\n        ? severityColor('error')('[BANNED] ')\n        : severityColor('warn')('[RESTRICTED] ');\n  } else if (pkg.internal) {\n    prefix += severityColor('warn')('[int] ');\n  }\n  return prefix + pkg.packageName;\n}\n\n// Describe the recommended upgrade for a breached tier.\n//\n// When a genuinely in-window compliant release exists (`compliantTarget`),\n// recommend THAT — even if it lives in a different, unbreached tier than the\n// one that failed (e.g. a stale 0.5.x minor line breached while a fresh 1.x\n// major sits within its window). The overdue count still reflects how long the\n// breached tier has been out of compliance, measured from its oldest breaching\n// release (#24).\n//\n// Only when there's no in-window target at all does the \"no compliant release\n// available\" wording apply — every candidate is itself past its threshold, so\n// a day count would imply a countdown that was never achievable (#26).\nexport function describeUpgradeTarget(\n  top: AvailableUpgrade,\n  compliantTarget?: { version: string; bump: SemverBump },\n): string {\n  if (compliantTarget) {\n    const overdue = formatDaysOverdue(\n      top.breachReleasedDaysAgo,\n      top.thresholdDays,\n    );\n    return `${compliantTarget.bump} ${compliantTarget.version} (${overdue})`;\n  }\n  const overdue =\n    top.releasedDaysAgo > top.thresholdDays\n      ? 'no compliant release available'\n      : formatDaysOverdue(top.breachReleasedDaysAgo, top.thresholdDays);\n  return `${top.semverBump} ${top.version} (${overdue})`;\n}\n\n// Prefer a genuinely compliant, still-in-window release as the recommended\n// target — it may sit in a different tier than the one that breached (the\n// breached tier's own newest release can itself be stale). Only when no such\n// target exists does `describeUpgradeTarget` fall back to \"no compliant\n// release available\". Extracted so both the human table and `--summary-file`\n// derive the recommended target the same way — they diverged on this once\n// before (#57).\nexport function resolveCompliantTarget(\n  releaseAge?: ReleaseAgeEntry,\n): { version: string; bump: SemverBump } | undefined {\n  if (!releaseAge?.minCompliantInWindow || !releaseAge.minCompliantVersion) {\n    return undefined;\n  }\n  return {\n    version: releaseAge.minCompliantVersion,\n    bump: releaseAge.minCompliantBump ?? releaseAge.upgrades[0]?.semverBump,\n  };\n}\n\n// Nested lockfile copies that are themselves overdue but aren't part of the\n// enforced verdict (e.g. non-root duplicates under `scope: 'root'`) must\n// stay visible — they don't block `comply`, but silently hiding them would\n// let real problems go unnoticed just because the policy doesn't enforce\n// them. One shared formatter, reused by the human table and\n// `--summary-file`, so the wording can't drift between the two (#57).\n//\n// Doesn't re-list which versions are overdue — `describeBundleImpact`\n// already names every resolved copy right before this in the same note, so\n// repeating a subset of that same list here would just be noise. Bare fact\n// text, no icon — the single leading icon for the whole note line is\n// decided once by `describePackageNotes`, not per-fact.\nexport function describeAdvisoryBreaches(\n  releaseAge?: ReleaseAgeEntry,\n): string | undefined {\n  if (!releaseAge?.advisoryBreaches?.length) return undefined;\n  const n = releaseAge.advisoryBreaches.length;\n  return `${n} nested ${n > 1 ? 'copies' : 'copy'} overdue, not enforced but recommended to resolve`;\n}\n\n// The single version a package's compliance verdict was actually measured\n// against — `releaseAge.installedVersion` when release-age ran (which, under\n// `scope: 'tree'`, may be a nested copy rather than the root version), else\n// the plain root-resolved `pkg.version`. Always a single value, never the\n// full `allVersions` list — that ambiguity (which of several installed\n// copies a cell's overdue count refers to) is exactly what #57 flagged.\nexport function resolveInstalledVersion(pkg: PackageDistribution): string {\n  return pkg.releaseAge?.installedVersion ?? pkg.version ?? 'N/A';\n}\n\n// Bundle-impact note for a package with more than one resolved lockfile\n// copy — kept separate from the Installed/Target columns (and from\n// describeAdvisoryBreaches) so each concern renders as its own sentence in\n// the notes list, not crammed into a table cell (#57).\nexport function describeBundleImpact(\n  pkg: PackageDistribution,\n): string | undefined {\n  if (!pkg.hasVersionConflict) return undefined;\n  return `${pkg.allVersions.length} versions installed (bundle impact): ${pkg.allVersions.join(', ')}`;\n}\n\n/** Separator between facts on a Notes line — a real Unicode arrow, not an\n * ASCII ligature (\"->\"/\"-->\") that only renders as an arrow in specific\n * fonts and shows as literal dashes everywhere else (a rendered GitHub PR\n * comment, a plain terminal). */\nexport const NOTE_ARROW = '→';\n\nexport interface PackageNote {\n  /** Always the info icon (🔵) — Notes are stdout-only advisory context,\n   * never part of the mandatory verdict (they don't appear in\n   * `--summary-file` at all), so nothing here should read as a warning. */\n  icon: string;\n  /** Each individual fact, to be joined with `NOTE_ARROW` by the caller. */\n  facts: string[];\n}\n\n// Combines bundle-impact and advisory-breach info into the note shown for a\n// package below the human table — stdout only. `--summary-file` feeds CI\n// checks and PR comments, where non-blocking context read as a colored\n// row/line looks like blame for something that isn't actually failing;\n// stdout is the right place for \"here's some extra context\" (#59).\nexport function describePackageNotes(\n  pkg: PackageDistribution,\n): PackageNote | undefined {\n  const facts = [\n    describeBundleImpact(pkg),\n    describeAdvisoryBreaches(pkg.releaseAge),\n  ].filter((fact): fact is string => Boolean(fact));\n  if (facts.length === 0) return undefined;\n  return { icon: severityIcon('info'), facts };\n}\n\nexport function formatUpgradeCell(releaseAge?: ReleaseAgeEntry): string {\n  if (!releaseAge) return '';\n  const { worstLevel, upgrades, severity, pendingUpgrade } = releaseAge;\n\n  if (!worstLevel) {\n    if (pendingUpgrade) {\n      return `${severityIcon('info')} ${pendingUpgrade.semverBump} ${pendingUpgrade.version} (${formatDaysRemaining(pendingUpgrade.daysRemaining)})`;\n    }\n    return severityIcon('success');\n  }\n\n  const top = upgrades[0];\n  if (!top) return severityIcon('success');\n\n  const suffix = severity === 'warn' ? chalk.gray(' [not enforced]') : '';\n  const description = describeUpgradeTarget(\n    top,\n    resolveCompliantTarget(releaseAge),\n  );\n\n  // The status reflects severity, not which tier breached: an enforced package\n  // fails comply whether the worst breach is minor_overdue or major_overdue\n  // (#28), so it renders red — never a softer yellow just because the breached\n  // tier happens to be minor.\n  const icon = severityIcon(severity === 'warn' ? 'warn' : 'error');\n  return `${icon} ${description}${suffix}`;\n}\n\n/**\n * The `forbid_packages` hit for this package, if any. Filters `ruleViolations`\n * by `type` rather than reading a dedicated banned-packages array, which is\n * what #77 removed — `packageName` is what keeps the join to a table row\n * exact, since a violation carries no file paths to match on.\n */\nexport function findForbidViolation(\n  pkg: PackageDistribution,\n  violations: RuleViolation[],\n): RuleViolation | undefined {\n  return violations.find(\n    (v) => v.type === 'forbid_packages' && v.packageName === pkg.packageName,\n  );\n}\n\nexport function printPackages(\n  aggregated: AggregatedReport,\n  mode: 'table' | 'chart',\n) {\n  const packages = aggregated.packageDistribution;\n  const violations = aggregated.ruleViolations;\n\n  // Nothing to report — print nothing at all, rather than a \"Packages\"\n  // header plus \"No packages found\" underneath it. Pure boilerplate when\n  // there's genuinely zero data (as opposed to zero *violations* among\n  // real packages, which still renders the full table/chart below).\n  if (packages.length === 0) return;\n\n  if (mode === 'table') {\n    printPackagesTable(packages, violations);\n  } else if (mode === 'chart') {\n    printPackagesChart(packages, violations);\n  }\n}\n\n// Only ever called via printPackages, which already guarantees a non-empty\n// `packages` array — see the \"nothing to report\" guard there.\nfunction printPackagesTable(\n  packages: PackageDistribution[],\n  violations: RuleViolation[],\n) {\n  printHeader();\n\n  const hasReleaseAge = packages.some((p) => p.releaseAge !== undefined);\n  // With release age on, \"Version\" splits into \"Installed\" (the single\n  // version the verdict was actually measured against) and \"Target\" (the\n  // recommended upgrade) — cramming a multi-version list and an upgrade\n  // recommendation into one cell was exactly the ambiguity #57 reported.\n  const head = hasReleaseAge\n    ? ['Package', 'Installed', 'Target']\n    : ['Package', 'Version'];\n\n  const table = new Table({\n    head,\n    style: {\n      head: ['cyan'],\n      border: ['gray'],\n    },\n  });\n\n  packages.forEach((pkg) => {\n    const row = [formatPackageName(pkg, findForbidViolation(pkg, violations))];\n    if (hasReleaseAge) {\n      row.push(resolveInstalledVersion(pkg), formatUpgradeCell(pkg.releaseAge));\n    } else {\n      row.push(pkg.version || 'N/A');\n    }\n    table.push(row);\n  });\n\n  console.log(table.toString());\n\n  // Bundle-impact (multiple resolved copies) and advisory nested breaches\n  // are per-package context, not part of the pass/fail verdict — printed as\n  // notes below the table rather than inside a cell, so the table itself\n  // stays a clean \"installed → target\" comparison (#57).\n  const notes = packages\n    .map((pkg) => ({ pkg, note: describePackageNotes(pkg) }))\n    .filter(\n      (entry): entry is { pkg: PackageDistribution; note: PackageNote } =>\n        entry.note !== undefined,\n    );\n  if (notes.length > 0) {\n    console.log(chalk.gray('\\nNotes:'));\n    for (const { pkg, note } of notes) {\n      const facts = note.facts.map((fact) => `${NOTE_ARROW} ${fact}`).join(' ');\n      console.log(chalk.gray(`  ${note.icon} ${pkg.packageName} ${facts}`));\n    }\n  }\n\n  console.log(chalk.gray(`\\nTotal: ${formatCount(packages.length)} packages`));\n}\n\n// Only ever called via printPackages, which already guarantees a non-empty\n// `packages` array — see the \"nothing to report\" guard there.\nfunction printPackagesChart(\n  packages: PackageDistribution[],\n  violations: RuleViolation[],\n) {\n  // A share-of-usage chart has nothing to say about a package with no\n  // measured usage — every such row would be a 0% empty bar, and since #78\n  // `packages` is every package the repo owns rather than only the used\n  // ones. With all-zero usage `maxPercentage` would also be 0, making every\n  // bar length NaN.\n  const charted = packages.filter((p) => p.usageCount > 0);\n  if (charted.length === 0) return;\n\n  printHeader();\n\n  const maxBarWidth = 40;\n  const maxPercentage = Math.max(...charted.map((p) => p.percentage));\n  const maxLabelLength = Math.max(\n    ...charted.map((p) => p.packageName.length + (p.internal ? 6 : 0)),\n  );\n\n  charted.forEach((pkg) => {\n    const barLength = Math.round(\n      (pkg.percentage / maxPercentage) * maxBarWidth,\n    );\n    const emptyLength = maxBarWidth - barLength;\n    const label = formatPackageName(\n      pkg,\n      findForbidViolation(pkg, violations),\n    ).padEnd(maxLabelLength, ' ');\n\n    const bar =\n      chalk.green('█'.repeat(barLength)) + chalk.gray('░'.repeat(emptyLength));\n\n    console.log(\n      `${label} ${bar} ${chalk.bold(pkg.percentage.toFixed(1) + '%')} (${pkg.usageCount})`,\n    );\n  });\n}\n","import chalk from 'chalk';\nimport type { AggregatedReport, VersusResult } from './aggregator';\n\nconst BAR_WIDTH = 30;\n\nfunction renderBar(percentage: number): string {\n  const filled = Math.round((percentage / 100) * BAR_WIDTH);\n  const empty = BAR_WIDTH - filled;\n  return chalk.cyan('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));\n}\n\nfunction printVersusResult(result: VersusResult) {\n  console.log(chalk.bold(`  ${result.name}`));\n  console.log(chalk.gray(`  ${'─'.repeat(50)}`));\n\n  const maxNameLen = Math.max(\n    ...result.entries.map((e) => e.packageName.length),\n  );\n\n  for (const entry of result.entries) {\n    const name = entry.packageName.padEnd(maxNameLen);\n    const bar = renderBar(entry.percentage);\n    const pct = chalk.bold(`${entry.percentage.toFixed(1)}%`);\n    const usage = chalk.gray(`(${entry.count} usages)`);\n\n    console.log(`  ${name}  ${bar} ${pct} ${usage}`);\n  }\n\n  if (result.totalCount === 0) {\n    console.log(\n      chalk.gray('  No usage detected for any package in this group.'),\n    );\n  }\n\n  console.log();\n}\n\nexport function printVersus(aggregated: AggregatedReport) {\n  if (aggregated.versusResults.length === 0) return;\n\n  console.log(chalk.magentaBright.bold('\\n⚖️ Versus\\n'));\n\n  for (const result of aggregated.versusResults) {\n    printVersusResult(result);\n  }\n}\n","import chalk from 'chalk';\nimport Table from 'cli-table3';\nimport type { AggregatedReport } from './aggregator';\nimport type { RuleViolation } from '../rules/evaluator';\nimport { formatTruncatedList } from './format-utils';\nimport { severityIcon } from './severity-format';\n\nexport function formatRuleType(type: RuleViolation['type']): string {\n  switch (type) {\n    case 'detect_files':\n      return 'detect_files';\n    case 'require_files':\n      return 'require_files';\n    case 'require_packages':\n      return 'require_packages';\n    case 'forbid_packages':\n      return 'forbid_packages';\n    case 'require_scripts':\n      return 'require_scripts';\n    case 'require_package_fields':\n      return 'package_fields';\n    case 'forbid_package_fields':\n      return 'package_fields';\n    case 'engine_version':\n      return 'engine_version';\n    case 'codeowners':\n      return 'codeowners';\n  }\n}\n\nexport function describeViolation(v: RuleViolation): string {\n  const patterns = v.patterns.join(', ');\n  const suffix = v.message ? chalk.gray(` — ${v.message}`) : '';\n\n  if (v.type === 'detect_files') {\n    const files = v.matchedFiles.map((f) => {\n      const parts = f.replace(/\\\\/g, '/').split('/');\n      return parts[parts.length - 1];\n    });\n    return `${patterns} detected (${formatTruncatedList(files, 'file')})${suffix}`;\n  }\n\n  if (v.type === 'require_files') return `${patterns} not found${suffix}`;\n  if (v.type === 'require_packages')\n    return `${patterns} not installed${suffix}`;\n  if (v.type === 'forbid_packages')\n    return `${v.packageName ?? patterns} is forbidden${suffix}`;\n  if (v.type === 'require_scripts')\n    return `script ${patterns} missing in package.json${suffix}`;\n  if (v.type === 'require_package_fields') {\n    if (v.fieldPath && v.actualValue !== undefined)\n      return `field ${v.fieldPath} is ${chalk.yellow(v.actualValue)}, does not match required value${suffix}`;\n    return `field ${patterns} missing in package.json${suffix}`;\n  }\n  if (v.type === 'forbid_package_fields')\n    return `field ${v.fieldPath ?? patterns} is forbidden in package.json${suffix}`;\n\n  if (v.type === 'engine_version') {\n    if (!v.installedRange)\n      return `engines.node not specified (required ${v.requiredRange})${suffix}`;\n    return `engines.node is ${chalk.yellow(v.installedRange)}, required ${chalk.cyan(v.requiredRange)}${suffix}`;\n  }\n\n  if (v.type === 'codeowners') {\n    if (v.matchedFiles.length === 0)\n      return `CODEOWNERS not found (looked in ${patterns})${suffix}`;\n    return `${v.matchedFiles.length} scanned file(s) have no owner: ${formatTruncatedList(v.matchedFiles, 'file')}${suffix}`;\n  }\n\n  return `${patterns} not present${suffix}`;\n}\n\nexport function printRules(aggregated: AggregatedReport): void {\n  const { ruleViolations } = aggregated;\n\n  // Nothing to report — print nothing at all, rather than a \"Rules\" header\n  // plus an \"All rule checks passed\" line with zero rows underneath it.\n  // The overall compliance verdict (printComplianceVerdict) already gives\n  // the definitive pass/fail signal; an empty section here is pure\n  // boilerplate, indistinguishable from \"no rules were ever configured.\"\n  if (ruleViolations.length === 0) return;\n\n  console.log(chalk.blueBright.bold('\\n🔍 Rules\\n'));\n\n  // A table, matching the Packages table's shape/scanability, rather than a\n  // bullet list.\n  const table = new Table({\n    head: ['Rule', 'Description'],\n    style: { head: ['cyan'], border: ['gray'] },\n  });\n\n  for (const v of ruleViolations) {\n    table.push([\n      formatRuleType(v.type),\n      `${severityIcon(v.severity)} ${describeViolation(v)}`,\n    ]);\n  }\n\n  console.log(table.toString());\n\n  const errorCount = ruleViolations.filter(\n    (v) => v.severity === 'error',\n  ).length;\n  const warnCount = ruleViolations.filter((v) => v.severity === 'warn').length;\n\n  const parts: string[] = [];\n  if (errorCount > 0)\n    parts.push(chalk.red(`${errorCount} error${errorCount > 1 ? 's' : ''}`));\n  if (warnCount > 0)\n    parts.push(chalk.yellow(`${warnCount} warning${warnCount > 1 ? 's' : ''}`));\n  console.log(chalk.gray(`\\n${parts.join(', ')}`));\n}\n","import type { AggregatedReport } from './aggregator';\nimport type { RuleViolation } from '../rules/evaluator';\nimport type { PackageDistribution } from './package-distribution';\n\n/**\n * The canonical, three-state compliance verdict hermex publishes so\n * downstream consumers (sheet sync, CI dashboards) don't have to invent\n * their own mapping over the raw JSON and disagree with `comply` (#55):\n *\n * - `non-compliant` — has at least one mandatory (error) violation; exactly\n *   `compliant === false`, the same condition `comply` exits non-zero on.\n * - `warning` — passes `comply`, but the policy author flagged something at\n *   `warn` severity: a warn-severity rule or banned-package violation.\n * - `compliant` — no mandatory violations and nothing flagged at `warn`.\n */\nexport type ComplianceStatus = 'compliant' | 'warning' | 'non-compliant';\n\nexport interface ComplianceResult {\n  compliant: boolean;\n  status: ComplianceStatus;\n  /** Every error-severity rule violation, whatever its `type`. */\n  errorRuleViolations: RuleViolation[];\n  releaseAgeViolations: PackageDistribution[];\n  /** Every warn-severity rule violation, whatever its `type`. */\n  warningRuleViolations: RuleViolation[];\n}\n\n/**\n * A package is a compliance failure when its releaseAge severity is 'error'\n * (i.e. it's in scope per `releaseAge.enforceOn`) AND it has any breached\n * threshold at all (worstLevel is non-null) — both 'minor_overdue' and\n * 'major_overdue' fail comply for an enforced package; only severity\n * decides mandatory vs advisory, not which tier breached (#28).\n *\n * The `warning` tier is deliberately narrow: it covers only warn-severity\n * *rule* violations — signals the policy author opted into. Severity alone\n * decides the bucket; the rule's `type` never does. A non-enforced\n * (severity 'warn') overdue\n * release-age package or a not-yet-due `pendingUpgrade` is advisory data,\n * not a warning, and must not on its own demote `compliant` → `warning`.\n * Consumers that treated any non-blocking outdated row as Warning disagreed\n * with `comply`; reading `status` here is the fix (#55).\n */\nexport function computeCompliance(\n  aggregated: AggregatedReport,\n): ComplianceResult {\n  const errorRuleViolations = aggregated.ruleViolations.filter(\n    (v) => v.severity === 'error',\n  );\n  const releaseAgeViolations = aggregated.packageDistribution.filter(\n    (p) =>\n      p.releaseAge?.severity === 'error' && p.releaseAge?.worstLevel !== null,\n  );\n  const warningRuleViolations = aggregated.ruleViolations.filter(\n    (v) => v.severity === 'warn',\n  );\n\n  const compliant =\n    errorRuleViolations.length === 0 && releaseAgeViolations.length === 0;\n\n  const status: ComplianceStatus = !compliant\n    ? 'non-compliant'\n    : warningRuleViolations.length > 0\n      ? 'warning'\n      : 'compliant';\n\n  return {\n    compliant,\n    status,\n    errorRuleViolations,\n    releaseAgeViolations,\n    warningRuleViolations,\n  };\n}\n\n/**\n * The count behind the \"N mandatory violations found\" line both the terminal\n * verdict and `--summary-file` print — a display concern, which is why it\n * lives here rather than in the emitted JSON (consumers read `compliant`, or\n * add the buckets themselves; they're disjoint).\n *\n * Shared by those two renderers because they had this sum copied between\n * them, and both got it wrong the same way when `forbid_packages` moved into\n * `ruleViolations` (#77): each was still adding a separate banned-package\n * bucket that now overlapped, double-reporting every forbidden package.\n */\nexport function countMandatoryViolations(result: ComplianceResult): number {\n  return result.errorRuleViolations.length + result.releaseAgeViolations.length;\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\n\nlet cachedVersion: string | undefined;\n\n/**\n * Walks up from `dir` to find the nearest package.json.\n * Needed because this module's own path differs between the tsdown-bundled\n * single-file `dist/cli.mjs` and the unbundled source used by tests.\n */\nfunction findPackageJson(dir: string): string {\n  let current = dir;\n  while (true) {\n    const candidate = path.join(current, 'package.json');\n    if (existsSync(candidate)) return candidate;\n    const parent = path.dirname(current);\n    if (parent === current) {\n      throw new Error(`Could not locate package.json above ${dir}`);\n    }\n    current = parent;\n  }\n}\n\nexport function getVersion(): string {\n  if (cachedVersion) return cachedVersion;\n\n  const dir = path.dirname(fileURLToPath(import.meta.url));\n  const pkgPath = findPackageJson(dir);\n  const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { version: string };\n\n  cachedVersion = pkg.version;\n  return cachedVersion;\n}\n","import type { AggregatedReport } from './aggregator';\nimport type { ComplianceResult } from './compliance';\nimport { computeCompliance } from './compliance';\nimport { getVersion } from './version';\n\n/**\n * Emits the scan/comply JSON. The `compliance` block is the official,\n * machine-readable verdict — `status` (`compliant` | `warning` |\n * `non-compliant`) plus the per-bucket counts that explain it — so consumers\n * read one canonical field instead of re-deriving a status from `packages` /\n * `ruleViolations` and drifting from `comply` (#55). `compliant` mirrors the\n * CLI exit code (0 ⇔ true); `status: 'warning'` never changes that exit code.\n *\n * `ruleViolations` is the single list of every rule hit, `forbid_packages`\n * included (#77) — there is no second violations field to remember to read.\n *\n * Every top-level key besides `version`, `summary` and `compliance` is a\n * per-item dataset. `patternCounts` sits under `summary` rather than beside\n * them (#80) because it is aggregate statistics — the same kind of number as\n * `totalImports` next to it, just broken down by pattern type.\n *\n * `compliance` defaults to `computeCompliance(aggregated)` so `scan --format\n * json` carries the same verdict as `comply`; callers that already computed\n * it (comply) pass it through to avoid recomputing.\n */\nexport function printJson(\n  aggregated: AggregatedReport,\n  compliance: ComplianceResult = computeCompliance(aggregated),\n): void {\n  const result = {\n    version: getVersion(),\n    summary: {\n      filesAnalyzed: aggregated.filesAnalyzed,\n      totalImports: aggregated.totalImports,\n      totalComponents: aggregated.totalComponents,\n      totalUsagePatterns: aggregated.totalUsagePatterns,\n      patternCounts: aggregated.patternCounts,\n    },\n    packages: aggregated.packageDistribution,\n    components: aggregated.topComponents.map((c) => ({\n      ...c,\n      files: [...c.files],\n    })),\n    versus: aggregated.versusResults,\n    ruleViolations: aggregated.ruleViolations,\n    compliance: {\n      status: compliance.status,\n      compliant: compliance.compliant,\n      counts: {\n        errorRuleViolations: compliance.errorRuleViolations.length,\n        releaseAgeViolations: compliance.releaseAgeViolations.length,\n        warningRuleViolations: compliance.warningRuleViolations.length,\n      },\n    },\n  };\n  process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n}\n","import { z } from 'zod';\n\n// ── Sub-schemas ────────────────────────────────────────────────────────────────\n\n// 'off' disables a rule — same as ESLint/oxlint. It's meaningful anywhere a\n// rule is authored (not just inside `overrides`): a rule reaching a repo's\n// final config with severity 'off' is dropped before evaluators ever see\n// it (see `resolveRules` in ./overrides), so a future shared/extends-style\n// base config could ship a rule that individual repos turn off, the same\n// way an override cancels an org-wide rule for specific repos today.\nconst RuleSeveritySchema = z.enum(['error', 'warn', 'info', 'off']);\n\nconst RuleConfigSchema = z.object({\n  severity: RuleSeveritySchema,\n  patterns: z.array(z.string()),\n  message: z.string().optional(),\n});\n\nconst RuleConfigOrArraySchema = z.union([\n  RuleConfigSchema,\n  z.array(RuleConfigSchema),\n]);\n\nconst PackageFieldRuleSchema = RuleConfigSchema.extend({\n  /** Optional micromatch patterns the field's stringified value must match */\n  values: z.array(z.string()).optional(),\n});\n\nconst PackageFieldRuleOrArraySchema = z.union([\n  PackageFieldRuleSchema,\n  z.array(PackageFieldRuleSchema),\n]);\n\nconst EngineVersionRuleSchema = z.object({\n  severity: RuleSeveritySchema,\n  range: z.string(),\n  message: z.string().optional(),\n});\n\nconst CodeownersRuleSchema = z.object({\n  severity: RuleSeveritySchema,\n  message: z.string().optional(),\n  /** If set, matched files must be owned by at least one of these owner strings (exact match against CODEOWNERS entries, e.g. \"@org/team\"). */\n  requiredOwners: z.array(z.string()).optional(),\n});\n\nconst ThresholdSchema = z.union([z.number(), z.literal(false)]);\n\n// Overrides use the same rule schemas as the base `rules` below (severity\n// 'off' included) — an override rule is resolved into the base the same\n// way `resolveRules` resolves the base config against itself.\nconst OverrideRulesSchema = z\n  .object({\n    detect_files: RuleConfigOrArraySchema.optional(),\n    require_files: RuleConfigOrArraySchema.optional(),\n    forbid_packages: RuleConfigOrArraySchema.optional(),\n    require_packages: RuleConfigOrArraySchema.optional(),\n    require_scripts: RuleConfigOrArraySchema.optional(),\n    require_package_fields: PackageFieldRuleOrArraySchema.optional(),\n    forbid_package_fields: PackageFieldRuleOrArraySchema.optional(),\n    engine_version: z\n      .union([EngineVersionRuleSchema, z.array(EngineVersionRuleSchema)])\n      .optional(),\n    codeowners: CodeownersRuleSchema.optional(),\n  })\n  .default(() => ({}));\n\nconst OverrideSchema = z.object({\n  /** Micromatch patterns checked against the current repo's package.json \"name\" */\n  match: z.array(z.string()).min(1),\n  rules: OverrideRulesSchema,\n});\n\n// ── Main schema with defaults ──────────────────────────────────────────────────\n\nexport const HermexConfigSchema = z.object({\n  includes: z.array(z.string()).default(['**/*.{tsx,jsx,ts,js}']),\n  excludes: z\n    .array(z.string())\n    .default(['**/node_modules/**', '**/dist/**', '**/build/**']),\n\n  packages: z\n    .object({\n      internal: z.array(z.string()).default([]),\n      ignore: z.array(z.string()).default([]),\n    })\n    .default(() => ({ internal: [], ignore: [] })),\n\n  versus: z\n    .array(z.object({ name: z.string(), packages: z.array(z.string()).min(2) }))\n    .default([]),\n\n  /**\n   * Repo-scoped rule adjustments: when the current repo's package.json \"name\"\n   * matches an entry's `match` patterns, its `rules` are upserted into the\n   * base `rules` below, keyed by identity (a rule's `patterns`, or `range`\n   * for engine_version) — a rule with new patterns is added, one whose\n   * patterns match an existing base rule replaces it, and severity 'off'\n   * replaces it with nothing (like ESLint's per-rule 'off'). Lets one shared\n   * config both add rules to a subset of repos (a mandatory dependency for\n   * 30 of 150 apps) and loosen/cancel an org-wide rule for specific repos.\n   */\n  overrides: z.array(OverrideSchema).default([]),\n\n  rules: z\n    .object({\n      detect_files: RuleConfigOrArraySchema.default([]),\n      require_files: RuleConfigOrArraySchema.default([]),\n      forbid_packages: RuleConfigOrArraySchema.default([]),\n      require_packages: RuleConfigOrArraySchema.default([]),\n      require_scripts: RuleConfigOrArraySchema.default([]),\n      require_package_fields: PackageFieldRuleOrArraySchema.default([]),\n      forbid_package_fields: PackageFieldRuleOrArraySchema.default([]),\n      engine_version: z\n        .union([EngineVersionRuleSchema, z.array(EngineVersionRuleSchema)])\n        .optional(),\n      codeowners: CodeownersRuleSchema.optional(),\n    })\n    .default(() => ({\n      detect_files: [] as RuleConfig[],\n      require_files: [] as RuleConfig[],\n      forbid_packages: [] as RuleConfig[],\n      require_packages: [] as RuleConfig[],\n      require_scripts: [] as RuleConfig[],\n      require_package_fields: [] as PackageFieldRule[],\n      forbid_package_fields: [] as PackageFieldRule[],\n    })),\n\n  output: z\n    .object({\n      summary: z.union([z.literal('log'), z.literal(false)]).default('log'),\n      components: z\n        .union([z.enum(['table', 'chart']), z.literal(false)])\n        .default('table'),\n      packages: z\n        .union([z.enum(['table', 'chart']), z.literal(false)])\n        .default('table'),\n      patterns: z\n        .union([z.enum(['table', 'chart']), z.literal(false)])\n        .default('table'),\n      details: z.boolean().default(false),\n      versus: z.boolean().default(true),\n      rules: z.boolean().default(true),\n      format: z.enum(['human', 'json']).default('human'),\n    })\n    .default(() => ({\n      summary: 'log' as const,\n      components: 'table' as const,\n      packages: 'table' as const,\n      patterns: 'table' as const,\n      details: false,\n      versus: true,\n      rules: true,\n      format: 'human' as const,\n    })),\n\n  releaseAge: z\n    .object({\n      enabled: z.boolean().default(false),\n      registry: z.string().default('https://registry.npmjs.org'),\n      authToken: z.string().optional(),\n      thresholds: z\n        .object({\n          patch: ThresholdSchema.default(30),\n          minor: ThresholdSchema.default(45),\n          major: ThresholdSchema.default(60),\n        })\n        .default(() => ({ patch: 30, minor: 45, major: 60 })),\n      enforceOn: z.array(z.string()).default([]),\n      cacheTtlMs: z.number().int().positive().optional(),\n      cacheDisabled: z.boolean().default(false),\n      // 'root' checks only each package's direct/root-installed version;\n      // 'tree' checks every resolved copy in the lockfile, failing if any\n      // is overdue. Nested duplicates are always visible as advisory data\n      // regardless of scope — this only decides what's mandatory (#57).\n      scope: z.enum(['root', 'tree']).default('root'),\n      // Glob-matched (like enforceOn): packages matching here use the\n      // OPPOSITE of `scope`, letting one global policy carve out\n      // exceptions for specific packages.\n      scopeExceptions: z.array(z.string()).default([]),\n    })\n    .default(() => ({\n      enabled: false,\n      registry: 'https://registry.npmjs.org',\n      thresholds: { patch: 30, minor: 45, major: 60 },\n      enforceOn: [],\n      cacheDisabled: false,\n      scope: 'root' as const,\n      scopeExceptions: [],\n    })),\n});\n\n// ── Derived types ──────────────────────────────────────────────────────────────\n\n/** Config as returned after parsing — all defaults applied, all fields required */\nexport type HermexConfig = z.infer<typeof HermexConfigSchema>;\n\n/** Config as accepted by the user — everything optional */\nexport type HermexConfigInput = z.input<typeof HermexConfigSchema>;\n\n// Sub-types derived from the output shape so they can never drift from the schema\nexport type RuleSeverity = z.infer<typeof RuleSeveritySchema>;\nexport type RuleConfig = z.infer<typeof RuleConfigSchema>;\nexport type PackageFieldRule = z.infer<typeof PackageFieldRuleSchema>;\nexport type EngineVersionRule = z.infer<typeof EngineVersionRuleSchema>;\nexport type CodeownersRule = z.infer<typeof CodeownersRuleSchema>;\nexport type PackagesConfig = HermexConfig['packages'];\nexport type VersusConfig = HermexConfig['versus'][number];\nexport type RulesConfig = HermexConfig['rules'];\nexport type OverrideConfig = HermexConfig['overrides'][number];\nexport type OutputConfig = HermexConfig['output'];\nexport type ReleaseAgeConfig = HermexConfig['releaseAge'];\nexport type ReleaseAgeThresholds = HermexConfig['releaseAge']['thresholds'];\n","import { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { HermexConfigSchema } from './schema';\nimport type { HermexConfig } from './schema';\n\nexport async function loadConfig(\n  cwd: string,\n  explicitPath?: string,\n): Promise<HermexConfig> {\n  const configPath = explicitPath\n    ? resolve(explicitPath)\n    : join(cwd, 'hermex.config.ts');\n\n  if (explicitPath && !existsSync(configPath)) {\n    throw new Error(`Config file not found: ${configPath}`);\n  }\n\n  if (existsSync(configPath)) {\n    const mod = await import(pathToFileURL(configPath).href);\n    return HermexConfigSchema.parse(mod.default ?? mod);\n  }\n\n  return HermexConfigSchema.parse({});\n}\n","import type { ParserState, UsagePatterns } from '../types';\n\nexport function createState(): ParserState {\n  const usagePatterns: UsagePatterns = {\n    namedImports: new Set(),\n    namespaceImports: new Set(),\n    defaultImports: new Set(),\n    aliasedImports: new Map(),\n    variableAssignments: new Map(),\n    lazyImports: new Set(),\n    dynamicImports: new Set(),\n    conditionalUsage: new Set(),\n    arrayMappings: new Set(),\n    objectMappings: new Set(),\n    hocUsage: new Set(),\n    forwardedRefs: new Set(),\n    memoizedComponents: new Set(),\n    portalUsage: new Set(),\n    jsxUsage: new Map(),\n    destructuredUsage: new Set(),\n    propsAnalysis: new Map(),\n  };\n\n  return {\n    usagePatterns,\n    componentNames: new Set(),\n    allIdentifiers: new Set(),\n  };\n}\n","import type { ImportDeclaration } from '@swc/core';\nimport type { ParserState } from '../types';\n\n/**\n * Analyzes import declarations and tracks all types:\n * - Default imports\n * - Named imports\n * - Namespace imports\n * - Aliased imports\n */\nexport function analyzeImportDeclaration(\n  node: ImportDeclaration,\n  state: ParserState,\n): void {\n  const source = node.source.value;\n\n  for (const spec of node.specifiers) {\n    switch (spec.type) {\n      case 'ImportDefaultSpecifier':\n        analyzeDefaultImport(spec, source, node, state);\n        break;\n\n      case 'ImportNamespaceSpecifier':\n        analyzeNamespaceImport(spec, source, node, state);\n        break;\n\n      case 'ImportSpecifier':\n        analyzeNamedImport(spec, source, node, state);\n        break;\n    }\n  }\n}\n\nfunction analyzeDefaultImport(\n  spec: any,\n  source: string,\n  node: ImportDeclaration,\n  state: ParserState,\n): void {\n  const name = spec.local.value;\n\n  state.usagePatterns.defaultImports.add({\n    name,\n    source,\n    line: node.span?.start || 0,\n  });\n\n  state.componentNames.add(name);\n}\n\nfunction analyzeNamespaceImport(\n  spec: any,\n  source: string,\n  node: ImportDeclaration,\n  state: ParserState,\n): void {\n  const name = spec.local.value;\n\n  state.usagePatterns.namespaceImports.add({\n    name,\n    source,\n    line: node.span?.start || 0,\n  });\n\n  state.allIdentifiers.add(name);\n}\n\nfunction analyzeNamedImport(\n  spec: any,\n  source: string,\n  node: ImportDeclaration,\n  state: ParserState,\n): void {\n  const importedName = spec.imported ? spec.imported.value : spec.local.value;\n  const localName = spec.local.value;\n\n  state.usagePatterns.namedImports.add({\n    name: importedName,\n    source,\n    line: node.span?.start || 0,\n  });\n\n  // Track aliases\n  if (importedName !== localName) {\n    state.usagePatterns.aliasedImports.set(localName, {\n      imported: importedName,\n      local: localName,\n      source,\n      line: node.span?.start || 0,\n    });\n  }\n\n  state.componentNames.add(localName);\n}\n","import type { ParserState } from '../types';\n\n/**\n * Extracts the name from a JSX element (handles identifiers and member expressions)\n */\nexport function getJSXElementName(nameNode: any): string {\n  if (!nameNode) return '';\n\n  switch (nameNode.type) {\n    case 'Identifier':\n      return nameNode.value;\n    case 'JSXMemberExpression':\n      return `${getJSXElementName(nameNode.object)}.${nameNode.property.value}`;\n    default:\n      return '';\n  }\n}\n\n/**\n * Checks if a JSX member expression is a known component\n */\nexport function isMemberExpressionComponent(\n  nameNode: any,\n  state: ParserState,\n): boolean {\n  if (nameNode?.type === 'JSXMemberExpression') {\n    const objectName = getJSXElementName(nameNode.object);\n    return state.allIdentifiers.has(objectName);\n  }\n  return false;\n}\n\n/**\n * Extracts props from JSX attributes\n */\nexport function extractJSXProps(attributes: any[]): Array<{\n  name: string;\n  value: any;\n  isSpread?: boolean;\n}> {\n  if (!attributes) return [];\n\n  return attributes\n    .map((attr) => {\n      if (attr.type === 'JSXAttribute') {\n        return {\n          name: attr.name?.value || attr.name?.name?.value,\n          value: extractJSXAttributeValue(attr.value),\n        };\n      }\n      if (attr.type === 'SpreadElement') {\n        return {\n          name: '...',\n          value: '[spread]',\n          isSpread: true,\n        };\n      }\n      return null;\n    })\n    .filter(Boolean) as Array<{\n    name: string;\n    value: any;\n    isSpread?: boolean;\n  }>;\n}\n\n/**\n * Extracts value from JSX attribute\n */\nexport function extractJSXAttributeValue(value: any): any {\n  if (!value) return true; // boolean attribute\n\n  switch (value.type) {\n    case 'StringLiteral':\n      return value.value;\n    case 'JSXExpressionContainer':\n      return extractExpressionValue(value.expression);\n    default:\n      return '[complex]';\n  }\n}\n\n/**\n * Extracts a readable value from an expression\n */\nexport function extractExpressionValue(expr: any): any {\n  if (!expr) return '[unknown]';\n\n  switch (expr.type) {\n    case 'StringLiteral':\n    case 'NumericLiteral':\n    case 'BooleanLiteral':\n      return expr.value;\n    case 'Identifier':\n      return `{${expr.value}}`;\n    case 'ArrowFunctionExpression':\n    case 'FunctionExpression':\n      return '[function]';\n    case 'ObjectExpression':\n      return '[object]';\n    case 'ArrayExpression':\n      return '[array]';\n    default:\n      return '[expression]';\n  }\n}\n\n/**\n * Determines the context where a component is being used\n */\nexport function getUsageContext(parent: any): string {\n  if (!parent) return 'direct';\n\n  switch (parent.type) {\n    case 'ConditionalExpression':\n      return 'conditional';\n    case 'ArrayExpression':\n      return 'array';\n    case 'ObjectExpression':\n      return 'object';\n    case 'CallExpression':\n      return 'hoc';\n    case 'VariableDeclarator':\n      return 'variable';\n    default:\n      return 'jsx';\n  }\n}\n","import type { PropsAnalysis, PropDetail, ParserState } from '../types';\n\n/**\n * Analyzes props in detail for a component\n */\nexport function analyzePropsInDetail(\n  attributes: any[],\n  componentName: string,\n  state: ParserState,\n): PropsAnalysis {\n  const analysis: PropsAnalysis = {\n    namedProps: [],\n    hasSpread: false,\n    hasComplexProps: false,\n    hasEventHandlers: false,\n    propDetails: [],\n  };\n\n  if (!attributes) return analysis;\n\n  for (const attr of attributes) {\n    if (attr.type === 'JSXAttribute') {\n      const propName = attr.name?.value || attr.name?.name?.value;\n      if (propName) {\n        analysis.namedProps.push(propName);\n\n        const propDetail: PropDetail = {\n          name: propName,\n          type: getPropType(attr.value),\n          isEventHandler: propName.startsWith('on'),\n          isComplex: isComplexProp(attr.value),\n        };\n\n        if (propDetail.isEventHandler) {\n          analysis.hasEventHandlers = true;\n        }\n        if (propDetail.isComplex) {\n          analysis.hasComplexProps = true;\n        }\n\n        analysis.propDetails.push(propDetail);\n      }\n    } else if (attr.type === 'SpreadElement') {\n      analysis.hasSpread = true;\n      analysis.propDetails.push({\n        name: '...',\n        type: 'spread',\n        isSpread: true,\n        isComplex: true,\n        isEventHandler: false,\n        warning: 'Spread props cannot be statically analyzed',\n      });\n      analysis.hasComplexProps = true;\n    }\n  }\n\n  // Store in state\n  state.usagePatterns.propsAnalysis.set(componentName, analysis);\n\n  return analysis;\n}\n\n/**\n * Determines the type of a prop value\n */\nfunction getPropType(value: any): string {\n  if (!value) return 'boolean';\n\n  switch (value.type) {\n    case 'StringLiteral':\n      return 'string';\n    case 'JSXExpressionContainer': {\n      const expr = value.expression;\n      if (!expr) return 'unknown';\n      switch (expr.type) {\n        case 'NumericLiteral':\n          return 'number';\n        case 'BooleanLiteral':\n          return 'boolean';\n        case 'StringLiteral':\n          return 'string';\n        case 'ArrowFunctionExpression':\n        case 'FunctionExpression':\n          return 'function';\n        case 'ObjectExpression':\n          return 'object';\n        case 'ArrayExpression':\n          return 'array';\n        case 'Identifier':\n          return 'variable';\n        default:\n          return 'expression';\n      }\n    }\n    default:\n      return 'unknown';\n  }\n}\n\n/**\n * Checks if a prop value is complex (object, array, call, conditional)\n */\nfunction isComplexProp(value: any): boolean {\n  if (!value) return false;\n  if (value.type === 'JSXExpressionContainer') {\n    const expr = value.expression;\n    if (!expr) return false;\n    return (\n      expr.type === 'ObjectExpression' ||\n      expr.type === 'ArrayExpression' ||\n      expr.type === 'CallExpression' ||\n      expr.type === 'ConditionalExpression'\n    );\n  }\n  return false;\n}\n","import type { ParserState, JSXUsage } from '../types';\nimport {\n  getJSXElementName,\n  isMemberExpressionComponent,\n  extractJSXProps,\n  getUsageContext,\n} from '../utils/jsx-helpers';\nimport { analyzePropsInDetail } from './props';\n\n/**\n * Analyzes JSX element usage\n */\nexport function analyzeJSXElement(node: any, state: ParserState): void {\n  if (node.opening) {\n    analyzeJSXOpeningElement(node.opening, state, node);\n  }\n}\n\n/**\n * Analyzes JSX opening element and tracks component usage\n */\nexport function analyzeJSXOpeningElement(\n  node: any,\n  state: ParserState,\n  parent?: any,\n): void {\n  const elementName = getJSXElementName(node.name);\n\n  // Check if this is a known component\n  if (\n    !state.componentNames.has(elementName) &&\n    !isMemberExpressionComponent(node.name, state)\n  ) {\n    return;\n  }\n\n  const propsAnalysis = analyzePropsInDetail(\n    node.attributes,\n    elementName,\n    state,\n  );\n  const usage: JSXUsage = {\n    component: elementName,\n    props: extractJSXProps(node.attributes).map((p) => p.name),\n    propsAnalysis,\n    line: node.span?.start || 0,\n    context: getUsageContext(parent),\n  };\n\n  // Track JSX usage\n  if (!state.usagePatterns.jsxUsage.has(elementName)) {\n    state.usagePatterns.jsxUsage.set(elementName, usage);\n  }\n}\n","import type { ParserState } from '../types';\n\n/**\n * Checks if a name is a known component from imports\n */\nexport function isKnownComponent(name: string, state: ParserState): boolean {\n  return state.componentNames.has(name) || state.allIdentifiers.has(name);\n}\n\n/**\n * Checks if a function name matches HOC patterns\n */\nexport function isHOCPattern(name: string): boolean {\n  const hocPatterns = ['with', 'enhance', 'wrap', 'connect', 'create'];\n  return hocPatterns.some((pattern) => name.startsWith(pattern));\n}\n\n/**\n * Checks if a node represents a HOC function call\n */\nexport function isHOCFunction(callee: any): boolean {\n  if (!callee) return false;\n\n  if (callee.type === 'Identifier') {\n    return isHOCPattern(callee.value);\n  }\n\n  if (callee.type === 'MemberExpression') {\n    const prop = callee.property;\n    return prop?.value && isHOCPattern(prop.value);\n  }\n\n  return false;\n}\n\n/**\n * Checks if an expression looks like a React component\n * (starts with capital letter)\n */\nexport function looksLikeComponent(name: string): boolean {\n  return /^[A-Z]/.test(name);\n}\n\n/**\n * Checks if source is from a specific library (for filtering)\n */\nexport function isFromLibrary(source: string, libraryName: string): boolean {\n  return source.startsWith(libraryName) || source.includes(libraryName);\n}\n","import type { ParserState } from '../types';\nimport { isKnownComponent } from '../utils/matchers';\n\n/**\n * Analyzes variable declarations for component assignments\n */\nexport function analyzeVariableDeclaration(\n  node: any,\n  state: ParserState,\n): void {\n  if (!node.declarations) return;\n\n  for (const decl of node.declarations) {\n    if (decl.id?.type === 'Identifier') {\n      const varName = decl.id.value;\n\n      // Check if it's assigning a component\n      if (decl.init) {\n        const assignment = extractAssignmentInfo(decl.init);\n        if (assignment && isKnownComponent(assignment, state)) {\n          state.usagePatterns.variableAssignments.set(varName, {\n            assignment,\n            line: node.span?.start || 0,\n          });\n          state.componentNames.add(varName);\n        }\n      }\n    }\n\n    // Handle destructuring assignments\n    if (decl.id?.type === 'ObjectPattern') {\n      analyzeDestructuringPattern(decl.id, decl.init, state);\n    }\n  }\n}\n\n/**\n * Analyzes destructuring patterns\n */\nexport function analyzeDestructuringPattern(\n  pattern: any,\n  init: any,\n  state: ParserState,\n): void {\n  if (!pattern.properties) return;\n\n  for (const prop of pattern.properties) {\n    if (\n      prop.type === 'AssignmentPatternProperty' &&\n      prop.key?.type === 'Identifier'\n    ) {\n      const propName = prop.key.value;\n\n      if (init?.type === 'Identifier' && state.allIdentifiers.has(init.value)) {\n        state.usagePatterns.destructuredUsage.add({\n          property: propName,\n          source: init.value,\n          line: pattern.span?.start || 0,\n        });\n        state.componentNames.add(propName);\n      }\n    }\n  }\n}\n\n/**\n * Extracts assignment information from various node types\n */\nfunction extractAssignmentInfo(node: any): string | null {\n  switch (node.type) {\n    case 'Identifier':\n      return node.value;\n    case 'MemberExpression':\n      return `${extractAssignmentInfo(node.object)}.${node.property.value}`;\n    case 'ConditionalExpression':\n      return `${extractAssignmentInfo(node.consequent)} | ${extractAssignmentInfo(node.alternate)}`;\n    default:\n      return null;\n  }\n}\n","import type { ParserState } from '../types';\n\n/**\n * Analyzes conditional expressions (ternary operators) with components\n */\nexport function analyzeConditionalExpression(\n  node: any,\n  state: ParserState,\n): void {\n  const consequent =\n    node.consequent?.type === 'Identifier' ? node.consequent.value : null;\n  const alternate =\n    node.alternate?.type === 'Identifier' ? node.alternate.value : null;\n\n  if (\n    (consequent && state.componentNames.has(consequent)) ||\n    (alternate && state.componentNames.has(alternate))\n  ) {\n    state.usagePatterns.conditionalUsage.add({\n      consequent: consequent || '',\n      alternate: alternate || '',\n      line: node.span?.start || 0,\n    });\n  }\n}\n","import type { ParserState } from '../types';\n\n/**\n * Analyzes array expressions containing components\n */\nexport function analyzeArrayExpression(node: any, state: ParserState): void {\n  // Check if array contains components\n  const hasComponents = node.elements?.some((elem: any) => {\n    if (elem?.expression?.type === 'Identifier') {\n      return state.componentNames.has(elem.expression.value);\n    }\n    return false;\n  });\n\n  if (hasComponents) {\n    state.usagePatterns.arrayMappings.add({\n      components: node.elements\n        ?.map((elem: any) => elem?.expression?.value)\n        .filter(Boolean),\n      line: node.span?.start || 0,\n    });\n  }\n}\n\n/**\n * Analyzes object expressions with component mappings\n */\nexport function analyzeObjectExpression(node: any, state: ParserState): void {\n  // Check if object contains component mappings\n  const componentProps = node.properties?.filter((prop: any) => {\n    if (prop.type === 'KeyValueProperty' && prop.value?.type === 'Identifier') {\n      return state.componentNames.has(prop.value.value);\n    }\n    return false;\n  });\n\n  if (componentProps?.length > 0) {\n    state.usagePatterns.objectMappings.add({\n      mappings: componentProps.map((prop: any) => ({\n        key: prop.key?.value || '[computed]',\n        component: prop.value?.value,\n      })),\n      line: node.span?.start || 0,\n    });\n  }\n}\n","import type { ParserState } from '../types';\n\n/**\n * Analyzes React.lazy() imports\n */\nexport function analyzeLazyImport(node: any, state: ParserState): void {\n  const arg = node.arguments?.[0]?.expression;\n  if (\n    arg?.type === 'ArrowFunctionExpression' &&\n    arg.body?.type === 'CallExpression'\n  ) {\n    const importCall = arg.body;\n    if (importCall.callee?.type === 'Import') {\n      const source = importCall.arguments?.[0]?.expression?.value;\n      if (source) {\n        state.usagePatterns.lazyImports.add({\n          source,\n          line: node.span?.start || 0,\n        });\n      }\n    }\n  }\n}\n\n/**\n * Analyzes dynamic import() calls\n */\nexport function analyzeDynamicImport(node: any, state: ParserState): void {\n  const source = node.arguments?.[0]?.expression?.value;\n  if (source) {\n    state.usagePatterns.dynamicImports.add({\n      source,\n      line: node.span?.start || 0,\n    });\n  }\n}\n","import type { ParserState } from '../types';\n\n/**\n * Analyzes Higher-Order Component (HOC) usage\n */\nexport function analyzeHOCUsage(node: any, state: ParserState): void {\n  state.usagePatterns.hocUsage.add({\n    function: node.callee?.value || '[unknown]',\n    component: node.arguments?.[0]?.expression?.value || '[unknown]',\n    line: node.span?.start || 0,\n  });\n}\n\n/**\n * Analyzes React.memo() usage\n */\nexport function analyzeMemoUsage(node: any, state: ParserState): void {\n  const component = node.arguments?.[0]?.expression;\n  if (\n    component?.type === 'Identifier' &&\n    state.componentNames.has(component.value)\n  ) {\n    state.usagePatterns.memoizedComponents.add({\n      component: component.value,\n      line: node.span?.start || 0,\n    });\n  }\n}\n\n/**\n * Analyzes React.forwardRef() usage\n */\nexport function analyzeForwardRefUsage(node: any, state: ParserState): void {\n  state.usagePatterns.forwardedRefs.add({\n    line: node.span?.start || 0,\n  });\n}\n\n/**\n * Analyzes ReactDOM.createPortal() usage\n */\nexport function analyzePortalUsage(node: any, state: ParserState): void {\n  state.usagePatterns.portalUsage.add({\n    line: node.span?.start || 0,\n  });\n}\n\n/**\n * Analyzes member expression access (e.g., Foundation.Button)\n */\nexport function analyzeMemberExpression(node: any, state: ParserState): void {\n  // Check if this is a namespace access like Foundation.Button\n  if (\n    node.object?.type === 'Identifier' &&\n    state.allIdentifiers.has(node.object.value)\n  ) {\n    // const namespaceName = node.object.value;\n    const propertyName = node.property?.value;\n\n    if (propertyName) {\n      // Track namespace property access\n      state.componentNames.add(propertyName);\n    }\n  }\n}\n\n/**\n * Checks if a node represents HOC pattern\n */\nexport function isHOCPattern(node: any, state: ParserState): boolean {\n  // Simple heuristic: function that returns a component-like structure\n  return (\n    node.callee?.type === 'Identifier' &&\n    node.arguments?.some(\n      (arg: any) =>\n        arg.expression?.type === 'Identifier' &&\n        state.componentNames.has(arg.expression.value),\n    )\n  );\n}\n","import type { ParserState, VisitorContext } from '../types';\nimport { analyzeImportDeclaration } from '../patterns/imports';\nimport { analyzeJSXElement, analyzeJSXOpeningElement } from '../patterns/jsx';\nimport { analyzeVariableDeclaration } from '../patterns/variables';\nimport { analyzeConditionalExpression } from '../patterns/conditionals';\nimport {\n  analyzeArrayExpression,\n  analyzeObjectExpression,\n} from '../patterns/collections';\nimport {\n  analyzeLazyImport,\n  analyzeDynamicImport,\n} from '../patterns/lazy-dynamic';\nimport {\n  analyzeHOCUsage,\n  analyzeMemoUsage,\n  analyzeForwardRefUsage,\n  analyzePortalUsage,\n  analyzeMemberExpression,\n  isHOCPattern,\n} from '../patterns/advanced';\n\n/**\n * Main AST visitor that routes nodes to appropriate pattern analyzers\n */\nexport function visitNode(\n  node: any,\n  state: ParserState,\n  context: VisitorContext = {},\n): void {\n  if (!node) return;\n\n  switch (node.type) {\n    case 'Module':\n      // Process imports first (they populate componentNames)\n      if (node.body) {\n        for (const item of node.body) {\n          if (item.type === 'ImportDeclaration') {\n            visitNode(item, state, context);\n          }\n        }\n        // Then process everything else\n        for (const item of node.body) {\n          if (item.type !== 'ImportDeclaration') {\n            visitNode(item, state, { ...context, parent: node });\n          }\n        }\n      }\n      break;\n\n    case 'ImportDeclaration':\n      analyzeImportDeclaration(node, state);\n      break;\n\n    case 'CallExpression':\n      analyzeCallExpression(node, state, context);\n      break;\n\n    case 'VariableDeclaration':\n      analyzeVariableDeclaration(node, state);\n      visitChildren(node, state, context);\n      break;\n\n    case 'JSXElement':\n    case 'JSXFragment':\n      analyzeJSXElement(node, state);\n      visitChildren(node, state, context);\n      break;\n\n    case 'JSXOpeningElement':\n      analyzeJSXOpeningElement(node, state, context.parent);\n      visitChildren(node, state, { ...context, parent: node });\n      break;\n\n    case 'ArrayExpression':\n      analyzeArrayExpression(node, state);\n      visitChildren(node, state, context);\n      break;\n\n    case 'ObjectExpression':\n      analyzeObjectExpression(node, state);\n      visitChildren(node, state, context);\n      break;\n\n    case 'MemberExpression':\n      analyzeMemberExpression(node, state);\n      visitChildren(node, state, context);\n      break;\n\n    case 'ConditionalExpression':\n      analyzeConditionalExpression(node, state);\n      visitChildren(node, state, context);\n      break;\n\n    case 'FunctionDeclaration':\n    case 'ClassDeclaration':\n    case 'ExpressionStatement':\n    case 'ReturnStatement':\n    case 'VariableDeclarator':\n    case 'ArrowFunctionExpression':\n    case 'FunctionExpression':\n      visitChildren(node, state, { ...context, parent: node });\n      break;\n\n    default:\n      visitChildren(node, state, context);\n      break;\n  }\n}\n\n/**\n * Analyzes call expressions and routes to specific analyzers\n */\nfunction analyzeCallExpression(\n  node: any,\n  state: ParserState,\n  context: VisitorContext,\n): void {\n  // Analyze lazy imports\n  if (\n    node.callee?.value === 'lazy' ||\n    (node.callee?.object?.value === 'React' &&\n      node.callee?.property?.value === 'lazy')\n  ) {\n    analyzeLazyImport(node, state);\n  }\n\n  // Analyze dynamic imports\n  if (node.callee?.type === 'Import') {\n    analyzeDynamicImport(node, state);\n  }\n\n  // Analyze HOC patterns\n  if (isHOCPattern(node, state)) {\n    analyzeHOCUsage(node, state);\n  }\n\n  // Analyze React.memo, React.forwardRef\n  if (node.callee?.object?.value === 'React') {\n    if (node.callee?.property?.value === 'memo') {\n      analyzeMemoUsage(node, state);\n    } else if (node.callee?.property?.value === 'forwardRef') {\n      analyzeForwardRefUsage(node, state);\n    }\n  }\n\n  // Analyze createPortal\n  if (\n    node.callee?.property?.value === 'createPortal' ||\n    node.callee?.value === 'createPortal'\n  ) {\n    analyzePortalUsage(node, state);\n  }\n\n  visitChildren(node, state, context);\n}\n\n/**\n * Visits all children of a node\n */\nfunction visitChildren(\n  node: any,\n  state: ParserState,\n  context: VisitorContext,\n): void {\n  if (!node) return;\n\n  for (const key in node) {\n    const value = node[key];\n\n    if (Array.isArray(value)) {\n      for (const item of value) {\n        if (item && typeof item === 'object') {\n          visitNode(item, state, { ...context, parent: node });\n        }\n      }\n    } else if (value && typeof value === 'object' && value.type) {\n      visitNode(value, state, { ...context, parent: node });\n    }\n  }\n}\n","import type { ParserState, UsageReport } from '../types';\n\n/**\n * Generates a comprehensive usage report from parser state\n */\nexport function generateReport(\n  state: ParserState,\n  filePath: string,\n): UsageReport {\n  const report: UsageReport = {\n    filePath,\n    summary: {\n      totalImports:\n        state.usagePatterns.defaultImports.size +\n        state.usagePatterns.namedImports.size +\n        state.usagePatterns.namespaceImports.size,\n      totalComponents: state.componentNames.size,\n      totalUsagePatterns: calculateTotalPatterns(state),\n    },\n    patterns: {\n      imports: {\n        default: Array.from(state.usagePatterns.defaultImports),\n        named: Array.from(state.usagePatterns.namedImports),\n        namespace: Array.from(state.usagePatterns.namespaceImports),\n        aliased: Array.from(state.usagePatterns.aliasedImports.values()),\n      },\n      usage: {\n        jsx: Array.from(state.usagePatterns.jsxUsage.values()),\n        variables: Array.from(\n          state.usagePatterns.variableAssignments.entries(),\n        ).map(([key, value]) => ({\n          variable: key,\n          assignment: value.assignment,\n        })),\n        destructuring: Array.from(state.usagePatterns.destructuredUsage),\n        conditional: Array.from(state.usagePatterns.conditionalUsage),\n        arrays: Array.from(state.usagePatterns.arrayMappings),\n        objects: Array.from(state.usagePatterns.objectMappings),\n      },\n      advanced: {\n        lazy: Array.from(state.usagePatterns.lazyImports),\n        dynamic: Array.from(state.usagePatterns.dynamicImports),\n        hoc: Array.from(state.usagePatterns.hocUsage),\n        memo: Array.from(state.usagePatterns.memoizedComponents),\n        forwardRef: Array.from(state.usagePatterns.forwardedRefs),\n        portal: Array.from(state.usagePatterns.portalUsage),\n      },\n      props: Array.from(state.usagePatterns.propsAnalysis.entries()).map(\n        ([component, analysis]) => ({\n          component,\n          analysis,\n        }),\n      ),\n    },\n    components: Array.from(state.componentNames).sort(),\n  };\n\n  return report;\n}\n\n/**\n * Calculates total number of usage patterns found\n */\nfunction calculateTotalPatterns(state: ParserState): number {\n  return Object.values(state.usagePatterns).reduce((sum, collection) => {\n    if (collection instanceof Set || collection instanceof Map) {\n      return sum + collection.size;\n    }\n    return sum;\n  }, 0);\n}\n","import { parseSync } from '@swc/core';\nimport type { ParseOptions as SwcParseOptions } from '@swc/core';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { UsageReport } from './types';\nimport { createState } from './core/state';\nimport { visitNode } from './core/visitor';\nimport { generateReport } from './core/report';\n\nfunction swcOptionsForFile(filePath: string): SwcParseOptions {\n  const ext = path.extname(filePath).toLowerCase();\n  if (ext === '.ts')\n    return {\n      syntax: 'typescript',\n      tsx: false,\n      decorators: true,\n      dynamicImport: true,\n    };\n  if (ext === '.tsx')\n    return {\n      syntax: 'typescript',\n      tsx: true,\n      decorators: true,\n      dynamicImport: true,\n    };\n  if (ext === '.jsx')\n    return {\n      syntax: 'ecmascript',\n      jsx: true,\n      decorators: true,\n      importAssertions: true,\n    };\n  // .js / .mjs / .cjs\n  return {\n    syntax: 'ecmascript',\n    jsx: true,\n    decorators: true,\n    importAssertions: true,\n  };\n}\n\nexport function parseCode(code: string, filePath = 'file.tsx'): UsageReport {\n  const state = createState();\n  const ast = parseSync(code, swcOptionsForFile(filePath));\n  visitNode(ast, state);\n  return generateReport(state, filePath);\n}\n\nexport function parseFile(filePath: string): UsageReport | null {\n  const code = fs.readFileSync(filePath, 'utf8');\n  return parseCode(code, filePath);\n}\n\nexport type { UsageReport } from './types';\n","import micromatch from 'micromatch';\nimport type { ResolvedHermexConfig } from '../config/types';\nimport type { LockfileResolutionMap, MultiVersionMap } from '../lock-parser';\n\n/** A `package.json` field that declares dependencies. */\nexport type DependencyBucket =\n  | 'dependencies'\n  | 'devDependencies'\n  | 'peerDependencies'\n  | 'optionalDependencies';\n\n/** Package name → the manifest buckets that declare it. */\nexport type DeclaredPackages = Record<string, DependencyBucket[]>;\n\nexport interface ComponentUsage {\n  name: string;\n  source: string;\n  count: number;\n  files: Set<string>;\n}\n\n/**\n * One package, with every axis hermex knows about it. A package can be\n * present on any combination of the three:\n *\n * - **declared** — listed in this repo's `package.json` (`declaredIn`).\n * - **installed** — present in the lockfile, as a direct dependency\n *   (`rootVersion`) and/or as one or more resolved copies (`allVersions`).\n *   This is the `root` vs `tree` distinction `releaseAge.scope` already\n *   exposes to users.\n * - **used** — imported by scanned source (`usageCount` > 0).\n *\n * A transitive dependency is installed but neither declared nor used; a\n * build tool run via `npx` is declared and installed but not used; a phantom\n * dependency is used but neither declared nor installed.\n */\nexport interface PackageInventoryEntry {\n  packageName: string;\n  /** Manifest buckets declaring this package; empty when undeclared. */\n  declaredIn: DependencyBucket[];\n  /** Effective installed version — `rootVersion` when known, else the highest resolved copy. `null` when not installed. */\n  version: string | null;\n  /** Version of the direct/root dependency declaration; `null` when the package is purely transitive. */\n  rootVersion: string | null;\n  /** Every resolved copy in the lockfile — the `tree` axis. */\n  allVersions: string[];\n  hasVersionConflict: boolean;\n  /** Matches `packages.internal`. */\n  internal: boolean;\n  /** Matches `packages.ignore`. Kept in the inventory rather than filtered out at construction so each consumer can decide — the packages table and forbid rules skip these, `require_packages` deliberately does not. */\n  ignored: boolean;\n  usageCount: number;\n  /**\n   * How many distinct components this package supplies. The names themselves\n   * live only in the aggregator's flat component list (#79) — carrying them\n   * here too meant the same strings were serialized twice, and every\n   * consumer had to decide which copy was canonical.\n   */\n  componentCount: number;\n}\n\nexport interface BuildInventoryInput {\n  /** Effective installed version per package, from the lockfile layer. */\n  versions?: Record<string, string>;\n  multiVersions?: MultiVersionMap;\n  resolutions?: LockfileResolutionMap;\n  /** Manifest declarations, from `collectDeclaredPackages`. */\n  declared?: DeclaredPackages;\n  /** Component usage keyed by `source::component`, from the aggregator. */\n  componentUsage?: Map<string, ComponentUsage>;\n  config?: ResolvedHermexConfig;\n}\n\n/**\n * Sources that are not packages at all — a relative import, or one that\n * could not be resolved against any known package name.\n */\nconst NON_PACKAGE_SOURCES = new Set(['local', 'unknown']);\n\n/**\n * Compiles a glob list once and reuses it. `micromatch.isMatch` re-parses its\n * patterns on every call, which is fine for a handful of packages but not\n * when the inventory spans an entire lockfile (thousands of entries × every\n * configured pattern).\n */\nfunction createGlobMatcher(patterns: string[]): (name: string) => boolean {\n  if (patterns.length === 0) return () => false;\n  const matchers = patterns.map((pattern) => micromatch.matcher(pattern));\n  return (name) => matchers.some((match) => match(name));\n}\n\nfunction getPackageVersion(\n  packageName: string,\n  versions: Record<string, string>,\n): string | null {\n  if (versions[packageName]) return versions[packageName];\n\n  if (packageName.includes('/')) {\n    const parts = packageName.split('/');\n    if (packageName.startsWith('@') && parts.length > 2) {\n      const basePackage = `${parts[0]}/${parts[1]}`;\n      if (versions[basePackage]) return versions[basePackage];\n    }\n    if (!packageName.startsWith('@') && parts.length > 1) {\n      if (versions[parts[0]]) return versions[parts[0]];\n    }\n  }\n\n  return null;\n}\n\n// Same base-package fallback as getPackageVersion (a subpath import like\n// `@scope/pkg/sub` resolves to `@scope/pkg`'s data), but reading the true\n// root/direct-dependency version from the lockfile layer's resolutions\n// rather than the `rootVersion ?? maxSemver(allVersions)` fallback baked\n// into `versions`. `null` here (as opposed to `versions` being silently\n// absent) is the signal `scope: 'root'` needs to correctly decline to\n// enforce a package that was never a direct dependency in the first place.\nfunction getRootVersion(\n  packageName: string,\n  resolutions: LockfileResolutionMap,\n): string | null {\n  if (resolutions[packageName]) return resolutions[packageName].rootVersion;\n\n  if (packageName.includes('/')) {\n    const parts = packageName.split('/');\n    if (packageName.startsWith('@') && parts.length > 2) {\n      const basePackage = `${parts[0]}/${parts[1]}`;\n      if (resolutions[basePackage]) return resolutions[basePackage].rootVersion;\n    }\n    if (!packageName.startsWith('@') && parts.length > 1) {\n      if (resolutions[parts[0]]) return resolutions[parts[0]].rootVersion;\n    }\n  }\n\n  return null;\n}\n\n/**\n * The single list of packages every downstream consumer reads.\n *\n * Before this existed, each feature answered \"what packages are in this\n * repo?\" for itself — the packages table and `forbid_packages` from import\n * analysis, `require_packages` from the lockfile, `forbid_package_fields`\n * from the manifest — so a package could be visible to one rule and\n * invisible to another (#75). Merging the three axes once, here, means the\n * features differ only in which axis they *select*, not in what they can\n * see.\n */\nexport function buildPackageInventory(\n  input: BuildInventoryInput = {},\n): PackageInventoryEntry[] {\n  const {\n    versions = {},\n    multiVersions = {},\n    resolutions = {},\n    declared = {},\n    componentUsage,\n    config,\n  } = input;\n\n  const isIgnored = createGlobMatcher(config?.packages.ignore ?? []);\n  const isInternal = createGlobMatcher(config?.packages.internal ?? []);\n\n  // Fold component usage up to one record per package first — several\n  // components can come from the same source.\n  const usage = new Map<\n    string,\n    { usageCount: number; componentCount: number }\n  >();\n  for (const component of componentUsage?.values() ?? []) {\n    if (NON_PACKAGE_SOURCES.has(component.source)) continue;\n\n    const existing = usage.get(component.source);\n    if (existing) {\n      existing.usageCount += component.count;\n      existing.componentCount++;\n    } else {\n      usage.set(component.source, {\n        usageCount: component.count,\n        componentCount: 1,\n      });\n    }\n  }\n\n  // Used packages first so the inventory (and every view derived from it)\n  // stays usage-ordered; declared-only and transitive packages follow.\n  const names = new Set<string>([\n    ...usage.keys(),\n    ...Object.keys(declared),\n    ...Object.keys(versions),\n    ...Object.keys(resolutions),\n  ]);\n\n  const entries: PackageInventoryEntry[] = [];\n  for (const packageName of names) {\n    const packageUsage = usage.get(packageName);\n    const allVersions = multiVersions[packageName] ?? [];\n\n    entries.push({\n      packageName,\n      declaredIn: declared[packageName] ?? [],\n      version: getPackageVersion(packageName, versions),\n      rootVersion: getRootVersion(packageName, resolutions),\n      allVersions,\n      hasVersionConflict: allVersions.length > 1,\n      internal: isInternal(packageName),\n      ignored: isIgnored(packageName),\n      usageCount: packageUsage?.usageCount ?? 0,\n      componentCount: packageUsage?.componentCount ?? 0,\n    });\n  }\n\n  // Stable sort — equal usage keeps insertion order, so the usage-ranked\n  // head is deterministic and the tail stays in discovery order.\n  return entries.sort((a, b) => b.usageCount - a.usageCount);\n}\n\n/** Declared in this repo's `package.json`, in any dependency bucket. */\nexport function isDeclared(entry: PackageInventoryEntry): boolean {\n  return entry.declaredIn.length > 0;\n}\n\n/** Imported by scanned source. */\nexport function isUsed(entry: PackageInventoryEntry): boolean {\n  return entry.usageCount > 0;\n}\n\n/**\n * Present in the lockfile. `root` counts only direct dependencies; `tree`\n * counts any resolved copy, including purely transitive ones — the same\n * axis `releaseAge.scope` exposes.\n */\nexport function isInstalled(\n  entry: PackageInventoryEntry,\n  scope: 'root' | 'tree' = 'tree',\n): boolean {\n  if (scope === 'root') return entry.rootVersion !== null;\n  return entry.version !== null || entry.allVersions.length > 0;\n}\n\n/**\n * Packages this repo owns — the ones it can actually add or remove. Excludes\n * purely transitive dependencies (nothing the repo can do about those short\n * of dropping the parent) and anything under `packages.ignore`.\n *\n * \"Declared\" is taken from two independent sources: `package.json`, and the\n * lockfile's own record of the root project's direct dependencies (pnpm's\n * `importers`, npm's root `packages` entry, yarn's ranges read back from the\n * manifest). They normally agree, and either one alone is enough — so a repo\n * whose manifest cannot be read still gets its direct dependencies checked,\n * and a manifest entry missing from the lockfile is still checked too.\n *\n * The used axis is included because a package can be imported without being\n * declared anywhere (a phantom dependency), and that is still the repo's to\n * remove.\n */\nexport function isOwnedByRepo(entry: PackageInventoryEntry): boolean {\n  return (\n    !entry.ignored &&\n    (isDeclared(entry) || isInstalled(entry, 'root') || isUsed(entry))\n  );\n}\n","import micromatch from 'micromatch';\nimport type { UsageReport } from '../swc-parser';\nimport type { ReleaseAgeEntry } from '../npm-registry/types';\nimport type { ResolvedHermexConfig } from '../config/types';\nimport type {\n  DependencyBucket,\n  PackageInventoryEntry,\n} from './package-inventory';\nimport { isInstalled, isOwnedByRepo } from './package-inventory';\n\nexport type { ComponentUsage } from './package-inventory';\n\nexport interface PackageDistribution {\n  packageName: string;\n  version: string | null;\n  /**\n   * The `package.json` buckets declaring this package; empty when the repo\n   * imports it without declaring it (a phantom dependency) or the lockfile\n   * alone records it as a direct dependency.\n   */\n  declaredIn: DependencyBucket[];\n  componentCount: number;\n  usageCount: number;\n  /** Share of total measured component usage. 0 for a package that is never rendered as a component — which includes every package used only as a function. */\n  percentage: number;\n  internal: boolean;\n  hasVersionConflict: boolean;\n  allVersions: string[];\n  /**\n   * The version resolved for this package's root/direct dependency\n   * declaration (from the lockfile layer's `PackageResolution.rootVersion`),\n   * or `null` when the package is confirmed NOT a direct dependency (purely\n   * transitive). `undefined` (the value if never set — e.g. a hand-built\n   * `PackageDistribution` in a test) is treated as \"unknown, assume root\"\n   * for backward compatibility — only an explicit `null` marks a package as\n   * definitively non-root, which is what makes `scope: 'root'` correctly\n   * decline to enforce it (releaseAge would otherwise silently fall back to\n   * the highest resolved version and enforce THAT, wrongly treating a\n   * transitive-only package as if it were a root dependency).\n   */\n  rootVersion?: string | null;\n  releaseAge?: ReleaseAgeEntry;\n}\n\nfunction resolvePackageFromImportPath(\n  importPath: string,\n  availablePackages: string[],\n): string {\n  if (importPath.startsWith('.') || importPath.startsWith('/')) {\n    return 'local';\n  }\n\n  const sortedPackages = [...availablePackages].sort(\n    (a, b) => b.length - a.length,\n  );\n\n  for (const pkg of sortedPackages) {\n    if (importPath === pkg) return pkg;\n    if (importPath.startsWith(`${pkg}/`)) return pkg;\n  }\n\n  return 'unknown';\n}\n\nexport function findComponentSource(\n  componentName: string,\n  report: UsageReport,\n  availablePackages: string[],\n): string {\n  const namedImport = report.patterns.imports.named.find(\n    (imp) => imp.name === componentName,\n  );\n  if (namedImport)\n    return resolvePackageFromImportPath(namedImport.source, availablePackages);\n\n  const defaultImport = report.patterns.imports.default.find(\n    (imp) => imp.name === componentName,\n  );\n  if (defaultImport)\n    return resolvePackageFromImportPath(\n      defaultImport.source,\n      availablePackages,\n    );\n\n  const aliasedImport = report.patterns.imports.aliased.find(\n    (imp) => imp.local === componentName,\n  );\n  if (aliasedImport)\n    return resolvePackageFromImportPath(\n      aliasedImport.source,\n      availablePackages,\n    );\n\n  return 'unknown';\n}\n\n/**\n * The reported view of the package inventory: what the packages table and\n * the JSON `packages[]` array show.\n *\n * Selects the packages this repo *owns* (`isOwnedByRepo`) — declared in\n * `package.json`, recorded as a direct dependency by the lockfile, and/or\n * imported by scanned source. Before #78 this selected the *used* axis\n * instead, which made the name a lie: usage is measured from JSX component\n * rendering, so a package imported and called as a function (`lodash`,\n * `moment`) never appeared, and a repo with no JSX at all reported zero\n * packages while depending on dozens. \"Does this repo depend on X?\" is the\n * question the field's name promises to answer, and now does.\n *\n * Purely transitive dependencies stay out: `isOwnedByRepo` excludes them, so\n * this is still the repo's own dependency surface rather than the whole\n * lockfile. The one exception is a transitive package explicitly named by\n * `releaseAge.enforceOn` — installed and deliberately enforced, yet owned by\n * nobody. Dropping it here would silently exempt it from compliance, so it\n * is surfaced with zero usage.\n *\n * Note this is deliberately NOT the set release-age enrichment operates on —\n * see `isReleaseAgeTarget`. Enriching every owned package would fire a\n * registry request per declared dependency, and (with the default empty\n * `enforceOn`, which marks every fetched package `severity: 'error'`) would\n * turn newly-visible overdue dependencies into mandatory compliance\n * failures for repos that pass today.\n */\nexport function calculatePackageDistribution(\n  inventory: PackageInventoryEntry[],\n  config?: ResolvedHermexConfig,\n): PackageDistribution[] {\n  const enforceOnPatterns = config?.releaseAge.enforceOn ?? [];\n  const enforcesUnownedPackages =\n    (config?.releaseAge.enabled ?? false) && enforceOnPatterns.length > 0;\n\n  const distribution = inventory\n    .filter((entry) => {\n      if (entry.ignored) return false;\n      if (isOwnedByRepo(entry)) return true;\n      // Transitive, but explicitly enforced. Requires an installed version:\n      // there is no release date to check without one.\n      return (\n        enforcesUnownedPackages &&\n        isInstalled(entry) &&\n        micromatch.isMatch(entry.packageName, enforceOnPatterns)\n      );\n    })\n    .map((entry) => ({\n      packageName: entry.packageName,\n      version: entry.version,\n      rootVersion: entry.rootVersion,\n      declaredIn: entry.declaredIn,\n      componentCount: entry.componentCount,\n      usageCount: entry.usageCount,\n      percentage: 0,\n      internal: entry.internal,\n      hasVersionConflict: entry.hasVersionConflict,\n      allVersions: entry.allVersions,\n    }));\n\n  const totalExternalUsage = distribution.reduce(\n    (sum, pkg) => sum + pkg.usageCount,\n    0,\n  );\n\n  for (const pkg of distribution) {\n    pkg.percentage =\n      totalExternalUsage > 0 ? (pkg.usageCount / totalExternalUsage) * 100 : 0;\n  }\n\n  // The inventory is already usage-ordered; re-sorting keeps this view\n  // self-contained rather than silently depending on that. Equal usage keeps\n  // insertion order, so the zero-usage tail stays in discovery order.\n  return distribution.sort((a, b) => b.usageCount - a.usageCount);\n}\n\n/**\n * Whether release-age enrichment should look this package up in the\n * registry. Deliberately narrower than `packages[]` itself (#78): that array\n * is now every package the repo owns, and enriching all of them would\n * - fire one registry request per declared dependency rather than per\n *   *used* one, and\n * - with the default empty `enforceOn` — which `enricher.ts` reads as\n *   \"everything is severity `error`\" — promote every newly-visible overdue\n *   dependency to a mandatory violation, flipping `comply` to a failure for\n *   repos that pass today.\n *\n * So the target set is exactly what it was before `packages[]` expanded:\n * packages with measured usage, plus `enforceOn` matches (which can be\n * installed and explicitly enforced yet never imported as a component — a\n * side-effect-only `import '@acme-ui/pulse-styles/button.css'` has no\n * specifiers, so the usage scan never sees it, and skipping it would\n * silently exempt it from compliance).\n */\nexport function isReleaseAgeTarget(\n  pkg: Pick<PackageDistribution, 'packageName' | 'usageCount'>,\n  enforceOn: string[],\n): boolean {\n  if (pkg.usageCount > 0) return true;\n  return enforceOn.length > 0 && micromatch.isMatch(pkg.packageName, enforceOn);\n}\n","import micromatch from 'micromatch';\nimport type { ResolvedHermexConfig } from '../config/types';\nimport type { RuleViolation } from '../rules/evaluator';\nimport type { PackageInventoryEntry } from './package-inventory';\nimport { isInstalled, isOwnedByRepo, isUsed } from './package-inventory';\n\n/**\n * Selects the packages this repo owns (`isOwnedByRepo`): declared in\n * `package.json`, recorded as a direct dependency by the lockfile, and/or\n * imported by scanned source.\n *\n * Matching usage alone was the bug behind #75: the usage axis is built from\n * component imports, so build-only tooling — invoked via `npx`, an npm\n * script or a git hook, and never imported — was invisible to a rule that\n * named it outright. Purely transitive dependencies stay out of scope: the\n * repo cannot remove one without dropping its parent, so flagging it would\n * report a violation nobody can fix.\n *\n * Returns `RuleViolation`s like every other rule (#77). One violation per\n * matched package, so a glob rule (`@legacy/*`) hitting three packages\n * yields three entries sharing `patterns` and differing on `packageName` —\n * `matchedFiles` stays empty because the inventory carries no file paths,\n * and a hit can be declared-only with no files at all (#75).\n */\nexport function detectForbiddenPackages(\n  inventory: PackageInventoryEntry[],\n  config?: ResolvedHermexConfig,\n): RuleViolation[] {\n  const forbidRules = config?.rules.forbid_packages ?? [];\n  if (forbidRules.length === 0) {\n    return [];\n  }\n\n  const violations: RuleViolation[] = [];\n  for (const entry of inventory) {\n    if (!isOwnedByRepo(entry)) continue;\n\n    for (const rule of forbidRules) {\n      if (micromatch.isMatch(entry.packageName, rule.patterns)) {\n        violations.push({\n          type: 'forbid_packages',\n          severity: rule.severity,\n          patterns: rule.patterns,\n          message: rule.message,\n          matchedFiles: [],\n          packageName: entry.packageName,\n        });\n        break;\n      }\n    }\n  }\n  return violations;\n}\n\n/**\n * Selects the *installed* axis (plus used, to cover a phantom dependency\n * that is imported without being in the lockfile).\n *\n * Deliberately not `isOwnedByRepo`: \"required\" means the package must be\n * available to the code, so a transitive copy satisfies it, and a name in\n * `packages.ignore` — excluded from *reporting*, not uninstalled — must not\n * suddenly count as missing. Being declared but absent from the lockfile,\n * on the other hand, is a genuinely unsatisfied requirement.\n */\nexport function detectRequiredPackages(\n  inventory: PackageInventoryEntry[],\n  config?: ResolvedHermexConfig,\n): RuleViolation[] {\n  const requireRules = config?.rules.require_packages ?? [];\n  if (requireRules.length === 0) return [];\n\n  const installedNames = inventory\n    .filter((entry) => isInstalled(entry) || isUsed(entry))\n    .map((entry) => entry.packageName);\n\n  const violations: RuleViolation[] = [];\n  for (const rule of requireRules) {\n    const satisfied = rule.patterns.some((p) =>\n      installedNames.some((name) => micromatch.isMatch(name, p)),\n    );\n    if (!satisfied) {\n      violations.push({\n        type: 'require_packages',\n        severity: rule.severity,\n        patterns: rule.patterns,\n        message: rule.message,\n        matchedFiles: [],\n      });\n    }\n  }\n  return violations;\n}\n","import type { UsageReport } from '../swc-parser';\n\nexport interface PatternCount {\n  patternType: string;\n  displayName: string;\n  count: number;\n}\n\nexport function countPatterns(\n  report: UsageReport,\n  patternMap: Map<string, number>,\n) {\n  increment(\n    patternMap,\n    'imports.default',\n    report.patterns.imports.default.length,\n  );\n  increment(patternMap, 'imports.named', report.patterns.imports.named.length);\n  increment(\n    patternMap,\n    'imports.namespace',\n    report.patterns.imports.namespace.length,\n  );\n  increment(\n    patternMap,\n    'imports.aliased',\n    report.patterns.imports.aliased.length,\n  );\n  increment(patternMap, 'usage.jsx', report.patterns.usage.jsx.length);\n  increment(\n    patternMap,\n    'usage.variables',\n    report.patterns.usage.variables.length,\n  );\n  increment(\n    patternMap,\n    'usage.destructuring',\n    report.patterns.usage.destructuring.length,\n  );\n  increment(\n    patternMap,\n    'usage.conditional',\n    report.patterns.usage.conditional.length,\n  );\n  increment(patternMap, 'usage.arrays', report.patterns.usage.arrays.length);\n  increment(patternMap, 'usage.objects', report.patterns.usage.objects.length);\n  increment(patternMap, 'advanced.lazy', report.patterns.advanced.lazy.length);\n  increment(\n    patternMap,\n    'advanced.dynamic',\n    report.patterns.advanced.dynamic.length,\n  );\n  increment(patternMap, 'advanced.hoc', report.patterns.advanced.hoc.length);\n  increment(patternMap, 'advanced.memo', report.patterns.advanced.memo.length);\n  increment(\n    patternMap,\n    'advanced.forwardRef',\n    report.patterns.advanced.forwardRef.length,\n  );\n  increment(\n    patternMap,\n    'advanced.portal',\n    report.patterns.advanced.portal.length,\n  );\n}\n\nfunction increment(map: Map<string, number>, key: string, value: number) {\n  map.set(key, (map.get(key) || 0) + value);\n}\n\nexport function getPatternDisplayName(patternType: string): string {\n  const displayNames: Record<string, string> = {\n    'imports.default': 'Default Imports',\n    'imports.named': 'Named Imports',\n    'imports.namespace': 'Namespace Imports',\n    'imports.aliased': 'Aliased Imports',\n    'usage.jsx': 'JSX Usage',\n    'usage.variables': 'Variable Assignments',\n    'usage.destructuring': 'Destructuring',\n    'usage.conditional': 'Conditional Usage',\n    'usage.arrays': 'Array Mappings',\n    'usage.objects': 'Object Mappings',\n    'advanced.lazy': 'Lazy Loading',\n    'advanced.dynamic': 'Dynamic Imports',\n    'advanced.hoc': 'Higher-Order Components',\n    'advanced.memo': 'Memoized Components',\n    'advanced.forwardRef': 'Forward Refs',\n    'advanced.portal': 'Portal Usage',\n  };\n  return displayNames[patternType] || patternType;\n}\n","import type { VersusConfig } from '../config/types';\nimport type { PackageDistribution } from './package-distribution';\n\nfunction toPercentage(count: number, total: number): number {\n  return total > 0 ? (count / total) * 100 : 0;\n}\n\nexport interface VersusEntry {\n  packageName: string;\n  count: number;\n  percentage: number;\n}\n\nexport interface VersusResult {\n  name: string;\n  packages: string[];\n  entries: VersusEntry[];\n  totalCount: number;\n}\n\nexport function calculateVersusResults(\n  distribution: PackageDistribution[],\n  versusConfigs: VersusConfig[],\n): VersusResult[] {\n  const distMap = new Map(distribution.map((p) => [p.packageName, p]));\n\n  return versusConfigs.map((vc) => {\n    const entries: VersusEntry[] = vc.packages.map((pkgName) => {\n      const pkg = distMap.get(pkgName);\n      return {\n        packageName: pkgName,\n        count: pkg?.usageCount ?? 0,\n        percentage: 0,\n      };\n    });\n\n    const totalCount = entries.reduce((sum, e) => sum + e.count, 0);\n\n    for (const entry of entries) {\n      entry.percentage = toPercentage(entry.count, totalCount);\n    }\n\n    entries.sort((a, b) => b.count - a.count);\n\n    return { name: vc.name, packages: vc.packages, entries, totalCount };\n  });\n}\n","import type { UsageReport } from '../swc-parser';\nimport type { ResolvedHermexConfig } from '../config/types';\nimport type { LockfileResolutionMap, MultiVersionMap } from '../lock-parser';\nimport type { RuleViolation } from '../rules/evaluator';\nimport type {\n  ComponentUsage,\n  PackageDistribution,\n} from './package-distribution';\nimport {\n  calculatePackageDistribution,\n  findComponentSource,\n} from './package-distribution';\nimport type {\n  DeclaredPackages,\n  PackageInventoryEntry,\n} from './package-inventory';\nimport { buildPackageInventory } from './package-inventory';\nimport {\n  detectForbiddenPackages,\n  detectRequiredPackages,\n} from './package-rules';\nimport type { PatternCount } from './pattern-counter';\nimport { countPatterns, getPatternDisplayName } from './pattern-counter';\nimport type { VersusResult } from './versus';\nimport { calculateVersusResults } from './versus';\n\nexport interface AggregatedReport {\n  filesAnalyzed: number;\n  totalImports: number;\n  totalComponents: number;\n  totalUsagePatterns: number;\n  patternCounts: PatternCount[];\n  componentUsage: Map<string, ComponentUsage>;\n  topComponents: ComponentUsage[];\n  /** Every package known to this run, on all three axes — the list every rule and view below is derived from. */\n  packageInventory: PackageInventoryEntry[];\n  packageDistribution: PackageDistribution[];\n  versusResults: VersusResult[];\n  /** Every rule hit, `forbid_packages` included (#77) — one list, no second field to remember to read. */\n  ruleViolations: RuleViolation[];\n  reports: UsageReport[];\n}\n\nexport function aggregateReports(\n  reports: UsageReport[],\n  versions: Record<string, string> = {},\n  config?: ResolvedHermexConfig,\n  multiVersions: MultiVersionMap = {},\n  resolutions: LockfileResolutionMap = {},\n  declaredPackages: DeclaredPackages = {},\n): AggregatedReport {\n  const componentUsageMap = new Map<string, ComponentUsage>();\n  let totalImports = 0;\n  let totalUsagePatterns = 0;\n  const patternCountMap = new Map<string, number>();\n\n  const availablePackages = Object.keys(versions);\n\n  for (const report of reports) {\n    totalImports += report.summary.totalImports;\n    totalUsagePatterns += report.summary.totalUsagePatterns;\n\n    for (const jsx of report.patterns.usage.jsx) {\n      // Keyed by (source, name), not name alone — the same component name\n      // (e.g. `Button`) can be imported from two different packages across\n      // a repo, and a name-only key would collapse them into one entry,\n      // silently attributing every usage to whichever source was seen\n      // first.\n      const source = findComponentSource(\n        jsx.component,\n        report,\n        availablePackages,\n      );\n      // For a named/aliased import, `jsx.component` is the local JSX\n      // identifier (e.g. `ArcCard`), not the package's actual export name\n      // (e.g. `Card`) — resolve back to the canonical export so the same\n      // export used under different local aliases aggregates as one\n      // component instead of fragmenting into several. Default imports have\n      // no canonical export name (the module path is the real identity), so\n      // they never have an `aliased` entry and pass through unchanged.\n      const aliasedImport = report.patterns.imports.aliased.find(\n        (imp) => imp.local === jsx.component,\n      );\n      const canonicalName = aliasedImport\n        ? aliasedImport.imported\n        : jsx.component;\n      const key = `${source}::${canonicalName}`;\n      const existing = componentUsageMap.get(key);\n\n      if (existing) {\n        existing.count++;\n        existing.files.add(report.filePath);\n      } else {\n        componentUsageMap.set(key, {\n          name: canonicalName,\n          source,\n          count: 1,\n          files: new Set([report.filePath]),\n        });\n      }\n    }\n\n    countPatterns(report, patternCountMap);\n  }\n\n  const topComponents = Array.from(componentUsageMap.values()).sort(\n    (a, b) => b.count - a.count,\n  );\n\n  const patternCounts = Array.from(patternCountMap.entries())\n    .map(([type, count]) => ({\n      patternType: type,\n      displayName: getPatternDisplayName(type),\n      count,\n    }))\n    .sort((a, b) => b.count - a.count);\n\n  // Built once, here: every package rule and every reported view below\n  // reads this same list, differing only in which axis it selects.\n  const packageInventory = buildPackageInventory({\n    versions,\n    multiVersions,\n    resolutions,\n    declared: declaredPackages,\n    componentUsage: componentUsageMap,\n    config,\n  });\n\n  const packageDistribution = calculatePackageDistribution(\n    packageInventory,\n    config,\n  );\n\n  const versusResults = calculateVersusResults(\n    packageDistribution,\n    config?.versus ?? [],\n  );\n  const forbiddenPackageViolations = detectForbiddenPackages(\n    packageInventory,\n    config,\n  );\n\n  const requiredPackageViolations = detectRequiredPackages(\n    packageInventory,\n    config,\n  );\n\n  return {\n    filesAnalyzed: reports.length,\n    totalImports,\n    totalComponents: componentUsageMap.size,\n    totalUsagePatterns,\n    patternCounts,\n    componentUsage: componentUsageMap,\n    topComponents,\n    packageInventory,\n    packageDistribution,\n    versusResults,\n    // Detection order: package rules here, then the file/script/manifest\n    // evaluators appended by the pipeline.\n    ruleViolations: [\n      ...forbiddenPackageViolations,\n      ...requiredPackageViolations,\n    ],\n    reports,\n  };\n}\n","import chalk from 'chalk';\nimport type { ParseError } from '../swc-parser/types';\n\nexport function printErrors(errors: ParseError[], isJson: boolean): void {\n  if (errors.length === 0) return;\n  const stream = isJson ? process.stderr : process.stdout;\n  stream.write(chalk.yellow(`\\n⚠ ${errors.length} file(s) failed to parse:\\n`));\n  for (const { file, message } of errors) {\n    stream.write(chalk.yellow(`  ${file}\\n`));\n    stream.write(chalk.gray(`    ${message}\\n`));\n  }\n  stream.write('\\n');\n}\n","import fs from 'fs';\nimport { glob } from 'glob';\n\n/**\n * Find files matching a glob pattern\n * @param pattern - Glob pattern\n * @param ignorePatterns - Glob pattenrs to ignore\n * @returns Array of file paths\n */\nexport async function findFiles(\n  pattern: string | string[],\n  ignorePatterns: string[],\n): Promise<string[]> {\n  const files = await glob(pattern, {\n    ignore: ignorePatterns,\n    nodir: true,\n    windowsPathsNoEscape: true,\n  });\n\n  // Sorted because glob returns directory-walk order, which varies by\n  // filesystem and platform. Everything downstream inherits this order —\n  // component tie-breaks, `components[].files`, the order parse errors are\n  // reported in — so leaving it unsorted makes hermex's own output differ\n  // between two machines analyzing the identical repo.\n  return files.map((f) => f.replace(/\\\\/g, '/')).sort();\n}\n\n/**\n * Read file content\n * @param filePath - Path to file\n * @returns File content\n */\nexport function readFile(filePath: string): string {\n  return fs.readFileSync(filePath, 'utf8');\n}\n","import fs from 'fs';\nimport semver from 'semver';\n\nexport type MultiVersionMap = Record<string, string[]>;\n\nexport interface PackageResolution {\n  /**\n   * The version resolved for this package's root/direct dependency\n   * declaration. `null` when the package isn't a direct dependency of the\n   * root project (purely transitive), or root resolution genuinely\n   * couldn't be determined (e.g. yarn without a readable package.json).\n   */\n  rootVersion: string | null;\n  /**\n   * Every distinct version resolved anywhere in the lockfile for this\n   * package, sorted. Always includes `rootVersion` when it is non-null.\n   */\n  allVersions: string[];\n}\n\nexport type LockfileResolutionMap = Record<string, PackageResolution>;\n\nexport interface LockfileAdapter {\n  name: string;\n  supportedVersions: string[];\n  detect(projectPath: string): string | null;\n  resolve(lockfilePath: string, projectPath: string): LockfileResolutionMap;\n}\n\n/**\n * Reads a lockfile and parses it with `parseFn`, returning `fallback` and\n * warning to the console if the file can't be read or `parseFn` throws.\n */\nexport function readAndParseLockfile<T>(\n  lockFilePath: string,\n  parseFn: (content: string) => T,\n  fallback: T,\n  warnLabel: string,\n): T {\n  try {\n    const content = fs.readFileSync(lockFilePath, 'utf8');\n    return parseFn(content);\n  } catch (error) {\n    const message = error instanceof Error ? error.message : String(error);\n    console.warn(`Warning: Could not parse ${warnLabel}: ${message}`);\n    return fallback;\n  }\n}\n\n/**\n * Accumulates per-package resolution data (every resolved version, plus\n * which one — if any — is the root/direct dependency's version) while an\n * adapter walks its lockfile in a single pass, then builds the final\n * `LockfileResolutionMap` with sorted, deduplicated version lists.\n */\nexport function createResolutionAccumulator(): {\n  addVersion(pkgName: string, version: string): void;\n  setRoot(pkgName: string, version: string): void;\n  build(): LockfileResolutionMap;\n} {\n  const versionSets: Record<string, Set<string>> = {};\n  const roots: Record<string, string> = {};\n\n  return {\n    addVersion(pkgName, version) {\n      (versionSets[pkgName] ??= new Set()).add(version);\n    },\n    setRoot(pkgName, version) {\n      roots[pkgName] = version;\n    },\n    build() {\n      const result: LockfileResolutionMap = {};\n      for (const [pkgName, versions] of Object.entries(versionSets)) {\n        result[pkgName] = {\n          rootVersion: roots[pkgName] ?? null,\n          allVersions: Array.from(versions).sort(),\n        };\n      }\n      return result;\n    },\n  };\n}\n\n/** Highest valid semver among `versions`, or `undefined` if none are valid. */\nexport function maxSemver(versions: string[]): string | undefined {\n  return versions\n    .filter((v) => semver.valid(v))\n    .sort(semver.compare)\n    .at(-1);\n}\n","import fs from 'fs';\nimport path from 'path';\nimport {\n  readAndParseLockfile,\n  createResolutionAccumulator,\n  type LockfileAdapter,\n  type LockfileResolutionMap,\n} from '../lock-file-adapter';\n\nfunction canonicalPackageName(pkgPath: string): string {\n  // pkgPath examples:\n  //   \"node_modules/react\"\n  //   \"node_modules/@scope/pkg\"\n  //   \"node_modules/react/node_modules/scheduler\"\n  //   \"node_modules/@scope/a/node_modules/@scope/b\"\n  // We want the last segment after the last \"node_modules/\"\n  const idx = pkgPath.lastIndexOf('node_modules/');\n  if (idx === -1) return pkgPath;\n  return pkgPath.slice(idx + 'node_modules/'.length);\n}\n\nconst ROOT_DEPENDENCY_FIELDS = [\n  'dependencies',\n  'devDependencies',\n  'optionalDependencies',\n  'peerDependencies',\n];\n\n/**\n * The names the root manifest actually declares, read from the lockfile's\n * own `packages[\"\"]` entry.\n *\n * Depth in `packages` cannot answer this. npm hoists: a transitive\n * dependency with no version conflict is installed at\n * `node_modules/<name>`, exactly where a direct dependency lives, so\n * \"depth 1\" describes where a package ended up, not whether this repo\n * asked for it. Returns null when the lockfile records no root manifest —\n * then depth is the only signal there is.\n */\nfunction declaredRootNames(lockData: {\n  packages?: Record<string, unknown>;\n}): Set<string> | null {\n  const root = lockData.packages?.[''];\n  if (typeof root !== 'object' || root === null) return null;\n\n  const names = new Set<string>();\n  for (const field of ROOT_DEPENDENCY_FIELDS) {\n    const bucket = (root as Record<string, unknown>)[field];\n    if (typeof bucket !== 'object' || bucket === null || Array.isArray(bucket))\n      continue;\n    for (const name of Object.keys(bucket)) names.add(name);\n  }\n  return names.size > 0 ? names : null;\n}\n\nexport class NpmLockfileAdapter implements LockfileAdapter {\n  name = 'npm';\n  supportedVersions = ['v2', 'v3'];\n\n  detect(projectPath: string): string | null {\n    const lockfilePath = path.join(projectPath, 'package-lock.json');\n    return fs.existsSync(lockfilePath) ? lockfilePath : null;\n  }\n\n  resolve(lockFilePath: string): LockfileResolutionMap {\n    return readAndParseLockfile(\n      lockFilePath,\n      (content) => {\n        const lockData = JSON.parse(content);\n        const acc = createResolutionAccumulator();\n        let sawPackages = false;\n\n        // npm v7+ uses \"packages\" field (lockfileVersion 2, 3). Every entry\n        // (any depth) contributes to allVersions; only depth-1 entries (no\n        // nested \"node_modules/\" in the path) are the root/direct\n        // dependency's resolution.\n        if (lockData.packages) {\n          const declared = declaredRootNames(lockData);\n\n          Object.entries(lockData.packages).forEach(\n            ([pkgPath, pkgData]: [string, any]) => {\n              if (!pkgPath || pkgPath === '') return;\n              const version = pkgData?.version;\n              if (!version) return;\n\n              sawPackages = true;\n              const pkgName = canonicalPackageName(pkgPath);\n              acc.addVersion(pkgName, version);\n\n              const atTopLevel = pkgPath.split('node_modules/').length <= 2;\n              if (!atTopLevel) return;\n\n              // A workspace entry (\"packages/app\") is part of the project\n              // itself, not something hoisted into it, so it is root\n              // regardless of what the manifest declares.\n              const isWorkspace = !pkgPath.includes('node_modules/');\n              // Without a declared set, depth is all there is (#94). With\n              // one, it decides: npm's hoisting puts transitive packages at\n              // the same depth as direct ones, and treating those as direct\n              // made a repo look like it owned — and could be told to\n              // remove — packages it never asked for.\n              const isRoot =\n                isWorkspace || declared === null || declared.has(pkgName);\n              if (isRoot) acc.setRoot(pkgName, version);\n            },\n          );\n        }\n\n        // npm v6 uses \"dependencies\" field (fallback). Keyed strictly by\n        // real package name (not a depth-prefixed compound key) so nested\n        // copies of the same package share one allVersions entry.\n        if (lockData.dependencies && !sawPackages) {\n          function extractVersions(deps: any, depth = 0): void {\n            Object.entries(deps).forEach(([name, data]: [string, any]) => {\n              if (data.version) {\n                acc.addVersion(name, data.version);\n                if (depth === 0) acc.setRoot(name, data.version);\n              }\n              if (data.dependencies) {\n                extractVersions(data.dependencies, depth + 1);\n              }\n            });\n          }\n          extractVersions(lockData.dependencies);\n        }\n\n        return acc.build();\n      },\n      {},\n      'package-lock.json',\n    );\n  }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { load } from 'js-yaml';\nimport {\n  parse as parseDependencyPath,\n  removeSuffix,\n} from '@pnpm/dependency-path';\nimport {\n  readAndParseLockfile,\n  createResolutionAccumulator,\n  type LockfileAdapter,\n  type LockfileResolutionMap,\n} from '../lock-file-adapter';\n\nfunction parsePackageKey(\n  rawKey: string,\n): { name: string; version: string } | null {\n  const key = rawKey.startsWith('/') ? rawKey.slice(1) : rawKey;\n\n  const parsed = parseDependencyPath(key);\n  if (parsed.name && parsed.version) {\n    return { name: parsed.name, version: parsed.version };\n  }\n\n  // Legacy pnpm v5/v6 slash-separated format (e.g. \"/@babel/core/7.22.5\"),\n  // which @pnpm/dependency-path's `parse` — built for the newer\n  // `name@version(...)` scheme — doesn't recognize.\n  const slashMatch = key.match(/^(.+?)\\/(\\d+\\.\\d+\\.\\d+.*)$/);\n  if (slashMatch) return { name: slashMatch[1], version: slashMatch[2] };\n\n  return null;\n}\n\nexport class PnpmLockfileAdapter implements LockfileAdapter {\n  name = 'pnpm';\n  supportedVersions = ['v5', 'v6', 'v9'];\n\n  detect(projectPath: string): string | null {\n    const lockfilePath = path.join(projectPath, 'pnpm-lock.yaml');\n    return fs.existsSync(lockfilePath) ? lockfilePath : null;\n  }\n\n  resolve(lockFilePath: string): LockfileResolutionMap {\n    return readAndParseLockfile(\n      lockFilePath,\n      (content) => {\n        const lockData = load(content) as any;\n        const acc = createResolutionAccumulator();\n\n        // Every resolved copy anywhere in the lockfile (v6+ flat \"packages\"\n        // key namespace) — this is allVersions, regardless of scope.\n        if (lockData.packages) {\n          Object.keys(lockData.packages).forEach((key) => {\n            const parsed = parsePackageKey(key);\n            if (!parsed) return;\n            acc.addVersion(parsed.name, parsed.version);\n          });\n        }\n\n        // Root resolution: pnpm v9+ \"importers\" field is authoritative —\n        // the root workspace importer's own resolved version.\n        let hasImporterRoot = false;\n        const rootImporter = lockData.importers?.['.'];\n        if (rootImporter) {\n          for (const depsField of ['dependencies', 'devDependencies']) {\n            const deps = rootImporter[depsField];\n            if (!deps) continue;\n            for (const [name, data] of Object.entries(deps)) {\n              if (\n                typeof data === 'object' &&\n                data !== null &&\n                'version' in data\n              ) {\n                const version = removeSuffix((data as any).version);\n                acc.setRoot(name, version);\n                acc.addVersion(name, version);\n                hasImporterRoot = true;\n              }\n            }\n          }\n        }\n\n        // Legacy pnpm v5/v6-8 lockfiles have no \"importers\" field at all —\n        // these formats don't retain a root/nested distinction, so whatever\n        // single resolution they produce is treated as root too (accepted\n        // gap, documented).\n        if (!hasImporterRoot) {\n          // pnpm v6-8 uses \"packages\" field\n          if (lockData.packages) {\n            Object.keys(lockData.packages).forEach((key) => {\n              // Key format: \"/@babel/core/7.22.5\" or \"/package/1.0.0\"\n              const match = key.match(/\\/(.+?)\\/(\\d+\\.\\d+\\.\\d+.*?)(?:_|$)/);\n              if (match) {\n                const [, pkgName, version] = match;\n                const resolved = removeSuffix(version);\n                acc.setRoot(pkgName, resolved);\n                acc.addVersion(pkgName, resolved);\n              }\n            });\n          }\n\n          // pnpm v5 uses \"dependencies\" and \"specifiers\"\n          if (lockData.dependencies) {\n            Object.entries(lockData.dependencies).forEach(\n              ([name, versionSpec]: [string, any]) => {\n                // versionSpec format: \"1.0.0\" or \"link:../package\"\n                let version: string | undefined;\n                if (\n                  typeof versionSpec === 'string' &&\n                  !versionSpec.startsWith('link:')\n                ) {\n                  version = removeSuffix(versionSpec);\n                } else if (\n                  typeof versionSpec === 'object' &&\n                  versionSpec.version\n                ) {\n                  version = removeSuffix(versionSpec.version);\n                }\n                if (version) {\n                  acc.setRoot(name, version);\n                  acc.addVersion(name, version);\n                }\n              },\n            );\n          }\n        }\n\n        return acc.build();\n      },\n      {},\n      'pnpm-lock.yaml',\n    );\n  }\n}\n","import { globSync } from 'glob';\nimport fs from 'fs';\nimport path from 'path';\nimport type {\n  DeclaredPackages,\n  DependencyBucket,\n} from '../utils/package-inventory';\n\nexport interface RuleViolation {\n  type:\n    | 'detect_files'\n    | 'require_files'\n    | 'require_packages'\n    | 'forbid_packages'\n    | 'require_scripts'\n    | 'require_package_fields'\n    | 'forbid_package_fields'\n    | 'engine_version'\n    | 'codeowners';\n  severity: 'error' | 'warn' | 'info';\n  patterns: string[];\n  message?: string;\n  matchedFiles: string[];\n  // engine_version only\n  installedRange?: string;\n  requiredRange?: string;\n  // package-field rules only\n  fieldPath?: string;\n  actualValue?: string;\n  /**\n   * forbid_packages only — the package that matched `patterns`. Kept as a\n   * scalar rather than folded into `matchedFiles` because that field is read\n   * as file paths everywhere (`describeViolation` takes basenames off it, the\n   * codeowners branch counts files with it), and because a package's identity\n   * is what the packages table joins on.\n   */\n  packageName?: string;\n}\n\nexport function toArray<T>(val: T | T[] | undefined): T[] {\n  if (!val) return [];\n  return Array.isArray(val) ? val : [val];\n}\n\n/**\n * Type-guard filter for rules whose severity may be 'off' (config-authored\n * rules, resolved via `applyOverrides`/`resolveRules` before evaluators run\n * — see src/config/overrides.ts). Narrows `severity` down to the\n * evaluator-facing 'error' | 'warn' | 'info', so a `RuleViolation` built\n * from a filtered rule type-checks without a cast.\n */\nexport function isEnabled<T extends { severity: string }>(\n  rule: T,\n): rule is T & { severity: Exclude<T['severity'], 'off'> } {\n  return rule.severity !== 'off';\n}\n\nexport function findMatches(\n  patterns: string[],\n  repoPath: string,\n  ignore: string[],\n): string[] {\n  const matches: string[] = [];\n  for (const pattern of patterns) {\n    const found = globSync(pattern, { cwd: repoPath, nodir: true, ignore });\n    matches.push(...found.map((f) => f.replace(/\\\\/g, '/')));\n  }\n  return [...new Set(matches)];\n}\n\nexport function readPackageJson(\n  repoPath: string,\n): Record<string, unknown> | null {\n  try {\n    const content = fs.readFileSync(\n      path.join(repoPath, 'package.json'),\n      'utf-8',\n    );\n    return JSON.parse(content) as Record<string, unknown>;\n  } catch {\n    return null;\n  }\n}\n\nconst DEPENDENCY_FIELDS: DependencyBucket[] = [\n  'dependencies',\n  'devDependencies',\n  'peerDependencies',\n  'optionalDependencies',\n];\n\n/**\n * The *declared* axis of the package inventory: every package this repo\n * lists in `package.json`, with the bucket(s) that declare it.\n *\n * Distinct from the lockfile, which also contains every transitive\n * dependency — this is only what the repo can actually add or remove.\n */\nexport function collectDeclaredPackages(repoPath: string): DeclaredPackages {\n  const pkg = readPackageJson(repoPath);\n  if (!pkg) return {};\n\n  // Null prototype: dependency names come from an untrusted manifest, and a\n  // key like `__proto__` on a plain object literal would hit the prototype\n  // setter instead of creating an own property — silently dropping the\n  // package here, and mutating the object's prototype.\n  const declared: DeclaredPackages = Object.create(null) as DeclaredPackages;\n  for (const field of DEPENDENCY_FIELDS) {\n    const bucket = pkg[field];\n    // The manifest is untyped user input — a malformed bucket (a string, an\n    // array, null) must not take the whole scan down.\n    if (typeof bucket !== 'object' || bucket === null || Array.isArray(bucket))\n      continue;\n    for (const name of Object.keys(bucket)) {\n      declared[name] ??= [];\n      declared[name].push(field);\n    }\n  }\n  return declared;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport lockfile from '@yarnpkg/lockfile';\nimport {\n  readAndParseLockfile,\n  createResolutionAccumulator,\n  type LockfileAdapter,\n  type LockfileResolutionMap,\n} from '../lock-file-adapter';\nimport { readPackageJson } from '../../rules/shared';\n\nconst ROOT_DEPENDENCY_FIELDS = [\n  'dependencies',\n  'devDependencies',\n  'optionalDependencies',\n  'peerDependencies',\n] as const;\n\nfunction extractPackageName(key: string): string {\n  if (key.startsWith('@')) {\n    const match = key.match(/^(@[^@]+\\/[^@]+)@/);\n    return match ? match[1] : key;\n  }\n  const match = key.match(/^([^@]+)@/);\n  return match ? match[1] : key;\n}\n\n/**\n * Merges every declared dependency range from the root package.json into a\n * single `name -> range` map, so a yarn.lock entry's exact key (`name@range`)\n * can be matched against it to find the root-resolved version — yarn.lock\n * itself retains no root/nested distinction, unlike npm's and pnpm's\n * lockfile formats (#57).\n */\nfunction collectRootRanges(\n  pkgJson: Record<string, unknown> | null,\n): Record<string, string> {\n  const ranges: Record<string, string> = {};\n  if (!pkgJson) return ranges;\n\n  for (const field of ROOT_DEPENDENCY_FIELDS) {\n    const deps = pkgJson[field];\n    if (!deps || typeof deps !== 'object') continue;\n    for (const [name, range] of Object.entries(\n      deps as Record<string, unknown>,\n    )) {\n      if (typeof range === 'string') ranges[name] = range;\n    }\n  }\n\n  return ranges;\n}\n\nexport class YarnLockfileAdapter implements LockfileAdapter {\n  name = 'yarn';\n  supportedVersions = ['v1', 'v2+'];\n\n  detect(projectPath: string): string | null {\n    const lockfilePath = path.join(projectPath, 'yarn.lock');\n    return fs.existsSync(lockfilePath) ? lockfilePath : null;\n  }\n\n  resolve(lockFilePath: string, projectPath: string): LockfileResolutionMap {\n    const rootRanges = collectRootRanges(readPackageJson(projectPath));\n\n    return readAndParseLockfile(\n      lockFilePath,\n      (content) => {\n        const parsed = lockfile.parse(content);\n\n        if (parsed.type !== 'success') {\n          console.warn('Warning: Failed to parse yarn.lock');\n          return {};\n        }\n\n        const acc = createResolutionAccumulator();\n\n        // `@yarnpkg/lockfile`'s parse() has already decoded the lockfile —\n        // we only correlate its already-parsed keys against package.json\n        // ranges here, not re-implementing any lockfile parsing ourselves.\n        Object.entries(parsed.object).forEach(([key, value]: [string, any]) => {\n          if (!value.version) return;\n          const pkgName = extractPackageName(key);\n          acc.addVersion(pkgName, value.version);\n\n          const range = rootRanges[pkgName];\n          if (range && key === `${pkgName}@${range}`) {\n            acc.setRoot(pkgName, value.version);\n          }\n        });\n\n        return acc.build();\n      },\n      {},\n      'yarn.lock',\n    );\n  }\n}\n","import { NpmLockfileAdapter } from './patterns/npm';\nimport { PnpmLockfileAdapter } from './patterns/pnpm';\nimport { YarnLockfileAdapter } from './patterns/yarn';\nimport {\n  maxSemver,\n  type LockfileAdapter,\n  type LockfileResolutionMap,\n  type MultiVersionMap,\n} from './lock-file-adapter';\n\nexport type {\n  MultiVersionMap,\n  LockfileResolutionMap,\n  PackageResolution,\n} from './lock-file-adapter';\n\nexport interface LockfileResult {\n  /** Complete per-package resolution data — root version (if determinable) and every resolved copy. */\n  resolutions: LockfileResolutionMap;\n  /**\n   * The single \"installed version\" per package: `rootVersion` when known,\n   * otherwise the highest semver among `allVersions` (undeterminable root,\n   * e.g. a yarn package with no readable package.json, or a purely\n   * transitive dependency).\n   */\n  versions: Record<string, string>;\n  multiVersions: MultiVersionMap;\n  lockfileType: 'npm' | 'yarn' | 'pnpm' | null;\n  lockfilePath: string | null;\n  supportedVersions: string[];\n}\n\nconst LOCKFILE_ADAPTERS: LockfileAdapter[] = [\n  new NpmLockfileAdapter(),\n  new YarnLockfileAdapter(),\n  new PnpmLockfileAdapter(),\n];\n\n/**\n * Find and parse the appropriate lockfile in a directory\n * @param projectPath - Path to the project directory\n * @returns Object with versions map and lockfile type\n */\nexport function findAndParseLockfile(projectPath: string): LockfileResult {\n  for (const adapter of LOCKFILE_ADAPTERS) {\n    const lockfilePath = adapter.detect(projectPath);\n    if (lockfilePath) {\n      const resolutions = adapter.resolve(lockfilePath, projectPath);\n\n      const versions: Record<string, string> = {};\n      const multiVersions: MultiVersionMap = {};\n      for (const [packageName, resolution] of Object.entries(resolutions)) {\n        multiVersions[packageName] = resolution.allVersions;\n        const effective =\n          resolution.rootVersion ?? maxSemver(resolution.allVersions);\n        if (effective) versions[packageName] = effective;\n      }\n\n      return {\n        resolutions,\n        versions,\n        multiVersions,\n        lockfileType: adapter.name as 'npm' | 'yarn' | 'pnpm',\n        lockfilePath,\n        supportedVersions: adapter.supportedVersions,\n      };\n    }\n  }\n\n  throw new Error('No supported lockfile found');\n}\n\n/**\n * Get the version of a specific package from lockfile\n * @param projectPath - Path to the project directory\n * @param packageName - Name of the package\n * @returns Version string or null if not found\n */\nexport function getPackageVersion(\n  projectPath: string,\n  packageName: string,\n): string | null {\n  const { versions } = findAndParseLockfile(projectPath);\n  return versions[packageName] || null;\n}\n\n/**\n * Get versions for multiple packages\n * @param projectPath - Path to the project directory\n * @param packageNames - Array of package names\n * @returns Map of package names to versions\n */\nexport function getPackageVersions(\n  projectPath: string,\n  packageNames: string[],\n): Record<string, string> {\n  const { versions } = findAndParseLockfile(projectPath);\n  const result: Record<string, string> = {};\n\n  packageNames.forEach((pkgName) => {\n    if (versions[pkgName]) {\n      result[pkgName] = versions[pkgName];\n    }\n  });\n\n  return result;\n}\n","import type { ResolvedRulesConfig } from '../config/types';\nimport { findMatches } from './shared';\nimport type { RuleViolation } from './shared';\n\nexport function evaluateFileRules(\n  repoPath: string,\n  rulesConfig: ResolvedRulesConfig,\n  excludes: string[],\n): RuleViolation[] {\n  const violations: RuleViolation[] = [];\n\n  for (const rule of rulesConfig.detect_files) {\n    const matches = findMatches(rule.patterns, repoPath, excludes);\n    if (matches.length > 0) {\n      violations.push({\n        type: 'detect_files',\n        severity: rule.severity,\n        patterns: rule.patterns,\n        message: rule.message,\n        matchedFiles: matches,\n      });\n    }\n  }\n\n  for (const rule of rulesConfig.require_files) {\n    const matches = findMatches(rule.patterns, repoPath, excludes);\n    if (matches.length === 0) {\n      violations.push({\n        type: 'require_files',\n        severity: rule.severity,\n        patterns: rule.patterns,\n        message: rule.message,\n        matchedFiles: [],\n      });\n    }\n  }\n\n  return violations;\n}\n","import micromatch from 'micromatch';\nimport type { ResolvedRulesConfig } from '../config/types';\nimport { readPackageJson } from './shared';\nimport type { RuleViolation } from './shared';\n\nexport function evaluateScriptRules(\n  repoPath: string,\n  rulesConfig: ResolvedRulesConfig,\n): RuleViolation[] {\n  const rules = rulesConfig.require_scripts;\n  if (rules.length === 0) {\n    return [];\n  }\n\n  const pkg = readPackageJson(repoPath);\n  const scriptKeys = Object.keys(\n    (pkg?.scripts as Record<string, string> | undefined) ?? {},\n  );\n\n  return rules\n    .filter(\n      (rule) =>\n        !rule.patterns.some((p) =>\n          scriptKeys.some((k) => micromatch.isMatch(k, p)),\n        ),\n    )\n    .map((rule) => ({\n      type: 'require_scripts' as const,\n      severity: rule.severity,\n      patterns: rule.patterns,\n      message: rule.message,\n      matchedFiles: [],\n    }));\n}\n","import micromatch from 'micromatch';\nimport type { ResolvedRulesConfig } from '../config/types';\nimport { readPackageJson } from './shared';\nimport type { RuleViolation } from './shared';\n\ninterface FieldLookup {\n  exists: boolean;\n  value: unknown;\n}\n\n/** Resolves a dot-path like \"engines.node\" against the manifest object. */\nfunction getFieldAtPath(\n  pkg: Record<string, unknown> | null,\n  path: string,\n): FieldLookup {\n  let current: unknown = pkg;\n  for (const key of path.split('.')) {\n    if (\n      current === null ||\n      typeof current !== 'object' ||\n      !(key in (current as Record<string, unknown>))\n    ) {\n      return { exists: false, value: undefined };\n    }\n    current = (current as Record<string, unknown>)[key];\n  }\n  return { exists: true, value: current };\n}\n\n/** Primitives compare by string form; objects/arrays never match a value pattern. */\nfunction valueMatches(value: unknown, valuePatterns: string[]): boolean {\n  if (value === null || typeof value === 'object') return false;\n  return micromatch.isMatch(String(value), valuePatterns);\n}\n\nexport function evaluatePackageFieldRules(\n  repoPath: string,\n  rulesConfig: ResolvedRulesConfig,\n): RuleViolation[] {\n  const requireRules = rulesConfig.require_package_fields;\n  const forbidRules = rulesConfig.forbid_package_fields;\n  if (requireRules.length === 0 && forbidRules.length === 0) return [];\n\n  const pkg = readPackageJson(repoPath);\n  const violations: RuleViolation[] = [];\n\n  for (const rule of requireRules) {\n    const lookups = rule.patterns.map((p) => ({\n      path: p,\n      ...getFieldAtPath(pkg, p),\n    }));\n    const satisfied = lookups.some(\n      (l) => l.exists && (!rule.values || valueMatches(l.value, rule.values)),\n    );\n    if (!satisfied) {\n      // Prefer reporting a present-but-mismatched field over a missing one\n      const mismatch = rule.values ? lookups.find((l) => l.exists) : undefined;\n      violations.push({\n        type: 'require_package_fields',\n        severity: rule.severity,\n        patterns: rule.patterns,\n        message: rule.message,\n        matchedFiles: [],\n        fieldPath: mismatch?.path,\n        actualValue:\n          mismatch && typeof mismatch.value !== 'object'\n            ? String(mismatch.value)\n            : undefined,\n      });\n    }\n  }\n\n  for (const rule of forbidRules) {\n    for (const pattern of rule.patterns) {\n      const lookup = getFieldAtPath(pkg, pattern);\n      const hit =\n        lookup.exists &&\n        (!rule.values || valueMatches(lookup.value, rule.values));\n      if (hit) {\n        violations.push({\n          type: 'forbid_package_fields',\n          severity: rule.severity,\n          patterns: rule.patterns,\n          message: rule.message,\n          matchedFiles: [],\n          fieldPath: pattern,\n          actualValue:\n            lookup.value !== null && typeof lookup.value !== 'object'\n              ? String(lookup.value)\n              : undefined,\n        });\n      }\n    }\n  }\n\n  return violations;\n}\n","import semver from 'semver';\nimport type { ResolvedRulesConfig } from '../config/types';\nimport { readPackageJson } from './shared';\nimport type { RuleViolation } from './shared';\n\nexport function evaluateEngineVersion(\n  repoPath: string,\n  rulesConfig: ResolvedRulesConfig,\n): RuleViolation[] {\n  const rules = rulesConfig.engine_version;\n  if (rules.length === 0) {\n    return [];\n  }\n\n  const pkg = readPackageJson(repoPath);\n  const nodeRange = (pkg?.engines as Record<string, string> | undefined)?.node;\n\n  return rules.flatMap((rule): RuleViolation[] => {\n    if (!nodeRange) {\n      return [\n        {\n          type: 'engine_version',\n          severity: rule.severity,\n          patterns: [],\n          message: rule.message ?? 'engines.node not specified in package.json',\n          matchedFiles: [],\n          requiredRange: rule.range,\n        },\n      ];\n    }\n\n    const minVer = semver.minVersion(nodeRange);\n    if (!minVer || !semver.satisfies(minVer, rule.range)) {\n      return [\n        {\n          type: 'engine_version',\n          severity: rule.severity,\n          patterns: [],\n          message: rule.message,\n          matchedFiles: [],\n          installedRange: nodeRange,\n          requiredRange: rule.range,\n        },\n      ];\n    }\n\n    return [];\n  });\n}\n","import fs from 'fs';\nimport path from 'path';\nimport micromatch from 'micromatch';\nimport type { ResolvedRulesConfig } from '../config/types';\nimport type { RuleViolation } from './shared';\n\nconst CODEOWNERS_LOCATIONS = [\n  '.github/CODEOWNERS',\n  'CODEOWNERS',\n  'docs/CODEOWNERS',\n];\n\nexport interface CodeownersEntry {\n  /** as written in the CODEOWNERS file */\n  pattern: string;\n  /** translated micromatch patterns */\n  globs: string[];\n  /** may be empty — an empty list un-assigns ownership for matching files */\n  owners: string[];\n}\n\n/** First existing location, GitHub search order. Null if none exist. */\nexport function findCodeownersFile(repoPath: string): string | null {\n  for (const location of CODEOWNERS_LOCATIONS) {\n    const full = path.join(repoPath, location);\n    if (fs.existsSync(full)) return full;\n  }\n  return null;\n}\n\n/** Parses content into entries; skips blank lines and # comments. */\nexport function parseCodeowners(content: string): CodeownersEntry[] {\n  const entries: CodeownersEntry[] = [];\n\n  for (const rawLine of content.split(/\\r?\\n/)) {\n    const line = rawLine.trim();\n    if (!line || line.startsWith('#')) continue;\n\n    const tokens = line.split(/\\s+/);\n    const pattern = tokens[0];\n    const owners = tokens.slice(1);\n\n    entries.push({\n      pattern,\n      globs: codeownersPatternToGlobs(pattern),\n      owners,\n    });\n  }\n\n  return entries;\n}\n\n/**\n * Translates a CODEOWNERS (gitignore-style) pattern into micromatch glob(s).\n *\n * Rules:\n * - `*` alone matches everything.\n * - A leading `/`, or a `/` anywhere in the middle of the pattern, anchors\n *   the match to the repo root (the leading `/` is stripped once anchored).\n * - A pattern with no anchoring gets a `**\\/` prefix so it matches at any depth.\n * - A trailing `/` restricts the match to a directory, so `/**` is appended.\n * - A bare name (no glob characters, no slash at all) also matches as a\n *   directory anywhere, so the `/**` directory variant is added alongside\n *   the plain match.\n */\nexport function codeownersPatternToGlobs(pattern: string): string[] {\n  if (pattern === '*') return ['**'];\n\n  let p = pattern;\n\n  const hadLeadingSlash = p.startsWith('/');\n  if (hadLeadingSlash) p = p.slice(1);\n\n  const hadTrailingSlash = p.endsWith('/') && p.length > 1;\n  if (hadTrailingSlash) p = p.slice(0, -1);\n\n  const hasInternalSlash = p.includes('/');\n  const anchored = hadLeadingSlash || hasInternalSlash;\n  const hasGlobChars = /[*?[\\]{}!()]/.test(p);\n  const isBareName = !anchored && !hasGlobChars && !hadTrailingSlash;\n\n  const base = anchored ? p : `**/${p}`;\n  const globs = [hadTrailingSlash ? `${base}/**` : base];\n\n  if (isBareName) {\n    globs.push(`${base}/**`);\n  }\n\n  return globs;\n}\n\n// Precompiled-matcher cache, keyed by the entries array identity. Avoids\n// re-parsing each entry's glob(s) into a regex on every findOwningEntry()\n// call — evaluateCodeowners calls this once per scanned file against the\n// same `entries` array (both directly, and via fileIsOwned), so this turns\n// an O(files x entries) sequence of fresh `micromatch.isMatch` glob\n// evaluations into a one-time compile plus cheap `RegExp.test` calls.\n// Entries are treated as static for the lifetime of one `entries` array; a\n// WeakMap means a fresh `entries` array (e.g. a new `parseCodeowners` call)\n// naturally gets a fresh compiled cache instead of reading stale matchers.\nconst compiledMatchersCache = new WeakMap<CodeownersEntry[], RegExp[][]>();\n\nfunction getCompiledMatchers(entries: CodeownersEntry[]): RegExp[][] {\n  let compiled = compiledMatchersCache.get(entries);\n  if (!compiled) {\n    compiled = entries.map((entry) =>\n      entry.globs.map((glob) => micromatch.makeRe(glob, { dot: true })),\n    );\n    compiledMatchersCache.set(entries, compiled);\n  }\n  return compiled;\n}\n\n/** Last matching entry, or null if none match. */\nexport function findOwningEntry(\n  file: string,\n  entries: CodeownersEntry[],\n): CodeownersEntry | null {\n  const compiled = getCompiledMatchers(entries);\n  for (let i = entries.length - 1; i >= 0; i--) {\n    if (compiled[i].some((re) => re.test(file))) {\n      return entries[i];\n    }\n  }\n  return null;\n}\n\n/** Last matching entry wins; owned iff that entry has >= 1 owner. */\nexport function fileIsOwned(file: string, entries: CodeownersEntry[]): boolean {\n  const entry = findOwningEntry(file, entries);\n  return entry !== null && entry.owners.length > 0;\n}\n\nexport function evaluateCodeowners(\n  repoPath: string,\n  rulesConfig: ResolvedRulesConfig,\n  scannedFiles: string[],\n): RuleViolation[] {\n  const rule = rulesConfig.codeowners;\n  if (!rule) return [];\n\n  const filePath = findCodeownersFile(repoPath);\n  if (!filePath) {\n    return [\n      {\n        type: 'codeowners',\n        severity: rule.severity,\n        patterns: CODEOWNERS_LOCATIONS,\n        message: rule.message,\n        matchedFiles: [],\n      },\n    ];\n  }\n\n  const entries = parseCodeowners(fs.readFileSync(filePath, 'utf-8'));\n  const relFiles = scannedFiles.map((f) =>\n    (path.isAbsolute(f) ? path.relative(repoPath, f) : f).replace(/\\\\/g, '/'),\n  );\n\n  const unowned: string[] = [];\n  const wrongOwner: string[] = [];\n  const requiredOwners = rule.requiredOwners;\n\n  for (const f of relFiles) {\n    const entry = findOwningEntry(f, entries);\n    const owned = entry !== null && entry.owners.length > 0;\n    if (!owned) {\n      unowned.push(f);\n      continue;\n    }\n    if (requiredOwners && requiredOwners.length > 0) {\n      const hasRequiredOwner = entry!.owners.some((o) =>\n        requiredOwners.includes(o),\n      );\n      if (!hasRequiredOwner) wrongOwner.push(f);\n    }\n  }\n\n  const violations: RuleViolation[] = [];\n  if (unowned.length > 0) {\n    violations.push({\n      type: 'codeowners',\n      severity: rule.severity,\n      patterns: [path.basename(filePath)],\n      message: rule.message,\n      matchedFiles: unowned,\n    });\n  }\n  if (wrongOwner.length > 0) {\n    violations.push({\n      type: 'codeowners',\n      severity: rule.severity,\n      patterns: [path.basename(filePath)],\n      message:\n        rule.message ??\n        `Files must be owned by one of: ${requiredOwners!.join(', ')}`,\n      matchedFiles: wrongOwner,\n    });\n  }\n  return violations;\n}\n","import type { ResolvedRulesConfig } from '../config/types';\nimport { evaluateFileRules } from './file-rules';\nimport { evaluateScriptRules } from './script-rules';\nimport { evaluatePackageFieldRules } from './package-field-rules';\nimport { evaluateEngineVersion } from './engine-version';\nimport { evaluateCodeowners } from './codeowners';\n\nexport type { RuleViolation } from './shared';\n\nexport function evaluateRules(\n  repoPath: string,\n  rulesConfig: ResolvedRulesConfig,\n  excludes: string[],\n  scannedFiles: string[] = [],\n): import('./shared').RuleViolation[] {\n  return [\n    ...evaluateFileRules(repoPath, rulesConfig, excludes),\n    ...evaluateScriptRules(repoPath, rulesConfig),\n    ...evaluatePackageFieldRules(repoPath, rulesConfig),\n    ...evaluateEngineVersion(repoPath, rulesConfig),\n    ...evaluateCodeowners(repoPath, rulesConfig, scannedFiles),\n  ];\n}\n","import type { RegistryPackageInfo } from './types';\n\nexport async function fetchPackageInfo(\n  name: string,\n  registryUrl: string,\n  authToken?: string,\n): Promise<RegistryPackageInfo | null> {\n  const url = `${registryUrl.replace(/\\/$/, '')}/${encodeURIComponent(name).replace('%40', '@')}`;\n  const controller = new AbortController();\n  const timeoutId = setTimeout(() => controller.abort(), 10_000);\n\n  try {\n    const headers: Record<string, string> = {\n      Accept: 'application/json',\n    };\n    if (authToken) {\n      headers['Authorization'] = `Bearer ${authToken}`;\n    }\n\n    const response = await fetch(url, {\n      headers,\n      signal: controller.signal,\n    });\n\n    clearTimeout(timeoutId);\n\n    if (!response.ok) return null;\n\n    const data = (await response.json()) as RegistryPackageInfo;\n    return data;\n  } catch {\n    clearTimeout(timeoutId);\n    return null;\n  }\n}\n","import { randomUUID } from 'node:crypto';\nimport { mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport type { RegistryPackageInfo } from './types';\nimport { fetchPackageInfo } from './client';\n\nconst DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour\nconst DEFAULT_CACHE_DIR = join(homedir(), '.hermex', 'cache', 'npm');\n\nexport interface CacheOptions {\n  /** Time-to-live for cache entries, in milliseconds. Default: 1 hour. */\n  ttlMs?: number;\n  /** Override the cache root directory — primarily for tests. */\n  cacheDir?: string;\n  /** Fully disable cache reads and writes (falls straight through to a live fetch). */\n  disabled?: boolean;\n}\n\ninterface CacheEntry {\n  cachedAt: number;\n  registryUrl: string;\n  packageName: string;\n  data: RegistryPackageInfo;\n}\n\nfunction cachePathFor(\n  registryUrl: string,\n  packageName: string,\n  options?: CacheOptions,\n): string {\n  const root = options?.cacheDir ?? DEFAULT_CACHE_DIR;\n  const host = new URL(registryUrl).host.replace(/:/g, '_');\n  const fileName = `${encodeURIComponent(packageName)}.json`;\n  return join(root, host, fileName);\n}\n\nexport async function readCache(\n  registryUrl: string,\n  packageName: string,\n  options?: CacheOptions,\n): Promise<RegistryPackageInfo | null> {\n  const ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;\n  try {\n    const path = cachePathFor(registryUrl, packageName, options);\n    const raw = await readFile(path, 'utf8');\n    const entry = JSON.parse(raw) as CacheEntry;\n\n    if (\n      entry.registryUrl !== registryUrl ||\n      entry.packageName !== packageName\n    ) {\n      return null;\n    }\n    if (Date.now() - entry.cachedAt >= ttlMs) return null;\n\n    return entry.data;\n  } catch {\n    return null;\n  }\n}\n\nexport async function writeCache(\n  registryUrl: string,\n  packageName: string,\n  data: RegistryPackageInfo,\n  options?: CacheOptions,\n): Promise<void> {\n  const finalPath = cachePathFor(registryUrl, packageName, options);\n  const tmpPath = `${finalPath}.tmp-${randomUUID()}`;\n\n  try {\n    await mkdir(dirname(finalPath), { recursive: true });\n    const entry: CacheEntry = {\n      cachedAt: Date.now(),\n      registryUrl,\n      packageName,\n      data,\n    };\n    await writeFile(tmpPath, JSON.stringify(entry), 'utf8');\n    await rename(tmpPath, finalPath);\n  } catch {\n    try {\n      await unlink(tmpPath);\n    } catch {\n      // best-effort cleanup only\n    }\n  }\n}\n\nexport async function getPackageInfo(\n  packageName: string,\n  registryUrl: string,\n  authToken?: string,\n  options?: CacheOptions,\n): Promise<RegistryPackageInfo | null> {\n  const cacheEnabled = !authToken && !options?.disabled;\n\n  if (cacheEnabled) {\n    const cached = await readCache(registryUrl, packageName, options);\n    if (cached) return cached;\n  }\n\n  const info = await fetchPackageInfo(packageName, registryUrl, authToken);\n  if (info && cacheEnabled) {\n    await writeCache(registryUrl, packageName, info, options);\n  }\n  return info;\n}\n","import semver from 'semver';\nimport micromatch from 'micromatch';\nimport type { PackageDistribution } from '../utils/aggregator';\nimport { isReleaseAgeTarget } from '../utils/package-distribution';\nimport type { ReleaseAgeConfig } from '../config/types';\nimport type {\n  AvailableUpgrade,\n  PendingUpgrade,\n  ReleaseAgeEntry,\n  SemverBump,\n  UpgradeLevel,\n} from './types';\nimport { getPackageInfo, type CacheOptions } from './cache';\n\nconst CONCURRENCY = 8;\n\nfunction daysSince(dateStr: string): number {\n  const ms = Date.now() - new Date(dateStr).getTime();\n  return Math.floor(ms / (1000 * 60 * 60 * 24));\n}\n\nfunction classifyBump(installed: string, candidate: string): SemverBump | null {\n  const diff = semver.diff(installed, candidate);\n  if (!diff) return null;\n  if (diff === 'patch' || diff === 'prepatch') return 'patch';\n  if (diff === 'minor' || diff === 'preminor') return 'minor';\n  if (diff === 'major' || diff === 'premajor') return 'major';\n  return null;\n}\n\nfunction pickNewest(versions: { version: string; daysAgo: number }[]): {\n  version: string;\n  daysAgo: number;\n} {\n  return versions.reduce((a, b) => (a.daysAgo < b.daysAgo ? a : b));\n}\n\nfunction upgradeLevel(\n  daysAgo: number,\n  bump: SemverBump,\n  thresholds: ReleaseAgeConfig['thresholds'],\n): UpgradeLevel | null {\n  const threshold = thresholds[bump];\n  if (threshold === false || threshold === undefined) return null;\n  if (daysAgo > threshold) {\n    return bump === 'major' ? 'major_overdue' : 'minor_overdue';\n  }\n  return null;\n}\n\ninterface ReleaseAgeForVersion {\n  upgrades: AvailableUpgrade[];\n  worstLevel: UpgradeLevel | null;\n  pendingUpgrade?: PendingUpgrade;\n  latestVersion?: string;\n  latestReleasedDaysAgo?: number;\n  minCompliantVersion?: string;\n  minCompliantReleasedDaysAgo?: number;\n  minCompliantInWindow: boolean;\n  minCompliantBump?: SemverBump;\n}\n\n/**\n * Computes everything version-dependent for a single installed version\n * against the registry's release timeline — no notion of scope, severity,\n * or deprecation, which are policy/registry facts independent of which\n * installed copy is being checked (#57).\n */\nfunction computeReleaseAgeForVersion(\n  installedVersion: string,\n  timeMap: Record<string, string>,\n  thresholds: ReleaseAgeConfig['thresholds'],\n  distTags: Record<string, string> | undefined,\n): ReleaseAgeForVersion {\n  const byBump = new Map<SemverBump, { version: string; daysAgo: number }[]>();\n  let minCompliantVersion: string | undefined;\n  let minCompliantReleasedDaysAgo: number | undefined;\n  let minCompliantBump: SemverBump | undefined;\n\n  for (const [version, dateStr] of Object.entries(timeMap)) {\n    if (version === 'created' || version === 'modified') continue;\n    if (!semver.valid(version)) continue;\n    if (semver.prerelease(version)) continue;\n    if (semver.lte(version, installedVersion)) continue;\n\n    const bump = classifyBump(installedVersion, version);\n    if (!bump) continue;\n\n    const daysAgo = daysSince(dateStr);\n    const list = byBump.get(bump) ?? [];\n    list.push({ version, daysAgo });\n    byBump.set(bump, list);\n\n    // Track the oldest release, at whichever bump tier it belongs to, that's\n    // still within that tier's configured age threshold (#21) — generalizes\n    // what was previously a patch-only check to all three tiers, since the\n    // same \"is this candidate old enough to be safely adopted\" question\n    // applies identically to patch, minor, and major bumps, just against a\n    // different configured threshold per tier.\n    const threshold = thresholds[bump];\n    if (\n      threshold !== false &&\n      threshold !== undefined &&\n      daysAgo <= threshold &&\n      (minCompliantReleasedDaysAgo === undefined ||\n        daysAgo > minCompliantReleasedDaysAgo)\n    ) {\n      minCompliantVersion = version;\n      minCompliantReleasedDaysAgo = daysAgo;\n      minCompliantBump = bump;\n    }\n  }\n\n  // A bump tier is \"breached\" if its oldest available version is older than the\n  // tier's threshold — report the newest version in that tier as the upgrade\n  // target, not the version that happened to trigger the breach.\n  const upgrades: AvailableUpgrade[] = [];\n  for (const [bump, versions] of byBump.entries()) {\n    const oldestDaysAgo = Math.max(...versions.map((v) => v.daysAgo));\n    const level = upgradeLevel(oldestDaysAgo, bump, thresholds);\n    if (!level) continue;\n\n    const newest = pickNewest(versions);\n    upgrades.push({\n      version: newest.version,\n      releasedDaysAgo: newest.daysAgo,\n      breachReleasedDaysAgo: oldestDaysAgo,\n      semverBump: bump,\n      level,\n      thresholdDays: thresholds[bump] as number,\n    });\n  }\n\n  const finalUpgrades = upgrades.sort(\n    (a, b) => b.releasedDaysAgo - a.releasedDaysAgo,\n  );\n\n  const latestVersion = distTags?.['latest'];\n  const latestEntry = latestVersion ? timeMap[latestVersion] : undefined;\n  const latestReleasedDaysAgo = latestEntry\n    ? daysSince(latestEntry)\n    : undefined;\n\n  // If nothing newer than installed ever fell inside its tier's threshold,\n  // the only real landing spot is latest — treat it as the compliant target\n  // even though it's itself past the window, since there's no fresher\n  // release to upgrade to instead (#26).\n  const hadInWindowCandidate = minCompliantVersion !== undefined;\n  if (\n    !hadInWindowCandidate &&\n    latestVersion &&\n    latestReleasedDaysAgo !== undefined &&\n    !semver.prerelease(latestVersion) &&\n    semver.gt(latestVersion, installedVersion)\n  ) {\n    minCompliantVersion = latestVersion;\n    minCompliantReleasedDaysAgo = latestReleasedDaysAgo;\n  }\n\n  for (const upgrade of finalUpgrades) {\n    if (latestVersion && upgrade.version === latestVersion) {\n      upgrade.isLatest = true;\n    }\n  }\n\n  // The latest-fallback above is a display convenience for \"closest\n  // achievable target\" — it must not also erase worstLevel. A package with\n  // breached upgrades is still overdue even when latest itself is past the\n  // threshold and there's nothing fresher to recommend instead (#29).\n  const worstLevel: UpgradeLevel | null = finalUpgrades.some(\n    (u) => u.level === 'major_overdue',\n  )\n    ? 'major_overdue'\n    : finalUpgrades.length > 0\n      ? 'minor_overdue'\n      : null;\n\n  // Only surface a \"coming due\" advisory when nothing has breached yet — a\n  // package that's already in violation on one tier doesn't also need an\n  // \"N days remaining\" note about another, unbreached tier.\n  let pendingUpgrade: PendingUpgrade | undefined;\n  if (worstLevel === null) {\n    for (const [bump, versions] of byBump.entries()) {\n      const threshold = thresholds[bump];\n      if (threshold === false || threshold === undefined) continue;\n\n      const oldestDaysAgo = Math.max(...versions.map((v) => v.daysAgo));\n      const daysRemaining = threshold - oldestDaysAgo;\n      if (daysRemaining <= 0) continue;\n\n      if (!pendingUpgrade || daysRemaining < pendingUpgrade.daysRemaining) {\n        const newest = pickNewest(versions);\n        pendingUpgrade = {\n          version: newest.version,\n          semverBump: bump,\n          releasedDaysAgo: newest.daysAgo,\n          thresholdDays: threshold,\n          daysRemaining,\n        };\n      }\n    }\n  }\n\n  return {\n    upgrades: finalUpgrades,\n    worstLevel,\n    pendingUpgrade,\n    latestVersion,\n    latestReleasedDaysAgo,\n    minCompliantVersion,\n    minCompliantReleasedDaysAgo,\n    minCompliantInWindow: hadInWindowCandidate,\n    minCompliantBump,\n  };\n}\n\nconst LEVEL_RANK: Record<'null' | UpgradeLevel, number> = {\n  null: 0,\n  minor_overdue: 1,\n  major_overdue: 2,\n};\n\nfunction levelRank(level: UpgradeLevel | null): number {\n  return LEVEL_RANK[level ?? 'null'];\n}\n\n/** A vacuous \"nothing enforced\" result — worstLevel stays null regardless\n * of what the registry timeline actually says, since there's no enforced\n * baseline to measure against. */\nconst NOTHING_ENFORCED: ReleaseAgeForVersion = {\n  upgrades: [],\n  worstLevel: null,\n  minCompliantInWindow: false,\n};\n\n/**\n * Resolves which of `allVersions` count toward compliance ('root': just\n * `installedVersion`, and only when `hasRootVersion` confirms it's a real\n * direct dependency — not the \"fell back to the highest resolved version\"\n * placeholder for a purely transitive package (#62); 'tree': every\n * resolved copy). Evaluates each candidate independently via\n * `computeReleaseAgeForVersion`, and combines them into a single verdict —\n * the worst result among the enforced versions — while still surfacing\n * overdue-but-not-enforced copies via `advisoryBreaches` regardless of\n * scope (#57).\n */\nfunction computeReleaseAge(\n  installedVersion: string,\n  allVersions: string[],\n  timeMap: Record<string, string>,\n  deprecated: string | undefined,\n  thresholds: ReleaseAgeConfig['thresholds'],\n  distTags: Record<string, string> | undefined,\n  severity: 'error' | 'warn',\n  scope: 'root' | 'tree',\n  hasRootVersion: boolean,\n): ReleaseAgeEntry {\n  const candidates =\n    allVersions.length > 0\n      ? Array.from(new Set(allVersions))\n      : [installedVersion];\n  if (!candidates.includes(installedVersion)) candidates.push(installedVersion);\n\n  const enforcedVersions =\n    scope === 'tree' ? candidates : hasRootVersion ? [installedVersion] : [];\n\n  const perVersion = new Map<string, ReleaseAgeForVersion>();\n  for (const version of candidates) {\n    perVersion.set(\n      version,\n      computeReleaseAgeForVersion(version, timeMap, thresholds, distTags),\n    );\n  }\n\n  // No enforced baseline at all — e.g. `scope: 'root'` on a package that\n  // was never a direct dependency (only reachable transitively). Nothing\n  // can fail comply for it; every candidate below still gets a chance to\n  // surface as an advisory breach instead of vanishing silently.\n  let baselineVersion = installedVersion;\n  let baseline: ReleaseAgeForVersion = NOTHING_ENFORCED;\n  if (enforcedVersions.length > 0) {\n    baselineVersion = enforcedVersions[0];\n    baseline = perVersion.get(baselineVersion)!;\n    for (const version of enforcedVersions.slice(1)) {\n      const candidate = perVersion.get(version)!;\n      const candidateRank = levelRank(candidate.worstLevel);\n      const baselineRank = levelRank(baseline.worstLevel);\n      const candidateBreachAge =\n        candidate.upgrades[0]?.breachReleasedDaysAgo ?? 0;\n      const baselineBreachAge =\n        baseline.upgrades[0]?.breachReleasedDaysAgo ?? 0;\n      if (\n        candidateRank > baselineRank ||\n        (candidateRank === baselineRank &&\n          candidateBreachAge > baselineBreachAge)\n      ) {\n        baseline = candidate;\n        baselineVersion = version;\n      }\n    }\n  }\n\n  const advisoryBreaches: { version: string; level: UpgradeLevel }[] = [];\n  for (const version of candidates) {\n    if (enforcedVersions.includes(version)) continue;\n    const result = perVersion.get(version)!;\n    if (result.worstLevel) {\n      advisoryBreaches.push({ version, level: result.worstLevel });\n    }\n  }\n\n  return {\n    installedVersion: baselineVersion,\n    upgrades: baseline.upgrades,\n    worstLevel: baseline.worstLevel,\n    pendingUpgrade: baseline.pendingUpgrade,\n    deprecated,\n    latestVersion: baseline.latestVersion,\n    latestReleasedDaysAgo: baseline.latestReleasedDaysAgo,\n    minCompliantVersion: baseline.minCompliantVersion,\n    minCompliantReleasedDaysAgo: baseline.minCompliantReleasedDaysAgo,\n    minCompliantInWindow: baseline.minCompliantInWindow,\n    minCompliantBump: baseline.minCompliantBump,\n    severity,\n    scope,\n    evaluatedVersions: candidates.length > 1 ? candidates : undefined,\n    advisoryBreaches:\n      advisoryBreaches.length > 0 ? advisoryBreaches : undefined,\n  };\n}\n\n/**\n * Resolves the effective scope for a package: `scopeExceptions` (glob,\n * matched like `enforceOn`) flips the global `scope` default for packages\n * that need the opposite policy — e.g. tree-wide everywhere except a\n * package whose transitive pins can't be controlled down to root (#57).\n */\nexport function resolveReleaseAgeScope(\n  packageName: string,\n  config: ReleaseAgeConfig,\n): 'root' | 'tree' {\n  if (\n    config.scopeExceptions.length > 0 &&\n    micromatch.isMatch(packageName, config.scopeExceptions)\n  ) {\n    return config.scope === 'root' ? 'tree' : 'root';\n  }\n  return config.scope;\n}\n\nexport async function enrichWithReleaseAge(\n  packages: PackageDistribution[],\n  config: ReleaseAgeConfig,\n): Promise<{ enriched: PackageDistribution[]; skipped: number }> {\n  const registryUrl = config.registry;\n  const authToken =\n    config.authToken ?? process.env['HERMEX_REGISTRY_AUTH_TOKEN'];\n  // `packages` is every package the repo owns (#78); only a subset is in\n  // scope for a registry lookup — see `isReleaseAgeTarget`. Filtering here\n  // rather than upstream keeps `packages[]` honest about what the repo\n  // depends on while leaving registry traffic and the compliance verdict\n  // exactly where they were.\n  const targets = packages.filter(\n    (p) => !p.internal && p.version && isReleaseAgeTarget(p, config.enforceOn),\n  );\n  const enriched = [...packages];\n  let skipped = 0;\n\n  const envTtl = Number(process.env['HERMEX_REGISTRY_CACHE_TTL_MS']);\n  const cacheOptions: CacheOptions = {\n    ttlMs: Number.isFinite(envTtl) && envTtl > 0 ? envTtl : config.cacheTtlMs,\n    disabled:\n      process.env['HERMEX_REGISTRY_CACHE_DISABLED'] === '1' ||\n      config.cacheDisabled === true,\n  };\n\n  // Process in batches of CONCURRENCY\n  for (let i = 0; i < targets.length; i += CONCURRENCY) {\n    const batch = targets.slice(i, i + CONCURRENCY);\n    const results = await Promise.all(\n      batch.map(async (pkg) => {\n        const info = await getPackageInfo(\n          pkg.packageName,\n          registryUrl,\n          authToken,\n          cacheOptions,\n        );\n        if (!info || !info.time) {\n          skipped++;\n          return { pkg, entry: null };\n        }\n\n        const deprecated =\n          info.versions?.[pkg.version!]?.deprecated ?? info.deprecated;\n\n        const severity: 'error' | 'warn' =\n          config.enforceOn.length === 0 ||\n          micromatch.isMatch(pkg.packageName, config.enforceOn)\n            ? 'error'\n            : 'warn';\n\n        const scope = resolveReleaseAgeScope(pkg.packageName, config);\n        // `undefined` (never populated — e.g. a hand-built PackageDistribution\n        // in a test) is treated as \"unknown, assume root\" for backward\n        // compatibility; only an explicit `null` — set by the real pipeline\n        // when the lockfile layer confirms this isn't a direct dependency —\n        // means \"don't enforce this under root scope\" (#62).\n        const hasRootVersion = pkg.rootVersion !== null;\n\n        const entry = computeReleaseAge(\n          pkg.version!,\n          pkg.allVersions,\n          info.time,\n          typeof deprecated === 'string' ? deprecated : undefined,\n          config.thresholds,\n          info['dist-tags'],\n          severity,\n          scope,\n          hasRootVersion,\n        );\n\n        return { pkg, entry };\n      }),\n    );\n\n    for (const { pkg, entry } of results) {\n      if (!entry) continue;\n      const idx = enriched.findIndex((p) => p.packageName === pkg.packageName);\n      if (idx !== -1) {\n        enriched[idx] = { ...enriched[idx], releaseAge: entry };\n      }\n    }\n  }\n\n  return { enriched, skipped };\n}\n","import micromatch from 'micromatch';\nimport { readPackageJson, toArray, isEnabled } from '../rules/shared';\nimport type {\n  HermexConfig,\n  RulesConfig,\n  RuleConfig,\n  PackageFieldRule,\n  EngineVersionRule,\n  CodeownersRule,\n} from './schema';\n\n/**\n * A rule with severity narrowed to 'error' | 'warn' | 'info' — 'off' is only\n * ever a valid *input* severity (authored in `rules` or `overrides[].rules`);\n * `resolveRules` below is the one place that resolves it away, so nothing\n * downstream (evaluators, aggregation, compliance) needs to account for it.\n */\ntype Resolved<T extends { severity: string }> = T & {\n  severity: Exclude<T['severity'], 'off'>;\n};\n\nexport type ResolvedRuleConfig = Resolved<RuleConfig>;\nexport type ResolvedPackageFieldRule = Resolved<PackageFieldRule>;\nexport type ResolvedEngineVersionRule = Resolved<EngineVersionRule>;\nexport type ResolvedCodeownersRule = Resolved<CodeownersRule>;\n\n/** The shape `RulesConfig` resolves to after `applyOverrides` — see `ResolvedRuleConfig`. */\nexport interface ResolvedRulesConfig {\n  detect_files: ResolvedRuleConfig[];\n  require_files: ResolvedRuleConfig[];\n  forbid_packages: ResolvedRuleConfig[];\n  require_packages: ResolvedRuleConfig[];\n  require_scripts: ResolvedRuleConfig[];\n  require_package_fields: ResolvedPackageFieldRule[];\n  forbid_package_fields: ResolvedPackageFieldRule[];\n  engine_version: ResolvedEngineVersionRule[];\n  codeowners: ResolvedCodeownersRule | undefined;\n}\n\n/** What `applyOverrides` returns: `HermexConfig` with `rules` resolved. */\nexport type ResolvedHermexConfig = Omit<HermexConfig, 'rules'> & {\n  rules: ResolvedRulesConfig;\n};\n\nfunction patternsMatch(a: string[], b: string[]): boolean {\n  const setA = new Set(a);\n  const setB = new Set(b);\n  if (setA.size !== setB.size) return false;\n  for (const p of setA) if (!setB.has(p)) return false;\n  return true;\n}\n\n/**\n * Upserts each rule into `base`, keyed by an exact (order-independent)\n * match on `patterns` — mirrors ESLint's per-rule override: a rule whose\n * patterns match an existing one replaces it; patterns with no existing\n * match are appended as a new rule. Severity 'off' is resolved away right\n * here (via `isEnabled`) rather than replacing anything — this is the one\n * place in the whole pipeline that needs to know 'off' exists.\n */\nfunction upsertPatternRules<T extends { severity: string; patterns: string[] }>(\n  base: Resolved<T>[],\n  overrides: T[],\n): Resolved<T>[] {\n  let result = base;\n  for (const rule of overrides) {\n    result = result.filter((r) => !patternsMatch(r.patterns, rule.patterns));\n    if (isEnabled(rule)) {\n      result = [...result, rule];\n    }\n  }\n  return result;\n}\n\n/** Same upsert semantics as {@link upsertPatternRules}, keyed by `range` instead of `patterns` (engine_version has no patterns). */\nfunction upsertEngineVersionRules<\n  T extends { severity: string; range: string },\n>(base: Resolved<T>[], overrides: T[]): Resolved<T>[] {\n  let result = base;\n  for (const rule of overrides) {\n    result = result.filter((r) => r.range !== rule.range);\n    if (isEnabled(rule)) {\n      result = [...result, rule];\n    }\n  }\n  return result;\n}\n\n/** `codeowners` only ever holds one rule, so 'off' simply clears it. */\nfunction resolveCodeowners<T extends { severity: string }>(\n  rule: T | undefined,\n): Resolved<T> | undefined {\n  if (rule === undefined) return undefined;\n  if (!isEnabled(rule)) return undefined;\n  return rule;\n}\n\n/**\n * Resolves `rules` to its final, evaluator-ready form by upserting each\n * list against itself: a rule authored with severity 'off' — directly in\n * the base config, not only via `overrides` — is dropped, and rules\n * sharing an identity (patterns, or range for engine_version) collapse to\n * the last one. This is the same upsert primitive `applyOverrides` uses\n * for `overrides`, just seeded from an empty base — so a rule authored\n * once in `rules` and a rule layered in via `overrides` behave\n * identically. It's what a future shared/extends-style base config would\n * need too: 'off' isn't an overrides-only concept, it's how any layer\n * disables a rule, same as ESLint/oxlint.\n */\nfunction resolveRules(rules: RulesConfig): ResolvedRulesConfig {\n  return {\n    detect_files: upsertPatternRules([], toArray(rules.detect_files)),\n    require_files: upsertPatternRules([], toArray(rules.require_files)),\n    forbid_packages: upsertPatternRules([], toArray(rules.forbid_packages)),\n    require_packages: upsertPatternRules([], toArray(rules.require_packages)),\n    require_scripts: upsertPatternRules([], toArray(rules.require_scripts)),\n    require_package_fields: upsertPatternRules(\n      [],\n      toArray(rules.require_package_fields),\n    ),\n    forbid_package_fields: upsertPatternRules(\n      [],\n      toArray(rules.forbid_package_fields),\n    ),\n    engine_version: upsertEngineVersionRules([], toArray(rules.engine_version)),\n    codeowners: resolveCodeowners(rules.codeowners),\n  };\n}\n\n/**\n * Resolves the final `rules` for the repo at `repoPath`: first `rules`\n * itself is resolved against itself (severity 'off' and duplicate\n * identities collapse — see `resolveRules`), then every `overrides` entry\n * whose `match` patterns hit the repo's package.json \"name\" is upserted on\n * top, in array order. `codeowners` only ever holds one rule, so a\n * matching override replaces the base entirely (severity 'off' clears it).\n *\n * The return type guarantees no rule can have severity 'off' — nothing\n * downstream of this function (evaluators, aggregation, compliance) needs\n * to check for it.\n */\nexport function applyOverrides(\n  config: HermexConfig,\n  repoPath: string,\n): ResolvedHermexConfig {\n  const rules = resolveRules(config.rules);\n\n  if (config.overrides.length > 0) {\n    const pkg = readPackageJson(repoPath);\n    const repoName = typeof pkg?.name === 'string' ? pkg.name : undefined;\n\n    if (repoName) {\n      const matching = config.overrides.filter((override) =>\n        micromatch.isMatch(repoName, override.match),\n      );\n\n      for (const override of matching) {\n        const o = override.rules;\n        if (o.detect_files !== undefined) {\n          rules.detect_files = upsertPatternRules(\n            rules.detect_files,\n            toArray(o.detect_files),\n          );\n        }\n        if (o.require_files !== undefined) {\n          rules.require_files = upsertPatternRules(\n            rules.require_files,\n            toArray(o.require_files),\n          );\n        }\n        if (o.forbid_packages !== undefined) {\n          rules.forbid_packages = upsertPatternRules(\n            rules.forbid_packages,\n            toArray(o.forbid_packages),\n          );\n        }\n        if (o.require_packages !== undefined) {\n          rules.require_packages = upsertPatternRules(\n            rules.require_packages,\n            toArray(o.require_packages),\n          );\n        }\n        if (o.require_scripts !== undefined) {\n          rules.require_scripts = upsertPatternRules(\n            rules.require_scripts,\n            toArray(o.require_scripts),\n          );\n        }\n        if (o.require_package_fields !== undefined) {\n          rules.require_package_fields = upsertPatternRules(\n            rules.require_package_fields,\n            toArray(o.require_package_fields),\n          );\n        }\n        if (o.forbid_package_fields !== undefined) {\n          rules.forbid_package_fields = upsertPatternRules(\n            rules.forbid_package_fields,\n            toArray(o.forbid_package_fields),\n          );\n        }\n        if (o.engine_version !== undefined) {\n          rules.engine_version = upsertEngineVersionRules(\n            rules.engine_version,\n            toArray(o.engine_version),\n          );\n        }\n        if (o.codeowners !== undefined) {\n          rules.codeowners = resolveCodeowners(o.codeowners);\n        }\n      }\n    }\n  }\n\n  return { ...config, rules };\n}\n","import type { Ora } from 'ora';\nimport chalk from 'chalk';\nimport { parseFile } from '../swc-parser';\nimport type { UsageReport } from '../swc-parser';\nimport type { ParseError } from '../swc-parser/types';\nimport { aggregateReports } from '../utils/aggregator';\nimport type { AggregatedReport } from '../utils/aggregator';\nimport { printErrors } from '../utils/print-errors';\nimport { findFiles } from '../utils/file-utils';\nimport { findAndParseLockfile } from '../lock-parser';\nimport { evaluateRules } from '../rules/evaluator';\nimport { collectDeclaredPackages } from '../rules/shared';\nimport { enrichWithReleaseAge } from '../npm-registry/enricher';\nimport { applyOverrides } from '../config/overrides';\nimport type { HermexConfig } from '../config/types';\n\nconst DECLARATION_FILE_RE = /\\.d\\.(ts|mts|cts)$/;\n\nfunction isDeclarationFile(filePath: string): boolean {\n  return DECLARATION_FILE_RE.test(filePath);\n}\n\n/**\n * Runs the shared parse → aggregate → rules → release-age pipeline used by\n * both `scan` and `comply`. Returns `null` if no files matched (the spinner\n * has already reported the failure); throws on unexpected errors.\n */\nexport async function runPipeline(\n  config: HermexConfig,\n  spinner: Ora,\n  isJson: boolean,\n): Promise<AggregatedReport | null> {\n  // Repo-scoped rule overrides are resolved here, against the repo actually\n  // being analyzed (process.cwd()) — not in the loader, which only knows\n  // where the config file itself came from and may be pointed elsewhere via\n  // `--config`.\n  const resolvedConfig = applyOverrides(config, process.cwd());\n\n  const lockfileResult = findAndParseLockfile(process.cwd());\n  const declaredPackages = collectDeclaredPackages(process.cwd());\n\n  spinner.succeed(\n    chalk.blue(\n      `Found ${lockfileResult.lockfileType} lockfile (supports: ${lockfileResult.supportedVersions.join(', ')}) - ${Object.keys(lockfileResult.versions).length} packages`,\n    ),\n  );\n\n  if (spinner.isEnabled) spinner.start('Finding files...');\n  const discovered = await findFiles(\n    resolvedConfig.includes,\n    resolvedConfig.excludes,\n  );\n  const files = discovered.filter((f) => !isDeclarationFile(f));\n\n  if (files.length === 0) {\n    spinner.fail(\n      chalk.red(\n        `No files found matching includes: ${resolvedConfig.includes.join(', ')}`,\n      ),\n    );\n    return null;\n  }\n\n  spinner.succeed(chalk.green(`Found ${files.length} files`));\n\n  if (spinner.isEnabled) spinner.start('Analyzing files...');\n  const reports: UsageReport[] = [];\n  const parseErrors: ParseError[] = [];\n\n  for (let i = 0; i < files.length; i++) {\n    const file = files[i];\n    if (spinner.isEnabled)\n      spinner.text = `Analyzing files... (${i + 1}/${files.length})`;\n\n    try {\n      const report = parseFile(file);\n      if (report) {\n        reports.push(report);\n      }\n    } catch (error: unknown) {\n      const message = error instanceof Error ? error.message : String(error);\n      parseErrors.push({ file, message });\n    }\n  }\n\n  spinner.succeed(\n    chalk.green(\n      `Analysis complete! Analyzed ${reports.length}/${files.length} files`,\n    ),\n  );\n\n  printErrors(parseErrors, isJson);\n\n  const aggregated = aggregateReports(\n    reports,\n    lockfileResult.versions,\n    resolvedConfig,\n    lockfileResult.multiVersions,\n    lockfileResult.resolutions,\n    declaredPackages,\n  );\n\n  const evaluatorViolations = evaluateRules(\n    process.cwd(),\n    resolvedConfig.rules,\n    resolvedConfig.excludes,\n    files,\n  );\n  aggregated.ruleViolations = [\n    ...aggregated.ruleViolations,\n    ...evaluatorViolations,\n  ];\n\n  if (resolvedConfig.releaseAge.enabled) {\n    if (spinner.isEnabled)\n      spinner.start('Fetching release age from registry...');\n    const { enriched, skipped } = await enrichWithReleaseAge(\n      aggregated.packageDistribution,\n      resolvedConfig.releaseAge,\n    );\n    aggregated.packageDistribution = enriched;\n    spinner.succeed(\n      chalk.blue(\n        `Release age fetched${skipped > 0 ? chalk.gray(` (${skipped} packages skipped — registry unreachable or not found)`) : ''}`,\n      ),\n    );\n  }\n\n  return aggregated;\n}\n","import ora from 'ora';\nimport type { Ora } from 'ora';\nimport chalk from 'chalk';\nimport { getVersion } from '../utils/version';\nimport { applyColorLevel, resolveColorLevel } from '../utils/severity-format';\nimport type { HermexConfig } from '../config/types';\n\nexport interface CommandContext {\n  isJson: boolean;\n  spinner: Ora;\n}\n\nexport interface CommandContextOptions {\n  /** Overrides config.output.format when set (from --format). */\n  format?: 'human' | 'json';\n  /** Set to false when --no-color is passed. */\n  color?: boolean;\n}\n\n/**\n * Shared command preamble: routes human-readable chrome (version line,\n * spinner) to stderr when the command emits JSON on stdout.\n */\nexport function createCommandContext(\n  config: HermexConfig,\n  options: CommandContextOptions = {},\n): CommandContext {\n  applyColorLevel(\n    resolveColorLevel({\n      colorFlag: options.color === false ? false : undefined,\n      noColorEnv: process.env['NO_COLOR'],\n    }),\n  );\n\n  const isJson = (options.format ?? config.output.format) === 'json';\n  const stream = isJson ? process.stderr : process.stdout;\n  stream.write(chalk.gray(`hermex v${getVersion()}\\n`));\n  const spinner = ora({ text: 'Parsing lockfile...', stream }).start();\n  return { isJson, spinner };\n}\n","import { Command, Option } from 'commander';\nimport chalk from 'chalk';\nimport { aggregateReports } from '../utils/aggregator';\nimport { printSummary } from '../utils/print-summary';\nimport { printDetails } from '../utils/print-details';\nimport { printComponents } from '../utils/print-components';\nimport { printPatterns } from '../utils/print-patterns';\nimport { printPackages } from '../utils/print-packages';\nimport { printVersus } from '../utils/print-versus';\nimport { printRules } from '../utils/print-rules';\nimport { printJson } from '../utils/print-json';\nimport { loadConfig } from '../config/loader';\nimport { runPipeline } from './pipeline';\nimport { createCommandContext } from './command-context';\nimport type { CommandContextOptions } from './command-context';\nimport type { HermexConfig } from '../config/types';\n\nexport function registerScanCommand(program: Command) {\n  program\n    .command('scan')\n    .description('Scan and analyze local files')\n    .option(\n      '--config <path>',\n      'Path to hermex config file (overrides CWD discovery)',\n    )\n    .addOption(\n      new Option(\n        '--format <format>',\n        'Output format, overrides output.format in the config file',\n      ).choices(['human', 'json']),\n    )\n    .option('--no-color', 'Disable colored output (see also NO_COLOR env var)')\n    .action(\n      async (options: {\n        config?: string;\n        format?: 'human' | 'json';\n        color?: boolean;\n      }) => {\n        const config = await loadConfig(process.cwd(), options.config);\n        await executeScan(config, {\n          format: options.format,\n          color: options.color,\n        });\n      },\n    );\n}\n\nexport async function executeScan(\n  config: HermexConfig,\n  contextOptions: CommandContextOptions = {},\n) {\n  const { isJson, spinner } = createCommandContext(config, contextOptions);\n\n  try {\n    const aggregated = await runPipeline(config, spinner, isJson);\n    if (!aggregated) return;\n\n    if (isJson) {\n      printJson(aggregated);\n    } else {\n      printScanResults(aggregated, config);\n    }\n  } catch (error: unknown) {\n    const message = error instanceof Error ? error.message : String(error);\n    spinner.fail(chalk.red('Analysis failed: ' + message));\n    process.exitCode = 1;\n  }\n}\n\nfunction printScanResults(\n  aggregated: ReturnType<typeof aggregateReports>,\n  config: HermexConfig,\n) {\n  if (config.output.packages) {\n    printPackages(aggregated, config.output.packages);\n  }\n\n  if (config.output.versus) {\n    printVersus(aggregated);\n  }\n\n  if (config.output.rules) {\n    printRules(aggregated);\n  }\n\n  if (config.output.details) {\n    printDetails(aggregated);\n  }\n\n  if (config.output.components) {\n    printComponents(aggregated, config.output.components);\n  }\n\n  if (config.output.patterns) {\n    printPatterns(aggregated, config.output.patterns);\n  }\n\n  if (config.output.summary) {\n    printSummary(aggregated);\n  }\n}\n","import chalk from 'chalk';\nimport type { ComplianceResult } from './compliance';\nimport { countMandatoryViolations } from './compliance';\nimport { severityIcon } from './severity-format';\n\n/**\n * Prints only the bottom-line verdict — the Rules and Packages sections\n * printed above this already itemize every violation (rule and release-age\n * alike), so repeating them here would just restate the same 🔴 rows.\n */\nexport function printComplianceVerdict(result: ComplianceResult): void {\n  const mandatoryCount = countMandatoryViolations(result);\n\n  if (result.compliant) {\n    console.log(\n      chalk.greenBright.bold(`\\n${severityIcon('success')} COMPLIANT\\n`),\n    );\n    return;\n  }\n\n  console.log(chalk.redBright.bold(`\\n${severityIcon('error')} NOT COMPLIANT`));\n  console.log(\n    chalk.red(\n      `  ${mandatoryCount} mandatory violation${mandatoryCount > 1 ? 's' : ''} found`,\n    ),\n  );\n  console.log();\n}\n","import { writeFileSync } from 'node:fs';\nimport type { AggregatedReport } from './aggregator';\nimport type { ComplianceResult } from './compliance';\nimport { countMandatoryViolations } from './compliance';\nimport { describeViolation, formatRuleType } from './print-rules';\nimport {\n  describeUpgradeTarget,\n  resolveCompliantTarget,\n  resolveInstalledVersion,\n} from './print-packages';\nimport { severityIcon, stripAnsi } from './severity-format';\n\n// A table, mirroring the Packages section below it, rather than a bullet\n// list — same shape, same scanability, in both output surfaces.\nfunction buildRulesSection(aggregated: AggregatedReport): string {\n  // Info-severity rows are excluded here (unlike the terminal `printRules`,\n  // which shows everything) — a summary meant for a PR comment or job\n  // summary should only surface what's actually enforceable (#31).\n  const ruleViolations = aggregated.ruleViolations.filter(\n    (v) => v.severity !== 'info',\n  );\n\n  // Nothing to report — omit the section entirely, matching\n  // buildPackagesSection below. The verdict section always states pass/fail\n  // clearly; a \"### Rules / All rule checks passed\" block with zero rows\n  // is boilerplate indistinguishable from \"no rules were ever configured.\"\n  if (ruleViolations.length === 0) {\n    return '';\n  }\n\n  const lines: string[] = [\n    '### Rules',\n    '',\n    '| | Rule | Description |',\n    '|---|---|---|',\n  ];\n\n  for (const v of ruleViolations) {\n    lines.push(\n      `| ${severityIcon(v.severity)} | ${formatRuleType(v.type)} | ${describeViolation(v)} |`,\n    );\n  }\n\n  const errorCount = ruleViolations.filter(\n    (v) => v.severity === 'error',\n  ).length;\n  const warnCount = ruleViolations.filter((v) => v.severity === 'warn').length;\n  const parts: string[] = [];\n  if (errorCount > 0)\n    parts.push(`${errorCount} error${errorCount > 1 ? 's' : ''}`);\n  if (warnCount > 0)\n    parts.push(`${warnCount} warning${warnCount > 1 ? 's' : ''}`);\n  lines.push('', parts.join(', '));\n\n  return lines.join('\\n') + '\\n';\n}\n\n// Built directly from compliance.releaseAgeViolations rather than a\n// separately-derived filter — that's already exactly \"release-age packages\n// that are mandatory failures\" (src/utils/compliance.ts), so the row list\n// can never drift from the verdict's mandatory-violation count. Banned and\n// deprecated-only/not-enforced packages don't get a row here: banned ones\n// are already shown in Rules as a forbid_packages line, and\n// deprecated-only or not-enforced-overdue packages are info-level, not\n// enforceable (#31).\n//\n// Bundle-impact (multiple resolved copies) and advisory nested breaches are\n// deliberately NOT included here — they're non-blocking context, and a\n// summary meant for a PR comment or CI check reads any colored row/line as\n// something that needs attention. That context belongs in the human\n// `--format human` table (stdout), not in a surface used for gating (#59).\nfunction buildPackagesSection(compliance: ComplianceResult): string {\n  const mandatory = compliance.releaseAgeViolations;\n  if (mandatory.length === 0) return '';\n\n  const lines: string[] = [\n    '### Packages',\n    '',\n    '| | Package | Installed | Target |',\n    '|---|---|---|---|',\n  ];\n  for (const pkg of mandatory) {\n    const top = pkg.releaseAge?.upgrades[0];\n    const reasons: string[] = [];\n    if (top)\n      reasons.push(\n        describeUpgradeTarget(top, resolveCompliantTarget(pkg.releaseAge)),\n      );\n    if (pkg.releaseAge?.deprecated) reasons.push('deprecated');\n    lines.push(\n      `| ${severityIcon('error')} | \\`${pkg.packageName}\\` | ${resolveInstalledVersion(pkg)} | ${reasons.join(', ')} |`,\n    );\n  }\n\n  return lines.join('\\n') + '\\n';\n}\n\nfunction buildVerdictSection(compliance: ComplianceResult): string {\n  if (compliance.compliant) {\n    return `### ${severityIcon('success')} COMPLIANT\\n`;\n  }\n\n  const mandatoryCount = countMandatoryViolations(compliance);\n\n  return `### ${severityIcon('error')} NOT COMPLIANT\\n\\n${mandatoryCount} mandatory violation${mandatoryCount > 1 ? 's' : ''} found\\n`;\n}\n\nexport const DEFAULT_SUMMARY_TITLE = 'Hermex Compliance Report';\n\n/**\n * Writes a concise, ANSI-free markdown summary (title, rules, mandatory\n * package violations, verdict) for CI surfaces that can't render the full\n * human report — a sticky PR comment or job summary (#31). Omits Versus and\n * progress chrome by construction; never touches ora or the Versus renderer.\n */\nexport function writeSummaryFile(\n  path: string,\n  aggregated: AggregatedReport,\n  compliance: ComplianceResult,\n  title: string = DEFAULT_SUMMARY_TITLE,\n): void {\n  const sections = [\n    `# ${title}\\n`,\n    buildRulesSection(aggregated),\n    buildPackagesSection(compliance),\n    buildVerdictSection(compliance),\n  ].filter((section) => section.length > 0);\n\n  writeFileSync(path, stripAnsi(sections.join('\\n')));\n}\n","import { Command, Option } from 'commander';\nimport chalk from 'chalk';\nimport { printJson } from '../utils/print-json';\nimport { printRules } from '../utils/print-rules';\nimport { printPackages } from '../utils/print-packages';\nimport { printVersus } from '../utils/print-versus';\nimport { printComplianceVerdict } from '../utils/print-compliance';\nimport { computeCompliance } from '../utils/compliance';\nimport {\n  writeSummaryFile,\n  DEFAULT_SUMMARY_TITLE,\n} from '../utils/write-summary-file';\nimport { loadConfig } from '../config/loader';\nimport { runPipeline } from './pipeline';\nimport { createCommandContext } from './command-context';\nimport type { CommandContextOptions } from './command-context';\nimport type { HermexConfig } from '../config/types';\n\nexport function registerComplyCommand(program: Command) {\n  program\n    .command('comply')\n    .description(\n      'Check compliance with hermex.config.ts rules and release-age policy (exits non-zero if not compliant)',\n    )\n    .option(\n      '--config <path>',\n      'Path to hermex config file (overrides CWD discovery)',\n    )\n    .addOption(\n      new Option(\n        '--format <format>',\n        'Output format, overrides output.format in the config file',\n      ).choices(['human', 'json']),\n    )\n    .option('--no-color', 'Disable colored output (see also NO_COLOR env var)')\n    .option(\n      '--summary-file <path>',\n      'Write a concise, ANSI-free markdown summary (rules, flagged packages, verdict) to this path, for a CI job summary or PR comment',\n    )\n    .option(\n      '--summary-title <text>',\n      'Title/heading for the --summary-file markdown output',\n      DEFAULT_SUMMARY_TITLE,\n    )\n    .action(\n      async (options: {\n        config?: string;\n        format?: 'human' | 'json';\n        color?: boolean;\n        summaryFile?: string;\n        summaryTitle: string;\n      }) => {\n        const config = await loadConfig(process.cwd(), options.config);\n        await executeComply(\n          config,\n          {\n            format: options.format,\n            color: options.color,\n          },\n          options.summaryFile,\n          options.summaryTitle,\n        );\n      },\n    );\n}\n\nexport async function executeComply(\n  config: HermexConfig,\n  contextOptions: CommandContextOptions = {},\n  summaryFile?: string,\n  summaryTitle: string = DEFAULT_SUMMARY_TITLE,\n) {\n  const { isJson, spinner } = createCommandContext(config, contextOptions);\n\n  try {\n    // Runs the full pipeline to completion regardless of violations found —\n    // comply must report everything in one pass, not fail on the first issue.\n    const aggregated = await runPipeline(config, spinner, isJson);\n    if (!aggregated) {\n      process.exitCode = 2;\n      return;\n    }\n\n    const compliance = computeCompliance(aggregated);\n\n    if (isJson) {\n      printJson(aggregated, compliance);\n    } else {\n      printRules(aggregated);\n      if (config.releaseAge.enabled) {\n        printPackages(aggregated, 'table');\n      }\n      if (config.output.versus) {\n        printVersus(aggregated);\n      }\n      printComplianceVerdict(compliance);\n    }\n\n    if (summaryFile) {\n      writeSummaryFile(summaryFile, aggregated, compliance, summaryTitle);\n    }\n\n    process.exitCode = compliance.compliant ? 0 : 1;\n  } catch (error: unknown) {\n    const message = error instanceof Error ? error.message : String(error);\n    spinner.fail(chalk.red('Compliance check failed: ' + message));\n    process.exitCode = 2;\n  }\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registerScanCommand } from './commands/scan';\nimport { registerComplyCommand } from './commands/comply';\nimport { getVersion } from './utils/version';\n\nexport const program = new Command();\n\nprogram\n  .name('hermex')\n  .description('Analyze React component usage patterns in your codebase')\n  .version(getVersion());\n\nregisterScanCommand(program);\nregisterComplyCommand(program);\n\nprogram.parse(process.argv);\n"],"mappings":"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"}