Skip to content

Resolve change-log revert by category slug, not display name#39

Merged
jeherve merged 1 commit into
m:mainfrom
jeherve:fix/wpcom-change-log-slug-revert
Jun 3, 2026
Merged

Resolve change-log revert by category slug, not display name#39
jeherve merged 1 commit into
m:mainfrom
jeherve:fix/wpcom-change-log-slug-revert

Conversation

@jeherve

@jeherve jeherve commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

The wpcom change log stored category identities as display names joined with |, and inverse-replay resolved them back via the first name match. Two real-world failures fell out of that.

WordPress allows two categories to share a display name under different slugs. Reverting picked whichever same-named category was first in the cache, silently reassigning the post to the wrong one, on the undo path.

A category name containing | (e.g. Tips | Tricks) was split into phantom names on revert, 404ing and producing a partial restore.

Display names are also a poor revert key because a category deleted by the apply run and recreated during restore keeps its slug but gets a new term ID, so the slug is the only identifier that stays stable across a restore.

This adds old_category_slugs / new_category_slugs columns to the change log and resolves the SET_CATS inverse by slug, with a name-based fallback for logs written before the columns existed (or by the WP-CLI script). I updated the AGENTS.md schema and the parse_change_log docs, and added regression tests for the duplicate-name and |-in-name reverts.

I also confirmed it against a live Jetpack site: with two categories sharing the name "ZZ WP Dup" under different slugs, a logged change plus an inverse-replay restore put the post back on the exact original category by slug, not the same-named one.

Testing

  • python3 -m unittest discover tests — green
  • ruff check lib/ tests/ — clean

The wpcom change log stored category identities as display names joined
with '|', and inverse-replay resolved them back via the first name match.
Two real-world failures fell out of this:

- WordPress allows two categories to share a display name under different
  slugs. Reverting picked whichever same-named category was first in the
  cache, silently reassigning the post to the wrong one — on the undo path.
- A category name containing '|' (e.g. 'Tips | Tricks') was split into
  phantom names on revert, 404ing and producing a partial restore.

Display names are also a poor revert key because a category deleted by the
apply run and recreated during restore keeps its slug but gets a new term
ID, so neither the name nor the original ID is reliable — the slug is.

Add old_category_slugs / new_category_slugs columns to the change log and
resolve the SET_CATS inverse by slug (via _lookup_category_by_slug), with a
name-based fallback for logs written before the columns existed or by the
WP-CLI script. Update the AGENTS.md schema and parse_change_log docs. Add
regression tests for duplicate names and '|'-in-name reverts.
@jeherve jeherve self-assigned this Jun 3, 2026
@jeherve jeherve merged commit 33f7937 into m:main Jun 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant