Type: Bug (code) · UI / state-correctness. Two defects, one cause: the archived state never reaches the two read surfaces that render readiness.
Parent: MOTIR-1464 — the open "Planner self-improvement · auto-reported quality bugs" epic, the de-facto home for agent-discovered quality bugs (Yue's call, 2026-08-03; filed at root first). NOT parented by where the defective code lives: that would be Story 2.5 (the peek, 2.5.19/2.5.21), Story 2.4 (the detail relationships panel) and 7.8.14 (archive/restore) — all done, so per the bug-parent rule the bug is not re-attached into a sealed epic. Nothing open is blocked by it.
Discovered in: out-of-band manual dogfooding, 2026-08-03. Reported: "the archived item still shows the ready banner in the quick view modal and detail page, and archived status is not showing in the quick view modal."
Archive a work item that is still in a todo-category status, then look at it:
The banner is not merely cosmetic — it contradicts the system's own ready set. workItemRepository's ready-set query filters w."archivedAt" IS NULL, so an archived item can never be returned by /ready, list_ready or claim_next_ready. The UI promises work that the ready path will never hand out.
origin/main @ c4ec51b1)Archiving is a pure soft-delete: workItemsService.archiveWorkItem (~line 2072) stamps archivedAt and records the revision — it does not touch status, by design ("archiving a node hides only that node from active views"). So an archived item keeps its todo status, and every gate that keys off status alone still fires.
Both readiness gates key off status alone:
app/(authed)/items/[key]/_components/RelationshipsPanel.tsx:156: const showReadiness = currentCategory === 'todo';. The component receives readiness, currentStatus and workflow, but no archived input at all — it could not gate on it even if it wanted to. Meanwhile app/(authed)/items/[key]/page.tsx:416 already computes isArchived for the ArchivedBanner a few lines above, and never passes it down.app/(authed)/items/_components/IssueQuickViewPanel.tsx:302: data.readiness && data.statusCategory === 'todo'. Same shape, same omission.The peek's missing archived state has its own precise cause: QuickViewData (lib/dto/quickView.ts) carries no archived field. There is no archivedAt, no archivedBy, no isArchived — the interface goes straight from updatedAt to parent. lib/mappers/quickViewMappers.ts maps from the full IssueDetailDto, which does carry item.archivedAt and detail.archivedBy (the detail page's ArchivedBanner reads exactly those), so the data is present at the mapper and simply dropped on the floor. The peek panel therefore cannot render an archived signal — it never receives one.
So: one omission (archived state not threaded to the read surfaces) with two visible faces. Neither is a design defect — the detail page's own ArchivedBanner shows the intent was understood; the readiness gate was just written before/independently of archive and never revisited. No notes.html entry warranted.
todo-category status (To Do or Blocked) — ideally one with no open blockers, so the banner is the green "Ready to start" rather than the peach "Blocked".archive_work_item).?peek= from the /items list) → Actual: the green "Ready to start" badge shows, and nothing anywhere in the panel says the item is archived. Expected: no readiness banner, and a clear archived signal.RelationshipsPanel (the page already has isArchived at page.tsx:416 — pass it) and add the field to QuickViewData, then make both conditions !isArchived && category === 'todo'. Prefer deriving from a single shared predicate rather than duplicating the boolean expression at two call sites, so the next readiness surface inherits it.QuickViewData and map them in toQuickViewData from detail.item.archivedAt / detail.archivedBy — both already ride the aggregate the mapper receives, so this costs no extra read. Note the read-back-DTO ripple: adding a field to this DTO breaks exact-shape route/mapper tests, so run the whole affected test dirs, not one file.ArchivedBanner treatment/vocabulary rather than inventing a second archived language; the peek is read-only, so decide explicitly whether Restore belongs there (the detail banner's Restore is canEdit-gated) and say which way you went in the Resolution. New strings need en.json + zh.json parity.todo renders no readiness badge — one component test per surface — plus a mapper test asserting the archived fields survive into QuickViewData, and a peek test asserting the archived signal renders. Write the failing repro first.Resolution: (open — the close-out subtask fills this)