<?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: Ryulhwan Kim</title>
    <description>The latest articles on DEV Community by Ryulhwan Kim (@igotojapan123web).</description>
    <link>https://dev.to/igotojapan123web</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%2F4119180%2Fe34f41ba-2a1d-44bd-8e63-c9a11f7a55de.png</url>
      <title>DEV Community: Ryulhwan Kim</title>
      <link>https://dev.to/igotojapan123web</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igotojapan123web"/>
    <language>en</language>
    <item>
      <title>My regression test passed for 3 weeks while the code it tested was deleted</title>
      <dc:creator>Ryulhwan Kim</dc:creator>
      <pubDate>Thu, 10 Sep 2026 11:13:11 +0000</pubDate>
      <link>https://dev.to/igotojapan123web/my-regression-test-passed-for-3-weeks-while-the-code-it-tested-was-deleted-3f47</link>
      <guid>https://dev.to/igotojapan123web/my-regression-test-passed-for-3-weeks-while-the-code-it-tested-was-deleted-3f47</guid>
      <description>&lt;p&gt;I had a check guarding a bug fix. It was one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;trySendWithRetry(&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;It was matching the &lt;strong&gt;import statement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The actual call had been removed during a refactor weeks earlier. The check reported green the entire time, while user messages were being dropped whenever the network blipped once.&lt;/p&gt;

&lt;p&gt;What bothers me is not that I wrote a sloppy check. It is that &lt;strong&gt;there was no way to notice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A check that &lt;em&gt;cannot&lt;/em&gt; fail and a check that passes produce byte-identical output. There is no signal to look for. And the better your enforcement layer gets, the worse this becomes — you stop reading the green and start trusting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I was writing these checks at all
&lt;/h2&gt;

&lt;p&gt;Not new bugs. The &lt;em&gt;same&lt;/em&gt; ones, weeks apart, in different screens of the same app.&lt;/p&gt;

&lt;p&gt;The cause was almost never a bad fix. It was that the same five lines had been copy-pasted into eight places and only one got patched. Or a later cleanup removed a guard clause whose reason nobody had written down.&lt;/p&gt;

&lt;p&gt;Once I started using a coding agent daily it got noticeably worse, because the agent has no memory of &lt;em&gt;why&lt;/em&gt; a line is there. It removes it while simplifying, every test still passes, and the bug you paid for three weeks ago comes back.&lt;/p&gt;

&lt;p&gt;So each fix became an executable rule that carries the incident with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;why&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-04-02: the retry loop had no idempotency key, so the gateway treated each
      attempt as a new charge. 38 customers double-charged, ~$4,100 refunded.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not &lt;em&gt;"prevents silent failures."&lt;/em&gt; The date and the cost.&lt;/p&gt;

&lt;p&gt;That difference matters more than it looks. An agent — or a tired human — deciding whether to delete a line has nothing to weigh "this is important" against. It has something to weigh $4,100 against.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that fixes the real problem
&lt;/h2&gt;

&lt;p&gt;Every rule declares mutations that &lt;em&gt;should&lt;/em&gt; break it. One command applies each one, asserts the rule fails, and restores the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;npm run demo:verify
&lt;span class="go"&gt;  ✓ key removed entirely
  ✓ key declared but not passed
  ✓ key made random
  caught 3/3 deliberate breaks
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the same rule written the obvious way — &lt;code&gt;src.includes("idempotencyKey")&lt;/code&gt;, which is what I wrote first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;npm run demo:leak
&lt;span class="go"&gt;  ✗ LEAK — the code was broken and the rule still passed
  caught 0/1 deliberate breaks
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Both of those pass a normal run.&lt;/strong&gt; Only one of them is real. That is the entire point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three checks that leaked on me
&lt;/h2&gt;

&lt;p&gt;These are not hypothetical. Each one looked correct in review and each one was worthless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The file-level check&lt;/strong&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rawApi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nf"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reads fine: "this file calls the raw API and doesn't use the wrapper." But a file that calls the wrapper in &lt;em&gt;one&lt;/em&gt; place and the raw API in &lt;em&gt;another&lt;/em&gt; satisfies both conditions and passes — which is exactly what a half-applied fix looks like, and the single most likely shape of the bug. It has to be line by line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The comment match&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A rule checked &lt;code&gt;/PREVIOUS/i.test(source)&lt;/code&gt; to confirm a previous-secret fallback still existed. The file's own header comment said &lt;em&gt;"accepting the previous secret for one overlap window…"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So deleting the actual fallback code changed nothing. The rule stayed green as long as the comment survived. Scan only lines that execute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Evidence of a bound is not a bound&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A rule looked for the identifier &lt;code&gt;YEARS&lt;/code&gt; as proof that a year range was limited. Widening the range to a hardcoded list left &lt;code&gt;YEARS&lt;/code&gt; in place, so the rule found its own evidence and passed.&lt;/p&gt;

&lt;p&gt;Mentioning a bound is not having one. Check the values, not the vocabulary.&lt;/p&gt;

&lt;h2&gt;
  
  
  And one that only broke for other people
&lt;/h2&gt;

&lt;p&gt;On a CRLF checkout, any mutation whose anchor spans a newline matched nothing. So &lt;code&gt;verify&lt;/code&gt; reported &lt;em&gt;"mutation changed nothing"&lt;/em&gt; instead of testing the rule, and the headline demo caught &lt;strong&gt;0/0&lt;/strong&gt; for anyone who cloned the repo on Windows.&lt;/p&gt;

&lt;p&gt;Everything passed on my machine. I found it only by cloning fresh into a clean directory.&lt;/p&gt;

&lt;p&gt;That is precisely the class of bug the tool exists to catch, and it shipped anyway. Make of that what you will — I mostly take it as evidence that "it works here" is not a test.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/igotojapan123-web/regression-guard
&lt;span class="nb"&gt;cd &lt;/span&gt;regression-guard
npm run demo:verify   &lt;span class="c"&gt;# careful rule: caught 3/3&lt;/span&gt;
npm run demo:leak     &lt;span class="c"&gt;# naive rule: exposed as fake&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT, no dependencies, Node 18+. No install step, no signup, two npm scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this does and does not belong
&lt;/h2&gt;

&lt;p&gt;If what you need is "ban this API", &lt;strong&gt;ESLint's &lt;code&gt;no-restricted-syntax&lt;/code&gt; is better and you should reach for it first.&lt;/strong&gt; Semgrep and CodeQL are vastly stronger pattern engines than this 400-line thing.&lt;/p&gt;

&lt;p&gt;The only thing I could not find in any of them is a first-class way to &lt;em&gt;prove a rule fails when it should&lt;/em&gt;. If that exists somewhere, please tell me — I would genuinely rather use it than maintain this.&lt;/p&gt;

&lt;p&gt;A guard rule is also not a lint rule. A linter says "this is bad style." A guard says "this specific past fix is still present, and here is what it cost when it wasn't."&lt;/p&gt;

&lt;p&gt;The thing I am least comfortable with: the mutations are string-based, so a rule's &lt;code&gt;breaks&lt;/code&gt; rot when the code around them is rewritten. &lt;code&gt;verify&lt;/code&gt; warns about that instead of failing, and I suspect that is the wrong default.&lt;/p&gt;

&lt;p&gt;Curious whether anyone has solved the "prove the check can fail" problem in a cleaner way. Happy to be told the whole premise is wrong.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>ai</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
