From eebfd9d0ec831bc603b2b6d1a0acc14baa8d75fd Mon Sep 17 00:00:00 2001 From: Aron Bijl Date: Sat, 3 Oct 2026 18:32:27 +0200 Subject: [PATCH 1/5] fix: support Hermes live-compression config and current route windows Add the missing cap coercion, lazy context/threshold invalidation, per-model threshold handling and isolated clone state. Use the host request's current window without resetting usage or retry bindings. Nine offline regressions passed against installed Hermes 188a1a5 on Python 3.14. Live installation and restart were blocked by remote execution and are not claimed; the upstream discovery race remains a separate deployment concern. --- docs/LIVE_COMPRESSION_COMPAT.md | 32 +++++++ src/rtk_hermes_plus/hermes_engine.py | 123 +++++++++++++++++++++++++- tests/test_hermes_live_compression.py | 120 +++++++++++++++++++++++++ 3 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 docs/LIVE_COMPRESSION_COMPAT.md create mode 100644 tests/test_hermes_live_compression.py diff --git a/docs/LIVE_COMPRESSION_COMPAT.md b/docs/LIVE_COMPRESSION_COMPAT.md new file mode 100644 index 0000000..590877f --- /dev/null +++ b/docs/LIVE_COMPRESSION_COMPAT.md @@ -0,0 +1,32 @@ +# Live-compression adapter repair + +The v0.11.0 adapter omitted the compatibility surface used by current Hermes +`_apply_live_compression_config`. That host function updates the selected +`context_compressor` even when it is a plugin ContextEngine, including calling +`_coerce_threshold_tokens_cap` and clearing lazy window/threshold caches. + +This patch supplies positive-int/None cap normalization, lazy threshold and window +invalidation, current-route metadata resolution when an explicit pin is removed, +per-model threshold handling and isolated clone state. The current host request's +`budget_tokens` refreshes the engine's window without resetting response counters. +No hardcoded 272k or assumed replacement window is introduced. Host-side metadata +is reused; the underlying request tokenizer and reduction acceptance gate are not +relaxed. Internal service calls remain excluded. No generative compressor is built. + +Nine offline regression tests passed against the installed Hermes checkout +`188a1a5efd098f067638032fea6e24c42d06178f` on Python 3.14. The tests call the real +live-config function with mocked model metadata and disposable stores. They do not +claim paid-provider validation or a reduction of an existing live session. + +Operational state: applying the tested patch to the live managed installation was +blocked by the remote execution tool. No live adapter replacement or backend restart +was performed. The test candidate is retained separately. A partial older patch +was already present in the managed source; it must not be confused with repository +v0.11.0 or evidence that a running process has loaded a repair. + +The observed host directory loader can expose a partially initialized cached module +to simultaneous discovery. This adapter patch does not modify that upstream loader +or claim to resolve its race. Deployment must use the host's managed plugin update +path and a controlled backend restart, then check loaded engine identity and actual +provider-request metrics. Do not kill unrelated relay/messaging/dashboard processes, +delete conversation/vault data, or claim a reset UI percentage proves reduction. diff --git a/src/rtk_hermes_plus/hermes_engine.py b/src/rtk_hermes_plus/hermes_engine.py index 5c28f1b..7159183 100644 --- a/src/rtk_hermes_plus/hermes_engine.py +++ b/src/rtk_hermes_plus/hermes_engine.py @@ -1,4 +1,4 @@ -"""Optional Hermes adapter. Normal TT imports never depend on Hermes being installed.""" +"""Hermes adapter with live-config and route-local model-window compatibility.""" from agent.context_engine import ContextEngine @@ -6,8 +6,127 @@ class TokenTerminatorContextEngine(HistoryContextEngine, ContextEngine): - """Selectable through Hermes' supported user ContextEngine directory mechanism.""" + """Hermes updates its selected engine through context_compressor as well.""" + + def __init__(self, **kwargs): + self.threshold_tokens_cap = None + self._config_context_length = None + self._model_metadata_kwargs = {} + self._resolved_context_length = 0 + self._threshold_tokens = self._tail_token_budget = None + super().__init__(**kwargs) @property def name(self) -> str: return "token-terminator" + + @staticmethod + def _coerce_threshold_tokens_cap(value) -> int | None: + """Positive integer or None, as required by Hermes' live-config hook.""" + try: + cap = int(value) if value is not None else 0 + except (TypeError, ValueError, OverflowError): + return None + return cap if cap > 0 else None + + @staticmethod + def _effective_threshold_percent(context_length, threshold_percent): + from agent.context_compressor import ContextCompressor + + return ContextCompressor._effective_threshold_percent( + context_length, threshold_percent + ) + + @property + def context_length(self) -> int: + if self._resolved_context_length is None: + from agent.model_metadata import get_model_context_length + + self._resolved_context_length = get_model_context_length( + self.model, + config_context_length=self._config_context_length, + **self._model_metadata_kwargs, + ) + return self._resolved_context_length + + @context_length.setter + def context_length(self, value: int) -> None: + self._resolved_context_length = max(0, int(value)) + self._threshold_tokens = self._tail_token_budget = None + + def _effective_threshold_cap(self, context_length: int) -> int | None: + cap = self._coerce_threshold_tokens_cap(self.threshold_tokens_cap) + return min(cap, context_length) if cap is not None else None + + @property + def threshold_tokens(self) -> int: + if self._threshold_tokens is None: + window = self.context_length + base = getattr(self, "_base_threshold_percent", self.threshold_percent) + self.threshold_percent = self._effective_threshold_percent(window, base) + threshold = int(window * self.threshold_percent) + cap = self._effective_threshold_cap(window) + self._threshold_tokens = ( + min(threshold, cap) if cap is not None else threshold + ) + return self._threshold_tokens + + @threshold_tokens.setter + def threshold_tokens(self, value: int) -> None: + self._threshold_tokens = value + + def update_model(self, model: str, context_length: int, **kwargs) -> None: + from agent.context_compressor import resolve_model_threshold + + with self._lock: + self._model_metadata_kwargs = { + key: kwargs[key] + for key in ("base_url", "api_key", "provider", "custom_providers") + if key in kwargs + } + if not hasattr(self, "_config_threshold_percent"): + self._config_threshold_percent = self.threshold_percent + self._base_threshold_percent = resolve_model_threshold( + model, + getattr(self, "model_thresholds", {}), + self._config_threshold_percent, + kwargs.get("provider", ""), + ) + self.threshold_percent = self._effective_threshold_percent( + context_length, self._base_threshold_percent + ) + super().update_model(model, context_length, **kwargs) + self._threshold_tokens = self._tail_token_budget = None + + def select_context(self, request_messages, **kwargs): + from .call_scope import internal_operation + + if internal_operation(): + return None + with self._lock: + # The hook carries the host's current route window, not a fixed TT cap. + # Do not use update_model here: that would reset retry/usage state. + budget = kwargs.get("budget_tokens", 0) + if type(budget) is int and budget > 0: + self.context_length = budget + return super().select_context(request_messages, **kwargs) + + def clone_for_agent(self): + with self._lock: + clone = type(self)(config=self.config, limits=self.limits) + clone.threshold_percent = self.threshold_percent + clone.threshold_tokens_cap = self.threshold_tokens_cap + clone._config_context_length = self._config_context_length + for key in ("_config_threshold_percent", "_base_threshold_percent"): + if hasattr(self, key): + setattr(clone, key, getattr(self, key)) + clone.model_thresholds = dict(getattr(self, "model_thresholds", {})) + clone.update_model( + self.model, self.context_length, **self._model_metadata_kwargs + ) + return clone + + def get_status(self): + result = super().get_status() + result["adapter_compat"] = "hermes-live-compression-v1" + return result diff --git a/tests/test_hermes_live_compression.py b/tests/test_hermes_live_compression.py new file mode 100644 index 0000000..ddecbd5 --- /dev/null +++ b/tests/test_hermes_live_compression.py @@ -0,0 +1,120 @@ +"""Regression against the real optional Hermes live-config implementation.""" + +import copy +import tempfile +import types +import unittest +from pathlib import Path +from unittest.mock import patch + +try: + from tui_gateway.session_compression import _apply_live_compression_config +except ImportError as exc: + raise unittest.SkipTest("requires a current Hermes checkout") from exc + +from rtk_hermes_plus.config import Config +from rtk_hermes_plus.hermes_engine import TokenTerminatorContextEngine as Engine +from rtk_hermes_plus.history_engine import HistoryContextEngine + + +class LiveConfigTests(unittest.TestCase): + def setUp(self): + self.tmp = tempfile.TemporaryDirectory() + self.addCleanup(self.tmp.cleanup) + self.engine = Engine( + config=Config( + db_path=Path(self.tmp.name) / "vault.db", ledger_enabled=False + ) + ) + self.engine.update_model("fixture-main", 272000, provider="fixture") + self.agent = types.SimpleNamespace( + context_compressor=self.engine, model="fixture-main", provider="fixture" + ) + + def apply(self, cfg, pin=None): + with patch( + "agent.agent_init.config_context_length_for_runtime", return_value=pin + ): + _apply_live_compression_config(self.agent, cfg) + + def test_cap_values(self): + cases = [ + (None, None), (0, None), (-1, None), ("bad", None), + ("", None), (180000, 180000), ("180000", 180000), (float("inf"), None), + ] + for value, expected in cases: + with self.subTest(value=value): + self.assertEqual( + self.engine._coerce_threshold_tokens_cap(value), expected + ) + + def test_actual_live_hook_updates_pin_and_cap(self): + self.apply( + {"compression": {"threshold": 0.7, "threshold_tokens": 180000}}, + pin=1000000, + ) + self.assertEqual(self.engine.context_length, 1000000) + self.assertEqual(self.engine.threshold_tokens, 180000) + self.assertEqual(self.engine._config_context_length, 1000000) + + def test_removed_pin_reresolves_current_route(self): + self.apply( + {"compression": {"threshold": 0.7, "threshold_tokens": 180000}}, + pin=1000000, + ) + with patch( + "agent.model_metadata.get_model_context_length", return_value=600000 + ) as resolver: + self.apply( + {"compression": {"threshold": 0.7, "threshold_tokens": None}} + ) + self.assertIsNone(self.engine._config_context_length) + self.assertEqual(self.engine.context_length, 600000) + self.assertEqual(self.engine.threshold_tokens, 420000) + self.assertEqual(resolver.call_args.args[0], "fixture-main") + self.assertEqual(resolver.call_args.kwargs["provider"], "fixture") + + def test_live_small_window_threshold_floor(self): + self.apply({"compression": {"threshold": 0.1, "threshold_tokens": None}}) + self.assertEqual(self.engine.threshold_tokens, 204000) + + def test_model_switch_preserves_cap_and_changes_route(self): + self.engine.threshold_tokens_cap = 180000 + self.engine._threshold_tokens = None + self.engine.update_model("fixture-small", 32000, provider="other") + self.assertEqual(self.engine.threshold_tokens, 24000) + self.assertEqual(self.engine._model_metadata_kwargs, {"provider": "other"}) + + def test_host_request_window_replaces_stale_272k(self): + self.engine.last_prompt_tokens = 270000 + messages = [{"role": "user", "content": "Keep this exact."}] + original = copy.deepcopy(messages) + with patch.object( + HistoryContextEngine, "select_context", return_value=None + ) as select: + self.engine.select_context(messages, budget_tokens=1000000) + select.assert_called_once() + self.assertEqual(self.engine.context_length, 1000000) + self.assertEqual(self.engine.last_prompt_tokens, 270000) + self.assertEqual(messages, original) + + def test_unknown_window_does_not_erase_known_window(self): + with patch.object(HistoryContextEngine, "select_context", return_value=None): + self.engine.select_context([], budget_tokens=0) + self.assertEqual(self.engine.context_length, 272000) + + def test_clones_do_not_share_mutable_budget_state(self): + self.engine.threshold_tokens_cap = 100000 + self.engine.model_thresholds = {"fixture": 0.6} + other = self.engine.clone_for_agent() + other.threshold_tokens_cap = 50000 + other.model_thresholds["fixture"] = 0.9 + other.context_length = 1000000 + self.assertEqual(self.engine.threshold_tokens_cap, 100000) + self.assertEqual(self.engine.model_thresholds, {"fixture": 0.6}) + self.assertEqual(self.engine.context_length, 272000) + + def test_no_summarizer_or_destructive_compression(self): + self.assertFalse(self.engine.should_compress(9999999)) + self.assertFalse(self.engine.should_compress_preflight([])) + self.assertIsNone(self.engine._catalog) From 58b6d6c2af2b9014bce658caf2f6fb0119d0f759 Mon Sep 17 00:00:00 2001 From: Aron Bijl Date: Sat, 3 Oct 2026 21:41:39 +0200 Subject: [PATCH 2/5] style: ruff format hermes live-compression tests --- tests/test_hermes_live_compression.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/test_hermes_live_compression.py b/tests/test_hermes_live_compression.py index ddecbd5..7387aba 100644 --- a/tests/test_hermes_live_compression.py +++ b/tests/test_hermes_live_compression.py @@ -39,8 +39,14 @@ def apply(self, cfg, pin=None): def test_cap_values(self): cases = [ - (None, None), (0, None), (-1, None), ("bad", None), - ("", None), (180000, 180000), ("180000", 180000), (float("inf"), None), + (None, None), + (0, None), + (-1, None), + ("bad", None), + ("", None), + (180000, 180000), + ("180000", 180000), + (float("inf"), None), ] for value, expected in cases: with self.subTest(value=value): @@ -65,9 +71,7 @@ def test_removed_pin_reresolves_current_route(self): with patch( "agent.model_metadata.get_model_context_length", return_value=600000 ) as resolver: - self.apply( - {"compression": {"threshold": 0.7, "threshold_tokens": None}} - ) + self.apply({"compression": {"threshold": 0.7, "threshold_tokens": None}}) self.assertIsNone(self.engine._config_context_length) self.assertEqual(self.engine.context_length, 600000) self.assertEqual(self.engine.threshold_tokens, 420000) From 34987bc9dfcdef46eb90e492c9198fe174c2c398 Mon Sep 17 00:00:00 2001 From: Aron Bijl Date: Sun, 4 Oct 2026 06:11:35 +0200 Subject: [PATCH 3/5] chore: prepare approved v0.11.1 patch release metadata --- .github/workflows/prepare-0.11.1.yml | 220 +++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 .github/workflows/prepare-0.11.1.yml diff --git a/.github/workflows/prepare-0.11.1.yml b/.github/workflows/prepare-0.11.1.yml new file mode 100644 index 0000000..01bc4a5 --- /dev/null +++ b/.github/workflows/prepare-0.11.1.yml @@ -0,0 +1,220 @@ +name: Prepare approved v0.11.1 metadata + +on: + push: + branches: [fix/hermes-live-compression-compat] + paths: [.github/workflows/prepare-0.11.1.yml] + +permissions: + contents: write + +jobs: + prepare: + if: github.repository == 'AronAxe/Token-Terminator' && github.ref == 'refs/heads/fix/hermes-live-compression-compat' + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Update only release metadata and documentation + shell: bash + run: | + set -euo pipefail + test "$GITHUB_REF" = refs/heads/fix/hermes-live-compression-compat + git merge-base --is-ancestor 58b6d6c2af2b9014bce658caf2f6fb0119d0f759 HEAD + python - <<'PY' + from pathlib import Path + import hashlib + + expected = { + 'README.md': '060d1c08b33ac27fa3e0c455d08472296a0ecf1e46ef8b83cd7b634163531a18', + 'MIGRATION.md': 'd0f08d6ce668d045e90aa78ed91223749722797939624e63fcac5239e75f23b4', + 'CHANGELOG.md': '81dac26dc60aaa244ec1c9a61907c8d5cba77ad0e958b3cb00ef5e818a5ea93e', + 'pyproject.toml': '0a4fa5081dde2a87cf02adf00c67238b1d6d5dbdbe298a8d85949b38f1710daf', + 'src/rtk_hermes_plus/_version.py': 'ada32ef5703d2448ef7684e616a70ec3baa1257db8ad80cfed7992e7d4c03be4', + } + for name, digest in expected.items(): + assert hashlib.sha256(Path(name).read_bytes()).hexdigest() == digest, name + + def write(name, text): + Path(name).write_bytes(text.encode('utf-8')) + + for name in ('pyproject.toml', 'Cargo.toml', 'src/rtk_hermes_plus/_version.py'): + text = Path(name).read_text(encoding='utf-8') + assert text.count('"0.11.0"') == 1, name + write(name, text.replace('"0.11.0"', '"0.11.1"')) + + readme = Path('README.md').read_text(encoding='utf-8') + for old, new in ( + ('releases/tag/v0.11.0', 'releases/tag/v0.11.1'), + ('alt="Release v0.11.0"', 'alt="Release v0.11.1"'), + ('badge/release-v0.11.0-', 'badge/release-v0.11.1-'), + ('badge/crates.io-v0.11.0-', 'badge/crates.io-v0.11.1-'), + ('Token-Terminator.git@v0.11.0', 'Token-Terminator.git@v0.11.1'), + ('Install **v0.11.0**', 'Install **v0.11.1**'), + ('Token Terminator 0.11.0 builds on', 'Token Terminator 0.11.1 builds on'), + ('commands below pin the `v0.11.0` release tag', 'commands below pin the `v0.11.1` release tag'), + ('cargo add token-terminator@0.11.0', 'cargo add token-terminator@0.11.1'), + ): + assert old in readme, old + readme = readme.replace(old, new) + old = "No. Token Terminator operates after or alongside normal context assembly. It does not own the transcript, alter persisted conversation history, or require a particular memory engine." + assert old in readme + readme = readme.replace(old, "It can replace the selected **Hermes context engine**, including LCM, when explicitly configured with `context.engine: token-terminator`. Middleware-only mode keeps the host engine upstream. Neither mode replaces the memory system or transcript store, or destructively rewrites persisted conversation history.") + note = '''## Patch v0.11.1: Hermes live-compression compatibility + + Repairs the missing `_coerce_threshold_tokens_cap` adapter method and live + window/threshold invalidation. The selected TT engine now follows Hermes' + current route budget and isolates cloned engine settings. No new settings, + generative summarizer or relaxed tokenizer gate are introduced. + + For managed/multiplex installs, upgrade the environment that actually imports + TT, then restart the appropriate idle backend through its normal supervisor. + This patch does not add unknown-model tokenizer mappings or fix Hermes' separate + concurrent plugin-discovery race. [Patch notes](docs/releases/v0.11.1.md) · + [Compatibility details](docs/LIVE_COMPRESSION_COMPAT.md). + + ''' + # Triple-quoted text is indented only for the workflow's Python block. + import textwrap + readme = readme.replace('## New in v0.11.0\n', textwrap.dedent(note) + '## New in v0.11.0\n', 1) + write('README.md', readme) + + entry = '''## 0.11.1 - 2026-10-04 + + - Fixed the Hermes live-compression adapter's missing `_coerce_threshold_tokens_cap` + method and lazy context-window/threshold cache invalidation. + - Reused installed Hermes route metadata and per-model threshold handling; current + `select_context` budgets refresh the window without resetting retry/usage state. + - Preserved independent cloned-engine configuration, exact recovery, internal-call + isolation and the existing strict tokenizer acceptance gate. + - Added nine real-Hermes regression cases and corrected their Ruff formatting. + - Updated release/install references and corrected the README's stale context-engine + FAQ. Rust companion version aligned; its runtime behavior is unchanged. + - Unknown-model tokenizers and the host's plugin-discovery race remain separate + limitations; publication does not install or restart a running Hermes profile. + + ''' + changelog = Path('CHANGELOG.md').read_text(encoding='utf-8') + assert changelog.startswith('# Changelog\n\n') + write('CHANGELOG.md', '# Changelog\n\n' + textwrap.dedent(entry) + changelog[len('# Changelog\n\n'):]) + + migration = '''# Migration to Token Terminator 0.11.1 + + ## 0.11.0 to 0.11.1 + + This is the PR #20 Hermes live-compression compatibility repair. No new key, + database migration, tokenizer override or engine-selection change is required. + Upgrade the environment actually used by the managed Hermes launcher, not an + unrelated Python environment or stale venv copy: + + ```bash + python -m pip install --upgrade 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' + python -m rtk_hermes_plus.cli install-context-engine + ``` + + Confirm the imported `rtk_hermes_plus` path in that environment. When the relevant + backend is idle, restart it once through its normal supervisor; do not start a + competing gateway or delete histories/vaults. Verify the loaded version and + current-model request metrics. A healthy restart or a lower UI percentage alone + does not prove reduction. Unknown target tokenizers still bypass the engine. + See [the compatibility guide](docs/LIVE_COMPRESSION_COMPAT.md). These instructions + do not imply publication performs a live installation or restart. + + --- + + ''' + write('MIGRATION.md', textwrap.dedent(migration) + Path('MIGRATION.md').read_text(encoding='utf-8')) + + compat = Path('docs/LIVE_COMPRESSION_COMPAT.md').read_text(encoding='utf-8') + start = compat.index('Operational state:') + end = compat.index('The observed host directory loader', start) + compat = compat[:start] + '''Release scope: v0.11.1 publishes PR #20's adapter and tests. Earlier incident + deployment notes are historical; a separately deployed adapter snapshot is not + proof that this exact release has loaded in a running process. Installation, + engine discovery and actual current-model request reduction remain separate + checks. This release performs no live installation or backend restart. + + '''.replace('\n ', '\n') + compat[end:] + compat += '\nUnknown target tokenizers still cause ContextEngine/IR to pass through. This\npatch does not supply new tokenizer mappings, guess a replacement model window,\nor guarantee a reduction in a live session.\n' + write('docs/LIVE_COMPRESSION_COMPAT.md', compat) + + notes = '''# Token Terminator v0.11.1 — Hermes live-compression compatibility + + A focused patch release of PR #20. The v0.11.0 ContextEngine, learned JEV policy, + Context IR, exact-evidence vault and Observatory remain in place. + + ## Fixed + + - Supply `_coerce_threshold_tokens_cap` for Hermes' live-compression configuration. + - Honor invalidated context-window and threshold caches, explicit pin removal, + current-route metadata and per-model threshold handling. + - Refresh the engine window from the host's current `select_context` budget + without resetting retry bindings or usage counters. + - Keep cloned engines' settings independent. No generative compressor, destructive + history truncation, new key or weakened tokenizer gate is introduced. + - Include nine real-Hermes regression cases and the formatting-only CI correction. + + ## Upgrade + + Use the Python environment actually loaded by your managed Hermes launcher: + + ```bash + python -m pip install --upgrade 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' + python -m rtk_hermes_plus.cli install-context-engine + ``` + + Keep your existing plugin/engine selection and JEV settings. Once idle, restart + only the relevant backend through its normal supervisor. Do not delete the + conversation history or evidence vault. Verify the imported package path, + loaded version and current-model request metrics, not only a UI percentage. + + ## Validation and scope + + The formatted PR candidate passed Python 3.10–3.13, Windows, packaging, Rust, + learned-policy, ContextEngine, dashboard and Context IR workflows before release + preparation. The learning artifact reported 611 passed and three skips; one + skip is the whole optional real-Hermes test module. Its nine cases were previously + run locally against installed Hermes `188a1a5` on Python 3.14, not counted as + executed in that learning job. Final release-head CI status is recorded on PR #20. + No paid inference or new performance/answer-quality claims accompany this patch. + + **Not fixed by this patch:** unknown-model tokenizer support and the separate + host plugin-discovery race. Without an exact target tokenizer, ContextEngine/IR + still pass through. This is not a guarantee that an affected live session has + shrunk, and it does not merge the separate deployed-adapter branch. + + README changes are limited to a compatibility note, current install/version + references and correcting the stale FAQ: explicitly selected TT can replace LCM + as Hermes' ContextEngine. Artwork and schematics are unchanged. + + The Rust interoperability companion is version-aligned to 0.11.1 without a Rust + behavior change; it is not the Python runtime. GitHub assets include the wheel, + source distribution and SHA256SUMS. Existing releases remain unchanged. + Publication does not install, configure or restart your running agents. + + [PR #20](https://github.com/AronAxe/Token-Terminator/pull/20) · + [Compatibility guide](https://github.com/AronAxe/Token-Terminator/blob/v0.11.1/docs/LIVE_COMPRESSION_COMPAT.md) · + [Migration](https://github.com/AronAxe/Token-Terminator/blob/v0.11.1/MIGRATION.md) + ''' + notes = textwrap.dedent(notes) + Path('docs/releases').mkdir(exist_ok=True) + assert not Path('docs/releases/v0.11.1.md').exists() + write('docs/releases/v0.11.1.md', notes) + + for name in ('README.md', 'MIGRATION.md', 'CHANGELOG.md'): + text = Path(name).read_text(encoding='utf-8') + assert '0.11.1' in text + for name in expected: + print(name, hashlib.sha256(Path(name).read_bytes()).hexdigest()) + PY + git diff --check + git diff --exit-code 58b6d6c2af2b9014bce658caf2f6fb0119d0f759 -- src/rtk_hermes_plus/hermes_engine.py tests scripts benchmarks docs/assets + git add src/rtk_hermes_plus/_version.py pyproject.toml Cargo.toml README.md MIGRATION.md CHANGELOG.md docs/LIVE_COMPRESSION_COMPAT.md docs/releases/v0.11.1.md + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git commit -m 'release: prepare v0.11.1 Hermes compatibility patch' + git push origin HEAD:refs/heads/fix/hermes-live-compression-compat + git rev-parse HEAD + git rev-parse HEAD^{tree} From c6c62e40c0c0cfb25e91d5e37d456a9d1d188f12 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 4 Oct 2026 04:11:44 +0000 Subject: [PATCH 4/5] release: prepare v0.11.1 Hermes compatibility patch --- CHANGELOG.md | 14 ++++++++ Cargo.toml | 2 +- MIGRATION.md | 24 ++++++++++++++ README.md | 35 +++++++++++++------- docs/LIVE_COMPRESSION_COMPAT.md | 14 +++++--- docs/releases/v0.11.1.md | 57 +++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/rtk_hermes_plus/_version.py | 2 +- 8 files changed, 131 insertions(+), 19 deletions(-) create mode 100644 docs/releases/v0.11.1.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ef921d8..95a65b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.11.1 - 2026-10-04 + +- Fixed the Hermes live-compression adapter's missing `_coerce_threshold_tokens_cap` + method and lazy context-window/threshold cache invalidation. +- Reused installed Hermes route metadata and per-model threshold handling; current + `select_context` budgets refresh the window without resetting retry/usage state. +- Preserved independent cloned-engine configuration, exact recovery, internal-call + isolation and the existing strict tokenizer acceptance gate. +- Added nine real-Hermes regression cases and corrected their Ruff formatting. +- Updated release/install references and corrected the README's stale context-engine + FAQ. Rust companion version aligned; its runtime behavior is unchanged. +- Unknown-model tokenizers and the host's plugin-discovery race remain separate + limitations; publication does not install or restart a running Hermes profile. + ## 0.11.0 - 2026-09-29 **Context, learning & observability.** Includes the unshipped 0.10.0 milestone; diff --git a/Cargo.toml b/Cargo.toml index ffb9760..8f98d97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "token-terminator" -version = "0.11.0" +version = "0.11.1" edition = "2021" rust-version = "1.78" description = "Rust interoperability helpers for Token Terminator artifact identities and reduction invariants" diff --git a/MIGRATION.md b/MIGRATION.md index 50a1f31..86e2a72 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,3 +1,27 @@ +# Migration to Token Terminator 0.11.1 + +## 0.11.0 to 0.11.1 + +This is the PR #20 Hermes live-compression compatibility repair. No new key, +database migration, tokenizer override or engine-selection change is required. +Upgrade the environment actually used by the managed Hermes launcher, not an +unrelated Python environment or stale venv copy: + +```bash +python -m pip install --upgrade 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' +python -m rtk_hermes_plus.cli install-context-engine +``` + +Confirm the imported `rtk_hermes_plus` path in that environment. When the relevant +backend is idle, restart it once through its normal supervisor; do not start a +competing gateway or delete histories/vaults. Verify the loaded version and +current-model request metrics. A healthy restart or a lower UI percentage alone +does not prove reduction. Unknown target tokenizers still bypass the engine. +See [the compatibility guide](docs/LIVE_COMPRESSION_COMPAT.md). These instructions +do not imply publication performs a live installation or restart. + +--- + # Migration to Token Terminator 0.11.0 ## Optional learned policy diff --git a/README.md b/README.md index a6d1b9a..ac82ffa 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,10 @@

