Rounds that are not answers
Two defects with one shape: a round's record claimed something its own evidence did not support, and every reader downstream — the PR steward, the bug-fix pool, triage — acted on the claim.
1. A selected agent the catalog does not hold is an Error, never Completed (Plugins #2797)
When a round's explicitly selected agent matches no loaded agent (after the bounded catalog wait,
AgentChatClient.MissingAgentGrace), AgentChatClient streams the sentence "Selected agent 'X' was
not found among the available agents (…)" as the round's only output. No model runs and no tool runs.
RoundOutcome.Classify read any non-empty text with no tool call as an answer, so the cell settled
Completed — measured on the control instance as
Hosting/Triage/_Thread/review-pull-request-…-6c03/c400d55d (2026-10-03). Every control-plane caller
counts a Completed round as a spent attempt, so a catalog gap silently consumed their budgets.
The rule: an unresolved selection is its own verdict, RoundVerdict.SelectionUnresolved, decided
ahead of every text rule and never Completed.
AgentChatClient.UnresolvedSelectionErrorlatches the sentence only when the failed selection was an explicit pick that matched nothing — never for a matched-but-unbuildable agent, whose truthful error (no model, no factory) is a different condition.ThreadExecutionpasses it toRoundOutcome.Classify; the round writes*Error: Selected agent …*as its text,Error: …as its Summary, and tells a delegating parent it failed. That is the same terminal shape as no model can serve this round (#476).- Readers:
PullRequestSweep.ClassifyRoundreads theErrorshape (and still the legacyCompletedone) as infrastructure,reviewer agent not found, only when the round ran no model and no tool. The round carries no output tokens, which is what the bug-fix pool's infrastructure classifier keys on.
The "pr-reviewer not found" wave itself (fresh and resumed rounds dispatching without the space layer)
was fixed by Plugins #2729 and the AI build that carried it; on the control instance the sentence has
not appeared in any Hosting/Triage cell since 2026-10-04 06:30Z, over hundreds of pr-reviewer
rounds. This section is about what such a round is CALLED when it does happen.
2. The supervisor's "last error" is the stuck round's, never an earlier round's (Plugins #3050)
ThreadSupervisor.Diagnosis embeds last error: in the Error cell it settles with and in the feedback
it files. It took that text from Thread.Summary. A round writes Summary only in the write that
ends it (the terminal Idle write), so on an executing thread — every Stale verdict — any Summary
was written by an EARLIER round, possibly another episode, possibly days old.
Measured on the control instance (2026-10-07): round d0cb3e56 of
Hosting/Triage/pull-request/systemorph-meshweaver-plugins-2969/_Thread/owner-…-2969 was cut three
times by its host shutting down during successive rolls (Loki on the control instance:
Host is shutting down, cannot route to …/d0cb3e56 from three different pods, at 02:02:32Z,
02:38:13Z and 03:10:02Z). The supervisor relaunched it twice and gave
up at 03:15:36Z, quoting as last error an OpenRouter HTTP 403 … Key limit exceeded (daily limit) —
written by round 233a0419 on 2026-10-05 23:48Z, 27 hours earlier. Triage filed it as "Agent thread
wedges on an exhausted model key". The key was not involved: the next round that did hit the exhausted
key (04:07:15Z, 271046c3) failed in 43 ms with a named Error cell and the dispatch pool closed the
provider until midnight.
The rule: on an executing thread the last error is the round's own ExecutionStatus, or "none —
the round in flight has written no error"; an earlier Summary is still reported, labelled "left by an
EARLIER round, not this one". On an idle thread (Parked) the Summary IS the last round's terminal
write and is read as before — including the #2236 cases after a wake or a relaunch
(ThreadSupervisorSettleLoopTest).
Tests
UnresolvedAgentSelectionRoundTest— a real round withAgent/ghost-agent-2797settlesErrorwith the not-found line; the control (default agent, same mesh, same model) completes. Negative control: without theThreadExecutionchange the first case fails with "found Completed".RoundOutcomeTest.AnUnresolvedSelection_IsNotAnAnswer_EvenWithText— the marker decides, not the wording.ThreadSupervisorLastErrorProvenanceTest— the measured thread's shape; negative control: without theDiagnosischange both executing cases fail quoting the 403.PullRequestSweepTests.ARound_IsInfrastructureOnlyOnWhatThePlatformWrites— theErrorshape is infrastructure; the same line after a model call is not.
Not established
- Why three rolls landed inside 70 minutes on the control instance, and whether a host-shutdown interruption should count against the supervisor's relaunch cap at all — the supervisor sees only the node and cannot tell a dead pod from a wedged round.
- Whether an exhausted key fails over to another key or rung for the round that HITS it: the dispatch
pool closes the provider for later rounds ("its rounds move to alternatives or wait"); the round that
met the 403 ends
Error. Not changed here.