MOTIR-979Done
2.9.2 Read path — list archived work items (paginated, archivedAt IS NOT NULL)
Estimate: 50m · Type: code
The read path for archived items — the inverse of the pervasive archivedAt IS NULL filter. Today nothing lists archived items.
- Repository (
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 byarchivedAt 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. - Service (
lib/services/workItemsService.ts): alistArchivedWorkItems(params, ctx)that gates read access (per the 2.9.1 view-access decision —canBrowse), maps to a paginated DTO vialib/mappers/*, and includes thearchivedAt+ archived-by actor (from the latestarchivedrevision) the view needs. - Transport: expose via a server action or
GETroute consistent with how/issuesreads (4-layer: route/action → service → repo → Prisma; no Prisma in the route).
Acceptance criteria
- A new repo read returns ONLY archived items (
archivedAt IS NOT NULL), scoped + ordered byarchivedAt DESC, paginated with a total count; non-archived items never appear. - A
listArchivedWorkItemsservice method returns the paginated DTO (incl. archived-at + archived-by) and enforces the read-access gate; respects the page-size clamp. - Vitest covers: only-archived filter, scope isolation, pagination/clamp, empty result. (Per the coverage gate — subtask-targeted tests; CI verifies the per-file branch/fn/line bar.)
Context refs
lib/repositories/workItemRepository.ts(thearchivedAt IS NULLreads to invert;listWorkItems/listRootIssuesscoping)lib/services/workItemsService.ts:404clampIssuePageSize/clampTreePage/ISSUE_LIST_PAGE_SIZE(reuse),listWorkItems(shape)lib/repositories/workItemRepository.ts:2008-2027archive/unarchive(the column semantics)motir-core/CLAUDE.md(4-layer: write-vs-readtxrules; DTO mapping)