Skip to content

fix(web): keep reply playback hooks stable during chat hydration - #202

Open
leoisadev1 wants to merge 1 commit into
mainfrom
fix/group-reply-playback-hook-order
Open

fix(web): keep reply playback hooks stable during chat hydration#202
leoisadev1 wants to merge 1 commit into
mainfrom
fix/group-reply-playback-hook-order

Conversation

@leoisadev1

Copy link
Copy Markdown
Member

Problem

Cold-loading a group chat could show “This view failed to load” with React error 310. The reply-playback hook ran after an early return, so hydration changed the hook order. Bot hydration and archive transitions had the same defect.

Fix

Call the existing playback hook before the missing/archived entity guards in both chat views. Preserve message filtering, playback context, and the existing disabled stored-reply controls. Add regression tests for hydration and reverse transitions.

Verification

  • All three new real-React regressions fail on the unchanged base and pass with the fix.
  • 16 focused tests pass, plus targeted lint, formatting, web typecheck, and production build.
  • Isolated browser verification reproduces the original group reload crash, then verifies cold group and bot reloads, bot/group navigation in both directions, message-menu open/close, and unchanged disabled read-aloud behavior.
  • Group checks pass at 1440px and 390px with no browser exceptions. This covers the shared web/desktop renderer; mobile uses a separate unconditional hook and is unchanged.
  • No provider calls or live user data were used.

Before and after screenshots are attached below.

Implemented and verified by gpt-6-astra in T3 Code through the Grok harness.

prg-hook-order-before

prg-hook-order-after-1440

prg-hook-order-after-390

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
akeru-bot-landing Skipped Skipped Sep 8, 2026 8:22pm UTC

Request Review

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S labels Sep 8, 2026
@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

Greptile Summary

Summary

  • Unavailable bot and group landings can retain reply-playback state after they stop rendering.
  • A later assistant reply can then be played for a roster target that is no longer available.

Merge safety

Do not merge until unavailable roster targets clear their reply-playback context and messages. This is an explicit repository requirement.

Confidence Score: 4/5

Not safe to merge: unavailable roster targets can remain active in reply playback, contrary to the repository requirement.

The reproduced issue is limited to retained reply-playback state for unavailable bot and group landings.

Files Needing Attention: apps/web/src/components/roster/BotThreadLanding.tsx and apps/web/src/components/roster/GroupThreadLanding.tsx

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a proof for a posted P2 finding and linked it to the reviewer’s comment.
  • T-Rex produced a second proof for another posted P2 finding, referencing its review comment.
  • Validated the contract behavior that playback starts for the retained thread when a new assistant reply occurs after the landing target becomes unavailable under synthesis-enabled readout.
  • Confirmed that supplying null context or no messages is required to prevent the playback behavior; merely returning null from the component does not suppress hook effects.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (2)

  1. apps/web/src/components/roster/BotThreadLanding.tsx, line 213-218 (link)

    P2 Clear hidden playback context

    When a bot is missing or archived, this component returns null but still supplies its retained thread reference and messages to reply playback. A later assistant reply can therefore start playback for a roster target that is no longer visible. The group landing has the same behavior. Keep the hook unconditional for hook-order safety, but provide a null context and no observable messages when the target is unavailable. This violates the repository directive for unavailable roster targets, and the requirement must be satisfied before merging.

    Context Used: Any issues please mention them and give each small... (source)

    Knowledge Base Used: Web workspace interaction

    Artifacts

    Evidence from the check

    • The authored focused ReactDOM test mocks retained linked-thread runtime state and asserts playback context and messages are still passed while the unavailable landing returns null; it demonstrates the retained input path.

    Command output from the check

    • The captured command output shows the focused web test completed with 3 passing tests for missing bot, archived bot, and missing group states; it confirms the components retain playback inputs.

    Evidence from the check

    • The authored runtime session test compares retaining a linked playback context with clearing it before observing a later assistant reply; it demonstrates why null context is required to suppress automatic playback.

    Command output from the check

    • The captured command output shows the focused client-runtime session test completed with 2 passing tests; it confirms retained context starts automatic synthesis and cleared context does not.

    View artifacts

    T-Rex Ran code and verified through T-Rex

    Fix in Claude Code

  2. General comment

    P2 Unavailable roster landings keep reply playback active for retained threads

    • Bug
      • When a bot is missing or archived, or a group is missing, the respective component returns null but still calls useReplyPlaybackThread with runtime.linkedThreadRef and visible runtime messages. The focused component test observed calls to setContext for thread-bot/thread-group and observe([message]) in all unavailable cases. The session test then showed a later assistant message starts automatic synthesis while this context remains set.
    • Cause
      • BotThreadLanding invokes the hook at lines 213-218 before its unavailable return at line 220; GroupThreadLanding invokes it at lines 91-96 before its unavailable return at line 98. useReplyPlaybackThread sets a non-null session context whenever both IDs are present and independently observes messages. The playback session processes new messages whenever its scope remains non-null.
    • Fix
      • For unavailable targets, pass null environmentId/threadId and an empty message list to the hook, or make the hook receive an explicit inactive state that calls session.setContext(null) and avoids observation. Preserve unconditional hook invocation to maintain hook order.

    T-Rex Ran code and verified through T-Rex

Fix all with Greploop Fix All in Claude Code

Reviews (1): Last reviewed commit: "fix(web): keep reply playback hooks stab..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant