Phase 5 — The Final Purge
Phase 5 — The Final Purge (100% Go)
Section titled “Phase 5 — The Final Purge (100% Go)”Status: 🔨 in progress
Deliverable: Python tool scripts ported to Go or WASM. Python disappears entirely from the runtime path.
Completion lanes: Phase 5 spans Lane 3 — Tool Surface, Security, And Skills, Lane 4 — Gateway, Channels, Cron, And Delivery, and Lane 5 — CLI, API, TUI, Packaging, And Release. The phase is not “port every handler first.” Descriptor, schema, availability, trust, audit, and doctor contracts must land before broad tool or CLI handler ports.
Phase 5 is when Python disappears entirely from the runtime path. Each sub-phase is a separable spec.
Phase 5 Sub-phase Outline
Section titled “Phase 5 Sub-phase Outline”| Subphase | Status | Deliverable |
|---|---|---|
| 5.A — Tool Surface Port | ⏳ planned | Keep the 61-tool registry as inventory only; execute through schema parity, then refresh the Hermes b35d692f manifest for Discord split/cron schema/toolset drift before pure/core tools, stateful groups, and network/browser/sandbox-dependent handlers |
| 5.B — Sandboxing Backends | ⏳ planned | Port the environment interface and file-sync contract first, then Docker, Modal, Daytona, and Singularity as backend-specific implementations |
| 5.C — Browser Automation | ⏳ planned | Freeze the browser action/result transcript, then bind Chromedp/Rod and optional Browserbase/Firecrawl provider fallbacks behind the shared contract |
| 5.D — Vision + Image Generation | ⏳ planned | Split multimodal work into vision input normalization/token budgeting and image-generation result/storage contracts |
| 5.E — TTS / Voice / Transcription | ⏳ planned | Split voice work into voice-mode state, transcription ingestion, TTS synthesis, and gateway media-delivery hooks |
| 5.F — Skills System (Remaining) | ⏳ planned | Port remaining tools/{skill_manager_tool,skills_hub,skills_sync,skills_guard}.py + registry metadata on top of the Phase 2.G active/inactive store, plus upstream skill preprocessing, skill-backed slash command preprocessing, and bundled-skill credential evidence such as Airtable. Note: Core learning loop (skill extraction, improvement) is Phase 6 |
| 5.F.1 — Skills Hub Integration | ⏳ planned | Port skills.sh, clawhub, lobehub, hermes-index registries |
| 5.F.2 — Skill Auto-Discovery | ⏳ planned | Port auto-generated skill discovery and metadata management |
| 5.G — MCP Integration | ✅ complete | Dependency-ordered MCP slices are validated: config/env resolver, stdio/HTTP discovery, schema normalization, OAuth state/refresh recovery, and managed tool gateway bridge. Honcho MCP HONCHO_API_URL self-hosted drift is handled as server-local MCP config, not a hosted dependency for internal Goncho memory |
| 5.H — ACP Integration | ⏳ planned | Port acp_adapter/ as an authenticated protocol server with session lifecycle, tool permission prompts, and event streaming tests |
| 5.I — Plugins Architecture | ⏳ planned | Port plugin manifest loading, capability registration, version checks, isolation boundaries, then extension install/enable/disable flows; upstream Spotify has moved into plugins/spotify/, so it is now the first first-party plugin fixture rather than a built-in tool port |
| 5.J — Approval / Security Guards | ⏳ planned | Port tools/{approval,path_security,url_safety,tirith_security,website_policy}.py as small guard slices: dangerous-command detection, approval-mode config, cron approvals.cron_mode, then combined Tirith/path/URL/website policy decisions |
| 5.K — Code Execution | ✅ complete | Go-native execute_code now runs guarded shell snippets with timeout/output caps and filesystem/network blocking; Python runtimes are hard-blocked at terminal and execute-code boundaries; broader backend-specific sandboxes remain Phase 5.B |
| 5.L — File Ops + Patches | ⏳ planned | Split tools/{file_operations,file_tools,checkpoint_manager,patch_parser}.py into checkpoint shadow-repo GC, file-read dedup/cache guards, then write/patch/rollback primitives |
| 5.M — Mixture of Agents | ⏳ planned | Port tools/mixture_of_agents_tool.py only after provider routing and subagent envelopes are stable |
| 5.N — Misc Operator Tools | ⏳ planned | Port todo, clarify, session search, debug helpers, send_message, cronjob tools, and interrupt as small contracts; session search must reuse Phase 3 lineage/source evidence and exclude the current lineage root in recent mode; cron parity remains split into tool API/schedule parsing, context_from output chaining, prompt/script safety, and multi-target/media/live-adapter delivery follow-ups |
| 5.O — Hermes CLI Parity | ⏳ planned | Port the 49-file hermes_cli/ tree as dependency-aware command groups: deterministic helpers, PTY bridge adapter, registry/active-turn/busy policy, profile path/active-profile helpers before config/auth/setup UI, gormes chat -q scripted-chat model/provider resolution plus removed -z/--oneshot guidance, current auth command-tree parity (auth add/list/remove/reset/status/logout/spotify; top-level login is removed guidance), platform toolset persistence/MCP sentinel behavior, RestartSec-aware service restart polling, gateway management read-model closeout before mutating commands, local log snapshot diagnostics before backup/upload behavior, and later webhook/cron/platform/status command groups; replaces the upstream hermes binary |
| 5.P — Docker / Packaging | ⏳ planned | Mirror upstream Docker/Homebrew/release layout with gormes doctor --offline smoke checks and no Python runtime dependency in the final image; publish Unix install.sh through GitHub Releases, keep Windows install.cmd/install.ps1 as landing-site aliases, and freeze the root/FHS vs user-scoped Unix layout policy from Hermes b35d692f |
| 5.Q — API Server + TUI Gateway Streaming Surface | ⏳ planned | Port tui_gateway/ plus the upstream OpenAI-compatible gateway/platforms/api_server.py surface: Bubble Tea remote streaming, native TUI/no-Node bundle independence after Hermes ee0728c6, TUI startup model/provider override and static alias behavior from 283c8fd6, native selection/copy parity-or-divergence after edc78e25, /v1/chat/completions, /v1/responses, /v1/runs/{id}/events, incomplete snapshot persistence on disconnect/cancel, gateway proxy mode, dashboard-facing API contracts, /health/detailed, and cron admin endpoints over the native Go runtime |
| 5.R — Code Execution Mode Policy | ⏳ planned | Split upstream PR #11971 into four dependency-ordered TDD slices — mode resolver + config precedence, strict-mode CWD/interpreter parity, project-mode CWD + active venv detection, then default-mode selection + config cut-over — without widening the shipped 5.K filesystem/network blocking contract |
Relationship to Phase 6
Section titled “Relationship to Phase 6”Phase 5.F (Skills System port) is the mechanical work: porting the upstream Python skills plumbing. Phase 6 (The Learning Loop) is the algorithm on top — detecting complexity, distilling patterns, scoring feedback. Phase 5.F is a dependency of Phase 6, but they are not the same work.
Planning Notes
Section titled “Planning Notes”Phase 2.D shipped the Go-native cron MVP: scheduler, job store, run audit, CRON.md mirror, and Heartbeat delivery rules. It did not port the full upstream cron operator surface. The remaining cron/jobs.py, cron/scheduler.py, and tools/cronjob_tools.py parity work belongs in 5.N as TDD slices so it can reuse the Phase 2.D store without reopening the shipped cron audit contract. Hermes b35d692f added context_from chaining; Gormes should map that to the native run audit/output read model rather than copying Hermes’ Markdown output directory as source of truth.
Hermes b35d692f also reshaped the operator tool surface: Discord is now split into discord and discord_admin toolsets with platform restrictions, cronjob schemas include context_from, Feishu gained document/drive toolset coverage, and hermes tools persistence hardens MCP server names, numeric YAML keys, no_mcp, and restricted toolsets. The 5.A manifest-refresh row must land before handler or CLI rows use the old embedded manifest, otherwise workers will keep targeting the stale discord_server shape.
Hermes 4921b269 adds a smaller toolset regression fix: homeassistant stays
default-off when HASS_TOKEN is absent, but the env var opts it back into
cron/CLI default toolsets because the runtime check function already gates the
actual HA tools. Track this as a pure internal/cli/toolset_config.go row; do
not combine it with Home Assistant handlers, cron execution, or unrelated
default-off toolsets such as MOA/RL.
Hermes 5006b220 adds two CLI/service deltas that Gormes should freeze as small rows before broad CLI ports: top-level one-shot mode (hermes -z) with explicit model/provider/env resolution, and update restart polling that waits through systemd RestartSec before declaring the gateway failed to relaunch. The parser half of one-shot mode is already validated; keep final-output capture, noninteractive safety policy, RestartSec parsing, and active-status polling as separate rows so workers do not mix output plumbing with service-manager state machines.
Current upstream Hermes auth is not auth login: hermes login is a removed
shim that points users to hermes auth, hermes model, or hermes setup.
The non-deprecated provider command family is
auth add/list/remove/reset/status/logout/spotify, with top-level logout
kept as a narrow provider-auth shortcut. Gormes should land the command-tree
manifest refresh before cmd/gormes/auth.go, then port the credential-pool
commands before OAuth provider adapters and the Spotify service-provider
subcommand.
The OpenAI-compatible API server is not the Phase 1 bridge. Phase 1 consumes Python’s api_server; Phase 5.Q replaces that donor surface in Go. The latest upstream API server adds stored Responses snapshots for disconnect/cancel paths and gateway proxy mode; keep those as separate slices after the base chat/Responses contracts so client-resilience work does not hide basic HTTP parity failures. Keep cron admin endpoints behind the 5.N cronjob parity slices so HTTP control, CLI control, and tool control all share one scheduler/store contract. Hermes ee0728c6 fixed a first-launch TUI rebuild bug by treating a missing packages/hermes-ink/dist/ink-bundle.js as stale; Gormes should not port that Node/Ink machinery, but it should fixture-lock that native TUI startup, doctor/status output, docs, and landing-page install copy never require npm, HERMES_TUI_DIR, or Hermes bundle files. Hermes 283c8fd6 moved model/provider override state into TUI launch and resolved short aliases without startup network lookup; Gormes should adapt that into the native Cobra/Bubble Tea path instead of leaving overrides oneshot-only. Hermes edc78e25/31d7f195 tightened custom Ink selection copy over SSH, indentation, rendered spaces, and bounds; Gormes’ next slice should explicitly document and fixture-lock terminal-native Bubble Tea selection with no advertised custom copy hotkey. A later Go-native copy mode can be planned separately if the product decision changes. Hermes’ local interactive terminal is not the old Node/Ink bundle: cli.py owns the prompt_toolkit chat surface with bottom-pinned input, skin-aware prompt symbols, response boxes, status bars, busy-input routing, slash autocomplete, modal approval/clarify/secret panels, paste/image handling, and tool-progress scrollback. Exact Gormes TUI parity therefore means replacing the current Bubble Tea dashboard chrome with that operator contract while preserving the Go-native kernel/event boundary.
Operation And Tool Descriptor Rule
Section titled “Operation And Tool Descriptor Rule”The retired donor study strengthened the Phase 5 rule: do not start by porting handlers. Start by freezing operation/tool descriptors.
Each ported operation should declare:
- name and description;
- JSON schema and result envelope;
- toolset/category;
- availability check;
- mutating or read-only;
- idempotent or not;
- prompt-visible or operator-only;
- allowed trust classes;
- timeout and result-size budget;
- audit event kind;
- degraded-mode status field.
Those descriptors should drive model tool schemas, CLI/gateway command surfaces, doctor checks, audit taxonomy, and fixture generation wherever possible. A Python donor file remains inventory until the descriptor and parity fixture exist.
Hermes adds the schema-repair lesson: dynamic schemas must reflect available tools. If a related tool or provider is disabled, the prompt-visible schema must not advertise an impossible path that causes hallucinated tool calls.
TDD Execution Notes
Section titled “TDD Execution Notes”Phase 5 is the highest-risk place to accidentally create giant porting tasks. Treat every broad row above as an inventory bucket, not a direct worker assignment.
- Start with schema parity, not handlers. The first 5.A slice should snapshot upstream tool names, toolsets, required env vars, and JSON result shapes so later ports can prove compatibility without reading the Python tree repeatedly.
- Land shared contracts before heavy backends. The environment/file-sync interface must precede Docker/Modal/Daytona/Singularity. The browser action transcript must precede Chromedp/Rod/provider bindings. The checkpoint/path-policy contract must precede write-capable file tools.
- Keep external-service work fixture-first. Browserbase, Firecrawl, MCP OAuth, ACP, cloud sandboxes, image models, TTS, and transcription should all land with fake clients before any live credential smoke test.
- Reuse existing Gormes substrates. Cron tool/API parity should reuse Phase 2.D stores. Session search should reuse Phase 3 catalog and GONCHO scoping. Skills hub and preprocessing work should reuse the Phase 2.G active/inactive store. CLI parity should consume the same gateway/pairing/status read models as the runtime.
- 5.R mode policy is strictly additive. The shipped 5.K sandboxed-exec envelope (
status,error,filesystem_access,network_access, stdout/stderr caps, timeout) is a public contract. 5.R slices must not widen or renegotiate it — they only choose CWD and interpreter per mode. Land the pure resolver first, then strict parity, then project mode, then the default cut-over; the order matters because both later slices depend on the frozen resolver and the pinned strict baseline. - 5.P installer parity is release-asset-bounded. The Unix installer lives at repo-root
install.shand is published through GitHub Releases, not the custom-domain landing site; Windows installer assets stay under the landing-site module with tests guarding their published copies. The Goinstall_unix_test.go/install_windows_test.gotests must drive the scripts under fake toolchains — no network calls, no root-owned writes, no Python/Node side-installs — so Gormes stays a single-binary deployment target even as the installer surface widens. Hermesb35d692fchanged root Linux installs toward an FHS layout, so the new row must either port that behavior or document and test an intentional user-scoped Gormes divergence before public install copy changes. - 5.Q dashboard drift is API-contract inventory. The upstream React dashboard is not a reason to add Node/TypeScript to the Gormes runtime. Track its chat, session, model picker, OAuth, tool-progress, PTY, and plugin-panel expectations as API contracts first; a Go-native dashboard UI can be decided only after the native endpoints are stable.
- 5.O CLI buckets stay split by side effect.
gormes chat -q, final-output capture, noninteractive safety, and removed-z/--oneshotguidance are validated on main. Remaining broad CLI buckets must stay dependency-ordered: profile path/active-profile helpers before config/auth/setup commands, gateway read-model closeout before mutating service commands, and local log snapshot capture before backup/archive/upload behavior. - 5.O service restart polling is parser first, poller second. Parse fake
RestartUSecoutput and compute bounded restart delays before landing the fake active-status poller that waitsmax(10s, RestartSec+10s). Neither row should touch realsystemctl, Windows service control, installers, or gateway restart logic. - 5.Q TUI bundle drift is a deliberate divergence. Upstream Hermes still has to defend its Node/Ink TUI bundle, including the
ee0728c6stale-bundle rebuild check. Gormes proves the opposite withcmd/gormes/tui_bundle_independence_test.go: native Bubble Tea startup and offline status do not shell out to npm/node, inspectnode_modules, or requirepackages/hermes-ink/dist/ink-bundle.js. - 5.Q TUI model/copy drift is native-first. Port
283c8fd6model/provider startup override semantics into Gormes’ Cobra/Bubble Tea path with static alias fixtures and no provider catalog network calls. Treatedc78e25/31d7f195Ink selection-copy fixes as an explicit divergence row for now: docs and TUI status should say Gormes relies on terminal-native selection and should not advertise custom copy hotkeys until a Go-native copy mode exists.
Go donor pointers
Section titled “Go donor pointers”Before writing a new Phase 5 slice, route through the gormes-references
skill (docs/development-skills/gormes-references/SKILL.md) to find the
donor file that already shapes the seam.
| Phase 5 problem | Donor file | Notes |
|---|---|---|
| 5.A tool registry + descriptor-driven schema/availability/trust | nanobot/pkg/tools/service.go, nanobot/pkg/tools/flows.go | Apache 2.0; descriptor pattern |
| 5.A tool-output truncation while persisting full bytes (artifact pointer) | nanobot/pkg/agents/truncate.go | Already used in Phase 2 inbound |
| 5.A image-token estimation per provider | nanobot/pkg/agents/tokencount.go | Conservative per-provider fallback |
| 5.B sandbox environment interface + cancellable workers | nanobot/pkg/runtime/runtime.go | Explicit dependency layering |
| 5.G MCP serialized write queue (deterministic, cancel-before-start) | engram/internal/mcp/write_queue.go | Already in production use in engram |
| 5.G MCP activity/audit logging (redaction, append-only) | engram/internal/mcp/activity.go | Same audit shape Gormes uses in 2.D/3.E |
| 5.J approval / dangerous-action filters with declarative pre-call gates | nanobot/pkg/tools/flows.go, axe/internal/tool/ | Filter helpers + flow gates |
| 5.J path-traversal/URL/website policy guards | axe/internal/artifact/tracker.go | Sanitized-path pattern, append-only registry |
| 5.K code execution sandbox + bounded stdout/stderr caps | nanobot/pkg/agents/truncate.go | Output-cap policy already shipped uses this shape |
| 5.L file-ops checkpoint + path-sanitization + dedup | axe/internal/artifact/tracker.go | Path-traversal guard for write-capable file tools |
| 5.M mixture-of-agents — workflow agents (loop / sequential / parallel) | adk-go/agent/workflowagents/... | Workflow primitives without rewriting kernel |
| 5.N session-search / debug helpers — bounded token budget | axe/internal/budget/budget.go | Per-turn counter + reset |
| 5.O CLI parity — config/profile/dotenv layered loaders | axe/internal/config/, axe/internal/xdg/ | XDG-respecting layered config |
| 5.O CLI parity — credential/auth surface | goclaw/internal/oauth/openai.go, goclaw/internal/oauth/token.go | Code permitted with provenance for PKCE/state/token-source shape; Hermes hermes_cli/auth.py and hermes_cli/auth_commands.py remain the behavior contract |
| 5.Q API server proxy mode + run-event SSE | nanobot/pkg/runtime/runtime.go | Cancellable session-scoped workers |
| 5.R code-execution-mode resolver (strict vs project, CWD/interpreter) | axe/internal/resolve/, axe/internal/envinterp/ | Per-mode resolver pattern |
Provider-side surfaces (auth/streaming/quota/retry) inside any 5.x tool route
through gormes-provider-parity and
references/go-agent-os/GORMES-PROVIDER-PATTERN-REFERENCES.md instead of
re-deriving the OAuth/quota classifier.