First pass of test-suite reduction to address flaky CI and bloat.
Removed tests that fall into these change-detector patterns:
1. Source-grep tests (tests/gateway/test_feishu.py, test_email.py): tests
that call inspect.getsource() on production modules and grep for string
literals. Break on any refactor/rename even when behavior is correct.
2. Platform enum tautologies (every gateway/test_X.py): assertions like
`Platform.X.value == 'x'` duplicated across ~9 adapter test files.
3. Toolset/PLATFORM_HINTS/setup-wizard registry-presence checks: tests that
only verify a key exists in a dict. Data-layout tests, not behavior.
4. Argparse wiring tests (test_argparse_flag_propagation, test_subparser_routing
_fallback): tests that do parser.parse_args([...]) then assert args.field.
Tests Python's argparse, not our code.
5. Pure dispatch tests (test_plugins_cmd.TestPluginsCommandDispatch): patch
cmd_X, call plugins_command with matching action, assert mock called.
Tests the if/elif chain, not behavior.
6. Kwarg-to-mock verification (test_auxiliary_client ~45 tests,
test_web_tools_config, test_gemini_cloudcode, test_retaindb_plugin): tests
that mock the external API client, call our function, and assert exact
kwargs. Break on refactor even when behavior is preserved.
7. Schedule-internal "function-was-called" tests (acp/test_server scheduling
tests): tests that patch own helper method, then assert it was called.
Kept behavioral tests throughout: error paths (pytest.raises), security
tests (path traversal, SSRF, redaction), message alternation invariants,
provider API format conversion, streaming logic, memory contract, real
config load/merge tests.
Net reduction: 169 tests removed. 38 empty classes cleaned up.
Collected before: 12,522 tests
Collected after: 12,353 tests
- Pastes uploaded by /debug now auto-delete after 1 hour via a detached
background process that sends DELETE to paste.rs
- CLI: shows privacy notice listing what data will be uploaded
- Gateway: only uploads summary report (system info + log tails), NOT
full log files containing conversation content
- Added 'hermes debug delete <url>' for immediate manual deletion
- 16 new tests covering auto-delete scheduling, paste deletion, privacy
notices, and the delete subcommand
Addresses user privacy concern where /debug uploaded full conversation
logs to a public paste service with no warning or expiry.
* feat: add `hermes debug share` — upload debug report to pastebin
Adds a new `hermes debug share` command that collects system info
(via hermes dump), recent logs (agent.log, errors.log, gateway.log),
and uploads the combined report to a paste service (paste.rs primary,
dpaste.com fallback). Returns a shareable URL for support.
Options:
--lines N Number of log lines per file (default: 200)
--expire N Paste expiry in days (default: 7, dpaste.com only)
--local Print report locally without uploading
Files:
hermes_cli/debug.py - New module: paste upload + report collection
hermes_cli/main.py - Wire cmd_debug + argparse subparser
tests/hermes_cli/test_debug.py - 19 tests covering upload, collection, CLI
* feat: upload full agent.log and gateway.log as separate pastes
hermes debug share now uploads up to 3 pastes:
1. Summary report (system info + log tails) — always
2. Full agent.log (last ~500KB) — if file exists
3. Full gateway.log (last ~500KB) — if file exists
Each paste uploads independently; log upload failures are noted
but don't block the main report. Output shows all links aligned:
Report https://paste.rs/abc
agent.log https://paste.rs/def
gateway.log https://paste.rs/ghi
Also adds _read_full_log() with size-capped tail reading to stay
within paste service limits (~512KB per file).
* feat: prepend hermes dump to each log paste for self-contained context
Each paste (agent.log, gateway.log) now starts with the hermes dump
output so clicking any single link gives full system context without
needing to cross-reference the summary report.
Refactored dump capture into _capture_dump() — called once and
reused across the summary report and each log paste.
* fix: fall back to .1 rotated log when primary log is missing or empty
When gateway.log (or agent.log) doesn't exist or is empty, the debug
share now checks for the .1 rotation file. This is common — the
gateway rotates logs and the primary file may not exist yet.
Extracted _resolve_log_path() to centralize the fallback logic for
both _read_log_tail() and _read_full_log().
* chore: remove unused display_hermes_home import