Skip to content

test(server): strengthen v1 cutover proof with event-stream waits and content snapshots - #11869

Open
saphid wants to merge 479 commits into
pingdotgg:t3code/codex-turn-mappingfrom
saphid:work/ov2-20260913-22-followup
Open

saphid wants to merge 479 commits into
pingdotgg:t3code/codex-turn-mappingfrom
saphid:work/ov2-20260913-22-followup

Conversation

@saphid

@saphid saphid commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #11639 (merged as 2aa8552) addressing post-merge review findings on LegacyV1Cutover.integration.test.ts:

  • Run completion via event stream, not polling. The previous waitForIdle helper polled the projection 1000×5ms. dispatchMessageAwaitingRun now forks a filtered streamDomainEvents fiber (run.updated/completed, matched to the dispatched userMessageId and threadId) before dispatch, then drains the outbox worker, joins the terminal fiber, and drains again — the established pattern from SelectionRestart.integration.test.ts.
  • Preservation proof compares contents, not counts. The recovery assertion previously compared only row counts. seedV1Database now returns a deterministic pre-migration snapshot (column list + full ordered rows) of projection_projects, projection_threads, and projection_thread_messages; after both boots, rows are restricted to the pre-migration column set and deep-compared — so mutated transcript text, attachments, or metadata would fail. Migrations legitimately append columns (e.g. 051/052), so comparison is restricted to the v1 column set.
  • Recovery source file hash. SHA-256 of the seeded source database is captured before the copy and re-verified at the end, proving the recovery file was never written.

Test plan

  • vp test run apps/server/src/orchestration-v2/LegacyV1Cutover.integration.test.ts — passes (~500ms)
  • vp run typecheck (apps/server) — zero diagnostics on the changed file
  • vp fmt clean

Generated with Devin

juliusmarminge and others added 30 commits September 14, 2026 23:27
- Omit transcript bodies from shell rows
- Query archived threads separately and stream compact resume metadata
Re-applies the deltas that mid-stack blob reverts discarded, and merges
main's work into the v2-owned surfaces:

- keybindings: main's STATIC_KEYBINDING_COMMANDS rename plus both new
  commands (rightPanel.toggleMaximized alongside threadPanel.toggle)
- OpenInPicker: main's remote-open/SSH routing and favorite-editor
  shortcut layered onto the branch's panel/toolbar variants; the
  extracted shouldShowOpenInPicker now takes remoteOpenMode
- ChatMarkdown: main's bare-filename resolver (pingdotgg#6297) ported into the
  branch's module-level component factory, plus pingdotgg#4133 title-attribute
  stripping on links and images
- ComposerPrimaryActions: main's pingdotgg#4781 model (stop stays reachable, send
  joins it when Enter-to-send is unavailable) carrying the branch's
  steering send button
- ComposerPendingUserInputPanel: main's collapsible redesign with the v2
  RuntimeRequestId and responseCapability gate
- ChatComposer: main's oversized-prompt submission guard wrapping the
  branch's dispatch-mode send
- preview shell: main's container-aware width clamp ported into the
  branch's usePreviewPanelInlineSize hook
- MessagesTimeline/Sidebar: main's day-aware timestamps, code-font tool
  bodies and provider accent badges on the v2 runtime shell
- index.css: main's @variant dark migration (pingdotgg#6381) replaces the branch's
  standalone .dark block
- contracts: main's send-turn image mime allowlist re-homed to
  chatAttachment.ts, where v2 keeps the other send-turn limits

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports v1's pingdotgg#5246 guard into the v2 dispatcher: a stored receipt only
proves that this exact command already ran for the thread it was recorded
against, so returning it for a command aimed at a different thread reports
success for work that never happened there. The check is extracted as
canReplayCommandReceipt so the rule is unit-testable, and reuse now fails
with OrchestratorCommandIdConflictError like the v1 path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Keep prominent activity rows visible with lifecycle status and provider metadata
- Move feed sizing logic into tested helpers and preserve native measurement for activity groups
Re-applies the deltas that mid-stack blob reverts discarded, and merges
main's round-9 work into the v2-owned surfaces:

- settings: main's Integrations page (pingdotgg#7082) coexists with the branch's
  Scheduled Tasks page in the path union, section labels, icons, and
  search catalog
- contracts: main's preview appearance/zoom/viewport settings imports
  restored beside the branch's modelSelection home for ModelSelection
- mobile: main's built-in themes (pingdotgg#6619) re-applied to the v2 thread
  screens and work log (useThemeColor over hand-rolled color-scheme
  ternaries)
