fix(web): park conversation-id wire-field cutover above current daemon (0.8.6)#32146
Merged
Merged
Conversation
…n (0.8.6) Daemon 0.8.5 strict-lookup on conversationId rejects locally-minted draft conversation ids, 404ing the first message of every new conversation. Keep the legacy create-or-lookup conversationKey path live until the draft-id flow moves to daemon-mints-on-first-send. Boundary tests updated; targeted tests + eslint + tsc clean.
dvargasfuertes
approved these changes
May 26, 2026
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.
Symptom
On staging (
release/v0.8.5), the first message of any new conversation 404s.Root cause
PR #31944 ("feat(web): version-gated cutover to conversationId on POST /v1/messages + GET /v1/events") flipped the wire-field gate at MIN_VERSION =
0.8.5. Two things collide:createDraftConversationId()→chat-layout.handleStartNewConversation) and uses it as the URL key before the daemon has ever heard of it.conversationIdhandler is strict-lookup (getConversation(id)→ 404 on miss).conversationKeyis the create-or-lookup path that materializes the row on first use.On a 0.8.5 daemon,
pickConversationIdWireField()returns"conversationId", so the very first POST/v1/messagesof a new conversation sends an id the daemon has never minted →NotFoundError→ 404. The SSE subscribe path (GET /v1/events) has the same shape.Fix
Bump
MIN_VERSIONfrom0.8.5→0.8.6. No daemon ships with 0.8.6 yet, so the gate falls through toconversationKeyeverywhere → first send materializes the row → no 404.Why this is a stopgap, not the cure
The cleaner architecture is "daemon mints the conversation on the first send; UI navigates to the response's id." That removes the entire backwards-compat module and the family of bugs it papers over. Tracked as a follow-up; doing it without time pressure.
Scope
apps/web/src/lib/backwards-compat/conversation-id-wire-field.ts—MIN_VERSION0.8.5 → 0.8.6, docstring updated to describe current state (gate parked above current daemon version).apps/web/src/lib/backwards-compat/conversation-id-wire-field.test.ts— boundary moved to 0.8.6; 0.8.5 now belongs in the "and older" group.apps/web/src/domains/chat/api/post-chat-message.test.ts— three version-boundary tests updated.apps/web/src/domains/chat/api/stream.test.ts— two version-boundary tests updated.apps/web/src/domains/chat/api/messages.ts+stream.ts— comments rewritten to drop the version reference and describe current state.Verification
bun test src/lib/backwards-compat/conversation-id-wire-field.test.ts— 5 passbun test src/domains/chat/api/post-chat-message.test.ts— 9 passbun test src/domains/chat/api/stream.test.ts— 26 passbun run lint— cleanbun run typecheck— clean