Hermes Update Triage
Answer "I'm N commits behind upstream — is it worth getting?" This is NOT a
released-version changelog (that's hermes-version-summary, which reads
RELEASE_v*.md). Here there are no release notes yet — you triage raw commits and
filter through the user's actual stack.
Workflow
1. Establish the gap
hermes --version # installed ver + "N commits behind"
cd ~/.hermes/hermes-agent
git fetch origin 2>&1 | tail -3 # MUST fetch first or range is stale
git status -sb | head -3 # dirty tree? warn BEFORE offering update
# Snapshot the list ONCE, then analyze the file — never re-run git log per slice
# (rtk-rewrite intercepts each git invocation separately; see Pitfalls)
git log --format='%h|%s' HEAD..origin/main > /tmp/hermes_triage.txt
git rev-list --count HEAD..origin/main # ground-truth N; must equal wc -l of the file
git diff --stat HEAD..origin/main | tail -1 # scale: files / insertions
2. Strip noise, isolate signal
# Drop test/ci/docs/fmt-only — rarely affect runtime
git log --oneline HEAD..origin/main --format="%h %s" | grep -viE "^.{8} (test|fmt|ci|docs)\("
# Features only
git log --oneline HEAD..origin/main --format="%h %s" | grep -E "feat\("
3. Bucket by relevance to THIS user
- 🟢 Worth getting — hits their surfaces: cron fleet (model pins, drift
guard, failure recording — they run ~14+ crons and have been burned by drift),
memory/mnemosyne/LCM pipeline (flush-before-teardown, compression prompt
preservation), gateway fleet + Discord, MCP discovery/locking, session/profile
isolation, model catalog + pricing changes (they run a pricing watchdog cron),
provider-aware tooling, web_search/DDGS stability, secrets scrubbing,
macOS TUI/CLI fixes, voice pipeline.
- 🟡 Nice-to-have — desktop/Electron features (only if they use the app),
wake-word/voice-chat UX, new platform adapters (Photon, Buzz) unless asked.
- ⚪ Skip — platform adapters they don't run, CI pipeline, test coverage,
docs cleanup, provider-scoped fixes for providers they don't use.
4. Verdict + offer
One line: update or not, and why. Then offer to run hermes update.
Variant: "will the update fix THIS bug?"
When the user is debugging a specific failure and suspects an update will cure
it, triage the gap AGAINST THE FAILING FILES before promising anything:
cd ~/.hermes/hermes-agent && git fetch origin
# Does the gap touch the code path that broke?
git diff --stat HEAD origin/main -- agent/<module>.py
# Empty diff = the update will NOT fix it (hygiene only)
git log --oneline HEAD..origin/main --grep="<feature>" -i # named fixes in gap?
git merge-base --is-ancestor <sha> HEAD && echo LOCAL || echo MISSING # is a known fix already local?
Observed 2026-07-31: 72 commits behind, but the gap touched zero MOA files
(agent/moa_loop.py, agent/chat_completion_helpers.py, agent/conversation_loop.py)
— so the update would not have fixed the MOA crash the user was seeing, even
though the SimpleNamespace-tolerance fix that IS upstream was already local.
Verdict was: update for hygiene, don't promise it fixes MOA. Same check applies
to any feature: gap empty on the failing module → the honest answer is "update
won't cure this; here's the real workaround."
Variant: "any new SKILLS since vX?"
Bundled skills live in the hermes-agent repo under TWO roots: skills/ and
optional-skills/ (~181 SKILL.md files as of 2026-07). Triage them like commits:
cd ~/.hermes/hermes-agent && git fetch origin -q
# Upstream skill delta since local HEAD:
git diff --name-status HEAD origin/main -- skills optional-skills
# Locally-added/modified profile skills since a date:
find ~/.hermes/profiles/<profile>/skills -maxdepth 2 -name SKILL.md -newermt 'YYYY-MM-DD'
~/.hermes/profiles/<profile>/skills/.bundled_manifest records which bundled
skills are materialized locally (name:content-hash per line) — diff it after an
update to see what the bundle changed.
- Empty upstream diff = the honest answer is "no new skills, the churn is core
code" — then bucket the commit log per §3 and say that. Don't invent skill news.
Pitfalls
- rtk-rewrite silently truncates
git log to ~50 lines. With the rtk-rewrite plugin active, bare git log through the terminal tool gets intercepted and capped — you see 50 commits while git rev-list --count reports the true N (observed 2026-07-28: 50 shown vs 391 real; again 2026-07-29: consecutive calls ALTERNATED between 50 and 610 on the same range, including inside execute_code's terminal()). The user's "N commits behind" number then disagrees with your triage. Fix: snapshot once — git log --format='%h|%s' HEAD..origin/main > /tmp/file — verify wc -l equals git rev-list --count, then grep/python the FILE for all further slicing. If the file itself comes out short, rerun with /usr/bin/git log (absolute path bypasses the rewrite). Same failure class as the rtk grep interception in hermes-maintenance.
- Dirty tree before update. If
git status -sb shows local modifications (observed: agent/model_metadata.py dirty), flag it in the verdict BEFORE offering hermes update — user must stash/commit first.
- Fetch first.
HEAD..origin/main is empty/stale without git fetch origin.
- Don't dump all N commits. The user wants the filtered few that matter to
their stack. Bucket hard; lead with 🟢.
- Installed version ≠ git HEAD.
hermes --version shows the release tag;
local HEAD may already carry post-release commits. HEAD..origin/main is the
true missing delta.
- Provider-scoped fixes can be skip-tier. A
fix(...) scoped to a provider
they don't use (Codex OAuth) is ⚪ even though it's a fix.
- After they say yes, hand off to
hermes-maintenance for the post-update
health check (MCP binaries, mnemosyne/rtk venv wipes, profile wrapper).
- Plugins have their own upstream remotes. Git-managed plugins (e.g.
hermes-lcm, web-search-plus) may have origin (user fork) AND upstream
(canonical repo) remotes. A plugin can be up-to-date with origin but behind
upstream. After hermes update, also check git plugins against their
upstream remotes — see hermes-maintenance §6b for the multi-remote audit
script. Non-git plugins (eikon, katana, kanban-api, session-api) are bundled
with Hermes and auto-updated; only git-managed plugins need manual pulling.
Overlap note (for curator)
Adjacent to hermes-version-summary (released-version reporting). Distinct
question + workflow; kept separate. If consolidating, this is the "unreleased
triage" half, version-summary is the "released report" half.
1---2name: hermes-update-triage3description: Decide whether to run `hermes update` by triaging the unreleased upstream commits the local install is behind. Buckets raw commits by relevance to THIS user's fleet (not a generic changelog) and returns a go/no-go. Use when the user asks "what's new in the repo vs what I have", "are the new commits worth getting", "should I update hermes", or `hermes --version` reports "N commits behind".4---5
6# Hermes Update Triage
7
8Answer **"I'm N commits behind upstream — is it worth getting?"** This is NOT a
9released-version changelog (that's `hermes-version-summary`, which reads
10RELEASE_v*.md). Here there are no release notes yet — you triage raw commits and
11filter through the user's actual stack.
12
13## Workflow
14
15### 1. Establish the gap
16```bash
17hermes --version # installed ver + "N commits behind"
18cd ~/.hermes/hermes-agent
19git fetch origin 2>&1 | tail -3 # MUST fetch first or range is stale
20git status -sb | head -3 # dirty tree? warn BEFORE offering update
21# Snapshot the list ONCE, then analyze the file — never re-run git log per slice
22# (rtk-rewrite intercepts each git invocation separately; see Pitfalls)
23git log --format='%h|%s' HEAD..origin/main > /tmp/hermes_triage.txt
24git rev-list --count HEAD..origin/main # ground-truth N; must equal wc -l of the file
25git diff --stat HEAD..origin/main | tail -1 # scale: files / insertions
26```
27
28### 2. Strip noise, isolate signal
29```bash
30# Drop test/ci/docs/fmt-only — rarely affect runtime
31git log --oneline HEAD..origin/main --format="%h %s" | grep -viE "^.{8} (test|fmt|ci|docs)\("
32# Features only
33git log --oneline HEAD..origin/main --format="%h %s" | grep -E "feat\("
34```
35
36### 3. Bucket by relevance to THIS user
37- 🟢 **Worth getting** — hits their surfaces: cron fleet (model pins, drift
38 guard, failure recording — they run ~14+ crons and have been burned by drift),
39 memory/mnemosyne/LCM pipeline (flush-before-teardown, compression prompt
40 preservation), gateway fleet + Discord, MCP discovery/locking, session/profile
41 isolation, model catalog + pricing changes (they run a pricing watchdog cron),
42 provider-aware tooling, web_search/DDGS stability, secrets scrubbing,
43 macOS TUI/CLI fixes, voice pipeline.
44- 🟡 **Nice-to-have** — desktop/Electron features (only if they use the app),
45 wake-word/voice-chat UX, new platform adapters (Photon, Buzz) unless asked.
46- ⚪ **Skip** — platform adapters they don't run, CI pipeline, test coverage,
47 docs cleanup, provider-scoped fixes for providers they don't use.
48
49### 4. Verdict + offer
50One line: update or not, and why. Then offer to run `hermes update`.
51
52## Variant: "will the update fix THIS bug?"
53
54When the user is debugging a specific failure and suspects an update will cure
55it, triage the gap AGAINST THE FAILING FILES before promising anything:
56
57```bash
58cd ~/.hermes/hermes-agent && git fetch origin
59# Does the gap touch the code path that broke?
60git diff --stat HEAD origin/main -- agent/<module>.py
61# Empty diff = the update will NOT fix it (hygiene only)
62git log --oneline HEAD..origin/main --grep="<feature>" -i # named fixes in gap?
63git merge-base --is-ancestor <sha> HEAD && echo LOCAL || echo MISSING # is a known fix already local?
64```
65
66Observed 2026-07-31: 72 commits behind, but the gap touched zero MOA files
67(`agent/moa_loop.py`, `agent/chat_completion_helpers.py`, `agent/conversation_loop.py`)
68— so the update would not have fixed the MOA crash the user was seeing, even
69though the SimpleNamespace-tolerance fix that IS upstream was already local.
70Verdict was: update for hygiene, don't promise it fixes MOA. Same check applies
71to any feature: gap empty on the failing module → the honest answer is "update
72won't cure this; here's the real workaround."
73
74## Variant: "any new SKILLS since vX?"
75
76Bundled skills live in the hermes-agent repo under TWO roots: `skills/` and
77`optional-skills/` (~181 SKILL.md files as of 2026-07). Triage them like commits:
78
79```bash
80cd ~/.hermes/hermes-agent && git fetch origin -q
81# Upstream skill delta since local HEAD:
82git diff --name-status HEAD origin/main -- skills optional-skills
83# Locally-added/modified profile skills since a date:
84find ~/.hermes/profiles/<profile>/skills -maxdepth 2 -name SKILL.md -newermt 'YYYY-MM-DD'
85```
86
87- `~/.hermes/profiles/<profile>/skills/.bundled_manifest` records which bundled
88 skills are materialized locally (name:content-hash per line) — diff it after an
89 update to see what the bundle changed.
90- Empty upstream diff = the honest answer is "no new skills, the churn is core
91 code" — then bucket the commit log per §3 and say that. Don't invent skill news.
92
93## Pitfalls
94- **rtk-rewrite silently truncates `git log` to ~50 lines.** With the rtk-rewrite plugin active, bare `git log` through the terminal tool gets intercepted and capped — you see 50 commits while `git rev-list --count` reports the true N (observed 2026-07-28: 50 shown vs 391 real; again 2026-07-29: consecutive calls ALTERNATED between 50 and 610 on the same range, including inside `execute_code`'s `terminal()`). The user's "N commits behind" number then disagrees with your triage. Fix: snapshot once — `git log --format='%h|%s' HEAD..origin/main > /tmp/file` — verify `wc -l` equals `git rev-list --count`, then grep/python the FILE for all further slicing. If the file itself comes out short, rerun with `/usr/bin/git log` (absolute path bypasses the rewrite). Same failure class as the rtk `grep` interception in hermes-maintenance.
95- **Dirty tree before update.** If `git status -sb` shows local modifications (observed: `agent/model_metadata.py` dirty), flag it in the verdict BEFORE offering `hermes update` — user must stash/commit first.
96- **Fetch first.** `HEAD..origin/main` is empty/stale without `git fetch origin`.
97- **Don't dump all N commits.** The user wants the filtered few that matter to
98 *their* stack. Bucket hard; lead with 🟢.
99- **Installed version ≠ git HEAD.** `hermes --version` shows the release tag;
100 local HEAD may already carry post-release commits. `HEAD..origin/main` is the
101 true missing delta.
102- **Provider-scoped fixes can be skip-tier.** A `fix(...)` scoped to a provider
103 they don't use (Codex OAuth) is ⚪ even though it's a fix.
104- **After they say yes**, hand off to `hermes-maintenance` for the post-update
105 health check (MCP binaries, mnemosyne/rtk venv wipes, profile wrapper).
106- **Plugins have their own upstream remotes.** Git-managed plugins (e.g.
107 `hermes-lcm`, `web-search-plus`) may have `origin` (user fork) AND `upstream`
108 (canonical repo) remotes. A plugin can be up-to-date with `origin` but behind
109 `upstream`. After `hermes update`, also check git plugins against their
110 upstream remotes — see `hermes-maintenance` §6b for the multi-remote audit
111 script. Non-git plugins (eikon, katana, kanban-api, session-api) are bundled
112 with Hermes and auto-updated; only git-managed plugins need manual pulling.
113
114## Overlap note (for curator)
115Adjacent to `hermes-version-summary` (released-version reporting). Distinct
116question + workflow; kept separate. If consolidating, this is the "unreleased
117triage" half, version-summary is the "released report" half.