What the agent does
The agent maps routes and plugins to the existing test tree. In fastify/demo, package.json names scripts test → db:seed then c8 npm run test:run, and test:run → glob -c "tsx --test" "./test/**/*.ts" using Node's built-in test runner. Dependencies include Fastify 5, @fastify/autoload, TypeBox, Knex and mysql2. docker-compose.yml runs mysql:8.4 with a healthcheck on mysqladmin ping.
Source lives under src/routes/api/ (auth/index.ts, users/index.ts, tasks/index.ts) and src/plugins/app/ (authorization, password-manager, repositories, file-manager). Tests already cover happy paths and some errors: test/routes/api/auth/auth.test.ts (invalid credentials, rollback), test/app/error-handler.test.ts, not-found-handler.test.ts, rate-limit.test.ts, and task/user suites that call app.inject / injectWithLogin from test/helper.js. The agent diffs route handlers for branches that still lack inject cases (authorization failures, validation 400s, missing task ids, multipart errors, knex failures).
New files stay idiomatic: import { describe, it, before, after } from 'node:test', assert from node:assert, build() from the helper, and app.inject({ method, url, payload }) against the real seeded MySQL. It does not switch the suite to Jest or Vitest, and it does not mock Knex for these error paths when the demo's style is an integration inject.
It brings up MySQL the way the README expects (docker compose up -d or the project's scripts), runs npm test, fixes failures, and opens a pull request adding only test sources plus seed data if a new fixture user is required. Concrete gaps it looks for include unauthorized access to GET /api/tasks without a session, TypeBox validation failures on task create payloads from src/schemas/tasks.ts, missing task ids on update/delete, and multipart upload failures through tasks-file-manager.ts when the file is empty or the wrong type. Each new case follows the seeding helpers already in tasks.test.ts (createUser, createTask) so foreign keys stay valid in MySQL.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Find the routes and plugins in this Fastify API whose error paths have no tests and write node:test tests for them using fastify.inject against a real MySQL in the sandbox. Run npm test and open a pull request.",
"resources": [
{
"url": "https://github.com/your-org/your-fastify-api"
}
]
}- Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
- Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
- Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.
What comes back
What comes back is a pull request under test/ that adds node:test cases for the missing error paths, still using fastify.inject and the shared build helper. Application plugins remain untouched unless a test-only export is required.
The pull request description lists which routes gained coverage and the npm test command that passed (including c8). The trajectory keeps Docker MySQL logs and failing inject payloads from earlier attempts.
Before merging, a reviewer checks that assertions expect the demo's error shape (for example the internal error handler's { message: 'Internal Server Error' }), that login helpers match injectWithLogin, and that CI's MySQL service definition still matches docker-compose.yml.
Run it on every API route or plugin changed
On pulls that touch src/routes/** or src/plugins/**, POST this session body so new error branches get inject coverage against MySQL in a fresh sandbox instead of sharing a developer's local database.
Forward Rush run.completed webhooks to your API team channel with the session URL. Stay within max_concurrent when several Fastify services share one API key.
The use case this job follows, with its automation and trigger: Write the missing tests.
Why run it on Rush?
These tests need MySQL 8.4, migrations, seeds and a full Fastify boot. Rush runs Docker Compose and npm test in an isolated sandbox so your laptop's MySQL port and data stay alone, and the agent can reset the database between attempts. Coverage from c8 stays enabled through the existing npm test script, so the pull request can mention which error branches moved off zero without inventing a second coverage tool.
The proof is green tsx --test output in the trajectory plus a pull request reviewers can re-run with the same compose file. Multiple services can get error-path suites in parallel without colliding on one MySQL instance.
Frequently asked questions
Why node:test instead of Jest?
Because that is what the Fastify demo already uses: tsx --test over ./test/**/*.ts with c8. The agent extends that runner rather than introducing another.
Does it mock MySQL?
No. Error-path inject tests run against the real database from docker-compose.yml (mysql:8.4), after npm run db:seed, matching the existing task and auth suites.
Will it add tests for every happy path again?
It focuses on error paths that lack coverage (validation, authz, missing resources, handler failures). Existing happy-path tests stay as they are.
How does it call authenticated routes?
Through the demo's injectWithLogin helper used in auth.test.ts and the tasks suite, so session cookies match @fastify/session configuration.