Skip to content

feat: add Hermes token usage source - #88

Merged
nicosuave merged 9 commits into
nicosuave:mainfrom
MaterAnime:feat/hermes-usage-upstream
Aug 14, 2026
Merged

feat: add Hermes token usage source#88
nicosuave merged 9 commits into
nicosuave:mainfrom
MaterAnime:feat/hermes-usage-upstream

Conversation

@MaterAnime

Copy link
Copy Markdown
Contributor

Summary

Adds Hermes Agent as a first-class Memex token-usage source.

  • discovers the canonical Hermes root state.db and immediate profile databases
  • reads SQLite in read-only, WAL-compatible mode
  • supports legacy sessions aggregates and current session_model_usage model/task rows
  • reconciles model rows against session totals without double counting
  • preserves Hermes' disjoint input/cache-read/cache-write/output accounting
  • adds CLI, TUI, web, audit, source-filter, cache, and documentation integration

Privacy and safety

The adapter reads usage counters and limited attribution metadata only. It does not query message text, system prompts, tool/reasoning content, credentials, auth, memory, skills, plugins, or cron data. JSON/JSONL transcripts are not treated as Hermes usage sources.

SQLite databases are opened read-only. WAL metadata participates in cache freshness; SHM coordination metadata does not. Parser version 4 invalidates older Hermes projections, and malformed legacy dependency cache entries fail closed by reparsing.

Accounting model

Hermes stores disjoint buckets:

total = input_tokens + cache_read_tokens + cache_write_tokens + output_tokens

For databases with session_model_usage, per-model/task rows are emitted first and capped conservatively against the session aggregate. Any positive residual is retained once at session level. Legacy databases use the session aggregate directly.

Verification

  • cargo fmt --check
  • cargo clippy -- -D warnings
  • 11 focused Hermes source tests
  • focused parser-version, WAL freshness, and fail-closed cache tests
  • full cargo test: 301 passed, 0 failed, 2 ignored
  • integration tests: 3 passed
  • exact aggregate comparison against immutable snapshots of four local Hermes databases: exact bucket and total match, zero warnings

The upstream branch intentionally excludes the local installer/rollback scripts and Herdr cockpit metadata used during development.

@MaterAnime

Copy link
Copy Markdown
Contributor Author

Follow-up verification completed on commit 8b943b4:

  • cargo fmt --check
  • cargo clippy -- -D warnings
  • cargo clippy --all-targets -- -D warnings
  • cargo test hermes ✅ (15 passed)
  • cargo test ✅ (304 passed, 2 ignored)

The follow-up only resolves test-target Clippy warnings; HERDR_WORKSPACE.md remains local and is not part of the PR.

@MaterAnime

Copy link
Copy Markdown
Contributor Author

@nicosuave This is ready for maintainer review. The implementation and follow-up all-target Clippy cleanup are pushed, and the full local verification results are recorded above.

@nicosuave

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b943b45f0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sources/hermes.rs Outdated
Comment thread src/sources/hermes.rs
Comment thread src/sources/hermes.rs
Comment thread src/sources/hermes.rs Outdated
@MaterAnime

Copy link
Copy Markdown
Contributor Author

Addressed all four Codex review findings in commit 5c33ec6.

Verification after the final repair:

  • cargo fmt --check
  • cargo clippy -- -D warnings
  • cargo clippy --all-targets -- -D warnings
  • focused Hermes parser tests ✅ (14 passed)
  • cargo test hermes ✅ (18 passed)
  • cargo test ✅ (307 passed, 2 ignored)
  • independent adversarial re-review: no blockers
  • additional reviewer run: all-target/all-feature suite and Clippy passed

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c33ec61d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sources/hermes.rs Outdated
Comment thread src/sources/hermes.rs Outdated
Comment thread src/usage.rs Outdated
@MaterAnime

Copy link
Copy Markdown
Contributor Author

Addressed the three latest Codex findings in commit 36981df.

Additional hardening included:

  • authoritative cost reconciliation across missing/zero/below/equal/above model costs
  • capped-row handling with and without authoritative session cost
  • zero-token session/model-row coverage
  • positive token residual preservation independent of cost reconciliation
  • malformed dependency bytes and SQLite types quarantined per cache row

Final local verification:

  • cargo fmt --check
  • cargo clippy -- -D warnings
  • cargo clippy --all-targets --all-features -- -D warnings
  • Hermes tests: 23 passed ✅
  • all-target/all-feature suite: 320 passed, 2 ignored ✅
  • independent static review: no blockers ✅

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36981df8f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sources/hermes.rs
Comment thread src/sources/hermes.rs
Comment thread src/sources/hermes.rs Outdated
Comment thread src/sources/hermes.rs
@nicosuave

Copy link
Copy Markdown
Owner

Thanks for this @MaterAnime

…eat/hermes-usage-upstream

# Conflicts:
#	src/sources/hermes.rs
#	src/usage.rs
@MaterAnime

Copy link
Copy Markdown
Contributor Author

Merged Nico’s concurrent fixes with the independently verified aggregate-accounting repair on head 84fa162. No force push or history rewrite was used.

The merged result addresses all four latest findings and includes:

  • authoritative-cost suppression for Auto without synthetic public row costs
  • no-authority Auto fallback preservation
  • Hermes aggregate exclusion from cache-waste chains
  • canonical/immediate-profile discovery with existing-file checks
  • one SQLite snapshot for session/model reads
  • internal-only reconciliation/cache flags with cache round-trip coverage
  • Hermes usage parser version 7, invalidating versions through the concurrent version 6 repair

Merged-tree verification:

  • cargo fmt --check
  • cargo clippy -- -D warnings
  • cargo clippy --all-targets --all-features -- -D warnings
  • Hermes tests: 31 passed ✅
  • all-target/all-feature suite: 330 passed, 2 ignored ✅
  • all review threads resolved ✅

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84fa162d1d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sources/hermes.rs Outdated
@MaterAnime

Copy link
Copy Markdown
Contributor Author

Fixed the non-UTF-8 WAL path finding on head 366bd8f.

Verification:

  • native-byte WAL regression ✅
  • previous four-field postcard dependency compatibility ✅
  • malformed/older dependency quarantine regressions ✅
  • Hermes tests: 32 passed ✅
  • all-target/all-feature suite: 332 passed, 2 ignored ✅
  • cargo fmt --check
  • standard and all-target/all-feature Clippy with -D warnings
  • independent static compatibility review: pass ✅

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 366bd8f03a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/usage.rs
model: Option<String>,
tokens: TokenBuckets,
source_cost_usd: Option<f64>,
cost_authoritative: bool,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve existing cached event blobs

When upgrading with a populated usage_file_cache, inserting this field changes the positional postcard layout while the usage parser versions for Claude, Codex, Cursor, OpenCode, Pi, OpenClaw, and Copilot remain unchanged. Their rows are therefore selected as cache hits, but decoding encounters the old dedupe_confidence string where this Boolean is expected and reparses every cached history file, making the first usage or TUI scan unnecessarily behave like a cold scan for large histories. Decode the previous event format or introduce a cache-format migration that supplies false for the new internal fields.

Useful? React with 👍 / 👎.

Comment thread src/sources/hermes.rs

fn split_roots(roots: &std::ffi::OsStr) -> Vec<PathBuf> {
roots
.to_string_lossy()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve native bytes in explicit Hermes roots

On Unix, when HERMES_PROFILE_ROOTS contains a path component with non-UTF-8 bytes, this lossy conversion replaces those bytes before discovery, so the resulting PathBuf does not identify the configured directory and its state.db is never scanned. Fresh evidence beyond the prior WAL-sidecar issue is that the explicit-root path is still converted before discovery; split the OsStr using native bytes so the WAL fix is reachable for this configuration.

Useful? React with 👍 / 👎.

@MaterAnime

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 366bd8f03a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/usage.rs
.into_iter()
.map(|file| file.path)
.collect::<Vec<_>>();
scan_files_cached(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve native Hermes paths in the primary cache key

When default Hermes profile entries differ only in invalid UTF-8 bytes and their databases have matching size/mtime, this scanner passes both native paths to scan_files_cached, but that function persists and looks them up using path.to_string_lossy() under PRIMARY KEY (source, path). Both paths collapse to the same key, so one cache row overwrites the other and a subsequent scan can reuse one profile's events for both, double-counting it while omitting the other. Fresh evidence beyond the prior WAL and explicit-root findings is that the primary usage cache key remains lossy; preserve native path identity there as well.

Useful? React with 👍 / 👎.

Comment thread src/sources/hermes.rs
let inconsistent = current != raw_current;
invalid_model |= inconsistent;
summed = add(summed, &current);
if !is_zero(&current) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Mark sessions with fully capped model rows conservative

When model-detail rows exceed a session aggregate and a later row is capped entirely to zero, this guard suppresses the only event carrying inconsistent = true; earlier retained model events remain non-conservative, and without an authoritative session cost there is no residual event either. For example, two 10-token models against a 10-token aggregate produce only the lexicographically first model with conservative_events == 0, silently presenting an arbitrary model/task attribution as reliable. Propagate invalid_model to the retained session events or emit an explicit conservative fallback.

Useful? React with 👍 / 👎.

@nicosuave

Copy link
Copy Markdown
Owner

The Codex toil is getting to be a little too much; feel free to open a followup PR if you notice anything.

@nicosuave
nicosuave merged commit c1d8284 into nicosuave:main Aug 14, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants