From 676a596a66eaa5cb5e980589efb169ca11911448 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 8 Jun 2026 02:58:03 -0400 Subject: [PATCH] Weak endings need a full vowel; trailing sibilant is transparent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit middle / unavoidable shared only a schwa+L tail — the weak-ending rule firing on a reduced vowel. Weak endings now require a full final vowel (infancy/see on IY stays). Surfaced that swimmers' plural -s blocked its coda from nesting with finisher; a trailing sibilant is inflection, so it's stripped from the coda tag — Wayne's chain stays whole, garbage (JH) still stays out. Co-Authored-By: Claude Opus 4.8 (1M context) --- app.py | 6 ++++++ tests/test_rhymes.py | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/app.py b/app.py index 554f1ed..0b9f17b 100644 --- a/app.py +++ b/app.py @@ -344,6 +344,8 @@ def _final_coda_tag(pl: list[str]) -> str: if p[-1].isdigit(): last = i coda = "".join(_coda_class(DIGITS.sub("", p)) for p in pl[last + 1:]) + if coda.endswith("S"): + coda = coda[:-1] # trailing plural/3rd-person sibilant is transparent return coda or "." @@ -398,6 +400,10 @@ def weak_end_key(word: str) -> str | None: for i in range(len(pl) - 1, -1, -1): if pl[i][-1].isdigit(): syl = [DIGITS.sub("", p) for p in pl[i:]] + if syl[0] in REDUCED: + return None # a bare schwa tail (-le, -able) rhymes + # everything; weak endings need a full final vowel + # (infancy/see on IY, not middle/unavoidable on AH-L) out = [syl[0]] + [_coda_class(c) for c in syl[1:]] return "w:" + " ".join(out) return None diff --git a/tests/test_rhymes.py b/tests/test_rhymes.py index 9f0b51d..4d4399f 100644 --- a/tests/test_rhymes.py +++ b/tests/test_rhymes.py @@ -714,3 +714,12 @@ def test_garbage_javascript_dont_attach(): bg[t["g"]].add(res["lines"][t["l"]][t["s"]:t["e"]].lower()) dfam = next(s for s in bg.values() if "dollar" in s) assert "garbage" not in dfam and "javascript" not in dfam + + +def test_weak_ending_needs_a_full_vowel(): + # middle and unavoidable share only a schwa+L tail — too weak to rhyme + text = ("Wednesday has given up and admitted it's the middle\n" + "slightly apologetic and entirely unavoidable") + assert "middle" not in highlighted(text) + # but a full-vowel feminine ending still pairs (infancy/see on IY) + group_with("all I can see\nin my infancy", "see", "infancy")