SHAPE

SHIFT

Back to homepage

Plugins Are Semantic Contracts

Most plugin systems start with loading code.

That is useful, but it is not the interesting part.

The interesting part is the boundary.

A plugin wants to enter a host. The host has state, UI surfaces, permissions, policies, data shapes, effects, users, runtime quirks, and failure modes. If the plugin boundary is just a package import or a JavaScript bundle, the host has to trust too much too early.

The better shape is a semantic contract.

A plugin should say what it provides, what it requires, where it mounts, what it can read, what it can write, which effects it may run, which runtime it needs, and what evidence would prove that it fits.

Plugin BoundaryAdmissible
One Extension Contract
Host exposes
mounts, state views, actions, effects, gatesThe host publishes the surfaces a plugin can safely depend on.
Plugin provides
views, commands, workers, rules, projectionsThe plugin contributes capabilities, not just files.
Plugin requires
capabilities, data shape, policy, runtimeRequirements are visible before the host admits the plugin.
Admission proof
type, policy, preview, runtime, rollbackInstallation becomes a decision with evidence, not a blind load.
A semantic plugin boundary names the contract before code crosses into the host.

Loading Code Is Not Enough

A traditional plugin system often has a shape like this:

host app -> plugin API -> plugin bundle

That shape answers one question:

can the host call the plugin?

But the harder questions are different:

what does the plugin believe the host contains?
which state can it read?
which state can it mutate?
which effects can it run?
which UI surface can it occupy?
which runtime does it assume?
which version of the contract was it built against?
what proof says it still works?
what happens when the host changes?

Those are semantic questions.

If they are hidden inside code, every plugin install becomes a trust exercise. If they are represented as a contract, the host can route the plugin: admit it, sandbox it, adapt it, ask a human, or block it.

The Host Exposes A World

A host application should not expose itself as a bag of callbacks.

It should expose a world.

That world contains typed mount points, readable state views, callable actions, effect capabilities, event streams, policy rules, and gates.

For example:

host Dashboard @id("host_dashboard") {
  mount sidebar @surface("navigation.sidebar")
  mount panel @surface("dashboard.panel")
 
  state CurrentUser @readonly
  state WorkspaceSummary @readonly
 
  capability host.fetch {
    effect network.fetch
    policy same_origin
  }
 
  action openPanel {
    input PanelRoute
    writes ui.route
  }
 
  gate previewProbe {
    checks layout, focus, accessibility
  }
}

This is not a widget API.

It is the host saying: these are the places an extension can appear, these are the resources it can ask for, and these are the proofs required before it becomes real.

The Plugin Declares Its Shape

The plugin should be equally explicit.

plugin WeatherWidget @id("plugin_weather") {
  mounts host.dashboard.panel
 
  provides view WeatherPanel {
    reads WorkspaceSummary.location
    uses host.fetch
    emits openPanel
  }
 
  requires capability host.fetch
  requires gate previewProbe
 
  fallback view WeatherUnavailable
}

The important thing is not the exact syntax.

The important thing is that the plugin can be reasoned about before the host executes it.

It has a mount. It has a provided view. It has declared reads. It has a capability requirement. It has a gate. It has a fallback.

That gives the host a review object.

Projection Is The ABI

An ABI is usually thought of as a low-level calling convention.

For this kind of system, the useful ABI is semantic.

The host and plugin do not need to share one implementation language. They need to share stable meaning: mounts, capabilities, state shapes, actions, effects, identities, and proof obligations.

One Plugin Contract, Several Projections
1plugin WeatherWidget @id("plugin_weather") {2  mounts host.dashboard.panel3 4  provides view WeatherPanel {5    reads WorkspaceSummary.location6    uses host.fetch7    emits openPanel8  }9 10  requires gate previewProbe11  fallback view WeatherUnavailable12}
Semantic contractThe authored boundary names the mount, provided view, reads, capability use, emitted action, gate, and fallback.
A semantic plugin contract can lower into different runtimes because the shared boundary is not the target syntax. It is the declared meaning.

This is where Frontier-style representation matters.

The plugin can be written once as a contract, projected into a host-specific implementation, and still carry the proof that says what survived.

Admission Is The Install Step

Installing a plugin should not mean copying code into the host.

It should mean admitting a capability through a boundary.

Plugin AdmissionWhat A Plugin Has To Prove
SurfaceClaimRequired proofCurrent evidenceRoute
ProvedMountThe plugin fits a host surfaceMount identity and slot contracthost.dashboard.panel exists with matching view shapeAdmit mount
RequiredAuthorityThe plugin can use requested capabilitiesPolicy, role, effect, and scope checkhost.fetch allowed under same-origin policyAdmit or sandbox
RequiredStateReads and writes stay inside the contractState-view and action-boundary checkReads WorkspaceSummary.location, emits openPanelAdmit or adapt
MissingRuntimeThe projected UI behaves in the hostPreview, layout, focus, accessibility, rollbackPreview probe required before durable installRun gate
RequiredTranslationThe target implementation preserves the contractSource-span, identity, and loss accountingProjection evidence records no known lossAdmit or review
The host can admit a plugin only to the degree that its claims are proved.

The useful result is not just safer extension.

It is more malleable software.

Plugins stop being vendor-specific bundles. They become bounded capabilities that can move between hosts when the semantic boundary matches.

The Host Can Route The Plugin

A semantic contract gives the host choices.

The host does not need to say only yes or no.

Plugin RouterBoundary Decisions
RouteSignalRequiresProduces
ApplyMount, policy, state, runtime, and projection proof all passCurrent host contract and rollback handleDurable plugin install
ReviewPlugin is useful but crosses a sensitive boundaryHuman or coordinator approval over the remaining claimDecision record
RebaseHost changed but the plugin intent still fitsFresh projection against the current host contractUpdated plugin candidate
RerunRuntime proof is stale or missingPreview probe, accessibility check, or effect replayNew evidence bundle
AskThe plugin needs authority the host has not declaredTyped policy question with scope and alternativesAnswer node or rejected requirement
BlockThe plugin asks for an unsafe effect or incompatible mountRecorded non-admissionNo install, plus a sharper contract row
A semantic plugin system routes extension work by evidence instead of reducing everything to install or fail.

That routing is the difference between a plugin ecosystem and a controlled extension surface.

Plugins Become Composable Capabilities

Once plugins are semantic contracts, composition gets more interesting.

A plugin can provide a view to one host, a command to another host, and a worker to a third host. A host can expose only the mounts and capabilities it is willing to admit. A translator can lower the same plugin contract into React, SwiftUI, HTML, a CLI command, or an agent tool manifest.

The plugin boundary becomes less like:

download this package and hope it behaves

And more like:

this capability can mount here
this state view is readable
this effect is allowed
this target projection is proved
this fallback exists
this install can be rolled back

That is a much stronger foundation for user extension, internal tools, agent-built software, and cross-language projection.

The larger idea is that a plugin is not an escape hatch from the system.

It is a request to join the system.

And if software is represented semantically, that request can be inspected, translated, tested, routed, and admitted without pretending that loading code is the same thing as trusting it.