Why: AssistantMessage reordered a message's parts by the process flag,
so tool calls floated above the text that surrounded them instead of
appearing where they actually ran; live streams had the same defect via
a fixed template order and never showed artifacts mid-run. Generated
files (e.g. meeting-minutes docx) had no visible download path, the
artifacts panel was a bare list, DocViewer nested a modal inside the
overlay, and settings rows used a legacy grid with a floating save
button.
Evidence: messageparts.ts adds groupParts (order-preserving grouping of
consecutive process parts, unit-tested) plus humanSize/artifactIcon
helpers; Conversation renders blocks in original order and the artifact
chip becomes icon + open + download; LiveState.parts accumulates events
in arrival order including artifact_ref so live view matches the
persisted message; ArtifactsPanel gains search/kind filter/upload and
per-row preview/download/delete-confirm; DocViewer is a single-layer
OverlayHost with pdf iframe, csv/json monospace, and a binary info card
with a download CTA; SettingsModal migrates to @ui SettingRow with the
save button pinned in the shell actions bar; inbox cards receive the
docBridge so result cards can open artifacts. tsc clean, vitest 20
passed, production build succeeds.
Impact: message timelines read in true execution order during and after
runs; every artifact is previewable and downloadable from the message
chip, the workspace panel, and the viewer; settings render on the fixed
two-column shell.
Refs: task feature/chat-order-artifact-files (ui# c3e1f3b backend#
44b51fa).