medsci-skills 5.15.0 → 5.16.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.
- package/README.md +10 -5
- package/metadata/distribution_files.json +67 -12
- package/metadata/distribution_manifest.json +2 -1
- package/metadata/skills_catalog.json +13 -3
- package/package.json +1 -1
- package/skills/model-scaffold/SKILL.md +31 -15
- package/skills/model-scaffold/references/finetuning_guide.md +91 -0
- package/skills/model-scaffold/scripts/check_training_hygiene.py +38 -2
- package/skills/model-scaffold/scripts/scaffold.py +263 -1
- package/skills/model-scaffold/scripts/scaffold_challenge/problem.md +6 -0
- package/skills/model-scaffold/scripts/scaffold_challenge/verify.sh +20 -2
- package/skills/model-scaffold/skill.yml +4 -1
- package/skills/model-scaffold/tests/fixtures/finetune_no_provenance/train.py +24 -0
- package/skills/model-scaffold/tests/test_training_hygiene.sh +14 -1
- package/skills/radiomics-ml/SKILL.md +134 -0
- package/skills/radiomics-ml/references/radiomics_ml_guide.md +115 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml.py +229 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml_challenge/expected/strong.txt +9 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml_challenge/expected/weak.txt +14 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml_challenge/fixture/pipeline_strong.json +13 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml_challenge/fixture/pipeline_weak.json +13 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml_challenge/problem.md +20 -0
- package/skills/radiomics-ml/scripts/check_radiomics_ml_challenge/verify.sh +37 -0
- package/skills/radiomics-ml/skill.yml +46 -0
- package/skills/radiomics-ml/tests/test_radiomics_ml.sh +88 -0
package/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
# MedSci Skills
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**54 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)
|
|
10
10
|
[](https://github.com/Aperivue/medsci-skills/releases/latest)
|
|
11
11
|
[](https://github.com/Aperivue/medsci-skills/actions/workflows/validate.yml)
|
|
12
|
-

|
|
13
13
|
[](https://www.npmjs.com/package/medsci-skills)
|
|
14
14
|
[](https://youtu.be/MclQ_RIofpE)
|
|
15
15
|
[](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.16** — model-engineering produce-side depth, clinical fine-tuning focus (Items 3–4 of the [produce-side depth roadmap](docs/roadmap_model_engineering_depth.md)). A new **`radiomics-ml`** skill + `check_radiomics_ml` gate for the most common solo-doable clinical-ML workflow — radiomics / tabular features → any classical learner (LASSO / SVM / random forest / XGBoost / …) → a clinical outcome, no GPU — with a learner-agnostic nested-CV / calibration / stability gate; plus a **`model-scaffold` fine-tuning mode** (`--task finetune` + `--from-pretrained`) that adapts a pretrained backbone on collected clinical data with a frozen→unfrozen schedule, discriminative learning rates, and a pretrained-weight provenance record (`PRETRAINED.md` + a `PRETRAINED_PROVENANCE_MISSING` verdict on the existing `check_training_hygiene`, plus a MedSAM-adaptation + train-only diffusion-augmentation guide). Additive and backward-compatible; **54 skills / 44 guidelines / 49 integrity detectors / 22 domain-probe modules**. (See the [CHANGELOG](CHANGELOG.md) for v5.0–v5.15.)
|
|
289
|
+
|
|
288
290
|
**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
291
|
|
|
290
292
|
**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):
|
|
@@ -402,6 +404,8 @@ MedSci Skills is **opinionated and narrow on purpose**: a single physician-resea
|
|
|
402
404
|
|
|
403
405
|
📖 **Per-skill reference:** [`docs/skills/`](docs/skills/) — one page per skill (what it does, when it activates, its Quality Card — purpose, safety boundaries, known limitations, validation, evidence — and bundled resources), generated from each `SKILL.md` + `skill.yml`. See [`docs/skills/AUDIT.md`](docs/skills/AUDIT.md) for how the skills are validated.
|
|
404
406
|
|
|
407
|
+
🧠 **ML / DL method coverage:** [`docs/method_coverage_map.md`](docs/method_coverage_map.md) — which machine-learning and deep-learning method families (CNN / transformer / segmentation / detection / foundation / diffusion / SSL for imaging; the full classical family — penalised regression, SVM, k-NN, trees, boosting [XGBoost / LightGBM / CatBoost], MLP, ensembles, clustering — for radiomics/tabular; LLM/MLLM) map to which skills for selection, production, validation, interpretation, and reporting.
|
|
408
|
+
|
|
405
409
|
```
|
|
406
410
|
┌─────────────────────────────────┐
|
|
407
411
|
│ orchestrate: single entry point │
|
|
@@ -451,14 +455,14 @@ ma-scout -> search-lit -> fulltext-retrieval -> design-study ──> write-proto
|
|
|
451
455
|
|
|
452
456
|
### By research stage
|
|
453
457
|
|
|
454
|
-
All
|
|
458
|
+
All 54 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
459
|
|
|
456
460
|
| Stage | Skills |
|
|
457
461
|
|-------|--------|
|
|
458
462
|
| 🔭 **Discover & scope** | `ma-scout` · `find-cohort-gap` · `search-lit` · `fulltext-retrieval` · `lit-sync` · `author-strategy` |
|
|
459
463
|
| 📐 **Design & plan** | `design-study` · `calc-sample-size` · `define-variables` · `write-protocol` · `fill-protocol` · `design-ai-benchmarking` |
|
|
460
464
|
| 🧹 **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` |
|
|
465
|
+
| 🤖 **Medical-AI model engineering** | `preprocess-imaging` · `architecture-zoo` · `model-scaffold` · `model-validation` · `model-evaluation` · `explainability` · `radiomics-ml` · `model-card` · `mllm-eval` |
|
|
462
466
|
| ✍️ **Write & visualize** | `write-paper` · `make-figures` · `review-paper` · `present-paper` · `humanize` · `polish-language` · `academic-aio` |
|
|
463
467
|
| ✅ **Comply & verify** | `check-reporting` · `self-review` · `verify-refs` · `manage-refs` |
|
|
464
468
|
| 📤 **Submit & respond** | `find-journal` · `add-journal` · `sync-submission` · `revise` · `peer-review` · `fill-icmje-coi` |
|
|
@@ -481,11 +485,12 @@ All 53 skills, grouped by where they fit in the clinical-manuscript and medical-
|
|
|
481
485
|
| **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. |
|
|
482
486
|
| **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
487
|
| **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. |
|
|
484
|
-
| **model-scaffold** | Generate a reproducible, runnable PyTorch training repo for a medical-imaging task — segmentation (U-Net), classification, detection, image-to-image synthesis,
|
|
488
|
+
| **model-scaffold** | Generate a reproducible, runnable PyTorch training repo for a medical-imaging task — segmentation (U-Net), classification, detection, image-to-image synthesis, self-supervised pretraining, or fine-tuning a pretrained backbone (transfer learning) — 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). Fine-tuning mode (`--task finetune`) adds a frozen→unfrozen schedule, discriminative learning rates, and a pretrained-weight provenance record (`PRETRAINED.md`), with a MedSAM-adaptation + train-only diffusion-augmentation guide. Reproducibility holds by construction; ships a `check_training_hygiene` AST gate (RNG seeding, eval-mode inference, train-split-only loaders, pretrained-provenance) + a network-free build→validate challenge. Integrates with MONAI / nnU-Net / TorchIO / timm / torchvision for production-grade models. |
|
|
485
489
|
| **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. |
|
|
486
490
|
| **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. |
|
|
487
491
|
| **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
492
|
| **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. |
|
|
493
|
+
| **radiomics-ml** | Produce or audit a radiomics / tabular clinical-ML study — features → random forest / XGBoost / regularised logistic → clinical outcome — the most common solo-doable clinical-ML workflow (no GPU, no engineer). Emits a pipeline manifest + a deterministic rigor gate (`check_radiomics_ml`): `NO_NESTED_CV`, `HIGH_DIM_LOW_EVENTS`, `SELECTION_OUTSIDE_CV` (Major); `NO_FEATURE_STABILITY`, `NO_CALIBRATION`, `NO_EXTERNAL_VALIDATION` (Minor). pyradiomics/IBSI settings, nested CV with in-fold selection, ICC stability, SHAP, calibration + decision curve, CLEAR/TRIPOD+AI/PROBAST-AI reporting. Integrates scikit-learn / xgboost / pyradiomics; never reimplements them. |
|
|
489
494
|
| **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. |
|
|
490
495
|
| **intake-project** | Classifies new research projects, summarizes current state, identifies missing inputs, and recommends next steps. |
|
|
491
496
|
| **grant-builder** | Structures grant proposals: significance, innovation, approach, milestones, and consortium roles. |
|
|
@@ -2868,8 +2868,13 @@
|
|
|
2868
2868
|
},
|
|
2869
2869
|
{
|
|
2870
2870
|
"path": "skills/model-scaffold/SKILL.md",
|
|
2871
|
-
"size":
|
|
2872
|
-
"sha256": "
|
|
2871
|
+
"size": 9237,
|
|
2872
|
+
"sha256": "d7e736178cb60d2d13cef9174474297bd54bc6d4d1f3862023d802ff0c034a95"
|
|
2873
|
+
},
|
|
2874
|
+
{
|
|
2875
|
+
"path": "skills/model-scaffold/references/finetuning_guide.md",
|
|
2876
|
+
"size": 6208,
|
|
2877
|
+
"sha256": "b7817d53eeeb506b573beaae1889fa863dd81286d474ab99b46b38ad046b32e7"
|
|
2873
2878
|
},
|
|
2874
2879
|
{
|
|
2875
2880
|
"path": "skills/model-scaffold/references/training_guide.md",
|
|
@@ -2878,13 +2883,13 @@
|
|
|
2878
2883
|
},
|
|
2879
2884
|
{
|
|
2880
2885
|
"path": "skills/model-scaffold/scripts/check_training_hygiene.py",
|
|
2881
|
-
"size":
|
|
2882
|
-
"sha256": "
|
|
2886
|
+
"size": 14095,
|
|
2887
|
+
"sha256": "57542a54dac607e89e7f13e5025bd2ce6b32e629064a18cbb0f0c15fdfc6181c"
|
|
2883
2888
|
},
|
|
2884
2889
|
{
|
|
2885
2890
|
"path": "skills/model-scaffold/scripts/scaffold.py",
|
|
2886
|
-
"size":
|
|
2887
|
-
"sha256": "
|
|
2891
|
+
"size": 51482,
|
|
2892
|
+
"sha256": "150abbc4864a92913b202893962c29cda8ec6ce1918f35558aa5b02514b6a0cb"
|
|
2888
2893
|
},
|
|
2889
2894
|
{
|
|
2890
2895
|
"path": "skills/model-scaffold/scripts/scaffold_challenge/expected/split_assignment.csv",
|
|
@@ -2898,18 +2903,18 @@
|
|
|
2898
2903
|
},
|
|
2899
2904
|
{
|
|
2900
2905
|
"path": "skills/model-scaffold/scripts/scaffold_challenge/problem.md",
|
|
2901
|
-
"size":
|
|
2902
|
-
"sha256": "
|
|
2906
|
+
"size": 3226,
|
|
2907
|
+
"sha256": "950af6c956f73b491b2bee102d884765aaeb783b5842eb428ac2ad81b49f67e8"
|
|
2903
2908
|
},
|
|
2904
2909
|
{
|
|
2905
2910
|
"path": "skills/model-scaffold/scripts/scaffold_challenge/verify.sh",
|
|
2906
|
-
"size":
|
|
2907
|
-
"sha256": "
|
|
2911
|
+
"size": 6396,
|
|
2912
|
+
"sha256": "77d81387647abf00de4b03f91a7c7bf9bef38d9679b148762c906eaccfee9f73"
|
|
2908
2913
|
},
|
|
2909
2914
|
{
|
|
2910
2915
|
"path": "skills/model-scaffold/skill.yml",
|
|
2911
|
-
"size":
|
|
2912
|
-
"sha256": "
|
|
2916
|
+
"size": 3772,
|
|
2917
|
+
"sha256": "aaae59edb50c50b01be2aaca3c94b63ce76af067ff25750248517c5ce91ccf41"
|
|
2913
2918
|
},
|
|
2914
2919
|
{
|
|
2915
2920
|
"path": "skills/model-validation/SKILL.md",
|
|
@@ -3411,6 +3416,56 @@
|
|
|
3411
3416
|
"size": 1372,
|
|
3412
3417
|
"sha256": "81caa10775246f2db3f5e08948292f63076d44ffc039d8eec764f1d46aab275f"
|
|
3413
3418
|
},
|
|
3419
|
+
{
|
|
3420
|
+
"path": "skills/radiomics-ml/SKILL.md",
|
|
3421
|
+
"size": 8273,
|
|
3422
|
+
"sha256": "cc65bfd50db2b6e9b6681e1c9649b306490cd5dd74192bfdf5316362b71f141b"
|
|
3423
|
+
},
|
|
3424
|
+
{
|
|
3425
|
+
"path": "skills/radiomics-ml/references/radiomics_ml_guide.md",
|
|
3426
|
+
"size": 6707,
|
|
3427
|
+
"sha256": "29bf2b2b847c488ddb33e50cd21ea0e2cd4937a1a62ab2655f31227a0e42215a"
|
|
3428
|
+
},
|
|
3429
|
+
{
|
|
3430
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml.py",
|
|
3431
|
+
"size": 10179,
|
|
3432
|
+
"sha256": "b1cfbd9991aa8871d5aabc528c9aa22eecf8e46cb5983872bca2359229223840"
|
|
3433
|
+
},
|
|
3434
|
+
{
|
|
3435
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml_challenge/expected/strong.txt",
|
|
3436
|
+
"size": 369,
|
|
3437
|
+
"sha256": "c73c776e6558d9a78dacd3c63ae1cc3dee183d9e1a2f27d99b1e0db70f44997e"
|
|
3438
|
+
},
|
|
3439
|
+
{
|
|
3440
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml_challenge/expected/weak.txt",
|
|
3441
|
+
"size": 1408,
|
|
3442
|
+
"sha256": "3bb90f31587e94f3f2b267874a9ac58cce5adf3436254bc206092e0acfb86cd7"
|
|
3443
|
+
},
|
|
3444
|
+
{
|
|
3445
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml_challenge/fixture/pipeline_strong.json",
|
|
3446
|
+
"size": 322,
|
|
3447
|
+
"sha256": "83d128fe0b728ef52a1fd98ef5b5bd478c3e48455cdb07d8040f9d130df81cee"
|
|
3448
|
+
},
|
|
3449
|
+
{
|
|
3450
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml_challenge/fixture/pipeline_weak.json",
|
|
3451
|
+
"size": 313,
|
|
3452
|
+
"sha256": "2fa1a3f98f952faf2e6e1faf1bdbf4675a44dc88679dcfaf18a4f32eb47ba9e7"
|
|
3453
|
+
},
|
|
3454
|
+
{
|
|
3455
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml_challenge/problem.md",
|
|
3456
|
+
"size": 894,
|
|
3457
|
+
"sha256": "9a6abad4e12f9b4e9290eb305fb9ad04127fa1cde03961a38ac4ccb5431a2100"
|
|
3458
|
+
},
|
|
3459
|
+
{
|
|
3460
|
+
"path": "skills/radiomics-ml/scripts/check_radiomics_ml_challenge/verify.sh",
|
|
3461
|
+
"size": 1988,
|
|
3462
|
+
"sha256": "b9e55aaf9b29f3e810b837fc373c7a212dc5f778a49bac11854bdb50ed84a184"
|
|
3463
|
+
},
|
|
3464
|
+
{
|
|
3465
|
+
"path": "skills/radiomics-ml/skill.yml",
|
|
3466
|
+
"size": 3790,
|
|
3467
|
+
"sha256": "9b99b87add656873d3f7277ce12490ffea36d919e9538bc4f4fbe1ebbfedc18e"
|
|
3468
|
+
},
|
|
3414
3469
|
{
|
|
3415
3470
|
"path": "skills/render-pdf-doc/SKILL.md",
|
|
3416
3471
|
"size": 7490,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.16.0",
|
|
4
4
|
"owned_skills": [
|
|
5
5
|
"academic-aio",
|
|
6
6
|
"add-journal",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"preprocess-imaging",
|
|
44
44
|
"present-paper",
|
|
45
45
|
"publish-skill",
|
|
46
|
+
"radiomics-ml",
|
|
46
47
|
"render-pdf-doc",
|
|
47
48
|
"replicate-study",
|
|
48
49
|
"review-paper",
|
|
@@ -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":
|
|
3
|
+
"skill_count": 54,
|
|
4
4
|
"categories": [
|
|
5
5
|
{
|
|
6
6
|
"key": "literature_references",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"model-evaluation",
|
|
39
39
|
"model-scaffold",
|
|
40
40
|
"model-validation",
|
|
41
|
-
"preprocess-imaging"
|
|
41
|
+
"preprocess-imaging",
|
|
42
|
+
"radiomics-ml"
|
|
42
43
|
]
|
|
43
44
|
},
|
|
44
45
|
{
|
|
@@ -415,7 +416,7 @@
|
|
|
415
416
|
"layer": "B",
|
|
416
417
|
"owner_domain": "model_development",
|
|
417
418
|
"maturity": "official",
|
|
418
|
-
"description": "Generate a reproducible, runnable PyTorch training repo for a medical-imaging task — segmentation, classification, detection, image-to-image synthesis,
|
|
419
|
+
"description": "Generate a reproducible, runnable PyTorch training repo for a medical-imaging task — segmentation, classification, detection, image-to-image synthesis, self-supervised pretraining, or fine-tuning a pr…"
|
|
419
420
|
},
|
|
420
421
|
{
|
|
421
422
|
"slug": "model-validation",
|
|
@@ -480,6 +481,15 @@
|
|
|
480
481
|
"maturity": "official",
|
|
481
482
|
"description": "Convert a personal agent skill into a distributable, open-source-ready skill."
|
|
482
483
|
},
|
|
484
|
+
{
|
|
485
|
+
"slug": "radiomics-ml",
|
|
486
|
+
"category": "model_engineering",
|
|
487
|
+
"category_label": "Model Engineering & Validation",
|
|
488
|
+
"layer": "D",
|
|
489
|
+
"owner_domain": "model_validation",
|
|
490
|
+
"maturity": "official",
|
|
491
|
+
"description": "Produce or audit a radiomics / tabular clinical-ML study — imaging or clinical features → any classical learner (penalised logistic [LASSO / ridge / elastic-net], SVM, k-NN, naive Bayes, LDA/QDA, deci…"
|
|
492
|
+
},
|
|
483
493
|
{
|
|
484
494
|
"slug": "render-pdf-doc",
|
|
485
495
|
"category": "presentation_tooling",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medsci-skills",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.16.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",
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
name: model-scaffold
|
|
3
3
|
description: >
|
|
4
4
|
Generate a reproducible, runnable PyTorch training repo for a medical-imaging task — segmentation,
|
|
5
|
-
classification, detection, image-to-image synthesis,
|
|
6
|
-
middle link between choosing an architecture and
|
|
7
|
-
seed-locked split as an auditable artifact, a
|
|
8
|
-
seed every RNG and infer under eval mode, a
|
|
9
|
-
Methods stub with VERIFY placeholders (no
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
classification, detection, image-to-image synthesis, self-supervised pretraining, or fine-tuning a
|
|
6
|
+
pretrained backbone (transfer learning) — the missing middle link between choosing an architecture and
|
|
7
|
+
validating a trained model. Emits a patient-level seed-locked split as an auditable artifact, a
|
|
8
|
+
task-appropriate model, train and evaluate scripts that seed every RNG and infer under eval mode, a
|
|
9
|
+
config, requirements, a reproducibility record, and a Methods stub with VERIFY placeholders (no
|
|
10
|
+
fabricated numbers). Fine-tuning mode adds a frozen-then-unfrozen schedule, discriminative learning
|
|
11
|
+
rates, and a pretrained-weight provenance record. The reproducibility guarantees hold by construction,
|
|
12
|
+
so the build is leakage-safe before any training runs. Integrates with MONAI, nnU-Net, TorchIO, timm,
|
|
13
|
+
and torchvision — it does not reimplement them.
|
|
14
|
+
triggers: model scaffold, scaffold a model, training repo, PyTorch repo, build a model, train a model, fine-tune, finetune, transfer learning, pretrained backbone, MedSAM, SAM adaptation, segmentation, classification, detection, image synthesis, self-supervised, SimCLR, Pix2Pix, Faster R-CNN, U-Net, UNet, nnU-Net, MONAI, timm, torchvision, dataloader, train.py, patient-level split, reproducible training, seed everything, generate training code, medical imaging model
|
|
13
15
|
tools: Read, Write, Edit, Bash, Grep, Glob
|
|
14
16
|
model: inherit
|
|
15
17
|
---
|
|
@@ -20,7 +22,8 @@ model: inherit
|
|
|
20
22
|
|
|
21
23
|
This skill stamps out a **runnable PyTorch training repo** for a medical-imaging task — `--task`
|
|
22
24
|
**segmentation** (U-Net), **classification** (CNN / `timm` backbone), **detection** (torchvision Faster
|
|
23
|
-
R-CNN / FPN), **synthesis** (Pix2Pix generator + PatchGAN),
|
|
25
|
+
R-CNN / FPN), **synthesis** (Pix2Pix generator + PatchGAN), **ssl** (SimCLR encoder), or **finetune**
|
|
26
|
+
(transfer-learning a pretrained backbone with a frozen→unfrozen schedule + a provenance record) —
|
|
24
27
|
with the reproducibility guarantees **baked in by construction** — so the build is leakage-safe and
|
|
25
28
|
reproducible before a single epoch runs. It is the imaging analogue of how `/analyze-stats` generates
|
|
26
29
|
runnable statistical code: the generator produces the repo, you run the training on your GPU / Colab,
|
|
@@ -34,6 +37,9 @@ in the generated `requirements.txt`); it does not reimplement them.
|
|
|
34
37
|
## When to use
|
|
35
38
|
- You have a data manifest (one row per image, with a patient/subject ID) and want a reproducible,
|
|
36
39
|
leakage-safe starting repo for a segmentation model.
|
|
40
|
+
- You want to **fine-tune a pretrained backbone** (transfer learning — the common clinician workflow:
|
|
41
|
+
a `timm` / MONAI / MedSAM checkpoint adapted to your collected clinical data) with the freeze schedule,
|
|
42
|
+
discriminative learning rates, and pretrained-weight provenance recorded (`--task finetune`).
|
|
37
43
|
|
|
38
44
|
## When NOT to use
|
|
39
45
|
- Auditing an already-trained model's validation design → `/model-validation`.
|
|
@@ -54,8 +60,14 @@ patient level off this column.
|
|
|
54
60
|
python3 ${CLAUDE_SKILL_DIR}/scripts/scaffold.py \
|
|
55
61
|
--manifest <manifest.csv> --task segmentation --out model_repo --seed 42 \
|
|
56
62
|
--in-channels 1 --out-channels 1
|
|
57
|
-
# --task = segmentation | classification | detection | synthesis | ssl
|
|
58
|
-
# (out-channels = num classes for classification, target channels for synthesis)
|
|
63
|
+
# --task = segmentation | classification | detection | synthesis | ssl | finetune
|
|
64
|
+
# (out-channels = num classes for classification/finetune, target channels for synthesis)
|
|
65
|
+
# fine-tuning a pretrained backbone (transfer learning) on collected clinical data:
|
|
66
|
+
python3 ${CLAUDE_SKILL_DIR}/scripts/scaffold.py \
|
|
67
|
+
--manifest <manifest.csv> --task finetune --out model_repo --seed 42 \
|
|
68
|
+
--out-channels <num_classes> --from-pretrained timm:resnet50.a1_in1k
|
|
69
|
+
# emits PRETRAINED.md (provenance) + a frozen→unfrozen train.py with discriminative LRs;
|
|
70
|
+
# record the exact pretrained source so the fine-tune is reproducible.
|
|
59
71
|
```
|
|
60
72
|
This writes `model_repo/` with `config.yaml`, `model.py` (the task's model — U-Net / CNN / Faster R-CNN
|
|
61
73
|
/ Pix2Pix / SimCLR encoder), `dataset.py` (reads the frozen split), `losses.py` (task-appropriate),
|
|
@@ -79,9 +91,11 @@ patient-disjointness proof, and (optionally, locally with torch installed)
|
|
|
79
91
|
### Phase 4 — Plug in your data and train
|
|
80
92
|
Implement `dataset.py`'s `_load_image` / `_load_label` for your modality (DICOM / NIfTI / TIFF via
|
|
81
93
|
nibabel / pydicom / tifffile / TorchIO / MONAI transforms). For production, swap `model.py` for MONAI
|
|
82
|
-
`UNet` / `SegResNet` or an nnU-Net plan (see `${CLAUDE_SKILL_DIR}/references/training_guide.md`).
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
`UNet` / `SegResNet` or an nnU-Net plan (see `${CLAUDE_SKILL_DIR}/references/training_guide.md`). For a
|
|
95
|
+
fine-tuning repo (`--task finetune`), fill `PRETRAINED.md` and set the freeze schedule / discriminative
|
|
96
|
+
learning rates (see `${CLAUDE_SKILL_DIR}/references/finetuning_guide.md`, which also covers MedSAM/SAM
|
|
97
|
+
adaptation and train-only diffusion augmentation). Run `python train.py` (best model selected on the
|
|
98
|
+
**val** split), then `python evaluate.py` (predictions on the **test** split, touched once).
|
|
85
99
|
|
|
86
100
|
### Phase 5 — Validate, evaluate, publish
|
|
87
101
|
Hand off to `/model-validation` (validation-tier + comparator + metric-selection audit),
|
|
@@ -110,7 +124,9 @@ runnability.
|
|
|
110
124
|
## Deterministic gates
|
|
111
125
|
- `scripts/scaffold.py` — the generator (stdlib + numpy; deterministic given manifest + seed).
|
|
112
126
|
- `scripts/check_training_hygiene.py` — AST linter: all RNGs seeded, cuDNN deterministic,
|
|
113
|
-
`eval()` + `no_grad()` inference, no training on a non-train split
|
|
127
|
+
`eval()` + `no_grad()` inference, no training on a non-train split, and (fine-tuning) a
|
|
128
|
+
recorded pretrained-weight provenance when pretrained weights are loaded
|
|
129
|
+
(`PRETRAINED_PROVENANCE_MISSING`).
|
|
114
130
|
- `scripts/scaffold_challenge/verify.sh` — the build → validate chain, network-free (torch tier
|
|
115
131
|
self-skips).
|
|
116
132
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Fine-tuning guide (model-scaffold — `--task finetune`)
|
|
2
|
+
|
|
3
|
+
Load-on-demand notes for the target workflow of a clinician-researcher: **fine-tune an
|
|
4
|
+
existing pretrained model on collected clinical data**, rather than train from scratch or
|
|
5
|
+
design a new architecture. `scaffold.py --task finetune` emits a leakage-safe transfer-learning
|
|
6
|
+
repo (frozen→unfrozen schedule, discriminative learning rates, a `PRETRAINED.md` provenance
|
|
7
|
+
record); this guide covers the decisions it deliberately leaves to you.
|
|
8
|
+
|
|
9
|
+
## When to fine-tune (vs train from scratch)
|
|
10
|
+
Fine-tuning a pretrained backbone is the right default whenever the labelled clinical set is
|
|
11
|
+
small (hundreds–low-thousands of patients) — the regime almost every solo clinical study is
|
|
12
|
+
in. From-scratch training needs far more data to beat a fine-tuned ImageNet/medical backbone.
|
|
13
|
+
Pick the backbone in `/architecture-zoo`; adapt it here.
|
|
14
|
+
|
|
15
|
+
## The provenance record is load-bearing — `PRETRAINED.md`
|
|
16
|
+
A fine-tune is only reproducible if the **exact** pretrained weights are recorded. `--task
|
|
17
|
+
finetune` emits `PRETRAINED.md` with `[VERIFY]` fields; fill them before publishing:
|
|
18
|
+
- **Source** — the exact model + weights tag (`timm:resnet50.a1_in1k`, `MedSAM`, a URL/DOI),
|
|
19
|
+
set via `--from-pretrained`.
|
|
20
|
+
- **Pretraining data** — the dataset the backbone was pretrained on. **Confirm it does not
|
|
21
|
+
overlap this study's test set.** A backbone pretrained on (or including) your evaluation
|
|
22
|
+
images is *pretraining-set contamination*: leakage that no train/val/test split table can
|
|
23
|
+
see, because it entered through the weights, not the split. This is the fine-tuning analogue
|
|
24
|
+
of benchmark contamination in LLM evaluation (`/mllm-eval`).
|
|
25
|
+
- **License**, **checkpoint hash** (sha256), **access date** — for auditability.
|
|
26
|
+
|
|
27
|
+
`check_training_hygiene.py` fires `PRETRAINED_PROVENANCE_MISSING` (Minor) when a training
|
|
28
|
+
script loads pretrained weights (`pretrained=True` / `from_pretrained`) but the repo carries
|
|
29
|
+
no `PRETRAINED.md` and no `pretrained:` block in `config.yaml`. The scaffold passes by
|
|
30
|
+
construction; a hand-rolled repo (a copied Kaggle notebook that does
|
|
31
|
+
`timm.create_model(..., pretrained=True)` and records nothing) fails.
|
|
32
|
+
|
|
33
|
+
## The frozen→unfrozen schedule
|
|
34
|
+
The emitted `train.py` implements the standard two-phase transfer schedule:
|
|
35
|
+
1. **Freeze the backbone, warm up the fresh head** for a few epochs (`FREEZE_EPOCHS`). The
|
|
36
|
+
randomly-initialised head would otherwise back-propagate large gradients that damage the
|
|
37
|
+
pretrained features.
|
|
38
|
+
2. **Unfreeze with discriminative learning rates** — a small learning rate for the pretrained
|
|
39
|
+
backbone (`BACKBONE_LR`, e.g. 1e-5) and a larger one for the head (`HEAD_LR`, e.g. 1e-3).
|
|
40
|
+
The backbone should *adapt*, not be overwritten.
|
|
41
|
+
|
|
42
|
+
Tune the two rates and `FREEZE_EPOCHS` per task. For very small datasets, keep more of the
|
|
43
|
+
backbone frozen (train only the last block + head) and lean on regularisation (weight decay,
|
|
44
|
+
dropout, strong but physiology-preserving augmentation, early stopping on the **val** split).
|
|
45
|
+
|
|
46
|
+
## BatchNorm and small clinical batches
|
|
47
|
+
Fine-tuning with small batches destabilises BatchNorm running statistics. Options: keep the
|
|
48
|
+
backbone's BN layers in `eval()` (frozen running stats) while the backbone is frozen; switch
|
|
49
|
+
to GroupNorm; or use a larger effective batch (gradient accumulation). Record the choice in
|
|
50
|
+
Methods — it materially affects reproducibility.
|
|
51
|
+
|
|
52
|
+
## MedSAM / SAM adaptation
|
|
53
|
+
Promptable foundation segmenters (SAM, **MedSAM**) are adapted, not retrained. The common,
|
|
54
|
+
solo-doable path is **adapter / decoder fine-tuning**: freeze the heavy image encoder and
|
|
55
|
+
fine-tune only the mask decoder (and optionally a lightweight adapter or the prompt encoder)
|
|
56
|
+
on your labelled masks. Integrate the upstream implementation
|
|
57
|
+
([MedSAM](https://github.com/bowang-lab/MedSAM),
|
|
58
|
+
[SAM](https://github.com/facebookresearch/segment-anything)) — do not reimplement it. Keep the
|
|
59
|
+
scaffold's split-reading contract (`splits/split_assignment.csv`) so the patient-level split
|
|
60
|
+
is preserved, and record the SAM/MedSAM checkpoint in `PRETRAINED.md`. Prompt design (points /
|
|
61
|
+
boxes / automatic) is part of the method — report it, and report whether prompts used any
|
|
62
|
+
ground-truth information at test time (a leakage trap unique to promptable models).
|
|
63
|
+
|
|
64
|
+
## Diffusion augmentation — train split only
|
|
65
|
+
A diffusion model can synthesise extra training images (an off-the-shelf augmentation, **not**
|
|
66
|
+
a novel method here). Two hard rules keep it leakage-safe:
|
|
67
|
+
1. **Any generative model used for augmentation must be trained on the TRAIN split only.** If
|
|
68
|
+
the diffusion (or GAN) model saw val/test images, its samples leak that distribution into
|
|
69
|
+
training — the generative analogue of fitting a normaliser on full data
|
|
70
|
+
(`/preprocess-imaging` `NORMALIZATION_LEAKAGE`).
|
|
71
|
+
2. **Synthetic images augment TRAIN only, never val/test.** Evaluating on — or augmenting —
|
|
72
|
+
the held-out split with synthetic data invalidates the metric. `check_preprocessing_leakage`
|
|
73
|
+
flags `AUGMENTATION_ON_EVAL`; declare synthetic augmentation in the preprocessing manifest
|
|
74
|
+
as `applies_to: ["train"]`.
|
|
75
|
+
Report the synthetic:real ratio and show the result holds without synthetic data (a sensitivity
|
|
76
|
+
analysis) — reviewers discount models propped up by synthetic training data.
|
|
77
|
+
|
|
78
|
+
## Reporting
|
|
79
|
+
Fill `methods_stub.md` and `PRETRAINED.md`, then hand off to `/write-paper` +
|
|
80
|
+
`/check-reporting`. Fine-tuning specifics reviewers expect: the pretrained source + its
|
|
81
|
+
pretraining data (contamination check), the freeze/unfreeze schedule and learning rates,
|
|
82
|
+
and — for SAM/MedSAM — the prompt protocol. Report held-out metrics as **mean ± SD over ≥ 3
|
|
83
|
+
seeds** (`/model-evaluation` → `/analyze-stats`); fine-tuning is seed-sensitive on small data.
|
|
84
|
+
|
|
85
|
+
## Hand-offs
|
|
86
|
+
- Backbone / architecture choice (incl. SAM/MedSAM, diffusion) → `/architecture-zoo`.
|
|
87
|
+
- Data-stage leakage (normalisation fit, augmentation-on-eval, slice crossing) →
|
|
88
|
+
`/preprocess-imaging` (`check_preprocessing_leakage`).
|
|
89
|
+
- Split / validation-design audit → `/model-validation` (`check_split_leakage.py`).
|
|
90
|
+
- Held-out metrics + CIs → `/model-evaluation` → `/analyze-stats`.
|
|
91
|
+
- Provenance/model documentation → `/model-card` (Model Card + Datasheet).
|
|
@@ -27,6 +27,14 @@ CHECKS (verdicts):
|
|
|
27
27
|
5. EVAL_SHUFFLE (Minor) an evaluation DataLoader uses shuffle=True
|
|
28
28
|
(reorders the test set; harmless for metrics but
|
|
29
29
|
a smell, and breaks index-aligned outputs).
|
|
30
|
+
6. PRETRAINED_PROVENANCE_MISSING (Minor) the training script loads PRETRAINED weights
|
|
31
|
+
(a `pretrained=True` kwarg or a `from_pretrained`
|
|
32
|
+
call — fine-tuning / transfer learning) but the repo
|
|
33
|
+
records no pretrained-weight provenance (no non-empty
|
|
34
|
+
PRETRAINED.md and no `pretrained:` block in
|
|
35
|
+
config.yaml). A fine-tune whose starting checkpoint is
|
|
36
|
+
unrecorded is not reproducible. Fires only in --repo
|
|
37
|
+
mode (the provenance record is a repo-level artifact).
|
|
30
38
|
|
|
31
39
|
INPUTS
|
|
32
40
|
--repo a scaffolded repo directory; train.py and evaluate.py are auto-found.
|
|
@@ -84,6 +92,7 @@ def _scan(src: str):
|
|
|
84
92
|
"cudnn_determ": False, # cudnn.deterministic = True
|
|
85
93
|
"dataset_split": {}, # var name -> split literal it was built with
|
|
86
94
|
"loaders": [], # (first_arg_name, shuffle_bool)
|
|
95
|
+
"loads_pretrained": False, # a pretrained=True kwarg or a from_pretrained call
|
|
87
96
|
}
|
|
88
97
|
# dataset var <- Ctor(..., split="X")
|
|
89
98
|
for node in ast.walk(tree):
|
|
@@ -120,6 +129,9 @@ def _scan(src: str):
|
|
|
120
129
|
name = first.id if isinstance(first, ast.Name) else None
|
|
121
130
|
sh = _kw(node, "shuffle")
|
|
122
131
|
facts["loaders"].append((name, _is_true(sh)))
|
|
132
|
+
# pretrained-weight load: `...(pretrained=True)` or a `...from_pretrained(...)` call
|
|
133
|
+
if _is_true(_kw(node, "pretrained")) or tail == "from_pretrained":
|
|
134
|
+
facts["loads_pretrained"] = True
|
|
123
135
|
# cudnn.deterministic = True (assignment to an Attribute target)
|
|
124
136
|
if isinstance(node, ast.Assign):
|
|
125
137
|
for tgt in node.targets:
|
|
@@ -129,7 +141,21 @@ def _scan(src: str):
|
|
|
129
141
|
return facts
|
|
130
142
|
|
|
131
143
|
|
|
132
|
-
def
|
|
144
|
+
def _has_pretrained_provenance(repo: Path) -> bool:
|
|
145
|
+
"""True if the repo records pretrained-weight provenance: a non-empty PRETRAINED.md, or
|
|
146
|
+
a `pretrained:` block in config.yaml."""
|
|
147
|
+
pm = repo / "PRETRAINED.md"
|
|
148
|
+
if pm.is_file() and pm.read_text(encoding="utf-8").strip():
|
|
149
|
+
return True
|
|
150
|
+
cfg = repo / "config.yaml"
|
|
151
|
+
if cfg.is_file():
|
|
152
|
+
for line in cfg.read_text(encoding="utf-8").splitlines():
|
|
153
|
+
if line.strip().startswith("pretrained:"):
|
|
154
|
+
return True
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def analyze(train: str | None, eval_: str | None, repo: str | None = None) -> dict:
|
|
133
159
|
claims = []
|
|
134
160
|
tfacts = _scan(Path(train).read_text(encoding="utf-8")) if train else None
|
|
135
161
|
efacts = _scan(Path(eval_).read_text(encoding="utf-8")) if eval_ else None
|
|
@@ -160,6 +186,16 @@ def analyze(train: str | None, eval_: str | None) -> dict:
|
|
|
160
186
|
f"'{name}' constructed with split=\"{sp}\" — training on the {sp} split",
|
|
161
187
|
"where": Path(train).name,
|
|
162
188
|
})
|
|
189
|
+
# fine-tuning: pretrained weights loaded but no provenance recorded (repo mode only)
|
|
190
|
+
if tfacts["loads_pretrained"] and repo and not _has_pretrained_provenance(Path(repo)):
|
|
191
|
+
claims.append({
|
|
192
|
+
"verdict": "PRETRAINED_PROVENANCE_MISSING", "severity": "Minor",
|
|
193
|
+
"detail": "the training script loads pretrained weights (fine-tuning) but the "
|
|
194
|
+
"repo records no pretrained-weight provenance (a non-empty PRETRAINED.md "
|
|
195
|
+
"or a 'pretrained:' block in config.yaml). Record the exact "
|
|
196
|
+
"source / checkpoint / license / hash so the fine-tune is reproducible.",
|
|
197
|
+
"where": Path(train).name,
|
|
198
|
+
})
|
|
163
199
|
|
|
164
200
|
if efacts is not None:
|
|
165
201
|
if not (efacts["has_eval"] and efacts["has_no_grad"]):
|
|
@@ -229,7 +265,7 @@ def main() -> int:
|
|
|
229
265
|
args = ap.parse_args()
|
|
230
266
|
|
|
231
267
|
train, eval_ = _resolve(args.repo, args.train, args.eval_)
|
|
232
|
-
result = analyze(train, eval_)
|
|
268
|
+
result = analyze(train, eval_, repo=args.repo)
|
|
233
269
|
|
|
234
270
|
if not args.quiet:
|
|
235
271
|
print("=" * 41)
|