Community라이팅 & 에디팅github.com

realshahriya/mukhon-constraint-driven-dev

프로젝트 품질 기준을 문서화된 계약으로 수립하고, 에이전트가 조용히 기준을 낮추는 것을 차단합니다. 사용자와 어떤 품질 차원이 중요한지 인터뷰하고, 사용자가 숫자를 모를 때 합리적인 기본 임계값을 제공하며, 모든 것을 CONSTRAINTS.md에 기록하고, 기준이 약화되는 변경 사항(새로운 @ts-ignore 또는 eslint-disable 억제, 테스트 건너뛰기 또는 삭제, 단정문 제거, 미구현 스텁, 임계값 편집)을 감시합니다.

mukhon-constraint-driven-dev란 무엇인가요?

이 스킬은 **Constraint-Driven Development** 프레임워크로, 개발 에이전트가 코드 품질 기준을 임의로 낮추는 것을 방지합니다. 사용자와의 인터뷰를 통해 테스트 커버리지, 보안 스캐닝, 성능 예산, 접근성 등 프로젝트에 중요한 품질 차원을 식별하고, 각 차원에 대해 기본값을 제공합니다. 이후 `CONSTRAINTS.md` 파일을 생성하여 측정 가능한 품질 기준을 명시하고, git diff를 통해 기준이 약화되는 변경(임계값 수정, 테스트 건너뛰기, 억제 주석 추가 등)을 감지합니다. Claude Code, Cursor, Codex 등 다양한 에이전트 플랫폼에서 작동하며, 에이전트가 자율적으로 작업할 때 품질 기준을 유지하는 데 필수적입니다. 이 스킬은 특히 프로젝트 초기 설정, 에이전트가 과도한 코드를 생성할 때, 또는 PR마다 품질 기준이 논쟁될 때 유용합니다.

지원 대상✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/realshahriya/Mukhon-Skill-pack/tree/HEAD/mukhon-constraint-driven-dev

Installed? Explore more 라이팅 & 에디팅 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

제약 조건 기반 개발

개요

이 팩의 다른 스킬들은 '좋은 코드'가 무엇인지 설명합니다. 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)을 원할 때
  • 예상 수명이 2주인 제품-시장 적합성 이전 코드 — 아래의 최소 기준은 여전히 가치 있지만, 나머지는 그렇지 않습니다

제약 조건 로딩

인터뷰는 실시간 사용자가 필요합니다. 비대화형 컨텍스트(CI, /loop, 자율 실행)에서는 실행하지 마세요. 제약 조건이 누락되었고 이러한 컨텍스트에 있다면, 아래의 최소 기준을 적용하고, 그렇게 했음을 기록하며, 나머지는 사람에게 표시하세요.

프로세스

1단계: 묻기 전에 감지하세요

읽을 수 있는 것은 절대 묻지 마세요. 첫 번째 질문 전에 다음을 수집하세요:

항목찾을 위치
언어 및 스택package.json, pyproject.toml, go.mod, Cargo.toml
테스트 러너dev dependencies, test 스크립트, 기존 테스트 파일
기존 린터eslint.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: 에이전트가 작업 중일 때 검사가 실패하면, 차단해야 합니까 아니면 경고해야 합니까?
추측: 차단. 무인 에이전트를 실행 중이며 아무도 읽지 않는 경고는 경고가 아닙니다.
확실하지 않을 경우 기본값: 처음 2주 동안은 최소 기준에 대해서는 차단하고, 나머지는 경고.
Q3: 목표 숫자가 있습니까, 아니면 현재 위치를 측정하고 그 선을 유지해야 합니까?
추측: 측정. 대부분의 팀은 숫자가 없으며, 발명된 숫자는 무시됩니다.
확실하지 않을 경우 기본값: 측정하고 유지. 아래 "래칫" 참조.
Q4: 에이전트가 작업을 반환하기 전에 참을 수 있는 가장 느린 검사는 얼마입니까?
추측: 약 90초. 더 길면 실행을 중단할 것입니다.
확실하지 않을 경우 기본값: 작업 종료 시 90초, CI에서는 무제한.

네 가지로 멈추세요. 열두 가지 질문으로 구성된 인테이크는 아무도 이해하지 못하는 구성과 시작을 후회하는 사용자를 만듭니다.

3단계: CONSTRAINTS.md 작성

저장소 루트에 하나의 파일. 모든 도구의 모든 에이전트가 읽을 수 있으며, 변경 사항은 리뷰에서 확인할 수 있습니다.

# 제약 조건

마지막 검토: 2026-08-08 by @mukhon-core

## 최소 기준 (항상 적용, 설정 불필요)

- 새로운 억제 주석 없음: `@ts-ignore`, `eslint-disable`, `# noqa`, `# type: ignore`
- 미구현 스텁 없음: `throw new Error("Not implemented")`, 빈 `catch {}`
- 커밋 메시지에 사유 없는 테스트 건너뛰기 또는 삭제 없음
- 소스 코드에 비밀 정보 없음
- 변경 사항을 통과시키기 위해 이 파일이 약화되지 않음

## 숫자로 적용됨

| 차원 | 규칙 | 검사 도구 | 실행 시점 |
|-----------|------|-----------|---------|
| 타입 | 타입 오류 0개 | `tsc --noEmit` | 모든 편집 시 |
| 린트 | 구성에서 오류 0개 | `biome check` | 모든 편집 시 |
| 비밀 정보 | 소스 코드에 비밀 정보 없음 | `gitleaks detect --redact` | 모든 편집 시 |
| 커버리지 | 변경된 라인 ≥ 80% 커버 | `vitest run --coverage` + git diff | 작업 종료, CI |
| 보안: 코드 | 높은 수준 발견 사항 없음 | `semgrep scan --config p/default` | CI |
| 보안: 종속성 | 높음 이상 없음 | `osv-scanner scan source -r .` | CI |
| 접근성 | 치명적 또는 심각 0개 | `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에서 추적 | @mukhon-core | 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치명적 또는 심각 0개
아키텍처dependency-cruisernpm i -D dependency-cruiserdepcruise --validate src모든 위반
단정문 품질Strykernpm i -D @stryker-mutator/corestryker run --mutate <변경된 파일>변이 점수

건너뛰면 당신을 물어뜯을 다섯 가지:

  1. gitleaks의 --redact는 선택 사항이 아닙니다. 이것 없이 일치하는 비밀 정보가 에이전트의 기록에 남게 되어, 유출된 키가 로그, 요약 또는 커밋 메시지에 포함될 수 있습니다. 규칙과 위치를 보고하고, 값을 절대 보고하지 마세요.
  2. Lighthouse와 axe는 URL이 필요합니다. 실행 중인 앱에 대해서만 작동하므로, 미리보기 배포 또는 먼저 시작한 로컬 서버에 대한 런타임 단계에 속합니다. 프로젝트에 접속 가능한 URL이 없으면(CLI, 라이브러리, 데스크톱 앱) 그렇게 말하고 차원을 삭제하세요. 실행할 수 없는 검사를 발명하지 마세요.
  3. 비용이 많이 드는 것은 diff로 범위를 한정하세요. 전체 저장소에 대해 stryker run --mutate를 실행하면 몇 시간이 걸려 꺼지게 됩니다. 변경이 닿은 파일에 대해서는 1분 미만이 소요됩니다. 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/build타입, 린트, 비밀 정보, 최소 기준5초 미만, 변경된 파일만
VERIFY/test관련 테스트, 변경된 라인의 커버리지90초 미만
REVIEW/review모든 것, 아래의 보호 장치 포함몇 분
SHIP/ship방향 검사, 회귀 없음CI

이것을 견딜 수 있게 만드는 두 가지 규칙:

  1. diff로 범위를 한정하세요. 이 변경이 닿은 라인을 확인하고, 전체 저장소를 확인하지 마세요. 변경된 라인의 커버리지는 에이전트가 움직일 수 있는 숫자입니다. 프로젝트 커버리지는 에이전트가 물려받은 숫자입니다.
  2. 비용이 배치를 결정합니다. 몇 초가 넘는 것은 편집 루프 밖으로 이동하세요. 전체 저장소에 대한 변이 테스트는 몇 시간이 걸립니다. 변경이 닿은 파일에 대해서는 1분 미만이 소요되며, 이것이 사람들이 실행하는 검사와 실행하지 않는 검사의 차이입니다.

6단계: 기준 자체를 보호

에이전트가 코드와 검사를 모두 작성한다면, 검사는 아무것도 증명하지 못한다고 누군가 지적할 것입니다. 반은 맞고, 엔지니어링으로 해결할 가치가 있습니다.

에이전트는 교묘한 허점을 만들지 않습니다. 빨간색 검사에 부딪히고 녹색으로 가는 가장 저렴한 길을 선택합니다. 리뷰 시간에 diff에서 다음 다섯 가지 움직임을 주시하세요:

  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로 제공됩니다(diff 범위, 종료 코드 0/1/2, 생태계별 적응 가능 패턴). 처음부터 다시 만드는 대신 이것을 적용하세요. 모든 차원이 사실상의 도구를 명명하는 것과 같은 이유입니다: 메커니즘이 실행 및 스택 전반에 걸쳐 동일하도록.

모든 검사가 동등하게 순환적인 것은 아닙니다. 한 가지 질문으로 순위를 매기세요: 에이전트가 작동하지 않는 코드를 작성하여 이 검사를 통과할 수 있습니까?

  • 외부 — axe-core는 WCAG를 인코딩하고, osv-scanner는 취약점 데이터베이스를 읽으며, Lighthouse는 실제 브라우저를 측정합니다. 에이전트는 이에 대해 논쟁할 수 없습니다.
  • 프로젝트 — 당신의 린트 규칙, 당신의 레이어 경계. 사람이 파일을 소유합니다.
  • 스위트 — 당신 자신의 테스트. 가장 유용하며, 유일하게 진정으로 순환적입니다.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