Type: bug · Parent: Epic 2 · Surfaces: issue detail relationships panel (Subtask 2.4.5) + issue-list quick-view peek (Subtask 2.5.21) · Status: fixed (PR #250, merged) · Reported by: Yue.
The green "Ready to start" readiness banner only appears on a work item that has at least one is_blocked_by blocker (all of them terminal). An item with no depended-on work item at all shows no banner — even though "nothing blocks it" is the most ready an item can be. It SHOULD show "Ready to start" too: a todo-category item with zero open blockers is ready, whether that is because every blocker resolved OR because it never had any.
Repro: sign in as zhuyue@prodect.co / !QAZ1qaz, open the moooon / prodect project, open any todo-status issue that has no "blocked by" links, and observe the relationships panel shows no readiness banner. Open one that IS blocked by an issue that is already done → it correctly shows the green "Ready to start". The no-dependency item should match. Same gap in the issue-list quick-view peek.
Root cause. NOT the service and NOT the badge — both already handle the no-blocker case correctly. workItemsService.getReadiness returns ready: true with an empty open-blocker set when an item has no blockers ("An item with no blockers → ready"), and components/ui/ReadinessBadge renders the green "Ready to start" state whenever ready is true (its prop doc: "true iff every blocker is terminal or none exist"). The suppression is purely the call-site gate in the two consuming components, which short-circuit on the blocker COUNT before ever rendering the badge:
app/(authed)/issues/[key]/_components/RelationshipsPanel.tsx — const showReadiness = blockedBy.length > 0 && currentCategory === 'todo';app/(authed)/issues/_components/IssueQuickViewContent.tsx — detail.blockedBy.length > 0 ? {…} : null (mirrors the same rule by design).Both carry a comment rationalizing it ("an item nothing blocks has no signal to give") — that decision is what is being reversed: a no-dependency todo item DOES have a signal, "Ready to start".
Fix. Drop the blockedBy.length > 0 precondition from BOTH gates; keep the category === 'todo' guard (readiness is still moot once in-progress / done). The banner then renders off the readiness verdict alone: ready (no blockers, or all terminal) → green "Ready to start"; not-ready → peach "Blocked" naming the open blockers. No service or DTO change — the readiness verdict and ReadinessBadge already cover the empty-blocker case. Update the two stale "shows only when there ARE blockers" comments accordingly.
is_blocked_by blockers shows the green "Ready to start" banner on the issue detail relationships panel.todo guard is retained on both surfaces).app/(authed)/issues/[key]/_components/RelationshipsPanel.tsx — the showReadiness gate (the primary fix site) + its rationalizing commentapp/(authed)/issues/_components/IssueQuickViewContent.tsx — the mirrored quick-view gatecomponents/ui/ReadinessBadge.tsx — already renders the ready state for ready: true (no change expected)lib/services/workItemsService.ts — getReadiness / isReady (already returns ready: true, empty blockers, for the no-dependency case — no change expected)design/work-items/relationships.mock.html — the readiness-banner design sourceResolution (PR #250, merged). Dropped the blockedBy.length > 0 precondition from BOTH call-site gates, keeping only the category todo guard: RelationshipsPanel’s showReadiness is now just currentCategory === 'todo', and IssueQuickViewContent always builds the readiness verdict (the quick-view panel still suppresses it past todo via statusCategory). No service / DTO / badge change — exactly as diagnosed. Regression coverage added: relationships-panel.test.tsx + issue-quick-view.test.tsx assert a no-blocker todo item renders "Ready to start" on both surfaces, and issue-detail-flow.spec.ts (E2E) asserts a fresh item reads "Ready to start" before any link is added, then flips to "Blocked".