Skip to content

feat(runtime): materialize binding and flow usages as connector objects - #474

Open
devin-ai-integration[bot] wants to merge 3 commits into
developfrom
feature/binding-flow-connector-objects
Open

devin-ai-integration[bot] wants to merge 3 commits into
developfrom
feature/binding-flow-connector-objects

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

What and why

A two-ended binding (bind a.p = b.q, binding bnd bind a.p = b.q, binding of x = y) and a non-message flow (flow f of Item from a.p to b.q, flow a.p to b.q) are connectors of the kernel layer, but until now only connect connectors were materialized as connector objects; a binding or flow reached routing and value propagation through lowering and was otherwise invisible in the instance model. This PR materializes both through the same connector path connect uses — no parallel structure — so bnd.source, f.target, feature chains through an end, OwnedConnectors, REPL completion and queries see them like any connector object.

  • semantics/connector.go: new Model.IsConnectorObjectUsage and Model.ConnectorObjectEnds beside the existing IsConnectorUsage/ConnectorEndAttachments, which stay connect-only for views, document queries and passes. Both share one end-naming helper (connectorEndAttachments), so connect ends are named exactly as before; a binding's ends are its two ConnectorEnds, a flow's are FlowEnds.From/To in declaration order. A one-ended binding (bind x;, binding b of x;) and a message are not connector objects.
  • runtime: every object-model consumer (connector.go, instance.go, adopt.go, classifier_behavior.go, subsetting.go, variation.go, repl/complete.go) switches to the wider predicate; anonymousConnectors now asks the semantics for ends instead of counting ConnectorEnds, and anonymousConnectorSymbol gives flows and bindings their own symbol kinds. runtime/binding.go and routing.go are untouched.
  • symbols: a binding usage had no symbol kind (SymbolUnknown), which two passes were compensating for. It is now SymbolBindingUsage (BindingConnectorAsUsage in the semantic annotations and query metamodel), included in the feature kinds, typecheck table and shape features. Because the kind is persisted, the library index record version (26 → 27) and stdlib snapshot version (17 → 18) are bumped and stdlib.snapshot regenerated; the two kind-mapping digests move accordingly.

Known limitation (documented): a flow object does not yet hold its payload.

Specification basis

KerML 1.0 §7.4.6 (connectors; BindingConnector :> Connector, Links::selfLinks), SysML v2 §7.13.2 / §8.3.13 (BindingConnectorAsUsage, FlowConnectionUsage; Connections.sysml), Transfers::flowTransfers. Moves the connector rows of the Structural map in docs/project/spec-compliance.md (the flow/binding row goes ⚠️ → ✅) and removes "Binding and flow connector objects" from "Implementable But Not Yet Done".

How it was verified

  • semantics/connector_test.go TestConnectorObjectEnds (named/anonymous binding and flow, binding of, one-ended binding, message, succession; ConnectorEndAttachments still nil for binding/flow).
  • runtime/connector_test.go: TestBindingConnectorIsAnObjectOfItsEnds, TestFlowConnectorIsAnObjectOfItsEnds, TestAnonymousBindingAndFlowAreOwnedConnectors, TestBindingConnectorEndFollowsAFeatureChain, TestBindingConnectorEndsHoldBoundValues.
  • runtime/robustness_connector_objects_test.go TestRuntimeRobustnessConnectorObjects (unattachable binding/flow ends are typed ErrConnectorEnd with a location and leave no object; unvalued ends; one-ended binding is no connector object).
  • Conformance connector_object_binding_flow.sysml (identity assertions on bnd.source/f.target).
  • Differential routing: runtime/routing_differential_test.go TestRoutingUnchangedByConnectorObjects runs every send_*, port_*, *_routing*, action_port_communication* and binding_* fixture normally and again with every owned connector forced (recursively over held objects) before execution, and requires identical outcomes; the send_bind_relay_* relays are asserted to have run in forced mode.
  • Gates: go build ./..., go vet ./..., gofmt -l . empty, go test -count=1 ./..., training + pilot corpus gates with the require variables set (no ratchet movement), corpus round-trip gate, pilot-library XMI identity gate, scripts/check-doc-ids.py, scripts/changelog.py check, make lint.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

devin-ai-integration Bot and others added 3 commits September 20, 2026 18:53
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 20, 2026 20:31

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

// one of them failing is reported as its own, with the connector kept.
func (ctx *Context) materializeConnectorAs(owner *Instance, connSym, base *symbols.Symbol, id int64, keep func(*Instance)) error {
ends := ctx.model.semantics.ConnectorEndAttachments(connSym)
ends := ctx.model.semantics.ConnectorObjectEnds(connSym)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Connector ends retain stale values

After bnd or f materializes, changing an endpoint leaves its ConnectorEnd.Value stale. The connector stores a value without retaining the endpoint feature.

Learn more

Connector materialization evaluates each attachment once and stores the resulting Value in both Instance.Ends and the synthesized end feature value. SetFeatureValue can later replace the connected feature's value, but the stored connector value has no dependency or reference back to that FeatureValue. This especially affects bindings between scalar attributes, where reassignment is common, and flows whose ends are value features.

Example: Materialize binding bnd bind x = y while both attributes equal 3, then write x = 5. Reading bnd.source still returns 3, although the connected feature now holds 5.

Recommended fix: Represent each materialized end as a reference to its owning FeatureValue, or add invalidation/rebinding that refreshes every attached connector end when that feature changes. Apply the same mechanism to Instance.Ends and named end feature values so both views stay consistent.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the behavior of the shared materialization path: connect connector objects on develop store each end's value once at materialization in exactly the same way, and this PR deliberately routes bindings and flows through that path rather than a parallel one. Making a materialized end a live reference to the endpoint's FeatureValue (for all connector kinds, including connect) is a separate change to materializeConnectorAs/Instance.Ends; left out of this PR to keep it to the object-model gap, and noted as a limitation.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant