feat(board): card-face indicators — stage / PR / agent / round / stall + density toggle #417
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!417
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev/413"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Extends the Kanban board card face with six new indicators and a density toggle, so operators can read board health at a glance without opening each card.
Backend (
GET /board): addsstage,pr_state,round,stalled_for_ms, andlast_event_labelto every card; addsdrafttoBoardCardPr.Frontend (
BoardCardView): top-left stage icon + round badge, top-right PR state pill, 24 px agent avatar slot, stall age withtext-warning/text-errorat per-stage thresholds (fromdocs/label-routing.md), and a design-review badge derived fromdesign:accepted/design:rejectedlabels.Density toggle in the filter toolbar, persisted to
localStorage("board.density"):compact(stage + title + stall),default(full face),detailed(+ last-event line).Test plan
board-card.test.tsxtests: full face at default/detailed density, compact-only elements, stall threshold colour classes.board.test.tscases: all five card statuses carry correctstage,pr_state,last_event_label; draft PR surfacespr_state=draft.Closes #413
CI green. All six AC indicators are wired up end-to-end, density toggle persists correctly, tests cover thresholds and compact/detailed modes. Two nits and one dead-code note below — none blocking.
doc-gap
apps/web/src/components/board/board-card.tsx(useElapsedLabel):fmtDuration(live + tick * 0)—tick * 0is always 0. The re-render fromsetTickis what drives the update (sinceDate.now()is re-evaluated each render), so this is functionally correct, but the expression is misleading. PreferfmtDuration(live)with a comment explaining thetickstate drives the re-render.doc-gap
apps/server/src/domain/views/board.ts—roundis hardcoded to0on every card path. The round badge renders only whencard.round > 1, so it will never appear in production with this implementation. If round tracking isn't available yet, add a// TODO: wire from task history once round counter is persistedcomment so the gap is explicit.doc-gap
apps/server/src/domain/views/board.ts(derivePrState):BoardCardPrStateincludes"merged", andPR_STATE_LABELS/PR_STATE_COLORShandle it in the UI, butderivePrStateonly ever returns"draft" | "open" | "none"— merged PRs are filtered out bylistOpenPullRequests. The"merged"branch in the UI is dead code for now. Fine if this is intentional for a future closed-issues view, but worth a comment.6aec7bbe94d3fc1ca4fad3fc1ca4fa115ab421bd