What your agent inherits between sessions

This morning a scheduled run of my own content pipeline woke up, read its memory, and very nearly shipped a post onto a branch that would never have shown it to anyone. The memory was perfect. The session log was exactly where the last run left it. The pipeline's pointer file and its state JSON were intact down to the timestamp. Everything I had taught the engine to remember, it remembered. And it was about to commit on top of a workspace that had quietly drifted almost two weeks out of date.

That gap is the thing I want to talk about, because it is the part of vibe coding the demos skip. Every vibe coder running agents across more than one sitting is exposed to it, and almost nobody specs for it.

Here is what actually happened. The run grounds itself, reads the day's research, and when the outside world is quiet it mines its own recent work for a methodology angle instead of going dark. All of that depends on durable memory, and the durable memory was flawless. What was not flawless was the git checkout the run inherited. The local branch it deploys from was sitting thirteen commits behind the published branch. Not diverged in some exotic way. Just stale, because a previous session had parked some unrelated work on that branch and the remote had moved on without the local copy catching up.

If the agent had done the obvious thing, commit the new post and push, one of two things happens. The friendly outcome is the push gets rejected as a non-fast-forward, the agent records a failure it does not understand, and the post never deploys. A "ship" that ships nothing. The unfriendly outcome is worse: if the agent had been written to muscle through a rejected push with a force flag, it would have overwritten the published branch with its stale local copy and erased nearly two weeks of already-live posts. Same starting condition, two ways to lose, and the agent's own logs would have reported success right up until the moment a human noticed the site was wrong.

The reason this class of bug is so easy to miss is that we serialize the wrong half of the state. We are careful with memory. We write the notes file, we checkpoint the decisions, we hand the next session a clean summary of what happened and what is next. That part is a solved problem in most agent setups now. What we do not serialize is the environment. The branch you are on, the commits the remote has that you do not, the working tree that a different run left half-changed: none of that lives in the memory file, and the agent has no reason to suspect it moved. Durable memory is necessary. It is not a durable handoff. The handoff has to cover the workspace the next session wakes up in, not just the log of what the last one was thinking.

Once you name the gap, the discipline that closes it is almost boring, which is how you know it is the right one.

First, the deploy target is the single source of truth, not the local copy. The branch that actually serves visitors is the authority; the local checkout is a guess about that authority until proven otherwise. The run's first real act is to reconcile the local branch to the deployed one, so that whatever it commits lands as a clean fast-forward instead of a fight. This is the same lesson a wrong-branch incident burned into this pipeline weeks ago, when a post once committed to a side branch and never deployed at all. The fix then became an invariant: the engine only ever commits content to the branch the site is built from. Today's drift was that invariant earning its keep a second time, from a different direction.

Second, you never reconcile destructively until the drifted work is provably safe. Before realigning the local branch this morning, the run confirmed the parked commit was preserved on a backup branch and in the reflog. Only then did it move. That ordering is the whole game. A reconcile that could lose work is not a fix, it is a coin flip, and a scheduled agent flipping that coin unattended at five in the morning is exactly the thing you do not want. Prove the escape hatch exists, then act.

Third, give the agent a workspace preflight, not just a memory read. The same way you teach it to read its notes at the top of a run, teach it to interrogate its environment: what branch am I on, does the remote have commits I do not, is the working tree clean, is this the branch that deploys. Those four questions take seconds and they convert a silent class of failure into a loud one you can see and handle. A loud failure is a gift. The dangerous failures are the ones that look like success.

I can show you this rather than assert it, because the post you are reading shipped through that exact check. The content engine behind this blog is not a thing I describe from the outside. It runs the way the writing says to run, and when it drifts, the drift is part of the record. That is the point of building the proof-of-work in public: the methodology is only worth anything if it holds up on the mornings it gets tested, and this was one of those mornings. I wrote up a close cousin of this failure, where a stale environment from a prior session made a build error lie about its own cause, in the build error that lied, and the through-line is the same. The agent's memory is rarely the thing that betrays you. The environment around the memory is.

If you are formalizing the AI orchestration around your own agents, especially anything that runs across sessions or runs unattended, and you want to compare notes on what actually holds when no one is watching the run, /work-with-us. VibeKoded works on the spec-and-handoff layer of agent builds: the invariants a run is held to, and the preflights that catch a drifted workspace before it ships. Work with VibeKoded.