/** * Confidence-boundary disclosure (change: add-confidence-boundary-disclosure). * * Every conclusion answer carries a deterministic `confidenceBoundary` saying what * it does NOT know: how much of the traversal rested on directly-resolved edges vs * synthesized (heuristic) ones, which known-unknowable boundaries it crossed, and * whether the index it ran against still matches the working tree. Categorical * labels and counts only — never a blended confidence score, never an LLM call * (north star c6d1ad07). Additive metadata: a caller that ignores it sees today's * answer unchanged. * * The basis and crossings are derived from the `confidence`/`synthesizedBy` * provenance already on every edge (spec: add-synthesized-dynamic-dispatch-edges, * add-type-hierarchy-resolved-dispatch). The staleness marker reuses the project * fingerprint written at analyze time and the git diff machinery — nothing new is * computed at analyze time except the optional build commit. */ /** The only edge fields the boundary reads — a minimal, structural view. */ export interface BoundaryEdge { confidence?: string; synthesizedBy?: string; } /** An edge in the call graph, as the boundary needs to see it for pair indexing. */ interface PairableEdge extends BoundaryEdge { callerId?: string; calleeId?: string; } /** How an answer's traversal was grounded: direct vs heuristically-recovered edges. */ export interface EdgeBasis { /** Edges resting on direct name/type resolution. */ directEdges: number; /** Edges recovered heuristically (confidence === 'synthesized'). */ synthesizedEdges: number; /** Synthesized-edge count broken down by the rule that produced each. */ synthesizedByRule?: Record; } export type KnownUnknowableKind = 'synthesized-dispatch' | 'unindexed-repo'; /** A boundary the computation is known to be unable to see past. */ export interface KnownUnknowableCrossing { kind: KnownUnknowableKind; /** The synthesis rule, when kind === 'synthesized-dispatch'. */ rule?: string; count: number; /** Actionable, human-readable disclosure. */ detail: string; } /** The index lags the working tree: source has changed since the build commit. */ export interface StalenessMarker { /** Short SHA the index was built at. */ indexCommit: string; /** Source files changed since the build commit (graph-relevant extensions). */ filesChangedSince: number; detail: string; } export interface ConfidenceBoundary { /** How the traversal was grounded. Omitted for non-traversal answers (recall). */ basis?: EdgeBasis; /** Boundaries the computation cannot see past. Absent when none. */ knownUnknowable?: KnownUnknowableCrossing[]; /** Index-vs-working-tree staleness. Absent when the index is current. */ staleness?: StalenessMarker; /** * True iff the computation crossed no boundary: no synthesized-edge reliance, no * known-unknowable crossing, and a current index. The answer-level * NoFalseCompleteness flag — an incomplete answer is never dressed as complete. */ complete: boolean; } /** Tally direct vs synthesized edges (by rule) from a set of traversed edges. */ export declare function edgeBasis(edges: Iterable): EdgeBasis; /** Count direct vs synthesized edges internal to a node-id set (both endpoints in). */ export declare function edgeBasisWithinSet(edges: Iterable, nodeIds: Set): EdgeBasis; /** * Index a call-edge list by `caller→callee` for chain lookups. When both a direct * and a synthesized edge exist for the same pair, the direct one wins: the path is * realizable without the heuristic, so it is not a boundary crossing. */ export declare function buildPairEdgeIndex(edges: Iterable): Map; /** Edge basis for a set of node-id chains, deduping repeated caller→callee pairs. */ export declare function edgeBasisForChains(chains: string[][], pairIndex: Map): EdgeBasis; /** * The known-unknowable crossings implied by a basis: each synthesized rule is a * recovered-heuristic dispatch boundary the agent should verify before asserting. */ export declare function crossingsFromBasis(basis: EdgeBasis): KnownUnknowableCrossing[]; /** * Pure staleness decision: emit a marker only when we can both name the build * commit AND count graph-relevant source files changed since it. A null commit * (older index, or a non-git analyze) or a null count (not a git repo, git failed) * means we cannot assess staleness reliably — we stay silent rather than cry wolf * on every answer. Zero changed source files means the index is current. */ export declare function buildStalenessMarker(indexCommit: string | null, changedSourceFiles: number | null): StalenessMarker | undefined; /** * Staleness marker when source has changed since the index's build commit. Git-based * and deterministic: staleness fires iff graph-relevant source files changed since * the commit the index was built at. Returns undefined when the index is current, or * when staleness cannot be assessed (no build commit, or not a git repo). */ export declare function computeStaleness(absDir: string, now?: number): Promise; /** * Assemble a boundary from its parts and derive `complete`. The synthesized-edge * crossings are derived from the basis; callers may add extra crossings (e.g. an * unindexed federated repo). An answer is complete only when nothing was crossed * and the index is current. */ export declare function assembleBoundary(parts: { basis?: EdgeBasis; extraCrossings?: KnownUnknowableCrossing[]; staleness?: StalenessMarker; }): ConfidenceBoundary; /** Reset the staleness memo — test-only hook so a stubbed fingerprint is re-read. */ export declare function __resetStalenessMemo(): void; export {}; //# sourceMappingURL=confidence-boundary.d.ts.map