feat(hermes): modernize hermes agent adapter and skills support

- Add --yolo and --accept-hooks headless auto-approval flags to spawn_spec and resume_spec
- Define Hermes TUI input delimiters (input_prompt='❯', input_rule_pattern='─{10,}')
- Refactor verify_artifact and discover in hermes.py using session started_at timestamps
- Fix HERDR_EPOCH capture timing before spawn in create_session.sh to prevent epoch race
- Update reconcile.sh for hermes drift-C multi-candidate and sibling claimed exclusion
- Add Hermes contract, epoch filtering, and C-ambiguous unit tests (140 passed)
- Add agent evaluation report and final review reports for Hermes support
This commit is contained in:
2026-08-28 20:17:04 +09:00
parent 4a3328d0b7
commit 6208a7fda3
12 changed files with 624 additions and 34 deletions
+42 -20
View File
@@ -14,7 +14,7 @@ class HermesAgentAdapter(BaseAgentAdapter):
@property
def ready_tokens(self) -> str:
return 'Hermes'
return 'Hermes|Welcome to Hermes Agent|NOUS HERMES'
@property
def exit_key(self) -> str:
@@ -28,6 +28,18 @@ class HermesAgentAdapter(BaseAgentAdapter):
def identity_cache_fields(self) -> tuple:
return ('session_id',)
@property
def input_prompt(self) -> str:
return ''
@property
def input_placeholder(self) -> str:
return ''
@property
def input_rule_pattern(self) -> str:
return '{10,}'
def artifact_path(self, uuid: str, ctx: DiscoveryContext) -> str:
return f"{ctx.home_dir}/.hermes/sessions/session_{uuid}.json"
@@ -35,15 +47,15 @@ class HermesAgentAdapter(BaseAgentAdapter):
hdb = f"{ctx.home_dir}/.hermes/state.db"
if not os.path.exists(hdb):
return False
if ctx.epoch and os.path.getmtime(hdb) < ctx.epoch:
return False
try:
conn = sqlite3.connect(hdb)
r = conn.execute("SELECT cwd FROM sessions WHERE id=?", (uuid,)).fetchone()
r = conn.execute("SELECT cwd, started_at FROM sessions WHERE id=?", (uuid,)).fetchone()
conn.close()
if not r:
return False
found_cwd = r[0]
found_cwd, started_at = r[0], r[1]
if ctx.epoch and started_at and float(started_at) < float(ctx.epoch):
return False
if found_cwd and workspace_key(found_cwd) != workspace_key(ctx.cwd):
return False
except Exception:
@@ -70,27 +82,37 @@ class HermesAgentAdapter(BaseAgentAdapter):
return purged
def spawn_spec(self, binary: str, session_uuid: str = "", use_wrapper: bool = False) -> str:
return binary
return f"{binary} --yolo --accept-hooks"
def resume_spec(self, binary: str, session_uuid: str, materialized: bool = False) -> str:
if materialized and session_uuid:
return f"{binary} --resume {session_uuid}"
return binary
return f"{binary} --resume {session_uuid} --no-restore-cwd --yolo --accept-hooks"
return f"{binary} --yolo --accept-hooks"
def auth_ok(self, run_cmd: Optional[Any] = None) -> bool:
return True
def discover(self, ctx: DiscoveryContext) -> list:
hdb = f"{ctx.home_dir}/.hermes/state.db"
if os.path.exists(hdb):
try:
conn = sqlite3.connect(hdb)
r = conn.execute("SELECT id FROM sessions WHERE cwd=? ORDER BY started_at DESC LIMIT 1", (ctx.workspace,)).fetchone()
conn.close()
if r:
cand = r[0]
if cand and self.verify_artifact(cand, ctx):
return [cand]
except Exception:
pass
return []
if not os.path.exists(hdb):
return []
try:
conn = sqlite3.connect(hdb)
if ctx.epoch:
rows = conn.execute(
"SELECT id FROM sessions WHERE cwd=? AND started_at >= ? ORDER BY started_at DESC LIMIT 20",
(ctx.workspace, ctx.epoch)
).fetchall()
else:
rows = conn.execute(
"SELECT id FROM sessions WHERE cwd=? ORDER BY started_at DESC LIMIT 20",
(ctx.workspace,)
).fetchall()
conn.close()
candidates = []
for (cand,) in rows:
if cand and self.verify_artifact(cand, ctx):
candidates.append(cand)
return candidates
except Exception:
return []