Skip to content

Commit 3153810

Browse files
hellpanderrrclaude
andcommitted
docs: session learnings — self-correcting notes section in CLAUDE.md
Traps that cost debugging time this session, recorded so they aren't repeated: wasmoon document-shim crash, regex char-class range bug in sanitize, attr(content) rendering vs textContent, app-ready waits in e2e, digit-bearing lexicon test words, IndexedDB bulk-write measurements, meta-written-last + visible background saves, git checkout staging. Plus a 2026-07-28 update to the WIP section (macronizer branch state, stash-apply conflict notes). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 7476f8b commit 3153810

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

wiktionary_pron/CLAUDE.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,33 @@ Two engines:
126126
- **Async yielding** during long operations: `await wait(1)` / `await new Promise(r => setTimeout(r, 0))` to keep the UI thread responsive.
127127
- **Multiple IPA values** for a word are stored in `all_values` HTML attribute and cycled on click.
128128

129+
## Self-correcting notes (mistakes made and fixed — don't repeat them)
130+
131+
Each of these cost real debugging time in past sessions. Check this list before "fixing" related symptoms.
132+
133+
**Testing traps**
134+
- **Never shim `document` in `scripts/tests/setup.cjs`** — wasmoon's Emscripten glue uses `typeof document` for environment detection and dies with "Invalid URL" under Node. Shim it per-test-file only in suites that don't load wasmoon (see `unit/lexicon_decode.test.js`).
135+
- **Lexicon test words must be letters only.** Every lookup path strips `[^\p{Letter}\p{Mark}-]` — synthetic words like `word000042` contain digits, get cleaned to `word`, and silently never match. Cost a failed "language isolation" test until spotted.
136+
- **Macronizer results have empty `textContent`** — words render via `<span class="ipa" content="...">` painted with CSS `attr(content)`. Assert the `content` attribute, not text. (Same idiom in the transcriber's line mode.)
137+
- **E2E must wait for `#lang` to be enabled before any interaction**`main.js` top-level-awaits the wasmoon engine; clicking earlier hits elements with no listeners attached. Symptom: clear/dark-mode/persistence tests fail with stale values.
138+
- **Browser Latin ≠ Node Latin**: the browser flow macronizes input first (provinciarum → prōvinciārum), so e2e IPA expectations carry length marks that the Node suite's don't.
139+
- **RU/UK stress-transfer skips multi-form dictionary entries by design** — test it with a single-form word (голова → голова́), not вода (record "во́да, вода́" has a comma → skipped).
140+
141+
**Code traps**
142+
- **Regex char classes with `-` between Unicode literals form ranges**: `[^\p{L}\p{M}'’-‿]` parsed `’-‿` as U+2019–U+203F and stripped ASCII hyphens from every word. Put `-` last in the class. (Was a live bug in `sanitize()` for years.)
143+
- **`#header > a > i` selects the HOME link's icon** — the dark-mode toggle on macronizer.html restyled the wrong button for this reason. Use `#dark_mode i`.
144+
- **Duplicated language lists in `main.js` drift**: `lang === "Lituanian"` (typo, missing h) appears in several copies of the multi-value language list — Lithuanian silently loses features in some modes. If touching those lists, extract one shared constant.
145+
146+
**IndexedDB performance (measured in Chromium, 100k rows)**
147+
- Row-per-entry `put()` with a secondary index is the killer: ~58s/100k. `durability: 'relaxed'` changes nothing (already default). Grouping by unique key: 1.8×. **Packing ~1000 rows per record: 20×** (2.8s/100k). This is why both the macronizer wordlist and the app lexicons use sorted range-chunk records.
148+
- **Structured-cloning big objects is the persist wall time** — storing each chunk's payload as one JSON string (parse on read) cut the French lexicon persist ~3× to ~11s.
149+
- **Write the meta record last** so an interrupted persist reads as unpopulated. And **show the user that the background save is running** — invisible saves get interrupted by reloads, which looks like "caching never works" (that exact bug report happened).
150+
151+
**Git traps (repo layout)**
152+
- `git checkout <branch> -- <file>` **stages** the restored file — follow with `git restore --staged` if you want it unstaged.
153+
- The git repo root is the parent directory; `.github/workflows/` and `.gitignore` live there, not here.
154+
- GitHub Pages deploys from `main` only — work on other branches is invisible in production until merged.
155+
129156
## Work-in-progress state (as of 2026-07-27)
130157

131158
Uncommitted local work was split into stashes on `main` (with a full backup on branch `wip-everything`):
@@ -138,3 +165,13 @@ Uncommitted local work was split into stashes on `main` (with a full backup on b
138165
| `utils-scripts-and-tests` | Python/CJS lexicon build scripts and Lua verify tests in `utils/` |
139166

140167
`wip-everything` also holds large generated lexicon data files in `utils/` that were never committed to `main`. Note: parts of `main.js`/`utils.js`/`liaison.js`/`lexicon.js` currently on `main` may not include these stashed features until the stashes are applied.
168+
169+
### Update 2026-07-28
170+
171+
Branch `macronizer` (pushed to origin, **not merged to `main`** — GitHub Pages still serves the pre-macronizer site) now carries, on top of the stash situation above:
172+
- the macronizer page + WASM engine (`macronizer/dist/`, synced from the `latin-macronizer-wasm` repo's `macronizer-ui-support` branch — never hand-edit `dist/`)
173+
- the full test infrastructure (see Tests section) + CI workflow
174+
- range-chunk IndexedDB stores for both the macronizer wordlist (first visit 10min → ~10s) and the app lexicons (return visits skip parsing)
175+
- `e2e/pending-features.spec.js` still holds skipped acceptance tests for the stashes
176+
177+
Applying the `french-liaison`/`portuguese-support` stashes onto this branch will conflict lightly in `main.js` (a prefetch block was added to `transcribe()`) and `lexicon.js` (chunk-store layer added) — resolve keeping both.

0 commit comments

Comments
 (0)