Rules and statuses
When you compare a source port with a target port, the comparison rules from each profile run against the two port contracts. Each rule produces a finding, and the findings combine into one status. This page lists the operators rules can use, what each status means, and what a finding looks like.
Rules are data, not code. A rule names a field in each contract using a JSON Pointer path, such as /contract/measurement/unit, and picks one operator from the list below. It can’t contain JavaScript, Python, templates or other expressions, so loading a profile never runs code. Field values are checked against JSON Schema (Draft 2020-12) first.
Here is a rule from the gene expression counts profile:
{
"source": "/contract/biological_context/species",
"target": "/contract/biological_context/species",
"operator": "context-compatible",
"missing": "unknown",
"reason_code": "BMCS_VALUE_MISMATCH",
"severity": "error"
}It reads the species from both contracts and compares them. If either side leaves the species out, the result is UNKNOWN. The missing field can also be conditional, incompatible or ignore.
Operators
| Operator | Passes when |
|---|---|
equal | Both values are the same |
not-equal | The values differ |
in | The source value is one of the target’s listed values |
not-in | The source value isn’t in the target’s list |
subset | Every item in the source list is in the target list |
superset | The source list contains every item in the target list |
range | The source range (minimum to maximum) sits inside the target range |
pattern | The value matches a pattern |
same-dimension | Both quantities have the same physical dimension, for example both are concentrations |
labels-equal | Both label lists are identical and in the same order |
labels-permutation | Both lists have the same labels in a different order, so a reorder can connect them |
unit-convertible | The units are the same, or the release’s unit table has a conversion between them (currently nM, µM and mM) |
term-equivalent | Two ontology terms mean the same thing |
term-subsumes | One ontology term includes the other, for example a broader cell type |
mapping-total | Every source identifier maps to a target identifier |
mapping-bijective | Identifiers map one-to-one in both directions |
context-compatible | The contexts match, or the target accepts any context (any, unspecified or null) |
digest-equal | Two sha256 hashes match |
Version 0.1.0-alpha.5 implements every operator above in both Python and TypeScript. Ontology and identifier-mapping rules need an exact, sha256-pinned snapshot when equality alone is not enough. If a needed snapshot is missing or invalid, the result is UNKNOWN with a stable reason code. Reports and plans record the snapshots they used.
Pattern checks are limited in length and reject unsafe forms. This keeps profile rules useful without letting a profile run arbitrary or expensive code.
For maintainers
A new profile that only uses existing operators needs a new data release and nothing else. A new operator needs code and conformance tests in both the Python and TypeScript implementations.
Order of checks
The specification groups checks from structure to policy:
- Port direction and name
- Whether the port carries a state or an event, and when data is produced and used
- Signal type, data type, shape and schema
- Dimensions, axes and feature order
- Units, scale, normalization and endpoint
- Biological meaning
- Identifier namespace and mappings
- Biological and experimental context
- Time context
- Origin, provenance, uncertainty and missing values
- File format
- Security, licensing, where data may be stored, and workspace policy
In this release, the reference implementations run each profile’s rules in the order the profile lists them.
Statuses
| Status | Meaning | Default policy decision |
|---|---|---|
EXACT | The two contracts are identical (same sha256) | ALLOW |
DIRECT_COMPATIBLE | The source satisfies the target as it is, with no conversion | ALLOW |
LOSSLESS_CONVERSION_AVAILABLE | A conversion that loses no information can connect them, such as nM to µM | ALLOW |
LOSSY_CONVERSION_REQUIRES_APPROVAL | A conversion exists, but it may lose information | APPROVAL_REQUIRED |
INFERENCE_MODEL_REQUIRED | The target needs data the source doesn’t have, so a model must estimate it | APPROVAL_REQUIRED |
CONDITIONAL | Compatibility depends on a condition that hasn’t been checked | APPROVAL_REQUIRED |
INCOMPATIBLE | At least one field contradicts the target, for example mouse data sent to a human-only input | BLOCK |
UNKNOWN | Not enough information to decide, usually because a required field is missing | BLOCK |
When you build a plan, a policy can change the decision for UNKNOWN, CONDITIONAL, and the conversion and inference statuses.
How findings combine:
- If any rule finds a contradiction, the status is
INCOMPATIBLE, even if other fields are missing. - Otherwise, if any rule lacks the information it needs, the status is
UNKNOWN. - If either port has no contract at all, the status is
UNKNOWNwith reason codeBMCS_CONTRACT_NOT_DECLARED.
Findings
Every finding has:
dimension: the part of the contract that was checked, such asbiological_contextstate: the result of this ruleseverity:error,warningorinforeason_code: a stableBMCS_*code that you can match on in codeexplanation: a short message for people
A finding can also include evidence (the two values that were compared), source_path, target_path and remediation.
Here the source outputs mouse data and the target expects human data. Both ports use the gene expression counts profile:
{
"dimension": "biological_context",
"state": "INCOMPATIBLE",
"severity": "error",
"reason_code": "BMCS_VALUE_MISMATCH",
"explanation": "/contract/biological_context/species: 'context-compatible' check failed.",
"evidence": {
"source": "NCBITaxon:10090",
"target": "NCBITaxon:9606"
}
}If the source leaves out the species instead, the finding is UNKNOWN:
{
"dimension": "biological_context",
"state": "UNKNOWN",
"severity": "info",
"reason_code": "BMCS_REQUIRED_EVIDENCE_MISSING",
"explanation": "/contract/biological_context/species is missing from the source or target contract."
}Every reason code and its meaning is listed in reason-codes.json.