Skip to content

Should the suffix separator be derived from the comma the writer typed, rather than from segment shape? #437

Description

@derek73

The suffix view space-joins two adjacent SUFFIX tokens when the continuation carries the stable "joined" tag, and comma-joins them otherwise. Which tokens get the tag is currently decided by reasoning about segment shape: tail-by-index (tail_start = 1 after a suffix comma, 2 after a family comma), ORed since #429 with a content predicate, and gated per piece by whether the piece lands in SUFFIX.

That is an indirect way to ask a question the input answers directly: did the writer put a comma between these two words?

The proposal

Derive the entry boundary from the written text — two adjacent SUFFIX tokens render ", "-separated iff a comma stands between their spans, and space-joined otherwise.

Simulated over 1175 corpus names, this reproduces every shape the current machinery gets right, including the two regressions found in review of #429:

input today comma-derived
Smith, MD PhD MD PhD MD PhD
Smith, MD, PhD MD, PhD MD, PhD
Smith, MD Dr. PhD MD PhD MD PhD
Smith Jr., Mr. Jr. Jr., Jr. Jr., Jr.
Smith, Ph. D. Jr. Ph. D. Jr. Ph. D. Jr.
Doe,, Jr., Smith, V MD

It also dissolves two asymmetries the current design records as deliberate:

14 of 1175 corpus names move, so this is a behavior change needing a release-log classification and rules across three ledger tiers.

Why it is a simplification, not just a different rule

The interleaved-title stickiness and the glue-across-a-written-comma bug that review caught are not two rules needing reconciliation. They are the same question — "is there a comma in the gap?" — asked indirectly, which is why the first draft got it wrong in both directions at once. Deriving it directly deletes one_entry, in_entry, entry_open, the tail/seg_cores split, and group's only reason to read _segment_holds_no_name.

Two constraints, both confirmed

It must run after assign. It needs roles: a blanket span rule would join A and B in John A B Smith into one middle_list element. _post_rules already declares pieces and structure as inputs, so a tail pass there is precedented.

The delimiter-core case needs an explicit boundary mark. Smith, MD - PhD - FACS under extra_suffix_delimiters renders PhD, FACS today and would wrongly space-join, because the core is dropped before the render sees it — two of the 14 movers are this. The honest shape is mechanisms.md#MARK-DONT-STRIP: mark the entry boundary at the drop site, where the fact is known, and let the render join everything the writer did not separate. That inverts today's polarity — currently a continuation is marked, from a guess about segment shape — and puts each mark at its decision site.

Keep the "joined" tag as the recorded form. _facade.__setstate__ synthesises span-less Tokens and marks continuations "joined"; the tag is the persisted representation of an entry, and it is what makes list → pickle → list the identity. A render-time span scan cannot work on an unpickled name. So the tag stays and is derived once and recorded, not replaced.

Do not make the tag role-aware. One tag carries two unrelated jobs and only one is suffix-specific. Within a piece it is genuinely role-blind and correct for every role — Smith, Ph. D. Smith routes the merged credential to GIVEN and gives first_list == ['Ph. D.']. Only the between-piece half is a suffix concept, and it is the half this proposal removes.

Cost

Roughly 35 lines out, 20 in, plus 14 corpus movers across three ledger tiers and a release-log entry. PR-sized on its own. Closes #436 if it lands.

Came out of the cleanup review of #435.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions