feat: wire conflictFiles through errand.get and add repository tests
- `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>
This commit is contained in:
@@ -35,6 +35,7 @@ vi.mock('../../git/manager.js', () => ({
|
||||
|
||||
vi.mock('../../git/project-clones.js', () => ({
|
||||
ensureProjectClone: mockEnsureProjectClone,
|
||||
getProjectCloneDir: vi.fn().mockReturnValue('repos/test-project-abc123'),
|
||||
}));
|
||||
|
||||
vi.mock('../../agent/file-io.js', async (importOriginal) => {
|
||||
@@ -393,7 +394,7 @@ describe('errand procedures', () => {
|
||||
|
||||
expect(result.id).toBe(errand.id);
|
||||
expect(result).toHaveProperty('agentAlias');
|
||||
expect(result.conflictFiles).toBeNull();
|
||||
expect(result.conflictFiles).toEqual([]);
|
||||
});
|
||||
|
||||
it('parses conflictFiles JSON when present', async () => {
|
||||
|
||||
@@ -18,8 +18,9 @@ import {
|
||||
} from './_helpers.js';
|
||||
import { writeErrandManifest } from '../../agent/file-io.js';
|
||||
import { buildErrandPrompt } from '../../agent/prompts/index.js';
|
||||
import { join } from 'node:path';
|
||||
import { SimpleGitWorktreeManager } from '../../git/manager.js';
|
||||
import { ensureProjectClone } from '../../git/project-clones.js';
|
||||
import { ensureProjectClone, getProjectCloneDir } from '../../git/project-clones.js';
|
||||
import type { TRPCContext } from '../context.js';
|
||||
|
||||
// ErrandStatus values for input validation
|
||||
@@ -200,10 +201,27 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
if (!errand) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Errand not found' });
|
||||
}
|
||||
return {
|
||||
...errand,
|
||||
conflictFiles: errand.conflictFiles ? (JSON.parse(errand.conflictFiles) as string[]) : null,
|
||||
};
|
||||
|
||||
// Parse conflictFiles; return [] on null or malformed JSON
|
||||
let conflictFiles: string[] = [];
|
||||
if (errand.conflictFiles) {
|
||||
try {
|
||||
conflictFiles = JSON.parse(errand.conflictFiles) as string[];
|
||||
} catch {
|
||||
conflictFiles = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Compute project clone path for cw errand resolve
|
||||
let projectPath: string | null = null;
|
||||
if (errand.projectId && ctx.workspaceRoot) {
|
||||
const project = await requireProjectRepository(ctx).findById(errand.projectId);
|
||||
if (project) {
|
||||
projectPath = join(ctx.workspaceRoot, getProjectCloneDir(project.name, project.id));
|
||||
}
|
||||
}
|
||||
|
||||
return { ...errand, conflictFiles, projectPath };
|
||||
}),
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user