Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions dataset-split-release-guard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Dataset Split Release Guard

This contribution adds a focused release guard for train/validation/test split manifests in SCIBASE's Scientific/Engineering Data & Code Hosting layer. It checks whether hosted dataset split artifacts are safe before DOI publication, API release, public previews, or reproducibility badges.

The slice is intentionally narrow. It does not rebuild broad FAIR manifests, artifact package integrity, schema evolution, data dictionaries, malware quarantine, sandbox egress, notebook rerun determinism, spreadsheet formula provenance, accessibility previews, SBOM checks, or general license metadata. It covers the release boundary for split artifacts.

## What It Checks

- Required train, validation, and test split manifests.
- Dataset record count parity with split record totals.
- Record identifier overlap across splits.
- Group-level leakage across participant, patient, subject, lab, or other grouping identifiers.
- Deterministic seed and split-script hash provenance.
- Per-split checksum and manifest-hash coverage.
- License and access-state parity across split artifacts.
- Class or stratum balance drift beyond release policy.
- Embargoed records present in public split manifests.
- Public DOI/API release left enabled while split-integrity findings are unresolved.

## Running Locally

```bash
npm test
npm run demo
npm run check
npm run video
```

The demo uses only synthetic split release packets in `data/sample_split_release_packets.json`.

Generated files:

- `reports/summary.json`
- `reports/reviewer-packet.md`
- `reports/summary.svg`
- `reports/demo.mp4`

The MP4 is generated from an FFmpeg color source and drawtext slate. It is not a screen recording and contains no desktop capture or private information.

## Why This Matters

Data/code hosting is not only about storing files. A hosted dataset often becomes the basis for reproduced results, model comparisons, public APIs, and DOI-backed artifacts. If train, validation, and test manifests leak records or participant groups across boundaries, downstream analyses can look reproducible while being contaminated.

This guard gives SCIBASE a deterministic packet to hold risky releases, regenerate split manifests, preserve checksum evidence, and keep public releases frozen until split artifacts are safe.
214 changes: 214 additions & 0 deletions dataset-split-release-guard/data/sample_split_release_packets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
[
{
"id": "split-release-001",
"title": "Clean imaging dataset split package for DOI release",
"dataset": {
"recordCount": 9,
"expectedClassBalance": { "case": 0.33, "control": 0.67 }
},
"splits": {
"train": {
"recordCount": 5,
"recordIds": ["r1", "r2", "r3", "r4", "r5"],
"groupIds": ["p1", "p2", "p3", "p4", "p5"],
"classBalance": { "case": 0.4, "control": 0.6 },
"license": "CC-BY-4.0",
"access": "public",
"checksum": "sha256:train",
"manifestHash": "sha256:manifest-train",
"embargoedRecordIds": []
},
"validation": {
"recordCount": 2,
"recordIds": ["r6", "r7"],
"groupIds": ["p6", "p7"],
"classBalance": { "case": 0.5, "control": 0.5 },
"license": "CC-BY-4.0",
"access": "public",
"checksum": "sha256:validation",
"manifestHash": "sha256:manifest-validation",
"embargoedRecordIds": []
},
"test": {
"recordCount": 2,
"recordIds": ["r8", "r9"],
"groupIds": ["p8", "p9"],
"classBalance": { "case": 0.5, "control": 0.5 },
"license": "CC-BY-4.0",
"access": "public",
"checksum": "sha256:test",
"manifestHash": "sha256:manifest-test",
"embargoedRecordIds": []
}
},
"provenance": {
"seedLocked": true,
"splitScriptHashPresent": true
},
"release": {
"publicDoiRelease": true,
"freezePublicRelease": false
},
"policy": {
"requireGroupDisjointness": true,
"maxClassBalanceDelta": 0.2
}
},
{
"id": "split-hold-002",
"title": "Clinical split package with patient leakage and embargoed rows",
"dataset": {
"recordCount": 8,
"expectedClassBalance": { "case": 0.5, "control": 0.5 }
},
"splits": {
"train": {
"recordCount": 4,
"recordIds": ["c1", "c2", "c3", "c4"],
"groupIds": ["patient-1", "patient-2", "patient-3", "patient-4"],
"classBalance": { "case": 0.75, "control": 0.25 },
"license": "restricted-clinical",
"access": "private",
"checksum": "sha256:train",
"manifestHash": "sha256:manifest-train",
"embargoedRecordIds": []
},
"validation": {
"recordCount": 2,
"recordIds": ["c4", "c5"],
"groupIds": ["patient-4", "patient-5"],
"classBalance": { "case": 1,
"control": 0 },
"license": "restricted-clinical",
"access": "public",
"checksum": "",
"manifestHash": "",
"embargoedRecordIds": ["c5"]
},
"test": {
"recordCount": 2,
"recordIds": ["c6", "c7"],
"groupIds": ["patient-6", "patient-7"],
"classBalance": { "case": 0,
"control": 1 },
"license": "restricted-clinical",
"access": "private",
"checksum": "sha256:test",
"manifestHash": "sha256:manifest-test",
"embargoedRecordIds": []
}
},
"provenance": {
"seedLocked": false,
"splitScriptHashPresent": false
},
"release": {
"publicDoiRelease": true,
"freezePublicRelease": false
},
"policy": {
"requireGroupDisjointness": true,
"maxClassBalanceDelta": 0.15
}
},
{
"id": "split-review-003",
"title": "Good disjointness with missing provenance and balance drift",
"dataset": {
"recordCount": 6,
"expectedClassBalance": { "positive": 0.5, "negative": 0.5 }
},
"splits": {
"train": {
"recordCount": 3,
"recordIds": ["a1", "a2", "a3"],
"groupIds": ["g1", "g2", "g3"],
"classBalance": { "positive": 0.9, "negative": 0.1 },
"license": "CC0-1.0",
"access": "public",
"checksum": "sha256:train",
"manifestHash": "sha256:manifest-train",
"embargoedRecordIds": []
},
"validation": {
"recordCount": 1,
"recordIds": ["a4"],
"groupIds": ["g4"],
"classBalance": { "positive": 0,
"negative": 1 },
"license": "CC0-1.0",
"access": "public",
"checksum": "sha256:validation",
"manifestHash": "sha256:manifest-validation",
"embargoedRecordIds": []
},
"test": {
"recordCount": 2,
"recordIds": ["a5", "a6"],
"groupIds": ["g5", "g6"],
"classBalance": { "positive": 0.5, "negative": 0.5 },
"license": "CC0-1.0",
"access": "public",
"checksum": "sha256:test",
"manifestHash": "sha256:manifest-test",
"embargoedRecordIds": []
}
},
"provenance": {
"seedLocked": true,
"splitScriptHashPresent": false
},
"release": {
"publicDoiRelease": false,
"freezePublicRelease": true
},
"policy": {
"requireGroupDisjointness": true,
"maxClassBalanceDelta": 0.25
}
},
{
"id": "split-hold-004",
"title": "Missing test split with public release still enabled",
"dataset": {
"recordCount": 5,
"expectedClassBalance": { "included": 1 }
},
"splits": {
"train": {
"recordCount": 3,
"recordIds": ["m1", "m2", "m3"],
"groupIds": ["mg1", "mg2", "mg3"],
"classBalance": { "included": 1 },
"license": "CC-BY-4.0",
"access": "public",
"checksum": "sha256:train",
"manifestHash": "sha256:manifest-train",
"embargoedRecordIds": []
},
"validation": {
"recordCount": 2,
"recordIds": ["m4", "m5"],
"groupIds": ["mg4", "mg5"],
"classBalance": { "included": 1 },
"license": "CC-BY-4.0",
"access": "public",
"checksum": "sha256:validation",
"manifestHash": "sha256:manifest-validation",
"embargoedRecordIds": []
}
},
"provenance": {
"seedLocked": true,
"splitScriptHashPresent": true
},
"release": {
"publicDoiRelease": true,
"freezePublicRelease": false
},
"policy": {
"requireGroupDisjointness": true,
"maxClassBalanceDelta": 0.15
}
}
]
13 changes: 13 additions & 0 deletions dataset-split-release-guard/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "dataset-split-release-guard",
"version": "1.0.0",
"description": "Dependency-free release guard for hosted train/validation/test split manifests.",
"main": "src/index.js",
"scripts": {
"test": "node --test",
"demo": "node scripts/demo.js",
"video": "node scripts/render-demo-video.js",
"check": "node --check src/index.js && node --check scripts/demo.js && node --check scripts/render-demo-video.js"
},
"license": "MIT"
}
Binary file added dataset-split-release-guard/reports/demo.mp4
Binary file not shown.
64 changes: 64 additions & 0 deletions dataset-split-release-guard/reports/reviewer-packet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Dataset Split Release Guard Report

Generated: 2026-08-15T22:12:47.311Z
Packets analyzed: 4
Decision counts: RELEASE 1, REVIEW_RELEASE 1, HOLD_RELEASE 2

## Findings

### split-release-001: Clean imaging dataset split package for DOI release

Decision: RELEASE
Splits: train, validation, test

- No split release risk detected.

Recommended actions:
- Release split manifests with normal artifact provenance.

### split-hold-002: Clinical split package with patient leakage and embargoed rows

Decision: HOLD_RELEASE
Splits: train, validation, test

- CRITICAL TRAIN_VALIDATION_TEST_RECORD_OVERLAP: One or more records appear in multiple splits.
- CRITICAL GROUP_LEAKAGE_ACROSS_SPLITS: A participant, patient, subject, lab, or other grouping identifier appears across multiple splits.
- MAJOR SPLIT_PROVENANCE_INCOMPLETE: The split generation seed or script hash is missing.
- MAJOR SPLIT_CHECKSUM_COVERAGE_MISSING: One or more split manifests lack checksum or manifest hash evidence.
- MAJOR SPLIT_LICENSE_ACCESS_PARITY_MISMATCH: Split manifests have inconsistent license or access states.
- MAJOR STRATIFICATION_BALANCE_DRIFT: Class or stratum balance differs from the dataset policy beyond the allowed threshold.
- CRITICAL EMBARGOED_RECORD_IN_PUBLIC_SPLIT: Embargoed records are present in one or more release split manifests.
- CRITICAL PUBLIC_RELEASE_NOT_FROZEN_FOR_SPLIT_RISK: Public DOI/API release is enabled while split-integrity findings remain unresolved.

Recommended actions:
- Freeze public DOI/API release and reproducibility badges.
- Attach findings to the dataset release review packet.
- Regenerate split manifests or document curator-approved exceptions.
- Re-run checksum, license, access, and stratification checks before DOI/API release.

### split-review-003: Good disjointness with missing provenance and balance drift

Decision: REVIEW_RELEASE
Splits: train, validation, test

- MAJOR SPLIT_PROVENANCE_INCOMPLETE: The split generation seed or script hash is missing.
- MAJOR STRATIFICATION_BALANCE_DRIFT: Class or stratum balance differs from the dataset policy beyond the allowed threshold.

Recommended actions:
- Attach findings to the dataset release review packet.
- Regenerate split manifests or document curator-approved exceptions.
- Re-run checksum, license, access, and stratification checks before DOI/API release.

### split-hold-004: Missing test split with public release still enabled

Decision: HOLD_RELEASE
Splits: train, validation

- CRITICAL REQUIRED_SPLIT_MISSING: The release packet lacks one or more required train/validation/test split manifests.
- CRITICAL PUBLIC_RELEASE_NOT_FROZEN_FOR_SPLIT_RISK: Public DOI/API release is enabled while split-integrity findings remain unresolved.

Recommended actions:
- Freeze public DOI/API release and reproducibility badges.
- Attach findings to the dataset release review packet.
- Regenerate split manifests or document curator-approved exceptions.
- Re-run checksum, license, access, and stratification checks before DOI/API release.
Loading