Skip to content

Triage rules

Thresholds come from config/triage.yaml. Rule conditions and reason strings come from apps/api/src/services/triage.ts. There is no parallel catalogue of rules.

# Priority is an additive weighted sum of flag severities.
# Closed deals (step 7) are excluded from pipeline totals and from triage.
#
# Formula: priority = sum(weight[severity] for each uncleared, unexpired flag)
# + judgement_bonus if any judgement flag is present
# Higher number ranks higher on the needs-attention list.
reference_date: "2026-08-14"
quarter_end: "2026-09-30"
stale_days_by_step:
1: 90
2: 60
3: 45
4: 30
5: 21
6: 14
# MEDDIC evidence added within this many days either side of a step/P2 increase.
# 21 covers the Northgate P2 jump (17 days before reference_date) so the
# unsupported_jump scenario still fires while the threshold remains config.
unsupported_jump_days: 21
close_date:
# "more than K times" — two or more later-moves fire the flag
max_slips: 1
max_days_past_original: 45
ratio_bands:
healthy_min: 15
healthy_max: 60
# RAG is derived ONLY from MEDDIC completeness vs required_at_step in gates.yaml.
# Analyst output is not an input.
rag:
green_max_missing: 0
amber_max_missing: 2
priority_weights:
high: 10
medium: 5
low: 1
judgement_bonus: 3
judgement_ttl_days: 14
# P2 = 90 requires at least this many MEDDIC criteria evidenced.
high_p2_min_evidenced: 5
suppression:
min_sample: 5
wrong_ratio: 0.6
graduation:
min_sample: 5
right_ratio: 0.8

The following excerpts are the reason strings the engine actually emits.

No activity for ${ageDays} days. At step ${deal.step} the tolerance is ${staleDays} days (triage.yaml stale_days_by_step).
Required at step ${deal.step} but neither evidenced nor marked unknown: ${missing.join(", ")}.
This rep's open-pipeline ratio sits outside the healthy band ${input.triage.ratioBands.healthyMin}–${input.triage.ratioBands.healthyMax}% (triage.yaml ratio_bands).
Close date has moved later ${laterMoves.length} time(s) (threshold: more than ${input.triage.closeDate.maxSlips}) and is ${daysPastOriginal} days past the original close date (threshold: ${input.triage.closeDate.maxDaysPastOriginal} days).
Close date ${deal.closeDate} is in the past and the deal is still open at step ${deal.step}.
Step or P2 increased without MEDDIC evidence for ${missing.join(", ")} within ${windowDays} days either side of the change (triage.yaml unsupported_jump_days).