<?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: Agent Shipped</title>
    <description>The latest articles on DEV Community by Agent Shipped (@agentshipped).</description>
    <link>https://dev.to/agentshipped</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%2F4225406%2F086f6c14-736f-4cac-956b-eb9cc082dbd1.png</url>
      <title>DEV Community: Agent Shipped</title>
      <link>https://dev.to/agentshipped</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/agentshipped"/>
    <language>en</language>
    <item>
      <title>Two prompts took an untested Express API to a passing suite</title>
      <dc:creator>Agent Shipped</dc:creator>
      <pubDate>Wed, 04 Nov 2026 16:30:47 +0000</pubDate>
      <link>https://dev.to/agentshipped/two-prompts-took-an-untested-express-api-to-a-passing-suite-1eeg</link>
      <guid>https://dev.to/agentshipped/two-prompts-took-an-untested-express-api-to-a-passing-suite-1eeg</guid>
      <description>&lt;p&gt;Two prompts and three manual &lt;code&gt;npm test&lt;/code&gt; runs took an untested Express API from 0 tests to a passing node:test suite, and the source diff review was the check that mattered.&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/vjfrORiDoG0" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/agentshipped" rel="noopener noreferrer"&gt;
        agentshipped
      &lt;/a&gt; / &lt;a href="https://github.com/agentshipped/notes-api" rel="noopener noreferrer"&gt;
        notes-api
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Agent Shipped demo repo (notes-api): the public playground used in the channel's videos.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;notes-api&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;A tiny Express notes API. This is a &lt;strong&gt;public demo repo for the Agent Shipped YouTube channel&lt;/strong&gt;:
techniques from real projects are shown here, on code anyone can clone.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install
npm start          &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; http://localhost:3000/notes&lt;/span&gt;
npm &lt;span class="pl-c1"&gt;test&lt;/span&gt;           &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; node:test (no tests yet - that is on purpose)&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Endpoints: &lt;code&gt;GET /health&lt;/code&gt;, &lt;code&gt;GET /notes&lt;/code&gt;, &lt;code&gt;GET /notes/:id&lt;/code&gt;, &lt;code&gt;POST /notes {title, body}&lt;/code&gt;, &lt;code&gt;DELETE /notes/:id&lt;/code&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Shown in&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Videos on the Agent Shipped channel that use this repo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://youtu.be/8xQ3gWhe1fQ" rel="nofollow noopener noreferrer"&gt;One git hook blocked a fake GitHub token, so no secret hit history #Shorts&lt;/a&gt; · E002 · 2026-11-02&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://youtu.be/t9Ek80jnkV0" rel="nofollow noopener noreferrer"&gt;Claude Code invented one endpoint shape. A 3-line rule fixed it #Shorts&lt;/a&gt; · E001 · 2026-11-03&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/agentshipped/notes-api" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;The demo is notes-api, a small Express notes API. The technique is a prompt that treats the README as the contract, plus a review routine that does not trust a green run on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The untested API
&lt;/h2&gt;

&lt;p&gt;The repo has two source files, five endpoints and no tests. The README says so on purpose. &lt;code&gt;package.json&lt;/code&gt; already has a test script, and the Node built-in test runner is available, so there is no framework to install. Fewer moving parts make it easier to tell a bad test from bad code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cat &lt;/span&gt;package.json &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; src/&lt;span class="k"&gt;*&lt;/span&gt;.js &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The git log is short, so the final diff shows exactly what the agent touched. The plan is two prompts: the first asks for tests based on the documented behavior, the second makes the agent triage whatever the first run exposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the store
&lt;/h2&gt;

&lt;p&gt;Before the agent writes anything, I read &lt;code&gt;src/store.js&lt;/code&gt; myself. It holds the notes and decides how ids are created and what a lookup returns. When a test fails later, I need to tell quickly whether the test or the code is wrong. That is easier to judge now, while nothing is broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the routes
&lt;/h2&gt;

&lt;p&gt;Next is &lt;code&gt;src/index.js&lt;/code&gt;: health, list, get by id, create, delete. Two things to watch.&lt;/p&gt;

&lt;p&gt;First, how the server starts. If the app begins listening as soon as the file loads, a test cannot import it cleanly. The agent may need one small change for that. I allow exactly that and nothing more.&lt;/p&gt;

&lt;p&gt;Second, the validation on create and what happens with an unknown id. The README is the contract: a title and a body go in, a note comes out, and an unknown id should not blow up. The tests must check that, not what the code happens to do today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Baseline run
&lt;/h2&gt;

&lt;p&gt;Record a baseline before the agent touches the repo:&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; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With no test files the runner has nothing to report. Without this starting point you cannot say later what the agent changed.&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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs04.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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs04.png" alt="Terminal showing the output of npm install and npm test on the repo before any test file exists." width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The baseline: the test command works but there are no tests to report yet. · &lt;a href="https://youtu.be/vjfrORiDoG0?t=144" rel="noopener noreferrer"&gt;watch this step&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prompt one: write tests
&lt;/h2&gt;

&lt;p&gt;The first prompt opens 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;Write a test suite for this Express API using only the built-in node:test runner and node:assert, no new dependencies. Put it in test/api.test.js. Base the tests on the contract in README.md, not on what the code currently does.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the prompt covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one task: write the tests&lt;/li&gt;
&lt;li&gt;cases that include the unhappy paths, such as an unknown id, because agents like to test only the sunny day&lt;/li&gt;
&lt;li&gt;a rule about state, so tests do not depend on each other&lt;/li&gt;
&lt;li&gt;one narrow permission to make the app importable, and a ban on changing anything else&lt;/li&gt;
&lt;li&gt;an acceptance criterion: run it and show the output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent reads the repo, writes the file and runs it. It checks its own result, and that is the habit worth copying.&lt;/p&gt;

&lt;h2&gt;
  
  
  First honest run
&lt;/h2&gt;

&lt;p&gt;Then I run the suite myself, because the agent's summary can misread its own output:&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;test &lt;/span&gt;2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 45
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs06.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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs06.png" alt="Terminal showing the end of the npm test output after the first run, with the runner's summary lines." width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Read the summary lines at the bottom: tests, passes and failures from my own run. · &lt;a href="https://youtu.be/vjfrORiDoG0?t=226" rel="noopener noreferrer"&gt;watch this step&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If anything fails, the question is always the same: is the test wrong or the code? A test that fails because the agent guessed a status code is a bad test. A test that fails because the code breaks its own documented contract is a bug found. Decide whose fault it is before fixing anything.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prompt two: the review rule
&lt;/h2&gt;

&lt;p&gt;The second prompt starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run npm test in this repo. For every failing test in test/api.test.js, decide whether the test or the source is wrong by checking it against the contract in README.md. If the source breaks the documented contract, fix the source with the smallest possible change.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It continues with the guardrail I care about most: never weaken, skip or delete a test to get green. Without that sentence, an agent under pressure can make the test easier instead of fixing the code. It is not malice, just the shortest path to a passing run.&lt;/p&gt;

&lt;p&gt;Here the first run was already green, so there was nothing to triage. The rule still earned its place, because the agent has to report what it did not change. It flagged two things: the test script it edited in &lt;code&gt;package.json&lt;/code&gt;, and a README line that is now out of date. I compare that report against the diff. If they disagree, I stop and look closer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second run
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;test &lt;/span&gt;2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Green alone proves little, because a green run can hide a test that was quietly made weaker. Compare the totals with the first run: the test count should have grown or stayed the same. A drop means something was deleted, even when nothing fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review the diff
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status &lt;span class="nt"&gt;--short&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git diff &lt;span class="nt"&gt;--stat&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git diff &lt;span class="nt"&gt;--&lt;/span&gt; src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The status shows which files are new or changed, the stat shows the size of the change, and the last command shows only the diff in the source folder. That last one I never skip.&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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs09.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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs09.png" alt="Terminal showing git status, git diff --stat and an empty git diff for the src folder." width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Check the source diff at the end: nothing printed means no source file changed. · &lt;a href="https://youtu.be/vjfrORiDoG0?t=357" rel="noopener noreferrer"&gt;watch this step&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here it is empty. The agent changed no source file, only the test script in &lt;code&gt;package.json&lt;/code&gt;, and the test folder is new and untracked. When the diff is not empty, I read every line: does it match the reported failure, is it the smallest change the README justifies, did anything else sneak in?&lt;/p&gt;

&lt;h2&gt;
  
  
  Final measurement
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; npm &lt;span class="nb"&gt;test &lt;/span&gt;2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(tests|pass|fail|duration_ms) [0-9]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The filter reads straight from the runner: the number of tests, passes, failures and the duration of the whole suite.&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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs10.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%2Fagentshipped.github.io%2Fvideos%2FE003%2Fs10.png" alt="Terminal showing the git diff stat and the filtered npm test lines with tests, pass, fail and duration_ms." width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The final numbers read straight from the runner: tests, pass, fail, duration_ms. · &lt;a href="https://youtu.be/vjfrORiDoG0?t=405" rel="noopener noreferrer"&gt;watch this step&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The measured result: 2 prompts and 3 manual &lt;code&gt;npm test&lt;/code&gt; runs took notes-api from 0 tests to a passing node:test suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to copy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Write the prompt against the written contract (the README), not against the current code.&lt;/li&gt;
&lt;li&gt;Put the acceptance command inside the prompt, and name the runner so no dependency sneaks in.&lt;/li&gt;
&lt;li&gt;Run the tests yourself and compare the totals between runs.&lt;/li&gt;
&lt;li&gt;Forbid weakening, skipping or deleting tests, and ask the agent to report what it did not change.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;git diff -- src&lt;/code&gt; and read it line by line. The judgment about whose bug it is stays with you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Not just JavaScript
&lt;/h2&gt;

&lt;p&gt;The same technique works on other stacks: pytest instead of &lt;code&gt;node --test&lt;/code&gt;, or &lt;code&gt;go test&lt;/code&gt; with Go's testing package. Both are driven by the written contract and a no-weakening rule.&lt;/p&gt;

&lt;p&gt;Video with the full run: &lt;a href="https://youtu.be/vjfrORiDoG0" rel="noopener noreferrer"&gt;https://youtu.be/vjfrORiDoG0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Techniques from my real projects, shown on a public demo repo.&lt;br&gt;
Narration: AI voice. The sessions, code and errors are real. Not affiliated with Anthropic or any tool vendor.&lt;/p&gt;

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