Commit Graph

224 Commits

Author SHA1 Message Date
Lukas May
d4a28713f6 fix: conflict resolution tasks now get dispatched instead of permanently blocking initiative
- Remove original task blocking in handleConflict (task is already completed by handleAgentStopped)
- Return created conflict task from handleConflict so orchestrator can queue it for dispatch
- Add dedup check to prevent duplicate resolution tasks on crash retries
- Queue conflict resolution task via dispatchManager in mergeTaskIntoPhase
- Add recovery for erroneously blocked tasks in recoverDispatchQueues
- Update tests and docs
2026-03-06 20:37:29 +01:00
Lukas May
a41caa633b fix: break Vite refresh loop by ignoring __tests__ in route generation
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.
2026-03-06 20:34:35 +01:00
Lukas May
f63b1c5eec Merge branch 'cw/radar' into cw-merge-1772825408137 2026-03-06 20:30:08 +01:00
Lukas May
cc4d4f6401 Merge branch 'cw/radar-task-JJ3yFeDd1HIKtqYWuF36n' into cw-merge-1772824727227 2026-03-06 20:18:47 +01:00
Lukas May
7c48c70d47 feat: Add SSE-driven real-time refresh and last-refreshed timestamp to drilldown dialogs
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>
2026-03-06 20:18:17 +01:00
Lukas May
5c5a4e9bab chore: remove stale hq.test.tsx route test file
The route-level test was replaced by component-level tests in ReviewTab.test.tsx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 20:18:09 +01:00
Lukas May
92a95ffa02 feat: wire drilldown dialogs into RadarPage with isAgentRunning prop
- 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>
2026-03-06 20:14:06 +01:00
Lukas May
9bd56ce4a1 Merge branch 'cw/radar-phase-drilldown-dialog-components' into cw-merge-1772824266700 2026-03-06 20:11:06 +01:00
Lukas May
b860bc100d feat: Add Radar page with nav item, filters, table, and tests
- 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>
2026-03-06 20:10:39 +01:00
Lukas May
20d591c51f feat: add QuestionsAskedDialog and InterAgentMessagesDialog with tests
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>
2026-03-06 20:10:38 +01:00
Lukas May
cb4519439d feat: add CompactionEventsDialog and SubagentSpawnsDialog with tests
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>
2026-03-06 20:06:32 +01:00
Lukas May
c0096503b2 fix: Re-record cassettes and exclude workdir from test discovery
Re-recorded all 4 cassette files to reflect current prompt templates.
Added `workdir/**` to vitest exclude list to prevent test discovery
in agent worktree directories.
2026-03-06 17:00:46 +01:00
Lukas May
5598e1c10f feat: implement Radar backend tRPC procedures with repository extensions
Add five new tRPC query procedures powering the Radar page's per-agent
behavioral metrics (questions asked, subagent spawns, compaction events,
inter-agent messages) plus the batch repository methods they require.

Repository changes:
- LogChunkRepository: add findByAgentIds() for batch fetching without N+1
- ConversationRepository: add countByFromAgentIds() and findByFromAgentId()
- Drizzle adapters: implement all three new methods using inArray()
- InMemoryConversationRepository (integration test): implement new methods

tRPC procedures added:
- agent.listForRadar: filtered agent list with per-agent metrics computed
  from log chunks (questionsCount, subagentsCount, compactionsCount) and
  conversation counts (messagesCount); supports timeRange/status/mode/initiative filters
- agent.getCompactionEvents: compact system init chunks for one agent (cap 200)
- agent.getSubagentSpawns: Agent tool_use entries with prompt preview (cap 200)
- agent.getQuestionsAsked: AskUserQuestion tool calls with questions array (cap 200)
- conversation.getByFromAgent: conversations by fromAgentId with toAgentName resolved

