C-5 이름 끝 글자 누출 — 「다나카 유이」가 `*** *이` 로 남는다 (절대 규칙)
정성윤이 09-22 저녁 최종 QA(류준 페르소나 4 + 검증 웨이브)·운영 확인 결과를 보고 만든 티켓이다. 담당은 «제안»이다 — 본인이 확인하고 맞으면 착수, 아니면 옮긴다.
무엇을
09-22 E2E SYN-017 #12 에서 외국인 이름 「다나카 유이」의 마지막 글자 「이」가 확정 자막과 DB 에 남았다(*** *이). 규칙·NER 둘 다 놓쳤다.
하네스의 「C-5 누락 0」은 골든셋에 이 형태(띄어 쓴 외국인 이름의 끝 글자 경계)가 없어서다.
왜
절대 원칙 3(누락 0 > 과잉 억제)과 SEC-1. 한 글자라도 남으면 「누락 0건」을 발표에서 말할 수 없다.
완료 조건
- 골든셋에 이름 끝 글자 경계 케이스(외국인 이름 두세 어절 · 「이」「우」 같은 한 글자 끝) 추가
- 규칙(
name_detector)·NER 겹(spans.py) 보강 — 과잉률 변동을 같은 표에 그대로 - E2E 24건 재실행에서 판정기 글자 단위 ❌ 0 (
w6-replay-last-turn이 글자 단위로 잡는다)
근거: 미결 「2026-09-22 최종 QA」 첫 항목 · 류준 07번 기록.
2026-09-22 — 원인·수정 (류준, 에이전트)
재현: mask_text("저 이름 다나카 유이.") → "저 이름 *** *이.". 범인은 규칙 server/apps/masking/domain/services/name_detector.py 의
_after_context — 둘째 어절 「유이」 에 _strip_particles 를 걸어 「이」 를 주격 조사로 벗겼다(_PARTICLES 의 「이」). NER 은 이 문장에서
「유이」 를 아예 태깅하지 않았다(SYN-017 원문 맥락에서는 「다나카」 만 PER) — 그래서 두 겹 합집합도 같은 글자가 샜다.
문장만 떼어 넣으면 NER 이 「유이」 를 잡는다 — 맥락에 따라 흔들리는 겹이라 규칙이 바닥이어야 한다.
같은 갈래를 넓혀 보니 더 있었다(전부 옛 규칙에서 누출): 「아이요」·「마이에요」(「이」 한 글자) · 「유우입니다」·「소피아요」(「니다」·「아요」 를 동사 어미로 보고 둘째 어절 통째로) · 「첸 메이」·「박 지우」(첫 어절이 한 글자라 이름 전체를 버림) · 「김서이에요」·「한소이.」(한국 이름 끝 「이」).
수정
- 규칙
name_detector.py—_name_length(벗긴 조사가 「이」 로 시작하면 이어진 어절·성씨+두 글자·문장 끝 홑 「이」 일 때 그 「이」 까지 가린다 · 이어진 어절이 한 글자만 남으면 어절째) ·_verbal_continuation(이어진 어절 끝 서술격 조사 「요·예요·이요·이에요·입니다」 는 동사로 보지 않는다 — 「세요·해요·어요」·_NOT_NAMES는 그대로 동사) · 첫 어절 한 글자 예외(성씨·한 음절 외국 성_FOREIGN_SURNAMES_1이고 뒤에 두 글자 이상 어절) - NER 겹
ai/apps/pii_ner/domain/services/spans.pyperson_spans— 모델이 「유」 만 줬을 때 꼬리 「이」 를 벗기지 않는다(남은 이름 두 글자 이하일 때만) - 과잉: 이름 끝 「이」 한 글자를 더 가린다(
"응우옌 티 란이에요"→"*** * **에요"— 09-17 테스트의 기대값을 이 이유로 바꿨다). 「에요」·「요」 는 남긴다
골든셋 v1-150.json GS-421~GS-429(양성 9) — note_2026_09_22_c5. C-5 n 28 → 40(요청 티켓 2건 포함).
| 골든셋 C-5 (40건 = 양성 34 + 음성 6) | 누락(하네스) | 글자 단위 누출 | 오분류 | 과잉 마스킹률 |
|---|---|---|---|---|
| 전 · 규칙만 | 5 (GS-424·425·426·428·431) | 10/34 | 0 | 0/6 = 0.0 |
| 전 · 규칙+NER | 0 | 5/34 (GS-421·422·423·427·429 — 끝 「이」) | 0 | 1/6 = 0.167 (GS-431 「요청」) |
| 후 · 규칙만 | 0 | 0/34 | 0 | 0/6 = 0.0 |
| 후 · 규칙+NER | 0 | 0/34 | 0 | 0/6 = 0.0 |
⚠ 「전 · 규칙+NER 누락 0」 은 하네스가 이름을 두 글자 이상 남아야 누출로 세기 때문이다(masking_robustness.survives) — 끝 글자 하나는
하네스가 못 본다. 글자 단위 열은 서버 골든셋 테스트와 같은 기준(공백 제외)으로 따로 쟀다. 명령: scripts/run_eval.py --no-ner / --ner-model models/koelectra-ner
(--runs 3, ES 없이 — C-5 절만), 워킹트리 미커밋 상태(-dirty)라 수치는 이 커밋에서 다시 재야 기록할 수 있다.
합성 대본 24건 글자 단위 전수(394턴·라벨 49): 누출 규칙 1 → 0 · 규칙+NER 1 → 0(SYN-017 #12). 과잉 턴 규칙 6 → 7 · 규칙+NER 10 → 11 — 늘어난 것은 SYN-002 #12 「응우옌 티 란이에요」 의 「이」 한 글자뿐이다.
남은 것: ① E2E 24건 재실행(판정기 글자 단위 ❌ 0) — 중앙에서 한다 → 그 뒤 done ② 장민석 사후 리뷰(server/apps/masking 주 담당)
③ 알고 남긴 과잉 — "이름은 이 사람이에요" 처럼 성씨 한 글자 + 보통 명사가 문맥 뒤에 오면 이름으로 가린다(띄어 쓴 이름을 살리려 받은 값)
④ 자기소개·짧은 답 갈래("저는 김서이에요"·"김서이요.")는 손대지 않았다 — 어미 하나만 보는 설계("민원이요" 과잉 방지)라 「이」 끝 한국 이름을 놓칠 수 있다. 골든셋 표본 없음
2026-09-22 (밤) — 닫는다 (류준)
셋째 완료 조건 확인 — 합친 트리 5b2b4c4 로 로컬 E2E 24건(판정기가 글자 단위로 본다): C-5 글자 누출 0, SYN-017#12 *** *이 → *** **. 확정 자막 394건 중 바뀐 곳은 이것과 「란이에요」 트레이드오프 둘뿐(data/processed/persona-e2e/2026-09-22-1659.md). 운영(0.1.36)에도 이 수정이 들어가 있다.