Published on

做了一整晚,周报还停在外围:我们为什么把一个大 Spec 拆成三期?

Authors
  • avatar
    Name
    hpoenixf
    Twitter

做了一整晚,周报还停在外围:我们为什么把一个大 Spec 拆成三期?

一次 Agent 周报开发复盘:完整思考方案,不等于一次性实现全部方案。

一、我们原本只是想让 Agent 写一份周报

2026 年 10 月,我们准备给 ETF Agent 增加一项很自然的能力:根据用户已有的基金持仓,每周生成一份投资组合复盘。

我们的目标不是让 Agent 罗列一周涨跌,而是让用户看完后知道:组合发生了什么变化、风险有没有偏离、哪些事情值得关注,以及是否需要调整后续研究。

报告最好是 HTML,手机上能读,有必要的图表和数据来源,聊天窗口再给一段简短结论。

但当我们真正开始设计,就发现这件事远比“每周总结一次”复杂。

如果是周报,似乎应该有历史记录;既然有历史,最好支持跨期比较;既然能够比较,就应该保存过去的投资观点,记录观点有没有变化;既然是每周的事,最好支持定时订阅;既然会订阅,就还需要通知、取消、重试;报告要交给用户,还得考虑 HTML、移动端、打印、文件保存和下载。

这些需求单独看,都合理。

于是我们认真讨论了完整产品方案,形成了覆盖多类场景、多个模块和不同验收路径的 Spec。

问题也从这里开始。

二、一个晚上过去了,我们还在完善外围能力

开始实施之后,我们并不是没有进展。

我们逐步处理了研究方法、固定 HTML 渲染、文件保存、历史资格、来源交接、页面可用性和一些失败路径。局部测试不断增加,一些组件也能够独立运行。

可开发了一整晚,我们回头看用户最初的要求,发现一个尴尬的事实:

我们花了大量时间让周报系统变得完整,却还没有让 Agent 从正常入口自主交付第一份周报。

这并不是说历史、订阅、安全或移动端不重要。

问题在于,我们没有足够严格地区分两类工作:

一类是没有它,第一份报告就无法交付。

另一类是有了第一份报告之后,产品才能长期变得更好。

它们都值得做,却不应该天然拥有相同的实施优先级。

当时的大 Spec 已经把这些工作组织在同一套任务和验收中。结果就是,某个外围机制尚未完善,整项工作看起来就还不能结束。

更糟糕的是,这种结构会不断产生新的依赖:历史比较要求更完整的来源;来源处理牵出版本管理;版本管理又牵出恢复;HTML 的视觉问题又让我们继续研究渲染器。

一个 Spec 可以在逻辑上自洽,却在交付顺序上不合理。

而 Coding Agent 的强执行能力,反而会放大这个问题。

过去开发一个外围功能可能需要几天,我们自然会重新考虑优先级。现在 Agent 可以连续创建模块、补测试、完善协议,只要计划里还有任务,它就能持续推进。

它并不知道:继续完成计划,与尽快交付用户价值,可能已经不是一回事。

三、真正改变方向的,是重新定义第一份结果

10 月 20 日,我们决定收缩第一期范围。

不再要求一次交付完整的周报产品,而是把第一阶段重新定义为:

用户通过一条正常 CLI 命令启动研究,Agent 自己取得获准的数据,形成报告,保存 HTML,并在最终回答中返回真正可下载的文件链接。

这条要求听起来比之前简单得多。

但它反而更严格。

因为它不接受几个常见的替代品:

  • 模型说“报告已生成”,却没有实际文件;
  • Python 完成了渲染,但没有经过文件保存;
  • 测试代码预先拼好结果,替 Agent 完成关键步骤;
  • 开发者手工修改参数或补文件之后,宣布“自动交付成功”;
  • 服务端已经保存,却无法从正常下载入口取得文件。

我们先要求离线生成、保存和下载一份真实文件,证明不依赖模型的基础交付链成立。之后再让真实模型通过正常入口使用同一项能力。

此时,第一期不再把长期历史、复杂比较、订阅通知、投资论点管理和精细版式当成关闭条件。

这不是取消它们,而是撤销它们对首份结果的阻塞权。

同样,首期 HTML 可以朴素,研究数据可以明确标记不足。但必须保留真实权限、来源身份、文件安全和执行事实。

缩小交付范围,不能靠删除必要的正确性保护实现。

四、HTML 又让我们发现:有些能力根本不该属于周报

范围收缩之后,还有一次更深的架构调整。

我们原来为周报准备了一条相对专用的生成路线:固定研究方法、Python Renderer、专门的 HTML 生成和文件交付接线。

固定模板有其优点,输出比较统一,也方便做确定性检查。

但真实研究逐渐暴露出另一面。

模型可能已经拿到数据,却把结果哈希误当成工具调用身份;可能尝试导出一个实际不存在的工作区路径;也可能在一段漫长的 Python 流程中完成计算和渲染,最后仍然没有交付文件。

另一批报告交付检查甚至出现过:文件已经保存,最终回答也给出了链接,但五次认证下载全部返回 404。

这些不是单纯的“HTML 排版问题”,而是在提醒我们:

周报的独特性主要是研究方法,不是文件基础设施。

为什么周报应该拥有一套自己的文件保存协议?为什么直接写 HTML 和 Python 生成 HTML 必须走两套不同的交付逻辑?

后来我们把通用 HTML 生成、保存和下载能力从周报专用路径中抽出来。

可以把新的交付路径简化成:

  1. Agent 研究并组织内容;
  2. 根据任务选择直接生成 HTML,或者用 Python 完成必要计算和批量生成;
  3. 两条路线共同使用既有内容准备、来源处理、文件保存和授权下载能力。

模型负责选择适合任务的表达方式,已有领域能力负责可信数值,Publication 处理内容准备,Artifact 负责实际文件字节和访问边界。

我们不再要求每一种报告都经过一条专用 Renderer,也没有顺手增加新的 HTML Router 或通用展示 DSL。

这一步非常关键。

分期交付不只是把任务往后推。有时还会迫使我们发现:某项能力原本就放错了产品边界。

最终,周报 Skill 可以专注于研究方法,而 HTML 成为其他研究任务也能够复用的通用交付能力。

五、一期、二期、三期,最后到底怎样划分?

经过重新整理,我们不再按照原 Spec 的章节顺序推进,而是按照可以独立交付的结果组织工作。

阶段独立结果不再作为本阶段阻塞的事情
一期:首份周报一条正常命令完成研究、HTML 保存和实际文件下载历史比较、订阅、复杂论点管理、综合质量优化
二期:连续周报合格的历史记录、跨期比较、保留与删除、历史读取及基础可用性订阅通知、进一步的论点版本管理、深度优化
三期:长期伴随有限周期执行、任务历史、通知偏好、投资论点与用户修正、进一步的研究深度选择新交易系统、第二套调度器,以及不属于 Runtime 的语义质量保证

HTML 通用能力不是“第四期周报”,而是从具体场景中识别出来的横向基础能力。

这次拆分还有一个不太显眼、但很重要的操作:

真正修改当前期的需求范围、任务清单和验收条件,同时把已有工作、失败和后续需求移交给相应阶段。

如果只在 Proposal 里写一句“MVP 优先”,原来的任务清单、依赖关系和关闭条件完全不变,那不叫分期,只叫给超大的 Spec 换了一个标题。

对于已经接近完成的二期工作,我们也没有为了拆分而机械搬走。是否拆出三期,取决于它是否拥有相对独立的交付结果、责任边界和验收周期,而不是根据任务数量平均分成三份。

六、拆分之后,交付终于有了可证明的结果

10 月 20 日,一期共享 HTML 路线取得了更明确的工程结果。

在固定候选的五次普通真实 CLI 运行中,五次都按当期交付条件正常结束,返回了实际保存文件的链接;13 个 HTML 文件版本通过认证下载,返回的字节大小与 SHA-256 与保存记录一致。

这次我们终于能够明确说明:

第一份报告所依赖的主要文件交付链,已经有正常入口的实际证据。

但我们没有因此宣布投资研究质量也已经通过。

一份文件可以真实存在、正确下载,而其中的分析仍可能不够深刻;一次报告可以完成,Agent 也未必能够稳定处理所有复杂变体。

后来的二期和三期分别完成了声明范围内的 Runtime 工程验收;它们并不自动证明周期研究具有长期产品价值,也不证明模型总能做出正确的投资判断。

这种结果分层,反而让开发进度更可信。

以前,一个外围问题没做好,可能让整项任务永远显示“未完成”。

现在,我们能分别回答:首份文件能否交付?历史能否正确保存和读取?定时任务是否遵守确认与取消?模型的研究质量又证明到了什么程度?

不同问题拥有不同的证据,不再互相借用成功。

七、怎样防止下一个大 Spec 再次陷入这种困境?

这次最值得保留的收获,不是临时把周报拆成了三份,而是我们随后调整了 Coding Agent 的 Spec 研发工作流。

否则下一个复杂需求到来时,Agent 仍然会兴致勃勃地规划十个模块,再花一个晚上建设外围。

我们把防止重演的做法收敛到了已有流程中,没有另外发明一套“分期审批系统”。

第一,设计阶段必须先说清第一份交付物

以前,我们更习惯从功能列表开始:要支持什么、有哪些模块、每个模块如何验收。

现在面对复杂需求,我们会更早提出:

用户最早可以得到什么真正可用的东西?

它可能是一份报告、一个文件、一次真实计算、一段可以完成的业务操作。

只有先确定这个结果,才能反过来判断哪些能力是必需依赖。

例如周报:

历史比较不是第一份报告的必要依赖;周期订阅不是;投资论点的完整版本管理也不是。

但合法取得数据、实际生成文件、保存并返回可下载链接,是必要依赖。

