/glossary

Hale's words, in familiar terms

Hale uses a small vocabulary of its own. Most of it names things you already know from other languages and tools, with one difference each that is worth knowing. This page gives the familiar idea first, then the difference. A dotted word anywhere on the site shows the same gloss when you hover it and links here.

The language

  • locus

    Familiar: a component that owns its own state and talks to others only through messages, like an actor, a small service, or an object nobody else can reach into. An app, a cache, a request handler and a library are all loci. The difference: there is no other kind of thing, so the compiler can see the whole graph of who owns what and who talks to whom.

  • topic

    Familiar: a named, typed message channel, like a pub/sub topic in Kafka or NATS. The difference: it is declared in source with its payload type, and publishing and subscribing are declarations too, so the compiler knows every sender and every receiver.

  • bus

    Familiar: an event bus. In a locus, the bus block lists which topics it publishes and subscribes to; at runtime, the bus delivers them. The difference: a bus edge can be a direct call, an in-process queue, a socket or a broker, and the program does not change when that changes.

  • keyed_by

    Familiar: a partition or sharding key. A keyed topic delivers each message only to the subscriber whose key matches. The difference: the routing is part of the topic's declaration, so the handler never filters and the compiler checks the key's type.

  • the send, <-

    Familiar: publishing a message. Broadcast <- m puts m on the Broadcast topic. The difference: a send is only allowed from a locus that declared it may publish there.

  • main locus

    Familiar: main() plus the deployment manifest, in one place. The difference: the root component also says where each part runs and how each channel travels, and nothing else in the program mentions a thread or a transport.

  • placement

    Familiar: thread affinity and scheduling: a shared pool, a dedicated thread, a pinned core, a NUMA node. The difference: it is a block in main, and the components it places do not change.

  • bindings

    Familiar: the wiring in a deployment config: which transport carries which channel. In-process, a Unix socket, a shared-memory ring, or an adapter to a broker like NATS. The difference: the transport is itself a child component, so it is supervised like one, and a binding that cannot open fails at startup, so no route drops messages silently.

  • params

    Familiar: a component's typed fields with defaults: its constructor arguments and its state. The difference: params are a contract, so constructing a component with a field it never declared is a compile error.

  • birth, run, dissolve

    Familiar: constructor, main body, destructor. The difference: dissolve frees the component's whole memory region at once, so there is no garbage collector and no borrow checker.

  • supervision, on_failure

    Familiar: Erlang-style supervisors: a parent handles a child's failure and can restart it, quarantine it, or pass it up. The difference: there is no other error channel; nothing fails sideways.

  • fallible(E)

    Familiar: a Result type or a checked exception: a function that can fail says so in its signature. The difference: the caller must say what happens at the call site, with or default, or raise and the rest, and forgetting is a compile error.

  • closure

    Familiar: an invariant, or an assertion that must hold. The difference: it is declared on the component and audited by the runtime at phase boundaries, and a broken one goes to the parent as a structural failure.

  • perspective

    Familiar: an interface with a swappable implementation. The difference: it can be swapped while the program runs, at the cost of a pointer flip, with state carried across.

  • @sealed

    Familiar: private fields. The difference: components are not otherwise encapsulated at the field level, so @sealed is what makes "nobody else can read this key" a fact the compiler enforces.

  • unit

    Familiar: a unit of measure, like ms or USD, declared with its equation: unit USD = 100 cent;. The difference: a program declares its own, the standard library's time units are declared the same way, and the compiler knows every conversion between two units as one exact factor.

  • quantity, point

    Familiar: a typed amount, such as Money or Duration, and a position on its line, such as Price or Time. The difference: every value is the integer it counts, arithmetic stays exact, widening is free, and narrowing is written where it happens with the rounding you chose: or floor at the site, or { round: half_even; } on the type.

  • distinct, range

    Familiar: a newtype for an id, and a bounded integer. The difference: an identity never passes for an Int and has no arithmetic; a range is an Int with bounds, and narrowing into it says what happens outside them: or clamp, or wrap, or 0, or a handler.

  • api, rpc, surface

    Familiar: an API definition, like an OpenAPI document or a gRPC service, listing the operations and who may call each. The difference: it is rows in the program, rpc Shop::on_order requires: [clerk], and the compiler checks them, hashes them into a contract digest, and generates the OpenAPI, JSON Schema and MCP forms. Arrives in the next release.

  • role

    Familiar: a permission group. The difference: a role is declared vocabulary with includes, the requirement sits on the operation's row, and who holds a role is a source the serve site names, so one program can serve the same surface to two sets of people.

  • api::serve, exposure

    Familiar: starting the server. The difference: one line puts a surface on a transport the standard library ships, a Unix socket, HTTP or MCP, with a bounded queue and one policy for when it is full, and the running exposure describes itself to any client.

  • hub, stream

    Familiar: a WebSocket channel. The difference: a stream is a topic bound to a hub, with the roles a subscriber needs on its row, so the same typed topic the program already publishes reaches the outside.

  • altitude

    Familiar: how low-level you are working: scripting, everyday application code, services, systems programming. The difference: it is one language at every level, and a function written at the top still compiles at the bottom. Scale, how big the system is, is a separate axis.

  • scale

    Familiar: how big the composed system is, from a function to a fleet of machines. The difference: the same construct, the locus, is what you write at every size.

What the compiler checks

  • effect, effect classes

    Familiar: what a function is allowed to do: make a syscall, block, read the clock, allocate, publish, spawn, recurse. It resembles an effect system, or a stricter notion of a pure function. The difference: a declaration is proven across everything the function can reach, and a violation names the path.

  • @budget

    Familiar: a performance assertion. The difference: it is a numeric bound the compiler checks, such as zero allocations per call, counting the allocation that broke it.

  • claim

    Familiar: an architecture test, like ArchUnit's "this package must not depend on that one". The difference: it is a sentence about the whole program's structure, checked over every path, including the ones no test takes, and it compiles to no code.

  • group

    Familiar: a named set of components that a rule talks about, such as billing or plugins. The difference: a misspelt member is an error, and an empty group is an error unless the rule says it may be empty.

  • constitution

    Familiar: a shared rulebook. The difference: written once, adopted by many programs, and proven by each against its own structure. Composition only adds rules; it cannot weaken one.

  • witness, countermodel

    Familiar: a counterexample, or a failing test's trace. The difference: when a rule is false, the compiler returns the concrete path that breaks it, in your own names: the call, the publish, the subscriber.

  • hole

    Familiar: "unknown". The difference: where the compiler could not see, such as a call through a function value, it records a hole and says so. A rule that reaches a hole reports uncertified, a different answer from false.

  • topology artifact

    Familiar: a generated architecture diagram, or a bill of materials for structure. The difference: it is a byte-reproducible JSON file the compiler emits, with every component, topic, edge and rule verdict, so the architecture can be diffed in review and signed for deployment.

  • fleet, plan

    Familiar: several separately built services deployed together, described by a manifest. The difference: hale fleet check checks rules across the binaries using their artifacts, so two correct services wired into an incorrect deployment are caught before it runs.

  • seed

    Familiar: a package or crate: a unit of Hale source, a library or an application. The difference: a library's rules travel with it into every program that imports it.

The toolchain and the runtime

  • hale check, hale verify

    Familiar: the type checker and a stricter lint gate. The difference: check is the whole-project check that runs as you type; verify turns every advisory into a failure.

  • Iris

    Familiar: an observability dashboard or a debugger for a running system. The difference: it reads the running program's components and messages against the same structure the compiler certified.

  • record and replay

    Familiar: a flight recorder. The difference: the runtime delivers the messages, so it can record a concurrent run's inputs and schedule and replay them exactly, with no instrumentation in the application.

  • pond

    Familiar: a package index. The difference: packages are vendored by pinning a git ref; there is no central registry.

DNA

  • organism

    Familiar: an application together with its own delivery pipeline, operations, governance and audit log. The difference: all of that is one Hale program generated next to the code, and it changes itself only under review.

  • DNA

    Familiar: the generator and command for the above: hale dna. The difference: the same parts in every organism, so what differs between two organisms is only what their projects wrote.

  • the Board

    Familiar: the people with final say. The difference: their authority is a position in the record, and only they can widen what the automated roles may do.

  • the Leader

    Familiar: a reviewer. The difference: an AI-backed role that may approve routine changes within limits the Board set, with its reasoning and cost on the record. It decides; it never commits.

  • grant

    Familiar: permissions. The difference: a grant is enforced by the compiler against the program's actual wiring: the editing role can read, edit, format and check and nothing more, and handing it a git handle fails the build.

  • the record, the journal

    Familiar: an audit log. The difference: it is kept as git commits on refs/dna/journal, one per event, in the repository the code lives in, so a clone carries the whole history.

  • memory

    Familiar: the organism's working state, in a Postgres database it owns under its own roles.

  • nerves

    Familiar: messaging between the organism's parts, over NATS.

  • senses, reflexes

    Familiar: monitoring, with Prometheus, and the automatic responses to what it sees.

  • skin

    Familiar: secrets and access control: a vault, and a role per client on each backend.

  • spine

    Familiar: the decision engine: tasks, reviews, grants and budgets.

  • legs, hands, voice

    Familiar: the workers that carry out tasks, their tools, and their access to models.

  • heart, body

    Familiar: the application itself, and the machines it runs on.

  • expression

    Familiar: deployment. The difference: an approved change is restarted locally or redeployed on every node the plan assigns, then watched, and rolled back everywhere if one instance fails.

  • habitat

    Familiar: shared infrastructure: the records, access, identity and tools that several organisms and the people in them share. The difference: sharing is deliberate publication between isolated records. Designed, and partly built.