Platform / overview
Capabilities, not crates.
Six things the toolchain does, in the order you would meet them. Each section says what the capability means, gives a real example from the repository, and points at the surface or page where you can check it.
9
Surfaces
23
Crates
5
Target backends
model
Model
Structure, relationships and behaviour in one file.
A package declares classes, features, operations, enums, datatypes and vocabularies. Relation ends are declared as a pair, so the compiler can check that both sides agree. A derived feature has a body and no stored value; an operation body is written in the shared expression language.
The point is not notation. Every name inside an operation body is resolved and every expression is type-checked, so a misspelt feature is a diagnostic with a span, not a bug three layers down.
In the repository
examples/support/support.mox declares a Ticket with a refundCents feature, a derived needsRefund predicate and two operations whose bodies are type-checked integer arithmetic.
connect
Connect
Every other surface imports the domain instead of restating it.
A design, a policy, a decision model, an event contract, a case and a deployment model all name the same classes. Imports are resolved by path, and the resolved content is handed to the compiler as pre-compiled artifacts or as source text — the compiler core itself never touches the filesystem or the network.
That is what makes cross-surface checking possible at all: the policy condition and the operation it guards are judged against one type index, not two.
In the repository
examples/support/ is one import-connected application: support.ddd, support.actor, support.dmn, support.evt, support.uc, support.cmmn, support.ifml and support.deploy all sit on support.mox.
validate
Validate
Checks that span surfaces, not just within one.
Within a surface, validation is ordinary compiler work: duplicate names, unresolved references, opposite pairing, inheritance and actor cycles, state machines closed over their enum, guards that type as boolean.
Across surfaces, one more pass checks the wiring between artifacts: a granted capability is carried by an operation or a search, an interaction action binds to exactly one service operation, a subscription consumer names a declared deployment component, and an operation's emitted event is declared in some event contract. The two capability joins resolve during compilation; this artifact-level pass is their lint channel.
In the repository
support.actor grants RaiseRefund to Agent with a condition over Ticket.refundCents; the condition is checked against the domain class, and the grant is checked against the operations the design declares.
generate
Generate
Backends read the artifact. They never read the grammar.
A backend is a pure function from a compiled artifact to output. The Rust backend writes arena-based model code, and an operation body written in Rust is emitted verbatim; the JSON Schema backend writes the wire and API schemas; the Cedar backend writes a policy set and an entity schema; the DMN and CMMN backends write the model their engines evaluate or execute.
Because the input is a versioned JSON contract, a backend can be written in another language, published outside this repository, and pinned by its formatVersion field — no compiler changes required, and no way for it to depend on a parser detail.
In the repository
pherolang gen rust examples/support/support.mox -o support-gen writes Rust from the same source that pherolang ir serialises, and the two cannot disagree about the model shape.
verify
Verify
Claims with an evidence class, and a review date where one is required.
The proof-obligation register enumerates what the compiler claims about its own structures, and what backs each claim: a proof obligation, a test, a code pointer, an argued residue, or a declared assumption. The statuses are proved, tested, argued and assumed — and each row is required to state the weakest honest one.
The verify command turns that into a receipt: the closure of source files it was checked over, the artifact hashes, and the register rows. A receipt validates offline, with no register, no models and no prover toolchain, which is what makes it useful to somebody who does not trust this machine.
In the repository
examples/artifacts/support.receipt.json covers the support desk: every source in the closure hashed, every artifact hashed, and the register stamped with its own digest.
extend
Extend
Three extension points, none of them a fork.
A backend: consume the artifact, publish the output — no compiler change at all. A surface: a lexer, a grammar, a compiler stage and an artifact type, added as one table row rather than a second pipeline. A pattern library: modules composed into flows by reference, so a shared view is imported rather than pasted.
The first is the cheapest: an out-of-tree backend is a program that reads JSON. The other two are ordinary work in a repository you can clone.
In the repository
patterns/ifml holds domain-agnostic interaction modules that examples/support/support.ifml composes with use — one library, many flows, one compiled manifest.
The invariant
Backends consume only the versioned IR artifact.
This is the one rule the rest of the design hangs on. It is also the reason a backend can be written by somebody who has never read this compiler.
Parsing, name resolution, validation and lowering happen once, in the compiler. What leaves that boundary is phero_ir::Model — or the artifact of the surface you compiled — serialized as JSON with camelCase keys, adjacent tagging and aformatVersion gate. A backend is handed that value. It is never handed an AST, and it cannot reach one.
Three things follow, and each one is checkable today:
pherolang artifact checkvalidates a serialized artifact with no compiler, no model and no import resolution in the loop — the artifact is a complete description.- An in-tree generator and an out-of-tree consumer cannot disagree about a model's shape, because there is only one shape to read.
- A change to a grammar cannot silently change generated code: it would have to change the artifact, and the artifact is pinned by byte-compared goldens.
Continue
Where to look next
The walkthrough follows one file end to end; the catalogue opens each surface on its own; the architecture page shows how the pieces are wired.