SHAPE

SHIFT

Back to homepage

Languages Become Interfaces

Most language interoperability starts at the wrong layer.

It starts with calls.

Can JavaScript call Rust? Can Swift call C? Can Python call a TypeScript service? Can WebAssembly sit between them?

Those are useful questions, but they are not the deepest question.

The deeper question is:

what does each side believe the program means?

If two languages only share a call boundary, they can exchange bytes, handles, objects, or messages. That is not the same as sharing state identity, type shape, permissions, effects, ownership, runtime assumptions, or proof.

The stronger form of interoperability is semantic.

InteroperabilityProjected
One Meaning, Many Languages
Shared contract
identity, state, actions, effects, typesLanguages meet through stable meaning, not through one target syntax.
Native implementations
Rust, TypeScript, Swift, Python, HTML, CSSEach language keeps its idioms while binding to the same contract.
Interop evidence
source spans, adapters, gates, runtime proofA boundary is trusted only to the degree that it can explain what survived.
Known loss
weaker types, missing ownership, runtime-only checksInteroperability should record loss instead of hiding it behind a successful build.
Languages become interoperable when they can attach to the same semantic contract and expose what each projection preserved.

Not One Language

The goal is not to replace every language with one universal syntax.

That would miss why languages exist.

Rust is good at making ownership and lifetimes explicit. TypeScript is good at expressing structural API shape in a JavaScript ecosystem. SwiftUI is good at native UI declaration. CSS is its own runtime for cascade and layout. SQL expresses relational constraints. Python is often the fastest way to bind data tools and operational scripts.

The point is not to flatten those differences.

The point is to let those differences attach to one semantic boundary.

Rust keeps ownership.
TypeScript keeps structural API shape.
SwiftUI keeps native view idioms.
CSS keeps cascade semantics.
Python keeps orchestration ergonomics.
 
The shared layer keeps identity, contracts, effects, proof, and loss.

That is a different promise than source-to-source translation.

Translation says:

turn this language into that language

Interoperability says:

let these languages cooperate without lying about what each one can express
The interlingua is not a replacement language. It is the place where source languages and target languages agree on stable meaning.

The Contract Is The Meeting Point

Imagine a search capability.

One part is implemented in Rust because the index needs speed and ownership discipline. Another part is exposed in TypeScript because the product shell is web-based. A native client wants SwiftUI. An automation system wants a command interface. A dashboard wants HTML, CSS, and runtime probes.

The old shape is a pile of adapters:

Rust library -> Node binding -> TypeScript wrapper -> API route -> Swift client -> dashboard widget

Every edge has a private agreement.

The semantic shape is different:

capability SearchIndex @id("cap_search_index") {
  capability search.query
  input SearchQuery
  returns SearchResults
  effects cpu.read, storage.read
  resources SearchCorpus.documents
}
 
action runSearch @id("action_run_search") {
  input SearchQuery
  returns SearchResults
  reads SearchCorpus.documents
  uses search.query
}

Now each language is not integrating with every other language directly.

Each language is integrating with the contract.

One Contract, Several Language Edges
1capability SearchIndex @id("cap_search_index") {2  capability search.query3  input SearchQuery4  returns SearchResults5  effects cpu.read, storage.read6  resources SearchCorpus.documents7}8 9action runSearch @id("action_run_search") {10  input SearchQuery11  returns SearchResults12  reads SearchCorpus.documents13  uses search.query14}
Shared meaningThe contract names the capability, action, data boundary, effects, and identities before choosing an implementation language.
Interoperability is not every language copying every other language. It is each language binding to the same semantic contract with its own projection evidence.

The ABI Moves Up

An ABI normally describes how compiled code talks at the machine boundary.

Calling convention. Memory layout. Symbol names. Registers. Stack shape.

That still matters.

But for malleable software and agent-built systems, the more important ABI moves up:

this is the stable identity
this is the data shape
this is the ownership rule
this is the effect boundary
this is the runtime assumption
this is the proof required before use

That higher-level ABI is what lets software be composed across languages without turning every boundary into bespoke glue.

Interop MatrixWhat Has To Cross The Boundary
SurfaceClaimRequired proofCurrent evidenceRoute
ProvedIdentityBoth sides refer to the same capability or actionStable semantic id@id, symbol map, generated bindingPreserve
RequiredData shapeInputs and outputs still mean the same thingType/declaration compatibilitySchema, generated declarations, codec fixtureGate
RequiredEffectsA caller cannot secretly gain new authorityCapability and policy checkEffect list, host grant, audit eventAdmit or block
reviewOwnershipBorrow, copy, move, or lifetime assumptions are not erasedOwnership constraint evidenceRust facts, adapter rule, runtime handle policyAdapt
ProvedRuntimeThe projection behaves under real conditionsExecutable probeRoute probe, telemetry hash, fixture resultPromote
BlockedLossThe target cannot express something directlyDeclared loss recordMissing type fact, weaker runtime guard, adapter noteAsk or fail closed
A semantic ABI is useful because it makes the boundary inspectable before languages start executing each other.

Interoperability Is Not Equivalence

This is the part that has to stay honest.

Two projections can be interoperable without being equivalent in every local detail.

A Rust implementation may prove ownership statically. A JavaScript caller may only preserve the call contract and rely on runtime checks. A SwiftUI surface may preserve the action and data shape but add UI lifecycle behavior. A CSS projection may preserve selectors and tokens while leaving layout proof to a browser probe.

The system should not pretend those are the same.

It should say:

same identity
compatible data shape
different enforcement mechanism
adapter required
runtime proof required
loss recorded

That honesty is what makes the system useful.

  1. Name matchweak
    Can proveThe target has a symbol that claims to implement the contract.
    Stops atDoes not prove shape, authority, or behavior.
    Bind candidate
  2. Shape matchpartial
    Can proveInputs, outputs, and public declarations line up.
    Stops atDoes not prove effects or runtime behavior.
    Run compatibility gate
  3. Capability matchbounded
    Can proveThe target only reads, writes, and effects what the contract allows.
    Stops atDoes not prove target runtime conditions.
    Admit authority
  4. Runtime probeobserved
    Can proveThe projected boundary is exercised under declared conditions.
    Stops atOnly covers the probed states and environments.
    Admit behavior
  5. Loss accountstrong
    Can proveAnything not preserved is explicit enough to route, review, adapt, or refuse.
    Stops atDoes not make the lost feature safe by itself.
    Decide boundary
The boundary becomes more trustworthy as it moves from naming to proof.

Routing Instead Of Glue

Once language boundaries become semantic, the system gets a better set of choices.

It does not only compile or fail.

It routes.

Interop RoutingWhat The Boundary Can Decide
RouteSignalRequiresProduces
AdmitIdentity, type, effect, runtime, and loss evidence passFresh proof against the current contractUsable cross-language binding
Generate adapterMeaning is compatible but target idioms differAdapter template plus source/target span mapProjection with adapter evidence
SandboxThe target needs authority or runtime behavior outside the default grantCapability boundary and audit trailRestricted execution boundary
AskThe system cannot decide whether a loss is acceptableA narrow human questionA durable answer or refusal
RejectThe target would misrepresent ownership, effects, data, or runtime behaviorRecorded blockerNo binding; sharper future work item
Semantic interoperability turns language integration into an admission problem instead of a pile of private glue code.

What Changes

This makes languages feel less like sealed worlds.

Not because their syntax disappears.

Because their useful meanings become addressable.

A Rust module can provide a capability to a TypeScript shell. A SwiftUI view can mount over a contract authored somewhere else. A Python worker can consume the same action surface as a browser UI. A CSS layer can bind to design tokens whose identity survives a projection. A plugin can be written as a semantic contract and lowered into several hosts.

The important move is that the boundary stops being:

language A calls language B

and becomes:

language A and language B both attach to contract C

That is why semantic merging and language translation are the same project.

If the system can prove what changed, it can merge. If it can prove what survived, it can project. If it can prove what a boundary means, languages can interoperate without collapsing into one language.

The future is not one perfect programming language.

It is many languages connected by contracts that can be inspected, lowered, tested, merged, and refused.