What's wrong
The quantities generator deliberately withholds binary - for V0 forms so that magnitudes stay non-negative (QuantitiesGenerator.cs:843-847, if (!isV0)). But for every scalar form, V0 included, it still emits:
- unary
operator -(value) => Create(-value.Quantity) (lines ~849-857)
operator *(q, T) and operator *(T, q)
operator /(q, T)
Create intentionally does not guard (CLAUDE.md ~l.84), and #50 added Vector0Guards only to the factories. So a V0 quantity becomes negative through a single operator.
Failure scenario
Reproduced:
-Temperature<double>.FromKelvin(300) gives −300 K, below absolute zero.
-Speed<double>.FromMeterPerSecond(3) gives −3 m/s for a magnitude.
Speed<double>.FromMeterPerSecond(2) * -3.0 gives −6.
This contradicts docs/architecture.md:400 and CLAUDE.md rule 4 ("Physical constraints are enforced structurally via the V0 form"). docs/complete-library-guide.md:137 claims Speed.Create(-1) throws, but it returns −1. Downstream code that relies on the type guaranteeing non-negativity (square roots, logs, dividing by magnitudes) gets NaN or wrong signs.
Suggested fix / acceptance criteria
- For V0 forms, don't emit unary negation (as is already done for binary
-).
- For V0 forms, guard scalar
* and / with Vector0Guards.EnsureNonNegative, or restrict them to non-negative scalars.
- Fix the
complete-library-guide.md line (or make Create behave as it says).
- Tests: unary negation of a V0 is unavailable, or throws. Scaling a V0 by a negative number throws.
What's wrong
The quantities generator deliberately withholds binary
-for V0 forms so that magnitudes stay non-negative (QuantitiesGenerator.cs:843-847,if (!isV0)). But for every scalar form, V0 included, it still emits:operator -(value) => Create(-value.Quantity)(lines ~849-857)operator *(q, T)andoperator *(T, q)operator /(q, T)Createintentionally does not guard (CLAUDE.md ~l.84), and #50 addedVector0Guardsonly to the factories. So a V0 quantity becomes negative through a single operator.Failure scenario
Reproduced:
-Temperature<double>.FromKelvin(300)gives −300 K, below absolute zero.-Speed<double>.FromMeterPerSecond(3)gives −3 m/s for a magnitude.Speed<double>.FromMeterPerSecond(2) * -3.0gives −6.This contradicts
docs/architecture.md:400and CLAUDE.md rule 4 ("Physical constraints are enforced structurally via the V0 form").docs/complete-library-guide.md:137claimsSpeed.Create(-1)throws, but it returns −1. Downstream code that relies on the type guaranteeing non-negativity (square roots, logs, dividing by magnitudes) gets NaN or wrong signs.Suggested fix / acceptance criteria
-).*and/withVector0Guards.EnsureNonNegative, or restrict them to non-negative scalars.complete-library-guide.mdline (or makeCreatebehave as it says).