v2026.4.8 — Phase Sigils and the :script Profile
v2026.4.8 — Phase Sigils and the :script Profile
Section titled “v2026.4.8 — Phase Sigils and the :script Profile”Release date: 2026-04-22
Profiles affected: :core, :service, :script (new)
Status: Standard release (6-month support)
This release codifies a language-level clarification that has been developing across the last two weeks and opens a new rung at the bottom of the profile ladder for quick, throwaway-or-promote programs.
The Three-Sigil Phase System
Section titled “The Three-Sigil Phase System”Janus now encodes phase directly in its sigils. Every sigil belongs to exactly one world; no sigil crosses worlds.
| Sigil | World | What it does | Examples |
|---|---|---|---|
§ | Compile-time | Structural computation, type reflection, code generation | §size_of(T), §type_info(T), §{ ... } |
$ | Extraction | Runtime pattern capture (regex, PEG, positional scripting) | $1, $2, $* |
@ | Metadata | FFI bindings, attributes, capability declarations | @ffi(path: ..., lang: .c), @requires(...) |
What changes for existing code:
- Compile-time builtins migrate from
$to§.$size_ofis deprecated with warningW5001in favor of§size_of. Same for$align_of,$offset_of,$is_integral,$is_float, and similar. - The
$sigil is now exclusively reserved for extraction — runtime pattern capture and the:scriptprofile positional system. @is declaration-time only.let x = @ffi(...)was never valid and is now explicitly rejected;@ffi(...)attaches to anextern funcdeclaration, nothing else.
Why this matters: The old convention overloaded $ for two unrelated phases — compile-time introspection and runtime extraction. That ambiguity meant readers had to infer which world a $name lived in from context. Splitting the worlds into three sigils with one purpose each makes every expression self-identifying about when it runs.
The :script Profile
Section titled “The :script Profile”A new profile sits at the bottom of the ladder, below :core:
:sovereign → bare-metal:compute → SIMD, tensors, device offload:cluster → actors, supervision, distribution:service → daemons, networking, structured concurrency:core → deterministic micro-systems:script → interactive scripting (NEW):script is :core with three additions and zero subtractions:
- Implicit defaults — entry point, allocator, capability set, common imports are all inferred.
- A bounded sugar surface — top-level statements,
$-family positional arguments ($1,$2,$*), ergonomics that desugar mechanically into legal:core. - AOT-cached execution —
janus path/to/file.jansfeels instant via content-addressed cache. No interpreter, no JIT, no second semantics.
The Script Law: Every :script program is a syntactically valid :core program after janus desugar. The transformation is purely additive. Promotion from :script to :core never requires a rewrite.
What :script is deliberately NOT:
- Not dynamically typed
- No
meta.eval("code")— reflection is typed-AST only - No hot reload
- No second error system (
!Tpropagation remains the only mechanism) - No second concurrency primitive (nurseries remain the only concurrency mechanism)
- Cannot be published through Hinge —
:scriptartifacts are local-only
Status: Rough around the edges, but working. Suitable for throwaway scripts, one-off tooling, and quick prototypes that may later promote to :core.
The Language Reference is now canonical
Section titled “The Language Reference is now canonical”Janus/.agents/architecture/LANGUAGE-REFERENCE.md is the single-source doctrine for writing Janus code — for humans and AI agents alike. It covers :core and :service completely, and :script as draft.
Two laws now sit at the foundation of the syntax:
Law 1 — do...end for control flow (imperative, vertical):
if cond do ... endwhile cond do ... endfor iter do |x| ... endfunc name() do ... endtest "name" do ... endLaw 2 — { } for data structures (declarative, containers):
struct { field: type }enum { Variant }match expr { pattern => value }extern struct { field: type }These two laws are non-negotiable. No exceptions. Every syntactic question in Janus answers itself once you ask: is this control flow, or is this a container?
Other notable items
Section titled “Other notable items”- Doc comments use bare keys, not sigils:
param:,returns:,error:,capability:,since:,see:,deprecated:,safety:,complexity:. No@prefix —@is reserved for metadata declarations, and documentation is not metadata. discardkeyword for explicit value discarding at statement level — replaces Zig’s_ = expr. Clear intent: “I am intentionally ignoring this result.”testis a reserved keyword.test "name" do ... endis the only valid use. Naming a function, variable, or typetestis a parse error.
Upgrade notes
Section titled “Upgrade notes”- Compile-time builtins using
$prefix ($size_ofetc.) will emit warningW5001. Migrate to§size_ofat your convenience — warnings, not errors. - Existing
:coreand:servicecode should compile unchanged (modulo the$→§deprecation). - Files using
testas an identifier need renaming. The parser will flag these clearly.
Binary version: 2026.4.8
Git hash: 84133fa
Built on: 2026-04-22