All 13 new unit tests pass; existing test suite unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 16:40:18 +01:00
Lukas May
1e16ad82e8 fix: Show conflict resolution agents in HQ dashboard
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.
2026-03-06 16:39:48 +01:00
Lukas May
02ca1d568e fix: Disable EventEmitter maxListeners warning for SSE subscriptions
Each SSE client registers a listener per event type (30+ types), so a
few concurrent connections easily exceed the previous limit of 100.
Listeners are properly cleaned up on disconnect via eventBusIterable's
finally block, so this is not a real leak.
2026-03-06 16:39:36 +01:00
Lukas May
cb95ac1c6e fix: Logo link navigates to HQ instead of Initiatives 2026-03-06 16:33:10 +01:00
Lukas May
2eccde0ee1 Merge branch 'cw/improved-agent-outputs' into cw-merge-1772810637670 2026-03-06 16:23:57 +01:00
Lukas May
e50eb17c3f Merge branch 'cw/headquarters' into cw-merge-1772810307192 2026-03-06 16:18:27 +01:00
Lukas May
313cf82ea4 Merge branch 'cw/headquarters-task-i16XYnxexfeqf8VCUuTL3' into cw-merge-1772809739062 2026-03-06 16:08:59 +01:00
Lukas May
2ec4ddb2fd feat: Wire up hq.tsx with query, live updates, loading/error states, and section rendering
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>
2026-03-06 16:08:35 +01:00
Lukas May
f6938ae7e1 feat: Add live todo strip and Task result preview to AgentOutputViewer
- 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>
2026-03-06 16:05:48 +01:00
Lukas May
32f58ddb43 Merge branch 'cw/improved-agent-outputs-phase-parser-enhancement-types-bug-fixes-tool-correlation' into cw-merge-1772809398045 2026-03-06 16:03:18 +01:00
Lukas May
ee6b0da976 feat: Add tool correlation, toolInput metadata, and unknown-type fallbacks to parser
- 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>
2026-03-06 16:02:50 +01:00
Lukas May
752bb67e3a feat: collapse tool_result blocks by default; restyle system messages
tool_result messages now render as a single collapsible preview line
(ChevronRight + first 80 chars) and expand on click to show full content.
system messages drop the Badge/border-l and render as a dim mono inline
line. expandedResults state resets when agentId changes.

Adds full test coverage in AgentOutputViewer.test.tsx (9 tests).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 16:02:20 +01:00
Lukas May
30d5f68f91 feat: Add HQ section components for Headquarters page
Implements the five section components consumed by the HQ page:
- HQWaitingForInputSection, HQNeedsReviewSection, HQNeedsApprovalSection,
  HQBlockedSection, HQEmptyState with typed props from RouterOutputs.
- Shared types.ts defines the 5 item types from getHeadquartersDashboard.
- Adds RouterOutputs export to trpc.ts via inferRouterOutputs<AppRouter>.
- 22 unit tests verify rendering, navigation CTAs, truncation, and edge cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 15:53:15 +01:00
Lukas May
f244304c6f Merge branch 'cw/headquarters-phase-backend-hq-dashboard-trpc-procedure' into cw-merge-1772807905914 2026-03-06 15:38:26 +01:00
Lukas May
89c98d38cc feat: Add getHeadquartersDashboard tRPC procedure for HQ action items
Aggregates all user-blocking action items into a single composite query:
- waitingForInput: agents paused on questions (oldest first)
- pendingReviewInitiatives: initiatives awaiting content review
- pendingReviewPhases: phases awaiting diff review
- planningInitiatives: active initiatives with all phases pending and no running agents
- blockedPhases: phases in blocked state with optional last-message snippet

