- Home
- Skills
- Testing & Debugging
- Validating in Reality — Prove Fixes Against the Live System
Works with the AI Agents you already use
Validating in Reality — Prove Fixes Against the Live System
Treats your cURL as the acceptance test: runs it before and after a fix, checks the database, and probes negative cases.
Free
Validating in Reality — Prove Fixes Against the Live System
Example session with this skill installed
Bug: marking a task as done doesn't stick. The API returns 200 with "status":"done", but after a refresh the task is back to todo. Fix it and validate it for real, no assumptions.
curl -s -i -X PATCH http://localhost:3000/api/v1/tasks/42 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"done"}'
Stack: Express + Sequelize + Postgres, started with docker compose up -d (services api and db, database tasks_dev, user app). This endpoint only updates status (todo, in_progress, done); title edits go through PUT. There's no frontend for this flow yet. $TOKEN belongs to user 3, who owns task 42. $OTHER_TOKEN is user 5.
Current handler (src/routes/tasks.js):
router.patch('/tasks/:id', auth, async (req, res) => {
const task = await Task.findByPk(req.params.id);
if (!task) return res.status(404).json({ error: 'not_found' });
task.set(req.body);
res.json(task);
});
- Read your context and instructions
- Compiled the validating in reality
Illustrative transcript: this listing has no real server behind it. The commands are exactly what the skill runs; the outputs show the checks it performs against the fictional service described in the request. This is not a real run.
Summary. The bug reproduces. The handler applies the change in memory and returns it, but never calls save(), so nothing reaches Postgres. Two more holes showed up during the negative cases: any field in the body was assigned (including ownerId), and any authenticated user could patch any task. After the fix, the cURL returns 200, the row persists as done, and the negative cases return 400/401/404. UI not exercised (no frontend in this flow).
1. System is running
$ docker compose ps --format '{{.Service}} {{.State}}'
api running
db running
2. BEFORE: acceptance test (live RED)
$ curl -s -i -X PATCH http://localhost:3000/api/v1/tasks/42 -H "Authorization: Bearer <redacted>" -H "Content-Type: application/json" -d '{"status":"done"}'
HTTP/1.1 200 OK
{"id":42,"title":"Ship invoices","status":"done","ownerId":3,"updatedAt":"2026-10-08T14:02:11.000Z"}
$ docker compose exec db psql -U app -d tasks_dev -c "select id, status, owner_id, updated_at from tasks where id = 42;"
id | status | owner_id | updated_at
----+--------+----------+---------------------
42 | todo | 3 | 2026-10-01 09:15:40
The response says done and the row says todo. Bug reproduced.
Negative probe before the fix
$ curl -s -i -X PATCH .../tasks/42 -H "Authorization: Bearer <redacted:OTHER_TOKEN>" -d '{"status":"done","ownerId":5}'
HTTP/1.1 200 OK
{"id":42,...,"status":"done","ownerId":5,...}
User 5 got a 200 on user 3's task, and ownerId was accepted from the body. It isn't persisted today only because save() is missing. Adding save() alone would turn this into a live privilege escalation.
3. Fix
const ALLOWED_STATUS = new Set(['todo', 'in_progress', 'done']);
router.patch('/tasks/:id', auth, async (req, res) => {
const { status, ...rest } = req.body ?? {};
if (Object.keys(rest).length > 0 || !ALLOWED_STATUS.has(status)) {
return res.status(400).json({ error: 'invalid_payload' });
}
const task = await Task.findOne({ where: { id: req.params.id, ownerId: req.user.id } });
if (!task) return res.status(404).json({ error: 'not_found' });
task.status = status;
await task.save();
res.json(task);
});
Regression tests are added alongside, following fixing-bugs: persists status, rejects unknown fields, 404 for a non-owner.
4. AFTER: same cURL, as given
HTTP/1.1 200 OK
{"id":42,"title":"Ship invoices","status":"done","ownerId":3,"updatedAt":"2026-10-08T14:09:52.000Z"}
Compared with BEFORE: status code unchanged (200), body unchanged except updatedAt. The real difference shows in the database.
5. Persisted state
$ docker compose exec db psql -U app -d tasks_dev -c "select id, status, owner_id, updated_at from tasks where id = 42;"
id | status | owner_id | updated_at
----+--------+----------+---------------------
42 | done | 3 | 2026-10-08 14:09:52
6. Negative cases
| Case | Command (abridged) | Expected after fix | Illustrative result |
|---|---|---|---|
| No token | curl -X PATCH .../tasks/42 -d '{"status":"done"}' | 401 | 401 |
| Other user's token | -H "Authorization: Bearer <OTHER_TOKEN>" | 404 | 404 |
| Invalid status | -d '{"status":"archived"}' | 400 | 400 |
| Extra field | -d '{"status":"done","ownerId":5}' | 400 | 400 |
| Nonexistent ID | .../tasks/999999 | 404 | 404 |
DB re-checked after the negative cases: task 42 still done, owner_id = 3.
7. UI
Not exercised: no frontend for this flow (per the request).
Validation status
In a real run this section would read: request + DB + negative cases checked, UI not exercised. Nothing above was executed for this listing.
Next steps
- Run the project's automated suite and
/verifygates. This live check sits on top of them and does not replace them. - Audit other
task.set(req.body)call sites for the same mass-assignment pattern. - Save how this project starts and queries its DB as a learning, so the next validation starts at step 2.
Connects securely to your tools. The creator never sees your data.
About this skill
"The code looks right" is not the same as "it works". An endpoint can return 200 and persist nothing. A fix can pass its unit test and still leave the real request broken. This skill makes the agent prove a bugfix or feature against the running system and paste the output, instead of reasoning from the diff.
When you give it a cURL, an endpoint URL or a repro, that artifact becomes the definition of done. The workflow:
- Confirm the system is running (project run command,
docker compose ps, the port in the cURL). If it cannot be started with the documented command, the agent says so and stops. It never simulates a validation. - Run the acceptance test before the change to prove the bug reproduces (or the feature is missing).
- Implement the fix, with tests as usual.
- Run it again after the change and compare status, body and headers against the before output.
- Check persisted state with the project's DB client or ORM shell.
- Try the negative cases: missing or wrong auth, invalid payload, nonexistent ID.
- Drive the UI end-to-end when the flow has one.
- Report with evidence: each command and its real output, trimmed, with tokens and PII redacted.
Rules it enforces: never claim "validated" for something it did not execute, and label partial validation ("request + DB checked; UI not exercised"). Run your cURL as given rather than swapping in an endpoint that happens to pass. Don't mutate data beyond the operation under test.
It triggers when you paste a cURL or a localhost URL, or say "validate", "test it for real", "check the database" or "no assumptions". A learnings/ folder records how your project starts, seeds, authenticates and connects to its DB, so later runs skip that discovery.
It complements automated tests rather than replacing them. Free and MIT-licensed, part of the claude-skills-czl collection.
Source on GitHub: this skill · full repository
How to use
Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.
Reviews
No reviews yet
Be one of the first to try it. Every listed skill passes our trust checks below.
Security scanned
Passed our 8-point scan before listing
Fresh listing
Recently published to Agensi
Free forever
No account required to browse
Trust & safety
Security scanned
Verified clean 11 days ago
- Free to download with an account