Skip to content
Back to skills

Bug Fix

ASecurity

완료된 프로젝트(plan_setup·harness_setup·loop_setup/LOOP.md 가 있고 STATE.md 의 Phase Overview 에 in_progress 가 없는 상태)에서 실제 사용 중에 발견된 문제 하나를 고친다. "xx 가 안 돼" 로 시작하는 신고를 받아 버그인지 요구 변경인지 먼저 가르고(문서·OQ 근거), 재현 절차와 기대 동작을 LOG.md 에 "### BUG-NN" 한 줄로 먼저 적고, 원인을 확인하고, 그 버그를 잡는 회귀 검사를 harness-update 로 게이트에 즉시 활성으로 넣고(고치기 전 실패를 실제로 확인), 코드를 고치고, 게이트 넷을 통과시키고(task_validation 은 분리 세션이 그 재현 줄을 수용 기준으로 판정), 커밋 1회(메시지에 BUG-NN) 한다. 문서·플랜·phase·STATE.md 는 건드리지 않는다. 사용자가 "필터가 안 돼", "저장했는데 사라져", "이 버튼 누르면 에러 나", "쓰다 보니 이상한 ...

  • 3 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 23, 2026
ai-agentsnodegitapi

Works with

  • claude code
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned September 23, 2026

npx -y skills add GangJaeYu/harness_loop_full_korean --skill bug-fix --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bug Fix?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Bug Fix
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gangjaeyu-bug-fix/badge)](https://www.skillsdirectory.com/skills/gangjaeyu-bug-fix)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: bug-fix
description: 완료된 프로젝트(plan_setup·harness_setup·loop_setup/LOOP.md 가 있고 STATE.md 의 Phase Overview 에 in_progress 가 없는 상태)에서 실제 사용 중에 발견된 문제 하나를 고친다. "xx 가 안 돼" 로 시작하는 신고를 받아 버그인지 요구 변경인지 먼저 가르고(문서·OQ 근거), 재현 절차와 기대 동작을 LOG.md 에 "### BUG-NN" 한 줄로 먼저 적고, 원인을 확인하고, 그 버그를 잡는 회귀 검사를 harness-update 로 게이트에 즉시 활성으로 넣고(고치기 전 실패를 실제로 확인), 코드를 고치고, 게이트 넷을 통과시키고(task_validation 은 분리 세션이 그 재현 줄을 수용 기준으로 판정), 커밋 1회(메시지에 BUG-NN) 한다. 문서·플랜·phase·STATE.md 는 건드리지 않는다. 사용자가 "필터가 안 돼", "저장했는데 사라져", "이 버튼 누르면 에러 나", "쓰다 보니 이상한 게 있어", "배포한 앱에서 xx 가 이상하게 나와", "사용자한테 버그 신고 들어왔어", "이 버그 고쳐줘" 처럼 다 만든 앱을 쓰다가 발견한 문제를 고쳐 달라고 할 때 반드시 이 스킬을 사용한다. 코드를 바로 고치지 말고 이 스킬로 먼저 기록과 회귀 검사를 세운다. 다만 개발 루프 안에서 게이트가 실패한 것은 이 스킬을 부를 이유가 아니다 — 그건 LOOP.md 의 실패 분류와 재시도 3회가 다룬다. 이 스킬은 루프 밖에서(Phase Overview 에 in_progress 없음), 실제 사용 중에 발견된 문제를 받는다. 문서에 적힌 대로 동작하는데 바꾸고 싶은 것은 feature-add, docs/PRD.md 가 없는 코드는 code-to-docs 가 먼저다.
---

# 버그 수정 (Layer 6 · 사용 중 발견된 문제)

## 이 스킬의 목적

프로젝트가 끝나고 실제로 쓰기 시작하면 "xx 가 안 돼" 가 온다. 스킬 없이도 코드는 고쳐진다. 그러나 그렇게 고치면 **셋이 빠진다** — 같은 버그를 다시 잡는 검사가 게이트에 안 들어가고, `LOG.md` 에 무엇을 왜 고쳤는지 안 남고, 고친 사람이 아닌 세션의 확인(분리 검증)을 안 거친다.
이 스킬은 그 셋을 지키려고 있다. 코드를 고치는 것 자체는 이 스킬의 가장 작은 부분이다.

```
진입 조건 — 루프가 도는 중인가                                             ← 0단계
   → 버그인가, 요구 변경인가 (아니면 feature-add 로 돌리고 끝)                  ← 1단계
   → BUG-NN 배정, 재현하고 LOG.md 에 재현 줄 (재현 절차 · 관찰 · 기대 동작)       ← 2단계  (고치기 전에)
   → 원인 확인, LOG.md 에 원인 줄                                             ← 3단계
   → 회귀 검사를 쓰고 고치기 전 실패를 본다 → harness-update ② 로 게이트에 등록   ← 4단계
   → 수정 → 게이트 넷 (task_validation 은 분리 세션, 재현 줄이 수용 기준)         ← 5·6단계
   → 커밋 1회 (메시지에 BUG-NN), LOG.md 에 게이트·커밋 줄                        ← 7단계
```

플랜·phase·태스크를 만들지 않는다. 버그 하나는 태스크가 아니다 — 태스크 ID 가 없으니 LOOP.md 의 커밋 규칙과 하네스의 활성 시점이 걸 곳이 없고, 그래서 그 자리를 **`BUG-NN`** 이 대신한다.

### 여기서 하는 일과 하지 않는 일

| 하지 않는 것 | 어디서 하는가 |
|---|---|
| 개발 중 게이트 실패를 고치는 것 | 개발 루프. `LOOP.md` 의 실패 분류(진짜 결함·낡은 스펙·환경 문제·흔들림·판정 불가)와 재시도 3회가 다룬다 — 이 스킬이 끼면 재시도 카운터와 분류를 건너뛰고, 하네스 갱신이 라운드 사이가 아닌 곳에 끼어 문서의 필자가 둘이 된다 |
| 문서에 적힌 대로 동작하는 것을 바꾸는 것 | `feature-add` — 후미 절에 "FR-00x 수용 기준 n 을 다음으로 대체". 요구 변경이다 |
| PRD·TRD·ARCHITECTURE·IDEA 를 고치는 것 | 하지 않는다. 문서와 어긋나게 된 곳은 보고한다(8단계) |
| phase·태스크·`STATE.md` 를 고치는 것 | 하지 않는다. 루프·플랜은 이 버그와 무관하게 그대로다 |
| 게이트 정의서를 직접 고치는 것 | `harness-update` ② — 회귀 검사 등록은 이 스킬이 호출 지시만 넘긴다 |
| 신고되지 않은 옆 버그까지 고치는 것 | 하지 않는다. 발견한 것은 보고에 "다음 BUG 후보" 로 적는다 — 한 요청은 한 `BUG-NN` 이다 |
| 리팩토링 ("고치는 김에 정리도") | `refactor-plan`. 동작이 안 바뀌는 정리는 버그 수정 커밋에 섞지 않는다 |

---

## 0단계. 진입 조건

`plan_setup/STATE.md` 를 읽는다. 하나라도 걸리면 **멈추고 보고한다.** 선택지로 묻지 않는다 — 진입 조건은 고를 것이 아니다.

| 확인 | 걸렸을 때 |
|---|---|
| `Phase Overview` 에 `in_progress` 인 phase 가 **없는가** | 있으면 멈춘다 — **"지금은 루프가 도는 중이다. 이 문제가 현재 태스크의 것이면 루프가 고치고(LOOP.md 3절 실패 분류·재시도 3회), 아니면 phase 완료 뒤에 다시 부르라."** 이유는 필자 충돌이다 — 루프가 도는 동안 `LOG.md`·하네스 문서의 필자는 코디네이터 하나여야 하고(Layer 5), 회귀 검사를 넣는 harness-update ② 는 라운드 사이에만 한다. 신고 문장은 보고에 그대로 옮겨 나중에 다시 설명하지 않게 한다 |
| code-to-docs 로 진입한 프로젝트(PRD 머리의 `> 코드에서 역으로 작성 (as-is` 또는 `phase-01-baseline`)면 phase-01 이 `completed` 인가 | 아니면 멈춘다 — 현행 고정 게이트가 아직 활성이 아니라 "기존 게이트 통과" 가 아무것도 지키지 않는다. 루프로 phase-01 을 먼저 끝내라고 답한다 |
| `plan_setup/LOG.md`·`harness_setup/`·`loop_setup/LOOP.md` 가 있는가 | 없으면 무엇이 없는지 보고한다. `docs/PRD.md` 부터 없으면 `code-to-docs` 가 먼저다 — 기대 동작을 판정할 문서가 없다 |

`pending` phase 는 막지 않는다 — feature-add 가 phase 를 더한 직후에도 이 스킬을 부를 수 있어야 한다. "전부 completed" 를 조건으로 삼으면 그 상태에서 막힌다.

**`HARNESS.md` 1절의 게이트 상태를 본다.** 전부 `미활성` 이면 멈추고 보고한다 — 회귀 검사를 넣을 게이트가 돌지 않는다. 일부만 미활성이면 진행하되 7단계에서 그 게이트의 결과를 `미활성` 으로 적는다(통과로 적지 않는다).

**git 상태를 본다.** 미커밋 변경이 있으면 알리고 사용자가 정할 때까지 기다린다 — 이 스킬의 커밋 1회에 남의 변경이 섞이면 `BUG-NN` 커밋이 무엇을 고쳤는지 말하지 못한다.

병렬 운용 프로젝트여도 이 스킬은 루프 밖이므로 **사용자가 연 트리(보통 `main`)** 에서 하고 거기에 커밋한다. 다음 코디네이터는 라운드를 열 때 `main` 을 먼저 병합한다(LOOP.md 8절).

---

## 1단계. 버그인가, 요구 변경인가

이 판정이 이 스킬의 첫 산출물이다. 틀리면 둘 중 하나가 된다 — 요구 변경을 버그로 고치면 문서(PRD)가 모르는 동작이 코드에 생기고 다음 스킬이 낡은 문서를 근거로 움직인다. 버그를 요구 변경으로 보내면 회귀 검사·BUG 기록·분리 검증 없이 phase 태스크로 들어간다.

신고를 읽고 관련 FR 을 찾는다 — PRD 4절과, 있으면 후미의 `## 추가 N` 절(같은 문서 안에서는 **뒤 절이 앞 절을 이긴다**). 그리고 두 질문을 순서대로 묻는다.

**질문 1 — 기대 동작에 근거가 있는가.** 아래 중 하나가 "지금 동작은 틀렸다" 고 말해야 한다.

| 근거 | 예 |
|---|---|
| **합의된 문서의 기준과 다르게 동작한다** — to-be PRD 의 수용 기준(as-is 가 아닌 문서, 또는 as-is 문서의 `## 추가 N` 절) | "FR-012 는 '완료 항목은 목록 아래로' 인데 위에 있다" |
| **as-is 문서가 그 동작을 적으며 "의도 여부: OQ-xxx" 를 붙였고, 그 OQ 의 답이 "의도가 아니다"** | code-to-docs 는 버그로 보이는 동작도 판단 없이 관찰대로 적고 OQ(`확인`)를 붙인다 — 그 OQ 가 바로 이 질문이다. 답을 모르면 사용자에게 묻는다(아래) |
| **코드가 스스로 드러낸 의도와 결과가 모순된다** — 파라미터 이름·화면 문구·주석이 말하는 동작을 어떤 입력으로도 얻을 수 없다 | `?done=false` 를 받는 필터가 어떤 값에도 빈 배열 · "안 끝난 것만" 체크박스가 늘 빈 목록 |
| 문서와 무관하게 명백히 망가짐 — 500·크래시·데이터 손실·저장한 것이 사라짐 | |

as-is 문서에 관찰대로 적혀 있고 OQ 가 없거나 답이 "의도였다" 면 → **요구 변경**(`feature-add`). 지금 동작이 합의된 것이고, 바꾸고 싶은 것은 새 요구다.

**질문 2 — 고친 뒤의 동작을 새 결정 없이 한 줄로 쓸 수 있는가.** 기대 동작 한 줄을 써 본다. 쓰다가 아래 중 하나를 **정해야** 하면 → **요구 변경**(`feature-add`). 질문 1 이 "틀렸다" 여도 그렇다.

- 누가 할 수 있는가(권한 규칙 — 소유자만? 멤버도? 관리자?)
- 새 응답 코드·오류 형식(지금 없는 401·403·409)
- 새 화면 요소·메시지·흐름(오류 안내, 확인 대화상자)
- 새 필드·저장 형식·설정값

이 질문이 필요한 이유 — "소유자만 지울 수 있어야 하는데" 는 흔히 버그라고 불리지만, 고치려면 소유자의 정의·거절 응답·화면 처리를 새로 정해야 한다. 그건 수용 기준을 새로 쓰는 일이고 수용 기준은 PRD 가 정한다. 이 스킬이 정하면 PRD 에 없는 규칙이 코드에만 생긴다.
반대로 "`done=false` 면 미완료 할 일만 온다" 는 파라미터 이름이 이미 정해 둔 동작이라 새로 정할 것이 없다. 경계 입력(예: `done=abc`)처럼 부수적으로 정할 것이 생기면 **지금 동작을 유지**하는 쪽으로 쓰고 보고에 적는다 — 그것까지 정하는 것은 요구 변경이다.

| 질문 1 | 질문 2 | 판정 |
|---|---|---|
| 예 | 예 | **버그** — 2단계로 |
| 예 | 아니오 | **요구 변경** — feature-add. "무엇이 틀렸는가" 는 맞지만 "어떻게 고치는가" 가 새 요구다 |
| 아니오 | — | **요구 변경** — feature-add |
| 판정할 문서 기준이 없다(기능이 PRD 에 아예 없다) | — | **요구 변경** — 없는 기능이 없는 것은 버그가 아니다 |

### OQ 의 답을 모를 때 — 묻는다

as-is 문서의 "의도 여부: OQ-xxx" 는 종류가 `확인` 이다 — 사용자도 모를 수 있다. 그래서 **답 대신 "모른다" 를 고를 수 있게** 묻는다.

```
FR-007 의 as-is 기준 4("done=true/false 는 빈 배열")에 OQ-002(의도 여부)가 걸려 있습니다.
이 동작이 의도였습니까?  ① 의도가 아니었다(버그) ② 의도였다 ③ 모른다
③이면 코드가 스스로 드러낸 의도(파라미터 이름 done, 화면 문구 "안 끝난 것만")로 판정해 버그로 진행합니다 (가정).
```

"모른다" 일 때는 **코드가 스스로 드러낸 의도**가 하나로 정해지면 그것으로 판정하고 `(가정)` 으로 기록한다. 하나로 안 정해지면 요구 변경으로 보낸다 — 추측으로 코드를 바꾸는 것보다 feature-add 가 묻는 편이 싸다.
대화할 수 없는 환경이면 질문을 기록으로 남기고(`questions.md` 등) 위 기본값으로 진행한다.

### feature-add 로 돌릴 때

여기서 끝난다. 코드·테스트·하네스·`LOG.md`·문서를 **하나도 고치지 않는다.** 보고에 넣을 것:

1. 판정과 근거 — 질문 1·2 각각의 답, 인용한 FR 기준·OQ·코드 위치
2. feature-add 에 넘길 요청 문장 — 신고를 그대로 + "FR-00x 수용 기준 n 을 대체하는 요구 변경" + 새로 정해야 할 것 목록(질문 2 에서 걸린 것)
3. 같은 모양의 다른 곳(예: 삭제 API 가 둘이면 둘 다) — feature-add 가 한 요청으로 묶을지 정한다

---

## 2단계. BUG-NN 배정과 재현 줄 — 고치기 전에

**NN** 은 `LOG.md` 전체에서 `BUG-(\d+)` 의 최댓값 + 1, 두 자리(`BUG-01`). LOG 가 유일한 기록처라 여기서 센다.

재현한다. 수단은 게이트와 같은 순서다 — 실행 중인 앱에서 HTTP·브라우저로 신고한 절차를 밟는다(`local-dev` 로 준비, 테스트 데이터 모드). **앱을 띄울 수 없으면**(`local-dev` 가 0이 아닌 코드 — 포트 점유·의존성 미설치) 그것은 환경 문제다. 남의 프로세스를 죽이지 않는다. 그때는 실행할 수 있는 가장 가까운 층에서 재현한다 — 결함이 있는 식을 그 입력값으로 직접 돌려 보는 것(예: 저장된 `false` 와 쿼리 문자열 `"false"` 의 `===` 비교를 `node -e` 로). 재현 수단을 줄에 적는다. 코드를 읽고 "그럴 것이다" 만으로는 재현이 아니다.

`LOG.md` 에 **재현 줄**을 쓴다. 기존 형식 그대로 — 오늘 날짜의 `## YYYY-MM-DD` 가 마지막 제목이 아니면 새로 달고, 그 아래 `### BUG-NN` 으로 시작하는 한 줄. **`## BUG-NN` 같은 새 H2 를 만들지 않는다** — plan-generator 가 만든 LOG 형식과 어긋나고, 중간에 harness-update 가 자기 한 줄을 쓰므로 "BUG 항목 아래에 붙인다" 는 구조가 서지 않는다. 모든 줄은 append 다.

```
### BUG-01 할 일 완료 필터 — 재현: 완료 1·미완료 1 을 만든 뒤 GET /api/tasks?done=false (화면: "안 끝난 것만" 체크) → 관찰: [] (빈 배열, 목록이 빈다) / 기대: 미완료 할 일 1개만 온다, done=true 면 완료 1개만. 재현 수단: HTTP (앱 미기동이면 "코드 단위 — local-dev 50") · 근거: FR-007 기준 4 · OQ-002 답 "의도 아님"(사용자, 2026-09-23)
```

**이 줄이 분리 검증의 수용 기준이다**(6단계). 그래서 고치기 전에 쓴다 — 고친 뒤에 쓰면 기대 동작이 "고친 코드가 하는 일" 로 적힌다. 쓰는 규칙은 수용 기준과 같다: 관찰 가능한 결과, 숫자가 필요한 곳엔 숫자, **기대 동작에 실패하면 안 되는 쪽 하나**(done=true 쪽처럼 고치다 깨지기 쉬운 옆 경로).

---

## 3단계. 원인을 확인하고 원인 줄을 쓴다

재현 절차를 거꾸로 따라가 결함이 있는 줄을 찾는다. **원인은 가설이 아니라 확인된 것이어야 한다** — 그 줄을 바꾸면 재현 결과가 바뀐다는 것을 보거나(4단계의 실패하는 검사가 그 증거가 된다), 최소한 그 식이 재현 입력에서 틀린 값을 낸다는 것을 실행으로 본다.

```
### BUG-01 원인: routes/tasks.js 21행 — 저장값 done(불리언)과 req.query.done(문자열 "true"/"false")을 === 로 비교해 어떤 값이든 거짓. 같은 OQ-002 의 PATCH !!"false" (85행)는 신고 범위 밖 — 다음 BUG 후보로 보고
```

원인이 문서 쪽에 있으면(수용 기준 자체가 모순) 멈추고 1단계로 돌아간다 — 요구 변경이다.
원인을 찾다 신고되지 않은 다른 결함을 보면 **고치지 않는다.** 원인 줄이나 보고에 "다음 BUG 후보" 로 남긴다. 한 커밋에 두 버그가 들어가면 회귀 검사가 무엇을 지키는지 흐려진다.

---

## 4단계. 회귀 검사 — 고치기 전에 실패하는 것을 본다

### 검사를 쓴다

회귀 검사는 **게이트가 이미 돌리는 테스트 파일**에 들어간다 — 같은 러너, 같은 스타일, 같은 위치. 게이트는 넷 고정이라 회귀 검사는 `unit` 또는 `e2e` 안에 들어간다(다섯째 게이트를 만들지 않는다).

- **층은 재현이 드러난 가장 낮은 곳** — API 로 재현되면 unit(API 테스트), 화면에서만 드러나면 e2e. 신고가 화면에서 왔어도 API 에서 재현되면 unit 이 주 검사이고, 화면 쪽 기존 케이스가 버그 동작을 붙잡고 있으면 그것도 뒤집는다(아래)
- **케이스 이름에 `BUG-NN`** — `LOG.md` 의 실패 기록이 케이스 이름으로 남으므로, 나중에 이 검사가 깨지면 이 줄로 거슬러 올라온다
- **진짜 단언** — 재현 줄의 기대 동작을 그대로 단언한다. 실패 경로 쪽(done=true 쪽)도 단언한다
- **기존 현행 고정 케이스가 버그 동작을 단언하고 있으면 뒤집는다** — code-to-docs 로 들어온 프로젝트는 as-is 동작("빈 배열")을 붙잡은 케이스가 있다. 그대로 두면 고친 뒤 그 케이스가 실패한다. **지우지 않고 기대값을 바꾼다**(케이스 이름에 `BUG-NN` 병기) — 단언을 빼는 것은 약화이고, 뒤집는 것은 같은 자리를 옳은 값으로 지키는 것이다. 무엇을 뒤집었는지 보고한다.
  unit·e2e **양쪽을 다 찾는다**(`grep` 으로 버그 동작을 적은 케이스 이름·주석 — "빈 배열", "비고"). 회귀 검사를 한 층에만 두더라도, 다른 층의 케이스가 이름으로 버그 동작을 기준처럼 적고 있으면 그 이름과 기대값도 뒤집는다 — 스텁이라 지금은 안 깨져도, 나중에 누가 스텁을 채우면 그 이름대로 버그를 다시 붙잡는다

**기존 테스트가 스텁인지 본다.** `assert.ok(true)`·`expect(true)` 처럼 아무것도 확인하지 않는 케이스는 게이트를 초록으로 만들 뿐 지키는 것이 없다. 그 파일에 회귀 검사를 더할 때 스텁 옆에 진짜 단언을 두고, 스텁이 있다는 사실(파일·케이스 수)을 보고에 적는다 — 게이트가 실제보다 강해 보이는 것은 하네스의 문제이고 이 스킬의 범위 밖이다(`harness-update` 또는 사용자 판단).

### 고치기 전 실패를 본다

**검사를 쓴 다음, 코드를 고치기 전에 그 게이트 명령을 돌린다.** 회귀 검사가 **재현 줄과 같은 이유로** 실패해야 한다(기대 [미완료 1개] / 실제 []). 통과하면 그 검사는 버그를 못 잡는다 — 다시 쓴다.
이 확인이 없으면 "고친 뒤 통과" 는 아무 뜻이 없다. 처음부터 통과하는 검사도 고친 뒤에는 통과한다.

**게이트 밖에서 코드 단위로 돌려 보는 것**(의존성을 대신하는 스텁, 다른 포트)은 참고 증거로 적어도 되지만 정본 게이트의 결과를 대신하지 않는다. 그리고 그런 실행은 **실데이터 파일을 건드리지 않게** 사본이나 메모리 데이터를 쓴다 — 하네스가 게이트를 테스트 데이터 모드에서만 돌리게 한 이유(실데이터일 수 있다)가 게이트 밖 실행에도 그대로 걸린다. 끝나면 `git status` 로 코드·테스트·하네스·LOG 외에 바뀐 파일이 없는지 본다.

**게이트가 환경 때문에 돌지 않으면**(앱 미기동으로 연결 거부, 도구 미설치) 그것은 "실패 확인" 이 아니다 — 연결 거부는 고친 뒤에도 연결 거부다. `LOOP.md` 의 환경 문제 규칙대로 `local-dev` 종료 코드로 확정하고, 재준비 1회(10·20·포트 점유는 사용자에게), 그래도 안 되면 **환경 문제로 기록하고 계속하되 커밋하지 않는다**(7단계). 러너 자체가 도는지(`node --test` 가 기존 파일을 실행하는지)는 따로 적는다 — "러너는 돈다, 앱이 없다" 와 "아무것도 안 돈다" 는 다음 사람이 할 일이 다르다.

### harness-update 로 게이트에 등록한다

테스트 파일은 코드이고 이 스킬이 쓴다. **게이트 정의서에 그 검사를 올리는 것은 harness-update 다**(②, 범위 확대 — 강화 방향이라 승인 없이 한다). 넘길 지시:

```
harness-update 호출 지시 (bug-fix 에서)

- BUG-NN 회귀 검사를 게이트에 더한다(②). 검사: <게이트> <파일> 의 케이스 "<BUG-NN …>" (뒤집은 기존 케이스: <파일::케이스>)
- 근거: plan_setup/LOG.md 의 "### BUG-NN … 재현:" 줄. 태스크 ID 가 없으므로 **즉시 활성**이고, 커버 영역 표(또는 검사 목록)의 활성 시점·담당 열에는 `BUG-NN` 을 적는다
- 그 게이트 정의서·HARNESS.md·task_validation.md 에 버그 동작을 기준·예시로 적은 문장(예: "as-is 동작 'done=false 가 빈 배열' 이 기준이다")이 있으면 BUG-NN 기준으로 바꾼다 — 단언을 빼는 것이 아니라 옳은 값으로 옮기는 것이라 ③ 이 아니다
- task_validation 의 "검증자가 받는 것" 에 BUG-NN 검증의 경우를 더한다(없으면) — 태스크 문서 경로 대신 LOG.md 의 BUG-NN 재현 줄을 지시문에 옮겨 준다. phase 전용 확인(예: "앱 코드 무변경")은 그 phase 의 태스크에만 걸린다고 적는다
- LOG.md 에 남기는 한 줄은 `### BUG-NN` 으로 시작한다(예: "### BUG-NN 회귀 검사 추가 — unit test/api/tasks-list.test.js 2케이스, 활성 시점 BUG-NN, 고치기 전 fail 2 확인"). 태스크 ID 로 시작하지 않는다 — 루프가 LOG 를 훑을 때 태스크로 읽는다
- STATE.md·태스크 문서·코드는 고치지 않는다. CLAUDE.md·AGENTS.md 의 `## 하네스` 절은 바뀐 값이 있을 때만
```

---

## 5단계. 고친다

원인 줄이 가리킨 곳을 **최소한으로** 고친다. 고치는 김에 이름을 바꾸거나 정리하지 않는다 — 그건 refactor-plan 이고, 섞이면 회귀 검사가 통과했을 때 무엇이 고쳐서 통과했는지 말할 수 없다.
화면과 API 가 둘 다 결함이 아니라면 결함이 있는 한 곳만 고친다(done 필터는 API 한 줄을 고치면 화면이 그대로 맞는다).

---

## 6단계. 게이트 넷

`LOOP.md` 3절 그대로 돈다 — 이 스킬은 그 안에서 움직인다. `local-dev` 로 준비(테스트 데이터 모드), `lint → unit → e2e` 를 순서대로, 앞이 실패하면 뒤를 돌리지 않는다. 명령은 정의서의 `## 명령` 에서 꺼낸다(여기 베껴 두지 않는다).

- **실패하면 분류부터** — 진짜 결함·낡은 스펙·환경 문제·흔들림·판정 불가(`LOOP.md` 3절). 진짜 결함만 수정 횟수로 세고 **3회**에서 멈춘다. 나머지는 확인 실행 1회
- **전체 스위트**가 대상이다 — 회귀 검사만 돌려 통과시키지 않는다. 다른 케이스가 깨졌으면 그것도 이 수정의 결과다
- 결과는 명령·종료 코드·케이스 수(`tests N / fail 0`)로 적는다. "통과함" 은 결과가 아니다

### task_validation — 분리 세션, 재현 줄이 수용 기준

평소처럼 **고친 이 세션이 아닌 세션**이 판정한다. 세션을 여는 방법은 `LOOP.md` 의 구동기가 정한 것(헤드리스 자식 `claude -p`·`codex exec` / 오르카 워커 / 서브에이전트)을 따른다.
태스크 문서가 없으므로 **검증자에게 태스크 문서 경로 대신 재현 줄을 준다.** `LOG.md` 경로를 주지 않고 **그 줄의 문장을 지시문에 옮긴다** — LOG 에는 원인 줄이 같이 있고, 원인 추정은 검증자가 받지 않는 것이다.

```
다음 버그의 기대 동작을 실행 중인 애플리케이션에서 관찰해 판정하세요.
- 수용 기준(재현 절차와 기대 동작): "<BUG-NN 재현 줄에서 '재현:' 부터 '기대:' 끝까지 그대로>"
- 절차와 판정 형식: harness_setup/quality_gates/task_validation.md  (TASK 칸에는 BUG-NN)
- 애플리케이션: <주소>. <local-dev 명령> 으로 테스트 데이터 모드로 준비돼 있습니다
- 이 문장, 그 문서, 실행 중인 앱 외의 정보는 찾지 마세요. 최근 커밋·변경 파일·LOG.md·작업 메모를 참고하지 말고, 코드도 테스트도 고치지 말고, 원인 추정을 하지 마세요.
- 판정 블록을 그대로 출력하세요 (END 로 끝냅니다).
```

판정 블록의 `RESULT` 가 `환경 문제` 면 FAIL 이 아니다(재준비 1회). `FAIL` 이면 진짜 결함으로 5단계로 돌아간다(3회 안에서). 분리 세션을 열 수단이 이 환경에 없으면 **이 세션이 대신 판정하지 않는다** — `task_validation` 미실행으로 적고 커밋하지 않는다.

---

## 7단계. 커밋 1회와 마지막 줄

**게이트 넷이 전부 통과한 뒤에만** 커밋한다 — 활성 게이트는 통과, 미활성 게이트는 `미활성` 으로 적힌 상태(0단계). 넷 중 하나라도 실패·환경 문제·미실행이면 **커밋하지 않고** 변경을 그대로 둔 채 멈춰 보고한다(`LOOP.md` 의 "3회 소진 시 미커밋 변경은 그대로 둔다" 와 같다). 게이트를 못 돌린 채 커밋하면 `BUG-NN` 커밋이 "검증된 수정" 이라는 뜻을 잃는다.

통과했으면 **마지막 줄**을 `LOG.md` 에 쓰고, 그 줄까지 포함해 **한 번** 커밋한다.

```
### BUG-01 게이트 넷 통과 — lint 0 · unit tests 64 fail 0 (회귀 2) · e2e 12 passed · task_validation PASS (관찰 수단 3). 고친 파일: routes/tasks.js. 커밋 "BUG-01: 완료 필터가 문자열과 불리언을 비교해 늘 빈 배열" (해시는 git log --grep BUG-01)
```

해시를 줄에 박지 않는 이유 — 그 줄이 들어간 커밋의 해시는 커밋 전에 알 수 없다. 커밋 메시지의 `BUG-NN` 이 LOG 와 커밋을 잇는다. 해시는 보고에 적는다.
커밋에는 이 버그로 바뀐 파일만 경로로 add 한다(`git add -A` 금지 — 0단계에서 확인한 뒤 생긴 파일이 섞인다): 고친 코드, 테스트 파일, harness-update 가 고친 하네스 문서, `LOG.md`.

**멈출 때의 마지막 줄**:

```
### BUG-01 게이트 미통과 — lint 0 · unit 환경 문제(local-dev 50: 포트 3000 을 다른 프로세스가 점유, 회귀 검사 미판정) · e2e·task_validation 미실행. 커밋하지 않음 — 고친 파일 routes/tasks.js 는 미커밋 상태로 둠
```

다시 불리면(환경을 고친 뒤 "BUG-01 이어서") `LOG.md` 의 `BUG-01` 줄들을 읽어 마지막 단계 다음부터 잇는다 — 재현·원인 줄을 다시 쓰지 않는다. 세션이 끊겨도 LOG 만 있으면 이어진다.

`STATE.md` 는 쓰지 않는다. 루프 상태(`Current Task`·`Last Verification`·`Retry`)는 태스크의 것이고 버그는 태스크가 아니다.
`CLAUDE.md`·`AGENTS.md` 의 `현재 단계` 줄도 건드리지 않는다 — 버그 수정은 단계가 바뀐 것이 아니다. 하네스 절은 harness-update 가 필요하면 갱신한다.

---

## 8단계. 자체 점검과 보고

전부 끝나면(또는 멈추면) 다시 읽으면서 확인한다.

| 확인할 것 | 통과 조건 | 걸렸을 때 |
|---|---|---|
| 진입 조건 | `in_progress` 0건, code-to-docs 진입이면 phase-01 completed | 0단계로 돌아가 멈춘다 |
| 판정 근거 | 질문 1·2 의 답과 인용(FR 기준·OQ·코드 위치)이 보고에 있음 | 채운다 |
| LOG 형식 | `## 날짜` 아래 `### BUG-NN` 으로 시작하는 줄만 더해짐. 재현 → 원인 → 회귀 검사(harness-update) → 게이트·커밋 순서. 새 H2 0개, 기존 줄 변경 0 | 고친다 |
| 재현 줄 | 원인·수정보다 먼저. 재현 절차·관찰·기대 동작·재현 수단이 있고 기대 동작이 관찰 가능 | 고친다 — 고친 뒤 기대 동작을 바꿔 쓰지 않는다 |
| 회귀 검사 | 진짜 단언(스텁 아님), 케이스 이름에 BUG-NN, **고치기 전 실패를 실제 실행으로 확인**(못 했으면 그 사실과 이유) | 다시 쓴다 |
| 버그 동작을 적은 기존 케이스 | unit·e2e 어디에도 이름·주석·기대값이 버그 동작을 기준으로 적은 케이스가 남지 않음(뒤집힘). 게이트 밖 실행 뒤 실데이터 파일 변경 0 | 뒤집는다. 데이터는 `git checkout` 으로 되돌리고 보고 |
| 게이트 등록 | 정의서에 BUG-NN 검사가 즉시 활성, 활성 시점 열 `BUG-NN`, 게이트 수 넷 그대로 | harness-update |
| 수정 범위 | 원인 줄의 파일만. 옆 버그·정리 0건 | 되돌리고 보고로 |
| 불변 | `docs/`·`plan_setup/`(LOG.md 제외)·`STATE.md`·`loop_setup/` 변경 0 | 되돌린다 |
| 게이트 결과 | 넷의 결과가 명령·숫자로 LOG 마지막 줄에. 미실행·환경 문제를 통과로 적은 곳 0 | 고친다 |
| 커밋 | 통과했으면 정확히 1회, 메시지에 BUG-NN, 바뀐 파일만. 미통과면 0회 | 고친다 |

**자체 점검 결과는 문서에 남기지 않는다.** 보고로 간다.

보고는 이렇게 한다.

1. 판정 — 버그 / 요구 변경, 질문 1·2 의 답과 근거. 사용자에게 물은 것과 답(또는 가정한 기본값)
2. `BUG-NN` 과 LOG 에 쓴 줄(그대로 옮긴다)
3. 원인과 고친 파일
4. 회귀 검사 — 파일·케이스, 고치기 전 실패 결과, 뒤집은 기존 케이스, 스텁을 발견했으면 그 사실
5. 게이트 넷 결과와 분리 검증 판정 블록. 커밋 해시와 `git log --oneline -1` 한 줄. 커밋하지 않았으면 이유와 이어서 할 일
6. **문서와 어긋나게 된 곳** — as-is 문서가 버그 동작을 관찰대로 적어 두었으면(예: PRD FR-007 기준 4, FR-014 의 화면 기준, OQ-002) 그 줄은 이제 과거의 관찰이다. 이 스킬은 문서를 고치지 않으므로 목록으로 넘긴다 — OQ 의 답은 LOG 의 BUG-NN 줄에 있고, PRD 를 다음에 부분 갱신하는 스킬(feature-add 가 prd-generator 를 부를 때)이 미결 표의 그 행을 "해소 — BUG-NN" 으로 옮길 수 있게
7. 다음 BUG 후보 — 원인을 찾다 본 다른 결함(신고 범위 밖)
8. 다음: 커밋했으면 "끝 — 루프·플랜은 그대로다". 멈췄으면 무엇을 고친 뒤 "BUG-NN 이어서" 로 다시 부르라

---

## 범위를 넘는 요청이 함께 오면

| 요청 | 이 스킬이 하는 것 | 왜 |
|---|---|---|
| "고치는 김에 이 부분도 정리해" | 버그만. 정리는 `refactor-plan` | 정리가 섞이면 회귀 검사의 통과가 무엇을 증명하는지 흐려진다 |
| "버그 셋 한꺼번에" | 하나에 `BUG-NN` 하나씩, 순서대로. 커밋도 각각 | 커밋과 회귀 검사가 버그 하나를 가리켜야 나중에 되돌리거나 추적할 수 있다 |
| "소유자만 지우게 해 줘"(권한이 없는 것을 버그로 신고) | 1단계 질문 2 로 판정 — 대개 feature-add | 누가 무엇을 할 수 있는지는 수용 기준이고 PRD 가 정한다 |
| "테스트는 됐고 그냥 고쳐 줘" | 재현 줄과 회귀 검사는 한다 | 이 스킬이 있는 이유가 그 둘이다. 스킬 없이 고치는 것과 같아진다 |
| "지금 루프 도는 중인데 이것도 고쳐 줘" | 0단계에서 멈춘다 | 현재 태스크의 것이면 루프가, 아니면 phase 완료 뒤 이 스킬이 |

---

## 에이전트별 참고

- Claude Code에서 실행 중이면: `references/claude-code.md`
- Codex에서 실행 중이면: `references/codex.md`

Files in this skill

  • SKILL.md30.4 KB
  • references/claude-code.md3.2 KB
  • references/codex.md2.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.