Skip to content

[Vulcan] Preserve surname particles after given-name initials - #23

Merged
iliaal merged 1 commit into
masterfrom
vulcan/nameparser-initial-surname-particles-20261016
Oct 21, 2026
Merged

iliaal merged 1 commit into
masterfrom
vulcan/nameparser-initial-surname-particles-20261016

Conversation

@iliaal

@iliaal iliaal commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fix surname-particle binding when the given name has already been mapped to initials. J. van Gogh now produces first name J., surname van Gogh, and prefix van; previously it promoted van to the first name and left J. as a middle initial.

The default pipeline runs InitialMapper before LastnameMapper. The old particle gate only counted earlier raw tokens, overlooking a mapped initial.

  • Count a preceding nonempty GivenNamePart as additional evidence that a recognized particle belongs to the surname. Keep the existing protected raw-token hook and the adjacent-particle/surname-only rules.
  • Cover initial-only names, multiple initials, Unicode and uppercase particles, salutations, nicknames, credentials, comma paths, surname-first mode, and fresh/reused parsers in 20 parser cases.
  • Add 10 direct mapper cases for mapped given-name types, consumer subclasses, empty parts, and excluded decorations.
  • Record the installed behavior change in the changelog with a link to the regression cases.

Validation

On PHP 8.4.26:

  • Full PHPUnit suite: 1,366 tests, 3,890 assertions, passed
  • PHPStan level 9 and PHP 8.5 configuration: passed
  • PHP-CS-Fixer dry run and repository guards: passed
  • Actual revert check from the final tree: replacing only LastnameMapper.php with its base version makes 17 of the 30 new cases fail. Restoring the fix passes all 30 cases and 193 assertions, with both test files unchanged.

The sibling sweep found one production hasUnmappedPartsBefore() caller; the patch stays in that particle gate. Existing GivenNamePart consumers already require nonempty output. All factory-built surname mappers use the same implementation.

CI verified

CI run 38920253843 completed successfully for head ad1c24a25b5c493d683a3b66c9bbfd09389e468c:

  • PHP 8.3.35, 8.4.26 and 8.5.11: each passed 1,366 tests and 3,890 assertions
  • Composer audit: passed in all three runtime jobs
  • Static Analysis: level 9, empty-baseline guard, PHP 8.5 configuration and deprecated-call guard passed
  • Code Style and README check: passed

All five job logs were reviewed. The PR merge-ref tree equals the tested head tree. The workflow-file scan is path-filtered and does not apply to these four changed files.

Independent review found no blocker and passed 1,106 additional assertions for explicit outputs, language/configuration reuse, sparse input, empty mapped names and protected-hook semantics. Local runtime verification used PHP 8.4; the other runtime versions were verified in the linked CI run. No performance claim is made.

@iliaal
iliaal merged commit 612656f into master Oct 21, 2026
5 checks passed
@iliaal
iliaal deleted the vulcan/nameparser-initial-surname-particles-20261016 branch October 21, 2026 21:22
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