A queued echo now records its Inbox position like transcript and steering
echoes. Later splices move that position, so a canceled splice that removes
the row retires the echo even when no Inbox projection ever showed it, for
example when the Turn is stopped right after queueing. A claimed row still
waits for its admitted message, and the queue dock still hands the echo over
to the Host row it renders.
The fold-room e2e no longer samples the running status slide or the
`data-chat-tail-pinned` mark that this branch removed. It asserts that fold
room below a short answer takes the new Turn's growth without scrolling
through Turn end, that the room never grows back, and that the running
status only moves down.
Measured against 0.2.1-rc.4 and master with the frame-sampled motion matrix,
the transcript moved back and forth at Turn end and around input landing.
This keeps rc.4's landing behavior, master's steering layout, and fixes the
reversals that remain.
- Completion-time folding keeps the first visible surviving row still when
work rows close at once, filling the gap with bottom space capped at half
the scrollport, instead of letting the browser clamp the position.
- After the Session stops running, the running status keeps its tail slot
hidden and silent until the Turn's actions row replaces it, so the tail
does not shrink and grow back.
- A Turn's duration control takes its gap in one frame instead of sliding.
- A fold batch that takes over following for a content change absorbs
growth outside the batch before its first frame.
- Steering lands at once under either fold timing: the running Turn keeps
streaming above its echo, which a native animation would push down.
- The running status no longer slides below a Step's first output, and the
column no longer carries `data-chat-tail-pinned`; the steering entrance
keeps its animation.
- A queued prompt is accepted by its Inbox row as well as by its receipt,
so the composer clears the draft in the frame the queue dock shows it.
- A queued echo waits for the Inbox projection instead of retiring on the
durable splice, so the queue dock does not empty for a frame.
Move the facade, listener, state, wait and history tests onto the new
controllers, and cover passive activation, omitted cursors and the
event subscription frames.
- The composer's primary button keeps master's rule that hides a denied
action and draws the sending state inside it; a sending prompt stays
interruptible through master's stopAction.
- The ui-conversation README pairing is recorded again for the merged
sections.
Address the review of this pull request:
- A failed image upload keeps the Host's attachment refusal reason. The
thumbnail of a refused image names the reason instead of offering a
retry that cannot succeed, and Enter while uploads hold the send names
the first failure; a transport failure still offers retry, and an
image without a file name uses the pending-image label.
- An image upload stops reading at the smaller of the per-image and
per-message byte limits.
- A carried image draft moving to a Session that sends images inline
drops its upload instead of staging it again.
- The image upload ready state no longer carries an unread image ref.
- Docs describe stored-image admission and the command image path, and
the attachment rail test builds typed props instead of casting through
unknown.
Prompt admission counted stored images only toward the image count, so
two uploads that each fit alone could exceed maxMessageImageBytes once a
prompt cited both receipts. A staged image now records the byte length
of its upload, and admission counts stored and encoded images together
against both per-message limits before storing anything.
An image upload cancelled after its last chunk, or while its image was
stored, still received a receipt. The upload now checks cancellation
after the read and again before staging, as the file stream path does;
an image whose storage began stays stored, but no receipt is issued.
Brings in master a8d675ecc92, which reverts the agent controller of #6418,
together with the composer's image upload on add.
The agent-controller message delivery Agent Note follows master's deletion.
The ui-conversation README keeps the read-only sending paragraph and takes
the image upload sentences. Service orchestration keeps both new sendSession
cases, and the refused-send reference case takes master's newSession
submission fact. README pairings are recorded again.
An ordinary Session's composer now uploads each image draft through the
background upload queue as soon as it is added. The raw upload route stages
the body as a prompt image when the request names its media type: the Host
reads at most the per-image byte limit, then validates, normalizes, and
stores the image as prompt admission would. The prompt cites the receipt in
a file part; prompt admission resolves it to the stored image, applies the
image-input check, and counts stored images toward maxImagesPerMessage.
Send waits for every image receipt, and a failed image upload turns its
thumbnail into a retry control. Commands and subagent continuations keep
encoding images inline.
The Host's Inbox projection can reach the client before the prompt receipt.
Until the receipt published the echo, QueueDock showed the message as a
queued row, and in "On next message" mode the conversation followed the
grown tail and then folded back.
An Inbox row carrying the request id proves that the Host accepted the
prompt. The Session now publishes the echo and leaves the blank layout at
whichever of the receipt or the row arrives first, and calls the new
onAccept callback in that update. The composer settles inside that callback,
before the echo renders, so the fold starts from the shrunk composer instead
of depending on microtask order.
AgentAdmissionRejected now extends HarnessError with the fixed code
AGENT_ADMISSION_REJECTED. The Session Remote recognizes a refusal by that
code and imports only agent-controller types, so its mapping also holds for
an error from another copy of the module; its literals are typed by the
agent-controller constants, so a changed value fails the build.
Master's async activation makes AgentRegistry inject sessionProjections and
makes createSessionTestRemote async. Install SessionProjectionRegistry in the
agent-controller and prompt-admission harnesses and await the test Remote in
the image admission tests.