60db Logo
  • Engineering

Speak brand names and URLs reliably

Keep canonical brands and URLs intact while constructing safe speech projections and reviewing what callers actually understand.

Editorial date
Reading time
26 min
A retained canonical URL card projects into a separate spoken rendering

TL;DR: Preserve the original brand or URL and derive a separate speech representation using reviewed, scoped rules. Construct SSML from trusted elements with caller content serialized as text, and evaluate canonical preservation separately from what listeners understand.


A caller asks for a link. The agent speaks a friendlier version, then stores that spoken version as the destination. A capitalized path, encoded slash or query value disappears even though the response sounds fluent. The rendering step has changed the object it was supposed to describe.

Start with two explicit fields: the canonical value supplied by the owning application and the speech projection derived from it. Keep the relationship traceable. A projection may help a listener, but spoken sound cannot reconstruct every character of an arbitrary URL.

Python's URL parsing documentation warns that parsing does not validate a URL and describes control-character stripping. This is why the artifact below checks its narrow input grammar before parsing and preserves the original string independently. The regression testing method provides the wider discipline for keeping those invariants stable.

The standard-library example constructs synthetic speech plans. It fetches no URL, loads no external lexicon, generates no audio and reports no pronunciation or comprehension measurement for 60db Agent. Its useful guarantee is that supported rendering operations preserve their original value and cannot turn caller-supplied text into executable SSML elements.

Table of contents

  1. Keep the canonical value separate
  2. Give URL components explicit rules
  3. Scope and review brand aliases
  4. Separate text escaping from markup permission
  5. Build a bounded speech-plan constructor
  6. Review intelligibility with the right evidence
  7. Bind rendering to current task state
  8. Diagnose failures without rewriting the reference
  9. Frequently asked questions
  10. Ship one inspectable rendering rule

Keep the canonical value separate

A canonical value belongs to the application that owns the object. For a URL, that can be the exact destination selected by an authorized workflow. For a brand, it can be a catalog identifier and its approved display label. A speech layer should receive that value without acquiring authority to rewrite it.

The speech projection is a presentation artifact. It can spell characters, use an approved alias, or supply a phoneme under a documented voice contract. Store its policy identity and scope beside the original so another engineer can explain which operation produced it.

Do not call the projection reversible. Several written strings can produce similar sound, punctuation can be difficult to distinguish, and a synthesis engine can interpret the same text differently under another voice. Retaining the original is the mechanism that preserves the value; listening cannot recover a missing source record.

The identifier-capture boundary makes a related distinction between a candidate sequence and a confirmed task value. A successful presentation is one stage in a workflow, not permission to replace the object that other stages depend on.

A useful record has an original value, field kind, rendering policy, locale, trusted context and derived speech text or SSML. Include the dictionary snapshot when an alias is used. Keep generated audio identity separately if the plan is later synthesized.

Choose what counts as original at the input boundary. This example receives Python strings and preserves their code points; it does not claim to preserve arbitrary incoming HTTP bytes before decoding. A transport adapter must retain those bytes separately if the reproduction requirement includes encoding behavior.

Use whole-field transformations where possible. A brand field with one approved alias has a clearer contract than a general paragraph in which every matching substring is replaced. The context-sensitive abbreviation method narrows the harder span-selection problem when embedded tokens need different treatment.

Keep display formatting separate too. A UI can truncate a long link visually while preserving the destination in its own accessible field. Speech output should not inherit the truncated display string and present it as the complete destination. The task must decide whether to speak, spell, clarify or send the exact link through an approved written channel.

An early test can compare the input string with the constructor's returned canonical field. Include query case, percent escapes and punctuation. This deterministic equality check is useful before any listener is recruited, because it can identify corruption that a fluent audio sample would not reveal.

The original canonical URL remains unchanged while an approved rendering rule creates a separate speech projection

Give URL components explicit rules

The URI generic syntax standard separates scheme, authority, path, query and fragment. Their comparison and normalization rules differ. A rule appropriate for the scheme or host must not be applied globally to a path or query value.

Preserve the submitted value before calling a convenience parser. The Python documentation describes removal of newline, carriage-return and tab characters, and leading control or space characters under its documented behavior. If exact input preservation matters, a parser result is not a substitute for the original.

The reference constructor uses a deliberately small policy: printable ASCII HTTPS URLs with a DNS-shaped authority, no user information, no port and valid percent-escape syntax. It rejects everything else as unsupported. That is an offline rendering subset, not a general internet URL validator or an authorization rule for network access.

Do not decode %2F merely to make a path easier to read. A percent-encoded delimiter can have different meaning from a literal delimiter. Preserve the exact source and use an approved speaking or written-delivery policy when a listener needs to understand the distinction.

Query strings require the same care. Turning a query into a dictionary and serializing it again can lose information relevant to an exact-string contract, such as repeated parameters or representation choices. The small example does not parse query parameters at all because it does not need to modify them.

A URL can also contain information that should not be spoken publicly. Task ownership must decide whether a destination is appropriate to disclose before it reaches the renderer. Rejecting user information in the teaching subset does not establish that every accepted query is safe to announce or share.

Reserved example domains are suitable for public fixtures. Use them instead of real customer links, signed access tokens or private hosts. A synthetic link can reproduce case and escaping behavior without exposing a live account or an operational route.

The constructor never follows the accepted URL. A parsed destination is data. Fetching it would introduce a different contract involving authorization, redirects, network boundaries and resource limits. Keep that action out of an offline speech example unless it is explicitly required and independently designed.

Order IDs and email capture has a related literal-preservation problem. Each identifier owner must define its own rules; a successful URL policy should not become a universal cleanup function for every string that contains punctuation.

The figure separates components to make that ownership visible. It does not propose that all URLs should be spoken component by component. Listener needs, privacy and task context still determine whether literal speech is useful.

Separate URL compartments preserve scheme, host, path, query and fragment rules without universal lowercasing

Define unsupported input as a first-class result in the surrounding adapter. The constructor raises a validation error for its unsupported URL grammar and returns an explicit unsupported-voice disposition for a documented rendering mismatch. Those are different recovery questions: one concerns the value format, and the other concerns the requested presentation capability.

A caller repair should provide a new value rather than asking the parser to guess the intended correction. For example, a missing scheme might be clarified by the application before presentation. The speech constructor should not prepend a scheme while returning a field labeled unchanged canonical value.

Keep raw input available when a parser rejects it. The error message can identify the policy boundary without echoing a private destination into public logs. A controlled diagnostic record can retain the exact synthetic or authorized string for reproduction while user-facing language asks for the necessary clarification.

The teaching authority grammar is intentionally limited and does not establish DNS existence or the validity of every path character under a broader standard. If a deployment needs international hosts, ports or another scheme, add a documented policy and corresponding tests. Do not infer that a broad parser's acceptance extends this example's guarantees.

Treat query and fragment contents as opaque for this contract. That keeps repeated parameters, empty values and percent-encoding representation separate from the optional decision to speak a shorter explanation. A shorter spoken explanation can refer to the destination, but it should never be persisted as the destination itself.

Scope and review brand aliases

An alias is a reviewed presentation rule for an exact label under a declared scope. Keep locale and context in the key. A short string can denote a brand in one catalog and an unrelated literal identifier in another workflow.

An approved alias should record its source, review revision and target synthesis conditions. The pronunciation dictionary release method binds those values to immutable content instead of letting a shared mutable mapping change active behavior unnoticed.

Unknown labels should retain a literal presentation or enter clarification under the interaction policy. Do not generate a plausible pronunciation and label it approved because the model returned confidently. A suggestion awaiting review is a different record from a released pronunciation rule.

A brand owner can provide useful pronunciation guidance, but the application still needs to check intelligibility for its selected voice and intended interaction. A text alias that looks reasonable does not prove that a particular synthesized recording is easy to distinguish over the deployed channel.

