When TodoWrite is called, the taskIdToIndex map was cleared and
rebuilt from scratch. However, TodoItem objects only contain content
and status fields — no taskId. This meant all taskId mappings from
prior TaskCreate calls were permanently lost, causing subsequent
TaskUpdate operations to silently fail.
Fix: Before clearing the map, build a reverse lookup of content →
taskIds from the existing state. After replacing latestTodos with the
new TodoWrite items, re-register taskId mappings for items whose
content matches a previously-known task. Stale mappings (for content
no longer present) are naturally dropped.
Adds two tests:
- TaskCreate → TodoWrite → TaskUpdate flow preserves taskId
- TodoWrite-only regression test (no TaskCreate involved)
Cover both rendering paths (expanded + compact) to verify that:
- modelFormat compact/short correctly strips context suffix and prefix
- modelOverride completely replaces the model name in the badge
- modelOverride takes precedence over modelFormat
- loadConfig structural test validates new display fields
Users can now set a fully custom model name in their config:
{ "display": { "modelOverride": "zane's intelligent opus 4.6" } }
When set, the override completely replaces the auto-detected model
name (while preserving the provider qualifier like "| Bedrock").
Follows the same pattern as customLine: string type, max 80 chars,
empty string means disabled (falls through to modelFormat).
Claude Code may include the context window size in display_name
(e.g. "Opus 4.6 (1M context)"), but the HUD already shows context
usage via the context bar — making the parenthetical redundant.
This adds stripContextSuffix() which removes any parenthetical
containing the word "context" from the display name. It handles
common variants like "(1M context)", "(200k context)",
"(with 1M context)", and "(extended context window)" while
preserving non-context parentheticals like "(beta)" or "(preview)".
Before: [Opus 4.6 (1M context) | Bedrock]
After: [Opus 4.6 | Bedrock]
- Fix detectLanguage() to follow POSIX priority: LC_ALL > LC_MESSAGES > LANG
- Fix Chinese format.resetsIn from broken wrap-around grammar to prefix form
- Fix loadConfig() to call mergeConfig({}) when no config file exists,
ensuring detectLanguage() runs for auto-detection
- Add setLanguage('en') guard to render.test.js for locale-independent tests
- Add dedicated i18n test suite (tests/i18n.test.js) covering t(),
detectLanguage(), and mergeConfig language handling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add i18n infrastructure with automatic language detection from system
locale (LANG/LC_ALL/LC_MESSAGES) and manual override via config.json.
Translates all user-facing HUD labels, status messages, and format
strings. English remains the default.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>