
I spent 8 years running a team that built software for clients, and this is still the mistake I think about the most.
We put together and signed a SOW with a client for a 6-month build. Pretty standard stuff: a scope doc, milestone schedule, a signature.
That 6-month build went on for a year and a half. Priorities moved. The client asked for things that weren't in the original scope and we built them in good faith. We prided ourselves on understanding what they actually needed, not just what the document said. Some things in the SOW quietly stopped mattering and we dropped them, with everyone's blessing at the time.
All of it was agreed. None of it was agreed anywhere durable. It lived in biweekly meetings, Slack channels, and email chains.
At the end, the client went back and read the SOW.
And from where they sat, we hadn't built what we agreed to. Things on the list weren't there. Things that were there weren't on the list. They were genuinely frustrated and I couldn't really argue, because the record of what we were supposed to be building had been wrong for at least 5 months.
The part that still bothers me is that a big share of that gap was their own requests. They had asked for those changes. They'd just forgotten. Reconstructing it meant digging through a year and a half of Slack, emails, and meeting notes, which is miserable, and doing it in front of a client is indistinguishable from making excuses.
We finished the project. The relationship didn't survive it.
Here's what I took from it:
The problem was never scope creep. Scope creep is the nature of software development. You can't spec 18 months of build in a document written before day one, and what gets delivered always drifts from what was signed.
And yes, we should have amended the SOW as we went. That's on me. But we'd treated it the way I think most teams do: a high-level foundation to start from, not a document you reopen every sprint. Each individual change felt too small to justify contract paperwork. By the time the drift was big enough to formalize, it was everywhere, and formalizing it would have meant reconstructing a year of decisions first.
The real problem was that there was no maintained record of what we were building. Meeting notes, email chains, Slack, Gantt charts, a Jira board — we communicated progress multiple times a week. But all of those show where things stand now. None of them show how the scope changed, when, or who asked. Two different memories of a year and a half, and no tiebreaker.
So I built the version I wanted. Here's how it works:
You upload the signed SOW and it becomes a scope record: a structured list of every deliverable in the agreement, each with a status, instead of a wall of contract text.
As the project moves, you keep the statuses current. Update them in a couple of clicks, or let it read your repo and draft the week's updates from your real commits and PRs, and you just confirm or reject. Upkeep is a review, not a writing task.
When you publish, it saves a version. That's the history I was missing: what changed, when it changed, and what was added beyond the original scope. The thing I needed that day, instead of scrolling Slack.
Your client gets one read-only link, no login. It opens on what's changed since they last looked, laid out cleanly enough that they actually read it.
Live example if you want to see the artifact, no signup: https://scopediff.com/demo/cobalt
What I'm genuinely curious about, since I only have my own experience here:
How do you send client updates today? Email, Slack, a weekly call? And do your clients actually read them?
If a client questions something months later ("when did we decide this?"), what do you actually do? Dig through Slack like I did, or do you have something better?
And the stuff you build that was never in the SOW (the small favors, the quick asks that never felt worth writing down): does that get recorded anywhere, or does it just disappear?
The line that matters here is "all of it was agreed, none of it was agreed anywhere durable." I ran client work for years and the failure was never the change itself — it was that the change was approved in a medium with no index. Slack is a great place to decide things and a terrible place to remember them.
The cheap version of the fix that worked for me was a single change log in the shared doc: one row per change, date, who asked, what it replaced or displaced, and a one-line schedule impact. Two minutes after the call, pasted into the same thread so nobody has to accept a summary they didn't see. The magic isn't the format, it's that "what this displaces" forces the tradeoff into the open while it's still a small conversation. Most drift happens because additions get an explicit yes and the things they quietly push out never get an explicit no.
The other piece I'd add: send a rolled-up scope state at every invoice, not every sprint. Clients don't read sprint updates, but they read the thing attached to a bill, and it means the record gets acknowledged monthly rather than reconstructed at month 18. Your point that reconstruction in front of a client is indistinguishable from excuses is exactly right — that's why the acknowledgment has to happen while it's still boring.
Thanks for this! Both of these are better than what we were doing. The change log especially. Additions getting an explicit yes while the things they pushed out never got a no was exactly what happened to us.
One question: could teammates keep the change log to the same standard, or was it mostly you? That's where every system I tried fell apart.
And a selfish ask: what I built is basically that change log made automatic. It versions the scope on every publish and has the client acknowledgment built in. If you ever look at the demo in the post, I'd honestly like to know what your manual setup did that mine doesn't. You've run this longer than most of the people I've talked to.
The strongest part is treating scope as a living record rather than a document that gets forgotten after signing. Versioned changes with a clear history seem much more useful than trying to reconstruct decisions from a year of Slack and email later.