Treat an alias collision as an explicit error. If two approved entries use the same label, locale and context but request different speech text, the constructor should reject the ambiguity. Selecting whichever mapping entry happened to be loaded last would make review and reproduction unreliable.

The example rejects duplicate keys even when the supplied output happens to be identical. That keeps the admitted schema simple: one owner supplies one entry for each key. A larger dictionary system can define a separate exact-duplicate policy, but it must not confuse duplicate delivery with a new approval.

Surname clarification needs a stricter identity boundary than a catalog brand. A person's preferred pronunciation is not a global alias for everyone sharing a spelling. Do not reuse a brand dictionary as a person-resolution service.

Preserve the original label during aliasing. The spoken phrase can differ from what appears in a receipt or written catalog. When a caller corrects the label, use the task's repair process rather than updating the canonical field as an incidental side effect of pronunciation review.

A good initial release contains a few high-value reviewed labels and explicit unsupported cases. Measure the review work and unclear cases before expanding coverage. Cost per verified outcome helps distinguish a useful task improvement from simply generating more synthesized text.

The Pronunciation Lexicon Specification provides a standardized representation for graphemes, aliases and phonemes. The tiny tuple format in this artifact is an application teaching schema, not a claim to implement every PLS feature or a provider's complete lexicon behavior.

Review source text and output text as different fields. A catalog can intentionally display a stylized label while the approved alias uses a clearer phrase. Retain that distinction in fixtures so a later cleanup cannot accidentally replace the display label with the pronunciation aid.

Do not use a dictionary update as an implicit task correction. If the application selected the wrong brand record, changing its spoken alias does not fix record selection. Diagnose the entity boundary and approval separately, then review pronunciation for the corrected value under its own scope.

A local alias lookup can be deterministic while acoustic output still varies with the selected voice. Keep the target voice and locale in the later audio review packet. If the voice changes, previous listening evidence should be reconsidered under the release process rather than attached automatically to a new synthesis condition.

Separate text escaping from markup permission

SSML 1.1 defines elements for controlling speech, including aliases, phonemes and interpretation hints. Actual support belongs to the target engine and voice. A standard's existence does not prove that a provider accepts every element or interprets it the way your task requires.

The safe construction boundary is straightforward: application code selects a small trusted element set, and caller text becomes text content. An input that looks like a closing tag remains literal content. It must not become a new element merely because it contains familiar SSML syntax.

ElementTree can construct XML trees without concatenating caller text into markup. That is different from parsing an arbitrary caller-supplied XML document. This example accepts no caller-selected tag names, arbitrary attributes, external audio references or lexicon URIs.

Escaping and permission answer different questions. Escaping preserves a literal ampersand inside text. An element allowlist determines whether an audio element is allowed at all. Correct escaping does not grant an external-resource fetch, and a trusted element name does not make its attributes automatically appropriate.

The example also checks its supported XML character subset. An XML serializer is not a blanket validator for every Python string. It rejects unsupported controls, isolated surrogates and carriage returns rather than silently deleting or normalizing them while claiming an exact text round trip.

Keep encoding layers separate. A string becomes XML text, then a provider request payload may encode that XML as a JSON string and UTF-8 bytes. Do not URL-encode the SSML document as an improvised solution to an XML problem. Preserve the payload at each boundary when diagnosing corruption.

A historical IBM Watson curl question illustrates confusion among transport and markup representations. Its question supplies a real diagnostic symptom, not a current provider recipe or proof that all voices share the same behavior.

Google's SSML documentation describes its supported subset and examples of characters and aliases. The constructor accepts a trusted capability flag for its character mode, but an adapter must establish that flag from the exact documented provider configuration. A local flag is not an acoustic measurement.

A check in the following table means sufficient for the named narrow property; a cross means separate evidence is required. These are construction criteria, not measured pronunciation scores.

Evidence Canonical string retained Caller text stays text Listener understood destination
Input equals returned canonical field ✓ Exact supported string ✗ No markup proof ✗ No listening evidence
Trusted tree and parse-round-trip fixture ✗ Separate source check ✓ Within character subset ✗ No listening evidence
Target voice documents character mode ✗ No source check ✗ Still need safe construction ✗ Support is not comprehension
Reviewed captured audio and task response ✗ Keep source evidence too ✗ Keep tree evidence too ✓ Only within reviewed task boundary

Caller text passes through an XML serializer into literal content rather than becoming trusted markup

Build a bounded speech-plan constructor

The artifact produces an immutable plan for a whole URL field or brand label. It preserves the canonical string, derives speech text, and serializes one trusted SSML structure. It is intentionally not a URL crawler, speech SDK, automatic pronunciation reviewer or complete international-domain validator.

Its trusted inputs are field kind, locale, context, reviewed alias entries and the selected voice's declared character-mode capability. Caller text is untrusted data. A production adapter must establish those control values and keep any authorization decision outside this pure presentation function.

Save the complete fence as speech_plan.py and run it with Python 3.12 or newer. All examples use synthetic labels and reserved domains. The printed example is an inspectable plan, not generated audio or a claim that the destination was understood.

from dataclasses import dataclass, FrozenInstanceError
import re
from urllib.parse import urlsplit
from xml.etree import ElementTree as ET

NS = "http://www.w3.org/2001/10/synthesis"

def text(value):
    if type(value) is not str or not value:
        raise ValueError("nonempty text required")
    return value

def xml_text(value):
    text(value)
    for c in value:
        n = ord(c)
        if not (n in (9, 10) or 0x20 <= n <= 0xD7FF or
                0xE000 <= n <= 0xFFFD or 0x10000 <= n <= 0x10FFFF):
            raise ValueError("outside supported XML text subset")
    return value

def url_literal(value):
    text(value)
    if any(not 0x21 <= ord(c) <= 0x7E for c in value):
        raise ValueError("printable ASCII URL required before parsing")
    if re.search(r"%(?![0-9A-Fa-f]{2})", value):
        raise ValueError("invalid percent escape")
    p = urlsplit(value)
    if p.scheme != "https" or not re.fullmatch(
            r"[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+", p.netloc):
        raise ValueError("unsupported URL authority or scheme")
    return value  # never reconstruct the original from parsed components

@dataclass(frozen=True)
class Plan:
    canonical: str
    spoken: str
    ssml: str
    disposition: str

def make_plan(value, kind, locale, context, entries=(), mode="literal",
              supports_characters=False):
    value, context = text(value), text(context)
    if type(supports_characters) is not bool:
        raise ValueError("trusted boolean capability required")
    if not re.fullmatch(r"[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*", text(locale)):
        raise ValueError("locale outside supported tag subset")
    if kind not in {"url", "brand"} or mode not in {"literal", "characters"}:
        raise ValueError("unsupported rendering policy")
    aliases = {}
    for row in entries:
        if type(row) not in (list, tuple) or len(row) != 4:
            raise ValueError("alias entry shape required")
        label, language, scope, alias = (xml_text(x) for x in row)
        key = (label, language, scope)
        if key in aliases:
            raise ValueError("duplicate scoped alias")
        aliases[key] = alias
    canonical = url_literal(value) if kind == "url" else xml_text(value)
    key = (canonical, locale, context)
    matched = kind == "brand" and key in aliases
    spoken = aliases[key] if matched else canonical
    disposition = "reviewed_alias" if matched else "literal"
    if mode == "characters" and not supports_characters:
        return Plan(canonical, spoken, "", "unsupported_voice")
    root = ET.Element("speak", {"xmlns": NS, "version": "1.1", "xml:lang": locale})
    node = root if mode == "literal" else ET.SubElement(
        root, "say-as", {"interpret-as": "characters"})
    node.text = xml_text(spoken)
    return Plan(canonical, spoken, ET.tostring(root, encoding="unicode"), disposition)

url = "https://example.com/CaseSensitive/%2F?q=A&q=B#Part"
p = make_plan(url, "url", "en-US", "synthetic-link")
assert p.canonical == url and p.spoken == url
assert "".join(ET.fromstring(p.ssml).itertext()) == url
for bad in (" https://example.com", "https://exa\nmple.com", "https://example.com/\tX",
            "http://example.com", "https://user@example.com", "https://example.com/%QZ"):
    try: make_plan(bad, "url", "en-US", "synthetic-link")
    except ValueError: pass
    else: raise AssertionError("unsupported URL accepted")
for raw in ("A & B < C", "literal &amp; text", '</speak><audio src="https://example.com"/>'):
    plan = make_plan(raw, "brand", "en-US", "synthetic-catalog")
    tree = ET.fromstring(plan.ssml)
    assert len(tree) == 0 and tree.text == raw
entries = [["SyntheticBrand", "en-US", "catalog-A", "reviewed synthetic label"]]
a = make_plan("SyntheticBrand", "brand", "en-US", "catalog-A", entries)
entries[0][3] = "mutated"
assert a.spoken == "reviewed synthetic label" and a.canonical == "SyntheticBrand"
same = [("SameText", "en-US", "catalog-A", "SameText")]
assert make_plan("SameText", "brand", "en-US", "catalog-A", same).disposition == "reviewed_alias"
assert make_plan("SyntheticBrand", "brand", "en-US", "other", entries).disposition == "literal"
assert make_plan(url, "url", "en-US", "link", mode="characters").disposition == "unsupported_voice"
c = make_plan(url, "url", "en-US", "link", mode="characters", supports_characters=True)
assert ET.fromstring(c.ssml)[0].tag == "{" + NS + "}say-as"
for raw in ("bad\x00text", "bad\rtext", "bad\ud800text"):
    try: make_plan(raw, "brand", "en-US", "catalog")
    except ValueError: pass
    else: raise AssertionError("unsupported XML character accepted")
try: make_plan("x", "brand", "en-US", "catalog", [("x", "en-US", "catalog", "a")] * 2)
except ValueError: pass
else: raise AssertionError("duplicate alias accepted")
try: p.canonical = "changed"
except FrozenInstanceError: pass
else: raise AssertionError("plan rebinding accepted")
print("Synthetic plan:", p)
print("Synthetic construction fixtures passed; no network or synthesis calls.")

The URL helper preserves the original before parsing and never rebuilds it from components. Its authority regex is a teaching subset, not proof of DNS assignment, destination safety or brand ownership. Unsupported values require a declared alternative route rather than a silent parser repair.

The XML fixtures parse only the program's generated output and assert the literal text. They do not accept caller XML for interpretation. A literal &amp; must survive as those original characters after parsing; pre-escaping it would change the intended data and fail that test.

The alias entries are copied into local string keys and values, and the returned plan contains only immutable strings. The mutation fixture changes the input list after construction without changing the earlier plan. The frozen property check protects the returned canonical value from rebinding.

Alias disposition records exact reviewed-rule membership, not whether the reviewed rendering differs textually from the canonical label. An equal-text reviewed alias therefore remains distinguishable from an unknown-label literal fallback.

The program emits its example plan as promised. That output can be saved as a synthetic regression artifact. It is not a production request, and the constructor does not claim that a provider accepts its SSML without an adapter's documented compatibility check.

Review intelligibility with the right evidence

A text test establishes text behavior. To assess speech, capture the actual synthesis output under the selected voice, locale, configuration and dictionary snapshot. Keep its digest and recording format beside the source plan so later review refers to the same sound.

Use a task-based listening question. Can a reviewer distinguish the intended brand or identify the exact link components the interaction requires? A natural-sounding sample can still omit a material delimiter or make similar labels difficult to distinguish.

Confirmation prosody concerns that discriminating function. Keep pronunciation preference separate from exact-value verification. A listener may prefer a smoother brand alias while needing a slower character sequence for an identifier.

Record listener instructions and permitted context. If the expected URL is visible during the trial, the result measures a different task from a caller reconstructing it without written support. Preserve which aid was available rather than attributing every successful response to the audio alone.

Do not invent a comprehension score from the constructor's assertions. The code generated no recordings and recruited no listeners. A real report needs its actual task population, review process, uncertain responses and exclusions. Cohort evaluation boundaries help avoid treating repeated clips as independent participants.

A long destination may be unsuitable for speech-only delivery. The workflow can offer an authorized written route, a short approved reference or clarification. That decision should preserve the canonical destination and should not create an unreviewed shortened URL by guessing a convenient path.

Speaking-rate changes can alter timing without proving clearer comprehension. If rate is changed during evaluation, record it as another condition. Avoid combining an alias change and a rate change while claiming the result isolates pronunciation.

Inspect the capture path before blaming the alias. A clipped streaming boundary can remove the final character or punctuation cue. Document sample rate, channel count, codec, decoder and capture point for any actual acoustic trial.

Supported reviewed aliases, documented interpretation, literal fallback, and unsupported voice conditions remain explicit alternatives

A listening review should record the question before playback. Asking whether a label sounds acceptable is different from asking which of two synthetic catalog entries a listener understood. Choose the question that matches the interaction and preserve the permitted visual or conversational context.

Include an uncertain response option where the protocol requires it. Forcing a reviewer to pick an answer can conceal ambiguity. Record disagreement and missing responses rather than converting them into a fabricated quality score or choosing the response preferred by the implementation owner.

Keep synthesis artifacts versioned. If the source plan is unchanged but a provider voice revision changes the audio, the new recording needs its own identity. Conversely, if the alias changes while the old recording remains cached, the source plan and audio no longer describe the same trial.

A replay should preserve those identities through export and review. The audio filename alone is not enough if a new file can overwrite it. Store a digest and the actual configuration mapping so another reviewer can identify which sound was presented without relying on an engineer's recollection.

Do not extend the review beyond its population. A few synthetic examples can expose a concrete ambiguity and guide another iteration. They do not establish how all callers will understand every brand, URL grammar or acoustic channel associated with a language label.

Bind rendering to current task state

The constructor is pure and has no live authorization lifecycle. A surrounding workflow must bind the selected canonical value and rendering policy to the current task revision. A plan produced earlier should remain historical evidence if the caller repairs the underlying value.

Spoken self-corrections show why a fluent partial interpretation cannot freeze intent. If a corrected destination arrives while synthesis is pending, the old audio belongs to the old proposal even if its bytes are received after the correction.

A confirmation request needs its own immutable identity. An exact retry preserves that identity and payload; a new request after repair needs a new identity. Do not reuse an old confirmation event and then treat a conflict as evidence that the caller refused the corrected value.

A qualified affirmative can also revise material content. The "yes, but" repair method prevents approval of an old URL or label merely because the caller began with an affirmative word. Interpret the whole response under the task policy.

If the surrounding controller has deadlines, enforce them during policy queries and replacement admission as well as after awaited work. An idle task does not remain valid simply because no callback arrived. Terminal shutdown semantics separates retained evidence from current permission.

After an asynchronous synthesis or delivery step, check generation, current value, dictionary snapshot, cancellation barrier and age before admitting the output. An obsolete generation should not expire a newer one or create a completion claim for a repaired task. This is an adapter responsibility, not a hidden guarantee of the pure constructor.

Caches need the same scope. The voice cache-key method explains why language, policy and ownership can affect output reuse. Include the rendering or dictionary identity when it changes the intended sound.

Keep delivery claims precise. Playback acknowledgments can support endpoint observations, but they do not establish that the caller understood a link. A task response or explicit confirmation remains another evidence boundary.

Before connecting the pure constructor to a live workflow, write down which component owns each control field. The task owner selects the canonical value, the policy owner selects supported presentation modes, and the dictionary publisher provides reviewed scoped aliases. Caller content supplies data rather than those control decisions.

If those roles share one mutable object, preserve an owned snapshot at admission. The pure constructor returns immutable strings, but an asynchronous adapter can still reread a changed source mapping after approval. Capture the selected values and revisions before waiting, then compare current authority before local submission.

An exact cached plan can remain useful as historical evidence after cancellation. It should not become a new active response merely because the cache lookup succeeded. A fresh task or repaired value needs the workflow's current identity and approval boundary, even when the resulting text happens to match an older plan.

Diagnose failures without rewriting the reference

When speech is wrong, preserve the original value and the entire derived plan before editing a rule. Compare the source, alias selection, XML tree, provider payload and captured audio in order. A defect can arise at any one of those boundaries.

If the canonical value changed, inspect transformations before synthesis. Global lowercasing, percent decoding, parser reconstruction and display truncation are plausible operations to audit. Keep a minimal synthetic reproducer that shows which exact characters changed.

If text became markup, inspect construction and transport layers. A historical Google TTS question reports a rejected request and includes discussion of encoding. Use the actual symptom as a debugging question; do not assert that one answer proves the root cause of every rejected request.

If a reviewed alias was not selected, inspect the complete key and dictionary snapshot. Locale or context mismatch can correctly produce a literal fallback. A change to the dictionary publisher should not be disguised as a generic improvement to recognition or language support.

If XML and provider payload are correct but the audio is unclear, preserve the voice and synthesis configuration for review. The voice-consistency corpus separates output properties that a single quality label would hide.

If a caller reports an incorrect action after hearing the label, inspect the owning task receipt. A correct pronunciation does not prove the correct entity or destination was selected. Outcome metrics keeps those failure owners distinct.

Keep the reproduction packet appropriately controlled. A signed link or private query value can reveal access even when a name is removed. Use synthetic reserved-domain fixtures for public reports and retain sensitive originals only under the authorized access and retention policy.

The next change should target the observed boundary. Fix canonical preservation, alias scope, XML construction, compatibility or listening uncertainty separately where possible. Re-run the negative cases that protect neighboring behavior before releasing the revised rule.

Deterministic canonical equality, XML parsing, and injection fixtures remain separate from listening review

Before release, have another engineer reconstruct one plan from only its retained inputs. They should identify the canonical value, field kind, locale, context, alias snapshot and selected presentation mode without relying on an unstored default. If a control value exists only in a wrapper's current configuration, capture it in the reproduction packet.

Repeat that audit for an unsupported case. The record should explain whether the value grammar failed, a reviewed alias was absent or the selected voice did not support the requested mode. Those distinctions guide a concrete next step while keeping unknown pronunciation and missing listening evidence honest.


Frequently asked questions

Why separate canonical text from spoken text?

The owning application needs an exact value while a listener may need another presentation. Preserve both and record the rendering rule. The spoken form cannot reconstruct every original character, so retaining the source rather than claiming reversibility is what prevents presentation changes from corrupting the task.

Should a URL be lowercased before speech?

Do not lowercase the stored URL globally. Component rules differ, and path or query values can carry material case distinctions. If a speaking policy changes presentation, keep that projection separate and verify the exact canonical value independently of how a voice pronounces it.

Which URL components have different case rules?

The URI standard distinguishes scheme and host normalization from other components such as path and query. Use the owning URL contract rather than applying one text rule everywhere. This example preserves the complete original string and performs no component normalization for storage.

How should query strings be spoken?

Choose a reviewed interaction policy based on the task, privacy and listener needs. Long or sensitive queries may require an approved written channel. The example preserves the query as literal text and does not claim that this alone makes an arbitrary query intelligible over a phone call.

Can percent encoding be expanded freely?

No. Decoding a reserved delimiter can alter how a URL is interpreted. Preserve the original encoding and define a separate presentation policy when necessary. The fixture includes an encoded slash specifically to prevent a helpful-looking transform from silently changing the canonical destination.

What does a speech plan preserve?

It preserves the supported original string, derived speech text, serialized SSML and explicit disposition. A production adapter should also bind policy, dictionary and voice identities. The plan does not prove synthesis, playback, comprehension, authorization or a successful business action.

When is a brand alias appropriate?

When a reviewed rule matches the exact label, locale and trusted context. Keep its source and release identity. Unknown or conflicting entries should remain literal or require clarification under the task policy rather than acquiring a guessed pronunciation labeled as approved evidence.

Who approves a pronunciation?

The application needs a declared review owner with appropriate source and listening evidence. A generated suggestion is not automatically approved. For personal names, the caller's preference requires person or session scope and remains separate from identity verification and permission to retain a durable hint.

How do I handle unknown brand names?

Use the declared literal or clarification behavior and preserve the original. A model-generated guess can enter a review queue if authorized, but it should not overwrite the source or become a released alias without review. Record uncertainty instead of treating every input as covered.

What is SSML injection?

It occurs when untrusted content becomes markup that controls synthesis rather than literal text. Construct trusted elements in code and serialize caller values as text. Do not parse arbitrary caller XML or accept caller-selected audio and lexicon references as an extension of a text field.

How should ampersands be escaped?

Let the XML serializer escape literal text once. A caller's literal entity-looking string must remain that original text after parsing the generated output. Pre-escaping before tree insertion can change the data, so test both ordinary ampersands and text such as a literal entity sequence.

Why build XML rather than concatenate strings?

A tree separates trusted structure from text values and handles serialization. It still needs an element and attribute policy plus a supported character boundary. The example permits only its fixed structure and rejects unsupported characters; it does not claim that any XML string is safe SSML.

Does SSML support vary by voice and vendor?

Use current documentation for the exact provider, endpoint and voice. A W3C element or a local compatibility flag does not establish universal support or intelligibility. Keep unsupported configurations explicit and review the actual captured output before making speech-quality claims.

Can browser TTS consume every SSML tag?

Do not assume that it can. Verify the actual browser and voice interface and keep that adapter contract separate from a hosted synthesis service. Historical community reports can identify questions to test, but they do not establish support across current browser versions and operating systems.

Should the example fetch a spoken URL?

No. The constructor is an offline representation function and treats the URL as data. Fetching introduces authorization and network behavior outside its scope. The same restriction applies to external audio and lexicon references: accepting text does not imply permission to retrieve another resource.

What should unsupported schemes or user information do?

The narrow example rejects them as unsupported rather than repairing or following them. A real application can define another authorized route if needed. A parser accepting a string is not enough to establish disclosure safety, destination validity or permission to make a network request.

How do I test canonical preservation?

Compare the original with the returned canonical field and include case, repeated query parameters, percent escapes and controls. Test rejection before parser stripping can conceal an invalid input. Do not rely on reconstructing a URL from parsed components when the contract promises the exact original string.

Can text tests prove intelligibility?

No. They establish deterministic construction properties for the tested inputs. Intelligibility requires actual captured audio, a declared task, appropriate reviewers and recorded responses. This article reports synthetic software fixtures and no listening score, recognition result or caller-comprehension measurement.

Which recordings need human review?

Review the actual output under the selected voice and task conditions when pronunciation or comprehension matters. Preserve source plan, audio identity and recording format. Qualified review should distinguish intended label recognition from aesthetic preference and retain disagreement instead of inventing an aggregate score.

When should a caller receive a written link instead?

When the approved interaction makes exact speech-only delivery impractical, ambiguous or inappropriate. Preserve the canonical destination and use an authorized written route. Sending a link still needs its own destination and delivery checks; it does not follow automatically from creating a speech projection.

Ship one inspectable rendering rule

Start with a supported synthetic URL and one scoped brand alias. Run the complete preservation, injection and ownership fixtures, then verify the documented target voice before capturing audio for review.

Keep the original, rendering policy and observed output together. That gives the next engineer a concrete way to distinguish a changed value from an unclear pronunciation, while keeping unsupported cases and missing listening evidence visible.