Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
957638a
refactor(context): extract lifecycle helpers for cache/logger/tempdir
Tomodovodoo Feb 28, 2026
8486fa6
refactor(context): remove non-lifecycle logic from context paths
Tomodovodoo Feb 28, 2026
ee2f21c
test(context): add lifecycle success/failure teardown tests
Tomodovodoo Feb 28, 2026
9086da8
docs(context): document lifecycle boundaries
Tomodovodoo Feb 28, 2026
87c9edd
feat(services): add ServiceAdapter ABC and registry
Tomodovodoo Feb 28, 2026
f738e57
feat(services): add adapters for opsin/pubchem/cir
Tomodovodoo Feb 28, 2026
0290729
feat(services): add adapters for chebi/comptox/srs/chemeo/cts/nist/ca…
Tomodovodoo Feb 28, 2026
1b60936
refactor(search): route service calls through adapter dispatcher
Tomodovodoo Feb 28, 2026
d84ccf4
test(services): add adapter contract tests
Tomodovodoo Feb 28, 2026
0a2a075
feat(search): add search_strategy API and query expansion helpers
Tomodovodoo Feb 28, 2026
bd2f6cb
feat(search): implement exhaustive collector with deduplication
Tomodovodoo Feb 28, 2026
88e4d24
test(search): first_hit vs exhaustive behavior coverage
Tomodovodoo Feb 28, 2026
cc06a7b
docs(search): add search strategy usage examples
Tomodovodoo Feb 28, 2026
ceba560
feat(scoring): add candidate grouping and score model
Tomodovodoo Feb 28, 2026
c05412a
feat(scoring): implement weighted consensus scorer
Tomodovodoo Feb 28, 2026
0bbcac9
feat(scoring): implement deterministic tie-break pipeline
Tomodovodoo Feb 28, 2026
ebdcfa1
test(scoring): deterministic ranking and tie scenarios
Tomodovodoo Feb 28, 2026
26ac7dd
feat(isomer): add resolution_mode API and strict_isomer mode
Tomodovodoo Feb 28, 2026
18306ef
feat(isomer): add OPSIN isomer verification stage
Tomodovodoo Feb 28, 2026
8ffc3a8
feat(isomer): enforce mismatch rejection in strict mode
Tomodovodoo Feb 28, 2026
7435db5
test(isomer): stereo match/mismatch and fallback behavior
Tomodovodoo Feb 28, 2026
4ec2870
feat(evidence): add CandidateEvidence and ResolutionResult models
Tomodovodoo Feb 28, 2026
922131a
feat(evidence): compute service agreement and identifier concordance
Tomodovodoo Feb 28, 2026
ec0fc7b
feat(evidence): add synonym overlap and score breakdown fields
Tomodovodoo Feb 28, 2026
bb951d8
test(evidence): evidence schema and values validation
Tomodovodoo Feb 28, 2026
89f9023
docs(evidence): document include_evidence contract
Tomodovodoo Feb 28, 2026
0ab2870
test(integration): add multi-name exhaustive benchmark cases
Tomodovodoo Feb 28, 2026
cc8bf5b
test(integration): add consensus vs legacy comparison cases
Tomodovodoo Feb 28, 2026
5d9e627
test(integration): add strict_isomer acceptance cases
Tomodovodoo Feb 28, 2026
49ebba8
chore(ci): run expanded test matrix in CI
Tomodovodoo Feb 28, 2026
5a207c5
merge: feature/context-lifecycle-cleanup
Tomodovodoo Feb 28, 2026
cf36f1d
merge: feature/service-adapter-base
Tomodovodoo Feb 28, 2026
892c15f
merge: feature/exhaustive-name-search
Tomodovodoo Feb 28, 2026
1a1e0a3
merge: feature/consensus-scoring-engine
Tomodovodoo Feb 28, 2026
73ace53
merge: feature/strict-isomer-mode
Tomodovodoo Feb 28, 2026
9732eb7
merge: feature/evidence-correlation-model
Tomodovodoo Feb 28, 2026
ee781fa
merge: feature/integration-test-upgrade
Tomodovodoo Feb 28, 2026
8ae7568
chore(tests): fold integration-upgrade tests into test_integration an…
Tomodovodoo Feb 28, 2026
3c8ffbf
test(integration): fix imports and adapter-path assertions
Tomodovodoo Feb 28, 2026
5532651
refactor(api): type resolution and strategy params with Literals
Tomodovodoo Feb 28, 2026
6989efc
refactor(services): add single-pair adapter resolution contract
Tomodovodoo Mar 1, 2026
bc9d42d
refactor(search): route exhaustive strategy through adapter single-pa…
Tomodovodoo Mar 1, 2026
c524dc2
feat(scoring): replace smiles-length scoring with rdkit stereo/chiral…
Tomodovodoo Mar 1, 2026
cb79192
refactor(scoring): update deterministic selector tie-break ordering
Tomodovodoo Mar 1, 2026
2d3f05f
test(scoring): replace length-based expectations with stereo-specific…
Tomodovodoo Mar 1, 2026
7c366a7
test(search): validate exhaustive adapter-path resolution
Tomodovodoo Mar 1, 2026
29a51fb
test(services): add single-pair adapter contract coverage
Tomodovodoo Mar 1, 2026
9522f24
docs(scoring): document consensus scoring signals and tie-break logic
Tomodovodoo Mar 1, 2026
9c19924
merge: feature/final-hardening-pass
Tomodovodoo Mar 1, 2026
5c7013d
chore(ci): install pytest-mock for lifecycle tests
Tomodovodoo Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ jobs:
with:
name: dist

