Parent: #991
Summary
The app has a typed .failed collection state, but multiple views treat every non-loaded empty collection as “still loading.” A failed request can leave an endless skeleton with no explanation or retry even though ProjectSession.statusMessage recorded an error elsewhere.
Evidence
macapp/Sources/GoCodeUI/ActivityView.swift:33-37 — failed empty tasks render LoadingPlaceholder.
ActivityView.swift:45-47 — failed runs with runs == nil render LoadingPlaceholder.
macapp/Sources/GoCodeUI/SessionsView.swift:24-39 — failed empty conversations render loading rows.
SessionsView.swift:156-169 — failed rewind-point loads render loading rows.
macapp/Sources/GoCodeUI/ModelSettingsView.swift:181-186,235-247 — failed provider loads render loading placeholders.
CollectionLoadState.failed has no failure-presentation contract.
Impact
Network/server failures masquerade as indefinite work. Users cannot tell whether to wait, retry, or fix connectivity, and several affected screens do not render statusMessage at all.
Scope
- Add one shared inline failure state with a concise reason and Retry action.
- Render it for failed empty conversations, tasks, runs, rewind points, providers, profiles, and models.
- When stale data exists, retain it and show a non-blocking refresh-error notice instead of replacing it.
- Keep
.idle, .loading, .loaded(empty), and .failed visually and semantically distinct.
Tests first
- Table-driven tests for presentation derived from state + item count + stale-data presence.
- Regression coverage for Activity, Sessions, Checkpoints, and Model Settings production call sites.
- Stub-client tests: 500/transport failure exposes Retry; retry success transitions to loaded content/empty state.
Acceptance criteria
Parent: #991
Summary
The app has a typed
.failedcollection state, but multiple views treat every non-loaded empty collection as “still loading.” A failed request can leave an endless skeleton with no explanation or retry even thoughProjectSession.statusMessagerecorded an error elsewhere.Evidence
macapp/Sources/GoCodeUI/ActivityView.swift:33-37— failed empty tasks renderLoadingPlaceholder.ActivityView.swift:45-47— failed runs withruns == nilrenderLoadingPlaceholder.macapp/Sources/GoCodeUI/SessionsView.swift:24-39— failed empty conversations render loading rows.SessionsView.swift:156-169— failed rewind-point loads render loading rows.macapp/Sources/GoCodeUI/ModelSettingsView.swift:181-186,235-247— failed provider loads render loading placeholders.CollectionLoadState.failedhas no failure-presentation contract.Impact
Network/server failures masquerade as indefinite work. Users cannot tell whether to wait, retry, or fix connectivity, and several affected screens do not render
statusMessageat all.Scope
.idle,.loading,.loaded(empty), and.failedvisually and semantically distinct.Tests first
Acceptance criteria
.failedcollection state renders an indefinite skeleton.swift test, Swift build, formatting, and strict format lint pass.