Commit Graph

44 Commits

Author SHA1 Message Date
Lukas May
377e8de5e9 feat: Add errand tRPC router with all 9 procedures and comprehensive tests
Implements the errand workflow for small isolated changes that spawn a
dedicated agent in a git worktree:
- errand.create: branch + worktree + DB record + agent spawn
- errand.list / errand.get / errand.diff: read procedures
- errand.complete: transitions active→pending_review, stops agent
- errand.merge: merges branch, handles conflicts with conflictFiles
- errand.delete / errand.abandon: cleanup worktree, branch, agent
- errand.sendMessage: delivers user message directly to running agent

Supporting changes:
- Add 'errand' to AgentMode union and agents.mode enum
- Add sendUserMessage() to AgentManager interface and MockAgentManager
- MockAgentManager now accepts optional agentRepository to persist agents
  to the DB (required for FK constraint satisfaction in tests)
- Add ORDER BY createdAt DESC, id DESC to errand findAll
- Fix dispatch/manager.test.ts missing sendUserMessage mock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 16:21:01 +01:00
Lukas May
3a328d2b1c feat: Add errands schema, repository, and wire into tRPC context/container
Creates the errands table (with conflictFiles column), errand-repository
port interface, DrizzleErrandRepository adapter, and wires the repository
into TRPCContext, the DI container, _helpers.ts requireErrandRepository guard,
and the test harness. Also fixes pre-existing TS error in controller.test.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 15:49:26 +01:00
Lukas May
6034f6d854 Merge branch 'main' into cw/unified-event-flow-conflict-1772795597661
# Conflicts:
#	apps/web/src/components/review/ReviewTab.tsx
#	apps/web/src/routes/initiatives/$id.tsx
2026-03-06 12:16:07 +01:00
Lukas May
1e723611e7 feat: Allow editing review comments
Add update method to ReviewCommentRepository, updateReviewComment tRPC
procedure, and inline edit UI in CommentThread. Edit button appears on
user-authored comments (not agent comments) when unresolved. Uses the
existing CommentForm with a new initialValue prop.
2026-03-06 11:58:08 +01:00
Lukas May
0c04a1d273 fix: Prevent conflict resolution agent from destroying initiative branch
spawnConflictResolutionAgent was passing the initiative branch as branchName,
causing SimpleGitWorktreeManager.create() to force-reset it to the target
branch. Now spawns on a unique temp branch based off the initiative branch,
with the agent using git update-ref to advance the initiative branch after
resolving conflicts. Also fixes stale diff/commits cache after resolution.
2026-03-06 11:40:22 +01:00
Lukas May
6cf6bd076f feat: Add merge conflict detection and agent resolution in initiative review
Pre-merge mergeability check via `git merge-tree --write-tree` (dry-run, no
side effects). When conflicts exist the "Merge & Push" button is disabled and
a ConflictResolutionPanel shows conflict files with options to resolve manually
or spawn a conflict-resolution agent. Agent questions appear inline via
QuestionForm; on completion the mergeability re-checks automatically.

New server-side: MergeabilityResult type, BranchManager.checkMergeability,
conflict-resolution prompt, checkInitiativeMergeability query,
spawnConflictResolutionAgent mutation, getActiveConflictAgent query.

New frontend: useConflictAgent hook, ConflictResolutionPanel component,
mergeability badge + panel integration in InitiativeReview.
2026-03-06 11:17:25 +01:00
Lukas May
14d09b16df fix: Phase completion check runs regardless of branch/merge status
handleTaskCompleted and handlePhaseAllTasksDone both bailed early when
initiative had no branch, silently skipping phase status transitions.
Also, merge failures would skip the phase completion check entirely.

- Decouple phase completion check from branch existence
- Wrap merge in try/catch so phase check runs even if merge fails
- Route updateTaskStatus through dispatchManager.completeTask when
  completing, so the task:completed event fires for orchestration
