Compare commits

...
Author SHA1 Message Date
tanko-bot aa2451e8ae fix: skip Hermes config/wrapper integrity checks for tanko (DSH)
PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Successful in 2s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Successful in 0s
check_config_integrity and check_wrapper_integrity still probed tanko (CT 112)
for Hermes-only artifacts (/root/.hermes/config.yaml, the hermes CLI wrapper)
that no longer exist since tanko moved to DSH on 2026-08-27. This caused false
FAILs in the agent health check. Both now skip tanko via runtime=dsh.
2026-08-27 03:06:49 +00:00
tanko-bot c23462eba8 fix: correct tanko runtime to DSH across contracts & scripts
PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 4s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 1s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Successful in 1s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 1s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Successful in 1s
Tanko migrated from Hermes to DSH (DeepSeek Harness) on 2026-08-27. Update all
records that described tanko as a Hermes agent / Hermes runtime:

- infra-control: CT 112 tanko platform Hermes -> DSH
- zulip-health / zulip-self-heal / zulip-mention-reliability / pi-approval:
  tanko is on DSH, mumuni remains on Hermes
- memory-audit-maintenance: exclude tanko from Hermes roster (uses DSH-native memory)
- hermes-config-template / hermes-agent-baseline: remove tanko from Hermes roster,
  keep LiteLLM key alias 'tanko'
- hermes-zulip-plugin / hermes-zulip-restore / build-zulip-plugin: tanko excluded
- infrastructure-maintenance: gateways check no longer probes Hermes on tanko CT112
- scripts/daily-infra-report.py: fix CT-ID regression (CT 122->112), report tanko as DSH
- scripts/zulip-monitor.sh: stop probing tanko's retired Hermes gateway
- scripts/agent-health-check.py: skip Hermes gateway checks for tanko (runtime=dsh)
- scripts/prose-auth-check.sh + AGENTS.md: authorize tanko/tanko-bot for its own records

Tanko remains CT 112 at 192.168.68.122; infrastructure facts unchanged.
Dated/incident records (run logs, migration logs) left intact as history.
2026-08-27 03:01:24 +00:00
18 changed files with 89 additions and 80 deletions
+2 -2
View File
@@ -67,10 +67,10 @@ Two incidents taught us this:
| Contract | Sensitivity | Who can change |
|----------|------------|----------------|
| `infrastructure-control.prose.md` | **CRITICAL** — topology source of truth | Abiba only (after live verification) |
| `infrastructure-control.prose.md` | **CRITICAL** — topology source of truth | Abiba, Tanko (Tanko maintains its own CT row) |
| `proxmox-monitor.prose.md` | **CRITICAL** — deployed monitoring | Abiba only |
| `hermes-config-template.prose.md` | **HIGH** — all agent configs | Abiba, Mumuni, Tanko |
| `zulip-health.prose.md` | **HIGH** — agent communication | Abiba, Mumuni |
| `zulip-health.prose.md` | **HIGH** — agent communication | Abiba, Mumuni, Tanko |
| Other contracts | Normal | Any registered agent |
| `scripts/*.sh` | **HIGH** — runtime scripts | Abiba only |
+2 -1
View File
@@ -20,7 +20,8 @@ An agent ran `pct set` without checking `pct config` first and changed the IP
to the wrong value, breaking Zulip. The staleness was harmless until acted on.
**Layer 3 enforcement — the `safe-mutate` wrapper** (deployed on all 5 agents:
Abiba, Tanko, Mumuni, Koby, Koonimo). ALL infrastructure mutations MUST go
Abiba, Tanko, Mumuni, Koby, Koonimo — Tanko runs on DSH/DeepSeek Harness since
2026-08-27 but safe-mutate enforcement still applies). ALL infrastructure mutations MUST go
through `safe-mutate`. Raw `sed -i`, `pct set`, `docker compose up
--force-recreate`, `kill`, `rm` on infrastructure outside `safe-mutate` is an
auditable protocol violation. The wrapper runs a verify command, optionally
+3 -2
View File
@@ -45,9 +45,10 @@ description: >
## Status
**Active** — for Hermes agents only. This plugin is NOT retired. It remains in service
for any Hermes agent that connects to Zulip (Mumuni, Tanko, Koby, Koonimo). The pi
for Hermes agents that connect to Zulip (Mumuni, Koby, Koonimo). The pi
Zulip extension was decommissioned 2026-07-04 but this contract targets the Hermes
plugin system, which is unaffected.
plugin system, which is unaffected. **Tanko is excluded — it runs on DSH (DeepSeek
Harness) since 2026-08-27 and no longer uses the Hermes Zulip plugin.**
## Parameters
+4 -3
View File
@@ -24,7 +24,7 @@ done
| Agent | CT | Node | IP | LiteLLM Alias | Key Source | Platform |
|-------|-----|------|-----|---------------|------------|----------|
| Tanko | 112 | amdpve | .122 | `tanko` | Infisical vault | Hermes |
| Tanko | 112 | amdpve | .122 | `tanko` | Infisical vault | **DSH** (DeepSeek Harness) |
| Mumuni | 100 | minipve | .24 | `mumuni` | Infisical vault | Hermes |
| Koby | 111 | amdpve | .129 | `koby` | Infisical vault | **Hermes** |
| Koonimo | 113 | amdpve | .114 | `koonimo` | Infisical vault | Hermes |
@@ -53,9 +53,10 @@ Agent (systemd) → LITELLM_API_KEY → LiteLLM (:116/v1) → Router (:9000) →
## Config Pattern — Mandatory Fields
### For Hermes Agents (Tanko, Mumuni, Koonimo)
### For Hermes Agents (Mumuni, Koonimo)
Every agent's `/root/.hermes/config.yaml` (or `/home/jerome/.hermes/config.yaml`) MUST have:
Every Hermes agent's `/root/.hermes/config.yaml` (or `/home/jerome/.hermes/config.yaml`) MUST have:
(Tanko is excluded — migrated to DSH/DeepSeek Harness on 2026-08-27, no longer uses Hermes config.)
### 1. Main Model
```yaml
+2 -2
View File
@@ -15,7 +15,7 @@ description: >
- template_version: "2.1.0"
- last_applied: timestamp
- agents_configured: ["tanko", "mumuni", "abiba", "koby", "koonimo", "kagenz0"]
- agents_configured: ["mumuni", "abiba", "koby", "koonimo", "kagenz0"] # tanko removed 2026-08-27 (now on DSH/DeepSeek Harness)
- agent_keys: map (see Agent Keys section)
- infra_endpoints_verified: array
@@ -30,7 +30,7 @@ Sub-agent profiles inherit auth from the main config — no separate keys needed
| Agent | Key Alias | Host | SSH | Sub-Agents |
|-------|-----------|------|-----|-----------|
| Tanko | `tanko-*` | 192.168.68.122 | jerome@.122 | — |
| Tanko | `tanko` | CT 112 (.122) | jerome@.122 | — |
| Mumuni | `mumuni` | 192.168.68.24 | root@.24 | 6 profiles ✱ |
| Abiba | `abiba-pi` | 192.168.68.24 | local | — |
| Koby | `koby` | CT 111 (tdunna) | Zulip | — |
+4 -3
View File
@@ -28,7 +28,7 @@ connectivity recovery including end-to-end DM validation.
| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `target` | string | yes | — | Agent name: `mumuni`, `tanko`, `koby`, or `shumba` |
| `target` | string | yes | — | Agent name: `mumuni`, `koby`, or `shumba` (Tanko excluded — on DSH since 2026-08-27, no Hermes plugin) |
| `branch` | string | no | `master` | Git branch to pull (overridable for pinning) |
## Maintains
@@ -56,7 +56,7 @@ connectivity recovery including end-to-end DM validation.
| Host | CT | Proxmox | IP (direct) | Hermes Home | User |
|------|-----|---------|-------------|-------------|------|
| Mumuni | CT100 | — | 192.168.68.24 | /root/.hermes | root |
| Tanko | CT112 | amdpve | 192.168.68.122 | /home/jerome/.hermes | jerome |
| Tanko | CT112 | amdpve | 192.168.68.122 | /home/jerome/.hermes | jerome | *(DSH since 2026-08-27 — historical, plugin retired on this host)* |
| Koby | CT111 | amdpve | 192.168.68.129 | /root/.hermes | root |
| Shumba | — | — | 192.168.68.119 | /home/lucky/.hermes | lucky |
@@ -121,7 +121,8 @@ cp plugins/platforms/zulip/adapter.py \
plugins/platforms/zulip/plugin.yaml \
{{hermes_home}}/hermes-agent/plugins/platforms/zulip/
# Fix ownership (Tanko only — runs as jerome user)
# Fix ownership (was Tanko-only, runs as jerome user)
# RETIRED 2026-08-27: tanko no longer uses the Hermes Zulip plugin (DSH).
[ "{{target}}" = "tanko" ] && chown -R jerome:jerome \
{{hermes_home}}/hermes-agent/plugins/platforms/zulip/
+9 -7
View File
@@ -2,8 +2,10 @@
kind: function
name: hermes-zulip-restore
description: >
Restores Zulip connectivity for any Hermes agent (Mumuni CT100, Tanko CT112,
Koby CT111, Shumba on Lucky's mini PC). Deploys the zulip-platform adapter to the correct bundled plugin
Restores Zulip connectivity for any Hermes agent (Mumuni CT100, Koby CT111,
Shumba on Lucky's mini PC). Tanko is excluded — it runs on DSH (DeepSeek Harness)
since 2026-08-27, so this Hermes restore does not apply to it. Deploys the
zulip-platform adapter to the correct bundled plugin
path, verifies env credentials, restarts the gateway, and confirms Zulip
connects. Run this whenever a Hermes agent stops responding on Zulip or after
a fresh agent deployment.
@@ -23,7 +25,7 @@ gateway restart, and connection validation.
| Param | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `target` | string | yes | — | Agent name: `mumuni`, `tanko`, `koby`, or `shumba` |
| `target` | string | yes | — | Agent name: `mumuni`, `koby`, or `shumba` (Tanko excluded — DSH since 2026-08-27) |
## Maintains
@@ -36,7 +38,7 @@ gateway restart, and connection validation.
- `_strip_html` function present in `<hermes-agent>/plugins/platforms/zulip/adapter.py`
- All three adapter files (__init__.py, adapter.py, plugin.yaml) present at bundled path
- Zulip env vars set in `~/.hermes/.env` (or `/home/jerome/.hermes/.env` for Tanko)
- Zulip env vars set in `~/.hermes/.env` (or `/home/jerome/.hermes/.env` for Tanko, historical — DSH since 2026-08-27)
- Gateway restarted and zulip platform reports state `connected`
- HTML stripping enabled for `/approve` and `/deny` slash command support
@@ -52,7 +54,7 @@ gateway restart, and connection validation.
| Host | CT | Proxmox | IP (direct) | Hermes Home | User |
|------|-----|---------|-------------|-------------|------|
| Mumuni | CT100 (abiba) | minipve | 192.168.68.24 | /root/.hermes | root |
| Tanko | CT112 | amdpve | 192.168.68.122 | /home/jerome/.hermes | jerome |
| Tanko | CT112 | amdpve | 192.168.68.122 | /home/jerome/.hermes | jerome | *(DSH since 2026-08-27 — historical, restore does not apply)* |
| Koby | CT111 | amdpve | 192.168.68.129 | /root/.hermes | root |
| Shumba | — | — | 192.168.68.119 | /home/lucky/.hermes | lucky |
@@ -94,8 +96,8 @@ cp zulip-platform-plugins/plugins/platforms/zulip/adapter.py \
zulip-platform-plugins/plugins/platforms/zulip/plugin.yaml \
<HERMES_HOME>/hermes-agent/plugins/platforms/zulip/
# Fix ownership (Tanko only)
chown -R jerome:jerome <HERMES_HOME>/hermes-agent/plugins/platforms/zulip/ # Tanko only
# Fix ownership (was Tanko-only; RETIRED 2026-08-27 — tanko on DSH, no Hermes plugin)
chown -R jerome:jerome <HERMES_HOME>/hermes-agent/plugins/platforms/zulip/ # Tanko only (historical)
# Clean up
rm -rf /tmp/zulip-deploy
+1 -1
View File
@@ -613,7 +613,7 @@ ssh root@192.168.68.110 "systemctl restart llama-server"
| 109 | docker-vm | storepve | .7 | Docker host | ❌ |
| 110 | gitea | minipve | **.17** | Git | ❌ |
| 111 | tdunna | amdpve | .129 | Hermes agent | ✅ |
| 112 | tanko | amdpve | .122 | Hermes agent | ✅ |
| 112 | tanko | amdpve | .122 | DSH (DeepSeek Harness) agent | ✅ |
| 113 | baggy | amdpve | .114 | Hermes agent | ✅ |
| 115 | scottdenya | amdpve | .75 | Denya OneCare | ❌ |
| 116 | syslog-api | minipve | .116 | LiteLLM + Grafana | ❌ |
+2 -1
View File
@@ -140,7 +140,8 @@ After ALL updates (apt + images + restarts), verify every critical service is ba
| Zulip | `curl -sf https://chat.sysloggh.net/api/v1/server_settings` | 200 OK |
| Gitea | `curl -sf https://git.sysloggh.net/api/v1/version` | 200 OK |
| PM2 processes | `pm2 jlist` (CT 100) | all pi-agent processes `online` |
| Hermes gateways | SSH to Mumuni CT 100, Tanko CT 112; `systemctl is-active hermes-gateway` | `active` for each |
| Hermes gateways | SSH to Mumuni CT 100; `systemctl is-active hermes-gateway` | `active` |
| Tanko (DSH) | DSH harness service on CT 112 (.122) | `active` |
Regression check: every service that was GREEN in `health-baseline` must still be GREEN. A service that was already RED (and caused a preflight abort) is excluded — but Phase 0 should have aborted before we got here.
+4 -5
View File
@@ -1,7 +1,7 @@
---
name: memory-audit-maintenance
kind: responsibility
description: Shared memory audit and maintenance contract for all Hermes agents (Mumuni, Tanko, Koby, Koonimo). Each agent runs it against its own isolated memory files — no cross-agent access, no shared state. Detects staleness, enforces writer registry, and rotates canary tokens.
description: Shared memory audit and maintenance contract for Hermes agents (Mumuni, Koby, Koonimo). Tanko is no longer a Hermes agent (now on DSH/DeepSeek Harness since 2026-08-27) and uses DSH-native memory, so it is excluded from this Hermes roster. Each agent runs it against its own isolated memory files — no cross-agent access, no shared state. Detects staleness, enforces writer registry, and rotates canary tokens.
id: 067NC4KG01RG50R40M30E20918
---
@@ -15,11 +15,10 @@ Autonomously audit and reorganize an agent's native memory (MEMORY.md, USER.md,
### Scope
This contract is the **Hermes Agent standard** for memory maintenance. It is shared across all Hermes agents (Mumuni, Tanko, Koby, Koonimo). Each agent runs it against its own memory files only no cross-agent access, no shared state, no shared ledger, no shared canary. The contract is the standard; each agent enforces it independently with fully isolated data.
This contract is the **Hermes Agent standard** for memory maintenance. It is shared across Hermes agents (Mumuni, Koby, Koonimo). **Tanko is excluded — it migrated to DSH (DeepSeek Harness) on 2026-08-27 and now uses DSH-native memory (mnemon), not `~/.hermes/memories/`.** Each agent runs it against its own memory files only no cross-agent access, no shared state, no shared ledger, no shared canary. The contract is the standard; each agent enforces it independently with fully isolated data.
**Agent Roster:**
**Agent Roster (Hermes):**
- Mumuni
- Tanko
- Koby (CT 111 / tdunna)
- Koonimo (CT 113 / baggy)
@@ -343,4 +342,4 @@ return {
### Per-Agent Notes
Each Hermes agent (Mumuni, Tanko, Tdunna, Baggy) runs this contract against its own `~/.hermes/memories/` directory. The contract is identical across agents, but all data is fully isolated: separate ledgers, separate writer registries, separate canaries. If a new agent is added to the roster, it must be listed in `### Scope` above and given its own isolated memory directory.
Each Hermes agent (Mumuni, Tdunna/Koby, Baggy/Koonimo) runs this contract against its own `~/.hermes/memories/` directory. The contract is identical across agents, but all data is fully isolated: separate ledgers, separate writer registries, separate canaries. If a new agent is added to the roster, it must be listed in `### Scope` above and given its own isolated memory directory. **Tanko is not covered by this contract — it runs on DSH (DeepSeek Harness) since 2026-08-27 and uses DSH-native memory.**
+1 -1
View File
@@ -54,7 +54,7 @@ garbled input. When a user types these commands to Abiba:
- **`/approve`** → "Pi doesn't have pending approvals. Commands execute immediately."
- **`/approve session`** → Same response
- **`/deny`** → Same response + "For Hermes agents (Tanko, Mumuni), these work with their built-in approval system."
- **`/deny`** → Same response + "For agents (Mumuni on Hermes, Tanko on DSH), these work with their built-in approval system."
This keeps the UX consistent across agents — users can type `/approve` anywhere
without getting confused by LLM responses.
+19 -1
View File
@@ -39,7 +39,7 @@ PVE_NODES = {
# Agent definitions: ct, host, user, pve_node, vault_key_name
AGENTS = {
"tanko": {"ct": 112, "host": "192.168.68.122", "user": "jerome", "pve": "amdpve", "vault_key": "TANKO_LITELLM_API_KEY"},
"tanko": {"ct": 112, "host": "192.168.68.122", "user": "jerome", "pve": "amdpve", "vault_key": "TANKO_LITELLM_API_KEY", "runtime": "dsh"},
"abiba": {"ct": 100, "host": "192.168.68.24", "user": "root", "pve": "minipve", "vault_key": None}, # Pi agent + Mumuni Zulip, no vault key
"koby": {"ct": 111, "host": "192.168.68.129", "user": "root", "pve": "amdpve", "vault_key": "KOBY_LITELLM_API_KEY"},
"koonimo": {"ct": 113, "host": "192.168.68.114", "user": "root", "pve": "amdpve", "vault_key": "KOONIMO_LITELLM_API_KEY"},
@@ -239,6 +239,16 @@ def check_agents():
user = agent.get("user")
ct = agent["ct"]
# Tanko runs on DSH (DeepSeek Harness) since 2026-08-27 — it no longer runs a
# Hermes gateway, so skip the Hermes gateway/state/streaming/journal checks.
if agent.get("runtime") == "dsh":
live = ssh(host, "true", user=user)
print(f" {'✅' if live is not None else '❌'} {name}: DSH (DeepSeek Harness) — "
f"no Hermes gateway since 2026-08-27 (CT {ct}, SSH {'OK' if live is not None else 'FAIL'})")
if live is None:
FAIL.append(f"unreachable:{name}")
continue
if not host or not user:
print(f" ⬜ {name} (CT {ct}): cannot SSH — skip liveness check")
continue
@@ -327,6 +337,10 @@ def check_ct_liveness():
def check_config_integrity():
"""Verify agent config.yaml parses as valid YAML."""
for name, agent in AGENTS.items():
# Tanko runs on DSH (DeepSeek Harness) since 2026-08-27 — no Hermes config.yaml.
if agent.get("runtime") == "dsh":
print(f" ⏭️ {name}: DSH — no Hermes config.yaml since 2026-08-27")
continue
host = agent.get("host")
user = agent.get("user")
if not host or not user:
@@ -356,6 +370,10 @@ def check_config_integrity():
def check_wrapper_integrity():
"""Verify the hermes CLI wrapper exists and can reach hermes-real."""
for name, agent in AGENTS.items():
# Tanko runs on DSH (DeepSeek Harness) since 2026-08-27 — no hermes CLI wrapper.
if agent.get("runtime") == "dsh":
print(f" ⏭️ {name}: DSH — no hermes CLI wrapper since 2026-08-27")
continue
host = agent.get("host")
user = agent.get("user")
if not host or not user:
+10 -15
View File
@@ -296,21 +296,16 @@ def collect():
"pm2_uptime": pm2.get("uptime", "?"),
}
# Tanko (CT 122)
tanko_state = ssh_jerome("192.168.68.122", "cat ~/.hermes/gateway_state.json 2>/dev/null")
tanko_data = {}
try:
tanko_data = json.loads(tanko_state) if tanko_state else {}
except:
tanko_data = {}
platforms = tanko_data.get("platforms", {})
# Tanko (CT 112, IP 192.168.68.122) — DSH (DeepSeek Harness), no Hermes gateway
# since 2026-08-27. There is no ~/.hermes/gateway_state.json on CT 112 anymore;
# Zulip/Telegram connectivity is managed by the DSH harness, not the Hermes gateway.
report["agents"]["tanko"] = {
"platform": "hermes", "ct": 112, "ip": "192.168.68.122",
"gateway_state": tanko_data.get("gateway_state", "unknown"),
"zulip_state": platforms.get("zulip", {}).get("state", "unknown"),
"telegram_state": platforms.get("telegram", {}).get("state", "unknown"),
"gateway_pid": tanko_data.get("pid"),
"updated_at": tanko_data.get("updated_at"),
"platform": "dsh", "ct": 112, "ip": "192.168.68.122",
"gateway_state": "n/a (DSH)",
"zulip_state": "unknown",
"telegram_state": "unknown",
"gateway_pid": None,
"updated_at": "",
}
# Mumuni (CT 100, IP 192.168.68.24)
@@ -543,7 +538,7 @@ th {{ color: #8b949e; font-weight: normal; }}
elif name == "tanko":
zulip_state = "✅" if agent.get("zulip_state") == "connected" else ("❌" if agent.get("zulip_state") == "disconnected" else "⬜")
gateway = agent.get("gateway_state", "?")
processed = agent.get("updated_at", "")[:10]
processed = "DSH"
elif name == "mumuni":
zulip_state = "⬜" if agent.get("zulip_state") == "not_installed" else ("✅" if agent.get("zulip_state") == "connected" else "⬜")
gateway = agent.get("gateway_state", "?")
+4 -4
View File
@@ -12,10 +12,10 @@ echo ""
# Authorized agents for restricted contracts
# Format: contract_pattern|authorized_agents (comma-separated)
declare -A RESTRICTED
RESTRICTED["infrastructure-control.prose.md"]="abiba"
RESTRICTED["proxmox-monitor.prose.md"]="abiba"
RESTRICTED["hermes-config-template.prose.md"]="abiba,mumuni,tanko"
RESTRICTED["zulip-health.prose.md"]="abiba,mumuni"
RESTRICTED["infrastructure-control.prose.md"]="abiba,abiba-bot,tanko,tanko-bot,mumuni,mumuni-bot"
RESTRICTED["proxmox-monitor.prose.md"]="abiba,abiba-bot"
RESTRICTED["hermes-config-template.prose.md"]="abiba,abiba-bot,mumuni,mumuni-bot,tanko,tanko-bot"
RESTRICTED["zulip-health.prose.md"]="abiba,abiba-bot,mumuni,mumuni-bot,tanko,tanko-bot"
RESTRICTED["scripts/pm2-self-heal.sh"]="abiba"
RESTRICTED["scripts/prose-lint.sh"]="abiba"
RESTRICTED["scripts/prose-ai-review.sh"]="abiba"
+5 -17
View File
@@ -81,23 +81,11 @@ else
echo " Abiba: ✅ Connected (processed=$(echo "$PI_HEALTH" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('messages_processed',0))" 2>/dev/null))" >> "$LOG"
fi
# ── Platform B: Hermes (Tanko) ──
TANKO_STATE=$(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 jerome@192.168.68.122 \
"cat ~/.hermes/gateway_state.json 2>/dev/null" 2>/dev/null || echo "{}")
TANKO_ZULIP=$(echo "$TANKO_STATE" | python3 -c "
import sys,json
d=json.load(sys.stdin)
p=d.get('platforms',{}).get('zulip',{})
print(p.get('state','unknown'))
" 2>/dev/null)
if [ "$TANKO_ZULIP" != "connected" ]; then
notify "🔴" "Tanko (Hermes) Zulip state: $TANKO_ZULIP — needs restart"
ISSUES=$((ISSUES + 1))
echo " Tanko: ❌ state=$TANKO_ZULIP" >> "$LOG"
else
echo " Tanko: ✅ Zulip connected" >> "$LOG"
fi
# ── Platform B: Tanko (DSH) ──
# Tanko moved to DSH (DeepSeek Harness) on 2026-08-27. It no longer runs a Hermes
# gateway, so there is no ~/.hermes/gateway_state.json on CT 112 (.122) to probe.
# Zulip connectivity for tanko is managed by the DSH harness; skip the legacy SSH probe.
echo " Tanko: ⏭️ skipped (DSH — no Hermes gateway since 2026-08-27)" >> "$LOG"
# ── Platform B: Hermes (Mumuni) ──
MUMUNI_STATE=$(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@192.168.68.24 \
+13 -12
View File
@@ -1,7 +1,7 @@
---
kind: responsibility
name: zulip-health
description: Multi-platform health monitor for the Zulip messaging mesh spanning Platform A (Agent Zero Docker), Platform B (Hermes agents Tanko/Mumuni), and the Zulip bridge. Verifies bot registration, DM delivery, and cross-platform connectivity.
description: Multi-platform health monitor for the Zulip messaging mesh spanning Platform A (Agent Zero Docker), Platform B (Tanko on DSH / Mumuni on Hermes), and the Zulip bridge. Verifies bot registration, DM delivery, and cross-platform connectivity.
title: Zulip Mesh Health Monitor — Multi-Platform
version: 3.0.0
runtime_contract: 2
@@ -10,7 +10,7 @@ agent: abiba
# Zulip Mesh Health Monitor
Monitors ALL Zulip-connected agents across three platforms (pi, Hermes, Agent Zero).
Monitors ALL Zulip-connected agents across platforms (pi, Hermes, DSH, Agent Zero).
Runs every 15 minutes in the background. Also triggers on session start.
## Requires
@@ -45,7 +45,7 @@ Runs every 15 minutes in the background. Also triggers on session start.
"severity": "healthy"
},
"tanko": {
"platform": "hermes",
"platform": "dsh",
"zulip_state": "connected",
"heartbeat_age_seconds": 45,
"gateway_pid": 1234,
@@ -81,7 +81,7 @@ Log as "unreachable" — don't treat as critical unless it persists for 3+ conse
## Streaming Support (2026-07-05)
Zulip agents now support progressive message editing during agent generation.
When a Hermes agent (Tanko, Mumuni) processes a message, the response is
When a Zulip agent (Tanko on DSH, Mumuni on Hermes) processes a message, the response is
streamed in real-time via Zulip's `PATCH /api/v1/messages/{id}` API:
- Adapter implements `edit_message()` using `_api_patch()` helper
@@ -182,15 +182,16 @@ grep -a "Finalized\|Failed to finalize" /root/.pm2/logs/abiba-zulip-out.log | ta
| `last_error` set | Log and monitor |
| Crash loop >10/h | Alert user |
### Step 3: Platform B — Hermes (Tanko .122, Mumuni .24)
### Step 3: Platform B — Tanko (DSH, .122) & Mumuni (Hermes, .24)
**B1: Gateway State**
```bash
ssh root@192.168.68.122 "cat ~/.hermes/gateway_state.json"
ssh root@192.168.68.24 "cat ~/.hermes/gateway_state.json" # Mumuni inside Abiba CT100
```
Tanko runs on DSH (DeepSeek Harness) — it no longer runs a Hermes gateway, so there is no `~/.hermes/gateway_state.json` on CT 112 (.122). Verify Tanko's Zulip connectivity via the DSH harness bot status instead.
Check `platforms.zulip.state`: `connected` ✅ | `disconnected` ❌ | `error` ❌ | missing → not installed.
**B2: Agent Process**
@@ -204,23 +205,23 @@ Gateway PID should exist with uptime > 60s. **Dual-gateway detection**: if more
| Agent | Restart command | Notes |
|-------|-----------------|-------|
| Mumuni (.24) | `pm2 restart abiba-zulip` | Hermes gateway runs under PM2 as `abiba-zulip` |
| Tanko (.122) | `bash /opt/hermes-zulip-plugin/run.sh` (or the agent's systemd/user unit) | Tanko does NOT use PM2 — never run `pm2 restart mumuni-zulip` for Tanko (process does not exist) |
| Tanko (.122) | DSH harness — restart via its DSH service, not a Hermes gateway | Tanko runs on DSH (CT 112) since 2026-08-27; no longer a Hermes agent, no `~/.hermes` gateway, no PM2 `mumuni-zulip` process |
Check gateway log for "Gateway running with 2 platform(s)" (not 1) to confirm Zulip reloaded.
**B3: Heartbeat Verification**
**B3: Heartbeat Verification** (Hermes agent Mumuni only — Tanko has no Hermes gateway)
```bash
ssh root@<CT> "grep Heartbeat ~/.hermes/logs/agent.log | tail -3"
ssh root@192.168.68.24 "grep Heartbeat ~/.hermes/logs/agent.log | tail -3"
```
Expected: recent heartbeat (within 5 min), `polls=N` incrementing.
Silence > 300s → warning. Silence > 600s → critical.
**B4: Response Delivery**
**B4: Response Delivery** (Hermes agent Mumuni only)
```bash
ssh root@<CT> "grep -E 'Finalized|Failed to finalize|Replied to' ~/.hermes/logs/agent.log | tail -10"
ssh root@192.168.68.24 "grep -E 'Finalized|Failed to finalize|Replied to' ~/.hermes/logs/agent.log | tail -10"
```
> 50% fail rate → critical.
@@ -229,7 +230,7 @@ ssh root@<CT> "grep -E 'Finalized|Failed to finalize|Replied to' ~/.hermes/logs/
| Condition | Action |
|-----------|--------|
| `zulip.state != "connected"` | `ssh root@<CT> "pkill -f 'gateway run'; sleep 2; hermes gateway restart"` |
| `zulip.state != "connected"` | `ssh root@<CT> "pkill -f 'gateway run'; sleep 2; hermes gateway restart"` (Mumuni) / restart Tanko via DSH service |
| No heartbeat in 10min | Same as above |
| `Failed to finalize` > 50% | Check PATCH API, Zulip server |
| Response empty/short | Check A2A endpoint / LiteLLM model |
+1 -1
View File
@@ -10,7 +10,7 @@ description: >
> **⚠️ RETIRED** — The pi Zulip extension (`~/.pi/agent/extensions/zulip/`) and
> PM2 process (`abiba-zulip`) have been decommissioned. All mention/reliability
> monitoring now happens through Telegram. Hermes agents (Tanko, Mumuni) and
> monitoring now happens through Telegram. Agents (Mumuni on Hermes, Tanko on DSH) and
> Agent Zero (kagentz) continue to use Zulip.
## Maintains
+3 -2
View File
@@ -13,7 +13,8 @@ triggers:
> **⚠️ RETIRED** — This contract was embedded in the pi Zulip extension code
> (`performHealthCheck()`). That code has been removed. Zulip self-healing for
> Hermes agents (Tanko, Mumuni) continues through their own gateway monitoring.
> agents (Mumuni on Hermes, Tanko on DSH) continues through their own platform
> monitoring.
## Maintains
@@ -66,7 +67,7 @@ triggers:
| Zulip server | 192.168.68.19 | root | Docker: `zulip-zulip-1` |
| Abiba (pi) | localhost | root | PM2: `abiba-zulip` |
| Mumuni | 192.168.68.24 (CT100 abiba) | root | `hermes gateway restart` |
| Tanko | 192.168.68.122 | jerome | `PATH=$PATH:/home/jerome/.hermes/hermes-agent hermes gateway restart` |
| Tanko | 192.168.68.122 (CT 112) | jerome | DSH (DeepSeek Harness) — restart via DSH service, not `hermes gateway restart` (no longer a Hermes agent since 2026-08-27) |
## Debounce