import type { HeapDiff, NodeFinding } from "./heap-diff.js"; import type { ModuleRegistry } from "./module-registry.js"; export type Owner = "app" | "dependency" | "framework" | "unattributed"; export type FindingAttribution = { owner: Owner; /** Display path relative to the project (e.g. `src/app/leaky/page.tsx`). */ source: string | null; packageName: string | null; }; export type RouteAttribution = FindingAttribution & { /** Share of attributed retained bytes held by the winning owner+source. */ dominance: number; }; /** * Classifies one bundler source path. Handles both real-world dialects seen * in Turbopack builds: `[project]/…` prefixes (Next 16.0) and URL-encoded * relative paths like `../../../node_modules/.pnpm/%40scope%2Bpkg@1/…` * (Next 16.2 sectioned maps). Exported for direct unit testing. */ export declare function classifySource(rawSource: string): FindingAttribution; /** * Resolves a finding's harvested module ids against the registry. When a * chain crosses several modules (e.g. Next's page-template wrapper retaining * the user's page module), the most user-actionable owner wins: app over * dependency over framework. Ties keep chain order (closest to the leak). */ export declare function attributeFinding(finding: Pick, registry: ModuleRegistry): FindingAttribution; export type AttributedDiff = { /** Aligned with `[...diff.grownNodes, ...diff.newNodes]`. */ findings: FindingAttribution[]; route: RouteAttribution; }; /** * Attributes every finding and derives the route-level verdict: the * owner+source group holding the most attributed retained bytes wins; * with nothing attributed the route stays `unattributed`. */ export declare function attributeDiff(diff: HeapDiff, registry: ModuleRegistry): AttributedDiff;