#874·ponytail

Hermes plugin's mode filter silently drops rule bullets that start with a mode word (pre-#571 regex)

Author: cr-sbarboucheCreated Sep 14, 2026Updated Sep 14, 2026

_filter_skill_body_for_mode in the Hermes plugin (__init__.py) is a Python port of filterSkillBodyForMode in hooks/ponytail-instructions.js. Both trim the shared skills/ponytail/SKILL.md body down to the active intensity, and every host adapter is supposed to see the same filtered text for a given mode (see docs/agent-portability.md).

#571 fixed a landmine in the JS filter: its worked-example detector matched any bullet shaped - label: text and treated it as a mode-specific example whenever the label happened to normalize to a mode name, silently dropping it in every other mode. The fix required the worked-example bullet to be quoted (- lite: "..."), since that's the only shape real examples take; an ordinary rule bullet that happens to start with, say, "Full:" is prose and must survive verbatim.

The Hermes/Python filter still has the pre-#571 regex and reproduces the exact bug:

import importlib.util
spec = importlib.util.spec_from_file_location('m', '__init__.py')
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
body = '## Rules\n- Full: real rule text about something unrelated to intensity.\n- Deletion over addition.'
print(m._filter_skill_body_for_mode(body, 'ultra'))
## Rules
- Deletion over addition.

The "Full:" rule silently disappears in ultra mode, with no error. Same input through the JS filter keeps it. Any Hermes Agent user is exposed to this the moment a rule bullet in SKILL.md happens to start with a mode word — which is exactly the scenario #571 called out as a landmine for a future edit, just on the adapter that didn't get the fix.

There's also a second, smaller divergence in the same function: Python's str.splitlines() drops the body's trailing newline on rejoin, while the JS filter's split(/\r?\n/) preserves it, so the two adapters don't even agree on whitespace at the end of the injected context.

Both bugs live in the one function every Hermes-integrated agent calls before every LLM turn (pre_llm_call -> build_injected_context -> _filter_skill_body_for_mode), so they affect the actual instructions an agent sees, not just test fixtures.