Skip to content

DDOS-8122: ADMET 2.x SDK bulk, async, and project runs - #650

Open
sg-s wants to merge 8 commits into
mainfrom
ddos-8122-admet-2x-sdk
Open

sg-s wants to merge 8 commits into
mainfrom
ddos-8122-admet-2x-sdk

Conversation

@sg-s

@sg-s sg-s commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Pin deeporigin.admet-properties to tool major 2 and extend Admet for 2.x: run() for ≤100 ligands (sync), start()/wait() for 101+ with auto ligands_file + ligands_count, and project-wide runs via Admet(ligands=[]) scoped to client.project_id.
  • Docking-style Quoted handling on run() (None + confirm()), workflow get_results() via admetproperty result-explorer with jobOutputs fallback, and from_dto for file/project inputs.
  • Molprops: fraction_csp3 key; load sa_score / fraction_csp3 from platform pins; docs (docs/dd/tools/admet.md, molprops/ligand copy); mock async ADMET path; remove legacy per-property molprops fixture folders.

Merge-ready status

Auto-updated — cycle 3, last updated: 2026-10-01T00:45:00Z

Check Status
Branch vs main ✅ synced at 59095f7
Head 6604664f
CI (required) ✅ formatting + Ubuntu 3.12/3.13
Copilot ✅ reviewed 6604664f, 0 open threads
Review threads 0

Recent activity

  • Fixed make test (run(quote=True) skips ligand sync).
  • Addressed Copilot round 1 + mock project ADMET / hydration tests on 6604664f.
  • Required checks green; staging/prod level-1 and Sonar dashboard are non-blocking flakes/history.

Test plan

  • uv run pytest --env local tests/test_admet_local.py tests/test_admet_unit.py
  • uv run pytest --env local tests/test_molprops_local.py tests/test_molprops.py
  • make test (local)

Links

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Blocking sync and async lifecycle defects can prevent capped runs and duplicated jobs from completing correctly.

Review effort: Balanced
Findings: 2 High severity · 3 Medium severity · 2 Low severity

Open (7)
What changed in this PR

Extends ADMET 2.x support with synchronous, bulk asynchronous, and project-wide execution paths, plus Molprops fields and documentation.

Changes:

  • Adds ADMET bulk uploads, async workflows, quotations, and result-explorer retrieval.
  • Adds fraction_csp3 and platform-pinned Molprops fields.
  • Updates mock infrastructure, tests, fixtures, and user documentation.
File Description
tests/​test_admet_local.py Expands ADMET integration tests.
tests/​mock_server/​routers/​tools.py Simulates ADMET async execution and results.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-pains/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy PAINS fixture.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-logs/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy LogS fixture.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-logp/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy LogP fixture.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-logd/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy LogD fixture.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-herg/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy hERG fixture.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-cyp/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy CYP fixture.
tests/​fixtures/​tool-runs/​deeporigin.mol-props-ames/​70456ca2628ceb7811e86e82fb2b0064e2a065e2afb7e03ef19694c803b84fc1.json Removes legacy AMES fixture.
src/​utils/​constants.py Adds ADMET limits and Molprops key.
src/​platform/​constants.py Pins ADMET to major version 2.
src/​drug_discovery/​structures/​ligand.py Adds and hydrates new Molprops attributes.
src/​drug_discovery/​admet.py Implements ADMET 2.x execution workflows.
docs/​dd/​tools/​molprops.md Documents updated Molprops capabilities.
docs/​dd/​tools/​admet.md Adds ADMET usage documentation.
docs/​dd/​ref/​ligand.md Documents new ligand attributes.
docs/​dd/​how-to/​ligands.md Documents bulk ADMET workflows.
CONTEXT.md Updates architectural context for ADMET 2.x.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/drug_discovery/admet.py
Comment thread tests/test_admet_local.py Outdated
Comment thread src/drug_discovery/admet.py Outdated
Comment thread src/drug_discovery/admet.py Outdated
Comment thread src/utils/constants.py
Comment thread src/drug_discovery/admet.py Outdated
Comment thread tests/test_admet_local.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Project-wide executions produce no mock results, preventing the documented local end-to-end workflow from succeeding.

Review effort: Balanced
Findings: None

Resolved since last review (7)
Previously missed (3)

In code that hasn't changed since last review

Medium severity Resolve project inputs before generating mock prediction rows

tests/​mock_server/​routers/​tools.py:1699

Project-wide inputs never produce mock predictions here: _admet_prediction_rows_from_inputs() only resolves ligands/ligands_file, so inputs={"project": ...} yields rows=[]. The execution then completes with no result-explorer records (and quotes it as one billable ligand), making the documented start() → wait() → get_results() project flow fail under --env local. Resolve the project's mock ligands before synthesizing rows, and extend the project test through get_results().

Low severity Remove unreachable empty-ligand validation branch

src/​drug_discovery/​admet.py:519

This branch is unreachable because _is_project_run() is exactly len(self._ligands) == 0 and already returns via the exception above. Removing it avoids implying that an empty ligand list can reach a different validation path.

Low severity Test platform hydration for sa_score and fraction_csp3

src/​drug_discovery/​structures/​ligand.py:120

The existing pinned-molprops hydration test does not exercise either newly added mapping, even though this PR promises loading both sa_score and fraction_csp3 from platform records. Add both fields to test_ligand_from_platform_record_hydrates_molprops and assert the resulting named attributes, so platform-key or attribute regressions are covered separately from the combined-tool response test.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The quoted-confirmation workflow omits required completion polling in several documents and lacks end-to-end coverage.

Review effort: Balanced
Findings: None

Previously missed (5)

In code that hasn't changed since last review

