/** * Deterministic "removed public export" signal for PR reviews. * * Two rules share this signal: * - structural-analysis, whose prompt used to tell the model to * "grep_codebase for EACH removed symbol" — the grep-and-reason * anti-pattern CLAUDE.md's design principle warns against; and * - boundary-change, which needs to cross-check a removed public export * against what the PR's changeset claims (a removal a changeset calls * "unchanged" is a contradiction — the real escape on PR #711). * * This module pre-computes the structural facts instead, mirroring the * `` / `` precedents: parse each * file's diff for exported symbols the PR REMOVES (minus any re-added * anywhere — a moved/renamed-file export is not a removal), then scan the * indexed head corpus for chunks that STILL reference each removed symbol * outside its own file. A surviving reference is a near-certain breaking * change; a removed export a changeset describes as unchanged is a * documentation contradiction. Both facts are injected as a * `` block so the agent confirms a handed-to-it worklist * rather than discovering it via blind grep. * * Scope is deliberately TS/JS (this repo's surface) plus a cheap Rust * `pub` shape (the structural-analysis canary is a Rust testbed file). */ import type { CodeChunk } from '../types.js'; import type { SignalContext } from './signal-context.js'; /** A symbol this PR removes from a module's exported surface. */ export interface RemovedExport { /** Public export name; a default export is recorded as `default (X)`. */ symbol: string; /** First file the diff removed this symbol from. */ file: string; } /** A surviving occurrence of a removed export, outside its own file. */ export interface ExportReference { file: string; line: number; } /** A removed export with its surviving references and any changeset mention. */ export interface RemovedExportContext { symbol: string; file: string; survivingReferences: ExportReference[]; /** The `.changeset/*.md` file that mentions this symbol, or null. */ changesetFile: string | null; } /** * Collect every exported symbol this PR removes, minus any re-added on a `+` * export line ANYWHERE in the PR (a moved/renamed-file export is not a * removal). Deduped by symbol, keeping the first file it was removed from. * Skips non-code files. Exposed for testing. */ export declare function extractRemovedExports(patches: Map): RemovedExport[]; /** * For each removed export, find chunks in the head corpus that STILL reference * it (word-boundary) outside the file it was removed from — the breakage * candidates. Default exports are skipped (no stable importable name). Exposed * for testing. */ export declare function findSurvivingReferences(removed: RemovedExport[], repoChunks: CodeChunk[] | undefined): Map; /** * For each removed export, the `.changeset/*.md` file (if any) whose ADDED * lines mention the symbol — the claim-vs-reality angle for boundary-change. * Exposed for testing. */ export declare function changesetMentions(removed: RemovedExport[], patches: Map): Map; /** * The `` worklist for a review: removed exports, each with its * surviving references and any changeset mention. Sorted breakage-first * (most surviving references first), then changeset-mentioned, then the rest; * ties broken by symbol name for determinism. Returns [] when no diff. */ export declare function computeRemovedExportContexts(context: SignalContext): RemovedExportContext[]; /** * Render removed-export contexts as a `` block for the agent's * initial message. Returns '' when there are none so callers can append * unconditionally. Caps at MAX_ENTRIES and MAX_BLOCK_CHARS with an explicit * omission note. Exposed for testing. */ export declare function renderRemovedExports(contexts: RemovedExportContext[]): string; /** * Build the `` section from the review context. Returns '' * when the PR removes no exported symbols (or there is no diff). */ export declare function renderRemovedExportsSection(context: SignalContext): string; //# sourceMappingURL=removed-export-signals.d.ts.map