The Language Stack Becomes A Constraint Stack
Programming languages are usually described as higher level or lower level.
That is true, but it hides the useful part.
Higher-level languages tend to expose more human and domain semantics: screens, actions, state machines, APIs, permissions, components, contracts, policies, workflows.
Lower-level languages expose more execution semantics: memory layout, ABI, registers, flags, cache behavior, interrupts, timing, device I/O, binary shape.
Those are both semantic.
They are just semantic at different altitudes.
The interesting move is to stop treating the language stack as a ladder and start treating it as a stack of constraints.
Abstraction Is Not One Direction
High-level code is semantic because it names intent.
show a checkout flow
only admins can approve refunds
render a keyed list of invoices
call search with a bounded capability
preserve the public User contractLow-level code is semantic because it names obligations.
write this register
preserve this calling convention
do not clobber this flag
fit inside this timing window
read from this memory-mapped device addressThe mistake is thinking that only the top has meaning.
The top has product meaning. The bottom has execution meaning. The system is trustworthy only when it can relate the two.
That is why a semantic interlingua gets strange.
It has to be high enough to hold a product contract and low enough to say what was lost when that contract was lowered into a concrete runtime.
A Stack Of Claims
The useful unit is a claim.
this view is the checkout step
this action mutates the order state
this effect reaches storage
this type shape is the public API
this adapter preserves ownership
this lowered code obeys the ABI
this routine touches the PPU registerA claim by itself is not enough. It needs a constraint and a proof.
Frontier Sits In The Middle
This is what makes Frontier feel both high level and low level.
It is not trying to be “above” every language in the normal abstraction sense.
It is trying to be between meanings.
It can hold a domain-level action:
action approveRefund @id("action_refund_approve") {
input RefundApproval
mutates Order.refundState
requires capability finance.refund.approve
effects audit.write, payment.refund
}It can also hold lowering obligations:
projection nativeRefundWorker -> rust {
preserves action_refund_approve
requires ownership unique RefundApproval
requires abi stable payment_gateway_v2
proves type_gate, effect_gate
}
projection refundDeviceRoutine -> asm-65816 {
preserves action_refund_approve
touches memory $2100..$21FF
clobbers a, x, p
requires bank_state, cycle_trace
}Those two snippets are not the same kind of thing.
But they can be part of the same semantic record because they are both constraints over the same claim.
1action approveRefund @id("action_refund_approve") {2 input RefundApproval3 mutates Order.refundState4 requires capability finance.refund.approve5 effects audit.write, payment.refund6}Lowering Is Constraint Accounting
Lowering is usually described as compilation.
But for semantic systems, lowering is also accounting.
It asks:
which claims survived exactly?
which claims became target-specific constraints?
which claims need runtime proof?
which claims became known losses?
which claims cannot be represented in this target?If a React component lowers into HTML, CSS, and JavaScript, the system should not only ask whether the output runs.
It should ask whether the keys survived, whether ARIA relationships survived, whether focus behavior survived, whether layout movement is bounded, whether event handlers still point to the same capability, and whether style changes stayed inside their declared cascade region.
If Rust lowers toward WebAssembly, the system should ask which ownership facts were proved before lowering, which memory effects are visible at the host boundary, which imports and exports exist, and which host capabilities the module can reach.
If a routine lowers into assembly, the system should ask which registers it clobbers, which flags it mutates, which memory regions it touches, whether its timing matters, and whether the binary can be mapped back to the source claim.
Lifting Is Loss Accounting
The reverse direction is not symmetrical.
Assembly can represent machine behavior. It cannot, by itself, tell you which product workflow the behavior belonged to.
A minified bundle can represent browser behavior. It cannot, by itself, tell you the original component boundaries with full confidence.
A database migration can represent a schema transition. It cannot, by itself, tell you every application-level invariant the old schema carried.
Lifting low-level artifacts back into the semantic layer is still useful, but the result must be humble.
binary -> instruction graph
instruction graph -> effect hints
debug symbols -> partial source identity
source maps -> stronger source identity
runtime traces -> observed behavior
missing maps -> known lossThat humility is not a weakness. It is what makes the system trustworthy.
The semantic layer should be able to say:
we know this routine writes $2115
we know it branches to write_refund
we know it clobbers A and P
we do not know that it still implements approveRefund
unless a source map or receipt binds it to that claimMerging Changes With The Stack
Semantic merge becomes more powerful when it can look above and below the text.
But it also becomes more conservative.
A text patch might be easy to apply. A semantic patch might still be unsafe because it changed a constraint at another layer.
renamed a function
safe if callers and public API proof rebase
changed a CSS selector
safe if DOM targets and cascade proof still hold
changed a Rust lifetime
safe if ownership proof still holds
changed an assembly routine
safe only if register, flag, memory, timing, and symbol proof still holdThe system should not ask, “did the text merge?”
It should ask, “which claim changed, which constraints moved, and which proof is still valid?”
The Weird Shape Is The Point
Frontier is strange because it is not trying to be only an application language, only a compiler IR, only a schema language, only a proof object, or only a runtime manifest.
It is trying to hold the semantic contract between those things.
That means it needs language features that feel high level:
capabilities
actions
views
resources
effects
policies
workflows
public contractsAnd it needs language features that feel low level:
source spans
layout constraints
ownership facts
ABI boundaries
memory regions
register effects
runtime traces
known lossesThat combination is not decorative.
It is what lets software become more malleable without becoming less trustworthy.
If the stack is explicit, then a system can change at the level the user means while still knowing what lower layers must prove.
If the stack is explicit, then a compiler can lower into many targets without pretending every target preserved the same meaning.
If the stack is explicit, then a merge system can admit more parallel work while refusing the parts it cannot prove.
The end state is not one perfect language above all others.
It is a shared constraint stack where languages can project, merge, interoperate, and fail closed without hiding the layer where meaning changed.