用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/lukemcqueen/hermes-cortex --skill upstream-fix-watchdog命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | upstream-fix-watchdog |
| version | 1.0.0 |
| description | Watch upstream for a bug fix to land; silent until fixed. |
| tags | ["cron","watchdog","upstream","fix","fleet","pin","monitoring"] |
| related_skills | ["watchers","fleet-commands","cron-format-standard","hermes-cortex-maintenance"] |
When an upstream project (e.g. hermes-agent by NousResearch) ships a bug that forces you to pin a version and pause fleet update crons, you need a cheap watchdog that tells you the moment the fix lands — without nagging every day while it's still broken.
Pattern proven 2026-08-25→28: _stdio_children_dead() inversion in
hermes-agent's tools/mcp_tool.py broke every stdio MCP call on all hosts.
Fleet pinned, paused agent-hermes-update, and a daily cron
(check-hermes-upstream-fix) watched upstream until the fix appeared, then
alerted with the exact fleet-action steps. Generalize this for every future
upstream pin.
no_agent=true
cron watchdog pattern: empty stdout = silent tick, no delivery, no tokens.MARKER = ~/.hermes/state/<incident>-notified; write it after first
notify; skip future notifies if it exists.CHECK FAILED: ... to stderr and exit 1, so a broken check can never go
silent. A silent watchdog that stopped polling is worse than no watchdog.return True # alive), PLUS positive proof of the fix (e.g. the
corrected return False path present, or the function deleted entirely).#!/usr/bin/env python3
"""Watchdog: notify when upstream <repo> fixes <bug>. Silent until then."""
import os, re, sys, urllib.request
DEFAULT_URL = "https://raw.githubusercontent.com/<org>/<repo>/main/<path>"
MARKER = os.path.expanduser("~/.hermes/state/<incident>-notified")
BUGGY_MARKER = "<exact buggy line>"
NOTIFY_TEXT = """🟢 UPSTREAM FIX DETECTED: <bug> is fixed on origin/main.
Fleet action:
1. <unpin/update steps>
2. <resume paused crons: hermes cron resume <job_id>>
3. <verify: grep -c '<buggy-symbol>' <file> on each host>
4. <remove the pin once all hosts verify clean>"""
def fetch(url: str) -> str:
req = urllib.request.Request(url, headers={"User-Agent": "hermes-cortex-fix-watchdog"})
with urllib.request.urlopen(req, timeout=30) as resp:
return resp.read().decode("utf-8", errors="replace")
def is_fixed(src: str) -> bool:
# 1. Function/symbol absent entirely -> bug gone
# 2. Extract the function body; if BUGGY_MARKER in body -> not fixed
# 3. Else require positive proof (correct return path present)
raise NotImplementedError # per-incident logic
def main(argv):
url = argv[0] if argv and argv[0].startswith("http") else DEFAULT_URL
dry = "--dry-run" argv
:
src = fetch(url)
Exception exc:
(, file=sys.stderr)
is_fixed(src):
dry os.path.exists(MARKER):
(NOTIFY_TEXT)
dry:
os.makedirs(os.path.dirname(MARKER), exist_ok=)
(MARKER, ).write()
__name__ == :
sys.exit(main(sys.argv[:]))
Full working example: ~/.hermes/scripts/check-hermes-upstream-fix.py
(2026-08-25 incident — real is_fixed() regex, marker handling, notify text).
hermes cron create --name <name> --schedule '0 9 * * *' \
--script <name>.py --no-agent --deliver origin
no_agent=true — script stdout IS the delivery; empty = silent tickpython3 <script>.py --dry-run (must print the
notify text but NOT write the marker), then python3 <script>.py once with
the marker deleted to see a real tickcronjob(action='pause')) — the job is done; don't let it tick
pointlessly forever. Keep the script for the next incident.git fetch origin && git log --oneline -1 origin/main or curl the raw file and eyeball the diff.
The watchdog is a tripwire, not proof.orch-bus-fleet-dispatch.py --execute (sync stale local
agent-registry from the bus host first — see fleet-commands skill), or
hc send <agent> UPDATE_REQUEST ....
Include ALL agents; the dispatch tool skips dev-agents — send those
manually. When the registry's health_url is a stale placeholder
(e.g. your-domain.com), hc send liveness refuses — use --force
(the bus is the authoritative proof; verify against bus.archives).
Verify UPDATE_RESULT git_sha_after on the AUTHORITATIVE bus
(never the local mirror — it lags).hermes cron resume <job_id> for each
agent-hermes-update-class job paused during the incident.grep -c '<buggy-symbol>' <file> = 0, or confirm
the fixed logic.During hermes update the updater autostashes local changes and asks whether
to restore. Decide by content, not by default:
git stash show --stat stash@{0} — see what's inside (working tree is
clean when the stash exists, so status won't help)git show HEAD:<file> | grep -c <symbol> — if
upstream now HAS the functionality (e.g. a lean mode), the local patch
may be partially redundant; restore anyway (semantics may differ)git rev-list --count <stash-base>..HEAD -- <files> — low
count = safe; git stash show -p stash@{0} inspects WITHOUT mutatinggit stash apply MUTATES the working tree — it is NOT a dry run.
To inspect: git stash show -p stash@{0}. Only apply/pop when you
intend to restore. (Learned 2026-08-28: an "inspection" apply created a
real conflict mid-update; restored via
git restore --source=HEAD --staged --worktree <files> + git rm --cached
for untracked stash files.)_stdio_children_dead() inversion was fixed upstream, but the same
feature's _watch_stdio_children probe still had its own coroutine-leak
bug: inspect.isawaitable(_watch_children()) INVOKES the async function,
creating a never-awaited coroutine per MCP call (RuntimeWarning: coroutine 'MCPServerTask._watch_stdio_children' was never awaited). On Titus this
made loop-governance MCP calls fail silently — begin_change never
completed, so the enforcer blocked ALL write tools "even for inspection."
Before trusting an upstream fix, grep the whole feature for the same
flaw class — a fix to one function often leaves siblings broken. See
references/mcp-tool-watch-probe-case.md for the full reproduction.<name> for a new
incident and the old marker suppresses the new notify. Name it after the
incident (upstream-hermes-fix-notified), not generically.raw.githubusercontent.com is the cheap fetch
(single file, no auth, no clone). Only clone when you need the whole tree.return True/False alone — the exact inverted line is
the anchor; the fix's positive return path is the proof. Stubs that remove
all returns are NOT fixes.origin — one alert to the operator's DM is the
point; don't fan out to every agent.set -euo pipefail assignment trap — if the script is bash and reads
an optional file, terminate the fallback chain with || true and gate on
[[ -n $VAR ]] (see shell-scripting skill).watchers skill — feed polling with watermark dedup (RSS/JSON/GitHub
issues); use for "new items" streams. This skill is for "did ONE specific
bug get fixed" — marker dedup instead of watermark, silent-until-fixed
semantics instead of new-item emission.fleet-commands — UPDATE_REQUEST dispatch + authoritative-bus verification.