Skip to content

perf(orchestration): avoid full history loads in runtime paths - #5080

Open
tarik02 wants to merge 200 commits into
pingdotgg:t3code/codex-turn-mappingfrom
tarik02-org:perf/orchestration-v2-projection-loads
Open

perf(orchestration): avoid full history loads in runtime paths#5080
tarik02 wants to merge 200 commits into
pingdotgg:t3code/codex-turn-mappingfrom
tarik02-org:perf/orchestration-v2-projection-loads

Conversation

@tarik02

@tarik02 tarik02 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Added bounded operational projections that load only the latest turn item.
  • Added targeted reads for runs, checkpoint scopes, run and node items, and item existence checks.
  • Switched recovery, provider control, checkpointing, queue handling, subagent finalization, and thread management paths to bounded or targeted reads.
  • Kept full-history reads for snapshots, legacy imports, forks, merges, and provider context handoffs.
  • Validated historical turn items sequentially in batches of 256.

Why

Routine server operations loaded and schema-decoded every historical turn item. Memory and CPU usage therefore grew with the full thread history, even when a call only needed current runtime state.

This reduces server-side loading without changing client behavior, thread snapshots, pagination, or visible history.

Checklist

  • This PR is small and focused
  • I explained what changed and why

Note

Avoid full history loads in orchestration runtime paths by introducing operational projections

  • Adds getOperationalProjection (latest turn item only) and getRecoveryProjection (pending/running/waiting items only) to ProjectionStoreV2, alongside targeted fetch methods getRun, getCheckpointScope, getRunTurnItems, getNodeTurnItems, and getPresentTurnItemIds.
  • Replaces most getThreadProjection calls across orchestration services (Orchestrator.ts, ThreadManagementService.ts, ProviderTurnStartService.ts, etc.) with the appropriate scoped fetch; full history is only loaded when explicitly required (e.g. provider resume fallback, legacy import).
  • ProjectionMaintenance verification now uses validateThreadProjection to decode turn item payloads in batches without loading full projections.
  • Message ordering is preserved when turn items are not fully loaded by seeding ordinals from persisted message_ordinal rows.
  • Behavioral Change: all orchestration decision-making paths (launch, interruption, continuation, title regeneration, checkpoint capture/rollback, session detach) now operate on bounded projections rather than full thread history.

Macroscope summarized 41fcc34.


Note

Medium Risk
Touches core orchestration dispatch and projection loading across many services; incorrect bounded reads could change runtime behavior on long threads, though full-history paths are preserved for handoffs and imports.

Overview
Orchestration V2 no longer hydrates every historical turn item on most server paths. ProjectionStoreV2 adds bounded projections (getOperationalProjection loads only the latest turn item; getRecoveryProjection loads pending/running/waiting items) and targeted reads (getRun, getCheckpointScope, getRunTurnItems, getNodeTurnItems, getPresentTurnItemIds).

The orchestrator, thread management, provider turn control/start, checkpoint capture/rollback, runtime requests, provider session manager, and continuation/recovery services now call those APIs instead of getThreadProjection. Full history remains for snapshots, provider handoffs, v1 import / provider-switch dispatch, and client-facing getThreadProjection.

Projection maintenance startup verification uses validateThreadProjection, which decodes turn items in batches of 256 instead of loading full projections. Tests cover bounded loads and a larger many-items scenario (301 items).

Reviewed by Cursor Bugbot for commit 41fcc34. Bugbot is set up for automated code reviews on this repo. Configure here.

@tarik02 tarik02 changed the title Perf/orchestration v2 projection loads perf(orchestration): avoid full history loads in runtime paths Jul 31, 2026
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Jul 31, 2026
Comment thread apps/server/src/orchestration-v2/ProjectionStore.ts
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 760aeea8-0a12-4151-ae47-e4ceb4f9a21c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tarik02
tarik02 marked this pull request as ready for review July 31, 2026 08:34
Comment thread apps/server/src/orchestration-v2/ProjectionStore.ts
@macroscopeapp

macroscopeapp Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR changes how projection data is loaded throughout the orchestration system, switching from full history loads to bounded/targeted queries. While designed as a performance optimization, this fundamentally changes what data is available at runtime in core orchestration paths, warranting careful human review.

You can customize Macroscope's approvability policy. Learn more.

@maria-rcks
maria-rcks force-pushed the t3code/codex-turn-mapping branch from a543fd4 to 378615b Compare August 3, 2026 16:01
juliusmarminge and others added 21 commits August 4, 2026 14:00
Co-authored-by: codex <codex@users.noreply.github.com>
- Initialize provider as unchecked in a pending state
- Update initial probe message to reflect session-local status
- Type the runtime effect with `Scope`
- Build the ACP session runtime without wrapping it in `Effect.scoped`
- Use strict TurnId and ProviderItemId parsing in Codex session routing
- Decode in-memory stdio chunks in streaming mode to avoid split UTF-8 corruption
- Transfer session-owned scopes into adapter state
- Ensure runtime scopes close on stop and startup failure
- Add regression coverage for scoped lifecycle cleanup
- Close the managed native event logger when the adapter layer tears down
- Make session runtime close idempotent with an atomic closed flag
- Add coverage for flushing thread native logs on shutdown
- Use codex app-server snapshots for auth, models, and skills
- Remove legacy CLI/config discovery paths and related helpers
- Update tests for the new provider status flow
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
- Document the target orchestration graph, IDs, lifecycles, and capability model
- Add Codex app-server probe fixtures and update the probe test harness
- Introduce orchestration v2 service interfaces and error types
- Add replay runtime, fixtures, and integration coverage
- Update shared contracts and probe transcripts

Co-authored-by: codex <codex@users.noreply.github.com>
- Add Codex adapter and replay harness wiring
- Introduce in-memory orchestration projections and provider registry
- Expand orchestration contracts for turn and runtime events
Co-authored-by: codex <codex@users.noreply.github.com>
- Add context transfer IDs, schemas, and projections
- Support cheap fork creation and Codex native fork rollback
- Cover fork idempotency and replay behavior in tests
- Track remaining projection, context transfer, rollback, capability, and subagent work
- Clarify current V2 baseline and debugger-only follow-ups
- Map fork and merge-back turns into stored handoffs and transfer resolutions
- Add shell snapshot projection support plus coverage tests
- Update replay fixtures and web contracts for the new turn flow
Co-authored-by: codex <codex@users.noreply.github.com>
juliusmarminge and others added 18 commits August 4, 2026 14:03
Co-authored-by: codex <codex@users.noreply.github.com>
… compaction (#4971)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- Disable LegendList end-maintenance that could snap after user scrolling
- Cancel stale imperative scrolls and release settled turn anchors
- Stabilize handoff run data to avoid per-event timeline rerenders
…elay

Live profiling of the built app (debugger pause inside the hot sqlite
call) showed AgentAwarenessRelay.publishThread grinding at ~8 full shell
snapshots per second after boot. Two causes:

- streamDomainEvents was eventSink.stream() with no cursor, which
  replays every stored event from genesis before going live — so each
  boot fed the relay the entire event history as fresh activity, and it
  queued a publish per activity-relevant event for hours. It now tails
  from the current high-water mark; the relay's startup snapshot publish
  already covers initial state, and the sink subscribes before reading
  the cursor so no live event is lost.
- publishThreadUnsafe materialized the full shell snapshot to find one
  thread; it now uses getThreadShell (archived/deleted map to the
  tombstone path exactly as the active-list lookup did).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A renderer performance trace showed the minimap strips as a standing
source of main-thread frame work: each strip transitioned
background-color (paint) and width (layout), and both fire constantly —
scrolling or streaming flips a band of in-view states at once, and the
hover fisheye animates several widths at a time — so any interaction
kept a 60fps style/layout/paint pipeline running.

The strip now animates only compositor-friendly properties: width tiers
are scale-x on a fixed-width box, and the in-view highlight is a bright
overlay faded with opacity. The scroll handler also skips no-op
data-in-view attribute writes, which previously re-dirtied style state
for every strip on every scroll tick.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follow-ups from the main merge:

- Migration numbering: main's 035_ProjectionThreadTitleRegeneration is
  released and keeps its id; this branch's unreleased v2 migrations shift
  to 036-044 instead (a released migration can never be renumbered).
- thread.metadata.update accepts regenerateTitle: true arms an in-flight
  titleRegeneration marker on the thread payload (requestId + startedAt),
  a landing title or explicit false clears it. The marker projects onto
  thread shells and through the client-runtime shell model, so the
  sidebar's Regenerating state works unchanged.
- New ThreadTitleRegenerationService worker reacts to armed markers on
  the live domain-event stream (so ws, MCP, and mobile dispatches all
  behave the same): builds a newest-first conversation digest from the
  v2 projection (8k-char budget, retained attachments — ported from the
  v1 reactor), generates via TextGeneration, and lands the title with a
  follow-up metadata update. Failures clear the marker and log.
- The server advertises threadTitleRegeneration again, and the client
  updateThreadMetadata dispatches regenerateTitle-only updates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The turn item materialized when a queued run is promoted was emitted
with inputIntent "turn_start", but the deterministic replay driver (and
the recorded queued_turn fixtures) expect "queued_turn" — the mismatch
stalled replay before the queued run could start, leaving run 1 waiting
and run 2 queued forever in all five queued_turn fixtures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Effect service conventions: ThreadManagementThreadNotSendableError
carried an Archived/NoSteerableRun reason union and switched on
reason._tag inside the message getter. Modelled as two error classes
(ThreadManagementThreadArchivedError, ThreadManagementNoSteerableRunError);
both still map to the MCP thread_not_sendable failure code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Prevent the title row from shifting when output is revealed
- Preserve panel and compact button sizing
…5309)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- Schema.UnknownFromJsonString -> Schema.fromJsonString(Schema.Unknown)
- SchemaIssue.InvalidValue single-argument form in checkpointDiff
- McpServerClient requires protocolVersion

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Required for follow-up requests by the 2025-06-18 MCP HTTP transport
that effect beta.103 enforces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 53f1402 to d36446e Compare August 4, 2026 12:16
juliusmarminge and others added 3 commits August 4, 2026 14:40
The thread-panel mapping change replaced the compact className on the
Run and Add controls with the isPanel conditional and dropped the
non-panel icon-compact classes that the responsive test asserts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports the deleted v1 ProviderCommandReactor title coverage onto the v2
service: marker arming/clearing via thread.metadata.update, superseded
requestId no-ops, digest-driven regeneration, the "New thread" and
unchanged-title fallbacks, generation failure, and missing initial
messages, plus unit tests for formatThreadTitleContext.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tarik02
tarik02 force-pushed the perf/orchestration-v2-projection-loads branch from 82209f3 to bc39163 Compare August 4, 2026 12:43

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit bc39163. Configure here.

Comment thread apps/server/src/orchestration-v2/Orchestrator.ts
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 3 times, most recently from 25de21d to 0af2a6e Compare August 7, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants