你无法让开发停下来。这是你必须接受的第一件事。工单不断涌入,客户期待发货,而你现有的代码并不会因为你决定编写文档就停止运行。没有哪个工程经理会批准长达一个月的停工期,好让团队去编写那些本该从第一天就存在的规范。OpenSpec 是为现实而生的,而不是为了绿地开发的幻想。当你把它嫁接到现有系统(包括现有的客户)上时,它的效果最好。

这里的目标不是重写,而是“诚实的考古”。你需要挖掘出生产环境中实际运行的东西,准确地描述它,并让这种描述随着代码的演进而演进。当你的规范与系统匹配时,你不仅能让下一季度加入的工程师受益,也能让现在集成在 IDE 中的 AI 工具受益。以下是如何在不耽误任何一次发布的情况下实现这一目标的。

从实际业务开始

打开你的代码仓库,你会看到名为 controllersmodelsservicesutils 的文件夹。这些是技术层,它们会“误导”你。它们并没有描述你的系统为业务做了什么。一个装满 JavaScript 文件的文件夹并不能解释订单是如何变成发货单的。要对 OpenSpec 进行追溯适配,你需要从“业务能力”的角度去思考。

寻找那些即使你用另一种语言重写整个技术栈也能幸存下来的稳定业务操作。在大多数产品型公司中,这些操作会反复出现:订单 (Orders)、计费 (Billing)、库存 (Inventory)、客户 (Customers) 和通知 (Notifications)。列出五到八个这样的核心能力。

针对每一个能力,强迫自己回答五个具体问题:这个能力解决了什么现实问题?代码实际存在于哪里——是一个服务、三个微服务,还是一个没人敢碰的遗留模块?它的触发机制是什么:用户点击、定时任务 (cron job),还是传入的 Webhook?输入数据是什么,输出数据又是什么?最后,哪些其他系统依赖于它,也就是说,如果这部分停止工作,什么会崩溃?

请保持绝对的诚实。如果你的“客户”能力分散在 Rails 单体架构、Node API 和外部 CRM 中,请务必如实记录。你的地图必须看起来像真实的领土,而不是建筑师的梦想。

记录真相,而非愿望清单

在任何文档编写工作中,最危险的一句话就是:“既然我们正在写这个,不如顺便把它修了吧。” 停下来。你不是在重新设计结账流程,你是在描述那个目前正在处理真实信用卡扣款的结账流程。

如果下单会立即触发支付捕获,然后通过后台工作进程发送电子邮件,请记录下这个精确的序列。不要插入你计划在下季度添加的消息队列。如果验证逻辑实际上深藏在某个服务类中,不要假装它发生在 API 边缘。准确性远比抱负更重要。

错误的文档比没有文档更糟糕。它会误导新员工,让他们对不存在的行为产生预期;它会让 AI 编程助手基于一厢情愿的想法走上错误的路径。当你的规范与生产环境匹配时,你就建立了一个可靠的基准。调试会变得更快,因为你不再需要猜测“预期”的流程;重构会变得更安全,因为你知道起点是真实的。

从 API 中提取契约

你的 API 端点已经在执行规则了,只是它们目前是隐性的。适配 OpenSpec 意味着将这些规则公开化。

从输入和验证开始。端点实际上接受什么?记录数据类型、必填字段、最大长度以及字段间的依赖关系。然后描述业务行为。这次调用是创建了一条记录、触发了一个副作用,还是仅仅针对另一个服务验证状态?请务必具体。

最后,编目响应结果。成功时返回什么?具体的错误代码是什么,它们在什么条件下出现?不要只写“返回错误”。要写“当账单地址缺失时返回 422,当库存已被另一个进程预留时返回 409”。这种精确度能将一个模糊的路由转变为前端团队、QA 工程师和自动化工具都可以信任的契约。

寻找隐藏的规则

Some of the most expensive knowledge in your system lives in the gaps. It is buried in conditional blocks inside service classes, tucked into database triggers, or written into stored procedures that no one has touched in two years. These are your business rules, and they are usually rediscovered during outages or by cornering the one engineer who has been there since the beginning.

Pull them into daylight. Start with the ones you already know. Orders above a certain value need manager approval before they proceed. Inactive user accounts cannot create new orders. Refunds are only permitted before settlement completes. Write each rule next to the capability it governs, in language clear enough that a product manager could read it without a translator.

When you centralize these rules, you do more than document them. You expose duplication. You reveal conflicts. And you give the entire team a single place to debate policy before someone commits a one-line change that accidentally violates a constraint you forgot existed.

Map the Plumbing

Modern systems run on events. An action in one service ripples through half a dozen others before anything visible reaches the user. You need to chart those ripples. Map the flow from one event to the next for your core workflows. Order created leads to inventory reserved, which waits for payment confirmed. Draw the full chain, even if some links feel fragile or use different protocols.

Do not stop at internal traffic. External services are part of your system whether you treat them that way or not. For each integration, record its purpose, how your application authenticates, and how it fails. Does the payment gateway timeout after thirty seconds and return a generic 500? Does the shipping API return malformed JSON on weekends? Does the identity provider revoke refresh tokens earlier than its own documentation claims? These details look trivial