Skip to content

[ISSUE-05] Implement SBOL resolver and inventory foundation#72

Merged
Gonza10V merged 3 commits into
full_buildfrom
codex/implement-sbol-resolver-and-inventory-foundation-i2plk2
May 5, 2026
Merged

[ISSUE-05] Implement SBOL resolver and inventory foundation#72
Gonza10V merged 3 commits into
full_buildfrom
codex/implement-sbol-resolver-and-inventory-foundation-i2plk2

Conversation

@Gonza10V
Copy link
Copy Markdown
Contributor

@Gonza10V Gonza10V commented May 5, 2026

Motivation

  • Provide a deterministic, local-first SBOL lookup abstraction and a minimal offline-capable pull policy so stages and planners use identity-based resolution instead of scattered Document lookups.
  • Introduce a normalized, eager Inventory facade that indexes plasmids, backbones, and reagents for fast deterministic queries needed by the full-build pipeline.
  • Keep the change scoped to lookup/indexing contracts (no route selection, scoring, or stage execution) and ensure core imports/tests run offline.

Description

  • Added PullPolicy and a small SbolResolver that resolves SBOL objects from a local sbol2.Document and optionally calls an injected pull_client; exported as buildcompiler.sbol.PullPolicy and buildcompiler.sbol.SbolResolver in src/buildcompiler/sbol/.
  • Implemented Inventory (eager deterministic indexes and incremental generated-product indexing) with the required query helpers and exports in src/buildcompiler/inventory/.
  • Kept domain contracts from existing src/buildcompiler/domain (reused IndexedPlasmid, IndexedBackbone, IndexedReagent, MaterialState, and BuildStage) and relied on a minimal metadata convention for insert identities, fusion sites, antibiotics, and optional backbone stage values.
  • Files changed/added: src/buildcompiler/sbol/resolver.py, src/buildcompiler/sbol/__init__.py, src/buildcompiler/inventory/inventory.py, src/buildcompiler/inventory/__init__.py, tests/unit/sbol/test_resolver.py, and tests/unit/inventory/test_inventory_indexes.py.

Testing

  • Import smoke tests (pass): python -c "from buildcompiler.sbol import SbolResolver, PullPolicy", python -c "from buildcompiler.inventory import Inventory", and python -c "from buildcompiler.api.options import BuildOptions; BuildOptions()" all succeeded.
  • Unit tests (pass): pytest tests/unit/sbol tests/unit/inventory and pytest tests/unit/domain tests/unit/api tests/unit/sbol tests/unit/inventory ran successfully (all tests passed locally).
  • Attempted environment bootstrap with uv run pytest ... failed due to the environment trying to fetch an optional git dependency (SBOLInventory) and being blocked by network/git access (HTTP 403), so uv-based virtualenv setup was not completed in this environment.
  • Quality/lint check ruff check . && ruff format --check . failed due to pre-existing unrelated lint issues elsewhere in the repository (not introduced by this PR) and is left outside the scope of this change.

Codex Task

@Gonza10V
Copy link
Copy Markdown
Contributor Author

Gonza10V commented May 5, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c672344bd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +169 to +171
def add_generated_product(self, product: IndexedPlasmid) -> None:
self.generated_products_by_identity[product.identity] = product
self._add_plasmid(product)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Remove stale index entries before re-adding a product

add_generated_product updates identity maps but then blindly calls _add_plasmid, which appends to all secondary lists without clearing any existing entry for the same product.identity. If the same product is indexed again (e.g., retries or state/metadata updates), lookups like find_single_part_plasmids and find_lvl1_region_plasmids can return duplicate or stale plasmid records, which can cascade into duplicate planning/execution actions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@codex good catch solve this issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

  • Fixed stale/duplicate plasmid secondary-index behavior by adding _remove_plasmid_from_secondary_indexes, which removes old insert/fusion-site/antibiotic mappings for an existing plasmid identity before reindexing. This ensures deterministic replacement instead of append-only duplication when the same generated product is added again. src/buildcompiler/inventory/inventory.pyL69-L120
  • Updated _add_plasmid to detect existing identity entries and clear their old secondary-index references before inserting updated data, while keeping identity map behavior unchanged. src/buildcompiler/inventory/inventory.pyL96-L120
  • Added a regression test that re-adds the same generated product identity with changed metadata and validates old index keys are cleared and new keys contain only the updated record. tests/unit/inventory/test_inventory_indexes.pyL73-L100

Testing

  • pytest tests/unit/inventory/test_inventory_indexes.py

View task →

Comment thread src/buildcompiler/sbol/resolver.py Outdated
Comment on lines +49 to +50
self.maybe_pull(identity)
obj = self.document.find(identity)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use pulled object when local lookup still misses

After maybe_pull(identity) in MISSING_ONLY mode, the resolver only re-checks document.find(...) and ignores the pull return value, so resolution works only if pull_client mutates document as an implicit side effect. A valid pull client that returns the fetched SBOL object directly will still trigger LookupError, even though retrieval succeeded.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@codex good catch, fix that issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

  • Fixed SbolResolver._get so that in both ALWAYS_REFRESH and MISSING_ONLY modes, if pull_client returns an object of the expected SBOL type, that object is returned immediately (instead of requiring document.find(...) to succeed via side effect). This resolves the review feedback at src/buildcompiler/sbol/resolver.py line 50. src/buildcompiler/sbol/resolver.pyL40-L56
  • Added a regression helper pull client (ReturnOnlyPullClient) and a targeted test that verifies MISSING_ONLY resolution succeeds even when the pull client does not mutate the local document. tests/unit/sbol/test_resolver.pyL17-L25 tests/unit/sbol/test_resolver.pyL96-L109
  • Committed changes on the current branch with commit message: Fix resolver to accept pulled SBOL objects directly.
  • Created a follow-up PR entry via make_pr with title: [ISSUE-05 Follow-up] Fix resolver behavior for non-mutating pull clients.

Testing

  • pytest tests/unit/sbol/test_resolver.py

View task →

@Gonza10V Gonza10V merged commit adf2a24 into full_build May 5, 2026
0 of 4 checks passed
@Gonza10V Gonza10V deleted the codex/implement-sbol-resolver-and-inventory-foundation-i2plk2 branch May 5, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant