/** * The `stale-decision-reference` finding (change: add-finding-enforcement-policy). * * OpenLore tracks decision supersession (`supersedes`, queryable via `asOf`) and * anchors memory to symbols, but a *live, authoritative artifact that still points * at a decision that has since been superseded* is only discoverable by manually * walking history. That is a textbook stale reference: the artifact asserts * something whose stated basis was retired. * * This module makes it a first-class deterministic finding. A live, authoritative * artifact is: * - an approved/synced architectural decision (and not itself superseded), * - a non-orphaned, non-invalidated anchored memory, or * - a spec requirement, * that names a decision id that has since been superseded by an active decision. * * The supersession edge that performed the retirement is EXEMPT: a decision whose * `supersedes` points at the retired one is supposed to reference it. The check is * a pure walk of the decision graph + anchored references — no LLM (north star * `c6d1ad07`). It is surfaced through existing surfaces (`recall`, the gate), never * a new MCP tool. */ import type { PendingDecision, AnchoredMemory, MemoryFreshness } from '../../../types/index.js'; export interface StaleDecisionReferenceFinding { code: 'stale-decision-reference'; /** Intrinsic severity, owned by this source (never altered by the enforcement policy). */ severity: 'warn'; /** The live, authoritative artifact that references the retired decision. */ referencingArtifact: { kind: 'decision' | 'memory' | 'spec'; /** Decision/memory id, or the spec file path. */ id: string; /** A short human label (decision title / memory excerpt / spec heading). */ label: string; }; /** The retired (superseded) decision id being referenced. */ retiredDecision: string; /** The decision that superseded it. */ supersededBy: string; message: string; } /** The retirement graph: which decision ids are retired, and by whom. */ export interface RetirementGraph { /** retiredId → the id of the active decision that superseded it. */ supersededBy: Map; } /** * Build the retirement graph from the decision set: for every active superseding * decision C (`C.supersedes = B`), B is retired by C. Uses the SAME predicate as * the reversal/authoritative surfaces ({@link isEffectiveSuperseder}) so the two * never disagree about what counts as superseded. */ export declare function buildRetirementGraph(decisions: readonly PendingDecision[]): RetirementGraph; /** A single stale reference: the retired decision a text cites and its active superseder. */ export interface StaleRef { retired: string; supersededBy: string; } /** * The stale references in a piece of text against a retirement graph — the reusable * core behind `recall`'s freshness signal. Returns one entry per distinct retired * decision the text cites (excluding the `exempt` supersedes edge). Empty when the * graph is empty or nothing is cited. Pure, no I/O. */ export declare function staleRefsInText(text: string, graph: RetirementGraph, exempt?: string): StaleRef[]; export interface StaleReferenceInputs { decisions: readonly PendingDecision[]; memories: readonly AnchoredMemory[]; /** Spec documents to scan, each as a file path + its full text. */ specs: readonly { file: string; text: string; }[]; /** Freshness of a memory's anchors against the current graph (orphaned ⇒ not authoritative). */ freshnessOf: (m: AnchoredMemory) => MemoryFreshness; } /** * Pure detector: walk the live, authoritative artifacts and emit one finding per * (artifact, retired decision) reference. Deterministic and order-independent — * findings are sorted by a stable key. No I/O, no LLM. */ export declare function findStaleDecisionReferences(input: StaleReferenceInputs): StaleDecisionReferenceFinding[]; /** * Filesystem entry point: load the decision store, memory store, and synced specs, * resolve memory freshness against the current call graph, and run the pure * detector. Never throws for an infrastructure problem — a missing store/graph * degrades to "no findings" (advisory-safe), consistent with the other guards. */ export declare function detectStaleDecisionReferences(directory: string): Promise; //# sourceMappingURL=stale-decision-reference.d.ts.map