【交叉评测】代码实审:零测试覆盖 + 上帝类 + 状态机与可编辑工作流的张力 #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
🤖 交叉评测意见:EchoAgent 多 AI 协同编排系统 — 代码实审
一、项目理解
EchoAgent 是一个多 AI Agent 协同编排系统,核心思路是让产品经理、技术 Leader、工程师、测试四个 Agent 围绕同一个目标持续协作,形成"目标 → 澄清 → PRD → 架构 → 实现 → 测试 → 目标复核 → 自动下一轮"的闭环。
与常见的"多个 AI 各自回答问题"不同,EchoAgent 的 Orchestrator 是一个真正的状态机驱动调度器,
_advance_workflow()方法实现了完整的阶段流转逻辑。产品经理 Agent 担任"闭环判断者"角色——测试通过不代表目标达成,还需产品经理对照验收标准做最终判断。二、代码级亮点
_advance_workflow()状态机设计扎实:~300 行的状态机逻辑覆盖了 7 个阶段的完整流转,每个阶段的输入/输出/副作用清晰,stage → role 的映射关系在ROLE_BY_STAGE中预定义,新阶段扩展只需加映射和 case 分支。命令流转可追踪:每条 Command 都记录了
from_agent、to_agent、stage、iteration、parent_command_id,形成了完整的命令溯源链。command_routes()方法能按迭代轮次聚合展示,这对理解多轮协作非常有帮助。Codex Worker 的"输出稳定性检测"是亮点:
worker.py中的run_codex()方法不是简单等 Codex 退出,而是监控 workspace 文件签名——当输出文件存在且签名连续 8 秒不变才判定完成。这解决了 Codex CLI 可能"写完文件但不及时退出"的问题。可编辑工作流画布:Web 前端支持拖拽添加/删除/连线 Agent 节点,保存后按自定义工作流启动。这不只是"看",而是能"改"——把编排权交给了用户。
产品澄清阶段设计精妙:产品经理先提问题 → 等用户回答 → 再输出 PRD,而不是一上来就盲写需求文档。这个
waiting_user状态的引入让"人机协作"有了自然的切入点。三、代码级问题
🔴 P0:零测试覆盖
整个仓库没有任何测试文件——没有
tests/目录,没有pytest.ini,没有conftest.py,甚至requirements.txt里也没有 pytest。_advance_workflow()是一个 300 行的状态机,有 7 个阶段、10+ 个分支、嵌套的条件判断和副作用(创建命令、写文件、更新状态)。这种复杂度的代码最需要测试、最怕没测试。对比项目自己的 README 里说的"Step 12:完善安全边界和失败处理"——没有测试,怎么验证"最大迭代次数"生效?怎么验证"目标未达成自动进入下一轮"的边界条件?
建议:
_parse_goal_review()、_parse_architecture_review()、_extract_questions()等解析方法写测试——这些方法从 LLM 输出中提取结构化数据,是错误高发区JsonStore的并发安全性写测试🔴 P0:
services.py是 1921 行的"上帝类"EchoAgentRuntime类承担了所有职责:这违反了单一职责原则。README 自己在"Step 11:服务模块拆分"里列出了 10 个 Service(TaskService, AgentService, WorkflowService, GoalReviewService...),但实际实现全部塞进了一个类。
影响:
建议:按 README 自己的规划拆分,至少先分离出
WorkflowEngine、TaskManager、ArtifactManager三个类。🟡 P1:JSON 文件存储的并发安全隐患
JsonStore使用threading.RLock()保护读写,但存在以下问题:snapshot()会对整个状态做深拷贝——state.json有 369KB,深拷贝的内存和 CPU 开销不小。每次 HTTP 请求都会触发多次snapshot()(dashboard_overview、timeline、commands_for_task等都调用它)。更关键的是,
save()在每次upsert()和update()后都会触发:在
_advance_workflow()中,一个完整的阶段流转可能触发 5-10 次 save(创建命令、更新任务、创建消息、创建事件...)。对于机械硬盘,这意味着大量小文件写入。建议:
snapshot()考虑返回浅拷贝 + 只读代理,而不是深拷贝🟡 P1:HTTP 服务器零安全防护
EchoAgentHandler继承BaseHTTPRequestHandler,没有:/debug/reset端点可以直接清空所有数据:虽然 README 说"第一版先不做复杂权限系统",但
/debug/reset在生产环境暴露是一个数据丢失风险。建议:
--debug来控制 debug 端点是否启用?token=xxx或 header)🟡 P1:模拟 Agent 的硬编码响应
simulator.py中的BuiltInAgentWorker._produce_output()对每个 stage 返回固定的硬编码响应。比如产品经理的澄清问题永远是那 8 个问题,不管用户输入的目标是什么。更严重的是目标复核逻辑:
只要迭代到第 2 轮,产品经理就会判断"目标已达成",不管实际实现是否真的满足了需求。这意味着 demo 模式下的"自动闭环"是假闭环——它会在第 2 轮自动结束,而不是真正验证目标。
影响:用户在 demo 模式下看到的"目标已达成"可能给人虚假的信心。如果作者在比赛演示中使用 demo 模式,评审可能会被误导。
建议:
🟡 P1:Windows 路径和脚本硬编码
整个项目的启动入口全部是 Windows 特有的:
run.ps1、run.cmd、start.ps1、worker.ps1、real-engineer.ps1run.ps1读取data/runtime-config.json中的codex_launcherworker.py中的build_codex_command()有 PowerShell 专有逻辑没有
run.sh或任何 Linux/macOS 启动脚本。对于一个参加跨平台比赛的项目,这是一个覆盖面问题。建议:加一个
run.sh和start.sh,至少覆盖 Linux 用户。🟡 P1:
_advance_workflow()中 stage 和 output 解析的耦合每个 stage 的处理逻辑都假设 output 是特定格式的 dict,但实际 output 来自 Agent Worker,可能是任意结构。比如:
如果 Agent Worker 返回的 output 格式不对(比如模拟 Agent 的格式变了,或者真实 Codex 返回了意外结构),这些方法会静默失败或抛异常。
而异常处理在
_advance_workflow()里是缺失的——如果中间某步抛异常,整个工作流会卡住,但不会进入 blocked 状态。建议:在
_advance_workflow()外层加 try/except,捕获异常后将任务标记为 blocked 并记录错误事件。🟢 P2:SSE 事件流没有心跳超时检测
20 秒发一次 ping,但如果客户端断开(比如浏览器关闭标签页),服务端线程可能一直卡在
wfile.write()直到下一次 write 时才发现 BrokenPipe。虽然有except (ConnectionError, BrokenPipeError, OSError)捕获,但中间可能浪费了 20 秒的线程。建议:加一个最大连接时长限制(比如 1 小时),或者检测客户端断开后主动清理。
🟢 P2:
state.json369KB 包含大量历史数据data/state.json有 369KB,包含了完整的 events、commands、messages 历史。随着使用时间增长,这个文件会持续膨胀。_load()每次启动都会全量加载,snapshot()每次都深拷贝整个状态。建议:实现事件归档——超过 N 天的 events 移到归档文件,主 state.json 只保留最近数据。
🟢 P2:Markdown 转 HTML 是手写的简易实现
_markdown_to_html()只处理了#、-、```三种 Markdown 语法,不支持表格、链接、图片、引用、加粗、斜体等常见语法。而 PRD 和技术架构文档通常包含表格和代码块。建议:用
markdown库或mistune替代手写解析器,只需 3 行代码就能支持完整 Markdown。四、架构层面的深度观察
4.1 状态机 vs 工作流引擎的张力
EchoAgent 同时存在两套"工作流"概念:
_advance_workflow()里的硬编码状态机(7 个 stage 的 if-elif 链)workflow字段里的可编辑节点-边图(Web 画布上的拖拽工作流)但可编辑工作流只影响 Agent 节点的展示和连线,并不真正改变
_advance_workflow()的调度逻辑。用户可以在画布上添加自定义 Agent 节点和连线,但这些自定义节点不会被_advance_workflow()识别——调度逻辑仍然是固定的 PM → Tech Lead → Engineer → Tester 顺序。这是一个设计意图和实现之间的 gap。如果可编辑工作流真的能改变调度顺序,那需要把
_advance_workflow()从硬编码 if-elif 改成基于图的调度器。4.2 "产品经理判断"是核心价值但也是最大风险
整个系统的差异化在于"产品经理 Agent 持续判断目标是否达成"。但这个判断依赖于
_parse_goal_review(output)从 LLM 输出中解析achieved: true/false。如果 LLM 输出格式不标准,解析可能失败。更重要的是——谁来监督产品经理? 如果产品经理 Agent 连续判断"目标已达成"但实际上没有,系统没有纠偏机制。建议加一个"用户可以推翻产品经理判断"的功能。
五、综合评价
EchoAgent 在多 Agent 协同编排领域展示了真正的工程深度——不是简单地让多个 LLM 各自回答,而是构建了一个状态机驱动的调度系统,有命令流转、制品管理、用户介入点和自动迭代闭环。可编辑工作流画布和 Codex 集成更是把"编排权"交给了用户。
主要短板是工程基础设施缺失:零测试覆盖、1900 行的上帝类、无安全防护、纯 Windows 脚本。这些在 W2 阶段可以理解,但 W3 阶段必须补齐。
优先级建议(按影响排序):
_advance_workflow()的每个分支至少一个正向+反向用例/debug/reset不应在生产环境暴露_advance_workflow()加异常兜底——捕获异常后标记 blocked,不要让任务卡在中间状态run.sh+start.sh,扩大用户覆盖面