Skip to content

app: questions settle everywhere, Hold holds, and late model lists are announced - #2015

Merged
AbirAbbas merged 6 commits into
app/v3from
fix/app-questions-settle
Oct 28, 2026
Merged

AbirAbbas merged 6 commits into
app/v3from
fix/app-questions-settle

Conversation

@AbirAbbas

Copy link
Copy Markdown
Collaborator

What was wrong (app mode)

Each of these shows up on the desktop as a question that stays stuck or comes back:

  1. A made crew's proposal stayed in the Inbox. "Make the crew" closed the proposal's ask, but its Inbox item was resolved only through a receipt id, and the formation receipt names the crew. Waiting stayed at 1, and the next Inbox read brought the proposal back.
  2. Inbox answers were checked only after the 5 s undo hold. inbox.answer returned an undo deadline before checking the answer, and a failure after the hold was dropped. An unoffered option or an already-closed question left the desktop on "Answering…".
  3. Hold didn't hold a model question's clock. asks.hold answered success for a clocked model question but only held task proposals, so the clock still picked the suggestion.
  4. A model listing that finished late was never announced. models.list answers within about 3 s with what it has. When a slow provider listing finished later, nothing told the desktop, so its pickers missed those models.

What changes

  1. On create, the proposal's Inbox item is resolved explicitly and once. The chat keeps its single formation fact.
  2. One side-effect-free validator, shared with the immediate answer path, runs before the hold: open question, offered option, required text, proposals, budget and fuel amounts, landing verdicts, service health. Failures are refused at once.
  3. Hold uses the question holder the terminal uses (HoldQuestion). A changed question is restated under its own id; identical replays stay silent, batch facts included.
  4. One lifecycle-owned subscription emits models.changed once per listing completion. It's sent outside the backend lock and stopped on close; no polling, no extra wait in models.list. The desktop listens in Agent-Field/codeaf-desk#57.

The terminal's behaviour is unchanged.

Manual verification on a real engine

Linux, isolated homes, a loopback OpenAI-compatible stub, this branch against app/v3:

Scenario app/v3 this branch
Make the crew → inbox.list waiting proposal still listed, Waiting 1 empty, Waiting 0, one inbox.resolved, Done +1
inbox.answer with an option the question doesn't offer undo_until +5 s, then silence; still waiting bad_params … offers no option "answer" at once, no hold
inbox.answer to a closed question undo_until +5 s, then silence not_found … is not open at once, no hold
Hold a 2 s clocked model question ask.closed by=elsewhere at +1.9 s restated without a clock; still open at +3 s
Provider /models held 4.5 s first list has 1 row; no event first list has 1 row; models.changed ~1 ms after completion; next list has 2 rows

Checks

gofmt, go vet ./cmd/codeaf ./internal/appwire, and the named tests in cmd/codeaf (crew proposals, Inbox validation and hold, Hold for model and task questions, late model notices, close cancelling notices) and internal/appwire, all passing on app/v3 36dba7c. CI (ci.yml, ci-full.yml) has been dispatched on this branch; it is judged against an app/v3 Full baseline.

Known limit (not a regression; before this change nothing was checked before the hold): a day-cap "Raise for today" whose amount is not above the current limit, or any raise when CODEAF_DAILY_BUDGET pins the limit, still passes preflight and fails only when sent. The desktop's held answer is cleared on its next engine-restart reconciliation.

Overlaps: app.go question restatement and the Inbox/proposal code also appear in draft #1933 (appconvo.go, appcrewmembers.go); whichever lands second rebases. Merge after #2009 like the other app.go lanes.

🤖 Generated with Claude Code

@AbirAbbas
AbirAbbas force-pushed the fix/app-questions-settle branch from 7def296 to 4fb58f9 Compare October 28, 2026 19:51
AbirAbbas and others added 6 commits October 28, 2026 16:31
Making the crew closed the proposal's ask, but its Inbox item was resolved
only through a receipt id, and the formation receipt names the crew, so the
item stayed waiting (and a later Inbox read brought it back). Resolve the
proposal's item explicitly on create, once; the chat keeps its single
formation fact.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
inbox.answer returned an undo deadline before checking the answer, and a
failure after the hold was dropped, so the desktop kept "Answering...".
Validate what the owning handler will check (open question, offered option,
required text, proposals, budget and fuel amounts, landing verdicts, service
health) before the hold, and refuse at once. Day-cap raises the limit itself
refuses are still checked only when sent.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
asks.hold answered success for a clocked model question but only held task
proposals, so the clock still picked the suggestion. Use the question
holder the terminal uses, and restate a changed question under its own id
while identical replays stay silent.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
models.list answers within about three seconds with what it has; when a
slow provider listing finished later, nothing told the desktop. Emit one
models.changed per completion from a lifecycle-owned subscription, sent
outside the backend lock and stopped on close. No polling and no extra wait
in models.list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The new Inbox section said a landed task and a standing order need an
offered verdict; the manual keeps that word for the harness. Say one of the
offered choices instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The section on models.changed described a protocol detail no person sees, and
its wording pulled "why does this model start with ~" away from the lanes
page. The protocol document already covers the event.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@AbirAbbas
AbirAbbas force-pushed the fix/app-questions-settle branch from e8f8031 to c63331b Compare October 28, 2026 20:37
@AbirAbbas
AbirAbbas merged commit b913432 into app/v3 Oct 28, 2026
14 of 20 checks passed
@AbirAbbas
AbirAbbas deleted the fix/app-questions-settle branch October 28, 2026 21:12
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