/** * Deterministic legacy-to-consolidated table-name resolver for exodus migration. * * ## Problem (ROOT CAUSE 1 — T11532) * * Legacy source DBs use UNPREFIXED table names (`tasks`, `messages`, `skills`, …) * while the consolidated dual-scope `cleo.db` uses DOMAIN-PREFIXED names * (`tasks_tasks`, `conduit_messages`, `skills_skills`, …). Without a mapping, * every `INSERT OR IGNORE INTO main.""` silently copies 0 rows because the * target table is absent under the legacy name. * * ## Design * * The mapping is a static lookup table derived from reading every * `cleo-project/` and `cleo-global/` schema file and matching the physical * `sqliteTable('', …)` names against each legacy DB's schema. * * Rules: * - If a legacy table is already domain-prefixed in the consolidated schema * (e.g. `brain_observations`, `nexus_audit_log`, `tasks_goal`), map identity. * - If a legacy table has NO consolidated counterpart (virtual tables, orphan * telemetry tables, …), return `null` so the caller can log + skip explicitly * rather than silently discarding rows. * * ## Source-DB scope * * The resolver takes a `sourceName` (the `LegacyDbDescriptor.name` value, e.g. * `"tasks"`, `"brain (project)"`, `"conduit"`) to disambiguate tables that * share the same legacy name across multiple DBs (e.g. `"attachments"` lives in * both conduit.db and attachments.ts/tasks.db; `"sessions"` lives in both * tasks.db and signaldock.db). * * ## Nexus code-graph residency move (ADR-090 · T11539) * * The four nexus code-graph tables — `nexus_nodes`, `nexus_relations`, * `nexus_contracts`, `nexus_code_index` (ADR-090 "Category A") — were removed * from the GLOBAL schema (`../schema/cleo-global/nexus.ts`) and now reside in * PROJECT scope (`../schema/cleo-project/nexus-graph.ts`). They are still * extracted from the legacy GLOBAL `nexus.db` source, but exodus MUST route them * into the PROJECT-scope consolidated `cleo.db`, not the global one. The source * descriptor `nexus` carries `targetScope: 'global'`, so a per-table scope * override is required for these four tables — see * {@link NEXUS_GRAPH_PROJECT_TABLES} and {@link resolveTableTargetScope}. The * six registry/identity tables (`nexus_project_registry`, * `nexus_project_id_aliases`, `nexus_audit_log`, `nexus_schema_meta`, * `nexus_user_profile`, `nexus_sigils`) stay GLOBAL. * * @task T11532 (ROOT CAUSE 1 — name-mapping gap) * @task T11533 (ROOT CAUSE 3 — signaldock skills mapping + brain_release_links skip + * brain_session_narrative mapping) * @task T11546 (no-home-table fixes — schema_meta→tasks_schema_meta, brain_usage_log mapping, * brain_schema_meta mapping) * @task T11539 (nexus code-graph residency — route the 4 graph tables to PROJECT scope) * @epic T11248 * @saga T11242 */ import type { ExodusScope } from './types.js'; /** * Legacy table names of the four nexus code-graph tables that moved from GLOBAL * to PROJECT scope (ADR-090 · T11538/T11539). * * Keyed by the LEGACY physical name as it appears in `nexus.db`: * - `nexus_nodes`, `nexus_relations`, `nexus_contracts` — already prefixed. * - `code_index` — bare in legacy `nexus.db`; → `nexus_code_index` consolidated. * * Membership drives {@link resolveTableTargetScope}: exodus copies/verifies * these against the PROJECT consolidated `cleo.db`, NOT the GLOBAL one, even * though the `nexus` source descriptor's `targetScope` is `'global'`. * * @task T11539 * @epic T11248 * @saga T11242 * @see cleo docs fetch adr-090-nexus-graph-residency-split */ export declare const NEXUS_GRAPH_PROJECT_TABLES: ReadonlySet; /** * Resolve the consolidated TARGET SCOPE for a legacy source table. * * Most tables share the scope of their source DB descriptor (`sourceScope`). * The exception is the four nexus code-graph tables — they are extracted from * the GLOBAL legacy `nexus.db` but land in PROJECT scope per ADR-090 (T11539). * * This is the SSoT consumed by BOTH the exodus migrate runner (insert target DB) * and the exodus verifier (verify target DB) so the two never disagree. * * @param sourceName - `LegacyDbDescriptor.name` (e.g. `"nexus"`, `"tasks"`). * @param legacyTable - Physical table name in the legacy source DB. * @param sourceScope - The source descriptor's `targetScope`. * @returns The scope of the consolidated `cleo.db` this table copies into. * * @task T11539 * @epic T11248 * @saga T11242 */ export declare function resolveTableTargetScope(sourceName: string, legacyTable: string, sourceScope: ExodusScope): ExodusScope; /** * Return `true` if `tableName` is a DERIVED or INTERNAL table that must be * EXCLUDED from the exodus row-count-parity gate (and from the copy path). * * This is the single, named, documented classification consumed by BOTH the * migrate copy loop and the `verifyMigration` parity check, so the two never * disagree about which tables carry migratable user data. It recognises: * * 1. **FTS5 virtual tables** — a bare `*_fts` name (e.g. `brain_decisions_fts`, * `messages_fts`). The virtual table itself cannot be `INSERT … SELECT`-ed * and is rebuilt from its content table after migration. * 2. **FTS5 shadow/backing tables** — `*_fts_data`, `*_fts_idx`, * `*_fts_docsize`, `*_fts_config`, `*_fts_content` (see * {@link FTS5_SHADOW_SUFFIXES}). Derived; rebuilt post-migration. * 3. **Internal bookkeeping** — any per-source schema-version / migration * ledger: `_conduit_meta`, `_conduit_migrations`, `_signaldock_meta`, * `_signaldock_migrations`, `_skills_meta`, and — generalised via * {@link INTERNAL_LEDGER_PATTERN} — ANY `__meta` / * `__migrations` ledger from a future source DB (see * {@link INTERNAL_BOOKKEEPING_TABLES}). Schema-version ledgers with no * consolidated home. * * A migration is "safe" iff every BASE-DATA row survives; these derived/internal * tables are NOT base data, so a 0-row consolidated counterpart for them is * expected and correct — not data loss. * * @param tableName - Physical table name from a legacy source DB. * @returns `true` when the table is derived/internal and must be skipped. * * @task T11572 (exodus parity gate: exclude FTS5 + internal/meta shadow tables) * @task T11577 (generalise internal-ledger skip to signaldock/skills + any per-source ledger) * @epic T11249 (E6) * @saga T11242 */ export declare function isDerivedOrInternalTable(tableName: string): boolean; /** * Result of resolving a legacy table name to its consolidated target. * * `kind === 'mapped'` — `targetName` holds the consolidated physical name. * `kind === 'skip'` — table is intentionally excluded (virtual, orphan, etc.); * `reason` holds a human-readable explanation. * `kind === 'unknown'` — source DB is unrecognized; falls back to identity copy * (best-effort for forward-compatibility with future DBs). */ export type TableNameResolution = { readonly kind: 'mapped'; readonly targetName: string; } | { readonly kind: 'skip'; readonly reason: string; } | { readonly kind: 'unknown'; readonly targetName: string; }; /** * Resolve the consolidated target table name for a legacy source table. * * @param sourceName - `LegacyDbDescriptor.name` (e.g. `"tasks"`, `"brain (project)"`). * @param legacyTable - Physical table name from the legacy source DB. * @returns A `TableNameResolution` describing how to copy (or skip) the table. */ export declare function resolveConsolidatedTableName(sourceName: string, legacyTable: string): TableNameResolution; /** * Reverse-lookup: given a consolidated target table name, return the set of * legacy (sourceName, legacyTableName) pairs that map to it. * * Used by `runExodusVerify()` to compare legacy source counts against the * correct consolidated target table rather than the legacy table name. * * Returns an empty array if no legacy table maps to the given consolidated name. */ export declare function reverseLookup(consolidatedTable: string, sources: ReadonlyArray<{ readonly name: string; }>): Array<{ sourceName: string; legacyTable: string; }>; //# sourceMappingURL=table-name-map.d.ts.map