Files
ARCADIA-Studio/harness/release-interface-operation-contract-20260906.md
T

12 KiB

Interface-operation message contract — proposal and falsifier, 2026-09-06

Status: contract/experiment only. No shared production edit, Cargo, or native input. This proposal requires independent critique and root approval before implementation.

Experiment outcome

Standalone existing-core probe builds a valid System/Actor boundary with one provided/required interface and two Synchronous Operation items, Reset and ReadStatus. Both have zero parameters. Calls with the same participant pair/channel have identical typed bodies despite their different names. Item/allocation substitutions for exchange reject; an operation JSON field rejects. Reset rename/delete does not affect its intended Call body, which remains structurally valid. This is a missing maintained semantic reference.

A valid alternative adds two Functions, four function ports, two FunctionalExchanges, two performer allocations, four port allocations and two exchange allocations. Its Calls select distinct FunctionalExchanges while retaining the original boundary. That is six additional elements/ten relationships, not a different notation for the same interface-only model. It is appropriate when the functional refinement is part of the engineer's design; it must not be fabricated solely to address an interface operation. All three probe models pass complete JSON/source round trips.

Alternatives and selected direction

Choice Tradeoff
Name/guard or generic constraint Can describe intent, but supplies no closed operation-use slot or automatic endpoint/lifecycle validation. Does not close the demonstrated gap.
Select only ExchangeItem Distinguishes Reset from ReadStatus but loses which interface allocation supplies its protocol/acquisition context; one item may occur in several interfaces.
Select InterfaceItemAllocation Reuses an existing identified relation, preserving interface, operation item and protocol context. Recommended.
New operation occurrence constructor / whole message-target union Can support channel-free interface scenarios later, but broadens constructors, old histories and UI beyond this demonstrated shared-channel case. Not required for the first slice.
Infer sole carried Operation item Ambiguous with multiple or zero-parameter operations and unstable when another item is added. Reject inference even when there happens to be one item.

Proposed persistent field in existing OccurrenceBody::Exchange:

#[serde(default)]
operation: Option<Id> // InterfaceItemAllocation identity, never an item or port

Text: operation @reset_service_allocation; or operation none;. JSON uses the existing externally tagged Exchange record with this optional UUID. No separate stored item/interface/provider fields: derive them through the selected allocation and validated message endpoints. The field is authored on Call/Asynchronous; Reply derives the operation from its exact correlated Call and must store None. This prevents two redundant identities disagreeing after edits. Display the derived operation on Reply as read-only provenance.

Applicability and validation

This bounded slice applies to SA BoundaryInterface scenarios with an explicit BoundaryExchange channel, participant lifelines and concrete component endpoints. Existing operation=None scenarios, including Functional and MixedLegacy, retain their prior meaning. New operation selection in MixedLegacy requires explicitly choosing BoundaryInterface; it must not silently reinterpret that viewpoint. OA participant channels remain operational communication and do not acquire invented technical ports/interfaces. Channel-free interface messages are a separate future design, not implied by this field.

Resolve the actual sender/receiver participant and corresponding boundary ports using the existing directional scenario resolver, including reversed traversal of an unoriented channel. Never assume stored boundary source is the caller. Require:

  • Existing same-SA-layer InterfaceItemAllocation whose target is an Information ExchangeItem with mechanism Operation; the channel carries that item through the existing effective-item/subtype rules.
  • Concrete Standard component ports. The actual receiver provides an interface exposing that exact allocation; the actual sender requires a compatible interface also exposing it. Reuse effective_interface_allocations and existing interface_satisfies inheritance rules. An item present through a different allocation is not interchangeable with the selected protocol context.
  • Call selects Synchronous transmission. Asynchronous selects Asynchronous transmission and has no correlated Reply. Unspecified transmission remains a visible incomplete-contract warning; explicit incompatible transmission rejects. Do not invent transport multicast/broadcast call-return semantics in this slice. Existing acquisition compatibility remains governed by the allocation validator.

Known wrong kind/layer/port/interface/direction/mechanism is a structural error. Unfinished sender/receiver or missing operation after an explicit operation-use edit is a warning while the candidate is otherwise safe; no automatic endpoint or operation choice. The exact warning distinction needs an operation-intent marker if None must distinguish ordinary channel calls from cleared operation calls: prefer a closed OperationSelection::{Unselected, Selected(Id)} optional field if testing confirms the plain Option cannot retain that distinction. See the open decision below; do not silently encode intent in names/history.

Calls, replies and values

Existing exact call/reply identity, order, reverse participant and repetition checks remain authoritative. Reply derives the operation from its Call; an independent Reply selection rejects. Editing Call's operation replans/validates all correlated Reply values atomically before admission.

Use the selected item's effective data-field paths, not the union of every item on the channel. Call values permit In/InOut; Reply permits Out/InOut/Return. Unspecified parameter direction warns until clarified. Asynchronous operation values use input parameters and cannot carry Return values. Parameterless calls need no fabricated field. Keep raw value drafts on operation changes; reject or require explicit value removal when a retained field is no longer applicable. Never insert defaults or prune authored expressions merely on picker change.

Lifecycle, transition and representation obligations

Surface Required contract and falsifier
References and deletion Visit allocation selection as a typed relation reference. Rename shows the new item/interface label without rewriting message prose. Reidentify allocation/item/interface preserves selection through existing visitors. Deleting allocation/item clears selection to an explicitly unresolved operation use, retains Call and correlated Reply, prunes only proven invalid live field references under normal delete policy, and creates a located warning. One Undo restores all identities/source. Removing provision/channel changes must validate dependents or offer an explicit repair batch; never switch to another matching allocation.
Transition Preserve source. OA→SA existing operation=None remains None; choosing a technical operation is an explicit SA refinement. SA→OA has no direct operational operation contract in this bounded design: preview must require explicit reviewed omission/abstraction, not silently drop the selection or invent OA ports. Proposed per-occurrence request decision OmitOperation { source, rationale } is needed if this transition is allowed; unknown/irrelevant decisions reject and omission is shown as a planned impact. Without that decision, refuse with a precise unsupported-projection message. Keep mapped channel, Call/Reply and values only when independently admissible. Same-layer/review mapping resolves allocation identity through its interface/item counterpart.
Semantic review Add a closed optional allocation-reference facet, e.g. OccurrenceFacet::Operation, to observed/current/history and constructor scope. Compare its actual field slot; preserve invalid candidates and excluded rows. Derived Reply operation has no second independently writable slot. Operation changes plus value edits must compose on one frozen base; conflicting selections remain explicit. Operation omission across layers is not an ordinary mapped Take.
Source/JSON/API Current source6 rejects new fields; introduce the next schema/source version coherently with any approved S1 change. Old input defaults to ordinary exchange behavior, never guesses an operation. Extend parser/writer/updater/reference spans, strict schemas/OpenAPI examples, migration rejection tests and commands; old historical DTOs remain frozen. Every modified relationship/value and history update must preserve unrelated source/comments and one command boundary.
Desktop In the existing scenario form, show an optional Operation-use control followed by a named allocation picker (Interface · operation · protocol). Filter choices by the proposed actual participant/channel context; no name inference. Preserve a rejected selection visibly when context changes rather than silently dropping it. Call and Reply labels make the selected/derived operation readable, including parameterless messages. Use the existing scenario canvas and draft/recovery machinery.
Recovery and history Persist exact operation intent/selection and rejected raw drafts; rebuild previews against the recorded base. A source-version migration must upgrade checkpoint accepted bundles/fingerprints through a proved adapter and reset approvals, not merely change schema numbers. Both old-v6 normal restore and new-version exact restore need tests; prior source5 recovery does not automatically prove this.

One open DTO choice to settle before coding

Plain Option<Id> is the smallest structural addition but conflates an ordinary channel Call with an authored operation Call whose allocation was deleted. To preserve explicit unresolved intent without inventing a tombstone, recommend the following final candidate, replacing the shorthand above:

operation: Option<OperationUse>
struct OperationUse { allocation: Option<Id> } // deny_unknown_fields

None means ordinary existing channel-message semantics; Some(allocation=None) means operation use requiring selection; Some(Some(id)) is a selected allocation. Reply still stores None and derives the Call's OperationUse. This is one authored semantic slot, with a maintained live reference inside it. Text renders operation { allocation @reset_service_allocation; }; and unresolved operation { allocation none; };. Migration default is None. Review must preserve the outer None versus explicit unresolved shape, as it already does for other closed optional/constructor observations. This is the recommendation to critique, not a field already added to core.

Decisive next tests

Before GUI wiring: same-boundary Reset/ReadStatus selections differ and survive rename/reidentify; selected allocation deletion yields unresolved operation intent; two interfaces containing the same item retain distinct protocol identities; inherited provider/required interfaces resolve the actual allocation; reverse unoriented channel uses actual caller/receiver; wrong provider/mechanism/protocol rejects unchanged; changing Call operation invalidates incompatible Reply values without data loss; explicit SA→OA omission versus missing decision; both semantic review directions with mapped/NotApplicable slots; full source/API/history/recovery round trips. Include the original parameterless fixture so parameter-value inference cannot accidentally substitute for operation identity.