# QA Log — CirrDecompUnit-Kor

**Date:** 2026-05-27
**Status:** PASS

## 1. Python syntax check (ast.parse)
| file | result |
|---|---|
| `main.py` | OK |
| `app.py` | OK |
| `modules/__init__.py` | OK |
| `modules/scoring.py` | OK |
| `modules/aclf.py` | OK |
| `modules/protocols.py` | OK |
| `modules/lt_candidacy.py` | OK |
| `modules/ingest.py` | OK |
| `modules/kpi_report.py` | OK |

Command:
```bash
for f in main.py app.py modules/*.py; do
  python3 -c "import ast; ast.parse(open('$f').read())" && echo "OK: $f"
done
```

## 2. CLI smoke tests (Python stdlib only for help/gen/summary/episode)
| command | result |
|---|---|
| `python3 main.py --help` | PASS — usage printed |
| `python3 main.py --gen --n 380` | PASS — 380 patients / 546 episodes / 3210 lab rows |
| `python3 main.py --summary --top 5` | PASS — 한국어 KPI 리포트 + 부합률 ward 랭킹 |
| `python3 main.py --episode E00010` | PASS — JSON detail printed |
| `python3 main.py --report` | PASS — docx (python-docx) + JSON written |

Note: `--gen`, `--summary`, `--report`, `--episode` all use Python standard library only. The Streamlit dashboard (`app.py`) requires installing `requirements.txt` in a virtualenv.

## 3. Data loading
All 6 CSV files load correctly with `csv.DictReader`:
- `patients.csv` (380 rows × 8 cols)
- `episodes.csv` (546 rows × 34 cols)
- `lab_trajectory.csv` (3210 rows × 8 cols)
- `protocol_adherence.csv` (546 rows × 4 cols)
- `lt_waitlist.csv` (546 rows × 12 cols)
- `outcomes.csv` (546 rows × 14 cols)

## 4. Module smoke test
End-to-end scoring chain verified:
- MELD 3.0 (bili=2, INR=1.5, creat=1.2, Na=132, alb=2.8, F) → 20.5
- Child-Pugh (bili=2, alb=2.8, INR=1.5, mild ascites, HE I) → 9 / class B
- CLIF-SOFA (bili=15, creat=4, INR=3, HE III, MAP 55, S/F 200) → liver=3, kidney=3, coag=3, brain=3, circ=3, resp=3 (total 18)
- ACLF grade for above → ACLF-3 (6 organ failures)
- LT candidate (MELD 3.0=28, Child-C, ACLF-2) → eligible, high urgency, KONOS Band A

## 5. Clinical realism check (synthetic data)
EASL-CLIF ACLF grade distribution after generation:
- no ACLF: 382 (30d mortality 6%)
- ACLF-1: 75 (28%)
- ACLF-2: 45 (42%)
- ACLF-3: 44 (82%)

Mortality gradient matches CANONIC (Moreau 2013) — confirms scoring rules calibrated correctly.

Etiology mix (MASLD-heavy, Korean cohort): MASLD 225 / HBV 127 / alcohol 99 / HCV 53 / autoimmune 27 / overlap 18 / other 9 (after most recent generation seed).

## 6. Safety / compliance checks
- PHI columns (name/RRN/MRN/phone/address/SSN) are auto-dropped at ingest (`modules/ingest.py::deidentify`).
- All synthetic data — no real patient information.
- 디스클레이머 present in README.md, app.py (caption + divider), `main.py --help` description, and every generated report.

## 7. Known limitations
- KM / Cox survival curves are not rendered (lifelines not used in this MVP path; counts and Kaplan-Meier-style aggregates are presented as period rates rather than curves to keep the MVP fully runnable on stdlib for --summary/--report).
- The Streamlit dashboard requires `pip install -r requirements.txt`. The CLI does not.
- "PDF" reports are produced as `.docx` (python-docx). A separate PDF export can be added via LibreOffice headless or reportlab in a follow-up.
- `--top` only works when paired with `--summary`.

## 8. Retry log
- Attempt 1: ACLF distribution was too lopsided (only 8 ACLF-1, 0 ACLF-2/3). Root cause: synthetic lab severity too mild for ACLF/HRS-AKI episodes.
- Attempt 2: Increased severity (bili/INR/creat) for ACLF and HRS-AKI episodes, set HE grade ≥II for ACLF, and tightened CLIF-SOFA organ-failure thresholds to match Moreau 2013 (liver≥12, kidney≥3.5, INR≥2.5, HE≥III, MAP<60). Result: realistic distribution (no/ACLF-1/2/3 = 382/75/45/44 with mortality 6/28/42/82%).

## Final verdict
PASS — all required checks succeed. MVP is runnable end-to-end with `python3 main.py --gen --summary --report` using only the Python standard library; Streamlit dashboard requires the pinned `requirements.txt`.
