Skip to content

refactor(T11523): route conduit-sqlite.ts through openDualScopeDb + DDL→Drizzle migration (E6-L3)#900

Merged
kryptobaseddev merged 5 commits into
mainfrom
task/T11523-e6-conduit
Jun 1, 2026
Merged

refactor(T11523): route conduit-sqlite.ts through openDualScopeDb + DDL→Drizzle migration (E6-L3)#900
kryptobaseddev merged 5 commits into
mainfrom
task/T11523-e6-conduit

Conversation

@kryptobaseddev
Copy link
Copy Markdown
Owner

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 the conduit_ prefix (conduit_conversations, …). Disjoint names → legacy + consolidated co-exist harmlessly in the same cleo.db. No drop/rebuild needed (unlike brain L2, which shared prefixed names).

Changes

  • ensureConduitDb()async, delegates open to openDualScopeDb('project', cwd), extracts $client native handle, runs the legacy drizzle-conduit migration set on it.
  • getConduitDbPath()resolveDualScopeDbPath('project') (.cleo/cleo.db).
  • Deleted the 16-table inline CONDUIT_SCHEMA_SQL blob (21 CREATE TABLE/index/FTS5/trigger statements) → converted to forward Drizzle migration migrations/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 ensureConduitDb at all callers (init, upgrade, open-cleo-db, sqlite-backup, role-accessors).
  • createProjectAgent + AgentRegistryAccessor.ensureDbs → async; migrateSignaldockToConduit → async; needsSignaldockToConduitMigration probes the consolidated cleo.db path so the one-shot legacy path can't perpetually re-fire.
  • project-health.ts: CONDUIT_DBcleo.db; removed the [CONDUIT_DB] expected-version entry (same key as [TASKS_DB], would clobber the floor of 3).
  • LocalTransport.isAvailable(): catch resolveCleoDir E_NO_PROJECT → return false (preserves "false when missing" contract).

Validation

  • pnpm run typecheck ✅ clean
  • cleo check arch ✅ 5/5 gates pass (Gate 2 DB-open-guard green — only dual-scope-db.ts opens native handles)
  • node build.mjs ✅ + cleo version smoke ✅
  • Dedicated conduit tests (conduit-sqlite, conduit-idempotency, migrate-signaldock, agent-registry-accessor, local-transport, local-credential-flow, a2a-topic, messaging-e2e) all pass in isolation.

🤖 Generated with Claude Code

kryptobaseddev and others added 5 commits June 1, 2026 02:44
…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 kryptobaseddev merged commit 8dcffd8 into main Jun 1, 2026
68 checks passed
@kryptobaseddev kryptobaseddev deleted the task/T11523-e6-conduit branch June 1, 2026 10:54
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant