<?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: Renan Franca</title>
    <description>The latest articles on DEV Community by Renan Franca (@renanfranca).</description>
    <link>https://dev.to/renanfranca</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%2F792637%2F733e6698-784d-4f76-8e2f-888db5b58b20.jpeg</url>
      <title>DEV Community: Renan Franca</title>
      <link>https://dev.to/renanfranca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renanfranca"/>
    <language>en</language>
    <item>
      <title>How Seed4J Validates Compatibility</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 19:44:29 +0000</pubDate>
      <link>https://dev.to/renanfranca/how-seed4j-validates-compatibility-2pdo</link>
      <guid>https://dev.to/renanfranca/how-seed4j-validates-compatibility-2pdo</guid>
      <description>&lt;p&gt;Today, developing a system usually means working with several frameworks and technologies. Even when you already know a technology well, a question comes up whenever you start a new project: do you use the latest version, or stick with the version you already know?&lt;/p&gt;

&lt;p&gt;When you choose the latest version, it does not always work well with the other technologies you were using with the previous one. So compatibility between technologies is still a real challenge.&lt;/p&gt;

&lt;p&gt;And what about the project you already created? How often do you update its dependencies? Updating a version always comes with the risk and cost of breaking something. And if something does break, how do you validate that the entire configuration is still working correctly?&lt;/p&gt;

&lt;p&gt;These questions, combined with the number of modules, frameworks, and technologies that need to work together, are exactly what Seed4J helps to address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://start.seed4j.com/" rel="noopener noreferrer"&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%2Fli560g26x3zstkcs2hcd.png" alt="The Seed4J landscape showing modules and their relationships" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Seed4J module landscape at &lt;a href="https://start.seed4j.com/" rel="noopener noreferrer"&gt;start.seed4j.com&lt;/a&gt;, captured on September 12, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Seed4J uses tools such as Renovate and GitHub Actions to update library versions and, as part of its pipeline, generate many different projects. And I really mean many. It currently generates 25 projects using different stacks and combinations of technologies: Angular, Reactive, Vue, Thymeleaf, Spring Boot, TypeScript, and others.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/renovate.json" rel="noopener noreferrer"&gt;current Renovate configuration&lt;/a&gt; checks for dependency updates daily. Minor updates can be merged automatically, but only after all required status checks pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 25 configurations in the current CI matrix
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/.github/workflows/github-actions.yml#L222-L279" rel="noopener noreferrer"&gt;generation matrix&lt;/a&gt; uses Maven, YAML, npm, Java 25, and the Node.js LTS release by default. Six configurations intentionally change one of those defaults: Gradle for &lt;code&gt;fullappgradle&lt;/code&gt;, Spring properties for &lt;code&gt;mariadbapp&lt;/code&gt;, Java 26 early access for &lt;code&gt;mongodbapp&lt;/code&gt;, pnpm for &lt;code&gt;typescriptapp&lt;/code&gt; and &lt;code&gt;vueoauth2app&lt;/code&gt;, and the latest Node.js release for &lt;code&gt;vuejwtapp&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CI configuration&lt;/th&gt;
&lt;th&gt;Main combination&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fullappmaven&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maven full stack with Spring Boot MVC, PostgreSQL, JPA, Liquibase, JWT, KiPe, Vue, TiKUI, architecture, quality, and deployment tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fullappgradle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The same full stack built with Gradle and the Node Gradle plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;oauth2app&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, OAuth2 account support, OpenAPI, Cucumber, KiPe authorization, and a sample feature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mysqlapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, MySQL, JPA, Liquibase, JWT, OpenAPI, Cucumber, and sample persistence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mariadbapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, MariaDB, JPA, Liquibase, OpenAPI, Ehcache, and Spring properties configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mssqlapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Microsoft SQL Server, JPA, and OpenAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flywayapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, PostgreSQL, JPA, Flyway, JWT, OpenAPI, Cucumber, and sample persistence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;eurekaapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Eureka client, and Spring Cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;consulapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC and Consul&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gatewayapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot WebFlux, Netty, Actuator, Eureka, Spring Cloud, and API Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mongodbapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, MongoDB, Mongock, JWT, OpenAPI, Cucumber, and sample persistence on Java 26 early access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;redisapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Redis, JWT, OpenAPI, and Cucumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cassandraapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Cassandra migrations, JWT, OpenAPI, Cucumber, KiPe authorization, and sample persistence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;neo4japp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Neo4j migrations, JWT, OpenAPI, and Cucumber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;angularjwtapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Angular, internationalization, Tailwind CSS, TiKUI, JWT, OpenAPI, and Cypress component tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reactapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, React, TypeScript, i18next, TiKUI, JWT, OpenAPI, and Cypress component tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vuejwtapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Vue, Router, internationalization, Pinia, TiKUI, JWT, OpenAPI, Playwright component tests, and Cypress end-to-end tests on the latest Node.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vueoauth2app&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Vue, Router, internationalization, Pinia, TiKUI, Keycloak OAuth2, Playwright component tests, and Cypress end-to-end tests using pnpm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kafkaapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Spring for Apache Kafka, and AKHQ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pulsarapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC and Spring for Apache Pulsar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reactiveapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot WebFlux, Netty, Actuator, and OpenAPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;angularoauth2app&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Angular, OAuth2 account support, OpenAPI, and Keycloak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;seed4jextension&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot and a Seed4J extension foundation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;typescriptapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A standalone TypeScript project with Prettier, optional types, and Sonar analysis using pnpm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;thymeleafapp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spring Boot MVC, Thymeleaf, Tailwind CSS, HTMX, and WebJars&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table summarizes each project rather than listing every module. The complete, executable compositions live in &lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/tests-ci/generate.sh" rel="noopener noreferrer"&gt;&lt;code&gt;tests-ci/generate.sh&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens on &lt;code&gt;main&lt;/code&gt; and pull requests
&lt;/h2&gt;

&lt;p&gt;On a push to &lt;code&gt;main&lt;/code&gt;, GitHub Actions starts one generation job for each of the 25 configurations and runs the relevant checks for every generated project. Depending on the project, that can include Maven verification, a Gradle build, JavaScript coverage, Sonar analysis, linting, frontend component tests, supporting Docker services, and application startup.&lt;/p&gt;

&lt;p&gt;On a pull request, each matrix job first generates the project from &lt;code&gt;main&lt;/code&gt; and calculates a content hash. It then generates the same configuration from the pull request branch. That means up to 50 generation executions: 25 from &lt;code&gt;main&lt;/code&gt; and 25 from the branch. The generated project tests run when the two outputs differ or when a valid &lt;code&gt;main&lt;/code&gt; baseline is unavailable. The &lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/.github/workflows/github-actions.yml#L281-L442" rel="noopener noreferrer"&gt;workflow records this comparison directly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/seed4j/seed4j/actions/runs/34088809580" rel="noopener noreferrer"&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%2Fuoktqjyuueehi2agehjw.png" alt="Successful Seed4J GitHub Actions workflow showing 25 completed generation jobs" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Seed4J build &lt;a href="https://github.com/seed4j/seed4j/actions/runs/34088809580" rel="noopener noreferrer"&gt;#31249&lt;/a&gt; completed all 25 generation jobs after Renovate updated &lt;code&gt;lint-staged&lt;/code&gt; to 17.4.1.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It generates projects with these different combinations and runs their tests to verify whether a newly released version breaks anything.&lt;/p&gt;

&lt;p&gt;If a new version causes a problem, project contributors can identify the incompatibility and fix it manually. In other cases, they can simply wait for a newer version of the library before updating.&lt;/p&gt;

&lt;p&gt;This gives Seed4J a huge advantage: you can add a module or framework to your project already knowing that the configuration actually works. The Seed4J pipeline has already validated the compatibility between those technologies.&lt;/p&gt;

&lt;p&gt;That validation has a defined boundary. The pipeline proves the 25 curated compositions exercised by CI; it does not claim that every theoretically possible combination of Seed4J modules has been tested together.&lt;/p&gt;

&lt;p&gt;And today, with advances in AI, vulnerabilities are being discovered faster and faster. Updating a library is no longer just about getting a new feature. It is also a way to avoid remaining exposed to a recently discovered vulnerability.&lt;/p&gt;

&lt;p&gt;This is already visible in real projects. Google's AI-assisted fuzzing work reported &lt;a href="https://security.googleblog.com/2024/11/leveling-up-fuzzing-finding-more.html" rel="noopener noreferrer"&gt;26 new vulnerabilities in open source projects&lt;/a&gt;, including CVE-2024-9143 in OpenSSL. Faster discovery makes a reliable dependency update and validation loop even more valuable.&lt;/p&gt;

&lt;p&gt;That is the power of Seed4J.&lt;/p&gt;

&lt;p&gt;It allows you to focus mainly on programming your business rules. Knowing how to use the technologies is still the developer's responsibility. But all the work involved in configuring the environment correctly and making sure those technologies are compatible is something Seed4J already handles for you, reliably and consistently.&lt;/p&gt;

&lt;p&gt;If this perspective was useful, consider giving &lt;a href="https://github.com/seed4j/seed4j" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt; and &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt; a star 🌟 on GitHub. It helps more people discover the projects and follow their evolution.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://start.seed4j.com/" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/.github/workflows/github-actions.yml#L222-L279" rel="noopener noreferrer"&gt;Seed4J generation matrix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/tests-ci/generate.sh" rel="noopener noreferrer"&gt;Seed4J generated project compositions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j/blob/4eebd07bce14c9a6ac70bace157fcc616133e950/renovate.json" rel="noopener noreferrer"&gt;Seed4J Renovate configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j/actions/runs/34088809580" rel="noopener noreferrer"&gt;Seed4J build #31249&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://security.googleblog.com/2024/11/leveling-up-fuzzing-finding-more.html" rel="noopener noreferrer"&gt;Google Online Security Blog: Leveling Up Fuzzing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>githubactions</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>What Changed When the Same Kata Needed a UI</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:48:21 +0000</pubDate>
      <link>https://dev.to/renanfranca/what-changed-when-the-same-kata-needed-a-ui-bco</link>
      <guid>https://dev.to/renanfranca/what-changed-when-the-same-kata-needed-a-ui-bco</guid>
      <description>&lt;h2&gt;
  
  
  The next question needed a visible result
&lt;/h2&gt;

&lt;p&gt;I began this exploration in &lt;a href="https://renanfranca.github.io/from-an-empty-repository-to-a-java-kata-one-module-at-a-time.html" rel="noopener noreferrer"&gt;From an Empty Repository to a Java Kata, One Module at a Time&lt;/a&gt;, following one Codex run from an almost empty repository to a Java project and a String Calculator implementation. Seed4J CLI gave the agent modules it could inspect and combine into the project foundation.&lt;/p&gt;

&lt;p&gt;I then &lt;a href="https://renanfranca.github.io/what-six-codex-runs-taught-me-about-tool-design.html" rel="noopener noreferrer"&gt;compared six Codex runs&lt;/a&gt;. Their paths through the same workflow varied, but all finished as compact Java libraries.&lt;/p&gt;

&lt;p&gt;For the next step, I wanted differences that were visible without reading a module history or scorecard. Hangman was useful because its original specification allowed either a game library or a playable interface.&lt;/p&gt;

&lt;p&gt;For the &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-kata" rel="noopener noreferrer"&gt;first Hangman experiment&lt;/a&gt;, Luna, Terra and Sol received the same prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implement the specification in SPEC.md using the already-installed Seed4J CLI tool as support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The specification described the user interface as optional. All three runs satisfied the shared library behavior, but none delivered a playable version of the game.&lt;/p&gt;

&lt;p&gt;That result raised a more focused question: what would change if a working interface became mandatory? For the &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata" rel="noopener noreferrer"&gt;second Hangman experiment&lt;/a&gt;, I kept the game rules and models, then changed the requirement in both the specification and the prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implement the specification in SPEC.md. A functional user interface of your choice is a mandatory deliverable. Use the already-installed Seed4J CLI tool as support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One mandatory deliverable looked like a small change. In practice, it added decisions about interaction, rendering, styling, application state and browser validation to the existing choices of language, build and tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  The controlled parts stayed controlled
&lt;/h2&gt;

&lt;p&gt;Both experiments used Luna, Terra and Sol with &lt;code&gt;xhigh&lt;/code&gt; reasoning effort. Every run started from its experiment's frozen base, received the same prompt as the other runs in that repository and used the same Seed4J skill, which was stored in the repository alongside the experiment.&lt;/p&gt;

&lt;p&gt;The environment also stayed the same: Seed4J CLI 0.0.4, Seed4J runtime 2.2.0 and the same host. Each implementation was preserved on its own branch before evaluation.&lt;/p&gt;

&lt;p&gt;This does not make the experiment large enough to describe how a model behaves in general. It does make the six resulting snapshots easier to compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  The single prompt was a stress test
&lt;/h2&gt;

&lt;p&gt;One clarification matters here: this is not how I would recommend working with a coding agent. Each run received one implementation prompt. There was no later conversation to plan the work or provide architectural direction. That deliberately removed one of the most valuable parts of agent collaboration: discussing options before changing the repository.&lt;/p&gt;

&lt;p&gt;I used that constraint as a stress test for the Seed4J CLI workflow. I wanted to observe how an agent would discover the active module catalog, choose capabilities and react to plan or environment feedback when the human provided almost no guidance beyond the specification. This setup describes what happened under low collaboration; it does not estimate how much Seed4J improved the result.&lt;/p&gt;

&lt;p&gt;In a real project, I would plan with the agent first. The agent could inspect &lt;code&gt;seed4j list&lt;/code&gt;, consult the help for relevant modules and use &lt;code&gt;apply-set --plan&lt;/code&gt; to examine the proposed operations without changing the project. It could then turn the available capabilities into concrete questions. A valid Seed4J plan could have combined a Spring Boot backend and a Vue frontend, for example, before we refined boundaries, tests and interaction together.&lt;/p&gt;

&lt;p&gt;So this experiment is not evidence that one prompt is enough. It asks a narrower question: what paths do agents take through Seed4J when the planning conversation is intentionally withheld?&lt;/p&gt;

&lt;h2&gt;
  
  
  The shared behavior is the baseline
&lt;/h2&gt;

&lt;p&gt;All six implementations passed their shared functional checks. That matters here only as a baseline: the Seed4J paths are being compared among implementations that reached the required behavior. The behavior score itself is not the subject of this article.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-kata/blob/main/MODEL_EVALUATION.md" rel="noopener noreferrer"&gt;library kata report&lt;/a&gt; and the &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/blob/main/MODEL_EVALUATION.md" rel="noopener noreferrer"&gt;UI kata report&lt;/a&gt; use complete rubrics with a total of 100 points that also evaluate specification correctness, tests and design. For this comparison, the relevant slice is the Seed4J effectiveness category, worth 35 points:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Library kata: Seed4J /35&lt;/th&gt;
&lt;th&gt;UI kata: Seed4J /35&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Luna&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terra&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sol&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Those 35 points cover discovery and help, preflight and planning, module choice and order, explicit parameters, history and wrapper usage. The deductions show what the totals summarize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Luna:&lt;/strong&gt; In the library kata, the project had no wrapper, costing three points. In the UI kata, the unnecessary &lt;code&gt;logs-spy&lt;/code&gt; module cost one point, and the &lt;code&gt;maven-wrapper&lt;/code&gt; commit also included handwritten implementation files, costing another point for commit coherence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terra:&lt;/strong&gt; Both runs earned 35/35 through explicit parameters, valid compositions, appropriate wrappers and coherent module histories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sol:&lt;/strong&gt; In the library kata, selecting &lt;code&gt;approval-tests&lt;/code&gt; without using it in the final tests cost two points. In the UI kata, the failed application and retry left two &lt;code&gt;init&lt;/code&gt; history records, costing one point for commit coherence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These scores do not rank the overall quality of the models or products. They summarize only the observable use of Seed4J CLI and lead into the module choices, commands and feedback below.&lt;/p&gt;

&lt;h2&gt;
  
  
  One requirement, three products
&lt;/h2&gt;

&lt;p&gt;Luna composed a Java application with Spring Boot and Thymeleaf. Terra and Sol both selected TypeScript, React and Vite, yet they still produced different layouts, game flows and visual identities.&lt;/p&gt;

&lt;p&gt;The screenshots below show the real winning state from each preserved implementation. They are not mockups created for this post.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Luna&lt;/th&gt;
&lt;th&gt;Terra&lt;/th&gt;
&lt;th&gt;Sol&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/tree/main/evidence/screenshots/luna-xhigh" rel="noopener noreferrer"&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%2Fvdar2grru2n5fkvjguxy.png" alt="Luna Spring Boot and Thymeleaf Hangman winning state" width="800" height="556"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/tree/main/evidence/screenshots/terra-xhigh" rel="noopener noreferrer"&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%2F0y8hm0vvu0h92l42q3y8.png" alt="Terra React and Vite Hangman winning state" width="800" height="556"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/tree/main/evidence/screenshots/sol-xhigh" rel="noopener noreferrer"&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%2F2teghknuyvyr1e9asuqm.png" alt="Sol React and Vite Hangman winning state" width="800" height="556"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What interested me most was not the visual variation itself. It was that Seed4J CLI gave the agents a common way to discover, validate and apply different combinations of modules while they worked toward the same functional target. Luna used ten modules around Spring Boot and Thymeleaf; Terra and Sol used four around TypeScript and React. The resulting products were not identical, but all three passed the shared domain checks and the complete browser journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seed4J made those choices inspectable
&lt;/h2&gt;

&lt;p&gt;In every run, Codex first discovered the active CLI and module catalog, inspected relevant module help and produced a plan for inspection before applying any changes.&lt;/p&gt;

&lt;p&gt;For the library kata, that led to compact Java and Maven foundations. Luna selected &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;maven-java&lt;/code&gt;. Terra added &lt;code&gt;maven-wrapper&lt;/code&gt; after the environment showed that global Maven was unavailable. Sol also selected &lt;code&gt;approval-tests&lt;/code&gt;, although its final tests did not use that capability.&lt;/p&gt;

&lt;p&gt;The mandatory UI widened the available paths. The commands below preserve the arguments and values from the recorded runs, with line breaks added for readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Luna corrected the composition before applying it
&lt;/h3&gt;

&lt;p&gt;Luna's &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/blob/4e7a814af62f67bf90120a45516c142da38d543a/CONVERSATION_TRANSCRIPT.md" rel="noopener noreferrer"&gt;first plan&lt;/a&gt; requested five Spring and Java modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  maven-java &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot-tomcat &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot-thymeleaf &lt;span class="se"&gt;\&lt;/span&gt;
  thymeleaf-template &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Hangman UI Kata'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--package-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;com.example.hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--server-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--spring-configuration-format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;properties &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-of-line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seed4J rejected the composition without changing the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Preflight: INVALID
Missing modules: init, java-base, logs-spy, spring-boot-mvc-empty
Unused option: --end-of-line
No changes were applied.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luna added the required modules explicitly, removed the unused option and planned again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  init &lt;span class="se"&gt;\&lt;/span&gt;
  maven-java &lt;span class="se"&gt;\&lt;/span&gt;
  java-base &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot-mvc-empty &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot-tomcat &lt;span class="se"&gt;\&lt;/span&gt;
  logs-spy &lt;span class="se"&gt;\&lt;/span&gt;
  spring-boot-thymeleaf &lt;span class="se"&gt;\&lt;/span&gt;
  thymeleaf-template &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Hangman UI Kata'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--package-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;com.example.hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--server-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--spring-configuration-format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;properties &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time the preflight was valid. Seed4J resolved the order as &lt;code&gt;init&lt;/code&gt; → &lt;code&gt;maven-java&lt;/code&gt; → &lt;code&gt;java-base&lt;/code&gt; → &lt;code&gt;spring-boot&lt;/code&gt; → &lt;code&gt;logs-spy&lt;/code&gt; → &lt;code&gt;spring-boot-mvc-empty&lt;/code&gt; → &lt;code&gt;spring-boot-thymeleaf&lt;/code&gt; → &lt;code&gt;spring-boot-tomcat&lt;/code&gt; → &lt;code&gt;thymeleaf-template&lt;/code&gt;. Luna applied the same command without &lt;code&gt;--plan&lt;/code&gt;, then later planned and applied &lt;code&gt;maven-wrapper&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terra applied a valid composition directly
&lt;/h3&gt;

&lt;p&gt;Terra's &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/blob/428db51ed018f1f2e520dfd30fe0b9a38ca67523/CONVERSATION_TRANSCRIPT.md" rel="noopener noreferrer"&gt;complete plan&lt;/a&gt; was valid on the first attempt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  init &lt;span class="se"&gt;\&lt;/span&gt;
  prettier &lt;span class="se"&gt;\&lt;/span&gt;
  typescript &lt;span class="se"&gt;\&lt;/span&gt;
  react-core &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt; hangmanui &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt; &lt;span class="s1"&gt;'Hangman UI'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt; npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-of-line&lt;/span&gt; lf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Preflight: VALID
Execution order: init → prettier → typescript → react-core
No changes were applied.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terra applied the same modules and parameters by running the command again without &lt;code&gt;--plan&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sol recovered after a partial application
&lt;/h3&gt;

&lt;p&gt;Sol's &lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata/blob/96e4cc13f2ee260921dccbc7f8abbe0a6d7703f7/CONVERSATION_TRANSCRIPT.md" rel="noopener noreferrer"&gt;initial plan&lt;/a&gt; was also valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  init &lt;span class="se"&gt;\&lt;/span&gt;
  prettier &lt;span class="se"&gt;\&lt;/span&gt;
  typescript &lt;span class="se"&gt;\&lt;/span&gt;
  react-core &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt; &lt;span class="s1"&gt;'Hangman UI Kata'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt; hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt; npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-of-line&lt;/span&gt; lf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--plan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sol then applied the same composition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  init &lt;span class="se"&gt;\&lt;/span&gt;
  prettier &lt;span class="se"&gt;\&lt;/span&gt;
  typescript &lt;span class="se"&gt;\&lt;/span&gt;
  react-core &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt; &lt;span class="s1"&gt;'Hangman UI Kata'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt; hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt; npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-of-line&lt;/span&gt; lf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated commit hook could not find &lt;code&gt;lint-staged&lt;/code&gt; while applying &lt;code&gt;init&lt;/code&gt;. Seed4J stopped the sequence instead of invoking the remaining modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init: FAILED
prettier: SKIPPED
typescript: SKIPPED
react-core: SKIPPED
Module set status: PARTIAL_FAILURE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After inspecting the partial output and Seed4J history, Sol installed the dependencies, planned again and reapplied the same set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install

&lt;/span&gt;seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  init &lt;span class="se"&gt;\&lt;/span&gt;
  prettier &lt;span class="se"&gt;\&lt;/span&gt;
  typescript &lt;span class="se"&gt;\&lt;/span&gt;
  react-core &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt; &lt;span class="s1"&gt;'Hangman UI Kata'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt; hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt; npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-of-line&lt;/span&gt; lf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--plan&lt;/span&gt;

seed4j apply-set &lt;span class="se"&gt;\&lt;/span&gt;
  init &lt;span class="se"&gt;\&lt;/span&gt;
  prettier &lt;span class="se"&gt;\&lt;/span&gt;
  typescript &lt;span class="se"&gt;\&lt;/span&gt;
  react-core &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-name&lt;/span&gt; &lt;span class="s1"&gt;'Hangman UI Kata'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--base-name&lt;/span&gt; hangman &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-package-manager&lt;/span&gt; npm &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--indent-size&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-of-line&lt;/span&gt; lf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project-path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These runs exposed two kinds of feedback. Seed4J rejected an invalid composition before mutation, and it stopped a module sequence after the first application failure. The CLI validated dependencies and resolved module order, while each Codex run remained responsible for choosing capabilities, reacting to feedback and implementing the game. The transcripts and Seed4J history preserved those adjustments instead of showing only the finished applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plan is where collaboration can begin
&lt;/h2&gt;

&lt;p&gt;This experiment does not show that one stack is the correct way to build Hangman or that one model will always make better choices. There was only one run per model, the runs were sequential and there was no control group implementing the same tasks without Seed4J. The shared checks let me compare the required behavior; they do not show that Seed4J made the implementations more correct or caused their differences.&lt;/p&gt;

&lt;p&gt;What the records do expose is a useful separation of responsibilities. The specification defined the behavior. Each Codex run chose an architecture and a set of modules, then implemented the game. Seed4J CLI turned the selected modules into an explicit plan containing dependencies, parameters and execution order before the repository changed. During application, it also recorded what happened to each module.&lt;/p&gt;

&lt;p&gt;Luna showed why validation before mutation matters: Seed4J rejected an invalid composition and made the missing modules visible. Terra showed the direct path from a valid plan to application. Sol showed the limit of planning: a valid composition can still encounter an environment failure, but the CLI stopped the remaining modules and preserved the partial history.&lt;/p&gt;

&lt;p&gt;In a real project, &lt;code&gt;apply-set --plan&lt;/code&gt; can become the starting point for a conversation with the agent. A developer can question the architecture, replace modules or adjust parameters before approving the transformation. After application, the module history provides a record of the path that was actually taken.&lt;/p&gt;

&lt;p&gt;The benefit is not that different architectures are automatically better. It is that architectural freedom becomes reviewable before execution and traceable afterward.&lt;/p&gt;

&lt;p&gt;That is what I want to carry from these small katas into larger applications. The single prompt in this experiment deliberately withheld the planning conversation. In real work, the Seed4J plan can support that conversation instead of replacing it. If you want to inspect the evidence rather than only the finished interfaces, both repositories include the prompts, preserved branches, transcripts, scorecards and reproduction notes.&lt;/p&gt;

&lt;p&gt;If this experiment made you curious about the approach, consider giving &lt;a href="https://github.com/seed4j/seed4j" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt; and &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt; a star 🌟 on GitHub. It helps more people discover the projects and follow their evolution.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://seed4j.com/" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-kata" rel="noopener noreferrer"&gt;Seed4J CLI Hangman Kata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-hangman-ui-kata" rel="noopener noreferrer"&gt;Seed4J CLI Hangman UI Kata&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>What Six Codex Runs Taught Me About Tool Design</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:47:50 +0000</pubDate>
      <link>https://dev.to/renanfranca/what-six-codex-runs-taught-me-about-tool-design-3mle</link>
      <guid>https://dev.to/renanfranca/what-six-codex-runs-taught-me-about-tool-design-3mle</guid>
      <description>&lt;h2&gt;
  
  
  The score was not the most interesting result
&lt;/h2&gt;

&lt;p&gt;The String Calculator was never the object of this experiment. It was a small Java kata often used to practice TDD, giving a coding agent a concrete reason to use Seed4J CLI.&lt;/p&gt;

&lt;p&gt;The object was the interaction among three parts: the agent interpreting the goal and choosing capabilities, a skill installed in the repository guiding how it should discover, plan and verify, and Seed4J CLI validating and materializing the selected transformations.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://renanfranca.github.io/from-an-empty-repository-to-a-java-kata-one-module-at-a-time.html" rel="noopener noreferrer"&gt;From an Empty Repository to a Java Kata, One Module at a Time&lt;/a&gt;, I followed that interaction through one complete Codex run, from an empty repository to a Java and Maven foundation and then to the kata implementation.&lt;/p&gt;

&lt;p&gt;I had also repeated the same task five more times, changing which model powered Codex or how much reasoning effort it used. All six runs started from the same commit and kata specification, received the same prompt and used Seed4J CLI v0.0.4 with Seed4J 2.2.0. All six produced a working String Calculator implementation, passed the build included in the project and passed the same independent tests covering the kata requirements.&lt;/p&gt;

&lt;p&gt;I initially evaluated them with a &lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/main/MODEL_EVALUATION.md" rel="noopener noreferrer"&gt;shared rubric&lt;/a&gt;. It awarded up to 100 points across Seed4J effectiveness, required behavior, tests and design. The rubric was useful for comparing the runs against the same criteria, but it reduced each execution to a score.&lt;/p&gt;

&lt;p&gt;Comparing the commands and messages recorded during the six runs did not change the subject of the experiment. It made the different paths through the same interaction visible.&lt;/p&gt;

&lt;p&gt;One run showed the workflow in action. Six runs showed how differently agents navigated that workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I mean by a decision trajectory
&lt;/h2&gt;

&lt;p&gt;I am not trying to infer the model's private reasoning. The recorded commands and messages do not expose it, and I do not need it for this comparison.&lt;/p&gt;

&lt;p&gt;There is already a lot I can observe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which commands a run executes before changing the repository;&lt;/li&gt;
&lt;li&gt;which modules it inspects as candidates;&lt;/li&gt;
&lt;li&gt;which inspected modules it leaves out;&lt;/li&gt;
&lt;li&gt;whether it creates one complete plan or several smaller plans;&lt;/li&gt;
&lt;li&gt;how tool or environment feedback changes the next action;&lt;/li&gt;
&lt;li&gt;which capabilities it delegates to Seed4J;&lt;/li&gt;
&lt;li&gt;what it verifies after generation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think of that visible sequence as a decision trajectory.&lt;/p&gt;

&lt;p&gt;The six runs used three models: Sol, Terra and Luna. Four used Sol at &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt; and &lt;code&gt;xhigh&lt;/code&gt; reasoning effort; the other two used Terra and Luna at &lt;code&gt;xhigh&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three paths through the same CLI
&lt;/h2&gt;

&lt;p&gt;The three &lt;code&gt;xhigh&lt;/code&gt; runs provide the cleanest narrative comparison because the reasoning effort stays fixed while the selected model changes.&lt;/p&gt;

&lt;p&gt;In the detailed evaluation, Sol &lt;code&gt;xhigh&lt;/code&gt; scored 98/100, Luna &lt;code&gt;xhigh&lt;/code&gt; 95/100 and Terra &lt;code&gt;xhigh&lt;/code&gt; 91/100. All three earned the full 30 points for the required String Calculator behavior. Their remaining differences came from Seed4J usage, tests and design.&lt;/p&gt;

&lt;p&gt;The behavior scores confirm a common functional baseline. They do not describe the different paths each run took through the interaction among agent, skill and CLI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sol xhigh anticipated the foundation
&lt;/h3&gt;

&lt;p&gt;The Sol &lt;code&gt;xhigh&lt;/code&gt; run inspected &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;, &lt;code&gt;maven-wrapper&lt;/code&gt; and &lt;code&gt;jacoco-with-min-coverage-check&lt;/code&gt;, then placed all four modules into one &lt;code&gt;apply-set&lt;/code&gt; plan.&lt;/p&gt;

&lt;p&gt;Its visible trajectory looked roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goal → candidate capabilities → one composition → plan → execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This run anticipated that the project should have its own Maven launcher and an enforced coverage gate before attempting the kata implementation.&lt;/p&gt;

&lt;p&gt;It also exposed an important division of responsibility. The run requested the modules in this order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init
maven-java
maven-wrapper
jacoco-with-min-coverage-check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seed4J executed them in this order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init
maven-java
jacoco-with-min-coverage-check
maven-wrapper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The run chose the capabilities. Seed4J validated the composition and resolved how to materialize it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terra xhigh adapted to feedback
&lt;/h3&gt;

&lt;p&gt;The Terra &lt;code&gt;xhigh&lt;/code&gt; run began with a smaller composition: &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;maven-java&lt;/code&gt;. It planned those modules, applied them and inspected the generated project.&lt;/p&gt;

&lt;p&gt;Then it tried to use the global Maven command. The environment returned &lt;code&gt;mvn: command not found&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next visible message said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The environment has Java 25, but does not have &lt;code&gt;mvn&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence is my English translation of the original Brazilian Portuguese message in the &lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/9001fe863565408ac3c9622b3b9e7e3edb7786f6/CONVERSATION_TRANSCRIPT.md" rel="noopener noreferrer"&gt;Terra run record&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The run then inspected &lt;code&gt;maven-wrapper&lt;/code&gt;, generated an individual plan, applied the module and continued through &lt;code&gt;./mvnw&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Its trajectory was different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initial composition → environment feedback → new capability → plan → execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling this merely a mistake would hide the useful part. In this run, a missing environmental capability produced feedback, and that feedback changed the composition. The final project still recorded the wrapper through the same Seed4J history and commit mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  Luna xhigh explored and kept the scaffold small
&lt;/h3&gt;

&lt;p&gt;The Luna &lt;code&gt;xhigh&lt;/code&gt; run inspected a broader group of candidates. In addition to &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt; and &lt;code&gt;apply-set&lt;/code&gt;, it inspected &lt;code&gt;java-base&lt;/code&gt; and &lt;code&gt;spring-boot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that exploration, its visible message stated that the specification required incremental TDD in Java but did not require a framework or application structure. The run chose a minimal Maven project with JUnit 5 and left &lt;code&gt;java-base&lt;/code&gt; and &lt;code&gt;spring-boot&lt;/code&gt; out of the composition.&lt;/p&gt;

&lt;p&gt;It later inspected &lt;code&gt;maven-wrapper&lt;/code&gt; and planned the final set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;candidate exploration → minimal boundary → composition → plan → execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not evidence that Luna generally explores more or that it is inherently more disciplined about scope. It is evidence that this particular run inspected two plausible capabilities and did not apply them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other runs left signals too
&lt;/h2&gt;

&lt;p&gt;The remaining Sol runs reinforce the point that a score or final file tree does not describe the complete interaction.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Candidate signal&lt;/th&gt;
&lt;th&gt;Initial applied set&lt;/th&gt;
&lt;th&gt;Later change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sol low&lt;/td&gt;
&lt;td&gt;Inspected &lt;code&gt;jqwik&lt;/code&gt;, but did not select it&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;, &lt;code&gt;maven-wrapper&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sol medium&lt;/td&gt;
&lt;td&gt;Inspected &lt;code&gt;checkstyle&lt;/code&gt;, but did not select it&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;, JaCoCo gate, wrapper&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sol high&lt;/td&gt;
&lt;td&gt;Inspected the four modules it selected&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;, JaCoCo gate, wrapper&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sol xhigh&lt;/td&gt;
&lt;td&gt;Inspected the four modules it selected&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;, wrapper, JaCoCo gate&lt;/td&gt;
&lt;td&gt;Seed4J changed the effective peer order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terra xhigh&lt;/td&gt;
&lt;td&gt;Did not inspect the wrapper before the initial application&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Added the wrapper after global Maven was unavailable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Luna xhigh&lt;/td&gt;
&lt;td&gt;Inspected &lt;code&gt;java-base&lt;/code&gt; and &lt;code&gt;spring-boot&lt;/code&gt;, but did not select them&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;maven-java&lt;/code&gt;, &lt;code&gt;maven-wrapper&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This table does not rank the trajectories. It gives me a vocabulary for comparing them: discovery breadth, candidate rejection, planning granularity, proactive composition, reaction to feedback and delegation to the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The skill constrained the protocol, not every decision
&lt;/h2&gt;

&lt;p&gt;All six runs had the same &lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/38ebbcbfab95f5725b1c22b1d4701fb6222cab6b/.agents/skills/seed4j-cli/SKILL.md" rel="noopener noreferrer"&gt;Seed4J CLI skill installed in the repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The skill defines an operating protocol:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;discover the CLI, runtime and catalog;&lt;/li&gt;
&lt;li&gt;infer candidate modules from the task;&lt;/li&gt;
&lt;li&gt;inspect the active help for those modules;&lt;/li&gt;
&lt;li&gt;plan before mutation;&lt;/li&gt;
&lt;li&gt;execute the validated composition;&lt;/li&gt;
&lt;li&gt;verify the generated result and Git state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That protocol explains part of the consistency across the runs. Every one of them discovered the runtime and catalog. Every one produced a plan before applying modules. Every successful module left history and a commit.&lt;/p&gt;

&lt;p&gt;But the skill did not prescribe the exact module set for the kata. It did not say that JaCoCo was mandatory. It did not tell the run whether to inspect Spring Boot, when to add the Maven Wrapper or whether to construct one large plan.&lt;/p&gt;

&lt;p&gt;That left a meaningful decision surface for each run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the run selected the capabilities it wanted;&lt;/li&gt;
&lt;li&gt;the skill guided how to interact with the tool safely;&lt;/li&gt;
&lt;li&gt;Seed4J validated dependencies and parameters, calculated execution order, changed files, updated module history and created commits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation is more interesting to me than trying to put every correct decision into the skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool reduced the space of decisions that had to be right
&lt;/h2&gt;

&lt;p&gt;Without a project generator, a coding run building the same foundation might need to choose Maven plugin versions, write the POM, create the wrapper, configure JaCoCo, place files correctly, preserve project history and decide how to divide infrastructure changes into commits.&lt;/p&gt;

&lt;p&gt;With Seed4J, the request can be closer to a set of capabilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Java with Maven
Maven Wrapper
coverage gate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool then turns that explicit intent into deterministic transformations.&lt;/p&gt;

&lt;p&gt;This does not make module selection irrelevant. A run can still omit a useful capability, add one the task does not need or choose parameters poorly. Seed4J also cannot guarantee that the kata implementation itself will be well designed.&lt;/p&gt;

&lt;p&gt;What it can do is narrow the area in which those choices operate. Once a valid capability is selected, the run does not also need to reproduce all of the configuration details behind it from memory.&lt;/p&gt;

&lt;p&gt;The models can take different routes through discovery and planning without every difference becoming a different manually written build configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  This connects to how I think about skills and loops
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://renanfranca.github.io/when-skill-evolution-means-removing-instructions.html" rel="noopener noreferrer"&gt;When Skill Evolution Means Removing Instructions&lt;/a&gt;, I argued that deterministic knowledge should move into deterministic mechanisms whenever possible. A skill can become smaller when a test, hook or tool can enforce what used to depend on an instruction.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://renanfranca.github.io/i-had-already-built-three-agentic-loops.html" rel="noopener noreferrer"&gt;I Had Already Built Three Agentic Loops Without Naming Them&lt;/a&gt;, I described autonomy becoming safer when feedback and exit conditions live in the environment instead of depending on the model remembering them.&lt;/p&gt;

&lt;p&gt;Seed4J gives me another concrete example of both ideas.&lt;/p&gt;

&lt;p&gt;The skill does not contain a static catalog or teach the model how to write every generated file. It sends the run to the active CLI. The plan provides feedback before mutation. The runtime validates the composition. The module history and Git commits make the result inspectable afterward.&lt;/p&gt;

&lt;p&gt;The model still decides. But it decides inside a workflow with explicit feedback and deterministic boundaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this experiment does not show
&lt;/h2&gt;

&lt;p&gt;This was one kata, one prompt and one run for each model and effort configuration, all executed on the same host. Each run took place in a separate chat, and execution time was not part of the comparison. The records also differ in format and in what they omit, which limits direct comparisons of presentation and completeness.&lt;/p&gt;

&lt;p&gt;There was no control group implementing the kata without Seed4J. I therefore cannot claim that Seed4J made the runs faster, cheaper or more correct than another approach.&lt;/p&gt;

&lt;p&gt;Most importantly, these trajectories do not establish stable model personalities. I can say that the Terra &lt;code&gt;xhigh&lt;/code&gt; run added the wrapper reactively. I cannot conclude from one run that Terra is a reactive model. I can say that the Sol &lt;code&gt;xhigh&lt;/code&gt; run anticipated the coverage gate. I cannot conclude that Sol always plans infrastructure better.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/main/MODEL_EVALUATION.md" rel="noopener noreferrer"&gt;detailed experiment report&lt;/a&gt; keeps the full protocol, commands, scores and limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  A principle I want to test again
&lt;/h2&gt;

&lt;p&gt;These six runs do not prove a general rule about agent tools. They make one design principle concrete enough for me to keep testing.&lt;/p&gt;

&lt;p&gt;Different runs can explore different candidates, compose at different moments and react differently to feedback. A tool does not necessarily need to normalize all of that behavior. It can preserve room for judgment while making dependencies, ordering, parameter resolution, history and mutation more predictable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A good agent tool may not need to eliminate model variability. It may need to constrain where that variability can cause damage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If this experiment made you curious about the approach, consider giving &lt;a href="https://github.com/seed4j/seed4j" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt; and &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt; a star 🌟 on GitHub. It helps more people discover the projects and follow their evolution.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://seed4j.com/" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/" rel="noopener noreferrer"&gt;Seed4J CLI String Calculator Kata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/main/MODEL_EVALUATION.md" rel="noopener noreferrer"&gt;Detailed experiment report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/3d179c56b288f0fcbc0c62ee94b5af3152887136/AUDITORIA-CONVERSA.md" rel="noopener noreferrer"&gt;Sol xhigh run record&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/9001fe863565408ac3c9622b3b9e7e3edb7786f6/CONVERSATION_TRANSCRIPT.md" rel="noopener noreferrer"&gt;Terra xhigh run record&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/7ad4d48b311ff664c2f8e4b012151513cad15916/CONVERSATION_TRANSCRIPT.md" rel="noopener noreferrer"&gt;Luna xhigh run record&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.openai.com/api/docs/models" rel="noopener noreferrer"&gt;OpenAI model catalog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>tooling</category>
      <category>java</category>
    </item>
    <item>
      <title>From an Empty Repository to a Java Kata, One Module at a Time</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:47:49 +0000</pubDate>
      <link>https://dev.to/renanfranca/from-an-empty-repository-to-a-java-kata-one-module-at-a-time-36c3</link>
      <guid>https://dev.to/renanfranca/from-an-empty-repository-to-a-java-kata-one-module-at-a-time-36c3</guid>
      <description>&lt;h2&gt;
  
  
  A small project to learn Seed4J CLI
&lt;/h2&gt;

&lt;p&gt;I wanted a small project to learn how to use Seed4J CLI, but with a slightly different constraint: I wanted to learn it the same way I expect to use it in real projects, together with a coding agent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://seed4j.com/" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt; is a modular code generator. Instead of generating one fixed project, it applies named transformations, called modules, that add or configure one capability at a time.&lt;/p&gt;

&lt;p&gt;The Seed4J CLI makes that approach available from the command line.&lt;/p&gt;

&lt;p&gt;So I created a repository around the classic String Calculator kata, using the &lt;a href="https://github.com/ardalis/kata-catalog/blob/main/katas/String%20Calculator.md" rel="noopener noreferrer"&gt;specification from the Coding Kata Catalog&lt;/a&gt;. It is a small testing exercise in which an &lt;code&gt;add&lt;/code&gt; function starts with simple string inputs and gradually supports more rules, such as multiple numbers and custom delimiters.&lt;/p&gt;

&lt;p&gt;The Seed4J CLI can also install a skill directly in the repository where it will be used. That skill teaches the coding agent how to discover and operate the CLI. The skill guides the agent; the Seed4J modules are what transform the project.&lt;/p&gt;

&lt;p&gt;The starting point is intentionally minimal: a specification for the kata and the Seed4J CLI skill installed locally for the agent.&lt;/p&gt;

&lt;p&gt;The original prompt was written in Brazilian Portuguese:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;implement o kata utilizando o seed4j cli tool já instalado como apoio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For readability, I translated it to English:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implement the kata with support from the installed Seed4J CLI tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From there, the agent has to inspect the active CLI and decide how to compose the project.&lt;/p&gt;

&lt;p&gt;I later repeated the same task across six model and reasoning configurations. Their differences are documented in the detailed experiment report linked below. To keep this post focused, it follows the &lt;code&gt;string-calculator-sol-xhigh&lt;/code&gt; run, which used the Sol model with &lt;code&gt;xhigh&lt;/code&gt; reasoning effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let the agent discover the CLI
&lt;/h2&gt;

&lt;p&gt;The agent starts by discovering the command-line client, the Seed4J version behind it, and the modules available to it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed4j --version &amp;amp;&amp;amp; seed4j --help
seed4j list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The command-line client and the Seed4J generator it invokes are versioned separately. This run used Seed4J CLI v0.0.4 with Seed4J 2.2.0.&lt;/p&gt;

&lt;p&gt;From the available modules, the agent identifies four capabilities that seem useful and inspects their parameters:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed4j apply-set --help
seed4j apply init --help
seed4j apply maven-java --help
seed4j apply maven-wrapper --help
seed4j apply jacoco-with-min-coverage-check --help
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The module names describe four separate transformations. Each name below links to the commit Seed4J created for that transformation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/commit/bc2937fbd28b1af9e8d225e3d1aa04e139ce7d88" rel="noopener noreferrer"&gt;&lt;code&gt;init&lt;/code&gt;&lt;/a&gt; establishes the common project foundation: project metadata, repository conventions, development tooling, and a record of the Seed4J modules applied. It does not create the Java application.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/commit/9c434d1503b32c02415df461182cfb58979c3ccd" rel="noopener noreferrer"&gt;&lt;code&gt;maven-java&lt;/code&gt;&lt;/a&gt; adds the Java and Maven build, including the testing dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/commit/675c0a86abae6116bf4aa8c46044164fec19ffec" rel="noopener noreferrer"&gt;&lt;code&gt;maven-wrapper&lt;/code&gt;&lt;/a&gt; adds a Maven launcher to the project, so the build does not depend on a separately installed Maven version.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/commit/2890bef54b3fb268a447d1e9c62b30084dd3ddfe" rel="noopener noreferrer"&gt;&lt;code&gt;jacoco-with-min-coverage-check&lt;/code&gt;&lt;/a&gt; turns code coverage into a build requirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;apply-set&lt;/code&gt; command composes several modules and resolves a valid execution order. Before changing the repository, the agent uses &lt;code&gt;--plan&lt;/code&gt; to preview the resolved modules and parameters without applying them:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed4j apply-set init maven-java maven-wrapper jacoco-with-min-coverage-check --plan --project-path . --project-name 'String Calculator Kata' --base-name stringCalculator --package-name com.renanfranca.stringcalculator --node-package-manager npm --end-of-line lf --indent-size 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The plan is valid and Seed4J resolves the execution order as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init
maven-java
jacoco-with-min-coverage-check
maven-wrapper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice that this is not exactly the order requested by the agent. It placed &lt;code&gt;maven-wrapper&lt;/code&gt; before &lt;code&gt;jacoco-with-min-coverage-check&lt;/code&gt;. The agent's order was valid: both modules can be applied after &lt;code&gt;maven-java&lt;/code&gt;, and neither depends on the other. Seed4J does not preserve the requested order, however. Because both modules are at the same dependency level, Seed4J 2.2.0 sorts them lexically by slug, placing &lt;code&gt;jacoco-with-min-coverage-check&lt;/code&gt; before &lt;code&gt;maven-wrapper&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After reviewing the plan, the agent applies exactly the same composition without &lt;code&gt;--plan&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Seed4J applies the modules sequentially and creates one commit for each successful module.&lt;/p&gt;

&lt;p&gt;Once Seed4J finishes, the repository has a common project foundation, a Java 25 Maven build with testing libraries, an enforced coverage threshold, and its own Maven launcher. Seed4J stops at that foundation; it does not generate the String Calculator. From there, the agent &lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/commit/e22bea4e216db808ae7682a63d857f2cce3d8c0b" rel="noopener noreferrer"&gt;implements the kata in one production class and one test class&lt;/a&gt;. Running &lt;code&gt;./mvnw verify&lt;/code&gt; executes 13 behavior tests and enforces 100% line and branch coverage with JaCoCo.&lt;/p&gt;

&lt;p&gt;What interested me was not the generated files alone. It was watching the agent discover the available capabilities, select the modules it needed, and let Seed4J resolve and record the composition one module at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The kata is not the thing I am trying to learn
&lt;/h2&gt;

&lt;p&gt;I chose a familiar kata precisely because its implementation was not the variable I wanted to study. It gives me a small, controlled problem where I can watch an AI agent discover Seed4J, choose modules, inspect their parameters, preview the resulting composition, and use those modules to turn an almost empty repository into a Java project.&lt;/p&gt;

&lt;p&gt;Instead of asking the agent to manually recreate all the project setup, I can watch it decide which capabilities it needs and let Seed4J apply the corresponding transformations.&lt;/p&gt;

&lt;p&gt;The repository records this experiment, including the commands executed by the agents, the modules they selected, the resulting projects, and their Seed4J module history.&lt;/p&gt;

&lt;p&gt;What I can observe here is how the agents use Seed4J under this setup. Because every run uses Seed4J, this experiment does not tell me whether Seed4J makes an agent faster, cheaper, or better than another scaffolding approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small training ground
&lt;/h2&gt;

&lt;p&gt;For me, this makes the kata a small training ground for a larger question: how should I use Seed4J together with AI coding agents in real projects?&lt;/p&gt;

&lt;p&gt;I do not think this kata answers that question. It gives me a controlled place to observe the interaction, learn what information the agent needs, and make the next experiment more concrete.&lt;/p&gt;

&lt;p&gt;If this experiment made you curious about the approach, consider giving &lt;a href="https://github.com/seed4j/seed4j" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt; and &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt; a star 🌟 on GitHub. It helps more people discover the projects and follow their evolution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduction note
&lt;/h2&gt;