2026-03-06 11:07:01 +01:00
Lukas May
7695604da2 feat: Add threaded review comments + agent comment responses
Introduces GitHub-style threaded comments via parentCommentId self-reference.
Users and agents can reply within comment threads, and review agents receive
comment IDs so they can post targeted responses via comment-responses.json.

- Migration 0032: parentCommentId column + index on review_comments
- Repository: createReply() copies parent context, default author 'you' → 'user'
- tRPC: replyToReviewComment procedure, requestPhaseChanges passes threaded comments
- Orchestrator: formats [comment:ID] tags with full reply threads in task description
- Agent IO: readCommentResponses() reads .cw/output/comment-responses.json
- OutputHandler: processes agent comment responses (creates replies, resolves threads)
- Execute prompt: conditional <review_comments> block when task has [comment:] markers
- Frontend: CommentThread renders root+replies with agent-specific styling + reply form
- Sidebar/ReviewTab: root-only comment counts, reply mutation plumbing through DiffViewer chain
2026-03-06 10:21:22 +01:00
Lukas May
65bcbf1a35 fix: Fix review task completion bug + add initiative-level Request Changes
Critical: review/merge tasks hit an early return in handleTaskCompleted()
that skipped the phase completion check, leaving phases stuck in
in_progress forever. Changed to an if-block wrapping only the merge step.

Also adds requestChangesOnInitiative() which creates/reuses a
"Finalization" phase for initiative-level review feedback, with dedup
guards for both phase and initiative request-changes flows.
2026-03-06 09:41:28 +01:00
Lukas May
84250955d1 fix: Show completed phase diffs in review tab
Completed phases showed "No phases pending review" because:
1. Frontend filtered only pending_review phases
2. Server rejected non-pending_review phases
3. After merge, three-dot diff returned empty (merge base moved)

Fix: store pre-merge merge base hash on phase, use it to reconstruct
diffs for completed phases. Frontend now shows both pending_review and
completed phases with read-only mode (Merged badge) for completed ones.
2026-03-05 22:05:28 +01:00
Lukas May
39d92d5de9 fix: Add changeset reconciliation to deleteTask and fix missing invalidation
Same orphaned-changeset pattern as deletePhase: manually deleting all
tasks from a detail changeset now marks it reverted. Also added
deleteTask to the invalidation map (was missing entirely).
2026-03-05 21:35:14 +01:00
Lukas May
7b93cfe7d7 feat: Remove checkpoint task types — per-phase review is sufficient
Checkpoint tasks (human-verify, decision, human-action) silently blocked
auto-dispatch with no UI to resolve them. Per-phase review + initiative
review already cover human verification, making checkpoints redundant.

Removed from: schema, dispatch manager, tRPC validators, detail prompt,
frontend types, tests, and docs.
2026-03-05 21:30:22 +01:00
Lukas May
39bb03e30b fix: Reconcile orphaned changesets when phases are manually deleted
Manually deleting phases left their parent changeset as "applied",
causing the Plan tab to show a stale "Created N phases" banner with
no phases visible.

- deletePhase now checks if all phases from a changeset are gone and
  marks it reverted
- PlanSection filters out dismissed agents so dismissed banners stay
  hidden
- revertChangeSet marks reverted before entity deletion to prevent
  ghost state on partial failure
- deletePhase invalidation now includes listChangeSets
2026-03-05 21:29:38 +01:00
Lukas May
2b06f9627b feat: Add addAccountByToken tRPC mutation with upsert logic
Adds the addAccountByToken procedure to accountProcedures(), which
accepts an email and raw OAuth token, stores the token as claudeAiOauth
credentials, and upserts the account (create or updateAccountAuth based
on findByEmail). Covers the four scenarios with unit tests: new account,
existing account, empty email, and empty token validation errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:58:44 +01:00
Lukas May
f19aac0a76 refactor: Remove dead lastEventId from subscription schemas and document at-most-once delivery
Strip the unused .input(z.object({ lastEventId })) from all 6 subscription
procedures — the parameter was never consumed by eventBusIterable. Remove the
now-unused zod import. Add at-most-once delivery JSDoc to the EventBus interface
to make the real guarantee explicit. Add compliance comment above
onConversationUpdate noting what to wire when a conversation view is built.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:51:58 +01:00
Lukas May
d81e0864f7 feat: Add retry mechanism for blocked tasks
Blocked tasks (from spawn failures) were a dead-end with no way to
recover. Add retryBlockedTask to DispatchManager that resets status
to pending and re-queues, a tRPC mutation that also kicks dispatchNext,
and a Retry button in the task slide-over when status is blocked.
2026-03-05 20:41:49 +01:00
Lukas May
8804455c77 Remove task-level approval system
Task-level approval (requiresApproval, mergeRequiresApproval,
pending_approval status) was redundant with executionMode
(yolo vs review_per_phase) and blocked the orchestrator's
phase completion flow. Tasks now complete directly;
phase-level review via executionMode is the right granularity.

Removed: schema columns (left in DB, removed from Drizzle),
TaskPendingApprovalEvent, approveTask/listPendingApprovals
procedures, findPendingApproval repository method, and all
frontend approval UI.
2026-03-05 17:09:48 +01:00
Lukas May
865e8bffa0 feat: Add initiative review gate before push
When all phases complete, the initiative now transitions to
pending_review status instead of silently stopping. The user
reviews the full initiative diff and chooses:
- Push Branch: push cw/<name> to remote for PR workflows
- Merge & Push: merge into default branch and push

Changes:
- Schema: Add pending_review to initiative status enum
- BranchManager: Add pushBranch port + SimpleGit adapter
- Events: initiative:pending_review, initiative:review_approved
- Orchestrator: checkInitiativeCompletion + approveInitiative
- tRPC: getInitiativeReviewDiff, getInitiativeReviewCommits,
  getInitiativeCommitDiff, approveInitiativeReview
- Frontend: InitiativeReview component in ReviewTab
- Subscriptions: Add initiative events + missing preview/conversation
  event types and subscription procedures
2026-03-05 17:02:17 +01:00
Lukas May
763871a2a5 fix: Refine flow — optimistic UI update + instruction passthrough
- Add getActiveRefineAgent to spawn mutation optimistic updates and
  live event invalidation rules so the refine panel reflects agent
  state immediately without manual refresh
- Accept optional instruction param in buildRefinePrompt() and inject
  it as <user_instruction> block so the agent knows what to focus on
- Pass input.instruction through in architect router spawn call
2026-03-05 16:58:12 +01:00
Lukas May
ebe186bd5e feat: Add agent preview integration with auto-teardown and simplified commands
- Add agentId label to preview containers (cw.agent-id) for tracking
- Add startForAgent/stopByAgentId methods to PreviewManager
- Auto-teardown: previews torn down on agent:stopped event
- Conditional preview prompt injection for execute/refine/discuss agents
- Agent-simplified CLI: cw preview start/stop --agent <id>
- cw preview setup command with --auto mode for guided config generation
- hasPreviewConfig hint on cw project register output
- New tRPC procedures: startPreviewForAgent, stopPreviewByAgent
2026-03-05 15:39:15 +01:00
Lukas May
143aad58e8 feat: Replace per-preview Caddy sidecars with shared gateway architecture
Refactor preview deployments to use a single shared Caddy gateway container
with subdomain routing (<previewId>.localhost:<port>) instead of one Caddy
sidecar and one port per preview. Adds dev/preview modes, git worktree
support for branch checkouts, and auto-start on phase:pending_review.

