<?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: Shivam Dwivedi</title>
    <description>The latest articles on DEV Community by Shivam Dwivedi (@panditshivam).</description>
    <link>https://dev.to/panditshivam</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%2F1157841%2Fd916da9c-3787-4c22-8f4d-715432202d0f.jpg</url>
      <title>DEV Community: Shivam Dwivedi</title>
      <link>https://dev.to/panditshivam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/panditshivam"/>
    <language>en</language>
    <item>
      <title>The Lemmings demo makes each line of text a platform</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Thu, 05 Nov 2026 17:50:45 +0000</pubDate>
      <link>https://dev.to/panditshivam/the-lemmings-demo-makes-each-line-of-text-a-platform-n97</link>
      <guid>https://dev.to/panditshivam/the-lemmings-demo-makes-each-line-of-text-a-platform-n97</guid>
      <description>&lt;p&gt;A line of text is an odd place to build a floor. It becomes a much better idea once a paragraph wraps.&lt;/p&gt;

&lt;p&gt;MarkBlah's Lemmings demo gives little walkers the page itself to walk on: borders, buttons, images and individual text fragments. [1] I went through the source because the interesting part is the choice of geometry. The pixels are drawn with CSS. JavaScript measures the terrain and advances the walkers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvro4u9fav8fkwtt029bp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvro4u9fav8fkwtt029bp.png" alt="Illustrative paragraph fragments act as separate one-way floors. A solid button blocks sideways movement, while text catches a falling walker without trapping it between lines." width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original mechanism illustration based on the source. This is not a screenshot or a recording of the demo.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A paragraph box would make a boring level
&lt;/h2&gt;

&lt;p&gt;An element's &lt;code&gt;getBoundingClientRect()&lt;/code&gt; gives a rectangle around it. That is useful for a button. Applied to a whole paragraph, it loses the gaps and different line lengths that make the text interesting as terrain. [2]&lt;/p&gt;

&lt;p&gt;The demo walks through text nodes, selects each node with a &lt;code&gt;Range&lt;/code&gt;, and collects its &lt;code&gt;getClientRects()&lt;/code&gt; fragments. [1][3] Wrapped text can therefore contribute several floor rectangles rather than one large paragraph wall.&lt;/p&gt;

&lt;p&gt;There is an equally useful choice after measurement: text is marked as &lt;strong&gt;floor-only&lt;/strong&gt;. It can catch a walker falling from above, while the ordinary solid-obstacle checks leave it out. Boxes and borders participate in those solid checks as well.&lt;/p&gt;

&lt;p&gt;Otherwise, closely spaced lines would be a collection of tiny cages. The character could fit on a line but not between the floors above and below it. Making text one-way terrain gives it a different job from a button's box.&lt;/p&gt;

&lt;h2&gt;
  
  
  From page pixels to a smaller world
&lt;/h2&gt;

&lt;p&gt;The source uses &lt;strong&gt;four screen pixels per world unit&lt;/strong&gt;. It adds scroll offsets to viewport-relative measurements, then rounds the left and top edges down and the right and bottom edges up. [1] Adding scroll offsets is what converts the client rectangle into document coordinates. [2]&lt;/p&gt;

&lt;p&gt;Here is my separate arithmetic illustration, using a synthetic rectangle rather than a measurement from a live page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ceil&lt;/span&gt;

&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;20.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;17.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;21.25&lt;/span&gt;
&lt;span class="n"&gt;scroll_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scroll_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="n"&gt;world&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;scroll_x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;scroll_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;scroll_x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;scroll_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;world&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# (4, 30, 7, 31)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting rectangle covers world x-coordinates from 4 up to, but excluding, 7, and y-coordinates from 30 up to, but excluding, 31. I checked the rounding independently with exact fractions and checked that the right and bottom edges are excluded.&lt;/p&gt;

&lt;p&gt;Rounding outward keeps a thin measured feature from disappearing just because its edges fall between world cells. It also makes this a coarse collision world: the resulting shape need not match the painted pixels exactly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast movement needs more than a final position
&lt;/h2&gt;

&lt;p&gt;A second source detail addresses thin surfaces during a fall. The airborne update divides movement into substeps no larger than one world unit on either axis. [1]&lt;/p&gt;

&lt;p&gt;For an arithmetic example, put a one-unit platform at y in &lt;strong&gt;[10, 11)&lt;/strong&gt;. A point moving directly from y=7 to y=19 lands beyond it. An endpoint-only overlap check sees nothing. Checking the intermediate integer positions finds y=10.&lt;/p&gt;

&lt;p&gt;I executed that small numerical case separately. It illustrates the reason for sampling along movement; it is not a claim that I ran the browser's complete collision engine. The upstream loop also handles the walker's body, direction, ceiling and wall checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The page can change under your feet
&lt;/h2&gt;

&lt;p&gt;Reflow matters because the world is a document. The source rebuilds its rectangle map after page changes and keeps a surface identity so a standing walker can follow the same surface when it moves. It also has explicit shortcuts for fixed or sticky elements and clipped content. [1]&lt;/p&gt;

&lt;p&gt;TheLuigiplayer's &lt;a href="https://dev.to/theluigiplayer/building-a-700-card-browser-rpg-with-react-19-vite-8-and-zero-monetization-2mmk"&gt;browser RPG write-up&lt;/a&gt; describes caching rectangles for pointer interaction. [4] The connection is practical: measuring layout and moving an object are separate jobs, and cached geometry needs a clear refresh point.&lt;/p&gt;

&lt;p&gt;I haven't rendered this demo or measured its frame cost. The source trace and numerical checks explain the terrain model. If I were borrowing the idea, I would start by deciding which page features should carry a character and which should block it. That choice gives the page its rules before the sprite takes a step.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;MarkBlah, &lt;a href="https://github.com/MarkBlah/lemmings/blob/8e7857ee5d68f043bca235201ff4ef21deb848f9/walker.js" rel="noopener noreferrer"&gt;Lemmings source at the reviewed revision&lt;/a&gt;, and the &lt;a href="https://markblah.github.io/lemmings/" rel="noopener noreferrer"&gt;original playground&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;MDN contributors, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect" rel="noopener noreferrer"&gt;Element.getBoundingClientRect()&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;MDN contributors, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Range/getClientRects" rel="noopener noreferrer"&gt;Range.getClientRects()&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;TheLuigiplayer, &lt;a href="https://dev.to/theluigiplayer/building-a-700-card-browser-rpg-with-react-19-vite-8-and-zero-monetization-2mmk"&gt;Building a 700+ Card Browser RPG with React 19, Vite 8, and Zero Monetization&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original schematic and arithmetic example. No upstream sprites, screenshots or source files are redistributed with the article. The original demo remains linked to its author.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>webdev</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>My first Phonon WAV, with the model and language pinned</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Thu, 05 Nov 2026 17:50:12 +0000</pubDate>
      <link>https://dev.to/panditshivam/my-first-phonon-wav-with-the-model-and-language-pinned-49g6</link>
      <guid>https://dev.to/panditshivam/my-first-phonon-wav-with-the-model-and-language-pinned-49g6</guid>
      <description>&lt;p&gt;&lt;code&gt;speech.wav&lt;/code&gt; was the first useful result: a mono PCM file containing &lt;strong&gt;44,160 samples at 24,000 Hz&lt;/strong&gt;. That works out to &lt;strong&gt;1.84 seconds of audio&lt;/strong&gt; for “Hello from Phonon.”&lt;/p&gt;

&lt;p&gt;I generated it with Phonon's public English checkpoint on CPU. Getting that file is a more useful starting point for me than borrowing a leaderboard latency number from a different machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiz2je189ao6boiiz3wu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiz2je189ao6boiiz3wu4.png" alt="Waveform of the generated Hello from Phonon clip, with seconds on the horizontal axis and normalized PCM amplitude on the vertical axis." width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Actual generated samples. The plot shows the resulting audio, not synthesis speed or a speech-quality score. Image by the author.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://panditshivam.github.io/assets/articles/phonon-local-wav/speech.wav" rel="noopener noreferrer"&gt;Listen to the generated WAV&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new Hugging Face write-up revisits Phonon's recent release and its integration options. [1] The model was already available before that article; this walkthrough checks one concrete route from the published tooling to a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pin the tool and the checkpoint
&lt;/h2&gt;

&lt;p&gt;I used &lt;strong&gt;ptts 0.6.0&lt;/strong&gt; and the &lt;strong&gt;phonon-31m-en&lt;/strong&gt; checkpoint at revision &lt;code&gt;92741c5b07d085ff840e26fea8ce43110b87852f&lt;/code&gt;. The runtime's Python package wraps its native implementation; this route does not require installing PyTorch. [2]&lt;/p&gt;

&lt;p&gt;You need &lt;code&gt;uv&lt;/code&gt;, a Python version supported by the published wheel, and a supported CPU platform. The first run needs access to the public model files. In a new working directory, this was my literal command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvx &lt;span class="nt"&gt;--from&lt;/span&gt; &lt;span class="nv"&gt;ptts&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;0.6.0 ptts &lt;span class="nt"&gt;--lang&lt;/span&gt; en &lt;span class="nt"&gt;--device&lt;/span&gt; cpu &lt;span class="nt"&gt;--seed&lt;/span&gt; 13 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--model&lt;/span&gt; hf://gradium/phonon-31m-en@92741c5b07d085ff840e26fea8ce43110b87852f &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Hello from Phonon.'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; speech.wav
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrote speech.wav (1.84s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That final number is the &lt;strong&gt;duration of the generated clip&lt;/strong&gt;. It is not the time the command spent generating it. The model download and loading step also belong outside any claim about time to first audio.&lt;/p&gt;

&lt;p&gt;I used the checkpoint's default voice. There was no voice cloning, account creation or hosted inference request in this check.&lt;/p&gt;

&lt;h2&gt;
  
  
  The language flag does real work
&lt;/h2&gt;

&lt;p&gt;I also tried the command without &lt;code&gt;--lang&lt;/code&gt;. It exited with status &lt;strong&gt;2&lt;/strong&gt; before synthesis and asked for a language.&lt;/p&gt;

&lt;p&gt;The CLI normalizes text before tokenization, so it requires an explicit language or &lt;code&gt;none&lt;/code&gt; to skip that step. Its help lists normalization languages; that list should not be read as a promise that every checkpoint speaks all of them. [2] The checkpoint here is specifically the English model.&lt;/p&gt;

&lt;p&gt;The model card lists &lt;strong&gt;Apache-2.0&lt;/strong&gt; for this English checkpoint. [3] The Phonon family includes other checkpoints with different licences. Check the particular files you plan to ship rather than carrying one model's label across the family.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspect the file before building around it
&lt;/h2&gt;

&lt;p&gt;Here is the standard-library check I ran from the directory containing &lt;code&gt;speech.wav&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wave&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;wave&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;speech.wav&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;channels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getnchannels&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getframerate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;frames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getnframes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;channels:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sample rate:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;frames:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;seconds:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frames&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;channels&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;24000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It printed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;channels: 1
sample rate: 24000
frames: 44160
seconds: 1.84
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also checked that the PCM samples were not all zero. A readable, non-silent WAV confirms the basic output path; it doesn't establish intelligibility, pronunciation quality or a model ranking.&lt;/p&gt;

&lt;p&gt;The first command populated the model cache. I then ran the same text and seed with the cached checkpoint directory passed directly as the model location, and that local-folder run completed too. I did not disable the machine's network, so this is not a network-isolation test.&lt;/p&gt;

&lt;p&gt;Dishant's &lt;a href="https://dev.to/dishant0406/phonon-tts-64-mb-six-milliseconds-one-licence-trap-4ch7"&gt;Phonon TTS: 64 MB, Six Milliseconds, One Licence Trap&lt;/a&gt; raises the useful packaging question: which checkpoint and supporting files are actually being deployed? [4] I kept this run to one public English checkpoint and verified the resulting file. The next integration decision should follow your application: save a whole clip, or consume a stream as audio becomes available. This command checks the file path.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Gradium and Hugging Face contributors, &lt;a href="https://huggingface.co/blog/phonon-tts" rel="noopener noreferrer"&gt;A Closer Look at Phonon TTS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Gradium, &lt;a href="https://github.com/gradium-ai/xn-ptts" rel="noopener noreferrer"&gt;ptts runtime and integration documentation&lt;/a&gt;, and &lt;a href="https://pypi.org/project/ptts/0.6.0/" rel="noopener noreferrer"&gt;ptts 0.6.0 on PyPI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Gradium, &lt;a href="https://huggingface.co/gradium/phonon-31m-en/tree/92741c5b07d085ff840e26fea8ce43110b87852f" rel="noopener noreferrer"&gt;the pinned English checkpoint&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Dishant, &lt;a href="https://dev.to/dishant0406/phonon-tts-64-mb-six-milliseconds-one-licence-trap-4ch7"&gt;Phonon TTS: 64 MB, Six Milliseconds, One Licence Trap&lt;/a&gt;. Third-party latency claims were not reproduced here.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original waveform of the generated clip. Speech was synthesized with Gradium's public Phonon English checkpoint and its default voice from the stated input text; the linked WAV is AI-generated audio. No person's recording was supplied or cloned.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Go JSON v2: when an empty patch stops being empty</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Thu, 05 Nov 2026 17:50:05 +0000</pubDate>
      <link>https://dev.to/panditshivam/go-json-v2-when-an-empty-patch-stops-being-empty-564m</link>
      <guid>https://dev.to/panditshivam/go-json-v2-when-an-empty-patch-stops-being-empty-564m</guid>
      <description>&lt;p&gt;An empty update should be a fairly quiet object. Mine grew two fields after I switched JSON packages.&lt;/p&gt;

&lt;p&gt;With the same Go struct and the same zero value, &lt;code&gt;encoding/json&lt;/code&gt; produced &lt;code&gt;{}&lt;/code&gt;. &lt;code&gt;encoding/json/v2&lt;/code&gt; produced &lt;code&gt;{"count":0,"enabled":false}&lt;/code&gt;. Both calls succeeded.&lt;/p&gt;

&lt;p&gt;For a PATCH-style endpoint where an absent member means “leave this alone,” that is a change in the request's meaning. The serializer hasn't become confused. The old tags are asking a different question under v2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7d066oa4iqp4fsqgk7lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7d066oa4iqp4fsqgk7lw.png" alt="An empty struct with old omission tags becomes an empty object under v1 and count zero plus enabled false under v2. Pointer fields and omitzero preserve absent and explicit-clear states." width="799" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Outputs from the executed Go example. The PATCH interpretation is the explicitly defined example contract, not a rule imposed by JSON itself. Image by the author.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide what an absent field means
&lt;/h2&gt;

&lt;p&gt;Go's new announcement makes &lt;code&gt;encoding/json/v2&lt;/code&gt; generally available in Go 1.27. [1] I used &lt;strong&gt;Go 1.27.3&lt;/strong&gt; for this example and ran both packages in the same program.&lt;/p&gt;

&lt;p&gt;Here is my small update contract: omitted fields leave the stored value unchanged; present fields replace it. So an explicit zero, &lt;code&gt;false&lt;/code&gt;, or empty list must survive serialization.&lt;/p&gt;

&lt;p&gt;The original struct uses plain values and &lt;code&gt;omitempty&lt;/code&gt;. In v1 that option omits the zero number and false Boolean. In v2 it is based on the encoded JSON value: an empty string, array, object or null can be omitted, while zero and false remain present. [2]&lt;/p&gt;

&lt;p&gt;That also means “replace a list with an empty list” needs attention. An &lt;code&gt;omitempty&lt;/code&gt; tag can remove the very empty array the receiver needs to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give presence its own representation
&lt;/h2&gt;

&lt;p&gt;For this contract I use pointers for the scalar fields and &lt;code&gt;omitzero&lt;/code&gt; for all fields. A nil pointer means absent. A non-nil pointer can carry an explicit zero or false. For the slice, nil means absent and a non-nil empty slice means clear the list.&lt;/p&gt;

&lt;p&gt;Save this as &lt;code&gt;patch.go&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="s"&gt;"encoding/json/v2"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;OldPatch&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="s"&gt;`json:"count,omitempty"`&lt;/span&gt;
    &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="s"&gt;`json:"enabled,omitempty"`&lt;/span&gt;
    &lt;span class="n"&gt;Labels&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"labels,omitempty"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Patch&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="s"&gt;`json:"count,omitzero"`&lt;/span&gt;
    &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="s"&gt;`json:"enabled,omitzero"`&lt;/span&gt;
    &lt;span class="n"&gt;Labels&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"labels,omitzero"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"old tags, v1:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OldPatch&lt;/span&gt;&lt;span class="p"&gt;{})))&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"old tags, v2:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OldPatch&lt;/span&gt;&lt;span class="p"&gt;{})))&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"absent, v2:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Patch&lt;/span&gt;&lt;span class="p"&gt;{})))&lt;/span&gt;
    &lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;off&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Patch&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enabled&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;off&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Labels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{}}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"explicit clear, v2:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"explicit clear, v1:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&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;With Go 1.27.3 installed, run &lt;code&gt;go run patch.go&lt;/code&gt;. No external module is needed. My output was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;old tags, v1: {}
old tags, v2: {"count":0,"enabled":false}
absent, v2: {}
explicit clear, v2: {"count":0,"enabled":false,"labels":[]}
explicit clear, v1: {"count":0,"enabled":false,"labels":[]}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important pair is the empty corrected patch and the explicit-clear patch. They now carry different requests. The corrected type also emits the same result through v1 in this check.&lt;/p&gt;

&lt;p&gt;I independently parsed those outputs and applied the declared replace-by-member rule to a synthetic record. The absent patch retained its original values; the explicit patch set the count to zero, disabled the flag and cleared its labels. This is serialization plus a small contract check, not a running HTTP service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the migration close to the API contract
&lt;/h2&gt;

&lt;p&gt;Frank Chu's &lt;a href="https://dev.to/frankchu/7-go-jsonv2-breaks-i-verified-in-go-127-21i3"&gt;7 Go jsonv2 breaks I verified in Go 1.27&lt;/a&gt; covers the wider behavior changes. [3] The omission example deserves a test at your own endpoint boundary because valid JSON can still express the wrong update.&lt;/p&gt;

&lt;p&gt;For this example, I would keep golden outputs for an absent patch, an explicit scalar zero and an empty list. A plain search-and-replace of the import cannot decide those meanings for you.&lt;/p&gt;

