ID-64 phase-b-execution-plan (S344 s344-id64)
ID-64 Phase B — execution plan ({64.12}+{64.13}), blast-radius CONFIRMED
Section titled “ID-64 Phase B — execution plan ({64.12}+{64.13}), blast-radius CONFIRMED”GO-GATE: do NOT supabase migration new (timestamp) or db push until parent GO that ID-107 {107.1}
content_items rename has merged to canonical (OQ oq-cbdb49056dca7ef8). Create migration files AFTER GO
so they sequence after ID-107’s rename. Staging link verified (turayklvaunphgbgscat). DDL via CLI only.
{64.12} and {64.13} are SERIAL (same content_items migration window — NEVER parallel worktrees).
Pre-push ritual (every push)
Section titled “Pre-push ritual (every push)”cat supabase/.temp/project-ref (== turayklvaunphgbgscat) → supabase migration new <name> → write SQL →
supabase db push --linked → regen supabase/types/database.types.ts → re-verify FK parity
(pg_get_constraintdef) → bun run test.
{64.12} — drop 5 AI-telemetry token columns + rewrite item-provenance consumer
Section titled “{64.12} — drop 5 AI-telemetry token columns + rewrite item-provenance consumer”Columns (content_items): classification_tokens_in, classification_tokens_out, classification_cache_creation_tokens, classification_cache_read_tokens, embedding_tokens. KEEP classification_model + embedding_model. CONFIRMED: 0 writers anywhere (incl. flow.py); sole reader item-provenance.ts. Risk LOW (getItemProvenance has ONE caller — provenance API route).
Code rewrite lib/provenance/item-provenance.ts (MORE than a SELECT trim):
- SELECT list 129-134 → remove the 5 token cols (keep classification_model:148, embedding_model:156).
- DELETE
import { estimateClassifyCost, estimateEmbedCost } from './pricing'(line 13). - DELETE cost-estimation block 164-179 (its only inputs are the dropped cols).
- Remove
ItemProvenanceResponse.processingtoken fields 54-60 + response mapping 280-284. Tests:__tests__/lib/provenance/item-provenance.test.ts(token fixtures 74-79,114-119 + processing.* assertions);__tests__/migrations/classification-disputes-rls.test.ts(column lists 328-333, 353-357);__tests__/components/reader/source-metadata.test.tsx(token fixtures 595-596). Migration SQL:ALTER TABLE content_items DROP COLUMN classification_tokens_in, DROP COLUMN classification_tokens_out, DROP COLUMN classification_cache_creation_tokens, DROP COLUMN classification_cache_read_tokens, DROP COLUMN embedding_tokens;testStrategy: provenance API/UI tests green; ast-dataflow column-reads = 0 remaining refs to the 5 cols.
{64.13} — drop 4 orphan columns (+ pre-drop FKs/index) + reader rewrites
Section titled “{64.13} — drop 4 orphan columns (+ pre-drop FKs/index) + reader rewrites”Columns (content_items): notes, parent_id, source_bid, source_document. PRE-DROP FIRST (exact defs from staging pg_constraint):
content_items_parent_id_fkeyFOREIGN KEY (parent_id) REFERENCES content_items(id) ON DELETE SET NULL (self-FK, re-added 20260601180102:22-23)content_items_source_bid_fkeyFOREIGN KEY (source_bid) REFERENCES workspaces(id) ON DELETE SET NULL- index
idx_content_items_source_bid(explicit DROP INDEX; auto-dropped with col but be explicit) notes / parent_id = 0 reader / 0 writer (CONFIRMED — all .notes and parent_id grep hits are OTHER tables, esp. source_documents.parent_id — do NOT touch source_documents_parent_id_fkey). source_bid = 0 reader/writer (only TYPE decls: item-detail-client.tsx:62, types/content.ts:215).
source_document rewrites → source_file ?? source_url (values migrated by 20260428131822). Reader sites:
- components/content/content-library-result.tsx:50 (drop trailing
?? result.source_document) - components/content/content-library-drawer.tsx:151 (drop trailing term)
- components/content/content-row.tsx:199,205 →
item.source_file ?? item.source_url - components/content/content-card.tsx:453 →
item.source_file ?? item.source_url - components/item-detail/reader-view.tsx:204,208 →
source_file ?? source_url - components/item-detail/item-title-section.tsx:60,64 →
source_file ?? source_urlType decls to remove: types/content.ts:32 (source_document?), app/item/[id]/item-detail-client.tsx:61. DO NOT TOUCH (not the column): lib/validation/schemas.ts:1688,2565 (metadata.source_document Zod); lib/mcp/tools/content.ts:335 (legacy MCP arg); review-filters / review/queueby_source_document(joins source_documents TABLE). Tests (source_document fixtures / display assertions): tests/app/library/library-content.test.tsx:229, tests/app/browse/browse-verification-names.test.tsx:52,78,104, content-row/content-card/content-library-drawer component tests, item-title-section + reader-view tests. (mcp/create_content_item.test.ts:209-210 is metadata, likely unaffected — verify.) Migration SQL: drop the 2 FKs + index, thenALTER TABLE content_items DROP COLUMN notes, DROP COLUMN parent_id, DROP COLUMN source_bid, DROP COLUMN source_document;testStrategy: build + display-surface tests green; ast-dataflow = 0 reads of the 4 dropped cols.
Code-intel note
Section titled “Code-intel note”gitnexus_impact(getItemProvenance) returned “Target not found” (symbol unindexed/stale) — NOT a risk signal;
manual blast radius = LOW (single caller). Executor should re-confirm via grep -rn getItemProvenance app/.
ast-dataflow column-WRITES is unreliable here (returns identical 22-file indirect list for all 9 cols) — all
write claims validated by literal source grep, not ast-dataflow writes.
Dispatch shape (post-GO)
Section titled “Dispatch shape (post-GO)”Single Executor (worktree), {64.12} then {64.13} SERIALLY (same migration window), commit per subtask via commit-commands, gitnexus_impact journaled. Then task-checker per subtask (spec-compliance + KH conventions). Return ledger_intents (flip {64.12}/{64.13} done + journals) to PARENT — never write ledger in-branch.