The persona prompt was built from the raw OUTPUT_LANGUAGE env while the reply-language directive read the settings-web UI value (config JSON), so changing the language in the settings page was honoured by the directive but ignored by the persona, leaving them contradicting each other. Add _resolve_output_language() as the single source of truth (config wins over env) and feed the same resolved value to both build_system_prompt() and reply_language_directive(). Update docs/llm_contexts.md to match. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
75 lines
3.0 KiB
Python
75 lines
3.0 KiB
Python
"""The locked reply language must have a single source of truth.
|
|
|
|
Regression: the persona prompt was built from the raw ``OUTPUT_LANGUAGE`` env
|
|
while the reply-language directive read the settings-UI value (config JSON).
|
|
Changing the language in the settings page rewrote the directive but left the
|
|
persona contradicting it. ``_resolve_output_language`` is now the one resolver
|
|
both call sites use, so they cannot diverge.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_settings_value_wins_over_env(monkeypatch, tmp_path):
|
|
from jarvis.reply.engine import _resolve_output_language
|
|
|
|
cfg_path = tmp_path / "config.json"
|
|
cfg_path.write_text('{"output_language": "Korean"}', encoding="utf-8")
|
|
monkeypatch.setenv("JARVIS_CONFIG_PATH", str(cfg_path))
|
|
monkeypatch.setenv("OUTPUT_LANGUAGE", "English")
|
|
|
|
# The settings page value must take effect over the compose env default.
|
|
assert _resolve_output_language() == "Korean"
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_env_used_when_settings_absent(monkeypatch, tmp_path):
|
|
from jarvis.reply.engine import _resolve_output_language
|
|
|
|
cfg_path = tmp_path / "config.json"
|
|
cfg_path.write_text("{}", encoding="utf-8")
|
|
monkeypatch.setenv("JARVIS_CONFIG_PATH", str(cfg_path))
|
|
monkeypatch.setenv("OUTPUT_LANGUAGE", "English")
|
|
|
|
assert _resolve_output_language() == "English"
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_unset_when_neither_configured(monkeypatch, tmp_path):
|
|
from jarvis.reply.engine import _resolve_output_language
|
|
|
|
cfg_path = tmp_path / "config.json"
|
|
cfg_path.write_text("{}", encoding="utf-8")
|
|
monkeypatch.setenv("JARVIS_CONFIG_PATH", str(cfg_path))
|
|
monkeypatch.delenv("OUTPUT_LANGUAGE", raising=False)
|
|
|
|
# Empty string or None both mean "no lock" downstream; normalise the check.
|
|
assert not _resolve_output_language()
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_persona_and_directive_agree_on_settings_value(monkeypatch, tmp_path):
|
|
"""End-to-end: the same resolved value feeds the persona and the directive,
|
|
so a settings-UI language can't be honoured by one and ignored by the other.
|
|
"""
|
|
from jarvis.reply.engine import _resolve_output_language
|
|
from jarvis.system_prompt import build_system_prompt, reply_language_directive
|
|
|
|
cfg_path = tmp_path / "config.json"
|
|
cfg_path.write_text('{"output_language": "Korean"}', encoding="utf-8")
|
|
monkeypatch.setenv("JARVIS_CONFIG_PATH", str(cfg_path))
|
|
monkeypatch.setenv("OUTPUT_LANGUAGE", "English")
|
|
|
|
lang = _resolve_output_language()
|
|
persona = build_system_prompt("Jarvis", lang)
|
|
directive = reply_language_directive(lang, "melo")
|
|
|
|
# Persona's user-language clause is rewritten to Korean, not English...
|
|
assert "in Korean" in persona
|
|
assert "in English" not in persona
|
|
# ...and the directive locks to the same Korean. (The directive may name
|
|
# English as a counter-example - "even if the user writes in English" - so
|
|
# we assert the lock target, not the mere absence of the word "English".)
|
|
assert directive is not None and "Korean" in directive
|