play icon for videos
← Academy
Analyze · Caseload momentum

How Do You Track Caseload Progress Over Time?

Some clients quietly stop moving, and the quarterly review is the first place anyone notices. Here is how to track caseload momentum over time and surface stalled clients early with Sopact Sense.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> @keyframes pulseDot{0%,100%{opacity:1}50%{opacity:.35}} *{box-sizing:border-box} body{margin:0;font-family:'Hanken Grotesk',-apple-system,BlinkMacSystemFont,sans-serif;background:#EEF2F9;padding:26px;display:flex;justify-content:center} .card{width:600px;max-width:100%;background:#FFFFFF;border:1px solid #E3E9F4;border-radius:20px;box-shadow:0 26px 64px -32px rgba(15,30,70,.34),0 2px 4px rgba(15,30,70,.05);overflow:hidden} .hdr{display:flex;align-items:center;gap:11px;padding:16px 20px;border-bottom:1px solid #EEF1F7;background:#F5F8FE} .hdr .ic{display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;border:2px solid #155DFC;border-radius:50%;color:#155DFC;font-size:15px;font-weight:800;flex-shrink:0} .hdr .t{min-width:0} .hdr .t .n{font-weight:800;font-size:14.5px;color:#0F172A;letter-spacing:-.2px} .hdr .t .s{font-size:12px;color:#64748B} .hdr .pill{margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;color:#155DFC;background:#E6EEFF;padding:5px 10px;border-radius:20px;white-space:nowrap} .hdr .pill .d{width:6px;height:6px;border-radius:50%;background:#155DFC;animation:pulseDot 2s infinite} .tabs{display:flex;gap:0;padding:12px 16px 0;background:#F5F8FE} .tab{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px;cursor:pointer;font-family:inherit;font-size:11.5px;font-weight:700;color:#64748B;background:transparent;border:none;border-bottom:2px solid transparent;padding:8px 4px 10px} .tab.on{font-weight:800;color:#155DFC;border-bottom-color:#155DFC} .tab .num{display:inline-flex;width:20px;height:20px;align-items:center;justify-content:center;border-radius:50%;font-size:11px;font-weight:800;color:#64748B;background:#EEF1F7} .tab.on .num{color:#fff;background:#155DFC} .divider{height:1px;background:#EEF1F7} .body{padding:20px} .eyebrow{font-size:10.5px;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:#155DFC;margin-bottom:5px} .eyebrow.g{color:#15884F} .headline{font-family:'Inter',Georgia,serif;font-size:18.5px;font-weight:600;line-height:1.25;color:#0F172A;margin-bottom:12px} .lede{font-size:12.5px;line-height:1.55;color:#475569;margin:0 0 14px} .rows{display:flex;flex-direction:column;gap:8px;margin-bottom:14px} .row{display:flex;align-items:center;gap:11px;background:#F5F8FE;border:1px solid #EEF1F7;border-radius:11px;padding:11px 13px} .row .emoji{font-size:17px} .row .rt{flex:1;min-width:0} .row .rt .n{font-size:13px;font-weight:700;color:#0F172A} .row .rt .s{font-size:12px;color:#64748B} .pillsm{font-size:11px;font-weight:800;color:#155DFC;background:#E6EEFF;padding:4px 9px;border-radius:6px;flex-shrink:0} .pillsm.gray{font-weight:700;color:#64748B;background:#EEF1F7} /* chain / timeline */ .chainwrap{position:relative;padding-left:26px} .chainline{position:absolute;left:8px;top:8px;bottom:8px;width:2px;background:#E3E9F4} .cnode{position:relative;margin-bottom:14px} .cdot{position:absolute;left:-26px;top:4px;width:16px;height:16px;border-radius:50%;background:#fff;border:3px solid #94A3B8} .clabel{font-size:9.5px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:#64748B;margin-bottom:4px} .cbox{background:#F5F8FE;border:1px solid #EEF1F7;border-radius:11px;padding:10px 12px;font-size:12px;line-height:1.5;color:#334155} .cbox.graded{display:flex;align-items:flex-start;gap:9px;border-left-width:3px;border-left-style:solid} .cnote{margin:0 0 14px 4px;font-size:11px;line-height:1.5} .cnote .plus{display:inline-flex;width:16px;height:16px;align-items:center;justify-content:center;background:#155DFC;color:#fff;border-radius:4px;font-size:10px;font-weight:800;flex-shrink:0;margin-right:6px} .csummary{display:flex;align-items:center;gap:12px;background:#0A1B3D;border-radius:13px;padding:11px 15px;margin-top:4px} .csummary .t{flex:1;font-size:11.5px;color:#CBD8F5} .csummary .t b{color:#F1F5FF} /* matrix */ .mxwrap{border:1px solid #EEF1F7;border-radius:12px;overflow:hidden;margin-bottom:10px} .mxhead{display:grid;grid-template-columns:118px 1fr 1fr;background:#F5F8FE;border-bottom:1px solid #EEF1F7} .mxhead div{font-size:9px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:#64748B;padding:7px 9px} .mxrow{display:grid;grid-template-columns:118px 1fr 1fr;border-bottom:1px solid #EEF1F7} .mxrow:last-child{border-bottom:none} .mxrow>div{padding:9px;font-size:11.5px;line-height:1.4;color:#334155;display:flex;align-items:center;flex-wrap:wrap;gap:5px} .mxrow .mxlabel{font-weight:700;color:#0F172A;background:#FAFBFE} .mxchip{font-size:9px;font-weight:800;letter-spacing:.3px;text-transform:uppercase;padding:3px 6px;border-radius:5px;white-space:nowrap} .promptwrap{padding:0 20px 18px} .promptlbl{font-size:10px;font-weight:800;letter-spacing:1px;text-transform:uppercase;color:#94A3B8;margin-bottom:7px} .prompt{display:flex;align-items:flex-start;gap:9px;font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:11px;line-height:1.5;color:#1E293B;background:#F5F8FE;border:1px solid #EEF1F7;border-left:3px solid #155DFC;border-radius:9px;padding:11px 12px} .prompt .car{color:#155DFC;font-weight:800;flex-shrink:0} .flagrow{display:flex;align-items:flex-start;gap:10px;background:#F5F8FE;border:1px solid #EEF1F7;border-radius:11px;padding:10px 12px;border-left-width:3px;border-left-style:solid;margin-bottom:8px} .flagtag{font-size:9.5px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;padding:4px 8px;border-radius:5px;white-space:nowrap;flex-shrink:0} .flagtxt{font-size:12px;line-height:1.45;color:#334155} .lp{display:flex;align-items:center;gap:12px;background:#0A1B3D;border-radius:13px;padding:14px 16px;margin-top:6px} .lp .ic{display:inline-flex;width:34px;height:34px;align-items:center;justify-content:center;background:#14295C;border:1px solid #26407A;border-radius:9px;color:#7FA8FF;font-size:16px;flex-shrink:0} .lp .rt{flex:1;min-width:0} .lp .rt .n{font-size:13px;font-weight:800;color:#F1F5FF} .lp .rt .s{font-size:11.5px;color:#9DB2D9} .lp .open{font-size:11px;font-weight:800;color:#0A1B3D;background:#7FA8FF;padding:6px 11px;border-radius:7px;white-space:nowrap} </style> </head> <body> <div class="card"> <div class="hdr"> <span class="ic">&#128202;</span> <div class="t"> <div class="n">Case-management program (synthetic) · caseload momentum over time</div> <div class="s">DEMO-08 · Sopact Sense · Caseload</div> </div> <span class="pill"><span class="d"></span>Tracking</span> </div> <div class="tabs" id="tabs"></div> <div class="divider"></div> <div class="body" id="body"></div> <div class="promptwrap"> <div class="promptlbl">The prompt behind this step</div> <div class="prompt"><span class="car">&gt;</span><span id="promptTxt"></span></div> </div> </div> <script> (function(){ var TABS = ["Setup", "Track", "Fix", "Report"]; var CONTENT = [{"eyebrow": "Step 1 · Load the dataset", "headline": "You don't crunch it by hand. You write the prompt.", "lede": "Point the Assistant at the Caseload dataset (DEMO-08) — clean, with persistent contact IDs — and wait for the task.", "prompt": "You are the Sopact Sense Assistant working over the [DEMO] dataset (clean data + persistent contact IDs). Load my Decision Brief (decision, audience, outcomes, indicators, evidence standard) first, then wait for my task."}, {"eyebrow": "Step 2 · Track momentum", "headline": "Five elements turn a dataset into a graded momentum read.", "lede": "Every client is graded <strong style=\"color:#15884F\">green</strong>, <strong style=\"color:#C9820A\">amber</strong>, or <strong style=\"color:#C63E2B\">red</strong> for cohort momentum — stalled cases surface before the quarterly review does.", "prompt": "For [PROGRAM], track progress per client over time; identify no-movement-in-[N]-months clients, cluster reasons, report cohort momentum. Grade green/amber/red."}, {"eyebrow": "Step 3 · One-fix follow-up", "headline": "Re-engage the stalled.", "lede": "The Assistant names the single data point that moves the lowest-graded element to green.", "prompt": "Take the lowest-graded element above and fix it using only what the program could realistically measure. Show the before → after grade and the single indicator/edit that moves it to green."}, {"eyebrow": "Step 4 · Missing & incomplete report", "headline": "Case — Caseload Momentum Report", "lede": "Every amber or red item becomes one named ask — the report leads with the decision it informs.", "prompt": "Create a 'missing & incomplete' report from this analysis in Sopact branding [or paste your website URL / brand guideline to apply your own]. List every element graded amber or red, what is missing, and the one input that fixes each. Lead with the decision this report informs."}]; var BODIES = { setup: "<div class=\"row\"><span class=\"emoji\">&#128203;</span><div class=\"rt\"><div class=\"n\">Dataset</div><div class=\"s\">Caseload demo (DEMO-08), clean data with persistent contact IDs</div></div><span class=\"pillsm\">Pasted</span></div><div class=\"row\"><span class=\"emoji\">&#128260;</span><div class=\"rt\"><div class=\"n\">Structure</div><div class=\"s\">Client → last progress → likely reason</div></div><span class=\"pillsm gray\">Structure</span></div><div class=\"row\"><span class=\"emoji\">&#128274;</span><div class=\"rt\"><div class=\"n\">No hallucination rule</div><div class=\"s\">Mark anything absent as MISSING; don&#x27;t guess</div></div><span class=\"pillsm gray\">Required</span></div>", build: "<div class=\"mxwrap\"><div class=\"mxhead\"><div></div><div>Last progress</div><div>Likely reason</div></div><div class=\"mxrow\"><div class=\"mxlabel\">CL-301</div><div>this month<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>active</div></div><div class=\"mxrow\"><div class=\"mxlabel\">CL-307</div><div>risk flag<span class=\"mxchip\" style=\"background:#C9820A;color:#fff\">AMBER</span></div><div>safeguarding follow-up</div></div><div class=\"mxrow\"><div class=\"mxlabel\">CL-305</div><div>no movement 3mo<span class=\"mxchip\" style=\"background:#C63E2B;color:#fff\">RED</span></div><div>stalled — unreachable</div></div></div>", fix: "<div class=\"mxwrap\"><div class=\"mxhead\"><div></div><div>Last progress</div><div>Likely reason</div></div><div class=\"mxrow\"><div class=\"mxlabel\">CL-301</div><div>this month<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>active</div></div><div class=\"mxrow\"><div class=\"mxlabel\">CL-307</div><div>risk flag<span class=\"mxchip\" style=\"background:#C9820A;color:#fff\">AMBER</span></div><div>safeguarding follow-up</div></div><div class=\"mxrow\"><div class=\"mxlabel\">CL-305</div><div>re-engaged<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>stalled — unreachable</div></div></div><div class=\"cnote\" style=\"color:#15884F;margin-left:0\"><span class=\"plus\">+</span><strong>Fix applied:</strong> Assign an outreach attempt + alternate contact</div>", reportFlags: "<div class=\"flagrow\" style=\"border-left-color:#C9820A\"><span class=\"flagtag\" style=\"color:#C9820A;background:#FBF0DA\">AMBER</span><div class=\"flagtxt\">CL-307 — safeguarding follow-up pending. Fix: close the loop on the flag.</div></div><div class=\"flagrow\" style=\"border-left-color:#C63E2B\"><span class=\"flagtag\" style=\"color:#C63E2B;background:#FCE9E7\">RED</span><div class=\"flagtxt\">CL-305 — no movement in 3 months. Fix: outreach + alternate contact.</div></div>", lpTitle: "Missing & incomplete report · shareable link", lpSub: "Decision-first · Sopact branding · Case-management program (synthetic) · caseload momentum over time", summaryBefore: "Grade: 1 green &middot; 1 amber &middot; 1 red. stalled cases, unflagged", summaryAfter: "Grade: 2 green &middot; 1 amber &middot; 0 red. outreach assigned, cohort re-engaged" }; var phase = 1; var tabsEl = document.getElementById('tabs'); var bodyEl = document.getElementById('body'); var promptEl = document.getElementById('promptTxt'); function renderTabs(){ tabsEl.innerHTML = ''; TABS.forEach(function(label, i){ var b = document.createElement('button'); b.type = 'button'; b.className = 'tab' + (i === phase ? ' on' : ''); b.innerHTML = '<span class="num">' + (i+1) + '</span><span>' + label + '</span>'; b.addEventListener('click', function(){ phase = i; render(); }); tabsEl.appendChild(b); }); } function renderBody(){ var c = CONTENT[phase]; var eyebrowClass = (phase===2) ? 'eyebrow g' : 'eyebrow'; var out = '<div class="' + eyebrowClass + '">' + c.eyebrow + '</div><div class="headline">' + c.headline + '</div><p class="lede">' + c.lede + '</p>'; if (phase === 0) { out += '<div class="rows">' + BODIES.setup + '</div>'; } else if (phase === 1) { out += BODIES.build; out += '<div class="csummary"><div class="t"><b>' + BODIES.summaryBefore + '</b></div></div>'; } else if (phase === 2) { out += BODIES.fix; out += '<div class="csummary"><div class="t"><b>' + BODIES.summaryAfter + '</b></div></div>'; } else { out += BODIES.reportFlags; out += '<div class="lp"><span class="ic">&#128196;</span><div class="rt"><div class="n">' + BODIES.lpTitle + '</div><div class="s">' + BODIES.lpSub + '</div></div><span class="open">Open &rarr;</span></div>'; } bodyEl.innerHTML = out; promptEl.textContent = c.prompt; } function render(){ renderTabs(); renderBody(); } render(); })(); </script> </body> </html>

In short: Some clients quietly stop moving, and the quarterly review is usually the first place anyone notices. Point the Sopact Sense Assistant at your caseload, track progress per client over time, surface the clients with no movement in N months, and cluster the reasons — so you spot stalled cases while you can still act on them.

1 · Set up over your data

Tell the Assistant which dataset it is working over and load your Decision Brief first, so the momentum read ties back to the decision, audience, outcomes, indicators, and evidence standard you already set.

You are the Sopact Sense Assistant working over the DEMO-08 · Caseload dataset (clean data + persistent contact IDs). Load my Decision Brief (decision, audience, outcomes, indicators, evidence standard) first, then wait for my task.

2 · Write the prompt

For [PROGRAM], track progress per client over time; identify no-movement-in-[N]-months clients, cluster reasons, report cohort momentum. Grade green/amber/red.

The prompt carries five elements. Dataset: the caseload across the program. Momentum over time: progress tracked per client, not a single snapshot. Stalled list: clients with no movement in N months. Cluster reasons: group the stalls by likely cause. Grade: a green / amber / red call on each client.

3 · What Sense produces

Run on the Caseload dataset (DEMO-08) already loaded in Sopact Sense.

GRADE: green | Active | client · amber | Follow-up | pending · red | Stalled | client

The Assistant tracks each client over time and grades momentum. Green is an active client who is moving. Amber is a follow-up pending — progress is recorded but recent contact is overdue. Red is a stalled client with no movement logged in months.

4 · Turn a weak link green

Take the lowest-graded element and fix it with something the program could realistically capture.

Take the stalled-client element above and fix it: capture a reason-for-stall field at each touchpoint so the cluster, not just the count, is actionable. Show the before → after grade and the single edit that moves it to green.

5 · Make the report and share it

Create a 'missing & incomplete' report from this analysis in Sopact branding. List every element graded amber or red, what is missing, and the one input that fixes each. Lead with the decision this report informs.
Create a shareable link for this report & open it in a new tab.

Tricks, tips, and troubleshooting

Define "stalled" with a number. No-movement-in-N-months only works if N is set. Pick a threshold that matches your program's cadence so the flag fires at the right time, not too early or too late.

Cluster the reasons, don't just count. A list of ten stalled clients is a workload; ten stalls grouped into two root causes is a plan. Ask for the clusters so the report points at a fix.

Use the amber tier as your early warning. Follow-up-pending clients haven't stalled yet. Acting on amber is how you stop a client from sliding to red before the next review.

Re-run it on a schedule. Momentum is only useful if it is fresh.

Run this prompt at a fixed cadence so the stalled list is current the day you review it, not a month old.

Frequently asked questions

How do you track caseload progress over time?

Track each client's progress across touchpoints rather than at a single point, then flag anyone with no movement in a set number of months and cluster the reasons. The Sopact Sense Assistant does this over your whole caseload and grades each client green, amber, or red, so stalled cases surface before the quarterly review catches them.

What counts as a stalled client?

A client with no recorded movement for the threshold you set — for example, three months. They grade red. A client whose progress is logged but whose recent contact is overdue grades amber, an early warning that they may stall next.

How do you make the stalled list actionable?

Capture a reason-for-stall field at each touchpoint so the Assistant can cluster the stalls by cause. That turns a flat list of names into grouped root causes you can actually plan against.

Ready to try it for yourself?

Open Sopact Sense, paste your program description, and put it to work.

Try in Sopact