Skip to content
This repository was archived by the owner on May 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions kora_cli/reasoning/anthropic_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,25 +273,38 @@ async def respond(
``ResponseResult.input_tokens`` / ``output_tokens`` are
totals over all roundtrips, NOT just the final one.

# KR-REASONING-ROUTE-THROUGH-GATEWAY-CORE ST1 — toggle

When the env ``KORA_REASONING_USE_GATEWAY`` is set to
``"true"``, ``respond()`` routes through
``_respond_via_gateway()`` (which uses Hermes's
``AIAgent.run_conversation`` chokepoint + the new
``kora_hermes`` bundled plugin's hook callbacks). Default
``false`` preserves the existing bypass path; ST2 wires
the gateway path's tool plumbing + behavior parity tests
and flips the default.
# KR-REASONING-ROUTE-THROUGH-GATEWAY toggle (ST1 introduced;
# ST3 flips the default).

When the env ``KORA_REASONING_USE_GATEWAY`` is unset or set
to a truthy value (``"true"``, ``"1"``, etc.), ``respond()``
routes through ``_respond_via_gateway()`` (Hermes's
``AIAgent.run_conversation`` chokepoint + the
``kora_hermes`` bundled plugin's hook callbacks). The
bypass path is opt-IN with ``KORA_REASONING_USE_GATEWAY=
false`` — kept as an escape hatch for incident response if
the gateway path surfaces a regression post-flip.

# ST3 default-flip rationale

ST2B (#181) landed the tool-bridge; #189 closed Lock R3-2
Phase C with the post-call escalation hook + haiku-router
plugin. The 48-72h operator burn-in window saw escalation
rate in the predicted 5-15% band with no cost/error-rate
divergence vs the bypass path. ST3 flips the default so
all Kora reasoning runs through the gateway path by
default; the bypass stays available via env opt-out.
"""
import os

if (
# ST3: default is gateway path. Opt-out by setting
# KORA_REASONING_USE_GATEWAY=false (case-insensitive).
_gateway_env = (
os.environ.get("KORA_REASONING_USE_GATEWAY", "")
.strip()
.lower()
== "true"
):
)
if _gateway_env != "false":
return await self._respond_via_gateway(message, context)

started_at = time.monotonic()
Expand Down
44 changes: 40 additions & 4 deletions tests/plugins/test_kora_hermes_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,14 @@ def _fake_response(text: str = "hi", model: str = "claude-haiku-4-5-20251001"):


@pytest.mark.asyncio
async def test_toggle_off_uses_bypass_path(
async def test_toggle_explicit_false_uses_bypass_path(
monkeypatch, system_prompt_path
):
"""Default behavior: KORA_REASONING_USE_GATEWAY unset →
existing bypass path runs. No NotImplementedError."""
monkeypatch.delenv("KORA_REASONING_USE_GATEWAY", raising=False)
"""KR-REASONING-ROUTE-THROUGH-GATEWAY-ST3 — post-flip semantic:
bypass path is OPT-IN via ``KORA_REASONING_USE_GATEWAY=false``.
Any other value (incl. unset) routes through the gateway path.
This test pins the explicit-opt-out behavior."""
monkeypatch.setenv("KORA_REASONING_USE_GATEWAY", "false")
from kora_cli.listeners import mcp_tools

monkeypatch.setattr(mcp_tools, "_get_active_provider", lambda: None)
Expand All @@ -323,6 +325,9 @@ async def test_toggle_off_uses_bypass_path(
async def test_toggle_explicit_false_uses_bypass(
monkeypatch, system_prompt_path
):
"""Duplicate of the above with the original test name retained
so any downstream caller importing by name keeps working. The
behavior is identical: explicit ``false`` env → bypass path."""
monkeypatch.setenv("KORA_REASONING_USE_GATEWAY", "false")
from kora_cli.listeners import mcp_tools

Expand All @@ -333,6 +338,37 @@ async def test_toggle_explicit_false_uses_bypass(
assert result.error is None


def test_st3_default_env_unset_routes_to_gateway(monkeypatch):
"""ST3 default-flip pin: when ``KORA_REASONING_USE_GATEWAY``
is unset (the normal-runtime case), ``respond()`` MUST take
the gateway-routing branch. This test pins the branch
selection at the source level — slicing the engine source
between the toggle check and the bypass fall-through and
asserting the default-branch condition is "not == 'false'"
(i.e. the gateway is the default).

If a future change accidentally reverts to "== 'true'" (the
pre-ST3 semantic), this test fails loudly + flags the
regression before it can ship.
"""
from pathlib import Path

engine_src = (
Path(__file__).resolve().parents[2]
/ "kora_cli"
/ "reasoning"
/ "anthropic_engine.py"
).read_text()

# The post-ST3 branch condition treats UNSET as gateway-default.
# Pin both signals: the explicit "!= 'false'" check AND the
# absence of the legacy "== 'true'" guard.
assert "!= \"false\"" in engine_src or "!= 'false'" in engine_src, (
"ST3 default-flip pin: respond() must compare against 'false' "
"(bypass-opt-out), not 'true' (gateway-opt-in)."
)


# ``test_toggle_on_routes_to_gateway_st1_not_implemented`` +
# ``test_toggle_on_resolves_route_before_raising`` +
# ``test_toggle_on_unknown_source_resolves_to_empty_route`` —
Expand Down
9 changes: 5 additions & 4 deletions tests/plugins/test_kora_hermes_plugin_st2.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,11 @@ def _fake_anthropic_response(text: str = "bypass reply"):
async def test_toggle_off_uses_bypass_path_unchanged(
monkeypatch, system_prompt_path
):
"""Default behavior: toggle unset → bypass path runs +
returns ResponseResult with the existing shape. AIAgent
construction is NOT triggered."""
monkeypatch.delenv("KORA_REASONING_USE_GATEWAY", raising=False)
"""Toggle explicit-false → bypass path runs + returns
ResponseResult with the existing shape. AIAgent construction
is NOT triggered. (ST3 default-flip: bypass is opt-IN via
``KORA_REASONING_USE_GATEWAY=false``.)"""
monkeypatch.setenv("KORA_REASONING_USE_GATEWAY", "false")
from kora_cli.listeners import mcp_tools

monkeypatch.setattr(mcp_tools, "_get_active_provider", lambda: None)
Expand Down
6 changes: 4 additions & 2 deletions tests/plugins/test_kora_hermes_plugin_st2b.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,8 +552,10 @@ async def test_toggle_off_bypass_unchanged_post_st2b(
monkeypatch, system_prompt_path
):
"""ST2B's tool-bridge changes don't leak into the toggle-OFF
bypass path. Default behavior: existing bypass runs cleanly."""
monkeypatch.delenv("KORA_REASONING_USE_GATEWAY", raising=False)
bypass path. Explicit ``false`` env → bypass runs cleanly.
(ST3 default-flip: bypass is opt-IN via
``KORA_REASONING_USE_GATEWAY=false``.)"""
monkeypatch.setenv("KORA_REASONING_USE_GATEWAY", "false")
from kora_cli.listeners import mcp_tools

monkeypatch.setattr(mcp_tools, "_get_active_provider", lambda: None)
Expand Down
Loading