Replace hardcoded phoneme-map.ts with a declarative normalize rule phase (phases/normalize.yaml) that runs first in the pipeline, with citations on every mapping.
public/rules/phases/normalize.yaml— Three splice rules: AX->AH, NX->NG, WH->W
public/rules/pipeline.yaml— Added normalize phase before postlexicalpublic/rules/frontend.yaml— Added normalize.yaml includesrc/g2p/syllabify.ts— Added AX to VOWELS set (so Hunnicutt stress counts schwas)src/g2p/lts-engine.ts— Removed mapElovitzToQlatt import/call, inlined prosodic marker filtertest/g2p-lts-engine.test.ts— Removed mapElovitzToQlatt tests, updated expectations (AX no longer mapped to AH at LTS level)
src/g2p/phoneme-map.ts— Responsibilities reassigned to normalize.yaml + inline filter
string(int(current.stress))failed — cel-js doesn't haveint()builtin- Used ternary chain instead:
current.stress == 1 ? "AH1" : (current.stress == 2 ? "AH2" : "AH0")
pronounce()now returns raw Elovitz symbols (AX, NX, WH) instead of mapped (AH, NG, W)- Full TTS pipeline output unchanged — normalize phase maps them before downstream rules fire
- G2P benchmark accuracy: "the" now shows as mismatch at pronounce() level (AX vs AH), but pipeline produces correct AH
- All G2P tests: 178/178 pass (6/6 files)
- Full suite: 10 files failed, 17 tests failed — ALL pre-existing (voice quality snapshots, schema validation)
- No regressions from these changes