Of the two weeks a project slipped, how much of that was actually yours? Until now, PtahCast could only tell you that a forecast moved — not why, and not who a client conversation about it should really be with. Blockers have always let you narrate a delay to a client in plain English. What was missing was any way to add that narration up.
What it does
Every blocker now gets a category alongside its description, chosen from a short, fixed list: Client (waiting on feedback, an approval, access, content, or a client-caused environment issue), Agency (internal capacity, an estimation miss, technical debt), Third-party (a vendor, an API, or a dependency outside either party's control), and Other. It's a dropdown, not a free-text field on purpose — a fixed list is what makes the totals below mean anything, and it's easy for Theo to extend the list later without breaking the rollup.
Duration is worked out automatically, not typed in by anyone. A resolved blocker's cost is simply the time between when it was opened and when it was cleared; a blocker that's still open shows its running duration right now, so you're not waiting for someone to close it out before its cost becomes visible.
That adds up into two places that already exist on your board and already carry accountability framing. The board detail page gets a small breakdown card — "14 days lost this month: 9 client, 3 agency, 2 third-party" — so your own team can see at a glance where the time actually went. And the client portal surfaces the client-caused figure specifically, worded as a plain fact rather than a complaint: "Time waiting on client input/approvals: 9 days this month."
What it doesn't do
A few things worth being upfront about, because they're deliberate scope decisions for this first version, not gaps we forgot about:
It doesn't change the forecast. Your Aggressive (P50), Commercial (P85), and Safe (P95) dates are untouched by category or duration. The Monte Carlo engine works in abstract per-period throughput counts and only converts that into calendar dates once, at the very end of a run — there's no notion of a blocked ticket state yet, so there's no reliable way to separate "this period was slow because of a client blocker" from ordinary variance. Feeding blocker time back into the forecast math properly is a real, separate project, and it isn't this one.
It doesn't detect blockers automatically. A ticket sitting untouched in "In Progress" for two weeks doesn't flag itself. Someone on your side still has to notice it and log it — this feature makes a logged blocker more useful, it doesn't change how a blocker gets created in the first place.
It doesn't retroactively categorize your history. Blockers logged before this shipped show as "Uncategorized" until someone edits them by hand. No bulk migration is guessing at old data on your behalf.
It doesn't touch billing. The client-caused total is a reporting number for a conversation, not a line item on an invoice.
Why the wording matters
A client-facing "days you cost us" figure can read as adversarial the moment it's used carelessly, however accurate it is — so the copy on the client portal stays descriptive rather than accusatory: time waiting on client input, not time the client wasted. The value of a number like this is the same as the value of an accountability log in general — it's only worth something if it reads as an honest record both sides can trust, not a scorecard one side keeps against the other.
Available on every plan, on every board that already uses blockers — nothing new to turn on. Log a blocker the way you always have; pick its category while you're there.