Estimate: 50m · Type: code
The read path for archived items — the inverse of the pervasive archivedAt IS NULL filter. Today nothing lists archived items.
lib/repositories/workItemRepository.ts): add a single-op read that returns archived items for a project (archivedAt IS NOT NULL), workspace+project scoped (mirror the scoping of the existing reads), ordered by archivedAt DESC, paginated (reuse the existing clamp infra — ISSUE_LIST_PAGE_SIZE / clampIssuePageSize / take+offset) and returning a total count. FLAT list, not a forest (archive is single-node; archived items drop out of subtrees) — do NOT reuse the recursive forest CTE.lib/services/workItemsService.ts): a listArchivedWorkItems(params, ctx) that gates read access (per the 2.9.1 view-access decision — canBrowse), maps to a paginated DTO via lib/mappers/*, and includes the archivedAt + archived-by actor (from the latest archived revision) the view needs.GET route consistent with how /issues reads (4-layer: route/action → service → repo → Prisma; no Prisma in the route).archivedAt IS NOT NULL), scoped + ordered by archivedAt DESC, paginated with a total count; non-archived items never appear.listArchivedWorkItems service method returns the paginated DTO (incl. archived-at + archived-by) and enforces the read-access gate; respects the page-size clamp.lib/repositories/workItemRepository.ts (the archivedAt IS NULL reads to invert; listWorkItems/listRootIssues scoping)lib/services/workItemsService.ts:404 clampIssuePageSize / clampTreePage / ISSUE_LIST_PAGE_SIZE (reuse), listWorkItems (shape)lib/repositories/workItemRepository.ts:2008-2027 archive / unarchive (the column semantics)motir-core/CLAUDE.md (4-layer: write-vs-read tx rules; DTO mapping)