/** * Public API surface contract — the exported symbols a package offers the outside * world, with their signatures, plus a deterministic breaking-change classification * of how that surface changed across a diff. (change: add-public-api-surface-contract) * * This module is intentionally PURE: it operates on already-extracted signature * strings and export sets, so the classification logic is unit-tested without disk, * git, or the call graph. The disk/git-backed assembly (base-ref snapshots, continuity * rename detection, consumer resolution, confidence-boundary) lives in the handler * `../services/mcp-handlers/public-surface.ts`. * * Discipline (mirrors the proposal's Decision): * - Classify compatibility from the statically-available signature ONLY. No type * checker, no compiler, no build. * - When compatibility CANNOT be proven from the available types, the verdict is * `potentially-breaking` — never silently `non-breaking`. The classifier never * asserts "safe" on evidence it does not have. * - No similarity score, no threshold, no tuning constant, no clock, no model. The * result is a pure, byte-identical function of the two signature views. */ import type { ContinuityReason, ContinuityBasis } from '../../types/index.js'; /** A symbol kind on the public surface. */ export type SurfaceKind = 'function' | 'method' | 'class' | 'interface' | 'type' | 'const' | 'unknown'; /** A symbol that is part of a module's exported public surface. */ export interface PublicSurfaceSymbol { /** Exported name (the contract name a consumer binds to). */ name: string; /** Repo-relative file the symbol is defined in. */ file: string; kind: SurfaceKind; /** Normalized one-line declaration (the comparable signature). */ signature: string; /** Call-graph node id (`file::name`) when the symbol resolved to one; for consumer lookup. */ nodeId?: string; } /** The closed breaking-change classification (proposal §2). */ export type ChangeClass = 'breaking' | 'non-breaking' | 'potentially-breaking'; /** How a public-surface symbol changed across the diff. */ export type SurfaceChangeKind = 'removed' | 'added' | 'renamed' | 'signature' | 'visibility-reduced'; /** A single classified change to the public surface. */ export interface SurfaceChange { changeKind: SurfaceChangeKind; class: ChangeClass; /** The symbol's contract name (the base name for removed/renamed/signature/visibility). */ name: string; file: string; kind: SurfaceKind; /** The base-ref signature, when the symbol existed before. */ before?: string; /** The head signature, when the symbol exists after. */ after?: string; /** Transparent, human-readable reasons behind the class (the evidence, not a score). */ reasons: string[]; /** For a rename, the new name/location (detected via symbol-identity continuity). */ rename?: { to: string; file: string; reason: ContinuityReason; basis: ContinuityBasis; }; } /** One parsed parameter of a signature. */ export interface ParsedParam { name: string; /** Optional via `?`, a default value (`=`), or a rest param (`...`). */ optional: boolean; rest: boolean; /** The declared type, when statically present; omitted for untyped params. */ type?: string; } /** A best-effort structured view of a normalized signature string. */ export interface ParsedSignature { params: ParsedParam[]; returnType?: string; /** * `typed` — params and return carry static types (compatibility is provable); * `untyped` — parsed, but some types are absent (compatibility may be unprovable); * `unparsed` — the param list could not be located (treat any change as unprovable). */ confidence: 'typed' | 'untyped' | 'unparsed'; } /** True when the language's signatures are structured enough to parse for compatibility. */ export declare function signatureClassifiable(language: string): boolean; /** * Parse a normalized signature string into a best-effort structured view. Tolerant by * design: an unlocatable param list yields `confidence: 'unparsed'` (every change is * then unprovable → potentially-breaking), never a guessed shape. */ export declare function parseSignature(signature: string, language: string): ParsedSignature; /** Relationship between two declared types under the union-subset model. */ export type TypeRelation = 'same' | 'narrowed' | 'widened' | 'incomparable'; /** * Compare two declared types by union membership only — the sound fragment we can * decide without a type lattice. `narrowed` = the set of admissible types shrank * (after ⊊ before); `widened` = it grew; `incomparable` = neither contains the other * (the honest "cannot prove a direction" case → potentially-breaking upstream). */ export declare function compareTypes(before: string, after: string): TypeRelation; /** * Classify a change to a symbol that exists on both sides (same name + file) from its * before/after signature. Conservative by construction: any change that cannot be * proven compatible from the available types is `potentially-breaking`, never folded * into `non-breaking`. */ export declare function classifySignatureChange(beforeSig: string, afterSig: string, language: string): { class: ChangeClass; reasons: string[]; }; /** Roll an overall verdict up from the per-symbol classes (breaking dominates). */ export declare function overallClass(changes: readonly SurfaceChange[]): ChangeClass; //# sourceMappingURL=public-surface.d.ts.map