f18db021c3
调度: - model/scoring.ts: score = 自身分(P0=3/P1=2/P2=1) + 已完成依赖分(链条惯性) + 等待解锁的 blocked 任务分(解锁加权),编排器与 nextExecutable 同一打分 - createTask 校验 deps 存在且同项目(依赖图天然无环) - daemon 重启中断自愈: executing 任务标 failed run 后重新入队(reconcileInterrupted) 执行管线: - executor/cc.ts: 公共 headless CC 执行器(转录/超时/模型回退重试) - executor/reviewer.ts: 执行后自动复审(只读 CC 审 diff),固定模板 summary (做了什么/怎么做/测试/CodeReview/安全Review/结论) + VERDICT 解析 - executor/models.ts: 按复杂度选模型(easy→sonnet/medium→opus/hard→fable5), env 可覆盖、project.model 最优先、不可用自动回退链 - runner: 测试/构建命令白名单(npm/go/shellcheck/make/pytest),prompt 要求实跑测试 - TaskResult 加 summary/verdict; RunKind 加 reviewer - 容器收口: 已拆解 Hard 子任务全 done → 容器自动 done(afterDone 逐级向上) 看板: - 五徽章组(待审批/待执行/执行中/被阻塞/总量,hover 展开,均不含已完成) - 归档区: 深度1整树完成沉底,时间倒序分页(10/20/50/100 chip 选择) - 归档详情对话框: 全属性/执行历史与时长/审批记录/状态流转时间线(含相关人或事) - Agent 面板显示调度模式 + 各复杂度实际模型 - 结果闸展示复审 summary + 建议通过/拒绝徽章 - 筛选修复(组选与单选分离、已拆解移出进行中)、同步按钮收进配置面板、 保存配置自动收起、预览全宽、被依赖阻塞→被阻塞 - API: GET /api/tasks/:id/events(任务级事件时间线)、/api/agents 带 scheduling/models 测试: 49/49(新增 scoring/复审/模型/容器收口/deps 校验/中断恢复) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
193 lines
8.4 KiB
HTML
193 lines
8.4 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>MAESTRO · 任务调度台</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
|
|
<!-- ════════ 左栏:项目 ════════ -->
|
|
<aside id="sidebar">
|
|
<div class="logo">
|
|
<div class="logo-word">MAESTRO<span class="cursor">▮</span></div>
|
|
<div class="logo-sub">多项目任务调度台</div>
|
|
</div>
|
|
|
|
<div class="side-head">
|
|
<span class="head-mark">▍</span>项目
|
|
<button class="btn btn-ghost btn-xs" data-action="open-new-project">+ 新建</button>
|
|
</div>
|
|
<ul id="projectList" class="project-list"></ul>
|
|
|
|
<div class="side-foot">
|
|
<span id="wsDot" class="ws-dot off"></span>
|
|
<span id="wsText">连接中…</span>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- ════════ 中栏:闸 + 任务树 ════════ -->
|
|
<main id="main">
|
|
<header id="topbar">
|
|
<div>
|
|
<div id="projTitle" class="proj-title">—</div>
|
|
<div id="projMeta" class="proj-meta"></div>
|
|
</div>
|
|
<div class="spacer"></div>
|
|
<div id="badgeGroup" class="badge-group" hidden>
|
|
<span id="bdgGate" class="bdg bdg-gate" title="等待你裁决的审批闸">
|
|
<span class="bdg-ico">⚠</span><span class="bdg-n">0</span><span class="bdg-label">待审批</span>
|
|
</span>
|
|
<span id="bdgReady" class="bdg bdg-ready" title="可执行(依赖已满足)+ 排队中">
|
|
<span class="bdg-ico">▸</span><span class="bdg-n">0</span><span class="bdg-label">待执行</span>
|
|
</span>
|
|
<span id="bdgRun" class="bdg bdg-run" title="agent 正在执行">
|
|
<span class="bdg-ico">◉</span><span class="bdg-n">0</span><span class="bdg-label">执行中</span>
|
|
</span>
|
|
<span id="bdgBlocked" class="bdg bdg-blocked" title="被依赖阻塞(依赖完成后自动放行)">
|
|
<span class="bdg-ico">⛓</span><span class="bdg-n">0</span><span class="bdg-label">被阻塞</span>
|
|
</span>
|
|
<span id="bdgTotal" class="bdg bdg-total" title="未完成任务总量(不含 done / 已拆解容器 / 取消)">
|
|
<span class="bdg-ico">Σ</span><span class="bdg-n">0</span><span class="bdg-label">总量</span>
|
|
</span>
|
|
</div>
|
|
<div id="topActions" class="top-actions" hidden>
|
|
<button class="btn btn-xs" data-action="toggle-config" title="项目配置(并发 / 工作模式 / todo 同步)">⚙ 配置</button>
|
|
</div>
|
|
</header>
|
|
|
|
<section id="configPanel" class="panel config-panel" hidden>
|
|
<div class="form-row">
|
|
<label class="narrow">最大并发
|
|
<input id="cfgConcurrency" type="number" min="1" step="1" value="1">
|
|
</label>
|
|
<label>工作模式
|
|
<select id="cfgAutonomy">
|
|
<option value="manual">manual · 手动</option>
|
|
<option value="auto-easy">auto-easy · 自动执行 Easy</option>
|
|
<option value="auto-approved">auto-approved · 自动执行已批准</option>
|
|
</select>
|
|
</label>
|
|
<span id="cfgCurrent" class="cfg-current"></span>
|
|
<button class="btn btn-solid" data-action="save-config">保存配置</button>
|
|
<button class="btn" data-action="toggle-config">收起</button>
|
|
</div>
|
|
<div class="form-row cfg-sync-row">
|
|
<span id="syncMeta" class="sync-meta"></span>
|
|
<button id="btnSync" class="btn btn-xs" data-action="sync-todo">⟳ 同步 todo</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="agentSection" class="agent-section">
|
|
<div class="sec-head"><span class="head-mark cyan">▍</span>Agent 执行<span id="agentTotal" class="agent-total"></span></div>
|
|
<div id="agentBody"></div>
|
|
</section>
|
|
|
|
<section id="gateSection" class="gate-section" hidden>
|
|
<div class="gate-stripe"></div>
|
|
<div class="sec-head gate-head"><span class="head-mark amber">▍</span>审批闸 · 等待裁决</div>
|
|
<div id="gateList"></div>
|
|
</section>
|
|
|
|
<section id="taskSection">
|
|
<div class="sec-head">
|
|
<span class="head-mark">▍</span>任务树
|
|
<button class="btn btn-ghost btn-xs" data-action="toggle-new-task">+ 新建任务</button>
|
|
</div>
|
|
|
|
<form id="newTaskPanel" class="panel form-panel" hidden>
|
|
<div class="form-row">
|
|
<label class="grow">标题 <span class="req">*</span>
|
|
<input name="title" type="text" placeholder="要做什么" autocomplete="off">
|
|
</label>
|
|
</div>
|
|
<div class="form-row">
|
|
<label>复杂度 <span class="req">*</span>
|
|
<span class="seg" id="cplxSeg">
|
|
<input type="radio" name="complexity" value="hard" id="cx-h"><label for="cx-h" class="seg-h">HARD</label>
|
|
<input type="radio" name="complexity" value="medium" id="cx-m" checked><label for="cx-m" class="seg-m">MEDIUM</label>
|
|
<input type="radio" name="complexity" value="easy" id="cx-e"><label for="cx-e" class="seg-e">EASY</label>
|
|
</span>
|
|
</label>
|
|
<label>父任务
|
|
<select name="parentId"><option value="">(顶层)</option></select>
|
|
</label>
|
|
<label class="narrow">优先级
|
|
<select name="priority">
|
|
<option value="0">P0 · 高</option>
|
|
<option value="1" selected>P1 · 中</option>
|
|
<option value="2">P2 · 低</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
<div class="form-row form-actions">
|
|
<button type="submit" class="btn btn-solid">创建任务</button>
|
|
<button type="button" class="btn" data-action="toggle-new-task">取消</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div id="filterBar" class="filter-bar" hidden>
|
|
<div class="filter-row">
|
|
<input id="filterKw" type="text" placeholder="⌕ 搜索标题…" autocomplete="off">
|
|
<span id="filterCplx" class="fchips"></span>
|
|
<span class="spacer"></span>
|
|
<span id="filterCount" class="filter-count"></span>
|
|
<button class="btn btn-ghost btn-xs" id="filterClear" data-action="filter-clear" hidden>✕ 清除筛选</button>
|
|
</div>
|
|
<div id="filterStatus" class="filter-row"></div>
|
|
</div>
|
|
|
|
<div id="taskTree"></div>
|
|
</section>
|
|
|
|
<!-- ════════ 已归档(done / 取消,时间倒序分页) ════════ -->
|
|
<section id="archiveSection" hidden>
|
|
<div class="sec-head"><span class="head-mark">▣</span>已归档 · <span id="archiveCount">0</span></div>
|
|
<div id="archiveList"></div>
|
|
<div id="archivePager" class="archive-pager"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<!-- ════════ 右栏:事件流 ════════ -->
|
|
<aside id="eventPanel">
|
|
<div class="sec-head"><span class="head-mark">▍</span>事件流</div>
|
|
<ul id="eventList" class="event-list"></ul>
|
|
</aside>
|
|
</div>
|
|
|
|
<!-- 新建项目 模态 -->
|
|
<div id="modalRoot" class="modal-root" hidden>
|
|
<div class="modal-mask" data-action="close-modal"></div>
|
|
<form id="newProjectForm" class="modal panel">
|
|
<div class="sec-head"><span class="head-mark">▍</span>新建项目</div>
|
|
<label>名称 <span class="req">*</span>
|
|
<input name="name" type="text" placeholder="my-project" autocomplete="off">
|
|
</label>
|
|
<label>仓库路径 <span class="req">*</span>
|
|
<input name="repoPath" type="text" placeholder="/path/to/repo" autocomplete="off">
|
|
</label>
|
|
<label>默认分支
|
|
<input name="defaultBranch" type="text" placeholder="main">
|
|
</label>
|
|
<label>校验命令
|
|
<input name="verifyCmd" type="text" placeholder="npm test(可空)">
|
|
</label>
|
|
<div class="form-row form-actions">
|
|
<button type="submit" class="btn btn-solid">创建</button>
|
|
<button type="button" class="btn" data-action="close-modal">取消</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div id="previewRoot" class="preview-root" hidden></div>
|
|
<div id="archiveModalRoot" class="preview-root" hidden></div>
|
|
<div id="toastRoot" class="toast-root"></div>
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|