- name: Install package and pytest
- name: Install package and test dependencies
shell: bash
run: |
WHL_NAME=$(ls molecule_resolver-*.whl)
pip install ${WHL_NAME} pytest
pip install ${WHL_NAME} pytest pytest-mock

- name: Run tests
shell: bash
Expand Down
21 changes: 21 additions & 0 deletions docs/context_lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Runtime Context Lifecycle

`MoleculeResolver` context management is intentionally limited to runtime resources.

## Enter

The `with MoleculeResolver() as mr:` enter step performs only:

1. RDKit log suppression context setup.
2. Molecule cache context setup.
3. OPSIN temp folder creation (when OPSIN batch support is enabled).

## Exit

The exit step performs only:

1. Molecule cache context teardown.
2. RDKit log suppression context teardown.
3. OPSIN temp folder cleanup (skipped when an exception is bubbling up).

This separation keeps search and resolution logic outside lifecycle handling, so runtime setup/teardown stays predictable and easier to maintain.
20 changes: 20 additions & 0 deletions docs/evidence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Evidence Output (`include_evidence`)

`find_single_molecule_crosschecked(..., include_evidence=True)` returns a
`ResolutionResult` instead of only a `Molecule`.

## Response fields

- `best_molecule`: Selected molecule (or `None` for unresolved ties).
- `ranked_candidates`: List of `CandidateEvidence` entries sorted by score.
- `grouped_by_structure`: Raw grouped molecules by SMILES.
- `selected_smiles`: SMILES selected as best candidate.
- `selection_reason`: Why this result form was returned.

## CandidateEvidence fields

- `service_agreement_count`: Number of unique supporting services.
- `identifier_concordance_count`: Number of unique supporting identifiers.
- `synonym_overlap_count`: Repeated synonym matches across supporting molecules.
- `score_breakdown`: Explicit points per evidence component.
- `total_score`: Sum of `score_breakdown`.
27 changes: 27 additions & 0 deletions docs/scoring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Consensus Scoring

`find_single_molecule_crosschecked(..., resolution_mode="consensus")` uses an
explicit score model for grouped structure candidates.

## Score Components

- `crosscheck_points`: `crosscheck_count * 100`
- `opsin_bonus`: `30` if at least one supporting OPSIN name match exists
- `stereo_specificity_bonus`: RDKit-derived stereochemistry signal:
- defined chiral centers: `20` points each
- stereochemical bonds: `15` points each
- unresolved chiral centers: `5` points each

## Deterministic Tie-Breaking

When total score ties, the selector orders by:

1. Higher crosscheck count
2. Higher OPSIN bonus
3. Higher stereo specificity bonus
4. Higher defined chirality bonus
5. Higher bond stereo bonus
6. Lexicographical SMILES fallback

This removes raw SMILES length from score weighting while preserving a stable
deterministic result.
25 changes: 25 additions & 0 deletions docs/search_strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Search Strategy

`find_single_molecule`, `find_single_molecule_crosschecked`, and
`find_multiple_molecules_parallelized` now support `search_strategy`.

## Options

- `first_hit` (default): preserves the previous behavior and returns as soon as
the first matching candidate is found in service order.
- `exhaustive`: evaluates all provided identifier/mode combinations across the
selected services, deduplicates candidates, and chooses the best supported
structure group.

## Example

```python
from moleculeresolver import MoleculeResolver

with MoleculeResolver() as mr:
molecule = mr.find_single_molecule(
identifiers=["ethanol", "ethyl alcohol"],
modes=["name", "name"],
search_strategy="exhaustive",
)
```
Loading