Skip to main content

Route A Phase II — the phrase-grouper re-gate overturns STAY (2026-06-07)

The Phase I baseline measured the opt-in joint-decode path against argmax and came back with a hard STAY: joint decodingjoint decodingA decode strategy where the neural model's proposals and rule-based solver's output are reconciled into a single parse tree. Formerly the default (Route A Phase II), now retired in favor of argmax after it was found to break the street+house_number geocode precondition. won big on the German city-statedual-role placeA place that is two placetypes at once — Berlin as both a city and a state, Washington DC as city and district. Resolved using the coincident-roles relation plus hierarchy completion. collision but tanked native-order multi-word localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. by 16–34%, so we shelved the default flip behind a phrase-grouper rebuild (#425). This is the re-gate after that rebuild. The verdict flips.

Verdict: the gate passes on all six locales. Joint-decode beats argmax everywhere, with per-field regression under the strict 0.5% bar.

Same harness (scripts/eval/joint-vs-argmax.ts, v0.9.4 modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.', warmed + alternated latency), same OpenAddressesOpenAddresses (OA). A global open aggregation of address points collected from many official sources. A primary source of component-supervised training data outside proprietary registries. samples, same argmax baseline — only the joint path changed. The argmax column is byte-identical to PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). I, which is the control that proves the movement is real and not a baseline shift.

localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.argmax locjoint locΔ locregressedimprovedlatency p99 ×
DE international (city-statedual-role placeA place that is two placetypes at once — Berlin as both a city and a state, Washington DC as city and district. Resolved using the coincident-roles relation plus hierarchy completion. collision)72.2%97.2%+25.0pp0.2%25.2%0.59
US (native)98.8%99.4%+0.6pp0.0%0.8%1.57
FR (native)97.5%100.0%+2.5pp0.0%2.5%0.57
NL (native)99.5%100.0%+0.5pp0.3%0.5%1.09
IT (native)84.8%99.8%+15.0pp0.0%15.0%0.83
ES (native)84.0%99.0%+15.0pp0.3%15.5%0.55

Compare the PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). I regression rates — NL 16.0%, IT 26.0%, ES 34.0% — against these: 0.3%, 0.0%, 0.3%. Every localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. now clears the ≤0.5% per-field-regression gate, joint beats argmax on all six (four of them at ≥99.8% localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.), and the improvements dwarf the residual regressions. Latency stays at or under 1× p99 on four localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. because the joint path produces cleaner trees with less downstream churn.

These are the numbers after the residual tail was chased down (see "Closing the tail" below). The first cut of this work landed every localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. netneural networkA model made of layers of simple numeric units whose connection strengths (weights) are learned from data. The transformer encoder at Mailwoman's core is a neural network.-positive but left IT at 1.3% and ES at 2.8% — above the bar; four small structural fixes took them the rest of the way.

Why — three fixes, one root cause

The PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). I post-mortem blamed proposal coveragecoverageThe fraction of a population or region for which a data source has real, non-placeholder entries — e.g. 47% rooftop coverage on Texas addresses. Distinct from accuracy on the rows that are present.: "the reconciler falls back to single-tokentokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words. spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. when proposals don't cover the multi-word component." That was half right. Maturing the phrase grouperphrase grouperStage 2.7 of the runtime pipeline: proposes coherent input units (street phrase, locality phrase, postcode, etc.) with structural kind hypotheses. Decouples boundary discovery from type classification so the classifier answers 'what type?' not 'where?' to propose multi-word spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. (Reggio nell'Emilia, Las Palmas de Gran Canaria) was necessary, but on its own it barely moved the aggregate — the proposals existed and the reconciler still fragmented. Digging into the live beam turned up two more mechanisms behind the same symptom, and all three had to land together.

  1. The phrase grouperphrase grouperStage 2.7 of the runtime pipeline: proposes coherent input units (street phrase, locality phrase, postcode, etc.) with structural kind hypotheses. Decouples boundary discovery from type classification so the classifier answers 'what type?' not 'where?' couldn't see multi-word localities. scoreLocalityPhrase walked a run of capitalized tokenstokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words. and stopped dead at the first lowercase one, so place-name connectives (de, in, nell'Emilia, aan den) ended the spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree.. Worse, in OpenAddressesOpenAddresses (OA). A global open aggregation of address points collected from many official sources. A primary source of component-supervised training data outside proprietary registries.' all-caps international data every short place word — SAN, DI, DEL — matches the 2-3-uppercase regionregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality.-abbreviation shape, so the headattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. of SAN NAZARIO got skipped as if it were a US stateregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality.. The walk now bridges a bounded set of place-name particles and apostrophe-fused names, and a regionregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality.-abbreviation-shaped tokentokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words. that headsattention headOne of several parallel attention computations in a layer, each free to focus on a different kind of relationship between tokens. Their outputs are concatenated — 'multi-head attention'. Mailwoman uses 4 heads. a multi-word place is allowed to start a localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy..

  2. The grouper-auditgrouper-auditA validation pass checking that phrase-grouper spans are internally consistent — no overlaps, no contradictions with BIO structural rules. Audit errors must be zero on a shipping model. ignored the classifier. Once the reconciler picked street="Trento" over Via Trento, the word Via was left orphaned. The post-reconcile audit, whose job is to rescue spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' couldn't type, saw an uncovered LOCALITY_PHRASE proposal for Via and promoted it to a locality node — burying the real trailing citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy., which is why Via Trento, …, SORBOLO came out with localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. Via. The classifier had typed that spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. street:0.73 all along. The audit now takes the classifier's per-spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. verdict for orphaned spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. and only falls back to the structural phrase kindphrase kindThe structural category a phrase-grouper proposal carries — NUMERIC, STREET_PHRASE, LOCALITY_PHRASE, REGION_ABBREVIATION, POSTCODE, VENUE_PHRASE, HYPHENATED_COMPOUND — a 'where, not what' hypothesis. when the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' abstained. This single fix took IT from 68.5% to 93.5%.

  3. Romance streetsstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. lead with their type. scoreStreetPhrase was suffix-only — it found Main Street by walking left from Street. Italian and Spanish put the type first (Via Trento, Calle Mayor, Largo Millefiori), so the rule never fired and the leading Via/Calle stayed a capitalized first-segmentsegmentA punctuation-bounded chunk of the normalized input — the comma-separated parts of 'Portland, OR' — used to give downstream stages structural context. word the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. rule happily proposed. We taught the grouper a bounded set of Romance streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-type prefixes — streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-types only, deliberately excluding the ambiguous area words like Polígono, Urbanización, and Lugar that legitimately serve as localities. That carried ES from 89.5% to 94.3% and cleaned up the IT tail.

