# 19-1 · VCF 변이 주석과 HPO 표현형 매칭 오케스트레이션, ACMG 규칙 감사 관문 (acmg19)

APOSTOLUS의 19-1 연구 가운데 공개 실자료로 돌린 판정·감사 파이프라인이다. 독립 연구의 재현 기록이며 공고 과제의 선정·수행·성과가 아니다. 환자 자료, 임상 성능, 감사자 서명은 포함하지 않는다. 같은 과제의 가상 시험은 고정 가상 사례 4건으로 역할 분리와 관문을 검증하고, 공개 문헌 순위 평가는 문헌 사례 1,874건의 유전자 순위를 잰다. 이 모듈은 전문가 패널 판정 변이와 모의 환자에서 ACMG 기준 주장을 감사한다. 프로젝트용 근거는 evidence/acmg19-audit.json과 evidence/acmg19-run.json에 있다.

2026-11-14 KST에 희귀질환 진단기술개발 과제를 실행 코드로 구체화했다. 환자 VCF와 HPO 용어를 받아 에이전트 여섯이 차례로 일하고, 판정 에이전트가 낸 ACMG/AMP 기준은 감사 관문을 통과한 것만 보고서에 들어간다. 공개 자료로 만든 고정 입력에서 변이 판정, 모의 환자 진단, 감사 관문의 차단율을 쟀다. 기계 판독 결과 · 입력 출처와 해시 · [공식 통합공고 pp.105–107](https://www.iris.go.kr/contents/retrieveBsnsAncmView.do?ancmId=017154)

공고는 질병 지표를 개발할 때 민감도와 특이도 자료를 요구한다. 아래 수치는 그 두 값을 ClinGen 전문가 패널 판정 8,667건과 모의 환자 480명에서 잰 것이다. 규칙은 패널 40개 유전자 가운데 개발용 20개만 보면서 다듬었고, 나머지 20개(보류)는 마지막 수치를 낼 때만 썼다.

| 측정 | 보류 유전자 20개 | 개발 유전자 20개 |
| --- | ---: | ---: |
| 변이 판정 특이도 (전문가 양성·양성 추정 변이를 병원성으로 부르지 않은 비율) | 1,323/1,324 = 99.92% | 681/685 = 99.42% |
| 변이 판정 민감도 (전문가 병원성·병원성 추정 변이를 같은 쪽으로 부른 비율) | 984/1,890 = 52.06% | 912/2,112 = 43.18% |
| 모의 환자 진단 특이도 (원인 변이가 없는 사례를 음성으로 낸 비율) | 120/120 = 100% | 120/120 = 100% |
| 모의 환자 진단 민감도 (원인 유전자를 진단 후보로 낸 비율) | 58/120 = 48.33% | 66/120 = 55.00% |

감사 관문에는 정직한 주장 묶음에 거짓 주장을 하나씩 넣은 9,493건을 통과시켰고, 9,493건 모두 예상한 사유로 차단됐다. 장부를 고친 360건도 모두 거부됐다.

문헌 근거 단계는 따로 표본 96개에서 쟀다. 보류 표본의 병원성 미스센스 36개 가운데 병원성 쪽 판정이 16개에서 18개로 늘었고, 불확실·양성 24개는 하나도 병원성 쪽으로 바뀌지 않았다. 위 표의 수치는 문헌 근거를 넣지 않은 값이다.

## 에이전트 구성

| 순서 | 에이전트 | 하는 일 | 장부에 남기는 근거 |
| --- | --- | --- | --- |
| 1 | 접수 (`agents.intake`) | VCF를 읽어 다중 대립유전자를 나누고 최소 표기로 맞춘 뒤 발단자가 가진 변이만 남긴다 | 유전형, 접합성, 부모 유전형 |
| 2 | 주석 (`agents.annotate`) | 고정 저장소에서 변이별 사실을 붙인다 | 결과 유형과 NMD 예측, 집단 빈도, REVEL·SpliceAI, 유전자 제약, 같은 유전자의 확립 병원성 변이, 같은 잔기의 병원성 변이 |
| 3 | 표현형 (`agents.phenotype`) | 환자 HPO 용어와 질환 주석의 정보량 유사도로 유전자 5천여 개의 순위를 낸다 | 후보 유전자의 순위, 점수, 맞은 용어 |
| 4 | 유전 (`agents.inheritance`) | 트리오 유전형에서 신생 변이, 동형접합, 반대쪽 대립유전자를 읽는다 | 전달 양식, 두 번째 대립유전자 |
| 5 | 문헌 (읽기 에이전트 → `literature.check` → 2차 판독 → `literature.admit`) | 변이를 언급한 논문 조각을 언어 모델이 읽어 소견을 내고, 검증기와 다른 계열 모델의 2차 판독을 통과한 것만 받는다 | 기능 실험, 가계 분리, 환자에서 본 반대쪽 대립유전자 |
| 6 | 판정 (`agents.propose_by_rules` 또는 언어 모델) | 변이마다 ACMG/AMP 기준과 5단계 분류를 주장하고 근거 번호를 인용한다 | 장부에 쓰지 못한다. 주장만 낸다 |
| 7 | 감사 (`acmg_audit.py`) | 주장을 하나씩 검사하고, 통과한 기준만으로 분류를 다시 계산한다 | 기준별 판정과 사유 |
| 8 | 종합 (`agents.adjudicate`) | 감사된 분류, 유전 양식에 맞는 유전형, 표현형 순위로 진단 후보를 만든다 | 보고서 |

근거 항목의 번호는 내용의 SHA-256에서 나온다. 내용을 바꾸면 번호가 달라지고, 없는 번호는 지어낼 수 없다. 판정 에이전트가 차단을 받으면 사유와 함께 한 번 되돌려 받는다. 그래도 차단된 주장은 보고서에 들어가지 않는다. 오케스트레이터 · 에이전트 · 규칙표와 술어

## 감사 관문이 막는 것

기준 하나는 다음을 모두 만족해야 통과한다. 코드가 2015년 지침의 28개 가운데 하나다. 강도 표기가 그 기준에 쓸 수 있는 것이다. 인용한 근거 번호가 장부에 있고 그 변이나 그 유전자의 것이다. 기준이 요구하는 근거 종류가 인용에 모두 들어 있다. 인용한 값이 기준의 조건을 만족한다. 주장한 강도가 근거가 받치는 강도 이하다. 분류는 통과한 기준만으로 Richards 2015 표 5와 ClinGen의 초강력 1개 + 지지 1개 규칙에 따라 다시 계산하고, 주장한 분류와 다르면 불일치로 표시한다. 감사 스크립트

| 넣은 거짓 주장 | 건수 | 예상 사유로 차단 |
| --- | ---: | ---: |
| 지침에 없는 코드 (PS5, PM7, BP8 등) | 487 | 487 |
| 쓸 수 없는 강도 (BA1_Supporting, PM2_StandAlone 등) | 487 | 487 |
| 폐기된 기준 (PP5, BP6) | 487 | 487 |
| 근거를 인용하지 않음 | 462 | 462 |
| 장부에 없는 근거 번호 | 924 | 924 |
| 다른 변이의 근거를 빌려 옴 | 487 | 487 |
| 문헌이 필요한 기준을 장부 근거 없이 주장 (PS3, PP1 등) | 487 | 487 |
| 장부 값이 반박하는 기준 (미스센스에 PVS1, 흔한 변이에 PM2 등) | 4,208 | 4,208 |
| 근거보다 높은 강도 | 393 | 393 |
| 같은 기준을 두 번 | 462 | 462 |
| 같은 관찰을 두 기준으로 셈 (BA1과 BS1 등) | 122 | 122 |
| 기준이 받치지 않는 분류 | 487 | 487 |

거짓 주장은 모의 사례 120건에서 사례마다 원인 변이와 분류별 변이 하나씩을 골라 넣었다. 정직한 주장에 거짓 주장을 덧붙인 7,714건에서는 그 변이의 감사 분류가 바뀌지 않았다. 나머지 1,779건은 정직한 기준 하나를 근거 없는 형태로 바꿔 쓴 것이라 그 기준이 차단된다. 9,493건 모두에서 다른 변이의 판정은 그대로였다. 장부 값을 고친 240건과 판정 에이전트가 직접 써넣은 근거 120건은 감사가 장부째 거부했다. 규칙 엔진이 낸 정직한 주장 164,867건(변이 판정 17,504건, 모의 사례 147,363건)에서는 차단이 0건이었다. 주입 코드

## 변이 판정

ClinGen Evidence Repository에서 패널 유전자의 판정 10,064건을 받아 ClinVar의 GRCh38 좌표와 이어지는 8,667건을 썼다. 철회 3건, 좌표가 없거나 50염기를 넘는 1,375건, 질환에 따라 판정이 갈린 8건은 뺐다. 이 변이들을 VCF 하나로 만들어 같은 파이프라인에 넣었다. 판정할 변이 자신의 ClinVar 기록과 전문가 판정은 근거에서 뺐다. 환자 맥락이 없어 PM3, PM6, PP4는 적용되지 않는다. [ClinGen Evidence Repository](https://erepo.clinicalgenome.org/evrepo/) · [ClinVar 변이 요약](https://ftp.ncbi.nlm.nih.gov/pub/clinvar/tab_delimited/)

| 전체 8,667건 | 값 | 95% 구간 |
| --- | ---: | ---: |
| 민감도 | 1,896/4,002 = 47.38% | 45.83–48.93 |
| 특이도 | 2,004/2,009 = 99.75% | 99.42–99.89 |
| 전문가 불확실 변이를 병원성 쪽으로 부름 | 181/2,656 = 6.81% | |
| 전문가 병원성 변이를 양성 쪽으로 부름 | 1/4,002 | |

보류 유전자의 95% 구간은 민감도 49.81–54.31, 특이도 99.57–99.99다. 결과 유형별로는 절단 변이의 민감도가 가장 높고, 미스센스가 그다음이며, 인트론·스플라이스 주변·틀 유지 변이는 병원성으로 부른 것이 없다. 전문가 패널은 기능 실험(PS3), 가계 분리(PP1), 환자 관찰(PM3, PP4, PS4)을 문헌에서 가져오는데 이 장부에는 그 종류의 근거가 아직 없다. 표와 구간은 `result.json`의 `blindVariantClassification`에 있다.

기준별로 전문가 기록과 맞춰 보면 다음과 같다. 앞의 값은 파이프라인이 적용한 기준이 전문가 기록에도 있는 비율, 뒤의 값은 전문가가 적용한 기준을 파이프라인도 적용한 비율이다.

| 기준 | 파이프라인 → 전문가 | 전문가 → 파이프라인 |
| --- | ---: | ---: |
| PVS1 | 96.21% | 94.34% |
| PM2 | 80.84% | 96.36% |
| PP3 | 81.48% | 88.03% |
| BA1 또는 BS1 | 96.90% | 36.25% |
| BP4 | 74.54% | 56.46% |
| BP7 | 77.76% | 62.74% |
| PM5 | 45.01% | 62.72% |
| PP2 | 31.15% | 99.54% |

BA1과 BS1은 전문가 패널마다 질환별 빈도 문턱을 따로 두고, 이 파이프라인은 모든 유전자에 일반 문턱을 쓴다. 그래서 적용한 것은 거의 다 맞지만 전문가가 적용한 것의 3분의 1 남짓만 잡는다. PP2와 PM5는 파이프라인이 더 넓게 적용한다.

결합 규칙은 따로 검증했다. 전문가 패널이 적은 기준 코드를 그대로 넣어 분류를 계산하면 8,667건 가운데 8,257건(95.27%)이 전문가의 최종 분류와 같다. 점수 방식으로는 8,235건(95.02%)이 같다. 다른 것의 절반 남짓은 전문가가 양성 추정으로 낸 변이가 표 5로는 불확실이 되는 경우(220건)다.

## 모의 환자

패널 유전자마다 전문가가 병원성·병원성 추정으로 판정한 변이 여섯 개를 골라 양성 사례를 만들고, 같은 표현형에 원인 변이만 뺀 음성 사례를 짝지었다. 모두 480명이다. 배경 변이는 gnomAD 대립유전자 빈도에서 부모 염색체를 하나씩 뽑아 자녀에게 물려주는 방식으로 만들었다. 사례당 발단자가 가진 변이는 106~147개(중앙값 127)다. 설계는 동형접합 트리오, 복합 이형접합 트리오, 신생 변이 트리오, 모계 보인자 트리오, 부모 없는 단독 검체다. 표현형은 그 질환의 HPO 주석에서 다섯 개를 뽑아 절반을 상위 용어로 바꾸고 무관한 용어 두 개를 섞었다. 실제 환자 기록은 쓰지 않았다. [HPO 2026-09-01판](https://github.com/obophenotype/human-phenotype-ontology/releases/tag/v2026-09-01) · [gnomAD](https://gnomad.broadinstitute.org/)

| 전체 480명 | 값 | 95% 구간 |
| --- | ---: | ---: |
| 진단 민감도 | 124/240 = 51.67% | 45.37–57.91 |
| 진단 특이도 | 240/240 = 100% | 98.42–100 |
| 원인이 아닌 유전자를 진단으로 낸 사례 | 0 | |

진단은 두 조건이 함께 맞아야 양성이다. 감사를 통과한 병원성·병원성 추정 변이가 유전 양식에 맞는 유전형으로 있고, 그 유전자가 표현형 순위 10위 안이다. 넣은 원인 변이 270개 가운데 164개가 병원성 쪽으로 판정됐고 106개는 불확실로 남았다. 잡음을 섞은 표현형에서 원인 유전자는 65.42%가 1위, 80.83%가 10위 안이었다. 정확한 용어나 상위 용어만 쓰면 240건 모두 1위인데, 환자 용어를 같은 주석에서 뽑았기 때문에 이 값은 순위 계산이 맞게 돈다는 확인으로만 읽는다. 설계별로는 신생 변이 트리오가 48/75로 가장 높고 동형접합 트리오가 11/30으로 가장 낮다.

## 언어 모델을 판정 에이전트로 세운 시험

보류 유전자의 변이 24개(병원성 절단 6, 병원성 미스센스 6, 불확실 6, 양성 6)를 같은 장부와 함께 Claude Opus에 주고 두 가지 지시를 비교했다. 답변 원문은 `model-runs/`에 있고, `evaluate.py`가 매번 다시 감사한다.

| 지시 | 주장한 기준 | 통과 | 차단 | 분류 불일치 |
| --- | ---: | ---: | ---: | ---: |
| 장부 근거만 쓰고 번호를 인용 | 46 | 39 | 7 | 3 |
| 위 답변을 차단 사유와 함께 한 번 되돌림 | 45 | 44 | 1 | 1 |
| 기억에 있는 지식도 허용 | 53 | 30 | 23 | 8 |

장부만 쓰게 했을 때 차단된 7건 가운데 5건은 장부가 받치는 기준인데 필요한 근거 번호 하나를 빠뜨린 것이고, 1건은 REVEL 값이 받치지 않는 강도였고, 1건은 장부에 없는 종류의 근거(BP1)였다. 되돌린 뒤에는 인용이 채워져 44건이 통과했고, 값이 받치지 않는 PP3_Moderate 1건만 남았다. 기억을 허용했을 때 차단된 23건 가운데 9건은 장부에 점수가 없는 변이에 예측 기준(BP4, BP7)을 적용한 것이고, 그 9건 중 7건은 전문가 기록에도 있는 기준이다. 맞는 주장이어도 장부에 근거가 없으면 통과하지 못한다. 세 조건 모두에서, 감사를 거친 분류가 전문가 분류보다 병원성 쪽으로 나간 변이는 0개다.

이 시험은 Claude Code 하위 에이전트 경로로 돌렸다. 스크립트 전용 Anthropic API 키가 이날 `401 invalid x-api-key`로 거절됐기 때문이다. 첫 요청 4건과 수정 요청 2건, 모두 여섯 번의 실행이 있었고, 실행마다 프롬프트 파일 하나를 읽고 답 파일 하나를 쓰는 도구 호출 두 번만 했다(실행기가 보고한 횟수이며 `result.json`에는 요청 수만 있다). API 경로(`python3 -B -m acmg19.model_runs run`)는 구조화 출력과 거절 처리까지 써 두었고 유효한 키로 한 번도 실행되지 않았다. 모델 실행 코드

## 문헌 근거 에이전트

전문가 패널이 문헌에서 가져오는 근거 세 종류를 장부에 넣는 단계다. 기능 실험(PS3·BS3), 가계 분리(PP1), 환자에서 함께 본 반대쪽 대립유전자(PM3)다. 변이별 논문 목록은 LitVar2에서, 변이 표지가 붙은 본문은 PubTator3에서 받았다. 변이를 언급한 문장과 앞뒤 문장을 700자 이내의 조각으로 잘라 번호를 붙이고, 읽기 에이전트는 조각 번호만 인용해 소견을 낸다. [LitVar2](https://www.ncbi.nlm.nih.gov/research/litvar2/) · [PubTator3](https://www.ncbi.nlm.nih.gov/research/pubtator3/) · 문헌 모듈

소견 하나는 다음을 모두 만족해야 장부에 들어간다. 인용한 조각 번호가 그 변이의 것이다. 인용한 조각에 그 종류의 소견에 필요한 표현이 있다. 반대쪽 대립유전자는 인용한 조각에 표지된 변이이고 같은 유전자의 확립 병원성 기록이며 드물다. 다른 계열의 모델이 같은 조각을 다시 읽고 그 주장이 조각에 있다고 본다. 기능 실험 소견이 양쪽 방향으로 갈리면 쓰지 않는다. 강도는 기능 실험과 가계 분리 모두 지지 수준으로 고정했고, PM3는 ClinGen 점수표대로 발단자 점수를 더하되 문헌 몫을 2점으로 막았다. PM3는 열성 질환이 기록된 유전자에서만 적용한다.

표본은 전문가 판정 변이 96개다. 개발 유전자에서 24개, 보류 유전자에서 72개를 병원성 미스센스, 병원성 기타, 불확실 미스센스, 양성 미스센스 층으로 나눠 뽑았다. 지시문과 검증 규칙은 개발 표본만 보고 정했고, 보류 표본은 한 번만 돌렸다.

| 측정 | 보류 표본 72개 | 개발 표본 24개 |
| --- | ---: | ---: |
| 논문 목록이 있는 변이 | 43 | 18 |
| 본문 조각이 있는 변이 (조각 수) | 36 (270) | 17 (94) |
| 읽기 에이전트가 낸 소견 | 27 | 13 |
| 장부에 들어간 소견 | 19 | 7 |
| 차단된 소견 | 8 | 6 |
| 병원성 미스센스를 병원성 쪽으로 판정 (문헌 전 → 후) | 16/36 → 18/36 | 4/12 → 4/12 |
| 불확실·양성 변이가 병원성 쪽으로 바뀐 수 | 0/24 | 0/8 |

보류 표본에서 차단된 8건은 필요한 표현이 조각에 없는 것 5건, 반대쪽 대립유전자가 확립 기록이 아닌 것 2건, 2차 판독이 이의를 낸 것 1건이다. 그 1건은 읽기 에이전트가 기능 저하를 말하는 조각을 정상 기능으로 읽은 경우였다. 개발 표본의 2차 판독 이의 1건은 주장한 발단자 일부가 조각에 없는 경우였다. 2차 판독은 azure/gpt-5.4-mini가 검증기를 통과한 28건을 읽었고 비용은 $0.0188이다. 표본 밖 변이의 판정은 하나도 바뀌지 않았다.

보류 표본에서 장부에 들어간 근거를 전문가 기록과 맞춰 보면, 기능 실험은 파이프라인 10개 변이·전문가 21개 변이 가운데 4개가 겹치고, 반대쪽 대립유전자는 6개·15개 가운데 4개, 가계 분리는 3개·17개 가운데 2개가 겹친다. 본문 조각이 있는 변이가 절반이고 강도를 지지 수준으로 두었기 때문에 분류가 바뀐 변이는 2개다. 둘 다 전문가가 병원성 추정으로 판정한 변이이고, 하나는 기능 실험(PS3_Supporting), 하나는 가계 분리(PP1)가 더해져 불확실에서 병원성 추정이 됐다.

장부에 들어간 19건 가운데 3건은 전문가가 병원성으로 보지 않은 변이에 붙은 병원성 방향 근거다. 불확실 변이 하나와 양성 변이 하나의 기능 실험 소견, 양성 변이 하나의 반대쪽 대립유전자 소견이다. 세 변이의 분류는 바뀌지 않았다. 목록은 `result.json`의 `acceptedForVariantsExpertsDidNotCallPathogenic`에 있다.

검증기에는 조각 저장소만으로 만든 거짓 소견 493건을 넣었다. 없는 조각 번호, 다른 변이의 조각, 표현이 없는 조각에 붙인 소견, 조각에 없는 반대쪽 대립유전자, 확립 기록이 아닌 반대쪽 대립유전자 등 아홉 종류이고, 493건 모두 첫 검사에서 예상한 사유로 차단됐다. 2차 판독이 보여 준 것을 전부 받아들인다고 가정해도 장부에 들어간 것이 없다. 주입 코드

고정 입력에는 조각의 본문을 두지 않았다. 조각마다 PMID, 구획, SHA-256, 표현 표지, 함께 표지된 변이만 `inputs/literature.json.gz`에 있고, 읽기 에이전트의 답변에는 조각 번호와 에이전트가 자기 말로 쓴 요약만 있다. 본문은 `python3 -B -m acmg19.fetch CACHE --only literature`로 다시 받아 해시로 대조한다.

## 규칙의 출처

원문에서 글자 그대로 확인한 것은 다음과 같다. 점수 방식의 강도별 점수와 구간, BA1의 0.05와 2,000 대립유전자 조건, PP5·BP6 폐기, PM2를 지지 강도로 낮추고 초강력 1개 + 지지 1개를 병원성 추정으로 하는 규칙, PM3의 발단자당 점수표와 열성 질환·환자 조건, PS2·PM6의 표현형 일치도별 점수표, NMD를 피하는 위치 규칙과 단백질 10% 기준, 기능 근거가 중간 강도에 닿으려면 검증 대조 변이가 11개 이상 필요하다는 문장(Brnich 2019 초록)이다. REVEL 문턱(Pejaver 2022 표 2), SpliceAI 문턱(Walker 2023), Richards 2015 표 5는 조회 도구가 본문을 요약한 형태로만 읽었다. 표 5는 위의 95.27% 일치로 한 번 더 확인했다. [Richards 2015](https://pmc.ncbi.nlm.nih.gov/articles/PMC4544753/) · [Tavtigian 2020](https://pmc.ncbi.nlm.nih.gov/articles/PMC8011844/) · [Ghosh 2018](https://pmc.ncbi.nlm.nih.gov/articles/PMC6188666/) · [Biesecker & Harrison 2018](https://pmc.ncbi.nlm.nih.gov/articles/PMC6709533/) · [Abou Tayoun 2018](https://pmc.ncbi.nlm.nih.gov/articles/PMC6185798/) · [Pejaver 2022](https://pmc.ncbi.nlm.nih.gov/articles/PMC9748256/) · [Walker 2023](https://pmc.ncbi.nlm.nih.gov/articles/PMC10357475/) · [ClinGen PM2 v1.0](https://clinicalgenome.org/docs/pm2-recommendation-for-absence-rarity/) · [ClinGen PM3 v1.0](https://clinicalgenome.org/docs/pm3-recommendation-for-in-trans-criterion-pm3-version-1.0/) · [ClinGen PS2/PM6 v1.1](https://clinicalgenome.org/docs/ps2-pm6-recommendation-for-de-novo-ps2-and-pm6-acmg-amp-criteria-version-1.0/) · [Brnich 2019](https://pmc.ncbi.nlm.nih.gov/articles/PMC6938631/)

이 파이프라인이 정한 운용 규칙은 지침의 숫자가 아니다. `acmg.POLICY`에 모여 있고 바꾸면 결과가 달라진다. PM2 빈도 상한 0.0001, BS1 문턱(같은 유전자의 확립 병원성 변이 중 가장 높은 빈도의 10배, 하한 0.001), 기능 상실 기전의 조건(확립된 절단 변이 3개 이상), PP2 조건(미스센스 Z 3.09 이상이고 확립된 병원성 미스센스 3개 이상), 표현형이 매우 특이적이라고 보는 조건(유전자 순위 1위), 표현형이 맞는다고 보는 조건(10위 안), 환자 용어의 하위 30%를 평균에서 빼는 절사, 문헌 소견의 강도(기능 실험과 가계 분리는 지지 수준), 문헌 PM3 점수의 상한 2점, 변이당 읽는 논문 12편(가장 이른 6편과 가장 늦은 6편)이다. 확립 병원성 변이는 ClinVar에서 검토 등급 별 2개 이상인 병원성·병원성 추정 기록이다. PVS1 결정 나무는 그림을 읽지 못해 본문에 적힌 가지만 구현했고, 엑손 건너뜀이 틀을 유지하면 제거되는 단백질 비율로 강도를 정한다.

## 재실행

프로젝트 루트에서 Python 3.10 이상의 표준 라이브러리만으로 돈다. 측정은 4분쯤 걸리고 저장본과 바이트 단위로 같다. `./scripts/check`는 단위 시험과 근거 파일 대조(`tests/test_acmg19.py`)까지 돌리고, 4분짜리 전체 측정은 아래 명령으로 따로 돌린다.

~~~sh
python3 -B -m acmg19.evaluate > /tmp/acmg19-recheck.json
cmp acmg19/result.json /tmp/acmg19-recheck.json
python3 -B -m acmg19.summarize --check
python3 -B -m unittest discover -s tests -p 'test_acmg19.py'
~~~

사례 하나를 돌리거나, 다른 에이전트가 낸 주장을 감사할 때는 다음과 같이 한다. 두 번째 명령은 기억으로 댄 주장 8건 가운데 5건을 다섯 가지 사유로 차단하고, 주장한 병원성을 병원성 추정으로 고친다.

~~~sh
python3 -B -m acmg19.orchestrate --vcf acmg19/inputs/examples/PAH-02-P.vcf --case acmg19/inputs/examples/PAH-02-P.json
python3 -B -m acmg19.orchestrate --vcf acmg19/inputs/examples/PAH-02-P.vcf --case acmg19/inputs/examples/PAH-02-P.json \
  --claims acmg19/inputs/examples/PAH-02-P.claims-from-memory.json --full
~~~

`inputs/examples/`의 세 사례는 양성으로 맞힌 것(PAH-02-P), 음성(PAH-02-N), 변이는 병원성 추정으로 판정했지만 표현형 순위가 16위라 진단을 내지 않은 것(MECP2-02-P)이다. 장부와 주장 파일을 따로 가지고 있으면 `python3 -B -m acmg19.acmg_audit LEDGER.json CLAIMS.json`으로 감사만 돌린다. 종료 값은 통과 0, 차단 1, 장부 거부 2다.

고정 입력을 원자료에서 다시 만들 때는 캐시 폴더를 정해 아래 순서로 실행한다. 원자료는 ClinGen 33MB, ClinVar 458MB, HPO 세 파일 67MB, gnomAD 유전자 40개 응답, 논문 377편의 표지 본문이고, 받은 파일의 SHA-256은 `sources.json`에 있다. ClinGen과 gnomAD는 판 번호가 없는 조회라 다시 받으면 내용이 달라질 수 있다.

~~~sh
python3 -B -m acmg19.fetch CACHE
python3 -B -m acmg19.build_inputs CACHE
python3 -B -m acmg19.fetch CACHE --only revel
python3 -B -m acmg19.fetch CACHE --only literature
python3 -B -m acmg19.build_inputs CACHE
python3 -B -m acmg19.evaluate > acmg19/result.json
python3 -B -m acmg19.summarize
~~~

읽기 에이전트의 소견 파일을 사례에 붙일 때는 `python3 -B -m acmg19.orchestrate --vcf … --case … --literature FINDINGS.json --second-reader JUDGE.json`을 쓴다. 문헌 에이전트가 소견을 직접 검증하고 통과한 것만 장부에 쓴다. 완성된 근거를 밖에서 넘기는 인자는 없고, 2차 판독 없이 장부에 넣는 방법도 없다. `literature.check`는 판정만 돌려주고 근거를 만들지 않으며, 근거는 2차 판독 결과를 받는 `literature.admit`에서만 나온다. 문헌 수집은 LitVar2 응답이 느려 표본 96개에 15분쯤 걸렸고, 받은 논문은 377편이다.

## 검증 기록

단위 시험 46개가 통과했다(파이프라인 42개와 프로젝트 근거 대조 4개). `evaluate.py`는 해시 시드를 바꿔 두 번 실행한 출력이 바이트 단위로 같다. 감사 관문을 직접 점검해 세 곳을 고쳤다. 형식이 깨진 주장은 예외 없이 차단한다. 같은 변이에 대한 두 번째 주장은 받지 않는다. 문헌 근거는 기준이 요구하는 종류의 기록만 읽는다. 문헌 단계를 붙이면서 PM3를 열성 질환이 기록된 유전자로 한정했다.

RISCON Aja 교차검증(azure/gpt-5.4-mini)은 감사 관문과 문헌 단계를 따로 받았다. 감사 관문의 첫 판정은 수정 필요였다(`b810a271-e472-4078-8ca0-980d19fea5c6`). 지적은 두 건이다. `audit()`가 호출자가 넘긴 검증 결과를 믿어 장부 검사를 건너뛸 수 있었고, 하위 에이전트의 도구 호출 횟수를 적은 문장이 요청 수와 헷갈렸다. 앞의 것은 검증한 장부를 사본으로 보관하는 `VerifiedLedger`로 바꿨고 뒤의 것은 문장을 고쳤다. 다시 받은 판정은 통과다(`6e6def9e-df33-4de1-8555-7ac1b8fa5965`). 두 건의 비용은 합계 $0.0311이다.

문헌 단계의 첫 판정은 보류였다(`ccbdde96-a4dc-408e-9754-ee393559cbf2`). 2차 판독이 늘 걸리는지를 근거만으로 확정할 수 없다는 이유였다. 2차 판독을 필수 인자로 바꾸고 호출 지점을 모두 근거에 넣어 다시 받은 판정은 수정 필요였다(`c0e7a414-fff3-4282-b187-2d8b4cd0ad52`). 2차 판독 없이 장부에 넣는 선택 인자가 남아 있다는 지적이었다. 그 인자를 없애고 첫 검사(`check`)와 장부 진입(`admit`)을 다른 함수로 나눴다. 고친 뒤의 재검토는 받지 못했다. 14:47부터 RISCON Aja 로컬 연결 파일이 없어 네 번의 시도가 모두 실행 전에 멈췄다. 고친 내용과 이 사정을 `cross-review --accept`의 사유로 남겼다. 두 건의 비용은 합계 $0.0271이고, 문헌 소견의 2차 판독 두 건($0.0188)까지 이번 작업의 Aja 비용은 모두 $0.0770이다.

APOSTOLUS로 옮긴 작업은 따로 검토받았다. 첫 판정은 수정 필요였다(`c7cfe539-b73c-41c3-bf41-5dacd380d0c6`). 루트 README의 8,667건·480명이 근거 파일에 항목으로 없다는 지적이었고, 두 값을 `benchmark.expertClassifiedVariants`와 `benchmark.simulatedPatients`로 넣었다. 두 번째는 보류였다(`83a05f11-b5a1-4a0f-9fe0-47c44a8b47cb`). 인수인계 절에 그 총계가 없다는 이유여서 문장을 넣고, 세 문서의 숫자를 근거 파일에서 찾은 대조표를 붙였다. 세 번째 판정은 통과다(`6bfe9865-0f02-41f5-bd74-ad886f739693`). 옮긴 뒤의 전체 측정 출력은 저장본과 바이트 단위로 같고, 프로젝트 공통 검사 `./scripts/check`는 시험 265건을 포함해 통과했다.

## 범위와 다음 작업

여기서 잰 것은 공개 자료와 모의 환자에서 파이프라인이 내는 판정이다. 공고 pp.105–106이 요구하는 임상의 참여, 논문과 특허, 시작품 확보와 성능평가, 실제 검체에서 얻는 민감도와 특이도는 별도 산출물이다. 이 모듈은 2026-11-14에 HEBE 작업본의 과제 감사 폴더에서 만들어 APOSTOLUS로 옮겼다. 옮기면서 패키지 형태(`python3 -B -m acmg19.…`)로 바꿨고, 옮긴 뒤의 전체 측정 출력은 옮기기 전 저장본과 바이트 단위로 같다.

문헌 근거 단계는 붙었고, 다음 작업은 그 단계가 닿는 범위를 넓히는 일이다. 본문 조각이 있는 변이가 표본의 절반이고(공개 전문이 있는 논문만 본문이 온다), 유전형을 나열한 표 조각은 필요한 표현이 없어 차단되며, 변이당 논문을 12편으로 묶었고, 기능 실험 강도를 지지 수준으로 고정했다. 순서대로 하면 표 조각의 머리글을 함께 읽기, 논문 수 상한 올리기, 전문가 패널이 검증한 실험법 목록으로 강도 올리기, 환자 수 기준(PS4)을 문헌에서 세기다. 그 밖에 gnomAD에 없는 변이의 SpliceAI 점수, 전문가 패널별 빈도 문턱, 실제 엑솜 배경에서의 음성 사례가 남아 있다.
