2.9.5 Archived-list row ⋯ Delete… affordance + optimistic removal
Estimate: 40m · Type: code
Add permanent Delete to the archived work items list (app/(authed)/issues/archived/_components/ArchivedWorkItemsList.tsx, 2.9.3) per delete-confirm.mock.html + design-notes.md §2.9.7. Restore stays the prominent inline [Restore] button (canEdit); Delete goes in a per-row ⋯ overflow menu as a single danger Delete… row, gated canManage — the row ⋯ is purely the Delete affordance (NOT the full edit/copy/archive menu), so it maps 1:1 to the capability.
Re-scoped (2026-06-16 re-plan). This card originally claimed "reuse the modal as-is, no new endpoint, no new design". Its design gate 2.9.7 (MOTIR-997) actually requires a
getDeletePreviewlive/archived split + a dialog variant + the⋯placement + new copy — so the work was split: 2.9.9 / MOTIR-999 (preview backend) and 2.9.10 (dialog variant) now precede this, which is just the LIST affordance. Detail is 2.9.11.
- Gate matrix (total over the 4 combos; each affordance HIDDEN — never shown-disabled — when its gate is unmet): canEdit→
[Restore], canManage→⋯(Delete…); both→both; neither→actions column dropped (the existing view-only state). ReadcanManagefromuseProjectAccess()(provider mounted in the authed layout — verified;WorkItemRowActionsreads it the same way) — no new server prop. The island today only takescanEdit. - Grid: widen the actions column 120→150px to seat
[Restore]+⋯(thecanEdittemplate only; view-only template unchanged). - Confirm: open the archived variant of
DeleteWorkItemDialog(2.9.10), already wired tofetchDeletePreview+deleteWorkItem(subtree cascade,canManage). No new endpoint/modal here. - Page state after delete (CLAUDE.md § page-state — the list is a CLIENT ISLAND): on the delete 200, remove the row LOCALLY (optimistic, seq-guarded, like the existing restore-removal set) + decrement the pager total; do NOT
router.refresh(). The deleted subtree disappears from the active /issues + board on their next read.
Design: delete-confirm.mock.html (row ⋯ → Delete… vocab + gate matrix) + archived.mock.html (the list this extends). Reuse the RowActionsMenu/Popover vocab; no new primitive.
Acceptance criteria
- An archived row shows
Delete…in a⋯menu to managers (canManage); non-managers don't see the⋯; Restore stays inline (canEdit); neither → column dropped. Delete…opens the 2.9.10 archived confirm (cascade count + live-descendant warning); confirming deletes the subtree and removes the row from the archived view (optimistic, seq-guarded, pager decremented) after the delete 200.- Reuses
DeleteWorkItemDialog(archived variant) +fetchDeletePreview+deleteWorkItem— no new endpoint. Component test covers render +canManagegating + delete-from-archived removal; coverage gate holds.
Context refs
app/(authed)/issues/archived/_components/ArchivedWorkItemsList.tsx,archived/page.tsx,_components/archivedRows.tsapp/(authed)/_components/ProjectAccessProvider.tsx(useProjectAccess→canManage);app/(authed)/issues/_components/WorkItemRowActions.tsx(the active-list pattern)components/issues/actions/DeleteWorkItemDialog.tsx(2.9.10 archived variant),WorkItemActionsMenu.tsx(the ⋯/Popover vocab)motir-core/CLAUDE.md§ "Page state after a mutation" + § "E2E authoritative signal"- design:
delete-confirm.mock.html,archived.mock.html,design-notes.md§2.9.7