<?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: zerocool</title>
    <description>The latest articles on DEV Community by zerocool (@zerocoool).</description>
    <link>https://dev.to/zerocoool</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%2F4033499%2F0ab13e43-7e8f-44f1-99c7-511c3f60038f.jpeg</url>
      <title>DEV Community: zerocool</title>
      <link>https://dev.to/zerocoool</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zerocoool"/>
    <language>en</language>
    <item>
      <title>Beyond the Dogma: How Object Calisthenics and AI Taught Me to Write Cleaner Kotlin</title>
      <dc:creator>zerocool</dc:creator>
      <pubDate>Fri, 14 Aug 2026 14:22:24 +0000</pubDate>
      <link>https://dev.to/zerocoool/beyond-the-dogma-how-object-calisthenics-and-ai-taught-me-to-write-cleaner-kotlin-525f</link>
      <guid>https://dev.to/zerocoool/beyond-the-dogma-how-object-calisthenics-and-ai-taught-me-to-write-cleaner-kotlin-525f</guid>
      <description>&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%2Fq77ul7xx8ttm6c9466s2.jpg" 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%2Fq77ul7xx8ttm6c9466s2.jpg" alt="Beyond the Dogma: How Object Calisthenics and AI Taught Me to Write Cleaner Kotlin" width="612" height="409"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A story about store layouts, over-engineering, and finding pragmatic balance with an AI Cognitive Sparring Partner.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Act I: The Layout Puzzle
&lt;/h2&gt;

&lt;p&gt;In spatial store design and merchandise engineering, every millimeter in a retail layout matters. Whether you are placing modular shelving, promotional stands, or store fixtures, physical space has strict rules.&lt;/p&gt;

&lt;p&gt;In software architecture, our domain models should reflect those same strict rules. Yet, domain logic often ends up scattered across procedural service classes.&lt;/p&gt;

&lt;p&gt;A while ago, I was working on our store mapping services—specifically, a feature responsible for calculating the final inventory requirements of furniture fixtures for a seasonal store layout.&lt;/p&gt;

