publish.yml ran from release/* so its version-bump commit would reach main
through a PR. That guarded a package.json version field and a lockfile and left
the shipped tree ungated, which is the wrong way round — and it was not
theoretical. On release/cli-readme:
00:33:19 v0.2.2 published to npm
00:44:45 v0.2.3 published to npm
00:48:18 PR #10 opened — first chance to review any of it
00:48:21 Checks and Branch policy run for the first time
00:51:33 merged to main
Two versions reached users from a branch with no pull request, no CI run and no
reviewer, seven minutes before the code reached main. `main` is not branch
protected either, so the PR route was never enforced to begin with.
Publishing from main means npm gets the tree that was reviewed, merged and
checked. The bump commit pushed back to main is mechanical and has nothing in
it to review; branch-policy.yml still governs the route for everything else.
Dry runs stay unrestricted — they publish and push nothing, and validating
packaging from a branch before merging it is what they are for.
The tag is now pushed on its own, ahead of the branch. main takes merges that a
release/* branch did not, so the bump commit can lose a race that a tag ref
cannot; rebasing to win it would move the commit off the tree that was actually
published. If the branch push loses, the release is still complete and recorded
by the tag, and the job says exactly which cherry-pick finishes it.