Skip to content

Add opt-in Headroom Phase 1 tool-output compression plugin - #40322

Closed
channkim wants to merge 1 commit into
NousResearch:mainfrom
channkim:feat/headroom-phase1
Closed

Add opt-in Headroom Phase 1 tool-output compression plugin#40322
channkim wants to merge 1 commit into
NousResearch:mainfrom
channkim:feat/headroom-phase1

Conversation

@channkim

@channkim channkim commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Promote the Headroom structured tool-output compression experiment to Phase 1 as disabled-by-default code + tests only.

  • Add bundled opt-in headroom plugin using the existing transform_tool_result hook.
  • Add default-disabled headroom config block.
  • Hard-limit Phase 1 to search_files and browser_snapshot; config can narrow but not widen the allowlist.
  • Keep explicit exclusions for terminal, read_file, delegate_task, patch, write_file, memory, send_message, clarify, and cronjob.
  • Add kill switches via config/env.
  • Do not introduce raw-result storage or retrieval handles in Phase 1; compressed payloads mark retrieval unavailable.
  • Redact secret-like strings and dict keys before constructing compressed payloads.
  • Preserve existing untrusted wrapper prefix/suffix when compressing wrapped results.
  • Handle real search_files JSON plus pagination hint suffix.

Non-goals / invariants

  • No default live behavior change: plugin loading alone remains identity because headroom.enabled defaults to false.
  • No default-profile canary/live rollout in this PR.
  • No raw output persistence in this PR.
  • No expansion beyond the Phase 1 allowlist.
  • Mandatory excluded tools cannot be re-enabled by config.

Validation

Ran locally:

scripts/run_tests.sh tests/plugins/test_headroom_plugin.py
scripts/run_tests.sh tests/plugins/test_headroom_plugin.py tests/test_transform_tool_result_hook.py tests/hermes_cli/test_plugin_scanner_recursion.py tests/hermes_cli/test_plugins.py
python -m py_compile plugins/headroom/__init__.py tests/plugins/test_headroom_plugin.py
git diff --check

Results:

  • tests/plugins/test_headroom_plugin.py: 19 passed
  • combined focused suite: 116 passed
  • py_compile: passed
  • git diff --check: passed

Review

Codex adversarial review initially found two blockers:

  1. headroom.excluded_tools was exposed but not read.
  2. real truncated search_files output appends a plaintext hint after JSON, causing parsing to skip compression.

Both were fixed and re-reviewed. Final Codex review verdict: PASS.

Handoff

  • Branch: feat/headroom-phase1
  • Commit: 8e5acc7b5
  • Implementation files:
    • plugins/headroom/__init__.py
    • plugins/headroom/plugin.yaml
    • hermes_cli/config.py
    • tests/plugins/test_headroom_plugin.py

Follow-ups before Phase 2

  • Storage/retrieval handle design review if raw output persistence is introduced.
  • Verify /compress, resume, missing handle, kill switch, scope isolation, and untrusted wrapper tests before any live canary.
  • Phase 2 must be in a separate test profile only, not default profile.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 6, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for keeping the experiment opt-in and using the existing transform_tool_result seam.

Problems

  • Current main changed the search_files wire shape in merged #47866: tools/file_tools.py:2004 requests densify=True, and tools/file_operations.py:281-297 emits matches_text for five or more matches. This PR's _compress_search_files() only recognizes matches, files, and counts, so it returns no transformation for the current densified result. The added tests exercise only the older matches array.
  • The PR adds non-secret HERMES_HEADROOM_* enablement, kill-switch, and allowlist settings. website/docs/user-guide/configuration.md:53-60 requires behavioral settings to live in config.yaml.

Suggested changes

  • Re-scope search_files around the native lossless representation from #47866, and add real-path coverage for matches_text plus the below-threshold array form.
  • Keep activation and limits in config.yaml; remove the new behavioral environment overrides.

Automated hermes-sweeper review.

def _clip_text(value: Any, max_chars: int) -> str:
text = str(value)
if len(text) <= max_chars:
return text

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current main's search_files output uses matches_text rather than matches when it has at least five matches (tools/file_tools.py:2004, tools/file_operations.py:281-297). This branch will therefore skip the common current result shape; add coverage using the real densified payload or re-scope this transformer around the native lossless representation.

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

Labels

area/compression Context compression and continuation sessions comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users 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/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants