Skip to content

Fix TUI waiting conversation overlay - #1061

Merged
dennisonbertram merged 5 commits into
mainfrom
codex/issue-1058-tui-waiting-overlay
Aug 11, 2026
Merged

Fix TUI waiting conversation overlay#1061
dennisonbertram merged 5 commits into
mainfrom
codex/issue-1058-tui-waiting-overlay

Conversation

@dennisonbertram

Copy link
Copy Markdown
Owner

Closes #1058

Summary

Preserves the SSE envelope's top-level run_id on the TUI's decoded event message and uses that canonical identity when run.waiting_for_user fetches pending input. A production-shape acceptance regression now proves the visible AskUserQuestion overlay can submit an answer, dismiss on resume, and render the later assistant continuation.

Scope and issue reconciliation

The final diff matches #1058. In scope: TUI envelope decoding, the waiting handler, production-shape bridge/model/input coverage, replay compatibility, corrected synthetic fixtures, and required plans/logs. Out of scope and unchanged: PR #1055's server-side pending-read ordering, native GUI, web, ACP, approvals, callbacks, cron execution, provider/model/tool catalogs, and completion status for epics #1000/#1010. There were no design deviations.

Impact analysis reconciliation

  • Data flow: cmd/harnesscli/tui/bridge.go now decodes top-level run_id into SSEEventMsg.RunID; model.go consumes it for the existing pending-input fetch.
  • Wire/API: SSE and GET/POST /v1/runs/{id}/input are unchanged. Raw remains payload-only.
  • Lifecycle: initial delivery and Last-Event-ID replay use the same decoder; backpressure, reconnect, cancellation, deadlines, resume, and terminal handling are unchanged.
  • Security: existing SSE and input bearer authentication remains intact; no prompt, answer, token, or credential logging was added.
  • Persistence/config/server/other clients/catalogs/deployment: unaffected because this is an additive internal TUI message field with no schema, server, or configuration change.
  • Tests/docs: existing synthetic waiting fixtures now model envelope identity separately from payload; plan, impact map, indexes, and durable logs record the contract and evidence.

Architecture and duplication check

Searched StartSSEBridge*, sseEnvelope, decodeSSE, SSEEventMsg, the model event switch, AskUserQuestion fetch/submit/render state, reconnect/Last-Event-ID, server input handlers, server event shape, non-TUI AskUser handling, and open PR ownership. The existing sseEnvelope -> SSEEventMsg -> Model.Update boundary remains the only normalization point. No payload mutation, fallback decoder, or second run-ID source was introduced. Open PR #1055 owns server ordering and does not touch cmd/harnesscli/tui.

Test-first evidence

Red command:

TMPDIR=/private/tmp/gocode-1058-tmp GOCACHE=/private/tmp/gocode-1058-cache go test ./cmd/harnesscli/tui -run TestAskUser_WaitingEnvelopeThroughBridge_ShowsSubmitsAndContinues -count=1 -v

Observed failure on the pre-fix decoder:

waiting conversation did not complete: overlay=false input_gets=0 input_posts=0

The event crossed the real SSE bridge, but no input request occurred because top-level run identity was discarded. After retaining run_id on SSEEventMsg and consuming it in the waiting handler, the same test passed in 0.01s.

Green command: the red command above, unchanged.

Refactor/characterization evidence: existing model-only fixtures were corrected from a synthetic nested run_id to SSEEventMsg.RunID plus payload-only call_id. A reconnect control asserts the exact Last-Event-ID, canonical decoded run ID, event ID, and absence of a duplicated payload run ID.

Verification evidence

PASS:

  • Production bridge/model/API/render acceptance:
    go test ./cmd/harnesscli/tui -run TestAskUser_WaitingEnvelopeThroughBridge_ShowsSubmitsAndContinues -count=1 -v
  • Focused AskUser/SSE:
    go test ./cmd/harnesscli/tui -run 'AskUser|WaitingForUser|WaitingEnvelope|SSEBridge' -count=1
  • Focused race:
    go test -race ./cmd/harnesscli/tui -run 'AskUser|WaitingForUser|WaitingEnvelope|SSEBridge' -count=1
  • Complete TUI normal:
    go test ./cmd/harnesscli/tui -count=1 (40.800s)
  • Complete TUI race:
    go test -race ./cmd/harnesscli/tui -count=1 (40.389s)
  • Full repository gate in the logged-in foreground context:
    ./scripts/test-regression.sh — normal PASS, complete race PASS, coveragegate: PASS (total=85.6%, min=80.0%, zero-functions=0).

Real-path proof: the acceptance uses an actual localhost SSE server and the production StartSSEBridge, Bubble Tea Model.Update/View, GET pending input, keyboard Enter, POST answer, resume event, assistant delta, and terminal event. It asserts visible question/options, exact request counts/body, and continued transcript.

Environment evidence: the first full gate in detached tmux failed both real-Keychain tests because security(1) waited on the controlling terminal and was killed at 15 seconds. This was not waived. The entire script was rerun in the repository-documented logged-in foreground context; internal/modelstore passed in both normal and race phases and the full script completed green.

Hosted checks are required and will be reported from this PR before handoff.

Rollout and rollback

Ship with the next harnesscli client build; no server deployment order, migration, flag, or data repair is required. Monitor stalled-wait and pending-input-fetch reports. Roll back by reverting commit e2686f445ab13cc7608d7f750874b5bbed4878a8 if unrelated TUI event decoding or reconnect behavior regresses. Already-pending server runs remain durable and answerable through the existing API.

