Yak Shaving: Four Hours In and the Actual Task Is Untouched
What it actually looks like
You sat down at 9:15 to add one endpoint. It is now half past one and the endpoint does not exist.
What exists instead is a build tool two major versions newer, a pinned runtime, a lint rule that finally passes, and a container image that builds on your machine again. You can retrace the path. The endpoint needed a new field. The field needed the schema regenerated. The generator crashed on the old runtime. Upgrading the runtime broke a lint plugin. The plugin wanted a newer build tool. Not one of those steps was a mistake. You were not wrong once.
Developers have a name for this. Yak shaving is the chain of things that must be cleared before the thing that must be cleared before the thing you came to do — the phrase for looking up and finding yourself grooming an animal that has nothing to do with anything.
Your branch is the evidence. Eleven changed files, none of them the file you opened. Writing the pull request title stops you for a second, because there is no honest sentence covering both the ticket you picked up and the work you did. You type chore: tooling and move on.
Someone asks how it is going and you talk for two minutes without once reaching the feature. It is a good answer, full of real detail. Afterwards you notice the thing you were building never came up.
And the day ends with the original line in the tracker in exactly the state it was in at 9:14. You are tired the way real work makes you tired, which is the part that matters: that is why tomorrow will go the same way.
Who this happens to
This is common among engineers who are genuinely good at doing things properly.
If you have spent years fixing root causes rather than symptoms, that instinct is not a flaw you picked up. It is most of what makes you worth having on a difficult system. It also has no volume control and no clock — it fires the same way for a broken production dependency and for a deprecation warning that has sat in the log since March.
It is common in solo builders and small teams, for a structural reason. In a larger organisation a reviewer bounces a change that touches the build system when the ticket said "add an endpoint." Working alone, nothing bounces. You have commit rights to every file, so every file is in scope, and the chain has nowhere it may not go.
And it happens to generalists who own the whole stack, because then every prerequisite is also yours to fix — and the tooling layer is legitimately interesting, more tractable than product work, and full of problems with clean right answers.
What sets it off
The trigger is almost never a large obstacle; a large one you would route around, escalate or schedule. It is the small blocker mid-task — the one that looks like three minutes of work from where you are standing, and looks like three minutes again from one level down.
An outdated dependency sets it off. So does a warning you have scrolled past a hundred times and read today, or a fresh clone, or a version bump somebody landed while you were away.
Listen for a specific phrase. While I'm in here. It arrives quietly, it sounds like efficiency, and it is the sound of your day changing scope without a decision being made.
And there is a trigger worth watching honestly: what the original task was going to require of you. The chain rarely starts on a morning when you know exactly what you are building. It starts on the mornings when the endpoint contains a design decision you have not made. Prerequisites never have that problem. They tell you precisely what to do next, and they tell you immediately.
Why it keeps happening
The mechanism is that the thread does not terminate on its own.
Each step is generated by the one before it, so the decision to continue is always made locally, with local information, about the problem directly in front of you. Nothing asks whether this is still the right use of the day. That question gets asked when you finish — and the chain does not finish, it forks.
Then there is the texture, which protects the whole pattern. Ordinary avoidance has a tell: a lightness to it, a guilty flick to another window, a moment where you know. This has none of that. It feels like diligence, because it is diligence, aimed at the wrong object. Nothing in you sounds an alarm on care. That is why it runs unchallenged for four hours, and why "have more discipline" has never made any difference to it.
The reward structure holds it in place. Every link you close pays out immediately: solved, verified, done, a green check. The original task pays nothing for hours and may not pay at all today. Given a solved-shaped problem and an unsolved-shaped one, effort flows to the solved-shaped one, and yours has been flowing there since eleven o'clock.
Underneath sits a sentence worth saying out loud: I have to fix this before I can do the real task. Sometimes that is true. It is worth testing rather than assuming, because it arrives as a fact and works as a permission slip. Test it with the only question that has authority here — of everything you built today, how much would a customer notice if it were missing? Four levels down, the honest answer is almost always none of it.
And the cost stays off the books, because nothing you did was waste in the ordinary sense. The upgrade was real. The image builds. What you spent was a day, and what you have against the thing you set out to do is the state it was already in.
What actually helps
Write the original task on a card and put it where your eyes land. One sentence, by hand, before you touch anything. Then, every so often — the moment you open a file you did not expect to open — read it and connect what your hands are doing to that sentence in one line. If it takes more than a line, you are three levels down. The card does the job a reviewer would do on a larger team.
Ask it out loud: would the customer notice if I stopped here? One level down, usually yes. Two, sometimes. Four, almost never. Say it rather than think it — the pattern runs on momentum, and hearing your own answer is usually enough to break it.
Take the duct-tape version, and file the proper fix as its own piece of work. Pin the old version. Hardcode the value. Disable the one lint rule with a comment and a ticket number beside it. Write the ticket while the details are fresh — what you are reluctant to lose is the understanding you built getting down here, and the ticket keeps it. Good enough to proceed beats correct and nowhere.
Put an edge on it, because the chain will not end by itself. A timer, twenty-five minutes, or a depth limit of two levels. When it fires you are not forbidden from continuing; you are required to decide, out loud, whether to. A scheduled moment where the question gets asked is the single thing this pattern lacks.
Keep a yak list and give it a window. Every prerequisite you duct-taped goes on one flat file, and the file gets a scheduled afternoon. By then some will have been fixed upstream and some will have stopped mattering, and what is left gets done on a day you chose rather than one you did not.