320 Commits

Author SHA1 Message Date
Lukas May
ce991fd8a4 Merge branch 'cw/improve-initiatives-ui' into cw-merge-1772872758746 2026-03-07 09:39:19 +01:00
Lukas May
59e710bc31 test: re-record full-flow cassettes 2026-03-07 01:09:30 +01:00
Lukas May
57784576e4 perf: speed up slow git tests from ~18s to ~5.5s
- branch-manager: beforeEach→beforeAll (all 12 tests are read-only)
- worktree manager: clone template repo per test instead of full init
- signal-manager: reduce setTimeout delay from 100ms to 30ms
2026-03-07 01:07:43 +01:00
Lukas May
4a657d6b96 fix: stabilize useQuery mock reference to prevent infinite re-render loop in AgentOutputViewer test 2026-03-07 01:01:37 +01:00
Lukas May
bf4a55f2f2 refactor: rewrite errand prompts with structured XML sections
Bring buildErrandPrompt() and buildErrandRevisionPrompt() in line with
the codebase pattern used by execute, plan, detail, etc. Import shared
DEVIATION_RULES and GIT_WORKFLOW constants. Add session_startup (pwd,
git status, CLAUDE.md, expected-pwd.txt), execution_rules, and
anti_patterns sections. Keep signal format inline since errands use
result.message instead of the standard questions format.
2026-03-07 01:00:36 +01:00
Lukas May
89f74efdb5 fix: add missing HQWaitingForInputSection component to fix broken test import
The HQSections.test.tsx imported HQWaitingForInputSection which was missing
after phase branch merges. The component was referenced in tests but never
created, causing the entire test file to fail with an import resolution error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 00:53:58 +01:00
Lukas May
3885a96c9d fix: strengthen signal.json prompt to prevent premature writes
Agents sometimes write signal.json before finishing output files,
causing work to be silently discarded. Replace weak "As your final
action" with explicit CRITICAL warning explaining the completion
trigger mechanism.
2026-03-07 00:51:25 +01:00
Lukas May
c3fb000f92 fix: prevent phase stuck in_progress when merge fails
In YOLO mode, if mergePhaseIntoInitiative() threw (e.g., branch
doesn't exist, merge conflict), the error propagated and completePhase()
was never called — leaving the phase permanently stuck at in_progress.

Also wrap per-phase recovery in try-catch so one failing phase doesn't
abort the entire recoverDispatchQueues() loop.
2026-03-07 00:44:46 +01:00
Lukas May
4298a8f4a6 Merge branch 'cw/improve-initiatives-ui-phase-default-filter-and-sessionstorage-persistence' into cw-merge-1772840051793 2026-03-07 00:34:11 +01:00
Lukas May
1dc908a8ab feat: add listInitiatives sort-order tests and qualityReview persistence
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 00:34:07 +01:00
Lukas May
1acc0b297e Merge branch 'cw/improve-initiatives-ui-phase-default-filter-and-sessionstorage-persistence' into cw-merge-1772840034224 2026-03-07 00:33:54 +01:00
Lukas May
7c35f262cf feat: default statusFilter to active with sessionStorage persistence
- Export DashboardPage for testability
- Initialize statusFilter from sessionStorage (key: initiatives.statusFilter),
  falling back to "active" when absent or invalid
- Write new filter value to sessionStorage on every change via
  handleStatusFilterChange, enabling same-session navigation persistence
- Add aria-label="Status" to the status select for accessible querying
- Add Vitest unit tests covering all 8 scenarios (default, read, write, fallback)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 00:33:26 +01:00
Lukas May
ed9184e0f1 Merge branch 'cw/improve-inbox-ui-on-hq' into cw-merge-1772839945283 2026-03-07 00:32:25 +01:00
Lukas May
b708977ef1 feat: add context panel, logs section, and task name fix to InboxDetailPanel
Enriches the HQ inbox detail view so users can answer agent questions
without navigating away from the inbox:

- Replace raw task UUID in header with human-readable task name
  (falls back to UUID, then em dash when both null)
- Add related context panel showing initiative link, task name,
  truncated/HTML-stripped description, and phase name; shows skeleton
  while loading, "No task context available" when agent has no task
- Add collapsible agent logs section using AgentOutputViewer;
  hidden when no output exists, resets on agent change
- Wire new props (taskName, phaseName, initiativeName, initiativeId,
  taskDescription, isLoadingContext) in hq.tsx from listWaitingAgents
- Add 11 tests covering all new behaviors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 00:31:32 +01:00
Lukas May
61aa0f9dd4 feat: rewrite InitiativeCard to single-row compact layout with tests
Replaces the two-row card layout with a single horizontal flex row that
fits within 48-56px height. Adds project badge overflow (max 2 + chip),
hover-reveal menu (opacity-0/group-hover), phase counter (X / Y),
active phase name with separator, and StatusDot pulse behavior.

Removes ProgressBar, status label text, and second row entirely.
Adds Vitest unit tests covering all 6 test groups from the spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 00:21:53 +01:00
Lukas May
40ec85deb8 fix: resolve all failing frontend tests
- Fix vitest.config.ts React alias to point to local node_modules
  instead of nonexistent ancestor path (../../../../node_modules/react)
- Remove stale HQWaitingForInputSection tests (component was deleted
  in e8d332e0 but test cases were left behind)
2026-03-07 00:14:44 +01:00
Lukas May
40900a5641 fix: self-healing stale worktree recovery in SimpleGitWorktreeManager
When git worktree add fails with "branch already used by worktree at
<path>", parse the stale path, force-remove it, and retry once. Fixes
blocked task retries where the old agent-workdirs directory still exists
on disk and git worktree prune alone can't clear the reference.
2026-03-07 00:13:24 +01:00
Lukas May
c52fa86542 refactor: unify errand worktree paths to use agent-workdirs/<alias>/
Errands now create worktrees via ProcessManager.createWorktreesForProjects()
into agent-workdirs/<alias>/<project.name>/ instead of repos/<project>/.cw-worktrees/<errandId>.
This makes getAgentWorkdir + resolveAgentCwd work correctly for all agent types.

Key changes:
- Extract createWorktreesForProjects() from createProjectWorktrees() in ProcessManager
- Add resolveAgentCwd() to ProcessManager (probes for .cw/output in subdirs)
- Add projectId to SpawnAgentOptions for single-project agents (errands)
- Skip auto-cleanup for errand agents (worktrees persist for merge/abandon)
- Errand router uses agentManager.delete() for cleanup instead of SimpleGitWorktreeManager
- Remove cwd parameter from sendUserMessage (resolves via worktreeId)
- Add pruneProjectRepos() to CleanupManager for errand worktree refs
2026-03-07 00:02:27 +01:00
Lukas May
7e6921f01e feat: enrich listWaitingAgents with task/phase/initiative context via DB joins
Replaces the in-memory filter (agentManager.list() + filter) with a direct
repository query that LEFT JOINs tasks, phases, and initiatives to return
taskName, phaseName, initiativeName, and taskDescription alongside agent fields.

- Adds AgentWithContext interface and findWaitingWithContext() to AgentRepository port
- Implements findWaitingWithContext() in DrizzleAgentRepository using getTableColumns
- Wires agentRepository into TRPCContext, CreateContextOptions, and TrpcAdapterOptions
- Adds requireAgentRepository() helper following existing pattern
- Updates listWaitingAgents to use repository query instead of agentManager
- Adds 5 unit tests for findWaitingWithContext() covering all FK join edge cases
- Updates existing AgentRepository mocks to satisfy updated interface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 23:29:49 +01:00
Lukas May
b17c0a2b4f fix: resolve errand worktree path for sendMessage instead of using agent-workdirs
Errand agents are spawned in the errand's git worktree (managed by
SimpleGitWorktreeManager), not in agent-workdirs/<alias>/.
sendUserMessage was deriving the cwd from worktreeId which pointed to
the non-existent agent-workdirs path. Now the errand.sendMessage
procedure resolves the actual worktree path and passes it through.
2026-03-06 23:11:55 +01:00
Lukas May
bc61e658dc fix: allow re-detailing phases after all tasks are deleted
The "Detail Tasks" button was hidden when an idle detail agent from a
previous run was still associated with the phase. The frontend gate
blocked any re-detail while a detail agent existed, even if it was idle
(i.e. done). The backend already auto-dismisses stale idle agents, so
the frontend just needed to allow idle agents through the gate.
2026-03-06 22:43:56 +01:00
Lukas May
e7c95af1ca fix: skip standalone worktree when errand provides cwd
When spawn() receives an explicit cwd (errands), the manager was still
creating a standalone worktree at agent-workdirs/<alias>/ and injecting
its path into the workspace layout prompt. The agent then edited files
in the wrong directory — on a different branch than the errand's.

Now when cwd is provided, we skip worktree creation entirely and use
the caller's cwd for workspace layout, .cw/output/, and all paths.
2026-03-06 22:39:56 +01:00
Lukas May
79a0bd0a74 Merge branch 'cw/continuous-code-quality' into cw-merge-1772833031033 2026-03-06 22:37:11 +01:00
Lukas May
b21d32fd91 Merge branch 'main' into cw/continuous-code-quality-conflict-1772832123778
# Conflicts:
#	apps/server/drizzle/meta/0037_snapshot.json
#	apps/server/drizzle/meta/_journal.json
2026-03-06 22:30:21 +01:00
Lukas May
a61376812a fix: errand baseBranch defaults to project.defaultBranch instead of 'main' 2026-03-06 22:27:12 +01:00
Lukas May
3ceb991200 fix: errand output race condition + require commit before signal
Merge two useEffects in AgentOutputViewer into one to fix race where
agentId reset clears messages after data effect sets them on remount.

Add "commit before signaling" instruction to errand prompts so
Changes tab shows diff after completion.
2026-03-06 22:23:50 +01:00
Lukas May
e199188670 feat: cw task add CLI command + {AGENT_ID} prompt placeholder
- Add `createTaskForAgent` tRPC mutation: resolves agent → task → phase, creates sibling task
- Add `cw task add <name> --agent-id <id>` CLI command
- Replace `{AGENT_ID}` and `{AGENT_NAME}` placeholders in writeInputFiles() before flushing
- Update docs/agent.md and docs/cli-config.md
2026-03-06 22:22:49 +01:00
Lukas May
753b2e9fb8 fix: resolve integration issues after phase branch merges
- Register errandProcedures in appRouter (was defined but never spread)
- Fix nullable projectId guard in errand delete/abandon procedures
- Add sendUserMessage stub to MockAgentManager in headquarters and
  radar-procedures tests (AgentManager interface gained this method)
- Add missing qualityReview field to Initiative fixture in file-io test
  (schema gained this column from the quality-review phase)
- Cast conflictFiles access in CLI errand resolve command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:16:53 +01:00
Lukas May
0211cdb8a6 Merge branch 'cw/continuous-code-quality-phase-quality-review-dispatch-hook' into cw-merge-1772831549281 2026-03-06 22:12:29 +01:00
Lukas May
425728205c chore: resolve merge conflicts — wire quality review into orchestrator handleAgentStopped
Resolved conflicts between cw/continuous-code-quality-phase-quality-review-dispatch-hook
and cw/continuous-code-quality-task-Cjc9jRT48MqxIZSQG3ypl.

- orchestrator.ts: adopted tryQualityReview() helper (incoming) over inline
  shouldRunQualityReview() call (HEAD); fixed duplicate agentManager constructor
  param; reordered optional params to agentRepository?, agentManager?
- orchestrator.test.ts: merged import blocks, used incoming mock defaults with
  .mockResolvedValue(), removed duplicate agentManager/agentRepository in
  createMocks(), used incoming createOrchestrator opts pattern; added missing
  project mock so HEAD's integration test works with tryQualityReview() flow
- docs/dispatch-events.md: kept HEAD's more explicit agent:stopped description
- container.ts: removed duplicate agentManager arg; reordered to match new
  constructor signature (agentRepository, agentManager)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:12:13 +01:00
Lukas May
30dcb8340a test: add error resilience case to orchestrator quality review hook tests
Adds the fourth test case from the spec: when shouldRunQualityReview
throws, the orchestrator must not crash, must log a warning (verified
implicitly by the catch block), and must still call scheduleDispatch()
so dispatch continuity is maintained.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:10:15 +01:00
Lukas May
6482960c6f feat: errand review & request changes
Add errand.requestChanges procedure that re-spawns an agent in the
existing worktree with user feedback. Replace raw <pre> diff blocks
with syntax-highlighted ErrandDiffView using FileCard components.
Add Output/Changes tabs to the active errand view.
2026-03-06 22:09:01 +01:00
Lukas May
4bc65bfe3d feat: wire quality review into orchestrator handleAgentStopped
When an agent stops, check whether a quality review should run before
auto-completing the task. If shouldRunQualityReview returns run:true,
delegate to runQualityReview (which transitions task to quality_review
and spawns a review agent) instead of calling completeTask directly.

Falls back to completeTask when agentRepository or agentManager are
not injected, or when the task lacks phaseId/initiativeId context.

- Add agentManager optional param to ExecutionOrchestrator constructor
- Extract tryQualityReview() private method to compute branch names and
  repo path before delegating to the quality-review service
- Pass agentManager to ExecutionOrchestrator in container.ts
- Add orchestrator integration tests for the agent:stopped quality hook

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:05:42 +01:00
Lukas May
b6a01e5748 Merge branch 'cw/continuous-code-quality-task-_Om84Be00WJgnctOvmkyo' into cw/continuous-code-quality-phase-quality-review-dispatch-hook
# Conflicts:
#	apps/server/execution/quality-review.test.ts
#	apps/server/execution/quality-review.ts
2026-03-06 22:04:50 +01:00
Lukas May
c3cace7604 feat: add quality-review dispatch hook to intercept agent:stopped events
When an execute-mode agent stops with task_complete and the initiative has
qualityReview=true, the orchestrator now spawns a fresh execute-mode agent
to run /simplify on changed .ts/.tsx/.js files before marking the task
completed. The task transitions through quality_review status as a recursion
guard so the review agent's stop event is handled normally.

- Add apps/server/execution/quality-review.ts with three exported functions:
  computeQualifyingFiles, shouldRunQualityReview, runQualityReview
- Add apps/server/execution/quality-review.test.ts (28 tests)
- Update ExecutionOrchestrator to accept agentManager, replace
  handleAgentStopped with quality-review-aware logic, add getRepoPathForTask
- Update orchestrator.test.ts with 3 quality-review integration tests
- Update container.ts to pass agentManager to ExecutionOrchestrator
- Update docs/dispatch-events.md to reflect new agent:stopped behavior

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:01:02 +01:00
Lukas May
9200891a5d feat: add quality-review service with qualifying file detection and agent spawning
Adds apps/server/execution/quality-review.ts with three exported functions:
- computeQualifyingFiles: diffs task branch vs base, filters out *.gen.ts and dist/ paths
- shouldRunQualityReview: evaluates all six guard conditions (task_complete, execute mode,
  in_progress status, initiative membership, qualityReview flag, non-empty changeset)
  and returns { run, qualifyingFiles } to avoid recomputing the diff in the orchestrator
- runQualityReview: transitions task to quality_review, spawns execute-mode review agent
  on the task branch, logs the review agent ID, and falls back to completed on spawn failure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:56:18 +01:00
Lukas May
bb770407db feat: expose qualityReview via updateInitiativeConfig tRPC mutation
Adds qualityReview: z.boolean().optional() to the updateInitiativeConfig
input schema so the field passes through to the repository layer.
Includes integration tests verifying set-true, set-false, and
omit-preserves-existing round-trip behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:53:58 +01:00
Lukas May
5137a60e70 feat: add quality_review task status and qualityReview initiative flag
Adds two new fields to the database and propagates them through the
repository layer:

- Task status enum gains 'quality_review' (between in_progress and
  completed), enabling a QA gate before tasks are marked complete.
- initiatives.quality_review (INTEGER DEFAULT 0) lets an initiative be
  flagged for quality-review workflow without a data migration (existing
  rows default to false).

Includes:
- Schema changes in schema.ts
- Migration 0037 (ALTER TABLE initiatives ADD quality_review)
- Snapshot chain repaired: deleted stale 0036 snapshot, fixed 0035
  prevId to create a linear chain (0032 → 0034 → 0035), then generated
  clean 0037 snapshot
- Repository adapter already uses SELECT * / spread-update pattern so
  no adapter code changes were needed
- Initiative and task repository tests extended with qualityReview /
  quality_review_status describe blocks (7 new tests)
- docs/database.md updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:47:34 +01:00
Lukas May
dca4224d26 Merge branch 'cw/merge-hq-inbox' into cw-merge-1772829971134 2026-03-06 21:46:11 +01:00
Lukas May
a3a9076411 Merge branch 'cw/radar-screen-performance' into cw-merge-1772829950184 2026-03-06 21:45:50 +01:00
Lukas May
e8d332e04b feat: embed InboxList + InboxDetailPanel inline on HQ page
Replaces HQWaitingForInputSection with a two-column inline panel that
lets users answer agent questions directly from HQ without navigating
to /inbox. Adds SSE invalidation for listWaitingAgents/listMessages,
useState for agent selection, and all required mutations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:45:26 +01:00
Lukas May
9c468f17cb chore: update generated route tree 2026-03-06 21:44:55 +01:00
Lukas May
346d62ef8d fix: prevent stale duplicate planning tasks from blocking phase completion
Three fixes for phases getting stuck when a detail task crashes and is retried:

1. detailPhase mutation (architect.ts): clean up orphaned pending/in_progress
   detail tasks before creating new ones, preventing duplicates at the source
2. orchestrator recovery: detect and complete stale duplicate planning tasks
   (same category+phase, one completed, one pending)
3. ensureBranch: catch "already exists" TOCTOU race instead of blocking phase
2026-03-06 21:44:26 +01:00
Lukas May
ee8c7097db fix: use String() instead of .toISOString() for errand timestamps
tRPC without superjson serializes Date objects as plain strings/numbers
over the wire. The .toISOString() calls crashed because the values
aren't Date instances on the client. Matches the existing pattern used
elsewhere (e.g. agents page).
2026-03-06 21:42:26 +01:00
Lukas May
f497905043 Merge branch 'cw/merge-hq-inbox-phase-nav-badge-move-questions-count-to-hq-remove-inbox-item' into cw-merge-1772829625670 2026-03-06 21:40:25 +01:00
Lukas May
d97afa84d4 Merge branch 'cw/radar-screen-performance-phase-backfill-script-cw-backfill-metrics-cli-command-docs' into cw-merge-1772829393658 2026-03-06 21:36:33 +01:00
Lukas May
db2196f1d1 feat: add backfill-metrics script and cw backfill-metrics CLI command
Populates the agent_metrics table from existing agent_log_chunks data after
the schema migration. Reads chunks in batches of 500, accumulates per-agent
counts in memory, then upserts with additive ON CONFLICT DO UPDATE to match
the ongoing insertChunk write-path behavior.

- apps/server/scripts/backfill-metrics.ts: core backfillMetrics(db) + CLI wrapper backfillMetricsFromPath(dbPath)
- apps/server/scripts/backfill-metrics.test.ts: 8 tests covering all chunk types, malformed JSON, isolation, empty DB, and re-run double-count behavior
- apps/server/cli/index.ts: new top-level `cw backfill-metrics [--db <path>]` command
- docs/database-migrations.md: Post-migration backfill scripts section documenting when and how to run the script

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:36:08 +01:00
Lukas May
1fd3a1ae4a fix: make errand.list input optional so frontend query works without args 2026-03-06 21:35:30 +01:00
Lukas May
4a9f38c4e1 perf: replace O(N·chunks) listForRadar read path with O(N·agents) metrics lookup
listForRadar previously called findByAgentIds() and JSON-parsed every chunk to
compute questionsCount, subagentsCount, and compactionsCount. Switch to
findMetricsByAgentIds() which reads the pre-computed agent_metrics table,
eliminating the chunk scan and per-row JSON.parse entirely.

Add two new test cases: agent with no metrics row returns zero counts, and
listForRadar response rows never carry chunk content.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:35:29 +01:00
Lukas May
6eb1f8fc2a feat: add agent_metrics write+read path to LogChunkRepository
Wrap insertChunk in a synchronous better-sqlite3 transaction that upserts
agent_metrics counters atomically on every chunk insert. Malformed JSON
skips the upsert but always preserves the chunk row.

Add findMetricsByAgentIds to the interface and Drizzle adapter for
efficient bulk metric reads.

Add 8-test suite covering all write/read paths and edge cases.

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