CR-2026-140 added a file-type badge and View action to the chat upload-confirmation bubble (UploadResultCard). This only renders in the same browser session, immediately after upload — it never survives a page reload. UploadResultCard renders from turn.uploadResults, populated only by the live optimistic-send path. toDisplayTurns(), which rebuilds turns from reloaded history, has no handling for uploadResults at all — the whole card never mounts on reload, leaving only plain text.
Extend structured_data's union (currently HeldItemsStructuredData and MatchedFilesStructuredData, CR-2026-138) with a third variant, UploadResultsStructuredData. Populate it at the upload endpoint's turn-persistence call site — currently entirely separate from converse.py's step 7, where CR-2026-138's mechanism lives. toDisplayTurns() gains a case for the new variant, rebuilding uploadResults from reloaded history the same way it already rebuilds heldItems/matchedFiles.
No conflict. Reinforces the seed's Memory commitment — accumulates with provenance, reliably recallable — the same reasoning that grounded CR-2026-138.
Must be tested with a real page reload, not just same-session state — the exact gap CR-2026-140's own verification missed. Verification must use a synthetic engagement created and destroyed for this purpose only, never a real engagement (E0060, E0007, E0030, or the shared E0006 test fixture).
No change to HeldCard/SettledCard/MatchedFilesInline (already correct, CR-2026-138/139). No change to the badge/View logic itself, which is correct — only the data path that should feed it after reload.