You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracking issue for cleanup work that follows the chat.recoupable.com → /api/chat/workflow cutover (chat#1747, shipped to prod on 2026-06-01). The cutover is fully live on chat.recoupable.com and recoup-api.vercel.app; this issue captures the remaining items that didn't need to ship with the bundle.
Goal
Delete the legacy /api/chat endpoint in api and rename /api/chat/workflow → /api/chat so the workflow path reclaims the canonical name. Downstream: lib/chat/handleChatStream.ts + every other reader of rooms/memories deleted, those tables dropped, the chat client's useChatTransport legacy fork and app/chat/[roomId]/page.tsx removed, and the known UX rough edges (bootstrap spinner wait, artist-switch lifecycle, dead /api/chats/{chatId}/artist 404s) smoothed.
What shipped (context)
api/main has 23 commits / 13 PRs of workflow + sessions + chats + backfill + archive-filter changes (merged via api#631 as 31c9d58b)
chat/main has 9 commits / 9 PRs of NewChatBootstrap + canonical URL + sidebar + artist-stamping + auto-login centralization (merged via chat#1766 as e8569589)
prod data: Phase 2 backfill + straggler backfill (6 additional rooms, 16 messages) all migrated cleanly to sessions/chats/chat_messages; 17,991 sessions with correct artist_id; 0 migratable stragglers remaining
Done
PR cleanup — closed chat#1754 (superseded; chat-side direct-DB approach was wrong layer) and chat#1755 (Approach A — pivoted to the incremental cutover) with rationale comments on each.
chat#1765 — drop legacy useChatTransport branch + delete app/chat/[roomId]/page.tsx. ✅ Shipped 2026-06-03 (merged to test, then test→main; main and test synced). sessionId is now required through useVercelChat / VercelChatProvider / Chat; the if(!sessionId) legacy /api/chat fork in useChatTransport is gone (transport always targets /api/chat/workflow); app/chat/[roomId]/page.tsx deleted so legacy /chat/{id} URLs return 404 (branded not-found page). Also: every roomIduseParams reader migrated to chatId, the two URL producers (useCreateArtistTool, generateTxtFileEmail) now emit session-scoped /sessions/{id}/chats/{id} URLs, and lib/chat/chatPaths was split one-function-per-file per SRP. Verified end-to-end on preview: new chat → session-scoped URL, transport POSTs /api/chat/workflow with sessionId+chatId+bearer, assistant streams, legacy route 404s.
chat#1774 — defer new-chat bootstrap wait from spinner to send button. ✅ Shipped 2026-06-03 (merged to test, then test→main via chat#1775; main/test synced). Chose option A: NewChatBootstrap renders <Chat> immediately with a typeable input + stable placeholder chat id, provisions session + sandbox in parallel, and gates Send until the api-minted sessionId+chatId land. The transport reads those ids via refs so the first send carries the real values (useChat pins the mount-time transport, so a memo rebuild alone wasn't enough). The flashing cue was replaced by a workspace status dot (red/yellow/green + tooltip; own WorkspaceStatusIndicator component, SRP) in the input's top-right. Measured the wait first per this item's note: POST /api/sandbox ≈ 10.9s cold is the dominant cost (api-side), so this ships the typeable-while-provisioning UX as the interim fix; the real latency fix is the non-blocking-sandbox work below (don't block the first token on the sandbox). Closed chat#1764 (stale option-A WIP) and chat#1773 (option B — app-level eager provisioning + draft shell) as superseded; verified end-to-end on preview.
Tighten artist-switch lifecycle (was: "currently mints 3 sessions per click"). ✅ Already fixed on main by chat#1759's merge — no separate follow-up fix was needed. The 3× was flagged on a feat(chat): stamp sessions with selected artist; refactor useArtists #1759preview SHA (4d26b488, flag comment) that never merged and still used react-query's isLoading; the merged version switched the roster gate to isPending (source: useArtistsRoster.ts L60-86), so the bootstrap stays gated until the roster is populated and selectedArtist never fires as null (with useArtistSelection's single-render useMemo). Verified on prod: each switch fires 1POST /api/sessions + 1POST /api/sandbox (tested personal + org/heavy-repo + 4× CPU/Slow-4G throttle, all switch paths incl. the hard-nav reload). chat#1769 was the follow-up PR but is redundant for the 3× bug — it remains optional defensive hardening for the in-flight-mismatch edge. Full analysis: chat#1769 comment.
Credit-spend visibility digest (Telegram). ✅ Shipped 2026-06-03 — api#634 → test → main (api#637). Vercel cron */10 * * * * → GET /api/internal/credit-spend-digest → get_credit_spend_digest (database#28, live in prod) → Telegram top-spenders summary; empty window no-ops; CRON_SECRET-gated. Verified end-to-end on preview (401/200 auth, empty no-op, real digest posted to Telegram). Surfaced the model-selector bug tracked below.
chat#1768 — clean up dead GET /api/chats/{chatId}/artist 404 spam. ✅ Shipped 2026-06-03 (squash-merged to test, then test→main via chat#1778; main/test synced). Deleted the legacy caller (useArtistFromRoom + lib/chats/getChatArtist.ts); the active artist is now resolved from the session — useArtistFromChat reads GET /api/sessions/{sessionId}.artistId (new client wrapper lib/sessions/getSessionById.ts, zod-validated at the boundary) and selects the matching roster artist. No new endpoint added to the chat repo — uses the existing recoup-api session endpoint. Added shared lib/api/safeJsonParse.ts (DRY, not in utils/). Verified end-to-end on preview via Chrome DevTools: opening a chat fires GET /api/sessions/{id} (returns artistId) and zeroGET /api/chats/{id}/artist calls; cross-artist switch confirmed (Bieber→Alex Paul: GET /api/sessions/{id} → GET /api/chats?artist_account_id=… for the new artist), re-verified on the final build. Edge cases that correctly no-op (not regressions): session artist_id null (~24% of sessions) and chats whose artist isn't in the user's roster.
Retire the legacy POST /api/chat streaming endpoint (api#632 + docs#230). ✅ Shipped 2026-06-04. Decision: deleted outright (no deprecate-with-comms) — after chat#1765 no in-monorepo caller remained and /api/chat/workflow fully covers the UI contract. api#632 (squash → test as c0eb5496, then test→main via api#643 as 5e31ad06; test re-synced with main): deleted app/api/chat/route.ts, lib/chat/handleChatStream.ts, lib/chat/handleChatCompletion.ts, lib/emails/handleSendEmailToolOutputs.ts + their tests, and trimmed chatEndToEnd.test.ts to the still-live validation/setup/credits paths. A follow-up dead-code sweep on the same PR removed 4 modules the legacy handlers were the sole reachers of: lib/emails/extractSendEmailResults.ts; the dead duplicate lib/messages/validateMessages.ts (the live one is lib/chat/validateMessages.ts); lib/supabase/memories/upsertMemory.ts (+ its now-vestigial vi.mock); and the pre-existing orphan lib/messages/getLatestUserMessageText.ts (+ test). A full transitive trace confirmed everything else the legacy handlers touched (setupConversation/createNewRoom/generateChatTitle/setupChatRequest/getGeneralAgent/rooms+memories readers) is still reachable from live entry points (/api/chat/generate, /api/chats, Slack, email-inbound, MCP create-artist), so it correctly stays for Phase 4. Net +26 / −1435. docs#230 (squash → main as b0eaaee): removed the endpoint page, its OpenAPI entries, and the nav link. Shared helpers used by /api/chat/workflow, /api/chat/generate, the stop route, Slack, and email flows untouched. Verified: local lint:check clean + 692 tests pass; repo-wide grep shows 0 references to any deleted module; preview E2E on api-git-feat-remove-legacy-chat-endpoint-recoup.vercel.app — POST /api/chat → 404 (gone), POST /api/chat/workflow → 400 (validation wired), POST /api/chat/generate → 400, GET /api/chats → 401 (sibling module graphs load cleanly, not 500). Full rooms/memories table teardown remains in Phase 4 below.
Workflow billed the default model instead of the picked one — fixed (chat#1781). ✅ Shipped 2026-06-04 (squash → test as c711516f, then test→main via chat#1782 as 07cdc2f0; main/test synced). Root cause: the workflow reads the model from chats.model_id (api/lib/chat/handleChatWorkflowStream.ts:93), which the UI never wrote before the first send, so new chats billed the column default. Decision: follow the open-agents pattern — resolve server-side from the persisted chat.model_id, not the request body, so api#638 (thread model through the workflow body) was closed as wrong-layer. Fix (chat-only, no api/DB change): persist the picker selection to chats.model_id and await that PATCH right before the send — covering the first-turn (useVercelChat.handleSubmit), retry/edit (reload→regenerate), and append paths — gated by a pure shouldPersistChatModel guard; extracted into hooks/usePersistSelectedModel.ts per OCP review feedback. Reuses Enhance chat functionality by integrating model ID persistence and updating chat update parameters. #1779's buildPatchChatBody + updateChat(modelId). Superseded chat#1779 (its PATCH-only sync hooks billed the localStorage default in the live repro; left open for its author to close). Verified end-to-end on the fix(chat): persist selected model before send so the workflow bills it #1781 preview (Chrome DevTools + Supabase usage_events): new chat → Claude Sonnet 4.6 → billed anthropic/claude-sonnet-4.6; then changed model → Retry → regenerated turn billed google/gemini-3-pro-preview; picked = billed on both paths. Unit tests green (shouldPersistChatModel, buildPatchChatBody); tsc + lint clean.
Renamed /api/chat/workflow → /api/chat — canonical name reclaimed, shipped to prod. ✅ Cut over 2026-06-05. Done doc-first then a coordinated hard rename (no alias): docs #235 (4b80c1d2→main) → api #645 (66bf07ef→test) → chat #1783 (9798ef30→test) → open-agents #47 (25468103→main); then promoted in lockstep: open-agents#47, api #648 (4a0d70ec→main), chat #1784 (5089252a→main); test re-synced with main on api + chat. What changed: added app/api/chat/route.ts (POST + OPTIONS → handleChatWorkflowStream) and deletedapp/api/chat/workflow/route.ts; repointed chat useChatTransport and open-agents CHAT_API_POST_PATH to /api/chat; docs OpenAPI makes /api/chat canonical. Verified in prod:api.recoupable.com/api/chat → 400 (live), /api/chat/workflow → 404 (gone); chat.recoupable.com new chat → POST api.recoupable.com/api/chat → 200, streamed pong, zero /workflow calls; open-agents live E2E POST …/api/chat → 200, pong. Cutover note: a brief deploy-lag window occurred — chat prod (old build) briefly POSTed /api/chat/workflow → 404 until chat's new build deployed; expected for a hard rename with no alias, self-healed on deploy. Accepted leftover (cosmetic): a few api route/handler comments still say "backward-compatible alias" (those docstring edits never got committed — the functional change shipped correctly); optional tidy follow-up. ⚠️ External API-key callers must use /api/chat (no alias).
Open — pre-existing docs gaps (separate work, low priority)
Surfaced while verifying api#628 against docs#228. Neither was introduced by the cutover; tracked for visibility:
Session.isNewBranch is marked required in the OpenAPI schema but is missing from every actual response (POST/GET/PATCH /api/sessions). Either drop the required-tag or have the api always emit it.
PATCH /api/sessions/{id} has no documented request body schema (PatchSessionBody doesn't exist in the spec) even though the endpoint clearly accepts { title } (and now { status }). Small docs PR to add it.
Open — Phase 4 cleanup (LAST, only after the cutover bundle is stable on main for some time)
Phase 4 — legacy code cleanup.(Updated: lib/chat/handleChatStream.ts, the legacy app/api/chat/route.ts, and lib/chat/handleChatCompletion.ts were already deleted by api#632. Note app/api/chat/route.ts now exists again as the canonical workflow endpoint from the rename — do NOT delete it.) Remaining rooms/memories readers to remove: getGeneralAgent.ts, setupChatRequest.ts, setupToolsForRequest.ts, MCP/Composio plumbing — i.e. the chain still reachable from /api/chat/generate, Slack, and email-inbound. Confirms no production code path still depends on the legacy tables.
Drop legacy rooms + memories tables. Only after Phase 4 has removed the last rooms/memories readers. Requires a migration file in recoupable/database to drop them (plus FK-dependent tables like room_reports / segment_rooms / memory_emails as applicable). Destructive + irreversible — snapshot first and confirm nothing still reads rooms/memories before dropping.
Inherited gaps from open-agents cutover (still applies, tracked separately)
Tracked in recoupable/api#605. Not blocking; documented here for visibility:
Stop monitor — Stop button doesn't actually halt the model (chat#1770 + api#590 address this.)
Multi-tool-call traces broken client-side
Sandbox state persistence missing
Sub-agent (task tool) credit attribution missing
ask_user_question result persistence on device switch missing
workflow_runs telemetry missing
Accepted regressions (still in effect — re-add later as needed)
These shipped with the cutover and are still missing from production chat:
No MCP tools (artist data, music industry APIs, send_email) inside the workflow sandbox
No Composio tools (Sheets, Drive, Docs, TikTok)
No artist context in system prompt
No automatic chat title generation (title = first user message verbatim)
No Telegram new-conversation notifications (being re-scoped above)
Tracking issue for cleanup work that follows the chat.recoupable.com →
/api/chat/workflowcutover (chat#1747, shipped to prod on 2026-06-01). The cutover is fully live onchat.recoupable.comandrecoup-api.vercel.app; this issue captures the remaining items that didn't need to ship with the bundle.Goal
Delete the legacy
/api/chatendpoint in api and rename/api/chat/workflow→/api/chatso the workflow path reclaims the canonical name. Downstream:lib/chat/handleChatStream.ts+ every other reader ofrooms/memoriesdeleted, those tables dropped, the chat client'suseChatTransportlegacy fork andapp/chat/[roomId]/page.tsxremoved, and the known UX rough edges (bootstrap spinner wait, artist-switch lifecycle, dead/api/chats/{chatId}/artist404s) smoothed.What shipped (context)
31c9d58b)e8569589)sessions/chats/chat_messages; 17,991 sessions with correctartist_id; 0 migratable stragglers remainingDone
PR cleanup — closed chat#1754 (superseded; chat-side direct-DB approach was wrong layer) and chat#1755 (Approach A — pivoted to the incremental cutover) with rationale comments on each.
chat#1765 — drop legacy
useChatTransportbranch + deleteapp/chat/[roomId]/page.tsx. ✅ Shipped 2026-06-03 (merged totest, thentest→main;mainandtestsynced).sessionIdis now required throughuseVercelChat/VercelChatProvider/Chat; theif(!sessionId)legacy/api/chatfork inuseChatTransportis gone (transport always targets/api/chat/workflow);app/chat/[roomId]/page.tsxdeleted so legacy/chat/{id}URLs return 404 (branded not-found page). Also: everyroomIduseParamsreader migrated tochatId, the two URL producers (useCreateArtistTool,generateTxtFileEmail) now emit session-scoped/sessions/{id}/chats/{id}URLs, andlib/chat/chatPathswas split one-function-per-file per SRP. Verified end-to-end on preview: new chat → session-scoped URL, transport POSTs/api/chat/workflowwithsessionId+chatId+bearer, assistant streams, legacy route 404s.chat#1774 — defer new-chat bootstrap wait from spinner to send button. ✅ Shipped 2026-06-03 (merged to
test, thentest→mainvia chat#1775;main/testsynced). Chose option A:NewChatBootstraprenders<Chat>immediately with a typeable input + stable placeholder chat id, provisions session + sandbox in parallel, and gates Send until the api-mintedsessionId+chatIdland. The transport reads those ids via refs so the first send carries the real values (useChatpins the mount-time transport, so a memo rebuild alone wasn't enough). The flashing cue was replaced by a workspace status dot (red/yellow/green + tooltip; ownWorkspaceStatusIndicatorcomponent, SRP) in the input's top-right. Measured the wait first per this item's note:POST /api/sandbox≈ 10.9s cold is the dominant cost (api-side), so this ships the typeable-while-provisioning UX as the interim fix; the real latency fix is the non-blocking-sandbox work below (don't block the first token on the sandbox). Closed chat#1764 (stale option-A WIP) and chat#1773 (option B — app-level eager provisioning + draft shell) as superseded; verified end-to-end on preview.Tighten artist-switch lifecycle (was: "currently mints 3 sessions per click"). ✅ Already fixed on
mainby chat#1759's merge — no separate follow-up fix was needed. The 3× was flagged on a feat(chat): stamp sessions with selected artist; refactor useArtists #1759 preview SHA (4d26b488, flag comment) that never merged and still used react-query'sisLoading; the merged version switched the roster gate toisPending(source:useArtistsRoster.tsL60-86), so the bootstrap stays gated until the roster is populated andselectedArtistnever fires asnull(withuseArtistSelection's single-renderuseMemo). Verified on prod: each switch fires 1POST /api/sessions+ 1POST /api/sandbox(tested personal + org/heavy-repo + 4× CPU/Slow-4G throttle, all switch paths incl. the hard-nav reload). chat#1769 was the follow-up PR but is redundant for the 3× bug — it remains optional defensive hardening for the in-flight-mismatch edge. Full analysis: chat#1769 comment.Credit-spend visibility digest (Telegram). ✅ Shipped 2026-06-03 — api#634 →
test→main(api#637). Vercel cron*/10 * * * *→GET /api/internal/credit-spend-digest→get_credit_spend_digest(database#28, live in prod) → Telegram top-spenders summary; empty window no-ops;CRON_SECRET-gated. Verified end-to-end on preview (401/200 auth, empty no-op, real digest posted to Telegram). Surfaced the model-selector bug tracked below.chat#1768 — clean up dead
GET /api/chats/{chatId}/artist404 spam. ✅ Shipped 2026-06-03 (squash-merged totest, thentest→mainvia chat#1778;main/testsynced). Deleted the legacy caller (useArtistFromRoom+lib/chats/getChatArtist.ts); the active artist is now resolved from the session —useArtistFromChatreadsGET /api/sessions/{sessionId}.artistId(new client wrapperlib/sessions/getSessionById.ts, zod-validated at the boundary) and selects the matching roster artist. No new endpoint added to the chat repo — uses the existing recoup-api session endpoint. Added sharedlib/api/safeJsonParse.ts(DRY, not inutils/). Verified end-to-end on preview via Chrome DevTools: opening a chat firesGET /api/sessions/{id}(returnsartistId) and zeroGET /api/chats/{id}/artistcalls; cross-artist switch confirmed (Bieber→Alex Paul:GET /api/sessions/{id}→GET /api/chats?artist_account_id=…for the new artist), re-verified on the final build. Edge cases that correctly no-op (not regressions): sessionartist_idnull (~24% of sessions) and chats whose artist isn't in the user's roster.Retire the legacy
POST /api/chatstreaming endpoint (api#632 + docs#230). ✅ Shipped 2026-06-04. Decision: deleted outright (no deprecate-with-comms) — after chat#1765 no in-monorepo caller remained and/api/chat/workflowfully covers the UI contract. api#632 (squash →testasc0eb5496, thentest→mainvia api#643 as5e31ad06;testre-synced withmain): deletedapp/api/chat/route.ts,lib/chat/handleChatStream.ts,lib/chat/handleChatCompletion.ts,lib/emails/handleSendEmailToolOutputs.ts+ their tests, and trimmedchatEndToEnd.test.tsto the still-live validation/setup/credits paths. A follow-up dead-code sweep on the same PR removed 4 modules the legacy handlers were the sole reachers of:lib/emails/extractSendEmailResults.ts; the dead duplicatelib/messages/validateMessages.ts(the live one islib/chat/validateMessages.ts);lib/supabase/memories/upsertMemory.ts(+ its now-vestigialvi.mock); and the pre-existing orphanlib/messages/getLatestUserMessageText.ts(+ test). A full transitive trace confirmed everything else the legacy handlers touched (setupConversation/createNewRoom/generateChatTitle/setupChatRequest/getGeneralAgent/rooms+memories readers) is still reachable from live entry points (/api/chat/generate,/api/chats, Slack, email-inbound, MCP create-artist), so it correctly stays for Phase 4. Net +26 / −1435. docs#230 (squash →mainasb0eaaee): removed the endpoint page, its OpenAPI entries, and the nav link. Shared helpers used by/api/chat/workflow,/api/chat/generate, the stop route, Slack, and email flows untouched. Verified: locallint:checkclean + 692 tests pass; repo-wide grep shows 0 references to any deleted module; preview E2E onapi-git-feat-remove-legacy-chat-endpoint-recoup.vercel.app—POST /api/chat→ 404 (gone),POST /api/chat/workflow→ 400 (validation wired),POST /api/chat/generate→ 400,GET /api/chats→ 401 (sibling module graphs load cleanly, not 500). Fullrooms/memoriestable teardown remains in Phase 4 below.Workflow billed the default model instead of the picked one — fixed (chat#1781). ✅ Shipped 2026-06-04 (squash →
testasc711516f, thentest→mainvia chat#1782 as07cdc2f0;main/testsynced). Root cause: the workflow reads the model fromchats.model_id(api/lib/chat/handleChatWorkflowStream.ts:93), which the UI never wrote before the first send, so new chats billed the column default. Decision: follow the open-agents pattern — resolve server-side from the persistedchat.model_id, not the request body, so api#638 (threadmodelthrough the workflow body) was closed as wrong-layer. Fix (chat-only, no api/DB change): persist the picker selection tochats.model_idandawaitthat PATCH right before the send — covering the first-turn (useVercelChat.handleSubmit), retry/edit (reload→regenerate), andappendpaths — gated by a pureshouldPersistChatModelguard; extracted intohooks/usePersistSelectedModel.tsper OCP review feedback. Reuses Enhance chat functionality by integrating model ID persistence and updating chat update parameters. #1779'sbuildPatchChatBody+updateChat(modelId). Superseded chat#1779 (its PATCH-only sync hooks billed the localStorage default in the live repro; left open for its author to close). Verified end-to-end on the fix(chat): persist selected model before send so the workflow bills it #1781 preview (Chrome DevTools + Supabaseusage_events): new chat → Claude Sonnet 4.6 → billedanthropic/claude-sonnet-4.6; then changed model → Retry → regenerated turn billedgoogle/gemini-3-pro-preview; picked = billed on both paths. Unit tests green (shouldPersistChatModel,buildPatchChatBody); tsc + lint clean.Renamed⚠️ External API-key callers must use
/api/chat/workflow→/api/chat— canonical name reclaimed, shipped to prod. ✅ Cut over 2026-06-05. Done doc-first then a coordinated hard rename (no alias): docs #235 (4b80c1d2→main) → api #645 (66bf07ef→test) → chat #1783 (9798ef30→test) → open-agents #47 (25468103→main); then promoted in lockstep: open-agents#47, api #648 (4a0d70ec→main), chat #1784 (5089252a→main);testre-synced withmainon api + chat. What changed: addedapp/api/chat/route.ts(POST + OPTIONS →handleChatWorkflowStream) and deletedapp/api/chat/workflow/route.ts; repointed chatuseChatTransportand open-agentsCHAT_API_POST_PATHto/api/chat; docs OpenAPI makes/api/chatcanonical. Verified in prod:api.recoupable.com/api/chat→ 400 (live),/api/chat/workflow→ 404 (gone); chat.recoupable.com new chat →POST api.recoupable.com/api/chat→ 200, streamedpong, zero/workflowcalls; open-agents live E2EPOST …/api/chat→ 200,pong. Cutover note: a brief deploy-lag window occurred — chat prod (old build) briefly POSTed/api/chat/workflow→ 404 until chat's new build deployed; expected for a hard rename with no alias, self-healed on deploy. Accepted leftover (cosmetic): a fewapiroute/handler comments still say "backward-compatible alias" (those docstring edits never got committed — the functional change shipped correctly); optional tidy follow-up./api/chat(no alias).Open — pre-existing docs gaps (separate work, low priority)
Surfaced while verifying api#628 against docs#228. Neither was introduced by the cutover; tracked for visibility:
Session.isNewBranchis marked required in the OpenAPI schema but is missing from every actual response (POST/GET/PATCH/api/sessions). Either drop the required-tag or have the api always emit it./api/sessions/{id}has no documented request body schema (PatchSessionBodydoesn't exist in the spec) even though the endpoint clearly accepts{ title }(and now{ status }). Small docs PR to add it.Open — Phase 4 cleanup (LAST, only after the cutover bundle is stable on
mainfor some time)Phase 4 — legacy code cleanup. (Updated:
lib/chat/handleChatStream.ts, the legacyapp/api/chat/route.ts, andlib/chat/handleChatCompletion.tswere already deleted by api#632. Noteapp/api/chat/route.tsnow exists again as the canonical workflow endpoint from the rename — do NOT delete it.) Remainingrooms/memoriesreaders to remove:getGeneralAgent.ts,setupChatRequest.ts,setupToolsForRequest.ts, MCP/Composio plumbing — i.e. the chain still reachable from/api/chat/generate, Slack, and email-inbound. Confirms no production code path still depends on the legacy tables.Drop legacy
rooms+memoriestables. Only after Phase 4 has removed the lastrooms/memoriesreaders. Requires a migration file in recoupable/database to drop them (plus FK-dependent tables likeroom_reports/segment_rooms/memory_emailsas applicable). Destructive + irreversible — snapshot first and confirm nothing still readsrooms/memoriesbefore dropping.Inherited gaps from open-agents cutover (still applies, tracked separately)
Tracked in recoupable/api#605. Not blocking; documented here for visibility:
ask_user_questionresult persistence on device switch missingworkflow_runstelemetry missingAccepted regressions (still in effect — re-add later as needed)
These shipped with the cutover and are still missing from production chat:
send_email) inside the workflow sandbox