Found while running MOTIR-2098 (the hasDescription list-row projection), logged rather than absorbed per notes.html #27 — a drive-by fix gets its own card and its own PR.
workItemRepository.findArchivedByProject (lib/repositories/workItemRepository.ts) SELECTs id, kind, key, identifier, title, status, priority, assigneeId, reporterId, dueDate, estimateMinutes, storyPoints, updatedAt plus the archive bits — it never projects w."type".
But its row type declares it:
export interface ArchivedWorkItemRow extends WorkItemListRow { … } // WorkItemListRow.type: WorkItemType | null
and toArchivedWorkItemDto spreads toWorkItemListItemDto(row), which reads row.type. So ArchivedWorkItemDto.type is undefined on every archived row — not null, which is what the DTO's own contract promises for a container.
$queryRaw<ArchivedWorkItemRow[]> is an unchecked cast: TypeScript takes the row shape on faith, so a column the SELECT omits is a runtime hole, never a compile error. Exactly the class MOTIR-2098 had to guard against by hand when it added hasDescription to the same base row (it projects the new column in all five reads for this reason).
app/(authed)/items/archived/_components/archivedRows.ts shapes archived rows off kind only and never reads .type, so nothing renders wrong right now. The bug is the TRAP: the next consumer to read type on an archived row — an archived-view Type chip mirroring the /items one (8.8.9), a filter, an export — gets undefined and a silently blank cell, and its unit test will pass because the fixtures set type by hand (tests/components/archived-work-items.test.tsx does).
w."type"::text AS "type" in findArchivedByProject, mirroring how findProjectIssuesFlat does it (the ::text cast is what makes $queryRaw return the plain enum label).tests/integration/work-items/archived-list.test.ts: an archived LEAF comes back with its work type, an archived container with null — the same pair issue-list-view.test.ts pins for the active read.Audit the other $queryRaw reads whose row type EXTENDS WorkItemListRow for the same omission, since the cast hides them all: findProjectIssuesKeyset, findProjectTreeLevel, findArchivedByProject. If a cheap compile-time guard exists (e.g. a satisfies-style column checklist next to each SELECT), name it as a follow-up rather than building it here.
findArchivedByProject projects type; an archived leaf's DTO carries its work type and an archived epic/story carries null — never undefined.