Skip to content

[fix] Waiting cards refuse transcript adoption without proof they ended - #5942

Merged
mmabrouk merged 1 commit into
release/v0.112.0from
fix/adoption-guard-waiting-card
Aug 11, 2026
Merged

[fix] Waiting cards refuse transcript adoption without proof they ended#5942
mmabrouk merged 1 commit into
release/v0.112.0from
fix/adoption-guard-waiting-card

Conversation

@mmabrouk

Copy link
Copy Markdown
Member

Context

After #5919, the user-request form card in the agent chat kept refreshing while the user typed, and the typed input was lost. The chain: the browser now re-reads the conversation from the server the instant a card parks (the new interaction-event listener). The guard that should protect a waiting card during that re-read counted any server part it could not recognize as "settled". But the server's replay of a freshly parked card is built from the durable record's harness-wrapped tool name (mcp.agenta-tools.request_input) with no render marker, so the guard failed to recognize it, wrongly concluded the card had ended, and let the server copy replace the live chat. The replacement carries different internal ids, so React remounted the form widget and destroyed the draft. A background poll repeated this.

Changes

settledLocallyWaitingIds now demands positive proof that a waiting card ended before it counts as settled: the server part sits in a terminal state (output-available, output-error, output-denied), or the card's interaction row has moved past pending (responded, resolved, cancelled). A part that is present but merely unrecognized now refuses adoption, exactly as an absent part always did.

The no-growth adoption path (which retires zombie cards in dead sessions) additionally refuses while any waiting card's row still reads pending. In a dead session the row is terminal, so that path keeps working; for a freshly parked live card the row is pending, so the card can no longer be swept away.

To make row evidence available, SessionTranscript now carries the interaction rows the transcript was replayed against (loadSession.ts already fetched them; it stopped discarding them). Rows and messages always come from the same fetch, so the two kinds of evidence cannot disagree across generations.

Before: a parked form card was replaced seconds after appearing, and typing was lost.
After: the card is replaced only when the server positively shows it ended.

Tests

  • 7 new tests in useSessionHydration.test.ts, derived from the real arabicPoetrySession golden records cut at the exact record boundary that reproduces the unrecognizable replay. With the old guard logic, the three refusal tests fail; with the new logic all 26 pass.
  • Zombie-card non-regression is covered twice: the pre-existing settled-card test and a new golden-backed test with a real cancelled row.
  • Full AgentChatSlice suite: 346 passed. @agenta/entities: 974 passed. Mobile transcript adoption: 6 passed.
  • Reviewed adversarially (row-join parity with replay, terminal-status vocabulary against the API, sweep timing for cancelled, fetch-failure degradation): no confirmed defects.

What to QA

  • Start an agent chat that raises a form card. Type into the form slowly for ~20 seconds. The card must not refresh or lose the text.
  • Answer the form. The run resumes and the answered card stays answered after a reload.
  • Regression: open an old session whose form card was already answered or abandoned. The card must show as ended, not live (this is the zombie-card behavior from feat(sessions): record card answers first and give replay one rule #5919 that had to survive).

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Aug 11, 2026
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
agenta-documentation Blocked Blocked Aug 11, 2026 2:57pm

Request Review

@dosubot dosubot Bot added bug report Something isn't working frontend labels Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved session restoration for conversations containing waiting or in-progress tool interactions.
    • Pending interaction cards now remain visible until the session provides clear completion evidence.
    • Completed interactions are restored correctly, including terminal results replayed from prior sessions.
    • Prevented incomplete server transcripts from prematurely replacing locally displayed waiting states.

Walkthrough

Session loading now carries interaction-row states into hydration. Transcript adoption uses terminal and pending row states to settle or retain local client-tool cards. Regression tests cover replay and no-growth cases.

Changes

Session hydration

Layer / File(s) Summary
Transcript interaction-state loading
web/oss/src/components/AgentChatSlice/assets/loadSession.ts
SessionTranscript now includes optional interactionRows. Initial and refreshed transcript loads populate the field.
Row-aware transcript adoption
web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.ts
Hydration tracks interaction-row states when settling local client-tool cards. Pending rows block adoption, while terminal rows or terminal parts permit adoption.
Hydration replay regression coverage
web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.test.ts
Fixture-based tests cover pending, missing, terminal, no-growth, and terminal replay states.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant adoptServerTranscript
  participant loadSession
  participant shouldAdoptTranscript
  adoptServerTranscript->>loadSession: Load SessionTranscript
  loadSession-->>adoptServerTranscript: Return messages and interactionRows
  adoptServerTranscript->>shouldAdoptTranscript: Evaluate transcript adoption
  shouldAdoptTranscript-->>adoptServerTranscript: Adopt or retain local cards
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states that waiting cards must not adopt transcripts until there is evidence that they ended.
Description check ✅ Passed The description directly explains the waiting-card replacement bug, the evidence-based adoption fix, tests, and QA expectations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/adoption-guard-waiting-card

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.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/oss/src/components/AgentChatSlice/assets/loadSession.ts (1)

61-70: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Load interaction rows for the refreshed record snapshot.

Line 64 builds refreshed messages with interactionRowStates captured before refreshed resolves. Line 69 forwards that stale state to adoption.

If a row changes from pending to terminal during record revalidation, the refreshed transcript can still block adoption of the settled card. Fetch a matching current row snapshot for fresh, or return records and interaction rows as one refreshed snapshot. Add a race regression test.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 575027f9-d6f1-4d93-8caf-0e79de20bb21

📥 Commits

Reviewing files that changed from the base of the PR and between a9c18ac and e8ea70e.

📒 Files selected for processing (3)
  • web/oss/src/components/AgentChatSlice/assets/loadSession.ts
  • web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.test.ts
  • web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.ts

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

lgtm

@mmabrouk mmabrouk added the lgtm This PR has been approved by a maintainer label Aug 11, 2026
@mmabrouk
mmabrouk merged commit dc680ca into release/v0.112.0 Aug 11, 2026
37 of 38 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-pr-5942.up.railway.app/w
Project agenta-oss-clone-spike
Image tag pr-5942-f48f7bf
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-08-11T15:07:45.281Z

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

Labels

bug report Something isn't working frontend lgtm This PR has been approved by a maintainer size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant