라이브코치 소스팩 새로고침 보강

This commit is contained in:
Yun Chan 2026-06-28 23:52:55 +09:00
parent 84599bbaa2
commit 1e9f293fda
5 changed files with 182 additions and 8 deletions

View file

@ -2,7 +2,10 @@
from __future__ import annotations
import json
import tempfile
import unittest
from pathlib import Path
from typing import Any
from unittest.mock import AsyncMock, patch
@ -24,6 +27,59 @@ class _SourcePackConn:
class LiveCoachSourcePackTest(unittest.TestCase):
def test_manifest_refresh_reads_changed_repo_source_pack_after_cache_warm(self) -> None:
with tempfile.TemporaryDirectory() as temp_root:
root = Path(temp_root)
workbook_path = root / "live_coaching_workbook_0615.json"
source_dir = root / "live_coaching_sources"
source_dir.mkdir()
def write_workbook(summary: str) -> None:
workbook_path.write_text(
json.dumps(
{
"source": {
"source_id": "source-a",
"title": "Source A",
"kb_kind": "theory",
"license_class": "A",
"citation": "source-a",
"external_llm_ok": True,
},
"chunks": [
{
"id": "chunk-a",
"summary": summary,
"citation": "source-a",
"visible_to": ["evaluator"],
}
],
},
ensure_ascii=False,
),
encoding="utf-8",
)
with (
patch.object(live_coach, "_REPO_ROOT", root),
patch.object(live_coach, "_WORKBOOK_PATH", workbook_path),
patch.object(live_coach, "_SOURCE_DIR", source_dir),
):
live_coach.clear_local_source_pack_cache()
write_workbook("first source pack summary")
_, first_payloads = source_pack_sync.build_repo_source_pack_manifest(refresh=True)
first_hash = first_payloads[0]["content_hash"]
write_workbook("changed source pack summary")
_, stale_payloads = source_pack_sync.build_repo_source_pack_manifest()
self.assertEqual(stale_payloads[0]["content_hash"], first_hash)
_, refreshed_payloads = source_pack_sync.build_repo_source_pack_manifest(refresh=True)
self.assertNotEqual(refreshed_payloads[0]["content_hash"], first_hash)
self.assertEqual(refreshed_payloads[0]["chunks"][0]["chunk_text"], "changed source pack summary")
live_coach.clear_local_source_pack_cache()
def test_source_packs_build_rag_rows_and_index_payloads(self) -> None:
rows = live_coach.build_rag_source_rows()
payloads = live_coach.build_rag_index_payloads()
@ -85,6 +141,91 @@ class RagIndexPolicyTest(unittest.IsolatedAsyncioTestCase):
class RepoSourcePackSyncTest(unittest.IsolatedAsyncioTestCase):
async def test_sync_refresh_after_file_change_reports_next_document_version(self) -> None:
with tempfile.TemporaryDirectory() as temp_root:
root = Path(temp_root)
workbook_path = root / "live_coaching_workbook_0615.json"
source_dir = root / "live_coaching_sources"
source_dir.mkdir()
def write_workbook(summary: str) -> None:
workbook_path.write_text(
json.dumps(
{
"source": {
"source_id": "source-a",
"title": "Source A",
"kb_kind": "theory",
"license_class": "A",
"citation": "source-a",
"external_llm_ok": True,
},
"chunks": [
{
"id": "chunk-a",
"summary": summary,
"citation": "source-a",
"visible_to": ["evaluator"],
}
],
},
ensure_ascii=False,
),
encoding="utf-8",
)
with (
patch.object(live_coach, "_REPO_ROOT", root),
patch.object(live_coach, "_WORKBOOK_PATH", workbook_path),
patch.object(live_coach, "_SOURCE_DIR", source_dir),
):
live_coach.clear_local_source_pack_cache()
write_workbook("first source pack summary")
_, first_payloads = source_pack_sync.build_repo_source_pack_manifest(refresh=True)
first_payload = first_payloads[0]
write_workbook("changed source pack summary")
conn = _SourcePackConn(
{
("source-a", first_payload["doc_uri"]): {
"doc_id": 10,
"version": 2,
"content_hash": first_payload["content_hash"],
}
}
)
result = await source_pack_sync.sync_repo_source_packs(conn, apply=False, refresh=True)
self.assertFalse(result.applied)
self.assertEqual(result.items[0].previous_version, 2)
self.assertEqual(result.items[0].new_version, 3)
self.assertFalse(result.items[0].skipped_unchanged)
self.assertNotEqual(result.items[0].content_hash, first_payload["content_hash"])
live_coach.clear_local_source_pack_cache()
def test_manifest_refresh_invalidates_live_coach_source_cache(self) -> None:
with (
patch.object(source_pack_sync.live_coach, "clear_local_source_pack_cache") as clear_cache,
patch.object(source_pack_sync.live_coach, "build_rag_source_rows", return_value=[]) as build_rows,
patch.object(source_pack_sync.live_coach, "build_rag_index_payloads", return_value=[]) as build_payloads,
):
source_pack_sync.build_repo_source_pack_manifest(refresh=True)
clear_cache.assert_called_once_with()
build_rows.assert_called_once_with()
build_payloads.assert_called_once_with()
def test_manifest_default_reuses_live_coach_source_cache(self) -> None:
with (
patch.object(source_pack_sync.live_coach, "clear_local_source_pack_cache") as clear_cache,
patch.object(source_pack_sync.live_coach, "build_rag_source_rows", return_value=[]),
patch.object(source_pack_sync.live_coach, "build_rag_index_payloads", return_value=[]),
):
source_pack_sync.build_repo_source_pack_manifest()
clear_cache.assert_not_called()
def _patch_manifest(self) -> Any:
row = {
"source_id": "source-a",