기대값: AI가 계산, 오너 검수 전. 기대값 표는 파이썬 계산기가 앱 엔진 코드를 쓰지 않고 병원 규정 문서의 규칙을 다시 읽어 계산했습니다. 데이터·기대값·엔진을 같은 도구(Claude Code)로 만든 편향이 있어, 오너가 달력으로 검수하기 전까지 정답이 아닙니다. 합성 데이터 기준입니다.
PRD 6절 지표
| 지표 | 분자 / 분모 | 기준 | 결과 |
|---|---|---|---|
| 일정 계산 정확도 (시점 날짜·상태, 직접 해 보기 가상 입력) | 441 / 441 | 전부 | 맞음(검수 전) |
| 기대값 대조 전체 (일정 + 오늘 목록·네 목록·미방문 연락·시간대) | 540 / 540 | 전부 | 맞음(검수 전) |
| 미방문 누락 (제자리에 오지 않은 심은 미방문) | 0 / 19 | 0건 | 맞음(검수 전) |
| 결정성 (같은 기준 시각으로 다시 만든 목록이 다름) | 0 / 3 | 0건 | 기준 충족 |
| 연락 가능 시간대 위반 (시간대 밖인데 ‘지금 보내기’) | 0 / 1,440분 | 0건 | 기준 충족 |
| 테스트가 결함을 잡는지 (코어에 심은 변이를 잡은 비율) | 52 / 52 1차 43 / 52 | 살아남은 변이도 싣는다 | 생존 0 |
| 테스트가 결함을 잡는지 (화면 연결에 심은 변이) | 19 / 19 1차 17 / 18 | 살아남은 변이도 싣는다 | 생존 0 |
| 테스트가 결함을 잡는지 (v0.2.1 규칙에 심은 변이: 휴진 이동 범위·수신 거부·예약·재시작·명칭) | 79 / 80 1차 63 / 76 | 살아남은 변이도 싣는다 | 생존 1 F6 — 아래 기록 참고 |
결정성은 같은 입력으로 한 번 더, 환자 순서를 뒤집어서, 환자 순서를 돌려서 세 번 다시 만들어 첫 목록과 글자 그대로 비교했습니다. 시간대 위반은 기준일 하루 1,440분마다 문구를 만들어 연락 규정의 시간대(09:00~20:00, 끝 불포함)와 따로 대조했습니다. 엔진 판정(예약 시각이 시간대 안이고 만든 시각 뒤인지)과 환자 화면이 그리는 보내기 배지를 둘 다 셉니다(엔진 0 · 화면 0). 오늘 목록 문구 32개 중 기준 시각 09:00에 ‘지금 보내기’ 32개, 막힘 0개. 기대값은 오너 검수 전이라 기대값에 기대는 지표는 ‘맞음(검수 전)’으로 적었습니다.
기대값 대조
| 대조 | 맞음 / 전체 |
|---|---|
| 시점 날짜·상태 (환자 57명) | 397 / 397 같음 |
| 가상 입력 H1·H2·H3·H4·H5·H6 시점 | 44 / 44 같음 |
| 오늘 목록 (기대 27줄) | 27 / 27 같음 |
| 간호팀 확인 (기대 6명) | 6 / 6 같음 |
| 재연락 대기 (기대 1명) | 1 / 1 같음 |
| 의료진 확인 (기대 2명) | 2 / 2 같음 |
| 수신 거부 (기대 1명) | 1 / 1 같음 |
| 미방문 연락 상태 (환자별) | 57 / 57 같음 |
| 연락 가능 시간대 (기대값 표의 시각) | 5 / 5 같음 |
시점은 날짜·미룬 사유·월말 규칙·상태·방문일 같은 항목을 모두 비교해, 모두 같을 때만 맞음으로 셉니다.
개발자용 기록: 비교한 항목
원래 날짜·잡힌 날짜·옮긴 방향(미룸·앞당김·날짜 미정)·살펴본 휴진일·월말 clamp·공휴일 미확인·완료 인정 시작일(내원 시점만)·유예 끝·상태·예약 날짜·재시작·방문일·지남 시작일·내일 내원 안내일. 간호팀 확인은 까닭(재시작·최대 시도·날짜 미정)까지, 수신 거부는 걸려 있던 이유까지 비교합니다. 안내 시점의 ‘안내함 / 기록 없음’ 구분은 연락 규정에 정의가 없어 표시용 해석(미룬 날짜 뒤 첫 연락이 유예 안)으로 맞췄습니다.
틀린 사례
없습니다.
심은 사례
심은 사례 52 / 52건을 의도대로 잡았습니다(오늘 이유·미방문 자리·의료진 확인이 모두 의도와 같을 때). 심은 미방문 19건: P001 P002 P003 P004 P005 P006 P007 P008 P009 P010 P012 P013 P014 P016 P017 P045 P121 P122 P125.
심은 사례 목록과 의도는 data/README.md와 data/scripts/planted.json에 있습니다. 대조군(목록에 오면 틀린 환자) 8명도 여기에 들어 있습니다. 미방문의 제자리는 오늘 목록·재연락 대기·간호팀 확인·수신 거부 중 하나입니다.
변이 검사 기록
코드에 일부러 결함(변이)을 심고 시험이 그것을 잡는지 봤습니다. 2차에서 52 / 52개를 잡았고, 살아남은 변이는 0개입니다.
개발자용 기록: 변이 계열과 1차 생존 변이
코어 변이 검사 기록. 브라우저에서 돌릴 수 없어 기록을 싣는다. 실행기: 변이마다 src/core 한 곳을 글자로 바꾸고 npx vitest run, 실패한 시험이 하나라도 있으면 '잡힘'. 1차(화면 작업 전): 시험 153개 · 2차(살아남은 9개에 시험 추가 뒤): 시험 186개.
| 변이 계열 | 1차 잡힘 | 2차 잡힘 |
|---|---|---|
| 휴진일 무시 | 3 / 3 | 3 / 3 |
| 공휴일 무시 | 2 / 2 | 2 / 2 |
| 월말 규칙 뒤집기(넘치게) | 1 / 1 | 1 / 1 |
| 밀림을 앞당김으로 | 2 / 2 | 2 / 2 |
| 유예 일수(graceDays) 무시 | 2 / 2 | 2 / 2 |
| 조기 방문 창(earlyDays) 무시 | 3 / 3 | 3 / 3 |
| 재연락 간격 무시 | 3 / 3 | 3 / 3 |
| 최대 시도 +1 | 2 / 2 | 2 / 2 |
| 병합 대신 중복 줄 | 2 / 2 | 2 / 2 |
| 정렬 순서 바꿈 | 4 / 10 | 10 / 10 |
| 연락 시간대 20:00 경계 | 3 / 3 | 3 / 3 |
| 없는 칸을 빈 문자열로 | 3 / 3 | 3 / 3 |
| 누락 필드를 기본값으로 | 3 / 5 | 5 / 5 |
| 시계 직접 호출 | 6 / 6 | 6 / 6 |
| KST 대신 UTC | 4 / 5 | 5 / 5 |
1차에서 살아남은 변이 9개
- M10b 묶음 안: 이른 날짜 순 뒤집기
- M10f 원장 확인: 시도 많은 순 뒤집기
- M10g 연락 대기: retryOn 순 뒤집기
- M10h 줄 안 항목: 같은 이유끼리 날짜 순 뒤집기
- M10i 원장 확인: 동률일 때 오래된 since 순 뒤집기
- M10j 의료진 확인: ID 순 정렬 제거
- M13c 규칙 파서: 최상위 누락 키 검사 끔 + holidays 누락 → []
- M13e V02 파서: extraClosedDates 누락 → []
- M15e 연락일(contactDate)을 시각 문자열 앞 10자로
목록 안 정렬 6개, 규칙 파서 누락값 2개, 연락일 계산 1개였습니다. 각각을 잡는 시험(기대 순서는 손으로 정함)을 더한 뒤 2차에서 생존 0개입니다.
위 코어 기록은 v0.2 코드 기준입니다. v0.2.1에 더한 규칙은 따로 변이를 심어 2차에서 79 / 80개를 잡았고, 살아남은 변이는 1개입니다.
개발자용 기록: v0.2.1 규칙 변이 계열과 살아남은 변이
v0.2.1 규칙 변이 검사 기록. 실행기: scripts/mutate-rules.py — 변이마다 한 곳(또는 짝지은 몇 곳)을 글자로 바꾸고 npx vitest run, 실패한 시험이 하나라도 있으면 '잡힘'. 1차는 v0.2.1 구현 직후 시험으로 A~G 76개를 돌렸고 13개가 살아남았다(앞당김 표시, 날짜 미정 배지·설명, 기준 시각 뒤 기록, 수신 거부 환자의 간호팀 확인, 옮긴 날짜 기준 재시작 일수, 힌트의 문서 번호 등). 그 12개를 잡는 시험을 더하고, 독립 대조로 찾은 결함(14일 넘게 지난 뒤 앞날로 잡은 예약이 재시작을 가림)을 고친 뒤 H 계열 4개를 더해 2차를 돌렸다. F6(완료된 뒤 회차도 재시작 전으로)은 동작이 원본과 같은 변이다 — 뒤 회차가 완료되면 앞 미방문은 이미 건너뜀이라 재시작 대상이 되지 않는다. F7·G13은 결함을 고치며 대상 코드가 바뀌어 2차에서 대상 글자를 새 코드에 맞췄다. 1차(v0.2.1 구현 직후): 시험 335개 · 2차(시험 추가·예약 재시작 수정 뒤): 시험 349개.
| 변이 계열 | 1차 잡힘 | 2차 잡힘 |
|---|---|---|
| 휴진 이동 범위를 무시하거나 경계를 하루 틀림 | 7 / 7 | 7 / 7 |
| 앞당김 금지·순서·방향 표시 | 6 / 8 | 8 / 8 |
| 허용 범위 안 진료일 없음(날짜 미정) 표시 누락 | 9 / 11 | 11 / 11 |
| 수신 거부 무시·잘못 셈 | 12 / 14 | 14 / 14 |
| 예약 날짜가 지나도 계속 제외·유예·기준 시각 | 10 / 11 | 11 / 11 |
| 주사 재시작 14일 경계와 기준일 | 7 / 11 | 10 / 11 |
| 볼트 명칭 매핑 누락('원장 확인' 되돌림 포함) | 12 / 14 | 14 / 14 |
| 예약과 재시작(독립 대조 뒤 추가) | — | 4 / 4 |
1차에서 살아남은 변이 13개
- B6 목록 배지 '허용 범위 안 앞당김' 누락
- B7 목록 줄 앞당김 문구를 '미룸'으로
- C9 직접 해 보기 표 '허용 범위 안에 진료일 없음' 배지 누락
- C10 환자 화면 설명에서 no-open-day 문장 누락
- D3 기준 시각 뒤의 수신 거부까지 봄
- D5 수신 거부여도 간호팀 확인 유지
- E7 기준 시각 뒤 예약까지 봄
- F3 재시작을 원래 날짜에서 셈
- F6 완료된 뒤 회차도 on-hold
- F9 타임라인 재시작 일수를 원래 날짜에서 셈
- F11 재시작을 첫 회차가 아닌 마지막 해당 회차에
- G12 규칙 바꿔 보기 힌트 문서 이름 → V07
- G14 수신 거부 held 간호팀 라벨 → 원장 확인
2차에서 살아남은 변이 1개
- F6 완료된 뒤 회차도 on-hold
대조로는 잡히지 않는 것 (오너 판단 필요)
- 휴진 이동 범위는 두 시점에만 있습니다. 병원 문서가 옮길 범위를 적은 D+7 내원(D+6~D+9)과 두피 주사 회차(예정일 앞뒤 3일)만 범위 안에서 옮기고(9/17 수술의 D+7 9/24 → 9/23 앞당김, P027), 범위 안에 진료일이 없으면 간호팀 확인으로 보냅니다(9/18 수술의 D+7, P033). D+1·4주·6개월·1년은 문서에 범위가 없어 지금처럼 다음 진료일로 미룹니다. 이 시점들의 범위와, 앞당김보다 미룸을 먼저 보는 순서가 맞는지는 병원이 정할 일입니다.
- 주사 회차 다시 계산. 14일 넘게 빠진 회차는 의료진 진료 뒤 재시작으로 간호팀 확인에 보내고 뒤 회차를 보류합니다(P017·P045, 14일째인 P008은 아님). 주사 프로그램 문서의 “4일에서 14일 늦어지면 간호팀이 확인한 뒤 남은 회차 날짜를 다시 계산”은 하지 않아, 그 사이의 회차는 지금도 예정일 지남 목록에 올라 재예약 안내를 씁니다.
- 사후관리 연락 규정의 문장끼리 부딪힙니다. “미룬 날짜가 바로 오늘인 시점은 오늘 목록에 올리지 않습니다”를 글자 그대로 읽으면 안내 시점도 빠지지만, 관리 안내 규칙은 “미룬 날짜부터”라고 씁니다. 엔진·기대값 모두 앞 문장을 내원·사진 시점에만 적용해 P027·P033·P042가 오늘 관리 안내에 오릅니다. 문장에 “내원·사진 시점은”을 넣어 고정할지 정해야 합니다.
- data/README.md 계산 방법 5단계의 내일 내원 조건(“그날 이후 연락이 없으면”)은 연락 규정 본문에 없습니다. 지금 데이터에는 9/21 연락이 없어 결과가 같습니다.
- 다시 연락할 날(마지막 연락 + 재연락 간격)이 휴진일이면 화면의 ‘다음 연락’은 다음 진료일로 미뤄 보입니다. 목록 판정은 규정 문장 그대로의 날짜로 하지만, 이 ‘미뤄 보이기’는 규정에 적혀 있지 않습니다. 날짜 미정 시점은 간호팀 확인에 오르지만, 코디네이터 목록의 다른 이유(P033의 D+3 안내)는 그대로 둡니다.
- 한 환자에게 성격이 다른 문자가 두 통 만들어지는 경우가 있습니다: 미방문 + 내일 내원(P013). 미방문 문구는 시점이 여럿이어도 가장 이른 것 하나로 줄였지만, 두 통을 한 통으로 합칠지(어떤 문구로)는 병원이 정할 일입니다.
- 예약 잡음은 이 브라우저의 기록일 뿐입니다. 예약표와 잇지 않아, 예약 날짜가 지나면 방문 기록이 들어오기 전까지 다시 예정일 지남입니다(P125). 수신 거부(P121)는 의료진 확인(증상 메모)에서는 빼지 않습니다.
병원 도입 지표 (실제로 쓴다면 볼 것, 여기서는 재지 않음)
- 예정일 지남 환자 수의 추이
- 연락 뒤 재방문율
- 연락 한 건 처리 시간
- ‘간호팀 확인’으로 넘어간 환자 수와 까닭
- 수신 거부 환자 수