dev-bounce · git:20261005.6fd3885 · 2026-10-05 · sha256 df38caf7f03fdcbb

dev-bounce git:20261005.6fd3885A

Immutable. This exact content never changes and is served at /api/v1/blob/df38caf7f03fdcbb.

---
name: dev-bounce
description: 코드를 고치거나 새로 짜는 작업을 단계별 워크플로우로 진행한다. 버그 수정, 기능 구현, 리팩터링, 설정·의존성 변경, "이거 고쳐줘" / "이 기능 추가해줘" / "왜 안 되는지 보고 고쳐봐" 같은 요청에 파일을 건드리기 전 반드시 먼저 호출할 것. 계획 승인·검증 통과·커밋을 엔진이 강제하는데, 이 스킬로 작업을 시작해야만 그 강제가 걸린다 — 스킬 없이 바로 Edit/Write하면 아무 규칙도 적용되지 않은 채 진행된다. 질문·설명·코드 읽기만 하는 요청에는 쓰지 않는다.
---

# dev-bounce

작업을 **스테이지 체인**으로 진행한다. 각 단계에서 무엇을 하고 무엇이 금지되는지는
프로젝트의 `workflow.yaml`에 정의돼 있고, 엔진이 단계마다 지시를 주입한다.

이 문서에 워크플로우 내용은 없다. **시작 절차만 있다.**
시작한 뒤에는 주입되는 지시를 따르면 된다.

## 물어야 하는데 물을 수단이 없을 때

이 문서는 몇 군데에서 AskUserQuestion으로 사용자에게 물으라고 한다.
그 도구가 없는 컨텍스트도 있다(서브에이전트, 위임 실행 등).

그럴 때는 **추측해서 진행하지 말고 멈춘다.** 선택지를 텍스트로 그대로 제시하고
사용자 답을 기다린다. 도구가 없다는 건 "알아서 하라"는 뜻이 아니다.

물어야 하는 것들은 전부 **사용자만 답할 수 있는 것**이기 때문이다 —
어느 모드로 갈지, 남의 작업과 병렬로 갈지, 이 규칙을 앞으로도 적용할지.
문구가 명확해 보여도(예: "앞으로 항상") 추측으로 진행하면
사용자가 원한 적 없는 영구 변경이 남는다. 되돌리는 비용이 묻는 비용보다 훨씬 크다.

---

## Step 1 — 상태 확인

```bash
bouncer scan
```

항상 부른다. 0.01초짜리고, 세션 시작 때 주입된 정보는 그 사이 다른 세션이
작업을 시작했으면 이미 낡았을 수 있다.

```
STATE    MINE  <경로> <워크플로우> <단계>     이 세션이 이어서 할 작업
STATE    OTHER <경로> <단계> <나이>           다른 세션이 잡고 있는 작업
STATE    NONE                                아무것도 없음
WORKFLOW <이름> <설명>                        모드 선택지
OPTION   <워크플로우> <단계> <id> <이름>       시작할 때 물어볼 선택 항목
```

| 결과 | 다음 |
|---|---|
| `MINE` | 이미 진행 중이다. 요청이 그 작업의 연장이면 `bouncer status`로 남은 조건을 보고 이어서 한다. Step 2~4는 건너뛴다 |
| `OTHER`만 있음 | 다른 세션이 작업 중이다. Step 2로 가되 Step 4에서 병렬 여부를 묻는다 |
| `NONE` | Step 2 |

**`bouncer: command not found`가 나오면** 이 프로젝트에 ai-bouncer가 설치되지 않은 것이다.
스킬을 쓰지 말고 사용자에게 알린 뒤 평소대로 작업한다. 설치를 임의로 진행하지 않는다.

## Step 2 — 요청이 개발 작업인지 판별

| 요청 성격 | 처리 |
|---|---|
| 질문·설명·코드 읽기 | 스킬을 쓰지 않고 그냥 답한다 |
| 계획을 세우려면 탐색이 먼저 필요 | 읽기 전용으로 탐색한다(수정 금지). 끝나면 **Step 1부터 다시 시작**한다 |
| 개발 의도는 있으나 무엇을 고칠지 불명확 | AskUserQuestion으로 구체화한다. "개발 작업으로 처리할까요?" 같은 확인 질문은 답이 뻔해서 사용자 시간만 쓴다 |
| 개발 요청 | Step 3 |

## Step 3 — 모드와 옵션을 사용자에게 묻는다

Step 1의 `WORKFLOW` 줄을 그대로 AskUserQuestion 선택지로 만든다.

모드가 정해지면 그 모드의 `OPTION` 줄들을 스테이지별로 묶어 다시 묻는다
(multiSelect, 기본 전체 켜짐). 선택지가 4개를 넘으면 질문을 나눠서 여러 번 호출한다.
`OPTION`이 없으면 이 질문은 건너뛴다.

모드는 사용자가 고른다. 계획 단계가 번거롭다는 이유로 가벼운 모드를 대신 고르면
사용자는 자기가 원한 검증이 빠진 줄 모른 채 결과를 받는다. 그건 워크플로우 회피다.
AskUserQuestion을 쓸 수 없으면 위 "물어야 하는데 물을 수단이 없을 때"를 따른다.

## Step 4 — 시작

```bash
bouncer start <모드> "<슬러그>" [--off <끈-항목-id>] ...
```

슬러그는 **영문 소문자와 하이픈**으로 짧게 쓴다 (`payment-bug`, `add-oauth`).
디렉토리 이름이 되므로 한글이나 공백을 쓰면 도구에 따라 정렬·경로 처리가 어긋난다.

Step 1에 `OTHER`가 있었으면 그냥 `start`하면 거부된다. 사용자에게 먼저 묻는다:

