On April 22, 2026, I was working on hotfix/3.346.12, a release branch pointed straight at production, when I ran /sync mid-session and watched the skill prepare to merge develop in.

That would have been bad.

develop in this codebase is the staging lane. It carries half-finished features, experimental schema changes, and at any given moment, code that is not production-ready. Merging it into a hotfix branch would have pulled all of that toward master. One merge commit, and the release becomes a vehicle for everything that was supposed to wait.

The skill didn’t know the difference. It saw a branch, it knew there was a develop and a master, and it ran the standard sync logic.

what the branch model actually is

HTO is a 25-year-old ASP-classic application. The release topology reflects that age. It works, but it has corners you have to know about.

develop is where features land before a release. master is production. ben is a preview branch David and Aaron use to review work before it goes live. Hotfixes cut directly from master, get a version tag like 3.346.12, and merge back into both master and develop in a specific order.

That last part matters. When a hotfix lands, the release pipeline carries it forward. master gets the fix, then develop gets it via the standard hotfix merge. If you run a separate master to develop sync inside your skill, you’re manufacturing a duplicate merge commit, racing the actual release flow, and creating phantom history that confuses future merges.

So there were two bugs in /sync, not one. Merging develop into a hotfix branch was wrong because it drags unfinished work toward production. Merging master into develop during sync was wrong because the release flow already handles that, and doing it again creates noise and timing risk.

what I changed

The fix is not complicated in retrospect. The skill now reads the branch prefix before deciding what to do.

Branches matching hotfix-* or hotfix/* get a different sync path. No develop merge. No master-to-develop push. Just a targeted sync against the base they actually cut from. develop and master get their own handling. Everything else falls through to the original logic.

I also updated the workflow docs and the branch validation checks so the agent has the branch semantics written down somewhere it can read them, not just inferred from the codebase topology. The topology is visible. The meaning of the topology is not. Which branches exist is a git branch -a. What you are allowed to merge into a hotfix branch is a policy, and policies need to be stated explicitly or they don’t exist.

One other thing I fixed at the same time. There was a hardcoded clone path in the sync skill that referenced a specific working directory on my machine. It was fine until I ran the skill from a different clone, at which point it tried to operate on the wrong repo. One line, obvious in hindsight, sitting there untouched because the nominal path always happened to be the one I was using.

the /item fix alongside it

While I was in the tooling, I also updated /item, the skill I use to open an investigation on a JIRA ticket.

The old behavior was to start every investigation with an empty browser tab and wait for me to supply the repro URL. Every session started with me reading the JIRA ticket, finding the Links field, copying the URL, pasting it into the skill. A two-minute tax on every investigation.

The Links field exists in JIRA exactly because repro URLs are part of ticket state. It lives at customfield_10101. The skill now reads it on open and navigates there directly. If no link is present, it asks. If one is present, it uses it. Two minutes saved per ticket, one fewer thing to hold in working memory.

Both fixes belong to the same category. The agent was making me supply context that was already written down somewhere accessible. The branch rules were in the workflow docs. The repro URL was in the JIRA ticket. The skill just wasn’t reading either.

the compounding direction

Workflow mistakes move faster than coding mistakes. A bug in a feature affects one feature. A bug in the deployment flow affects every feature that touches it.

Earlier the same day, the ExpiredRedirect fix I shipped for ITEM-6643 saturated the IIS worker pool by running a SELECT and UPDATE on every authenticated request. The damage was scoped to one server’s thread queue. Recoverable in minutes. If /sync had merged develop into hotfix/3.346.12 and I had pushed before catching it, the damage would have been whatever develop happened to contain that afternoon, arriving in a production release labeled as a hotfix.

The asymmetry matters. Coding mistakes tend to fail locally and loudly. Workflow mistakes tend to fail silently or at a distance, when the release lands and the wrong code is in it.

That is why the branch rules have to be explicit. Claude is not going to invent the deployment model of your repo from first principles. It will read what you’ve given it and do the most plausible thing. If you haven’t written down that hotfix branches cannot accept develop merges, the most plausible thing is to run the default sync. The default sync will do what it always does.

The leverage isn’t in better prompts. It’s in better operational rules. The policies your tooling enforces so the agent doesn’t have to guess at the shape of your repo.

An AI coding agent is only as safe as the branch rules you bothered to make explicit.