Two prompts and three manual npm test 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.

GitHub logo agentshipped / notes-api

Agent Shipped demo repo (notes-api): the public playground used in the channel's videos.

notes-api

A tiny Express notes API. This is a public demo repo for the Agent Shipped YouTube channel: techniques from real projects are shown here, on code anyone can clone.

npm install npm start # http://localhost:3000/notes npm test # node:test (no tests yet - that is on purpose)

Endpoints: GET /health, GET /notes, GET /notes/:id, POST /notes {title, body}, DELETE /notes/:id.

Shown in

Videos on the Agent Shipped channel that use this repo:




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.

The untested API

The repo has two source files, five endpoints and no tests. The README says so on purpose. package.json 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.

ls && cat package.json && wc -l src/*.js && git log --oneline | head -n 5 

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.

Read the store

Before the agent writes anything, I read src/store.js 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.

Read the routes

Next is src/index.js: health, list, get by id, create, delete. Two things to watch.

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.

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.

Baseline run

Record a baseline before the agent touches the repo:

npm install && npm test 

With no test files the runner has nothing to report. Without this starting point you cannot say later what the agent changed.

Terminal showing the output of npm install and npm test on the repo before any test file exists.
The baseline: the test command works but there are no tests to report yet. · watch this step

Prompt one: write tests

The first prompt opens like this:

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. 

The rest of the prompt covers:

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

The agent reads the repo, writes the file and runs it. It checks its own result, and that is the habit worth copying.

First honest run

Then I run the suite myself, because the agent's summary can misread its own output:

npm test 2>&1 | tail -n 45 

Terminal showing the end of the npm test output after the first run, with the runner's summary lines.
Read the summary lines at the bottom: tests, passes and failures from my own run. · watch this step

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.

Prompt two: the review rule

The second prompt starts:

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. 

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.

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 package.json, 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.

Second run

npm test 2>&1 | tail -n 30 

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.

Review the diff

git status --short && git diff --stat && git diff -- src 

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.

Terminal showing git status, git diff --stat and an empty git diff for the src folder.
Check the source diff at the end: nothing printed means no source file changed. · watch this step

Here it is empty. The agent changed no source file, only the test script in package.json, 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?

Final measurement

git diff --stat; npm test 2>&1 | grep -E "(tests|pass|fail|duration_ms) [0-9]" 

The filter reads straight from the runner: the number of tests, passes, failures and the duration of the whole suite.

Terminal showing the git diff stat and the filtered npm test lines with tests, pass, fail and duration_ms.
The final numbers read straight from the runner: tests, pass, fail, duration_ms. · watch this step

The measured result: 2 prompts and 3 manual npm test runs took notes-api from 0 tests to a passing node:test suite.

What to copy

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

Not just JavaScript

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

Video with the full run: https://youtu.be/vjfrORiDoG0

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