Implement a task with TDD (enforced when a test runner exists). Gate: tests pass + stack build check. Runs automatically right after spec. 트리거: \"구현해\", \"이 태스크\".
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Is that skill safe to install?
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
Are you the author of Build?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/snwlee-build)
---
name: build
description: "Implement a task with TDD (enforced when a test runner exists). Gate: tests pass + stack build check. Runs automatically right after spec. 트리거: \"구현해\", \"이 태스크\"."
---
# build
nereus:common 규칙을 따른다. 담당 에이전트: 스택에 따라 backend / frontend / app. 두 스택 이상이면 태스크별로 나눈다.
입출력·상태·게이트·handoff 선언: `assets/runtime-contract.json` — `tests/skills/build-contract.test.ts` 가 이 문서와 대조한다. 이 문서의 게이트 문구를 바꾸면 계약도 같이 바꾼다.
## 1. TDD 가능 환경 판별
`nereus` 훅 라이브러리의 `detectTestRunner`와 같은 기준이다.
- Flutter: `pubspec.yaml`에 `flutter_test` 또는 `test` → `flutter test`
- Spring: `gradlew`/`build.gradle*` → `./gradlew test`, `pom.xml` → `mvn test`
- Node: `package.json` test 스크립트, 또는 vitest/jest 설정 파일
러너가 있으면 **TDD 강제**. 없으면 사용자에게 딱 한 번 묻는다: "테스트 환경이 없습니다. 세팅할까요?" 승인하면 `references/<stack>.md`의 세팅을 적용한다. 거절하면 TDD 없이 진행하고 그 사실("테스트 없음(사용자 선택)")을 대화와 커밋 메시지에 남긴다.
## 2. 태스크 루프
tasks 파일에서 첫 미완료 태스크를 고른다. 태스크마다:
1. **RED**: 완료 조건을 테스트로 옮긴다. 실행해서 **실패를 확인**한다. 실패 출력 첫 줄을 기록한다. 실패하지 않으면 테스트가 잘못된 것이다.
> **Iron Law — NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST.**
> 실패하는 테스트 없이 프로덕션 코드를 쓰지 않는다.
2. **GREEN**: 테스트를 통과시키는 최소 구현. 처음 쓰는 API는 Context7로 확인.
**무엇을 만들지는 `references/laziness-ladder.md` 의 사다리로 정한다** — 버티는 첫 단에서 멈춘다.
사다리는 해답을 줄이는 것이지 문제를 읽는 것을 줄이지 않는다. 충돌하면 TDD 게이트가 이긴다.
3. **REFACTOR**: 중복 제거, 이름 정리. 테스트 다시 실행.
4. tasks 체크박스를 채운다.
`tdd.enforce: "block"` 이면 PreToolUse 가 구현 파일 편집을 **실제로 차단한다**(경고가 아니다).
| 상태 | 구현 파일 편집 |
|---|---|
| RED — 마지막 테스트 실행 실패 | 허용 (지금이 구현 단계) |
| GREEN + 대응 테스트 있음 | 허용 (REFACTOR) |
| GREEN + 대응 테스트 없음 | **차단** — 실패 테스트를 먼저 쓴다 |
| 테스트를 한 번도 안 돌림 | **차단** — RED 를 가정할 수 없다 |
테스트 파일 편집은 언제나 허용된다. 차단되면 정공법은 실패하는 테스트를 쓰고 `run-tests.mjs` 로 돌리는 것이다. 정당한 예외라면 사유를 적어 `.nereus/tdd-override` 를 만든다 — **다음 편집 1회만** 통과하고 파일은 소비된다. 급하면 `tdd.enforce` 를 `"warn"` 으로 낮춘다. 우회했으면 이유를 커밋 메시지 본문에 남긴다.
`tdd.enforce` 가 `"warn"`(기본)이면 PostToolUse 의 `tdd-guard` 훅이 사후 경고만 낸다. 경고를 무시하고 넘어가지 않는다.
설정·마이그레이션·생성 파일(`tdd.exclude`)은 테스트 대상이 아니다.
테스트 실행은 래퍼로 한다. 결과가 작업트리 해시와 함께 `.nereus/evidence.json`에 기록되어 finish 게이트가 "테스트가 진짜 돌았고 그 뒤 코드가 안 바뀌었는지"를 확인한다.
```bash
node "${CLAUDE_PLUGIN_ROOT}/skills/build/scripts/run-tests.mjs" # 러너 자동 감지
node "${CLAUDE_PLUGIN_ROOT}/skills/build/scripts/run-tests.mjs" --cmd "./gradlew test --tests '*Foo*'"
```
코드를 한 줄이라도 더 고쳤으면 evidence는 STALE이 된다. 마지막 편집 뒤에 반드시 한 번 더 돌린다.
## 3. 막혔을 때 — nereus:debug 를 부른다
버그·실패 테스트·예상과 다른 동작을 만나면 **`nereus:debug` 스킬을 부른다**. 여기서 요약하지 않는다 — 절차가 그 스킬에 있다.
철칙만 옮겨 적으면: **근본 원인 조사 없이 수정하지 않는다.** 같은 태스크에서 가설 3개가 연속으로 틀리면 멈추고 구조를 의심한다(`ooo unstuck` → 사용자에게 재설계 여부). 실패한 접근은 이유와 함께 대화에 명시적으로 남긴다(자동 압축 요약의 MUST NOT 섹션이 이어받는다).
## 4. 게이트
- 전체 테스트 실행 → 전부 통과. 출력을 인용한다.
- 스택별 빌드·정적 검사를 한 번 더 돌린다(`flutter analyze`, `./gradlew build`, `npm run build`, `tsc --noEmit`, 또는 `node --check`).
`ooo qa` 는 **아티팩트 하나**(파일이나 텍스트)를 판정하는 도구다 — `ooo qa <파일>` 형태로만 쓰고, 저장소 전체 게이트로 쓰지 않는다(`--json` 같은 플래그는 없다).
- 디자인 표면(스타일시트·디자인 토큰·시각 마크업)을 만졌으면 `nereus:design` 의 렌더 라운드를 돌린다. impeccable critique 로 비평받아 `record visual --files` 로 커버한다. 건너뛰면 finish 게이트가 차단한다.
```bash
node "${CLAUDE_PLUGIN_ROOT}/skills/design/scripts/design-feedback.mjs" status # 무엇이 미이행인지 먼저 확인
```
- `[flow]` 태스크가 포함됐으면 `nereus:e2e`를 먼저 실행한 뒤 `nereus:review`로 넘어간다. 아니면 바로 review.
## 5. 비용 티어 (출처: oh-my-openagent category + superpowers tiering)
| 작업 등급 | 예 | 티어 (모델 별칭) |
|---|---|---|
| 기계적 (mechanical) | 린트·재테스트 실행 | `haiku` (파일을 바꾸지 않는 실행만) |
| 통합 (integration) | 다파일 기능 구현·리뷰 반영·포맷·단순 수정 | 담당 에이전트 frontmatter 의 `model` |
| 설계·최종판단 (design/final) | 아키텍처 결정·R4–5 escalate·breaker 판정 | `opus` 이상 |
별칭 순서는 haiku < sonnet < opus < fable 이다. 담당 에이전트 기준값은 `skills/spec/scripts/model-tiers.mjs` 의 `AGENT_TIERS`.
fix 4라운드 이후는 무조건 고친 주체의 별칭보다 한 단계 높은 별칭으로 올린다 (고친 주체가 자기 문제를 못 본다).