renkin 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/package.json +1 -1
- package/renkin.d.ts +52 -0
- package/renkin.js +106 -0
- package/renkin_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -346,7 +346,7 @@ for the full acceptance criteria and licensing split.
|
|
|
346
346
|
| **Ring-context safety guard** | `--ring-context-policy conservative --ring-context-sidecar <path>` — opt-in match-level filter that rejects an extracted template's ring-opening/closing disconnection when its historical training data never observed that bond as ring-forming/-breaking; default `disabled` (unchanged legacy behavior) — see [Issue #72](https://github.com/kent-tokyo/renkin/issues/72) |
|
|
347
347
|
| **LightGBM candidate reranker** | `--reranker-model`/`--reranker-freq-table` (CLI) or `reranker_model_path`/`reranker_freq_table_path` (Python) — opt-in, ordering-only re-ranking via a frozen LightGBM model; never changes which candidates are generated, only their order, and reproduces legacy ordering byte-for-byte when off. Paired 100-target route-search gate: `route_to_configured_stock` 16→20 (+4/-0). `python3 scripts/fetch_reranker_model.py` fetches the frozen model (SHA-256-verified, not bundled in any package — see [Roadmap](#roadmap)) |
|
|
348
348
|
| **Coverage mode** (opt-in) | `--search-mode coverage --coverage-templates <path>` (CLI) or `search_mode="coverage"`, `coverage_templates_path=...` (Python) — if the default template set finds no route, automatically escalates to a larger, separately loaded template set, cooperatively cancellable via `--coverage-timeout-secs`. Standard-mode output is byte-for-byte unchanged when not used. `python3 scripts/fetch_coverage_templates.py` fetches the frozen 2,000-template Stage-2 set (SHA-256-verified, not bundled in any package, same reasoning as the reranker model — see [Roadmap](#roadmap)) |
|
|
349
|
-
| **RENKIN Bridge / `audit-route`** | `renkin audit-route route.json [--format auto\|renkin\|aizynthfinder] [--stock stock.smi] [--output human\|json]` — tool-neutral route audit: structural integrity, stock, and declared-reaction forward-replay validation, each reported independently as `pass`/`fail`/`not_evaluable`, rolled up into a route-level `pass`/`fail`/`partial` verdict. Reads RENKIN-native route JSON (v0.25.0) and real AiZynthFinder route JSON — single-target and gzip-compressed batch output, verified against AiZynthFinder v4.4.1 specifically, not claimed for every version (v0.26.0); `--format auto` detects the input shape and hard-errors rather than guessing on anything ambiguous |
|
|
349
|
+
| **RENKIN Bridge / `audit-route`** | `renkin audit-route route.json [--format auto\|renkin\|aizynthfinder] [--stock stock.smi] [--output human\|json]` — tool-neutral route audit: structural integrity, stock, and declared-reaction forward-replay validation, each reported independently as `pass`/`fail`/`not_evaluable`, rolled up into a route-level `pass`/`fail`/`partial` verdict. Reads RENKIN-native route JSON (v0.25.0) and real AiZynthFinder route JSON — single-target and gzip-compressed batch output, verified against AiZynthFinder v4.4.1 specifically, not claimed for every version (v0.26.0); `--format auto` detects the input shape and hard-errors rather than guessing on anything ambiguous. [5-minute walkthrough with real output →](https://kent-tokyo.github.io/renkin/guides/aizynthfinder-audit-demo/) |
|
|
350
350
|
| **Route scoring** | `confidence`, `step_confidence`, `success_probability` (Retro-prob style), `convergency`, `atom_economy`, `route_cost` (`Σ BB cost + steps×0.5`, or actual prices via `--bb-prices`/`--stock`) per step/route — see caveat below the table |
|
|
351
351
|
| **Step metadata provenance** | Each step reports `metadata_source`/`metadata_scope` so it's machine-readable whether `conditions`/`reaction_family` came from a rule-author default vs. something more grounded; absent (not fabricated) for extracted templates |
|
|
352
352
|
| **Pareto multi-objective search** | `--format pareto` returns a Pareto front across `route_cost`/`success_probability`/`steps`; objectives configurable via `--objectives` |
|
|
@@ -384,15 +384,17 @@ renkin -t "CC(=O)Oc1ccccc1C(=O)O" --format json | renkin-forward validate
|
|
|
384
384
|
# Faster template retrieval with bond-center index (~24% speedup)
|
|
385
385
|
renkin -t "c1ccc(NC(=O)c2ccccc2)cc1" --templates data/templates_extracted_5000.smi --bond-index
|
|
386
386
|
|
|
387
|
-
# Audit a real AiZynthFinder route export with RENKIN
|
|
388
|
-
renkin
|
|
387
|
+
# Audit a real AiZynthFinder route export with RENKIN (see the full walkthrough:
|
|
388
|
+
# https://kent-tokyo.github.io/renkin/guides/aizynthfinder-audit-demo/)
|
|
389
|
+
renkin audit-route tests/fixtures/aizynthfinder/v4.4.1/single_trees.json \
|
|
389
390
|
--format aizynthfinder \
|
|
390
|
-
--stock building_blocks.smi \
|
|
391
|
+
--stock data/building_blocks.smi \
|
|
391
392
|
--output human
|
|
392
393
|
|
|
393
|
-
# Same audit pipeline, either source — --format auto also detects
|
|
394
|
-
renkin
|
|
395
|
-
renkin audit-route
|
|
394
|
+
# Same audit pipeline, either source — --format auto also detects both correctly
|
|
395
|
+
renkin -t "CC(=O)Oc1ccccc1C(=O)O" --format json > /tmp/renkin-route.json
|
|
396
|
+
renkin audit-route /tmp/renkin-route.json --format renkin
|
|
397
|
+
renkin audit-route tests/fixtures/aizynthfinder/v4.4.1/single_trees.json --format aizynthfinder
|
|
396
398
|
```
|
|
397
399
|
|
|
398
400
|
---
|
|
@@ -620,6 +622,8 @@ see "Earlier milestones" below for older shipped work.
|
|
|
620
622
|
|
|
621
623
|
### Recently shipped
|
|
622
624
|
|
|
625
|
+
- [x] **Audit Playground** (`[ Audit a Route ]` tab, shipped v0.28.0) — *Audit a route in your browser — the same pipeline, the same verdict, zero network calls.* The [browser playground](https://kent-tokyo.github.io/renkin/playground/) now audits a RENKIN or AiZynthFinder route export (single-route or Pandas batch) and an optional stock list entirely client-side, via a new `audit_route` WASM export that calls the identical report-building pipeline `renkin audit-route` uses — the same pass/fail/partial verdict either way, not a separately-maintained copy. Paste or upload, run off the main thread, download the JSON report.
|
|
626
|
+
- [x] **Reproducible Route Audit** (`audit_manifest` on `renkin audit-route --output json`, shipped v0.27.0) — *Reproduce what was audited, from which input, with which stock and policy.* Every audit report now records RENKIN version, report schema version, source format/version, input/stock content SHA-256 hashes, and audit policy — tested for byte-identical determinism (auditing the same input twice), not just claimed. Adds a shared adapter conformance suite across RENKIN-native and AiZynthFinder route inputs, plus a written [reproducibility/compatibility contract](https://kent-tokyo.github.io/renkin/guides/audit-reproducibility-contract/) (verified-vs-supported versions, unknown-field tolerance, report-schema rules, adapter-fixture runbook). The [browser playground](https://kent-tokyo.github.io/renkin/playground/) also got a safety/UX pass this release: search runs off the main thread with cancel/time-budget support, structure rendering stays local by default (no third-party SMILES transmission), and search settings round-trip exactly through Copy CLI/Python.
|
|
623
627
|
- [x] **RENKIN Bridge — Cross-Tool Route Audit** (`renkin audit-route`, RENKIN-native adapter shipped v0.25.0, AiZynthFinder adapter shipped v0.26.0) — *Keep AiZynthFinder. Audit its routes with RENKIN.* A tool-neutral route audit model: structural-integrity, stock, and declared-reaction forward-replay validation, each reported independently as `pass`/`fail`/`not_evaluable`, rolled up into a route-level `pass`/`fail`/`partial` verdict — never a silently force-passed boolean. v0.26.0 adds a real AiZynthFinder adapter (single-target and gzip batch JSON, verified against captured v4.4.1 output — see [`PROVENANCE.md`](tests/fixtures/aizynthfinder/v4.4.1/PROVENANCE.md)) plus `--format auto` detection, so both tools' routes run through the exact same audit pipeline; auditing the real fixtures also surfaced and fixed a shared forward-replay bug where precursor ordering, not just chemistry, affected the verdict. `renkin audit-route route.json --stock stock.smi --output json` audits every route in a file and aggregates the results into one machine-readable report, regardless of which tool produced it.
|
|
624
628
|
- [x] Coverage mode (`--search-mode coverage`, [#101](https://github.com/kent-tokyo/renkin/issues/101), shipped v0.24.0) — opt-in Stage-1/Stage-2 template-count escalation, addressing the candidate-generation coverage gap below. Confirmed by a one-shot 500-target formal-TEST (`data/coverage_mode_formal_test/protocol_v2.md`): coverage +6.0pp, net gain +30, zero regressions, zero reranker failures, Stage-2 timeout rate 0.25% — all against pre-registered thresholds. See the Key Features table above for the shipped surface
|
|
625
629
|
- [x] Reranker made actually usable: Python exposure (`find_routes()`'s `reranker_model_path`/`reranker_freq_table_path`) and batteries-included model distribution (`scripts/fetch_reranker_model.py`, SHA-256-verified fetch from the v0.22.0 GitHub Release's canonical assets) ([#101](https://github.com/kent-tokyo/renkin/issues/101), shipped v0.23.0) — v0.22.0 proved the reranker works; v0.23.0 is the usability/distribution unlock, not a new accuracy claim
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"kent-tokyo <kent-tokyo@users.noreply.github.com>"
|
|
6
6
|
],
|
|
7
7
|
"description": "Ultra-fast retrosynthesis engine for computer-aided synthesis planning (CASP) — pure Rust, WASM-ready, Python bindings via PyO3",
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.28.0",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
package/renkin.d.ts
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Audit a pasted/uploaded route export (WASM entry point) -- the browser
|
|
6
|
+
* counterpart to `renkin audit-route`, calling the identical
|
|
7
|
+
* `bridge::build_audit_route_report` pipeline so a route audited in the
|
|
8
|
+
* playground gets exactly the same pass/fail/partial verdict the CLI would
|
|
9
|
+
* produce for the same input, not a separately-maintained copy.
|
|
10
|
+
*
|
|
11
|
+
* # Arguments
|
|
12
|
+
* * `content` - Route export JSON text (RENKIN `--format json` output,
|
|
13
|
+
* or an AiZynthFinder single-route/batch export). Plain
|
|
14
|
+
* JSON only -- unlike the CLI, this has no gzip support;
|
|
15
|
+
* a browser paste/upload never needs it.
|
|
16
|
+
* * `format` - `"auto" | "renkin" | "aizynthfinder"`, same vocabulary
|
|
17
|
+
* as the CLI's `--format` flag.
|
|
18
|
+
* * `stock_text` - Optional `.smi`-style stock listing (one SMILES per
|
|
19
|
+
* line, `#`-comments allowed), or `""` for "no stock to
|
|
20
|
+
* check against".
|
|
21
|
+
*
|
|
22
|
+
* Returns a JSON string: either the `AuditRouteReport` shape (same as
|
|
23
|
+
* `renkin audit-route --output json`) or `{"error": "..."}` on a bad
|
|
24
|
+
* input (malformed JSON, unrecognized format, ...).
|
|
25
|
+
*/
|
|
26
|
+
export function audit_route(content: string, format: string, stock_text: string): string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Static capabilities of this WASM build (browser edition), as a JSON
|
|
30
|
+
* string -- real counts read from the same compiled-in data `find_routes`
|
|
31
|
+
* itself searches against, not a hardcoded UI string that can drift from
|
|
32
|
+
* what the engine actually has loaded.
|
|
33
|
+
*/
|
|
34
|
+
export function capabilities(): string;
|
|
35
|
+
|
|
4
36
|
/**
|
|
5
37
|
* Find retrosynthetic routes for a target molecule (WASM entry point).
|
|
6
38
|
*
|
|
@@ -22,6 +54,23 @@
|
|
|
22
54
|
*/
|
|
23
55
|
export function find_routes(target: string, depth: number, max_routes: number, beam_width: number): string;
|
|
24
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Find retrosynthetic routes with element filtering (WASM entry point).
|
|
59
|
+
*
|
|
60
|
+
* Same as [`find_routes`] plus `avoid_elements`/`require_elements`: comma-
|
|
61
|
+
* separated element symbols, identical format and conversion
|
|
62
|
+
* (`chem_env::elem_symbols_to_mask`) as the CLI's own `--avoid-elements`/
|
|
63
|
+
* `--require-elements` flags, so browser filtering behaves exactly like
|
|
64
|
+
* the CLI's, not a separately-maintained copy. A distinct function name
|
|
65
|
+
* rather than optional/extra parameters on `find_routes`, so a caller on
|
|
66
|
+
* an old build gets a real "no such export" `TypeError` instead of a
|
|
67
|
+
* silently-ignored argument -- this playground's own JS previously relied
|
|
68
|
+
* on `try { 6-arg call } catch { 4-arg call }` to bridge this gap, which
|
|
69
|
+
* meant `avoid_elements`/`require_elements` silently never took effect
|
|
70
|
+
* against any WASM build that predates this function.
|
|
71
|
+
*/
|
|
72
|
+
export function find_routes_v2(target: string, depth: number, max_routes: number, beam_width: number, avoid_elements: string, require_elements: string): string;
|
|
73
|
+
|
|
25
74
|
/**
|
|
26
75
|
* Return the crate version string.
|
|
27
76
|
*/
|
|
@@ -31,7 +80,10 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
|
|
31
80
|
|
|
32
81
|
export interface InitOutput {
|
|
33
82
|
readonly memory: WebAssembly.Memory;
|
|
83
|
+
readonly audit_route: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
|
|
84
|
+
readonly capabilities: () => [number, number];
|
|
34
85
|
readonly find_routes: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
86
|
+
readonly find_routes_v2: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number];
|
|
35
87
|
readonly version: () => [number, number];
|
|
36
88
|
readonly __wbindgen_externrefs: WebAssembly.Table;
|
|
37
89
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
package/renkin.js
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
/* @ts-self-types="./renkin.d.ts" */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Audit a pasted/uploaded route export (WASM entry point) -- the browser
|
|
5
|
+
* counterpart to `renkin audit-route`, calling the identical
|
|
6
|
+
* `bridge::build_audit_route_report` pipeline so a route audited in the
|
|
7
|
+
* playground gets exactly the same pass/fail/partial verdict the CLI would
|
|
8
|
+
* produce for the same input, not a separately-maintained copy.
|
|
9
|
+
*
|
|
10
|
+
* # Arguments
|
|
11
|
+
* * `content` - Route export JSON text (RENKIN `--format json` output,
|
|
12
|
+
* or an AiZynthFinder single-route/batch export). Plain
|
|
13
|
+
* JSON only -- unlike the CLI, this has no gzip support;
|
|
14
|
+
* a browser paste/upload never needs it.
|
|
15
|
+
* * `format` - `"auto" | "renkin" | "aizynthfinder"`, same vocabulary
|
|
16
|
+
* as the CLI's `--format` flag.
|
|
17
|
+
* * `stock_text` - Optional `.smi`-style stock listing (one SMILES per
|
|
18
|
+
* line, `#`-comments allowed), or `""` for "no stock to
|
|
19
|
+
* check against".
|
|
20
|
+
*
|
|
21
|
+
* Returns a JSON string: either the `AuditRouteReport` shape (same as
|
|
22
|
+
* `renkin audit-route --output json`) or `{"error": "..."}` on a bad
|
|
23
|
+
* input (malformed JSON, unrecognized format, ...).
|
|
24
|
+
* @param {string} content
|
|
25
|
+
* @param {string} format
|
|
26
|
+
* @param {string} stock_text
|
|
27
|
+
* @returns {string}
|
|
28
|
+
*/
|
|
29
|
+
export function audit_route(content, format, stock_text) {
|
|
30
|
+
let deferred4_0;
|
|
31
|
+
let deferred4_1;
|
|
32
|
+
try {
|
|
33
|
+
const ptr0 = passStringToWasm0(content, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
34
|
+
const len0 = WASM_VECTOR_LEN;
|
|
35
|
+
const ptr1 = passStringToWasm0(format, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
36
|
+
const len1 = WASM_VECTOR_LEN;
|
|
37
|
+
const ptr2 = passStringToWasm0(stock_text, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
38
|
+
const len2 = WASM_VECTOR_LEN;
|
|
39
|
+
const ret = wasm.audit_route(ptr0, len0, ptr1, len1, ptr2, len2);
|
|
40
|
+
deferred4_0 = ret[0];
|
|
41
|
+
deferred4_1 = ret[1];
|
|
42
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
43
|
+
} finally {
|
|
44
|
+
wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Static capabilities of this WASM build (browser edition), as a JSON
|
|
50
|
+
* string -- real counts read from the same compiled-in data `find_routes`
|
|
51
|
+
* itself searches against, not a hardcoded UI string that can drift from
|
|
52
|
+
* what the engine actually has loaded.
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
export function capabilities() {
|
|
56
|
+
let deferred1_0;
|
|
57
|
+
let deferred1_1;
|
|
58
|
+
try {
|
|
59
|
+
const ret = wasm.capabilities();
|
|
60
|
+
deferred1_0 = ret[0];
|
|
61
|
+
deferred1_1 = ret[1];
|
|
62
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
63
|
+
} finally {
|
|
64
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
3
68
|
/**
|
|
4
69
|
* Find retrosynthetic routes for a target molecule (WASM entry point).
|
|
5
70
|
*
|
|
@@ -39,6 +104,47 @@ export function find_routes(target, depth, max_routes, beam_width) {
|
|
|
39
104
|
}
|
|
40
105
|
}
|
|
41
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Find retrosynthetic routes with element filtering (WASM entry point).
|
|
109
|
+
*
|
|
110
|
+
* Same as [`find_routes`] plus `avoid_elements`/`require_elements`: comma-
|
|
111
|
+
* separated element symbols, identical format and conversion
|
|
112
|
+
* (`chem_env::elem_symbols_to_mask`) as the CLI's own `--avoid-elements`/
|
|
113
|
+
* `--require-elements` flags, so browser filtering behaves exactly like
|
|
114
|
+
* the CLI's, not a separately-maintained copy. A distinct function name
|
|
115
|
+
* rather than optional/extra parameters on `find_routes`, so a caller on
|
|
116
|
+
* an old build gets a real "no such export" `TypeError` instead of a
|
|
117
|
+
* silently-ignored argument -- this playground's own JS previously relied
|
|
118
|
+
* on `try { 6-arg call } catch { 4-arg call }` to bridge this gap, which
|
|
119
|
+
* meant `avoid_elements`/`require_elements` silently never took effect
|
|
120
|
+
* against any WASM build that predates this function.
|
|
121
|
+
* @param {string} target
|
|
122
|
+
* @param {number} depth
|
|
123
|
+
* @param {number} max_routes
|
|
124
|
+
* @param {number} beam_width
|
|
125
|
+
* @param {string} avoid_elements
|
|
126
|
+
* @param {string} require_elements
|
|
127
|
+
* @returns {string}
|
|
128
|
+
*/
|
|
129
|
+
export function find_routes_v2(target, depth, max_routes, beam_width, avoid_elements, require_elements) {
|
|
130
|
+
let deferred4_0;
|
|
131
|
+
let deferred4_1;
|
|
132
|
+
try {
|
|
133
|
+
const ptr0 = passStringToWasm0(target, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
134
|
+
const len0 = WASM_VECTOR_LEN;
|
|
135
|
+
const ptr1 = passStringToWasm0(avoid_elements, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
136
|
+
const len1 = WASM_VECTOR_LEN;
|
|
137
|
+
const ptr2 = passStringToWasm0(require_elements, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
138
|
+
const len2 = WASM_VECTOR_LEN;
|
|
139
|
+
const ret = wasm.find_routes_v2(ptr0, len0, depth, max_routes, beam_width, ptr1, len1, ptr2, len2);
|
|
140
|
+
deferred4_0 = ret[0];
|
|
141
|
+
deferred4_1 = ret[1];
|
|
142
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
143
|
+
} finally {
|
|
144
|
+
wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
42
148
|
/**
|
|
43
149
|
* Return the crate version string.
|
|
44
150
|
* @returns {string}
|
package/renkin_bg.wasm
CHANGED
|
Binary file
|