Skip to content

feat(plugins): opt-in-by-default + bundled disk-cleanup plugin (salvage #12212)#12944

Merged
teknium1 merged 6 commits into
mainfrom
hermes/hermes-790604aa
Apr 20, 2026
Merged

feat(plugins): opt-in-by-default + bundled disk-cleanup plugin (salvage #12212)#12944
teknium1 merged 6 commits into
mainfrom
hermes/hermes-790604aa

Conversation

@teknium1

@teknium1 teknium1 commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes all plugins — user-installed, bundled, and pip — opt-in by default. Ships disk-cleanup as the first bundled plugin (salvaged from @LVT382009's #12212). Closes #12212.

What changes for users

Before: any plugin present on disk loaded automatically. Installing a plugin or adding a bundled one silently wired hooks, tools, and slash commands into every session.

After: plugins load only when explicitly listed under plugins.enabled in ~/.hermes/config.yaml. The install command prompts Enable 'name' now? [y/N] (defaults to no). Three explicit states: enabled, disabled, not enabled.

Existing user plugins are grandfathered via config migration so upgrades don't silently break anyone's setup. Bundled plugins are never auto-enabled — every user opts in explicitly.

Changes

  • plugins/disk-cleanup/ — new bundled plugin (salvage of @LVT382009's disk-guardian skill as a plugin with post_tool_call + on_session_end hooks, /disk-cleanup slash command, safe deterministic cleanup rules, atomic state writes, path-safety guards)
  • hermes_cli/plugins.py — bundled-plugin discovery (<repo>/plugins/<name>/) excluding memory/ and context_engine/; opt-in allow-list gate in discover_and_load; explicit disable always wins
  • hermes_cli/plugins_cmd.py — new _get_enabled_set / _save_enabled_set; cmd_enable / cmd_disable update both lists; cmd_install prompts for enable and accepts --enable / --no-enable; cmd_list shows bundled + user with three-state status; interactive UI tags bundled entries [bundled] and writes both enabled and disabled lists
  • hermes_cli/main.py--enable / --no-enable flags on hermes plugins install
  • hermes_cli/config.py — schema v20 → v21 migration: populate plugins.enabled from currently-installed user plugins (minus anything in plugins.disabled); bundled plugins explicitly excluded from grandfathering
  • website/docs/user-guide/features/plugins.md — new "Plugins are opt-in" section, three-state table, migration note, updated management commands
  • website/docs/user-guide/features/built-in-plugins.md — new "Bundled plugins are opt-in" section, removed now-defunct HERMES_DISABLE_BUNDLED_PLUGINS references
  • tests/plugins/test_disk_cleanup_plugin.py — 38 tests covering path safety, category inference, track/quick/status, hook behaviour, slash command, bundled discovery, enabled/disabled semantics
  • tests/hermes_cli/test_plugins.py — updated _make_plugin_dir helper auto-enables test plugins so existing test semantics are preserved
  • tests/conftest.py — removed HERMES_DISABLE_BUNDLED_PLUGINS env var (no longer exists)

Attribution

Contributor commits from #12212 are cherry-picked onto this branch so @LVT382009 / @nox keep authorship per-commit. My commits include Co-authored-by: where relevant. Needs --rebase merge.

Validation

Result
tests/plugins/test_disk_cleanup_plugin.py 38/38
tests/hermes_cli/test_plugins.py 48/48
tests/hermes_cli/test_plugins_cmd.py pass
tests/hermes_cli/test_plugin_cli_registration.py pass
tests/hermes_cli/test_config.py (migration) 49/49
tests/agent/test_memory_provider.py 287/287
Combined plugin+config suite 442/442
tests/hermes_cli/ full 2347/2348 (1 pre-existing unrelated gemini-catalog failure)
ascii-guard lint on new/updated docs clean

Live E2E (isolated HERMES_HOME, real imports):

  • Fresh install → disk-cleanup discovered as bundled, enabled=False, error "not enabled..."
  • plugins.enabled: [disk-cleanup] → loads on next discovery, hooks registered
  • Hook fires on write_file(path=test_foo.py) → file tracked as category test
  • plugins.disabled: [disk-cleanup] → explicit disable wins, error "disabled via config"
  • v20 → v21 migration with pre-installed user plugin my-fav-pluginplugins.enabled: [my-fav-plugin], bundled disk-cleanup NOT grandfathered

LVT382009 and others added 5 commits April 20, 2026 01:27
Rewires @LVT382009's disk-guardian (PR #12212) from a skill-plus-script
into a plugin that runs entirely via hooks — no agent compliance needed.

- post_tool_call hook auto-tracks files created by write_file / terminal
  / patch when they match test_/tmp_/*.test.* patterns under HERMES_HOME
- on_session_end hook runs cmd_quick cleanup when test files were
  auto-tracked during the turn; stays quiet otherwise
- /disk-guardian slash command keeps status / dry-run / quick / deep /
  track / forget for manual use
- Deterministic cleanup rules, path safety, atomic writes, and audit
  logging preserved from the original contribution
- Protect well-known top-level state dirs (logs/, memories/, sessions/,
  cron/, cache/, etc.) from empty-dir removal so fresh installs don't
  get gutted on first session end

The plugin system gains a bundled-plugin discovery path (<repo>/plugins/
<name>/) alongside user/project/entry-point sources. Memory and
context_engine subdirs are skipped — they keep their own discovery
paths. HERMES_DISABLE_BUNDLED_PLUGINS=1 suppresses the scan; the test
conftest sets it by default so existing plugin tests stay clean.

Co-authored-by: LVT382009 <levantam.98.2324@gmail.com>
… docs

The original name was cute but non-obvious; disk-cleanup says what it
does. Plugin directory, script, state path, log lines, slash command,
and test module all renamed. No user-visible state exists yet, so no
migration path is needed.

New website page "Built-in Plugins" documents the <repo>/plugins/<name>/
source, how discovery interacts with user/project plugins, the
HERMES_DISABLE_BUNDLED_PLUGINS escape hatch, disk-cleanup's hook
behaviour and deletion rules, and guidance on when a plugin belongs
bundled vs. user-installable. Added to the Features → Core sidebar next
to the main Plugins page, with a cross-reference from plugins.md.
@teknium1 teknium1 changed the title feat(plugins): convert disk-guardian into a bundled plugin (salvage #12212) feat(plugins): add disk-cleanup as a bundled plugin (salvage #12212) Apr 20, 2026
Plugins now require explicit consent to load. Discovery still finds every
plugin — user-installed, bundled, and pip — so they all show up in
`hermes plugins` and `/plugins`, but the loader only instantiates
plugins whose name appears in `plugins.enabled` in config.yaml. This
removes the previous ambient-execution risk where a newly-installed or
bundled plugin could register hooks, tools, and commands on first run
without the user opting in.

The three-state model is now explicit:
  enabled     — in plugins.enabled, loads on next session
  disabled    — in plugins.disabled, never loads (wins over enabled)
  not enabled — discovered but never opted in (default for new installs)

`hermes plugins install <repo>` prompts "Enable 'name' now? [y/N]"
(defaults to no). New `--enable` / `--no-enable` flags skip the prompt
for scripted installs. `hermes plugins enable/disable` manage both lists
so a disabled plugin stays explicitly off even if something later adds
it to enabled.

Config migration (schema v20 → v21): existing user plugins already
installed under ~/.hermes/plugins/ (minus anything in plugins.disabled)
are auto-grandfathered into plugins.enabled so upgrades don't silently
break working setups. Bundled plugins are NOT grandfathered — even
existing users have to opt in explicitly.

Also: HERMES_DISABLE_BUNDLED_PLUGINS env var removed (redundant with
opt-in default), cmd_list now shows bundled + user plugins together with
their three-state status, interactive UI tags bundled entries
[bundled], docs updated across plugins.md and built-in-plugins.md.

Validation: 442 plugin/config tests pass. E2E: fresh install discovers
disk-cleanup but does not load it; `hermes plugins enable disk-cleanup`
activates hooks; migration grandfathers existing user plugins correctly
while leaving bundled plugins off.
@teknium1 teknium1 changed the title feat(plugins): add disk-cleanup as a bundled plugin (salvage #12212) feat(plugins): opt-in-by-default + bundled disk-cleanup plugin (salvage #12212) Apr 20, 2026
@teknium1 teknium1 merged commit 70111ee into main Apr 20, 2026
5 of 7 checks passed
@teknium1 teknium1 deleted the hermes/hermes-790604aa branch April 20, 2026 11:46
LVT382009 added a commit to LVT382009/hermes-agent that referenced this pull request Apr 20, 2026
This commit converts NOX from a skill to a bundled plugin architecture,
following the pattern established in PR NousResearch#12944 (disk-guardian conversion).

Major Changes:
- Convert skills/nox/ → plugins/nox/ with full plugin structure
- Add plugin.yaml with metadata and configuration
- Add __init__.py with NOXPlugin class and hook registration
- Update hermes_cli/plugins.py to discover bundled plugins
- Add comprehensive tests in tests/plugins/test_nox_plugin.py

Critical Bug Fixes:
- Fix Literal type annotations for Python 3.12 compatibility
- Fix abort controller logic (proof cost > 2x expected gain, not > 0)
- Fix compression gain check (allow <50 token responses without compression)
- Fix _check_no_broken_symbols (allow identifiers with spaces)
- Fix missing Identifier import in verifier
- Fix IR cost calculation (handle missing attributes safely)

Performance Improvements:
- Fast path optimization: 0.31-0.61ms average (target: <75ms)
- Deep path optimization: <100ms hard ceiling
- 100% NOX application rate with 0% fallbacks
- 79.5% average compression (target: 30-50%)
- 803 total token savings across 25 test responses

Architecture:
- Approach A′.2: Latency-Constrained Proof-Carrying E-Graph Compiler
- Stratified rewrite tiers (0-3) with cost metadata
- Multi-layer verification (structural + semantic + compression)
- Automatic fallback with specific triggers
- Deterministic operations with reversibility guarantees

Files Added:
- plugins/nox/__init__.py (Plugin registration)
- plugins/nox/plugin.yaml (Plugin metadata)
- plugins/nox/nox.py (Main plugin logic)
- plugins/nox/types.py (Type system)
- plugins/nox/ast.py (AST definitions)
- plugins/nox/ir.py (E-graph IR)
- plugins/nox/parser.py (Natural language parser)
- plugins/nox/rewrite_rules.py (Stratified rewrite rules)
- plugins/nox/optimizer.py (Fast/deep path optimizers)
- plugins/nox/verifier.py (Multi-layer verification)
- plugins/nox/decoder.py (IR to natural language decoder)
- tests/plugins/test_nox_plugin.py (Comprehensive tests)

Files Modified:
- hermes_cli/plugins.py (Add bundled plugin discovery)

Documentation:
- plugins/nox/README.md (Complete documentation)
- plugins/nox/IMPLEMENTATION.md (Architecture details)
- plugins/nox/V1_SUMMARY.md (Implementation summary)

Benchmark Results:
- Average Time: 0.28ms (target: <75ms) ✅
- Max Time: 1.54ms (hard ceiling: <100ms) ✅
- NOX Applied Rate: 100% ✅
- Fallback Rate: 0% ✅
- Average Compression: 79.5% (target: 30-50%) ✅
- Total Token Savings: 803 tokens

This conversion aligns NOX with Hermes Agent's plugin architecture,
providing automatic application without agent compliance requirements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants