@codesentinel/codesentinel 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -0
- package/dist/index.js +1095 -51
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/application/run-analyze-command.ts","../../code-graph/src/domain/graph-model.ts","../../code-graph/src/domain/tarjan.ts","../../code-graph/src/domain/graph-metrics.ts","../../code-graph/src/infrastructure/typescript-project.ts","../../code-graph/src/application/build-project-graph-summary.ts","../../dependency-firewall/src/domain/external-analysis.ts","../../dependency-firewall/src/domain/types.ts","../../dependency-firewall/src/infrastructure/fs-loader.ts","../../dependency-firewall/src/parsing/package-json-loader.ts","../../dependency-firewall/src/parsing/package-lock-parser.ts","../../dependency-firewall/src/parsing/pnpm-lock-parser.ts","../../dependency-firewall/src/parsing/yarn-lock-parser.ts","../../dependency-firewall/src/parsing/bun-lock-parser.ts","../../dependency-firewall/src/application/analyze-dependency-exposure.ts","../../dependency-firewall/src/infrastructure/npm-registry-metadata-provider.ts","../../dependency-firewall/src/infrastructure/noop-metadata-provider.ts","../../dependency-firewall/src/index.ts","../../git-analyzer/src/domain/evolution-metrics.ts","../../git-analyzer/src/domain/evolution-types.ts","../../git-analyzer/src/application/analyze-repository-evolution.ts","../../git-analyzer/src/infrastructure/git-command-client.ts","../../git-analyzer/src/domain/git-log-format.ts","../../git-analyzer/src/parsing/git-log-parser.ts","../../git-analyzer/src/infrastructure/git-history-provider.ts","../../git-analyzer/src/index.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { runAnalyzeCommand, type AuthorIdentityCliMode } from \"./application/run-analyze-command.js\";\n\nconst program = new Command();\nconst packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), \"../package.json\");\nconst { version } = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version: string };\n\nprogram\n .name(\"codesentinel\")\n .description(\"Structural and evolutionary risk analysis for TypeScript/JavaScript codebases\")\n .version(version);\n\nprogram\n .command(\"analyze\")\n .argument(\"[path]\", \"path to the project to analyze\")\n .addOption(\n new Option(\n \"--author-identity <mode>\",\n \"author identity mode: likely_merge (heuristic) or strict_email (deterministic)\",\n )\n .choices([\"likely_merge\", \"strict_email\"])\n .default(\"likely_merge\"),\n )\n .action(async (path: string | undefined, options: { authorIdentity: AuthorIdentityCliMode }) => {\n const output = await runAnalyzeCommand(path, options.authorIdentity);\n process.stdout.write(`${output}\\n`);\n });\n\nif (process.argv.length <= 2) {\n program.outputHelp();\n process.exit(0);\n}\n\nawait program.parseAsync(process.argv);\n","import { resolve } from \"node:path\";\nimport { buildProjectGraphSummary } from \"@codesentinel/code-graph\";\nimport { analyzeDependencyExposureFromProject } from \"@codesentinel/dependency-firewall\";\nimport { analyzeRepositoryEvolutionFromGit } from \"@codesentinel/git-analyzer\";\nimport type { AnalyzeSummary } from \"@codesentinel/core\";\n\nexport type AuthorIdentityCliMode = \"likely_merge\" | \"strict_email\";\n\nconst resolveTargetPath = (inputPath: string | undefined, cwd: string): string =>\n resolve(cwd, inputPath ?? \".\");\n\nexport const runAnalyzeCommand = async (\n inputPath: string | undefined,\n authorIdentityMode: AuthorIdentityCliMode,\n): Promise<string> => {\n const invocationCwd = process.env[\"INIT_CWD\"] ?? process.cwd();\n const targetPath = resolveTargetPath(inputPath, invocationCwd);\n\n const structural = buildProjectGraphSummary({ projectPath: targetPath });\n const evolution = analyzeRepositoryEvolutionFromGit({\n repositoryPath: targetPath,\n config: { authorIdentityMode },\n });\n const external = await analyzeDependencyExposureFromProject({ repositoryPath: targetPath });\n\n const summary: AnalyzeSummary = {\n structural,\n evolution,\n external,\n };\n\n return JSON.stringify(summary, null, 2);\n};\n","export type NodeRecord = {\n id: string;\n absolutePath: string;\n relativePath: string;\n};\n\nexport type EdgeRecord = {\n from: string;\n to: string;\n};\n\nexport type GraphData = {\n nodes: readonly NodeRecord[];\n edges: readonly EdgeRecord[];\n adjacencyById: ReadonlyMap<string, readonly string[]>;\n};\n\nconst edgeKey = (from: string, to: string): string => `${from}\\u0000${to}`;\n\nexport const createGraphData = (\n nodes: readonly NodeRecord[],\n rawEdges: readonly EdgeRecord[],\n): GraphData => {\n const sortedNodes = [...nodes].sort((a, b) => a.id.localeCompare(b.id));\n const knownNodeIds = new Set(sortedNodes.map((node) => node.id));\n\n const uniqueEdgeMap = new Map<string, EdgeRecord>();\n for (const edge of rawEdges) {\n if (edge.from === edge.to) {\n continue;\n }\n\n if (!knownNodeIds.has(edge.from) || !knownNodeIds.has(edge.to)) {\n continue;\n }\n\n uniqueEdgeMap.set(edgeKey(edge.from, edge.to), edge);\n }\n\n const sortedEdges = [...uniqueEdgeMap.values()].sort((a, b) => {\n const fromCompare = a.from.localeCompare(b.from);\n if (fromCompare !== 0) {\n return fromCompare;\n }\n\n return a.to.localeCompare(b.to);\n });\n\n const adjacency = new Map<string, string[]>();\n for (const node of sortedNodes) {\n adjacency.set(node.id, []);\n }\n\n for (const edge of sortedEdges) {\n adjacency.get(edge.from)?.push(edge.to);\n }\n\n const adjacencyById = new Map<string, readonly string[]>();\n for (const [nodeId, targets] of adjacency.entries()) {\n adjacencyById.set(nodeId, [...targets]);\n }\n\n return {\n nodes: sortedNodes,\n edges: sortedEdges,\n adjacencyById,\n };\n};\n","type TarjanResult = {\n components: readonly (readonly string[])[];\n};\n\nexport const runTarjanScc = (adjacencyById: ReadonlyMap<string, readonly string[]>): TarjanResult => {\n let index = 0;\n const indices = new Map<string, number>();\n const lowLink = new Map<string, number>();\n const stack: string[] = [];\n const onStack = new Set<string>();\n const components: string[][] = [];\n\n const strongConnect = (nodeId: string): void => {\n indices.set(nodeId, index);\n lowLink.set(nodeId, index);\n index += 1;\n\n stack.push(nodeId);\n onStack.add(nodeId);\n\n const neighbors = adjacencyById.get(nodeId) ?? [];\n for (const nextId of neighbors) {\n if (!indices.has(nextId)) {\n strongConnect(nextId);\n const nodeLowLink = lowLink.get(nodeId);\n const nextLowLink = lowLink.get(nextId);\n if (nodeLowLink !== undefined && nextLowLink !== undefined && nextLowLink < nodeLowLink) {\n lowLink.set(nodeId, nextLowLink);\n }\n continue;\n }\n\n if (onStack.has(nextId)) {\n const nodeLowLink = lowLink.get(nodeId);\n const nextIndex = indices.get(nextId);\n if (nodeLowLink !== undefined && nextIndex !== undefined && nextIndex < nodeLowLink) {\n lowLink.set(nodeId, nextIndex);\n }\n }\n }\n\n const nodeLowLink = lowLink.get(nodeId);\n const nodeIndex = indices.get(nodeId);\n if (nodeLowLink === undefined || nodeIndex === undefined || nodeLowLink !== nodeIndex) {\n return;\n }\n\n const component: string[] = [];\n for (;;) {\n const popped = stack.pop();\n if (popped === undefined) {\n break;\n }\n\n onStack.delete(popped);\n component.push(popped);\n if (popped === nodeId) {\n break;\n }\n }\n\n component.sort((a, b) => a.localeCompare(b));\n components.push(component);\n };\n\n const nodeIds = [...adjacencyById.keys()].sort((a, b) => a.localeCompare(b));\n for (const nodeId of nodeIds) {\n if (!indices.has(nodeId)) {\n strongConnect(nodeId);\n }\n }\n\n components.sort((a, b) => {\n const firstA = a[0] ?? \"\";\n const firstB = b[0] ?? \"\";\n return firstA.localeCompare(firstB);\n });\n\n return { components };\n};\n","import type { FileDependency, GraphAnalysisSummary, GraphCycle, GraphMetrics } from \"@codesentinel/core\";\nimport type { GraphData } from \"./graph-model.js\";\nimport { runTarjanScc } from \"./tarjan.js\";\n\ntype DepthComputation = {\n depthByNodeId: ReadonlyMap<string, number>;\n graphDepth: number;\n cycles: readonly GraphCycle[];\n};\n\nconst hasSelfLoop = (nodeId: string, adjacencyById: ReadonlyMap<string, readonly string[]>): boolean => {\n const targets = adjacencyById.get(nodeId) ?? [];\n return targets.includes(nodeId);\n};\n\nconst computeCyclesAndDepth = (graph: GraphData): DepthComputation => {\n const { components } = runTarjanScc(graph.adjacencyById);\n\n const cycles: GraphCycle[] = [];\n const componentByNodeId = new Map<string, number>();\n components.forEach((component, index) => {\n for (const nodeId of component) {\n componentByNodeId.set(nodeId, index);\n }\n\n if (component.length > 1) {\n cycles.push({ nodes: [...component] });\n return;\n }\n\n const onlyNode = component[0];\n if (onlyNode !== undefined && hasSelfLoop(onlyNode, graph.adjacencyById)) {\n cycles.push({ nodes: [...component] });\n }\n });\n\n const dagOutgoing = new Map<number, Set<number>>();\n const inDegree = new Map<number, number>();\n\n for (let i = 0; i < components.length; i += 1) {\n dagOutgoing.set(i, new Set());\n inDegree.set(i, 0);\n }\n\n for (const edge of graph.edges) {\n const fromComponent = componentByNodeId.get(edge.from);\n const toComponent = componentByNodeId.get(edge.to);\n\n if (fromComponent === undefined || toComponent === undefined || fromComponent === toComponent) {\n continue;\n }\n\n const outgoing = dagOutgoing.get(fromComponent);\n if (outgoing?.has(toComponent) === true) {\n continue;\n }\n\n outgoing?.add(toComponent);\n inDegree.set(toComponent, (inDegree.get(toComponent) ?? 0) + 1);\n }\n\n const queue: number[] = [];\n const depthByComponent = new Map<number, number>();\n\n for (let i = 0; i < components.length; i += 1) {\n if ((inDegree.get(i) ?? 0) === 0) {\n queue.push(i);\n depthByComponent.set(i, 0);\n }\n }\n\n let cursor = 0;\n while (cursor < queue.length) {\n const componentId = queue[cursor];\n cursor += 1;\n\n if (componentId === undefined) {\n continue;\n }\n\n const currentDepth = depthByComponent.get(componentId) ?? 0;\n const outgoing = dagOutgoing.get(componentId) ?? new Set<number>();\n\n for (const nextComponent of outgoing) {\n const nextDepth = depthByComponent.get(nextComponent) ?? 0;\n if (currentDepth + 1 > nextDepth) {\n depthByComponent.set(nextComponent, currentDepth + 1);\n }\n\n const remainingIncoming = (inDegree.get(nextComponent) ?? 0) - 1;\n inDegree.set(nextComponent, remainingIncoming);\n if (remainingIncoming === 0) {\n queue.push(nextComponent);\n }\n }\n }\n\n const depthByNodeId = new Map<string, number>();\n let graphDepth = 0;\n\n components.forEach((component, componentId) => {\n const componentDepth = depthByComponent.get(componentId) ?? 0;\n if (componentDepth > graphDepth) {\n graphDepth = componentDepth;\n }\n\n for (const nodeId of component) {\n depthByNodeId.set(nodeId, componentDepth);\n }\n });\n\n cycles.sort((a, b) => {\n const firstA = a.nodes[0] ?? \"\";\n const firstB = b.nodes[0] ?? \"\";\n return firstA.localeCompare(firstB);\n });\n\n return {\n depthByNodeId,\n graphDepth,\n cycles,\n };\n};\n\nexport const createGraphAnalysisSummary = (\n targetPath: string,\n graph: GraphData,\n): GraphAnalysisSummary => {\n const fanInById = new Map<string, number>();\n const fanOutById = new Map<string, number>();\n\n for (const node of graph.nodes) {\n fanInById.set(node.id, 0);\n fanOutById.set(node.id, graph.adjacencyById.get(node.id)?.length ?? 0);\n }\n\n for (const edge of graph.edges) {\n fanInById.set(edge.to, (fanInById.get(edge.to) ?? 0) + 1);\n }\n\n const { cycles, depthByNodeId, graphDepth } = computeCyclesAndDepth(graph);\n\n let maxFanIn = 0;\n let maxFanOut = 0;\n\n const files: FileDependency[] = graph.nodes.map((node) => {\n const fanIn = fanInById.get(node.id) ?? 0;\n const fanOut = fanOutById.get(node.id) ?? 0;\n\n if (fanIn > maxFanIn) {\n maxFanIn = fanIn;\n }\n\n if (fanOut > maxFanOut) {\n maxFanOut = fanOut;\n }\n\n return {\n id: node.id,\n relativePath: node.relativePath,\n directDependencies: graph.adjacencyById.get(node.id) ?? [],\n fanIn,\n fanOut,\n depth: depthByNodeId.get(node.id) ?? 0,\n };\n });\n\n const metrics: GraphMetrics = {\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n cycleCount: cycles.length,\n graphDepth,\n maxFanIn,\n maxFanOut,\n };\n\n return {\n targetPath,\n nodes: graph.nodes,\n edges: graph.edges,\n cycles,\n files,\n metrics,\n };\n};\n","import { extname, isAbsolute, relative, resolve } from \"node:path\";\nimport * as ts from \"typescript\";\nimport type { EdgeRecord, NodeRecord } from \"../domain/graph-model.js\";\n\ntype ParsedProject = {\n nodes: readonly NodeRecord[];\n edges: readonly EdgeRecord[];\n};\n\nconst SOURCE_EXTENSIONS = new Set([\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".jsx\", \".mjs\", \".cjs\"]);\n\nconst normalizePath = (pathValue: string): string => pathValue.replaceAll(\"\\\\\", \"/\");\n\nconst isProjectSourceFile = (filePath: string, projectRoot: string): boolean => {\n const extension = extname(filePath);\n if (!SOURCE_EXTENSIONS.has(extension)) {\n return false;\n }\n\n const relativePath = relative(projectRoot, filePath);\n if (relativePath.startsWith(\"..\")) {\n return false;\n }\n\n return !relativePath.includes(\"node_modules\");\n};\n\nconst findProjectFiles = (projectRoot: string): readonly string[] => {\n const files = ts.sys.readDirectory(projectRoot, [...SOURCE_EXTENSIONS], undefined, undefined);\n return files.map((filePath) => resolve(filePath));\n};\n\nconst parseTsConfig = (projectRoot: string): { fileNames: readonly string[]; options: ts.CompilerOptions } => {\n const configPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, \"tsconfig.json\");\n if (configPath === undefined) {\n return {\n fileNames: findProjectFiles(projectRoot),\n options: {\n allowJs: true,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n },\n };\n }\n\n const parsedCommandLine = ts.getParsedCommandLineOfConfigFile(\n configPath,\n {},\n {\n ...ts.sys,\n onUnRecoverableConfigFileDiagnostic: () => {\n throw new Error(`Failed to parse TypeScript configuration at ${configPath}`);\n },\n },\n );\n\n if (parsedCommandLine === undefined) {\n throw new Error(`Failed to parse TypeScript configuration at ${configPath}`);\n }\n\n const fileNames = parsedCommandLine.fileNames.map((filePath) => resolve(filePath));\n if (fileNames.length === 0) {\n return {\n fileNames: findProjectFiles(projectRoot),\n options: parsedCommandLine.options,\n };\n }\n\n return {\n fileNames,\n options: parsedCommandLine.options,\n };\n};\n\nconst getSpecifierFromExpression = (expression: ts.Expression): string | undefined => {\n if (ts.isStringLiteral(expression)) {\n return expression.text;\n }\n\n if (ts.isNoSubstitutionTemplateLiteral(expression)) {\n return expression.text;\n }\n\n return undefined;\n};\n\nconst hasRuntimeImport = (importDeclaration: ts.ImportDeclaration): boolean => {\n const importClause = importDeclaration.importClause;\n if (importClause === undefined) {\n return true;\n }\n\n if (importClause.isTypeOnly) {\n return false;\n }\n\n if (importClause.name !== undefined) {\n return true;\n }\n\n const namedBindings = importClause.namedBindings;\n if (namedBindings === undefined) {\n return false;\n }\n\n if (ts.isNamespaceImport(namedBindings)) {\n return true;\n }\n\n if (namedBindings.elements.length === 0) {\n return true;\n }\n\n return namedBindings.elements.some((element) => !element.isTypeOnly);\n};\n\nconst extractModuleSpecifiers = (sourceFile: ts.SourceFile): readonly string[] => {\n const specifiers = new Set<string>();\n\n const visit = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) {\n if (hasRuntimeImport(node) && node.moduleSpecifier !== undefined) {\n const specifier = getSpecifierFromExpression(node.moduleSpecifier);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n return;\n }\n\n if (ts.isExportDeclaration(node)) {\n if (!node.isTypeOnly && node.moduleSpecifier !== undefined) {\n const specifier = getSpecifierFromExpression(node.moduleSpecifier);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n return;\n }\n\n if (ts.isCallExpression(node)) {\n if (node.expression.kind === ts.SyntaxKind.ImportKeyword && node.arguments.length > 0) {\n const firstArgument = node.arguments[0];\n if (firstArgument !== undefined) {\n const specifier = getSpecifierFromExpression(firstArgument);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n }\n\n if (ts.isIdentifier(node.expression) && node.expression.text === \"require\" && node.arguments.length > 0) {\n const firstArgument = node.arguments[0];\n if (firstArgument !== undefined) {\n const specifier = getSpecifierFromExpression(firstArgument);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return [...specifiers];\n};\n\nexport const parseTypescriptProject = (projectPath: string): ParsedProject => {\n const projectRoot = isAbsolute(projectPath) ? projectPath : resolve(projectPath);\n const { fileNames, options } = parseTsConfig(projectRoot);\n\n const sourceFilePaths = fileNames\n .filter((filePath) => isProjectSourceFile(filePath, projectRoot))\n .map((filePath) => normalizePath(resolve(filePath)));\n\n const uniqueSourceFilePaths = [...new Set(sourceFilePaths)].sort((a, b) => a.localeCompare(b));\n const sourceFilePathSet = new Set(uniqueSourceFilePaths);\n\n const program = ts.createProgram({\n rootNames: uniqueSourceFilePaths,\n options,\n });\n\n const nodeByAbsolutePath = new Map<string, NodeRecord>();\n for (const sourcePath of uniqueSourceFilePaths) {\n const relativePath = normalizePath(relative(projectRoot, sourcePath));\n const nodeId = relativePath;\n nodeByAbsolutePath.set(sourcePath, {\n id: nodeId,\n absolutePath: sourcePath,\n relativePath,\n });\n }\n\n const resolverCache = new Map<string, string | undefined>();\n const edges: EdgeRecord[] = [];\n\n for (const sourcePath of uniqueSourceFilePaths) {\n const sourceFile = program.getSourceFile(sourcePath);\n if (sourceFile === undefined) {\n continue;\n }\n\n const fromNode = nodeByAbsolutePath.get(sourcePath);\n if (fromNode === undefined) {\n continue;\n }\n\n const moduleSpecifiers = extractModuleSpecifiers(sourceFile);\n for (const specifier of moduleSpecifiers) {\n const cacheKey = `${sourcePath}\\u0000${specifier}`;\n let resolvedPath = resolverCache.get(cacheKey);\n\n if (resolvedPath === undefined && !resolverCache.has(cacheKey)) {\n const resolved = ts.resolveModuleName(specifier, sourcePath, options, ts.sys).resolvedModule;\n if (resolved !== undefined) {\n resolvedPath = normalizePath(resolve(resolved.resolvedFileName));\n }\n resolverCache.set(cacheKey, resolvedPath);\n }\n\n if (resolvedPath === undefined || !sourceFilePathSet.has(resolvedPath)) {\n continue;\n }\n\n const toNode = nodeByAbsolutePath.get(resolvedPath);\n if (toNode === undefined) {\n continue;\n }\n\n edges.push({ from: fromNode.id, to: toNode.id });\n }\n }\n\n return {\n nodes: [...nodeByAbsolutePath.values()],\n edges,\n };\n};\n","import type { GraphAnalysisSummary } from \"@codesentinel/core\";\nimport { createGraphData } from \"../domain/graph-model.js\";\nimport { createGraphAnalysisSummary } from \"../domain/graph-metrics.js\";\nimport { parseTypescriptProject } from \"../infrastructure/typescript-project.js\";\n\nexport type BuildProjectGraphSummaryInput = {\n projectPath: string;\n};\n\nexport const buildProjectGraphSummary = (\n input: BuildProjectGraphSummaryInput,\n): GraphAnalysisSummary => {\n const parsedProject = parseTypescriptProject(input.projectPath);\n const graphData = createGraphData(parsedProject.nodes, parsedProject.edges);\n return createGraphAnalysisSummary(input.projectPath, graphData);\n};\n","import type {\n CentralDependency,\n DependencyExposureRecord,\n DependencyRiskSignal,\n ExternalAnalysisSummary,\n} from \"@codesentinel/core\";\nimport type {\n DependencyMetadata,\n ExternalAnalysisConfig,\n LockfileExtraction,\n LockedDependencyNode,\n} from \"./types.js\";\n\nconst round4 = (value: number): number => Number(value.toFixed(4));\n\ntype NormalizedNode = {\n key: string;\n name: string;\n version: string;\n dependencies: readonly string[];\n};\n\nconst normalizeNodes = (nodes: readonly LockedDependencyNode[]): readonly NormalizedNode[] => {\n const byName = new Map<string, LockedDependencyNode[]>();\n\n for (const node of nodes) {\n const bucket = byName.get(node.name) ?? [];\n bucket.push(node);\n byName.set(node.name, bucket);\n }\n\n const normalized: NormalizedNode[] = [];\n\n for (const [name, candidates] of byName.entries()) {\n if (candidates.length === 0) {\n continue;\n }\n\n candidates.sort((a, b) => b.version.localeCompare(a.version));\n const selected = candidates[0];\n if (selected === undefined) {\n continue;\n }\n\n const deps = selected.dependencies\n .map((dep) => {\n const at = dep.lastIndexOf(\"@\");\n return at <= 0 ? dep : dep.slice(0, at);\n })\n .filter((depName) => depName.length > 0)\n .sort((a, b) => a.localeCompare(b));\n\n normalized.push({\n key: `${name}@${selected.version}`,\n name,\n version: selected.version,\n dependencies: deps,\n });\n }\n\n return normalized.sort((a, b) => a.name.localeCompare(b.name));\n};\n\nconst computeDepths = (\n nodeByName: ReadonlyMap<string, NormalizedNode>,\n directNames: ReadonlySet<string>,\n): { depthByName: ReadonlyMap<string, number>; maxDepth: number } => {\n const visiting = new Set<string>();\n const depthByName = new Map<string, number>();\n\n const compute = (name: string): number => {\n const known = depthByName.get(name);\n if (known !== undefined) {\n return known;\n }\n\n if (visiting.has(name)) {\n return 0;\n }\n\n visiting.add(name);\n\n const node = nodeByName.get(name);\n if (node === undefined) {\n visiting.delete(name);\n depthByName.set(name, 0);\n return 0;\n }\n\n let maxChildDepth = 0;\n for (const dependencyName of node.dependencies) {\n const childDepth = compute(dependencyName);\n if (childDepth > maxChildDepth) {\n maxChildDepth = childDepth;\n }\n }\n\n visiting.delete(name);\n const ownDepth = directNames.has(name) ? 0 : maxChildDepth + 1;\n depthByName.set(name, ownDepth);\n return ownDepth;\n };\n\n for (const name of nodeByName.keys()) {\n compute(name);\n }\n\n let maxDepth = 0;\n for (const depth of depthByName.values()) {\n if (depth > maxDepth) {\n maxDepth = depth;\n }\n }\n\n return { depthByName, maxDepth };\n};\n\nconst rankCentrality = (\n nodes: readonly NormalizedNode[],\n dependentsByName: ReadonlyMap<string, number>,\n directNames: ReadonlySet<string>,\n topN: number,\n): readonly CentralDependency[] =>\n [...nodes]\n .map((node) => ({\n name: node.name,\n dependents: dependentsByName.get(node.name) ?? 0,\n fanOut: node.dependencies.length,\n direct: directNames.has(node.name),\n }))\n .sort(\n (a, b) =>\n b.dependents - a.dependents ||\n b.fanOut - a.fanOut ||\n a.name.localeCompare(b.name),\n )\n .slice(0, topN);\n\nconst canPropagateSignal = (signal: DependencyRiskSignal): boolean =>\n signal === \"abandoned\" ||\n signal === \"high_centrality\" ||\n signal === \"deep_chain\" ||\n signal === \"high_fanout\";\n\nconst collectTransitiveDependencies = (\n rootName: string,\n nodeByName: ReadonlyMap<string, NormalizedNode>,\n): readonly string[] => {\n const seen = new Set<string>();\n const stack = [...(nodeByName.get(rootName)?.dependencies ?? [])];\n\n while (stack.length > 0) {\n const current = stack.pop();\n if (current === undefined || seen.has(current) || current === rootName) {\n continue;\n }\n\n seen.add(current);\n const currentNode = nodeByName.get(current);\n if (currentNode === undefined) {\n continue;\n }\n\n for (const next of currentNode.dependencies) {\n if (!seen.has(next)) {\n stack.push(next);\n }\n }\n }\n\n return [...seen].sort((a, b) => a.localeCompare(b));\n};\n\nexport const buildExternalAnalysisSummary = (\n targetPath: string,\n extraction: LockfileExtraction,\n metadataByKey: ReadonlyMap<string, DependencyMetadata | null>,\n config: ExternalAnalysisConfig,\n): ExternalAnalysisSummary => {\n const nodes = normalizeNodes(extraction.nodes);\n const directNames = new Set(extraction.directDependencies.map((dep) => dep.name));\n const directSpecByName = new Map(extraction.directDependencies.map((dep) => [dep.name, dep.requestedRange]));\n\n const nodeByName = new Map(nodes.map((node) => [node.name, node]));\n const dependentsByName = new Map<string, number>();\n\n for (const node of nodes) {\n dependentsByName.set(node.name, dependentsByName.get(node.name) ?? 0);\n }\n\n for (const node of nodes) {\n for (const dependencyName of node.dependencies) {\n if (!nodeByName.has(dependencyName)) {\n continue;\n }\n\n dependentsByName.set(dependencyName, (dependentsByName.get(dependencyName) ?? 0) + 1);\n }\n }\n\n const { depthByName, maxDepth } = computeDepths(nodeByName, directNames);\n const centralityRanking = rankCentrality(nodes, dependentsByName, directNames, config.centralityTopN);\n\n const topCentralNames = new Set(\n centralityRanking\n .slice(0, Math.max(1, Math.ceil(centralityRanking.length * 0.25)))\n .map((entry) => entry.name),\n );\n\n const allDependencies: DependencyExposureRecord[] = [];\n let metadataAvailableCount = 0;\n\n for (const node of nodes) {\n const metadata = metadataByKey.get(node.key) ?? null;\n if (metadata !== null) {\n metadataAvailableCount += 1;\n }\n\n const dependencyDepth = depthByName.get(node.name) ?? 0;\n const dependents = dependentsByName.get(node.name) ?? 0;\n\n const riskSignals: DependencyRiskSignal[] = [];\n\n if ((metadata?.maintainerCount ?? 0) === 1) {\n riskSignals.push(\"single_maintainer\");\n }\n\n if ((metadata?.daysSinceLastRelease ?? 0) >= config.abandonedDaysThreshold) {\n riskSignals.push(\"abandoned\");\n }\n\n if (topCentralNames.has(node.name) && dependents > 0) {\n riskSignals.push(\"high_centrality\");\n }\n\n if (dependencyDepth >= config.deepChainThreshold) {\n riskSignals.push(\"deep_chain\");\n }\n\n if (node.dependencies.length >= config.fanOutHighThreshold) {\n riskSignals.push(\"high_fanout\");\n }\n\n if (metadata === null) {\n riskSignals.push(\"metadata_unavailable\");\n }\n\n allDependencies.push({\n name: node.name,\n direct: directNames.has(node.name),\n requestedRange: directSpecByName.get(node.name) ?? null,\n resolvedVersion: node.version,\n transitiveDependencies: [],\n dependencyDepth,\n fanOut: node.dependencies.length,\n dependents,\n maintainerCount: metadata?.maintainerCount ?? null,\n releaseFrequencyDays: metadata?.releaseFrequencyDays ?? null,\n daysSinceLastRelease: metadata?.daysSinceLastRelease ?? null,\n repositoryActivity30d: metadata?.repositoryActivity30d ?? null,\n busFactor: metadata?.busFactor ?? null,\n ownRiskSignals: [...riskSignals].sort((a, b) => a.localeCompare(b)),\n inheritedRiskSignals: [],\n riskSignals,\n });\n }\n\n allDependencies.sort((a, b) => a.name.localeCompare(b.name));\n\n const allByName = new Map(allDependencies.map((dep) => [dep.name, dep]));\n\n const dependencies: DependencyExposureRecord[] = allDependencies\n .filter((dep) => dep.direct)\n .map((dep) => {\n const transitiveDependencies = collectTransitiveDependencies(dep.name, nodeByName);\n const inheritedSignals = new Set<DependencyRiskSignal>();\n const allSignals = new Set(dep.ownRiskSignals);\n\n for (const transitiveName of transitiveDependencies) {\n const transitive = allByName.get(transitiveName);\n if (transitive === undefined) {\n continue;\n }\n\n for (const signal of transitive.riskSignals) {\n if (canPropagateSignal(signal)) {\n inheritedSignals.add(signal);\n allSignals.add(signal);\n }\n }\n }\n\n return {\n ...dep,\n transitiveDependencies,\n inheritedRiskSignals: [...inheritedSignals].sort((a, b) => a.localeCompare(b)),\n riskSignals: [...allSignals].sort((a, b) => a.localeCompare(b)),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const highRiskDependencies = dependencies\n .filter((dep) => dep.riskSignals.length > 1)\n .sort((a, b) => b.riskSignals.length - a.riskSignals.length || a.name.localeCompare(b.name))\n .slice(0, config.maxHighRiskDependencies)\n .map((dep) => dep.name);\n\n const singleMaintainerDependencies = dependencies\n .filter((dep) => dep.ownRiskSignals.includes(\"single_maintainer\"))\n .map((dep) => dep.name)\n .sort((a, b) => a.localeCompare(b));\n\n const abandonedDependencies = dependencies\n .filter((dep) => dep.ownRiskSignals.includes(\"abandoned\"))\n .map((dep) => dep.name)\n .sort((a, b) => a.localeCompare(b));\n\n return {\n targetPath,\n available: true,\n metrics: {\n totalDependencies: allDependencies.length,\n directDependencies: dependencies.length,\n transitiveDependencies: allDependencies.length - dependencies.length,\n dependencyDepth: maxDepth,\n lockfileKind: extraction.kind,\n metadataCoverage: allDependencies.length === 0 ? 0 : round4(metadataAvailableCount / allDependencies.length),\n },\n dependencies,\n highRiskDependencies,\n singleMaintainerDependencies,\n abandonedDependencies,\n centralityRanking,\n };\n};\n","export type LockfileKind = \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\";\n\nexport type DirectDependencySpec = {\n name: string;\n requestedRange: string;\n};\n\nexport type LockedDependencyNode = {\n name: string;\n version: string;\n dependencies: readonly string[];\n};\n\nexport type LockfileExtraction = {\n kind: LockfileKind;\n directDependencies: readonly DirectDependencySpec[];\n nodes: readonly LockedDependencyNode[];\n};\n\nexport type DependencyMetadata = {\n name: string;\n version: string;\n maintainerCount: number | null;\n releaseFrequencyDays: number | null;\n daysSinceLastRelease: number | null;\n repositoryActivity30d: number | null;\n busFactor: number | null;\n};\n\nexport interface DependencyMetadataProvider {\n getMetadata(name: string, version: string): Promise<DependencyMetadata | null>;\n}\n\nexport type ExternalAnalysisConfig = {\n abandonedDaysThreshold: number;\n deepChainThreshold: number;\n fanOutHighThreshold: number;\n centralityTopN: number;\n maxHighRiskDependencies: number;\n metadataRequestConcurrency: number;\n};\n\nexport const DEFAULT_EXTERNAL_ANALYSIS_CONFIG: ExternalAnalysisConfig = {\n abandonedDaysThreshold: 540,\n deepChainThreshold: 6,\n fanOutHighThreshold: 25,\n centralityTopN: 20,\n maxHighRiskDependencies: 100,\n metadataRequestConcurrency: 8,\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type RepositoryFiles = {\n packageJsonPath: string;\n packageJsonRaw: string;\n lockfilePath: string;\n lockfileRaw: string;\n};\n\nconst LOCKFILE_CANDIDATES: readonly { fileName: string; kind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\" }[] = [\n { fileName: \"pnpm-lock.yaml\", kind: \"pnpm\" },\n { fileName: \"package-lock.json\", kind: \"npm\" },\n { fileName: \"npm-shrinkwrap.json\", kind: \"npm-shrinkwrap\" },\n { fileName: \"yarn.lock\", kind: \"yarn\" },\n { fileName: \"bun.lock\", kind: \"bun\" },\n { fileName: \"bun.lockb\", kind: \"bun\" },\n];\n\nexport type LockfileSelection = {\n path: string;\n kind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\";\n raw: string;\n};\n\nexport const loadPackageJson = (repositoryPath: string): { path: string; raw: string } | null => {\n const packageJsonPath = join(repositoryPath, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return null;\n }\n\n return {\n path: packageJsonPath,\n raw: readFileSync(packageJsonPath, \"utf8\"),\n };\n};\n\nexport const selectLockfile = (repositoryPath: string): LockfileSelection | null => {\n for (const candidate of LOCKFILE_CANDIDATES) {\n const absolutePath = join(repositoryPath, candidate.fileName);\n if (!existsSync(absolutePath)) {\n continue;\n }\n\n return {\n path: absolutePath,\n kind: candidate.kind,\n raw: readFileSync(absolutePath, \"utf8\"),\n };\n }\n\n return null;\n};\n","import type { DirectDependencySpec } from \"../domain/types.js\";\n\ntype ParsedPackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\nexport const parsePackageJson = (raw: string): readonly DirectDependencySpec[] => {\n const parsed = JSON.parse(raw) as ParsedPackageJson;\n const merged = new Map<string, string>();\n\n for (const block of [\n parsed.dependencies,\n parsed.devDependencies,\n parsed.optionalDependencies,\n parsed.peerDependencies,\n ]) {\n if (block === undefined) {\n continue;\n }\n\n for (const [name, versionRange] of Object.entries(block)) {\n merged.set(name, versionRange);\n }\n }\n\n return [...merged.entries()]\n .map(([name, requestedRange]) => ({ name, requestedRange }))\n .sort((a, b) => a.name.localeCompare(b.name));\n};\n","import type { DirectDependencySpec, LockfileExtraction, LockedDependencyNode } from \"../domain/types.js\";\n\ntype PackageLockNode = {\n version?: string;\n dependencies?: Record<string, string>;\n};\n\ntype PackageLockShape = {\n lockfileVersion?: number;\n packages?: Record<string, PackageLockNode>;\n dependencies?: Record<string, { version?: string; dependencies?: Record<string, unknown> }>;\n};\n\nexport const parsePackageLock = (raw: string, directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n const parsed = JSON.parse(raw) as PackageLockShape;\n const nodes: LockedDependencyNode[] = [];\n\n if (parsed.packages !== undefined) {\n for (const [packagePath, packageData] of Object.entries(parsed.packages)) {\n if (packagePath.length === 0 || packageData.version === undefined) {\n continue;\n }\n\n const segments = packagePath.split(\"node_modules/\");\n const name = segments[segments.length - 1] ?? \"\";\n if (name.length === 0) {\n continue;\n }\n\n const dependencies = Object.entries(packageData.dependencies ?? {})\n .map(([depName, depRange]) => `${depName}@${String(depRange)}`)\n .sort((a, b) => a.localeCompare(b));\n\n nodes.push({\n name,\n version: packageData.version,\n dependencies,\n });\n }\n } else if (parsed.dependencies !== undefined) {\n for (const [name, dep] of Object.entries(parsed.dependencies)) {\n if (dep.version === undefined) {\n continue;\n }\n\n const dependencies = Object.entries(dep.dependencies ?? {})\n .map(([depName, depVersion]) => `${depName}@${String(depVersion)}`)\n .sort((a, b) => a.localeCompare(b));\n\n nodes.push({\n name,\n version: dep.version,\n dependencies,\n });\n }\n }\n\n nodes.sort((a, b) => a.name.localeCompare(b.name) || a.version.localeCompare(b.version));\n\n return {\n kind: \"npm\",\n directDependencies: directSpecs,\n nodes,\n };\n};\n","import type { DirectDependencySpec, LockfileExtraction, LockedDependencyNode } from \"../domain/types.js\";\n\ntype ParserState = \"root\" | \"importers\" | \"packages\" | \"packageDeps\";\n\nconst sanitizeValue = (value: string): string => value.replace(/^['\"]|['\"]$/g, \"\").trim();\n\nconst parsePackageKey = (rawKey: string): { name: string; version: string } | null => {\n const key = sanitizeValue(rawKey.replace(/:$/, \"\"));\n const withoutSlash = key.startsWith(\"/\") ? key.slice(1) : key;\n\n const lastAt = withoutSlash.lastIndexOf(\"@\");\n if (lastAt <= 0) {\n return null;\n }\n\n const name = withoutSlash.slice(0, lastAt);\n const versionWithPeers = withoutSlash.slice(lastAt + 1);\n const version = versionWithPeers.split(\"(\")[0] ?? versionWithPeers;\n\n if (name.length === 0 || version.length === 0) {\n return null;\n }\n\n return { name, version };\n};\n\nexport const parsePnpmLockfile = (raw: string, directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n const lines = raw.split(\"\\n\");\n let state: ParserState = \"root\";\n let currentPackage: string | null = null;\n let currentDependencyName: string | null = null;\n const dependenciesByNode = new Map<string, Set<string>>();\n\n for (const line of lines) {\n if (line.trim().length === 0 || line.trimStart().startsWith(\"#\")) {\n continue;\n }\n\n if (line.startsWith(\"importers:\")) {\n state = \"importers\";\n continue;\n }\n\n if (line.startsWith(\"packages:\")) {\n state = \"packages\";\n continue;\n }\n\n if (state === \"packages\" || state === \"packageDeps\") {\n const packageMatch = line.match(/^\\s{2}([^\\s].+):\\s*$/);\n if (packageMatch !== null) {\n const parsedKey = parsePackageKey(packageMatch[1] ?? \"\");\n if (parsedKey !== null) {\n currentPackage = `${parsedKey.name}@${parsedKey.version}`;\n dependenciesByNode.set(currentPackage, new Set());\n state = \"packageDeps\";\n currentDependencyName = null;\n }\n continue;\n }\n }\n\n if (state === \"packageDeps\" && currentPackage !== null) {\n const depLine = line.match(/^\\s{6}([^:\\s]+):\\s*(.+)$/);\n if (depLine !== null) {\n const depName = sanitizeValue(depLine[1] ?? \"\");\n const depRef = sanitizeValue(depLine[2] ?? \"\");\n const depVersion = depRef.split(\"(\")[0] ?? depRef;\n\n if (depName.length > 0 && depVersion.length > 0) {\n dependenciesByNode.get(currentPackage)?.add(`${depName}@${depVersion}`);\n }\n currentDependencyName = null;\n continue;\n }\n\n const depBlockLine = line.match(/^\\s{6}([^:\\s]+):\\s*$/);\n if (depBlockLine !== null) {\n currentDependencyName = sanitizeValue(depBlockLine[1] ?? \"\");\n continue;\n }\n\n const depVersionLine = line.match(/^\\s{8}version:\\s*(.+)$/);\n if (depVersionLine !== null && currentDependencyName !== null) {\n const depRef = sanitizeValue(depVersionLine[1] ?? \"\");\n const depVersion = depRef.split(\"(\")[0] ?? depRef;\n if (depVersion.length > 0) {\n dependenciesByNode.get(currentPackage)?.add(`${currentDependencyName}@${depVersion}`);\n }\n currentDependencyName = null;\n continue;\n }\n\n if (line.match(/^\\s{4}(dependencies|optionalDependencies):\\s*$/) !== null) {\n continue;\n }\n }\n }\n\n const nodes: LockedDependencyNode[] = [...dependenciesByNode.entries()]\n .map(([nodeId, deps]) => {\n const at = nodeId.lastIndexOf(\"@\");\n return {\n name: nodeId.slice(0, at),\n version: nodeId.slice(at + 1),\n dependencies: [...deps].sort((a, b) => a.localeCompare(b)),\n };\n })\n .sort((a, b) =>\n a.name.localeCompare(b.name) || a.version.localeCompare(b.version),\n );\n\n return {\n kind: \"pnpm\",\n directDependencies: directSpecs,\n nodes,\n };\n};\n","import type { DirectDependencySpec, LockfileExtraction, LockedDependencyNode } from \"../domain/types.js\";\n\nconst stripQuotes = (value: string): string => value.replace(/^['\"]|['\"]$/g, \"\");\n\nconst parseVersionSelector = (selector: string): string | null => {\n const npmIndex = selector.lastIndexOf(\"@npm:\");\n if (npmIndex >= 0) {\n return selector.slice(npmIndex + 5);\n }\n\n const lastAt = selector.lastIndexOf(\"@\");\n if (lastAt <= 0) {\n return null;\n }\n\n return selector.slice(lastAt + 1);\n};\n\nexport const parseYarnLock = (raw: string, directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n const lines = raw.split(\"\\n\");\n const nodes: LockedDependencyNode[] = [];\n\n let selectors: string[] = [];\n let version: string | null = null;\n let readingDependencies = false;\n let dependencies: string[] = [];\n\n const flushEntry = (): void => {\n if (selectors.length === 0 || version === null) {\n selectors = [];\n version = null;\n dependencies = [];\n readingDependencies = false;\n return;\n }\n\n for (const selector of selectors) {\n const parsedVersion = parseVersionSelector(selector);\n const at = selector.lastIndexOf(\"@\");\n const name = at <= 0 ? selector : selector.slice(0, at);\n if (name.length === 0) {\n continue;\n }\n\n nodes.push({\n name,\n version,\n dependencies: [...dependencies].sort((a, b) => a.localeCompare(b)),\n });\n\n if (parsedVersion !== null) {\n nodes.push({\n name,\n version: parsedVersion,\n dependencies: [...dependencies].sort((a, b) => a.localeCompare(b)),\n });\n }\n }\n\n selectors = [];\n version = null;\n dependencies = [];\n readingDependencies = false;\n };\n\n for (const line of lines) {\n if (line.trim().length === 0) {\n continue;\n }\n\n if (!line.startsWith(\" \") && line.endsWith(\":\")) {\n flushEntry();\n const keyText = line.slice(0, -1);\n selectors = keyText\n .split(\",\")\n .map((part) => stripQuotes(part.trim()))\n .filter((part) => part.length > 0);\n continue;\n }\n\n if (line.match(/^\\s{2}version\\s+/) !== null) {\n const value = line.replace(/^\\s{2}version\\s+/, \"\").trim();\n version = stripQuotes(value);\n readingDependencies = false;\n continue;\n }\n\n if (line.match(/^\\s{2}dependencies:\\s*$/) !== null) {\n readingDependencies = true;\n continue;\n }\n\n if (readingDependencies && line.match(/^\\s{4}[^\\s].+$/) !== null) {\n const depLine = line.trim();\n const firstSpace = depLine.indexOf(\" \");\n if (firstSpace <= 0) {\n continue;\n }\n\n const depName = stripQuotes(depLine.slice(0, firstSpace));\n const depRef = stripQuotes(depLine.slice(firstSpace + 1).trim());\n const depVersion = parseVersionSelector(depRef) ?? depRef;\n dependencies.push(`${depName}@${depVersion}`);\n continue;\n }\n\n readingDependencies = false;\n }\n\n flushEntry();\n\n const deduped = new Map<string, LockedDependencyNode>();\n for (const node of nodes) {\n const key = `${node.name}@${node.version}`;\n if (!deduped.has(key)) {\n deduped.set(key, node);\n }\n }\n\n return {\n kind: \"yarn\",\n directDependencies: directSpecs,\n nodes: [...deduped.values()].sort((a, b) => a.name.localeCompare(b.name) || a.version.localeCompare(b.version)),\n };\n};\n","import type { DirectDependencySpec, LockfileExtraction } from \"../domain/types.js\";\n\nexport const parseBunLock = (_raw: string, _directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n throw new Error(\"unsupported_lockfile_format\");\n};\n","import type { ExternalAnalysisSummary } from \"@codesentinel/core\";\nimport { buildExternalAnalysisSummary } from \"../domain/external-analysis.js\";\nimport {\n DEFAULT_EXTERNAL_ANALYSIS_CONFIG,\n type DependencyMetadataProvider,\n type ExternalAnalysisConfig,\n type LockfileExtraction,\n} from \"../domain/types.js\";\nimport { loadPackageJson, selectLockfile } from \"../infrastructure/fs-loader.js\";\nimport { parsePackageJson } from \"../parsing/package-json-loader.js\";\nimport { parsePackageLock } from \"../parsing/package-lock-parser.js\";\nimport { parsePnpmLockfile } from \"../parsing/pnpm-lock-parser.js\";\nimport { parseYarnLock } from \"../parsing/yarn-lock-parser.js\";\nimport { parseBunLock } from \"../parsing/bun-lock-parser.js\";\n\nexport type AnalyzeDependencyExposureInput = {\n repositoryPath: string;\n config?: Partial<ExternalAnalysisConfig>;\n};\n\nconst withDefaults = (overrides: Partial<ExternalAnalysisConfig> | undefined): ExternalAnalysisConfig => ({\n ...DEFAULT_EXTERNAL_ANALYSIS_CONFIG,\n ...overrides,\n});\n\nconst parseExtraction = (\n lockfileKind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\",\n lockfileRaw: string,\n directSpecs: ReturnType<typeof parsePackageJson>,\n): LockfileExtraction => {\n switch (lockfileKind) {\n case \"pnpm\":\n return parsePnpmLockfile(lockfileRaw, directSpecs);\n case \"npm\":\n case \"npm-shrinkwrap\":\n return {\n ...parsePackageLock(lockfileRaw, directSpecs),\n kind: lockfileKind,\n };\n case \"yarn\":\n return parseYarnLock(lockfileRaw, directSpecs);\n case \"bun\":\n return parseBunLock(lockfileRaw, directSpecs);\n default:\n throw new Error(\"unsupported_lockfile_format\");\n }\n};\n\nconst mapWithConcurrency = async <T, R>(\n values: readonly T[],\n limit: number,\n handler: (value: T) => Promise<R>,\n): Promise<readonly R[]> => {\n const effectiveLimit = Math.max(1, limit);\n const results: R[] = new Array(values.length);\n let index = 0;\n\n const workers = Array.from({ length: Math.min(effectiveLimit, values.length) }, async () => {\n for (;;) {\n const current = index;\n index += 1;\n if (current >= values.length) {\n return;\n }\n\n const value = values[current];\n if (value === undefined) {\n return;\n }\n\n results[current] = await handler(value);\n }\n });\n\n await Promise.all(workers);\n return results;\n};\n\nexport const analyzeDependencyExposure = async (\n input: AnalyzeDependencyExposureInput,\n metadataProvider: DependencyMetadataProvider,\n): Promise<ExternalAnalysisSummary> => {\n const packageJson = loadPackageJson(input.repositoryPath);\n if (packageJson === null) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"package_json_not_found\",\n };\n }\n\n const lockfile = selectLockfile(input.repositoryPath);\n if (lockfile === null) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"lockfile_not_found\",\n };\n }\n\n try {\n const directSpecs = parsePackageJson(packageJson.raw);\n const extraction = parseExtraction(lockfile.kind, lockfile.raw, directSpecs);\n const config = withDefaults(input.config);\n\n const metadataEntries = await mapWithConcurrency(\n extraction.nodes,\n config.metadataRequestConcurrency,\n async (node) => ({\n key: `${node.name}@${node.version}`,\n metadata: await metadataProvider.getMetadata(node.name, node.version),\n }),\n );\n\n const metadataByKey = new Map<string, Awaited<(typeof metadataEntries)[number]>[\"metadata\"]>();\n for (const entry of metadataEntries) {\n metadataByKey.set(entry.key, entry.metadata);\n }\n\n return buildExternalAnalysisSummary(input.repositoryPath, extraction, metadataByKey, config);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"unknown\";\n if (message.includes(\"unsupported_lockfile_format\")) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"unsupported_lockfile_format\",\n };\n }\n\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"invalid_lockfile\",\n };\n }\n};\n","import type { DependencyMetadata, DependencyMetadataProvider } from \"../domain/types.js\";\n\ntype NpmPackagePayload = {\n time?: Record<string, string>;\n maintainers?: Array<{ name?: string; email?: string }>;\n};\n\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\nconst round4 = (value: number): number => Number(value.toFixed(4));\n\nconst parseDate = (iso: string | undefined): number | null => {\n if (iso === undefined) {\n return null;\n }\n\n const value = Date.parse(iso);\n return Number.isNaN(value) ? null : value;\n};\n\nexport class NpmRegistryMetadataProvider implements DependencyMetadataProvider {\n private readonly cache = new Map<string, DependencyMetadata | null>();\n\n async getMetadata(name: string, version: string): Promise<DependencyMetadata | null> {\n const key = `${name}@${version}`;\n if (this.cache.has(key)) {\n return this.cache.get(key) ?? null;\n }\n\n try {\n const encodedName = encodeURIComponent(name);\n const response = await fetch(`https://registry.npmjs.org/${encodedName}`);\n if (!response.ok) {\n this.cache.set(key, null);\n return null;\n }\n\n const payload = (await response.json()) as NpmPackagePayload;\n const timeEntries = payload.time ?? {};\n\n const publishDates = Object.entries(timeEntries)\n .filter(([tag]) => tag !== \"created\" && tag !== \"modified\")\n .map(([, date]) => parseDate(date))\n .filter((value): value is number => value !== null)\n .sort((a, b) => a - b);\n\n const modifiedAt = parseDate(timeEntries[\"modified\"]);\n const now = Date.now();\n const daysSinceLastRelease = modifiedAt === null ? null : Math.max(0, round4((now - modifiedAt) / ONE_DAY_MS));\n\n let releaseFrequencyDays: number | null = null;\n if (publishDates.length >= 2) {\n const totalIntervals = publishDates.length - 1;\n let sum = 0;\n for (let i = 1; i < publishDates.length; i += 1) {\n const current = publishDates[i];\n const previous = publishDates[i - 1];\n if (current !== undefined && previous !== undefined) {\n sum += current - previous;\n }\n }\n\n releaseFrequencyDays = round4(sum / totalIntervals / ONE_DAY_MS);\n }\n\n const maintainers = payload.maintainers ?? [];\n const maintainerCount = maintainers.length > 0 ? maintainers.length : null;\n\n const metadata: DependencyMetadata = {\n name,\n version,\n maintainerCount,\n releaseFrequencyDays,\n daysSinceLastRelease,\n repositoryActivity30d: null,\n busFactor: null,\n };\n\n this.cache.set(key, metadata);\n return metadata;\n } catch {\n this.cache.set(key, null);\n return null;\n }\n }\n}\n","import type { DependencyMetadata, DependencyMetadataProvider } from \"../domain/types.js\";\n\nexport class NoopMetadataProvider implements DependencyMetadataProvider {\n async getMetadata(_name: string, _version: string): Promise<DependencyMetadata | null> {\n return null;\n }\n}\n","import type { ExternalAnalysisSummary } from \"@codesentinel/core\";\nimport {\n analyzeDependencyExposure,\n type AnalyzeDependencyExposureInput,\n} from \"./application/analyze-dependency-exposure.js\";\nimport { NpmRegistryMetadataProvider } from \"./infrastructure/npm-registry-metadata-provider.js\";\nimport { NoopMetadataProvider } from \"./infrastructure/noop-metadata-provider.js\";\n\nexport type { AnalyzeDependencyExposureInput } from \"./application/analyze-dependency-exposure.js\";\n\nexport const analyzeDependencyExposureFromProject = async (\n input: AnalyzeDependencyExposureInput,\n): Promise<ExternalAnalysisSummary> => {\n const metadataProvider =\n process.env[\"CODESENTINEL_EXTERNAL_METADATA\"] === \"none\"\n ? new NoopMetadataProvider()\n : new NpmRegistryMetadataProvider();\n\n return analyzeDependencyExposure(input, metadataProvider);\n};\n","import type {\n CouplingMatrix,\n FileAuthorShare,\n FileCoupling,\n FileEvolutionMetrics,\n Hotspot,\n RepositoryEvolutionSummary,\n} from \"@codesentinel/core\";\nimport type { EvolutionComputationConfig, GitCommitRecord } from \"./evolution-types.js\";\n\ntype FileAccumulator = {\n commitCount: number;\n recentCommitCount: number;\n churnAdded: number;\n churnDeleted: number;\n authors: Map<string, number>;\n};\n\ntype AuthorProfile = {\n authorId: string;\n commitCount: number;\n primaryName: string;\n emailStem: string | null;\n isBot: boolean;\n};\n\nconst pairKey = (a: string, b: string): string => `${a}\\u0000${b}`;\n\nconst round4 = (value: number): number => Number(value.toFixed(4));\n\nconst normalizeName = (value: string): string =>\n value\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n\nconst extractEmailStem = (authorId: string): string | null => {\n const normalized = authorId.trim().toLowerCase();\n const githubNoReplyMatch = normalized.match(/^\\d+\\+([^@]+)@users\\.noreply\\.github\\.com$/);\n if (githubNoReplyMatch?.[1] !== undefined) {\n return githubNoReplyMatch[1].replace(/[._+-]/g, \"\");\n }\n\n const atIndex = normalized.indexOf(\"@\");\n if (atIndex <= 0) {\n return null;\n }\n\n return normalized.slice(0, atIndex).replace(/[._+-]/g, \"\");\n};\n\nconst areNamesCompatible = (left: string, right: string): boolean => {\n if (left.length === 0 || right.length === 0) {\n return false;\n }\n\n if (left === right) {\n return true;\n }\n\n if (left.startsWith(`${right} `) || right.startsWith(`${left} `)) {\n return true;\n }\n\n return false;\n};\n\nconst chooseCanonicalAuthorId = (profiles: readonly AuthorProfile[]): string => {\n const ordered = [...profiles].sort((a, b) => {\n const aIsNoReply = a.authorId.includes(\"@users.noreply.github.com\");\n const bIsNoReply = b.authorId.includes(\"@users.noreply.github.com\");\n if (aIsNoReply !== bIsNoReply) {\n return aIsNoReply ? 1 : -1;\n }\n\n if (a.commitCount !== b.commitCount) {\n return b.commitCount - a.commitCount;\n }\n\n return a.authorId.localeCompare(b.authorId);\n });\n\n return ordered[0]?.authorId ?? \"\";\n};\n\nconst buildAuthorAliasMap = (commits: readonly GitCommitRecord[]): ReadonlyMap<string, string> => {\n const nameCountsByAuthorId = new Map<string, Map<string, number>>();\n const commitCountByAuthorId = new Map<string, number>();\n\n for (const commit of commits) {\n commitCountByAuthorId.set(commit.authorId, (commitCountByAuthorId.get(commit.authorId) ?? 0) + 1);\n\n const normalizedName = normalizeName(commit.authorName);\n const names = nameCountsByAuthorId.get(commit.authorId) ?? new Map<string, number>();\n if (normalizedName.length > 0) {\n names.set(normalizedName, (names.get(normalizedName) ?? 0) + 1);\n }\n nameCountsByAuthorId.set(commit.authorId, names);\n }\n\n const profiles: AuthorProfile[] = [...commitCountByAuthorId.entries()].map(([authorId, commitCount]) => {\n const names = nameCountsByAuthorId.get(authorId);\n const primaryName =\n names === undefined\n ? \"\"\n : [...names.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))[0]?.[0] ?? \"\";\n const normalizedAuthorId = authorId.toLowerCase();\n const isBot = normalizedAuthorId.includes(\"[bot]\");\n\n return {\n authorId,\n commitCount,\n primaryName,\n emailStem: isBot ? null : extractEmailStem(authorId),\n isBot,\n };\n });\n\n const groupsByStem = new Map<string, AuthorProfile[]>();\n for (const profile of profiles) {\n if (profile.emailStem === null || profile.emailStem.length < 4) {\n continue;\n }\n\n const current = groupsByStem.get(profile.emailStem) ?? [];\n current.push(profile);\n groupsByStem.set(profile.emailStem, current);\n }\n\n const aliasMap = new Map<string, string>();\n for (const profile of profiles) {\n aliasMap.set(profile.authorId, profile.authorId);\n }\n\n for (const group of groupsByStem.values()) {\n if (group.length < 2) {\n continue;\n }\n\n const compatible: AuthorProfile[] = [];\n for (const profile of group) {\n if (profile.isBot || profile.primaryName.length === 0) {\n continue;\n }\n\n compatible.push(profile);\n }\n\n if (compatible.length < 2) {\n continue;\n }\n\n const canonical = chooseCanonicalAuthorId(compatible);\n const canonicalProfile = compatible.find((candidate) => candidate.authorId === canonical);\n if (canonicalProfile === undefined) {\n continue;\n }\n\n for (const profile of compatible) {\n if (areNamesCompatible(profile.primaryName, canonicalProfile.primaryName)) {\n aliasMap.set(profile.authorId, canonical);\n }\n }\n }\n\n return aliasMap;\n};\n\nconst computeBusFactor = (\n authorDistribution: readonly FileAuthorShare[],\n threshold: number,\n): number => {\n if (authorDistribution.length === 0) {\n return 0;\n }\n\n let coveredShare = 0;\n for (let i = 0; i < authorDistribution.length; i += 1) {\n const entry = authorDistribution[i];\n if (entry === undefined) {\n continue;\n }\n\n coveredShare += entry.share;\n if (coveredShare >= threshold) {\n return i + 1;\n }\n }\n\n return authorDistribution.length;\n};\n\nconst finalizeAuthorDistribution = (authorCommits: ReadonlyMap<string, number>): readonly FileAuthorShare[] => {\n const totalCommits = [...authorCommits.values()].reduce((sum, value) => sum + value, 0);\n if (totalCommits === 0) {\n return [];\n }\n\n return [...authorCommits.entries()]\n .map(([authorId, commits]) => ({\n authorId,\n commits,\n share: round4(commits / totalCommits),\n }))\n .sort((a, b) => b.commits - a.commits || a.authorId.localeCompare(b.authorId));\n};\n\nconst buildCouplingMatrix = (\n coChangeByPair: ReadonlyMap<string, number>,\n fileCommitCount: ReadonlyMap<string, number>,\n consideredCommits: number,\n skippedLargeCommits: number,\n maxCouplingPairs: number,\n): CouplingMatrix => {\n const allPairs: FileCoupling[] = [];\n\n for (const [key, coChangeCommits] of coChangeByPair.entries()) {\n const [fileA, fileB] = key.split(\"\\u0000\");\n if (fileA === undefined || fileB === undefined) {\n continue;\n }\n\n const fileACommits = fileCommitCount.get(fileA) ?? 0;\n const fileBCommits = fileCommitCount.get(fileB) ?? 0;\n const denominator = fileACommits + fileBCommits - coChangeCommits;\n const couplingScore = denominator === 0 ? 0 : round4(coChangeCommits / denominator);\n\n allPairs.push({\n fileA,\n fileB,\n coChangeCommits,\n couplingScore,\n });\n }\n\n allPairs.sort(\n (a, b) =>\n b.coChangeCommits - a.coChangeCommits ||\n b.couplingScore - a.couplingScore ||\n a.fileA.localeCompare(b.fileA) ||\n a.fileB.localeCompare(b.fileB),\n );\n\n const truncated = allPairs.length > maxCouplingPairs;\n\n return {\n pairs: truncated ? allPairs.slice(0, maxCouplingPairs) : allPairs,\n totalPairCount: allPairs.length,\n consideredCommits,\n skippedLargeCommits,\n truncated,\n };\n};\n\nconst selectHotspots = (\n files: readonly FileEvolutionMetrics[],\n config: EvolutionComputationConfig,\n): { hotspots: readonly Hotspot[]; threshold: number } => {\n if (files.length === 0) {\n return { hotspots: [], threshold: 0 };\n }\n\n const sorted = [...files].sort(\n (a, b) =>\n b.commitCount - a.commitCount || b.churnTotal - a.churnTotal || a.filePath.localeCompare(b.filePath),\n );\n\n const hotspotCount = Math.max(config.hotspotMinFiles, Math.ceil(sorted.length * config.hotspotTopPercent));\n const selected = sorted.slice(0, hotspotCount);\n\n const hotspots = selected.map((file, index) => ({\n filePath: file.filePath,\n rank: index + 1,\n commitCount: file.commitCount,\n churnTotal: file.churnTotal,\n }));\n\n const threshold = selected[selected.length - 1]?.commitCount ?? 0;\n return { hotspots, threshold };\n};\n\nexport const computeRepositoryEvolutionSummary = (\n targetPath: string,\n commits: readonly GitCommitRecord[],\n config: EvolutionComputationConfig,\n): RepositoryEvolutionSummary => {\n const authorAliasById =\n config.authorIdentityMode === \"likely_merge\" ? buildAuthorAliasMap(commits) : new Map<string, string>();\n const fileStats = new Map<string, FileAccumulator>();\n const coChangeByPair = new Map<string, number>();\n\n const headCommitTimestamp = commits.length === 0 ? null : commits[commits.length - 1]?.authoredAtUnix ?? null;\n const recentWindowStart =\n headCommitTimestamp === null\n ? Number.NEGATIVE_INFINITY\n : headCommitTimestamp - config.recentWindowDays * 24 * 60 * 60;\n\n let consideredCommits = 0;\n let skippedLargeCommits = 0;\n\n for (const commit of commits) {\n const uniqueFiles = new Set<string>();\n\n for (const fileChange of commit.fileChanges) {\n uniqueFiles.add(fileChange.filePath);\n const current = fileStats.get(fileChange.filePath) ?? {\n commitCount: 0,\n recentCommitCount: 0,\n churnAdded: 0,\n churnDeleted: 0,\n authors: new Map<string, number>(),\n };\n\n current.churnAdded += fileChange.additions;\n current.churnDeleted += fileChange.deletions;\n fileStats.set(fileChange.filePath, current);\n }\n\n for (const filePath of uniqueFiles) {\n const current = fileStats.get(filePath);\n if (current === undefined) {\n continue;\n }\n\n current.commitCount += 1;\n if (commit.authoredAtUnix >= recentWindowStart) {\n current.recentCommitCount += 1;\n }\n\n const effectiveAuthorId = authorAliasById.get(commit.authorId) ?? commit.authorId;\n current.authors.set(effectiveAuthorId, (current.authors.get(effectiveAuthorId) ?? 0) + 1);\n }\n\n const orderedFiles = [...uniqueFiles].sort((a, b) => a.localeCompare(b));\n if (orderedFiles.length > 1) {\n if (orderedFiles.length <= config.maxFilesPerCommitForCoupling) {\n consideredCommits += 1;\n for (let i = 0; i < orderedFiles.length - 1; i += 1) {\n for (let j = i + 1; j < orderedFiles.length; j += 1) {\n const fileA = orderedFiles[i];\n const fileB = orderedFiles[j];\n if (fileA === undefined || fileB === undefined) {\n continue;\n }\n\n const key = pairKey(fileA, fileB);\n coChangeByPair.set(key, (coChangeByPair.get(key) ?? 0) + 1);\n }\n }\n } else {\n skippedLargeCommits += 1;\n }\n }\n }\n\n const files: FileEvolutionMetrics[] = [...fileStats.entries()]\n .map(([filePath, stats]) => {\n const authorDistribution = finalizeAuthorDistribution(stats.authors);\n const topAuthorShare = authorDistribution[0]?.share ?? 0;\n return {\n filePath,\n commitCount: stats.commitCount,\n frequencyPer100Commits: commits.length === 0 ? 0 : round4((stats.commitCount / commits.length) * 100),\n churnAdded: stats.churnAdded,\n churnDeleted: stats.churnDeleted,\n churnTotal: stats.churnAdded + stats.churnDeleted,\n recentCommitCount: stats.recentCommitCount,\n recentVolatility: stats.commitCount === 0 ? 0 : round4(stats.recentCommitCount / stats.commitCount),\n topAuthorShare,\n busFactor: computeBusFactor(authorDistribution, config.busFactorCoverageThreshold),\n authorDistribution,\n };\n })\n .sort((a, b) => a.filePath.localeCompare(b.filePath));\n\n const fileCommitCount = new Map(files.map((file) => [file.filePath, file.commitCount]));\n const coupling = buildCouplingMatrix(\n coChangeByPair,\n fileCommitCount,\n consideredCommits,\n skippedLargeCommits,\n config.maxCouplingPairs,\n );\n\n const { hotspots, threshold } = selectHotspots(files, config);\n\n return {\n targetPath,\n available: true,\n files,\n hotspots,\n coupling,\n metrics: {\n totalCommits: commits.length,\n totalFiles: files.length,\n headCommitTimestamp,\n recentWindowDays: config.recentWindowDays,\n hotspotTopPercent: config.hotspotTopPercent,\n hotspotThresholdCommitCount: threshold,\n },\n };\n};\n","export type GitFileChange = {\n filePath: string;\n additions: number;\n deletions: number;\n};\n\nexport type GitCommitRecord = {\n hash: string;\n authorId: string;\n authorName: string;\n authoredAtUnix: number;\n fileChanges: readonly GitFileChange[];\n};\n\nexport type EvolutionComputationConfig = {\n authorIdentityMode: \"likely_merge\" | \"strict_email\";\n recentWindowDays: number;\n hotspotTopPercent: number;\n hotspotMinFiles: number;\n maxFilesPerCommitForCoupling: number;\n maxCouplingPairs: number;\n busFactorCoverageThreshold: number;\n};\n\nexport const DEFAULT_EVOLUTION_CONFIG: EvolutionComputationConfig = {\n authorIdentityMode: \"likely_merge\",\n recentWindowDays: 30,\n hotspotTopPercent: 0.1,\n hotspotMinFiles: 1,\n maxFilesPerCommitForCoupling: 200,\n maxCouplingPairs: 500,\n busFactorCoverageThreshold: 0.6,\n};\n","import type { RepositoryEvolutionSummary } from \"@codesentinel/core\";\nimport { computeRepositoryEvolutionSummary } from \"../domain/evolution-metrics.js\";\nimport {\n DEFAULT_EVOLUTION_CONFIG,\n type EvolutionComputationConfig,\n} from \"../domain/evolution-types.js\";\nimport type { GitHistoryProvider } from \"./git-history-provider.js\";\n\nexport type AnalyzeRepositoryEvolutionInput = {\n repositoryPath: string;\n config?: Partial<EvolutionComputationConfig>;\n};\n\nconst createEffectiveConfig = (\n overrides: Partial<EvolutionComputationConfig> | undefined,\n): EvolutionComputationConfig => ({\n ...DEFAULT_EVOLUTION_CONFIG,\n ...overrides,\n});\n\nexport const analyzeRepositoryEvolution = (\n input: AnalyzeRepositoryEvolutionInput,\n historyProvider: GitHistoryProvider,\n): RepositoryEvolutionSummary => {\n if (!historyProvider.isGitRepository(input.repositoryPath)) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"not_git_repository\",\n };\n }\n\n const commits = historyProvider.getCommitHistory(input.repositoryPath);\n const config = createEffectiveConfig(input.config);\n\n return computeRepositoryEvolutionSummary(input.repositoryPath, commits, config);\n};\n","import { execFileSync } from \"node:child_process\";\n\nexport class GitCommandError extends Error {\n readonly args: readonly string[];\n\n constructor(message: string, args: readonly string[]) {\n super(message);\n this.name = \"GitCommandError\";\n this.args = args;\n }\n}\n\nexport interface GitCommandClient {\n run(repositoryPath: string, args: readonly string[]): string;\n}\n\nexport class ExecGitCommandClient implements GitCommandClient {\n run(repositoryPath: string, args: readonly string[]): string {\n try {\n return execFileSync(\"git\", [\"-C\", repositoryPath, ...args], {\n encoding: \"utf8\",\n maxBuffer: 1024 * 1024 * 64,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown git execution error\";\n throw new GitCommandError(message, args);\n }\n }\n}\n","export const COMMIT_RECORD_SEPARATOR = \"\\u001e\";\nexport const COMMIT_FIELD_SEPARATOR = \"\\u001f\";\n\nexport const GIT_LOG_FORMAT =\n `%x1e%H%x1f%at%x1f%an%x1f%ae`;\n","import { COMMIT_FIELD_SEPARATOR, COMMIT_RECORD_SEPARATOR } from \"../domain/git-log-format.js\";\nimport type { GitCommitRecord, GitFileChange } from \"../domain/evolution-types.js\";\n\nconst parseInteger = (value: string): number | null => {\n if (value.length === 0) {\n return null;\n }\n\n const parsed = Number.parseInt(value, 10);\n if (Number.isNaN(parsed)) {\n return null;\n }\n\n return parsed;\n};\n\nconst normalizeAuthorIdentity = (authorName: string, authorEmail: string): string => {\n const normalizedName = authorName.trim().replace(/\\s+/g, \" \").toLowerCase();\n const normalizedEmail = authorEmail.trim().toLowerCase();\n\n if (/\\[bot\\]/i.test(normalizedName) || /\\[bot\\]/i.test(normalizedEmail)) {\n return normalizedEmail.length > 0 ? normalizedEmail : normalizedName;\n }\n\n const githubNoReplyMatch = normalizedEmail.match(/^\\d+\\+([^@]+)@users\\.noreply\\.github\\.com$/);\n const githubHandle = githubNoReplyMatch?.[1]?.trim().toLowerCase();\n if (githubHandle !== undefined && githubHandle.length > 0) {\n return `${githubHandle}@users.noreply.github.com`;\n }\n\n if (normalizedEmail.length > 0) {\n return normalizedEmail;\n }\n\n return normalizedName;\n};\n\nconst parseRenamedPath = (pathSpec: string): string => {\n if (!pathSpec.includes(\" => \")) {\n return pathSpec;\n }\n\n const braceRenameMatch = pathSpec.match(/^(.*)\\{(.+) => (.+)\\}(.*)$/);\n if (braceRenameMatch !== null) {\n const [, prefix, , renamedTo, suffix] = braceRenameMatch;\n return `${prefix}${renamedTo}${suffix}`;\n }\n\n const parts = pathSpec.split(\" => \");\n const finalPart = parts[parts.length - 1];\n return finalPart ?? pathSpec;\n};\n\nconst parseNumstatLine = (line: string): GitFileChange | null => {\n const parts = line.split(\"\\t\");\n if (parts.length < 3) {\n return null;\n }\n\n const additionsRaw = parts[0];\n const deletionsRaw = parts[1];\n const pathRaw = parts.slice(2).join(\"\\t\");\n\n if (additionsRaw === undefined || deletionsRaw === undefined) {\n return null;\n }\n\n const additions = additionsRaw === \"-\" ? 0 : parseInteger(additionsRaw);\n const deletions = deletionsRaw === \"-\" ? 0 : parseInteger(deletionsRaw);\n\n if (additions === null || deletions === null) {\n return null;\n }\n\n const filePath = parseRenamedPath(pathRaw);\n return {\n filePath,\n additions,\n deletions,\n };\n};\n\nexport const parseGitLog = (rawLog: string): readonly GitCommitRecord[] => {\n const records = rawLog\n .split(COMMIT_RECORD_SEPARATOR)\n .map((record) => record.trim())\n .filter((record) => record.length > 0);\n\n const commits: GitCommitRecord[] = [];\n\n for (const record of records) {\n const lines = record\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n\n if (lines.length === 0) {\n continue;\n }\n\n const headerParts = lines[0]?.split(COMMIT_FIELD_SEPARATOR) ?? [];\n if (headerParts.length !== 4) {\n continue;\n }\n\n const [hash, authoredAtRaw, authorName, authorEmail] = headerParts;\n if (hash === undefined || authoredAtRaw === undefined || authorName === undefined || authorEmail === undefined) {\n continue;\n }\n\n const authoredAtUnix = parseInteger(authoredAtRaw);\n if (authoredAtUnix === null) {\n continue;\n }\n\n const fileChanges: GitFileChange[] = [];\n for (const line of lines.slice(1)) {\n const parsedLine = parseNumstatLine(line);\n if (parsedLine !== null) {\n fileChanges.push(parsedLine);\n }\n }\n\n commits.push({\n hash,\n authorId: normalizeAuthorIdentity(authorName, authorEmail),\n authorName,\n authoredAtUnix,\n fileChanges,\n });\n }\n\n commits.sort((a, b) => a.authoredAtUnix - b.authoredAtUnix || a.hash.localeCompare(b.hash));\n return commits;\n};\n","import { GIT_LOG_FORMAT } from \"../domain/git-log-format.js\";\nimport type { GitCommitRecord } from \"../domain/evolution-types.js\";\nimport type { GitHistoryProvider } from \"../application/git-history-provider.js\";\nimport { GitCommandError, type GitCommandClient } from \"./git-command-client.js\";\nimport { parseGitLog } from \"../parsing/git-log-parser.js\";\n\nconst NON_GIT_CODES = [\"not a git repository\", \"not in a git directory\"];\n\nconst isNotGitError = (error: GitCommandError): boolean => {\n const lower = error.message.toLowerCase();\n return NON_GIT_CODES.some((code) => lower.includes(code));\n};\n\nexport class GitCliHistoryProvider implements GitHistoryProvider {\n constructor(private readonly gitClient: GitCommandClient) {}\n\n isGitRepository(repositoryPath: string): boolean {\n try {\n const output = this.gitClient.run(repositoryPath, [\"rev-parse\", \"--is-inside-work-tree\"]);\n return output.trim() === \"true\";\n } catch (error) {\n if (error instanceof GitCommandError && isNotGitError(error)) {\n return false;\n }\n\n throw error;\n }\n }\n\n getCommitHistory(repositoryPath: string): readonly GitCommitRecord[] {\n const output = this.gitClient.run(repositoryPath, [\n \"-c\",\n \"core.quotepath=false\",\n \"log\",\n \"--use-mailmap\",\n \"--no-merges\",\n \"--date=unix\",\n `--pretty=format:${GIT_LOG_FORMAT}`,\n \"--numstat\",\n \"--find-renames\",\n ]);\n\n return parseGitLog(output);\n }\n}\n","import type { RepositoryEvolutionSummary } from \"@codesentinel/core\";\nimport {\n analyzeRepositoryEvolution,\n type AnalyzeRepositoryEvolutionInput,\n} from \"./application/analyze-repository-evolution.js\";\nimport { ExecGitCommandClient } from \"./infrastructure/git-command-client.js\";\nimport { GitCliHistoryProvider } from \"./infrastructure/git-history-provider.js\";\n\nexport type { AnalyzeRepositoryEvolutionInput } from \"./application/analyze-repository-evolution.js\";\n\nexport const analyzeRepositoryEvolutionFromGit = (\n input: AnalyzeRepositoryEvolutionInput,\n): RepositoryEvolutionSummary => {\n const historyProvider = new GitCliHistoryProvider(new ExecGitCommandClient());\n return analyzeRepositoryEvolution(input, historyProvider);\n};\n"],"mappings":"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","names":["readFileSync","resolve","resolve","nodeLowLink","program","packageJsonPath","version","round4","round4","resolve","resolve","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/application/format-analyze-output.ts","../src/application/logger.ts","../src/application/run-analyze-command.ts","../../code-graph/src/domain/graph-model.ts","../../code-graph/src/domain/tarjan.ts","../../code-graph/src/domain/graph-metrics.ts","../../code-graph/src/infrastructure/typescript-project.ts","../../code-graph/src/application/build-project-graph-summary.ts","../../dependency-firewall/src/domain/external-analysis.ts","../../dependency-firewall/src/domain/types.ts","../../dependency-firewall/src/infrastructure/fs-loader.ts","../../dependency-firewall/src/parsing/package-json-loader.ts","../../dependency-firewall/src/parsing/package-lock-parser.ts","../../dependency-firewall/src/parsing/pnpm-lock-parser.ts","../../dependency-firewall/src/parsing/yarn-lock-parser.ts","../../dependency-firewall/src/parsing/bun-lock-parser.ts","../../dependency-firewall/src/application/analyze-dependency-exposure.ts","../../dependency-firewall/src/infrastructure/npm-registry-metadata-provider.ts","../../dependency-firewall/src/infrastructure/noop-metadata-provider.ts","../../dependency-firewall/src/index.ts","../../git-analyzer/src/domain/evolution-metrics.ts","../../git-analyzer/src/domain/evolution-types.ts","../../git-analyzer/src/application/analyze-repository-evolution.ts","../../git-analyzer/src/infrastructure/git-command-client.ts","../../git-analyzer/src/domain/git-log-format.ts","../../git-analyzer/src/application/git-history-provider.ts","../../git-analyzer/src/parsing/git-log-parser.ts","../../git-analyzer/src/infrastructure/git-history-provider.ts","../../git-analyzer/src/index.ts","../../risk-engine/src/config.ts","../../risk-engine/src/domain/math.ts","../../risk-engine/src/domain/normalization.ts","../../risk-engine/src/domain/risk-model.ts","../../risk-engine/src/application/compute-repository-risk-summary.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { formatAnalyzeOutput, type AnalyzeOutputMode } from \"./application/format-analyze-output.js\";\nimport { createStderrLogger, parseLogLevel, type LogLevel } from \"./application/logger.js\";\nimport { runAnalyzeCommand, type AuthorIdentityCliMode } from \"./application/run-analyze-command.js\";\n\nconst program = new Command();\nconst packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), \"../package.json\");\nconst { version } = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version: string };\n\nprogram\n .name(\"codesentinel\")\n .description(\"Structural and evolutionary risk analysis for TypeScript/JavaScript codebases\")\n .version(version);\n\nprogram\n .command(\"analyze\")\n .argument(\"[path]\", \"path to the project to analyze\")\n .addOption(\n new Option(\n \"--author-identity <mode>\",\n \"author identity mode: likely_merge (heuristic) or strict_email (deterministic)\",\n )\n .choices([\"likely_merge\", \"strict_email\"])\n .default(\"likely_merge\"),\n )\n .addOption(\n new Option(\n \"--log-level <level>\",\n \"log verbosity: silent, error, warn, info, debug (logs are written to stderr)\",\n )\n .choices([\"silent\", \"error\", \"warn\", \"info\", \"debug\"])\n .default(parseLogLevel(process.env[\"CODESENTINEL_LOG_LEVEL\"]) as LogLevel),\n )\n .addOption(\n new Option(\n \"--output <mode>\",\n \"output mode: summary (default) or json (full analysis object)\",\n )\n .choices([\"summary\", \"json\"])\n .default(\"summary\"),\n )\n .option(\"--json\", \"shortcut for --output json\")\n .action(\n async (\n path: string | undefined,\n options: {\n authorIdentity: AuthorIdentityCliMode;\n logLevel: LogLevel;\n output: AnalyzeOutputMode;\n json?: boolean;\n },\n ) => {\n const logger = createStderrLogger(options.logLevel);\n const summary = await runAnalyzeCommand(path, options.authorIdentity, logger);\n const outputMode: AnalyzeOutputMode = options.json === true ? \"json\" : options.output;\n process.stdout.write(`${formatAnalyzeOutput(summary, outputMode)}\\n`);\n },\n );\n\nif (process.argv.length <= 2) {\n program.outputHelp();\n process.exit(0);\n}\n\nconst executablePath = process.argv[0] ?? \"\";\nconst scriptPath = process.argv[1] ?? \"\";\n\nconst argv =\n process.argv[2] === \"--\"\n ? [executablePath, scriptPath, ...process.argv.slice(3)]\n : process.argv;\n\nif (argv.length <= 2) {\n program.outputHelp();\n process.exit(0);\n}\n\nawait program.parseAsync(argv);\n","import type { AnalyzeSummary } from \"@codesentinel/core\";\n\nexport type AnalyzeOutputMode = \"summary\" | \"json\";\n\ntype EvolutionAvailable = Extract<AnalyzeSummary[\"evolution\"], { available: true }>;\ntype ExternalAvailable = Extract<AnalyzeSummary[\"external\"], { available: true }>;\n\ntype SummaryShape = {\n targetPath: string;\n structural: AnalyzeSummary[\"structural\"][\"metrics\"];\n evolution:\n | {\n available: false;\n reason: \"not_git_repository\";\n }\n | {\n available: true;\n metrics: EvolutionAvailable[\"metrics\"];\n hotspotsTop: readonly string[];\n };\n external:\n | {\n available: false;\n reason:\n | \"package_json_not_found\"\n | \"lockfile_not_found\"\n | \"unsupported_lockfile_format\"\n | \"invalid_lockfile\";\n }\n | {\n available: true;\n metrics: ExternalAvailable[\"metrics\"];\n highRiskDependenciesTop: readonly string[];\n };\n risk: {\n repositoryScore: number;\n normalizedScore: number;\n hotspotsTop: ReadonlyArray<{\n file: string;\n score: number;\n }>;\n fragileClusterCount: number;\n dependencyAmplificationZoneCount: number;\n };\n};\n\nconst createSummaryShape = (summary: AnalyzeSummary): SummaryShape => ({\n targetPath: summary.structural.targetPath,\n structural: summary.structural.metrics,\n evolution: summary.evolution.available\n ? {\n available: true,\n metrics: summary.evolution.metrics,\n hotspotsTop: summary.evolution.hotspots.slice(0, 5).map((hotspot) => hotspot.filePath),\n }\n : {\n available: false,\n reason: summary.evolution.reason,\n },\n external: summary.external.available\n ? {\n available: true,\n metrics: summary.external.metrics,\n highRiskDependenciesTop: summary.external.highRiskDependencies.slice(0, 10),\n }\n : {\n available: false,\n reason: summary.external.reason,\n },\n risk: {\n repositoryScore: summary.risk.repositoryScore,\n normalizedScore: summary.risk.normalizedScore,\n hotspotsTop: summary.risk.hotspots.slice(0, 5).map((hotspot) => ({\n file: hotspot.file,\n score: hotspot.score,\n })),\n fragileClusterCount: summary.risk.fragileClusters.length,\n dependencyAmplificationZoneCount: summary.risk.dependencyAmplificationZones.length,\n },\n});\n\nexport const formatAnalyzeOutput = (summary: AnalyzeSummary, mode: AnalyzeOutputMode): string =>\n mode === \"json\"\n ? JSON.stringify(summary, null, 2)\n : JSON.stringify(createSummaryShape(summary), null, 2);\n","export type LogLevel = \"silent\" | \"error\" | \"warn\" | \"info\" | \"debug\";\n\nconst logLevelRank: Readonly<Record<Exclude<LogLevel, \"silent\">, number>> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\nexport type Logger = {\n error: (message: string) => void;\n warn: (message: string) => void;\n info: (message: string) => void;\n debug: (message: string) => void;\n};\n\nconst noop = (): void => {};\n\nexport const createSilentLogger = (): Logger => ({\n error: noop,\n warn: noop,\n info: noop,\n debug: noop,\n});\n\nconst shouldLog = (configuredLevel: LogLevel, messageLevel: Exclude<LogLevel, \"silent\">): boolean => {\n if (configuredLevel === \"silent\") {\n return false;\n }\n\n return logLevelRank[messageLevel] <= logLevelRank[configuredLevel];\n};\n\nconst write = (messageLevel: Exclude<LogLevel, \"silent\">, message: string): void => {\n process.stderr.write(`[codesentinel] ${messageLevel.toUpperCase()} ${message}\\n`);\n};\n\nexport const createStderrLogger = (level: LogLevel): Logger => {\n if (level === \"silent\") {\n return createSilentLogger();\n }\n\n return {\n error: (message) => {\n if (shouldLog(level, \"error\")) {\n write(\"error\", message);\n }\n },\n warn: (message) => {\n if (shouldLog(level, \"warn\")) {\n write(\"warn\", message);\n }\n },\n info: (message) => {\n if (shouldLog(level, \"info\")) {\n write(\"info\", message);\n }\n },\n debug: (message) => {\n if (shouldLog(level, \"debug\")) {\n write(\"debug\", message);\n }\n },\n };\n};\n\nexport const parseLogLevel = (value: string | undefined): LogLevel => {\n switch (value) {\n case \"silent\":\n case \"error\":\n case \"warn\":\n case \"info\":\n case \"debug\":\n return value;\n default:\n return \"info\";\n }\n};\n","import { resolve } from \"node:path\";\nimport type { AnalyzeSummary } from \"@codesentinel/core\";\nimport {\n buildProjectGraphSummary,\n type ParseTypescriptProjectProgressEvent,\n} from \"@codesentinel/code-graph\";\nimport {\n analyzeDependencyExposureFromProject,\n type DependencyExposureProgressEvent,\n} from \"@codesentinel/dependency-firewall\";\nimport {\n analyzeRepositoryEvolutionFromGit,\n type EvolutionAnalysisProgressEvent,\n} from \"@codesentinel/git-analyzer\";\nimport { computeRepositoryRiskSummary } from \"@codesentinel/risk-engine\";\nimport { createSilentLogger, type Logger } from \"./logger.js\";\n\nexport type AuthorIdentityCliMode = \"likely_merge\" | \"strict_email\";\n\nconst resolveTargetPath = (inputPath: string | undefined, cwd: string): string =>\n resolve(cwd, inputPath ?? \".\");\n\nconst createExternalProgressReporter = (logger: Logger): ((event: DependencyExposureProgressEvent) => void) => {\n let lastLoggedProgress = 0;\n\n return (event) => {\n switch (event.stage) {\n case \"package_json_loaded\":\n logger.debug(\"external: package.json loaded\");\n break;\n case \"lockfile_selected\":\n logger.info(`external: lockfile selected (${event.kind})`);\n break;\n case \"lockfile_parsed\":\n logger.info(\n `external: parsed ${event.dependencyNodes} locked dependencies (${event.directDependencies} direct)`,\n );\n break;\n case \"metadata_fetch_started\":\n logger.info(`external: fetching dependency metadata (${event.total} packages)`);\n break;\n case \"metadata_fetch_progress\": {\n const currentPercent = event.total === 0 ? 100 : Math.floor((event.completed / event.total) * 100);\n if (\n event.completed === event.total ||\n event.completed === 1 ||\n event.completed - lastLoggedProgress >= 25\n ) {\n lastLoggedProgress = event.completed;\n logger.info(\n `external: metadata progress ${event.completed}/${event.total} (${currentPercent}%)`,\n );\n logger.debug(`external: last package processed ${event.packageName}`);\n }\n break;\n }\n case \"metadata_fetch_completed\":\n logger.info(`external: metadata fetch completed (${event.total} packages)`);\n break;\n case \"summary_built\":\n logger.info(\n `external: summary built (${event.totalDependencies} total, ${event.directDependencies} direct)`,\n );\n break;\n }\n };\n};\n\nconst createStructuralProgressReporter = (\n logger: Logger,\n): ((event: ParseTypescriptProjectProgressEvent) => void) => {\n let lastProcessed = 0;\n\n return (event) => {\n switch (event.stage) {\n case \"config_resolved\":\n if (event.usedFallbackScan) {\n logger.info(\n `structural: using filesystem scan discovery (tsconfigs=${event.tsconfigCount})`,\n );\n } else {\n logger.info(`structural: discovered tsconfig graph (${event.tsconfigCount} configs)`);\n }\n break;\n case \"files_discovered\":\n logger.info(`structural: discovered ${event.totalSourceFiles} source files`);\n break;\n case \"program_created\":\n logger.debug(`structural: TypeScript program created (${event.totalSourceFiles} files)`);\n break;\n case \"file_processed\":\n if (\n event.processed === event.total ||\n event.processed === 1 ||\n event.processed - lastProcessed >= 50\n ) {\n lastProcessed = event.processed;\n logger.info(`structural: resolved ${event.processed}/${event.total} files`);\n logger.debug(`structural: last file processed ${event.filePath}`);\n }\n break;\n case \"edges_resolved\":\n logger.info(`structural: resolved ${event.totalEdges} dependency edges`);\n break;\n }\n };\n};\n\nconst createEvolutionProgressReporter = (\n logger: Logger,\n): ((event: EvolutionAnalysisProgressEvent) => void) => {\n let lastParsedRecords = 0;\n\n return (event) => {\n switch (event.stage) {\n case \"checking_git_repository\":\n logger.debug(\"evolution: checking git repository\");\n break;\n case \"not_git_repository\":\n logger.warn(\"evolution: target path is not a git repository\");\n break;\n case \"loading_commit_history\":\n logger.info(\"evolution: loading git history\");\n break;\n case \"history\":\n if (event.event.stage === \"git_log_received\") {\n logger.info(`evolution: git log loaded (${event.event.bytes} bytes)`);\n break;\n }\n\n if (event.event.stage === \"git_log_parsed\") {\n logger.info(`evolution: parsed ${event.event.commits} commits`);\n break;\n }\n\n if (\n event.event.stage === \"git_log_parse_progress\" &&\n (event.event.parsedRecords === event.event.totalRecords ||\n event.event.parsedRecords === 1 ||\n event.event.parsedRecords - lastParsedRecords >= 500)\n ) {\n lastParsedRecords = event.event.parsedRecords;\n const currentPercent =\n event.event.totalRecords === 0\n ? 100\n : Math.floor((event.event.parsedRecords / event.event.totalRecords) * 100);\n logger.info(\n `evolution: parse progress ${event.event.parsedRecords}/${event.event.totalRecords} (${currentPercent}%)`,\n );\n }\n break;\n case \"computing_metrics\":\n logger.info(\"evolution: computing metrics\");\n break;\n case \"analysis_completed\":\n logger.debug(`evolution: analysis completed (available=${event.available})`);\n break;\n }\n };\n};\n\nexport const runAnalyzeCommand = async (\n inputPath: string | undefined,\n authorIdentityMode: AuthorIdentityCliMode,\n logger: Logger = createSilentLogger(),\n): Promise<AnalyzeSummary> => {\n const invocationCwd = process.env[\"INIT_CWD\"] ?? process.cwd();\n const targetPath = resolveTargetPath(inputPath, invocationCwd);\n logger.info(`analyzing repository: ${targetPath}`);\n\n logger.info(\"building structural graph\");\n const structural = buildProjectGraphSummary({\n projectPath: targetPath,\n onProgress: createStructuralProgressReporter(logger),\n });\n logger.debug(\n `structural metrics: nodes=${structural.metrics.nodeCount}, edges=${structural.metrics.edgeCount}, cycles=${structural.metrics.cycleCount}`,\n );\n\n logger.info(`analyzing git evolution (author identity: ${authorIdentityMode})`);\n const evolution = analyzeRepositoryEvolutionFromGit({\n repositoryPath: targetPath,\n config: { authorIdentityMode },\n }, createEvolutionProgressReporter(logger));\n if (evolution.available) {\n logger.debug(\n `evolution metrics: commits=${evolution.metrics.totalCommits}, files=${evolution.metrics.totalFiles}, hotspotThreshold=${evolution.metrics.hotspotThresholdCommitCount}`,\n );\n } else {\n logger.warn(`evolution analysis unavailable: ${evolution.reason}`);\n }\n\n logger.info(\"analyzing external dependencies\");\n const external = await analyzeDependencyExposureFromProject(\n { repositoryPath: targetPath },\n createExternalProgressReporter(logger),\n );\n if (external.available) {\n logger.debug(\n `external metrics: total=${external.metrics.totalDependencies}, direct=${external.metrics.directDependencies}, transitive=${external.metrics.transitiveDependencies}`,\n );\n } else {\n logger.warn(`external analysis unavailable: ${external.reason}`);\n }\n\n logger.info(\"computing risk summary\");\n const risk = computeRepositoryRiskSummary({\n structural,\n evolution,\n external,\n });\n logger.info(`analysis completed (repositoryScore=${risk.repositoryScore})`);\n\n const summary: AnalyzeSummary = {\n structural,\n evolution,\n external,\n risk,\n };\n\n return summary;\n};\n","export type NodeRecord = {\n id: string;\n absolutePath: string;\n relativePath: string;\n};\n\nexport type EdgeRecord = {\n from: string;\n to: string;\n};\n\nexport type GraphData = {\n nodes: readonly NodeRecord[];\n edges: readonly EdgeRecord[];\n adjacencyById: ReadonlyMap<string, readonly string[]>;\n};\n\nconst edgeKey = (from: string, to: string): string => `${from}\\u0000${to}`;\n\nexport const createGraphData = (\n nodes: readonly NodeRecord[],\n rawEdges: readonly EdgeRecord[],\n): GraphData => {\n const sortedNodes = [...nodes].sort((a, b) => a.id.localeCompare(b.id));\n const knownNodeIds = new Set(sortedNodes.map((node) => node.id));\n\n const uniqueEdgeMap = new Map<string, EdgeRecord>();\n for (const edge of rawEdges) {\n if (edge.from === edge.to) {\n continue;\n }\n\n if (!knownNodeIds.has(edge.from) || !knownNodeIds.has(edge.to)) {\n continue;\n }\n\n uniqueEdgeMap.set(edgeKey(edge.from, edge.to), edge);\n }\n\n const sortedEdges = [...uniqueEdgeMap.values()].sort((a, b) => {\n const fromCompare = a.from.localeCompare(b.from);\n if (fromCompare !== 0) {\n return fromCompare;\n }\n\n return a.to.localeCompare(b.to);\n });\n\n const adjacency = new Map<string, string[]>();\n for (const node of sortedNodes) {\n adjacency.set(node.id, []);\n }\n\n for (const edge of sortedEdges) {\n adjacency.get(edge.from)?.push(edge.to);\n }\n\n const adjacencyById = new Map<string, readonly string[]>();\n for (const [nodeId, targets] of adjacency.entries()) {\n adjacencyById.set(nodeId, [...targets]);\n }\n\n return {\n nodes: sortedNodes,\n edges: sortedEdges,\n adjacencyById,\n };\n};\n","type TarjanResult = {\n components: readonly (readonly string[])[];\n};\n\nexport const runTarjanScc = (adjacencyById: ReadonlyMap<string, readonly string[]>): TarjanResult => {\n let index = 0;\n const indices = new Map<string, number>();\n const lowLink = new Map<string, number>();\n const stack: string[] = [];\n const onStack = new Set<string>();\n const components: string[][] = [];\n\n const strongConnect = (nodeId: string): void => {\n indices.set(nodeId, index);\n lowLink.set(nodeId, index);\n index += 1;\n\n stack.push(nodeId);\n onStack.add(nodeId);\n\n const neighbors = adjacencyById.get(nodeId) ?? [];\n for (const nextId of neighbors) {\n if (!indices.has(nextId)) {\n strongConnect(nextId);\n const nodeLowLink = lowLink.get(nodeId);\n const nextLowLink = lowLink.get(nextId);\n if (nodeLowLink !== undefined && nextLowLink !== undefined && nextLowLink < nodeLowLink) {\n lowLink.set(nodeId, nextLowLink);\n }\n continue;\n }\n\n if (onStack.has(nextId)) {\n const nodeLowLink = lowLink.get(nodeId);\n const nextIndex = indices.get(nextId);\n if (nodeLowLink !== undefined && nextIndex !== undefined && nextIndex < nodeLowLink) {\n lowLink.set(nodeId, nextIndex);\n }\n }\n }\n\n const nodeLowLink = lowLink.get(nodeId);\n const nodeIndex = indices.get(nodeId);\n if (nodeLowLink === undefined || nodeIndex === undefined || nodeLowLink !== nodeIndex) {\n return;\n }\n\n const component: string[] = [];\n for (;;) {\n const popped = stack.pop();\n if (popped === undefined) {\n break;\n }\n\n onStack.delete(popped);\n component.push(popped);\n if (popped === nodeId) {\n break;\n }\n }\n\n component.sort((a, b) => a.localeCompare(b));\n components.push(component);\n };\n\n const nodeIds = [...adjacencyById.keys()].sort((a, b) => a.localeCompare(b));\n for (const nodeId of nodeIds) {\n if (!indices.has(nodeId)) {\n strongConnect(nodeId);\n }\n }\n\n components.sort((a, b) => {\n const firstA = a[0] ?? \"\";\n const firstB = b[0] ?? \"\";\n return firstA.localeCompare(firstB);\n });\n\n return { components };\n};\n","import type { FileDependency, GraphAnalysisSummary, GraphCycle, GraphMetrics } from \"@codesentinel/core\";\nimport type { GraphData } from \"./graph-model.js\";\nimport { runTarjanScc } from \"./tarjan.js\";\n\ntype DepthComputation = {\n depthByNodeId: ReadonlyMap<string, number>;\n graphDepth: number;\n cycles: readonly GraphCycle[];\n};\n\nconst hasSelfLoop = (nodeId: string, adjacencyById: ReadonlyMap<string, readonly string[]>): boolean => {\n const targets = adjacencyById.get(nodeId) ?? [];\n return targets.includes(nodeId);\n};\n\nconst computeCyclesAndDepth = (graph: GraphData): DepthComputation => {\n const { components } = runTarjanScc(graph.adjacencyById);\n\n const cycles: GraphCycle[] = [];\n const componentByNodeId = new Map<string, number>();\n components.forEach((component, index) => {\n for (const nodeId of component) {\n componentByNodeId.set(nodeId, index);\n }\n\n if (component.length > 1) {\n cycles.push({ nodes: [...component] });\n return;\n }\n\n const onlyNode = component[0];\n if (onlyNode !== undefined && hasSelfLoop(onlyNode, graph.adjacencyById)) {\n cycles.push({ nodes: [...component] });\n }\n });\n\n const dagOutgoing = new Map<number, Set<number>>();\n const inDegree = new Map<number, number>();\n\n for (let i = 0; i < components.length; i += 1) {\n dagOutgoing.set(i, new Set());\n inDegree.set(i, 0);\n }\n\n for (const edge of graph.edges) {\n const fromComponent = componentByNodeId.get(edge.from);\n const toComponent = componentByNodeId.get(edge.to);\n\n if (fromComponent === undefined || toComponent === undefined || fromComponent === toComponent) {\n continue;\n }\n\n const outgoing = dagOutgoing.get(fromComponent);\n if (outgoing?.has(toComponent) === true) {\n continue;\n }\n\n outgoing?.add(toComponent);\n inDegree.set(toComponent, (inDegree.get(toComponent) ?? 0) + 1);\n }\n\n const queue: number[] = [];\n const depthByComponent = new Map<number, number>();\n\n for (let i = 0; i < components.length; i += 1) {\n if ((inDegree.get(i) ?? 0) === 0) {\n queue.push(i);\n depthByComponent.set(i, 0);\n }\n }\n\n let cursor = 0;\n while (cursor < queue.length) {\n const componentId = queue[cursor];\n cursor += 1;\n\n if (componentId === undefined) {\n continue;\n }\n\n const currentDepth = depthByComponent.get(componentId) ?? 0;\n const outgoing = dagOutgoing.get(componentId) ?? new Set<number>();\n\n for (const nextComponent of outgoing) {\n const nextDepth = depthByComponent.get(nextComponent) ?? 0;\n if (currentDepth + 1 > nextDepth) {\n depthByComponent.set(nextComponent, currentDepth + 1);\n }\n\n const remainingIncoming = (inDegree.get(nextComponent) ?? 0) - 1;\n inDegree.set(nextComponent, remainingIncoming);\n if (remainingIncoming === 0) {\n queue.push(nextComponent);\n }\n }\n }\n\n const depthByNodeId = new Map<string, number>();\n let graphDepth = 0;\n\n components.forEach((component, componentId) => {\n const componentDepth = depthByComponent.get(componentId) ?? 0;\n if (componentDepth > graphDepth) {\n graphDepth = componentDepth;\n }\n\n for (const nodeId of component) {\n depthByNodeId.set(nodeId, componentDepth);\n }\n });\n\n cycles.sort((a, b) => {\n const firstA = a.nodes[0] ?? \"\";\n const firstB = b.nodes[0] ?? \"\";\n return firstA.localeCompare(firstB);\n });\n\n return {\n depthByNodeId,\n graphDepth,\n cycles,\n };\n};\n\nexport const createGraphAnalysisSummary = (\n targetPath: string,\n graph: GraphData,\n): GraphAnalysisSummary => {\n const fanInById = new Map<string, number>();\n const fanOutById = new Map<string, number>();\n\n for (const node of graph.nodes) {\n fanInById.set(node.id, 0);\n fanOutById.set(node.id, graph.adjacencyById.get(node.id)?.length ?? 0);\n }\n\n for (const edge of graph.edges) {\n fanInById.set(edge.to, (fanInById.get(edge.to) ?? 0) + 1);\n }\n\n const { cycles, depthByNodeId, graphDepth } = computeCyclesAndDepth(graph);\n\n let maxFanIn = 0;\n let maxFanOut = 0;\n\n const files: FileDependency[] = graph.nodes.map((node) => {\n const fanIn = fanInById.get(node.id) ?? 0;\n const fanOut = fanOutById.get(node.id) ?? 0;\n\n if (fanIn > maxFanIn) {\n maxFanIn = fanIn;\n }\n\n if (fanOut > maxFanOut) {\n maxFanOut = fanOut;\n }\n\n return {\n id: node.id,\n relativePath: node.relativePath,\n directDependencies: graph.adjacencyById.get(node.id) ?? [],\n fanIn,\n fanOut,\n depth: depthByNodeId.get(node.id) ?? 0,\n };\n });\n\n const metrics: GraphMetrics = {\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n cycleCount: cycles.length,\n graphDepth,\n maxFanIn,\n maxFanOut,\n };\n\n return {\n targetPath,\n nodes: graph.nodes,\n edges: graph.edges,\n cycles,\n files,\n metrics,\n };\n};\n","import { extname, isAbsolute, relative, resolve } from \"node:path\";\nimport * as ts from \"typescript\";\nimport type { EdgeRecord, NodeRecord } from \"../domain/graph-model.js\";\n\ntype ParsedProject = {\n nodes: readonly NodeRecord[];\n edges: readonly EdgeRecord[];\n};\n\nexport type ParseTypescriptProjectProgressEvent =\n | { stage: \"config_resolved\"; tsconfigCount: number; usedFallbackScan: boolean }\n | { stage: \"files_discovered\"; totalSourceFiles: number }\n | { stage: \"program_created\"; totalSourceFiles: number }\n | { stage: \"file_processed\"; processed: number; total: number; filePath: string }\n | { stage: \"edges_resolved\"; totalEdges: number };\n\nconst SOURCE_EXTENSIONS = new Set([\".ts\", \".tsx\", \".mts\", \".cts\", \".js\", \".jsx\", \".mjs\", \".cjs\"]);\nconst SCAN_EXCLUDES = [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.next/**\",\n \"**/coverage/**\",\n \"**/.turbo/**\",\n \"**/.cache/**\",\n \"**/out/**\",\n];\nconst SCAN_INCLUDES = [\"**/*\"];\nconst IGNORED_SEGMENTS = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \"coverage\",\n \".turbo\",\n \".cache\",\n \"out\",\n]);\n\nconst normalizePath = (pathValue: string): string => pathValue.replaceAll(\"\\\\\", \"/\");\n\nconst isProjectSourceFile = (filePath: string, projectRoot: string): boolean => {\n const extension = extname(filePath);\n if (!SOURCE_EXTENSIONS.has(extension)) {\n return false;\n }\n\n const relativePath = relative(projectRoot, filePath);\n if (relativePath.startsWith(\"..\")) {\n return false;\n }\n\n const normalizedRelativePath = normalizePath(relativePath);\n const segments = normalizedRelativePath.split(\"/\");\n return !segments.some((segment) => IGNORED_SEGMENTS.has(segment));\n};\n\nconst discoverSourceFilesByScan = (projectRoot: string): readonly string[] => {\n const files = ts.sys.readDirectory(\n projectRoot,\n [...SOURCE_EXTENSIONS],\n SCAN_EXCLUDES,\n SCAN_INCLUDES,\n );\n return files.map((filePath) => resolve(filePath));\n};\n\nconst parseTsConfigFile = (configPath: string): ts.ParsedCommandLine => {\n const parsedCommandLine = ts.getParsedCommandLineOfConfigFile(\n configPath,\n {},\n {\n ...ts.sys,\n onUnRecoverableConfigFileDiagnostic: () => {\n throw new Error(`Failed to parse TypeScript configuration at ${configPath}`);\n },\n },\n );\n\n if (parsedCommandLine === undefined) {\n throw new Error(`Failed to parse TypeScript configuration at ${configPath}`);\n }\n\n return parsedCommandLine;\n};\n\ntype CollectedTsConfigData = {\n fileNames: readonly string[];\n rootOptions: ts.CompilerOptions;\n visitedConfigCount: number;\n};\n\nconst collectFilesFromTsConfigGraph = (\n projectRoot: string,\n): CollectedTsConfigData | null => {\n const rootConfigPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, \"tsconfig.json\");\n if (rootConfigPath === undefined) {\n return null;\n }\n\n const visitedConfigPaths = new Set<string>();\n const collectedFiles = new Set<string>();\n let rootOptions: ts.CompilerOptions | null = null;\n\n const visitConfig = (configPath: string): void => {\n const absoluteConfigPath = resolve(configPath);\n if (visitedConfigPaths.has(absoluteConfigPath)) {\n return;\n }\n\n visitedConfigPaths.add(absoluteConfigPath);\n const parsed = parseTsConfigFile(absoluteConfigPath);\n if (rootOptions === null) {\n rootOptions = parsed.options;\n }\n\n for (const filePath of parsed.fileNames) {\n collectedFiles.add(resolve(filePath));\n }\n\n for (const reference of parsed.projectReferences ?? []) {\n const referencePath = resolve(reference.path);\n const referenceConfigPath = ts.sys.directoryExists(referencePath)\n ? ts.findConfigFile(referencePath, ts.sys.fileExists, \"tsconfig.json\")\n : referencePath;\n\n if (referenceConfigPath !== undefined && ts.sys.fileExists(referenceConfigPath)) {\n visitConfig(referenceConfigPath);\n }\n }\n };\n\n visitConfig(rootConfigPath);\n\n return {\n fileNames: [...collectedFiles],\n rootOptions:\n rootOptions ?? {\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n },\n visitedConfigCount: visitedConfigPaths.size,\n };\n};\n\nconst createCompilerOptions = (base: ts.CompilerOptions | undefined): ts.CompilerOptions => ({\n ...base,\n allowJs: true,\n moduleResolution: base?.moduleResolution ?? ts.ModuleResolutionKind.NodeNext,\n});\n\nconst parseTsConfig = (\n projectRoot: string,\n): {\n fileNames: readonly string[];\n options: ts.CompilerOptions;\n tsconfigCount: number;\n usedFallbackScan: boolean;\n} => {\n const collected = collectFilesFromTsConfigGraph(projectRoot);\n if (collected === null) {\n return {\n fileNames: discoverSourceFilesByScan(projectRoot),\n options: createCompilerOptions(undefined),\n tsconfigCount: 0,\n usedFallbackScan: true,\n };\n }\n\n if (collected.fileNames.length === 0) {\n return {\n fileNames: discoverSourceFilesByScan(projectRoot),\n options: createCompilerOptions(collected.rootOptions),\n tsconfigCount: collected.visitedConfigCount,\n usedFallbackScan: true,\n };\n }\n\n return {\n fileNames: collected.fileNames,\n options: createCompilerOptions(collected.rootOptions),\n tsconfigCount: collected.visitedConfigCount,\n usedFallbackScan: false,\n };\n};\n\nconst getSpecifierFromExpression = (expression: ts.Expression): string | undefined => {\n if (ts.isStringLiteral(expression)) {\n return expression.text;\n }\n\n if (ts.isNoSubstitutionTemplateLiteral(expression)) {\n return expression.text;\n }\n\n return undefined;\n};\n\nconst hasRuntimeImport = (importDeclaration: ts.ImportDeclaration): boolean => {\n const importClause = importDeclaration.importClause;\n if (importClause === undefined) {\n return true;\n }\n\n if (importClause.isTypeOnly) {\n return false;\n }\n\n if (importClause.name !== undefined) {\n return true;\n }\n\n const namedBindings = importClause.namedBindings;\n if (namedBindings === undefined) {\n return false;\n }\n\n if (ts.isNamespaceImport(namedBindings)) {\n return true;\n }\n\n if (namedBindings.elements.length === 0) {\n return true;\n }\n\n return namedBindings.elements.some((element) => !element.isTypeOnly);\n};\n\nconst extractModuleSpecifiers = (sourceFile: ts.SourceFile): readonly string[] => {\n const specifiers = new Set<string>();\n\n const visit = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node)) {\n if (hasRuntimeImport(node) && node.moduleSpecifier !== undefined) {\n const specifier = getSpecifierFromExpression(node.moduleSpecifier);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n return;\n }\n\n if (ts.isExportDeclaration(node)) {\n if (!node.isTypeOnly && node.moduleSpecifier !== undefined) {\n const specifier = getSpecifierFromExpression(node.moduleSpecifier);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n return;\n }\n\n if (ts.isCallExpression(node)) {\n if (node.expression.kind === ts.SyntaxKind.ImportKeyword && node.arguments.length > 0) {\n const firstArgument = node.arguments[0];\n if (firstArgument !== undefined) {\n const specifier = getSpecifierFromExpression(firstArgument);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n }\n\n if (ts.isIdentifier(node.expression) && node.expression.text === \"require\" && node.arguments.length > 0) {\n const firstArgument = node.arguments[0];\n if (firstArgument !== undefined) {\n const specifier = getSpecifierFromExpression(firstArgument);\n if (specifier !== undefined) {\n specifiers.add(specifier);\n }\n }\n }\n }\n\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return [...specifiers];\n};\n\nexport const parseTypescriptProject = (\n projectPath: string,\n onProgress?: (event: ParseTypescriptProjectProgressEvent) => void,\n): ParsedProject => {\n const projectRoot = isAbsolute(projectPath) ? projectPath : resolve(projectPath);\n const { fileNames, options, tsconfigCount, usedFallbackScan } = parseTsConfig(projectRoot);\n onProgress?.({ stage: \"config_resolved\", tsconfigCount, usedFallbackScan });\n\n const sourceFilePaths = fileNames\n .filter((filePath) => isProjectSourceFile(filePath, projectRoot))\n .map((filePath) => normalizePath(resolve(filePath)));\n\n const uniqueSourceFilePaths = [...new Set(sourceFilePaths)].sort((a, b) => a.localeCompare(b));\n const sourceFilePathSet = new Set(uniqueSourceFilePaths);\n onProgress?.({ stage: \"files_discovered\", totalSourceFiles: uniqueSourceFilePaths.length });\n\n const program = ts.createProgram({\n rootNames: uniqueSourceFilePaths,\n options,\n });\n onProgress?.({ stage: \"program_created\", totalSourceFiles: uniqueSourceFilePaths.length });\n\n const nodeByAbsolutePath = new Map<string, NodeRecord>();\n for (const sourcePath of uniqueSourceFilePaths) {\n const relativePath = normalizePath(relative(projectRoot, sourcePath));\n const nodeId = relativePath;\n nodeByAbsolutePath.set(sourcePath, {\n id: nodeId,\n absolutePath: sourcePath,\n relativePath,\n });\n }\n\n const resolverCache = new Map<string, string | undefined>();\n const edges: EdgeRecord[] = [];\n\n for (const [index, sourcePath] of uniqueSourceFilePaths.entries()) {\n const sourceFile = program.getSourceFile(sourcePath);\n if (sourceFile === undefined) {\n continue;\n }\n\n const fromNode = nodeByAbsolutePath.get(sourcePath);\n if (fromNode === undefined) {\n continue;\n }\n\n const moduleSpecifiers = extractModuleSpecifiers(sourceFile);\n for (const specifier of moduleSpecifiers) {\n const cacheKey = `${sourcePath}\\u0000${specifier}`;\n let resolvedPath = resolverCache.get(cacheKey);\n\n if (resolvedPath === undefined && !resolverCache.has(cacheKey)) {\n const resolved = ts.resolveModuleName(specifier, sourcePath, options, ts.sys).resolvedModule;\n if (resolved !== undefined) {\n resolvedPath = normalizePath(resolve(resolved.resolvedFileName));\n }\n resolverCache.set(cacheKey, resolvedPath);\n }\n\n if (resolvedPath === undefined || !sourceFilePathSet.has(resolvedPath)) {\n continue;\n }\n\n const toNode = nodeByAbsolutePath.get(resolvedPath);\n if (toNode === undefined) {\n continue;\n }\n\n edges.push({ from: fromNode.id, to: toNode.id });\n }\n\n const processed = index + 1;\n if (processed === 1 || processed === uniqueSourceFilePaths.length || processed % 50 === 0) {\n onProgress?.({\n stage: \"file_processed\",\n processed,\n total: uniqueSourceFilePaths.length,\n filePath: fromNode.id,\n });\n }\n }\n onProgress?.({ stage: \"edges_resolved\", totalEdges: edges.length });\n\n return {\n nodes: [...nodeByAbsolutePath.values()],\n edges,\n };\n};\n","import type { GraphAnalysisSummary } from \"@codesentinel/core\";\nimport { createGraphData } from \"../domain/graph-model.js\";\nimport { createGraphAnalysisSummary } from \"../domain/graph-metrics.js\";\nimport {\n parseTypescriptProject,\n type ParseTypescriptProjectProgressEvent,\n} from \"../infrastructure/typescript-project.js\";\n\nexport type BuildProjectGraphSummaryInput = {\n projectPath: string;\n onProgress?: (event: ParseTypescriptProjectProgressEvent) => void;\n};\n\nexport const buildProjectGraphSummary = (\n input: BuildProjectGraphSummaryInput,\n): GraphAnalysisSummary => {\n const parsedProject = parseTypescriptProject(input.projectPath, input.onProgress);\n const graphData = createGraphData(parsedProject.nodes, parsedProject.edges);\n return createGraphAnalysisSummary(input.projectPath, graphData);\n};\n","import type {\n CentralDependency,\n DependencyExposureRecord,\n DependencyRiskSignal,\n ExternalAnalysisSummary,\n} from \"@codesentinel/core\";\nimport type {\n DependencyMetadata,\n ExternalAnalysisConfig,\n LockfileExtraction,\n LockedDependencyNode,\n} from \"./types.js\";\n\nconst round4 = (value: number): number => Number(value.toFixed(4));\n\ntype NormalizedNode = {\n key: string;\n name: string;\n version: string;\n dependencies: readonly string[];\n};\n\nconst normalizeNodes = (nodes: readonly LockedDependencyNode[]): readonly NormalizedNode[] => {\n const byName = new Map<string, LockedDependencyNode[]>();\n\n for (const node of nodes) {\n const bucket = byName.get(node.name) ?? [];\n bucket.push(node);\n byName.set(node.name, bucket);\n }\n\n const normalized: NormalizedNode[] = [];\n\n for (const [name, candidates] of byName.entries()) {\n if (candidates.length === 0) {\n continue;\n }\n\n candidates.sort((a, b) => b.version.localeCompare(a.version));\n const selected = candidates[0];\n if (selected === undefined) {\n continue;\n }\n\n const deps = selected.dependencies\n .map((dep) => {\n const at = dep.lastIndexOf(\"@\");\n return at <= 0 ? dep : dep.slice(0, at);\n })\n .filter((depName) => depName.length > 0)\n .sort((a, b) => a.localeCompare(b));\n\n normalized.push({\n key: `${name}@${selected.version}`,\n name,\n version: selected.version,\n dependencies: deps,\n });\n }\n\n return normalized.sort((a, b) => a.name.localeCompare(b.name));\n};\n\nconst computeDepths = (\n nodeByName: ReadonlyMap<string, NormalizedNode>,\n directNames: ReadonlySet<string>,\n): { depthByName: ReadonlyMap<string, number>; maxDepth: number } => {\n const visiting = new Set<string>();\n const depthByName = new Map<string, number>();\n\n const compute = (name: string): number => {\n const known = depthByName.get(name);\n if (known !== undefined) {\n return known;\n }\n\n if (visiting.has(name)) {\n return 0;\n }\n\n visiting.add(name);\n\n const node = nodeByName.get(name);\n if (node === undefined) {\n visiting.delete(name);\n depthByName.set(name, 0);\n return 0;\n }\n\n let maxChildDepth = 0;\n for (const dependencyName of node.dependencies) {\n const childDepth = compute(dependencyName);\n if (childDepth > maxChildDepth) {\n maxChildDepth = childDepth;\n }\n }\n\n visiting.delete(name);\n const ownDepth = directNames.has(name) ? 0 : maxChildDepth + 1;\n depthByName.set(name, ownDepth);\n return ownDepth;\n };\n\n for (const name of nodeByName.keys()) {\n compute(name);\n }\n\n let maxDepth = 0;\n for (const depth of depthByName.values()) {\n if (depth > maxDepth) {\n maxDepth = depth;\n }\n }\n\n return { depthByName, maxDepth };\n};\n\nconst rankCentrality = (\n nodes: readonly NormalizedNode[],\n dependentsByName: ReadonlyMap<string, number>,\n directNames: ReadonlySet<string>,\n topN: number,\n): readonly CentralDependency[] =>\n [...nodes]\n .map((node) => ({\n name: node.name,\n dependents: dependentsByName.get(node.name) ?? 0,\n fanOut: node.dependencies.length,\n direct: directNames.has(node.name),\n }))\n .sort(\n (a, b) =>\n b.dependents - a.dependents ||\n b.fanOut - a.fanOut ||\n a.name.localeCompare(b.name),\n )\n .slice(0, topN);\n\nconst canPropagateSignal = (signal: DependencyRiskSignal): boolean =>\n signal === \"abandoned\" ||\n signal === \"high_centrality\" ||\n signal === \"deep_chain\" ||\n signal === \"high_fanout\";\n\nconst collectTransitiveDependencies = (\n rootName: string,\n nodeByName: ReadonlyMap<string, NormalizedNode>,\n): readonly string[] => {\n const seen = new Set<string>();\n const stack = [...(nodeByName.get(rootName)?.dependencies ?? [])];\n\n while (stack.length > 0) {\n const current = stack.pop();\n if (current === undefined || seen.has(current) || current === rootName) {\n continue;\n }\n\n seen.add(current);\n const currentNode = nodeByName.get(current);\n if (currentNode === undefined) {\n continue;\n }\n\n for (const next of currentNode.dependencies) {\n if (!seen.has(next)) {\n stack.push(next);\n }\n }\n }\n\n return [...seen].sort((a, b) => a.localeCompare(b));\n};\n\nexport const buildExternalAnalysisSummary = (\n targetPath: string,\n extraction: LockfileExtraction,\n metadataByKey: ReadonlyMap<string, DependencyMetadata | null>,\n config: ExternalAnalysisConfig,\n): ExternalAnalysisSummary => {\n const nodes = normalizeNodes(extraction.nodes);\n const directNames = new Set(extraction.directDependencies.map((dep) => dep.name));\n const directSpecByName = new Map(extraction.directDependencies.map((dep) => [dep.name, dep.requestedRange]));\n\n const nodeByName = new Map(nodes.map((node) => [node.name, node]));\n const dependentsByName = new Map<string, number>();\n\n for (const node of nodes) {\n dependentsByName.set(node.name, dependentsByName.get(node.name) ?? 0);\n }\n\n for (const node of nodes) {\n for (const dependencyName of node.dependencies) {\n if (!nodeByName.has(dependencyName)) {\n continue;\n }\n\n dependentsByName.set(dependencyName, (dependentsByName.get(dependencyName) ?? 0) + 1);\n }\n }\n\n const { depthByName, maxDepth } = computeDepths(nodeByName, directNames);\n const centralityRanking = rankCentrality(nodes, dependentsByName, directNames, config.centralityTopN);\n\n const topCentralNames = new Set(\n centralityRanking\n .slice(0, Math.max(1, Math.ceil(centralityRanking.length * 0.25)))\n .map((entry) => entry.name),\n );\n\n const allDependencies: DependencyExposureRecord[] = [];\n let metadataAvailableCount = 0;\n\n for (const node of nodes) {\n const metadata = metadataByKey.get(node.key) ?? null;\n if (metadata !== null) {\n metadataAvailableCount += 1;\n }\n\n const dependencyDepth = depthByName.get(node.name) ?? 0;\n const dependents = dependentsByName.get(node.name) ?? 0;\n\n const riskSignals: DependencyRiskSignal[] = [];\n\n if ((metadata?.maintainerCount ?? 0) === 1) {\n riskSignals.push(\"single_maintainer\");\n }\n\n if ((metadata?.daysSinceLastRelease ?? 0) >= config.abandonedDaysThreshold) {\n riskSignals.push(\"abandoned\");\n }\n\n if (topCentralNames.has(node.name) && dependents > 0) {\n riskSignals.push(\"high_centrality\");\n }\n\n if (dependencyDepth >= config.deepChainThreshold) {\n riskSignals.push(\"deep_chain\");\n }\n\n if (node.dependencies.length >= config.fanOutHighThreshold) {\n riskSignals.push(\"high_fanout\");\n }\n\n if (metadata === null) {\n riskSignals.push(\"metadata_unavailable\");\n }\n\n allDependencies.push({\n name: node.name,\n direct: directNames.has(node.name),\n requestedRange: directSpecByName.get(node.name) ?? null,\n resolvedVersion: node.version,\n transitiveDependencies: [],\n dependencyDepth,\n fanOut: node.dependencies.length,\n dependents,\n maintainerCount: metadata?.maintainerCount ?? null,\n releaseFrequencyDays: metadata?.releaseFrequencyDays ?? null,\n daysSinceLastRelease: metadata?.daysSinceLastRelease ?? null,\n repositoryActivity30d: metadata?.repositoryActivity30d ?? null,\n busFactor: metadata?.busFactor ?? null,\n ownRiskSignals: [...riskSignals].sort((a, b) => a.localeCompare(b)),\n inheritedRiskSignals: [],\n riskSignals,\n });\n }\n\n allDependencies.sort((a, b) => a.name.localeCompare(b.name));\n\n const allByName = new Map(allDependencies.map((dep) => [dep.name, dep]));\n\n const dependencies: DependencyExposureRecord[] = allDependencies\n .filter((dep) => dep.direct)\n .map((dep) => {\n const transitiveDependencies = collectTransitiveDependencies(dep.name, nodeByName);\n const inheritedSignals = new Set<DependencyRiskSignal>();\n const allSignals = new Set(dep.ownRiskSignals);\n\n for (const transitiveName of transitiveDependencies) {\n const transitive = allByName.get(transitiveName);\n if (transitive === undefined) {\n continue;\n }\n\n for (const signal of transitive.riskSignals) {\n if (canPropagateSignal(signal)) {\n inheritedSignals.add(signal);\n allSignals.add(signal);\n }\n }\n }\n\n return {\n ...dep,\n transitiveDependencies,\n inheritedRiskSignals: [...inheritedSignals].sort((a, b) => a.localeCompare(b)),\n riskSignals: [...allSignals].sort((a, b) => a.localeCompare(b)),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const highRiskDependencies = dependencies\n .filter((dep) => dep.riskSignals.length > 1)\n .sort((a, b) => b.riskSignals.length - a.riskSignals.length || a.name.localeCompare(b.name))\n .slice(0, config.maxHighRiskDependencies)\n .map((dep) => dep.name);\n\n const singleMaintainerDependencies = dependencies\n .filter((dep) => dep.ownRiskSignals.includes(\"single_maintainer\"))\n .map((dep) => dep.name)\n .sort((a, b) => a.localeCompare(b));\n\n const abandonedDependencies = dependencies\n .filter((dep) => dep.ownRiskSignals.includes(\"abandoned\"))\n .map((dep) => dep.name)\n .sort((a, b) => a.localeCompare(b));\n\n return {\n targetPath,\n available: true,\n metrics: {\n totalDependencies: allDependencies.length,\n directDependencies: dependencies.length,\n transitiveDependencies: allDependencies.length - dependencies.length,\n dependencyDepth: maxDepth,\n lockfileKind: extraction.kind,\n metadataCoverage: allDependencies.length === 0 ? 0 : round4(metadataAvailableCount / allDependencies.length),\n },\n dependencies,\n highRiskDependencies,\n singleMaintainerDependencies,\n abandonedDependencies,\n centralityRanking,\n };\n};\n","export type LockfileKind = \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\";\n\nexport type DirectDependencySpec = {\n name: string;\n requestedRange: string;\n};\n\nexport type LockedDependencyNode = {\n name: string;\n version: string;\n dependencies: readonly string[];\n};\n\nexport type LockfileExtraction = {\n kind: LockfileKind;\n directDependencies: readonly DirectDependencySpec[];\n nodes: readonly LockedDependencyNode[];\n};\n\nexport type DependencyMetadata = {\n name: string;\n version: string;\n maintainerCount: number | null;\n releaseFrequencyDays: number | null;\n daysSinceLastRelease: number | null;\n repositoryActivity30d: number | null;\n busFactor: number | null;\n};\n\nexport interface DependencyMetadataProvider {\n getMetadata(name: string, version: string): Promise<DependencyMetadata | null>;\n}\n\nexport type ExternalAnalysisConfig = {\n abandonedDaysThreshold: number;\n deepChainThreshold: number;\n fanOutHighThreshold: number;\n centralityTopN: number;\n maxHighRiskDependencies: number;\n metadataRequestConcurrency: number;\n};\n\nexport const DEFAULT_EXTERNAL_ANALYSIS_CONFIG: ExternalAnalysisConfig = {\n abandonedDaysThreshold: 540,\n deepChainThreshold: 6,\n fanOutHighThreshold: 25,\n centralityTopN: 20,\n maxHighRiskDependencies: 100,\n metadataRequestConcurrency: 8,\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type RepositoryFiles = {\n packageJsonPath: string;\n packageJsonRaw: string;\n lockfilePath: string;\n lockfileRaw: string;\n};\n\nconst LOCKFILE_CANDIDATES: readonly { fileName: string; kind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\" }[] = [\n { fileName: \"pnpm-lock.yaml\", kind: \"pnpm\" },\n { fileName: \"package-lock.json\", kind: \"npm\" },\n { fileName: \"npm-shrinkwrap.json\", kind: \"npm-shrinkwrap\" },\n { fileName: \"yarn.lock\", kind: \"yarn\" },\n { fileName: \"bun.lock\", kind: \"bun\" },\n { fileName: \"bun.lockb\", kind: \"bun\" },\n];\n\nexport type LockfileSelection = {\n path: string;\n kind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\";\n raw: string;\n};\n\nexport const loadPackageJson = (repositoryPath: string): { path: string; raw: string } | null => {\n const packageJsonPath = join(repositoryPath, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return null;\n }\n\n return {\n path: packageJsonPath,\n raw: readFileSync(packageJsonPath, \"utf8\"),\n };\n};\n\nexport const selectLockfile = (repositoryPath: string): LockfileSelection | null => {\n for (const candidate of LOCKFILE_CANDIDATES) {\n const absolutePath = join(repositoryPath, candidate.fileName);\n if (!existsSync(absolutePath)) {\n continue;\n }\n\n return {\n path: absolutePath,\n kind: candidate.kind,\n raw: readFileSync(absolutePath, \"utf8\"),\n };\n }\n\n return null;\n};\n","import type { DirectDependencySpec } from \"../domain/types.js\";\n\ntype ParsedPackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\nexport const parsePackageJson = (raw: string): readonly DirectDependencySpec[] => {\n const parsed = JSON.parse(raw) as ParsedPackageJson;\n const merged = new Map<string, string>();\n\n for (const block of [\n parsed.dependencies,\n parsed.devDependencies,\n parsed.optionalDependencies,\n parsed.peerDependencies,\n ]) {\n if (block === undefined) {\n continue;\n }\n\n for (const [name, versionRange] of Object.entries(block)) {\n merged.set(name, versionRange);\n }\n }\n\n return [...merged.entries()]\n .map(([name, requestedRange]) => ({ name, requestedRange }))\n .sort((a, b) => a.name.localeCompare(b.name));\n};\n","import type { DirectDependencySpec, LockfileExtraction, LockedDependencyNode } from \"../domain/types.js\";\n\ntype PackageLockNode = {\n version?: string;\n dependencies?: Record<string, string>;\n};\n\ntype PackageLockShape = {\n lockfileVersion?: number;\n packages?: Record<string, PackageLockNode>;\n dependencies?: Record<string, { version?: string; dependencies?: Record<string, unknown> }>;\n};\n\nexport const parsePackageLock = (raw: string, directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n const parsed = JSON.parse(raw) as PackageLockShape;\n const nodes: LockedDependencyNode[] = [];\n\n if (parsed.packages !== undefined) {\n for (const [packagePath, packageData] of Object.entries(parsed.packages)) {\n if (packagePath.length === 0 || packageData.version === undefined) {\n continue;\n }\n\n const segments = packagePath.split(\"node_modules/\");\n const name = segments[segments.length - 1] ?? \"\";\n if (name.length === 0) {\n continue;\n }\n\n const dependencies = Object.entries(packageData.dependencies ?? {})\n .map(([depName, depRange]) => `${depName}@${String(depRange)}`)\n .sort((a, b) => a.localeCompare(b));\n\n nodes.push({\n name,\n version: packageData.version,\n dependencies,\n });\n }\n } else if (parsed.dependencies !== undefined) {\n for (const [name, dep] of Object.entries(parsed.dependencies)) {\n if (dep.version === undefined) {\n continue;\n }\n\n const dependencies = Object.entries(dep.dependencies ?? {})\n .map(([depName, depVersion]) => `${depName}@${String(depVersion)}`)\n .sort((a, b) => a.localeCompare(b));\n\n nodes.push({\n name,\n version: dep.version,\n dependencies,\n });\n }\n }\n\n nodes.sort((a, b) => a.name.localeCompare(b.name) || a.version.localeCompare(b.version));\n\n return {\n kind: \"npm\",\n directDependencies: directSpecs,\n nodes,\n };\n};\n","import type { DirectDependencySpec, LockfileExtraction, LockedDependencyNode } from \"../domain/types.js\";\n\ntype ParserState = \"root\" | \"importers\" | \"packages\" | \"packageDeps\";\n\nconst sanitizeValue = (value: string): string => value.replace(/^['\"]|['\"]$/g, \"\").trim();\n\nconst parsePackageKey = (rawKey: string): { name: string; version: string } | null => {\n const key = sanitizeValue(rawKey.replace(/:$/, \"\"));\n const withoutSlash = key.startsWith(\"/\") ? key.slice(1) : key;\n\n const lastAt = withoutSlash.lastIndexOf(\"@\");\n if (lastAt <= 0) {\n return null;\n }\n\n const name = withoutSlash.slice(0, lastAt);\n const versionWithPeers = withoutSlash.slice(lastAt + 1);\n const version = versionWithPeers.split(\"(\")[0] ?? versionWithPeers;\n\n if (name.length === 0 || version.length === 0) {\n return null;\n }\n\n return { name, version };\n};\n\nexport const parsePnpmLockfile = (raw: string, directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n const lines = raw.split(\"\\n\");\n let state: ParserState = \"root\";\n let currentPackage: string | null = null;\n let currentDependencyName: string | null = null;\n const dependenciesByNode = new Map<string, Set<string>>();\n\n for (const line of lines) {\n if (line.trim().length === 0 || line.trimStart().startsWith(\"#\")) {\n continue;\n }\n\n if (line.startsWith(\"importers:\")) {\n state = \"importers\";\n continue;\n }\n\n if (line.startsWith(\"packages:\")) {\n state = \"packages\";\n continue;\n }\n\n if (state === \"packages\" || state === \"packageDeps\") {\n const packageMatch = line.match(/^\\s{2}([^\\s].+):\\s*$/);\n if (packageMatch !== null) {\n const parsedKey = parsePackageKey(packageMatch[1] ?? \"\");\n if (parsedKey !== null) {\n currentPackage = `${parsedKey.name}@${parsedKey.version}`;\n dependenciesByNode.set(currentPackage, new Set());\n state = \"packageDeps\";\n currentDependencyName = null;\n }\n continue;\n }\n }\n\n if (state === \"packageDeps\" && currentPackage !== null) {\n const depLine = line.match(/^\\s{6}([^:\\s]+):\\s*(.+)$/);\n if (depLine !== null) {\n const depName = sanitizeValue(depLine[1] ?? \"\");\n const depRef = sanitizeValue(depLine[2] ?? \"\");\n const depVersion = depRef.split(\"(\")[0] ?? depRef;\n\n if (depName.length > 0 && depVersion.length > 0) {\n dependenciesByNode.get(currentPackage)?.add(`${depName}@${depVersion}`);\n }\n currentDependencyName = null;\n continue;\n }\n\n const depBlockLine = line.match(/^\\s{6}([^:\\s]+):\\s*$/);\n if (depBlockLine !== null) {\n currentDependencyName = sanitizeValue(depBlockLine[1] ?? \"\");\n continue;\n }\n\n const depVersionLine = line.match(/^\\s{8}version:\\s*(.+)$/);\n if (depVersionLine !== null && currentDependencyName !== null) {\n const depRef = sanitizeValue(depVersionLine[1] ?? \"\");\n const depVersion = depRef.split(\"(\")[0] ?? depRef;\n if (depVersion.length > 0) {\n dependenciesByNode.get(currentPackage)?.add(`${currentDependencyName}@${depVersion}`);\n }\n currentDependencyName = null;\n continue;\n }\n\n if (line.match(/^\\s{4}(dependencies|optionalDependencies):\\s*$/) !== null) {\n continue;\n }\n }\n }\n\n const nodes: LockedDependencyNode[] = [...dependenciesByNode.entries()]\n .map(([nodeId, deps]) => {\n const at = nodeId.lastIndexOf(\"@\");\n return {\n name: nodeId.slice(0, at),\n version: nodeId.slice(at + 1),\n dependencies: [...deps].sort((a, b) => a.localeCompare(b)),\n };\n })\n .sort((a, b) =>\n a.name.localeCompare(b.name) || a.version.localeCompare(b.version),\n );\n\n return {\n kind: \"pnpm\",\n directDependencies: directSpecs,\n nodes,\n };\n};\n","import type { DirectDependencySpec, LockfileExtraction, LockedDependencyNode } from \"../domain/types.js\";\n\nconst stripQuotes = (value: string): string => value.replace(/^['\"]|['\"]$/g, \"\");\n\nconst parseVersionSelector = (selector: string): string | null => {\n const npmIndex = selector.lastIndexOf(\"@npm:\");\n if (npmIndex >= 0) {\n return selector.slice(npmIndex + 5);\n }\n\n const lastAt = selector.lastIndexOf(\"@\");\n if (lastAt <= 0) {\n return null;\n }\n\n return selector.slice(lastAt + 1);\n};\n\nexport const parseYarnLock = (raw: string, directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n const lines = raw.split(\"\\n\");\n const nodes: LockedDependencyNode[] = [];\n\n let selectors: string[] = [];\n let version: string | null = null;\n let readingDependencies = false;\n let dependencies: string[] = [];\n\n const flushEntry = (): void => {\n if (selectors.length === 0 || version === null) {\n selectors = [];\n version = null;\n dependencies = [];\n readingDependencies = false;\n return;\n }\n\n for (const selector of selectors) {\n const parsedVersion = parseVersionSelector(selector);\n const at = selector.lastIndexOf(\"@\");\n const name = at <= 0 ? selector : selector.slice(0, at);\n if (name.length === 0) {\n continue;\n }\n\n nodes.push({\n name,\n version,\n dependencies: [...dependencies].sort((a, b) => a.localeCompare(b)),\n });\n\n if (parsedVersion !== null) {\n nodes.push({\n name,\n version: parsedVersion,\n dependencies: [...dependencies].sort((a, b) => a.localeCompare(b)),\n });\n }\n }\n\n selectors = [];\n version = null;\n dependencies = [];\n readingDependencies = false;\n };\n\n for (const line of lines) {\n if (line.trim().length === 0) {\n continue;\n }\n\n if (!line.startsWith(\" \") && line.endsWith(\":\")) {\n flushEntry();\n const keyText = line.slice(0, -1);\n selectors = keyText\n .split(\",\")\n .map((part) => stripQuotes(part.trim()))\n .filter((part) => part.length > 0);\n continue;\n }\n\n if (line.match(/^\\s{2}version\\s+/) !== null) {\n const value = line.replace(/^\\s{2}version\\s+/, \"\").trim();\n version = stripQuotes(value);\n readingDependencies = false;\n continue;\n }\n\n if (line.match(/^\\s{2}dependencies:\\s*$/) !== null) {\n readingDependencies = true;\n continue;\n }\n\n if (readingDependencies && line.match(/^\\s{4}[^\\s].+$/) !== null) {\n const depLine = line.trim();\n const firstSpace = depLine.indexOf(\" \");\n if (firstSpace <= 0) {\n continue;\n }\n\n const depName = stripQuotes(depLine.slice(0, firstSpace));\n const depRef = stripQuotes(depLine.slice(firstSpace + 1).trim());\n const depVersion = parseVersionSelector(depRef) ?? depRef;\n dependencies.push(`${depName}@${depVersion}`);\n continue;\n }\n\n readingDependencies = false;\n }\n\n flushEntry();\n\n const deduped = new Map<string, LockedDependencyNode>();\n for (const node of nodes) {\n const key = `${node.name}@${node.version}`;\n if (!deduped.has(key)) {\n deduped.set(key, node);\n }\n }\n\n return {\n kind: \"yarn\",\n directDependencies: directSpecs,\n nodes: [...deduped.values()].sort((a, b) => a.name.localeCompare(b.name) || a.version.localeCompare(b.version)),\n };\n};\n","import type { DirectDependencySpec, LockfileExtraction } from \"../domain/types.js\";\n\nexport const parseBunLock = (_raw: string, _directSpecs: readonly DirectDependencySpec[]): LockfileExtraction => {\n throw new Error(\"unsupported_lockfile_format\");\n};\n","import type { ExternalAnalysisSummary } from \"@codesentinel/core\";\nimport { buildExternalAnalysisSummary } from \"../domain/external-analysis.js\";\nimport {\n DEFAULT_EXTERNAL_ANALYSIS_CONFIG,\n type DependencyMetadataProvider,\n type ExternalAnalysisConfig,\n type LockfileExtraction,\n} from \"../domain/types.js\";\nimport { loadPackageJson, selectLockfile } from \"../infrastructure/fs-loader.js\";\nimport { parsePackageJson } from \"../parsing/package-json-loader.js\";\nimport { parsePackageLock } from \"../parsing/package-lock-parser.js\";\nimport { parsePnpmLockfile } from \"../parsing/pnpm-lock-parser.js\";\nimport { parseYarnLock } from \"../parsing/yarn-lock-parser.js\";\nimport { parseBunLock } from \"../parsing/bun-lock-parser.js\";\n\nexport type AnalyzeDependencyExposureInput = {\n repositoryPath: string;\n config?: Partial<ExternalAnalysisConfig>;\n};\n\nexport type DependencyExposureProgressEvent =\n | { stage: \"package_json_loaded\" }\n | { stage: \"lockfile_selected\"; kind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\" }\n | { stage: \"lockfile_parsed\"; dependencyNodes: number; directDependencies: number }\n | { stage: \"metadata_fetch_started\"; total: number }\n | { stage: \"metadata_fetch_progress\"; completed: number; total: number; packageName: string }\n | { stage: \"metadata_fetch_completed\"; total: number }\n | { stage: \"summary_built\"; totalDependencies: number; directDependencies: number };\n\nconst withDefaults = (overrides: Partial<ExternalAnalysisConfig> | undefined): ExternalAnalysisConfig => ({\n ...DEFAULT_EXTERNAL_ANALYSIS_CONFIG,\n ...overrides,\n});\n\nconst parseExtraction = (\n lockfileKind: \"pnpm\" | \"npm\" | \"npm-shrinkwrap\" | \"yarn\" | \"bun\",\n lockfileRaw: string,\n directSpecs: ReturnType<typeof parsePackageJson>,\n): LockfileExtraction => {\n switch (lockfileKind) {\n case \"pnpm\":\n return parsePnpmLockfile(lockfileRaw, directSpecs);\n case \"npm\":\n case \"npm-shrinkwrap\":\n return {\n ...parsePackageLock(lockfileRaw, directSpecs),\n kind: lockfileKind,\n };\n case \"yarn\":\n return parseYarnLock(lockfileRaw, directSpecs);\n case \"bun\":\n return parseBunLock(lockfileRaw, directSpecs);\n default:\n throw new Error(\"unsupported_lockfile_format\");\n }\n};\n\nconst mapWithConcurrency = async <T, R>(\n values: readonly T[],\n limit: number,\n handler: (value: T) => Promise<R>,\n): Promise<readonly R[]> => {\n const effectiveLimit = Math.max(1, limit);\n const results: R[] = new Array(values.length);\n let index = 0;\n\n const workers = Array.from({ length: Math.min(effectiveLimit, values.length) }, async () => {\n for (;;) {\n const current = index;\n index += 1;\n if (current >= values.length) {\n return;\n }\n\n const value = values[current];\n if (value === undefined) {\n return;\n }\n\n results[current] = await handler(value);\n }\n });\n\n await Promise.all(workers);\n return results;\n};\n\nexport const analyzeDependencyExposure = async (\n input: AnalyzeDependencyExposureInput,\n metadataProvider: DependencyMetadataProvider,\n onProgress?: (event: DependencyExposureProgressEvent) => void,\n): Promise<ExternalAnalysisSummary> => {\n const packageJson = loadPackageJson(input.repositoryPath);\n if (packageJson === null) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"package_json_not_found\",\n };\n }\n onProgress?.({ stage: \"package_json_loaded\" });\n\n const lockfile = selectLockfile(input.repositoryPath);\n if (lockfile === null) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"lockfile_not_found\",\n };\n }\n onProgress?.({ stage: \"lockfile_selected\", kind: lockfile.kind });\n\n try {\n const directSpecs = parsePackageJson(packageJson.raw);\n const extraction = parseExtraction(lockfile.kind, lockfile.raw, directSpecs);\n const config = withDefaults(input.config);\n onProgress?.({\n stage: \"lockfile_parsed\",\n dependencyNodes: extraction.nodes.length,\n directDependencies: extraction.directDependencies.length,\n });\n onProgress?.({ stage: \"metadata_fetch_started\", total: extraction.nodes.length });\n\n let completed = 0;\n\n const metadataEntries = await mapWithConcurrency(\n extraction.nodes,\n config.metadataRequestConcurrency,\n async (node) => {\n const result = {\n key: `${node.name}@${node.version}`,\n metadata: await metadataProvider.getMetadata(node.name, node.version),\n };\n completed += 1;\n onProgress?.({\n stage: \"metadata_fetch_progress\",\n completed,\n total: extraction.nodes.length,\n packageName: node.name,\n });\n return result;\n },\n );\n onProgress?.({ stage: \"metadata_fetch_completed\", total: extraction.nodes.length });\n\n const metadataByKey = new Map<string, Awaited<(typeof metadataEntries)[number]>[\"metadata\"]>();\n for (const entry of metadataEntries) {\n metadataByKey.set(entry.key, entry.metadata);\n }\n\n const summary = buildExternalAnalysisSummary(input.repositoryPath, extraction, metadataByKey, config);\n if (summary.available) {\n onProgress?.({\n stage: \"summary_built\",\n totalDependencies: summary.metrics.totalDependencies,\n directDependencies: summary.metrics.directDependencies,\n });\n }\n\n return summary;\n } catch (error) {\n const message = error instanceof Error ? error.message : \"unknown\";\n if (message.includes(\"unsupported_lockfile_format\")) {\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"unsupported_lockfile_format\",\n };\n }\n\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"invalid_lockfile\",\n };\n }\n};\n","import type { DependencyMetadata, DependencyMetadataProvider } from \"../domain/types.js\";\n\ntype NpmPackagePayload = {\n time?: Record<string, string>;\n maintainers?: Array<{ name?: string; email?: string }>;\n};\n\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\nconst round4 = (value: number): number => Number(value.toFixed(4));\n\nconst parseDate = (iso: string | undefined): number | null => {\n if (iso === undefined) {\n return null;\n }\n\n const value = Date.parse(iso);\n return Number.isNaN(value) ? null : value;\n};\n\nexport class NpmRegistryMetadataProvider implements DependencyMetadataProvider {\n private readonly cache = new Map<string, DependencyMetadata | null>();\n\n async getMetadata(name: string, version: string): Promise<DependencyMetadata | null> {\n const key = `${name}@${version}`;\n if (this.cache.has(key)) {\n return this.cache.get(key) ?? null;\n }\n\n try {\n const encodedName = encodeURIComponent(name);\n const response = await fetch(`https://registry.npmjs.org/${encodedName}`);\n if (!response.ok) {\n this.cache.set(key, null);\n return null;\n }\n\n const payload = (await response.json()) as NpmPackagePayload;\n const timeEntries = payload.time ?? {};\n\n const publishDates = Object.entries(timeEntries)\n .filter(([tag]) => tag !== \"created\" && tag !== \"modified\")\n .map(([, date]) => parseDate(date))\n .filter((value): value is number => value !== null)\n .sort((a, b) => a - b);\n\n const modifiedAt = parseDate(timeEntries[\"modified\"]);\n const now = Date.now();\n const daysSinceLastRelease = modifiedAt === null ? null : Math.max(0, round4((now - modifiedAt) / ONE_DAY_MS));\n\n let releaseFrequencyDays: number | null = null;\n if (publishDates.length >= 2) {\n const totalIntervals = publishDates.length - 1;\n let sum = 0;\n for (let i = 1; i < publishDates.length; i += 1) {\n const current = publishDates[i];\n const previous = publishDates[i - 1];\n if (current !== undefined && previous !== undefined) {\n sum += current - previous;\n }\n }\n\n releaseFrequencyDays = round4(sum / totalIntervals / ONE_DAY_MS);\n }\n\n const maintainers = payload.maintainers ?? [];\n const maintainerCount = maintainers.length > 0 ? maintainers.length : null;\n\n const metadata: DependencyMetadata = {\n name,\n version,\n maintainerCount,\n releaseFrequencyDays,\n daysSinceLastRelease,\n repositoryActivity30d: null,\n busFactor: null,\n };\n\n this.cache.set(key, metadata);\n return metadata;\n } catch {\n this.cache.set(key, null);\n return null;\n }\n }\n}\n","import type { DependencyMetadata, DependencyMetadataProvider } from \"../domain/types.js\";\n\nexport class NoopMetadataProvider implements DependencyMetadataProvider {\n async getMetadata(_name: string, _version: string): Promise<DependencyMetadata | null> {\n return null;\n }\n}\n","import type { ExternalAnalysisSummary } from \"@codesentinel/core\";\nimport {\n analyzeDependencyExposure,\n type DependencyExposureProgressEvent,\n type AnalyzeDependencyExposureInput,\n} from \"./application/analyze-dependency-exposure.js\";\nimport { NpmRegistryMetadataProvider } from \"./infrastructure/npm-registry-metadata-provider.js\";\nimport { NoopMetadataProvider } from \"./infrastructure/noop-metadata-provider.js\";\n\nexport type { AnalyzeDependencyExposureInput } from \"./application/analyze-dependency-exposure.js\";\nexport type { DependencyExposureProgressEvent } from \"./application/analyze-dependency-exposure.js\";\n\nexport const analyzeDependencyExposureFromProject = async (\n input: AnalyzeDependencyExposureInput,\n onProgress?: (event: DependencyExposureProgressEvent) => void,\n): Promise<ExternalAnalysisSummary> => {\n const metadataProvider =\n process.env[\"CODESENTINEL_EXTERNAL_METADATA\"] === \"none\"\n ? new NoopMetadataProvider()\n : new NpmRegistryMetadataProvider();\n\n return analyzeDependencyExposure(input, metadataProvider, onProgress);\n};\n","import type {\n CouplingMatrix,\n FileAuthorShare,\n FileCoupling,\n FileEvolutionMetrics,\n Hotspot,\n RepositoryEvolutionSummary,\n} from \"@codesentinel/core\";\nimport type { EvolutionComputationConfig, GitCommitRecord } from \"./evolution-types.js\";\n\ntype FileAccumulator = {\n commitCount: number;\n recentCommitCount: number;\n churnAdded: number;\n churnDeleted: number;\n authors: Map<string, number>;\n};\n\ntype AuthorProfile = {\n authorId: string;\n commitCount: number;\n primaryName: string;\n emailStem: string | null;\n isBot: boolean;\n};\n\nconst pairKey = (a: string, b: string): string => `${a}\\u0000${b}`;\n\nconst round4 = (value: number): number => Number(value.toFixed(4));\n\nconst normalizeName = (value: string): string =>\n value\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n\nconst extractEmailStem = (authorId: string): string | null => {\n const normalized = authorId.trim().toLowerCase();\n const githubNoReplyMatch = normalized.match(/^\\d+\\+([^@]+)@users\\.noreply\\.github\\.com$/);\n if (githubNoReplyMatch?.[1] !== undefined) {\n return githubNoReplyMatch[1].replace(/[._+-]/g, \"\");\n }\n\n const atIndex = normalized.indexOf(\"@\");\n if (atIndex <= 0) {\n return null;\n }\n\n return normalized.slice(0, atIndex).replace(/[._+-]/g, \"\");\n};\n\nconst areNamesCompatible = (left: string, right: string): boolean => {\n if (left.length === 0 || right.length === 0) {\n return false;\n }\n\n if (left === right) {\n return true;\n }\n\n if (left.startsWith(`${right} `) || right.startsWith(`${left} `)) {\n return true;\n }\n\n return false;\n};\n\nconst chooseCanonicalAuthorId = (profiles: readonly AuthorProfile[]): string => {\n const ordered = [...profiles].sort((a, b) => {\n const aIsNoReply = a.authorId.includes(\"@users.noreply.github.com\");\n const bIsNoReply = b.authorId.includes(\"@users.noreply.github.com\");\n if (aIsNoReply !== bIsNoReply) {\n return aIsNoReply ? 1 : -1;\n }\n\n if (a.commitCount !== b.commitCount) {\n return b.commitCount - a.commitCount;\n }\n\n return a.authorId.localeCompare(b.authorId);\n });\n\n return ordered[0]?.authorId ?? \"\";\n};\n\nconst buildAuthorAliasMap = (commits: readonly GitCommitRecord[]): ReadonlyMap<string, string> => {\n const nameCountsByAuthorId = new Map<string, Map<string, number>>();\n const commitCountByAuthorId = new Map<string, number>();\n\n for (const commit of commits) {\n commitCountByAuthorId.set(commit.authorId, (commitCountByAuthorId.get(commit.authorId) ?? 0) + 1);\n\n const normalizedName = normalizeName(commit.authorName);\n const names = nameCountsByAuthorId.get(commit.authorId) ?? new Map<string, number>();\n if (normalizedName.length > 0) {\n names.set(normalizedName, (names.get(normalizedName) ?? 0) + 1);\n }\n nameCountsByAuthorId.set(commit.authorId, names);\n }\n\n const profiles: AuthorProfile[] = [...commitCountByAuthorId.entries()].map(([authorId, commitCount]) => {\n const names = nameCountsByAuthorId.get(authorId);\n const primaryName =\n names === undefined\n ? \"\"\n : [...names.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))[0]?.[0] ?? \"\";\n const normalizedAuthorId = authorId.toLowerCase();\n const isBot = normalizedAuthorId.includes(\"[bot]\");\n\n return {\n authorId,\n commitCount,\n primaryName,\n emailStem: isBot ? null : extractEmailStem(authorId),\n isBot,\n };\n });\n\n const groupsByStem = new Map<string, AuthorProfile[]>();\n for (const profile of profiles) {\n if (profile.emailStem === null || profile.emailStem.length < 4) {\n continue;\n }\n\n const current = groupsByStem.get(profile.emailStem) ?? [];\n current.push(profile);\n groupsByStem.set(profile.emailStem, current);\n }\n\n const aliasMap = new Map<string, string>();\n for (const profile of profiles) {\n aliasMap.set(profile.authorId, profile.authorId);\n }\n\n for (const group of groupsByStem.values()) {\n if (group.length < 2) {\n continue;\n }\n\n const compatible: AuthorProfile[] = [];\n for (const profile of group) {\n if (profile.isBot || profile.primaryName.length === 0) {\n continue;\n }\n\n compatible.push(profile);\n }\n\n if (compatible.length < 2) {\n continue;\n }\n\n const canonical = chooseCanonicalAuthorId(compatible);\n const canonicalProfile = compatible.find((candidate) => candidate.authorId === canonical);\n if (canonicalProfile === undefined) {\n continue;\n }\n\n for (const profile of compatible) {\n if (areNamesCompatible(profile.primaryName, canonicalProfile.primaryName)) {\n aliasMap.set(profile.authorId, canonical);\n }\n }\n }\n\n return aliasMap;\n};\n\nconst computeBusFactor = (\n authorDistribution: readonly FileAuthorShare[],\n threshold: number,\n): number => {\n if (authorDistribution.length === 0) {\n return 0;\n }\n\n let coveredShare = 0;\n for (let i = 0; i < authorDistribution.length; i += 1) {\n const entry = authorDistribution[i];\n if (entry === undefined) {\n continue;\n }\n\n coveredShare += entry.share;\n if (coveredShare >= threshold) {\n return i + 1;\n }\n }\n\n return authorDistribution.length;\n};\n\nconst finalizeAuthorDistribution = (authorCommits: ReadonlyMap<string, number>): readonly FileAuthorShare[] => {\n const totalCommits = [...authorCommits.values()].reduce((sum, value) => sum + value, 0);\n if (totalCommits === 0) {\n return [];\n }\n\n return [...authorCommits.entries()]\n .map(([authorId, commits]) => ({\n authorId,\n commits,\n share: round4(commits / totalCommits),\n }))\n .sort((a, b) => b.commits - a.commits || a.authorId.localeCompare(b.authorId));\n};\n\nconst buildCouplingMatrix = (\n coChangeByPair: ReadonlyMap<string, number>,\n fileCommitCount: ReadonlyMap<string, number>,\n consideredCommits: number,\n skippedLargeCommits: number,\n maxCouplingPairs: number,\n): CouplingMatrix => {\n const allPairs: FileCoupling[] = [];\n\n for (const [key, coChangeCommits] of coChangeByPair.entries()) {\n const [fileA, fileB] = key.split(\"\\u0000\");\n if (fileA === undefined || fileB === undefined) {\n continue;\n }\n\n const fileACommits = fileCommitCount.get(fileA) ?? 0;\n const fileBCommits = fileCommitCount.get(fileB) ?? 0;\n const denominator = fileACommits + fileBCommits - coChangeCommits;\n const couplingScore = denominator === 0 ? 0 : round4(coChangeCommits / denominator);\n\n allPairs.push({\n fileA,\n fileB,\n coChangeCommits,\n couplingScore,\n });\n }\n\n allPairs.sort(\n (a, b) =>\n b.coChangeCommits - a.coChangeCommits ||\n b.couplingScore - a.couplingScore ||\n a.fileA.localeCompare(b.fileA) ||\n a.fileB.localeCompare(b.fileB),\n );\n\n const truncated = allPairs.length > maxCouplingPairs;\n\n return {\n pairs: truncated ? allPairs.slice(0, maxCouplingPairs) : allPairs,\n totalPairCount: allPairs.length,\n consideredCommits,\n skippedLargeCommits,\n truncated,\n };\n};\n\nconst selectHotspots = (\n files: readonly FileEvolutionMetrics[],\n config: EvolutionComputationConfig,\n): { hotspots: readonly Hotspot[]; threshold: number } => {\n if (files.length === 0) {\n return { hotspots: [], threshold: 0 };\n }\n\n const sorted = [...files].sort(\n (a, b) =>\n b.commitCount - a.commitCount || b.churnTotal - a.churnTotal || a.filePath.localeCompare(b.filePath),\n );\n\n const hotspotCount = Math.max(config.hotspotMinFiles, Math.ceil(sorted.length * config.hotspotTopPercent));\n const selected = sorted.slice(0, hotspotCount);\n\n const hotspots = selected.map((file, index) => ({\n filePath: file.filePath,\n rank: index + 1,\n commitCount: file.commitCount,\n churnTotal: file.churnTotal,\n }));\n\n const threshold = selected[selected.length - 1]?.commitCount ?? 0;\n return { hotspots, threshold };\n};\n\nexport const computeRepositoryEvolutionSummary = (\n targetPath: string,\n commits: readonly GitCommitRecord[],\n config: EvolutionComputationConfig,\n): RepositoryEvolutionSummary => {\n const authorAliasById =\n config.authorIdentityMode === \"likely_merge\" ? buildAuthorAliasMap(commits) : new Map<string, string>();\n const fileStats = new Map<string, FileAccumulator>();\n const coChangeByPair = new Map<string, number>();\n\n const headCommitTimestamp = commits.length === 0 ? null : commits[commits.length - 1]?.authoredAtUnix ?? null;\n const recentWindowStart =\n headCommitTimestamp === null\n ? Number.NEGATIVE_INFINITY\n : headCommitTimestamp - config.recentWindowDays * 24 * 60 * 60;\n\n let consideredCommits = 0;\n let skippedLargeCommits = 0;\n\n for (const commit of commits) {\n const uniqueFiles = new Set<string>();\n\n for (const fileChange of commit.fileChanges) {\n uniqueFiles.add(fileChange.filePath);\n const current = fileStats.get(fileChange.filePath) ?? {\n commitCount: 0,\n recentCommitCount: 0,\n churnAdded: 0,\n churnDeleted: 0,\n authors: new Map<string, number>(),\n };\n\n current.churnAdded += fileChange.additions;\n current.churnDeleted += fileChange.deletions;\n fileStats.set(fileChange.filePath, current);\n }\n\n for (const filePath of uniqueFiles) {\n const current = fileStats.get(filePath);\n if (current === undefined) {\n continue;\n }\n\n current.commitCount += 1;\n if (commit.authoredAtUnix >= recentWindowStart) {\n current.recentCommitCount += 1;\n }\n\n const effectiveAuthorId = authorAliasById.get(commit.authorId) ?? commit.authorId;\n current.authors.set(effectiveAuthorId, (current.authors.get(effectiveAuthorId) ?? 0) + 1);\n }\n\n const orderedFiles = [...uniqueFiles].sort((a, b) => a.localeCompare(b));\n if (orderedFiles.length > 1) {\n if (orderedFiles.length <= config.maxFilesPerCommitForCoupling) {\n consideredCommits += 1;\n for (let i = 0; i < orderedFiles.length - 1; i += 1) {\n for (let j = i + 1; j < orderedFiles.length; j += 1) {\n const fileA = orderedFiles[i];\n const fileB = orderedFiles[j];\n if (fileA === undefined || fileB === undefined) {\n continue;\n }\n\n const key = pairKey(fileA, fileB);\n coChangeByPair.set(key, (coChangeByPair.get(key) ?? 0) + 1);\n }\n }\n } else {\n skippedLargeCommits += 1;\n }\n }\n }\n\n const files: FileEvolutionMetrics[] = [...fileStats.entries()]\n .map(([filePath, stats]) => {\n const authorDistribution = finalizeAuthorDistribution(stats.authors);\n const topAuthorShare = authorDistribution[0]?.share ?? 0;\n return {\n filePath,\n commitCount: stats.commitCount,\n frequencyPer100Commits: commits.length === 0 ? 0 : round4((stats.commitCount / commits.length) * 100),\n churnAdded: stats.churnAdded,\n churnDeleted: stats.churnDeleted,\n churnTotal: stats.churnAdded + stats.churnDeleted,\n recentCommitCount: stats.recentCommitCount,\n recentVolatility: stats.commitCount === 0 ? 0 : round4(stats.recentCommitCount / stats.commitCount),\n topAuthorShare,\n busFactor: computeBusFactor(authorDistribution, config.busFactorCoverageThreshold),\n authorDistribution,\n };\n })\n .sort((a, b) => a.filePath.localeCompare(b.filePath));\n\n const fileCommitCount = new Map(files.map((file) => [file.filePath, file.commitCount]));\n const coupling = buildCouplingMatrix(\n coChangeByPair,\n fileCommitCount,\n consideredCommits,\n skippedLargeCommits,\n config.maxCouplingPairs,\n );\n\n const { hotspots, threshold } = selectHotspots(files, config);\n\n return {\n targetPath,\n available: true,\n files,\n hotspots,\n coupling,\n metrics: {\n totalCommits: commits.length,\n totalFiles: files.length,\n headCommitTimestamp,\n recentWindowDays: config.recentWindowDays,\n hotspotTopPercent: config.hotspotTopPercent,\n hotspotThresholdCommitCount: threshold,\n },\n };\n};\n","export type GitFileChange = {\n filePath: string;\n additions: number;\n deletions: number;\n};\n\nexport type GitCommitRecord = {\n hash: string;\n authorId: string;\n authorName: string;\n authoredAtUnix: number;\n fileChanges: readonly GitFileChange[];\n};\n\nexport type EvolutionComputationConfig = {\n authorIdentityMode: \"likely_merge\" | \"strict_email\";\n recentWindowDays: number;\n hotspotTopPercent: number;\n hotspotMinFiles: number;\n maxFilesPerCommitForCoupling: number;\n maxCouplingPairs: number;\n busFactorCoverageThreshold: number;\n};\n\nexport const DEFAULT_EVOLUTION_CONFIG: EvolutionComputationConfig = {\n authorIdentityMode: \"likely_merge\",\n recentWindowDays: 30,\n hotspotTopPercent: 0.1,\n hotspotMinFiles: 1,\n maxFilesPerCommitForCoupling: 200,\n maxCouplingPairs: 500,\n busFactorCoverageThreshold: 0.6,\n};\n","import type { RepositoryEvolutionSummary } from \"@codesentinel/core\";\nimport { computeRepositoryEvolutionSummary } from \"../domain/evolution-metrics.js\";\nimport {\n DEFAULT_EVOLUTION_CONFIG,\n type EvolutionComputationConfig,\n} from \"../domain/evolution-types.js\";\nimport type { GitHistoryProvider, GitHistoryProgressEvent } from \"./git-history-provider.js\";\n\nexport type AnalyzeRepositoryEvolutionInput = {\n repositoryPath: string;\n config?: Partial<EvolutionComputationConfig>;\n};\n\nexport type EvolutionAnalysisProgressEvent =\n | { stage: \"checking_git_repository\" }\n | { stage: \"not_git_repository\" }\n | { stage: \"loading_commit_history\" }\n | { stage: \"computing_metrics\" }\n | { stage: \"analysis_completed\"; available: boolean }\n | ({ stage: \"history\"; event: GitHistoryProgressEvent });\n\nconst createEffectiveConfig = (\n overrides: Partial<EvolutionComputationConfig> | undefined,\n): EvolutionComputationConfig => ({\n ...DEFAULT_EVOLUTION_CONFIG,\n ...overrides,\n});\n\nexport const analyzeRepositoryEvolution = (\n input: AnalyzeRepositoryEvolutionInput,\n historyProvider: GitHistoryProvider,\n onProgress?: (event: EvolutionAnalysisProgressEvent) => void,\n): RepositoryEvolutionSummary => {\n onProgress?.({ stage: \"checking_git_repository\" });\n if (!historyProvider.isGitRepository(input.repositoryPath)) {\n onProgress?.({ stage: \"not_git_repository\" });\n return {\n targetPath: input.repositoryPath,\n available: false,\n reason: \"not_git_repository\",\n };\n }\n\n onProgress?.({ stage: \"loading_commit_history\" });\n const commits = historyProvider.getCommitHistory(input.repositoryPath, (event) =>\n onProgress?.({ stage: \"history\", event }),\n );\n const config = createEffectiveConfig(input.config);\n onProgress?.({ stage: \"computing_metrics\" });\n\n const summary = computeRepositoryEvolutionSummary(input.repositoryPath, commits, config);\n onProgress?.({ stage: \"analysis_completed\", available: summary.available });\n return summary;\n};\n","import { execFileSync } from \"node:child_process\";\n\nexport class GitCommandError extends Error {\n readonly args: readonly string[];\n\n constructor(message: string, args: readonly string[]) {\n super(message);\n this.name = \"GitCommandError\";\n this.args = args;\n }\n}\n\nexport interface GitCommandClient {\n run(repositoryPath: string, args: readonly string[]): string;\n}\n\nexport class ExecGitCommandClient implements GitCommandClient {\n run(repositoryPath: string, args: readonly string[]): string {\n try {\n return execFileSync(\"git\", [\"-C\", repositoryPath, ...args], {\n encoding: \"utf8\",\n maxBuffer: 1024 * 1024 * 64,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown git execution error\";\n throw new GitCommandError(message, args);\n }\n }\n}\n","export const COMMIT_RECORD_SEPARATOR = \"\\u001e\";\nexport const COMMIT_FIELD_SEPARATOR = \"\\u001f\";\n\nexport const GIT_LOG_FORMAT =\n `%x1e%H%x1f%at%x1f%an%x1f%ae`;\n","import type { GitCommitRecord } from \"../domain/evolution-types.js\";\nimport type { ParseGitLogProgressEvent } from \"../parsing/git-log-parser.js\";\n\nexport type GitHistoryProgressEvent =\n | { stage: \"git_log_received\"; bytes: number }\n | { stage: \"git_log_parsed\"; commits: number }\n | { stage: \"git_log_parse_progress\"; parsedRecords: number; totalRecords: number };\n\nexport interface GitHistoryProvider {\n isGitRepository(repositoryPath: string): boolean;\n getCommitHistory(\n repositoryPath: string,\n onProgress?: (event: GitHistoryProgressEvent) => void,\n ): readonly GitCommitRecord[];\n}\n\nexport const mapParseProgressToHistoryProgress = (\n event: ParseGitLogProgressEvent,\n): GitHistoryProgressEvent => ({\n stage: \"git_log_parse_progress\",\n parsedRecords: event.parsedRecords,\n totalRecords: event.totalRecords,\n});\n","import { COMMIT_FIELD_SEPARATOR, COMMIT_RECORD_SEPARATOR } from \"../domain/git-log-format.js\";\nimport type { GitCommitRecord, GitFileChange } from \"../domain/evolution-types.js\";\n\nexport type ParseGitLogProgressEvent = {\n parsedRecords: number;\n totalRecords: number;\n};\n\nconst parseInteger = (value: string): number | null => {\n if (value.length === 0) {\n return null;\n }\n\n const parsed = Number.parseInt(value, 10);\n if (Number.isNaN(parsed)) {\n return null;\n }\n\n return parsed;\n};\n\nconst normalizeAuthorIdentity = (authorName: string, authorEmail: string): string => {\n const normalizedName = authorName.trim().replace(/\\s+/g, \" \").toLowerCase();\n const normalizedEmail = authorEmail.trim().toLowerCase();\n\n if (/\\[bot\\]/i.test(normalizedName) || /\\[bot\\]/i.test(normalizedEmail)) {\n return normalizedEmail.length > 0 ? normalizedEmail : normalizedName;\n }\n\n const githubNoReplyMatch = normalizedEmail.match(/^\\d+\\+([^@]+)@users\\.noreply\\.github\\.com$/);\n const githubHandle = githubNoReplyMatch?.[1]?.trim().toLowerCase();\n if (githubHandle !== undefined && githubHandle.length > 0) {\n return `${githubHandle}@users.noreply.github.com`;\n }\n\n if (normalizedEmail.length > 0) {\n return normalizedEmail;\n }\n\n return normalizedName;\n};\n\nconst parseRenamedPath = (pathSpec: string): string => {\n if (!pathSpec.includes(\" => \")) {\n return pathSpec;\n }\n\n const braceRenameMatch = pathSpec.match(/^(.*)\\{(.+) => (.+)\\}(.*)$/);\n if (braceRenameMatch !== null) {\n const [, prefix, , renamedTo, suffix] = braceRenameMatch;\n return `${prefix}${renamedTo}${suffix}`;\n }\n\n const parts = pathSpec.split(\" => \");\n const finalPart = parts[parts.length - 1];\n return finalPart ?? pathSpec;\n};\n\nconst parseNumstatLine = (line: string): GitFileChange | null => {\n const parts = line.split(\"\\t\");\n if (parts.length < 3) {\n return null;\n }\n\n const additionsRaw = parts[0];\n const deletionsRaw = parts[1];\n const pathRaw = parts.slice(2).join(\"\\t\");\n\n if (additionsRaw === undefined || deletionsRaw === undefined) {\n return null;\n }\n\n const additions = additionsRaw === \"-\" ? 0 : parseInteger(additionsRaw);\n const deletions = deletionsRaw === \"-\" ? 0 : parseInteger(deletionsRaw);\n\n if (additions === null || deletions === null) {\n return null;\n }\n\n const filePath = parseRenamedPath(pathRaw);\n return {\n filePath,\n additions,\n deletions,\n };\n};\n\nexport const parseGitLog = (\n rawLog: string,\n onProgress?: (event: ParseGitLogProgressEvent) => void,\n): readonly GitCommitRecord[] => {\n const records = rawLog\n .split(COMMIT_RECORD_SEPARATOR)\n .map((record) => record.trim())\n .filter((record) => record.length > 0);\n\n const commits: GitCommitRecord[] = [];\n\n for (const [index, record] of records.entries()) {\n const lines = record\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n\n if (lines.length === 0) {\n continue;\n }\n\n const headerParts = lines[0]?.split(COMMIT_FIELD_SEPARATOR) ?? [];\n if (headerParts.length !== 4) {\n continue;\n }\n\n const [hash, authoredAtRaw, authorName, authorEmail] = headerParts;\n if (hash === undefined || authoredAtRaw === undefined || authorName === undefined || authorEmail === undefined) {\n continue;\n }\n\n const authoredAtUnix = parseInteger(authoredAtRaw);\n if (authoredAtUnix === null) {\n continue;\n }\n\n const fileChanges: GitFileChange[] = [];\n for (const line of lines.slice(1)) {\n const parsedLine = parseNumstatLine(line);\n if (parsedLine !== null) {\n fileChanges.push(parsedLine);\n }\n }\n\n commits.push({\n hash,\n authorId: normalizeAuthorIdentity(authorName, authorEmail),\n authorName,\n authoredAtUnix,\n fileChanges,\n });\n\n const parsedRecords = index + 1;\n if (parsedRecords === 1 || parsedRecords === records.length || parsedRecords % 500 === 0) {\n onProgress?.({ parsedRecords, totalRecords: records.length });\n }\n }\n\n commits.sort((a, b) => a.authoredAtUnix - b.authoredAtUnix || a.hash.localeCompare(b.hash));\n return commits;\n};\n","import { GIT_LOG_FORMAT } from \"../domain/git-log-format.js\";\nimport type { GitCommitRecord } from \"../domain/evolution-types.js\";\nimport {\n mapParseProgressToHistoryProgress,\n type GitHistoryProvider,\n type GitHistoryProgressEvent,\n} from \"../application/git-history-provider.js\";\nimport { GitCommandError, type GitCommandClient } from \"./git-command-client.js\";\nimport { parseGitLog } from \"../parsing/git-log-parser.js\";\n\nconst NON_GIT_CODES = [\"not a git repository\", \"not in a git directory\"];\n\nconst isNotGitError = (error: GitCommandError): boolean => {\n const lower = error.message.toLowerCase();\n return NON_GIT_CODES.some((code) => lower.includes(code));\n};\n\nexport class GitCliHistoryProvider implements GitHistoryProvider {\n constructor(private readonly gitClient: GitCommandClient) {}\n\n isGitRepository(repositoryPath: string): boolean {\n try {\n const output = this.gitClient.run(repositoryPath, [\"rev-parse\", \"--is-inside-work-tree\"]);\n return output.trim() === \"true\";\n } catch (error) {\n if (error instanceof GitCommandError && isNotGitError(error)) {\n return false;\n }\n\n throw error;\n }\n }\n\n getCommitHistory(\n repositoryPath: string,\n onProgress?: (event: GitHistoryProgressEvent) => void,\n ): readonly GitCommitRecord[] {\n const output = this.gitClient.run(repositoryPath, [\n \"-c\",\n \"core.quotepath=false\",\n \"log\",\n \"--use-mailmap\",\n \"--no-merges\",\n \"--date=unix\",\n `--pretty=format:${GIT_LOG_FORMAT}`,\n \"--numstat\",\n \"--find-renames\",\n ]);\n onProgress?.({ stage: \"git_log_received\", bytes: Buffer.byteLength(output, \"utf8\") });\n const commits = parseGitLog(output, (event) => onProgress?.(mapParseProgressToHistoryProgress(event)));\n onProgress?.({ stage: \"git_log_parsed\", commits: commits.length });\n return commits;\n }\n}\n","import type { RepositoryEvolutionSummary } from \"@codesentinel/core\";\nimport {\n analyzeRepositoryEvolution,\n type EvolutionAnalysisProgressEvent,\n type AnalyzeRepositoryEvolutionInput,\n} from \"./application/analyze-repository-evolution.js\";\nimport { ExecGitCommandClient } from \"./infrastructure/git-command-client.js\";\nimport { GitCliHistoryProvider } from \"./infrastructure/git-history-provider.js\";\n\nexport type { AnalyzeRepositoryEvolutionInput } from \"./application/analyze-repository-evolution.js\";\nexport type { EvolutionAnalysisProgressEvent } from \"./application/analyze-repository-evolution.js\";\n\nexport const analyzeRepositoryEvolutionFromGit = (\n input: AnalyzeRepositoryEvolutionInput,\n onProgress?: (event: EvolutionAnalysisProgressEvent) => void,\n): RepositoryEvolutionSummary => {\n const historyProvider = new GitCliHistoryProvider(new ExecGitCommandClient());\n return analyzeRepositoryEvolution(input, historyProvider, onProgress);\n};\n","export type DimensionWeights = {\n structural: number;\n evolution: number;\n external: number;\n};\n\nexport type InteractionWeights = {\n structuralEvolution: number;\n centralInstability: number;\n dependencyAmplification: number;\n};\n\nexport type StructuralFactorWeights = {\n fanIn: number;\n fanOut: number;\n depth: number;\n cycleParticipation: number;\n};\n\nexport type EvolutionFactorWeights = {\n frequency: number;\n churn: number;\n recentVolatility: number;\n ownershipConcentration: number;\n busFactorRisk: number;\n};\n\nexport type DependencyFactorWeights = {\n signals: number;\n staleness: number;\n maintainerConcentration: number;\n transitiveBurden: number;\n centrality: number;\n chainDepth: number;\n busFactorRisk: number;\n};\n\nexport type RiskEngineConfig = {\n dimensionWeights: DimensionWeights;\n interactionWeights: InteractionWeights;\n structuralFactorWeights: StructuralFactorWeights;\n evolutionFactorWeights: EvolutionFactorWeights;\n dependencyFactorWeights: DependencyFactorWeights;\n quantileClamp: {\n lower: number;\n upper: number;\n };\n hotspotTopPercent: number;\n hotspotMinFiles: number;\n hotspotMaxFiles: number;\n couplingCluster: {\n minCoChangeCommits: number;\n percentileThreshold: number;\n floorScore: number;\n };\n amplificationZone: {\n pressureFloor: number;\n percentileThreshold: number;\n maxZones: number;\n };\n module: {\n maxPrefixSegments: number;\n rootLabel: string;\n commonSourceRoots: readonly string[];\n };\n dependencySignals: {\n inheritedSignalMultiplier: number;\n abandonedHalfLifeDays: number;\n missingMetadataPenalty: number;\n };\n externalDimension: {\n topDependencyPercentile: number;\n dependencyDepthHalfLife: number;\n };\n};\n\nexport const DEFAULT_RISK_ENGINE_CONFIG: RiskEngineConfig = {\n // Base dimensional influence. Risk is never dominated by a single dimension by default.\n dimensionWeights: {\n structural: 0.44,\n evolution: 0.36,\n external: 0.2,\n },\n // Interaction terms activate only when both related dimensions are high.\n interactionWeights: {\n structuralEvolution: 0.35,\n centralInstability: 0.25,\n dependencyAmplification: 0.2,\n },\n structuralFactorWeights: {\n fanIn: 0.3,\n fanOut: 0.25,\n depth: 0.2,\n cycleParticipation: 0.25,\n },\n evolutionFactorWeights: {\n frequency: 0.26,\n churn: 0.24,\n recentVolatility: 0.2,\n ownershipConcentration: 0.18,\n busFactorRisk: 0.12,\n },\n dependencyFactorWeights: {\n signals: 0.38,\n staleness: 0.16,\n maintainerConcentration: 0.16,\n transitiveBurden: 0.1,\n centrality: 0.08,\n chainDepth: 0.06,\n busFactorRisk: 0.06,\n },\n quantileClamp: {\n lower: 0.05,\n upper: 0.95,\n },\n hotspotTopPercent: 0.12,\n hotspotMinFiles: 3,\n hotspotMaxFiles: 30,\n couplingCluster: {\n minCoChangeCommits: 2,\n percentileThreshold: 0.9,\n floorScore: 0.35,\n },\n amplificationZone: {\n pressureFloor: 0.2,\n percentileThreshold: 0.85,\n maxZones: 20,\n },\n module: {\n maxPrefixSegments: 2,\n rootLabel: \"(root)\",\n commonSourceRoots: [\"src\", \"lib\", \"app\", \"packages\"],\n },\n dependencySignals: {\n inheritedSignalMultiplier: 0.45,\n // At this age, staleness reaches 50% risk.\n abandonedHalfLifeDays: 540,\n missingMetadataPenalty: 0.5,\n },\n externalDimension: {\n topDependencyPercentile: 0.85,\n dependencyDepthHalfLife: 6,\n },\n};\n","export const clamp01 = (value: number): number => {\n if (Number.isNaN(value)) {\n return 0;\n }\n\n if (value <= 0) {\n return 0;\n }\n\n if (value >= 1) {\n return 1;\n }\n\n return value;\n};\n\nexport const round4 = (value: number): number => Number(value.toFixed(4));\n\nexport const average = (values: readonly number[]): number => {\n if (values.length === 0) {\n return 0;\n }\n\n const total = values.reduce((sum, current) => sum + current, 0);\n return total / values.length;\n};\n\nexport const percentile = (values: readonly number[], p: number): number => {\n if (values.length === 0) {\n return 0;\n }\n\n if (values.length === 1) {\n return values[0] ?? 0;\n }\n\n const sorted = [...values].sort((a, b) => a - b);\n const position = clamp01(p) * (sorted.length - 1);\n const lowerIndex = Math.floor(position);\n const upperIndex = Math.ceil(position);\n\n const lower = sorted[lowerIndex] ?? 0;\n const upper = sorted[upperIndex] ?? lower;\n\n if (lowerIndex === upperIndex) {\n return lower;\n }\n\n const ratio = position - lowerIndex;\n return lower + (upper - lower) * ratio;\n};\n\nexport const saturatingComposite = (\n baseline: number,\n amplifications: readonly number[],\n): number => {\n let value = clamp01(baseline);\n\n for (const amplification of amplifications) {\n const boundedAmplification = clamp01(amplification);\n value += (1 - value) * boundedAmplification;\n }\n\n return clamp01(value);\n};\n\nexport const halfLifeRisk = (value: number, halfLife: number): number => {\n if (value <= 0 || halfLife <= 0) {\n return 0;\n }\n\n return clamp01(value / (value + halfLife));\n};\n\nexport const normalizeWeights = <T extends string>(\n weights: Readonly<Record<T, number>>,\n enabled: Readonly<Record<T, boolean>>,\n): Readonly<Record<T, number>> => {\n let total = 0;\n const result: Record<T, number> = { ...weights };\n\n for (const key of Object.keys(result) as T[]) {\n const enabledValue = enabled[key];\n if (!enabledValue) {\n result[key] = 0;\n continue;\n }\n\n const value = Math.max(0, result[key]);\n result[key] = value;\n total += value;\n }\n\n if (total === 0) {\n const activeKeys = (Object.keys(result) as T[]).filter((key) => enabled[key]);\n if (activeKeys.length === 0) {\n return result;\n }\n\n const uniform = 1 / activeKeys.length;\n for (const key of activeKeys) {\n result[key] = uniform;\n }\n\n return result;\n }\n\n for (const key of Object.keys(result) as T[]) {\n if (enabled[key]) {\n result[key] = result[key] / total;\n }\n }\n\n return result;\n};\n","import { clamp01, percentile } from \"./math.js\";\n\nexport type QuantileScale = {\n lower: number;\n upper: number;\n};\n\nexport const logScale = (value: number): number => Math.log1p(Math.max(0, value));\n\nexport const buildQuantileScale = (\n values: readonly number[],\n lowerPercentile: number,\n upperPercentile: number,\n): QuantileScale => {\n if (values.length === 0) {\n return { lower: 0, upper: 0 };\n }\n\n return {\n lower: percentile(values, lowerPercentile),\n upper: percentile(values, upperPercentile),\n };\n};\n\nexport const normalizeWithScale = (value: number, scale: QuantileScale): number => {\n if (scale.upper <= scale.lower) {\n return value > 0 ? 1 : 0;\n }\n\n return clamp01((value - scale.lower) / (scale.upper - scale.lower));\n};\n","import type {\n DependencyRiskScore,\n DependencyRiskSignal,\n ExternalAnalysisSummary,\n FileEvolutionMetrics,\n FileRiskScore,\n FragileCluster,\n GraphAnalysisSummary,\n ModuleRiskScore,\n RepositoryEvolutionSummary,\n RepositoryRiskSummary,\n RiskFactors,\n} from \"@codesentinel/core\";\nimport type { RiskEngineConfig } from \"../config.js\";\nimport {\n average,\n clamp01,\n halfLifeRisk,\n normalizeWeights,\n percentile,\n round4,\n saturatingComposite,\n} from \"./math.js\";\nimport { buildQuantileScale, logScale, normalizeWithScale } from \"./normalization.js\";\n\ntype DependencyScoreComputation = {\n dependencyScores: readonly DependencyRiskScore[];\n repositoryExternalPressure: number;\n};\n\ntype FileRiskContext = {\n file: string;\n score: number;\n normalizedScore: number;\n factors: RiskFactors;\n structuralCentrality: number;\n};\n\ntype MetricScales = {\n commitCount: ReturnType<typeof buildQuantileScale>;\n churnTotal: ReturnType<typeof buildQuantileScale>;\n busFactor: ReturnType<typeof buildQuantileScale>;\n};\n\nconst normalizePath = (path: string): string => path.replaceAll(\"\\\\\", \"/\");\n\nconst dependencySignalWeights: Readonly<Record<DependencyRiskSignal, number>> = {\n single_maintainer: 0.3,\n abandoned: 0.3,\n high_centrality: 0.16,\n deep_chain: 0.14,\n high_fanout: 0.06,\n metadata_unavailable: 0.04,\n};\n\nconst dependencySignalWeightBudget = Object.values(dependencySignalWeights).reduce(\n (sum, value) => sum + value,\n 0,\n);\n\nconst computeDependencySignalScore = (\n ownSignals: readonly DependencyRiskSignal[],\n inheritedSignals: readonly DependencyRiskSignal[],\n inheritedSignalMultiplier: number,\n): number => {\n const ownWeight = ownSignals.reduce((sum, signal) => sum + (dependencySignalWeights[signal] ?? 0), 0);\n const inheritedWeight = inheritedSignals.reduce(\n (sum, signal) => sum + (dependencySignalWeights[signal] ?? 0),\n 0,\n );\n\n const weightedTotal = ownWeight + inheritedWeight * inheritedSignalMultiplier;\n const maxWeightedTotal = dependencySignalWeightBudget * (1 + inheritedSignalMultiplier);\n\n if (maxWeightedTotal <= 0) {\n return 0;\n }\n\n return clamp01(weightedTotal / maxWeightedTotal);\n};\n\nconst computeDependencyScores = (\n external: ExternalAnalysisSummary,\n config: RiskEngineConfig,\n): DependencyScoreComputation => {\n if (!external.available) {\n return {\n dependencyScores: [],\n repositoryExternalPressure: 0,\n };\n }\n\n const transitiveCounts = external.dependencies.map((dependency) =>\n logScale(dependency.transitiveDependencies.length),\n );\n const dependentCounts = external.dependencies.map((dependency) => logScale(dependency.dependents));\n const chainDepths = external.dependencies.map((dependency) => dependency.dependencyDepth);\n\n const transitiveScale = buildQuantileScale(\n transitiveCounts,\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n );\n const dependentScale = buildQuantileScale(\n dependentCounts,\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n );\n const chainDepthScale = buildQuantileScale(\n chainDepths,\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n );\n\n const dependencyScores = external.dependencies\n .map<DependencyRiskScore>((dependency) => {\n const signalScore = computeDependencySignalScore(\n dependency.ownRiskSignals,\n dependency.inheritedRiskSignals,\n config.dependencySignals.inheritedSignalMultiplier,\n );\n\n const maintainerConcentrationRisk =\n dependency.maintainerCount === null\n ? config.dependencySignals.missingMetadataPenalty\n : clamp01(1 / Math.max(1, dependency.maintainerCount));\n\n const stalenessRisk =\n dependency.daysSinceLastRelease === null\n ? config.dependencySignals.missingMetadataPenalty\n : halfLifeRisk(\n dependency.daysSinceLastRelease,\n config.dependencySignals.abandonedHalfLifeDays,\n );\n\n const transitiveBurdenRisk = normalizeWithScale(\n logScale(dependency.transitiveDependencies.length),\n transitiveScale,\n );\n\n const centralityRisk = normalizeWithScale(logScale(dependency.dependents), dependentScale);\n const chainDepthRisk = normalizeWithScale(dependency.dependencyDepth, chainDepthScale);\n\n const busFactorRisk =\n dependency.busFactor === null\n ? config.dependencySignals.missingMetadataPenalty\n : clamp01(1 / Math.max(1, dependency.busFactor));\n\n const weights = config.dependencyFactorWeights;\n const normalizedScore = clamp01(\n signalScore * weights.signals +\n stalenessRisk * weights.staleness +\n maintainerConcentrationRisk * weights.maintainerConcentration +\n transitiveBurdenRisk * weights.transitiveBurden +\n centralityRisk * weights.centrality +\n chainDepthRisk * weights.chainDepth +\n busFactorRisk * weights.busFactorRisk,\n );\n\n return {\n dependency: dependency.name,\n score: round4(normalizedScore * 100),\n normalizedScore: round4(normalizedScore),\n ownRiskSignals: dependency.ownRiskSignals,\n inheritedRiskSignals: dependency.inheritedRiskSignals,\n };\n })\n .sort(\n (a, b) =>\n b.normalizedScore - a.normalizedScore || a.dependency.localeCompare(b.dependency),\n );\n\n const normalizedValues = dependencyScores.map((score) => score.normalizedScore);\n const highDependencyRisk =\n dependencyScores.length === 0\n ? 0\n : percentile(normalizedValues, config.externalDimension.topDependencyPercentile);\n const averageDependencyRisk = average(normalizedValues);\n const depthRisk = halfLifeRisk(\n external.metrics.dependencyDepth,\n config.externalDimension.dependencyDepthHalfLife,\n );\n\n const repositoryExternalPressure = clamp01(\n highDependencyRisk * 0.5 + averageDependencyRisk * 0.3 + depthRisk * 0.2,\n );\n\n return {\n dependencyScores,\n repositoryExternalPressure: round4(repositoryExternalPressure),\n };\n};\n\nconst mapEvolutionByFile = (\n evolution: RepositoryEvolutionSummary,\n): ReadonlyMap<string, FileEvolutionMetrics> => {\n if (!evolution.available) {\n return new Map<string, FileEvolutionMetrics>();\n }\n\n return new Map(\n evolution.files.map((fileMetrics) => [normalizePath(fileMetrics.filePath), fileMetrics]),\n );\n};\n\nconst computeEvolutionScales = (\n evolutionByFile: ReadonlyMap<string, FileEvolutionMetrics>,\n config: RiskEngineConfig,\n): MetricScales => {\n const evolutionFiles = [...evolutionByFile.values()];\n\n return {\n commitCount: buildQuantileScale(\n evolutionFiles.map((metrics) => logScale(metrics.commitCount)),\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n ),\n churnTotal: buildQuantileScale(\n evolutionFiles.map((metrics) => logScale(metrics.churnTotal)),\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n ),\n busFactor: buildQuantileScale(\n evolutionFiles.map((metrics) => metrics.busFactor),\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n ),\n };\n};\n\nconst inferModuleName = (filePath: string, config: RiskEngineConfig): string => {\n const normalized = normalizePath(filePath);\n const parts = normalized.split(\"/\").filter((part) => part.length > 0);\n\n if (parts.length <= 1) {\n return config.module.rootLabel;\n }\n\n const first = parts[0];\n if (first === undefined) {\n return config.module.rootLabel;\n }\n\n if (!config.module.commonSourceRoots.includes(first)) {\n return first;\n }\n\n if (parts.length <= config.module.maxPrefixSegments) {\n return first;\n }\n\n return parts.slice(0, config.module.maxPrefixSegments).join(\"/\");\n};\n\nconst buildFragileClusters = (\n structural: GraphAnalysisSummary,\n evolution: RepositoryEvolutionSummary,\n fileScoresByFile: ReadonlyMap<string, FileRiskScore>,\n config: RiskEngineConfig,\n): readonly FragileCluster[] => {\n const clusters: FragileCluster[] = [];\n\n let cycleClusterCount = 0;\n for (const cycle of structural.cycles) {\n const files = [...new Set(cycle.nodes.map((node) => normalizePath(node)))].filter((filePath) =>\n fileScoresByFile.has(filePath),\n );\n\n if (files.length < 2) {\n continue;\n }\n\n files.sort((a, b) => a.localeCompare(b));\n\n const averageRisk = average(\n files.map((filePath) => fileScoresByFile.get(filePath)?.normalizedScore ?? 0),\n );\n\n const cycleSizeRisk = clamp01((files.length - 1) / 5);\n const score = round4(clamp01(averageRisk * 0.75 + cycleSizeRisk * 0.25) * 100);\n\n cycleClusterCount += 1;\n clusters.push({\n id: `cycle:${cycleClusterCount}`,\n kind: \"structural_cycle\",\n files,\n score,\n });\n }\n\n if (evolution.available && evolution.coupling.pairs.length > 0) {\n const candidates = evolution.coupling.pairs.filter(\n (pair) => pair.coChangeCommits >= config.couplingCluster.minCoChangeCommits,\n );\n\n const threshold = Math.max(\n config.couplingCluster.floorScore,\n percentile(\n candidates.map((pair) => pair.couplingScore),\n config.couplingCluster.percentileThreshold,\n ),\n );\n\n const selectedPairs = candidates\n .filter((pair) => pair.couplingScore >= threshold)\n .map((pair) => ({\n fileA: normalizePath(pair.fileA),\n fileB: normalizePath(pair.fileB),\n couplingScore: pair.couplingScore,\n }))\n .filter(\n (pair) =>\n pair.fileA !== pair.fileB &&\n fileScoresByFile.has(pair.fileA) &&\n fileScoresByFile.has(pair.fileB),\n );\n\n const adjacency = new Map<string, Set<string>>();\n for (const pair of selectedPairs) {\n const aNeighbors = adjacency.get(pair.fileA) ?? new Set<string>();\n aNeighbors.add(pair.fileB);\n adjacency.set(pair.fileA, aNeighbors);\n\n const bNeighbors = adjacency.get(pair.fileB) ?? new Set<string>();\n bNeighbors.add(pair.fileA);\n adjacency.set(pair.fileB, bNeighbors);\n }\n\n const visited = new Set<string>();\n let couplingClusterCount = 0;\n\n const orderedStarts = [...adjacency.keys()].sort((a, b) => a.localeCompare(b));\n for (const start of orderedStarts) {\n if (visited.has(start)) {\n continue;\n }\n\n const stack = [start];\n const files: string[] = [];\n\n while (stack.length > 0) {\n const current = stack.pop();\n if (current === undefined || visited.has(current)) {\n continue;\n }\n\n visited.add(current);\n files.push(current);\n\n const neighbors = adjacency.get(current);\n if (neighbors === undefined) {\n continue;\n }\n\n for (const neighbor of neighbors) {\n if (!visited.has(neighbor)) {\n stack.push(neighbor);\n }\n }\n }\n\n if (files.length < 2) {\n continue;\n }\n\n files.sort((a, b) => a.localeCompare(b));\n const fileSet = new Set(files);\n const componentPairs = selectedPairs.filter(\n (pair) => fileSet.has(pair.fileA) && fileSet.has(pair.fileB),\n );\n\n const meanFileRisk = average(\n files.map((filePath) => fileScoresByFile.get(filePath)?.normalizedScore ?? 0),\n );\n const meanCoupling = average(componentPairs.map((pair) => pair.couplingScore));\n\n const score = round4(clamp01(meanFileRisk * 0.65 + meanCoupling * 0.35) * 100);\n\n couplingClusterCount += 1;\n clusters.push({\n id: `coupling:${couplingClusterCount}`,\n kind: \"change_coupling\",\n files,\n score,\n });\n }\n }\n\n return clusters.sort(\n (a, b) => b.score - a.score || a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id),\n );\n};\n\nexport const computeRiskSummary = (\n structural: GraphAnalysisSummary,\n evolution: RepositoryEvolutionSummary,\n external: ExternalAnalysisSummary,\n config: RiskEngineConfig,\n): RepositoryRiskSummary => {\n const dependencyComputation = computeDependencyScores(external, config);\n const evolutionByFile = mapEvolutionByFile(evolution);\n const evolutionScales = computeEvolutionScales(evolutionByFile, config);\n\n const cycleFileSet = new Set(\n structural.cycles.flatMap((cycle) => cycle.nodes.map((node) => normalizePath(node))),\n );\n\n const fanInScale = buildQuantileScale(\n structural.files.map((file) => logScale(file.fanIn)),\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n );\n const fanOutScale = buildQuantileScale(\n structural.files.map((file) => logScale(file.fanOut)),\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n );\n const depthScale = buildQuantileScale(\n structural.files.map((file) => file.depth),\n config.quantileClamp.lower,\n config.quantileClamp.upper,\n );\n\n const dimensionWeights = normalizeWeights(config.dimensionWeights, {\n structural: true,\n evolution: evolution.available,\n external: external.available,\n });\n\n const fileRiskContexts = structural.files\n .map<FileRiskContext>((file) => {\n const filePath = normalizePath(file.id);\n const inCycle = cycleFileSet.has(filePath) ? 1 : 0;\n\n const fanInRisk = normalizeWithScale(logScale(file.fanIn), fanInScale);\n const fanOutRisk = normalizeWithScale(logScale(file.fanOut), fanOutScale);\n const depthRisk = normalizeWithScale(file.depth, depthScale);\n\n const structuralWeights = config.structuralFactorWeights;\n const structuralFactor = clamp01(\n fanInRisk * structuralWeights.fanIn +\n fanOutRisk * structuralWeights.fanOut +\n depthRisk * structuralWeights.depth +\n inCycle * structuralWeights.cycleParticipation,\n );\n\n const structuralCentrality = clamp01((fanInRisk + fanOutRisk) / 2);\n\n let evolutionFactor = 0;\n const evolutionMetrics = evolutionByFile.get(filePath);\n if (evolution.available && evolutionMetrics !== undefined) {\n const frequencyRisk = normalizeWithScale(\n logScale(evolutionMetrics.commitCount),\n evolutionScales.commitCount,\n );\n const churnRisk = normalizeWithScale(\n logScale(evolutionMetrics.churnTotal),\n evolutionScales.churnTotal,\n );\n const volatilityRisk = clamp01(evolutionMetrics.recentVolatility);\n const ownershipConcentrationRisk = clamp01(evolutionMetrics.topAuthorShare);\n const busFactorRisk = clamp01(1 - normalizeWithScale(evolutionMetrics.busFactor, evolutionScales.busFactor));\n\n const evolutionWeights = config.evolutionFactorWeights;\n evolutionFactor = clamp01(\n frequencyRisk * evolutionWeights.frequency +\n churnRisk * evolutionWeights.churn +\n volatilityRisk * evolutionWeights.recentVolatility +\n ownershipConcentrationRisk * evolutionWeights.ownershipConcentration +\n busFactorRisk * evolutionWeights.busFactorRisk,\n );\n }\n\n const dependencyAffinity = clamp01(structuralCentrality * 0.6 + evolutionFactor * 0.4);\n const externalFactor = external.available\n ? clamp01(dependencyComputation.repositoryExternalPressure * dependencyAffinity)\n : 0;\n\n const baseline =\n structuralFactor * dimensionWeights.structural +\n evolutionFactor * dimensionWeights.evolution +\n externalFactor * dimensionWeights.external;\n\n const interactions = [\n structuralFactor * evolutionFactor * config.interactionWeights.structuralEvolution,\n structuralCentrality * evolutionFactor * config.interactionWeights.centralInstability,\n externalFactor * Math.max(structuralFactor, evolutionFactor) *\n config.interactionWeights.dependencyAmplification,\n ];\n\n const normalizedScore = saturatingComposite(baseline, interactions);\n\n return {\n file: filePath,\n score: round4(normalizedScore * 100),\n normalizedScore: round4(normalizedScore),\n factors: {\n structural: round4(structuralFactor),\n evolution: round4(evolutionFactor),\n external: round4(externalFactor),\n },\n structuralCentrality: round4(structuralCentrality),\n };\n })\n .sort((a, b) => b.score - a.score || a.file.localeCompare(b.file));\n\n const fileScores: FileRiskScore[] = fileRiskContexts.map((context) => ({\n file: context.file,\n score: context.score,\n normalizedScore: context.normalizedScore,\n factors: context.factors,\n }));\n\n const fileScoresByFile = new Map(fileScores.map((fileScore) => [fileScore.file, fileScore]));\n\n const hotspotsCount = Math.min(\n config.hotspotMaxFiles,\n Math.max(config.hotspotMinFiles, Math.ceil(fileScores.length * config.hotspotTopPercent)),\n );\n\n const hotspots = fileScores.slice(0, hotspotsCount).map((fileScore) => ({\n file: fileScore.file,\n score: fileScore.score,\n factors: fileScore.factors,\n }));\n\n const moduleFiles = new Map<string, number[]>();\n for (const fileScore of fileScores) {\n const moduleName = inferModuleName(fileScore.file, config);\n const values = moduleFiles.get(moduleName) ?? [];\n values.push(fileScore.normalizedScore);\n moduleFiles.set(moduleName, values);\n }\n\n const moduleScores: ModuleRiskScore[] = [...moduleFiles.entries()]\n .map(([module, values]) => {\n const averageScore = average(values);\n const peakScore = values.reduce((max, value) => Math.max(max, value), 0);\n const normalizedScore = clamp01(averageScore * 0.65 + peakScore * 0.35);\n\n return {\n module,\n score: round4(normalizedScore * 100),\n normalizedScore: round4(normalizedScore),\n fileCount: values.length,\n };\n })\n .sort((a, b) => b.score - a.score || a.module.localeCompare(b.module));\n\n const fragileClusters = buildFragileClusters(structural, evolution, fileScoresByFile, config);\n\n const externalPressures = fileScores.map((fileScore) => fileScore.factors.external);\n const pressureThreshold = Math.max(\n config.amplificationZone.pressureFloor,\n percentile(externalPressures, config.amplificationZone.percentileThreshold),\n );\n\n const dependencyAmplificationZones = fileScores\n .map((fileScore) => {\n const intensity = clamp01(\n fileScore.factors.external * Math.max(fileScore.factors.structural, fileScore.factors.evolution),\n );\n const normalizedZoneScore = clamp01(intensity * 0.7 + fileScore.normalizedScore * 0.3);\n\n return {\n file: fileScore.file,\n score: round4(normalizedZoneScore * 100),\n externalPressure: fileScore.factors.external,\n };\n })\n .filter((zone) => external.available && zone.externalPressure >= pressureThreshold)\n .sort((a, b) => b.score - a.score || a.file.localeCompare(b.file))\n .slice(0, config.amplificationZone.maxZones)\n .map((zone) => ({\n ...zone,\n externalPressure: round4(zone.externalPressure),\n }));\n\n const structuralDimension = average(fileScores.map((fileScore) => fileScore.factors.structural));\n const evolutionDimension = average(fileScores.map((fileScore) => fileScore.factors.evolution));\n const externalDimension = dependencyComputation.repositoryExternalPressure;\n\n const topCentralSlice = Math.max(1, Math.ceil(fileRiskContexts.length * 0.1));\n const criticalInstability = average(\n [...fileRiskContexts]\n .sort(\n (a, b) =>\n b.structuralCentrality * b.factors.evolution - a.structuralCentrality * a.factors.evolution ||\n a.file.localeCompare(b.file),\n )\n .slice(0, topCentralSlice)\n .map((context) => context.structuralCentrality * context.factors.evolution),\n );\n\n const dependencyAmplification = average(\n dependencyAmplificationZones.map((zone) =>\n clamp01((zone.externalPressure * zone.score) / 100),\n ),\n );\n\n const repositoryBaseline =\n structuralDimension * dimensionWeights.structural +\n evolutionDimension * dimensionWeights.evolution +\n externalDimension * dimensionWeights.external;\n\n const repositoryNormalizedScore = saturatingComposite(repositoryBaseline, [\n structuralDimension * evolutionDimension * config.interactionWeights.structuralEvolution,\n criticalInstability * config.interactionWeights.centralInstability,\n dependencyAmplification * config.interactionWeights.dependencyAmplification,\n ]);\n\n return {\n repositoryScore: round4(repositoryNormalizedScore * 100),\n normalizedScore: round4(repositoryNormalizedScore),\n hotspots,\n fragileClusters,\n dependencyAmplificationZones,\n fileScores,\n moduleScores,\n dependencyScores: dependencyComputation.dependencyScores,\n };\n};\n","import type {\n ExternalAnalysisSummary,\n GraphAnalysisSummary,\n RepositoryEvolutionSummary,\n RepositoryRiskSummary,\n} from \"@codesentinel/core\";\nimport { DEFAULT_RISK_ENGINE_CONFIG, type RiskEngineConfig } from \"../config.js\";\nimport { computeRiskSummary } from \"../domain/risk-model.js\";\n\nexport type ComputeRepositoryRiskSummaryInput = {\n structural: GraphAnalysisSummary;\n evolution: RepositoryEvolutionSummary;\n external: ExternalAnalysisSummary;\n config?: Partial<RiskEngineConfig>;\n};\n\nconst mergeConfig = (overrides: Partial<RiskEngineConfig> | undefined): RiskEngineConfig => {\n if (overrides === undefined) {\n return DEFAULT_RISK_ENGINE_CONFIG;\n }\n\n return {\n ...DEFAULT_RISK_ENGINE_CONFIG,\n ...overrides,\n dimensionWeights: {\n ...DEFAULT_RISK_ENGINE_CONFIG.dimensionWeights,\n ...overrides.dimensionWeights,\n },\n interactionWeights: {\n ...DEFAULT_RISK_ENGINE_CONFIG.interactionWeights,\n ...overrides.interactionWeights,\n },\n structuralFactorWeights: {\n ...DEFAULT_RISK_ENGINE_CONFIG.structuralFactorWeights,\n ...overrides.structuralFactorWeights,\n },\n evolutionFactorWeights: {\n ...DEFAULT_RISK_ENGINE_CONFIG.evolutionFactorWeights,\n ...overrides.evolutionFactorWeights,\n },\n dependencyFactorWeights: {\n ...DEFAULT_RISK_ENGINE_CONFIG.dependencyFactorWeights,\n ...overrides.dependencyFactorWeights,\n },\n quantileClamp: {\n ...DEFAULT_RISK_ENGINE_CONFIG.quantileClamp,\n ...overrides.quantileClamp,\n },\n couplingCluster: {\n ...DEFAULT_RISK_ENGINE_CONFIG.couplingCluster,\n ...overrides.couplingCluster,\n },\n amplificationZone: {\n ...DEFAULT_RISK_ENGINE_CONFIG.amplificationZone,\n ...overrides.amplificationZone,\n },\n module: {\n ...DEFAULT_RISK_ENGINE_CONFIG.module,\n ...overrides.module,\n },\n dependencySignals: {\n ...DEFAULT_RISK_ENGINE_CONFIG.dependencySignals,\n ...overrides.dependencySignals,\n },\n externalDimension: {\n ...DEFAULT_RISK_ENGINE_CONFIG.externalDimension,\n ...overrides.externalDimension,\n },\n };\n};\n\nexport const computeRepositoryRiskSummary = (\n input: ComputeRepositoryRiskSummaryInput,\n): RepositoryRiskSummary => {\n const config = mergeConfig(input.config);\n return computeRiskSummary(input.structural, input.evolution, input.external, config);\n};\n"],"mappings":";;;AAAA,SAAS,SAAS,cAAc;AAChC,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,SAAS,WAAAC,gBAAe;AACjC,SAAS,qBAAqB;;;AC2C9B,IAAM,qBAAqB,CAAC,aAA2C;AAAA,EACrE,YAAY,QAAQ,WAAW;AAAA,EAC/B,YAAY,QAAQ,WAAW;AAAA,EAC/B,WAAW,QAAQ,UAAU,YACzB;AAAA,IACE,WAAW;AAAA,IACX,SAAS,QAAQ,UAAU;AAAA,IAC3B,aAAa,QAAQ,UAAU,SAAS,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,YAAY,QAAQ,QAAQ;AAAA,EACvF,IACA;AAAA,IACE,WAAW;AAAA,IACX,QAAQ,QAAQ,UAAU;AAAA,EAC5B;AAAA,EACJ,UAAU,QAAQ,SAAS,YACvB;AAAA,IACE,WAAW;AAAA,IACX,SAAS,QAAQ,SAAS;AAAA,IAC1B,yBAAyB,QAAQ,SAAS,qBAAqB,MAAM,GAAG,EAAE;AAAA,EAC5E,IACA;AAAA,IACE,WAAW;AAAA,IACX,QAAQ,QAAQ,SAAS;AAAA,EAC3B;AAAA,EACJ,MAAM;AAAA,IACJ,iBAAiB,QAAQ,KAAK;AAAA,IAC9B,iBAAiB,QAAQ,KAAK;AAAA,IAC9B,aAAa,QAAQ,KAAK,SAAS,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,aAAa;AAAA,MAC/D,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,IACjB,EAAE;AAAA,IACF,qBAAqB,QAAQ,KAAK,gBAAgB;AAAA,IAClD,kCAAkC,QAAQ,KAAK,6BAA6B;AAAA,EAC9E;AACF;AAEO,IAAM,sBAAsB,CAAC,SAAyB,SAC3D,SAAS,SACL,KAAK,UAAU,SAAS,MAAM,CAAC,IAC/B,KAAK,UAAU,mBAAmB,OAAO,GAAG,MAAM,CAAC;;;AClFzD,IAAM,eAAsE;AAAA,EAC1E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AASA,IAAM,OAAO,MAAY;AAAC;AAEnB,IAAM,qBAAqB,OAAe;AAAA,EAC/C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEA,IAAM,YAAY,CAAC,iBAA2B,iBAAuD;AACnG,MAAI,oBAAoB,UAAU;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,aAAa,YAAY,KAAK,aAAa,eAAe;AACnE;AAEA,IAAM,QAAQ,CAAC,cAA2C,YAA0B;AAClF,UAAQ,OAAO,MAAM,kBAAkB,aAAa,YAAY,CAAC,IAAI,OAAO;AAAA,CAAI;AAClF;AAEO,IAAM,qBAAqB,CAAC,UAA4B;AAC7D,MAAI,UAAU,UAAU;AACtB,WAAO,mBAAmB;AAAA,EAC5B;AAEA,SAAO;AAAA,IACL,OAAO,CAAC,YAAY;AAClB,UAAI,UAAU,OAAO,OAAO,GAAG;AAC7B,cAAM,SAAS,OAAO;AAAA,MACxB;AAAA,IACF;AAAA,IACA,MAAM,CAAC,YAAY;AACjB,UAAI,UAAU,OAAO,MAAM,GAAG;AAC5B,cAAM,QAAQ,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,IACA,MAAM,CAAC,YAAY;AACjB,UAAI,UAAU,OAAO,MAAM,GAAG;AAC5B,cAAM,QAAQ,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,IACA,OAAO,CAAC,YAAY;AAClB,UAAI,UAAU,OAAO,OAAO,GAAG;AAC7B,cAAM,SAAS,OAAO;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,gBAAgB,CAAC,UAAwC;AACpE,UAAQ,OAAO;AAAA,IACb,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;AC7EA,SAAS,WAAAC,gBAAe;;;AIAxB,SAAS,SAAS,YAAY,UAAU,eAAe;AACvD,YAAY,QAAQ;AHgBpB,IAAM,UAAU,CAAC,MAAc,OAAuB,GAAG,IAAI,KAAS,EAAE;AAEjE,IAAM,kBAAkB,CAC7B,OACA,aACc;AACd,QAAM,cAAc,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACtE,QAAM,eAAe,IAAI,IAAI,YAAY,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAE/D,QAAM,gBAAgB,oBAAI,IAAwB;AAClD,aAAW,QAAQ,UAAU;AAC3B,QAAI,KAAK,SAAS,KAAK,IAAI;AACzB;IACF;AAEA,QAAI,CAAC,aAAa,IAAI,KAAK,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,EAAE,GAAG;AAC9D;IACF;AAEA,kBAAc,IAAI,QAAQ,KAAK,MAAM,KAAK,EAAE,GAAG,IAAI;EACrD;AAEA,QAAM,cAAc,CAAC,GAAG,cAAc,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AAC7D,UAAM,cAAc,EAAE,KAAK,cAAc,EAAE,IAAI;AAC/C,QAAI,gBAAgB,GAAG;AACrB,aAAO;IACT;AAEA,WAAO,EAAE,GAAG,cAAc,EAAE,EAAE;EAChC,CAAC;AAED,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,QAAQ,aAAa;AAC9B,cAAU,IAAI,KAAK,IAAI,CAAC,CAAC;EAC3B;AAEA,aAAW,QAAQ,aAAa;AAC9B,cAAU,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,EAAE;EACxC;AAEA,QAAM,gBAAgB,oBAAI,IAA+B;AACzD,aAAW,CAAC,QAAQ,OAAO,KAAK,UAAU,QAAQ,GAAG;AACnD,kBAAc,IAAI,QAAQ,CAAC,GAAG,OAAO,CAAC;EACxC;AAEA,SAAO;IACL,OAAO;IACP,OAAO;IACP;EACF;AACF;AC/DO,IAAM,eAAe,CAAC,kBAAwE;AACnG,MAAI,QAAQ;AACZ,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,aAAyB,CAAC;AAEhC,QAAM,gBAAgB,CAAC,WAAyB;AAC9C,YAAQ,IAAI,QAAQ,KAAK;AACzB,YAAQ,IAAI,QAAQ,KAAK;AACzB,aAAS;AAET,UAAM,KAAK,MAAM;AACjB,YAAQ,IAAI,MAAM;AAElB,UAAM,YAAY,cAAc,IAAI,MAAM,KAAK,CAAC;AAChD,eAAW,UAAU,WAAW;AAC9B,UAAI,CAAC,QAAQ,IAAI,MAAM,GAAG;AACxB,sBAAc,MAAM;AACpB,cAAMC,eAAc,QAAQ,IAAI,MAAM;AACtC,cAAM,cAAc,QAAQ,IAAI,MAAM;AACtC,YAAIA,iBAAgB,UAAa,gBAAgB,UAAa,cAAcA,cAAa;AACvF,kBAAQ,IAAI,QAAQ,WAAW;QACjC;AACA;MACF;AAEA,UAAI,QAAQ,IAAI,MAAM,GAAG;AACvB,cAAMA,eAAc,QAAQ,IAAI,MAAM;AACtC,cAAM,YAAY,QAAQ,IAAI,MAAM;AACpC,YAAIA,iBAAgB,UAAa,cAAc,UAAa,YAAYA,cAAa;AACnF,kBAAQ,IAAI,QAAQ,SAAS;QAC/B;MACF;IACF;AAEA,UAAM,cAAc,QAAQ,IAAI,MAAM;AACtC,UAAM,YAAY,QAAQ,IAAI,MAAM;AACpC,QAAI,gBAAgB,UAAa,cAAc,UAAa,gBAAgB,WAAW;AACrF;IACF;AAEA,UAAM,YAAsB,CAAC;AAC7B,eAAS;AACP,YAAM,SAAS,MAAM,IAAI;AACzB,UAAI,WAAW,QAAW;AACxB;MACF;AAEA,cAAQ,OAAO,MAAM;AACrB,gBAAU,KAAK,MAAM;AACrB,UAAI,WAAW,QAAQ;AACrB;MACF;IACF;AAEA,cAAU,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC3C,eAAW,KAAK,SAAS;EAC3B;AAEA,QAAM,UAAU,CAAC,GAAG,cAAc,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC3E,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,QAAQ,IAAI,MAAM,GAAG;AACxB,oBAAc,MAAM;IACtB;EACF;AAEA,aAAW,KAAK,CAAC,GAAG,MAAM;AACxB,UAAM,SAAS,EAAE,CAAC,KAAK;AACvB,UAAM,SAAS,EAAE,CAAC,KAAK;AACvB,WAAO,OAAO,cAAc,MAAM;EACpC,CAAC;AAED,SAAO,EAAE,WAAW;AACtB;ACrEA,IAAM,cAAc,CAAC,QAAgB,kBAAmE;AACtG,QAAM,UAAU,cAAc,IAAI,MAAM,KAAK,CAAC;AAC9C,SAAO,QAAQ,SAAS,MAAM;AAChC;AAEA,IAAM,wBAAwB,CAAC,UAAuC;AACpE,QAAM,EAAE,WAAW,IAAI,aAAa,MAAM,aAAa;AAEvD,QAAM,SAAuB,CAAC;AAC9B,QAAM,oBAAoB,oBAAI,IAAoB;AAClD,aAAW,QAAQ,CAAC,WAAW,UAAU;AACvC,eAAW,UAAU,WAAW;AAC9B,wBAAkB,IAAI,QAAQ,KAAK;IACrC;AAEA,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO,KAAK,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAAC;AACrC;IACF;AAEA,UAAM,WAAW,UAAU,CAAC;AAC5B,QAAI,aAAa,UAAa,YAAY,UAAU,MAAM,aAAa,GAAG;AACxE,aAAO,KAAK,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAAC;IACvC;EACF,CAAC;AAED,QAAM,cAAc,oBAAI,IAAyB;AACjD,QAAM,WAAW,oBAAI,IAAoB;AAEzC,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,GAAG;AAC7C,gBAAY,IAAI,GAAG,oBAAI,IAAI,CAAC;AAC5B,aAAS,IAAI,GAAG,CAAC;EACnB;AAEA,aAAW,QAAQ,MAAM,OAAO;AAC9B,UAAM,gBAAgB,kBAAkB,IAAI,KAAK,IAAI;AACrD,UAAM,cAAc,kBAAkB,IAAI,KAAK,EAAE;AAEjD,QAAI,kBAAkB,UAAa,gBAAgB,UAAa,kBAAkB,aAAa;AAC7F;IACF;AAEA,UAAM,WAAW,YAAY,IAAI,aAAa;AAC9C,QAAI,UAAU,IAAI,WAAW,MAAM,MAAM;AACvC;IACF;AAEA,cAAU,IAAI,WAAW;AACzB,aAAS,IAAI,cAAc,SAAS,IAAI,WAAW,KAAK,KAAK,CAAC;EAChE;AAEA,QAAM,QAAkB,CAAC;AACzB,QAAM,mBAAmB,oBAAI,IAAoB;AAEjD,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,GAAG;AAC7C,SAAK,SAAS,IAAI,CAAC,KAAK,OAAO,GAAG;AAChC,YAAM,KAAK,CAAC;AACZ,uBAAiB,IAAI,GAAG,CAAC;IAC3B;EACF;AAEA,MAAI,SAAS;AACb,SAAO,SAAS,MAAM,QAAQ;AAC5B,UAAM,cAAc,MAAM,MAAM;AAChC,cAAU;AAEV,QAAI,gBAAgB,QAAW;AAC7B;IACF;AAEA,UAAM,eAAe,iBAAiB,IAAI,WAAW,KAAK;AAC1D,UAAM,WAAW,YAAY,IAAI,WAAW,KAAK,oBAAI,IAAY;AAEjE,eAAW,iBAAiB,UAAU;AACpC,YAAM,YAAY,iBAAiB,IAAI,aAAa,KAAK;AACzD,UAAI,eAAe,IAAI,WAAW;AAChC,yBAAiB,IAAI,eAAe,eAAe,CAAC;MACtD;AAEA,YAAM,qBAAqB,SAAS,IAAI,aAAa,KAAK,KAAK;AAC/D,eAAS,IAAI,eAAe,iBAAiB;AAC7C,UAAI,sBAAsB,GAAG;AAC3B,cAAM,KAAK,aAAa;MAC1B;IACF;EACF;AAEA,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,MAAI,aAAa;AAEjB,aAAW,QAAQ,CAAC,WAAW,gBAAgB;AAC7C,UAAM,iBAAiB,iBAAiB,IAAI,WAAW,KAAK;AAC5D,QAAI,iBAAiB,YAAY;AAC/B,mBAAa;IACf;AAEA,eAAW,UAAU,WAAW;AAC9B,oBAAc,IAAI,QAAQ,cAAc;IAC1C;EACF,CAAC;AAED,SAAO,KAAK,CAAC,GAAG,MAAM;AACpB,UAAM,SAAS,EAAE,MAAM,CAAC,KAAK;AAC7B,UAAM,SAAS,EAAE,MAAM,CAAC,KAAK;AAC7B,WAAO,OAAO,cAAc,MAAM;EACpC,CAAC;AAED,SAAO;IACL;IACA;IACA;EACF;AACF;AAEO,IAAM,6BAA6B,CACxC,YACA,UACyB;AACzB,QAAM,YAAY,oBAAI,IAAoB;AAC1C,QAAM,aAAa,oBAAI,IAAoB;AAE3C,aAAW,QAAQ,MAAM,OAAO;AAC9B,cAAU,IAAI,KAAK,IAAI,CAAC;AACxB,eAAW,IAAI,KAAK,IAAI,MAAM,cAAc,IAAI,KAAK,EAAE,GAAG,UAAU,CAAC;EACvE;AAEA,aAAW,QAAQ,MAAM,OAAO;AAC9B,cAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;EAC1D;AAEA,QAAM,EAAE,QAAQ,eAAe,WAAW,IAAI,sBAAsB,KAAK;AAEzE,MAAI,WAAW;AACf,MAAI,YAAY;AAEhB,QAAM,QAA0B,MAAM,MAAM,IAAI,CAAC,SAAS;AACxD,UAAM,QAAQ,UAAU,IAAI,KAAK,EAAE,KAAK;AACxC,UAAM,SAAS,WAAW,IAAI,KAAK,EAAE,KAAK;AAE1C,QAAI,QAAQ,UAAU;AACpB,iBAAW;IACb;AAEA,QAAI,SAAS,WAAW;AACtB,kBAAY;IACd;AAEA,WAAO;MACL,IAAI,KAAK;MACT,cAAc,KAAK;MACnB,oBAAoB,MAAM,cAAc,IAAI,KAAK,EAAE,KAAK,CAAC;MACzD;MACA;MACA,OAAO,cAAc,IAAI,KAAK,EAAE,KAAK;IACvC;EACF,CAAC;AAED,QAAM,UAAwB;IAC5B,WAAW,MAAM,MAAM;IACvB,WAAW,MAAM,MAAM;IACvB,YAAY,OAAO;IACnB;IACA;IACA;EACF;AAEA,SAAO;IACL;IACA,OAAO,MAAM;IACb,OAAO,MAAM;IACb;IACA;IACA;EACF;AACF;ACxKA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,OAAO,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,MAAM,CAAC;AAChG,IAAM,gBAAgB;EACpB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACF;AACA,IAAM,gBAAgB,CAAC,MAAM;AAC7B,IAAM,mBAAmB,oBAAI,IAAI;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACF,CAAC;AAED,IAAM,gBAAgB,CAAC,cAA8B,UAAU,WAAW,MAAM,GAAG;AAEnF,IAAM,sBAAsB,CAAC,UAAkB,gBAAiC;AAC9E,QAAM,YAAY,QAAQ,QAAQ;AAClC,MAAI,CAAC,kBAAkB,IAAI,SAAS,GAAG;AACrC,WAAO;EACT;AAEA,QAAM,eAAe,SAAS,aAAa,QAAQ;AACnD,MAAI,aAAa,WAAW,IAAI,GAAG;AACjC,WAAO;EACT;AAEA,QAAM,yBAAyB,cAAc,YAAY;AACzD,QAAM,WAAW,uBAAuB,MAAM,GAAG;AACjD,SAAO,CAAC,SAAS,KAAK,CAAC,YAAY,iBAAiB,IAAI,OAAO,CAAC;AAClE;AAEA,IAAM,4BAA4B,CAAC,gBAA2C;AAC5E,QAAM,QAAW,OAAI;IACnB;IACA,CAAC,GAAG,iBAAiB;IACrB;IACA;EACF;AACA,SAAO,MAAM,IAAI,CAAC,aAAa,QAAQ,QAAQ,CAAC;AAClD;AAEA,IAAM,oBAAoB,CAAC,eAA6C;AACtE,QAAM,oBAAuB;IAC3B;IACA,CAAC;IACD;MACE,GAAM;MACN,qCAAqC,MAAM;AACzC,cAAM,IAAI,MAAM,+CAA+C,UAAU,EAAE;MAC7E;IACF;EACF;AAEA,MAAI,sBAAsB,QAAW;AACnC,UAAM,IAAI,MAAM,+CAA+C,UAAU,EAAE;EAC7E;AAEA,SAAO;AACT;AAQA,IAAM,gCAAgC,CACpC,gBACiC;AACjC,QAAM,iBAAoB,kBAAe,aAAgB,OAAI,YAAY,eAAe;AACxF,MAAI,mBAAmB,QAAW;AAChC,WAAO;EACT;AAEA,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,iBAAiB,oBAAI,IAAY;AACvC,MAAI,cAAyC;AAE7C,QAAM,cAAc,CAAC,eAA6B;AAChD,UAAM,qBAAqB,QAAQ,UAAU;AAC7C,QAAI,mBAAmB,IAAI,kBAAkB,GAAG;AAC9C;IACF;AAEA,uBAAmB,IAAI,kBAAkB;AACzC,UAAM,SAAS,kBAAkB,kBAAkB;AACnD,QAAI,gBAAgB,MAAM;AACxB,oBAAc,OAAO;IACvB;AAEA,eAAW,YAAY,OAAO,WAAW;AACvC,qBAAe,IAAI,QAAQ,QAAQ,CAAC;IACtC;AAEA,eAAW,aAAa,OAAO,qBAAqB,CAAC,GAAG;AACtD,YAAM,gBAAgB,QAAQ,UAAU,IAAI;AAC5C,YAAM,sBAAyB,OAAI,gBAAgB,aAAa,IACzD,kBAAe,eAAkB,OAAI,YAAY,eAAe,IACnE;AAEJ,UAAI,wBAAwB,UAAgB,OAAI,WAAW,mBAAmB,GAAG;AAC/E,oBAAY,mBAAmB;MACjC;IACF;EACF;AAEA,cAAY,cAAc;AAE1B,SAAO;IACL,WAAW,CAAC,GAAG,cAAc;IAC7B,aACE,eAAe;MACb,kBAAqB,wBAAqB;IAC5C;IACF,oBAAoB,mBAAmB;EACzC;AACF;AAEA,IAAM,wBAAwB,CAAC,UAA8D;EAC3F,GAAG;EACH,SAAS;EACT,kBAAkB,MAAM,oBAAuB,wBAAqB;AACtE;AAEA,IAAM,gBAAgB,CACpB,gBAMG;AACH,QAAM,YAAY,8BAA8B,WAAW;AAC3D,MAAI,cAAc,MAAM;AACtB,WAAO;MACL,WAAW,0BAA0B,WAAW;MAChD,SAAS,sBAAsB,MAAS;MACxC,eAAe;MACf,kBAAkB;IACpB;EACF;AAEA,MAAI,UAAU,UAAU,WAAW,GAAG;AACpC,WAAO;MACL,WAAW,0BAA0B,WAAW;MAChD,SAAS,sBAAsB,UAAU,WAAW;MACpD,eAAe,UAAU;MACzB,kBAAkB;IACpB;EACF;AAEA,SAAO;IACL,WAAW,UAAU;IACrB,SAAS,sBAAsB,UAAU,WAAW;IACpD,eAAe,UAAU;IACzB,kBAAkB;EACpB;AACF;AAEA,IAAM,6BAA6B,CAAC,eAAkD;AACpF,MAAO,mBAAgB,UAAU,GAAG;AAClC,WAAO,WAAW;EACpB;AAEA,MAAO,mCAAgC,UAAU,GAAG;AAClD,WAAO,WAAW;EACpB;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CAAC,sBAAqD;AAC7E,QAAM,eAAe,kBAAkB;AACvC,MAAI,iBAAiB,QAAW;AAC9B,WAAO;EACT;AAEA,MAAI,aAAa,YAAY;AAC3B,WAAO;EACT;AAEA,MAAI,aAAa,SAAS,QAAW;AACnC,WAAO;EACT;AAEA,QAAM,gBAAgB,aAAa;AACnC,MAAI,kBAAkB,QAAW;AAC/B,WAAO;EACT;AAEA,MAAO,qBAAkB,aAAa,GAAG;AACvC,WAAO;EACT;AAEA,MAAI,cAAc,SAAS,WAAW,GAAG;AACvC,WAAO;EACT;AAEA,SAAO,cAAc,SAAS,KAAK,CAAC,YAAY,CAAC,QAAQ,UAAU;AACrE;AAEA,IAAM,0BAA0B,CAAC,eAAiD;AAChF,QAAM,aAAa,oBAAI,IAAY;AAEnC,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAO,uBAAoB,IAAI,GAAG;AAChC,UAAI,iBAAiB,IAAI,KAAK,KAAK,oBAAoB,QAAW;AAChE,cAAM,YAAY,2BAA2B,KAAK,eAAe;AACjE,YAAI,cAAc,QAAW;AAC3B,qBAAW,IAAI,SAAS;QAC1B;MACF;AACA;IACF;AAEA,QAAO,uBAAoB,IAAI,GAAG;AAChC,UAAI,CAAC,KAAK,cAAc,KAAK,oBAAoB,QAAW;AAC1D,cAAM,YAAY,2BAA2B,KAAK,eAAe;AACjE,YAAI,cAAc,QAAW;AAC3B,qBAAW,IAAI,SAAS;QAC1B;MACF;AACA;IACF;AAEA,QAAO,oBAAiB,IAAI,GAAG;AAC7B,UAAI,KAAK,WAAW,SAAY,cAAW,iBAAiB,KAAK,UAAU,SAAS,GAAG;AACrF,cAAM,gBAAgB,KAAK,UAAU,CAAC;AACtC,YAAI,kBAAkB,QAAW;AAC/B,gBAAM,YAAY,2BAA2B,aAAa;AAC1D,cAAI,cAAc,QAAW;AAC3B,uBAAW,IAAI,SAAS;UAC1B;QACF;MACF;AAEA,UAAO,gBAAa,KAAK,UAAU,KAAK,KAAK,WAAW,SAAS,aAAa,KAAK,UAAU,SAAS,GAAG;AACvG,cAAM,gBAAgB,KAAK,UAAU,CAAC;AACtC,YAAI,kBAAkB,QAAW;AAC/B,gBAAM,YAAY,2BAA2B,aAAa;AAC1D,cAAI,cAAc,QAAW;AAC3B,uBAAW,IAAI,SAAS;UAC1B;QACF;MACF;IACF;AAEG,IAAA,gBAAa,MAAM,KAAK;EAC7B;AAEA,QAAM,UAAU;AAChB,SAAO,CAAC,GAAG,UAAU;AACvB;AAEO,IAAM,yBAAyB,CACpC,aACA,eACkB;AAClB,QAAM,cAAc,WAAW,WAAW,IAAI,cAAc,QAAQ,WAAW;AAC/E,QAAM,EAAE,WAAW,SAAS,eAAe,iBAAiB,IAAI,cAAc,WAAW;AACzF,eAAa,EAAE,OAAO,mBAAmB,eAAe,iBAAiB,CAAC;AAE1E,QAAM,kBAAkB,UACrB,OAAO,CAAC,aAAa,oBAAoB,UAAU,WAAW,CAAC,EAC/D,IAAI,CAAC,aAAa,cAAc,QAAQ,QAAQ,CAAC,CAAC;AAErD,QAAM,wBAAwB,CAAC,GAAG,IAAI,IAAI,eAAe,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC7F,QAAM,oBAAoB,IAAI,IAAI,qBAAqB;AACvD,eAAa,EAAE,OAAO,oBAAoB,kBAAkB,sBAAsB,OAAO,CAAC;AAE1F,QAAMC,WAAa,iBAAc;IAC/B,WAAW;IACX;EACF,CAAC;AACD,eAAa,EAAE,OAAO,mBAAmB,kBAAkB,sBAAsB,OAAO,CAAC;AAEzF,QAAM,qBAAqB,oBAAI,IAAwB;AACvD,aAAW,cAAc,uBAAuB;AAC9C,UAAM,eAAe,cAAc,SAAS,aAAa,UAAU,CAAC;AACpE,UAAM,SAAS;AACf,uBAAmB,IAAI,YAAY;MACjC,IAAI;MACJ,cAAc;MACd;IACF,CAAC;EACH;AAEA,QAAM,gBAAgB,oBAAI,IAAgC;AAC1D,QAAM,QAAsB,CAAC;AAE7B,aAAW,CAAC,OAAO,UAAU,KAAK,sBAAsB,QAAQ,GAAG;AACjE,UAAM,aAAaA,SAAQ,cAAc,UAAU;AACnD,QAAI,eAAe,QAAW;AAC5B;IACF;AAEA,UAAM,WAAW,mBAAmB,IAAI,UAAU;AAClD,QAAI,aAAa,QAAW;AAC1B;IACF;AAEA,UAAM,mBAAmB,wBAAwB,UAAU;AAC3D,eAAW,aAAa,kBAAkB;AACxC,YAAM,WAAW,GAAG,UAAU,KAAS,SAAS;AAChD,UAAI,eAAe,cAAc,IAAI,QAAQ;AAE7C,UAAI,iBAAiB,UAAa,CAAC,cAAc,IAAI,QAAQ,GAAG;AAC9D,cAAM,WAAc,qBAAkB,WAAW,YAAY,SAAY,MAAG,EAAE;AAC9E,YAAI,aAAa,QAAW;AAC1B,yBAAe,cAAc,QAAQ,SAAS,gBAAgB,CAAC;QACjE;AACA,sBAAc,IAAI,UAAU,YAAY;MAC1C;AAEA,UAAI,iBAAiB,UAAa,CAAC,kBAAkB,IAAI,YAAY,GAAG;AACtE;MACF;AAEA,YAAM,SAAS,mBAAmB,IAAI,YAAY;AAClD,UAAI,WAAW,QAAW;AACxB;MACF;AAEA,YAAM,KAAK,EAAE,MAAM,SAAS,IAAI,IAAI,OAAO,GAAG,CAAC;IACjD;AAEA,UAAM,YAAY,QAAQ;AAC1B,QAAI,cAAc,KAAK,cAAc,sBAAsB,UAAU,YAAY,OAAO,GAAG;AACzF,mBAAa;QACX,OAAO;QACP;QACA,OAAO,sBAAsB;QAC7B,UAAU,SAAS;MACrB,CAAC;IACH;EACF;AACA,eAAa,EAAE,OAAO,kBAAkB,YAAY,MAAM,OAAO,CAAC;AAElE,SAAO;IACL,OAAO,CAAC,GAAG,mBAAmB,OAAO,CAAC;IACtC;EACF;AACF;ACrWO,IAAM,2BAA2B,CACtC,UACyB;AACzB,QAAM,gBAAgB,uBAAuB,MAAM,aAAa,MAAM,UAAU;AAChF,QAAM,YAAY,gBAAgB,cAAc,OAAO,cAAc,KAAK;AAC1E,SAAO,2BAA2B,MAAM,aAAa,SAAS;AAChE;;;AGnBA,SAAS,YAAY,oBAAoB;AACzC,SAAS,YAAY;AFYrB,IAAM,SAAS,CAAC,UAA0B,OAAO,MAAM,QAAQ,CAAC,CAAC;AASjE,IAAM,iBAAiB,CAAC,UAAsE;AAC5F,QAAM,SAAS,oBAAI,IAAoC;AAEvD,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC;AACzC,WAAO,KAAK,IAAI;AAChB,WAAO,IAAI,KAAK,MAAM,MAAM;EAC9B;AAEA,QAAM,aAA+B,CAAC;AAEtC,aAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,GAAG;AACjD,QAAI,WAAW,WAAW,GAAG;AAC3B;IACF;AAEA,eAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAC;AAC5D,UAAM,WAAW,WAAW,CAAC;AAC7B,QAAI,aAAa,QAAW;AAC1B;IACF;AAEA,UAAM,OAAO,SAAS,aACnB,IAAI,CAAC,QAAQ;AACZ,YAAM,KAAK,IAAI,YAAY,GAAG;AAC9B,aAAO,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,EAAE;IACxC,CAAC,EACA,OAAO,CAAC,YAAY,QAAQ,SAAS,CAAC,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpC,eAAW,KAAK;MACd,KAAK,GAAG,IAAI,IAAI,SAAS,OAAO;MAChC;MACA,SAAS,SAAS;MAClB,cAAc;IAChB,CAAC;EACH;AAEA,SAAO,WAAW,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC/D;AAEA,IAAM,gBAAgB,CACpB,YACA,gBACmE;AACnE,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,cAAc,oBAAI,IAAoB;AAE5C,QAAM,UAAU,CAAC,SAAyB;AACxC,UAAM,QAAQ,YAAY,IAAI,IAAI;AAClC,QAAI,UAAU,QAAW;AACvB,aAAO;IACT;AAEA,QAAI,SAAS,IAAI,IAAI,GAAG;AACtB,aAAO;IACT;AAEA,aAAS,IAAI,IAAI;AAEjB,UAAM,OAAO,WAAW,IAAI,IAAI;AAChC,QAAI,SAAS,QAAW;AACtB,eAAS,OAAO,IAAI;AACpB,kBAAY,IAAI,MAAM,CAAC;AACvB,aAAO;IACT;AAEA,QAAI,gBAAgB;AACpB,eAAW,kBAAkB,KAAK,cAAc;AAC9C,YAAM,aAAa,QAAQ,cAAc;AACzC,UAAI,aAAa,eAAe;AAC9B,wBAAgB;MAClB;IACF;AAEA,aAAS,OAAO,IAAI;AACpB,UAAM,WAAW,YAAY,IAAI,IAAI,IAAI,IAAI,gBAAgB;AAC7D,gBAAY,IAAI,MAAM,QAAQ;AAC9B,WAAO;EACT;AAEA,aAAW,QAAQ,WAAW,KAAK,GAAG;AACpC,YAAQ,IAAI;EACd;AAEA,MAAI,WAAW;AACf,aAAW,SAAS,YAAY,OAAO,GAAG;AACxC,QAAI,QAAQ,UAAU;AACpB,iBAAW;IACb;EACF;AAEA,SAAO,EAAE,aAAa,SAAS;AACjC;AAEA,IAAM,iBAAiB,CACrB,OACA,kBACA,aACA,SAEA,CAAC,GAAG,KAAK,EACN,IAAI,CAAC,UAAU;EACd,MAAM,KAAK;EACX,YAAY,iBAAiB,IAAI,KAAK,IAAI,KAAK;EAC/C,QAAQ,KAAK,aAAa;EAC1B,QAAQ,YAAY,IAAI,KAAK,IAAI;AACnC,EAAE,EACD;EACC,CAAC,GAAG,MACF,EAAE,aAAa,EAAE,cACjB,EAAE,SAAS,EAAE,UACb,EAAE,KAAK,cAAc,EAAE,IAAI;AAC/B,EACC,MAAM,GAAG,IAAI;AAElB,IAAM,qBAAqB,CAAC,WAC1B,WAAW,eACX,WAAW,qBACX,WAAW,gBACX,WAAW;AAEb,IAAM,gCAAgC,CACpC,UACA,eACsB;AACtB,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAQ,CAAC,GAAI,WAAW,IAAI,QAAQ,GAAG,gBAAgB,CAAC,CAAE;AAEhE,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,UAAU,MAAM,IAAI;AAC1B,QAAI,YAAY,UAAa,KAAK,IAAI,OAAO,KAAK,YAAY,UAAU;AACtE;IACF;AAEA,SAAK,IAAI,OAAO;AAChB,UAAM,cAAc,WAAW,IAAI,OAAO;AAC1C,QAAI,gBAAgB,QAAW;AAC7B;IACF;AAEA,eAAW,QAAQ,YAAY,cAAc;AAC3C,UAAI,CAAC,KAAK,IAAI,IAAI,GAAG;AACnB,cAAM,KAAK,IAAI;MACjB;IACF;EACF;AAEA,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACpD;AAEO,IAAM,+BAA+B,CAC1C,YACA,YACA,eACA,WAC4B;AAC5B,QAAM,QAAQ,eAAe,WAAW,KAAK;AAC7C,QAAM,cAAc,IAAI,IAAI,WAAW,mBAAmB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;AAChF,QAAM,mBAAmB,IAAI,IAAI,WAAW,mBAAmB,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,IAAI,cAAc,CAAC,CAAC;AAE3G,QAAM,aAAa,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC;AACjE,QAAM,mBAAmB,oBAAI,IAAoB;AAEjD,aAAW,QAAQ,OAAO;AACxB,qBAAiB,IAAI,KAAK,MAAM,iBAAiB,IAAI,KAAK,IAAI,KAAK,CAAC;EACtE;AAEA,aAAW,QAAQ,OAAO;AACxB,eAAW,kBAAkB,KAAK,cAAc;AAC9C,UAAI,CAAC,WAAW,IAAI,cAAc,GAAG;AACnC;MACF;AAEA,uBAAiB,IAAI,iBAAiB,iBAAiB,IAAI,cAAc,KAAK,KAAK,CAAC;IACtF;EACF;AAEA,QAAM,EAAE,aAAa,SAAS,IAAI,cAAc,YAAY,WAAW;AACvE,QAAM,oBAAoB,eAAe,OAAO,kBAAkB,aAAa,OAAO,cAAc;AAEpG,QAAM,kBAAkB,IAAI;IAC1B,kBACG,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,kBAAkB,SAAS,IAAI,CAAC,CAAC,EAChE,IAAI,CAAC,UAAU,MAAM,IAAI;EAC9B;AAEA,QAAM,kBAA8C,CAAC;AACrD,MAAI,yBAAyB;AAE7B,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,cAAc,IAAI,KAAK,GAAG,KAAK;AAChD,QAAI,aAAa,MAAM;AACrB,gCAA0B;IAC5B;AAEA,UAAM,kBAAkB,YAAY,IAAI,KAAK,IAAI,KAAK;AACtD,UAAM,aAAa,iBAAiB,IAAI,KAAK,IAAI,KAAK;AAEtD,UAAM,cAAsC,CAAC;AAE7C,SAAK,UAAU,mBAAmB,OAAO,GAAG;AAC1C,kBAAY,KAAK,mBAAmB;IACtC;AAEA,SAAK,UAAU,wBAAwB,MAAM,OAAO,wBAAwB;AAC1E,kBAAY,KAAK,WAAW;IAC9B;AAEA,QAAI,gBAAgB,IAAI,KAAK,IAAI,KAAK,aAAa,GAAG;AACpD,kBAAY,KAAK,iBAAiB;IACpC;AAEA,QAAI,mBAAmB,OAAO,oBAAoB;AAChD,kBAAY,KAAK,YAAY;IAC/B;AAEA,QAAI,KAAK,aAAa,UAAU,OAAO,qBAAqB;AAC1D,kBAAY,KAAK,aAAa;IAChC;AAEA,QAAI,aAAa,MAAM;AACrB,kBAAY,KAAK,sBAAsB;IACzC;AAEA,oBAAgB,KAAK;MACnB,MAAM,KAAK;MACX,QAAQ,YAAY,IAAI,KAAK,IAAI;MACjC,gBAAgB,iBAAiB,IAAI,KAAK,IAAI,KAAK;MACnD,iBAAiB,KAAK;MACtB,wBAAwB,CAAC;MACzB;MACA,QAAQ,KAAK,aAAa;MAC1B;MACA,iBAAiB,UAAU,mBAAmB;MAC9C,sBAAsB,UAAU,wBAAwB;MACxD,sBAAsB,UAAU,wBAAwB;MACxD,uBAAuB,UAAU,yBAAyB;MAC1D,WAAW,UAAU,aAAa;MAClC,gBAAgB,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;MAClE,sBAAsB,CAAC;MACvB;IACF,CAAC;EACH;AAEA,kBAAgB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAE3D,QAAM,YAAY,IAAI,IAAI,gBAAgB,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;AAEvE,QAAM,eAA2C,gBAC9C,OAAO,CAAC,QAAQ,IAAI,MAAM,EAC1B,IAAI,CAAC,QAAQ;AACZ,UAAM,yBAAyB,8BAA8B,IAAI,MAAM,UAAU;AACjF,UAAM,mBAAmB,oBAAI,IAA0B;AACvD,UAAM,aAAa,IAAI,IAAI,IAAI,cAAc;AAE7C,eAAW,kBAAkB,wBAAwB;AACnD,YAAM,aAAa,UAAU,IAAI,cAAc;AAC/C,UAAI,eAAe,QAAW;AAC5B;MACF;AAEA,iBAAW,UAAU,WAAW,aAAa;AAC3C,YAAI,mBAAmB,MAAM,GAAG;AAC9B,2BAAiB,IAAI,MAAM;AAC3B,qBAAW,IAAI,MAAM;QACvB;MACF;IACF;AAEA,WAAO;MACL,GAAG;MACH;MACA,sBAAsB,CAAC,GAAG,gBAAgB,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;MAC7E,aAAa,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;IAChE;EACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAE9C,QAAM,uBAAuB,aAC1B,OAAO,CAAC,QAAQ,IAAI,YAAY,SAAS,CAAC,EAC1C,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,SAAS,EAAE,YAAY,UAAU,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,EAC1F,MAAM,GAAG,OAAO,uBAAuB,EACvC,IAAI,CAAC,QAAQ,IAAI,IAAI;AAExB,QAAM,+BAA+B,aAClC,OAAO,CAAC,QAAQ,IAAI,eAAe,SAAS,mBAAmB,CAAC,EAChE,IAAI,CAAC,QAAQ,IAAI,IAAI,EACrB,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpC,QAAM,wBAAwB,aAC3B,OAAO,CAAC,QAAQ,IAAI,eAAe,SAAS,WAAW,CAAC,EACxD,IAAI,CAAC,QAAQ,IAAI,IAAI,EACrB,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpC,SAAO;IACL;IACA,WAAW;IACX,SAAS;MACP,mBAAmB,gBAAgB;MACnC,oBAAoB,aAAa;MACjC,wBAAwB,gBAAgB,SAAS,aAAa;MAC9D,iBAAiB;MACjB,cAAc,WAAW;MACzB,kBAAkB,gBAAgB,WAAW,IAAI,IAAI,OAAO,yBAAyB,gBAAgB,MAAM;IAC7G;IACA;IACA;IACA;IACA;IACA;EACF;AACF;ACpSO,IAAM,mCAA2D;EACtE,wBAAwB;EACxB,oBAAoB;EACpB,qBAAqB;EACrB,gBAAgB;EAChB,yBAAyB;EACzB,4BAA4B;AAC9B;ACvCA,IAAM,sBAAiH;EACrH,EAAE,UAAU,kBAAkB,MAAM,OAAO;EAC3C,EAAE,UAAU,qBAAqB,MAAM,MAAM;EAC7C,EAAE,UAAU,uBAAuB,MAAM,iBAAiB;EAC1D,EAAE,UAAU,aAAa,MAAM,OAAO;EACtC,EAAE,UAAU,YAAY,MAAM,MAAM;EACpC,EAAE,UAAU,aAAa,MAAM,MAAM;AACvC;AAQO,IAAM,kBAAkB,CAAC,mBAAiE;AAC/F,QAAMC,mBAAkB,KAAK,gBAAgB,cAAc;AAC3D,MAAI,CAAC,WAAWA,gBAAe,GAAG;AAChC,WAAO;EACT;AAEA,SAAO;IACL,MAAMA;IACN,KAAK,aAAaA,kBAAiB,MAAM;EAC3C;AACF;AAEO,IAAM,iBAAiB,CAAC,mBAAqD;AAClF,aAAW,aAAa,qBAAqB;AAC3C,UAAM,eAAe,KAAK,gBAAgB,UAAU,QAAQ;AAC5D,QAAI,CAAC,WAAW,YAAY,GAAG;AAC7B;IACF;AAEA,WAAO;MACL,MAAM;MACN,MAAM,UAAU;MAChB,KAAK,aAAa,cAAc,MAAM;IACxC;EACF;AAEA,SAAO;AACT;AC3CO,IAAM,mBAAmB,CAAC,QAAiD;AAChF,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAM,SAAS,oBAAI,IAAoB;AAEvC,aAAW,SAAS;IAClB,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;EACT,GAAG;AACD,QAAI,UAAU,QAAW;AACvB;IACF;AAEA,eAAW,CAAC,MAAM,YAAY,KAAK,OAAO,QAAQ,KAAK,GAAG;AACxD,aAAO,IAAI,MAAM,YAAY;IAC/B;EACF;AAEA,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EACxB,IAAI,CAAC,CAAC,MAAM,cAAc,OAAO,EAAE,MAAM,eAAe,EAAE,EAC1D,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAChD;AClBO,IAAM,mBAAmB,CAAC,KAAa,gBAAqE;AACjH,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAM,QAAgC,CAAC;AAEvC,MAAI,OAAO,aAAa,QAAW;AACjC,eAAW,CAAC,aAAa,WAAW,KAAK,OAAO,QAAQ,OAAO,QAAQ,GAAG;AACxE,UAAI,YAAY,WAAW,KAAK,YAAY,YAAY,QAAW;AACjE;MACF;AAEA,YAAM,WAAW,YAAY,MAAM,eAAe;AAClD,YAAM,OAAO,SAAS,SAAS,SAAS,CAAC,KAAK;AAC9C,UAAI,KAAK,WAAW,GAAG;AACrB;MACF;AAEA,YAAM,eAAe,OAAO,QAAQ,YAAY,gBAAgB,CAAC,CAAC,EAC/D,IAAI,CAAC,CAAC,SAAS,QAAQ,MAAM,GAAG,OAAO,IAAI,OAAO,QAAQ,CAAC,EAAE,EAC7D,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpC,YAAM,KAAK;QACT;QACA,SAAS,YAAY;QACrB;MACF,CAAC;IACH;EACF,WAAW,OAAO,iBAAiB,QAAW;AAC5C,eAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,OAAO,YAAY,GAAG;AAC7D,UAAI,IAAI,YAAY,QAAW;AAC7B;MACF;AAEA,YAAM,eAAe,OAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,EACvD,IAAI,CAAC,CAAC,SAAS,UAAU,MAAM,GAAG,OAAO,IAAI,OAAO,UAAU,CAAC,EAAE,EACjE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEpC,YAAM,KAAK;QACT;QACA,SAAS,IAAI;QACb;MACF,CAAC;IACH;EACF;AAEA,QAAM,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAC;AAEvF,SAAO;IACL,MAAM;IACN,oBAAoB;IACpB;EACF;AACF;AC5DA,IAAM,gBAAgB,CAAC,UAA0B,MAAM,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAExF,IAAM,kBAAkB,CAAC,WAA6D;AACpF,QAAM,MAAM,cAAc,OAAO,QAAQ,MAAM,EAAE,CAAC;AAClD,QAAM,eAAe,IAAI,WAAW,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI;AAE1D,QAAM,SAAS,aAAa,YAAY,GAAG;AAC3C,MAAI,UAAU,GAAG;AACf,WAAO;EACT;AAEA,QAAM,OAAO,aAAa,MAAM,GAAG,MAAM;AACzC,QAAM,mBAAmB,aAAa,MAAM,SAAS,CAAC;AACtD,QAAMC,WAAU,iBAAiB,MAAM,GAAG,EAAE,CAAC,KAAK;AAElD,MAAI,KAAK,WAAW,KAAKA,SAAQ,WAAW,GAAG;AAC7C,WAAO;EACT;AAEA,SAAO,EAAE,MAAM,SAAAA,SAAQ;AACzB;AAEO,IAAM,oBAAoB,CAAC,KAAa,gBAAqE;AAClH,QAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,MAAI,QAAqB;AACzB,MAAI,iBAAgC;AACpC,MAAI,wBAAuC;AAC3C,QAAM,qBAAqB,oBAAI,IAAyB;AAExD,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,KAAK,EAAE,WAAW,KAAK,KAAK,UAAU,EAAE,WAAW,GAAG,GAAG;AAChE;IACF;AAEA,QAAI,KAAK,WAAW,YAAY,GAAG;AACjC,cAAQ;AACR;IACF;AAEA,QAAI,KAAK,WAAW,WAAW,GAAG;AAChC,cAAQ;AACR;IACF;AAEA,QAAI,UAAU,cAAc,UAAU,eAAe;AACnD,YAAM,eAAe,KAAK,MAAM,sBAAsB;AACtD,UAAI,iBAAiB,MAAM;AACzB,cAAM,YAAY,gBAAgB,aAAa,CAAC,KAAK,EAAE;AACvD,YAAI,cAAc,MAAM;AACtB,2BAAiB,GAAG,UAAU,IAAI,IAAI,UAAU,OAAO;AACvD,6BAAmB,IAAI,gBAAgB,oBAAI,IAAI,CAAC;AAChD,kBAAQ;AACR,kCAAwB;QAC1B;AACA;MACF;IACF;AAEA,QAAI,UAAU,iBAAiB,mBAAmB,MAAM;AACtD,YAAM,UAAU,KAAK,MAAM,0BAA0B;AACrD,UAAI,YAAY,MAAM;AACpB,cAAM,UAAU,cAAc,QAAQ,CAAC,KAAK,EAAE;AAC9C,cAAM,SAAS,cAAc,QAAQ,CAAC,KAAK,EAAE;AAC7C,cAAM,aAAa,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AAE3C,YAAI,QAAQ,SAAS,KAAK,WAAW,SAAS,GAAG;AAC/C,6BAAmB,IAAI,cAAc,GAAG,IAAI,GAAG,OAAO,IAAI,UAAU,EAAE;QACxE;AACA,gCAAwB;AACxB;MACF;AAEA,YAAM,eAAe,KAAK,MAAM,sBAAsB;AACtD,UAAI,iBAAiB,MAAM;AACzB,gCAAwB,cAAc,aAAa,CAAC,KAAK,EAAE;AAC3D;MACF;AAEA,YAAM,iBAAiB,KAAK,MAAM,wBAAwB;AAC1D,UAAI,mBAAmB,QAAQ,0BAA0B,MAAM;AAC7D,cAAM,SAAS,cAAc,eAAe,CAAC,KAAK,EAAE;AACpD,cAAM,aAAa,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AAC3C,YAAI,WAAW,SAAS,GAAG;AACzB,6BAAmB,IAAI,cAAc,GAAG,IAAI,GAAG,qBAAqB,IAAI,UAAU,EAAE;QACtF;AACA,gCAAwB;AACxB;MACF;AAEA,UAAI,KAAK,MAAM,gDAAgD,MAAM,MAAM;AACzE;MACF;IACF;EACF;AAEA,QAAM,QAAgC,CAAC,GAAG,mBAAmB,QAAQ,CAAC,EACnE,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM;AACvB,UAAM,KAAK,OAAO,YAAY,GAAG;AACjC,WAAO;MACL,MAAM,OAAO,MAAM,GAAG,EAAE;MACxB,SAAS,OAAO,MAAM,KAAK,CAAC;MAC5B,cAAc,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3D;EACF,CAAC,EACA;IAAK,CAAC,GAAG,MACR,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,QAAQ,cAAc,EAAE,OAAO;EACnE;AAEF,SAAO;IACL,MAAM;IACN,oBAAoB;IACpB;EACF;AACF;ACnHA,IAAM,cAAc,CAAC,UAA0B,MAAM,QAAQ,gBAAgB,EAAE;AAE/E,IAAM,uBAAuB,CAAC,aAAoC;AAChE,QAAM,WAAW,SAAS,YAAY,OAAO;AAC7C,MAAI,YAAY,GAAG;AACjB,WAAO,SAAS,MAAM,WAAW,CAAC;EACpC;AAEA,QAAM,SAAS,SAAS,YAAY,GAAG;AACvC,MAAI,UAAU,GAAG;AACf,WAAO;EACT;AAEA,SAAO,SAAS,MAAM,SAAS,CAAC;AAClC;AAEO,IAAM,gBAAgB,CAAC,KAAa,gBAAqE;AAC9G,QAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,QAAM,QAAgC,CAAC;AAEvC,MAAI,YAAsB,CAAC;AAC3B,MAAIA,WAAyB;AAC7B,MAAI,sBAAsB;AAC1B,MAAI,eAAyB,CAAC;AAE9B,QAAM,aAAa,MAAY;AAC7B,QAAI,UAAU,WAAW,KAAKA,aAAY,MAAM;AAC9C,kBAAY,CAAC;AACb,MAAAA,WAAU;AACV,qBAAe,CAAC;AAChB,4BAAsB;AACtB;IACF;AAEA,eAAW,YAAY,WAAW;AAChC,YAAM,gBAAgB,qBAAqB,QAAQ;AACnD,YAAM,KAAK,SAAS,YAAY,GAAG;AACnC,YAAM,OAAO,MAAM,IAAI,WAAW,SAAS,MAAM,GAAG,EAAE;AACtD,UAAI,KAAK,WAAW,GAAG;AACrB;MACF;AAEA,YAAM,KAAK;QACT;QACA,SAAAA;QACA,cAAc,CAAC,GAAG,YAAY,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;MACnE,CAAC;AAED,UAAI,kBAAkB,MAAM;AAC1B,cAAM,KAAK;UACT;UACA,SAAS;UACT,cAAc,CAAC,GAAG,YAAY,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;QACnE,CAAC;MACH;IACF;AAEA,gBAAY,CAAC;AACb,IAAAA,WAAU;AACV,mBAAe,CAAC;AAChB,0BAAsB;EACxB;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,KAAK,EAAE,WAAW,GAAG;AAC5B;IACF;AAEA,QAAI,CAAC,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAC/C,iBAAW;AACX,YAAM,UAAU,KAAK,MAAM,GAAG,EAAE;AAChC,kBAAY,QACT,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,YAAY,KAAK,KAAK,CAAC,CAAC,EACtC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACnC;IACF;AAEA,QAAI,KAAK,MAAM,kBAAkB,MAAM,MAAM;AAC3C,YAAM,QAAQ,KAAK,QAAQ,oBAAoB,EAAE,EAAE,KAAK;AACxD,MAAAA,WAAU,YAAY,KAAK;AAC3B,4BAAsB;AACtB;IACF;AAEA,QAAI,KAAK,MAAM,yBAAyB,MAAM,MAAM;AAClD,4BAAsB;AACtB;IACF;AAEA,QAAI,uBAAuB,KAAK,MAAM,gBAAgB,MAAM,MAAM;AAChE,YAAM,UAAU,KAAK,KAAK;AAC1B,YAAM,aAAa,QAAQ,QAAQ,GAAG;AACtC,UAAI,cAAc,GAAG;AACnB;MACF;AAEA,YAAM,UAAU,YAAY,QAAQ,MAAM,GAAG,UAAU,CAAC;AACxD,YAAM,SAAS,YAAY,QAAQ,MAAM,aAAa,CAAC,EAAE,KAAK,CAAC;AAC/D,YAAM,aAAa,qBAAqB,MAAM,KAAK;AACnD,mBAAa,KAAK,GAAG,OAAO,IAAI,UAAU,EAAE;AAC5C;IACF;AAEA,0BAAsB;EACxB;AAEA,aAAW;AAEX,QAAM,UAAU,oBAAI,IAAkC;AACtD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,OAAO;AACxC,QAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,cAAQ,IAAI,KAAK,IAAI;IACvB;EACF;AAEA,SAAO;IACL,MAAM;IACN,oBAAoB;IACpB,OAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,QAAQ,cAAc,EAAE,OAAO,CAAC;EAChH;AACF;AC1HO,IAAM,eAAe,CAAC,MAAc,iBAAsE;AAC/G,QAAM,IAAI,MAAM,6BAA6B;AAC/C;ACyBA,IAAM,eAAe,CAAC,eAAoF;EACxG,GAAG;EACH,GAAG;AACL;AAEA,IAAM,kBAAkB,CACtB,cACA,aACA,gBACuB;AACvB,UAAQ,cAAc;IACpB,KAAK;AACH,aAAO,kBAAkB,aAAa,WAAW;IACnD,KAAK;IACL,KAAK;AACH,aAAO;QACL,GAAG,iBAAiB,aAAa,WAAW;QAC5C,MAAM;MACR;IACF,KAAK;AACH,aAAO,cAAc,aAAa,WAAW;IAC/C,KAAK;AACH,aAAO,aAAa,aAAa,WAAW;IAC9C;AACE,YAAM,IAAI,MAAM,6BAA6B;EACjD;AACF;AAEA,IAAM,qBAAqB,OACzB,QACA,OACA,YAC0B;AAC1B,QAAM,iBAAiB,KAAK,IAAI,GAAG,KAAK;AACxC,QAAM,UAAe,IAAI,MAAM,OAAO,MAAM;AAC5C,MAAI,QAAQ;AAEZ,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,gBAAgB,OAAO,MAAM,EAAE,GAAG,YAAY;AAC1F,eAAS;AACP,YAAM,UAAU;AAChB,eAAS;AACT,UAAI,WAAW,OAAO,QAAQ;AAC5B;MACF;AAEA,YAAM,QAAQ,OAAO,OAAO;AAC5B,UAAI,UAAU,QAAW;AACvB;MACF;AAEA,cAAQ,OAAO,IAAI,MAAM,QAAQ,KAAK;IACxC;EACF,CAAC;AAED,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;AAEO,IAAM,4BAA4B,OACvC,OACA,kBACA,eACqC;AACrC,QAAM,cAAc,gBAAgB,MAAM,cAAc;AACxD,MAAI,gBAAgB,MAAM;AACxB,WAAO;MACL,YAAY,MAAM;MAClB,WAAW;MACX,QAAQ;IACV;EACF;AACA,eAAa,EAAE,OAAO,sBAAsB,CAAC;AAE7C,QAAM,WAAW,eAAe,MAAM,cAAc;AACpD,MAAI,aAAa,MAAM;AACrB,WAAO;MACL,YAAY,MAAM;MAClB,WAAW;MACX,QAAQ;IACV;EACF;AACA,eAAa,EAAE,OAAO,qBAAqB,MAAM,SAAS,KAAK,CAAC;AAEhE,MAAI;AACF,UAAM,cAAc,iBAAiB,YAAY,GAAG;AACpD,UAAM,aAAa,gBAAgB,SAAS,MAAM,SAAS,KAAK,WAAW;AAC3E,UAAM,SAAS,aAAa,MAAM,MAAM;AACxC,iBAAa;MACX,OAAO;MACP,iBAAiB,WAAW,MAAM;MAClC,oBAAoB,WAAW,mBAAmB;IACpD,CAAC;AACD,iBAAa,EAAE,OAAO,0BAA0B,OAAO,WAAW,MAAM,OAAO,CAAC;AAEhF,QAAI,YAAY;AAEhB,UAAM,kBAAkB,MAAM;MAC5B,WAAW;MACX,OAAO;MACP,OAAO,SAAS;AACd,cAAM,SAAS;UACb,KAAK,GAAG,KAAK,IAAI,IAAI,KAAK,OAAO;UACjC,UAAU,MAAM,iBAAiB,YAAY,KAAK,MAAM,KAAK,OAAO;QACtE;AACA,qBAAa;AACb,qBAAa;UACX,OAAO;UACP;UACA,OAAO,WAAW,MAAM;UACxB,aAAa,KAAK;QACpB,CAAC;AACD,eAAO;MACT;IACF;AACA,iBAAa,EAAE,OAAO,4BAA4B,OAAO,WAAW,MAAM,OAAO,CAAC;AAElF,UAAM,gBAAgB,oBAAI,IAAmE;AAC7F,eAAW,SAAS,iBAAiB;AACnC,oBAAc,IAAI,MAAM,KAAK,MAAM,QAAQ;IAC7C;AAEA,UAAM,UAAU,6BAA6B,MAAM,gBAAgB,YAAY,eAAe,MAAM;AACpG,QAAI,QAAQ,WAAW;AACrB,mBAAa;QACX,OAAO;QACP,mBAAmB,QAAQ,QAAQ;QACnC,oBAAoB,QAAQ,QAAQ;MACtC,CAAC;IACH;AAEA,WAAO;EACT,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,QAAI,QAAQ,SAAS,6BAA6B,GAAG;AACnD,aAAO;QACL,YAAY,MAAM;QAClB,WAAW;QACX,QAAQ;MACV;IACF;AAEA,WAAO;MACL,YAAY,MAAM;MAClB,WAAW;MACX,QAAQ;IACV;EACF;AACF;ACzKA,IAAM,aAAa,KAAK,KAAK,KAAK;AAElC,IAAMC,UAAS,CAAC,UAA0B,OAAO,MAAM,QAAQ,CAAC,CAAC;AAEjE,IAAM,YAAY,CAAC,QAA2C;AAC5D,MAAI,QAAQ,QAAW;AACrB,WAAO;EACT;AAEA,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,SAAO,OAAO,MAAM,KAAK,IAAI,OAAO;AACtC;AAEO,IAAM,8BAAN,MAAwE;EAC5D,QAAQ,oBAAI,IAAuC;EAEpE,MAAM,YAAY,MAAcD,UAAqD;AACnF,UAAM,MAAM,GAAG,IAAI,IAAIA,QAAO;AAC9B,QAAI,KAAK,MAAM,IAAI,GAAG,GAAG;AACvB,aAAO,KAAK,MAAM,IAAI,GAAG,KAAK;IAChC;AAEA,QAAI;AACF,YAAM,cAAc,mBAAmB,IAAI;AAC3C,YAAM,WAAW,MAAM,MAAM,8BAA8B,WAAW,EAAE;AACxE,UAAI,CAAC,SAAS,IAAI;AAChB,aAAK,MAAM,IAAI,KAAK,IAAI;AACxB,eAAO;MACT;AAEA,YAAM,UAAW,MAAM,SAAS,KAAK;AACrC,YAAM,cAAc,QAAQ,QAAQ,CAAC;AAErC,YAAM,eAAe,OAAO,QAAQ,WAAW,EAC5C,OAAO,CAAC,CAAC,GAAG,MAAM,QAAQ,aAAa,QAAQ,UAAU,EACzD,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,UAAU,IAAI,CAAC,EACjC,OAAO,CAAC,UAA2B,UAAU,IAAI,EACjD,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAEvB,YAAM,aAAa,UAAU,YAAY,UAAU,CAAC;AACpD,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,uBAAuB,eAAe,OAAO,OAAO,KAAK,IAAI,GAAGC,SAAQ,MAAM,cAAc,UAAU,CAAC;AAE7G,UAAI,uBAAsC;AAC1C,UAAI,aAAa,UAAU,GAAG;AAC5B,cAAM,iBAAiB,aAAa,SAAS;AAC7C,YAAI,MAAM;AACV,iBAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAAG;AAC/C,gBAAM,UAAU,aAAa,CAAC;AAC9B,gBAAM,WAAW,aAAa,IAAI,CAAC;AACnC,cAAI,YAAY,UAAa,aAAa,QAAW;AACnD,mBAAO,UAAU;UACnB;QACF;AAEA,+BAAuBA,QAAO,MAAM,iBAAiB,UAAU;MACjE;AAEA,YAAM,cAAc,QAAQ,eAAe,CAAC;AAC5C,YAAM,kBAAkB,YAAY,SAAS,IAAI,YAAY,SAAS;AAEtE,YAAM,WAA+B;QACnC;QACA,SAAAD;QACA;QACA;QACA;QACA,uBAAuB;QACvB,WAAW;MACb;AAEA,WAAK,MAAM,IAAI,KAAK,QAAQ;AAC5B,aAAO;IACT,QAAQ;AACN,WAAK,MAAM,IAAI,KAAK,IAAI;AACxB,aAAO;IACT;EACF;AACF;ACnFO,IAAM,uBAAN,MAAiE;EACtE,MAAM,YAAY,OAAe,UAAsD;AACrF,WAAO;EACT;AACF;ACMO,IAAM,uCAAuC,OAClD,OACA,eACqC;AACrC,QAAM,mBACJ,QAAQ,IAAI,gCAAgC,MAAM,SAC9C,IAAI,qBAAqB,IACzB,IAAI,4BAA4B;AAEtC,SAAO,0BAA0B,OAAO,kBAAkB,UAAU;AACtE;;;AItBA,SAAS,oBAAoB;AH0B7B,IAAM,UAAU,CAAC,GAAW,MAAsB,GAAG,CAAC,KAAS,CAAC;AAEhE,IAAME,UAAS,CAAC,UAA0B,OAAO,MAAM,QAAQ,CAAC,CAAC;AAEjE,IAAM,gBAAgB,CAAC,UACrB,MACG,YAAY,EACZ,QAAQ,gBAAgB,GAAG,EAC3B,QAAQ,QAAQ,GAAG,EACnB,KAAK;AAEV,IAAM,mBAAmB,CAAC,aAAoC;AAC5D,QAAM,aAAa,SAAS,KAAK,EAAE,YAAY;AAC/C,QAAM,qBAAqB,WAAW,MAAM,4CAA4C;AACxF,MAAI,qBAAqB,CAAC,MAAM,QAAW;AACzC,WAAO,mBAAmB,CAAC,EAAE,QAAQ,WAAW,EAAE;EACpD;AAEA,QAAM,UAAU,WAAW,QAAQ,GAAG;AACtC,MAAI,WAAW,GAAG;AAChB,WAAO;EACT;AAEA,SAAO,WAAW,MAAM,GAAG,OAAO,EAAE,QAAQ,WAAW,EAAE;AAC3D;AAEA,IAAM,qBAAqB,CAAC,MAAc,UAA2B;AACnE,MAAI,KAAK,WAAW,KAAK,MAAM,WAAW,GAAG;AAC3C,WAAO;EACT;AAEA,MAAI,SAAS,OAAO;AAClB,WAAO;EACT;AAEA,MAAI,KAAK,WAAW,GAAG,KAAK,GAAG,KAAK,MAAM,WAAW,GAAG,IAAI,GAAG,GAAG;AAChE,WAAO;EACT;AAEA,SAAO;AACT;AAEA,IAAM,0BAA0B,CAAC,aAA+C;AAC9E,QAAM,UAAU,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM;AAC3C,UAAM,aAAa,EAAE,SAAS,SAAS,2BAA2B;AAClE,UAAM,aAAa,EAAE,SAAS,SAAS,2BAA2B;AAClE,QAAI,eAAe,YAAY;AAC7B,aAAO,aAAa,IAAI;IAC1B;AAEA,QAAI,EAAE,gBAAgB,EAAE,aAAa;AACnC,aAAO,EAAE,cAAc,EAAE;IAC3B;AAEA,WAAO,EAAE,SAAS,cAAc,EAAE,QAAQ;EAC5C,CAAC;AAED,SAAO,QAAQ,CAAC,GAAG,YAAY;AACjC;AAEA,IAAM,sBAAsB,CAAC,YAAqE;AAChG,QAAM,uBAAuB,oBAAI,IAAiC;AAClE,QAAM,wBAAwB,oBAAI,IAAoB;AAEtD,aAAW,UAAU,SAAS;AAC5B,0BAAsB,IAAI,OAAO,WAAW,sBAAsB,IAAI,OAAO,QAAQ,KAAK,KAAK,CAAC;AAEhG,UAAM,iBAAiB,cAAc,OAAO,UAAU;AACtD,UAAM,QAAQ,qBAAqB,IAAI,OAAO,QAAQ,KAAK,oBAAI,IAAoB;AACnF,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,IAAI,iBAAiB,MAAM,IAAI,cAAc,KAAK,KAAK,CAAC;IAChE;AACA,yBAAqB,IAAI,OAAO,UAAU,KAAK;EACjD;AAEA,QAAM,WAA4B,CAAC,GAAG,sBAAsB,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,UAAU,WAAW,MAAM;AACtG,UAAM,QAAQ,qBAAqB,IAAI,QAAQ;AAC/C,UAAM,cACJ,UAAU,SACN,KACA,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AAC9F,UAAM,qBAAqB,SAAS,YAAY;AAChD,UAAM,QAAQ,mBAAmB,SAAS,OAAO;AAEjD,WAAO;MACL;MACA;MACA;MACA,WAAW,QAAQ,OAAO,iBAAiB,QAAQ;MACnD;IACF;EACF,CAAC;AAED,QAAM,eAAe,oBAAI,IAA6B;AACtD,aAAW,WAAW,UAAU;AAC9B,QAAI,QAAQ,cAAc,QAAQ,QAAQ,UAAU,SAAS,GAAG;AAC9D;IACF;AAEA,UAAM,UAAU,aAAa,IAAI,QAAQ,SAAS,KAAK,CAAC;AACxD,YAAQ,KAAK,OAAO;AACpB,iBAAa,IAAI,QAAQ,WAAW,OAAO;EAC7C;AAEA,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,WAAW,UAAU;AAC9B,aAAS,IAAI,QAAQ,UAAU,QAAQ,QAAQ;EACjD;AAEA,aAAW,SAAS,aAAa,OAAO,GAAG;AACzC,QAAI,MAAM,SAAS,GAAG;AACpB;IACF;AAEA,UAAM,aAA8B,CAAC;AACrC,eAAW,WAAW,OAAO;AAC3B,UAAI,QAAQ,SAAS,QAAQ,YAAY,WAAW,GAAG;AACrD;MACF;AAEA,iBAAW,KAAK,OAAO;IACzB;AAEA,QAAI,WAAW,SAAS,GAAG;AACzB;IACF;AAEA,UAAM,YAAY,wBAAwB,UAAU;AACpD,UAAM,mBAAmB,WAAW,KAAK,CAAC,cAAc,UAAU,aAAa,SAAS;AACxF,QAAI,qBAAqB,QAAW;AAClC;IACF;AAEA,eAAW,WAAW,YAAY;AAChC,UAAI,mBAAmB,QAAQ,aAAa,iBAAiB,WAAW,GAAG;AACzE,iBAAS,IAAI,QAAQ,UAAU,SAAS;MAC1C;IACF;EACF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CACvB,oBACA,cACW;AACX,MAAI,mBAAmB,WAAW,GAAG;AACnC,WAAO;EACT;AAEA,MAAI,eAAe;AACnB,WAAS,IAAI,GAAG,IAAI,mBAAmB,QAAQ,KAAK,GAAG;AACrD,UAAM,QAAQ,mBAAmB,CAAC;AAClC,QAAI,UAAU,QAAW;AACvB;IACF;AAEA,oBAAgB,MAAM;AACtB,QAAI,gBAAgB,WAAW;AAC7B,aAAO,IAAI;IACb;EACF;AAEA,SAAO,mBAAmB;AAC5B;AAEA,IAAM,6BAA6B,CAAC,kBAA2E;AAC7G,QAAM,eAAe,CAAC,GAAG,cAAc,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,UAAU,MAAM,OAAO,CAAC;AACtF,MAAI,iBAAiB,GAAG;AACtB,WAAO,CAAC;EACV;AAEA,SAAO,CAAC,GAAG,cAAc,QAAQ,CAAC,EAC/B,IAAI,CAAC,CAAC,UAAU,OAAO,OAAO;IAC7B;IACA;IACA,OAAOA,QAAO,UAAU,YAAY;EACtC,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,cAAc,EAAE,QAAQ,CAAC;AACjF;AAEA,IAAM,sBAAsB,CAC1B,gBACA,iBACA,mBACA,qBACA,qBACmB;AACnB,QAAM,WAA2B,CAAC;AAElC,aAAW,CAAC,KAAK,eAAe,KAAK,eAAe,QAAQ,GAAG;AAC7D,UAAM,CAAC,OAAO,KAAK,IAAI,IAAI,MAAM,IAAQ;AACzC,QAAI,UAAU,UAAa,UAAU,QAAW;AAC9C;IACF;AAEA,UAAM,eAAe,gBAAgB,IAAI,KAAK,KAAK;AACnD,UAAM,eAAe,gBAAgB,IAAI,KAAK,KAAK;AACnD,UAAM,cAAc,eAAe,eAAe;AAClD,UAAM,gBAAgB,gBAAgB,IAAI,IAAIA,QAAO,kBAAkB,WAAW;AAElF,aAAS,KAAK;MACZ;MACA;MACA;MACA;IACF,CAAC;EACH;AAEA,WAAS;IACP,CAAC,GAAG,MACF,EAAE,kBAAkB,EAAE,mBACtB,EAAE,gBAAgB,EAAE,iBACpB,EAAE,MAAM,cAAc,EAAE,KAAK,KAC7B,EAAE,MAAM,cAAc,EAAE,KAAK;EACjC;AAEA,QAAM,YAAY,SAAS,SAAS;AAEpC,SAAO;IACL,OAAO,YAAY,SAAS,MAAM,GAAG,gBAAgB,IAAI;IACzD,gBAAgB,SAAS;IACzB;IACA;IACA;EACF;AACF;AAEA,IAAM,iBAAiB,CACrB,OACA,WACwD;AACxD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,UAAU,CAAC,GAAG,WAAW,EAAE;EACtC;AAEA,QAAM,SAAS,CAAC,GAAG,KAAK,EAAE;IACxB,CAAC,GAAG,MACF,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,cAAc,EAAE,QAAQ;EACvG;AAEA,QAAM,eAAe,KAAK,IAAI,OAAO,iBAAiB,KAAK,KAAK,OAAO,SAAS,OAAO,iBAAiB,CAAC;AACzG,QAAM,WAAW,OAAO,MAAM,GAAG,YAAY;AAE7C,QAAM,WAAW,SAAS,IAAI,CAAC,MAAM,WAAW;IAC9C,UAAU,KAAK;IACf,MAAM,QAAQ;IACd,aAAa,KAAK;IAClB,YAAY,KAAK;EACnB,EAAE;AAEF,QAAM,YAAY,SAAS,SAAS,SAAS,CAAC,GAAG,eAAe;AAChE,SAAO,EAAE,UAAU,UAAU;AAC/B;AAEO,IAAM,oCAAoC,CAC/C,YACA,SACA,WAC+B;AAC/B,QAAM,kBACJ,OAAO,uBAAuB,iBAAiB,oBAAoB,OAAO,IAAI,oBAAI,IAAoB;AACxG,QAAM,YAAY,oBAAI,IAA6B;AACnD,QAAM,iBAAiB,oBAAI,IAAoB;AAE/C,QAAM,sBAAsB,QAAQ,WAAW,IAAI,OAAO,QAAQ,QAAQ,SAAS,CAAC,GAAG,kBAAkB;AACzG,QAAM,oBACJ,wBAAwB,OACpB,OAAO,oBACP,sBAAsB,OAAO,mBAAmB,KAAK,KAAK;AAEhE,MAAI,oBAAoB;AACxB,MAAI,sBAAsB;AAE1B,aAAW,UAAU,SAAS;AAC5B,UAAM,cAAc,oBAAI,IAAY;AAEpC,eAAW,cAAc,OAAO,aAAa;AAC3C,kBAAY,IAAI,WAAW,QAAQ;AACnC,YAAM,UAAU,UAAU,IAAI,WAAW,QAAQ,KAAK;QACpD,aAAa;QACb,mBAAmB;QACnB,YAAY;QACZ,cAAc;QACd,SAAS,oBAAI,IAAoB;MACnC;AAEA,cAAQ,cAAc,WAAW;AACjC,cAAQ,gBAAgB,WAAW;AACnC,gBAAU,IAAI,WAAW,UAAU,OAAO;IAC5C;AAEA,eAAW,YAAY,aAAa;AAClC,YAAM,UAAU,UAAU,IAAI,QAAQ;AACtC,UAAI,YAAY,QAAW;AACzB;MACF;AAEA,cAAQ,eAAe;AACvB,UAAI,OAAO,kBAAkB,mBAAmB;AAC9C,gBAAQ,qBAAqB;MAC/B;AAEA,YAAM,oBAAoB,gBAAgB,IAAI,OAAO,QAAQ,KAAK,OAAO;AACzE,cAAQ,QAAQ,IAAI,oBAAoB,QAAQ,QAAQ,IAAI,iBAAiB,KAAK,KAAK,CAAC;IAC1F;AAEA,UAAM,eAAe,CAAC,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACvE,QAAI,aAAa,SAAS,GAAG;AAC3B,UAAI,aAAa,UAAU,OAAO,8BAA8B;AAC9D,6BAAqB;AACrB,iBAAS,IAAI,GAAG,IAAI,aAAa,SAAS,GAAG,KAAK,GAAG;AACnD,mBAAS,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAAG;AACnD,kBAAM,QAAQ,aAAa,CAAC;AAC5B,kBAAM,QAAQ,aAAa,CAAC;AAC5B,gBAAI,UAAU,UAAa,UAAU,QAAW;AAC9C;YACF;AAEA,kBAAM,MAAM,QAAQ,OAAO,KAAK;AAChC,2BAAe,IAAI,MAAM,eAAe,IAAI,GAAG,KAAK,KAAK,CAAC;UAC5D;QACF;MACF,OAAO;AACL,+BAAuB;MACzB;IACF;EACF;AAEA,QAAM,QAAgC,CAAC,GAAG,UAAU,QAAQ,CAAC,EAC1D,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM;AAC1B,UAAM,qBAAqB,2BAA2B,MAAM,OAAO;AACnE,UAAM,iBAAiB,mBAAmB,CAAC,GAAG,SAAS;AACvD,WAAO;MACL;MACA,aAAa,MAAM;MACnB,wBAAwB,QAAQ,WAAW,IAAI,IAAIA,QAAQ,MAAM,cAAc,QAAQ,SAAU,GAAG;MACpG,YAAY,MAAM;MAClB,cAAc,MAAM;MACpB,YAAY,MAAM,aAAa,MAAM;MACrC,mBAAmB,MAAM;MACzB,kBAAkB,MAAM,gBAAgB,IAAI,IAAIA,QAAO,MAAM,oBAAoB,MAAM,WAAW;MAClG;MACA,WAAW,iBAAiB,oBAAoB,OAAO,0BAA0B;MACjF;IACF;EACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,cAAc,EAAE,QAAQ,CAAC;AAEtD,QAAM,kBAAkB,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,UAAU,KAAK,WAAW,CAAC,CAAC;AACtF,QAAM,WAAW;IACf;IACA;IACA;IACA;IACA,OAAO;EACT;AAEA,QAAM,EAAE,UAAU,UAAU,IAAI,eAAe,OAAO,MAAM;AAE5D,SAAO;IACL;IACA,WAAW;IACX;IACA;IACA;IACA,SAAS;MACP,cAAc,QAAQ;MACtB,YAAY,MAAM;MAClB;MACA,kBAAkB,OAAO;MACzB,mBAAmB,OAAO;MAC1B,6BAA6B;IAC/B;EACF;AACF;AC1XO,IAAM,2BAAuD;EAClE,oBAAoB;EACpB,kBAAkB;EAClB,mBAAmB;EACnB,iBAAiB;EACjB,8BAA8B;EAC9B,kBAAkB;EAClB,4BAA4B;AAC9B;ACXA,IAAM,wBAAwB,CAC5B,eACgC;EAChC,GAAG;EACH,GAAG;AACL;AAEO,IAAM,6BAA6B,CACxC,OACA,iBACA,eAC+B;AAC/B,eAAa,EAAE,OAAO,0BAA0B,CAAC;AACjD,MAAI,CAAC,gBAAgB,gBAAgB,MAAM,cAAc,GAAG;AAC1D,iBAAa,EAAE,OAAO,qBAAqB,CAAC;AAC5C,WAAO;MACL,YAAY,MAAM;MAClB,WAAW;MACX,QAAQ;IACV;EACF;AAEA,eAAa,EAAE,OAAO,yBAAyB,CAAC;AAChD,QAAM,UAAU,gBAAgB;IAAiB,MAAM;IAAgB,CAAC,UACtE,aAAa,EAAE,OAAO,WAAW,MAAM,CAAC;EAC1C;AACA,QAAM,SAAS,sBAAsB,MAAM,MAAM;AACjD,eAAa,EAAE,OAAO,oBAAoB,CAAC;AAE3C,QAAM,UAAU,kCAAkC,MAAM,gBAAgB,SAAS,MAAM;AACvF,eAAa,EAAE,OAAO,sBAAsB,WAAW,QAAQ,UAAU,CAAC;AAC1E,SAAO;AACT;ACnDO,IAAM,kBAAN,cAA8B,MAAM;EAChC;EAET,YAAY,SAAiB,MAAyB;AACpD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;EACd;AACF;AAMO,IAAM,uBAAN,MAAuD;EAC5D,IAAI,gBAAwB,MAAiC;AAC3D,QAAI;AACF,aAAO,aAAa,OAAO,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG;QAC1D,UAAU;QACV,WAAW,OAAO,OAAO;QACzB,OAAO,CAAC,UAAU,QAAQ,MAAM;MAClC,CAAC;IACH,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,YAAM,IAAI,gBAAgB,SAAS,IAAI;IACzC;EACF;AACF;AC7BO,IAAM,0BAA0B;AAChC,IAAM,yBAAyB;AAE/B,IAAM,iBACX;ACYK,IAAM,oCAAoC,CAC/C,WAC6B;EAC7B,OAAO;EACP,eAAe,MAAM;EACrB,cAAc,MAAM;AACtB;ACdA,IAAM,eAAe,CAAC,UAAiC;AACrD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;EACT;AAEA,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,MAAI,OAAO,MAAM,MAAM,GAAG;AACxB,WAAO;EACT;AAEA,SAAO;AACT;AAEA,IAAM,0BAA0B,CAAC,YAAoB,gBAAgC;AACnF,QAAM,iBAAiB,WAAW,KAAK,EAAE,QAAQ,QAAQ,GAAG,EAAE,YAAY;AAC1E,QAAM,kBAAkB,YAAY,KAAK,EAAE,YAAY;AAEvD,MAAI,WAAW,KAAK,cAAc,KAAK,WAAW,KAAK,eAAe,GAAG;AACvE,WAAO,gBAAgB,SAAS,IAAI,kBAAkB;EACxD;AAEA,QAAM,qBAAqB,gBAAgB,MAAM,4CAA4C;AAC7F,QAAM,eAAe,qBAAqB,CAAC,GAAG,KAAK,EAAE,YAAY;AACjE,MAAI,iBAAiB,UAAa,aAAa,SAAS,GAAG;AACzD,WAAO,GAAG,YAAY;EACxB;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,WAAO;EACT;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CAAC,aAA6B;AACrD,MAAI,CAAC,SAAS,SAAS,MAAM,GAAG;AAC9B,WAAO;EACT;AAEA,QAAM,mBAAmB,SAAS,MAAM,4BAA4B;AACpE,MAAI,qBAAqB,MAAM;AAC7B,UAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,MAAM,IAAI;AACxC,WAAO,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM;EACvC;AAEA,QAAM,QAAQ,SAAS,MAAM,MAAM;AACnC,QAAM,YAAY,MAAM,MAAM,SAAS,CAAC;AACxC,SAAO,aAAa;AACtB;AAEA,IAAM,mBAAmB,CAAC,SAAuC;AAC/D,QAAM,QAAQ,KAAK,MAAM,GAAI;AAC7B,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;EACT;AAEA,QAAM,eAAe,MAAM,CAAC;AAC5B,QAAM,eAAe,MAAM,CAAC;AAC5B,QAAM,UAAU,MAAM,MAAM,CAAC,EAAE,KAAK,GAAI;AAExC,MAAI,iBAAiB,UAAa,iBAAiB,QAAW;AAC5D,WAAO;EACT;AAEA,QAAM,YAAY,iBAAiB,MAAM,IAAI,aAAa,YAAY;AACtE,QAAM,YAAY,iBAAiB,MAAM,IAAI,aAAa,YAAY;AAEtE,MAAI,cAAc,QAAQ,cAAc,MAAM;AAC5C,WAAO;EACT;AAEA,QAAM,WAAW,iBAAiB,OAAO;AACzC,SAAO;IACL;IACA;IACA;EACF;AACF;AAEO,IAAM,cAAc,CACzB,QACA,eAC+B;AAC/B,QAAM,UAAU,OACb,MAAM,uBAAuB,EAC7B,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,EAC7B,OAAO,CAAC,WAAW,OAAO,SAAS,CAAC;AAEvC,QAAM,UAA6B,CAAC;AAEpC,aAAW,CAAC,OAAO,MAAM,KAAK,QAAQ,QAAQ,GAAG;AAC/C,UAAM,QAAQ,OACX,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,EAC5B,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AAEnC,QAAI,MAAM,WAAW,GAAG;AACtB;IACF;AAEA,UAAM,cAAc,MAAM,CAAC,GAAG,MAAM,sBAAsB,KAAK,CAAC;AAChE,QAAI,YAAY,WAAW,GAAG;AAC5B;IACF;AAEA,UAAM,CAAC,MAAM,eAAe,YAAY,WAAW,IAAI;AACvD,QAAI,SAAS,UAAa,kBAAkB,UAAa,eAAe,UAAa,gBAAgB,QAAW;AAC9G;IACF;AAEA,UAAM,iBAAiB,aAAa,aAAa;AACjD,QAAI,mBAAmB,MAAM;AAC3B;IACF;AAEA,UAAM,cAA+B,CAAC;AACtC,eAAW,QAAQ,MAAM,MAAM,CAAC,GAAG;AACjC,YAAM,aAAa,iBAAiB,IAAI;AACxC,UAAI,eAAe,MAAM;AACvB,oBAAY,KAAK,UAAU;MAC7B;IACF;AAEA,YAAQ,KAAK;MACX;MACA,UAAU,wBAAwB,YAAY,WAAW;MACzD;MACA;MACA;IACF,CAAC;AAED,UAAM,gBAAgB,QAAQ;AAC9B,QAAI,kBAAkB,KAAK,kBAAkB,QAAQ,UAAU,gBAAgB,QAAQ,GAAG;AACxF,mBAAa,EAAE,eAAe,cAAc,QAAQ,OAAO,CAAC;IAC9D;EACF;AAEA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC1F,SAAO;AACT;ACzIA,IAAM,gBAAgB,CAAC,wBAAwB,wBAAwB;AAEvE,IAAM,gBAAgB,CAAC,UAAoC;AACzD,QAAM,QAAQ,MAAM,QAAQ,YAAY;AACxC,SAAO,cAAc,KAAK,CAAC,SAAS,MAAM,SAAS,IAAI,CAAC;AAC1D;AAEO,IAAM,wBAAN,MAA0D;EAC/D,YAA6B,WAA6B;AAA7B,SAAA,YAAA;EAA8B;EAE3D,gBAAgB,gBAAiC;AAC/C,QAAI;AACF,YAAM,SAAS,KAAK,UAAU,IAAI,gBAAgB,CAAC,aAAa,uBAAuB,CAAC;AACxF,aAAO,OAAO,KAAK,MAAM;IAC3B,SAAS,OAAO;AACd,UAAI,iBAAiB,mBAAmB,cAAc,KAAK,GAAG;AAC5D,eAAO;MACT;AAEA,YAAM;IACR;EACF;EAEA,iBACE,gBACA,YAC4B;AAC5B,UAAM,SAAS,KAAK,UAAU,IAAI,gBAAgB;MAChD;MACA;MACA;MACA;MACA;MACA;MACA,mBAAmB,cAAc;MACjC;MACA;IACF,CAAC;AACD,iBAAa,EAAE,OAAO,oBAAoB,OAAO,OAAO,WAAW,QAAQ,MAAM,EAAE,CAAC;AACpF,UAAM,UAAU,YAAY,QAAQ,CAAC,UAAU,aAAa,kCAAkC,KAAK,CAAC,CAAC;AACrG,iBAAa,EAAE,OAAO,kBAAkB,SAAS,QAAQ,OAAO,CAAC;AACjE,WAAO;EACT;AACF;ACzCO,IAAM,oCAAoC,CAC/C,OACA,eAC+B;AAC/B,QAAM,kBAAkB,IAAI,sBAAsB,IAAI,qBAAqB,CAAC;AAC5E,SAAO,2BAA2B,OAAO,iBAAiB,UAAU;AACtE;;;AC0DO,IAAM,6BAA+C;;EAE1D,kBAAkB;IAChB,YAAY;IACZ,WAAW;IACX,UAAU;EACZ;;EAEA,oBAAoB;IAClB,qBAAqB;IACrB,oBAAoB;IACpB,yBAAyB;EAC3B;EACA,yBAAyB;IACvB,OAAO;IACP,QAAQ;IACR,OAAO;IACP,oBAAoB;EACtB;EACA,wBAAwB;IACtB,WAAW;IACX,OAAO;IACP,kBAAkB;IAClB,wBAAwB;IACxB,eAAe;EACjB;EACA,yBAAyB;IACvB,SAAS;IACT,WAAW;IACX,yBAAyB;IACzB,kBAAkB;IAClB,YAAY;IACZ,YAAY;IACZ,eAAe;EACjB;EACA,eAAe;IACb,OAAO;IACP,OAAO;EACT;EACA,mBAAmB;EACnB,iBAAiB;EACjB,iBAAiB;EACjB,iBAAiB;IACf,oBAAoB;IACpB,qBAAqB;IACrB,YAAY;EACd;EACA,mBAAmB;IACjB,eAAe;IACf,qBAAqB;IACrB,UAAU;EACZ;EACA,QAAQ;IACN,mBAAmB;IACnB,WAAW;IACX,mBAAmB,CAAC,OAAO,OAAO,OAAO,UAAU;EACrD;EACA,mBAAmB;IACjB,2BAA2B;;IAE3B,uBAAuB;IACvB,wBAAwB;EAC1B;EACA,mBAAmB;IACjB,yBAAyB;IACzB,yBAAyB;EAC3B;AACF;AC/IO,IAAM,UAAU,CAAC,UAA0B;AAChD,MAAI,OAAO,MAAM,KAAK,GAAG;AACvB,WAAO;EACT;AAEA,MAAI,SAAS,GAAG;AACd,WAAO;EACT;AAEA,MAAI,SAAS,GAAG;AACd,WAAO;EACT;AAEA,SAAO;AACT;AAEO,IAAMC,UAAS,CAAC,UAA0B,OAAO,MAAM,QAAQ,CAAC,CAAC;AAEjE,IAAM,UAAU,CAAC,WAAsC;AAC5D,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;EACT;AAEA,QAAM,QAAQ,OAAO,OAAO,CAAC,KAAK,YAAY,MAAM,SAAS,CAAC;AAC9D,SAAO,QAAQ,OAAO;AACxB;AAEO,IAAM,aAAa,CAAC,QAA2B,MAAsB;AAC1E,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;EACT;AAEA,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,OAAO,CAAC,KAAK;EACtB;AAEA,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAC/C,QAAM,WAAW,QAAQ,CAAC,KAAK,OAAO,SAAS;AAC/C,QAAM,aAAa,KAAK,MAAM,QAAQ;AACtC,QAAM,aAAa,KAAK,KAAK,QAAQ;AAErC,QAAM,QAAQ,OAAO,UAAU,KAAK;AACpC,QAAM,QAAQ,OAAO,UAAU,KAAK;AAEpC,MAAI,eAAe,YAAY;AAC7B,WAAO;EACT;AAEA,QAAM,QAAQ,WAAW;AACzB,SAAO,SAAS,QAAQ,SAAS;AACnC;AAEO,IAAM,sBAAsB,CACjC,UACA,mBACW;AACX,MAAI,QAAQ,QAAQ,QAAQ;AAE5B,aAAW,iBAAiB,gBAAgB;AAC1C,UAAM,uBAAuB,QAAQ,aAAa;AAClD,cAAU,IAAI,SAAS;EACzB;AAEA,SAAO,QAAQ,KAAK;AACtB;AAEO,IAAM,eAAe,CAAC,OAAe,aAA6B;AACvE,MAAI,SAAS,KAAK,YAAY,GAAG;AAC/B,WAAO;EACT;AAEA,SAAO,QAAQ,SAAS,QAAQ,SAAS;AAC3C;AAEO,IAAM,mBAAmB,CAC9B,SACA,YACgC;AAChC,MAAI,QAAQ;AACZ,QAAM,SAA4B,EAAE,GAAG,QAAQ;AAE/C,aAAW,OAAO,OAAO,KAAK,MAAM,GAAU;AAC5C,UAAM,eAAe,QAAQ,GAAG;AAChC,QAAI,CAAC,cAAc;AACjB,aAAO,GAAG,IAAI;AACd;IACF;AAEA,UAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,GAAG,CAAC;AACrC,WAAO,GAAG,IAAI;AACd,aAAS;EACX;AAEA,MAAI,UAAU,GAAG;AACf,UAAM,aAAc,OAAO,KAAK,MAAM,EAAU,OAAO,CAAC,QAAQ,QAAQ,GAAG,CAAC;AAC5E,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO;IACT;AAEA,UAAM,UAAU,IAAI,WAAW;AAC/B,eAAW,OAAO,YAAY;AAC5B,aAAO,GAAG,IAAI;IAChB;AAEA,WAAO;EACT;AAEA,aAAW,OAAO,OAAO,KAAK,MAAM,GAAU;AAC5C,QAAI,QAAQ,GAAG,GAAG;AAChB,aAAO,GAAG,IAAI,OAAO,GAAG,IAAI;IAC9B;EACF;AAEA,SAAO;AACT;AC3GO,IAAM,WAAW,CAAC,UAA0B,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,CAAC;AAEzE,IAAM,qBAAqB,CAChC,QACA,iBACA,oBACkB;AAClB,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,EAAE,OAAO,GAAG,OAAO,EAAE;EAC9B;AAEA,SAAO;IACL,OAAO,WAAW,QAAQ,eAAe;IACzC,OAAO,WAAW,QAAQ,eAAe;EAC3C;AACF;AAEO,IAAM,qBAAqB,CAAC,OAAe,UAAiC;AACjF,MAAI,MAAM,SAAS,MAAM,OAAO;AAC9B,WAAO,QAAQ,IAAI,IAAI;EACzB;AAEA,SAAO,SAAS,QAAQ,MAAM,UAAU,MAAM,QAAQ,MAAM,MAAM;AACpE;ACcA,IAAMC,iBAAgB,CAAC,SAAyB,KAAK,WAAW,MAAM,GAAG;AAEzE,IAAM,0BAA0E;EAC9E,mBAAmB;EACnB,WAAW;EACX,iBAAiB;EACjB,YAAY;EACZ,aAAa;EACb,sBAAsB;AACxB;AAEA,IAAM,+BAA+B,OAAO,OAAO,uBAAuB,EAAE;EAC1E,CAAC,KAAK,UAAU,MAAM;EACtB;AACF;AAEA,IAAM,+BAA+B,CACnC,YACA,kBACA,8BACW;AACX,QAAM,YAAY,WAAW,OAAO,CAAC,KAAK,WAAW,OAAO,wBAAwB,MAAM,KAAK,IAAI,CAAC;AACpG,QAAM,kBAAkB,iBAAiB;IACvC,CAAC,KAAK,WAAW,OAAO,wBAAwB,MAAM,KAAK;IAC3D;EACF;AAEA,QAAM,gBAAgB,YAAY,kBAAkB;AACpD,QAAM,mBAAmB,gCAAgC,IAAI;AAE7D,MAAI,oBAAoB,GAAG;AACzB,WAAO;EACT;AAEA,SAAO,QAAQ,gBAAgB,gBAAgB;AACjD;AAEA,IAAM,0BAA0B,CAC9B,UACA,WAC+B;AAC/B,MAAI,CAAC,SAAS,WAAW;AACvB,WAAO;MACL,kBAAkB,CAAC;MACnB,4BAA4B;IAC9B;EACF;AAEA,QAAM,mBAAmB,SAAS,aAAa;IAAI,CAAC,eAClD,SAAS,WAAW,uBAAuB,MAAM;EACnD;AACA,QAAM,kBAAkB,SAAS,aAAa,IAAI,CAAC,eAAe,SAAS,WAAW,UAAU,CAAC;AACjG,QAAM,cAAc,SAAS,aAAa,IAAI,CAAC,eAAe,WAAW,eAAe;AAExF,QAAM,kBAAkB;IACtB;IACA,OAAO,cAAc;IACrB,OAAO,cAAc;EACvB;AACA,QAAM,iBAAiB;IACrB;IACA,OAAO,cAAc;IACrB,OAAO,cAAc;EACvB;AACA,QAAM,kBAAkB;IACtB;IACA,OAAO,cAAc;IACrB,OAAO,cAAc;EACvB;AAEA,QAAM,mBAAmB,SAAS,aAC/B,IAAyB,CAAC,eAAe;AACxC,UAAM,cAAc;MAClB,WAAW;MACX,WAAW;MACX,OAAO,kBAAkB;IAC3B;AAEA,UAAM,8BACJ,WAAW,oBAAoB,OAC3B,OAAO,kBAAkB,yBACzB,QAAQ,IAAI,KAAK,IAAI,GAAG,WAAW,eAAe,CAAC;AAEzD,UAAM,gBACJ,WAAW,yBAAyB,OAChC,OAAO,kBAAkB,yBACzB;MACE,WAAW;MACX,OAAO,kBAAkB;IAC3B;AAEN,UAAM,uBAAuB;MAC3B,SAAS,WAAW,uBAAuB,MAAM;MACjD;IACF;AAEA,UAAM,iBAAiB,mBAAmB,SAAS,WAAW,UAAU,GAAG,cAAc;AACzF,UAAM,iBAAiB,mBAAmB,WAAW,iBAAiB,eAAe;AAErF,UAAM,gBACJ,WAAW,cAAc,OACrB,OAAO,kBAAkB,yBACzB,QAAQ,IAAI,KAAK,IAAI,GAAG,WAAW,SAAS,CAAC;AAEnD,UAAM,UAAU,OAAO;AACvB,UAAM,kBAAkB;MACtB,cAAc,QAAQ,UACpB,gBAAgB,QAAQ,YACxB,8BAA8B,QAAQ,0BACtC,uBAAuB,QAAQ,mBAC/B,iBAAiB,QAAQ,aACzB,iBAAiB,QAAQ,aACzB,gBAAgB,QAAQ;IAC5B;AAEA,WAAO;MACL,YAAY,WAAW;MACvB,OAAOD,QAAO,kBAAkB,GAAG;MACnC,iBAAiBA,QAAO,eAAe;MACvC,gBAAgB,WAAW;MAC3B,sBAAsB,WAAW;IACnC;EACF,CAAC,EACA;IACC,CAAC,GAAG,MACF,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,WAAW,cAAc,EAAE,UAAU;EACpF;AAEF,QAAM,mBAAmB,iBAAiB,IAAI,CAAC,UAAU,MAAM,eAAe;AAC9E,QAAM,qBACJ,iBAAiB,WAAW,IACxB,IACA,WAAW,kBAAkB,OAAO,kBAAkB,uBAAuB;AACnF,QAAM,wBAAwB,QAAQ,gBAAgB;AACtD,QAAM,YAAY;IAChB,SAAS,QAAQ;IACjB,OAAO,kBAAkB;EAC3B;AAEA,QAAM,6BAA6B;IACjC,qBAAqB,MAAM,wBAAwB,MAAM,YAAY;EACvE;AAEA,SAAO;IACL;IACA,4BAA4BA,QAAO,0BAA0B;EAC/D;AACF;AAEA,IAAM,qBAAqB,CACzB,cAC8C;AAC9C,MAAI,CAAC,UAAU,WAAW;AACxB,WAAO,oBAAI,IAAkC;EAC/C;AAEA,SAAO,IAAI;IACT,UAAU,MAAM,IAAI,CAAC,gBAAgB,CAACC,eAAc,YAAY,QAAQ,GAAG,WAAW,CAAC;EACzF;AACF;AAEA,IAAM,yBAAyB,CAC7B,iBACA,WACiB;AACjB,QAAM,iBAAiB,CAAC,GAAG,gBAAgB,OAAO,CAAC;AAEnD,SAAO;IACL,aAAa;MACX,eAAe,IAAI,CAAC,YAAY,SAAS,QAAQ,WAAW,CAAC;MAC7D,OAAO,cAAc;MACrB,OAAO,cAAc;IACvB;IACA,YAAY;MACV,eAAe,IAAI,CAAC,YAAY,SAAS,QAAQ,UAAU,CAAC;MAC5D,OAAO,cAAc;MACrB,OAAO,cAAc;IACvB;IACA,WAAW;MACT,eAAe,IAAI,CAAC,YAAY,QAAQ,SAAS;MACjD,OAAO,cAAc;MACrB,OAAO,cAAc;IACvB;EACF;AACF;AAEA,IAAM,kBAAkB,CAAC,UAAkB,WAAqC;AAC9E,QAAM,aAAaA,eAAc,QAAQ;AACzC,QAAM,QAAQ,WAAW,MAAM,GAAG,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AAEpE,MAAI,MAAM,UAAU,GAAG;AACrB,WAAO,OAAO,OAAO;EACvB;AAEA,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,UAAU,QAAW;AACvB,WAAO,OAAO,OAAO;EACvB;AAEA,MAAI,CAAC,OAAO,OAAO,kBAAkB,SAAS,KAAK,GAAG;AACpD,WAAO;EACT;AAEA,MAAI,MAAM,UAAU,OAAO,OAAO,mBAAmB;AACnD,WAAO;EACT;AAEA,SAAO,MAAM,MAAM,GAAG,OAAO,OAAO,iBAAiB,EAAE,KAAK,GAAG;AACjE;AAEA,IAAM,uBAAuB,CAC3B,YACA,WACA,kBACA,WAC8B;AAC9B,QAAM,WAA6B,CAAC;AAEpC,MAAI,oBAAoB;AACxB,aAAW,SAAS,WAAW,QAAQ;AACrC,UAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAASA,eAAc,IAAI,CAAC,CAAC,CAAC,EAAE;MAAO,CAAC,aACjF,iBAAiB,IAAI,QAAQ;IAC/B;AAEA,QAAI,MAAM,SAAS,GAAG;AACpB;IACF;AAEA,UAAM,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAEvC,UAAM,cAAc;MAClB,MAAM,IAAI,CAAC,aAAa,iBAAiB,IAAI,QAAQ,GAAG,mBAAmB,CAAC;IAC9E;AAEA,UAAM,gBAAgB,SAAS,MAAM,SAAS,KAAK,CAAC;AACpD,UAAM,QAAQD,QAAO,QAAQ,cAAc,OAAO,gBAAgB,IAAI,IAAI,GAAG;AAE7E,yBAAqB;AACrB,aAAS,KAAK;MACZ,IAAI,SAAS,iBAAiB;MAC9B,MAAM;MACN;MACA;IACF,CAAC;EACH;AAEA,MAAI,UAAU,aAAa,UAAU,SAAS,MAAM,SAAS,GAAG;AAC9D,UAAM,aAAa,UAAU,SAAS,MAAM;MAC1C,CAAC,SAAS,KAAK,mBAAmB,OAAO,gBAAgB;IAC3D;AAEA,UAAM,YAAY,KAAK;MACrB,OAAO,gBAAgB;MACvB;QACE,WAAW,IAAI,CAAC,SAAS,KAAK,aAAa;QAC3C,OAAO,gBAAgB;MACzB;IACF;AAEA,UAAM,gBAAgB,WACnB,OAAO,CAAC,SAAS,KAAK,iBAAiB,SAAS,EAChD,IAAI,CAAC,UAAU;MACd,OAAOC,eAAc,KAAK,KAAK;MAC/B,OAAOA,eAAc,KAAK,KAAK;MAC/B,eAAe,KAAK;IACtB,EAAE,EACD;MACC,CAAC,SACC,KAAK,UAAU,KAAK,SACpB,iBAAiB,IAAI,KAAK,KAAK,KAC/B,iBAAiB,IAAI,KAAK,KAAK;IACnC;AAEF,UAAM,YAAY,oBAAI,IAAyB;AAC/C,eAAW,QAAQ,eAAe;AAChC,YAAM,aAAa,UAAU,IAAI,KAAK,KAAK,KAAK,oBAAI,IAAY;AAChE,iBAAW,IAAI,KAAK,KAAK;AACzB,gBAAU,IAAI,KAAK,OAAO,UAAU;AAEpC,YAAM,aAAa,UAAU,IAAI,KAAK,KAAK,KAAK,oBAAI,IAAY;AAChE,iBAAW,IAAI,KAAK,KAAK;AACzB,gBAAU,IAAI,KAAK,OAAO,UAAU;IACtC;AAEA,UAAM,UAAU,oBAAI,IAAY;AAChC,QAAI,uBAAuB;AAE3B,UAAM,gBAAgB,CAAC,GAAG,UAAU,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC7E,eAAW,SAAS,eAAe;AACjC,UAAI,QAAQ,IAAI,KAAK,GAAG;AACtB;MACF;AAEA,YAAM,QAAQ,CAAC,KAAK;AACpB,YAAM,QAAkB,CAAC;AAEzB,aAAO,MAAM,SAAS,GAAG;AACvB,cAAM,UAAU,MAAM,IAAI;AAC1B,YAAI,YAAY,UAAa,QAAQ,IAAI,OAAO,GAAG;AACjD;QACF;AAEA,gBAAQ,IAAI,OAAO;AACnB,cAAM,KAAK,OAAO;AAElB,cAAM,YAAY,UAAU,IAAI,OAAO;AACvC,YAAI,cAAc,QAAW;AAC3B;QACF;AAEA,mBAAW,YAAY,WAAW;AAChC,cAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG;AAC1B,kBAAM,KAAK,QAAQ;UACrB;QACF;MACF;AAEA,UAAI,MAAM,SAAS,GAAG;AACpB;MACF;AAEA,YAAM,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AACvC,YAAM,UAAU,IAAI,IAAI,KAAK;AAC7B,YAAM,iBAAiB,cAAc;QACnC,CAAC,SAAS,QAAQ,IAAI,KAAK,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK;MAC7D;AAEA,YAAM,eAAe;QACnB,MAAM,IAAI,CAAC,aAAa,iBAAiB,IAAI,QAAQ,GAAG,mBAAmB,CAAC;MAC9E;AACA,YAAM,eAAe,QAAQ,eAAe,IAAI,CAAC,SAAS,KAAK,aAAa,CAAC;AAE7E,YAAM,QAAQD,QAAO,QAAQ,eAAe,OAAO,eAAe,IAAI,IAAI,GAAG;AAE7E,8BAAwB;AACxB,eAAS,KAAK;QACZ,IAAI,YAAY,oBAAoB;QACpC,MAAM;QACN;QACA;MACF,CAAC;IACH;EACF;AAEA,SAAO,SAAS;IACd,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE;EACxF;AACF;AAEO,IAAM,qBAAqB,CAChC,YACA,WACA,UACA,WAC0B;AAC1B,QAAM,wBAAwB,wBAAwB,UAAU,MAAM;AACtE,QAAM,kBAAkB,mBAAmB,SAAS;AACpD,QAAM,kBAAkB,uBAAuB,iBAAiB,MAAM;AAEtE,QAAM,eAAe,IAAI;IACvB,WAAW,OAAO,QAAQ,CAAC,UAAU,MAAM,MAAM,IAAI,CAAC,SAASC,eAAc,IAAI,CAAC,CAAC;EACrF;AAEA,QAAM,aAAa;IACjB,WAAW,MAAM,IAAI,CAAC,SAAS,SAAS,KAAK,KAAK,CAAC;IACnD,OAAO,cAAc;IACrB,OAAO,cAAc;EACvB;AACA,QAAM,cAAc;IAClB,WAAW,MAAM,IAAI,CAAC,SAAS,SAAS,KAAK,MAAM,CAAC;IACpD,OAAO,cAAc;IACrB,OAAO,cAAc;EACvB;AACA,QAAM,aAAa;IACjB,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK;IACzC,OAAO,cAAc;IACrB,OAAO,cAAc;EACvB;AAEA,QAAM,mBAAmB,iBAAiB,OAAO,kBAAkB;IACjE,YAAY;IACZ,WAAW,UAAU;IACrB,UAAU,SAAS;EACrB,CAAC;AAED,QAAM,mBAAmB,WAAW,MACjC,IAAqB,CAAC,SAAS;AAC9B,UAAM,WAAWA,eAAc,KAAK,EAAE;AACtC,UAAM,UAAU,aAAa,IAAI,QAAQ,IAAI,IAAI;AAEjD,UAAM,YAAY,mBAAmB,SAAS,KAAK,KAAK,GAAG,UAAU;AACrE,UAAM,aAAa,mBAAmB,SAAS,KAAK,MAAM,GAAG,WAAW;AACxE,UAAM,YAAY,mBAAmB,KAAK,OAAO,UAAU;AAE3D,UAAM,oBAAoB,OAAO;AACjC,UAAM,mBAAmB;MACvB,YAAY,kBAAkB,QAC5B,aAAa,kBAAkB,SAC/B,YAAY,kBAAkB,QAC9B,UAAU,kBAAkB;IAChC;AAEA,UAAM,uBAAuB,SAAS,YAAY,cAAc,CAAC;AAEjE,QAAI,kBAAkB;AACtB,UAAM,mBAAmB,gBAAgB,IAAI,QAAQ;AACrD,QAAI,UAAU,aAAa,qBAAqB,QAAW;AACzD,YAAM,gBAAgB;QACpB,SAAS,iBAAiB,WAAW;QACrC,gBAAgB;MAClB;AACA,YAAM,YAAY;QAChB,SAAS,iBAAiB,UAAU;QACpC,gBAAgB;MAClB;AACA,YAAM,iBAAiB,QAAQ,iBAAiB,gBAAgB;AAChE,YAAM,6BAA6B,QAAQ,iBAAiB,cAAc;AAC1E,YAAM,gBAAgB,QAAQ,IAAI,mBAAmB,iBAAiB,WAAW,gBAAgB,SAAS,CAAC;AAE3G,YAAM,mBAAmB,OAAO;AAChC,wBAAkB;QAChB,gBAAgB,iBAAiB,YAC/B,YAAY,iBAAiB,QAC7B,iBAAiB,iBAAiB,mBAClC,6BAA6B,iBAAiB,yBAC9C,gBAAgB,iBAAiB;MACrC;IACF;AAEA,UAAM,qBAAqB,QAAQ,uBAAuB,MAAM,kBAAkB,GAAG;AACrF,UAAM,iBAAiB,SAAS,YAC5B,QAAQ,sBAAsB,6BAA6B,kBAAkB,IAC7E;AAEJ,UAAM,WACJ,mBAAmB,iBAAiB,aACpC,kBAAkB,iBAAiB,YACnC,iBAAiB,iBAAiB;AAEpC,UAAM,eAAe;MACnB,mBAAmB,kBAAkB,OAAO,mBAAmB;MAC/D,uBAAuB,kBAAkB,OAAO,mBAAmB;MACnE,iBAAiB,KAAK,IAAI,kBAAkB,eAAe,IACzD,OAAO,mBAAmB;IAC9B;AAEA,UAAM,kBAAkB,oBAAoB,UAAU,YAAY;AAElE,WAAO;MACL,MAAM;MACN,OAAOD,QAAO,kBAAkB,GAAG;MACnC,iBAAiBA,QAAO,eAAe;MACvC,SAAS;QACP,YAAYA,QAAO,gBAAgB;QACnC,WAAWA,QAAO,eAAe;QACjC,UAAUA,QAAO,cAAc;MACjC;MACA,sBAAsBA,QAAO,oBAAoB;IACnD;EACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAEnE,QAAM,aAA8B,iBAAiB,IAAI,CAAC,aAAa;IACrE,MAAM,QAAQ;IACd,OAAO,QAAQ;IACf,iBAAiB,QAAQ;IACzB,SAAS,QAAQ;EACnB,EAAE;AAEF,QAAM,mBAAmB,IAAI,IAAI,WAAW,IAAI,CAAC,cAAc,CAAC,UAAU,MAAM,SAAS,CAAC,CAAC;AAE3F,QAAM,gBAAgB,KAAK;IACzB,OAAO;IACP,KAAK,IAAI,OAAO,iBAAiB,KAAK,KAAK,WAAW,SAAS,OAAO,iBAAiB,CAAC;EAC1F;AAEA,QAAM,WAAW,WAAW,MAAM,GAAG,aAAa,EAAE,IAAI,CAAC,eAAe;IACtE,MAAM,UAAU;IAChB,OAAO,UAAU;IACjB,SAAS,UAAU;EACrB,EAAE;AAEF,QAAM,cAAc,oBAAI,IAAsB;AAC9C,aAAW,aAAa,YAAY;AAClC,UAAM,aAAa,gBAAgB,UAAU,MAAM,MAAM;AACzD,UAAM,SAAS,YAAY,IAAI,UAAU,KAAK,CAAC;AAC/C,WAAO,KAAK,UAAU,eAAe;AACrC,gBAAY,IAAI,YAAY,MAAM;EACpC;AAEA,QAAM,eAAkC,CAAC,GAAG,YAAY,QAAQ,CAAC,EAC9D,IAAI,CAAC,CAAC,QAAQ,MAAM,MAAM;AACzB,UAAM,eAAe,QAAQ,MAAM;AACnC,UAAM,YAAY,OAAO,OAAO,CAAC,KAAK,UAAU,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC;AACvE,UAAM,kBAAkB,QAAQ,eAAe,OAAO,YAAY,IAAI;AAEtE,WAAO;MACL;MACA,OAAOA,QAAO,kBAAkB,GAAG;MACnC,iBAAiBA,QAAO,eAAe;MACvC,WAAW,OAAO;IACpB;EACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,cAAc,EAAE,MAAM,CAAC;AAEvE,QAAM,kBAAkB,qBAAqB,YAAY,WAAW,kBAAkB,MAAM;AAE5F,QAAM,oBAAoB,WAAW,IAAI,CAAC,cAAc,UAAU,QAAQ,QAAQ;AAClF,QAAM,oBAAoB,KAAK;IAC7B,OAAO,kBAAkB;IACzB,WAAW,mBAAmB,OAAO,kBAAkB,mBAAmB;EAC5E;AAEA,QAAM,+BAA+B,WAClC,IAAI,CAAC,cAAc;AAClB,UAAM,YAAY;MAChB,UAAU,QAAQ,WAAW,KAAK,IAAI,UAAU,QAAQ,YAAY,UAAU,QAAQ,SAAS;IACjG;AACA,UAAM,sBAAsB,QAAQ,YAAY,MAAM,UAAU,kBAAkB,GAAG;AAErF,WAAO;MACL,MAAM,UAAU;MAChB,OAAOA,QAAO,sBAAsB,GAAG;MACvC,kBAAkB,UAAU,QAAQ;IACtC;EACF,CAAC,EACA,OAAO,CAAC,SAAS,SAAS,aAAa,KAAK,oBAAoB,iBAAiB,EACjF,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,EAChE,MAAM,GAAG,OAAO,kBAAkB,QAAQ,EAC1C,IAAI,CAAC,UAAU;IACd,GAAG;IACH,kBAAkBA,QAAO,KAAK,gBAAgB;EAChD,EAAE;AAEJ,QAAM,sBAAsB,QAAQ,WAAW,IAAI,CAAC,cAAc,UAAU,QAAQ,UAAU,CAAC;AAC/F,QAAM,qBAAqB,QAAQ,WAAW,IAAI,CAAC,cAAc,UAAU,QAAQ,SAAS,CAAC;AAC7F,QAAM,oBAAoB,sBAAsB;AAEhD,QAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,KAAK,iBAAiB,SAAS,GAAG,CAAC;AAC5E,QAAM,sBAAsB;IAC1B,CAAC,GAAG,gBAAgB,EACjB;MACC,CAAC,GAAG,MACF,EAAE,uBAAuB,EAAE,QAAQ,YAAY,EAAE,uBAAuB,EAAE,QAAQ,aAClF,EAAE,KAAK,cAAc,EAAE,IAAI;IAC/B,EACC,MAAM,GAAG,eAAe,EACxB,IAAI,CAAC,YAAY,QAAQ,uBAAuB,QAAQ,QAAQ,SAAS;EAC9E;AAEA,QAAM,0BAA0B;IAC9B,6BAA6B;MAAI,CAAC,SAChC,QAAS,KAAK,mBAAmB,KAAK,QAAS,GAAG;IACpD;EACF;AAEA,QAAM,qBACJ,sBAAsB,iBAAiB,aACvC,qBAAqB,iBAAiB,YACtC,oBAAoB,iBAAiB;AAEvC,QAAM,4BAA4B,oBAAoB,oBAAoB;IACxE,sBAAsB,qBAAqB,OAAO,mBAAmB;IACrE,sBAAsB,OAAO,mBAAmB;IAChD,0BAA0B,OAAO,mBAAmB;EACtD,CAAC;AAED,SAAO;IACL,iBAAiBA,QAAO,4BAA4B,GAAG;IACvD,iBAAiBA,QAAO,yBAAyB;IACjD;IACA;IACA;IACA;IACA;IACA,kBAAkB,sBAAsB;EAC1C;AACF;AC7lBA,IAAM,cAAc,CAAC,cAAuE;AAC1F,MAAI,cAAc,QAAW;AAC3B,WAAO;EACT;AAEA,SAAO;IACL,GAAG;IACH,GAAG;IACH,kBAAkB;MAChB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,oBAAoB;MAClB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,yBAAyB;MACvB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,wBAAwB;MACtB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,yBAAyB;MACvB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,eAAe;MACb,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,iBAAiB;MACf,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,mBAAmB;MACjB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,QAAQ;MACN,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,mBAAmB;MACjB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;IACA,mBAAmB;MACjB,GAAG,2BAA2B;MAC9B,GAAG,UAAU;IACf;EACF;AACF;AAEO,IAAM,+BAA+B,CAC1C,UAC0B;AAC1B,QAAM,SAAS,YAAY,MAAM,MAAM;AACvC,SAAO,mBAAmB,MAAM,YAAY,MAAM,WAAW,MAAM,UAAU,MAAM;AACrF;;;A/BzDA,IAAM,oBAAoB,CAAC,WAA+B,QACxDE,SAAQ,KAAK,aAAa,GAAG;AAE/B,IAAM,iCAAiC,CAAC,WAAuE;AAC7G,MAAI,qBAAqB;AAEzB,SAAO,CAAC,UAAU;AAChB,YAAQ,MAAM,OAAO;AAAA,MACnB,KAAK;AACH,eAAO,MAAM,+BAA+B;AAC5C;AAAA,MACF,KAAK;AACH,eAAO,KAAK,gCAAgC,MAAM,IAAI,GAAG;AACzD;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,oBAAoB,MAAM,eAAe,yBAAyB,MAAM,kBAAkB;AAAA,QAC5F;AACA;AAAA,MACF,KAAK;AACH,eAAO,KAAK,2CAA2C,MAAM,KAAK,YAAY;AAC9E;AAAA,MACF,KAAK,2BAA2B;AAC9B,cAAM,iBAAiB,MAAM,UAAU,IAAI,MAAM,KAAK,MAAO,MAAM,YAAY,MAAM,QAAS,GAAG;AACjG,YACE,MAAM,cAAc,MAAM,SAC1B,MAAM,cAAc,KACpB,MAAM,YAAY,sBAAsB,IACxC;AACA,+BAAqB,MAAM;AAC3B,iBAAO;AAAA,YACL,+BAA+B,MAAM,SAAS,IAAI,MAAM,KAAK,KAAK,cAAc;AAAA,UAClF;AACA,iBAAO,MAAM,oCAAoC,MAAM,WAAW,EAAE;AAAA,QACtE;AACA;AAAA,MACF;AAAA,MACA,KAAK;AACH,eAAO,KAAK,uCAAuC,MAAM,KAAK,YAAY;AAC1E;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,4BAA4B,MAAM,iBAAiB,WAAW,MAAM,kBAAkB;AAAA,QACxF;AACA;AAAA,IACJ;AAAA,EACF;AACF;AAEA,IAAM,mCAAmC,CACvC,WAC2D;AAC3D,MAAI,gBAAgB;AAEpB,SAAO,CAAC,UAAU;AAChB,YAAQ,MAAM,OAAO;AAAA,MACnB,KAAK;AACH,YAAI,MAAM,kBAAkB;AAC1B,iBAAO;AAAA,YACL,0DAA0D,MAAM,aAAa;AAAA,UAC/E;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,0CAA0C,MAAM,aAAa,WAAW;AAAA,QACtF;AACA;AAAA,MACF,KAAK;AACH,eAAO,KAAK,0BAA0B,MAAM,gBAAgB,eAAe;AAC3E;AAAA,MACF,KAAK;AACH,eAAO,MAAM,2CAA2C,MAAM,gBAAgB,SAAS;AACvF;AAAA,MACF,KAAK;AACH,YACE,MAAM,cAAc,MAAM,SAC1B,MAAM,cAAc,KACpB,MAAM,YAAY,iBAAiB,IACnC;AACA,0BAAgB,MAAM;AACtB,iBAAO,KAAK,wBAAwB,MAAM,SAAS,IAAI,MAAM,KAAK,QAAQ;AAC1E,iBAAO,MAAM,mCAAmC,MAAM,QAAQ,EAAE;AAAA,QAClE;AACA;AAAA,MACF,KAAK;AACH,eAAO,KAAK,wBAAwB,MAAM,UAAU,mBAAmB;AACvE;AAAA,IACJ;AAAA,EACF;AACF;AAEA,IAAM,kCAAkC,CACtC,WACsD;AACtD,MAAI,oBAAoB;AAExB,SAAO,CAAC,UAAU;AAChB,YAAQ,MAAM,OAAO;AAAA,MACnB,KAAK;AACH,eAAO,MAAM,oCAAoC;AACjD;AAAA,MACF,KAAK;AACH,eAAO,KAAK,gDAAgD;AAC5D;AAAA,MACF,KAAK;AACH,eAAO,KAAK,gCAAgC;AAC5C;AAAA,MACF,KAAK;AACH,YAAI,MAAM,MAAM,UAAU,oBAAoB;AAC5C,iBAAO,KAAK,8BAA8B,MAAM,MAAM,KAAK,SAAS;AACpE;AAAA,QACF;AAEA,YAAI,MAAM,MAAM,UAAU,kBAAkB;AAC1C,iBAAO,KAAK,qBAAqB,MAAM,MAAM,OAAO,UAAU;AAC9D;AAAA,QACF;AAEA,YACE,MAAM,MAAM,UAAU,6BACrB,MAAM,MAAM,kBAAkB,MAAM,MAAM,gBACzC,MAAM,MAAM,kBAAkB,KAC9B,MAAM,MAAM,gBAAgB,qBAAqB,MACnD;AACA,8BAAoB,MAAM,MAAM;AAChC,gBAAM,iBACJ,MAAM,MAAM,iBAAiB,IACzB,MACA,KAAK,MAAO,MAAM,MAAM,gBAAgB,MAAM,MAAM,eAAgB,GAAG;AAC7E,iBAAO;AAAA,YACL,6BAA6B,MAAM,MAAM,aAAa,IAAI,MAAM,MAAM,YAAY,KAAK,cAAc;AAAA,UACvG;AAAA,QACF;AACA;AAAA,MACF,KAAK;AACH,eAAO,KAAK,8BAA8B;AAC1C;AAAA,MACF,KAAK;AACH,eAAO,MAAM,4CAA4C,MAAM,SAAS,GAAG;AAC3E;AAAA,IACJ;AAAA,EACF;AACF;AAEO,IAAM,oBAAoB,OAC/B,WACA,oBACA,SAAiB,mBAAmB,MACR;AAC5B,QAAM,gBAAgB,QAAQ,IAAI,UAAU,KAAK,QAAQ,IAAI;AAC7D,QAAM,aAAa,kBAAkB,WAAW,aAAa;AAC7D,SAAO,KAAK,yBAAyB,UAAU,EAAE;AAEjD,SAAO,KAAK,2BAA2B;AACvC,QAAM,aAAa,yBAAyB;AAAA,IAC1C,aAAa;AAAA,IACb,YAAY,iCAAiC,MAAM;AAAA,EACrD,CAAC;AACD,SAAO;AAAA,IACL,6BAA6B,WAAW,QAAQ,SAAS,WAAW,WAAW,QAAQ,SAAS,YAAY,WAAW,QAAQ,UAAU;AAAA,EAC3I;AAEA,SAAO,KAAK,6CAA6C,kBAAkB,GAAG;AAC9E,QAAM,YAAY,kCAAkC;AAAA,IAClD,gBAAgB;AAAA,IAChB,QAAQ,EAAE,mBAAmB;AAAA,EAC/B,GAAG,gCAAgC,MAAM,CAAC;AAC1C,MAAI,UAAU,WAAW;AACvB,WAAO;AAAA,MACL,8BAA8B,UAAU,QAAQ,YAAY,WAAW,UAAU,QAAQ,UAAU,sBAAsB,UAAU,QAAQ,2BAA2B;AAAA,IACxK;AAAA,EACF,OAAO;AACL,WAAO,KAAK,mCAAmC,UAAU,MAAM,EAAE;AAAA,EACnE;AAEA,SAAO,KAAK,iCAAiC;AAC7C,QAAM,WAAW,MAAM;AAAA,IACrB,EAAE,gBAAgB,WAAW;AAAA,IAC7B,+BAA+B,MAAM;AAAA,EACvC;AACA,MAAI,SAAS,WAAW;AACtB,WAAO;AAAA,MACL,2BAA2B,SAAS,QAAQ,iBAAiB,YAAY,SAAS,QAAQ,kBAAkB,gBAAgB,SAAS,QAAQ,sBAAsB;AAAA,IACrK;AAAA,EACF,OAAO;AACL,WAAO,KAAK,kCAAkC,SAAS,MAAM,EAAE;AAAA,EACjE;AAEA,SAAO,KAAK,wBAAwB;AACpC,QAAM,OAAO,6BAA6B;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO,KAAK,uCAAuC,KAAK,eAAe,GAAG;AAE1E,QAAM,UAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;;;AHrNA,IAAM,UAAU,IAAI,QAAQ;AAC5B,IAAM,kBAAkBC,SAAQ,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,iBAAiB;AAC1F,IAAM,EAAE,QAAQ,IAAI,KAAK,MAAMC,cAAa,iBAAiB,MAAM,CAAC;AAEpE,QACG,KAAK,cAAc,EACnB,YAAY,+EAA+E,EAC3F,QAAQ,OAAO;AAElB,QACG,QAAQ,SAAS,EACjB,SAAS,UAAU,gCAAgC,EACnD;AAAA,EACC,IAAI;AAAA,IACF;AAAA,IACA;AAAA,EACF,EACG,QAAQ,CAAC,gBAAgB,cAAc,CAAC,EACxC,QAAQ,cAAc;AAC3B,EACC;AAAA,EACC,IAAI;AAAA,IACF;AAAA,IACA;AAAA,EACF,EACG,QAAQ,CAAC,UAAU,SAAS,QAAQ,QAAQ,OAAO,CAAC,EACpD,QAAQ,cAAc,QAAQ,IAAI,wBAAwB,CAAC,CAAa;AAC7E,EACC;AAAA,EACC,IAAI;AAAA,IACF;AAAA,IACA;AAAA,EACF,EACG,QAAQ,CAAC,WAAW,MAAM,CAAC,EAC3B,QAAQ,SAAS;AACtB,EACC,OAAO,UAAU,4BAA4B,EAC7C;AAAA,EACC,OACE,MACA,YAMG;AACH,UAAM,SAAS,mBAAmB,QAAQ,QAAQ;AAClD,UAAM,UAAU,MAAM,kBAAkB,MAAM,QAAQ,gBAAgB,MAAM;AAC5E,UAAM,aAAgC,QAAQ,SAAS,OAAO,SAAS,QAAQ;AAC/E,YAAQ,OAAO,MAAM,GAAG,oBAAoB,SAAS,UAAU,CAAC;AAAA,CAAI;AAAA,EACtE;AACF;AAEF,IAAI,QAAQ,KAAK,UAAU,GAAG;AAC5B,UAAQ,WAAW;AACnB,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,iBAAiB,QAAQ,KAAK,CAAC,KAAK;AAC1C,IAAM,aAAa,QAAQ,KAAK,CAAC,KAAK;AAEtC,IAAM,OACJ,QAAQ,KAAK,CAAC,MAAM,OAChB,CAAC,gBAAgB,YAAY,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC,IACrD,QAAQ;AAEd,IAAI,KAAK,UAAU,GAAG;AACpB,UAAQ,WAAW;AACnB,UAAQ,KAAK,CAAC;AAChB;AAEA,MAAM,QAAQ,WAAW,IAAI;","names":["readFileSync","resolve","resolve","nodeLowLink","program","packageJsonPath","version","round4","round4","round4","normalizePath","resolve","resolve","readFileSync"]}
|