用途
约束驱动开发用于为一个项目确立书面的质量线,并防止 AI agent 在开发过程中悄悄降低它。本技能包里的其他技能描述的是“好”长什么样,例如代码审查给出五个轴、测试驱动开发给出一个循环、安全加固给出一份威胁清单,但这些都活在文字里,agent 读了可能照做也可能不照做,而且没有一个能活过会话结束。本技能产出的是别的东西:本项目质量线的书面记录,带数字,能活过对话,并且可以被机械地检查。
背后的原因:当你亲手写代码时,读代码就能告诉你它好不好。一个 agent 一个下午写下的代码超出你一周能读完的量,于是判断就从你的脑子里挪到了围绕循环运行的检查里。这些检查需要存在,需要用到你真正选过的数字,而且需要离工作足够近,让 agent 能修好自己的产出。Spec-driven development 说清楚要构建什么,Test-driven development 证明它能工作,Constraint-driven development 定义“好到可以发布”意味着什么——在任何人在 pull request 里为此争吵之前。
何时使用
在以下情况应用这个技能:启动一个项目或一个重要功能,而没有任何质量线被写下来;用户要求 set up constraints、add quality gates、define our standards 或 stop the agent shipping junk;agent 在产出没人逐行阅读的体量;CI 有检查,但没人说得清哪些会阻塞合并、哪些只是摆设;覆盖率、性能或无障碍性的数字在每个 PR 上被争论,而不是被一次性决定;你正准备运行 /build auto 或任何自主循环,而它和 main 之间唯一的屏障是一套 agent 自己写的测试。
何时不要使用:项目已经有 CONSTRAINTS.md 而用户并不想改它——去读它并遵循它;一次性脚本、spike、用完即弃的原型;用户现在就要 code review 或要搭 CI pipeline;product-market fit 之前的代码,预期寿命两周——下面的 floor 仍然值得,其余的不值得。
主要能力
该技能通过一场需要活用户的访谈来加载约束,不要在非交互上下文中运行它(CI、/loop、自主运行)。如果你在其中之一里且约束缺失,套用下面的 Floor,注明你这样做了,并把剩下的标记出来交给人来处理。
流程分为七步。
Step 1:先检测,再提问。能读到的东西绝不要问。在第一个问题之前,先收集语言与技术栈(package.json、pyproject.toml、go.mod、Cargo.toml)、测试 runner(dev 依赖、test script、已有的测试文件)、已有的 linter(eslint.config.*、biome.json、.ruff.toml)、当前覆盖率(coverage/ 输出,或把套件跑一遍)、CI(.github/workflows/、.gitlab-ci.yml)、Agent harness(.claude/、.codex/、AGENTS.md)。用两行汇报你发现的东西,然后只问剩下的。
Step 2:四个问题,每个都带默认值。遵循 interview-me 的一次一问纪律,只有一个变化:这里的每个问题都有默认值,所以 I don't know 也是一个完整的答案,并且仍能产出可用的配置。Q1 询问除 floor 外还要强制哪些维度(测试覆盖率、安全扫描、性能预算、无障碍性、架构边界),猜测为 (a) 和 (b),不确定时默认 (a) 和 (b),并说明每个选择的成本。Q2 询问检查失败时是阻塞还是警告,猜测为阻塞,不确定时默认 floor 阻塞、其余前两周警告。Q3 询问是否有目标数字,还是测量当前值并守住,猜测为测量,不确定时默认测量并守住。Q4 询问能容忍的最慢检查时间,猜测约 90 秒,不确定时默认任务结束 90 秒、CI 不限。止步于四个问题。
Step 3:写出 CONSTRAINTS.md。仓库根目录放一个文件,任何 harness 上的任何 agent 都能读它,而它的一次变更会出现在 review 里。文件包含 Floor(始终强制、无需设置)、Enforced with numbers(带数字强制的维度表,每行都写明产生裁决的命令)、Measured, not yet enforced(仅测量的指标,记录今天的值和方向)、Exceptions(例外表,含 ID、规则、路径、原因、owner、到期日)。然后在 AGENTS.md 和 CLAUDE.md 各加一行:Read CONSTRAINTS.md before writing code. Do not weaken it to make a change pass.
Step 4:为每个维度安装它需要的东西。选择一个维度就意味着安装一些东西。别给用户留下一个数字却没有机制,也别在有事实标准工具时凭空发明你自己的 checker。技能给出了维度到工具的映射表,包括类型(tsc、mypy)、Lint(已有配置)、覆盖率(vitest/jest、pytest-cov)、安全代码(Semgrep)、安全 secrets(gitleaks)、安全依赖(osv-scanner)、性能页面(Lighthouse)、性能 bundle(size-limit)、无障碍性(axe-core)、架构(dependency-cruiser)、断言质量(Stryker)。并提醒五件会反咬一口的事:gitleaks 的 --redact 不是可选的;Lighthouse 和 axe 需要一个 URL;把贵的检查限定在 diff 上;覆盖率不需要第二次 test run;Semgrep 注册表规则再分发前先看 licence。把每一个都加进项目自己的 script,让它在没有 agent 的情况下也可复现,例如 check:fast、check:task、check:full。
Step 5:把它接到生命周期上。最大的单一错误就是在所有地方运行所有东西。一个会拖慢 agent 的检查会被关掉,而被人关掉的 gate 比没有 gate 更糟。技能给出阶段到命令的映射:BUILD 阶段运行类型、lint、secrets、floor,预算 5 秒内只查变更文件;VERIFY 阶段运行相关测试、变更行的覆盖率,预算 90 秒内;REVIEW 阶段运行全部外加 guards,以分钟计;SHIP 阶段做方向检查,不许回退。两条规则:限定到 diff;成本决定位置。
Step 6:守护质量线本身。Agent 不会精心构造巧妙的漏洞,它们撞上一个红色检查,然后走通往绿色的最便宜的路。在 review 时盯住 diff 里的五个动作:阈值动了、测试变简单了、checker 被静默了、工作没完成、出现了例外。这些都不需要 git diff 之外的任何工具。收紧质量线应当是无声的,放松它应当是响亮的。技能还指出不是所有检查都同样循环自证,按外部、项目、套件排序,检查至少存在一个外部约束。
Step 7:没有数字时用 Ratchet(棘轮)。在一个 62% 的代码库上设 80% 覆盖率,你会得到一个永远红色的 build,然后是一个学会无视红色 build 的团队。另一种做法不需要任何决策:记录你现在在哪里,然后拒绝变差。把它放进 Measured, not yet enforced 表,带上今天的数字和一个方向。每次检查都对照记录值,而不是对照愿景。当数字变好时,更新它;当数字下滑时,那就是 finding。
使用方式
该技能以访谈方式加载约束,需要活用户参与,不要在 CI、/loop、自主运行等非交互上下文中运行。流程为:先检测项目现状,再问四个带默认值的问题,然后写出 CONSTRAINTS.md,为每个维度安装对应工具,把检查接到生命周期各阶段,守护质量线本身,并在没有数字时采用棘轮策略。技能还提供了合理默认值表,例如变更行的覆盖率 ≥ 80%、项目覆盖率取今天的值不许下降、Mutation score 起步 ≥ 60%、依赖漏洞 high 及以上不许有、LCP ≤ 2500 ms、CLS ≤ 0.1、无障碍性 axe 的 critical 或 serious 违规为零、例外寿命 90 天、Ratchet 容差 0.5%。升级路径分三个牙齿强度:仅书面、脚本化、工具化,多数项目应当止步于 2。第一次运行可以只有 floor。
适用场景
适用于启动新项目或重要功能、需要设定质量门禁、agent 产出体量超出人工逐行阅读能力、CI 检查职责不清、质量数字反复争论、准备运行自主循环等场景。
限制
不要在非交互上下文中运行访谈;项目已有 CONSTRAINTS.md 且用户不想改时应直接遵循;一次性脚本、spike、用完即弃的原型不适用;用户现在就要 code review 或搭 CI pipeline 时不适用;product-market fit 之前的代码预期寿命两周,只有 floor 值得。技能还列出了常见合理化借口和危险信号,用于判断是否误用。验证条件包括 CONSTRAINTS.md 存在且每个数字都有理由、Floor 被强制执行且当前代码库无需改动即可通过、每个维度都有安装好的工具和今天就能运行的命令、每条约束都写明运行在哪、至少一条约束是外部的、仅测量的指标记录了今天的值和方向、例外有 owner 和到期日、AGENTS.md 或 CLAUDE.md 指向该文件、在当前分支上试运行一次没有用户不认可的失败。