All checks were successful
CI / test (push) Successful in 3m22s
将本轮架构审查 HTML 报告按先例归档至 docs/archive/,并同步 登记 docs/README.md 与 docs/archive/README.md 索引。 本轮五个深化候选已全部落地: - 候选① 智能作业结算统一(ADR-0012) - 候选② 可见性接缝(require_live_eval 单一接缝) - 候选③ storage/repository.py 拆分 - 候选④ 前端 ReadSlot 资源接缝 - 候选⑤ api.ts 拆分为 10 个域模块 刻意不做项(CAS 共享原语、db.py 拆分、app.py 关停顺序归一、 会话/任务状态机转换表)已在 v3 计划与 ADR-0012 中记录。
398 lines
27 KiB
HTML
398 lines
27 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>架构审查 · AgentEvalTool · 2026-08-24</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<script type="module">
|
||
import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
|
||
mermaid.initialize({ startOnLoad: true, theme: "neutral", securityLevel: "loose" });
|
||
</script>
|
||
<style>
|
||
body { font-family: -apple-system, "PingFang SC", "Helvetica Neue", sans-serif; }
|
||
.badge-strong { @apply bg-emerald-100 text-emerald-800 border-emerald-300; }
|
||
.iface { background:#fef3c7; border:2px solid #f59e0b; }
|
||
.impl { background:#0f172a; color:#e2e8f0; }
|
||
.impl-shallow { background:#e2e8f0; color:#334155; border:2px dashed #94a3b8; }
|
||
.seam { border-top:3px dashed #ef4444; }
|
||
.leak { box-shadow: 0 0 0 3px rgba(239,68,68,.35); }
|
||
pre.mermaid { background: transparent; }
|
||
</style>
|
||
</head>
|
||
<body class="bg-slate-100 text-slate-800">
|
||
|
||
<header class="bg-slate-900 text-slate-100 py-10 px-6">
|
||
<div class="max-w-6xl mx-auto">
|
||
<p class="text-emerald-400 font-mono text-sm mb-2">/improve-codebase-architecture · 第三轮</p>
|
||
<h1 class="text-3xl font-bold">架构审查总结 — AgentEvalTool</h1>
|
||
<p class="mt-3 text-slate-300 max-w-3xl">
|
||
2026-08-24 · 前两轮(campaign v1.0、智能评估 v1.2)的候选已全部落地。本轮聚焦落地后新暴露与新残留的摩擦:
|
||
耐久作业结算序列、逻辑删除可见性、存储 monolith、前端读模型采纳面、api.ts 单文件。
|
||
</p>
|
||
<div class="mt-5 flex gap-6 text-sm flex-wrap">
|
||
<div><span class="text-2xl font-bold text-emerald-400">5</span> 深化候选</div>
|
||
<div><span class="text-2xl font-bold text-emerald-400">2</span> 已落地前轮(v1.0 / v1.2)</div>
|
||
<div><span class="text-2xl font-bold text-amber-400">3</span> 处"已删 eval 仍可见"泄漏</div>
|
||
<div><span class="text-2xl font-bold text-amber-400">1180</span> 行 repository.py · 12 个类</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="max-w-6xl mx-auto px-6 py-10 space-y-12">
|
||
|
||
<!-- ============ 全景 ============ -->
|
||
<section>
|
||
<h2 class="text-xl font-bold mb-4">摩擦全景</h2>
|
||
<div class="bg-white rounded-xl shadow p-6">
|
||
<pre class="mermaid">
|
||
flowchart TB
|
||
subgraph BE["后端"]
|
||
IJ["intelligence_jobs.py<br/>两套手写结算序列"] --> AR["AsyncJobRepository<br/>claim/recovery 已深"]
|
||
R1["routers/intelligent_evals.py<br/>直 import ORM 表"] -.泄漏.-> VIS["逻辑删除可见性<br/>三处独立实现"]
|
||
DL["decision_logs._require_eval"] -.泄漏.-> VIS
|
||
REPO["storage/repository.py<br/>1180 行 · 12 类 · 5 域"]
|
||
APP["web/app.py<br/>手工编排 5 个 registry 关停顺序"]
|
||
end
|
||
subgraph FE["前端"]
|
||
READ["src/read 深模块<br/>仅 1 个消费者"] -.绕过.-> TABS["drawer 标签页群<br/>各自手写 fetch/polling"]
|
||
API["api.ts 909 行 · 12 域"]
|
||
end
|
||
classDef warn fill:#fef3c7,stroke:#f59e0b,stroke-width:2px;
|
||
class IJ,VIS,REPO,APP,TABS,API warn;
|
||
</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 候选 1 ============ -->
|
||
<section class="bg-white rounded-xl shadow overflow-hidden">
|
||
<div class="p-6 border-b border-slate-200 flex items-start justify-between gap-4">
|
||
<div>
|
||
<h2 class="text-2xl font-bold">① 耐久智能作业:结算序列收进单一执行器</h2>
|
||
<p class="text-slate-500 mt-1 font-mono text-sm">intelligence_jobs.py · AsyncJobRepository · campaigns 路由 · app.py</p>
|
||
</div>
|
||
<span class="shrink-0 px-3 py-1 rounded-full text-sm font-semibold border bg-emerald-100 text-emerald-800 border-emerald-300">Strong</span>
|
||
</div>
|
||
<div class="p-6 grid md:grid-cols-2 gap-8">
|
||
<div class="space-y-4 text-sm leading-relaxed">
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Files</h3>
|
||
<ul class="list-disc ml-5 space-y-0.5 text-slate-600">
|
||
<li><code>evaluation/intelligence_jobs.py</code> — 两个 executor(53–150、153–263)</li>
|
||
<li><code>storage/repository.py</code> — <code>AsyncJobRepository</code>(782–863)</li>
|
||
<li><code>evaluation/campaign_runner.py:242-247</code>、<code>routers/campaigns.py:128-134</code></li>
|
||
<li><code>evaluation/comparison.py:245-280</code>(死代码 + 投影越界)</li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Problem</h3>
|
||
<p>v2 计划已建出 <code>AsyncJobRepository</code>(claim / recovery / orphan 结算都深),但<strong>编排序列仍按 adapter 手抄</strong>:分析与周期对比两个 executor 各自复制「缺则入队 → claim_queued → upsert(generating) → try/except → failed/completed」。错误截断 <code>str(exc)[:500]</code> 出现两次(123、250);正式线跳过守卫两处(campaign_runner.py:242 与 intelligence_jobs.py:136);分析触发校验在路由与 executor 各一份(周期对比已有共享入口,分析没有);<code>build_comparison_payload</code> 是零调用死代码且与 <code>_build_auto_baseline_payload</code> 逐字节相同。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Solution</h3>
|
||
<p>在执行器层提供单一深接缝 <code>execute(job_kind, work_fn)</code>:入队幂等、认领、generating、失败归一(截断)、成功结算、重复触发幂等观察——全部收进 implementation。分析与周期对比退化为纯领域工作 adapter;顺带删除死代码、把 <code>load_comparison_view</code> 投影移回读模型、分析校验对齐周期对比的共享入口。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Benefits</h3>
|
||
<p><strong>Locality</strong>:结算顺序知识(先认领再 generating、失败先归一再落库)只住一处。<strong>Leverage</strong>:第三个作业类型只需一个 work adapter。测试面从"两套序列各测一遍"收敛为执行器接口一组契约测试 + 每 adapter 的纯领域测试。两个 adapter 已存在——这是真接缝,不是假想接缝。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-3 text-sm">Before / After</h3>
|
||
<div class="grid grid-cols-2 gap-3 text-xs mb-4">
|
||
<div>
|
||
<p class="text-center font-semibold text-red-600 mb-2">Before · 序列手抄 ×2</p>
|
||
<div class="iface rounded p-2 text-center text-slate-800">长接口:调用方须知认领顺序 / 截断 / 幂等</div>
|
||
<div class="impl-shallow rounded p-2 mt-1 text-center">分析 executor:~100 行编排</div>
|
||
<div class="impl-shallow rounded p-2 mt-1 text-center">对比 executor:~110 行同形编排</div>
|
||
</div>
|
||
<div>
|
||
<p class="text-center font-semibold text-emerald-600 mb-2">After · 单一执行器</p>
|
||
<div class="iface rounded p-2 text-center text-slate-800">小接口:execute(kind, work_fn)</div>
|
||
<div class="impl rounded p-4 mt-1 text-center">深 implementation<br>认领·结算·归一·幂等</div>
|
||
<div class="flex gap-1 mt-1">
|
||
<div class="flex-1 bg-slate-200 rounded p-1 text-center">分析 adapter</div>
|
||
<div class="flex-1 bg-slate-200 rounded p-1 text-center">对比 adapter</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<pre class="mermaid">
|
||
sequenceDiagram
|
||
participant C as 触发方(路由/自动)
|
||
participant E as execute() 深模块
|
||
participant W as work adapter
|
||
C->>E: execute(kind, work_fn)
|
||
E->>E: 幂等入队 + claim_queued
|
||
E->>E: upsert(generating)
|
||
E->>W: 领域工作(无 Session 编排)
|
||
alt 成功
|
||
E->>E: upsert(completed + 结果)
|
||
else 异常
|
||
E->>E: 归一 + 截断 + upsert(failed)
|
||
end
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 候选 2 ============ -->
|
||
<section class="bg-white rounded-xl shadow overflow-hidden leak">
|
||
<div class="p-6 border-b border-slate-200 flex items-start justify-between gap-4">
|
||
<div>
|
||
<h2 class="text-2xl font-bold">② 智能评估可见性接缝:逻辑删除语义三处收敛为一</h2>
|
||
<p class="text-slate-500 mt-1 font-mono text-sm">intelligent_eval/repository.py · decision_logs.py · routers/intelligent_evals.py · task_queue.py</p>
|
||
</div>
|
||
<span class="shrink-0 px-3 py-1 rounded-full text-sm font-semibold border bg-emerald-100 text-emerald-800 border-emerald-300">Strong</span>
|
||
</div>
|
||
<div class="p-6 grid md:grid-cols-2 gap-8">
|
||
<div class="space-y-4 text-sm leading-relaxed">
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Files</h3>
|
||
<ul class="list-disc ml-5 space-y-0.5 text-slate-600">
|
||
<li><code>intelligent_eval/repository.py</code> — 可见性谓词重复 6 处(103、117、130、137、147、171)</li>
|
||
<li><code>decision_logs.py:30-33</code> — <code>_require_eval</code> 绕过 repo 直查 ORM</li>
|
||
<li><code>routers/intelligent_evals.py:73-80</code> — 第三份实现,且路由直接 import <code>IntelligentEvalDB</code></li>
|
||
<li><code>task_queue.list_tasks:330</code> — 删除不感知,监控面板泄漏已删评估</li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Problem</h3>
|
||
<p>逻辑删除(2d2c5a2,一周前)落地后,「已删即 404」由<strong>三个独立实现</strong>分别裁决:repo 的 <code>get()</code> 隐藏 + <code>get_including_deleted()</code>、<code>decision_logs._require_eval</code> 直查 ORM、路由 <code>_require_eval_exists</code> 再直查 ORM——路由跨过 repository 接缝直接握表,等于把删除语义焊死在 HTTP 层。附带浅点:配置快照 11 字段序列化 dict 在路由里逐字写了两遍(399–416、430–442);expired 会话的 Markdown 标注住在路由(242–252);<code>count_decisions</code> 全量载入后 <code>len()</code>(112–121)。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Solution</h3>
|
||
<p>可见性收进 repository 单一谓词(内部 <code>_visible()</code>),对外只留 <code>require_live_eval(session, id)</code> 服务接缝——三处调用方改走它,路由删掉 ORM import。快照序列化与 expired 标注下沉到读模型投影;<code>count_decisions</code> 改 <code>func.count</code>。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Benefits</h3>
|
||
<p><strong>Locality</strong>:删除语义改动(如未来回收站、级联策略)只改一处。<strong>正确性</strong>:消除三处分歧风险——当前任务监控已实际泄漏已删评估。测试面:逻辑删除契约从分散的集成断言收敛为 repo 接口一组测试。这是新功能知识<strong>正在扩散</strong>的窗口期,越早收敛成本越低。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-3 text-sm">Before / After</h3>
|
||
<div class="grid grid-cols-2 gap-3 text-xs mb-4">
|
||
<div>
|
||
<p class="text-center font-semibold text-red-600 mb-2">Before · 三处裁决"已删即 404"</p>
|
||
<div class="space-y-1">
|
||
<div class="bg-slate-200 rounded p-1.5 text-center">repo.get() 隐藏删除</div>
|
||
<div class="bg-red-50 border border-red-300 rounded p-1.5 text-center">decision_logs 直查 ORM</div>
|
||
<div class="bg-red-50 border border-red-300 rounded p-1.5 text-center">路由直查 ORM(import 表)</div>
|
||
<div class="bg-amber-50 border border-amber-300 rounded p-1.5 text-center">task_queue 完全不知情</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p class="text-center font-semibold text-emerald-600 mb-2">After · 单一可见性接缝</p>
|
||
<div class="iface rounded p-2 text-center text-slate-800">require_live_eval(id)</div>
|
||
<div class="impl rounded p-3 mt-1 text-center">repository:_visible 谓词 + get/get_including_deleted</div>
|
||
<div class="flex gap-1 mt-1">
|
||
<div class="flex-1 bg-slate-200 rounded p-1 text-center">decision_logs</div>
|
||
<div class="flex-1 bg-slate-200 rounded p-1 text-center">路由</div>
|
||
<div class="flex-1 bg-slate-200 rounded p-1 text-center">task_queue</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<pre class="mermaid">
|
||
flowchart LR
|
||
subgraph NOW["现状:三份语义"]
|
||
A["router 直查<br>IntelligentEvalDB"] --> D["DB"]
|
||
B["decision_logs<br>session.get()"] --> D
|
||
C["repo.get()<br>隐藏 deleted"] --> D
|
||
end
|
||
classDef bad fill:#fee2e2,stroke:#ef4444;
|
||
class A,B bad;
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 候选 3 ============ -->
|
||
<section class="bg-white rounded-xl shadow overflow-hidden">
|
||
<div class="p-6 border-b border-slate-200 flex items-start justify-between gap-4">
|
||
<div>
|
||
<h2 class="text-2xl font-bold">③ 存储层 monolith:repository.py / db.py 按域拆分</h2>
|
||
<p class="text-slate-500 mt-1 font-mono text-sm">storage/repository.py(1180 行)· storage/db.py(709 行)</p>
|
||
</div>
|
||
<span class="shrink-0 px-3 py-1 rounded-full text-sm font-semibold border bg-amber-100 text-amber-800 border-amber-300">Worth exploring</span>
|
||
</div>
|
||
<div class="p-6 grid md:grid-cols-2 gap-8">
|
||
<div class="space-y-4 text-sm leading-relaxed">
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Files</h3>
|
||
<ul class="list-disc ml-5 space-y-0.5 text-slate-600">
|
||
<li><code>storage/repository.py</code> — 1180 行、12 个 repository 类、跨约 5 个域</li>
|
||
<li><code>storage/db.py</code> — 709 行、20 张表一个模块</li>
|
||
<li>对比项:<code>intelligent_eval/repository.py</code>(510 行、单域)是良好范本</li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Problem</h3>
|
||
<p>文件级 <strong>locality</strong> 欠佳:目录(Target/Scenario)、执行(Run/Result)、评估活动(Campaign + 两个智能作业)、探索式评测(ExplorationSession/Message)同居一文件;探索对(1057–1163)与异步作业仓库(782–996)完全自包含,却被迫与无关域共享导航成本。AI 与新成员定位"活动的 CAS 写入"必须扫过全部 12 个类。CAS 条件写模式也在此三度独立实现(680–739、802–828 与 intelligent_eval 的 190–248),同文件却不共享原语。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Solution</h3>
|
||
<p>纯移动不改行为:拆出 <code>storage/exploration_repository.py</code>、<code>storage/async_job_repository.py</code>(或随候选①并入执行器模块);db.py 可暂不动(表定义集中有 create_all 的便利)。可选第二步:把三份 CAS 收敛为一个共享条件写原语——但需先过<strong>删除测试</strong>:三处的条件字段与冲突语义确有差异,只有当共享原语接口小到不泄漏这些差异时才值得。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Benefits</h3>
|
||
<p>每域一个文件 = 改动、bug、知识同址;导航成本从"扫 1180 行"降到"开对应文件"。本身不产生 leverage,故标记为 Worth exploring——它是其他候选(①②)的天然搭车项,单独做价值有限。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-3 text-sm">Before / After</h3>
|
||
<div class="text-xs space-y-3">
|
||
<div>
|
||
<p class="text-center font-semibold text-red-600 mb-2">Before · 一文件 12 类 5 域</p>
|
||
<div class="border-2 border-slate-400 rounded p-2">
|
||
<p class="text-center font-mono mb-1.5">storage/repository.py — 1180 行</p>
|
||
<div class="grid grid-cols-3 gap-1">
|
||
<div class="bg-sky-100 rounded p-1 text-center">Target</div>
|
||
<div class="bg-sky-100 rounded p-1 text-center">Scenario</div>
|
||
<div class="bg-violet-100 rounded p-1 text-center">Run</div>
|
||
<div class="bg-violet-100 rounded p-1 text-center">Result</div>
|
||
<div class="bg-emerald-100 rounded p-1 text-center">Campaign</div>
|
||
<div class="bg-emerald-100 rounded p-1 text-center">AnalysisJob</div>
|
||
<div class="bg-emerald-100 rounded p-1 text-center">ComparisonJob</div>
|
||
<div class="bg-rose-100 rounded p-1 text-center">ExplSession</div>
|
||
<div class="bg-rose-100 rounded p-1 text-center">ExplMessage</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p class="text-center font-semibold text-emerald-600 mb-2">After · 每域一文件</p>
|
||
<div class="grid grid-cols-2 gap-1.5">
|
||
<div class="bg-sky-50 border border-sky-300 rounded p-1.5 text-center">catalog_repository</div>
|
||
<div class="bg-violet-50 border border-violet-300 rounded p-1.5 text-center">run_repository</div>
|
||
<div class="bg-emerald-50 border border-emerald-300 rounded p-1.5 text-center">campaign_repository</div>
|
||
<div class="bg-rose-50 border border-rose-300 rounded p-1.5 text-center">exploration_repository</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 候选 4 ============ -->
|
||
<section class="bg-white rounded-xl shadow overflow-hidden">
|
||
<div class="p-6 border-b border-slate-200 flex items-start justify-between gap-4">
|
||
<div>
|
||
<h2 class="text-2xl font-bold">④ 前端读取模块:src/read 从单消费者扩展为统一资源接缝</h2>
|
||
<p class="text-slate-500 mt-1 font-mono text-sm">src/read/* · components/intelligent_eval/* · hooks/useCampaignReport.ts · hooks/useResource.ts</p>
|
||
</div>
|
||
<span class="shrink-0 px-3 py-1 rounded-full text-sm font-semibold border bg-emerald-100 text-emerald-800 border-emerald-300">Strong</span>
|
||
</div>
|
||
<div class="p-6 grid md:grid-cols-2 gap-8">
|
||
<div class="space-y-4 text-sm leading-relaxed">
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Files</h3>
|
||
<ul class="list-disc ml-5 space-y-0.5 text-slate-600">
|
||
<li><code>read/intelligentEval.ts</code>(118 行,有测试)· <code>read/useIntelligentEvalRead.ts</code>(83 行,有测试)</li>
|
||
<li><code>components/intelligent_eval/</code> — ExecutionProcess(480 行)、DecisionProcess、ConfigSnapshots、TaskQueueMonitor</li>
|
||
<li><code>hooks/useCampaignReport.ts:16-21</code>、<code>hooks/useResource.ts</code></li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Problem</h3>
|
||
<p><code>src/read</code> 是一个<strong>真正的深模块</strong>(ReadSlot 相位机、竞态守卫、静默刷新、可注入 adapter,且有测试)——但只有 IntelligentEvals.tsx 一个消费者,连它自己都绕过读模块做 mutation。五个 drawer 标签页各自手写同形 fetch 样板(DecisionProcess:25-35、ConfigSnapshots:32-42、TaskQueueMonitor:39-50);<code>ACTIVE_STATUSES</code> 定义两份;<code>ReadPhase/ReadSlot</code> 在 useCampaignReport.ts 里平行重造;Blob 导出仪式重复三遍;同一份决策日志有三种新鲜度策略(父级 5s 轮询详情 + ExecutionProcess 独立 5s 轮询 + DecisionProcess 只挂载取一次)。组件群零测试(EvalReport / EvalOverview / DecisionProcess / ConfigSnapshots / TaskQueueMonitor)。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Solution</h3>
|
||
<p>把 ReadSlot 泛化为通用资源接缝(或强制 drawer 标签页走既有 <code>useResource</code> + 轮询门控),决策日志的新鲜度策略由父级读模块统一供给一次;常量与导出仪式各自归位单一出口。组件退化为纯渲染,状态经 props/reducer 注入。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Benefits</h3>
|
||
<p><strong>Leverage</strong>:竞态守卫、静默刷新、轮询暂停这些已写好且已测的行为,一次学习全组件受益。<strong>可测性</strong>:接口即测试面——五个零覆盖组件的测试从"mock 整个 api + 时序"变成对纯 reducer/props 的断言,这正是 sessionReducer 已验证的形状。深模块已存在、adapter 需求已出现(campaign 报告平行重造)——符合"两个 adapter 才是真接缝"。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-3 text-sm">Before / After</h3>
|
||
<div class="text-xs space-y-3">
|
||
<div>
|
||
<p class="text-center font-semibold text-red-600 mb-2">Before · 深模块闲置,样板四散</p>
|
||
<div class="flex gap-1.5">
|
||
<div class="w-1/3 impl rounded p-2 text-center self-stretch">src/read<br><span class="text-amber-300">深·有测试</span><br><span class="text-red-300">1 个消费者</span></div>
|
||
<div class="w-2/3 grid grid-cols-2 gap-1">
|
||
<div class="bg-red-50 border border-red-300 rounded p-1.5 text-center">ExecutionProcess<br>手写 5 个 fetch 槽</div>
|
||
<div class="bg-red-50 border border-red-300 rounded p-1.5 text-center">DecisionProcess<br>手写样板</div>
|
||
<div class="bg-red-50 border border-red-300 rounded p-1.5 text-center">ConfigSnapshots<br>手写样板</div>
|
||
<div class="bg-red-50 border border-red-300 rounded p-1.5 text-center">TaskQueueMonitor<br>手写样板</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p class="text-center font-semibold text-emerald-600 mb-2">After · 资源接缝统一供给</p>
|
||
<div class="iface rounded p-2 text-center text-slate-800">useReadResource(slot, adapter) — 竞态/轮询/静默刷新内置</div>
|
||
<div class="grid grid-cols-3 gap-1 mt-1.5">
|
||
<div class="bg-slate-200 rounded p-1 text-center">列表页</div>
|
||
<div class="bg-slate-200 rounded p-1 text-center">5 个 drawer 标签</div>
|
||
<div class="bg-slate-200 rounded p-1 text-center">活动报告</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 候选 5 ============ -->
|
||
<section class="bg-white rounded-xl shadow overflow-hidden">
|
||
<div class="p-6 border-b border-slate-200 flex items-start justify-between gap-4">
|
||
<div>
|
||
<h2 class="text-2xl font-bold">⑤ api.ts 单文件按域拆分</h2>
|
||
<p class="text-slate-500 mt-1 font-mono text-sm">frontend/web/src/api.ts(909 行 · 12 域)</p>
|
||
</div>
|
||
<span class="shrink-0 px-3 py-1 rounded-full text-sm font-semibold border bg-slate-200 text-slate-600 border-slate-300">Speculative</span>
|
||
</div>
|
||
<div class="p-6 grid md:grid-cols-2 gap-8">
|
||
<div class="space-y-4 text-sm leading-relaxed">
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Files</h3>
|
||
<p class="text-slate-600"><code>src/api.ts</code> — auth、targets、scenarios、modelConfigs、runs、reports、stats、exploration、campaigns、intelligentEvals(16 个端点)、files,全部类型内联。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Problem</h3>
|
||
<p>v1.2 已点名的残留浅点。单文件本身不深不浅——axios 拦截器统一错误是真实深度——但 12 域同居迫使每次改动载入全部类型;报告 Markdown 下载的 DOM 副作用(835–843)住在"接口定义单一出口"里属越界。注意:它是<strong>locality 问题而非 depth 问题</strong>,单独拆不产生 leverage。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Solution</h3>
|
||
<p>保留 <code>api/index.ts</code> 作为拦截器与 axios 实例的唯一住处(现有唯一出口语义不丢),各域拆为 <code>api/intelligentEvals.ts</code> 等;Blob 导出仪式与候选④合并到同一个下载工具。</p>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-1">Benefits</h3>
|
||
<p>导航与 diff 噪声下降;域类型就近。无行为变化、无测试变化——因此只做搭车项,不单独立项。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-slate-900 mb-3 text-sm">Before / After</h3>
|
||
<div class="text-xs">
|
||
<div class="border-2 border-slate-400 rounded p-3 mb-3">
|
||
<p class="text-center font-mono mb-2">api.ts — 909 行</p>
|
||
<div class="flex flex-wrap gap-1 justify-center">
|
||
<span class="bg-slate-200 rounded px-1.5 py-0.5">auth</span><span class="bg-slate-200 rounded px-1.5 py-0.5">targets</span><span class="bg-slate-200 rounded px-1.5 py-0.5">scenarios</span><span class="bg-slate-200 rounded px-1.5 py-0.5">modelConfigs</span><span class="bg-slate-200 rounded px-1.5 py-0.5">runs</span><span class="bg-slate-200 rounded px-1.5 py-0.5">reports</span><span class="bg-slate-200 rounded px-1.5 py-0.5">stats</span><span class="bg-slate-200 rounded px-1.5 py-0.5">exploration</span><span class="bg-slate-200 rounded px-1.5 py-0.5">campaigns</span><span class="bg-amber-100 rounded px-1.5 py-0.5">intelligentEvals +DOM 副作用</span><span class="bg-slate-200 rounded px-1.5 py-0.5">files</span>
|
||
</div>
|
||
</div>
|
||
<div class="text-center text-2xl text-slate-400 my-1">↓</div>
|
||
<div class="grid grid-cols-2 gap-1.5">
|
||
<div class="iface rounded p-1.5 text-center text-slate-800">api/index.ts<br>实例 + 拦截器</div>
|
||
<div class="bg-slate-200 rounded p-1.5 text-center">api/<domain>.ts ×11</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ Top ============ -->
|
||
<section class="bg-slate-900 text-slate-100 rounded-xl shadow p-8">
|
||
<h2 class="text-2xl font-bold mb-3">Top recommendation — 先做 ②</h2>
|
||
<p class="text-slate-300 leading-relaxed max-w-4xl">
|
||
<strong class="text-emerald-400">候选②(智能评估可见性接缝)应当第一个做。</strong>
|
||
理由有三:其一,逻辑删除是一周前刚落地的新功能,其领域知识<strong>正在扩散</strong>——三处独立实现 + 路由直 import ORM 表 + 任务监控已实际泄漏已删评估,每晚一天收敛成本更高;其二,它是五个候选里<strong>爆炸半径最小</strong>的——纯收敛、零行为变化、已有 +100 行集成测试做行为锁;其三,它顺带把快照序列化与 expired 标注移出路由,巩固 v1.2 已确立的"路由只做 HTTP 翻译"纪律。
|
||
</p>
|
||
<p class="text-slate-300 leading-relaxed max-w-4xl mt-3">
|
||
紧随其后做 <strong class="text-emerald-400">候选①</strong>(结算序列——真有两个 adapter,接缝是真的),③⑤ 作为搭车项,④ 作为前端独立战役(涉及组件改造与补测试,体量最大)。
|
||
</p>
|
||
<p class="text-slate-500 text-sm mt-5">词汇:module / interface / implementation / depth / seam / adapter / leverage / locality(codebase-design);领域名词取自 CONTEXT.md。</p>
|
||
</section>
|
||
|
||
</main>
|
||
</body>
|
||
</html>
|