- console.log routes non-scalar arguments through the static inspect machinery
- Union arguments dispatch per arm at runtime; string arms print raw
- Object literals widen per-field into a uniquely-fitting union arm
- The limitations page documents the type surface
- Island values exit validated into intrinsic slots; checker-any dispatches to the DOM machinery
- World-mixing backstops make jsval/dyn confusion structurally impossible
- Regex arrays compile; dyn-root JSON.stringify matches across backends
- A silent invalid-C escape and a giant-TU stack overflow fixed
- The full legacy surface: parse, stringify, escape, unescape, the aliases
- Node's scan state machine in C: separators, maxKeys, malformed-escape and truncation quirks
- Link-gated; escape-only programs never link the unit
- Lexically-bound private calls devirtualize by construction; statics and static blocks included
- Private accessors with observable get-then-set order; private generator methods
- Brand checks fold statically or ride the vtable interval test
- util.inspect omits private members exactly like Node
- The performance global routes through the perf_hooks lowering in all spellings
- Response declares its implemented headers/arrayBuffer/bytes surface
- Math.max and Math.min lower at any arity with NaN and negative-zero exactness
- Copy-installed workspace members classify like symlinked ones
- The performance global routes through the perf_hooks lowering in all spellings
- Response declares its implemented headers/arrayBuffer/bytes surface
- Math.max and Math.min lower at any arity
- Copy-installed workspace members classify like symlinked ones
- the uncollected-class capture box no longer carries the boxNewC marker comment: run()'s sweep sanitizes the slot before emission, so the pin asserts no R adapters, no uncollected marker, and a plain-kind box
- a dyn root holding undefined stringifies to the TEXT "undefined" (Node's answer for the undefined result value) instead of the nested-position writer's null — corpus 2448 pins both backends
- fallible like the C dispatch: a runtime handle inside the tree throws, so the pending check runs
- island ('any') arguments at intrinsic/libCall/callValue slots take the validated exit (dynCheck's stance); non-exit-safe slots fence with the slot named, and the boundary pass backstops every jsOp/dynCall/dynInvoke argument so world-mixing sites can never ICE
- a checker-'any' receiver/callee that LOWERED checked-dynamic dispatches to the DOM machinery: ambient-this reads are dynKeyGet, rest-args map/forEach ride the runtime dispatch, dyn callees take dynCall
- Object.entries/values push unit-armed (null | undefined) fields as the null literal; new Set(seed) exits an island-handle seed as a validated copy
- fence-bodied functions emit even when their ABI names an unregistered class, and a run()-end sweep rewrites leftover unregistered-class type slots to the inert f64 placeholder — the clang invalid-C escape closes with the ICE
- RegExp[] compiles (REF elements, both backends; map callbacks returning other unrepresentable kinds meet a named fence), and the C emitter appends program-sized line arrays by loop, not spread (500k-line TUs overflowed the stack)
- order-parity baseline gains the 2450-2457 corpus entries and the private-members diagnostics entry (purely additive; re-recorded from the native lane).
- Privates ride the ordinary member maps under their unspellable spelled names; a subclass redeclaring an inherited private name is fenced, so base-chain walks ARE lexical resolution and privates never enter vtables — JS's no-dynamic-dispatch semantics by construction.
- Private GENERATOR methods compose the generator machinery with this as param 0 through the gen-spawn wrapper (the vtable problem that keeps public generator methods fenced does not exist for privates); async and generic privates ride their existing static-dispatch machinery.
- Private statics lower as module globals/functions through the declaring class's own name; subclass-named and class-value receivers fence (JS brands the declaring constructor alone).
- '#x in obj' lowers as instanceof-the-declarer: static folds at/below and disjoint, the vtable interval test when the declarer sits below the receiver's static class, and unions of decided class arms collapse to tag tests; unknown/generic/static brands fence with pointed hints.
- util.inspect omits private fields exactly like Node (an all-private class prints 'C {}'); corpus 2450-2457 pin every form differentially on both backends, diagnostics private-members pins the fences.
- scr_qs.c ports Node v24's legacy codec quirk-faithfully (the scan state machine with maxKeys' pair budget, unescapeBuffer's code-unit byte truncation with U+FFFD replacement decode, encodeStringified's value rules over the DOM crossing); link-gated by moduleUsesQs, and escape rides the always-linked component encoder
- parse's result is the call site's ParsedUrlQuery dictionary (the networkInterfaces verification stance; the runtime fills the overflow map and groups repeats into string[] buckets), sep/eq/maxKeys complete to Node's defaults, and custom encoder/decoder options fence by name
- decode/encode lower as Node's own aliases; both backends emit the same runtime calls byte-identically
- querystring joins SUPPORTED_BUILTIN_MODULES, the fallback declarations, and the regenerated surface manifest, so npm-static packages requiring it unguarded stop falling back to the island (the shim stays for island code)
- corpus 2460-2464 pin the grammar corners against Node: malformed escapes, '+' vs %2B, repeated keys, maxKeys with empty segments, multi-char/multi-byte separators, astral truncation, and every CJS acquisition spelling
- non-core scr_trap/scr_trap_fmt move from scr_console.c to scr_exception.c: the failure-channel unit is in every link, the runtime's own unit-test TU subsets included (the console unit is not)
- K8 additionally asserts no scr_loop/fiber/timer/child symbol is defined in or referenced by the archive — the design's mechanical backstop for the narrowed core base set
- five generic fixtures under tests/core-mode (scalars, buffers, reinit, traps, init-trap) with C probe drivers; the harness flips the profile emission and pins identical outputs across the two lanes
- K1 nm symbol exactness both directions; K8 ambient audit (no sigaction/signal/pthread_create/atexit/setvbuf references — scr_init and scr_lib_init compile out under SCR_CORE)
- K3 covers both arena postures over one core; K5-K7 cover sink-exactly-once, init traps, pre-registration abort, Uncaught rendering, poisoned-core aborts; K10 reruns K4/K5/K7 under ASan + the RC audit's re-init zero-heap seam
- K9 drives SC4002/SC4003/SC4004/SC4005/SC4007 end to end with the profile-teaching rider verbatim
- IrModule.core lands the resolved export map + mode-provided symbol names on the IR; both emitters generate the external ccc wrappers, the re-runnable init entry (globals released and zeroed, error-vt stamps, %main, escaped-exception check), sink registration, and the optional reset/collect entries from the same facts
- marshalling wrappers delegate to scr_core.c helpers (str/bytes in-copy, arena-out), so the two emissions are identical by construction; both arena postures emit from resultResetSymbol
- compileCoreArchive builds <name>.core.a: program TU + the narrowed core runtime set (no scr_async/scr_child) + IR-gated pure-data units, all -DSCR_CORE; vendored zlib objects keep the libc/libm-only undefined-reference contract on hosts
- profile-mapped exports seed lowering reachability (coreRoots) so uncalled exports stop dead-stripping on the core path
- emitted family-4 traps (OOM, invalid union tag, bad key) route through scr_trap in both backends
- CLI verb: scriptc core --profile <file> [-o out]
- names the deliberately re-typed ambient surface, the second-chance preflight, and the declared-but-fenced console members
- the union-edges bullet drops console.log(u), which now dispatches per arm
- literalUnionArmOf probes the contextual union's checker members: literal-vs-literal fields decide by value, absent arm fields must be optional-flavored, excess fields disqualify
- exactly one fitting member builds the literal at that arm's shape so its field types drive every property's coercion; zero or several keep the SC2003 fences
- corpus 2442-2444 pin the reducer and discriminated-message shapes differentially on both backends
- console.log/info/debug/error/warn take unknown[] and render every non-scalar argument through the static util.inspect at the rest-args depth 2, strings verbatim
- top-level unions dispatch per arm at runtime with string arms raw, and util.format's %s/rest args take the same per-arm rule
- info and debug lower as stdout aliases of log; the remaining stock console members are declared in the fallback so stock-clean programs meet per-site SC2020 hints instead of a fallback-manufactured SC0001
- corpus 2440/2441 pin the widened shapes on both backends, console.log(process.argv), a find() miss union, and console.log(undefined) included
- diagnostics snapshots re-pinned: the union console fences retire and utility-types reports its real per-site fences
- mixed.ts and dynamic-mix.ts compare unknown against number so the SC1040 blocker line survives the same-kind == lowering; snapshots re-record
- corpus 2428's example strings drop the brand word; order-parity baseline re-records for the content change
- executable expansion in scr_console.c is byte-identical fputs/vfprintf + abort; core expansion in the new scr_core.c poisons, delivers to the registered sink exactly once, aborts pre-registration or if the sink returns
- 89 fputs/fprintf+abort pairs and 10 bare OOM aborts across the 20 core-linkable TUs now funnel; lazy atexit teardowns (json errdyn, regex bytecodes, symbol registry) reroute to the core reset registry via scr_atexit
- scr_core.c owns sink/poison/result-arena/reset-registry/marshalling helpers; scr_exception.c renders escaped exceptions as "Uncaught ..." into the funnel; scr_lib exposes its cleanup to the reset seam
- moduleCoreAsyncSurface finds the first async/timer/event-loop/ambient-process reach with its source anchor (async/generator functions named; libCall prefix table over timers/child/net/http/streams/signals; refused value kinds)
- coarse moduleUses* predicates as the entry-anchored safety net behind the fine-grained table
- six-program detection test (sync graph clean; async fn, generator, setTimeout, spawnSync, process.on refused)
- loadCoreProfile parses/validates the ratified profile shape (prefix discipline, pairwise-distinct symbols, meaning-changing unknown-field refusal, both arena postures, the collect entry)
- u8/u32/i32 plumbing classes accepted in parameter position only; integer returns name ask 4 in the refusal
- SC4001–SC4007 factories in the diagnostics registry, with the SC4004/SC4005 profile-teaching rider
- 17-case validation test
- esbundled's esbuild banner runs createRequire(import.meta.url) at module init; a static compile would fence at load where the island runs the package as shipped, so the opt-in falls back with the reason naming the pattern
- the ambient allowlist made node:module non-bare, so the check keys canonicalBuiltinModule alone
- == and != between two strings, two numbers, or two booleans dispatch to === per the spec (typeof guards spelled ==, n != 0); mixed kinds keep the SC1040 fence
- corpus 2430 pins typeof/number/string/bool forms and the == null idiom on both backends
- a !-asserted (or SPI-off) field first assigned past the constructor's top level rides an undefined-armed union slot: allocation writes the interned undefined, writes wrap, reads extract the declared type
- scalar reads take unit defaults where JS-undefined behavior survives (bool false, f64 NaN — conditions and arithmetic exact); string/ref reads keep the checked-extraction trap, JS's own first-member-use TypeError named earlier
- union/map/dyn-typed ! fields keep the fence; deferral propagates down the base chain with the fields map
- diagnostics fixtures re-pin the surviving fences; corpus 2429 pins the Output.initialize idiom on both backends; SEMANTICS.md 372-375
- default-export.ts diagnostics fixture repoints to the surviving export= fence (the mutable-default form graduated to corpus 2426)
- destructuring-fences.ts pins the class-instance residue: method extraction, rest elements, setter-only reads (field/getter destructures graduated to corpus 2429)
- surface-manifest sc1031 sample moves to the method-extraction refusal; manifest regenerated for the new builtin list and hint text
- order-parity baselines re-recorded: new fixtures 2426-2430, create-require, npm-reexport, and the SC1010 hint text
- tsgo panics computing readonly [] (the empty as-const array) and the facade answers any; the syntax pins the truth, so the record member walk, lowerArrayLiteral, the island-literal route, and lowerAsExpression each repair the shape to the unit-element array
- func arms now map beside data arms in unions (typeof narrows, unionEq compares closures per tag); the diagnostics pin updates
- widthLiftPlan learns tupleArr (tuple fields into array slots, per-position) and emptyArr (unit-only-element arrays reshape to a fresh empty array behind a runtime non-empty trap), so Pick-style {name, aliases} flows lift
- corpus 2428 pins the command-table idiom end to end on both backends
- a parameter-pattern/default poison in a JS source no longer fails the build: the function compiles as a single runtimeFence body (calling it throws the first captured diagnostic at its source position), the statement-deferral stance applied one level up
- signatures whose ABI names an unregistered class emit no function (the emitter would name a nonexistent struct); the diagnostics still move to the runtime-fence ledger — no call site can lower such a value (brokenGlobals family, validator backstop)
- prettier's source CLI graph now measures blocker-free; the real build proceeds to the IR validator, exposing ~61 latent SC9001 ICEs as the next burn-down list
- redeclaring an inherited field WITH an initializer lowers as the [[Define]]-equivalent assignment into the base slot at the subclass's field-init position (builtin Error prefix included — prettier's errors.js `name = "ConfigError"`); bare and type-changing redeclares keep sharpened fences (corpus 2428, diagnostics inheritance re-record)
- object destructuring of CLASS instances desugars to one member read per element, left to right: fields read slots, accessors call getters through the fieldGetExpr dispatch, renames/parameter patterns/defaults included (corpus 2429 — prettier's AstPath { previous, next })
- an object literal missing an 'unknown' field completes with the DOM undefined (the absent-property read's answer), at literal completion and in the record width relation (corpus 2430 — prettier's getFileInfo(file, {}))
- node:module joins the supported builtins prefix-only as an admit-then-fence surface: createRequire keeps a per-member fence that defers to a catchable runtime error in JS sources (diagnostics create-require pins the hint naming the pattern)
- class fields initialized with a generic arrow/function expression collect as generic members (no field slot, static per-instantiation dispatch, this as param 0); value reads and writes keep fencing at their sites, which enforces never-reassigned by construction
- the async fence in collectGenericMember lifts: generic async methods, statics, and field arrows lower as async IrFunctions through lowerGenericInstance's existing spawn-wrapper path
- Awaited<T> over a bound type parameter resolves against the binding (promise kinds unwrap recursively), so async generic bodies can bind their await results
- shadowing fences both ways: fields over inherited generic members and redeclared generic field members
- corpus 2427 pins the Output.time idiom, async generic methods, and async generic statics on both backends
- export default <mutable let> registers Node's snapshot as const storage keyed by the default alias symbol; resolveValueSymbol's default-hop walk stops importer reads there instead of chasing to the live let (corpus 2426 pins the snapshot/live split against export { x as default })
- named re-exports from installed npm packages lower as import-plus-export plumbing: the island load registers at the statement's position and bindings key the aliased symbols direct imports use (npm case npm-reexport covers named, renamed, CJS, and as-default spellings)
- node:perf_hooks joins the supported builtins: performance.now() lowers to scr_perf_now (the uptime anchor's monotonic clock, fractional ms), and performance.now.bind(performance) lowers as a () => number function value (corpus 2427); both backends
- StringConstructor/NumberConstructor/BooleanConstructor (stdlib provenance) map to the one concrete signature (value: string) => primitive
- bare String/Number/Boolean identifiers lower to interned %builtin.* closures (String identity, Number via num.fromString, Boolean emptiness), so === is JS function identity
- union func arms relax to func/unit siblings (unionFuncSetArmsOk, shared frontend/validator): closure pointer identity per tag is the narrowing
- the unionKeyGet join guards against unbuildable arm kinds instead of interning them
- corpus 2426 pins the option-table idiom on both backends
- 302 entries generated from the diagnostics registry and lowering tables
- Non-static entries carry their SC code; compilerVersion is the release string
- Committed, shipped in the compiler package, attached to GitHub releases
- Sampling harness asserts refusal codes equal listed codes
- Narrowing establishment/containment, kill routing, sibling-arm restoration
- Terminality, do-while, ternary lowering, nullish and IEEE corners
- All byte-exact against Node on both backends; two fixtures renumbered 2424/2425
- packages/compiler/surface-manifest.json is generated (pnpm manifest), committed, and shipped in @scriptc/compiler; entries project mechanically from the diagnostics registry, the unsupported-syntax dispatch tables, the stdlib/builtin lowering tables, and the supported-builtin-module list
- every non-static entry carries the SC code the compiler raises for it, and the version spine is the exact published release version
- FENCE_CODES joins the diagnostics registry so factory-minted construct fences are enumerable
- the sampling harness compiles listed-static probes and asserts each sampled non-static entry refuses with exactly its listed code, beside a byte-identical staleness guard
- the release workflow regenerates the manifest, fails on drift, and attaches it to the GitHub release
- Bare '.' and '..' specifiers resolve as relative directory imports
- TS default imports of supported builtins pass under the project's interop knobs
- Workspace packages register eagerly before the tsc gate; their shipped JS never gates
- Benign-cycle admission accepts d.ts-rooted callable arguments in the init window
- npm-static auto probes from the importing file's realm; ladder fixtures renumbered 2390/2391
- resolver-parity routes bare '.' and '..' through the relative arm (ts5 resolves them relative too)
- order-parity baselines recorded for corpus 2386/2387 and the workspace-unclean npm case
- RELEASING.md makes 'prepare X release' a complete prompt; AGENTS.md points at it
- CHANGELOG.md carries the marked 0.0.1 entry; the marked block is the release body
- sync-versions.mjs stamps the three packages in lockstep
- A github-release job tags and publishes the body after npm publish
- RELEASING.md documents the lockstep three-package prepare flow and the marked-changelog convention
- CHANGELOG.md starts with an Unreleased section and the marked 0.0.1 entry that becomes the GitHub release body
- AGENTS.md states repo-wide build/test conventions and defers docs-site specifics to docs/AGENTS.md
- scripts/sync-versions.mjs stamps runtime and compiler from the CLI version; the workflow's sync check now hints at it
- release.yml gains a github-release job that tags v<version> after a successful publish, never gating npm