feat: Phase1 核心——模型/状态机 + SQLite Store(守卫+审批闸) + REST/WS API + daemon

- src/model: 复杂度分级、16 状态状态机、实体类型
- src/store: better-sqlite3 接 schema,transition 受 canTransition 守卫,
  decide 审批闸(reject 必带改进意见),事件订阅广播,nextExecutable
- src/api: Fastify REST + ws 事件广播(/ws)
- src/daemon: maestrod 入口(env 配置,默认 ~/.maestro :4517)
- test: 9 个生命周期单测全过;typecheck/build 干净;REST+WS 端到端实跑验证

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-12 20:44:45 +08:00
commit 3172718a94
18 changed files with 2757 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
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; status: string; created_at: string;
}
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; created_at: string; updated_at: string;
}
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;
}
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, status: r.status as Project['status'], createdAt: r.created_at,
};
}
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 ? (JSON.parse(r.result) as TaskResult) : null,
assignee: r.assignee as Task['assignee'], 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,
};
}
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<string, unknown>, at: r.at,
};
}