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-audio plays sound effects without waiting behind the music. load-audio-cue uploads a sound once to a second AudioWorklet processor per context; play-audio-cue posts "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). No SharedArrayBuffer needed; 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). Also unload-audio-cue!, stop-audio-cues!, set-audio-cue-volume!, audio-cue-mode and audio-cue-lag (the frames a play waited for its quantum, measured in the worklet).
  • A sigil-wasm-audio sink can be fed below the context's rate. open-audio-stream rate: and set-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-sounding counts 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-idle is 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 (in make test-gates) drives the real processors in all three modes.
  • sigil-wasm-audio drains off the main thread on a page that is not cross-origin isolated. The bridge had two sink modes: a SharedArrayBuffer ring drained by an AudioWorkletNode when the page is isolated (COOP/COEP), and a ScriptProcessorNode draining 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: when AudioWorkletNode exists but the ring cannot be shared, the ring stays on the main thread and sink_push fills 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, so audio-stream-depth / -room / -underruns keep 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. The ScriptProcessorNode path stays the fallback for a browser without AudioWorkletNode. test/integration/test-wasm-audio-worklet-msg.mjs executes 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 ^X with 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. See docs/reference/package-sigil-field.md and the 2026-08-25 decision records.
  • Relocking never moves the Sigil runtime. sigil deps install keeps sigil-stdlib/sigil-lib at the locked version even across the migration's range restatement; sigil deps update re-resolves ordinary dependencies while holding the runtime, and moves it only under the new --upgrade-sigil flag. 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_HOME while retaining ~/.sigil as the normal default. The bootstrap installer now honors an existing lockfile, and the release build checks every external worktree against its committed sigil.lock SHA 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 sigil binary, bundled sigil-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 keyless libsigil.a archives 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 .sgs CPS summary generation now skips generated mega-functions over 10,000 continuations. This fixes a release-build hang seen after .sgb output 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.sgl based 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-test is back in tree. The user-facing sigil-test DSL and the sigil-test-runner execution layer are part of this release, including the native-backend harness used by sigil test.
  • Scaffolded projects now target 0.15. sigil init templates use ^0.15 for the generated package manifest's sigil: 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=generational now propagates through the bootstrap Makefile path and the sigil-build custom 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-debug verification 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 generated mod_<package>.c files (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_VECSETNC opcodes; readers in v0.14.5+ accept both v8 and v9); sigil_module_add_export gained a leading SigilVM *vm parameter (v0.14.10, generational GC Phase 4 write-barrier audit); critical aarch64-openbsd UAF fixes in gc_remset_clear (v0.14.15), fiber-side I/O hang in port.c (v0.14.16), native_call_with_values UAF (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-build patch landing default-package handling and the app-version bundle 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_export pattern) 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; see sigil-lang/CHANGELOG.md for full semantics. Once validated under daily-driver use, future patch bumps may flip selected defaults.
  • Stale ^0.13.1 pins in packages/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 as tasks/sigil-cli-stale-pin-cleanup.