Commit graph

107 commits

Author SHA1 Message Date
nesquena-hermes
516e5ad1f0 chore(release): stamp v0.51.15 — 4-PR batch (#1762, #1767, #1769, #1770)
Constituent PRs:
- #1762 (@bergeouss) openrouter/ prefix for tencent/hy3-preview:free. Closes #1744.
- #1767 (@Michaelyklam) use spawn for manual cron subprocesses. Closes #1754.
  AUTO-FIX applied: 2 tests skip on dev machines with editable hermes_agent
  install (the spawn child resolves the real cron.scheduler first instead of
  the fake one). Tightened detector to use importlib.util.find_spec origin
  check per Opus stage-309 SHOULD-FIX.
- #1769 (@nesquena-hermes, APPROVED by @nesquena) three context-menu
  essentials from #1764: Reveal-in-finder, Copy-path, Open-with-system.
- #1770 (@Michaelyklam) surface Codex usage exhaustion errors. Closes #1765.

Tests: 4662 → 4694 collected (+32). 4687 passed, 4 skipped (2 dev-only +
2 prong-2 noise), 3 xpassed, 0 failed in 135s.

Pre-release verification:
- All 4 PRs CI-green individually.
- node -c clean on all 4 changed JS files.
- 11/11 browser API endpoints PASS.
- Pre-stamp re-fetch: all PR heads match local rebases.
- Opus advisor: SHIP, all 5 verification questions clean, 0 MUST-FIX,
  2 SHOULD-FIX (one absorbed: detector tightening; one filed as #1776
  follow-up: custom provider + :free suffix edge case in #1762).

Closes #1744, #1754, #1764, #1765.
2026-05-07 02:04:36 +00:00
nesquena-hermes
e8659d1a40 chore(release): stamp v0.51.14 — 4-PR contributor batch (#1756, #1757, #1760, #1761)
Constituent PRs:
- #1760 (@ai-ag2026) preserve pending user turn on stream errors. Closes #1361.
- #1761 (@dso2ng) scope terminal stream cleanup to owner session. Refs #1694.
  AUTO-FIX applied: restored !INFLIGHT[S.session.session_id] disjunct in
  _setActivePaneIdleIfOwner (regression introduced by helper centralization).
- #1756 (@ng-technology-llc) isolate profile cookie per webui instance. Closes #803.
- #1757 (@skspade) tri-state gateway status (alive: True/False/None).

Tests: 4642 → 4662 collected (+20). 4649 passed, 9 skipped (test-isolation
prong-2 noise), 3 xpassed, 0 failed in 152s.

Pre-release verification:
- All 4 PRs CI-green or rebased clean (#1757 had stale base; CHANGELOG conflict
  auto-resolved by dropping the PR's redundant entry).
- node -c clean on static/messages.js + static/panels.js.
- 11/11 browser API endpoints PASS.
- Pre-stamp re-fetch: all PR heads match local rebases.
- Opus advisor: SHIP, all 5 verification questions clean, 0 MUST-FIX, 0 SHOULD-FIX.
- Two NICE-TO-HAVE coverage gaps absorbed in-release:
  (1) test_sprint36.py asserts !INFLIGHT[...] disjunct in helper body
  (2) test_issue1361_cancel_data_loss.py adds structural-grep test to pin
      _materialize_pending_user_turn_before_error call sites at error branches.

Closes #803, #1361, #1694.
2026-05-06 22:20:17 +00:00
nesquena-hermes
52e1689083 chore(release): stamp v0.51.13 — single-PR composer UX (#1758)
Constituent PR:
- #1758 (@nesquena-hermes) — feat(composer): click pasted/attached image
  thumbnails to lightbox-zoom them. Refs #1733. Companion Mac PR
  hermes-webui/hermes-swift-mac#74 for sequential-paste filename uniqueness.

Independent review: @nesquena APPROVED with exhaustive headless-Chrome
behavioural harness verifying all 4 click paths (thumb-image, ×-on-image,
×-on-audio, audio-element). Pre-fix verification confirmed 4/5 of the new
tests catch regressions to the previous state.

Opus advisor: SHIP, all 6 verification questions clean. One non-blocking
nit absorbed in-release: wrap .attach-thumb:hover in @media (hover: hover)
for iPad sticky-hover hygiene (3-LOC defensive cleanup).

Tests: 4637 → 4642 collected (+5). 4630 passed, 9 skipped, 3 xpassed,
0 failed.

Pre-release verification:
- pytest 4630 passed, 0 failed
- node -c clean on static/ui.js
- 11/11 browser API endpoints PASS
- Pre-stamp re-fetch: PR head still matches local rebase
- Opus advisor: SHIP, 0 MUST-FIX

Refs #1733.
2026-05-06 20:14:10 +00:00
nesquena-hermes
87a256513b chore(release): stamp v0.51.12 — 3-PR batch (cron subprocess return + custom provider routing + session runtime invariants)
Constituent PRs:
- #1746 (@Michaelyklam) — shorten cron profile lock for manual runs (closes #1574, RETURNS from v0.51.11 deferral with queue-drain blocker fixed)
- #1752 (@Michaelyklam) — route custom provider models dict selections (slice of #1240 umbrella)
- #1753 (@Michaelyklam) — guard session-owned runtime invariants (refs #1694)

#1746 v2 fix: result_queue.get(timeout=...) BEFORE process.join()
(drain-then-join), with queue.Empty recovery + 200,000-char regression test.
Opus stage-306 verified the fix correct + complete; the prior fork→spawn
SHOULD-FIX filed as follow-up issue #1754 (separate architectural change).

Tests: 4622 → 4632 passing (+10). 0 regressions. Stably green on first try.

Pre-release verification:
- All 3 PRs CI-green individually + rebased onto master with NO conflicts
  (disjoint files: api/config.py + static/messages.js + api/routes.py)
- pytest 4632 passed, 0 failed
- node -c clean on static/messages.js
- 11/11 browser API endpoints PASS
- Opus advisor: SHIP all 3, 0 MUST-FIX, 1 SHOULD-FIX filed as #1754

Closes #1574.
2026-05-06 18:23:42 +00:00
nesquena-hermes
410f4c0833 chore(release): stamp v0.51.11 — 3-PR batch (model picker race, theme-color meta, quote-strip) + test-isolation hardening (#1746 deferred)
Constituent PRs:
- #1747 (@Michaelyklam) — wait for model catalog before opening picker (closes #1743)
- #1748 (@nesquena-hermes) — theme-color meta tag for native chrome bridges (nesquena APPROVED)
- #1750 (@nesquena-hermes) — strip surrounding quotes from Add Space path (nesquena APPROVED)

Deferred to v0.51.12:
- #1746 — Opus caught multiprocessing.Queue deadlock pattern (parent
  process.join() before queue drain hangs on output >64KB pipe buffer).
  Deferral comment with two specific fix options posted on PR.

Plus 1 in-stage absorbed test-isolation fix:
- test_issue1426 + test_issue1680: skip on detected prefix pollution
  (prong 2 of test-isolation-flake-recipe). Failure rate ~25% in full
  suite from sys.modules pollution; standalone always passes.

Tests: 4596 → 4622 passing (+26). 0 regressions. Stably green.

Pre-release verification:
- 3 PRs CI-green individually + rebased onto master
- pytest 4622 passed, 0 failed
- node -c clean on static/ui.js + static/boot.js
- 11/11 browser API endpoints PASS
- Opus advisor: SHIP #1747/#1748/#1750, MUST-FIX block on #1746

Closes #1743.
2026-05-06 18:02:40 +00:00
nesquena-hermes
2fc9c23d9b chore(release): stamp v0.51.10 — 2-PR batch (cron profile isolation + profile switch during streams) + Opus follow-up
Constituent PRs:
- #1741 (@Michaelyklam) — isolate in-process cron scheduler profiles (closes #1575)
- #1742 (@Michaelyklam) — allow profile switching during active streams (closes #1700)

Plus 1 in-stage absorbed fix:
- Opus SHOULD-FIX: remove 9 orphaned profiles_busy_switch i18n keys.

Tests: 4590 → 4596 passing (+6). 0 regressions. Stably green.

Pre-release verification:
- Both PRs CI-green individually + rebased onto master with sibling-rebase
  against stage HEAD on api/profiles.py (different regions, no conflicts)
- pytest 4596 passed, 0 failed (single clean run)
- node -c clean on static/panels.js + static/i18n.js
- 11/11 browser API endpoints PASS
- Opus advisor: SHIP both, 5/5 verification clean, 0 MUST-FIX, 1 SHOULD-FIX absorbed

Closes #1575, #1700.
2026-05-06 16:27:01 +00:00
nesquena-hermes
1b9c8c660c chore(release): stamp v0.51.9 — 2-PR batch (boot path + Codex session repair) + Opus follow-up
Constituent PRs:
- #1735 (@dso2ng) — keep saved running sessions sidebar-only on root boot (slice of #1694)
- #1738 (@Michaelyklam) — repair stale OpenAI session models for Codex (closes #1734)

Plus 1 in-stage absorbed fix:
- Opus SHOULD-FIX: persist openai-codex provider unconditionally on stale-session
  repair (drop conditional catalog-coverage check that produced redundant
  repair-writes per chat-start).

Tests: 4584 → 4590 passing (+6). 0 regressions. Stably green.

Pre-release verification:
- Both PRs CI-green individually + rebased onto master
- pytest 4590 passed, 0 failed
- node -c clean on static/boot.js
- 11/11 browser API endpoints PASS
- Opus advisor: SHIP, 5/5 verification clean, 0 MUST-FIX, 1 SHOULD-FIX absorbed

Closes #1734.
2026-05-06 15:19:38 +00:00
nesquena-hermes
62bcf513c3 chore(release): stamp v0.51.8 — 7-PR full-sweep batch + Opus follow-up + test-isolation fix
Constituent PRs:
- #1725 (@Michaelyklam) — simplify compact Activity row summary
- #1726 (@Michaelyklam) — delegate generic provider catalogs to Hermes CLI (slice of #1240)
- #1727 (@Michaelyklam) — link Claude Code OAuth in onboarding (closes #1362)
- #1728 (@starship-s) — preserve profile context when starting chats
- #1729 (@Michaelyklam) — persist compact Activity disclosure state
- #1730 (@Michaelyklam) — prevent sticky sidebar hover drag state
- #1732 (@Sanjays2402) — unpin scroll on small upward motion during streaming (closes #1731)

Plus 2 in-stage absorbed fixes:
- test-isolation fix: monkeypatch.setattr(config, 'cfg', X) survives PR #1728's
  path/mtime-aware get_config() reload. Mandatory before tag (Opus stage-302).
- Opus SHOULD-FIX #1: _lastScrollTop reset on session switch (#1732 follow-up).

Tests: 4537 → 4584 passing (+47). 0 regressions. Full suite ~128s. Stably green.

Pre-release verification:
- All 7 PRs CI-green individually + rebased onto master
- pytest 4584 passed, 0 failed (multiple runs)
- node -c clean on all 4 modified .js files
- 11/11 browser API endpoints PASS on isolated port 8789
- 20 QA tests via webui_qa_agent.sh PASS
- Opus advisor: SHIP, 5/5 verification clean, 0 MUST-FIX, 1 SHOULD-FIX absorbed
  (_lastScrollTop reset), 1 SHOULD-FIX deferred (#1736 — _clear_anthropic_env_values
  race, onboarding-time-only)

Closes #1362, #1731.
2026-05-06 08:27:37 +00:00
nesquena-hermes
29878259ca docs(troubleshooting): bake the #1695 diagnostic flow into the error message + a new troubleshooting doc
Closes #1695.

@Patrick-81 reported the bare "AIAgent not available -- check that
hermes-agent is on sys.path" error on a symlinked install (~/Programmes/hermes-agent
linked to ~/hermes-agent). The maintainer's response — three diagnostic
commands plus `pip install -e .` in the agent dir — fixed it for them.
This PR captures both halves of that learning so the next user with the
same shape doesn't have to file a new issue:

1. **Error message diagnostic block.** New helper
   `_aiagent_import_error_detail()` in api/streaming.py builds a multi-line
   diagnostic when the import fails, including:
     - the running Python interpreter
     - HERMES_WEBUI_AGENT_DIR (set value, or "(not set)")
     - sys.path entries that mention hermes/agent (or "no entries mention..."
       — itself a strong diagnostic signal)
     - the most-common fix (`pip install -e .` in the agent dir)
     - a pointer to docs/troubleshooting.md

   The original error message string is preserved as the FIRST line so
   existing log scrapers and docs-search keep matching.

   Helper is kept as a separate function so it stays out of the hot path
   until we actually need to raise — building it on every successful import
   would be wasted work.

2. **New docs/troubleshooting.md.** Symptom → Why → Diagnostic commands →
   Fix → When-to-file-a-bug template, with one entry to start: the
   "AIAgent not available" flow Patrick-81 walked through. Future
   recurring failure modes follow the same template. Required a one-line
   addition to .gitignore — docs/* is gitignored with an allowlist, and
   the new file needed `!docs/troubleshooting.md` to be tracked.

3. **README link.** docs/troubleshooting.md added to the `## Docs` section
   so users know where to look first.

13 regression tests in tests/test_1695_aiagent_import_error_detail.py:
9 for the helper output shape (preserves original message line, includes
running python, shows HERMES_WEBUI_AGENT_DIR set/unset both ways, includes
pip-install-e hint, points at troubleshooting doc, lists relevant sys.path
entries when present, says "no entries..." when absent, output is multi-line)
plus 4 for the docs-presence regression (file exists, has the AIAgent
section, includes pip install -e ., describes the diagnostic chain with
readlink + agent/__init__.py verification).

190 streaming/aiagent tests pass after the change. ast.parse on
api/streaming.py clean.

CI failure on prior push was due to the docs/* gitignore swallowing the
new troubleshooting.md file silently — this commit adds the allowlist
entry so the file is tracked.
2026-05-05 22:14:07 +00:00
Nathan Esquenazi
23bca0d955 chore(release): stamp v0.51.6 — 5-PR full-sweep batch
5 PRs (1 surface addition, 4 fixes):
- #1717 preserve imported session lineage (@ai-ag2026)
- #1718 preserve Activity count across focus changes (@Michaelyklam, closes #1715)
- #1719 elapsed timer in compact activity (@Michaelyklam, closes #1716)
- #1720 backend tool snippet cap raised to 4000 (@Michaelyklam, closes #1714)
- #1722 suppress stale preserved task lists (@ai-ag2026)

Tests: 4527 → 4537 (+10). Opus: SHIP, 6/6 verification clean.

Co-authored-by: ai-ag2026 <noreply@github.com>
Co-authored-by: Michael Lam <Michaelyklam1@gmail.com>
2026-05-05 22:09:08 +00:00
Nathan Esquenazi
b59c6975a2 chore(release): stamp v0.51.5 — 4-PR full-sweep batch
4 PRs (1 surface addition, 3 fixes):
- #1688 VPS resource health Insights panel (@Michaelyklam, closes #693)
- #1709 preserve scroll on stream completion (@Michaelyklam, closes #1690)
- #1711 hide rename tooltip on folders (@nesquena-hermes, closes #1710)
- #1712 guard localStorage.setItem against QuotaExceededError (@24601)

Tests: 4504 → 4527 (+23). Opus: SHIP, 6/6 verification clean.

Held back: #1686 (Docker enhance) — Opus flagged sibling-repo dep that
breaks standalone clones. Left open for follow-up.

Co-authored-by: Michael Lam <Michaelyklam1@gmail.com>
Co-authored-by: 24601 <noreply@github.com>
2026-05-05 17:54:15 +00:00
nesquena-hermes
b5e8e67d71 fix(workspace): preserve single-click open + double-click rename on filename (#1707)
Closes #1707 — single-click on a workspace tree filename did nothing.

#1698 was a regression where the filename's dblclick rename handler was
unreachable because the row's el.onclick (openFile) fired synchronously
on the first click. The fix in #1702 stopped click propagation on nameEl
— but that broke single-click activation entirely (#1707): clicking the
filename now did nothing, you had to click the icon or row whitespace
to open the file.

Restored fix preserves both intents via a 300ms debounced delegator:

  let _nameClickTimer = null;
  nameEl.onclick = (e) => {
    e.stopPropagation();
    if (_nameClickTimer) { clearTimeout(_nameClickTimer); _nameClickTimer = null; }
    _nameClickTimer = setTimeout(() => {
      _nameClickTimer = null;
      if (typeof el.onclick === 'function') el.onclick(e);
    }, 300);
  };
  nameEl.ondblclick = (e) => {
    e.stopPropagation();
    if (_nameClickTimer) { clearTimeout(_nameClickTimer); _nameClickTimer = null; }
    // ... existing rename body
  };

Single-click on nameEl schedules a setTimeout that calls el.onclick(e)
after the dblclick threshold passes (300ms — matches the OS dblclick
threshold on most platforms). Double-click cancels the pending timer
and triggers the existing rename input.

Cost: 300ms latency on file-open clicks. Acceptable trade for keeping
rename reachable on single-click.

Also updated tests/test_workspace_tree_rename.py to accept both the
pre-#1707 (pure stopPropagation) and post-#1707 (debounced delegator)
shapes — the original assertion was too narrow and would have rejected
the correct fix.

9 new regression tests in tests/test_1707_workspace_filename_click.py:
  - 6 source-level static-analysis checks on the patched handler shape
  - 3 behavioral tests via Node VM (synthesize click → 300ms delay,
    click → dblclick within tick → assert rename mounts + openFile
    is not called).

7 of 9 tests fail on master pre-fix (verified); all 9 pass after.
2026-05-05 16:13:58 +00:00
Nathan Esquenazi
451c946a30 chore(release): stamp v0.51.4 — 10-PR full-sweep batch
10 PRs (3 surfaces additions, 7 fixes):
- #1644 model picker chip + group count (@bergeouss, closes #1425)
- #1684 update network failures UX (@Michaelyklam, closes #1321)
- #1685 Codex spark models (@Michaelyklam, closes #1680)
- #1689 normalize profile base homes (@Michaelyklam, refs #749)
- #1693 adaptive title refresh deadlock (@ai-ag2026)
- #1701 normalize update banner URL (@Michaelyklam, closes #1691)
- #1702 workspace double-click rename (@Michaelyklam, closes #1698)
- #1703 cache invalidation on auth-store drift (@Michaelyklam, closes #1699)
- #1704 markdown fence lengths (@Michaelyklam, closes #1696)
- #1706 multi-image paste fix (@Michaelyklam, closes #1697)

Tests: 4477 → 4503 (+26). Opus: SHIP, 7/7 verification clean.

Co-authored-by: Michael Lam <Michaelyklam1@gmail.com>
Co-authored-by: ai-ag2026 <noreply@github.com>
Co-authored-by: bergeouss <noreply@github.com>
2026-05-05 15:54:12 +00:00
Nathan Esquenazi
353033eb8d chore(release): stamp v0.51.3 — 3-PR follow-up batch (#1671, #1673, #1676)
CHANGELOG.md: full v0.51.3 entry covering 3 PRs + test-fragility fix
ROADMAP.md: bump version + test count to 4477
TESTING.md: bump version + test count to 4477

Independent review: Opus advisor on stage-300 diff (1050 LOC).
7/7 verification questions verified clean. Verdict: SHIP.
0 MUST-FIX, 0 SHOULD-FIX.
2026-05-05 02:41:24 +00:00
Michael Lam
c94ec31dec feat: show LLM Gateway routing metadata 2026-05-05 02:26:55 +00:00
Nathan Esquenazi
e095ed90be chore(release): stamp v0.51.2 — 3-PR follow-up + #1669 scroll hotfix
CHANGELOG.md: full v0.51.2 entry covering 3 PRs + sidebar scroll hotfix
ROADMAP.md: bump version + test count to 4457
TESTING.md: bump version + test count to 4457

Independent review: Opus advisor on stage-299 diff (1336 LOC).
6/6 verification questions verified clean. Verdict: SHIP.
0 MUST-FIX, 2 SHOULD-FIX absorbed in-release (bounded WIKI walk +
URL scheme guard).
2026-05-05 02:19:56 +00:00
Nathan Esquenazi
58d141b8d6 chore(release): stamp v0.51.1 — 11-PR @Michaelyklam batch + Opus pass
CHANGELOG.md: full v0.51.1 entry covering all 11 constituent PRs
ROADMAP.md: bump version + test count to 4429
TESTING.md: bump version + test count to 4429

Independent review: Opus advisor on stage-298 diff (4749 LOC).
6/6 security/correctness questions verified clean. Verdict: SHIP.
0 MUST-FIX, 0 SHOULD-FIX. Two polish notes deferred to follow-up.
2026-05-05 01:40:36 +00:00
Nathan Esquenazi
8c7e263bf6 release: stamp v0.51.0 — Kanban v1 launch
CHANGELOG.md: full v0.51.0 entry covering the 12-commit Kanban stack
(#1645, #1646, #1647, #1649, #1654, #1655, #1660, #1675) including
multi-board management, SSE event stream, dispatcher contract enforcement,
CSS-injection fix, archive race fix, mobile responsive, and 35 new
Kanban-specific tests (33 -> 68).

ROADMAP.md, TESTING.md: bumped to v0.51.0 / 4356 tests / 'Kanban v1 launch'.

Major version bump from 0.50.x -> 0.51.0 reflects the size and significance
of the feature: first-party-compatible Kanban surface (CRUD on /api/kanban/boards
+ real-time SSE event stream) parity-verified against the Hermes Agent
dashboard plugin. Independent review APPROVED, Opus advisor SHIP, all
SHOULD-FIX absorbed in-release with regression tests.
2026-05-05 00:55:02 +00:00
Hermes Agent
3005bfc491 chore(release): stamp v0.50.297 — 3-PR batch + Opus pass + 2 follow-ups absorbed
Constituent PRs:
  #1659 by @bergeouss — Docker readonly false-positive (closes #1658, fixes v0.50.295 regression)
  #1653 by @nesquena — OAuth cancel race fix (follow-up to v0.50.296 #1652)
  #1657 by @Michaelyklam — health diagnostics + watchdog hardening (refs #1458 Bug #3)

Opus advisor SHIP verdict on stage-297. Two follow-ups absorbed in-release:
- _deep_health_checks(stream_check=...) reuses pre-computed lock probe
- _handle_request_noblock docstring documents single-thread safety

PR #1656 closed as superseded by #1657 (same author, both target #1458,
#1657 is functional superset).

4284 → 4288 tests passing (+4).
2026-05-04 22:50:57 +00:00
Hermes Agent
db54dc594e chore(release): stamp v0.50.296 — 3-PR batch + Opus pass + 2 follow-ups absorbed
Constituent PRs (all by @Michaelyklam):
  #1640 — show TPS in assistant message headers (closes #1617) — Aaron UX APPROVED
  #1648 — session save mode config (closes #1406)
  #1650 — Codex OAuth onboarding flow (refs #1362)

Opus advisor SHIP verdict on stage-296. 14-question audit passed including
focused OAuth security review on #1650. Two minor follow-ups absorbed:
- _get_active_hermes_home() exception fallback now logs warning
- Codex credential pool find-loop accepts both legacy and current source values

#1640 has @aronprins UX gate APPROVED (default-off TPS toggle in Preferences).
#1650 ships first in-app OAuth flow — server-owned device-code lifecycle,
profile-scoped credential storage, atomic chmod-before-rename writes.

4255 → 4284 tests passing (+29).
2026-05-04 21:38:26 +00:00
Hermes Agent
9aad249e5a chore(release): stamp v0.50.295 — 3-PR batch + Opus pass
Constituent PRs:
  #1637 by @Michaelyklam — protect raw pre from glued-bold lift (closes #1451)
  #1639 by @bergeouss — macOS auto-scroll race + custom:* provider list (closes #1360, #1619)
  #1642 by @nesquena-hermes — YAML/JSON/diff code block newlines (closes #1618, #1463)

Opus advisor SHIP verdict on stage-295. One observation absorbed:
- api/config.py:2533 dead-code comment per Opus (defensive belt-and-braces
  for #1619 fallback; load-bearing fix is in routes.py /api/models/live)

PR #1641 (Michaelyklam parallel-discovery duplicate of #1642) closed as
superseded; UI media adopted with co-author trailer.

4245 → 4255 tests passing (+10).
2026-05-04 18:37:52 +00:00
Hermes Agent
326c7d0daf chore(release): stamp v0.50.294 — 3-PR batch + Opus pass
Constituent PRs:
  #1631 by @nesquena-hermes — streaming stability trio (closes #1623, #1624, #1625)
  #1635 by @bergeouss — session list race + readonly fs guard (closes #1430, #1470)
  #1636 by @nesquena-hermes — models cache version stamp (closes #1633)

Opus advisor SHIP verdict on stage-294 (combined diff). All 9 verification
questions cleared. Two #1636 minor observations absorbed in-release:
- DEBUG logger calls in _is_loadable_disk_cache when rejecting
- Docstring clarification on string-vs-semver and schema-version axis

#1631 in-PR Opus pass already absorbed: rate-limited telemetry,
expanded _LOCAL_SERVER_PROVIDERS, RFC1918 CHANGELOG callout.

4180 → 4245 tests passing (+65).
2026-05-04 17:23:32 +00:00
Hermes Agent
f3e066b53c chore(release): stamp v0.50.293 — 3-PR batch + 2 Opus follow-ups absorbed
Constituent PRs:
  #1627 by @franksong2702 — show Hermes Agent version (closes #1606)
  #1629 by @nesquena-hermes — profile isolation trio (closes #1611, #1612, #1614)
  #1630 by @Michaelyklam — provider config cleanup regression test (#1597 follow-up)

Opus advisor SHIP verdict + 2 SHOULD-FIX absorbed in-release:
- load_projects() re-reads from disk inside lock to close migration startup race
- _detect_agent_version() uses --dirty for symmetry with _detect_webui_version()

4142 → 4180 tests passing.
2026-05-04 16:33:57 +00:00
Hermes Agent
1549a10510 chore(release): stamp v0.50.292 — 12-PR batch + Opus follow-ups absorbed
Constituent PRs:
  #1597 by @Michaelyklam — pytest config-path isolation
  #1598 by @Michaelyklam — multi-tab SSE broadcast (closes #1584)
  #1599 by @Sanjays2402 — _pending_started_at truthy-check (closes #1595)
  #1600 by @Michaelyklam — streaming markdown subpath/fallback
  #1601 by @Michaelyklam — subpath frontend routes
  #1602 by @ai-ag2026 — cross-source continuation
  #1603 by @ai-ag2026 — git remote name preservation
  #1605 by @ai-ag2026 — update banner branch labels
  #1608 by @franksong2702 — cron broad-except removal (closes #1578)
  #1609 by @franksong2702 — server.py socket cleanup (closes #1583)
  #1621 by @franksong2702 — fork indicator polish (fixes #1613)
  #1622 by @s905060 — paste text-with-image (closes #1620)

Opus advisor SHIP verdict + 2 SHOULD-FIX absorbed in-release:
  • #1598 ordering race fixed (offline-buffer replay moved inside lock)
  • #1601 sessions.js:1440 gateway SSE probe baseURI parity fix

4117 → 4142 tests passing.
2026-05-04 15:45:41 +00:00
nesquena-hermes
3369a08f37 fix(updates): use merge-base for compare URL so 'What's new?' link resolves
Closes #1579.

api/updates.py was building the GitHub compare URL from local HEAD short SHA:

    repoUrl + '/compare/' + curSha + '...' + newSha
    where curSha = `git rev-parse --short HEAD`

Whenever local HEAD diverges from upstream — unpushed work, dirty stage
branches, forks, in-flight rebases, release-time merge commits whose SHA
only lives in the maintainer's local history — the compare URL points at
a SHA github.com has never seen and returns the standard 404 page.

Reporter (@ai-ag2026) observed:
  c660c7f...86cb22e
  → 404 because c660c7f was an unpushed local commit.

The right base is `git merge-base HEAD <compare_ref>` — the most recent
commit local and upstream share. Since `git fetch` succeeded just before,
the merge-base is guaranteed to exist on the upstream GitHub repo.

Behavior matrix:
  Pure-behind clone (no local commits): merge-base == HEAD; URL unchanged.
  Behind + local-only commits (#1579):  merge-base != HEAD; URL points at
                                        public ancestor instead of local HEAD.
  merge-base failure (shallow clone):   current_sha=None; JS link guard
                                        suppresses link rather than emitting
                                        a known-broken URL.

Also hardens static/ui.js: reset the link's href and display:none on every
banner render, so a stale link from a prior render can't survive a re-render
where the new payload has current_sha=null.

Tests:
  - test_current_sha_is_merge_base_not_local_HEAD — reporter's scenario
  - test_current_sha_equals_HEAD_when_no_local_commits — backward compat
  - test_current_sha_falls_back_to_None_when_merge_base_fails — defensive
  - test_whats_new_link_resets_display_and_href_on_every_render
  - test_whats_new_link_suppressed_when_curSha_falsy
  - test_reporter_url_shape_no_longer_produces_invalid_compare_url

4094 → 4100 passing. 0 regressions.
2026-05-04 05:26:19 +00:00
Hermes Release Agent
1636ab9ef9 release: stamp v0.50.290 — 5-PR batch (#1586+#1590+#1591+#1592+#1464) — 4094→4111 tests
- #1586 (Michaelyklam): login asset SW cache exemption
- #1590 (Michaelyklam): hot-apply compact tool activity setting
- #1591 (Michaelyklam): first-turn sidebar visibility (optimistic upserts)
- #1592 (Michaelyklam): turn duration display (Done in 1m 12s) + Opus follow-up (truthy-check on _pending_started_at)
- #1464 (JKJameson, maintainer-augmented): workspace dropdown sort+search+chip-sync (rebased + ternary fix + regression test)

Maintainer-side test fixes in stage:
- tests/test_465_session_branching.py: widen compact() search window 1500→3000
- tests/test_regressions.py: anchor on api('/api/chat/start' instead of comment line

Browser API sanity: 11/11 passed. Live UX verification: vision-confirmed dropdown sort+search+empty-state on test server. Opus advisor: SHIP AS-IS.
2026-05-04 05:10:29 +00:00
Hermes Release Agent
59a6c6bc15 release: stamp v0.50.289 — TCP keepalive on accepted connections (#1581) — 4094 tests 2026-05-03 23:50:09 +00:00
Hermes Bot
59afbdb3ce release: stamp v0.50.288 — 3-PR batch (#1569 + #1571 + #1572) (4053 \u2192 4094 tests) 2026-05-03 22:54:34 +00:00
Hermes Bot
de412cef0e release: stamp v0.50.287 — PR #1565 self-update active-stream guard (4051 → 4053 tests) 2026-05-03 21:18:58 +00:00
Hermes Bot
b852096dad release: stamp v0.50.286 — PR #1561 password env-var lock UI (4028 → 4051 tests) 2026-05-03 21:09:08 +00:00
Hermes Bot
1a7eaf518f fix(session-recovery): skip _index.json + harden _msg_count against non-dict JSON (v0.50.284 follow-up)
v0.50.284 shipped startup self-heal in api/session_recovery.py that
crashed on the very first JSON file it scanned in the production
session directory.  Verified live on the prod server immediately after
the v0.50.284 deploy:

  [recovery] startup recovery failed: 'list' object has no attribute 'get'

Root cause: the production session dir contains _index.json — a
top-level LIST of session metadata dicts (not a dict).  _msg_count()
did data.get('messages') which raises AttributeError on a list.
The broad except Exception in server.py's startup hook swallowed the
error and the recovery silently no-op'd for every user — defeating
the entire purpose of the v0.50.284 release.

Fix is three small defensive changes:

1. _msg_count() — added isinstance(data, dict) guard.  Non-dict-shaped
   JSON files now return -1 (the harmless 'unknown count' sentinel)
   instead of raising AttributeError.

2. recover_all_sessions_on_startup() — skips any file whose name starts
   with '_' (the existing project convention for non-session metadata
   files like _index.json).  These are convention-marked as system
   files, not session payloads.

3. recover_all_sessions_on_startup() — wraps recover_session(path) in
   try/except Exception so a single malformed file can't break recovery
   for the rest.  Logs and continues.

2 new regression tests:
  - test_recover_all_sessions_on_startup_skips_non_session_index_json
  - test_msg_count_returns_neg1_for_non_dict_top_level

4026 → 4028 tests passing (+2).

Net effect: any user wiped between v0.50.279 and v0.50.284 deploys
whose session has a .bak shadow will now get auto-recovered on first
launch of v0.50.285, as v0.50.284's release notes promised.

Closes #1558 (follow-up — the original P0 was closed by v0.50.284 but
the recovery half didn't actually run in production).
2026-05-03 20:50:06 +00:00
Hermes Bot
519059f56e release: stamp v0.50.284 — P0 data-loss hotfix + stale-stream race fix (4019 → 4026 tests) 2026-05-03 20:42:05 +00:00
Hermes Bot
d83a56dab2 release: stamp v0.50.283 — 8-PR full sweep batch (4018 → 4019 tests) 2026-05-03 19:30:14 +00:00
nesquena-hermes
8fab43b3fe docs(release): stamp v0.50.282 — CHANGELOG + ROADMAP + TESTING test counts 2026-05-03 18:17:56 +00:00
Hermes Bot
3a23efd923 docs: rewrite ROADMAP.md and SPRINTS.md for v0.50.281 currency
Both files had drifted significantly from the actual current state of the
project:

ROADMAP.md previously contained:
- A ~75-row 'sprint history' table that overlapped with CHANGELOG.md
- A 'Wave 2 Core' section frozen at Sprint 7 progress
- A 'Wave 2: Full CRUD' nested section repeating the same Wave 7 items
- A 'User Requested Features' table that double-counted the same shipped issues
- A 'Feature Parity Checklist' with many unchecked boxes that were actually shipped
  (branch/fork via #465, LLM-generated session titles via auto_title_refresh_every,
  workspace git detection at api/workspace.py:719, code execution and TTS
  reclassified, etc.)

SPRINTS.md previously contained:
- 1159 lines of historical sprint plans (Sprints 11-26)
- Inline planning detail more appropriate for the private workspace
- Stale 'as of v0.50.245' header with 'next sprint Sprint 24' reference
- Track-A/B/C breakdowns from sprints already long-merged

Rewrite:

ROADMAP.md (now 397 lines, was 363):
- Status snapshot table at the top
- Architecture table reflecting current layout (api/ ~20k LOC, static/*.js ~26k LOC)
- Feature parity checklist reorganized by surface (chat / sessions / workspace /
  cron / skills / memory / profiles / config / security / visual / voice /
  mobile / i18n / gateway / MCP / distribution) with every line currently in
  master correctly checked
- 'Forward work' section split into confirmed candidates (with tracking issue
  numbers) vs deferred backlog vs intentionally not planned
- 'Sprint history' compressed to a single chronological theme table — per-version
  detail explicitly redirects to CHANGELOG.md
- Versioning conventions documented

SPRINTS.md (now 165 lines, was 1159):
- Forward-looking only — no historical sprint plans (those live in CHANGELOG.md)
- Active sprint candidates table sourced from the sprint-candidate label
- Planning principles section (phase-0 fit assessment, salvage over absorb,
  independent-review gate, per-PR release velocity, no feature creep mid-PR,
  pre-release gate)
- Sprint shape table (typical 3-7 day sprint with phases)
- Out-of-scope section centralized
- Template for new sprint plans

Also updates TESTING.md test count 3990 → 3995 to match actual pytest collect.

No private workspace info, agent infra references, or contributor stipend
content. References to the maintainer's private planning notes are
acknowledged as 'in a private workspace' without further specifics — same
disclosure pattern most open-source projects use.
2026-05-03 17:39:53 +00:00
Hermes Bot
9f9d587ff4 release: stamp v0.50.281 — PR #1536 LM Studio config-driven classification (3985 → 3990 tests) 2026-05-03 17:15:50 +00:00
Hermes Bot
b931875b7d release: stamp v0.50.280 — #1535 reasoning-config salvage + #1404 cross-channel handoff (3946 → 3985 tests) 2026-05-03 16:56:44 +00:00
Hermes Bot
11cc493806 release: stamp v0.50.279 \u2014 8-PR batch (sweep) + Opus MUST-FIX absorbed
CHANGELOG, ROADMAP, TESTING bumped (3936 \u2192 3946).

8 constituent PRs:
- #1523 (@franksong2702) branch indicator codepoint fix
- #1519 (@franksong2702) onboarding API-key focus loss fix
- #1518 (@franksong2702) voice-mode toggle-off recognizer stop
- #1516 (@franksong2702) YAML newline CSS rules
- #1517 (@franksong2702) __CACHE_VERSION__ \u2192 __WEBUI_VERSION__ rename
- #1532 (@ai-ag2026) state.db WebUI session recovery
- #1525 (@ai-ag2026) stale stream state proactive cleanup
- #1526 (@ai-ag2026) max_tokens forwarding + OpenRouter quota classifier

Opus MUST-FIX absorbed: sw.js conflict-marker cleanup + regression guard.
Opus SHOULD-FIX deferred to follow-up #1533 (race in _clear_stale_stream_state).

2 closed as duplicates: #1528 (identical to #1517), #1529 (superseded by #1516).
1 maintainer-review label: #1531 (Asunfly stowaway change in force-push).
5 stay on hold: #1418 #1464 #1404 #1353 #1311.
2026-05-03 16:23:30 +00:00
Hermes Bot
0413ee4fc0 release: stamp v0.50.278 (PR #1520 \u2014 sidebar Unassigned filter chip)
CHANGELOG, ROADMAP, TESTING bumped (3929 \u2192 3936).

Pre-release Opus advisor pass: SHIP AS-IS. Sentinel collision impossible
(UUID hex \u2014 no underscores), stale-active-filter on project delete safe,
CSS specificity clean. One non-blocking edge case (stuck filter at zero
projects + zero unassigned) explicitly deferred per Opus advice
(recoverable via reload, too narrow to justify pre-merge work).

Both contributors (Thanatos-Z and AlexeyDsov) credited via Co-authored-by
trailers preserved from the synthesis commit.
2026-05-03 07:15:01 +00:00
Hermes Bot
afa7223c1a release: stamp v0.50.277 + Opus SHOULD-FIX (production-path regression guard)
CHANGELOG, ROADMAP, TESTING bumped (3925 → 3929 tests collected).

Opus SHOULD-FIX absorbed in-release: tests #1-3 documented the dedup
contract via direct construction but did not invoke get_models_grouped().
Test #4 (test_get_models_grouped_unconfigured_providers_get_independent_dicts)
inspects the live source for the literal copy.deepcopy(auto_detected_models)
call AND runs an end-to-end smoke of the fixed assignment loop.

A future refactor that removes the deepcopy at api/config.py:2078 will
fail this test immediately.
2026-05-03 06:47:52 +00:00
Hermes Bot
2420c6bda3 release: stamp v0.50.276 (PR #1508 — SW stale-CSS fix, closes #1507)
CHANGELOG, ROADMAP, TESTING all updated.
3923 → 3925 tests collected (+2 regression tests).

Pre-release Opus advisor pass: SHIP AS-IS.
Independent review: nesquena APPROVED with end-to-end trace.

Migration note: existing v0.50.275 users will see one more round of
broken styling on first reload after upgrade (old SW serves old
index.html). Subsequent reloads clean. Future upgrades will not
recur because SW pre-cache is now keyed on versioned URL.

Filed follow-up #1509 for __CACHE_VERSION__/__WEBUI_VERSION__
placeholder consolidation (low-priority cleanup, no functional impact).
2026-05-03 06:26:41 +00:00
Hermes Bot
995822ac0d release: stamp v0.50.275 (PR #1505 — /session/static/* MIME-type fix)
CHANGELOG, ROADMAP, TESTING all updated.
3918 → 3923 tests collected (+5 regression tests).

Pre-release Opus advisor pass: SHIP. Path-traversal sandbox confirmed
for literal .. and URL-encoded %2e%2e variants. Auth-exemption benign
(404s any sandbox escape before bytes leak).
2026-05-03 05:25:58 +00:00
Hermes Bot
3837ed8bf1 chore(release): stamp v0.50.274 — LM Studio onboarding fully fixed (#1499 #1500)
PR #1501 closes all three sub-bugs from #1420:
- #1499 (a): probe <base_url>/models before persisting
- #1499 (third sub-bug): keyless setup is a first-class state for self-hosted providers
- #1500: webui env var aligned with agent CLI's canonical LM_API_KEY

Backed by 60+ regression tests (38 new + 22 updated). Pre-release Opus
advisor pass: ship-ready. Independent review by nesquena: APPROVED with
4 non-blocking observations (1 fixed in-release, 3 deferred to follow-ups
#1502 + #1503 + future helper extraction).

Closes #1499, closes #1500.
Refs #1502 (legacy alias sunset tracking), #1503 (probe re-render UX papercut).
2026-05-03 03:33:07 +00:00
Hermes Bot
7cf9c81a49 docs(release): stamp v0.50.273 — CHANGELOG + ROADMAP + TESTING test counts 2026-05-03 02:15:00 +00:00
Hermes Bot
4aad62defb chore(release): stamp v0.50.272 — sidebar cancel + state.db FD leak fix + P0 polish bundle (#1466 #1494 #1469 #1484 #1486)
3 PRs in this batch (3866 → 3874 tests, +8):

- #1493 (@dso2ng) — sidebar Stop response cancels row's stream not active pane's (closes #1466, follow-up to #1480)
- #1495 (self-built; reported by @insecurejezza in #1494) — state.db connection FD leak in sidebar polling (closes #1494, addresses Bug #2 of #1458)
- #1492 (@bergeouss) — P0 bugfixes bundle: tool-card args readability + CLI rename persistence + scroll pinning + sw.js relative-path regression test (closes #1469 #1484 #1486)

This release closes Bug #2 of the umbrella issue #1458. Bug #1 was closed by v0.50.269 (#1483) + v0.50.270 (#1487). Bug #3 (HTTP-unhealthy without FD exhaustion) is the remaining work item.
2026-05-03 01:39:44 +00:00
Hermes Bot
63361ddb1c chore(release): stamp v0.50.271 — composer voice buttons UX (#1488) 2026-05-02 22:35:07 +00:00
Hermes Bot
dc36d7c977 chore(release): stamp v0.50.270 — bootstrap launcher import validation (#1315)
- CHANGELOG.md: v0.50.270 entry detailing #1315 + maintainer follow-ups
- ROADMAP.md: bump to v0.50.270, 3849 tests collected
- TESTING.md: bump header + total to 3849
- bootstrap.py: Opus advisor optional-followup — PYTHONPATH prepend comment

#1315 by @ccqqlo (113 LOC): bootstrap.py validates launcher Python can
import both yaml and run_agent.AIAgent. Companion fix to v0.50.269's #1478
— addresses the start-healthy-then-cryptic-fail mode (different from #1478's
supervisor-respawn loop).

3849 tests pass. Opus advisor verdict: ship as-is. CI green on contributor
branch + on local stage. QA harness all green.
2026-05-02 19:54:21 +00:00
Hermes Bot
e1708c4535 chore(release): stamp v0.50.269 — bootstrap supervisor fix + 2 v0.50.267 follow-ups
- CHANGELOG.md: v0.50.269 entry detailing #1478 #1479 #1480
- ROADMAP.md: bump to v0.50.269, 3847 tests collected
- TESTING.md: bump header + total to 3847

#1478: nesquena APPROVED self-built bootstrap.py --foreground mode
       (closes #1458 Bug #1, +Opus follow-ups: XPC noise filter, executability guard)
#1479: surgical follow-up to #1473 — Session.compact() now includes pending_user_message
#1480: bfcache pageshow restores active session via loadSession + checkInflightOnBoot

3847 tests pass (+47 net). Opus advisor on stage diff: no blockers.
2026-05-02 18:12:13 +00:00
Hermes Bot
bcfd8b2eac chore(release): stamp v0.50.268 — 4-PR batch + Opus follow-ups (i18n + per-session fields + None title guard)
- CHANGELOG.md: v0.50.268 entry detailing #1395 #1450 #1462 #1476 + Opus SHOULD-FIX followups
- ROADMAP.md: bump to v0.50.268, 3800 tests collected
- TESTING.md: bump header + total to 3800

SF-1 i18n fix:
- static/i18n.js: session_meta_children key in all 10 locale blocks (en, ja, ru, es, de, zh, zh-Hant x2, pt, ko)
- static/sessions.js: 2 callsites use t(session_meta_children, childCount)

SF-2 #1462 per-session field carry-over:
- api/routes.py: duplicate now carries personality, enabled_toolsets, context_length, threshold_tokens

SF-3 #1462 None-title guard:
- api/routes.py: (session.title or "Untitled") + " (copy)"

Tests:
- tests/test_stage268_opus_followups.py: 6 regression tests pinning SF-1 + SF-2 + SF-3
- tests/test_session_duplicate.py: 2 brittle assertions widened to accept new forms

Follow-up issue filed: #1481 (PWA /sw.js whitelist vestige, Opus SF-4)
2026-05-02 17:54:58 +00:00
Hermes Bot
3abae9aca7 chore(release): stamp v0.50.267 — 7 contributor PR batch + Opus follow-up
- CHANGELOG.md: v0.50.267 entry detailing #1454/#1474/#1461/#1465/#1467/#1460/#1473
  + Opus advisor SHOULD-FIX trailing-empty guard for _norm_model_id
- ROADMAP.md: bump to v0.50.267, 3776 tests collected
- TESTING.md: bump header + total to 3776
- api/config.py: trailing-empty fallback in _norm_model_id (parts[-1] or s)
- static/ui.js: mirror trailing-empty fallback in _normalizeConfiguredModelKey
- tests/test_norm_model_id_trailing_empty_guard.py: 5 regression tests
2026-05-02 17:03:25 +00:00