Skip to content

feat(tts): phone numbers as digits + the flatten keeps the pause (gh-#700, gh-#703) - #833

Merged
genwave-radio merged 5 commits into
mainfrom
tts/flatten-keeps-the-pause-465
Sep 23, 2026
Merged

genwave-radio merged 5 commits into
mainfrom
tts/flatten-keeps-the-pause-465

Conversation

@genwave-radio

Copy link
Copy Markdown
Collaborator

🎯 What

PR-2 of the launch-polish epic: STORY-464 (phone numbers are spoken as digits) + STORY-465 (the flatten keeps the pause). Built on PR-1 (#830, merged); four commits ahead of main.

Fixes #700, fixes #703.

🔬 Wire evidence (T548, dev station on the branch image)

STORY-464 AC3/AC4/AC6–AC8 and STORY-465 AC1–AC6 through POST /api/tts/normalize-preview on the deployed api (the one SpeechText.Normalize chokepoint every voice uses):

Input Spoken
Call 555-0142 today call five five five, zero one four two today
Call (812) 555-0199 now call eight one two, five five five, zero one nine nine now
Back in 1994 and 2026 back in 1994 and 2026
at 7:30 tonight at 7:30 tonight
over 1000 tracks over 1000 tracks
Tonight, on GenWave, the hits tonight, on genwave, the hits
Coming up: the news coming up, the news
Rock — and roll – tonight - late rock, and roll, tonight, late
Wait for it… now wait for it, now
Well, — well well, well
re-render the drive-time show re-render the drive-time show
AC/DC and Ke$ha play... now ac/dc and ke$ha play, now
Call us: 555-0142 call us, five five five, zero one four two
Coming up, [pause:1s] the news coming up, [pause:1s] the news

STORY-464 AC5 (every voice) — the same three-line spot rendered through POST /api/ads + /preview on the t545 image and again on the t547 image; the text Kokoro logged as its input:

t545: wire diner the late-night stop on route nine breakfast all night coffee always hot.
      call eight one two, five five five, zero one four two for a table or just walk in.
t547: wire diner, the late-night stop on route nine, breakfast all night, coffee, always hot.
      call eight one two, five five five, zero one four two for a table, or just walk in.

STORY-465 AC8/AC9 — a four-line spot (ANNOUNCER ×3, VOICE1) previewed with the same seed before and after T547: gaps 0.729 / 0.737 / 0.451 s → 0.332 / 0.334 / 0.451 s; the preview wav shrank 0.799 s against a predicted 0.799 s.

F198.2 re-render — after each api restart on the new MergePolicyVersion the booth log shows the evergreen lines re-rendering (five patter-aired rows in the first 40 s, AIR rows resuming within twenty minutes: first LeadIn at 20:30:57Z after the 20:12Z restart, 30 renders ahead of it).

STORY-465 AC10 (manual) — clip pairs for Dean's ear at ~/pace-ear-check/2026-09-22-flatten-pause/index.html (pause pair t545→t547, gap pair t546→t547, same script each).

Full solution (dotnet test GenWave.sln --filter "Category!=Integration", Host with MaxParallelThreads=3): 0 failed across all 9 projects (Host 3082 passed / 48 skipped, Tts 907 / 16 skipped). admin-ui untouched.

⚠️ Follow-ups (not fixed here)

  1. No spec runs AssembleCastAsync end to end with two consecutive same-tag lines; AC8 pins CrosstalkTimeline and the wire proof covers the assembler. A one-fact wiring spec would close that gap.
  2. Comma/ender adjacency (well,.) is deliberately not normalised; only a true trailing , collapses.
  3. STORY-464 AC2 lives in Architecture.Tests rather than Core.Tests: referencing Ads from Core.Tests makes the GenWave.Loudness namespace shadow the Loudness record there (CS0118). Noted in both spec headers.

GenWave.Core.PhoneShape holds the one NANP phone-shape regex (SPEC F197.1);
Ads.PhoneShapeCheck matches through it and keeps no regex of its own. The
pattern is byte-identical to the one Ads carried, so the 555 rule (F160.3)
and the owner-sponsor phone skip (F172.5) behave exactly as before.

STORY-464 AC1 (four shapes) is pinned in Core.Tests; AC2 (no \d{3} regex
literal anywhere in Ads) is a fitness law in Architecture.Tests — a
compiled-attribute scan plus a source-text scan — because referencing
GenWave.Ads from Core.Tests makes the GenWave.Loudness namespace shadow the
unqualified Loudness domain type there (CS0118).

Smoke on the deployed api: POST /api/ads refuses "812-0142" and
"812.301.0199" with the phone_shape violation and accepts "(812) 555-0199".
SpeechText.FlattenSegment runs a spoken-digit pass on the raw segment
before every prose pass: each GenWave.Core.PhoneShape match becomes its
digits spoken one by one, groups joined by a comma (SPEC F197.2). Years,
times, and counts never match the shape, so they pass through untouched
(F197.3). The prose passes moved into FlattenProse and run on the text
between matches, so the emitted comma survives ClauseMarkRx.

Story464 AC3-AC6 and AC8 green; AC7 ("7:30" unchanged) asserts the story
and stays skipped pending T546, which narrows the colon strip (F198).
MergePolicyVersion is untouched; T546 bumps it once for the branch.
LooseMarkRx keeps the comma the writer put there. A loose colon,
semicolon, spaced dash, or ellipsis folds to exactly one comma and runs
collapse to one (SPEC F198.1); in-word hyphens and an intra-digit colon
such as 7:30 are untouched. The comma-run collapse runs once over the
assembled segment so the space before a spoken phone number or a
markup token survives (F197.2 + F198.1).

TtsSegmentSource.MergePolicyVersion is now f97.4+gh541+gh703 (F198.2),
so every evergreen clip re-renders once after upgrade.

Story465 AC1-AC7 green plus three fragment-boundary pins; Story464 AC7
un-skipped. Specs that pinned a stripped comma or loose mark re-pinned
to the F198.1 output: Gh541, Gh491, Gh161, Story005, Story456,
Story185, Story186.
CrosstalkTimeline maps a transition's single seeded draw into
[0.20, 0.35] s when the two lines share a speaker, and keeps the
0.2-0.8 s range between different speakers (SPEC F198.3). One draw per
transition, in order, so flagging a transition never reshuffles later
jitter. Both assembler paths thread the per-transition flags through
MixAsync: crosstalk compares the speaker enum, cast lines compare the
tag ordinally.

Story465 AC8-AC9 green; Story327 call sites carry the new parameter with
their alternating scripts. Deployed proof: the same four-line spot
rendered 0.799 s shorter after the change, matching the timeline's
predicted delta to the millisecond.
@genwave-radio
genwave-radio merged commit c2faff9 into main Sep 23, 2026
11 checks passed
@genwave-radio
genwave-radio deleted the tts/flatten-keeps-the-pause-465 branch September 23, 2026 01:32
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

1 participant