Wired into appRouter and covered by 10 unit tests using in-memory Drizzle DB
and an inline MockAgentManager (no real processes required).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 15:35:54 +01:00
Lukas May
48c324ac15 chore: Update tsbuildinfo after web build 2026-03-06 15:27:41 +01:00
Lukas May
3c55349c4c feat: Add /hq route, nav item, and update root redirect
- Create apps/web/src/routes/hq.tsx with HeadquartersPage shell component
- Add "HQ" as first entry in AppLayout.tsx navItems array
- Change root redirect from /initiatives to /hq
- Regenerate routeTree.gen.ts with the new /hq route

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 15:27:09 +01:00
Lukas May
c069049c35 fix: Retry blocked task button does nothing due to missing query invalidation
retryBlockedTask was not in the centralized invalidation map, so the
mutation succeeded server-side but the UI never refreshed. Also changed
the button to wait for the mutation response before closing the slide-over
and show a loading spinner.
2026-03-06 15:00:38 +01:00
Lukas May
2bef0fa682 Merge branch 'cw/project-management-operations-to-ui' into cw-merge-1772805244951 2026-03-06 14:54:05 +01:00
Lukas May
986cae880d chore: Remove unused realpathSync import 2026-03-06 14:52:42 +01:00
Lukas May
4a7105eb8f fix: Worktree get() matches wrong agent due to ambiguous endsWith lookup
The `get(id)` method on SimpleGitWorktreeManager used `path.endsWith(id)`
to find worktrees. Since all agents working on the same project create
worktrees with the same project name suffix (e.g., "codewalk-district"),
cleanup for one agent could match and delete another agent's worktree.

Fix: match on `basename(worktreesDir)/id` so each manager's lookups are
scoped to its own worktree base directory.
2026-03-06 14:52:28 +01:00
Lukas May
7a4d0d2582 feat: Add Sync All button to projects settings page with tests
- Adds syncAllMutation calling trpc.syncAllProjects once for all cards
- Shows Sync All button in header when ≥1 project exists (hidden otherwise)
- Propagates isPending to ProjectCard.syncAllPending to disable per-card sync
- On success: toasts all-success or failure count; invalidates listProjects + getProjectSyncStatus per project
- On network error: toasts Sync failed with err.message
- Adds unit tests for ProjectSyncManager.syncAllProjects: empty list, all succeed, partial failure, result shape, and failure counting logic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 14:39:58 +01:00
Lukas May
c1b88bfcfe Merge branch 'cw/project-management-operations-to-ui-task-NAUgQl_7T7wcDxRkWQ5TX' into cw-merge-1772804260272 2026-03-06 14:37:41 +01:00
Lukas May
8f4fa2a233 fix: disambiguate CONFLICT errors in registerProject by inspecting the SQLite UNIQUE constraint column
Previously a single "that name or URL" message was thrown regardless of which
column violated uniqueness. Now the catch block inspects the error string from
SQLite to emit a name-specific or url-specific message, with a generic fallback
when neither column can be identified.

Adds vitest tests covering all four scenarios: name conflict, url conflict,
unknown column conflict, and non-UNIQUE error passthrough.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 14:37:21 +01:00
Lukas May
4c99f89462 feat: Improve RegisterProjectDialog UX for long-running clone
- Add Loader2 spinner with "Cloning repository…" label while pending
- Keep Cancel button always enabled (no disabled gate)
- Map INTERNAL_SERVER_ERROR to user-friendly clone failure message
- Invalidate listProjects cache on success so new card appears immediately

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 14:34:34 +01:00
Lukas May
d867a5f397 Merge branch 'main' into cw/account-ui-conflict-1772803526476
# Conflicts:
#	apps/server/trpc/router.test.ts
#	docs/server-api.md
2026-03-06 14:27:38 +01:00
Lukas May
23964374d1 Merge branch 'cw/agent-details' into cw-merge-1772802959182 2026-03-06 14:15:59 +01:00
Lukas May
6f38ae21ed Merge branch 'main' into cw/agent-details-conflict-1772802863659
# Conflicts:
#	docs/server-api.md
2026-03-06 14:15:30 +01:00
Lukas May
30b27f8b4a fix: Conflict agent auto-dismiss fails on page load/remount
prevStateRef was initialized with current state, so when the page loaded
with an already-idle conflict agent, the transition guard was immediately
false and dismiss() never fired. Initialize with null instead.
2026-03-06 14:13:42 +01:00
Lukas May
0f1c578269 fix: Fail fast when agent worktree creation or branch setup fails
Previously, branch computation errors and ensureBranch failures were
silently swallowed for all tasks, allowing execution agents to spawn
without proper git isolation. This caused alert-pony to commit directly
to main instead of its task branch.

