The Developer's Review Checklist for AI-Generated Hooks
AI follows the rules it knows. Your job is knowing the rules it missed. Here's the definitive review checklist for AI-generated Logic Bee hooks — 10 hard rules and 12 soft conventions, explained with real examples.
The Premise
Logic Bee's AI validation system checks generated hooks against two categories of rules: hard rules that must never be violated, and soft conventions that should be followed unless there's a documented reason not to. The AI self-validates, but no validation is perfect — and understanding why each rule exists makes you a better reviewer.
The Story
A junior developer merges an AI-generated hook without review. It passes all automated checks. Two weeks later, a production incident reveals that the hook was silently mutating bob.dataPayload directly — causing downstream hooks in the pipeline to receive corrupted data. The mutation wasn't caught because it's a soft convention violation, not a hard rule.
That incident inspired this checklist.
The 10 Hard Rules
These are non-negotiable. If any of these fail, the hook must not be merged.
1. ok Must Be Assigned Before Return
// ❌ Missing ok assignment in success path
try {
data = await someOperation()
// forgot: ok = true
} catch (err) { error = err; ok = false }
2. data Must Be Assigned Before Return
Every successful execution must set data — even if it's just { success: true }.
3. bob.flowUser Must Be Passed to Every FlowQuery
No exceptions. No helper functions that skip it. Every .flowQuery() chain needs .user(bob.flowUser).
4. returnEventResult Must Be the Last Statement
// ❌ Code after returnEventResult
return returnEventResult(bob, { ok, error, data })
console.log('done') // unreachable but indicates confusion
5. Error Variable Must Be Set in Catch Block
// ❌ Missing error assignment
catch (err) {
ok = false
// forgot: error = err
}
6. try/catch Must Wrap All Logic
No business logic outside the try block except variable initialization.
7. FlowQuery Must Include .flowOptions()
Every query needs the collection metadata to resolve correctly.
8. Decorator Metadata Must Match File Path
path: 'finance-bills/calculate-late-fees' must correspond to the actual file location.
9. Write Operations Must Pass bob.dbSession()
For transactional integrity across multi-document updates.
10. Thrown Errors Must Use naoFormatErrorById
Raw throw new Error() produces unstructured error responses.
The 12 Soft Conventions
These improve code quality and consistency. Violations should be fixed unless there's a strong reason to deviate.
1. eventOptions First
Declare the eventOptions object as the first statement inside the try block.
try {
const eventOptions = {
billNaoQueryOptions: { docName: 'bill', cfpPath: 'finance/bills' }
}
// ... rest of logic
}
2. Arrow Comments for Structure
Use // -->Get:, // -->Set:, // -->Validate:, // -->Iterate:, // -->Update: prefix comments.
3. naoUtils.mathChain() for Math
Never use raw arithmetic for financial calculations. Floating point errors are real.
// ❌ Raw arithmetic
const total = quantity * unitPrice
// ✅ Math chain
const total = naoUtils.mathChain(quantity).multiply(unitPrice).done()
4. naoDateTime() for Dates
Never use new Date() or Date.now(). The Luxon-based wrapper handles timezones correctly.
5. Don't Mutate bob.dataPayload
Read from it. Don't write to it. Use bob.replaceDataPayload() if you need to pass modified data downstream.
6. One Responsibility Per Hook
If the AI generates a hook that both validates and processes, consider splitting it into two hooks.
7. Guard Clauses Before Logic
Check for nulls, empty arrays, and invalid states at the top of the try block.
8. Descriptive Error Reasons
// ❌ Vague
throw naoFormatErrorById('bad_request', { reason: 'Invalid' })
// ✅ Descriptive
throw naoFormatErrorById('bad_request', {
reason: `Bill ${bill.docId} has zero balance and cannot accrue late fees`
})
9. TypeScript Interface References
Pass the interface name to .getMany() and .getOne() for type safety.
10. Consistent Variable Naming
Use fc for flow collections, doc for single documents, docs for arrays.
11. No console.log in Production Code
Use the structured logging utilities from @logic-bee/utils.
12. End With ok = true; data = result
The last two lines of the try block should always be the success assignment.
The Review Shortcut
When reviewing AI-generated hooks, scan in this order:
- Scroll to the bottom — is
returnEventResultthe last statement? - Search for
.flowQuery()— does every chain have.user(bob.flowUser)? - Search for
.updateOne()/.updateMany()— does every write passbob.dbSession()? - Read the catch block — are both
error = errandok = falsepresent? - Read the first line of the try block — is
eventOptionsdeclared first?
If all five pass, you're likely looking at a clean hook.
The Takeaway
Print this. Pin it next to your monitor. Use it every time you review AI output:
Hard rules = merge blockers. Soft conventions = code quality. Both = production readiness.