- Add GatewayManager for shared Caddy lifecycle + Caddyfile generation
- Add git worktree helpers for preview mode branch checkouts
- Add dev mode: volume-mount + dev server image instead of build
- Remove per-preview Caddy sidecar and port publishing
- Use shared cw-preview-net Docker network with container name DNS
- Auto-start previews when phase enters pending_review
- Delete unused PreviewPanel.tsx
- Update all tests (40 pass), docs, events, CLI, tRPC, frontend
2026-03-05 12:22:29 +01:00
Lukas May
5e77bf104c feat: Add remote sync for project clones
Fetch remote changes before agents start working so they build on
up-to-date code. Adds ProjectSyncManager with git fetch + ff-only
merge of defaultBranch, integrated into phase dispatch to sync
before branch creation.

- Schema: lastFetchedAt column on projects table (migration 0029)
- Events: project:synced, project:sync_failed
- Phase dispatch: sync all linked projects before creating branches
- tRPC: syncProject, syncAllProjects, getProjectSyncStatus
- CLI: cw project sync [name] --all, cw project status [name]
- Frontend: sync button + ahead/behind badge on projects settings
2026-03-05 11:45:09 +01:00
Lukas May
7e0749ef17 feat: Wire full request-changes flow for phase review
- Add PhaseChangesRequestedEvent to event bus
- Add requestChangesOnPhase() to ExecutionOrchestrator: reads unresolved
  comments, creates revision task (category='review'), resets phase to
  in_progress, queues task for dispatch
- Expand merge-skip and branch routing to include 'review' category so
  revision tasks work directly on the phase branch
- Add requestPhaseChanges tRPC procedure (reads comments from DB)
- Wire frontend: mutation replaces stub handler, window.prompt for
  optional summary, loading state on button
2026-03-05 11:35:34 +01:00
Lukas May
173c7f7916 feat: Persist review comments to database
Review comments on phase diffs now survive page reloads and phase
switches. Adds review_comments table (migration 0028), repository
port/adapter (13th repo), tRPC procedures (listReviewComments,
createReviewComment, resolveReviewComment, unresolveReviewComment),
and replaces useState-based comments in ReviewTab with tRPC queries
and mutations.
2026-03-05 11:16:54 +01:00
Lukas May
c58e0ea77e feat: Redesign review tab with phase selection, commit navigation, and consolidated toolbar
- Add BranchManager.listCommits() and diffCommit() for commit-level navigation
- Add getPhaseReviewCommits and getCommitDiff tRPC procedures
- New ReviewHeader: consolidated toolbar with phase selector pills, branch info,
  stats, integrated preview controls, and approve/reject actions
- New CommitNav: horizontal commit strip with "All changes" + individual commits,
  each showing hash, message, and change stats
- Slim down ReviewSidebar: file list only with dimming for out-of-scope files
  when viewing a single commit
- ReviewTab orchestrates all pieces in a single bordered card layout
2026-03-05 10:20:43 +01:00
Lukas May
70fd996fa1 Revert "fix: Spawn chat agent in background to avoid blocking event loop"
This reverts commit 8ee02f6013.
2026-03-04 12:07:00 +01:00
Lukas May
8ee02f6013 fix: Spawn chat agent in background to avoid blocking event loop
sendChatMessage was awaiting the full agentManager.spawn() which
includes worktree creation, ~50 writeFileSync calls for input files,
credential setup, and process spawning. This blocked the Node.js event
loop long enough to cause ECONNREFUSED on the SSE connection.

Now the mutation returns immediately after storing the user message
and creating the task. The heavy spawn work runs in a detached promise.
On failure, a system message is stored so the UI can display the error.
2026-03-04 12:05:21 +01:00
Lukas May
069eb66acb feat: Add project filter to listInitiatives
Add findByProjectId to InitiativeRepository using a subquery on the
initiative_projects junction table. Extend the listInitiatives tRPC
procedure to accept an optional projectId filter that composes with
the existing status filter. Add a project dropdown to the initiatives
page alongside the status filter.
2026-03-04 11:40:32 +01:00
Lukas May
9c09683029 fix: Add scope awareness to chat prompt so agents focus on target entities
Pass targetId to buildChatPrompt and add <scope> block that clearly
distinguishes primary target files from context files. Context entities
may be modified when necessary (e.g. dependency links) but the agent
is instructed to focus changes on the primary target.
2026-03-04 11:31:49 +01:00
Lukas May
354950bb8a fix: Retry sends message with retry flag to avoid duplicate storage
Added retry:true flag to sendChatMessage input. Server skips storing
the user message when retry is set. Frontend uses a dedicated
retryLastMessage function that skips the optimistic message add.
2026-03-04 11:25:43 +01:00
Lukas May
1aef986127 fix: Sort pipeline tasks by dependency order instead of priority+createdAt
The Execution tab's PipelinePhaseGroup was using sortByPriorityAndQueueTime
which ignores task dependencies entirely. Tasks now sort topologically via
topologicalSortPhases, matching the Plan tab's TaskGraph behavior.

- Add listInitiativeTaskDependencies tRPC procedure (bulk fetch)
- Fetch task deps in PipelineTab, group by phase, pass through
- Replace priority sort with topological sort in PipelinePhaseGroup
- Show "blocked by N" count on PipelineTaskCard
2026-03-04 10:18:26 +01:00
Lukas May
fcf822363c feat: Add persistent chat sessions for iterative phase/task refinement
Introduces a chat loop where users send instructions to an agent that
applies changes (create/update/delete phases, tasks, pages) and stays
alive for follow-up messages. Includes schema + migration, repository
layer, chat prompt, file-io action field extension, output handler chat
mode, revert support for deletes, tRPC procedures, events, frontend
slide-over UI with inline changeset display and revert, and docs.
2026-03-04 10:14:28 +01:00
Lukas May
2948eb1139 feat: Add tiptap editor for task descriptions in slide-over panel
- Add updateTask tRPC mutation (name, description fields)
- Replace static description with TiptapEditor in TaskSlideOver
- Auto-detect existing markdown descriptions and convert to tiptap JSON
- Debounced auto-save with flush on close/unmount
- Saving indicator in header
2026-03-04 09:06:44 +01:00
Lukas May
9e7c246280 fix: Switch auto-spawn from discuss to refine agent, surface in UI
The auto-spawned agent on initiative creation was using discuss mode
(Q&A) when it should use refine mode (expand content). Now:

- Description seeds root page as tiptap content (split on double newlines)
- Spawns refine agent with the populated page in inputContext
- getActiveRefineAgent broadened to also surface discuss agents (for
  CLI-spawned discuss agents)
- RefineAgentPanel shows mode-appropriate label for discuss vs refine
2026-03-03 14:25:43 +01:00
Lukas May
b38a2ec034 fix: Pass task with description to auto-spawned discuss agent
The discuss agent spawned on initiative creation received only the
initiative in its inputContext, missing the task that carries the user's
description. The agent started without knowing what to discuss.
2026-03-03 14:13:45 +01:00
Lukas May
3d04cb2081 fix: Surface active architect agents in initiative activity state
Auto-spawned discuss/plan/refine agents were invisible because:
1. listInitiatives only filtered for mode='detail' agents
2. deriveInitiativeActivity returned 'idle' for zero phases before
   checking for active agents

Broadened agent filter to all architect modes (discuss, plan, detail,
refine), moved active agent check before zero-phases early return, and
added 'discussing'/'refining' activity states with pulsing indicators.
2026-03-03 14:12:20 +01:00
Lukas May
9b91ffe0e5 fix: Persist and expose task dependencies from detail output
Detail agents define task dependencies in YAML frontmatter but they were
silently dropped — never written to the task_dependencies table. This
caused all tasks to dispatch in parallel regardless of intended ordering,
and the frontend showed no dependency information.

- Add fileIdToDbId mapping and second-pass dependency creation in
  output-handler.ts (mirrors existing phase dependency pattern)
- Add task_dependency to changeset entry entityType enum
- Add listPhaseTaskDependencies tRPC procedure for batch querying
- Wire blockedBy in PhaseDetailPanel and PhaseWithTasks from real data
- Clarify dependency semantics in detail prompt
2026-03-03 13:46:29 +01:00
Lukas May
86a1912959 feat: Add description field and auto-spawn discuss agent on initiative creation 2026-03-03 13:40:37 +01:00
Lukas May
9edc93a268 feat: Auto-resume idle agents for inter-agent conversations
When an agent asks a question via `cw ask` targeting an idle agent,
the conversation router now auto-resumes the idle agent's session so
it can answer. Previously, questions to idle agents sat unanswered
forever because target resolution only matched running agents.

Changes:
- Add `resumeForConversation()` to AgentManager interface and implement
  on MultiProviderAgentManager (mirrors resumeForCommit pattern)
- Relax createConversation target resolution: prefer running, fall back
  to idle (was running-only)
- Trigger auto-resume after conversation creation for idle targets
- Add concurrency lock (conversationResumeLocks Set) to prevent
  double-resume race conditions
2026-03-03 13:29:39 +01:00
Lukas May
3e678f2591 fix: Show detailing indicator by including detail tasks in listInitiativeTasks
listInitiativeTasks was filtering out detail tasks server-side, so the
detailAgentByPhase mapping could never resolve agent.taskId to a phaseId.
Move the filter to client-side (displayTasks) so detail tasks are available
for agent mapping but excluded from counts and display grouping.
2026-03-03 13:25:29 +01:00
Lukas May
411700d37d feat: Show detailing status in initiative overview and phase sidebar
Add 'detailing' activity state derived from active detail agents
(mode=detail, status running/waiting_for_input). Initiative cards show
pulsing "Detailing" indicator. Phase sidebar items show spinner during
active detailing and "Review changes" when the agent finishes.
2026-03-03 13:08:05 +01:00
Lukas May
96386e1c3d feat: Replace initiative card N+1 queries with server-computed activity indicator
listInitiatives now returns an activity object (state, activePhase, phase
counts) derived server-side from phases, eliminating per-card listPhases
queries. Initiative cards show a StatusDot with pulse animation + label
instead of a static StatusBadge. Removed redundant View and Spawn Architect
buttons from cards. Added variant override prop to StatusDot.
2026-03-03 12:49:07 +01:00
Lukas May
c8f370583a feat: Add codebase exploration to architect agent prompts
Architect agents (discuss, plan, detail, refine) were producing generic
analysis disconnected from the actual codebase. They had full tool access
in their worktrees but were never instructed to explore the code.

- Add CODEBASE_EXPLORATION shared constant: read project docs, explore
  structure, check existing patterns, use subagents for parallel exploration
- Inject into all 4 architect prompts after INPUT_FILES
- Strengthen discuss prompt: analysis method references codebase, examples
  cite specific paths, definition_of_done requires codebase references
- Fix spawnArchitectDiscuss to pass full context (pages/phases/tasks) via
  gatherInitiativeContext() — was only passing bare initiative metadata
- Update docs/agent.md with new tag ordering and shared block table
2026-03-03 12:45:14 +01:00
Lukas May
34578d39c6 refactor: Restructure monorepo to apps/server/ and apps/web/ layout
Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt
standard monorepo conventions (apps/ for runnable apps, packages/
for reusable libraries). Update all config files, shared package
imports, test fixtures, and documentation to reflect new paths.

Key fixes:
- Update workspace config to ["apps/*", "packages/*"]
- Update tsconfig.json rootDir/include for apps/server/
- Add apps/web/** to vitest exclude list
- Update drizzle.config.ts schema path
- Fix ensure-schema.ts migration path detection (3 levels up in dev,
  2 levels up in dist)
- Fix tests/integration/cli-server.test.ts import paths
- Update packages/shared imports to apps/server/ paths
- Update all docs/ files with new paths
2026-03-03 11:22:53 +01:00