Release beta 2.0.1.1021
check / local-gate (push) Failing after 5m16s

This commit is contained in:
JWeBot Contributors
2026-10-21 17:38:47 +08:00
parent e4365841ed
commit 645a282b22
17 changed files with 778 additions and 124 deletions
+149 -15
View File
@@ -310,7 +310,11 @@ class LedgerAndApplicationTests(unittest.TestCase):
self.assertEqual(first["text"], MODULE.FAST_ACKNOWLEDGEMENT)
self.assertEqual(second["text"], MODULE.FAST_ACKNOWLEDGEMENT)
self.assertEqual(observed_context, [("你好", "第一条回复喵")])
self.assertEqual(len(observed_context), 1)
self.assertEqual(observed_context[0]["speaker"], "Alice")
self.assertEqual(observed_context[0]["user_text"], "你好")
self.assertEqual(observed_context[0]["taffy_text"], "第一条回复喵")
self.assertIn("same_sender", observed_context[0]["tags"])
self.assertEqual(
self.application.ledger.row("event-2")["response_text"],
"第二条回复喵",
@@ -335,12 +339,14 @@ class LedgerAndApplicationTests(unittest.TestCase):
self.application.process_direct_chat_once()
self.assertEqual(
observed["group-second"],
[("群里的第一条", "group-first 回复喵")],
[(item["speaker"], item["user_text"], item["taffy_text"])
for item in observed["group-second"]],
[("Alice", "群里的第一条", "group-first 回复喵")],
)
self.assertEqual(
observed["direct-second"],
[("私聊里的第一条", "direct-first 回复喵")],
[(item["speaker"], item["user_text"], item["taffy_text"])
for item in observed["direct-second"]],
[("Alice", "私聊里的第一条", "direct-first 回复喵")],
)
def test_shadow_event_is_rejected_before_routing_or_persistence(self):
@@ -371,15 +377,143 @@ class LedgerAndApplicationTests(unittest.TestCase):
self.application.accept(event("chat-context", "@JWeBot 刚才是什么结果"))
self.application.process_direct_chat_once()
self.assertIn(
(
"[本地命令结果][发送者:Alice][类型:coin] /翻硬币",
local["text"],
),
observed_context,
self.assertTrue(
any(
item["route"] == "local"
and item["route_reason"] == "local_coin"
and item["speaker"] == "Alice"
and item["user_text"] == "/翻硬币"
and item["taffy_text"] == local["text"]
for item in observed_context
)
)
self.assertTrue(
all(question != "/version" for question, _reply in observed_context)
all(item["user_text"] != "/version" for item in observed_context)
)
def test_self_referential_context_does_not_cross_senders(self):
observed_context = []
def complete(**kwargs):
observed_context[:] = list(kwargs["context"])
return "我只看你的喵"
self.application.deepseek.complete = complete
self.application.deliver = mock.Mock()
self.application.accept(event("alice-first", "@JWeBot Alice 的事", sender="Alice"))
self.application.process_direct_chat_once()
self.application.accept(event("bob-first", "@JWeBot Bob 的事", sender="Bob"))
self.application.process_direct_chat_once()
self.application.accept(event("bob-follow", "@JWeBot 我刚才说啥", sender="Bob"))
self.application.process_direct_chat_once()
self.assertTrue(observed_context)
self.assertEqual(
{item["speaker"] for item in observed_context},
{"Bob"},
)
self.assertTrue(
all("Alice 的事" not in item["user_text"] for item in observed_context)
)
def test_mentioned_person_context_can_cross_senders(self):
observed_context = []
def complete(**kwargs):
observed_context[:] = list(kwargs["context"])
return "看 Bob 那句喵"
self.application.deepseek.complete = complete
self.application.deliver = mock.Mock()
self.application.accept(event("bob-mentioned", "@JWeBot Bob 的事", sender="Bob"))
self.application.process_direct_chat_once()
self.application.accept(
event("alice-asks-bob", "@JWeBot Bob 刚才说啥", sender="Alice")
)
self.application.process_direct_chat_once()
self.assertTrue(
any(
item["speaker"] == "Bob"
and item["user_text"] == "Bob 的事"
and "mentioned_person" in item["tags"]
for item in observed_context
)
)
def test_low_confidence_sender_does_not_receive_identity_memory(self):
captured = {}
def complete(**kwargs):
captured.update(kwargs)
return "先确认是谁喵"
self.application.deepseek.complete = complete
self.application.deliver = mock.Mock()
self.application.accept(
{
**event("low-conf-chat", "@JWeBot 我是谁", sender="alice"),
"sender_confidence": 0.42,
"body_confidence": 0.98,
"source": "rapidocr-local",
}
)
self.application.process_direct_chat_once()
self.assertEqual(captured["person_memory"], ())
self.assertIsNone(
self.application.ledger.person_profile(
"group-a",
MODULE.person_scope_key("group-a", "Alice"),
)
)
def test_low_confidence_identity_bound_local_command_is_rejected(self):
response = self.application.accept(
{
**event("low-conf-draw", "@JWeBot /抽奖 10", sender="alice"),
"sender_confidence": 0.42,
"body_confidence": 0.98,
"source": "rapidocr-local",
}
)
self.assertEqual(response["route"], "local")
self.assertIn("没认稳", response["text"])
self.assertEqual(
self.application.ledger.row("low-conf-draw")["status"],
"local_rejected",
)
def test_delivered_taffy_broadcast_is_available_to_context(self):
self.application.ledger.reserve_clock_broadcast(
group_fingerprint="group-a",
slot_key="hourly:2026-10-21T17",
local_date="2026-10-21",
kind="ambient_chat",
message="我刚刚路过说了一句喵",
)
self.assertTrue(
self.application.ledger.complete_clock_broadcast(
"group-a",
"hourly:2026-10-21T17",
)
)
context = self.application.ledger.conversation_context(
"group-a",
exclude_event_id="current",
sender="Alice",
question="Taffy 刚刚说了什么",
)
self.assertTrue(
any(
item["speaker"] == "Taffy"
and item["taffy_text"] == "我刚刚路过说了一句喵"
and "taffy_broadcast" in item["tags"]
for item in context
)
)
def test_route_and_ack_telemetry_is_privacy_safe(self):
@@ -1081,9 +1215,9 @@ class LedgerAndApplicationTests(unittest.TestCase):
self.assertEqual(version["route"], "local")
self.assertIn("JWeBot 版本", version["text"])
self.assertIn("kernel", version["text"])
self.assertIn("最新版本:beta 2.0.0.1021", version["text"])
self.assertIn("更新时间:2026-10-21 16:57:39", version["text"])
self.assertIn("更新摘要:Beta 2.0 架构更新完成", version["text"])
self.assertIn("最新版本:beta 2.0.1.1021", version["text"])
self.assertIn("更新时间:2026-10-21 17:32:46", version["text"])
self.assertIn("更新摘要:上下文管理小版本更新完成", version["text"])
self.assertEqual(debug["route"], "local")
self.assertIn("调试埋点", debug["text"])
self.assertEqual(balance["route"], "local")