import type { Task, WorkflowStepResult } from "./types.js"; const BLOCKING_TASK_STATUSES = new Set([ "failed", "awaiting-inspection", ]); const NON_TERMINAL_STEP_STATUSES = new Set([ "pending", "in-progress", ]); const NON_TERMINAL_WORKFLOW_STATUSES = new Set([ "pending", "failed", ]); /** * Returns a human-readable reason when a task in review is not safe to finalize. * Undefined means the task is eligible to move from `in-review` to `done`. */ export function getTaskMergeBlocker( task: Pick, ): string | undefined { if (task.column !== "in-review") { return `task is in '${task.column}', must be in 'in-review'`; } if (task.paused) { return "task is paused"; } if (task.status && BLOCKING_TASK_STATUSES.has(task.status)) { return task.error ? `task is marked '${task.status}': ${task.error}` : `task is marked '${task.status}'`; } if (task.steps.length > 0 && task.steps.some((step) => NON_TERMINAL_STEP_STATUSES.has(step.status))) { return "task has incomplete steps"; } if ( task.workflowStepResults?.some((result) => NON_TERMINAL_WORKFLOW_STATUSES.has(result.status)) ) { return "task has incomplete or failed workflow steps"; } return undefined; } export function isTaskReadyForMerge( task: Pick, ): boolean { return getTaskMergeBlocker(task) === undefined; }