One ticket showed Done in JIRA. The Claude session was closed. CI had passed. One of its ten sub-branches was on origin/develop.

I found this during a read-only review pass, not a release. That is the only reason it did not go to production with nine-tenths of the change missing.

The ticket was a moderately complex feature across the platform’s codebase. The work spread across multiple branches that needed to land on develop in a specific order. At some point during the close sequence, either I or Claude reported success after the first branch landed and nobody checked the others. JIRA moved to Done. The session ended. The remaining branches sat in git, waiting, attached to a ticket the system believed was finished.

how the close workflow allowed this

The close workflow at the time was human-reported. The pattern was: merge the branch, run CI, post a comment, move the JIRA status. Each step had ceremony around it. None of those steps required the closer to prove that every branch was actually on develop before JIRA could transition.

A status field is not evidence. A comment is not evidence. CI passing on a branch that never merged is not evidence. The only thing that counts is whether the SHA is reachable from origin/develop, and nothing in the workflow was checking that.

The platform’s codebase runs across four local clones, the base checkout through clone four, with develop as the release branch and master as prod. The preview branch is preview only. In that shape, “merged to develop” is the gate for any ticket that touches customer-facing code. If you close without verifying that gate, you are filing paperwork on a thing that did not happen.

the guardrails I landed in clone three

The same day I found that gap, I wrote what I called Appendix C into the workflow docs in clone three. Three rules, now encoded as checks in the close orchestrator.

Contaminated develop is refused. If a develop branch contains a recovery revert that has not been cleared, the close process halts with a named error instead of a status transition. The check runs before anything else.

Dirty worksite is refused. If the worksite still has an uncommitted diff or a stale branch reference, close halts. Not a warning. A halt.

Preview-branch checks are widened. The preview-branch verification now confirms that the shipped feature SHA is actually reachable from the preview tip, not just that the branch exists.

Writing those three checks took about forty minutes. Encoding the rule in the docs had taken two seconds and accomplished nothing. The codebase had the written rule for weeks. The gap was that the written rule could be skipped under time pressure, and apparently had been.

the backport problem was a separate failure mode

The same audit surfaced a second pattern: hotfix branches were occasionally handled by merging master into develop instead of cherry-picking the fix commit onto develop explicitly. Those are not the same operation.

A master-to-develop merge in a repo where the preview branch has diverged from develop can pull in preview-specific commits transitively. This had happened at least once. I built a hotfix-backport tool that enforces the cherry-pick path and refuses to run if it detects that master has commits not reachable from the preview branch. The tool is not clever. It makes the right operation the only operation available.

the same day, twice more

May 21 also produced an exit-survey mailer that overwrote a live customer row, and a retro-script build that I’d been deferring because I had no systematic way to catch corrective patterns across sessions. Three different failure modes, same shape: a system that could report success while the actual state was wrong.

The overwrite happened because an identity-insert script assumed existence meant consent. The JIRA gap happened because status transitions assumed ceremony meant verification. The retro gap was subtler: I was catching individual mistakes but not the meta-pattern of which rules I kept re-learning.

A green checkmark is a signal, not a proof. Every workflow that lets you move a status field without verifying the underlying state will eventually let you believe something happened that did not.

A workflow that can report success while the code is missing is not a workflow, it is a rumor.