refactor(T11523): route conduit-sqlite.ts through openDualScopeDb + DDL→Drizzle migration (E6-L3)#900
Merged
Merged
Conversation
…DL→Drizzle migration (E6-L3)
- ensureConduitDb() now async, delegates open to openDualScopeDb('project') facade
(mirrors L1/L2); extracts $client native handle, runs legacy drizzle-conduit set
- getConduitDbPath() -> resolveDualScopeDbPath('project') (.cleo/cleo.db)
- delete 16-table inline CONDUIT_SCHEMA_SQL; move to forward migration
drizzle-conduit/20260601000003_t11523-conduit-inline-schema (verbatim, IF NOT EXISTS)
- conduit legacy names are BARE (conversations/messages/...) vs consolidated conduit_*
-> DISJOINT, co-exist like tasks; SIMPLE facade, no drop/rebuild (unlike brain L2)
- closeConduitDb/resetConduitDbState: shared-handle safety + liveness guard
- await ensureConduitDb at all callers (init/upgrade/open-cleo-db/sqlite-backup)
- createProjectAgent + AgentRegistryAccessor.ensureDbs -> async (await both ensures)
- migrateSignaldockToConduit -> async; needsSignaldockToConduitMigration probes
consolidated cleo.db path so the one-shot legacy path can't perpetually re-fire
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…leo.db (E6-L3) - conduit-sqlite.test.ts: await async ensureConduitDb; assert cleo.db path + arrayContaining(legacy bare tables); reset dual-scope cache per case; assert E6-L3 forward-migration journal row - conduit-idempotency.test.ts: await + async it() callbacks + .cleo dir setup - migrate-signaldock-to-conduit.test.ts: mock resolveCleoDir; conduit.db->cleo.db file assertions; await async migrate - agent-registry-accessor.test.ts: add resolveCleoDir to all 17 paths mocks; openConduit->cleo.db; await async createProjectAgent/ensureConduitDb; async cbs - a2a-topic/local-transport/messaging-e2e: async setupTestDb + await + async beforeEach - local-credential-flow/agent-install: await async ensureConduitDb; async it() cbs - local-transport.ts isAvailable(): catch resolveCleoDir E_NO_PROJECT -> false - project-health.ts: CONDUIT_DB -> cleo.db; drop [CONDUIT_DB] expected-version entry (same key as TASKS_DB; would clobber the floor of 3) - t310/graph-memory/lifecycle-e2e: await async conduit calls Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ackup snapshot (E6-L3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t w/ tasks/brain literal reads) (E6-L3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e shard) (E6-L3) The sole deterministic CI failure: runtime lifecycle-e2e.test.ts:41 asserted result.path contains 'conduit.db'; the conduit domain now consolidates into cleo.db. Other tests use getConduitDbPath/result.path (no hardcoded name). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kryptobaseddev
added a commit
that referenced
this pull request
Jun 1, 2026
…db (attachments_conversation_idx) — clean-build conduit/agent commands (#912) Root cause: E6-L3 (#900) routed the conduit domain into the consolidated project cleo.db, where the docs-domain bare `attachments` table already lives. The conduit forward migration's `CREATE TABLE IF NOT EXISTS attachments` silently no-opped against the docs table, then `CREATE INDEX attachments_conversation_idx ON attachments(conversation_id)` crashed with "no such column: conversation_id" — breaking `cleo agent list` and every `cleo conduit *` command on a fresh build. The migration's own "disjoint physical names" assumption was wrong: `attachments` collided with the tasks/docs domain. Fix: prefix the four conduit attachment-family tables/indexes/FKs with `conduit_` (conduit_attachments, conduit_attachment_versions, conduit_attachment_approvals, conduit_attachment_contributors) so they are physically disjoint from the docs `attachments` table — matching the consolidated cleo-project schema and the exodus rename-map target. The signaldock→conduit one-shot migration now maps legacy bare source names to the prefixed destination names (copyTableRows gains a destTableName param). - migration.sql + conduit-schema.ts: rename the 4 attachment-family tables, their indexes, unique constraints, and FK references to conduit_* names - migrate-signaldock-to-conduit.ts: PROJECT_TIER_TABLES is now {src,dest} pairs; copyTableRows accepts a destTableName - conduit-sqlite.test.ts: EXPECTED_LEGACY_TABLES updated to the prefixed names Verified: fresh-XDG_DATA_HOME `cleo agent list` + `cleo conduit status` run clean; conduit migration applies alongside a pre-existing docs `attachments` table; @cleocode/core conduit suite (181) + @cleocode/runtime (120) green; cleo check arch 5/5. Co-authored-by: kryptobaseddev <kryptobaseddev@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
E6-L3 — conduit domain → consolidated cleo.db (T11523)
Routes the conduit domain through the
openDualScopeDb('project')dual-scope chokepoint, mirroring E6-L1 (tasks, #884) and E6-L2 (brain, #899). Critical sequential-path leaf 3.Same-name vs differ-prefix outcome
DIFFER-PREFIX (SIMPLE facade — like tasks, NOT like brain). Conduit legacy physical tables are BARE (
conversations,messages,delivery_jobs, …) while the consolidated schema (cleo-project/conduit.ts) carries theconduit_prefix (conduit_conversations, …). Disjoint names → legacy + consolidated co-exist harmlessly in the samecleo.db. No drop/rebuild needed (unlike brain L2, which shared prefixed names).Changes
ensureConduitDb()→ async, delegates open toopenDualScopeDb('project', cwd), extracts$clientnative handle, runs the legacydrizzle-conduitmigration set on it.getConduitDbPath()→resolveDualScopeDbPath('project')(.cleo/cleo.db).CONDUIT_SCHEMA_SQLblob (21CREATE TABLE/index/FTS5/trigger statements) → converted to forward Drizzle migrationmigrations/drizzle-conduit/20260601000003_t11523-conduit-inline-schema/migration.sql(verbatim,IF NOT EXISTS,--> statement-breakpoint).closeConduitDb/resetConduitDbState: shared-handle safety (do NOT close the co-owned dual-scope handle) + liveness guard (re-derive singleton if another domain closed the shared handle).await ensureConduitDbat all callers (init, upgrade, open-cleo-db, sqlite-backup, role-accessors).createProjectAgent+AgentRegistryAccessor.ensureDbs→ async;migrateSignaldockToConduit→ async;needsSignaldockToConduitMigrationprobes the consolidatedcleo.dbpath so the one-shot legacy path can't perpetually re-fire.project-health.ts:CONDUIT_DB→cleo.db; removed the[CONDUIT_DB]expected-version entry (same key as[TASKS_DB], would clobber the floor of 3).LocalTransport.isAvailable(): catchresolveCleoDirE_NO_PROJECT → return false (preserves "false when missing" contract).Validation
pnpm run typecheck✅ cleancleo check arch✅ 5/5 gates pass (Gate 2 DB-open-guard green — onlydual-scope-db.tsopens native handles)node build.mjs✅ +cleo versionsmoke ✅🤖 Generated with Claude Code