Skip to content

Keep each accepted chat message with its chosen model and effort - #28207

Closed
brennanb2025 wants to merge 45 commits into
brennanb2025/agent-start-split-4-pi-startfrom
brennanb2025/agent-start-message-choices
Closed

brennanb2025 wants to merge 45 commits into
brennanb2025/agent-start-split-4-pi-startfrom
brennanb2025/agent-start-message-choices

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 59 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1506 $\color{#cf222e}{\Huge{\mathbf{−}}}$​873 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​633
Prod 110 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1506 $\color{#cf222e}{\Huge{\mathbf{−}}}$​768 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​738

ELI5

Changing the model while an agent was starting could make an earlier message run with a choice intended for a later one. Messages waiting as cards also relied on whichever choice the chat held when they eventually ran. Each new message and card now keeps the choices it had when accepted.

What Changed

Each accepted message and queued card keeps its own model and effort, and delivery applies them immediately before sending the prompt. For example, send A on model X, pick model Y, then send B: A records X as its choice and B records Y; the running-turn differences are described below. Close, quit, restart, card edit and Send now preserve those choices. Desktop and mobile omit choices while the picker is unknown, so the host uses its saved choice. Mobile follows the host status stream and includes an in-flight pick when the full choice is known; otherwise it omits choices and uses the host selection. A desktop on an older host still refreshes after another device picks. The picker retains its model pill while an unloaded list is filled in.

Why

The host already owns message acceptance and the saved selection. Capturing choices with each message keeps later picker changes from changing work already accepted. Picker clicks now save the selection instead of writing to a running child; delivery applies each message's own choices. Provider reports enrich catalogs and live facts without rewriting saved choices. Older records stay readable; choices missing from an older record cannot be reconstructed.

Differences from the common pattern

  • INTENDED — Independently updated peers retain the old path. The new Send field is optional and used only when the host advertises support. An older client omits it and the new host copies saved choices for new messages; a client connected to an older host uses the existing options read and status stamp.
  • INTENDED — Choices are applied as each agent permits. Claude and Pi keep their existing live-switch behavior for messages sent during a running turn. Codex receives explicit choices when a turn starts. Known defaults clear previous turn overrides; installed-agent compatibility is covered by scripted tests, not claimed for untested binary versions.
  • INTENDED — Stop before prompt delivery records a cancellation result. If Stop ends startup or option application before the first prompt reaches the agent, the host writes one request note and returns cancelled. This gives feedback for a user action even though no provider turn exists yet.
  • INTENDED — The host distinguishes startup waits from option application before delivery. Its cancellation tracker marks the latter as a handover, meaning the prompt is about to be sent. Stop can end that wait and report cancellation without treating it as a failed start; several agent adapters share this host path.

Codex messages with a different model or effort currently wait for the running turn to end. Whether they should instead steer now and apply choices to a later turn remains undecided; the message wait remains here. Goal changes and rewinds on a running agent answer immediately, even when an earlier message is held by that wait. A goal requested during startup also stops waiting behind messages once their delivery parks.

Older ACP and Pi messages or cards that contain no recorded choices still receive no saved-choice fallback. A downgrade that discards this metadata cannot retain the per-message guarantee.

Linked Issue

Replaces the message-choice portion of #26561 and folds #27641 into the aligned stack. Depends on #28048 and its three lower drafts; #28051 will target this branch.

Visual Proof

Rendered before/after evidence is pending. Scripted tests cover the behavior; no screenshot or manual platform evidence is claimed.

Testing

  • Manually tested on all supported platforms
  • Automated tests added or updated

Focused host/card, desktop, shared-choice and provider tests; Node, Web, mobile production and CI project typechecks; mobile test-type ratchet; 14 real Claude CLI tests; static checks with the accepted pinned-main HtmlDocPreview exception. New unknown-send and kept-card regressions cover the failure cases. Goal pause, edit and clear are tested while a message remains held by the Codex wait; those cases fail without the ordering fix. No rendered Electron, simulator or actual SSH QA.

Review

Reviewed the owning diff, failure paths and covered races. Tests demonstrate covered behaviors; rendered and real remote-host QA are pending.

Agent skill upstream boundary

  • Not applicable; no upstream skill-installer source is copied or translated.

Notes

Execution stays on the host owning the agent. Folder workspaces and independently updated peers retain their existing paths. Loss of contact is not process-exit evidence. Draft only; no main sync or hosted CI watch.

Checklist

  • Problem, user-facing change, mechanism and approach explained
  • Self-reviewed source and regression evidence
  • Cross-platform, folder, SSH and older-peer behavior considered
  • Final main sync, hosted CI and rendered proof completed

# Conflicts:
#	src/main/acp/acp-structured-host-option-hang.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-acquire-aborts.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-claude-option-queue.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-host-mutations.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-option-settlement.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-provider-started.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt-registrations.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-startup-permission-mode.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-startup-picks.test.ts
# Conflicts:
#	src/main/acp/acp-structured-acquire.ts
#	src/main/acp/acp-structured-handshake.ts
#	src/main/acp/acp-structured-host-option-hang.test.ts
#	src/main/acp/acp-structured-publish-at-spawn.test.ts
#	src/main/claude/claude-structured-session-adapter.test.ts
#	src/main/claude/claude-structured-session-startup.ts
#	src/main/claude/claude-structured-start-fast-mode.ts
#	src/main/codex/codex-structured-publish-at-spawn.test.ts
#	src/main/codex/codex-structured-session-start.ts
#	src/main/native-chat/agent-session-journal/journal-row-builders.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-acquisition-options.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-acquisition.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-attach-flow.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-attach-orchestration.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-claude-option-queue.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-conversation-lifetime.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-create.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-delivery-loop.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-held-start.test-support.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-instant-start.test-support.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-mutation-context.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-option-settlement.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-provider-child-record.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-provider-open.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-provider-started-catalog.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-queued-message-rig.test-fixture.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-send-restarts-failed-start.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt-host.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt-registrations.test.ts
#	src/main/native-chat/agent-session-wire/structured-agent-session-startup-attempt.ts
#	src/main/native-chat/agent-session-wire/structured-conversation-command.test.ts
#	src/main/pi/rpc-session-startup.ts
#	src/main/runtime/structured-agent-session-failure-logging.test.ts
#	src/main/runtime/structured-agent-session-pi-startup.test.ts
# Conflicts:
#	src/main/native-chat/agent-session-wire/structured-agent-session-host-mutations.ts
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Folded into #28046, which merged as 5319125. Closing this draft; nothing here is lost.

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