# Phase 7: Archive Lifecycle Controls - Context

**Gathered:** 2026-03-10
**Status:** Ready for planning

<domain>
## Phase Boundary

Add archive filtering and automatic returned-status archiving with override control. Cards have a three-state lifecycle: Active → To Be Archived → Archived. Users can toggle archived card visibility per discovery mode and manually archive/unarchive any card.

</domain>

<decisions>
## Implementation Decisions

### Archive toggle placement
- "Show archived" is a chip in the existing ChipBar component, alongside status filter chips
- Chip appears in all four discovery modes
- Toggle state is per-discovery-mode (stored in ModeState), resets to OFF on app start
- Default: OFF (archived cards hidden)

### Archive toggle and search interaction
- When "Show archived" is OFF, search respects the toggle and excludes archived cards
- When archived results exist but are hidden, show a dynamic message at the bottom of search results: "N archived results hidden" with a button to reveal them (toggles the chip ON for that mode)

### Auto-archive trigger
- Auto-archive fires when shipment_status transitions to exactly "Returned" — not "Return In Transit"
- Archive flag is computed during projection (when building DashboardCardViewModel from domain data)
- One-way latch: once auto-archived, the flag persists even if status changes away from "Returned". Only manual unarchive clears it

### Three-state archive lifecycle
- **Active** → normal card, fully visible
- **To Be Archived** → dimmed styling (same as archived visual treatment), but visible even without "Show archived" toggle. Cards always enter this state first, whether auto-archived or manually archived
- **Archived** → hidden by default, visible only when "Show archived" chip is active (dimmed opacity)
- Transition from "To Be Archived" to "Archived" occurs on app restart OR after 12 hours, whichever comes first
- "To Be Archived" cards show "Archive Now" in hover controls to skip the waiting period

### Manual override behavior
- Card-level hover-reveal controls (new): bundles Refresh (moved from always-visible to hover-reveal) and Archive/Unarchive button
- Any card can be manually archived regardless of status (not limited to "Returned" cards)
- Manual unarchive wins over auto-archive: once manually unarchived, auto-archive rule does not re-trigger for that card (sticky override persists through syncs)
- "To Be Archived" cards show only "Archive Now" (no separate Unarchive button at this stage)

### Visual treatment
- Archived and "To Be Archived" cards rendered with ~50% opacity / desaturated colors
- When "Show archived" is ON, archived cards are mixed into their natural sort position (not grouped at end)
- No separate section or divider — opacity difference provides sufficient visual distinction

### Toast notifications
- Manual archive: "Archived [name]. Undo?" — 5-second toast with undo action
- Manual "Archive Now" from TBA state: same toast format with undo to revert to Active
- Auto-archive (sync detects "Returned"): "N cards auto-archived. Undo?" — 5-second toast showing count, not names
- Undo reverts card from "To Be Archived" back to Active state

### Claude's Discretion
- Exact opacity/desaturation values for dimmed cards
- Toast component implementation and positioning
- How to track the 12-hour TBA timer (timestamp field on archive record)
- Database schema for archive state (likely an archive_state enum column + archived_at timestamp)
- Whether "Archive Now" uses same icon as initial archive or a different variant

</decisions>

<specifics>
## Specific Ideas

- The "N archived results hidden" message during search is a nice touch for discoverability — should feel like a subtle inline hint, not an intrusive banner
- Toast for auto-archive events uses count ("2 cards auto-archived") instead of listing names, to avoid spam when multiple cards get returned in one sync
- The "To Be Archived" transitional state gives users a grace period to notice and undo before cards fully disappear

</specifics>

<code_context>
## Existing Code Insights

### Reusable Assets
- ChipBar component (chip-bar.slint): Toggle chips for filter states — "Show archived" fits as a new chip
- RecipientCard component (card.slint): Has hover-reveal pattern at item level — extend to card-level controls
- ModeState in discovery.rs: Per-mode persistent state with search text and filters — add show_archived flag here
- filter_cards_by_search / filter_cards_by_status (discovery.rs): Composable filter pipeline — add archive filter stage
- RecipientOverride on domain model: Existing pattern for manual overrides that survive sync

### Established Patterns
- Filter pipeline composes: search filter → status filter → push to Slint model — archive filter slots in before push
- Per-mode state array [ModeState; 4] indexed by DiscoveryMode::index() — archive toggle fits as a boolean field
- Soft-delete pattern already used for items (is_active flag) — similar approach for archive state
- DashboardCardViewModel built during projection — archive state computation fits here

### Integration Points
- projection.rs: Where DashboardCardViewModel is built from domain data — add archive flag computation
- main.rs: Status values include "Returned" in seed data — auto-archive trigger matches this
- dashboard.slint: Card grid rendering — needs opacity binding based on archive state
- state.rs: CardRefreshState pattern — similar enum approach for archive state tracking

</code_context>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope

</deferred>

---

*Phase: 07-archive-lifecycle-controls*
*Context gathered: 2026-03-10*
