Skip to content

Fix review stream routing and log rendering#32

Open
lynnswap wants to merge 6 commits into
mainfrom
codex/fix-review-stream-router-log-animation
Open

Fix review stream routing and log rendering#32
lynnswap wants to merge 6 commits into
mainfrom
codex/fix-review-stream-router-log-animation

Conversation

@lynnswap
Copy link
Copy Markdown
Owner

@lynnswap lynnswap commented Jun 8, 2026

Purpose

Fix ReviewMonitor correctness and performance issues observed while running multiple reviews and streaming long reasoning logs: duplicated app-server notification consumption, fragile reasoning word-fade ownership, command lifecycle rows that could remain active, and full log reloads that made live output heavy or caused animation to stop.

Changes

  • Replaced per-review app-server notification subscriptions with a single backend-owned notification router that decodes each notification once and routes by threadID.
  • Moved per-review buffering, turn tracking, completion deferral, command lifecycle cleanup, cancellation finishing, and router metrics into session-owned state.
  • Preserved same-thread review/start serialization while allowing different threads to start and stream concurrently.
  • Made reasoning word-fade animation projection-owned by carrying explicit animation spans through append paths, including fallback suffix reconstruction.
  • Kept live reasoning stream updates append-only and avoided destructive log cap trimming while a review is still running.
  • Fixed command-output display updates so command panels appended after reasoning do not replace or erase preceding reasoning text.
  • Closed active command lifecycle rows on completion, failure, and cancellation paths so command timers stop at terminal state.
  • Applied the log cap at terminal transitions, including completion or cancellation paths that do not append a final result message.
  • Avoided duplicating the final review message when it was already logged by the stream.
  • Added regression coverage for routing, buffering, diagnostics broadcast, cancellation cleanup, command lifecycle closure, animation spans, command panel append mapping, live log cap behavior, terminal cap enforcement, and final-result de-duplication.

Testing

  • git diff --check
  • swift test --build-system swiftbuild --no-parallel
  • xcodebuild test -project Tools/ReviewMonitor/CodexReviewMonitor.xcodeproj -scheme CodexReviewMonitor -destination 'platform=macOS,arch=arm64' CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO
  • Codex review with base main: no findings

@lynnswap lynnswap changed the title Fix review stream routing and reasoning log animation Fix review stream routing and log rendering Jun 8, 2026
@lynnswap lynnswap marked this pull request as ready for review June 8, 2026 13:45
Copy link
Copy Markdown

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

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: a8a0022c5f

ℹ️ 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 on lines +389 to +392
if let threadID = payload.threadID {
guard let session = reviewEventSessionsByThreadID[threadID] else {
notificationRouterMetrics.ignored += 1
return
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route detached review-thread notifications

When review/start returns a distinct reviewThreadID, the session is still stored only under the parent threadID, so any later app-server notification whose threadId is the detached review thread will hit this guard and be dropped before decodeReviewNotification can use reviewThreadID to accept it. In that detached-review scenario the event stream never receives the started/progress/completion events, leaving the review stuck or missing its result; register an alias for run.reviewThreadID or route by both IDs.

Useful? React with 👍 / 👎.

Comment on lines +285 to +287
if let outputSourceRange = panel.outputSourceRange {
hasher.combine(true)
combine(outputSourceRange, into: &hasher)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include output content in finder supplement signatures

For collapsed command-output panels, finder text is now loaded lazily from currentSourceText via outputSourceRange, but this signature only hashes the range. If a command-output block is replaced with different text of the same UTF-16 length while the panel stays collapsed, both the displayed text and this supplement signature remain unchanged, so applyReload skips updateFinderSupplement and find/search continues using the stale output text. Include a source-text/content revision in this signature when outputSourceRange is used.

Useful? React with 👍 / 👎.

}
notificationRouterMetrics.routed += 1
await session.receive(routed)
} else if isGlobalDiagnosticMethod(notification.method) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route threadless error notifications

The router recognizes error as a review notification and decodeReviewNotification can turn it into a failed/progress event, but when the app-server sends an error payload without threadId it falls through this global-only branch and is counted as ignored. In that threadless error scenario the active review never receives the failure/retry message and can continue waiting for events; include error in the broadcast path when no thread id is present, or otherwise route it to the matching active session.

Useful? React with 👍 / 👎.

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