Found while driving the wizard in a real browser: I set the box temperature to 9999 K expecting a
validation error, and the server accepted it.
That is not a UI bug — the schema only declares gt=0 for site.temperature_k. But it means the
wizard will happily submit physically impossible configurations, and spec §4.1 lists "valid range /
enum" as required field metadata.
Current state
17 of 22 numeric fields have a lower bound and no upper bound:
site.temperature_k site.pressure_mbar site.h2o_ppmv
injection.plume_length_m injection.plume_width_m injection.plume_height_m
injection.so2_mass_kg dilution.rate_per_s background.so2_pptv
chemistry.so2_ho2_rate microphysics.nucleation_rate_scale
microphysics.coag_kernel_scale microphysics.ion_pair_rate
numerics.output_dt_s numerics.couple_dt_s schedule.duration_days
termination.max_wall_time_s
5 are bounded on both sides, and they share a pattern — their bounds are definitional rather
than physical: latitude_deg (±90), longitude_deg, day_of_year (<366), start_utc_hour (<24),
condensation_alpha (a coefficient in [0, 1]).
So the split is not an oversight so much as a line that was never explicitly drawn: bounds got added
where the number's own definition supplies them, and omitted where an upper limit would be a
judgement about plausible physics.
The decision
Where should physical upper bounds come from? I am not picking these numbers — per the project rule,
a bound like "temperature ≤ 300 K" is a convention, and inventing it is exactly the fabricated-physics
failure mode studio/CLAUDE.md puts first.
Options:
- Leave unbounded, validate nothing further. Honest about what we know; the wizard will submit
9999 K and the model will produce nonsense for it.
- Bounds from the operating envelope, cited to where the number came from — e.g. temperature and
pressure bounded by the range the TUV-x tables and JPL rate fits are valid over, rather than by a
guess at what is "reasonable". This has a real source and is my suggestion, but it needs someone
who knows those validity ranges to state them.
- Warn, do not refuse. A soft range in
x-studio that the UI renders as "outside the ensemble's
range" without blocking submission — useful for deliberate sensitivity tests that go out of bounds
on purpose.
(2) and (3) compose: hard bounds where a source says the model is invalid, soft warnings for the rest.
Meanwhile
test_which_numeric_fields_have_no_upper_bound pins the current list, so whatever is decided shows up
as a deliberate change to it, and nobody assumes bounds exist that do not.
Also fixed in the same PR: x-studio.range is a dict of operators ({gt: 0}), and the front end had
typed it as a [min, max] tuple — so range[0] was always undefined and a metadata-only bound
reached the input as no bound at all. Nothing failed, which is why it now has a test on both sides.
Found while driving the wizard in a real browser: I set the box temperature to 9999 K expecting a
validation error, and the server accepted it.
That is not a UI bug — the schema only declares
gt=0forsite.temperature_k. But it means thewizard will happily submit physically impossible configurations, and spec §4.1 lists "valid range /
enum" as required field metadata.
Current state
17 of 22 numeric fields have a lower bound and no upper bound:
5 are bounded on both sides, and they share a pattern — their bounds are definitional rather
than physical:
latitude_deg(±90),longitude_deg,day_of_year(<366),start_utc_hour(<24),condensation_alpha(a coefficient in [0, 1]).So the split is not an oversight so much as a line that was never explicitly drawn: bounds got added
where the number's own definition supplies them, and omitted where an upper limit would be a
judgement about plausible physics.
The decision
Where should physical upper bounds come from? I am not picking these numbers — per the project rule,
a bound like "temperature ≤ 300 K" is a convention, and inventing it is exactly the fabricated-physics
failure mode
studio/CLAUDE.mdputs first.Options:
9999 K and the model will produce nonsense for it.
pressure bounded by the range the TUV-x tables and JPL rate fits are valid over, rather than by a
guess at what is "reasonable". This has a real source and is my suggestion, but it needs someone
who knows those validity ranges to state them.
x-studiothat the UI renders as "outside the ensemble'srange" without blocking submission — useful for deliberate sensitivity tests that go out of bounds
on purpose.
(2) and (3) compose: hard bounds where a source says the model is invalid, soft warnings for the rest.
Meanwhile
test_which_numeric_fields_have_no_upper_boundpins the current list, so whatever is decided shows upas a deliberate change to it, and nobody assumes bounds exist that do not.
Also fixed in the same PR:
x-studio.rangeis a dict of operators ({gt: 0}), and the front end hadtyped it as a
[min, max]tuple — sorange[0]was alwaysundefinedand a metadata-only boundreached the input as no bound at all. Nothing failed, which is why it now has a test on both sides.