<?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: Dominic Harmon</title>
    <description>The latest articles on DEV Community by Dominic Harmon (@dominic_harmon_18363706c7).</description>
    <link>https://dev.to/dominic_harmon_18363706c7</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%2F4004719%2Fa1686e81-0968-4ac2-aff7-f5be182b8e8b.png</url>
      <title>DEV Community: Dominic Harmon</title>
      <link>https://dev.to/dominic_harmon_18363706c7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dominic_harmon_18363706c7"/>
    <language>en</language>
    <item>
      <title>I Built a Claude Code Skill That Finds Broken Callers Before You Deploy</title>
      <dc:creator>Dominic Harmon</dc:creator>
      <pubDate>Sat, 27 Jun 2026 02:33:31 +0000</pubDate>
      <link>https://dev.to/dominic_harmon_18363706c7/i-built-a-claude-code-skill-that-finds-broken-callers-before-you-deploy-52a2</link>
      <guid>https://dev.to/dominic_harmon_18363706c7/i-built-a-claude-code-skill-that-finds-broken-callers-before-you-deploy-52a2</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Claude Code Skill That Finds Broken Callers Before You Deploy
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;You fix a bug. You deploy. Three hours later, production is on fire. Here's how I built a tool to stop that.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The moment I realized I needed this
&lt;/h2&gt;

&lt;p&gt;I was working on a Chinese chess app. Changed &lt;code&gt;is_checkmate()&lt;/code&gt; — added a simple empty-board guard clause. Two lines. Trivial.&lt;/p&gt;

&lt;p&gt;Ran my tests. Green. Deployed.&lt;/p&gt;

&lt;p&gt;Two hours later: puzzle solving was broken. Level submission returned wrong results. &lt;strong&gt;I changed one function. It silently broke two callers I didn't even know existed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The test coverage report said 87%. It didn't matter. Coverage tells you which lines ran — not which callers your change silently corrupted.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Test Shield&lt;/strong&gt; — a Claude Code skill with one job:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read your git diff&lt;/li&gt;
&lt;li&gt;Trace every caller of every changed function&lt;/li&gt;
&lt;li&gt;Show you which impacts are expected (you meant to change that) and which are surprising (you didn't know that used it)&lt;/li&gt;
&lt;li&gt;Generate pytest regression tests for the surprising ones&lt;/li&gt;
&lt;li&gt;Run them — all green? Ship. Any red? Stop and fix.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/test-shield
     │
     ▼
Changed: is_checkmate() — chess_utils.py:320

⚠️  Unexpected impact:
  ● solve_puzzle() — levels.py:687     ← wouldn't have caught this
  ● submit_level_solution() — levels.py:516   ← or this

→ Generate 6 regression tests
→ 4/6 pass, 2 need review
→ Safe to merge. Here's the evidence.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why this is different from coverage tools
&lt;/h2&gt;

&lt;p&gt;Coverage tells you: "Line 42 was executed during tests."&lt;/p&gt;

&lt;p&gt;Test Shield tells you: "Line 42 changed. These 3 callers depend on it. They have zero tests. You didn't know about 2 of them."&lt;/p&gt;

&lt;p&gt;One is about &lt;strong&gt;what ran&lt;/strong&gt;. The other is about &lt;strong&gt;what will break&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The hard lesson: what it won't do
&lt;/h2&gt;

&lt;p&gt;I learned this the hard way during building: Python's dynamic nature means some callers are invisible to static analysis. &lt;code&gt;getattr()&lt;/code&gt;, &lt;code&gt;importlib&lt;/code&gt;, decorator injection, monkey-patching — AST tracing can't see through those.&lt;/p&gt;

&lt;p&gt;So Test Shield doesn't pretend. Every run ends with a "honesty report":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tracing method:         AST static analysis
Dynamic call risks:     0 detected
Known blind spots:      getattr, importlib, decorators
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it can't trace something, it tells you. No false confidence.&lt;/p&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Standalone — no Claude Code required&lt;/span&gt;
git clone https://github.com/dominicharmon-commits/test-shield.git
&lt;span class="nb"&gt;cd &lt;/span&gt;your-python-project
python ../test-shield/scripts/analyze.py &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# With Claude Code&lt;/span&gt;
/test-shield
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero dependencies. Pure Python stdlib. Python 3.10+.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] TypeScript/Jest support (v1.2)&lt;/li&gt;
&lt;li&gt;[ ] pytest-cov integration for coverage verification (v1.1)&lt;/li&gt;
&lt;li&gt;[ ] CI/CD integration (v2.0)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PRs welcome. MIT licensed.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Claude Code. Tested on a real production codebase. Stars appreciated.&lt;/em&gt; ⭐&lt;/p&gt;

</description>
      <category>python</category>
      <category>claude</category>
      <category>testing</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
