feat: migrate v1 state into orchestrator v2#4400
Conversation
Co-authored-by: codex <codex@users.noreply.github.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
| const suffix = | ||
| section.length <= remaining ? section : section.slice(section.length - remaining); | ||
| selected.unshift(suffix); |
There was a problem hiding this comment.
🟡 Medium orchestration-v2/ContextHandoffService.ts:182
makeLegacyImportSummary truncates from the left when a section exceeds the remaining character budget, taking a raw suffix via section.slice(section.length - remaining). When this cut lands inside the first retained section, the User: or Assistant: label is dropped and the text can start mid-word, so the imported context begins with unattributed, fragmentary text. Consider preserving the role prefix and truncating only the message body, or omitting the partial section entirely.
| const suffix = | |
| section.length <= remaining ? section : section.slice(section.length - remaining); | |
| selected.unshift(suffix); | |
| const suffix = | |
| section.length <= remaining | |
| ? section | |
| : section.slice(section.length - remaining); | |
| selected.unshift(suffix); |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/orchestration-v2/ContextHandoffService.ts around lines 182-184:
`makeLegacyImportSummary` truncates from the left when a section exceeds the remaining character budget, taking a raw suffix via `section.slice(section.length - remaining)`. When this cut lands inside the first retained section, the `User:` or `Assistant:` label is dropped and the text can start mid-word, so the imported context begins with unattributed, fragmentary text. Consider preserving the role prefix and truncating only the message body, or omitting the partial section entirely.
| const getThreadSnapshot: ThreadManagementServiceShape["getThreadSnapshot"] = (threadId) => | ||
| ensureLegacyTranscript(threadId).pipe(Effect.andThen(orchestrator.getThreadSnapshot(threadId))); | ||
|
|
||
| const dispatch: ThreadManagementServiceShape["dispatch"] = (command) => { |
There was a problem hiding this comment.
🟠 High orchestration-v2/ThreadManagementService.ts:261
The dispatch wrapper only calls ensureLegacyTranscript for message.dispatch, thread.fork, and thread.merge_back. All other commands targeting an existing migrated thread — such as thread.metadata.update, thread.archive, or thread.delete — bypass hydration and dispatch directly. When a later projection read triggers the importer, its transcript marker emits a thread.metadata-updated event from the stale v1 row, overwriting the newer title/archive/deletion metadata. Hydrate every command that operates on an existing thread before dispatching, not just those three types.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/orchestration-v2/ThreadManagementService.ts around line 261:
The `dispatch` wrapper only calls `ensureLegacyTranscript` for `message.dispatch`, `thread.fork`, and `thread.merge_back`. All other commands targeting an existing migrated thread — such as `thread.metadata.update`, `thread.archive`, or `thread.delete` — bypass hydration and dispatch directly. When a later projection read triggers the importer, its transcript marker emits a `thread.metadata-updated` event from the stale v1 row, overwriting the newer title/archive/deletion metadata. Hydrate every command that operates on an existing thread before dispatching, not just those three types.
| const ensureLegacyTranscript = (threadId: ThreadId) => | ||
| legacyImporter.ensureTranscript(threadId).pipe( | ||
| Effect.tapError((cause) => | ||
| Effect.logWarning("Unable to hydrate migrated v1 thread transcript", { | ||
| threadId, | ||
| cause, | ||
| }), | ||
| ), | ||
| Effect.ignore, | ||
| ); |
There was a problem hiding this comment.
🟡 Medium orchestration-v2/ThreadManagementService.ts:242
ensureLegacyTranscript swallows all hydration failures with Effect.ignore, so every call site (dispatch, getThreadProjection, getThreadSnapshot) proceeds as if the legacy transcript was loaded even when it wasn't. For message.dispatch this means the provider turn is built from only the shell preview instead of the full legacy conversation — context omitted from that turn cannot be restored by a later retry. Consider letting hydration failures propagate (or retrying) so dispatch does not silently continue with an incomplete transcript.
- const ensureLegacyTranscript = (threadId: ThreadId) =>
- legacyImporter.ensureTranscript(threadId).pipe(
- Effect.tapError((cause) =>
- Effect.logWarning("Unable to hydrate migrated v1 thread transcript", {
- threadId,
- cause,
- }),
- ),
- Effect.ignore,
- );
+ const ensureLegacyTranscript = (threadId: ThreadId) =>
+ legacyImporter.ensureTranscript(threadId).pipe(
+ Effect.tapError((cause) =>
+ Effect.logWarning("Unable to hydrate migrated v1 thread transcript", {
+ threadId,
+ cause,
+ }),
+ ),
+ );🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/server/src/orchestration-v2/ThreadManagementService.ts around lines 242-251:
`ensureLegacyTranscript` swallows all hydration failures with `Effect.ignore`, so every call site (`dispatch`, `getThreadProjection`, `getThreadSnapshot`) proceeds as if the legacy transcript was loaded even when it wasn't. For `message.dispatch` this means the provider turn is built from only the shell preview instead of the full legacy conversation — context omitted from that turn cannot be restored by a later retry. Consider letting hydration failures propagate (or retrying) so dispatch does not silently continue with an incomplete transcript.
Summary
userdatadirectoryMigration behavior
projection_thread_messagesafter command readiness and on first open/dispatchVerification
Stacked on #2829.
Note
Migrate v1 thread state into orchestrator v2 with on-demand transcript hydration
LegacyV1ThreadImporterservice that imports v1 threads into v2 by emitting shell events (thread.created, metadata, preview messages) during startup and full transcripts asynchronously after the server accepts commands.OrchestratorcallsContextHandoffService.prepareLegacyImportto generate amanual_contexthandoff containing a bounded (32,000 char) summary of prior messages.ThreadManagementServicewrapsgetThreadProjection,getThreadSnapshot, anddispatchto callensureLegacyTranscriptbefore returning data; errors are logged as warnings and do not fail the operation.LegacyV1ImportState) creating theorchestration_v2_legacy_importstracking table, and renumbers migrations 033–041 to make room.userdata-v2touserdata(andt3code-v2→t3code) across server, desktop, and SSH tunnel.userdata-v2paths will not find prior state at the newuserdatalocation without a manual migration or compatibility shim.📊 Macroscope summarized 0fff2d0. 14 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.