"""kb_block 注入契约:零库冷启动 vs 有库全量。

背景(2026-07-24):零库时 kb_block 返回空串,agent 不知道 KB 机制存在,用户说
「放进我的知识库」被就近写进 .memory/。修复 = 零库注极简冷启动契约(建库步骤 +
INDEX 行格式 + 知识库/记忆分工),与 memory 空契约常驻同一课。本测试锁住两个分支。
"""
from __future__ import annotations

import sys
import tempfile
import unittest
from pathlib import Path
from uuid import UUID

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from core.kb import (  # noqa: E402
    INDEX_LINE_FORMAT,
    create_kb,
    format_index_line,
    kb_block,
)

_UID = UUID("6b14d2ab-7a6e-4d0b-8562-ea62a801e32c")


class TestKbBlock(unittest.TestCase):
    def setUp(self):
        self.ws = Path(tempfile.mkdtemp()) / "workspace"

    def test_cold_start_injects_minimal_contract(self):
        block = kb_block(self.ws, _UID, "/workspace/.kb")
        # 机制存在 + 建库/入库指引 + 行格式契约都在
        self.assertIn("个人知识库", block)
        self.assertIn("还没有任何知识库", block)
        self.assertIn("/workspace/.kb/<库名>/docs/", block)
        self.assertIn(INDEX_LINE_FORMAT, block)
        # 与记忆的分工写明(误写 .memory 正是要防的失败模式)
        self.assertIn("短事实才写记忆", block)
        # 冷启动块不含任何库清单
        self.assertNotIn("### 库「", block)

    def test_cold_start_host_path_display(self):
        block = kb_block(self.ws, _UID, None)
        root = self.ws / "users" / str(_UID) / ".kb"
        self.assertIn(str(root), block)

    def test_with_kb_injects_full_index(self):
        d = create_kb(self.ws, _UID, "标准库")
        assert d is not None
        line = format_index_line(
            title="水泥胶砂强度检验方法",
            doc="docs/gbt17671.md",
            source="sources/gbt17671.pdf",
            summary="ISO 法测定水泥胶砂抗压抗折强度。",
            keywords="水泥,强度,GB/T 17671",
        )
        (d / "INDEX.md").write_text(f"# 标准库\n\n{line}\n", encoding="utf-8")
        block = kb_block(self.ws, _UID, "/workspace/.kb")
        # 全量分支:库清单 + 条目 + 完整契约(对话内入库段)
        self.assertIn("### 库「标准库」", block)
        self.assertIn("水泥胶砂强度检验方法", block)
        self.assertIn("对话内入库", block)
        # 冷启动文案不应出现
        self.assertNotIn("还没有任何知识库", block)

    def test_empty_kb_counts_as_having_kb(self):
        # 建了库但零文档:走全量分支(注库名 + 空库提示),不再是冷启动
        create_kb(self.ws, _UID, "新库")
        block = kb_block(self.ws, _UID, "/workspace/.kb")
        self.assertIn("### 库「新库」", block)
        self.assertIn("空库", block)
        self.assertNotIn("还没有任何知识库", block)


if __name__ == "__main__":
    unittest.main()
