Commit graph

7201 commits

Author SHA1 Message Date
nesquena-hermes
ca9444292d Release exp: Nix flake/NixOS module (#5431) + composer-focus shortcut (#5795). Thanks @rodboev.
#5431 (#2422): optional Nix flake + NixOS systemd module. Codex SAFE — zero non-Nix
  impact (only guarded bootstrap.py fallback touches core), secure-by-default
  (loopback, 0700/0077, non-root, EnvironmentFile secrets), 100 tests.
#5795 (#5759): Cmd/Ctrl+/ focuses composer. Codex SAFE after maintainer fix
  (matched e.key==='/' not physical Slash code so QWERTZ Ctrl+- zoom isn't stolen
  + shifted-/ works); focus-only, guarded, no conflict, 4 tests.
2026-07-14 01:25:40 +00:00
nesquena-hermes
7c3eae400a Merge branch 'rebase-5431' into stage/nix-slash 2026-07-14 01:24:31 +00:00
nesquena-hermes
ccbaa4ba61 Merge branch 'rebase-5795' into stage/nix-slash 2026-07-14 01:24:31 +00:00
nesquena-hermes
7b210baca4 fix(#5759): match composer-focus chord on '/' char not physical Slash code
The Cmd/Ctrl+/ predicate keyed off e.code==='Slash' + !e.shiftKey, which on
QWERTZ layouts (a) stole Ctrl/Cmd+- browser zoom-out (physical Slash there is
the minus/zoom key) and (b) missed the real shifted-'/' chord. Match e.key==='/'
instead — layout-correct on every keyboard. Tests updated to assert the physical
code isn't used and a layout-shifted '/' still matches.

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
2026-07-14 01:20:12 +00:00
Rod Boev
9bd96fb75d fix(#2422): support packaged Hermes Agent discovery 2026-07-14 01:06:49 +00:00
Rod Boev
53348df68d fix(#2422): allow Nix package version generation 2026-07-14 01:06:49 +00:00
Rod Boev
b7f523c3a1 fix(#2422): tighten Nix module polish 2026-07-14 01:06:49 +00:00
Rod Boev
243f27e7ed fix(#2422): keep NixOS state private 2026-07-14 01:06:49 +00:00
Rod Boev
72b51a6b78 fix(#2422): avoid hardcoded agent site packages 2026-07-14 01:06:49 +00:00
Rod Boev
70514549c4 fix(#2422): harden NixOS packaged runtime 2026-07-14 01:06:49 +00:00
Rod Boev
1f505aad88 fix(#2422): pin the flake input for reproducible builds 2026-07-14 01:06:49 +00:00
Rod Boev
654a691155 fix(#2422): keep the Nix launch path declarative 2026-07-14 01:06:48 +00:00
Rod Boev
5bd940a49b fix(#2422): honor the service-mode host default 2026-07-14 01:06:48 +00:00
Rod Boev
d77d956380 fix(#2422): validate env files before user drop 2026-07-14 01:06:48 +00:00
Rod Boev
09003b5e92 feat(#2422): add Nix flake package and NixOS module 2026-07-14 01:06:48 +00:00
Rod Boev
37b51803e6 Keep composer focus shortcut easy to reach 2026-07-14 01:06:46 +00:00
Rod Boev
ca5f02bbff feat(#5759): add composer focus shortcut 2026-07-14 01:06:46 +00:00
nesquena-hermes
11eb1b7a83
docs(changelog): stamp v0.52.28 stable section (first promotion since v0.52.0) (#6046)
Cuts the promoted range's bullets from [Unreleased] into a stamped
## [v0.52.28] section (41 bullets, v0.52.0..v0.52.28). Companion to the
v0.52.28 stable tag pushed by the promotion engine.

Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-07-13 16:54:47 -07:00
nesquena-hermes
a1b60f304e
Merge pull request #6044 from nesquena/stage/6042-ttft
Release exp: send-to-first-token latency instrumentation (#6042, #6006)
2026-07-13 15:56:49 -07:00
nesquena-hermes
7fb3d412f5 Release exp: instrument send-to-first-token latency (#6042, closes #6006). Thanks @rodboev.
Measure-only TTFT (ttft_ms) on the metering session + _firstTokenMs diagnostic. Computed once
on first token (no hot-path latency), all mutation under existing GlobalMeter._lock, existing
token/usage/cost metering unchanged. Codex SAFE (16-stream concurrency probe, no leak/None-deref)
+ stream-gate GREEN all modes + 22 tests.
2026-07-13 22:52:15 +00:00
nesquena-hermes
f1480ad407 Merge branch 'rebase-6042' into stage/6042-ttft 2026-07-13 22:51:55 +00:00
Rod Boev
001d7985bc feat(#6006): instrument send-to-first-token latency 2026-07-13 17:56:44 -04:00
nesquena-hermes
e5148f9dbe
Merge pull request #6036 from nesquena/stage/6035-approval
Release exp: fix 'approve once' persisting as session approval (#6035, #6017)
2026-07-13 13:25:18 -07:00
nesquena-hermes
ea5af7b6c8 Release exp: fix 'approve once' persisting as session approval (#6035, closes #6017). Thanks @rudidev08.
Local (non-gateway) _resolve_approval_legacy collapsed 'once'+'session' into approve_session()
→ 'approve once' silently persisted session-wide. Narrowed to choice=='session' only; 'once'
still resolves the current call but doesn't persist. Codex SAFE (adversarial: once resolves
current+no residue+next re-prompts, session/always/deny unregressed, gateway consistent, tests
non-vacuous + parked-thread probe of all 4 choices).
2026-07-13 20:16:26 +00:00
nesquena-hermes
b86922ae38 Merge branch 'rebase-6035' into stage/6035-approval 2026-07-13 20:15:59 +00:00
rudidev08
34cf2de57a Fix: "Approve once" no longer persists as a session approval (#6017)
In the local (non-gateway) approval path, _resolve_approval_legacy grouped
"once" together with "session" and called approve_session() for both.
approve_session() records the pattern in the session-wide allowlist that the
guard later consults, so a single "Approve once" click silently approved every
later matching tool call for the whole session -- a destructive tool could then
run with no approval card.

Only "session"/"always" persist now. "once" falls through: the
resolve_gateway_approval() call below still unblocks the parked agent thread for
every choice, so the current tool call proceeds, but nothing is written to
_session_approved and the next matching guarded call re-prompts.

Adds tests/test_issue6017_approve_once_no_persist.py, asserting is_approved is
False after "once" and True after "session".
2026-07-13 13:05:52 -07:00
nesquena-hermes
07a1fad2c8
Merge pull request #6034 from nesquena/stage/6019-a11y
Release exp: a11y keyboard access for conversation actions menu (#6019)
2026-07-13 12:42:32 -07:00
nesquena-hermes
d6684c091f Release exp: keyboard/screen-reader access for conversation actions menu (#6019). Thanks @sheldon-im.
ARIA (aria-expanded/controls, role=menu/menuitem) + focus-to-first-action on open +
Arrow/Home/End/Escape nav + focus-restore-to-trigger on close; existing click/touch unchanged.
Codex SAFE (isConnected-guarded restore, menu-scoped bounded arrow-nav, no listener leak
[25-cycle probe], 49 tests) + stream-gate GREEN.
2026-07-13 19:37:56 +00:00
nesquena-hermes
e02636c58c Merge branch 'rebase-6019' into stage/6019-a11y 2026-07-13 19:24:30 +00:00
sheldon-im
d7c2cc2d5d Restore focus from non-button session action menus 2026-07-13 19:24:09 +00:00
sheldon-im
bc85711af2 Improve conversation actions menu keyboard access 2026-07-13 19:24:09 +00:00
nesquena-hermes
41f1eb5624
Merge pull request #6032 from nesquena/stage/r2-batch
Release exp: Round-2 batch — picker dedup (#5997) + zh-CN i18n (#6024)
2026-07-13 12:20:51 -07:00
nesquena-hermes
735d74df46 Release exp: Round-2 batch — model-picker dedup (#5997) + zh-CN localization fill (#6024)
#5997 (rodboev, closes #5989): proxy/catalog model-picker dedup, 4-round convergence.
  Colon-suffix collision closed (provider-context exact-prefix strip, :free/:thinking/:latest
  survive), 5 prior findings stay fixed. Codex SAFE r4 (73 tests) + stream-gate GREEN.
#6024 (Loukky): zh-CN localization fill (+55/-55, pure value replacement on existing keys,
  no key add/remove, no value-swap [en block 0 CJK], placeholders preserved).
Disjoint (static/ui.js picker logic / static/i18n.js locale data).
2026-07-13 19:17:13 +00:00
nesquena-hermes
4016130c24 Merge branch 'rebase-6024' into stage/r2-batch 2026-07-13 19:04:13 +00:00
nesquena-hermes
54a7bb2058 Merge branch 'rebase-5997' into stage/r2-batch 2026-07-13 19:04:12 +00:00
Loukky
d1aa5945b6 Update i18n.js 2026-07-13 18:57:49 +00:00
Loukky
6ccf9168f2 [locale]Localization for Simplified Chinese
Translate all untranslated English strings into Simplified Chinese.
2026-07-13 18:57:49 +00:00
Rod Boev
3ada146d48 fix(#5989): keep colon-suffixed proxy models distinct 2026-07-13 18:57:15 +00:00
Rod Boev
ff89f2ebd6 fix(#5989): keep cross-provider live rows selectable 2026-07-13 18:57:15 +00:00
Rod Boev
58725d5de9 fix(#5989): separate picker dedup from restore matching 2026-07-13 18:57:15 +00:00
Rod Boev
052effcfc4 fix(#5989): deduplicate proxy and catalog model rows in the picker 2026-07-13 18:57:15 +00:00
nesquena-hermes
e4188ccd5e
Merge pull request #6031 from nesquena/stage/6028-solo
Release exp: worktree unlock-before-remove (#6028, #6023)
2026-07-13 11:31:19 -07:00
nesquena-hermes
996705b7b1 Release exp: worktree unlock-before-remove so WebUI worktrees are reapable (#6028, #6023). Thanks @ayxuerui.
Fail-soft git worktree unlock before remove (agent locks worktrees it creates; git refuses
--force remove on locked → orphan accumulation). Dirty-guard still runs first. Codex SAFE,
13 tests pass. Shipped solo (unbundled from #6013 which has a full-suite test-interaction).
2026-07-13 18:27:44 +00:00
nesquena-hermes
1e2a01102a Merge branch 'verify-6028' into stage/6028-solo 2026-07-13 18:27:23 +00:00
Rui Xue
c833f290a9 fix(worktrees): unlock before remove so WebUI-created worktrees can be reaped
WebUI-created worktrees are locked at creation by the agent
(cli._setup_worktree locks with --reason 'hermes pid=...'), but
remove_worktree_for_session never unlocked, so git refused every removal
with "use 'remove -f -f' to override or unlock first" — force=true
included, since a single --force cannot override a lock.

Mirror the agent's own _cleanup_worktree ordering: fail-soft
'git worktree unlock' right before the remove, after all
dirty/untracked/unpushed/stream/terminal guards have passed. Those
guards remain the real safety layer; force keeps meaning 'override
dirty working state', never 'override a foreign lock'.

Tests: locked worktree now removes cleanly without force; unlock is
fail-soft when the worktree was never locked; existing mocked
call-order assertions updated for the leading unlock call.

Fixes #6023
2026-07-13 17:47:58 +00:00
nesquena-hermes
d486394f7b
Merge pull request #6012 from nesquena/stage/5802-media
Release exp: render MEDIA: tokens inline during streaming (#5802)
2026-07-13 01:21:25 -07:00
nesquena-hermes
42d62e0793 Release exp: render MEDIA: tokens inline during streaming (#5802). Thanks @silent-reader-cn.
MEDIA tokens (image/video/audio/pdf/diff/csv/excalidraw) render inline in real time
during streaming incl split-across-chunk markers. Codex SAFE r4 (both prose regressions
closed — ownership preserved + fade retained, normal prose byte-identical to master, all
4 original findings fixed, security clean, no ReDoS), stream-gate GREEN all modes (hide_all
RED was load flake, isolated re-run clean). 227 tests + 18 real-SMD subtests pass. 4-round
convergence on the crown-jewel render + security path.
2026-07-13 08:17:52 +00:00
nesquena-hermes
2d1a2d15a0 Merge branch 'rebase-5802' into stage/5802-media 2026-07-13 08:06:28 +00:00
silent-reader-cn
946f7dbc2b fix(media): preserve scanner prose ownership 2026-07-13 07:41:13 +00:00
silent-reader-cn
e13a75b7b1 test(media): cover fade MEDIA streaming splits 2026-07-13 07:41:13 +00:00