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.