The through-line: the joint path was being asked to type spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. the rule layerlayerOne transformer block — attention plus a feed-forward network, with normalization and residual connections — applied to every position. Stacking layers lets the model build up richer representations; Mailwoman's encoder has 6. couldn't describe and the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' hadn't seen, and the audit was papering over both with its most confident-looking guess. Give the grouper the vocabularyvocabularyThe fixed set of tokens a tokenizer can produce. Mailwoman's SentencePiece vocabulary is tens of thousands of subword pieces, with byte fallback for anything outside it. and let the audit defer to the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.', and the fragmentation evaporates.

Closing the tail

The three fixes above cleared the catastrophe but left IT at 1.3% and ES at 2.8%, above the gate. Dumping those rows showed two more shapes, and a fourth structural fix per shape took every localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. under 0.5%.

  1. The audit injected a second localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.. On a Romance streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. like Via Francesca Nord, the OOD modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' itself mistypes the streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.-name word Francesca as a localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.; the reconciler orphans it and the audit — correctly deferring to the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' now — injects locality="Francesca". The real trailing citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. was still in the tree, but decodeAsJSON reads the earlier-positioned spurious one. The audit now refuses to inject a second singleton-tag node (locality/region/postcode/country) when the reconciler already produced one. Joint-path only; the argmax default stays byte-stable. This is what carried IT to 99.8%.

  2. The modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' tags a trailing citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. as a postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.. Facing the postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-then-citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. order, the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' puts Toulouse (postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.:0.77, localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.:0.06) and Sena (postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.:0.53) in the postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. slot, so the localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy. drops entirely. But Toulouse has no digit, and postcodespostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. contain a digit in every localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. we handle — so the spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree.-logitlogitA raw, unnormalized per-label score the model outputs before softmax. Priors and biases are added in logit space, then softmax turns logits into probabilities. aggregation now drops the postcode and house_number candidates for any digit-less spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree., and the reconciler picks the real component. That alone recovered eight French cities and most of the Spanish tail.

  3. Accented capitals weren't proper nouns. startsCapitalized tested /^[A-Z]/, so Évellys and Étagnac — leading É — were invisible to the grouper, never proposed, never recovered. Making it Unicode-aware (\p{Lu}) brought FR to a clean 100%. The lone holdout is La Florida, where the modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.''s Florida → region prior is strong enough to win the slot outright; one row, and a modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' problem, not a rule one.

