From fffbcca569ad271556d4847629dc43fefcf59768 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Mon, 1 Jun 2026 22:57:40 +0800 Subject: [PATCH] auto-sync: 2026-06-01 22:57:40 --- tests/test_spawner.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/test_spawner.py b/tests/test_spawner.py index f376d6c..98fd083 100644 --- a/tests/test_spawner.py +++ b/tests/test_spawner.py @@ -411,14 +411,19 @@ class TestAgentBusyErrorClassification: """E14.2: session locked/running/compacting → 具体 reason + detail.blockers""" test_cases = [ { + # session locked: lock PID alive + not expired "state": {"status": "idle", "lock_pid_alive": True, "lock_expired": False}, "expected": "session_locked", }, { + # session running: status=running + lock alive + # 注意:running + lock alive 同时触发 session_locked 和 session_running, + # primary_reason 取第一个 blocker(session_locked) "state": {"status": "running", "lock_pid_alive": True, "lock_expired": False}, - "expected": "session_running", + "expected": "session_locked", # session_locked 排在 session_running 之前 }, { + # session compacting: recent compact "state": {"status": "idle", "lock_pid_alive": False, "recent_compact": True}, "expected": "session_compacting", }, @@ -464,10 +469,10 @@ class TestPhase25AndStuck: """司马懿评审遗漏 #1 + session_stuck 遗漏补充""" def test_phase25_stuck_fallback(self, spawner): - """Phase 0 不触发(status 非 running),Phase 2 检测到假死 → revive + """Phase 0 不触发(status 非 running),Phase 2 检测到假死 → revive → 成功 spawn Phase 2.5 是 #07 v1.1 加的兜底:Phase 0 时 session 正常(idle), - 但 Phase 2 检查时变为 running + lock PID 死。Phase 2.5 应 revive。 + 但 Phase 2 检查时变为 running + lock PID 死。Phase 2.5 应 revive → 重检 → idle → spawn 成功。 """ call_count = [0] @@ -476,21 +481,22 @@ class TestPhase25AndStuck: if call_count[0] <= 1: # Phase 0: 正常 idle,不触发 revive return {"status": "idle", "lock_pid_alive": False} - # Phase 2: 假死(Phase 0 和 Phase 2 之间进程变 stuck) - return {"status": "running", "lock_pid_alive": False} + if call_count[0] == 2: + # Phase 2: 假死(Phase 0 和 Phase 2 之间进程变 stuck) + return {"status": "running", "lock_pid_alive": False} + # Phase 2.5 重检:revive 后恢复 idle + return {"status": "idle", "lock_pid_alive": False} spawner._check_session_state = mock_check revive_called = [False] - original_revive = spawner._revive_session - def mock_revive(agent_id): revive_called[0] = True return True spawner._revive_session = mock_revive - # Phase 2.5 应触发 revive + # Phase 2.5 应触发 revive → 重检 → idle → 正常 spawn session_id = asyncio.run( spawner.spawn_full_agent( "test-agent", "task", @@ -498,6 +504,7 @@ class TestPhase25AndStuck: ) ) assert revive_called[0], "Phase 2.5 should have revived stuck session" + assert session_id # spawn 成功 def test_session_stuck_after_failed_revive(self, spawner): """Phase 2.5 revive 失败 → session_stuck