在 Vibe Coding 高速迭代中构建可约束的 AI 开发流

发布时间:2026/6/26 1:21:31
在 Vibe Coding 高速迭代中构建可约束的 AI 开发流 如果一个项目主要靠 Vibe Coding 推进而且每周要处理几十个 PR真正困难的地方往往不是“让大模型写出代码”。这件事反而越来越容易。困难的是当需求、代码、文档、测试、PR 都被大模型高速生成时团队如何确保它没有悄悄扩范围、没有漏掉契约、没有把临时判断写成长期事实也没有在下一个会话里忘掉前一个会话的前提。toLink-Rag 现在搭建的docs/文档结构、.specs/spec-as-test 开发流以及一组自建 skills本质上是在回答同一个问题在极快的 AI 辅助迭代里如何给大模型建立稳定的行为边界。这套机制不是为了增加仪式感也不是为了把开发流程变重。它的目标更直接让大模型在该发散的时候发散在该收敛的时候收敛在该停下来的时候停下来。需要先说清楚架构上的分层这套体系不是端到端的硬状态机而是「契约层机器门禁 需求/流程层 skill 协议」的组合。前者在 pre-commit / CI 里真拦截后者靠 skill 分岗、flow-guard.py和 PR 收口自觉执行。读下文时应区分“提交时一定会被拦住”和“规范上应该做、但机器暂时看不见”。高速 Vibe Coding 先带来的不是效率问题而是约束问题纯 Vibe Coding 的优势很明显。一个想法可以很快变成代码一个 bug 可以很快得到修复一个模块也可以在很短时间里被重构出雏形。对单个开发者来说这种速度很有吸引力。但当这种方式变成项目主开发模式问题会从“能不能写出来”转为“写出来的东西是否可控”。尤其在 toLink-Rag 这样的后端项目里代码并不只服务于自己。它负责文档解析、分块、向量化索引、召回并通过 MQ、HTTP、MySQL、Qdrant、Elasticsearch、对象存储等契约与外部系统协作。一个字段名、topic、HTTP 路径、状态机终态语义可能都会影响 Java 业务方或运维交付。大模型擅长补全但它天然有几个风险它容易把上下文里“看起来合理”的东西写成事实。它容易在实现阶段顺手改需求边界。它容易把一次性讨论沉淀到长期文档里之后变成误导。它容易在跨会话时丢失阶段状态只根据当前聊天片段继续推进。它可以生成大量内容但不一定知道哪些内容应该长期维护哪些内容应该合并后清理。所以高速 Vibe Coding 项目需要的不是更多提示词而是一套能约束提示词行为的工程框架——其中最危险的部分必须机器化其余部分用可交接的流程协议补足。长期契约docs/分层与机器同步长期知识放在哪里、怎样不失真是整套约束的第一根柱子docs/管结构与生命周期机器规则管最危险的契约漂移。为什么先搭docs/架构docs/在这个项目里不是“所有文档的垃圾桶”而是长期知识的分层入口。当前docs/README.md把文档按读者旅程拆成几类docs/ ├── api/ 对外契约 ├── internals/ 内部实现 ├── ops/ 部署与配置 └── contributing.md 贡献者规范与开发流程读者分层。对接方关心 HTTP API、MQ 消息、错误码、MySQL schema、Qdrant payload、ES 索引内部开发者关心解析 pipeline、召回 pipeline、分块、向量化、MQ 中间件等模块边界运维交付人员关心部署、配置和依赖贡献者关心分支、测试、迁移、文档同步和 spec-as-test 流程。如果这些内容混在一个大文档里大模型每次都会读过多上下文也更容易把面向运维的说明写进内部实现或者把一次设计讨论写成对外契约。按读者拆分后每类信息有明确归属模型在维护文档时也更容易定位“这条事实应该写到哪里”。事实单一来源。docs/README.md明确约定每个事实只在一处正式描述其他位置只链接引用文档是代码的摘要代码是权威源。这个规则对人类开发者有帮助对大模型更重要。因为模型很擅长“补一段说明”但不擅长天然判断这段说明会不会在三个地方形成三份略有差异的事实副本。一旦字段表、topic、路径、配置项被复制到多个文档中高速迭代时必然有人漏改。漏改一次下一次模型再读到旧文档就会把旧信息继续放大。需要诚实补充“单一来源”目前是规范 部分机器校验不是全量语义对账。check_docs_sync.py只管“改代码时有没有一起改文档”文件级耦合check_docs_facts.py补了死路径、MQ topic 串、文档内锚点等内容级探针但尚不做 ORM 字段表与mysql.md的逐字段对账。文档与代码的完全一致仍依赖 PR 评审和contract-guard等 skill 的语义核对。长期与临时分离。项目明确规定设计草稿、PRD、迭代计划、实施报告这类一次性产物不放进docs/而是放到.specs/。docs/只沉淀合并后仍然有长期价值的内容比如对外契约、模块边界、配置约定、部署方式。这条边界看似细节实际是高速开发里非常关键的治理动作。因为 Vibe Coding 会产生大量中间文本如果不区分生命周期仓库很快会被“曾经正确、现在不一定正确”的文档淹没。文档同步的机器门槛仅仅规划目录还不够。因为在几十个 PR 的节奏下靠人记得同步文档并不可靠靠模型自觉也不可靠。所以项目把一部分文档同步变成机器规则放在scripts/doc-sync-rules.yaml、scripts/check_docs_sync.py、pre-commit hook 和 CI 里执行并用scripts/check_docs_facts.py在 pre-commit 做内容级对账捕获“文档改了但内容仍引用已删除路径 / 错误 topic”这类文件级规则抓不到的失真。当前error 级规则只拦截会导致集成 bug 的关键契约例如改src/models/**.py必须同步docs/api/schemas/mysql.md并新增 Alembic migration。migrations/db.sql是 0001 baseline 冻结快照禁止直接修改。改 MQ 消息结构必须同步docs/api/mq_contracts.md和docs/internals/mq.md。改对外 HTTP 路由必须同步docs/api/http_contracts.md。改解析任务流水线状态机必须同步docs/internals/parse_task_pipeline.md。这里有一个重要取舍项目没有把所有文档同步都做成强制拦截而是只保留error级规则。原因很现实。如果 warning 太多大家会习惯性忽略如果所有内部文档都被 hook 拦住小改动会被流程拖慢。因此这套规则只管“失同步会引发跨服务集成事故”的部分。内部模块说明仍然靠 PR 评审兜底召回 pipeline、Qdrant payload、ES mapping、跨端配置取值一致config-contract-sync所管的值层等目前仍以 skill 核对为主按真实事故面逐步纳入机器规则而不是一次性全拦。这个取舍让流程既能拦住真正危险的漂移又不至于让每个小改动都被文档流程卡死。对大模型来说机器门槛还有另一层意义它把“你应该同步文档”变成了“不同步就不能提交”。这比单纯提示词可靠得多——但只覆盖上表列出的契约面不是项目里所有协作面。开发期约束.specs/、spec-as-test 与 flow-guarddocs/管合并后仍成立的事实开发过程中的需求收敛、验收与阶段状态由.specs/目录、spec-as-test 链路和flow-guard共同承担。为什么需要.specs/而不是把需求都写进docs/docs/解决长期知识但它不适合承载开发过程中的所有中间产物。一个 feature 从想法到合并通常会经历需求理解、验收收敛、技术方案、编码偏差、测试验证、PR 收口。中间会有很多判断只在当前 feature 生命周期内有效。比如某次方案为什么选择 A 不选择 B某个风险为什么接受某个验收场景为什么被改写。这些内容对本次开发很重要但不一定应该永久留在主分支文档里。这就是.specs/的职责。.specs/README.md明确说除 README 外.specs/下的 feature 产物都不进 git。每个 feature 目录里按阶段生成.specs/feature-name/ ├── state.yaml ├── brief.md ├── acceptance.feature ├── technical_design.md └── implementation_report.md这些文件不是长期文档而是开发过程中的临时交付物。.specs/目录本身 git-ignored只放 feature 交付物定稿后的博客、论文等若需长期保留应移到docs/或仓库外发布避免模糊临时/长期的边界。这个设计避免了两个极端。第一个极端是没有 spec。模型直接从口头需求进入编码看起来很快但边界、异常、契约、验证都容易在实现中漂移。尤其跨会话继续做时模型很可能只记得“要实现某功能”忘掉之前已经确认过的限制。第二个极端是所有 spec 都入库长期维护。这样短期看可追溯长期看会留下大量过期设计。代码已经演进了旧 brief 和旧 technical_design 还躺在主分支里下一次模型读到它们反而会被误导。.specs/选择第三条路开发期强约束合并前只沉淀长期价值。合并前有价值的信息会被搬到正确位置关键设计决策、风险和权衡进入 PR 描述。可执行 Gherkin 场景提升到tests/acceptance/features/python scripts/promote_acceptance.py feature。新模块或边界变化进入docs/internals/。新对外契约进入docs/api/。新配置项进入docs/ops/configure.md。数据库表变化进入docs/api/schemas/mysql.md和 Alembic migration。合并后.specs/feature/应清理掉。这样既保留开发期约束又不让临时材料污染长期知识库。代价也要写进架构brief、technical_design 等中间产物的演化过程不在 git 里PR reviewer 看不到 spec 全文只能靠 PR 描述 提升后的 acceptance 代码 diff 还原决策。若promote_acceptance或 PR 沉淀漏做信息会随本地目录删除而丢失。因此 acceptance 提升和 PR 门槛自查不是可选项而是.specs/不入库设计必须配齐的下游动作。spec-as-test从自然语言到可验证链路这套流程叫 spec-as-test不是因为它喜欢写文档而是因为它把需求逐步变成可执行验证。第一步是brief.md。它回答“做什么、为什么做、不做什么、影响哪些模块、还有什么没定”。它不写方法级实现也不写物理 schema因为这些属于技术方案。它的目标是让另一个开发者读完后能在脑子里跑通需求。第二步是acceptance.feature。它把冻结后的 brief 转成 Gherkin 场景。每个业务规则都要落到Given / When / Then。其中Then必须是可机器验证的断言比如状态值、错误码、数据库行、MQ 消息而不是“系统应正确处理”。这一步对约束大模型尤其关键。自然语言需求里最容易藏模糊空间而 Gherkin 会强迫模型把“正确处理”拆成可判断结果。后续实现偏离需求时测试能直接暴露问题。第三步是technical_design.mdL3 全链才要求独立产出。它以brief.md和acceptance.feature为输入再结合真实代码、组件文档和公共契约写出可落地方案。当前 skill 里要求方法级变更表并要求每个方法关联到 acceptance 里的 Scenario。这就形成了一条追溯链业务目标 - brief.md - acceptance.feature - technical_design.md(L3) - 代码实现 - 测试验证第四步是implementation_report.md。它不是重复需求和方案而是在实现偏离方案、跨模块改造、L3 复杂需求或发生 spec 回写时记录实际落地差异。这样模型在编码时发现 spec 缺口不能直接绕过而要先回写 spec再继续实现。这个“回流规则”很重要。传统提示词常常假设流程是单向的需求写完方案写完然后编码。但实际开发里经常是编码时才发现前面漏了边界。没有回流规则时模型会直接改代码导致 spec 和实现脱节。有回流规则后缺口必须回到上游产物里被记录后续收口才能对齐。需要区分Gherkin 链路设计上是可验证的但 merge 前并非全部由 CI 硬拦。CI 的acceptance-steps.yml守的是 step 是否绑定防空壳 feature不保证每个 L3 PR 都新增了对应 acceptance后者目前靠branch-pr-workflow收口和 PR 留痕。state.yaml与 flow-guard长 feature 很少在一个会话里完成。Vibe Coding 的一个现实问题是今天的 agent 和明天的 agent 不一定有完整上下文甚至同一个会话压缩后也可能丢失细节。.specs/README.md里引入state.yaml和scripts/flow-guard.py就是为了解决这个问题。state.yaml是机器拥有的阶段状态记录当前 feature 的 phase、各 artifact 是否 frozen、acceptance 是否 promoted、是否 verified 等不变量。flow-guard.py在进入下游阶段前检查这些状态。例如brief 没冻结时不能生成 acceptanceacceptance 没冻结时不能进入 technical_designimplementation 阶段前要检查上游产物是否满足条件。脚本返回HARD STOP时agent 必须停下回到正确阶段。关键架构事实因为.specs/整目录 git-ignoredflow-guard.py不是git hook而是各 skill 在运行时主动调用的校验脚本。agent 不调、开发者直接改代码流程上可以完全绕过。它的价值是把“当前能不能进入下一步”从模型记忆里拿出来放进可校验但 opt-in 的本地状态里——比纯 prompt 可靠但弱于 pre-commit 硬拦截。跨会话续做时应先跑python scripts/flow-guard.py status恢复当前 feature、phase 和唯一允许的下一站而不是重读全部.specs产物。协议层落地自建 skills 与 L1/L2/L3 车道文档与 spec 定义了「存什么、走什么链」skills 负责让 agent 在正确阶段做正确判断并按复杂度选车道避免小改动被全流程拖死。为什么要自建 skills通用 skill 套件可以提供很多现成能力。如果把 superpowers 这类工具理解为通用的 agent 能力包它的价值在于覆盖常见任务模式比如规划、编码、测试、审查、总结。但 toLink-Rag 这里要解决的问题不是“有没有一个通用开发助手”而是“这个项目的 agent 必须按本项目的契约和流程行动”。这两者差异很大。通用 skill 很难天然知道哪些改动命中 L3必须走完整链。migrations/db.sql是 0001 baseline 冻结快照不能直接改。.specs/是临时目录合并前要提升 acceptance合并后要清理。docs/api/、docs/internals/、docs/ops/分别承载什么生命周期的信息。MQ 改动必须同步对外契约和内部实现文档。技术方案中的每个方法级改动要映射到 Gherkin Scenario。编码阶段发现 spec 缺口时必须先回写 spec而不是直接绕过。这些都不是通用方法论而是项目级制度。它们必须被写进项目自己的 skills。当前.ai/skills/是 skill 的物理唯一来源.claude/skills等通过 symlink 指向它scripts/check_skills.py在 pre-commit / CI 校验 skill 格式与引用。各 IDE 侧不应再维护一份独立副本否则治理层本身会失同步。多个 skill 本质上不是“功能越多越好”而是把开发链拆成多个带边界的岗位flow-router做入口分诊把需求按 L1、L2、L3 分车道小改动不被全流程拖慢契约改动也不能被当作快车道绕过。brief-generator收敛需求只写做什么、边界和影响面不越界写具体实现。acceptance-generator把冻结 brief 转成可执行验收契约消除自然语言模糊。technical-design把验收契约映射到方法级实现方案和测试策略L3。implementation-execution按冻结 spec 编码并在发现缺口时触发 spec 回流。contract-guard、config-contract-sync、doc-maintenance-sync把契约治理拆成结构层、值层、文档层避免一个 skill 同时判断、核值、改文档导致职责混乱。branch-pr-workflow在收口时检查测试、契约同步、acceptance 提升等门槛避免“代码写完了就直接提 PR”。这种拆分的好处是每个 skill 都只在一个阶段做一类判断。模型不需要在一个巨大提示词里同时记住需求分析、技术设计、编码、测试、文档、PR 收口所有规则。它只需要在当前阶段遵守当前阶段的边界然后把结果交给下一站。这比复用通用 skill 更适合当前项目因为它把项目经验编码成了可重复触发的行为而不是停留在某个开发者的习惯里。但也要承认skill 是 prompt 协议不是运行时编排器——没有统一引擎强制“当前只能跑哪个 skill”跳站仍可能发生。L1/L2/L3 车道与「为什么不拖慢开发」最容易产生的误解是既然有 docs、有 specs、有 skills、有门槛那开发一定变慢。实际不是这样。流程拖慢的是错误路径不是正常路径。flow-router把需求分成 L1、L2、L3判定从严命中任一 L3 强信号ORM、MQ 消息、migration、parse_task 状态机、对外 HTTP/错误码即升 L3不因“看起来小”压级。车道走什么链说明L1 快车道实现 → 测试 → PR单文件 / 配置 / 文案 / 小修无契约变更不需要state.yaml、brief、acceptanceL2 标准brief → acceptance → 实现 → 测试 → review → PR单模块功能仍要 acceptance仅跳过独立technical_design.mdL3 全链brief → acceptance → technical_design → 实现 → 测试 → review → PR跨模块 / 契约 / 中间件 / 数据迁移L1 是刻意的 bypass车道判定本身没有机器校验靠 flow-router 与开发者就高不就低误判时事后靠check_docs_sync和集成测试兜底。在每周几十个 PR 的节奏下这个设计很重要。因为真正昂贵的不是前面多写一页 brief而是后面出现这些问题PR review 时才发现需求边界不清。合并前才发现接口文档没同步。测试时才发现验收标准没有可断言结果。合并后才发现 Java 对端消费的 MQ 字段变了。新会话接手时才发现前一个 agent 的设计判断没有留痕。spec-as-test 和文档同步规则把这些问题前移。它们不是为了让每个 PR 更重而是为了让高风险 PR 更早暴露风险让低风险 PR 不被不必要流程拖住。边界与有效性硬拦什么、软靠什么、如何验证、往哪演进前三节分别讲了长期契约、开发期流程和执行协议。本节回答这套东西实际约束了什么、代价在哪、怎么判断有效、还缺什么。机器层 vs 协议层如果只看表面这套体系包含很多文件docs/README.md、docs/contributing.md、.specs/README.md、state.yaml、各种 skills、各种检查脚本。从架构上应分成两层理解机器层pre-commit / CI 真拦截机制约束什么check_docs_sync.py契约相关代码改动必须同步指定文档 / migrationcheck_docs_facts.py文档内容不与代码路径、MQ topic、锚点严重脱节check_skills.py项目 skill 格式与引用合法check_ai_links.pyAI 资产 symlink 不被误改成实目录acceptance-steps.ymlacceptance feature 的 step 均已绑定全量 pytest CI回归不绿不得合并协议层skill 脚本 opt-inPR 留痕机制约束什么flow-router入口车道判定flow-guard.py阶段冻结与跨会话恢复brief / acceptance / design / 回流需求与实现不对齐时的上游修正promote_acceptance.py验收场景进 git、进长期测试branch-pr-workflow收口门槛自查测试范围、契约语义、acceptance 提升contract-guard/config-contract-sync结构破坏与跨端取值一致行为上框架希望引导模型入口先判断车道不把所有改动都走同一套流程。需求先收敛业务目标和边界不直接凭口头需求编码。验收把规则写成可断言 Scenario不让“正确处理”停留在散文里。设计L3技术方案必须读真实代码和契约方法级改动要映射到验收。编码实现受冻结 spec 约束发现缺口先回写。文档长期知识进docs/临时交付物留.specs/合并前只沉淀长期价值。收口测试、契约同步、acceptance 提升不过关就不应假装完成。其中前四项与收口里的 acceptance 提升主要落在协议层文档同步与测试回归落在机器层。把两层混在一起谈“可约束”会高估 spec-as-test 主链的 enforce 程度。风险与 trade-off这套框架并不是银弹。下面几条比“需要持续维护”更重属于架构 trade-off不是小瑕疵。第一enforce 不对称。契约文档同步很硬spec-as-test 主链很软。agent 跳过flow-guard、不做promote_acceptance、L3 被自评成 L1机器在 merge 前都看不见——除非靠 PR 描述、reviewer 经验和后续要补的 PR 级启发式检查。第二.specs/不入 git 换开发期轻量换团队 audit trail。中间 spec 不进版本库多人协作时 reviewer 看不到 brief/design 演化沉淀完全依赖 merge 前动作。漏一步信息随本地目录删除而丢失。第三机器规则覆盖面小于项目真实契约面。parse_task、MQ、HTTP、MySQL 已纳入 error 规则recall pipeline、Qdrant/ES 索引语义、配置值层一致等仍主要靠 skill 与 PR 评审。若把“上了 doc-sync 就等于全契约安全”会误判。第四车道与 skill 依赖自评与自觉。L1/L2/L3 无统一 orchestratorskills 是 Markdown 指令模型可误触发或跳站。.ai/skills/若与 IDE 侧副本漂移治理层会先失同步。第五治理 meta 层需要跟人一起演进。契约、事故、目录职责变了docs、doc-sync-rules、skills 都要跟改。AI 改代码快于改规则时旧 skill 会误导新 agent——这是自指维护问题。第六强制规则不能无限膨胀。只有会导致集成事故的漂移适合 error 级拦截其余内部文档若全硬拦小改动会被拖慢大家会更倾向[skip docs-sync]类绕过。所以这套框架的重点不是“自动化一切”而是最危险的契约漂移机器化需求与流程用可交接协议补足明确哪些仍靠人审。如何验证有效性不应只靠主观感受应同时看结果指标和过程信号。结果指标是否少出事契约改动是否能被check_docs_sync.py和 CI 拦住。文档是否仍出现死路径 / 错误 topiccheck_docs_facts.py是否频繁报回归。L3 类 PR 是否稳定带有tests/acceptance/变更acceptance 是否被提升而非留在本地。PR 描述是否沉淀关键设计决策、风险、测试结论和门槛自查。新成员或新 agent 是否能通过docs/README.md和AGENTS.md快速找到入口。后续需求是否能从docs/api/、docs/internals/、docs/ops/读到稳定事实而不是翻旧 feature 的临时设计。高风险改动是否在 brief、acceptance、technical_design 阶段提前暴露而不是到 review 或线上集成时才暴露。过程信号流程是否真在被走PR 里 L1 / L2 / L3 车道分布是否合理L3 强信号改动是否被压成 L1。[skip docs-sync]使用频率是否异常升高。promote_acceptance之后是否仍有大量 undefined step 长期残留。skill 与 doc-sync-rules 是否落后于代码规则误导 agent 的 incident 数。若结果指标变好、过程信号无系统性绕过说明流程在降低协调成本若只有文档结构变漂亮、L3 PR 仍常零 acceptance说明协议层尚未落地。演进方向下列补强与当前架构一致按投入/收益排序供后续迭代——不代表仓库已全部具备PR 模板 CI 读 PR bodyL3 强信号 diff 应要求声明车道并启发式检查是否带有 acceptance / migration 等对应产物。按事故面扩展 doc-sync优先 recall pipeline 等已文档化、集成会炸的面不一次性全拦。check_config_contracts.pyCI把config-contract-sync的值层核对脚本化。flow-guardopt-in 硬模式L3 feature 开发可选启用 pre-commit gate不拖死 L1 日常 commit。skill 严格单源禁止 IDE 侧维护与.ai/skills/平行的实目录副本。总结toLink-Rag 搭建docs/架构、spec-as-test 流程和自建 skills不是为了把 Vibe Coding 变成传统重流程开发。恰恰相反它是在承认 AI 生成速度极快的前提下为这种速度补上分层工程约束。docs/负责长期事实和公共契约并由 doc-sync / doc-facts 在机器层守住最危险的漂移。.specs/负责开发期临时决策和可执行验收合并前通过 PR 与tests/acceptance/沉淀长期价值合并后清理本地目录。自建 skills 负责把大模型限制在正确阶段、正确边界和正确输出里——这是协议层需要与机器层分开评估。通用 skill 可以提高 agent 的基础能力但项目级开发流必须吸收项目自己的契约、历史事故、目录职责和交付门槛。只有这样大模型才不只是一个会写代码的助手而是能在高速迭代中被分层约束、被验证、被交接的工程参与者——其中“被约束”的程度取决于你走的是机器层还是协议层。LinkRag开箱即用的企业级 RAG 后端基于 FastAPI 的检索增强后端负责文档解析、智能分块与向量化索引。 三路混合召回稠密稀疏重排recall10 稳定 0.9 多格式文档解析支持标题层级与结构化分块⚡ 全链路异步流水线工程化可直接用于生产体验 linkrag.cn源码 github.com/ql-link/LinkRag