ActAI
경력근거: Identify failure modes and ensure AI systems behave predictably
※ 실제 산출물이 아닌 AI 예측 시안입니다.
ActAI 공고는 이 자리의 일을 실패 유형을 찾아내고 시스템이 예측 가능하게 움직이게 하는 것으로 적고, 쓰는 사람을 복잡한 프롬프팅에 익숙하지 않은 사람으로 잡습니다. 프롬프트를 모르는 사람이 메일함을 통째로 맡기는 제품이라, 앱이 무엇을 근거로 그렇게 답장했는지 사용자가 앱 안에서 확인하는 자리가 곧 제품 기능입니다. 이 포트폴리오는 그 확인 화면과 판정 규칙을 보여줍니다. 언어 모델이 사실을 지어내지 않게 만드는 학습·정렬 쪽 깊이는 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
공고가 이 역할에 실패 유형을 찾아내고 시스템이 예측 가능하게 움직이게 하는 일을 맡깁니다. 그래서 자동 처리 결과를 원문과 맞대는 화면이 곧 그 일의 산출물입니다.
이 제품의 사용자는 복잡한 프롬프팅을 배우지 않은 사람입니다. 앱이 알아서 처리한 결과를 사용자가 앱 안에서 그대로 확인하는 자리를 만듭니다.
평가 틀과 품질 기준을 세우는 일이 공고의 주요 업무입니다. 처리 종류별 확신도 기준과 회신 기준 시간을 표로 받아 규칙이 판정합니다.
AI 이메일 앱 안에 들어가는 자동 처리 확인 화면입니다. 앱이 어제 대신 보낸 답장과 등록한 일정을 원문 메일과 맞대어, 원문에 없던 날짜와 금액이 들어간 처리와 기한을 넘겨 나간 처리를 사유별로 세우고 어떤 원문 값을 보고 그렇게 판정했는지 붙입니다. 판정은 Node.js 서버의 규칙이 계산하고 React Native 화면이 그 결과를 그립니다.
복잡한 프롬프팅을 모르는 채로 AI 이메일 앱에 메일함을 맡긴 사람 — 앱이 알아서 답장하고 일정을 잡아 주는데, 그게 원래 메일에 있던 내용인지 앱이 지어낸 말인지 확인할 자리가 지금은 없어서 보낸 편지함을 하나씩 열어 본다
앱이 대신 처리한 결과를 원문 메일의 날짜와 금액에 맞대어 사유별로 세우면, 사용자가 보낸 편지함을 하나씩 열지 않고 짚어 볼 처리만 확인합니다.
행동 기록 15건과 원문 메일 14건, 처리 기준 10건을 넣으면 짚어 볼 처리가 사유별로 뜨는 React Native 화면과 Node.js 판정 API 가 돕니다. 메일함 실계정 연동은 앱이 이미 내려받아 저장한 상태로 가정하고 3주차로 미룹니다.
Claude Sonnet 이 판정 결과를 사용자가 읽을 한 문장으로 옮기고 JSON 스키마로 형식을 잡습니다. 규칙 정답표와 맞대는 러너가 판정 일치 수를 화면 아래에 올립니다.
카드에서 발송을 되돌리는 요청과 처리 종류별 확신도 기준을 앱에서 고치는 화면이 붙습니다. 메일함 연동으로 받은 원문을 그대로 담는 경로도 이때 넣습니다.
사용자가 어제치 행동 기록 15건과 원문 메일 14건을 올리면 짚어 볼 처리가 사유별로 뜨고 어떤 원문 값을 보고 그렇게 판정했는지 카드에서 펼쳐집니다.
판정이 규칙과 맞는지 행동 기록 15건을 자가채점 러너로 세어 화면 아래에 표시합니다. 정답과 데이터를 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건에서의 동작입니다.
원문의 금액 칸이 비어 있거나 회신 기한이 아예 없는 악성·결측 입력 30종을 넣어도 카드 대신 어느 줄이 왜 걸렸는지 나오고 응답 형식이 깨지지 않습니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 더미데이터 자가채점이고, 실제 자동 처리 정확도는 ActAI 의 실사용 메일함과 실제 사용자 신고가 있어야 잽니다. 이 포트폴리오는 그 검증을 바로 돌릴 상태까지 만듭니다.
카드 아래 판정 일치 수는 제가 만든 메일 더미를 제가 채점한 값이라 자동 처리 정확도의 증명이 아닙니다. 면접에서는 이 화면이 실제 메일함에 붙었을 때 무엇부터 재야 하는지로 이야기를 잇습니다.
짚어 볼 처리를 제가 고르고 제가 채점했으니 잘 맞는 것은 당연합니다. 그래서 원문에 금액이 없는데 답장에는 금액이 들어간 처리, 확신도가 최대값 1.00 인 채로 나간 처리, 한 대화에 답장이 두 통 나간 처리, 종류별 기준 점수에 못 미치는데 확인 없이 나간 처리를 더미에 일부러 넣어 규칙이 무엇을 잡고 무엇을 놓치는지 드러나게 했습니다.
원문에 없는 사실이라는 판정은 날짜와 금액 두 칸을 견주는 데까지입니다. 답장 문장의 어조가 원문과 달라진 경우는 이 규칙이 잡지 못하고, 사람이 카드를 열어 원문을 읽어야 압니다.
이 포트폴리오는 확인 화면과 판정 규칙을 보여줍니다. 언어 모델이 사실을 지어내지 않게 만드는 학습·정렬 쪽 전문성은 주장하지 않고, 판정은 원문 값과의 대조로만 합니다.
실제로 붙이면 메일 본문에서 날짜와 금액을 뽑아내는 일부터 달라집니다. 첨부와 인용문이 섞인 본문 파싱, 개인 메일 보관 기간과 접근 권한은 도입 단계 과제로 따로 잡습니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
AI 앱이 사용자를 대신해 한 처리 기록입니다. 원문에서 뽑았다고 앱이 적어 둔 날짜와 금액을 그대로 담고, 뽑을 값이 없던 처리는 두 칸을 null 로 둡니다. 한 대화에 답장이 두 통 나간 기록, 확신도가 최대값 1.00 으로 찍힌 기록, 종류별 기준 점수에 못 미치는데 사람 확인 대상이 아니라 그대로 나간 기록도 그대로 담았습니다.
| action_no | thread_id | action_type | extracted_due_date | extracted_amount | sent_at | confidence |
|---|---|---|---|---|---|---|
| ACT-20260303-001 | TH-1041 | 회신 | — | — | 2026-03-03T07:12 | 0.88 |
| ACT-20260303-002 | TH-1042 | 회신 | — | 1,200,000 | 2026-03-03T07:20 | 1 |
| ACT-20260303-003 | TH-1043 | 회신 | 2026-03-14 | — | 2026-03-03T07:31 | 0.91 |
| ACT-20260303-004 | TH-1044 | 회신 | — | — | 2026-03-03T09:00 | 0.83 |
| ACT-20260303-005 | TH-1045 | 회신 | — | — | 2026-03-03T08:02 | 0.79 |
아래 JSON Schema 에 정확히 맞는 AI 이메일 앱의 자동 처리 기록 30개를 JSON 배열로 만들어 주세요.
{"type":"object","properties":{"action_no":{"type":"string"},"thread_id":{"type":"string"},"action_type":{"type":"string","enum":["회신","일정 등록","전달","요약 발송","문서 요청","결제 안내 회신","부재 안내","구독 해지 회신","미팅 확정","첨부 확인 요청"]},"extracted_due_date":{"type":["string","null"]},"extracted_amount":{"type":["integer","null"]},"sent_at":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1}},"required":["action_no","thread_id","action_type","extracted_due_date","extracted_amount","sent_at","confidence"]}
조건: action_no 는 ACT-연월일-일련 형식으로 서로 다르게 씁니다. thread_id 는 mailbox_thread 에 실재하는 값만 쓰고, sent_at 은 하루치 새벽과 오전 시각으로 흩뿌립니다. confidence 는 0.40 에서 1.00 사이로 소수 둘째 자리까지 씁니다.
쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: extracted_amount 가 비어 있는 행 8건, extracted_due_date 가 비어 있는 행 10건, confidence 가 최대값 1.00 인 행 2건, 종류별 min_confidence 에 미달하는 행 3건, 한 thread_id 에 회신이 두 줄 붙은 대화 2건. 그리고 형식 깨뜨리기 시도 3건(컬럼 이름 오타·쉼표 누락·따옴표 불일치)을 별도 파일로 만들어 화면이 어떻게 걸러 내는지 보게 합니다.
JSON 배열만 출력합니다.{"type":"object","properties":{"action_no":{"type":"string"},"thread_id":{"type":"string"},"action_type":{"type":"string","enum":["회신","일정 등록","전달","요약 발송","문서 요청","결제 안내 회신","부재 안내","구독 해지 회신","미팅 확정","첨부 확인 요청"]},"extracted_due_date":{"type":["string","null"]},"extracted_amount":{"type":["integer","null"]},"sent_at":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1}},"required":["action_no","thread_id","action_type","extracted_due_date","extracted_amount","sent_at","confidence"]}앱이 답장하기 전에 받은 원문 메일 대화입니다. 상대가 본문에 적은 마감일과 금액, 회신 기한을 담고, 본문에 그런 값이 없던 대화는 해당 칸이 비어 있습니다. 이 표가 판정의 기준 원문이라 앱이 뽑았다고 적은 값과 짝지어 견줍니다.
| thread_id | counterpart | subject | body_due_date | body_amount | reply_deadline | received_at |
|---|---|---|---|---|---|---|
| TH-1041 | 관리사무소 | 3월 관리비 안내 | — | — | 2026-03-03T18:00 | 2026-03-03T06:40 |
| TH-1042 | 세무사 | 부가세 신고 자료 요청 | — | — | 2026-03-04T18:00 | 2026-03-03T06:55 |
| TH-1043 | 채용 담당 | 과제 제출 안내 | 2026-03-04 | — | 2026-03-03T18:00 | 2026-03-02T10:00 |
| TH-1044 | 은행 알림 | 이체 한도 상향 확인 | — | — | 2026-03-02T21:00 | 2026-03-02T15:00 |
| TH-1045 | 집주인 | 보일러 점검 일정 | — | — | 2026-03-03T20:00 | 2026-03-02T19:30 |
아래 JSON Schema 에 정확히 맞는 개인 메일함의 대화 행 25개를 JSON 배열로 만들어 주세요.
{"type":"object","properties":{"thread_id":{"type":"string"},"counterpart":{"type":"string"},"subject":{"type":"string"},"body_due_date":{"type":["string","null"]},"body_amount":{"type":["integer","null"]},"reply_deadline":{"type":["string","null"]},"received_at":{"type":"string"}},"required":["thread_id","counterpart","subject","body_due_date","body_amount","reply_deadline","received_at"]}
조건: thread_id 는 TH-네자리 형식으로 서로 다르게 씁니다. counterpart 는 세무사·관리사무소·은행 알림·채용 담당처럼 개인이 실제로 받는 상대로 쓰고, subject 는 그 상대가 보낼 법한 제목으로 씁니다. received_at 은 agent_action 의 sent_at 보다 앞선 시각으로 둡니다.
쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: body_amount 가 비어 있는 행 15건, body_due_date 가 비어 있는 행 18건, reply_deadline 이 아예 없는 행 3건, 회신 기한이 받은 지 6시간 뒤로 짧게 잡힌 행 2건.
JSON 배열만 출력합니다.{"type":"object","properties":{"thread_id":{"type":"string"},"counterpart":{"type":"string"},"subject":{"type":"string"},"body_due_date":{"type":["string","null"]},"body_amount":{"type":["integer","null"]},"reply_deadline":{"type":["string","null"]},"received_at":{"type":"string"}},"required":["thread_id","counterpart","subject","body_due_date","body_amount","reply_deadline","received_at"]}처리 종류마다 몇 점부터 사람 확인 없이 내보내도 되는지, 몇 시간 안에 회신해야 하는지를 적은 기준표입니다. 판정은 이 표의 값을 읽어 계산하므로 기준이 바뀌면 코드가 아니라 이 표만 고칩니다.
| action_type | min_confidence | needs_confirm | max_reply_hours |
|---|---|---|---|
| 회신 | 0.7 | false | 6 |
| 일정 등록 | 0.8 | false | 12 |
| 전달 | 0.6 | false | 24 |
| 요약 발송 | 0.6 | false | 24 |
| 문서 요청 | 0.7 | false | 24 |
아래 JSON Schema 에 맞는 action_policy 행을 더 만들어 주세요. {"type":"object","properties":{"action_type":{"type":"string","enum":["회신","일정 등록","전달","요약 발송","문서 요청","결제 안내 회신","부재 안내","구독 해지 회신","미팅 확정","첨부 확인 요청"]},"min_confidence":{"type":"number","minimum":0,"maximum":1},"needs_confirm":{"type":"boolean"},"max_reply_hours":{"type":"integer","minimum":1,"maximum":72}},"required":["action_type","min_confidence","needs_confirm","max_reply_hours"]} action_type 은 AI 이메일 앱이 대신 하는 처리 종류이고, min_confidence 는 사람 확인 없이 내보낼 최소 점수, max_reply_hours 는 받은 뒤 회신까지 허용하는 시간입니다.{"type":"object","properties":{"action_type":{"type":"string","enum":["회신","일정 등록","전달","요약 발송","문서 요청","결제 안내 회신","부재 안내","구독 해지 회신","미팅 확정","첨부 확인 요청"]},"min_confidence":{"type":"number","minimum":0,"maximum":1},"needs_confirm":{"type":"boolean"},"max_reply_hours":{"type":"integer","minimum":1,"maximum":72}},"required":["action_type","min_confidence","needs_confirm","max_reply_hours"]}| TypeScript | 앱 화면과 판정 API 를 같은 언어로 쓰고 판정 결과의 모양을 타입으로 잡습니다. |
| React Native | 하단 탭 네 개와 사유별 카드 목록, 근거 펼침 화면을 만듭니다. |
| Node.js | 원문 메일과 행동 기록을 맞대어 사유를 계산하는 판정 API 를 세웁니다. |
| PostgreSQL | 행동 기록과 원문 메일, 처리 기준 세 표를 담고 대화 단위로 묶어 조회합니다. |
| LLM | 판정이 끝난 카드의 사유를 사용자가 읽을 한 문장으로 옮깁니다. 판정에는 관여하지 않습니다. |
| JSON Schema | 카드 출력의 형식을 강제해 문장이 길어져도 화면이 받는 모양이 그대로입니다. |
✓ pass → 여기서 멈춰도 완결입니다. 더 키우려면 카드 문장 생성과 자가채점 러너를 붙입니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우려면 되돌리기와 처리 기준 편집 화면을 넣습니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · action_no + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
원문대로 나감원문대로메일에 없는 사실 지어냄없는 사실회신 기한 넘겨 처리기한 초과확인 받아야 하는데 그냥 보냄확인 없이 발송같은 대화에 두 번 답장답장 두 통앱이 대신 한 처리 한 건에 대해 원문과 맞대 본 결과를 담는 카드입니다. 원문대로 나간 처리도 카드로 내보내 사용자가 무엇이 정상이었는지 함께 봅니다.
{"type":"object","properties":{"action_no":{"type":"string"},"thread_id":{"type":"string"},"counterpart":{"type":"string"},"verdict":{"type":"string","enum":["원문대로 나감","메일에 없는 사실 지어냄","회신 기한 넘겨 처리","확인 받아야 하는데 그냥 보냄","같은 대화에 두 번 답장"]},"overdue_hours":{"type":["number","null"],"description":"agent_action.sent_at 과 mailbox_thread.received_at 의 차를 시간으로 잰 뒤 그 종류의 max_reply_hours 를 뺀 값이며 소수 둘째 자리까지 반올림합니다. 그 세 값은 evidence 에 그대로 싣습니다. 판정과 무관하게 채웁니다 — 다른 사유가 먼저 걸린 처리도 기한을 넘겼으면 그 시간이 남습니다. 뺀 값이 0 이하이거나 상대가 회신 기한을 적지 않은 대화는 null 로 둡니다."},"low_confidence":{"type":"boolean","description":"그 처리의 confidence 가 종류별 min_confidence 에 못 미치면 참입니다. needs_confirm 이 거짓이라 사람 확인 없이 나간 처리도 이 칸으로 확인 목록에 올라옵니다."},"summary":{"type":"string"},"evidence":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"agg":{"type":"string","enum":["count"],"description":"이 항목의 value 가 수록 행의 값이 아니라 그 컬럼으로 센 행 수임을 밝힙니다. 없으면 수록 행의 값 그대로입니다."},"value":{"type":["string","number","boolean","null"]},"quote":{"type":"string"}},"required":["field"]}},"hedge":{"type":["string","null"]}},"required":["action_no","thread_id","counterpart","verdict","overdue_hours","low_confidence","summary","evidence","hedge"]}[
{
"action_no": "ACT-20260303-001",
"thread_id": "TH-1041",
"counterpart": "관리사무소",
"verdict": "원문대로 나감",
"overdue_hours": null,
"summary": "관리사무소 회신은 원문에 없던 날짜와 금액을 넣지 않았고 상대가 적어 둔 기한 안에 나갔습니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-001",
"quote": "ACT-20260303-001"
},
{
"field": "extracted_amount",
"value": null
},
{
"field": "body_amount",
"value": null
},
{
"field": "confidence",
"value": 0.88
},
{
"field": "min_confidence",
"value": 0.7
}
],
"hedge": null,
"low_confidence": false
},
{
"action_no": "ACT-20260303-013",
"thread_id": "TH-1052",
"counterpart": "학원",
"verdict": "원문대로 나감",
"overdue_hours": null,
"summary": "학원 부재 안내는 원문에 없던 값을 넣지 않았고 사람 확인이 필요한 종류도 아닙니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-013",
"quote": "ACT-20260303-013"
},
{
"field": "extracted_due_date",
"value": null
},
{
"field": "confidence",
"value": 0.94
},
{
"field": "min_confidence",
"value": 0.6
},
{
"field": "needs_confirm",
"value": false
}
],
"hedge": null,
"low_confidence": false
},
{
"action_no": "ACT-20260303-002",
"thread_id": "TH-1042",
"counterpart": "세무사",
"verdict": "메일에 없는 사실 지어냄",
"overdue_hours": null,
"summary": "세무사 회신에 120만원이라는 금액이 들어갔는데 원문 메일에는 금액이 없습니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-002",
"quote": "ACT-20260303-002"
},
{
"field": "extracted_amount",
"value": 1200000
},
{
"field": "body_amount",
"value": null
},
{
"field": "confidence",
"value": 1
},
{
"field": "subject",
"value": "부가세 신고 자료 요청",
"quote": "부가세 신고 자료 요청"
}
],
"hedge": "모델 확신도가 최대값 1.00 인 채로 원문에 없는 금액이 나갔습니다. 확신도만 보고는 지어낸 답장을 거르지 못합니다.",
"low_confidence": false
},
{
"action_no": "ACT-20260303-003",
"thread_id": "TH-1043",
"counterpart": "채용 담당",
"verdict": "메일에 없는 사실 지어냄",
"overdue_hours": 15.52,
"summary": "채용 담당 회신이 제출 마감을 3월 14일로 답했는데 원문 메일의 마감은 3월 4일입니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-003",
"quote": "ACT-20260303-003"
},
{
"field": "extracted_due_date",
"value": "2026-03-14"
},
{
"field": "body_due_date",
"value": "2026-03-04"
},
{
"field": "subject",
"value": "과제 제출 안내",
"quote": "과제 제출 안내"
},
{
"field": "received_at",
"value": "2026-03-02T10:00"
},
{
"field": "sent_at",
"value": "2026-03-03T07:31"
},
{
"field": "max_reply_hours",
"value": 6
}
],
"hedge": "이 처리는 회신 기한도 15.52시간 넘겼습니다. 판정 순서상 지어냄이 먼저 걸려 카드는 그쪽으로 세우고, 넘긴 시간은 칸에 남겨 둡니다.",
"low_confidence": false
},
{
"action_no": "ACT-20260303-004",
"thread_id": "TH-1044",
"counterpart": "은행 알림",
"verdict": "회신 기한 넘겨 처리",
"overdue_hours": 12,
"summary": "은행 알림 회신이 받은 지 18시간 만에 나가 회신 기준 6시간을 12시간 넘겼습니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-004",
"quote": "ACT-20260303-004"
},
{
"field": "received_at",
"value": "2026-03-02T15:00"
},
{
"field": "sent_at",
"value": "2026-03-03T09:00"
},
{
"field": "reply_deadline",
"value": "2026-03-02T21:00"
},
{
"field": "max_reply_hours",
"value": 6
}
],
"hedge": null,
"low_confidence": false
},
{
"action_no": "ACT-20260303-007",
"thread_id": "TH-1046",
"counterpart": "통신사",
"verdict": "확인 받아야 하는데 그냥 보냄",
"overdue_hours": null,
"summary": "결제 안내 회신은 사람 확인을 받고 나가야 하는 종류인데 확신도 0.42 인 채로 발송까지 끝났습니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-007",
"quote": "ACT-20260303-007"
},
{
"field": "confidence",
"value": 0.42
},
{
"field": "min_confidence",
"value": 0.7
},
{
"field": "needs_confirm",
"value": true
},
{
"field": "sent_at",
"value": "2026-03-03T08:15"
}
],
"hedge": null,
"low_confidence": true
},
{
"action_no": "ACT-20260303-006",
"thread_id": "TH-1045",
"counterpart": "집주인",
"verdict": "같은 대화에 두 번 답장",
"overdue_hours": 7.18,
"summary": "집주인 대화에 답장이 39분 사이로 두 통 나갔는데 그 사이 새로 받은 메일이 없습니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-005",
"quote": "ACT-20260303-005"
},
{
"field": "action_no",
"value": "ACT-20260303-006",
"quote": "ACT-20260303-006"
},
{
"field": "action_no",
"agg": "count",
"value": 2
},
{
"field": "received_at",
"value": "2026-03-02T19:30"
},
{
"field": "sent_at",
"value": "2026-03-03T08:02"
},
{
"field": "sent_at",
"value": "2026-03-03T08:41"
},
{
"field": "max_reply_hours",
"value": 6
}
],
"hedge": "두 통 가운데 나중 답장이 회신 기한을 7.18시간 넘겼습니다. 판정 순서상 두 번 답장이 먼저라 카드는 그쪽으로 세웁니다.",
"low_confidence": false
},
{
"action_no": "ACT-20260303-015",
"thread_id": "TH-1054",
"counterpart": "동호회 총무",
"verdict": "원문대로 나감",
"overdue_hours": null,
"low_confidence": true,
"summary": "동호회 총무 메일 전달은 원문에 없던 값을 넣지 않았지만 확신도 0.55 가 전달 기준 0.60 에 못 미칩니다.",
"evidence": [
{
"field": "action_no",
"value": "ACT-20260303-015",
"quote": "ACT-20260303-015"
},
{
"field": "confidence",
"value": 0.55
},
{
"field": "min_confidence",
"value": 0.6
},
{
"field": "needs_confirm",
"value": false
},
{
"field": "extracted_amount",
"value": null
}
],
"hedge": "이 종류는 사람 확인 대상이 아니라 기준 점수에 못 미쳐도 그대로 나갑니다. 판정은 원문대로 나감이지만 확신도가 낮은 처리 목록에 함께 올려 사용자가 한 번 보게 합니다."
}
][자동 검증 · 사람 없이 러너가 돌립니다] 1. verdict 가 스키마가 선언한 다섯 값 안에 있는지 확인합니다. 2. action_no·thread_id·verdict·overdue_hours·low_confidence·summary·evidence 필드가 샘플에 있는지 확인합니다. 3. agent_action 의 confidence 가 0 이상 1 이하 범위인지 확인합니다. 4. overdue_hours 를 그 처리의 sent_at 에서 그 대화의 received_at 을 뺀 시간에서 action_policy.max_reply_hours 를 뺀 값으로 다시 계산해 소수 둘째 자리까지 반올림한 값과 같은지 봅니다. **판정과 무관하게 채웁니다** — 지어냄이나 두 번 답장으로 판정이 갈린 처리도 기한을 넘겼으면 그 시간이 남고, 뺀 값이 0 이하이거나 reply_deadline 이 비어 있으면 null 입니다. 5. low_confidence 를 confidence 가 그 종류의 min_confidence 보다 작은지로 다시 계산해 같은 값인지 봅니다. needs_confirm 이 참이면 verdict 가 확인 받아야 하는데 그냥 보냄으로 갔는지, 거짓이면 판정은 그대로 두고 이 칸만 참인지 맞춰 봅니다. 6. evidence 의 field 가 세 데이터셋의 컬럼에 실재하는지 확인합니다. 7. evidence 의 quote 가 수록 샘플의 원문 그대로인지 확인합니다. 8. summary 가 존댓말로 끝나는지 확인합니다. 9. 조건 규칙으로 mailbox_thread 의 reply_deadline 이 비어 있으면 overdue_hours 는 null 입니다. 성립 사례는 TH-1048 로 이어지는 처리이고, 불성립 사례는 ACT-20260303-004 입니다. [판정 순서 · 한 처리가 두 사유에 걸릴 때] ① 메일에 없는 사실 지어냄, ② 한 대화에 답장이 두 통 나간 경우, ③ 확인 받아야 하는데 그냥 보냄, ④ 회신 기한 넘겨 처리 차례로 보고 앞에서 걸리면 뒤는 보지 않습니다. ⑤ 어디에도 안 걸리면 원문대로 나감입니다. 사용자가 상대에게 다시 연락해야 하는 정도가 큰 순서입니다 — 없는 사실이 나간 답장은 정정 메일을 보내야 하지만 늦게 나간 답장은 이미 나갔습니다. ACT-20260303-003 은 지어냄과 기한 초과에, ACT-20260303-006 은 두 번 답장과 기한 초과에 함께 걸려 이 차례로 갈렸고, 넘긴 시간은 overdue_hours 칸에 그대로 남습니다. 확신도가 min_confidence 에 못 미치는데 needs_confirm 이 거짓인 처리는 verdict 를 바꾸지 않고 low_confidence 만 참으로 둡니다. 그 종류는 애초에 사람 확인 대상이 아니라 규칙을 어긴 것이 아니고, 그래도 사용자가 한 번 볼 자리는 필요하기 때문입니다. ACT-20260303-015 가 그 경우입니다. [수동 검증 · 사람이 봅니다] 1. 카드 문장이 프롬프트를 모르는 사용자에게 그대로 읽히는 말인지 봅니다. 2. 원문에 없는 값이라는 판정이 상대가 보낸 메일의 뜻과 어긋나지 않는지 봅니다. [평가 러너 · 2주차] 행동 기록 15건에 규칙으로 만든 정답표를 붙여 판정 일치를 세고, 갈라진 처리는 어느 사유에서 갈렸는지 나눠 리포트에 답니다.
근거: Identify failure modes and ensure AI systems behave predictably