Skip to content

[Fix] Pending question panel stays answerable when the reported phase flips - #33

Merged
daniel-lxs merged 1 commit into
developfrom
fix/pending-question-panel-not-phase-gated
Jul 9, 2026
Merged

[Fix] Pending question panel stays answerable when the reported phase flips#33
daniel-lxs merged 1 commit into
developfrom
fix/pending-question-panel-not-phase-gated

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

What problem this solves

Second fix from the steering/questions test pass (repro: task 11nl0xsy05oyl on openmote). The request_user_input panel was rendered only while taskPhase === 'waiting_for_user_input'. A queued or steered follow-up flips the reported phase back to running while the harness turn is still blocked inside the question tool — the question disappeared from the UI with no way to answer it, deadlocking the task ("Working" forever, message queued forever).

What changed

  • Panel visibility now tracks the live pendingUserInputRequests list instead of the task phase. The runtime clears pending requests on answer, cancel, and turn teardown, so the list is self-correcting.
  • The prompt input's free-text answer routing keys off the active pending request for the same reason — in the desynced state, typed text must answer the visible question rather than being sent as a regular message.
  • Dropped the now-unused taskPhase plumbing from both spots.

Complements #32 (web sends steer the active turn): #32 makes the deadlock much harder to reach from the web path; this one makes the question panel correct regardless of how the phase and queue got into that state. The PRs touch different hunks of PromptInput.tsx and merge cleanly in either order.

Validation

  • New PendingUserInputRequestPanel.client.test.tsx: pending question renders regardless of reported phase; empty state renders nothing.
  • Full src/app/(sandbox)/task/ suite green (478 tests); pnpm lint:fast and pnpm check-types:fast clean.

🤖 Generated with Claude Code

… flips

The request_user_input panel (and the free-text answer path in the
prompt input) were gated on taskPhase === 'waiting_for_user_input'.
A queued or steered follow-up can flip the reported phase back to
running while the harness turn is still blocked inside the question
tool - in that state the question vanished from the UI and could never
be answered, deadlocking the task.

Visibility now tracks the live pendingUserInputRequests themselves,
which the runtime clears on answer, cancel, and turn teardown. The
free-text answer routing keys off the active pending request for the
same reason.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@roomote-roomote-v1

roomote-roomote-v1 Bot commented Jul 9, 2026

Copy link
Copy Markdown

1 issue outstanding. See task

  • apps/web/src/app/(sandbox)/task/[taskId]/PendingUserInputRequestPanel.tsx:158 now renders every request left in the client pending list, but the cancel/session-error paths only clear the worker-side map and emit TaskAborted; the client never removes the matching pendingUserInputRequests. After cancelling a visible question, the stale request remains answerable, and free-text submissions can be swallowed as answers to an unknown request instead of being sent as normal prompts.

@daniel-lxs
daniel-lxs marked this pull request as ready for review July 9, 2026 15:22
@daniel-lxs
daniel-lxs merged commit 3f57a00 into develop Jul 9, 2026
1 check passed
daniel-lxs added a commit that referenced this pull request Jul 9, 2026
…ion panel fixes

Three issues from the openmote reviews of #33 and #37:

- The history rebuild no longer resets the protocol service's auxiliary
  lookups: rebindMessages re-points only the id/position indexes, so the
  pending request_user_input map populated from history survives a
  refetch and a subsequent live response still masks secret answers.
- Todos now converge to the fetched history whenever it carries plan
  state, including an intentionally empty list, instead of falling back
  to stale live todos.
- A taskAborted status (cancel or terminal session error) drops the
  client-side pending user input requests, matching the worker-side
  clear, so an aborted question can no longer stay answerable and
  swallow free-text sends.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
daniel-lxs added a commit that referenced this pull request Jul 9, 2026
…ion panel fixes (#44)

* [Fix] Address review findings on the transcript convergence and question panel fixes

Three issues from the openmote reviews of #33 and #37:

- The history rebuild no longer resets the protocol service's auxiliary
  lookups: rebindMessages re-points only the id/position indexes, so the
  pending request_user_input map populated from history survives a
  refetch and a subsequent live response still masks secret answers.
- Todos now converge to the fetched history whenever it carries plan
  state, including an intentionally empty list, instead of falling back
  to stale live todos.
- A taskAborted status (cancel or terminal session error) drops the
  client-side pending user input requests, matching the worker-side
  clear, so an aborted question can no longer stay answerable and
  swallow free-text sends.

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

* [Fix] Address second-round review findings on the merge reconciliation

- The history rebuild now derives the trailing turn-completion decision
  from the live task status (falling back to what the transcript already
  shows), instead of always marking it - merging while a task is running
  no longer flips the active trailing assistant message to completed.
- todowrite plan state arriving through ToolCall/ToolCallUpdate history
  envelopes now counts as authoritative plan history for todo
  convergence.
- Live terminal tool results are matched by terminality rather than
  id/tool key: a persisted pending tool_call no longer swallows the live
  result (which can sit under the same envelope id after an in-place
  update), and the superseded pending call row is dropped instead.

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

* [Fix] Match live tool results against persisted terminality, not result kind

A persisted in-progress ToolCallUpdate also rebuilds as a (partial)
tool_result, so kind alone let it swallow a live terminal result and
leave the transcript stuck on stale in-progress output. Coverage now
requires a non-partial persisted result for live terminal results, and
carried terminal results supersede both pending tool_call and partial
tool_result rebuilt rows.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@mrubens
mrubens deleted the fix/pending-question-panel-not-phase-gated branch July 12, 2026 04:19
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