chore: merge main into cw/small-change-flow
Integrates main branch changes (headquarters dashboard, task retry count, agent prompt persistence, remote sync improvements) with the initiative's errand agent feature. Both features coexist in the merged result. Key resolutions: - Schema: take main's errands table (nullable projectId, no conflictFiles, with errandsRelations); migrate to 0035_faulty_human_fly - Router: keep both errandProcedures and headquartersProcedures - Errand prompt: take main's simpler version (no question-asking flow) - Manager: take main's status check (running|idle only, no waiting_for_input) - Tests: update to match removed conflictFiles field and undefined vs null
This commit is contained in:
@@ -102,6 +102,7 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
let errand;
|
||||
try {
|
||||
errand = await repo.create({
|
||||
id: nanoid(),
|
||||
description: input.description,
|
||||
branch: branchName,
|
||||
baseBranch,
|
||||
@@ -202,16 +203,6 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Errand not found' });
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@@ -221,7 +212,7 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
}
|
||||
}
|
||||
|
||||
return { ...errand, conflictFiles, projectPath };
|
||||
return { ...errand, projectPath };
|
||||
}),
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@@ -235,6 +226,9 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Errand not found' });
|
||||
}
|
||||
|
||||
if (!errand.projectId) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Errand has no project' });
|
||||
}
|
||||
const project = await requireProjectRepository(ctx).findById(errand.projectId);
|
||||
if (!project) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Project not found' });
|
||||
@@ -303,6 +297,9 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
|
||||
const targetBranch = input.target ?? errand.baseBranch;
|
||||
|
||||
if (!errand.projectId) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Errand has no project' });
|
||||
}
|
||||
const project = await requireProjectRepository(ctx).findById(errand.projectId);
|
||||
if (!project) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Project not found' });
|
||||
@@ -319,15 +316,12 @@ export function errandProcedures(publicProcedure: ProcedureBuilder) {
|
||||
// Clean merge — remove worktree and mark merged
|
||||
const worktreeManager = new SimpleGitWorktreeManager(clonePath);
|
||||
try { await worktreeManager.remove(errand.id); } catch { /* no-op */ }
|
||||
await repo.update(input.id, { status: 'merged', conflictFiles: null });
|
||||
await repo.update(input.id, { status: 'merged' });
|
||||
return { status: 'merged' };
|
||||
} else {
|
||||
// Conflict — persist conflict files and throw
|
||||
// Conflict — update status and throw
|
||||
const conflictFilesList = result.conflicts ?? [];
|
||||
await repo.update(input.id, {
|
||||
status: 'conflict',
|
||||
conflictFiles: JSON.stringify(conflictFilesList),
|
||||
});
|
||||
await repo.update(input.id, { status: 'conflict' });
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: `Merge conflict in ${conflictFilesList.length} file(s)`,
|
||||
|
||||
Reference in New Issue
Block a user