Two Sessions, One RunManager
A cloud agent and a local agent both edited the same function in Earfh. I wrote down who owned what and a merge rule, and the rule never ran, because one branch merged in 13 minutes and the other was closed two days later.
Earfh's RunManager.end_run decides what a finished run is worth. It banks the run, marks milestones and, since the Whistleblower work, decides whether the player gets a hire. On 2026-09-26 and 2026-09-27 two agent sessions edited it at the same time without knowing about each other.
One was a cloud session building the groundwork for a second act, in PR #39. In that design the Comb Overlord's death calls act_break(), which banks act 1, hires the next crew and shows a banner. The other was a local session, building the Whistleblower in PR #44. It gave end_run a finished parameter and made it mark a "first run" milestone only when a run ends in a death or a boss win.
What I wrote down
The scaling spec has a section called "Who owns what". It gives the run structure, the act break and act 2's levels to one side, and says "the local session owns the Pen Pal himself": his scene, his moveset and his art. That is a fair split by feature. It says nothing about end_run, which neither list names, and both changes needed it.
So the handoff file, last updated on 2026-09-27, carries the rule for the day the two meet. Once #44 is on main, #39 must merge main in. In end_run it keeps its own banking call, adds #44's finished parameter and first_run marking, and does not restore a boss milestone there, because act_break() owns it. It is a careful paragraph and it is the sort of thing I would want to find in a repo six months later.
A second hole in the same function
While the two branches were open, a bug turned up in the local one. quit_to_menu() always called end_run() with the default finished of false. A run that won the boss and then quit during the victory transition banked the win and never hired the new character. The change that introduced finished landed at 22:22 on the 26th, and the fix at 01:07 on the 27th, about an hour and forty-five minutes later. The commit message doesn't record how it was found, so I won't guess.
The detail I take from it is that the function was getting hit from two directions at once. The new parameter had a default that was wrong for one caller, and the other branch was about to rewrite the same function around it.
What happened to the rule
The merge rule was never carried out. PR #44 merged on the morning of the 27th, 13 minutes after it was opened. PR #39 stayed open. On 2026-09-28 I closed it with a note that main had moved a long way (the Last Straw, the horde engine, the mob attack layer) and that the branch rewrote the same spawning and run code. Act 2 will be rebuilt as its own slice, reusing the ideas.
So the paragraph I wrote to protect the merge describes a merge that did not happen. The collision was predicted correctly. The branch that stayed open for two days was the one that paid for it.
What I changed
An ownership list by feature is not ownership by function. The spec said who owned the Pen Pal and did not say who owned end_run, and the file both sessions needed was the one nobody had listed. If I split parallel work again, the check is a pass over the shared files before the split, so the spec names an owner for each.
A handoff rule is also a promise about a future merge, and it only holds if that merge comes soon. Of the two branches, the small one merged within minutes and the large one aged out. The better protection was never the paragraph. It was the size of the slice.
More on the game at /games/earfh, and the rest of this series at /notes.