Pain Streak Algorithm
"The most dangerous pattern is the invisible grind."
The Pain Streak is HEAT's burnout early warning system. It detects when team members work on the same difficult task for consecutive days — the pattern that precedes silent failure and resignation.
The Problem: Silent Grinding
Traditional View (Timesheets)
Alice's Timesheet (Week of Nov 25):
Monday: 8 hours (Payment Feature)
Tuesday: 8 hours (Payment Feature)
Wednesday: 8 hours (Payment Feature)
Thursday: 8 hours (Payment Feature)
Friday: 8 hours (Payment Feature)
Manager's interpretation: "Great progress on Payment Feature!"Reality (What Actually Happened)
Alice's Reality:
Monday: Discovered SQL deadlock bug (x7 intensity, frustrated)
Tuesday: Still debugging deadlock (x8 intensity, stressed)
Wednesday: Tried 3 approaches, all failed (x9 intensity, exhausted)
Thursday: Senior dev helped, found root cause (x10 intensity, relieved)
Friday: Implemented fix (x3 intensity, finally moving forward)
Outcome: Alice almost quit Wednesday night.
Manager had no idea until Friday 1:1.The Gap: Timesheets show "consistent progress." Reality shows a crisis that almost caused turnover.
How Pain Streak Detection Works
Algorithm Logic
function detectPainStreak(workItem: WorkItem): number {
const today = workItem.timestamp;
const yesterday = subtractDays(today, 1);
// Check if same tag + same task worked on yesterday
const yesterdayWork = getWorkItems({
userId: workItem.userId,
taskId: workItem.taskId,
tags: workItem.tags, // Same work type (e.g., "Blocker")
date: yesterday
});
if (yesterdayWork.exists) {
// Increment streak from yesterday
return yesterdayWork.streakCount + 1;
} else {
// New task or different tag — reset to 1
return 1;
}
}Visual Output
| Streak Count | Badge | Color | Alert Level |
|---|---|---|---|
| 1 day | - | None | Normal (task started) |
| 2 days | 🔥 Streak: 2 | 🟡 Yellow | Monitor |
| 3 days | 🔥 Streak: 3 | 🟠 Orange | Review at standup |
| 4-5 days | 🔥 Streak: 4-5 | 🔴 Red | Intervention required |
| 6+ days | 🔥 Streak: 6+ | 🔴 Deep Red | Escalate immediately |
Real-World Examples
Example 1: The Stuck Developer
Scenario: Bob working on performance optimization
Day 1 (Monday):
Task: Optimize API response time
Tags: Blocker, API, x6
Streak: 1 (normal — just started)
Day 2 (Tuesday):
Task: Optimize API response time
Tags: Blocker, API, x7
Streak: 🔥 2 (starting to struggle)
Day 3 (Wednesday):
Task: Optimize API response time
Tags: Blocker, API, x8
Streak: 🔥 3 (manager should check in)
Day 4 (Thursday):
Task: Optimize API response time
Tags: Blocker, API, x9
Streak: 🔥 4 (intervention required — pair with senior)
Day 5 (Friday):
Task: Optimize API response time (with senior dev help)
Tags: Blocker, API, x5
Streak: 🔥 5 (but intensity dropping — help working)
Day 6 (Monday next week):
Task: Finalize optimization (root cause found)
Tags: Feature, API, x2
Streak: ENDED (switched from Blocker to Feature)Manager action triggered: Day 4 (Thursday) — paired Bob with senior architect. Result: Root cause found Friday, fix implemented Monday. Prevented: Burnout, potential resignation, wasted effort.
Example 2: The Knowledge Silo
Scenario: Carol is the only person who knows the legacy billing system
Month View:
Week 1: 🔥 Streak: 4 days on "Billing reconciliation" (Blocker, SQL, x7)
Week 2: 🔥 Streak: 3 days on "Invoice generation bug" (Blocker, SQL, x8)
Week 3: 🔥 Streak: 5 days on "Payment processing error" (Blocker, SQL, x9)
Pattern detected:
├── Carol consistently has high-intensity streaks on Billing module
├── No one else touches Billing (Bus Factor = 1)
├── Carol's burnout risk: Critical
└── Business risk: If Carol quits, Billing breaks
Manager action:
1. Immediate: Reduce Carol's other responsibilities
2. Short-term: Pair junior dev with Carol to learn Billing
3. Long-term: Schedule "Billing deep dive" workshop (knowledge transfer)
4. Strategic: Plan Billing system modernization to reduce complexityWhy Streaks Matter More Than Intensity
Scenario A: High Intensity, No Streak
Developer: Dave
Monday: Emergency production fix (Blocker, x10 intensity)
Tuesday: Feature work (Feature, x3 intensity)
Wednesday: Feature work (Feature, x3 intensity)
Burnout Risk: LOW
Reason: High intensity was one-time spike, followed by recovery.
Dave can handle occasional firefighting.Scenario B: Moderate Intensity, Long Streak
Developer: Eve
Monday: Debug legacy code (Bug, x5 intensity)
Tuesday: Debug legacy code (Bug, x6 intensity) 🔥 Streak: 2
Wednesday: Debug legacy code (Bug, x6 intensity) 🔥 Streak: 3
Thursday: Debug legacy code (Bug, x7 intensity) 🔥 Streak: 4
Friday: Debug legacy code (Bug, x7 intensity) 🔥 Streak: 5
Burnout Risk: HIGH
Reason: Grinding for 5 consecutive days with no resolution.
Eve is stuck, losing hope, considering quitting.Key Insight: Duration of struggle matters more than peak intensity. A x10 spike is survivable. A x6 grind for a week is soul-crushing.
Streak-Based Interventions
Intervention Matrix
| Streak Length | Intensity | Action | Who Acts |
|---|---|---|---|
| 2 days | Any | Check in at standup | Scrum Master |
| 3 days | x5+ | 1:1 conversation | Manager |
| 4 days | x6+ | Pair programming assigned | Manager |
| 5 days | x7+ | Escalate blocker to senior/architect | Manager |
| 6+ days | Any | Immediate intervention + root cause review | Director |
Sample Intervention Scripts
Day 3 (Manager check-in):
"I see you've been working on the Payment bug for 3 days. How's it going? Do you need a second set of eyes?"
Day 4 (Pair programming assignment):
"Let's get Sarah to pair with you on this today. Fresh perspective might help."
Day 5 (Escalation):
"This blocker has been going on too long. I'm pulling in the architect to help. Let's get this unblocked today."
Technical Implementation
Streak Persistence
interface StreakRecord {
userId: string;
taskId: string;
tagSignature: string; // Hash of work type tags
startDate: string;
currentStreak: number;
lastUpdated: string;
}
// On new work item submission
function updateStreak(workItem: WorkItem): StreakRecord {
const tagSignature = hashTags(workItem.tags);
const existing = findStreak({
userId: workItem.userId,
taskId: workItem.taskId,
tagSignature: tagSignature
});
if (existing && isConsecutiveDay(existing.lastUpdated, workItem.timestamp)) {
// Continue streak
return {
...existing,
currentStreak: existing.currentStreak + 1,
lastUpdated: workItem.timestamp
};
} else {
// New streak
return {
userId: workItem.userId,
taskId: workItem.taskId,
tagSignature: tagSignature,
startDate: workItem.timestamp,
currentStreak: 1,
lastUpdated: workItem.timestamp
};
}
}Alert Generation
function generateStreakAlerts(team: User[]): Alert[] {
const alerts = [];
for (const user of team) {
const activeStreaks = getActiveStreaks(user.id);
for (const streak of activeStreaks) {
if (streak.currentStreak >= 4) {
alerts.push({
severity: streak.currentStreak >= 6 ? 'critical' : 'high',
userId: user.id,
message: `🔥 Streak: ${streak.currentStreak} days on ${streak.taskTitle}`,
suggestedAction: 'Pair programming or escalation recommended'
});
}
}
}
return alerts;
}Next Steps
"A streak is not a productivity badge. It's a distress signal." 🔥