Use when writing or modifying code in this project — 구현 착수, 플랜 실행, 버그 수정, 리팩토링 등 코드 diff를 만들기 시작하는 모든 시점. 직접 수정이든 서브에이전트 dispatch 구현이든 무관 — 코드는 서브에이전트가 만지고 메인 세션은 브리프만 쓰는 경우에도 첫 dispatch 전에 invoke한다. 플랜 파일 유무와 무관하게 적용. superpowers 코딩 절차(test-driven-development·executing-plans·subagent-driven-development)를 대체하지 않는 컴패니언 — 프로젝트 종속 절차(변경 경로→테스트 스킴 계산, tuist generate 시점, 짝지어진 두 위치, rules·구조 패턴 확인, 리팩터 게이트, 완료 판정)를 주입한다. Triggers on "구현하자", "플랜 실행하자", "고치자", "리팩토링하자", "서브에이전트 시켜서 구현하자" 등 코드 수정이 시작될...
Installs into .claude/skills of the current project.
Are you the author of Implement?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/sudopark-implement)
---
name: implement
description: Use when writing or modifying code in this project — 구현 착수, 플랜 실행, 버그 수정, 리팩토링 등 코드 diff를 만들기 시작하는 모든 시점. 직접 수정이든 서브에이전트 dispatch 구현이든 무관 — 코드는 서브에이전트가 만지고 메인 세션은 브리프만 쓰는 경우에도 첫 dispatch 전에 invoke한다. 플랜 파일 유무와 무관하게 적용. superpowers 코딩 절차(test-driven-development·executing-plans·subagent-driven-development)를 대체하지 않는 컴패니언 — 프로젝트 종속 절차(변경 경로→테스트 스킴 계산, tuist generate 시점, 짝지어진 두 위치, rules·구조 패턴 확인, 리팩터 게이트, 완료 판정)를 주입한다. Triggers on "구현하자", "플랜 실행하자", "고치자", "리팩토링하자", "서브에이전트 시켜서 구현하자" 등 코드 수정이 시작될 때 — superpowers 코딩 스킬과 함께 invoke. Does NOT trigger on 코드 조회·분석·설계 논의만 할 때.
---
# Implement — TodoCalendar 구현 컴패니언
**superpowers 절차의 대체가 아니다.** TDD 사이클·플랜 실행 흐름은 superpowers 스킬이 이끈다. 이 스킬은 그 위에 TodoCalendar 종속 지식과 게이트를 주입한다.
## 채점 4축 좌표계 (#690)
작업 결과물(코드) 채점은 4축 순차 관문이다 — 이 스킬이 축1~3 관문을 집행하고, 축4는 review 스킬이 갖는다 — pre-PR whole-branch 레인(상시)과 공개 PR 레인(유저 지시 시). 축4에서 잡힌 finding은 어느 쪽에서 나왔든 "축1~3 중 어디서 잡혔어야 했나" 누수 태깅(axis_leak 레코드)의 좌표로 이 축 번호를 쓴다.
| 축 | 질문 | 관문 |
|---|---|---|
| 1 명세의 TC 표현 | TC가 명세를 나타내는가 | RED 직후 한 줄 선언 (§구현 중) |
| 2 동작 무오류 | 동작 무오류가 TC로 드러나는가 | GREEN — 무조건 통과 |
| 3 구현 품질 | 효율(복잡도)·역할 분배·협업이 합리적인가 | 리팩터 게이트 |
| 4 종합 검사 | 기획 홀·엣지케이스·논리 모순·false positive test·보안·축1~3의 논리적 완결성 | PR 리뷰 — 이 스킬 밖 |
축1~3 실시간 관문은 통과 선언만 남기고 레코드는 쌓지 않는다 — 기록은 소비자(누수 분석)가 있는 축4 쪽에서만.
## 착수
**첫 코드 diff 전에 컨텍스트를 한 번 접는다.** 구현은 계획·정찰 단계보다 훨씬 긴 대화를 만든다. 중간에 접으면 그때까지 쌓인 결정이 요약으로 뭉개지고, 남은 태스크가 뭉개진 요약 위에서 돈다. `/compact` 는 클라이언트 명령이라 세션이 스스로 못 부른다 — **멈추고 유저에게 청한다.**
청하기 전에 **대화에만 있는 사실을 먼저 파일로 내린다.** 요약은 무엇이 중요한지 모르는 채로 접는다. 내릴 자리는 진행 파일·활동 로그·작전명령 부록 D 이고, 어디에도 안 맞으면 메모리다. 내리지 않고 접은 사실은 사라진다.
한 런의 첫 코드 diff 앞에서 한 번이다 — 세션 재개·SDD 중간 태스크에서 다시 청하지 않는다. DP 경계에서 `/clear` 로 비운 뒤 이 DP 의 kickoff·작전명령만 쌓인 세션도 청하지 않는다 — 비운 뒤 쌓인 것이 계획 단계뿐이라 접을 이유가 없고, 그 계획은 이미 파일로 서 있다 (campaign §5).
**작전명령 유무로 흐름만 갈리고 절차는 동일하다:**
- **작전명령 있음** (`docs/operations/<이슈>/opord.md`, 부록 A 가 태스크 순서) → superpowers executing-plans/subagent-driven-development가 부록 A 를 이끈다. 첫 태스크 착수 시 진행 파일(`.operations/<이슈>/progress.md`)의 `명령 상태:` 를 `실행` 으로 갱신하고, 태스크 완료·커밋마다 진행 파일의 태스크 표(상태·커밋 sha·보고)를 갱신한 뒤 이슈 본문 미러를 재조립한다 (opord §6·§8 — SDD ledger 와 별개, 진행 파일은 커밋하지 않는다). **태스크 착수 시에도** 태스크 표의 그 행 상태를 `실행` 으로 갱신하고, 태스크 착수·GREEN·커밋·보고·블로커 같은 유의미한 활동마다 활동 로그(`.operations/<이슈>/activity.md`, opord §8 서식)에 한 줄 append 한다 — **진행 파일·활동 로그를 쓸 때마다 `.claude/scripts/campaign-board-sync.sh <이슈>` 를 짝으로 호출한다** (실패 비차단, 이슈 미러 재조립은 기존 시점 유지 — 활동마다 재조립하지 않는다). 각 태스크에 아래 절차를 적용한다.
- **작전명령 없음** (구두지시·즉흥 수정) → superpowers TDD + 이 스킬만으로 진행한다. 계획 단계만 빠질 뿐, rules 확인 → 패턴 파악 → 구현 → 완료 판정은 동일하게 탄다. **킥오프 씨앗(`.operations/<이슈>/progress.md`)이 있으면 상태 전이는 같다** — 구현 착수 시 `명령 상태:` 를 `실행` 로 올리고 유의미한 활동마다 활동 로그에 한 줄, 둘 다 board-sync 짝호출 (opord §6 의 S 경로). 태스크 표도 이슈 본문 미러도 없다 — 부록 A 가 없어 담을 것이 없고, 이 진행 파일은 상황판 전용이다. 안 올리면 상황판이 구현 내내 `정찰` 로 보인다.
- **페어 프로그래밍 모드** (유저가 명시 선언한 세션) → 턴 규칙·TDD 수준·커밋 시점은 pair-programming 스킬이 이끈다. 이 스킬은 프로젝트 종속 규칙(rules·tuist generate·짝지어진 두 위치·콜사이트 grep) 공급자로만 동작한다.
- **서브에이전트 dispatch 구현** (subagent-driven-development·병렬 dispatch 등) → 서브에이전트는 이 스킬을 스스로 invoke하지 못한다. dispatch하는 메인 세션이 첫 브리프 작성 전에 이 스킬을 invoke하고, 아래 절차를 브리프로 승계시킨다. "내가 직접 코드를 안 만지니 해당 없음"은 성립하지 않는다 — 코드 diff가 시작되는 주체가 누구든 발동한다. 갭 보고 루프(rules·플랜)의 유저 반문은 메인 세션이 중계한다 — 브리프에 "갭 발견 시 추측으로 채우지 말고 보고 후 중단"을 명시한다. 축1 선언·리팩터 게이트 선언은 브리프 승계와 컨트롤러 검수로 갈음한다 — 컨트롤러가 매 GREEN마다 선언을 재생산하지 않는다 (직접 구현 시에만 선언 관문).
- **갈음 대상엔 산출물 4종이 든다** — 축1 3칸 선언·축1 실측 1발 줄·TC 실효 줄·리팩터 게이트 신설·수정물 줄. 브리프에 그 형식을 그대로 싣고 서브에이전트 보고로 받는다. **대상에 TC가 존재할 수 없으면**(리소스·문서·record 전용 스냅샷 스위트) 축1 3칸 선언·축1 실측 1발 줄·TC 실효 줄 대신 **그 대상의 검증 수단 보고**(parity·plutil·lint·촬영 이미지 확인)를 싣는다. 직접 구현일 때도 같다 — 축1 선언은 §구현 중 `TC 작성이 구조적으로 불가할 때`의 생략 형식으로 남기고, **되돌릴 TC 가 없으니 축1 실측 1발 줄도 그 검증 수단 보고로 갈음한다**. 이 경로는 이행이다.
- **태스크별 리뷰어 dispatch는 돌리지 않는다.** superpowers SDD가 매 태스크마다 강제하는 task review·scoped re-review는 이 프로젝트에서 무효다 (그 스킬의 `Never skip the task review`를 여기서 오버라이드한다). 태스크 완료 판정은 **서브에이전트 자체 테스트 + 컨트롤러 검수**(§착수)로 하고 ledger를 `Task <N>: complete (commits <base7>..<head7>, self-test + controller review)`로 닫는다 — SDD 원문의 `review clean`·`parked` 표기는 리뷰가 돈 것을 전제한 값이라 쓰지 않는다. orchestrate 스킬과 같은 검증 모델이다. 실행 중 신호(DONE_WITH_CONCERNS·테스트 불안정·갭 보고)도 리뷰 dispatch로 넘기지 않고 컨트롤러가 그 자리에서 처리한다 — correctness·scope 관련이면 재dispatch로 고치고, observation이면 확인만 하고 진행, 갭이면 유저 반문.
- **에이전트 리뷰는 PR 직전 최종 whole-branch 1회로 모은다.** 이 리뷰는 생략 대상이 아니다 — 태스크 단위 그물이 없어진 만큼 축4의 상시 관문이 이것 하나다. 그래서 축1~3 귀속을 판정해 `axis_leak`을 기록한다 (시점·명령·판정 기준은 review 스킬 §6 — pre-PR 레인은 PR 생성 직후) — 기록이 빠지면 관문이 줄어든 만큼 누수 집계도 같이 죽는다.
- **리뷰를 돌릴 수 없는 조건이면 갈음한다** — 유저가 리뷰 없이 PR 생성을 명시 지시했거나, 세션 지시가 Agent tool 호출을 금지한 경우. 컨트롤러가 브랜치 diff를 직접 자기검토(review 스킬 §2 관점 세트 기준)하고 그 결과를 대화로 보고한다. `axis_leak` 기록 의무는 그대로다. 이 경로는 이행이고, 그 밖의 생략은 이탈이다.
시작할 때:
- **베이스 브랜치** — 브랜치 지정 지시가 없으면 지금 워크트리의 베이스 브랜치를 최신 develop 에 맞춘 뒤 거기서 `features/` 브랜치를 딴다. 이미 지정된 작업 브랜치에 있으면 유지.
- 메인 워크트리의 베이스는 `develop` (`git pull origin develop`), 서브 워크트리는 `base/<워크트리명>` — develop 을 미러링하는 상시 브랜치다 (`git fetch origin develop && git switch --no-track -C base/<워크트리명> origin/develop`). **베이스 브랜치엔 직접 커밋하지 않는다** — 리셋 전에 `git log origin/develop..base/<워크트리명>` 으로 얹힌 커밋이 없는지 먼저 보고, 잡히면 리셋하지 말고 유저에게 보고한다.
- **워크트리는 새로 만들지 않는다** — 작업 브랜치는 **베이스 브랜치가 이미 체크아웃된 워크트리**에서 딴다. 워크트리는 유저가 미리 만들어 둔 것만 쓰고, 새로 생성하거나 지금 작업 중인 자리를 다른 워크트리로 옮기지 않는다. 유저가 베이스 브랜치를 지정했다면 그게 체크아웃된 워크트리가 곧 작업 자리다. **superpowers SDD의 Setup(`using-git-worktrees`로 격리 워크스페이스 생성·확인)은 이 조항이 오버라이드한다** — 그 지시를 따르면 유저가 열어둔 작업 자리를 벗어나고, 워크트리마다 빌드 캐시가 갈려 증분 빌드도 깨진다. orchestrate 병렬 모드가 sub-work마다 워크트리를 배정하는 것은 이 금지 대상이 아니다 — 그 배정도 **기존 워크트리 중에서** 고른다.
- 변경 대상 경로에 걸리는 `.claude/rules/*.md` 조항을 확인하고, 구현 결정 시점에 해당 조항을 적극 invoke한다. 확인한 결과를 첫 diff 전에 대화에 한 줄로 남긴다 — `착수: rules <연 파일> / child CLAUDE.md <연 파일>`. 걸리는 파일은 각 rules 파일 frontmatter 의 `paths:` glob 을 변경 대상 경로에 대 보고 고른다 (`grep -A6 '^paths:' .claude/rules/*.md`) — 디렉토리 이름만 보고 짐작하면 `composition-root.md` 같은 파일이 빠진다.
- child CLAUDE.md가 있는 프레임워크(Domain·Repository·각 Presentation 등)를 수정할 땐 해당 child CLAUDE.md를 확인하고, 수정 후 그 규칙과 어긋남이 없는지 재점검한다.
- 동종 컴포넌트를 grep해 구조 패턴(상태관리·합성·추상화 수준)을 파악하고 그 패턴을 따른다. 요구사항만 보고 즉흥 구현하지 않는다.
- 서브에이전트에 구현을 dispatch할 땐 브리프에 적용 rules 조항의 **요지를 발췌해 싣는다** — 파일 경로·조항명만 던지지 않는다 (path 매칭 자동 로드는 서브에이전트에겐 없다). 따라야 할 구조 패턴도 함께 명시한다. 승계할 때 넷을 지킨다:
- **조항 문언 그대로 승계한다** — 요구 수준을 올리지 않는다. 판정·기록을 요구하는 조항(축1 판별력·TC 실효 스캔)을 실행 요구로 바꾸면 서브에이전트가 구현을 되돌려 테스트를 다시 돌린다. **축1 실측 1발은 거꾸로 실행을 요구하는 조항이니** 그 블록은 문언 그대로 싣는다 — 명세 항목당 한 번이라는 한도까지 함께 승계해야 매 TC 로 번지지 않는다.
- **검증 범위는 사다리 자체를 발췌한다** — 4단계와 `-only-testing:<테스트타겟>/<클래스>[/<메서드>]` 형식, "최소 범위에서 멈춘다"를 함께 싣는다. 최종 스킴만 적으면 국소 확인에도 스킴 전체가 돈다. "전체 스킴 통과"를 기본값으로 승계하지 않는다.
- **증분 빌드 원칙**(§구현 중 — clean·DerivedData 삭제 금지, `-derivedDataPath` 신설 금지, 불필요 tuist generate 금지)과 **파일 추가/삭제 직후 generate → 그 뒤 테스트** 순서(§구현 중·§완료 판정)도 발췌한다.
- **글 규범을 발췌한다** — CLAUDE.md §1 의 비문·번역체와 피동·줄임말과 상투어·훈계형 마무리 금지 넷 전부. 서브에이전트가 쓰는 커밋 메시지·보고·문서가 이 경로 말고는 규범에 닿지 않는다.
- 브리프에 **"테스트는 포그라운드로 돌리고 `sleep`·`Monitor` 폴링을 쓰지 않는다"를 명시한다.** 백그라운드 작업은 끝나면 자동 재invoke되는데, 폴링을 얹으면 폴링 중에 턴이 끝나 컨트롤러엔 완료로 보인다.
- **대기 상태로 끝난 서브에이전트를 재개시키기 전에 진행 중인 백그라운드 작업을 확인한다** — 직전 dispatch가 백그라운드로 띄운 프로세스가 아직 도는지 `pgrep`으로 보고, 돌고 있으면 종료를 기다린 뒤 재개시킨다. 안 그러면 재개한 쪽이 그 실행을 버리고 처음부터 다시 돈다.
- 서브에이전트 산출물 검수 때 브리프에 실은 rules 조항의 위반 여부를 항목별로 스캔하고, **브리프가 요구한 명세 항목과 산출물을 대조한다** — 컴파일·테스트 통과는 rules 준수도 명세 충족도 보증하지 않는다. 대조 대상엔 승계시킨 산출물 4종(축1 3칸 선언·축1 실측 1발 줄·TC 실효 줄·신설·수정물 줄)도 든다 — 빠졌으면 받아낸 뒤 검수한다. **서브에이전트가 쓴 커밋 메시지·보고문은 CLAUDE.md §1 글 규범으로 함께 훑는다** — 정형 보고 3종과 달리 산문이라 대조 항목이 따로 없고, 여기서 안 보면 어디서도 안 걸린다. 태스크 리뷰어가 없으므로(위 태스크별 리뷰어 dispatch 금지) 이 대조가 spec 판정의 유일한 자리다.
## 구현 중
- **명세 항목 뽑기 — 첫 RED 전 1회.** 이 태스크가 덮어야 할 명세 항목 목록을 먼저 적는다. 목록은 첫 테스트 파일을 열기 전에 대화에 `명세 항목: <항목들>` 한 줄로 남긴다 — 테스트를 먼저 세우고 목록을 뒤에 뽑으면 이미 쓴 TC 에 맞춰 목록을 짜게 된다. 플랜·이슈 문장을 그대로 옮기면 해피패스만 남으므로, 아래 다섯 축을 각각 물어 항목을 늘린다. **여기서 안 뽑힌 항목은 TC가 없어도 선언이 형식적으로 통과해 관문이 못 잡는다** — 축1이 새는 자리는 대개 판정이 무른 게 아니라 명세 항목 목록이 짧은 것이다. 플랜·이슈가 "이 축은 해당 없음"을 단정했어도 다섯 축은 각자 다시 답한다 — 플랜 단계의 단정은 탐색 시점 지식이라 구현 diff가 만드는 재진입·갱신 경로를 모른다.
- **실패 축** — 이 동작이 실패하는 경로(throw·원격 에러·권한 거부)가 있나. 실패한 뒤 뭐가 보장돼야 하나 — 캐시·큐·화면 상태, 재시도가 쓸 값의 보관
- **순서 축** — 신규 설치·최초 실행·마이그레이션처럼 선행 상태가 없는 순서로 들어오면 뭐가 달라지나. **선행 UI·시스템 모달과 겹치는 순서도 이 축이다** — 권한 알럿·다이얼로그·시트가 이미 떠 있거나 곧 뜨는 자리에 이 동작이 끼어들면 유저가 어느 쪽에 답하게 되나
- **범위 축** — 대상이 단건인가 집합(반복 시리즈·다계정·전체 선택)인가. 집합 경로가 명세에 있나. **같은 명세가 걸리는 진입점이 여럿인지도 이 축이다** — 한 진입점에서 확인한 동작을 나머지 진입점이 각각 갖는지 grep으로 센다. **같은 명세가 지나가는 레이어 층(뷰모델·usecase·저장소)도 각각 진입점이다** — 양 끝 층만 TC 로 덮이면 가운데 층의 재조립이 값을 떨궈도 초록이다
- **재진입 축** — 같은 액션이 응답 대기 중에 다시 들어오면, 또는 앞선 요청이 아직 안 끝났으면 뭐가 달라지나. 늦게 끝난 응답이 화면·서버 상태를 덮어쓰나. **같은 대상의 값이 되돌려지는 경로(reset·discard·취소)도 이 축이다** — 되돌린 뒤 화면·뷰 상태가 옛 값을 붙들고 있나
- **부재 축** — 이 동작이 읽는 값이 비어서 들어오면 뭐가 달라지나. NULL 컬럼·빈 배열·nil 옵셔널·빈 문자열이 각각 다른 경로이고, 디코딩이 그 자리에서 기본값을 세우면 그 기본값이 명세와 같나. 저장 왕복이 걸리면 **쓸 때 비어 있던 칸이 읽을 때도 비어 돌아오나** — 시드가 모든 칸을 채우고 들어가면 빈 경로를 TC 가 한 번도 안 지난다
각 축은 "해당 없음"도 답이다 — 답을 적고 넘어간다. 이 목록이 아래 선언의 `<명세 항목>` 후보 전체다.
- **RED 직후 축1 선언** — 방금 쓴 TC가 표현하는 명세 항목(위 목록의 한 항목)과, 그 단언이 실패하려면 프로덕션의 무엇이 깨져야 하는지를 한 줄로 선언한다:
```
축1: <TC명> ⇢ <명세 항목> | 깨지면 빨개짐: <프로덕션 지점 — 파일·심볼·분기·상수>
```
**세 번째 칸이 관문이다.** 프로덕션 지점을 못 적으면(느슨한 단언·스텁이 못 만드는 경로·도메인상 불가능한 픽스처) 그 TC는 없는 것과 같다 — GREEN으로 가지 않고 TC부터 재작성한다. 앞 두 칸만 채운 선언은 "TC가 있는가" 확인에 그쳐 명세를 못 담는 TC도 형식적으로 통과시킨다. 선언 시 **이 TC**와 **이 명세 항목의 TC 집합**을 각각 확인한다:
*이 TC* —
- **판별력** — given을 다르게 골라도 통과하나. 나아가 **구현의 비교 연산자를 뒤집거나(`<=` → `<`) 분기를 반대로 바꿔도 green인가** — green이면 그 경계·분기를 찌르는 given으로 다시 고른다. **조건이 `A && B`·`A || B`처럼 복합이면 항을 하나씩 지워도 green인가** — given이 대각선으로만 놓이면(각각 한 항만 참) 어느 항을 지워도 전부 초록이라, 항마다 그 항만 판정을 뒤집는 given이 있어야 한다. **단언의 양변이 같은 소스에서 오면**(검증 대상 함수·프로퍼티로 기대값을 만드는 자기비교) 판별력이 0이다 — 양변이 함께 틀려도(둘 다 nil이어도) 초록이다. 기대값은 리터럴·독립 계산으로 세운다. **같은 값을 두 인자로 넣는 것도 같다** — `x.isSame(x) == true`처럼 재귀성·항등만 보는 단언은 구현이 무엇이든 초록이라 세 번째 칸에 적을 프로덕션 지점이 없다. **TC 이름이 순서·보존·횟수를 주장하면 단언도 그것을 본다** — 이름은 "권한 요청 뒤 마이크" 인데 단언이 호출 여부뿐이면 순서가 뒤집혀도 초록이다. 구현이 아직 없는 첫 TC면 이 확인만 GREEN 직후로 미룬다. **TC 하나하나의 확인은 판정이다** — 매 TC 마다 구현을 되돌려 테스트를 다시 돌리지 않는다 (TC 실효 스캔도 같다). 실측은 명세 항목마다 한 번 몰아서 한다 (아래 축1 실측 1발). 브리프 승계는 §착수 소관
- **픽스처 유효성** — given으로 세운 상태 조합이 도메인상 실제로 발생하나. 커버리지를 채우려고 조립한 조합이면 검증하는 대상이 없는 TC다. 조합만이 아니라 **값도 구분을 만들게 고른다** — 서로 달라야 의미 있는 두 값(마스터/인스턴스 id, 원본/회차 시각)이 우연히 같으면 그 경로의 회귀가 초록이고, 경계 정밀도(소수점 초 절삭·반올림)가 명세에 걸리면 절삭이 드러나는 값을 쓴다. 상태 조합이 도메인 불변식(순서·선후)을 지키는지도 여기서 본다. **stub 이 조회 키(id·좌표)를 무시하고 값을 돌려주면** 엉뚱한 키로 읽어도 초록이다 — 키마다 다른 값을 심는다
- **결정성** — wait를 방출 횟수(expectedFulfillmentCount 류)에 결합하는 등 단언이 타이밍에 기대나. 플레이키를 타임아웃 상향으로 덮지 않는다
*이 명세 항목의 TC 집합* —
- **제거분** — 이번 diff가 안전장치·기존 동작을 없앴으면 그 부재가 만드는 새 동작을 덮는 TC가 있나. 추가는 TC를 부르지만 제거는 조용히 지나간다
- **신규 공개 계약** — 추가한 public 메서드·프로토콜 요구사항에 Imple 레벨 TC가 있나. stub 플래그 검증은 계약 검증이 아니다
- **형제 기준선** — 이번에 추가·수정한 메서드의 형제가 가진 TC 종류를 grep해 대조한다. 형제는 셋이고 각각 따로 본다: 같은 타입·같은 프로토콜의 **다른 메서드** / 같은 계약의 **다른 구현체**(구글·애플처럼 서비스별로 갈린 대응 컴포넌트 — 한쪽에만 이식된 TC가 여기서 드러난다) / 같은 테스트 파일의 **형제 테스트**(파라미터화 케이스 수·커버리지 종류). 형제가 실패 케이스 3종을 갖는데 새 메서드엔 성공 경로만 붙었으면, 그 차이에 근거가 있나. 신규 대상만 자기완결적으로 보면 바로 옆의 커버리지 기준선이 시야에 안 들어온다. **같은 규칙을 다른 경로가 해석하는 자리**(위젯 provider 의 해석과 갤러리 미리보기의 해석처럼)도 형제다 — 같은 입력에 두 경로가 같은 결과를 내는지 대조한다. 같은 대상을 덮는 **스냅샷 테스트·픽스처**도 형제다 — 형제 diff가 스냅샷을 함께 갱신했으면 이번 변경도 갱신 대상인지 본다
- **행복 경로 밖** — 실패 경로(throw·에러 응답)·입력 정규화(공백·빈값 → nil)·순서 의존이 명세에 있으면 각각 TC가 붙었나. "정상 입력이 정상 출력을 낸다" 하나로는 셋 다 안 드러난다. 명세 항목 자체에 그 축이 없으면 이 확인은 통과해버린다 — 상류가 §명세 항목 뽑기다
- **더블 왕복** — 이번 diff가 추가·수정한 stub·spy 필드에 **값을 보는 단언**이 있나. 배선만 되고 아무도 안 읽는 필드는 커버리지 착시고, **호출 여부(`didCall == true`·nil 아님)만 보는 단언도 왕복이 아니다** — 실린 payload·갱신된 상태를 단언한다. "호출됐다"는 인자에 엉뚱한 값을 실어도 초록이다. 단언을 붙이거나 필드를 지운다
**TC 실효 스캔** — 명세 항목 구현이 GREEN으로 끝난 시점(리팩터 게이트 직전)에 **프로덕션 diff를 기준으로** 훑는다. **대상 목록을 먼저 명령 출력으로 고정한다.** 대상은 **이번 명세 항목이 만든 프로덕션 변경**이다 — 앞 항목에서 이미 스캔한 hunk는 다시 세지 않는다. 직전 항목이 커밋으로 닫혔으면 `git diff <그 커밋>..HEAD -- '*/Sources/*'`, 아직 커밋 전이면 `git diff HEAD -- '*/Sources/*'`로 변경 hunk를 열거하고 그 목록의 **모든 항목**에 한 줄씩 답한다. 기준만 diff로 두고 열거를 기억에 맡기면 눈에 띄는 변경만 훑고 끝난다. 각 항목의 답은 그 변경이 만든 분기·에러 래핑·보존 값에 대해 "이걸 되돌리면 어떤 TC가 빨개지나"다. 빨개질 TC를 못 대면 그 변경을 검증하는 TC가 없는 것이다 — TC를 붙이거나 기존 단언을 조인다. 기존 TC가 그 경로를 지나가 보여도 단언이 느슨하거나(`(any Error).self`는 래핑 제거를 못 잡는다) 스텁이 그 분기를 만들 수 없으면 같다. 집합 쪽 다섯은 이 스캔에서 자주 새는 자리다 — 다섯 각각에 같은 질문을 적용해 확인하되 각 항목의 단서는 그대로 남는다 (stub 플래그 단언이 빨개지는 것은 계약 검증이 아니다). TC를 하나씩 쓰는 동안엔 빠진 자리가 안 보이고, **TC를 새로 안 쓴 프로덕션 변경은 RED 선언이 아예 없다** — 그래서 판정 대상은 TC지만 열거 기준은 프로덕션 diff다.
스캔 결과는 프로덕션 변경 항목별 한 줄로 남긴다 — `TC 실효: <프로덕션 변경> → <되돌리면 빨개지는 TC>`. 못 적는 항목이 남은 채로 리팩터 게이트에 들어가지 않는다. 이 스캔이 새는 이유는 판정이 무른 게 아니라 **머릿속으로만 돌아 돌았는지 여부조차 확인되지 않기** 때문이다.
**축1 실측 1발** — 명세 항목이 GREEN 으로 닫힌 뒤 TC 실효 스캔과 같은 자리에서, 그 항목의 TC 하나를 골라 **실제로 프로덕션을 되돌려 RED 를 본다.** 머릿속 판정이 "통과" 라고 답하는 자리가 누수의 가장 큰 갈래였다 (#1208 축1 — 자기비교·구현상 항상 참인 단언·구독 초기값으로 공허하게 통과한 10건).
- **고르는 기준** — 판별력이 가장 의심스러운 TC 하나다. 기대값이 검증 대상에서 나오거나(자기비교), 단언이 호출 여부·불일치만 보거나, 더미·픽스처가 이번 분기를 안 타도 통과할 수 있는 TC 가 후보다. 그런 TC 가 없으면 이 항목의 핵심 분기를 지키는 TC 를 고른다
- **되돌림은 한 줄이다** — 비교 연산자 반전, 분기 조건 반전, 가드·filter 한 줄 제거, 보존하는 값을 기본값으로 바꾸기 중 하나다. 이 항목이 만든 프로덕션 변경 안에서 고른다
- **실행은 최소 범위로** — XCTest 는 `-only-testing:<테스트타겟>/<클래스>/<메서드>` 로 그 메서드만 돌리고, **Swift Testing 은 `-only-testing:<테스트타겟>/<타입 이름>` 까지만 지정한다** — 함수명을 주면 `0 tests` 로 아무것도 안 돈다 (`docs/operations/1145/opord-DP-2.1.md:201` 실측). 줄 것은 `@Suite` 의 표시 문구가 아니라 `struct`·`class` 타입 이름이다 — 이 레포의 Swift Testing 스위트 대다수가 `@Suite` 없이 `struct XxxTests { @Test ... }` 형태다. 스킴 전체를 돌리지 않는다
- **xcpretty 없이 raw `xcodebuild` 로 돌린다** — `xcpretty` 는 Swift Testing 출력을 삼켜 판별 문구를 지운다 (`opord-DP-2.1.md:161`). 스킴·destination 은 `scripts/ensure-test-simulator.sh` 가 돌려주는 기기를 쓴다 (§구현 중 증분 빌드 원칙 — destination 을 바꾸면 전 모듈 재빌드)
- **0건은 RED 가 아니고, `0 tests` 는 그 신호가 아니다** — 판별 마커는 `Test run with [1-9]… test`(Swift Testing)·`Executed [1-9]… test`(XCTest) 의 **존재**다 (`scripts/run-all-tests.sh` 의 `RAN_SWIFT_TESTING`·`RAN_XCTEST` 와 같은 패턴). Swift Testing 전용 스킴은 XCTest 쪽이 정상 실행에서도 늘 `Executed 0 tests` 를 찍어서, `0 tests` 를 신호로 삼으면 멀쩡한 실행을 안 돈 것으로 읽는다 (`docs/troubleshooting/2026-08-08-run-all-tests-reports-compile-failure-as-passed.md`). 마커가 없으면 멀쩡한 단언을 조이기 전에 명령부터 고친다
- **복원 확인이 짝이고, 그 기준은 파일로 떠 둔다** — 되돌리기 **전에** `git diff -- <그 파일> > <scratchpad>/<파일명>.before` 를 먼저 찍고, 복원 뒤 같은 diff 를 다시 찍어 두 파일을 비교한다. 기억에 맡기면 큰 diff 에서는 확인이 서지 않는다. 이 확인을 빠뜨리면 깨진 프로덕션이 커밋에 실린다
선언은 한 줄이다 — `축1 실측: <되돌린 한 줄> → <빨개진 TC> (실행 <N>건 · RED 확인 · 복원 ✓)`. **RED 가 안 나오면 그 TC 는 그 분기를 안 지킨다** — 단언을 조이거나 given 을 바꿔 다시 실측한다. 되돌릴 한 줄을 못 고르는 항목(프로덕션 변경이 선언·데이터뿐이어서 반전할 분기가 없는 자리)은 그 사유를 선언 줄에 적고 넘어간다.
*TC 작성이 구조적으로 불가할 때* — 주입 지점 없는 시스템 static 호출(`AVCaptureDevice.authorizationStatus` 류), 테스트 타겟이 없는 확장 타겟(`withTest: false`)처럼 TC를 붙일 자리 자체가 없으면 **형제 컴포넌트를 grep해 같은 이유로 TC를 갖지 않는지 확인한다.** 선례가 있으면 그 선례를 근거로 TC를 생략하고, 축1 선언을 `축1: TC 생략(<사유> — 선례 <형제 컴포넌트>) ⇢ 대체 검증 <수단>` 형식으로 남긴다 — TC가 없어 `깨지면 빨개짐` 칸이 성립하지 않으므로 위 3칸 형식의 의도된 예외다. 대체 검증은 그 계약을 실제로 덮는 상위 수단(빌드 그래프 검증·상위 스킴 실행·실물 확인)이어야 하고, "빌드는 된다"는 대체가 아니다. **선례가 없으면 TC를 붙이려고 추상을 새로 만들지 말고**(YAGNI — 소비자 없는 주입 포인트가 남는다) 유저에게 보고한다. 이 경로를 탄 것은 조항 이행이다.
- **파일 추가/삭제/이동 직후 `mise exec -- tuist generate --no-open`** — 미루면 빌드·테스트가 이전 프로젝트 구조로 돈다. **그 외엔 재실행 금지** — 프로젝트 재생성은 증분 빌드 캐시를 무효화한다. "혹시 몰라" 재실행하지 말 것, 필요 판정은 impact-check가 한다.
- **증분 빌드 유지** — 반복 빌드·테스트는 증분을 전제로 돈다:
- `xcodebuild clean`·DerivedData 삭제 금지 (빌드 오염 진단 같은 명시적 사유가 있을 때만)
- `-derivedDataPath`로 새 경로를 만들지 않는다 — 기본 공유 DerivedData가 증분의 원천. `./DerivedData` + reset은 pr_test.yml의 CI 전용 패턴이니 로컬에 복제 금지
- destination(시뮬레이터)을 바꾸지 않는다 — `scripts/ensure-test-simulator.sh`가 돌려주는 기기(iPhone 16 / iOS 18.0)를 따른다. 단발 `xcodebuild`도 같다. destination이 바뀌면 전 모듈 재빌드
- **객체 시그니처(특히 init) 변경 시 콜사이트 전수 grep** — 수정 전에 참조처를 확인한다. 이 짝은 스크립트가 못 잡는다.
- Query/Command 분리 유지 — 읽기와 사이드이펙트를 한 흐름에 섞지 않는다.
### Rules 갭 보고 루프
지금 하려는 결정이 rules·기존 패턴 어디에도 커버되지 않으면(선례 없는 컴포넌트 유형, 조항 간 충돌, 조항이 모호해 두 구현이 다 성립) **추측으로 채우지 말고 유저에게 보고한다.**
- 유저가 준 해결책으로 구현을 잇는다.
- **보고와 동시에 doctrine 스킬을 invoke 한다** — 갭 확증·요구 형식·신설/보강 판정·반영 시점이 그 스킬 소관이다. 이 루프는 보고까지고, 받은 답을 룰로 정착시키는 것이 doctrine 이다. 예약으로 미루지 않는다 — 잃어버리지 않는 것이 불변 조건이다.
- 작전명령·작전계획 있는 런이면 이 보고를 즉시보고(`report-immediate.md`)로 이슈에도 게시한다 — 머리 게시 줄대로 봇 계정 코멘트 + `@sudopark` 멘션 (수단은 issue 스킬 §코멘트).
### 플랜 갭 보고 루프
작전명령(또는 유저 지시)이 커버하지 않는 상황을 실행 중 만나면 — 예상 밖 의존 발견, 명령에 없는 결정 분기, 범위 밖 결함 — **추측으로 채우지 말고 유저에게 선택을 반문한다.**
- 유저 답으로 실행을 잇는다. 그 결과는 작전명령 부록 D 에 단편명령(`docs/operations/templates/frago.md` 서식 — 바뀐 항목만)으로 누적한다 — 발부는 세 짝 묶음이다: 봇 코멘트 기록·`핵심:` 줄 갱신 + 미러 재조립·board-sync (opord §6). 유저 답이 **계획 변경을 의도하면**(단편명령 커버 범위 초과) 상위 계획 개정 우선 → 명령 재작성 유도다 (opord §6 재작성 경계).
- 사후보고 등급의 자율 결정(태스크 순서·커밋 시퀀스 변경 등)은 반문 없이 진행하고 종결보고 7항에 한 줄로 누적한다.
- 범위 밖 작업으로 드러난 것은 **후속 이슈로 따거나 같은 이슈 내 추가 할일로 정리한다** — 형태는 그 시점에 유저와 결정. 잃어버리지 않는 것이 불변 조건.
- 즉시보고 게시는 Rules 갭 루프와 같다 — 작전명령·작전계획 있는 런만.
- 이 루프는 우발상황의 escape hatch다. 빈발하면 작전명령 단계의 범위 명확성이 부실했다는 신호 — 그 사실도 유저에게 함께 보고한다.
### 리뷰 지시 게이트
리뷰 코멘트 반영도 구현이다 — 유저 지시와 같은 충언 의무가 걸린다 (superpowers:receiving-code-review와 함께). 작전명령 있는 런은 리뷰 라운드도 활동 로그 대상이다 — 리뷰 접수·반영 push·스레드 회신·재리뷰 대기 전환마다 활동 로그 append + board-sync 짝호출 (opord §8 — `검토` 상태 동안, 종결은 머지다). 반영을 서브에이전트에 dispatch 해도 이 짝호출과 FRAGO 판정은 컨트롤러 의무로 남는다 — 브리프로 넘기지 않는다. 리뷰 반영이 작전명령 본문 층(범위·구조·산출물)을 바꾸면 부록 D 단편명령으로 누적한다 (opord §6 — 계획 이탈 신호로 상황판에 집계된다). 반대 방향도 같다 — **아직 머지 안 된 구현을 바꾸는 건 비용이 아니라서 반박 근거가 못 된다** (CLAUDE.md §1). 반영 전에 지시대로 구현하면 목적이 실제로 성립하는지 검증한다 (예: dedupe 지시면 그 형태가 정말 중복을 제거하는지). 성립하지 않으면 문자 그대로 맞추는 코드를 내지 말고 반영 전에 되묻는다.
## 리팩터 게이트 (축3) — 매 GREEN 직후
superpowers TDD의 REFACTOR 단계를 이 게이트로 수행한다. **아래 선언 없이 다음 단계(다음 RED 또는 완료 판정)로 넘어가지 않는다.**
**스멜 스캔** — 이번 diff가 만진 코드 + 그 중복 상대까지만:
- **중복** — 같은 지식이 두 곳에. Rule of Three: 세 번째 중복은 무조건 제거
- **의도 은폐** — 이름이 처리 케이스를 드러내는가, 함수가 한 추상화 수준을 유지하는가
- **표현 우겨넣기** — 부작용·throw 있는 호출을 인자 자리·조건식 안에 인라인했으면 중간 `let`으로 푼다. 동작이 일어나는 지점이 괄호 안에 숨는다
- **조건 분기 반복** — 같은 분기가 여러 곳 → enum exhaustive switch·다형성으로 한 곳에
- **Feature Envy·Data Clumps** — 로직은 데이터 곁으로, 항상 같이 다니는 값 묶음은 타입으로
- **Speculative Generality** — 소비자 없는 추상·안 쓰는 파라미터 제거 (YAGNI)
- **죽은 TC·찌꺼기** — 프로덕션 코드를 옮기거나 지웠으면 그 코드를 덮던 TC도 함께 옮겼나·지웠나. 남은 껍데기(then이 빈 케이스·같은 것을 두 번 보는 케이스)는 커버리지 착시다. 옮긴 뒤 안 쓰이게 된 `import`·헬퍼도 같이 지운다
- **호출 비용** — 한 흐름에서 같은 값을 저장소·네트워크·디스크로 두 번 이상 읽나. 한 번 읽어 넘긴다
- **문서 낡힘** — 이번 diff 가 바꾼 파일 경로·심볼로 `grep -rn '<경로·심볼>' docs .claude/rules` 해서 그걸 인용한 문서를 연다. 줄 번호 인용·현재형 서술·심볼명이 이번 diff 뒤에도 맞나. 아직 구현하지 않은 동작은 현재형으로 적지 않는다. **문서가 이번 diff 의 대상이면 방향이 뒤집힌다** — 코드에서 문서를 찾는 게 아니라, 그 문서가 주장하는 사실(파일명·테이블·컬럼 이름과 개수·버전 번호·심볼명·호출 범위)을 하나씩 실물 선언에서 확인한다. 문서만 고치는 작업은 코드를 안 건드려 위 grep 축이 아예 안 걸리고, 그래서 문서 PR 이 통째로 샌다 (#1208 축3 — PR #1218 한 건에서 7건)
- **선례 미조회** — 같은 일을 하는 기존 컴포넌트·관례를 grep했나. 재사용 여부뿐 아니라 **형제 컴포넌트의 구조·시그니처 관례**(타입 형태·의존 주입 방식·네이밍·토큰 사용)까지 대조한다. 열거는 diff로 고정한다 — 직전 항목이 커밋으로 닫혔으면 `git diff <그 커밋>..HEAD`, 아직 커밋 전이면 `git diff HEAD`로 이번에 추가·수정한 심볼을 뽑아 각각에 형제를 한 줄씩 답한다. **첫 형제는 같은 파일이다** — 고친 파일 안의 기존 값·관례(주입 방식·에러 문구·어형·반환 타입)가 0순위 대조 대상이고, 그 다음이 셋이다: 같은 타입의 **다른 메서드** / 같은 계약의 **다른 구현체** / 같은 역할의 **다른 컴포넌트**. **대조는 존재 확인이 아니라 차이 확인이다** — 형제와 갈린 차원마다 근거를 답하고, 근거를 못 적으면 형제를 따른다. **grep 축을 심볼 이름 하나로 두지 않는다** — 같은 일을 다른 이름으로 하는 구현은 이름으로 안 걸린다. 호출하는 시스템 API·상수 문자열(`UIApplication.openSettingsURLString` 류)로도 찾는다
- **전제 미검증 이식** — 다른 맥락의 근거·패턴을 그대로 옮겼으면 그 전제가 여기서도 성립하나
- **테스트 편의가 구조를 결정** — 명령형 상태·수동 가드·주입 포인트를 "선언적으로 짜면 테스트가 어려워서" 골랐다면, 그 편의 없이 정말 테스트 불가한지 먼저 확인한다 (대개 scheduler 주입·async 테스트로 풀린다). production은 테스트 때문에 훼손하지 않는다 (testability.md)
- **신설물 rules 대조** — 이번 diff가 **새로 만든** 타입·컴포넌트·상수 묶음·파일 각각에 대해, 그 종류를 규정하는 rules 조항을 다시 연다. **테스트 타입·테스트 파일도 신설물이다** — 배치·미러링은 testability §8이 규정한다. 착수 시점 rules 확인은 "무엇을 만들지" 모르는 상태의 경로 기반 확인이라 신설물을 안 덮는다 — 이름·배치·카탈로그 등재 의무는 물건이 생긴 뒤에만 판정된다. **이번 diff가 새로 고른 선언 형태**(접근제어자·타입 형태·값 묶음 구조)도 신설물로 센다 — 기존 파일 안이라도 코드베이스 다수파와 **다른** 형태를 골랐으면 신설물이다. 대조는 위 선례 미조회대로 하고, 갈린 근거를 신설·수정물 줄에 적는다
- **프로젝트 축** — Query/Command 섞임, imperative loop → functional, mutable var 수동 합성 → CombineLatest 선언적 합성, 값 타입 업데이트는 렌즈 체인(`|>`·`.~`) — var 선언 후 프로퍼티 대입 금지 (domain-rules §5), `static func` 금지 — case 없는 enum으로 감싼 우회도 같다 (CLAUDE.md §1·swift-style §2·§3). pr 스킬의 static 검토가 PR 직전에 잡기 전에 여기서 해소한다
**종료 판정 = Simple Design 4규칙 (우선순위순).** 전부 만족해야 "불필요" 선언 가능:
1. 테스트 전부 통과
2. 의도가 드러남 — 본문을 안 열어도 뭘 하는지 앎
3. 중복 없음
4. 요소 최소 — 위 셋을 만족하는 한에서 타입·프로토콜·간접층이 가장 적은 상태
**선언 형식:**
```
리팩터: <스멜 → 처치>
또는
리팩터 불필요 — 테스트 ✓ / 의도 ✓ / 중복 ✓ / 최소 요소 ✓
신설·수정물: 항목마다 한 줄 — <심볼·파일> ⇢ <대조한 rules 조항·형제(첫 형제 = 같은 파일) — 따랐거나 갈린 차원 + 근거>
```
`신설·수정물` 줄은 두 형식 공통 필수다 — 이번 diff가 만들지도 고치지도 않은 것은 없으므로 이 줄이 비는 자리는 사실상 없다. 4체크만 남기는 선언은 rules·형제 대조를 돌았는지가 흔적으로 안 남아 형식적으로 통과한다. 여러 항목을 한 줄로 뭉뚱그린 요약도 같다 — 값 수준 차원(문구·어형·주입 방식·반환 타입)의 차이가 흔적 없이 지나간다 (#1038 누수 3건·correction 2건 전부 이 자리).
**경계:** 리팩터 중 동작 추가 금지(두 모자), 테스트 그린 유지. 이 게이트는 세션 내 절차일 뿐 커밋 단위에 대응시키지 않는다 — 커밋은 리팩터 반영이 끝난 결과를 논리 단위로 묶는다.
## 완료 판정 — 커밋 전
아래 전부 충족해야 "구현/수정 끝"으로 판정한다:
1. `bash .claude/skills/implement/scripts/impact-check.sh [--base <ref>]` (기본 origin/develop) 실행 후 3섹션을 순서대로 처리:
- **tuist generate** — "필요"인데 아직 안 돌렸으면 `mise exec -- tuist generate --no-open` 먼저. 원칙은 파일 추가/삭제/이동 직후 이미 실행돼 있는 것이고, 여기는 누락 안전망. 테스트는 반드시 generate 반영 후에 돈다
- **테스트 — 검증 범위 사다리** — 출력된 스킴 목록은 파급의 상한이지 실행 지시가 아니다. 실행 범위는 최소부터 산정한다:
- TDD로 진행한 변경은 사이클의 GREEN이 이미 검증 — 커밋 전 재실행은 사다리 산정 범위만
- 변경이 유닛테스트 커버 밖(문서·리소스·스크립트, 테스트 없는 대상)이면 **테스트 실행 생략** — PR CI(pr_test.yml)가 스킴 단위 안전망
- 실행이 필요하면 **개별 TC → 관련 TC 파일 → 해당 모듈 스킴 → 모듈+연결 스킴(impact-check 산출 전체)** 순으로, 변경 파급이 요구하는 최소 범위에서 멈춘다 — 구현 내부 로직 수정은 관련 TC 파일까지, 공유 타입·시그니처·프로토콜 변경은 연결 모듈까지
- TC·파일 단위 실행은 `xcodebuild test -only-testing:<테스트타겟>/<클래스>[/<메서드>]`, 스킴 단위는 run-tests 스킬. **Swift Testing 스위트는 `/<메서드>` 를 붙이면 `0 tests` 로 안 돈다** — `struct`·`class` 타입 이름까지만 지정하고, 실행 여부는 `Test run with [1-9]… test`·`Executed [1-9]… test` 마커로 확인한다 (축1 실측 1발과 같은 기준)
- **짝지어진 두 위치** — 각 경고를 해소(대응처 수정)하거나 오탐임을 확인하고 유저에게 보고. 경고를 무시한 채 커밋하지 않는다. 스크립트 경고는 기계화된 짝만 덮는다 — **이번 diff가 바꾼 기본값·상수·심볼명·파일 경로는 `grep -rn '<값·심볼·경로>' docs .claude/rules`로 훑어** 그 값이나 줄 번호를 적어둔 문서가 있는지 확인한다 (리팩터 게이트의 문서 낡힘과 같은 확인이다 — 거기서 돌았으면 diff 가 그 뒤로 바뀐 몫만 본다)
2. 마지막 리팩터 게이트 선언 완료 + 명세 항목마다 축1 TC 실효 스캔과 축1 실측 1발(§구현 중)을 각각 1회 수행 — 실측은 `축1 실측:` 줄이 남아 있어야 한다. 두 경로만 갈음한다: 프로덕션 변경이 선언·데이터뿐이어서 반전할 분기가 없으면 그 사유를 선언 줄에 적고, TC 를 붙일 자리 자체가 없으면(§구현 중 `TC 작성이 구조적으로 불가할 때`) 대체 검증 수단 보고로 갈음한다. **사유는 프로덕션 diff 로 반박되지 않아야 한다** — 비교·가드·filter 가 diff 에 있으면 반전할 분기가 있는 것이다
3. Rules 갭·플랜 갭이 있었다면 후속 정리까지 완료 — Rules 갭은 doctrine 이 요구·반영을 닫았거나 유저가 고른 반영 시점이 기록으로 남았고(예약으로 끝난 것은 미완료다), 플랜 갭은 후속 이슈·추가 할일로 정리됐다. 이번 작업이 `resolution: deferred` 레코드를 해소했으면(kickoff §2 탐색이 끌어올린다) 그 레코드를 `fixed`로 갱신하고 해결 항목을 채운다 — 새 레코드를 만들지 않는다
4. 컴파일·유닛 테스트로 검증되지 않는 계약을 만졌으면 실물을 직접 확인한다 — 테스트 전부 통과가 이 계약들의 동작을 보증하지 않는다:
- **빌드 산출물** — AppIntents parameterSummary·메타데이터, Info.plist 키, 엔타이틀먼트, 위젯 타임라인. 예: `.appex/Metadata.appintents/extract.actionsdata`
- **프로세스 경계** — 앱/확장/위젯은 별개 프로세스라 앱의 전역 설정(UIAppearance·DI 컨테이너·런타임 초기화)이 승계되지 않는다. 확장에서 도는 코드는 그 전제로 재확인
- **빌드 그래프** — 소스 공유 디렉토리를 스킴에 매핑할 땐 embed인지 타겟별 소스 컴파일인지 확인한다. 잘못 매핑하면 CI에서 해당 테스트가 조용히 안 돈다
- **파서·정규식** — 새로 쓴 정규식·파서는 실데이터 코퍼스 전체에 돌려 미매치·오절단을 확인한다. 샘플 몇 개 통과는 커버리지가 아니다
**확인이 유저 환경을 요구하면 인계한다** — 로그인 계정, 실기기, 콜드스타트, 시스템 권한 다이얼로그처럼 Claude가 수행할 수 없는 검증은 갈음 수단이 없다. 이때는 **미검증 상태를 감춘 채 완료를 선언하지 않는다**:
- 검증 항목·검증 방법·판정 기준을 **PR 본문에 실어 인계한다** — 검증 인계의 영속 자리는 PR 본문이다 (kickoff A-2 코멘트 상한). PR이 아직 없으면 인계 항목을 pr 스킬 시점까지 승계하고, **PR을 만들지 않는 런**(직접 커밋·문서 작업)만 이슈 코멘트로 남긴다. 다음 세션이 기록만 봐도 "무엇이 아직 검증 안 됐는지" 복원돼야 한다 — 대화에만 남기면 사라진다.
- 완료 보고 마지막 줄에 `유저 검증 대기: <항목>`을 명시한다. 이 항목이 남아 있어도 구현은 끝난 것으로 판정한다 — 인계가 갈음이다.
- 인계 기록까지 마치면 조항 이행이다. 인계 없이 넘어간 것만 이탈이다.
## 커밋
커밋 메시지는 `[#이슈번호] 동작 변화 요약` — 파일 목록이 아니라 동작이 어떻게 달라졌는지 (CLAUDE.md §5). 커밋·PR 구성 상세 절차는 commit·pr 스킬이 다룬다 — **커밋은 commit 스킬, PR 은 pr 스킬을 invoke 해서 만든다.** 컨벤션을 외워 직접 만들면 pr 스킬의 올리기 전 검토 4종(구독 보관함·주석·문장·static)을 건너뛴다.
## 종료 기록 — skill_end (#712)
- **시점: commit 또는 pr 스킬로 전이하는 순간** — 완료 판정을 통과하고 더 만들 diff가 없어 커밋·PR 절차로 넘어갈 때, 해당 스킬 invoke 직전에 `log-record.py skill_end`를 기록한다 (명령·compliance 규칙은 CLAUDE.md §1).
- **동반 superpowers 코딩 스킬도 같은 시점에 각각 기록 (#715)** — superpowers:subagent-driven-development·superpowers:executing-plans·superpowers:test-driven-development는 자체 종료 조항이 없어 여기가 기록 주체다. superpowers:brainstorming은 **작전명령을 안 거치고 바로 구현으로 온 런에서만** 여기서 기록한다 — 작전명령을 거쳤으면 opord 스킬이 이미 기록했다. 이 런에 실제 발동(invoke)된 것만, 발동 레코드와 동일한 `superpowers:` prefix 포함 이름으로 기록한다 (집계가 문자열 완전일치 버킷팅). compliance는 스킬별 따로 판정 — implement가 full이어도 동반 스킬 절차 이탈이 있으면 그 스킬만 partial.
- **런당 1회** — 기준은 한 작업 단위(플랜 실행 전체·이슈 단위 즉흥 수정)다. 세션 재개·컨텍스트 복원·SDD 태스크 진행으로 이 스킬이 여러 번 재발동돼도, 이어진 런이면 종료 기록은 런을 마무리하는 전이에서 한 번만 남긴다. SDD 중간 태스크의 커밋 전이는 런의 끝이 아니므로 기록하지 않는다.