Skip to content

fix(managed_uv): add missing hermes_state_* modules to py-modules for replacement env smoke tests - #74506

Open
webtecnica wants to merge 3 commits into
NousResearch:mainfrom
webtecnica:fix/74479-replacement-env-smoke
Open

fix(managed_uv): add missing hermes_state_* modules to py-modules for replacement env smoke tests#74506
webtecnica wants to merge 3 commits into
NousResearch:mainfrom
webtecnica:fix/74479-replacement-env-smoke

Conversation

@webtecnica

Copy link
Copy Markdown
Contributor

Problem

The replacement environment smoke test (_smoke_candidate_venv) runs
python -I -c "import ... hermes_state" in isolated mode on the
candidate venv. hermes_state.py imports four sibling top-level
modules:

  • hermes_state_common
  • hermes_state_portability
  • hermes_state_schema
  • hermes_state_search

These were NOT listed in pyproject.toml's py-modules, so
setuptools/uv never installs them into the venv's site-packages, and
the editable finder's MAPPING dict doesn't cover them. In normal CLI
usage (no -I), the current directory's sys.path[0] entry lets
Python resolve them. But in isolated mode (-I), the current
directory is not searched, producing ModuleNotFoundError: No module named 'hermes_state_common' — causing the entire replacement
environment to be rejected.

Fixes #74479

Root Cause

hermes_state.py imports hermes_state_common, hermes_state_portability,
hermes_state_schema, and hermes_state_search at the top of the file.
These are top-level .py files in the repository root (not part of any
package). The pyproject.toml [tool.setuptools] py-modules list tells
setuptools which standalone modules to include in the distribution. Any
module not listed there is never installed into the venv.

When uv sync creates an editable install, it generates an
__editable___hermes_agent_0_19_0_finder.py file with a MAPPING dict
that translates module names to filesystem paths. Only modules listed
in py-modules appear in MAPPING. Modules that are missing from
MAPPING but are imported by other modules in MAPPING fail with
ModuleNotFoundError in isolated mode.

Changes

  1. pyproject.toml: Added hermes_state_common, hermes_state_portability,
    hermes_state_schema, and hermes_state_search to the py-modules list.

  2. hermes_cli/managed_uv.py: Log the full smoke stderr output at debug
    level (logger.debug) so future failures include the complete traceback
    instead of just the last line of the error.

Verification

Before the fix, running python -I -c "import hermes_state" from the
repository root fails with:

ModuleNotFoundError: No module named 'hermes_state_common'

After the fix (after uv sync regenerates the editable finder),
hermes_state_common and the other three modules will be in the
MAPPING and the import will succeed in isolated mode.

…g early (NousResearch#74465)

get_custom_provider_extra_headers() was returning the result of
normalize_extra_headers() on the first matching base_url, even when
that entry had no extra_headers configured. A later providers.<name>
entry sharing the same URL but with headers set was therefore ignored.

Fix: store the normalized headers and only return when non-empty,
otherwise continue searching the remaining entries.

Fixes NousResearch#74465
…earch#74478)

P1: turns abort with "session storage could not be written" when a
sibling process holds the state.db write lock longer than ~1.3s.

Root cause: SessionDB._execute_write used attempt-counted retries
(15 * 20-150ms ≈ 1.3s max), but shared state.db can be legitimately
held for multiple seconds by VACUUM, WAL checkpoint, offline recovery,
or mixed-version connection pools. The SessionDB() open path had zero
retry for locked/busy errors.

Changes:
- Replace _WRITE_MAX_RETRIES=15 with time-based patience:
  routine (20s) and transcript-critical (60s) budgets
- Add _WRITE_BACKOFF_AFTER_S=2.0: first 2s uses 20-150ms uniform
  jitter (preserving existing convoy-breaking behavior), then
  linearly ramps max sleep to _WRITE_BACKOFF_MAX_S=1.0
- Mark append_message as critical=True so transcript writes get
  the full 60s window
- Add locked/busy retry loop around _connect_and_init() in __init__,
  using the same routine patience budget
- Replace "database is locked after max retries" with an actionable
  error that names the real cause (sibling process holding the lock),
  not disk corruption
… replacement env smoke tests

The replacement environment smoke test (_smoke_candidate_venv) runs
'python -I -c "import ... hermes_state"' in isolated mode on the
candidate venv. hermes_state.py imports four sibling top-level
modules (hermes_state_common, hermes_state_portability,
hermes_state_schema, hermes_state_search) that were NOT listed in
pyproject.toml's py-modules.

Without a py-modules entry, setuptools/uv never installs these
modules into the venv's site-packages, and the editable finder's
MAPPING doesn't cover them. In the regular CLI (no -I) the current
directory's sys.path[0] entry lets Python resolve them, but in
the isolated mode used by _smoke_candidate_venv the current
directory is not searched. The result is ModuleNotFoundError
for hermes_state_common -- causing the entire replacement
environment to be rejected.

Also logs full smoke stderr at debug level so future failures
include the complete traceback instead of just the last line.

Fixes NousResearch#74479
@webtecnica
webtecnica requested a review from a team July 30, 2026 01:14
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint area/install-update Installer, updater, packaging, wheels, doctor python:uv Pull requests that update python:uv code P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 30, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks — the managed-UV packaging diagnosis is valid on current main, and the stacked config fix is also still needed.

Problems

  • 9526ebb6de5abc90f1e6d502a81a5f43c09f9f61 is redundant: current main already has the lock-patience implementation in hermes_state.py:1920-1959, 2317-2396, and 5607-5614, shipped by 8da8a7887d06373e169af6e431ec52ebb439ec7a.
  • The pyproject.toml correction has no regression that exercises the isolated candidate/editable import path. Current main still omits the four imported state modules from py-modules at pyproject.toml:349, while hermes_state.py:45 and 70-72 import them.

Suggested changes

  • Salvage the packaging commit and the still-needed duplicate-URL header fix (0984788bd187d8b373f2d544567d26d317215e50) independently; omit the already-implemented SessionDB commit.
  • Add a temporary isolated-environment smoke regression for import hermes_state.

Automated hermes-sweeper review.

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

One PR, #74506, references #74479. Its pyproject.toml change directly addresses the isolated-import failure by packaging the four hermes_state_* modules, while its managed-UV logging is diagnostic and its custom-provider-header and SessionDB changes address separate concerns.

Related pull requests

Duplicates

The pyproject.toml portion of #74506 duplicates the packaging correction already applied by #74362; no competing open PR duplicates the remaining custom-provider-header fix.

Suggested consolidation

Keep #74506 open with a salvage path: rebase it onto current main and split out the duplicate-URL custom-provider-header fix, retain the managed-UV diagnostic only if independently justified, and drop both the packaging hunk already supplied by #74362 and the SessionDB work already supplied by 8da8a78. The automated keep-open review supports this extraction rather than closing the entire PR.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I74479(["issue #74479 (closed)"])
    P74506["PR #74506 (open)"]
    P74506 -->|best fix| I74479
    class I74479 closed
    class P74506 open
    class P74506 best
    class P74506 target
    click I74479 "https://github.com/NousResearch/hermes-agent/issues/74479"
    click P74506 "https://github.com/NousResearch/hermes-agent/pull/74506"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 1 pull request and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 21 kB of PR diffs, 7 kB of issue/PR text, 1 kB of discussion (1 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install-update Installer, updater, packaging, wheels, doctor comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists python:uv Pull requests that update python:uv code sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Replacement environment did not pass dependency and import smoke tests

4 participants