Commit Graph

722 Commits

Author SHA1 Message Date
Lukas May
bdc95bcb26 fix: Handle existing branch in worktree creation
When re-dispatching tasks, the branch from a previous run may still
exist. Instead of failing with "a branch named X already exists",
reset the existing branch to the base and check it out.
2026-03-06 10:54:33 +01:00
Lukas May
1e2819eeff fix: Request changes uses in-app confirmation, requires review comments
- Replace window.prompt with in-app dropdown confirmation (matches merge dialog pattern)
- Disable button when no unresolved comments exist (comments-only, no summary)
- Remove initiative-level request changes button (no comment system there)
2026-03-06 10:43:36 +01:00
Lukas May
4656627a59 fix: Restore drizzle-kit generate by syncing snapshot baseline
Snapshots were stale since migration 0008. Generated a schema-derived
snapshot at 0032 so drizzle-kit generate works again (zero diff on
current schema.ts). Also fixed migration 0032 to use statement-breakpoint
separator required by better-sqlite3.

- Added 0032_snapshot.json derived from current schema.ts
- Fixed 0032 SQL to use --> statement-breakpoint between statements
- Updated CLAUDE.md and database-migrations.md with correct workflow
2026-03-06 10:36:07 +01:00
Lukas May
03c2abbd8f docs: Fix migration workflow — document hand-written SQL + journal registration
drizzle-kit generate has been broken since migration 0008 (stale snapshots).
The actual workflow is hand-written SQL + manual _journal.json registration.
Updated CLAUDE.md and database-migrations.md to reflect reality and prevent
future migrations from silently failing to apply.
2026-03-06 10:29:49 +01:00
Lukas May
eb667dd3d7 fix: Register migration 0032 in drizzle journal
The migration file existed but wasn't in _journal.json, so drizzle-kit's
migrator never applied it. Adds the journal entry for 0032_add_comment_threading.
2026-03-06 10:27:44 +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
2da6632298 docs: Update dispatch-events, server-api, frontend for request-changes fixes 2026-03-06 09:42:28 +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
1b8e496d39 fix: Switch preview gateway from path-prefix to subdomain routing
Path-prefix routing (`localhost:9100/<id>/`) broke SPAs because absolute
asset paths (`/assets/index.js`) didn't match the `handle_path /<id>/*`
route. Subdomain routing (`<id>.localhost:9100/`) resolves this since
all paths are relative to the root. Chrome/Firefox resolve *.localhost
to 127.0.0.1 natively — no DNS setup needed.
2026-03-05 22:38:00 +01:00
Lukas May
aedf149471 fix: Use container-internal port 80 in gateway Caddyfile
The Caddyfile was using the host port (e.g., 9100) as the Caddy listen
address, but Docker maps host:9100 → container:80. Caddy inside the
container was listening on 9100 while Docker only forwarded to port 80,
causing all health checks to fail with "connection reset by peer".
2026-03-05 22:16:19 +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
cdb3de353d fix: Use SSE events instead of polling for preview status updates
httpBatchLink batches polling queries behind the long-running
startPreview mutation, so refetchInterval never fires independently.
Replace polling with preview: event invalidation via the existing
useLiveUpdates SSE subscription — preview:building/ready/stopped/failed
events now trigger listPreviews and getPreviewStatus invalidation.
2026-03-05 22:01:16 +01:00
Lukas May
df84a877f2 fix: Prioritize polled preview status over mutation pending state
The startPreview mutation blocks server-side through the entire Docker
build + health check + seed cycle. isPending was checked first, so even
after polling detected containers running, the UI stayed on "Building..."
until the full mutation resolved. Now polled status (running/failed)
takes priority, falling back to isPending only when no status exists.
2026-03-05 21:58:02 +01:00
Lukas May
4958b6624d fix: Refetch previews on start and switch to path-based routing
Two fixes:
- Call previewsQuery.refetch() in startPreview.onSuccess so the UI
  transitions from "building" to the preview link without a page refresh.
- Switch from subdomain routing (*.localhost) to path-based routing
  (localhost:<port>/<id>/) since macOS doesn't resolve wildcard
  localhost subdomains.
