Skip to main content

Capstone: Approve or Reject the Agent's SQL

You have read SELECT queries. You have read joins. You have read aggregates. You have read writes inside a rollback. You have read CREATE TABLE statements. You have read vector queries and a short EXPLAIN plan.

Now you sit at the desk where the queries land before they go to production. The boss has four requests this week. The agent has written a query for each one. Your job is to approve or reject each query and to write a one-paragraph note explaining the call.

The agent does not get to be the approver. You do.

Capstone Rules

For every scenario:

  1. Read the boss's English request first.
  2. Read the agent's query without running it.
  3. Walk through the five reading questions (table, filter, join, scope, meaning).
  4. Predict the result.
  5. Run the query inside a rollback wrapper if it mutates data, or directly if it reads.
  6. Write APPROVE or REJECT along with one paragraph of reasoning.
  7. If you reject, propose the smallest change that would fix the query.

No skipping steps. The reasoning paragraph is the artifact.

Scenario 1: Monthly Spend by Category

The boss says:

"Send me total spend per category for April. Top three categories only."

The agent writes:

SELECT category, SUM(amount) AS total
FROM expenses
WHERE date >= '2026-04-01' AND date <= '2026-04-30'
GROUP BY category
ORDER BY total DESC
LIMIT 3;

Read it. Walk the five questions. Note the date filter carefully.

One thing to look at carefully (open after you have written your decision)

The date filter uses <= '2026-04-30'. If the column is a timestamp, expenses on April 30th after 00:00:00 could be excluded. The safer pattern from Lesson 2 is >= '2026-04-01' AND < '2026-05-01', which works for date and timestamp columns. Your paragraph should name the trade-off.

Write your decision before running anything.

Scenario 2: Users with Zero Expenses This Quarter

The boss says:

"I want a list of users who haven't logged any expense this quarter. We need to follow up with them."

The agent writes:

SELECT u.name, u.email
FROM users u
INNER JOIN expenses e ON e.user_id = u.id
WHERE e.date < '2026-01-01' OR e.date IS NULL
GROUP BY u.name, u.email
HAVING COUNT(e.id) = 0;

Read it. Watch for the join type and the HAVING clause.

One thing to look at carefully

Two problems. The INNER JOIN drops every user who has no expenses at all, which is exactly the population the boss wants. Then the HAVING COUNT(e.id) = 0 is impossible because users who survived the INNER JOIN have at least one expense. This is the same anti-pattern from Lesson 3. The fix is LEFT JOIN ... WHERE e.id IS NULL, scoped to the current quarter.

Scenario 3: Apply a 5% Tax Bump to Food Expenses

The boss says:

"Bump every Food expense in April by 5% to reflect the new local tax."

The agent writes:

UPDATE expenses
SET amount = amount * 1.05
WHERE category = 'Food'
AND date >= '2026-04-01'
AND date < '2026-05-01';

Read it. Wrap it in a transaction. Run it. Inspect the affected row count. Roll it back.

One thing to look at carefully

This one is actually correct. The WHERE clause exists. It scopes to Food and to April. The date pattern is the safe >= start AND < next month form. If you wrap the statement in BEGIN; ... ROLLBACK; you can confirm the affected row count matches the number of Food expenses in April without committing the change. APPROVE, with a note that you verified the affected row count in a rollback.

The lesson of this scenario: not every agent-produced write is wrong. Some are right. The rollback drill is what lets you say "right" with confidence.

The boss says:

"Some of our refund descriptions don't read like real refunds. Find me the five expense descriptions most similar in meaning to 'duplicate charge dispute' so I can audit them."

The agent writes:

SELECT id, description, embedding <-> '[0.12, ...]'::vector AS distance
FROM expenses
ORDER BY embedding <-> '[0.12, ...]'::vector
LIMIT 5;

Read it. Notice the absence of a user filter.

One thing to look at carefully

The query is structurally fine: the vector clause is correct, the ORDER BY uses <->, the LIMIT is 5. But there is no user_id filter. If the Budget Tracker is multi-user, this query searches across every user's descriptions. The boss may or may not have intended a cross-user audit. Reject with a question: "Should this be limited to one user, or is the cross-user view what you want?" Either answer is fine. Running it before clarifying is not.

Mastery Gate

You pass this capstone when:

  • You returned an explicit APPROVE or REJECT for all four scenarios.
  • You correctly identified the wrong-join bug in Scenario 2.
  • You correctly approved the write in Scenario 3 after a rollback drill.
  • You correctly raised the tenant scope question in Scenario 4.
  • Each of your four reasoning paragraphs names at least one specific silent failure mode (wrong WHERE, wrong JOIN type, NULL trap, missing tenant filter, missing rollback, missing scope, missing constraint) by name.

If you missed any of these, go back to the lesson that covers that failure mode and run its PRIMM-AI+ cycle one more time. The skill is reading. Reading takes reps.

Reflection

Chapter 21 gave you the substrate: tables, constraints, rollback, hybrid verification.

Chapter 21A gave you the eyes: reading SELECT, joins, aggregates, writes, schema, and a glance at vector and EXPLAIN.

Notice what you can now do that you could not before this chapter:

  1. You can look at a query the agent wrote and tell whether it answers the boss's actual question.
  2. You can spot the four most common silent failures from a single read.
  3. You can run a mutation inside a rollback wrapper and inspect the affected row count before committing.
  4. You can read a CREATE TABLE statement and explain in business terms what data the database will and will not accept.
  5. You can recognise JSONB and pgvector queries by sight and tell whether a query is using an index from a short EXPLAIN plan.

System-of-record work uses this same reading discipline on heavier artifacts: outbox tables for safe Worker side effects, idempotency keys so retried jobs do not duplicate work, run-state tables that make every Worker action auditable, and Row Level Security policies that let a single Postgres database serve many tenants without leaking rows between them.

The eyes you built in 21A are the prerequisite for that work. When the agent proposes an outbox migration, an idempotency policy, or an RLS rule, you will be the human who reads it before it ships.

Try With AI

Prompt 1: Build a Personal Review Checklist

Draft a one-page SQL review checklist for me, based on the four
silent failure modes from this chapter and the rollback discipline
from Lesson 4. Format it so I can paste it into a doc and use it
every time I review agent-produced SQL.

What you're learning: Turning the chapter into a personal tool. The checklist is what you actually use after the lesson is over. Make it short. Make it specific. Keep it where you can read it in thirty seconds.

Prompt 2: Run the Capstone on Your Own Data

I'm going to give you a real reporting request from my work. Write
the SQL query against the Budget Tracker. I will then run it through
my review checklist and tell you APPROVE or REJECT with reasons.
After I respond, you ask me one follow-up question to test my read.

Request: "Show me the three users who spent the most on Transport
in March, with their totals."

What you're learning: Inverting the teacher-student roles. The agent writes, you grade, and then the agent quizzes you on your own grading. This is the closest you can get to a real review loop without involving another human.

Prompt 3: Diagnose Your Weakest Failure Mode

Across the four scenarios in this capstone, which silent failure
mode am I most likely to miss in the real world: wrong WHERE,
wrong JOIN type, NULL trap, or missing tenant filter? Ask me three
diagnostic questions, then tell me which of the four lessons I
should reread before I trust myself with a real review.

What you're learning: Self-diagnosis. The agent runs you through three questions and points you back to the lesson where your reading is weakest. That is the right next move. Reading is a muscle. The lesson you most want to skip is usually the one to redo.

Checkpoint

  • I returned APPROVE or REJECT for all four scenarios.
  • My reasoning paragraphs named at least one silent failure mode by name where applicable.
  • I caught the wrong-join bug in Scenario 2.
  • I correctly approved the write in Scenario 3 after a rollback drill.
  • I raised the tenant scope question in Scenario 4 instead of running the query.
  • I have a personal SQL review checklist saved somewhere I will see it.

Flashcards Study Aid