Daily Word: grow the hopeful answer pool + lock it with a validation test

Per Codex. Pool grown 51/44 → 115/104 hopeful answers (5/6 letter) via the
agreed workflow: LLM proposes themed candidates → code filters to the bundled
guess dictionary (length/alpha/dedup) → human spot-check prunes tone-drift
("growl", "plain", "color"…). ~3.5-month runway before repeats per variant.

test_wordpool.py locks the invariant in CI: every answer must be lowercase
alpha, correct length, unique, and present in words-5/6.json — so no future
addition can become an unguessable puzzle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-10 17:34:44 -04:00
parent 215a5c4d64
commit a7fb8e5739
2 changed files with 149 additions and 5 deletions
+129 -5
View File
@@ -1,101 +1,225 @@
{
"5": [
"adore",
"agile",
"alive",
"amaze",
"ample",
"amply",
"angel",
"arise",
"aroma",
"award",
"aware",
"beams",
"bless",
"bliss",
"bloom",
"blush",
"bonus",
"brave",
"brisk",
"charm",
"cheer",
"chime",
"clean",
"clear",
"climb",
"craft",
"daisy",
"dance",
"dawns",
"dream",
"drift",
"eager",
"earth",
"elate",
"enjoy",
"faith",
"fancy",
"favor",
"feast",
"fresh",
"gifts",
"glade",
"gleam",
"glide",
"glory",
"glows",
"grace",
"grand",
"green",
"grins",
"happy",
"heals",
"heart",
"honor",
"hopes",
"humor",
"ideal",
"jewel",
"jolly",
"laugh",
"learn",
"light",
"lucky",
"magic",
"maple",
"mends",
"mercy",
"merit",
"merry",
"mirth",
"music",
"noble",
"oasis",
"peace",
"plant",
"pluck",
"poise",
"pride",
"prize",
"proud",
"quiet",
"reach",
"quilt",
"ready",
"relax",
"renew",
"river",
"savor",
"share",
"shine",
"smile",
"space",
"spark",
"stars",
"still",
"sunny",
"sweet",
"swift",
"teach",
"thank",
"treat",
"trust",
"truth",
"tulip",
"unity",
"value",
"vital"
"vigor",
"vital",
"vivid",
"water",
"winds",
"wings",
"witty",
"worth",
"youth",
"yummy",
"zesty"
],
"6": [
"adored",
"ascend",
"aspire",
"beauty",
"bestow",
"better",
"bouncy",
"breeze",
"bright",
"credit",
"bubbly",
"calmly",
"caring",
"cheery",
"cherub",
"chirpy",
"clever",
"dainty",
"dazzle",
"devote",
"divine",
"dreamy",
"earthy",
"esteem",
"family",
"flower",
"fondly",
"forest",
"friend",
"garden",
"gather",
"genial",
"gentle",
"giving",
"glossy",
"golden",
"growth",
"health",
"heaven",
"honest",
"joyful",
"joyous",
"kindly",
"laurel",
"lively",
"lovely",
"loving",
"mellow",
"mended",
"morale",
"nature",
"nestle",
"nicely",
"nuzzle",
"please",
"plenty",
"praise",
"pretty",
"prized",
"purify",
"purity",
"quaint",
"reborn",
"refine",
"relish",
"renews",
"repair",
"rescue",
"revive",
"reward",
"savior",
"savory",
"secure",
"serene",
"settle",
"simple",
"smiled",
"smooth",
"soothe",
"spirit",
"spring",
"sprout",
"steady",
"strong",
"summit",
"superb",
"supple",
"tender",
"thanks",
"thrive",
"unfold",
"united",
"uplift",
"valued",
"velvet",
"verity",
"vision",
"voyage",
"warmly",
"warmth",
"willow",
"wisdom",
"wonder"
"wonder",
"zenith",
"zephyr"
]
}
+20
View File
@@ -0,0 +1,20 @@
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
def test_wordpool_answers_are_valid_and_guessable():
"""Every daily-word answer must be lowercase alpha, the right length, unique,
and present in the bundled guess dictionary — so no answer is ever unguessable.
Locks the 'code disposes' invariant against future pool additions."""
pool = json.loads((ROOT / "goodnews" / "data" / "wordpool.json").read_text())
for variant, n in (("5", 5), ("6", 6)):
dictwords = set(json.loads((ROOT / "frontend" / "static" / f"words-{n}.json").read_text()))
answers = pool[variant]
assert answers, f"{variant}-letter pool is empty"
assert len(answers) == len(set(answers)), f"{variant}-letter pool has duplicates"
for w in answers:
assert isinstance(w, str) and w.isalpha() and w.islower(), f"bad token: {w!r}"
assert len(w) == n, f"{w!r} is not {n} letters"
assert w in dictwords, f"{w!r} not in the guess dictionary → would be unguessable"