- Remove C emission, debugging options, and automatic backend fallback.
- Complete LLVM lowering and native bootstrap coverage across supported targets.
- Link executables and libraries with precompiled C runtime packs, including iOS and Android.
* Split volatile library identity code
- Emit build identity getters from a tiny standalone C translation unit
- Cache generated library program objects independently of volatile identity and archives
- Preserve toolchain, runtime, and translation-unit dependency invalidation coverage
* Preserve library identity during localization
* Keep library identity sources private
* Preserve library identity in public emission
* Preserve identity in kept library units
* feat: add host-callback channels to library mode
- the profile's `callbacks` array declares named channels and
`abi.callback_register_symbol` names the one registration entry point:
`int32_t <sym>(const char *name, void (*fn)(void), void *ctx)` — 0 on
success, -1 for an unknown or NULL name, latest registration wins, a
NULL fn clears, registrations persist across init/reset. The stored
pointer's typed shape is the channel's with the opaque context first,
the panic sink's layout
- channel signatures ride the existing marshalling classes: params are
f64/bool/string/bytes plus the u8/u32/i32 plumbing classes (outbound
plumbing keeps JS's ToUint32/ToInt32, the executable FFI rule);
returns are scalar only (f64/bool/u8/u32/i32/void — a buffer return
needs an ownership contract the mode does not define). string/bytes
parameters arrive as (ptr, len) pairs borrowed for the call's duration
- compiled code reaches a channel as a signature-only ambient function
declaration whose direct calls deliver synchronously on the calling
thread; the recognition rides the FFI import machinery under a library
flavor: SC4024 refuses a call the channels cannot serve (undeclared
name or off-class signature), unused channels are legal capacity, and
callback-free profiles keep the ambient ReferenceError semantics
- calling an unregistered channel is the SC4025 runtime trap: a detected
trap through the library funnel, so the structured sink message names
the channel in its text and the entry the host called in its symbol
field, and profile teachings/remediations overlay it like the rest of
the runtime family
- registration slots are per copy of the runtime state, the sink's story:
per-archive under abi.localize_runtime (the register symbol joins the
localization keep-list), per-thread instance under
abi.instance_per_thread. The host callback must not reenter any library
entry or unwind across library frames
- both emissions produce identical behavior by construction: the slot
store/fetch lives in scr_library.c (scr_library_cb_set/_require/_ctx),
the generated TU emits the registration dispatch and typed indirect
calls, and the trap text is assembled once at export resolution
- callback-free profiles emit byte-identical program TUs and serialized
IR, and executable builds are byte-identical end to end
- conformance: the CB suite (tests/harness/library-callbacks.test.ts)
covers the acceptance stream, unregistered and pre-registration traps,
symbol exactness, teaching overlays, SC4024 refusals, capacity and
callback-free postures, the localized+thread-instanced composition
probe, and ASan reruns; profile-shape refusals join
library-profile.test.ts
* fix: preserve callback binding identity
* fix: harden library callback contracts
* fix: recognize project callback declarations
* fix: enforce host callback declarations
- Track whether subscriptions_export is explicitly declared and reject dangling names at the profile.
- Preserve optional omission semantics and cover both paths with contract regressions.
- Resolve scalar alias chains to their primitive wire types.
- Keep aliases out of the sidecar type table.
- Cover records, messages, helpers, and integer slots.
- Treat readonly T[] and ReadonlyArray<T> as mutability-neutral slices.
- Cover model, message, optional, and helper projections across readonly spellings.
- A fences array denies manifest-identified surfaces reached by the compiled library graph: SC4008 names the id and surface with the profile's teaching as an attributed note; unreached fences leave emission byte-identical
- Fence evaluation walks the dead-stripped module IR — the same ground as the deterministic attestation, making the full-fences invariant structural
- Teachings generalize to any refusal code or manifest id; unknown or unpoliceable fence selectors refuse loudly rather than sit inert
- Teaching and remediation strings take the ratified byte constraints and the 512-byte cap everywhere
- Profile fences (determinism.fences) resolve at load against this release's surface manifest: exactly one of id/prefix, unknown selectors and unpoliceable static entries refuse SC4001 loudly (ratified strictness), folded constants exempt under a prefix only
- A fenced static surface reached by the compiled library graph refuses SC4008 at the reaching construct, over the same dead-stripped module IR the deterministic attestation reads; unreached fences emit byte-identical code
- The SC4004/SC4005 teaching rider generalizes: one decoration pass attaches profile text to any library refusal by code, manifest id, or fence coverage, rendered as a visibly-attributed note line the renderer prints after the hint
- Teaching/remediation strings now refuse every control byte below 0x20 except newline and cap at 512 UTF-8 bytes; fence remediations feed profileRemediation through covered entry codes
- K14 fence conformance on both emissions, fence-family SC4001 exact-path tests, and the ask-5 §4 pin: the full-fence worked-example profile compiles and attests deterministic: true
- library-mode, library-contract (cache dir plus the tmpdir npm root), and library-asyncfree now carry a plain/san path segment: both flavors run the same ordinary builds, and the nightly's concurrent both-flavor recipe raced ar/ranlib in the shared dirs ("can't open file ... lib.lib.a"); the per-build -san tag stays, it distinguishes explicitly-sanitized builds within one suite
- the same flavor split lands on npm-static's fixed npm-static-workspace dir (the two flavors even build with different sanitize flags there), provenance's shared outDir, and diagnostics' $TMPDIR/scriptc-diag scratch (some entries emit backend artifacts before failing)
- dec-oracle publishes in the differential/llvm/linux/windows lanes are now atomic (write tmp, rename): the content-keyed path is shared across flavors and lanes, and a truncate-and-rewrite could expose a torn oracle to a concurrent reader
- every other suite already keys its build dirs by a content hash that includes the flavor, and the CAS build cache folds the sanitized flags into its key, so those stay as they are
- proof: three consecutive concurrent both-flavor library-mode runs from a wiped cache all pass 45/45 with zero ar/ranlib failures, and a concurrent both-flavor run of all four library suites passes 125/125 in each flavor
- compileLibrary runs the --npm-static eligibility bar automatically over every bare specifier the graph exposes (opted-in packages' own import and top-level require edges included, iterated to a fixpoint) — an eligible package compiles statically into the library graph, and every fallback the shared frontend records refuses as SC4013 naming the package, the specific failed bar, and the vendor-or-drop remedy (with the profile's SC4013 teaching riding the hint), never SC1010/SC2013's executable-lane teachings.
- requireInitStmt now emits the guarded %init call for a bare require naming another opted-in package: the dep's module body never ran before (NULL-closure crash at first use), a latent npm-static gap on both lanes that the library fixpoint hits immediately; the executable lane never exercised an inter-package require.
- Contract facts exclude statically-compiled npm files (their .d.ts is dropped by construction, so no npm declaration can name a wire-contract type) while their bytes keep joining source_hash/build_id through moduleOrder; the sidecar stays byte-deterministic and a package-file edit flips both identity hashes.
- Builtins keep their story under the npm posture: async_free builtin imports compile alongside npm code, event-loop surfaces still refuse SC4005, no new fence.
- New fixtures npm-static, npm-refuse, and contract-npm vendor fake packages per the tests/fixtures/npm precedent; the K12 suites assert the compile and refusal sides on both emissions and the contract suite covers the identity-hash implications.
- New contract-order conformance fixture (both emissions): union arms anti-alphabetical with payload records declared in a separate file (import order never perturbs table order), an anti-alphabetical enum with a global-shadowing "Infinity" member, and a union referenced through a type alias (the table derives from the aliased declaration; the alias adds no entry and no reordering).
- Contract facts now scan the whole program graph, not just the entry: type-only modules join (they have no runtime edge, so they ride the program's source files rather than moduleOrder), non-entry modules anchor after the entry in bytewise path order, and the identity hashes cover type-only modules so contract-bearing edits always move source_hash/build_id.
- SC4010: a tabled or designated type whose members gather from multiple declaration sites (interface merging, module augmentation, a same-name exported type in another module) refuses with every site named file:line.
- SC4011: a conditional or mapped type producing a tabled/designated type refuses with its own teaching.
- Union composition (type Msg = A | B where A/B are kind-tagged unions) is allowed and pinned: arms flatten depth-first in source order, each constituent in its own declaration order, and an arm name appearing in several constituents keeps its first occurrence; a repeat among one declaration's own inline arms still refuses.
- The return shapeRef now seeds container 'helpers' with the helper name as the member, so an inline-record helper return tables helpers_<name> instead of helpers_<name>_return; parameter naming (helpers_<name>_<param>) is unchanged
- The contract fixture gains 'extent', a helper returning an inline record, pinning the synthesized name helpers_extent in the type table and the value-kind helper return with the arena bit
- The anti-alphabetical suite asserts the new struct entry and helper row on both emissions; V13 byte-determinism stays green
- the contract fixture declares every order anti-alphabetically (type names, fields, enum members, union arms, msg arms, helpers) and the harness asserts the exact orders on both emissions
- its probe reads the identity getters before init and after a poisoning trap and the harness compares both reads to the sidecar's build_id (V12 plus the ratified exemption, end to end)
- V13 rides two independent identical invocations compared hash-equal; V11 rides nm both directions over the prefix
- the contract-attest fixture pins tuple-returning init/update, subscriptions presence, the default <out>.contract.json path, the empty absent forms, and Date.now demoting deterministic to false
- the validator suite passes a full-vocabulary conformance document and catches one targeted mutation per rule, plus SC4009 refusal coverage through compileLibrary