Medium severity Test confirm, wait, and get_results workflow

tests/​test_admet_local.py:314

This test stops at Quoted, so the newly documented confirmation path is untested; in particular, it would not catch fetching results before confirmation has finished. Exercise confirm(), wait(), and get_results() here.

Low severity Document polling before retrieving results

CONTEXT.md:32

A confirmed quote may transition to Running, so get_results() is not yet available. Record the polling step here to avoid encoding an invalid SDK workflow in the project context.

Low severity Wait for execution completion before fetching results

docs/​dd/​how-to/​ligands.md:613

This sequence can fetch results before a confirmed execution completes. Add wait() or watch() between confirmation and result retrieval.

Low severity Add wait/watch before retrieving execution results

docs/​dd/​tools/​admet.md:42

Confirmation starts the execution and can return while it is still Running; get_results() at that point has no rows. Include the required wait/watch step in this workflow.

Low severity Scope exception message to statuses reaching this branch

src/​drug_discovery/​admet.py:609

The Quoted case already returns at line 600, so this exception can never be raised for that status. The confirmation guidance is therefore misleading for the actual failure states reaching this branch; keep the message scoped to the observed status and execution ID.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Negative quote amounts still mutate ligands, and several lifecycle and documentation inconsistencies remain.

Review effort: Balanced
Findings: None

Previously missed (7)

In code that hasn't changed since last review

Medium severity Handle all negative approval amounts as quote-only

src/​drug_discovery/​admet.py:591

The quote-only check only recognizes -1, but the execution API treats any negative approve_amount as quote-only. For example, run(approve_amount=-2) registers and mutates the ligands even though no inference runs. Skip synchronization for every negative amount.

Low severity Document conditional polling after confirmation

CONTEXT.md:32

This abbreviated workflow omits polling after confirm(), although confirmation may leave ADMET running. Keep the context contract accurate by mentioning the conditional wait before result retrieval.

Low severity Tell users to wait when confirmation is nonterminal

docs/​dd/​how-to/​ligands.md:613

A confirmation is not guaranteed to complete the execution; ADMET confirmation is Running in the local mock. Calling get_results() immediately can therefore report missing predictions. Tell users to wait when status is nonterminal.

Low severity Wait for nonterminal executions before retrieving results

docs/​dd/​tools/​admet.md:42

confirm() can return while the ADMET execution is still running, so this sequence can call get_results() before any rows exist. Include wait()/watch() when confirmation is nonterminal.

Low severity Document waiting after nonterminal confirmation

src/​drug_discovery/​admet.py:581

confirm() may leave an execution in Created or Running (and the mock confirmation route does so for ADMET), so an immediate get_results() can raise because neither result-explorer nor jobOutputs has rows yet. Document the required wait for nonterminal confirmations.

Low severity Document the newly exposed fraction_csp3 attribute

src/​drug_discovery/​structures/​ligand.py:261

The public class documentation’s exhaustive Molprops attribute list still ends at sa_score, so the newly exposed fraction_csp3 field is omitted. Add it to the list near src/drug_discovery/structures/ligand.py:225.

Low severity Update ADR to reflect the dependency version change

src/​platform/​constants.py:164

The accepted ADR at docs/adr/0004-admet-properties-from-tool-definition.md:10-24 explicitly says this pin remains "latest" and explains why. Pinning major 2 leaves that architectural record false; update or supersede the ADR as part of this change.

@ASinanSaglam ASinanSaglam self-assigned this Oct 1, 2026
sg-s and others added 7 commits October 1, 2026 15:11
…ops fixes

Extend Admet for tool v2 (pin major 2): sync run up to 100 ligands, workflow
start for 101+ with auto ligands_file, project-wide runs via empty ligands and
client.project_id, Docking-style Quoted handling, and admetproperty results.
Add fraction_csp3 molprops support, sa_score platform load, docs, mock async
path, and remove legacy per-property fixture folders.
Quote-only runs should not register ligands on the platform before
estimating cost, matching SecondaryPharmacology and test_admet contract.
Keep run() sync blocking; hydrate async start from DTO; reset status on
duplicate; skip ligand sync only for quote. Extend mock molprops for
fraction_csp3 and async ADMET wait coverage.
Resolve project inputs in the ADMET mock synthesizer, exercise project
start/wait/get_results locally, and cover sa_score/fraction_csp3 platform
hydration. Drop unreachable run() empty-ligand guard.
- Stub _ensure_run_ligand_count / _ensure_platform_inputs in the BALTO-447
  restriction test; Admet.run() now calls both before submit.
- Sonar S8513: single endswith() with a tuple.
- ADR 0004: tool_version is pinned to major "2", not "latest".
- admet.md: define the ligand set used in the bulk example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…olism _ligand_payloads (DDOS-8122)

Sonar gate on 1792911: new_coverage 77.3% (<80), new_duplicated_lines_density
3.7% (>3). admet._ligand_payloads was a 13-line copy of
metabolism._ligand_payloads; import it instead. Add unit tests for
_ligands_from_list_file_bytes (valid + corrupt bodies) and
_rows_from_result_explorer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch had an error being deployed

2 failed and 2 active deployments
staging — dab1f764 Deployed Oct 2, 2026 by ASinanSaglam via level-1-tests (3.13, staging) #880
prod — dab1f764 Deployed Oct 2, 2026 by ASinanSaglam via level-1-tests (3.13, prod) #880
docs — dab1f764 Deployed Oct 1, 2026 by ASinanSaglam via build-docs #838
dev — dab1f764 Deployed Oct 1, 2026 by ASinanSaglam via level-1-tests (3.13, dev) #880
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-ready All merge-ready checks passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants