Lead scores that accumulate without triggering any action are a vanity metric. The system faithfully increments a number, the number crosses 100, and nothing happens — no CRM task, no Slack notification, no lifecycle stage change. CWE-691 (Insufficient Control Flow Management) applies: the application collects state (score) but fails to enforce the behavioral transitions that state is supposed to trigger. iso-25010:2011 functional-suitability.functional-completeness rates the scoring system as incomplete when threshold actions are missing. In practice, sales-ready leads sit uncontacted because the handoff mechanism was never wired.
High because scores without threshold actions mean qualified leads are never routed to sales, producing invisible pipeline leakage from a system that appears to be working correctly.
Implement evaluateScoreThresholds with idempotent, crossing-triggered actions. Track the highest threshold already fired on the contact record to prevent repeat notifications.
const THRESHOLDS = [
{ score: 50, action: 'mark_mql', label: 'Marketing Qualified Lead' },
{ score: 100, action: 'mark_sql', label: 'Sales Qualified Lead' },
{ score: 150, action: 'notify_sales', label: 'Hot Lead — Notify Rep' },
]
async function evaluateScoreThresholds(contactId: string, currentScore: number) {
const contact = await db.contact.findUnique({ where: { id: contactId } })
for (const threshold of THRESHOLDS) {
const alreadyFired = (contact.highestTriggeredThreshold ?? 0) >= threshold.score
if (currentScore >= threshold.score && !alreadyFired) {
await fireThresholdAction(contact, threshold.action)
await db.contact.update({
where: { id: contactId },
data: { highestTriggeredThreshold: threshold.score }
})
}
}
}
Define at least two thresholds with distinct actions (e.g., MQL at 50, SQL at 100). Thresholds stored only in comments or documentation with no wired handler do not satisfy this check.
ID: campaign-orchestration-sequencing.lead-scoring.threshold-actions
Severity: high
What to look for: Check whether score thresholds trigger automated actions — specifically creating a CRM task, sending a Slack/email notification to a sales rep, changing the contact's lifecycle stage, or routing the contact to a different sequence. Look for: a evaluateThresholds() or similar function that fires after score updates, threshold configuration (e.g., score > 50 → MQL, score > 100 → SQL, score > 150 → notify sales), and the action implementations (CRM API calls, notifications). Verify that thresholds trigger once (not on every update when score remains above threshold) — they should fire on the crossing event, not repeatedly.
Pass criteria: Score thresholds are defined and trigger specific actions when crossed. Actions fire once on threshold crossing, not repeatedly. Threshold configuration is readable and maintainable. Count all defined thresholds — at least 2 must exist with distinct actions (e.g., MQL at 50, SQL at 100). Report the count even on pass.
Fail criteria: No threshold actions configured. Scores are tracked but never trigger automated routing or notifications. Or: actions fire on every score update when above threshold (not just on crossing).
Skip (N/A) when: The project does not implement lead scoring.
Detail on fail: "Lead scores tracked but no threshold actions defined — scores accumulate with no automated routing or notifications" or "Threshold check fires on every engagement event regardless of whether the threshold was crossed for the first time"
Remediation: Implement idempotent threshold actions that fire only on crossing:
const THRESHOLDS = [
{ score: 50, action: 'mark_mql', label: 'Marketing Qualified Lead' },
{ score: 100, action: 'mark_sql', label: 'Sales Qualified Lead' },
{ score: 150, action: 'notify_sales', label: 'Hot Lead — Notify Rep' },
]
async function evaluateScoreThresholds(contactId: string, currentScore: number) {
const contact = await db.contact.findUnique({ where: { id: contactId } })
for (const threshold of THRESHOLDS) {
if (currentScore >= threshold.score && contact.highestTriggeredThreshold < threshold.score) {
// Only fire if this threshold hasn't been triggered before
await fireThresholdAction(contact, threshold.action)
await db.contact.update({
where: { id: contactId },
data: { highestTriggeredThreshold: threshold.score }
})
}
}
}