Skip to content

Recover terminal chat when transcript files are replaced - #16045

Merged
teamleaderleo merged 5 commits into
mainfrom
fix/cloud-transcript-file-replacement
Sep 30, 2026
Merged

teamleaderleo merged 5 commits into
mainfrom
fix/cloud-transcript-file-replacement

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

An atomically replaced terminal transcript can have the same or a larger size than the old file. Agent Chat currently keeps the old byte offset: a same-size replacement is invisible, and a larger replacement can skip its first records. This leaves Cloud terminal chat stale even though the source file changed.

Track file device/inode identity and confirm the opened file's stats before using its offset. On replacement, reset byte and UTF-8 decoding state and read using the existing bounded initial window (8 MiB by default). Unchanged files retain the stat-only polling path.

A file reset also resets the transcript parser and replaces displayed history. Subscribed views receive an empty authoritative history before replacement events, so copied Codex history is shown once and removed content does not remain in the view. In-place truncation uses the same history reset; transcript path changes reuse the server's shared reset path. This covers atomic replacements and observed shrinkage; same-inode rewrites that grow between polls are outside this detection rule.

Validation

  • From agent-chat, the focused command is bun test test/transcript-replacement.test.ts.
  • First red regression: e54f0021e0ed1259b68f8bf8ff9e7701ac731041 — six failures, including a missed same-size replacement and skipped first records after a larger replacement.
  • History reconciliation regression: 4151a9da08f3e346ba874a87202c72c9ccd4e093 — three failures, showing stale displayed content and duplicated copied Codex history after the reader resumed.
  • Green: acd284567484b77fbaca6e78b6f4446da98cf72a — all 11 focused tests pass. Real file renames cover identical size/mtime, larger and empty replacements, split UTF-8 decoding, bounded replay, and continued appends. Both Claude and Codex attachment paths are exercised. The production server reset/event paths are driven through a subscribed socket fixture, verifying history-before-event ordering and reset generation metadata.
  • bun run check passed TypeScript, 23 script suites, and 55 Bun tests across 14 files. Both production browser entrypoints bundled successfully; git diff --check 304d3468debbcc21d3c691392404f46607aba77d..HEAD passed. Bundle output stayed under the worktree's disposable scratch/build-check.
  • No live terminal agent or Cloud instance was used. The sparse checkout omits the root verifier, so verification used the affected package. No UI copy or localization keys changed.

Changelog

Fixed Cloud terminal chat missing replaced transcripts or duplicating copied history when following the replacement file.


Summary by cubic

Fixes Cloud terminal chat missing transcripts when the source file is atomically replaced, by tracking file identity (dev/ino) instead of relying on size/mtime alone.

  • On replacement, reading restarts from the bounded initial window (8 MiB by default) and UTF-8 decoding state is cleared.
  • Subscribed views receive an empty history before replacement events, so replayed events replace instead of duplicate the displayed history.
  • Stops and disposal now fence in-flight reads by generation, so late filesystem results can’t deliver events, rename the view, or update status after a session is redirected or disposed.
  • Same-inode truncation and transcript path changes reuse the same reset path.

Written for commit 09ab33c. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 8 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 583d90f6-94b4-4e08-ba5d-ce24a56d929f

📥 Commits

Reviewing files that changed from the base of the PR and between d1ec789 and 09ab33c.

📒 Files selected for processing (5)
  • agent-chat/adapters/transcript.ts
  • agent-chat/server.ts
  • agent-chat/test/transcript-disposal.test.ts
  • agent-chat/test/transcript-replacement.test.ts
  • agent-chat/types.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review: codex review at acd2845 found no actionable regressions; transcript replacement and parser reset tests pass. Fixed: none needed. Left: none.

* test: reproduce late transcript events after disposal

* fix: fence transcript reads after stop and disposal
@teamleaderleo
teamleaderleo enabled auto-merge (squash) September 30, 2026 15:48
@teamleaderleo
teamleaderleo merged commit 3dcf462 into main Sep 30, 2026
53 checks passed
@teamleaderleo
teamleaderleo deleted the fix/cloud-transcript-file-replacement branch September 30, 2026 15:53
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for 09ab33ca5c, merged 2026-09-30 15:53:49 UTC

  • Not verified at merge: CI timing (in progress)
  • Verified: ci-status, Web complexity, web-validation, CI fast guards, Fast static checks, guards (19), linux-preflight, Testbox broker trust boundary, tests
  • Skipped by policy: browser, Claude wrapper regressions, Dogfood build #​${{ github.event.pull_request.number }}, GhosttyKit release check, macos, macOS admission gate, remote-daemon, suite-coverage, ui-tests, web, web-build, web-database-tests, and 1 more
  • Full suite: runs on main after merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 30, 2026
e709b69 fix(cloud): stop reconciling panes a Cloud workspace already shows (manaflow-ai#16025)
d13dde3 Diff viewer: viewed state, file filter, generated and large diffs collapsed (manaflow-ai#15536)
e0d5c5e test: pay the Pi fixtures' first exec before timing them (manaflow-ai#16028)
e2e0b61 ci: disable unstable UI test dispatch lane (manaflow-ai#16075)
15996b0 ci: sweep side lanes instead of rescuing workflow runs (manaflow-ai#16076)
3dcf462 Recover terminal chat when transcript files are replaced (manaflow-ai#16045)
272d069 fix(agent-chat): let Stop cancel a queued or starting ACP turn (manaflow-ai#15925)
30bd116 test: cover invalid unquoted Xcode extension paths (manaflow-ai#16054)
a24a1b5 Make GitHub references in the agent chat transcript clickable (manaflow-ai#15916)
86d1cfc Reap failed Codex app-server startups before retrying (manaflow-ai#15977)
890cd1e fix(sidebar): expose workspace close button to accessibility (manaflow-ai#15965)
faf4c8f docs: define agent fan-out and reusable Cloud work environments (manaflow-ai#15836)
ab20b79 ci: cut cmux-tui Testbox warmup hold time (manaflow-ai#15557)
31fb228 Promote devbox images with cmux-tui 7d17754 (VT replay blank-cell fix) (manaflow-ai#16072)
e0da0a6 feat(acp): cmux as a read-only ACP host, phase 1 (manaflow-ai#15976)
3ed1d77 Reap failed ACP startups and temporary catalog probes (manaflow-ai#15979)
f5c3567 Add a Focus TextBox Input item to the View menu (manaflow-ai#15730)
b3a1ca1 Document the 32 CLI verbs the contract table was missing, and guard it (manaflow-ai#15993)
3bba04e Say which app-host result file could not be read (manaflow-ai#15997)
7ef6d3a Resume Cloud Codex chats after app-server restart (manaflow-ai#15915)
a803f36 fix: surface simulator process output reader failures (manaflow-ai#15880)
f6a0163 Keep terminal approval notices from moving the composer (manaflow-ai#15886)
b8ab767 test: isolate feature flag defaults between runs (manaflow-ai#15587)
5150a9b Keep unsent cloud prompts recoverable (manaflow-ai#15902)
233bd6d Restore terminal attention when transcript chat reconnects (manaflow-ai#15891)
573f998 Resolve a dogfood menu path against the direct children of each open menu (manaflow-ai#15923)
7b7a1b2 test(ci): assert the registry guard's exit code, and handle merge_group (manaflow-ai#16017)

# Conflicts:
#	.github/workflows/ci-guards.yml
#	.github/workflows/ci-owned-pool-rescue.yml
#	.github/workflows/ci-ui-tests.yml
#	.github/workflows/ci.yml
#	.github/workflows/cmux-tui-testbox-warmup.yml
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