git:20260915.1b5578d to git:20261013.f2be3c7

13 added, 7 removed. Audit A to A.

---
name: root-cause-first
- description: "버그, 테스트 실패, CI 빨강, 런타임 예외를 만났을 때 고치기 전에 원인부터 밝히는 네 단계(재현, 원인, 가설, 수정)와 멈춰야 하는 신호. 증상만 가리는 수정(카운터·로그만 추가, 문자열 분류에 경우 하나 더 붙이기, 같은 수정을 자리마다 따로 붙이기, 상한·재시도 간격으로 누르기)을 고르기 직전에 쓴다. 컴파일러가 정확히 짚은 오타 한 줄처럼 원인이 이미 보이는 수정에는 쓰지 않는다."
+ description: "버그·테스트 실패·런타임 예외에서 다음 행동을 고를 때, 실패 증거와 가설을 연결해 원인을 좁히고 수정한다. 이미 확보한 재현·로그를 재사용하고, 가설을 구분하는 관측만 추가한다. 원인이 분명한 오타 수정에는 생략한다. 환경 준비가 막히면 원래 작업의 완료 조건을 보존한 채 환경 문제를 분리한다. 같은 실패를 조건 변화 없이 반복하거나, 로그·문자열 분기·상한으로 증상만 가리려 할 때 사용한다."
---
# 근본 원인 먼저
## 언제 쓰나
- 테스트가 빨갛다. 빌드는 되는데 스위트가 실패한다. 기본 브랜치가 안 빌드된다.
- 런타임에 예외가 뜬다. 턴이 죽는다. 판정 레인이 거절한다.
- "어제까지 됐는데 안 된다." 그 사이 누가 무엇을 바꿨는지 모른다.
원인이 이미 보이는 수정에는 쓰지 않는다. 오타 하나, 빠진 구분자, 컴파일러가 정확히
짚어 준 한 줄은 그냥 고친다.
## 원칙
**원인을 밝히기 전에 고치지 않는다.** 증상이 사라지는 것과 원인이 사라지는 것은 다르다.
인증이 안 된다고 인증을 끄는 것은 해결이 아니다.
## 네 단계
- 순서대로 밟는다. 건너뛰었으면 처음으로 돌아간다.
+ 이미 확보한 증거에서 이어간다. 부족한 단계만 보완한다.
- 1. **재현.** 실패를 한 번 직접 낸다. 무엇이 들어가면 무엇이 나오는지 정확히 적는다.
- 재현이 안 되면 아직 디버깅이 아니라 관찰이다. 관찰 시간을 늘려 다시 본다.
+ 1. **실패 증거.** 입력, 기대 결과, 실제 오류와 환경을 적는다. 기존 로그나 재현이
+ 같은 조건을 다루면 재사용한다. 재현이 안 되면 가설을 구분할 입력이나 관측을
+ 고른다. 시간만 늘려 같은 동작을 반복하지 않는다.
2. **원인.** 증상에서 거슬러 올라간다. 스택을 따라가고, 마지막으로 됐던 커밋과 지금을
`git log --oneline` 으로 가른다. "여기서 틀렸다"가 아니라 "여기서부터 틀리기
시작했다"를 찾는다.
3. **가설.** 원인을 한 문장으로 쓰고, 그게 맞다면 무엇을 바꿨을 때 무엇이 달라지는지
예측한다. 예측 없는 수정은 추측이다.
4. **수정.** 가설이 가리킨 자리만 고친다. 1의 재현을 다시 돌려 증상이 사라졌는지,
다른 것이 깨지지 않았는지 본다.
- ## 멈추고 처음으로 돌아가는 신호
+ 환경 준비가 원래 작업을 막으면 오류·재현 명령·작업 경로와 필요한 수리를 분리해
+ 기록하고 담당 Keeper에게 전달한다. 원래 완료 조건과 다음 단계는 보존한다.
+ 수리가 끝나면 원래 작업의 남은 단계에서 이어간다.
- - 같은 자리를 두 번째 고치고 있다 → 호출하는 쪽을 하나씩 막는 것을 멈추고, 그 실수가
+ ## 가설을 다시 확인할 신호
+
+ - 같은 조건에서 같은 수정이 실패한다 → 호출하는 쪽을 하나씩 막는 것을 멈추고, 그 실수가
생길 수 없게 만드는 한 곳(타입, 공용 함수, 검사 도구)을 찾는다.
- "일단 이렇게 넘기고"라고 쓰고 있다 → 그게 증상 가리기다. 왜 넘어가야 하는지부터 본다.
- - 수정이 처음 짚은 자리 밖으로 번진다 → 원인을 잘못 짚었을 수 있다. 2로 돌아간다.
+ - 수정 범위가 넓어진다 → 같은 원인을 고치는 데 필요한지 확인한다. 새 증거가
+ 가설을 뒤집었다면 가설을 수정하고, 그대로 유효한 증거는 보존한다.
- 고친 결과가 "이제 실패가 보인다"뿐이다 → 카운터나 로그는 경보다. 실패는 그대로 난다.
- 문자열에서 단어를 찾아 분기를 하나 더 붙이고 있다 → 다음에 올 새 문구를 또 놓친다.
값의 종류를 닫힌 타입으로 나눌 수 있는지 먼저 본다.
- 상한, 재시도 간격, 중복 제거로 증상 횟수를 줄이고 있다 → 왜 반복되는지가 원인이다.
## 2단계가 막힐 때 — `references/root-cause-tracing.md`
스택이 깊어 어디서부터 틀렸는지 안 잡히면 이 파일을 연다. `keeper_skill` 을 같은
`identity` 에 `file = "references/root-cause-tracing.md"` 로 부른다. 호출 사슬을 거꾸로
따라가 처음 잘못된 값이 들어온 곳을 찾는 절차가 예시와 함께 있다.