Pre-cleanup before extending intent classification. Extracts
``ChatRuntime._maybe_apply_discourse_planner(text, source_tag) ->
str | None`` and replaces the two duplicated blocks (cold-start
pack-grounded branch + warm post-walk branch) with single-line
``planned = ...; if planned is not None: assign`` call sites.
Signature locked: takes only the prompt and the already-classified
grounding source tag; returns the replacement surface or None.
Callers own assignment — the helper neither reads nor writes any
surface or articulation state. The warm site additionally does the
``articulation = replace(articulation, surface=planned)`` follow-up
which the cold site does not need.
Gating discipline unchanged (re-pinned in 9 new tests):
* Returns None when ``self.config.discourse_planner`` is False.
* Returns None unless source_tag ∈ {"pack", "teaching"}.
* Returns None when the classified intent has no subject.
* Returns None on single-move plans (BRIEF mode / empty bundle).
* Returns None on empty rendered string.
Behavior is byte-identical to the pre-dedup state — same metrics:
flag off: multi=0.1429, primed_multi=0.0000, conn=0.0769
flag on : multi=0.5238, primed_multi=0.5000, conn=0.2308
cognition eval byte-identical: public 100/100/91.7/100.
smoke suite 67/67.
The two paths now cannot drift; the upcoming intent classifier
extension lifts both branches in lockstep.
69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
"""Tests for ``ChatRuntime._maybe_apply_discourse_planner``.
|
|
|
|
Pins the single-helper contract that the cold and warm runtime hooks
|
|
both call. These tests are unit-level — they exercise the helper
|
|
directly with a real ``ChatRuntime``, without driving the full
|
|
``chat`` pipeline.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from chat.runtime import ChatRuntime
|
|
from core.config import RuntimeConfig
|
|
|
|
|
|
@pytest.fixture()
|
|
def runtime_flag_off() -> ChatRuntime:
|
|
return ChatRuntime(config=RuntimeConfig(discourse_planner=False))
|
|
|
|
|
|
@pytest.fixture()
|
|
def runtime_flag_on() -> ChatRuntime:
|
|
return ChatRuntime(config=RuntimeConfig(discourse_planner=True))
|
|
|
|
|
|
class TestPlannerHelperGating:
|
|
def test_flag_off_returns_none(self, runtime_flag_off: ChatRuntime) -> None:
|
|
result = runtime_flag_off._maybe_apply_discourse_planner(
|
|
"Tell me about truth.", "teaching"
|
|
)
|
|
assert result is None
|
|
|
|
@pytest.mark.parametrize("tag", ["vault", "none", "oov", "", "unknown"])
|
|
def test_non_grounded_source_returns_none(
|
|
self, runtime_flag_on: ChatRuntime, tag: str
|
|
) -> None:
|
|
result = runtime_flag_on._maybe_apply_discourse_planner(
|
|
"Tell me about truth.", tag
|
|
)
|
|
assert result is None
|
|
|
|
def test_empty_subject_returns_none(self, runtime_flag_on: ChatRuntime) -> None:
|
|
# An unclassified prompt has no head-noun subject.
|
|
result = runtime_flag_on._maybe_apply_discourse_planner("", "pack")
|
|
assert result is None
|
|
|
|
|
|
class TestPlannerHelperEngagement:
|
|
def test_returns_multi_clause_surface_on_grounded_subject(
|
|
self, runtime_flag_on: ChatRuntime
|
|
) -> None:
|
|
result = runtime_flag_on._maybe_apply_discourse_planner(
|
|
"Tell me about truth.", "teaching"
|
|
)
|
|
assert result is not None
|
|
# Multi-clause: at least one connective from the canonical table.
|
|
assert "Furthermore," in result or "In turn," in result
|
|
|
|
def test_returns_none_for_single_move_plan(
|
|
self, runtime_flag_on: ChatRuntime
|
|
) -> None:
|
|
# BRIEF mode (default for "What is X?") collapses to ANCHOR-only;
|
|
# helper must return None so callers don't replace the byte-
|
|
# identical single-sentence pack-grounded surface.
|
|
result = runtime_flag_on._maybe_apply_discourse_planner(
|
|
"What is truth?", "pack"
|
|
)
|
|
assert result is None
|