/** * SQLite store for the project-scope CONDUIT domain — agent-to-agent messaging, * delivery queue, attachments, A2A topics, and per-project agent refs. * * ## E6-L3 — thin-facade migration (T11523) * * `ensureConduitDb()` is now a thin facade that delegates the database open to * {@link openDualScopeDb}('project', cwd) — the canonical dual-scope chokepoint * introduced by E3/E4 (T11512/T11517) and already adopted by the tasks domain * (E6-L1, T11521) and brain domain (E6-L2, T11522). This ensures: * * - Every conduit-domain open flows through the single pragma SSoT (ADR-068/069). * - The conduit tables now live inside the consolidated project `cleo.db` — NOT a * separate `conduit.db` file — co-existing with `tasks_*` / `brain_*` / etc. * - DB Open Guard Gate 3 (`scripts/lint-no-direct-db-open.mjs`) stays green: the * only native open is inside `dual-scope-db.ts`. * * ## COMPLETE-CUTOVER to prefixed `conduit_*` tables (T11578 · AC4) * * The conduit runtime READ + WRITE path now targets the PREFIXED consolidated * tables (`conduit_conversations`, `conduit_messages`, `conduit_topics`, …) that * the consolidated cleo-project migration creates — NOT the legacy BARE tables * (`conversations`, `messages`, …). The schema barrel imported below is therefore * `schema/cleo-project/conduit.ts` (the prefixed target shape, TEXT ISO-8601 * timestamps + CHECK constraints), replacing the legacy `schema/conduit-schema.ts` * bare shape. The drizzle journal `runConduitMigrations` reconciles now only needs * the FTS5 quartet that the consolidated migration omits (drizzle-orm sqlite-core * does not model FTS5 virtual tables). * * ## Inline DDL → forward migration (T11523 → T11578) * * The legacy 16-table inline `CONDUIT_SCHEMA_SQL` blob was first converted to a * forward Drizzle migration under * `migrations/drizzle-conduit/20260601000003_t11523-conduit-inline-schema` * (T11523, bare runtime shape). The AC4 cutover (T11578) rewrote that migration to * carry ONLY the `conduit_messages_fts` FTS5 virtual table + its 3 sync triggers * (`conduit_messages_ai/ad/au`) + the two legacy `_conduit_meta` / * `_conduit_migrations` health-probe tables. The 14 prefixed `conduit_*` tables * are owned by the consolidated cleo-project migration (single SSoT) — this * migration no longer creates them. * * ## Single physical shape (consolidated owns the tables) * * After AC4 the runtime writes the SAME prefixed `conduit_*` tables the * consolidated schema (`cleo-project/conduit.ts`) declares — there is no longer a * disjoint bare runtime shape. The exodus migration (T11248 / T11553) still * renames any LEGACY bare data (`messages` → `conduit_messages`) from a * pre-cutover DB into those same prefixed tables; the FTS index is rebuilt * post-migration from `conduit_messages` (exodus skips `*_fts` tables). * * Architecture (ADR-037): * conduit (this module) — project-scoped — messaging, delivery, attachments, * project_agent_refs * signaldock.db — global-scoped (T346) — agents, capabilities, cloud-sync tables * * @task T344 * @task T1407 * @task T11523 - E6-L3: route ensureConduitDb through openDualScopeDb (SG-DB-SUBSTRATE-V2) * @epic T310 * @epic T11249 * @why ADR-037 splits single signaldock.db into project-tier conduit * (this module) and global-tier signaldock.db (T346). T1407 unifies * conduit under the canonical Drizzle migration runner; T11523 routes it * through the consolidated `cleo.db` dual-scope chokepoint. * @what Path helper, database initializer (dual-scope facade), Drizzle migration * runner wiring, health check, native DB accessor, and project_agent_refs * CRUD accessors. */ import type { DatabaseSync as _DatabaseSyncType } from 'node:sqlite'; import type { ProjectAgentRef } from '@cleocode/contracts'; type DatabaseSync = _DatabaseSyncType; declare const DatabaseSync: new (path: import("fs").PathLike, options?: import("node:sqlite").DatabaseSyncOptions | undefined) => DatabaseSync; /** * Legacy database file name. Retained as an export for backwards compatibility * with callers that still reference the constant; the conduit domain now lives * inside the consolidated project `cleo.db` (E6-L3, T11523). * * @deprecated The conduit domain no longer has a standalone `conduit.db` file — * it is served from the project `cleo.db`. Use {@link getConduitDbPath}. */ export declare const CONDUIT_DB_FILENAME = "conduit.db"; /** * Schema version for the conduit domain. * * Bumped only when the conduit Drizzle schema changes. Pinned at the post-T1252 * A2A topics value; retained for backwards compatibility with pre-T1407 health * checks that read `_conduit_meta.schema_version`. */ export declare const CONDUIT_SCHEMA_VERSION = "2026.4.23"; /** * Returns the project-scope conduit database path. * * ## E6-L3 (T11523) * * After the dual-scope migration, `ensureConduitDb()` opens the consolidated * project `cleo.db` via {@link openDualScopeDb} — not the legacy standalone * `conduit.db`. This function therefore returns the dual-scope `cleo.db` path so * that callers checking for the file `ensureConduitDb()` created (existence / * backup / health probes) point at the correct file. * * The supplied `projectRoot` is passed through as the `cwd` for the SSoT * resolver, which walks up to find the `.cleo/` directory. * * @task T344 * @task T11523 * @epic T310 * @param projectRoot - Absolute path to the project root directory. * @returns Absolute path to the project `cleo.db`. */ export declare function getConduitDbPath(projectRoot: string): string; /** * Resolve the absolute path to the drizzle-conduit migrations folder inside * `@cleocode/core`, using ESM-native module resolution (T1177 pattern). * * @task T1407 * @epic T310 */ export declare function resolveConduitMigrationsFolder(): string; /** * Apply the conduit-domain schema to an arbitrary open `DatabaseSync` handle by * running the `drizzle-conduit` migration set against it. * * ## E6-L3 (T11523) * * Previously this executed the inline `CONDUIT_SCHEMA_SQL` blob directly. That * blob has been moved into the forward migration * `20260601000003_t11523-conduit-inline-schema`, so this helper now reconciles * the journal and runs the conduit migrations — the same path `ensureConduitDb` * uses internally. It remains exported for the signaldock→conduit migration * executor (T358) and characterization tests that need to seed the conduit schema * onto a caller-owned handle. * * Idempotent: every migration statement uses `IF NOT EXISTS`, so applying it onto * an already-populated DB is a no-op (the journal reconciler marks it applied). * * @task T344 * @task T1407 * @task T11523 * @epic T310 * @param db - An open node:sqlite DatabaseSync instance. */ export declare function applyConduitSchema(db: DatabaseSync): void; /** * Initialize the project-scope CONDUIT domain SQLite database (lazy, singleton). * * ## E6-L3 façade (T11523) * * Delegates the physical DB open to {@link openDualScopeDb}('project', cwd) — the * canonical dual-scope chokepoint. openDualScopeDb applies the pragma SSoT, * creates the directory, runs the consolidated cleo-project migrations (which * create the prefixed `conduit_*` tables), and manages the singleton cache. We * extract its native handle (`$client`) and run the `drizzle-conduit` migration on * it to (idempotently) create the `conduit_messages_fts` FTS5 quartet that the * consolidated migration omits. After the AC4 cutover (T11578) the LocalTransport + * accessor writers query the SAME prefixed `conduit_*` tables — the exodus * migration (T11248 / T11553) renames any pre-cutover BARE data into them. * * On subsequent calls the existing singleton is returned immediately if the * resolved path matches AND the shared handle is still live (liveness guard); * otherwise it re-derives from the live dual-scope cache. * * Uses a promise guard so concurrent callers wait for the same initialization to * complete (the dual-scope open is async). * * @task T344 * @task T1407 * @task T11523 * @epic T310 * @param projectRoot - Absolute path to the project root directory. * @returns Object with `action` (`'created'` | `'exists'`) and `path`. */ export declare function ensureConduitDb(projectRoot: string): Promise<{ action: 'created' | 'exists'; path: string; }>; /** * Returns the live node:sqlite DatabaseSync handle for the conduit domain. * * Returns `null` if `ensureConduitDb` has not been called yet for this process, * or if the shared handle has been closed since the last open. * * @task T344 * @epic T310 * @returns The open DatabaseSync instance, or `null` if not initialized. */ export declare function getConduitNativeDb(): DatabaseSync | null; /** * Close the conduit-domain database connection and reset the module singleton. * * ## E6-L3 (T11523) * * The conduit domain now SHARES the consolidated project `cleo.db` handle with * the tasks + brain domains (all open it via {@link openDualScopeDb}, same cache * key). This function therefore must NOT close the underlying `DatabaseSync` nor * evict the dual-scope cache — doing so would break in-flight tasks/brain-domain * queries with "database is not open". It only drops the conduit-domain singleton * references; the shared handle's lifecycle is owned by `openDualScopeDb` and torn * down by a coordinated reset (`closeAllDatabases` → `_resetDualScopeDbCache`). * * Safe to call multiple times. * * @task T344 * @task T11523 * @epic T310 */ export declare function closeConduitDb(): void; /** * Reset conduit-domain singleton state without saving. * * Used during tests or when the shared database handle is recreated. Drops only * the conduit-domain singleton references — does NOT close the shared dual-scope * `cleo.db` handle nor evict the dual-scope cache (that handle is shared with the * tasks + brain domains). Mirrors {@link closeConduitDb}. Safe to call multiple * times. * * @task T11523 * @epic T310 */ export declare function resetConduitDbState(): void; /** * Attaches an agent to the current project. If a row exists with enabled=0, * re-enables it (update attached_at timestamp). If a row exists with enabled=1, * no-op. Inserts a new row otherwise. * * @param db - conduit handle (from ensureConduitDb). * @param agentId - Global signaldock.db:agents.id (soft FK, not validated here). * @param opts - Optional role and capabilities override. * @task T353 * @epic T310 */ export declare function attachAgentToProject(db: DatabaseSync, agentId: string, opts?: { role?: string | null; capabilitiesOverride?: string | null; }): void; /** * Detaches an agent from the current project by setting enabled=0. * Does NOT delete the row (preserves attachment history for audit). * * @param db - conduit handle (from ensureConduitDb). * @param agentId - Agent ID to detach. * @task T353 * @epic T310 */ export declare function detachAgentFromProject(db: DatabaseSync, agentId: string): void; /** * Lists project_agent_refs rows. By default returns only enabled=1 rows. * Pass enabledOnly=false to return all rows regardless of enabled state. * * @param db - conduit handle (from ensureConduitDb). * @param opts - Filter options. Defaults to `{ enabledOnly: true }`. * @returns Array of ProjectAgentRef rows ordered by attached_at DESC. * @task T353 * @epic T310 */ export declare function listProjectAgentRefs(db: DatabaseSync, opts?: { enabledOnly?: boolean; }): ProjectAgentRef[]; /** * Returns a single project_agent_refs row by agentId, or null if not found. * * @param db - conduit handle (from ensureConduitDb). * @param agentId - Agent ID to look up. * @returns The ProjectAgentRef row, or null if the agent is not attached. * @task T353 * @epic T310 */ export declare function getProjectAgentRef(db: DatabaseSync, agentId: string): ProjectAgentRef | null; /** * Updates the last_used_at timestamp for an agent to now. * No-op if the agent_id does not exist in project_agent_refs. * * @param db - conduit handle (from ensureConduitDb). * @param agentId - Agent ID to update. * @task T353 * @epic T310 */ export declare function updateProjectAgentLastUsed(db: DatabaseSync, agentId: string): void; /** * Checks conduit-domain health — table count, WAL mode, schema version, and * foreign keys status. * * ## E6-L3 (T11523) * * The conduit domain now lives in the consolidated project `cleo.db`. This probe * opens that file (read-only inspection of pragma + sqlite_master state) — it does * NOT require `ensureConduitDb` to have been called and opens/closes its own * short-lived connection. Used by `cleo doctor` to verify conduit integrity. * * @task T344 * @task T11523 * @epic T310 * @param projectRoot - Absolute path to the project root directory. * @returns Health report object. `exists: false` when the DB is absent. */ export declare function checkConduitDbHealth(projectRoot: string): { exists: boolean; path: string; tableCount: number; walMode: boolean; schemaVersion: string | null; foreignKeysEnabled: boolean; }; /** * Open a fresh (non-singleton) connection to the conduit-domain DB with pragmas * applied. * * ## E6-L3 (T11523) * * The conduit domain now lives in the consolidated project `cleo.db`. This opens * an independent connection to that file (WAL mode permits concurrent * connections) that the caller owns and must close. Intended for callers that * manage connection lifecycle explicitly (e.g. LocalTransport connect/disconnect * cycle). The caller is responsible for ensuring `ensureConduitDb` has run first * so the bare conduit tables exist. * * Applies the pragma SSoT from `specs/sqlite-pragmas.json` (T9047, T9189). * * @param projectRoot - Project root for resolving the conduit DB path. * @returns An open DatabaseSync connection (caller must close). * @task T9189 * @task T11523 */ export declare function openFreshConduitDb(projectRoot: string): DatabaseSync; export {}; //# sourceMappingURL=conduit-sqlite.d.ts.map