Skip to content

feat(autopilot): make Hermes implementer delegation lifecycle-safe - #1849

Merged
ritsuKai2000 merged 13 commits into
nextfrom
feat/autopilot-hermes-implementer
Jul 18, 2026
Merged

feat(autopilot): make Hermes implementer delegation lifecycle-safe#1849
ritsuKai2000 merged 13 commits into
nextfrom
feat/autopilot-hermes-implementer

Conversation

@ritsuKai2000

@ritsuKai2000 ritsuKai2000 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Keep the full implement-issue lifecycle in one canonical skill and reduce the Claude/Hermes differences to thin runtime adapter references.
  • Route Hermes coordinator sessions and depth-needing stages through a Jinn-owned stateless launcher, while leaving the installed upstream Hermes runtime unchanged.
  • Launch stages 1, 3, 4, and 5 as fresh Hermes OS roots so each stage gets its own native delegation-depth budget and can fan out.
  • Carry the selected adapter, bare model, explicit provider, installed Python, and Autopilot package path consistently from dispatcher to stage runner.
  • Fail closed at boot if the configured Python cannot import Hermes, the model is org-prefixed, or the provider is not openai-codex.
  • Add contract tests for the canonical skill boundary, launcher session context, runtime argv/env, fresh-root stages, runtime/billing guards, and Claude compatibility.

Why the stateless launcher exists

Hermes Agent v0.18.2 forces top-level model delegation into background mode. A finite hermes chat -q process can therefore exit before its delegated child result returns. There is no released CLI/config switch that changes that capability. The checked-in launcher binds the normal Hermes session context with async_delivery=False, invokes the standard Hermes CLI, and clears the context afterward. This makes finite sessions synchronously join native delegates without patching or forking upstream Hermes.

Upstream context:

Verification

  • cd packages/autopilot && yarn typecheck — exit 0.
  • cd packages/autopilot && yarn test — 65 test files, 618 tests passed; exit 0.
  • Installed-Hermes import probe (gateway.session_context + hermes_cli.main) — exit 0.
  • git diff --check origin/next...HEAD — exit 0.
  • Final whole-branch review — ready to merge, with no remaining findings.

Direct native-delegation smoke used the checked-in launcher with the installed Hermes Python, normal HERMES_HOME, bare gpt-5.6-sol, and explicit openai-codex provider:

HERMES_HOME="$HOME/.hermes" "$HOME/.hermes/hermes-agent/venv/bin/python" \
  packages/autopilot/bin/jinn-hermes-stateless.py chat -q \
  'Delegate exactly one task using delegate_task. In that child task, instruct the child to return exactly HERMES_SYNC_CHILD_OK and nothing else. Wait for the delegated result. After receiving it, output exactly: PARENT_RECEIVED: HERMES_SYNC_CHILD_OK' \
  -Q --yolo --accept-hooks --model gpt-5.6-sol --provider openai-codex

Result: exit 0 in 16 seconds with exact marker PARENT_RECEIVED: HERMES_SYNC_CHILD_OK.

Live Autopilot outcome

Issue #1822 was still parked solely from the original Hermes one-shot failure, had no implementation PR/new external work, and returned classification: clear. It was restored for one bounded retry: #1822 (comment)

The authorized command was:

cd packages/autopilot
JINN_DISPATCHER_IMPLEMENTER_RULES='[{"effort":"Low","implementer":"hermes"}]' \
  yarn autopilot --once --cap 1

The boot log correctly named the Hermes coordinator, bare model, explicit provider, and installed Python. However, the cycle dispatched no issue: existing shared eng-loop work consumed the cap (skipped (throttle): 6). The shared dispatcher was repeatedly retrying #1816, #1829, and #1833, whose session logs ended on Claude session-limit messages. Concurrent drift also changed #1822 during observation without producing a #1822 worktree, updated session log, commits, or PR.

To prevent unintended pickup, #1822 was safely parked at Blocked on: Human / Status: Human: #1822 (comment)

Therefore the direct native-delegation proof passed, but the full nine-point live issue pipeline was blocked before Hermes dispatch. No live Hermes session or implementation PR was created, and this PR does not claim that end-to-end proof.

Scope guard

The unrelated local change to docs/runbooks/swe-rebench-v2-public-testnet.md was not staged, committed, pushed, or included in this PR.

claude added 13 commits July 17, 2026 16:28
…odex sub)

Implementer routing was directive-only: resolveImplementer picked a CLI but
dispatch.ts always spawned `claude -p`, so the choice only edited a prompt
sentence. Make `hermes` a REAL second coordinator running its own machinery
end-to-end — its SKILL.md loader, its MCP wiring, and its native delegate_task
subagents for the stage pipeline. No claude inside the session; the claude
review-pr loop remains the independent cross-model gate at the PR boundary.

- types: Implementer += 'hermes'; hermesModel/hermesProvider/hermesPath config.
- hermes-home (new): per-session $HERMES_HOME + generated config.yaml. Required
  because hermes reads reasoning effort ONLY from agent.reasoning_effort (no CLI
  flag, no env), so concurrent sessions at different Efforts cannot share a home.
  Board Effort -> hermes tier, with Max->xhigh ('max' is not a hermes tier and
  would silently degrade to the provider default). Enables the `delegation`
  toolset (the client daemon deliberately strips it for marketplace solves; a
  coordinator is the opposite case). Seeds operator .env/auth/auth.json/bin by
  copy — the dispatcher never handles the secret values.
- dispatch: branch the spawn; claude path unchanged (regression-locked).
- run-autopilot: IMPLEMENTERS += hermes, env parsing, boot log + org-prefix warn.
- implement-issue-hermes (new skill): same lifecycle contract as implement-issue
  (triage gate, TDD, zero-commit guards, draft PR + Closes #N + engine:review,
  Status->In Review, escalation) with delegate_task in place of claude subagents;
  reviewers are fresh children that never saw the implementer's context.

Billing correctness (operator-corrected mid-implementation): the model id is
BARE and the provider is passed EXPLICITLY. hermes infers the provider from the
model id's shape, and any `<org>/<model>` infers `openrouter` — which would bill
an API key instead of the ChatGPT/Codex subscription. Defaults mirror the
operator's own working setup (~/.codex/config.toml model="gpt-5.6-sol";
~/.hermes/config.yaml provider: openai-codex). openai-codex auto-selects the
codex_responses api_mode + Codex base_url, so neither is configured. Guarded by
tests and a boot-time warning.

Activation is a routing rule, not a flag: JINN_DISPATCHER_IMPLEMENTER_RULES
e.g. [{"effort":"Low","implementer":"hermes"}]. Rollback = drop the rule.

Verified: packages/autopilot typecheck clean, 586 tests. Live smoke on the real
Codex subscription (config generated by prepareHermesHome) — exit 0, child
returned DONE: proves the model id resolves, subscription auth works, the
config parses, and delegate_task spawns a real subagent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ritsuKai2000
ritsuKai2000 marked this pull request as ready for review July 18, 2026 12:25
@ritsuKai2000
ritsuKai2000 merged commit a70dfa7 into next Jul 18, 2026
3 checks passed
@ritsuKai2000
ritsuKai2000 deleted the feat/autopilot-hermes-implementer branch August 24, 2026 08:25
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