AtlatestRenderedmarkdown
Readme
Changelog
Notable changes to the sigil monorepo (sigil-cli, sigil-run, sigil-wasm-runtime). Pre-1.0, patch bumps cover all non-breaking changes (including new features, perf wins, and default-flag flips) per the ecosystem's 0.x caret-range convention; minor bumps are reserved for genuinely-breaking API changes. Lead bullets with user-facing impact.
Earlier releases (v0.14.3 and below) predate this changelog; see packages/sigil-cli/CHANGELOG.md and the per-extracted-repo CHANGELOGs (e.g. sigil-lang/CHANGELOG.md) for prior history.
Unreleased
sigil-wasm-audioplays sound effects without waiting behind the music.load-audio-cueuploads a sound once to a second AudioWorklet processor per context;play-audio-cueposts "play it now" and the processor mixes it into the next 128-frame render quantum, independent of any sink's ring depth (a cue pushed into a 12288-frame ring is heard 256 ms late at 48 kHz). NoSharedArrayBufferneeded; with no worklet a play starts an AudioBufferSourceNode on a buffer built once, on the cue's first play (that path pans with a StereoPannerNode and refuses a play past 32 voices, where the worklet ends the oldest). Alsounload-audio-cue!,stop-audio-cues!,set-audio-cue-volume!,audio-cue-modeandaudio-cue-lag(the frames a play waited for its quantum, measured in the worklet).- A
sigil-wasm-audiosink can be fed below the context's rate.open-audio-stream rate:andset-audio-stream-rate!; the drain upsamples with a 4-tap cubic Hermite and a change lands at the write head it was asked at, so queued frames keep their rate. On a cross-origin-isolated page the change travels in the ring's shared header (a 4-entry queue) rather than on the port, so it cannot arrive after the frames it governs. At the context's rate the ring is still copied sample for sample. - Starved frames are split into sounding and idle.
audio-stream-underruns-soundingcounts output frames that cut sound off (the ring ran dry within 128 frames of a sample above -80 dB, after the sink's volume);audio-stream-underruns-idleis the rest. The total is unchanged. - The three sink modes (worklet-sab, worklet-msg, scriptprocessor) share one drain function, embedded into the worklet with
Function.prototype.toString.test/integration/test-wasm-audio-worklet-cues-rate.mjs(inmake test-gates) drives the real processors in all three modes. sigil-wasm-audiodrains off the main thread on a page that is not cross-origin isolated. The bridge had two sink modes: aSharedArrayBufferring drained by anAudioWorkletNodewhen the page is isolated (COOP/COEP), and aScriptProcessorNodedraining on the main thread otherwise, which is where a busy game frame pops the audio (Crash The Stack on a phone over an http host: the cues' sink starved 131,072 frames in a 21 s read). A third mode,worklet-msg, sits between: whenAudioWorkletNodeexists but the ring cannot be shared, the ring stays on the main thread andsink_pushfills it as before, each push also posts the accepted frames to the worklet as a transferable copy, the processor keeps a ring of the same capacity and drains it on the audio thread, and every 8 render quanta (1024 frames) it reports its read counter and starved frames back into the header, soaudio-stream-depth/-room/-underrunskeep their meaning with a lag of at most one report; the lag makes the main thread see less room than the worklet has, never more.SigilWasmAudio.sinkMode(id)answers"worklet-sab","worklet-msg"or"scriptprocessor"for a page's readout. TheScriptProcessorNodepath stays the fallback for a browser withoutAudioWorkletNode.test/integration/test-wasm-audio-worklet-msg.mjsexecutes the embedded processor against the real producer with the port wired both ways, including the lag bound under a stalled main thread. The Sigil facade is unchanged.- The
sigil:field is now a bare minimum version.sigil: "0.16"means "needs at least Sigil 0.16", compared as resolved >= declared, with an implicit ceiling at the next major (1.0 — never the semver-0.x pseudo-major, so declarations no longer expire when a minor ships). A measured incompatibility can name its ceiling explicitly:sigil: (supports min: "0.16" max: "1.0")(max exclusive). Range operators refuse with a diagnostic naming the operator and the replacement (exit 78) — except the grandfathered caret: an existing^Xwith a floor below 0.20 is tolerated, read as its bare floor, and warned about in one line, until the compiler's major reaches 1. The tolerance is bounded in code (cutoff + flag day), deliberately without any switch, so it fades out on its own and new caret debt cannot accumulate. Migrate a caret only once every toolchain building the repo is at least the version the warning names — older sigils read bare versions as exact pins and evict lockfile pins. Seedocs/reference/package-sigil-field.mdand the 2026-08-25 decision records. - Relocking never moves the Sigil runtime.
sigil deps installkeeps sigil-stdlib/sigil-lib at the locked version even across the migration's range restatement;sigil deps updatere-resolves ordinary dependencies while holding the runtime, and moves it only under the new--upgrade-sigilflag. A fresh install with no lockfile takes the newest version the declared window admits. - The coherence check's advisory axis now reports declared-floor understatement (a dependency declaring a higher
sigil:floor than its host) instead of declaration-era range intersection, which measured how long ago a manifest was written rather than compatibility.
v0.18.4 - 2026-08-09
- Source files can select installed language readers with
#lang. Alternate readers lower their notation to located Sigil syntax while retaining the normal compiler, dependency graph, cache, runtime, and tooling. The protocol covers every program-file entry point and adds generated-origin locations, positioned syntax-reader APIs, and passive tooling discovery. Existing standard Sigil sources are unchanged; bytecode caches rebuild once for format version 11. Sigil Doc is the first separately installed protocol user. - Release builds now isolate and verify dependency worktrees. Dependency repositories and worktrees honor
SIGIL_HOMEwhile retaining~/.sigilas the normal default. The bootstrap installer now honors an existing lockfile, and the release build checks every external worktree against its committedsigil.lockSHA before compiling, so resolver or shared-state drift cannot enter an artifact silently.
v0.18.3 - 2026-08-08
- Large module graphs no longer overflow the VM registry. The registry now grows beyond 256 modules. Native caches rebuild once because the internal runtime ABI key moved from v3 to v5.
v0.15.0 - 2026-05-02
- Reintegration release. Brings the compiler/runtime, standard library, build system, dependency resolver, and test runner back into the main Sigil release train. The
sigilbinary, bundledsigil-lib, stdlib bytecode, build pipeline, and native test harness now ship from one coherent checkout again, which reduces the risk of host/runtime ABI drift and stale bytecode cache mismatches in downstream apps. - Native builds are stricter about stale runtimes. The native test and runtime cache path now resolves package manifests as well as workspace manifests, falls back through sibling packages to find the matching
sigil-lib, and rejects keylesslibsigil.aarchives when it cannot prove they match the active sources. This prevents old native runtimes from being reused after SGB or C ABI changes. - Generated-module summary work is bounded. Best-effort
.sgsCPS summary generation now skips generated mega-functions over 10,000 continuations. This fixes a release-build hang seen after.sgboutput in generated modules such as Live Crafter's theme module, without disabling normal CPS summaries. - Dependency resolution prefers workspace-owned packages. Local workspace packages now win over stale installed copies when the manifest says they should, which makes
dev-redirects.sglbased cross-repo development much less fragile. - Hygienic direct module refs are fixed. Macro-expanded references to direct module bindings now resolve correctly, closing a reintegration regression in the compiler/runtime boundary.
sigil-testis back in tree. The user-facingsigil-testDSL and thesigil-test-runnerexecution layer are part of this release, including the native-backend harness used bysigil test.- Scaffolded projects now target 0.15.
sigil inittemplates use^0.15for the generated package manifest'ssigil:field and rely on the auto-derived core stdlib dependency. Templates with optional extracted libraries keep those dependencies on the current stable ecosystem range. - Generational GC remains opt-in.
SIGIL_GC=generationalnow propagates through the bootstrap Makefile path and thesigil-buildcustom runtime path. The default GC is unchanged, and minor collection is still deferred for further investigation before it is recommended for production builds. - Forgejo Actions CI is available. The Codeberg workflow now runs the local validation suite used for this reintegration branch.
- Local validation. The bytecode suite passed 1986/1986, focused CPS summary bytecode and native acceptance tests passed after the generated summary guard, Live Crafter release builds complete again, and downstream
release-debugverification was exercised against cinder-cantata and Kiln with local redirects.
v0.14.18 — 2026-04-30
- Ecosystem alignment release. Refreshes the monorepo's pinned dep set so the host sigil binary, the bundled libsigil/stdlib, and downstream native release builds all agree on the C ABI and SGB bytecode format. Pre-fix, a host built from v0.14.3 emitted 3-arg
sigil_module_add_export(...)calls in generatedmod_<package>.cfiles (the v0.14.3 codegen shape), which could not compile against v0.14.10+ headers; separately, a v0.14.3 libsigil reader (SGB_VERSION=8) rejected v9 bytecode emitted by a v0.14.5+ sigil-stdlib. Behavior-preserving for all downstream consumers (apiary, courier, folio, bureau, enclave, motif, etc.) — no source change required; the alignment is purely about producing a host binary that is internally coherent. - Pulls in sigil-lang v0.14.17 (latest extracted release, 2026-04-29). Net effect from v0.14.3 → v0.14.17: SGB bytecode bumped v8 → v9 (v0.14.5, BCE pass +
OP_VECREFNC/OP_VECSETNCopcodes; readers in v0.14.5+ accept both v8 and v9);sigil_module_add_exportgained a leadingSigilVM *vmparameter (v0.14.10, generational GC Phase 4 write-barrier audit); critical aarch64-openbsd UAF fixes ingc_remset_clear(v0.14.15), fiber-side I/O hang inport.c(v0.14.16),native_call_with_valuesUAF (v0.14.17); generational GC Phase 1–5 (v0.14.9–v0.14.11, opt-in); BCE inter-procedural fixpoint perf fix (~140x speedup on stdlib BCE compile, v0.14.13). - Pulls in sigil-build v0.14.4 (no native codegen lives here; this was the intermediate
sigil-buildpatch landing default-package handling and theapp-versionbundle helper). - Pulls in sigil-crypto v0.15.0 transitively via downstream consumers (apiary, courier) that already pinned
^0.15. Hand-written native bindings (sigil_module_register_native+sigil_module_exportpattern) were unaffected by the codegen-internal ABI change. - Available for opt-in testing (defaults preserved):
SIGIL_CPS_CROSS_CU,SIGIL_GC_GENERATIONAL,SIGIL_GC_ENABLE_MINOR. None of these have their default flipped in this release; seesigil-lang/CHANGELOG.mdfor full semantics. Once validated under daily-driver use, future patch bumps may flip selected defaults. - Stale
^0.13.1pins inpackages/sigil-cli/package.sgl(sigil-args, sigil-ansi, sigil-version, sigil-format, sigil-json, sigil-nrepl, sigil-repl, sigil-test, sigil-http, sigil-tls, sigil-ffi, sigil-sqlite, sigil-store, sigil-mcp, sigil-lsp, sigil-socket, sigil-docs) are intentionally left alone in this alignment release — caret resolution still picks compatible versions. A follow-up cleanup pass tracked separately astasks/sigil-cli-stale-pin-cleanup.