Skip to main content

The Developer's Review Checklist for AI-Generated Hooks

· 4 min read
Gabriel Paunescu
Founder CTO Neologic

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:

  1. Scroll to the bottom — is returnEventResult the last statement?
  2. Search for .flowQuery() — does every chain have .user(bob.flowUser)?
  3. Search for .updateOne() / .updateMany() — does every write pass bob.dbSession()?
  4. Read the catch block — are both error = err and ok = false present?
  5. Read the first line of the try block — is eventOptions declared 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.