hermes-agent/gateway
Teknium de0f20ff05 fix(gateway): spool cap-dropped pending transcript messages instead of discarding
When the per-session pending transcript queue hits _MAX_PENDING_PER_SESSION
(200) while the session DB is broken, the gateway previously popped the
oldest message and discarded it permanently — silent user data loss during
live operation (#78182). The on-disk pending spool only ran at shutdown via
flush_pending_to_file.

Extend that existing spool machinery for runtime drops:

- gateway/shutdown_flush.py: add spool_dropped_transcript_message() and
  drain_transcript_spool(), reusing _get_flush_dir/_write_payload (same
  atomic-JSON pending_messages/ spool format). recover_pending_to_db()
  now also replays transcript_cap_drop payloads left over across restarts.
- gateway/session.py: on cap eviction, spool the dropped message and log a
  WARNING that includes the spool path; if spooling fails, degrade to the
  previous drop-and-warn behavior. On the next fully successful transcript
  flush for that session, drain and replay spooled messages in drop order;
  replay failures keep the spool files for the next attempt.
- tests/gateway/test_pending_queue_spool.py: drop→spool→drain roundtrip,
  per-session drain isolation, spool-failure degradation, replay-failure
  retention, and spool primitive ordering/reason filtering.

No new config; extends existing flush_pending_to_file infrastructure per
AGENTS.md guidance.

Refs #82616, #78182
2026-08-09 14:08:51 -07:00
..
assets
builtin_hooks
platforms fix: store strong ref to detached fatal handler task to prevent GC 2026-08-09 22:34:28 +05:30
relay fix(gateway): rename a Discord thread once, after the reply lands 2026-08-09 04:33:58 -05:00
__init__.py
agent_cache_pressure.py fix: follow-ups for salvaged PR #80795 2026-08-07 21:02:33 +05:30
authz_mixin.py fix(secrets): route authz gate and pairing allowlist reads through the profile secret scope 2026-08-02 10:02:33 -07:00
cgroup_cleanup.py
channel_directory.py perf(slack): parallelize conversations.info lookups with asyncio.gather 2026-08-07 18:40:33 +05:30
code_skew.py
config.py fix: address self-review findings on the check_fn/ensure_deps_fn split 2026-08-07 13:28:43 +05:30
cwd_placeholder.py
dead_targets.py
delivery.py
delivery_ledger.py
display_config.py
drain_control.py
hooks.py fix: handle replacement transforms after CLI streaming 2026-08-08 14:06:30 +05:30
kanban_watchers.py feat(kanban,mcp): orphaned-card reconciliation + per-server MCP identity header 2026-08-07 08:58:20 -07:00
lifecycle_ledger.py
memory_monitor.py
message_timestamps.py
mirror.py
pairing.py fix(secrets): route authz gate and pairing allowlist reads through the profile secret scope 2026-08-02 10:02:33 -07:00
platform_registry.py fix(gateway): split check_fn (passive probe) from ensure_deps_fn (active installer) 2026-08-07 13:28:43 +05:30
profile_routing.py
readiness.py
response_filters.py
restart.py fix(gateway): defer in-band restart until active turns finish (#77184) 2026-08-03 09:57:58 +05:30
restart_loop_guard.py fix(gateway): make the restart-loop breaker see slow crash cycles (#81642) 2026-08-09 21:40:23 +05:30
rich_sent_store.py
run.py fix(gateway): make the restart-loop breaker see slow crash cycles (#81642) 2026-08-09 21:40:23 +05:30
runtime_footer.py feat(gateway): add opt-in 'latency' runtime footer field 2026-08-03 17:16:57 +05:30
scale_to_zero.py
session.py fix(gateway): spool cap-dropped pending transcript messages instead of discarding 2026-08-09 14:08:51 -07:00
session_context.py fix(cron): scope cron approval context per session 2026-08-03 00:25:20 +05:30
session_stall.py feat(gateway): session activity watchdog, stall notify, compress timeout (#72424) 2026-08-02 16:16:36 -07:00
session_state.py refactor(gateway): extract the hygiene recovery gate and forward the failure reason 2026-08-06 15:04:53 +05:30
shutdown_flush.py fix(gateway): spool cap-dropped pending transcript messages instead of discarding 2026-08-09 14:08:51 -07:00
shutdown_forensics.py
shutdown_watchdog.py
slash_access.py
slash_commands.py fix(personality): single-owner personality state + one-time reset migration 2026-08-09 10:33:58 -07:00
status.py fix(gateway): self-reacquire scoped lock by PID alone 2026-08-08 13:50:08 +05:30
status_phrases.py
sticker_cache.py
stream_consumer.py fix(gateway): cover all finalized stream sends 2026-08-08 16:59:42 -07:00
stream_dispatch.py
stream_events.py
streaming_tts_consumer.py
systemd_notify.py
turn_context.py fix(gateway): reap only the background processes an abandoned turn created 2026-08-02 14:23:55 +05:30
turn_lease.py refactor(gateway): drop dead degraded token field; de-churn salvage diff 2026-08-07 18:23:57 +05:30
wake.py
whatsapp_identity.py