medsci-skills 5.8.0 → 5.9.1
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.
- package/README.md +7 -3
- package/installers/install.py +14 -1
- package/metadata/distribution_files.json +105 -30
- package/metadata/distribution_manifest.json +1 -1
- package/package.json +1 -1
- package/skills/analyze-stats/SKILL.md +14 -3
- package/skills/calc-sample-size/SKILL.md +47 -2
- package/skills/calc-sample-size/references/prediction_model_sample_size.md +97 -0
- package/skills/check-reporting/scripts/check_framework_naming.py +19 -9
- package/skills/check-reporting/tests/test_framework_naming.sh +16 -0
- package/skills/design-study/SKILL.md +2 -1
- package/skills/design-study/references/dag_adjustment.md +93 -0
- package/skills/design-study/references/target_trial_emulation.md +94 -0
- package/skills/design-study/scripts/adjustment_set_challenge/fixture/confounder.json +1 -0
- package/skills/design-study/scripts/adjustment_set_challenge/fixture/instrument.json +1 -0
- package/skills/design-study/scripts/adjustment_set_challenge/fixture/mbias.json +1 -0
- package/skills/design-study/scripts/adjustment_set_challenge/fixture/mediator.json +1 -0
- package/skills/design-study/scripts/adjustment_set_challenge/problem.md +35 -0
- package/skills/design-study/scripts/adjustment_set_challenge/verify.sh +45 -0
- package/skills/design-study/scripts/adjustment_set_helper.py +163 -0
- package/skills/design-study/skill.yml +1 -0
- package/skills/fulltext-retrieval/fetch_oa.py +8 -2
- package/skills/make-figures/references/exemplar_plots/README.md +14 -0
- package/skills/make-figures/scripts/render_core_figures.py +295 -0
- package/skills/make-figures/scripts/render_core_figures_challenge/fixture/synthetic_inputs.json +42 -0
- package/skills/make-figures/scripts/render_core_figures_challenge/problem.md +42 -0
- package/skills/make-figures/scripts/render_core_figures_challenge/verify.sh +37 -0
- package/skills/make-figures/skill.yml +1 -0
- package/skills/model-validation/SKILL.md +14 -1
- package/skills/model-validation/references/validation_design.md +32 -1
- package/skills/self-review/SKILL.md +37 -87
- package/skills/self-review/references/panel_review_template.md +5 -2
- package/skills/self-review/references/phases/confounding_completeness.md +90 -0
- package/skills/self-review/scripts/check_claim_artifact.py +42 -6
- package/skills/self-review/tests/test_claim_artifact.sh +24 -0
- package/skills/verify-refs/scripts/verify_refs.py +28 -5
package/README.md
CHANGED
|
@@ -51,11 +51,15 @@ integrity gates** for submission-grade biomedical research. As of **v5.0** it ad
|
|
|
51
51
|
**model-engineering lane**: choose a paper-grounded architecture, scaffold a
|
|
52
52
|
reproducible, leakage-safe PyTorch training repo, and validate, document, and
|
|
53
53
|
evaluate a medical-imaging or LLM/MLLM model so the work reaches a paper — it
|
|
54
|
-
|
|
54
|
+
ships a minimal runnable default model for a forward-pass smoke test and
|
|
55
|
+
**integrates** MONAI / nnU-Net / timm / torchvision for production-grade models,
|
|
56
|
+
rather than reimplementing the ecosystem. Clinical AI model research
|
|
55
57
|
engineering is in scope; it is **not** a diagnostic tool, an autonomous author, or a
|
|
56
58
|
general AI-scientist platform, and every output requires human-expert verification.
|
|
57
59
|
New here? See the [3 workflows below](#start-here-3-workflows), the
|
|
58
|
-
[FAQ](docs/faq.md),
|
|
60
|
+
[FAQ](docs/faq.md), the
|
|
61
|
+
[research connectors it calls](docs/connectors.md) (keyless public APIs — nothing to set
|
|
62
|
+
up in the common case), and the
|
|
59
63
|
[scope boundary](ROADMAP.md#not-planned--explicitly-out-of-scope).
|
|
60
64
|
|
|
61
65
|
---
|
|
@@ -459,7 +463,7 @@ ma-scout -> search-lit -> fulltext-retrieval -> design-study ──> write-proto
|
|
|
459
463
|
| **design-study** | Study design review: identifies analysis unit, cohort logic, data leakage risks, comparator design, validation strategy, and reporting guideline fit. |
|
|
460
464
|
| **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. |
|
|
461
465
|
| **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. |
|
|
462
|
-
| **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.
|
|
466
|
+
| **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. |
|
|
463
467
|
| **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. |
|
|
464
468
|
| **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. |
|
|
465
469
|
| **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. |
|
package/installers/install.py
CHANGED
|
@@ -167,10 +167,23 @@ def run_self_test() -> int:
|
|
|
167
167
|
return 0
|
|
168
168
|
|
|
169
169
|
|
|
170
|
+
LOG_DIR = REPO_ROOT / "installers" / ".logs"
|
|
171
|
+
LOG_KEEP = 10 # retain the most recent N install logs; prune older
|
|
172
|
+
|
|
173
|
+
|
|
170
174
|
def write_log(log_lines: list[str]) -> Path:
|
|
175
|
+
"""Write the timestamped install log to installers/.logs/ (gitignored) and keep only
|
|
176
|
+
the most recent LOG_KEEP — logs used to accumulate in the repo root."""
|
|
177
|
+
LOG_DIR.mkdir(parents=True, exist_ok=True)
|
|
171
178
|
stamp = dt.datetime.now().strftime("%Y%m%d-%H%M%S")
|
|
172
|
-
log_path =
|
|
179
|
+
log_path = LOG_DIR / f"{stamp}-{LOG_NAME}"
|
|
173
180
|
log_path.write_text("\n".join(log_lines) + "\n", encoding="utf-8")
|
|
181
|
+
old = sorted(LOG_DIR.glob(f"*-{LOG_NAME}"))
|
|
182
|
+
for stale in old[:-LOG_KEEP]:
|
|
183
|
+
try:
|
|
184
|
+
stale.unlink()
|
|
185
|
+
except OSError:
|
|
186
|
+
pass
|
|
174
187
|
return log_path
|
|
175
188
|
|
|
176
189
|
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"path": "installers/install.py",
|
|
26
|
-
"size":
|
|
27
|
-
"sha256": "
|
|
26
|
+
"size": 14720,
|
|
27
|
+
"sha256": "b22e5d5be62ba1f71a81ad3214aed2cbfefbf97fd52179b21a8452a11ae95fcf"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"path": "installers/medsci_txn.py",
|
|
@@ -153,8 +153,8 @@
|
|
|
153
153
|
},
|
|
154
154
|
{
|
|
155
155
|
"path": "skills/analyze-stats/SKILL.md",
|
|
156
|
-
"size":
|
|
157
|
-
"sha256": "
|
|
156
|
+
"size": 55302,
|
|
157
|
+
"sha256": "3809b6a55e8a79b7dc48f617e3be0a7faf2a96a6f0ba03d58977a39f267cce81"
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
"path": "skills/analyze-stats/references/analysis_guides/health_economic_evaluation.md",
|
|
@@ -513,8 +513,8 @@
|
|
|
513
513
|
},
|
|
514
514
|
{
|
|
515
515
|
"path": "skills/calc-sample-size/SKILL.md",
|
|
516
|
-
"size":
|
|
517
|
-
"sha256": "
|
|
516
|
+
"size": 23904,
|
|
517
|
+
"sha256": "0bed1ee5d43f044a490d77fac181900f9e513dfd379831d0446b118b4768b798"
|
|
518
518
|
},
|
|
519
519
|
{
|
|
520
520
|
"path": "skills/calc-sample-size/references/formulas.md",
|
|
@@ -531,6 +531,11 @@
|
|
|
531
531
|
"size": 2142,
|
|
532
532
|
"sha256": "97062f5aa63ce8f5b5e340e6b65683720b3ce1d94e34d201977d9a2601293038"
|
|
533
533
|
},
|
|
534
|
+
{
|
|
535
|
+
"path": "skills/calc-sample-size/references/prediction_model_sample_size.md",
|
|
536
|
+
"size": 5074,
|
|
537
|
+
"sha256": "bf3d42ad59d2a3b3abc2f00db9559de671514b7b64bd4cf44ec53717966dc635"
|
|
538
|
+
},
|
|
534
539
|
{
|
|
535
540
|
"path": "skills/calc-sample-size/skill.yml",
|
|
536
541
|
"size": 2958,
|
|
@@ -808,8 +813,8 @@
|
|
|
808
813
|
},
|
|
809
814
|
{
|
|
810
815
|
"path": "skills/check-reporting/scripts/check_framework_naming.py",
|
|
811
|
-
"size":
|
|
812
|
-
"sha256": "
|
|
816
|
+
"size": 8455,
|
|
817
|
+
"sha256": "bd44ffb3f55d6539f972cd4bf50f1d9301e865da41e05c8d279776e94fb6d3d7"
|
|
813
818
|
},
|
|
814
819
|
{
|
|
815
820
|
"path": "skills/check-reporting/scripts/check_prisma_figure.py",
|
|
@@ -1003,13 +1008,58 @@
|
|
|
1003
1008
|
},
|
|
1004
1009
|
{
|
|
1005
1010
|
"path": "skills/design-study/SKILL.md",
|
|
1006
|
-
"size":
|
|
1007
|
-
"sha256": "
|
|
1011
|
+
"size": 19220,
|
|
1012
|
+
"sha256": "d4a05f6dd2530620bd1ec3e1c64ba0625aae25def12892247e61a77724132cd6"
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
"path": "skills/design-study/references/dag_adjustment.md",
|
|
1016
|
+
"size": 4390,
|
|
1017
|
+
"sha256": "8b6c9d2b2d4e79652b355cf30f0d56f4232619cad8589489707107f85bef9de3"
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
"path": "skills/design-study/references/target_trial_emulation.md",
|
|
1021
|
+
"size": 6025,
|
|
1022
|
+
"sha256": "3f3b8aa8256689a2109e06b0eaa92f0e793869838711c19f0b2d9e9e01dcb0ff"
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
"path": "skills/design-study/scripts/adjustment_set_challenge/fixture/confounder.json",
|
|
1026
|
+
"size": 111,
|
|
1027
|
+
"sha256": "3d1c43f40a41e91f674cca1d47fd9bb8566e9d74f9ebb18aa097a41fbf0b11ff"
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
"path": "skills/design-study/scripts/adjustment_set_challenge/fixture/instrument.json",
|
|
1031
|
+
"size": 199,
|
|
1032
|
+
"sha256": "5a99731963404b122cb3e233cc5c850885fe42cc49c9b1cfbac0206ea936703b"
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
"path": "skills/design-study/scripts/adjustment_set_challenge/fixture/mbias.json",
|
|
1036
|
+
"size": 182,
|
|
1037
|
+
"sha256": "b05f7d537b9a25841172d4325fba858933aedab20718ac78e58547d11f8b6561"
|
|
1038
|
+
},
|
|
1039
|
+
{
|
|
1040
|
+
"path": "skills/design-study/scripts/adjustment_set_challenge/fixture/mediator.json",
|
|
1041
|
+
"size": 106,
|
|
1042
|
+
"sha256": "9e3fe1ed554a115058e9d7916856eaeca4d666c00741282960320cb87e1cfe91"
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
"path": "skills/design-study/scripts/adjustment_set_challenge/problem.md",
|
|
1046
|
+
"size": 2264,
|
|
1047
|
+
"sha256": "79cba6ed5f3259a9e633c88d7a4d6d08994fff5f4f8461482dd86bcd2c7239ab"
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
"path": "skills/design-study/scripts/adjustment_set_challenge/verify.sh",
|
|
1051
|
+
"size": 2672,
|
|
1052
|
+
"sha256": "87349a1eb69b1c5e1b6120c6e5b1269bc830ef91803e7f09219da2285451bb76"
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
"path": "skills/design-study/scripts/adjustment_set_helper.py",
|
|
1056
|
+
"size": 8231,
|
|
1057
|
+
"sha256": "239948c31d513f95f834fdf2d48e9938f7e585a2ebb12387a5abf3b06305dca0"
|
|
1008
1058
|
},
|
|
1009
1059
|
{
|
|
1010
1060
|
"path": "skills/design-study/skill.yml",
|
|
1011
|
-
"size":
|
|
1012
|
-
"sha256": "
|
|
1061
|
+
"size": 1411,
|
|
1062
|
+
"sha256": "3981d5da7734b90e6905ac329e996b145af82bd6a28ec2a8d42918e9ce077ee5"
|
|
1013
1063
|
},
|
|
1014
1064
|
{
|
|
1015
1065
|
"path": "skills/fill-icmje-coi/SKILL.md",
|
|
@@ -1528,8 +1578,8 @@
|
|
|
1528
1578
|
},
|
|
1529
1579
|
{
|
|
1530
1580
|
"path": "skills/fulltext-retrieval/fetch_oa.py",
|
|
1531
|
-
"size":
|
|
1532
|
-
"sha256": "
|
|
1581
|
+
"size": 24810,
|
|
1582
|
+
"sha256": "12bfbf094d338ac461267cea133c0a63a66bc0d2dadd28727921149bc5b72855"
|
|
1533
1583
|
},
|
|
1534
1584
|
{
|
|
1535
1585
|
"path": "skills/fulltext-retrieval/fetch_oa_report_challenge/expected/projection.json",
|
|
@@ -1953,8 +2003,8 @@
|
|
|
1953
2003
|
},
|
|
1954
2004
|
{
|
|
1955
2005
|
"path": "skills/make-figures/references/exemplar_plots/README.md",
|
|
1956
|
-
"size":
|
|
1957
|
-
"sha256": "
|
|
2006
|
+
"size": 5872,
|
|
2007
|
+
"sha256": "32f93f0c65b2fe353b17dd1345267c85d5646fcf7de7adb9f784be551fc900af"
|
|
1958
2008
|
},
|
|
1959
2009
|
{
|
|
1960
2010
|
"path": "skills/make-figures/references/exemplar_plots/bland_altman.md",
|
|
@@ -2116,6 +2166,26 @@
|
|
|
2116
2166
|
"size": 17167,
|
|
2117
2167
|
"sha256": "88c5e0829bb7c6d1fb6d6e1f45e1ce61bccdd91a7ed9a153623e51d8bc30b651"
|
|
2118
2168
|
},
|
|
2169
|
+
{
|
|
2170
|
+
"path": "skills/make-figures/scripts/render_core_figures.py",
|
|
2171
|
+
"size": 14436,
|
|
2172
|
+
"sha256": "35f91147d51dd73b75dc116be9e0a80588fe1daf502966e82468d3c62b12f25d"
|
|
2173
|
+
},
|
|
2174
|
+
{
|
|
2175
|
+
"path": "skills/make-figures/scripts/render_core_figures_challenge/fixture/synthetic_inputs.json",
|
|
2176
|
+
"size": 1429,
|
|
2177
|
+
"sha256": "24c0944fcb1384f073988d0f6e28b8f375ba4a7eff62fb4e21bc7066726d5ebc"
|
|
2178
|
+
},
|
|
2179
|
+
{
|
|
2180
|
+
"path": "skills/make-figures/scripts/render_core_figures_challenge/problem.md",
|
|
2181
|
+
"size": 2485,
|
|
2182
|
+
"sha256": "a4e62161806d95b637d9ce984541190e5e9e213e2522d1f8740d847ee10c1a30"
|
|
2183
|
+
},
|
|
2184
|
+
{
|
|
2185
|
+
"path": "skills/make-figures/scripts/render_core_figures_challenge/verify.sh",
|
|
2186
|
+
"size": 1907,
|
|
2187
|
+
"sha256": "7f05fd9cd4e2bfdf6c5b7e8e2a61bee5f8fd44d7d2746e29e2ae77adec84b9c0"
|
|
2188
|
+
},
|
|
2119
2189
|
{
|
|
2120
2190
|
"path": "skills/make-figures/scripts/validate_pptx_mac_compat.py",
|
|
2121
2191
|
"size": 8662,
|
|
@@ -2123,8 +2193,8 @@
|
|
|
2123
2193
|
},
|
|
2124
2194
|
{
|
|
2125
2195
|
"path": "skills/make-figures/skill.yml",
|
|
2126
|
-
"size":
|
|
2127
|
-
"sha256": "
|
|
2196
|
+
"size": 2205,
|
|
2197
|
+
"sha256": "b973c376998b15cefe9bffdf580889f905b60ddc2dead00cc5cbc900a6fd50f5"
|
|
2128
2198
|
},
|
|
2129
2199
|
{
|
|
2130
2200
|
"path": "skills/make-figures/templates/official/NOTES.md",
|
|
@@ -2773,13 +2843,13 @@
|
|
|
2773
2843
|
},
|
|
2774
2844
|
{
|
|
2775
2845
|
"path": "skills/model-validation/SKILL.md",
|
|
2776
|
-
"size":
|
|
2777
|
-
"sha256": "
|
|
2846
|
+
"size": 10836,
|
|
2847
|
+
"sha256": "5cfd4ac6d75b3a474408b10d8eead3fdf7be8a44e1578dcac332cc2203ae75fe"
|
|
2778
2848
|
},
|
|
2779
2849
|
{
|
|
2780
2850
|
"path": "skills/model-validation/references/validation_design.md",
|
|
2781
|
-
"size":
|
|
2782
|
-
"sha256": "
|
|
2851
|
+
"size": 13780,
|
|
2852
|
+
"sha256": "c7ad02c2679b241d94af70c05f22740a6ad75c61c0c70d71ba2e48c4f3d64bf5"
|
|
2783
2853
|
},
|
|
2784
2854
|
{
|
|
2785
2855
|
"path": "skills/model-validation/scripts/check_split_leakage.py",
|
|
@@ -3418,8 +3488,8 @@
|
|
|
3418
3488
|
},
|
|
3419
3489
|
{
|
|
3420
3490
|
"path": "skills/self-review/SKILL.md",
|
|
3421
|
-
"size":
|
|
3422
|
-
"sha256": "
|
|
3491
|
+
"size": 102413,
|
|
3492
|
+
"sha256": "97219c57684d4eaced9e35b0968ca09da7731095c186a4e97757b4039f43f2f6"
|
|
3423
3493
|
},
|
|
3424
3494
|
{
|
|
3425
3495
|
"path": "skills/self-review/references/domain-probes/ai_overclaiming.md",
|
|
@@ -3573,8 +3643,13 @@
|
|
|
3573
3643
|
},
|
|
3574
3644
|
{
|
|
3575
3645
|
"path": "skills/self-review/references/panel_review_template.md",
|
|
3576
|
-
"size":
|
|
3577
|
-
"sha256": "
|
|
3646
|
+
"size": 15095,
|
|
3647
|
+
"sha256": "f9c084e950602ec88f7465dc953ed2309148cab37a3bef5f1b4c80deca2707a4"
|
|
3648
|
+
},
|
|
3649
|
+
{
|
|
3650
|
+
"path": "skills/self-review/references/phases/confounding_completeness.md",
|
|
3651
|
+
"size": 5344,
|
|
3652
|
+
"sha256": "051f2b066d2d708b161c1e97d666d9e214d128f1413a9c4822f0333e748bda14"
|
|
3578
3653
|
},
|
|
3579
3654
|
{
|
|
3580
3655
|
"path": "skills/self-review/scripts/check_artifact_coverage.py",
|
|
@@ -3593,8 +3668,8 @@
|
|
|
3593
3668
|
},
|
|
3594
3669
|
{
|
|
3595
3670
|
"path": "skills/self-review/scripts/check_claim_artifact.py",
|
|
3596
|
-
"size":
|
|
3597
|
-
"sha256": "
|
|
3671
|
+
"size": 13065,
|
|
3672
|
+
"sha256": "ac29a7e8145152e6641fce8eaf98766cfc943a034db72252cc38538d7ab59db2"
|
|
3598
3673
|
},
|
|
3599
3674
|
{
|
|
3600
3675
|
"path": "skills/self-review/scripts/check_classical_style.py",
|
|
@@ -3778,8 +3853,8 @@
|
|
|
3778
3853
|
},
|
|
3779
3854
|
{
|
|
3780
3855
|
"path": "skills/verify-refs/scripts/verify_refs.py",
|
|
3781
|
-
"size":
|
|
3782
|
-
"sha256": "
|
|
3856
|
+
"size": 41415,
|
|
3857
|
+
"sha256": "4377e25e6b125ace31fd35df9ffdd21a413f0f70ba1e429e5bfcf50c0a29510e"
|
|
3783
3858
|
},
|
|
3784
3859
|
{
|
|
3785
3860
|
"path": "skills/verify-refs/skill.yml",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medsci-skills",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.1",
|
|
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",
|
|
@@ -283,9 +283,20 @@ rho = 0.39 between a fasting marker (IQR 0.6 to 3.5 units, SD 3.05) and an index
|
|
|
283
283
|
marker is associated with about 0.8 index units higher on average (monotonic-linear approximation;
|
|
284
284
|
crude, unadjusted)."
|
|
285
285
|
|
|
286
|
-
**Output contract
|
|
287
|
-
|
|
288
|
-
|
|
286
|
+
**Output contract (clinical-utility is a default, not an optional add-on).** Report every
|
|
287
|
+
primary effect in units a clinician acts on, by default — do not leave these as prose to be
|
|
288
|
+
added later:
|
|
289
|
+
- **OR/HR/RR primary outcomes** → report the relative measure **and** the absolute risk at
|
|
290
|
+
a stated baseline + absolute risk difference + **NNT** (or NNH = 1/ARI), baseline risk
|
|
291
|
+
explicit. A relative-only headline is incomplete.
|
|
292
|
+
- **Continuous outcomes** → add the IQR/clinically-anchored "Real-world translation" line
|
|
293
|
+
beneath the effect size.
|
|
294
|
+
- **Prediction / classification (incl. medical-AI) models** → a **decision-curve /
|
|
295
|
+
net-benefit** pass at the relevant threshold is standard output, not just AUC +
|
|
296
|
+
calibration. An incremental claim reports added **net benefit / NRI / IDI over the
|
|
297
|
+
established clinical model**, not the new model's AUC alone. See
|
|
298
|
+
`references/table-standards/table-types/incremental_value.md` and the `make-figures`
|
|
299
|
+
`decision_curve` exemplar (and `render_core_figures.py` for the rendered curve).
|
|
289
300
|
|
|
290
301
|
## Error Handling
|
|
291
302
|
|
|
@@ -20,6 +20,7 @@ Python (alternative), interpret effect sizes clinically, and produce IRB-ready j
|
|
|
20
20
|
|
|
21
21
|
- **Formulas**: `${CLAUDE_SKILL_DIR}/references/formulas.md` -- mathematical formulas, R/Python functions, effect size conventions
|
|
22
22
|
- **Observational cohort precision branch**: `${CLAUDE_SKILL_DIR}/references/observational_cohort.md`
|
|
23
|
+
- **Prediction-model / medical-AI sample size (Riley)**: `${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md` -- the current TRIPOD+AI-aligned standard for a clinical prediction/classification model (development via `pmsampsize`, external validation via `pmvalsampsize`, net-benefit precision). Use this instead of EPV-10 whenever the goal is risk prediction for use rather than a single-predictor hypothesis test (Tests 12-13).
|
|
23
24
|
- **Justification prose exemplars**: `${CLAUDE_SKILL_DIR}/references/justification_examples.md` -- reviewer-safe IRB/Methods justification paragraphs per design (proportions, means, DTA precision, survival/log-rank, ICC agreement, non-inferiority), each stating the five required elements; load when producing the justification text
|
|
24
25
|
- **Existing R template**: See `analyze-stats` skill at `references/templates/sample_size.R` for the 7 original tests
|
|
25
26
|
|
|
@@ -49,7 +50,10 @@ What is your primary outcome?
|
|
|
49
50
|
| | +-- NO --> How many groups?
|
|
50
51
|
| | +-- 2 groups, superiority --> [4] Two-proportion comparison (chi-square)
|
|
51
52
|
| | +-- 2 groups, non-inferiority --> [10] Non-inferiority / equivalence
|
|
52
|
-
| | +-- Multivariable model --> [9] Logistic regression
|
|
53
|
+
| | +-- Multivariable model --> single-predictor hypothesis test? --> [9] Logistic regression
|
|
54
|
+
| | --> clinical prediction / AI model for use?
|
|
55
|
+
| | +-- developing the model --> [12] Prediction-model development (Riley)
|
|
56
|
+
| | +-- externally validating --> [13] External-validation (Riley)
|
|
53
57
|
| |
|
|
54
58
|
+-- Continuous (measurement, score)
|
|
55
59
|
| |
|
|
@@ -242,7 +246,10 @@ What is your primary outcome?
|
|
|
242
246
|
**Approach A: Peduzzi Rule of Thumb (EPV >= 10)**
|
|
243
247
|
- N_events = 10 * n_predictors
|
|
244
248
|
- N_total = N_events / event_rate
|
|
245
|
-
- Simple, widely cited, conservative. Use as a minimum baseline
|
|
249
|
+
- Simple, widely cited, conservative. Use as a minimum baseline **for a single-predictor
|
|
250
|
+
hypothesis test only**. For a **clinical prediction / medical-AI model intended for use**,
|
|
251
|
+
EPV-10 is outdated and reviewer-vulnerable — use the Riley criteria in Test 12
|
|
252
|
+
(development) / Test 13 (validation) instead.
|
|
246
253
|
|
|
247
254
|
**Approach B: Hsieh (1989) Formula**
|
|
248
255
|
- Uses the OR of interest for the primary predictor to calculate a more precise sample size.
|
|
@@ -320,6 +327,44 @@ N_adj = N_total / (1 - attrition_rate)
|
|
|
320
327
|
|
|
321
328
|
---
|
|
322
329
|
|
|
330
|
+
### Test 12: Prediction-Model Development (Riley)
|
|
331
|
+
|
|
332
|
+
**When to use**: developing a clinical prediction / classification model (including a
|
|
333
|
+
medical-AI model evaluated as one) — the goal is risk prediction *for use*, not a single
|
|
334
|
+
predictor's hypothesis test. EPV-10 (Tests 9/11) is outdated here.
|
|
335
|
+
|
|
336
|
+
**Approach**: the minimum N is the largest satisfying all four Riley criteria
|
|
337
|
+
simultaneously — global shrinkage ≥ 0.9, apparent–adjusted R² gap ≤ 0.05, precise overall
|
|
338
|
+
risk estimate, and (time-to-event) precise baseline survival. Implemented in R `pmsampsize`.
|
|
339
|
+
|
|
340
|
+
**Required parameters**: number of **candidate predictor parameters** (count dummy/non-linear
|
|
341
|
+
terms), a conservative expected **C-statistic or Cox-Snell R²** (with its literature source),
|
|
342
|
+
and outcome **prevalence** (binary) or **event rate + mean follow-up** (time-to-event).
|
|
343
|
+
|
|
344
|
+
Read `${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md` for the criteria, the
|
|
345
|
+
`pmsampsize` code, and the reporting requirements. Report N + required events + the binding
|
|
346
|
+
criterion + the assumed C/R² and its source.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
### Test 13: External-Validation Sample Size (Riley)
|
|
351
|
+
|
|
352
|
+
**When to use**: sizing an **external validation** of an existing prediction/AI model.
|
|
353
|
+
|
|
354
|
+
**Approach**: size to estimate the key validation metrics *precisely enough to be
|
|
355
|
+
conclusive* — target the CI width of the **C-statistic**, the **calibration slope**, the
|
|
356
|
+
**calibration-in-the-large / O:E ratio**, and (if a utility claim) **net benefit**.
|
|
357
|
+
Implemented in R `pmvalsampsize`. A floor of ≥ 100 events and ≥ 100 non-events applies, but
|
|
358
|
+
the precise target is usually larger.
|
|
359
|
+
|
|
360
|
+
**Required parameters**: expected **prevalence**, anticipated **C-statistic**, and the
|
|
361
|
+
target CI widths.
|
|
362
|
+
|
|
363
|
+
Read `${CLAUDE_SKILL_DIR}/references/prediction_model_sample_size.md` for the `pmvalsampsize`
|
|
364
|
+
code. Report the targeted CI widths and the resulting events / non-events.
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
323
368
|
## Scope Limitations
|
|
324
369
|
|
|
325
370
|
### Supported
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Prediction-model sample size (Riley) — development & external validation
|
|
2
|
+
|
|
3
|
+
For a **clinical prediction model** (or a medical-AI model evaluated as one), the
|
|
4
|
+
events-per-variable rule of thumb (EPV ≥ 10) is **outdated and reviewer-vulnerable**. EPV
|
|
5
|
+
does not target the things that determine whether a developed model is trustworthy
|
|
6
|
+
(overfitting, precise risk estimates) or whether a validation is conclusive (precise
|
|
7
|
+
discrimination and calibration). Use the **Riley criteria** instead — they are the current
|
|
8
|
+
TRIPOD+AI-aligned standard, and they are implemented in the R packages `pmsampsize`
|
|
9
|
+
(development) and `pmvalsampsize` (external validation).
|
|
10
|
+
|
|
11
|
+
Apply this whenever the goal is **risk prediction / classification for use**, not a single
|
|
12
|
+
predictor's hypothesis test. (For a single-predictor association test, the Hsieh/logistic
|
|
13
|
+
power calculation in Test 9 is appropriate.)
|
|
14
|
+
|
|
15
|
+
## Development sample size — `pmsampsize` (Riley et al.)
|
|
16
|
+
|
|
17
|
+
The minimum development sample size is the largest N satisfying four criteria
|
|
18
|
+
simultaneously:
|
|
19
|
+
|
|
20
|
+
1. **Small overfitting** — global shrinkage factor ≥ 0.9.
|
|
21
|
+
2. **Small optimism in apparent fit** — absolute difference between apparent and adjusted
|
|
22
|
+
Nagelkerke R² ≤ 0.05.
|
|
23
|
+
3. **Precise estimate of overall risk** — margin of error of the mean predicted outcome
|
|
24
|
+
(the intercept) ≤ 0.05.
|
|
25
|
+
4. **(time-to-event)** precise estimate of the baseline survival at a key time point.
|
|
26
|
+
|
|
27
|
+
Inputs you must specify (and justify from prior literature, not guess):
|
|
28
|
+
- number of **candidate predictor parameters** (count dummy variables and non-linear terms,
|
|
29
|
+
not just variables);
|
|
30
|
+
- the anticipated model performance — a conservative **Cox-Snell R²** (derivable from an
|
|
31
|
+
expected **C-statistic** + outcome prevalence) or expected R²;
|
|
32
|
+
- the **outcome prevalence** (binary) or **event rate + mean follow-up** (time-to-event),
|
|
33
|
+
or outcome mean/SD (continuous).
|
|
34
|
+
|
|
35
|
+
```r
|
|
36
|
+
library(pmsampsize)
|
|
37
|
+
# Binary outcome: prevalence 0.20, 30 candidate parameters, expected C ≈ 0.78
|
|
38
|
+
# (convert C to a conservative Cox-Snell R²; pmsampsize accepts csrsquared or cstatistic)
|
|
39
|
+
pmsampsize(type = "b", cstatistic = 0.78, parameters = 30, prevalence = 0.20)
|
|
40
|
+
|
|
41
|
+
# Time-to-event: rate per person-year, mean follow-up, timepoint of interest
|
|
42
|
+
pmsampsize(type = "s", csrsquared = 0.05, parameters = 30,
|
|
43
|
+
rate = 0.08, timepoint = 5, meanfup = 4.2)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Report the **minimum N and the required number of events**, the assumed C-statistic / R²
|
|
47
|
+
and its source, and the binding criterion. A development set below this is a standard
|
|
48
|
+
high-impact-journal rejection.
|
|
49
|
+
|
|
50
|
+
## External-validation sample size — `pmvalsampsize` (Riley et al.)
|
|
51
|
+
|
|
52
|
+
Size the validation set to estimate the key performance metrics **precisely enough to be
|
|
53
|
+
conclusive** — target the confidence-interval width of each:
|
|
54
|
+
|
|
55
|
+
- **discrimination** — C-statistic (target CI width, e.g. ±0.05);
|
|
56
|
+
- **calibration slope** (target SE / CI width);
|
|
57
|
+
- **calibration-in-the-large / O:E ratio**;
|
|
58
|
+
- **(if reporting clinical utility)** the standardized **net benefit** at the decision
|
|
59
|
+
threshold.
|
|
60
|
+
|
|
61
|
+
```r
|
|
62
|
+
library(pmvalsampsize)
|
|
63
|
+
# Validate a model with expected prevalence 0.20, anticipated C ≈ 0.78,
|
|
64
|
+
# targeting a C-statistic CI half-width of 0.05 and a precise calibration slope
|
|
65
|
+
pmvalsampsize(type = "b", prevalence = 0.20, cstatistic = 0.78,
|
|
66
|
+
cslope = 1, oe = 1, lpnormal = c(-0.5, 0.5),
|
|
67
|
+
cstatci = 0.10) # target CI *width* for the C-statistic
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
A common **floor** is ≥ 100 events and ≥ 100 non-events (Vergouwe; Collins), but
|
|
71
|
+
`pmvalsampsize` gives the precise target for your metrics and usually requires more.
|
|
72
|
+
|
|
73
|
+
## Sample size for net benefit / decision-curve
|
|
74
|
+
|
|
75
|
+
If the model's value claim rests on **net benefit** (decision-curve analysis), size the
|
|
76
|
+
study to estimate net benefit at the relevant threshold with adequate precision —
|
|
77
|
+
`pmvalsampsize` supports a net-benefit target, and the development criteria should be met
|
|
78
|
+
so the model is not overfit before its utility is judged. Do not claim clinical utility
|
|
79
|
+
from a decision curve estimated on an underpowered validation set.
|
|
80
|
+
|
|
81
|
+
## Reporting
|
|
82
|
+
|
|
83
|
+
- State that sizing followed the **Riley criteria** (cite the originals) — not EPV-10.
|
|
84
|
+
- Report the assumed C-statistic / R² / prevalence and **where they came from**.
|
|
85
|
+
- For development, report N + events + the binding criterion; for validation, report the
|
|
86
|
+
targeted CI widths and the resulting N (events and non-events).
|
|
87
|
+
|
|
88
|
+
## References (cite the originals)
|
|
89
|
+
|
|
90
|
+
- Riley RD, Snell KIE, Ensor J, et al. Minimum sample size for developing a multivariable
|
|
91
|
+
prediction model: PART II — binary and time-to-event outcomes. *Stat Med* 2019.
|
|
92
|
+
- Riley RD, Ensor J, Snell KIE, et al. Calculating the sample size required for developing
|
|
93
|
+
a clinical prediction model. *BMJ* 2020.
|
|
94
|
+
- Riley RD, Debray TPA, Collins GS, et al. Minimum sample size for external validation of a
|
|
95
|
+
clinical prediction model with a binary outcome. *Stat Med* 2021.
|
|
96
|
+
- Collins GS, Ogundimu EO, Altman DG. Sample size considerations for the external
|
|
97
|
+
validation of a multivariable prognostic model. *Stat Med* 2016.
|
|
@@ -65,6 +65,11 @@ VAGUE = re.compile(
|
|
|
65
65
|
r"\b(?:recent|current|emerging|latest|evolving)\b\s+"
|
|
66
66
|
r"(?:best[- ]practice|guidance|practice|recommendations?|standards?|guidelines?)",
|
|
67
67
|
re.I)
|
|
68
|
+
# VAGUE only counts inside a reporting-framework context; otherwise "recent
|
|
69
|
+
# best-practice recommendations" about a method is a false positive (F05).
|
|
70
|
+
REPORTING_CUE = re.compile(
|
|
71
|
+
r"\b(?:report(?:ing|ed)?|checklist|EQUATOR|reporting\s+standard|"
|
|
72
|
+
r"reporting\s+framework)\b", re.I)
|
|
68
73
|
|
|
69
74
|
|
|
70
75
|
def _sentences(text: str) -> list[str]:
|
|
@@ -128,15 +133,20 @@ def check(text: str) -> list[dict]:
|
|
|
128
133
|
"where": m,
|
|
129
134
|
})
|
|
130
135
|
|
|
131
|
-
# VAGUE_GUIDANCE
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
# VAGUE_GUIDANCE — only when the sentence is clearly about REPORTING (a reporting
|
|
137
|
+
# guideline / checklist) yet names no specific framework. Gating on a reporting cue
|
|
138
|
+
# prevents firing on method-level wording like "external validation following recent
|
|
139
|
+
# best-practice recommendations", which is not a reporting-framework claim at all.
|
|
140
|
+
for s in _sentences(text):
|
|
141
|
+
m = VAGUE.search(s)
|
|
142
|
+
if m and REPORTING_CUE.search(s):
|
|
143
|
+
claims.append({
|
|
144
|
+
"verdict": "VAGUE_GUIDANCE",
|
|
145
|
+
"severity": "Minor",
|
|
146
|
+
"detail": (f"vague wording '{m.group(0).strip()}' in a reporting context — name "
|
|
147
|
+
f"the specific framework and cite it"),
|
|
148
|
+
"where": m.group(0).strip()[:80],
|
|
149
|
+
})
|
|
140
150
|
|
|
141
151
|
return claims
|
|
142
152
|
|
|
@@ -41,5 +41,21 @@ check "SELF_COINED_LABEL detected (12-AI)" has_verdict SELF_COINED_LABEL
|
|
|
41
41
|
python3 "$SCRIPT" --manuscript "$CLEAN" --strict --quiet >/dev/null 2>&1
|
|
42
42
|
check "exit 0 on clean manuscript (base named + cited)" test "$?" -eq 0
|
|
43
43
|
|
|
44
|
+
# (3) FP guard (less-defensive, F05): method-level "recent best-practice recommendations"
|
|
45
|
+
# with NO reporting context must NOT trigger VAGUE_GUIDANCE.
|
|
46
|
+
NOFP="$(mktemp -t fw_nofp_XXXX).md"
|
|
47
|
+
trap 'rm -f "$OUT" "$NOFP"' EXIT
|
|
48
|
+
cat > "$NOFP" <<'EOF'
|
|
49
|
+
# Methods
|
|
50
|
+
We performed external validation following recent best-practice recommendations.
|
|
51
|
+
The imputation strategy was aligned with current guidance for handling missingness.
|
|
52
|
+
EOF
|
|
53
|
+
python3 "$SCRIPT" --manuscript "$NOFP" --out "$OUT" --quiet >/dev/null 2>&1
|
|
54
|
+
check "no VAGUE_GUIDANCE on method-level recommendations (no reporting cue)" python3 -c "
|
|
55
|
+
import json
|
|
56
|
+
d=json.load(open('$OUT'))
|
|
57
|
+
raise SystemExit(0 if not any(c['verdict']=='VAGUE_GUIDANCE' for c in d['claims']) else 1)
|
|
58
|
+
"
|
|
59
|
+
|
|
44
60
|
echo "fail=$fail"; [[ "$fail" -eq 0 ]] && echo "ALL PASS" || echo "FAILURES: $fail"
|
|
45
61
|
exit "$fail"
|
|
@@ -275,7 +275,8 @@ Recommend one primary guideline:
|
|
|
275
275
|
- healthy volunteer bias unacknowledged → inflated external validity claims
|
|
276
276
|
- surveillance bias from unequal follow-up frequency between groups
|
|
277
277
|
- **3 bias classification (Hernan/Robins)**: selection bias (who enters), information bias (how measured), confounding (what else differs) — explicitly map each threat
|
|
278
|
-
- **
|
|
278
|
+
- **comparative / causal question → emulate a target trial.** For a treatment-vs-treatment, screening-vs-no-screening, or drug-A-vs-drug-B question on routinely-collected data, specify the seven target-trial components (eligibility, strategies, assignment, **time zero**, outcome, causal contrast, analysis plan) before extraction — this is what prevents the immortal-time / prevalent-user / confounding-by-indication trio above and turns an association into a defensible causal contrast. New-user + active-comparator design, grace-period clone-censor-weight, and negative controls are in `references/target_trial_emulation.md`.
|
|
279
|
+
- **confounding completeness**: pre-specify the adjustment set from a DAG (not a Table-1 p < 0.05 rule), and plan to report whether any measured covariate that turns out imbalanced by exposure but outside the adjustment set leaves the primary estimate robust (an extended-adjustment sensitivity model). Build the DAG and pre-screen the proposed covariates with `scripts/adjustment_set_helper.py` (flags mediator / collider / descendant adjustment and omitted confounders, and proposes a candidate backdoor set), then derive the **minimal** sufficient set with dagitty — see `references/dag_adjustment.md`. At review time `/self-review` Phase 2.5e + the O1–O12 probes in `observational_confounding.md` check this against Table 1 (including O7 over-adjustment, O10 overlapping-subset-gradient discipline, for complex-survey data O11 design-based weighting and O12 data-driven-threshold mining, O13 — a cross-sectional mediation claim cannot order X→M→Y, and O14 — a synergy/joint-effect claim needs the additive interaction scale (RERI/AP/S), not a multiplicative-only test).
|
|
279
280
|
|
|
280
281
|
### Multimodal LLM / report generation
|
|
281
282
|
- no clear rubric for clinical correctness
|