&lt;p&gt;I opened the service and found a method responsible for matching fixture families with furniture ranges and aggregating their total quantities. What greeted me was a classic piece of procedural logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StoreFurnitureService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;calculateImplantationFurnitures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;families&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
        &lt;span class="n"&gt;implantableElements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TreeNodeLeaf&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
        &lt;span class="n"&gt;furnitures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Furniture&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ImplantationFurniture&lt;/span&gt;&lt;span class="p"&gt;&amp;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;families&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;implantationFurnitures&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;familyId&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;implantedElementDetail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;implantableElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&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;span class="n"&gt;familyId&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;implantedElementDetail&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;furnituresDetail&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;furnitures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;idFamily&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;implantedElementDetail&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;&amp;amp;&amp;amp;&lt;/span&gt;
                    &lt;span class="n"&gt;implantedElementDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rangeChoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;idRange&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="n"&gt;furnituresDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;implantationFurnitures&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;allFurnitures&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;addedFurnitureIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;allFurnitures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOfFirst&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&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;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;referenceId&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;addedFurnitureIndex&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&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="p"&gt;{&lt;/span&gt;
                        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;existing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;allFurnitures&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;addedFurnitureIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                        &lt;span class="n"&gt;allFurnitures&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;addedFurnitureIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
                        &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;allFurnitures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="nc"&gt;ImplantationFurniture&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;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;referenceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&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="n"&gt;allFurnitures&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;implantationFurnitures&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's pause and pair-program on this snippet for a second. Read lines 16–28 again.&lt;/p&gt;

&lt;p&gt;Notice what is happening here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have a &lt;code&gt;fold&lt;/code&gt; nested inside another &lt;code&gt;fold&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside the inner &lt;code&gt;fold&lt;/code&gt;, we are searching an accumulator list with &lt;code&gt;indexOfFirst&lt;/code&gt;, mutating existing elements in place if found, and appending new ones if not. We are using &lt;code&gt;fold&lt;/code&gt; like an imperative loop with state side-effects.&lt;/li&gt;
&lt;li&gt;Look closely at the filter condition: &lt;code&gt;implantedElementDetail.rangeChoice.range == furniture.idRange&lt;/code&gt;. The service layer is directly reaching three levels deep into a tree node to inspect a raw &lt;code&gt;Int&lt;/code&gt; primitive and compare it with another raw &lt;code&gt;Int&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The service is asking objects for their raw data and performing list arithmetic on their behalf. The domain models (&lt;code&gt;Furniture&lt;/code&gt;, &lt;code&gt;TreeNodeLeaf&lt;/code&gt;) are acting as mere passive data buckets—a textbook example of an &lt;strong&gt;Anemic Domain Model&lt;/strong&gt; violating &lt;strong&gt;Tell, Don't Ask&lt;/strong&gt; and the &lt;strong&gt;Law of Demeter&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Act II: Peak Dunning-Kruger (The Over-Engineering Trap)
&lt;/h2&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%2F0av4tr4jm3jvrlrz7n9v.jpg" 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%2F0av4tr4jm3jvrlrz7n9v.jpg" alt="Dunning-Kruger - object calisthenics" width="675" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted to refactor this logic into a clean, rich Kotlin domain model. I remembered Jeff Bay’s 9 rules of &lt;strong&gt;Object Calisthenics&lt;/strong&gt; from &lt;em&gt;The ThoughtWorks Anthology&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Only one level of indentation per method.&lt;/li&gt;
&lt;li&gt;Do not use the &lt;code&gt;else&lt;/code&gt; keyword.&lt;/li&gt;
&lt;li&gt;Wrap all primitives and strings.&lt;/li&gt;
&lt;li&gt;First-class collections.&lt;/li&gt;
&lt;li&gt;One dot per line (Law of Demeter).&lt;/li&gt;
&lt;li&gt;Do not abbreviate.&lt;/li&gt;
&lt;li&gt;Keep entities small (under 150 lines).&lt;/li&gt;
&lt;li&gt;No class with more than two instance variables.&lt;/li&gt;
&lt;li&gt;No getters/setters/properties (Tell, Don't Ask).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;"I am going to apply every single rule strictly,"&lt;/em&gt; I thought.&lt;/p&gt;

&lt;p&gt;An hour later, I looked at my changes: I had created 10 separate abstractions—&lt;code&gt;FamilyId&lt;/code&gt;, &lt;code&gt;RangeId&lt;/code&gt;, &lt;code&gt;FurnitureReferenceId&lt;/code&gt;, &lt;code&gt;FurnitureQuantity&lt;/code&gt;, &lt;code&gt;FurnitureLabel&lt;/code&gt;, &lt;code&gt;FurnitureMatcher&lt;/code&gt;, &lt;code&gt;RangeMatchingSpecification&lt;/code&gt;, &lt;code&gt;FurnitureAggregationStrategy&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;I had created a maze of single-method wrappers and strategy interfaces just to match a furniture range and add two numbers together. To trace how a single piece of furniture was counted, I had to navigate through layers of abstractions.&lt;/p&gt;

&lt;p&gt;I had eliminated the nested branches and wrapped every &lt;code&gt;Int&lt;/code&gt;, but I had introduced massive accidental complexity. I had fallen into the Dunning-Kruger trap: confusing dogmatic compliance with good software design.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Calisthenics Cheat Sheet: From Smell to Idiomatic Kotlin
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Object Calisthenics Rule&lt;/th&gt;
&lt;th&gt;Procedural Code Smell&lt;/th&gt;
&lt;th&gt;Modern Kotlin Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rule 1: 1 Level of Indentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deeply nested loops and conditionals&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fold&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, and early returns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rule 2: No &lt;code&gt;else&lt;/code&gt; Keyword&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Branching state machines&lt;/td&gt;
&lt;td&gt;Guard clauses (&lt;code&gt;require&lt;/code&gt;, &lt;code&gt;check&lt;/code&gt;), &lt;code&gt;when&lt;/code&gt; expressions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rule 3: Wrap Primitives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Primitive Obsession (&lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@JvmInline value class&lt;/code&gt; (zero-cost allocation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rule 4: First-Class Collections&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Leaky, mutable &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; operations&lt;/td&gt;
&lt;td&gt;Dedicated domain wrapper classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rule 9: Tell, Don't Ask&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Anemic Data Holders&lt;/td&gt;
&lt;td&gt;Rich Domain Entities with behavior methods&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Act III: Enter the AI Cognitive Sparring Partner
&lt;/h2&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%2Fvk0kk1e66e9xwfclsqlf.webp" 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%2Fvk0kk1e66e9xwfclsqlf.webp" alt="AI Cognitive Sparring Partner" width="700" height="292"&gt;&lt;/a&gt;&lt;br&gt;
There are two ways developers use Artificial Intelligence today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Viber's Way:&lt;/strong&gt; Asking AI to &lt;em&gt;"refactor this method using Object Calisthenics."&lt;/em&gt; The AI will happily generate 15 files of boilerplate, amplifying your over-engineering and drowning your domain in accidental complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Craftsman Way:&lt;/strong&gt; Using AI as a &lt;strong&gt;Cognitive Sparring Partner&lt;/strong&gt;—a concept championed by software craftspeople. You don't ask AI to think for you; you ask it to challenge your design choices and expose your blind spots.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I invoked a custom prompt in my IDE named &lt;code&gt;calisthenics-challenger&lt;/code&gt;, pasted my 10 new classes, and asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Play devil's advocate. I strictly applied Object Calisthenics to this furniture aggregation logic. Where did I over-engineer this? Where did I create class explosion instead of domain clarity?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI’s response was an immediate reality check:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"You created &lt;code&gt;FurnitureMatcher&lt;/code&gt;, &lt;code&gt;RangeMatchingSpecification&lt;/code&gt;, and &lt;code&gt;FurnitureAggregationStrategy&lt;/code&gt;. None of these abstractions represent distinct business concepts in your domain—they are procedural logic dressed up in strategy patterns.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;In Kotlin, you don't need heavy wrapper objects for every primitive ID. Use &lt;code&gt;@JvmInline value class&lt;/code&gt; for zero-cost type safety on &lt;code&gt;FamilyId&lt;/code&gt; and &lt;code&gt;RangeId&lt;/code&gt;. Then, encapsulate your raw lists into two First-Class Collections: an &lt;code&gt;ImplantedElements&lt;/code&gt; collection that knows how to filter by family/range, and an &lt;code&gt;ImplantationInventory&lt;/code&gt; collection that owns the accumulation logic via operator overloading."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That pushback changed my perspective. The rules of Object Calisthenics were never meant to be dogmatic laws to follow blindly; they were training wheels designed to build muscle memory around encapsulation and cohesion.&lt;/p&gt;


&lt;h2&gt;
  
  
  Act IV: The Pragmatic Kotlin Solution
&lt;/h2&gt;

&lt;p&gt;With the AI serving as a guardrail against over-engineering, we refactored the store furniture implantation logic into expressive, idiomatic Kotlin.&lt;/p&gt;

&lt;p&gt;Here is the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rule 3: Zero-allocation Value Objects via Kotlin Inline Classes&lt;/span&gt;
&lt;span class="nd"&gt;@JvmInline&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FamilyId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@JvmInline&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RangeId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@JvmInline&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReferenceId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@JvmInline&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Quantity cannot be negative."&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Idiomatic Kotlin operator overloading for domain arithmetic&lt;/span&gt;
    &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Quantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Domain Entity encapsulating Furniture characteristics&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Furniture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;referenceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ReferenceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;familyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FamilyId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;rangeId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RangeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Quantity&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Encapsulated domain logic matching range constraints&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;matchesRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FamilyId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RangeId&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;familyId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;family&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rangeId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Rich Value Object representing a matched element in the layout&lt;/span&gt;
&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;ImplantedElementDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FamilyId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;selectedRange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RangeId&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Rule 4: First-Class Collection encapsulating Store Furniture Inventory&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImplantationInventory&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReferenceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ImplantationItem&lt;/span&gt;&lt;span class="p"&gt;&amp;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;data class&lt;/span&gt; &lt;span class="nc"&gt;ImplantationItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;referenceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ReferenceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Quantity&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;emptyMap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;// Immutable collection aggregation using operator overloading&lt;/span&gt;
    &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Furniture&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ImplantationInventory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;existing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;referenceId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;updatedQuantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;updatedItem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImplantationItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;referenceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updatedQuantity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ImplantationInventory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;referenceId&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;updatedItem&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ImplantationItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Rule 4: First-Class Collection managing the Catalog of Furnitures&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FurnitureCatalog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;furnitures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Furniture&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Rules 1, 2 &amp;amp; 9: Flat processing adhering to Tell, Don't Ask&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;calculateImplantationRequirements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;implantedElements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ImplantedElementDetail&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;ImplantationInventory&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;implantedElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ImplantationInventory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;matchingFurnitures&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;furnitures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;furniture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchesRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&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;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectedRange&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;matchingFurnitures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;currentInventory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;furniture&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;currentInventory&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;furniture&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Design Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero &lt;code&gt;else&lt;/code&gt; Keywords &amp;amp; Single-Level Nesting:&lt;/strong&gt; The imperative nested loops and list mutations were replaced with immutable functional operations (&lt;code&gt;fold&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Class Collection (&lt;code&gt;ImplantationInventory&lt;/code&gt;):&lt;/strong&gt; The logic for merging furniture quantities by &lt;code&gt;ReferenceId&lt;/code&gt; no longer lives in a random service method. It is isolated inside &lt;code&gt;ImplantationInventory&lt;/code&gt;, which manages its internal map immutably using the &lt;code&gt;+&lt;/code&gt; operator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Victory of Tell, Don't Ask:&lt;/strong&gt; Compare these two lines:&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Before (Procedural):&lt;/em&gt; &lt;code&gt;implantedElementDetail.rangeChoice.range == furniture.idRange&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;After (Crafted):&lt;/em&gt; &lt;code&gt;furniture.matchesRange(element.id, element.selectedRange)&lt;/code&gt;&lt;br&gt;
We stopped reaching three levels deep into internal object structures and started delegating intent directly to the entity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compile-Time Type Safety:&lt;/strong&gt; Kotlin's &lt;code&gt;@JvmInline value class&lt;/code&gt; ensures we can never accidentally pass a &lt;code&gt;RangeId&lt;/code&gt; into a parameter expecting a &lt;code&gt;FamilyId&lt;/code&gt;, with zero runtime allocation overhead.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Act V: Your AI Sparring Toolkit (4 Custom Skills)
&lt;/h2&gt;

&lt;p&gt;To integrate this workflow into your daily routine—whether using Claude Code, Cursor, or custom assistant prompts—here are the four AI Skills formatted for your IDE environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skill 1: &lt;code&gt;calisthenics-suggester&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calisthenics-suggester&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Analyzes legacy or complex Kotlin code for Object Calisthenics violations and proposes a clean domain refactoring plan. Use when staring at a complex method, deep nested branches, primitive obsession, or anemic domain logic.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gu"&gt;## Calisthenics Opportunity Suggester&lt;/span&gt;

Identifies structural code smells in Kotlin code using Object Calisthenics as a diagnostic tool, then proposes a pragmatic refactoring strategy.

When exploring the codebase, read &lt;span class="sb"&gt;`CONTEXT.md`&lt;/span&gt; (if it exists) to match domain language.

&lt;span class="gu"&gt;## Diagnostic Process&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Scan for Core Violations:**&lt;/span&gt;
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Indentation &amp;amp; Branching:**&lt;/span&gt; Methods with &amp;gt;1 level of nesting or reliance on &lt;span class="sb"&gt;`else`&lt;/span&gt; keywords.
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Primitive Obsession:**&lt;/span&gt; Raw &lt;span class="sb"&gt;`Int`&lt;/span&gt;, &lt;span class="sb"&gt;`String`&lt;/span&gt;, or &lt;span class="sb"&gt;`Double`&lt;/span&gt; types carrying business invariants without validation.
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Naked Collections:**&lt;/span&gt; Direct list manipulation (&lt;span class="sb"&gt;`filter`&lt;/span&gt;, &lt;span class="sb"&gt;`map`&lt;/span&gt;, &lt;span class="sb"&gt;`reduce`&lt;/span&gt;, &lt;span class="sb"&gt;`indexOfFirst`&lt;/span&gt;) inside service classes instead of dedicated containers.
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Anemic Domain Entities:**&lt;/span&gt; Classes that act as passive data buckets while services execute domain math on their behalf (&lt;span class="ge"&gt;*Tell, Don't Ask*&lt;/span&gt; breach).&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Formulate Refactoring Strategy:**&lt;/span&gt;
&lt;span class="p"&gt;*&lt;/span&gt; Group raw primitives into Kotlin &lt;span class="sb"&gt;`@JvmInline value class`&lt;/span&gt; abstractions.
&lt;span class="p"&gt;*&lt;/span&gt; Extract raw collection operations into First-Class Collections.
&lt;span class="p"&gt;*&lt;/span&gt; Convert nested conditional logic into early-exit guard clauses (&lt;span class="sb"&gt;`require`&lt;/span&gt;, &lt;span class="sb"&gt;`check`&lt;/span&gt;).&lt;span class="sb"&gt;


&lt;/span&gt;&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Output Format:**&lt;/span&gt;
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Smells Identified:**&lt;/span&gt; Quote the exact lines violating encapsulation.
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Domain Concept to Surface:**&lt;/span&gt; Name the hidden business entity or value object wanting to be born.
&lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="gs"&gt;**Refactored Kotlin Draft:**&lt;/span&gt; Provide concise, high-signal Kotlin code implementing the fix.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Skill 2: &lt;code&gt;calisthenics-challenger&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calisthenics-challenger&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Acts as a pragmatic Tech Lead to challenge proposed refactorings. Prevents over-engineering, class explosion, and YAGNI violations. Use before committing a refactoring or when evaluating if a Calisthenics abstraction is worth the complexity.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Calisthenics Challenger (The Cognitive Sparring Partner)&lt;/span&gt;

Prevents dogmatic compliance with Object Calisthenics from turning clean code into over-engineered accidental complexity.

&lt;span class="gu"&gt;## The Sparring Framework&lt;/span&gt;

When presented with a proposed refactoring, audit it against these four anti-patterns before approving:
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Class Explosion:**&lt;/span&gt; Creating 5+ single-method interfaces, strategy patterns, or wrapper classes for a simple requirement. Use Kotlin's &lt;span class="sb"&gt;`@JvmInline value class`&lt;/span&gt; for zero-allocation type safety instead of heavy wrapper objects.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Speculative Generality (YAGNI):**&lt;/span&gt; Adding generic parameters, strategy interfaces, or factory wrappers for "future extensibility" not asked for by the domain.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Anemic Abstractions:**&lt;/span&gt; Creating a Value Object that wraps a primitive but contains zero validation logic or domain behavior.
&lt;span class="p"&gt;4.&lt;/span&gt; &lt;span class="gs"&gt;**Broken Navigation:**&lt;/span&gt; Requiring a developer to jump across 8 different small files to trace a single 20-line feature.

&lt;span class="gu"&gt;## Response Process&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Acknowledge the Intent:**&lt;/span&gt; State what the refactoring was trying to solve.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Push Back Explicitly:**&lt;/span&gt; Point out exactly where dogmatic rule compliance created noise or class explosion.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Offer the Pragmatic Balance:**&lt;/span&gt; Show a simplified Kotlin alternative that retains domain encapsulation without file clutter.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Skill 3: &lt;code&gt;boyscout-refactor&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boyscout-refactor&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scopes down refactoring after completing a feature or bugfix. Identifies exactly ONE low-risk Object Calisthenics improvement on touched files without expanding scope. Use right after passing feature tests before opening a PR.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Boy Scout Refactor&lt;/span&gt;

Applies the Boy Scout Rule (&lt;span class="ge"&gt;*"Leave the code cleaner than you found it"*&lt;/span&gt;) in surgical, low-risk vertical slices.

&lt;span class="gu"&gt;## Rules of Engagement&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Scope Limit:**&lt;/span&gt; Examine ONLY files touched in &lt;span class="sb"&gt;`git diff HEAD~1`&lt;/span&gt; or current working tree.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Single Improvement Rule:**&lt;/span&gt; Identify and execute &lt;span class="gs"&gt;**exactly ONE**&lt;/span&gt; high-value refactoring. Do not attempt a full system rewrite.
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Zero Behavior Change:**&lt;/span&gt; The refactoring must preserve existing test coverage. Run tests before and after.

&lt;span class="gu"&gt;## Priority Checklist (Pick ONE)&lt;/span&gt;
&lt;span class="p"&gt;
*&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Guard Clauses:**&lt;/span&gt; Replace a nested &lt;span class="sb"&gt;`if/else`&lt;/span&gt; block with an early &lt;span class="sb"&gt;`require()`&lt;/span&gt; or &lt;span class="sb"&gt;`check()`&lt;/span&gt; guard clause.
&lt;span class="p"&gt;*&lt;/span&gt; [ ] &lt;span class="gs"&gt;**First-Class Collection:**&lt;/span&gt; Extract a raw list/map filtering pipeline into a dedicated First-Class Collection method.
&lt;span class="p"&gt;*&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Value Class:**&lt;/span&gt; Convert a naked domain parameter (e.g., &lt;span class="sb"&gt;`familyId: Int`&lt;/span&gt;) into a Kotlin &lt;span class="sb"&gt;`@JvmInline value class`&lt;/span&gt;.
&lt;span class="p"&gt;*&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Tell, Don't Ask:**&lt;/span&gt; Move a calculation from a service method directly onto the entity holding the data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Skill 4: &lt;code&gt;craft-code-review&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;craft-code-review&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Two-axis code review evaluating diffs along Standards (Object Calisthenics &amp;amp; Kotlin Idioms) and Spec (PRD/Issue requirements). Use during pull request review or before merging work-in-progress.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Craft Code Reviewer&lt;/span&gt;

Executes a two-axis review comparing the current diff against &lt;span class="gs"&gt;**Standards**&lt;/span&gt; (Software Craftsmanship / Object Calisthenics) and &lt;span class="gs"&gt;**Spec**&lt;/span&gt; (Issue / Business Requirements).

&lt;span class="gu"&gt;## Process&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Identify Context:**&lt;/span&gt; Capture diff via &lt;span class="sb"&gt;`git diff &amp;lt;fixed-point&amp;gt;...HEAD`&lt;/span&gt;. Read &lt;span class="sb"&gt;`CONTEXT.md`&lt;/span&gt; for domain terminology.
&lt;span class="p"&gt;2.&lt;/span&gt; &lt;span class="gs"&gt;**Standards Axis:**&lt;/span&gt; Evaluate diff against Calisthenics rules (Indentation depth, &lt;span class="sb"&gt;`else`&lt;/span&gt; keyword, primitive obsession, naked collections, &lt;span class="ge"&gt;*Tell, Don't Ask*&lt;/span&gt;, and over-engineering).
&lt;span class="p"&gt;3.&lt;/span&gt; &lt;span class="gs"&gt;**Spec Axis:**&lt;/span&gt; Verify acceptance criteria, check for missing edge cases or scope creep.

&lt;span class="gu"&gt;## Output Format&lt;/span&gt;

Present findings under separate headings without reranking:

&lt;span class="gu"&gt;### Standards Findings&lt;/span&gt;
&lt;span class="p"&gt;
*&lt;/span&gt; [Rule/Smell Name]: Quote hunk &amp;amp; suggest Kotlin fix.

&lt;span class="gu"&gt;### Spec Findings&lt;/span&gt;
&lt;span class="p"&gt;
*&lt;/span&gt; [Requirement ID/Line]: Missing or incorrectly implemented behavior.

&lt;span class="gu"&gt;### Summary&lt;/span&gt;
&lt;span class="p"&gt;
*&lt;/span&gt; Standards: X findings | Spec: Y findings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Continuous, Intentional Learning
&lt;/h2&gt;

&lt;p&gt;As Robert Heinlein wrote, &lt;em&gt;"When one teaches, two learn."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Software craftsmanship isn't about collecting tools, chasing trendy frameworks, or blindly following 18-year-old rules. It is about understanding the underlying domain problem deeply enough to choose the right trade-offs for that exact context.&lt;/p&gt;

&lt;p&gt;When you combine disciplined constraints like Object Calisthenics with modern Kotlin idioms and an AI assistant that actively challenges your design decisions, you stop writing clever code—and start building software that makes tomorrow easier than today.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What are your favorite Object Calisthenics rules to use (or break)?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>kotlin</category>
      <category>softwareengineering</category>
      <category>softwarecraftsmanship</category>
    </item>
    <item>
      <title>Stop Vibe-Checking Your AI Agents: The Complete Guide to the SKILL.md Lifecycle</title>
      <dc:creator>zerocool</dc:creator>
      <pubDate>Tue, 11 Aug 2026 14:17:28 +0000</pubDate>
      <link>https://dev.to/zerocoool/stop-vibe-checking-your-ai-agents-the-complete-guide-to-the-skillmd-lifecycle-36a1</link>
      <guid>https://dev.to/zerocoool/stop-vibe-checking-your-ai-agents-the-complete-guide-to-the-skillmd-lifecycle-36a1</guid>
      <description>&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%2Fjuox0z9xr6ebxj9h6ai5.webp" 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%2Fjuox0z9xr6ebxj9h6ai5.webp" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s be honest about how most of us build AI skills today.&lt;/p&gt;

&lt;p&gt;We sit down, write a few hundred lines of system prompts or instructions, run them once or twice in our local terminal, see that it works, and hit merge. We call it a day. There are no automated tests, no regression suites, and no validation gates.&lt;/p&gt;

&lt;p&gt;We pull changes based entirely on a &lt;em&gt;vibe check&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But here is the catch: AI skills are no longer just toys generating poetic text. In modern agentic workflows, your skills are triggering production deployments, drafting legal contracts, bootstrapping infrastructure, and communicating directly with internal databases via your APIs.&lt;/p&gt;

&lt;p&gt;When a traditional software function breaks, you get a noisy stack trace. When an AI skill breaks—and it &lt;em&gt;will&lt;/em&gt; break the second the underlying model receives a silent upstream update—it fails in absolute silence. It doesn’t crash. It simply hallucinates an answer with unearned confidence, directly to a user who trusts it.&lt;/p&gt;

&lt;p&gt;If your AI skills have the power of code, you need to start treating them like code. That means moving from vibes to engineering: design, validation, evaluation, and strict retirement. Let’s take a journey through what it actually takes to run a professional AI skill pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  What an AI Skill Actually Is Under the Hood
&lt;/h2&gt;

&lt;p&gt;Stripped of the marketing hype, an AI skill is remarkably simple: &lt;strong&gt;it’s a folder.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the root of this folder sits a single file: &lt;code&gt;SKILL.md&lt;/code&gt;. This file contains a YAML header (known as the frontmatter) followed by a body written in standard Markdown.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;frontmatter&lt;/strong&gt; tells the agent &lt;em&gt;when&lt;/em&gt; to use the skill.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;body&lt;/strong&gt; tells the agent &lt;em&gt;how&lt;/em&gt; to do the work.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;setup_nextjs_app&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use this skill when the user wants to bootstrap a new Next.js project with Tailwind CSS.&lt;/span&gt;
&lt;span class="na"&gt;allowed_tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;bash&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;file_writer&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Setup NextJS App&lt;/span&gt;
&lt;span class="s"&gt;Follow these steps to safely initialize the repository...&lt;/span&gt;

&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%2F83my0l081b2382ip6a3z.webp" 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%2F83my0l081b2382ip6a3z.webp" alt="SKILLS.md lifecycle" width="800" height="635"&gt;&lt;/a&gt;&lt;br&gt;
This format is a rapidly emerging open standard. Born out of research at Anthropic and open-sourced at &lt;code&gt;agentskills.io&lt;/code&gt;, it has been rapidly adopted across the ecosystem by tools like Claude Code, GitHub Copilot, Cursor, Mistral, and Gemini CLI. Think of a &lt;code&gt;SKILL.md&lt;/code&gt; file as the &lt;code&gt;package.json&lt;/code&gt; of the agentic era.&lt;/p&gt;

&lt;p&gt;The magic that keeps this system efficient is an architectural pattern called &lt;strong&gt;progressive disclosure&lt;/strong&gt;. If an agent had to read the full body of every single skill you wrote at the start of every user prompt, your context window would explode. Instead, agents load skills in three distinct waves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discovery:&lt;/strong&gt; The agent scans your repository but only reads the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; from the YAML frontmatter. This costs a tiny fraction of tokens (around 100 tokens per skill).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activation:&lt;/strong&gt; Only when a user’s prompt matches a specific description does the agent open the file and inject the full Markdown body into its context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution:&lt;/strong&gt; Scripts, templates, and complex environment references are fetched purely on-demand as the steps run.&lt;/li&gt;
&lt;/ul&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%2Fyfmfis0nhd8lqode1iny.webp" 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%2Fyfmfis0nhd8lqode1iny.webp" alt="SKILLS.md progressive disclosure" width="800" height="885"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This architectural reality reveals the number one reason why custom skills fail to trigger: &lt;strong&gt;it’s almost never a code problem; it’s a description problem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because the agent never looks at the body of the skill during the discovery phase, it relies entirely on the description to route the request. If your description reads like a documentation comment rather than an explicit behavioral trigger, your agent will walk right past it.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Two Families of Skills
&lt;/h2&gt;

&lt;p&gt;Not all skills are created equal. Understanding how they age dictates exactly how you need to test them. Anthropic separates them into two distinct categories:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Capability Uplift Skills
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does:&lt;/strong&gt; Teaches the model to do something it cannot do well natively (e.g., parsing a highly specific PDF format or generating a perfectly styled Word document).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifespan:&lt;/strong&gt; &lt;strong&gt;Short.&lt;/strong&gt; Obsolescence comes fast in this category. What a model fails at today might be handled flawlessly and natively by an upstream foundational model update a year from now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it needs evals:&lt;/strong&gt; To detect obsolescence. Your evaluations will warn you the moment a newer foundation model renders your custom code redundant.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Encoded Preference Skills
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it does:&lt;/strong&gt; It doesn’t teach the model anything fundamentally new—the model already understands every individual step. Instead, it sequences those steps according to &lt;em&gt;your company’s exact business logic&lt;/em&gt; or architectural workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifespan:&lt;/strong&gt; &lt;strong&gt;Long.&lt;/strong&gt; These are highly durable. They live as long as your internal business process lives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it needs evals:&lt;/strong&gt; To verify absolute fidelity to your workflow. You need to ensure the model doesn’t skip a mandatory compliance, security, or logging step over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Skip managing this lifecycle, and you will fall victim to &lt;strong&gt;skill rot&lt;/strong&gt;—a slow accumulation of dead folders and conflicting descriptions that pollute your discovery phase and confuse your router.&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%2Fdblanfb8qs0d3wj6ckj7.webp" 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%2Fdblanfb8qs0d3wj6ckj7.webp" alt="SKILLS.md life cycle" width="800" height="695"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Phase 1: Designing with Intent
&lt;/h2&gt;

&lt;p&gt;The most common trap is starting with the Markdown body. It feels natural to write out the beautiful, styled steps first, but expert engineering requires the exact inverse.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write the description first:&lt;/strong&gt; Treat it like a user prompt. If a developer wanted to invoke this skill explicitly, what would they type? Put those exact keywords into the description.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expose hidden assumptions:&lt;/strong&gt; Bugs love the spaces between what the model thinks it knows and what your environment actually expects. Before writing execution code, explicitly state three categories of hypotheses:&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Trigger assumptions:&lt;/em&gt; What should match, and critically, what should &lt;em&gt;not&lt;/em&gt; match?&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Environment assumptions:&lt;/em&gt; Does this skill assume an empty directory? A specific package manager? Active network access? (Pro tip: always write a step that checks these prerequisites before executing real work).&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Execution assumptions:&lt;/em&gt; What dependencies must be present? What is the strict sequence of events?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write the body as explicit directives:&lt;/strong&gt; Use numbered steps and authoritative vocabulary. &lt;em&gt;“Always use method()”&lt;/em&gt; performs exponentially better than &lt;em&gt;“It is recommended to use method()”&lt;/em&gt;. LLMs obey directives far better than they synthesize suggestions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Phase 2: The Human Quality Gate (Validation)
&lt;/h2&gt;

&lt;p&gt;Validation sits right between design and automated evaluation. Think of it as a manual code review checkpoint to see if a skill is clean enough to earn a spot in your test runner.&lt;/p&gt;

&lt;p&gt;Before committing, run through this &lt;strong&gt;7-point validation checklist&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the frontmatter syntactically complete and accurate?&lt;/li&gt;
&lt;li&gt;Does the description read like a routing trigger, not a comment?&lt;/li&gt;
&lt;li&gt;Does the body include explicit “when to apply” and “when to ignore” sections?&lt;/li&gt;
&lt;li&gt;Is the methodology structurally sound with numbered steps and zero &lt;code&gt;TODO&lt;/code&gt; items?&lt;/li&gt;
&lt;li&gt;Is the &lt;code&gt;allowed_tools&lt;/code&gt; block minimized? (If a skill only reads data, block it from running bash scripts).&lt;/li&gt;
&lt;li&gt;Is the exact output format stringently documented?&lt;/li&gt;
&lt;li&gt;Does it follow the Single Responsibility Principle? (One skill, one domain).&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Phase 3: Writing Targeted Evals
&lt;/h2&gt;

&lt;p&gt;An AI skill “eval” is not a massive, generalized academic benchmark. It is a highly targeted, reproducible unit test. It consists of four elements: a &lt;strong&gt;prompt&lt;/strong&gt;, an &lt;strong&gt;agent run execution trace&lt;/strong&gt;, a &lt;strong&gt;suite of checks&lt;/strong&gt;, and a &lt;strong&gt;historical score&lt;/strong&gt; to track regression over time.&lt;/p&gt;

&lt;p&gt;When defining what a “successful run” looks like, you must look across four distinct dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Outcome:&lt;/strong&gt; Did the agent finish the task? Does the generated application actually boot up?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Process:&lt;/strong&gt; Did it invoke the correct skill? Did it use the right tools, or did it go rogue?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Style:&lt;/strong&gt; Does the code respect your company’s formatting rules, nomenclature, and exact SDK imports?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Efficiency:&lt;/strong&gt; Did it achieve the goal optimally?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Efficiency is where invisible cost leaks hide. Two different skills can produce the exact same working code output. But if Skill A takes 3,000 tokens and Skill B takes 12,000 tokens because it repeatedly retried failing bash commands, Skill B represents an invisible architectural regression. You can only catch this by tracking the trace.&lt;/p&gt;
&lt;h3&gt;
  
  
  Building Your Automated Test Suite
&lt;/h3&gt;

&lt;p&gt;You don’t need thousands of test cases to start. A lean set of &lt;strong&gt;10 to 20 highly diverse prompts&lt;/strong&gt; is more than enough for a single skill. As users encounter real-world failures, harvest those edge cases and feed them directly into your test suite.&lt;/p&gt;

&lt;p&gt;Ensure your test set breaks down into these four core buckets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Invocation:&lt;/strong&gt; The prompt names the skill directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implicit Invocation:&lt;/strong&gt; The prompt describes a business scenario without mentioning the skill’s name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contextual Noise:&lt;/strong&gt; The prompt wraps the intent in realistic, chaotic developer conversations to test routing durability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Negative Controls:&lt;/strong&gt; Prompts designed specifically to see if the skill falsely triggers when it shouldn’t.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Phase 4: The 3-Layer Grading Matrix
&lt;/h2&gt;

&lt;p&gt;Once your tests run, how do you grade the output programmatically? You build a tiered grading structure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Layer 1: Deterministic Graders
&lt;/h3&gt;

&lt;p&gt;These are your unit tests. They are fast, completely reproducible, and dirt cheap. They read the JSON execution trace or the disk artifacts and evaluate binary realities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Did the agent write a &lt;code&gt;package.json&lt;/code&gt; to the disk?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Did the code import the correct SDK version?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Did it call the new method instead of the deprecated one?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layer is usually written in a few dozen lines of Python or TypeScript using simple regex, file checking, or AST parsing. If a check can be written deterministically, it &lt;em&gt;must&lt;/em&gt; be written deterministically.&lt;/p&gt;
&lt;h3&gt;
  
  
  Layer 2: LLM-as-a-Judge
&lt;/h3&gt;

&lt;p&gt;Deterministic code can tell you if a file exists, but it cannot tell you if the architectural trade-offs inside that file make sense. For qualitative assessment, we use a secondary LLM as an impartial judge, scoring the output against a highly granular grading rubric.&lt;/p&gt;

&lt;p&gt;To ensure your system can parse the evaluations automatically, enforce a strict JSON schema layout for your rubrics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://json-schema.org/draft-07/schema#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JSON Rubric for Deterministic Checks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"overall_pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"minimum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maximum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"boolean"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"overall_pass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checks"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When building an LLM judge, you must enforce two non-negotiable rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enforce a strict JSON schema output&lt;/strong&gt; so you can programmatically track scores over time in your CI pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the judge 3 to 5 times per test&lt;/strong&gt; and evaluate the score distribution. Because the judge itself is an LLM, its grading has a variance curve. Tighten your rubrics to minimize this drift.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Layer 3: Advanced Environment Runtime Checks
&lt;/h3&gt;

&lt;p&gt;The ultimate layer of confidence mimics a real production environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run a static analysis build check (&lt;code&gt;npm run build&lt;/code&gt; or &lt;code&gt;mvn compile&lt;/code&gt;) to catch broken imports.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;git status --porcelain&lt;/code&gt; to ensure the agent left a clean workspace.&lt;/li&gt;
&lt;li&gt;Spin up the containerized app and ping it with an automated &lt;code&gt;curl&lt;/code&gt; request to verify a &lt;code&gt;200 OK&lt;/code&gt; response.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Phase 5: Spotting “Outgrowth” and Retiring Skills
&lt;/h2&gt;

&lt;p&gt;Most teams are fantastic at creating skills, but terrible at deleting them. Over time, your codebase gets bloated with legacy instructions. Automated evals give you the exact instrument you need to clean house via two specific patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Catch Regressions:&lt;/strong&gt; Your skill worked perfectly a month ago. The model provider ships a stealth update, and suddenly the skill begins looping or failing. Scheduled CI evals will instantly sound the alarm before your users find out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spot Outgrowth:&lt;/strong&gt; You wrote a complex Capability Uplift skill in 2025 to help a model parse intricate markdown tables. By 2026, the native foundational model has improved so much that it can do this out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do you test for outgrowth? &lt;strong&gt;Run your eval suite with the skill completely turned off.&lt;/strong&gt; If the agent passes your rigorous tests without the extra instructions, the model has absorbed the capability natively. Your skill is officially dead weight. Move it to an &lt;code&gt;archive/&lt;/code&gt; folder, log the retirement date, and delete it.&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%2F2gdhtc5dcrzzxnetb01g.webp" 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%2F2gdhtc5dcrzzxnetb01g.webp" alt="SKILLS.md deprecation strategy" width="754" height="616"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Shift from How to What: The “Skills as Code” Matrix
&lt;/h2&gt;

&lt;p&gt;If we peel back the AI hype and look at the structural design of a &lt;code&gt;SKILL.md&lt;/code&gt; setup, it becomes undeniable: &lt;strong&gt;AI skills are code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at this direct architectural mapping as a clean side-by-side alignment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The YAML Description&lt;/strong&gt; ➔ Your &lt;strong&gt;Public API Contract&lt;/strong&gt; (It handles discovery and routing).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Markdown Body&lt;/strong&gt; ➔ Your &lt;strong&gt;Implementation Details&lt;/strong&gt; (The sequential instructions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Allowed Tools&lt;/strong&gt; ➔ Your &lt;strong&gt;Core Dependencies&lt;/strong&gt; (Filesystem, bash, or API permissions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Evals&lt;/strong&gt; ➔ Your &lt;strong&gt;Unit &amp;amp; Integration Tests&lt;/strong&gt; (The absolute guardrails of success).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Evolution of the Body
&lt;/h3&gt;

&lt;p&gt;Right now, a &lt;code&gt;SKILL.md&lt;/code&gt; file is an &lt;em&gt;imperative&lt;/em&gt; implementation plan. It explicitly holds the model’s hand, telling it what to do step-by-step.&lt;/p&gt;

&lt;p&gt;But look closely at what a robust evaluation suite actually contains. It holds target prompts, expected file artifacts, explicit formatting conventions, and token efficiency budgets. Your evals already describe the &lt;em&gt;what&lt;/em&gt;—while remaining entirely silent on the &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In traditional software history, every time an industry transitions from telling the machine &lt;em&gt;how&lt;/em&gt; to do something to simply telling it &lt;em&gt;what&lt;/em&gt; we want achieved, engineering capabilities skyrocket and friction drops. We saw it when manual imperative scripts gave way to declarative infrastructure (like Terraform or Kubernetes), and we saw it when hand-crafted loop indexing gave way to SQL query planners.&lt;/p&gt;

&lt;p&gt;As foundational LLMs continue to become more capable, the imperative Markdown body of your custom skills is going to shrink. Models will already inherently know how to safely execute standard engineering workflows. Legacy capability uplift instructions will vanish entirely. Your business-specific preference skills will reduce down to a single paragraph of pure intent, a few gold-standard examples, and a rigorous test set asserting your company’s constraints.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The code inside the skill body is temporary. The evaluation contract is permanent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, your evals verify your skills. Tomorrow, &lt;strong&gt;the eval could &lt;em&gt;be&lt;/em&gt; the skill.&lt;/strong&gt; The description of success will become so precise that a highly capable model will simply deduce the implementation path dynamically at runtime.&lt;/p&gt;

&lt;p&gt;Writing strict, automated e-vals today isn’t just a defensive quality-assurance practice to keep your current agents from breaking next week—it is a long-term architectural investment.&lt;/p&gt;

&lt;p&gt;Stop guessing if your AI agents actually work. Build your contracts, establish your baselines, and start measuring.&lt;/p&gt;




&lt;h3&gt;
  
  
  Sources &amp;amp; Further Reading
&lt;/h3&gt;

&lt;p&gt;To dive deeper into the AI agent skill lifecycle, engineering workflows, and evaluation strategies, explore these official open standards and research papers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;[Anthropic Claude Blog]&lt;/strong&gt; &lt;a href="https://claude.com/blog/improving-skill-creator-test-measure-and-refine-agent-skills" rel="noopener noreferrer"&gt;Improving Skill Creator: Test, Measure, and Refine Agent Skills&lt;/a&gt; – The foundational framework detailing how to refine custom agent capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[OpenAI Developers]&lt;/strong&gt; &lt;a href="https://developers.openai.com/blog/eval-skills" rel="noopener noreferrer"&gt;Eval Skills &amp;amp; Agentic Frameworks&lt;/a&gt; – OpenAI’s perspective on standardizing evaluations within enterprise-grade agent layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Philipp Schmid]&lt;/strong&gt; &lt;a href="https://www.philschmid.de/testing-skills" rel="noopener noreferrer"&gt;Testing AI Agent Skills in Production&lt;/a&gt; – A hands-on, practical technical guide on building and deploying automated test runners for LLM actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[ArXiv Research]&lt;/strong&gt; &lt;a href="https://arxiv.org/html/2602.12670v1" rel="noopener noreferrer"&gt;Evaluation and Lifecycles of Agentic Skills&lt;/a&gt; – The core academic research paper breaking down token consumption patterns, skill drift, and model outgrowth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Ultimate Claude Code Guide by Bruniaux]&lt;/strong&gt; &lt;a href="https://www.google.com/search?q=https://cc.bruniaux.com/guide/learning-path/05-skills/%23skill-lifecycle" rel="noopener noreferrer"&gt;Learning Path: Skill Lifecycle &amp;amp; Open Standards&lt;/a&gt; – An extensive deep-dive into the mechanics of the open &lt;code&gt;SKILL.md&lt;/code&gt; format and the architecture of progressive disclosure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[Anthropic Developer Docs]&lt;/strong&gt; &lt;a href="https://platform.claude.com/docs/en/test-and-evaluate/eval-tool" rel="noopener noreferrer"&gt;Using the Evaluation Tool in Console&lt;/a&gt; – The step-by-step user manual for configuring matrix test sets and scoring model responses quantitatively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[GitHub Awesome-Copilot]&lt;/strong&gt; &lt;a href="https://github.com/github/awesome-copilot/blob/main/skills/agentic-eval/SKILL.md" rel="noopener noreferrer"&gt;Official agentic-eval Skill Standard&lt;/a&gt; – The gold-standard open-source reference template implementing automated self-critique loops and JSON-structured rubrics.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>development</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>The Go Era: What Actually Matters in TypeScript 7.0 (Beyond the 10x Speedup)</title>
      <dc:creator>zerocool</dc:creator>
      <pubDate>Fri, 17 Jul 2026 09:22:03 +0000</pubDate>
      <link>https://dev.to/zerocoool/the-go-era-what-actually-matters-in-typescript-70-beyond-the-10x-speedup-16f6</link>
      <guid>https://dev.to/zerocoool/the-go-era-what-actually-matters-in-typescript-70-beyond-the-10x-speedup-16f6</guid>
      <description>&lt;p&gt;The tech world has spent the last year buzzing about the complete rewrite of the TypeScript compiler. Now that &lt;strong&gt;TypeScript 7.0&lt;/strong&gt; is officially out, the headline is clear: a native Go port delivering 8x to 12x build speedups and an instant editor experience.&lt;/p&gt;

&lt;p&gt;But if we look past the raw performance numbers, TypeScript 7.0 represents something much deeper. It is the most aggressive modernization sweep in the language's history. The TypeScript team used this architectural migration to eliminate a decade of technical debt, kill off legacy web standards, and restructure how the compiler interacts with the JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;If you are planning to upgrade your frontend or backend repositories, here is what actually matters, why the team chose Go, and the breaking changes you need to prepare for.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Architectural Plot Twist: Why Go and Not Rust?
&lt;/h2&gt;

&lt;p&gt;When Microsoft first announced they were moving away from a bootstrapped JavaScript compiler to a native binary, the collective internet assumed they would choose Rust—the darling of the modern frontend tooling space (used by SWC, Turbo, and Oxc).&lt;/p&gt;

&lt;p&gt;Instead, the team chose &lt;strong&gt;Go&lt;/strong&gt;, sparking heavy debate across the community. The reasoning reveals exactly how the TS team prioritizes stability over absolute micro-benchmarks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bug-for-Bug Compatibility:&lt;/strong&gt; The goal wasn't to write a brand-new compiler from scratch; it was a 1:1 faithful translation of the massive, decade-old TypeScript codebase. Go’s straightforward syntax allowed a clean mapping of existing JavaScript logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Memory Model Challenge:&lt;/strong&gt; Compilers are inherently full of deeply nested, circular object graphs (ASTs, symbol tables, type structures). Managing these in Rust without heavily leaning on &lt;code&gt;unsafe&lt;/code&gt; blocks or running into a brick wall with the borrow checker would have taken years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage Collection Alignment:&lt;/strong&gt; Go’s built-in garbage collection mirrors JavaScript’s memory model elegantly. This allowed the team to achieve multi-threaded parallelism safely and ship a stable production compiler years faster than a Rust rewrite would have allowed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. The Great Modernization Sweep (The Real Breaking Changes)
&lt;/h2&gt;

&lt;p&gt;TypeScript 7.0 acts as a strict forcing function to push the entire ecosystem into the modern era. If your repository relies on configurations or patterns from five years ago, TS 7.0 will throw &lt;strong&gt;hard compilation errors&lt;/strong&gt; instead of warnings.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Death of Legacy Formats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Goodbye ES5:&lt;/strong&gt; The &lt;code&gt;ES5&lt;/code&gt; output target is officially dead. TypeScript 7.0 defaults its target to the current stable ECMAScript version preceding &lt;code&gt;esnext&lt;/code&gt;. If you still need to support legacy browsers that don't support ES6 classes, you must handle down-leveling via an external bundler or babel step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legacy Modules Prohibited:&lt;/strong&gt; Support for legacy module systems (&lt;code&gt;AMD&lt;/code&gt;, &lt;code&gt;UMD&lt;/code&gt;, and &lt;code&gt;SystemJS&lt;/code&gt;) has been completely discontinued.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Elimination of &lt;code&gt;downlevelIteration&lt;/code&gt;:&lt;/strong&gt; Iteration helpers for ancient targets have been stripped out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Strict Configuration Defaults
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;strict&lt;/code&gt; is True by Default:&lt;/strong&gt; You no longer opt-in to strict type-checking; it is the default baseline behavior for any new initialization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;module&lt;/code&gt; Defaults to &lt;code&gt;esnext&lt;/code&gt;:&lt;/strong&gt; This ensures modern bundlers (Vite, Rsbuild, etc.) receive standard ESM out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Path Resolution Adjustments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;baseUrl&lt;/code&gt; is Dead:&lt;/strong&gt; You can no longer use &lt;code&gt;baseUrl&lt;/code&gt; for absolute path mappings. TypeScript 7.0 strictly requires you to use the modern &lt;code&gt;paths&lt;/code&gt; property for aliases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;rootDir&lt;/code&gt; Restrictions:&lt;/strong&gt; &lt;code&gt;rootDir&lt;/code&gt; now defaults to &lt;code&gt;./&lt;/code&gt;. If your &lt;code&gt;tsconfig.json&lt;/code&gt; sits in your root folder but your source code is inside a &lt;code&gt;/src&lt;/code&gt; directory, you &lt;strong&gt;must&lt;/strong&gt; explicitly define &lt;code&gt;"rootDir": "./src"&lt;/code&gt;. Failing to do so will alter your build's output directory layout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global &lt;code&gt;types&lt;/code&gt; are Isolated:&lt;/strong&gt; Previously, TypeScript would automatically scan your entire &lt;code&gt;node_modules/@types&lt;/code&gt; folder and inject them globally. TS 7.0 defaults the &lt;code&gt;types&lt;/code&gt; array to &lt;code&gt;[]&lt;/code&gt; (empty). If your backend relies on Node global variables (like &lt;code&gt;process.env&lt;/code&gt;) or your frontend relies on browser testing globals, you must list them explicitly (e.g., &lt;code&gt;"types": ["node"]&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Modern ECMAScript Realignment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Import Assertions Banned:&lt;/strong&gt; The legacy &lt;code&gt;assert { type: "json" }&lt;/code&gt; syntax has been completely dropped. You must use the official ECMAScript standard: &lt;code&gt;with { type: "json" }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;module&lt;/code&gt; Namespace Fix:&lt;/strong&gt; You can no longer use the &lt;code&gt;module&lt;/code&gt; keyword to declare code namespaces (e.g., &lt;code&gt;module MyNamespace {}&lt;/code&gt;). You must use the &lt;code&gt;namespace&lt;/code&gt; keyword exclusively.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. The Language Fix: Unicode-Aware Types
&lt;/h2&gt;

&lt;p&gt;While the core type-checking logic is structurally identical to previous versions, there is a major language fix under the hood involving template literal types.&lt;/p&gt;

&lt;p&gt;In older versions of TypeScript, string manipulation at the type level could easily break when encountering surrogate pairs, emojis, or specific international characters. TypeScript 7.0 correctly preserves &lt;strong&gt;Unicode code points&lt;/strong&gt; during type inference. If your project does heavy string-manipulation types (such as routing schemas, internationalization keys, or database ORM typings involving special characters), types will no longer mysteriously break when facing an emoji.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Rebuilt File Watching
&lt;/h2&gt;

&lt;p&gt;If you spend your day running &lt;code&gt;tsc --watch&lt;/code&gt;, TypeScript 7.0 introduces an entirely new filesystem watcher. Rather than relying on computationally heavy polling mechanisms that slow down dramatically when dealing with giant &lt;code&gt;node_modules&lt;/code&gt; folders, the team successfully ported the core logic of the highly efficient &lt;strong&gt;Parcel file-watcher&lt;/strong&gt; (&lt;code&gt;@parcel/watcher&lt;/code&gt;) directly into Go.&lt;/p&gt;

&lt;p&gt;The result is a drastically lower CPU and memory footprint on your machine while watch-mode sits in the background of your local frontend and backend servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Your Biggest Immediate Headache: The Missing JS API
&lt;/h2&gt;

&lt;p&gt;There is one massive catch you need to look out for if you upgrade today: &lt;strong&gt;TypeScript 7.0 does not ship with a programmatic JavaScript API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because the entire compiler engine was moved to Go, JavaScript-based tools cannot import and execute compiler methods natively yet. This affects critical tools in your toolchain—most notably &lt;strong&gt;&lt;code&gt;typescript-eslint&lt;/code&gt;&lt;/strong&gt;, along with various framework-specific compiler extensions (like those for Vue or Svelte templates).&lt;/p&gt;

&lt;p&gt;To prevent the ecosystem from shattering, Microsoft has introduced a bridging strategy. If you want to use TS 7.0 for your builds but still need your linter to function, you have to run a dual-installation using npm aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:@typescript/typescript6@^6.0.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript/native"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:typescript@^7.0.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that your development tools can fall back to the JavaScript-based TypeScript 6.0 API, while your actual code compilation uses the native Go-based &lt;code&gt;tsc&lt;/code&gt; runner. The TypeScript team promises a brand-new native programmatic API will arrive with &lt;strong&gt;TypeScript 7.1&lt;/strong&gt; in a few months to resolve this permanently.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;TypeScript 7.0 is far more than a performance patch. It represents Microsoft drawing a line in the sand and leaving the legacy web behind. By shedding ES5 targets, killing dead module frameworks, and tightening configuration defaults, it delivers a sleeker, faster, and remarkably modern toolchain.&lt;/p&gt;

&lt;p&gt;If your codebase is already aligned with modern ESM standards, the upgrade will feel like an absolute gift to your daily developer workflow. If you are harboring legacy tech debt, TS 7.0 is the wake-up call to finally clean it up.&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
  </channel>
</rss>
