1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! Phase 22: connects gugen's chemical planning output to real purchasable
//! products, without ever feeding commercial data back into scientific
//! planning. Two strictly separate stages: chemical planning (existing
//! `Planner`/`score_plan`) produces a `SynthesisPlan`; this module then
//! matches that plan's precursor compositions against a caller-supplied
//! catalog of commercial offers (price, purity, package size, supplier).
//!
//! **Never mutates `SynthesisPlan`.** `assess_commercial_precursors`/
//! `assess_commercial_plans` take `&SynthesisPlan` and return a wholly
//! separate `CommercialPlanAssessment` -- score, confidence, the balanced
//! reaction, and process steps are structurally unreachable from this
//! module (mirrors `literature_evidence.rs`'s "reference-only, by
//! construction" boundary: this is a separate return type from a separate
//! function, never threaded into `score_plan`'s signature or as a new
//! `SynthesisPlan` field).
//!
//! **No network access anywhere in this module.** Product URLs are stored
//! strings, never fetched. Catalogs are loaded from caller-supplied CSV/JSON
//! text only.
//!
//! **Commercial offer matching uses a canonical, scale-invariant
//! composition ratio -- not literal `Composition::eq`.** Two formulas
//! written at different formula-unit scale (`Fe2O3` vs `Fe4O6`) are the
//! same substance and match here, via exact-rational GCD reduction of the
//! whole element-ratio vector (never floating-point ratio comparison --
//! see `canonical_ratio_key`). This is scale-invariant canonicalization of
//! *one supplied formula*, not alias or substitute-precursor inference:
//! gugen's own `Composition::eq` (used everywhere else in the crate, e.g.
//! reaction balancing) is untouched and stays strictly literal. Formulas
//! with a genuinely different ratio (`FeO` vs `Fe2O3`), a different
//! element set (different oxides, carbonates, doped vs. undoped hosts), or
//! a hydrate vs. its anhydrous form (`CaSO4` vs `CaSO4ยท2H2O` -- the
//! formula parser folds hydrate water into the flat element-amount map,
//! giving them different, non-proportional atom counts) remain distinct:
//! canonicalization only reduces a shared ratio to lowest terms, it never
//! bridges formulas that aren't proportional to begin with.
//!
//! **gugen does not certify commercial data.** Catalog values are supplied
//! data; prices are estimates; availability may be stale; product
//! suitability for a given synthesis is not certified. Vendor documentation
//! and SDS sheets must be checked separately.
pub use ;
pub use ;