&lt;p&gt;This representation has a limit: a single pointer does not distinguish every possible “absent versus explicit null” requirement. If your API gives null a separate meaning, model that presence state explicitly. The example only promises the absent and explicit-value cases shown above. I haven't measured a speedup or audited a production API.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go team, &lt;a href="https://go.dev/blog/jsonv2" rel="noopener noreferrer"&gt;A new Go API for JSON&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Go standard library, &lt;a href="https://pkg.go.dev/encoding/json/v2" rel="noopener noreferrer"&gt;encoding/json/v2 documentation&lt;/a&gt;, including &lt;code&gt;omitempty&lt;/code&gt; and &lt;code&gt;omitzero&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Frank Chu, &lt;a href="https://dev.to/frankchu/7-go-jsonv2-breaks-i-verified-in-go-127-21i3"&gt;7 Go jsonv2 breaks I verified in Go 1.27&lt;/a&gt;. Its performance measurement is not reused here.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original contract diagram drawn from the saved program outputs. The program and synthetic update example are original explanatory material.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>go</category>
      <category>json</category>
      <category>testing</category>
      <category>backend</category>
    </item>
    <item>
      <title>StateBench’s matched traces make a better reading test</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Wed, 04 Nov 2026 15:18:44 +0000</pubDate>
      <link>https://dev.to/panditshivam/statebenchs-matched-traces-make-a-better-reading-test-m8c</link>
      <guid>https://dev.to/panditshivam/statebenchs-matched-traces-make-a-better-reading-test-m8c</guid>
      <description>&lt;p&gt;At one point in my generated StateBench example, &lt;code&gt;g&lt;/code&gt; holds 99 and &lt;code&gt;c&lt;/code&gt; holds 57. Three versions of the next update all leave &lt;code&gt;g&lt;/code&gt; at 57:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;g &amp;lt;- c;
g &amp;lt;- (g + 58) mod 100;
g &amp;lt;- 57;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer agrees. The work needed to get it does not. One line reads another variable, one reads its own previous value, and one supplies the answer directly.&lt;/p&gt;

&lt;p&gt;That is a useful way into Ai2's new StateBench release. Rather than treating every long-context question as the same reading task, it separates different kinds of state updates. [1]&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7tov7qpikd67vxctzvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo7tov7qpikd67vxctzvb.png" alt="Three generated updates leave g at 57: copy c, add 58 modulo 100, or assign 57 directly. The immutable family instead retains the original value 99." width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An actual update from the generated trace family. This is a program-semantics illustration, not a language-model score. Image by the author.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a shared trace
&lt;/h2&gt;

&lt;p&gt;I ran the released generator and inspected four matched samples. The repository calls their families &lt;code&gt;periodic&lt;/code&gt;, &lt;code&gt;solvable&lt;/code&gt;, &lt;code&gt;aperiodic&lt;/code&gt; and &lt;code&gt;r-trivial&lt;/code&gt;. The announcement describes the first two as general-finite and soluble problems respectively. [1][2]&lt;/p&gt;

&lt;p&gt;For the specific preview I used &lt;strong&gt;seed 13&lt;/strong&gt;, &lt;strong&gt;eight ordinary variables&lt;/strong&gt;, and &lt;strong&gt;eight extra assignments&lt;/strong&gt;, without filler. The generated program also initializes a temporary register. That produces &lt;strong&gt;17 assignments&lt;/strong&gt; in each version: nine initializations plus the eight extra steps.&lt;/p&gt;

&lt;p&gt;To reproduce that preview, use Python 3.12 or later and &lt;code&gt;uv&lt;/code&gt;. Check out the source revision first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/allenai/state-bench.git
&lt;span class="nb"&gt;cd &lt;/span&gt;state-bench
git checkout 5b333b8d426638d8825f40efe8a508c20eb85730
uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then generate the four JSON previews:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;family &lt;span class="k"&gt;in &lt;/span&gt;periodic solvable aperiodic r-trivial&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;uv run &lt;span class="nt"&gt;--no-dev&lt;/span&gt; state-bench sample &lt;span class="se"&gt;\&lt;/span&gt;
    configs/experiments/solvable.yaml &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"integer-code-modular--&lt;/span&gt;&lt;span class="nv"&gt;$family&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--seed&lt;/span&gt; 13 &lt;span class="nt"&gt;--num-variables&lt;/span&gt; 8 &lt;span class="nt"&gt;--extra-assignments&lt;/span&gt; 8 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--filler-proportion&lt;/span&gt; 0 &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$family&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used the repository's supported variable count. Asking this configuration for five variables failed validation; its configured counts are 2, 4, 8 and 16. A CLI flag selects a permitted condition here rather than silently rewriting the experiment configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow what the right-hand side reads
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;aperiodic&lt;/code&gt; version, the update states the new value explicitly. To recover the final &lt;code&gt;g&lt;/code&gt;, a reader can find the last assignment to &lt;code&gt;g&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;solvable&lt;/code&gt; version, the update needs the current &lt;code&gt;g&lt;/code&gt;. For this step, &lt;code&gt;(99 + 58) mod 100&lt;/code&gt; is 57. Skipping an earlier update can change the input to a later one.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;periodic&lt;/code&gt; version, &lt;code&gt;g &amp;lt;- c&lt;/code&gt; needs the current value of another register. Earlier changes to &lt;code&gt;c&lt;/code&gt; can now matter to &lt;code&gt;g&lt;/code&gt;. These are copies at assignment time, not persistent aliases: changing &lt;code&gt;c&lt;/code&gt; later does not retroactively change &lt;code&gt;g&lt;/code&gt;. [2]&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;r-trivial&lt;/code&gt; construction replaces later writes with the first value assigned to their target. At this position it writes 99, so that family keeps a different answer. It does not share the changing-state answer just because its assignments appear in the same places.&lt;/p&gt;

&lt;p&gt;For this preview, the final values of &lt;code&gt;a&lt;/code&gt; through &lt;code&gt;h&lt;/code&gt;, followed by &lt;code&gt;TMP&lt;/code&gt;, were:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;periodic:  [16, 75, 99, 1, 48, 28, 57, 23, 28]
solvable:  [16, 75, 99, 1, 48, 28, 57, 23, 28]
aperiodic: [16, 75, 99, 1, 48, 28, 57, 23, 28]
r-trivial: [28, 75, 57, 1, 48, 34, 99, 23, 81]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I independently replayed every canonical assignment with a small interpreter and checked those outputs. The first three families also matched after &lt;strong&gt;every&lt;/strong&gt; assignment in this sample, rather than merely arriving at the same final vector. That is a check of the generator's transformations, not evidence about an LLM's ability to follow them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieval is only part of the question
&lt;/h2&gt;

&lt;p&gt;When I read a memory benchmark result, I want to know whether it tests finding an explicit value or composing updates. A larger input window does not make those operations interchangeable.&lt;/p&gt;

&lt;p&gt;He Fangsheng's &lt;a href="https://dev.to/he_fangsheng_23597e192e87/vector-rag-cant-fix-long-context-state-tracking-33-runs-zero-variance-23e4"&gt;DEV discussion of derived state and retrieval&lt;/a&gt; argues for treating the current state as a separate object. [3] I would keep the claim narrower than “retrieval cannot help”: retrieval can provide relevant updates, but the system still needs to put those updates in order and apply their semantics.&lt;/p&gt;

&lt;p&gt;The matched traces help isolate that distinction. A system can be handed similar-looking programs, the same update positions, and even the same expected output, while the dependency structure changes. Looking only at final answers would hide how each question was constructed.&lt;/p&gt;

&lt;p&gt;Ai2 also evaluates pretrained and frontier models in the release. [1] I did not rerun those evaluations, train a model, or measure accuracy here. The concrete result is smaller: the published generator makes the difference between lookup, self-update and cross-variable dependency visible in an executable example.&lt;/p&gt;

&lt;h2&gt;
  
  
  References and resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ai2, &lt;a href="https://huggingface.co/blog/allenai/statebench" rel="noopener noreferrer"&gt;StateBench: Testing how language models track state changes over long documents&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ai2 contributors, &lt;a href="https://github.com/allenai/state-bench/tree/5b333b8d426638d8825f40efe8a508c20eb85730" rel="noopener noreferrer"&gt;StateBench source at the checked revision&lt;/a&gt;. The repository documents family derivation and eager-copy semantics.&lt;/li&gt;
&lt;li&gt;He Fangsheng, &lt;a href="https://dev.to/he_fangsheng_23597e192e87/vector-rag-cant-fix-long-context-state-tracking-33-runs-zero-variance-23e4"&gt;Vector RAG can't fix long-context state tracking&lt;/a&gt;. Its model measurements were not reproduced for this article.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original assignment diagram based on the generated synthetic traces. StateBench source is Apache-2.0; the figure contains no third-party screenshots or benchmark charts.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>python</category>
      <category>research</category>
    </item>
    <item>
      <title>Two coroutines, one journal: a Restate restart demo</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Wed, 04 Nov 2026 15:17:26 +0000</pubDate>
      <link>https://dev.to/panditshivam/two-coroutines-one-journal-a-restate-restart-demo-46fp</link>
      <guid>https://dev.to/panditshivam/two-coroutines-one-journal-a-restate-restart-demo-46fp</guid>
      <description>&lt;p&gt;Both preparation steps had finished when I stopped the Node process. The Restate server stayed running. After I started the service again, the pending invocation returned &lt;code&gt;["A", "B"]&lt;/code&gt;, and the preparation writes were still present only once each.&lt;/p&gt;

&lt;p&gt;This is the small recovery demo I wanted for Restate's new durable coroutines: two routines with their own steps, an interruption in the middle, and a file that makes the executed effects easy to inspect. There is no language model in this example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fit1na6dbyozopk9hu2wz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fit1na6dbyozopk9hu2wz.png" alt="Two Restate coroutines prepare work, wait on durable timers and finish after a Node worker restart. The server journal stays running. The recorded effect file contains prepare-b, prepare-a, finish-b and finish-a." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Diagram of the completed restart trial. The spacing is schematic, not a latency measurement. Image by the author.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the work inside the routines
&lt;/h2&gt;

&lt;p&gt;Restate's announcement describes generator-based coroutines that let its scheduler control when routines advance. Their I/O can overlap while completion order is recorded for recovery. [1] I used Restate Server &lt;strong&gt;1.8.1&lt;/strong&gt;, Node &lt;strong&gt;22.22.1&lt;/strong&gt;, and both JavaScript packages at &lt;strong&gt;1.18.2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The service writes a short line during preparation, waits on a durable timer, then writes a finish line. A returned value travels through the generator's local variable into the final result.&lt;/p&gt;

&lt;p&gt;In a new package with &lt;code&gt;"type": "module"&lt;/code&gt;, install the matching dependencies:&lt;br&gt;
&lt;/p&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; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; @restatedev/restate-sdk@1.18.2 @restatedev/restate-sdk-gen@1.18.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the service as &lt;code&gt;service.mjs&lt;/code&gt;:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:http2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;appendFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;restate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@restatedev/restate-sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@restatedev/restate-sdk-gen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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="nf"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&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;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;effects.log&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`prepare-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n`&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;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`prepare-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&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;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;`prepared-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&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="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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="nf"&gt;appendFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;effects.log&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`finish-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`finish-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&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="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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;restate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CoroutineDemo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;execute&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="nf"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lane&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&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="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;all&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;b&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;restate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;http2Handler&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12880&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The timer is set to &lt;strong&gt;8,000 milliseconds&lt;/strong&gt; to leave a clear interruption window. It is a demo setting, not a measured overhead result.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gen()&lt;/code&gt; receives a generator factory. &lt;code&gt;spawn()&lt;/code&gt; registers a routine and gives back a task handle; the scheduler advances it when the current routine yields. &lt;code&gt;all()&lt;/code&gt; waits for both handles and returns their values in input order. The package's own README distinguishes these operations and notes that spawned work can be abandoned when the main operation exits; explicitly joining the tasks avoids relying on fire-and-forget behavior. [2]&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the journal outside the worker process
&lt;/h2&gt;

&lt;p&gt;The service is only one part of the setup. It needs a running Restate server and a registered deployment. I used this local server configuration, saved as &lt;code&gt;restate.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="n"&gt;disable-telemetry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;bind-address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:15122"&lt;/span&gt;
&lt;span class="n"&gt;advertised-address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"http://127.0.0.1:15122"&lt;/span&gt;
&lt;span class="n"&gt;rocksdb-total-memory-size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"256 MiB"&lt;/span&gt;
&lt;span class="n"&gt;default-num-partitions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;bind-address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:19070"&lt;/span&gt;

&lt;span class="k"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ingress&lt;/span&gt;&lt;span class="k"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;bind-address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:18080"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing Server 1.8.1 from its official release, start it in one terminal with its own data directory: [3]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;restate-server &lt;span class="nt"&gt;--config-file&lt;/span&gt; restate.toml &lt;span class="nt"&gt;--base-dir&lt;/span&gt; ./restate-data &lt;span class="nt"&gt;--no-logo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start &lt;code&gt;node service.mjs&lt;/code&gt; in another terminal. Once it is listening, register that endpoint and invoke it through the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--fail-with-body&lt;/span&gt; &lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:19070/deployments &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"uri":"http://127.0.0.1:12880"}'&lt;/span&gt;
curl &lt;span class="nt"&gt;--fail-with-body&lt;/span&gt; &lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:18080/CoroutineDemo/run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'null'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final command returned &lt;code&gt;["A", "B"]&lt;/code&gt; in the uninterrupted check. Calling the Node endpoint directly would skip the server that owns this journal.&lt;/p&gt;

&lt;p&gt;I first let an invocation finish without interruption. It returned &lt;code&gt;["A", "B"]&lt;/code&gt; and wrote each preparation and finish line once. That was the control before introducing a restart.&lt;/p&gt;

&lt;p&gt;For the restart trial, I waited until &lt;strong&gt;both &lt;code&gt;prepared-...&lt;/code&gt; messages&lt;/strong&gt; appeared. These messages come after the corresponding &lt;code&gt;yield* run(...)&lt;/code&gt; has resolved. I then killed only the Node service process, started it again on the same port, and left the original request waiting for its response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the effects, not just the replay messages
&lt;/h2&gt;

&lt;p&gt;The restarted worker logged that it was replaying the invocation. It also printed &lt;code&gt;prepared-b&lt;/code&gt; and &lt;code&gt;prepared-a&lt;/code&gt; again: those diagnostic statements are outside the durable closures, so seeing them again is expected.&lt;/p&gt;

&lt;p&gt;The file tells a more specific story. Immediately before the crash it held:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prepare-b
prepare-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After recovery and completion it held:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prepare-b
prepare-a
finish-b
finish-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response was &lt;code&gt;["A", "B"]&lt;/code&gt;. The order of returned values follows &lt;code&gt;all([a, b])&lt;/code&gt;; it need not be the order in which the effects finish. In the uninterrupted control, the finish lines appeared in the opposite order.&lt;/p&gt;

&lt;p&gt;That is the useful division in this example: normal JavaScript flow is reconstructed, while acknowledged durable steps supply their recorded results. The local &lt;code&gt;value&lt;/code&gt; variable is rebuilt through replay; it is not a heap snapshot copied out of the crashed process.&lt;/p&gt;

&lt;p&gt;There is still a boundary around external side effects. This trial interrupted the worker &lt;strong&gt;after&lt;/strong&gt; the preparation results had resolved. It did not kill the process between a file append and acknowledgement of that step. The append itself has no idempotency key, so I would not infer exactly-once writes for every possible crash point.&lt;/p&gt;

&lt;p&gt;The Diagrid team's &lt;a href="https://dev.to/diagrid/understanding-at-least-once-execution-and-why-it-matters-for-workflow-developers-3nen"&gt;explanation of at-least-once workflow execution&lt;/a&gt; describes that effect-before-recording window in Dapr. [4] It is a useful question to bring to any recovery demo: which side of the acknowledgement did the failure happen on?&lt;/p&gt;

&lt;p&gt;Here, the server was never restarted, no remote tool or LLM was called, and no throughput benchmark was run. The completed check is service-process recovery with two joined coroutines and inspectable effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  References and resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Igal Shilman, Stephan Ewen and Giselle van Dongen, &lt;a href="https://restate.dev/blog/durable_coroutines" rel="noopener noreferrer"&gt;Durable Coroutines for TypeScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Restate contributors, &lt;a href="https://www.npmjs.com/package/@restatedev/restate-sdk-gen/v/1.18.2" rel="noopener noreferrer"&gt;generator SDK package and API documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Restate contributors, &lt;a href="https://github.com/restatedev/restate/releases/tag/v1.8.1" rel="noopener noreferrer"&gt;Restate Server 1.8.1&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Diagrid, &lt;a href="https://dev.to/diagrid/understanding-at-least-once-execution-and-why-it-matters-for-workflow-developers-3nen"&gt;Understanding At-Least-Once Execution and Why It Matters for Workflow &amp;amp; Agent Developers&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original recovery diagram based on the executed local service and its effect files. The service example is original; Restate dependencies retain their upstream licences.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Updating Rustup 1.29.3 while keeping the compiler fixed</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Wed, 04 Nov 2026 15:17:11 +0000</pubDate>
      <link>https://dev.to/panditshivam/updating-rustup-1293-while-keeping-the-compiler-fixed-3p5n</link>
      <guid>https://dev.to/panditshivam/updating-rustup-1293-while-keeping-the-compiler-fixed-3p5n</guid>
      <description>&lt;p&gt;The toolchain manager and the compiler have separate version numbers. I updated an isolated Rustup installation from &lt;strong&gt;1.29.2 to 1.29.3&lt;/strong&gt;, kept its linked compiler at &lt;strong&gt;1.99.1&lt;/strong&gt;, then compiled and ran a small program through that same toolchain.&lt;/p&gt;

&lt;p&gt;That gives me a useful way to handle this patch: update the manager that selects the tools, then check which compiler a project actually uses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhuihw13fuosbaeqsnc7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhuihw13fuosbaeqsnc7z.png" alt="Two version tracks: Rustup moves from 1.29.2 to 1.29.3, while the linked Rust compiler stays at 1.99.1. The sample program still prints sum equals 10." width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Recorded versions from the isolated update and the compiled sample. Image by the author.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the patch changes
&lt;/h2&gt;

&lt;p&gt;The Rustup team reports two regression fixes in 1.29.3: an illegal-instruction failure on certain x86_64 CPUs without SSE4.1, and an unsupported-lock error on Solaris. Those are upstream release claims; this walkthrough does not reproduce either hardware-specific failure. [1]&lt;/p&gt;

&lt;p&gt;If you already have Rustup, the release instructions say to stop programs using it and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup self update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The word &lt;code&gt;self&lt;/code&gt; matters. This updates Rustup itself. It is different from asking Rustup to update installed Rust toolchains with &lt;code&gt;rustup update&lt;/code&gt;. That broader command can also update the manager. [1]&lt;/p&gt;

&lt;h2&gt;
  
  
  Check both sides of the selection
&lt;/h2&gt;

&lt;p&gt;I used separate &lt;code&gt;CARGO_HOME&lt;/code&gt; and &lt;code&gt;RUSTUP_HOME&lt;/code&gt; directories for the trial, with shell startup files left alone. Rustup documents these locations as configurable. [2] I linked an existing compiler under the custom name &lt;code&gt;pinned-local&lt;/code&gt;; I did not download a fresh compiler or replace the usual installation.&lt;/p&gt;

&lt;p&gt;Here is the version ledger:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rustup&lt;/td&gt;
&lt;td&gt;1.29.2&lt;/td&gt;
&lt;td&gt;1.29.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linked Rust compiler&lt;/td&gt;
&lt;td&gt;1.99.1&lt;/td&gt;
&lt;td&gt;1.99.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To check the selection in that shell, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup &lt;span class="nt"&gt;--version&lt;/span&gt;
rustup show active-toolchain
rustc &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The active toolchain was &lt;code&gt;pinned-local (default)&lt;/code&gt;. Keep the complete version output when troubleshooting; the table above extracts the version fields so the two components are easy to compare.&lt;/p&gt;

&lt;p&gt;Rustup's &lt;code&gt;rustc&lt;/code&gt; and &lt;code&gt;cargo&lt;/code&gt; commands are proxies: they pass the invocation to a selected toolchain. Updating that routing program does not, by itself, request a different compiler. [3]&lt;/p&gt;

&lt;p&gt;There is one practical prerequisite here: the shell must be reaching those proxies. A &lt;code&gt;rustc&lt;/code&gt; supplied by another installation can produce a perfectly valid version line while bypassing the Rustup selection you intended. Mayur Kumbhar's &lt;a href="https://dev.to/themayurkumbhar/rust-essentials-how-to-set-up-your-development-environment-6f9"&gt;environment setup walkthrough&lt;/a&gt; makes the related point that verifying the compiler and Cargo in a fresh shell is part of installation, rather than an optional last step. [4]&lt;/p&gt;

&lt;h2&gt;
  
  
  Compile through the named toolchain
&lt;/h2&gt;

&lt;p&gt;For a small end-to-end check, I saved this as &lt;code&gt;demo.rs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2_u32&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sum={}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;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;Then I selected the linked toolchain explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustup run pinned-local rustc demo.rs &lt;span class="nt"&gt;-o&lt;/span&gt; demo
./demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The executable printed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sum=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pinned-local&lt;/code&gt; is the custom name from this trial, not a toolchain Rustup ships. Use a toolchain you have actually installed or linked when adapting the command.&lt;/p&gt;

&lt;p&gt;This is a narrow update check: manager version, compiler selection, compilation and program output. It does not test all Cargo dependencies or establish that a project will build on every target. For a real project, keep its selected compiler visible alongside the manager version. “Rust updated” hides a distinction that the tools themselves already let you inspect.&lt;/p&gt;

&lt;h2&gt;
  
  
  References and resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The Rustup Team, &lt;a href="https://blog.rust-lang.org/2026/11/03/Rustup-1.29.3/" rel="noopener noreferrer"&gt;Rustup 1.29.3 release announcement&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Rustup Book, &lt;a href="https://rust-lang.github.io/rustup/installation/index.html" rel="noopener noreferrer"&gt;installation locations and environment variables&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Rustup Book, &lt;a href="https://rust-lang.github.io/rustup/concepts/index.html" rel="noopener noreferrer"&gt;how Rustup and its proxies work&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Mayur Kumbhar, &lt;a href="https://dev.to/themayurkumbhar/rust-essentials-how-to-set-up-your-development-environment-6f9"&gt;Rust Essentials: How to Set Up Your Development Environment&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original version-track diagram from the recorded update and compile check. No third-party image assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>What counts as feedback in weight-space programming?</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Tue, 03 Nov 2026 12:38:45 +0000</pubDate>
      <link>https://dev.to/panditshivam/what-counts-as-feedback-in-weight-space-programming-5gc4</link>
      <guid>https://dev.to/panditshivam/what-counts-as-feedback-in-weight-space-programming-5gc4</guid>
      <description>&lt;p&gt;What would convince me that an LLM can make a useful edit to another model's weights?&lt;/p&gt;

&lt;p&gt;I would start by asking what it was allowed to observe. Reading numbers, running a network, and receiving scored practice answers give an editor different kinds of evidence. That distinction is a good way into the new weight-space programming results from Rikiya Takehi, Jayden Teoh, Alex Zhang and Omar Khattab. [1]&lt;/p&gt;

&lt;p&gt;The authors report GPT-6 Astra directly reading and writing neural-network weights, with gradient-based training forbidden. Their experiments use different permissions: some are tool-free; others allow Python analysis or behavioral feedback. The Qwen3.5-0.8B math result belongs to the latter group. Their blog reports MATH-500 moving from 7.9% to 48.1% after a targeted edit, alongside reduced reasoning loops. Those are the authors' results; I have not run Astra or Qwen for this article. [1]&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow one feedback loop
&lt;/h2&gt;

&lt;p&gt;For the Qwen experiment, the released setup gives the editor a persistent Python kernel, practice problems, and a separate forward-pass service. It can propose an edit, ask the service to run the original or edited model, inspect the returned information, and revise. Gradient descent remains prohibited throughout. [2]&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcp1cvm72majn54y1kvvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcp1cvm72majn54y1kvvq.png" alt="An editor writes candidate weights, a service runs practice inputs, and returned behavior informs the next edit; held-out scoring sits outside that loop." width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original interpretation of the released experiment protocol. This is a process diagram, not a model run or a performance chart.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That gives two independent questions: &lt;strong&gt;how are the weights changed&lt;/strong&gt;, and &lt;strong&gt;what evidence guides the change&lt;/strong&gt;? An edit can avoid gradients while still being guided by the target model's behavior. Calling that feedback-driven does not contradict the gradient restriction.&lt;/p&gt;

&lt;p&gt;The authors' repository separates the model's built-in tool access from their own harness. It describes model-written Python being executed in a sandbox, with output returned in the following turn. [3] “Built-in tools disabled” therefore needs that context; it does not mean the surrounding experiment supplied no tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the unit beside the budget
&lt;/h2&gt;

&lt;p&gt;The Qwen setup defines one forward pass as a batched request: generation can contain up to 512 practice problems, or a teacher-forced request can inspect up to 1,024 texts. Those are limits, not counts of what every request used. [2]&lt;/p&gt;

&lt;p&gt;I parsed the released 50-pass run's state record. It records 50 successful passes, 80 Python runs and 158 turns. Its first saved generation response contains 96 generations, with 85 cut at the token limit. This is a check of published records, not an independent reproduction of the model behavior. [4]&lt;/p&gt;

&lt;p&gt;So “50 passes” is not “50 answers,” and it is not a complete compute budget. Batch size, generated length, editor inference and analysis work all affect what was available to find the edit. A fair replication needs to preserve those resources, not just the number in the column heading.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would conclude from this
&lt;/h2&gt;

&lt;p&gt;The result is interesting as a demonstration of an editor using explicit access to another network's internals. The scope of each demonstration depends on its allowed observations. I would keep those permissions attached whenever comparing it with a different editing method.&lt;/p&gt;

&lt;p&gt;I would also separate two replication questions. Can someone rebuild the released edited checkpoint and check its behavior? Can a fresh editor session discover a similarly useful edit under the same constraints? Success at the first question does not by itself establish the second.&lt;/p&gt;

&lt;p&gt;Frank Chu's &lt;a href="https://dev.to/frankchu/79-to-481-llm-rewrote-qwen-weights-no-training-2aec"&gt;DEV breakdown&lt;/a&gt; focuses on the looping explanation and the reported Gemma follow-up. [5] My emphasis here is the surrounding feedback contract. It lets a reader appreciate the result while keeping the experiment specific enough to compare and rerun.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Rikiya Takehi, Jayden Teoh, Alex Zhang and Omar Khattab, &lt;a href="https://rikiyat.github.io/blog/weight-space-programming/" rel="noopener noreferrer"&gt;Sparks of Weight-Space Programming&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The authors, &lt;a href="https://github.com/RikiyaT/lm_understand-logs/blob/main/exp8_math/README.md" rel="noopener noreferrer"&gt;Experiment 8 setup and run mapping&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The authors, &lt;a href="https://github.com/RikiyaT/lm_understand-logs" rel="noopener noreferrer"&gt;released logs and harness description&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The authors, &lt;a href="https://github.com/RikiyaT/lm_understand-logs/blob/main/exp8_math/runs/p50c/state.json" rel="noopener noreferrer"&gt;50-pass state record&lt;/a&gt; and &lt;a href="https://github.com/RikiyaT/lm_understand-logs/blob/main/exp8_math/runs/p50c/requests/fwd_1.done.json" rel="noopener noreferrer"&gt;first generation feedback&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Frank Chu, &lt;a href="https://dev.to/frankchu/79-to-481-llm-rewrote-qwen-weights-no-training-2aec"&gt;7.9% to 48.1%: LLM rewrote Qwen weights, no training&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original process diagram based on the authors' released protocol and records. Logs and data are released under CC BY 4.0; scripts under MIT. [3]&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>llm</category>
      <category>research</category>
    </item>
    <item>
      <title>Defining revenue for an SQL agent, one row at a time</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Tue, 03 Nov 2026 12:38:23 +0000</pubDate>
      <link>https://dev.to/panditshivam/defining-revenue-for-an-sql-agent-one-row-at-a-time-a4h</link>
      <guid>https://dev.to/panditshivam/defining-revenue-for-an-sql-agent-one-row-at-a-time-a4h</guid>
      <description>&lt;p&gt;Before an agent writes a revenue query, I want one sentence settled: what does one row of revenue represent?&lt;/p&gt;

&lt;p&gt;An order? An item? A paid invoice? Those choices change the calculation even when every table name and join key is correct. NVIDIA's Auto Ontology puts business definitions and relationships into the context supplied to agents. Its repository describes a catalog and ontology layer, query validation, provenance, and interfaces through MCP, CLI and API. [1] The useful question for me is what a definition must say to make a concrete query checkable.&lt;/p&gt;

&lt;p&gt;Here is a deliberately small example, using synthetic integer amounts rather than a real business dataset. It runs in Python's standard-library SQLite. I am not running NVIDIA's stack or evaluating an LLM here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two orders, three joined rows
&lt;/h2&gt;

&lt;p&gt;The metric for this example is &lt;strong&gt;the sum of paid order amounts, counting each order once&lt;/strong&gt;. That last phrase specifies the &lt;em&gt;grain&lt;/em&gt;: the entity one contribution belongs to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:memory:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executescript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
CREATE TABLE orders(id INTEGER PRIMARY KEY, status TEXT, amount INTEGER);
CREATE TABLE items(order_id INTEGER, sku TEXT);
INSERT INTO orders VALUES
  (1, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, 100), (2, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, 100), (3, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cancelled&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, 500);
INSERT INTO items VALUES
  (1, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;), (1, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;), (2, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;), (3, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;D&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="n"&gt;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;joined&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT SUM(o.amount) FROM orders o JOIN items i ON o.id=i.order_id WHERE o.status=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;distinct_amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT SUM(DISTINCT o.amount) FROM orders o JOIN items i ON o.id=i.order_id WHERE o.status=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order_grain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT COALESCE(SUM(amount), 0) FROM orders WHERE status=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paid&lt;/span&gt;&lt;span class="sh"&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;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetchone&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;joined 300
distinct_amount 100
order_grain 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbv23nii8c2s0to30ndsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbv23nii8c2s0to30ndsu.png" alt="Two equal-value paid orders contribute 200 at order grain, 300 after joining their three items, and 100 with distinct amounts." width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original diagram of the executed synthetic fixture. Amounts have arbitrary units; the example defines its own metric.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Order 1 has two items, so the join repeats its amount. The joined sum is 100 + 100 + 100. Order 2 is perfectly real, but &lt;code&gt;SUM(DISTINCT amount)&lt;/code&gt; collapses its 100 together with the other order's 100. Distinct &lt;strong&gt;values&lt;/strong&gt; are not distinct &lt;strong&gt;orders&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The direct query stays at order grain. &lt;code&gt;COALESCE&lt;/code&gt; adds another explicit choice: return zero when no paid orders exist. Without it, &lt;code&gt;SUM&lt;/code&gt; over no eligible rows returns NULL. I checked the empty-eligible-set case as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  When an item condition is required
&lt;/h2&gt;

&lt;p&gt;Suppose the question means paid orders with at least one item. There is no need to multiply order rows just to check that an item exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&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="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'paid'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also returned 200. It would exclude an itemless paid order, while the direct order query would include it. Which one is correct depends on the agreed question. Adding an item-category filter would make that scope decision even more visible.&lt;/p&gt;

&lt;p&gt;A definition supplied to an agent should therefore include the grain, eligible status, join behavior and empty-set behavior. This fixture can act as a compact regression case: two different orders share an amount, and one order has multiple items. Both details earn their place.&lt;/p&gt;

&lt;p&gt;Michael Tuszynski makes the related governance point in &lt;a href="https://dev.to/michaeltuszynski/an-ontology-your-ai-generated-is-a-guess-with-a-schema-22d5"&gt;“An Ontology Your AI Generated Is a Guess With a Schema”&lt;/a&gt;: an inferred definition still needs an accountable owner. In its discussion, ontomato also asks for ownership of grain and access to the source rows being counted. [2] A graph can store the chosen meaning; generating the graph does not settle that choice.&lt;/p&gt;

&lt;p&gt;For an agent workflow, I would keep this expected answer beside the metric definition. Checking that SQL executes is one check. Checking which entities contributed to the answer is another.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;NVIDIA, &lt;a href="https://github.com/NVIDIA/auto-ontology" rel="noopener noreferrer"&gt;Auto Ontology&lt;/a&gt;. This article examines a definition problem; it makes no benchmark claim about that project.&lt;/li&gt;
&lt;li&gt;Michael Tuszynski, &lt;a href="https://dev.to/michaeltuszynski/an-ontology-your-ai-generated-is-a-guess-with-a-schema-22d5"&gt;An Ontology Your AI Generated Is a Guess With a Schema&lt;/a&gt;, including ontomato's comment.&lt;/li&gt;
&lt;li&gt;SQLite, &lt;a href="https://www.sqlite.org/lang_aggfunc.html" rel="noopener noreferrer"&gt;aggregate functions&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original diagram from the executed SQLite fixture; no third-party image assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>ai</category>
      <category>python</category>
    </item>
    <item>
      <title>A small temperature alarm in Toit 2.0</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Tue, 03 Nov 2026 12:38:13 +0000</pubDate>
      <link>https://dev.to/panditshivam/a-small-temperature-alarm-in-toit-20-41fk</link>
      <guid>https://dev.to/panditshivam/a-small-temperature-alarm-in-toit-20-41fk</guid>
      <description>&lt;p&gt;A temperature alarm needs a little memory. Switch it on at 30°C, keep it on while the reading drifts down, and switch it off at 27°C. That gap stops a sequence like 30, 29, 30, 29 from repeatedly changing the alarm state.&lt;/p&gt;

&lt;p&gt;I used that small task to try Toit 2.0. The release is a useful excuse to look beyond blinking an LED: the same language also runs host scripts, so the decision logic can be exercised before connecting a sensor. [1][2]&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the state you want
&lt;/h2&gt;

&lt;p&gt;There are two states, on and off. A reading at or above 30 sets the state to on. A reading at or below 27 sets it to off. Everything between those limits leaves it alone. This is hysteresis: the current reading does not completely determine the output; the previous state matters too.&lt;/p&gt;

&lt;p&gt;The initial state is part of the design. In this example it is off, so starting at 29°C leaves the alarm off. Arriving at the same temperature after a 30°C reading leaves it on. Neither case is an accident.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpd0y19tppzw4uj2pgx1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpd0y19tppzw4uj2pgx1n.png" alt="Synthetic temperature trace with an alarm turning on at 30 degrees, holding through 29, and turning off at 27." width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original plot from the executed synthetic sequence. Sample positions are ordered readings, not elapsed seconds.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the whole program
&lt;/h2&gt;

&lt;p&gt;Get the archive that matches your platform from the &lt;a href="https://github.com/toitlang/toit/releases/tag/v2.0.0" rel="noopener noreferrer"&gt;official v2.0.0 release&lt;/a&gt;, extract it, and put its &lt;code&gt;bin&lt;/code&gt; directory on your PATH. Check the selected runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;toit &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mine returned &lt;code&gt;v2.0.0&lt;/code&gt;. Save this as &lt;code&gt;sensor.toit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main:
  readings := [28, 30, 29, 30, 29, 27, 29, 31]
  alarm := false
  readings.do: |temperature|
    if temperature &amp;gt;= 30:
      alarm = true
    else if temperature &amp;lt;= 27:
      alarm = false
    print "$temperature C: $alarm"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then analyze and execute it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;toit analyze sensor.toit
toit run sensor.toit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The analyzer completed successfully. The program printed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;28 C: false
30 C: true
29 C: true
30 C: true
29 C: true
27 C: false
29 C: false
31 C: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax takes a moment to read if you normally use Python. &lt;code&gt;:=&lt;/code&gt; introduces a local variable; &lt;code&gt;=&lt;/code&gt; changes it. &lt;code&gt;readings.do:&lt;/code&gt; calls a block for each value, and &lt;code&gt;|temperature|&lt;/code&gt; names the block's parameter. The string interpolates both variables. [3]&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing assignment does the work
&lt;/h2&gt;

&lt;p&gt;There is deliberately no final &lt;code&gt;else&lt;/code&gt;. At 28 or 29, the program does not assign to &lt;code&gt;alarm&lt;/code&gt;, which preserves the previous state. Replacing that block with &lt;code&gt;alarm = temperature &amp;gt;= 30&lt;/code&gt; would throw the memory away.&lt;/p&gt;

&lt;p&gt;For this exact sequence, including the initial off state, the single-threshold rule changes state five times. The hysteresis rule changes it three times. Those are properties of this synthetic input, not measurements of a physical sensor or proof that these thresholds suit a device.&lt;/p&gt;

&lt;p&gt;I also ran separate inputs for an empty list, each exact threshold, a starting value inside the gap, a descending sequence, and repeated boundary readings. They behaved as specified. A real device still needs decisions about missing readings, units, startup behavior and what should happen if its process restarts.&lt;/p&gt;

&lt;p&gt;Toit 2.0's announcement includes a peripheral API change that accepts pin numbers directly. That is relevant when taking the next step onto supported hardware, but this program uses no GPIO, board or sensor. [1] It is a small, completed host-side example you can change without wiring anything first.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Florian Loitsch, &lt;a href="https://toit.io/blog/toit-v2-0-0/" rel="noopener noreferrer"&gt;Toit v2.0.0&lt;/a&gt; and the &lt;a href="https://github.com/toitlang/toit/releases/tag/v2.0.0" rel="noopener noreferrer"&gt;official release&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Toit contributors, &lt;a href="https://docs.toit.io/language/" rel="noopener noreferrer"&gt;Learn Toit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Toit contributors, &lt;a href="https://github.com/toitlang/toit/tree/v2.0.0" rel="noopener noreferrer"&gt;language source and standard library&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original chart made from the synthetic program output; no third-party image assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>iot</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The smaller token bill can buy fewer working builds</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Mon, 02 Nov 2026 11:35:58 +0000</pubDate>
      <link>https://dev.to/panditshivam/the-smaller-token-bill-can-buy-fewer-working-builds-13h1</link>
      <guid>https://dev.to/panditshivam/the-smaller-token-bill-can-buy-fewer-working-builds-13h1</guid>
      <description>&lt;p&gt;A failed build can be wonderfully economical. It just has the small inconvenience of not working. 🫠&lt;/p&gt;

&lt;p&gt;That sounds obvious until a chart sorts coding agents by tokens per attempt. A workflow can win that chart while producing fewer usable results.&lt;/p&gt;

&lt;p&gt;I made a tiny ledger to show the accounting change. &lt;strong&gt;Every number below is synthetic.&lt;/strong&gt; These are invented workflows named &lt;code&gt;lean&lt;/code&gt; and &lt;code&gt;steady&lt;/code&gt;, not measurements of models or frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;The starting point was the renewed discussion around Nolan Lawson's JavaScript framework benchmark. His setup asks agents to build an app, checks conformance, and reports several dimensions, including tokens and resulting app quality. It also reports variation and failed runs.[1]&lt;/p&gt;

&lt;p&gt;That's a useful direction: inspect the finished thing as well as the effort spent making it. My example isn't a rerun of his benchmark or a correction to his framework rankings. It isolates one question for anyone building their own evaluation: &lt;strong&gt;what happens to the tokens spent on failed attempts?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I wrote a Python summary that retains those attempts and reports both the per-attempt median and the total tokens divided by accepted results. 🧮&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpi8qjlt3h6tr6vu1lm8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpi8qjlt3h6tr6vu1lm8c.png" alt="Synthetic workflows reverse order depending on the denominator. Lean uses a median 1,000 tokens per attempt but 3,000 per accepted result; steady uses 1,600 for both. Lean accepts one of three attempts, while steady accepts three of three." width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Computed illustration from the synthetic records below. No model calls or framework comparison were run.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;The fixture contains the same number of attempts for each workflow:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Synthetic workflow&lt;/th&gt;
&lt;th&gt;Token units per attempt&lt;/th&gt;
&lt;th&gt;Accepted results&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,000; 1,000; 1,000&lt;/td&gt;
&lt;td&gt;1 of 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;steady&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,600; 1,600; 1,600&lt;/td&gt;
&lt;td&gt;3 of 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For this illustration, each row represents a complete attempt, including its repair work. All rows use the same token-unit definition. ✅&lt;/p&gt;

&lt;p&gt;Run this with Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;statistics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;median&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="c1"&gt;# Synthetic attempts: (workflow, token units, acceptance passed).
# Each row includes the complete attempt, including repair work.
&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steady&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steady&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steady&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;workflow&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attempts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;median_tokens_per_attempt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens_per_accepted_result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;accepted&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&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="n"&gt;result&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The useful part of the output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lean:   median per attempt = 1000; total / accepted = 3000
steady: median per attempt = 1600; total / accepted = 1600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The arithmetic is plain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lean:   (1000 + 1000 + 1000) / 1 = 3000
steady: (1600 + 1600 + 1600) / 3 = 1600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I silently drop the failed rows, &lt;code&gt;lean&lt;/code&gt; looks like it spent only 1,000 tokens per accepted result. That discards the effort that produced no accepted output. The ledger keeps it.&lt;/p&gt;

&lt;p&gt;💡 These summaries answer different questions. The median describes a typical attempt. Total divided by accepted results describes the observed aggregate token effort per acceptance in this fixture. Neither replaces the pass count.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if nothing passes?
&lt;/h3&gt;

&lt;p&gt;I also checked a group containing a failed attempt and no accepted result. The summary returns &lt;code&gt;None&lt;/code&gt;, serialized as &lt;code&gt;null&lt;/code&gt;, for tokens per accepted result.&lt;/p&gt;

&lt;p&gt;Zero would be a misleading result: it would make total failure look exceptionally efficient. There was no accepted result to divide by.&lt;/p&gt;

&lt;h3&gt;
  
  
  The acceptance check is part of the measurement
&lt;/h3&gt;

&lt;p&gt;Before collecting your own records, decide what “accepted” means for the task. Does the app boot? Does the requested behavior work? Are important error cases checked? Keep that grader outside the agent's editable output.&lt;/p&gt;

&lt;p&gt;The DEV write-up from the Kumiko team is a useful companion: their isolated agent evaluation first exposed problems in their own grader and documentation.[2] A pass count only helps if the acceptance check itself is doing the intended job. 🔍&lt;/p&gt;

&lt;p&gt;For real comparisons, keep the task set, model settings, versions and stopping rules matched. Save failed and timed-out attempts, and record whether setup or repair effort is included. If an attempt has missing usage, mark it missing rather than turning it into zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Partner Technologies
&lt;/h2&gt;

&lt;p&gt;This example uses Python's standard library. It doesn't use a model provider or sponsor integration.&lt;/p&gt;

&lt;p&gt;The limit is deliberate: this is an accounting demonstration, not evidence that one coding workflow beats another. Token counts also aren't a billing total. Cached input, uncached input and output can have different prices; preserve those buckets when accounting for actual usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackathon Experience
&lt;/h2&gt;

&lt;p&gt;I built this as a standalone local example. It isn't an MLH event project or competition entry.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://nolanlawson.com/2026/10/28/the-ai-cost-of-javascript-frameworks/" rel="noopener noreferrer"&gt;Nolan Lawson — The AI cost of JavaScript frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/marc_kumiko/our-framework-docs-three-models-isolated-agents-99-seconds-50-minutes-and-a-timeout-4jlf"&gt;@marc_kumiko — Our framework docs, three models, isolated agents: 99 seconds, 50 minutes, and a timeout&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original chart computed from the synthetic ledger. No external benchmark figure is reused.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My parser read past the input. AddressSanitizer stayed quiet.</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Mon, 02 Nov 2026 11:35:14 +0000</pubDate>
      <link>https://dev.to/panditshivam/my-parser-read-past-the-input-addresssanitizer-stayed-quiet-4mbi</link>
      <guid>https://dev.to/panditshivam/my-parser-read-past-the-input-addresssanitizer-stayed-quiet-4mbi</guid>
      <description>&lt;p&gt;I gave a deliberately broken parser three bytes. It read byte four. AddressSanitizer said nothing.&lt;/p&gt;

&lt;p&gt;Then I changed the allocation around the input. Same parser, same three bytes, same compiler flags: &lt;strong&gt;heap-buffer-overflow&lt;/strong&gt;. There it was. 🧪&lt;/p&gt;

&lt;p&gt;The bug hadn't appeared between runs. My first test had given it somewhere comfortable to hide.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I made a small C reproducer for a fuzz-harness trap: &lt;strong&gt;the length of a test case can be smaller than the memory holding it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Chris Wellons describes this in his AFL++ guide, which is circulating again in the fuzzing discussion. It's an older guide, not a new AFL++ release. The useful detail is the warning about passing a reusable input buffer straight into a target.[1]&lt;/p&gt;

&lt;p&gt;A fuzzer's harness is the bit of code that hands generated inputs to the program. If it hands over a short input inside a larger allocation, an invalid read relative to the input can still touch allocated memory.&lt;/p&gt;

&lt;p&gt;AddressSanitizer, or ASan, instruments memory accesses to catch errors such as heap overflows.[2] It doesn't automatically know the meaning of every length argument in your API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xamhao7au031so95zo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xamhao7au031so95zo9.png" alt="The same three-byte input occupies either a 64-byte allocation or an exact three-byte allocation. Reading index three stays inside the first allocation but reaches the poisoned boundary of the second." width="799" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original diagram of the executed example. The wider buffer is a synthetic stand-in for reusable backing storage.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Here's the complete intentionally broken program. Save it as &lt;code&gt;boundary.c&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;observed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;__attribute__&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;noinline&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;observed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="cm"&gt;/* Deliberate bug: first byte past logical input. */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&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="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&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="s"&gt;"exact"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&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="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ABC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"returned without an ASan report"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;volatile&lt;/code&gt; destination keeps the read observable. The parser is deliberately wrong: for a nonempty input, the last valid index is &lt;code&gt;size - 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Compile it with Clang and its ASan runtime available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clang &lt;span class="nt"&gt;-O1&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fsanitize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;address &lt;span class="nt"&gt;-fno-omit-frame-pointer&lt;/span&gt; boundary.c &lt;span class="nt"&gt;-o&lt;/span&gt; boundary
./boundary shared
./boundary exact
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command to run the program printed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returned without an ASan report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact-size version exited with an ASan &lt;code&gt;heap-buffer-overflow&lt;/code&gt; report. ✅&lt;/p&gt;

&lt;p&gt;Both inputs contain &lt;code&gt;ABC&lt;/code&gt;, with logical length three. The first allocation has room for 64 bytes; the second has room for three. Reading &lt;code&gt;data[3]&lt;/code&gt; violates the parser's input contract in both runs, but only crosses the allocated region in the second.&lt;/p&gt;

&lt;p&gt;Zero-filling the larger buffer makes this example repeatable. &lt;strong&gt;The extra capacity hides the boundary violation; the zeros aren't a safety check.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Change the harness and fix the parser
&lt;/h3&gt;

&lt;p&gt;For this kind of harness, a useful check is to copy the current input into an allocation sized to that input before calling the target. Handle allocation failure and the target's empty-input contract explicitly. If the API expects a terminating zero, its contract also needs space for that byte.&lt;/p&gt;

&lt;p&gt;That makes the allocation boundary match the boundary you want ASan to observe. It doesn't repair the target.&lt;/p&gt;

&lt;p&gt;The actual fix in this example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;observed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I compiled that version with the same sanitizer flags. The shared-buffer, exact-size and empty-input cases all returned successfully.&lt;/p&gt;

&lt;p&gt;⚠️ A quiet sanitizer run is evidence about the accesses it could check. It isn't proof that the program respected your logical input length.&lt;/p&gt;

&lt;p&gt;A second harness check is worth borrowing from a DEV postmortem by &lt;a class="mentioned-user" href="https://dev.to/malwaredante"&gt;@malwaredante&lt;/a&gt;: verify that generated inputs reach the intended parser at all. Their mutator selected a different parser while coverage continued growing.[3] Buffer boundaries and target selection are separate ways for a busy test run to miss its purpose. 🔍&lt;/p&gt;

&lt;h2&gt;
  
  
  Partner Technologies
&lt;/h2&gt;

&lt;p&gt;This demo uses C, Clang and AddressSanitizer. The AFL++ documentation supplies context for reusable buffers and persistent-mode harnesses; this reproduction runs directly, without an AFL++ campaign.[4]&lt;/p&gt;

&lt;p&gt;The important limit: exact-size input copies can expose reads past the allocation. They don't catch every semantic mistake within an otherwise valid allocation, and a clean result isn't a safety guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackathon Experience
&lt;/h2&gt;

&lt;p&gt;This is a standalone local demo. It wasn't built at an MLH event and isn't a competition entry.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://nullprogram.com/blog/2025/02/05/" rel="noopener noreferrer"&gt;Chris Wellons — Tips for more effective fuzz testing with AFL++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://clang.llvm.org/docs/AddressSanitizer.html" rel="noopener noreferrer"&gt;Clang — AddressSanitizer documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/malwaredante/the-illusion-of-progress-how-a-typo-in-my-custom-mutator-sent-my-fuzzer-into-the-wrong-parser-435j"&gt;@malwaredante — The Illusion of Progress: how a typo in my custom mutator sent my fuzzer into the wrong parser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md" rel="noopener noreferrer"&gt;AFL++ — Persistent-mode documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original memory-layout diagram, based on the checked reproducer.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>c</category>
      <category>testing</category>
      <category>debugging</category>
      <category>programming</category>
    </item>
    <item>
      <title>Nibnib says 4bpp. The file still has a header.</title>
      <dc:creator>Shivam Dwivedi</dc:creator>
      <pubDate>Mon, 02 Nov 2026 11:35:05 +0000</pubDate>
      <link>https://dev.to/panditshivam/nibnib-says-4bpp-the-file-still-has-a-header-56e4</link>
      <guid>https://dev.to/panditshivam/nibnib-says-4bpp-the-file-still-has-a-header-56e4</guid>
      <description>&lt;p&gt;My tiny nibnib file was larger than the raw RGB image I fed into it.&lt;/p&gt;

&lt;p&gt;For a 16×16 synthetic gradient, the raw RGB pixels took &lt;strong&gt;768 bytes&lt;/strong&gt;. The nibnib file took &lt;strong&gt;1,220 bytes&lt;/strong&gt;. Nothing had gone wrong with the encoder. The file had a palette to carry. 📦&lt;/p&gt;

&lt;p&gt;That was the useful surprise in trying Raph Levien's image format: “4 bits per pixel” describes the compact pixel coding, not an all-inclusive promise for every file size.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I made three original RGB gradients, ran the upstream nibnib encoder and decoder, and wrote an independent reader to check the decoded pixels.&lt;/p&gt;

&lt;p&gt;Nibnib is aimed at constrained-device decoding. It works on pixel pairs and uses a palette of differences rather than just a palette of absolute colors.[1] The current interest in it makes a good excuse to inspect the bytes instead of borrowing the speed claim. 🔍&lt;/p&gt;

&lt;p&gt;My check covers file layout and round trips. It doesn't measure microcontroller decoding speed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fserzmzpjlkev74vtx4tq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fserzmzpjlkev74vtx4tq.png" alt="The original 128 by 64 RGB gradient beside the actual nibnib-decoded output. A byte ledger beneath shows the 1,028-byte header and palette plus 4,352 bytes of row data, totaling 5,380 bytes." width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original synthetic input and actual decoded output. Display enlargement is for inspection; neither image is a photo.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;I used nibnib version &lt;code&gt;0.1.0&lt;/code&gt; at commit &lt;code&gt;2f02f8c225d937d1c19459e2b246f37d87a98f54&lt;/code&gt;. With a Rust toolchain available, build that checkout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--locked&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a small input you can generate yourself, save this as &lt;code&gt;make_gradient.py&lt;/code&gt;. It needs Pillow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;putdata&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gradient.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, from the nibnib checkout with that input file available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 make_gradient.py
./target/release/nibnib gradient.png gradient.nib &lt;span class="nt"&gt;--compress&lt;/span&gt;
./target/release/nibnib gradient.nib decoded.png &lt;span class="nt"&gt;--decompress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The explicit flags matter. At this revision, the default path encodes and then writes a decoded PNG; &lt;code&gt;--compress&lt;/code&gt; writes the compressed file.[2]&lt;/p&gt;

&lt;p&gt;Here are my checked sizes across the three fixtures:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input dimensions&lt;/th&gt;
&lt;th&gt;Raw RGB bytes&lt;/th&gt;
&lt;th&gt;nibnib file bytes&lt;/th&gt;
&lt;th&gt;Whole-file bits per pixel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;16×16&lt;/td&gt;
&lt;td&gt;768&lt;/td&gt;
&lt;td&gt;1,220&lt;/td&gt;
&lt;td&gt;38.125&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64×32&lt;/td&gt;
&lt;td&gt;6,144&lt;/td&gt;
&lt;td&gt;2,180&lt;/td&gt;
&lt;td&gt;8.516&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128×64&lt;/td&gt;
&lt;td&gt;24,576&lt;/td&gt;
&lt;td&gt;5,380&lt;/td&gt;
&lt;td&gt;5.254&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;✅ Each upstream decoder output matched my independent reader byte for byte. Each decoded image differed from its original input: this is a lossy round trip, not a pixel-preserving archive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the bytes go
&lt;/h3&gt;

&lt;p&gt;At the checked revision, the file stores dimensions and a fixed palette before its row data. Each row starts with an explicit pixel pair; later pairs use palette indices. Rows are aligned to four-byte boundaries.[1][2]&lt;/p&gt;

&lt;p&gt;Here's the size calculation for positive, even widths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nib_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;row_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;stride&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row_bytes&lt;/span&gt; &lt;span class="o"&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="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1028&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;nib_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# 5380
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For that image, the rows occupy &lt;code&gt;64 × 68 = 4,352&lt;/code&gt; bytes. Add the 1,028-byte header and palette, and the result is 5,380.&lt;/p&gt;

&lt;p&gt;The tiny image pays that same fixed palette cost. A larger image spreads it across more pixels. The row seeds and alignment still add overhead too. 💡&lt;/p&gt;

&lt;h3&gt;
  
  
  Compare against the right baseline
&lt;/h3&gt;

&lt;p&gt;My table compares the file with &lt;strong&gt;uncompressed RGB&lt;/strong&gt;, not with PNG or JPEG at matched quality.&lt;/p&gt;

&lt;p&gt;In fact, Pillow's PNG for the 128×64 gradient was only 514 bytes in this run. A smooth synthetic gradient is friendly to PNG. That doesn't settle which format suits a constrained display; it shows why “smaller than raw pixels” and “smaller than an existing compressed image” are different claims.&lt;/p&gt;

&lt;p&gt;A DEV discussion about palette reduction makes a related distinction: a lossless container can store pixels that an earlier conversion has already changed.[3] Check the actual decoded image, not just the format label.&lt;/p&gt;

&lt;h2&gt;
  
  
  Partner Technologies
&lt;/h2&gt;

&lt;p&gt;This walkthrough uses the upstream Rust nibnib CLI and Python with Pillow. The independent reader follows the documented layout and the checked decoder source.&lt;/p&gt;

&lt;p&gt;I haven't run this on an RP2350 or compared decoder speed with JPEG. The upstream encoder also generates a partly random palette, so preserve the encoded file when you need to reproduce the exact decoded pixels. The layout calculation doesn't depend on which palette values were selected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackathon Experience
&lt;/h2&gt;

&lt;p&gt;This was a standalone local format check. It isn't an MLH event build or competition entry.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/raphlinus/nibnib/tree/2f02f8c225d937d1c19459e2b246f37d87a98f54" rel="noopener noreferrer"&gt;Raph Levien — nibnib README at the checked revision&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/raphlinus/nibnib/tree/2f02f8c225d937d1c19459e2b246f37d87a98f54/src" rel="noopener noreferrer"&gt;nibnib — CLI, encoder and decoder source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yue_shu_c621a4a637f22396f/png-is-lossless-palette-reduction-is-not-53h0"&gt;@yue_shu_c621a4a637f22396f — PNG is lossless, palette reduction is not&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Asset credits
&lt;/h2&gt;

&lt;p&gt;Original synthetic gradients, actual decoded output and original byte-layout illustration. The nibnib implementation is credited to its upstream project, licensed MIT or Apache-2.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI disclosure
&lt;/h2&gt;

&lt;p&gt;AI was used to draft the article.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
