tests/test_daily_summary.py
Rama main · réplica de lectura del repositorio original.
from __future__ import annotations
import importlib
import sys
import unittest
from pathlib import Path
from unittest import mock
ROOT = Path(__file__).resolve().parents[1]
SCRIPTS = ROOT / "scripts"
if str(SCRIPTS) not in sys.path:
sys.path.insert(0, str(SCRIPTS))
class DailySummaryTests(unittest.TestCase):
"""訊息第一行就要回答「這是我要處理的嗎」。
原本的分法是「故障 vs 待辦」,而待辦 = 堆積。2026-09-12 發現那個分法是錯的:
堆積有兩種。治理追不上是**故障**(系統自己該做的事做不完),而「要不要開一個
新的 wiki 主題」才是**只有 Pan 能決定**的那種。
舊分法把整個 governance_actionable section 當成決定類,於是「吸收追不上」每天
被寫成「請你審核 180 筆」——實測那 180 筆裡 106 筆是 safe_promotion,一筆都不
需要人。叫人決定一件系統自己會做的事,是這則訊息會被停止閱讀的直接原因。
現在:追不上算故障,proposal / overdue 才進「等你決定」。
"""
@classmethod
def setUpClass(cls) -> None:
cls.notify = importlib.import_module("health_check_notify")
def _build(self, sections, failures):
# Inventory reads the live workspace; not what these tests are about.
with mock.patch.object(self.notify, "_inventory_lines", return_value=[]):
return self.notify.build_message(sections, failures)
def _governance(self, **counts):
return {"name": "governance_actionable", "checks": [], "actionable_counts": counts}
def test_all_clear(self) -> None:
self.assertTrue(self._build([], []).startswith("XKB 一切正常"))
def test_proposals_alone_are_a_decision_not_a_fault(self) -> None:
"""只有「要不要開新主題」時,不該說壞掉——那真的只有 Pan 能決定。"""
message = self._build(
[self._governance(pending=226, proposal=153, quarantine=23)], [])
self.assertTrue(message.startswith("XKB 運作正常,有事情等你決定"))
self.assertIn("153 條想開新的 wiki 主題", message)
self.assertNotIn("壞掉了", message)
def test_falling_behind_is_a_fault_not_a_decision(self) -> None:
"""治理吸收追不上是故障,不是待辦。
這個測試原本斷言相反的事(「堆積不算壞掉」),而那個分法讓「追不上」
每天被寫成「請你審核」。追不上是系統做不完自己該做的事,那是故障;
要人決定的只有提案。
"""
message = self._build(
[self._governance(pending=226, proposal=0)],
[("governance_actionable", "治理每天吸收 20 筆、進來 35 筆——追不上")],
)
self.assertTrue(message.startswith("XKB 有 1 個地方壞了"), message)
self.assertIn("治理吸收追不上", message) # 可讀標籤,不是內部識別字
self.assertNotIn("等你決定", message)
def test_a_fault_and_a_decision_are_both_reported(self) -> None:
message = self._build(
[self._governance(pending=226, proposal=153)],
[("conversation_capture", "0/5 sessions recorded turns")],
)
self.assertTrue(message.startswith("XKB 有 1 個地方壞了"), message)
self.assertIn("對話沒有被記錄下來", message)
self.assertIn("等你決定", message)
self.assertIn("153 條想開新的 wiki 主題", message)
def test_raw_section_names_do_not_reach_the_reader(self) -> None:
message = self._build([], [("conversation_capture", "0/5 sessions recorded turns")])
self.assertNotIn("conversation_capture", message.split("\\n")[0])
self.assertIn("對話沒有被記錄下來", message)
def test_an_unknown_check_still_reports_something(self) -> None:
"""A check added later must not vanish from the message."""
message = self._build([], [("something_new", "詳細說明")])
self.assertIn("something_new", message)
self.assertIn("詳細說明", message)
def test_counts_that_do_not_apply_are_omitted(self) -> None:
message = self._build([self._governance(pending=0, proposal=0, quarantine=0)], [])
self.assertTrue(message.startswith("XKB 一切正常"))
if __name__ == "__main__":
unittest.main()