Skip to main content

Wework long-history responsiveness

Task control, task discovery, and transcript bodies have separate responsibilities. A conversation may contain thousands of tool steps without making history reads, terminal reconciliation, or reconnect recovery block unrelated task operations.

Incident evidence​

On 2026-11-03, two reads of one conversation in the installed build (source a19aa4b, different from the fix baseline) took 176,741 ms and 232,519 ms. The configured 75-second executor deadline fired only after the computation completed. A separate status request entered its executor handler after its client had timed out, then completed in 1 ms. Sampling captured synchronous transcript projection and JSON copies. This demonstrates missing compute isolation; it does not establish exhaustion of all Tokio workers.

The approximately 83 MiB history contained only about 12 turns, including one with 7,363 completed items. Turn-count pagination does not bound work. The old terminal coordinator requested includeFullContent: true, which walks all history pages; limit: 50 does not limit the total read.

A separate ordinary task remained running after turn_settled until an authoritative snapshot arrived about 69 seconds later, with no active Goal. This establishes delayed terminal confirmation, without attributing the entire wait to history projection.

Responsibility boundaries​

  • Consume task events and authoritative execution state first. Complete live content with authoritative terminal state needs no history repair. Necessary repairs read a bounded tail without resuming the provider session or scanning the entire conversation.

  • Stop the thinking indicator when an ordinary turn settles; authoritative state still owns task occupancy. An active Goal may continue between turns, so final text or one settled turn cannot establish that its execution is idle. A provider turn result cannot rewrite an already-final native execution outcome. Confirm local task state independently through the existing task query without waiting for body repair; project sessions retain their project-authorized read path.

  • Provider checks before stopping or compacting read current thread state and recent turn metadata without bodies or history-worker admission. An active thread's synthetic historical interrupted status cannot establish completion.

  • Publish reconnect task state before content recovery. Recover tasks independently with bounded concurrency.

  • Event-gap, reconnect, and system-resume recovery reconcile only the currently unconfirmed message IDs against explicit native turn bindings, including accepted messages outside the loaded tail. Missing bodies do not establish non-acceptance. Missing receipts retain unconfirmed sends with a diagnostic instead of automatically resending them. An empty receipt list cannot prove rejection: accepted executor work may still be queued without a turn binding. A query cannot requeue a newer send created after it started. After an executor restart, cursors earlier than the new journal's starting boundary trigger event-gap recovery instead of entering its replay window. Project and cloud sessions pass receipt queries and results through their existing authorization path.

  • Normal history uses item cursors and item/byte budgets. Long turns remain pageable. Full export is explicit and never a prerequisite for terminal state. Automatic pagination tracks the opaque beforeCursor directly. An unchanged cached first item does not mean the cursor stopped. Stop automatic requests and retain manual recovery only when neither the cursor nor the display boundary advances. Building a native rollout offset index initially still scans its file on a cancellable isolated worker. Later reads update the index incrementally and load only the selected page's item bodies. Rollout cursors bind to source-file identity and the length and digest of a fully indexed prefix, rather than an in-memory index instance. Rebuilding after cache eviction or process restart validates old cursors during that scan. Appends retain old boundaries; file replacement or rewriting indexed content rejects old cursors. Digests advance within the existing scan without rescanning complete files for ordinary pagination. Explicit historyMode=legacy threads use the shared legacy projection of their canonical rollout instead of the unsupported thread/items/list API. Ordinary pages retain at most 100 item bodies and 2 MiB, allowing one oversized item alone. Record-level cancellation preserves synthetic IDs, rollbacks, and late terminal metadata. Each legacy page still scans metadata to EOF; it does not have the incremental index's read cost.

  • Preserve content and ordering. The page byte budget permits one oversized item alone through existing lossless chunks. It is not a strict per-body memory bound. A strict bound requires a separate body-reference/hydration contract, rather than silently truncating content or rejecting valid conversations.

  • Run projection in a bounded worker pool. A worker owns its permit until it actually exits. Dropping the asynchronous caller signals cancellation, checked at bounded item checkpoints; dropping a JoinHandle alone does not stop work.

  • Native history pages read lightweight task metadata and select page-related prompts and interaction overlays before copying bodies. Never clone the entire transcript cache under the shared task lock. Filter completed active-turn items before cloning the bodies needed to supplement the page.

  • Identical conversation/range/options reads share work. Each viewer owns its subscription; cancel the provider only when the last subscriber leaves.

  • The new IPC cancellation and admission contract applies only to runtime.tasks.transcript requests owned by the same authenticated connection. Search endpoints retain their existing contract. Ordinary concurrent reads wait in FIFO order instead of failing as soon as both active slots are occupied. Waiting remains subject to the existing deadline, disconnect, and cancellation; an expired queued request cannot start computation. HTTP cancellation cannot establish that a send or another action was not accepted; retain message identity and idempotency semantics. Existing search and search-result context computation paths are outside this isolation change; cooperative cancellation is not guaranteed for all of their blocking work.

  • A read deadline, cancellation, or busy response is local operation state, not evidence that the executor process stopped.

  • Task lists distinguish initial loading, successful empty, refresh, and failure. Keep successful same-scope data during refresh failure. A same-owner reconnect or token refresh replaces request generations without clearing the selected project, conversation, or navigation and without unmounting active collaboration panels. Remote task and device caches share the backend/account scope. Older cache entries without backend identity cannot hydrate a new backend, and an old request cannot abandon synchronization owned by the new scope. List and device responses own discovery data, not profile or preference updates: they cannot overwrite the current account's newer model selection with an older user snapshot. Explicit profile and preference updates own that state. Clear old snapshots on backend or account changes and reject late responses from previous scopes. Electron's local authentication user can differ from the connected cloud account. Navigation refresh uses the same workbench identity as runtime services; it must not write the local authentication user into connected-account state and rely on a later effect to correct it. The workbench component, shared lifecycle store, and persisted lifecycle namespace use the same backend/account identity. Replace them together on an owner change so summary lookup cannot recover an old task or seed a new store from old reducer state. Same-owner token refresh retains them. Do not migrate old lifecycle storage that lacks backend/account ownership. Read and write the last selected project under the complete backend/account key, rather than the local login or a numeric cloud user ID that another backend can reuse. Global notification sources and interaction history, drafts, and acceptance records use that same backend/account scope, so an unchanged local login cannot retain the previous cloud account's counts or replies. Candidate connection configuration stays local to the authorization attempt until success publishes it with the authenticated account. Failure must not combine an old account with a candidate backend or unmount the connection dialog that owns its error and recovery actions. Candidate progress is independent of the active connection: retain its token and services throughout authorization and after candidate failure. Expired active credentials recreate the workbench for the local owner, so cloud panes never call local services under the previous cloud identity. Native refresh credentials are staged as a candidate until its account is validated. Failure or cancellation discards only that candidate; a successful authorization poll must not overwrite or delete the active owner's credentials. Every refresh carries its expected account, and native credentials must match both backend and account. Older credentials without an owner require an actual refresh and /users/me validation before binding or returning an access token. Once native commit issues the atomic replacement, a later pending candidate cannot revoke that owner. Publish in commit order; disconnect independently invalidates old commits so delayed acknowledgements cannot restore a signed-out account.

  • Collaboration navigation distinguishes unsettled, settled partial, and complete caches. Creating a workspace or project adds its target without marking source discovery complete. A route change shows that target immediately and completes unsettled catalogs so a late local workspace can still appear. Settled partial caches retain covered targets when a cloud source fails.

  • Built-in browser device emulation holds a shared debugger session for its entire lifetime. Page reads and file uploads hold temporary sessions only for their own operations; completing either must not detach CDP while emulation remains active. Serialize device-metric set and clear operations, and release ownership on close so concurrent operations cannot silently reset the viewport.

