- `const r: Repo = new MemRepo()` over an interface whose every member is a generic-callable method keeps the initializer's CLASS representation (genericIfaceBindingKeepsClass): the record shape maps empty — generic members are excluded — so the width copy would drop the class the calls dispatch against, and in JS the binding IS the instance.
- Calls like `r.get(...)` resolve through exactInstanceClassOf to a class generic-method call on the exact class: `this` works, state mutates on the one real instance, and record-typed USES width-coerce at the use site instead of the declaration.
- Receivers with no provable class (parameters, `let`, produced values) keep the fence, now naming the actual blocker: static dispatch needs a const bound to its `new` expression.
- Fixture 2552 (stateful implementations, two classes, block scope, casts back to the class, record-typed uses), byte-identical vs Node on both backends.
- Instantiations carry ts-level bindings alongside the mapped IrTypes: a `K extends keyof T` parameter keys its instance on the bound literal (no cross-literal sharing — the bodies read different fields), and literals forward through generic-to-generic calls.
- `T[K]` inside instance bodies resolves through the bound checker types (mapBoundIndexedAccess via the new resolveTypeParamTs hook), and `o[k]` reads whose key TYPE proves one literal — a keyof-bound parameter or a literal-typed const — lower to static field reads.
- `const h = id` registers the target's GenericFnInfo under the alias's symbol (chains, block scope, pinned values, and calls all resolve like the target's own name); non-const/reassigned aliases fence by name, and unpinned VALUE uses keep their fence at the reference.
- Fixtures 2550 (keyof/pick shapes, forwarding, runtime keys, literal-typed key vars) and 2551 (alias chains, contextual pinning, annotated generic aliases), byte-identical vs Node on both backends.
- SC2005 generic call signatures, SC2006 index-signature shapes, SC2007 overloads, SC2008 unresolved intersections, SC2009 supported shapes over an unsupported component with the component named
- Stdlib nominal types reroute to the SC2020 story instead of a duplicate code
- SC2001 keeps only bigint/symbol, constructor objects, and unresolved library generics — its registry name now says so
- Five new diagnostics programs pin one frame per code; manifest entries added; zero behavior change to accepted programs
# Conflicts:
# tests/harness/__snapshots__/regex.ts.txt
- X.#m() calls, const-bound class expressions, decorated names, and const aliases all reach static #private members when the receiver provably holds the declaring class
- The write path's exactClassOfReceiver and leaf-class rules extend to the call and read paths through one shared predicate
- Slots that can hold a descendant still fence; the read path gains the subclass-spelling fence the other paths had
- Fixtures 2520-2523 on both backends
- tsc's evolving-array analysis answers the pushed element type at later call sites; the monomorphizer trusted it while the receiver value lowered as array<jsval>, producing an ill-typed call the validator rejected
- The receiver value's element type now wins across the array method family, riding the explicit-any[] handle path; unannotated locals and file-scope aliases adopt the same spelling
- .find on handle-element arrays fences honestly instead of ICEing
- Fixtures 2510-2513 under --dynamic, byte-identical on both backends
- T[K] indexed access resolves against instantiations; Object.hasOwn/assign on records and DOM values; runtime-keyed writes to fixed shapes with a key-miss trap
- Regex union arms with instanceof RegExp as the tag test; string | RegExp shapes map
- Island literals gain getters, spreads, and real TemplateStringsArray identity for tagged templates
- JS variadics under --dynamic bind the engine's arguments array; fn(...args) lowers to engine apply
- Fixtures 2470-2476 on both backends; SEMANTICS entries 385-390
# Conflicts:
# packages/compiler/src/frontend/types.ts
# packages/compiler/test/ts7/baselines/order-parity.json
- An evolving-any array (const fns = []; fns.push(() => 1)) lowers array<jsval> at its any[] declaration, but tsc's evolving-array analysis answers the pushed element type at later method calls, so the lowering handed monomorphized helpers a jsval-element receiver under a typed signature — the SC9001 validator ICE.
- lowerArrayMethodCall now adopts the receiver VALUE's element type when it is a jsval-element array, riding the explicit-any[] handle-element lowering; HOF callback lead params bind the handles via jsvalParamOverrides whatever the evolved contextual type spelled.
- Derived bindings keep the handle-element array instead of the evolved spelling: locals adopt the initializer's type in lowerVarDecl, and file-scope globals register the handle-element array for aliases and receiver-type-preserving chains (filter/slice/splice/concat) rooted at a registered one.
- concat over a handle-element receiver decides spread-vs-element by the argument VALUE's array-ness, exactly JS's IsArray, instead of the evolved checker spelling.
- Corpus fixtures 2510-2513 pin map, filter/forEach/some/every/findIndex, mixed push sites, and the slice/concat and function-scope derived shapes, byte-identical vs Node under --dynamic on both backends.
- New codes, minted in badType's classification order: SC2005 values whose type keeps a generic call signature, SC2006 index-signature shapes outside the supported set, SC2007 overloaded function types, SC2008 intersections with no resolved lowering, SC2009 supported container/function/record shapes over a component outside its slot — the SC2009 message names the offending component (Map/Set key-value domains, array/tuple elements, union arms, function rest/params/returns, record members) via describeComponentBlocker/describeRecordMemberBlocker in frontend/types.ts, which mirror mapType's own rules on the failure path only.
- Standard-library nominal types with no lowering at all (Date, ArrayBuffer, WeakMap, the iterator and constructor interfaces) now route to the existing SC2020 story instead of the supported-set recitation; stdlib provenance is checked after the container claims so Map/Set/Promise instantiation failures keep their component story.
- SC2001 keeps the honest remainder — bigint and symbol primitives, constructor objects, and library-derived or unresolved generic shapes — and its registry name now says so; across the diagnostics corpus its rendered sites drop from 57 to 5.
- Every new code flows through the diagnostics registry, the regenerated surface manifest, and coverage-report grouping; five new tests/diagnostics programs pin one rendered frame per code, and the ts7 order-parity baselines re-record to include them.
- Zero behavior change to accepted programs: the differential corpus (900 programs) is untouched and green, and the full suite passes.
- staticCallOn and lowerClassValueProperty fenced every #private static access with a through-a-VALUE receiver, so C.#m()/C.#f on a const-bound class expression, A.#f through a const alias of the class, and Example.#m() under a replacing decorator all died with SC1090 while the direct class-name spelling compiled.
- The static-WRITE path already knew the sound rule (exactClassOfReceiver plus the leaf-class arm); classValueIsExactlyOwn now shares it with the call and read paths: a receiver that provably IS the class, or a class with no strict descendants, always carries the declaring class's brand — the fence stays for slots a subclass can inhabit, where Node throws TypeError.
- Rebindable decorated names ride the leaf arm for free: replacement decorators fence any class with subclasses before minting the rebindable global, so the decoration result is always the declaring class object.
- The read path additionally gains the subclass-spelling fence (reading an inherited private static through a subclass-named binding) that the call and direct-read paths already had.
- Fixtures 2520-2523 pin the four call forms (class-name calls including static field initializers and subclassed declarers, const-bound class expressions with reads/writes/calls, decorated classes under both replacing and void decorators, aliased class values local/module/param) byte-identical vs Node on both backends; the private-members diagnostics fixture repins the residual fence on a descendant-capable slot.
- the mockImplementations body defers one statement in static builds (SC2011, never executed) — the @deferred-fences directive keeps the coverage sweep honest
- order-parity baselines re-record for corpus 2470-2476 (new fixtures only)
- regex.ts drops the RegExp | undefined fence (regex union arms compile)
- spread-fences.ts drops the optional-into-required SC2002 (the checked NARROW lift, divergence 38's stance: the flow traps at runtime where it used to fence at compile)
- LIB_FN_SYMS mapped net.{get,set}AutoSelTimeout to scr_net_{get,set}_auto_sel_timeout; the runtime defines autosel — every LLVM-tier program touching the surface died at link
- The ABI guard gains a table-existence audit: every scr_* string the backend sources can emit must exist in scr_runtime.h as a prototype or extern data symbol
- Fixture 2500 exercises the surface differentially on both backends
- LIB_FN_SYMS mapped net.getAutoSelTimeout/setAutoSelTimeout to scr_net_get_auto_sel_timeout/scr_net_set_auto_sel_timeout, but the runtime defines scr_net_get_autosel_timeout/scr_net_set_autosel_timeout (the C backend already used the correct spelling), so any program touching net.getDefaultAutoSelectFamilyAttemptTimeout on the LLVM tier died at link with undefined symbols.
- The ABI guard could not see this: the literal-declare source scan only checks fully-literal declare strings, and the emitted scan's corpus slice never exercises the net autosel surface — a table entry whose fixture doesn't exist was invisible from both directions.
- llvm-runtime-abi.test.ts grows a third, table-driven direction: every scr_* name the backend sources can ever emit — the static string tables plus every literal @scr_* template reference (interpolated per-type families excluded) — must exist in scr_runtime.h as a prototype or extern data symbol, so a two-string name skew now fails at test time instead of at the user's link step.
- parseHeader additionally collects extern data symbols (scr_emitter_vt, scr_error_vts) so vtable-global references audit cleanly.
- New corpus fixture 2500-net-autosel-timeout.ts round-trips the default attempt timeout (set then get, integers >= 10 to stay clear of Node's clamp) and is byte-identical vs Node through both backends.
- 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
- T[K] resolves against record bindings, Object.hasOwn/assign lower over records and the DOM, fixed shapes take runtime-keyed writes with the miss trap, and string|RegExp unions narrow by instanceof
- the width family gains the checked NARROW lift and the tuple-arm literal route (the option-table shapes)
- island literals complete: get accessors, plain spreads, tagged templates with .raw, jsval ??, and call-time fence deferral for unlowerable members (lambda poisons defer too)
- JS variadic rests under --dynamic bind the engine arguments array and re-invoke through apply; dyn values marshal into the island as the deep copy
- corpus 2470-2476 pin every landing against the Node oracle on both backends
- All twenty schema fields: declaration-ordered type tables, wyhash-64 build_id, descriptor families
- Deterministic byte-equal emission on both backends, validated against rules V1-V14
- Identity getters synthesize as constants: pre-init and post-poison reads match the sidecar
- A computed determinism attestation from a conservative ambient-surface scan
- A union lacking null or undefined compares against that literal as a constant, both orders
- Effectful operands still evaluate exactly once; switch unit cases ride the same lowering
- The external adversarial corpus stands at 52 of 53 byte-identical
- 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
- profile.sidecar declares the echoed constants (wire/abi/snapshot), the identity-getter symbols, the model/msg designations, and the profile-selected "module-graph" source-hash contract; presence turns contract emission on
- wyhash.ts implements wyhash-64 final_version_3 (BigInt, vector-pinned) with the length-prefixed framing the schema's build_id definition requires
- the profile's exact bytes ride the resolved LibraryProfile (build_id input 2), getter symbols join the pairwise-distinct claim set, and unknown fields inside the section refuse as SC4001
- lowerUnitComparison folds ===/!== against a union lacking the unit arm to the constant answer, both operand orders
- a non-droppable operand still evaluates exactly once, riding a throwaway tag test
- union-switch case null / case undefined take the unit-comparison lowering, so a lacking arm never matches
- the unionEq fallback had coerced the literal through the stranded-arm trap, throwing where Node answers false
- corpus 2490-2494: the find-miss repro, every strict and loose spelling, switch unit cases, effect preservation
- mapType back-references mint placeholder shapes/unions finalized at frame exit; identity is per checker type, and context-sensitive (generic/mixin) knots stay fenced
- every type walk survives cyclic shape graphs: coinductive JSON/dyn-safety predicates, guarded formatIrType/jsvalLiftable, cycle headers via the existing collector fixpoint on both backends
- JSON.stringify throws V8's byte-exact circular TypeError (hop lines, ellipsis rule); cyclic values crossing into checked-dynamic slots trap instead of hanging
- console.log/util.inspect render <ref *N>/[Circular *N] exactly (SEMANTICS 129 resolved; depth:null lowers) and deepStrictEqual terminates through Node's pair memo
- corpus 2480-2488 green on C, LLVM, and the sanitized RC-audit lane, which proves child->parent cycles collect
- Six jobs: plain/san across three sha1-keyed case shards; an aggregate check keeps the old name
- SCRIPTC_TEST_SHARD slices the corpus harnesses; unset means everything
- Two vitest passes per job so file-granular sharding cannot drop corpus slices
- A canonical-table rewrite recognizes getter-table and star re-export plumbing
- Chaseable getter bodies type by their resolved values; the lexer name set is the contract
- Consumer-anchored errors degrade the opted-in package with a note instead of gating
- Two lowering ICE classes fixed; untyped packages stay flag-invariant
- 2465-2468 byte-match Node fully static: the esbuild __export table, the __reExport star, the tsc __exportStar barrel, and the defineProperty getter family
- 2469 pins consumer-anchored degradation: a type-only surface name drops exactly the named package to the island with the site-count note
- auto opts a getter-table bundle in (the marker relaxation), and the untyped-package stub pin replaces the accidental inferred-surface bonus
- the island differential lane excludes the opt-in-only cases by design
- ci.yml runs test (plain|san, 1..3/3) on macos-15; an aggregate job keeps the old "test" check name for anything pinned to it
- each job runs vitest twice: --shard=i/3 over everything but the corpus lanes, then the four corpus lanes with only their case slice — a file lands in exactly one --shard slice, so mixing the axes would silently drop cases
- tests/harness/shard.ts: SCRIPTC_TEST_SHARD="i/n" slices case lists by sha1(name) mod n — stable across corpus growth, every case in exactly one shard, unset means everything
- differential, llvm-differential, npm, and server harnesses slice through it; the llvm tier-floor assertion checks only this shard's floor programs
- shard.test.ts pins the partition contract (union exact, disjoint, key-stable, env-driven default) and stays green with the job-wide env set
- Node-on-macOS backs fs.watch with an FSEvents stream that starts asynchronously, so both fixtures' single delayed touch could slip into the startup window and vanish, the persistent watcher holding Node's loop until the 300s hang detector fired
- 1751 rewrites the target on a 50ms interval until the first delivery closes everything; the options-record pins (three-arg form with undocumented keys, options-only form, readline crlfDelay) and the exact stdout bytes are unchanged
- 1564 gets the same treatment in both phases: interval appends for the change phase, name flipped out of and back into existence for the rename phase
- a 600-kick bound turns a genuinely dead watcher into a loud nonzero exit instead of a silent hang
- the compiled side never raced (kqueue/inotify register synchronously at the fs.watch call), so only the Node oracle behavior changes
- scriptc build --lib --profile emits ccc wrappers, init/sink/reset/collect entries, and a static archive
- async_free is structural: the async and event-loop units never link, symbol-audit proven
- Every runtime trap routes through one funnel; the sink contract covers both emissions
- The K-fixture conformance matrix runs a real C host against both backends
- 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
- 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)
- 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
- 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
- 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