Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
232 commits
Select commit Hold shift + click to select a range
bdab0e3
Add migration strategy and technical documentation
pmayd Oct 19, 2025
4e06793
Initialize Python project structure (Phase 0)
pmayd Oct 19, 2025
5be3f78
Add GitHub Actions CI with Astral toolchain
pmayd Oct 19, 2025
de25d6d
Consolidate migration documentation
pmayd Oct 19, 2025
611dcd4
Add root CLAUDE.md as navigation hub
pmayd Oct 19, 2025
7c45b79
update pyproject.toml and add proper dev group
pmayd Oct 20, 2025
7f641fb
Add justfile and update README with development commands
pmayd Oct 20, 2025
c35a072
Implement column synonyms mapper for data extraction
pmayd Oct 20, 2025
98e0419
Add shared utilities and province validation with case-insensitive ma…
pmayd Oct 20, 2025
361a898
Refactor: Reorganize into reference/ package for better structure
pmayd Oct 20, 2025
469c738
add examples to modules, fix docxtring indent
pmayd Oct 20, 2025
77af9df
Optimize patient extraction with single-pass read-only loading
pmayd Oct 22, 2025
05d24aa
update tests
pmayd Oct 22, 2025
3b06496
1. Patient Data Extraction Module (src/a4d/extract/patient.py)
pmayd Oct 23, 2025
a7f1a88
further updates in the migration; step 2
pmayd Oct 25, 2025
ca3cad6
fix error in R pipeline with some 2024 trackers not correctly parsing…
pmayd Oct 25, 2025
0b0a376
add tqdm
pmayd Oct 27, 2025
061748a
next improvements
pmayd Oct 27, 2025
1b944ca
add log table summary to cli
pmayd Nov 4, 2025
02ffd36
Fix age calculation to match R pipeline behavior
pmayd Nov 4, 2025
cdd4be8
Add date validation and FBG text conversion to patient cleaning
pmayd Nov 4, 2025
ff5d755
remove old scripts
pmayd Nov 6, 2025
1617013
Implement flexible date parsing for legacy tracker formats
pmayd Nov 6, 2025
911f6e5
Simplify comparison script to use fixed base paths
pmayd Nov 6, 2025
8e6c91f
Fix date parser to handle month-year without separator
pmayd Nov 6, 2025
1d963da
Update VALIDATION_TRACKING: mark 2018 tracker as validated
pmayd Nov 6, 2025
ce4caf3
Fix extraction and cleaning bugs for 2021 Phattalung Hospital tracker
pmayd Nov 8, 2025
b62047d
Fix extraction to handle rows with missing row numbers
pmayd Nov 8, 2025
b0f4f37
Update validation tracking: 2022 Surat Thani Hospital fixed
pmayd Nov 8, 2025
d121f76
Fix extraction bugs: handle None max_row and filter Excel errors
pmayd Nov 9, 2025
3f1ba18
Update validation tracking: 2024 Sultanah Bahiyah fixed
pmayd Nov 9, 2025
426cae4
Add patient_id normalization for transfer patients
pmayd Nov 9, 2025
2355603
Add unit tests for patient cleaning preprocessing functions
pmayd Nov 9, 2025
989715b
Fix extraction to filter numeric zero patient IDs (0, 0.0)
pmayd Nov 9, 2025
0ba9d6e
Update validation tracking: investigation complete
pmayd Nov 9, 2025
228ebfc
Add comprehensive R vs Python validation test suite
pmayd Nov 10, 2025
f763c7b
Refactor R validation tests and fix HbA1c exceeds default value
pmayd Nov 11, 2025
0475663
Add patient-level exceptions for R extraction errors
pmayd Nov 11, 2025
c696630
Add file-specific column exceptions and identify R Unicode bug
pmayd Nov 11, 2025
2ed8ee0
Clarify Unicode character handling difference between R and Python
pmayd Nov 11, 2025
218886b
Treat null and empty string as equivalent in R vs Python validation
pmayd Nov 11, 2025
a9a74db
Add exceptions for Kantha Bopha II Hospital tracker R extraction errors
pmayd Nov 12, 2025
f2e8d4e
Implement province validation in Python to match R behavior
pmayd Nov 12, 2025
c727c32
Remove Kantha Bopha II province validation exception
pmayd Nov 12, 2025
63d9f38
Revert: Keep province exception - R validation is still broken
pmayd Nov 12, 2025
71b86c1
Implement sex synonym mapping to match R behavior
pmayd Nov 12, 2025
68b48b1
Implement BMI calculation to match R pipeline
pmayd Nov 12, 2025
55ad1ca
Complete migration of R data transformation functions
pmayd Nov 12, 2025
0eccaf9
Fix extract tests to use numeric values in column A
pmayd Nov 12, 2025
42f4abb
update exceptions for end to end tests
pmayd Nov 13, 2025
dc91f18
add a delete parameter to ingest_Data
pmayd Nov 14, 2025
5ec67b8
Add exception for 2017 Mandalay tracker missing status values
pmayd Nov 14, 2025
7ed5e36
Add exception for 2019 CDA tracker missing status value
pmayd Nov 15, 2025
97d34de
Update required column test to alert when exceptions are fixed
pmayd Nov 15, 2025
d88ef45
Add exception for 2019 Preah Kossamak tracker missing status
pmayd Nov 15, 2025
870c505
Add exception for 2019 Vietnam National Children's Hospital tracker
pmayd Nov 15, 2025
622d500
Fix header merge bug causing status column loss in 2021 Kantha Bopha …
pmayd Nov 15, 2025
87a7169
new limits for fbg, hba1c, bmi, age
pmayd Nov 15, 2025
c96611b
Fix validation error for rows with missing patient_id
pmayd Nov 15, 2025
9c3f236
Improve worker log file naming with timestamp and PID
pmayd Nov 15, 2025
52283fd
Fix patient_id normalization to handle hyphens before removing transf…
pmayd Nov 16, 2025
1948d13
Add exception for missing status in 2021 Mandalay tracker
pmayd Nov 16, 2025
dbb94a4
Add exception for missing status in 2021 Preah Kossamak tracker
pmayd Nov 16, 2025
52fa688
Add exceptions for missing status in 2022 Chiang Mai tracker
pmayd Nov 16, 2025
3fe851a
Add exception for missing status in 2022 Chulalongkorn tracker
pmayd Nov 16, 2025
6d43474
Add exception for missing status in 2022 Kantha Bopha tracker
pmayd Nov 16, 2025
60147ca
Add exception for missing status in 2022 Likas tracker
pmayd Nov 16, 2025
c4975ce
Add exception for missing status in 2022 Mandalay tracker
pmayd Nov 16, 2025
f38d5b5
Add exception for missing status in 2022 Penang tracker
pmayd Nov 16, 2025
118c580
Add exception for missing status in 2022 Putrajaya DC tracker
pmayd Nov 16, 2025
a47cdc1
Add exception for missing status in 2022 Sarawak DC tracker
pmayd Nov 16, 2025
e28c695
Add exception for missing status in 2022 Surat Thani tracker
pmayd Nov 16, 2025
e5e050b
Add exception for missing status in 2022 Udon Thani tracker
pmayd Nov 16, 2025
6371894
Add exception for missing status in 2023 Mahosot tracker
pmayd Nov 16, 2025
43d84d8
Add exception for missing status in 2023 Nakornping tracker
pmayd Nov 16, 2025
59507bb
Add exception for missing status in 2023 Surat Thani tracker
pmayd Nov 16, 2025
7cc0764
format
pmayd Dec 8, 2025
5f1fc33
exception for status in 2024_Likas Women & Children's Hospital A4D Tr…
pmayd Dec 8, 2025
32fbcad
exception for status in 2024_Yangon General Hospital A4D Tracker
pmayd Dec 8, 2025
20c90c6
add vscode settings
pmayd Dec 8, 2025
489a3b4
remove -m option from addopts to not exclude tests from test explorer…
pmayd Dec 8, 2025
f391249
ruff check
pmayd Dec 9, 2025
a9ce967
fix header merge forward-fill for group headers like observations_cat…
Dec 27, 2025
4b1c6ab
use Excel merge metadata for header forward-fill instead of heuristics
Dec 27, 2025
0cffe77
fix openpyxl warning filter to match submodules
Dec 27, 2025
7c91db1
perf: replace Excel merge metadata with synonym validation (6.6x faster)
Dec 27, 2025
424f9e7
fix: convert height from cm to m before BMI calculation
Dec 27, 2025
a812ecc
fix: date parsing truncated dd-Mon-yyyy format (11 chars) to 10
Dec 28, 2025
58700fd
test: add R extraction error exceptions for Mandalay trackers
Dec 28, 2025
7018884
test: add R extraction error exception for NPH tracker
Dec 28, 2025
1a8c7b8
fix: calculate age/t1d_diagnosis_age from DOB, handle Excel errors
Dec 28, 2025
a5b9948
Initial plan
Copilot Feb 20, 2026
1b7998d
feat: add BigQuery loading and GCS integration modules
Copilot Feb 20, 2026
b2ccea1
refactor: address code review feedback
Copilot Feb 20, 2026
ac2fa23
Fix all 63 ruff linting errors in a4d-python
Copilot Feb 20, 2026
7e06dbc
Merge pull request #3 from CorrelAid/copilot/plan-data-migration-steps
pmayd Feb 24, 2026
580b186
Initial plan
Copilot Feb 24, 2026
4eac0a8
Add Dockerfile, .dockerignore, deploy.sh, and cloud-run config for se…
Copilot Feb 24, 2026
b57b483
Deploy Python pipeline as Cloud Run Job: fix Dockerfile, add run-pipe…
Copilot Feb 24, 2026
c488a8c
Fix PR diff: sync migration branch files, leaving only the 4 new depl…
Copilot Feb 24, 2026
f3910a2
Merge branch 'migration' of https://github.com/CorrelAid/a4d into cop…
Copilot Feb 25, 2026
e6241f8
Upgrade Python from 3.11 to 3.13 in Dockerfile and CI workflow
Copilot Feb 25, 2026
ac1181f
Remove unused duckdb dependency and upgrade to Python 3.14
Copilot Feb 25, 2026
ef6a1b9
Merge pull request #4 from CorrelAid/copilot/setup-serverless-pipeline
pmayd Feb 25, 2026
38595b4
Initial plan
Copilot Feb 25, 2026
f5db33c
Fix patient pipeline: stale column names, Python version, product ing…
Copilot Feb 25, 2026
72c7be9
Remove longitudinal data table creation and all related code
Copilot Feb 25, 2026
8d188e6
Merge pull request #5 from CorrelAid/copilot/finalize-patient-data-mi…
pmayd Feb 25, 2026
7fb63fa
Finalize patient pipeline: fix bugs, remove stale code, add CLI tests
Feb 25, 2026
cccaea8
format code
Feb 26, 2026
0a7c3c5
Add clean output, CLI step output, and setup guide
Feb 26, 2026
7f88230
rename just commands, fix error in tests, fix max_workers not working…
Feb 26, 2026
b0085ce
Improve CLI UX, GCS performance, and GCP setup
Feb 27, 2026
a119270
Add backup-bq and fix logs-job in justfile
Feb 28, 2026
945d230
Audit and update docs: remove obsolete files, update to reflect curre…
Mar 1, 2026
fc5973f
Move all GCP resources to asia-southeast2 (Jakarta) for data residency
Mar 1, 2026
aa70d9e
Fix uv not found in Docker and update justfile region to Jakarta
Mar 1, 2026
767b433
Fix Docker build: add UV_PYTHON_DOWNLOADS and copy README.md
Mar 1, 2026
2012fe6
Fix Docker build: split uv sync to avoid editable install before src/…
Mar 1, 2026
6b22d19
Add gcloud command to list images in Artifact Registry after docker-push
Mar 1, 2026
81b77bf
Add local Docker test instructions and docker-smoke just command
Mar 1, 2026
dce1dd7
Add --provenance=false to docker-build to suppress attestation manifests
Mar 1, 2026
92f9ac6
Add git-SHA tagging strategy and rollback command to justfile
Mar 1, 2026
40293dc
Add docker-list command to justfile
Mar 1, 2026
7236446
Reorder and group justfile into logical sections
Mar 1, 2026
9e8089d
Fix E402: move warnings.filterwarnings after imports in cli.py
Mar 1, 2026
f96d4e0
Fix ty type errors: PolarsDataType annotation and tqdm isinstance check
Mar 1, 2026
657e3f6
Update Cloud Run Job spec: bump to 8 vCPU / 8 GiB, add jobs list command
Mar 1, 2026
80ee1e3
Code cleanup: remove unused imports, fix forward reference, reformat
Mar 1, 2026
3a6faae
Add --platform=linux/amd64 to docker-build for Cloud Run compatibility
Mar 1, 2026
8824cc3
Fix CI test failures by excluding slow and integration tests
Mar 1, 2026
b2c91a6
Fix reference_data path resolution in Docker/Cloud Run
Mar 1, 2026
bfa8c85
Switch parallel processing from ProcessPoolExecutor to ThreadPoolExec…
Mar 1, 2026
fb078ff
Update SETUP.md: fix BigQuery IAM grant command
Mar 1, 2026
113890f
Restore clean console output for parallel pipeline runs
Mar 1, 2026
c306479
Revert to ProcessPoolExecutor; add docker-clean command
Mar 1, 2026
38efab6
Fix GCS upload: timestamped prefix, upload only tables and logs
Mar 1, 2026
5560b38
Fix BigQuery loading: delete-before-recreate and update logs clustering
Mar 1, 2026
c18fb70
Add clinic_data_static table creation
Mar 1, 2026
7e345dd
Add error_code classification to pipeline logs
Mar 1, 2026
f4fb7b5
Fix CLI test runner for CI environment
Mar 1, 2026
a99473a
add new command to see resources of cloud job; add script dependencies
Mar 13, 2026
24125ae
Promote Python pipeline to root; archive R code
Mar 13, 2026
76631d4
Update clinic_data.xlsx from Google Drive
Mar 13, 2026
8f4b8bc
docs: add product data pipeline feature proposal
Mar 29, 2026
2069a4d
Persist data quality errors to table_errors.parquet and BigQuery
Apr 1, 2026
faa3c28
add new error log table combining all errors in a single parquet file…
Apr 1, 2026
56f2192
refactor(patient): extract shared tracker helpers
Ali88-hub May 4, 2026
b810120
feat(patient): typo-rescue + multi-insulin CSV
Ali88-hub May 4, 2026
9608bca
feat(clean): shared utilities + product extraction layer
Ali88-hub May 4, 2026
1151155
feat(product): cleaning pipeline + table aggregation
Ali88-hub May 4, 2026
fdc8c8c
feat(state): incremental processing via tracker_metadata
Ali88-hub May 4, 2026
85891e7
feat(pipeline): product orchestration + CLI integration
Ali88-hub May 4, 2026
c485bc2
feat(validate): source-vs-output reconciliation
Ali88-hub May 4, 2026
9e95796
refactor(bigquery): drop pandas from tracker_metadata read
Ali88-hub May 5, 2026
27cfe26
chore: drop redundant utf-8 encoding and Windows path shims
Ali88-hub May 5, 2026
9a30cc9
chore(justfile): drop Windows compatibility shims
Ali88-hub May 5, 2026
3070ea6
feat(cli): --skip-patient flag for run-pipeline
Ali88-hub May 7, 2026
b9a67ac
feat(product): propagate clinic_id from tracker folder to product output
Ali88-hub May 7, 2026
2daae89
docs(readme): align with dual patient + product pipeline
Ali88-hub May 7, 2026
523a2d6
fix(product): null end-of-block residue in product_entry_date
Ali88-hub May 10, 2026
e2f25fa
chore: fix readme casing
Ali88-hub May 28, 2026
840daa3
docs(product): bump schema column count 19 -> 20
Ali88-hub May 28, 2026
b309fcb
feat(reference): add 226 product->category mappings to Stock_Summary
Ali88-hub May 28, 2026
7b60b16
docs(migration): add dashboard evaluation and product parity reports
Ali88-hub May 29, 2026
f917703
Chart wayfinder map for closing out the R-to-Python migration
Aug 8, 2026
1b43e92
Record execution-override and daily-routine notes on the wayfinder map
Aug 8, 2026
c425988
Clarify cloud routine has no GCP creds or real tracker data
Aug 8, 2026
6b9a095
Bring product pytest suite to parity with patient (ticket 8)
Aug 8, 2026
2322166
Merge migration into product-pipeline, resolve conflicts
Aug 8, 2026
f90eaa6
Fix repo-wide ruff violations blocking PR CI
Aug 8, 2026
acb748e
Fix the 2 remaining ty diagnostics blocking CI
Aug 8, 2026
b970cf6
Fix CI: disable Typer's forced terminal styling in tests
Aug 9, 2026
7713fea
Merge pull request #6 from CorrelAid/product-pipeline
pmayd Aug 9, 2026
7417faf
Close wayfinder ticket 7: pipeline completeness audit
Aug 8, 2026
530470c
Close wayfinder ticket 8: pytest-suite parity decision
Aug 8, 2026
18c1e8b
Record PDF contents on wayfinder ticket 2
Aug 8, 2026
aabc472
Resequence wayfinder ticket 2 to after the merge, not before
Aug 8, 2026
87bebda
Close wayfinder ticket 3: PR #6 conflicts resolved, mergeable
Aug 8, 2026
4c26084
Close wayfinder ticket 4: CI fixed via Typer force-terminal escape hatch
Aug 9, 2026
9a343bb
Record PR #6 merged into migration on wayfinder map
Aug 9, 2026
29e2286
Add production-run verification script comparing live tables to backu…
Aug 9, 2026
b304068
Fix verify_production_run.py crashing on tables without clinic_id
Aug 9, 2026
7e38fb2
Close wayfinder ticket 5: real GCP production run executed and verified
Aug 9, 2026
50e55dd
Redraw wayfinder destination to include rollout readiness
Aug 9, 2026
c31660d
Add wayfinder tickets 12 and 13: retire R, audit dependencies before …
Aug 9, 2026
cd5d7e9
Remove tools/LogViewerA4D (R Shiny log viewer), out of ticket-12 sequ…
Aug 9, 2026
c4721ad
Audit and update dependencies before rollout (ticket 13)
Aug 9, 2026
9a36dfd
Close ticket 13 on the wayfinder map, unblocking ticket 10
Aug 9, 2026
97479f8
Fix O(n^2) find_data_start_row on read-only worksheets (ticket 10)
Aug 9, 2026
da8b590
Close ticket 10 (performance profiling), spawn ticket 14 (product bug)
Aug 9, 2026
1242dc4
Fix product cleaning crash on pre-product-tracking tracker years (tic…
Aug 9, 2026
9eeb12d
Close ticket 2 (comparison-doc strategy), spawn ticket 15 to build/ru…
Aug 9, 2026
33694b4
Add combined patient+product run summary; soft-fail patient arm
Aug 9, 2026
6de3551
Close ticket 11 (combined run summary), spawn ticket 16 (log-analyzer…
Aug 9, 2026
0e05590
Restructure CLI into process-first command groups (run/create/upload/…
Aug 9, 2026
daf0a61
Rename download trackers --destination to --data-root for consistency
Aug 9, 2026
2958f06
Fix product-patient link validation joining against the wrong patient…
Aug 9, 2026
5c762b6
Condense product table-stage error logging; add dataset overview and …
Aug 9, 2026
05a4eb3
Give run product parity with run patient's console output; drop per-f…
Aug 9, 2026
296fa86
Build R/Python output comparison script; find product row-alignment b…
Aug 11, 2026
3f5ebde
Fix compare-outputs just recipe quoting; add a legend explaining each…
Aug 11, 2026
512c6a1
Add ID/categorical overlap checks, raw-stage comparison, year grouping
Aug 11, 2026
ac4090e
Add Excel detail export, --only-mismatches flag; rename overlap to di…
Aug 11, 2026
9fd16bb
Drop HTML output; add row-key divergence check; consistent naming
Aug 11, 2026
a96ffc4
Add row_key_overlap sheet to the Excel export
Aug 11, 2026
6307be8
Update wayfinder map with tool-hardening work done after ticket 15 cl…
Aug 11, 2026
bcfc32e
Fix product row-alignment key with ordinal position, not equi-join
Aug 11, 2026
cc2ef67
Close ticket 17 (product row-alignment key fix), spawn ticket 18 for …
Aug 11, 2026
7c90645
Add run-over-run history/deltas to the R/Python comparison script
Aug 11, 2026
5d62865
Give compare_outputs.py a per-run output directory, clean up scripts/
Aug 11, 2026
d9a8357
Update wayfinder map for compare_outputs.py's per-run-folder refinement
Aug 11, 2026
655369f
Close ticket 18: root-cause product_category/entry_date mismatches, s…
Aug 11, 2026
9279386
remove deprecated files
Aug 11, 2026
7804b8f
Close ticket 20: normalize raw-stage product_entry_date representation
Aug 11, 2026
dfa6b55
Fold ticket 20's residual entry_date mismatches into ticket 22
Aug 11, 2026
1027218
Close ticket 22: fix blank-row extraction bug, normalize float/whites…
Aug 12, 2026
d9022ef
Close ticket 21: root-cause remaining product cleaned-stage mismatches
Aug 12, 2026
ed572ad
Silence loguru DEBUG spam in compare_outputs.py
Aug 12, 2026
23e7204
Spawn ticket 26: compare_columns' Column divergence was never triaged
Aug 12, 2026
90c6275
Close ticket 23: patient raw-stage mismatches are the ticket-20 date …
Aug 12, 2026
4eb6a40
new clinic data
Aug 12, 2026
3607ffe
Fix t1d_diagnosis_age bug, classify two more patient cleaned-stage di…
Aug 12, 2026
42562f0
Triage product/patient column-existence and dtype divergence (ticket 26)
Aug 12, 2026
28c5082
Close ticket 24: triage residual raw-stage units_received/released/re…
Aug 12, 2026
dc074e9
Close ticket 27: normalize patient raw-stage numeric/date columns, cl…
Aug 12, 2026
bd341ba
Preserve source Excel formula errors through extraction, null and log…
Aug 12, 2026
a042194
Set triage decision bar, add comparison totals rollup, silence date-p…
Aug 12, 2026
d41916a
Ticket 33: diagnose red CI on migration (ruff format on markdown snip…
Aug 12, 2026
62445e2
Close ticket 33: exclude docs/migration from ruff, restoring green CI
Aug 12, 2026
c185f71
Remove accidentally committed coverage.xml, gitignore it
Aug 12, 2026
91f8571
Ticket 35: surface the 17 Polars 2.0 deprecation warnings
Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 10 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.git
.github
r-archive/
.pytest_cache
.ruff_cache
htmlcov
.coverage
profiling/*.prof
data/
secrets/
26 changes: 26 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Environment Configuration
A4D_ENVIRONMENT=development

# GCP Configuration
A4D_PROJECT_ID=a4dphase2
A4D_DATASET=tracker
A4D_DOWNLOAD_BUCKET=a4dphase2_upload
A4D_UPLOAD_BUCKET=a4dphase2_output

# GCP Authentication
# Use the a4d-pipeline service account key for local development — this gives identical
# auth to Cloud Run and is required for Drive API access (user ADC blocks Drive scope).
# Store the key in secrets/ (gitignored). In Cloud Run, the SA authenticates via metadata server.
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/a4d-pipeline-key.json

# Paths
A4D_DATA_ROOT=/path/to/tracker/files
A4D_OUTPUT_DIR=output

# Processing Settings
A4D_MAX_WORKERS=4

# Error Values (matching R pipeline)
A4D_ERROR_VAL_NUMERIC=999999
A4D_ERROR_VAL_CHARACTER=Undefined
A4D_ERROR_VAL_DATE=9999-12-31
57 changes: 57 additions & 0 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Python CI

on:
push:
branches: [migration]
paths:
- 'src/**'
- 'tests/**'
- 'pyproject.toml'
- '.github/workflows/python-ci.yml'
pull_request:
branches: [main, develop, migration]
paths:
- 'src/**'
- 'tests/**'
- 'pyproject.toml'
- '.github/workflows/python-ci.yml'

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v2
with:
enable-cache: true

- name: Set up Python
run: uv python install 3.14

- name: Install dependencies
run: uv sync --all-extras

- name: Run ruff linting
run: uv run ruff check .

- name: Run ruff formatting check
run: uv run ruff format --check .

- name: Run type checking with ty
run: uv run ty check src/

- name: Run tests
run: uv run pytest -m "not slow and not integration" --cov --cov-report=xml

- name: Enforce coverage floor for product pipeline code
run: |
uv run coverage report --include="src/a4d/extract/product.py,src/a4d/clean/product.py,src/a4d/clean/schema_product.py,src/a4d/extract/wide_format.py,src/a4d/pipeline/product.py,src/a4d/tables/product.py,src/a4d/validate/source_vs_output_product.py" --fail-under=85

- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
flags: python
56 changes: 0 additions & 56 deletions .github/workflows/test-coverage.yaml

This file was deleted.

89 changes: 78 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,80 @@
.Rproj.user
.Rhistory
.RData
.Ruserdata
.Rhistory
.Rdata
.httr-oauth
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual environments
.venv/
venv/
ENV/
env/

# uv
.uv/

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/

# Type checking
.mypy_cache/
.dmypy.json
dmypy.json

# IDEs
.vscode/
.idea/
*.swp
*.swo
*~

# Environment
.env
.env.local

# Logs
*.log
logs/

# Data (sensitive)
data/
output/
*.parquet
*.xlsx
!reference_data/
compare_report*.html

# OS
.DS_Store
.Renviron
rsconnect
Thumbs.db

data/output
data/mapping_table.csv
# Serena (MCP server state)
.serena/

# Secrets (GCP service accounts, etc.)
secrets/
.opencode
.Rproj.user
CLAUDE.local.md
.Rhistory
r-archive/config.yml
coverage.xml
29 changes: 29 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.cwd": "${workspaceFolder}/a4d-python",
"python.testing.pytestArgs": [
"${workspaceFolder}/a4d-python/tests"
],
"python.defaultInterpreterPath": "${workspaceFolder}/a4d-python/.venv/bin/python",
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#ab307e",
"activityBar.background": "#ab307e",
"activityBar.foreground": "#e7e7e7",
"activityBar.inactiveForeground": "#e7e7e799",
"activityBarBadge.background": "#25320e",
"activityBarBadge.foreground": "#e7e7e7",
"commandCenter.border": "#e7e7e799",
"sash.hoverBorder": "#ab307e",
"statusBar.background": "#832561",
"statusBar.foreground": "#e7e7e7",
"statusBarItem.hoverBackground": "#ab307e",
"statusBarItem.remoteBackground": "#832561",
"statusBarItem.remoteForeground": "#e7e7e7",
"titleBar.activeBackground": "#832561",
"titleBar.activeForeground": "#e7e7e7",
"titleBar.inactiveBackground": "#83256199",
"titleBar.inactiveForeground": "#e7e7e799"
},
"peacock.color": "#832561"
}
39 changes: 39 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# CLAUDE.md

## Python Pipeline

**Location**: Repo root
**Branch**: `migration`

Python implementation of the A4D medical tracker data processing pipeline.

**Key Directories**:
- `src/` - Python package source
- `tests/` - Test suite
- `docs/` - Documentation (see [docs/CLAUDE.md](docs/CLAUDE.md) for detailed guidance)
- `scripts/` - Utility scripts
- `reference_data/` - Shared YAML configs (synonyms, validation rules, provinces)

**Quick Start**:
```bash
uv sync
uv run pytest
```

**Migration Guide**: [docs/migration/MIGRATION_GUIDE.md](docs/migration/MIGRATION_GUIDE.md)

## R Archive

**Location**: `r-archive/`

Legacy R implementation, preserved for reference. Do not modify.

## Shared Resources

- `reference_data/synonyms/` - Column name mappings
- `reference_data/data_cleaning.yaml` - Validation rules
- `reference_data/provinces/` - Allowed provinces

**Do not modify these** without testing the Python pipeline.
- Always check your implementation against the original R pipeline and verify the logic is the same
- Limit comments to explain why a design was made or give important context for the migration; do not use comments for obvious code
37 changes: 37 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
FROM python:3.14-slim

# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
g++ \
&& rm -rf /var/lib/apt/lists/*

# Install uv from the official image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Use the system Python from the base image; do not let uv download its own
ENV UV_PYTHON_DOWNLOADS=never

WORKDIR /app

# Install dependencies first (without the project) for better layer caching.
# --no-install-project skips the editable install of a4d itself, which requires
# src/ to be present. Dependencies rarely change so this layer stays cached.
COPY pyproject.toml uv.lock README.md ./
RUN uv sync --frozen --no-dev --no-install-project

# Copy application code and reference data
COPY src/ src/
COPY reference_data/ reference_data/

# Install the project itself now that src/ exists
RUN uv sync --frozen --no-dev

# Set environment
ENV PYTHONPATH=/app/src
ENV PYTHONUNBUFFERED=1
ENV A4D_DATA_ROOT=/workspace/data
ENV A4D_REFERENCE_DATA=/app/reference_data

# Run the full pipeline: download → process → upload to GCS → ingest into BigQuery
CMD ["uv", "run", "a4d", "run"]
Loading