因此 Spec 中要明确第一份产物,以及如何观察它确实完成,而不只是罗列一串功能。

第二,允许完整设计,但不允许提前实施所有阶段

我们没有转向另一种极端:只准讨论第一期,未来一概不考虑。

复杂系统有些边界必须提前想清楚,例如权限、数据身份、持久化兼容,以及后续阶段是否会迫使当前结构推倒重来。

所以可以完整讨论远期方案。

但讨论过,不等于这一期承诺实现。

当前阶段只把必要依赖放入执行任务。远期功能可以保留方向和关键接口约束,但不因为它们已经出现在设计稿里,就提前创建表、服务、协议和测试框架。

哪怕有多个 Coding Agent 可以并行工作,也不代表应该让它们同时铺开所有外围模块。

并行能力解决的是执行效率,不会替我们自动判断任务的价值顺序。

第三,真正按阶段维护任务和验收,不只是给清单加标签

这是我们从周报拆分中得到的直接教训。

现在,若一个需求确实需要分期,我们要求每一期都能回答:

本期交付什么?依赖什么?哪些事情明确不属于本期?怎样证明本期完成?

实施顺序也按这个结果安排,而不是按照原来文档章节的先后顺序。

如果任务已经缩小范围,就要同步修改当前任务、计划和验收承诺。延期能力从当前完成条件中移除,并保留其后续归属和已经完成的证据。

不能一边说“先交付”,一边继续执行原来那份庞大的任务清单。

同样,某一期通过,不等于整个大需求已经完成。

这既防止首期交付被无关工作拖延,也防止我们把阶段成功包装为完整产品成功。

第四,把“是否值得新增机制”放回原有设计评审

即使当前阶段已经收窄,Coding Agent 仍可能在实现途中不断增加新模块。

因此我们继续使用原有的四个设计问题:

事实归谁,决定权归谁,失败如何处理,新机制究竟带来什么价值?

例如报告生成失败,应该先检查已有生成和保存能力哪里断了,而不是马上创建一个专用 Report Manager、Repair Agent 或新的流程控制器。

这项检查不要求开发者再填写一份新表格,也不为每种复杂度创建自动评分器。

我们希望改变的是开发者和 Coding Agent 的判断,而不是增加一道流程。

第五,验收沿真实交付路径,证据足够就停止扩大范围

对周报来说,文件存在不等于下载成功,局部测试通过不等于 Agent 自己完成。

因此第一期要求从正常入口走到实际文件交付。

与此同时,我们也明确区分:工程交付链的验证和模型研究质量的验证,是两个问题。

局部接口变更先做针对性回归;真正需要观察模型行为时,才进行相应真实测评。

同一范围已经得到有效证据,也不因进入下一个文档阶段就反复重跑整套检查。

验证是为了回答明确的问题,而不是为下一轮验证创造理由。

这一套方法什么时候启动?

不是所有需求都强制拆分。

如果任务很小、范围清楚、可以一次完成,就正常开发。

只有当一个 Spec 涉及多个可独立交付的结果、外围工作开始延迟核心交付,或者单次承诺已经难以清晰验收时,才需要认真考虑分期。

我们也不设固定的两期、三期或任务数量阈值。

防止重演的关键,不是让所有项目都变得流程化,而是在复杂需求第一次进入设计时,就建立清晰的交付顺序。

八、最后,我们改变了对完整设计的理解

问题不在于我们思考得太完整。

讨论历史、订阅、长期论点和恢复,是有价值的。提前识别会造成返工的关键约束,也有必要。

真正的问题是:

我们把“设计时应该考虑的问题”,变成了“第一期必须完成的事情”。

完整设计与分期实施并不冲突。

设计可以提前看见终局,实施却应该围绕最早能够交给用户的真实结果展开。对后续阶段,只保留必要的职责边界、不可违反的约束和已确认的方向。

如果第一份结果可以在更小的闭环内产生,就不应该让未来的完整产品形态持续决定今天是否可以交付。

这次周报实践最后让我记住了一句话:

完整思考方案,是为了避免未来走错方向;围绕第一份结果实施,是为了避免今天一直走不到终点。

而把它写入现有研发工作流,是为了让下一次 Coding Agent 面对复杂需求时,不必再靠做了一整晚之后的醒悟,才想起用户最初要的是什么。


取材边界:本文基于 2026 年 10 月周报一期、二期、三期的 Spec、实施记录、HTML 交付复盘和后续 Spec 工作流调整。完成与下载数据属于各自测试窗口;不代表生产部署、模型研究质量或实际投资收益已获证明。

延伸阅读与交流

这次经历与从 Bug 循环走向真实任务收敛、HTML 交付架构反转、Spec 与 Evidence 工作流相互补充。另一篇代码删了,旧文档为什么仍在指挥 Agent?继续讨论长期工程知识怎样跟着架构演进。

更多实践见 ETF Agent 工程文章与阅读目录。如果这些真实开发经验对你有帮助,欢迎到 GitHub 点个 Star。