/** * Knowledge store query layer for iranti. * * The central CRUD and search interface over the `knowledge_base` (Prisma * `knowledgeEntry`) table and related tables. All reads and writes go through * this module so the vector index, decay metadata, and conflict log stay * consistent with the relational rows. * * Key operations: * - `findEntry` / `findEntriesByEntity` — point lookups and entity scans * - `createEntry` — insert + save vector embedding + set initial stability * - `archiveEntry` / `insertArchiveFromCurrent` — move row to archive table * - `appendConflictLog` — append a conflict event to the entry's JSONB log * - `hybridSearch` — lexical (full-text) + vector (cosine) weighted search; * falls back to pure lexical when the vector backend is unavailable * - `searchWithBridging` — extends hybrid search by walking the entity * relationship graph up to `SEARCH_BRIDGE_MAX_HOPS` hops from top results * - `checkVectorIndexConsistency` / `repairVectorIndex` — audit and repair * drift between the relational store and the vector backend * - Write receipt helpers (M-2): `claimWriteReceiptSlot`, `getWriteReceipt`, * `clearPendingWriteReceiptSlot` * * `DbClient` accepts both the full `PrismaClient` and transaction clients so * callers can pass either `getDb()` or a Prisma transaction `tx`. */ import { EntryInput, EntryQuery, HybridSearchInput, HybridSearchResult, QueryResult } from '../types'; import { Archive, ArchivedReason, KnowledgeEntry, PrismaClient, ResolutionOutcome, ResolutionState } from '../generated/prisma/client'; import { VectorBackend, VectorConsistencyFilter } from './vectorBackend'; type DbClient = PrismaClient | Omit; export type ArchiveHistoryEntry = Archive; export type VectorIndexConsistencyReport = { backend: string; reachable: boolean; repairable: boolean; consistent: boolean; expectedCount: number; indexedCount: number; missingEntryIds: string[]; orphanedVectorIds: string[]; }; export type VectorIndexRepairReport = VectorIndexConsistencyReport & { repairedMissingCount: number; removedOrphanedCount: number; }; type SupersededByPointer = { entityType: string; entityId: string; key: string; }; export type TemporalArchiveOptions = { reason: ArchivedReason; validFrom?: Date; validUntil?: Date | null; resolutionState?: ResolutionState; resolutionOutcome?: ResolutionOutcome; supersededBy?: SupersededByPointer; }; export declare function __setVectorBackendSingletonForTests(backend: VectorBackend | null): void; export declare function getVectorBackendSingleton(): VectorBackend; export declare function findEntry(query: EntryQuery, db?: DbClient): Promise; export declare function queryEntry(query: EntryQuery, db?: DbClient): Promise; export declare function findEntriesByEntity(entityType: string, entityId: string, db?: DbClient): Promise; export declare function findEntriesByEntityType(entityType: string, db?: DbClient): Promise; export declare function listAttendantStateEntries(filters?: { agentId?: string; }, db?: DbClient): Promise>>; /** * A2: reverse-index query used by `iranti revert-autowrite`. Finds all * knowledge entries written with a specific `source` tag inside a * time window. The Attendant stamps every autowrite with * source='attendant_autowrite' and an autowriteBatchId in properties, so * this pair (source, createdAt window) is enough to list every autowrite * the agent performed in the last N minutes/hours. * * Returned entries include their id so the caller can call deleteEntryById * on each one — we intentionally do NOT delete here, because the CLI * defaults to --dry-run and should print targets before destroying them. * * @param source The source label to match (e.g. 'attendant_autowrite'). * @param since Lower bound (inclusive) on createdAt. Entries created at or * after this timestamp are eligible. * @param until Optional upper bound (inclusive). Defaults to now — callers * can narrow to a specific window for deterministic rollback. */ export declare function findEntriesBySourceAndWindow(source: string, since: Date, until?: Date, db?: DbClient): Promise; /** * A2: destructive counterpart to findEntriesBySourceAndWindow. Deletes * every knowledge entry matching (source, createdAt window) and returns * the count deleted. Meant to be called only from the CLI after the * dry-run preview has been shown to the user. Uses a single deleteMany * query so it is atomic at the Prisma level. */ export declare function deleteEntriesBySourceAndWindow(source: string, since: Date, until?: Date, db?: DbClient): Promise; export declare function findArchiveAsOf(query: EntryQuery, asOf: Date, options?: { includeExpired?: boolean; includeContested?: boolean; }, db?: DbClient): Promise; export declare function findArchiveHistory(query: EntryQuery, options?: { includeExpired?: boolean; includeContested?: boolean; }, db?: DbClient): Promise; export declare function findPendingEscalation(query: EntryQuery, db?: DbClient): Promise; export declare function searchEntriesHybrid(input: HybridSearchInput, db?: DbClient): Promise; export declare function createEntry(input: EntryInput, db?: DbClient): Promise; export declare function updateEntry(query: EntryQuery, updates: Partial, db?: DbClient): Promise; export declare function deleteEntryById(entryId: number, db?: DbClient): Promise; export declare function auditVectorIndexConsistency(filter?: VectorConsistencyFilter, db?: DbClient): Promise; export declare function repairVectorIndexConsistency(filter?: VectorConsistencyFilter, options?: { repopulateMissing?: boolean; removeOrphaned?: boolean; }, db?: DbClient): Promise; export declare function insertArchiveFromCurrent(entry: KnowledgeEntry, options: TemporalArchiveOptions, db?: DbClient): Promise; export declare function archiveEntry(entry: KnowledgeEntry, reason: ArchivedReason, supersededBy?: SupersededByPointer, db?: DbClient): Promise; export declare function updateArchiveEntry(id: number, updates: { validUntil?: Date | null; resolutionState?: ResolutionState; resolutionOutcome?: ResolutionOutcome; }, db?: DbClient): Promise; export declare function recordKnowledgeEntryAccess(entryIds: number[], db?: DbClient): Promise; export declare function isProtectedEntry(query: EntryQuery, db?: DbClient): Promise; export declare function isStaffNamespace(entityType: string): boolean; export declare function canWriteToStaffNamespace(createdBy: string, entityType: string): boolean; export declare function appendConflictLog(entryId: number, event: unknown, db?: DbClient): Promise; export declare function getWriteReceipt(requestId: string, db?: DbClient): Promise<{ entityType: string; entityId: string; key: string; id: number; createdAt: Date; requestId: string; outcome: string; resultEntryId: number | null; escalationFile: string | null; } | null>; export declare function createWriteReceipt(data: { requestId: string; entityType: string; entityId: string; key: string; outcome: string; resultEntryId?: number | null; escalationFile?: string | null; }, db?: DbClient): Promise<{ entityType: string; entityId: string; key: string; id: number; createdAt: Date; requestId: string; outcome: string; resultEntryId: number | null; escalationFile: string | null; }>; export declare function claimWriteReceiptSlot(data: { requestId: string; entityType: string; entityId: string; key: string; }, db?: DbClient): Promise; export declare function clearPendingWriteReceiptSlot(requestId: string, db?: DbClient): Promise; export declare function updateWriteReceiptOutcome(requestId: string, outcome: string, resultEntryId?: number | null, escalationFile?: string | null, db?: DbClient): Promise; export interface ExportFactsOptions { /** Only export facts of this entityType. */ entityType?: string; /** Only export facts for this entityId (requires entityType). */ entityId?: string; /** Only export facts whose updatedAt is at or after this date (incremental export). */ since?: Date; } /** * A single fact row ready for JSONL serialisation. All Date fields are left * as Date objects so the caller controls how they are serialised (typically * with JSON.stringify which calls .toISOString() automatically). */ export interface ExportRow { entityType: string; entityId: string; key: string; valueRaw: unknown; valueSummary: string | null; confidence: number; source: string; validFrom: Date; validUntil: Date | null; createdBy: string | null; isProtected: boolean; properties: Record | null; updatedAt: Date; createdAt: Date; } /** * Read all (or a filtered slice of) knowledge entries and return them as * plain ExportRow objects suitable for streaming to JSONL. * * Filtering: * entityType + entityId → single-entity export * entityType only → all entries of that type * since → incremental: only entries updated since that timestamp * * No rows are excluded by default — the caller (CLI or REST route) decides * what to filter. Rows are returned ordered by entityType, entityId, key so * the output file is deterministic and easy to diff. */ export declare function exportFacts(options?: ExportFactsOptions, db?: DbClient): Promise; export type ImportConflictMode = 'skip' | 'overwrite' | 'merge'; /** * Shape of a single row in an import file. Mirrors ExportRow but with * optional/nullable fields where a round-trip may omit them. */ export interface ImportRow { entityType: string; entityId: string; key: string; valueRaw: unknown; valueSummary?: string | null; confidence: number; source: string; validFrom?: string | Date | null; validUntil?: string | Date | null; createdBy?: string | null; isProtected?: boolean; properties?: Record | null; } export interface ImportFactResult { outcome: 'added' | 'skipped' | 'overwritten'; entityType: string; entityId: string; key: string; /** Human-readable explanation when outcome is 'skipped'. */ reason?: string; } /** * Write one ImportRow into the knowledge base with configurable conflict * handling. Bypasses the Librarian conflict pipeline intentionally — the user * has already chosen a conflict mode at the import boundary. * * Conflict modes: * skip — leave any existing entry unchanged; return 'skipped' * overwrite — always write (create new or replace existing) * merge — keep whichever entry has the higher confidence value; * skip if existing.confidence >= incoming.confidence * * provenanceTag, when provided, is stamped as `properties.importedFrom` and * `properties.importedAt` on every written entry. This enables targeted undo * with `iranti delete --imported-from `. */ export declare function importFact(row: ImportRow, conflictMode: ImportConflictMode, provenanceTag?: string, db?: DbClient): Promise; export {}; //# sourceMappingURL=queries.d.ts.map