- `errand.get` now returns `conflictFiles: string[]` (always an array,
never null) with defensive JSON.parse error handling
- `errand.get` returns `projectPath: string | null` computed from
workspaceRoot + getProjectCloneDir so cw errand resolve can locate
the worktree without a second tRPC call
- Add `apps/server/db/repositories/drizzle/errand.test.ts` covering
conflictFiles store/retrieve, null for non-conflict errands, and
findAll including conflictFiles
- Update `errand.test.ts` mock to include getProjectCloneDir and fix
conflictFiles expectation from null to []
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wires errand command group into CLI with start, list, chat, diff,
complete, merge, resolve, abandon, and delete subcommands. All
commands call tRPC procedures via createDefaultTrpcClient(). The
start command validates description length client-side (≤200 chars)
before making any network calls.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the errand detail panel with three context-aware views:
- Active: live agent output via AgentOutputViewer, chat input, Mark Done/Abandon
- Pending review/conflict: diff block, conflict notice with file list, Merge/Delete/Abandon
- Merged/abandoned: read-only diff, info line with relative date, Delete only
Follows TaskSlideOver.tsx patterns: Framer Motion slide-in, backdrop, Escape key close.
Shift+click skips window.confirm on all destructive actions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Replace the original design document / brainstorm with a focused project
README covering what Codewalkers does, getting started, architecture,
supported providers, CLI reference, workflow, development, testing, and
links to detailed docs.
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>
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>
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>
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>
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>
Option A ("ask inline, session stays open") described a path where the
errand agent could ask questions without writing signal.json, which broke
the server's completion detection (checkAgentCompletionResult polls for
done|questions|error status). Remove the Option A/B distinction and make
signal.json with questions status the single mechanism for all user-input
requests, consistent with how other agents handle blocking questions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
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.
The errand agent can now write { "status": "questions", ... } to
signal.json to pause mid-task and ask the user for clarification.
The session ends cleanly; the user answers via UI or CLI; the system
resumes the agent with their answers via sendUserMessage.
Two changes:
- buildErrandPrompt: adds "Option B" explaining the questions signal
format and the resume-on-answer lifecycle, alongside the existing
inline-question approach.
- sendUserMessage: extends allowed statuses from running|idle to also
include waiting_for_input, so agents paused on a questions signal
can be resumed when the user replies.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
- 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>
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>
Add a dedicated "Asking questions" section to the errand prompt so the
agent knows it can pause, ask for clarification, and wait for the user
to reply via the UI chat input or `cw errand chat`. Previously the
prompt said "work interactively" with no guidance on the mechanism,
leaving the agent to guess.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
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.
Implements three primitives needed before errand tRPC procedures can be wired up:
- agentManager.sendUserMessage(agentId, message): resumes an errand agent with a
raw user message, bypassing the conversations table and conversationResumeLocks.
Throws on missing agent, invalid status, or absent sessionId.
- writeErrandManifest(options): writes .cw/input/errand.md (YAML frontmatter),
.cw/input/manifest.json (errandId/agentId/agentName/mode, no files/contextFiles),
and .cw/expected-pwd.txt to an agent workdir.
- buildErrandPrompt(description): minimal prompt for errand agents; exported from
prompts/errand.ts and re-exported from prompts/index.ts.
Also fixes a pre-existing TypeScript error in lifecycle/controller.test.ts (missing
backoffMs property in RetryPolicy mock introduced by a concurrent agent commit).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Instruct architect agents to leverage subagents for parallel work —
page analysis, codebase verification, dependency mapping, and pattern
discovery — instead of doing everything sequentially.
- 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>
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
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>
7 of 12 initiative activity state transitions were broken due to missing
event routing at three layers: SSE event arrays, live-update prefix rules,
and mutation invalidation map.
- Add initiative:changes_requested to ALL_EVENT_TYPES and TASK_EVENT_TYPES
- Add initiative:/agent: prefix rules to initiatives list and detail pages
- Add approveInitiativeReview, requestInitiativeChanges, requestPhaseChanges
to INVALIDATION_MAP; add listInitiatives to approvePhase
- Extract INITIATIVE_LIST_RULES constant for reuse
Implements three primitives needed before errand tRPC procedures can be wired up:
- agentManager.sendUserMessage(agentId, message): resumes an errand agent with a
raw user message, bypassing the conversations table and conversationResumeLocks.
Throws on missing agent, invalid status, or absent sessionId.
- writeErrandManifest(options): writes .cw/input/errand.md (YAML frontmatter),
.cw/input/manifest.json (errandId/agentId/agentName/mode, no files/contextFiles),
and .cw/expected-pwd.txt to an agent workdir.
- buildErrandPrompt(description): minimal prompt for errand agents; exported from
prompts/errand.ts and re-exported from prompts/index.ts.
Also fixes a pre-existing TypeScript error in lifecycle/controller.test.ts (missing
backoffMs property in RetryPolicy mock introduced by a concurrent agent commit).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds an Output/Details tab bar to the agents page right-panel. The Details
tab renders AgentDetailsPanel, which surfaces agent metadata (status, mode,
provider, initiative link, task name, exit code), input files with a
file-picker UI, and the effective prompt text — all streamed via the new
getAgent/getAgentInputFiles/getAgentPrompt tRPC procedures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>