fa472a06a7
后端: - src/sync/todo-sync.ts: todo.json 单向同步引擎(导入=首次同步,幂等,source_ref 映射, subs 复杂度修正为 easy,旧侧 done 历史事实优先 forceDone) - 依赖自动落位:ready 意图按 deps 落位 blocked,依赖全 done 自动放行, daemon 启动 reconcileDeps 对账,手动绕过会弹回 - 新 API: PATCH projects/:id(autonomy/concurrency)、POST :id/sync、GET /api/agents、 PATCH tasks/:id(title/priority/complexity 重置) - daemon 定时同步(MAESTRO_SYNC_INTERVAL 默认 300s) + project.synced 事件 - priority 语义翻转: P0 最高/P1 默认/P2 最低,取值限 0..2,排序/映射/MCP/CLI 全跟进 - 静态服务发 no-cache 头(修浏览器吃旧 CSS/JS) - schema 迁移: tasks.source_ref / projects.last_sync_at(ensureColumn 平滑升级旧库) 看板: - 全屏预览模式(94vh 读完整方案+就地裁决,Esc/遮罩/裁决自动关闭) - 产出 markdown 渲染为 HTML(零依赖渲染器,转义优先) - 任务树筛选(复杂度/状态分组/关键字)+ 顶栏徽章组(待审批/可执行/执行中,hover 展开) - 依赖可视化:详情 DEPS 区块 + 行内⛓等依赖 + 锚点跳转定位 - 按钮收敛:提交评审/编辑产出移除(CC 经 MCP 操作),界面只留用户动作 - Agent 执行面板 + 项目配置(并发/工作模式)+ 同步按钮 测试:21 个全过(新增 sync 幂等/迁移/patch/依赖落位/对账幂等) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
75 lines
3.2 KiB
TypeScript
75 lines
3.2 KiB
TypeScript
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;
|
|
last_sync_at: 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; created_at: string; updated_at: string;
|
|
source_ref: string | null;
|
|
}
|
|
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,
|
|
lastSyncAt: r.last_sync_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,
|
|
};
|
|
}
|