All notable changes to Sisyphus are documented here. Format follows
Keep a Changelog. Version numbers
track pyproject.toml.
Note on versioning: The git tag
v1.0.0(commit67b7064, 2026-03-xx) predates the currentpyproject.tomlversion0.1.0. The tag records an earlier milestone on a feature branch whose work was absorbed into the currentmainline after merges and rewrites. The repository will align on a single scheme in an upcoming release decision.
build_drug_on_graph double-allocated UGT tags: a tag present in both the ugt_enzymes block
and the per-gene non_cyp_fractions registry was counted twice in _get_fm_fractions, leaking
the CYP residual into a phantom UGT slot and ~8×-suppressing CYP (a UGT2B7-only substrate at the
literature 0.85/0.15 split resolved to 0.983/0.017). Routing each UGT tag through exactly one fm
mechanism (PR #93) corrects the split for the 8 B-02 UGT substrates (all in-holdout). Predict-layer,
deterministic, no model retraining; single-arm canonical CI regen (.github/workflows/ugt-regen.yml,
PR #94) → Meta AAFE 2.735 → 2.743 (Δ +0.00748, within the bootstrap CI; sign stack-dependent).
Correctness-first — 0.85/0.15 is the literature fate; the meta damps the net (morphine improves,
codeine worsens). Cache/bootstrap regenerated; cache-pin test_cached_holdout_aafe_is_2p743; CIs
data/validation/4track_ci_2026-07-03_ugt.json.
The CL/F-track training builder (scripts/build_clf_training_data.py) filtered holdout drugs by
name/flag only, admitting 5 name-evading structural collisions (valacyclovir, darunavir ethanolate,
ofloxacin/levofloxacin, dexmethylphenidate/methylphenidate, quinidine/quinine) into clf_training.csv.
Added a structural InChIKey-14 4th filter key (1131 → 1126 rows) plus a guard test (PR #90). A
dual-arm canonical CI regen (.github/workflows/clf-leakfree-regen.yml, PR #91) reproduced the
committed 2.73104 from the leaky csv, so Δ_leak is cleanly attributable = +0.00427 (within the
bootstrap CI; sign stack-dependent). Correctness-first per Invariant #5 (holdout inviolable), not an
accuracy claim — the leaked drugs are poorly predicted (methylphenidate 12×, quinine 8.7×).
Cache/models/bootstrap regenerated; cache-pin test_cached_holdout_aafe_is_2p735; CIs
data/validation/4track_ci_2026-07-02_clf_leakfree.json.
New module src/sisyphus/mipd/. Repositions the mechanistic engine from a one-shot
SMILES→Cmax oracle (walled at the holdout ceiling) into a structural prior that
any sparse measured observation sharply updates. With zero measured data it reduces to the
a-priori prediction, so the 107-holdout headline (2.731) is untouched — this is new product
surface in the regimes where the ML/meta stack has no signal by construction (out-of-domain
chemistry, dose/regimen/population extrapolation, individualized MIPD).
- Engine-as-prior posterior PK core (PR #69,
4cb76ed, 2026-06-09). Bioavailability F as a latent with a wide prior centered on the engine's emergentF_engine, updated from measured observations (F, Cmax, AUC, plasma conc) by SIR.mipd/core.py,mipd/clgrid.py(CL latent + conc grid surrogate),mipd/meta.py(route the posterior through the meta blend),mipd/grid.py.predictsurfacesengine_fvia a shareddetect_disposition. Gate 0b/0c passed (one measured anchor materially improves Cmax, ~3× more out-of-domain). Charter:docs/_internal/specs/2026-06-09-engine-as-prior-mipd-charter.md. - CrCl renal individualization + steady-state IV TDM + weight/age covariates (2026-06-11).
predict_posterior(covariates=Covariates(crcl_ml_min=...))scales renal CL byCrCl/125and surfaces the individualized posteriorpost.cmax;predict_tdm(...)conditions the prior on a steady-state IV trough to individualize a renal-CL latent over a multi-dosesolve_regimen(vancomycin/aminoglycoside scope); weight/age swap the reference graph forsbi.physiology_generator.generate_physiology. AddedPosteriorPK.{warnings,renal_scale}and an opt-inci_floor. Fixed an IV-infusion float-overshoot inregimen.solver.solve_regimen. - Dose recommendation + Cockcroft-Gault CrCl (2026-06-12).
recommend_dose(...)inverts the IV TDM posterior into a target-attainment dose (Css,max/Css,min/AUC) under constraints; Cockcroft-Gault estimates CrCl from age/weight/sex/SCr when no measured CrCl is supplied.
Same-stack regen (.github/workflows/flux1-regen.yml) of origin/main + paracellular absorption:
Meta AAFE 2.7310 (engine 4.244, ML 2.998, in-domain 2.777, N=107). The pinned 2.784 was stale
(predated the merged oxybutynin reference fix). Attribution: oxybutynin −0.026 + paracellular −0.031,
both within the bootstrap CI — correctness-driven, not a distinguishable accuracy gain. Cache, baseline,
bootstrap CIs (data/validation/4track_ci_2026-06-10_flux1.json), and the cache-pin (renamed
test_cached_holdout_aafe_is_2p731) all regenerated.
All correctness-first; the net holdout effect is captured by the 2.731 batch regen above.
- FLUX-1 — flow-limitation double-count fix (PR #65, 2026-06-04). The clearance flux applied the
whole-organ
CL_h(Q-embedded) to the compartment outlet alongside the convectiveQ·c_outedge, double-counting flow and capping hepatic/gut extraction at E→0.5 instead of →1.0. Fixed to apply the intrinsic clearance across all 4 clearance models; gut CYP3A4 abundance re-anchored to hold midazolam E_gut invariant. Correct physics; regresses the benchmark (2.698 → 2.784) — the wrong formula was load-bearing as calibration. This is the DE-41/42/43 first-pass-F root cause. - RBP-2 — blood:plasma concentration-basis cleanup (2026-06-04). Holdout-bit-identical; corrects drugs with RB:P ≠ 1 on non-holdout paths.
- Conformal prediction intervals (2026-06-04). User-facing 90% Cmax PI is now a train-calibrated split-conformal interval (q90=1.111, /÷12.92), holdout-validated to 0.953 coverage at nominal 0.90. Replaces the MC interval (29.9% @ nominal 90%). Point estimates bit-identical.
- OATP1B1 re-anchor to pitavastatin (2026-06-04). Re-anchored the liver OATP1B1 uptake abundance 5.0e5 → 1.3e5 against a non-holdout substrate (was pravastatin = holdout → Invariant #5 erosion); un-xfailed pravastatin + pitavastatin ECM tests. Headline-neutral.
- Measured-F routing (PR #64, 2026-06-03).
MeasuredADMEInput.f_bioavailexposure-scales engine Cmax/AUC by F_measured/F_engine; bit-identical when unused (headline untouched). - Engine contract hardening (WS-2..6,
f8edfbc, 2026-06-07). Fail-loudengine/contracts.pyfu-correction guard, real parallel-tube viagraph/axial.pyaxial sub-compartment expansion, active-transport direction, JAX↔SciPy RHS parity. Headline bit-identical (no productionparallel_tube/active_transportedges). - Oxybutynin holdout reference correction (PR #68, 2026-06-09).
cmax_mg_L0.001 → 0.008 (FDA Ditropan IR single-dose ~8 ng/mL; a decimal/unit slip); AUC + ct_curve rescaled ×8. Primary-source, model-blind. Regen-folded into the 2.731 headline above.
- B-13 — gut UGT2B7 correction (PR #49,
242b100, 2026-05-29). Gut-wallUGT2B7 = 3.6e3 pmol(0.60 pmol/mg total-mucosal × 6000; Al-Majdoub 2021 / Couto 2020); gutUGT1A9dropped (not expressed in human small intestine; Oda 2012). Drug-level UGT1A9 affinity still acts at liver. Metric-neutral: Meta AAFE 2.69828 → 2.69825 (103/107 bit-identical; only the 4 UGT2B7 gut seeds shift, all down). A citation-confabulation audit (11-agent adversarial verification) re-derived both gut abundances from primary sources after two fabricated citations were caught. - B-14 — hepatic UGT IVIVE differential = DE-40 no-op (PR #50,
3b0b72b, 2026-05-30). Predict-side per-enzyme UGT scaling-factor hook ships as audited no-op infrastructure:data/enzymes/ugt_ivive_sf.json(all-1.0 registry) +get_ugt_ivive_sf()loader inpredict/non_cyp_substrates.py+ a one-linescaled_affinity *= sfin_decompose_clint. Engine untouched (identity-blind preserved); 107/107 bit-identical. No verified per-substrate hepatocyte-basis hepatic-fraction SF exists (DE-40); the clean hook remains available for any future curated value. - gitignore housekeeping (PR #52,
7749f41, 2026-05-30). Added.ruff_cache/,.mypy_cache/,.hypothesis/,*.orig,*.rej, andSisyphus_Preprint_*.{docx,pdf}(local-only manuscript drafts). No tracked files affected. - Pravastatin holdout→MMPK leak closed + JAX RHS guard (PR #53,
d424688, 2026-05-31). Forward-looking audit follow-up: pravastatin was the only holdout drug surviving both filters inml_cmax_improvement.load_mmpk_data(in_holdout=False rows + an InChIKey-14 connectivity mismatch theho_ikfilter missed). Corrected thein_holdoutflag inmmpk_expanded_{full,v2}.csv, added a name-based exclusion (load_holdout_names()), and pinned it withtests/regression/test_mmpk_holdout_leak.py. The shippedxgboost_cmax.jsonwas trained via Omega's own 3-key exclusion, so the headline cache is unaffected (stays Meta 2.698). Also hardenedmake_jax_rhswith a pure-Python_unsupported_flux_specs()guard that raisesNotImplementedErrorinstead of silently dropping prodrug-activation / 1-compartment-elimination fluxes (dead path; no production caller usesbackend="jax").
Agent-operational docs that external readers do not need are now gitignored under
docs/_internal/, mirroring the existing local-only project-context decision (2026-05-02).
Moved out of the tracked tree (via git mv, history preserved): backlog.md,
landmarks.md, phase-completion.md, hardening_backlog.md, propranolol_cmax_drift.md
(from docs/research/), next_steps_plan.md + current_directory_completion_audit_2026-04-24.md
(from docs/), and the entire docs/_internal/plans/ directory (implementation
scaffolding — specs stay public as audit-trail per cherry_picking_process_v1.md §2).
The full internal development superset lives locally under docs/_internal/.
The committed docs/research/ set is now the
externally-meaningful five: dead-ends, experiment-log, diagnosis,
cherry_picking_process_v1, cherry_picking_audit_2026-04-22. Note: historical
CHANGELOG / spec / experiment-log entries that cite the moved paths
(docs/_internal/plans/…, docs/research/backlog.md, etc.) are left as immutable dated
records; those files now live under docs/_internal/ and resolve only in a working tree
that retains the internal docs.
Resolution of T1 caution flags deferred from v2. Architecture unchanged (pure data-quality refresh per spec §3.3 mechanistic-A doctrine).
Items resolved:
- Item 1 (BH4 CL/Vd, sepiapterin): ceiling_accepted (F_sapropterin not located in primary literature; FDA Kuvan + EMA EPAR explicit "absolute bioavailability not known")
- Item 2 (GS-441524 CL/Vd, remdesivir): literature_applied (Tamura 2023 + Leegwater 2022 popPK geomean: CL=17.4 L/h, V=535 L)
- Item 3 (R406 CL/Vd, fostamatinib): literature_applied (Matsukane 2022 IV microdose review: CL=15.7 L/h, Vss=256 L)
- Item 4 (tebipenem CL/Vd): ceiling_accepted (F_tebipenem absolute not located; Eckburg V/F=46.2 surrogate rejected per §4.1 Gap 5)
- Item 5 (SPR primary proteomic abundance): ceiling_accepted (no quantitative MS-based human SPR pmol/mg located; HPA + Wu 2020 review animal-only)
- Item 6 (CES2/tebipenem direct CLint): ceiling_accepted (no in vitro tebipenem-pivoxil/CES2 Vmax/Km located; Gupta 2023 generic intestinal esterases)
v1→v2→v3 fold-error progression (per docs/_internal/specs/2026-04-29-prodrug-v3-literature.md):
| Drug | v1 | v2 | v3 | gate |
|---|---|---|---|---|
| sepiapterin | 5356× over | 4692× over | 4748× over | xfail (Item 1 ceiling) |
| remdesivir | 4.45× under | 4.43× under | 4.44× under | xfail (Item 2 lit_applied; parent obs not active) |
| fostamatinib | 4.78× under | 4.51× under | 4.50× under | xfail (Item 3 lit_applied; extraction rate-limited) |
| tebipenem_pivoxil | 8.63× under | 9.02× under | 9.05× under | xfail (Items 4+6 ceiling) |
Headline AAFE delta: zero shift (4 prodrugs not in 107-holdout). Meta 2.702, Engine 3.572, ML 3.057 unchanged from v2 baseline. Verified by §6.2 enzyme-leak audit (107/107 byte-identical).
Per spec §3.3 mechanistic-A promise, gate-fail with mechanistic-A-compliant values is acceptable outcome (informative not failing). v4 candidates require new mechanistic terms beyond data refresh: extra-hepatic esterase distribution, BH4 first-pass depletion, in vitro CES2/tebipenem kinetics.
References: docs/_internal/specs/2026-04-29-prodrug-activation-v3-design.md + docs/_internal/specs/2026-04-29-prodrug-v3-literature.md + plan docs/_internal/plans/2026-04-29-prodrug-activation-v3.md.
-
Prodrug activation routing infrastructure (branch
feat/prodrug-activation, commits0db67a8..a2ad03e, 17 commits, 2026-04-25/26):ActiveMetabolitedataclass (core.py) +DrugOnGraph.active_metaboliteobservation_speciesfields with__post_init__validation.
- 2 new edge types (
graph/types.py):ProdrugActivationEdge(asymmetric parent→active mass transfer with MW × yield scaling) andOneCompartmentEliminationEdge(aggregate 1st-order CL/Vd elimination). - 2 new FluxSpecs (
engine/flux.py): registered via@register_flux, asymmetric mass transfer + 1-compartment elimination. ResolvedParams._build_edge_paramsadditive branches for the new types (existing logic untouched).BodyGraph.sample()resampling branches for new edge types.graph/builder.py::augment_for_active_species— adds 1 plasma node + 2 edges per prodrug (no-op whenactive_metabolite=None).predict/registry.py— SMILES-keyed registry loader with RDKit canonicalization + JSON validation.data/sbi/prodrug_activation_registry.json— 4 N50 evidence drugs: sepiapterin→BH4, remdesivir→GS-441524, tebipenem_pivoxil→tebipenem, fostamatinib→R406.pipeline/predict.pyintegration — augmentation hook before compile,_resolve_observation_node+_adjust_ad_for_prodrughelpers.- 50+ new tests across unit/integration/regression categories.
-
Prodrug activation v2 — enzyme-abundance mechanistic (branch
feat/prodrug-activation-v2, 2026-04-27/28): replaces v1's kinetic 1st-order conversion (rate = k × A_parent) with well-stirred extraction at flow-through nodes (mirrors existing CYP3A4 elimination pattern). Drug declaresenzyme_affinity_for_conversion: dict[str, Distribution]; augmentation discovers conversion sites by enzyme intersection with physiology. Affinity values sourced from in-vitro literature or substrate-class kinetics (no clinical fit; tier 3 / "infrastructure_only" rejected by registry loader per spec §3.3 mechanistic-A promise).Architectural changes (additive to engine; identity-blind preserved):
ProdrugActivationEdge.conversion_rate: Distributionremoved; replaced byenzyme_tags: frozenset[str](compile-time set).ProdrugActivationFluxSpec.apply()rewritten as well-stirred extraction parallel toClearanceFluxSpec(model="well_stirred"), destination redirected to active species pool with MW × yield scaling.DrugOnGraph.enzyme_affinity_for_conversion: dict[str, Distribution]new additive field (__post_init__enforces non-empty + active_metabolite pairing).ResolvedParams.drug_enzyme_affinity_for_conversion(tag) -> floatnew method (parallel todrug_enzyme_affinityfor elimination).augment_for_active_speciesrewritten: multi-site discovery viaenzyme_tags ∩ node.enzymes; one ProdrugActivationEdge per site.lookup_active_metabolitereturns 3-tuple(am, obs, affinities); schema requiresaffinity_source+yield_sourceenums.
Physiology YAML additions: SPR (1e5 liver, 3e3 gut, 3e4 kidney, all CV~1.0–1.2 class-estimated), CES1 (8e7 liver, CV 0.47, Boberg 2017), CES2 (8.4e6 liver, 3e6 gut, CV 0.6), ALPI (2.3e4 gut, CV 0.9, Al-Majdoub 2020). All independent lognormal (no Achour matrix entry).
v1-vs-v2 fold-error comparison (deterministic Cmax at registered doses; per-drug parametrized 3-fold gate per spec §6.1):
Drug v1 fold-error v2 fold-error Δ sepiapterin 5356× 4692× -12% remdesivir 4.45× 4.43× ~unchanged tebipenem_pivoxil 8.63× 9.02× +5% fostamatinib 4.78× 4.51× -6% All four drugs fail the 3-fold validation gate (xfail with documented reasons). This is expected per spec §3.3 mechanistic-A promise: affinity values are NOT refit to clinical data. Failure is informative, not project-failing.
Disposition decisions (from brainstorming review, 2026-04-28):
- D1 (deferred to v3): v1 active species CL/Vd values retained
unchanged. T1 literature (
docs/_internal/specs/2026-04-27-prodrug-v2-task1-literature.md§4) found inconsistencies for BH4, GS-441524, R406 (1.5–50× literature deviation). Deferred to preserve clean architectural attribution (v2 = conversion math + affinity sourcing only). v3 task to update active CL/Vd from popPK literature with 1C-vs-2C reduction analysis. - D2 (applied): fostamatinib
conversion_yield_fraction0.7 → 0.9. v1 conflated hydrolysis stoichiometry with bioavailability; v2 yield is pure hydrolysis (absorption losses captured by parent peff upstream). - D3 (kept): sepiapterin retained in v2 registry. Tier 2 (SPR abundance class-estimated, T1 caution flag). Removing would weaken architecture stress test (Eg ≈ 99.99% case).
Validation tests added:
- Mass balance well-stirred (flow-loop synthetic) —
tests/integration/test_prodrug_v2_mass_balance.py. - Per-prodrug pipeline smoke (4 drugs end-to-end) —
tests/integration/test_prodrug_v2_pipeline_smoke.py. - DDI smoke (halving CES1 → 0.53× remdesivir active Cmax) —
tests/integration/test_prodrug_v2_ddi_smoke.py. - Identity-blind random tag rename invariance —
tests/regression/test_prodrug_v2_identity_blind.py. - 107-holdout numerical invariance verified (no leak from new enzymes).
- Per-prodrug Cmax ±5% snapshots —
tests/regression/test_prodrug_v2_snapshot.py. - Per-drug parametrized 3-fold validation gate —
tests/regression/test_prodrug_v2_validation_gate.py.
Reuse from v1: 60% (9/15 components unchanged: ActiveMetabolite, OneCompartmentEliminationEdge, observation_routing, AD adjustment, pipeline integration shape, holdout regression, ACTIVE_SUFFIX/sink constants, DrugOnGraph 19 existing fields, edge_id sampling pattern). Changed: 6 (edge struct, flux body, registry schema, registry loader, augmentation, mass balance test). New: 3 (physiology entries, drug field, ResolvedParams method).
v1 known-limitation note (now superseded) covered the kinetic 1st-order architecture's inability to capture fast first-pass extraction — diagnosed root cause was gut_wall residence ~64s. v2 well-stirred resolves this architectural limitation; remaining prediction errors trace to literature-input quality (per T1 caution flags), addressable in v3 via CL/Vd updates and tighter SPR/CES2/ALPI abundance measurements.
-
H1-H5 hardening infrastructure (PRs #3-#6, 2026-04-23):
- H5 GitHub Actions CI (
.github/workflows/ci.yml): Python 3.10 ubuntu, unit + integration + benchmark smoke, ruff advisory. - H1
requirements-lock.txtpinned from fresh venv, RDKit-coupled hashes. - H3
--compute-piCLI flag wirespi_coverage_90via Monte Carlo MC propagation. Diagnostic only (parameter uncertainty; not calibrated). - H2
ModelRegistry+<model>.meta.jsonsidecar manifests withfeature_schema.sha256on all 12 actively-loaded XGBoost artifacts. - H4
docs/science/ecm_unit_audit.md— dimensional chain analysis of ECM extended clearance.
- H5 GitHub Actions CI (
-
First empirical 90% PI coverage measurement (2026-04-24, commit
bbedd9f): 29.9% at N=107 holdout × 1000 MC samples. AAFE 2.719 reproduces the 2.695 headline within MC noise. PI captures ~1/3 of observed residual spread — interval is ~3× too narrow relative to structural error. Recorded in the project README as diagnostic, not calibrated. Artifact:data/validation/holdout_pi_coverage_2026-04-24.json. -
P4.5 Achour correlated abundance prior (merge
2275932, 2026-04-23):Distribution.correlation_groupfield +physiology.correlation_registry- Achour 2021 5-way CYP log-correlation matrix at the liver node. AAFE 2.6946 invariant. SBC retraining deferred to P4.5a.
-
N50 secondary holdout — FROZEN cycle 2026Q2 (commit
b366035, 2026-04-23): AAFE 5.249 [95% CI 3.79-7.77, N=50]. Cannot re-run per spec §7 single-use-per-cycle. Retireholdout_n50.jsonbefore 2026Q3+.
README.mdstructure diagram:- Replaced non-existent
ml/vdss_predictor.pywithregistry.py; VDss is a track weight inensemble.py(_W_VDSS=0.20), not a module. - Replaced non-existent
sbi/hierarchical.pywithmulti_drug.py,priors.py,physiology_generator.py(the Achour sampler). - Removed
validation/split.py(deleted; see below).
- Replaced non-existent
graph/presets.py::reference_woman()now raisesNotImplementedErrorwith migration guidance instead of failing opaquely on a missing YAML file. Usereference_man()+ body-weight override via the continuous-hierarchical path.README.md— added Prediction-interval coverage section under Current Performance (diagnostic caveat emphasized).docs/current_directory_completion_audit_2026-04-24.md— counter-audit patch Option α (commitc52b62f): 3-wayNotImplementedErrorreclassification, P0-1 option (c) flagged inadequate, §7 ceiling split into scientific vs release axes, §4.6 CHANGELOG/tag gap noted, §6 P2-5 CI fail-closed gates proposed.
src/sisyphus/validation/split.py(commitdd4282f):scaffold_splitwas aNotImplementedErrorstub with no callers (grep ∅). The holdout split is already frozen indata/reference/holdout.json.
.gitignore— added.claude/(agent/session-local config) as part of the counter-audit patch.
- No security-relevant changes in this cycle.
This tag records an earlier milestone on a feature branch (now merged
into main after rewrites). Retained for historical traceability.
- In-domain holdout AAFE: 1.697 (target ≤ 1.7)
- PK/PD link (effect compartment + Emax) implemented
- DDI module (inhibition + induction via enzyme abundance) implemented
- MC optimization (fast solve + propagate_fast for N=1000)
- Prodrug detection, Kp capping, in-domain AAFE ≤ 1.7
Note: the current main line (301 commits ahead of v1.0.0) supersedes
these numbers with a more conservative measurement regime (N=107 full
holdout AAFE 2.695, secondary holdout AAFE 5.249). The v1.0.0
acceptance criteria are therefore historical, not current.