# DKDPulse — Diabetic Kidney Disease Daily Research Curator

> **Disclaimer / 면책 고지**
> 본 도구는 연구·교육 목적의 참고용이며, 임상 의사결정 근거로 사용할 수 없습니다.
> This tool is for research and educational reference only. Do not use it as a basis for clinical decisions.

## 목적 (Purpose)

PubMed + ClinicalTrials.gov + medRxiv를 매일 정해진 DKD(Diabetic Kidney Disease, 당뇨병성 신증) 키워드와 4개 약물 클래스로 incremental 수집한 뒤, **약물 × outcome × phenotype 3차원 태깅**과 **novelty score ranking**을 거쳐 일간 digest(HTML / Markdown)를 만든다.

- **Domain**: 당뇨병성 신증 (DKD)
- **Category**: 연구 알림 (PubMed / ClinicalTrials.gov / preprint 큐레이션)
- **Entry point**: Python CLI — `main.py`

## 핵심 기능 (Features)

1. **PubMed E-utilities 일간 incremental fetch** — DKD 정의 쿼리 (`"diabetic kidney disease"` OR `"diabetic nephropathy"` OR `DKD`) AND 4개 약물 클래스(SGLT2i / MRA / GLP-1RA / dual-GIP-GLP1).
2. **ClinicalTrials.gov v2 status diff** — 동일 조건의 trial status change 모니터링.
3. **medRxiv preprint 일간 추가**.
4. **3차원 자동 태깅** — 약물(4) × outcome(eGFR slope, UACR, MAKE, hypoglycemia, hyperkalemia, all-cause death = 6) × phenotype(macroalbuminuric, normoalbuminuric, T1DM-DKD, T2DM-DKD, advanced CKD eGFR<30 = 5). 키워드 매칭 + 정규식만 사용. **외부 모델 사용 금지**.
5. **Novelty score** = `(1 + guideline boost) × citation_velocity_proxy(JIF / days) × coverage_bonus × source_weight`, seen-PMID는 마스킹되어 0점 처리. 상위 N개 항목을 약물 클래스별 섹션으로 묶어 HTML / Markdown digest 생성.

## 제약 (Constraints)

- **외부 네트워크 호출 금지** — 모든 라이브 fetcher는 `NotImplementedError`로 막혀 있다. 기본 동작은 `--offline` 모드의 합성 mock data.
- **표준 라이브러리만 사용** — `json`, `csv`, `datetime`, `pathlib`, `argparse`, `html`, `re` 만으로 동작. `pip install` 불필요.
- 24시간 범위 확장 금지.
- mock data의 PMID / NCT ID / DOI는 모두 가상 (`MOCK_PM_*`, `NCT_MOCK_*`, `10.5555/mock.*`).

## 디렉터리 구조 (Layout)

```
2026-04-26-1-dkd-pulse/
├── README.md
├── main.py                     # CLI 진입점
├── dkdpulse/
│   ├── __init__.py
│   ├── vocab.py                # 약물·outcome·phenotype 사전
│   ├── classifier.py           # 3D 키워드 태거
│   ├── novelty.py              # novelty score
│   ├── digest.py               # HTML / Markdown 빌더
│   └── fetchers.py             # offline-first PubMed / CTG / medRxiv 스텁
├── data/
│   ├── mock_pubmed_2026-04-26.json
│   ├── mock_ctg_2026-04-26.json
│   ├── mock_medrxiv_2026-04-26.json
│   └── seen_pmids.json
├── output/                     # digest 생성 결과
└── QA.md                       # 검수 로그
```

## 실행 (Run)

```bash
# 도움말
python3 main.py --help

# Markdown digest (top 10, 오늘 날짜 mock data)
python3 main.py --offline --top 10 --format md --since 2026-04-26

# HTML digest
python3 main.py --offline --top 10 --format html --since 2026-04-26

# seen_pmids.json 갱신 없이
python3 main.py --offline --top 10 --format md --since 2026-04-26 --no-update-seen
```

생성된 digest는 `output/dkdpulse_digest_<YYYY-MM-DD>.{md,html}` 에 저장된다.

## 검수 체크리스트 (QA Checklist)

QA 결과는 `QA.md` 참고.

1. `python3 -c "import ast; ast.parse(open('main.py').read())"` → 구문 OK
2. 모든 `.py` 파일 ast.parse 통과
3. `python3 main.py --help` → usage 출력
4. `python3 main.py --offline --top 10 --format md --since 2026-04-26` → Markdown digest 생성, exit 0
5. `python3 main.py --offline --top 10 --format html --since 2026-04-26` → HTML digest 생성, `<html>`/`<body>`/`<table>` 포함
6. `data/*.json` 모두 `json.load` 성공
7. 디스클레이머가 README와 digest 출력에 모두 포함됨

## 출처 (Source endpoints — documented, not called)

- **PubMed E-utilities**: `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi`, `efetch.fcgi`
- **ClinicalTrials.gov v2**: `https://clinicaltrials.gov/api/v2/studies`
- **medRxiv API**: `https://api.medrxiv.org/details/medrxiv`

위 endpoint는 `dkdpulse/fetchers.py`에 상수로 명시되어 있으며, MVP 빌드는 호출하지 않는다.

## 향후 확장 (Future enhancements — not in MVP)

- scispaCy / `en_core_sci_md` 또는 transformer 기반 NER로 키워드 매칭 보강
- KDIGO / KDA / ADA 가이드라인 본문 임베딩 후 semantic novelty boost
- 실제 PubMed / CTG / medRxiv API 연동 (rate-limit + retry)
- 사용자별 알림 채널 (이메일, Slack)

## 라이선스 / 사용 제한

- 본 코드는 연구자 개인 사용 목적의 합성 데이터 시연 빌드.
- 임상 사용 절대 금지.
