커밋 규칙 하나를 훅으로 올렸더니 다섯 런타임에 네 가지 방식으로 붙었다.
그중 셋은 이름만 훅이고 실제로는 다시 프롬프트였다.
규칙을 어느 층에 두느냐가 그 규칙이 지켜지는 방식을 정한다.
문제
지침 파일에 적은 규칙은 모델이 읽으면 지켜지고 흘리면 안 지켜진다.
자작 메모리를 굴리던 시절 문서에만 적어 둔 규칙 하나가 다섯 번 재발했고, 다섯 번 모두 대응은 문장을 더 세게 고치는 쪽이었다.
거기서 훅으로 올릴 규칙을 가르는 기준 셋이 나왔다.
두 번 넘게 재발할 것, 정규식으로 잡힐 것, 훅 유지비가 재발 피해보다 작을 것.
그 기준을 통과한 규칙을 훅으로 올리기 시작하면서 새 문제가 나왔다.
훅은 도달률을 사지만 그 도달률이 어디서나 같지 않다.
지침을 243줄까지 불렸다가 77줄로 깎은 것이 2026년 2월부터 5월까지의 일인데, 깎고 나서도 규칙 자체는 계속 늘었다.
줄어든 것은 지침의 길이지 규칙의 수가 아니었다.
그래서 남은 질문은 어떻게 잘 적을 것인가가 아니라 어디에 둘 것인가였다.
훅이 사는 것은 도달률이다
2026년 7월에 도구 호출 전 훅 둘을 걸었다.
하나는 스택 강제다.
셸 명령을 가로채 npm과 yarn을 pnpm으로, pip와 conda를 uv로 몰고 어긋난 명령은 실패 코드로 즉시 끊는다.
도입 시점에 테스트 10케이스를 붙였고, 예외가 필요한 레거시 저장소는 표시 파일 하나를 두면 통과한다.
문서로 적어 두면 확률이던 것이 여기서는 명령이 아예 실행되지 않는 상태가 된다.
다른 하나는 커밋 직전 훅이다.
커밋 메시지에 붙일 근거 트레일러 세 종의 규칙을 그 시점에만 주입하고, 주입에 실패해도 커밋은 막지 않는다.
테스트 12케이스를 같이 넣었다.
설계 근거로 적어 둔 값이 이 층의 성질을 정확히 말한다.
커밋 시점 도달률 100%에 상시 토큰 0이다.
같은 내용을 지침에 적으면 모든 세션이 그 토큰을 내고도 정작 커밋할 때 읽힐지는 확률이다.
런타임마다 붙는 방식이 갈린다
훅은 런타임이 제공하는 기능이다.
커밋 직전 훅은 만든 날 하루 안에 다섯 런타임으로 전파됐는데 방식이 네 가지로 갈렸다.
Claude Code는 네이티브 훅으로 받았다.
Codex는 별도 훅 설정에 등록한 뒤 화면에서 신뢰 승인을 한 번 더 눌러야 했다.
나머지 셋은 훅 자리가 없었다.
둘은 다섯 런타임이 공유하는 지침 파일에 한 줄을 얹는 것으로 갈음했고, 마지막 하나는 그 런타임 전용 지침에 직접 적었다.
뒤의 셋은 전파 목록에는 올랐지만 실제로는 프롬프트 층으로 되돌아간 것이다.
도달률 100%는 훅을 실제로 발화시키는 런타임에서만 성립하는 값이다.
배선 자체도 런타임이 정한다.
같은 스택에서 설정 파일을 연결하는 방식이 심링크, 실경로 직접, 복사 동기 셋으로 갈렸다.
한 런타임은 경로에 심링크가 끼면 그 설정을 조용히 무시했고, 다른 런타임은 원자적 교체로 심링크를 실파일로 바꿔 버려서 한동안 정상으로 보이다가 조용히 이탈했다.
발화 시점이 판정을 무너뜨린다
같은 해 7월에 절차 게이트 플러그인의 오탐을 잡았다.
그 게이트는 도구 호출이 끝난 뒤 발화하는 훅에서 도구 결과 텍스트를 정규식으로 훑어 실패를 판정하고 있었다.
그런데 호출 후 훅은 성공한 호출에만 발화한다.
실패한 호출은 애초에 그 훅에 도달하지 않으므로, 그 자리에서 실패를 찾는 판정은 구조적으로 오탐만 낸다.
고친 것은 세 건이고 회귀 6과 합성 7에 라이브 검증을 붙였다.
규칙의 문장은 옳았고 훅을 건 시점이 판정의 전제를 무너뜨렸다.
훅 층에서 값을 치르는 자리는 둘이다.
발화 여부와 발화 시점이다.
게이트웨이는 통과 자체를 막는다
세 번째 층은 서버다.
개인 메모리 뱅크는 오픈소스 에이전트 메모리 Hindsight로 굴린다.
그 앞에 직접 만든 게이트웨이를 하나 세우고, 2026년 7월 26일 하루에 규칙 강제 계층을 여덟 단계로 나눠 얹었다.
그날의 계수는 커밋 27건, 단위 테스트 162건 통과, 배포 검증 게이트 8개 전부 통과다.
게이트웨이가 강제하는 것은 태그 접두 문법, 기록 앞머리의 라벨 형식, 뱅크별 접근 목록이다.
어기면 요청이 422로 거부되고 위반한 규칙 번호가 응답에 실린다.
고칠 수 있는 위반은 거부 대신 기계적으로 교정한다.
다만 의미를 지어내야 고쳐지는 것은 교정하지 않는다.
오타 접두사를 그럴듯한 접두사로 묻어 주는 동작이 그래서 빠졌다.
| 층 | 지켜지는 방식 | 지불하는 값 |
|---|---|---|
| 지침 파일 | 확률 | 모든 세션이 그 토큰을 낸다 |
| 훅 | 발화하는 런타임에서만 100% | 런타임마다 배선과 유지가 따로 든다 |
| 게이트웨이 | 요청 거부 | 요청이 지나가는 경로에만 걸린다 |
이 층의 성질은 클라이언트를 가리지 않는다는 것이다.
다섯 런타임이 같은 게이트웨이를 지나므로 어느 쪽이 훅을 못 걸든 상관이 없다.
훅 층에서는 런타임 하나가 훅 자리를 안 주면 그 런타임만 규칙 밖에 남는데, 서버 층에서 규칙 밖에 남으려면 요청을 안 보내는 수밖에 없다.
그렇다고 서버가 전부를 받지는 않는다.
어떤 규칙은 요청 이전, 즉 에이전트가 무엇을 할지 정하는 단계에 걸린다.
완료를 선언하기 전에 기록을 남기게 하는 규칙이 그렇다.
그 자리에는 게이트웨이가 없어서, 한 런타임에서는 작업이 끝나는 순간을 잡아 기록 턴을 강제하는 훅을 따로 만들어야 했다.
게이트웨이가 닿지 않는 자리는 다시 훅이 받는다.
서버가 강제하면 지침에서 뺀다
규칙 강제 계층을 배포한 그날의 마지막 작업은 지침을 지우는 일이었다.
지침의 메모리뱅크 절에서 태그 문법과 실패 판정 설명을 걷어내고 한 줄로 바꿨다.
형식과 실패 판정은 게이트웨이가 강제하므로 프롬프트에 중복해 적지 않는다.
같은 계열의 축소가 8월에 한 번 더 있었다.
전역 지침 89줄을 깎으면서 잘라낸 연구 내용은 버리지 않고 독립 문서로 뺐다.
지침이 짧아진 것은 문장을 잘 다듬어서가 아니라 무게를 받을 자리가 코드 쪽에 생겼기 때문이다.
결론
층은 규칙의 내용으로 고르지 않는다.
그 규칙이 깨질 때 어떤 모양으로 깨지는지를 보고 고른다.
어겨도 다음 세션에 다시 말하면 되는 규칙은 지침에 둔다.
같은 위반이 반복되고 정규식으로 잡히면 훅으로 올리되, 발화하는 런타임과 발화 시점을 먼저 확인한다.
클라이언트를 못 믿겠으면 서버로 내린다.
층을 고르는 일은 규칙을 어디에 적을지 정하는 일이 아니다.
위반을 어느 지점에서 만나게 할지 정하는 일이라는 뜻이다.
지금 이 스택의 규칙은 지침과 훅과 Hindsight 앞 게이트웨이 세 층에 흩어져 있고, 어느 층에 있는지가 곧 그 규칙을 얼마나 믿을 수 있는지다.
짧아진 지침은 그만큼 무거워진 코드가 뒤에 있을 때만 성과로 친다.
한계·재검토 트리거
2026-09 기준 / 재검토 트리거: 훅 자리를 주지 않던 런타임이 네이티브 훅을 지원하거나, 게이트웨이 뒤의 규칙을 클라이언트가 우회해 통과시킨 사례가 한 건이라도 관측되면 이 배치 판정을 다시 연다.