Skip to content

feat(agent-launch): a click's follow-up survives a window reload, once - #26173

Closed
brennanb2025 wants to merge 21 commits into
brennanb2025/host-owns-first-promptfrom
brennanb2025/host-owns-first-prompt-follow-ups
Closed

brennanb2025 wants to merge 21 commits into
brennanb2025/host-owns-first-promptfrom
brennanb2025/host-owns-first-prompt-follow-ups

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 17 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2153 $\color{#cf222e}{\Huge{\mathbf{−}}}$​77 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2076
Prod 45 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1420 $\color{#cf222e}{\Huge{\mathbf{−}}}$​239 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1181

ELI5

Reloading the window mid-launch could leave notes looking unsent and review threads open after the agent received the prompt, inviting a duplicate click. Notes New agent and Checks Resolve comments performed their follow-up only in the original window, even though #26168 lets the host finish sending the prompt.

This PR records those follow-ups with the launch and atomically takes each after confirmed prompt handoff. Pending notes and threads stay in flight across reload. This PR and #26168 must land together.

What Changed

The original click records the sent-note identities or selected threads and reply snippets. A window removes a settled follow-up in the same write that takes it, so another window or notification cannot run it again. Notes clear only if their sent content is unchanged; edited/new notes and unrelated threads remain. GitHub and GitLab keep the existing resolution path.

The window keeps listening while the host reports a live launch as pending. It no longer treats the former five-minute prompt deadline as proof that a live launch has finished. When a canceled navigation restores the same window, the host re-announces its current settled launches, and the same atomic take prevents a repeated follow-up.

If a lookup following the host’s settlement notification fails, the window releases its Notes or Checks hold without marking anything sent or resolving a thread. An untaken durable follow-up remains available to a later existing lookup; no extra retry or notice is added. A response lost after the atomic take can still lose the follow-up, as before.

When a live launch finishes after its receipt expires or is pruned, the host still tells the waiting window it has settled. The window releases the hold, but an expired or absent record authorizes no follow-up. This preserves the existing retention and atomic-take rules.

The shrink removes #26168's saved first-prompt text and restart repasting while preserving this separate follow-up record and atomic take. A bare terminal creation does not authorize a follow-up. A restart before prompt handoff remains unconfirmed and runs no follow-up; it sends no late prompt. That earlier first-prompt restart guarantee is withdrawn, matching main.

Why

Current notes or threads cannot reconstruct the original click. The launch record already owns its outcome, so the follow-up uses that receipt and the live launch state. Taking before execution avoids duplicate external replies; a crash after take can still lose the follow-up. No second prompt store or retry flag is added. This is the step that reaches parity with main; a later simplification phase will change how prompts are delivered.

Linked Issue

Stacked on #26168, step 2 of agent-launch unification. The pair must land together.

Visual Proof

Fresh live QA ran on hidden desktop windows with an isolated profile, a stand-in Codex agent that records every byte it receives, and a closed fake GitHub provider (no real agent, account or GitHub writes). The reload rows and the slow-agent check ran on #26173 at c746688, which contains this branch; restart and Checks rows ran on c6dbbe4 before the final sync with main. Between those builds and the final heads only main's own commits differ (none touch agent launch).

Notes "New agent", window reloaded while the agent starts: both saved notes are held; one is then edited.

Notes held after the reload

After the prompt is delivered: only the unchanged sent note clears; the edited note and a newly added note stay. A second reload changes nothing.

Only the unchanged sent note cleared

Checks "Resolve comments", reloaded while pending: after delivery only the selected thread is resolved (one write to the fake provider, never repeated); the unrelated thread stays open.

Selected thread resolved, unrelated thread still open

Testing

QA ran on this laptop with hidden windows because the remote Mac test machine was unreachable that evening. Stand-in agent and fake provider only: no real Codex or GitHub. Windows, WSL and SSH were not exercised.

Review

Fresh adversarial reviews and an independent architecture sketch checked reload ownership, admission/replay, settled receipts, original-terminal write guards and atomic follow-ups. Final readiness review and a fresh narrow review of the last settlement change are complete; no open P0 or P1 was established. Live QA and CI remain separate gates.

Agent skill upstream boundary

  • Not applicable; this change copies no upstream skill-installer implementation.

Notes

  • Intended — app restart: interrupted paste-only delivery stays unconfirmed and is never automatically retried. The earlier restart-recovery guarantee has been withdrawn.
  • Intended — follow-up take: a crash or lost response between taking and executing can lose a follow-up; another take cannot repeat the same reply.
  • Intended — compatibility: older peers keep their existing request/receipt behavior; uncertainty remains capability-qualified.
  • Intended — original terminal: writes check the launched terminal and program ownership; replacement terminals never inherit the text.
  • Temporary — route coverage: managed SSH, direct native-chat and paired web-host routes retain their existing window callbacks and reload gaps. Broader caller unification belongs to later agent-launch work.
  • Deferred — follow-up notification after receipt expiry: if a launch spans the 24-hour receipt retention and finishes while navigation suspends notifications, Notes or Checks can remain held until reload. Covering that combined case needs separate notification recovery work; no ticket exists. No follow-up runs from an expired record.
  • Intended — caller access: current main requires every host method to declare who may call it; the new follow-up lookup uses the same workspace level as the other agent-launch methods.
  • Intended — readiness wait: a launch started from a desktop dialog waits for the agent as long as main's window did (20 seconds for Codex, 8 seconds by default) before reporting that the prompt was not sent; other callers keep the host's 60 seconds. Without this, a slow or blocked agent kept the dialog open three times longer than on main.
  • Intended — paste frame: the host retains its existing bracketed-frame writer; a relay frame over 2 MiB can refuse. This shrink does not change bytes or timing.

No new UI copy or status surface is added. No merge or auto-merge is enabled. Review, CI and live QA are green.

Author: @BrennanKB5

Checklist

  • Explained problem, user-facing change, mechanism and alternatives.
  • Fresh visual/live proof on the final shrink.
  • Final correctness, compatibility and readiness source review.
  • Required checks and exact-head CI.

@brennanb2025
brennanb2025 force-pushed the brennanb2025/host-owns-first-prompt-follow-ups branch 4 times, most recently from 601e304 to 64efbf3 Compare October 7, 2026 11:29
…follow-up path

The host's word that a launch settled is bookkeeping: a missing notifier or an unreadable store
leaves the follow-up for the window's next look, never fails the launch. Tests now cover the
live click's take, the push and the deadline take, the held Checks threads, the shared
resolution logic with and without a panel, the startup hook, and the notes and Checks wiring.
…d reach an open Checks panel

- The window's startup take neither opens nor creates the record store when no launch recorded a
  follow-up.
- The host says a launch settled however it ended (failed, tab closed), once it no longer reads as
  running, so a reloaded window stops holding notes and threads for a launch that failed.
- One waiter per window: it listens before startup's first take, takes each launch once at a time
  (a second, empty answer never releases a hold another take is still running), and also holds a
  click's follow-up its own take missed, taking it when the host says so.
- A reload's comment resolution goes through the Checks panel open on that review, as the click
  would, re-reading it from GitHub or GitLab.
- A recorded comment keeps the one-line snippet its "Fixing:" reply quotes.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/host-owns-first-prompt-follow-ups branch from 64efbf3 to 128843a Compare October 7, 2026 11:33
@brennanb2025
brennanb2025 marked this pull request as ready for review October 8, 2026 08:06
@brennanb2025
brennanb2025 marked this pull request as draft October 8, 2026 19:52
…host-owns-first-prompt-follow-ups

# Conflicts:
#	src/main/runtime/rpc/methods/agent-launch.ts
#	src/shared/agent-launch-runtime-capability.ts
@brennanb2025
brennanb2025 marked this pull request as ready for review October 9, 2026 10:42
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Ready for review: #26168 + #26173 (land together)

The problem. Clicking an AI button (Resolve with AI, Fix with AI, Notes "New agent", Checks "Resolve comments") starts an agent and then types the first prompt once the agent is ready. If the window reloaded during that wait, the prompt could be lost; for Notes and Checks, the "clear sent notes" / "resolve the selected threads" step that should follow could also be lost or run twice, leaving notes looking unsent and threads open after the agent had actually received them.

What changes for you.

  • A window reload while an agent is starting no longer loses the first prompt: the agent receives it exactly once, in the same terminal.
  • Notes and Checks keep their "sending…" state across the reload and, once the prompt has arrived, clear only the notes you sent unchanged and resolve only the threads you picked — once.
  • After an app restart mid-launch, an interrupted prompt is reported as not confirmed and is never typed in late. This matches main; an earlier version of feat(agent-launch): the host delivers AI buttons' first prompt across reload #26168 tried to recover it automatically after restart, and that is withdrawn.
  • A slow or stuck agent makes the dialog give up after the same time as main (20 seconds for Codex), with main's existing "Your prompt wasn't sent" notice.

How. The app's host process (not the window) now sends the first prompt and records the result, so a reloaded window joins the launch already in progress instead of starting over. #26173 stores the Notes/Checks follow-up with that launch and takes it in one step after the prompt is delivered, so no second window or reload can repeat it.

Fixed in this final round.

  • Live QA showed that, on a slow or blocked agent, the dialog could stay open for up to 60 seconds (the host's own wait), against about 20 seconds on main. Desktop launches now use main's per-agent wait; other callers keep 60 seconds. A regression test fails without the fix and passes with it, and live QA confirmed the dialog gives up at 20.2 seconds.
  • Current main requires every host method to declare who may call it; feat(agent-launch): a click's follow-up survives a window reload, once #26173's new follow-up method uses the same level as the other agent-launch methods.
  • Both branches are merged with current main (import-only conflicts, both sides kept).

Deferred (P3, not fixed here). If a launch somehow stays pending past the 24-hour record retention and finishes while the window is mid-navigation, Notes/Checks can stay "sending…" until the next reload. No follow-up runs from an expired record.

Seen, but already on main (not changed here). After the "prompt wasn't sent" timeout, the dialog stays open with Start agent enabled, so a second click would start a second agent. Same code path on main.

Verified.

Not verified.

  • QA ran on this laptop (hidden windows, isolated profile) because the remote Mac test machine was unreachable; Windows, WSL and SSH were not exercised.
  • No real Codex and no real GitHub writes (stand-in and fake provider only).
  • The restart and Checks rows ran before the final merge with main; the final heads differ from that build only by main's own commits, none in agent launch.

Author: @BrennanKB5

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Closed: the agent.launch migration is parity-only. This fixes main's reload-loses-the-prompt bug, which moves to the post-migration bug-fix work, done there by handing the prompt over at agent start instead of pasting.

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