Removed reports that documented work already shipped and not tied to
any archived plan dir:
- docs-manager-260420-2151-documentation-audit.md (one-off doc audit)
- researcher-260421-0845-leaguepedia-api-verification.md (lolschedule research)
- researcher-260421-0909-leaguepedia-auth-token.md (lolschedule research)
The lolschedule module is in src/modules/lolschedule/ but never had a
discrete plan dir. Findings from the leaguepedia reports are reflected
in the live module code; the markdown is no longer load-bearing.
plans/reports/ now contains only the 6 Atlas migration reports for the
active plan.
Six research reports were sitting in plans/reports/ but tied to
already-archived plans. Move each under the matching archived plan
dir so the archive is self-contained and plans/reports/ only holds
reports for in-flight or unarchived work.
Moves
- researcher-260422-2329-semantle-api-alternatives.md
- researcher-260423-0025-bge-m3-cosine-calibration.md
- researcher-260423-1110-vietnamese-embeddings-semantle.md
→ plans/archive/260422-2128-semantle-module/reports/
- researcher-260424-2215-loldle-ability-splash-modes.md
- researcher-260424-2215-loldle-emoji-and-modes-overview.md
- researcher-260424-2215-loldle-quote-mode.md
→ plans/archive/260424-2215-loldle-new-modes/reports/ (new dir)
Stays in plans/reports/
- 6 Atlas migration reports (active plan)
- docs-manager-260420-2151-documentation-audit.md (general audit, no
discrete plan home)
- researcher-260421-0845-leaguepedia-api-verification.md
- researcher-260421-0909-leaguepedia-auth-token.md
(lolschedule research; no archived lolschedule plan exists)
No code changes.
Three feature plans (semantle, twentyq, loldle-new-modes) are
status:completed in their frontmatter and the corresponding modules
exist in src/modules/. Move them to plans/archive/ to keep the active
plans/ dir focused on in-flight work.
Atlas migration (260425-1945-mongodb-atlas-migration/plan.md): bump
status from `planning` to `code-complete` and annotate each phase row
with its commit SHA + whether operator action is still pending. Plan
stays in active plans/ until cutover lands or the Upstash standby
(phase-07-alt-pivot.md) executes.
No code changes. Tests, lint, register:dry unaffected (733 passing).
Operator-facing summary in the plan.md status note: 8 phases of
implementation are committed on dev (6f0b5ff..e2e3112). Outstanding
operator work: Atlas provisioning, real-cluster smoke tests,
backfill runs, soak, cutover stages, Stage 3 code cleanup.
Closes deferred phases 04 + 05 of loldle-new-modes plan.
- loldle-ability: 5 guesses, DDragon ability icon as photo. State pins
slot (P/Q/W/E/R) so the same icon shows every turn. Abilities pulled
from DDragon per-champion — same source loldle.net uses at runtime.
- loldle-splash: 4 guesses, random skin splash as photo. Skin pool
scraped from loldle.net bundle (var Ad=[…] — 172 champs × 1939 skins,
non-chroma, matches their splash mode exactly). URLs from Riot
DDragon CDN (no version segment, stable across patches).
- fetch-ddragon-data.js: extended to write all four JSONs in one run.
Shares a single DDragon per-champion fetch cycle (concurrency 10).
- Credits loldle.net + Riot Games in all loldle-family READMEs.
19 new tests (503 total). Lint clean. register:dry reports 12 loldle_*
commands with no conflicts.
Ship two new loldle-family modules mirroring loldle.net's non-classic
modes. Text-only MVP (ability/splash phases stay deferred).
- loldle-emoji: 5 guesses, emoji-sequence clue. Pool derived algorithmically
from classic's champions.json metadata (species/region/resource mapping
table) since loldle.net's bundle has no static emoji pool.
- loldle-quote: 6 guesses, lore-blurb clue. Pool seeded from Data Dragon
champion title + first lore sentence; champion name redacted to ___.
- scripts/fetch-ddragon-data.js: single generator for both JSONs.
- src/util/normalize-name.js: shared lookup helper; loldle/lookup.js
refactored to import it.
35 new tests (484 total passing). Lint clean.
BGE embeddings occupy a narrow cone in vector space, so raw cosine of
two unrelated words already sits at ~0.40-0.55. Displaying `raw * 100`
made every random guess read as 40-70% warm, which defeated the warmth
UX.
format.js now applies a normalized sigmoid (FLOOR 0.40, CENTER 0.60,
SCALE 8) to remap raw cosine → displayed 0-100. Unrelated pairs drop
to ≤30, loose relation lands around 40-55, clear synonyms hit 85+, and
exact match stays at 100. Emoji buckets were rebased onto the calibrated
score; formatWarmth lost its sign column (calibrated output is always
non-negative).
render.js rounds once and feeds the integer to both formatWarmth and
warmthEmoji so the display value and bucket stay in sync.
Constants are empirical — retune if swapping to a non-BGE model.
ConceptNet (api.conceptnet.io) was returning sustained 502s, breaking
every guess with an "Upstream hiccup" reply. Replace with env.AI.run
on @cf/baai/bge-small-en-v1.5 and score guesses by computing cosine
similarity locally against the target vector.
The local google-10k wordlist doubles as the in/out-of-vocabulary set,
so OOV detection is an O(1) Set.has() with no upstream call. The
similarity() response shape is unchanged, so handlers/render/state
stay as-is.
Free on the Workers Free plan: 10k Neurons/day cap, ~0.0037 Neurons
per 2-word guess → ~2.7M guesses/day headroom for this bot.
Telegram commands /semantle, /semantle_new, /semantle_giveup, /semantle_stats.
Round starts with /random pick from hosted word2sim; each guess scored via
/similarity. Unlimited guesses; solve on case-insensitive exact match.
New env var WORD2SIM_API_URL (wrangler.toml, .env.deploy). Includes
module README and 90 unit tests covering api-client, state, format,
render, and handlers.
Captures the feasibility check and auth-token investigation that led to
the lolschedule module: confirmed endpoint + table + field set, and
documented why caching beats token-based rate-limit mitigation on Fandom.
Paper trading system with 5 commands (trade_topup, trade_buy,
trade_sell, trade_convert, trade_stats). Supports VN stocks via TCBS,
crypto via CoinGecko, forex via ER-API, and gold via PAX Gold proxy.
Per-user portfolio stored in KV with 60s price caching. 54 new tests.
grammY-based bot with a module plugin system loaded from the MODULES env
var. Three command visibility levels (public/protected/private) share a
unified command namespace with conflict detection at registry build.
- 4 initial modules (util, wordle, loldle, misc); util fully implemented,
others are stubs proving the plugin system end-to-end
- util: /info (chat/thread/sender ids) + /help (pure renderer over the
registry, HTML parse mode, escapes user-influenced strings)
- KVStore interface with CFKVStore and a per-module prefixing factory;
getJSON/putJSON convenience helpers; other backends drop in via one file
- Webhook at POST /webhook with secret-token validation via grammY's
webhookCallback; no admin HTTP surface
- Post-deploy register script (npm run deploy = wrangler deploy && node
--env-file=.env.deploy scripts/register.js) for setWebhook and
setMyCommands; --dry-run flag for preview
- 56 vitest unit tests across 7 suites covering registry, db wrapper,
dispatcher, help renderer, validators, and HTML escaper
- biome for lint + format; phased implementation plan under plans/