feat(hermes): Add Hermes Agent harness — on_session_start bootstrap injection#1922
feat(hermes): Add Hermes Agent harness — on_session_start bootstrap injection#1922kumarabd wants to merge 18 commits into
Conversation
…s object
Codex auto-discovers a plugin's hooks/hooks.json whenever the Codex
manifest has no `hooks` field: load_plugin_hooks falls back to a
hardcoded DEFAULT_HOOKS_CONFIG_FILE = "hooks/hooks.json" and registers
it. hooks/hooks.json is the Claude Code SessionStart hook, it is tracked
in this repo, and the Codex marketplace installs the whole repo root
(source url "./"), so the fallback re-registered the SessionStart hook
and its install-time trust prompt on Codex.
Removing the Codex hook file and the manifest `hooks` pointer (commit
"Remove Codex hooks") did not disable the hook on Codex — it removed the
explicit declaration that was overriding the fallback, so the fallback
took over and found the Claude hooks/hooks.json.
Declare an empty inline hooks object ({}) in .codex-plugin/plugin.json.
It parses as an empty inline hook set and stops Codex reaching the
auto-discovery fallback. An absent field, an empty array ([]), and an
empty inline list all collapse back to the fallback, so the value must
be exactly {}.
Update the test to assert the manifest declares hooks: {} (and that
hooks/hooks.json exists, which is what makes the declaration necessary),
replacing the prior assertion that the field was absent — which passed
while the hook was still being auto-discovered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… docs hooks/session-start-codex has had no caller since "Remove Codex hooks" (obra#1845) deleted hooks-codex.json and its manifest registration; the Codex manifest now declares an empty hooks object so Codex registers no session-start hook at all. The script is Codex-specific dead code — nothing executes it on Codex or any other harness. - Delete hooks/session-start-codex. - tests/hooks/test-session-start.sh: drop the two Codex cases that are redundant with the generic session-start tests (nested-format and the legacy-warning omission are already covered by the Claude Code cases). Re-point the "wrapper dispatches" case to the live `session-start` script so run-hook.cmd dispatch coverage — used by Claude Code and Cursor in production — is preserved rather than lost. - docs/porting-to-a-new-harness.md: Codex is no longer a Shape A (shell-hook) harness, so re-anchor that worked example to Cursor (a live shell-hook harness that demonstrates the same per-harness field, schema, and matcher variance) and mark Codex as native skill discovery with no session-start hook. Clears the references to the deleted hooks-codex.json. - docs/windows/polyglot-hooks.md: the "check hooks-codex.json" pointer referenced a file deleted in obra#1845; re-point to hooks-cursor.json. RELEASE-NOTES.md keeps its historical mention of hooks-codex.json (it accurately records what that release did). The tests/codex-plugin-sync fixtures build their own synthetic session-start-codex and test the sync mechanism generically, so they are intentionally left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…x portal packaging
Scaffold for Hermes Agent harness (Shape B in-process plugin): - .hermes-plugin/plugin.yaml: manifest with on_session_start hook - .hermes-plugin/__init__.py: stub with _bootstrap_cache, _SKILLS_DIR, _last_session_id - tests/hermes/: conftest (simplified, session_id-based dedup), test_plugin.py (10 failing tests) All tests fail cleanly at stub level (AssertionError/KeyError, no ImportError). Dedup tests use session_id per Task 1 API discovery (no messages kwarg). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevent __pycache__, *.pyc, and .pytest_cache from being tracked. Untrack previously committed .pyc files from tests/hermes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ELY_IMPORTANT wrapper Implements _strip_frontmatter, _get_bootstrap, _hermes_tool_mapping, and resolves _SKILLS_DIR in .hermes-plugin/__init__.py. Adds test_bootstrap.py with 10 passing tests (RED→GREEN). register() remains a stub for Task 4. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements register(ctx) in .hermes-plugin/__init__.py: - Registers on_session_start hook via ctx.register_hook - Guards against repeated injection within the same session via _last_session_id - Injects assembled bootstrap as user-role message on new sessions - Skips silently when SKILL.md is missing (bootstrap is None/False) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, add skill_view fallback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s skills skill_view() looks in Hermes' own skill registry and returns 'not found' for the superpowers bundled skills. Include the resolved _SKILLS_DIR path in the bootstrap so the model has an explicit read_file fallback path for skills like brainstorming. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@obra does it look like something that can be merged in? |
|
Thanks @kumarabd — of the three open Hermes PRs this is the strongest: it keeps the stock
The two competing Hermes PRs (#1892, #1861) are being closed in favor of this one. When the four items above are addressed, this goes to maintainer review. — Claude Fable 5 (AI assistant), Claude Code 2.1.218, doing PR triage for this repo. Direction from @obra. |
|
@kumarabd To make item 3 easy: I've pushed a clean rebase of your Hermes work onto current dev as To adopt it on this PR: git fetch https://github.com/obra/superpowers.git hermes-harness-rebase
git reset --hard FETCH_HEAD
git push --force-with-lease origin <your-branch>That leaves items 1, 2, and 4 from the review above (pre_llm_call injection or proof of inject_message, ctx.register_skill over the stock skills, fresh passing transcript) — all inside — Claude Fable 5 (AI assistant), Claude Code 2.1.218, doing PR triage for this repo. |
|
Update: the review items above have been resolved empirically, and the
For this PR that means: reset your branch to — Claude Fable 5 (AI assistant), Claude Code 2.1.218, doing PR triage for this repo. |
Who is submitting this PR? (required)
What problem are you trying to solve?
Hermes Agent (by Nous Research) has no Superpowers plugin harness — issue #1859. Without a harness, the
using-superpowersbootstrap never reaches the model at session start, so no skill auto-triggers. This PR adds one using Hermes' native in-process plugin API.What does this PR change?
Adds
.hermes-plugin/plugin.yaml+.hermes-plugin/__init__.py: an in-process Python plugin that fireson_session_start, readsskills/using-superpowers/SKILL.md, and injects it as a user-role message wrapped in<EXTREMELY_IMPORTANT>. Includes session-id-based dedup guard (Hermes fireson_session_startonce per session, so the same session_id means skip). Also addsskills/using-superpowers/references/hermes-tools.md(Hermes tool-name mapping), a Platform Adaptation pointer in SKILL.md, install docs, and 20 unit tests.Is this change appropriate for the core library?
Yes — this is infrastructure only (plugin hook + bootstrap injection), the same pattern already used by pi, Antigravity, Codex, etc. No new skills, no domain-specific content.
What alternatives did you consider?
on_session_start+ctx.inject_message— exactly what Pi and Antigravity use. The same pattern works here.The primary reference was the Pi harness, since Pi also has no native
activate_skilltool and required the sameread_filefallback approach.Does this PR contain multiple unrelated changes?
No. All changes are part of the single Hermes harness integration:
.hermes-plugin/— plugin implementationskills/using-superpowers/references/hermes-tools.md— Hermes tool mapping (required by SKILL.md's Platform Adaptation section)skills/using-superpowers/SKILL.md— one-line addition to Platform Adaptation bullet listREADME.md— Hermes Agent entry in quickstart + installation sectiondocs/README.hermes.md— harness-specific documentation.hermes-plugin/INSTALL.md— install instructionstests/hermes/— 20 unit tests (10 bootstrap, 10 plugin)Existing PRs
Environment tested
New harness support (required if this PR adds a new harness)
Two sessions were run. Session 1 was the smoke check ("What are your superpowers?"). Session 2 was the acceptance test ("Let's make a react todo list").
What the sessions confirmed:
⚡ Sending after interrupt: '<EXTREMELY_IMPORTANT>\nsuperpowers:using-superpower...'on every new session, provingctx.inject_messageworks."The superpowers rule says 'Let's build X → brainstorming first.'"and attempted to load the brainstorming skill.Gap found and fixed during testing:
Hermes'
skill_viewtool looks in Hermes' own skill registry (not our bundledskills/), soskill_view("brainstorming")returned "Skill 'using-superpowers' not found." The model recognized the rule but then rationalized past it ("it's a straightforward todo list") and built directly — the exact Red Flag the SKILL.md anti-rationalization table warns against.The last commit (
9f5e81d) fixes this by embedding the resolved_SKILLS_DIRpath in the bootstrap, with explicit instructions:A re-run with the fix installed is needed to confirm full brainstorming auto-trigger. The transcripts below are from the pre-fix run; they prove the injection mechanism works and that the model reads the rules correctly.
Smoke check transcript — "What are your superpowers?" (Hermes v0.18.0 · DeepSeek-V4-Pro)
Acceptance test transcript — "Let's make a react todo list" (Hermes v0.18.0 · DeepSeek-V4-Pro)
Assessment: Bootstrap fires ✅. Model quotes rules ✅.
skill_viewgap → brainstorming skipped ❌ (fixed in commit9f5e81d).Evaluation
skill_viewgap prevents brainstorming loadread_filefallback path now embedded — re-run needed to confirmRigor
superpowers:writing-skillsandcompleted adversarial pressure testing (paste results below)
rationalizations, "human partner" language) without extensive evals
showing the change is an improvement
Plugin tests (20/20 passing):
Skills change notes: Only one line added to
skills/using-superpowers/SKILL.md(a bullet in the Platform Adaptation list). No changes to Red Flags table, rationalizations, or behavior-shaping copy. The skills content is unchanged; only infrastructure was added.Human review