---
title: "The Hotfix Branch Collided With .claude/skills/ticket/SKILL.md"
canonical: https://dxdev.com/blog/ai-skill-is-production-infra/
datePublished: 2026-04-03
---
We had `hotfix-messaging-visibility` open, a customer was waiting on a text-delivery fix, and git stopped us on `.claude/skills/ticket/SKILL.md`.

It wasn't a source file or a database migration. It was the prompt file that tells Claude how to run a ticket session.

Our first reaction was mild irritation. Merge conflicts on prose files feel bureaucratic, not dangerous. It's just instructions, we figured: read the diff, pick the version that makes sense, move on. We were treating a policy file as soft configuration, and it had just stopped a customer fix cold.

## What the /ticket skill does

The `/ticket` skill at `.claude/skills/ticket/SKILL.md` was how we opened work sessions on production-app tickets. We typed `/ticket 1234`, and the agent session used the skill as its workflow instructions. It covered how to resolve the ticket, choose an appropriate branch type, claim the repository lock, apply ticket-state transitions, record intent, and reserve a clone for the work.

That list matters because the skill shaped repeatable behavior across many sessions. It encoded the branching and ticket-state policy the agent was expected to follow. If its logic for a ticket class was wrong, later sessions using that version could inherit the same wrong workflow.

We had thought of it as a prompt we could refine freely. By April 3rd, three tickets in one day taught us otherwise.

## Three tickets, three edits, one file

The first ticket was the text-delivery investigation. Customers were reporting unreceived texts. The session produced a new diagnostic page in the admin panel and a set of JIRA transitions through the hotfix flow. Somewhere in that session we updated the skill to handle customer-type ticket priority correctly. The existing logic was ambiguous about how to sequence a customer-type issue through JIRA versus a standard staging ticket.

The second ticket was event organization structure. That session produced a second diagnostic page in the admin panel. To work it cleanly, the skill needed to be smarter about role disambiguation, specifically how it handles tickets that sit at the intersection of multiple JIRA components. We edited the skill again.

The third ticket was a [docs-viewer root-path fix](/blog/internal-docs-as-product/). It was smaller in scope, but it exposed something in the branch-creation step. The skill had been cutting branches immediately at session open. The fix for a particular edge case was to defer branch creation until the first edit was actually imminent, after a fetch and sync step confirmed the clone was at the right base commit.

Each edit felt like a local patch for the ticket at hand. Then we tried to merge `hotfix-messaging-visibility` back, and git showed us the skill file had diverged in two directions at once.

## The conflict was a policy collision

We read the conflict as a coordination problem. We had touched the same file on two branches and now had to reconcile them. That is standard merge hygiene, and we started down that path.

It was the wrong reading. We had been editing a file that shapes automated workflow behavior wherever that version is used, and we had not thought about what branch-specific skill edits mean once the branches meet.

The hotfix branch had changed the skill's JIRA transition rules. The other branch had changed its deferred branch-creation logic. Those two branches were now shipping different definitions of how the agent should behave on every future ticket. Merging the file meant deciding which behavior wins on every future session. We had been making that decision by hand, under deadline, on a file we thought was just notes.

The fetch/sync step from the third ticket shows why this matters. It runs before branch creation and verifies the clone's remote state, and it was added so the agent would never cut a branch on a stale base. That makes it a safety invariant for future tickets, and the docs-viewer fix was only the ticket that surfaced it. Once it sits in the shared skill, it can influence any session configured to use that version. We had put it in on a feature branch without checking whether it conflicted with anything on the hotfix branch in flight. That kind of casual edit is what produces a conflict at merge time.

The [blast radius of a skill edit](/blog/route-changes-by-blast-radius-not-schedule/) is every future ticket session that runs on a clone with that version of the file. A prompt file with that reach is a policy file, and it deserves the same change-control caution as the code it orchestrates.

## What we changed

The immediate fix was to resolve the conflict, read both sides of the diff carefully, and write a merged version that kept the customer-priority, role-disambiguation, and deferred-branch-creation changes. The result was a clean merged policy decision.

The structural change is slower. We now treat edits to `.claude/skills/ticket/SKILL.md` the way we treat edits to the JIRA workflow configuration or the CI pipeline. They happen on a branch with intention, and they get reviewed before merge. They don't get patched as a side effect of ticket work. If a ticket session reveals a skill gap, the fix goes into a tracked commit with a note, instead of an ambient edit that blurs into the ticket's history.

One question from that day is still open. Should the skill be split into a stable policy layer and a per-ticket behavior layer, so local work can adapt without changing a shared workflow file? We did not have an answer yet.

Find out which files shape how your automated agents work, such as prompt and skill files, and put them under the same review and change control as your code and workflow configuration. An edit to one of them is a policy decision for every future session that uses that version. Make it deliberately, on a branch, and review it before merge.
