/** * Persistence for the concept layer (`file_concepts`, `subsystems`, * `concept_edges`). * * Unlike the rank tables, these are written incrementally: a summary costs a * model call, so the runner checkpoints as it goes and a cancelled or crashed * pass must not throw away what it already paid for. */ import type { DatabaseSync } from 'node:sqlite'; type Statement = ReturnType; type PrepareStatement = (sql: string) => Statement; /** * Whether a stored summary describes the file's current bytes. * * `stale` is kept rather than deleted: an outdated description of a file is * still a better starting point than nothing, both for a reader and as a hint * to the model on the next pass. */ export type ConceptState = 'ready' | 'stale' | 'pending'; export interface FileConcept { file: string; contentHash: string; summary: string; /** 1-based inclusive line span of the file's load-bearing lines. */ cruxStart: number | null; cruxEnd: number | null; state: ConceptState; model: string; updatedAt: number; } export interface Subsystem { id: string; name: string; summary: string; memberFiles: string[]; model: string; updatedAt: number; } /** * Closed vocabulary for concept-to-concept relations. * * Closed on purpose. An open-ended verb list produces a graph where * `configures`, `sets up` and `initialises` are three different edges between * the same pair, which nothing downstream can group or filter on. */ export declare const CONCEPT_RELATIONS: readonly ['uses', 'configures', 'validates', 'extends', 'persists', 'observes']; export type ConceptRelation = (typeof CONCEPT_RELATIONS)[number]; export declare function isConceptRelation(value: string): value is ConceptRelation; export interface ConceptEdge { fromId: string; toId: string; relation: ConceptRelation; } /** Write (or replace) one file's concept. */ export declare function upsertFileConceptWithStatement(stmt: PrepareStatement, concept: FileConcept): void; export declare function getFileConceptWithStatement(stmt: PrepareStatement, file: string): FileConcept | undefined; /** All concepts, for whole-index consumers (atlas, embeddings, injection). */ export declare function getAllFileConceptsWithStatement(stmt: PrepareStatement): FileConcept[]; /** `file → summary` for the files that currently have a usable description. */ export declare function getReadyConceptSummariesWithStatement(stmt: PrepareStatement): Map; export interface ConceptCoverage { ready: number; stale: number; pending: number; subsystems: number; } export declare function getConceptCoverageWithStatement(stmt: PrepareStatement): ConceptCoverage; /** * Mark every concept whose recorded hash no longer matches the indexed file as * `stale`, in one statement. * * Run before a pass rather than during indexing: the indexer's atomic write is * not the place to reason about a layer it does not own, and a summary that is * one generation behind harms nothing until someone asks for it. */ export declare function markStaleConceptsWithStatement(stmt: PrepareStatement): number; /** Drop concepts for files that are no longer indexed. */ export declare function pruneOrphanConceptsWithStatement(stmt: PrepareStatement): number; /** Replace the whole subsystem layer. Subsystems are derived as a set. */ export declare function replaceSubsystemsWithStatement(stmt: PrepareStatement, maxSqlVars: number, subsystems: readonly Subsystem[], edges: readonly ConceptEdge[]): void; export declare function getSubsystemsWithStatement(stmt: PrepareStatement): Subsystem[]; export declare function getConceptEdgesWithStatement(stmt: PrepareStatement): ConceptEdge[]; export {}; //# sourceMappingURL=writer-concepts.d.ts.map