Parent: #991
Summary
High-stakes run-control requests are fire-and-forget. Cancel, approve, deny, and answer use try? or otherwise discard failures. answer() removes pendingQuestions before the server acknowledges the response, and the form considers an answer complete based only on dictionary key count.
Evidence
macapp/Sources/GoCodeUI/RunSession.swift:128-149 — cancel/approve/deny swallow request failures.
RunSession.swift:169-173 — pending questions are cleared before an acknowledged answer and submission errors are swallowed.
macapp/Sources/GoCodeUI/ChatView.swift:813-855 — Send is enabled by answers.count; typing then deleting a required freeform answer leaves an empty value counted as complete.
- The first failed cancel sets
cancelRequested = true; the next click can abandon the stream locally while the server run continues.
Impact
The GUI can claim or imply that a decision was delivered when it was not. A pending question can disappear permanently on a transient failure, and a failed cooperative stop can turn the next click into a local-only force stop.
Scope
- Introduce explicit pending/succeeded/failed action state for cancel, approve, deny, plan approval, and user answers.
- Clear a pending question only after the server acknowledges the answer.
- Validate trimmed non-empty required answers; preserve entered answers and focus on error.
- Reset cancel escalation when the cooperative request fails.
- Surface retryable errors inline at the action that failed and announce them accessibly.
- Prevent duplicate submissions while a request is in flight.
Tests first
- Stub-client tests for success, transport failure, structured server failure, retry, and duplicate-click suppression for each action family.
- Regression: an answer failure keeps
pendingQuestions and the answer draft.
- Regression: an erased-to-empty freeform answer does not enable Send.
- Regression: failed first cancel does not arm local force-cancel.
Acceptance criteria
Parent: #991
Summary
High-stakes run-control requests are fire-and-forget. Cancel, approve, deny, and answer use
try?or otherwise discard failures.answer()removespendingQuestionsbefore the server acknowledges the response, and the form considers an answer complete based only on dictionary key count.Evidence
macapp/Sources/GoCodeUI/RunSession.swift:128-149— cancel/approve/deny swallow request failures.RunSession.swift:169-173— pending questions are cleared before an acknowledged answer and submission errors are swallowed.macapp/Sources/GoCodeUI/ChatView.swift:813-855— Send is enabled byanswers.count; typing then deleting a required freeform answer leaves an empty value counted as complete.cancelRequested = true; the next click can abandon the stream locally while the server run continues.Impact
The GUI can claim or imply that a decision was delivered when it was not. A pending question can disappear permanently on a transient failure, and a failed cooperative stop can turn the next click into a local-only force stop.
Scope
Tests first
pendingQuestionsand the answer draft.Acceptance criteria
swift test, Swift build, formatting, strict format lint, and a live daemon control smoke pass.