2026-03-05 21:56:05 +01:00
Lukas May
0e61c48c86 fix: Use lowercase alphanumeric nanoid for Docker compose project names
Docker compose requires project names to be lowercase alphanumeric
with hyphens/underscores only. The default nanoid alphabet includes
uppercase and special characters, causing build failures.
2026-03-05 21:49:01 +01:00
Lukas May
13e009a82d feat: Add preview controls to initiative-level review
Extract PreviewControls into shared component and wire up preview
start/stop to InitiativeReview header alongside Push Branch and
Merge & Push to Default buttons.
2026-03-05 21:47:06 +01:00
Lukas May
269a2d2616 feat: Extend AgentInfo with exitCode + add getAgentInputFiles/getAgentPrompt tRPC procedures
Adds exitCode to AgentInfo type and propagates it through all toAgentInfo()
implementations. Enhances getAgent to also return taskName and initiativeName
from their respective repositories. Adds two new filesystem-reading tRPC
procedures for the Agent Details tab: getAgentInputFiles (reads .cw/input/
files with binary detection, 500 KB cap, sorted) and getAgentPrompt (reads
.cw/agent-logs/<name>/PROMPT.md with 1 MB cap and structured ENOENT handling).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 21:39:29 +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
ff398f84ac fix: Move useMemo above early returns in ReviewTab to fix hooks ordering crash
The allFiles useMemo was declared after two early-return branches. Approving
the last phase empties pendingReviewPhases, triggering the early return and
causing React to see fewer hooks than the previous render.
2026-03-05 21:35:10 +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
7bc1e7f25b perf: Remove preview polling in favour of SSE-driven invalidation
refetchInterval: 3000 on listPreviews and getPreviewStatus is now
redundant. Phase oMHtTekCDgdnBG0kkk25A wired useLiveUpdates in
$id.tsx to invalidate both queries on every preview:* SSE event,
so queries refetch exactly once per state change instead of on
a fixed 3-second timer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 21:17:00 +01:00
Lukas May
47fa924927 fix: Recover in-memory dispatch queues from DB on server startup
Both phaseQueue and taskQueue are in-memory Maps lost on restart. Now
the orchestrator's start() method scans active initiatives and:
- Re-queues approved phases into the phase dispatch queue
- Re-queues pending tasks for in_progress phases into the task dispatch queue
- Triggers a dispatch cycle if anything was recovered

This fixes stuck phases/tasks after server restarts.
2026-03-05 21:10:32 +01:00
Lukas May
573e1b40d2 fix: Re-queue approved phases before dispatch to survive server restarts
The in-memory phaseQueue (Map) in DefaultPhaseDispatchManager is lost on
server restart. After approving a phase review, dispatchNextPhase() found
nothing in the empty queue, so the next unblocked phase never started.

Now the orchestrator re-queues all approved phases for the initiative from
the DB before attempting to dispatch, making the queue self-healing.
2026-03-05 21:04:39 +01:00
Lukas May
5f36fcf4ce docs: Add cw account extract to CLI reference docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:59:38 +01:00
Lukas May
a3ee581629 fix: Merge confirmation dropdown hidden behind sticky file headers
Remove overflow-hidden from ReviewTab outer wrapper (was clipping the
absolutely-positioned dropdown), make ReviewHeader sticky with z-20 to
sit above file headers (z-10), and bump the dropdown to z-30.
2026-03-05 20:59:30 +01:00
Lukas May
3c99bdeeb5 feat: Add cw account extract CLI command with tests
Adds `cw account extract [--email <email>]` subcommand to the accountCommand
group. Reads directly from the local Claude config via extractCurrentClaudeAccount()
without requiring a server connection. Supports optional email verification,
outputting JSON with email, configJson (stringified), and credentials fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:59:23 +01:00
Lukas May
0adbb55898 docs: Document addAccountByToken in server-api.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:59:01 +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
5ccf4ae556 Merge branch 'cw/unified-event-flow-phase-frontend-query-invalidation-completeness' into cw/unified-event-flow 2026-03-05 20:58:34 +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
fff4ce2bb7 fix: close five frontend invalidation gaps for changeset, preview, and dependency events
- Add changeset: SSE rule (Gap 1-A) to cover cross-agent changeset events
- Add getChangeSet to revertChangeSet INVALIDATION_MAP (Gap 1-B) for same-client path
- Add preview: SSE rule (Gap 2) covering listPreviews and getPreviewStatus
- Extend task:/phase: SSE rules with getPhaseDependencies and listPhaseTaskDependencies (Gap 4-A)
- Add listPhaseTaskDependencies to createPhaseDependency/removePhaseDependency (Gap 4-B)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 20:51:16 +01:00
Lukas May
50aea7e6f1 fix: Ensure phase branches exist before task dispatch
Task dispatch computed baseBranch as the phase branch name but never
ensured it existed in the git clone. When phases weren't dispatched
through the PhaseDispatchManager (which creates branches), the
git worktree add failed with "fatal: invalid reference".

