Files
maestro/docs/optimization-plan.html
T
wangjia fa4ba3db28 feat(rule13): 执行前分歧重评估闸——main 撞声明范围→needs_attention 重评估
通用规则13的(B)半边:sync main 之前先跑 reevalScopeGate,
以 git diff HEAD...origin/main 取 main 自分支点以来改动的文件,
与任务 scopeFiles 求交集;非空即 emit needs-reeval →
daemon markReeval 直接转 needs_attention(不重试/不计失败/run收尾cancelled)。

- checks.ts: + reevalScopeGate / ReevalGateFn / ReevalGateResult
- pipeline.ts: createWorktree 后、syncMain 前插入重评估闸 + reevalGate 依赖注入
- protocol.ts: + needs-reeval OutboxRecord/Payload 事件
- ingest.ts: + case 'needs-reeval' → store.markReeval
- store.ts: + markReeval(executing→needs_attention,不进重试链)
- status.ts: executing 合法转移 + needs_attention
- 测试 +5:reevalScopeGate(命中/未命中/空/无前移/git错) · pipeline(命中emit/未命中续跑) · store.markReeval;全套 242 绿
- docs: optimization-plan.html 规则13 标  已实现

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 20:15:02 +08:00

968 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Maestro 三类任务执行方法优化方案</title>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<style>
:root {
--bg: #0f1117;
--bg2: #1a1d27;
--bg3: #242736;
--border: #2e3148;
--text: #e2e4ef;
--text2: #9ba3c2;
--accent: #6c8aff;
--green: #4caf82;
--orange: #f0a35b;
--red: #e05a5a;
--purple: #b47bff;
--teal: #4ec9b0;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--text);
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 14px;
line-height: 1.7;
}
header {
background: var(--bg2);
border-bottom: 1px solid var(--border);
padding: 24px 40px;
position: sticky; top: 0; z-index: 10;
}
header h1 { font-size: 20px; color: var(--accent); letter-spacing: .5px; }
header p { color: var(--text2); font-size: 12px; margin-top: 4px; }
.toc {
background: var(--bg2);
border-bottom: 1px solid var(--border);
padding: 12px 40px;
display: flex; gap: 24px; flex-wrap: wrap;
}
.toc a { color: var(--text2); text-decoration: none; font-size: 13px; }
.toc a:hover { color: var(--accent); }
main { max-width: 1200px; margin: 0 auto; padding: 40px; }
section { margin-bottom: 60px; }
h2 {
font-size: 18px; color: var(--accent);
border-left: 3px solid var(--accent);
padding-left: 14px;
margin-bottom: 24px;
}
h3 { font-size: 15px; color: var(--teal); margin: 24px 0 12px; }
h4 { font-size: 13px; color: var(--orange); margin: 16px 0 8px; }
/* Category cards */
.cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
.cat-card {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 20px;
}
.cat-card .label { font-size: 11px; color: var(--text2); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 6px; }
.cat-card .value { color: var(--text); font-size: 13px; }
.cat-card .value.changed { color: var(--green); }
.cat-card .value.new { color: var(--orange); }
/* Dim table */
.dim-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.dim-table th {
background: var(--bg3);
color: var(--text2);
text-align: left;
padding: 8px 12px;
font-weight: 600;
font-size: 11px;
letter-spacing: .5px;
border-bottom: 1px solid var(--border);
}
.dim-table td {
padding: 10px 12px;
border-bottom: 1px solid var(--border);
vertical-align: top;
}
.dim-table tr:last-child td { border-bottom: none; }
.dim-table tr:hover td { background: rgba(108,138,255,.04); }
.dim-label { color: var(--text2); width: 120px; }
.dim-was { color: var(--text2); font-size: 12px; text-decoration: line-through; opacity: .6; }
.dim-now { color: var(--green); font-weight: 600; }
.dim-same { color: var(--text); }
.tag {
display: inline-block;
padding: 1px 7px;
border-radius: 4px;
font-size: 11px;
font-weight: 600;
margin-right: 4px;
}
.tag-new { background: rgba(240,163,91,.15); color: var(--orange); border: 1px solid rgba(240,163,91,.3); }
.tag-changed { background: rgba(76,175,130,.15); color: var(--green); border: 1px solid rgba(76,175,130,.3); }
.tag-keep { background: rgba(155,163,194,.1); color: var(--text2); border: 1px solid rgba(155,163,194,.2); }
.tag-hard { background: rgba(224,90,90,.15); color: var(--red); border: 1px solid rgba(224,90,90,.3); }
.tag-fable { background: rgba(180,123,255,.15); color: var(--purple); border: 1px solid rgba(180,123,255,.3); }
.tag-opus { background: rgba(108,138,255,.15); color: var(--accent); border: 1px solid rgba(108,138,255,.3); }
.tag-sonnet { background: rgba(78,201,176,.15); color: var(--teal); border: 1px solid rgba(78,201,176,.3); }
/* Rules */
.rule-list { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.rule-item {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 6px;
padding: 14px 16px;
display: grid;
grid-template-columns: 28px 1fr;
gap: 0 12px;
}
.rule-num {
color: var(--accent);
font-weight: 700;
font-size: 13px;
padding-top: 1px;
}
.rule-body strong { color: var(--orange); }
.rule-impl {
grid-column: 2;
margin-top: 6px;
font-size: 12px;
color: var(--text2);
border-left: 2px solid var(--border);
padding-left: 10px;
}
.rule-impl code { color: var(--teal); }
/* DB tables */
.db-grid { display: flex; flex-direction: column; gap: 16px; }
.db-table-card {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
}
.db-table-card .db-header {
background: var(--bg3);
padding: 10px 16px;
display: flex; align-items: center; gap: 10px;
}
.db-table-card .db-name { font-weight: 700; color: var(--accent); font-size: 14px; }
.db-table-card .db-desc { color: var(--text2); font-size: 12px; }
.db-cols { padding: 0; }
.db-col {
display: grid;
grid-template-columns: 180px 120px 1fr;
gap: 0;
padding: 8px 16px;
border-bottom: 1px solid var(--border);
font-size: 12px;
}
.db-col:last-child { border-bottom: none; }
.db-col .col-name { color: var(--teal); font-weight: 600; }
.db-col .col-type { color: var(--orange); }
.db-col .col-note { color: var(--text2); }
.db-col.highlight { background: rgba(108,138,255,.05); }
/* State machine */
.mermaid-wrap {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 24px;
overflow-x: auto;
}
.mermaid { display: flex; justify-content: center; }
/* Badges */
.badge {
display: inline-flex; align-items: center;
padding: 2px 10px; border-radius: 12px;
font-size: 11px; font-weight: 700;
}
.badge-approved { background: rgba(76,175,130,.2); color: var(--green); }
.badge-new { background: rgba(240,163,91,.2); color: var(--orange); }
/* Status flow */
.flow-row {
display: flex; align-items: center; flex-wrap: wrap;
gap: 8px; margin: 8px 0;
}
.st {
background: var(--bg3);
border: 1px solid var(--border);
border-radius: 5px;
padding: 3px 10px;
font-size: 12px;
color: var(--text);
}
.st.gate { border-color: var(--orange); color: var(--orange); }
.st.terminal { border-color: var(--green); color: var(--green); }
.st.err { border-color: var(--red); color: var(--red); }
.st.attn { border-color: var(--purple); color: var(--purple); }
.arrow { color: var(--text2); font-size: 13px; }
code { background: var(--bg3); padding: 1px 5px; border-radius: 3px; color: var(--teal); font-size: 12px; }
.note { color: var(--text2); font-size: 12px; margin-top: 6px; }
.divider { border: none; border-top: 1px solid var(--border); margin: 32px 0; }
</style>
</head>
<body>
<header>
<h1>Maestro · 三类任务执行方法优化方案</h1>
<p>2026-06-14 定稿 · 2026-06-25 全部实现并上线 · 含实现状态</p>
</header>
<nav class="toc">
<a href="#status">★ 实现状态</a>
<a href="#cat1">① 任务拆解类 (planner)</a>
<a href="#cat2">② 执行类 (executor)</a>
<a href="#cat3">③ 解冲突类 (conflict)</a>
<a href="#rules">④ 通用规则 (13条)</a>
<a href="#fsm">⑤ 状态机流转图</a>
<a href="#db">⑥ 数据库结构</a>
</nav>
<main>
<!-- ============================================================ 实现状态 -->
<section id="status">
<h2>★ 实现状态 <span class="badge badge-approved">✅ 全部上线</span></h2>
<p style="color:var(--text2);margin-bottom:16px">本方案各项已于 2026-06-25 实现、补测试并经 launchd daemon 端到端实跑验证;下表为「优化点 → 实现 → 提交」对照。线上实测捕获并修复了 3 个单测未覆盖的 bug(DB 迁移漏列 / fable-5 不可用未触发回退 / autoApproveExec 传错 id)。</p>
<table class="dim-table">
<thead>
<tr>
<th style="width:170px">优化点</th>
<th>实现要点</th>
<th style="width:90px">状态</th>
<th style="width:120px">提交</th>
</tr>
</thead>
<tbody>
<tr><td class="dim-label">Agent 记忆注入 L1L4</td>
<td>L1 上次失败原因(重试任务)· L2 项目级 agent 规范(DB 列)· L3 拆解背景(父意图+兄弟状态)· L4 全局规范文件,注入 4 处 prompt 头部</td>
<td><span class="badge badge-approved"></span></td>
<td><code>ecea1ae</code> <code>fe7923a</code> <code>74be3ec</code></td></tr>
<tr><td class="dim-label">① plan 自动放行</td>
<td>autoApprovePlan:全 easy 子任务 + ≤5 个时跳过 plan_review(项目级开关,默认关)</td>
<td><span class="badge badge-approved"></span></td>
<td><code>73f80d2</code></td></tr>
<tr><td class="dim-label">② approve 前硬闸</td>
<td>分项 lint/typecheck/build 闸 + diff 体量闸 + 复审并行(Promise.all</td>
<td><span class="badge badge-approved"></span></td>
<td><code>2d12769</code></td></tr>
<tr><td class="dim-label">② exec 自动放行</td>
<td>autoApproveExec:双复审 approve 后跳过 exec_review 自动 --no-ff 合并;抽出共享合并流程 exec-merge.ts</td>
<td><span class="badge badge-approved"></span></td>
<td><code>1f318c2</code> <code>4c09186</code></td></tr>
<tr><td class="dim-label">模型可配置(项目维度)</td>
<td>projects.modelsJSON,按角色×复杂度覆盖);默认统一 opus-4.8;优先级 models &gt; 旧 project.model(仅 exec/planner&gt; env &gt; 默认;回退链 opus→sonnet→fable</td>
<td><span class="badge badge-approved"></span></td>
<td><code>ff2d7c2</code> <code>59ce391</code></td></tr>
<tr><td class="dim-label">② diff 声明外文件闸</td>
<td>tasks.scope_filesglob/路径);scopeFileGate 改动越界=硬闸;planner 拆解出 files 自动填充;executor prompt 注入范围约束</td>
<td><span class="badge badge-approved"></span></td>
<td><code>59ce391</code></td></tr>
<tr><td class="dim-label">线上实测 bug 修复</td>
<td>ensureColumn 漏迁移补列 · isModelError 识别「issue with the selected model」触发回退 · autoApproveExec 传错 id</td>
<td><span class="badge badge-approved"></span></td>
<td><code>1bf3fec</code> <code>a9c5102</code> <code>4c09186</code></td></tr>
</tbody>
</table>
<p class="note">注:③ 解冲突专用 conflict run / 模型固定档 等部分按方案落地,conflict 模型同样走「项目可配置 + 默认 opus-4.8」。fable-5 在本机不可用,已从内置默认移除,仅在项目级显式配置时使用。</p>
</section>
<!-- ============================================================ CAT 1 -->
<section id="cat1">
<h2>① 任务拆解类 (planner) <span class="badge badge-approved">✅ 定稿</span></h2>
<p style="color:var(--text2);margin-bottom:16px">Hard 任务拆解(decompose) · Medium 写方案(spec) · 只读主仓、不建 worktree</p>
<table class="dim-table">
<thead>
<tr>
<th style="width:130px">维度</th>
<th style="width:260px">现状</th>
<th>优化决策</th>
<th style="width:80px">变更</th>
</tr>
</thead>
<tbody>
<tr>
<td class="dim-label">触发 / 执行期锁</td>
<td>Hard→analyzing / Medium→speccing;无写保护</td>
<td class="dim-now">
<strong>执行期锁(通用规则)</strong>:任务有在途 run 即锁只读;禁改 title/spec/complexity/deps,禁再调度;run 结束解锁。<br>
<span class="note">覆盖 AUTO 占位回填竞态;store mutation 入口 + API 层加"在途即拒"校验。</span>
</td>
<td><span class="tag tag-new">新增</span></td>
</tr>
<tr>
<td class="dim-label">调度并发</td>
<td>与 executor 共用 concurrency 池</td>
<td class="dim-same">维持共用池,不改并发模型</td>
<td><span class="tag tag-keep">不变</span></td>
</tr>
<tr>
<td class="dim-label">执行流程</td>
<td>纯只读 Read/Glob/GrepmaxTurns=60 固定</td>
<td class="dim-now">
① 加 <code>Bash(git log/*)</code> <code>Bash(git diff/*)</code> <code>Bash(git show/*)</code>(读历史/演化)<br>
② decompose prompt 注入 <code>tasks.depth</code> + 剩余可拆层数(≤3层),防无限拆 hard<br>
③ maxTurns 按复杂度:<strong>hard=90 / medium=60 / easy=40</strong>
</td>
<td><span class="tag tag-changed">改进</span></td>
</tr>
<tr>
<td class="dim-label">模型 / 档位</td>
<td>一律 <code>claude-opus-4-8</code></td>
<td class="dim-now">
按复杂度分档:<span class="tag tag-hard">hard</span> <span class="tag tag-fable">fable-5</span>
<span class="tag tag-changed">medium</span> <span class="tag tag-opus">opus-4-8</span>
<span class="tag tag-keep">easy</span> <span class="tag tag-sonnet">sonnet-4-6</span><br>
env <code>MAESTRO_MODEL_PLAN_EASY/MEDIUM/HARD</code> 三档可独立覆盖
</td>
<td><span class="tag tag-changed">改进</span></td>
</tr>
<tr>
<td class="dim-label">输出格式</td>
<td>spec=3段mddecompose=分析+fenced JSON<br><code>{plan, subtasks:[{title,complexity}]}</code></td>
<td class="dim-now">
<strong>decompose</strong> 扩展为:<br>
&nbsp;① 正文先输出子任务 <strong>Markdown 表格</strong>(标题/复杂度/优先级/依赖序号)供人审<br>
&nbsp;② 末尾 JSON 扩展:<code>{plan, subtasks:[{title,complexity,priority,deps:[序号]}]}</code><br>
&nbsp;③ 解析向后兼容(缺 deps/priority 给默认值);deps 序号→taskId 二次映射后写 <code>tasks.deps</code><br>
<strong>spec</strong> 增加验收标准必填 + 可选影响文件清单
</td>
<td><span class="tag tag-changed">扩展</span></td>
</tr>
<tr>
<td class="dim-label">是否审批</td>
<td>decompose→plan_reviewspec→spec_review;均强制人审</td>
<td class="dim-now">
默认仍人审;<strong>可选自动放行</strong>(默认关):<br>
<code>auto-approved</code> + 拆解全 easy + 子任务数≤N → 跳过 plan_review 直接 ready<br>
<span class="note">项目级开关 autoApprovePlan 控制;高风险,默认关</span>
</td>
<td><span class="tag tag-new">新增选项</span></td>
</tr>
</tbody>
</table>
<h4>实现涉及文件</h4>
<div class="cat-grid" style="margin-top:8px">
<div class="cat-card">
<div class="label">models.ts</div>
<div class="value changed">planner 档位表三档分化:sonnet/opus/fable(当前三档同值 opus</div>
</div>
<div class="cat-card">
<div class="label">runner.ts · runPlanner</div>
<div class="value changed">allowedTools 加3条 git 只读;maxTurns 改按复杂度取值</div>
</div>
<div class="cat-card">
<div class="label">runner.ts · buildPlannerPrompt</div>
<div class="value changed">decompose 分支:注入 depth/剩余层数;改要求表格+扩展 JSON</div>
</div>
<div class="cat-card">
<div class="label">pipeline.ts · parseDecompose</div>
<div class="value changed">解析扩展 JSON 字段 priority/deps,兼容旧格式</div>
</div>
<div class="cat-card">
<div class="label">ingest.ts · decompose-result</div>
<div class="value changed">priority 落 createTaskdeps 序号→taskId 二次映射后 setDeps;判定 autoApprovePlan</div>
</div>
<div class="cat-card">
<div class="label">store.ts + api/server.ts</div>
<div class="value new">执行期锁:所有 mutation 入口加"在途即拒"校验</div>
</div>
</div>
</section>
<hr class="divider">
<!-- ============================================================ CAT 2 -->
<section id="cat2">
<h2>② 执行类 (executor + verify + 双复审) <span class="badge badge-approved">✅ 定稿</span></h2>
<p style="color:var(--text2);margin-bottom:16px">执行 → verify → 双复审(code+security)→ exec_review 人审 → 合并</p>
<h3>当前 approve 前的检查链</h3>
<div style="overflow-x:auto;margin-bottom:20px">
<table class="dim-table">
<thead>
<tr><th>#</th><th>检查</th><th>当前性质</th><th>优化后</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>executor 完成 + commit 含 task ID</td><td>硬闸</td><td class="dim-same">不变</td></tr>
<tr><td>2</td><td>verify<code>project.verifyCmd</code>10min,未配=通过)</td><td>硬闸(可选)</td><td class="dim-same">不变</td></tr>
<tr><td>3 <span class="tag tag-new"></span></td><td>执行前 sync main + 分歧度量</td><td></td><td class="dim-now">新增:merge main 进 worktree;冲突/改动面过大→重评估/needs_attention</td></tr>
<tr><td>4 <span class="tag tag-new"></span></td><td>分项 lint/typecheck/build 闸</td><td></td><td class="dim-now">project 可配 checks;分项报告;任一非0=硬失败</td></tr>
<tr><td>5 <span class="tag tag-new"></span></td><td>diff 越界/体量闸</td><td></td><td class="dim-now">改了声明外文件 / diff 行数超阈值 → 拦截或告警</td></tr>
<tr><td>6</td><td>code reviewmaxTurns4015min</td><td style="color:var(--orange)">仅建议</td><td class="dim-now">reject → <strong>硬闸</strong>:退回重执行(带复审意见)而非进 exec_review</td></tr>
<tr><td>7</td><td>security review(与 code 串行)</td><td style="color:var(--orange)">仅建议</td><td class="dim-now">reject → 硬闸;改<strong>并行</strong>跑(Promise.all,总耗≤15min</td></tr>
<tr><td></td><td>exec_review 人审</td><td>强制</td><td class="dim-now">补完硬闸后:auto-approved+全绿+双approve → 自动合并(默认关)</td></tr>
<tr><td>merge</td><td>git merge --no-ffapprove后)</td><td>硬闸</td><td class="dim-same">不变(冲突→③解冲突)</td></tr>
</tbody>
</table>
</div>
<table class="dim-table">
<thead>
<tr><th style="width:130px">维度</th><th style="width:260px">现状</th><th>优化决策</th><th style="width:80px">变更</th></tr>
</thead>
<tbody>
<tr>
<td class="dim-label">触发</td>
<td>ready/queued → claimOne runKind=executor</td>
<td class="dim-now">同上 + 执行前 sync main(通用规则13</td>
<td><span class="tag tag-changed">改进</span></td>
</tr>
<tr>
<td class="dim-label">调度并发</td>
<td>共用 concurrency 池;复审在 worker 内串行,不占名额</td>
<td class="dim-same">维持不变</td>
<td><span class="tag tag-keep">不变</span></td>
</tr>
<tr>
<td class="dim-label">执行流程</td>
<td>建 worktree → executing → verifying → diff → reviewing(串行) → exec_review</td>
<td class="dim-now">
① 新增 sync main 步骤(verify 前)<br>
② 新增 分项检查 + diff 越界闸(verify 后)<br>
③ code+security 双复审改 <strong>Promise.all 并行</strong><br>
④ reject 变硬闸(不进 exec_review,退回/needs_attention
</td>
<td><span class="tag tag-changed">改进</span></td>
</tr>
<tr>
<td class="dim-label">模型 / 档位</td>
<td>reviewer easy=sonnet/medium=opus/hard=opuscode+security 共用档;project.model 覆盖全角色</td>
<td class="dim-now">
复审统一 <span class="tag tag-fable">fable-5</span>(三档全升)<br>
<strong>复审不被 project.model 降档</strong>(保自审独立性)
</td>
<td><span class="tag tag-changed">升档</span></td>
</tr>
<tr>
<td class="dim-label">输出格式</td>
<td>verdict 二元 approve/reject;均为建议</td>
<td class="dim-now">verdict 仍二元;但 <strong>reject 变硬闸</strong>(ingest 分流,不再无条件进 exec_review</td>
<td><span class="tag tag-changed">硬化</span></td>
</tr>
<tr>
<td class="dim-label">是否审批</td>
<td>双复审后一律 exec_review 强制人审</td>
<td class="dim-now">
分阶段:<strong>先补完三项硬闸,再开自动合并</strong><br>
条件:auto-approved + verify全过 + 分项检查全过 + diff合规 + 双approve → 跳过 exec_review 自动合并(默认关)
</td>
<td><span class="tag tag-new">新增选项</span></td>
</tr>
</tbody>
</table>
<h4>实现涉及文件</h4>
<div class="cat-grid" style="margin-top:8px">
<div class="cat-card">
<div class="label">pipeline.ts</div>
<div class="value changed">双复审改 Promise.all;新增 sync main 步骤;加 diff 越界判定</div>
</div>
<div class="cat-card">
<div class="label">models.ts · reviewer 档</div>
<div class="value changed">三档全改 fable-5pickModel 对 reviewer 角色跳过 project.model</div>
</div>
<div class="cat-card">
<div class="label">ingest.ts · result 分支</div>
<div class="value changed">按 code/security verdict 分流:reject→退回重执行;双approve+开关→自动合并</div>
</div>
<div class="cat-card">
<div class="label">verify.ts / pipeline</div>
<div class="value new">分项 lint/typecheck/build 闸(新 project.checks 配置)</div>
</div>
<div class="cat-card">
<div class="label">worktree.ts / pipeline</div>
<div class="value new">执行前 git merge main 进 worktree;分歧度量超阈值→重评估信号</div>
</div>
<div class="cat-card">
<div class="label">protocol.ts</div>
<div class="value changed">新增 phase=sync-mainemit 新信号类型(重评估/diff越界)</div>
</div>
</div>
</section>
<hr class="divider">
<!-- ============================================================ CAT 3 -->
<section id="cat3">
<h2>③ 解冲突类 (conflict agent) <span class="badge badge-new">🆕 新实现</span></h2>
<p style="color:var(--text2);margin-bottom:16px">当前仅检测冲突+abort,无专用 agent;本轮新建完整解冲突流程</p>
<h3>现状硬伤</h3>
<ul style="color:var(--text2);font-size:13px;margin-left:20px;margin-bottom:16px">
<li>executor 白名单<strong style="color:var(--red)">没有 git merge</strong>——补救任务被要求 git merge 却跑不了,CC 只能 Read/Edit 硬模拟,极易丢改动</li>
<li>解冲突标 easy→sonnet<strong style="color:var(--red)">最弱档</strong>,认知难度远超单文件改动</li>
<li>补救 worktree 从 defaultBranch 新建分支,operations 文字写"已从 targetBranch 检出"<strong style="color:var(--red)">文案与实际不符</strong></li>
</ul>
<table class="dim-table">
<thead>
<tr><th style="width:130px">维度</th><th style="width:200px">现状</th><th>优化决策</th><th style="width:80px">变更</th></tr>
</thead>
<tbody>
<tr>
<td class="dim-label">触发 / 调度</td>
<td>合并冲突→建 P0 easy 补救任务;按 score 排队等领取</td>
<td class="dim-now">
触发不变(自动建补救任务,幂等)<br>
调度改为<strong>优先抢占</strong>conflict run 插队,先于普通 executor 领取
</td>
<td><span class="tag tag-changed">改进</span></td>
</tr>
<tr>
<td class="dim-label">执行流程</td>
<td>复用 executor pipelineCC 靠 Read/Edit 猜着解冲突;无专用模板</td>
<td class="dim-now">
<strong>专用 conflict pipeline</strong><br>
1. worker 在补救 worktree 内真正发起 <code>git merge &lt;branch&gt;</code> 制造冲突态<br>
2. CC 以只读+Edit 逐个解冲突文件(白名单加 <code>Bash(git merge:*)</code><br>
3. CC commit 沿用合并 commit message<br>
4. 走双复审(同②)<br>
5. exec_review 通过后自动收口原任务
</td>
<td><span class="tag tag-new">新建</span></td>
</tr>
<tr>
<td class="dim-label">模型 / 档位</td>
<td>easy → sonnet(最弱)</td>
<td class="dim-now">固定 <span class="tag tag-fable">fable-5</span>(不随原任务复杂度,恒最强)</td>
<td><span class="tag tag-changed">大幅升档</span></td>
</tr>
<tr>
<td class="dim-label">输出格式</td>
<td>无专用;executor 自述</td>
<td class="dim-now">
<strong>专用解冲突自述模板</strong><br>
解了哪些文件 / 各文件取舍策略 / 保留了双方哪些意图 / 测试结果
</td>
<td><span class="tag tag-new">新增</span></td>
</tr>
<tr>
<td class="dim-label">是否审批</td>
<td>走 exec_review + 合并成功自动收口原任务</td>
<td class="dim-same">保持;可选纳入②的自动放行条件</td>
<td><span class="tag tag-keep">不变</span></td>
</tr>
</tbody>
</table>
<h4>实现涉及文件</h4>
<div class="cat-grid" style="margin-top:8px">
<div class="cat-card">
<div class="label">protocol.ts</div>
<div class="value new">runKind 加 'conflict';新增 conflict-related OutboxPayload 类型</div>
</div>
<div class="cat-card">
<div class="label">pipeline.ts</div>
<div class="value new">新增 runConflictPipeline 分支:git merge 触发冲突态 → CC 解 → commit → 双复审</div>
</div>
<div class="cat-card">
<div class="label">runner.ts · buildConflictPrompt</div>
<div class="value new">专用解冲突 prompt 模板(冲突文件列表/取舍原则/禁丢任一方改动/commit规范)</div>
</div>
<div class="cat-card">
<div class="label">models.ts</div>
<div class="value new">ModelRole 加 'conflict'pickModel for conflict 直返 fable-5</div>
</div>
<div class="cat-card">
<div class="label">orchestrator.ts</div>
<div class="value new">conflict 补救任务优先抢占(claimOne 按 runKind=conflict 优先)</div>
</div>
<div class="cat-card">
<div class="label">store.ts · ensureMergeRemediationTask</div>
<div class="value changed">complexity 不再固定 easyoperations 改用 conflict runKind 标记,修正 worktree 文案</div>
</div>
</div>
</section>
<hr class="divider">
<!-- ============================================================ RULES -->
<section id="rules">
<h2>④ 任务通用规则(13条,全部采纳)</h2>
<p style="color:var(--text2);margin-bottom:16px">跨三类的横切规则;蓝色=本轮新引入;灰色=已有不变量明文固化</p>
<ul class="rule-list">
<li class="rule-item">
<div class="rule-num">1</div>
<div class="rule-body">
<span class="tag tag-new">新增</span>
<strong>执行期锁</strong>:任务有在途 runplanner/executor/reviewer/conflict)即锁只读——禁改 title/spec/complexity/deps 等任何字段,禁再调度;run 结束(finishRun/failAttempt/reap)解锁。
<div class="rule-impl">实现:store mutation 入口 + API 层加"在途即拒"校验;orchestrator.claimable 已天然排除,保持</div>
</div>
</li>
<li class="rule-item">
<div class="rule-num">2</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>worktree 隔离</strong>:写类 runexecutor/conflict)在独立 worktree 内,禁碰 worktree 外文件;planner/reviewer 只读,不建 worktree。
</div>
</li>
<li class="rule-item">
<div class="rule-num">3</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>不 push / 不部署</strong>:任何 run 都不得 <code>git push</code> / 对外发布 / 部署;解冲突的 merge 是受控本地合并,不 push。
</div>
</li>
<li class="rule-item">
<div class="rule-num">4</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>commit 含 task ID</strong>:所有产出 commit message 必带任务 ID<code>ensureCommitted</code> 兜底。
</div>
</li>
<li class="rule-item">
<div class="rule-num">5</div>
<div class="rule-body">
<span class="tag tag-changed">改进</span>
<strong>模型回退链</strong>:模型不可用 → <code>fable-5 → opus-4-8 → sonnet-4-6</code> 回退(fable 置链首),单 run 内只重试一次。
<div class="rule-impl">实现:<code>models.ts</code> <code>MODEL_FALLBACK_CHAIN</code> 改为 <code>['claude-fable-5','claude-opus-4-8','claude-sonnet-4-6']</code></div>
</div>
</li>
<li class="rule-item">
<div class="rule-num">6</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>重试退避 + 上限升级</strong>:失败按退避(backoff,间隔递增)自动重试;超 <code>max_retries</code>(项目配,默认2)→ 转 <code>needs_attention</code>(需人工介入)。
<div class="rule-impl">needs_attention = 任务卡住不再自动重试,等人改/requeue/取消。触发:①失败超重试上限 ②合并冲突 ③歧义</div>
</div>
</li>
<li class="rule-item">
<div class="rule-num">7</div>
<div class="rule-body">
<span class="tag tag-new">新增</span>
<strong>自动放行默认关</strong>:所有"跳过人审自动放行"(plan/exec)默认关闭,须项目级开关 + <code>auto-approved</code> autonomy 才生效。
</div>
</li>
<li class="rule-item">
<div class="rule-num">8</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>审批 reject 必带意见</strong>plan/spec/exec 的 reject 必须带 reason,按状态机回流。
<div class="rule-impl">plan_review→analyzing · spec_review→speccing · exec_review→ready</div>
</div>
</li>
<li class="rule-item">
<div class="rule-num">9</div>
<div class="rule-body">
<span class="tag tag-changed">强化</span>
<strong>复审独立性</strong>:复审只读、与执行分离、用最强模型(fable-5);复审不被 project.model 降档;任一 verdict=reject 变硬闸(退回重执行,不进 exec_review)。
</div>
</li>
<li class="rule-item">
<div class="rule-num">10</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>daemon 唯一 DB 写者 / worker 不碰 DB</strong>:进程模型铁律;状态变更只经 <code>transition()</code> 守卫(<code>canTransition</code>)。
</div>
</li>
<li class="rule-item">
<div class="rule-num">11</div>
<div class="rule-body">
<span class="tag tag-new">新增</span>
<strong>统一输出锚点</strong>:每类 run 固定输出模板——planner=表格+JSON · executor=自述 · reviewer=模板+VERDICT · conflict=解冲突自述,便于机器解析 + 人审。
</div>
</li>
<li class="rule-item">
<div class="rule-num">12</div>
<div class="rule-body">
<span class="tag tag-keep">固化</span>
<strong>超时分层</strong>planner/executor 30min · verify 10min · 复审15min(并行) · conflict 按强档给足;均可项目级配置。
</div>
</li>
<li class="rule-item">
<div class="rule-num">13</div>
<div class="rule-body">
<span class="tag tag-approved">✅ 已实现</span>
<strong>执行前同步 main + 分歧重评估</strong>:任务正式执行前,先把 defaultBranch 最新代码 merge 进 worktree;若改动过大 / 耦合过深 / 存在逻辑冲突,则触发方案重评估(转 needs_attention 待人工)而非盲目继续。
<div class="rule-impl">实现:sync main 前先跑 <code>reevalScopeGate</code>——以 <code>git diff HEAD...origin/main</code> 取 main 自分支点以来改动的文件,与任务声明范围 <code>scopeFiles</code> 求交集;非空即 emit <code>needs-reeval</code> → daemon <code>markReeval</code> 直接转 <code>needs_attention</code>(不重试、不计失败次数、run 收尾 cancelled)。与③协同:执行前同步冲突=早发现;执行后合并冲突=③兜底</div>
</div>
</li>
</ul>
</section>
<hr class="divider">
<!-- ============================================================ FSM -->
<section id="fsm">
<h2>⑤ 任务状态机流转图</h2>
<p style="color:var(--text2);margin-bottom:16px"><code>src/model/status.ts</code> TRANSITIONS 真实表绘制;paused/cancelled 通用终态图中略去</p>
<h3>主干流转(按复杂度)</h3>
<div style="margin-bottom:16px">
<h4>Hard 任务</h4>
<div class="flow-row">
<span class="st">init</span><span class="arrow"></span>
<span class="st">analyzing</span><span class="arrow">→(拆解完成)</span>
<span class="st gate">plan_review ⊙</span><span class="arrow">→(accept)</span>
<span class="st">decomposed</span><span class="arrow">→(子全done)</span>
<span class="st terminal">done</span>
</div>
<div class="flow-row" style="margin-left:140px">
<span class="arrow">reject(+意见)↙</span>
<span class="st">analyzing</span>
</div>
</div>
<div style="margin-bottom:16px">
<h4>Medium 任务</h4>
<div class="flow-row">
<span class="st">init</span><span class="arrow"></span>
<span class="st">speccing</span><span class="arrow">→(方案完成)</span>
<span class="st gate">spec_review ⊙</span><span class="arrow">→(accept)</span>
<span class="st">ready</span>
</div>
</div>
<div style="margin-bottom:20px">
<h4>Easy 任务</h4>
<div class="flow-row">
<span class="st">init</span><span class="arrow"></span>
<span class="st">ready</span>
</div>
</div>
<h3>执行主链(所有复杂度共用,从 ready 开始)</h3>
<div class="flow-row">
<span class="st">ready</span><span class="arrow">→(调度)</span>
<span class="st">queued</span><span class="arrow">→(worker起跑)</span>
<span class="st">executing</span>
<span class="arrow">→(完成)</span>
<span class="st gate">exec_review ⊙</span>
<span class="arrow">→(accept+合并)</span>
<span class="st terminal">done</span>
</div>
<div class="flow-row" style="margin-top:8px;margin-left:290px">
<span class="arrow">reject(+意见)↓</span>
<span class="st">ready</span>
<span class="arrow">(带复审意见重做)</span>
</div>
<h3 style="margin-top:20px">失败 / 重评估链</h3>
<div class="flow-row">
<span class="st">executing</span><span class="arrow"></span>
<span class="st err">failed</span>
<span class="arrow">→(退避重试)</span>
<span class="st">queued</span>
</div>
<div class="flow-row">
<span class="st err">failed</span><span class="arrow">→(超限)</span>
<span class="st attn">needs_attention</span>
<span class="arrow">→(人工requeue)</span>
<span class="st">ready / queued / analyzing / speccing</span>
</div>
<h3>合并冲突链(③)</h3>
<div class="flow-row">
<span class="st gate">exec_review</span>
<span class="arrow">→(approve but 冲突)</span>
<span class="st attn">conflict run 抢占</span>
<span class="arrow">→(解决+复审)</span>
<span class="st gate">exec_review</span>
<span class="arrow">→(approve)</span>
<span class="st terminal">done</span>
<span class="arrow">→自动收口原任务</span>
</div>
<h3 style="margin-top:20px">完整 Mermaid 图</h3>
<div class="mermaid-wrap">
<div class="mermaid">
stateDiagram-v2
direction LR
[*] --> init
init --> analyzing : hard
init --> speccing : medium
init --> ready : easy
analyzing --> plan_review : 拆解完成
analyzing --> needs_attention : 失败超限
plan_review --> decomposed : accept
plan_review --> analyzing : reject+意见
decomposed --> done : 子任务全done
decomposed --> analyzing : 重拆
speccing --> spec_review : 方案完成
speccing --> needs_attention : 失败超限
spec_review --> ready : accept
spec_review --> speccing : reject+意见
ready --> blocked : 依赖未满足
blocked --> ready : 依赖满足
ready --> queued : 编排器领取
queued --> executing : worker启动
queued --> ready : 退回
executing --> exec_review : 执行完成
executing --> failed : 执行失败
failed --> queued : 退避重试
failed --> needs_attention : 超重试上限
exec_review --> done : accept合并
exec_review --> ready : reject返工
needs_attention --> ready
needs_attention --> queued
needs_attention --> analyzing
needs_attention --> speccing
done --> [*]
</div>
</div>
<div style="margin-top:12px;color:var(--text2);font-size:12px">
⊙ = 人审闸(plan_review / spec_review / exec_review&nbsp;·&nbsp;
paused ↔ 所有活跃态互通(图中略)&nbsp;·&nbsp;
cancelled = 所有活跃态均可取消(图中略)
</div>
</section>
<hr class="divider">
<!-- ============================================================ DB -->
<section id="db">
<h2>⑥ 数据库结构(单一 SQLite · <code>~/.maestro/</code></h2>
<p style="color:var(--text2);margin-bottom:16px">WAL 模式,外键开。三类任务是 tasks 表上按 complexity+status+run.kind 区分的行为,不是独立表。schema 见 <code>src/store/schema.sql</code></p>
<div class="db-grid">
<div class="db-table-card">
<div class="db-header">
<span class="db-name">projects</span>
<span class="db-desc">项目配置</span>
</div>
<div class="db-cols">
<div class="db-col"><span class="col-name">id</span><span class="col-type">TEXT PK</span><span class="col-note">唯一标识</span></div>
<div class="db-col"><span class="col-name">autonomy</span><span class="col-type">TEXT</span><span class="col-note">manual | auto-easy | auto-approved</span></div>
<div class="db-col"><span class="col-name">concurrency</span><span class="col-type">INTEGER</span><span class="col-note">并发 run 上限(默认1</span></div>
<div class="db-col"><span class="col-name">max_retries</span><span class="col-type">INTEGER</span><span class="col-note">失败最大重试次数(默认2</span></div>
<div class="db-col"><span class="col-name">timeout_ms</span><span class="col-type">INTEGER</span><span class="col-note">单次执行超时毫秒(默认30min</span></div>
<div class="db-col"><span class="col-name">verify_cmd</span><span class="col-type">TEXT?</span><span class="col-note">验证命令(未配=视为通过)</span></div>
<div class="db-col"><span class="col-name">model</span><span class="col-type">TEXT?</span><span class="col-note">项目级模型覆盖(最优先)</span></div>
<div class="db-col highlight"><span class="col-name">checks</span><span class="col-type">TEXT?</span><span class="col-note">🆕 分项检查配置 JSONlint/typecheck/build</span></div>
<div class="db-col highlight"><span class="col-name">auto_approve_plan</span><span class="col-type">INTEGER</span><span class="col-note">🆕 全easy子任务自动放行(0=关)</span></div>
<div class="db-col highlight"><span class="col-name">auto_approve_exec</span><span class="col-type">INTEGER</span><span class="col-note">🆕 双approve自动合并(0=关)</span></div>
</div>
</div>
<div class="db-table-card">
<div class="db-header">
<span class="db-name">tasks</span>
<span class="db-desc">任务主表(三类共用)</span>
</div>
<div class="db-cols">
<div class="db-col"><span class="col-name">id</span><span class="col-type">TEXT PK</span><span class="col-note"></span></div>
<div class="db-col"><span class="col-name">parent_id</span><span class="col-type">TEXT?</span><span class="col-note">Hard 拆解的父任务</span></div>
<div class="db-col"><span class="col-name">depth</span><span class="col-type">INTEGER</span><span class="col-note">1..4cat1 直接读此值注入 decompose prompt</span></div>
<div class="db-col"><span class="col-name">complexity</span><span class="col-type">TEXT</span><span class="col-note">hard | medium | easy(决定 run 类型和模型档)</span></div>
<div class="db-col"><span class="col-name">status</span><span class="col-type">TEXT</span><span class="col-note">见状态机(16种)</span></div>
<div class="db-col"><span class="col-name">priority</span><span class="col-type">INTEGER</span><span class="col-note">P0=最高 / P1=中 / P2=最低;cat1 planner 可直接输出</span></div>
<div class="db-col"><span class="col-name">deps</span><span class="col-type">TEXT</span><span class="col-note">JSON idscat1 planner 可直接产出,序号→id 二次映射后写入</span></div>
<div class="db-col"><span class="col-name">plan</span><span class="col-type">TEXT?</span><span class="col-note">Hard:分析+拆解(decompose 写入)</span></div>
<div class="db-col"><span class="col-name">spec</span><span class="col-type">TEXT?</span><span class="col-note">Medium:改动方案(spec 写入)</span></div>
<div class="db-col"><span class="col-name">operations</span><span class="col-type">TEXT?</span><span class="col-note">Easy:操作说明</span></div>
<div class="db-col"><span class="col-name">result</span><span class="col-type">TEXT?</span><span class="col-note">JSON TaskResultbranch/worktree/diffSummary/verdict/securityVerdict/mergeTaskId…)</span></div>
<div class="db-col"><span class="col-name">retry_baseline</span><span class="col-type">INTEGER</span><span class="col-note">上次手动重投时的失败数基线(重置重试计数用)</span></div>
<div class="db-col"><span class="col-name">next_eligible_at</span><span class="col-type">TEXT?</span><span class="col-note">退避截止时间;早于此不被调度(null=即刻可领)</span></div>
</div>
</div>
<div class="db-table-card">
<div class="db-header">
<span class="db-name">runs</span>
<span class="db-desc">每次 agent 运行记录</span>
</div>
<div class="db-cols">
<div class="db-col"><span class="col-name">kind</span><span class="col-type">TEXT</span><span class="col-note">planner | executor | reviewer | security <strong style="color:var(--orange)">+ conflict(本轮新增)</strong></span></div>
<div class="db-col"><span class="col-name">status</span><span class="col-type">TEXT</span><span class="col-note">started | succeeded | failed | cancelled</span></div>
<div class="db-col"><span class="col-name">worktree</span><span class="col-type">TEXT?</span><span class="col-note">executor/conflict 有;planner/reviewer 无</span></div>
<div class="db-col"><span class="col-name">worker_pid</span><span class="col-type">INTEGER?</span><span class="col-note">daemon 判活用</span></div>
<div class="db-col"><span class="col-name">last_seq</span><span class="col-type">INTEGER</span><span class="col-note">已 ingest 的 outbox 最大 seq(幂等游标)</span></div>
<div class="db-col"><span class="col-name">transcript_ref</span><span class="col-type">TEXT?</span><span class="col-note">转录 .jsonl 路径</span></div>
</div>
</div>
<div class="db-table-card">
<div class="db-header">
<span class="db-name">approvals</span>
<span class="db-desc">审批闸记录(不可变日志)</span>
</div>
<div class="db-cols">
<div class="db-col"><span class="col-name">gate</span><span class="col-type">TEXT</span><span class="col-note">plan | spec | exec</span></div>
<div class="db-col"><span class="col-name">action</span><span class="col-type">TEXT</span><span class="col-note">accept | reject</span></div>
<div class="db-col"><span class="col-name">reason</span><span class="col-type">TEXT?</span><span class="col-note">reject 时必填</span></div>
</div>
</div>
<div class="db-table-card">
<div class="db-header">
<span class="db-name">events</span>
<span class="db-desc">追加型事件日志(审计 + 看板实时推送源)</span>
</div>
<div class="db-cols">
<div class="db-col"><span class="col-name">type</span><span class="col-type">TEXT</span><span class="col-note">task.updated · merge.failed · merge.remediated · …</span></div>
<div class="db-col"><span class="col-name">payload</span><span class="col-type">TEXT</span><span class="col-note">JSON;包含冲突文件列表、verdict 等结构化数据</span></div>
</div>
</div>
</div>
<div style="margin-top:16px;color:var(--text2);font-size:12px">
🆕 标注的列是本轮优化新增字段(projects 表 schema 需 migration);runs.kind 无 CHECK 约束,加 'conflict' 兼容老数据。
</div>
</section>
<hr class="divider">
<section style="margin-bottom:40px">
<h2>实现顺序</h2>
<p style="color:var(--text2);margin-bottom:16px">每类先 typecheck + build + test 验证,通过后再进下一类</p>
<div class="cat-grid">
<div class="cat-card">
<div class="label">第一批(① 任务拆解类)</div>
<div class="value">models.ts 档位分化 → runner.tsgit工具+maxTurns+prompt改) → pipeline.tsparseDecompose扩展) → ingest.tspriority/deps落库+autoApprovePlan → store.ts+api(执行期锁)</div>
</div>
<div class="cat-card">
<div class="label">第二批(② 执行类)</div>
<div class="value">pipeline.tssync main+并行复审+分项检查+diff闸) → models.ts reviewer改fable → ingest.tsreject硬闸+自动合并条件) → protocol.ts(新信号类型)</div>
</div>
<div class="cat-card">
<div class="label">第三批(③ 解冲突类)</div>
<div class="value">protocol.ts runKind+conflict → pipeline.ts conflict分支 → runner.ts buildConflictPrompt → models.ts conflict角色 → orchestrator.ts 优先抢占</div>
</div>
<div class="cat-card">
<div class="label">第四批(DB schema migration</div>
<div class="value">projects 表加 checks/auto_approve_plan/auto_approve_exec 列;schema.sql + store.ts 读写;版本迁移脚本</div>
</div>
</div>
</section>
</main>
<script>
mermaid.initialize({
startOnLoad: true,
theme: 'dark',
themeVariables: {
background: '#1a1d27',
primaryColor: '#242736',
primaryTextColor: '#e2e4ef',
primaryBorderColor: '#2e3148',
lineColor: '#6c8aff',
secondaryColor: '#1a1d27',
tertiaryColor: '#242736',
}
});
</script>
</body>
</html>