/** * Semantic note repository — the SemanticNote type, row mapping, and CRUD * (save, read, update, supersede, link migration). */ import type { Database } from "./schema.js"; export interface SemanticNote { noteId: string; type: "fact" | "preference" | "pattern" | "entity" | "relationship"; content: string; keywords: string[]; confidence: number; priority: number; threadId: number | null; sourceEpisodes: string[]; linkedNotes: string[]; linkReasons: Record; validFrom: string; validTo: string | null; supersededBy: string | null; accessCount: number; lastAccessed: string | null; isGuardrail: boolean; pinned: boolean; qualityScore: number | null; /** * Optional write-time TTL (ISO-8601). When set, the consolidation TTL sweep * soft-expires the note once it passes. NULL = never expires on a timer. * Independent of validTo, which is the tombstone written at expiry. */ expiresAt: string | null; createdAt: string; updatedAt: string; } /** A primary `ORDER BY` key a caller puts in front of the shared chain. */ interface OrderKey { column: string; sql: string; } /** * The chain's own clause for `column`, for callers that lead with a column the * chain also carries. Look it up rather than respelling it: `rankedOrderBy` drops * the duplicate by column name, so a caller and the table can never disagree about * how "confidence DESC" happens to be written. */ export declare function rankKey(column: string): OrderKey; /** * `ORDER BY` list for a SQL read path, with the shared chain as its tail. * * `leading` is for callers whose own primary sort is deliberate. A leading key on a * column the chain also sorts by is not repeated in the tail. */ export declare function rankedOrderBy(...leading: OrderKey[]): string; /** `ORDER BY` tail for the paths that rank by relevance alone. */ export declare const RANK_TIEBREAKERS: string; /** The same chain for the in-memory path, applied after relevance. */ export declare function compareRankTiebreakers(a: SemanticNote, b: SemanticNote): number; /** Increment access_count and update last_accessed for a batch of note IDs. */ export declare function bumpAccessCounts(db: Database, noteIds: string[]): void; export declare function rowToSemanticNote(row: Record): SemanticNote; /** Look up a single semantic note by ID (returns type + keywords only, or undefined). */ export declare function getSemanticNoteById(db: Database, noteId: string): { type: string; keywords: string[]; } | undefined; export declare function getSemanticNotesByIds(db: Database, noteIds: string[]): SemanticNote[]; export declare function saveSemanticNote(db: Database, note: { type: "fact" | "preference" | "pattern" | "entity" | "relationship"; content: string; keywords: string[]; confidence?: number; priority?: number; threadId?: number | null; isGuardrail?: boolean; pinned?: boolean; sourceEpisodes?: string[]; qualityScore?: number | null; linkedNotes?: string[]; linkReasons?: Record; /** Optional write-time TTL (ISO-8601). Unset ⇒ NULL ⇒ note never times out. */ expiresAt?: string | null; }): string; export declare function getTopSemanticNotes(db: Database, options?: { type?: string; limit?: number; sortBy?: "confidence" | "access_count" | "created_at" | "updated_at"; threadId?: number; }): SemanticNote[]; /** * Guardrail notes: explicitly flagged decision constraints the LLM must always * follow. Capped at 5, ordered by priority DESC — a guardrail surfaces by how * important it is, not by how often it has been read — then by the shared chain. */ export declare function getGuardrailNotes(db: Database): SemanticNote[]; /** * IDs of every active pinned note for a thread — the boost set fed to the * relevance-anchored Key-Knowledge selection. This is uncapped and unordered: * pinning only nudges a note's ranking now, so the selector needs the full set. */ export declare function getPinnedNoteIds(db: Database, threadId: number): Set; export declare function updateSemanticNote(db: Database, noteId: string, updates: Partial<{ content: string; confidence: number; priority: number; keywords: string[]; linkedNotes: string[]; linkReasons: Record; }>): void; export declare function supersedeNote(db: Database, oldNoteId: string, newNote: { type: string; content: string; keywords: string[]; confidence?: number; priority?: number; qualityScore?: number | null; sourceEpisodes?: string[]; }): string; /** * Repoint inbound causal links from a now-dead note to its successor. * When `fromNoteId` is superseded/merged into `toNoteId`, any active note that * linked to `fromNoteId` is repointed at the live successor — otherwise the link * is dead-on-arrival, since the consumer filters out expired link targets. */ export declare function migrateInboundLinks(db: Database, fromNoteId: string, toNoteId: string): void; export {}; //# sourceMappingURL=semantic-notes.d.ts.map