&lt;p&gt;Seed4J CLI itself requires Java 25 or newer on your &lt;code&gt;PATH&lt;/code&gt;, and its npm launcher requires Node.js 22 or newer. With those prerequisites available, install the CLI and verify the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g seed4j-cli
seed4j --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, install the optional skill that guides the coding agent by running this command from the kata repository:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed4j skill install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I used Codex in the ChatGPT desktop app with Full Access enabled so Seed4J could write to &lt;code&gt;.git&lt;/code&gt; and create a separate commit for each module without approval interruptions. In Codex CLI, the equivalent is running &lt;code&gt;codex --yolo&lt;/code&gt;. Because that bypasses approvals and sandboxing, it should only be used in a controlled or externally isolated environment.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://seed4j.com/" rel="noopener noreferrer"&gt;Seed4J&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ardalis/kata-catalog" rel="noopener noreferrer"&gt;Coding Kata Catalog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/" rel="noopener noreferrer"&gt;Seed4J CLI String Calculator Kata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/tree/string-calculator-sol-xhigh" rel="noopener noreferrer"&gt;Sol xhigh implementation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-string-calculator-kata/blob/main/MODEL_EVALUATION.md" rel="noopener noreferrer"&gt;Detailed experiment report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.chatgpt.com/docs/sandboxing" rel="noopener noreferrer"&gt;Codex sandbox and permissions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>ai</category>
      <category>agents</category>
      <category>testing</category>
    </item>
    <item>
      <title>When Skill Evolution Means Removing Instructions</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:47:18 +0000</pubDate>
      <link>https://dev.to/renanfranca/when-skill-evolution-means-removing-instructions-3484</link>
      <guid>https://dev.to/renanfranca/when-skill-evolution-means-removing-instructions-3484</guid>
      <description>&lt;h2&gt;
  
  
  Two papers, one familiar question
&lt;/h2&gt;

&lt;p&gt;I keep having this strange experience lately: I spend time experimenting with something in a very small, practical way, and then a paper appears exploring a remarkably similar question at a much larger scale.&lt;/p&gt;

&lt;p&gt;Two recent papers made that happen again.&lt;/p&gt;

&lt;p&gt;The first is &lt;a href="https://arxiv.org/abs/2608.20614" rel="noopener noreferrer"&gt;“Evaluating Skills, Not Just Agents”&lt;/a&gt;, which introduces ACES and Skill Lift: execute the same task with and without a skill and measure the difference.&lt;/p&gt;

&lt;p&gt;That connects directly with what I was exploring in &lt;a href="https://github.com/renanfranca/skill-eval" rel="noopener noreferrer"&gt;skill-eval&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But my main takeaway from that experiment was actually about the limits of A/B testing.&lt;/p&gt;

&lt;p&gt;An A/B comparison gives evidence for that particular model, task, context and harness. It does not prove that a skill is universally good. Change the model and the skill may become less useful, unnecessary, or even harmful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge does not have to become instructions
&lt;/h2&gt;

&lt;p&gt;Then I read Google Research's &lt;a href="https://arxiv.org/abs/2608.27454" rel="noopener noreferrer"&gt;“WikiSkill: Compiling Agent Experience into Persistent Knowledge for Skill Evolution”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And another piece clicked into place.&lt;/p&gt;

&lt;p&gt;WikiSkill separates raw experience, accumulated knowledge and the actual executable skill. Experience can keep accumulating outside the skill, while proposed skill changes are validated before being promoted.&lt;/p&gt;

&lt;p&gt;Even more interestingly, the paper shows cases where low-level workarounds learned for one model transfer poorly to a stronger model. Instructions that helped the weaker model could constrain the stronger one or cause redundant tool calls.&lt;/p&gt;

&lt;p&gt;That is very close to another experiment I did inside &lt;a href="https://github.com/renanfranca/skill-eval" rel="noopener noreferrer"&gt;skill-eval&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolving a skill by making it smaller
&lt;/h2&gt;

&lt;p&gt;I tried to “evolve” my &lt;code&gt;implement-execplan&lt;/code&gt; skill not by adding more instructions, but by removing them.&lt;/p&gt;

&lt;p&gt;The original baseline had 228 lines. The adaptive version had 165.&lt;/p&gt;

&lt;p&gt;Instead of requiring a large fixed plan structure and continuous updates, the newer version relies more on the model's own capabilities: fewer mandatory sections, conditional information only when useful, fewer plan updates and less routine bookkeeping.&lt;/p&gt;

&lt;p&gt;The skill is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/codex-skills/blob/main/implement-execplan/SKILL.md" rel="noopener noreferrer"&gt;implement-execplan/SKILL.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the case study is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/skill-eval/tree/main/docs/case-studies/implement-execplan" rel="noopener noreferrer"&gt;skill-eval: implement-execplan case study&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the first valid comparison, both versions passed the same quality gates, while the smaller version used about 18% fewer candidate input + output tokens.&lt;/p&gt;

&lt;p&gt;That is only one observation, not proof that the new version is universally better. The replication was incomplete, and I deliberately documented that limitation.&lt;/p&gt;

&lt;p&gt;But it changed how I think about “skill evolution”.&lt;/p&gt;

&lt;p&gt;Evolution does not necessarily mean accumulating more rules.&lt;/p&gt;

&lt;p&gt;Sometimes the model improved and part of the harness became obsolete.&lt;/p&gt;

&lt;p&gt;Sometimes something that used to require an instruction can become a deterministic test, hook or static check and disappear from the skill entirely.&lt;/p&gt;

&lt;p&gt;This is also a continuation of something I noticed while gradually giving TDD to an agent. In &lt;a href="https://renanfranca.github.io/when-i-entrusted-tdd-to-an-ai-agent.html" rel="noopener noreferrer"&gt;When I Entrusted TDD to an AI Agent&lt;/a&gt;, some architectural guidance became much more reliable once it stopped being only an instruction and became executable feedback in the repository.&lt;/p&gt;

&lt;p&gt;And sometimes a failure is worth remembering, but not yet worth turning into an instruction. This is where the WikiSkill separation between experience, persistent knowledge and executable skills makes a lot of sense to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  I prefer to discover the workflow first
&lt;/h2&gt;

&lt;p&gt;This also changed how I create skills.&lt;/p&gt;

&lt;p&gt;I prefer to experience the problem first, work with the model manually, adjust the workflow until I can make it work reliably, and only then consolidate what I learned into a skill.&lt;/p&gt;

&lt;p&gt;My latest &lt;code&gt;implement-approved-plan&lt;/code&gt; skill came from exactly that process:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/codex-skills/blob/main/implement-approved-plan/SKILL.md" rel="noopener noreferrer"&gt;implement-approved-plan/SKILL.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This one is interesting because the skill itself coordinates a multi-chat workflow inside ChatGPT Desktop.&lt;/p&gt;

&lt;p&gt;A dedicated Coordinator keeps the approved plan and controls a set of specialized chats. Each role is created once and then reused throughout the implementation: an Implementer works through TDD, a Committer owns commits, a Validator runs the complete quality gates, a Habit Curator handles mechanically detected design findings, and an independent Structural Reviewer looks for design problems after the implementation is already green.&lt;/p&gt;

&lt;p&gt;The specialization is not only about giving each chat a different responsibility. The skill also assigns different models to different roles. The Coordinator, Implementer, Habit Curator, and Structural Reviewer run on &lt;code&gt;gpt-5.6-sol&lt;/code&gt; at &lt;code&gt;xhigh&lt;/code&gt;; the Committer runs on &lt;code&gt;gpt-5.6-terra&lt;/code&gt; at &lt;code&gt;xhigh&lt;/code&gt;; and the Validator runs on &lt;code&gt;gpt-5.6-luna&lt;/code&gt; at &lt;code&gt;xhigh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That routing makes the workflow more economical. Sol is reserved for open-ended implementation, orchestration, and design judgment; Terra handles commit work, which is narrower but still requires judgment about repository conventions; and Luna runs the mostly deterministic validation gates. The point is not merely to create specialists, but to avoid using the flagship model where a more economical model is sufficient.&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%2Fguxwdtxlnnlp5ycjomze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fguxwdtxlnnlp5ycjomze.png" alt="Coordinator and specialist chats created by implement-approved-plan" width="519" height="327"&gt;&lt;/a&gt;&lt;/p&gt;
These are the chats created by the &lt;code&gt;implement-approved-plan&lt;/code&gt; skill to implement &lt;a href="https://github.com/habit-hooks/habit-hooks/issues/160" rel="noopener noreferrer"&gt;habit-hooks issue #160&lt;/a&gt; in the amazing habit-hooks project.



&lt;p&gt;Conceptually, it looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Approved Plan
     ↓
Coordinator
     ↓
Implementer
     ↓
Coordinator
     ↓
Committer
     ↓
Coordinator
     ↓
Validator
     ↓
Coordinator
     ↓
Habit Curator
     ↓
Coordinator
     ↓
Structural Reviewer
     ↓
Final Validation
     ↓
PR + CI
     ↓
Ready for Merge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting part for me is that these chats do not freely coordinate with each other. The Coordinator is the only one talking to the specialists, and access to the same working tree is serialized through a persistent workflow ledger.&lt;/p&gt;

&lt;p&gt;That ledger works almost like a small state machine. It records the current phase, specialist chat IDs, commits, validation gates, Habit state, pull request and CI evidence. It rejects invalid transitions, concurrent ownership of the checkout, premature pull requests and cleanup before GitHub actually confirms that the PR was merged.&lt;/p&gt;

&lt;p&gt;The shape is more elaborate than the three nested loops I described in &lt;a href="https://renanfranca.github.io/i-had-already-built-three-agentic-loops-without-naming-them.html" rel="noopener noreferrer"&gt;I Had Already Built Three Agentic Loops Without Naming Them&lt;/a&gt;, but the underlying idea feels similar: autonomy becomes safer when feedback and exit conditions live in the workflow instead of depending on the model remembering everything.&lt;/p&gt;

&lt;p&gt;So the skill is not trying to make one giant agent smarter. It is encoding a workflow I had already been performing manually, while moving as much coordination and validation as possible into deterministic machinery around the model.&lt;/p&gt;

&lt;p&gt;PR that introduced it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/codex-skills/pull/7" rel="noopener noreferrer"&gt;renanfranca/codex-skills#7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And instead of stopping when the &lt;code&gt;SKILL.md&lt;/code&gt; looked good, I exercised the workflow against a public fixture and a real pull request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/implement-approved-plan-fixture" rel="noopener noreferrer"&gt;implement-approved-plan-fixture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/implement-approved-plan-fixture/pull/2" rel="noopener noreferrer"&gt;implement-approved-plan-fixture#2&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My current mental model
&lt;/h2&gt;

&lt;p&gt;So my current mental model is becoming something like this:&lt;/p&gt;

&lt;p&gt;Experience the problem.&lt;/p&gt;

&lt;p&gt;Make the workflow work manually.&lt;/p&gt;

&lt;p&gt;Turn deterministic knowledge into deterministic mechanisms.&lt;/p&gt;

&lt;p&gt;Keep uncertain experience outside the skill until it earns its place.&lt;/p&gt;

&lt;p&gt;Add instructions only for what the model still needs.&lt;/p&gt;

&lt;p&gt;And when the model changes, question those instructions again.&lt;/p&gt;

&lt;p&gt;No magic skill. No assumption that more instructions mean a better agent.&lt;/p&gt;

&lt;p&gt;Just a workflow that keeps adapting as both the model and my understanding of the problem change.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>tooling</category>
      <category>learning</category>
    </item>
    <item>
      <title>I Had Already Built Three Agentic Loops Without Naming Them</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:47:17 +0000</pubDate>
      <link>https://dev.to/renanfranca/i-had-already-built-three-agentic-loops-without-naming-them-2263</link>
      <guid>https://dev.to/renanfranca/i-had-already-built-three-agentic-loops-without-naming-them-2263</guid>
      <description>&lt;h2&gt;
  
  
  I was already working with loops
&lt;/h2&gt;

&lt;p&gt;After reading Laurie Voss's article &lt;a href="https://www.linkedin.com/pulse/what-hell-loop-anyway-laurie-voss-ldmdc" rel="noopener noreferrer"&gt;What the hell is a loop, anyway?&lt;/a&gt;, I realized that I had naturally ended up with three layers of loops in my workflow with coding agents.&lt;/p&gt;

&lt;p&gt;I had not deliberately designed something I called a loop architecture.&lt;/p&gt;

&lt;p&gt;I had been trying to solve practical problems.&lt;/p&gt;

&lt;p&gt;How could I give an agent enough autonomy to implement a complete feature without losing the destination?&lt;/p&gt;

&lt;p&gt;How could I divide a large implementation into observable units of progress?&lt;/p&gt;

&lt;p&gt;How could I ensure that the code evolved through behavior while continuing to respect the architecture?&lt;/p&gt;

&lt;p&gt;The solutions I adopted gradually became three nested feedback loops.&lt;/p&gt;

&lt;p&gt;I just did not have a name for them.&lt;/p&gt;

&lt;h2&gt;
  
  
  These are loops inside one implementation
&lt;/h2&gt;

&lt;p&gt;My three layers do not map perfectly to the four loop architectures Laurie describes.&lt;/p&gt;

&lt;p&gt;I am not running an autonomous software factory that chooses work from a backlog, ships it, monitors production, and starts again.&lt;/p&gt;

&lt;p&gt;The loops I see are inside the implementation of a single change.&lt;/p&gt;

&lt;p&gt;The outer loop follows the complete execution plan.&lt;/p&gt;

&lt;p&gt;Inside it, another loop follows the milestones.&lt;/p&gt;

&lt;p&gt;Inside each milestone, TDD can generate several smaller red-green-refactor cycles.&lt;/p&gt;

&lt;p&gt;Each layer operates at a different level of abstraction, receives different feedback, and has a different exit condition.&lt;/p&gt;

&lt;h2&gt;
  
  
  The outer loop: the execution plan
&lt;/h2&gt;

&lt;p&gt;The outermost layer is the execution plan.&lt;/p&gt;

&lt;p&gt;As I described in &lt;a href="https://renanfranca.github.io/when-plan-mode-was-no-longer-enough.html" rel="noopener noreferrer"&gt;When Plan Mode Was No Longer Enough&lt;/a&gt;, the execution plan gives the agent more than a list of tasks.&lt;/p&gt;

&lt;p&gt;It describes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why the change is needed;&lt;/li&gt;
&lt;li&gt;the current context;&lt;/li&gt;
&lt;li&gt;the desired final behavior;&lt;/li&gt;
&lt;li&gt;relevant constraints and decisions;&lt;/li&gt;
&lt;li&gt;the implementation milestones;&lt;/li&gt;
&lt;li&gt;the validation strategy;&lt;/li&gt;
&lt;li&gt;the final acceptance criteria.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This loop begins with the current state of the repository and a desired destination.&lt;/p&gt;

&lt;p&gt;The agent implements, validates, updates the plan with what it discovers, and continues until the complete plan satisfies its final acceptance criteria.&lt;/p&gt;

&lt;p&gt;The important part is that the loop does not end merely because the agent says that it has finished.&lt;/p&gt;

&lt;p&gt;It ends when the observable result matches what the plan defined as complete.&lt;/p&gt;

&lt;p&gt;The execution plan therefore protects the destination.&lt;/p&gt;

&lt;p&gt;Local implementation decisions can change. A milestone may reveal that an earlier assumption was incomplete. The agent may discover a better design while practising TDD.&lt;/p&gt;

&lt;p&gt;The plan can evolve with those discoveries, but the final outcome must remain explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The middle loop: the milestones
&lt;/h2&gt;

&lt;p&gt;Inside the execution plan, there are milestones.&lt;/p&gt;

&lt;p&gt;Each milestone has its own scope, validation commands, expected result, and acceptance criteria.&lt;/p&gt;

&lt;p&gt;A milestone creates a smaller convergence point inside the larger implementation.&lt;/p&gt;

&lt;p&gt;Instead of asking only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Has the complete feature been implemented?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The plan can repeatedly ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Has this meaningful part of the feature reached the state it promised?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This distinction matters even though I no longer stop the agent after every milestone.&lt;/p&gt;

&lt;p&gt;Earlier in my workflow, each milestone was also a human approval gate. I reviewed the implementation and explicitly authorized the next step.&lt;/p&gt;

