Audit a Syntheseus Route with RENKIN
Syntheseus has no native route export. RENKIN owns the converter.
Syntheseus is a retrosynthesis
search library, not a route-export format — it has no to_json() on its
own SynthesisGraph type. RENKIN Bridge closes that gap with its own
syntheseus-route-v1 interchange schema: an optional Python module,
renkin.syntheseus_exporter (pip install
renkin[syntheseus]), walks a real SynthesisGraph object via its public
interface and produces JSON that renkin audit-route --format syntheseus
consumes through the exact same tool-neutral pipeline RENKIN's own routes
and AiZynthFinder's routes already go through.
The fixtures
tests/fixtures/syntheseus/0.7.2/ has two real, exporter-produced JSON
files — not hand-typed, not from a live model search (that needs a
checkpoint/GPU, out of scope for this adapter's own construction and
testing). Both are genuine syntheseus.search.graph.route.SynthesisGraph
objects built from Syntheseus's own public interface classes
(Molecule/Bag/SingleProductReaction), validated by Syntheseus's own
assert_validity(), then exported. Full provenance — exact construction
code, package versions, checksums — is in the sibling
PROVENANCE.md.
linear_two_leaf_route.json— a single-step route, both leaves carrying full purchasability metadata.convergent_route.json— a deliberately non-tree route (a molecule produced by one step and consumed by two different downstream steps), with one leaf carrying no purchasability claim at all.
Step 1: audit without a configured stock
renkin audit-route tests/fixtures/syntheseus/0.7.2/linear_two_leaf_route.json \
--format syntheseus \
--output human
1 routes audited — 0 pass, 0 fail, 1 partial
route 1/1: PARTIAL
- ForwardValidationNotEvaluable
- stock: StockNotProvided
- forward: MissingAtomMapping
stock: StockNotProvided is the same honest "we didn't check" result every
adapter reports without --stock — see the
AiZynthFinder demo for why that's correct,
not weaker. forward: MissingAtomMapping is specific to this adapter, and
worth understanding rather than dismissing as noise (see Step 3).
Step 2: audit with a configured stock
renkin audit-route tests/fixtures/syntheseus/0.7.2/linear_two_leaf_route.json \
--format syntheseus \
--stock data/building_blocks.smi \
--output human
1 routes audited — 0 pass, 0 fail, 1 partial
route 1/1: PARTIAL
- ForwardValidationNotEvaluable
- forward: MissingAtomMapping
stock: StockNotProvided is gone — both leaves (ethanol, benzoic acid) are
in data/building_blocks.smi, so stock validation now passes outright. The
route still comes back PARTIAL, not PASS, purely because of forward
validation. That's Step 3.
Step 3: why forward validation stays not_evaluable
RENKIN's declared-reaction-replay check needs an atom-mapped SMIRKS to know
which atom in the product came from which atom in the reactants.
AiZynthFinder's route metadata optionally carries one
(mapped_reaction_smiles); Syntheseus's reaction_smiles is a computed
property — a plain reactants>>product string, generated from canonical
SMILES, with no atom mapping at all, on every real Syntheseus route today.
renkin audit-route doesn't invent mapping that isn't there: it reports
MissingAtomMapping, the same honest not_evaluable result you'd get from
an AiZynthFinder route whose metadata omits mapped_reaction_smiles too
(see missing_reaction_evidence_is_not_evaluable_never_silently_resolved_on_either_tool
in tests/cross_tool_audit.rs). A future exporter enhancement could add
atom mapping if a real need for it shows up — nothing here rules it out —
but nothing today fabricates it to force a PASS.
The convergent (non-tree) fixture
renkin audit-route tests/fixtures/syntheseus/0.7.2/convergent_route.json \
--format syntheseus \
--output human
1 routes audited — 0 pass, 1 fail, 0 partial
route 1/1: FAIL
- AmbiguousLeafStatus
- AmbiguousLeafStatus
This fixture's one true leaf (CC, ethane) genuinely carries no
purchasability claim — AmbiguousLeafStatus is the correct, honest result,
never silently guessed at. It appears twice, not once: the same molecule is
reachable via two different reaction paths in this convergent route, and
RENKIN's route representation has no way to express a shared node with two
parents, so it's expanded independently under each parent — the same
duplication-on-flatten behavior RENKIN-native routes already have for this
case, not something new invented for Syntheseus (see
docs/design/syntheseus-bridge-v0.md §7.1).
What --format auto does here
Every command above passes --format syntheseus explicitly. Omit it and
--format auto (the default) detects the same result on its own, by
looking for a top-level object with "source_tool": "syntheseus" — checked
ahead of RENKIN-native's own {"target": ..., "routes": [...]} shape,
since both are top-level objects and this is the more specific signal.
Compatibility
| Source | Verified version | Input |
|---|---|---|
| Syntheseus | 0.7.2 and 0.8.0 (via renkin.syntheseus_exporter's syntheseus-route-v1 JSON) |
single-route document only — no batch format exists for this adapter |
Declared dependency interval vs. individually verified versions — these are two different claims, not one:
pip install renkin[syntheseus]declaressyntheseus>=0.7.2,<=0.8.0. This is what pip's resolver will actually install.- Individually verified against real, artifact-pinned PyPI packages:
only
0.7.2(the original named target) and0.8.0(added in v0.31.0 Phase 1 after a real dual-version compatibility spike — seedocs/design/syntheseus-0.8-compatibility-spike.mdfor the full report). The interval's upper bound is deliberately capped at<=0.8.0, not an open-ended<0.9— an unverified release above the verified range (0.8.1,0.9.0, ...) isn't silently accepted just because it would likely still work. Note the interval still admits any intermediate release too (a hypothetical future0.7.3, for instance) — it's not restricted to exactly the two named versions; an intermediate release, if one is ever published, falls within the declared interval but is not individually verified unless it's later added to the exact-version CI matrix. "Verified" and "supported" are not the same claim; see the Audit Reproducibility and Compatibility Contract. renkin.syntheseus_exporter's own production code is byte-for-byte identical for both verified versions — no0.8.0-specific branch, fallback, or private-attribute dependency exists anywhere in it.- Compatibility-verified does not mean forward-validation-capable.
Forward validation stays
not_evaluable(MissingAtomMapping) for every real Syntheseus route on both verified versions — see Step 3 above for why, confirmed independently for0.8.0by the same compatibility spike (its own atom-mapping feasibility investigation reached the identical conclusion for both versions).
See the AiZynthFinder demo and SynPlanner demo for those adapters' own compatibility rows. Unlike this adapter and AiZynthFinder, SynPlanner's forward validation genuinely passes on real output — see that guide's own Step 3 for why.
Hit a compatibility problem?
If audit-route --format syntheseus rejects real
renkin.syntheseus_exporter output, or a real route gets flagged
not_evaluable/fail in a way that looks wrong, please
open an adapter-compatibility issue —
it's set up to capture exactly what turns a real report into the next test
fixture.