B-37 은 열의 role 과 셀 타입이 맞는지를 본다. 양방향이다 — value·x·y·size 열은 number 또는 null 을, category 열은 string 을 요구한다. 하나라도 어긋나면 그 카테고리의 성립 판정이 통째로 깨진다.
role 을 쓰는 게 121건(30.9%)이고 그중 26건(6.6%)이 위반이다. 위반하면 예외 없이 tier 1 이 사라진다 — tier 1 소실 33건 중 26건(79%)이 이 경로다.
26건을 원문으로 다 열어 봤더니 성격이 넷으로 갈린다. 고치는 방법이 서로 다르다.
A. 연도 축에 문자열 — 12건 (46%)
role: x 인 연도 열에 "2023년"·"2021" 처럼 문자열이 들었다. csv-19·21·26·52·54.
데이터는 멀쩡하고 표기만 문제다. 축 라벨로는 "2023년" 이 오히려 자연스럽다.
B. 서술 열에 role: value — 11건 (42%)
주요 지원 내용·교육부·혜택 같은 서술 열 전체에 value 를 붙였다. csv-4·5·8·20·32·65·7.
csv-8 은 4개 열 16셀이 전부 문장이다. role 을 잘못 붙인 것이지 셀이 틀린 게 아니다.
C. category 열에 빈 칸 — 2건
csv-14 세부유형(category) 에 null, csv-51 내용(category) 에 null.
처음 24건으로 셌을 때 놓친 둘이 이것이다 — 숫자 role 만 검사했는데 B-37 은 category 열도 본다.
D. YAML 이 깨진 것 — 1건
csv-49 의 행이 ["기타(미혼", "비혼", "별거 등)", 5.4] 다. 원문은 "기타(미혼, 비혼, 별거 등)" 한 칸이었을 텐데 따옴표 없이 쉼표가 들어가 3칸으로 쪼개졌다.
여기서는 B-37 이 제 일을 했다 — 진짜 깨진 데이터를 잡아냈다.
검사 자체는 aippt — checkCellTypesByRole 이 벤더 packages/comp-frame-shared/src/eregion/visual-summary/establish.ts:142-188 에 있고 VENDOR.json 의 30개 .ts 중 하나다. AGENTS.md:87-88 이 패치를 금한다. 다만 검사를 느슨하게 하는 건 답이 아니다 — D 를 놓치게 된다.
A·B 는 생성기가 만든다 — 실서비스 프롬프트 aippt src/lib/visual-summary/generator/prompt.ts 에 「role: x 인 축 열의 셀은 숫자로 적는다(연도는 2023, "2023년" 이 아니다)」와 「서술 열에는 role 을 붙이지 않는다」 두 줄을 더하면 23건(88%)이 사라진다.
완화는 iui — src/comp-frame/useFrameSearch.ts 의 searchOne 앞에 보정 패스를 두고, 사유 문자열이 가리키는 그 열의 role 만 지워 재판정한다. A·B·C 에는 통하고 D 에는 통하면 안 된다 — 행 길이가 열 수와 다르면 건너뛰는 가드가 필요하다. 40줄 안팎.
실제 위반 · csv-19 (A)
columns:
- label: 연도
role: x
- label: 목표인원
role: y
rows:
- ["2023년", 800, 367]
- ["2024년", 540, 466]
→ tier 1 LineAreaChart 소실
1위 ComparisonTable tier 2 cost 201
실제 위반 · csv-49 (D)
- ["이혼", 84.2]
- ["사별", 10.4]
- ["기타(미혼", "비혼", "별거 등)", 5.4]
따옴표가 빠져 한 칸이 세 칸이 됐다
이건 B-37 이 옳게 잡은 것