diff --git a/CHANGELOG.md b/CHANGELOG.md index b12f4a7f..86dc0b08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,37 @@ # Hermes Web UI -- Changelog -## [v0.51.28] — 2026-05-08 — 2-PR contributor batch (Release E2: MCP server Option A rewrite + WebUI /goal command) +## [v0.51.29] — 2026-05-08 — 6-PR contributor batch (Release F: Docker hardening + login persistence + scroll/lineage fixes + i18n cleanup) + +### Added (1 PR) + +- **PR #1919** by @franksong2702 — Persist login rate limit attempts (closes #1910). Stores failed-login buckets in `STATE_DIR/.login_attempts.json` instead of in-process memory, so password-auth deployments keep the same failed-attempt window across restarts. Atomic temp+rename writes, `0600` permissions, prunes expired entries on load. If the file is missing, malformed, or unwritable, the auth path falls back to current in-memory behavior with debug-level logging — no infinite-loop risk. + +### Fixed (5 PRs) + +- **PR #1920** by @franksong2702 — Remove dead `kanban_card_start` i18n key. PR #1886 removed the Kanban card-level Start action (direct `running` transitions are now owned by the dispatcher), but the `kanban_card_start` locale key was left present in every locale block. Removed across all 9 locales and strengthened the Kanban static regression test so the dead key cannot be reintroduced. + +- **PR #1921** by @Michaelyklam — Production Docker image hardening (closes #1908). Removes passwordless sudo path, drops the `hermeswebuitoo` sudo-capable staging user, and reworks `docker_init.bash` so privileged setup runs in an explicit root init block before re-execing as the `hermeswebui` user without sudo. Init scratch state now uses owner-only permissions (`umask 0077`, `0700` directory, `0600` files). Added `docs/docker.md` with production-image security model notes. A shell gained through the WebUI runtime no longer has a passwordless sudo path to root inside the production container. + +- **PR #1926** by @ai-ag2026 — Prevent chat scroll resets after final render. The final-render path could write/rebuild DOM, queue native scroll events, and then lose the explicit bottom pin before delayed layout growth settled. Separately, clicking the already-open session still ran the `loadSession()` teardown/setup path. Fix: keep explicit bottom scroll pins stable across `renderMessages({preserveScroll: true})` and late Markdown/layout growth, and make clicking the currently-active sidebar session a no-op before `loadSession()` mutates state. + +- **PR #1927** by @ai-ag2026 — Preserve viewport when loading older messages. Pre-fix, prepending older history could snap the viewport to the bottom or surface only a larger hidden-count marker. Fix: expand transcript render window before rendering newly fetched older messages, then anchor at the current viewport instead of snapping. Adds focused regression coverage for older-history viewport anchoring. + +- **PR #1930** by @ai-ag2026 — Collapse stale compression sidebar segments. The sidebar collapse key treated any row whose `parent_session_id` pointed at another visible row as a non-collapsible child/fork row — correct for subagent/fork sessions, but wrong for automatic compression continuations that already carry `_lineage_root_id`/`lineage_root_id` and should collapse by lineage even when stale optimistic parent segments are still locally visible. Fix: prefer explicit lineage metadata before the visible-parent guard. + +### Tests + +4947 → **4960 collected, 4960 passing, 0 regressions** (+13 net new). Full suite ~145s on Python 3.11 (HERMES_HOME isolated). JS syntax check (`node -c`) clean on `static/i18n.js`, `static/sessions.js`, `static/ui.js`. Browser API sanity harness (port 8789): all 11 endpoints + 20 QA tests PASS. Opus advisor pass: SHIP-READY (only flag was a #1919 CHANGELOG conflict already auto-resolved during stage rebase). + +### Pre-release verification + +- Full pytest under `HERMES_HOME` isolation: **4960 passed, 11 skipped, 1 xfailed, 2 xpassed, 8 subtests passed** in 145.24s. +- Browser API harness against stage-324 on port 8789: all 11 endpoints + 20 QA tests PASS (110.90s for QA phase). +- `node -c` on all 3 modified `static/*.js` files: clean. +- Stage diff: 18 files, +588/-150. +- Opus advisor pass on stage-324 brief: VERDICT=SHIP-WITH-FIXES (single fix: #1919 CHANGELOG rebase — already auto-resolved during stage merge). Coexistence verified for #1926/#1927/#1930 sharing `static/sessions.js` (different functions, scroll-pin and viewport-anchor cannot fight; lineage metadata degrades gracefully on legacy sessions). +- v0.51.28 carry-overs verified preserved (no in-batch changes to `api/routes.py:_strip_workspace_prefix`, `api/streaming.py:evaluate_goal_after_turn`, `api/profiles.py:_profiles_match`, `tests/test_mcp_server.py` module-restoration logic). +- Pre-stamp re-fetch of all 6 PR heads: no contributor force-push during Opus window. + ### Added (2 PRs) diff --git a/ROADMAP.md b/ROADMAP.md index 30080d0f..f39cdfad 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,7 +2,7 @@ > Web companion to the Hermes Agent CLI. Same workflows, browser-native. > -> Last updated: v0.51.28 (May 8, 2026) — 4947 tests collected — 2-PR Release E2 batch (MCP server Option A rewrite + WebUI /goal command) +> Last updated: v0.51.29 (May 8, 2026) — 4960 tests collected — 6-PR Release F batch (Docker hardening + login persistence + scroll/lineage fixes + i18n cleanup) > Test source: `pytest tests/ --collect-only -q` > Per-version detail: see [CHANGELOG.md](./CHANGELOG.md) diff --git a/TESTING.md b/TESTING.md index d254ea4d..e9e7a980 100644 --- a/TESTING.md +++ b/TESTING.md @@ -1835,8 +1835,8 @@ Bridged CLI sessions: --- -*Last updated: v0.51.28, May 8, 2026* -*Total automated tests collected: 4947* +*Last updated: v0.51.29, May 8, 2026* +*Total automated tests collected: 4960* *Regression gate: tests/test_regressions.py* *Run: pytest tests/ -v --timeout=60* *Source: /*