All checks were successful
CI / lint (push) Successful in 44s
CI / notebooks-smoke (push) Successful in 1m33s
Deploy / changes (push) Successful in 14s
CI / test (push) Successful in 3m9s
Infra CI / zotero (push) Successful in 14s
Infra CI / notebooks (push) Successful in 55s
Infra CI / api (push) Successful in 1m9s
Infra CI / docs (push) Successful in 1m23s
Infra CI / llm (push) Successful in 1m1s
Infra CI / mc (push) Successful in 16s
Infra CI / bcda (push) Successful in 1m43s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Package Supply Chain / pkg-supply-chain (push) Successful in 1m30s
Deploy / api (push) Successful in 1m17s
Deploy / llm (push) Successful in 1m18s
Deploy / mc (push) Has been skipped
Deploy / bcda (push) Successful in 1m42s
Deploy / report (push) Successful in 1m36s
Ports the public CMS "LEAD Model PY 2027 Alignment and Financial Methodology Paper" v1.2 (bib E4PEU3HV) as generic engines: parameters come from the paper, everything CMS computes per ACO or per year comes from the caller. No participant data, no organization-specific rules. - lead.params: Table 5.2.1 discounts, 3% Quality Withhold, 2% retention incentive, Box 5.3.3 Stop-Loss bands, Tables 5.4.1/5.4.3 corridors, 2% sequestration, base-year weights, Table 3.5.1 ACPT guardrails, risk-score growth caps, REA/PSA shares and caps, voluntary guardrail and 500 minimum, Table 2.6.1 base-year alignment minimums. - lead.settlement: Final Financial Settlement, Table 5.6.1 line by line (settle(SettlementInputs) -> SettlementLines). - lead.stop_loss: Box 5.3.3 charge, banded payout, neutrality factor, application to PY expenditure. - lead.monies_owed: Table 5.5.1 Total Monies Owed, APO reconciliation. - lead.timing: run-out end, settlement-basis rule, settlement-stage inputs. - lead.benchmark: §3 formulas — risk standardization, two-/three-way trend, base-year weights and sufficiency, voluntary guardrail, regional FFS, spending designation, REA, PSA, risk-score cap, hybrid alignment dollars, category blend. - lead.express: the same as narwhals Exprs; express.settlement.settle settles a frame of scenarios on any backend. Rounding: every dollar line rounds to the cent (half away from zero) as it is produced; PBPMs, rates and factors never do. It is the only rule under which Tables 3.3.3, 3.5.3.2, 3.5.4, 5.5.1 and 5.6.1 all reproduce (3.5.4 line 24 sums cent-rounded cells; 3.3.3 carries unrounded PBPMs). The Expr cents snaps its ÷100 with round(2): polars 2.0 divides a column by a literal as a reciprocal multiply (k × 0.01), one ulp off k/100 for ~15% of values. Missing inputs stay missing (None/null or a refused input model); the only zeros are the paper's own (Professional "N/A" discount, no Stop-Loss election, sequestration on losses, ineligible REA/PSA). Paper inconsistencies recorded in tests: Table 5.5.1 line 2 is a cent below Table 5.6.1 line 28 (.43 vs .44); Box 3.3.2 prints 1.104 then says 1.103; §3.5.1 prose widens the ACPT lower bound a year later than Table 3.5.1 (the table is followed). Tests: 283 in tests/lead — every published line to the cent, Expr builders on polars and DuckDB, bit-for-bit scalar/frame parity over 160 scenarios; 100% of src/lead.
258 lines
5.7 KiB
TOML
258 lines
5.7 KiB
TOML
[project]
|
|
name = "stack"
|
|
version = "0.1.0"
|
|
description = "Healthcare data platform — ACO analytics, CMS data, BCDA FHIR, PFS equations"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
dependencies = [
|
|
"pydantic>=2.0.0",
|
|
# AGPL-3.0 — flag if shipping outside internal use. <2: pymupdf 2.x folds
|
|
# in the former pymupdf_layout code (Polyform Noncommercial / Artifex
|
|
# commercial) and pulls onnxruntime into every image — a licence call,
|
|
# not a routine bump.
|
|
"pymupdf>=1.27.2,<2",
|
|
"python-docx>=1.1",
|
|
"xlrd>=2.0.2",
|
|
]
|
|
|
|
[project.scripts]
|
|
stack = "cli:main"
|
|
|
|
[project.optional-dependencies]
|
|
conf = [
|
|
"pydantic>=2.0.0",
|
|
"httpx>=0.28.1",
|
|
"duckdb>=1.5.4",
|
|
]
|
|
aco = [
|
|
"stack[conf]",
|
|
"narwhals>=2.17.0",
|
|
"sqlglot>=26.0.0",
|
|
"pyarrow>=23.0.1",
|
|
"duckdb>=1.5.4",
|
|
]
|
|
api = [
|
|
"stack[conf]",
|
|
"fastapi>=0.139.0",
|
|
"uvicorn>=0.41.0",
|
|
"httpx>=0.28.1",
|
|
"pyjwt>=2.15.1",
|
|
"cryptography>=50.0.0",
|
|
]
|
|
bcda = [
|
|
"stack[conf]",
|
|
"httpx>=0.28.1",
|
|
"fsspec>=2026.6.0",
|
|
"narwhals>=2.17.0",
|
|
"pyarrow>=23.0.1",
|
|
"streamlit>=1.40",
|
|
"polars>=1.0",
|
|
]
|
|
bib = [
|
|
"stack[conf]",
|
|
"pydantic>=2.0.0",
|
|
"markdown-it-py>=4.0",
|
|
"mdit-py-plugins>=0.4",
|
|
]
|
|
bls = []
|
|
llm = [
|
|
"stack[conf]",
|
|
"stack[bib]",
|
|
"httpx>=0.28.1",
|
|
"fastapi>=0.139.0",
|
|
"uvicorn>=0.41.0",
|
|
"langchain-core>=0.3.0",
|
|
"langchain-ollama>=0.2.0",
|
|
"langchain-postgres>=0.0.12",
|
|
"psycopg[binary]>=3.2.0",
|
|
"sqlalchemy>=2.0.0",
|
|
"pyyaml>=6.0.0", # dev/scripts/llm_golden.py (golden set YAML) runs inside the llm container
|
|
]
|
|
ccw = [
|
|
"pydantic>=2.0.0",
|
|
]
|
|
lead = [
|
|
"stack[conf]",
|
|
"narwhals>=2.17.0",
|
|
]
|
|
cli = [
|
|
"stack[aco]",
|
|
"stack[api]",
|
|
"stack[bib]",
|
|
"stack[llm]",
|
|
"stack[mail]",
|
|
"stack[nlm]",
|
|
"typer>=0.24.1",
|
|
"uvicorn>=0.41.0",
|
|
]
|
|
nlm = [
|
|
"stack[conf]",
|
|
"httpx>=0.28.1",
|
|
]
|
|
mail = [
|
|
"httpx>=0.28.1",
|
|
"pydo>=0.29.0",
|
|
"resend>=2.0.0",
|
|
]
|
|
cms = [
|
|
"narwhals>=2.17.0",
|
|
"pydantic>=2.0.0",
|
|
]
|
|
opps = [
|
|
"stack[conf]",
|
|
"stack[rex]",
|
|
"duckdb>=1.5.4",
|
|
"narwhals>=2.17.0",
|
|
]
|
|
pfs = [
|
|
"stack[conf]",
|
|
"stack[rex]",
|
|
"duckdb>=1.5.4",
|
|
"narwhals>=2.17.0",
|
|
]
|
|
qpp = [
|
|
"stack[conf]",
|
|
"pydantic>=2.0.0",
|
|
]
|
|
rec = [
|
|
"stack[conf]",
|
|
"stack[pfs]",
|
|
"duckdb>=1.5.4",
|
|
"narwhals>=2.17.0",
|
|
"typer>=0.24.1",
|
|
]
|
|
rex = [
|
|
"stack[conf]",
|
|
"narwhals>=2.17.0",
|
|
"pyarrow>=23.0.1",
|
|
"fsspec>=2026.6.0",
|
|
]
|
|
prisma = [
|
|
"stack[conf]",
|
|
"stack[bib]",
|
|
"anthropic>=0.40.0",
|
|
"httpx[socks]>=0.28.1",
|
|
"pyyaml>=6.0.0",
|
|
"pydo>=0.29.0",
|
|
"pdfminer.six>=20221105",
|
|
"resend>=2.0.0",
|
|
]
|
|
perf = [
|
|
"stack[conf]",
|
|
"opentelemetry-api>=1.45.1",
|
|
"opentelemetry-sdk>=1.45.1",
|
|
"opentelemetry-exporter-otlp-proto-grpc>=1.25.0",
|
|
"opentelemetry-exporter-prometheus>=0.46b0",
|
|
"opentelemetry-instrumentation-fastapi>=0.46b0",
|
|
"opentelemetry-semantic-conventions>=0.46b0",
|
|
"psutil>=5.9.0",
|
|
]
|
|
sem = [
|
|
"coverage>=7.13.4",
|
|
]
|
|
lake = [
|
|
"stack[aco]",
|
|
"databricks-sdk>=0.85.0",
|
|
"databricks-bundles>=0.295.0",
|
|
]
|
|
aws = [
|
|
"boto3>=1.35.0",
|
|
"s3fs>=2026.2.0",
|
|
]
|
|
gcp = [
|
|
"google-cloud-storage>=2.18.0",
|
|
"gcsfs>=2024.1.0",
|
|
]
|
|
azure = [
|
|
"azure-storage-blob>=12.23.0",
|
|
"adlfs>=2024.1.0",
|
|
]
|
|
all = [
|
|
"stack[aco]",
|
|
"stack[api]",
|
|
"stack[bcda]",
|
|
"stack[bib]",
|
|
"stack[bls]",
|
|
"stack[ccw]",
|
|
"stack[cli]",
|
|
"stack[cms]",
|
|
"stack[llm]",
|
|
"stack[perf]",
|
|
"stack[pfs]",
|
|
"stack[qpp]",
|
|
"stack[rec]",
|
|
"stack[rex]",
|
|
"stack[lake]",
|
|
"stack[nlm]",
|
|
"stack[lead]",
|
|
]
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"stack[all]",
|
|
"coverage>=7.13.4",
|
|
"dbt-core==1.10.15",
|
|
"dbt-duckdb>=1.10,<1.11",
|
|
"openpyxl>=3.1.5",
|
|
"pdfplumber>=0.11.9",
|
|
"polars>=1.38.1",
|
|
"pytest>=9.0.2",
|
|
"pytest-cov>=7.0.0",
|
|
"pytest-xdist>=3.5.0",
|
|
"marimo>=0.23.13",
|
|
"ruff>=0.11.0",
|
|
"altair>=6.0.0",
|
|
"pandas>=3.0.1",
|
|
"obstore>=0.9.2",
|
|
"s3fs>=2026.2.0",
|
|
"jinja2>=3.1.0",
|
|
"fastexcel>=0.19.0",
|
|
]
|
|
|
|
[build-system]
|
|
requires = ["uv_build>=0.7,<1"]
|
|
build-backend = "uv_build"
|
|
|
|
[tool.ruff]
|
|
line-length = 88
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I"]
|
|
ignore = ["E501", "E741"]
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
markers = [
|
|
"stub: marks tests that report stub vs implemented status (deselect with '-m \"not stub\"')",
|
|
"live: marks tests that need a live DuckDB replica on disk (skipped without one)",
|
|
]
|
|
filterwarnings = [
|
|
"error::ResourceWarning",
|
|
"ignore::ResourceWarning:coverage.*",
|
|
]
|
|
|
|
[tool.coverage.run]
|
|
# Required for reliable pytest-cov + pytest-xdist combining: each worker
|
|
# writes .coverage.<host>.<pid>, then pytest-cov auto-combines at exit.
|
|
# Without this, parallel test runs randomly drop coverage data.
|
|
parallel = true
|
|
source = ["src"]
|
|
concurrency = ["multiprocessing", "thread"]
|
|
|
|
[tool.uv]
|
|
# Supply-chain cooldown: resolve only releases at least a week old, so a
|
|
# hijacked or yanked-within-days upload never lands in the lock. Renovate's
|
|
# minimumReleaseAge matches. Exempt one package with
|
|
# `exclude-newer-package` when a CVE fix can't wait. Lives here, not in a
|
|
# uv.toml: images copy only pyproject.toml + uv.lock, and the lock records
|
|
# the span, so `uv sync --locked` fails wherever the setting isn't visible.
|
|
exclude-newer = "7 days"
|
|
# Prevents broken .venv symlinks when uv runs under different users.
|
|
link-mode = "copy"
|
|
python-preference = "managed"
|
|
|
|
[tool.uv.build-backend]
|
|
module-name = ["aco", "api", "bcda", "bib", "bls", "ccw", "cli", "cms", "conf", "lead", "llm", "mail", "nlm", "opps", "perf", "pfs", "prisma", "qpp", "rec", "rex", "sem"]
|
|
namespace = true
|
|
source-exclude = ["compose.yml","infra/**","data/**","notebooks/**","tuva/**","assets/**","docs/**","dev/**","bundle/**","cloud/**"]
|