Changes in version 0.99.25 Changed - The seven audit feature columns of pdactrace_reference (audit_score_layer, _direction, _early, _serum, _rescue, the gate multipliers and flags) were frozen at v0.3.0, before the 12-template catalog. 286 genes whose best RNA template became Monotonic (284) or Late (2) therefore kept Early-onset and RNA-layer credit, and genes whose protein label changed kept their old layer and direction credit. The columns are now recomputed from the atlas's current labels with the same code that scores a user evidence table, so atlas and user scores follow one rule. data-raw/attach_audit_columns.R, which previously copied the v0.3.0 CSV, now does this recomputation. - Effect: 310 genes change score; 71 change class (60 supported_uncertain -> low, 9 high_confidence -> low, NCAPG and IQGAP3 high_confidence -> supported_uncertain). Class counts are now high_confidence 370, supported_uncertain 7941, low 1749, penalized 22, excluded 31. The top gene, the four case-study genes, SERPINA1 and the anchor enrichment (7 hits in the top 100, 39.3x; leave-one-out median 41.6x; bootstrap 95% CI 20.2-56.3) are unchanged, and the top 100 differs by one gene. Monte Carlo columns were regenerated (stable_high 153, high_uncertain 620, medium 502, low 8807). Changes in version 0.99.24 Documentation - The weight-sensitivity section of the methodology_validation vignette reported the same top-100 anchor enrichment (7 hits, 39.3x) for every weight profile, including single-axis extremes, and concluded that the ranking is "fundamentally insensitive" to the weights. The sweep was a no-op: it wrote a reweighted audit_score into the atlas and passed it to evaluate_anchor_enrichment(), which recomputes audit_score with the frozen weights. Ranked directly, the profiles give 7, 6, 1, 5 and 6 hits (biological-coherence-only: 5.6x, not significant). The section now ranks the reweighted score itself and states that the enrichment depends on the weights; across the simplex the top-100 hit count ranges from 1 to 8. - The README said that vignette re-evaluates the anchor enrichment at other template cutoffs; it only counts the genes that clear each cutoff. - ?pdactrace_reference and the README now document that the scRNA cell-origin layer exists only for the 300 genes of an earlier candidate ranking (Phase 2D; tissue stage effects plus serum detection by the author's account, no literature or known-marker list; its script was not retained). 11 of the 18 secondary anchors are among them. Within those genes the top-100 enrichment is 1.9x (p = 0.04); with the scRNA layer removed from the score it is 16.9x (3 hits). Changes in version 0.99.23 Changed - classify_claim_tier() now uses strict TRACE-D only. A gene is serum_concordant only when its measured serum log2FC reaches tau_serum in the tissue direction, and translation_status follows the same strict class. Previously the legacy translation_class label could override a strict class C, although that label records only the sign of the phase77 serum change, not its size or significance. The legacy label is still returned, as legacy_translation_class, and does not raise the tier. Strict class C is no longer counted as a serum signal. - Effect on the bundled atlas: serum_concordant 8 -> 6 (LGALS3BP, log2FC 0.035, adjusted p 0.81, and FN1, 0.006, move to exportable_plausible); serum_observed 13 -> 9 (ECM1, FBLN1, GGH, LCN2 move to exportable_plausible). LTBP1, SPARC and TAGLN2 stay serum_observed, but their translation_status is serum_observed_no_tissue_direction rather than direction_inverted: their serum change opposes tissue, but their tissue meta-effect is below tau_tissue. Audit scores, audit classes and the anchor enrichment are unchanged. - serum_log2fc_PDAC_vs_HC in pdactrace_reference now holds the pooled phase77 log2FC for the 19 serum-detected genes that had no phase42 value, so strict TRACE-D sees all 38 serum-detected genes (19 before). No other column changed. The rule is in data-raw/build_reference.R; data-raw/attach_phase77_serum_log2fc.R applied it to the shipped atlas. Bug fixes - compute_trace_d() treated a missing pancreatitis log2FC as 0 and could call such a gene pdac_specific; it is now ambiguous. A serum-detected gene with no measured log2FC is recorded as serum_unmeasured in tracd_decision_path instead of serum_subthr. Documentation - ?pdactrace_reference documents that rna_padj_E/M/L are copies of the omnibus LRT padj (stage-specific values are rna_wald_padj_*), where each serum log2FC comes from, what translation_class does and does not encode, and that the plasma high-abundance gate is a curated list: SERPINA1 is not on it (adding it would give 0.32, penalized, and 6 rather than 7 anchor hits in the top 100); the list is kept as frozen. Changes in version 0.99.22 Bug fixes - propagate_uncertainty() perturbed the pre-v0.3.0 seven-feature score (weights 0.20/0.20/0.20/0.10/0.10) instead of the 3-axis score that compute_audit_score() returns, so its intervals, rank intervals and confidence_class described a different score. SERPINA1 scored 0.6406 but had a Monte Carlo median of 0.520 (the old formula gives 0.519). The loop now uses the 3-axis formula (SERPINA1 median 0.641). Only template rho, cohort agreement and I2 are perturbed, as before. - The stored Monte Carlo columns of pdactrace_reference (audit_score_median, _lo95, _hi95, audit_uncertainty_width, audit_rank_*, audit_confidence_class) were regenerated with the fixed loop (500 draws, seed 42); every other column is byte-identical. data-raw/monte_carlo_uncertainty.R, which no longer ran on the current atlas, now calls the package's own loop, and its stale figures were removed. confidence_class counts: stable_high 241 -> 153, high_uncertain 820 -> 622, medium 684 -> 509, low 8337 -> 8798. - sb_lock_manifest() failed on Windows ("Every locked file must be inside root") because normalizePath() returned backslashes while the prefix check used /. Paths are now normalised with winslash = "/". Documentation - compute_audit_score(), explain_score() and the README now state that the gated score is divided by the largest gated score in the scored table, so audit_score is relative to the top gene (LGALS3BP in the bundled atlas), and that there are five audit classes, including low. - classify_trajectory() and classify_protein_trajectory() no longer say the 0.85 default matches the bundled atlas: the atlas was built with 0.75. The README no longer claims 0.85 is hard to reach with four points; for a gene with no stage effect the best of 12 templates exceeds it about 58% of the time. - The README, audit/PROVENANCE.md and vignette 7 described both PDAC one-shot audits as stopped by assay coverage. Only MSV000101183 v1_1 stopped at technical QC; MSV000101183 v2 and PXD067770 stopped because the deposited outcome labels did not match the frozen dictionary or group counts. The tables now list each lock with its recorded reason. Changes in version 0.99.21 PDAC refocus: prespecification and audit layer merged in. The PDAC subset of the wider cross-cancer working tree is now part of the package; the non-PDAC analyses stay in the v0.1.0-pancancer-archive tag and are out of scope here. New - Prespecification and audit layer (13 exports): stagebridge(), sb_one_shot(), sb_default_one_shot_rule(), sb_pareto_fronts(), sb_loco_stability(), sb_observability(), sb_validate_effects(), sb_simulate(), sb_method_scores(), sb_multiblock_plsda_scores(), sb_binary_auc(), sb_average_precision() and sb_topk_recall(). - sb_one_shot() returns a terminal PASS / FAIL / INCONCLUSIVE decision, where INCONCLUSIVE records that a frozen gate halted the run before the endpoint was computed and is therefore distinct from a biological FAIL. - audit/PROVENANCE.md records the archive tag, the transfer hashes and the two PDAC one-shot audits, both of which terminated INCONCLUSIVE at the prespecified coverage gate. Documentation - New vignette 7, prespecification_audit, covers the whole prespecification layer: stagebridge() ranking, exact Pareto fronts, leave-one-cohort-out stability, the shipped comparators scored with sb_binary_auc() / sb_average_precision() / sb_topk_recall(), and sb_one_shot() driven to PASS, FAIL and INCONCLUSIVE. It reports that StageBridge has the lowest AUROC of the eight methods on the simulated translation scenario while ranking second on AUPRC and top-20 recall, rather than selecting a scenario that flatters it. - Vignette 8 (formerly "Cross-cancer demonstration") is retitled "Portability of the R API to a non-PDAC cohort" and its opening claim is narrowed from "the framework is cancer-agnostic" to the interface statement its own Limitations section already made: the API accepts non-PDAC input, and no result is claimed outside PDAC. - Fixed the vignette index: two vignettes were both numbered 5 and no vignette was numbered 7. Ordinals are now 1-8 with titles matching their \VignetteIndexEntry, and stale author: version strings are replaced with the maintainer name. - sb_default_one_shot_rule() now records that its thresholds come from a lock held in the archived working tree, not from a path inside this package. Changed - DESCRIPTION and README.md state the PDAC-specific scope and the prospectively frozen score layer. - Seeds in the new code are scoped with withr::local_seed() rather than set.seed(), matching the existing BiocCheck-compliant pattern. - stats::reshape() is called with its namespace qualified. Bug fixes - report_gene() failed for every gene with "'pdactrace_reference' is not an exported object". Its report templates read the atlas as pdactrace::pdactrace_reference, which stopped resolving when 0.99.20 set LazyData: false; the \donttest{} example hid it from R CMD check. The templates now load the atlas with data(). - citation("pdactrace") and the README cited Zenodo DOI 10.5281/zenodo.20076698, which is the v0.99.0 record under an older title. Both now use the concept DOI 10.5281/zenodo.20068234, which resolves to the latest archived version, and the current title. - The \donttest{} examples of fit_stage_de(), fit_stage_de_protein(), classify_trajectory() and classify_protein_trajectory() referenced undefined placeholder objects (my_counts, my_intensity) and failed under --run-donttest. They now run on the bundled toy data. - download_phase_csvs() could not work for anyone: it fetched from a private repository, at a path that repository does not contain, while its documentation called the source public. The two upstream fits (phase33 RNA, phase34 protein; gene-level summary statistics) now live in data-raw/ of this repository, the helper fetches them from there, and data-raw/build_reference.R and build_protein_betas.R read them in place. A clean checkout with no other repository reproduces the 64 base columns of pdactrace_reference exactly. - The reproducibility vignette no longer tells users to clone the private manuscript repository or cite Zenodo record 10.5281/zenodo.20067849 as its archive; that record is the pdactrace v0.99.0 source. Tests - Added test-sb-core.R and test-sb-one-shot.R. The one-shot suite is a positive control: it drives the frozen runner to all three terminal states on synthetic input and checks that AUROC rises monotonically with planted signal, so a PASS is reachable in principle and the real-data INCONCLUSIVE results reflect coverage, not an over-conservative gate. Changes in version 0.99.20 Bioconductor pre-submission polish. This release keeps the claim-audit API unchanged and addresses BiocCheck new-package feedback before opening the Bioconductor Contributions issue. Changed - Added short runnable examples to exported Rd pages that previously only contained long \donttest{} examples, clearing the BiocCheck runnable-example ERROR. - Replaced remaining \dontrun{} examples with \donttest{}. - Set LazyData: false and added missing vignette chunk labels plus sessionInfo() chunks where BiocCheck requested them. Tests - R CMD check --no-manual and BiocCheck(new-package=TRUE) were run on the source tarball as the final submission gate. Changes in version 0.99.19 BiB-facing claim-audit release. This release reframes pdactrace from a scalar biomarker prioritisation package into a deterministic stage-aware PDAC atlas and tissue-to-blood biomarker claim-audit framework. Added - classify_claim_tier() and summarize_translation_gap() separate tissue dysregulation from stronger blood-biomarker claims. - compute_trace_d() implements TRACE-D in strict mode, with an explicit legacy_translation = "fallback" compatibility mode for historical translation_class annotations. - run_weight_robustness(), compute_pareto_class(), compute_pareto_layers(), and evaluate_pareto_stability() audit whether candidates depend on one arbitrary 3-axis weight vector. Changed - README, DESCRIPTION, and CITATION now use the claim-audit framing: stage-aware tissue evidence is not treated as validated blood biomarker evidence unless serum observability, direction concordance, and confounding checks support that stronger claim. - The GitHub version badge now follows semantic tags rather than GitHub Releases, so package-version display remains correct for lightweight tagged development releases. Tests - Added focused tests for claim tiers, TRACE-D strict/fallback behaviour, weight robustness, and Pareto support. - R CMD check --no-manual passes with rebuilt vignettes. Changes in version 0.99.18 viz_gene() default flips to multi-page (layout = "split"). The v0.99.16 split mode was opt-in, so the bare viz_gene("X") call still rendered the cramped single-page 2x3 patchwork. This release flips the default so the natural call gives the six panels at full size, one per plot-pane page. Changed - viz_gene(layout) default flipped from "compact" to "split". Calling viz_gene("LTBP1") now returns a pdactrace_viz_panels named list of six full-size ggplots (rna, protein, cell, serum, filter, hexagon). - New S3 print method print.pdactrace_viz_panels renders each of the six panels sequentially to the active graphics device. In RStudio the six panels become six entries in the Plots pane history (navigate with back/forward arrows). In a batch script with pdf() open they become six pages of the PDF. - The single-page 2x3 patchwork composite is preserved as viz_gene("X", layout = "compact") for embedding contexts and back-compatibility. Tests - Default viz_gene("X") test now expects pdactrace_viz_panels instead of patchwork. - layout = "compact" patchwork tests retained, gated on skip_if_not_installed("patchwork"). - New test for print.pdactrace_viz_panels round-trip. This is a behaviour change but not an API removal: every existing viz_gene(..., layout = "compact") call still works, and the named-list shape for layout = "split" is unchanged. Changes in version 0.99.17 README compression for Bioconductor reviewer scan-readability. The pre-submission README had grown to 1,749 lines as scenarios and a per-function reference accreted; this rewrite compresses it to 532 lines (-70%) without removing any reviewer-defending content. Function-level argument tables are intentionally pushed to ?function_name Rd pages (the canonical R discovery surface) and scenario-level worked examples to the existing vignettes. Changed - README.md rewritten: - Hero + value prop + 39.3x sanity check + install + quick-start block at the top (~80 lines, scan-readable on first screen). - Six Scenarios compressed from ~700 lines of prose to ~120 lines of code blocks plus 2-3 sentence framing each, with explicit vignette("...") pointers for the long form. - Function reference compressed from ~600 lines of per-function blocks to a single grouped table covering all 59 exports; detailed argument and return shape now live in ?function_name (the canonical R help surface). - Trajectory framework + Stage harmonization + Reference atlas sections trimmed to essentials (~60 lines combined). - Preserved verbatim: audit scoring rule + cutoffs justification ("Why these specific cutoffs?"), the three-way projection stress-test table + housekeeping negative-control table, Reproducibility section's four-layer description, Citation / License blocks. These are the reviewer-defending sections. - Added an explicit Limitations section (PDAC-only atlas, cohort independence caveat, held-out RNA-only baseline does not recover anchor enrichment, no supervised classifier shipped) that previously was scattered across the long-form scenarios. - Walked back over-reaching cancer-agnostic language ("framework applies unchanged to other cancers" / "transferable to any cancer") to stay consistent with the package name and with the fact that the bundled atlas, the curated external anchor set, and all validation work are PDAC-specific. The API is now described as designed for transferability given an analogous per-stage atlas, not as turnkey pan-cancer. No code, vignette, test, or NAMESPACE changes; documentation-only release. Changes in version 0.99.16 viz_gene() gains layout = "split" for full-size per-panel output. The 6-panel composite layout is great for a one-glance overview, but the per-panel cells get cramped at default print sizes. The new split mode returns each panel as its own full-size figure -- either as a named list of ggplots (for custom layout in a script) or as one cairo-PDF per panel (when output_dir is set). Added - viz_gene(layout = c("compact", "split")) -- backwards- compatible. "compact" (default) keeps the 2x3 patchwork composite; "split" returns a named list of 6 ggplots (rna, protein, cell, serum, filter, hexagon). - viz_gene(..., layout = "split", output_dir = ...) -- writes each of the 6 panels to a separate cairo-PDF file via [pdactrace_save()] (default width = 6, height = 4.5 inches, single-column NCS-grade). Files are named viz_gene__.pdf. Returns the named list invisibly with attr(., "files") carrying the file paths. Tests - 3 new test_that blocks covering split mode (return type, names, output_dir file count, sparse-evidence gene support). - Full suite: 507 PASS / 0 FAIL (was 504). No public API removals; layout, output_dir, width, height are additive optional arguments. Changes in version 0.99.15 Final pre-Bioconductor-submission audit fixes. Addresses two items found in the v0.99.14 R CMD check NOTEs and tightens BIOCONDUCTOR.md to proactively address the maintainer-team review questions most likely to come up. Fixed - .Rbuildignore now excludes the .claude hidden directory (caught by R CMD check checking for hidden files and directories ... NOTE). The directory holds editor scratch state and is not part of the package. - R/pdactrace-package.R utils::globalVariables() now declares serum_log2fc_Pan_vs_HC (caught by R CMD check checking R code for possible problems ... NOTE for the .ft_serum_strip() helper). BIOCONDUCTOR.md hardened - New top "Submission overview" paragraph -- a copy-paste-ready risk-neutralizing summary for the reviewer issue body that states up-front that pdactrace is a Software package for interpretable, stage-aware multi-omics biomarker prioritization, not a clinical diagnostic classifier; that the bundled atlas is PDAC-focused while the projection interface is cancer-agnostic; and that anchor enrichment is reported as a sanity check, not validation. - New "Primary user workflow" section that intentionally spotlights the small Core API (viz_gene, query_gene, explain_gene, compare_candidates) and frames the broader 71-export API as layered, not unstructured. - New "Known submission risks" section that proactively discloses: - tarball ~5.83 MB exceeds the 5 MB BiocCheck software-package threshold (medium-high risk; reasoning: atlas required for offline reproducibility; pdactraceData ExperimentHub companion planned for v1.1; if reviewers request atlas relocation as a pre-acceptance condition we are prepared to split on the first iteration); - API surface size (with the deprecation list of 5 alias pairs ready if reviewers prefer a smaller surface); - the two local R CMD check WARNINGs are vignette-build- environment artefacts (no pandoc locally; all 7 vignettes knit cleanly via knitr::knit()); - BiocCheck network step was blocked in our sandbox; package previously passed BiocCheck cleanly at v0.99.0. Tests - Full suite: 504 PASS / 0 FAIL. - R CMD check --as-cran on v0.99.15 tarball: 0 ERROR / 2 WARN (vignette-only) / 3 NOTE (down from 4; .claude hidden-dir NOTE eliminated; serum_log2fc_Pan_vs_HC global-binding NOTE eliminated; remaining 3 are CRAN incoming feasibility, pandoc-not-installed, pre-existing R CMD check static-analysis noise). DESCRIPTION bumped 0.99.14 -> 0.99.15. End of pre-submission hardening. Changes in version 0.99.14 Pre-Bioconductor-submission audit fix. inst/CITATION was stale (carried the old "Queryable Stage-Aware PDAC Tissue-to-Serum Biomarker Reference Atlas" title and a hard-coded "0.99.0" version note). Updated to the current DESCRIPTION title ("Transparent Multi-Omics Tissue-to-Serum Biomarker Translation Framework with PDAC Reference Atlas") and to read utils::packageVersion("pdactrace") so the citation note follows future version bumps automatically. This release also marks the end of pre-submission hardening. v0.99.0 -> v0.99.14 covers: Bioconductor pre-submission blockers (v0.99.0), Bioconductor compliance pass (v0.99.3), reproducibility vignette + on-demand fetcher (v0.99.4), Evidence Math layer (v0.99.5), interpretable ML layer (v0.99.6), pandoc-friendly report_gene (v0.99.6.1), viz_gene canvas + BiB framing (v0.99.7), viz_gene rebalanced (v0.99.7.1), viz_gene 6-panel + plot_serum_direction (v0.99.8), serum projection helper (v0.99.9), methodology validation pass (v0.99.10), anchor-language softening (v0.99.11), held-out PDAC stress test + 3-way baseline (v0.99.12), BIOCONDUCTOR.md submission summary (v0.99.13), CITATION fix (this release). Changes in version 0.99.13 Reviewer-facing documentation pass + Bioconductor submission summary added. Final hardening before Bioconductor submission issue. No API change; documentation-only. Added - BIOCONDUCTOR.md (NEW) -- single-page submission summary prepared as a copy-paste-ready body for the Bioconductor review issue. Documents package purpose, what the package is and is not, user-facing API groups (Core query / Visualization / Evidence math / User cohort / Translation discipline / Optional / Reports + I/O), evaluation discipline including the 3-way anchor enrichment table, an explicit limitations section, and the conservative submission tone for the issue body itself ("prepared for Bioconductor review and passes local checks; standard reviewer iteration expected"). - README.md -- new top-level section "Projection stress test and evidence-layer dependence" inserted into the Audit scoring rule chapter. Surfaces the 3-way anchor enrichment table (Bundled FULL multi-layer 39.3x at top-100; Bundled RNA-only 16.9x; Held-out RNA-only 0) and the negative-control housekeeping bottom-500 enrichment after atlas-defined leakage annotations are applied (17.8x, p = 1.1e-33). Frames the held-out RNA-only result as a "projection stress test", not as definitive external multi-omics validation. Phrasing nuances locked - "Atlas-defined leakage annotations were applied" (not "gates transferred automatically") -- the leakage flags are manually curated at v0.3.0 freeze and require explicit transfer to user / external projections. - "Projection stress test" (not "external validation") -- the held-out cohort uses RNA only and lacks the multi-layer evidence the bundled atlas integrates. These wording rules are in feedback_submission_framing.md. Tests - Full suite: 504 PASS / 0 FAIL (no regression). Changes in version 0.99.12 Held-out PDAC validation + 3-way enrichment baseline added to methodology_validation vignette. Phase 2 of the locked roadmap. Documentation-only release; no API change. Added - vignettes/methodology_validation.Rmd Section D (NEW) -- held-out PDAC cohort projection. Constructed by combining GSE253260 (397 PDAC primary tumour bulk RNA-seq, never used in atlas construction; stage labels harmonised from GEO diseasestage:ch1) with GTEx (360 normal pancreas) for the Normal stage. Cohort confound (Normal samples entirely from GTEx, Tumour entirely from GSE253260) is honestly disclosed; cohort_col was dropped from the DESeq2 design as a result. ENSEMBL -> SYMBOL mapping done at the SYMBOL level after per-cohort mapping (not at the ENSG-intersect level which collapsed to 1166 genes); the fixed pipeline gives anchor coverage 18 / 28 (vs. the broken pipeline's 1 / 28). - vignettes/methodology_validation.Rmd Section E (NEW) -- 3-way baseline comparison of anchor enrichment by ranking source: - Bundled FULL audit_score (multi-layer): 39.3x at top-100 (p = 2.2e-10) - Bundled RNA-only audit_score (multi-layer evidence stripped, audit_* recomputed from raw RNA): 16.9x at top-100 (p = 6.9e-4) - Held-out RNA-only projection: 0 hits (top-100, top-500) The 3-way comparison decomposes the framework's enrichment contribution into multi-layer integration vs. same-cohort RNA evidence, and shows that single-cohort RNA-only projection on a new cohort cannot reproduce anchor enrichment without the multi-layer atlas as a reference. The negative-control housekeeping bottom-500 enrichment (fold 17.8x, p = 1.1e-33 in held-out vs. 20.2x, p = 1.3e-41 in bundled FULL) does transfer when the atlas's curated leakage flags are externally applied -- confirming gate discipline robustness across cohorts when the curated flags travel with the analysis. Honest disclosure (process error during validation) During the v0.99.12 work I initially proceeded with a broken ENSEMBL -> SYMBOL pipeline that gave 1166 / 17252 atlas overlap and 1 / 28 anchor coverage. The fix was to map per-cohort to SYMBOL first, then intersect at the SYMBOL level, then restrict to the atlas universe. The bug + fix is documented in this NEWS entry as a transparency item. Tests - Full suite: 504 PASS / 0 FAIL (no regression). Changes in version 0.99.11 Submission framing hardening: anchor enrichment language softened to 'sanity check', and complementary negative-control depletion analysis added. Two coordinated changes for the BiB / Bioconductor reviewer audience. Changed - R/model_card.R -- the validation_summary field renamed to sanity_check_summary and reworded: "T1_validated anchors land in the top decile by anchor_similarity in the bundled atlas (post-freeze sanity check, not fully-blinded external validation)". model_card() printer auto-picks up the new field name. - README.md -- every reference to the 39.3x anchor enrichment now framed as a "post-freeze evaluation-only sanity check" rather than "validation". Explicitly notes that anchor curators and framework designers share domain expert input, so the result is best interpreted as a sanity check pending v1.0's held-out PDAC cohort run. - vignettes/methodology_validation.Rmd -- intro reworded from "two reviewer-facing methodology validations" to "two reviewer-facing methodology sanity checks (post-freeze evaluation, not fully-blinded external validation)". Limitations section retitled and softened. New - vignettes/methodology_validation.Rmd Section C -- Negative control depletion analysis. The complement of the Section B anchor enrichment: housekeeping (n=31) and plasma_high_abundance (n=22) genes -- both intentionally zeroed/halved by the leakage gate -- should be DEPLETED at the top of the audit-score ranking and ENRICHED at the bottom. Quantitative result: all 31 housekeeping genes land in the bottom-500 (fold = 20.2, p = 1.3e-41); top-1000 housekeeping depletion p = 0.04. Paired with Section B's anchor enrichment, this demonstrates the framework discriminates in both directions: known signal goes up, known noise goes down -- a circular score would not produce both effects. These are submission-framing changes (not API changes). The actual numeric outputs of audit_score, anchor_enrichment(), and model_card() are unchanged; only the user-facing language and the additional negative-control documentation are updated. Tests - Full suite: 504 PASS / 0 FAIL (no regression). Changes in version 0.99.10 Methodology validation pass for the BiB / Bioconductor reviewer audience. No new public API; this release closes five documentation-and-validation gaps that the v0.99.9 self-audit flagged as the most likely BiB reviewer pushback points. Changed - README.md "Audit scoring rule" section -- new "Why these specific cutoffs?" subsection that documents the rationale for every numeric in the framework: rho_cutoff = 0.85 (conservative four-point trajectory threshold), 3-axis weights 0.40 / 0.35 / 0.25 (priority order: layer presence > biological coherence > translational relevance), 2-gate multipliers (housekeeping 0.00 / plasma-high 0.50; Higgins-Thompson I-squared boundaries 70 / 90 mapped to multipliers 1.00 / 0.70 / 0.30), audit class boundaries 0.5 / 0.3, effect-size threshold 0.585 = log2(1.5), and a one-paragraph disclosure of the Stouffer cohort-independence assumption (TCGA-PAAD and CPTAC PDAC partial donor overlap, addressed via the heterogeneity gate). New vignettes - vignette("cross_cancer_demonstration") (NEW) -- end-to-end demonstration that the framework's R API is cancer-agnostic. Uses a synthetic CRC-flavoured cohort (50 genes x 24 samples) to walk project_user_cohort() through the same pipeline used in Scenario 6a of the README. Includes a "what changes between PDAC and non-PDAC" table making explicit which components are PDAC-specific (bundled atlas, anchor evaluation set) and which are framework-portable (12-template catalog, 3-axis + 2-gate audit, Evidence Math layer, Class A / B / C translation discipline). - vignette("methodology_validation") (NEW) -- two reviewer- facing methodology validations on the bundled atlas: - Section A: cutoff sensitivity -- sweeps rho_cutoff in {0.80, 0.85, 0.90} and re-evaluates top-100 anchor enrichment; perturbs the 3-axis weights across 5 profiles and shows the framework is not brittle to the exact weight choice. - Section B: tool comparison -- benchmarks the full audit_score ranking against simpler alternatives (raw |beta|, -log10(padj), layer count, signal-peptide-only) on the same anchor harness; the multi-axis integration + leakage / heterogeneity gating produces a specificity advantage no single feature reaches. DESCRIPTION - Version bumped 0.99.9 -> 0.99.10. No Imports: / Suggests: change. These additions close the five highest-priority methodology gaps identified in the v0.99.9 final audit: P1.1 cohort independence disclosure; P1.2 cutoff justifications in the README; P1.3 cross-cancer transferability demonstration; P2.1 cutoff sensitivity analysis; P2.2 tool comparison. Changes in version 0.99.9 Asymmetric user-data projection: serum needs only PDAC vs HC. The tissue side (RNA + tissue protein) requires stage-aware input (N/E/M/L 4-level) for the 12-template trajectory framework, but the serum side uses binary group contrasts -- which is exactly what most public PDAC serum DIA / TMT studies publish. Until now pdactrace had no user-facing helper for the serum side; this release adds one and explicitly closes the documentation / friendly-error gaps that left users with N vs T input confused. New - project_user_serum_cohort(intensity, coldata, group_col, pdac_label, hc_label, pan_label, test, padj_cutoff, link_to_atlas) -- projects a user's serum proteomics matrix through the binary-contrast pipeline. Computes serum_log2fc_PDAC_vs_HC and (optionally) serum_log2fc_Pan_vs_HC, runs a per-gene two-group test (limma_eBayes / wilcox / t_test), BH-adjusts, joins the bundled atlas RNA direction to assign translation_class (A / B / C), and flags serum_detected. Output plugs straight into assemble_user_evidence(serum_summary = ...). No stage labels required; minimum 3 samples per group recommended. Changed - fit_stage_de() -- new pre-validation step that surfaces a friendly error when the user provides binary c("Normal", "Tumor") instead of c("Normal", "Early", "Mid", "Late"). Previously the silent factor() coercion dropped Tumor samples and the user got the misleading "Need at least 8 samples" error downstream. The new error names which labels matched / unmatched and points the user at three options (clinical staging, project_user_serum_cohort() for serum, or the user_cohort_extension vignette's TNM/AJCC mapping table). - vignettes/user_cohort_extension.Rmd -- two new appendices: Appendix A is a TNM / AJCC -> Normal / Early / Mid / Late harmonization table for users mapping their clinical staging data; Appendix B walks project_user_serum_cohort() end-to-end with a synthetic 50-gene x 24-sample (8 PDAC / 8 HC / 8 Pancreatitis) example that returns ready-to-assemble serum_summary. - README.md Scenario 6 -- restructured into 6a (tissue projection, stage-aware), 6b (serum projection, binary), and 6c (combined tissue + serum -> single audit score). Adds an explicit "Important data requirement" callout at the top of Scenario 6 that documents the asymmetry and tells N vs T users which path to take. Tests - 9 new test_that blocks in tests/testthat/test-project-user-serum.R covering schema, log2FC = mean(PDAC) - mean(HC), planted PDAC-up signal detection, missing/wrong group labels (friendly errors), link_to_atlas TRUE / FALSE, and translation_class cross-checks (LTBP1 / LGALS3BP -> A; ALB -> B; GAPDH -> C). - One new block verifies the friendly stage error fires on N vs T input to fit_stage_de(). - Full suite: 504 PASS / 0 FAIL. project_user_serum_cohort is a new export; no public API removals. fit_stage_de() behaviour is strictly stricter (now errors on N vs T instead of silently degenerating), but no previously valid input changes outcome. Changes in version 0.99.8 **viz_gene() expanded to a six-panel evidence-to-score canvas - compact NCS-grade redesign of plot_filter_trace() + plot_serum_direction() exported.** The single-call composite now shows the entire prioritisation flow on one page: four input layers (RNA, tissue protein, scRNA cell origin, serum direction), the 7-step tissue-to-serum filter trail that gates them, and the 6-axis hexagon that compresses all of the above into the final audit-score components. New - plot_serum_direction(gene) -- exported standalone version of the per-gene serum direction strip (PDAC vs HC and Pancreatitis vs HC log2FC, faceted by contrast, coloured by translation Class A / B / C). Previously available only as the strip embedded above plot_filter_trace()'s grid. Changed - R/viz_gene.R -- panel layout expanded from four to six (default ncol = 3, 2x3 grid): TL bulk RNA per-stage forest; TM tissue protein per-stage trajectory; TR scRNA cell-of-origin distribution; BL serum direction (PDAC + Pancreatitis log2FC); BM 7-step filter trail with pass-count badges; BR 6-axis audit hexagon. Every panel-builder is wrapped in a .vg_safe() helper so a NULL / error return becomes a graceful "no data" placeholder, keeping the grid intact for genes with sparse evidence layers. New ncol options: 3 (default), 2 (3x2), 1 (6x1 vertical). The previous RNA per-cohort sign-vote panel remains available standalone via [plot_per_cohort()]. - R/plot_filter_trace.R -- visual rewrite of the 7-step filter grid and the auxiliary-routes panel. Step labels move from top (rotated 45 degrees, 5.5 pt) to bottom (horizontal, 7 pt, two-line) for higher legibility at smaller embeddings; tile borders go from grey50 / 0.4 to white / 0.6 for a cleaner separation; pass-fill upgraded from olive (#2E7D32) to teal (#00796B) and fail-fill from white to soft blush (#FFE0E0) for higher contrast at print size; coord_equal() keeps cells square. Each gene row gains an inline pass-count badge ("X/7") in monospace. The serum direction strip header is tightened (subtitle inlined into title; legend keys shrunk to 0.35 cm). Auxiliary routes panel mirrors the same compact styling. - R/plot_stage_effect.R -- protein-layer subtitle now states explicitly that no per-stage SE is rendered because the upstream phase34_protein_pooled_12template.csv is a limma F-test (overall significance) rather than per-contrast Wald (which would yield lfcSE_E/M/L). Per-contrast Wald is deferred (would require an upstream limma rerun + atlas rebuild). Tests - 4 new test_that blocks: viz_gene returns 6 panels; viz_gene gracefully degrades on sparse-evidence genes (ALB, GAPDH, SERPINA1); plot_serum_direction returns ggplot; errors on empty input. - Full suite still passes (no regressions vs v0.99.7.1). No public API removals; six-panel layout is additive (was 4 in v0.99.7.1), and plot_serum_direction is a new export. Changes in version 0.99.7.1 viz_gene() rebalanced to one panel per evidence layer + plot_filter_trace() enriched with serum direction context. The v0.99.7 canvas was RNA-heavy: two of the four panels (per-stage forest + per-cohort sign-vote) read from the same RNA layer, while tissue proteomics and serum proteomics had no dedicated visual slot. This release rebalances so each of the four evidence layers (bulk RNA, tissue protein, scRNA cell origin, serum + filter) gets exactly one panel. Changed - R/plot_stage_effect.R -- new layer = c("rna", "protein") argument. The protein variant reads prot_beta_N/E/M/L from the bundled [pdactrace_protein_betas] table and draws per-stage point estimates. Per-stage SE is unavailable on the protein side so no CI is drawn (the overall F-test padj is reported in the subtitle instead). Genes absent from the protein atlas render as a graceful "no data" placeholder. - R/plot_filter_trace.R -- new show_serum = TRUE default appends a serum direction strip above the 7-step phase60 grid showing per-gene PDAC vs HC and Pancreatitis vs HC log2FC, coloured by translation class (Class A blue, Class B red, Class C grey, NA light grey). Existing callers see a richer panel by default; pass show_serum = FALSE to recover the v0.99.7 layout. Output type is unchanged (inherits(., "ggplot") still TRUE for all combinations). - R/viz_gene.R -- panel layout rebalanced to one-per-layer: TL bulk RNA per-stage forest, TR tissue protein per-stage trajectory (uses the new layer = "protein" arg), BL scRNA cell-of-origin distribution, BR serum direction strip + 7-step filter trace. The previous RNA per-cohort sign-vote panel remains available standalone via [plot_per_cohort()]. Tests - 3 new test_that blocks in tests/testthat/test-plots.R covering: plot_filter_trace(show_serum = TRUE/FALSE), plot_stage_effect(layer = "protein"), and graceful handling for genes absent from pdactrace_protein_betas. No public API removals; layer and show_serum are additive optional arguments. The default behaviour of plot_filter_trace() now includes the serum strip; this is the intended improvement, and a one-line show_serum = FALSE opt-out is provided for callers who want the older bare grid. Changes in version 0.99.7 Single-call visual evidence canvas + methodology-first positioning. Two coordinated changes for non-technical reviewers and reader audiences: (1) one new function that turns the entire per-gene evidence story into a single composite figure, and (2) a DESCRIPTION + README reframing that leads with the tissue-to-serum translation framework and demotes the bundled PDAC atlas to the demonstration cohort role. New - viz_gene(gene_symbol, title, ncol) -- 2x2 patchwork canvas composing per-stage trajectory forest, per-cohort sign-vote bar, scRNA cell-of-origin distribution, and 7-step tissue-to-serum filter trace, under a one-line headline naming the matched template, audit class, and translation class. The visual analog of summarize_gene_evidence() and the recommended first call for a clinician or biologist who hands you a gene -- one plot, no per-axis function names required. ncol = 1 for a vertical strip suitable for narrow embedding. Changed (BiB framing) - DESCRIPTION: Title: reframed from "Queryable Stage-Aware PDAC Tissue-to-Serum Biomarker Reference Atlas" to "Transparent Multi-Omics Tissue-to-Serum Biomarker Translation Framework with PDAC Reference Atlas". Description: rewritten to lead with the framework components (12-template catalog, 3-axis + 2-gate audit, Evidence Math layer, optional interpretable ML layer, Class A / B / C translation discipline) and to position the PDAC atlas explicitly as the demonstration cohort, not the primary contribution. - README.md opening: same reframe, plus a quantitative anchor for the framework's evaluation harness (39.3x external-anchor enrichment, p = 2.18e-10; LOO median 41.6x; bootstrap 95% CI [20.2, 56.3]). - README.md "What you get": now split into "Methodology (transferable to any cancer)" and "PDAC demonstration cohort" sub-sections; the four canonical case studies (LGALS3BP, LTBP1, ALB, GAPDH) are listed equally as one-per-class demonstrations, with no single gene treated as a flagship. - README.md Scenario 1: now leads with viz_gene("LTBP1") as the visual entry point; the existing query_gene("LTBP1") text view is presented as the scripting / knitr-report alternative. No public API removals; viz_gene() is purely additive. Changes in version 0.99.6.1 Friendlier report_gene() failure when pandoc is missing. Patch release for the one user-facing rough edge that surfaced during the post-v0.99.6 install verification: report_gene() requires pandoc (a system tool that powers rmarkdown::render()), but until now the failure was reported as a generic rmarkdown error. Changed - R/report_gene.R — pre-checks rmarkdown::pandoc_available("1.12.3") and raises a friendly error pointing the user at install instructions for RStudio / Debian / macOS / pandoc.org. - README.md Scenario 4 — adds an explicit "System requirement" callout naming pandoc as the dependency. Reaffirms that all other pdactrace functions (query_gene, evidence_math, plot_*, etc.) work without pandoc. No public API changes; nothing to migrate. Changes in version 0.99.6 Optional interpretable ML layer + Bioconductor hygiene patch. Adds an opt-in machine-learning prioritisation layer on top of the v0.99.5 deterministic atlas. Per-axis-first by design: an ML-ready feature matrix, a descriptive feature-space similarity score that uses curated anchors without training a classifier, and a user-supplied supervised wrapper for callers who bring their own labels. The package still ships no pretrained predictor. Deep learning is intentionally out of scope for the core Bioconductor package: PDAC biomarker discovery has limited samples, many features, and ambiguous labels — the regime where DL invites hard-to-defend reviewer questions about training labels, leakage, external validation, and Python / GPU dependencies. DL extensions belong in the manuscript-monorepo, not in the tool package. New - make_evidence_features(genes, scale, impute, drop_na_rows) — flat numeric data.table (genes × ~21 features) suitable for glmnet, ranger, scikit-learn, etc. Computes the same arithmetic that evidence_math() exposes per-axis but in a tabular shape. scale ∈ {"none", "z", "robust"}; impute ∈ {"none", "mean", "zero"} for callers that need complete-case numerics for ML fitting. - score_anchor_similarity(genes, anchors, method, tier) — descriptive cosine / inverse-Euclidean similarity in z-scored feature space to the centroid of the bundled pdactrace_external_anchors set. Reuses the same tier partition (primary / secondary / all) as evaluate_anchor_enrichment(). The bundled anchor labels define the centroid only — they are never used as supervised training labels for any shipped predictor. - fit_user_evidence_model(features, labels, method = "elastic_net", alpha, nfolds, seed) — wraps glmnet::cv.glmnet(family = "binomial"). Requires user-supplied labels; errors politely on NULL, single-class, or length-mismatched inputs. Returns an S3 pdactrace_user_model carrying CV AUC, coefficient table, top-N positive / negative contributors, and a model card. glmnet joins Suggests: (runtime-checked via requireNamespace()). - predict_user_evidence_model(model, new_features) — score new genes from a fitted user model. - explain_user_evidence_model(model, top_n) — print signed top-N positive and top-N negative coefficients with feature names. This is the user-facing rationale for the supervised score ("Main positive / negative contributors"). - model_card(source, model, verbose) — single point of reviewer-facing metadata. For "anchor_similarity": feature set version, anchor count, "no labels used for training", intended use, leakage controls, limitations. For "user_model": same shape, plus n_positives / n_train / CV AUC ± SD / lambda.min / alpha / seed / top contributors. Bioconductor hygiene - .Rbuildignore: now excludes analysis/, data_raw/, figure/, *.pptx, *.docx, *.xlsx, ..Rcheck, pdactrace_*.tar.gz, pdactrace.Rcheck, pdactrace.BiocCheck, plus repo docs (AGENTS.md, CHANGELOG.md, CLAUDE.md, BIOCONDUCTOR.md). Without these, the next R CMD build could pull a 99 GB analysis/ tree into the tarball. - inst/extdata/multi_cohort_consistency.csv.xz (NEW; ~518 KB) — bundles the Stouffer + per-cohort RNA consistency table that data-raw/build_reference.R previously read from analysis/transcriptomics/results/figure1/. The Layer 3 reproducibility claim ("rebuild from documented processed inputs") now actually holds without the manuscript-monorepo. data-raw/build_reference.R routes the read through the same bundled-first lookup chain as the six existing phase CSVs. - data-raw/bundle_multi_cohort_consistency.R — bundler script mirroring data-raw/bundle_phase_csvs.R for this single file. Tests - 4 new test files (~25 test_that blocks): coverage for feature matrix integrity (numeric, no duplicates, scale moments, NA policy), anchor-similarity rank quality (T1 anchors enrich into the top decile), label-leakage discipline (no training labels in score_anchor_similarity(); fit_user_evidence_model() requires user-supplied labels), and model card content. - Full suite: 476 PASS / 0 FAIL. DESCRIPTION - Suggests: gains glmnet (used by fit_user_evidence_model() via runtime requireNamespace(); not a hard dependency for any user who only wants the lookup / scoring / Evidence Math API). - Version bumped 0.99.5 → 0.99.6. Changes in version 0.99.5 Evidence Math layer. Adds a third interpretability layer between the existing plain-English provenance text (format_provenance()) and the audit-score decomposition (explain_score()): the mathematical evidence values that actually fed those decisions, exposed per axis. Per-axis-first by design — there is no new black-box composite score. New - evidence_math(gene_symbol) — returns a structured list with one element per axis (trajectory_fit, effect_magnitude, cohort_consistency, rna_protein_coupling, serum_bridge, cell_specificity, filter_survival, clinical_role). All values are read directly from the bundled atlas or derived by a single named arithmetic operation. New derived quantities: delta_rho = rho_best - rho_runner_up (template specificity margin), ||beta||_2 (Euclidean norm of the per-stage beta vector over E,M,L) and cosine(beta_RNA, beta_prot) (RNA-protein direction concordance). - explain_gene(gene_symbol, view = c("evidence", "math", "both")) — text formatter that prints either the plain-English provenance, the Evidence Math sections, or both. Mirrors explain_score() in pattern (verbose-print + invisible structured return). - compare_genes(gene_symbols, axes, wide) — multi-gene tidy-table pivot of evidence_math() output. Long form by default (gene, axis, metric, value); wide = TRUE for one row per gene with axis.metric columns suitable for manuscript tables. Documentation - README.md: new Evidence Math subsection demonstrating evidence_math("LTBP1"), explain_gene("LTBP1", view = "math"), and compare_genes(...) with truncated example output. - README.md: Reproducibility section rewritten to position the bundled atlas as the default offline path (Layer 1) and the user-cohort projection (Layer 2) as the second core scope. The optional processed-input rebuild (Layer 3) and raw-data reanalysis (Layer 4) are clearly framed as advanced reproducibility / data provenance outside the package's primary user path. download_phase_csvs() is documented as not evaluated during package checks. - README.md: note that the appropriate Bioconductor mechanism for hosting the larger raw quantification matrices is a companion pdactraceData ExperimentHub package, planned for a future release. Changes in version 0.99.4 Reproducibility vignette + on-demand phase33/34 fetcher. Closes the v0.99.3 self-contained-rebuild story: the bundled inst/extdata plus the new download_phase_csvs() helper plus a 4-layer vignette("05_reproducibility") give end users a complete documented path from the prebuilt atlas all the way back to the public phase-CSV inputs, without cloning the manuscript-monorepo. New - download_phase_csvs(target, ref, cache, verbose) — fetches the two large upstream phase CSVs (phase33_deseq2_coef_12template.csv, phase34_protein_pooled_12template.csv) on demand from raw.githubusercontent.com/jibeomko/PDAC_biomarker (Zenodo 10.5281/zenodo.20067849) and caches them via [BiocFileCache::BiocFileCache()]. Returns a named character vector of cached file paths. BiocFileCache is a soft (Suggests) dependency picked up at runtime via requireNamespace() — no impact on packages that only need the query / score / report API. - vignettes/05_reproducibility.Rmd — 4-layer reproducibility guide: 1. Layer 1 — offline, bundled (use data/*.rda directly; no network). 2. Layer 2 — user cohort (project a count / intensity matrix through project_user_cohort()). 3. Layer 3 — re-derive the bundled atlas from the package's own inst/extdata plus the two upstream CSVs cached via download_phase_csvs(). 4. Layer 4 — full FASTQ → counts → fits pipeline (out of scope; pointer to the manuscript-monorepo). Changed - DESCRIPTION — Suggests: gains BiocFileCache for the new helper. Version bumped 0.99.3 → 0.99.4. Imports / Depends are unchanged. Changes in version 0.99.3 Self-contained reproducibility — small phase CSVs bundled in inst/extdata. The package now ships the six small downstream phase tables (phase2c / phase42 / phase77 / phase29 / phase60 / phase80; ~52 KB compressed total) so that the full build_reference.R re-derivation chain runs without the companion manuscript-monorepo. Two large upstream CSVs (phase33 RNA fit, phase34 protein fit) remain external because they push the tarball over Bioconductor's 5 MB limit; the build scripts now fall through a clean lookup chain (inst/extdata/ → $PDAC_BASE_DIR/... → informative error pointing at the manuscript Zenodo archive 10.5281/zenodo.20067849). New - inst/extdata/phase{2c,29,42,60,77,80}_*.csv.xz — bundled, xz-compressed copies of the six small phase outputs that build_reference.R joins onto the RNA/protein base. Total ~52 KB added to the tarball; no impact on R CMD check or BiocCheck. - data-raw/bundle_phase_csvs.R — bundler that re-creates the inst/extdata/*.csv.xz set from the manuscript-monorepo when PDAC_BASE_DIR is set. Strips phase33 to the 16 columns that build_reference.R actually uses; everything else is a verbatim trim + xz pass. Changed - data-raw/build_reference.R — adds an internal read_phase() helper that prefers the bundled inst/extdata copy, falls back to $PDAC_BASE_DIR/.../*.csv (and .csv.xz), and errors with a clear "set PDAC_BASE_DIR or download from Zenodo 10.5281/zenodo.20067849" message if neither exists. Six of the seven fread() calls in the script now route through this helper. The two large CSVs (phase33, phase34) still come via read_phase() but resolve via the fallback chain because the tarball can't accommodate them. - data-raw/build_protein_betas.R — same lookup chain via .find_phase_csv() + xz-aware fread. Re-running the script now works against the bundled CSV (set data/pdactrace_protein_betas.rda rebuild path entirely in-package once the phase34 input is available). Documentation - README "Reproducibility" section update is queued — the current v0.99.0..v0.99.2 wording still claims phase scripts "live in a separate companion repository". A subsequent commit will rewrite this section to acknowledge the bundled inst/extdata chain and the Zenodo download path for the two remaining external CSVs. Changes in version 0.99.2 Human-readable provenance + larger Arial-bold typography on all plots. Two reviewer-facing polish passes: the phaseXX tags that the bundled atlas carries in provenance are now relabelled to plain-English evidence sources on the user-facing print path (phase IDs are preserved verbatim as a Technical: footer for reproducibility), and the NCS-grade ggplot theme that backs every plot_*() function gains larger, sharper Arial-bold typography for clearer single-column embedding. New - format_provenance(provenance, style) (exported) — maps the internal phase tags onto plain-English evidence-source labels. Three styles: "compact" (one-line plus-separated summary), "verbose" (multi-line bulleted list with explanations), "raw" (the original phase tags, for the technical footer). Mapping: phase33 → "RNA trajectory", phase34 → "Tissue protein trajectory", stouffer_consistency → "Multi-cohort RNA consistency", phase2c → "scRNA cell origin", phase42 → "Serum / pancreatitis comparison", phase60 → "7-step serum filter audit", phase77 → "Strict RNA-protein-serum bridge", phase29 → "Resectable-stage marker screen", phase80 → "Predeclared panel member". Unknown tags fall through unchanged with an (unmapped) suffix in verbose mode. Changed - query_gene() print method — replaces the Provenance: line with two lines: Evidence: (plus-separated human labels) and Technical: (the raw phase IDs). - query_gene_detailed() print method — surfaces the verbose bulleted list so that for an interactive query, the reviewer sees a per-source one-line explanation immediately, with the raw IDs folded below. - summarize_gene_evidence() — same two-line restructuring of the trailing provenance block; the rest of the summary text is unchanged. - R/theme.R — pdactrace_axes_theme() and pdactrace_panel_theme() switch font family to Arial with a sans fallback, bump axis titles 6.5 → 8.5 pt (bold), axis text 5.8 → 7.5 pt (now also bold), plot title 8 → 10 pt, subtitle 5.5 → 7.5 pt, legend text 5.4 → 7.0 pt, strip text 5.6 → 7.5 pt, tighten the axis line / tick contrast (grey15 instead of grey30). Plots render the same shape as before but at clearly legible sizes for both single-column and double-column embedding. No API change — every existing plot_*() function picks up the new typography automatically. Changes in version 0.99.1 Per-template trajectory PDFs (RNA + protein). Two new exported functions render the bundled atlas's 12-template trajectory catalogue as compact, NCS-grade PDF panels — one panel per template showing the cohort of genes / proteins that match it best (z-scored Pearson-rho argmax across all 12 templates) as thin translucent lines, a mean line, and a ±1 SD ribbon. Reproduces the historical fig2C_RNA_*.pdf figures inside the package and extends them to the four templates introduced in v0.4.0 (Late_Burst_Up, Late_Loss_Down, Monotonic_Up, Monotonic_Down). New - plot_template_atlas(layer, templates, output_dir, ...) — atlas-wide reference, returns 12 ggplot panels (or a user-chosen subset). When output_dir is set, writes one cairo-PDF per template via pdactrace_save() and reports paths in attr(out, "files"). - plot_gene_template(gene_symbol, layer, output_file, ...) — per-gene overlay: identifies the gene's matched template via the same 12-template Pearson-rho argmax that backs classify_trajectory() / score_trajectory(), then draws that template's cohort with the gene's own z-scored trajectory highlighted on top. Genes whose best-match is a non-Early template (i.e., pdactrace_reference$rna_pattern is NA because only Early × 4 is surfaced) get a visible "non-Early best-match" sub-title. - pdactrace_protein_betas — bundled data.table (5,917 measurable proteins × 8 columns) carrying per-stage tissue-protein effect sizes (prot_beta_N/E/M/L), the full 12-template best-match label, matched ρ, and BH-adjusted F-test padj. Generated by data-raw/build_protein_betas.R from phase34_protein_pooled_12template.csv. Drives the protein layer of the two new plot functions; the main atlas (pdactrace_reference) only carries categorical prot_pattern / prot_tier, which is why this separate object is needed for trajectory visualisation. Edge-case handling .plot_template_panel() (the private layout helper used by both public functions) degrades gracefully on tiny cohorts: cohorts of 1 drop the SD ribbon, cohorts of 2–4 drop the ribbon but keep individual lines, cohorts of ≥ 5 show the full thin-lines + mean + ribbon. This keeps every one of the 12 panels renderable — relevant for template_protein_Late_Loss_Down (n = 1 in the current bundled data). Tests - tests/testthat/test-plot-template-atlas.R — 6 blocks: length-12 / named return shape (RNA + protein), every RNA cohort non-empty, templates subsetting, invalid-name error, output_dir writes one PDF per template. - tests/testthat/test-plot-gene-template.R — 5 blocks: ggplot return for an Early-surface gene, non-Early fallback subtitle for GAPDH (housekeeping), PDF write-out, protein-layer round-trip, missing-gene error. - Total testthat coverage: 262 → 317 PASS on Linux. Changes in version 0.99.0 First Bioconductor submission. Per Bioconductor convention, new packages submit at 0.99.0; subsequent versions in the review queue go 0.99.1, 0.99.2, ... and on acceptance into the release branch the version becomes 1.0.0. The audit framework, the bundled atlas, the 12-template trajectory catalog, and the external anchor evaluation results are all carried forward unchanged from the v0.4.1 development line. v0.99.0 is the first version made visible to Bioconductor and consolidates everything below in a single release. Companion repositories and DOIs - Software (this package): github.com/jibeomko/pdactrace, Zenodo concept DOI 10.5281/zenodo.20069896. - Manuscript reproducibility monorepo: github.com/jibeomko/PDAC_biomarker, Zenodo 10.5281/zenodo.20067849. New — single-gene + panel evidence reports - report_gene(gene_symbol, ...) — accepts either a single HGNC symbol or a multi-gene character vector. Length 1 produces a self-contained one-page HTML evidence report (audit-class tag, audit-component table, six-axis evidence radar versus the high_confidence_mean reference, stage-trajectory plot, per-cohort breakdown, per-stage detail table, filter trace, atlas-version provenance footer). Length 2+ produces a panel template with a compare_candidates() table at the top, a multi-gene evidence radar, and one explain_score()-derived rationale card per gene. Both templates use a minimal inline CSS (no Bootstrap) and weigh ~230–410 KB. Templates: inst/rmd/gene_report.Rmd, inst/rmd/panel_report.Rmd. rmarkdown and knitr are picked up at runtime from Suggests via requireNamespace() — no hard dependency added. New — audit-framework explainability - explain_score(gene_symbol, verbose = TRUE) — decomposes one gene's audit_score into the three weighted evidence axes (evidence_strength 40%, biological_coherence 35%, translational_relevance 25%) and the two reliability gates (leakage_gate, heterogeneity_gate). Returns a list with the structured breakdown plus a one-paragraph plain-English rationale derived from which gate state actually fired (housekeeping flag, plasma-high-abundance flag, max meta I² bracket). E.g., "LTBP1 lands in supported_uncertain because the heterogeneity_gate = 0.7 — max meta I² = 75% in [70%, 90%)". - compare_candidates(gene_symbols) — one row per input gene with audit class + score, RNA / protein trajectory pattern, translation class, dominant scRNA cell origin, serum detectability, max meta I², plus a redundancy_with column flagging genes that share both rna_pattern and cell_origin_top in the input set. Sorted by audit_score descending; missing genes returned as NA rows. - project_user_cohort(rna, coldata, stage_col, cohort_col, ...) — end-to-end wrapper around fit_stage_de() → classify_trajectory() → assemble_user_evidence() → compute_audit_score(). Accepts either a count matrix + coldata, or a SummarizedExperiment whose colData() carries the stage / cohort columns. Optional protein argument (matrix or SE) layers in tissue-protein evidence on the same design. Returns a pdactrace_user_projection list with each intermediate object (rna_fit, rna_pattern, prot_fit, prot_pattern, evidence, audit) plus a one-row summary of audit-class counts. Designed to make "apply pdactrace to my own staged cohort" a single line. New — single-patient trajectory alignment - align_patient_profile(rna_logfc, prot_logfc = NULL, ...) — sample-level analog of score_trajectory(). Computes audit-weighted Pearson rho between the patient's per-gene log2FC vector and each of the three atlas stage axes (rna_beta_E, rna_beta_M, rna_beta_L), with Fisher-z 95% CI, plus a secondary audit-weighted vote share that surfaces disagreement-with-rho as a diagnostic. Returns a pdactrace_patient_alignment list with $rna (4-row data.table), $prot (categorical concordance, optional), $summary (one-line), and $attrs (provenance). Misalignment with all three stage axes is a legitimate output and does not imply Normal. Discipline-aligned: deliberately not a supervised classifier — an RF / GLM trained on TCGA stage labels would break the package's "no supervised fitting under limited ground truth" core principle. New — Bioconductor-native input and atlas view - fit_stage_de(object, ...) and fit_stage_de_protein(object, ...) are S4 generics with two methods each. The ANY method preserves the original matrix / data.frame signature (fit_stage_de(counts, stage, cohort)); a new SummarizedExperiment method accepts fit_stage_de(se, stage_col, cohort_col, assay_name = "counts") (and assay_name = "intensity" for the protein side). Both paths share the same DESeq2 LRT (RNA) / limma (protein) kernel and produce numerically identical output (verified by tests/testthat/test-se-input.R). - as_summarized_experiment(reference = NULL) — converts the bundled 10,113-gene atlas into a SummarizedExperiment with two assays (rna_beta, rna_lfcSE; both 10,113 × 4 stages), a 4-row colData (stage, reference_level), a ~109-column rowData (audit components, RNA / protein trajectory pattern, translation class, scRNA cell origin, serum direction, meta-analysis I², ...), and atlas-provenance metadata. The bundled object remains a data.table for fast query-based use cases; this constructor is the Bioc-native view on demand. New — bundled toy cohort and provenance helpers - toy_counts (50 × 24 integer matrix; 10 stage-progressive rows), toy_coldata (24 rows: stage, cohort, sample), and toy_protein (50 × 24 log2 matrix; 8 stage-progressive rows). Generated by data-raw/build_toy_data.R with set.seed(2026). The user-cohort vignette uses these in place of inline synthetic generation so examples run end-to-end with no external download. - pdactrace_data_sources — bundled data.table, one row per public dataset (GEO / PRIDE / PDC / ICGC / GTEx / MassIVE / SRA) contributing to the v0.99 atlas (26 rows: 6 RNA + 3 Protein + 10 scRNA + 3 Serum + 2 Pancreatitis + 2 Validation). Generated by data-raw/build_data_sources.R from the manifest TSVs. - list_data_sources(layer = NULL) — accessor for the data-source table, with optional layer filter. - atlas_provenance() — one-call provenance dossier returning package version, atlas snapshot, both Zenodo DOIs, both repo URLs, cohort count, and per-layer dataset count. New — short function aliases Five exported aliases alongside their fully-spelled originals to reduce typing friction. Both forms refer to the same function and share one Rd page; existing scripts using the long names continue to work unchanged. | Long name (kept) | Short alias (new) | |---|---| | evaluate_anchor_enrichment() | anchor_enrichment() | | early_pattern_names() | early_patterns() | | mid_pattern_names_excluded() | mid_patterns() | | align_patient_profile() | align_patient() | | classify_protein_trajectory() | classify_prot_trajectory() | Changed - plot_gene_hexagon() migrated from bare theme_void() to pdactrace_panel_theme() so all 10 plot functions now share the same NCS-grade typography (single-column 88 mm, NCS_W_15COL = 4.72 in, NCS_W_DOUBLE = 7.08 in). geom_text sizes reduced to 1.7–2.2 mm (≈5–6.5 pt) so the hexagon embeds cleanly at single-column width. - pdactrace_save() replaces cat() with message() so package diagnostics route through the standard message stream (BiocCheck-compliant). - The internal .audit_mc_table() Monte-Carlo helper replaces the manual set.seed() + on.exit() save/restore block with a single withr::local_seed(seed) call. The seed parameter is scoped to the helper and the global RNG state is restored on function exit — same behaviour, BiocCheck-compliant. - README adds a horizontal 6-panel workflow figure at the top (man/figures/pdactrace_overview.jpg, 1800 × 1344, 280 KB, hand-drawn, license-clean): staged omics evidence → 12-template trajectory matching → Early-onset atlas surface → multi-layer evidence integration → 3-axis + 2-gate audit scoring → user outputs (query_gene · explain_score · compare_candidates · trace_filters · project_user_cohort). Closing tagline: "Transparent prioritization, not a supervised diagnostic classifier." DESCRIPTION - Version: 0.99.0. Authors@R is canonical; the redundant Author: / Maintainer: lines are omitted. - Depends: R (>= 4.5.0) (Bioconductor 3.22's minimum supported R). - Imports: data.table, ggplot2, patchwork, glue, methods, stats, utils, withr, SummarizedExperiment. - Suggests: DESeq2, limma, S4Vectors, testthat (>= 3.0.0), knitr, rmarkdown, pkgdown. - LazyData: true, LazyDataCompression: xz, Roxygen: list(markdown = TRUE), Config/testthat/edition: 3. Tests - tests/testthat/test-se-input.R — matrix vs SummarizedExperiment numerical equivalence for both fit_stage_de (DESeq2) and fit_stage_de_protein (limma), plus informative-error coverage on missing colData columns / assay_name. - tests/testthat/test-explain-compare-se.R — explain_score() structure + missing-gene error, compare_candidates() row count + sort order + missing-gene padding, as_summarized_experiment() shape + reference-column invariant. - tests/testthat/test-marker-class-stability.R — pins LGALS3BP (high_confidence), LTBP1 (supported_uncertain), ALB (penalized), GAPDH (excluded); verifies compare_candidates() ordering on the four case studies; round-trips toy_counts through fit_stage_de() + classify_trajectory(); checks list_data_sources() shape + filter and atlas_provenance() Zenodo-DOI invariants. - Total testthat coverage at v0.99.0: 251 PASS. Verification (R 4.5.2 conda, matched libs) - R CMD check --as-cran: 0 ERROR, 1 WARN, 6 NOTE. The single WARN is qpdf needed for PDF size checks — env-only (the Bioconductor build farm has qpdf installed); no substantive WARN remains. - BiocCheck(new-package = TRUE): 0 ERROR, 0 WARN, 15 NOTE. Changes in version 0.4.0 User-data extension track + dual-classification cleanup — additive, backwards-compatible API that lets a new user run the v0.3.0 audit framework on their own multi-omics cohort. The frozen 3-axis + 2-gate rule, the audit labels, and all v0.3.0 evaluation results remain unchanged. Removed (breaking schema change) - v0.2.0 confidence-tier columns (confidence_tier, early_onset_score, heterogeneity_factor) are dropped from the bundled atlas. They were superseded by v0.3.0 audit_class and retained as legacy in v0.3.0 for ablation; the dual-classification was creating reviewer-grade ambiguity (e.g., LGALS3BP scoring audit_class = high_confidence for strong multi-layer convergence while the v0.2 tier flagged it ARTIFACT for low single-layer effect size). v0.3.0 audit_class is now the canonical per-gene classification. - list_candidates() no longer accepts min_tier. Use the new min_audit_class parameter instead. Default changed from "SILVER" to "ALL" (no audit-class filter applied) — explicit filtering by audit_class is the intended workflow. - The audit-framework numerical inputs max_abs_beta_meta and max_I2_meta are retained because they feed the heterogeneity_gate and rescue-eligibility logic. - Atlas dimensions: 10,113 × 116 → 10,113 × 113 columns. New - plot_gene_hexagon(gene_symbol, comparison) — compact 6-axis hexagonal radar chart of a gene's audit-feature profile (Multi-layer / Direction / Stage-onset / Serum bridge / Leakage safety / Cohort consistency). Multi-gene overlay and optional comparison polygon (e.g., comparison = "high_confidence_mean") are supported; designed as a high-quality NCS-grade per-gene summary card. - fit_stage_de_protein(intensity, stage, cohort) — limma-based parallel of fit_stage_de for user-supplied tissue-protein intensity matrices. Returns the same column schema so downstream trajectory classification works for either layer. - classify_protein_trajectory(fit, rho_cutoff) — protein-side wrapper of classify_trajectory that renames the output column from rna_pattern to prot_pattern for assembly downstream. - assemble_user_evidence(rna_fit, prot_fit, scrna_summary, serum_summary, signal_peptide, cross_cohort_agreement, max_I2) — combines optional per-layer user inputs into a per-gene evidence table conforming to the schema columns the bundled atlas exposes; layers the user does not supply are filled with NA and degrade gracefully through the existing feature constructor. Modified - 12-template trajectory catalog (was 8-template in v0.3.0). Adds Late × 2 (Late_Burst_Up, Late_Loss_Down — onset at Stage III/IV; Peak/Trough/Plateau are structurally degenerate at the last stage) and pan-stage Monotonic × 2 (Monotonic_Up, Monotonic_Down — linear progression with maximum at Late, distinct from Mid_Plateau_* which has its largest jump at Stage II). Atlas surface (rna_pattern) still exposes only Early × 4 by design; the other 8 templates compete in the matching step and are flagged via excluded_mid_pattern, excluded_late_pattern, excluded_monotonic_pattern. Effect on numbers: GAPDH and CDH13 correctly reclassified as Monotonic_Up and dropped from the Early surface (housekeeping/leaky-plasma genes that previously contaminated Early × 4); RNA × Protein 4-Early-concordant set 1,424 → 1,356; full Tier 1 gold (any 12-template match) 1,449 → 1,375. Headline anchor enrichment numbers are invariant (deterministic top-100 secondary: 7 hits / 39.3× / p = 2.18e-10 unchanged from v0.3.0; LOO median 41.6, bootstrap 95% CI [20.2, 56.3]). - Atlas schema gains three columns rna_wald_padj_E/M/L — genuine per-contrast Wald padj (Early/Mid/Late vs Normal) from a nbinomWaldTest() refit of the same ~ dataset + stage_group model used for the LRT. rna_padj_E/M/L remain in the schema for back-compat but are LRT padj copies (DESeq2 LRT mode returns the same omnibus padj for every per-contrast results() call). The audit framework continues to use rna_lrt_padj as its significance gate, so no v0.3.0 audit numbers change. query_gene_detailed() $per_stage now exposes both lrt_padj and wald_padj columns; plot_stage_effect() uses Wald padj for the per-stage * marks. - compute_audit_score(gene_symbol, evidence = NULL) — new evidence parameter accepts a user-supplied evidence table (e.g., the output of assemble_user_evidence). When NULL (default), the bundled v0.3.0 reference atlas is used; behaviour and numbers are bit-for-bit identical to v0.3.0. - propagate_uncertainty(gene_symbol, n_mc, seed, evidence = NULL) — same evidence override; stored MC summaries are unavailable for user evidence and n_mc must be supplied in that case. - evaluate_anchor_enrichment(top_n, tier, score_col, evidence = NULL, anchors = NULL) — both the evidence table and the anchor table can be overridden so a user can run anchor enrichment against their own evidence and their own anchor reference set. - .get_reference(reference = NULL) — internal helper now accepts an optional reference override; default behaviour unchanged. - .audit_genes(genes, reference = NULL) — internal helper takes an optional reference for membership checks against user evidence. New vignette - user_cohort_extension.Rmd — five-step walkthrough on a small synthetic example showing user RNA + protein → assemble_user_evidence → compute_audit_score → evaluate_anchor_enrichment with a user-supplied anchor list. Runs in <60 s under devtools::check(). New tests - tests/testthat/test-user-extension.R — round-trip on a fixed synthetic example: schema sanity for both fit functions, full audit-score column schema after assemble_user_evidence, and a backwards-compat assertion that compute_audit_score(evidence = NULL) matches the bundled v0.3.0 result. Scope boundary The PDAC reference atlas remains the default reference; v0.4 does not provide a build_user_atlas() function or layer plugin architecture. Disease-agnostic atlas building is planned for v0.5 (see Discussion §6 of the BiB manuscript). Suggests - limma is added to Suggests so fit_stage_de_protein() can be loaded conditionally; users who do not need protein input do not need to install limma. Changes in version 0.3.0 Audit framework track — replaces opaque marker tiers with a transparent, pre-specified evidence aggregation framework for PDAC early-marker hypothesis prioritization. The deterministic rule summarises each gene along three evidence axes (evidence_strength, biological_coherence, translational_relevance), applies two reliability gates (leakage_gate, heterogeneity_gate), and assigns it to one of interpretable audit labels (high_confidence, supported_uncertain, penalized, excluded, low). This release does not train a supervised biomarker predictor; external anchors are used only for post-freeze enrichment evaluation. New - build_evidence_graph(gene) — returns a descriptive evidence graph for a gene, including layer presence, direction agreement, early-pattern support, serum bridge, leakage gate, heterogeneity gate, and final audit score. - extract_graph_features(gene) — exposes the deterministic feature components that compose the three evidence axes (mapping in supplement Table S1). - compute_audit_score(gene) — computes the frozen v0.3.0 score audit_score = positive_score × leakage_gate × heterogeneity_gate with positive_score = 0.40 × evidence_strength + 0.35 × biological_coherence + 0.25 × translational_relevance, normalized to the atlas-wide maximum, and assigns an audit_class label per gene. - propagate_uncertainty(gene) — returns Monte Carlo score/rank intervals and a confidence_class (stable_high, high_uncertain, medium, low, excluded) reported alongside the deterministic audit_class. - evaluate_anchor_enrichment(top_n, tier) — evaluates top-N enrichment of external PDAC biomarker anchors against the frozen audit ranking; anchors are never used for training or weight tuning. - case_study(genes) — combines v0.2 tier, deterministic audit_class, MC uncertainty, anchor provenance, and the composite pdactrace_call label for manuscript panels. Reference DB schema (84 → 111 columns) 27 populated audit_* columns: - 3 evidence axes (new in 3+2 reparameterization): audit_evidence_strength, audit_biological_coherence, audit_translational_relevance. - 2 reliability gates (new): audit_leakage_gate, audit_heterogeneity_gate. - Audit-label assignment (new): audit_class (high_confidence / supported_uncertain / penalized / excluded / low). - Internal feature components (kept for supplement reproducibility): audit_score_layer, audit_score_direction, audit_score_early, audit_score_serum, audit_score_rescue, audit_positive_score, audit_leakage_mult, audit_heterogeneity_mult, audit_score_raw, audit_score, audit_is_housekeeping, audit_is_plasma_high_abundance, audit_rescue_eligible. - Monte Carlo uncertainty: audit_score_median, audit_score_lo95, audit_score_hi95, audit_uncertainty_width, audit_rank_median, audit_rank_lo95, audit_rank_hi95, audit_confidence_class. Audit validation - External anchor enrichment is strong under the frozen 3+2 rule with deterministic audit_score ranking: secondary Tier 1+2 anchors show 7 hits in the top 100 (39.3×, hypergeometric p = 2.2e-10; hits = MSLN, THBS2, CEACAM1, TIMP1, MUC16, SERPINA1, ANPEP) — strengthened from the prototype 7-feature flat-weight implementation (5 hits / 28.1× / p = 6.6e-07). - Robustness under the v0.3.0 rule: leave-one-anchor-out median fold 41.6× (range 35.7–41.6×); bootstrap median 40.5× with 95% CI [20.2, 56.3] (1,000 iterations). MC-median ranking (audit_score_median) gives 5 hits / 28.1× and is reported as a sensitivity ranking (Methods §7). - Negative rejection is explicit: housekeeping genes receive a hard leakage_gate = 0 (audit_class = excluded), and high-abundance plasma proteins receive leakage_gate = 0.5 (audit_class = penalized). - Case-study behavior matches the intended framing: LGALS3BP and THBS2 are high_confidence, LTBP1 is supported_uncertain (heterogeneity-gated), ALB is penalized, and GAPDH is excluded. Manuscript figures (PDAC_졸업final5/) - F1 — overview infographic (3 axes + 2 gates + audit labels). - F2 — Sankey from v0.2 tier to audit labels + anchor target board (39.3×, p = 2.2e-10) + housekeeping rejection traffic light + audit-label showcase + robustness badges. - F3 — multi-layer evidence aggregation (per-cohort RNA forest, RNA × Protein direction, scRNA cell origin, serum bridge, cross-layer support). - F4 — top candidate landscape (4 mini-cards, top-30 ranked table, mechanism distribution, rescue showcase, layer coverage matrix). - F5 — clinical demonstration (LTBP1+SERPINA1 LOOCV ROC, illustrative) + R API quick-start + anchor provenance + tool ecosystem badge. Changes in version 0.1.1 Granularity track — exposes hidden per-stage / per-cohort / per-celltype / per-filter-step detail that v0.1.0 only summarized at the headline level. No breaking changes: all v0.1.0 functions preserved; new functions are additive. New - query_gene_detailed(gene) — returns 5-slot data.table list: per_stage, per_cohort, per_celltype (all 11), filter_diag, serum_per_cohort. Stouffer p, agreement %, specificity tau, PDAC-vs-Pan t-pval exposed as table attributes. - summarize_gene_evidence(detail = TRUE) — adds per-stage, per-cohort, pancreatitis raw means, and filter underlying-metric block to text summary. - 4 new plot functions: - plot_stage_effect() — log2FC ± 95% CI forest with significance asterisks per stage. - plot_per_cohort() — TCGA / CPTAC / GSE224564 / GSE79668 trend - monotonic indicator + Stouffer summary annotation. - plot_filter_diagnostics() — 7-step filter bar with underlying metric annotation (e.g., pool padj = NA, pan-vs-HC pval = 0.017). - plot_celltype_full() — full 11-celltype expression bar with PDAC-relevant cell types highlighted in red. Reference DB schema (45 → 62 columns) 13 new populated columns: - rna_padj_E/M/L, rna_lfcSE_E/M/L (per-stage) - rna_stouffer_p, rna_stouffer_padj - rna_per_cohort_trend, rna_per_cohort_monotonic (list-cols) - cell_specificity_tau - ann_pan_vs_hc_logfc, ann_pan_vs_hc_pval, ann_pan_excluded_phase60 - ann_pdac_mean, ann_pan_mean, ann_hc_mean, ann_pdac_vs_pan_pval Audit findings exposed by v0.1.1 - LTBP1: 4-cohort RNA divergence (TCGA Increasing + monotonic vs CPTAC Decreasing + monotonic vs 2 non-monotonic; Stouffer p=0.51, 50% agreement). The headline Early_Burst_Up label hides this. - SERPINA1: passes all 7 phase60 filters (only gene to do so among the 4 panel members). Per-stage ↑ +1.05/+0.76/+0.72. Tests - 100 testthat passes (current 59 + 41 new). Changes in version 0.1.0 Initial public release of PDAC-TRACE — queryable PDAC stage-aware multi-omics gene-level lookup atlas. Central message: PDAC tissue biomarker ≠ always serum-up biomarker. Tissue-derived candidates can preserve, invert, or decouple when projected into serum. Framework Originally introduced as a 4-Early-pattern trajectory framework (v0.1.0). Widened in v0.4.0 to a 12-template competitive catalog (Early × 4 + Mid × 4 + Late × 2 + Monotonic × 2) where each gene must out-compete 11 alternatives before being surfaced as Early. The atlas surface (rna_pattern) restricts visible calls to: - Early_Burst_Up — Normal low → Early up → sustained - Early_Loss_Down — Normal high → Early down → sustained - Early_Peak — Early peak → Mid/Late decline - Early_Trough — Early trough → Mid/Late recovery Mid / Late / Monotonic best-matches are flagged via excluded_mid_pattern / excluded_late_pattern / excluded_monotonic_pattern for transparent provenance. Features - Reference atlas — pdactrace_reference (10,113 genes × 45 cols) bundling 8 source phase result CSVs across bulk RNA-seq, tissue proteomics, scRNA cell origin, serum proteomics, pancreatitis context, and phase60 7-step filter audit trail. - Lookup API — query_gene(), query_panel(), list_candidates() (multi-param), trace_filters(), summarize_gene_evidence(), list_atlas_metadata(). - Trajectory scoring — fit_stage_de(), classify_trajectory(), score_trajectory() for users with their own bulk RNA-seq. - Visualization — plot_gene_evidence(), plot_filter_trace(), plot_panel_heatmap(), plot_candidate_landscape(). - Vignettes — 01_lookup_basics, 02_ltbp1_case_study. LTBP1 narrative (inverse stromal exemplar) - RNA: Early_Burst_Up (rho ≈ 1.0) - Tissue protein: Early_Burst_Up (Tier 1 gold concordant) - scRNA cell origin: myCAF / iCAF dominant - Serum: detected, Class B (inverse) — PDAC down vs HC, pancreatitis-elevated - Filter audit: phase77_classB route — passes phase77 strict + Class B + manual curation, while phase60 strict 7-step funnel only captures SignalP Design - 4-Early-only surface, by design (v0.1.0; in v0.4.0 the catalog itself widens to 12 templates and Mid / Late / Monotonic best- matches are flagged via excluded_*_pattern rather than surfaced — see v0.4.0 entry above). - Class B is manually curated, not predicted. - Two parallel narrowing funnels (phase60 strict vs phase77 strict) can disagree — trace_filters() shows both routes honestly. Deferred - v0.2 (optional): calibrated detectability classifier (predict_detectability()). - Future paper: direction predictor (Class A vs B), inverse marker risk modeling, web/Shiny version, cross-cancer generalization.