php -l includes/class-order-export.phpThat’s the first command I run on PHP that an AI tool just wrote. It parses the file, exits 0 if the syntax is fine, and takes under a second, so it feels like verification. It isn’t. A green exit code says nothing about which table the code reads from, which WooCommerce version it assumes, or what happens to a client’s data when it runs. This is the first minute of reviewing AI generated code, and it’s the minute when the judgment either happens or gets skipped.
The argument behind this post comes from Rashi Desai, who writes on Towards Data Science that the people getting the most from AI aren’t the best prompters but the ones who keep checking whether they understand the output and agree with it, or whether they’re coasting. She calls that skill metacognitive regulation. I buy it, with one addition for those of us shipping plugins: thinking about your thinking doesn’t survive client deadlines unless you turn it into steps you can run.
The check that passes while you coast
My usual example is an order export. The model writes a tidy class, uses $wpdb->prepare so it looks security conscious, and selects order rows from $wpdb->posts with a join on $wpdb->postmeta. The syntax check passes. It even runs correctly on a dev copy where order storage still lives in the posts table. Then the same code lands on a store with High Performance Order Storage enabled, where WooCommerce keeps orders in dedicated tables, and the export returns an empty file. The order storage docs are blunt about this: direct SQL against the post tables breaks the moment HPOS is on.
Nothing in that diff was badly written. The failure was an assumption the model never stated and nobody asked about, which is close to what Desai describes as accepting an answer because it sounded convincing. Escaped SQL against the wrong tables is still wrong, and it’s a specific kind of logical debt: the code is clean, but the model of the system underneath it is off.
What I check when reviewing AI generated code
The order matters more than the items. Once you’ve read 300 lines, you start defending them, so the checking has to happen before the answer arrives. That’s also why reviewing agent output is now the slow part of my week, and writing code is the fast part.
- Write down two things the code must survive. For an export: refunds have to be included, and order data has to come through wc_get_orders instead of raw SQL. If I can’t name two, I don’t have a spec yet.
- Ask for the assumptions along with the code. A short addition to the prompt does most of the work:
Rewrite this to use wc_get_orders and target current WooCommerce.
After the code, list every assumption you made
about where order data lives.The assumptions list is the part I can argue with line by line. The code itself I can only skim.
- Check APIs against the docs, not against memory: the wpdb::prepare() rules, the %i placeholder for identifiers that arrived in WordPress 6.2, hooks that moved when order storage changed. The model’s training data is not a changelog. The wpdb reference is a two-minute read and it has caught real mistakes for me.
- Run it on ugly data: a copy of a store with variations, refunded orders, and HPOS enabled. Clean test installs hide the exact cases from step one.
When to skip most of this
For a throwaway wp eval on my own site, php -l and ship is fine, and turning that into an hour of ritual review is its own judgment failure. The steps above earn their keep where the blast radius is real: anything that writes to the database, touches order storage, or handles personal data. I don’t know exactly where that line sits, but it’s somewhere before the first query that updates order rows. Test those first, before code style or performance.
If you have a plugin or a store where AI-written code has been piling up faster than anyone can read it, that audit is the kind of work I take on. Send the repo and I’ll tell you what I find.