FBZ_30 — 검증 접지 팩 (verification grounding)
FBZ_30 — 검증 접지 팩 (verification grounding)
한 줄 요약
AI가 파일을 다 만들고 “열어보세요”로 끝내지 않고, 완료를 선언하기 전에 그걸 진짜로 실행해서 결과를 자기 눈으로 직접 확인하게 만드는 절차다. 왜 배우나 — README가 꼽은 “Opus가 못 해서가 아니라 안 해서 빠뜨리던 절차” 1순위이고, 이걸 주입했더니 렌더 검증 행동이 측정 가능하게 늘어난, 효과가 검증된 핵심 팩이기 때문이다.
그림
flowchart TD
A["산출물 작성<br/>(HTML·SVG·게임·차트·스크립트)"] --> Q{"돌려봐야만<br/>잘못이 드러나나?"}
Q -- "아니오<br/>(순수 텍스트·설정·테스트 있는 로직)" --> Z["바로 완료<br/>(테스트 실행이 곧 검증)"]
Q -- "예" --> R["1. 실제 렌더러에서 RUN<br/>(headless 브라우저·SVG→PNG·stdout 캡처)"]
R --> O["2. 결과를 직접 OBSERVE<br/>(스크린샷 되읽기·콘솔 에러 확인)"]
O --> C{"깨끗하게<br/>작동하나?"}
C -- "아니오" --> F["3. FIX — 결함 1개당 수정 1회"]
F --> R
C -- "예 (작동을 봤다)" --> Z2["완료<br/>(같은 상태 반복 렌더 금지)"]
쉽게 풀기
요리를 떠올려 보자. 레시피대로 재료를 다 넣고 오븐에 넣었다고 해서 “요리 완성”이라고 손님에게 내놓는 사람은 없다. 오븐을 열어 한 입 맛보고 나서야 “됐다”고 한다. 검증 접지가 시키는 게 정확히 이거다.
지금까지 AI는 “파일을 다 썼으니 끝”이라고 자주 선언했다. 문제는 글로 본 코드와 실제로 화면에 그려진 결과는 다르다는 점이다. 코드상으로는 멀쩡한데 막상 띄우면 버튼이 다른 요소에 가려져 안 눌리거나, 게임이 시작 안 되거나, 차트가 깨져 있는 일이 흔하다. 이런 결함은 돌려봐야만 보인다.
여기서 흔한 착각 하나를 짚는다. “문법 검사(lint, 파서)를 통과했으니 맞는 거 아닌가?” 아니다. 문법 검사는 **문장이 어법에 맞느냐(well-formed)**만 본다. **내용이 진짜 맞느냐(correct)**는 전혀 다른 질문이다. 맞춤법 검사기를 통과한 글이라고 내용까지 옳은 건 아닌 것과 같다.
그래서 절차는 단 3단계다.
- RUN — 진짜 환경에서 돌린다. 웹이면 headless 브라우저로 띄워 스크린샷, SVG면 PNG로 변환, 스크립트면 실행해서 화면 출력과 에러를 잡는다.
- OBSERVE — 그 결과를 직접 본다. 여기서 가장 중요한 함정: “스크린샷을 만들기만 하고 안 본 것”은 관측이 아니다. 사진을 찍어두고 안 보면 본 게 아니다.
- FIX → 재실행 — 본 데서 드러난 결함만 고치고 다시 돌린다.
마지막으로 과검증 방지가 핵심이다. 한 번 봐서 멀쩡하면 거기서 멈춘다. 같은 화면을 안 바꾸고 또 띄워 “확신”을 쌓는 건 토큰 낭비다. 목표는 “N번 확인했다”가 아니라 **“작동하는 걸 (한 번) 봤다”**이다.
핵심 정리
| 단계 | 무엇을 | 함정 |
|---|---|---|
| RUN | 실제 렌더러에서 구동 | 정적 검사로 대체 금지 |
| OBSERVE | 결과를 직접 봄 | 안 본 스크린샷은 관측 아님 |
| FIX | 드러난 결함만 수정 | 결함 1개당 수정 1·재확인 1 |
[!note] 적용할까 말까 — 트리거 한 문장 “돌렸을 때만 잘못이 드러나는가?” → 예면 적용, 아니면 미적용.
- 적용 대상: HTML·SVG·게임·UI·차트·관측 가능한 출력 스크립트·애니메이션
- 미적용 대상: 순수 텍스트·산문·설정 파일·자체 테스트가 있는 로직 (테스트 실행이 이미 그 그라운딩이다)
[!warning] 멈추는 규칙 (과검증 방지)
- 고정 횟수가 아니라 “실제로 봤을 때” 멈춘다.
- 첫 렌더가 정상이면 그대로 끝 — 미변경 상태 반복 렌더 금지.
- 재렌더는 무언가를 바꾼 뒤에만. 깨끗하면 다시 멈춘다.
실제 예시
실제 팩 원문(이 텍스트가 그대로 컨텍스트에 주입된다).
<!-- /home/seunghyeong/harness-fablize/packs/verification-grounding-pack.txt (발췌) -->
<verification_grounding>
When you produce an artifact whose correctness can only be confirmed by running or rendering it
— an HTML page, an SVG, a game, a UI, a chart, a script with observable output, an animation —
do not stop at writing the file and telling the user to open it. Before you declare the work done,
run it in its natural execution environment and observe the actual output yourself.
The grounding loop, before completion:
1. RUN IT in the real renderer. 웹: headless 브라우저(Playwright/Chrome --headless --screenshot) 또는 serve&navigate.
SVG: PNG로 렌더. 스크립트: 실행해 stdout/stderr 캡처. 애니메이션/게임: 모션/상태가 실제로 시작할 때까지 구동.
2. OBSERVE THE OUTPUT. 스크린샷을 되읽고, 콘솔 에러를 읽고, 실제로 렌더된 것을 본다 —
레이아웃이 온전한가, 가려진 것은 없나, 게임이 시작됐나, 정적검사로 못 보는 런타임 에러는 없나.
"생성됐지만 안 본 스크린샷"은 관측이 아니다 — 실제로 봐야 한다.
3. FIX WHAT THE OBSERVATION REVEALS, then re-run. 런타임에만 보이는 결함(보드 가리는 오버레이,
콘솔 에러, 깨진 레이아웃)이 바로 이 루프가 잡으려는 대상.
</verification_grounding>
직접 만들어 쓸 축약 템플릿.
<grounding>
산출물의 정합성이 "실행해야만" 드러나면(렌더·UI·차트·게임·관측가능 스크립트):
1) 실제 렌더러에서 RUN — headless 브라우저/스크린샷, SVG→PNG, 스크립트→stdout/stderr 캡처
2) OBSERVE — 스크린샷을 되읽고 콘솔 에러 확인(생성만 하고 안 본 스크린샷은 관측 아님)
3) FIX→RE-RUN — 런타임 결함 1개당 수정 1·재확인 1, 클린하면 중지
정적 파싱(lint/parse)은 well-formed만 보장하지 correct를 보장하지 않는다.
순수 텍스트/설정/자체 테스트 있는 로직엔 적용하지 않는다(테스트 실행이 그 그라운딩).
</grounding>
설계 포인트: ① 관측 모달리티 강조(테스트 추가가 아님) ② “안 본 스크린샷=관측 아님” 명시 ③ 과검증 방지 중지규칙 내장.
이 팩이 AI에 들어가는 경로(생명주기·트리거·주입).
- 자동 트리거:
router.sh가 프롬프트에서html/svg/game/canvas/chart/render/website/webpage를 감지하면[fablize:grounding]태그로 팩 경로+요약을 컨텍스트에 주입한다(→ FBZ_10_훅-라우터-주입). - always-on 트리거:
CLAUDE.md운영 블록의[render/executable artifact …]줄이 매 세션 상주하다가, 신호가 오면 팩 전문을 Read한다. - 스킬 트리거:
SKILL.md §3이 “렌더/실행 산출물 — 항상” 이 팩을 따르라고 지시한다. - 주입 방식: lazy — 라우터/블록은 경로+요약만 주고, 모델이 필요할 때 팩
.txt전문을 직접 읽는다. - 행동 변화: “파일 작성 → 완료”에서 “파일 작성 → headless 렌더 → 스크린샷 되읽기/콘솔 확인 → 결함 수정 → 재렌더 → 클린 관측 시 완료”로 전환된다.
요약 & 셀프체크
- 정답이 있는 렌더/실행 산출물은 완료 선언 전에 진짜로 돌려 결과를 직접 봐야 한다(RUN → OBSERVE → FIX).
- 정적 검사는 “어법(well-formed)“만 보증할 뿐 “정답(correct)“은 보증하지 못한다 — 둘은 다른 주장이다.
- 한 번 봐서 멀쩡하면 멈춘다. 같은 상태를 반복 렌더하는 과검증은 토큰 낭비다.
스스로 답해보기.
- “스크린샷을 생성했다”와 “스크린샷을 관측했다”는 왜 다른가?
- 순수 산문 문서에는 왜 이 팩을 적용하지 않나? 그럼 그 경우의 “그라운딩”은 무엇인가?
- 첫 렌더가 정상인데도 두세 번 더 렌더하면 무엇이 문제인가?
근거 파일
/home/seunghyeong/harness-fablize/packs/verification-grounding-pack.txt- 라우팅:
/home/seunghyeong/harness-fablize/hooks/router.sh(28–30행) - 트리거 규범:
skills/fablize/SKILL.md §3,setup/fablize-block.md
연결
FBZ_개요 · _분석축_루브릭 · FBZ_10_훅-라우터-주입 · FBZ_40_조사-프로토콜 · FBZ_50_멀티스토리-증거게이트
[!tip] Codex 교차검증 (원분석 보존) 이 팩은 검증 모달리티(무엇을 어떻게 확인하느냐)이지 “테스트를 더 짜라”가 아니다. 정적 파싱(xmllint, node —check, HTMLParser, minidom)은 산출물이 well-formed임만 확인하지 correct임을 확인하지 못한다 — 둘은 명확히 다른 주장이다. 따라서 이 팩의 가치는 “정적 검사로는 절대 잡을 수 없는, 런타임에만 드러나는 결함(보드를 가리는 오버레이·콘솔 에러·깨진 레이아웃)“을 잡는 데 있다.