Problem
The Factory sidebar uses cascading <select> dropdowns (Project → Ticket → Run) to navigate runs. This requires 3 clicks to reach a run and provides no at-a-glance view of all available runs or their statuses.
Proposed solution
Add a RunList component to the sidebar that shows all runs in a flat, scrollable list sorted by most recent. Each item displays a color-coded status indicator (CGA-16 palette), is clickable to select the run for viewing, and has a dismiss (×) button. A "Clear all" button dismisses all visible runs at once.
The fetchProjects call is lifted from RunSelector to App.tsx so both components share the same ProjectIndex data. RunSelector is refactored to accept the index as a prop.
Key considerations
- Dismiss state scope: Uses React
useState (session-scoped). Dismissed runs reset on page refresh, matching "keep until manually removed" without cross-session persistence.
- Run key uniqueness: Runs are identified by
projectSlug/runId composite key.
- RunSelector preserved: The existing cascading dropdowns remain alongside the new list. Their removal is deferred to a follow-up ticket.
- Status indicators: Unicode symbols with CGA-16 colors —
▶ cyan (in_progress), ✔ green (completed), ✘ red (failed), ⚠ yellow (needs_manual_review).
Acceptance criteria
Files
New:
packages/factory/src/shared/types/api.ts — FlatRunInfo type
packages/factory/src/client/helpers/flatten-project-index.ts + tests
packages/factory/src/client/hooks/useDismissedRuns.ts + tests
packages/factory/src/client/components/RunList.tsx + CSS + tests
Modified:
packages/factory/src/client/App.tsx — lift fetch, wire RunList
packages/factory/src/client/components/RunSelector.tsx — accept index prop
- Test files for App and RunSelector
Problem
The Factory sidebar uses cascading
<select>dropdowns (Project → Ticket → Run) to navigate runs. This requires 3 clicks to reach a run and provides no at-a-glance view of all available runs or their statuses.Proposed solution
Add a
RunListcomponent to the sidebar that shows all runs in a flat, scrollable list sorted by most recent. Each item displays a color-coded status indicator (CGA-16 palette), is clickable to select the run for viewing, and has a dismiss (×) button. A "Clear all" button dismisses all visible runs at once.The
fetchProjectscall is lifted fromRunSelectortoApp.tsxso both components share the sameProjectIndexdata.RunSelectoris refactored to accept the index as a prop.Key considerations
useState(session-scoped). Dismissed runs reset on page refresh, matching "keep until manually removed" without cross-session persistence.projectSlug/runIdcomposite key.▶cyan (in_progress),✔green (completed),✘red (failed),⚠yellow (needs_manual_review).Acceptance criteria
startedAtdescendingRunSelectorFiles
New:
packages/factory/src/shared/types/api.ts—FlatRunInfotypepackages/factory/src/client/helpers/flatten-project-index.ts+ testspackages/factory/src/client/hooks/useDismissedRuns.ts+ testspackages/factory/src/client/components/RunList.tsx+ CSS + testsModified:
packages/factory/src/client/App.tsx— lift fetch, wire RunListpackages/factory/src/client/components/RunSelector.tsx— acceptindexprop