Complete source 6 engineering workflows and preserve release validation evidence
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
# 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](fixtures/interface-operation-probe/README.md)
|
||||
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`:
|
||||
|
||||
```rust
|
||||
#[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:
|
||||
|
||||
```rust
|
||||
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.
|
||||
Reference in New Issue
Block a user