首頁 / Skills / 開發提效 / 約束驅動開發 Constraint-Driven Development
開發提效

約束驅動開發 Constraint-Driven Development

Addy OsmaniMITSkill 語言: 英文
授權已核對不含腳本中風險
演示真實執行紀錄 · claude-sonnet-5-5 · 2026年10月
Set up quality constraints for our project (fictional example). Facts you may rely on instead of asking: TypeScript 5, Vitest, Biome for lint, GitHub Actions CI, the web app has a preview URL on every PR, AGENTS.md exists, project coverage today is 58.2%, bundle is 212 kB. I know this is normally an interview, so here are my answers: Q1 pick coverage, security scanning and accessibility; Q2 block on the floor, warn on the rest for two weeks; Q3 measure where we are and hold it; Q4 90 seconds. Write CONSTRAINTS.md in the current folder and tell me what to install and wire up. Then check this agent-made diff against the floor and tell me what it violates: ``` --- a/src/cart.test.ts +++ b/src/cart.test.ts @@ - it('rejects negative quantities', () => { expect(() => addItem(-1)).toThrow(); }); + it.skip('rejects negative quantities', () => {}); --- a/src/pay.ts +++ b/src/pay.ts @@ + // @ts-ignore + const total: number = order.total; + try { await charge(total); } catch {} --- a/CONSTRAINTS.md +++ b/CONSTRAINTS.md -| Coverage | Changed lines >= 80% covered | vitest | task end | +| Coverage | Changed lines >= 60% covered | vitest | task end | ```
Skill: constraint-driven-development

I wrote CONSTRAINTS.md in the current folder. There is no AGENTS.md here, so I didn't add the pointer line to it. In your real repo, add this line to AGENTS.md: Read CONSTRAINTS.md before writing code. Do not weaken it to make a change pass.

What's in it

  • Floor (blocks now): no new suppressions, no stubs or empty catch, no skipped or deleted tests, no stripped assertions, no secrets, and no weakening the file itself.
  • Warn until 2026-10-24, then block: types, lint, changed-line coverage ≥ 80%, Semgrep, osv-scanner and axe.
  • Held, not enforced: project coverage stays at 58.2% (0.5% tolerance) and the bundle stays at 212 kB.
  • Budget: checks at task end must finish in 90 seconds. Semgrep, osv-scanner and axe run in CI or on the preview deploy.
  • Performance budget: you didn't pick one, so bundle size is only tracked. I picked 80% for changed-line coverage myself, because you asked to hold the current level and 80% is the skill's default for new code. Say so if you'd rather not have it.

What to install and wire up

You already have tsc, Vitest and Biome.

Tool Install
Coverage npm i -D @vitest/coverage-v8, with the lcov reporter on
gitleaks brew install gitleaks
Semgrep pipx install semgrep
osv-scanner brew install osv-scanner
axe npm i -D @axe-core/cli

Add these scripts to package.json:

"check:fast": "tsc --noEmit && biome check . && 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 --config p/owasp-top-ten && osv-scanner scan source -r ."
  • After each edit: run check:fast, for example from an agent post-edit hook.
  • At task end: run check:task. Compare the lcov it writes against git diff for the 80% changed-line check, without running the tests a second time.
  • In GitHub Actions: run check:full on every PR. After the preview deploy, run axe $PREVIEW_URL --tags wcag2a,wcag2aa,wcag21aa.
  • Floor guard: it needs no installs and only reads the diff. Adapt the reference implementation in the skill's references/floor-guard.md, which I haven't opened.
  • gitleaks: always use --redact, so a leaked key never lands in a transcript.

The diff against the floor

It violates the floor in four places, and one of them also edits the constraints file.

  1. cart.test.ts: it.skip adds a skipped test, and the assertion expect(...).toThrow() is stripped. Nothing in the diff gives a reason in a commit message. The negative-quantity rule is no longer tested.
  2. pay.ts, // @ts-ignore: this is a new suppression. It hides a type problem on order.total that should be fixed.
  3. pay.ts, catch {}: this is an empty catch around charge(total). A failed payment now passes silently and the code carries on as if it worked. This is the most dangerous change in the diff.
  4. CONSTRAINTS.md: the changed-line coverage threshold drops from 80% to 60% in the same change as the code it would excuse. That breaks the rule against weakening the file.

The four edits fit one pattern: the agent hit red checks and took the cheapest route to green. Reject the diff. The agent should restore the test, fix the type of order.total, handle or rethrow the charge error, and put the threshold back at 80%.

Test run with the interview answers given up front, because the Skill does not run its interview in non-interactive mode. The model wrote CONSTRAINTS.md in a temporary folder, listed what to install, and correctly found four floor violations in a sample diff. It chose the 80% coverage figure itself and said so, and it did not open the floor-guard reference file. Nothing was installed.

它做什麼

先做一次簡短的訪談(技術棧、目前基線、已有的檢查、智能體可以改什麼),然後寫出 CONSTRAINTS.md。裡面有從第一天起就攔截的底線(不新增壓制註解、不留樁程式碼或空 catch、不跳過或刪除測試、不移除斷言、不放金鑰、不削弱這份檔案本身),每條都有具名工具與執行時點的數字規則(型別、lint、金鑰、變更行覆蓋率、程式碼與相依套件安全、無障礙),守住今天的數字而不拉高的棘輪,智能體自檢的時間預算,以及附負責人與到期日的例外表。新規則先只警告,並註明改為攔截的日期。它會列出要安裝什麼、要加哪些腳本,還能把智能體的 diff 拿來對照底線審查。

輸出

一份 CONSTRAINTS.md、安裝與接線說明,以及(視需要)對某個 diff 的審查結論。

適合什麼場景

讓智能體寫程式、又希望檢查不能被智能體改寫來換取「綠燈」的團隊。

說明與風險

中風險:Skill 本身只有指令(外加一份底線守衛腳本的參考檔),但它會讓智能體寫 CONSTRAINTS.md,並建議你安裝工具(覆蓋率、gitleaks、Semgrep、osv-scanner、axe)、在專案裡加腳本或鉤子。執行這些指令之前請先看一遍。因為訪談在非互動模式下不會執行,試用時把訪談答案預先給出:它把檔案寫在暫存資料夾,列出要裝的東西(沒有真的安裝),並在範例 diff 裡找出四處違反底線。80% 這個數字是它自己選的,它也明確說了;它沒有開啟底線守衛的參考檔。作者 Addy Osmani,MIT 授權。

SKILL.md 原文套件內共 3 個檔案