Documentation

Added the Issue #1058 plan and one-page impact map; updated the plans index and active plan; recorded command/user intent, symptom/cause/fix, wire-shape/testing observations, system ownership, valid red/green evidence, the Keychain execution-context failure, and the successful full rerun. Public docs, runbooks, release notes, and operator routes are unchanged because this restores already-intended behavior without changing a public contract.

Contract checklist

  • Linked issue follows the current structured contract and this PR closes it
  • Issue acceptance criteria, impact map, and scope were updated when the design changed
  • All callers, consumers, sources of truth, and similar abstractions were searched
  • No unrelated cleanup, hidden scope growth, duplicated wiring, or parallel abstraction was introduced
  • Tests were written first and the expected red failure was observed
  • Targeted checks and the repository-required full regression are green
  • Security, compatibility, lifecycle, deployment, observability, documentation, and rollback were reconciled
  • Real keyboard/API/operator behavior was exercised through the production localhost TUI bridge/model path

@cursor

cursor Bot commented Jul 30, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2686f445a

ℹ️ 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 thread cmd/harnesscli/tui/model.go Outdated
@dennisonbertram

Copy link
Copy Markdown
Owner Author

@codex review

Please review exact head 53fb2ce1e1857e4b9be6d7e053bcd13bc3d6f39f. The prior actionable thread is fixed with deterministic resumed-before-GET and superseded-call regressions; local focused/package normal and race plus the full foreground regression gate pass.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53fb2ce1e1

ℹ️ 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".

callID: p.CallID,
generation: m.askUserGeneration,
}
cmds = append(cmds, fetchAskUserPendingCmd(

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 Retry the pending fetch until broker registration

When the TUI receives a real run.waiting_for_user event immediately after it is emitted, this GET can race ahead of pending-input registration: runner_step_engine.go:1105 emits the event before runTools.Execute at line 1201 invokes the AskUser broker, whose Ask method installs the pending entry. If the GET wins, /input returns 409, askUserFetchErrorMsg clears the overlay, and no retry or later event re-fetches the question, so the run remains blocked and the user never sees the prompt. Retry the transient no-pending response or render/fetch only after registration is guaranteed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmed and mapped to existing issue #1054 and PR #1055. That PR changes the owning server invariant so pending input is readable/durable before waiting_for_user status/event publication; its exact-head fast/race checks are green. Issue #1058 and PR #1061 intentionally scope this branch to TUI envelope identity plus late-resume/supersession correlation, so I did not add a second client retry workaround here. Current main does not yet contain #1055, so I am leaving this thread unresolved and recording #1055 as the residual integration dependency rather than claiming the P1 is fixed on this branch.

@dennisonbertram
dennisonbertram force-pushed the codex/issue-1058-tui-waiting-overlay branch from 53fb2ce to 221ab05 Compare July 31, 2026 00:28
@dennisonbertram

Copy link
Copy Markdown
Owner Author

Rebase verification evidence:

  • Base: b3afc7ec487c60762a91a1219ceb92c523ef0e78 (origin/main, merged Fix AskUserQuestion status regression test race #1045)
  • Exact head: 221ab05da62ae6b16968ccc6dabb7472b6b67866
  • Rebase: conflict-free; git range-diff preserves the [Bug]: TUI drops top-level run_id and cannot answer waiting runs #1058 runtime/test commits, with only merged plan-index context changing around the first commit.
  • Focused normal: go test ./cmd/harnesscli/tui -run 'AskUser|WaitingEnvelope|SSEBridge' -count=1 — PASS
  • Focused race: go test -race ./cmd/harnesscli/tui -run 'AskUser|WaitingEnvelope|SSEBridge' -count=1 — PASS
  • Full foreground non-TTY: ./scripts/test-regression.sh — PASS (normal, complete race, coverage 85.6%, zero uncovered functions)

The late-resume and superseded-call/generation AskUser regressions remain present and green. No baseline failure appeared.

@codex review

Please review exact head 221ab05da62ae6b16968ccc6dabb7472b6b67866.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 221ab05da6

ℹ️ 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 +4407 to +4408
m.askUser = askUserState{
active: true,

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 Keep cancellation keys active while loading the question

When a production run.waiting_for_user event arrives, this marks askUser active before the GET has returned any questions. If that request is slow or unreachable, renderAskUserOverlay displays nothing, while the tea.KeyMsg branch routes every key to handleAskUserKey, which immediately no-ops because questions is empty; even Esc and Ctrl+C cannot dismiss or cancel the run until the HTTP client's 10-second timeout expires. Keep the loading state from claiming overlay key priority, or explicitly handle cancellation keys while the fetch is pending.

Useful? React with 👍 / 👎.

Resolved against main's newer TUI work (context meter, tool-call grouping,
provider-key provenance, config persistence). model.go and bridge.go merged
cleanly; the one code conflict was messages.go, where main added Conversation
and ConversationID to SSEEventMsg after this branch was cut — main's fields are
kept. Append-only logs and plan indexes keep both sides.
@dennisonbertram
dennisonbertram merged commit a0d1521 into main Aug 11, 2026
2 checks passed
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.

[Bug]: TUI drops top-level run_id and cannot answer waiting runs

1 participant