---
phase: 27-hermes-adapter
verified: 2026-04-02T16:30:35Z
status: gaps_found
score: 3/4 must-haves verified
re_verification: false
gaps:
  - truth: "AGENT_ADAPTER_TYPES has no duplicate entries"
    status: failed
    reason: "packages/shared/src/constants.ts still contains two gemini_local entries (lines 29 and 35). The SUMMARY claimed this was 'already clean on this branch' but the file has not been deduplicated. Commit 79b61059 ([nexus] feat(20-01)) added gemini_local after hermes_local, creating the duplicate, and no subsequent commit removed it."
    artifacts:
      - path: "packages/shared/src/constants.ts"
        issue: "gemini_local appears twice: line 29 (first occurrence, correct) and line 35 (second occurrence after hermes_local, duplicate to remove)"
    missing:
      - "Remove the second 'gemini_local' entry (line 35) from AGENT_ADAPTER_TYPES in packages/shared/src/constants.ts"
---

# Phase 27: Hermes Adapter Verification Report

**Phase Goal:** Users can create a Hermes agent in Nexus, configure it, and have it execute heartbeats that spawn `hermes chat -q`, return a result, and persist the session across runs
**Verified:** 2026-04-02T16:30:35Z
**Status:** gaps_found — 1 gap blocking full compliance
**Re-verification:** No — initial verification

## Goal Achievement

### Observable Truths

| #  | Truth                                                                                  | Status      | Evidence                                                                                     |
|----|----------------------------------------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 1  | hermes_local is treated as a sessioned local adapter for orphan-process liveness checks | VERIFIED   | `heartbeat.ts` line 75: `"hermes_local"` in `SESSIONED_LOCAL_ADAPTERS` set; consumed at line 1759 via `isTrackedLocalChildProcessAdapter` in orphan-reaping logic |
| 2  | Toolsets field does not corrupt extraArgs when creating a new Hermes agent             | VERIFIED    | `config-fields.tsx` lines 70–119: Toolsets `<Field>` is inside `{!isCreate && (<> ... </>)}` guard; no `extraArgs` reference anywhere in the file |
| 3  | Hermes session codec round-trip is tested (serialize, deserialize, getDisplayId, legacy key) | VERIFIED | `adapter-session-codecs.test.ts` lines 16, 109–132: hermesSessionCodec imported from `hermes-paperclip-adapter/server`; 2 hermes test cases pass; all 11 adapter-session-codecs tests pass |
| 4  | AGENT_ADAPTER_TYPES has no duplicate entries                                           | FAILED      | `constants.ts` line 29 and line 35 both contain `"gemini_local"` — duplicate not removed    |

**Score:** 3/4 truths verified

### Required Artifacts

| Artifact                                              | Expected                                        | Status     | Details                                                                                                   |
|-------------------------------------------------------|-------------------------------------------------|------------|-----------------------------------------------------------------------------------------------------------|
| `server/src/services/heartbeat.ts`                    | hermes_local in SESSIONED_LOCAL_ADAPTERS set    | VERIFIED   | Line 75: `"hermes_local"` present in set; function `isTrackedLocalChildProcessAdapter` wraps set at line 655–657, called at line 1759 |
| `packages/shared/src/constants.ts`                    | Deduplicated AGENT_ADAPTER_TYPES array          | FAILED     | File exists and contains hermes_local (line 34), but gemini_local is duplicated (lines 29 and 35); deduplication task was not completed |
| `ui/src/adapters/hermes-local/config-fields.tsx`      | Toolsets field hidden in create mode            | VERIFIED   | File created (123 lines); Toolsets inside `{!isCreate && ...}` at line 70; no extraArgs references; no stubs |
| `server/src/__tests__/adapter-session-codecs.test.ts` | Hermes session codec test block                 | VERIFIED   | Lines 16 (import), 109–132 (2 test cases); all 11 tests pass in vitest run                                |

### Key Link Verification

| From                                              | To                                       | Via                                          | Status   | Details                                                                                              |
|---------------------------------------------------|------------------------------------------|----------------------------------------------|----------|------------------------------------------------------------------------------------------------------|
| `server/src/services/heartbeat.ts`                | `server/src/adapters/registry.ts`        | SESSIONED_LOCAL_ADAPTERS set membership check | WIRED    | `isTrackedLocalChildProcessAdapter` defined line 655, called line 1759 in orphan-reaping loop        |
| `server/src/__tests__/adapter-session-codecs.test.ts` | `hermes-paperclip-adapter/server`    | import sessionCodec                          | WIRED    | Line 16: `import { sessionCodec as hermesSessionCodec } from "hermes-paperclip-adapter/server"`; tests pass |

### Data-Flow Trace (Level 4)

Not applicable — this phase modifies backend constants, a heartbeat set, test coverage, and a UI config form. No new data-rendering components were introduced that require data-flow tracing.

