phase: 178_split_thinking_levels
## Phase 178 — final verification pass: 100% green
**Verified (all 5 tasks complete in `complete/178_split_thinking_levels/`):**
- `config.py` rename (`llm_chat_thinking_level` default `low`) + new `llm_summary_thinking_level` (default `""`); two `CATALOG` rows; `.env.example` replaced; no stale old-key references (only intentional negative pins in tests)
- Wire split: `chat_stream()` → chat level, one-shot `chat()` → summary level (absent `extra_body` when empty); per-turn line reads chat level only
**Gates:**
- `uv run pytest -k "config and thinking" -v` → 7 passed (defaults + env overrides both knobs)
- `uv run pytest` (unit + integration) → 4170 tests, exit 0; `--cov=app` → **99%** (>90% ✓)
- `uv run ruff check .` clean; `uv run pyright` clean
- `uv run pytest tests/e2e/test_split_thinking_levels.py -v --no-cov` → 3 passed in isolation
- `test_admin_settings_panel.py` + `test_admin_settings_layout.py` → 17 passed in isolation
**Completion criteria:** all 6 test/doc criteria ✅ (admin GET lists both keys, old key gone — integration + E2E pins); commit + phase-dir move = harness's job.
**Documentation:** README.md — both new env vars correctly documented in the LLM (aipi) table with defaults/wire-mapping/off-rule, defaults match `config.py`, all `.env.example` vars covered: verified consistent, no changes needed. AGENTS.md — all referenced files/commands verified to exist, no phase-178 impact (no UI code change, A4): verified consistent, no changes needed.
**Decisions:** none required — no live changes made (E2E booted its own app subprocess against the existing DB).
**Next pending phase:** none — 178 is the last phase in `todo/`.
This commit is contained in:
@@ -1550,8 +1550,13 @@ def test_endpoint_log_line_records_suggested_after_summary_hits(
|
||||
seeded suggestion tier's size (``len(plan.suggested_docs)``).
|
||||
Phase 172 (A6): the line gains ``thinking=<level>`` immediately
|
||||
BEFORE ``thinking_chars=N`` — the effective (overlay-resolved)
|
||||
``BOR_LLM_THINKING_LEVEL``, trimmed, ``-`` when empty (the off
|
||||
switch)."""
|
||||
``BOR_LLM_CHAT_THINKING_LEVEL`` (the chat level), trimmed,
|
||||
``-`` when empty (the off switch).
|
||||
Phase 178 (A5): the field stays pinned to the CHAT level — the
|
||||
level the turn actually ran at; the one-shot summary level
|
||||
(``llm_summary_thinking_level``, a different knob) is never read
|
||||
by the line and must not leak into the line's ``thinking=``
|
||||
value (cross-pin + inverse off-pin below)."""
|
||||
_session, _llm = gate_env
|
||||
doc = _doc("Kubernetes Homelab Cluster", "TALOS_DOC_SENT")
|
||||
chunks = [_chunk(doc, 0.30), _chunk(doc, 0.20, is_summary=True)]
|
||||
@@ -1606,7 +1611,7 @@ def test_endpoint_log_line_records_suggested_after_summary_hits(
|
||||
monkeypatch.setattr(
|
||||
chat_api,
|
||||
"get_settings",
|
||||
lambda: Settings(_env_file=None, relevance_threshold=0.30, llm_thinking_level="high"), # pyright: ignore[reportCallIssue]
|
||||
lambda: Settings(_env_file=None, relevance_threshold=0.30, llm_chat_thinking_level="high"), # pyright: ignore[reportCallIssue]
|
||||
)
|
||||
line = _last_log_line()
|
||||
assert "thinking=high thinking_chars=" in line
|
||||
@@ -1615,7 +1620,7 @@ def test_endpoint_log_line_records_suggested_after_summary_hits(
|
||||
monkeypatch.setattr(
|
||||
chat_api,
|
||||
"get_settings",
|
||||
lambda: Settings(_env_file=None, relevance_threshold=0.30, llm_thinking_level=""), # pyright: ignore[reportCallIssue]
|
||||
lambda: Settings(_env_file=None, relevance_threshold=0.30, llm_chat_thinking_level=""), # pyright: ignore[reportCallIssue]
|
||||
)
|
||||
line = _last_log_line()
|
||||
assert "thinking=- thinking_chars=" in line
|
||||
@@ -1625,7 +1630,42 @@ def test_endpoint_log_line_records_suggested_after_summary_hits(
|
||||
monkeypatch.setattr(
|
||||
chat_api,
|
||||
"get_settings",
|
||||
lambda: Settings(_env_file=None, relevance_threshold=0.30, llm_thinking_level=" "), # pyright: ignore[reportCallIssue]
|
||||
lambda: Settings(_env_file=None, relevance_threshold=0.30, llm_chat_thinking_level=" "), # pyright: ignore[reportCallIssue]
|
||||
)
|
||||
line = _last_log_line()
|
||||
assert "thinking=- thinking_chars=" in line
|
||||
|
||||
# Phase 178 (A5) cross-pin: the line is pinned to the CHAT level
|
||||
# — with the one-shot summary level set to a DIFFERENT value,
|
||||
# the line still shows the chat level; the summary's "high"
|
||||
# does not appear as the line's ``thinking=`` value.
|
||||
monkeypatch.setattr(
|
||||
chat_api,
|
||||
"get_settings",
|
||||
lambda: Settings(
|
||||
_env_file=None, # pyright: ignore[reportCallIssue]
|
||||
relevance_threshold=0.30,
|
||||
llm_chat_thinking_level="low",
|
||||
llm_summary_thinking_level="high",
|
||||
),
|
||||
)
|
||||
line = _last_log_line()
|
||||
assert "thinking=low thinking_chars=" in line
|
||||
assert "thinking=high" not in line
|
||||
|
||||
# The inverse off-pin: the chat off-switch logs ``-`` even
|
||||
# though the one-shot summary knob is set — only the chat level
|
||||
# (the level this turn ran at) rides the line.
|
||||
monkeypatch.setattr(
|
||||
chat_api,
|
||||
"get_settings",
|
||||
lambda: Settings(
|
||||
_env_file=None, # pyright: ignore[reportCallIssue]
|
||||
relevance_threshold=0.30,
|
||||
llm_chat_thinking_level="",
|
||||
llm_summary_thinking_level="high",
|
||||
),
|
||||
)
|
||||
line = _last_log_line()
|
||||
assert "thinking=- thinking_chars=" in line
|
||||
assert "thinking=high" not in line
|
||||
|
||||
Reference in New Issue
Block a user