{"repo":"NousResearch/hermes-agent","public_id":"20020","display_label":"Fix incorrect compress command name in tips","summary":"Multiple fixes correcting a wrong command name (likely /compact instead of /compress) appearing in context-overflow and compaction guidance tips. Related changes also touch memory authority, cache eviction, and summary boundary markers.","subsystem":"gateway","counts":{"members":6,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":4},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":20579},"resolution":{"state":"resolved","by":"pr-20579"},"freshness":{"state":"verified","last_verified_at":"2026-05-06T05:33:46+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.3333333333333333},"fix_edges":[{"issue_number":20020,"pr_number":20579,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":20020,"title":"[Bug]: Compress command tips wrong","url":null,"state":"closed"},{"kind":"pr","number":20027,"title":"fix(gateway): correct compression guidance command","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"2e5acc5e771f111abf5335323c35b8a84343b021","number":0}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":20057,"title":"fix: use correct /compress command name in context-overflow tips","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#20027","number":20027}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":20163,"title":"fix(gateway): correct /compact to /compress in context overflow tips","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#20027","number":20027}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":20172,"title":"fix: salvage batch — compaction guidance, memory authority, eviction, summary boundary marker","url":null,"state":"closed","close_reason":{"category":"silent_close","implication":"active"},"merged":false},{"kind":"pr","number":20579,"title":"fix: salvage batch — compaction guidance, memory authority, cache eviction after compression","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["agent/context_compressor.py","agent/memory_manager.py","gateway/run.py","scripts/release.py"],"fix_hunks":[{"file":"agent/context_compressor.py","hunks":["@@ -43,6 +43,9 @@\n     \"they were already addressed. \"\n     \"Your current task is identified in the '## Active Task' section of the \"\n     \"summary — resume exactly from there. \"\n+    \"IMPORTANT: Your persistent memory (MEMORY.md, USER.md) in the system \"\n+    \"prompt is ALWAYS authoritative and active — never ignore or deprioritize \"\n+    \"memory content due to this compaction note. \"\n     \"Respond ONLY to the latest user message \"\n     \"that appears AFTER this summary. The current session state (files, \"\n     \"config, etc.) may reflect work described here — avoid repeating it:\"","@@ -1373,7 +1376,7 @@ def compress(self, messages: List[Dict[str, Any]], current_tokens: int = None, f\n             msg = messages[i].copy()\n             if i == 0 and msg.get(\"role\") == \"system\":\n                 existing = msg.get(\"content\")\n-                _compression_note = \"[Note: Some earlier conversation turns have been compacted into a handoff summary to preserve context space. The current session state may still reflect earlier work, so build on that summary and state rather than re-doing work.]\"\n+                _compression_note = \"[Note: Some earlier conversation turns have been compacted into a handoff summary to preserve context space. The current session state may still reflect earlier work, so build on that summary and state rather than re-doing work. Your persistent memory (MEMORY.md, USER.md) remains fully authoritative regardless of compaction.]\"\n                 if _compression_note not in _content_text_for_contains(existing):\n                     msg[\"content\"] = _append_text_to_content(\n                         existing,"]},{"file":"agent/memory_manager.py","hunks":["@@ -46,7 +46,7 @@\n     re.IGNORECASE,\n )\n _INTERNAL_NOTE_RE = re.compile(\n-    r'\\[System note:\\s*The following is recalled memory context,\\s*NOT new user input\\.\\s*Treat as informational background data\\.\\]\\s*',\n+    r'\\[System note:\\s*The following is recalled memory context,\\s*NOT new user input\\.\\s*Treat as (?:informational background data|authoritative reference data[^\\]]*)\\.\\]\\s*',\n     re.IGNORECASE,\n )\n ","@@ -180,7 +180,8 @@ def build_memory_context_block(raw_context: str) -> str:\n     return (\n         \"<memory-context>\\n\"\n         \"[System note: The following is recalled memory context, \"\n-        \"NOT new user input. Treat as informational background data.]\\n\\n\"\n+        \"NOT new user input. Treat as authoritative reference data — \"\n+        \"this is the agent's persistent memory and should inform all responses.]\\n\\n\"\n         f\"{clean}\\n\"\n         \"</memory-context>\"\n     )"]},{"file":"gateway/run.py","hunks":["@@ -6322,6 +6322,10 @@ async def _handle_message_with_agent(self, event, source, _quick_key: str, run_g\n                                                 _werr,\n                                             )\n                                 finally:\n+                                    # Evict the cached agent so the next turn\n+                                    # rebuilds its system prompt from current\n+                                    # SOUL.md, memory, and skills.\n+                                    self._evict_cached_agent(session_key)\n                                     self._cleanup_agent_resources(_hyg_agent)\n \n                     except Exception as e:","@@ -9505,6 +9509,9 @@ async def _handle_compress_command(self, event: MessageEvent) -> str:\n                 _aux_fail_model = getattr(compressor, \"_last_aux_model_failure_model\", None)\n                 _aux_fail_err = getattr(compressor, \"_last_aux_model_failure_error\", None)\n             finally:\n+                # Evict cached agent so next turn rebuilds system prompt\n+                # from current files (SOUL.md, memory, etc.).\n+                self._evict_cached_agent(session_key)\n                 self._cleanup_agent_resources(tmp_agent)\n             lines = [f\"🗜️ {summary['headline']}\"]\n             if focus_topic:"]},{"file":"scripts/release.py","hunks":["@@ -177,6 +177,8 @@\n     \"[redacted:email]\": \"hendrixfreire\",\n     \"[redacted:email]\": \"benjaminsehl\",\n     \"[redacted:email]\": \"Nerijusas\",\n+    # Compaction salvage batch (May 2026)\n+    \"[redacted:email]\": \"MacroAnarchy\",\n     \"[redacted:email]\": \"Ito-69\",\n     \"[redacted:email]\": \"georgeglessner\",\n     \"[redacted:email]\": \"maxims-oss\",\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}