Now DefaultDispatchManager calls ensureBranch for both the initiative
and phase branches before spawning, matching what PhaseDispatchManager
already does.
2026-03-05 20:49:21 +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
2eac5b9908 fix: Remove agent:output from general SSE subscriptions to prevent listener leak
agent:output is high-frequency streaming data that was included in
ALL_EVENT_TYPES and AGENT_EVENT_TYPES, causing every onEvent/onAgentUpdate
SSE subscription to register a listener. With multiple subscriptions per
browser tab plus reconnections, this exceeded the 100 listener limit.

The dedicated onAgentOutput subscription handles output streaming already.
Bonus: stops useLiveUpdates from refetching listAgents on every output chunk.
2026-03-05 17:50:01 +01:00
Lukas May
8387d5b22c chore: Gitignore agent-generated screenshots 2026-03-05 17:29:09 +01:00
Lukas May
f3042abe04 fix: Use absolute paths and git add -u in post-completion commit resume
Prevents two bugs in the resumeForCommit flow:
1. Agent navigated to main repo instead of worktree due to relative paths
   in commit prompt — now uses absolute paths from getDirtyWorktreePaths
2. git add -A staged unrelated files (screenshots, other agents' work) —
   now uses git add -u to only stage tracked modified files
2026-03-05 17:13:31 +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
209629241d feat: Add PREVIEW_EVENT_TYPES, CONVERSATION_EVENT_TYPES, and subscription procedures
- Add preview:building/ready/stopped/failed to ALL_EVENT_TYPES
- Export PREVIEW_EVENT_TYPES and CONVERSATION_EVENT_TYPES constants
- Add onPreviewUpdate and onConversationUpdate subscription procedures
- Add audit comment confirming phase:pending_review presence (gap 3 verified)
- Add unit tests covering constants, filtering behavior, and procedure shape
- Update server-api.md to document new subscription procedures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 17:07:00 +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
dab1a2ab13 docs: Add initiative review gate to dispatch-events, server-api, and database docs 2026-03-05 17:00:38 +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
3d1818d567 feat: Add Approve button for pending_approval tasks in TaskSlideOver 2026-03-05 16:46:12 +01:00
Lukas May
da8c714de2 fix: Handle spawn and branch failures gracefully in dispatch cycle
Wrap agentManager.spawn() in try/catch — on failure, block the task
instead of crashing the entire dispatch cycle. Move phase status update
to after branch creation succeeds — on branch failure, block the phase
and skip task queuing. Fix statement-breakpoint markers in migration
0020 to use separate lines.
2026-03-05 16:36:39 +01:00
Lukas May
42f5bcb80a refactor: Drive connection status from tRPC subscription state
Replace browser online/offline event listeners with tRPC onEvent subscription
status, so the connection indicator reflects actual server reachability rather
than general network availability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 15:59:39 +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
66605da30d feat: Add Dockerfile, preview config, and seed script for self-preview deployments
Containerize Codewalkers with a multi-stage Docker build (Node + Caddy) and
add a seed script that populates the database with a demo initiative, 3 phases,
9 tasks, 3 agents with JSONL log output, a root page, review comments, and a
git repo with real branch diffs for the review tab.
2026-03-05 14:26:22 +01:00
Lukas May
714262fb83 feat: Add seed command support to preview deployments
Run project-specific initialization commands (DB migrations, fixture
loading, etc.) automatically after containers are healthy, before the
preview is marked ready. Configured via per-service `seed` arrays in
.cw-preview.yml.
2026-03-05 12:39:02 +01:00
Lukas May
3913aa2e28 docs: Add setup guide for preview deployments
Add a clear "Setting Up Preview Deployments" section with prerequisites,
quick start, multi-service example, config reference table, dev mode
instructions, healthcheck docs, and auto-start explanation. Remove
duplicate config example from the old Configuration section.
2026-03-05 12:31:57 +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