- manager.ts: Verify each project worktree subdirectory exists after
  createProjectWorktrees; throw if any are missing. Convert passive
  cwdVerified log to a hard guard.
- dispatch/manager.ts: Make branch computation and ensureBranch errors
  fatal for execution tasks (execute, verify, merge, review) while
  keeping them non-fatal for planning tasks.
2026-03-06 14:08:59 +01:00
Lukas May
b419981924 perf: Speed up conflict resolution agents by trimming prompt bloat
Replace SESSION_STARTUP (full test suite run) and CONTEXT_MANAGEMENT
(progress file refs) with a minimal startup block (pwd, git status,
CLAUDE.md). Add skipPromptExtras option to SpawnAgentOptions to skip
inter-agent communication and preview deployment instructions. Conflict
agents now go straight to the resolution protocol — one post-resolution
test run instead of two.
2026-03-06 14:05:23 +01:00
Lukas May
a0574a1ae9 feat: Add subagent usage guidance to refine and plan prompts
Instruct architect agents to leverage subagents for parallel work —
page analysis, codebase verification, dependency mapping, and pattern
discovery — instead of doing everything sequentially.
2026-03-06 13:39:19 +01:00
Lukas May
a94e72ccbc feat: Wire AddAccountDialog and UpdateCredentialsDialog into health page and AccountCard
- health.tsx: Add Account button + AddAccountDialog, Refresh button with
  tooltip and spinner calling refreshAccounts mutation, inline account
  error state instead of full-page error, updated empty state text, and
  active-agent warning on delete confirm
- AccountCard.tsx: Show KeyRound button when credentials/token invalid,
  opens UpdateCredentialsDialog pre-populated with account identity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 13:35:14 +01:00
Lukas May
1629285778 Merge branch 'refs/heads/main' into cw/agent-details-conflict-1772799979862
# Conflicts:
#	apps/server/drizzle/meta/_journal.json
2026-03-06 13:34:28 +01:00
Lukas May
e3246baf51 feat: Show resolving_conflict activity state on initiative cards
Add 'resolving_conflict' to InitiativeActivityState and detect active
conflict agents (name starts with conflict-) in deriveInitiativeActivity.
Conflict resolution takes priority over pending_review since the agent
is actively working.

- Add resolving_conflict to shared types and activity derivation
- Include conflict agents in listInitiatives agent filter (name + mode)
- Map resolving_conflict to urgent variant with pulse in InitiativeCard
- Add merge: prefix to INITIATIVE_LIST_RULES for merge event routing
- Add spawnConflictResolutionAgent to INVALIDATION_MAP
- Add getActiveConflictAgent to detail page agent: SSE invalidation
2026-03-06 13:32:37 +01:00
Lukas May
b4baba67a5 Merge branch 'cw/account-ui-phase-updatecredentialsdialog-component' into cw-merge-1772800279801 2026-03-06 13:31:20 +01:00
Lukas May
05efa9c08e fix: Replace getTaskAgent polling with event-driven invalidation
Add getTaskAgent to the agent: prefix SSE invalidation rule so spawned
agents are picked up immediately instead of polling every 5s.
2026-03-06 13:30:18 +01:00
Lukas May
575ad48a55 feat: Add UpdateCredentialsDialog component for re-authenticating accounts
Implements a self-contained dialog that allows users to update credentials
for an existing account without deleting and re-adding it. Supports two
modes: token-based (Tab A) and credentials JSON (Tab B).

Also sets up web component test infrastructure: vitest now includes
apps/web/**/*.test.tsx files with happy-dom environment, @vitejs/plugin-react
for JSX, and @testing-library/{react,jest-dom,user-event} packages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 13:27:13 +01:00