Codex should implement the BuildCompiler clean-architecture refactor in small, verifiable increments. The goal is not to preserve legacy APIs. The current repository is inspiration and evidence, especially for level-1 assembly and SBOL digestion/ligation behavior.
- Reducing ambiguity.
- Revising architecture and product decisions.
- Breaking work into milestones and tasks.
- Deciding between alternatives when requirements conflict.
- Reviewing whether Codex output matches the intended plan.
- Updating this guidance when product or architecture decisions change.
- Creating and editing repository files.
- Implementing scoped tasks.
- Refactoring within approved boundaries.
- Adding tests.
- Running checks.
- Reporting assumptions, blockers, and deviations.
When a decision changes architecture, product scope, biological behavior, or public API semantics, Codex should stop and ask ChatGPT/user for a decision before continuing.
- Prefer small, incremental changes.
- Keep the project runnable after every task.
- Write tests for non-trivial logic.
- Update docs when architecture, behavior, or commands change.
- Do not preserve legacy APIs unless explicitly requested.
- Do not add compatibility wrappers.
- Do not silently expand scope.
- Do not hide assumptions.
- Do not make PUDU or Opentrons required for core tests.
- Do not run Opentrons simulation by default.
- Do not silently mutate biological sequences.
- Do not silently assume reagent purchase.
- Keep domain contracts identity-based where possible.
- Keep raw
sbol2objects at inventory/SBOL/stage boundaries. - Use
SbolResolverinstead of scattered direct SBOL document lookup. - Use structured blockers, warnings, and approvals instead of raw exceptions for expected build issues.
- Raise unexpected implementation errors by default.
A task is safe for Codex when it has:
- A clear target file or module.
- A clear expected behavior.
- A test strategy.
- No unresolved product or architecture tradeoff.
- No need to choose between incompatible biological semantics.
Examples:
- Add
StageStatus,BuildStatus, and tests. - Implement
BuildOptionsdataclasses. - Create
SbolResolverwithPullPolicy.NEVERunit tests. - Add
Inventory.add_generated_product()and indexing tests. - Port
AssemblybehindAssemblyServicewithout changing internals.
A task is risky when it:
- Changes public API semantics.
- Changes build-stage behavior.
- Changes approval or sequence-edit policy.
- Changes route-selection ranking.
- Changes material-state semantics.
- Touches PUDU/Opentrons execution side effects.
- Requires choosing how SBOL structures should be interpreted.
- Would take more than one focused PR.
Risky tasks should be decomposed or escalated to ChatGPT/user.
Every Codex task should begin with:
Task goal:
Files expected to change:
Behavior expected:
Tests expected:
Known constraints:
Every Codex completion should report:
Implemented:
Tests added/updated:
Commands run:
Assumptions made:
Blockers or follow-up tasks:
If tests cannot be run, Codex must say why and identify the smallest command that should be run later.
Implement in milestone order. Do not jump directly to the full-build loop before contracts and tests exist.
Create:
src/buildcompiler/domain/
src/buildcompiler/api/options.py
Add contracts for:
BuildStageStageStatusBuildStatusMaterialStateBuildRequestStageResultFullBuildResultMissingBuildInputRequiredApprovalBuildWarningIndexedPlasmidIndexedBackboneIndexedReagentBuildOptionsand focused option groups
Tests:
tests/unit/domain/
tests/unit/api/test_options.py
Create:
src/buildcompiler/sbol/resolver.py
src/buildcompiler/inventory/
Implement:
PullPolicySbolResolver- normalized inventory records
- eager indexes
- generated-product indexing
- reagent lookup
- backbone lookup
Tests should use offline SBOL fixtures and PullPolicy.NEVER.
Create:
src/buildcompiler/planning/classifier.py
src/buildcompiler/planning/combinatorial.py
src/buildcompiler/planning/full_build_planner.py
src/buildcompiler/planning/validation.py
Implement classification rules:
ModuleDefinition -> assembly_lvl2
CombinatorialDerivation -> expanded assembly_lvl1 requests
ComponentDefinition >1 component -> assembly_lvl1
ComponentDefinition <=1 component with supported role -> domestication
ComponentDefinition <=1 component unsupported -> unsupported
Implement combinatorial cap and invalid variant warnings.
Create:
src/buildcompiler/inventory/selector.py
src/buildcompiler/inventory/compatibility.py
Implement route scoring dataclasses for level-1 and level-2. Keep scores explicit, not opaque numbers.
Port current working Assembly behavior into:
src/buildcompiler/sbol/assembly.py
Wrap it with:
src/buildcompiler/stages/assembly_lvl1.py
Do not deeply refactor SBOL internals until tests protect the new service interface.
Create:
src/buildcompiler/sbol/domestication.py
src/buildcompiler/stages/domestication.py
Implement:
- supported role validation
- missing backbone handling
- missing reagent handling
- sequence edit proposals
- approval-gated execution behavior
- domesticated plasmid output
Create:
src/buildcompiler/stages/assembly_lvl2.py
Implement:
ModuleDefinitionengineered-region extraction- optional
region_orderconstraint - exhaustive order search up to 4 regions
- missing level-1 promotion
- selected route and top rejected alternatives
Create:
src/buildcompiler/execution/full_build_executor.py
src/buildcompiler/execution/worklist.py
src/buildcompiler/execution/stage_runner.py
src/buildcompiler/execution/context.py
Implement bounded retry loop with mocked/stubbed stages first, then wire real stages.
Create:
src/buildcompiler/stages/transformation.py
src/buildcompiler/stages/plating.py
src/buildcompiler/sbol/transformation.py
Implement SBOL transformation records, PUDU JSON intermediates, plate mapping, and deduplication.
Create:
src/buildcompiler/adapters/pudu/
src/buildcompiler/adapters/opentrons/
src/buildcompiler/reporting/
Implement:
- assembly/transformation/plating JSON adapters
- optional manual/automated protocol file generation
- optional Opentrons simulation wrapper
BuildSummary- opt-in
BuildReport - reporting-only
BuildGraph - end-to-end happy-path fixture test
Use pytest and Ruff for default CI.
Core commands:
uv run ruff check .
uv run ruff format --check .
uv run pytestFallback without uv:
ruff check .
ruff format --check .
pytestAutomation-specific tests should be marked and optional:
pytest -m automationSuggested test layout:
tests/
unit/
domain/
planning/
inventory/
execution/
reporting/
stages/
test_assembly_lvl1.py
test_domestication.py
test_assembly_lvl2.py
test_transformation.py
test_plating.py
integration/
test_full_build_happy_path.py
test_full_build_missing_lvl1_then_domestication.py
automation/
test_pudu_json_adapters.py
test_opentrons_simulation_smoke.py
fixtures/
sbol/
expected_json/
Update docs in the same PR when:
- public API changes
- package layout changes
- option defaults change
- stage behavior changes
- status semantics change
- approval behavior changes
- route scoring changes
- test commands or CI commands change
Create or update an ADR when:
- There are multiple reasonable architecture options.
- A decision changes module boundaries.
- A decision changes biological interpretation.
- A decision changes public API.
- A decision adds or removes a stage.
- A decision changes default safety behavior.
- A decision adds persistent side effects.
Codex should keep progress compact and evidence-based:
Done:
- Added domain status enums and tests.
- Added BuildOptions groups with defaults.
Verified:
- uv run pytest tests/unit/domain tests/unit/api
- uv run ruff check src tests
Assumptions:
- MaterialState.PLANNED ranks below ASSEMBLED and above missing material.
Next:
- Implement SbolResolver with PullPolicy.NEVER tests.
Stop and ask ChatGPT/user before:
- Changing approval semantics.
- Changing level-1 cardinality.
- Supporting new part roles.
- Changing level-2 route scoring.
- Making graph scheduling drive execution.
- Making PUDU/Opentrons required.
- Adding persistent approvals.
- Adding DNA extraction as a real stage.