This release broadens the vocabulary of leakage relations splitGraph can model,
hardens the split_spec interchange format into a formally specified contract,
and demonstrates that contract across a language boundary. splitGraph continues
to stop at the constraint / split_spec boundary: generating folds, fitting
models, applying purge/embargo, and producing statistical leakage evidence
remain the responsibility of downstream consumers such as bioLeak.
Sitenode type andsample_collected_at_siteedge. Multi-site / multi-center structure is now a first-class typed relation.graph_from_metadata()auto-detects asite_idcolumn;validate_graph()flags samples assigned to multiple sites (sample_multiple_site_assignments);derive_split_constraints(mode = "site")groups samples by collection site (and rejects ambiguous multi-site assignments); andas_split_spec()carriessite_groupas a blocking annotation insample_data.Sitealso participates inmode = "composite"derivations and the typedplot()layout.Regionnode type andsample_located_in_regionedge. Categorical tissue / anatomical region structure is now a first-class typed relation, mirroringSite:region_idauto-detection, multi-region validation (sample_multiple_region_assignments),derive_split_constraints(mode = "region"), aregion_groupblocking annotation insplit_spec, and composite / plot support.Platformnode type andsample_run_on_platformedge, plusplatformandassayconstraint modes. Sequencing / measurement-platform structure is now a first-class typed relation:graph_from_metadata()auto-detects aplatform_idcolumn,validate_graph()flags samples run on multiple platforms (sample_multiple_platform_assignments), andderive_split_constraints(mode = "platform")groups samples by platform.mode = "assay"reuses the existingsample_measured_by_assayrelation to group by assay / modality. Both carry a blocking annotation insplit_spec(platform_group,assay_group), participate inmode = "composite"(via = c("Subject", "Platform")), and are covered by the typedplot()layout. Theassay_uses_platformedge (Assay->Platform) is also part of the schema for manually encoding which platform an assay runs on.- Pairwise (thresholded) leakage relations:
relatednessandspatialmodes. Some leakage sources are pairwise and continuous rather than clean groups. Two new undirected, thresholded edge types model them —subject_related_to(genetic relatedness between subjects) andsample_adjacent_to(spatial proximity between samples) — together with the edge-building helpersrelatedness_edges_from_kinship(pairs, threshold)andspatial_edges_from_coords(coords, radius).derive_split_constraints(mode = "relatedness")andmode = "spatial"form groups as connected components (transitive closure) over the thresholded edges, so a chain of individually near neighbours still lands in one group — a grouping that column-based approaches structurally cannot express. Both modes honor thesamples=subset (components are recomputed within the subset, so an excluded bridge sample cannot leak structure across the split).
- Formal JSON Schema. The
dependency_graphandsplit_specon-disk formats now have formal JSON Schemas (Draft 2020-12) shipped ininst/schema/, and every written file references its schema via a$schemakey. - JSON validators.
validate_graph_json()andvalidate_split_spec_json()check a handoff file against the contract — required fields, value types, node/edge-type enumerations, and referential integrity of edge endpoints — with no dependency beyondjsonlite. - Schema-version policy and one-shot upgraders.
schema_versionis now"0.2.0", and the compatibility rule is explicit and enforced: the major version is the compatibility boundary, so files sharing the installed major (including all"0.1.0"files) load silently, while a differing major loads with a warning.migrate_dependency_graph_json()andmigrate_split_spec_json()upgrade an older file in place, filling fields introduced since it was written and stamping the current version and$schema. - Provenance.
split_specmetadata now records derivation provenance (splitgraph_version,derived_at) alongside the existingsource_mode/source_strategy/relations_used.
- Python reference consumer. A pure-Python reader (
inst/python/splitspec/) parses thesplit_specJSON and exposes the grouping, ordering, and stratum annotations needed to drive scikit-learnGroupKFold/StratifiedGroupKFold/TimeSeriesSplit(the reader itself needs only the standard library). A conformance script (inst/python/conformance.py) and an accompanying R test assert that the Python reader recovers exactly the grouping (grouping_vector()) andorder_rankthat R emitted; the test is skipped whenpython3is absent and never runs on CRAN.
- Composite-strict subset scoping.
derive_split_constraints(mode = "composite", strategy = "strict", samples = ...)now recomputes connected components within the requested subset. Previously two in-subset samples connected only through an out-of-subset sample could inherit a shared group, silently leaking excluded structure into the split. - Mode-aware leakage summaries.
summarize_leakage_risks()now reports aseveredcolumn indicating whether the chosen constraint mode structurally eliminates each leakage path (TRUE/FALSE), orNAwhen no constraint is supplied. Previously the same risk report was returned regardless of the mode. query_paths()truncation is now visible. When the search hits the finitemax_lengthcap, the result metadata carries atruncated = TRUEflag so suppressed longer paths are no longer silent.- Timestamp round-trips. A missing or unparseable
created_atnow round-trips asNA(POSIXct) instead of falling back to the current time. split_specJSON round-trip fidelity. The newsite_group/region_group/platform_group/assay_groupcolumns are written and read back correctly; earlier development builds dropped them on serialization.
- Removed the unused
leakage_constraint()constructor and itsprint/summary/as.data.framemethods. The object was exported but never produced or consumed anywhere in the package;leakage_risk_summary()(produced bysummarize_leakage_risks()) is the supported leakage-reporting type and is unaffected. - The data-model
schema_versionmoved from"0.1.0"to"0.2.0". This is backward compatible — existing"0.1.0"files load without warning — but the stamped version in newly written files changes.
- New vignette
cross-language-handoff: the full R -> JSON -> Python -> scikit-learn path, showingsplit_specas an interchange format rather than downstream plumbing. - New vignette
modeling-structure: modeling site, platform, assay, relatedness, and spatial structure end to end. - The README gains a "Scope & Relationship to bioLeak" section, and the
?splitGraphpackage doc now states scope and non-goals explicitly. - A contract test (
Suggests: bioLeak, skipped if absent) pins the seam to the reference consumer, asserting that a splitGraphsplit_specsatisfiesbioLeak::as_leaksplits(). - The package ships GitHub Actions workflows (multi-OS
R-CMD-check,test-coverage) and a JOSSpaper.mdframed on the representation and interchange-format contribution. statsandutilsare now declared inImports(both were already used).
- JSON serialization for both core handoff objects:
write_dependency_graph()/read_dependency_graph()andwrite_split_spec()/read_split_spec(). The on-disk format is documented under?write_dependency_graphand?write_split_spec, carries aschema_versionfield, and round-tripsNAvalues faithfully. This makessplitGraphobjects portable across R sessions and across language boundaries (Python, Julia, CLI tools — anything that can read JSON). Requiresjsonlite(added toSuggests); a helpful error is raised if it is not installed. - A new vignette,
adapter-cookbook, walks through three small adapter patterns: a base-R leave-one-group-out adapter (executed), a grouped-CV adapter built onrsample::group_vfold_cv()(illustrative), and an ordered-evaluation adapter built onrsample::rolling_origin()(illustrative). It also shows the JSON cross-language handoff path. validate_graph()andvalidate_depgraph()now accept a documentedvalidation_overridesargument. Currently supported override:allow_multi_subject_samples(defaultFALSE); whenTRUE, samples linked to multiple subjects are not flagged by the semantic validator andderive_split_constraints(mode = "subject")keeps the first listed assignment instead of erroring. The override mechanism is now first-class and merges into any graph-level override for the duration of the call only.derive_split_constraints(mode = "subject")honorsallow_multi_subject_samplesconsistently withvalidate_graph(). When the override is active and ambiguity exists, the choice is recorded inmetadata$warningsso it is not invisible.query_paths()now applies a finite default safety cap onmax_length(8edges) so thatigraph::all_simple_paths()cannot blow up on dense graphs. Passmax_length = Infto opt out and search exhaustively, or any non-negative integer for an explicit cap. Negative values and non-numeric inputs are rejected with a clear error.
build_dependency_graph()returns a more useful error when edge endpoints don't match any node ID and the mismatch looks like a prefix problem (e.g. edges built withfrom_prefix = TRUEbut nodes built withprefix = FALSE). The error now points at the likely cause.graph_from_metadata()warns when it constructsOutcomenodes from a numericoutcome_valuecolumn (which producesoutcome:0/outcome:1nodes that are usually not what the user wants). To silence the warning, passoutcome_id(character class label) instead, or coerceoutcome_valueto character first.- The data-model
schema_versionis now explicitly decoupled from the package version. Bumping the package will not bump the schema; only an explicit, documented schema change should.
These remain functional in 0.2.0 but emit .Deprecated() warnings and are
scheduled for removal in a future release. Use the canonical names instead:
validate_graph(checks = …)→ uselevels = …andseverities = ….build_depgraph()→ usebuild_dependency_graph().validate_depgraph()→ usevalidate_graph().new_depgraph_nodes()→ usegraph_node_set().new_depgraph_edges()→ usegraph_edge_set().new_depgraph()→ usedependency_graph().
- README and the main vignette now use
outcome_id(character) in their quick-start example instead of numericoutcome_value, matching the new warning behavior. - The
validation_overridesparameter and theallow_multi_subject_sampleskey are now documented on?build_dependency_graph/?validate_graph.
Initial public release. Highlights:
- Typed dependency-graph construction from canonical metadata via
graph_from_metadata(), or from explicit node and edge tables viacreate_nodes()/create_edges()/build_dependency_graph(). - Structural, semantic, and leakage-relevant validation
(
validate_graph()), typed query helpers, and projected sample-dependency detection. - Split-constraint derivation (
derive_split_constraints()) forsubject,batch,study,time, andcompositemodes, translated into a stable, tool-agnosticsplit_specviaas_split_spec()with preflight validation and leakage-risk summaries. plot()method fordependency_graphwith a typed, layered layout, per-type node colors, and an auto-generated node-type legend.splitGraphemitssplit_specobjects without runtime dependencies on downstream tooling. Adapters are expected to live in consumer packages (e.g. packages built on top ofrsample) so thatsplitGraphitself stays neutral.
See the README for a full feature overview and a runnable Quick Start.