Testing
tests/runtime.spec.tsrejects absent, non-executable, non-CPython, pre-3.10, and unresponsive interpreter configurations at load; changesPATHafter activation to prove the resolved executable is frozen; removes that executable after activation to preserve the lateworker-exitpath; and asserts a running program seesTMPDIRbut notPATH,HOME, orDEEPSEEK_API_KEY. The native-output case pins each source stream's order without requiring a total order across independent channels, and the Darwin resource-limit cases state or skip the platform-specificRLIMIT_ASbehavior.snapshots/session/ptc-python-turnreplaces the headless PTC worker provider with the private Python provider through the real Loader, replays a Pythonrun_codeprogram over real bash bindings, and pins the Python SDK prompt, tool schema, dispatch events, captured log, and completion value.tests/boot-write-failure.spec.tsmocksspawnso the fd-3 pipe throws on the boot write — the one path a real subprocess cannot be coerced into — and assertsrun()resolves aworker-exitrather than rejecting. A sibling case makes the mockedspawnthrow SYNCHRONOUSLY and assertsrun()still resolves aworker-exitand removes its staging directory, keyed off the exact bootstrap path the mockedspawnreceived in its argv so a sibling worker's concurrent staging cannot flake it. Both are isolated in this spec so the real-subprocess suite is untouched.tests/residual-detach.spec.tsunit-testsdetachResidual: the carried copy equals the residual, owns a backing store sized to its own length (fixture kept above Node's Buffer pool threshold), and does not share the source frame'sArrayBuffer.tests/runtime.spec.ts— the output-cap case asserts theparse-cap - envelopebound (67108800) and its message. A daemon-thread case drives four threads emitting unterminated writes through settlement's flush. A native-write case writes 200 KiB with no newline viaos.writeunder a raisedmaxLogBytesand asserts it reads back as EXACTLY one log entry (proving stray output is aggregated by line, not split at pipe-chunk boundaries); a companion writesb"one\ntwo\nthree"and asserts three entries (proving real newlines still delimit). A newline-free-flood case writes 2 MiB under a 4 KiBmaxLogBytesand asserts the capture ends at the truncation marker and stays under budget (proving the residual is bounded by the ledger, not buffered whole); a NUL-flood companion writes 4000 newline-free NULs under the same budget and asserts truncation (proving the residual is charged by SERIALIZED cost, ~6× raw, measured without allocating the escaped copy); an illegal-UTF-8 case paces single-byte\xffwrites under a 3072-byte budget withBuffer.concatwrapped to measure the peak merged buffer, asserting it stays under 2048 (charged at the U+FFFD width 3 the residual flushes near 1024 raw bytes; a raw-byte undercount would let it reach ~3072, so the bound discriminates); a CESU-8/overlong case paces the structurally-well-formed but illegalED A0 80one byte at a time and asserts the same peak bound (charged at the true 9 per sequence it flushes early; charging the structural width 3 triples the peak, so reverting the per-lead range check turns it red); a broken-multibyte case writes a 3-byte lead then a fresh ASCII byte in separate chunks and asserts both a capturedAand a U+FFFD (exercisingaccrueStrayCost's cross-chunk broken-sequence branch); a post-truncation case writes a 108-byte payload (under the smallest PIPE_BUF, so one atomic write) whose first line exhausts a 64-byte budget and asserts the second line is dropped (exercising the post-truncation admit no-op in onedatacallback, no v8-ignore); a short-escape case writes a line mixing a tab, quote, backslash, a\uXXXXcontrol, a multibyte character, and ASCII, asserting it round-trips verbatim (exercising every branch ofjsonStringCostUpTo); a reassembly case writes a payload spanning every valid multibyte lead class (E0-range, plain 3-byte, F0, and F4) past the pipe buffer and asserts it round-trips with no U+FFFD (exercisingaccrueStrayCost's per-lead ranges and cross-chunk reassembly); a lone-surrogate case forges an fd-3logframe flooding 1000\ud800escapes under a 4 KiB budget and asserts truncation (the count sits in the window where charging 3 bytes would admit and 6 bytes truncates, proving the surrogate is charged its full escaped width); a stray-sealing case paces 60000 single-byte newline-freeos.write(1, …)calls under a raised budget withBuffer.concatwrapped to measure copy volume, asserting the trickle coalesces to one entry and the cumulative copy stays under a measured 256 KiB threshold (the sealed shape copies ~120 KB, the re-merge shape ~538 KB, so reverting the seal to a re-merge turns the assertion red — proving the fragment list seals into blocks pastMAX_PENDING_CHUNKS). A closeDeadline-flush case has the leader write a newline-free diagnostic then spawn asetsidorphan holding the pipes open, and asserts the diagnostic survives inlogs(proving the residual is flushed before the deadline destroys the streams). The same-group reap case spawns a SIGTERM-ignoring same-group descendant that releases the pipes and bumps a heartbeat file; the test asserts the heartbeat STOPS after the grace-window SIGKILL — an assertion robust whether the killed descendant is reaped or lingers as a zombie, so it holds where PID 1 does not wait() orphans. A dispose-after-resolve case assertsdispose()of a completed run with a same-group survivor returns only after the survivor stops executing (proving the run stays inliveuntil its group is reaped), with anexpect(afterDispose).toBeGreaterThan(0)guard so the frozen-heartbeat assertion cannot pass vacuously when the file was never written. A deadline case busy-blocks the event loop past both timers and asserts the survivor's heartbeat freezes (proving the poll's deadline arm sends SIGKILL itself rather than cancelling the unfired escalation). The cross-loop case runs a binding from a worker thread's ownasyncio.runloop while the main coroutine yields withawait asyncio.sleep, asserting the reply round-trips instead of timing out; a companion case abandons a thread's call so its loop closes, then answers it before a later binding — asserting the pump survives the closed-loopcall_soon_threadsafe(host-gated ordering makes it deterministic, fail-before hangs the later binding to the wall clock). The inherited-soft-limit case runs the interpreter through aulimit -S -twrapper that sets a CPU soft limit belowcpuSecondsand asserts the appliedRLIMIT_CPUsoft is the inherited value, not the configured one (CPU rather than address space, since macOS ignoresulimit -v); a companion inherits a 1 s CPU soft, has the program trap SIGXCPU and busy-loop past it, and asserts the settlement recheck reports a timeout — proving the recheck uses the effective soft, not the configuredcpuSeconds. A control-heavy-diagnostic case raises a NUL-flood exception under a smallmaxValueBytesand asserts the serialized frame fits (proving the diagnostic is metered by serialized cost). A tail-copy case (maxLogBytes: 256,addressSpaceMb: 384) has the program build a tail in a variable and write"\n" + tailwheretailis 150 MiB — construction peaks at ~2× (~300 MiB, within the address space, so the model's own allocation succeeds and any OOM belongs to the defect path), and the pre-fix whole-tail re-buffer added a third ~150 MiB copy past 384 MiB; the sliced prefix lets the run truncate and complete (Linux-only RLIMIT_AS repro, macOS happy path — the fixture's own construction must fit the address space, a general rule for these RLIMIT_AS cases). An output-budget/address-space case asserts amaxLogBytesof 50 MB AND amaxValueBytesof 50 MB each reject at load against a 256 MiBaddressSpaceMb(past the room left after the interpreter baseline when multiplied by the worst-case 12) while the default caps against 512 MiB load, gating both budgets symmetrically; a discriminating case asserts a 48 MiBmaxLogBytesagainst a 512 MiBaddressSpaceMbrejects — 48×8 = 384 MiB fits the 448 MiB budgetable (the old 8× multiple wrongly admitted it) but 48×12 = 576 MiB does not. The ~12× peak the multiple covers is the NEWLINE path's single near-budget write — the caller's own string, the line slice, and the encode copy live at once; the settlement flush is no longer the binding case, becauseflush_linedrops the pending chunks before its push and so holds two copies rather than three. An inherited-RLIMIT_AS case runs the interpreter through aulimit -v 131072wrapper with a 32 MiBmaxLogBytesthe configured 512 MiBaddressSpaceMbadmits, and asserts the boot re-check rejects it as anexceptionwhose message names the inherited RLIMIT_AS (the 128 MiB inherited limit leaves too little after the baseline; Linux-only, macOS ignoresulimit -vand the run proceeds). A non-integer-budget case asserts a fractionalmaxLogBytes/maxValueBytesrejects at load. A combined-peak case (maxLogBytes: 32 MiB,maxValueBytes: 32 MiB,addressSpaceMb: 512— each budget admitted alone at 12×) writes ~33M newline-free astral characters (buffered, unflushed) then returns ~33M astral characters, and asserts the run settles asoutput-limit(the value is itself over its 32 MiB budget); pre-fix the unflushed log pending plus the value's build-and-encode peak added past the 512 MiB address space and OOM'd, so flushing the logs before framing the value is what lets the value check complete (Linux-only RLIMIT_AS repro; on macOS the over-budget value reports output-limit under both orders). A wide-value case (maxValueBytes: 20 MiB,addressSpaceMb: 384) returns[0] * 6_000_000— ~12 MB of JSON, under the 20 MiB budget, so it must round-trip; pre-fix the O(width) walk allocated ~400 MB of per-element traversal tuples and encoder stack entries (~28× the serialized size, past the 12× the gate reserves) and OOM'd on a value the meter admitted, while the O(depth) cursor keeps the only width-proportional allocation the output string itself (Linux-only RLIMIT_AS repro; the fixture stays within the address space so it is honest on macOS too). A wide-BINDING-ARGUMENT case (addressSpaceMb: 384) calls a binding with[0] * 6_000_000and asserts the length echoes back:_lossless_json_violationruns on model-built arguments that no child-side budget bounds first, and its per-member tuples measured 459.1 MiB against 0.0 MiB for the cursor. A backtracking case returns a 4 MiB string from a binding and asserts it round-trips: the old scalar regex retained engine state proportional to the string's width (146 MiB at 1 MiB, 557.8 MiB at 4 MiB, past the default 512 MiB), which raised MemoryError inside_pump_repliesand stranded the call to the wall clock. A control-heavy metering case returns 8M NULs under a 16 MiBmaxValueBytesand assertsoutput-limit, notexception: charging by counting instead of materializing the escaped form measured 19.1 MiB against 228.9 MiB for an identical byte count. An addressSpaceMb-baseline case asserts 64 MiB and 32 MiB reject at load with a message namingaddressSpaceMb, rather than the budget loop's negative admissible limit. A process-identity case asserts the leader's start time reads stably on Linux and reports undefined on Darwin, the guard that keeps a recycled pgid from receiving this run's SIGTERM. A paced-replies case resolves eight 4 MiB values in oneasyncio.gatherround and asserts the frames round-trip; the peak the fix removes (32.0 MiB buffered → 0.0 MiB) lives in the host's fd-3 writable buffer, invisible through the seam, so this case pins the round-trip and the no-regression match but is measured for its peak only out-of-tree. A late-drop case settles the run onmaxWallMsand resolves the pending binding afterwards, asserting atimeoutresult, an undefined value, and that the late path actually ran — the three assertions all hold pre-fix becausesendReplyalready dropped after-settlement values, just later, so the case pins the ordering, not a seam-observable behavior. A binding-all-names case (rebinds every name the failure path uses) asserts a realValueErrorsurvives send-done binding — a tested fix pinned by a case that rebinds__main__.ProtocolChannel.send_sync,__main__.ProtocolChannel.write_encoded, and__main__._encode_json_plain— the three names the shippedsend_donewould resolve late if it looked them up at call time — and pins thedoneframe against that call-time look-up skipping it; the done-value TOCTOU pre-encoding, the stray-UTF-8 budget-flush retention, and the late-rejection settled guard are counted among the ten no-fail-before fixes (reasons in the Problem section), not pinned by a fail-before test. A fragment-cap drip case writes 200 000 single-character newline-freesys.stdout.writecalls and asserts the run completes with a truncation marker rather than a MemoryError (no-fail-before: the 25 M-scale OOM is not deterministically constructible in CI). A dual-limit CPU case runs the interpreter through aulimit -t 2wrapper and busy-loops past it, asserting atimeout(the soft limit is lowered to 1 so SIGXCPU fires, not aworker-exit). A transitive-name rebind case rebinds__main__._dump_scalar,__main__.os,__main__._os_write,__main__._memoryview, and__main__._FALLBACK_DONE_FRAMEand asserts a done frame still lands as anexception, not aworker-exit(the real message is replaced by the fixed fallback literal). A BaseException-rebind case rebinds__main__.BaseExceptiontoRuntimeErrorand raisesValueError, asserting the run still reports anexception, not aworker-exit(the catch uses a pre-program local exception class). A RuntimeError-rebind closed-loop case rebinds__main__.RuntimeErrortoValueErroras the first program statement and drives the closed-loop worker pattern, asserting the pump survives the dead-loop reply and delivers the later binding (the pump's_RuntimeErroris a def-time default argument, so it captures the original before the rebind). A_done_with_value-rebind case rebinds__main__._done_with_valueto a raising function and returns a legitimate value, asserting the run still reports the success (the entry name is a_runlocal bound before the program runs). Asys.__stdout__-flush case writes throughsys.__stdout__/sys.__stderr__without an explicit flush and asserts both bytes appear inlogs(the-uunbuffered child plus the settlement drain of the original std streams). The host closes the child's stdin write handle immediately after spawn (the program is an async body that reads nothing from fd 0; a live pipe would hold a host-side handle open past the run, letting a setsid-escaped descendant inheriting fd 0 keep the host process alive). The channel's frame readers bind their decode primitives (_decode_json_plain,os.read,_READ_CHUNK_BYTES,bytes, andlen;asyncio.get_event_loopon the async reader) as def-time default arguments, so a__main__rebind cannot kill the reply pump;_decode_json_plainitself capturesjson.loads/the two regexes/len/isinstance/str/listthe same way. The reply pump's frame reader is a BOUND METHOD captured by_runbefore the program runs and passed into_pump_repliesas an explicit argument (a body-localchannel.read_frame_asynclookup would resolve a rebound class attribute, since the pump starts after the program's top-level statements).send_done's frame-shape check uses_run's bound_str/_isinstance(a program rebinding__main__.isinstancecannot make a legitimate success fall into the fixed-literal fallback)._make_error_classcapturesExceptionandsetattras def-time defaults, and dispatch binds_lossless_json_violation/asyncio.get_event_loop/the channel's send and write primitives into_runlocals (the frame WRITE goes through def-time boundwrite_encoded+_encode_json_plainrather thansend_sync's call-time body, and the log sink directly through the bound encode+write primitives, not send_sync) — a rebind of those names before the first binding call cannot break a legitimate call.compile(wrapped, ..., dont_inherit=True)stops the module'sfrom __future__ import annotationsfrom stringifying the program's type annotations. A basenamepythonBinthat does not resolve on the CURRENT process PATH now fails at LOAD ('does not resolve on PATH', like the empty/NUL checks): the child spawns withenv: \{\}, so falling back to the bare name would let execvp silently start a system interpreter from the platform default PATH — a product-visible change from the old run-time ENOENT worker-exit to an early, loud configuration error. The bootstrap resets SIGXCPU toSIG_DFLand unblocks it before any model code runs: the child inherits the host's disposition and mask, and a host that ignores or blocks SIGXCPU would let a program run past the softRLIMIT_CPUuntil the hard limit's SIGKILL — classifying a definite overrun asworker-exitinstead oftimeout. (The settle-time enforcer already restoresSIG_DFLfor a program that traps or masks the signal mid-run; this closes the inherited-state gap.) The float encoder'sDecimal(repr(value)).normalize()runs on a fixed module-level_FLOAT_CONTEXT = Context(prec=28)(constructed before any model code): the process-global decimal context would otherwise let a legitimate program'sgetcontext().prec = 2silently round the completion value's digits ortraps[Inexact] = Truemake the encode raise, misclassifying a successful run as an exception. A regression case mutates both knobs and asserts a float completion round-trips exactly. The host caps an fd-3 frame's RAW length at 64 MiB (FRAME_PARSE_CAP_BYTES) beforetoString/JSON.parse: the 256 MiB wire ceiling bounds the bytes, not the decoded structure, and a compact wide frame near it could decode to far more host memory.maxLogBytes/maxValueBytesare load-bounded to that parser cap so an honest child's frames always fit; a model-constructed binding argument above it is dropped (registered in the README). A frame-cap case writes 65 MiB ofAs plus a newline and asserts aworker-exitwith the protocol-frame-exceeded message (the pre-join counter rejects a newline-free single frame; the first-frame check rejects a newline-bearing one BEFORE the join, keeping the peak at one copy of the wire bytes — verified fail-before by reverting to the unconditional counter). A_decode_json_plain-rebind case asserts a binding reply still round-trips; a stdin-EOF case has the program read fd 0 and asserts it sees EOF immediately (the destroyed write handle), verified fail-before by disabling the destroy. A frame-cap case writes 65 MiB ofAs plus a newline and asserts aworker-exitwith the protocol-frame-exceeded message (the pre-join counter rejects a newline-free single frame; the first-frame check rejects a newline-bearing one BEFORE the join, keeping the peak at one copy of the wire bytes — verified fail-before by reverting to the unconditional counter). A multi-frame case lets two within-cap frames whose combined buffer crosses the cap both survive (the first-frame check, not the byte counter, decides), and a sealing-threshold case writes 64 MiB of 4 KiB atomic newline-free writes plus 12289 more bytes before the first newline, asserting the run is a worker-exit (sealing is the ELSE half of the newline branch, so the newline-bearing chunk always reaches the first-frame check). A pythonBin case resolves a basename against a PATH whose first entry is relative ('.') and asserts the absolute entry is used. An exact-limit case (maxLogBytes: 64) writes a 60-character line (62-byte JSON + 1 separator = 63 = the reserved ledger) and a 61-character line (64 > 63), asserting the first is admitted and the second truncates to the marker — the outer-array envelope reservation, pinned at the exact boundary; a companion case assertsmaxLogBytes: 61rejects at construction. A syntax-label case asserts a parse-time syntax error carriesFile "<model>"(ast.parse passes the same source label as compile and the runtime traceback filter). A SIGXCPU-mask case masks SIGXCPU (pthread_sigmask), burns past the soft limit, and returns, asserting atimeout(the recheck unblocks before re-raising); a trap+mask companion installs a custom handler that re-masks and asserts the sametimeout(SIG_DFL is restored before the unblock, so the pending signal kills inside the kernel).