Skip to content

A union of groups is written inline only: no reference fits it #91

Closed

Description

@SimonHeybrock

ADR 0008 lets a reference fit a union of groups when the output's type fits one alternative. Every alternative carries a tag field (kind: Literal['given']), so an output that should fit a union must be of a tagged class. A producer then has to know its consumers. The form spike (#89) shows the cost. The toy FIND_CENTRE outputs BeamCentre, which fits IOFQ's beam_centre: BeamCentre, but not a union GivenCentre | FindCentre. So the spike needed a second finder that outputs a tagged GivenCentre(BeamCentre). Reference-only alternatives such as ComputedTransmission carry a tag that no request ever writes.

Proposal. A place given by reference is a plain group, possibly typed X | None. A union of groups is written inline only:

beam_centre: BeamCentre = BeamCentre()      # typed in, or from a record: finder.ref('centre')
beam_centre: Annotated[GivenCentre | FindCentre, Field(discriminator='kind')] = GivenCentre()
                                            # typed in, or found in this graph; no reference fits
  • WorkflowSpec refuses an alternative that a request cannot write inline, i.e. one with a data value.
  • A request with a reference at a union place is refused at submission.
  • The params schema of a union has no reference form.
  • In a generated UI, a group offers {its fields, a record}, and a union offers {its alternatives}. None adds one option to either.

Removed: tags on outputs; tagged reference-only alternatives (ComputedTransmission with kind); reference fitting for unions (the union branches of fits and of the reference schema in _forms); the mixed group/union/record case in UIs. Tags stay as pydantic-native kind fields on input groups, as in scipp/esslivedata#1426.

What has to change:

  • Story C2: normalization: ComputedNormalization | PublishedNormalization | None. It becomes ComputedNormalization | None, given by reference. A published normalization file reaches it through a loader workflow that outputs a ComputedNormalization. In general, "a record, or another way" becomes "a record", plus a workflow that produces the output type from the other way.
  • README and ADR 0008 examples: transmission FromFile | ComputedTransmission, and a beam-centre union that accepts finder.ref('centre').
  • Spike feat: Panel forms and apps generated from specs, and the client calls they need #89: drop LOCATE and GivenCentre's second role, and the union's record option.

What is given up: one place can no longer offer "type it in, compute it here, or take it from a record" together. The spec author picks one style. No story needs the mix.

Out of scope: each case above is Computed | File, an output of a workflow or a file of the same data. A way to support that, or hide the difference, may come later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions