6. Core Atomic Operators and Call Contracts
Operator and call contracts specify:
- operation name
- input parameter names and parameter types
- return type policy
6.1 Source Forms and Operator Contracts
- Surface sugar is defined in Chapter 4 and exists for source ergonomics.
- Source authoring truth is the combination of Chapter 4 source forms and the statement/operator contract set in
6.3.7-6.3.20. - The contracts in
6.3.7-6.3.20govern source-level operator behavior; historical frontend spellings are accepted only when listed as compatibility inputs.
6.2 Contract Type Notation
6.2.1 Argument Type Aliases
Container: abstract logical container handle identifying a container and its tracked material stateTubeContainer: concreteContainerkind for tube-like vesselsWellContainer: concreteContainerkind for plate-well vesselsContent: logical content identity handle (independent of container position)ContentKind: enum of canonical material families (§6.2.5 and §6.2.7)Text: free-form text (STRING)Bool: boolean valueScalar: unitless numeric scalarQ[Volume]: quantity with volume unitQ[Mass]: quantity with mass unitQ[Temperature]: quantity with temperature unitQ[Time]: quantity with time unitQ[Count]: discrete-count quantity; the initial supported domain unit iscellsQ[Volume|Mass|Count]: quantity constrained to a material amount axisList[Container]: list of logical containersList[Text]: list of text valuesQuantity: quantity value with supported unit family (general form)Record: key-value map for structured metadata fieldsContainerContents: target view selecting the material contents carried by a containerContainerStructureFacet: target view selecting one physical container-structure facetContainerTargetView:ContainerContents | ContainerStructureFacetHoldTarget: environment-hold target;Container,ContainerTargetView, or a group composed of those targetsContainerGroup: flat, ordered group of resolvableContainervaluesContentType: enum of canonical material types (§6.2.6 and §6.2.7)ContainerKind: enum of concrete container kinds (§6.2.4 and §6.2.7)LegacyText: a bare token or text value admitted by the classification compatibility rules (§6.2.7–8)PlateCarrier: a plate identity, distinct from its individual content-bearing wells and their ordered groups
ContainerGroup static indexing contract:
group_ref[i]requires a compile-time decidable non-negative integeri.- The result is the existing container at ordered position
i; indexing does not allocate, copy, or reconstruct a container. - A statically known index outside the group cardinality is rejected before execution.
- Plate selector-derived groups use selector expansion order and therefore preserve the selected well's original carrier identity.
6.2.2 Return Type Aliases
Void: no required return objectContainer: resulting logical containersep_container_group: fixed two-slot separation result handlefraction_group: ordered multi-slot fractionation result handledata_ref: single readout result handledata_group_ref: grouped readout result handle
6.2.3 Container Content Contract
Container content state records the current aggregate volume and mass, material identities and their quantities, and relevant metadata such as density and carrier position. Material quantities retain their dimension and unit. This contract specifies the information preserved, independently of its storage representation. The aggregate contents volume is readable without changing material state. A read reflects the modeled amount after preceding material operations; it does not report container capacity or constitute a physical measurement.
Container target-accessor surface:
container.contentsdenotes the material contents carried by the container.container.structure.topdenotes the top structural facet of the container.container.structure.bottomdenotes the bottom structural facet of the container.container.structure.sidewalldenotes the sidewall structural facet of the container.container.structureby itself is a target-view namespace, not a complete target view.container.structure.topis closure-agnostic. For closed vessels it may correspond to the cap/seal-facing top structure; for open vessels it denotes the upper rim/top structural facet, not headspace air and not liquid surface.- A bare
containerused as aHoldTargetdefaults to the content-facing target view, equivalent tocontainer.contentsfor env-hold semantics. - Container target views are not material container aliases; they do not carry volume, mass, or components and must not be used as mutation targets or as
sep/frac/img/ecp/phy/stream/agitsample inputs unless a future operator explicitly accepts target-view types. container.contents[i]is the defined exception for mutation source position: it selects an indexed, container-backed source portion from the container's current contents state.- These accessors are direct target views, not
partition(...)-style methods and not materialized child containers. - No deeper structure path is defined.
container.structure.top.innerand device-like aliases such ascontainer.lidare not container target-view accessors.
Carrier information identifies the carrier kind, carrier identity, and position (for example plate well A1). A declared container capacity is an upper volume bound and applies to every operation that increases the contained volume.
6.2.4 Container/Carrier and Content Taxonomy
Container taxonomy rules:
Containeris an abstract handle type, not a user-mutable object/class.- Concrete container kinds are
tube,well,chamber, andsurface. platedenotes a carrier identity; material state belongs to its individual well containers. Carrier identity follows the declaration rules in §4.5.1.- Built-ins must accept abstract
Containerhandles and remain independent of frontend sugar spellings.
Content taxonomy rules:
- Content identity/classification is represented as
Contentrecords and container-linked content state. - Recommended content fields:
content_kind,content_type,content_code,content_name, andattrs. content_kindis a closed mid-level material family and answers "what family of material is this?".content_typeis a closed canonical material category withincontent_kindand answers "what material category is this?".content_codeandcontent_nameidentify/display the concrete instance; they are not taxonomy fields.attrsis the open metadata record for state, source, preparation, concentration, composition detail, andattrs.role.attrs.roleis the role field. It is not promoted to a top-levelroleargument in this baseline. Standard metadata may useContentRole,ContentStateandBeadPropertymembers in the correspondingrole,stateandbead_propertyfields. Member names use uppercase canonical spellings, for exampleContentRole.CULTURE,ContentState.SUSPENSION, andBeadProperty.MAGNETIC. Role members reflect the existing recommendation table;washandwashingremain distinct andpH_adjusterretains its spelling. Initial state members include suspension, solution, stock, extract and reaction_assembled; the standard bead property is magnetic. Standard strings retain their existing persisted representation. Unknown text, other metadata forms and unrelated attribute keys remain subject to the existing open-metadata contract, not a new closed whitelist. Explicit members must belong to the field's domain. Installed extensions retain stable domain identity, version and member data when stored; they are metadata declarations, not new physical-state or scientific behavior. Recommendation rows do not become mandatory combinations, and a stored extension identity must not cause automatic code loading.- Source-level family constructors (
blood/reagent/buffer) are compatibility/ergonomic sugar and do not define canonicalcontent_kindnames by themselves.
6.2.5 Canonical Content Kind Set
content_kind set used by strict-mode validation:
bio_entitybio_fluidbio_cellularbio_subcellularbio_molecule_or_viruschemicalparticulateformulation
Mode note:
- Strict-mode conformance uses this exact whitelist.
- Authoring examples and conformance claims must stay within this whitelist.
- Legacy inputs such as
biosample,reagent,buffer,control,waste, orfractionare compatibility inputs only when legacy normalization mode is explicitly enabled.
6.2.6 Canonical content_type and attrs.role Table
This table defines the canonical material taxonomy. attrs.role contains recommended role values for that kind/type. It is optional, remains within the open attrs record, and is not a top-level constructor parameter. The recommendation table does not restrict a material to the listed roles.
| content_kind | canonical content_type | recommended attrs.role values |
|---|---|---|
bio_entity | organism, organ, tissue, other_bio_entity | material |
bio_fluid | whole_blood, plasma, serum, buffy_coat, urine, saliva, lymph, cerebrospinal_fluid, tears, semen, ascites, synovial_fluid, bronchoalveolar_lavage_fluid, other_body_fluid | material |
bio_cellular | cell_line, primary_cells, cell_population, microbial_cells, other_cellular_material | material |
bio_subcellular | organelle, membrane, vesicle, cytoskeletal_structure, other_subcellular_structure | sample |
bio_molecule_or_virus | dna | sample, template, primer, probe, marker, standard, vector |
bio_molecule_or_virus | rna | sample, template, guide, probe, marker, standard |
bio_molecule_or_virus | protein | sample, antibody, enzyme, cytokine, marker, standard, antigen |
bio_molecule_or_virus | virus | sample, vector |
bio_molecule_or_virus | other_biomolecule_or_virus | sample |
chemical | organic_compound | substrate, inhibitor, activator, fixative, selection, precipitation, crowding_agent, matrix_component |
chemical | inorganic_compound | salt, pH_adjuster, ion_source, cofactor |
chemical | solvent | solvent, carrier, extraction, fixative |
chemical | detergent | lysis, permeabilization, washing, solubilization |
chemical | dye | stain, detection, tracking |
chemical | other_chemical | material |
particulate | beads | capture, cleanup, purification, enrichment |
particulate | resin | affinity_purification, chromatography, capture |
particulate | particle | labeling, calibration |
particulate | other_particulate | material |
formulation | medium | culture, maintenance |
formulation | buffer | wash, elution, binding, lysis, storage, reaction_environment |
formulation | supplement | supplement, selection, growth_factor |
formulation | master_mix | reaction_mix |
formulation | gradient_medium | density_gradient_separation |
formulation | other_formulation | material |
Normalization rules:
content_typevalues SHOULD use lowercase snake_case for stable matching.- Display labels (human-readable) MAY be stored separately in metadata.
content_typeis closed by the canonical table. Unknown or lab-local material categories should use the appropriate canonicalother_*type plusattrs,code, andname.- Non-standard
attrs.rolevalues MAY be recorded as ordinary attr metadata; unknown attr keys remain allowed becauseattrsis open metadata. - Specific identities such as mitochondrion, exosome, plasmid, amplicon, peptide, polymer class, bead material, unusual body-fluid identity, or virus form belong in
attrswhen they are more specific than the canonicalkind/typetable. - Preparation or state labels such as pellet, suspension, lysate, stock, diluted, purified, or amplified belong in
attrs.stateor a more specific attr key, not incontent_type. - Workflow labels such as control, waste, fraction, wash, elution, binding, lysis, detection, or capture belong in
attrs.role,attrs.disposition, or operation-return metadata, not incontent_kind. - Legacy aliases or previously accepted unknown/custom type strings are compatibility inputs; legacy normalization mode should emit a warning and normalize to canonical
content_kind, canonicalcontent_typeincluding another_*fallback when needed, andattrs.
Examples:
content(kind = bio_fluid, type = whole_blood, code = "WB-001")
content(kind = bio_fluid, type = synovial_fluid, code = "SF-001")
content(kind = formulation, type = buffer, code = "PBS-001", attrs = { role: wash })
content(kind = bio_molecule_or_virus, type = protein, code = "AB-001", attrs = { role: antibody })
content(kind = bio_molecule_or_virus, type = dna, code = "PRIMER-001", attrs = { role: primer })
content(kind = bio_fluid, type = other_body_fluid, code = "AF-001", attrs = { fluid_identity: amniotic_fluid })6.2.7 Explicit Content Enum Contract
ContentKind, ContentType, and ContainerKind are distinct enum families. Their members are named by uppercasing the canonical tokens in §6.2.4–6. For example, ContentKind.FORMULATION, ContentType.MEDIUM, and ContainerKind.TUBE denote the corresponding classification values. Member names are case-sensitive. A member of one family MUST NOT be accepted in a position requiring another family, even if their textual representations match.
A content classification consists of a kind and a type from that kind's canonical set. Invalid members and invalid kind/type pairs MUST be rejected. If either argument is an explicit enum, compatibility normalization MUST NOT repair an invalid pair.
Bindings follow the language's lexical scope rules. Local bindings shadow enum namespaces; aliases and parameter defaults preserve enum family and value. Assignments MUST preserve the binding's enum family. An alias captures the value at its declaration, so subsequent assignment to the original binding does not change the alias. Where a branch or loop can change a value, validation MUST consider the value that reaches the use rather than assume an earlier value still applies.
Bare canonical tokens and quoted canonical strings are accepted in both strict and compatibility taxonomy modes. Noncanonical legacy inputs are admitted only in compatibility mode and are subject to §6.2.8. These compatibility forms do not add enum members.
A classification MUST be valid before it is recorded as material state. Static errors are rejected when decidable; values determined only during execution are checked before the affected material write. Serialization and restoration MUST preserve enum family and value wherever subsequent classification checks depend on them. Material-record classification fields use canonical text values; unknown historical values MUST NOT be treated as valid canonical classifications. Diagnostic placement is specified in Chapter 8.
Example:
protocol EnumMedium {
let medium = container(kind = ContainerKind.TUBE, capacity = 5mL, load = [
content(kind = ContentKind.FORMULATION, type = ContentType.MEDIUM,
code = "DMEM_F12_COMPLETE", attrs = { role: culture }):4mL
]);
}
EnumMedium();6.2.8 Selected Legacy Normalization Conformance Cases
The following cases specify representative legacy conversions. They are not additional canonical members or an exhaustive alias list. The fallback for each canonical kind is its unique other_* type in §6.2.6. Conversion preserves the original kind/type and inferred attributes; explicitly supplied attributes take precedence when material is defined.
| legacy kind | legacy type | canonical kind | canonical type | inferred attrs |
|---|---|---|---|---|
biosample | dna_stock | bio_molecule_or_virus | dna | {"state":"stock"} |
biosample | cell_pellet | bio_cellular | other_cellular_material | {"state":"pellet"} |
buffer | wash_buffer | formulation | buffer | {"role":"wash"} |
reagent | enzyme | bio_molecule_or_virus | protein | {"role":"enzyme"} |
blood | lab_local | bio_fluid | whole_blood | {} |
formulation | lab_local | formulation | other_formulation | {"original_type":"lab_local"} |
chemical | medium | chemical | other_chemical | {"original_type":"medium"} |
waste | lab_local | formulation | other_formulation | {"disposition":"waste","original_type":"lab_local"} |
Historical material plans may retain the generic container kind. It is not an additional source-level ContainerKind member. Compatibility of source forms and compatibility of historical records are independent contracts.
6.3 Global Call Rules
These rules apply to every call, including constructor expressions nested in load items and expressions reached through aliases.
- All required args
MUSTbe provided. - Provided args
MUSTbe in the allowed arg set. Open records such asattrsdo not make the call's top-level parameter set open. - Duplicate arg names
MUSTbe rejected; an implementation MUST NOT silently choose one occurrence. - Quantity args
MUSTsatisfy declared dimension constraints. Containerargs resolve to runtime container identity and operate on container content state.- For volume-increasing writes, the resulting volume
MUSTnot exceed the target container's declared capacity. - A declared capacity
MUSTbe positive. - Equivalent source forms
MUSTpreserve the same argument, quantity, identity, and effect contracts.
Capacity enforcement:
- Capacity rules above are enforced through explicit capacity normalization and overflow diagnostics.
6.3.1 Initialization and Operations
Initialization establishes container and content identities, initial quantities, and metadata. Operations consume these declared values to move or organize material, apply environmental conditions and execution requirements, or obtain readouts. Both are governed by the argument types and quantity rules in this chapter; their internal execution representation is implementation-defined.
6.3.2 Semantic Domain Layering
Operations are classified by execution semantic domain.
Domain definitions:
material: operation primarily updates container material state (aggregate quantities, material identities and quantities, and metadata).bridge: operation consumes container state and also produces structured analytical/process payload.data: operation consumes only data payloads/records and does not read/write container material state.
Built-in mapping:
| Operation | Semantic Domain | Primary state effect |
|---|---|---|
<< | material | move/merge material across containers |
sep | material | split material into a fixed two-slot indexed group |
frac | material | split material into an ordered indexed group |
stream | material | convert a macro sample into a unit stream |
img / ecp / phy | bridge | consume container state and emit data_ref / data_group_ref |
constraint | semantic policy | attach device-independent execution requirements to a scope or single step |
Domain boundary note:
bridgeoperators are container-addressed; they are not pure data operators.- Pure
dataoperators are reserved for future vocabulary extension and are not part of built-ins.
6.3.3 Equivalent Source Forms
- Chapter 4 defines source syntax; this chapter defines its accepted arguments and effects.
- Container constructors and inline content declarations establish the identities and initial quantities described in §6.3.4.
target << [sources...]is the source form for transfer and merge behavior.- Historical calls such as
Transfer(...),Mix(...), andDilute(...)are not accepted source forms.
6.3.4 Container and Content Initialization
- A container constructor creates a new logical container identity. Its declared kind, capacity, closure state, and metadata describe that container.
- A
content(...)declaration establishes material identity and classification independently of container position. Classification follows §6.2.7–8. - Each item in
loadassigns a declared material quantity to the container. The quantity must use a supported volume, mass, or count axis. - Descriptive metadata does not by itself change material quantity.
opendeclares the initial closure state;loaddeclares the initial contents. The source forms and accepted constructor arguments are defined in Chapter 4.cellsis valid only for content classified asbio_cellular; directly authored count loadsMUSTbe non-negative integers.- A count load does not itself add volume. A free count-only cellular population may acquire an inferred carrier volume under the declared carrier-assumption policy. Any such volume participates in capacity checks, and its assumed origin must remain explicit.
6.3.5 Mutation Statement Sugar Contract (<<)
Container mutation sugar contract:
Surface forms:
target << [s1, s2, ...]target << [s1:q1, s2:q2, ...]group_target << [series(src_ref, [q1, q2, ...])]target << [source.partition(program_expr)[i]: q]target << [container.contents[i]]target << [container.contents[i]: q]
Contract rules:
[]denotes the mutation source list. It is a statement-specific source-list form, not an ordinary list literal.- Full-transfer (
src) and quantified (src:Q) items may appear in the same source list. They are applied in source-list order as one mutation step; material-state changes are committed only if every item succeeds. - Quantified mode requires unit-bearing quantities, including expression results governed by Section 11.2.1.
series(...)is the sole ordered-mapping surface form.series(...)is valid only when the target is acontainer_group_ref.series(src_ref, [v1, ...])requires cardinality equality between target-group size and value-list length.- Ordinary
[...]source-list semantics remain unchanged and do not imply ordered mapping. - If an ordinary source item resolves to the same container as
target, that source item is valid and evaluates as a no-op rather than a validation/runtime error. source.partition(program_expr)[i]is a source-local selector form; its accepted program set and selector semantics are defined in Section 6.3.11.container.contents[i]is a container-backed contents-portion selector valid only as a mutation source item. It does not create a child container and does not make barecontainer.contentsa material container alias.- If
container.contents[i]resolves to the same container astarget, the material transfer is a no-op but the current indexed contents state is disturbed and must not be reused for latercontainer.contents[j]reads without a new explicit organization-producing operation. - The current public contract is conservative: ordinary mutation of a container with current indexed contents state invalidates that indexed state unless the mutation effect can be applied to the current contents state.
- A mutation effect is preservable only when it is covered by an explicit selected-part operation such as
container.contents[i], or by a preservation contract recorded on the current indexed contents state. - Preservation contracts are declared by the operation or program that produced the indexed contents state. A preserving mutation must satisfy the contract through the current execution gate and must map the mutation effect to a declared indexed part, such as a default incoming slot.
- If the contract is satisfied and the effect is mappable, runtime updates the affected indexed part and keeps the contents state valid. Otherwise the indexed state is marked stale.
Currently defined preservation contracts:
field_retention: produced by magnetic separation. It requires a matching active field context and declares a retained slot plus a default incoming slot for compatible additions.
Material effects:
- Source items contribute in source-list order. A full-transfer item contributes its entire current material contents to the target.
- A quantified item contributes its declared quantity from the source's state at that point in the list. Volume/mass transfers follow the density rules and proportionally carry component quantities. A count transfer from a homogeneous cell suspension determines the corresponding carrier volume from the recorded concentration.
- An ordinary source that is the target itself has no material effect.
- Same-container
container.contents[i]sources preserve material totals but invalidate the current indexed contents state. series(...)maps the declared quantities to the target group in order.
6.3.5.1 Author-Declared Component Replacement
Component replacement is an author-declared change in tracked composition. It identifies the existing material entries being replaced and declares the products that take their place within the same container. Transfer moves existing material; a relationship transition preserves an entry's identity and quantity; replacement introduces new product identities.
The declaration must identify distinct live source entries against the same pre-change material state. Each source has a tracked mass, volume, or count quantity and one or more declared products. Product quantities may be known mass, volume, or whole-number count, or explicitly unknown mass.
Replacement preserves the container identity and the identity and order of unselected entries. Products occupy their source entry's position and retain provenance to that source. An empty product set does not constitute deletion. Material in active indexed contents must be collected before replacement; coupled multi-source transformations are outside this contract.
The product identities and quantities are authored assumptions. A preceding disruption does not determine them, and unspecified constituents and yields are not inferred. Chapter 7 defines provenance, atomic state changes, and subsequent movement; Section 11.2.2 defines unknown quantity. These semantic requirements do not prescribe a particular implementation API.
6.3.6 Implementation Independence
Implementations may use different internal operations and data structures. Conformance is determined by the source forms, accepted values, observable results, and failure behavior specified here.
6.3.7 Atomic Statement Contract Matrix
Alignment rule:
- Source-level shapes in this subsection MUST follow Chapter 4 when older draft wording conflicts.
- Operator call contracts are listed in one place.
- For closed enum parameters, qualified members retain their enum-family identity through bindings and protocol arguments. A member from another family is a type error even if its text is identical. Unknown members and members outside the operation's allowed subset are rejected before the affected operation executes. Existing permitted tokens and strings are compatibility spellings, not an extension mechanism. Normal name binding takes precedence over interpreting an unbound name as a legacy token.
| Atomic unit | Source shape | Required core args | Run spec / options | Return contract |
|---|---|---|---|---|
<< | target << [sources...]; | target, sources | no program; full-transfer and quantified items may mix in source order; quantified item must be unit-bearing (src:20uL) | mutates target/source container material state |
agit | agit(sample=..., mode=..., [drive=...], [motion=...], [duration=...], [rate=...], [cycles=...]); | `sample: Container | ContainerGroup, or PlateCarrierforTAP; mode` | closed AgitationMode; SHAKE accepts optional ShakeMotion; CENTRIFUGE requires drive and duration; parameter combinations follow §6.3.15 |
with env | with env(...) { [hold(target_expr);] ... } | env, body, optional hold target declarations | scalar thermal may use duration inside env(...) when a finite environment window is required; thermal_program forbids outer duration duplication; env targets are declared by positional hold(target_expr) or inferred from body; legacy hold(sample = ...) is compatibility-only | scoped environment context over statement block |
with constraint | with constraint(...) { ... } or stmt with constraint(...); | constraint set, scoped stmt/block | device-independent execution requirements; see Constraint Contract | applies execution requirement scope to enclosed statement(s) |
stream | let s = stream(sample = x, unit = single_cell, [panel = p]); | sample, unit | panel optional; result is unit-stream only, not material split group | unit_stream_ref |
sep | let g = sep(sample=..., program=centrifuge_program(...)); | sample, program | optional component_fates and transitions; program is mechanism group; keep_source only inside centrifuge_program(...) | sep_container_group fixed group[0] / group[1] |
frac | let fg = frac(sample=..., program=density_gradient_program(...)); | sample, program | program carries axis/order/bins | fraction_group ordered containers (fg[0..n-1]) |
img | let obs = img(sample=..., quantity=..., [schema_ref=...], [save_raw=...]); | sample, quantity | standard simple quantities use fixed result fields; complex results use schema_ref | single data_ref; grouped input returns data_group_ref |
ecp | let obs = ecp(sample=..., quantity=..., [schema_ref=...], [save_raw=...]); | sample, quantity | standard simple quantities use fixed result fields; complex results use schema_ref | single data_ref; grouped input returns data_group_ref |
phy | let obs = phy(sample=..., quantity=..., [schema_ref=...], [save_raw=...]); | sample, quantity | standard simple quantities use fixed result fields; complex/raw results use schema_ref | single data_ref; grouped input returns data_group_ref |
6.3.8 Program / Quantity / Schema Contracts
| Contract kind | Typical statement/operator | Role |
|---|---|---|
thermal_program | env(thermal=thermal_program(...)), pcr(...) | retained as single-segment thermal trajectory object |
centrifuge_program / centrifugal_filtration_program / magnetic_program / field_program / filtration_program / phase_partition_program / precipitation_program / disrupt_program | sep(..., program=...) | separation mechanism parameter groups; non-fractionating agit(mode=CENTRIFUGE, ...) uses action-local drive instead |
density_gradient_program / chromatography_program | frac(..., program=...) | fractionation mechanism parameter groups |
quantity = ... | img/ecp/phy | standard measurement/readout target selector |
data_schema(...) / schema_ref | img/ecp/phy/data_ref | open result-structure declaration and injection surface |
Program constructors are descriptor/callable values, not executable actions by themselves. They may be bound with let for readability and reuse, but take effect only when a compatible operation or scope consumes the descriptor, for example sep(..., program=p), frac(..., program=p), or with env(thermal=tp). The consuming owner is responsible for resolving the descriptor and enforcing the program family match.
6.3.9 Core Contract Boundary
Core source contract:
- atomic statements and statement-scoped forms from Chapter 4
- container/content initialization contracts required to explain those forms
- readout/result contracts needed by
img/ecp/phyauthoring
Workflow libraries and higher-level standard-library compositions are outside this chapter's scope.
6.3.10 Source-Level Contract Summary
Cross-cutting source-level contracts used by the operator-specific sections:
| Topic | Contract |
|---|---|
| Container/content mutation | Source-level mutation is unified as statement-first <<; no separate mix/dilute/transfer source keywords. |
| Mutation source style | One << source list may mix full-transfer (src) and quantified (src:Q) items; each item uses its own transfer mode in source order. |
| Quantified source item | Must carry physical units (for example 20uL); unitless ratio form (for example src:1) is forbidden. |
| Source-local partition selector | source.partition(program)[i] is a mutation-source-only selector for drawing from one ordered portion of a source container without first materializing a sep group. |
| Container contents selector | container.contents[i] is a mutation-source-only selector for drawing from the current indexed contents state produced by standalone sep(...) or frac(...); it is not a child container or bindable value. |
| Environment control | Environment is block-scoped via with env(...) { ... }; scalar thermal uses optional duration inside env(...) when the block needs a finite environment window; thermal_program.cycles does not imply block repetition; canonical explicit target declaration is hold(target_expr). |
| Constraint layer | Execution requirements are represented by constraint(...), not by device/program fields; block form is formal semantics and trailing form is sugar. See Constraint Contract. |
| Macro-to-micro transition | stream(sample=..., unit=...) is the source-level entry for converting macro samples into unit streams. |
| Binary separation | sep is fixed two-output split with ordered return group[0] / group[1], with mechanism program and mode-specific slot semantics. |
| Multi-fraction separation | frac is ordered multi-output split and is not collapsed into sep. |
| Measurement/readout | img/ecp/phy use quantity = ...; outputs are data_ref / data_group_ref. |
6.3.10.1 Transfer Delivery Requirements
See Constraint Contract: transfer delivery for DROPWISE and SPREAD.
6.3.10.2 Sealed Environment-Hold Requirement
See Constraint Contract: sealed environment holds.
6.3.11 Source-Local Partition Selector Contract
Canonical source-level shapes:
target << [source.partition(program_expr)[0]: amount];target << [source.partition(program_expr)[1]];
The selector source.partition(program_expr)[i] is a source-local portion reference. It selects one ordered portion of source under the supplied partition program and is valid only as a mutation source item. It is not a container, not a materialized group, and not a value that authors may bind with let for later standalone use.
program_expr must resolve to a concrete let-bound or inline partition-capable program descriptor. The accepted program descriptors are the same binary separation program descriptors used by sep; no new program type is introduced for this selector.
partition(program_expr) accepted program | Required fields | Optional fields | [0] | [1] |
|---|---|---|---|---|
centrifuge_program | drive: CentrifugalSetting | keep_source | supernatant | pellet |
magnetic_program | - | - | bound / retained | flowthrough / removable |
disrupt_program | - | method, duration | lysate | debris_or_residue |
field_program | exactly one of voltage: Q[ElectricPotential], current: Q[ElectricCurrent], or field: Q[ElectricPotential] | duration | target_band_fraction | non_target_fraction |
filtration_program | membrane, drive | - | filtrate | retentate |
centrifugal_filtration_program | membrane, drive: CentrifugalSetting | duration | filtrate | retentate |
phase_partition_program | solvent | - | target_phase | other_phase |
precipitation_program | reagent | - | precipitate | supernatant |
centrifugal_filtration_program(...) models membrane/column filtration driven by centrifugal force. It does not inherit the sedimentation result semantics of centrifuge_program(...): its stable outputs remain filtrate and retentate. Its drive field has type CentrifugalSetting.
Rules:
- The index must be a compile-time decidable non-negative integer.
- Current partition selectors are binary; only
[0]and[1]are valid. density_gradient_program(...)andchromatography_program(...)are not accepted bypartition(...); they remainfracprograms.thermal_program(...)and readout-oriented descriptors are not partition programs.partition(...)does not accept free-form named fields such aspartition(mode = ..., drive = ...); program fields stay inside the concrete*_program(...)descriptor.- A full-transfer selector item moves the whole selected portion. A quantified selector item moves the requested amount from the selected portion.
- Unselected portions, and any residual material left in the selected portion after quantified transfer, remain associated with the original source container according to the program's partition semantics.
partition(...)does not replacesep(...). Usepartition(...)when the source container remains the operative container and the partition is only consumed by the current transfer. Usesep(...)when the protocol needs materialized, independently addressable output containers or groups.
Magnetic-bead liquid removal example:
let mag_sep = magnetic_program(duration = 5min);
with env(field = magnetic_rack) {
waste << [bead_tube.partition(mag_sep)[1]: 180uL];
}Here [0] is the bound/retained bead-associated portion and [1] is the flowthrough/removable liquid portion. The transfer removes liquid from the source-local portion without first creating a sep_group.
6.3.12 sep Detailed Contract
Canonical source-level shapes:
let sep_group = sep(sample=..., program=centrifuge_program(...));sep(sample=..., program=centrifuge_program(...));let sep_group = sep(sample=..., program=filtration_program(...), component_fates={RPE1:{filtrate:0%, retentate:100%}});let sep_group = sep(sample=..., program=magnetic_program(...), transitions=[transition(subject=sample.materials[1], output=MagneticProgramOutput.FLOWTHROUGH, to=MaterialRelation.FREE)]);let sep_group = sep(sample=..., program=magnetic_program(...), transitions=[transition(subject=sample.materials.get("TARGET_PROTEIN"), output=MagneticProgramOutput.FLOWTHROUGH, to=MaterialRelation.FREE)]);
Effect contract:
- Let-bound
sep(...)materializes a two-slot container group and preserves existingsep_group[0]/sep_group[1]return behavior. - Standalone
sep(...)acts on the source container and records an indexed contents organization for latercontainer.contents[0]/container.contents[1]mutation-source reads. - Standalone
sep(...)does not create a bindable group unless authored in aletbinding.
Per-content fate contract:
component_fatesis optional and maps content identity to a two-output ratio record.- Output keys may use the selected program's semantic output names or the string slot keys
"0"and"1". - Both outputs are required. Each value is a unitless ratio from 0 to 1 or a percentage from 0% to 100%, and the pair must sum to 1 (100%).
- An authored fate has precedence over association-derived retention and the reference partition strategy. It remains subject to quantity-axis and conservation validation.
- The referenced content must exist in the source container at runtime.
Per-material relationship-transition contract:
A live quantity may be a positive known amount or a retained positive share of an unknown mass. Selection does not grant transition eligibility: unknown-mass replacement does not support relationship changes on its products (Sections 7.2.2 and 11.2.2).
transitionsis optional and containstransition(...)values scoped to a concrete positive-quantity separation output.subjectis eithersample.materials[index]orsample.materials.get(entry_id), wherematerialsis the normalized, ordered list of live material entries immediately before the operation. The index is a non-negative static integer. Theentry_idkey is a statically resolvable non-empty string and is matched exactly within the same container.get(...)never matchescontent_ref, content codes, labels, or prefixes and never falls back to another same-content entry.outputis one namespaced member of the selected separation program's concrete output enum. The enum type must match the concrete program; for example,filtration_program(...)acceptsFiltrationProgramOutput.FILTRATEorFiltrationProgramOutput.RETENTATEand rejects members ofMagneticProgramOutput.tois a namespacedMaterialRelation.MEMBERexpression. The author-settable domain isfree,container_surface,pellet,precipitate,disrupted,bead_bound,membrane_bound,cell_bound, andfield_retained.UNRESOLVEDis an internal sentinel and MUST NOT be authored. String values, bare identifiers such asfree, and members outside this enum are invalid.- The directed transition graph has no source/target-pair whitelist. Runtime derives the current
MaterialRelationfrom the selected entry and accepts any target in the author-settable enum domain, subject to target-state structural invariants. freehas no association target and clears the source association. The container-associated target relations use the concrete output container as their typed association target.bead_bound,membrane_bound, andcell_boundrequireassociated_withto use either same-sample material selector form. The selected association target must have positive quantity in the same output and is the material entry to which the selected subject becomes bound.associated_withis forbidden for target relations that are not component-bound.- An authored relationship transition specifies the relation of the selected source entry in the selected output, taking precedence over the default relation assigned by the separation model.
component_fatesindependently determines quantity allocation. A transition preserves material identity and quantity; it does not infer chemistry or introduce another separation program. - Runtime preserves identity and quantity, validates the complete candidate, and commits atomically. Any selector, enum, association, output, or conservation failure preserves the previously committed source state.
Surface-release authoring pattern:
filtration_program(membrane = "adherent_cell_surface", drive = "cell_lifter") uses the existing surface-boundary partition vocabulary: FILTRATE is the released liquid fraction and RETENTATE is the surface-retained fraction. It does not declare an additional filter material. An author routes cells and carrier with component_fates and declares the selected cellular entry MaterialRelation.FREE in FILTRATE. A bound let lifted = sep(...) produces the output group; subsequent transfer collects lifted[0]. Detachment therefore precedes collection and any chemical-lysis material replacement.
Complete recovery is an author-declared fate, not a predicted efficiency. This pattern preserves count and carrier volume and supplies no rupture, yield, duration, force, or stroke-count inference. Human execution presents cell-lifter handling; a robot projection identifies surface release separately from a filter-device action. Actual device execution requires an adapter for that handling operation. Existing selector, output, quantity, and association validation rules apply without additional syntax or diagnostic codes.
MaterialRelation has the following closed association contract. In this table, “required” means that the author must supply associated_with = sample.materials[index] or associated_with = sample.materials.get(entry_id); “not applicable” means that the argument MUST NOT appear because the relationship either has no target or its target is the concrete output container.
to member | Relationship target category | Explicit same-sample material selector | Runtime association target |
|---|---|---|---|
MaterialRelation.FREE | no association | not applicable | association is cleared |
MaterialRelation.CONTAINER_SURFACE | output-container association | not applicable | concrete output container |
MaterialRelation.PELLET | output-container association | not applicable | concrete output container |
MaterialRelation.PRECIPITATE | output-container association | not applicable | concrete output container |
MaterialRelation.DISRUPTED | output-container-scoped state | not applicable | concrete output container |
MaterialRelation.FIELD_RETAINED | output-container-scoped retention | not applicable | concrete output container |
MaterialRelation.BEAD_BOUND | component-entry association | required | selected bead material entry projected into the same output |
MaterialRelation.MEMBRANE_BOUND | component-entry association | required | selected membrane material entry projected into the same output |
MaterialRelation.CELL_BOUND | component-entry association | required | selected cell material entry projected into the same output |
MaterialRelation.UNRESOLVED | internal sentinel | invalid author target | none; the transition is rejected |
Therefore, only BEAD_BOUND, MEMBRANE_BOUND, and CELL_BOUND explicitly bind one material entry to another material entry. For those three members, the selected association target must belong to the operation's source materials list and must have positive quantity in the same output. All other author-settable relations reject the associated_with argument.
Program-owned output enums are closed and ordered by output index:
| Program | Output enum | part 0 | part 1 |
|---|---|---|---|
sep_program compatibility surface | SepProgramOutput | FRACTION_A | FRACTION_B |
centrifuge_program | CentrifugeProgramOutput | SUPERNATANT | PELLET |
magnetic_program | MagneticProgramOutput | BOUND | FLOWTHROUGH |
disrupt_program | DisruptProgramOutput | LYSATE | DEBRIS_OR_RESIDUE |
field_program | FieldProgramOutput | TARGET_BAND_FRACTION | NON_TARGET_FRACTION |
filtration_program | FiltrationProgramOutput | FILTRATE | RETENTATE |
centrifugal_filtration_program | CentrifugalFiltrationProgramOutput | FILTRATE | RETENTATE |
phase_partition_program | PhasePartitionProgramOutput | TARGET_PHASE | OTHER_PHASE |
precipitation_program | PrecipitationProgramOutput | PRECIPITATE | SUPERNATANT |
The same enum members define the ordered sep result and the transition selector. sep_group[0] / sep_group[1] remain the stable structural access surface. component_fates record keys remain the program's semantic-role keys because record-key grammar does not use member expressions; those keys denote the same output roles as the enum members.
Return contract:
sep_group[0]/sep_group[1]are the stable user-facing access forms for let-boundsep(...)output groups.- Return arity is fixed at 2 for all included modes.
container.contents[0]/container.contents[1]are valid only when a current standalone contents state exists for that container.
keep_source contract:
- Allowed only inside
centrifuge_program(...). - Values:
CentrifugeProgramOutput.SUPERNATANTorCentrifugeProgramOutput.PELLET. Compatiblesupernatant/pellettokens and strings denote those same members; an output member from another program family is not interchangeable. - Omitted
keep_sourcemeans both outputs are newly materialized container identities.
Mode contract:
| program | Required fields | Optional fields | group[0] | group[1] |
|---|---|---|---|---|
centrifuge_program | drive: CentrifugalSetting | keep_source | supernatant | pellet |
magnetic_program | - | - | bound | flowthrough |
disrupt_program | - | method, duration | lysate | debris_or_residue |
field_program | exactly one of voltage: Q[ElectricPotential], current: Q[ElectricCurrent], or field: Q[ElectricPotential] | duration | target_band_fraction | non_target_fraction |
filtration_program | membrane, drive | - | filtrate | retentate |
centrifugal_filtration_program | membrane, drive: CentrifugalSetting | duration | filtrate | retentate |
phase_partition_program | solvent | - | target_phase | other_phase |
precipitation_program | reagent | - | precipitate | supernatant |
Separation program fields describe the separation mechanism and its direct mechanism parameters. They do not duplicate block-scoped physical environment control. Run temperature remains an enclosing with env(thermal=...) condition. centrifugal_filtration_program(...) owns an optional action-local duration because it describes the membrane run time. In contrast, centrifuge_program(...) intentionally does not accept duration; an authoring phrase such as "centrifuge 5 min at 4C" for an actual separation is represented as a sep(...) statement inside with env(thermal=4C, duration=5min). For non-fractionating centrifugation, agit(mode=CENTRIFUGE, drive=..., duration=...) owns both the centrifugal drive and finite action time. It does not use a separation program.
field_program(...) describes electric-field-driven separation. It requires exactly one control setting: voltage: Q[ElectricPotential], current: Q[ElectricCurrent], or field: Q[ElectricPotential], where field is an alias for voltage. Voltage and current are not implicitly converted.
filtration_program.drive accepts the standard members FiltrationDrive.PRESSURE, FiltrationDrive.ASPIRATION, and FiltrationDrive.CELL_LIFTER, corresponding to pressure, aspiration, and cell_lifter. These names identify authored handling; they do not calculate separation efficiency or supply an equipment implementation. Hosts may install a Python enum subclass of FiltrationDriveBase with a stable identity and version, then reference its qualified members in source. Types from other parameter families are not interchangeable. Standard bare tokens and strings normalize to the standard members; other historical text remains compatible text, not an implicitly installed extension. Registration rejects duplicate standard spellings and identities. This contract does not change the quantity-valued drive of centrifuge_program or centrifugal_filtration_program.
disrupt_program.method has the closed type DisruptionMethod, with members MECHANICAL, SONICATION, SHEAR_HOMOGENIZATION, HIGH_PRESSURE_DISRUPTION, and BEAD_IMPACT. The corresponding lowercase tokens and strings remain compatibility inputs. It records the authored disruption method or physical mechanism; it does not select a device. Concrete equipment binding remains a planner or driver concern. Omit method when the source does not state one; implementations must not infer it from the resulting material state.
6.3.13 frac Detailed Contract
Canonical source-level shapes:
let frac_group = frac(sample=..., program=density_gradient_program(...));frac(sample=..., program=density_gradient_program(...));
Core argument contract:
- Required source-level args:
sample,program. programisdensity_gradient_program(...)orchromatography_program(...).binsis integer-like and must satisfy semantic lower bound for ordered fractionation.
Return contract:
- Return value is
fraction_groupwith stable ordered indexing. frac_group[i]resolves to container output at indexi; only compile-time non-negative integer indexing is part of the contract.- For
density_gradient_program,axisacceptsDensityGradientAxis.DENSITY;orderacceptsDensityGradientOrder.TOP_TO_BOTTOMorDensityGradientOrder.BOTTOM_TO_TOP. The lowercase tokens and strings are compatible spellings of those members. These closed types do not close the separate extensible axis/order vocabulary ofchromatography_program. - For
chromatography_program, the standard pair isChromatographyAxis.RETENTION_TIMEandChromatographyOrder.EARLY_TO_LATE. The existingretention_time/early_to_latetokens and strings resolve to those members. Other previously accepted text remains compatibility metadata, not a declaration of a registered extension. - Extension packages provide domain-specific axis and order types. An order declares its exact axis; registered typed values must form a matching pair. An unknown compatibility string cannot satisfy the counterpart of an explicit extension. Historical text-only pairs retain their prior acceptance. Protocols reference installed type members; this does not introduce class declarations into the source language.
- Installed extensions have stable domain identity, version and member names. Stored values use that identity rather than implementation module paths. Restoring an unknown type/version fails explicitly and must not load code from a serialized class path. Type names obey ordinary source binding and shadowing; installation must not replace standard types.
- Declaring an extension does not provide a new separation algorithm or device capability. Execution requires explicit support for the extension identities; an unsupported driver must reject the operation before executing it.
- Standalone
frac(...)records an ordered indexed contents state for latercontainer.contents[i]mutation-source reads; it does not create a bindable group unless authored in aletbinding.
6.3.14 with env Contract
Canonical shape:
with env(thermal=..., [co2=...], [rh=...], [duration=...]) { ... }with env(thermal=thermal_program(...)) { ... }with env(field=...) { ... }
Explicit target declaration shape:
hold(container_ref);hold(container_ref.contents);hold(container_ref.structure.top);hold(container_ref.structure.bottom);hold(container_ref.structure.sidewall);hold(group([target_ref_1, target_ref_2, ...]));
Parameter contract:
- At least one supported environment dimension is required; dimensions are
thermalandfield. thermalaccepts union type:Q[Temperature] | thermal_program.fieldis used for non-thermal field domains such asmz_separation.co2/rhare optional thermal modifiers; they are not primary dimensions.
Behavior constraints:
thermal = Q[Temperature]: constant-temperature environment scope.durationis required when the block is a pure environment hold/incubation, when the block body needs an enclosing time boundary, or when the author intentionally supplies a finite environment window.thermal = Q[Temperature]may omitdurationfor active-operation blocks whose environment lifecycle is exactly the lexical execution of the enclosed statements. This form represents instructions such as assembling or mixing a reaction under a stated temperature condition without inventing a finite hold time.thermal = thermal_program: program-driven thermal scope;durationis forbidden because total time is derived by program.field = ...: field-domain environment scope; outerdurationis forbidden.co2/rhrequirethermal; they are forbidden whenthermalis program-typed.durationandthermal_program.cyclesdescribe the environment program itself and MUST NOT imply block-body repetition.- Block-body statements execute once in lexical order; per-cycle/stage hooks are not part of the contract.
- When a single enclosed action has no action-local duration field and the source supplies an execution time boundary, the enclosing scalar thermal
durationsupplies the time boundary for executing that action under the stated environment; for example centrifugation time may be expressed by wrappingsep(..., program=centrifuge_program(drive=...))inwith env(thermal=..., duration=...). - Action-local duration remains distinct from environment duration. Operations such as
agit(...)do not inheritenv.duration; if the action itself requires a duration, the action must declare it.
Target declaration constraints:
hold(...)is only valid directly inside awith env(...)block.- Canonical
hold(...)accepts exactly one positionalHoldTargetexpression and no named arguments. hold(...)records environment-hold/reporting targets for the nearest enclosingwith env(...); it does not define the environment scope and does not introduce temperature, time, program, device, or execution-requirement parameters.- Direct-child
hold(...)declarations are not standalone executable actions. If awith env(...)block contains onlyhold(...)declarations, the block applies a pure environment hold to those targets. - If a
with env(...)block contains direct-childhold(...)declarations plus executable body statements, those declarations record environment-hold targets for that layer and the remaining statements execute under that same layer. They do not narrow the lexical environment scope, impose ordering, or exclude other body statements from the environment context. - Direct-child
hold(...)declarations may appear anywhere in the immediatewith env(...)body and are collected as environment targets rather than executable steps. - If a
with env(...)block contains no explicithold(...)declarations, env targets are inferred from enclosed executable statements as in the body-inference model. - Bare container targets in
hold(container_ref)are content-facing by default. Authors should use a structure facet such ascontainer_ref.structure.topwhen the controlled object is the physical container structure rather than the contained material. - Legacy
hold(sample = container_ref)may be accepted by implementations as compatibility input, but it is not the canonical source form for new examples. hold(...)inside nestedif,repeat,with constraint, or other non-env sub-blocks is not a valid target declaration for the enclosing env block.
Target semantics:
- Chapter 6 defines the
HoldTargettype andwith envtarget-declaration contract; Chapter 4 defines the corresponding source spelling. with env(...)owns environmental conditions,thermal_program(...)owns thermal trajectory fields, andhold(...)owns only target declaration.- A container structure-facet target is not a sample/material state and must not be interpreted as sample thermal state.
- A bare container remains ergonomic for ordinary thermal holds by defaulting to its contents in
HoldTargetposition. container.contentsandcontainer.structure.<facet>are direct target views, not partitioning methods and not new container allocation.container.structure.topis closure-agnostic and must not be restricted to a device-specific lid/cap concept.- A PCR anti-condensation or top-structure heating requirement is represented as a structure-facet hold such as
hold(pcr_tube.structure.top)under a thermal env, not as sample temperature.
6.3.15 Agitation Contract (agit)
Shape: agit(sample=..., mode=..., [drive=...], [motion=...], [duration=...], [rate=...], [cycles=...]);.
sample accepts one Container or a flat, ordered ContainerGroup. Explicit and let-bound groups have the same semantics: the action applies independently to each member without merging members or transferring material between them. For TAP, the sample may instead be a whole plate carrier. This denotes one carrier action affecting the contents organization of its allocated wells, without transferring material between wells. A selected well group continues to denote independent member actions. Whole-plate TAP requires a declared carrier; an inline descriptor does not identify that instance. Its affected wells must have an explicit association with the carrier. Incomplete membership is rejected before the action changes any contents organization; membership must not be inferred from equal labels or well names.
Existing plate-descriptor calls for other modes, including whole-plate SHAKE, remain accepted with their established meaning. They do not become independent well-group actions.
mode has the closed type AgitationMode: VORTEX, INVERT, FLICK, TAP, SHAKE, STIR, CENTRIFUGE, and the compatibility member ROTATION. Qualified members are canonical; the corresponding lowercase tokens and strings remain accepted.
SHAKE describes agitation by moving the container. Its optional motion has the closed type ShakeMotion: LINEAR, ORBITAL, ROCK, or ROTATION. Lowercase tokens and strings denote the corresponding motion members. The two enum families are not interchangeable. Omitting motion leaves the trajectory unspecified; no orbital or other default motion is inferred. motion is not accepted with any other mode, including the compatibility mode=ROTATION.
| Mode / motion | Meaning | Parameter contract |
|---|---|---|
VORTEX | Vortex mixing | Optional duration and rate in rpm; no cycles or motion. |
INVERT | Discrete inversion | Optional cycles; no duration, rate or motion. |
FLICK | Gentle tube flicking, distinct from inversion, vortexing and plate tapping | Optional cycles; no duration, rate or motion. An omitted count is not inferred. |
TAP | Discrete tapping of a container or plate carrier to mix its contents | No duration, rate, cycles, motion or drive. Count, timing and intensity remain unspecified. Gentle handling is a separate requirement. |
STIR | Stirring | Optional duration and rate in rpm; no cycles or motion. |
SHAKE without motion | Unspecified shaking trajectory | Existing optional duration and rate in rpm; no cycles. |
SHAKE, LINEAR | Back-and-forth translation along a line | Required duration, optional frequency rate; no cycles. |
SHAKE, ORBITAL | Circular orbital translation, without implying end-over-end inversion | Required duration, optional rate in rpm; no cycles. |
SHAKE, ROCK | Repeated limited-angle tilting and return | Exactly one of duration or cycles, plus optional frequency rate. One cycle is a complete out-and-back movement. |
SHAKE, ROTATION | Continuous rotation, such as end-over-end tube rotation | Required duration, optional rate in rpm; no cycles. |
Compatibility ROTATION | Same motion and parameter contract as SHAKE with ShakeMotion.ROTATION | Existing source and stored plans remain valid. |
CENTRIFUGE | Centrifugation of the same container without declared fractions | Required drive in g or rpm and finite positive duration; no motion, rate, cycles, or program. |
For an explicit motion, duration must be a finite positive time quantity. Rocking cycles must be a positive, unitless integer. Every supplied motion rate must be finite and positive: LINEAR and ROCK use Hz or cycle/min, while ORBITAL and ROTATION use rpm. A frequency is not implicitly converted to a rotation rate. Rocking may combine a count with a rate, but not a count with a duration; no additional duration is inferred or inserted.
agit(sample = sample, mode = AgitationMode.SHAKE,
motion = ShakeMotion.ROCK, cycles = 3);
agit(sample = sample, mode = AgitationMode.SHAKE,
motion = ShakeMotion.ORBITAL, duration = 1min, rate = 200rpm);
agit(sample = sample, mode = AgitationMode.SHAKE,
motion = ShakeMotion.ROTATION, duration = 2h, rate = 20rpm);
agit(sample = sample, mode = AgitationMode.CENTRIFUGE,
drive = 3000g, duration = 5s);Omitted rate and geometric details remain unspecified. This contract does not introduce times, orbit_diameter, stroke_length, tilt_angle, a SWIRL member, or a SURFACE_RINSE mode. Gentle execution can be expressed separately with a compatible constraint; rocking does not itself guarantee gentleness or preservation of adherent cells.
These rules apply after aliases, protocol arguments and runtime expressions are resolved. Known invalid combinations are rejected before execution; deferred values must be checked before the action executes. An enclosing environment duration does not supply a required action-local duration.
agit returns no material or data value. All modes preserve container identity and quantities and invalidate prior indexed-contents organization as specified in Chapter 7. CENTRIFUGE does not create separation slots or assert a pellet, supernatant, or bead-settling outcome. Its finite drive/time settings describe the action, not an observed result. Other modes do not imply binding yield, reaction progress, or proof of complete homogenization. The execution backend must receive the selected mode and parameters without silently substituting another motion or separation.
6.3.16 Readout Family Contract (img/ecp/phy)
quantity has the closed type ReadoutQuantity. Each lowercase quantity below maps to the uppercase member of that type, for example fluorescence to ReadoutQuantity.FLUORESCENCE and ph to ReadoutQuantity.PH. Compatible lowercase tokens and strings denote the same members. Each operation accepts only its own subset; sharing the enum type does not permit PH in img. ReadoutQuantity.CUSTOMIZED still requires schema_ref.
img:
- Shape:
let obs = img(sample=..., quantity=..., [schema_ref=...], [save_raw=...]); - Core args:
sample,quantity. - Quantity set:
uv_absorbance | fluorescence | colorimetric | customized. - Return: single-sample input yields
data_ref; grouped sample input yieldsdata_group_ref.
ecp:
- Shape:
let obs = ecp(sample=..., quantity=..., [schema_ref=...], [save_raw=...]); - Quantity set:
ph | conductivity | dissolved_oxygen | orp | customized. - Return: single-sample input yields
data_ref; grouped sample input yieldsdata_group_ref.
phy:
- Shape:
let obs = phy(sample=..., quantity=..., [schema_ref=...], [save_raw=...]); - Quantity set:
temperature | pressure | flow_rate | mass | volume | humidity | current | customized. - Return: single-sample input yields
data_ref; grouped sample input yieldsdata_group_ref.
Cross-family rule:
- Readout operators are data-producing operators and are not container-mutation operators.
data_refuses a shared envelope plus family- and quantity-specificresultpayload.resultfield sets are determined byfamily + quantity, not by free-form runtime text.raw_artifact(when present) is auxiliary evidence and does not replace structuredresult.- Optional
export_refsmay attach richer external/profile-specific result exports; they do not replaceresultas the source-level control surface. - Grouped sample input yields
data_group_ref, whose order matches the input container group.
Local data reference constructors:
data_ref(kind=...) and data_group_ref(kind=...) share the DataKind parameter family: OBSERVATION, SEQUENCE_READ, and SORT_RECORD denote observation, sequence_read, and sort_record. A host may explicitly install a Python enum subclass of DataKindBase; source refers to its qualified members. Standard old spellings normalize to these members, while other historical text remains text. A bound value of another enum family is rejected rather than reinterpreted by its spelling. Declaring a data kind does not define result fields, grant measurement behavior, or change the schema_ref rules.
Serialized local references retain the textual data_kind. An installed extension also retains data_kind_type, carrying its stable identity, version, and member; standard kinds and historical text do not add that field. Extension-bearing plans require the matching installed identity for replay; decoding never loads Python code from stored paths. Both extension families follow the existing scoped naming and parameter-validation rules, including aliases, protocol arguments and bindings. An installed type must belong to exactly one parameter family: multiple inheritance across unrelated enum bases is rejected at registration, including combinations of chromatography axis and order bases. Intermediate bases within one family and ordinary non-enum mixins remain valid. Open enum members cannot be restored from closed class-name/member payloads; identity and version checks always use the currently installed registry, even when a decoder outlives an installation scope.
6.3.17 Core Contract Boundary
- Sections
6.3.7to6.3.19define source-level contracts for the core atomic operator surface. - The core source path covers constructor/init,
<<,agit,with env,sep,frac, source-local partition selectors,img,ecp,phy, and indexed group references. - Higher-level workflow libraries are outside the core contract defined in this chapter.
- Compatibility behavior must not change the source-level contracts defined in this chapter.
6.3.18 Separation vs Fractionation Boundary
Principle distinction:
sepis binary semantic split (targetvsnon-target) and returns fixed two-slot outputs.fracis ordered distribution split across multiple bins and returns ordered multi-slot outputs.- If domain intent is to preserve distribution/layer profile, use
fracinstead of collapsing tosep.
Classification note:
sepandfracare parallel atomic operators under the same broad separation family.- They are not aliases of each other.
6.3.19 Readout Category Map
| Category | Typical scenarios | Preferred atomic path | Typical output form |
|---|---|---|---|
| Optical quantification | UV/optical fluor/colorimetric quant | img(sample=..., quantity=...) | scalar/data readout reference |
| Electric-field-separated readout | gel/capillary style readout | sep(sample=..., program=field_program(...)) + img(sample=..., quantity=customized, schema_ref=...) | band/peak data reference |
| Microscopy imaging | fixed/live-cell imaging | img(sample=..., quantity=customized, schema_ref=...) | image data reference |
| Physiological state readout | viability / pH / conductivity | img(...) (indicator route) or ecp(sample=..., quantity=...) | data reference |
| Separation-coupled readout | post-separation flow/seq/ms readout | decomposition path (stream/repeat/env/img/phy/data_ref) | data reference |
6.3.20 Constraint Contract (with constraint)
This section owns constraint meaning, applicability, execution requirements and compatibility checks. Chapter 4 defines the source forms; Chapter 8 defines the diagnostic catalog.
Forms:
with constraint(ConstraintRequirement.GENTLE) {
target << [source:10uL];
}
target << [source:10uL] with constraint(ConstraintRequirement.GENTLE);The trailing form is equivalent to a block containing that one statement. The standard requirement catalog below specifies which actions each requirement allows; the compatibility checks specify additional semantic conditions.
6.3.20.1 Meaning and Scope
Execution requirements constrain how an existing operation is performed. They do not introduce a new material operation or override its quantity and conservation rules. Requirements must be compatible with the enclosed action family; incompatibility is SEM_CONSTRAINT_ACTION_FAMILY_MISMATCH.
Standard requirement identities use ConstraintRequirement members; bare names remain compatibility spellings. agit accepts GENTLE, ASEPTIC, CROSS_CONTAM_CONTROL, COLD_CHAIN, DARK_PROTECTED, and CONTROLLED_ATMOSPHERE. These requirements restrict the explicit mechanical action without changing its mode, quantities, or indexed-contents effects. Other agitation combinations remain outside the accepted contract.
Nested scopes accumulate requirements, including through protocol calls. A requirement cannot be silently cancelled or skipped for an incompatible action; leaving a scope restores its enclosing requirements. Combination restrictions, including the exclusivity of CUSTOMIZED, apply to the combined active set.
Standard requirements support both block and trailing forms. Requirement names are static declarations. Unknown names, empty bodies, duplicate options and unsupported options are rejected. Standard requirements accept no extra options; CUSTOMIZED requires schema_ref and accepts no other option.
Applicability and decidable conflicts are checked before execution. Deferred conditions must be checked once their required values become available. Execution support is a separate requirement: a backend cannot override a language conflict.
6.3.20.2 Transfer Delivery
dropwise is a standard requirement in the delivery-mode category, valid on << transfers in either block or trailing form:
target << [source:150uL] with constraint(ConstraintRequirement.DROPWISE);The liquid is delivered drop by drop. 150uL remains the total transfer quantity; a full-transfer source likewise retains full-transfer semantics. No drop count, per-drop volume, rate, duration, mixing, or material conversion is inferred. The requirement applies to each source delivery in the statement and can coexist with compatible requirements such as gentle. As with other standard requirements, additional options are rejected with SEM_CONSTRAINT_UNKNOWN_OPTION.
The requirement must be preserved through execution. Human instructions must make dropwise delivery explicit, and device execution must honor it. A driver's declared lack of support produces RT_DRIVER_REQUIREMENT_UNSUPPORTED before material movement. An instruction or command projection alone does not establish physical execution.
spread is a standard delivery-mode requirement for distributing transferred material evenly across a receiving surface. It accepts the same block and trailing forms as dropwise:
plate_surface << [suspension:100uL]
with constraint(ConstraintRequirement.SPREAD, ConstraintRequirement.ASEPTIC);The target must resolve to a surface, including through protocol parameters; a different target kind is SEM_SPREAD_TARGET_NOT_SURFACE. The requirement preserves the transferred amount, source and destination identities, and material accounting. It does not specify a spreading tool or add a second transfer. aseptic is independent and may be combined with it; spread and dropwise are not intrinsically exclusive. The requirement must reach the execution provider, and declared lack of support fails before material movement.
6.3.20.3 Sealed Environment Holds
sealed is a standard requirement in the environmental-protection category. It is valid on a pure environment hold and states that the hold target remains sealed for the duration of that hold:
with constraint(ConstraintRequirement.SEALED) {
with env(thermal = 25C, duration = 2h) {
hold(elisa_plate);
}
}For a plate-level closure requirement, the hold target is the plate binding, not a selected well group. sealed does not create a material operation, container-state transition, implicit seal/unseal step, or persistent closure state after the constraint scope ends. Applying it to an unrelated action family is SEM_CONSTRAINT_ACTION_FAMILY_MISMATCH.
The requirement applies throughout the hold. Human instructions must explicitly state that the target remains sealed, and device execution must honor that condition. A driver's declared lack of support produces RT_DRIVER_REQUIREMENT_UNSUPPORTED before the hold.
6.3.20.4 Standard Requirement Scenarios
The following entries define the standard vocabulary and its current applicability. Each name is a member of ConstraintRequirement. An allowed action must still satisfy applicable semantic checks and execution-provider requirements. Qualitative requirements do not introduce numerical limits or prove physical outcomes. For stream, applicability attaches to the declaration; it does not itself establish that sampling or measurement has occurred.
DROPWISE
Use for gradual liquid delivery into a receiving vessel; the specified transfer quantity remains the total amount.
Applies to: <<.
SPREAD
Use when transferred suspension or liquid must be distributed across a receiving surface.
Applies to: <<.
PRESERVE_BOUNDARY
Use when transferring above a pellet or handling separated material while protecting a material interface. The requirement does not identify a particular interface or imply preserved cell adhesion.
Applies to: <<, sep, frac.
PRESERVE_LAYERING
Use when overlaying or handling layered material without disrupting its layers. It cannot be applied to agitation, whose contract invalidates existing layer indices.
Applies to: <<, sep, frac.
PRESERVE_FRACTION_ORDER
Use when collecting separation outputs or a fraction series whose order must remain identifiable. It does not reorder the declared outputs.
Applies to: sep, frac.
ASEPTIC
Use when handling material that requires aseptic technique, such as transferring culture medium or agitating a sterile preparation.
Applies to: <<, agit, sep, img, ecp, phy, stream.
LOW_CARRYOVER
Use when a shared transfer or sampling path must limit material carried from one sample to another.
Applies to: <<, sep, img, ecp, phy, stream.
CROSS_CONTAM_CONTROL
Use when handling multiple samples or outputs that must remain protected from cross-contamination.
Applies to: <<, agit, sep, img, ecp, phy, stream.
GENTLE
Use for disturbance-sensitive material during transfer, separation or agitation. The requirement does not prescribe a speed, force or duration.
Applies to: <<, agit, sep, frac, stream, environment hold.
AVOID_RESUSPENSION
Use when removing liquid above settled material while leaving that material undisturbed. It does not establish that sediment exists or guarantee adhesion.
Applies to: <<, sep, frac.
AVOID_SHEAR
Use when transferring or processing shear-sensitive material. The requirement does not prescribe a numerical shear limit.
Applies to: <<, sep, frac, stream.
PRESERVE_VIABILITY
Use when transferring or preparing a stream from living material for which viability-preserving handling is required. The requirement is not a prediction or measurement of survival.
Applies to: <<, stream.
COLD_CHAIN
Use for temperature-sensitive material during transfer, agitation, separation or an environment hold. Explicit thermal settings must satisfy the cold-chain compatibility checks below.
Applies to: <<, agit, sep, frac, img, ecp, phy, stream, environment hold.
DARK_PROTECTED
Use for light-sensitive preparations during handling or agitation. No protected spectral range or exemption for readout illumination is inferred; execution support must address the intended protection.
Applies to: <<, agit, img, ecp, phy, stream, environment hold.
SEALED
Use when an environment-hold target must remain sealed throughout the hold; see Section 6.3.20.3.
Applies to: environment hold.
CONTROLLED_ATMOSPHERE
Use when handling or holding material that requires a controlled atmosphere. No gas composition or concentration is inferred.
Applies to: <<, agit, img, ecp, phy, stream, environment hold.
HIGH_PRECISION
Use when a transfer quantity, separation control or measured quantity requires high-precision execution. No numerical tolerance is inferred.
Applies to: <<, sep, frac, ecp, phy.
LOW_LOSS
Use when handling limited or valuable material to minimize losses from transfer, separation or sampling. Intended waste is not thereby designated for retention.
Applies to: <<, sep, frac, ecp, phy.
QUANTITATIVE_RECOVERY
Use when transfer or separation is intended to recover a designated material or output quantitatively. The requirement does not alter allocation ratios or assert an achieved recovery percentage.
Applies to: <<, sep, frac.
STABILIZED_READING
Use when a measurement should be taken after its reading has stabilized. No settling time or stability threshold is inferred.
Applies to: img, ecp, phy.
LOW_NOISE
Use when a readout requires noise-reducing execution conditions. No numerical noise threshold is inferred.
Applies to: img, ecp, phy.
NONINVASIVE
Use when the selected readout must avoid invasive alteration of the sample. The selected method must support that requirement.
Applies to: img, ecp, phy.
CUSTOMIZED
Use when an execution requirement needs an explicitly declared schema rather than a standard requirement. Supply schema_ref and do not combine CUSTOMIZED with another requirement, including an inherited one.
Applies to: <<, sep, frac, img, ecp, phy, stream.
6.3.20.5 Compatibility Checks
Constraint checks supplement the owning action's parameter contract. They inspect only the inputs relevant to the requirement; they do not replace checks of an action's required arguments, parameter types or units.
| Check | Relevant input | Required behavior |
|---|---|---|
| Action applicability | Requirement and enclosed action | Reject an action outside the requirement's permitted families with SEM_CONSTRAINT_ACTION_FAMILY_MISMATCH. |
| Scope and combination | Requirements in the current and enclosing scopes | Accumulate requirements, restore the outer set on exit, and reject incompatible combinations. CUSTOMIZED cannot be mixed with other requirements (SEM_CONSTRAINT_CUSTOMIZED_EXCLUSIVE). |
| Surface spreading | Receiving target kind | A resolved non-surface target is rejected with SEM_SPREAD_TARGET_NOT_SURFACE, including when resolved through a protocol parameter. |
| Cold-chain temperature | Each explicit scoped thermal setting | Check a finite temperature in C or K against 8 C / 281.15 K. A known high temperature is SEM_CONSTRAINT_ENV_CONFLICT; a bound high temperature is RT_CONSTRAINT_ENV_CONFLICT. An explicit value still unresolved or invalid at execution is rejected with RT_CONSTRAINT_INVALID. |
| Customized contract | schema_ref and supplied options | Require schema_ref; reject unsupported options. |
| Execution support | Action and attached requirements | Declared lack of support is RT_DRIVER_REQUIREMENT_UNSUPPORTED before the affected action. Support cannot override a semantic conflict. |
For example, this temperature is compatible with the cold-chain requirement:
let sample = tube(label = "Sample");
with constraint(ConstraintRequirement.COLD_CHAIN) {
with env(thermal = 4C) {
agit(sample = sample, mode = AgitationMode.SHAKE, motion = ShakeMotion.ROTATION, duration = 1min);
}
}Changing 4C to 37C creates a semantic conflict even though COLD_CHAIN is allowed on agit. 277.15K and 310.15K have the corresponding outcomes. A temperature determined only during execution must be checked before the action. Omitting an explicit temperature does not infer one or remove the execution requirement. None of these checks proves the sample's physical temperature.
For other qualitative requirements, the action whitelist and execution support remain distinct from condition-specific semantic checks. No numerical gentle, precision, noise, viability or recovery criterion is defined here. In particular, permitted readout applicability does not by itself settle light-exposure or invasiveness compatibility.
6.4 Authoring Boundary
Core source-level authoring boundary:
target << [sources...]for material transfer/merge/collectionagit(...)for agitation/mixing behaviorsource.partition(program)[i]inside mutation source items for source-local portion selectionsep(..., program=...)andfrac(..., program=...)for separation/fractionationimg(...),ecp(...),phy(...)for readout- constructor sugar and
with env/with constraintforms as defined by Chapters 4 and 5
6.5 Contract Failures and Diagnostics
Call-contract validation covers:
- unknown operation names, commonly reported as
SEM_UNKNOWN_STEP - missing required arguments, commonly reported as
SEM_MISSING_REQUIRED_ARG - unknown argument names, commonly reported as
SEM_UNKNOWN_ARG - duplicate argument names, commonly reported as
SEM_DUPLICATE_ARG - dimension/unit mismatches, reported with
TYPE_*diagnostics - state-dependent material feasibility, such as capacity bounds, reported with
MAT_*diagnostics
The complete diagnostic list and earliest-stage placement are specified in Chapter 8.
6.6 Check Placement
- Membership and arg-shape checks: semantic validation.
- Unit/dimension checks: typecheck stage.
- State-dependent feasibility: runtime/material stage.
6.7 Conformance Boundary
Validators, typecheckers, planners, runtime material handlers, and examples must conform to these operation vocabulary and call contracts; they do not define separate operation behavior.
