Commit graph

3193 commits

Author SHA1 Message Date
nesquena-hermes
359eae93de test: de-flake test_skills_stats_cache mtime race
test_skills_stats_cache asserted that adding a skill bumps the skills-dir
mtime so the cheap per-call probe recomputes counts on the next call. Two
_write_skill() calls inside the same coarse filesystem mtime tick could leave
the skills-dir mtime byte-identical to the cached probe value, so the probe
saw no change and served the stale count of 1 (assert enabled==2 failed). This
is an order-dependent flake: passes in isolation, fails intermittently under
full-suite ordering (observed across multiple unrelated PRs).

Force the skills-dir mtime strictly forward after the second write so the
probe is guaranteed to detect a genuine mtime change. The assertion stays
honest (it still proves recompute-on-mtime-change); only the race is removed.
2026-06-29 06:07:44 +00:00
nesquena-hermes
72f7530c45 ci: run tests across 5 shards (up from 3) + fix 2 latent test-isolation leaks
Two cross-file isolation leaks that a finer shard partition exposes are fixed at
root so every shard passes regardless of execution order:
- test_auth_session_persistence.py: bind api.auth STATE_DIR/_SESSIONS_FILE/
  _LOGIN_ATTEMPTS_FILE in setUp + restore in tearDown (was relying on a sibling
  reload test to rebind them).
- test_request_diagnostics_cache.py: pin the session-list cache source stamp via
  an autouse fixture (matches test_session_sidebar_cache.py) so a leaked state.db
  WAL sidecar can't cause a spurious cache-miss.

Verified all shards green under 3-, 4-, and 5-way partitions. CI infra + test
harness only; no application behavior change.
2026-06-29 05:55:16 +00:00
Frank Song
058372c15f Preserve empty anchor tool args in parity helper
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-29 05:35:03 +00:00
Frank Song
e670320337 Tighten anchor runtime journal parity test
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-29 05:35:03 +00:00
Frank Song
e1bf1122a7 Test anchor runtime journal parity 2026-06-29 05:35:03 +00:00
santastabber
178db13512 fix: authorize session html media artifacts 2026-06-29 05:17:33 +00:00
Stacey2911
dd658d7a04 fix(workspace): align Workspace Todos rendering with sidebar 2026-06-29 04:44:16 +00:00
Rod Boev
a98b0551c9 test(updates): keep launchd regression proofs faithful (#5175) 2026-06-29 04:22:51 +00:00
Rod Boev
a052f390f8 fix(updates): resolve git under macOS launchd (#5175) 2026-06-29 04:22:51 +00:00
nesquena-hermes
fae5c45395 Merge #5163 into stage/p1a 2026-06-29 04:07:21 +00:00
nesquena-hermes
65b27886d0 Merge #5166 into stage/p1a 2026-06-29 04:07:21 +00:00
Rod Boev
31a443ff88 fix(health): preserve restart failure contract and proofs (#5156) 2026-06-29 03:44:06 +00:00
Rod Boev
8b22c20061 fix(tests): tighten stash reset proof for agent update (#5156) 2026-06-29 03:44:06 +00:00
Rod Boev
6d80dd41d6 fix(updates): restart gateway after in-app agent update (#5156) 2026-06-29 03:44:06 +00:00
nesquena-hermes
16e280804b
Merge branch 'master' into fix/4657-fit-engine-rebased 2026-06-28 19:24:13 -07:00
claw-io
159298d319 fix(profiles): use profile-scoped resolver for /api/profile/active default_workspace (Codex gate #5169)
Codex flagged that get_last_workspace() falls back to the GLOBAL last_workspace.txt
before the profile config.yaml — so a named profile without its own
last_workspace.txt would leak the global path, re-introducing the #5169 bug.
Add get_profile_default_workspace() (profile last_workspace.txt -> config.yaml ->
terminal.cwd -> default, NO global fallback) and call it from /api/profile/active.
Adds a regression test: global last_workspace.txt present + named profile with
only config.yaml workspace must return the profile path, never the global.

Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-06-29 01:45:17 +00:00
nesquena-hermes
628d378857 chore(composer): drop #4657's quota-chip default-flip — keep just the fit-engine
Per maintainer decision: #4657 bundled a scope-creep change flipping
show_quota_chip default off->on plus a migration force-resetting stored false->true
(stomping explicit opt-outs). Master deliberately ships quota-chip default-off.
Reverted config.py + the quota-chip wiring in panels.js/boot.js + the quota test
to master, keeping ONLY the footer fit-by-overflow engine. The mobile quota-action
selector addition (hide_composer_quota_chip selectors) is kept (fit-related, not a
default change).

Co-authored-by: Paladin173 <Paladin173@users.noreply.github.com>
2026-06-29 01:38:34 +00:00
claw-io
ec0ef4a0d3 fix(profiles): show active profile workspace on blank new-chat (#5169)
Expose a profile-scoped default_workspace on GET /api/profile/active (resolved
by the profile-aware get_last_workspace(), fail-open) and hydrate boot.js from
it, overriding the global GET /api/settings value. GET /api/settings stays
global-only so the settings UI can't clobber the shared default. Combines
claw-io's #5173 (primary) with the fail-open backend hardening + regression test
from #5171.

Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-06-29 01:25:58 +00:00
nesquena-hermes
c6370235be feat(composer): fit footer controls by overflow (#4657, rebased onto master)
Rebased Paladin173's #4657 onto current master. The per-control visibility
toggles half already shipped via his own #4598, so this rebase carries only the
net-new JS fit-by-overflow engine (_fitComposerFooter: ResizeObserver +
MutationObserver measure .composer-left overflow, step full -> cf-icons ->
cf-burger). Co-authored-by: Paladin173 <Paladin173@users.noreply.github.com>
2026-06-29 01:19:02 +00:00
nesquena-hermes
c344844766 fix(#5132): split state.db sidebar override — source uncapped, count capped
Codex deep-gate caught a CORE regression in the original top-N cap: capping
_apply_sidebar_state_db_overrides also capped the SOURCE classification that
/api/sessions filters on BEFORE the lazy lineage correction, so a stale-CLI JSON
row whose state.db source is webui could be silently filtered out of a WebUI-only
sidebar once it fell beyond the cap. Split the read: the indexed sessions-table
source/title lookup runs for ALL rows; only the expensive messages COUNT/MAX
aggregation (the actual 5-18s bottleneck) is capped to top-N. Added a 500-row
end-to-end regression with a real state.db proving the beyond-cap stale-CLI row
stays webui.
2026-06-29 00:54:15 +00:00
nesquena-hermes
c646d92206 perf(#5132): cap /api/sessions state.db source/title overrides to top-N
On power-user instances with thousands of sessions, GET /api/sessions
blocked 5-18s in the all_sessions.state_db_overrides stage:
_apply_sidebar_state_db_overrides read state.db for every row (2400+ ids)
on every concurrent poll. With the gateway-watcher reading and the agent
writing the same state.db, this became lock/IO contention that piled up
concurrent polls and flapped the UI to 'Connection lost'.

Cap the override lookup to the top-N most-recent (paint-priority) rows
that are actually visible, mirroring the existing lineage-enrichment cap
(#4638). The caller passes an already pinned-first/newest-first sorted
list, so the top-N covers the visible window; rows beyond the cap keep
their JSON source/title and are corrected lazily on history-panel open.
Cap defaults to 300, env-configurable via
HERMES_WEBUI_STATE_DB_OVERRIDE_TOP_N (0 disables). Fails open.

Reported by @latipun, reproduced by @b3nw.

Co-authored-by: latipun <latipun@users.noreply.github.com>
2026-06-29 00:40:10 +00:00
nesquena-hermes
a8e921d13a fix(sidebar): scope hidden archived-parent references to active project + source
The sidebar_reference_sessions payload arrives project-unscoped from
/api/sessions. _renderSidebarRowsFromRawSessions appended it to EVERY
render unconditionally, so an archived parent in project B entered a
project-A-filtered render's suppression context and silently hid a
visible project-A child/fork (rendered as []). Add
_scopedSidebarReferenceRows() to filter references to the same project +
webui/cli source bucket as the render they feed, mirroring
_partitionSidebarSessionRows. Regression test locks the cross-project
case; the existing suppression test now exercises the scoped helper.

Co-authored-by: santastabber <santastabber@users.noreply.github.com>
2026-06-29 00:21:04 +00:00
santastabber
5ed0ba6ef6 fix(sidebar): keep hidden archived parents as child references 2026-06-29 00:13:32 +00:00
Rod Boev
e0f8f61e03 test(#5152): anchor resolver assertion to the new helper 2026-06-28 19:44:38 -04:00
nesquena-hermes
4d79de266c Merge master into stage-5155 (catch up to v0.51.728) 2026-06-28 23:25:57 +00:00
Rod Boev
4eb77da80e Keep settings-search coverage anchored 2026-06-28 19:24:51 -04:00
Rod Boev
dfeb21da98 fix(tests): accept Windows venv layout in scripts/test.sh (#5152) 2026-06-28 19:17:19 -04:00
nesquena-hermes
f968de8d35 merge #5155 extension settings surface 2026-06-28 23:07:00 +00:00
nesquena-hermes
9736e943bb merge #5151 distinguish offline gateway approval warnings 2026-06-28 22:54:54 +00:00
nesquena-hermes
751ba20fec merge #5129 surface provider auth failures in chat 2026-06-28 22:54:54 +00:00
nesquena-hermes
1a4dcd4fb5 merge #5128 custom-provider bare-model wakeup repair 2026-06-28 22:54:54 +00:00
Rod Boev
ec00e037f3 fix(settings): widen busy-input settings search coverage (#5148) 2026-06-28 18:47:42 -04:00
Rod Boev
7153e8d78f fix(extensions): prune malformed browser overrides (#5094) 2026-06-28 18:31:43 -04:00
Rod Boev
234fefe6ee fix(#5139): keep timeout capability probes on the unsupported path 2026-06-28 18:29:37 -04:00
Rod Boev
aef8e524fd fix(extensions): keep settings-only installs canonical (#5094) 2026-06-28 18:25:47 -04:00
nesquena-hermes
fc02953ea6 Merge branch 'pr-5117-head' into stage/5117-defer 2026-06-28 22:25:26 +00:00
Rod Boev
269d2e4d93 test(#5139): isolate the 404 warning regression from shared cache state 2026-06-28 18:23:20 -04:00
nesquena-hermes
7b12dff3e6 test(#5121): make auth-failure tests host-independent
The 4 terminal-auth-failure tests assert an unrecoverable 401 surfaces an
apperror / persisted _error turn. The settlement path first attempts the
#1401 credential self-heal, which reads ~/.hermes/auth.json. On a host with
populated credentials, self-heal can succeed and retry the mock agent,
swallowing the error the test expects -- so the result depended on host
credentials (green on CI / Windows with no creds, red on a live agent box).

Add an autouse fixture that forces _attempt_credential_self_heal to a no-op
so every host exercises the unrecoverable-failure path. The one test that
verifies a successful retry already patches the symbol in its own body, so it
is unaffected.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-06-28 22:20:28 +00:00
Rod Boev
23b7a7935a fix(#5139): keep older gateways on the unsupported warning path 2026-06-28 18:18:47 -04:00
Rod Boev
46d91a7c61 fix(extensions): render installed controls from trusted state (#5094) 2026-06-28 18:15:36 -04:00
Rod Boev
938f721b16 fix(extensions): reload before editing untrusted installs (#5094) 2026-06-28 18:07:52 -04:00
Rod Boev
615b023eb0 fix(extensions): pin schemas to trusted bootstrap state (#5094) 2026-06-28 17:59:36 -04:00
Rod Boev
343a8b50bf fix(#5139): distinguish offline gateway approval warnings 2026-06-28 17:53:37 -04:00
b3nw
7a04b7e9aa fix: gate bare-model repair on profile provider match (#5128 review)
When session model_provider differs from profile model.provider, do not
expose profile_default_model for suffix repair. Fast path also requires
profile_provider to match requested_provider when profile_provider is set.

Addresses cross-provider mis-resolution (custom:other-proxy + bare suffix).

Co-authored-by: b3nw <b3nw@users.noreply.github.com>
2026-06-28 21:52:06 +00:00
Rod Boev
cb96a5cf39 fix(extensions): trust only bootstrapped extension ids (#5094) 2026-06-28 17:51:42 -04:00
nesquena-hermes
c556262159 Merge branch 'pr-5147-head' into stage/5147-approval 2026-06-28 21:48:51 +00:00
Rod Boev
07ed67a793 fix(extensions): keep runtime settings gated on owned storage (#5094) 2026-06-28 17:44:02 -04:00
Rod Boev
62be5b02ea fix(#5135): clear stale gateway approval mirrors on stream teardown 2026-06-28 17:32:55 -04:00
Rod Boev
a76c794d6d feat(extensions): add browser-local extension settings surface (#5094) 2026-06-28 17:28:20 -04:00
nesquena-hermes
fc087c067f Merge branch 'pr-5118-head' into stage/5118-scroll 2026-06-28 21:22:53 +00:00