What this means for the plan

  • The flip is now justified by the gate, not just the accuracy. The original bar wanted ≤0.5% per-field regression with non-negative accuracy. Every localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. clears it: DE 0.2%, US 0.0%, FR 0.0%, NL 0.3%, IT 0.0%, ES 0.3% — and joint beats argmax everywhere, by +25pp on the German collision and +15pp on IT/ES. FR's old 2.0% churn, which PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). I treated as a noise floor, turned out to be the digit-less-postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. and accented-capital bugs; it's gone.
  • JUST-FLIP is alive and clean. The German city-statedual-role placeA place that is two placetypes at once — Berlin as both a city and a state, Washington DC as city and district. Resolved using the coincident-roles relation plus hierarchy completion. recovery the dual-role work ships is matched by joint decodingjoint decodingA decode strategy where the neural model's proposals and rule-based solver's output are reconciled into a single parse tree. Formerly the default (Route A Phase II), now retired in favor of argmax after it was found to break the street+house_number geocode precondition. doing it in-modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.', and now without collateral on any native-order localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for..
  • The flip shipped. Joint-decode is now the default decode path (#427): jointReconcile defaults to true, and jointReconcile: false (or the deprecated forceJointReconcile: false) forces the legacy argmax sort. The full unitunitA subdivision of a building — apartment, suite, floor — that refines a street address. Mailwoman's unit component; a designator plus identifier forms a subpremise. suite (1660 tests) and the integration suite (439 tests) pass on the flip. Callers without a phrase grouperphrase grouperStage 2.7 of the runtime pipeline: proposes coherent input units (street phrase, locality phrase, postcode, etc.) with structural kind hypotheses. Decouples boundary discovery from type classification so the classifier answers 'what type?' not 'where?' or a parseWithLogits classifier fall back to argmax automatically, so the change reaches only the joint-capable path it was measured on.

So PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). II did its job and then some. The question PhasephaseA milestone in the implementation plan (Foundation, Corpus, Training, Integration, and forward-looking phases). Distinct from stage (runtime pipeline) and tier (model vocabulary). I left open — "can the phrase grouperphrase grouperStage 2.7 of the runtime pipeline: proposes coherent input units (street phrase, locality phrase, postcode, etc.) with structural kind hypotheses. Decouples boundary discovery from type classification so the classifier answers 'what type?' not 'where?' ever cover multi-word spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. well enough to flip?" — has a measured yes, and the residual is a single modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.'-prior row, not a 34% cliff.

Harness: scripts/eval/joint-vs-argmax.ts (regression rows dumped via MW_DUMP_REGRESSIONS=1). Per-localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. JSON under docs/articles/evals/data/.