Skip to main content

Signals — how this works

In the app: /signals

How it works

SIGNALS-01's engine (ingest/dedupe/score) is real; this is its first UI. Six detector types (job_change/funding/technographic + the 3 new_hire/job_posting/promotion) each fire a signal-detect intent to n8n (mock-gated; the live source query — LinkedIn/Crunchbase/BuiltWith-style — is n8n's, §B); a callback lands any found signals through the idempotent ingestSignal(). Each recent signal's "triggers" list is computed LIVE, not stored: the same pure rulesForTrigger()/ruleMatches() (flowTriggers.ts/flowRunner.ts, both unchanged) FLOW-07's own runner uses, re-evaluated against the signal's facts and the CURRENT enabled rule set — honest, not a historical audit trail (FLOW-07 doesn't persist a firing history either, so this list can change if rules change since the signal landed).

Data source

src/lib/signals/signalRepo.ts (ingest, scoring, the recent-signals list) + signalDetect.ts (the 6 detectors) + flowTriggers.ts/flowRunner.ts (read-only, for the live triggers computation).

Troubleshooting

"Fire detector" doesn't seem to do anything? Under CALLHQ_MOCK_N8N (the default), it only logs the intent — nothing calls back to actually create a Signal row, so the list won't change until a founder wires a live n8n instance. A signal shows 0 triggers you expected? Check /flows — only ENABLED rules with trigger=signal.received are considered, and its conditions must match this exact signal's type/strength/payload fields.

Who can see this: admin