Sigil 0.18.4
Sigil source files can now select an installed language reader with #lang. A reader turns its source into ordinary located Sigil syntax, so a language can introduce its own notation while retaining Sigil's compiler, build graph, cache, runtime, and tooling. The same source works through compilation, direct execution, load, tests, bundles, native builds, and both WebAssembly backends.
Sigil Doc is the first separately installed language built on this protocol. It uses #lang sigil/doc for programmable prose: authors can combine document markup with ordinary Sigil bindings and macros, then render the resulting semantic document as a website or book.
Existing standard Sigil projects build without source changes. Compiler and bytecode caches rebuild once because this release advances the bytecode format to version 11 and adds language-reader inputs to cache identity.
A source file can select an installed language
A header such as #lang sigil/doc resolves (sigil doc reader) and calls its exported read-language-source procedure. The reader receives the complete source plus its name, language id, and exact header-end byte offset, then returns syntax for the normal compiler.
Resolution is mechanical. It does not search a registry, install a package, access the network, or fall back to standard Sigil after recognizing a valid header. Missing or invalid readers fail with stable diagnostics. A byte-order mark and a physical-line-one shebang are supported; displaced and overlong headers are rejected.
Files without a language header follow the existing reader path with their original bytes unchanged. The .sgd extension is a useful convention for alternate-language manuscripts, not a semantic requirement.
Language readers participate in the normal dependency graph and caches
A document's compiler inputs now include its selected reader and the reader's complete ordinary transitive dependency closure. Changing only a reader support module invalidates the document correctly, even when manuscript bytes and timestamps are unchanged. The same identity reaches CLI auto-compilation, content-addressed package builds, native code generation, bytecode WebAssembly, and native WebAssembly.
Compiled modules publish compiler-input metadata so later builds can recover the closure without source files. Incomplete metadata fails closed rather than claiming an unsafe cache hit. Identity uses content and logical modules rather than absolute checkout paths, preserving reproducibility across roots.
Every program-file entry point honors the selected language
Language dispatch is shared by the compiler and file evaluator. It works through compile-file, sigil eval -f, direct and shebang execution, load, tests, module source fallback, package builds, bundles, native builds, and both WebAssembly configurations. String and expression interfaces, including the REPL and eval-string, remain standard Sigil by design.
Reader failures preserve caller state, and recognized languages never trigger an installer or network fallback. The matrix covers multiple readers, failure followed by ordinary source, forced garbage collection, and every supported backend.
Generated syntax retains manuscript provenance
Source locations can now carry a bounded generated-origin chain. A language may locate a generated form in its own synthetic source while retaining the authoritative outer manuscript span that caused it. Diagnostics report the manuscript location first, and origin chains survive garbage collection and bytecode serialization.
The syntax library also gains a positioned reader with exact UTF-8 byte offsets, one-based lines and columns, spans, and a caller-owned cursor. Languages can delegate embedded Sigil fragments to it instead of maintaining another Scheme lexer.
Tooling can inspect a language without executing it
The new (sigil language) module exposes pure header inspection and reader availability discovery without loading reader code. Explicit activation separately validates declared capabilities before enabling formatter or document-analysis behavior.
This separation lets editors safely recognize an alternate-language buffer, show its language identity, and ask for trust without running author code on open. Persistent approval can be tied to the exact resolved reader artifact, so changing that artifact revokes the approval rather than silently extending it to new code.
Release builds reject dependency drift
Dependency repositories and worktrees now follow SIGIL_HOME, with ~/.sigil retained as the ordinary default. This gives release and CI builds a real private dependency store instead of allowing an ambient shared worktree to change beneath a locked build.
The bootstrap installer now honors an existing lockfile instead of resolving the latest matching tag. The release procedure also checks every external worktree against its exact committed sigil.lock revision before compilation. A rewritten lock or a missing, dirty, or mismatched checkout stops the build before artifacts are produced.