ControlledGraph API
Core controlled-graph attachment, canonical snapshots, change requests, and diagnostics.
attachControlledGraph(engine, callbacks) declares “controlled” authority,
installs the line reconciler, and returns the handle the application pushes
canonical snapshots through:
| Handle member | Meaning |
|---|---|
setCanonicalGraph(snapshot) | Cache the latest CanonicalGraphSnapshot ({ lines: LineRecord[] }) and schedule one coalesced reconciliation pass — the only inbound canonical channel |
flush() | Run any pending reconciliation synchronously (vanilla apps and tests) |
dispose() | Detach the reconciler |
A LineRecord is { id, fromConnectorId, toConnectorId, payload? } with
application-owned stable ids. Node and connector existence stays
framework-mount-led; the snapshot carries only line records.
Change requests
callbacks.onLineChangeRequest(request) receives one atomic LineChangeRequest per gesture: an intent ("connect" | "disconnect" | "replace" | "reconnect") plus add (ProposedLine[] with SnapLine-minted ids), remove (LineId[]), update (LineEndpointUpdate[]), and the originalEvent. Apply the proposal to your
records and push them back through setCanonicalGraph — adopting a proposed
id settles the staged line in place; pushing unchanged records rejects it.
Diagnostics
callbacks.onDiagnosticsChanged(diagnostics) and query(engine).diagnostics() expose the current ReconciliationError[]. code is one of:
| Code | Meaning |
|---|---|
"duplicate-id" | A record id appears more than once in the snapshot; the first record wins |
"capacity-exceeded" | A record violates a connector’s maxIncoming |
"connection-rejected" | An endpoint’s isValidConnection vetoed the record |
Reconciliation never rewrites, reorders, or deletes canonical records: a record the mirror cannot represent stays latent (endpoints not mounted; silent) or errored (rules violation; structured diagnostic) and is retried when relevant state changes.