medsci-skills 5.13.0 → 5.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +65 -9
  2. package/metadata/distribution_files.json +136 -16
  3. package/metadata/distribution_manifest.json +3 -1
  4. package/metadata/skills_catalog.json +22 -2
  5. package/package.json +1 -1
  6. package/skills/analyze-stats/SKILL.md +2 -1
  7. package/skills/analyze-stats/references/analysis_guides/calibration.md +132 -0
  8. package/skills/explainability/SKILL.md +109 -0
  9. package/skills/explainability/references/explainability_guide.md +66 -0
  10. package/skills/explainability/scripts/check_explainability_report.py +239 -0
  11. package/skills/explainability/scripts/check_explainability_report_challenge/expected/strong.txt +9 -0
  12. package/skills/explainability/scripts/check_explainability_report_challenge/expected/weak.txt +11 -0
  13. package/skills/explainability/scripts/check_explainability_report_challenge/fixture/report_strong.json +9 -0
  14. package/skills/explainability/scripts/check_explainability_report_challenge/fixture/report_weak.json +8 -0
  15. package/skills/explainability/scripts/check_explainability_report_challenge/problem.md +19 -0
  16. package/skills/explainability/scripts/check_explainability_report_challenge/verify.sh +37 -0
  17. package/skills/explainability/skill.yml +45 -0
  18. package/skills/explainability/tests/test_explainability_report.sh +88 -0
  19. package/skills/peer-review/references/domain-probes/survival_prognostic.md +1 -0
  20. package/skills/preprocess-imaging/SKILL.md +117 -0
  21. package/skills/preprocess-imaging/references/preprocessing_guide.md +69 -0
  22. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage.py +294 -0
  23. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/expected/clean.txt +9 -0
  24. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/expected/leak.txt +12 -0
  25. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/fixture/manifest_clean.json +16 -0
  26. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/fixture/manifest_leak.json +17 -0
  27. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/problem.md +20 -0
  28. package/skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/verify.sh +39 -0
  29. package/skills/preprocess-imaging/skill.yml +45 -0
  30. package/skills/preprocess-imaging/tests/test_preprocessing_leakage.sh +77 -0
  31. package/skills/self-review/references/domain-probes/survival_prognostic.md +1 -0
  32. package/skills/self-review/scripts/check_scope_coherence.py +18 -1
  33. package/skills/self-review/tests/fixtures/scope_antipattern_list.md +13 -0
  34. package/skills/self-review/tests/test_scope_coherence.sh +14 -0
  35. package/skills/write-paper/SKILL.md +3 -3
  36. package/skills/write-paper/references/exemplar_discussion/README.md +2 -0
  37. package/skills/write-paper/references/exemplar_discussion/rct_consort.md +42 -0
  38. package/skills/write-paper/references/exemplar_methods/README.md +1 -0
  39. package/skills/write-paper/references/exemplar_methods/rct_consort.md +55 -0
  40. package/skills/write-paper/references/exemplar_results/README.md +2 -0
  41. package/skills/write-paper/references/exemplar_results/rct_consort.md +38 -0
package/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  # MedSci Skills
4
4
 
5
- **51 skills that actually work.** Built by a physician-researcher, tested on real publications.
5
+ **53 skills that actually work.** Built by a physician-researcher, tested on real publications.
6
6
 
7
7
  *MedSci Skills is an end-to-end research tool for physician and medical-engineering researchers — design → scaffold → validate → publish — for the clinical manuscript and the medical-AI model behind it. Its moat is the compliance layer — 44 reporting guidelines and risk-of-bias tools, reference/citation verification, and deterministic integrity gates before peer review — now extended by a model-engineering lane that scaffolds reproducible, leakage-safe training repos and audits model validation. Clinical AI model research engineering is in scope; a general AI-scientist platform is not. It competes on clinical submission reliability, not skill count.*
