Skip to content

Plugin dependencies follow the plugin's own security policy; Hermes's 14-day quarantine applies to Hermes deps only (reverses #118841 item 3, unblocks #120076 #114530) - #120231

Merged
teknium1 merged 2 commits into
mainfrom
plugin-dep-policy
Sep 23, 2026
Merged

teknium1 merged 2 commits into
mainfrom
plugin-dep-policy

Conversation

@teknium1

Copy link
Copy Markdown
Collaborator

Plugin python_dependencies now install under the plugin's own dependency-security policy; Hermes's 14-day exclude-newer quarantine applies to Hermes's own dependencies only — so catalog re-pins floored on a fresh release (#120076 hindsight 1.0.1 → hindsight-client>=0.10.1) install again, while hermes update / lazy extras stay quarantined.

Reverses item 3 of #118841 (merged 74f726c), which pinned the uv tier's cwd to the checkout for every install so the quarantine reached plugin deps from any cwd. Maintainer ruling:

plugins dont have to abide by our 14 day rule btw. They can have their own security policy on that. Only hermes' dependencies themselves have to. We should recommend that they do this for their plugins and we should give guidance to plugin devs that they should though.
— @teknium1

Changes

  • tools/lazy_deps.py — the line is drawn in code, not by cwd tricks: INSTALL_POLICIES = ("core", "plugin"). _uv_policy_args(policy) replaces _uv_policy_cwd(): core runs uv from the checkout root (quarantine + exclude-newer-package exceptions apply from $HOME, a service, the Desktop backend); plugin passes --no-config (no project file discovered from any cwd; env knobs UV_INDEX_URL / UV_EXCLUDE_NEWER still apply, so an operator can quarantine plugin deps themselves). _venv_pip_install(policy=) defaults to core (ensure() / LAZY_DEPS extras); install_specs(policy=) defaults to plugin — every caller of install_specs installs plugin/provider-manifest deps (plugin_python_deps.resolve → CLI install/enable/update, catalog installs, dashboard memory-provider setup, hermes memory setup, post-update reapply_all, memory-provider migration, mem0/honcho SDK self-installs). The core constraints file still bounds plugin resolution.
  • hermes_cli/plugin_python_deps.py — resolve() passes policy="plugin" explicitly.
  • Hermes's own pinning untouched — pyproject.toml [tool.uv], uv lock/sync in managed_uv, the exact-pin/upper-bound lint in tests/test_packaging_metadata.py.
  • Docs / guidance (half the ask)
    • website/docs/developer-guide/plugins/index.md — new Dependency security policy section: Hermes does not quarantine plugin deps; plugin authors are responsible for their own deps and strongly recommended to pin upper bounds, floor on the oldest API-compatible version, adopt their own new-release quarantine (uv --exclude-newer "14 days" / UV_EXCLUDE_NEWER in their CI), review bumps; the catalog review reads the dependency list at the pin.
    • plugin-catalog/README.md — admission rule 9: dependency policy is the plugin's; reviewers recommend (not require) bounds + oldest floor + own quarantine; a recent floor alone is not grounds to hold an entry.
    • AGENTS.md § Dependency Pinning Policy — scope of the quarantine and the ruling, with the code seam named.
    • Catalog intake skill (local, hermes-plugin-catalog-intake) — the stale "quarantine applies to plugin installs from any cwd, hold until it ages" rule replaced by the ruling + recommend-not-require guidance.
  • Tests — the Plugin loader: version gate reads running code, SystemExit isolated, uv quarantine from any cwd, impostor dirs refused, range pins (#72052 #104404 #101962 #112096 #108371 #71650 #86992 #98407) #118841 test (uv tier runs from the checkout) is replaced by two invariants in tests/tools/test_lazy_deps.py: a plugin install_specs call carries --no-config and no checkout cwd (red on base, green fixed); a core ensure() install keeps the checkout cwd and no --no-config (control, green both sides).

Validation

Check Before (origin/main eb8960f) After
hermes plugins install vectorize-io/hindsight#hindsight-integrations/hermes --ref f7a153dd… (fresh scratch venv, fake HOME/HERMES_HOME, cwd=$HOME) refused: Because only hindsight-client<=0.9.2 is available and you require hindsight-client>=0.10.1,<1 … filtered by exclude-newer (the #120076 symptom) ✓ Plugin installed, hindsight-client==0.10.1 in the venv
_venv_pip_install(("hindsight-client>=0.10.1,<1",), dry_run=True, policy="core") from $HOME — still refused: filtered by exclude-newer to only include packages uploaded before 2026-09-09 — Hermes's quarantine holds from any cwd
… policy="plugin" — resolves + hindsight-client==0.10.1
uv pip install --dry-run --show-settings from checkout / checkout --no-config / $HOME 14d / — / None 14d / None / None (--no-config deterministic from any cwd; UV_EXCLUDE_NEWER="7 days" under --no-config → 7d)
tests/tools/test_lazy_deps.py new plugin invariant 1 red on base green
scripts/run_tests.sh tests/tools/ tests/hermes_cli/test_plugin*.py … — see thread if anything is red

Live repro: before — HOME=<scratch>/fakehome HERMES_HOME=… python -m hermes_cli.main plugins install vectorize-io/hindsight#hindsight-integrations/hermes --ref f7a153dd9050e800cb295fd278f0a3ed0af29f32 exits 1 with the exclude-newer refusal; after — same command exits 0 and installs hindsight-client 0.10.1; core dry-run under policy="core" from the same cwd still refuses.

Root cause in one sentence: #118841 applied a project-scoped uv policy to installs that are not the project's, by making cwd carry the policy for every install.

Trade-off noted: --no-config also skips a user-level ~/.config/uv/uv.toml for plugin installs (env vars such as UV_INDEX_URL still apply; pip.conf/PIP_INDEX_URL are bridged already). A --project <dir> alternative preserved user config but walks up the directory tree and is not deterministic.

Unblocks #120076 and #114530 (the re-pins land once this merges). Follow-up to #118841.

Infographic

plugin-dependency-policy

@teknium1 teknium1 added the ci-reviewed applied to manually approve dangerous changes label Sep 23, 2026
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins labels Sep 23, 2026
…licy

Hermes's 14-day `[tool.uv] exclude-newer` quarantine applies to Hermes's own
dependencies only (uv lock/sync, `hermes update`, LAZY_DEPS extras via
`ensure()`). A plugin's declared `python_dependencies` install under the
PLUGIN's policy: `install_specs(policy="plugin")` runs uv with `--no-config`
from any cwd, still inside the core constraints file.

Reverses item 3 of #118841, which ran the uv tier with cwd=<checkout> for
every install so the quarantine reached plugin deps from any cwd. That made
catalog re-pins floored on a <14-day release uninstallable (#120076:
"only hindsight-client<=0.9.2 is available"; #114530 held on the same gate).

Maintainer ruling (Teknium): "plugins dont have to abide by our 14 day rule
btw. They can have their own security policy on that. Only hermes'
dependencies themselves have to. We should recommend that they do this for
their plugins and we should give guidance to plugin devs that they should
though."

- tools/lazy_deps.py: INSTALL_POLICIES ("core" | "plugin"); `_uv_policy_args`
  replaces `_uv_policy_cwd`; `_venv_pip_install(policy=)` defaults to core
  (ensure/LAZY_DEPS), `install_specs(policy=)` defaults to plugin.
- hermes_cli/plugin_python_deps.py: `resolve()` passes policy="plugin".
- Docs: developer guide "Dependency security policy" section, catalog README
  admission rule 9, AGENTS.md pinning policy — plugin authors are responsible
  for their deps and strongly recommended to pin upper bounds, floor on the
  oldest API-compatible version and run their own release quarantine
  (`uv --exclude-newer` in their CI); operators can set UV_EXCLUDE_NEWER.
- Tests: the #118841 cwd test is replaced by two invariants — a plugin install
  carries `--no-config` and no checkout cwd (red on base), a core lazy install
  keeps the checkout cwd and no `--no-config`.
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

૮ >ﻌ< ა ci review

ran on cf931e5 — chore: retrigger CI (zero-job dispatch failure, auto-heal)

⚠️ Warnings

CI timings · View report · View job

Wall time 6m8s vs 1m17s (+377.9%). 1 faster, 1 unchanged.

  • Detect affected areas: -59.0s

@teknium1
teknium1 merged commit 358d50c into main Sep 23, 2026
36 checks passed
@teknium1
teknium1 deleted the plugin-dep-policy branch September 23, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-reviewed applied to manually approve dangerous changes comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants