# DEVX-179: auto-merge must never select `[skip ci]` squash titles ## Problem PR #351 squash-merged as `DEVX-178: chore: update badge URLs to commit 4422c70b [skip ci]`. `extract_conventional_msg` picked a commit subject carrying `[skip ci]` — a master badge commit surfaced in the PR's commit list after force-push/amend rewrote branch history. The resulting merge commit suppressed the post-merge push run: no release, no publish, no wiki sync, no Vikunja close. PR #352 shows the secondary defect: two `ci:` commits on the branch and the older one won the tie, so the squash title described a throwaway retrigger commit instead of the real change. ## Approach REQ-1: Subjects containing `[skip ci]`, `[ci skip]`, or `[skip actions]` (case-insensitive) are ineligible merge titles. They are excluded before priority scoring, so a badge/chore/`[skip ci]` commit can never suppress the post-merge pipeline again. REQ-2: Equal-priority ties resolve to the newest commit in the returned list (Gitea returns PR commits newest-first; iterate in returned order and keep the first best candidate). ## Test Plan - `test_auto_merge.py`: commits `[ci retrigger, badge-chore-skipci]` → the `ci` subject wins; commits `[older-ci, newer-ci]` → newest wins; all commits `[skip ci]` → falls back to newest non-skipped subject. - `make pytest-cov` (100% gate), `make lint-all`. ## Deploy Plan Merge as `fix:` → post-merge cuts a release that also ships DEVX-178's PLAYBOOK_ROLE_MAP entry. ## Rollback Plan Revert the squash commit; extract behavior returns to the previous (unhardened) selection. ## Acceptance Criteria - [x] REQ-1: `[skip ci]`/`[ci skip]`/`[skip actions]` subjects are never selected. - [x] REQ-2: Equal-priority ties pick the newest commit. - [x] Unit tests cover both; 100% coverage maintained.