CI - Release v0.11.0 + Release v0.11.1 JEV-powered GitHub Wiki - crates.io + crates.io docs.rs Python 3.10–3.13 MIT License @@ -27,6 +27,19 @@ Token Terminator is an agent-runtime optimization layer. It removes token bloat Documentation: see the [GitHub Wiki](https://github.com/AronAxe/Token-Terminator/wiki) for quick start, architecture, configuration, recovery, security, troubleshooting, migration, and release notes. +## Patch v0.11.1: Hermes live-compression compatibility + +Repairs the missing `_coerce_threshold_tokens_cap` adapter method and live +window/threshold invalidation. The selected TT engine now follows Hermes' +current route budget and isolates cloned engine settings. No new settings, +generative summarizer or relaxed tokenizer gate are introduced. + +For managed/multiplex installs, upgrade the environment that actually imports +TT, then restart the appropriate idle backend through its normal supervisor. +This patch does not add unknown-model tokenizer mappings or fix Hermes' separate +concurrent plugin-discovery race. [Patch notes](docs/releases/v0.11.1.md) · +[Compatibility details](docs/LIVE_COMPRESSION_COMPAT.md). + ## New in v0.11.0 **Context, learning & observability.** This release includes the unshipped 0.10.0 @@ -146,12 +159,12 @@ See [JEV roles and implemented scope](docs/JEV_ROLES.md) and ## Select Token Terminator as the Hermes ContextEngine -Install **v0.11.0** in the Python environment that runs Hermes, then install its +Install **v0.11.1** in the Python environment that runs Hermes, then install its managed adapter. Replace `python` below with that environment's interpreter: ```bash python -m pip install --upgrade \ - 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.0' + 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' python -m rtk_hermes_plus.cli install-context-engine ``` @@ -309,9 +322,9 @@ The optional working-state block defaults to zero characters, even in `balanced` ## Install: Hermes Agent (turnkey) -Token Terminator 0.11.0 builds on v0.9.0 and replaces the earlier `rtk-hermes-plus` distribution. `token-terminator` and `rtk-hermes-plus` must not coexist because both own the `rtk_hermes_plus` Python import package. +Token Terminator 0.11.1 builds on v0.9.0 and replaces the earlier `rtk-hermes-plus` distribution. `token-terminator` and `rtk-hermes-plus` must not coexist because both own the `rtk_hermes_plus` Python import package. -This is the supported zero-glue installation: the repository already contains the Hermes hooks, slash command, recovery tool, and lifecycle accounting. The commands below pin the `v0.11.0` release tag. +This is the supported zero-glue installation: the repository already contains the Hermes hooks, slash command, recovery tool, and lifecycle accounting. The commands below pin the `v0.11.1` release tag. ### 1. Install RTK when using terminal rewriting @@ -333,7 +346,7 @@ HERMES_PY="$HOME/.hermes/hermes-agent/venv/bin/python" hermes plugins disable rtk-plus "$HERMES_PY" -m pip uninstall -y rtk-hermes-plus token-terminator "$HERMES_PY" -m pip install \ - 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.0' + 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' ``` Windows example: @@ -342,7 +355,7 @@ Windows example: $HermesPy = "$env:LOCALAPPDATA\hermes\hermes-agent\venv\Scripts\python.exe" hermes plugins disable rtk-plus & $HermesPy -m pip uninstall -y rtk-hermes-plus token-terminator -& $HermesPy -m pip install "git+https://github.com/AronAxe/Token-Terminator.git@v0.11.0" +& $HermesPy -m pip install "git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1" ``` `tiktoken` now ships with Token Terminator and is used automatically for supported OpenAI-family models, including common provider-qualified model IDs. Hugging Face `tokenizers` remains optional when pointing Token Terminator at a local `tokenizer.json`: @@ -374,7 +387,7 @@ Installation and enablement are separate operations. Disabling affects subsequen Rust agent hosts can use the supported `token-terminator` companion crate for the stable cross-language pieces of the Token Terminator contract: ```bash -cargo add token-terminator@0.11.0 +cargo add token-terminator@0.11.1 ``` ```rust @@ -396,7 +409,7 @@ Install the same distribution in the environment that owns your agent loop: ```bash python -m pip install \ - 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.0' + 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' ``` Then connect your runtime's tool-result and final-request hooks to `Runtime`. The adapter must map equivalent tools to Token Terminator's canonical names (`search_files`, `process`, and optionally `read_file`) and expose `Runtime.tool` to the model for exact recovery. @@ -649,7 +662,7 @@ No. Provider-visible content may be compacted, and `artifact_peek` is deliberate ### Does it replace the host's memory or context engine? -No. Token Terminator operates after or alongside normal context assembly. It does not own the transcript, alter persisted conversation history, or require a particular memory engine. +It can replace the selected **Hermes context engine**, including LCM, when explicitly configured with `context.engine: token-terminator`. Middleware-only mode keeps the host engine upstream. Neither mode replaces the memory system or transcript store, or destructively rewrites persisted conversation history. ### Does enabling Jev turn off the normal Token Terminator pipeline? diff --git a/docs/LIVE_COMPRESSION_COMPAT.md b/docs/LIVE_COMPRESSION_COMPAT.md index 590877f..77c9a17 100644 --- a/docs/LIVE_COMPRESSION_COMPAT.md +++ b/docs/LIVE_COMPRESSION_COMPAT.md @@ -18,11 +18,11 @@ Nine offline regression tests passed against the installed Hermes checkout live-config function with mocked model metadata and disposable stores. They do not claim paid-provider validation or a reduction of an existing live session. -Operational state: applying the tested patch to the live managed installation was -blocked by the remote execution tool. No live adapter replacement or backend restart -was performed. The test candidate is retained separately. A partial older patch -was already present in the managed source; it must not be confused with repository -v0.11.0 or evidence that a running process has loaded a repair. +Release scope: v0.11.1 publishes PR #20's adapter and tests. Earlier incident +deployment notes are historical; a separately deployed adapter snapshot is not +proof that this exact release has loaded in a running process. Installation, +engine discovery and actual current-model request reduction remain separate +checks. This release performs no live installation or backend restart. The observed host directory loader can expose a partially initialized cached module to simultaneous discovery. This adapter patch does not modify that upstream loader @@ -30,3 +30,7 @@ or claim to resolve its race. Deployment must use the host's managed plugin upda path and a controlled backend restart, then check loaded engine identity and actual provider-request metrics. Do not kill unrelated relay/messaging/dashboard processes, delete conversation/vault data, or claim a reset UI percentage proves reduction. + +Unknown target tokenizers still cause ContextEngine/IR to pass through. This +patch does not supply new tokenizer mappings, guess a replacement model window, +or guarantee a reduction in a live session. diff --git a/docs/releases/v0.11.1.md b/docs/releases/v0.11.1.md new file mode 100644 index 0000000..4c1b939 --- /dev/null +++ b/docs/releases/v0.11.1.md @@ -0,0 +1,57 @@ +# Token Terminator v0.11.1 — Hermes live-compression compatibility + +A focused patch release of PR #20. The v0.11.0 ContextEngine, learned JEV policy, +Context IR, exact-evidence vault and Observatory remain in place. + +## Fixed + +- Supply `_coerce_threshold_tokens_cap` for Hermes' live-compression configuration. +- Honor invalidated context-window and threshold caches, explicit pin removal, + current-route metadata and per-model threshold handling. +- Refresh the engine window from the host's current `select_context` budget + without resetting retry bindings or usage counters. +- Keep cloned engines' settings independent. No generative compressor, destructive + history truncation, new key or weakened tokenizer gate is introduced. +- Include nine real-Hermes regression cases and the formatting-only CI correction. + +## Upgrade + +Use the Python environment actually loaded by your managed Hermes launcher: + +```bash +python -m pip install --upgrade 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' +python -m rtk_hermes_plus.cli install-context-engine +``` + +Keep your existing plugin/engine selection and JEV settings. Once idle, restart +only the relevant backend through its normal supervisor. Do not delete the +conversation history or evidence vault. Verify the imported package path, +loaded version and current-model request metrics, not only a UI percentage. + +## Validation and scope + +The formatted PR candidate passed Python 3.10–3.13, Windows, packaging, Rust, +learned-policy, ContextEngine, dashboard and Context IR workflows before release +preparation. The learning artifact reported 611 passed and three skips; one +skip is the whole optional real-Hermes test module. Its nine cases were previously +run locally against installed Hermes `188a1a5` on Python 3.14, not counted as +executed in that learning job. Final release-head CI status is recorded on PR #20. +No paid inference or new performance/answer-quality claims accompany this patch. + +**Not fixed by this patch:** unknown-model tokenizer support and the separate +host plugin-discovery race. Without an exact target tokenizer, ContextEngine/IR +still pass through. This is not a guarantee that an affected live session has +shrunk, and it does not merge the separate deployed-adapter branch. + +README changes are limited to a compatibility note, current install/version +references and correcting the stale FAQ: explicitly selected TT can replace LCM +as Hermes' ContextEngine. Artwork and schematics are unchanged. + +The Rust interoperability companion is version-aligned to 0.11.1 without a Rust +behavior change; it is not the Python runtime. GitHub assets include the wheel, +source distribution and SHA256SUMS. Existing releases remain unchanged. +Publication does not install, configure or restart your running agents. + +[PR #20](https://github.com/AronAxe/Token-Terminator/pull/20) · +[Compatibility guide](https://github.com/AronAxe/Token-Terminator/blob/v0.11.1/docs/LIVE_COMPRESSION_COMPAT.md) · +[Migration](https://github.com/AronAxe/Token-Terminator/blob/v0.11.1/MIGRATION.md) diff --git a/pyproject.toml b/pyproject.toml index 82bd8a7..fa38af8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "token-terminator" -version = "0.11.0" +version = "0.11.1" description = "Fail-open token reduction, exact recovery, and request compilation for Hermes Agent" readme = "README.md" requires-python = ">=3.10" diff --git a/src/rtk_hermes_plus/_version.py b/src/rtk_hermes_plus/_version.py index ae6db5f..fee46bd 100644 --- a/src/rtk_hermes_plus/_version.py +++ b/src/rtk_hermes_plus/_version.py @@ -1 +1 @@ -__version__ = "0.11.0" +__version__ = "0.11.1" From a0ac08e2d6b52dc27a4ef8644b72c9b0aaef4728 Mon Sep 17 00:00:00 2001 From: Aron Bijl Date: Sun, 4 Oct 2026 06:12:04 +0200 Subject: [PATCH 5/5] chore: remove completed patch-release preparation workflow --- .github/workflows/prepare-0.11.1.yml | 220 --------------------------- 1 file changed, 220 deletions(-) delete mode 100644 .github/workflows/prepare-0.11.1.yml diff --git a/.github/workflows/prepare-0.11.1.yml b/.github/workflows/prepare-0.11.1.yml deleted file mode 100644 index 01bc4a5..0000000 --- a/.github/workflows/prepare-0.11.1.yml +++ /dev/null @@ -1,220 +0,0 @@ -name: Prepare approved v0.11.1 metadata - -on: - push: - branches: [fix/hermes-live-compression-compat] - paths: [.github/workflows/prepare-0.11.1.yml] - -permissions: - contents: write - -jobs: - prepare: - if: github.repository == 'AronAxe/Token-Terminator' && github.ref == 'refs/heads/fix/hermes-live-compression-compat' - runs-on: ubuntu-latest - timeout-minutes: 3 - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - name: Update only release metadata and documentation - shell: bash - run: | - set -euo pipefail - test "$GITHUB_REF" = refs/heads/fix/hermes-live-compression-compat - git merge-base --is-ancestor 58b6d6c2af2b9014bce658caf2f6fb0119d0f759 HEAD - python - <<'PY' - from pathlib import Path - import hashlib - - expected = { - 'README.md': '060d1c08b33ac27fa3e0c455d08472296a0ecf1e46ef8b83cd7b634163531a18', - 'MIGRATION.md': 'd0f08d6ce668d045e90aa78ed91223749722797939624e63fcac5239e75f23b4', - 'CHANGELOG.md': '81dac26dc60aaa244ec1c9a61907c8d5cba77ad0e958b3cb00ef5e818a5ea93e', - 'pyproject.toml': '0a4fa5081dde2a87cf02adf00c67238b1d6d5dbdbe298a8d85949b38f1710daf', - 'src/rtk_hermes_plus/_version.py': 'ada32ef5703d2448ef7684e616a70ec3baa1257db8ad80cfed7992e7d4c03be4', - } - for name, digest in expected.items(): - assert hashlib.sha256(Path(name).read_bytes()).hexdigest() == digest, name - - def write(name, text): - Path(name).write_bytes(text.encode('utf-8')) - - for name in ('pyproject.toml', 'Cargo.toml', 'src/rtk_hermes_plus/_version.py'): - text = Path(name).read_text(encoding='utf-8') - assert text.count('"0.11.0"') == 1, name - write(name, text.replace('"0.11.0"', '"0.11.1"')) - - readme = Path('README.md').read_text(encoding='utf-8') - for old, new in ( - ('releases/tag/v0.11.0', 'releases/tag/v0.11.1'), - ('alt="Release v0.11.0"', 'alt="Release v0.11.1"'), - ('badge/release-v0.11.0-', 'badge/release-v0.11.1-'), - ('badge/crates.io-v0.11.0-', 'badge/crates.io-v0.11.1-'), - ('Token-Terminator.git@v0.11.0', 'Token-Terminator.git@v0.11.1'), - ('Install **v0.11.0**', 'Install **v0.11.1**'), - ('Token Terminator 0.11.0 builds on', 'Token Terminator 0.11.1 builds on'), - ('commands below pin the `v0.11.0` release tag', 'commands below pin the `v0.11.1` release tag'), - ('cargo add token-terminator@0.11.0', 'cargo add token-terminator@0.11.1'), - ): - assert old in readme, old - readme = readme.replace(old, new) - old = "No. Token Terminator operates after or alongside normal context assembly. It does not own the transcript, alter persisted conversation history, or require a particular memory engine." - assert old in readme - readme = readme.replace(old, "It can replace the selected **Hermes context engine**, including LCM, when explicitly configured with `context.engine: token-terminator`. Middleware-only mode keeps the host engine upstream. Neither mode replaces the memory system or transcript store, or destructively rewrites persisted conversation history.") - note = '''## Patch v0.11.1: Hermes live-compression compatibility - - Repairs the missing `_coerce_threshold_tokens_cap` adapter method and live - window/threshold invalidation. The selected TT engine now follows Hermes' - current route budget and isolates cloned engine settings. No new settings, - generative summarizer or relaxed tokenizer gate are introduced. - - For managed/multiplex installs, upgrade the environment that actually imports - TT, then restart the appropriate idle backend through its normal supervisor. - This patch does not add unknown-model tokenizer mappings or fix Hermes' separate - concurrent plugin-discovery race. [Patch notes](docs/releases/v0.11.1.md) · - [Compatibility details](docs/LIVE_COMPRESSION_COMPAT.md). - - ''' - # Triple-quoted text is indented only for the workflow's Python block. - import textwrap - readme = readme.replace('## New in v0.11.0\n', textwrap.dedent(note) + '## New in v0.11.0\n', 1) - write('README.md', readme) - - entry = '''## 0.11.1 - 2026-10-04 - - - Fixed the Hermes live-compression adapter's missing `_coerce_threshold_tokens_cap` - method and lazy context-window/threshold cache invalidation. - - Reused installed Hermes route metadata and per-model threshold handling; current - `select_context` budgets refresh the window without resetting retry/usage state. - - Preserved independent cloned-engine configuration, exact recovery, internal-call - isolation and the existing strict tokenizer acceptance gate. - - Added nine real-Hermes regression cases and corrected their Ruff formatting. - - Updated release/install references and corrected the README's stale context-engine - FAQ. Rust companion version aligned; its runtime behavior is unchanged. - - Unknown-model tokenizers and the host's plugin-discovery race remain separate - limitations; publication does not install or restart a running Hermes profile. - - ''' - changelog = Path('CHANGELOG.md').read_text(encoding='utf-8') - assert changelog.startswith('# Changelog\n\n') - write('CHANGELOG.md', '# Changelog\n\n' + textwrap.dedent(entry) + changelog[len('# Changelog\n\n'):]) - - migration = '''# Migration to Token Terminator 0.11.1 - - ## 0.11.0 to 0.11.1 - - This is the PR #20 Hermes live-compression compatibility repair. No new key, - database migration, tokenizer override or engine-selection change is required. - Upgrade the environment actually used by the managed Hermes launcher, not an - unrelated Python environment or stale venv copy: - - ```bash - python -m pip install --upgrade 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' - python -m rtk_hermes_plus.cli install-context-engine - ``` - - Confirm the imported `rtk_hermes_plus` path in that environment. When the relevant - backend is idle, restart it once through its normal supervisor; do not start a - competing gateway or delete histories/vaults. Verify the loaded version and - current-model request metrics. A healthy restart or a lower UI percentage alone - does not prove reduction. Unknown target tokenizers still bypass the engine. - See [the compatibility guide](docs/LIVE_COMPRESSION_COMPAT.md). These instructions - do not imply publication performs a live installation or restart. - - --- - - ''' - write('MIGRATION.md', textwrap.dedent(migration) + Path('MIGRATION.md').read_text(encoding='utf-8')) - - compat = Path('docs/LIVE_COMPRESSION_COMPAT.md').read_text(encoding='utf-8') - start = compat.index('Operational state:') - end = compat.index('The observed host directory loader', start) - compat = compat[:start] + '''Release scope: v0.11.1 publishes PR #20's adapter and tests. Earlier incident - deployment notes are historical; a separately deployed adapter snapshot is not - proof that this exact release has loaded in a running process. Installation, - engine discovery and actual current-model request reduction remain separate - checks. This release performs no live installation or backend restart. - - '''.replace('\n ', '\n') + compat[end:] - compat += '\nUnknown target tokenizers still cause ContextEngine/IR to pass through. This\npatch does not supply new tokenizer mappings, guess a replacement model window,\nor guarantee a reduction in a live session.\n' - write('docs/LIVE_COMPRESSION_COMPAT.md', compat) - - notes = '''# Token Terminator v0.11.1 — Hermes live-compression compatibility - - A focused patch release of PR #20. The v0.11.0 ContextEngine, learned JEV policy, - Context IR, exact-evidence vault and Observatory remain in place. - - ## Fixed - - - Supply `_coerce_threshold_tokens_cap` for Hermes' live-compression configuration. - - Honor invalidated context-window and threshold caches, explicit pin removal, - current-route metadata and per-model threshold handling. - - Refresh the engine window from the host's current `select_context` budget - without resetting retry bindings or usage counters. - - Keep cloned engines' settings independent. No generative compressor, destructive - history truncation, new key or weakened tokenizer gate is introduced. - - Include nine real-Hermes regression cases and the formatting-only CI correction. - - ## Upgrade - - Use the Python environment actually loaded by your managed Hermes launcher: - - ```bash - python -m pip install --upgrade 'git+https://github.com/AronAxe/Token-Terminator.git@v0.11.1' - python -m rtk_hermes_plus.cli install-context-engine - ``` - - Keep your existing plugin/engine selection and JEV settings. Once idle, restart - only the relevant backend through its normal supervisor. Do not delete the - conversation history or evidence vault. Verify the imported package path, - loaded version and current-model request metrics, not only a UI percentage. - - ## Validation and scope - - The formatted PR candidate passed Python 3.10–3.13, Windows, packaging, Rust, - learned-policy, ContextEngine, dashboard and Context IR workflows before release - preparation. The learning artifact reported 611 passed and three skips; one - skip is the whole optional real-Hermes test module. Its nine cases were previously - run locally against installed Hermes `188a1a5` on Python 3.14, not counted as - executed in that learning job. Final release-head CI status is recorded on PR #20. - No paid inference or new performance/answer-quality claims accompany this patch. - - **Not fixed by this patch:** unknown-model tokenizer support and the separate - host plugin-discovery race. Without an exact target tokenizer, ContextEngine/IR - still pass through. This is not a guarantee that an affected live session has - shrunk, and it does not merge the separate deployed-adapter branch. - - README changes are limited to a compatibility note, current install/version - references and correcting the stale FAQ: explicitly selected TT can replace LCM - as Hermes' ContextEngine. Artwork and schematics are unchanged. - - The Rust interoperability companion is version-aligned to 0.11.1 without a Rust - behavior change; it is not the Python runtime. GitHub assets include the wheel, - source distribution and SHA256SUMS. Existing releases remain unchanged. - Publication does not install, configure or restart your running agents. - - [PR #20](https://github.com/AronAxe/Token-Terminator/pull/20) · - [Compatibility guide](https://github.com/AronAxe/Token-Terminator/blob/v0.11.1/docs/LIVE_COMPRESSION_COMPAT.md) · - [Migration](https://github.com/AronAxe/Token-Terminator/blob/v0.11.1/MIGRATION.md) - ''' - notes = textwrap.dedent(notes) - Path('docs/releases').mkdir(exist_ok=True) - assert not Path('docs/releases/v0.11.1.md').exists() - write('docs/releases/v0.11.1.md', notes) - - for name in ('README.md', 'MIGRATION.md', 'CHANGELOG.md'): - text = Path(name).read_text(encoding='utf-8') - assert '0.11.1' in text - for name in expected: - print(name, hashlib.sha256(Path(name).read_bytes()).hexdigest()) - PY - git diff --check - git diff --exit-code 58b6d6c2af2b9014bce658caf2f6fb0119d0f759 -- src/rtk_hermes_plus/hermes_engine.py tests scripts benchmarks docs/assets - git add src/rtk_hermes_plus/_version.py pyproject.toml Cargo.toml README.md MIGRATION.md CHANGELOG.md docs/LIVE_COMPRESSION_COMPAT.md docs/releases/v0.11.1.md - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git commit -m 'release: prepare v0.11.1 Hermes compatibility patch' - git push origin HEAD:refs/heads/fix/hermes-live-compression-compat - git rev-parse HEAD - git rev-parse HEAD^{tree}