fix(templates): dial the number the sheet printed, not one like it - #659
Merged
Merged
Conversation
…ble one The rule that a printed telephone number and the number a device dials are different strings was written three times — ContactUri in the CV presets, InvoiceUri in the invoice presets, ProposalUri in the proposal presets — and where the three overlapped they were byte-identical, down to the regex and its comment. They are now one helper, core.identity.ContactUri, beside the contact-block and link records it serves: tel, telLink, mailLink, webLink, channelLink. Twenty-three preset files call it and the three copies are gone. It is public because the three families are three packages and a helper shared between them cannot be package-private. It is not marked experimental, because the shape is not a guess: three independent implementations had already agreed on it. Every method answers null rather than throwing, which the proposal copy had already learned and the other two had not: a notice, a name or a line of prose can reach a channel field, DocumentLinkOptions refuses a string that is not a URI, and a contact line is not the place to find that out. Nothing renders differently. A link annotation is not ink, so every pixel baseline in the suite passes untouched — the reactor gate ran the visual tests and moved no baseline. Tests: the CV suite's ContactUriTest moves to the shared package and gains what the other two copies contributed — an address, a site with and without a scheme, a channel read from its own shape, a site carrying digits that is not mistaken for a number, and prose in a channel field losing its link rather than the page. Ten cases. Reactor gate green, 1238 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A printed telephone number and the number a device dials are different strings. That conversion had been given one home, core.identity.ContactUri, but thirteen presets still carried their own private copy of it, written inline rather than named, and five of the copies did not drop the parenthesised trunk prefix. A sheet printing +44 (0)20 7946 0832 linked tel:+4402079460832 -- a number that reaches nobody from abroad -- in CharcoalGold, NavySidebar, ProfessionalSidebar and SerifHeadline, and ConsultingInvoice was further out still: its copy removed spaces and nothing else, so the printed brackets went into the target and the link was not a dialable number at all. All thirteen are gone. The other eight were already producing the right target, in eight separate places -- four spelling the regex out inline and four naming a constant for it -- and that duplication is as much what this removes as the five that got it wrong. The same sweep removes three copies of the scheme-prefixing rule for a printed website, which ContactUri gains as web: the target form of webLink, the way tel is of telLink. The Consulting closing moves to telLink at the same time. It hands its phone field straight to a link constructor, and a contact line reading "ask reception" carries no digits: the old copy made a junk target out of it, the target form answers null, and only the link form turns that into no link rather than a page that refuses to compose. Nothing on any page moves. A link annotation is not ink, and no fixture prints a trunk prefix, so no pixel baseline and no layout snapshot changes; what changes is where the link goes when a caller's own number carries one. Tests: CvPresetDialTargetTest asks all ten promoted CV designs the same question -- render a contact block whose number carries a trunk prefix, read the tel: targets back out of the file. This is the check the private copies never had: two designs had a test naming a trunk prefix and both handled one, while the other eight asserted their dial target with a number carrying none, so every copy agreed with its own test and four still built a target no caller could reach. Proved fails-closed by removing the trunk-prefix rule from ContactUri and watching all ten go red. ConsultingInvoiceSmokeTest asks the same of the invoice design, giving the masthead and the closing prose different numbers so neither site can answer for the other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DemchaAV
changed the base branch from
chore/one-contact-uri
to
feature/template-promotion
September 7, 2026 07:33
… refactor/contact-uri-sweep # Conflicts: # CHANGELOG.md # knowledge/api/templates.json # knowledge/api/templates.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on
chore/one-contact-uri(#658) — merge that first.Why
#658 gave the rule one home. It did not find all the places that had it.
The rule is that a printed telephone number and the number a device dials are
different strings. #658 collapsed three named helper classes; thirteen presets
were still carrying the same rule written inline, where a search for the class
names could not see it. Five of the thirteen did not drop the parenthesised
trunk prefix:
CharcoalGold,NavySidebar,ProfessionalSidebar,SerifHeadline+44 (0)20 7946 0832tel:+4402079460832tel:+442079460832ConsultingInvoice+44 (0)20 7946 0832tel:+44(0)2079460832tel:+442079460832The first four kept the trunk zero, which a caller abroad omits — the target
reaches nobody.
ConsultingInvoiceremoved spaces and nothing else, so theprinted brackets went into the target and it was not a dialable number at all.
One printed number, five different answers, decided by which design its owner
picked.
What
All thirteen copies are gone. The other eight were already producing the right
target, in eight separate places — four spelling the regex out inline, four
naming a constant for it — and that duplication is as much what this removes as
the five that got it wrong.
The same sweep removes three copies of the scheme-prefixing rule for a printed
website.
ContactUrigainsweb: the target form ofwebLink, the waytelis of
telLink. Two call sites take a plainString, sowebLinkcould notserve them.
The Consulting closing moves from the target form to
telLink. It hands itsphone field straight to a link constructor, and a contact line reading
"ask reception" carries no digits: the old copy made a junk target out of it,
the target form answers
null, and only the link form turns that into no linkrather than a page that refuses to compose. Every other rewritten site was
already null-tolerant.
Nothing on any page moves. A link annotation is not ink, and no fixture
prints a trunk prefix, so no pixel baseline and no layout snapshot changes.
What changes is where the link goes when a caller's own number carries one.
Tests
CvPresetDialTargetTestasks all ten promoted CV designs the same question:render a contact block whose number carries a trunk prefix, read the
tel:targets back out of the file.
This is the check the private copies never had. Two designs had a test naming a
trunk prefix and both handled one; the other eight asserted their dial target
with a number carrying none. So every copy agreed with its own test, and four
still built a target no caller could reach. Proved fails-closed by removing the
trunk-prefix rule from
ContactUriand watching all ten go red.ConsultingInvoiceSmokeTestasks the same of the invoice design that wasfurthest out, giving the masthead and the closing prose different numbers so
that neither site can answer for the other.
Reactor gate green, 1249 tests, no baseline moved; javadoc gate green; API
surface regenerated in the same change.