MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-2050

An ARCHIVED work item still shows the green "Ready to start" banner on the detail page and in the quick-view peek — and the peek shows no archived state at all (neither surface gates on `archivedAt`)

Done
Description

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."

Symptom (observed)

Archive a work item that is still in a todo-category status, then look at it:

  1. Detail page — the page renders BOTH the "Archived" banner and, further down in the Relationships section, the green "Ready to start" badge. The two statements contradict each other on the same screen.
  2. Quick-view peek — the same green "Ready to start" badge appears at the top of the panel.
  3. Quick-view peek — there is no archived indicator anywhere in the peek. Nothing distinguishes an archived item from a live one: no banner, no chip, no dimming, no Restore affordance. The peek says an archived item is ready to be picked up.

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.

Root cause (VERIFIED against 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:

  • Detail pageapp/(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.
  • Quick-view peekapp/(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.

Reproduce

  1. Take a work item in a 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".
  2. Archive it (detail page ··· menu, or archive_work_item).
  3. Open its detail page → Actual: the "Archived" banner and the green "Ready to start" badge render on the same page. Expected: no readiness banner on an archived item.
  4. Open the same item in the quick-view peek (?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.

Fix direction (for the close-out subtask)

  • Gate readiness on archived at both sites. Thread the archived state into 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.
  • Carry the archived state into the peek payload. Add the field(s) to 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.
  • Render the archived signal in the peek. Reuse the detail page's 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.
  • Check the neighbours while you are in here (report findings; do not silently widen scope): does an archived item render a readiness banner on any other surface, and does an archived BLOCKER still count as an open blocker in the readiness verdict? Both are the same "archived is invisible to readiness" class. Anything real gets its own card.
  • Tests: archived + 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)