| 선택 | 처리 |
|---|---|
| 병렬로 진행 | `bouncer start <모드> "<슬러그>" --parallel`<br>별도 브랜치와 레포 밖 worktree가 만들어지고 base 브랜치가 이 시점에 기록된다.<br>끝나면 `bouncer worktree finalize`로 base에 FF 머지된다 |
| 기존 작업 이어하기 | 그 세션의 작업이므로 건드리지 않는다. 해당 세션에서 계속하라고 안내한다 |

## Step 5 — 이후

엔진이 단계마다 지시를 주입한다. 그 지시를 따른다.

- 응답을 끝내려 할 때 조건이 안 맞으면 엔진이 사유를 알려주고 계속 진행시킨다
- 조건이 다 맞으면 자동으로 다음 단계로 넘어간다
- 단계는 스스로 넘길 수 없다. `state.json` 수정은 차단된다

---

## 막혔을 때

**hook이 차단했을 때** — 차단 사유에 무엇이 필요한지 적혀 있다. 그 조건을 충족시킨다.
우회로를 찾지 마라. 차단은 지금 그 행동이 이 단계에서 안전하지 않다는 뜻이고,
우회하면 사용자가 원한 검증이 빠진 채로 결과가 나간다.

**`bouncer run`이 계속 실패할 때** — 출력을 읽고 원인을 고친 뒤 다시 실행한다.
같은 실패가 반복되면 접근이 틀린 것이다. 같은 수정을 반복하지 말고
다른 원인을 찾거나, 사용자에게 상황과 막힌 지점을 보고한다.
설정된 횟수를 넘기면 엔진이 알아서 사용자에게 판단을 넘긴다.

**작업을 접어야 할 때** — `bouncer cancel`로 정리한다.
`.active`를 직접 지우면 상태가 어긋난 채로 남는다.

---

## 사용자가 "앞으로 항상 ~해라"라고 할 때

이번 작업 한정인지 앞으로 계속인지 먼저 구분한다. 잘못 판단하면
한 번짜리 요청이 영구 규칙이 되거나, 반복될 규칙이 매번 잊힌다.

| 사용자 말 | 해석 | 처리 |
|---|---|---|
| "이번엔 e2e까지 돌려" | 이번만 | 그냥 한다. yaml은 건드리지 않는다 |
| "작업 끝나면 CHANGELOG도 갱신해" | 애매 | 물어본다 |
| "앞으로 커밋 전엔 항상 린트 돌려" | 계속 | 물어본다 |

애매하거나 반복될 성격이면 AskUserQuestion으로 확인한다.
도구가 없으면 아래 선택지를 텍스트로 제시하고 답을 기다린다 — 문구가 명확해 보여도
확인 없이 `workflow.yaml`을 고치지 않는다. 그건 사용자가 요청한 적 없는 영구 변경이다.

```
❓ 이걸 워크플로우에 넣을까요?
   ○ 이번 작업만        — 지금 한 번만 수행
   ○ 워크플로우에 추가   — 앞으로 모든 작업에 적용 (workflow.yaml 수정)
```

"워크플로우에 추가"를 고르면:

1. 어느 단계에 넣을지 정한다:
   - "작업 끝나면 ~" → `finalize` 앞 (커밋 전에 끝내야 할 정리)
   - "커밋 전에 ~" → `finalize`의 첫 step
   - "구현하면서 ~" → `implement` / "검증할 때 ~" → `verify`
   - 성격이 뚜렷이 다른 묶음이면 새 스테이지로 만들고 체인 배열에 끼워넣는다
2. 자동 검증이 가능하면 `run`, 사람 판단이 필요하면 `inject`로 쓴다.
   강제할 것이면 `blocking: true`, 매번 물어볼 성격이면 `optional: true`
3. 수정 전에 추가할 yaml을 사용자에게 그대로 보여주고, **승인을 받은 뒤에** 고친다
4. Edit 도구로 `.claude/ai-bouncer/workflow.yaml`을 수정한다
5. `bouncer check`로 검증한다. 실패하면 되돌린다
6. 다음 세션부터 적용된다고 알린다 (이번 작업의 규칙은 시작 시점에 고정돼 있다)

`forbid`를 약화시키는 방향(차단 해제)은 사용자가 명시적으로 요구할 때만 한다.
게이트가 귀찮다는 이유로 규칙을 무르면 그 규칙을 만든 이유가 사라진다.

---

## 명령

| 명령 | 용도 |
|---|---|
| `bouncer scan` | 상태·모드·선택항목 (시작 전 1회) |
| `bouncer start <모드> "<슬러그>"` | 작업 시작 |
| `bouncer status` | 현재 단계와 남은 조건 |
| `bouncer run <step-id>` | 검증 명령 실행 후 결과 기록. 명령 문자열은 엔진이 소유한다 |
| `bouncer done <step-id>` | 사람 확인이 필요한 step 완료 처리 |
| `bouncer cancel` | 작업 취소 |
| `bouncer worktree finalize` | 병렬 작업을 base로 FF 머지하고 정리 |
| `bouncer check` | `workflow.yaml`을 고친 뒤 유효한지 검사 |

## 하지 말 것

- 모드를 사용자 대신 고르기
- 물을 수단이 없다는 이유로 사용자 몫의 결정을 대신 내리기
- `state.json` / `.active` / `workflow.compiled.json` 직접 수정
- 검증 명령을 직접 타이핑해 실행하고 "통과했다"고 보고하기
  → `bouncer run`으로 해야 결과가 증거로 남는다. 직접 실행한 것은 기록되지 않아
    엔진이 계속 미충족으로 판정한다
- 실패한 것을 통과로 보고하기
- 완료 후 사용자 지시 없이 새 작업 시작하기