Consonance only on the ending, not a buried stress

meticulous (me-TIC-ulous, IH-K under -ulous) was consonance-rhyming
quick. Consonance now fires only when the stressed vowel is within one
syllable of the word end — people/sleep still rhymes, meticulous/quick
doesn't. Gated the projection side too, so a long-rime group stops
advertising a misleading stressed-syllable consonance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 17:42:13 -04:00
parent 5f22e28721
commit 23cc6434f7
2 changed files with 23 additions and 4 deletions
+10 -4
View File
@@ -212,10 +212,11 @@ def founding_projections(key: str) -> dict[str, str]:
vowels = [p for p in ph if p in ARPA_VOWELS]
if vowels:
out["slant"] = "v:" + " ".join(vowels)
if len(ph) > 1 and ph[1] not in ARPA_VOWELS:
out["vc"] = "c:" + ph[0] + " " + _coda_class(ph[1])
else:
out["vc"] = "c:" + ph[0]
if len(vowels) <= 2: # consonance only for short rimes
if len(ph) > 1 and ph[1] not in ARPA_VOWELS:
out["vc"] = "c:" + ph[0] + " " + _coda_class(ph[1])
else:
out["vc"] = "c:" + ph[0]
mk = _multi_key(vowels)
if mk:
out["multi"] = mk
@@ -336,6 +337,11 @@ def vc_key(word: str) -> str | None:
tail = pl[start:]
if not tail or not tail[0][-1].isdigit():
return None
# consonance is an ENDING sound: allow at most one trailing syllable
# (people/sleep), but not a stress buried deep in a long word
# (meticulous's IH-K under -ulous shouldn't consonance-rhyme quick)
if sum(p[-1].isdigit() for p in tail) > 2:
return None
key = DIGITS.sub("", tail[0])
if len(tail) > 1:
key += " " + _coda_class(tail[1])
+13
View File
@@ -754,3 +754,16 @@ def test_near_miss_radar():
res = analyze(Draft(text=text))
near = {res["lines"][t["l"]][t["s"]:t["e"]].lower() for t in res["near"]}
assert near == {"hand", "bond"}
def test_consonance_only_on_final_syllable():
# me-TIC-ulous's mid-word IH-K must not consonance-rhyme quick
text = "a maverick imagine that I travel quick\nso meticulous and ridiculous"
res = analyze(Draft(text=text))
from collections import defaultdict
bg = defaultdict(set)
for t in res["tokens"]:
bg[t["g"]].add(res["lines"][t["l"]][t["s"]:t["e"]].lower())
assert not any({"meticulous", "quick"} <= s for s in bg.values())
# bliss/exist (final-syllable consonance) still works
group_with("bliss whisps in the nights exist", "bliss", "exist")