Flows — how this works
In the app: /flows
How it works
A rule is trigger + conditions + actions ("when signal.received AND intent=high, enrich → score → route → enroll"), persisted as a FlowRule row. Rules are ONLY created from a template (flowTemplates.ts) — never a free-form builder — and validateRule() (unchanged, flowTriggers.ts) rejects a malformed rule before it's ever saved. Every trigger has a live caller: a NEWLY-detected signal fires signal.received (signalDetect.ts), a finished enrichment fires lead.enriched (enrichFullCallback.ts), an inbound reply fires reply.received (replyIngest.ts), and a first-time booking fires meeting.booked (appointments.ts) — each running the enabled rule set through the same runner with the REAL production handlers (createFlowHandlers: enrich/score/route/enroll/notify, each a thin delegate to its existing engine). No rule action ever contacts a prospect directly — enroll only writes an enrollment row; the cadence walker re-guards every step it sends.
Data source
src/lib/flow/flowRuleRepo.ts (persistence) + src/lib/flow/{flowRunner,flowTriggers,flowTemplates,flowEvents,flowHandlers}.ts (the engine + the trigger seam + the production handlers) + the four trigger sites above.
Troubleshooting
A rule you enabled never seems to fire? Check its trigger matches the event you're testing (signal.received fires on a newly-detected signal; lead.enriched when an enrichment callback lands; reply.received when an inbound reply is ingested; meeting.booked on a first-time booking — never a reschedule), and check its conditions aren't excluding every real event's facts. "Disable"/"Enable" does nothing? setEnabled() no-ops (never throws) for an unknown rule id.
Who can see this: admin