### Behavioral Spot-Checks

| Behavior                                          | Command                                                                                               | Result                      | Status  |
|---------------------------------------------------|-------------------------------------------------------------------------------------------------------|-----------------------------|---------|
| All session codec tests pass (incl. hermes)       | `pnpm --filter server exec vitest run src/__tests__/adapter-session-codecs.test.ts`                   | 11/11 tests pass             | PASS    |
| Hermes dual-source tests pass (regression check) | `pnpm --filter server exec vitest run src/__tests__/hermes-dual-source.test.ts`                       | 7/7 tests pass               | PASS    |
| UI TypeScript compiles cleanly                    | `pnpm --filter ui exec tsc --noEmit`                                                                  | Exit 0, no errors            | PASS    |
| Server TypeScript (excluding pre-existing errors) | `pnpm --filter server exec tsc --noEmit`                                                              | Only plugin-sdk errors (pre-existing, unrelated to this phase) | PASS (scoped) |
| Toolsets field has no extraArgs reference         | `grep -n "extraArgs" ui/src/adapters/hermes-local/config-fields.tsx`                                  | No output (no matches)       | PASS    |
| constants.ts gemini_local count                   | `grep -c "gemini_local" packages/shared/src/constants.ts`                                             | 2 (should be 1)              | FAIL    |

### Requirements Coverage

| Requirement | Source Plan | Description                                                                                               | Status         | Evidence                                                                                               |
|-------------|-------------|-----------------------------------------------------------------------------------------------------------|----------------|--------------------------------------------------------------------------------------------------------|
| HERM-01     | 27-01-PLAN  | Hermes adapter installed, enabled, appears in "Add Agent" dropdown                                        | SATISFIED      | Pre-existing: `ui/src/components/NewAgentDialog.tsx` lists hermes_local; `ui/src/components/AgentConfigForm.tsx` includes hermes_local in ENABLED_ADAPTER_TYPES |
| HERM-02     | 27-01-PLAN  | User can create a Hermes agent with config options (model selection, tool permissions)                     | SATISFIED      | `config-fields.tsx` has Model field in both modes; Toolsets properly guarded to edit-only, preventing extraArgs corruption |
| HERM-03     | 27-01-PLAN  | Heartbeat execution spawns `hermes chat -q`, processes task, returns result                                | SATISFIED      | `hermes_local` in SESSIONED_LOCAL_ADAPTERS enables correct orphan-process liveness checks; adapter wiring pre-exists from prior phase; 7 hermes-dual-source tests pass |
| HERM-04     | 27-01-PLAN  | Session persistence works across heartbeats via `--resume` flag                                            | SATISFIED      | Hermes session codec tests pass: serialize/deserialize round-trip and legacy session_id key both verified |

**Note:** HERM-01 through HERM-04 are marked complete in REQUIREMENTS.md. The one failing truth (duplicate constant) is a cleanup item that supports HERM-01 type compliance but does not directly block any of the 4 HERM requirements from functioning at runtime. However, the PLAN explicitly listed it as a must-have truth, so it is recorded as a gap.

### Anti-Patterns Found

| File                               | Line  | Pattern                                      | Severity  | Impact                                                                                          |
|------------------------------------|-------|----------------------------------------------|-----------|-------------------------------------------------------------------------------------------------|
| `packages/shared/src/constants.ts` | 35    | `"gemini_local"` — duplicate array entry     | Warning   | TypeScript `as const` array has duplicate. No runtime breakage (TypeScript union types deduplicate), but it is incorrect and the plan explicitly required removal. |

The server TS errors (`plugin-sdk` module not found) are pre-existing and unrelated to this phase — they exist on the branch prior to any phase-27 commits and are not introduced by this phase.

### Human Verification Required

None — all critical behaviors are verifiable programmatically for this phase.

### Gaps Summary

One gap blocks full must-have compliance:

**Duplicate `gemini_local` in `AGENT_ADAPTER_TYPES` (constants.ts)** — The plan task required removing the second `"gemini_local"` entry from `AGENT_ADAPTER_TYPES` in `packages/shared/src/constants.ts`. The SUMMARY noted "already clean on this branch," but the actual file has the duplicate at lines 29 and 35. Commit `79b61059` (from an earlier phase) added `gemini_local` after `hermes_local`, and no subsequent commit in phase 27 removed it. The fix is a single-line deletion.

The three other must-haves are fully implemented and tested:
- `hermes_local` is correctly in `SESSIONED_LOCAL_ADAPTERS` and the orphan-reaping logic uses it
- `config-fields.tsx` correctly guards the Toolsets field behind `{!isCreate && ...}` with no extraArgs corruption
- Hermes session codec has 2 passing tests (standard sessionId + legacy session_id key)

---

_Verified: 2026-04-02T16:30:35Z_
_Verifier: Claude (gsd-verifier)_
