ask() already fails EMPTY_QUESTIONS before a request exists, so a
question/requested frame with zero items is host breakage; muxFrameSchema
now refuses it instead of letting an undefined first question reach the
composer (review r3635427102).
Two hardenings on the chain outlet branch:
A throwing chain selector runs before its entry's SlotErrorBoundary
exists, so uncontained it blacked out the whole owner region and skipped
the remaining chain. It now degrades to a decline: reported via
console.error with the registrant identity, later entries still tried,
all-null/all-throw passes land on the owner fallback.
The elected entry's boundary is now keyed by entry identity: an unkeyed
boundary that failed on entry A survived a re-election and kept a
healthy entry B blacked out until the outlet unmounted. The key remounts
the boundary fresh whenever the election changes.
ClientContext types ctx.slots as always present (inject-declared service);
the unnecessary-condition lint rule rejects the dead guard and its
fail-loud test premise. Load-order failure still surfaces loud through
the undeclared-slot registration path, covered by the remaining case.
The FIFO-conservation invariant fired on the loop-authored continuation
reason path: a continue-with-reason decision entered the steering FIFO
without an agent/inbox/enqueue, so its later dequeue/discard had no
matching enqueue. Emit the enqueue for that steer too, add a regression
test that mounts the invariant over a continue-with-reason turn and a
cancel, and hoist the duplicated inboxInfo helper into inbox.ts.
Found by fresh-eye review.
Replace send/steer/inject with one Agent.send primitive over the
(target × wakeup) matrix; followup/steer/inject become fixed-preset
alias methods on the now-abstract Agent class. Coalesce context/message
into user/message (injected context is a non-user source). Replace
agent/queued with agent/inbox/enqueue/dequeue/discard, add cancel
keepInbox, and add a FIFO-conservation invariant.
Restack the ask-user domain layer onto the carrier-chain architecture
branch. Conflict policy: runtime and ui-conversation take the
carrier-chain side (master sessions shape, dual-kind PendingCard,
'internal' envelope shell tests); the 'cancelled' wire code and its
semantics tests stay in apiproxy + ui-question (domain layer); the
smoke fixture keeps the nine-bundle success pass with the resident
question round over the carrier-chain first-describe shape.