Phase 3.5 cleanup: 17-item backlog burndown #5

Merged
dohertj2 merged 33 commits from phase-3.5 into main 2026-04-27 01:56:29 -04:00
2 changed files with 56 additions and 1 deletions
Showing only changes of commit 9d06eaf57a - Show all commits
+8 -1
View File
@@ -29,6 +29,7 @@ keeps moving.
from __future__ import annotations from __future__ import annotations
import json import json
import logging
import uuid import uuid
from datetime import datetime, timezone from datetime import datetime, timezone
from sqlite3 import Connection from sqlite3 import Connection
@@ -39,6 +40,8 @@ from chat.eventlog.log import append_and_apply
from chat.llm.classify import classify from chat.llm.classify import classify
from chat.llm.client import LLMClient from chat.llm.client import LLMClient
_log = logging.getLogger(__name__)
class ScenePOVSummary(BaseModel): class ScenePOVSummary(BaseModel):
"""Classifier output: one witness's view of a closing scene. """Classifier output: one witness's view of a closing scene.
@@ -589,7 +592,11 @@ async def apply_scene_close_summary(
open_threads=list_open_threads(conn, chat_id), open_threads=list_open_threads(conn, chat_id),
timeout_s=timeout_s, timeout_s=timeout_s,
) )
except Exception: except Exception as exc:
# T80.3: log the swallowed exception at DEBUG so a
# programmer-error flap (e.g. wrong kwarg name) surfaces in
# local logs without breaking the close pipeline.
_log.debug("detect_threads failed: %s", exc, exc_info=True)
from chat.services.thread_detection import ThreadDetectionResult from chat.services.thread_detection import ThreadDetectionResult
thread_result = ThreadDetectionResult() thread_result = ThreadDetectionResult()
+48
View File
@@ -1625,3 +1625,51 @@ async def test_thread_detection_uses_scene_scoped_transcript(
joined = " ".join(t.get("text", "") for t in scene_two_transcript) joined = " ".join(t.get("text", "") for t in scene_two_transcript)
assert "SCENE_TWO" in joined assert "SCENE_TWO" in joined
assert "SCENE_ONE" not in joined assert "SCENE_ONE" not in joined
@pytest.mark.asyncio
async def test_detect_threads_failure_is_logged(tmp_path, monkeypatch, caplog):
"""T80.3: when ``detect_threads`` raises, the broad except must log
the failure at DEBUG so a programmer-error flap surfaces in local
logs even though the close pipeline keeps moving."""
import logging
from chat.services import thread_detection as td_mod
canned = json.dumps(
{
"summary": "BotA had a quick chat.",
"knowledge_facts": [],
"relationship_summary": "Steady.",
}
)
async def boom(client, **kwargs):
raise RuntimeError("test-detect-threads-boom")
monkeypatch.setattr(td_mod, "detect_threads", boom)
db = tmp_path / "t.db"
apply_migrations(db)
with open_db(db) as conn:
_seed_single_bot_scene(conn)
project(conn)
caplog.set_level(logging.DEBUG, logger="chat.services.scene_summarize")
client = MockLLMClient(canned=[canned])
# Close should NOT raise even though detect_threads did.
await apply_scene_close_summary(
conn,
client,
classifier_model="x",
chat_id="chat_bot_a",
scene_id=1,
host_bot_id="bot_a",
)
# Log carries the error message.
assert any(
"detect_threads failed" in rec.message
and "test-detect-threads-boom" in rec.message
for rec in caplog.records
), [r.message for r in caplog.records]