Files
maestro/docs/architecture.html
T
wangjia 1fcd811c12 docs: maestro 后端重构 Phase1 设计文档(schedule_status × work_type)
8 章设计文档 HTML(架构决策/状态设计/DB Schema/记忆注入/Agent 规格/
运维护栏/安全沙箱/前端 API 契约),全图深色内联 SVG,附 docs/index.html 索引。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 13:52:53 +08:00

441 lines
23 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" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MAESTRO · 架构设计</title>
<style>
:root {
--bg: #0a0d0b;
--bg-deep: #070908;
--panel: #111610;
--panel-2: #161c13;
--line: #1e2a1c;
--ink: #c8d4c0;
--muted: #7a9070;
--faint: #445040;
--green: #4ade80;
--green-dim: rgba(74,222,128,.12);
--violet: #a78bfa;
--violet-dim: rgba(167,139,250,.1);
--amber: #fbbf24;
--amber-dim: rgba(251,191,36,.1);
--red: #f87171;
--red-dim: rgba(248,113,113,.1);
--cyan: #22d3ee;
--cyan-dim: rgba(34,211,238,.1);
--mono: 'IBM Plex Mono', 'Noto Sans SC', monospace;
--radius-sm: 4px;
--radius-md: 6px;
}
[data-theme="light"] {
--bg: #f4f6f2; --bg-deep: #eaede7; --panel: #ffffff; --panel-2: #f0f2ee;
--line: #d0d8cc; --ink: #1a2418; --muted: #4a6045; --faint: #8a9e86;
--green: #16a34a; --green-dim: rgba(22,163,74,.1);
--violet: #7c3aed; --violet-dim: rgba(124,58,237,.1);
--amber: #d97706; --amber-dim: rgba(217,119,6,.1);
--red: #dc2626; --red-dim: rgba(220,38,38,.1);
--cyan: #0891b2; --cyan-dim: rgba(8,145,178,.1);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
background: var(--bg); color: var(--ink);
font-family: var(--mono); font-size: 13px; line-height: 1.6;
padding: 32px;
}
body::before {
content: ''; position: fixed; inset: 0; z-index: 0; pointer-events: none;
background:
repeating-linear-gradient(0deg, rgba(0,0,0,.14) 0 1px, transparent 1px 3px),
radial-gradient(ellipse at 50% 40%, transparent 55%, rgba(0,0,0,.45));
opacity: .45;
}
[data-theme="light"] body::before { opacity: .07; }
.page { position: relative; z-index: 1; max-width: 1200px; margin: 0 auto; }
.header {
display: flex; align-items: baseline; gap: 16px;
border-bottom: 1px solid var(--line); padding-bottom: 20px; margin-bottom: 32px;
}
.logo { font-size: 18px; font-weight: 700; letter-spacing: .25em; color: var(--green); text-shadow: 0 0 16px var(--green); }
.logo span { animation: blink 1.1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
.subtitle { color: var(--muted); font-size: 11px; letter-spacing: .2em; }
.theme-btn {
margin-left: auto; background: var(--panel); border: 1px solid var(--line);
color: var(--muted); font-family: var(--mono); font-size: 11px;
padding: 4px 10px; border-radius: var(--radius-sm); cursor: pointer; letter-spacing: .1em;
}
.theme-btn:hover { color: var(--ink); border-color: var(--muted); }
.sec-head {
display: flex; align-items: center; gap: 8px;
font-size: 10px; font-weight: 600; letter-spacing: .28em;
color: var(--muted); text-transform: uppercase;
margin-bottom: 16px; margin-top: 40px;
}
.sec-mark { width: 3px; height: 14px; border-radius: 2px; }
/* Architecture grid */
.arch { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 12px; }
.layer {
border: 1px solid var(--line); border-radius: var(--radius-md);
background: var(--panel); padding: 16px;
}
.layer-title {
font-size: 10px; font-weight: 600; letter-spacing: .18em;
text-transform: uppercase; margin-bottom: 12px;
display: flex; align-items: center; gap: 8px;
}
.dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.layer-frontend { border-color: rgba(34,211,238,.4); background: linear-gradient(135deg, var(--panel), rgba(34,211,238,.03)); }
.layer-frontend .layer-title { color: var(--cyan); }
.layer-api { border-color: rgba(167,139,250,.4); background: linear-gradient(135deg, var(--panel), rgba(167,139,250,.03)); }
.layer-api .layer-title { color: var(--violet); }
.layer-db { border-color: rgba(251,191,36,.4); background: linear-gradient(135deg, var(--panel), rgba(251,191,36,.03)); }
.layer-db .layer-title { color: var(--amber); }
.layer-daemon { border-color: rgba(74,222,128,.4); background: linear-gradient(135deg, var(--panel), rgba(74,222,128,.03)); }
.layer-daemon .layer-title { color: var(--green); }
.layer-worker { border-color: rgba(248,113,113,.4); background: linear-gradient(135deg, var(--panel), rgba(248,113,113,.03)); }
.layer-worker .layer-title { color: var(--red); }
.modules { display: flex; flex-wrap: wrap; gap: 6px; }
.mod {
font-size: 11px; padding: 4px 8px; border-radius: var(--radius-sm);
border: 1px solid var(--line); background: var(--panel-2); color: var(--muted); line-height: 1.5;
}
.mod b { color: var(--ink); font-weight: 600; display: block; }
.mod small { font-size: 10px; color: var(--faint); }
.mod-c { border-color: rgba(34,211,238,.35); background: var(--cyan-dim); color: var(--cyan); }
.mod-v { border-color: rgba(167,139,250,.35); background: var(--violet-dim); color: var(--violet); }
.mod-a { border-color: rgba(251,191,36,.35); background: var(--amber-dim); color: var(--amber); }
.mod-g { border-color: rgba(74,222,128,.35); background: var(--green-dim); color: var(--green); }
.mod-r { border-color: rgba(248,113,113,.35); background: var(--red-dim); color: var(--red); }
.connector {
grid-column: span 3; display: flex; justify-content: space-around;
padding: 6px 0; color: var(--faint); font-size: 10px; letter-spacing: .12em;
align-items: center;
}
.conn-item { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.conn-line { width: 1px; height: 16px; background: var(--line); }
/* Flow */
.flow {
display: grid; grid-template-columns: repeat(5, 1fr);
border: 1px solid var(--line); border-radius: var(--radius-md); overflow: hidden;
margin-bottom: 40px;
}
.flow-step {
padding: 14px 14px; border-right: 1px solid var(--line); position: relative;
}
.flow-step:last-child { border-right: none; }
.flow-num { font-size: 10px; color: var(--faint); letter-spacing: .15em; margin-bottom: 4px; }
.flow-title { font-size: 12px; font-weight: 600; color: var(--ink); margin-bottom: 4px; }
.flow-desc { font-size: 11px; color: var(--muted); line-height: 1.5; }
.flow-arr {
position: absolute; right: -9px; top: 50%; transform: translateY(-50%);
color: var(--faint); font-size: 16px; z-index: 2; background: var(--panel); padding: 2px 1px;
}
/* Detail grid */
.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 40px; }
.detail-card {
border: 1px solid var(--line); border-radius: var(--radius-md);
background: var(--panel); padding: 16px;
}
.detail-card h3 { font-size: 11px; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; margin-bottom: 10px; }
.detail-card ul { list-style: none; display: flex; flex-direction: column; gap: 6px; }
.detail-card li { font-size: 11px; color: var(--muted); display: flex; gap: 8px; align-items: flex-start; }
.detail-card li::before { content: '→'; color: var(--faint); flex-shrink: 0; margin-top: 1px; }
.detail-card li b { color: var(--ink); }
.note { font-size: 10px; color: var(--faint); display: block; margin-top: 1px; }
/* File tree */
.file-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 40px; }
.file-tree {
background: var(--bg-deep); border: 1px solid var(--line);
border-radius: var(--radius-md); padding: 20px;
font-size: 12px; line-height: 2; margin-bottom: 40px;
}
.ft-dir { color: var(--cyan); font-weight: 600; }
.ft-file { color: var(--muted); }
.ft-new { color: var(--green); }
.ft-del { color: var(--red); text-decoration: line-through; opacity: .55; }
.ft-c { color: var(--faint); font-size: 10px; }
.i1 { padding-left: 16px; }
.i2 { padding-left: 32px; }
.i3 { padding-left: 48px; }
</style>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="page">
<div class="header">
<div class="logo">MAESTRO<span></span></div>
<div class="subtitle">架构设计 · ARCHITECTURE DESIGN v2.0 DRAFT</div>
<button class="theme-btn" onclick="document.documentElement.dataset.theme=document.documentElement.dataset.theme==='dark'?'light':'dark'">⊙ 切换主题</button>
</div>
<!-- 全景架构 -->
<div class="sec-head"><div class="sec-mark" style="background:var(--green)"></div>全景架构 · SYSTEM OVERVIEW</div>
<div class="arch">
<!-- Frontend -->
<div class="layer layer-frontend span-3">
<div class="layer-title"><div class="dot" style="background:var(--cyan);box-shadow:0 0 8px var(--cyan)"></div>前端层 · FRONTEND — React 18 + TypeScript + Vite</div>
<div class="modules">
<div class="mod mod-c"><b>Design System 组件</b><small>从 claude.ai/design 迁移 · TSX</small></div>
<div class="mod mod-c"><b>三栏看板</b><small>Sidebar · Main · EventPanel · 拖拽宽度</small></div>
<div class="mod mod-c"><b>Mobile Tab</b><small>390px · 底部四 Tab 导航</small></div>
<div class="mod mod-c"><b>Zustand</b><small>客户端状态管理</small></div>
<div class="mod mod-c"><b>i18n · 5 语言</b><small>zh / en / es / ja / fr</small></div>
<div class="mod mod-c"><b>WebSocket Client</b><small>实时看板刷新</small></div>
<div class="mod"><b>Vite Dev Server</b><small>开发时 API 代理 · HMR</small></div>
<div class="mod"><b>dist/web/</b><small>构建产物 → Fastify 托管</small></div>
</div>
</div>
<div class="connector">
<div class="conn-item"><div class="conn-line"></div><span>REST · /api/*</span><div class="conn-line"></div></div>
<div class="conn-item"><div class="conn-line"></div><span>WebSocket · /ws</span><div class="conn-line"></div></div>
<div class="conn-item"><div class="conn-line"></div><span style="opacity:.4">Auth Token(预留)</span><div class="conn-line"></div></div>
</div>
<!-- API -->
<div class="layer layer-api span-2">
<div class="layer-title"><div class="dot" style="background:var(--violet);box-shadow:0 0 8px var(--violet)"></div>API 层 · Fastify(路由拆分 + Schema 校验)</div>
<div class="modules">
<div class="mod mod-v"><b>routes/projects</b><small>CRUD · logo · sync · reorder</small></div>
<div class="mod mod-v"><b>routes/tasks</b><small>CRUD · decide · requeue · transition</small></div>
<div class="mod mod-v"><b>routes/runs</b><small>transcript · active runs</small></div>
<div class="mod mod-v"><b>routes/approvals</b><small>pendingApprovals</small></div>
<div class="mod mod-v"><b>routes/metrics</b><small>健康度 · 成本聚合</small></div>
<div class="mod mod-v"><b>ws.ts</b><small>Store 事件 → 广播所有客户端</small></div>
<div class="mod"><b>middleware/auth.ts</b><small>no-op · 预留 JWT 插槽</small></div>
<div class="mod"><b>schemas/</b><small>Fastify JSON Schema 请求校验</small></div>
</div>
</div>
<!-- DB -->
<div class="layer layer-db">
<div class="layer-title"><div class="dot" style="background:var(--amber);box-shadow:0 0 8px var(--amber)"></div>数据层 · DB ABSTRACTION</div>
<div class="modules">
<div class="mod mod-a"><b>DBAdapter 接口</b><small>统一抽象</small></div>
<div class="mod mod-a"><b>SqliteAdapter</b><small>当前实现</small></div>
<div class="mod" style="border-style:dashed;opacity:.55"><b>PostgresAdapter</b><small>未来多租户</small></div>
<div class="mod mod-a"><b>ProjectRepo</b></div>
<div class="mod mod-a"><b>TaskRepo</b></div>
<div class="mod mod-a"><b>RunRepo</b></div>
<div class="mod mod-a"><b>ApprovalRepo</b></div>
<div class="mod mod-a"><b>EventRepo</b></div>
<div class="mod mod-a"><b>MetricsRepo</b></div>
</div>
</div>
<div class="connector">
<div class="conn-item"><div class="conn-line"></div><span>读写 DB</span><div class="conn-line"></div></div>
<div class="conn-item"><div class="conn-line"></div><span>事件订阅 → WS 推送</span><div class="conn-line"></div></div>
<div class="conn-item"><div class="conn-line"></div><span>调度查询</span><div class="conn-line"></div></div>
</div>
<!-- Daemon -->
<div class="layer layer-daemon span-2">
<div class="layer-title"><div class="dot" style="background:var(--green);box-shadow:0 0 8px var(--green)"></div>Daemon 层(拆分 4 职责)</div>
<div class="modules">
<div class="mod mod-g"><b>Orchestrator</b><small>协调者 · tick 主循环</small></div>
<div class="mod mod-g"><b>Scheduler</b><small>纯调度逻辑 · score → 选任务</small></div>
<div class="mod mod-g"><b>WorkerManager</b><small>spawn / reap / pid 管理</small></div>
<div class="mod mod-g"><b>Ingestor</b><small>outbox.ndjson → DB · 幂等摄取</small></div>
<div class="mod mod-g"><b>MergeCoordinator</b><small>merge-resolve 池 + settle</small></div>
<div class="mod"><b>config.ts</b></div>
<div class="mod"><b>notify.ts</b></div>
</div>
</div>
<!-- Worker -->
<div class="layer layer-worker">
<div class="layer-title"><div class="dot" style="background:var(--red);box-shadow:0 0 8px var(--red)"></div>Worker 进程(按类型拆分)</div>
<div class="modules">
<div class="mod mod-r"><b>pipelines/executor</b></div>
<div class="mod mod-r"><b>pipelines/planner</b></div>
<div class="mod mod-r"><b>pipelines/conflict</b></div>
<div class="mod mod-r"><b>pipelines/merge-resolve</b></div>
<div class="mod mod-r"><b>runners/executor</b><small>prompt + runTask</small></div>
<div class="mod mod-r"><b>runners/planner</b><small>prompt + runPlanner</small></div>
<div class="mod mod-r"><b>runners/conflict</b></div>
<div class="mod mod-r"><b>runners/merge-resolve</b></div>
<div class="mod" style="border-style:dashed"><b>文件协议(保留不变)</b><small>job.json → outbox.ndjson → heartbeat</small></div>
</div>
</div>
</div><!-- /arch -->
<!-- 执行数据流 -->
<div class="sec-head"><div class="sec-mark" style="background:var(--cyan)"></div>任务执行数据流 · EXECUTION FLOW</div>
<div class="flow">
<div class="flow-step" style="background:var(--violet-dim)">
<div class="flow-num">01 · 触发</div>
<div class="flow-title">用户 / API</div>
<div class="flow-desc">POST /api/.../tasks<br>创建任务 → init 态</div>
<div class="flow-arr"></div>
</div>
<div class="flow-step" style="background:var(--green-dim)">
<div class="flow-num">02 · 调度</div>
<div class="flow-title">Scheduler</div>
<div class="flow-desc">score 排序 → claimable<br>ready → queued → executing</div>
<div class="flow-arr"></div>
</div>
<div class="flow-step" style="background:var(--green-dim)">
<div class="flow-num">03 · 起进程</div>
<div class="flow-title">WorkerManager</div>
<div class="flow-desc">spawn worker 进程<br>写 job.json · 记 pid</div>
<div class="flow-arr"></div>
</div>
<div class="flow-step" style="background:var(--red-dim)">
<div class="flow-num">04 · 执行</div>
<div class="flow-title">Worker Pipeline</div>
<div class="flow-desc">CC Agent 执行任务<br>追加 outbox.ndjson</div>
<div class="flow-arr"></div>
</div>
<div class="flow-step" style="background:var(--amber-dim)">
<div class="flow-num">05 · 摄取</div>
<div class="flow-title">Ingestor</div>
<div class="flow-desc">outbox → DB<br>→ WS 推送 → 审核闸</div>
</div>
</div>
<!-- 重构变更 -->
<div class="sec-head"><div class="sec-mark" style="background:var(--amber)"></div>重构变更对照 · WHAT CHANGES</div>
<div class="detail-grid">
<div class="detail-card">
<h3 style="color:var(--red)">✕ 删除</h3>
<ul>
<li><b>web/app.js</b> (2473 行)<span class="note">替换为 React + TypeScript 前端</span></li>
<li><b>web/style.css</b> (1333 行)<span class="note">设计 token 迁移到 frontend/src/tokens/</span></li>
<li><b>web/index.html</b><span class="note">Vite 入口替代</span></li>
</ul>
</div>
<div class="detail-card">
<h3 style="color:var(--green)">✓ 保留不动</h3>
<ul>
<li><b>文件协议</b> — job.json / outbox.ndjson / heartbeat</li>
<li><b>状态机</b> — src/model/status.ts · TRANSITIONS</li>
<li><b>Score 调度算法</b> — src/model/scoring.ts</li>
<li><b>CC 封装</b> — src/executor/cc.ts</li>
<li><b>Schema SQL</b> — src/store/schema.sql</li>
<li><b>MCP server</b> — src/mcp/</li>
<li><b>CLI</b> — src/cli/</li>
</ul>
</div>
<div class="detail-card">
<h3 style="color:var(--amber)">⟳ 拆分重构</h3>
<ul>
<li><b>store.ts</b> (1227行) → <span style="color:var(--amber)">6 Repo + DBAdapter 接口</span></li>
<li><b>orchestrator.ts</b> (426行) → <span style="color:var(--amber)">Scheduler + WorkerManager + Ingestor + MergeCoordinator</span></li>
<li><b>runner.ts</b> (353行) → <span style="color:var(--amber)">runners/ 4 个独立文件</span></li>
<li><b>pipeline.ts</b> (358行) → <span style="color:var(--amber)">pipelines/ 4 个独立文件</span></li>
<li><b>server.ts</b> (401行) → <span style="color:var(--amber)">routes/ 5 个路由模块 + Schema</span></li>
</ul>
</div>
<div class="detail-card">
<h3 style="color:var(--cyan)">✦ 新增</h3>
<ul>
<li><b>frontend/</b> — React + TypeScript + Vite 工程</li>
<li><b>frontend/components/</b> — claude design → TSX 组件库</li>
<li><b>src/store/db.ts</b> — DBAdapter 抽象接口</li>
<li><b>src/store/repos/</b> — 6 个职责单一的 Repository</li>
<li><b>src/api/middleware/auth.ts</b> — Auth 插槽(no-op</li>
<li><b>src/api/schemas/</b> — Fastify JSON Schema 校验</li>
</ul>
</div>
</div>
<!-- 目录结构 -->
<div class="sec-head"><div class="sec-mark" style="background:var(--violet)"></div>目录结构 · FILE STRUCTURE</div>
<div class="file-tree">
<div class="file-grid">
<div>
<div class="ft-dir">frontend/ <span class="ft-new">← 全新</span></div>
<div class="i1 ft-new">src/</div>
<div class="i2 ft-new">main.tsx</div>
<div class="i2 ft-new">App.tsx <span class="ft-c">三栏布局 · 状态根</span></div>
<div class="i2 ft-new">components/ <span class="ft-c">← claude design 迁移</span></div>
<div class="i3 ft-new">core/ <span class="ft-c">Button · StatusChip · ...</span></div>
<div class="i3 ft-new">forms/ <span class="ft-c">Input · Select · ...</span></div>
<div class="i3 ft-new">surfaces/ <span class="ft-c">Panel · GateCard · ...</span></div>
<div class="i2 ft-new">ui/ <span class="ft-c">页面级组件</span></div>
<div class="i3 ft-new">Sidebar.tsx</div>
<div class="i3 ft-new">Topbar.tsx</div>
<div class="i3 ft-new">GateSection.tsx</div>
<div class="i3 ft-new">TaskTree.tsx</div>
<div class="i3 ft-new">EventPanel.tsx</div>
<div class="i3 ft-new">ArchiveSection.tsx</div>
<div class="i2 ft-new">api/ <span class="ft-c">HTTP + WS 客户端</span></div>
<div class="i2 ft-new">store/ <span class="ft-c">Zustand 状态管理</span></div>
<div class="i2 ft-new">i18n/ <span class="ft-c">5 语言字符串</span></div>
<div class="i2 ft-new">tokens/ <span class="ft-c">CSS 自定义属性</span></div>
<div class="i1 ft-new">index.html</div>
<div class="i1 ft-new">vite.config.ts</div>
<div class="i1 ft-new">tsconfig.json</div>
<br>
<div class="ft-del">web/ <span class="ft-c">整体删除</span></div>
<div class="i1 ft-del">app.js <span class="ft-c">2473 行</span></div>
<div class="i1 ft-del">style.css <span class="ft-c">1333 行</span></div>
<div class="i1 ft-del">index.html</div>
</div>
<div>
<div class="ft-dir">src/</div>
<div class="i1 ft-dir">api/</div>
<div class="i2 ft-file">server.ts <span class="ft-c">入口(精简为注册插件)</span></div>
<div class="i2 ft-new">routes/ <span class="ft-c">← 拆分</span></div>
<div class="i3 ft-new">projects.ts · tasks.ts · runs.ts</div>
<div class="i3 ft-new">approvals.ts · metrics.ts</div>
<div class="i2 ft-new">schemas/ <span class="ft-c">JSON Schema 请求校验</span></div>
<div class="i2 ft-new">middleware/auth.ts <span class="ft-c">no-op 插槽</span></div>
<br>
<div class="i1 ft-dir">store/</div>
<div class="i2 ft-new">db.ts <span class="ft-c">DBAdapter 接口</span></div>
<div class="i2 ft-new">sqlite.ts <span class="ft-c">当前实现</span></div>
<div class="i2 ft-new">repos/ <span class="ft-c">← 拆分自 store.ts</span></div>
<div class="i3 ft-new">ProjectRepo · TaskRepo · RunRepo</div>
<div class="i3 ft-new">ApprovalRepo · EventRepo · MetricsRepo</div>
<div class="i2 ft-file">index.ts <span class="ft-c">Store 聚合(外部接口不变)</span></div>
<div class="i2 ft-file">mappers.ts <span class="ft-c">保留</span></div>
<br>
<div class="i1 ft-dir">daemon/</div>
<div class="i2 ft-new">scheduler.ts <span class="ft-c">← 拆分 · 纯调度逻辑</span></div>
<div class="i2 ft-new">worker-manager.ts <span class="ft-c">← 拆分 · 进程管理</span></div>
<div class="i2 ft-file">ingest.ts <span class="ft-c">保留接口不变</span></div>
<div class="i2 ft-new">merge-coordinator.ts <span class="ft-c">← 拆分</span></div>
<div class="i2 ft-new">orchestrator.ts <span class="ft-c">精简为协调者</span></div>
<br>
<div class="i1 ft-dir">executor/</div>
<div class="i2 ft-new">runners/ <span class="ft-c">← 拆分自 runner.ts</span></div>
<div class="i3 ft-new">executor · planner · conflict · merge-resolve</div>
<div class="i2 ft-new">pipelines/ <span class="ft-c">← 拆分自 pipeline.ts</span></div>
<div class="i3 ft-new">executor · planner · conflict · merge-resolve</div>
<div class="i2 ft-file">cc.ts · models.ts · worktree.ts <span class="ft-c">保留</span></div>
</div>
</div>
</div>
<div style="padding:14px 16px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--panel); color:var(--faint); font-size:11px; letter-spacing:.08em;">
MAESTRO ARCHITECTURE · v2.0 DRAFT · 仅设计文档,尚未实现 · <span style="color:var(--green)">保留</span> · <span style="color:var(--amber)">拆分重构</span> · <span style="color:var(--cyan)">新增</span> · <span style="color:var(--red)">删除</span>
</div>
</div>
</body>
</html>