<?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: Muzammil Hussain</title>
    <description>The latest articles on DEV Community by Muzammil Hussain (@smhd21).</description>
    <link>https://dev.to/smhd21</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%2F4192061%2Ff6f91056-9067-40f5-84ff-4bbdb07ec81a.png</url>
      <title>DEV Community: Muzammil Hussain</title>
      <link>https://dev.to/smhd21</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smhd21"/>
    <language>en</language>
    <item>
      <title>A build check that stops stale numbers, and the one error it could not catch</title>
      <dc:creator>Muzammil Hussain</dc:creator>
      <pubDate>Sun, 18 Oct 2026 13:37:57 +0000</pubDate>
      <link>https://dev.to/smhd21/a-build-check-that-stops-stale-numbers-and-the-one-error-it-could-not-catch-odd</link>
      <guid>https://dev.to/smhd21/a-build-check-that-stops-stale-numbers-and-the-one-error-it-could-not-catch-odd</guid>
      <description>&lt;p&gt;I run a small site of calculators (pay raise, credit card payoff, overtime tax and so on). Each page has the calculator, a formula and worked examples written in prose: "a 3% raise on $60,000 makes $61,800". The usual way those drift apart is that someone changes the code and forgets the text.&lt;/p&gt;

&lt;p&gt;So the page text is not written by hand. It is generated from the same module the calculator uses, and every number that goes into a sentence is checked against a value worked out on paper first:&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="c1"&gt;// Build-time only, never shipped to the browser.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mustBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.005&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="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;eps&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`BUILD CHECK FAILED: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: calculator gave &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, hand-check says &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the calculator changes behaviour, the page does not build. That is the whole mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case where it worked
&lt;/h2&gt;

&lt;p&gt;The pay raise page compares a raise with inflation. It quotes the US consumer price rise from a small block of dated facts:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FACTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-10-11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2027-04-30&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cpi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;3.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cpiMonth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;August 2026&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;and the example sentence is backed by a hand-check:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;real&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;nominal&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;FACTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cpi&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;mustBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;real change of a 3% raise at 3.4% inflation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;real&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.3868&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0005&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1.03 / 1.034 - 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On 14 October the Bureau of Labor Statistics published September CPI: 3.7%, up from 3.4%. When I went to update the page on 18 October I changed &lt;code&gt;cpi&lt;/code&gt; to 3.7 and ran the build. It stopped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BUILD CHECK FAILED: real change of a 3% raise at 3.4% inflation:
calculator gave -0.6750241080038522, hand-check says -0.3868
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the behaviour I wanted. The sentence "a 3% raise buys what $59,767.89 bought before" could not be published with the new inflation figure in it. I recalculated by hand (1.03 / 1.037 − 1 = −0.6750%, and $61,800 / 1.037 = $59,594.99), updated the three expected values, and the build passed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case where it did not
&lt;/h2&gt;

&lt;p&gt;The same day I checked every figure on the site against its source, and found a mistake that every test had passed.&lt;/p&gt;

&lt;p&gt;Two pages quote the Federal Reserve's average credit card interest rate and call it the figure for "the second quarter of 2026": 22.25% on accounts charged interest, 21.16% across all accounts. The Fed's G.19 release shows those are the second quarter of &lt;strong&gt;2025&lt;/strong&gt; values. The second quarter of 2026 figures are 22.15% and 20.94%.&lt;/p&gt;

&lt;p&gt;Nothing in the build could have flagged it. The calculator was correct. The text was generated from the calculator, and the hand-checks compared the calculator with itself. The label "second quarter of 2026" was a string I typed. A check that compares code with text has no way to know that a number is attached to the wrong period in the real world.&lt;/p&gt;

&lt;p&gt;The visible effect was small. On a $5,000 balance paid at $200 a month, interest at the quoted average rate was $1,779.73 instead of $1,767.76, a difference of $11.97. The wrong label was the real problem: a page that cites a source and cites it wrongly has lost the one thing it claims to offer.&lt;/p&gt;

&lt;p&gt;I fixed both pages, and added a public entry to the site's corrections page stating what was wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the build check does not cover
&lt;/h2&gt;

&lt;p&gt;Writing this down made the boundary plain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code versus text:&lt;/strong&gt; covered. The text is generated from the code and compared with hand-checked values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facts versus their source:&lt;/strong&gt; not covered. A rate, a threshold or a date is only as right as the person who typed it, on the day they typed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facts versus time:&lt;/strong&gt; only partly covered. &lt;code&gt;FACTS.expires&lt;/code&gt; makes the build refuse to publish after a set date, which forces a re-check, but it says nothing about the six months before that.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A script that reads the source, not the code. It runs every two days and writes a report; it never edits the site.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It fetches the Fed's G.19 page and compares the whole credit card row of the table with the row I last verified. Any new month or quarter changes the row and raises a flag, including when the figure I quote has not changed. That false alarm is deliberate. A silent miss is worse.&lt;/li&gt;
&lt;li&gt;It recomputes the CPI 12-month change from the BLS data series and compares it with the page: September 2026 comes out at 3.74%, which BLS rounds to 3.7%.&lt;/li&gt;
&lt;li&gt;For sources it cannot parse reliably, it flags the release date as due a few days ahead, and a human checks the source.&lt;/li&gt;
&lt;li&gt;It also fetches each live page and confirms that the figure I registered is still there and the stale one is not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tested it the only way that means anything: I set the registered CPI to 3.6% and confirmed it reported the mismatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tradeoffs
&lt;/h2&gt;

&lt;p&gt;Whole-row comparison on the Fed page is brittle. If the Fed reformats the table, the script reports "anchor not found" and I look at it by hand. I prefer that to a clever parser that quietly returns the wrong column.&lt;/p&gt;

&lt;p&gt;Generating text from code also constrains how the pages can be written. A sentence like "this is usually a bad idea" has no value to assert, so it lives outside the generated part. The checks cover arithmetic and quoted figures, not judgement.&lt;/p&gt;

&lt;p&gt;The calculators, the formulas and the corrections log are at &lt;a href="https://sumfern.com/methodology/" rel="noopener noreferrer"&gt;sumfern.com/methodology&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: this article was written by an AI assistant (Claude) for the editor of Sumfern, who owns the project. The events, figures and code are from the real repository and the official Federal Reserve and BLS releases, and were checked against them before publishing.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
