Community编程与开发github.com

约束驱动开发

将项目的质量门槛确立为一份书面契约,并阻止智能体悄然降低标准。通过访谈了解用户关心的维度,当用户心中无数时提供合理的默认阈值,将所有内容记录在 CONSTRAINTS.md 中,并监控差异中是否出现标准降低——例如新增的 @ts-ignore 或 eslint-disable 抑制、跳过或删除的测试、被剥离的断言、未实现的存根、被调低的阈值等。

约束驱动开发 是什么?

约束驱动开发是一款专注于为 AI 驱动项目确立并维护“足够好到可以发布”的明确质量门槛的技能。它通过引导式访谈,在性能、测试覆盖率、安全性和可访问性等维度上帮助用户定义量化标准,并为不知道该找什么数字的用户提供推断合理的默认值。该技能会自动生成一份 CONSTRAINTS.md 文件——这份文件不仅超越了单个会话的生命周期,其“阈值”、“检查依据的命令”和“运行阶段”表格还使其可被自动验证。此外,它还包括了“区间守卫”,即在代码审查期间检查五项关于标准侵蚀的常见手法(如阈值滑动、测试简化、抑制注释、未完成的存根以及未经协商的例外),同时还提供了最低标准(禁止抑制、跳过测试和硬编码密钥),以确保即使在非交互模式下运行,质量也不会下降。它适用于 Claude Code、Cursor 和 Codex 等平台,并能无缝功能地集成到各种构建、验证和发布周期中。

兼容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/addyosmani/agent-skills/tree/main/skills/constraint-driven-development

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

约束驱动开发 是做什么的?

概述

本包中的其他技能描述了理想状态的样子。code-review-and-quality 为你提供了五个维度。test-driven-development 为你提供了一个循环。security-and-hardening 为你提供了一个威胁列表。所有这些都存在于智能体阅读的文本中,它们可能被遵循也可能不被遵循,并且没有一项能跨越会话的边界而持久存在。

这项技能的产生结果则不同:一份关于本项目质量门槛的书面记录,包含数字,它比一次对话存活得更久,并且可以被自动化检查。

为什么这很重要?当你自己编写代码时,阅读它就能告诉你代码质量如何。一个智能体一下午的产出比你一周能读的还多,因此判断力必须从你的头脑中转移到围绕循环运行的检查中去。这些检查需要存在,它们需要你真正选择的数字,并且它们需要在足够接近工作的地方触发,以便智能体自行修复其输出。

规范驱动开发告诉你构建什么。测试驱动开发证明它能工作。约束驱动开发则定义了“足够好到可以发布”意味着什么,在任何人开始在拉取请求中争论之前。

何时使用

在以下情况应用此技能:

  • 开始一个项目或一个重要的功能,并且没有书面记录的质量门槛
  • 用户要求“设置约束”、“添加质量门”、“定义我们的标准”或“阻止智能体产出垃圾”
  • 一个智能体正在产生大量的、无人逐行阅读的代码
  • CI 有检查,但没人能说出哪些会阻止合并,哪些只是装饰
  • 覆盖率、性能或可访问性数字在每个 PR 都会引发争论,而不是一次性决定
  • 你即将运行 /build auto 或任何自主循环,而介于它和主分支之间的唯一保障是智能体自己编写的测试套件

何时不要使用:

  • 项目已经存在 CONSTRAINTS.md 并且用户没有在修改它——此时应该阅读并遵循它
  • 一次性脚本、临时原型或快速实验
  • 用户想要立即进行代码审查(code-review-and-quality)或建立 CI 流水线(ci-cd-and-automation)
  • 预期生命周期只有两周的产品市场适配前代码——此时最低标准仍然值得,但其余部分则不必

加载约束

访谈需要一个实时的用户。不要在非交互式上下文中运行它(例如 CI、/loop、自主运行)。如果在这些环境中缺少约束,应用下面的最低标准,记录此操作,并将剩余部分标记给人类处理。

流程

步骤 1:在询问前先检测

永远不要问你可以从文件里读到的东西。在问第一个问题之前,先收集以下信息:

信息项查阅位置
语言和技术栈package.json, pyproject.toml, go.mod, Cargo.toml
测试运行器开发依赖项, test 脚本,现有的测试文件
现有的 lintereslint.config.*, biome.json, .ruff.toml
当前的覆盖率coverage/ 输出,或者运行一次测试套件
CI 配置.github/workflows/, .gitlab-ci.yml
智能体框架.claude/, .codex/, AGENTS.md

用两行报告你发现的结果,然后只询问剩余的部分。

步骤 2:四个问题,每个都有默认值

遵循 interview-me 中的“一次一个问题”原则,但有一个变化:这里的每个问题都有一个默认值,因此“我不知道”也是一个完整的答案,仍然能生成可工作的配置。

Q1:除了最低标准,你希望强制执行以下哪些项?
    (a) 新代码的测试覆盖率
    (b) 安全扫描
    (c) 性能预算
    (d) 可访问性
    (e) 架构边界
推测:(a) 和 (b)——你已经有了测试运行器,并且正在处理用户输入。
不确定时的默认值:(a) 和 (b)。
说出每个选择带来的成本:(c) 和 (d) 需要一个正在运行的 URL,(e) 需要编写一个规则文件。
Q2:当智能体在任务执行过程中某项检查失败时,应该阻止还是仅仅警告?
推测:阻止。因为你是无人值守地运行智能体,而一个无人阅读的警告就只是警告而已。
不确定时的默认值:对于最低标准进行阻止,对于其他所有项,在前两周内进行警告。
Q3:你心中有目标数字,还是希望我测量你当前的状况并维持该标准?
推测:测量。大多数团队没有数字,而一个凭空捏造的数字会被忽略。
不确定时的默认值:测量并维持。请参见下面的“棘轮”机制。
Q4:在智能体将工作交还给你之前,你能容忍的最慢检查是多长时间?
推测:大约 90 秒。再长的话你就会停止运行它。
不确定时的默认值:任务结束时 90 秒,CI 中不限制。

总共四个问题。一个包含十二个问题的引导过程只会产生一份没人理解的配置和一个后悔开始的用户。

步骤 3:编写 CONSTRAINTS.md

在仓库根目录下创建一份文件。任何框架上的任何智能体都能读取它,并且对它的任何修改都会出现在代码审查中,这本来也是它应该出现的地方。

# 约束

最后审查日期:2026-08-08 由 @addy 完成

## 最低标准(始终强制执行,无需设置)

- 不允许新增抑制注释:`@ts-ignore`, `eslint-disable`, `# noqa`, `# type: ignore`
- 不允许未实现的存根:`throw new Error("Not implemented")`,空的 `catch {}`
- 不允许跳过或删除测试,除非在提交信息中说明了原因
- 不允许在源代码中包含密钥
- 此文件不允许为了通过某项更改而被弱化

## 用数字强制执行

| 维度 | 规则 | 检查依据 | 运行阶段 |
|-----------|------|-----------|---------|
| 类型 | 零类型错误 | `tsc --noEmit` | 每次编辑后 |
| 代码风格 | 零错误,使用我们的配置 | `biome check` | 每次编辑后 |
| 密钥 | 源代码中无密钥 | `gitleaks detect --redact` | 每次编辑后 |
| 覆盖率 | 变更行的覆盖率 ≥ 80% | `vitest run --coverage` + git diff | 任务结束时,CI 中 |
| 安全:代码 | 无高级别发现 | `semgrep scan --config p/default` | CI |
| 安全:依赖 | 无高或更高级别 | `osv-scanner scan source -r .` | CI |
| 可访问性 | 零严重或重要问题 | `axe $PREVIEW_URL --tags wcag2a,wcag2aa,wcag21aa` | 预览部署时 |
| 性能 | LCP ≤ 2500ms, CLS ≤ 0.1 | `lighthouse $PREVIEW_URL --output=json` | 预览部署时 |

每一行都指明了产生裁决结果的命令。一个没有数字且此列中没有命令的维度只是一个愿望,而不是一个约束。

## 已测量,尚未强制执行

| 指标 | 当前值 | 方向 |
|--------|-------|-----------|
| 项目整体覆盖率 | 62.4% | 不得下降 |
| 包体积 (main 分支) | 184 kB | 不得增长 |

## 例外情况

| ID | 规则 | 路径 | 原因 | 负责人 | 过期时间 |
|----|------|------|--------|-------|---------|
| W1 | `no-explicit-any` | `src/legacy/**` | 重构工作由 ENG-441 跟踪 | @addy | 2026-11-01 |

然后在 AGENTS.md 和 CLAUDE.md 中添加一行:在编写代码前阅读 CONSTRAINTS.md。不要为了通过某项更改而弱化它。

步骤 4:安装每个维度所需的内容

选择一个维度意味着要安装一些东西。不要只给用户一个数字而没有实现机制,也不要当存在事实上的标准工具时自己发明一个检查器——这里列出的工具之所以被选中,是因为生态系统中的其他所有东西都以它们的规则格式和阈值为目标,因此团队现有的配置可以继续工作。

维度工具安装方式运行命令门控条件
类型 (TS)tsc已存在tsc --noEmit任何错误
类型 (Python)mypypip install mypymypy .任何错误
代码风格你现有的配置已存在eslint . / biome check / ruff check任何错误
覆盖率 (JS)你的测试运行器已存在vitest run --coverage (或 jest --coverage)变更行的覆盖率
覆盖率 (Python)pytest-covpip install pytest-covpytest --cov --cov-report=lcov同上
安全:代码Semgreppipx install semgrepsemgrep scan --config p/default --config p/owasp-top-ten任何高级别发现
安全:密钥gitleaksbrew install gitleaksgitleaks detect --redact --no-banner任何发现
安全:依赖osv-scannerbrew install osv-scannerosv-scanner scan source -r .高级别或更高
性能:页面Lighthousenpm i -D lighthouselighthouse $URL --output=json --quietLCP, CLS, 性能分数
性能:包体积size-limitnpm i -D size-limitsize-limit --json每项入口的字节预算
可访问性axe-corenpm i -D @axe-core/cliaxe $URL --tags wcag2a,wcag2aa,wcag21aa零严重或重要问题
架构dependency-cruisernpm i -D dependency-cruiserdepcruise --validate src任何违规
断言质量Strykernpm i -D @stryker-mutator/corestryker run --mutate <changed files>变异分数

如果你跳过它们,有五件事会给你带来麻烦:

  1. gitleaks 的 --redact 参数不是可选的。 如果没有它,匹配到的密钥会落入智能体的转录文本中,这就是泄漏的密钥最终会出现在日志、摘要或提交信息中的原因。请报告规则和位置,永远不要报告值。
  2. Lighthouse 和 axe 需要一个 URL。 它们只能针对正在运行的应用程序工作,因此它们属于运行时阶段,针对预览部署或你先启动的本地服务器。如果项目没有可供访问的 URL(例如 CLI 工具、库、桌面应用),请说明情况并放弃该维度,而不是发明一个无法运行的检查。
  3. 将代价高的检查限制在差异范围内。 对整个仓库运行 stryker run --mutate 需要数小时并最终会被关闭;而仅针对变更所影响的文件运行则需要不到一分钟。Semgrep 也是如此,它可以接受一个路径列表。
  4. 覆盖率不需要第二次运行测试套件。 读取你的套件已经生成的 lcov 覆盖率文件,并将其与 git diff 的结果进行交集运算。为了得到一个数字而运行两次测试套件是让人们讨厌这个做法的捷径。
  5. Semgrep 的注册表规则可以免费运行;但在重新分发前请检查许可证。 如果这关系到你的法务团队,opengrep 是一个即插即用的替代方案,具有相同的规则格式和 JSON 输出。

将每个工具添加到项目自己的脚本中,以便无需智能体即可重现:

{
  "scripts": {
    "check:fast": "tsc --noEmit && eslint . && gitleaks detect --redact --no-banner",
    "check:task": "npm run check:fast && vitest run --coverage",
    "check:full": "npm run check:task && semgrep scan --config p/default && osv-scanner scan source -r ."
  }
}

这个映射关系比工具本身更重要。check:fast 是在每次编辑后运行的,check:task 在智能体认为任务完成时运行,check:full 在 CI 中运行。

这些命令现在存在于两个地方——CONSTRAINTS.md 的“检查依据”列和这些脚本中。CONSTRAINTS.md 是权威来源:它为每个命令附带了理由,并且会出现在代码审查中。脚本只是方便使用的包装器,必须完全镜像它,而不是第二个真相来源;如果它们开始偏离,以文件为准。

步骤 5:将其连接到开发生命周期

最大的错误是在所有地方运行所有检查。一个拖慢智能体的检查会被关闭,而一个人们关闭了的门禁比没有门禁更糟糕,因为标准看起来仍然存在。

阶段命令运行内容预算
构建/build类型检查,代码风格,密钥检查,最低标准5 秒以内,仅限变更文件
验证/test相关测试,变更行覆盖率90 秒以内
审查/review所有检查,加上下面的守卫几分钟
发布/ship方向性检查,无回归CI

两条使得这一切可容忍的规则:

  1. 限定到差异范围内。 检查此变更影响的代码行,而不是整个仓库。变更行的覆盖率是智能体可以改变的数字;项目整体覆盖率则是它继承来的。
  2. 成本决定位置。 任何超过几秒的检查都应移出编辑循环。对整个仓库进行变异测试需要数小时;仅针对变更所影响的文件则需要不到一分钟,这决定了检查是人们会运行还是不会运行。

步骤 6:守卫门槛本身

有人会指出,如果智能体既编写代码又编写检查,那么这些检查证明不了什么。这句话说对了一半,并且值得通过工程手段来解决。

智能体不会精心设计巧妙的漏洞。它们遇到红色的检查项,然后选择通往绿色的最便宜路径。在代码审查时,留意差异中的这五种行为:

  1. 阈值移动了。 预算被降低了,严重等级被降低了,检查项被从快速阶段移除了。将 CONSTRAINTS.md 与其在分支点时的状态进行比较。
  2. 测试变容易了。 添加了 .skip,删除了测试文件,从保留的测试中删除了断言。
  3. 检查器被静音了。 新增了 @ts-ignore 或 eslint-disable。有四种抑制操作尤其值得注意,因为它们会关闭你所依赖的检查:istanbul ignore 会使代码不被纳入覆盖率统计而非进行测试,Stryker disable 会隐藏一个幸存的变异体,nosemgrep 和 gitleaks:allow 对安全发现的作用也是如此。
  4. 工作未完成。 一个抛出异常的存根,一个将失败转化为静默的空 catch 块,一个本应是实现的地方却放着一个 TODO。
  5. 出现了一个例外。 例外表格中出现了一个没有人讨论过的新行。

这些都不需要比 git diff 更复杂的工具。收紧标准应该是静默的;放松标准则应该大声宣告。

与编号的维度不同,最低标准没有自己的事实上的工具,因此被要求执行它的智能体倾向于从头编写一个检查器,而两个智能体会写出两个不同的。作为参考,这五项检查的参考实现随本技能一同提供,位于 references/floor-guard.md(限定于差异范围,退出代码为 0/1/2,模式可适应不同生态系统)。请改编它,而不是重新发明它,原因与每个维度都命名一个事实上的工具相同:这样机制在所有运行中和所有技术栈上都是相同的。

并非所有检查都同等循环论证。 根据一个问题对它们进行排序:智能体能否通过编写无法工作的代码来让这个检查通过?

  • 外部检查——axe-core 编码了 WCAG 标准,osv-scanner 读取漏洞数据库,Lighthouse 测量真实的浏览器行为。智能体无法与这些争论。
  • 项目级检查——你的代码风格规则,你的层边界。人类拥有这个文件。
  • 套件级检查——你自己的测试。最有用,并且是唯一真正循环论证的检查。

一个门槛

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

addyosmani/agent-skills

Prepares production launches. Use when preparing to deploy to production, or when asking what needs to be in place before shipping. Use when you need a pre-launch checklist, when setting up monitoring, when planning a staged rollout, or when you need a rollback strategy.

addyosmani/agent-skills

Builds production-quality, accessible, responsive user-facing UIs. Use when building or modifying interfaces and pages, creating components, implementing layouts, meeting WCAG accessibility requirements, managing state, or when the output needs to look and feel production-quality rather than AI-generated.

addyosmani/agent-skills

Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend.

addyosmani/browser-testing-with-devtools

Tests in real browsers via Chrome DevTools MCP. Use when building or debugging anything that runs in a browser. Use when you need to inspect the DOM, capture console errors, analyze network requests, profile performance, or verify visual output with real runtime data. Requires the chrome-devtools MCP server to be configured.

addyosmani/ci-cd-and-automation

Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines. Use when you need to automate quality gates, configure test runners in CI, or establish deployment strategies.

addyosmani/code-review-and-quality

Conducts multi-axis code review. Use before merging any change. Use when reviewing code written by yourself, another agent, or a human. Use when you need to assess code quality across multiple dimensions before it enters the main branch.

addyosmani/code-simplification

Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read, maintain, or extend than it should be. Use when reviewing code that has accumulated unnecessary complexity.

addyosmani/debugging-and-error-recovery

Guides systematic root-cause debugging. Use when tests fail, builds break, behavior doesn't match expectations, or you encounter any unexpected error. Use when you need a systematic approach to finding and fixing the root cause rather than guessing.

addyosmani/deprecation-and-migration

Manages deprecation and migration. Use when removing old systems, APIs, or features. Use when migrating users from one implementation to another. Use when deciding whether to maintain or sunset existing code.

addyosmani/documentation-and-adrs

Records decisions and documentation. Use when making architectural decisions, changing public APIs, shipping features, or when you need to record context that future engineers and agents will need to understand the codebase.

addyosmani/doubt-driven-development

Subjects every non-trivial decision to a fresh-context adversarial review before it stands. Use when correctness matters more than speed, when working in unfamiliar code, when stakes are high (production, security-sensitive logic, irreversible operations), or any time a confident output would be cheaper to verify now than to debug later.

addyosmani/git-workflow-and-versioning

Structures git workflow practices. Use when making any code change. Use when committing, branching, resolving conflicts, or when you need to organize work across multiple parallel streams.

addyosmani/idea-refine

Refines raw ideas into sharp, actionable concepts through structured divergent and convergent thinking. Use when an idea is still vague, when you need to stress-test assumptions before committing to a plan, or when you want to expand options before converging on one. Triggers on "ideate", "refine this idea", or "stress-test my plan".

addyosmani/incremental-implementation

Delivers changes incrementally. Use when implementing any feature or change that touches more than one file. Use when you're about to write a large amount of code at once, or when a task feels too big to land in one step.

addyosmani/interview-me

Extracts what the user actually wants instead of what they think they should want. Achieves this through one-question-at-a-time interview until ~95% confidence about the underlying intent. Use when an ask is underspecified ("build me X" without "for whom" or "why now"), when the user explicitly invokes ("interview me", "grill me", "are we sure?", "stress-test my thinking"), or when you catch yourself silently filling in ambiguous requirements before any plan, spec, or code exists.

addyosmani/observability-and-instrumentation

Instruments code so production behavior is visible and diagnosable. Use when adding logging, metrics, tracing, or alerting. Use when shipping any feature that runs in production and you need evidence it works. Use when production issues are reported but you can't tell what happened from the available data.

addyosmani/performance-optimization

Optimizes application performance. Use when performance requirements exist, when you suspect performance regressions, or when Core Web Vitals or load times need improvement. Use when profiling reveals bottlenecks that need fixing.

addyosmani/planning-and-task-breakdown

Breaks work into ordered tasks. Use when you have a spec or clear requirements and need to break work into implementable tasks. Use when a task feels too large to start, when you need to estimate scope, or when parallel work is possible.

addyosmani/security-and-hardening

Hardens code against vulnerabilities. Use when handling user input, authentication, data storage, or external integrations. Use when building any feature that accepts untrusted data, manages user sessions, or interacts with third-party services.

addyosmani/source-driven-development

Grounds every implementation decision in official documentation. Use when you want authoritative, source-cited code free from outdated patterns. Use when building with any framework or library where correctness matters.

相关技能