/** * Temporal Supersession — audit-trail-preserving memory supersession for CLEO BRAIN. * * When new information contradicts or replaces old memory, the old entry is * marked as SUPERSEDED (via `invalid_at`) and a directed `supersedes` graph * edge is created from the new entry to the old one. Nothing is deleted — * the full chain is preserved for temporal reasoning. * * Key design properties: * - All writes are BEST-EFFORT where indicated — failures never block callers. * - Supersession only operates on currently-valid entries (invalid_at IS NULL). * - Embedding similarity is used when sqlite-vec is available; keyword overlap * is used as a fallback. * - A single node ID convention is maintained: ':'. * * Supported tables: brain_decisions, brain_patterns, brain_learnings, brain_observations. * * T739: detectSupersession now uses sqlite-vec ANN query as the primary similarity * path when embeddings are available (isEmbeddingAvailable() + isBrainVecLoaded()). * Falls back to Jaccard keyword overlap when vectors are absent. The final * candidate score is the max of the embedding cosine similarity and the keyword * Jaccard ratio, so the most informative signal wins. * * @epic T523 * @task T739 */ /** A brain table entry capable of being superseded. */ export interface SupersedableEntry { /** Row primary key. */ id: string; /** Text content used for similarity comparison. */ text: string; /** ISO 8601 creation timestamp. */ createdAt: string; /** Quality score 0.0–1.0 (null on legacy rows). */ qualityScore: number | null; /** Whether this entry is currently valid (invalid_at IS NULL). */ isValid: boolean; } /** The full supersession chain for one entry (newest → oldest). */ export interface SupersessionChain { /** The entry whose history was requested. */ entryId: string; /** * Ordered chain of node IDs from the entry back to the original. * The first element is the entry itself; subsequent elements are older * versions that were superseded one-by-one. */ chain: SupersessionChainEntry[]; } /** One entry in a supersession chain. */ export interface SupersessionChainEntry { /** Brain graph node ID in the form ':'. */ nodeId: string; /** Source entry ID (without the type prefix). */ entryId: string; /** Human-readable label from brain_page_nodes (may be absent for external nodes). */ label: string | null; /** ISO 8601 creation time of the graph node. */ createdAt: string; /** Whether the source entry is currently valid (invalid_at IS NULL). */ isLatest: boolean; /** Reason this entry was superseded (null if it is the latest). */ supersededReason: string | null; } /** Result of a `supersedeMemory` call. */ export interface SupersedeResult { /** Whether the supersession was recorded. */ success: boolean; /** The entry that was marked as superseded. */ oldId: string; /** The new entry that supersedes the old one. */ newId: string; /** The created edge type ('supersedes'). */ edgeType: 'supersedes'; } /** A candidate supersession pair found by `detectSupersession`. */ export interface SupersessionCandidate { /** ID of the existing entry that may be superseded. */ existingId: string; /** Similarity score 0.0–1.0 that triggered the candidate. */ similarity: number; /** Table containing the existing entry. */ table: string; /** Shared keywords that connected the two entries (keyword-fallback path). */ sharedKeywords: string[]; } /** * Mark an existing memory entry as superseded by a newer one. * * Effects: * 1. Sets `invalid_at` on the old entry (soft-eviction; the row is kept). * 2. Inserts a `supersedes` edge in brain_page_edges: new → old. * The `provenance` field carries the reason for the supersession. * 3. Creates/refreshes brain_page_nodes rows for both entries (best-effort). * * The old entry is NEVER deleted — it remains in the table as an audit record. * Only entries currently valid (invalid_at IS NULL) can be superseded. * * @param projectRoot - Absolute path to the CLEO project root. * @param oldId - ID of the entry being superseded. * @param newId - ID of the newer entry that supersedes the old one. * @param reason - Human-readable reason for the supersession (stored as edge provenance). * @returns SupersedeResult describing the outcome. * @throws When either entry cannot be located or the DB is unavailable. */ export declare function supersedeMemory(projectRoot: string, oldId: string, newId: string, reason: string): Promise; /** * Detect whether a new entry supersedes existing brain entries. * * Called automatically by the store functions (`storeDecision`, `storeLearning`, * `storePattern`) after a new entry is written. Compares the new entry's content * against existing valid entries in the same table using keyword-based Jaccard * similarity (embedding similarity used when available via sqlite-vec). * against existing valid entries in the same table using: * * 1. Embedding similarity (via sqlite-vec) when available and the entry has a * vector. Falls back to keyword-based Jaccard if vectors are absent. * 2. Keyword Jaccard similarity ≥ KEYWORD_OVERLAP_THRESHOLD. * * An entry is only considered a supersession candidate when the new entry is * temporally newer than the existing one (guaranteed for freshly-written entries). * * This function is BEST-EFFORT — it never throws. Errors are swallowed and * logged with console.warn so the calling store function is not blocked. * * @param projectRoot - Absolute path to the CLEO project root. * @param newEntry - The freshly-stored entry to check against existing entries. * @returns List of candidate supersessions (empty if none found or on any error). */ export declare function detectSupersession(projectRoot: string, newEntry: { id: string; text: string; /** ISO 8601 creation timestamp of the new entry. */ createdAt: string; }): Promise; /** * Trace the full supersession chain for a given entry. * * Follows `supersedes` edges outward (new → old) until no further edges * exist or a cycle guard limit is reached. Returns the chain ordered from * the given entry (first element) back to the original version (last element). * * This is a pure read operation that never modifies any data. * * @param projectRoot - Absolute path to the CLEO project root. * @param entryId - The entry whose history should be traced. * @returns SupersessionChain with the full ordered chain. */ export declare function getSupersessionChain(projectRoot: string, entryId: string): Promise; /** * Check whether a brain entry is the latest (non-superseded) version in its chain. * * An entry is "latest" when its `invalid_at` column IS NULL. This is the same * gate used by all query paths to filter out stale entries. * * @param projectRoot - Absolute path to the CLEO project root. * @param entryId - The entry to check. * @returns true when the entry is valid; false when superseded or not found. */ export declare function isLatest(projectRoot: string, entryId: string): Promise; //# sourceMappingURL=temporal-supersession.d.ts.map