Skip to content

Refactor corpus I/O, parsers, and pipeline orchestration - #6

Open
apodobe wants to merge 11 commits into
mainfrom
cursor/refactor-corpus-pipeline-753f
Open

Refactor corpus I/O, parsers, and pipeline orchestration#6
apodobe wants to merge 11 commits into
mainfrom
cursor/refactor-corpus-pipeline-753f

Conversation

@apodobe

@apodobe apodobe commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

Refactoring from code-quality audit — data correctness, architecture cleanup, and CI hygiene.

Data correctness

  • Atomic JSON writes (atomic_write_text, write_json in corpus_io)
  • _append_lab_rows no longer drops duplicate keys; vendor priority in dedup_labs (medsi > gemotest > emias)
  • LOINC-first dedup grouping: (loinc:{code}|key:{canonical_key}, specimen_date)
  • Patient DOB passed explicitly through parser chain (no module global)
  • merge_labs_corpus parses each document once

Architecture

  • medbots/parsers/ — split from 1265-line monolith: common, emias, gemotest, medsi; local_structure_pdfs is ~330-line orchestrator
  • vendor_registry — unified vendor detection and entry targeting
  • pipeline/run.py — direct function calls (subprocess only for optional scripts)
  • time_util, cli_args, log_config — shared utilities

CI / quality

  • ruff + mypy in dev deps and GitHub Actions
  • Logging in pipeline orchestration (log_config)

Tests

  • 101 tests: vendor registry, dedup vendor priority, LOINC dedup, single-parse merge, existing parser fixtures

Follow-up (not blocking)

  • Analyte synonym map before LOINC assignment
  • Extend logging to validation/extract modules
  • Remove E501 per-file ignore by splitting long regex constants
Open in Web Open in Cursor 

cursoragent and others added 11 commits August 11, 2026 13:36
- Add atomic_write_text, load_json, write_json helpers in corpus_io
- Use atomic writes in write_manifest and write_labs
- Remove existing_keys skip in _append_lab_rows; always append rows
- Route dedup_labs, apply_loinc_map, merge_labs through load_labs/write_labs

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
…cture_pdfs

Remove module-level _skip_patient_dob and _configure_patient_dob.
Thread patient_dob parameter through _first_iso_date, parse helpers,
_parse_entry, and run(). run() loads DOB from corpus when not provided.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Introduce utc_now_iso() and corpus argparse helpers, then replace
duplicated inline datetime formatting and --corpus parsing across
scan/extract/pipeline modules.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Parse each lab document once and store the extracted dict in targets.
Load patient_dob once via load_patient_dob and pass to _parse_entry.
Reuse stored extraction in dry_run and write paths.

Add test_dedup_vendor_priority for medsi-over-emias vendor priority.
Add test_merge_parses_each_document_once to guard against re-parsing.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Refactor medbots/pipeline/run.py to import and invoke module functions
directly instead of spawning python -m subprocesses for merge labs,
LOINC mapping, dedup, goals/supplements/protocols extraction, discrepancies,
LHM generation, goal reconciliation, validation, and corpus index writing.

Keep subprocess only for optional legacy scripts (bridge_legacy_flat_pdfs,
reconcile_weekly_pending). Update cli.py structure and validate commands
to call local_structure_pdfs.run() and validate_corpus.main() directly.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Extract vendor detection, lab-source filtering, and structure-target
selection into medbots/vendor_registry.py. Update merge_labs_corpus and
local_structure_pdfs to use the shared helpers, and add unit tests.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Add _dedup_key() that builds grouping keys as (loinc:code|key:canonical_key,
specimen_date). Rows with the same LOINC on the same date are deduplicated
even when canonical_key differs. Vendor priority (medsi > gemotest > emias)
still applies within each group.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Add medbots/log_config.py with setup_logging() and get_logger().
Use logger.info/error in pipeline/run.py for step progress and failures.
Keep user-facing print in cli.py; route structure warnings to logger.
Use logger in dedup_labs and merge_labs_corpus main() entry points.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Configure ruff (E/F/I/UP, line-length 100) and mypy (packages medbots,
ignore_missing_imports) in pyproject.toml. Run both in GitHub Actions
before pytest. Auto-fix import order and style issues across medbots;
fix mypy narrowing in import_apple_health. Temporarily ignore_errors for
local_structure_pdfs during incremental parser split.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Extract vendor-specific parse_* functions and shared utilities into
medbots/parsers/ (common, emias, gemotest, medsi). Keep
local_structure_pdfs.py as a thin orchestrator for manifest routing,
run(), and backward-compatible re-exports for tests.

Pure refactor with no behavior changes; all 100 tests pass.

Co-authored-by: apodobe <apodobe@users.noreply.github.com>
Co-authored-by: apodobe <apodobe@users.noreply.github.com>
@apodobe
apodobe marked this pull request as ready for review August 11, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants