<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maverick Y</title>
    <description>The latest articles on DEV Community by Maverick Y (@maverickyadav).</description>
    <link>https://dev.to/maverickyadav</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4005246%2Facb385a5-0ea9-4f5b-833e-b905c77cd4a6.png</url>
      <title>DEV Community: Maverick Y</title>
      <link>https://dev.to/maverickyadav</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maverickyadav"/>
    <language>en</language>
    <item>
      <title>Block Google's AI Overviews at the Network Layer, Not the DOM</title>
      <dc:creator>Maverick Y</dc:creator>
      <pubDate>Thu, 02 Jul 2026 18:40:26 +0000</pubDate>
      <link>https://dev.to/maverickyadav/block-googles-ai-overviews-at-the-network-layer-not-the-dom-4aii</link>
      <guid>https://dev.to/maverickyadav/block-googles-ai-overviews-at-the-network-layer-not-the-dom-4aii</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Most extensions block Google's AI Overviews by hiding the panel with a content script after it renders — fragile, flickery, and always a step behind Google's markup changes. A better approach: force &lt;code&gt;udm=14&lt;/code&gt; at the network layer with &lt;code&gt;declarativeNetRequest&lt;/code&gt;, so the AI Overview never loads. The content script becomes a backstop, not the main mechanism. One Chrome API mystery — AI Mode being invisible to four different extension APIs — shows why the DOM was never the right layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Google puts an AI Overview at the top of most search results now, and a lot of people would rather it didn't. So there's a whole shelf of Chrome extensions that remove it. Almost all of them work the same way, and I think that way is a mistake.&lt;/p&gt;

&lt;h2&gt;
  
  
  The obvious approach, and why it's a trap
&lt;/h2&gt;

&lt;p&gt;The default move is DOM-hiding: inject a content script, wait for the AI Overview panel to render, find it by class name or attribute, and set &lt;code&gt;display: none&lt;/code&gt;. It's the first thing anyone reaches for, and it works — until it doesn't.&lt;/p&gt;

&lt;p&gt;The problems are all baked into the approach. You're reacting &lt;em&gt;after&lt;/em&gt; the render, so there's a flash of AI content before your script catches it. You're matching against Google's markup, which is obfuscated and reshuffled constantly, so every layout change is a silent breakage. And you're paying for DOM churn on a page you don't control. You end up in a permanent game of catch-up against a page that changes whenever Google feels like it.&lt;/p&gt;

&lt;p&gt;The deeper issue is that you're operating one layer too high. The panel is a &lt;em&gt;symptom&lt;/em&gt;. By the time it's in the DOM, the work is already done — the server decided to send it, the page rendered it, and now you're scrambling to un-render it. If you can move the decision earlier, none of that scramble has to happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thesis: prevent it at the network layer
&lt;/h2&gt;

&lt;p&gt;Google Search takes a parameter, &lt;code&gt;udm&lt;/code&gt;, that selects which result vertical you get. &lt;code&gt;udm=14&lt;/code&gt; is the plain "Web" results view — the classic list of links, no AI Overview, no AI Mode. It's Google's own filter; we're just always asking for it.&lt;/p&gt;

&lt;p&gt;So instead of hiding the panel after it loads, force &lt;code&gt;udm=14&lt;/code&gt; onto the search request &lt;em&gt;before&lt;/em&gt; it loads. The AI Overview is never generated, never sent, never rendered. Nothing to hide because nothing arrived.&lt;/p&gt;

&lt;p&gt;Manifest V3's &lt;code&gt;declarativeNetRequest&lt;/code&gt; does exactly this — it rewrites requests by rule, without the extension ever reading the traffic. Here's the core rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redirect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;queryTransform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;addOrReplaceParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;udm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;requestDomains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;www.google.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;urlFilter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/search?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;requestMethods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;resourceTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main_frame&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole mechanism. Every top-level search navigation gets &lt;code&gt;udm=14&lt;/code&gt; stamped onto it and comes back as clean Web results. No content script races the render, because there's no AI render to race. It's language-independent too — &lt;code&gt;udm&lt;/code&gt; is a server-side parameter, so it doesn't care whether Google is serving you English or German, which is a nice bonus over text-matching a panel heading.&lt;/p&gt;

&lt;p&gt;Note &lt;code&gt;resourceTypes: ["main_frame"]&lt;/code&gt; — this only touches the top-level page load, not the page's own internal requests, so it changes what you searched for without breaking how the page works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The proof that the DOM was never enough: AI Mode
&lt;/h2&gt;

&lt;p&gt;Here's the part that turned me from "the network layer is nicer" to "the DOM layer is genuinely the wrong place."&lt;/p&gt;

&lt;p&gt;Alongside AI Overviews, Google has AI Mode — a separate conversational surface you reach from a tab in the results. I wanted to suppress its page too, and I assumed the content-script backstop would catch it like anything else. It didn't. So I tried to observe that page from every angle a Chrome extension has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;declarativeNetRequest&lt;/code&gt; — no rule matched the navigation.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;MutationObserver&lt;/code&gt; on the document — fired for nothing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chrome.tabs.onUpdated&lt;/code&gt; — never reported the change.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chrome.storage.onChanged&lt;/code&gt; as a last resort signal — silent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Four unrelated APIs, and every one came back blank — even though the address bar plainly showed &lt;code&gt;udm=50&lt;/code&gt; for AI Mode. Not "my selector missed it." Zero signal of any kind reached the extension.&lt;/p&gt;

&lt;p&gt;The consistent silence across four different mechanisms is the tell: that surface isn't part of the same page a content script attaches to. Whatever it is, it's stitched into the tab in a way that never injects a content script or surfaces a navigation the extension can see. Which means the DOM layer can't touch it &lt;em&gt;even in principle&lt;/em&gt;. If your entire strategy is "hide it in the DOM," you have no move here at all.&lt;/p&gt;

&lt;p&gt;The network-layer approach at least has an answer: since I can't catch that page, I prevent the click that leads to it — the extension hides the AI Mode tab in the results before it's ever pressed. Prevention again, one step earlier than the thing I couldn't reach.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the network layer can't do either
&lt;/h2&gt;

&lt;p&gt;I'd be selling you something if I stopped there, so here are the honest limits.&lt;/p&gt;

&lt;p&gt;Forcing &lt;code&gt;udm=14&lt;/code&gt; catches the searches that go through the search box. It does not catch someone who navigates &lt;em&gt;directly&lt;/em&gt; to a &lt;code&gt;udm=50&lt;/code&gt; URL — a typed address, an old bookmark, an external link — because there's no clean search request to rewrite. And it does nothing about Chrome's own omnibox AI button, which is native browser UI, not part of any page; no extension API can remove it.&lt;/p&gt;

&lt;p&gt;Those aren't bugs to fix later; they're the edge of what this layer owns. Naming them is the difference between an approach you trust and one you find out about the hard way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the content script goes: the backstop, not the star
&lt;/h2&gt;

&lt;p&gt;I didn't delete the content script — I demoted it. It still runs, but as a labeled safety net for one specific case: Google quietly changing how &lt;code&gt;udm=14&lt;/code&gt; behaves. If that ever happens, the backstop hides whatever slipped through and the extension tells me about it, instead of silently degrading.&lt;/p&gt;

&lt;p&gt;That's the content script in its right role — a fallback for the thing the primary mechanism can't guarantee, not the primary mechanism itself. The same code that's fragile as a front line is perfectly reasonable as a backstop, because it only has to fire when something has already gone wrong.&lt;/p&gt;

&lt;p&gt;There's a small elaboration worth mentioning: I wanted users to be able to summon the AI Overview for a single search on demand. That's a second &lt;code&gt;declarativeNetRequest&lt;/code&gt; rule at higher priority that &lt;em&gt;allows&lt;/em&gt; a specifically-marked request through unmodified — the redirect and the exception live at the same layer, which keeps the whole thing coherent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The transferable part
&lt;/h2&gt;

&lt;p&gt;Forget Google for a second. The lesson generalizes: when you're fighting a web page's behavior, find the layer that actually owns the decision before you reach for the DOM. The DOM is where behavior becomes &lt;em&gt;visible&lt;/em&gt;, which makes it the tempting place to intervene — and often the wrong one, because by then the decision is already made. Ask what produced the thing you're trying to stop, and see if you can get upstream of it. Sometimes you can't, and the DOM really is your only handle. But it's worth checking, because when you &lt;em&gt;can&lt;/em&gt; move upstream, the fragile parts of the problem tend to disappear rather than get patched.&lt;/p&gt;

&lt;p&gt;For this problem, that meant a request-rewrite rule instead of a render-and-hide loop — and an AI Mode mystery that made the point better than I could have on purpose.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I built this out as a small extension, &lt;a href="https://chromewebstore.google.com/detail/no-ai-search/bpgffbdgipfobnjdoikbbficmenihffg" rel="noopener noreferrer"&gt;No AI Search&lt;/a&gt;, if you want to see the whole thing shipped. Source is on &lt;a href="https://github.com/antrixy/no-ai-search" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>extensions</category>
    </item>
    <item>
      <title>I built a differential tester for TOON, and it found two silent-corruption bugs on the first run</title>
      <dc:creator>Maverick Y</dc:creator>
      <pubDate>Thu, 02 Jul 2026 16:18:56 +0000</pubDate>
      <link>https://dev.to/maverickyadav/i-built-a-differential-tester-for-toon-and-it-found-two-silent-corruption-bugs-on-the-first-run-4ia7</link>
      <guid>https://dev.to/maverickyadav/i-built-a-differential-tester-for-toon-and-it-found-two-silent-corruption-bugs-on-the-first-run-4ia7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — I built a differential tester for TOON: it runs data through one implementation's encoder and a &lt;em&gt;different&lt;/em&gt; implementation's decoder, and checks the round-trip survived. On its first run it found two silent-corruption bugs (a rounded 64-bit integer and an empty array that decoded to a corrupted string), both filed upstream. The hard part wasn't finding bugs — it was building a comparison oracle honest enough that its FAIL means something. Repo: &lt;a href="https://github.com/antrixy/toon-diff" rel="noopener noreferrer"&gt;github.com/antrixy/toon-diff&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I built a small tool that checks whether independent &lt;a href="https://github.com/toon-format/spec" rel="noopener noreferrer"&gt;TOON&lt;/a&gt; implementations actually agree with each other. On its first real run — across the TypeScript reference and the Python port — it found two silent-corruption bugs. Both are now filed upstream.&lt;/p&gt;

&lt;p&gt;This post is about &lt;em&gt;why&lt;/em&gt; the approach finds bugs that ordinary conformance suites miss, and about the one genuinely tricky part: building a comparison oracle that doesn't corrupt the data while it's checking it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup: TOON, and the promise of lossless round-trips
&lt;/h2&gt;

&lt;p&gt;TOON (Token-Oriented Object Notation) is a compact, line-oriented encoding of the JSON data model, designed for things like trimming token counts in LLM prompts. The whole value proposition rests on one property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JSON  →  TOON  →  JSON     should give you back what you started with.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are independent TOON implementations in 25+ languages. Each ships its own conformance tests. Each is green. And yet the moment you have more than one implementation, a new failure mode appears that none of those green test suites can see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why conformance suites miss the interesting bugs
&lt;/h2&gt;

&lt;p&gt;A conformance suite checks one implementation against a set of blessed expected outputs: &lt;em&gt;given input X, the encoder must produce exactly Y.&lt;/em&gt; That's useful, but it has a structural blind spot.&lt;/p&gt;

&lt;p&gt;Every implementation round-trips &lt;strong&gt;its own&lt;/strong&gt; output just fine. The TS encoder produces something the TS decoder reads back perfectly. The Python encoder produces something the Python decoder reads back perfectly. Both suites pass. The bug lives in the gap between them — when TS encodes something and &lt;em&gt;Python&lt;/em&gt; has to decode it, or vice versa.&lt;/p&gt;

&lt;p&gt;That's what differential testing targets directly. Instead of checking against expected outputs, you check implementations against &lt;strong&gt;each other&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decode_Y( encode_X( value ) )  ==  value     for every ordered pair (X, Y)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With N implementations you run N×N ordered pairs (including each against itself, which is your control). Two implementations is a 4-cell matrix; three is 9. Any cell that fails is a place where two implementations disagree about what a given value means — and because both sides individually pass their own tests, nobody had noticed.&lt;/p&gt;

&lt;p&gt;The harness for this is almost trivial. Each implementation gets wrapped in a tiny adapter with a uniform, text-in/text-out contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Adapter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// JSON text -&amp;gt; TOON text&lt;/span&gt;
  &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toonText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// TOON text -&amp;gt; JSON text&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Working on text means the harness never has to hold any language's native value model. Adding a new language is one adapter. The driver loop is just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;adapters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Y&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;adapters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;cases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsonText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;back&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toon&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;ingest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;back&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the difficulty is hiding in one word: &lt;code&gt;equal&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hard part: an oracle that doesn't corrupt the data it's judging
&lt;/h2&gt;

&lt;p&gt;Here's the trap. You want to compare the original value against the round-tripped value. The obvious way is to parse both back into native objects and compare. In JavaScript that means &lt;code&gt;JSON.parse&lt;/code&gt;. And &lt;code&gt;JSON.parse&lt;/code&gt; will quietly destroy the exact cases you most want to test.&lt;/p&gt;

&lt;p&gt;Consider the integer &lt;code&gt;9007199254740993&lt;/code&gt;, which is 2⁵³ + 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9007199254740993&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// -&amp;gt; 9007199254740992   (!!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It comes back as 2⁵³, off by one, because it rounded through an IEEE-754 double. If your oracle parses values this way, then when one implementation preserves the integer and another rounds it, your oracle rounds &lt;em&gt;both&lt;/em&gt; and reports a false &lt;strong&gt;PASS&lt;/strong&gt; — on the single most important case in the suite. The comparator silently corrupts the evidence.&lt;/p&gt;

&lt;p&gt;My first version "solved" this by quarantining such cases — detecting numbers that couldn't survive a float and benching them. But that benches exactly the inputs where implementations with different number models (JS &lt;code&gt;f64&lt;/code&gt;, Python arbitrary-precision int, Rust &lt;code&gt;i64/u64/f64&lt;/code&gt;) are &lt;em&gt;guaranteed&lt;/em&gt; to diverge. You're throwing away your strongest evidence to protect a broken comparator.&lt;/p&gt;

&lt;p&gt;The fix is to never let a number touch a float. ES2023 added a &lt;code&gt;context&lt;/code&gt; argument to the &lt;code&gt;JSON.parse&lt;/code&gt; reviver that hands you the &lt;strong&gt;exact source lexeme&lt;/strong&gt; of each value, before any numeric conversion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NUM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;num&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// collision-proof: JSON.parse can't produce a Symbol key&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ingest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ctx.source is the raw digits as written: "9007199254740993",&lt;/span&gt;
      &lt;span class="c1"&gt;// captured BEFORE the lossy f64 conversion that produced `value`.&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NUM&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nf"&gt;canonicalNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ctx.source&lt;/code&gt; is the string &lt;code&gt;"9007199254740993"&lt;/code&gt; — the actual characters from the input — even though &lt;code&gt;value&lt;/code&gt; is already the rounded double. We ignore &lt;code&gt;value&lt;/code&gt; entirely and keep the digits. Numbers are stored as a &lt;code&gt;Symbol&lt;/code&gt;-tagged node so they can never collide with a real object that happens to have a &lt;code&gt;"__num"&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;canonicalNumber&lt;/code&gt; then reduces the lexeme to a canonical &lt;strong&gt;value&lt;/strong&gt; form using arbitrary-precision string arithmetic — never an &lt;code&gt;f64&lt;/code&gt; — so &lt;code&gt;2⁵³+1&lt;/code&gt; stays itself all the way through the comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inside canonicalNumber: value identity without a float
&lt;/h3&gt;

&lt;p&gt;The reviver gets us the raw digits; the remaining job is to map two different lexemes that denote the &lt;em&gt;same number&lt;/em&gt; to the &lt;em&gt;same string&lt;/em&gt;, without ever evaluating them numerically. &lt;code&gt;"1.0"&lt;/code&gt;, &lt;code&gt;"1.00"&lt;/code&gt;, and &lt;code&gt;"1e0"&lt;/code&gt; must all become &lt;code&gt;"1"&lt;/code&gt;; &lt;code&gt;"1e-2"&lt;/code&gt; must become &lt;code&gt;"0.01"&lt;/code&gt;; and &lt;code&gt;"9007199254740993"&lt;/code&gt; must stay exactly itself. The whole thing is regex + string shifts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;canonicalNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;([&lt;/span&gt;&lt;span class="sr"&gt;+-&lt;/span&gt;&lt;span class="se"&gt;]?)(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)(?:\.(\d&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;))?(?:[&lt;/span&gt;&lt;span class="sr"&gt;eE&lt;/span&gt;&lt;span class="se"&gt;]([&lt;/span&gt;&lt;span class="sr"&gt;+-&lt;/span&gt;&lt;span class="se"&gt;]?\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;))?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// not a well-formed JSON number; fail safe, never throw&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// all significant digits, point removed&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pointPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// where the point lands&lt;/span&gt;

  &lt;span class="c1"&gt;// Shift the decimal point by `pointPos`, padding with zeros when it falls&lt;/span&gt;
  &lt;span class="c1"&gt;// outside the digit run — pure string surgery, no parseFloat anywhere.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;intStr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointPos&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;intStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;pointPos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointPos&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;intStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointPos&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;                                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;intStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointPos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointPos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;intStr&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;intStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^0+&lt;/span&gt;&lt;span class="se"&gt;(?=\d)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// strip leading zeros, keep one&lt;/span&gt;
  &lt;span class="nx"&gt;fracStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/0+$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// strip trailing zeros&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intStr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// canonical zero, sign dropped&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fracStr&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;intStr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fracStr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;intStr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things worth calling out. First, the &lt;code&gt;if (!m) return lex&lt;/code&gt; line: a lexeme that doesn't match the JSON number grammar is returned untouched rather than throwing — the oracle should never crash on input, it should compare faithfully and let the &lt;em&gt;result&lt;/em&gt; be the signal. Second, this is the exact spot where the value-vs-representation policy lives. Returning a value-normalized form here is what makes &lt;code&gt;1.0 == 1&lt;/code&gt; and &lt;code&gt;-0 == 0&lt;/code&gt;. If you instead wanted to &lt;em&gt;flag&lt;/em&gt; representational drift — say, to surface that one implementation preserves &lt;code&gt;-0&lt;/code&gt; while another normalizes it — you'd return a representation-preserving form here (keep the trailing &lt;code&gt;.0&lt;/code&gt;, keep the leading &lt;code&gt;-&lt;/code&gt; on zero) and integers would still compare exactly. One function, one deliberate stance, documented in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one real judgment call: compare by value, with exact integers
&lt;/h2&gt;

