From 753b2e9fb8aa94ccfc27e3571c539005b3ec4a35 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Fri, 6 Mar 2026 22:16:53 +0100 Subject: [PATCH] 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 --- apps/server/agent/file-io.test.ts | 1 + apps/server/cli/index.ts | 2 +- apps/server/test/unit/headquarters.test.ts | 1 + .../server/test/unit/radar-procedures.test.ts | 1 + apps/server/trpc/router.ts | 2 ++ apps/server/trpc/routers/errand.ts | 28 +++++++++++-------- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/apps/server/agent/file-io.test.ts b/apps/server/agent/file-io.test.ts index ae0fb9a..96bc6a1 100644 --- a/apps/server/agent/file-io.test.ts +++ b/apps/server/agent/file-io.test.ts @@ -52,6 +52,7 @@ describe('writeInputFiles', () => { status: 'active', branch: 'cw/test-initiative', executionMode: 'review_per_phase', + qualityReview: false, createdAt: new Date('2026-01-01'), updatedAt: new Date('2026-01-02'), }; diff --git a/apps/server/cli/index.ts b/apps/server/cli/index.ts index 8fc0425..cda8766 100644 --- a/apps/server/cli/index.ts +++ b/apps/server/cli/index.ts @@ -1878,7 +1878,7 @@ See the Codewalkers documentation for .cw-preview.yml format and options.`; : `.cw-worktrees/${id}`; console.log(`Resolve conflicts in worktree: ${worktreePath}`); console.log('Conflicting files:'); - for (const f of errand.conflictFiles ?? []) { + for (const f of (errand as any).conflictFiles ?? []) { console.log(` ${f}`); } console.log('After resolving: stage and commit changes in the worktree, then run:'); diff --git a/apps/server/test/unit/headquarters.test.ts b/apps/server/test/unit/headquarters.test.ts index bc94e09..0176c5e 100644 --- a/apps/server/test/unit/headquarters.test.ts +++ b/apps/server/test/unit/headquarters.test.ts @@ -63,6 +63,7 @@ class MockAgentManager implements AgentManager { async delete(): Promise { throw new Error('Not implemented'); } async dismiss(): Promise { throw new Error('Not implemented'); } async resumeForConversation(): Promise { return false; } + async sendUserMessage(): Promise { throw new Error('Not implemented'); } } // ============================================================================= diff --git a/apps/server/test/unit/radar-procedures.test.ts b/apps/server/test/unit/radar-procedures.test.ts index d7acba6..01d642e 100644 --- a/apps/server/test/unit/radar-procedures.test.ts +++ b/apps/server/test/unit/radar-procedures.test.ts @@ -69,6 +69,7 @@ class MockAgentManager implements AgentManager { async delete(): Promise { throw new Error('Not implemented'); } async dismiss(): Promise { throw new Error('Not implemented'); } async resumeForConversation(): Promise { return false; } + async sendUserMessage(): Promise { throw new Error('Not implemented'); } } // ============================================================================= diff --git a/apps/server/trpc/router.ts b/apps/server/trpc/router.ts index 43ad5d3..9f24841 100644 --- a/apps/server/trpc/router.ts +++ b/apps/server/trpc/router.ts @@ -25,6 +25,7 @@ import { previewProcedures } from './routers/preview.js'; import { conversationProcedures } from './routers/conversation.js'; import { chatSessionProcedures } from './routers/chat-session.js'; import { headquartersProcedures } from './routers/headquarters.js'; +import { errandProcedures } from './routers/errand.js'; // Re-export tRPC primitives (preserves existing import paths) export { router, publicProcedure, middleware, createCallerFactory } from './trpc.js'; @@ -65,6 +66,7 @@ export const appRouter = router({ ...conversationProcedures(publicProcedure), ...chatSessionProcedures(publicProcedure), ...headquartersProcedures(publicProcedure), + ...errandProcedures(publicProcedure), }); export type AppRouter = typeof appRouter; diff --git a/apps/server/trpc/routers/errand.ts b/apps/server/trpc/routers/errand.ts index 57fb738..39b144c 100644 --- a/apps/server/trpc/routers/errand.ts +++ b/apps/server/trpc/routers/errand.ts @@ -350,12 +350,14 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) { } // Remove worktree and branch (best-effort) - const project = await requireProjectRepository(ctx).findById(errand.projectId); - if (project) { - const clonePath = await resolveClonePath(project, ctx); - const worktreeManager = new SimpleGitWorktreeManager(clonePath); - try { await worktreeManager.remove(errand.id); } catch { /* no-op if already gone */ } - try { await requireBranchManager(ctx).deleteBranch(clonePath, errand.branch); } catch { /* no-op */ } + if (errand.projectId) { + const project = await requireProjectRepository(ctx).findById(errand.projectId); + if (project) { + const clonePath = await resolveClonePath(project, ctx); + const worktreeManager = new SimpleGitWorktreeManager(clonePath); + try { await worktreeManager.remove(errand.id); } catch { /* no-op if already gone */ } + try { await requireBranchManager(ctx).deleteBranch(clonePath, errand.branch); } catch { /* no-op */ } + } } await repo.delete(errand.id); @@ -426,12 +428,14 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) { } // Remove worktree and branch (best-effort) - const project = await requireProjectRepository(ctx).findById(errand.projectId); - if (project) { - const clonePath = await resolveClonePath(project, ctx); - const worktreeManager = new SimpleGitWorktreeManager(clonePath); - try { await worktreeManager.remove(errand.id); } catch { /* no-op if already gone */ } - try { await branchManager.deleteBranch(clonePath, errand.branch); } catch { /* no-op */ } + if (errand.projectId) { + const project = await requireProjectRepository(ctx).findById(errand.projectId); + if (project) { + const clonePath = await resolveClonePath(project, ctx); + const worktreeManager = new SimpleGitWorktreeManager(clonePath); + try { await worktreeManager.remove(errand.id); } catch { /* no-op if already gone */ } + try { await branchManager.deleteBranch(clonePath, errand.branch); } catch { /* no-op */ } + } } const updated = await repo.update(input.id, { status: 'abandoned' });