import type { Project, Task, ApprovalRecord, Run, Event, TaskResult, Autonomy } from '../model/types.js'; import type { Complexity } from '../model/complexity.js'; import type { TaskStatus, GateKind } from '../model/status.js'; import type { RunKind, RunStatus, EventType } from '../model/types.js'; /** SQLite 行类型(snake_case,文本/数字原样) */ export interface ProjectRow { id: string; name: string; repo_path: string; default_branch: string; verify_cmd: string | null; autonomy: string; model: string | null; concurrency: number; max_retries: number; timeout_ms: number; status: string; created_at: string; last_sync_at: string | null; logo: string | null; sort_order: number; checks: string | null; auto_approve_plan: number; auto_approve_exec: number; budget_usd: number | null; budget_period: string | null; agent_rules: string | null; } export interface TaskRow { id: string; project_id: string; parent_id: string | null; depth: number; title: string; complexity: string; status: string; priority: number; deps: string; plan: string | null; spec: string | null; operations: string | null; result: string | null; assignee: string | null; retry_baseline: number; next_eligible_at: string | null; created_at: string; updated_at: string; source_ref: string | null; attachments: string | null; last_run_error?: string | null; // pendingApprovals 扩展字段(subquery) } export interface ApprovalRow { id: string; task_id: string; gate: string; action: string; actor: string; reason: string | null; at: string; } export interface RunRow { id: string; task_id: string; kind: string; worktree: string | null; branch: string | null; status: string; started_at: string; ended_at: string | null; transcript_ref: string | null; claude_session_id: string | null; error: string | null; worker_pid: number | null; last_seq: number; usage: string | null; cost_usd: number | null; } export interface EventRow { id: string; project_id: string; task_id: string | null; type: string; payload: string; at: string; } export function rowToProject(r: ProjectRow): Project { return { id: r.id, name: r.name, repoPath: r.repo_path, defaultBranch: r.default_branch, verifyCmd: r.verify_cmd, autonomy: r.autonomy as Autonomy, model: r.model, concurrency: r.concurrency, maxRetries: r.max_retries ?? 2, timeoutMs: r.timeout_ms ?? 1_800_000, status: r.status as Project['status'], createdAt: r.created_at, lastSyncAt: r.last_sync_at, logo: r.logo, sortOrder: r.sort_order, checks: r.checks ?? null, autoApprovePlan: Boolean(r.auto_approve_plan), autoApproveExec: Boolean(r.auto_approve_exec), budgetUsd: r.budget_usd ?? null, budgetPeriod: (r.budget_period === 'day' ? 'day' : 'month'), agentRules: r.agent_rules ?? null, }; } /** 旧 result JSON 兜底:summary/verdict/securitySummary/securityVerdict 是后加字段,老数据缺省补 null */ function parseResult(json: string): TaskResult { const raw = JSON.parse(json) as Partial; const verdict = (v: unknown): TaskResult['verdict'] => (v === 'approve' || v === 'reject' ? v : null); return { branch: raw.branch ?? null, worktree: raw.worktree ?? null, diffSummary: raw.diffSummary ?? null, commits: raw.commits ?? [], prUrl: raw.prUrl ?? null, summary: raw.summary ?? null, verdict: verdict(raw.verdict), securitySummary: raw.securitySummary ?? null, securityVerdict: verdict(raw.securityVerdict), mergeTaskId: raw.mergeTaskId ?? null, }; } export function rowToTask(r: TaskRow, approvals: ApprovalRecord[] = []): Task { return { id: r.id, projectId: r.project_id, parentId: r.parent_id, depth: r.depth, title: r.title, complexity: r.complexity as Complexity, status: r.status as TaskStatus, priority: r.priority, deps: JSON.parse(r.deps) as string[], plan: r.plan, spec: r.spec, operations: r.operations, approvals, result: r.result ? parseResult(r.result) : null, assignee: r.assignee as Task['assignee'], retryBaseline: r.retry_baseline ?? 0, nextEligibleAt: r.next_eligible_at ?? null, lastRunError: r.last_run_error ?? null, attachments: r.attachments ? (JSON.parse(r.attachments) as Task['attachments']) : undefined, createdAt: r.created_at, updatedAt: r.updated_at, }; } export function rowToApproval(r: ApprovalRow): ApprovalRecord { return { gate: r.gate as GateKind, action: r.action as ApprovalRecord['action'], actor: r.actor, reason: r.reason, at: r.at, }; } export function rowToRun(r: RunRow): Run { return { id: r.id, taskId: r.task_id, kind: r.kind as RunKind, worktree: r.worktree, branch: r.branch, status: r.status as RunStatus, startedAt: r.started_at, endedAt: r.ended_at, transcriptRef: r.transcript_ref, claudeSessionId: r.claude_session_id, error: r.error, workerPid: r.worker_pid ?? null, lastSeq: r.last_seq ?? 0, usage: r.usage ? (JSON.parse(r.usage) as Run['usage']) : null, costUsd: r.cost_usd ?? null, }; } export function rowToEvent(r: EventRow): Event { return { id: r.id, projectId: r.project_id, taskId: r.task_id, type: r.type as EventType, payload: JSON.parse(r.payload) as Record, at: r.at, }; }