Commit Graph

71 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
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
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
0ff65b0b02 feat: Rename application from "Codewalk District" to "Codewalkers"
Update all user-facing strings (HTML title, manifest, header logo,
browser title updater), code comments, and documentation references.
Folder name retained as-is.
2026-03-05 12:05:08 +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
222d73d0d6 fix: Clean up agent worktrees, branches, and logs on dismiss and auto-cleanup
- Track worktree removal success in autoCleanupAfterCompletion() instead of
  always returning removed:true when removeAgentWorktrees() throws
- Add removeAgentBranches() call to auto-cleanup path (agent/* branches were
  never cleaned after completion)
- Add filesystem cleanup (worktrees, branches, logs) to dismiss() to prevent
  resource leaks until next server restart
2026-03-05 11:09:11 +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
f91ed5ab2d feat: Harden execute agent prompt with industry best practices
- Add Conventional Commits format requirement to git workflow
- Add pre-commit hook guidance (never --no-verify)
- Add secrets/credentials guard (never stage .env, API keys)
- Strengthen git add reasoning (explain why not git add .)
- Add CLAUDE.md read step to session startup
- Add lint/type-check gate to verification step
- Add doc update step to execution protocol
- Expand Definition of Done: lint, types, docs, debug cleanup
- Add anti-patterns: debug artifacts, spinning on failures (3x retry cap)
- Add stale reference check on file renames/moves
- Improve error signal guidance (include stack traces, not summaries)
2026-03-05 10:18:30 +01:00
Lukas May
91ce7dc4c0 fix: Prevent commit-retry infinite loop by preserving retry count across cleanup
commitRetryCount was being deleted in cleanupAgentState(), which runs
before tryAutoCleanup() checks the count. This reset the counter to 0
on every cycle, making MAX_COMMIT_RETRIES=1 dead code. Agents would
retry commits forever.

Move commitRetryCount cleanup to stop()/delete() only, letting
tryAutoCleanup() manage it during the retry lifecycle.
2026-03-05 10:10:40 +01:00
Lukas May
63400211b8 fix: Auto-complete tasks when agents finish successfully
The orchestrator's agent:stopped listener only called scheduleDispatch(),
never marking the agent's assigned task as completed. Tasks stayed
in_progress forever after their agent finished.

Now handleAgentStopped() calls dispatchManager.completeTask() before
scheduling new dispatches, respecting requiresApproval and skipping
manual (user_requested) stops.
2026-03-04 14:01:54 +01:00
Lukas May
1c7d6f20ee feat: Connect dispatch queue to agent spawning via auto-dispatch
ExecutionOrchestrator now listens for phase:queued and agent:stopped
events to drive the dispatch cycle, closing the gap between queueing
phases (Execute button) and actually spawning agents. Coalesced
scheduling prevents reentrancy with synchronous EventEmitter.
2026-03-04 12:55:20 +01:00
Lukas May
cc72c6d478 fix: Add missing await and update tests for async file-io reads 2026-03-04 12:29:10 +01:00
Lukas May
a0152ce238 fix: Convert sync file I/O to async in credential manager and usage module
Replace readFileSync/writeFileSync/mkdirSync with async equivalents from
fs/promises in default-credential-manager.ts and usage.ts to stop blocking
the Node.js event loop during credential read/write operations.
2026-03-04 12:26:37 +01:00
Lukas May
73a4c6cb0c fix: Convert sync file I/O to async in read path to unblock event loop
readFrontmatterFile, readFrontmatterDir, readSummary, readPhaseFiles,
readTaskFiles, readDecisionFiles, and readPageFiles all used readFileSync
and readdirSync which block the Node.js event loop during agent completion
handling. Converted to async using readFile/readdir from fs/promises and
added await at all call sites in output-handler.ts.
2026-03-04 12:25:34 +01:00
Lukas May
a2afc2e1fd fix: Convert sync file I/O to async in credential handler and account setup
Removes blocking readFileSync, writeFileSync, and mkdirSync calls from the
agent spawn hot path, replacing them with async fs/promises equivalents to
avoid stalling the Node.js event loop during credential operations.
2026-03-04 12:25:05 +01:00
Lukas May
bd0aec4499 fix: Convert sync file I/O to async in agent spawn path to unblock event loop
writeInputFiles, spawnDetached, and diagnostic writes now use
fs/promises (mkdir, writeFile) instead of mkdirSync/writeFileSync.
File writes in writeInputFiles are batched with Promise.all.
openSync/closeSync for child process stdio FDs remain sync as
spawn() requires the FDs immediately.
2026-03-04 12:15:31 +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
5d8830d2d3 fix: Write context/index.json so agents can look up tasks by phase
Agents were bulk-reading all context task files (39 files) because
filenames are opaque IDs and there was no way to find phase-relevant
tasks without reading every file. Now writeInputFiles generates a
context/index.json with tasksByPhase mapping phaseId to task metadata
(file, id, name, status). Prompt updated to direct agents to read
the index first.
2026-03-04 11:55:22 +01:00
Lukas May
26ed9e0395 fix: Tell agents context files are on-demand, not bulk-read
Agents were reading all contextFiles (38 tasks + 8 phases) upfront,
wasting massive context window. Updated INPUT_FILES and SESSION_STARTUP
prompts to clearly distinguish assignment files (read all) from context
files (read only when needed).
2026-03-04 11:48:25 +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