别再把代码当成最终产物:Symphony 作者谈规范驱动开发
原文标题:Stop Treating Code as the Artifact
Ryan Lopopolo 以 Symphony 为例提出,代码不应被视为最终产物,规范才是分发物。Symphony 是一个基于 issue tracker 的智能体编排系统,先以 SPEC.md 形式分发,Elixir 参考实现只是衍生产物,README 邀请读者把 SPEC.md 交给自己的编码智能体,用任意语言重建。
作者用 Symphony 的 spec 蒸馏循环说明代码只是可替换产物,为规范驱动开发提供了一条可迁移的路径。
当前语言的正文正在等待翻译,暂时显示原文。
Ryan Lopopolo•March 13, 2026 • Updated July 17, 2026
Symphony is an issue-tracker-based agent orchestration system. It polls for
work, creates an isolated workspace, runs a coding agent, and exposes enough
status to operate many concurrent runs. The system is distributed first as a
spec. There is an Elixir reference implementation, but the implementation is
explicitly derivative: the invitation in the README is to
hand SPEC.md to your coding agent and have it build Symphony in the
environment and language of your choice. Symphony is a ghost library: the
spec is the distribution, and the source tree is one generated artifact.

Before coding agents, we would still have needed to ship and maintain a canonical implementation beside the spec.
We did not produce the Symphony spec by starting with a blank Markdown file and attempting to imagine every requirement. We gave the working system to Codex and asked it to write the spec. A disconnected agent was then given only that spec and asked to reimplement Symphony. Another agent compared the new implementation with the original and amended the spec where they diverged. We repeated that loop until the spec could reproduce the system with high fidelity.1
This is spec-driven development in reverse. Code is an extremely information-dense straw man for what the system could be. It is easier to build the concrete thing, engage with it as a team, and distill the accepted decisions into a spec than it is to anticipate every consequential decision up front. The implementation does the exploration; the spec records enough of the result for an agent to assemble it again.
A spec is not sufficient on its own inside a working repository. An agent-authored PR should carry the prompt that produced it because the diff only shows what was implemented. The prompt records the work that was intended. The repo-owned spec defines what the system does; typed boundaries and executable guardrails constrain the implementations the agent is allowed to produce; the operator surface emits the logs, state, and status that prove whether a run behaved correctly.
These constraints are also code, and all code in the repository is itself a prompt. A codebase with six competing patterns requires the model to spend attention rediscovering which one is canonical. Unifying the repository on one pattern makes the intended choice legible without loading another page of rules into the context window.
For review, I want the prompt beside the diff so I can compare intent with implementation. I want the invariant encoded in a boundary or verifier, and the proof emitted through the operator surface. Those are the parts that survive a replacement implementation. The source tree still matters because future agents use it as a prompt, but it is one replaceable realization of the system.
Footnotes
-
I described the spec-distillation loop and the “ghost library” name in the Latent Space interview on harness engineering. ↩
来源:Ryan Lopopolo · hyperbo.la