- MessagesTimeline: main's pingdotgg#7157 cleanup adopted (toolCallExpandedBody
  class name unexported, implementation-detail test dropped)
- ChangedFilesTree: main's styled tooltip (pingdotgg#7209) carrying the v2 runId
- pullRequestDetail tests: branch's row-action coverage renamed onto
  main's buildAddSelectionToAgentHandoff (pingdotgg#6597)
- lint: migrated the six branch-owned native title tooltips that main's
  new no-native-title-tooltip rule (pingdotgg#7209) flags to styled Tooltips
  (GitActionsControl, QueuedRunsControl, TimelineSystemDivider,
  MessagesTimeline intent badge and MCP tool logo)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports pingdotgg#7083 into the v2 session path, which replaced the v1
ProviderService where main's gate lives. Instead of withholding the whole
t3-code MCP credential — on this branch it also carries the thread
orchestration and worktree toolkits — the credential is minted without
the "preview" capability when enableAgentBrowserAccess is off, so every
preview tool call rejects while orchestration stays available.

ProviderSessionManager reads the setting at prepare time (deny on an
unreadable settings file, matching main), rotates a reused credential
whose capability set no longer reflects the setting, and the session
config now carries browserToolsAvailable so the Codex adapter keeps its
developer instructions truthful via main's parameterized instruction
builders instead of the removed constants.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s style simplification

Main's pingdotgg#6381 deleted the shared .workspace-topbar and scroll-fade rules
from index.css after inlining them at main's own call sites, but this
branch's slim chat chrome still references both classes. The round-8
rebase took the deletion without migrating the branch call sites, so the
header collapsed to zero height — the breadcrumb sat on the window edge,
timeline rows scrolled unfaded through it, and the thread-details popover
anchored to the collapsed header.

Restores both as composable utilities in pingdotgg#6381's own style: a
workspace-topbar utility for the titlebar rows, and the branch's
chat-timeline-scroll-fade mask (soft ramp plus a full-height scrollbar
column). Also drops the duplicated media override and its dead
settings-page-scroll-fade selector.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation

A follow-up sweep against pingdotgg#6381 found the branch still carrying the
pre-simplification forms it replaced, which my earlier fix had papered
over with a compat utility instead of finishing the migration:

- ChatView now uses main's inlined titlebar sizing and the
  data-workspace-titlebar-controls hook on both control clusters. The
  class-based markup was silently missing the themed-toggle bridge
  (html[data-theme-id] [data-workspace-titlebar-controls] …), so custom
  themes lost their titlebar accent in the thread view.
- The scroll-to-end pill becomes main's Button size="xs" variant="glass"
  instead of a hand-rolled button recreating it.
- MessagesTimeline uses main's consolidated topbar-scroll-fade utility;
  the byte-identical chat-timeline-scroll-fade copy and the
  workspace-topbar compat utility are gone.
- The composer-glass dark rules move into nested @variant dark like
  main's (the raw .dark duplicates could drift from the nested copies
  they shadowed), including the branch-only queue strip.
- The pre-pingdotgg#6381 dialog-glass/dialog-backdrop/dropdown-glass class rules
  and their .dark variants are deleted: the pingdotgg#6381 utilities plus
  call-site shadow utilities own every declaration, and the stale
  dropdown rule still had the saturate-less backdrop-filter. The dead
  model-picker-surface dark rule goes with them.

index.css now has zero raw .dark selectors outside the variant
definitions, matching the doctrine in
.macroscope/check-run-agents/ui-consistency.md. Verified against the
emitted production CSS: dark variants compile to :is(.dark,.dark *) with
their @supports color-mix fallbacks intact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Complete retry items when provider activity resumes
- Keep retry progress visible across web and mobile clients
Ten days of main (194 commits, 640 files) re-integrated with the v2
re-architecture. The headline mechanics:

- migrations: main added 041-043 (AuthSessionClientConnection,
  ProjectionThreadLinkedPullRequest, ProjectionThreadsUnsettledAt), so the
  v2 block renumbers 041-049 → 044-052 with the migration tests shifted to
  match
- contracts: OrchestrationClientOrigin (pingdotgg#7774) and the origin metadata
  field live in applicationEvent.ts and re-export through the legacy
  path; ProviderApprovalOption + acceptAlways + mcp-elicitation (pingdotgg#8058)
  land in providerPolicy.ts; OrchestrationDispatchCommandError (pingdotgg#8824)
  added; the send-turn image-mime home stays chatAttachment.ts
- threadSettled: main's settle-once-on-merge semantics (pingdotgg#7454) and
  un-settle re-anchor (pingdotgg#8231) hand-merged onto the v2 duck-typed shells
  (latestRun ?? latestTurn reads); web callers pass the new
  ChangeRequestSettleSource shape
- timeline anchoring: main's pingdotgg#7897 (follow-up sends no longer push to the
  top) ported by scanning user rows only; the branch test now encodes the
  new semantics, as does mobile's pingdotgg#7969 settled-pinned shelf behavior
- vcs: branch's deleteLocalBranch coexists with main's pruneWorktrees and
  the pingdotgg#7674 submodule checkout tests
- ws: v2 RPC surface keeps its dispatch path; main's attachment upload
  RPCs (pingdotgg#8048) and client-connection analytics recording are wired;
  providerUploadFeedback (pingdotgg#7949) fails explicitly pending a v2 route
- approvals: main's option-driven approval buttons (pingdotgg#8058) render through
  the v2 canRespond gate on web and mobile
- ChatView/ChatComposer/MessagesTimeline/Sidebar/session-logic/
  threadActivity keep the branch's v2 architecture; main's v1-coupled
  deltas to those files are recorded for follow-up rather than
  force-fitted

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…in the v2 work log

Ports main's pingdotgg#7999/pingdotgg#7893 failure policy onto the v2 turn-item work log:
output text that reports a failure (command not found, ENOENT, nonzero
exit markers) now flags a row even when the provider item completed
"successfully", while the rendered row judges only its displayed result —
a command that merely greps for failure strings stays calm. Success now
also requires the failure check to pass, so recovered failures no longer
get the blue check.

The server half of pingdotgg#7893 needs no port: CodexAdapterV2 already projects
item.status directly, so a failed item never masquerades as completed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dotgg#8160)

Main's thread↔PR linking never reached the v2 runtime: the client types
were optional stubs and the v2 server dropped the field, so linking a PR
on a v2 environment silently no-opped and pingdotgg#7454's settle-once logic could
never match the linked identity.

The link now flows end to end: thread.metadata.update carries an optional
linkedPullRequest (object to link, null to unlink), the orchestrator
folds it into thread state, and both shell builders project it — no
migration needed since v2 shells persist as payload JSON. The client
command sends the field and the shell mapper surfaces it, so the existing
web/mobile badge and settle plumbing light up on v2 threads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lient (pingdotgg#8058)

Round 10 ported main's option-driven approval buttons, but v2 runtime
requests had no way to deliver the data — every approval rendered the
default button set, MCP app names never showed, and worse, the Codex
app-server's mcpServer/elicitation/request went entirely unhandled on the
v2 adapter, so ChatGPT-app access requests could never be answered.

The v2 approval_request turn item now carries optional appName and
options, the client derivation passes them into ThreadPendingApproval,
and CodexAdapterV2 handles mcpServer/elicitation/request end to end:
unsupported shapes decline immediately (mirroring the v1 runtime), and
supported ones surface a mcp-elicitation approval built from the shared
describeMcpElicitation/toMcpElicitationResponse helpers, so the persist
tiers (session / always) advertise exactly the choices the elicitation
can express.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pingdotgg#7949)

The round-10 rebase stubbed providerUploadFeedback to an explicit error
because its v1 ProviderService route died with the v2 rewrite. The route
now goes through the v2 runtime: session runtimes may expose an optional
uploadFeedback capability, the Codex adapter implements it against the
app-server's feedback/upload request, and the WS handler resolves the
thread's live provider session through ProviderSessionManagerV2 —
failing with a plain-language reason when no session has run, the session
is gone, or the driver has no feedback channel. This also un-blocks the
dormant mobile feedback UI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ingdotgg#7774)

Main records which client surface started each thread and turn; the v2
dispatch path replaced the v1 handler that did the recording, so v2
environments only reported connections. The v2 RPC layer now records
client.thread.started on thread launches (plus client.turn.requested when
the launch carries an initial message) and client.turn.requested on
message dispatches, using the connection's announced origin. Recording is
best-effort — attribution can never fail the user's command.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…#8358, partial)

Ports the rate-limit half of main's pingdotgg#8358 into the branch's reworked XAi
extension: a prompt_complete carrying stopReason rate_limit now fails the
hung prompt with the -32003 usage-limit error instead of settling it as a
normal end_turn, so the turn surfaces "usage limit reached" rather than
silently ending. The prompt-completion deferreds carry the error channel
end to end.

The exit_plan_mode approval gate from pingdotgg#8358 is NOT ported here: it needs
a v2 plan-flow design in AcpAdapterV2 (the v1 GrokAdapter it lived in is
gone) and is tracked separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gg#8144)

The v2 context meter could only show token counts after a compaction had
already happened — v2 had no live usage plumbing at all, so main's
compaction-threshold UX was invisible on v2 threads. Provider turns now
carry an optional tokenUsage report: the Codex adapter maps the
app-server's thread/tokenUsage/updated notification (total breakdown +
model context window) onto the active provider turn, ChatView picks the
newest report out of the projection, and the meter prefers it over the
compaction fallback — so usage and remaining-context percentages update
while the turn runs.

Claude's v2 adapter does not report usage yet; its meter falls back to
compaction items as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ingdotgg#6519)

Ports main's anchor-release semantics onto the branch's timeline anchor
state: the scroll-to-end pill and a manual scroll back to the live edge
both drop the send-time anchored end space before re-enabling follow, and
the pill's scroll runs a frame later so the list measures without the
anchor space and lands on the true end. Without this the timeline could
settle into following-end with the anchor still installed — following
nothing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ngdotgg#8358)

Completes the deferred half of pingdotgg#8358: Grok's plan-approval gate now works
on the v2 runtime. The XAi extension regains main's exit-plan helpers
(request schemas, plan-markdown extraction, the abandoned-with-feedback
response, and the plan.md session-path sniffing), and the v2 ACP adapter
grows a captureProposedPlan primitive that emits a completed
proposed-plan artifact for the active turn — one plan id per turn, so
plan.md rewrites and the exit gate update a single card.

The Grok flavor wires both ends: tool calls that write plan.md under a
Grok session dir surface the plan while plan mode is still active, and
x.ai/exit_plan_mode (plus the underscore alias) captures the final plan —
request content first, then the sniffed plan.md contents, then the
empty-state placeholder — and abandons the native gate so the turn does
not hang, mirroring the Claude ExitPlanMode pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…er chrome

Two post-rebase regressions from the round-10 index.css merge:

- The merge seam ate the closing brace of .chat-composer-glass, silently
  nesting the entire composer-glass section (shell, host, context strip,
  shoulder tab, banner cap) inside it as descendant rules that never
  matched — the composer surface stopped painting and thread content
  showed straight through the input. The brace is restored and the
  compensating over-close removed; every composer selector emits at top
  level again.

- The thread-details popover grew dropdown-glass card chrome around the
  panel: round 9 deleted the legacy components-layer .dropdown-glass rule
  in favor of the @Utility, which the popover's border-0/bg-transparent
  suppressors no longer outrank (the utility emits later in the layer).
  The suppressors are now important variants, matching the !overflow
  override already there.

Verified against the emitted production CSS: shell::before is top-level,
no descendant-of-glass selectors remain, and the important suppressors
(including [backdrop-filter:none]!) are emitted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s survives shoulder tabs

The composer went frameless exactly when the stash or tasks badge was
showing: main's pingdotgg#7150 css hides the classic shell chrome whenever the
shell :has() a shoulder tab or top drawer and repaints the glass on
[data-chat-composer-main-surface] instead — an element the branch's
composer body never rendered, since it predates the drawer system while
the badges and css came through the rebase in main's new form.

The branch composer's frame div now carries the main-surface attribute
(with main's relative z-10 stacking) so attached mode paints background,
outline, and backdrop on it and the tab connects to the surface, and
ChatView applies chat-composer-glass-shell-attached while banner items
render in the drawer slot, matching main's externalComposerDrawerAttached
wiring. Without a tab or banner the attribute is inert and the classic
shell chrome paints as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round 10 restored the branch's pre-pingdotgg#7150 composer body while its
satellites (shoulder badges, banner drawers, glass css) arrived in
main's new form, and every seam between the two was a visible bug:
opaque/frameless composer, overflowing stash tab, detached stash menu.

Rebuilt ChatComposer via a reverse three-way merge (main's body as the
base, branch delta re-applied): dispatchMode send boundary, live-capable
approval gates, latestRun reads, and the v2 context-window meter stay;
everything else now matches main, including ComposerPrimaryActions and
the sendDisabledReason send gating. Attachment uploads stay off until
the v2 claim path lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The v2 timeline rendered every tool call as its own raw row; main's
tool-group collapsing (generated "Ran N commands and changed M files"
summaries, the live "Running <program>" pill for the active tool run,
and the "+N previous log entries" clamp for mixed groups) never made it
into the v2 row model.

Ported the work-live/work-toggle row kinds and group summarization into
the v2 derive, keyed on v2 item types (command_execution, file_change,
file_search, dynamic_tool, subagent) and runId lifecycle instead of v1
activities. Expanded groups keep the branch's richer per-entry detail
rows (V2ItemInspector) — only the collapsed presentation converges on
main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v2 already projected todo_list plan artifacts (deriveActivePlanState
existed with zero consumers), but nothing rendered them: todo_list turn
items showed as a bare "Updated tasks" work row, the composer Tasks
drawer never appeared, and the working row had no current-step label.

todo_list items now become inline turn-plan chips (mini step segments,
current step, N/M count, expandable step list) that fold with their
settled turn, ChatView derives the composer Tasks drawer progress and
steps from the running run's plan artifact, and the working row shows
"Working for Xs · <current step>" like main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collapsed command rows rendered "Command" plus the raw result JSON as
the preview; the command itself is the useful collapsed line, so it now
renders as the row text (whitespace-collapsed, truncated) with stdout
and the full payload behind the expander. Tool-like headings drop the
bold foreground for the muted secondary-label the summary rows use, and
the "+N previous tool calls" toggle loses its bold black label for the
same muted treatment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extends the command-row fix to the whole preview: file-change rows were
still leaking raw diff lines into the collapsed line. workEntryPreview
now resolves input-first — command, then touched-file paths, then
detail (which is input for the remaining types: search patterns,
reasoning text, error messages) — so outputs only appear behind the
expander.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round-11 rebase onto main (25 commits). Reverse-merged main's new work
into the v2 cutover files: pingdotgg#8395 muted ordinary-tool-failure treatment
(v2-adapted workEntrySignalsSevereFailure keyed on error items), pingdotgg#5931
sidebar project-filter combobox + #4c51 keyboard pin/settle with their
ChatView support graph, the auto-settle-mode migration through
threadSettled/threadListV2, pingdotgg#8235 file/unknown attachment schemas moved
into chatAttachment.ts with nullable attachment paths, pingdotgg#8481 client
analytics through the v2 ws layer, pingdotgg#8480 OpenCode server owner wired
into the driver beside the v2 orchestration adapter, and the mobile
semantic-theme migration applied to branch-only components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports the v2-applicable half of pingdotgg#8480 (the v1 adapter rewrite was not
carried; this branch's OpenCode path is OpenCodeAdapterV2). Permission
and question asks from child sessions — task subagents and their
descendants — were dropped because the adapter only looked up root
thread sessions. Related sessions now map back to the owning root
state (registered from task parts and session.created/updated parent
chains), and an ask that arrives before the relation is known resolves
it inline via session.get with a short forked backoff, then surfaces
the approval on the root turn. Replies already route by native request
id. Interrupts now tolerate the abort racing turn settlement instead
of failing the stop.

Covered by a new opencode_child_approval replay fixture where the
child asks for bash permission before the task part reveals the
relation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Small rebase onto main (4 commits). The composer stash-shortcut label
and the mobile start-task menu refactor merged onto the v2 composer
bodies, and main's new auto-settle list tests are ported to the v2
thread-list test file (latestRun/RunId shapes). The auto-settle
machinery itself already matched main from the round-11 reconcile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Round-13 rebase onto main (2 commits). Main reverted the auto-settle
opt-in (pingdotgg#8596 undoing pingdotgg#8321), so the branch drops the ported
autoSettleMode machinery and returns to sidebarAutoSettleOnMerge with
settling-by-default, keeping only the v2 shell-shape delta in
threadSettled. The unpin confirmation (pingdotgg#7313) merges into the v2
thread-actions hook, and the mobile list tests re-sync to main's
reverted semantics in v2 shapes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
juliusmarminge and others added 20 commits September 14, 2026 23:27
…g#11499)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…#11574)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… scheduler (pingdotgg#11585)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…pingdotgg#11590)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…g#11490)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…registry (pingdotgg#11578)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…vergent migration ids (pingdotgg#11639)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… content snapshots

Review follow-up to pingdotgg#11639: run completion is now awaited on the live
domain-event stream (run.updated/completed filtered to the dispatched
message) plus worker drains, instead of bounded projection polling; legacy
table preservation compares preserved column contents against a
pre-migration snapshot after both boots; and the recovery source file hash
is verified unchanged end to end.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 15, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 025f008

Macroscope's review found this PR approvable — This PR only strengthens an existing server integration test by waiting on terminal events and checking full legacy-table contents and fixture immutability. It does not modify production behavior, product defaults, schemas, deployment configuration, or static-analysis settings.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 6 times, most recently from f63b335 to 08a1b86 Compare September 16, 2026 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants