chore(database): stop declaring the dead tables and columns, ahead of the migration that drops them (cleanup round 2, 1/2)
Summary
Cleanup round 2, step 2, PR 1 of 2 (Dean approved: do #2). The expand/contract half that stops naming the dead tables and columns. The drop migration follows in PR 2 once this is live in production.
Nothing in the code reads or writes these, and the README already said so. No schema module declares them now, so no Drizzle insert names them, and the drift check (apps/web/tests/drizzle-schema.test.ts) lists them as waiting on their drop:
- Tables (new
PENDING_DROP_TABLES, same terms asPENDING_DROP, held by a test that fails once one is gone):events,provider_cursors,provider_key,roster_snapshot,transcript_mark,observation_pass,workspace_file,workspace_embedding,devices,account_workspace_preference,introduction_usage. Theschemas/{devices,roster,vault,workspace}.tsmodules and their package exports go. provider_keyis NOT the BYOK table. BYOK keys live inaccount_provider_key(migration0080_account_provider_key,schemas/account-provider-key.ts,models/provider-key-store.ts), which this PR doesn't touch.provider_keyis the earlier vault table (schemas/vault.ts). No code imports itsproviderKeydeclaration, and production holds 9 rows.- Columns (
PENDING_DROP):account_preference.default_workspace_provider- on
conversations:- the observed-session columns
provider_id,provider_session_id,workspace spawned_by_message_idandcompletion_delivered_at(0 non-null rows in production)next_event_seq, which numbered theeventsrows- the three
memory_flush_*columns ("nothing writes the column now")
- the observed-session columns
- The indexes over them (
conversations_observed_session,conversations_undelivered_children) go with the columns in PR 2.
- Kept, because they're live: a child conversation's
parent_conversation_id,label,title, andexpects_completion.brain-host/conversation.ts'sopenChildConversationwrites them for every subagent and coding-agent worker (38 child rows in production), andchild-titles.tsandcoding-agent-store.tsreadtitle. drizzle.__drizzle_migrations:core/migrator.ts's one-timebootstrapFromDrizzleHistory(andDRIZZLE_MIGRATIONS_TABLE) goes, along with its two tests. Every database the deployments migrate already records its history ineffect_sql_migrations(101 rows in production, and every Neon preview branches from production). The table itself is dropped in PR 2.@sidecar/wire'sCONVERSATION_EVENT_KINDtyped only theeventscolumn, so it goes.RATING_WORDstays. knip then flaggedschemas/_helpers.ts'stimestampsand the test helperinstantColumnas unused, so they go too.- Migration
20261013120444_dead_tables_pending_dropis the onepnpm db:generatewrote, with its statements emptied out, perapps/web/server/README.md's two-deployment rule. Its snapshot already records the shape after the drop, soschemas/__tests__/migrations.test.tsstays green, and applying it changes nothing.
Production row counts PR 2 will drop: events 2155, provider_cursors 403, provider_key 9, roster_snapshot 3, transcript_mark 3, observation_pass 3, workspace_file 65, workspace_embedding 380, devices 22, account_workspace_preference 3, introduction_usage 31, drizzle.__drizzle_migrations 22; and 3 non-null default_workspace_provider values, 969/969/479 provider_id/provider_session_id/workspace values on the observed conversation rows (the rows themselves stay).
Tests
-
New
apps/web/tests/dead-tables-dropped.test.tsmakes PR 2's drop on its own database (every dead table and column gone) and then runs the store paths that write beside them or cascade through them. Each one still answers:- account preferences and the plan template
- a plan and its conversation
- a child conversation and its title
- the account's deletion
It fails without this PR's schema change (
column "default_workspace_provider" of relation "account_preference" does not exist), which is the release-overlap window it guards. -
Deleted, because they held only the dead shape, with no behavior test left to cover them:
storage-schema.test.ts's event-ledger and claim tests, the observed-session uniqueness test, the provider-cursor test, and the completion-sweep index row;voice-schema.test.ts's device-departure test (voice_sessions.device_idhas no foreign key);effect-migrator.test.ts's two bootstrap tests. -
grep: no production source names any dropped table or column.
tscoverapps/webafter removing the declarations only flagged test files.
Evidence
- Platform-independent checks:
./scripts/check.shlocally: knip, discarded-effect, typecheck, and tests (1132 + shards) passed; lint first failed on biome formatting of the new test and snapshot, fixed, andpnpm lintthen exits 0. CI runs the whole check plus the Postgres migrations and store job - macOS Electron verification (
./scripts/verify.sh):not run. No Mac or UI change, and this is a Linux VM; CI cannot verify the Mac (LUKE-159 is the manual Mac pass)
Invariants
-
./scripts/check.shgreen. No renderer/UI change. - JSON Schema goldens unchanged.
- The behavior change (no insert names a dropped column) has the post-drop store test that fails without it; no change-detector test added.
- Gateway envelope goldens unchanged.
- No new
astype assertion. - No
Effect.runPromise/runSync/runForkadded. - No raw async primitive added.
- No discarded Effect.
- Test count delta listed above (tests removed with the dead tables; one store test added).
- No hand-rolled file replaced.
-
apps/web/server/README.md's migration-runner paragraph and dead-tables paragraph are edited; rootAGENTS.md/CLAUDE.mduntouched. -
PRIVACY.mdunchanged. - Package deps unchanged;
@sidecar/databasedrops four schema subpath exports. - Barrel/door rule untouched.
Notes
- PR 2 (the drop): once this is live in production, take a Neon snapshot, re-verify against the live release, then write a
--custommigration ofDROP TABLE IF EXISTS ⦠CASCADE/DROP COLUMN IF EXISTS/DROP TABLE IF EXISTS drizzle.__drizzle_migrations, empty the two pending-drop lists, delete this PR's post-drop test, and dropeventsfromstore-writer-boundary.test.ts's guard. - Also dead and left alone (not on the approved list):
voice_sessions.device_id("nothing writes it any more").
š¤ Generated with Claude Code