/** * Drizzle ORM schema for the **self-improvement DHQ** table (`selfimprove_dhq`), * the durable sink for the P5 self-improvement loop (T11889 · T11889-A · T11911). * * One row per Dogfood-Harness-Question (DHQ) emitted by `cleo selfimprove run`: * the loop replays a canned dogfood scenario, diffs the resulting LAFS envelopes * against a golden, and — on regression — UPSERTs exactly ONE row here through the * leased Gate-3 accessor ({@link ./selfimprove-dhq-store.ts}). On green it writes * nothing. The table is dual-scope: co-located inside EACH scope's consolidated * `cleo.db` (project + global) via the `drizzle-cleo-project` / `drizzle-cleo-global` * migration sets, exactly like the `_writer_leases` (T11627) and `pi_session_*` * (T11899) runtime-infrastructure tables. It is NOT part of the exodus target shape * under `schema/cleo-project/`. * * ## Idempotency invariant — at most ONE open DHQ per `question_hash` * * A repeated regression must UPSERT the SAME open row rather than spam N duplicates. * This is enforced by the **partial UNIQUE index** * `ux_selfimprove_dhq_open ON selfimprove_dhq (question_hash) WHERE status = 'open'`. * drizzle-orm does **not** surface partial-`WHERE` indexes in its typed schema API * (cf. `writer-lease-schema.ts` `_writer_leases.active`, `conduit-schema.ts` * `project_agent_refs.enabled`), so the partial index is emitted as **raw SQL in the * baseline migration** — this module declares only the full-column table plus the two * non-partial indexes drizzle CAN model. The runtime bootstrap asserts the partial * index exists via {@link assertSelfimproveDhqOpenIndexPresent} so a missing index * (a migration that never ran, or a dropped index) fails loudly instead of silently * permitting two open rows for the same `question_hash`. * * @module * @task T11911 * @task T11889 * @epic T11889 * @see ./selfimprove-dhq-store.ts — the Gate-3 accessor over these tables * @see ./writer-lease-schema.ts — the partial-UNIQUE-index-via-raw-SQL precedent * @see ../../migrations/drizzle-cleo-project — project migration (raw partial index) * @see ../../migrations/drizzle-cleo-global — global migration (raw partial index) */ import type { DatabaseSync } from 'node:sqlite'; /** * The physical name of the self-improvement DHQ table. Exported so the engine, the * store accessor, the bootstrap assertion, and tests all reference one source of * truth. */ export declare const SELFIMPROVE_DHQ_TABLE: "selfimprove_dhq"; /** * The physical name of the partial-UNIQUE active-row index (`WHERE status = 'open'`). * Asserted present at bootstrap because drizzle cannot emit it — it lives as raw SQL * in the baseline migration. */ export declare const SELFIMPROVE_DHQ_OPEN_INDEX: "ux_selfimprove_dhq_open"; /** * `selfimprove_dhq` — one row per self-improvement-loop DHQ. * * The at-most-one-open-per-`question_hash` invariant is enforced by the raw-SQL * partial-UNIQUE index `ux_selfimprove_dhq_open ON selfimprove_dhq (question_hash) * WHERE status = 'open'` (emitted in the baseline migration — drizzle cannot model * partial `WHERE`). This declaration intentionally carries only the full-column * table plus the two non-partial indexes; do NOT add a `.unique()` on * `question_hash` here (it would emit a NON-partial unique that wrongly forbids a * second non-open row for the same hash). */ export declare const selfimproveDhq: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{ name: "selfimprove_dhq"; schema: undefined; columns: { id: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "number int53"; data: number; driverParam: number; notNull: true; hasDefault: true; isPrimaryKey: true; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; dhqId: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; scenario: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; questionHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; title: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; regressionJson: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; status: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: true; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; severity: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: false; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; prUrl: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: false; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; runId: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "string"; data: string; driverParam: string; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: [string, ...string[]]; baseColumn: never; identity: undefined; generated: undefined; }, {}>; createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "number int53"; data: number; driverParam: number; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{ name: string; tableName: "selfimprove_dhq"; dataType: "number int53"; data: number; driverParam: number; notNull: true; hasDefault: false; isPrimaryKey: false; isAutoincrement: false; hasRuntimeDefault: false; enumValues: undefined; baseColumn: never; identity: undefined; generated: undefined; }, {}>; }; dialect: "sqlite"; }>; /** * Assert that the raw-SQL partial-UNIQUE open-row index is physically present on the * given native `cleo.db` handle. * * Because drizzle cannot emit a partial-`WHERE` index, the at-most-one-open-DHQ * invariant depends entirely on the hand-written baseline migration having run. This * check makes a missing index a loud, immediate failure at bootstrap rather than a * silent loss of the idempotency guarantee (which would let the loop spam duplicate * open rows). * * @param nativeDb - The native `DatabaseSync` handle for a scope's `cleo.db`. * @throws {Error} `E_SELFIMPROVE_DHQ_INDEX_MISSING` if `ux_selfimprove_dhq_open` is * absent (the migration did not run, or the partial index was dropped). * * @example * ```ts * const nativeDb = (handle.db as { $client: DatabaseSync }).$client; * assertSelfimproveDhqOpenIndexPresent(nativeDb); // throws if the index is missing * ``` * * @task T11911 */ export declare function assertSelfimproveDhqOpenIndexPresent(nativeDb: DatabaseSync): void; //# sourceMappingURL=selfimprove-dhq-schema.d.ts.map