Skip to content

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] declares syntheseus>=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) and 0.8.0 (added in v0.31.0 Phase 1 after a real dual-version compatibility spike — see docs/design/syntheseus-0.8-compatibility-spike.md for 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 future 0.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 — no 0.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 for 0.8.0 by 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.