&lt;p&gt;Once numbers survive ingestion intact, you have to decide what "equal" &lt;em&gt;means&lt;/em&gt;. This is the only genuinely opinionated part of the oracle, and it's worth stating explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.0     == 1        value-equal (RFC 8259: these denote the same number)
-0      == 0        value-equal (JSON's value model has no signed zero)
2^53+1  != 2^53     DIFFERENT integers — precision loss is a real divergence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words: compare by mathematical value (so representational noise like &lt;code&gt;1.0&lt;/code&gt; vs &lt;code&gt;1&lt;/code&gt; doesn't generate false positives), but preserve exact integer identity (so genuine precision loss is caught). That's the correct default for a "did the round-trip stay lossless?" question. Everything else in the oracle is strict: types don't coerce (&lt;code&gt;"123"&lt;/code&gt; ≠ &lt;code&gt;123&lt;/code&gt;), array order matters, missing keys differ from explicit nulls, and there's no Unicode normalization (&lt;code&gt;e&lt;/code&gt; + combining acute ≠ precomposed &lt;code&gt;é&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  How equality is actually computed
&lt;/h3&gt;

&lt;p&gt;Rather than a recursive deep-equal with a pile of type checks, the oracle serializes each value tree to a single canonical string and compares the strings. The serialization is where the strictness is enforced structurally, so it can't be forgotten case by case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;null&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;boolean&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;false&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// quoted form&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isNum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NUM&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;               &lt;span class="c1"&gt;// unquoted #-token&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                               &lt;span class="c1"&gt;// key order normalized&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;])).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;equal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nf"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The detail that does the heavy lifting: a string serializes to its &lt;strong&gt;quoted&lt;/strong&gt; form (&lt;code&gt;"123"&lt;/code&gt; → &lt;code&gt;"123"&lt;/code&gt;) while a number serializes to a &lt;code&gt;#&lt;/code&gt;-prefixed token (&lt;code&gt;123&lt;/code&gt; → &lt;code&gt;#123&lt;/code&gt;). Those can never collide, so the string &lt;code&gt;"123"&lt;/code&gt; and the number &lt;code&gt;123&lt;/code&gt; are structurally incapable of comparing equal — type-strictness falls out of the representation instead of being a check you have to remember to write. Object keys are sorted so key &lt;em&gt;order&lt;/em&gt; doesn't matter, but arrays aren't, so element order does. And because the leaves are the &lt;code&gt;Symbol&lt;/code&gt;-tagged value-form numbers from &lt;code&gt;canonicalNumber&lt;/code&gt;, exact-integer identity is already baked in by the time we get here.&lt;/p&gt;

&lt;p&gt;This is also what makes the oracle cheaply self-provable: &lt;code&gt;canonical&lt;/code&gt; has no dependency on TOON at all, so its self-test just asserts pairs of values that must (or must not) share a canonical string — &lt;code&gt;1.0&lt;/code&gt;/&lt;code&gt;1&lt;/code&gt; equal, &lt;code&gt;2⁵³+1&lt;/code&gt;/&lt;code&gt;2⁵³&lt;/code&gt; not, &lt;code&gt;"123"&lt;/code&gt;/&lt;code&gt;123&lt;/code&gt; not — and runs before any adapter is touched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the matrix: the &lt;em&gt;shape&lt;/em&gt; of the failures diagnoses the bug
&lt;/h2&gt;

&lt;p&gt;With two adapters (TS, Python) and 13 cases, a run is 2×2×13 = 52 pair-checks. Most cells pass. But the interesting thing isn't &lt;em&gt;that&lt;/em&gt; cells fail — it's &lt;em&gt;which&lt;/em&gt; cells fail, because the pattern tells you what kind of bug you're looking at before you read a single value.&lt;/p&gt;

&lt;p&gt;Here are the two cases that diverged, as 2×2 grids. Rows are the encoder, columns are the decoder; ✓ means the round-trip survived, ✗ means the oracle caught a divergence:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case &lt;code&gt;013&lt;/code&gt; — integer &lt;code&gt;9007199254740993&lt;/code&gt; (2⁵³+1):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                decode_TS   decode_Py
  encode_TS        ✗            ✗
  encode_Py        ✗            ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three of four pairs fail — including &lt;code&gt;TS→TS&lt;/code&gt;, the self-pair that's supposed to be your control. That shape is the diagnosis: when even an implementation's round-trip &lt;em&gt;with itself&lt;/em&gt; fails, the problem isn't a handoff between languages, it's that implementation's &lt;strong&gt;number model&lt;/strong&gt;. TS holds the integer as an &lt;code&gt;f64&lt;/code&gt; the instant it touches it, so &lt;code&gt;encode_TS&lt;/code&gt; has already lost the digit before any decoder runs; and &lt;code&gt;decode_TS&lt;/code&gt; re-loses it even when Python encoded it faithfully. The only surviving cell is &lt;code&gt;Py→Py&lt;/code&gt;, because Python's arbitrary-precision integers never round. A failure that includes the diagonal = an encode/decode-side capability limit, not a protocol disagreement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case &lt;code&gt;002&lt;/code&gt; — empty array &lt;code&gt;[]&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                decode_TS   decode_Py
  encode_TS        ✓            ✗
  encode_Py        ✓            ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exactly &lt;strong&gt;one&lt;/strong&gt; cell fails: &lt;code&gt;encode_TS → decode_Py&lt;/code&gt;. That's the signature of a true cross-implementation handoff bug. TS encodes the empty array as the bare &lt;code&gt;[]&lt;/code&gt; — a form TS's &lt;em&gt;own&lt;/em&gt; decoder happily reads back (so &lt;code&gt;TS→TS&lt;/code&gt; passes and its conformance suite stays green), but which Python's decoder chokes on, returning the corrupted &lt;code&gt;'['&lt;/code&gt;. Python's own output (&lt;code&gt;[0]:&lt;/code&gt;, the spec-canonical form) is read correctly by everyone, so its whole row passes. A single off-diagonal failure points straight at "implementation A emits something only A can read."&lt;/p&gt;

&lt;p&gt;This is the entire argument for differential testing in one picture. The &lt;code&gt;013&lt;/code&gt; pattern (fails on the diagonal) and the &lt;code&gt;002&lt;/code&gt; pattern (fails on exactly one off-diagonal cell) are &lt;em&gt;different bug classes&lt;/em&gt;, and you can tell them apart by the geometry of the matrix without even inspecting the payloads. A single-implementation conformance suite only ever runs the diagonal — so it can see &lt;code&gt;013&lt;/code&gt; (sort of, if it tests the boundary) but is structurally blind to &lt;code&gt;002&lt;/code&gt;, whose only failing cell is off-diagonal by definition.&lt;/p&gt;

&lt;p&gt;Scale this to three adapters and it's a 3×3 grid per case; the Rust adapter (different number model again) turns each case into 9 pair-checks and adds a whole new row and column of handoffs where divergences can hide.&lt;/p&gt;

&lt;p&gt;Thirteen hand-designed probe cases, aimed at known fault lines: empty containers, almost-uniform tables, string-lookalikes, Unicode edge cases, whitespace, and the number boundaries around 2⁵³. First run, two real divergences.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Integer 2⁵³+1 — silent precision loss across the boundary
&lt;/h3&gt;

&lt;p&gt;Input &lt;code&gt;{"unsafe": 9007199254740993}&lt;/code&gt;. The TS path rounds it to &lt;code&gt;...992&lt;/code&gt;; the Python path preserves it exactly. Round-trip each through &lt;em&gt;itself&lt;/em&gt; and both pass — the loss only appears when you cross them, which is precisely what the matrix does.&lt;/p&gt;

&lt;p&gt;The honest framing here matters: TOON's spec permits precision loss for numbers outside a host's safe range &lt;strong&gt;if the implementation documents it&lt;/strong&gt;. So this isn't a flat bug — it's a documented-divergence boundary, and the right place to surface it is the tool's README, not an accusatory issue. Differential testing is what makes the boundary &lt;em&gt;visible&lt;/em&gt; instead of theoretical.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Empty array — a genuine cross-implementation bug, both halves
&lt;/h3&gt;

&lt;p&gt;This one's a real bug, and it has two sides.&lt;/p&gt;

&lt;p&gt;The spec is explicit (&lt;a href="https://github.com/toon-format/spec" rel="noopener noreferrer"&gt;§9.1&lt;/a&gt;): an empty array encodes as &lt;code&gt;[0]:&lt;/code&gt;. But:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encoder side (TS):&lt;/strong&gt; &lt;code&gt;encode([])&lt;/code&gt; emits the bare &lt;code&gt;[]&lt;/code&gt;, with no length header — non-conformant to §9.1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decoder side (Python):&lt;/strong&gt; &lt;code&gt;decode("[]")&lt;/code&gt; returns the string &lt;code&gt;'['&lt;/code&gt; — a single character, with the &lt;code&gt;]&lt;/code&gt; silently dropped. Not the empty array, not an error, not even the literal string &lt;code&gt;"[]"&lt;/code&gt;. Just corrupted output flowing downstream with no signal.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c1"&gt;# -&amp;gt; '['            corrupted
&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[0]:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# -&amp;gt; []             correct (canonical form)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both halves filed: &lt;a href="https://github.com/toon-format/toon/issues/322" rel="noopener noreferrer"&gt;toon-format/toon#322&lt;/a&gt; (encoder) and &lt;a href="https://github.com/toon-format/toon-python/issues/61" rel="noopener noreferrer"&gt;toon-format/toon-python#61&lt;/a&gt; (decoder). Each side individually "worked" — the bug only existed in the handoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest status: a differential &lt;em&gt;probe&lt;/em&gt;, not yet a &lt;em&gt;fuzzer&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;I want to be precise about what this is. Right now it's 13 curated inputs, not a generative fuzzer. The next step is a mutation-based generator that takes those seeds and pushes along the same fault lines — boundary integers, delimiter-adjacent strings, near-uniform tables, empty containers — then shrinks any failure to a minimal reproducer. That's what turns "I picked inputs that break things" into "the tool finds inputs nobody wrote." A third adapter (Rust, with its &lt;code&gt;i64/u64/f64&lt;/code&gt; split) widens the number-model coverage where the next divergences most likely hide.&lt;/p&gt;

&lt;h2&gt;
  
  
  The transferable idea
&lt;/h2&gt;

&lt;p&gt;None of this is TOON-specific. If you maintain any format with multiple independent implementations — a serializer, a parser, a protocol codec — the same shape applies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cross, don't self-check.&lt;/strong&gt; Run &lt;code&gt;decode_B(encode_A(x))&lt;/code&gt;, not &lt;code&gt;decode_A(encode_A(x))&lt;/code&gt;. Same-implementation round-trips hide boundary bugs by construction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't let your oracle corrupt the evidence.&lt;/strong&gt; If your comparison path rounds, normalizes, or coerces, it will mask the exact divergences you're hunting. Capture values losslessly (the &lt;code&gt;ctx.source&lt;/code&gt; trick is a clean way to do it in JS) and decide your equality semantics deliberately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prove the judge independently.&lt;/strong&gt; The oracle must pass its own self-test with zero dependency on the things it judges.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repo: &lt;strong&gt;&lt;a href="https://github.com/antrixy/toon-diff" rel="noopener noreferrer"&gt;https://github.com/antrixy/toon-diff&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two real bugs, no fuzzer yet, on inputs a person hand-wrote. The interesting part wasn't the bugs — it was building a comparator honest enough to believe when it said FAIL.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>fuzzing</category>
    </item>
    <item>
      <title>Decades In, and a Date Field Still Got Me</title>
      <dc:creator>Maverick Y</dc:creator>
      <pubDate>Wed, 01 Jul 2026 02:14:52 +0000</pubDate>
      <link>https://dev.to/maverickyadav/decades-in-and-a-date-field-still-got-me-3e43</link>
      <guid>https://dev.to/maverickyadav/decades-in-and-a-date-field-still-got-me-3e43</guid>
      <description>&lt;p&gt;I've been writing software for a long time. Long enough to have shipped in languages people don't run anymore, long enough to have made just about every mistake in the book at least once. You'd think that by now the simple bugs would be behind me.&lt;/p&gt;

&lt;p&gt;They're not. And this is a story about one of them — written, mostly, for the junior developers who think the dangerous bugs are the complicated ones.&lt;/p&gt;

&lt;p&gt;They aren't. Let me explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened
&lt;/h2&gt;

&lt;p&gt;A flow that very few people use, but where each transaction carries a serious dollar amount, quietly stopped letting anyone complete it. No crash. No alarm. No stack trace begging for attention. Just a validation check that calmly, confidently refused to let people finish.&lt;/p&gt;

&lt;p&gt;The cause: a date comparison was treating the &lt;em&gt;current&lt;/em&gt; month as if it were in the future. A perfectly valid entry got rejected as impossible. Nobody on the other end was doing anything wrong — the code had simply decided that "now" hadn't arrived yet.&lt;/p&gt;

&lt;p&gt;Low traffic, high value. That combination matters. When millions of people hit a broken page, you find out in minutes. When a handful of people hit it — but each one represents real money on the line — the failure is quieter and the cost per failure is enormous. It's the kind of thing that doesn't trip your dashboards but absolutely lands on someone's desk.&lt;/p&gt;

&lt;p&gt;And here's the part I have to own: I didn't find it. A user did. They were the ones who hit the wall, figured out something was wrong, and reported it. My tests were green. My dashboards were calm. My decades of instinct hadn't flagged a thing. The failure surfaced because someone on the outside ran into it and bothered to tell us.&lt;/p&gt;

&lt;p&gt;Once it was in front of me, the diagnosis was fast and the fix took minutes. But I want to be honest about how it felt: not triumphant. The bug was an off-by-one in date logic, the kind of mistake I'd have sworn I was long past — and it took a user to point at it before I ever saw it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I want the juniors to hear
&lt;/h2&gt;

&lt;p&gt;Early in your career, you'll assume that big problems have big causes. That if something important breaks, the explanation must be appropriately sophisticated — a race condition, a subtle architectural flaw, something worthy of the damage.&lt;/p&gt;

&lt;p&gt;I'm here, decades in, to tell you that's a comforting lie.&lt;/p&gt;

&lt;p&gt;Software doesn't grade on a curve. A one-line date mistake and a thousand-line design failure can produce the identical outcome: a person blocked, money stalled, and no idea why. The user never sees whether the cause was elegant or embarrassing. They just see a door that won't open.&lt;/p&gt;

&lt;p&gt;The bugs that have cost me — and the businesses I've worked for — the most over my career were almost never the clever ones. The clever ones get attention. They get design reviews, careful testing, three sets of eyes. The simple ones slip through &lt;em&gt;precisely because&lt;/em&gt; they look too trivial to be wrong. Nobody scrutinizes a date check the way they scrutinize the scary concurrency code. That's exactly why the date check is the one that bites.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell my younger self
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dates are a trap that never stops being a trap.&lt;/strong&gt; Timezones, month boundaries, "today," inclusive vs. exclusive ranges, off-by-one at the edges. I have decades of experience and date logic &lt;em&gt;still&lt;/em&gt; demands my full attention. Treat every comparison like it's hiding an edge case, because it is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low volume is not low risk.&lt;/strong&gt; Don't measure a bug's severity by how many people hit it. Measure it by what each hit costs. A rarely used path guarding something valuable deserves more care than a busy path guarding something trivial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The boring bugs are the dangerous ones.&lt;/strong&gt; They survive code review because they look harmless. Your instinct will be to spend your scrutiny on the complex code. Fight that instinct and give the "obvious" code a second look.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calm is a senior skill, and you can start building it now.&lt;/strong&gt; I diagnosed this quickly not because I'm brilliant but because once it was in front of me I didn't burn twenty minutes panicking. I read the logic, traced the input, and trusted that the cause was probably mundane. It almost always is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your users are your last line of defense — which means your earlier lines failed.&lt;/strong&gt; A user caught this, not me, not my tests, not my monitoring. That's a gift and a warning at the same time. Be grateful when someone reports a bug clearly; they just did your QA for free. But also ask the harder question: why did it have to reach them at all? Every user-reported bug is a quiet audit of the safety nets that didn't catch it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the boundaries, not the middle.&lt;/strong&gt; Bugs don't live at "obviously valid" or "obviously invalid." They live at the edges — the first of the month, the last second of the year, the value that's exactly equal. Write the test for the edge before you write the code for the middle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The thing that took me years to accept
&lt;/h2&gt;

&lt;p&gt;When you find a bug this simple, a voice shows up: &lt;em&gt;how did I miss something so obvious?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I still hear that voice. The difference now is that I don't believe it anymore. Obvious-in-hindsight is the natural condition of nearly every bug ever fixed. Hindsight makes everything look inevitable.&lt;/p&gt;

&lt;p&gt;The measure of a good engineer was never &lt;em&gt;never writing the simple mistake.&lt;/em&gt; You will write it. I still write it, after all this time. The measure is whether you can stay calm, find it fast, and fix it before it costs someone something that matters.&lt;/p&gt;

&lt;p&gt;To the juniors reading this: the unglamorous saves count. Quietly. Permanently. Most of the real work of this job looks exactly like this — not heroic, just careful. Get comfortable with that early, and the decades go a lot smoother.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Cut LLM prompt tokens on structured data — losslessly</title>
      <dc:creator>Maverick Y</dc:creator>
      <pubDate>Sat, 27 Jun 2026 12:01:37 +0000</pubDate>
      <link>https://dev.to/maverickyadav/cut-llm-prompt-tokens-on-structured-data-losslessly-op5</link>
      <guid>https://dev.to/maverickyadav/cut-llm-prompt-tokens-on-structured-data-losslessly-op5</guid>
      <description>&lt;h1&gt;
  
  
  Cut LLM prompt tokens on structured data — losslessly
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A small, dependency-free tool for shrinking logs, JSON, and CSV in prompts — without dropping a single byte.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Logs, JSON, and CSV are some of the bulkiest, most repetitive things we feed into LLMs. They're also where prompt-token costs quietly pile up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trouble with lossy compression
&lt;/h2&gt;

&lt;p&gt;The usual fix is &lt;strong&gt;semantic compression&lt;/strong&gt;: have a model summarize the input and drop "low-information" tokens. It works — until the question needs the data that got dropped.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"How many errors are in this log?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"What's the total across these 400 rows?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;…and a lossy compressor can hand back a &lt;strong&gt;confident, wrong answer&lt;/strong&gt; — because the rows it discarded were exactly the ones you needed. The compression looks great. The answer is broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  A different bet: lossless or no-op
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ctxfold&lt;/strong&gt; takes the opposite approach. Its single rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lossless or no-op. Never lossy.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of summarizing, it re-encodes &lt;em&gt;structure&lt;/em&gt;. Logs, JSON arrays, and CSV are tables in disguise — the same keys, prefixes, and templates repeat on every line. ctxfold lifts those repeated parts into a one-time header and keeps only what varies per row, producing a compact, self-labeling table the model reads directly. &lt;strong&gt;Nothing is dropped.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The guarantee is enforced in code: every encoder ships with a decoder, and &lt;code&gt;compress()&lt;/code&gt; verifies that decoding its output reproduces the input &lt;em&gt;before&lt;/em&gt; returning it. If it can't, you get your original text back, untouched. It &lt;strong&gt;can't corrupt your data&lt;/strong&gt; — worst case, it does nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the model still read it?
&lt;/h2&gt;

&lt;p&gt;Yes. On real data, ctxfold cuts &lt;strong&gt;~35–40% of tokens&lt;/strong&gt; on templated logs and JSON arrays, fully losslessly. And because the output is plain, labeled text, the model reads it as well as the raw input — in lookup tests against GPT-4o-mini, answers off the compressed form matched answers off the raw data, field for field.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Readability is validated on GPT-4o-mini; the lossless guarantee is model-independent.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;ctxfold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;compress&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ctxfold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bigLogOrJsonOrCsv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// send `text` instead of the original&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokenRatio&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;% fewer tokens, lossless: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lossless&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a pure text transform — no API calls, no model, zero dependencies — so it works with any LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not a replacement — the other half
&lt;/h2&gt;

&lt;p&gt;ctxfold isn't a competitor to semantic compression; it's the complement. &lt;strong&gt;Summarize to extract a subset; ctxfold to shrink repetition without losing anything.&lt;/strong&gt; It shines on structured data, not prose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;This started from a simple frustration: lossy prompt compressors gave impressive token savings, but on aggregate questions — counts, totals, "find this record" — the answers came back wrong, because the data needed to answer had been summarized away. Great compression, broken results. The fix wasn't a smarter summarizer; it was to stop dropping data at all. Repetitive structured text is compressible &lt;em&gt;losslessly&lt;/em&gt; — you just have to treat it as structure instead of prose.&lt;/p&gt;

&lt;p&gt;If you push a lot of logs, JSON, or CSV into prompts, I'd genuinely like to know what your payloads look like and whether the lossless tradeoff fits your use case. &lt;strong&gt;What's eating the most tokens in your prompts right now?&lt;/strong&gt; Questions, critique, and edge cases that break it are all welcome in the comments.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repo &amp;amp; docs:&lt;/strong&gt; &lt;a href="https://github.com/antrixy/ctxfold" rel="noopener noreferrer"&gt;https://github.com/antrixy/ctxfold&lt;/a&gt; · &lt;strong&gt;npm:&lt;/strong&gt; &lt;code&gt;npm install ctxfold&lt;/code&gt; · MIT licensed.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
