Skip to content

feat(app): paginate long histories and recover stalled sessions - #90

Merged
acking-you merged 5 commits into
mainfrom
chore/codex-upstream-sync
Sep 5, 2026
Merged

feat(app): paginate long histories and recover stalled sessions#90
acking-you merged 5 commits into
mainfrom
chore/codex-upstream-sync

Conversation

@acking-you

@acking-you acking-you commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Summary

Long conversations now load history a page at a time, and failed app-server requests no longer leave the UI reporting a dead connection as ready. This PR completes the follow-up work from the thread-list stall handoff:

  • Load paginated threads through upstream turn/item APIs, retain the legacy full-history path, and fetch older items or an unloaded turn on demand. Fix the continuation cursor for a single long turn and parse upstream user-message text. Add the corresponding FRB bindings and cap concurrent sidebar summaries. See crates/pocket-codex-bridge/src/engine/app_session.rs and crates/pocket-codex-bridge/src/api/bridge.rs:577.
  • Close and drain pending RPCs consistently on transport failure or timeout, cover writer-lock waits with the deadline, and remove cancelled requests. Reconnect only reports success while the new connection remains healthy. Adopted processes and existing host watchdogs must pass initialize plus thread/list within one budget. See crates/pocket-codex-codex/src/client.rs:253, crates/pocket-codex-codex/src/readiness.rs:244, and apps/flutter/lib/src/screens/app_session_screen.dart:1179.
  • Preserve a still-valid relay credential while renewal stalls or fails, separate network serialization from cache reads, and replace the cache only after a successful response for the same account. Actual expiry and account isolation still apply. See crates/pocket-codex-bridge/src/engine/account.rs:500.
  • Add middle-button autoscroll to the transcript and restore the turn rail's width when the pointer leaves the tick or preview card, including transparent space in the expanded hit area. See apps/flutter/lib/src/widgets/middle_click_scroll.dart:13 and apps/flutter/lib/src/widgets/turn_minimap.dart:371.
  • Include RPC diagnostics, an isolated app-server probe, a real Windows/relay integration test, and the handoff evidence. Include the Windows submodule initialization scripts, updating their check for the current Codex-only submodule layout and using a per-command HTTPS fallback.

The branch incorporates current main, including its Windows release-build stability fix. The Codex dependency update from #89 is already on main and is not repeated in this PR's diff.

Review follow-up

The initial eight review findings are addressed. History pages now merge by turn order with shared item IDs anchoring overlapping pages. A partially loaded turn remains navigable, selection waits for an in-flight prefetch and list layout, and request generations prevent stale completions from affecting another conversation. Programmatic rail jumps do not trigger older-page loading that shifts the target. Live turns join the snapshot-based rail and count.

All enumerated turn timestamps are retained for initial, older-page, and single-turn reads. Summary calls use an async FRB entry point and a separate blocking executor, so they occupy no interactive FRB worker slots even on a single-core device. Logs rotate hourly and prune every minute, including while idle in the tray. Ten Flutter tests and four Rust tests cover these cases.

Type of change

  • feat — paginated history and middle-button autoscroll
  • fix — connection recovery, relay renewal, and turn-rail hover
  • Other — diagnostics, regression coverage, handoff documentation, and Windows initialization helpers

Userspace impact

  • Adds to the FRB API surface in crates/pocket-codex-bridge/src/api/.
  • Changes a documented CLI flag, subcommand, or output format.
  • Changes account configuration or persisted session formats.
  • Changes the upstream JSON-RPC protocol, Responses API, or relay key format.

The bridge adds older-history/turn-item operations and history metadata; generated Rust and Dart bindings are included together. Legacy threads retain their existing history-loading path. Diagnostic logs are written under the application's support directory with six-hour retention. No user migration is required.

Hosted mode still uses the backend for credential issuance and renewal; this PR does not persist relay credentials across app restarts or change their TTL or TLS validation. Session data continues to travel directly through the relay.

Tested

  • Full first-party Rust formatting check, with -- --config newline_style=Auto for the existing Windows CRLF checkout. No formatting or linting of deps/.
  • WSL: cargo clippy --workspace --all-targets --locked -- -D warnings.
  • WSL: cargo test --workspace --locked293 passed, 6 ignored after the review fixes.
  • Windows: cargo check -p pocket_codex_bridge --locked, exercising the embedded Codex path.
  • Flutter 3.44.0: pub get, dart format --output=none --set-exit-if-changed lib test integration_test, and analyze.
  • Flutter tests — 435 passed, 3 skipped after the review fixes.
  • Native Windows integration test through a temporary pb-mapper relay and real app-server using isolated history copies: repeated list/open operations; paginated → legacy → paginated rendered 100/82/100 items, then loaded 41 older items.
  • Windows Release build using pubspec-desktop.yaml; verified bundled fonts, themes, close-to-tray behavior, and single-instance restore. The latest Release launches and displays real account history.
  • After the review fixes: native Windows Profile build using pubspec-desktop.yaml completed successfully, including the regenerated async bridge and embedded Codex. Verified Figtree, Geist Mono, and Noto Sans SC in the output. The default mobile manifest was restored after the build.
  • PowerShell initialization script syntax and the pinned Codex submodule status checked; git diff --check passes.

The new middle-button and hover behaviors are covered by widget tests, including the real session screen and virtual list. Native pointer automation was stopped when it detected active user input, so a physical mouse verification of those two interactions is not claimed.

The original long-lived Mac process's internal thread/list stall was not reproduced locally, and its root cause remains unconfirmed. Regression tests do reproduce dead RPCs despite Pong traffic, unhealthy process adoption, misleading reconnect readiness, pagination defects, and stalled/failed credential renewal. Details and reproduction instructions are in design/HANDOFF-thread-list-stall.md:1. Local history copies and validation logs are excluded from the commit.

Linked issues

Follow-up to #89 and design/HANDOFF-thread-list-stall.md.

Sync checklist

  • Public Rust items have documentation; no unjustified production unwrap() / expect() added.
  • Rust and Dart FRB bindings are included together and were compiled in the Windows desktop build.
  • No formatting, linting, or rewrite commands were run against deps/.
  • This is follow-up work within the existing Flutter/embedded-host roadmap; no new roadmap milestone is declared.

acking-you and others added 4 commits September 1, 2026 14:52
Opening an existing conversation could fail with errors from the vendored
codex thread-store: "unknown variant `completed`" for a stored
SubAgentActivity item, and "invalid paginated history lineage: cycle
detected". Neither was our bug. Codex Desktop writes ~/.codex with a newer
schema than deps/codex was pinned to, so our reader rejected records whose
variants it lacked.

Upstream already carries the reads: SubAgentActivityKind::Completed
(openai/codex#40437), RolloutItem::RealtimeItem (#40508), and
SessionMeta.forked_from_ordinal_exclusive (#40987), which decouples a
thread's logical fork boundary from its physical history_base so a
paginated thread survives revert.

Merged rather than rebased, matching the two prior upstream syncs. The
Windows console-suppression and ConPTY adaptations carried over without
conflict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paginated threads reject a whole-history read, so opening one failed
outright after the codex bump. They now load a bounded tail plus a
skeleton of every turn, and the transcript fills in on demand:

- `thread_read` branches on `historyMode`. Paginated threads walk
  `thread/turns/list` + `thread/items/list`; legacy threads keep the
  whole-history read, which is the only shape their rollout supports.
- New `thread_older_page` / `thread_turn_items` continue backwards and
  fetch one turn, for scrolling up and for jumping via the rail.
- Cursor walks copy upstream's `advancing_cursor`, so a server that
  repeats a cursor ends the walk instead of looping forever.
- Items come from bounded item pages, never `itemsView: "full"`, which
  makes the server walk each turn's items in nested loops inside one
  request — a turn with hundreds of items blew past the request timeout.
- `thread_summary` reads a summary view instead of the whole transcript
  for one sentence.

The turn rail now draws from the turn skeleton rather than the loaded
rows, so a long conversation shows its true length immediately instead
of growing as history arrives. Hovering an unloaded tick prefetches it;
the skeleton already carries the preview text, so previews cost nothing.

Also lands the log plumbing that made this diagnosable: captured lines
mirror to `<support>/logs/` with 6-hour retention, and every JSON-RPC
call records its direction, duration, size and in-flight depth. Three
rounds of reading code had blamed the wrong thing each time; the log
found the real stall on the first try.

`design/HANDOFF-thread-list-stall.md` documents an unrelated outage
found along the way — `thread/list` never answers on a long-lived
adopted app-server, so the client times out and reconnects every 72s.
Root cause unconfirmed; the doc records the evidence, the leading
hypothesis, and the dead ends.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T16:18:54.935737Z 378c2d2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 378c2d267b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/flutter/lib/src/screens/app_session_screen.dart Outdated
Comment thread apps/flutter/lib/src/screens/app_session_screen.dart Outdated
Comment thread apps/flutter/lib/src/screens/app_session_screen.dart
Comment thread crates/pocket-codex-bridge/src/engine/app_session.rs Outdated
Comment thread crates/pocket-codex-bridge/src/engine/logging.rs Outdated
Comment thread apps/flutter/lib/src/screens/app_session_screen.dart Outdated
Comment thread apps/flutter/lib/src/providers.dart Outdated
Comment thread apps/flutter/lib/src/screens/app_session_screen.dart Outdated
@acking-you
acking-you merged commit e54741b into main Sep 5, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant