Summary
Add a validator in ord-schema that flags two common mistakes authors make when defining reaction inputs and returns warnings (not hard errors). Once added to ord-schema, the same validation should be surfaced in ord-app so users see it in the editor.
Mistake 1
- Symptom: Reaction contains multiple inputs, but each input has only a single component.
- Why it’s a problem: This is almost always a misunderstanding of how the schema is meant to represent inputs (multiple inputs usually implies separate additions/units). It is correct for simple reactions where every component is added sequentially as neat solids/liquids, but usually indicates an incomplete/incorrect record.
- Suggested validator behavior: If reaction.inputs.length > 1 and every input.components.length == 1, emit a warning suggesting the user may have intended to list multiple components within a single input or to record separate addition steps.
Mistake 2
- Symptom: The reaction contains a single input with multiple components of type REACTANT, REAGENT, or CATALYST.
- Why it’s a problem: This pattern is widely used for reactions with indeterminate or very complex input addition systems; it’s acceptable but should be discouraged when a complete record of inputs is possible.
- Suggested validator behavior: If reaction.inputs.length == 1 and that input.components contains multiple components where component.type is one of {REACTANT, REAGENT, CATALYST}, emit a warning recommending the user provide a more complete record (separate inputs for distinct additions) where feasible.
Implementation notes / acceptance criteria
- Add a schema-level validator in ord-schema that returns warnings (not fatal errors) with clear messages and examples of preferred structures.
- Include unit tests covering positive and negative examples for both warnings.
- Expose the new validator message codes so ord-app can surface them in the editor UI.
- Update ord-app to display these warnings inline in the editor with guidance and a link to documentation on how to represent input additions correctly.
- Add short example snippets in the validator tests or docs demonstrating correct vs. flagged structures.
Suggested validator messages (examples)
-
Code: input-composition:multiple-inputs-single-component
Text: "Reaction has multiple inputs where each input contains a single component. This often indicates a misunderstanding of input addition semantics — consider grouping components in the same input or recording explicit separate addition steps. (Warning)"
-
Code: input-composition:single-input-multiple-active-components
Text: "Single input contains multiple REACTANT/REAGENT/CATALYST components. Consider recording separate inputs for distinct additions to improve completeness and clarity. (Warning)"
Quick examples (illustrative)
Flagged: multiple inputs each with one component
JSON
{
"inputs": [
{ "components": [{ "name": "A", "type": "REACTANT" }] },
{ "components": [{ "name": "B", "type": "REACTANT" }] }
]
}
Flagged: single input with multiple REACTANT/REAGENT/CATALYST components
JSON
{
"inputs": [
{
"components": [
{ "name": "A", "type": "REACTANT" },
{ "name": "B", "type": "REAGENT" },
{ "name": "Cat", "type": "CATALYST" }
]
}
]
}
Preferred (example) — multiple components in a single well-described input or separate inputs that reflect distinct additions:
JSON
{
"inputs": [
{
"components": [
{ "name": "A", "type": "REACTANT" },
{ "name": "B", "type": "REACTANT" }
],
"addition_step": "add A and B together at start"
},
{
"components": [
{ "name": "C", "type": "SOLVENT" }
],
"addition_step": "add C later"
}
]
}
Suggested validator implementation (example)
The example below follows the repository’s existing pattern of issuing warnings via warnings.warn(..., ValidationWarning). Adapt imports, message codes, enum names, and registration to match ord-schema.
File suggestion: ord_schema/validators/input_composition_validator.py
Python
import warnings
from ord_schema import reaction_pb2
from ord_schema.validations import ValidationWarning # adapt import
ACTIVE_COMPONENT_TYPES = {"REACTANT", "REAGENT", "CATALYST"}
def _is_active_component(component) -> bool:
try:
return component.reaction_role in (
reaction_pb2.ReactionRole.ReactionRoleType.REACTANT,
reaction_pb2.ReactionRole.ReactionRoleType.REAGENT,
reaction_pb2.ReactionRole.ReactionRoleType.CATALYST,
)
except Exception:
t = getattr(component, "type", None)
return isinstance(t, str) and t.upper() in ACTIVE_COMPONENT_TYPES
def _collect_components(inp):
return list(inp.components) + list(getattr(inp, "crude_components", []))
def add_input_composition_warnings(message: reaction_pb2.Reaction) -> None:
# Mistake 1: multiple inputs where each has only one component
inputs_len = len(message.inputs)
if inputs_len > 1:
all_single = True
for key in message.inputs:
inp = message.inputs[key]
comp_count = len(_collect_components(inp))
if comp_count != 1:
all_single = False
break
if all_single:
warnings.warn(
"Reaction has multiple inputs where each input contains a single component. "
"This often indicates a misunderstanding of input addition semantics — consider "
"grouping components in the same input or recording explicit separate addition steps.",
ValidationWarning,
)
# Mistake 2: single input with multiple active components
if inputs_len == 1:
single_key = next(iter(message.inputs))
inp = message.inputs[single_key]
active_count = sum(1 for c in _collect_components(inp) if _is_active_component(c))
if active_count > 1:
warnings.warn(
"Single input contains multiple REACTANT/REAGENT/CATALYST components. "
"Consider recording separate inputs for distinct additions to improve completeness and clarity.",
ValidationWarning,
)
Suggested unit tests (example)
Adapt imports and helpers to the repository test harness (e.g., use _run_validation).
File suggestion: ord_schema/validations_test.py (or tests/test_input_composition_validator.py)
Python
def test_multiple_inputs_single_component_flagged():
message = reaction_pb2.Reaction()
inp1 = message.inputs["i1"]
c1 = inp1.components.add()
c1.identifiers.add(type="CUSTOM").value = "A"
inp2 = message.inputs["i2"]
c2 = inp2.components.add()
c2.identifiers.add(type="CUSTOM").value = "B"
output = _run_validation(message)
assert any("multiple inputs" in w for w in output.warnings)
def test_single_input_multiple_active_components_flagged():
message = reaction_pb2.Reaction()
inp = message.inputs["single"]
c1 = inp.components.add()
c1.identifiers.add(type="CUSTOM").value = "A"
# c1.reaction_role = reaction_pb2.ReactionRole.ReactionRoleType.REACTANT
c2 = inp.components.add()
c2.identifiers.add(type="CUSTOM").value = "B"
# c2.reaction_role = reaction_pb2.ReactionRole.ReactionRoleType.REAGENT
output = _run_validation(message)
assert any("REACTANT/REAGENT/CATALYST" in w or "Single input contains multiple" in w for w in output.warnings)
def test_non_flagged_structures():
message = reaction_pb2.Reaction()
inp = message.inputs["i"]
c1 = inp.components.add()
c1.identifiers.add(type="CUSTOM").value = "A"
c1.amount.mass.value = 1
inp2 = message.inputs["i2"]
c2 = inp2.components.add()
c3 = inp2.components.add()
output = _run_validation(message)
assert not any("multiple inputs" in w or "Single input contains multiple" in w for w in output.warnings)
Notes for ord-app integration
- Expose/register the two validator message codes so ord-app can map them to inline warnings.
- In ord-app, display a non-blocking inline warning message with:
- a concise explanation,
- a link to docs with examples,
- an ability to dismiss/acknowledge the warning when the user intentionally chooses this structure.
- If ord-schema includes structured validation paths, ord-app can highlight the affected inputs/components in the editor UI.
Summary
Add a validator in ord-schema that flags two common mistakes authors make when defining reaction inputs and returns warnings (not hard errors). Once added to ord-schema, the same validation should be surfaced in ord-app so users see it in the editor.
Mistake 1
Mistake 2
Implementation notes / acceptance criteria
Suggested validator messages (examples)
Code: input-composition:multiple-inputs-single-component
Text: "Reaction has multiple inputs where each input contains a single component. This often indicates a misunderstanding of input addition semantics — consider grouping components in the same input or recording explicit separate addition steps. (Warning)"
Code: input-composition:single-input-multiple-active-components
Text: "Single input contains multiple REACTANT/REAGENT/CATALYST components. Consider recording separate inputs for distinct additions to improve completeness and clarity. (Warning)"
Quick examples (illustrative)
Flagged: multiple inputs each with one component
Flagged: single input with multiple REACTANT/REAGENT/CATALYST components
Preferred (example) — multiple components in a single well-described input or separate inputs that reflect distinct additions:
Suggested validator implementation (example)
The example below follows the repository’s existing pattern of issuing warnings via warnings.warn(..., ValidationWarning). Adapt imports, message codes, enum names, and registration to match ord-schema.
File suggestion: ord_schema/validators/input_composition_validator.py
Suggested unit tests (example)
Adapt imports and helpers to the repository test harness (e.g., use _run_validation).
File suggestion: ord_schema/validations_test.py (or tests/test_input_composition_validator.py)
Notes for ord-app integration