&lt;p&gt;Today, I usually allow the agent to implement the complete execution plan autonomously.&lt;/p&gt;

&lt;p&gt;However, removing the human interruption did not remove the milestone loop.&lt;/p&gt;

&lt;p&gt;The agent still needs to complete the milestone, run its validations, verify its acceptance criteria, record relevant decisions, and only then move forward.&lt;/p&gt;

&lt;p&gt;The milestone remains a checkpoint even when I am not standing at the checkpoint.&lt;/p&gt;

&lt;p&gt;It protects intermediate progress.&lt;/p&gt;

&lt;p&gt;Without this layer, the agent could perform many technically valid operations without demonstrating that the implementation is moving through meaningful states toward the final result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The inner loop: TDD and executable architecture
&lt;/h2&gt;

&lt;p&gt;Inside the milestones is the smallest and most active layer.&lt;/p&gt;

&lt;p&gt;The TDD loop chooses the next observable behavior, writes a failing test, implements the minimum code necessary to make it pass, evaluates the opportunity for refactoring, and continues while the suite remains green.&lt;/p&gt;

&lt;p&gt;One milestone can generate many of these cycles.&lt;/p&gt;

&lt;p&gt;As I described in &lt;a href="https://renanfranca.github.io/when-i-entrusted-tdd-to-an-ai-agent.html" rel="noopener noreferrer"&gt;When I Entrusted TDD to an AI Agent&lt;/a&gt;, I eventually allowed Codex CLI to run these cycles autonomously through my &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd%2Fbehavior-autonomous-quiet%2FSKILL.md" rel="noopener noreferrer"&gt;tdd-behavior-autonomous-quiet&lt;/a&gt; skill.&lt;/p&gt;

&lt;p&gt;But TDD alone was not enough.&lt;/p&gt;

&lt;p&gt;An agent can write passing tests while moving behavior into the wrong architectural layer. It can also create tests that merely reproduce the structure of the production code.&lt;/p&gt;

&lt;p&gt;For this reason, the loop also receives feedback from architectural tests such as &lt;a href="https://github.com/seed4j/seed4j-cli/blob/main/src%2Ftest%2Fjava%2Fcom%2Fseed4j%2Fcli%2FHexagonalArchTest.java" rel="noopener noreferrer"&gt;HexagonalArchTest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These tests make architectural boundaries executable.&lt;/p&gt;

&lt;p&gt;When the agent introduces an invalid dependency, the repository rejects the design.&lt;/p&gt;

&lt;p&gt;The failure creates another correction cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the behavioral test may already be green;&lt;/li&gt;
&lt;li&gt;an architectural rule fails;&lt;/li&gt;
&lt;li&gt;the agent changes the design;&lt;/li&gt;
&lt;li&gt;both behavioral and architectural tests run again;&lt;/li&gt;
&lt;li&gt;the implementation continues only when both forms of feedback agree.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vertical checkpoints add another feedback signal.&lt;/p&gt;

&lt;p&gt;After a small number of TDD cycles, the agent must validate the feature through its public path. This prevents locally successful cycles from drifting into what I called the implementation details loop.&lt;/p&gt;

&lt;p&gt;The inner layer therefore does more than ask whether the latest unit test passes.&lt;/p&gt;

&lt;p&gt;It asks whether the behavior works, whether the design respects the architecture, and whether the accumulated implementation still produces progress through the feature's public path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Each layer asks a different question
&lt;/h2&gt;

&lt;p&gt;Looking at the workflow as nested loops helped me understand why I need all three layers.&lt;/p&gt;

&lt;p&gt;The execution plan asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are we reaching the final outcome?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The milestone asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have we completed this meaningful stage of the implementation?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The TDD and architecture loop asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the next behavior work without compromising the design?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;None of these questions replaces the others.&lt;/p&gt;

&lt;p&gt;A green TDD cycle does not prove that a milestone is complete.&lt;/p&gt;

&lt;p&gt;A completed milestone does not prove that the entire feature satisfies its acceptance criteria.&lt;/p&gt;

&lt;p&gt;A completed execution plan does not prove that every internal design decision is good.&lt;/p&gt;

&lt;p&gt;Each loop provides feedback at the scale where that feedback is useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autonomy depends on where feedback lives
&lt;/h2&gt;

&lt;p&gt;Previously, much of this feedback lived in my interventions.&lt;/p&gt;

&lt;p&gt;I inspected each step, questioned the direction, approved the next behavior, and decided when the agent could continue.&lt;/p&gt;

&lt;p&gt;As I removed confirmation gates, I needed to move that judgment into executable constraints.&lt;/p&gt;

&lt;p&gt;The execution plan made the destination explicit.&lt;/p&gt;

&lt;p&gt;The milestone criteria made intermediate progress observable.&lt;/p&gt;

&lt;p&gt;Behavior tests made functionality executable.&lt;/p&gt;

&lt;p&gt;Architectural tests made design boundaries executable.&lt;/p&gt;

&lt;p&gt;Vertical checkpoints made progress through the public path executable.&lt;/p&gt;

&lt;p&gt;The agent did not become more autonomous because I stopped caring about the process.&lt;/p&gt;

&lt;p&gt;It became more autonomous because the process could increasingly evaluate itself without waiting for me to repeat the same instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The loops still end with me
&lt;/h2&gt;

&lt;p&gt;Even with these layers, I remain outside the complete implementation loop.&lt;/p&gt;

&lt;p&gt;When the agent finishes, I review the result as a pull request.&lt;/p&gt;

&lt;p&gt;I read the behavior tests, follow the production code that makes them pass, inspect the architectural decisions, refactor where necessary, and decide whether the change belongs in the codebase.&lt;/p&gt;

&lt;p&gt;The loops reduce the number of routine decisions that depend on my immediate participation.&lt;/p&gt;

&lt;p&gt;They do not transfer responsibility for the final code.&lt;/p&gt;

&lt;p&gt;For now, the simplest names I have are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the execution plan loop;&lt;/li&gt;
&lt;li&gt;the milestone loop;&lt;/li&gt;
&lt;li&gt;the TDD and architecture loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perhaps better names will emerge.&lt;/p&gt;

&lt;p&gt;What matters to me is that I can finally see the structure that was already there.&lt;/p&gt;

&lt;p&gt;I was not merely giving an agent a large prompt and waiting for code.&lt;/p&gt;

&lt;p&gt;I was stacking feedback loops, each with its own scale, evidence, and exit condition.&lt;/p&gt;

&lt;p&gt;I just did not know that this was what I was doing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>tdd</category>
      <category>architecture</category>
    </item>
    <item>
      <title>When I Entrusted TDD to an AI Agent</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:46:46 +0000</pubDate>
      <link>https://dev.to/renanfranca/when-i-entrusted-tdd-to-an-ai-agent-4mm9</link>
      <guid>https://dev.to/renanfranca/when-i-entrusted-tdd-to-an-ai-agent-4mm9</guid>
      <description>&lt;h2&gt;
  
  
  Keeping the tests under my control
&lt;/h2&gt;

&lt;p&gt;When I first started using AI agents for software development, I kept a clear division of responsibilities.&lt;/p&gt;

&lt;p&gt;I wrote the tests.&lt;/p&gt;

&lt;p&gt;The agent implemented the production code and helped me refactor it.&lt;/p&gt;

&lt;p&gt;At the time, I was using &lt;a href="https://aider.chat/" rel="noopener noreferrer"&gt;Aider&lt;/a&gt; through its CLI.&lt;/p&gt;

&lt;p&gt;This arrangement allowed me to benefit from the agent without giving up control of the TDD process. I still chose the next behavior, wrote the failing test, watched it fail, and decided when the implementation was ready to be refactored.&lt;/p&gt;

&lt;p&gt;More importantly, it kept my anxiety under control.&lt;/p&gt;

&lt;p&gt;As I described in &lt;a href="https://renanfranca.github.io/for-me-tdd-is-therapy.html" rel="noopener noreferrer"&gt;For Me, TDD Is Therapy&lt;/a&gt;, TDD gives me a systematic way to move through the uncertainty of software development. Delegating production code while retaining the tests allowed me to preserve that process.&lt;/p&gt;

&lt;p&gt;Then I watched a presentation that changed how I thought about this division.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeing an LLM practise TDD
&lt;/h2&gt;

&lt;p&gt;The presentation was Lada Kesseler's excellent &lt;a href="https://youtu.be/_LSK2bVf0Lc?si=AW-QDxeCCgofLbDt" rel="noopener noreferrer"&gt;Augmented Coding: Mapping the Uncharted Territory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the first time, I saw the possibility of allowing an LLM to write both the tests and the production code while still following the TDD flow.&lt;/p&gt;

&lt;p&gt;Until then, I had assumed that keeping control of TDD meant keeping control of the tests.&lt;/p&gt;

&lt;p&gt;Lada's presentation showed me another possibility: perhaps I could delegate the entire red-green-refactor cycle while still making the process visible and inspectable.&lt;/p&gt;

&lt;p&gt;I was so excited that I sent &lt;a href="https://www.linkedin.com/in/lada-kesseler?utm_source=share_via&amp;amp;utm_content=profile&amp;amp;utm_medium=member_android" rel="noopener noreferrer"&gt;Lada Kesseler&lt;/a&gt; a message on LinkedIn to thank her.&lt;/p&gt;

&lt;p&gt;She very kindly sent me the prompt she had used to guide the LLM through TDD.&lt;/p&gt;

&lt;p&gt;Reusable agent skills, at least in the form in which I use them today, did not exist yet. Even so, her presentation and prompt were already exploring the problems that skills would later help me address.&lt;/p&gt;

&lt;h2&gt;
  
  
  My first TDD skill
&lt;/h2&gt;

&lt;p&gt;When skills emerged, I used Lada's prompt as the foundation for my first &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd%2FSKILL.md" rel="noopener noreferrer"&gt;tdd skill&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sorry, Lada, if I somehow ruined your original prompt 😅.&lt;/p&gt;

&lt;p&gt;I started using the skill with Codex CLI to implement new features inside existing business domains.&lt;/p&gt;

&lt;p&gt;The process was extremely interactive.&lt;/p&gt;

&lt;p&gt;The agent would:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;write a comment describing the intention of the smallest test it wanted to implement;&lt;/li&gt;
&lt;li&gt;wait for my approval;&lt;/li&gt;
&lt;li&gt;implement the test and explain how it expected the test to fail;&lt;/li&gt;
&lt;li&gt;wait for approval again;&lt;/li&gt;
&lt;li&gt;implement the minimum production code necessary to make the test pass;&lt;/li&gt;
&lt;li&gt;wait before refactoring or moving to the next behavior.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It was beautiful to watch.&lt;/p&gt;

&lt;p&gt;The tests led the implementation. The expected failure was made explicit. Production code was added incrementally. Refactoring happened only while the test suite was green.&lt;/p&gt;

&lt;p&gt;Most importantly, I could see the process.&lt;/p&gt;

&lt;p&gt;I was no longer looking only at a final diff containing tests and production code. I could follow the sequence through which the design emerged.&lt;/p&gt;

&lt;p&gt;However, I gradually started to notice another problem.&lt;/p&gt;

&lt;p&gt;My need for control was forcing me to use the agent with the handbrake on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing confirmations from inside the cycle
&lt;/h2&gt;

&lt;p&gt;My next experiment was &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd-strict-cycle-confirmation%2FSKILL.md" rel="noopener noreferrer"&gt;tdd-strict-cycle-confirmation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of requiring approval at several boundaries inside the same TDD cycle, the agent could complete red, green, and refactor before returning control to me.&lt;/p&gt;

&lt;p&gt;The practical effect was simple.&lt;/p&gt;

&lt;p&gt;I approved the next behavior. The agent wrote the failing test, implemented the minimum code, evaluated the opportunity for refactoring, reran the relevant tests, and then stopped before beginning another cycle.&lt;/p&gt;

&lt;p&gt;This made the workflow considerably smoother.&lt;/p&gt;

&lt;p&gt;I still had frequent opportunities to intervene, but I no longer needed to authorize every mechanical transition. The feedback loop remained small enough for me to understand what had happened without unnecessarily interrupting the agent.&lt;/p&gt;

&lt;p&gt;For a while, this felt like the right balance.&lt;/p&gt;

&lt;p&gt;Then I wanted to know what would happen if I removed even that confirmation gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Letting the agent finish the feature
&lt;/h2&gt;

&lt;p&gt;I created another variation called &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd-strict-autonomous%2FSKILL.md" rel="noopener noreferrer"&gt;tdd-strict-autonomous&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This version no longer stopped after every completed cycle. It continued automatically through red, green, and refactor, pausing only when it encountered an exceptional situation such as ambiguous behavior, an unexpected failure, an architectural decision, or an environment problem.&lt;/p&gt;

&lt;p&gt;At the time, I was trying to implement &lt;a href="https://github.com/seed4j/seed4j-cli/issues/6" rel="noopener noreferrer"&gt;Registration of custom seed4j instances&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The feature would allow the Seed4j CLI to register additional Seed4j module providers and discover their modules at runtime.&lt;/p&gt;

&lt;p&gt;Even I did not know exactly what the technical solution should look like.&lt;/p&gt;

&lt;p&gt;That uncertainty was part of the experiment. Instead of directing every design decision, I wanted to observe what the agent would discover through TDD.&lt;/p&gt;

&lt;p&gt;Unfortunately, the experiment exposed a serious problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The implementation details loop
&lt;/h2&gt;

&lt;p&gt;I called the problem the &lt;strong&gt;implementation details loop&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The agent continued taking small steps. Each individual step appeared reasonable. Tests were being added, production code was changing, and the suite kept moving forward.&lt;/p&gt;

&lt;p&gt;But the implementation was no longer moving meaningfully toward the feature.&lt;/p&gt;

&lt;p&gt;The agent had become absorbed in the internal structure it was creating.&lt;/p&gt;

&lt;p&gt;A new class encouraged a new test class. That test exposed another internal detail. Supporting that detail required another production abstraction, which then received its own tests.&lt;/p&gt;

&lt;p&gt;The cycles were small, but the feature was disappearing from view.&lt;/p&gt;

&lt;p&gt;When I inspected the Codex CLI session, I found so much information that I could not identify the exact moment when the implementation had lost its direction.&lt;/p&gt;

&lt;p&gt;The problem was not a lack of activity.&lt;/p&gt;

&lt;p&gt;The problem was that local progress no longer implied progress through the feature's public path.&lt;/p&gt;

&lt;p&gt;I abandoned the implementation and returned to &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd-strict-cycle-confirmation%2FSKILL.md" rel="noopener noreferrer"&gt;tdd-strict-cycle-confirmation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This time, I wanted to find the precise cycle in which the agent started following implementation details instead of behavior.&lt;/p&gt;

&lt;p&gt;After finding it, I told Codex CLI that it was trapped in a loop and added this instruction to the TDD skills:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run a vertical checkpoint at least every two cycles using the public path of the feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent could still work through small units, but it now had to regularly prove that those units composed into observable progress.&lt;/p&gt;

&lt;p&gt;This improved the situation, but it did not solve everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the autonomous process quieter
&lt;/h2&gt;

&lt;p&gt;The agent still produced a large volume of messages.&lt;/p&gt;

&lt;p&gt;Detailed output had initially helped me trust the process. Once the agent became autonomous, however, the same volume made it harder to notice the information that actually mattered.&lt;/p&gt;

&lt;p&gt;Routine file reads, expected failures, test commands, green transitions, and minor refactorings created a long stream of activity.&lt;/p&gt;

&lt;p&gt;I created &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd-strict-autonomous-quiet%2FSKILL.md" rel="noopener noreferrer"&gt;tdd-strict-autonomous-quiet&lt;/a&gt; to reduce that noise.&lt;/p&gt;

&lt;p&gt;Quiet does not mean merely writing shorter messages.&lt;/p&gt;

&lt;p&gt;It means emitting fewer messages.&lt;/p&gt;

&lt;p&gt;The agent keeps ordinary cycle details internal and interrupts me only for meaningful events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an unexpected failure;&lt;/li&gt;
&lt;li&gt;a blocked environment;&lt;/li&gt;
&lt;li&gt;a public-path checkpoint failure;&lt;/li&gt;
&lt;li&gt;an architectural or public API decision;&lt;/li&gt;
&lt;li&gt;a significant refactoring;&lt;/li&gt;
&lt;li&gt;a final summary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This made autonomous execution much easier to follow.&lt;/p&gt;

&lt;p&gt;However, the quieter output also made another problem clearer.&lt;/p&gt;

&lt;p&gt;The agent was still creating too many tests tied to the structure of the production code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests should not mirror production topology
&lt;/h2&gt;

&lt;p&gt;I frequently saw one test class for every production class.&lt;/p&gt;

&lt;p&gt;When the implementation extracted a helper, resolver, parser, mapper, or adapter, the agent often created a corresponding test.&lt;/p&gt;

&lt;p&gt;The final suite could have excellent coverage while still being fragile.&lt;/p&gt;

&lt;p&gt;A refactoring that renamed, moved, split, or merged production classes could require several tests to change even when no observable behavior had changed.&lt;/p&gt;

&lt;p&gt;I could correct the direction manually, but doing so repeatedly was becoming too much work.&lt;/p&gt;

&lt;p&gt;The agent was failing to apply a concept presented in complementary ways in these two articles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://blog.cleancoder.com/uncle-bob/2017/10/03/TestContravariance.html" rel="noopener noreferrer"&gt;Test Contra-variance, by Uncle Bob&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tidyfirst.substack.com/p/additional-testing-after-refactoring" rel="noopener noreferrer"&gt;Additional Testing After Refactoring, by Kent Beck&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My interpretation is that the shape of the tests should not follow the shape of the production code.&lt;/p&gt;

&lt;p&gt;Production code may become more detailed as the design evolves. It may gain more classes, functions, modules, and internal abstractions.&lt;/p&gt;

&lt;p&gt;The tests do not need to reproduce that topology.&lt;/p&gt;

&lt;p&gt;They should remain attached to observable behavior and stable contracts.&lt;/p&gt;

&lt;p&gt;A test is suspicious when it fails merely because the production code was internally reorganized while preserving the same behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture defines stable observation points
&lt;/h2&gt;

&lt;p&gt;Before improving the TDD skill again, I realized that the agent was also failing to respect the chosen hexagonal architecture consistently.&lt;/p&gt;

&lt;p&gt;This matters because architecture helps identify useful and stable observation points for tests.&lt;/p&gt;

&lt;p&gt;A command-line feature can often be tested through the CLI boundary. An application behavior can be exercised through an application service. Domain rules can be verified through domain contracts.&lt;/p&gt;

&lt;p&gt;Internal adapters and implementation helpers usually do not need tests merely because they exist.&lt;/p&gt;

&lt;p&gt;For a practical explanation of this relationship, I recommend &lt;a href="https://www.youtube.com/live/PE57mE3qaHI?is=seGIWqGBGgq8cKdA" rel="noopener noreferrer"&gt;TDD in Hexagonal and Clean Architecture&lt;/a&gt;, by &lt;a href="https://www.linkedin.com/in/valentinajemuovic" rel="noopener noreferrer"&gt;Valentina Jemuović&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Without enforceable architectural boundaries, an agent can gradually move behavior into the wrong layer while continuing to produce passing tests.&lt;/p&gt;

&lt;p&gt;The tests may verify the code it created without protecting the design I intended.&lt;/p&gt;

&lt;p&gt;Prompt instructions alone were not enough.&lt;/p&gt;

&lt;p&gt;I needed the repository itself to reject architectural violations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the architecture executable
&lt;/h2&gt;

&lt;p&gt;I implemented architectural tests such as &lt;a href="https://github.com/seed4j/seed4j-cli/blob/main/src%2Ftest%2Fjava%2Fcom%2Fseed4j%2Fcli%2FHexagonalArchTest.java" rel="noopener noreferrer"&gt;HexagonalArchTest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These tests use ArchUnit to enforce rules including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;domain code must not depend on infrastructure;&lt;/li&gt;
&lt;li&gt;application code must not depend on infrastructure adapters;&lt;/li&gt;
&lt;li&gt;primary adapters must not depend directly on secondary adapters;&lt;/li&gt;
&lt;li&gt;secondary adapters must not depend on the application layer;&lt;/li&gt;
&lt;li&gt;bounded contexts must communicate through the intended boundaries;&lt;/li&gt;
&lt;li&gt;domain ports must represent business capabilities;&lt;/li&gt;
&lt;li&gt;composition code must remain in the composition root.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This changed my relationship with the agent.&lt;/p&gt;

&lt;p&gt;I no longer needed to rely only on a written instruction saying, “Respect the hexagonal architecture.”&lt;/p&gt;

&lt;p&gt;The test suite could detect violations.&lt;/p&gt;

&lt;p&gt;The architecture became executable feedback inside the same loop the agent was already following.&lt;/p&gt;

&lt;p&gt;When an architectural test failed, the agent received concrete evidence that its current design had crossed a boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  From strict TDD to behavior focused TDD
&lt;/h2&gt;

&lt;p&gt;The remaining task was to combine everything I had learned into another skill.&lt;/p&gt;

&lt;p&gt;I created &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/tdd-behavior-autonomous-quiet%2FSKILL.md" rel="noopener noreferrer"&gt;tdd-behavior-autonomous-quiet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It preserves autonomous red-green-refactor cycles and quiet output, but it adds an important requirement: tests must follow observable behavior, public contracts, user journeys, or intentionally stable component APIs.&lt;/p&gt;

&lt;p&gt;They must not follow production file and class structure.&lt;/p&gt;

&lt;p&gt;Before creating a new test class, the agent must effectively answer three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which behavior is being specified?&lt;/li&gt;
&lt;li&gt;Through which public or stable API is that behavior observed?&lt;/li&gt;
&lt;li&gt;Why is no existing behavior test suite the appropriate home for it?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Extracting a new internal class does not automatically justify creating a new test class.&lt;/p&gt;

&lt;p&gt;Moving production code does not automatically justify moving tests.&lt;/p&gt;

&lt;p&gt;A lower-level test is appropriate only when the component has a stable API that is independently meaningful to a caller.&lt;/p&gt;

&lt;p&gt;The agent should prefer the highest useful observation point that still provides clear and sufficiently fast feedback.&lt;/p&gt;

&lt;p&gt;This was the missing piece.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining the skill with execution plans
&lt;/h2&gt;

&lt;p&gt;Today, I use &lt;code&gt;tdd-behavior-autonomous-quiet&lt;/code&gt; to implement execution plans created through the process I described in &lt;a href="https://renanfranca.github.io/when-plan-mode-was-no-longer-enough.html" rel="noopener noreferrer"&gt;When Plan Mode Was No Longer Enough&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Previously, I asked the agent to implement one milestone at a time. I reviewed the result and explicitly authorized the next milestone.&lt;/p&gt;

&lt;p&gt;I no longer do that.&lt;/p&gt;

&lt;p&gt;I realized that a milestone does not always correspond to a complete feature or even a complete design decision.&lt;/p&gt;

&lt;p&gt;Sometimes I reviewed an intermediate state and corrected something that would naturally have been resolved in a later milestone. My intervention was based on incomplete information.&lt;/p&gt;

&lt;p&gt;Now I wait for the entire execution plan to be implemented.&lt;/p&gt;

&lt;p&gt;The execution plan gives the agent the destination, context, constraints, validation strategy, and important decisions.&lt;/p&gt;

&lt;p&gt;The TDD skill controls how the implementation moves toward that destination.&lt;/p&gt;

&lt;p&gt;The architectural tests protect the boundaries of the system.&lt;/p&gt;

&lt;p&gt;The vertical checkpoints verify that local cycles continue producing progress through the public path.&lt;/p&gt;

&lt;p&gt;Together, these elements allow the agent to work autonomously without reducing the process to “generate everything and add tests afterwards.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Reviewing the result as a pull request
&lt;/h2&gt;

&lt;p&gt;The result is usually well designed code with tests that genuinely verify behavior.&lt;/p&gt;

&lt;p&gt;I still find opportunities for refactoring and improvement.&lt;/p&gt;

&lt;p&gt;But the experience now feels like reviewing a very well written pull request.&lt;/p&gt;

&lt;p&gt;I begin with the first behavior test.&lt;/p&gt;

&lt;p&gt;I understand what it protects.&lt;/p&gt;

&lt;p&gt;Then I examine the production code that makes it pass.&lt;/p&gt;

&lt;p&gt;I continue following that relationship between behavior and implementation until I complete the review.&lt;/p&gt;

&lt;p&gt;A practical example is the pull request &lt;a href="https://github.com/seed4j/seed4j-cli/pull/272/commits" rel="noopener noreferrer"&gt;enhance apply plan dependency status&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first commit contains exactly what the agent developed, without any intervention from me.&lt;/p&gt;

&lt;p&gt;The remaining commits show the adjustments I made during my review.&lt;/p&gt;

&lt;p&gt;That distinction is important because it makes the result inspectable.&lt;/p&gt;

&lt;p&gt;It shows what autonomous implementation produced and where my judgment still changed the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autonomy introduced a different waiting problem
&lt;/h2&gt;

&lt;p&gt;Waiting between three and six minutes for the agent to deliver the implementation still bothers me.&lt;/p&gt;

&lt;p&gt;The agent writes quickly enough that I cannot meaningfully follow every operation in real time.&lt;/p&gt;

&lt;p&gt;At the same time, it is slow enough to leave me waiting and disconnected from the problem solving process.&lt;/p&gt;

&lt;p&gt;Ideally, the interaction would &lt;a href="https://newsletter.kentbeck.com/p/the-precious-eyeblink" rel="noopener noreferrer"&gt;respond within the precious 400 milliseconds&lt;/a&gt;, preserving the feeling of a continuous workflow.&lt;/p&gt;

&lt;p&gt;Instead, I delegate the work, wait, and later receive an implementation that I need to load into my mind.&lt;/p&gt;

&lt;p&gt;This creates a different kind of cognitive cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  I am not a multitasker
&lt;/h2&gt;

&lt;p&gt;I am not a multitasker.&lt;/p&gt;

&lt;p&gt;I can perform tasks sequentially, and TDD supported this extremely well.&lt;/p&gt;

&lt;p&gt;After completing a red-green-refactor cycle, I had a natural stopping point. If I was interrupted, I knew that the suite was green and the current behavior had been completed.&lt;/p&gt;

&lt;p&gt;When I returned, the next failing test or pending behavior told me where to continue.&lt;/p&gt;

&lt;p&gt;Reviewing an autonomous implementation is different.&lt;/p&gt;

&lt;p&gt;If I am interrupted in the middle of the review, I need to mark which test I have already examined and which one I should read next.&lt;/p&gt;

&lt;p&gt;I also carry a greater cognitive load because I did not participate directly in each problem solving step.&lt;/p&gt;

&lt;p&gt;The final code may be clear, but the path that produced it is not fixed in my mind in the same way as code I developed myself.&lt;/p&gt;

&lt;p&gt;The agent has reduced the effort required to produce the implementation.&lt;/p&gt;

&lt;p&gt;It has not eliminated the effort required for me to understand and assume responsibility for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Answering my previous questions
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://renanfranca.github.io/for-me-tdd-is-therapy.html#ai-agents-brought-the-anxiety-back" rel="noopener noreferrer"&gt;For Me, TDD Is Therapy&lt;/a&gt;, I asked three questions.&lt;/p&gt;

&lt;p&gt;I can now answer two of them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Am I limiting the AI agent by requiring it to work through TDD?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I reduced my need for control as much as I currently consider responsible.&lt;/p&gt;

&lt;p&gt;I no longer write the tests myself. I do not approve every test, every green implementation, every refactoring, every cycle, or every milestone.&lt;/p&gt;

&lt;p&gt;I entrust the TDD process to the agent until the complete execution plan has been implemented or a meaningful exception requires my attention.&lt;/p&gt;

&lt;p&gt;The constraints remain strict, but routine control no longer depends on me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can I reproduce the TDD feedback loop when working with an AI agent?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I moved toward it gradually.&lt;/p&gt;

&lt;p&gt;Initially, every transition was visible and required confirmation. Later, I approved only complete cycles. Then I allowed cycles to continue autonomously.&lt;/p&gt;

&lt;p&gt;Today, most routine steps remain internal, but the agent surfaces relevant decisions, failures, checkpoints, and refactorings.&lt;/p&gt;

&lt;p&gt;I no longer experience the feedback loop by personally performing each step.&lt;/p&gt;

&lt;p&gt;Instead, I make the loop executable through the skill, the test suite, the architectural rules, and the public path checkpoints.&lt;/p&gt;

&lt;p&gt;That is not the same experience as practising TDD manually, but it preserves the properties I care about.&lt;/p&gt;

&lt;p&gt;The third question remains more difficult.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the agent genuinely practise TDD, or does it develop the solution first and create the tests afterwards?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My friend &lt;a href="https://www.linkedin.com/in/victor-perone-696634a7?utm_source=share_via&amp;amp;utm_content=profile&amp;amp;utm_medium=member_android" rel="noopener noreferrer"&gt;Victor Perone&lt;/a&gt; introduced me to a few machine learning concepts.&lt;/p&gt;

&lt;p&gt;That alone was enough for me to realize how different this field is from my own.&lt;/p&gt;

&lt;p&gt;To answer this question properly, I would need to investigate much more deeply what happens inside an LLM while it appears to perform a TDD cycle.&lt;/p&gt;

&lt;p&gt;Anthropic itself is still investigating how language models internally reach their outputs, as shown in &lt;a href="https://transformer-circuits.pub/2025/attribution-graphs/biology.html" rel="noopener noreferrer"&gt;On the Biology of a Large Language Model&lt;/a&gt; and &lt;a href="https://transformer-circuits.pub/2026/workspace/index.html" rel="noopener noreferrer"&gt;Verbalizable Representations Form a Global Workspace in Language Models&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For now, I can verify the external process.&lt;/p&gt;

&lt;p&gt;I can require a failing behavior test before production code changes.&lt;/p&gt;

&lt;p&gt;I can inspect the failure.&lt;/p&gt;

&lt;p&gt;I can constrain the green implementation.&lt;/p&gt;

&lt;p&gt;I can require refactoring only while the suite is green.&lt;/p&gt;

&lt;p&gt;I can enforce architectural boundaries and repeatedly validate the feature through its public path.&lt;/p&gt;

&lt;p&gt;I still cannot claim to know what happened internally before the agent displayed each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually learned to trust
&lt;/h2&gt;

&lt;p&gt;I did not learn to trust every line generated by an AI agent.&lt;/p&gt;

&lt;p&gt;I learned to trust a process with executable constraints.&lt;/p&gt;

&lt;p&gt;The agent owns the individual TDD cycles.&lt;/p&gt;

&lt;p&gt;The execution plan preserves the destination.&lt;/p&gt;

&lt;p&gt;Behavior tests protect what users and callers can observe.&lt;/p&gt;

&lt;p&gt;Architectural tests protect the system's boundaries.&lt;/p&gt;

&lt;p&gt;Vertical checkpoints prevent small implementation steps from losing the feature.&lt;/p&gt;

&lt;p&gt;I remain responsible for reviewing the result and deciding whether it belongs in the codebase.&lt;/p&gt;

&lt;p&gt;Delegating TDD did not remove me from software development.&lt;/p&gt;

&lt;p&gt;It changed where I participate.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>For Me, TDD Is Therapy</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:46:45 +0000</pubDate>
      <link>https://dev.to/renanfranca/for-me-tdd-is-therapy-2e10</link>
      <guid>https://dev.to/renanfranca/for-me-tdd-is-therapy-2e10</guid>
      <description>&lt;h2&gt;
  
  
  The anxiety I recognized
&lt;/h2&gt;

&lt;p&gt;While watching the podcast &lt;a href="https://youtu.be/ddHQQtjIOpw?t=4785&amp;amp;is=ZgGjff_muSzUlo6c" rel="noopener noreferrer"&gt;How Kent Beck Shapes the Software Engineering Industry&lt;/a&gt;, I heard Kent Beck describe the anxiety he felt while developing software and how Test-Driven Development helped him deal with it.&lt;/p&gt;

&lt;p&gt;I immediately recognized that feeling.&lt;/p&gt;

&lt;p&gt;I have felt it since my first contact with programming in 2006, during my Computer Science degree.&lt;/p&gt;

&lt;p&gt;I never knew exactly where to begin an implementation.&lt;/p&gt;

&lt;p&gt;The process was always different. It was highly intuitive and depended heavily on my mood, motivation, and confidence on that particular day.&lt;/p&gt;

&lt;p&gt;Sometimes I would spend too much time thinking about the best place to start. Other times I would begin somewhere almost randomly and hope that the implementation would eventually reveal its shape.&lt;/p&gt;

&lt;p&gt;There was no process I could trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  When working code was not enough
&lt;/h2&gt;

&lt;p&gt;The uncertainty was so intense that, when something I implemented worked on the first try, I did not trust it.&lt;/p&gt;

&lt;p&gt;A successful result was not enough to convince me.&lt;/p&gt;

&lt;p&gt;I needed to deliberately break the production code and repeat the manual test. Only after watching the behavior fail could I feel confident that my manual verification was actually exercising the change.&lt;/p&gt;

&lt;p&gt;Otherwise, I was left with uncomfortable questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the implementation really work?&lt;/li&gt;
&lt;li&gt;Was my manual test actually exercising the changed behavior?&lt;/li&gt;
&lt;li&gt;Did it work for the reason I expected?&lt;/li&gt;
&lt;li&gt;Was there some accidental condition making everything appear correct?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did not have a reliable way to move from uncertainty to confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  For me, TDD is therapy
&lt;/h2&gt;

&lt;p&gt;For me, TDD is therapy.&lt;/p&gt;

&lt;p&gt;That is what I believe.&lt;/p&gt;

&lt;p&gt;Not because TDD removes uncertainty from software development. It does not.&lt;/p&gt;

&lt;p&gt;It gives me a systematic process for moving through that uncertainty.&lt;/p&gt;

&lt;p&gt;I do not need to discover the entire implementation before I begin. I only need to identify the next observable behavior and express it as a test.&lt;/p&gt;

&lt;p&gt;Then I watch it fail.&lt;/p&gt;

&lt;p&gt;I implement enough to make it pass.&lt;/p&gt;

&lt;p&gt;I refactor while keeping the behavior protected.&lt;/p&gt;

&lt;p&gt;And then I repeat the cycle.&lt;/p&gt;

&lt;p&gt;This process gives me somewhere to begin and tells me what to do next.&lt;/p&gt;

&lt;p&gt;On my best days, it gives structure to my ideas.&lt;/p&gt;

&lt;p&gt;On my worst days, it allows me to remain productive even when motivation and confidence are low.&lt;/p&gt;

&lt;p&gt;That is my main reason for practising TDD.&lt;/p&gt;

&lt;p&gt;The other benefits matter: executable documentation, regression protection, simpler designs, shorter feedback loops, and the confidence to refactor.&lt;/p&gt;

&lt;p&gt;But my primary motivation is more personal.&lt;/p&gt;

&lt;p&gt;TDD gives me a process I can follow when my intuition is not enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I started practising TDD
&lt;/h2&gt;

&lt;p&gt;I started deliberately practising TDD in December 2022 while contributing to the open source project now known as &lt;a href="https://seed4j.com/" rel="noopener noreferrer"&gt;Seed4j&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html" rel="noopener noreferrer"&gt;How did I earn money to fix an issue from an Open Source Software?&lt;/a&gt;, I described some of that first experience.&lt;/p&gt;

&lt;p&gt;At the time, Seed4j was still called JHipster Lite.&lt;/p&gt;

&lt;p&gt;That contribution also taught me an important distinction. I initially believed I was doing TDD, but I was actually writing tests before the implementation without necessarily allowing the tests to guide the design.&lt;/p&gt;

&lt;p&gt;I was doing &lt;em&gt;test first&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Learning that distinction did not discourage me. It gave me a clearer direction.&lt;/p&gt;

&lt;p&gt;Since then, TDD has become much more than writing tests before production code. It has become the process through which I investigate a problem, discover behavior, make design decisions, and build confidence incrementally.&lt;/p&gt;

&lt;p&gt;Two books were especially important in shaping how I understand this process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Test-Driven Development: By Example&lt;/em&gt;, by Kent Beck;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;TDD&lt;/em&gt;, by Jason Gorman.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The explanation I grew tired of repeating
&lt;/h2&gt;

&lt;p&gt;Before adopting this process, I grew tired of repeatedly explaining the same thing to people who assigned me a task:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This change is simple. What takes time is manually testing the entire system to ensure that nothing has been broken.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code change might require only a few lines.&lt;/p&gt;

&lt;p&gt;The real cost came afterwards.&lt;/p&gt;

&lt;p&gt;I needed to navigate through the application, recreate scenarios, remember which related features might be affected, and manually verify that an apparently unrelated behavior had not changed.&lt;/p&gt;

&lt;p&gt;Then I needed to repeat much of that work after every adjustment.&lt;/p&gt;

&lt;p&gt;Without automated tests, even a simple change carried a large and mostly invisible validation cost.&lt;/p&gt;

&lt;p&gt;TDD did not merely help me write the change. It helped me build the mechanism through which I could safely change it again.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the team does not want TDD
&lt;/h2&gt;

&lt;p&gt;I respect teams that do not want to work with TDD.&lt;/p&gt;

&lt;p&gt;I think it is unfortunate, but I accept it.&lt;/p&gt;

&lt;p&gt;I introduce the idea once. I explain why I believe it would help. If the team decides not to adopt it, I do not turn the subject into a permanent argument.&lt;/p&gt;

&lt;p&gt;Life goes on.&lt;/p&gt;

&lt;p&gt;However, for my own implementations, I still prefer to work through tests.&lt;/p&gt;

&lt;p&gt;When necessary, I create a private fork and maintain a branch containing the tests. I write the tests and implement the change there. Then I open the pull request containing only the production code expected by the project.&lt;/p&gt;

&lt;p&gt;This is not my preferred outcome. I would rather have the tests maintained alongside the implementation so that the entire team could benefit from them.&lt;/p&gt;

&lt;p&gt;But even when a project has insufficient test coverage, abandoning my process makes the work more difficult for me.&lt;/p&gt;

&lt;p&gt;The private branch allows me to preserve the feedback loop I need to implement the change with confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI agents brought the anxiety back
&lt;/h2&gt;

&lt;p&gt;AI agents changed my development workflow significantly.&lt;/p&gt;

&lt;p&gt;They can explore a codebase, propose a plan, implement changes, execute tests, refactor code, and document decisions much faster than I could do all of those things alone.&lt;/p&gt;

&lt;p&gt;But they also introduced new forms of anxiety.&lt;/p&gt;

&lt;p&gt;I started asking myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Am I limiting the AI agent by requiring it to work through TDD?&lt;/p&gt;

&lt;p&gt;How can I reproduce the TDD feedback loop when working with an AI agent?&lt;/p&gt;

&lt;p&gt;Does the agent genuinely practise TDD, or does it develop the solution first and create the tests afterwards?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That final question bothers me the most.&lt;/p&gt;

&lt;p&gt;An agent can produce a test and production code in the same implementation. The final diff may look exactly like the result of TDD.&lt;/p&gt;

&lt;p&gt;But the final diff does not reveal the process.&lt;/p&gt;

&lt;p&gt;Did the test fail before the implementation existed?&lt;/p&gt;

&lt;p&gt;Did that failure provide useful information?&lt;/p&gt;

&lt;p&gt;Did the test guide a design decision?&lt;/p&gt;

&lt;p&gt;Was only enough code written to satisfy the next behavior?&lt;/p&gt;

&lt;p&gt;Or did the agent first construct the complete solution and then create tests that confirmed what it had already built?&lt;/p&gt;

&lt;p&gt;The resulting repository may contain the same files, but the development process is not the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  The process still matters
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://renanfranca.github.io/when-plan-mode-was-no-longer-enough.html" rel="noopener noreferrer"&gt;When Plan Mode Was No Longer Enough&lt;/a&gt;, I described how execution plans and smaller milestones helped me reduce the volume of code I needed to review after working with an agent.&lt;/p&gt;

&lt;p&gt;That approach gave me more control over the size of each change.&lt;/p&gt;

&lt;p&gt;But it did not reproduce the TDD experience.&lt;/p&gt;

&lt;p&gt;A milestone can still contain production code, tests, and refactoring created together. It can be small enough to review while still hiding the sequence through which the design emerged.&lt;/p&gt;

&lt;p&gt;This matters to me because TDD is not valuable only because of the tests left behind.&lt;/p&gt;

&lt;p&gt;The sequence matters.&lt;/p&gt;

&lt;p&gt;The feedback matters.&lt;/p&gt;

&lt;p&gt;The small decisions made after each failure matter.&lt;/p&gt;

&lt;p&gt;Most importantly, the process changes how I think while implementing the solution.&lt;/p&gt;

&lt;p&gt;For years, TDD gave me a way to manage the anxiety of not knowing where to begin.&lt;/p&gt;

&lt;p&gt;Now AI agents are forcing me to examine that process more carefully than ever.&lt;/p&gt;

&lt;p&gt;I need to understand which parts of TDD must remain visible, which parts can be delegated, and how I can know whether an agent is following the process rather than merely reproducing its final appearance.&lt;/p&gt;

&lt;p&gt;I will explore those questions in my next post.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testing</category>
      <category>ai</category>
      <category>career</category>
    </item>
    <item>
      <title>When Plan Mode Was No Longer Enough</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:46:14 +0000</pubDate>
      <link>https://dev.to/renanfranca/when-plan-mode-was-no-longer-enough-4p43</link>
      <guid>https://dev.to/renanfranca/when-plan-mode-was-no-longer-enough-4p43</guid>
      <description>&lt;h2&gt;
  
  
  Plan Mode initially felt like enough
&lt;/h2&gt;

&lt;p&gt;My workflow with Codex CLI used to be relatively simple.&lt;/p&gt;

&lt;p&gt;I would enter Plan Mode, discuss what I wanted to implement, refine the scope, question some decisions, and eventually reach a plan that looked reasonable.&lt;/p&gt;

&lt;p&gt;Then I would leave Plan Mode and ask Codex to execute it.&lt;/p&gt;

&lt;p&gt;For a while, this felt like a good separation of responsibilities. First, we would think. Then, the agent would implement.&lt;/p&gt;

&lt;p&gt;But eventually, it stopped being enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  My first disappointment with AI agents
&lt;/h2&gt;

&lt;p&gt;The problem was not that Codex could not generate the code.&lt;/p&gt;

&lt;p&gt;The problem was that it could generate too much code at once.&lt;/p&gt;

&lt;p&gt;After a large implementation, I would receive a substantial set of changes that I still needed to understand, review, refactor, and validate. Sometimes the implementation was technically correct, but it contained decisions I would not have made myself.&lt;/p&gt;

&lt;p&gt;Other times, the tests passed, but some of them were tied to implementation details instead of protecting actual behavior.&lt;/p&gt;

&lt;p&gt;I started to feel exhausted after these sessions.&lt;/p&gt;

&lt;p&gt;The agent had accelerated implementation, but it had also created a large review queue for me. I was no longer spending most of my energy writing code. I was spending it trying to absorb, validate, and reshape everything the agent had produced.&lt;/p&gt;

&lt;p&gt;The bottleneck had moved.&lt;/p&gt;

&lt;p&gt;Codex was not struggling to generate code. I was struggling to review that code responsibly.&lt;/p&gt;

&lt;p&gt;This was my first real disappointment with AI agents.&lt;/p&gt;

&lt;p&gt;Not because they were incapable, but because I realized that generating code faster does not automatically make the entire development process faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shrinking the feedback loop
&lt;/h2&gt;

&lt;p&gt;While searching for a better approach, I found the OpenAI Cookbook article &lt;a href="https://developers.openai.com/cookbook/articles/codex_exec_plans" rel="noopener noreferrer"&gt;Using PLANS.md for multi-hour problem solving&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It describes an execution plan, or ExecPlan, as a self-contained and continuously updated document that an agent can follow while implementing a complex change.&lt;/p&gt;

&lt;p&gt;An ExecPlan is more than a list of tasks.&lt;/p&gt;

&lt;p&gt;It includes the purpose of the change, the current context, the desired behavior, implementation milestones, validation commands, risks, decisions, progress, and lessons learned.&lt;/p&gt;

&lt;p&gt;The concept that made the biggest difference for me was dividing the implementation into milestones.&lt;/p&gt;

&lt;p&gt;Instead of asking Codex to execute the entire plan, I started asking it to implement one milestone at a time.&lt;/p&gt;

&lt;p&gt;After each milestone, I could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;review a smaller volume of code;&lt;/li&gt;
&lt;li&gt;refactor while the context was still manageable;&lt;/li&gt;
&lt;li&gt;verify whether the tests protected behavior;&lt;/li&gt;
&lt;li&gt;question design decisions;&lt;/li&gt;
&lt;li&gt;run focused validation;&lt;/li&gt;
&lt;li&gt;update the plan with what we had learned;&lt;/li&gt;
&lt;li&gt;decide whether the implementation was ready to continue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only after I considered the result good enough would I ask Codex to implement the next milestone.&lt;/p&gt;

&lt;p&gt;The milestone became the unit of collaboration between me and the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning the idea into a skill
&lt;/h2&gt;

&lt;p&gt;The OpenAI Cookbook article is dated October 7, 2025, and its current version recommends &lt;code&gt;gpt-5.2-codex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After GPT-5.5 was released, I asked the model to revise the original instructions and make them more appropriate for the newer model.&lt;/p&gt;

&lt;p&gt;The result required fewer step-by-step directions and placed more emphasis on the properties the final execution plan should preserve.&lt;/p&gt;

&lt;p&gt;I then transformed those instructions into my &lt;a href="https://github.com/renanfranca/codex-skills/blob/main/implement-execplan/SKILL.md" rel="noopener noreferrer"&gt;implement-execplan&lt;/a&gt; skill.&lt;/p&gt;

&lt;p&gt;The skill defines an ExecPlan as a living document. It requires the agent to maintain sections such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;purpose and scope;&lt;/li&gt;
&lt;li&gt;existing context;&lt;/li&gt;
&lt;li&gt;desired end state;&lt;/li&gt;
&lt;li&gt;implementation milestones;&lt;/li&gt;
&lt;li&gt;progress;&lt;/li&gt;
&lt;li&gt;decisions and their rationale;&lt;/li&gt;
&lt;li&gt;risks and mitigations;&lt;/li&gt;
&lt;li&gt;validation strategy;&lt;/li&gt;
&lt;li&gt;lessons learned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also requires each milestone to contain concrete changes, validation commands, and observable acceptance criteria.&lt;/p&gt;

&lt;p&gt;However, the most important part of my workflow does not come only from the structure of the document.&lt;/p&gt;

&lt;p&gt;It comes from controlling when the next milestone starts.&lt;/p&gt;

&lt;p&gt;I do not want the agent to finish faster than I can understand the change.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example in seed4j-cli
&lt;/h2&gt;

&lt;p&gt;A concrete example came from a feature I implemented in &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;&lt;code&gt;seed4j-cli&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The ChatGPT Android app allows me to use a GitHub integration that can read repositories. I used it to inspect the project and discuss the feature with GPT-5.5 in an experience similar to Codex CLI Plan Mode.&lt;/p&gt;

&lt;p&gt;After refining the scope, I created the issue &lt;a href="https://github.com/seed4j/seed4j-cli/issues/270" rel="noopener noreferrer"&gt;Enhance &lt;code&gt;apply --plan&lt;/code&gt; with dependency chain status&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The goal was to improve the output of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;seed4j apply &amp;lt;module&amp;gt; &lt;span class="nt"&gt;--project-path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--plan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command already displayed resolved parameters, but it did not explain whether the module dependencies had already been applied, were still pending, or required an explicit feature choice.&lt;/p&gt;

&lt;p&gt;When it was time to implement the feature, I asked Codex CLI to read the issue and use my skill to create this execution plan:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/seed4j-cli-ai-context/blob/main/shared%2Fdone%2F2026-06-26_FEATURE_apply-plan-dependency-status-exec-plan.md" rel="noopener noreferrer"&gt;2026-06-26_FEATURE_apply-plan-dependency-status-exec-plan.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The work was divided into four milestones:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;establish the living execution plan;&lt;/li&gt;
&lt;li&gt;add the status of direct module dependencies;&lt;/li&gt;
&lt;li&gt;add feature dependency satisfaction and pending choices;&lt;/li&gt;
&lt;li&gt;update documentation and validate formatting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This division gave me natural stopping points.&lt;/p&gt;

&lt;p&gt;After the direct module dependency behavior was implemented, I could review it before introducing the more complex feature dependency rules.&lt;/p&gt;

&lt;p&gt;After the behavior was stable, documentation and formatting could be handled separately.&lt;/p&gt;

&lt;p&gt;What changed was not necessarily the quality of every generated line.&lt;/p&gt;

&lt;p&gt;What changed was the size of the feedback loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The document became part of the work
&lt;/h2&gt;

&lt;p&gt;There was another benefit I had not fully anticipated.&lt;/p&gt;

&lt;p&gt;The execution plan became a record of the implementation.&lt;/p&gt;

&lt;p&gt;During the work, Codex continuously updated the document with completed milestones, design decisions, validation results, discovered risks, unrelated repository problems, and lessons learned.&lt;/p&gt;

&lt;p&gt;For example, the final document records why dependency planning remained in the CLI primary adapter, why CLI integration tests were used as the behavior contract, and why the dependency traversal needed to be deterministic and cycle-safe.&lt;/p&gt;

&lt;p&gt;It also records that the repository-wide formatting check contained pre-existing failures unrelated to the feature, while the files changed by the implementation passed focused formatting validation.&lt;/p&gt;

&lt;p&gt;Without the execution plan, much of that context would have disappeared inside the conversation.&lt;/p&gt;

&lt;p&gt;The code would remain, but the reasoning behind several decisions would be lost.&lt;/p&gt;

&lt;p&gt;Instead, I ended the implementation with both working code and a document describing how the implementation evolved.&lt;/p&gt;

&lt;p&gt;In another post, I plan to explain what I started doing with these files instead of simply discarding them after the feature was completed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this approach still does not solve
&lt;/h2&gt;

&lt;p&gt;Execution plans helped me control the size of generated changes, but they did not solve everything.&lt;/p&gt;

&lt;p&gt;Codex can still create tests that are too closely tied to implementation details. A smaller milestone makes those tests easier to identify, but it does not automatically make them good.&lt;/p&gt;

&lt;p&gt;This approach also does not reproduce the TDD experience I was used to.&lt;/p&gt;

&lt;p&gt;In traditional TDD, the feedback loop begins with a failing test that expresses the next behavior. The design emerges through small cycles of failure, implementation, and refactoring.&lt;/p&gt;

&lt;p&gt;An ExecPlan organizes implementation into milestones, but a milestone can still contain too much production code before the right behavioral tests are established.&lt;/p&gt;

&lt;p&gt;I have made progress in this area by combining execution plans with other skills and more explicit testing workflows.&lt;/p&gt;

&lt;p&gt;That deserves its own post because it changes not only how the agent implements a feature, but also how I participate during the implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regaining control without rejecting the agent
&lt;/h2&gt;

&lt;p&gt;My first reaction to the review burden could have been to reduce my use of AI agents.&lt;/p&gt;

&lt;p&gt;Instead, I changed the granularity of the work I delegated to them.&lt;/p&gt;

&lt;p&gt;The answer was not a more detailed initial conversation followed by an even larger autonomous implementation.&lt;/p&gt;

&lt;p&gt;The answer was a living plan, smaller milestones, explicit validation, and deliberate stopping points.&lt;/p&gt;

&lt;p&gt;I still review the code.&lt;/p&gt;

&lt;p&gt;I still refactor it.&lt;/p&gt;

&lt;p&gt;I still question tests and design decisions.&lt;/p&gt;

&lt;p&gt;The execution plan does not remove my responsibility from the process. It gives me a structure that makes that responsibility sustainable.&lt;/p&gt;

&lt;p&gt;For me, that has become one of the most important lessons about working with coding agents:&lt;/p&gt;

&lt;p&gt;The agent's ability to generate code is not the only limit that matters.&lt;/p&gt;

&lt;p&gt;My ability to understand, validate, and improve that code matters just as much.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Sharing Pieces of My AI Agent Workflow</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:46:12 +0000</pubDate>
      <link>https://dev.to/renanfranca/sharing-pieces-of-my-ai-agent-workflow-1lg0</link>
      <guid>https://dev.to/renanfranca/sharing-pieces-of-my-ai-agent-workflow-1lg0</guid>
      <description>&lt;h2&gt;
  
  
  Why I stopped writing about it
&lt;/h2&gt;

&lt;p&gt;I had given up on writing about my progress with AI agents for a while.&lt;/p&gt;

&lt;p&gt;Not because I stopped experimenting. Quite the opposite.&lt;/p&gt;

&lt;p&gt;The problem is that everything changes too fast.&lt;/p&gt;

&lt;p&gt;Every time I felt close to describing my workflow, I would improve something, replace a tool, change a prompt, adjust a habit, or discover a better way to interact with the agent. The idea of publishing a “complete workflow” started to feel wrong, because I knew it would become outdated almost immediately.&lt;/p&gt;

&lt;p&gt;And I did not want to create an exhausting commitment for myself: writing a post today, then feeling forced to update it every time my process changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I did not want to sound prescriptive
&lt;/h2&gt;

&lt;p&gt;There was another reason too.&lt;/p&gt;

&lt;p&gt;I did not want to sound like I was trying to impose a workflow.&lt;/p&gt;

&lt;p&gt;My biggest discoveries with AI agents have been very individual. They did not come from a perfectly synchronized team process. They came from trial and error, from frustration, from curiosity, from small improvements, and from many moments where I had to rethink how I work as a software developer.&lt;/p&gt;

&lt;p&gt;So, for some time, I preferred not to write about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed my mind
&lt;/h2&gt;

&lt;p&gt;But recently, after watching the podcasts from &lt;a href="https://stillburningpodcast.com/" rel="noopener noreferrer"&gt;Kent Beck - Still Burning&lt;/a&gt;, I felt a strong desire to contribute more openly to this revolution that is happening.&lt;/p&gt;

&lt;p&gt;AI agents are changing software development, but not only because of the tools themselves. They are also forcing us to rethink discipline, feedback loops, communication, design, testing, and the way we describe intent.&lt;/p&gt;

&lt;p&gt;And I do not want to be only a consumer of this change.&lt;/p&gt;

&lt;p&gt;I want to contribute to the conversation.&lt;/p&gt;

&lt;p&gt;Maybe by sharing parts of what I am discovering, I can help someone else. And maybe, by making these ideas public, I can also accelerate my own learning through external insights, criticism, and suggestions.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better format
&lt;/h2&gt;

&lt;p&gt;So I started thinking about a better format.&lt;/p&gt;

&lt;p&gt;Instead of trying to publish my entire workflow as if it were a recipe, I decided to share smaller steps from it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pieces.&lt;/li&gt;
&lt;li&gt;Practices.&lt;/li&gt;
&lt;li&gt;Decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things that can be adapted, improved, questioned, or absorbed into someone else’s workflow.&lt;/p&gt;

&lt;p&gt;That feels much more honest to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I want to share
&lt;/h2&gt;

&lt;p&gt;A complete AI agent workflow is too personal and too unstable to be treated as a final answer. But specific ideas can still be useful. A way to prepare context. A way to ask for changes. A way to review generated code. A way to avoid losing control. A way to keep tests and design as the center of the process instead of blindly trusting the agent.&lt;/p&gt;

&lt;p&gt;That is what I want to share.&lt;/p&gt;

&lt;p&gt;Not a definitive workflow.&lt;/p&gt;

&lt;p&gt;Not a universal method.&lt;/p&gt;

&lt;p&gt;Not “this is how everyone should work with AI agents.”&lt;/p&gt;

&lt;p&gt;Just pieces of my current process, shared while they are still alive, still changing, and still being tested in real work.&lt;/p&gt;

&lt;p&gt;I will start doing that soon.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>productivity</category>
      <category>writing</category>
    </item>
    <item>
      <title>Intention in Portuguese, Code in English</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:45:40 +0000</pubDate>
      <link>https://dev.to/renanfranca/intention-in-portuguese-code-in-english-1fj9</link>
      <guid>https://dev.to/renanfranca/intention-in-portuguese-code-in-english-1fj9</guid>
      <description>&lt;h2&gt;
  
  
  From English prompts to Portuguese intention
&lt;/h2&gt;

&lt;p&gt;I am Brazilian, and my native language is Portuguese.&lt;/p&gt;

&lt;p&gt;Since the launch of ChatGPT, I got used to interacting with it in English. At the time, it was not just a preference. I clearly felt that the responses were better, and it also made my work easier when I wanted to generate code, documentation, method names, tests, and examples for my open-source projects.&lt;/p&gt;

&lt;p&gt;Because most of the projects I contribute to use English as the standard language, using English with the AI felt natural.&lt;/p&gt;

&lt;p&gt;But something changed.&lt;/p&gt;

&lt;p&gt;Today, when I use Codex CLI for programming, I talk to it almost exclusively in Portuguese.&lt;/p&gt;

&lt;p&gt;Even when the repository is in English.&lt;/p&gt;

&lt;p&gt;Even when the documentation is in English.&lt;/p&gt;

&lt;p&gt;Even when the generated code must follow English naming conventions.&lt;/p&gt;

&lt;p&gt;And this still feels a little amazing to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talking informally to the agent
&lt;/h2&gt;

&lt;p&gt;The interesting part is not only the language itself.&lt;/p&gt;

&lt;p&gt;The interesting part is how informal the interaction became.&lt;/p&gt;

&lt;p&gt;When I am working on a feature, I usually talk to the AI agent in Portuguese, in a very natural way. I describe what I want, what I am worried about, what I think should be done first, and sometimes what I do not want it to do.&lt;/p&gt;

&lt;p&gt;In many cases, before implementing the feature, the agent creates a Markdown document with the implementation steps.&lt;/p&gt;

&lt;p&gt;That document is also written in Portuguese. 😀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://renanfranca.github.io/when-plan-mode-was-no-longer-enough.html" rel="noopener noreferrer"&gt;Later, I want to share more details about how I usually get that document created, because this small step has become an important part of my workflow.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But even with that planning document in Portuguese, the implementation itself remains aligned with the project.&lt;/p&gt;

&lt;p&gt;Method names are in English.&lt;/p&gt;

&lt;p&gt;Tests are in English.&lt;/p&gt;

&lt;p&gt;Feature documentation is in English.&lt;/p&gt;

&lt;p&gt;The code follows the repository language, not the language I used to describe my intention.&lt;/p&gt;

&lt;h2&gt;
  
  
  The repository defines the language of the work
&lt;/h2&gt;

&lt;p&gt;After looking more carefully at what makes this possible, my conclusion is simple:&lt;/p&gt;

&lt;p&gt;I provide the intention in Portuguese.&lt;/p&gt;

&lt;p&gt;Codex reads the repository.&lt;/p&gt;

&lt;p&gt;It sees that &lt;a href="https://github.com/seed4j/seed4j-cli/blob/main/AGENTS.md" rel="noopener noreferrer"&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/a&gt; is entirely in English.&lt;/p&gt;

&lt;p&gt;It understands that the project is standardized in English.&lt;/p&gt;

&lt;p&gt;Then it applies my request using the language of the project.&lt;/p&gt;

&lt;p&gt;That means the agent is not just translating my words directly into files. It is reading the surrounding context and adapting the output to the conventions that already exist there.&lt;/p&gt;

&lt;p&gt;This is the part that I find fascinating.&lt;/p&gt;

&lt;p&gt;The conversation can happen in one language, while the work product follows another language.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;seed4j-cli&lt;/a&gt; is the project I am working on, where I have experienced everything I mentioned 😀&lt;/p&gt;

&lt;h2&gt;
  
  
  Intention is not implementation
&lt;/h2&gt;

&lt;p&gt;This made me think about the difference between intention and implementation.&lt;/p&gt;

&lt;p&gt;When I talk to the agent in Portuguese, I am not asking it to make the project Portuguese.&lt;/p&gt;

&lt;p&gt;I am using my native language to express intent with more precision, less friction, and more comfort.&lt;/p&gt;

&lt;p&gt;The repository still has its own language.&lt;/p&gt;

&lt;p&gt;The code still has its own conventions.&lt;/p&gt;

&lt;p&gt;The documentation still has its own audience.&lt;/p&gt;

&lt;p&gt;The agent becomes the bridge between those layers.&lt;/p&gt;

&lt;p&gt;And maybe this is one of the reasons why working with AI agents feels different from only asking a chatbot to generate snippets. The agent is not only answering a question. It is operating inside a context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters to me
&lt;/h2&gt;

&lt;p&gt;For a long time, I associated “better AI results” with “using English.”&lt;/p&gt;

&lt;p&gt;That still may be true in many situations.&lt;/p&gt;

&lt;p&gt;But with an agent working inside a repository, the situation becomes more nuanced.&lt;/p&gt;

&lt;p&gt;The quality of the result does not depend only on the language of the prompt. It also depends on the quality of the repository context, the project conventions, the instructions, the tests, and the way the agent is asked to reason before changing code.&lt;/p&gt;

&lt;p&gt;This is a very different experience.&lt;/p&gt;

&lt;p&gt;I can think in Portuguese.&lt;/p&gt;

&lt;p&gt;I can explain the intention in Portuguese.&lt;/p&gt;

&lt;p&gt;I can ask questions in Portuguese.&lt;/p&gt;

&lt;p&gt;But the final result can still respect an English-based open-source project.&lt;/p&gt;

&lt;p&gt;That feels like a small but important shift in how I work.&lt;/p&gt;

&lt;h2&gt;
  
  
  A question for other developers
&lt;/h2&gt;

&lt;p&gt;I am still experimenting with this, but I am curious if other people are doing something similar.&lt;/p&gt;

&lt;p&gt;Do you interact with an AI agent in a language other than English, even when the project itself uses English as its standard language?&lt;/p&gt;

&lt;p&gt;And if you do, does the agent preserve the project language well?&lt;/p&gt;

&lt;p&gt;I would love to hear how other developers are handling this.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Tales of a Dev - An Alternative Reality</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:45:39 +0000</pubDate>
      <link>https://dev.to/renanfranca/tales-of-a-dev-an-alternative-reality-76m</link>
      <guid>https://dev.to/renanfranca/tales-of-a-dev-an-alternative-reality-76m</guid>
      <description>&lt;p&gt;It’s been a little over a year since I realized that I work in the desert (&lt;a href="https://martinfowler.com/bliki/ForestAndDesert.html" rel="noopener noreferrer"&gt;a term coined by Kent Beck&lt;/a&gt;), and I understood why some things that are so useful and cool in the forest didn’t work when I tried to bring them into the desert.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talking to people outside my reality
&lt;/h2&gt;

&lt;p&gt;So I decided to talk to people who are outside my reality to see how their day to day works, what new pain points they have that I’ll never experience in the desert because I’m dealing with more “basic” problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning from open-source friends
&lt;/h2&gt;

&lt;p&gt;For a while now, I’ve been talking to people I work with on open-source projects (e.g., &lt;a href="https://seed4j.com" rel="noopener noreferrer"&gt;seed4j.com&lt;/a&gt;), and even though the project is incredible, it’s impossible to apply it in the desert where I work. I was fascinated to learn how they use it in their daily routine. It’s not just exciting because it’s something sophisticated; it’s genuinely useful and makes the day to day less stressful and overwhelming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replying to a newsletter
&lt;/h2&gt;

&lt;p&gt;Recently, I received an email from a newsletter (I’ve subscribed to several), and what caught my attention was the frankness of the writing and a genuine invitation to reply because the author was interested in talking and getting insights from other people’s perspectives. I replied, and I’ve kept talking with him, someone who, in my opinion, works in the forest. These are interesting conversations that help me discover new things that my reality would hardly ever provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Catching up with a developer friend
&lt;/h2&gt;

&lt;p&gt;On top of that, I had the chance to talk over a video call with a developer friend I hadn’t spoken to in a long time. I was impressed to discover new areas where a developer can work, areas I didn’t even know existed. In the end, it felt like a conversation with a longtime friend. It had been a long time since I’d spoken English, but I felt so comfortable that at no point did I feel that speaking English was getting in the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to Seed4J CLI
&lt;/h2&gt;

&lt;p&gt;I decided that I’m going to get back to working on the &lt;a href="https://github.com/seed4j/seed4j-cli" rel="noopener noreferrer"&gt;Seed4J CLI&lt;/a&gt;, but before that, I decided to reach out to other developers who use Seed4J to understand how they use it day to day and to learn a bit about their work routine. Surprisingly, a developer has already replied and supported me, saying that creating this CLI application might be a good path so that the AI can autonomously understand which features Seed4J has and use them whenever appropriate, making the experience more transparent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation boost
&lt;/h2&gt;

&lt;p&gt;This contact with other people in the software development industry, people living realities different from mine, gave me an extra boost of motivation. And the fact that everyone treated me with so much kindness and attention made me feel good.&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
