Commit Graph
4353 Commits
Author SHA1 Message Date
rudidev08 6c8d130a7b fix: classify Matrix gateway sessions as messaging 2026-08-07 21:54:52 +00:00
nesquena-hermes d018233e84 lint: remove unused pathlib import in #6498 test (ruff F401) 2026-08-06 02:41:27 +00:00
nesquena-hermes 2c9e621b3d Merge PR #6498: gate memory/user-profile reads via nested config (re-gate) 2026-08-06 02:26:24 +00:00
webtecnica a5b1898e20 fix(api): read memory flags from nested memory config section (#6498) 2026-08-05 22:23:55 -03:00
nesquena-hermes 874d62bc3a Merge PR #6486: show final assistant report with tool-limit status card 2026-08-06 01:05:50 +00:00
nesquena-hermes 8ecf391340 Merge PR #6670: don't duplicate active turn's user row on mid-run reload 2026-08-06 00:26:35 +00:00
nesquena-hermes 4c042dbfdf Merge PR #6688: clean dirty stable no-ref checkouts on Force recovery 2026-08-05 23:20:27 +00:00
nesquena-hermes a260746d04 Merge PR #6663: warn on ambiguous legacy OIDC allow_values scalars 2026-08-05 22:53:47 +00:00
nesquena-hermes 8fc9a7e2de Merge PR #6706: HTML inline preview no-store (fix stale preview) 2026-08-05 22:22:23 +00:00
nesquena-hermes bbe5283e99 Merge PR #6690: fix CLI sessions unreadable on named profiles 2026-08-05 21:39:06 +00:00
nesquena-hermes 0e122174be Merge PR #6763: fix(workspace) open artifacts with Windows backslash paths 2026-08-05 21:39:05 +00:00
nesquena-hermes c7b5a2cba5 Merge PR #6614: guard _autoScrollFollow ReferenceError before settings init 2026-08-05 21:14:57 +00:00
fatbee0808 5a01ce11cd test(workspace): cover Windows backslash artifact open paths
openArtifactPath/_workspacePathExists split on '/' but Windows artifact
paths arrive as backslash absolute paths. Regression tests drive the real
functions from static/workspace.js via node (mirroring
test_issue3262_artifact_path_canonicalization.py): backslash subdir and
root artifacts must open, POSIX relative clicks must keep working, and a
genuinely missing artifact must still surface file_open_failed.
2026-08-05 11:26:27 +08:00
Rod Boev c91fb55064 fix(#4085): restore legacy dirty contract for non-status-1 exits 2026-08-04 10:58:24 -04:00
webtecnica ed09ee6930 fix(api): request-owned config snapshot for memory gates (#6498)
- _handle_memory_read: pass the request-owned get_config_snapshot() into
  _external_notes_sources_enabled() so no ambient/process-global config is
  re-read later in the handler (review requirement).
- tests: add cross-profile forced-reload regressions for both directions
  (A disabled/B enabled and inverse), covering memory_enabled and
  user_profile_enabled for read (no content/path/mtime) and write (403 +
  byte-identical file).
- tests: adapt _external_notes_sources_enabled mock arity in
  test_3866_project_context_memory_section.py to the new snapshot param.
2026-08-04 11:46:32 -03:00
happy5318 5cda58fc9b fix: match active turn by exact identity (token/epsilon), not 1.5s proximity
Review round 2: the 1.5s timestamp tolerance over-deduped a legitimate
rapid repeat — two identical-text turns <1.5s apart collapsed into one,
hiding the second turn and copying its attachments onto the earlier row
(the mirror risk of #6649).

_pendingActiveTurnUserMessage now matches only on unambiguous identity:
- the row carries the server-stamped _active_turn_token (stream_id +
  started_at, per build_active_turn_token), or
- its timestamp equals pending_started_at within a precision-only
  epsilon (1e-6, absorbs float/state.db drift, never a full second).

Anything wider (whole-second truncation, ~1s rapid repeat) returns null
so getPendingSessionMessage() materializes the pending turn — fail
toward the harmless transient duplicate the settle render clears.

Regressions added: two completed identical-text turns ~1s apart → second
pending row returned + first row's attachments untouched; token-identity
row adopted even when its timestamp is outside the epsilon.
2026-08-03 13:46:56 +08:00
happy5318 22b155e8d0 test: strengthen HTML preview cache regression coverage
Per review feedback:
- Frontend: assert exact fetch(mediaUrl, {cache:'no-store'}) in
  loadHtmlInline body, not just 'fetch(mediaUrl' prefix (too broad,
  other fetch calls match the prefix)
- Backend: assert Cache-Control: no-store on both attachment and inline
  HTML responses in test_html_media_endpoint_inline_requires_csp_sandbox
- Both assertions fail independently if either the frontend no-store
  option or backend no-store policy is reverted
2026-08-02 18:10:18 +08:00
happy5318 5f5ebd259e test: update fetch assertion for no-store cache option 2026-08-02 16:54:17 +08:00
webtecnica 6dd1fed8d3 fix(ui): guard all bare _autoScrollFollow reads (#6614) 2026-08-01 17:52:30 -03:00
Zhike ChenandClaude Opus 5 ef8f42c7b4 fix: resolve CLI session display in WebUI
Claude Code sessions listed in the sidebar rendered "Session not available
in web UI." when clicked under a named (non-root) profile.

Root cause: get_claude_code_sessions() scans ~/.claude/projects and stamps
profile=None on every row, because those JSONL transcripts belong to no
Hermes profile. /api/sessions lists them regardless of active profile, but
the GET /api/session detail load ran them through
_session_visible_to_active_profile, whose _profiles_match coerces None ->
'default'. With hermes_profile=feng-family active, the gate 404'd before
_claim_or_synthesize_cli_session ever ran, so the frontend hit its 404
branch and painted the empty-state message. POST /api/session/import_cli
correctly returned 200 with an inline read-only payload (Claude Code
sessions are read_only by design and never get a sidecar), which is why no
file appeared in webui/sessions/ -- Session.save() was never supposed to
run and was not silently failing.

Exempt profile-less claude_code rows from the detail-load profile gate via
_is_profile_agnostic_foreign_session(). Profile-tagged foreign rows keep
the #5419 409 cross-profile contract.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 02:01:09 +08:00
Rod Boev f6903c4f34 test(#4085): preserve version badge dirtiness 2026-08-01 11:55:30 -04:00
Rod Boev 678a1ee926 fix(#4085): align dirty display probes 2026-08-01 11:16:57 -04:00
Rod Boev 5f8fd9d85a test(#4085): preserve checker dirty-state compatibility 2026-08-01 08:08:24 -04:00
Rod Boev a261e46e7e test(#4085): prove stable force no-op preservation 2026-08-01 07:48:19 -04:00
Rod Boev 95a5bc37e8 fix(#4085): classify dirty probe failures safely 2026-08-01 07:23:35 -04:00
Rod Boev 83c4013774 fix(#4085): harden dirty stable recovery 2026-08-01 06:41:01 -04:00
Rod Boev d0cceea54a fix(#4085): recover dirty stable checkout 2026-08-01 06:13:09 -04:00
Rod Boev 737ba90440 fix(auth): align OIDC startup checks with runtime normalization (#6603) 2026-08-01 05:53:07 -04:00
happy5318 55af555846 fix: do not duplicate the active turn's user row on mid-run reload
While a turn is live the server can reconcile that turn's user row into the
transcript returned by /api/session (the sidecar/state.db merge picks it up
from state.db, where the agent writes it immediately) while
pending_user_message is still set. The row is then followed by the same
turn's assistant/tool rows.

_pendingCurrentTailUserMessage() scans the tail backwards and returns null as
soon as it meets a completed assistant, so in that state it reports "the
current turn has no user row". getPendingSessionMessage() then materializes
pending_user_message a second time and the pane renders two identical user
bubbles until the settle render replaces the list wholesale (which is why the
duplicate disappears when the answer lands, and why nothing wrong is ever
persisted).

Scanning past assistant/tool rows on text alone would regress #3300: a user
who submits the same text twice in a row legitimately gets two identical user
turns. Use pending_started_at as the discriminator instead — the server stamps
the active turn's user row with it, and no earlier turn can share it. Text
equality is still required, so a false match needs identical text AND a
near-identical timestamp. Absent/invalid pending_started_at disables the
fallback and keeps the previous strict-tail behaviour.

Verified: the new midRunReloadDedupe assertion fails on the unpatched ui.js
and passes with the fix; the existing repeat-prompt, compaction-boundary and
strict-tail assertions still pass.
2026-08-01 12:07:45 +08:00
Rod Boev 042804fd5a fix(auth): surface ambiguous OIDC allowlist scalars at startup (#6603) 2026-07-31 20:16:57 -04:00
Rod Boev a4ea848f38 fix(auth): detect all Unicode whitespace in ambiguous allowlist scalars (#6603) 2026-07-31 19:51:57 -04:00
Rod Boev ab11795aa4 fix(auth): warn on ambiguous legacy OIDC allowlist scalars (#6603) 2026-07-31 19:14:44 -04:00
nesquena-hermes 32581913ba test: correct staged-source lifecycle wording 2026-07-31 19:42:07 +00:00
qxxaa 3c6566b430 fix(docker): stage editable source under persistent /app/ path
Move the staged agent source from /tmp/hermes-agent-build (ephemeral
tmpfs) to /app/hermes-agent-src (persistent, same lifecycle as the
venv). The editable install records this path in a .pth file - placing
it alongside the venv ensures both survive container restarts and are
lost together on recreation, eliminating the dangling-link class of
bugs without sentinel files or state machines.

Three states now handled by lifecycle equivalence:
- First boot: stages source, installs editable, writes .deps_installed
- Restart (same container): .deps_installed + staged source both present
- Recreation (new container): both gone, fresh boot re-stages
2026-07-31 19:26:34 +00:00
nesquena-hermes d85eb85c25 Merge branch 'master' into fix/interim-anchor-final-character 2026-07-31 11:52:58 -07:00
nesquena-hermes 07b33505fd Merge branch 'master' into franksong2702/fix-gateway-terminal-persistence 2026-07-31 11:47:43 -07:00
nesquena-hermes d482a12345 Merge branch 'master' into franksong2702/viewport-scroll-anchor-6414 2026-07-31 11:40:47 -07:00
Nathan Esquenazi 94a2091435 Merge branch 'master' into fix/interim-anchor-final-character 2026-07-31 11:11:50 -07:00
Nathan Esquenazi 15e3e89c3c Merge branch 'master' into franksong2702/fix-gateway-terminal-persistence 2026-07-31 11:09:50 -07:00
Nathan Esquenazi eb1484bede Merge branch 'master' into franksong2702/viewport-scroll-anchor-6414 2026-07-31 11:09:39 -07:00
Nathan Esquenazi 46623de2bd Merge branch 'master' into fix/preflight-compression-false-positive 2026-07-31 11:09:09 -07:00
Frank SongandFrank Song 89023eb191 Live-to-Final: prove historical hydration and fence terminal retry ownership (#6451)
* test: add historical hydration lifecycle proof

* fix: retry anchor persistence after terminal app errors

* fix: fence deferred anchor settlement ownership

* test: cover deferred anchor retry ownership

* fix: preserve terminal anchor retry across refresh

* fix: bind terminal anchor retry to turn owner

---------

Co-authored-by: Frank Song <franksong2702@gmail.com>
2026-07-31 11:04:40 -07:00
happy5318 f52be26610 docs: update comments to reflect preflight exclusion reasoning
Clarify that preflight compression is intentionally excluded because
the later authoritative 'Compacting context' marker from
conversation_compression is the real signal that compression
proceeded. The preflight status can fire even when compression
exits before compaction (e.g. durable guard refresh, Codex-Hermes
mode with no active thread).
2026-08-01 01:47:51 +08:00
happy5318 9c1c1d8063 fix: stop false Compressing-context card for preflight compression
PR #6184 narrowed the agent-status-to-SSE bridge to real compression
start notices, but the 'preflight compression:' pattern matches the
Hermes agent's preflight check message ("Preflight compression: ~X
tokens >= Y threshold"). This fires on every new session where the
system prompt alone exceeds the threshold, showing a "Compressing
context" card before any model output — a false positive.

Remove 'preflight compression:' from the pattern. The preflight check
is a one-time pre-model-call estimate, not a mid-conversation
compression event that the user needs to see.
2026-08-01 01:07:12 +08:00
Frank Song c69f1a73dc test: exercise renderer scroll restore ownership 2026-07-31 22:24:25 +08:00
Frank Song fd1879418d fix: queue pinned live scroll ownership check 2026-07-31 22:24:25 +08:00
Frank Song c32b10ee8b test: update live scroll fixture contracts 2026-07-31 22:24:25 +08:00
Frank Song cc5cf19710 test: exercise reachable live scroll restore boundary 2026-07-31 22:24:25 +08:00
Frank Song 713418dec0 test: cover live render scroll ownership boundary 2026-07-31 22:24:25 +08:00
Frank Song 7a320bea3c fix: preserve live scroll ownership on snapshot mismatch 2026-07-31 22:24:25 +08:00