/** * Framework route handlers as liveness roots, joined from the route inventory * (change: root-framework-routes). * * `get_route_inventory` and `find_dead_code` read the same build and must not * contradict each other. The liveness roots in `reachability.ts` are built only * from graph EDGES (`http_endpoint`, `deploys_symbol`, `implements_endpoint`, and * synthesized `route-handler` edges), and a framework-decorator route whose * contract is not declared anywhere (`contractSource: "none"`) produces none of * them — so a `@Get('broadcast')` handler that only Nest invokes read as * high-confidence dead while the inventory listed it as a route. * * `route-inventory.json` is already on disk from `analyze`, so this is a JOIN, not * new analysis: each inventoried route is resolved to a graph node by file + * handler name. * * HONEST BY CONSTRUCTION — a root attributed to the wrong node is worse than a * disclosed unresolved handler, because it makes real dead code look live. So a * handler is a root ONLY when it pins to exactly one declaration in that file. * Every other outcome (several declarations, none, a file not in the index, an * unnamed handler, a path outside the repository, a route past the cap) is * counted and named in {@link RouteRootsNotAssessed}, never guessed — because an * inventoried route whose handler cannot be pinned leaves real code looking dead. */ /** Routes joined in one answer. A repository-controlled count, so it is bounded and the cap disclosed. */ export declare const MAX_ROUTES_JOINED = 50000; /** Longest handler name matched. A longer one cannot be a declaration name, so it is not matched. */ export declare const MAX_HANDLER_NAME_CHARS = 256; /** Unresolved routes listed individually; the rest are counted. */ export declare const MAX_UNRESOLVED_LISTED = 10; /** Why an inventoried route kept no function live. A closed set. */ export type RouteRootRefusal = /** The route names no handler, or a name too long to be a declaration. */ 'handler-not-named' /** The route's file is absolute, or escapes the repository root. */ | 'outside-repository' /** No indexed function lives in that file (not parsed, excluded, or deleted since). */ | 'file-not-indexed' /** The file is indexed but holds no declaration of that name. */ | 'handler-not-in-file' /** Several declarations of that name in that file — none is selected. */ | 'ambiguous' /** Past {@link MAX_ROUTES_JOINED}. */ | 'over-cap'; export interface RouteRootsNotAssessed { total: number; byReason: Partial>; items: Array<{ method: string; path: string; framework: string; file: string; handler: string; reason: RouteRootRefusal; }>; note: string; } export interface RouteInventoryRoots { /** Node ids an inventoried route pins to exactly one declaration — liveness roots. */ rootIds: Set; /** * Node ids an inventoried handler NAMES but could not be pinned to (the several * same-named declarations of an `ambiguous` route). Not roots — but the inventory * says one of them serves a route, so none may be asserted high-confidence dead * and none may be told it is "not a route handler". */ namedButUnresolvedIds: Set; /** Routes read from the artifact (0 when it is absent or unreadable). */ routesRead: number; /** Resolved roots per inventory `framework`, for the roots receipt. */ byFramework: Record; /** Present when a route kept no function live. */ notAssessed?: RouteRootsNotAssessed; /** * Present when the artifact could not be read as a route inventory: the answer then * degrades to the edge-only roots it had before this join, and says so. */ artifactBoundary?: string; } /** A graph node, as much of it as the join reads. */ export interface JoinableNode { id: string; name: string; filePath: string; } /** One route, as far as the join trusts the (repository-controlled) artifact. */ interface RawRoute { method: string; path: string; framework: string; file: string; handler: string; } /** * A graph file path and an inventory file path in ONE spelling: forward slashes, no * `./` prefix. Both sides are repo-relative, so this is the whole normalization — * there is deliberately no suffix or basename fallback, because a basename match is * exactly the guess that attributes a root to the wrong node. */ export declare function routeFileKey(filePath: string): string; /** * Resolve the inventory's handlers against the graph. O(nodes + routes): the file → * name → ids index is built once, and each route is a constant-time lookup. */ export declare function buildRouteInventoryRoots(routes: readonly RawRoute[], nodes: readonly JoinableNode[]): RouteInventoryRoots; /** * Read `route-inventory.json` and resolve its handlers. An absent, oversized, * truncated, or non-JSON artifact degrades to the edge-only roots WITH a boundary — * it never throws and never silently reports "no routes". */ export declare function loadRouteInventoryRoots(absDir: string, nodes: readonly JoinableNode[]): Promise; /** * The per-candidate reason clause. Every inventory `framework` is an HTTP routing * framework (nestjs, express, fastify, nextjs-app, fastapi, flask, django, * starlette, spring, jaxrs, …), so these roots all count under * `rootKinds.httpHandlers`; no finer split is clearly true from this field alone. */ export declare function routeHandlerReason(): string; export {}; //# sourceMappingURL=route-inventory-roots.d.ts.map