Remove task-level approval system

Task-level approval (requiresApproval, mergeRequiresApproval,
pending_approval status) was redundant with executionMode
(yolo vs review_per_phase) and blocked the orchestrator's
phase completion flow. Tasks now complete directly;
phase-level review via executionMode is the right granularity.

Removed: schema columns (left in DB, removed from Drizzle),
TaskPendingApprovalEvent, approveTask/listPendingApprovals
procedures, findPendingApproval repository method, and all
frontend approval UI.
This commit is contained in:
Lukas May
2026-03-05 17:09:48 +01:00
parent 209629241d
commit 8804455c77
27 changed files with 48 additions and 237 deletions

View File

@@ -4,7 +4,7 @@
* Implements TaskRepository interface using Drizzle ORM.
*/
import { eq, asc, and } from 'drizzle-orm';
import { eq, asc } from 'drizzle-orm';
import { nanoid } from 'nanoid';
import type { DrizzleDatabase } from '../../index.js';
import { tasks, taskDependencies, type Task } from '../../schema.js';
@@ -12,7 +12,6 @@ import type {
TaskRepository,
CreateTaskData,
UpdateTaskData,
PendingApprovalFilters,
} from '../task-repository.js';
/**
@@ -77,26 +76,6 @@ export class DrizzleTaskRepository implements TaskRepository {
.orderBy(asc(tasks.order));
}
async findPendingApproval(filters?: PendingApprovalFilters): Promise<Task[]> {
const conditions = [eq(tasks.status, 'pending_approval')];
if (filters?.initiativeId) {
conditions.push(eq(tasks.initiativeId, filters.initiativeId));
}
if (filters?.phaseId) {
conditions.push(eq(tasks.phaseId, filters.phaseId));
}
if (filters?.category) {
conditions.push(eq(tasks.category, filters.category));
}
return this.db
.select()
.from(tasks)
.where(and(...conditions))
.orderBy(asc(tasks.createdAt));
}
async update(id: string, data: UpdateTaskData): Promise<Task> {
const [updated] = await this.db
.update(tasks)

View File

@@ -22,7 +22,6 @@ export type {
TaskRepository,
CreateTaskData,
UpdateTaskData,
PendingApprovalFilters,
} from './task-repository.js';
export type {

View File

@@ -20,15 +20,6 @@ export type CreateTaskData = Omit<NewTask, 'id' | 'createdAt' | 'updatedAt'> & {
*/
export type UpdateTaskData = Partial<CreateTaskData>;
/**
* Filters for finding pending approval tasks.
*/
export interface PendingApprovalFilters {
initiativeId?: string;
phaseId?: string;
category?: TaskCategory;
}
/**
* Task Repository Port
*
@@ -70,13 +61,6 @@ export interface TaskRepository {
*/
findByPhaseId(phaseId: string): Promise<Task[]>;
/**
* Find all tasks with status 'pending_approval'.
* Optional filters by initiative, phase, or category.
* Returns tasks ordered by createdAt.
*/
findPendingApproval(filters?: PendingApprovalFilters): Promise<Task[]>;
/**
* Update a task.
* Throws if task not found.

View File

@@ -22,9 +22,6 @@ export const initiatives = sqliteTable('initiatives', {
status: text('status', { enum: ['active', 'completed', 'archived', 'pending_review'] })
.notNull()
.default('active'),
mergeRequiresApproval: integer('merge_requires_approval', { mode: 'boolean' })
.notNull()
.default(true),
branch: text('branch'), // Auto-generated initiative branch (e.g., 'cw/user-auth')
executionMode: text('execution_mode', { enum: ['yolo', 'review_per_phase'] })
.notNull()
@@ -153,11 +150,10 @@ export const tasks = sqliteTable('tasks', {
.notNull()
.default('medium'),
status: text('status', {
enum: ['pending_approval', 'pending', 'in_progress', 'completed', 'blocked'],
enum: ['pending', 'in_progress', 'completed', 'blocked'],
})
.notNull()
.default('pending'),
requiresApproval: integer('requires_approval', { mode: 'boolean' }), // null = inherit from initiative
order: integer('order').notNull().default(0),
summary: text('summary'), // Agent result summary — propagated to dependent tasks as context
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),