Three Rules for a Kernel Grammar and What Each Costs
Updated
Knowledge on this page was mainly distilled from Malleable Software Needs a Kernel You Can Still Change.
A kernel grammar is the published middle layer of a malleable product. It is a fixed list of words naming the kernel's primitives, plus rules for combining them, and a model composes every capability a customer asks for inside it. The claim here is that this layer holds only if three rules are kept together. Drop any one of them and you get a system that generates features beautifully and can never be changed underneath them. Each rule also carries a real cost, and accepting that cost is part of the design.
Two checks at two different times
The rules depend on keeping two moments apart.
- Compose time. The customer describes what they want, and the model translates it into a sentence in the grammar. The system checks whether the words exist, whether the combination is legal, and whether the types agree. It then refuses with a reason or stores the sentence in the customer's account. Nothing has touched data yet. The question is: can this be said?
- Run time. On every execution, the kernel loads the stored sentence and checks that it is still legal, because the grammar may have moved since it was written. It resolves each word to what that word means today. Then it checks permissions for the person running it right now, against the rows in front of it. The question is: may this person do this, now?
The grammar is checked twice, but only the second check is a security boundary. The first asks whether a sentence is legal, and then it finishes. The second is still on duty while the capability is doing something.
Rule 1: One grammar, and no way around it
There is no escape hatch and no arbitrary-code rung at the top of a ladder for the hard cases. The moment such a rung exists, everything expensive migrates onto it, and the vendor is back to owning code it cannot read.
Cost: the hard cases have nowhere to go, and you will hear about it. That complaint can be useful, because it tells you exactly where the grammar ran out.
Rule 2: The grammar translates, the kernel enforces
The grammar turns a customer's sentence into the vendor's own operations. It never decides who may read what. The kernel decides that, while the capability is running. It is tempting to give the grammar the permission job too, because a bounded language looks like a safe one. But a security boundary has to hold still, and a translation layer has to be free to move. Fuse them and you can never change a word again.
Cost: you build the permission model yourself, in the kernel, in terms it can check on every call.
Rule 3: Every word is a definition you own
A word is not a name for something underneath. It is a definition, a promise about meaning.
Cost: you can never quietly drop a word, because publishing one is a promise.
Where near-miss designs give a rule up
An August 2026 post on r/softwarearchitecture laid out most of this shape: a stable host owning domain invariants, a capability ladder, provenance, and governance. Two of its choices relax the rules. It keeps arbitrary code on the ladder as an escalation path for hard cases, and it lets the capability layer do the enforcing. Remove the escape hatch, and let that layer translate while the kernel enforces, and you get an answer to the item the post itself could not resolve: what happens to generated extensions when the thing underneath them has to move.
The rules cannot be retrofitted
The migration a vendor ultimately sells, keeping ten thousand private capabilities working as the kernel moves, is only possible if the grammar was built under all three rules from the beginning. They cannot be added afterwards.
Q&A
Isn't the compose-time check enough to keep a capability safe?
No. The compose-time check only confirms that a sentence is legal: the words exist, the combination is allowed, and the types agree. It finishes before any data is touched and knows nothing about who will run the capability later. Only the run-time check, which evaluates the current person against the current rows on every execution, is a security boundary.
Why re-check legality at run time if the sentence was already checked when stored?
Because the grammar may have moved since the sentence was written. A capability can sit in a customer's account for months while the vendor changes the grammar. At run time the kernel confirms the stored sentence is still legal and resolves each word to what it means today, rather than trusting a check made against an older version.
Why not allow an arbitrary-code escape hatch just for rare hard cases?
Because it does not stay rare. The moment an arbitrary-code rung exists, everything expensive migrates onto it, and the vendor is back to owning code it cannot read, search, or change. Keeping one grammar means hard cases get refused instead, which is uncomfortable but tells you precisely what the grammar cannot yet say.
Does owning every word as a definition mean the code behind a word can never change?
No. The promise is about meaning, not machinery. A word commits you to what it means, while the implementation behind it can change on any Tuesday. What the third rule forbids is quietly dropping a word or letting its published meaning disappear without a deliberate decision.