executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
dev-bounce코드를 고치거나 새로 짜는 작업을 단계별 워크플로우로 진행한다. 버그 수정, 기능 구현, 리팩터링, 설정·의존성 변경, "이거 고쳐줘" / "이 기능 추가해줘" / "왜 안 되는지 보고 고쳐봐" 같은 요청에 파일을 건드리기 전 반드시 먼저 호출할 것. 계획 승인·검증 통과·커밋을 엔진이 강제하는데, 이 스킬로 작업을 시작해야만 그 강제가 걸린다 — 스킬 없이 바로 Edit/Write하면 아무 규칙도 적용되지 않은 채 진행된다. 질문·설명·코드 읽기만 하는 요청에는 쓰지 않는다.
Independent GitHub snapshot · Automated classification · Original documentation governs
작업을 스테이지 체인으로 진행한다. 각 단계에서 무엇을 하고 무엇이 금지되는지는
프로젝트의 workflow.yaml에 정의돼 있고, 엔진이 단계마다 지시를 주입한다.
이 문서에 워크플로우 내용은 없다. 시작 절차만 있다. 시작한 뒤에는 주입되는 지시를 따르면 된다.
이 문서는 몇 군데에서 AskUserQuestion으로 사용자에게 물으라고 한다. 그 도구가 없는 컨텍스트도 있다(서브에이전트, 위임 실행 등).
그럴 때는 추측해서 진행하지 말고 멈춘다. 선택지를 텍스트로 그대로 제시하고 사용자 답을 기다린다. 도구가 없다는 건 "알아서 하라"는 뜻이 아니다.
물어야 하는 것들은 전부 사용자만 답할 수 있는 것이기 때문이다 — 어느 모드로 갈지, 남의 작업과 병렬로 갈지, 이 규칙을 앞으로도 적용할지. 문구가 명확해 보여도(예: "앞으로 항상") 추측으로 진행하면 사용자가 원한 적 없는 영구 변경이 남는다. 되돌리는 비용이 묻는 비용보다 훨씬 크다.
blocking: plan_approved는 ExitPlanMode가 실제로 승인된 것만 인정한다.
그런데 비대화 세션(claude -p 등)에는 EnterPlanMode / ExitPlanMode가 아예 없다.
그 세션에서 plan 워크플로우를 시작하면 충족할 방법이 없는 조건에 갇힌다.
도구가 없다는 걸 확인했으면 조용히 멈춰 있지 말고 막힌 이유와 빠져나갈 길을 알려라:
plan 대신 simple 워크플로우로 시작한다 (계획 단계가 없다), 또는승인을 위조하거나 bouncer done으로 우회하지 않는다 — 그러면 게이트가 있으나 마나다.
아직 시작하지 않았다면 bouncer start를 하지 말고, 이미 시작했다면 bouncer cancel로
정리한 뒤 안내한다. 갇힌 작업을 그대로 두면 다음 세션까지 잠금이 남는다.
bouncer scan
항상 부른다. 0.01초짜리고, 세션 시작 때 주입된 정보는 그 사이 다른 세션이 작업을 시작했으면 이미 낡았을 수 있다.
STATE MINE <경로> <워크플로우> <단계> 이 세션이 이어서 할 작업
STATE OTHER <경로> <단계> <나이> 다른 세션이 잡고 있는 작업
STATE NONE 아무것도 없음
ORPHAN <task-id> <워크플로우> <단계> 잠금이 풀린 미완 작업 (이어받을 수 있다)
ERROR <메시지> 설정을 읽을 수 없다 — 사용자에게 그대로 알린다
WORKFLOW <이름> <설명> 모드 선택지
OPTION <워크플로우> <단계> <id> <이름> 시작할 때 물어볼 선택 항목
| 결과 | 다음 |
|---|---|
MINE | 이미 진행 중이다. 요청이 그 작업의 연장이면 bouncer status로 남은 조건을 보고 이어서 한다. Step 2~4는 건너뛴다 |
OTHER만 있음 | 다른 세션이 작업 중이다. Step 2로 가되 Step 4에서 병렬 여부를 묻는다. 그 세션이 죽은 것 같으면 bouncer release로 누가 잡고 있는지 보여주고 회수 여부를 사용자에게 묻는다 |
ORPHAN 줄이 있음 | 잠금이 풀린 미완 작업이다 (세션이 죽었거나 회수됨). 요청이 그 작업의 연장인지 사용자에게 확인하고, 맞으면 bouncer resume <task-id> 로 이어받는다 |
NONE | Step 2 |
bouncer: command not found가 나오면 두 가지 경우다. 먼저 구분해라:
.claude/ai-bouncer/engine/bouncer.sh 가 있다 → 설치는 됐고 ~/.local/bin 이
PATH에 없는 것뿐이다. 그 경로로 직접 부르고, 사용자에게 PATH 추가를 알린다.설치돼 있는데 "설치 안 됨"으로 오진하면 워크플로우 없이 작업하게 된다.
| 요청 성격 | 처리 |
|---|---|
| 질문·설명·코드 읽기 | 스킬을 쓰지 않고 그냥 답한다 |
| 계획을 세우려면 탐색이 먼저 필요 | 읽기 전용으로 탐색한다(수정 금지). 끝나면 Step 1부터 다시 시작한다 |
| 개발 의도는 있으나 무엇을 고칠지 불명확 | AskUserQuestion으로 구체화한다. "개발 작업으로 처리할까요?" 같은 확인 질문은 답이 뻔해서 사용자 시간만 쓴다 |
| 개발 요청 | Step 3 |
Step 1의 WORKFLOW 줄을 그대로 AskUserQuestion 선택지로 만든다.
모드가 정해지면 그 모드의 OPTION 줄들을 스테이지별로 묶어 다시 묻는다
(multiSelect, 기본 전체 켜짐). 선택지가 4개를 넘으면 질문을 나눠서 여러 번 호출한다.
OPTION이 없으면 이 질문은 건너뛴다.
모드는 사용자가 고른다. 계획 단계가 번거롭다는 이유로 가벼운 모드를 대신 고르면 사용자는 자기가 원한 검증이 빠진 줄 모른 채 결과를 받는다. 그건 워크플로우 회피다. AskUserQuestion을 쓸 수 없으면 위 "물어야 하는데 물을 수단이 없을 때"를 따른다.
bouncer start <모드> "<슬러그>" [--off <끈-항목-id>] ...
슬러그는 영문 소문자와 하이픈으로 짧게 쓴다 (payment-bug, add-oauth).
디렉토리 이름이 되므로 한글이나 공백을 쓰면 도구에 따라 정렬·경로 처리가 어긋난다.
Step 1에 OTHER가 있었으면 그냥 start하면 거부된다. 사용자에게 먼저 묻는다:
| 선택 | 처리 |
|---|---|
| 병렬로 진행 | bouncer start <모드> "<슬러그>" --parallel별도 브랜치와 레포 밖 worktree가 만들어지고 base 브랜치가 이 시점에 기록된다.출력에 나온 worktree 경로로 먼저 cd 하고, 이후 편집·검증·커밋을 전부 거기서 한다. 메인 레포를 고치면 엔진이 막는다 — 검증이 손대지 않은 트리를 보게 되기 때문이다.끝나면 bouncer worktree finalize로 base에 FF 머지된다 |
| 기존 작업 이어하기 | 그 세션의 작업이므로 건드리지 않는다. 해당 세션에서 계속하라고 안내한다 |
엔진이 단계마다 지시를 주입한다. 그 지시를 따른다.
state.json 수정은 차단된다hook이 차단했을 때 — 차단 사유에 무엇이 필요한지 적혀 있다. 그 조건을 충족시킨다.
우회로를 찾지 마라. 차단은 지금 그 행동이 이 단계에서 안전하지 않다는 뜻이고,
우회하면 사용자가 원한 검증이 빠진 채로 결과가 나간다.
단, plan 단계에서 계획 작성 자체가 막혔다면 묻지 말고 스스로 복구한다:
bouncer cancel → 막혔던 준비 작업 → bouncer start <같은 모드> "<같은 슬러그>" → ExitPlanMode.
bouncer run이 계속 실패할 때 — 출력을 읽고 원인을 고친 뒤 다시 실행한다.
같은 실패가 반복되면 접근이 틀린 것이다. 같은 수정을 반복하지 말고
다른 원인을 찾거나, 사용자에게 상황과 막힌 지점을 보고한다.
설정된 횟수를 넘기면 엔진이 알아서 사용자에게 판단을 넘긴다.
작업을 접어야 할 때 — bouncer cancel로 정리한다.
.active를 직접 지우면 상태가 어긋난 채로 남는다.
이번 작업 한정인지 앞으로 계속인지 먼저 구분한다. 잘못 판단하면 한 번짜리 요청이 영구 규칙이 되거나, 반복될 규칙이 매번 잊힌다.
| 사용자 말 | 해석 | 처리 |
|---|---|---|
| "이번엔 e2e까지 돌려" | 이번만 | 그냥 한다. yaml은 건드리지 않는다 |
| "작업 끝나면 CHANGELOG도 갱신해" | 애매 | 물어본다 |
| "앞으로 커밋 전엔 항상 린트 돌려" | 계속 | 물어본다 |
애매하거나 반복될 성격이면 AskUserQuestion으로 확인한다.
도구가 없으면 아래 선택지를 텍스트로 제시하고 답을 기다린다 — 문구가 명확해 보여도
확인 없이 workflow.yaml을 고치지 않는다. 그건 사용자가 요청한 적 없는 영구 변경이다.
❓ 이걸 워크플로우에 넣을까요?
○ 이번 작업만 — 지금 한 번만 수행
○ 워크플로우에 추가 — 앞으로 모든 작업에 적용 (workflow.yaml 수정)
"워크플로우에 추가"를 고르면:
finalize 앞 (커밋 전에 끝내야 할 정리)finalize의 첫 stepimplement / "검증할 때 ~" → verifyrun, 사람 판단이 필요하면 inject로 쓴다.
강제할 것이면 blocking: true, 매번 물어볼 성격이면 optional: truedone으로 끝난 뒤에 적용한다..claude/ai-bouncer/workflow.yaml을 수정한다bouncer check로 검증한다. 실패하면 되돌린다forbid를 약화시키는 방향(차단 해제)은 사용자가 명시적으로 요구할 때만 한다.
게이트가 귀찮다는 이유로 규칙을 무르면 그 규칙을 만든 이유가 사라진다.
| 명령 | 용도 |
|---|---|
bouncer scan | 상태·모드·선택항목 (시작 전 1회) |
bouncer start <모드> "<슬러그>" | 작업 시작 |
bouncer todo | 할 일 목록 보기 (plan 모드면 승인된 계획에서 자동으로 채워진다) |
bouncer todo add '<항목>' … | 요청 범위를 목록으로 세운다 (checklist 게이트가 이걸 센다) |
bouncer todo done <n> | 그 항목을 실제로 구현한 뒤 체크 |
bouncer todo drop <n> | 범위에서 뺀다 (기록에 남으니 사유를 사용자에게 알린다) |
bouncer status | 현재 단계와 남은 조건 (각 step의 id: 도 함께 나온다) |
bouncer run <step-id> | 검증 명령 실행 후 결과 기록. 명령 문자열은 엔진이 소유한다 |
bouncer done <step-id> | 할 일을 마친 step 완료 표시 (사람 확인은 없다) |
bouncer cancel | 작업 취소 |
bouncer skip <step-id> | 엔진이 포기한 조건을 이번 작업에서만 건너뛴다 (사용자가 요청할 때만) |
bouncer release [--force] | 죽은 세션이 남긴 잠금 확인 / 회수 |
bouncer resume | 이어받을 수 있는 미완 작업 목록 (인자 없으면 조회) |
bouncer resume <task-id> | 그 작업을 이어받는다 (scan의 ORPHAN 줄) |
bouncer workflows | 정의된 모드 목록 |
bouncer worktree finalize | 병렬 작업을 base로 FF 머지하고 정리 |
bouncer check | workflow.yaml을 고친 뒤 유효한지 검사 |
state.json / .active / workflow.compiled.json 직접 수정workflow.yaml 고치기 (엔진이 막는다 — 끝난 뒤에 한다)bouncer skip / bouncer release --force 쓰기bouncer run으로 해야 결과가 증거로 남는다. 직접 실행한 것은 기록되지 않아
엔진이 계속 미충족으로 판정한다