-
Notifications
You must be signed in to change notification settings - Fork 1
[ISSUE-02] Implement domain enums and result dataclasses #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Gonza10V
merged 2 commits into
full_build
from
codex/implement-domain-enums-and-result-dataclasses
May 5, 2026
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,34 @@ | ||
| """Package scaffolding for clean architecture.""" | ||
| """Domain contracts for BuildCompiler clean architecture.""" | ||
|
|
||
| from .approvals import ApprovalStatus, RequiredApproval | ||
| from .build_request import BuildRequest | ||
| from .build_result import FullBuildResult, StageResult | ||
| from .build_stage import BuildStage | ||
| from .design import DesignKind | ||
| from .material_state import MaterialState | ||
| from .missing_input import MissingBuildInput | ||
| from .plasmid import IndexedBackbone, IndexedPlasmid | ||
| from .reagent import IndexedReagent | ||
| from .status import BuildStatus, StageStatus | ||
| from .warnings import BuildWarning | ||
|
|
||
| __all__ = [ | ||
| "ApprovalStatus", | ||
| "BuildRequest", | ||
| "BuildResult", | ||
| "BuildStage", | ||
| "BuildStatus", | ||
| "BuildWarning", | ||
| "DesignKind", | ||
| "FullBuildResult", | ||
| "IndexedBackbone", | ||
| "IndexedPlasmid", | ||
| "IndexedReagent", | ||
| "MaterialState", | ||
| "MissingBuildInput", | ||
| "RequiredApproval", | ||
| "StageResult", | ||
| "StageStatus", | ||
| ] | ||
|
|
||
| BuildResult = FullBuildResult |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| """Approval contracts for expected gated processes.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from enum import Enum | ||
| from typing import Any | ||
|
|
||
|
|
||
| class ApprovalStatus(str, Enum): | ||
| """Minimal approval state used by RequiredApproval.""" | ||
|
|
||
| REQUIRED = "required" | ||
| APPROVED = "approved" | ||
|
|
||
|
|
||
| @dataclass | ||
| class RequiredApproval: | ||
| """Approval record for a process required to proceed.""" | ||
|
|
||
| status: ApprovalStatus | ||
| process: str | ||
| reason: str | ||
| metadata: dict[str, Any] = field(default_factory=dict) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| """Build request contract dataclass.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from typing import Any | ||
|
|
||
| from .build_stage import BuildStage | ||
| from .design import DesignKind | ||
|
|
||
|
|
||
| @dataclass | ||
| class BuildRequest: | ||
| """Planner-produced request for a single stage/source item.""" | ||
|
|
||
| id: str | ||
| stage: BuildStage | ||
| source_identity: str | ||
| source_display_id: str | None | ||
| source_kind: DesignKind | ||
| parent_group: str | None = None | ||
| variant_index: int | None = None | ||
| constraints: dict[str, Any] = field(default_factory=dict) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| """Stage/full-build result contracts.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from typing import Any | ||
|
|
||
| from .approvals import RequiredApproval | ||
| from .build_stage import BuildStage | ||
| from .missing_input import MissingBuildInput | ||
| from .plasmid import IndexedPlasmid | ||
| from .status import BuildStatus, StageStatus | ||
| from .warnings import BuildWarning | ||
|
|
||
|
|
||
| @dataclass | ||
| class StageResult: | ||
| """Output contract from a single stage invocation.""" | ||
|
|
||
| id: str | ||
| stage: BuildStage | ||
| status: StageStatus | ||
| request_ids: list[str] = field(default_factory=list) | ||
| products: list[IndexedPlasmid] = field(default_factory=list) | ||
| missing_inputs: list[MissingBuildInput] = field(default_factory=list) | ||
| required_approvals: list[RequiredApproval] = field(default_factory=list) | ||
| warnings: list[BuildWarning] = field(default_factory=list) | ||
| sbol_document: Any | None = None | ||
| json_intermediate: dict[str, Any] | list[Any] | None = None | ||
| protocol_artifacts: dict[str, Any] = field(default_factory=dict) | ||
| logs: list[str] = field(default_factory=list) | ||
|
|
||
|
|
||
| @dataclass | ||
| class FullBuildResult: | ||
| """Aggregate full-build output contract. | ||
|
|
||
| Neighboring contracts (plan/graph/summary/report) are intentionally typed | ||
| conservatively until their milestone implementations are added. | ||
| """ | ||
|
|
||
| status: BuildStatus | ||
| plan: Any | ||
| build_document: Any | ||
| stage_results: list[StageResult] = field(default_factory=list) | ||
| graph: Any = None | ||
| final_products: list[IndexedPlasmid] = field(default_factory=list) | ||
| missing_inputs: list[MissingBuildInput] = field(default_factory=list) | ||
| required_approvals: list[RequiredApproval] = field(default_factory=list) | ||
| warnings: list[BuildWarning] = field(default_factory=list) | ||
| summary: Any = None | ||
| report: Any | None = None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| """Build stage enum contracts.""" | ||
|
|
||
| from enum import Enum | ||
|
|
||
|
|
||
| class BuildStage(str, Enum): | ||
| """Planned v1 build stages for full-build execution.""" | ||
|
|
||
| DOMESTICATION = "domestication" | ||
| ASSEMBLY_LVL1 = "assembly_lvl1" | ||
| ASSEMBLY_LVL2 = "assembly_lvl2" | ||
| TRANSFORMATION = "transformation" | ||
| PLATING = "plating" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| """Design identity/type contracts.""" | ||
|
|
||
| from enum import Enum | ||
|
|
||
|
|
||
| class DesignKind(str, Enum): | ||
| """Supported SBOL design source kinds for build requests.""" | ||
|
|
||
| COMPONENT_DEFINITION = "component_definition" | ||
| MODULE_DEFINITION = "module_definition" | ||
| COMBINATORIAL_DERIVATION = "combinatorial_derivation" | ||
| UNSUPPORTED = "unsupported" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| """Material lifecycle states used across stages.""" | ||
|
|
||
| from enum import Enum | ||
|
|
||
|
|
||
| class MaterialState(str, Enum): | ||
| """Normalized lifecycle states for build materials.""" | ||
|
|
||
| PLANNED = "planned" | ||
| GENERATED = "generated" | ||
| ASSEMBLED = "assembled" | ||
| TRANSFORMED = "transformed" | ||
| PLATED = "plated" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| """Missing input/blocker contracts.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from typing import Literal | ||
|
|
||
| from .build_stage import BuildStage | ||
|
|
||
| MissingKind = Literal[ | ||
| "engineered_region", | ||
| "promoter", | ||
| "rbs", | ||
| "cds", | ||
| "terminator", | ||
| "backbone", | ||
| "restriction_enzyme", | ||
| "ligase", | ||
| "reagent", | ||
| ] | ||
|
|
||
|
|
||
| @dataclass | ||
| class MissingBuildInput: | ||
| """Expected blocker produced when build inputs are unavailable.""" | ||
|
|
||
| source_stage: BuildStage | ||
| source_design_identity: str | ||
| missing_identity: str | ||
| missing_display_id: str | None | ||
| missing_kind: MissingKind | ||
| required_stage: BuildStage | Literal["fatal"] | ||
| reason: str | ||
| candidates_tried: list[str] = field(default_factory=list) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| """Normalized plasmid/backbone records.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from typing import Any | ||
|
|
||
| from .material_state import MaterialState | ||
|
|
||
|
|
||
| @dataclass | ||
| class IndexedPlasmid: | ||
| """Inventory/index record for a plasmid-like material.""" | ||
|
|
||
| identity: str | ||
| display_id: str | None = None | ||
| name: str | None = None | ||
| state: MaterialState = MaterialState.PLANNED | ||
| roles: list[str] = field(default_factory=list) | ||
| metadata: dict[str, Any] = field(default_factory=dict) | ||
| sbol_component: Any | None = None | ||
|
|
||
|
|
||
| @dataclass | ||
| class IndexedBackbone: | ||
| """Inventory/index record for a backbone material.""" | ||
|
|
||
| identity: str | ||
| display_id: str | None = None | ||
| name: str | None = None | ||
| metadata: dict[str, Any] = field(default_factory=dict) | ||
| sbol_component: Any | None = None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| """Normalized reagent record contracts.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from typing import Any | ||
|
|
||
|
|
||
| @dataclass | ||
| class IndexedReagent: | ||
| """Inventory/index record for reagents.""" | ||
|
|
||
| identity: str | ||
| display_id: str | None = None | ||
| name: str | None = None | ||
| reagent_type: str | None = None | ||
| metadata: dict[str, Any] = field(default_factory=dict) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| """Status enums and contract-level semantics helpers.""" | ||
|
|
||
| from enum import Enum | ||
|
|
||
|
|
||
| class StageStatus(str, Enum): | ||
| """Status for a single stage result. | ||
|
|
||
| BLOCKED means expected inputs or approvals can unblock this stage later. | ||
| FAILED means the request cannot proceed without changing design/options/ | ||
| collections/approval state. | ||
| """ | ||
|
|
||
| SUCCESS = "success" | ||
| PARTIAL_SUCCESS = "partial_success" | ||
| BLOCKED = "blocked" | ||
| FAILED = "failed" | ||
|
|
||
|
|
||
| class BuildStatus(str, Enum): | ||
| """Status for full-build aggregate results.""" | ||
|
|
||
| SUCCESS = "success" | ||
| PARTIAL_SUCCESS = "partial_success" | ||
| FAILED = "failed" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| """Domain warning contracts.""" | ||
|
|
||
| from dataclasses import dataclass, field | ||
| from typing import Any | ||
|
|
||
| from .build_stage import BuildStage | ||
|
|
||
|
|
||
| @dataclass | ||
| class BuildWarning: | ||
| """Structured non-fatal warning for planning/execution/reporting.""" | ||
|
|
||
| code: str | ||
| message: str | ||
| stage: BuildStage | None = None | ||
| source_identity: str | None = None | ||
| metadata: dict[str, Any] = field(default_factory=dict) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| from buildcompiler.domain import ( | ||
| ApprovalStatus, | ||
| BuildRequest, | ||
| BuildStage, | ||
| BuildStatus, | ||
| BuildWarning, | ||
| DesignKind, | ||
| MissingBuildInput, | ||
| RequiredApproval, | ||
| StageResult, | ||
| StageStatus, | ||
| ) | ||
|
|
||
|
|
||
| def test_enum_values_and_planned_stages(): | ||
| assert StageStatus.BLOCKED.value == "blocked" | ||
| assert StageStatus.FAILED.value == "failed" | ||
| assert BuildStatus.SUCCESS.value == "success" | ||
| assert BuildStage.ASSEMBLY_LVL1.value == "assembly_lvl1" | ||
| assert BuildStage.DOMESTICATION.value == "domestication" | ||
| assert BuildStage.ASSEMBLY_LVL2.value == "assembly_lvl2" | ||
| assert BuildStage.TRANSFORMATION.value == "transformation" | ||
| assert BuildStage.PLATING.value == "plating" | ||
|
|
||
|
|
||
| def test_blocked_vs_failed_semantics_are_documented_as_contract_data(): | ||
| blocked = MissingBuildInput( | ||
| source_stage=BuildStage.ASSEMBLY_LVL1, | ||
| source_design_identity="sbol://design/x", | ||
| missing_identity="sbol://part/y", | ||
| missing_display_id="y", | ||
| missing_kind="cds", | ||
| required_stage=BuildStage.DOMESTICATION, | ||
| reason="Input could be generated by upstream stage", | ||
| ) | ||
| failed = MissingBuildInput( | ||
| source_stage=BuildStage.ASSEMBLY_LVL1, | ||
| source_design_identity="sbol://design/x", | ||
| missing_identity="sbol://part/z", | ||
| missing_display_id="z", | ||
| missing_kind="cds", | ||
| required_stage="fatal", | ||
| reason="Unsupported design cannot proceed without changes", | ||
| ) | ||
|
|
||
| assert blocked.required_stage != "fatal" | ||
| assert failed.required_stage == "fatal" | ||
|
|
||
|
|
||
| def test_default_mutables_are_isolated_across_instances(): | ||
| req1 = BuildRequest("r1", BuildStage.DOMESTICATION, "a", None, DesignKind.COMPONENT_DEFINITION) | ||
| req2 = BuildRequest("r2", BuildStage.DOMESTICATION, "b", None, DesignKind.COMPONENT_DEFINITION) | ||
| req1.constraints["x"] = 1 | ||
| assert req2.constraints == {} | ||
|
|
||
| s1 = StageResult("s1", BuildStage.DOMESTICATION, StageStatus.SUCCESS) | ||
| s2 = StageResult("s2", BuildStage.DOMESTICATION, StageStatus.SUCCESS) | ||
| s1.request_ids.append("r1") | ||
| s1.products.append(object()) | ||
| s1.missing_inputs.append( | ||
| MissingBuildInput(BuildStage.DOMESTICATION, "a", "b", None, "promoter", "fatal", "missing") | ||
| ) | ||
| s1.required_approvals.append(RequiredApproval(ApprovalStatus.REQUIRED, "biosafety", "needed")) | ||
| s1.warnings.append(BuildWarning("warn", "msg")) | ||
| s1.protocol_artifacts["x"] = "y" | ||
| s1.logs.append("log") | ||
|
|
||
| assert s2.request_ids == [] | ||
| assert s2.products == [] | ||
| assert s2.missing_inputs == [] | ||
| assert s2.required_approvals == [] | ||
| assert s2.warnings == [] | ||
| assert s2.protocol_artifacts == {} | ||
| assert s2.logs == [] | ||
|
|
||
| a1 = RequiredApproval(ApprovalStatus.REQUIRED, "biosafety", "needed") | ||
| a2 = RequiredApproval(ApprovalStatus.APPROVED, "biosafety", "granted") | ||
| a1.metadata["id"] = "1" | ||
| assert a2.metadata == {} | ||
|
|
||
| w1 = BuildWarning("w1", "warning") | ||
| w2 = BuildWarning("w2", "warning") | ||
| w1.metadata["code"] = "X" | ||
| assert w2.metadata == {} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The project metadata still advertises
requires-python = ">=3.7", but this new contract class uses 3.10-only annotation syntax (str | None) without postponed annotation evaluation, so importingbuildcompiler.domainwill fail on supported interpreters (3.7–3.9) at class-definition time. This turns a previously importable package namespace into an import-time error for those environments; either add compatibility-friendly annotations (Optional[...], etc. orfrom __future__ import annotations) or bump the declared minimum Python version.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@codex Good catch, lets change the declared minimum Python version to 3.10 onwards
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary
requires-pythonfrom>=3.7to>=3.10inpyproject.toml, matching the 3.10-style type-union syntax already present in the domain contracts.e994682) and created a follow-up PR with title[ISSUE-02 follow-up] Bump declared Python minimum to 3.10.Testing
python -m py_compile src/buildcompiler/domain/build_request.pygit diff -- pyproject.toml(verified only the Python version metadata line changed)View task →