Profiles × Targets
Profiles × Targets
Section titled “Profiles × Targets”Janus has two axes that determine what code can be compiled and where it can run. They are orthogonal but not freely composable. Pairing the wrong profile with the wrong target produces a compile error, not a broken binary.
// Legal{.profile :sovereign.} // can target anything, including bare metal{.profile :service.} // can target Linux, macOS, NexusOS, WASI
// Rejected at compile time{.profile :service.} // + target=none → E_PROFILE_TARGET_INCOMPATIBLEThis page documents the matrix, the doctrine behind it, and the escape hatch when you need to violate it.
The Two Axes
Section titled “The Two Axes”Profile (capability tier)
Section titled “Profile (capability tier)”Profiles are documented in the Profiles overview and codified in SPEC-002. The six canonical profiles form a monotonic capability ladder:
:script ⊆ :core ⊆ :service ⊆ :cluster ⊆ :compute ⊆ :sovereignEach rung is a strict superset of the one below. :sovereign is the top —
the complete language, with no capability hidden behind a safety rail.
As of 2026-07-09, the CLI (src/profiles.zig), semantic resolver, effect graph,
pipeline, and LSP all share this ladder. Legacy spellings such as :main →
:core, :npu → :compute, and :full → :sovereign are aliases, not
separate enum variants. See the
Profile Enum Unification release note.
Target (execution environments)
Section titled “Target (execution environments)”Targets are documented in
RFC-NNN-target-attribute
and codified as the compiler’s target_triple string. The classes that matter
for profile-compatibility:
| Target class | Examples | Hosted? |
|---|---|---|
linux | x86_64-linux-gnu, aarch64-linux-musl | ✓ |
darwin | aarch64-darwin, x86_64-macos | ✓ |
freebsd | x86_64-freebsd | ✓ |
nexusos | riscv64-nexusos, aarch64-nexusos | ✓ |
wasi | wasm32-wasi, wasm32-wasi-preview1 | ✓ (sandboxed) |
freestanding | *-none-elf, *-uefi, *-opensbi-*, *-bare-* | ✗ |
The freestanding class collapses none, uefi, opensbi, and bare-metal
targets into one bucket because, for profile-compatibility purposes, they are
all equivalent: no OS, no hosted facilities, no allocator, no runtime.
The Constitutional Doctrine
Section titled “The Constitutional Doctrine”
:sovereignis the only profile that may target a freestanding environment.
Ratified 2026-07-02 (Markus ruling). Codified in SPEC-002 §2.6.5 and RFC-NNN-target-attribute §4.1.
This single rule explains why kernels, bootloaders, firmware, hypervisors,
SBI, device drivers, MMIO, DMA, page tables, and NexFS all live in
:sovereign — without inventing a separate :baremetal profile. The
prior :bare proposal was rejected:
runtime presence is modeled on the target axis, not as a profile-axis tier.
Why this rule exists
Section titled “Why this rule exists”Hosted profiles (:script through :compute) define capability sets in terms
of POSIX-or-better facilities:
- processes and threads
- file descriptors
- sockets and network primitives
- environment variables
- GPU driver stacks
None of these exist on target=none, target=uefi, or target=opensbi.
Permitting :service against target=none would silently produce a binary
whose capability calls resolve to absent facilities. The compile-time rejection
makes the asymmetry explicit.
:sovereign is the exception because its capability set makes no hosted
presumption. It speaks raw memory, MMIO, and hardware primitives directly. See
SPEC-225
§6 (peripherals), §12 (memory regions).
The Full Matrix
Section titled “The Full Matrix”| Profile | linux / darwin / freebsd | nexusos | wasi | freestanding |
|---|---|---|---|---|
:script | ✓ | ✓ | ✓ | ✗ E_PROFILE_TARGET_INCOMPATIBLE |
:core | ✓ | ✓ | ✓ | ✗ E_PROFILE_TARGET_INCOMPATIBLE |
:service | ✓ | ✓ | ✓ | ✗ E_PROFILE_TARGET_INCOMPATIBLE |
:cluster | ✓ | ✓ | ✗ | ✗ E_PROFILE_TARGET_INCOMPATIBLE |
:compute | ✓ | ✓ | ✓ | ✗ E_PROFILE_TARGET_INCOMPATIBLE |
:sovereign | ✓ | ✓ | ✓ | ✓ — the only profile permitted here |
Two special cases
Section titled “Two special cases”:cluster×wasiis rejected because:cluster’s capability set (distributed actors, network message-passing) presumes network primitives that WASI does not provide.:compute×wasiis permitted, but real GPU compute on WASM depends onwasm-simdand future WASI GPU proposals. The matrix marks it ✓ pending implementation feedback from the first WASM compute consumer.
The Escape Hatch: Escalation, Not Downgrade
Section titled “The Escape Hatch: Escalation, Not Downgrade”A hosted-profile module that needs one freestanding operation does not
need to become a :sovereign module. Use the SPEC-044 escalation mechanism:
// :service HTTP server that needs to call ONE MMIO routine{.profile :service, escalations: [:sovereign].}
func read_sensor_register(addr: usize) -> u32 do let value = escalate :sovereign do let ptr: :sovereign *u32 = std.mem.pointer_from[u32](addr) return ptr.* end return valueendThe module’s base profile stays :service — every line outside the
escalate block is normal service code, audited as such. The bare-metal
capability is named (:sovereign), scoped (single block), and
tracked (the return value carries the :sovereign origin tag).
This is the supported path for “hosted module with one bare-metal call.”
It is not a path to ship a :service kernel. Kernels live in :sovereign
unconditionally — no amount of escalation turns a hosted module into a kernel.
Read SPEC-044 for the full escalation semantics, origin tags, and composition rules.
Diagnostics
Section titled “Diagnostics”E_PROFILE_TARGET_INCOMPATIBLE
Section titled “E_PROFILE_TARGET_INCOMPATIBLE”Emitted when a hosted profile is paired with a freestanding target (or when
:cluster is paired with wasi). The diagnostic includes:
- The declared profile name
- The requested target name
- A description of what the target lacks
- A remediation hint pointing at either
:sovereign(if you truly need freestanding) or SPEC-044 escalation (if you have a hosted module with one bare-metal call)
E_PROFILE_TARGET_UNKNOWN
Section titled “E_PROFILE_TARGET_UNKNOWN”Emitted when the target triple cannot be classified into one of the six target
classes. The diagnostic names the unrecognized triple and lists the recognized
keywords (linux, darwin, freebsd, nexusos, wasi, none, uefi,
opensbi, freestanding, bare).
If you hit this, either your target triple is misspelled, or you are targeting an environment Janus does not yet recognize. File an issue.
Implementation
Section titled “Implementation”- Validator source:
compiler/semantic/profile_target_compat.zig - Standalone test target:
zig build test-profile-target-compat - Pipeline integration: Wired into STAGE 1.6 (transitive stdlib + user-module preloader). The check fires after profile resolution and target triple parsing, before any code generation.
See Also
Section titled “See Also”- Profiles overview — the capability axis
:sovereignprofile — the only hostless profile- Error handling doctrine — how Janus thinks about errors
- SPEC-002: Profiles system — canonical profile taxonomy
- SPEC-225:
:sovereignprofile — full hardware-aware surface - SPEC-044: Profile escalation — the escape hatch mechanism
- RFC-NNN-target-attribute — the
@target(...)attribute spec