Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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 model-scaffold builds the training repo. Emits a declarative preprocessing manifest and a deterministic data-stage leakage gate that catches the leaks a split table cannot see: a dataset-level normaliser fit on non-train data, any data-fitted transform run before the split, and the same patient's sli
.claude/skills/aperivue-preprocess-imaging/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 87% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 59% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 46% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 25% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 26% | 0% |
This skill designs and audits the data-preparation stage of a medical-imaging model — the stage before a training repo is built — and proves it is leakage-safe by construction. Data leakage enters one step earlier than the split table can see: a normaliser fit on the whole dataset, a data-fitted transform run before the split exists, or a patient whose slices land in more than one partition. Each silently inflates every downstream metric (Kapoor & Narayanan, Patterns 2023; Varoquaux & Cheplygina, npj Digit Med 2022; CLAIM 2024 data items).
It is the missing first link in the lane: preprocess-imaging (prepare + audit) → /model-scaffold (build) → /model-validation (validate the split) → /model-evaluation + /analyze-stats (metrics) → /write-paper + /check-reporting (publish). It integrates MONAI / TorchIO transforms (referenced in the emitted plan); it does not reimplement them, and it never executes preprocessing on real patient data.
leakage-safe preprocessing plan + a machine-checkable manifest before scaffolding a model.
/model-validation (split-leakage gate)./model-scaffold (it consumes this manifest)./architecture-zoo./model-evaluation then /analyze-stats.Collect: modality (CT / MR / X-ray / US / path), the data manifest (one row per image/slice with a patient_id), the intended resample spacing, the intensity transform (fixed HU window vs a fitted z-score / min-max / histogram match), and the augmentation plan. See references/preprocessing_guide.md for modality-aware guidance (what normalisation is standard per modality, which augmentations preserve vs break physiology).
distinction, so the fit spans partitions.
image's own statistics and is leakage-free even before the split.
into the reported metric.
Write a declarative JSON manifest that model-scaffold consumes and the gate checks:
json{ "split_seed": 42, "transforms": [ {"name": "hu_window", "type": "clip", "fit_scope": "none", "stage": "before_split"}, {"name": "train_zscore", "type": "standardize", "fit_scope": "train", "stage": "after_split"}, {"name": "flip_rotate", "type": "augmentation", "stage": "after_split", "applies_to": ["train"]} ], "split_assignment": [ {"patient_id": "P001", "unit_id": "P001_s1", "split": "train"} ] }
fit_scope: train (OK) · all/full/dataset/test (leak) · sample/per_image/none/fixed (not data-fitted, leakage-free). stage: before_split / after_split.
Declare the fit scope of resampling too. A target spacing you chose in advance is fixed and never leaks (fit_scope: fixed). A target derived from the cohort does: nnU-Net sets its target spacing from a percentile of the dataset fingerprint, so a resample fitted over every case carries held-out geometry into the training grid exactly as an intensity statistic would. Which one you have is decided by the fingerprint's scope, not by the word "resample".
bashpython3 scripts/check_preprocessing_leakage.py --manifest preprocessing_manifest.json --strict
That gate asks whether a transform was fit on the right scope. Before an inference run on a cohort the model was not trained on, ask the other question — is that cohort in the intensity domain the trained normaliser assumes?
bashpython3 scripts/check_normalizer_domain.py \ --profile eda/<cohort>_profile.json \ --contract work/nnUNet_results/.../plans.json \ --splits external_mri --out qc/normalizer_domain.json --strict
Verdicts: PREPROCESS_BEFORE_SPLIT, NORMALIZATION_LEAKAGE, PATIENT_CROSS_SPLIT (Major); AUGMENTATION_ON_EVAL, UNSPECIFIED_FIT_SCOPE, MISSING_SEED (Minor). The verdict is reproduced by set arithmetic + rule on the manifest, never asserted from prose. A green gate is a precondition for handing the manifest to /model-scaffold.
/model-scaffold — the audited manifest is the scaffold's preprocessing input; itssplit_assignment is the same patient-level split /model-validation later re-verifies.
/self-review model_development probe audits data-stage leakage in a finished manuscript;this skill produces the leakage-safe pipeline it looks for.
/check-reporting — the manifest documents the CLAIM 2024 / TRIPOD+AI data-preprocessing items.manifest comes from the real data manifest and the researcher's declared pipeline — never invented. This skill designs and audits the plan; it does not run preprocessing on real patient data or synthesise the images it describes.
check_preprocessing_leakage.py. Theleakage verdict is reproduced deterministically (rule + set arithmetic on the manifest), never asserted from prose.
type / fit_scope / stage must describe what the code actually does; a mislabelled transform hides a real leak the gate would otherwise catch.
normalisation/resampling implementation or claim results for one.
scripts/check_normalizer_domain_challenge/ ships a synthetic profile/contract triple: a cohort in the contract's own domain that must come back clean (the false-positive guard), an arbitrary-unit cohort that must raise a Major, and an unreadable contract that must refuse rather than pass.
scripts/check_preprocessing_leakage_challenge/ ships a synthetic leak/clean manifest pair with a network-free verify.sh wired into the skill's validation commands.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 19,886 | 22,096 | +11% | 1 | 1 | 0% | 3,881 | 5,424 | +40% | 0 | 0 | — |
case-02 | fail→fail | 28,413 | 4,878 | -83% | 1 | 1 | 0% | 5,395 | 2,258 | -58% | 0 | 0 | — |
case-03 | fail→fail | 19,979 | 5,418 | -73% | 1 | 1 | 0% | 3,912 | 2,169 | -45% | 0 | 0 | — |
case-04 | fail→fail | 16,889 | 18,463 | +9% | 1 | 1 | 0% | 3,479 | 5,327 | +53% | 0 | 0 | — |
case-05 | fail→fail | 42,353 | 20,687 | -51% | 1 | 1 | 0% | 1,764 | 5,632 | +219% | 0 | 0 | — |
case-06 | pass→pass | 18,064 | 5,007 | -72% | 1 | 1 | 0% | 3,513 | 2,644 | -25% | 0 | 0 | — |
case-07 | fail→pass | 23,053 | 8,153 | -65% | 1 | 1 | 0% | 1,824 | 3,418 | +87% | 0 | 0 | — |
case-08 | fail→pass | 12,896 | 7,560 | -41% | 1 | 1 | 0% | 1,962 | 3,129 | +59% | 0 | 0 | — |
case-09 | fail→pass | 13,633 | 8,660 | -36% | 1 | 1 | 0% | 2,140 | 3,124 | +46% | 0 | 0 | — |
case-10 | pass→pass | 9,940 | 10,044 | +1% | 1 | 1 | 0% | 1,663 | 3,587 | +116% | 0 | 0 | — |
case-11 | pass→pass | 10,744 | 7,271 | -32% | 1 | 1 | 0% | 1,750 | 2,997 | +71% | 0 | 0 | — |
case-12 | fail→pass | 23,766 | 2,751 | -88% | 1 | 1 | 0% | 1,862 | 2,322 | +25% | 0 | 0 | — |
case-13 | fail→pass | 22,226 | 4,802 | -78% | 1 | 1 | 0% | 2,133 | 2,691 | +26% | 0 | 0 | — |
case-14 | fail→pass | 12,976 | 10,296 | -21% | 1 | 1 | 0% | 1,933 | 3,580 | +85% | 0 | 0 | — |
case-15 | pass→pass | 13,044 | 8,153 | -37% | 1 | 1 | 0% | 1,967 | 3,192 | +62% | 0 | 0 | — |
case-16 | pass→pass | 15,360 | 9,960 | -35% | 1 | 1 | 0% | 2,521 | 3,440 | +36% | 0 | 0 | — |
case-17 | fail→pass | 12,089 | 3,696 | -69% | 1 | 1 | 0% | 1,898 | 2,404 | +27% | 0 | 0 | — |
case-18 | pass→pass | 6,039 | 6,972 | +15% | 1 | 1 | 0% | 918 | 2,762 | +201% | 0 | 0 | — |
case-19 | fail→pass | 9,788 | 3,742 | -62% | 1 | 1 | 0% | 1,624 | 2,450 | +51% | 0 | 0 | — |
case-20 | fail→pass | 34,996 | 6,043 | -83% | 1 | 1 | 0% | 2,940 | 3,010 | +2% | 0 | 0 | — |
case-21 | pass→pass | 7,950 | 3,203 | -60% | 1 | 1 | 0% | 1,378 | 2,434 | +77% | 0 | 0 | — |
case-22 | fail→pass | 18,933 | 2,283 | -88% | 1 | 1 | 0% | 1,264 | 2,252 | +78% | 0 | 0 | — |
case-23 | fail→pass | 15,688 | 4,918 | -69% | 1 | 1 | 0% | 1,030 | 2,687 | +161% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 17 counted toward the lift figure. The other 6 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +48 percentage points is the difference between those two pass rates over the 17 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.