Skip to content

Merge keys that normalize alike under one name instead of swapping them [patch] - #165

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/deterministic-canonical-name-131
Sep 29, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/deterministic-canonical-name-131

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Under Aggressive and Maximum merging, keys that normalize alike now merge. related: [a] and page_related: [b] become a single related holding both lists. Before this, each value was written under the other key's name and nothing was merged.

Cause

FindBasicCanonicalName mapped each key to another key in its equivalence class, so related went to page_related and page_related went to related. MergeSimilarProperties then saw two one-key groups, and MergeArrayValues wrote each list under the other key's name.

Change

  • One name per equivalence class. Every key that normalizes alike maps to the same name, whatever the key order: a known property first, then the shortest key, then an ordinal tie-break. When the chosen key has a known mapping, that mapping is used.
  • The partial-match pass chooses between a pair by the same rule, so two keys that contain each other can no longer swap either.
  • Maximum no longer lets the semantic pass move the class's chosen key onto some other key after the basic pass has settled it.
  • Safety net, as the triage suggested: a group with one original key keeps its own name rather than taking another existing key's. A lone known key such as keywords is still standardized when no other key is involved.

Tests

EquivalentKeyMergeTests adds nine cases:

  • the list case and the scalar case, under Aggressive and Maximum, with the keys in both orders;

  • the issue's end-to-end input through CombineFrontmatter(..., AsIs, AsIs, Aggressive).

  • Without the fix: all nine fail. I checked by reverting PropertyMerger.cs.

  • With the fix: all pass, and so does the full suite (206 tests).

Fixes #131

🤖 Generated with Claude Code

https://claude.ai/code/session_015BJVibRvmTotkqEGp3695R


Generated by Claude Code

…em [patch]

FindBasicCanonicalName mapped each key in a normalize-alike class to
another key in the class, so related went to page_related and
page_related to related. Aggressive and Maximum then wrote each value
under the other key's name and merged nothing.

Every key in the class now maps to one name, chosen independently of key
order: a known property first, then the shortest key, then ordinally. The
partial-match pass picks between a pair the same way, Maximum no longer
moves the chosen key elsewhere, and a key left alone in its group keeps
its own name rather than taking another key's.

Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015BJVibRvmTotkqEGp3695R
@sonarqubecloud

Copy link
Copy Markdown

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.

Aggressive/Maximum merging swaps the values of two keys that normalize alike (e.g. related / page_related) instead of merging them

1 participant