/** * Brain graph back-fill — populates brain_page_nodes and brain_page_edges from * existing typed table rows (decisions, patterns, learnings, observations, * sticky notes). * * Each row in a typed table gets a corresponding node in brain_page_nodes. * Relationship edges are derived from: * - decision.contextTaskId / contextEpicId → applies_to edges * - observation.sourceSessionId → produced_by edge * - observation text referencing task IDs → applies_to edges * - pattern entries → derived_from stubs * * Stub nodes (task:, session:, epic:) are created for referenced * external entities so edges have valid targets. * * Duplicate nodes are silently skipped (INSERT OR IGNORE semantics via * Drizzle onConflictDoNothing). * * T1003: Staged backfill functions (stagedBackfillRun, approveBackfillRun, * rollbackBackfillRun, listBackfillRuns) are appended below the graph * back-fill core. Staged runs write row IDs to brain_backfill_runs first; * actual mutations happen only on approve. * * @task T530 * @epic T523 */ import type { BrainBackfillRunRow } from '../store/schema/memory-schema.js'; /** Result returned by backfillBrainGraph. */ export interface BrainBackfillResult { /** Counts before the back-fill ran. */ before: { nodes: number; edges: number; decisions: number; patterns: number; learnings: number; observations: number; stickyNotes: number; }; /** Counts after the back-fill ran. */ after: { nodes: number; edges: number; }; /** Number of nodes inserted during this run. */ nodesInserted: number; /** Number of edges inserted during this run. */ edgesInserted: number; /** Number of stub nodes created for external references (tasks, sessions, epics). */ stubsCreated: number; /** Node counts broken down by type. */ byType: Record; } /** * Back-fill brain_page_nodes and brain_page_edges from all existing typed rows * in brain.db. * * Safe to run multiple times — duplicate nodes and edges are silently ignored * via INSERT OR IGNORE semantics. * * @param projectRoot - Absolute path to the project root (contains .cleo/). * @returns BackfillResult with before/after counts and insertion stats. */ export declare function backfillBrainGraph(projectRoot: string): Promise; /** * Result of a staged backfill run creation. * * A staged run does NOT commit any rows to live tables. The caller must call * `approveBackfillRun` to commit or `rollbackBackfillRun` to discard. * * @task T1003 */ export interface StagedBackfillRunResult { /** The new run record. */ run: BrainBackfillRunRow; /** * True when no rows matched the source (run was staged with rowsAffected=0). * Callers may still approve or rollback a zero-row run. */ empty: boolean; } /** * Stage a graph backfill run against brain_page_nodes / brain_page_edges. * * Discovers all candidate node IDs from typed tables (decisions, patterns, * learnings, observations, sticky notes) that are NOT yet in brain_page_nodes. * Writes the list to `rollback_snapshot_json` and creates a `brain_backfill_runs` * row with status='staged'. No rows are inserted into brain tables. * * Pass `source` as a human-readable descriptor (e.g. a file path or session ID). * Pass `kind` as the backfill kind (e.g. 'graph-backfill', 'observation-promotion'). * * @param projectRoot - Absolute path to the project root. * @param opts - Optional overrides for source, kind, and target table. * @returns StagedBackfillRunResult with the staged run record. * * @task T1003 */ export declare function stagedBackfillRun(projectRoot: string, opts?: { source?: string; kind?: string; targetTable?: string; }): Promise; /** * Approve a staged backfill run, committing its rows to live brain tables. * * Reads the run record, validates that it is in 'staged' status, then triggers * `backfillBrainGraph` to perform the actual INSERT OR IGNORE work. Finally, * updates the run row to status='approved' with the current timestamp. * * Double-approve is idempotent: returns `{ alreadySettled: true }` if the run * is already approved or rolled-back. * * @param projectRoot - Absolute path to the project root. * @param runId - The brain_backfill_runs.id to approve. * @param approvedBy - Optional identity of the approver (defaults to 'owner'). * @returns Result with the updated run record and graph backfill stats. * * @task T1003 */ export declare function approveBackfillRun(projectRoot: string, runId: string, approvedBy?: string): Promise<{ run: BrainBackfillRunRow; alreadySettled: boolean; backfillResult?: BrainBackfillResult; }>; /** * Rollback a staged backfill run, discarding staged rows. * * If the run is still 'staged', marks it as 'rolled-back' (no rows were ever * committed, so no DELETE is required). * * If the run is 'approved', reads `rollback_snapshot_json` and DELETEs the * committed rows from the target table, then marks the run as 'rolled-back'. * * Idempotent: rolling back an already-rolled-back run returns * `{ alreadySettled: true }` without error. * * @param projectRoot - Absolute path to the project root. * @param runId - The brain_backfill_runs.id to roll back. * @returns Result with the updated run record and optional delete count. * * @task T1003 */ export declare function rollbackBackfillRun(projectRoot: string, runId: string): Promise<{ run: BrainBackfillRunRow; alreadySettled: boolean; deletedRows: number; }>; /** * List backfill runs, optionally filtered by status. * * @param projectRoot - Absolute path to the project root. * @param opts - Optional status filter and limit. * @returns Array of run records, ordered by created_at DESC. * * @task T1003 */ export declare function listBackfillRuns(projectRoot: string, opts?: { status?: string; limit?: number; }): Promise; //# sourceMappingURL=brain-backfill.d.ts.map