F-2 종결 게이트 스포크 — 규칙이 판정한다
무엇을
w7-closure-gate-pipeline이 경로만 깔아 뒀다 —
포트·인터랙터·라우터는 있고 실제 판정이 없어 POST /hub/closure-checks 가 501 이었다.
이 티켓이 그 뒤에 붙는 판정 스포크(server/apps/closure_gate/)를 만든다.
왜 server/ 인가
규칙 기반 판정이라 요청 경로에서 매번 실행된다(server/CLAUDE.md §0). 모델을 쓰지 않으므로
계약 2(transformers 금지)에 걸리지 않는다. 부록 A-2 “판정은 규칙이,
설명만 LLM이 한다” 를 배치로 고정한 것이다.
규칙표는 지어내지 않았다
전부 도메인별 내부처리규정 문서에서 그대로 옮겼다. 규정이 바뀌면 문서를 먼저 고치고 코드를 맞춘다.
| 처리유형 | 필수 근거 | 출처 |
|---|---|---|
상품해지 |
중도해지수수료_안내 · 약정혜택소멸_안내 · 고객확인_기록 | FIN-POLICY-CLOSE-1 |
보상 |
사고경위_확인 · 귀책여부_확인 | FIN-POLICY-COMPENSATE-1 |
반품 |
환불금액_안내 · 환불기간_안내 · 상품상태_확인 | SHOP-POLICY-RETURN-1 |
교환 |
교환가능_확인 · 재고_확인 | SHOP-POLICY-EXCHANGE-1 |
다산·질병관리본부는 F-2 미적용이다(안내형 업무라 종결 개념이 없다). 빈 규칙을 만들지 않았다.
판정하지 않는 경우를 따로 뒀다
규칙표에 없는 처리유형("민원접수"·오타 "해지")은 판정하지 않고 422 다.
approved 는 절대 규칙 위반이고, blocked 도 거짓말이다 — “근거가 빠졌다”가 아니라
“판정할 규칙이 없다”이기 때문이다. 둘 중 무엇을 돌려줘도 화면이 사실과 달라진다.
애매하면 막는다 — 두 가지로 고정
- 키가 아예 없으면 미충족이다.
false와 구분하지 않는다 — 둘 다 “고지했다는 근거가 없다” True인지 엄격하게 본다.1·"yes"를 참으로 세면 클라이언트 버그가 종결을 승인시킨다
완료 조건
closure_gate스포크 — 규칙표 · 판정 서비스 · 포트 어댑터.importlinter에 스포크 등록(root_packages · 계약 1·2·3·4)- 프로바이더를 501 → 실제 구현으로
- 골든셋 F-2 16건 오판정 0건 (verdict · missing 순서 · source 전부 일치)
- 회귀 테스트를 CI 에 — 건 단위 실패(6.2절)
결과
골든셋 F-2 16건 — 불일치 0건. verdict·missing(순서 포함)·source 가 전부 일치한다.
missing 순서는 규정 문서의 표 순서를 따른다 — 상담원이 보는 순서와 규정을 읽는 순서를 맞췄다.
server 200 → 271개 통과, 계약 4종 KEPT. 실제 HTTP 경로 확인:
차단 200 verdict=blocked missing=['약정혜택소멸_안내','고객확인_기록'] source=FIN-POLICY-CLOSE-1
통과 200 verdict=approved missing=[] source=SHOP-POLICY-RETURN-1
판정불가 422 '민원접수' 은 종결 게이트가 판정할 수 있는 처리유형이 아닙니다
응답에 위험도·점수·”안전” 류 표현이 없다(부록 A-1).
⚠ 주장 범위를 넘지 않는다
이 게이트는 “근거 없는 종결의 비용을 올린다” 는 목적이지 “허위 기재를 막는다” 는 목적이 아니다(2.7절·부록 A-3). 상담원이 필드를 고의로 거짓 입력하면 막을 수 없고, 막을 수 있는 척하지도 않는다. 판정 서비스 docstring 에 적어 뒀다.
F-2 는 기획서상 조건부(7주차 체크포인트) 다. 코어를 미루고 착수한 것이 아니라,
w2-naive-rag(류준 님)가 붙어야 풀리는 501 두 개(트리거·검색)를 기다리는 동안server/안에서 모델 없이 완결되는 일이라 먼저 했다.