---
status: resolved
phase: 10-refresh-auto-archive-wiring
source: [10-01-SUMMARY.md, 10-02-SUMMARY.md]
started: 2026-03-20T23:50:00Z
updated: 2026-03-21T00:45:00Z
---

## Current Test

[testing complete]

## Tests

### 1. Cold Start Smoke Test
expected: Kill any running instance. Start fresh with `cargo run -p app`. App boots without errors, dashboard loads, seed cards display. Auto-archive fires on initial load.
result: issue
reported: "everything loads fine. none of the sample cards have the Returned status, so auto-archive on load can't be tested. also, changing a card to To Be Archived state, the state does not persist through to the next app restart"
severity: major

### 2. Refresh-All Button Click
expected: Click the refresh-all button in the dashboard header. Button should dim/disable during refresh and show "Refreshing..." label. After completion, button re-enables. Cards should update with any new data. If refresh fails, an error toast appears.
result: issue
reported: "refresh all button reverts the TBA or Archived status of cards. everything it does seems instant, so there is no time for it to change to the Refreshing... state. no error toasts show either."
severity: major

### 3. F5 Key Triggers Refresh-All
expected: Press F5 while the dashboard is focused. Same behavior as clicking the refresh-all button — button dims, "Refreshing..." label appears, cards refresh, button re-enables.
result: pass

### 4. Per-Card Refresh via Ellipsis Menu
expected: Click the three-dots menu on any card, then click "Refresh". Card shows in-flight state during refresh. On success, card data updates and archive state recomputes. On failure, three-dots button turns amber and menu shows "Refresh failed - retry".
result: issue
reported: "all the same issues of test 2 apply. TBA/Archive state reverts, no visible in flight state, no error signaling"
severity: major

### 5. Refresh Error Indicator
expected: If a per-card refresh fails, the three-dots button background turns amber (#4a2810/#5a3818). The ellipsis menu item text changes to "Refresh failed - retry". Clicking retry attempts refresh again.
result: skipped
reason: unable to test — refresh never fails with seed data, no error state observable

### 6. Auto-Archive After Refresh
expected: After a successful refresh-all, auto-archive recomputes for every card. Cards whose status changed to "Returned" should have their archive_state updated. After per-card refresh success, that specific card's archive_state recomputes.
result: skipped
reason: unable to test — none of the test cards are in the Returned state

## Summary

total: 6
passed: 1
issues: 3
pending: 0
skipped: 2

## Gaps

- truth: "Auto-archive state persists across app restarts"
  status: resolved
  reason: "User reported: changing a card to To Be Archived state, the state does not persist through to the next app restart"
  severity: major
  test: 1
  root_cause: "ArchiveStore is purely in-memory HashMap with zero disk persistence. DashboardRuntime::default() creates a fresh empty store every launch. Any manual TBA state set by the user during the previous session is never serialized to disk."
  artifacts:
    - path: "crates/app/src/dashboard/archive.rs"
      issue: "ArchiveStore has no serde derives, no file path, no load/save methods"
    - path: "crates/app/src/main.rs"
      issue: "DashboardRuntime::default() creates fresh empty ArchiveStore on every launch"
  missing:
    - "Add serde serialization to ArchiveStore/ArchiveRecord"
    - "Save to JSON file on every mutation (manual_archive, manual_unarchive, archive_now, undo_archive, compute_and_store)"
    - "Load from file in ArchiveStore::new() before init loop runs"
  debug_session: ".planning/debug/tba-state-not-persisting.md"

- truth: "Refresh-all preserves TBA/Archived state and shows in-flight UI feedback"
  status: resolved
  reason: "User reported: refresh all button reverts the TBA or Archived status of cards. everything it does seems instant, so there is no time for it to change to the Refreshing... state. no error toasts show either."
  severity: major
  test: 2
  root_cause: "Two bugs: (1) compute_archive_state() only preserves state via auto_archived=true latch or manual_unarchive_override=true. Cards manually archived via manual_archive() have auto_archived=false, so compute_and_store during refresh falls through to ArchiveRecord::default() (Active), wiping TBA/Archived state. (2) on_refresh_all_clicked is fully synchronous — sets Refreshing... label, dispatches instantly (NoopClient), restores label, all in one callback. Slint never repaints between. Error toasts unreachable with NoopClient (returns Ok(()))."
  artifacts:
    - path: "crates/app/src/dashboard/archive.rs"
      issue: "compute_archive_state has no gate for manually-set non-Active states (auto_archived=false falls through to default Active)"
    - path: "crates/app/src/main.rs"
      issue: "on_refresh_all_clicked is synchronous with no event loop yield"
  missing:
    - "Add gate in compute_archive_state for manually-archived cards (state != Active regardless of auto_archived)"
    - "Split refresh into two event loop ticks or defer async to production client"
  debug_session: ".planning/debug/refresh-reverts-archive-state.md"

- truth: "Per-card refresh preserves TBA/Archived state and shows in-flight UI feedback and error signaling"
  status: resolved
  reason: "User reported: all the same issues of test 2 apply. TBA/Archive state reverts, no visible in flight state, no error signaling"
  severity: major
  test: 4
  root_cause: "Same two bugs as refresh-all: (1) compute_archive_state wipes manually-archived state during post-refresh recompute. (2) on_card_refresh is fully synchronous — in-flight state set then immediately cleared within one callback. Additionally, NoopClient does not override refresh_recipient (default returns Ok(())), so error path (refresh_error=true, amber styling) is unreachable during testing."
  artifacts:
    - path: "crates/app/src/dashboard/archive.rs"
      issue: "compute_archive_state does not preserve manually-archived records"
    - path: "crates/app/src/main.rs"
      issue: "on_card_refresh synchronous dispatch; NoopClient missing refresh error overrides"
  missing:
    - "Same compute_archive_state fix as gap 2"
    - "Override refresh_recipient and refresh_all on NoopClient to return Err(...) for testability"
  debug_session: ".planning/debug/per-card-refresh-issues.md"