Verification contract​

ScenarioRequired result
One turn with 7,000+ tool itemsBounded normal reads; cursor traversal preserves all items and their order
Status during heavy history workControl requests proceed without waiting for projection
Transcript deadline, disconnect, view exitTranscript work cancels; permits release after actual computation exit
Two shared viewers, one exitsThe remaining viewer receives its complete result
Old completion overlaps a new sendThe old result cannot settle or overwrite the new turn
Initial/refresh list failureLocal error and retry; no false empty state or discarded valid data
Refresh overlaps account switchIndependent results publish promptly; old responses cannot cross scopes
Same-account reconnect overlaps preferencesRetain project, conversation, and new model selection; reject old transport results
Create and open a cloud project or empty workspace during navigationShow the target immediately and include the local catalog when it arrives

Run focused Rust, component, and protocol tests locally. Desktop regression coverage uses the existing CI checkpoint runner. Repository policy requires an explicit request before local E2E or ai:verify execution.

Desktop CI queries health, task state, task discovery, and renderer snapshots concurrently with real transcript transfer. Each control query must complete within three seconds. Restore full history through UI pagination while retaining existing large-output and content-integrity assertions. Observe the request boundary after completion to reject automatic full-history scans and confirm that the thinking indicator disappears. Receipt recovery reuses the existing active reply: explicitly enqueue through the UI, then release that reply so the real queue controller sends the message. An idle direct send is not a queued message. Retain the two Electron restarts and add one real executor SIGTERM followed by supervisor recovery.

Diagnostics include request IDs and stage durations: client send, IPC receive, admission, provider read, projection, encoding, queue, and client receipt. Record counts, byte sizes, and state without bodies, credentials, or session contents.