Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.0.33] - 2026-08-25
Honest-uncertainty release. Every headline number the report shows now carries an interval that accounts for how the cohort is actually structured, and the report states which negatives it was scored against — the choice that moves the headline more than any modeling decision. Also ships the pipeline DAG as a drawn object and the report's visual rebuild.
Added
- The verification-bias ladder as a panel (#136). Anchor choice moves the headline 13.1 AUC points and the report stated it in the third clause of a caption. Four rungs now, scored on the same model and the same positives with only the negative class changing: verified within-patient negatives 0.845, all negatives pooled 0.856, unpaired negatives 0.865, healthy donors 0.976 — each with its n, patient count and a patient-clustered interval. The unpaired rung existed in the campaign record but never in the report. The donor rung is labelled as a different question (between people rather than within a patient), not as an unreliable one: at 55 negatives its interval is only ~1.7× wider than the verified rung's, checked against a stratified two-sample bootstrap and Hanley–McNeil before the claim was drawn.
- The Nextflow DAG drawn into the report (#127), in Methods (two densities, structure
only) and Run diagnostics (this run's task counts above the tables they summarise). Layouts
are computed at build time from one declaration and injected as finished SVG; the page never
positions a node.
tests/test_pipeline_diagram.pyasserts the declaration against the workflow in both directions, so a stage added to the DAG cannot leave the diagram describing the old topology. - Report visual rebuild (#126): a hero zone carrying the primary endpoint, the burden-response curve and the stacking lift; findings that title the chart they are derived from; a 16-term glossary behind info icons.
Changed
- The primary endpoint carries an interval (#132). Sensitivity at 98% specificity against
verified true negatives had shipped as a bare point estimate —
_wilsonexisted but was wired only to the LOD bins. It is now 0.483 [0.424, 0.519] from a patient-clustered bootstrap with the threshold re-estimated inside every resample, because the threshold is itself an estimate from a finite negative set. Decomposing the width separates two things that had been conflated: clustering inflates the variance 1.26×, estimating the threshold inflates it 11.3×. - AUC intervals resample patients, not samples (#132).
_bootstrap_aucresampled rows, so every evaluator and holdout interval in the scoreboard treated a patient's repeated timepoints as independent. Measured design effect 1.21 on the stacking AUC — intervals widen ~10%. CI values from earlier releases are not comparable to these. - Subgroup AUCs gain a per-class floor, an interval and tier composition (#134). The panel printed retinoblastoma's AUC on 72 positives at the same visual weight as NSCLC's on 2,254. The floor now counts the scarce class, rows carry patient-clustered intervals (primary evaluator only — every other subgroup table is exploratory), and each row reports the share of its positives that are tumour-confirmed, which ranges from 51% to 90% across histologies.
- Dual-anchor operating points and the one-sided donor bound (#125, closing #123); per-sample depth metadata as first-class label columns (#122).
Fixed
- Chart axis overrides no longer erase axis titles —
PL_LAYOUTmerged layouts with a shallowObject.assign, so a partial{xaxis:{…}}replaced the whole axis object and dropped its title. Three charts had silently lost a label (#126). - Category ticks are forced one per row: plotly thinned them on short plots, and the row it dropped first was the best evaluator at the top of the chart (#126).
- Two mypy errors that reproduce under the pinned toolchain but not in CI. Neither was type
noise — the CLI one guarded a
pivot_tableresult that unpacks the characters of a column name when pandas returns a flat Index (#130). mkdocs build --strictpasses again: four unannotated parameters and one generator without a return annotation had been failing the documented release gate.
Documentation
- The label taxonomy is six tiers, and the docs said five — in eleven files, including
AGENTS.md, which agents read on every turn. Worse,.agents/rules/labeling-hierarchy.mdand thectdna-labelingskill both stated that a CH-onlyPossible ctDNA+is "demoted to Possible ctDNA−". The code demotes it toUndetermined(LABEL_UNDETERMINED), which is outside_MODEL_LABELSand therefore excluded from modelling — following the documented behaviour would have put CH-only samples in the negative class.docs/biology/ctdna-labeling.mdcontradicted itself, prose against its own code block three lines below. - The report interpretation guide described a report that no longer exists — four tabs, no
Methods tab, none of this release's panels. It now covers five tabs, the primary endpoint and
its interval, the verification-bias ladder, the run map, the subgroup floor and tier
composition, and why the interval width is mostly threshold estimation rather than clustering.
Its
#page-5-cohort-qclink, a leftover from the retired Quarto dashboard, is repointed. - The API reference covered 5 of 13 modules.
report_data— which decides what every number in the report means — andselection— which decides which features reach a model — were both undocumented while the scoreboard displaying their output had a page. All thirteen now have one, withclionmkdocs-typer. - The release guide described a flow no release has used. It said to land the version bump on
developand PRdevelop→main; v0.0.32, v0.0.31 and v0.0.28 each merged arelease/vX.Y.Zbranch straight intomainand back-merged afterwards. The documented path is also riskier — withdevelopas the staging area, anything merged there between the bump and the PR rides into the release unreviewed. - README claimed Boruta-SHAP as a multimodal selection option two bullets above its own table naming grootcv the default; Boruta is now a legacy extra that cannot be installed alongside arfs at all.
Infrastructure
- Notebook hygiene tests (#130): a notebook written as nbformat 4.4 carries no cell ids, so nbdev's export hash moves on every run and the sync gate fails on an unrelated PR.
- An sbatch wrapper for GPU research jobs outside the Nextflow DAG, and an isolated-env recipe that refuses to install unless the target really is isolated (#130).
- Research scripts for the review campaign: the grouped-CV leakage delta, a two-measure depth re-check, the reporting-precision battery, and the matched-stratum histology analysis (#128, #132, #133).
[0.0.32] - 2026-08-18
Scoreboard-contract release (#108, closing #107): the scoreboard stops fabricating values for inputs it never saw. Cut back-to-back with v0.0.31 so the #96 confirmation run on iris exercises the GrootCV migration and the honest scoreboard in a single production run.
Changed
- The scoreboard is rebuilt on an explicit, versioned contract (#108, found via #107:
the shipped v0.0.29 scoreboard stamped
selection_method=legacy_cohens_d,n_selected_features=0andselection_overlap_pct=0.0on all 26 evaluators — fabricated defaults for inputs the process never saw). Every field is now sourced from a named artifact or explicitly unknown (NaN / None /"unknown") and recorded in a per-rowmissing_fieldscolumn (schema_version=2.0stamped on every row; fixed column set — an AUC column for every configured model, NaN when it didn't run).KREVIEW_SCOREBOARDnow stages the selection-QC sidecars (the same channel REPORT consumes), so selection columns are real (mrmr, true counts, total inputs). The previously silentn_features=0-when-a-GPU-model-wins pathology is now visible as a named missing field. Dead monolithic-era code (embeddedselection_qcprobing,"stacking"branches, the legacy label,selection_overlap_pct) is deleted.extract_evaluator_summaryis the single place that knows the model-results key shapes; a drift-canary test fails if a producer renames a key without the extractor learning it.scoreboard.pyis now nbdev-generated fromnbs/07_scoreboard.ipynb— the standalone-module exception list shrinks toreproducibility.py.
[0.0.31] - 2026-08-18
GrootCV migration release (#96): the multimodal all-relevant selector moves from the
unmaintained BorutaShapPlus to arfs 3.0 GrootCV, validated head-to-head on the real
v0.0.29 cohort before a line of pipeline code changed. run_hpc.sh now runs grootcv —
the next production run doubles as the tabicl-inclusive confirmation before the library
default flips.
Changed
- Multimodal all-relevant selection migrated to arfs 3.0 GrootCV (#96, literature-backed
and validated on the real v0.0.29 cohort).
grootcvis the recommended--multimodal-selectionfor production (run_hpc.shnow uses it): measured selection stability Nogueira 0.85 vs 0.65 for boruta_shap (pairwise Jaccard 0.77 vs 0.53) with equivalent-or-better downstream AUC and sensitivity, and boruta's full-train selection a strict subset of grootcv's. New evidence-based knobs, exposed CLI→Nextflow:--selection-cutoff/multimodal_selection_cutoff(default 3.0 — the #96 sweep winner: dominates boruta_shap on stability, AUC and sens@100spec-healthy simultaneously) and--selection-n-iter/multimodal_selection_n_iter(default 10 — 0.96 selection agreement with n_iter=50 at ~6× less runtime; ~40 s on the production 944-feature super-matrix). GrootCV's LightGBM threads are pinned totask.cpusin the Nextflow module (oversubscription guard). Both container images now ship thearfsextra. boruta_shapis deprecated and BorutaShapPlus left the core dependencies: it is mutually uninstallable with arfs 3.0 (BorutaShapPlus pinsnumpy<=2.0.0, arfs 3.0 needsnumpy>=2.0.2). Reproducing pre-#96 runs requires the new[legacy-boruta]extra (conflicts with[arfs]by construction); using the strategy logs a deprecation warning. Themidefault of--multimodal-selectionis unchanged; flipping the default to grootcv is deferred to the tabicl-inclusive confirmation run (#96 rider).
Fixed
- arfs strategies no longer crash on genomic-coordinate feature names (#96, found on
the real v0.0.29 super matrix): LightGBM rejects feature names with JSON-special
characters (
FsdGenomewide__fsd_gw_chr8:46838888-…_ratio), so Leshy/GrootCV now fit under sanitized names and map selections back to the originals (_lgbm_safe_columns, collision-guarded). The docker smoke test exercises exactly this case, and the leshy/grootcv strategy tests are real passing tests again (the #91/#92 xfails are gone; the boruta_shap test skips visibly unless[legacy-boruta]is installed).
[0.0.30] - 2026-08-17
Report + rigor release: the reporting layer is rebuilt as one data-driven, PHI-guarded, self-contained page (#79, Quarto path deleted); the train/test split is patient-grouped (#101 — found by the new report's own integrity check); and the two terminal failures from the first production v0.0.29 iris run are fixed (#97 multimodal-ablation collapse, #98 stranded dashboards). Holdout metrics from this release onward are not directly comparable to earlier runs (see the split entry below).
Fixed
- The train/test split is now grouped by patient (#101, found by the #79 report's own
integrity check on the v0.0.29 run: 1,266 patients had samples in BOTH train and test,
optimistically biasing every holdout metric).
_assign_train_test_splitusesStratifiedGroupKFoldonPATIENT_ID— all timepoints of a patient travel together, every timepoint stays usable, label-tier stratification is approximately preserved (verified on the real 16,272-sample labels: 0 leaked patients, test fraction 0.203, per-tier drift ≤ 0.4 pp, deterministic). A post-split assertion makes a leaked patient a hard error. Healthy donors (no cBioPortal record, one sample per donor) now carryPATIENT_ID = SAMPLE_ID, keeping the column complete for all grouped consumers. The eval-stage CV folds deliberately stay ungrouped — measured on the real v0.0.29 matrices, patient-mixing inflates CV AUC by ≤ ~0.001 (an order of magnitude below fold noise); the grouped holdout is the honest headline. Full measurement tables and the documented decision are on #101. Note: holdout numbers from runs ≤ v0.0.29 are not comparable to grouped-split runs — expect shifts of ~0.005–0.02 from test-set re-composition (the leaked repeat-timepoint patients were the harder cases, so the old numbers were dragged down, not inflated).
Changed
- The reporting layer is one data-driven page (#79).
kreview reportnow takes the pipeline--outdirand renders a single self-contained HTML (plotly inlined from the installed package — zero CDN, air-gapped-safe) via the newkreview/report_data.pydata layer: sortable scoreboard with per-evaluator deep-dive modals (per-model AUC+CI, fold AUCs, OOF-computed ROC/PR, calibration, decision curves, subgroup AUCs with an n≥30 floor, feature-group ablation stability), multimodal stacking, cohort composition with the train/test split (and a loud patient-leakage warning — see the split issue), and run diagnostics from the execution trace. Aggregates only:assert_no_phirefuses to emit anything sample-identifying. The #98 manifest semantics carry over (always written, failure recorded). Validated end-to-end on the real iris v0.0.29 outputs: 26 evaluators, 5 MB page, rendered in ~3 s. KREVIEW_REPORT(Nextflow) stages channel inputs into the canonical outdir layout and runs the new renderer —process_low, 8 GB, no more 64→192 GB ladder. The separateKREVIEW_REPORT_MULTIMODALprocess is gone (its content is the report's multimodal tab); multimodal/ablation inputs are optional sentinels (#97 pattern), so a failed optional stage degrades the tab instead of starving the report.
Removed
- The Quarto render path (#79): both
.qmdtemplates (~4,000 lines, 1,009 of them duplicated),_render_quarto_report/_find_quarto, render-time SHAP, and thequarto-cli,papermillanditablesdependencies.kreview/feature_cards.py(used only by the deleted templates) is gone too. Report-only params--shap-samples,--shap-featuresand--cvd-saferemoved from the CLI and Nextflow (eval-stage SHAP is untouched).
Fixed
- A failed dashboard no longer strands the successful ones (#98, found on the iris
v0.0.29 run where 17/26 rendered dashboards published nothing).
kreview reportstill exits 1 when any dashboard fails (fail loud), but theKREVIEW_REPORTwrapper now applies the retry-then-degrade pattern from #59: non-terminal attempts fail (the retry ladder gets a chance), and the terminal attempt exits 0 so everything that rendered publishes. The CLI also always writesreports/report_manifest.json(succeeded/failed evaluators + pointers to per-failure*_render.logQuarto debug logs, which now publish too) — a partialreports/directory is loud, never silently incomplete.
Changed
- Multimodal ablation runs in the GPU container when GPU models are in play (#97
follow-up).
KREVIEW_MULTIMODAL_ABLATIONnow routes its container, queue, memory, time and cluster options onparams.multimodal_gpu_models— when GPU stacking models are requested, the ablation gets the GPU image and a GPU slot instead of silently falling back to a CPU model. The #97 loud CPU fallback remains for environments with no GPU. - Lint toolchain fully pinned:
mypy==2.3.1andruff==0.15.4join the exactnbdev/blackpins in the[dev]/[all]extras — unpinned linter releases twice broke CI on untouched code.
Added
- Vendored the official
migrate-nextflow-codeskill from nextflow-io/agent-skills (Apache-2.0, attribution inVENDORED.md) into.agents/skills/— detect → fix → verify procedures for the strict-syntax migration class that produced #80 and the #97 config gotcha. Its detection tool,nextflow lint(26.04+), reports the tree at 0 errors / 36 style warnings.
Fixed
- Multimodal ablation no longer collapses when the best stacking model is GPU-only
(#97, found on the first production v0.0.29 iris run). The LOO ablation stage runs in the
CPU container, but picked the best stacking model unconditionally — when that was
tabicl(GPU-only),_build_modelreturnedNone, all 39 evaluator ablations failed with a baffling sklearn error, and the terminally-failed stage starvedMULTIMODAL_MERGEandREPORT_MULTIMODAL, silently losing the merged multimodal results and dashboard. Three fixes, per the terminal-failure policy (degrade AND surface loudly): multimodal_ablationnow collects every model's stacking AUC, probes candidates best-first, and falls back loudly to the best model the environment can build — re-baselining deltas against the used model's own full-matrix AUC (deltas against an unbuildable model's baseline would be scientifically wrong). The substitution is recorded inablation_results.json(ablation_model_fallback: requested/used/AUCs/reason).- If no candidate is buildable, it raises one clear
RuntimeErrornaming the models — not 39 repeats ofestimator ... Got None instead. - The workflow now passes
ifEmpty(file('NO_ABLATION'))on the merge input — themultimodal_mergemodule already handled that sentinel; the workflow just never sent it. Verified behaviourally with a forced-fail ablation stub: merge + multimodal dashboard now survive a terminal ablation failure (and the pre-fix tree provably loses them). Guarded by a structural assertion inscripts/nextflow_stub_test.sh.
[0.0.29] - 2026-07-22
Hardening release: closes the recurring release-breakage classes from the 2026-07 review
(fail-loud invariants, Nextflow v25–v26, centralized HPC env) and validates the shipped
container end to end. The boruta_shap multimodal workflow (used by run_hpc.sh) is now
smoke-tested inside the built CPU image on every CI run.
Added
- Test coverage for the CLI,
report.py, and the multimodal strategies (#63). Added areport.pysmoke test (0% → 57% — covers the matrix-not-found guard) and CliRunner--helptests across the full nested command tree (eval ablate *,eval multimodal *), which guard command registration/wiring. A newtest-strategiesCI job installs thearfsextra and runs the multimodal strategy tests, which previously skipped in every environment — the same "looks protected, isn't" pattern that hid the original BorutaShap outage. Un-skipping them immediately surfaced that all three are broken against modern deps (not kreview bugs — the strategy dispatch is correct):arfs2.4 is incompatible with sklearn 1.9 (force_all_finite, breaksleshy) and lightgbm 4.x (categorical_feature, breaksgrootcv) — #91; andboruta_shaphits a BorutaShap→shap xgboost-parser error on some versions — #92. All three are nowxfail(strict=False)with tracked issues so the breakage is visible rather than invisibly skipped (they xpass and alert when the deps are fixed). Thearfsextra also now pinssetuptools<81(arfs imports the removedpkg_resources). Overall coverage 44% → 46%; CI floor 38% → 42%. (Nonf-testharness — the Nextflow-stub-runinscripts/nextflow_stub_test.shcovers the workflow wiring, per the #80 maintainer decision.)
Changed
- Centralized the HPC env setup and fixed inconsistent hardening (#58). The Singularity
read-only-
/home/ cache-redirect env was copy-pasted across five modules and had drifted:PYTORCH_CUDA_ALLOC_CONF(the CUDA-OOM guard) was set inmultimodal_singlebut missing fromeval_gpu_singleandablate_gpu_single, and the report modules lackedHOME/TMPDIR/MPLCONFIGDIR. It is now defined once each (params.gpu_env_setup,params.report_env_setup) and interpolated into every module'sscript:, so the hardening is applied identically everywhere.scoreboard.nf'spython3heredoc now fails loud with a clear message if the interpreter is missing (Singularity PATH strip) instead of a cryptic exit 127.
Two deliberate design choices, contrary to the issue's original suggestion, because the
nf-core iris institutional config sets its own beforeScript, withLabel resources,
errorStrategy and cache: (1) the env stays in-script, not in a beforeScript, which
is a single non-additive directive that would clobber (or be clobbered by) iris's; (2) the
per-withName resource ladders stay as they are — they are defensive armour against iris's
withLabel override, and Nextflow 24+ forbids the def-closure hoisting that would dedup
them. Rationale recorded in .agents/memory/reference-iris-config-interaction.md.
Fixed
- Published output nested a working-directory prefix (#84). Because a process'
output:path carries the working subdir (selected/,fused/,output/,prep_out/, …) andpublishDiralready named the destination folder, results landed atmatrices/selected/selected/…,matrices/fused/fused/…,models/multimodal/prep_out/…. AddedsaveAs: { fn -> file(fn).name }to the seven affected modules so files publish by basename — the tree now matches the documented structure (matrices/selected/X,models/multimodal/X). Publish-path only; nothing consumesparams.outdir(all inter-process data flows through channels), so the DAG is unaffected. Guarded by a new flatness assertion inscripts/nextflow_stub_test.sh. - DuckDB reads masked failures as empty results (#61). Both chunked-read paths
(
_read_parquet_chunk,run_feature_sql) retried on any exception and then returned an empty DataFrame — indistinguishable from a legitimate 0-row read, so a persistently failing feature silently dropped those samples (iter_feature_chunksskips an "empty" chunk). They now classify the error:OperationalError(I/O, resource, OOM) backs off and retries, and raises if it never succeeds;ProgrammingError/DataError(bad column, malformed SQL, type mismatch) raises immediately — no wasted retries, no masking. The legitimate "no files found" case still returns empty. - eval_engine masked errors as low scores (#61). Two broad excepts turned real failures
into a
0.0:mutual_info_scorescored a feature 0 on any exception, and the ablation inner-CV appended0.0for a fold that raised. Both benign degenerate cases (constant feature, <2 classes, too-few-samples, empty folds) are handled explicitly before these points, so both now raise with context instead. The four legitimate degeneratereturn 0.0cases are preserved. A new shared_numeric_feature_columnshelper replaces two duplicatedselect_dtypes(include=np.number)filters and loudly flags any non-metadata column that is unexpectedly non-numeric (an object-dtype feature that would otherwise be dropped silently), consolidating the two sites into one implementation. - GPU retry ladder never engaged (#59). The GPU eval/ablation/multimodal wrappers always
exited 0 (emitting an error-JSON on failure) to avoid a
collect()deadlock — but that also meanterrorStrategy='retry'never fired, so the 64→256 GB /gpushort→gpuescalation was dead code for transient CUDA OOM. The wrappers now fail loud on non-terminal attempts (exit non-zero → the ladder climbs) and only degrade gracefully (error-JSON + exit 0) once retries are exhausted, preserving the channel-closing invariant that prevents the deadlock (see commits698c72e/dcfe356). - Silent evaluator drop on ablation failure (#60).
kreview_eval.nfpaired each matrix with itsbest_subsetviacombine(by:0)— an inner join — so an evaluator whose ablation failed and was ignored upstream was silently dropped from both CPU and GPU eval (missing from results entirely, with no error). Now usesjoin(by:0, remainder:true)with aNO_BEST_SUBSETfallback (identical to the ablation-off path) and a loud per-evaluator warning, so the evaluator is degraded-but-present, never dropped. This is also strictly safer than the oldcombine+.ifEmptyguards when the whole ablation channel is empty. - Failed evaluators masked as blank rows (#59/#60). A GPU wrapper that exhausts its retry
ladder emits
{"error": ...}; the scoreboard rendered that as an innocent all-NaN row. The scoreboard now carries astatuscolumn (OK/PARTIAL/FAILED/NO_RESULTS) with anerror_detail, logs degraded evaluators loudly, and no longer drops an evaluator that throws during metric extraction (emits aFAILEDrow instead). Both report templates show thestatuscolumn and a "Degraded evaluators" callout, and their stalekreview runfallback text (removed in #55) was corrected to the Nextflow invocation.
Added
scripts/test_nextflow_join_dropguard.nf— a standalone channel-logic regression test for #60 (3 matrices, 2 best_subsets → all 3 survive with a fallback). Run byscripts/nextflow_stub_test.sh, which also structurally asserts the #59 retry guard is present in all three GPU wrappers.
Removed
kreview run(monolithic pipeline command) and everything that existed only to serve it: the NextflowKREVIEW_RUNprocess (run.nf), theparams.pipeline_modeswitch, and itswithNameresource block. The Nextflow multistage DAG is now the only way to run the pipeline.kreview runwas a second, drifting implementation of the whole pipeline — the largest single source of the fix-one-path-miss-the-other bugs (see #55) — and was neither used nor exercised by CI. Individual stages remain available as subcommands (kreview label|extract|select|eval|fuse|report) for debugging.--export-duckdb. It existed only onkreview runand was unreachable from the Nextflow DAG, so it was never usable on HPC. Feature matrices are written as parquet under the output directory and can be queried directly with DuckDB or pandas.- Four orphaned Nextflow modules (
eval_cpu.nf,eval_gpu.nf,select.nf,eval_multimodal.nf). They were included by zero workflows and encoded an older DAG that ran straight offEXTRACT, bypassingSELECT/ABLATE— re-enabling one would have produced different, incorrect results.
Fixed
nextflow.configwould not parse on Nextflow 24 or newer (#80), so the pipeline could not start at all on a current Nextflow — an outright adoption blocker, and invisible because nothing in CI ran Nextflow. Three constructs were rejected by the modern config parser:try/catcharound the nf-core institutionalincludeConfig. Replaced with the nf-core ternary idiom, which also honoursNXF_OFFLINE(anifstatement is rejected too).- Five
${manifest.version}references in container tags —manifestis not resolvable fromprocess/profilesscope. The version now lives inparams.kreview_version, which the manifest reads back, so there is still exactly one version literal in the file. ${HOME}interpolation in the SingularitycacheDir, nowenv('HOME').- Stale
withName:selectors forKREVIEW_EVAL_CPU/KREVIEW_EVAL_GPU, left behind when the Gen-1 bulk modules were deleted. They matched no process and made Nextflow warn on every run; the resource settings they carried applied to nothing.
Added
- Nextflow stub smoke test (
scripts/nextflow_stub_test.sh, and astubprofile). Every process now declares astub:block, so-stub-run -profile stubexercises the entire DAG — config parsing, all four profiles, module includes and channel wiring — in seconds without data or containers. CI runs it against both ends of the supported range. It asserts fromexecution_trace.txtthat all 17 processes ran and every task reachedCOMPLETED, and fails on anywithName:selector naming a process that does not exist.
Changed
- Documentation now presents a single run path.
--pipeline_mode multistageis no longer needed (or accepted); use-profile dockerlocally and-profile iris/slurmon HPC. - Supported Nextflow range is now declared and enforced: v25–v26.
manifest.nextflowVersionwas!>=22.10.1, an unbounded floor that let a modern Nextflow get far enough to fail with a cryptic parse error. It is now!>=25.04.0(the floorenv()requires), verified against 25.04.6, 25.10.6 and 26.04.6.
[0.0.28] - 2026-07-09
Fixed
- Silent Report Failures:
kreview reportnow exits with code1when any dashboards fail to render, enabling Nextflow to retry with higher memory allocations. Previously exited0even when multiple reports failed. - ValueError in Feature Plotting: Added a fallback in
report_template.qmdwhen the univariatetop_col(selected by eval_stats) is filtered out during feature selection or matrix fusion. Falls back to the first available numeric column instead of crashing Plotly. - CUDA OOM on Shared GPU Nodes: Added
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:Trueto theKREVIEW_MULTIMODAL_SINGLE_GPUNextflow process, reducing PyTorch memory fragmentation on shared Slurm nodes. Prevents TabICL_ft failures from CUDA allocation errors. - IPython Home Path on HPC: Exported
IPYTHONDIR="$PWD/.ipython"inreport.nf,report_multimodal.nf, andmultimodal_single.nfto prevent errors when/homeis read-only on HPC Singularity nodes. - Healthy Normal Specificity = 0.0 in Multimodal Stacking: The stacking matrix parquet files did not carry the original 4-tier label text (e.g. "Healthy Normal", "Possible ctDNA-"), so
evaluate_model()could not compute sensitivity at 100% healthy-normal specificity. Fixed by plumbingoof_sample_labelsthrough the full pipeline: evaluator JSONs → baselines loader → stacking matrix alignment → parquet persistence →evaluate_model()in all paths (decomposed Nextflow + monolithickreview run).
Added
_sample_labelColumn: Thestacking_matrix.parquetandraw_features_matrix.parquetoutputs frommultimodal_prep()now include a_sample_labelcolumn carrying the 4-tier text labels. This enables downstream consumers (multimodal_single, dashboard) to compute per-label-tier specificity without joining back tolabels.parquet.
[0.0.27] - 2026-06-25
Fixed
- GPU Stacking random_state Duplicate: Resolved a
TypeError: got multiple values for argument 'random_state'occurring during fine-tuning of TabPFN and TabICL GPU multimodal models inmultimodal_eval()andmultimodal_single(). This was caused byrandom_statebeing passed as both a positional argument and duplicated via unpackedgpu_kwargs. - Baseline Best Metric Recovery: Fixed a bug in
_load_per_evaluator_baselines()wherebest_modelandbest_auckeys were resolved asNonefrom the source model JSONs. They are now dynamically computed from the model's actual OOF AUC values. - Nextflow GPU Singularity Path: Added symlinks for
python3andpythonto/usr/local/bininside the Dockerfile, and replaced container python sub-processes with nativegrepextraction inmultimodal_single.nf's script blocks. This preventspython3command not found (exit code 127) errors triggered by Singularity path-stripping behavior on HPC nodes. - GPU Pipeline Deadlock Avoidance: Configured
KREVIEW_MULTIMODAL_SINGLE_GPUto catch non-zero exit codes during evaluation failures and output an error metadata JSON instead of terminating the pipeline immediately. This prevents Nextflow's.collect()channel from deadlocking when a GPU node experiences a runtime error. - Resource Limits Hardening: Bumped
KREVIEW_ABLATE_CPU_SINGLEmemory allocation from 32 GB to 64 GB to prevent OOM errors on large transcription factor annotation matrices, and bumpedKREVIEW_EXTRACTwalltime to 1.5h.
Added
- Dashboard Readiness Column: Appended the unique
_sample_idcolumn to both the multimodalstacking_matrix.parquetandraw_features_matrix.parquet. This enables joining multimodal predictions back tolabels.parquetfor per-label-tier (e.g. Healthy Normal) and per-cancer-type performance comparisons in the kreview dashboard.
[0.0.26] - 2026-06-23
Fixed
- BorutaShap Import: The pip package
BorutaShapPlusprovides an importable module namedBorutaShap, notBorutaShapPlus. Correctedfrom BorutaShapPlus import BorutaShap→from BorutaShap import BorutaShapineval_engine.py. This was the root cause of multimodal pipeline failures in v0.0.24 and v0.0.25 — previously misdiagnosed as a container build issue. - Test Skip Guard: Fixed
test_boruta_shap_passes_throughwhich usedimport BorutaShapPlusas its skip guard. Since the module name isBorutaShap, the test was always being silently skipped even when the package was correctly installed. - Report Memory (OOM): Bumped
KREVIEW_REPORTandKREVIEW_REPORT_MULTIMODALmemory from 32 GB → 64 GB base (128 GB on retry). In v0.0.25, 8/26 reports OOM'd at SHAP summary plot computation (cell 31/53) and 3/26 OOM'd at pandoc--embed-resourcesHTML self-containment. Evaluators with 270+ features at--shap-samples 5000require more memory than the 32 GB allocation.
[0.0.25] - 2026-06-22
Fixed
- Container Dependencies: Moved
papermill>=2.5.0from[jupyter]optional extra to core dependencies. Quarto's--execute-params(-P) flag requires papermill at runtime, and the CPU Docker container did not include it — causing all 26 evaluator reports to fail on HPC with"The papermill package is required for processing --execute-params". - BorutaShapPlus Container Availability: Ensured
BorutaShapPlus>=0.1.3(already in core deps since v0.0.24) is present in rebuilt containers. The v0.0.24 container was built from a stale state, causing multimodal prep to fail with"No module named 'BorutaShapPlus'"and cascading failure of the entire multimodal pipeline chain.
[0.0.24] - 2026-06-18
Added
- ARFS Feature Selection: Added Leshy (Boruta+LightGBM/SHAP) and GrootCV (cross-validated SHAP importance) as
--multimodal-selectionoptions. Install viapip install kreview[arfs]. - Strategy Validation:
_select_multimodal_features()now raisesValueErroron unknown strategy names instead of silently falling through to MI ranking. Typos like--multimodal-selection borta_shapare caught immediately. - MI-Reduction Helper: Extracted
_mi_reduce_confirmed()to deduplicate the >500-feature MI reduction logic across Boruta-SHAP, Leshy, and GrootCV strategies. - Tests: Added
test_invalid_strategy_raises,test_valid_strategies_constant,test_leshy_passes_through, andtest_grootcv_passes_throughtotest_selection.py.
Changed
- BorutaShap → BorutaShapPlus: Migrated from
BorutaShap>=1.0.17toBorutaShapPlus>=0.1.3with scipybinom_testand NumPynp.NaNcompatibility shims.
Fixed
- Quarto EROFS on Read-Only Singularity: Quarto 1.9+ creates a
.quarto/project directory next to the QMD source. Inside read-only Singularity containers, this failed withEROFS (error 30). Templates are now staged to a writable.render_{feat_name}/directory beforequarto render. - Report publishDir Double-Nesting: Fixed
publishDir "${params.outdir}/reports"→"${params.outdir}"inreport.nfandreport_multimodal.nfto preventresults/reports/reports/nesting. - GrootCV Constructor: Fixed invalid parameters (
estimator,n_iterations,cv) → correct ARFS API (objective="binary",n_folds=5,n_iter=50,silent=True). - Leshy Constructor: Fixed
n_iter(not a valid param) →max_iter=50; addedn_estimators=1000,verbose=0. - Test Import: Updated
test_selection.pyskip guard fromimport BorutaShaptoimport BorutaShapPlus.
[0.0.23] - 2026-06-16
Fixed
- Scoreboard Nextflow Quote-Escaping: Replaced
python3 -c "..."with bash heredoc (python3 << 'EOF') inscoreboard.nfto prevent Nextflow shell interpolation from stripping escaped quotes, which causedNameError: name 'evaluator' is not definedandKREVIEW_SCOREBOARDfailing all retry attempts. - scipy.stats Version Attribute: Fixed
AttributeErrorin thebinom_testcompatibility shim by importingscipy(top-level) instead of accessing__version__onscipy.stats(which has no such attribute). This causedKREVIEW_MULTIMODAL_PREPto crash when--multimodal-selection boruta_shapwas used (scipy ≥1.12). - Quarto HPC Cache Permissions: Export
XDG_CACHE_HOMEandXDG_DATA_HOMEto writable local paths inreport.nfandreport_multimodal.nf, preventing Quarto from failing on HPC compute nodes with read-only~/.cachedirectories.
[0.0.22] - 2026-06-11
Fixed
- WPSGenome MAD Memory Optimization: Replaced the nested Python loop that materialized ~446M rows in memory with a DuckDB-native window function query, reducing peak memory usage to under 100MB and runtime to ~7s.
- GPU Ablation TypeError: Fixed a bug where
_build_ablation_model_factoriescalledGPUModelCVAdapterdirectly with invalidmodel_nameargument instead of using_build_gpu_modelbuilder, causing GPU ablation to silently fail and default toALL.
[0.0.21] - 2026-06-10
Performance
- WPSGenome SQL pushdown: Uses DuckDB native
list_avg(),list_max(),list_min()to aggregate 1.9B rows inside DuckDB instead of materializing in pandas. Reduces peak memory from 96+ GB to ~17 GB. - DuckDB resource tuning: Default threads 4→8, memory 4GB→32GB,
exposed via
--duckdb-threads/--duckdb-memoryCLI options. - Nextflow KREVIEW_EXTRACT: cpus 4→8, memory 32GB→64GB per attempt, maxRetries 7→3 (SQL pushdown eliminates the memory ladder).
Added
configure_duckdb()API for pre-connection resource configuration.--duckdb-threadsand--duckdb-memoryCLI options onextractandruncommands.sql_pivot_columnevaluator property for multi-row SQL result pivoting.- Exact MAD hybrid computation via second lightweight DuckDB query.
- Nextflow params:
duckdb_threads,duckdb_memory.
Fixed
- Nextflow resilience: Added explicit
errorStrategy+maxRetriesto 14 processes that relied on global defaults. One failed evaluator no longer terminates the entire pipeline — it is ignored after 3 retries. - KREVIEW_FUSE uses
terminate(notignore) since downstream processes depend on the super-matrix. - Added
ifEmptychannel guards on EXTRACT→SELECT and GPU ablation.combine()to prevent pipeline deadlocks when upstream processes are ignored. - Added missing
withNameconfig blocks forKREVIEW_MULTIMODAL_SINGLE_CPU,KREVIEW_MULTIMODAL_SINGLE_GPU, andKREVIEW_MULTIMODAL_MERGE.
Changed
get_duckdb_conn()defaults: 8 threads, 32GB memory (was 4 threads, 4GB).
[0.0.20] - 2026-06-09
Added
- Feature Group Ablation:
kreview eval ablate {cpu,gpu,merge}CLI commands for nested CV feature group selection. Identifies suffix-based feature groups, evaluates all subsets via inner CV, and picks the optimal subset per model per fold usingsensitivity_at_100spec_healthy. - Nested CV Pipeline: Per-model per-fold feature subsets flow from ablation → merge → eval via
--best-subset. Supports both CPU (LR/RF/XGB) and GPU (TabPFN/TabICL) models. - Nextflow Ablation Stages: 3 new modules (
ablate_cpu_single.nf,ablate_gpu_single.nf,merge_ablation.nf) wired intokreview_eval.nfbehindparams.run_ablationflag. All stages run in parallel per evaluator. - Scoreboard Columns:
nested_cvflag andbest_sens_100spec_healthy(best sensitivity across ALL models) added tobuild_scoreboard(). - Bootstrap CIs:
_compute_oof_metrics()produces 95% bootstrap CIs for AUC, sensitivity@100%spec, and all clinical metrics. - GPU Subgroup Stats:
gpu_models()now reportsassay_statsandcancer_type_statsfor subgroup analysis. - Test Suite:
tests/test_ablation.pywith 17 tests covering feature grouping, subset generation, OOF metrics, backward compatibility, and scoreboard.
Changed
eval cpuandeval gpuaccept optional--best-subsetfor nested CV with per-fold feature subsets.eval_cpu_single.nfandeval_gpu_single.nfaccept optionalbest_subsetinput channel (backward compatible via sentinel file).nextflow.config: new paramsrun_ablation(default: false),ablation_inner_folds(default: 3).
[0.0.19] - 2026-06-08
Fixed
- WPSGenome Extraction Failure: Removed broken SQL pushdown (
extract_sql()) that usedtrim(col, '[]')on nativelist<float>arrays, silently producing NULL results. Replaced with pure-Pythonextract()using_to_array()helper that handles numpy arrays, Python lists, and legacy string-encoded arrays. Added_to_array()as a public utility. - WPSGenome Last-Row-Wins Bug: Rewrote
extract()to aggregate per-region-type (TSS, CTCF) statistics across all regions instead of overwriting with the last row. Now computes mean, peak_valley, std, and MAD of per-region array means. - WPSPanel Last-Row-Wins Bug: Rewrote
extract()to aggregate per-region-type (TSS, CTCF) statistics across all panel regions (~59-85 rows per type) instead of overwriting with the last row.local_depthnow averaged across panel regions instead of using last value. - GPUModelCVAdapter Serialization: Added
__getstate__/__setstate__to exclude unpicklablemodel_factorylambda from pickle. Deserialized adapters work for inference (predict_proba) but raiseTypeErroronfit()— preventing silent misuse. - Joblib Corrupt File Detection:
_save_fitted_models()now validates post-write file size (>100 bytes) and deletes truncated files. Error-level logging replaces silentlog.warning. Partial files from failedjoblib.dump()are cleaned up. parse_array()Numpy Passthrough: Now handles numpy arrays and Python lists as input (passthrough), not just string-encoded arrays. Previously returned[]for native parquetlist<float>data, causing silent data loss.
Changed
- WPSBackground Cleanup: Removed bare
try/exceptfor consistency with WPSGenome/WPSPanel. Errors now propagate to CLI handler. Added structured logging for empty/success cases with feature counts and chromosome counts. Metrics list moved to class constant_metrics.
Removed
- WPSGenome SQL Pushdown: Removed
extract_sql(),sql_pivot_column, and CLI pivot code. See v0.0.17 entry — the SQL path was fundamentally incompatible with native array storage. - WPSGenome FFT Features: Dropped
spectral_max_powerandspectral_dominant_freq. Empirical analysis (r=0.91–1.00 with basic stats) proved FFT is redundant with mean/std/peak_valley. Nucleosome periodicity is captured byWPSBackgroundEvaluator. - WPSPanel
spectral_max_power: Removed — real-data analysis (4 patient samples) showed r=0.90–1.00 withstdafter per-region-type aggregation.spectral_dominant_freqretained (38.5% CV inwps_tfacross samples — potentially informative for curated TSS/CTCF loci).
[0.0.18] - 2026-06-05
Added
- Fine-tuned GPU Model Variants:
tabpfn_ftandtabicl_ftviaFinetunedTabPFNClassifierandFinetunedTabICLClassifierwith configurable--finetune-epochs(default: 50) and--finetune-lr(default: 1e-5). Total GPU model count: 4 (was 2). GPUModelCVAdapter: sklearn-compatible wrapper ineval_engine.pythat resolvesAttributeError: 'FinetunedTabPFNClassifier' has no attribute 'classes_'duringcross_val_predict. Exposesclasses_as a plain attribute set duringfit().kreview eval multimodalnested subgroup: 5 subcommands —run(monolithic backward-compat),prep,single,ablation,merge.- Decomposed multimodal Nextflow pipeline: 4 new NF modules (
multimodal_prep.nf,multimodal_single.nf,multimodal_ablation.nf,multimodal_merge.nf) enabling per-model parallel execution. Legacyeval_multimodal.nfkept for standalone testing viakreview eval multimodal run. - GPU foundation model expansion: 4 GPU model variants (
tabpfn,tabpfn_ft,tabicl,tabicl_ft) evaluated per-evaluator in parallel viaKREVIEW_EVAL_GPU_SINGLE. Each process runs all requested GPU models and outputs a single{evaluator}_gpu_model_results.json. - Intentional 7-color palette: Vanilla/FT shade families (
#00e5ff/#00b0fffor TabPFN,#76ff03/#64dd17for TabICL) in report templates. - Stacking feature selection: MI or Boruta-SHAP on stacking matrix via
--stacking-selection. - Decomposed NF resource configs: Per-process
withNameblocks forKREVIEW_MULTIMODAL_PREP,KREVIEW_MULTIMODAL_SINGLE_GPU, andKREVIEW_MULTIMODAL_ABLATION.
Changed
- Default
--gpu-models→tabpfn,tabpfn_ft,tabicl,tabicl_ft(4 models, was 2). kreview eval multimodaluses nested Typer sub-commands (was flat hyphenated commands).- NF config: decomposed process resource configs replace monolithic
withName: 'KREVIEW_EVAL_MULTIMODAL'. - Report
_name_mapincludesTabPFN-FTandTabICL-FTdisplay names. multimodal_cpu_onlyNF param marked as legacy (decomposed pipeline routes CPU/GPU per-process).
Removed
--no-finetuneCLI flag (use--gpu-models tabpfn,tabiclfor zero-shot only).- Dead
KREVIEW_EVAL_MULTIMODALimport fromkreview_eval.nf.
Fixed
- TabPFN
AttributeError: 'FinetunedTabPFNClassifier' has no attribute 'classes_'viaGPUModelCVAdapterwrapper. - Stale
multimodal-prep(hyphen) references in CLI help strings →multimodal prep(space). - Stale DAG comments in
eval_cpu_single.nf,eval_gpu_single.nf,report_multimodal.nfreferencing removedKREVIEW_EVAL_MULTIMODAL.
[0.0.17] - 2026-06-04
Added
- GPU Model Pre-flight Validation:
_validate_gpu_models()incli_eval.pyverifies GPU model packages are installed andTABPFN_TOKENis set before any work begins. Shared acrosseval gpu,eval multimodal, and monolithicruncommands. Exits with code 1 and actionable instructions on failure.
Fixed
- OOF Sample IDs Alignment (P0):
oof_sample_idsscoped to train-split only in CPU, GPU, and monolithic paths to matchoof_probslength fromcross_val_predict. Addedoof_sample_idsandoof_labelsto merge skip set preventing GPU from overwriting CPU alignment keys. This was the root cause of multimodal stacking failure ("25 had IDs but no probs"). - BorutaShap scipy Compatibility (P1): Monkey-patched
scipy.stats.binom_testwithbinomtest().pvaluewrapper for BorutaShap compatibility on scipy ≥1.12 (removed in 1.12). EliminatesImportError: cannot import name 'binom_test'in multimodal raw feature selection. - Scoreboard Crash Handling (P2): Added try/except with traceback to
scoreboard.nfinline Python. Moved file writes inside try block. AddedKREVIEW_SCOREBOARDwithName config block (retry 3×, then ignore). Added per-evaluator try/except inbuild_scoreboard()so a malformed evaluator result doesn't kill the scoreboard for all evaluators. - WPSGenome Timeout (P3): Implemented DuckDB SQL pushdown (
extract_sql()) forWPSGenomeEvaluator— parses string-encoded arrays vialist_avg/list_max/list_minin C++. Addedsql_pivot_columnfor tall-to-wide pivot in CLI. Usedpivot_table(aggfunc='first')for duplicate safety with null guard on pivot failure fallback. Added time/queue escalation innextflow.config(retries 3+ →cmobic_cpu8h). Note: This SQL pushdown was later found to be broken — krewlyzer stores arrays as nativeFLOAT[], not string-encoded. Removed in [Unreleased]. - GPU Silent Failure Logging (P4): Record per-model error keys (
{model}_error) in GPU results dict. Detect all-models-failed state and setresults["error"]. Added visible⚠ WARNINGstdout output in bothcli_eval.pyand monolithiccli.py. - REPORT Blocked by SCOREBOARD (P5): Guarded REPORT channel with
.ifEmpty(file('NO_SCOREBOARD'))so reports render even when scoreboard fails. Templates already checkscoreboard_path.exists(). - REPORT_MULTIMODAL SLURM Rejection: Added
withName: 'KREVIEW_REPORT_MULTIMODAL'config block with explicitqueue = params.partition ?: 'cmobic_short'. Previously fell through toprocess_mediumlabel which lacked a queue directive, causing iris institutional config to inject the inaccessiblecpupartition into sbatch. - Nextflow Channel Deadlocks: Added
.ifEmpty([])guards on JSON collect, joblib collect, and GPU collect channels to prevent pipeline deadlock when tasks fail witherrorStrategy = 'ignore'. - Pivot Crash on Duplicate Rows: Switched from
pivot()topivot_table(aggfunc='first')in CLI wide-pivot for WPSGenome tall-to-wide conversion, preventingValueError: cannot reshapeon duplicate region_type rows. - Null Guard on Pivot Failure: Added null check on
feat_matrixafter pivot failure fallback, preventingAttributeError: NoneType has no attribute 'columns'. - Queue Directive Safety Net: Added
queue = params.partition ?: 'cmobic_short'toprocess_mediumandprocess_highlabel defaults. Prevents any future process from failing SLURM submission due to missing partition.
Changed
- Version Bump:
__init__.py,settings.ini,nextflow.config→0.0.17. - Version-agnostic
run_hpc.sh: Auto-detects version fromnextflow.configat runtime. DynamicGPU_MODELSbased onTABPFN_TOKENavailability. No manual edits needed between releases.
[0.0.16] - 2026-06-03
Added
- 80/20 Stratified Holdout Validation:
_assign_train_test_split()inCtDNALabeler.label_all()assigns asplitcolumn (train/test/exclude) tolabels.parquet. Split is stratified by 4-tier label withrandom_state=42for reproducibility.evaluate_holdout()ineval_engine.pyprovides unbiased AUC estimates on the held-out 20%. - Sensitivity at Fixed Specificity:
evaluate_model()now computes sensitivity at 100%, 99%, and 95% specificity, plus a healthy-normal-only variant usingsample_labels. 12 new JSON fields per model. - Intelligent GPU Feature Capping:
gpu_models()accepts--max-gpu-features(default: 150) and caps features using score-based priority (MI > AUC > variance). Returnsgpu_feature_cap_indicesfor holdout dimension consistency. - CH-Only → Undetermined Label: Samples with
n_non_ch_variants == 0and no SV/CNA/IMPACT match are now labeledUndetermined(was:Possible ctDNA−).Undeterminedis excluded from binary classification viabuild_binary_target(). - WPSGenome Streaming:
extract_columnsandmax_chunk_rowsclass attributes onFeatureEvaluatorenable DuckDB column projection and chunked reads. WPSGenome setsmax_chunk_rows = 5_000_000and projects to 4 columns, reducing peak memory ~80%. - Scoreboard Enhancements:
build_scoreboard()surfacessens_at_100spec,holdout_auc,holdout_sens_100spec,holdout_n_train/n_test, andauc_drop(CV overfit diagnostic). LABEL_UNDETERMINEDConstant:CtDNALabeler.LABEL_UNDETERMINED = "Undetermined"added alongside existing 5-tier constants.- Report Value Boxes: Both
report_template.qmdandreport_multimodal_template.qmdnow display "Sens @ 100% Spec" (with detection count) and "Holdout AUC" (with dynamic color: green/yellow/red by AUC drop severity) in the Executive Summary. - Report Clinical Metrics: Model summary tables auto-discover and display
Sens@100%Spec,Sens@95%Spec, andHoldout AUCper model. - Report Scoreboard Expansion: Scoreboard display expanded from 7 to 13 columns (
best_model,holdout_auc,auc_drop,sens_at_100spec,sens_at_95spec,holdout_n_train,holdout_n_test).
Changed
- Feature Selection Train-Only:
score_features()andselect_features()(mRMR + hybrid paths) now filter tosplit == "train"before scoring, preventing test set leakage into feature rankings. LABEL_META_COLS: Addedsplitto the 22-entry meta column set incore.pyto prevent it from leaking into feature matrices.- Nextflow GPU Module:
eval_gpu_single.nfnow stageseval_statsparquet and passes--eval-stats-dir+--max-gpu-featuresto the CLI. - Nextflow Workflow:
kreview_eval.nfwiresSELECT.out.eval_stats→EVAL_GPU_SINGLE. - Version Bump:
__init__.py,settings.ini,nextflow.config→0.0.16. - Report
meta_colsDynamic Import: Both templates now importLABEL_META_COLSfromkreview.coreinstead of maintaining a stale hardcoded copy. Prevents label metadata columns from leaking into feature sets. - Report Glossary: Added
Undeterminedlabel definition and train/test split documentation to both template glossary sidebars. MODEL_LABELS/POSITIVE_LABELSPublic API: Promoted from private_MODEL_LABELS/_POSITIVE_LABELSinselection.pyto public exports. Backward-compat aliases maintained.
Fixed
- GPU Holdout Dimension Mismatch:
cli.pyandcli_eval.pynow applygpu_feature_cap_indicestoX_testbefore callingevaluate_holdout(), matching the capped training feature space. - Data Leakage in mRMR/Hybrid Selection: Both
select_features()code paths now restrict MI scoring to train-only rows. - Unused Import: Removed
pandasimport fromreport.py(F401). - Boolean Comparisons: Replaced
== Falsewith~operator inlabels.py(E712). - Ambiguous Variable: Renamed
l→lblin list comprehensions ineval_engine.py(E741). - Nested If Statements: Merged nested
ifblocks ineval_engine.pyandregistry.py(SIM102). - Ternary Simplifications: Converted if/else blocks to ternary in
eval_engine.py(SIM108). - Test Lint: Removed 5 unused imports from test files and fixed 7 E712/SIM108 in test assertions.
[0.0.15] - 2026-06-01
Added
- CPU+GPU JSON Merge Helpers:
load_model_results(directory, evaluator_name)andload_all_model_results(directory)ineval_engine.pytransparently discover and merge*_model_results.json(CPU) and*_gpu_model_results.json(GPU) files. GPU model keys (AUC, OOF probs, SHAP) are merged into the CPU dict. Used by report templates, scoreboard, and multimodal engine. - KREVIEW_SCOREBOARD: New Nextflow process (
scoreboard.nf) generatesscoreboard_combined__all.parquetafter all CPU/GPU eval jobs complete. Usesbuild_scoreboard()which now callsload_all_model_results()for unified GPU+CPU scoring. - GPU Exit Code:
kreview eval gpunow exits with code 1 if NO models produced valid AUC results (was silent success). Prevents Nextflow from treating empty GPU results as success. - Unit Tests: 11 new tests in
test_merge_helpers.pycovering CPU-only, GPU-only, CPU+GPU merge, malformed JSON, and directory scan scenarios.
Changed
- GPU JSON Output Naming: GPU eval module now produces
*_gpu_model_results.json(was*_model_results.json), preventing filename collision when CPU and GPU outputs are collected into the same Nextflow channel. - Report Input Signature:
KREVIEW_REPORTnow accepts 6 inputs (matrices, model_results, eval_stats, selection_qc, joblib_files, scoreboard) for complete dashboard rendering. - Workflow Wiring:
kreview_eval.nfcreates unifiedch_all_jsonsandch_all_joblibchannels that mix CPU+GPU outputs, feeds them to SCOREBOARD → REPORT. - Scoreboard Loading:
build_scoreboard()now usesload_all_model_results()instead of manual glob+load loop. - Multimodal Baselines Loading:
_load_per_evaluator_baselines()now usesload_all_model_results()instead of manual glob+load loop. - FSD Density Calculation: Added
select_dtypes(include="number")filter before density computation infsd.pyandfsd_genomewide.pyto prevent TypeError on non-numeric metadata columns. - Multimodal NF Module: Removed unnecessary staging loop —
--results-dir .uses Nextflow work dir symlinks directly. - Dockerfile Optimization: Selective builder
COPY(onlypyproject.toml,kreview/,LICENSE), singlepip install "${WHL}[gpu]"pass to ensure local wheel resolution, droppedpython3.12-devandwgetfrom GPU runtime, merged OCI labels into singleLABELinstruction. - CI Parallelism:
test.ymlsplit into paralleltest(Python) anddocker(matrix[cpu, gpu]) jobs withfail-fast: false. GPU build getsjlumbroso/free-disk-spacecleanup (~20-30 GB freed). .dockerignore: Expanded to excludedocs/,nextflow/,scripts/,tests/,.github/,.agents/— reduces build context transfer.
Fixed
- OOF Label Key Search:
"oof_labels".endswith("_oof_labels")isFalse— fixed to check both exact match and suffix match. Applied to bothreport_template.qmdandreport_multimodal_template.qmd. - FSD TypeError: Non-numeric columns (e.g.,
sample_id,filename) causedTypeError: ufunc 'divide' not supportedin FSD density calculation. Now filtered to numeric columns only. - Multimodal Validation Logging: Now shows CPU vs GPU JSON counts separately for better debugging.
- Docker GPU Build CI Failure: GPU image build exceeded runner disk space (~14 GB free). Fixed by adding
jlumbroso/free-disk-spaceaction and optimizing Dockerfile layers.
Removed
tabpfn-extensions[interpretability]from[gpu]extras — unused since v0.0.13 (SHAP computation replaced byshapiq). Eliminatestransformers,wandb,huggingface-hub,tokenizerstransitive dependencies (~500 MB).- Deprecated HPC scripts:
run_hpc_0.8.3.sh,run_hpc_v0.0.10.sh,run_hpc_v0.0.11.sh,runner.sh,utils/symlinker.py— replaced by unifiedscripts/run_hpc.sh.
Breaking Changes
- GPU JSON output renamed:
{eval}_model_results.json→{eval}_gpu_model_results.json KREVIEW_REPORTinput signature expanded from 2 to 6 inputs
[0.0.14] - 2026-05-25
Added
- Reproducibility Seed:
--seedCLI flag onrun,eval cpu,eval gpu,eval multimodal, andselectcommands (default: 42). - Deterministic Mode:
--deterministic / --no-deterministicflag for PyTorch cudnn (default: True) on all eval commands. kreview/reproducibility.py:seed_everything()utility for Python, PyTorch, and cuDNN seeding.- Nextflow Params:
seedanddeterministicparams innextflow.config, forwarded through all 8 pipeline modules. - Reproducibility Docs: New section in
models-and-metrics.mddocumenting seed propagation strategy.
Fixed
- 3 hardcoded
random_state=42in_select_multimodal_features()now accept caller seed. - 7 internal forwarding gaps where
random_statewas not passed to child functions. - GPU models (TabPFN, TabICL) now receive
random_stateparameter via_build_gpu_model(). shapiq.TabularExplainerandshap.PermutationExplainernow seeded for reproducible SHAP values.BorutaShap.fit()now receivesrandom_statefor deterministic feature selection.- SLURM Partition Routing: All
withNameprocess blocks now pinqueueexplicitly to bypass the nf-core iris institutional config's dynamic queue closure that injects the inaccessiblecpupartition intosbatch -p. - KREVIEW_LABEL Error Strategy: Changed from inherited
'ignore'(from iris config) to'terminate'— pipeline aborts immediately if labeling fails instead of deadlocking.
[0.0.13] - 2026-05-24
Added
- GPU Foundation Models: TabPFN v8.0.3 and TabICL v2.1 support via
_build_gpu_model()with updated import paths (tabpfn.TabPFNClassifier,tabicl.TabICLClassifier). - shapiq Integration: SHAP values for GPU models now computed via
shapiq.TabularExplainer(model-agnostic kernel-based Shapley values), replacing the deprecatedtabpfn-extensionsinterpreter. - Unified Model Persistence:
_save_fitted_models()helper incli_eval.pyprovides consistent joblib saves for both CPU and GPU models.--skip-gpu-joblibflag opts out of large GPU model files. - Multimodal GPU Models:
kreview eval multimodalnow accepts--gpu-models tabpfn,tabiclfor GPU-accelerated stacking and raw feature evaluation. - Pre-computed SHAP Fallback: Report templates render mean |SHAP| bar charts from JSON when joblib files are unavailable (e.g.,
--skip-gpu-joblib). - KREVIEW_REPORT_MULTIMODAL: New Nextflow process for rendering multimodal stacking dashboards in multistage mode.
- HPC Script v0.0.13: Updated SLURM launch script with GPU multimodal params, Boruta-SHAP selection, and top_percentile.
Changed
- Feature Selection:
--top-percentilereplaces--top-kfor MI-based feature selection. Percentage-based selection adapts to varying feature set sizes across evaluators. - Boruta-SHAP MI Reducer: When Boruta-SHAP confirms >500 features, an MI-based reducer narrows the set to
top_percentile(default 10%). - SLURM Hardening:
KREVIEW_LABELandKREVIEW_EVAL_GPU_SINGLEprocesses now setcache = 'lenient'andscratch = falseto prevent institutional queue/cache interference on IRIS. - Dynamic Report Rendering: ROC CI reverse-map, DCA loop, and AUC deltas now dynamically discover models from
DYNAMIC_MODELSinstead of hardcoding LR/RF/XGB.
Fixed
- ROC CI KeyError: Hardcoded
{"Logistic Regression": "lr", ...}reverse-map inreport_template.qmdreplaced with dynamic lookup fromDYNAMIC_MODELS, preventing crashes when GPU models are present. - DCA Loop: DCA now renders curves for all trained models (was hardcoded to RF/XGB only).
- AUC Deltas: Pairwise AUC delta display now discovers all
auc_delta_*keys dynamically. - Monolithic GPU Fitted Capture:
gpu_res, gpu_fitted = gpu_models(...)now captures fitted models (was_ = ...).
Dependencies
tabpfn >= 8.0.3(was>= 2.0)tabicl >= 2.1(was>= 0.0.4)- Added
shapiqfor GPU model SHAP computation.
[0.0.12] - 2026-05-24
Added
- Nextflow publishDir: All 8 multistage modules now publish outputs to
params.outdirwithmode: copy. Output structure:labels/,matrices/raw/,matrices/selected/,models/cpu/,models/gpu/,matrices/fused/,models/multimodal/,reports/. - Label-first DAG:
KREVIEW_LABELruns once as the first step in multistage mode, producinglabels.parquetshared across all extract jobs. Eliminates 26× redundant re-labeling (~13 min saved). --labelsCLI flag:kreview extractnow accepts--labels /path/to/labels.parquetto skip internal labeling and use pre-computed labels.- Boruta-SHAP in HPC script:
scripts/run_hpc_v0.0.11.shnow passes--multimodal_selection boruta_shapfor rigorous multimodal feature selection.
Changed
- Report DAG dependency: Report process now receives both matrices AND
*_model_results.jsonfrom CPU/GPU eval, enabling complete dashboard rendering (ROC, SHAP, metrics). Report runs in parallel with FUSE + MULTIMODAL. - Extract module:
extract.nfnow acceptslabels.parquetas input from upstreamKREVIEW_LABEL.
Documentation
- README: Comprehensive overhaul — added mRMR/Boruta-SHAP, GPU models, multimodal stacking, Nextflow HPC, pipeline architecture Mermaid diagram, fixed stale
--workersflag. - Statistical Tests: Detailed mRMR documentation (optimization objective, F-statistic/Pearson explanation, algorithm steps), Boruta-SHAP documentation (shadow features, SHAP importance, flowchart, configuration table, when-to-choose guide), fixed stale Selection QC keys.
- Nextflow Operations: Updated module list to match actual filenames, added
irisprofile docs, added publishDir output structure tree, addedparq-clitip. - Pipeline CLI: Fixed stale
--workers 4, added--labelsto extract example, added--ch-hotspot-maf, added label-first modular pipeline flow, addedparq-clitip. - Pipeline Architecture: Updated DAG (Label-first, Report parallel with Multimodal), fixed process table with actual
_single.nfmodule names, added publishDir column.
[0.0.11] - 2026-05-24
Changed
- Feature Selection (Default): Default single-evaluator strategy changed from
hybrid_uniontomrmr(Minimum Redundancy Maximum Relevance). mRMR selects features maximizing target correlation while minimizing inter-feature redundancy, preventing multi-collinearity. - Multimodal Selection:
--multimodal-selectionnow supportsboruta_shap(interaction-aware, SHAP-based) in addition tomi(mutual information, default). - CLI Log Output:
kreview selectandkreview runnow display method-aware selection summaries (mRMR shows variance-dropped count; hybrid_union shows AUC∩MI overlap breakdown).
Added
mrmr-selectiondependency: Addedmrmr-selection>=0.2.8topyproject.toml.BorutaShapdependency: AddedBorutaShap>=1.0.17topyproject.toml.- Structured startup logging:
kreview selectandkreview eval multimodalnow emitlog.info("select_start", ...)andlog.info("eval_multimodal_start", ...)at startup for machine-parseable audit trails. - Multimodal selection method persistence:
multimodal_results.jsonnow includesraw_features_selection_method("mi"or"boruta_shap"). - Selection Strategy value box: Multimodal dashboard executive summary displays the cross-evaluator selection strategy.
- Scoreboard
selection_methodcolumn: Now visible in both single-evaluator and multimodal dashboard scoreboard tables. - mRMR scatter disclaimer: When
strategy="mrmr", the Feature Selection scatter plot displays a callout explaining that AUC/MI axes are observational (mRMR uses F-statistic + Pearson correlation internally). - mRMR scatter coloring: Selected features labeled "Selected (mRMR)" with cyan color, distinct from hybrid_union's 4-way AUC/MI overlap coloring.
Fixed
KeyErrorcrash incli_select.py: Fixed crash when--strategy mrmrwas used — the log output tried to access hybrid-union-only QC keys (n_overlap_both,n_auc_only,n_mi_only).- Misleading
cli.pylog output:kreview run --strategy mrmrnow shows mRMR-specific summary instead of zeroed-out hybrid_union counts. - Stale docstrings: Updated module docstrings in
selection.py,cli_select.py,cli_eval.py, andeval_engine.pyto reflect mRMR as default.
[0.0.10] - 2026-05-22
Added
- Modular CLI: Extracted
runinto atomic sub-commands (label,extract,fuse,eval,select,report). - Nextflow DAG: Complete rebuild of monolithic pipeline into a multi-stage, per-evaluator parallelized workflow.
- GPU Evaluation: Native support for PyTorch-based GPU models (TabPFN, TabICL) via the
kreview eval --gpu-modelstarget. - Multimodal Models: Cross-evaluator stacking capability allowing evaluation of multiple fragmentomics assays simultaneously.
- Testing Optimizaton: Dropped unit testing execution time from >6min to <30s via module-scoped caching.
- Docker Containers: Stabilized multi-target release action generating discrete CPU and GPU containers cleanly.
[0.0.9] - 2026-05-07
Changed
- Feature Selection: Replaced Cohen's D
--top-nselection with hybrid union: top X% by Univariate AUC ∪ top X% by Mutual Information. This captures both linear and non-linear predictors. - CLI:
--top-ndeprecated (prints warning, ignored). Use--top-percentile(default: 10%) instead.--compute-univariate-aucnow defaults toTrue. - Volcano Plot: X-axis changed from Cohen's D to Univariate AUC for better alignment with model-based selection.
- Top-20 Bar Chart: Ranked by Univariate AUC instead of Cohen's D.
- Statistical Ledger: Sort priority changed to
univariate_auc > mutual_info > cohens_d > kw_statistic. - Feature Cards: Display AUC + MI scores instead of Cohen's D.
Added
mutual_info_score(): New function ineval_engine.pyusingsklearn.feature_selection.mutual_info_classif(k=3)for non-linear feature relevance scoring.selection_qcmetadata: Saved inmodel_results.jsonwith method, overlap stats, and feature counts for audit trail.- Feature Selection QC Scatter: New dashboard plot showing AUC vs MI with 4-color category coding (Both / AUC-only / MI-only / Dropped).
- Scoreboard columns:
selection_method,n_selected_features,selection_overlap_pct. - Structured logging:
feature_scoring_complete,feature_selection_complete,univariate_auc_disabled,variance_guard_dropped,model_skip_insufficient_data. - Resume checkpoint: Warns on legacy JSONs missing
selection_qc(pre-v0.0.9 Cohen's D runs). - Tests: 13 new tests for
univariate_auc(6) andmutual_info_score(7) covering bounds, NaN handling, constant features, signal detection, and reproducibility. - univariate_auc logging:
log.warning("univariate_auc_failed")replaces bare silentexcept.
Fixed
- Duplicate label mask (GAP-1): Removed duplicate 4-tier label mask construction; reuse scoring target for model target.
- Redundant import (GAP-3): Removed
import structlog as _sloginside evaluator loop; use module-levellog. - Silent degradation (GAP-4): Explicit warning when
--no-compute-univariate-aucdegrades to MI-only selection. - Double imputation (GAP-6): Cached
_impute()result in variance guard to avoid re-computation. - Silent model skip (GAP-7): Added echo + structlog warning when model eligibility fails (< 20 samples or single class).
[0.0.8] - 2026-05-06
Fixed
- AUC Consistency (D-01): ROC plots and KDE density now use out-of-fold predictions matching the official AUC value boxes. Eliminates the misleading AUC discrepancy (e.g., 0.845 vs 0.72) caused by mixing training/subsample models.
- Dashboard Crashes (D-02/D-03): All
cohens_d_true_vs_healthyreferences guarded with column existence checks. Statistical Ledger falls back tokw_statistic→univariate_aucwhen Cohen's D is unavailable. - Classification Labels (C-02): Confusion matrix and classification report now correctly show "ctDNA Negative" instead of "Healthy Normal".
- Fold Variability (C-01): Now displays all three models (LR, RF, XGBoost) with per-model std in title instead of hardcoded RF-only.
- Duplicate Imports (C-03): Removed redundant plotly import in report template.
- Volcano Hover (GAP-1): NaN-safe hover text shows "N/A" instead of "nan" for zero-variance features.
- JSON Bloat (GAP-6): OOF probability arrays rounded to 6 decimal places (~40% size reduction per evaluator).
- HPC Memory (OOM): Base memory bumped 256→512GB for genome-wide evaluators (FSD, WPS).
Added
- Structured Logging:
structlog-based logging in CLIreport()with per-evaluator timing, success/fail counts, and summary statistics. - Smart Resume (GAP-4): Resume checkpoint validates JSON freshness — warns if OOF keys are missing from pre-hardening runs.
- SHAP Waterfall Guards (S-04): Validates array lengths before plotting to prevent IndexError.
- SHAP Docstrings: All three SHAP helper functions now have full docstrings.
- Variable Initialization:
oof_y,oof_preds, andkde_labelsinitialized at template top level to prevent NameError when models fail.
Removed
plot_threshold_sensitivity()— dead code replaced by pre-computed threshold sweep in v0.0.7.- Redundant
cross_val_scoreimport and second independent CV computation. - Stale
plot_threshold_sensitivityentry from_modidx.py.
[0.0.7] - 2026-04-13
Added
- Dashboard Redesign: Restructured from single-page to 6-page progressive disclosure hierarchy (Executive Summary, Model Validation, Feature Explanation, Biomarker Yield, Cohort & QC, Data Explorer).
- XGBoost Integration: Full XGBoost model evaluation alongside LR and RF in
single_feature_model(). - Bootstrap AUC CIs: 95% confidence intervals for all model AUCs using
scipy.stats.bootstrap. - Decision Curve Analysis (DCA): Standalone
decision_curve_analysis()function computing net clinical benefit across thresholds for RF and XGBoost models. - Precision-Recall Curves: PR curves and average precision for all three models (LR, RF, XGBoost).
- Fold-Level AUC Tracking: Per-fold AUC tracking via
cross_val_scorefor all three models with*_auc_stdstability metric. - Threshold Sensitivity Sweep: 50-point sweep of sensitivity, specificity, and PPV across thresholds (0.01–0.99) for RF.
- Feature Stability: CV cross-fold feature importance consistency scoring (0.0–1.0 scale).
- QC Metrics: Per-feature
n_missing,pct_missing, andis_zero_variancecomputed inevaluate_feature(). - Feature Cards: Auto-generated metadata cards from evaluator registry with tier, category, and derived feature type detection.
- SHAP Tabbed Interface: Unified SHAP tabs for RF and XGBoost with consistent layout.
- Verdict Value Box: AUC-threshold verdict (Strong ≥0.80, Moderate ≥0.70, Weak <0.70) in Executive Summary.
- Label × Cancer Type Sunburst: Interactive sunburst visualization replacing static bar chart.
- Per-Sample Coverage Histogram: Histogram of non-null feature percentage per sample.
- Per-Chromosome Feature Chart: Conditional chromosome-level feature bar chart.
- Feature Importances Tab: Top-20 RF Gini importance bar chart in Model Validation.
- AUC Deltas: RF–LR and XGB–RF AUC deltas surfaced in Performance Metrics.
- Training Time: Model training time displayed in Performance Metrics tab.
- VAF Scatter: Re-added tumor burden independence scatter (top feature vs max_vaf, LOWESS trendline).
- great_tables Integration: Column-grouped data explorer using
great_tableswith auto-detected feature family spanners. - Quarto Auto-Discovery:
_find_quarto()probes PATH then 7 well-known install locations (Positron, Homebrew, system, conda). - Methods Link: Sidebar link to API documentation site.
- Documentation: New dashboard guide, DCA methodology doc, feature cards API reference, comprehensive CLI flag docs.
- Tests: 24 new tests (53 total) covering DCA, PR curves, fold AUC, threshold sweep, feature stability, QC metrics, training time, AUC deltas, and feature cards.
Changed
- JSON schema expanded from 24 to 44 fields per feature set.
- Dashboard template: 1,555 lines, 52 balanced code blocks.
- Language discipline applied across docs and template (removed promotional/overclaiming language).
custom.scss: bumped font size to 0.95rem, added QC warning class, added@media printrules.
Fixed
- Silent
except: passin calibration code replaced withlog.warning(). - Division by
len(df)without zero-guard in class balance text. - Scoreboard NaN values: sensitivity, specificity, n_samples, n_positive now correctly extracted from
rf_classification_reportdict instead of non-existent top-level keys. - QC tab Figure code dump: unsuppressed
fig.update_traces()return displayed as rawFigure({...})text. - Dashboard
debug: trueleaked Python output into rendered HTML; replaced withwarning: false. - QC row heights summed to 135%; rebalanced to 100% (10+40+25+25).
- Undefined
_to_float_arrayinwps_panel.pyandwps_genomewide.pyreplaced with correctly importedparse_array. - SHAP waterfall rendering stabilized for edge cases with zero feature contributions.
- Typo
fallsbacks→fallbacksinpyproject.toml. great_tables>=0.15.0added topyproject.tomldependencies.
[0.0.6] - 2026-04-10
Fixed
- Bin-Level Extractor Coverage Filtering: Fixed critical data bug where FSC and FSR on-target extractors computed
median()across all 28,823 genomic bins, including the 98% with zero coverage. The zero-coverage sentinel values (-29.897for log2,0.0for ratios) dominated the median, producing constant features and AUC=0.500 for all models. Now filters tototal > 0bins before aggregation. - SHAP Feature Shape Mismatch: Fixed
TreeExplainercrashes caused by passing a feature-subset matrix instead of the full model-trained feature set. SHAP now computes on all 50 model features;--shap-featuresonly limits visualization display count. - SHAP Binary Output Handling: Added robust handling for all
TreeExplainerreturn shapes (list, 3D array, 2D array) and safeexpected_valueextraction for binary classifiers. - Error Visibility: Changed Quarto stderr capture from first 500 chars to last 1500 chars, surfacing actual Python errors instead of kernel boot messages.
Added
- Nextflow HPC Parity: Wired all new CLI flags (
--top-n,--shap-samples,--shap-features,--resume,--skip-report,--cvd-safe) into Nextflownextflow.configandrun.nfwith HPC-optimized SLURM defaults (10-fold CV, 5000 SHAP samples, 64GB RAM). - CLI Configuration Logging: All three commands (
label,run,report) now log their full parameter state at startup for reproducibility. - Resume Support:
--resumeflag skips evaluators with existing model results, enabling incremental re-runs. - Variance Guard: CLI automatically drops zero-variance features before model training with a logged warning, preventing wasted compute on constant columns.
- Coverage Monitoring: All bin-level extractors now emit
n_covered_binsandn_total_binsin the feature matrix for downstream QC.
Changed
- Memory Management: Aggressive dashboard optimization — subsampled KDE plots (2000 samples),
gc.collect()between SHAP runs, explicit dataframe deletion after filtering. - SHAP Explainer: Switched from generic
shap.Explainertoshap.TreeExplainerto prevent OOM-causingKernelExplainerfallback. - HPC Resource Allocation:
process_highmemory increased from 32GB to 64GB for SHAP-heavy report generation.
[0.0.5] - 2026-04-09
Fixed
- PyPI Release Wheel Artifact Synchorization: Enforced a permanent "Triple Bump" protocol standardizing manual version matching globally across
settings.ini,nextflow.config, andkreview/__init__.pynatively. This resolves a decoupling bug that structurally blocked Github Actionspython -m buildcommands from publishing Wheels accurately tracking downstream package footprints correctly.
[0.0.4] - 2026-04-09
Fixed
- Documentation Sync: Hardcoded the
mikeversion provider default target alias gracefully tolatestintrinsically allowing GitHub Action GH-Pages orchestration arrays to map tags seamlessly. - Git Flow Constraints: Implemented official mandatory 8-step PR-driven workflow structures strictly bypassing raw fast-forward terminal merges blocking CI.
[0.0.3] - 2026-04-09
Added
- Global Config Parity: Synchronized dynamic execution limits tracking across native Python modules (v0.0.3) and HPC workflow blocks (
nextflow.config0.0.3). - Core CLI Flags: Engineered
@app.callback()directly intokreviewTyper infrastructure enabling standalone--versioninvocation blocks natively supporting Nextflowsoftware_versions.yamlregistry capture logging.
Fixed
- Systemic Module Sync: Repaired native
__init__.pydecoupling bugs where sequential tool paths caused legacy0.0.1footprints to bypass metadata injections. - Git Asset Purge: Permanently bound dynamic CLI Quarto runtimes (
html,static_plots,nohup) directly inside.gitignoreblocking blob registry accumulation remotely. - CI Formatting: Established uniform
black .compliance thresholds natively locking bothnbs/JSON source notebooks and/kreviewPython exports securely for Github Actions lint workflows.
[0.0.2] - 2026-04-09
Added
- Diagnostic Upgrades: Implemented explicit Sensitivity and Specificity clinical evaluations automatically calculating Youden's J static cutoffs and logging metrics securely to the results JSON matrix.
- Model Expansion: Added scalable
XGBoostmodeling alongside nativeRandom ForestandLogistic Regressionclassifiers inline. - Theme Selection: Introduced
set_theme()support parsing--cvd-safetoggle parameters. Allows zero-friction toggling between Okabe-Ito (colorblind secure) and global Muted Neon visualization workflows. - Cluster Deployment Optimization: Injected
[all]pip extra support resolving seamless multi-tool HPC dependencies smoothly (pip install -e ".[all]").
Fixed
- Dashboard Standalone Render: Resolved
format: dashboardclipping anomalies resulting from undocumented Quarto_quarto.ymlproject context bleeding. Hardcoded formatting constraints dynamically allowing pipeline usage deeply isolated in site-packages perfectly. - Path Resolution Hacks: Removed namespace package AST resolution assumptions and substituted secure
__file__contextual path checks, completely resolving editablepip install -e .templateNoneTypebugs natively. - CLI Options: Restored destroyed
--verboseoption parsing.
[0.0.1] - 2026-04-09
Added
- Formally released the production-grade
kreviewEvaluation Framework for fragmentomics features. - Five-tier classification algorithm implemented for accurate clinical ctDNA labeling:
Possible ctDNA−,True ctDNA+,Possible ctDNA+,Healthy Normal,Malignancy (Heme). - Scikit-learn Pipeline injection to eliminate cross-fold scaling leakage during standard ML
evaluate_feature. - DuckDB I/O optimizations strictly mapping internal batch chunks dynamically configured for Desktop (
--chunk-size 50) and HPC SLURM networks (--chunk-size 500). - Integrated dynamic
kaleidoplotting backends for clinical PDF Quarto workflows. - Dedicated Nextflow NF-Core DSL2 environment scaling wrapper specifically designed to ingest
manifest.txtparameters recursively without crushing symmetricwork/limits. - GitHub Container Registry release pipeline (
ghcr.io/msk-access/kreview) fully established utilizing OCI registry labels.
Fixed
- Out-of-fold probability caching logic strictly refactored away from simplistic aggregation bias.
- Hardcoded
papermillexceptions mapped into modular pipeline architecture. - Replaced ambiguous test metrics with explicitly verified Benjamini-Hochberg (FDR) corrections over Mann-Whitney metrics.