Replaces the two-row card layout with a single horizontal flex row that
fits within 48-56px height. Adds project badge overflow (max 2 + chip),
hover-reveal menu (opacity-0/group-hover), phase counter (X / Y),
active phase name with separator, and StatusDot pulse behavior.
Removes ProgressBar, status label text, and second row entirely.
Adds Vitest unit tests covering all 6 test groups from the spec.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merge two useEffects in AgentOutputViewer into one to fix race where
agentId reset clears messages after data effect sets them on remount.
Add "commit before signaling" instruction to errand prompts so
Changes tab shows diff after completion.
Add errand.requestChanges procedure that re-spawns an agent in the
existing worktree with user feedback. Replace raw <pre> diff blocks
with syntax-highlighted ErrandDiffView using FileCard components.
Add Output/Changes tabs to the active errand view.
Replaces HQWaitingForInputSection with a two-column inline panel that
lets users answer agent questions directly from HQ without navigating
to /inbox. Adds SSE invalidation for listWaitingAgents/listMessages,
useState for agent selection, and all required mutations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tRPC without superjson serializes Date objects as plain strings/numbers
over the wire. The .toISOString() calls crashed because the values
aren't Date instances on the client. Matches the existing pattern used
elsewhere (e.g. agents page).
Converts /inbox from a 270-line interactive page to a minimal
TanStack Router redirect route. Bookmarked or externally linked
/inbox URLs now redirect cleanly to /hq instead of 404-ing.
InboxList and InboxDetailPanel components are preserved for reuse
in the HQ page (Phase 569ZNKArI1OYRolaOZLhB).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Badge showing agents in waiting_for_input status now appears on HQ nav item.
Inbox link removed from the nav. Adds regression test for navItems structure.
When a refine agent crashes, the Retry dialog now extracts the
user_instruction from the agent's stored prompt and pre-fills the
textarea, so users can re-run with the same instruction without
retyping it.
Merges task KGRrdWohwZ6YcWjOZ0KqF (ReviewTab rawDiff → metadata file list,
phaseId/commitMode wiring) into the viewport virtualization phase branch.
Key resolution decisions:
- Keep viewport virtualization IntersectionObserver logic from HEAD
- Use activeFiles (not undefined `files`) in ReviewTab DiffViewer render — bug fix from incoming
- Keep FileDiff/FileDiffDetail split from HEAD (not deprecated FileChangeType)
- Keep FileDiff['status'] in parse-diff (status lives on base type)
- Drop spurious `comments` prop the incoming branch added to DiffViewer (unused)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TanStack Router plugin was picking up test files under routes/__tests__/,
causing routeTree.gen.ts to regenerate in a loop. Added routeFileIgnorePattern
and removed stale radar.test.tsx.
Covers IntersectionObserver placeholder rendering for 300-file diffs,
single-file bypass, sidebar ref registration, expandAll batch fetching
(25 files → 3 batches of 10), and all FileCard lazy-load states:
default collapsed, loading, success with HunkRows, error+retry, binary,
no-hunks, detail-prop pre-expanded, and collapse/re-expand UX.
Cherry-picks viewport virtualization implementation commit (f804cb19)
onto this branch so the tests run against the actual new code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add isAgentRunning prop to all four radar drilldown dialog components.
When true, subscribe to relevant SSE events and trigger refetch on
matching events for the current agentId. Show a "Last refreshed: just now"
timestamp that ticks to "Xs ago" in the dialog footer. Reset on close.
- CompactionEventsDialog, SubagentSpawnsDialog, QuestionsAskedDialog:
subscribe to agent:waiting events
- InterAgentMessagesDialog: subscribe to conversation:created and
conversation:answered events (matches on fromAgentId)
- Update DrilldownDialogProps type with isAgentRunning?: boolean
- Add test coverage for all new behavior across all four dialogs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add isAgentRunning? to DrilldownDialogProps interface
- Import and render all four dialog components in RadarPage
- Replace MetricCell helper with per-type td elements using data-testid
attributes for reliable test targeting
- Add drilldown state (type/agentId/agentName) and isAgentRunning derivation
- Wire non-zero metric cell onClick handlers to open the correct dialog
- Zero cells retain no onClick handler
- Extend radar.test.tsx with 8 new dialog integration test cases covering
open/close behavior and isAgentRunning prop passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Writes Vitest + RTL tests covering the virtual list threshold (>50 rows),
fallback path (≤50), directory collapse/expand, tab-switch scroll
preservation, file-click callback, and root-level files.
Also aliases react/react-dom to the parent monorepo copies in
vitest.config.ts so all components share the same ReactSharedInternals
dispatcher — fixing the pre-existing null-dispatcher hook errors that
affected all web component tests in this git worktree.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Adds "Radar" nav item to AppLayout between Agents and Inbox
- Creates /radar route with validateSearch for timeRange/status/initiativeId/mode filters
- Summary stat cards for questions, messages, subagents, compactions aggregates
- Agent activity table with client-side sorting on all 10 columns (default: started desc)
- Real-time SSE updates via useLiveUpdates invalidating agent namespace
- Loading skeleton (5 rows) and empty state messaging
- Non-zero metric cells show cursor-pointer for future drilldown dialogs
- 12-test suite covering rendering, sorting, filtering, nav, and states
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the remaining two Radar drilldown dialogs following the
established AddAccountDialog pattern. Both use tRPC lazy queries,
skeleton loading, and expandable rows via useState<number | null>.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Split FileDiff into FileDiff (metadata-only) and FileDiffDetail (with hunks)
so the phase branch diff no longer requires client-side diff parsing
- ReviewTab now reads diffQuery.data.files (FileStatEntry[]) and maps
path → newPath for sidebar and DiffViewer; no parseUnifiedDiff call
in the phase branch view path
- Commit view still parses rawDiff via parseUnifiedDiff → FileDiffDetail[]
- Pass phaseId, commitMode, comments, expandAll to DiffViewer
- Pass totalAdditions/totalDeletions from server to ReviewHeader stats bar
- Wire Expand all button in ReviewHeader to expandAll toggle state
- Update FileCard to use FileDiffDetail and status (replaces changeType)
- Update ReviewSidebar to use file.status instead of file.changeType
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements two Radar drilldown dialog components following the
AddAccountDialog pattern (Radix UI Dialog + tRPC lazy query + skeleton
loading). CompactionEventsDialog shows a simple table of compaction
events; SubagentSpawnsDialog adds expandable rows that reveal the full
Agent tool prompt. Shared DrilldownDialogProps type in types.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prepares the review components for the backend phase that returns
metadata-only file lists from getPhaseReviewDiff. FileDiff now holds
only path/status/additions/deletions; FileDiffDetail extends it with
hunks. Renames changeType→status and adds 'binary' to the union.
Also fixes two pre-existing TypeScript errors: InitiativeReview was
passing an unknown `comments` prop to DiffViewer (should be
commentsByLine), and ConflictResolutionPanel destructured an unused
`agent` variable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds windowed rendering to FilesView in ReviewSidebar.tsx using
react-window 2.x (List component). File lists with more than 50 rows
render only visible items, keeping the DOM lean for large diffs.
- Install react-window 2.x and @types/react-window in apps/web
- Flatten directory-grouped file tree into a typed Row[] array via useMemo
- Use VariableSizeList-equivalent react-window 2.x List with rowHeight fn
(32px for dir-headers, 40px for file rows); falls back to plain DOM
render for ≤50 rows to avoid overhead on small diffs
- Directories are collapsible: clicking the dir-header toggles collapse,
removing its file rows from the Row[] and from the virtual list
- Preserve sidebar scroll offset across Files ↔ Commits tab switches via
filesScrollOffsetRef passed from ReviewSidebar into FilesView
- Clicking a file calls listRef.scrollToRow({ index, align: "smart" })
to keep the clicked row visible in the virtual list
- Root-level files (directory === "") render without a dir-header,
preserving existing behavior
- Add resolve.dedupe for react/react-dom in vitest.config.ts to prevent
duplicate-React errors after local workspace package installation
- Add 6 Vitest + RTL tests covering: large-list DOM count, small-list
fallback, collapse, re-expand, tab-switch smoke, root-level files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add single-chunk equivalence test (≤200 lines produces complete token
map with no missing line entries) and AbortController abort spy test
(unmount during chunked fallback triggers abort signal) to cover the
remaining spec scenarios not included by the implementation branch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a 2-worker pool in use-syntax-highlight.ts so shiki tokenisation
runs off the main thread. Callers continue to receive null while the
worker is in flight and a LineTokenMap once it resolves — no caller
changes needed.
Fallback: if Worker construction is blocked (e.g. CSP), the hook falls
back to the existing createHighlighter singleton but processes 200 lines
at a time, yielding between chunks via scheduler.yield()/setTimeout(0)
to avoid long tasks.
Also adds worker.format:'es' to vite.config.ts (required when the app
uses code-splitting) and covers all paths with Vitest tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Build a Map<string, ReviewComment[]> once in ReviewTab and thread it
down through DiffViewer → FileCard → HunkRows, replacing O(n) filter
calls with O(1) map lookups. With 200 comments and 5000 diff lines,
this reduces ~1M iterations per render cycle to ~5K.
Key: "${filePath}:${lineNumber}:${lineType}" for line-level comments,
"${filePath}:file" for file-level (lineNumber === null) comments.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Integrates main branch changes (headquarters dashboard, task retry count,
agent prompt persistence, remote sync improvements) with the initiative's
errand agent feature. Both features coexist in the merged result.
Key resolutions:
- Schema: take main's errands table (nullable projectId, no conflictFiles,
with errandsRelations); migrate to 0035_faulty_human_fly
- Router: keep both errandProcedures and headquartersProcedures
- Errand prompt: take main's simpler version (no question-asking flow)
- Manager: take main's status check (running|idle only, no waiting_for_input)
- Tests: update to match removed conflictFiles field and undefined vs null
getHeadquartersDashboard had no section for active conflict agents,
so initiatives with a running conflict-* agent disappeared from all
HQ sections. Add resolvingConflicts array to surface them.
Replaces the placeholder body in apps/web/src/routes/hq.tsx with the
full Headquarters page. The component fetches from getHeadquartersDashboard,
subscribes to live SSE invalidations via useLiveUpdates, and renders the
four action sections or an empty state. Includes skeleton loading and
error-with-retry states. Also adds apps/web/src/components/ui/skeleton.tsx
(standard shadcn component not yet in the project).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Derives currentTodos from the most recent TodoWrite tool_call on each render
- Renders a TASKS strip between the header and scroll area with status icons
(CheckCircle2 for completed, Loader2/animate-spin for in_progress, Circle for pending)
- Caps the strip at 5 rows and shows "+ N more" for overflow
- Updates collapsed tool_result preview to show "{subagent_type} result" for
Task tool results instead of the raw first-80-chars substring
- Adds 10 new tests covering all todo strip states and Task preview variants
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extend ParsedMessage.meta with toolInput to expose raw tool arguments
- Add toolUseRegistry to correlate tool_result blocks back to originating tool_use
- Set toolInput on tool_call messages and populate meta.toolName/toolInput on tool_result
- Fix tool_result with is_error:true now correctly produces type "error"
- Add catch-all for unknown top-level event types (emits system message)
- Add catch-all for unknown assistant content block types (emits system message)
- Add unit tests covering all 8 scenarios including regression cases
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>