8
8
 
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
10
  [![Release](https://img.shields.io/github/v/release/Aperivue/medsci-skills?style=flat-square&color=blue)](https://github.com/Aperivue/medsci-skills/releases/latest)
11
11
  [![CI](https://img.shields.io/github/actions/workflow/status/Aperivue/medsci-skills/validate.yml?branch=main&style=flat-square&label=CI)](https://github.com/Aperivue/medsci-skills/actions/workflows/validate.yml)
12
- ![Skills](https://img.shields.io/badge/Skills-51-brightgreen?style=flat-square)
12
+ ![Skills](https://img.shields.io/badge/Skills-53-brightgreen?style=flat-square)
13
13
  [![npm](https://img.shields.io/npm/v/medsci-skills?style=flat-square&label=npm&color=cb3837)](https://www.npmjs.com/package/medsci-skills)
14
14
  [![Watch the 2-min intro](https://img.shields.io/badge/▶_Watch-2--min_intro-FF0000?style=flat-square&logo=youtube&logoColor=white)](https://youtu.be/MclQ_RIofpE)
15
15
  [![good first issues](https://img.shields.io/github/issues/Aperivue/medsci-skills/good%20first%20issue?style=flat-square&label=good%20first%20issues&color=7057ff)](https://github.com/Aperivue/medsci-skills/contribute)
@@ -285,6 +285,8 @@ The E2E pipeline (`orchestrate --e2e`) produces everything up to `qc/`. The `sub
285
285
 
286
286
  ## What's New
287
287
 
288
+ **v5.15** — model-engineering produce-side depth. Two new skills that *produce* what the review lane previously only audited: **`preprocess-imaging`** (DICOM/NIfTI data prep + a `check_preprocessing_leakage` gate that extends the split-leakage moat upstream to the data stage) and **`explainability`** (Grad-CAM / saliency held to the reviewer bar — Adebayo sanity checks, quantitative localisation vs ground truth, attribution-not-validation framing, via `check_explainability_report`). Plus a by-stage skill index, multi-host README/About (Claude Code · Codex · Cursor · Copilot), copy-paste citation ergonomics, and a real-project precision fix. Additive and backward-compatible; **53 skills / 44 guidelines / 48 integrity detectors / 22 domain-probe modules**. (See the [CHANGELOG](CHANGELOG.md) for v5.0–v5.14.)
289
+
288
290
  **v4.10** — reviewer-coverage expansion reverse-engineered from high-IF, CC-BY papers (learn-only under the `reverse_engineer/` license firewall), plus a clinician-friendly update path. Additive and backward-compatible; 45 skills / **44 guidelines** / 36 detectors / **15 domain-probe modules** (was 12):
289
291
 
290
292
  - **Three new reviewer domain-probe modules** (`/peer-review` + `/self-review`, vendored byte-identical): **Mendelian randomization** (MR1–MR8 — IV assumptions, pleiotropy-robust sensitivity suite, Steiger, sample overlap, NLMR, drug-target colocalization), **polygenic risk score** (PG1–PG8 — ancestry portability, base/target leakage, incremental value over the clinical model, screening-vs-discrimination, calibration), and **network meta-analysis** (NM1–NM8 — transitivity, incoherence, SUCRA over-interpretation, CINeMA/GRADE-NMA, component-NMA additivity). Plus observational **O17** (agnostic many-exposure-scan multiplicity: ExWAS/EWAS/MWAS).
@@ -447,6 +449,21 @@ ma-scout -> search-lit -> fulltext-retrieval -> design-study ──> write-proto
447
449
  └─────────────────────────────────────────────┘
448
450
  ```
449
451
 
452
+ ### By research stage
453
+
454
+ All 53 skills, grouped by where they fit in the clinical-manuscript and medical-AI lifecycle. Full descriptions are in the table below; one page per skill lives in the [per-skill reference](docs/skills/).
455
+
456
+ | Stage | Skills |
457
+ |-------|--------|
458
+ | 🔭 **Discover & scope** | `ma-scout` · `find-cohort-gap` · `search-lit` · `fulltext-retrieval` · `lit-sync` · `author-strategy` |
459
+ | 📐 **Design & plan** | `design-study` · `calc-sample-size` · `define-variables` · `write-protocol` · `fill-protocol` · `design-ai-benchmarking` |
460
+ | 🧹 **Data & analysis** | `deidentify` · `clean-data` · `generate-codebook` · `version-dataset` · `analyze-stats` · `batch-cohort` · `cross-national` · `replicate-study` |
461
+ | 🤖 **Medical-AI model engineering** | `preprocess-imaging` · `architecture-zoo` · `model-scaffold` · `model-validation` · `model-evaluation` · `explainability` · `model-card` · `mllm-eval` |
462
+ | ✍️ **Write & visualize** | `write-paper` · `make-figures` · `review-paper` · `present-paper` · `humanize` · `polish-language` · `academic-aio` |
463
+ | ✅ **Comply & verify** | `check-reporting` · `self-review` · `verify-refs` · `manage-refs` |
464
+ | 📤 **Submit & respond** | `find-journal` · `add-journal` · `sync-submission` · `revise` · `peer-review` · `fill-icmje-coi` |
465
+ | 🧭 **Orchestrate & manage** | `orchestrate` · `intake-project` · `manage-project` · `meta-analysis` · `grant-builder` · `publish-skill` · `render-pdf-doc` · `setup-medsci` |
466
+
450
467
  ### Available Now
451
468
 
452
469
  | Skill | What It Does |
@@ -463,10 +480,12 @@ ma-scout -> search-lit -> fulltext-retrieval -> design-study ──> write-proto
463
480
  | **design-study** | Study design review: identifies analysis unit, cohort logic, data leakage risks, comparator design, validation strategy, and reporting guideline fit. |
464
481
  | **design-ai-benchmarking** | Design and validity review for benchmarking AI system(s) against a human-expert panel: evaluation-question and arm definition, decoupled multi-dimensional rubrics with anchors, planted calibration probes (positive-control / known-bad / instability / mechanism-contradiction), reviewer-panel construction with per-reviewer randomization, inter-rater reliability targets with separate control-item reliability, LLM-as-judge vs human-as-judge adjudication, construct-independence guards, and a structured JSON rating-export schema. Locks the rubric before data collection. |
465
482
  | **model-validation** | Design or audit the clinical-validation study for an engineer-built medical-imaging model (segmentation / classification / detection): patient-level split disjointness and the data-leakage taxonomy, tuning-on-test, internal vs genuine external validation, comparator design, single-run vs multi-seed variance, task-correct metric selection (Metrics Reloaded), test-set sizing, and CLAIM 2024 / TRIPOD+AI / STARD-AI reporting fit. Ships a deterministic split-leakage gate that proves patient disjointness by set arithmetic on the emitted split table. Integrates with MONAI / nnU-Net — does not replace them. |
483
+ | **preprocess-imaging** | Design or audit the data-preparation stage of a medical-imaging model — DICOM/NIfTI intake, resampling, intensity normalization, and the augmentation plan — so the pipeline is leakage-safe before `model-scaffold` builds the training repo. Emits a declarative preprocessing manifest and a deterministic data-stage leakage gate (`check_preprocessing_leakage`) that catches what the split table cannot see: a dataset-level normaliser fit on non-train data (`NORMALIZATION_LEAKAGE`), a data-fitted transform run before the split (`PREPROCESS_BEFORE_SPLIT`), and a patient's slices crossing splits (`PATIENT_CROSS_SPLIT`). Integrates MONAI / TorchIO transforms; never reimplements them or touches real patient data. |
466
484
  | **model-scaffold** | Generate a reproducible, runnable PyTorch training repo for a medical-imaging task — segmentation (U-Net), classification, detection, image-to-image synthesis, or self-supervised pretraining — the missing middle link between choosing an architecture and validating a trained model. Emits a patient-level seed-locked split as an auditable artifact, a task-appropriate model, train/evaluate scripts that seed every RNG and infer under eval mode, a config, requirements, a reproducibility record, and a Methods stub with VERIFY placeholders (no fabricated numbers). Reproducibility holds by construction; ships a `check_training_hygiene` AST gate + a network-free build→validate challenge. Emits a minimal runnable default model for a forward-pass smoke test, and integrates with MONAI / nnU-Net / TorchIO / timm / torchvision for production-grade models. |
467
485
  | **architecture-zoo** | "Which architecture for which research question" decision tool: maps task (classification / segmentation / detection / transfer), modality, data scale, and class imbalance to a paper-grounded architecture shortlist. Curates the foundational curriculum (ResNet / DenseNet / EfficientNet / ViT / Swin; U-Net / 3-D U-Net / Attention & Residual U-Net / nnU-Net / Mask R-CNN; SAM/MedSAM / TotalSegmentator / BiomedCLIP / DINO / MAE / SimCLR) — each with core idea, when-to-use, medical-imaging use, reference implementation, validation setup, and the matching model-scaffold template. Advisory; teaches archetypes, not a live SOTA leaderboard. |
468
486
  | **model-card** | Generate the documentation an engineer-built medical-imaging model must carry — a Model Card (Mitchell et al. 2019), a Datasheet for its dataset (Gebru et al. 2021), and a METRIC-informed data-quality pass — filled from user-supplied facts (never fabricated), then verify every required section is present and non-empty with a deterministic completeness gate (`check_model_card_complete`). Model Card / Datasheet are documentation standards vendored as templates, not counted reporting checklists. |
469
487
  | **model-evaluation** | Compute and report task-correct held-out metrics for a trained medical-imaging model — segmentation (Dice + a boundary metric HD95/NSD, per structure), classification (AUROC + AUPRC + sensitivity/specificity with bootstrap CIs at the deployment prevalence), or detection (FROC/mAP with a stated IoU criterion) — plus calibration and subgroup slices. Emits a per-case table for analyze-stats and gates the metric choice against Metrics Reloaded / CLAIM 2024 (`check_metric_reporting`). Numbers come only from executed code. |
488
+ | **explainability** | Produce or audit the interpretability/explainability analysis of a medical-imaging model — Grad-CAM / Grad-CAM++ / attention-rollout / saliency / integrated-gradients — so it clears the rigor bar: mandatory Adebayo sanity checks (model- and data-randomisation), a quantitative localisation metric against ground truth (IoU / pointing game / Dice) instead of eyeballed examples, a cohort-level result, and attribution framing rather than "proof the model is correct". Emits an explainability-report manifest + a deterministic gate (`check_explainability_report`): `SALIENCY_AS_VALIDATION`, `NO_SANITY_CHECK`, `NO_LOCALIZATION_METRIC` (Major); `INSUFFICIENT_SANITY`, `CHERRY_PICKED_EXAMPLES`, `MISSING_METHOD` (Minor). Integrates captum / pytorch-grad-cam; never reimplements them or touches real patient data. |
470
489
  | **mllm-eval** | Model-agnostic evaluation harness (closed API or open weights) for an LLM/MLLM on a clinical task — radiology report generation, VQA, clinical text extraction — covering the adjudicated reference standard, clinical-efficacy metrics (RadGraph-F1 / CheXbert-F1 beyond BLEU/ROUGE), faithfulness/hallucination, pretraining-contamination, prompt sensitivity, and a reader study; gates the plan with `check_mllm_eval_completeness` and routes the reviewer audit to the MLLM probe. |
471
490
  | **intake-project** | Classifies new research projects, summarizes current state, identifies missing inputs, and recommends next steps. |
472
491
  | **grant-builder** | Structures grant proposals: significance, innovation, approach, milestones, and consortium roles. |
@@ -787,15 +806,44 @@ It helps other researchers find the toolkit — and we list it (with your permis
787
806
 
788
807
  ## Citation
789
808
 
790
- If you use MedSci Skills in your research, please cite the software via
791
- [`CITATION.cff`](CITATION.cff) (Zenodo concept DOI
792
- [10.5281/zenodo.20155321](https://doi.org/10.5281/zenodo.20155321)).
809
+ If MedSci Skills helped produce your manuscript, protocol, or analysis, please cite it
810
+ software citation is how a tool like this earns academic recognition, and it takes one line.
793
811
 
794
- The design and evaluation of the toolkit are described in a preprint:
812
+ **In your manuscript** (Methods or Acknowledgements cite the version you actually used):
795
813
 
796
- > Nam Y, Kim N. *Agentic Skills for Auditable and Reproducible Medical Research
797
- > Writing: An Integrity-gated Architecture for LLM-Assisted Clinical Manuscripts.*
798
- > arXiv:2606.09500 (2026). https://arxiv.org/abs/2606.09500
814
+ > Reporting-guideline compliance, reference verification, and pre-submission integrity checks
815
+ > were assisted by MedSci Skills (version X.Y.Z; https://github.com/Aperivue/medsci-skills;
816
+ > archived at Zenodo, https://doi.org/10.5281/zenodo.20155321).
817
+
818
+ **BibTeX** (the software, and the preprint describing its design):
819
+
820
+ ```bibtex
821
+ @software{nam_medsci_skills,
822
+ author = {Nam, Yoojin},
823
+ title = {{MedSci Skills: Claude Code Skills for the Medical Research Lifecycle}},
824
+ year = {2026},
825
+ publisher = {Zenodo},
826
+ doi = {10.5281/zenodo.20155321},
827
+ url = {https://github.com/Aperivue/medsci-skills}
828
+ }
829
+
830
+ @article{nam2026agentic,
831
+ author = {Nam, Yoojin and Kim, Namkug},
832
+ title = {{Agentic Skills for Auditable and Reproducible Medical Research Writing:
833
+ An Integrity-gated Architecture for LLM-Assisted Clinical Manuscripts}},
834
+ year = {2026},
835
+ journal = {arXiv preprint arXiv:2606.09500},
836
+ url = {https://arxiv.org/abs/2606.09500}
837
+ }
838
+ ```
839
+
840
+ The Zenodo **concept DOI** [10.5281/zenodo.20155321](https://doi.org/10.5281/zenodo.20155321)
841
+ always resolves to the latest release; [`CITATION.cff`](CITATION.cff) carries the machine-readable
842
+ metadata (GitHub's "Cite this repository" button reads it).
843
+
844
+ **Used it in published or in-review work?** Tell us via the
845
+ ["Used in research" issue template](https://github.com/Aperivue/medsci-skills/issues/new?template=used-in-research.yml)
846
+ — with your permission it is added to [`docs/citations.md`](docs/citations.md).
799
847
 
800
848
  ## Disclaimer
801
849
 
@@ -815,8 +863,16 @@ Bundled reporting guideline checklists retain their original Creative Commons li
815
863
 
816
864
  Optional dependency: `pdf_to_md.py` uses [pymupdf4llm](https://pymupdf.readthedocs.io) (AGPL-3.0). Not bundled -- installed separately by the user via `pip install pymupdf4llm`.
817
865
 
866
+ ## Star History
867
+
868
+ <a href="https://star-history.com/#Aperivue/medsci-skills&Date">
869
+ <img src="https://api.star-history.com/svg?repos=Aperivue/medsci-skills&type=Date" alt="MedSci Skills star history" width="640">
870
+ </a>
871
+
818
872
  ## About
819
873
 
820
874
  Built by [Aperivue](https://aperivue.com) -- tools for medical AI research and education.
821
875
 
876
+ **Runs anywhere the [Agent Skills standard](https://agentskills.io) is supported** -- not Claude Code alone. Claude Code, OpenAI Codex, Cursor, and GitHub Copilot are all verified against each host's own docs: one install, four hosts, no per-host fork ([host compatibility](docs/host_compatibility.md)).
877
+
822
878
  If you find this useful, consider giving it a star. It helps other researchers discover these tools.
@@ -153,14 +153,19 @@
153
153
  },
154
154
  {
155
155
  "path": "skills/analyze-stats/SKILL.md",
156
- "size": 56422,
157
- "sha256": "ddb73598fe60601942e8b44a87771e3ba583a585304effac4ae206d53ab4f154"
156
+ "size": 56948,
157
+ "sha256": "e7f01164e2fc9db924e49ee226b13bcf78d4d7c0463099c0f666985152a91d2e"
158
158
  },
159
159
  {
160
160
  "path": "skills/analyze-stats/references/analysis_guides/agreement_reliability.md",
161
161
  "size": 6674,
162
162
  "sha256": "599ad2551f547043b2bec79e3139d9c2c3ae33c5025784359b22022f882504c2"
163
163
  },
164
+ {
165
+ "path": "skills/analyze-stats/references/analysis_guides/calibration.md",
166
+ "size": 6470,
167
+ "sha256": "ac33862c6c707997be5a2511ed6a6d546c1e829fc9fc033d1c85eca9afa3ca9a"
168
+ },
164
169
  {
165
170
  "path": "skills/analyze-stats/references/analysis_guides/diagnostic_accuracy.md",
166
171
  "size": 9303,
@@ -1076,6 +1081,56 @@
1076
1081
  "size": 1411,
1077
1082
  "sha256": "3981d5da7734b90e6905ac329e996b145af82bd6a28ec2a8d42918e9ce077ee5"
1078
1083
  },
1084
+ {
1085
+ "path": "skills/explainability/SKILL.md",
1086
+ "size": 6474,
1087
+ "sha256": "4d1c082ad48393adb65203ffbedf63f772fdc521d873f657cbfc81150c7b36de"
1088
+ },
1089
+ {
1090
+ "path": "skills/explainability/references/explainability_guide.md",
1091
+ "size": 4203,
1092
+ "sha256": "24bc06181e54801b148f142f9312fe0eede9f540a4e57810701506681e254b4b"
1093
+ },
1094
+ {
1095
+ "path": "skills/explainability/scripts/check_explainability_report.py",
1096
+ "size": 10783,
1097
+ "sha256": "4071a93aacf509f73a44b2c7f6423b5722aab3d44c79e9a8680845454261d47d"
1098
+ },
1099
+ {
1100
+ "path": "skills/explainability/scripts/check_explainability_report_challenge/expected/strong.txt",
1101
+ "size": 391,
1102
+ "sha256": "317018eb7546f77b2de39ff1b73c9e82584a9d65c25eb91a940de76a4c7d2ec5"
1103
+ },
1104
+ {
1105
+ "path": "skills/explainability/scripts/check_explainability_report_challenge/expected/weak.txt",
1106
+ "size": 876,
1107
+ "sha256": "de5c090c1ee4c632d7d59bc0d5f20fac8d28342b74b68eb51066677658245451"
1108
+ },
1109
+ {
1110
+ "path": "skills/explainability/scripts/check_explainability_report_challenge/fixture/report_strong.json",
1111
+ "size": 238,
1112
+ "sha256": "b835871c1d98313f736575faf7f6adbb5cfabe4e3dfd1abe1279976c8c5f1867"
1113
+ },
1114
+ {
1115
+ "path": "skills/explainability/scripts/check_explainability_report_challenge/fixture/report_weak.json",
1116
+ "size": 163,
1117
+ "sha256": "dfde5db357a83660f941fdde957bb3a9af25f60d26300322f04b3981b13c429a"
1118
+ },
1119
+ {
1120
+ "path": "skills/explainability/scripts/check_explainability_report_challenge/problem.md",
1121
+ "size": 805,
1122
+ "sha256": "1b667c138ac54e38614e438efdb995adba208588007e95eed6f374233ff6dcdc"
1123
+ },
1124
+ {
1125
+ "path": "skills/explainability/scripts/check_explainability_report_challenge/verify.sh",
1126
+ "size": 2005,
1127
+ "sha256": "5246897dc616e04fa1260e9b20d9970e1499f95ebb52034bba59482d401c1156"
1128
+ },
1129
+ {
1130
+ "path": "skills/explainability/skill.yml",
1131
+ "size": 3569,
1132
+ "sha256": "5b3e135825470392867dc851627d9899bc512d9a5ee52556c205eea8fae4edb1"
1133
+ },
1079
1134
  {
1080
1135
  "path": "skills/fill-icmje-coi/SKILL.md",
1081
1136
  "size": 9997,
@@ -3053,8 +3108,8 @@
3053
3108
  },
3054
3109
  {
3055
3110
  "path": "skills/peer-review/references/domain-probes/survival_prognostic.md",
3056
- "size": 14022,
3057
- "sha256": "96195cd1b575535bc12a133125b9d85e2ca7e756b96a0649e03d4c3696e5312b"
3111
+ "size": 14297,
3112
+ "sha256": "32cd929ff2e151f33bc5b106eddef0d38d5bd15672054e690c603ee82a22a817"
3058
3113
  },
3059
3114
  {
3060
3115
  "path": "skills/peer-review/references/exemplar_reviews/README.md",
@@ -3176,6 +3231,56 @@
3176
3231
  "size": 1753,
3177
3232
  "sha256": "ce4996820b24c230584890c501860c8d37dfd07521195954077d2fdd1a26f419"
3178
3233
  },
3234
+ {
3235
+ "path": "skills/preprocess-imaging/SKILL.md",
3236
+ "size": 7068,
3237
+ "sha256": "e17b73b0760194d4e6e3924ec2a0452601adc27122e7455cc5f2993d5af1d0d0"
3238
+ },
3239
+ {
3240
+ "path": "skills/preprocess-imaging/references/preprocessing_guide.md",
3241
+ "size": 5023,
3242
+ "sha256": "fdab6d435ff6bce7b6787319acda9b0b160411bc2e1109e15154bbb8a68c8282"
3243
+ },
3244
+ {
3245
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage.py",
3246
+ "size": 12992,
3247
+ "sha256": "dcce1493a29122ed4259adc116ed7ad239b11ee1f45a10f6f7eb94698b3efa67"
3248
+ },
3249
+ {
3250
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/expected/clean.txt",
3251
+ "size": 370,
3252
+ "sha256": "bc1efcfc1d8575d78a0448752e60a3b58d654a5bc1a7b11360e4d9ba690665ac"
3253
+ },
3254
+ {
3255
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/expected/leak.txt",
3256
+ "size": 1030,
3257
+ "sha256": "fe046c81f20b34a6ff3fd6858f7832e786106ed56635b39f7e413b4853d4b7e8"
3258
+ },
3259
+ {
3260
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/fixture/manifest_clean.json",
3261
+ "size": 800,
3262
+ "sha256": "e01ff6d09aae6f76d3b2b1cd05c333d66fd53499a2a2d1296380eefde720c515"
3263
+ },
3264
+ {
3265
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/fixture/manifest_leak.json",
3266
+ "size": 881,
3267
+ "sha256": "a55389654128c577e16eefb3c6b8f85d8a47bdc06a817619f13036a1e1ebe4b4"
3268
+ },
3269
+ {
3270
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/problem.md",
3271
+ "size": 903,
3272
+ "sha256": "042ddd4736133ccf63192ea65c4faa714b2854ec9bb704f29ca2f401cd4658ee"
3273
+ },
3274
+ {
3275
+ "path": "skills/preprocess-imaging/scripts/check_preprocessing_leakage_challenge/verify.sh",
3276
+ "size": 2188,
3277
+ "sha256": "9201d264720627f7281f43bcf3b1093bf6940f67acd7c299c8b3ac64fb58b564"
3278
+ },
3279
+ {
3280
+ "path": "skills/preprocess-imaging/skill.yml",
3281
+ "size": 3518,
3282
+ "sha256": "c6edc7ac6421438d4e0b64cd416202ac9f91092870ea1cb8531ba15fda7d5c72"
3283
+ },
3179
3284
  {
3180
3285
  "path": "skills/present-paper/SKILL.md",
3181
3286
  "size": 33518,
@@ -3613,8 +3718,8 @@
3613
3718
  },
3614
3719
  {
3615
3720
  "path": "skills/self-review/references/domain-probes/survival_prognostic.md",
3616
- "size": 14022,
3617
- "sha256": "96195cd1b575535bc12a133125b9d85e2ca7e756b96a0649e03d4c3696e5312b"
3721
+ "size": 14297,
3722
+ "sha256": "32cd929ff2e151f33bc5b106eddef0d38d5bd15672054e690c603ee82a22a817"
3618
3723
  },
3619
3724
  {
3620
3725
  "path": "skills/self-review/references/exemplar_findings/README.md",
@@ -3753,8 +3858,8 @@
3753
3858
  },
3754
3859
  {
3755
3860
  "path": "skills/self-review/scripts/check_scope_coherence.py",
3756
- "size": 11920,
3757
- "sha256": "e600e54fcbe308060a8dadd871ec274b6ae19f89456ae0194490e152c0d09a91"
3861
+ "size": 12989,
3862
+ "sha256": "2444bce9c5bd2fc088c43eae97c1fc5791ae4da44f428a2caa0559b976dbe622"
3758
3863
  },
3759
3864
  {
3760
3865
  "path": "skills/self-review/scripts/check_supplement_hygiene.py",
@@ -3918,8 +4023,8 @@
3918
4023
  },
3919
4024
  {
3920
4025
  "path": "skills/write-paper/SKILL.md",
3921
- "size": 66771,
3922
- "sha256": "1a50c9ceb040a79feaa60e809c7196f9f04b85cab2f5f3402dcaed3f7aee552c"
4026
+ "size": 67054,
4027
+ "sha256": "62b3cbff56a139ed20a783c462fb6dde6b7a932bb057762a2d1c6382c8d044c1"
3923
4028
  },
3924
4029
  {
3925
4030
  "path": "skills/write-paper/references/exemplar_abstract.md",
@@ -3938,8 +4043,8 @@
3938
4043
  },
3939
4044
  {
3940
4045
  "path": "skills/write-paper/references/exemplar_discussion/README.md",
3941
- "size": 2727,
3942
- "sha256": "3bfcd4eb4df4ca0309446a606550cb11adc4d88daa676f2217249691d2e6b042"
4046
+ "size": 2902,
4047
+ "sha256": "1db58e8d3801a7fd2bd6a6bb9c271f22436a71e82ba034a8c888e9468945a026"
3943
4048
  },
3944
4049
  {
3945
4050
  "path": "skills/write-paper/references/exemplar_discussion/ai_validation_tripod_claim.md",
@@ -3961,6 +4066,11 @@
3961
4066
  "size": 3652,
3962
4067
  "sha256": "21ec3cbfcb626cc00f09e66aa27d8f2f835a202ed083bcebcba57b787ddff866"
3963
4068
  },
4069
+ {
4070
+ "path": "skills/write-paper/references/exemplar_discussion/rct_consort.md",
4071
+ "size": 2613,
4072
+ "sha256": "2fa6e9f621219974f07294e8637da83d923327207e38e1692b62bb45c7d20ab5"
4073
+ },
3964
4074
  {
3965
4075
  "path": "skills/write-paper/references/exemplar_introduction.md",
3966
4076
  "size": 2636,
@@ -3968,8 +4078,8 @@
3968
4078
  },
3969
4079
  {
3970
4080
  "path": "skills/write-paper/references/exemplar_methods/README.md",
3971
- "size": 2342,
3972
- "sha256": "6966e8b723d0c4ccc012d54e2b8a22ef59b39c22619e63a8597f9badb380b4e7"
4081
+ "size": 2426,
4082
+ "sha256": "b55addd809841fdb8ae8e834693c7a03602cb1d8aeb00131ed86ecb8fbc713f6"
3973
4083
  },
3974
4084
  {
3975
4085
  "path": "skills/write-paper/references/exemplar_methods/ai_validation_tripod_claim.md",
@@ -3991,10 +4101,15 @@
3991
4101
  "size": 2364,
3992
4102
  "sha256": "e2ea3f64be321d2fb8249d4d528cfd24231c0b69d2562e4290cf3dcddd29d419"
3993
4103
  },
4104
+ {
4105
+ "path": "skills/write-paper/references/exemplar_methods/rct_consort.md",
4106
+ "size": 3268,
4107
+ "sha256": "742e343b163336a6dda2fa2054e0f486df489e1d6cb2cf3eb782e05d25d9710d"
4108
+ },
3994
4109
  {
3995
4110
  "path": "skills/write-paper/references/exemplar_results/README.md",
3996
- "size": 2799,
3997
- "sha256": "14b588f1f4433be71c39f11627148fff797eb87b3b74be75e61514095d4c38ea"
4111
+ "size": 2989,
4112
+ "sha256": "b67ec682f899a1774af10913eaeb8f33956859da2ef787250c01ef3b437f1155"
3998
4113
  },
3999
4114
  {
4000
4115
  "path": "skills/write-paper/references/exemplar_results/ai_validation_tripod_claim.md",
@@ -4016,6 +4131,11 @@
4016
4131
  "size": 2452,
4017
4132
  "sha256": "4c8e1fc5c5d00a3c0dc26ea0d94dc80e3077a96503ada653ccdcee8eeb8b14da"
4018
4133
  },
4134
+ {
4135
+ "path": "skills/write-paper/references/exemplar_results/rct_consort.md",
4136
+ "size": 2356,
4137
+ "sha256": "6a0becfe8f24db7f686bd23f26c9caec749dd996914705679ea915398fc7c3dd"
4138
+ },
4019
4139
  {
4020
4140
  "path": "skills/write-paper/references/journal_profiles/AJNR.md",
4021
4141
  "size": 6381,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "version": "5.13.0",
3
+ "version": "5.15.0",
4
4
  "owned_skills": [
5
5
  "academic-aio",
6
6
  "add-journal",
@@ -16,6 +16,7 @@
16
16
  "deidentify",
17
17
  "design-ai-benchmarking",
18
18
  "design-study",
19
+ "explainability",
19
20
  "fill-icmje-coi",
20
21
  "fill-protocol",
21
22
  "find-cohort-gap",
@@ -39,6 +40,7 @@
39
40
  "orchestrate",
40
41
  "peer-review",
41
42
  "polish-language",
43
+ "preprocess-imaging",
42
44
  "present-paper",
43
45
  "publish-skill",
44
46
  "render-pdf-doc",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "_comment": "AUTO-GENERATED by scripts/gen_skills_catalog_json.py from each skills/<slug>/SKILL.md + skill.yml. Machine-readable skill catalog (single source of truth) consumed by external surfaces such as the aperivue.com storefront to gate skill-list completeness. Do not hand-edit; CI gate: python3 scripts/gen_skills_catalog_json.py --check.",
3
- "skill_count": 51,
3
+ "skill_count": 53,
4
4
  "categories": [
5
5
  {
6
6
  "key": "literature_references",
@@ -32,11 +32,13 @@
32
32
  "label": "Model Engineering & Validation",
33
33
  "slugs": [
34
34
  "architecture-zoo",
35
+ "explainability",
35
36
  "mllm-eval",
36
37
  "model-card",
37
38
  "model-evaluation",
38
39
  "model-scaffold",
39
- "model-validation"
40
+ "model-validation",
41
+ "preprocess-imaging"
40
42
  ]
41
43
  },
42
44
  {
@@ -235,6 +237,15 @@
235
237
  "maturity": "official",
236
238
  "description": "Study design and validity review for radiology and medical AI research."
237
239
  },
240
+ {
241
+ "slug": "explainability",
242
+ "category": "model_engineering",
243
+ "category_label": "Model Engineering & Validation",
244
+ "layer": "D",
245
+ "owner_domain": "model_validation",
246
+ "maturity": "official",
247
+ "description": "Produce or audit the interpretability/explainability analysis of a medical-imaging model — Grad-CAM / Grad-CAM++ / attention-rollout / saliency / integrated-gradients — so it clears the rigor bar a re…"
248
+ },
238
249
  {
239
250
  "slug": "fill-icmje-coi",
240
251
  "category": "submission_journals",
@@ -442,6 +453,15 @@
442
453
  "maturity": "official",
443
454
  "description": "Academic English consistency linting and non-native (ESL) language polish for medical manuscripts."
444
455
  },
456
+ {
457
+ "slug": "preprocess-imaging",
458
+ "category": "model_engineering",
459
+ "category_label": "Model Engineering & Validation",
460
+ "layer": "D",
461
+ "owner_domain": "model_validation",
462
+ "maturity": "official",
463
+ "description": "Design or audit the data-preparation stage of a medical-imaging model — DICOM/NIfTI intake, resampling and intensity normalisation, and the augmentation plan — so the pipeline is leakage-safe before m…"
464
+ },
445
465
  {
446
466
  "slug": "present-paper",
447
467
  "category": "presentation_tooling",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medsci-skills",
3
- "version": "5.13.0",
3
+ "version": "5.15.0",
4
4
  "description": "MedSci Skills — a medical/scientific research skill suite for AI coding agents (Claude Code, Codex, Cursor, Copilot). The npm package is a terminal-friendly installer shortcut; the canonical distribution remains the GitHub repository and the Claude Code plugin marketplace.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://github.com/Aperivue/medsci-skills#readme",
@@ -545,7 +545,8 @@ When death or other events preclude the outcome of interest, standard KM overest
545
545
  - **Guide**: Load `analysis_guides/regression.md` before generating code
546
546
  - **Template**: `references/templates/regression.py` (set `regression_type = "logistic"`)
547
547
  - Run univariable analysis first, then multivariable with clinically selected variables
548
- - Required outputs: OR table (univariable + multivariable), C-statistic (95% CI), Hosmer-Lemeshow
548
+ - Required outputs: OR table (univariable + multivariable), C-statistic (95% CI), and **calibration** (intercept + slope + flexible plot — **not** HosmerLemeshow, which is deprecated; see the calibration guide)
549
+ - **Prediction-model calibration guide**: `references/analysis_guides/calibration.md` (**load before generating code** for any model that outputs a risk used for a decision — the apparent slope of exactly 1.00 is the in-sample tell, so produce the **bootstrap optimism-corrected** slope/intercept; Van Calster's calibration levels; scaled Brier; why Hosmer–Lemeshow is dropped; produce-side of probe S7)
549
550
  - Check VIF < 5, EPV >= 10 (warn if violated)
550
551
  - **Nested observation units**: when rows are clustered within subjects (multiple lesions/visits per patient), use cluster-robust standard errors (`cov_type="cluster"`, `cov_kwds={"groups": id}` in statsmodels) or a mixed-effects logistic model — a naive logit CI assumes independent rows and is too narrow
551
552
  - Box-Tidwell test for continuous predictor linearity
@@ -0,0 +1,132 @@
1
+ # Prediction-Model Calibration Guide
2
+
3
+ For a clinical prediction model (a logistic risk score or a Cox/survival model at a fixed
4
+ horizon), **discrimination (AUC / C-index) is not enough** — a model that ranks well can still
5
+ output probabilities that are systematically too high or too low. The ways calibration fails
6
+ review are (1) reporting **apparent (in-sample)** calibration — a slope of exactly 1.00 is the
7
+ fingerprint — with no internal-validation correction, (2) leaning on the **Hosmer–Lemeshow**
8
+ test (deprecated), and (3) omitting calibration entirely for a model meant to guide care. This
9
+ guide produces the corrected estimand; it is the produce-side of probe **S7**.
10
+
11
+ ---
12
+
13
+ ## When to Use
14
+
15
+ - Any model that outputs a **risk / probability** used for a decision (surveillance intensity,
16
+ treatment eligibility, triage) — logistic or survival-at-a-horizon.
17
+ - Reported **alongside** discrimination and, for a utility claim, decision-curve net benefit —
18
+ never discrimination alone.
19
+ - NOT a substitute for external validation: internal (bootstrap/CV) calibration corrects
20
+ optimism but does not establish transportability.
21
+
22
+ ---
23
+
24
+ ## Apparent calibration is optimistic — correct it (this is the S7 issue)
25
+
26
+ Fit a logistic model by maximum likelihood and its **apparent** calibration slope on the same
27
+ data is **exactly 1.00** and its calibration-in-the-large intercept **exactly 0** — by
28
+ construction, not because the model is well-calibrated. A slope printed as `1.00` (or metrics
29
+ with no `bootstrap` / `cross-valid` / `optimism` / `held-out` token nearby) is presumptively
30
+ in-sample. Produce the **bootstrap optimism-corrected** slope instead (Harrell/Steyerberg).
31
+
32
+ ```python
33
+ import numpy as np, statsmodels.api as sm
34
+ X = ... # design matrix (add_constant), y = 0/1 outcome
35
+ def cal_slope(y, lp):
36
+ m = sm.GLM(y, sm.add_constant(lp), family=sm.families.Binomial()).fit()
37
+ return m.params[1], m.params[0] # slope, calibration-in-the-large intercept
38
+
39
+ full = sm.GLM(y, X, family=sm.families.Binomial()).fit()
40
+ app_slope, app_int = cal_slope(y, X @ full.params) # apparent: slope ~1.00, intercept ~0
41
+
42
+ rng = np.random.default_rng(42); n = len(y); opt = []
43
+ for _ in range(500): # bootstrap optimism (Harrell)
44
+ idx = rng.integers(0, n, n)
45
+ bm = sm.GLM(y[idx], X[idx], family=sm.families.Binomial()).fit()
46
+ s_boot, _ = cal_slope(y[idx], X[idx] @ bm.params) # boot model on boot data (apparent)
47
+ s_orig, _ = cal_slope(y, X @ bm.params) # boot model on original data (test)
48
+ opt.append(s_boot - s_orig)
49
+ corrected_slope = app_slope - float(np.mean(opt)) # < 1.00 when the model overfits
50
+ print(f"apparent slope {app_slope:.3f} -> optimism-corrected {corrected_slope:.3f}")
51
+ ```
52
+
53
+ A corrected slope **< 1** means predictions are too extreme (overfit) and should be shrunk
54
+ (a penalized/uniform-shrinkage refit); a slope **> 1** means they are too moderate.
55
+
56
+ ---
57
+
58
+ ## The four levels of calibration (report weak calibration at least)
59
+
60
+ Van Calster's hierarchy — report at minimum **weak calibration** (intercept + slope):
61
+
62
+ - **Mean** (calibration-in-the-large): mean predicted = observed event rate (the intercept).
63
+ - **Weak**: intercept ≈ 0 **and** slope ≈ 1.
64
+ - **Moderate**: a **flexible calibration curve** (loess / spline of observed on predicted),
65
+ not decile bins — the plot most reviewers now expect.
66
+ - **Strong**: correct per-covariate (rarely achievable; not required).
67
+
68
+ ```python
69
+ import matplotlib.pyplot as plt
70
+ from sklearn.calibration import calibration_curve
71
+ phat = full.predict(X)
72
+ frac_pos, mean_pred = calibration_curve(y, phat, n_bins=10, strategy="quantile")
73
+ plt.plot([0, 1], [0, 1], "--"); plt.plot(mean_pred, frac_pos, "o-") # add a loess curve for moderate
74
+ plt.xlabel("Predicted probability"); plt.ylabel("Observed frequency")
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Brier score; do NOT rely on Hosmer–Lemeshow
80
+
81
+ - **Brier score** = mean squared error of the probabilities; report the **scaled Brier**
82
+ (1 − Brier / Brier_null) so it is interpretable against the event rate.
83
+ - **Hosmer–Lemeshow is deprecated** (Van Calster 2016; Austin & Steyerberg): its p-value depends
84
+ on an arbitrary number of bins, it is underpowered in small samples and rejects trivially in
85
+ large ones, and it gives no direction or magnitude. Report the **calibration slope + intercept
86
+ + a flexible calibration plot** instead of an H–L p-value.
87
+
88
+ ```python
89
+ from sklearn.metrics import brier_score_loss
90
+ brier = brier_score_loss(y, phat); scaled = 1 - brier / (y.mean() * (1 - y.mean()))
91
+ ```
92
+
93
+ ## Survival models
94
+
95
+ For a Cox/survival model, calibrate the **predicted vs observed risk at a fixed horizon**
96
+ (e.g. 3-year): group by predicted-risk decile and compare to a Kaplan–Meier / pseudo-value
97
+ estimate at that time, or use `rms::calibrate` / `pec` in R with bootstrap optimism correction.
98
+ State the horizon; a model can be well-calibrated at 1 year and not at 5.
99
+
100
+ ---
101
+
102
+ ## Reporting
103
+
104
+ - Calibration **intercept and slope** with the **internal-validation method named**
105
+ (bootstrap/CV), not the apparent slope of 1.00; the flexible calibration plot.
106
+ - Scaled Brier; the horizon (survival); the cohort each metric was computed on (development vs
107
+ held-out vs external) stated explicitly.
108
+ - Discrimination **and** calibration together; add decision-curve net benefit for a utility claim
109
+ (see `table-standards/table-types/incremental_value.md` and the `make-figures` decision-curve
110
+ exemplar).
111
+
112
+ ---
113
+
114
+ ## Common failures (flag at review)
115
+
116
+ - **Apparent calibration slope of exactly 1.00** (and intercept 0) with no bootstrap/CV/external
117
+ token — in-sample fit presented as calibration (S7).
118
+ - **Hosmer–Lemeshow p-value** offered as the calibration evidence (deprecated).
119
+ - **Discrimination reported without calibration** for a model meant to guide care (S7 → MAJOR).
120
+ - **Decile-bin calibration only**, no flexible curve; or a survival calibration with no stated
121
+ horizon.
122
+
123
+ ---
124
+
125
+ ## Anti-Hallucination
126
+
127
+ - Never hand-type a calibration slope/intercept, Brier, or CI — compute it from predictions with
128
+ a seeded script.
129
+ - Do not report a calibration slope of 1.00 as evidence of good calibration — it is the
130
+ apparent-fit artifact; report the optimism-corrected value the bootstrap produced.
131
+ - Name the validation source of every calibration number (development / bootstrap-corrected /
132
+ external); do not present development-sample calibration as validated performance.