Adversarial verification verdicts
Produced by a multi-agent research session (Claude Code). All local numbers were measured on the session container — Node v22.22.2 / V8 12.4, 4-vCPU Xeon 2.80 GHz, 16 GB RAM; absolute MB/s are machine-specific, ratios are the durable signal. Referenced
scratchpad/*.mjsscripts were session throwaways and are not committed.
Each design listed up to 5 load-bearing assumptions; 12 (of 15, capped) were handed to independent adversarial verifier agents instructed to REFUTE them — by reading the installed sources, fetching primary sources, and running real Node/wasm experiments on this machine. Result: 9 CONFIRMED, 3 REFUTED, 0 UNCERTAIN. The three refutations (V8 scan-substrate conjunction, the “JSON-class RSS via allocation elimination” model, and rapidyaml’s 150 MB/s premise) are incorporated into the dossier summary.
[CONFIRMED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)
Section titled “[CONFIRMED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)”CLAIM: The benchmark remains JSON-bytes/ASCII fixtures (bench/fixtures/datasets.ts), so the flow-collection fast path dominates the committed numbers; block-YAML estimates are extrapolated, not measured, and datasets may later grow block-style cases.
EVIDENCE: All parts verified against source and by inspecting the actual generated fixture bytes; refutation attempts failed. (1) JSON-bytes: /home/user/lightning-yaml/bench/fixtures/datasets.ts:1-8 states every fixture is plain JSON fed as identical bytes to JSON.parse and both YAML parsers; the 6 defined datasets (lines 26-33) are all records/nested shapes serialized via JSON.stringify (bench/fixtures/generate.ts:82-83). Both harnesses load only these .json fixtures (bench/speed/parse.bench.ts:16-17, bench/memory/worker.ts:31); no .yaml/.yml fixture exists anywhere in the repo. (2) ASCII: ran grep -P '[^\x00-\x7F]' over all 6 generated files in bench/fixtures/data/ — zero non-ASCII bytes; zero backslash escapes in the 10.7MB xlarge-records.json. (Latent caveat: bench/util/prng.ts:14-15 defines a UNICODE array [“é”,“ñ”,…,“🚀”] used by chars() in the currently-UNUSED “strings” shape — if a strings dataset is added, ASCII-only stops holding, which is exactly the claim’s “datasets may later grow” hedge.) (3) Flow-path dominance: JSON is 100% flow-style YAML, so every byte of the corpus exercises flow collections + quoted scalars only; no block constructs exist in any fixture, so any numbers produced from these fixtures are necessarily flow-path-dominated. Nuance: as of now BOTH README result blocks are unpopulated placeholders (README.md:111-121: “Not generated yet” / “No lightning-yaml implementation exists yet”), so “committed numbers” is prospective — but that makes part (4) trivially true. (4) Block-YAML unmeasured: no harness path parses block YAML; README.md:143-146 explicitly concedes “Input is flow-style JSON… A block-YAML variant (via yaml.stringify) could be added later for an apples-to-YAML view” — confirming both that block performance is not measured today and that block-style cases are an anticipated future addition. No counter-evidence found.
[CONFIRMED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)
Section titled “[CONFIRMED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)”CLAIM: minijson’s ~57-60%-of-native throughput transfers to a YAML flow parser with no more than 10-25% generality tax, with YAML’s extra checks kept to predicted-not-taken compares and zero hot-path allocations.
EVIDENCE: Built and ran an empirical head-to-head at /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/taxtest.mjs on the repo’s real fixtures (/home/user/lightning-yaml/bench/fixtures/data/*.json, 0.11-10.7 MB, Node v22.22.2): (1) a minimal charCodeAt-dispatch JSON parser (“minijson”: no-escape substring string fast path, inline int accumulation, Number(slice) only for floats) and (2) a YAML-1.2 flow-context superset (“yamlflow”) coded in the identical style, adding everything the design promises: comment skipping in the ws loop, single-quoted strings with ‘’ escapes, DQ line-folding via the existing slow-path branch, anchor/alias/tag dispatch as extra not-taken compares, ‘:’-lookahead and ’ #’ plain-scalar termination, trailing-space trim, and speculative single-pass core-schema resolution (null/true/false//int/float/0x/0o/.inf/.nan) with no re-scan. Correctness verified: both parsers reproduce JSON.parse output byte-identically (JSON.stringify equality) on medium-records, plus YAML-specific smoke tests (plain scalars, comments, sq-escapes, hex) pass. Results over two runs — generality tax (1 - yamlflow/minijson MB/s): medium-records 8.9%/8.7%, medium-nested 15.5%/15.9%, large-nested 21.4%/19.0%, xlarge-records 9.7%/11.0% — every case inside the claimed ~10-25% band. yamlflow absolute: 61-81 MB/s = 42-56% of native JSON.parse (129-178 MB/s on this container) and 3.0-3.6x js-yaml@4.1.0 (20-24 MB/s) on the same fixtures, i.e. the claimed 3.9x-js-yaml headroom survives the tax with margin (js-yaml is only ~14-17% of native). minijson itself hit 46-66% of native across fixtures, bracketing the design’s 57-60% premise (absolute MB/s differs from the doc’s 98-104 — hardware-dependent, but the ratio structure reproduces). Zero-hot-path-allocation is demonstrated feasible: yamlflow allocates only result values; the sole non-result allocation (Number(slice) for floats) exists identically in minijson so it cannot widen the tax. Caveats that keep this from being a rubber stamp: (a) the tax is data-dependent — nested/literal-heavy data (many true/false/null values forced through the plain-scalar scan+resolve path instead of JSON’s 4-char literal check) lands at 15-21%, the upper half of the claimed band, so the “~10%” end is only realistic for record-style data; (b) my yamlflow is flow-context-only (the thing the claim covers) — block-context dispatch, full error reporting, and multi-line plain folding are untested here and are where additional tax could hide in the full parser.
[REFUTED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)
Section titled “[REFUTED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)”CLAIM: V8 behaviors measured on Node 22.22.2 hold across Node >=20 and near-future V8: SlicedString/ConsString kMinLength=13 with O(1) slice, ~5 GB/s indexOf, flat-string charCodeAt speed, hidden-class transition sharing for same-order keys, and no advantage for Uint8Array scanning.
EVIDENCE: Ran identical experiments on Node 20.20.2 (V8 11.3) and Node 22.22.2 (V8 12.4), both installed at /opt/node20 and /opt/node22; scripts in /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/{sliced,scan,scan2,maps,optstatus}.js. Four of five sub-claims CONFIRMED, one REFUTED — and the conjunction therefore fails. (1) kMinLength=13 + O(1) slice: CONFIRMED. Retained-memory probe (100 x 1MB parents, keep only slice): len<=12 retains 1.1 MB, len>=13 retains 104.9 MB — identical boundary on Node 20 and 22; 1e6 slices of 1e6 chars from a 128M-char string took 66-71 ms (~70 ns/slice, clearly O(1)). Near-future V8: https://raw.githubusercontent.com/v8/v8/main/src/objects/string.h still has static const uint32_t kMinLength = 13; at lines 1078 (ConsString) and 1185 (SlicedString). (2) indexOf: qualitatively CONFIRMED and version-stable, but the number is machine-dependent, not “~5 GB/s”: measured 12.7-13.7 GB/s on THIS machine for single-char and 7-char absent needles, essentially identical on Node 20 and 22. Treat 5 GB/s as a floor, not a constant. (3) charCodeAt on flat one-byte string: stable across versions but only 0.31 GB/s (~3.2 ns/char) on BOTH Node 20 and 22, verified TurboFan-optimized via %GetOptimizationStatus=0b1010001 (TurboFanned bit set) after %OptimizeFunctionOnNextCall. (4) Hidden-class sharing: CONFIRMED on both versions via %HaveSameMap — true for object literals, dynamic same-order assignment, and computed-string keys (the parser-relevant case); false for different insertion order. (5) “No advantage for Uint8Array scanning”: REFUTED empirically. In verified TurboFan-optimized code, sequential Uint8Array/Buffer scans ran 0.92-1.36 GB/s vs charCodeAt 0.31 GB/s — a consistent 2.6-4.4x advantage for typed-array scanning, reproduced on int32-accumulator sum loops AND lexer-style compare/branch loops (0.54-0.65 vs 0.28-0.29 GB/s), on BOTH Node 20.20.2 and Node 22.22.2. I could not reproduce “no advantage” even on the same Node 22.22.2 the design cites. Caveats: the raw-scan advantage does not include string→bytes transcoding or per-token byte→string decoding costs, which may still make a string-based parser win end-to-end — but the assumption as stated (a raw V8 scanning behavior) is contradicted; also Node 23/24 (V8 13.x, Turboshaft string lowering) untested locally, so absolute charCodeAt/indexOf ratios there remain a residual risk even though the structural constants (kMinLength, map transitions) are unchanged on V8 main. Design impact: revise the “scan JS string via charCodeAt, ignore Uint8Array” rationale — either justify it via transcoding/decode overhead measurements on realistic parse workloads, or reconsider a byte-scanning fast path; and restate indexOf as “>=5 GB/s, hardware-dependent”.
[CONFIRMED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)
Section titled “[CONFIRMED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)”CLAIM: The competitive target is js-yaml 4.x as installed (4.3.0); js-yaml 5.x (June 2026 TypeScript rewrite) has not been benchmarked here and is assumed not to be dramatically faster than 4.x. EVIDENCE: All four sub-claims check out, and the load-bearing assumption (5.x not dramatically faster) survived an adversarial head-to-head measurement — 5.x is in fact mostly SLOWER and much heavier on memory. (1) Installed version: /home/user/lightning-yaml/node_modules/js-yaml/package.json reports 4.3.0, resolved from devDependency spec “js-yaml”: “^4.1.0” in /home/user/lightning-yaml/package.json — claim’s “(4.3.0)” is exact. (2) 5.x exists and matches the description: npm registry (https://registry.npmjs.org/js-yaml) dist-tags are latest=5.2.1, v4-legacy=4.3.0; 5.0.0 was published 2026-06-20 (“June 2026”); the 5.2.1 dist bundle (node_modules/js-yaml/dist/js-yaml.cjs.js in scratchpad install) contains “//#region src/tag.ts” markers and ships js-yaml.d.ts, confirming the TypeScript rewrite. (3) “Not benchmarked here”: only 4.3.0 is installed in the repo; no 5.x anywhere in /home/user/lightning-yaml/node_modules. (4) Empirical test: installed js-yaml@5.2.1 in scratchpad and ran identical load() benchmarks (warmup + median of N iters, separate Node processes per version) on the repo’s own fixtures (/home/user/lightning-yaml/bench/fixtures/data). Results, 4.3.0 vs 5.2.1 median: small-records 952B: 0.03ms vs 0.05ms (5.x ~65% slower); medium-records 106KB: 4.23ms vs 3.78ms (5.x ~11% faster — its only win); large-records 1.2MB: 48.7ms vs 62.3ms (5.x 28% slower); large-nested 1.25MB: 53.7ms vs 65.6ms, peak RSS 127MB vs 210MB (5.x 22% slower, +65% memory); xlarge-records 10.7MB: 464.8ms vs 667.1ms, peak RSS 343MB vs 895MB (5.x 44% slower, 2.6x peak RSS). Conclusion: on these JSON-subset workloads 5.2.1 is nowhere near “dramatically faster” — beating 4.3.0 implies beating 5.2.1 too. Caveats: fixtures are JSON bytes, so 5.x’s relative performance on idiomatic YAML (block scalars, anchors) was not tested; and since npm “latest” is now 5.2.1, the design doc could strengthen its framing by noting 4.3.0 is the npm v4-legacy tag while 5.2.1 is what fresh installs get — but that nuance does not weaken the assumption as stated.
[REFUTED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)
Section titled “[REFUTED] (lightning-yaml v1 design — a single-pass, allocation-minimal, pure-JS YAML parser engineered for V8)”CLAIM: Peak RSS in the memory harness is governed by allocation rate plus live output (as measured for all three competitors), so eliminating js-yaml’s per-node/per-pair allocation categories is sufficient to reach JSON-class RSS without engine-level control. EVIDENCE: Empirically refuted by direct experiment under the harness’s exact protocol (mirroring /home/user/lightning-yaml/bench/memory/worker.ts:36-53 — isolated node –expose-gc child, gc-settle, 25 iterations, process.resourceUsage().maxRSS). I wrote a best-case proxy for the design: a pure-JS recursive-descent JSON parser with ZERO per-node/per-pair intermediate allocations (no state/token/position objects, charCodeAt scanning, output-only allocation; /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/purejson.js), verified byte-identical to JSON.parse on all 6 fixtures. This strictly supersedes “eliminating js-yaml’s per-node/per-pair categories” (State ctor at node_modules/js-yaml/lib/loader.js:142, captureSegment:354, storeMappingPair:395, per-pair push :849 — js-yaml@4.3.0 actually installed, not 4.1.0). Results on xlarge-records.json (10.7MB), 25 iters: JSON.parse peak RSS 220.5MB / heapΔ 17.4MB; pureJS 357.6MB / 27.7MB (1.62x RSS); js-yaml 404.6MB / 37.3MB (1.83x). Eliminating ALL intermediate allocation closed only ~1/4 of the js-yaml→JSON RSS gap — nowhere near “JSON-class”. Decomposition falsifies the model itself: (a) with a full gc() after EVERY iteration (allocation-rate term forced to ~0), pureJS is still 177MB vs JSON 140.5MB (1.26x), so the residual is not allocation rate; (b) the “live output” term is NOT parser-independent — the identical value retains 27.7MB when built by pure JS vs 17.4MB via JSON.parse (1.59x), and JSON.parse(JSON.stringify(pureJSOutput)) collapses back to exactly 17.4MB, proving the +59% is construction-path overhead (V8’s C++ JSON parser allocates exact-fit arrays/objects/flat strings and internalized keys, whereas generic JS object construction via arr.push growth, dynamic property transitions, and slice-based strings over-allocates backing stores) — i.e., engine-level representation control that user JS cannot fully reach by eliminating allocation categories. Caveats: pureJS still makes transient Number(slice) strings for non-smi numbers (small, and the gcEach run bounds their effect); some retained overhead (e.g., trimming array backing stores, key interning discipline) is partially mitigable from JS, so the RSS gap can be narrowed below 1.6x — but the claim’s “sufficient to reach JSON-class RSS without engine-level control” is quantitatively false, and its two-term RSS model omits a construction-path-dependent live-output term worth ~1.6x on the flagship 10MB fixture.
[REFUTED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)
Section titled “[REFUTED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)”CLAIM: rapidyaml’s published ~150 MB/s native YAML parse rate survives Emscripten compilation within the 1.45-2.5x derate band (USENIX ATC’19, nickb.dev); if wasm ryml lands below ~45 MB/s on the fixtures, the margin over js-yaml (24-29 MB/s) collapses. EVIDENCE: Empirically measured NATIVE rapidyaml (v0.15.2 official manylinux wheel, compiled C++ via /usr/local/lib/python3.11/dist-packages/ryml/_ryml.so + libryml.so — SWIG binding, per-call overhead negligible at MB sizes) on this repo’s actual fixtures (/home/user/lightning-yaml/bench/fixtures/data/, all flow-style JSON per bench/fixtures/datasets.ts:5-8), scripts at /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/{bench_ryml.py,bench-jsyaml.mjs}. Results: (1) The “~150 MB/s native” premise fails on the fixtures that matter: ryml parse_in_arena = 144-181 MB/s on medium-records (0.11 MB) but only 75.6 MB/s on large-records (1.2 MB), 103 MB/s on large-nested (1.25 MB), and 45.3-47.9 MB/s (6 stable iterations) on xlarge-records (10.73 MB) — native ryml is ALREADY at the claim’s ~45 MB/s collapse threshold on the 10 MB fixture BEFORE any wasm derate. Applying the claim’s own band (1.45x optimistic / 2.5x pessimistic) to measured native rates: xlarge → 18.6-32.1 MB/s wasm, i.e. at or BELOW js-yaml (measured 22.9-23.7 MB/s on the same machine/fixtures, matching the brief’s 24-29 MB/s band); large-records → 30-52 MB/s, marginal. (2) Machine calibration is fair: js-yaml and JSON.parse (137-170 MB/s) measured on the same box match the brief’s own baseline numbers, so the ryml numbers are directly comparable — the 150 MB/s figure comes from rapidyaml’s README benchmarks on different data (appveyor.yml/travis.yml block YAML at 101-176 MB/s; their JSON bench at 430-453 MB/s, github.com/biojppm/rapidyaml README) and does not transfer to these record-heavy, node-dense 1-10 MB JSON fixtures, where per-node tree-building and arena growth dominate (throughput drops 3-4x from 0.1 MB to 10 MB input). (3) Unbudgeted pipeline costs make it worse: Design B’s end-to-end path adds string copy-in, in-WASM YAML→JSON emit, copy-out, and native JSON.parse, which itself runs at only ~144 MB/s on xlarge here — even a hypothetically free wasm parse plus JSON.parse caps the pipeline, and a 30 MB/s wasm stage composes to ~1/(1/30+1/144) ≈ 25 MB/s ≈ js-yaml parity on xlarge. Caveats: the ATC’19 1.45-2.5x band itself is consistent with the paper (Jangda et al., “Not So Fast”, mean 1.45-1.55x, peak 2.08-2.5x) and was not the weak link; a hand-tuned emscripten build with Tree::reserve() could beat the Python-wheel proxy somewhat, and wasm derates on modern V8 can be under 1.45x for some workloads — but even a 1.0x (zero) derate leaves xlarge at ~47 MB/s parse-only, barely 2x js-yaml before transcode+JSON.parse costs, far from the design’s intent. The assumption as stated — that the 150 MB/s figure applies to these fixtures and survives the derate above 45 MB/s — is contradicted on the >=1 MB fixtures, which dominate benchmark weight.
[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)
Section titled “[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)”CLAIM: The in-wasm JSON emitter runs at >=150 MB/s derated (~30-60 ms/10 MB) using scalar-verbatim byte copies; if escaping/typing pushes emit toward parse-cost levels, the 10 MB total drifts past 350 ms and the win thins to <1.3x. EVIDENCE: Empirically tested with a real in-WASM benchmark, not just citation. (1) Built a faithful emit-stage simulation in C (scratchpad/emit.c): per-node dispatch over a record table, per-byte escape-table scan + chunked memcpy for string scalars, YAML core-schema type resolution (null/bool/number single-pass check) for plain scalars, single-byte structural tokens — compiled with clang 18.1.3 –target=wasm32 -O3 -mbulk-memory and run in Node v22.22.2 (V8 WASM). Workload = the repo’s real 10.23 MiB fixture /home/user/lightning-yaml/bench/fixtures/data/xlarge-records.json tokenized to 2,549,158 records (837,623 string scalars, 270,270 plain scalars, 1,441,265 tokens; scalar bytes = 71% of input); emitted output byte-identical length and verified valid via JSON.parse round-trip. Result: in-WASM emit best 25.46 ms = 402 MiB/s input-relative — 2.7x ABOVE the claimed 150 MB/s floor and faster than the claimed 30-60 ms/10 MB window. Native build of identical code: 16.11 ms = 635 MiB/s, giving an observed WASM derate of 1.58x (consistent with published ~1.45-1.55x V8 overhead findings). Escaping+typing cost did NOT push emit toward parse-cost levels: 402 MiB/s emit vs js-yaml parse at 23 MiB/s, and far above any plausible WASM YAML-parse speed, so emit is a minor pipeline term. (2) Structural fidelity confirmed against rapidyaml’s actual emitter: src/c4/yml/emit.def.hpp line 1021 (_write_scalar_json_dquo, fetched from https://cdn.jsdelivr.net/gh/biojppm/rapidyaml@v0.7.2/src/c4/yml/emit.def.hpp) uses the same deferred clean-run chunk-write pattern (pos tracking, _do_write(s.range(pos,i)) only at escape chars, tail write) — i.e., scalar-verbatim byte copies is what rapidyaml actually does for JSON emit. (3) The claim’s downside arithmetic is internally consistent with measured baselines on this machine (scratchpad/baseline.mjs): js-yaml@4.1.0 load = 436.7 ms best, JSON.parse = 78.6 ms on the 10.23 MiB fixture; 437/350 = 1.25 < 1.3x, matching the brief’s stated failure threshold. Caveats: simulation walks a flat record array rather than rapidyaml’s node arena (~112 B/node index-chasing would add some traversal cost), and excludes output-buffer growth checks; but the 2.7x headroom over the 150 MB/s floor absorbs even a 2x pessimism factor (~200 MiB/s). The emit-throughput assumption survives adversarial testing; the real pipeline risk lies in the WASM parse stage and the WASM->JS string transfer, neither of which this claim covers.
[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)
Section titled “[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)”CLAIM: V8 promptly collects dropped WebAssembly.Memory objects under the throwaway-instance policy, keeping <=2 live ~100 MB linear memories during the 25-iteration harness; lazy collection would push peak RSS above js-yaml’s 495 MB and fail the memory goal. EVIDENCE: Ran real Node experiments (node v22.22.2, Linux, 16 GB RAM) simulating the design’s exact per-iteration flow: instantiate a wasm module exporting a 1600-page (~104.9 MB) memory, touch every page, drop the instance, 25 iterations, no gc() inside the loop — matching the harness, which calls gc() only before/after the loop (/home/user/lightning-yaml/bench/memory/worker.ts:36-44; ITERS=25 at bench/memory/run.ts:29; js-yaml 495 MB at README.md:41). Scripts at /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/{wasm-mem-test.mjs,wasm-mem-jsonparse.mjs,wasm-mem-realistic.mjs}. RESULT, faithful workload (per iteration: fresh ~100 MB instance + JSON.parse of a resident ~10 MB JSON string, i.e. the design’s transcode+native-parse step): peak live wasm external memory = 201.6 MB = exactly 2 memories, peak maxRSS = 350.1-350.8 MB across 3 runs (also 1 live memory / 455.7 MB in a heavier object-churn variant) — all comfortably under 495 MB. The <=2-live-memories bound held reproducibly. The claim’s counterfactual half is also empirically true: with wasm-only churn and no JS-side allocation per iteration, V8 IS lazy — external memory oscillated 401-601 MB (4-6 live 100 MB memories, first collection only after 5 accumulated) and peak maxRSS = 552.5-552.7 MB > 495 MB, reproducible with and without –expose-gc. IMPORTANT CAVEAT for the design (mechanism mis-attribution, not a refutation of the numbers): the promptness is NOT a property of dropping the instance/Memory per se. V8’s external-memory accounting alone only starts incremental marking, which stalls without allocation; the <=2 bound is delivered by the per-iteration JS allocation pressure from the JSON.parse step driving major GCs to completion. Any variant that creates ~100 MB throwaway memories WITHOUT materializing JS objects each iteration (e.g. a warmup loop, a bytes-in/bytes-out mode, or reading results via views) measured 6 live memories and 552 MB peak — above the 495 MB goal. The design should either keep the JSON.parse-per-iteration coupling, reuse one instance/memory, or explicitly detach (buffer.transfer()) rather than rely on ‘throwaway-instance’ collection promptness in general.
[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)
Section titled “[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)”CLAIM: ryml + transcoder compile to <=~1 MB of wasm with -Oz/no-exceptions and its WIP emscripten port needs no deep upstream fixes; a multi-MB module or broken port sinks packaging (base64-inline) and cold-start economics.
EVIDENCE: Empirically built and ran it. Cloned rapidyaml master (db5747a, 2026-07-04, https://github.com/biojppm/rapidyaml); c4core is vendored in-tree at ext/c4core.src (no submodule friction). Wrote a ~30-line YAML->JSON transcoder (parse_in_place + Tree::resolve() + emit_json; sources at /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/rapidyaml/transcode.cpp) and compiled the FULL library (all 10 src/c4/yml/*.cpp + 7 c4core .cpp) with em++ -Oz -fno-exceptions -fno-rtti using apt’s emcc 3.1.6 (Jan-2022 vintage, clang-15) — zero upstream source patches, zero compile errors on first attempt. Sizes: ryml.wasm = 200,198 bytes (~0.19 MB, 5x under the ~1 MB bound); gzip -9 = 69,608 bytes; base64 ≈ 267 KB chars; JS glue 15.3 KB. Runtime-verified on Node 22.22.2 via the exact base64-inline loading path (factory({wasmBinary})): YAML with flow/block collections, quoted scalars, and anchors/aliases transcoded to JSON that JSON.parse accepts (anchor ref correctly resolved to {“k”:“v”}); an 818 KB YAML doc -> 955 KB JSON + JSON.parse in ~119 ms first call. The claim even overstates the risk: upstream README calls the port done, not WIP — README.md lines 65 (“x64, x86, wasm (emscripten)… “ tested platforms), 82, and 492 (“A JavaScript+WebAssembly port is available, compiled through emscripten”), https://raw.githubusercontent.com/biojppm/rapidyaml/master/README.md. Two implementation caveats found (neither an upstream fix, neither size-related): (1) emit_json does NOT resolve anchors/aliases by default — the transcoder must call Tree::resolve() (in-library API, src/c4/yml/tree.hpp:1112), else aliases emit as literal “*x” strings; (2) old emscripten 3.1.6 Node glue tries fetch() on file paths under Node>=18 — irrelevant when passing wasmBinary directly (the planned base64-inline packaging), and fixed in current emscripten. Full YAML-spec edge behavior of the transcode (special floats, non-string keys) was not exercised; the size/port-health claim itself is solid with ~5x margin.
[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)
Section titled “[CONFIRMED] (lightning-yaml Design Brief B: WASM-wrapped rapidyaml with in-WASM YAML→JSON transcode + native JSON.parse)”CLAIM: The benchmark target remains js-yaml@4.x semantics/performance (repo pins ^4.1.0, installed 4.3.0); js-yaml 5.2.1’s June 2026 TS rewrite has not materially closed the 5.7-7.1x gap to JSON.parse that the 1.4-2.1x projected win is built on.
EVIDENCE: All four sub-claims checked, none refuted. (1) Pin: /home/user/lightning-yaml/package.json:23 has “js-yaml”: “^4.1.0”; the semver range can never resolve to 5.x, so the benchmarked target stays 4.x. (2) Installed version: node_modules/js-yaml/package.json reports 4.3.0 (the orchestrator context’s “4.1.0” was stale; the design doc’s 4.3.0 is correct — 4.3.0 published 2026-06-26 per registry.npmjs.org/js-yaml, and it is the current “v4-legacy” dist-tag). (3) TS rewrite exists as described: npm registry shows dist-tags latest=5.2.1 (published 2026-07-02), with the v5 rewrite landing 5.0.0 on 2026-06-20 (June 2026); the installed 5.2.1 dist bundle header contains “//#region src/tag.ts” and devDeps include typescript+rollup, confirming it is a TypeScript rewrite. (4) Empirical head-to-head (script at /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/jsy5/bench.cjs, run on this repo’s actual fixtures, median of N iters after warmup): gap to JSON.parse for v5.2.1 = 6.7x (medium-records 104KB), 5.4x (medium-nested), 7.4x (large-records 1.2MB), 5.9x (large-nested), 6.6x (xlarge-records 10.5MB) vs v4.3.0 = 6.9x, 6.1x, 7.5x, 5.5x, 5.8x. v5/v4 speed ratio ranged 0.89-1.13 (mean ~1.01) — v5 is at parity with v4, and actually 7-13% SLOWER on the two largest fixtures. The observed 5.4-7.5x gap band brackets the design doc’s cited 5.7-7.1x; the rewrite has not materially closed it, so the 1.4-2.1x projected-win math stands. Only nuance worth flagging to the doc author: npm install js-yaml fresh now yields 5.x (latest dist-tag), so competitor tables should eventually note v5 exists — but per this measurement that changes nothing quantitatively.
[CONFIRMED] (Design C — Pragmatic hybrid: JSON.parse delegation + tiered fast-path routing inside a single-pass pure-JS YAML parser)
Section titled “[CONFIRMED] (Design C — Pragmatic hybrid: JSON.parse delegation + tiered fast-path routing inside a single-pass pure-JS YAML parser)”CLAIM: Design C’s assumption: the benchmark must evolve as README.md:141-146 proposes (block-style fixture variants added, both styles reported, plus a delegation-off row for ours), because without this, Design C’s headline numbers on the current flow-JSON fixtures are indefensible as evidence of YAML-parsing speed.
EVIDENCE: Attempted refutation on three fronts; all failed except one minor attribution nuance. (1) Citation check: /home/user/lightning-yaml/README.md lines 141-146 are the “Caveats” section and do propose exactly the fixture evolution: “Input is flow-style JSON… A block-YAML variant (via yaml.stringify) could be added later for an apples-to-YAML view.” Nuance: the README proposes only the block-YAML fixture variant; the “delegation-off row for ours” is the design doc’s own addition (no parser exists yet — /home/user/lightning-yaml/bench/candidates.ts:50 shows group “ours” is still a commented-out stub), so that element is over-attributed to the README but is a coherent extension of it, not a contradiction. (2) Empirical test (ran /tmp/claude-0/-home-user-lightning-yaml/5b5afb90-7c63-5a56-af0b-8798d3e9b488/scratchpad/delegation-test.mjs on the real generated fixture bench/fixtures/data/medium-records.json, 106,002 bytes): a Design C-style delegate (try JSON.parse, catch -> js-yaml) measured 629.8 us/op vs raw JSON.parse 630.0 us/op — delegation overhead 1.000x, i.e. on the current fixtures 100% of the measured work is JSON.parse and 0% is any YAML code path; it beats js-yaml load (4738 us) by 7.5x and yaml parse (49702 us) by ~79x purely via delegation. So the headline “beats js-yaml” number on current fixtures literally measures JSON.parse, confirming it is not evidence of YAML-parsing speed. (3) The block-style variant materially changes the measurement: yaml.stringify of the same data (112,711 bytes, block style) makes JSON.parse delegation impossible (JSON.parse throws), and the competition itself slows down (js-yaml 7751 us = 1.64x its flow number; yaml 67561 us = 1.36x), so both the target and our parser’s true cost are unmeasured by flow-only fixtures. (4) Refutation angle “competitors also short-circuit JSON” fails: grep of node_modules/js-yaml/lib finds zero JSON.parse calls, and node_modules/yaml/dist’s only JSON.parse mentions are reviver-doc comments (applyReviver.js:4) — neither library delegates, so delegation-on flow-JSON numbers compare our JSON.parse call against their full YAML lexers. (5) Refutation angle “the existing caveat already discloses this” fails: README:143-146 frames identical bytes as the apples-to-apples guarantee for the competition; once a candidate branches on those exact bytes to a different engine, that guarantee inverts into the loophole, and only a delegation-off row restores a YAML-parsing measurement. Verdict: the assumption’s substance is confirmed empirically; only the parenthetical attribution slightly overstates what README.md:141-146 itself proposes (block variant: yes; delegation-off row: design doc’s own, necessary, addition).
[CONFIRMED] (Design C — Pragmatic hybrid: JSON.parse delegation + tiered fast-path routing inside a single-pass pure-JS YAML parser)
Section titled “[CONFIRMED] (Design C — Pragmatic hybrid: JSON.parse delegation + tiered fast-path routing inside a single-pass pure-JS YAML parser)”CLAIM: Last-wins duplicate-key default is acceptable to users and the yaml-test-suite (rapidyaml passes 100% of the suite while permitting duplicates; js-yaml itself offers json:true last-wins); fallback if market demands throw-by-default: disable Tier 0, degrade to 0.45-0.65x full-parser number. EVIDENCE: (1) js-yaml json:true last-wins — CONFIRMED empirically: ran installed js-yaml (node_modules/js-yaml, actually v4.3.0, not 4.1.0 as briefed) on ‘a: 1\na: 2’: default THROWS ‘duplicated mapping key (2:1)’; {json:true} returns {“a”:2} (last-wins). So the escape hatch exists AND the design’s premise that js-yaml’s default is throw is also correct. (2) yaml-test-suite does not require duplicate-key rejection — CONFIRMED: GitHub code search of yaml/yaml-test-suite for ‘duplicate’ finds the ‘duplicate-key’ tag only on VALID tests (src/2JQS.yaml, ‘: a\n: b’, no fail:true, event-level expectation with two empty keys); the only duplicate-related fail test is SF5V (duplicate %YAML directive, unrelated). Stronger still: throw-by-default actually FAILS the suite — installed yaml@2.9.0 (uniqueKeys:true default) throws ‘Map keys must be unique’ on valid test 2JQS, while uniqueKeys:false parses it. So the suite is not merely neutral on duplicates; it contains a valid case a strict-throw composer rejects. (3) rapidyaml — CONFIRMED via README (github.com/biojppm/rapidyaml): ‘passes 100.00% of the cases in the YAML test suite’ and ‘Non-unique map keys are allowed’, citing the log-linear cost of uniqueness enforcement. One nuance that does NOT refute but tempers ‘acceptable to users’: BOTH installed JS competitors (js-yaml 4.3.0 default, yaml 2.9.0 default) throw on duplicates, so the JS-ecosystem incumbent default is throw — but the claim explicitly anticipates exactly this with the Tier-0-off fallback, and the 0.45-0.65x degraded figure is the design’s own projection (not testable, no implementation exists yet per /home/user/lightning-yaml/CLAUDE.md). A last-wins default would, however, silently change behavior for js-yaml migrators who relied on duplicate detection — worth a loud docs note or a cheap opt-in duplicate check.