- Stamp all publishable packages at v0.0.20.
- Publish release notes for the contract-sidecar improvements.
- Refresh the compiler surface manifest for the release.
- Add static Array and Uint8Array copying, sorting, and join surfaces.
- Lower Uint8Array spread, destructuring, and iterator methods across C and LLVM.
- Pin Node 24 semantics with differential coverage and runtime size gating.
- Retain representative Darwin kqueue coverage in the default gate.
- Schedule native runtime tests by host and make Linux clang invocations portable.
- Resolve canonical OCI manifest digests for direct and indexed images.
- Shard portable coverage across 16 sandboxes while retaining focused Darwin contracts.
- Run invariant suites once and keep differential and sanitizer-sensitive coverage in both lanes.
- Harden sandbox transport, exit-status parsing, and Linux runtime test portability.
- Lower asynchronous ESM initialization with Node-compatible dependency ordering and caching.
- Finish top-level promises consistently across the C and LLVM runtimes.
- Add differential coverage for imports, rejection, and unsettled evaluation.
- Stamp the runtime, compiler, and CLI packages at 0.0.17.
- Regenerate the surface manifest for the synchronized version.
- Add release notes for the Windows CLI build and run fixes.
- Lower Number.prototype.toFixed through the compiler IR and native backends.
- Match JavaScript rounding, range errors, and numeric edge cases in the runtime.
- Add differential coverage and update surface metadata and diagnostics.
- Synchronize package versions and regenerate the compiler surface manifest.
- Publish release notes for prompt output flushing and Linux host clang builds.
- Bump all published packages to 0.0.15 and refresh the surface manifest.
- Promote the outbound native FFI notes into the marked release block.
- Verify the workspace build plus plain and sanitized full test lanes.
- `http.get("http://host/path")` and its https spelling now compile. The declarations only described the options-record form, so the first thing a from-scratch client writes was a type error — the shape worked under --dynamic, where the engine does not consult our declarations, which is how it read as a hello-world failure.
- A URL object is accepted the same way, as its href through the same parse. An unparsable input is the WHATWG "Invalid URL" TypeError and a scheme that is not the calling module's is ERR_INVALID_PROTOCOL, both catchable, matching Node rather than silently upgrading the dial.
- `request` and `get` take one signature with a union first parameter instead of Node's two overloads: `tls ? https.request : http.request` unions two function types, and resolving a call on that union collapses each side to a single signature, so an overload set misresolves in either declaration order. The lowering dispatches on the argument's own type.
- Both rows run on the LLVM backend, and the tls CA-store entries joined it too — the omission there was stale, so 2557-tls-ca-store moved off the C lane with identical output.
- Corpus 2644 and 2645 cover both schemes against loopback servers, so neither needs the network.
- http, https, TLS and HTTP/2 clients now resolve the hostname before connecting. A client that dialed by name got ENOTFOUND regardless of the name — only literal addresses worked, which is most of what a from-scratch client writes.
- Only the dial takes the address. The original name stays on the request, which is what the Host header carries and what SNI and certificate verification see, so a resolved dial does not weaken the TLS check.
- node:net's own connect surface stays resolver-less: Node's async lookup semantics there are a separate piece of work, so `net.connect(port, hostname)` still refuses to resolve.
- Island values held in `unknown` arm the routed operation set (SCR_DYN_JSVAL): keyed reads and writes, calls and method dispatch, Object statics, and `??` all run in the engine, so a wrapped value answers exactly what Node answers instead of meeting a fence.
- Scalars normalize at the wrap, composites stay engine values by reference, and the round trip preserves identity — a value that crosses into the checked-dynamic tree and back is the same engine value.
- deepStrictEqual over a mixed engine-vs-native pair fails with the reason stated rather than guessing at an answer.
- Corpus 2582–2585 and an npm routed-row fixture pin the behavior; the dyncheck expectations move with it.
- The retired "DOM" nickname is swept out of the sources and corpus in the same pass (29 comment sites) — the world is the checked-dynamic tree, its values are dyn values.
- The crypto introspection statics (getFips and the cipher/hash/curve name lists) bake at the call site, and the crypto constant table joins http2's under a generalized per-module baked-constants lowering.
- The CA-store introspection surface lands in its own unit (scr_tls_ca.c) behind its own link gate, so a getCACertificates-only binary never pulls mbedTLS: getCACertificates, rootCertificates, setDefaultCACertificates.
- http2.createSecureServer grows the eager request handler and the runtime options record, riding the same server-options walk as tls.createServer; string-typed 'data' listeners decode.
- process once/off for 'unhandledRejection' plus the sibling 'rejectionHandled' registry, removal by closure identity per the warning-registry stance.
- Merge resolution unions this lane with main's fs ladders, createRequire erasure, and dyn secure-context work; the runtime's retired "DOM" nickname is spelled "dyn" throughout.
- Add Agent connection accounting and HTTP/socket compatibility surfaces
- Support dynamic Buffer at and slice access
- Pin behavior with differential corpus coverage
- for-of, destructuring, and spread over engine-held dyn values ride the engine's own iterator protocol with V8's exact non-iterable spellings; for-of over dyn lowers generally
- Static promises cross into the engine as thenables; Promise.all over mixed and non-literal entries runs the engine's own combinator; engine-array fulfillments exit by reference
- The re-minted silent-wrong-answer path is closed: island-literal members whose values poison fence at the read with the captured diagnostic
- The checked-dynamic tree replaces the old nickname across comments and internal docs
- text, json, and buffer settle real promises over the readable machinery with Node's settle timing and rejection set; arrayBuffer and blob fence with their representation reasons
- createRequire over this file's URL is compile-time plumbing: builtin specs become namespace imports, relative JSON bakes as validated documents, npm packages ride the require-condition graph, unresolvable names throw Node's catchable MODULE_NOT_FOUND
- module.builtinModules bakes as the compat target's exact list
# Conflicts:
# packages/compiler/src/frontend/lowering/lower-modules.ts
# packages/compiler/src/frontend/lowering/lowerer.ts
- Buffer slice and subarray become true aliasing views over the retained owner — mutating through a view was silently computing wrong bytes
- Each stream tick posts a one-to-one marker on the user tick queue, so stream emissions interleave with process.nextTick in enqueue order, Node's order by construction; the station remains for teardown
- Stream emitters model the pre-created event-key shape governing eventNames order; push honors defaultEncoding with Node's unknown-encoding errors
# Conflicts:
# packages/compiler/test/ts7/baselines/order-parity.json
- An interval-and-wholeness inference over the lowered IR proves integrality and range for every value reaching a declared i64/u64 slot, with loop-header widening precise enough that the bounded counter loop proves its exact range
- Refusals carry the slot path, the failed obligation with evidence, and the author's concrete fix as SC4021, SC4022, and SC4023
- Declared slots are both obligation and assumption: call sites check arguments, callee bodies assume their classes; integer returns emit exact machine-integer wrappers and inbound params trap through the structured host-contract family
- Math.trunc and Math.ceil compile statically
# Conflicts:
# packages/compiler/src/library/profile.ts
- The loadPlugins shape end-to-end: Promise.all(plugins.map((p) => loadPlugin(p))) — a NON-literal argument the checker spells any[] — lowers to the ENGINE's own Promise.all over the lifted array, and the INFERRED Promise<any[]> return coerces through the island→static promise bridge with the new SCR_ISLP_JSVAL_ARR settle payload: the fulfillment exits Array.isArray-gated BY REFERENCE at the settle, a lying fulfillment rejecting with the boundary TypeError (trust-but-verify at the settle).
- coerceToExpected's jsval branch gains the promise-slot arm generally: island values flowing into Promise<void>/Promise<any>/Promise<any[]>-typed slots bridge instead of fencing (the passing-a-package-promise-into-promise-typed-parameters fence retires for these inners); other inners keep the named fence.
- Corpus 2605 extended with the non-literal all + inferred-return rows, byte-identical to Node under both backends and SAN-clean; dyncheck/errors/island suites green.
- jsvalIn (and the island-literal member path behind it) accepts STATIC promises whose fulfillment is in the reverse bridge's payload domain — void/number/boolean/string/'any', plus the NEW Promise<any[]> payload (SCR_ISLP_JSVAL_ARR: a native array of engine cells re-enters as a fresh engine array over the SAME engine values). scr_jsval_from_promise emits from jsMarshal in both backends; the IR validator admits the arm.
- Promise.all with MIXED entries where some entry is an island value (the withPlugins shape: Promise.all([loadBuiltinPlugins(), loadPlugins(plugins)])) lowers to the ENGINE's own Promise.all — island entries pass through, static promises bridge as thenables, and the combined result stays an island value the static side awaits through the existing island→static bridge. All-static tuples keep the typed fence hint.
- Corpus 2605 (unawaited static promise in an 'any' slot answers typeof "object" and awaits engine-side; the mixed-all + .flat() chain) is byte-identical to Node under both backends; SAN clean. Composite fulfillments (Promise<{...}[]>) stay fenced with the promise type named — the payload-domain residue.
- LIB_PARAM_CLASSES/LIB_RETURN_CLASSES grow i64/u64 (the prove-or-refuse pair); u8/u32/i32 stay param-only with the message updated to point at the landed machinery
- sidecar.integer_slots declares contract slots by sidecar path (Msg.count, Point.x, helpers.f.params[0], helpers.f.return); the projection spells each declared slot i64 (the frozen format-1 vocabulary — u64 is the stricter compile-time obligation over the same wire spelling), refuses non-number or unresolvable paths, and emits integer_slots as the resolved-decision attestation in declaration order
- compileLibrary runs the integer-boundary inference over export-map and sidecar-declared slots and refuses SC4021 (representability) / SC4022 (wholeness) / SC4023 (range), each carrying slot path, failed obligation with evidence, and the author's fix; u8/u32/i32 plumbing classes seed parameter shapes for free precision
- Both emitters grow i64/u64 wrappers: inbound params range-check through scr_library_i64_in/u64_in (the SC4012 host-contract trap — silent rounding past 2^53 is a coercion the author never wrote), returns convert exactly under the discharged proof
- Profile-loader suite pins the new surface; the pre-ask-4 pins updated
- The ratified rename rider (world-unification §7 lane 5): "DOM" collided with the browser DOM and, post-lane-1, the structure is no longer a document tree. Comments and doc prose now say "the checked-dynamic tree" for the noun and "dyn" adjectivally; runtime symbol names (scr_dyn_*), the error.domClone libCall, and the real web DOMException family are unchanged.
- The few user-facing strings carrying the nickname move with it (the structuredClone cyclic message, the dc subscriber/publish fences, two emitter ICE texts); diagnostics snapshots regenerated (96 pass). One private compiler constant (DOM_PROTO_METHOD_NAMES -> DYN_PROTO_METHOD_NAMES) rides along.
- Mechanical sweep, 142 files, comments/prose only — no behavior change.
- The iteration pack's JSVAL arm is ARMED (scr_dyn_iter_pack, scr_dyn_arr_push_spread, scr_dyn_pack_push_spread_iter route through the new iter_drain ops row): the ENGINE's iterator protocol drains into a fresh DOM array — engine arrays, generators, Maps, Sets, and Symbol.iterator implementations step exactly as Node runs them, elements wrapping back scalar-normalized.
- for-of over checked-dynamic values LOWERS now (both backends): the source packs once through dyn.iterPack and a hidden index loop binds each element as a dyn value (new dyn.arrLen/dyn.arrAt accessors) — an eager snapshot, the matchAll stance. Pattern heads, pre-declared and var heads, and labeled break/continue all ride the desugar. Non-iterables throw V8's for-of CallPrinter spellings, threaded into the engine-side guard.
- The validated exit gains the jsval-element-array arm (scr_jsval_exit_jsval_arr, both backends): an 'any' value exits into 'any[]'- and 'any[] | undefined'-declared slots Array.isArray-gated, elements BY REFERENCE (identity crosses, the spine is a snapshot) — the withPlugins loadPlugins(plugins) boundary, the driver frontier's first named poison.
- Corpus 2604 and npm case jsval-iterate (package-minted Set/Map/generator/Symbol.iterator) are byte-identical to Node under both backends; dyncheck's jsval-iterate pin flips from the retired island fence to the armed answers; SAN clean over the drain/wrap/exit churn.
- The pattern fence lifts: the vendored engine already executes named groups and named backreferences
- Match results project .groups at compile time as the checker's own record shape, with Node's key order, undefined-when-none, and null-read error texts
- Replace and replaceAll resolve $<name> templates with Node's exact edge behaviors; matchAll rows carry groups through for-of, drains, and destructuring
- Destructuring over index-signature records reads through the overflow map generally
- lowerRegexLiteral drops the (?<name> fence: patterns and \k<name> backreferences run natively in libregexp, and .groups on exec/match/matchAll results desugars into a compile-time record projection over the honest slice — the checker's own Record<string,string> hybrid with overflow entries in group declaration order — whenever the regex is statically known (literals, const bindings, new RegExp("..."), matchAll rows via for-of bindings, stored drains, spread rows, element access)
- Node's exact shapes: a group-less regex answers .groups === undefined, nullable receivers throw Node's TypeError on the unit arms, ES2025 duplicate names project the participating alternative, and destructuring rides — flat, aliased, and the nested { groups: { year } } pattern — via the groups wrap plus a general overflow read for undeclared keys of index-signature shapes
- scr_put_substitution resolves $<name> against lre_get_groupnames with Node's edge answers: nonexistent and nonparticipating names substitute empty, $< stays literal when the pattern has no named groups, an unterminated $<name stays literal
- s.match(re) also claims a nullable string receiver (the Dict<string> member spelling) through the checked narrow; an untraceable .groups read keeps the SC2020 fence with a hint naming the traceable shapes
- Differential corpus 2604-2607 (both backends, SAN), runtime C substitution/backreference cases, refreshed diagnostics snapshots and surface manifest; corpus 1614's deliberate deferred fence moves to a Proxy wrap now that hybrid record reads compile
- The Readable defaultEncoding option lowers to a push-side decode default (Buffer.from(chunk, enc)); push(chunk, enc) with any literal encoding decodes per call and overrides the default, utf8 included
- Unknown literal encodings become Node's runtime TypeError — at construction for the encoding/defaultEncoding options (nodeThrowExpr, the ladder pattern), at the call for push
- on/once/off admit Node's ignored extra arguments when they are pure reads (the suite's stray-third-argument shape); effectful extras keep the fence
- readable.pushStrEnc/readable.pushEncoding land in both backends; corpus 2607-stream-push-encodings pins the decode, override, and both throw sites differentially
- Every deferred stream emission posts a raw marker on the user tick queue (scr_next_tick_raw) and each marker dispatches exactly one stream tick, so resume_/emitReadable_/endReadableNT interleave with user nextTicks in enqueue order — in Node they are the same queue
- Cures the setEncoding-with-buffered-bytes shape: a nextTick registered after on('data') now observes the flowed chunks, and stream emissions run before microtasks at each checkpoint instead of after
- The loop station stays as the drain for anything a marker never reached and as the uncaught-throw cleanup of undelivered ticks
- Corpus 2606-stream-ticks-are-nextticks pins the interleavings (buffered decode, split multi-byte char, tick/data/tick ordering, end-after-tick) differentially on both backends
- Stream constructors reserve their class's known _events names (Readable close/error/data/end/readable, Writable close/error/prefinish/finish/drain, Duplex the union) — empty reserved buckets are invisible to every read but hold the first-registration rank, so eventNames lists them before earlier user events, exactly Node's shape optimization
- Shape mode reproduces Node's removal split: removeListener keeps an emptied name's rank (events[type] = undefined), the named removeAllListeners deletes a populated key (and resets wholesale when the count drains, kShapeMode quirk included), the no-argument wipe resets everything and leaves shape mode
- Corpus 2605-stream-event-names pins the order, rank survival, drain, and wipe behaviors differentially on both backends
- scr_bytes_subarray: a same-elem view retaining the owner (the DataView rule, chain depth 1); subarray() and Buffer's slice() lower there, plain typed arrays' slice() keeps the copy — mutations through views are visible both ways now, byte-exactly with Node
- Buffer.from(x.buffer, byteOffset?, length?) lowers as the dataViewNew view construction (the syntactic .buffer peel); the fallback lib gains the ArrayBuffer overload
- fillElem: TypedArray.prototype.fill on non-u8 receivers, per-element coercion with slice-clamped indices; u8 keeps the Buffer fill family
- Both backends emit the new intrinsics; corpus 2604-bytes-views pins aliasing, offset composition, swap-through-slice, clamping, and fill coercion differentially
- scr_sc_text/json/buffer accumulate every chunk through a native 'data' listener (string chunks as their utf8 bytes, the Blob rule) and settle at the terminal point through the finished watcher — Node's own eos timing, verified byte-exact including resolution landing after 'close'
- Rejections match Node's set: the stream's error, ERR_STREAM_PREMATURE_CLOSE on an early close, json's SyntaxError on malformed text, and the async-iterable TypeError for a stream with no readable side
- lower-stream's stream/consumers arm lowers text/json/buffer over one lowered stream argument (json answers a checked-dynamic promise — the JSON.parse unknown stance); arrayBuffer and blob fence module-qualified with pointed hints, since neither value has a representation
- Both backends emit sc.text/sc.json/sc.buffer; the trio joins the may-throw seeds, the loop-liveness set, and moduleUsesStream's link gate; the SC1010 hint, its snapshots, and the surface manifest gain stream/consumers
- Corpus 2604/2605 pin the consumers differentially on both backends and under ASan + RC audit: split multibyte sequences across chunks, encoded string-chunk streams, settle ordering, empty streams, and all four rejection arms
- fs.exists' async fire compiles out under SCR_LIB and the compile-time scan refuses the surface with the event-loop family
- The regex-free size ceiling re-bases +8KB for the engine-handle arms and validation-ladder strings
- Evolving-any receivers holding checked-dynamic values take keyed writes with ToPropertyKey-exact key spelling; dyn-keyed reads gain the same key stringification
- Array destructuring over dyn sources packs via the spread walk with V8's exact non-iterable TypeError wordings
- The dyn keyed-write miss error appends the primitive's rendering, matching Node
# Conflicts:
# packages/compiler/src/frontend/lowering/lower-exprs.ts
# packages/compiler/src/ir/validate.ts
- Per-API validators in the checked-dynamic lane run Node's argument checks in Node's order, then the real operation or a rendered fence thrown after validation
- fs.exists is genuinely async including the synchronous-false wart; mkdtempSync and lchmod are real
- Destructured sub-namespace bindings resolve as their module; function-armed unions cross into the checked-dynamic world
- dgram state errors carry their ERR_SOCKET codes
# Conflicts:
# packages/compiler/test/ts7/baselines/order-parity.json
- Object.create(null) is a real null-prototype dictionary: inspect, toString, and deepStrictEqual answer Node's forms; the dynamic tier routes to the engine's own Object.create for live delegation
- Object prototypes fence by name in static builds — an own-copy stance is observably wrong under Node's empty-own-set answers and live proto mutations
- entries() and keys() walk any static array live in for-of heads and iterator-helper chains
- Object.assign(target, ...sources) packs spreads with JS's evaluation order before any copy, with V8's position-dependent error texts
# Conflicts:
# packages/compiler/test/ts7/baselines/order-parity.json
# packages/runtime/src/scr_json.c