docs(release): stamp v0.50.266 — CHANGELOG + ROADMAP + TESTING test counts

This commit is contained in:
nesquena-hermes committed 2026-05-02 04:20:44 +00:00
1 parent c73f2ff387
commit 8f6b9d43dd
3 files changed
+16 -3

No files matched your search

+13
View File
@@ -1,5 +1,18 @@
# Hermes Web UI -- Changelog
## [v0.50.266] — 2026-05-02
### Fixed (i18n parity)
- **Server-side `_LOGIN_LOCALE` missing ja/pt/ko** (#1442) — the password/login page is rendered server-side BEFORE the JS i18n bundle loads, so its strings come from `_LOGIN_LOCALE` in `api/routes.py`, not `static/i18n.js`. The dict only contained 6 entries (`en/es/de/ru/zh/zh-Hant`), so users with `language=ja|pt|ko` set saw the English login page even after their UI language preference was saved. v0.50.264 added Japanese as the 8th built-in locale, making the gap newly visible. **Fix:** added `ja`, `pt`, `ko` entries with the same 7 sub-keys (`lang/title/subtitle/placeholder/btn/invalid_pw/conn_failed`) that the existing locales carry, mirroring the corresponding `login_*` strings from `static/i18n.js`. **20 regression tests** in `tests/test_login_locale_parity.py` pin two invariants: every locale registered in `LOCALES` (i18n.js) must have a matching `_LOGIN_LOCALE` entry, and every locale's user-facing login-flow keys (13 of them) must NOT equal the English value. Adding a new locale to `i18n.js` without updating `routes.py` now trips a test. (`api/routes.py`, `tests/test_login_locale_parity.py`)
- **English-leaking login-flow keys in i18n.js** (#1442 audit) — while auditing the login-flow surface, found 13 keys still in English across `ko` (10: `login_placeholder`, `login_btn`, `login_invalid_pw`, `login_conn_failed`, `sign_out_failed`, `password_placeholder`, `settings_saved_pw`, `settings_saved_pw_updated`, `auth_disabled`, `disable_auth_confirm_title`), `es` (3: `sign_out_failed`, `auth_disabled`, `disable_auth_confirm_title`), and `pt` (3 missing entirely: `sign_out_failed`, `auth_disabled`, `disable_auth_confirm_title`). All 13 now use natural translations matching the existing locale's terminology. The wider English-leak gap across non-login translation entries is a much larger problem requiring native-speaker review and is tracked separately. (`static/i18n.js`)
### Fixed (Safari IME composition — broader coverage)
- **`_isImeEnter` helper not used in 6 other Safari-affected Enter guards** (#1443) — PR #1441 (v0.50.264) widened the chat composer (`#msg`) Enter guard from `e.isComposing` to a 3-guard `_isImeEnter(e)` helper that combines `e.isComposing || e.keyCode === 229 || _imeComposing` for Safari's race where the committing keydown fires AFTER `compositionend` with `isComposing=false`. Six other Enter-input handlers were left on the original narrow guard: session rename, project create, project rename, app dialog (confirm/prompt), message edit, and workspace rename. Japanese/Chinese/Korean users on Safari composing into any of those would still get their IME-confirming Enter committed prematurely. **Fix:** exposed `_isImeEnter` as `window._isImeEnter` from `static/boot.js`, then replaced `e.isComposing` with `window._isImeEnter && window._isImeEnter(e)` at all 6 sites. The state-free part of the helper (`isComposing || keyCode === 229`) handles Safari's race for any focused input without needing per-input composition listeners or a per-input `_imeComposing` flag. The defensive `&& window._isImeEnter` short-circuits if the helper isn't loaded yet (boot.js loads after sessions.js/ui.js with `defer`, but the keydown handlers fire on user interaction which happens after all scripts execute). **9 regression tests** in `tests/test_issue1443_ime_helper_promotion.py` pin each of the 6 sites + verify `e.isComposing` Enter-guards no longer remain in `sessions.js`/`ui.js`. The existing `tests/test_ime_composition.py` alternation regex was extended to accept the windowed form alongside `e.isComposing` and bare `_isImeEnter(e)` — codifies the v0.50.264 reflection note about loosening pattern-shape tests when changing the shape of a guarded check. (`static/boot.js`, `static/sessions.js`, `static/ui.js`, `tests/test_ime_composition.py`, `tests/test_issue1443_ime_helper_promotion.py`)
### Fixed (assistant-output readability)
- **Glued-bold-heading lift in renderMd** (#1446) — LLMs in thinking/reasoning mode frequently emit "section headers" glued to the end of the previous paragraph with no whitespace: `Para 1 text.**Heading to Para 2**\n\nPara 2 text.**Heading to Para 3**`. CommonMark renders that correctly as paragraph-end inline `<strong>`, but visually it looks like trailing emphasis on the body text rather than a section break. Reported by **Cygnus** (Discord, May 1 2026, "Markdown feedback 2 of 3", relayed by @AvidFuturist). **Fix:** added a single regex pre-pass in `renderMd()` that lifts the glued bold into its own paragraph: `s.replace(/([.!?])\*\*([^*\n]{1,80})\*\*\n\n/g, '$1\n\n**$2**\n\n')`. Constraints chosen to avoid false positives: trigger only on `[.!?]` IMMEDIATELY before `**` (no space — almost always an LLM-glued heading, not intentional emphasis); inner text ≤80 chars; no `*` or newline in the inner text (single-line bold only); trailing `\n\n` required (preserves `this is **important** to know.` mid-paragraph emphasis untouched). Position: between `rawPreStash` restore and `fence_stash` restore, so fenced code blocks (still `\x00P` / `\x00F` placeholders at lift-time) are protected. Mirrored in `tests/test_sprint16.py` `render_md()` so the Python mirror stays in sync with the JS. **17 regression tests** in `tests/test_issue1446_glued_heading_lift.py` cover all 3 trigger forms (`.!?`), 5 preserve-emphasis cases, chain rendering, source-level position pin, regex shape pin, and 5 node-driver tests against the actual `static/ui.js` for fenced/inline code protection. (`static/ui.js`, `tests/test_sprint16.py`, `tests/test_issue1446_glued_heading_lift.py`)
- **Markdown headings visually indistinguishable from body text** (#1447) — pre-fix `.msg-body` heading sizes were 18/16/14/13/12/11px against a 14px body, making h3 the same size as body and h4–h6 actually SMALLER than body. Reported by **Cygnus** (Discord, May 1 2026, "Markdown feedback 3 of 3", relayed by @AvidFuturist): "Headings seem to be missing across the board in Hermes. They're there, but all plaintext. They get lost so easily in all the plaintext." **Fix:** new sizes 24/20/17/15/14/13px with `font-weight:700` (was 600), `color:var(--strong, var(--text))`, and `line-height:1.3` (vs body's 1.75 for tighter heading rhythm); h1 and h2 carry a `border-bottom:1px solid var(--border)` for "section title" affordance (mirrors GitHub/Notion convention); h5 and h6 use `text-transform:uppercase` + `letter-spacing:0.04em` for "label-style" affordance instead of being smaller-than-body. Added `margin-top:0` for the first heading of a message so opening with a heading doesn't push down with extra top margin. **Companion fixes:** synced `.preview-md h1-h6` to match `.msg-body` exactly (file preview pane previously had only h1-h3 rules at 18/15/13px); updated `data-font-size="small"` and `data-font-size="large"` h1-h6 overrides to scale proportionally with the new defaults so the hierarchy is preserved at all three font-size settings. **9 regression tests** in `tests/test_issue1447_heading_hierarchy.py` pin the size hierarchy, the bottom borders on h1/h2, the uppercase affordance on h5/h6, the `.preview-md` sync, and the small/large override scaling. (`static/style.css`, `tests/test_issue1447_heading_hierarchy.py`)
## [v0.50.265] — 2026-05-02
### Added
+1 -1
View File
@@ -3,7 +3,7 @@
> Goal: Full 1:1 parity with the Hermes CLI experience via a clean dark web UI.
> Everything you can do from the CLI terminal, you can do from this UI.
>
> Last updated: v0.50.263 (May 2, 2026) — 3658 tests collected
> Last updated: v0.50.266 (May 2, 2026) — 3753 tests collected
> Tests: `pytest tests/ --collect-only -q`
> Source: <repo>/
+2 -2
View File
@@ -1835,8 +1835,8 @@ Bridged CLI sessions:
---
*Last updated: v0.50.263, May 2, 2026*
*Total automated tests collected: 3658*
*Last updated: v0.50.266, May 2, 2026*
*Total automated tests collected: 3753*
*Regression gate: tests/test_regressions.py*
*Run: pytest tests/ -v --timeout=60*
*Source: <repo>/*