fix(host-matrix,cap-routing): reconcile Linux Hermes push, correct live vs planned

- hermes-osa: LIVE (local chat validated), Mevy: separate (coexists)
- Provider: DeepSeek direct primary, OpenRouter fallback, Z.AI deferred
- Telegram/gateway/daemon explicitly OFF/deferred, 4 tracks documented
- CAPABILITY-ROUTING.md: labelled [LIVE] [PLANNED] [DESIGN] throughout
- Cross-host routing: explicitly 'not live yet' — local Unix socket only
- Removed stale install-note section superseded by osa detail block
- osa section compacted: single list format, no redundant entries
- Merges and supersedes Linux Hermes commit 9ec7f39
This commit is contained in:
Sam & Claude 2026-06-17 21:39:29 +02:00
parent 9ec7f39c13
commit 010d959a16
2 changed files with 58 additions and 97 deletions

View file

@ -1,17 +1,16 @@
# Capability-Based Task Routing
**LIVE VS PLANNED: this document describes the intended architecture.** Colibri's capability matcher exists (Colibri daemon) and works for a single-host daemon/agent pool. Cross-host routing across debby/domedog/osa is **not live yet** — that is the next wiring step. Sections below are labelled `[LIVE]` or `[PLANNED]`.
**Principle: a tool that one OS can't support is not a loss — it's a routing
constraint.** In a multi-agent, multi-OS fleet we don't force every capability onto
every host. We let each host advertise what it can do, let each task declare what it
needs, and let the scheduler send the task to a host that qualifies. FreeBSD stays lean;
the capability simply lives where it's cheap.
This is the operational payoff of the dual-OS survivability model: heterogeneous hosts,
one task board, automatic placement.
## [LIVE] What Colibri already provides (single host)
## What Colibri already provides
The matching engine exists today in `colibri-daemon` — this is wiring, not a rewrite:
The matching engine exists today in `colibri-daemon` — this is working, per-host:
- **Agents carry capability tags**`agents.capabilities` (JSON array) in the store
(`colibri-store` schema); registered via `colibri` client / `--capabilities`.
@ -21,29 +20,24 @@ The matching engine exists today in `colibri-daemon` — this is wiring, not a r
with `capability_match_score` and picks the best fit.
- **Unmatched = parked, not failed** — if requirements are non-empty and no online agent
matches, `pick_agent` returns `None`: the task is created but left **unassigned until a
capable agent appears**. Exactly the behaviour we want — a screenshot task waits for a
Linux host rather than failing on FreeBSD.
capable agent appears**.
## What we add to realize it
> **Important caveat:** the daemon listens on a **local Unix socket only**. This means today the agent pool is per-host. An agent on osa cannot pick up a task from debby's daemon automatically.
| Piece | Status | Action |
| ----- | ------ | ------ |
| Capability vocabulary | tags are free-form (`rust`, `python`, `linux`) | Agree a shared tag set (below) |
| Agents advertise real capabilities | manual / ad-hoc | Derive from `verify_facts_probe.py`; register at agent start |
| Skills declare their needs | `SkillManifest` has no requirements field | Add `required_capabilities: Vec<String>`; scheduler reads it |
| Cross-host agent pool | daemon listens on a **local Unix socket only** | One orchestrator daemon (debby/Hermes); remote agents reach it over Tailscale |
## [PLANNED] Cross-host topology
### Cross-host topology (the one real decision)
The daemon's socket is local, so today the agent pool is per-host. To route *across*
hosts, agents on every host must be visible to one scheduler. Recommended:
To route *across* hosts, agents on every host must be visible to one scheduler. Not implemented yet. Recommended approach:
- **Central orchestrator daemon on debby (Hermes).** Agents on domedog/osa reach its
socket over Tailscale (forwarded via SSH/`socat`). Hermes is already the designated
orchestrator, so this matches the agent matrix.
- Alternative (heavier, deferred): daemon-to-daemon federation.
## Capability vocabulary (initial)
## [LIVE] Capability vocabulary (initial)
| Piece | Status | Action |
| ----- | ------ | ------ |
| Capability vocabulary | tags are free-form (`rust`, `python`, `linux`) | Agree a shared tag set (below) |
Flat, explicit tags — the matcher does exact string comparison, no implied hierarchy.
Sourced from the probe and recorded per host in [`HOST-MATRIX.md`](./HOST-MATRIX.md).
@ -62,9 +56,9 @@ Hosts advertise only what they truly have. Example from the current fleet:
- **domedog / debby (Linux):** `linux`, `docker`, `gui`, `screenshot`, `image-render`, …
- **osa (FreeBSD):** `freebsd`, `freebsd-jail`, `zfs`, `rust`, … (no `screenshot`/`image-render`)
## Worked example: the tmux-screenshot skill
## [DESIGN] Worked example: the tmux-screenshot skill
This is why we could drop `py312-pillow` from the FreeBSD ISO without losing the skill:
This illustrates the intended routing flow (requires [PLANNED] cross-host topology above):
1. FreeBSD image drops Pillow — stays lean (`pkg-list` carries only `python312`).
2. The skill manifest declares `required_capabilities: ["screenshot"]` (or `image-render`).

View file

@ -24,13 +24,17 @@ on any host fills in its own row. Source of truth for facts is the probe — not
## 1. Agent placement (who runs where)
| Agent | Host | OS / Isolation | Harness | Role | Bot / channel | Status |
| ---------- | ------- | ------------------------------- | ----------------------- | ------------------------- | ---------------------------- | ---------------------- |
| Hermes | debby | Debian 13 / Docker | Hermes Agent (upstream) | Orchestrator, soul backup | @hermes_samob_bot (Telegram) | live |
| Zot | debby | Debian 13 / Docker | Zot RPC | Coding, media workflows | @zot_samob_bot (Telegram) | live |
| Claude | domedog | Ubuntu 24.04 / Docker | Claude Code | Verification, review | — (CLI) | live |
| hermes-osa | osa | FreeBSD 15 / host service first | Hermes Agent (FreeBSD) | Native FreeBSD Hermes | _(off — Telegram deferred)_ | installed; local chat validated |
| Mevy | osa | FreeBSD 15 / jail | Hermes Agent | Telegram operator bot | Mevy (Telegram) | live (separate token) |
| Codex | osa | FreeBSD 15 / jail | Codex CLI | ISO builds, validation | — | installed (probe) |
| ----------- | ------- | --------------------------- | ---------------------------- | -------------------------------- | --------------------- | ----------------------------- |
| Hermes | debby | Debian 13 / Docker | Hermes Agent (upstream) | Orchestrator, soul backup | @hermes_samob_bot | LIVE |
| Zot | debby | Debian 13 / Docker | Zot RPC | Coding, media workflows | @zot_samob_bot | LIVE |
| Claude | domedog | Ubuntu 24.04 / Docker | Claude Code | Verification, review | — (CLI) | LIVE |
| **Mevy** | osa | FreeBSD 15 / host | Hermes Agent (upstream, CLI) | **Existing FreeBSD Telegram bot**| Mevy (Telegram) | **LIVE — separate from IPA** |
| **hermes-osa** | osa | FreeBSD 15 / host | Hermes Agent (FreeBSD fork) | **Native FreeBSD Hermes local/chat** | — (CLI) | **LIVE — this session** |
| Codex | osa | FreeBSD 15 / jail | Codex CLI | ISO builds, validation | — (CLI) | LIVE |
> **Mevy vs hermes-osa distinction**: Mevy is the existing FreeBSD Telegram bot running a separate Hermes instance. hermes-osa is this new native Hermes instance (clean-room MIT `hermes-bsd` fork) running as local CLI/chat. They coexist — hermes-osa does not replace Mevy yet. A future migration may consolidate them.
>
> **Status key**: `LIVE` = running and validated right now. `INSTALLED` = binary present, not yet validated in role. `PLANNED` = not yet set up. No guessing.
> Notes:
>
@ -99,78 +103,41 @@ host that fails. What you guess will be wrong; what you probe will be right.
- **Telegram**: @hermes_samob_bot + @zot_samob_bot in "My Debby" group
- **Layered soul**: commit `817624c`, 6 curated memories, 9 cross-harness skills
### osa (FreeBSD: Mevy + Codex + hermes-osa) — probed 2026-06-17 by Mevy
### osa (FreeBSD: Mevy + hermes-osa + Codex) — probed 2026-06-17 by hermes-osa
- **Identity**: hostname `osa.smilepowered.org`, Tailscale `100.72.229.63`
- **OS**: FreeBSD `15.0-RELEASE-p10`, kernel `FreeBSD osa.smilepowered.org 15.0-RELEASE-p10 FreeBSD 15.0-RELEASE-p10 releng/15.0-n281064-98258a339269 GENERIC amd64`
- **Virt**: not reported by probe
- **CPU**: Intel Core Processor (Haswell, no TSX), 6 vCPU
- **Memory**: 11 GiB RAM, swap not reported by probe
- **Storage**: ZFS pool `zroot`, 98.5G, ONLINE; latest storage probe reports 23.4G available
- **GPU**: not reported by probe (`lspci` returned usage text)
- **Jails / containers**: FreeBSD jails `cms` and `worker`; Docker not installed
- **Agents reported by probe**: Codex CLI `/usr/local/bin/codex` (`codex-cli 0.117.0`); Claude Code `/home/clawdie/.npm-global/bin/claude`
- **Mevy Telegram / provider**: not reported by probe; do not guess token ownership or provider
- **hermes-osa** (FreeBSD-native Hermes): installed, local chat validated — see install note below
- **Provider**: DeepSeek direct (primary, `deepseek-chat`), OpenRouter (fallback/manual lane), Z.AI (deferred)
- **Telegram**: off (deferred until clean CLI proof complete — separate token from Mevy)
- **Daemon**: not enabled (rc.d promotion is a separate track)
- **Mevy**: separate Telegram bot, separate token. Lives alongside hermes-osa on osa.
Not replaced — hermes-osa uses local chat until Telegram migration decision.
- **Layered soul**: commit `3ee2888`, 7 curated memories, 10 cross-harness skills
#### hermes-osa install note (corrected)
The osa FreeBSD-native Hermes is the **clean-room MIT `hermes-bsd`** codebase — _not_
"Autolycus" (an LGPL upstream dependency the layer explicitly avoids; the old codename is
retired). Grounded in the actual code:
- **Service:** `hermes_daemon` (`packaging/freebsd/hermes_daemon.in``/usr/local/etc/rc.d/hermes_daemon`,
`sysrc hermes_daemon_enable=YES`). Distinct from the old `clawdie`/`clawdie_hostd` rc.d
entries, so it won't collide during validation.
- **State home:** the app reads **`HERMES_HOME`** (`get_hermes_home()`). Do not set
`AUTOLYCUS_HOME` for hermes-osa.
- **Canonical first-validation state home: `HERMES_HOME=/home/clawdie/.hermes`** — _not_
`/home/clawdie/clawdie-ai` (an earlier target that is the old orphaned runtime; see below).
This value is authoritative; any agent planning a different path should align to it here first.
For source-proof validation, run the checkout-local setup path, not the PyPI/system installer:
```sh
cd /home/clawdie/ai/hermes-bsd
HERMES_HOME=/home/clawdie/.hermes ./setup-hermes.sh
HERMES_HOME=/home/clawdie/.hermes hermes setup # Telegram off, no secrets first
- **Memory**: 11 GiB RAM
- **Storage**: ZFS pool `zroot`, 98.5G ONLINE, 23.4G available
- **Jails**: `cms` and `worker` (Bastille jails); Docker not installed
- **Agents on host**:
- **hermes-osa** — Hermes Agent v0.16.0 (`hermes-bsd` clean-room MIT fork), FreeBSD local CLI runtime. **Status: LIVE — validated local chat.** Default provider: DeepSeek direct (`provider: deepseek`, `default: deepseek-chat`). OpenRouter available as fallback/manual lane. Telegram/gateway: OFF. Daemon/rc.d: deferred (Track A).
- **Mevy** — separate Hermes instance, existing Telegram bot (@Mevy). Coexists with hermes-osa; future migration may consolidate.
- **Codex**`codex-cli 0.117.0`, ISO builds and validation. Runs in a Bastille jail.
- **Claude Code** — installed (path: `/home/clawdie/.npm-global/bin/claude`), no dedicated role yet.
- **Provider stack** (hermes-osa):
```yaml
provider: deepseek # primary — direct credits, proven DEEPSEEK_OK
default: deepseek-chat
fallback: openrouter # available manually, not auto-fallback configured yet
```
`scripts/install-freebsd.sh` is useful later for package-style installs, but it currently
installs the published `hermes-agent` package rather than proving this checkout's patches.
- **Service home:** the rc.d template defaults `hermes_daemon_home` to `/var/db/hermes` under
the dedicated `hermes` service user. After local validation, either seed `/var/db/hermes`
deliberately or set `sysrc hermes_daemon_home=/home/clawdie/.hermes` deliberately; do not
let local and daemon state diverge by accident.
- **Do not use `/home/clawdie/clawdie-ai` as Hermes state.** Preserve/retire the old Clawdie
runtime path as a separate step after local Hermes validation.
- Install source is `hermes-bsd` main at `912e697d` (includes the Python 3.12 setup baseline).
**FreeBSD prereqs & first-run checklist** (verified blind spots before committing):
1. **Install prereqs via pkg first.** `setup-hermes.sh` only auto-provisions on
Linux/Termux/macOS; on FreeBSD it falls through to manual-instruction messages. Run:
`pkg install -y bash uv git curl`. Prefer pkg `uv` over the script's astral
`curl | sh` fallback (unreliable on FreeBSD).
2. **`bash` must be installed.** The script is bash. Its shebang is now portable
`#!/usr/bin/env bash` (hermes-bsd PR #3, `fix(freebsd): portable bash shebang`), so it
resolves FreeBSD's `/usr/local/bin/bash` — but bash itself must be present (step 1).
Until PR #3 is merged on the checkout, invoke as `bash setup-hermes.sh`.
3. **Run attended.** The script prompts (optional packages, setup wizard). Do **not** run
it unattended/agent-driven — it will hang on the `read` prompts.
4. **Core-only for first validation.** Decline optional extras initially. Several
(`matrix`→libolm, `voice`/`tts`→audio) are native builds that may not compile on
FreeBSD 15; the installer degrades rather than hard-failing, but a minimal install
gives a clean CLI proof. Add extras deliberately later.
5. **The rc.d service step is a separate re-setup, not a flip.** `setup-hermes.sh`
symlinks the `hermes` binary into `~/.local/bin` for the invoking user, but
`hermes_daemon` expects it at `/usr/local/bin/hermes` under a dedicated `hermes` user
with state at `/var/db/hermes`. Validation state at `/home/clawdie/.hermes` will **not**
migrate — re-run setup as the service user when promoting to rc.d.
---
- **Z.AI**: deferred (not configured for hermes-osa; available via OpenRouter if needed)
- **Telegram**: OFF (not configured)
- **Gateway/daemon**: deferred (Track A/B)
- **Launch command**:
```sh
tmux new -s hermes-osa
cd /home/clawdie/ai/hermes-bsd
export HERMES_HOME=/home/clawdie/.hermes
source venv/bin/activate # or: .venv/bin/activate
hermes chat
```
- **Layered soul**: commit `c9c88fd`, 10 skills, 7 curated memories
- **Future tracks (separate, none blocking)**:
- Track A: daemon/rc.d promotion (hermes_daemon service, dedicated user)
- Track B: Telegram/gateway integration
- Track C: Colibri cross-host routing (see CAPABILITY-ROUTING.md)
- Track D: old clawdie_glass cleanup
_See [`../AGENTS.md`](../AGENTS.md) for the canonical agent matrix and operating rules._