Commit Graph

11 Commits

Author SHA1 Message Date
teknium1
7fbe16aed5 test: exempt evals/ from the managed-runtime which() guard; make the OS-marker lister tolerate vanishing dirs
Two CI reds from the previous commits.

benchmark_browser_eval.py moved from scripts/ (exempt) to evals/ and its
bare shutil.which("npx") tripped test_no_unreviewed_bare_managed_runtime_
lookups. evals/ are standalone user-invoked benchmark programs, the same
class as scripts/ and skills/, and three other eval files already call
which() the same way; the guard just never saw them because the harness
that carried them lived under scripts/. Exempt the directory.

list_os_marked_tests.py used Path.rglob, which raises FileNotFoundError
when a __pycache__ directory disappears mid-scan (a sibling job in the
same workspace). The managed-runtime guard already switched to os.walk
for the identical TOCTOU; do the same here. Same output, sorted.
2026-09-13 06:06:46 -07:00
Teknium
caa29fb43a Merge branch 'simp/r2-tools-a' into simp/integration2
# Conflicts:
#	tests/test_managed_runtime_resolution.py
2026-09-02 17:07:24 -07:00
Teknium
5e7ff3d8fc Merge branch 'simp/r2-update-cmd-sub' into simp/integration2 2026-09-02 17:05:23 -07:00
Teknium
bd30c9b6ac refactor(browser): move cloud-provider/backend selection to tools/browser_tool_cloud.py and agent-browser/Chromium discovery+install to tools/browser_tool_install.py 2026-09-02 16:18:57 -07:00
Teknium
a59680217f refactor(update): hand-compact comments/docstrings in split modules (AST-identical); re-export get_hermes_home/shutil; repoint source-inspection tests 2026-09-02 16:11:02 -07:00
Teknium
07cd3ba7c9 refactor(hermes_cli/main): extract install/update recovery cluster to main_install_repair.py 2026-09-02 16:08:08 -07:00
Teknium
b131e0d87f refactor(hermes_cli/main): extract TUI launcher cluster to main_tui_launch.py 2026-09-02 15:30:43 -07:00
Teknium
75bf672a78 test: managed-runtime source scan survives a vanishing sdist dir (TOCTOU)
Path.rglob raises FileNotFoundError when a directory disappears between
listing and scandir — a sibling CI job creating/removing its sdist
extraction (hermes_agent-<ver>/) killed test_allowlist_has_no_stale_entries
on run 33531869442. Switch to os.walk (tolerates vanishing dirs) with
top-level pruning of exempt and packaging dirs; file set is byte-identical
(886 files verified old==new) and a 30-scan churn harness that reliably
exercised the window shows zero errors.
2026-09-01 10:52:42 -07:00
Teknium
3f5d37568e fix: managed-runtime guard no longer trips on sdist/build copies in the workspace
The bare-which() scanner rglobs the repo root; a CI job that builds the
wheel leaves an sdist extraction (hermes_agent-<version>/) in the
workspace, and the scanner re-found every already-exempted call site
under that versioned prefix — which can never match an _ALLOWED key —
failing the guard on untouched code (flaked PR #93420's Python-tests
job). _source_files now skips build/, dist/, *.egg-info, and any
top-level dir carrying PKG-INFO.

A/B: planted a fake hermes_agent-9.9.9/ sdist with a which('node')
site — old scanner 1 failed, fixed scanner 7 passed, clean tree
unchanged.
2026-08-23 19:15:28 -07:00
Teknium
10e9da6f2d fix: ASCII-only install.ps1 comment; allow-list install_cli's uv PATH fallback
- install.ps1 must stay pure ASCII (PowerShell 5.1 ANSI code-page
  decoding, #66994/#67000): em-dash -> '--'
- tests/test_managed_runtime_resolution.py: install_cli()'s
  shutil.which('uv') is a reviewed fallback AFTER ensure_uv() misses
2026-08-11 17:06:15 -05:00
ethernet
25d0bcd424 fix(runtime): resolve Hermes-managed Node and uv before bare PATH
Hermes installs runtimes for itself — `uv` at `$HERMES_HOME/bin/uv`, Node
at `$HERMES_HOME/node` — and neither directory is on an arbitrary
process's PATH. Every `shutil.which("node"/"npm"/"npx"/"uv")` in Hermes's
own code therefore has two failure modes: the managed runtime is invisible,
so the caller reports "not installed" or degrades to a slower tier on a
machine that has exactly what it needed; and when a system copy also
exists, the one Hermes does not own wins.

Routed the Hermes-owned call sites through managed-aware resolvers:

- `agent/lsp/install.py`, `hermes_cli/dep_ensure.py`, `hermes_cli/main.py`
  (`_make_tui_argv`), `hermes_cli/tools_config.py` (`_run_post_setup`) now
  use `find_node_executable()`.
- `hermes_cli/tools_config.py::_pip_install` and `hermes_cli/setup.py`'s
  vercel install use `ensure_uv()` (installing uv is in scope during setup,
  and the Windows installer's `uv venv` does not seed pip, so the fallback
  tier is "No module named pip"). `tools/lazy_deps.py` uses `resolve_uv()`
  — a lookup, not a bootstrap, because it runs mid-turn for an optional
  dependency and downloading a runtime as a side effect exceeds what the
  caller asked for.
- `hermes_cli/gateway.py`: extracted `_append_node_dir_for_service()`,
  shared by the systemd unit and launchd plist generators, which appends
  the managed dirs before the PATH-resolved one. A service definition is
  written once and survives reboots, so resolving a system Node that
  happens to lead the installing shell's PATH bakes the wrong interpreter
  in permanently. Managed dirs are profile-scoped, so each profile's unit
  still names its own Node; the existing symlink-parent rule (don't
  `.resolve()`) is preserved verbatim.
- `tools/environments/local.py`: the terminal tool's subshell PATH gains
  the managed dirs, appended alongside the sane entries rather than
  prepended — a tool the user deliberately put on their own PATH still
  wins, and the managed one only fills a gap. This is also what makes the
  bare `which("uv")` in `tools/env_probe.py` correct: that probe reports
  the environment the *model* sees, and the model can only run what is on
  that subshell's PATH.

`scripts/install.ps1`: the persisted User PATH update becomes
`Set-ManagedNodeFirstOnUserPath`, a move-to-front rather than an
add-if-missing. Installs made by an older install.ps1 already have the
managed dir in User PATH — at the tail, behind a system Node — and an
add-if-missing check sees it present and leaves that ordering in place
forever, so the users the bug hurt would never be repaired. Unrelated
entries keep their relative order (empty segments included; a trailing
`;` is legal and the installer's other PATH code preserves them),
duplicates collapse, and it writes only when the string actually changes.

Tests:

- `tests/test_managed_runtime_resolution.py` — AST guard that fails any
  new bare `which()` for a managed runtime, with a short justified
  allow-list and a companion test that fails when an allow-list entry goes
  stale. Reading source is banned by AGENTS.md and this is the documented
  exception: the property is "no call site anywhere spells it this way",
  which no runtime seam can observe.
- `scripts/ci/test_install_ps1_path_migration.ps1` — behavioral, not a
  source regex: it lifts the real `Set-ManagedNodeFirstOnUserPath` out of
  install.ps1's AST and rewrites only the two registry calls into an
  in-memory store, so the shipped split/dedupe/prepend/change-detection
  logic executes for real. Not in the default lane (Linux runners have no
  PowerShell host); runs under `pwsh`. 13/13 assertions pass.
2026-08-01 21:17:51 -04:00