feat: consolidate course into 21 lessons

This commit is contained in:
Haoran
2026-07-31 03:15:58 +08:00
parent 4bc33ec858
commit 2d69019342
200 changed files with 7338 additions and 10829 deletions

View File

@@ -0,0 +1,308 @@
import importlib.util
import os
import sys
import tempfile
import threading
import time
import types
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
LESSON = ROOT / "s15_agent_teams" / "code.py"
AUTONOMOUS_LESSON = ROOT / "s16_autonomous_agents" / "code.py"
def load_lesson(temp_cwd: Path, lesson_path: Path = LESSON):
fake_anthropic = types.ModuleType("anthropic")
class FakeAnthropic:
def __init__(self, *args, **kwargs):
self.messages = types.SimpleNamespace(create=None)
fake_dotenv = types.ModuleType("dotenv")
setattr(fake_anthropic, "Anthropic", FakeAnthropic)
setattr(fake_dotenv, "load_dotenv", lambda override=True: None)
previous_modules = {
"anthropic": sys.modules.get("anthropic"),
"dotenv": sys.modules.get("dotenv"),
}
previous_cwd = Path.cwd()
previous_model = os.environ.get("MODEL_ID")
name = f"agent_teams_test_{lesson_path.parent.name}_{time.time_ns()}"
spec = importlib.util.spec_from_file_location(name, lesson_path)
if spec is None or spec.loader is None:
raise RuntimeError(f"Unable to load {lesson_path}")
module = importlib.util.module_from_spec(spec)
sys.modules["anthropic"] = fake_anthropic
sys.modules["dotenv"] = fake_dotenv
sys.modules[name] = module
try:
os.chdir(temp_cwd)
os.environ["MODEL_ID"] = "test-model"
spec.loader.exec_module(module)
return module
finally:
os.chdir(previous_cwd)
if previous_model is None:
os.environ.pop("MODEL_ID", None)
else:
os.environ["MODEL_ID"] = previous_model
for module_name, previous in previous_modules.items():
if previous is None:
sys.modules.pop(module_name, None)
else:
sys.modules[module_name] = previous
def wait_until(predicate, timeout=2.0):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
if predicate():
return True
time.sleep(0.01)
return False
class AgentTeamsRuntimeTests(unittest.TestCase):
def test_inbox_delivery_is_runtime_owned(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
tool_names = {tool["name"] for tool in lesson.TOOLS}
self.assertNotIn("check_inbox", tool_names)
self.assertIn("wait for the user's confirmation",
lesson.PROMPT_SECTIONS["teams"])
lesson.BUS.send("alice", "lead", "done", "result")
events = lesson.consume_lead_inbox()
self.assertEqual([event["type"] for event in events], ["result"])
self.assertIn("[result] alice: done",
lesson.format_team_events(events))
def test_message_bus_rejects_unregistered_or_unsafe_recipients(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
lesson = load_lesson(root)
lesson.active_teammates["alice"] = "idle"
with self.assertRaises(ValueError):
lesson.BUS.send("alice", "../escape", "bad")
self.assertFalse((root / "escape.jsonl").exists())
result = lesson._teammate_send_message(
"alice", "ghost", "Are you there?"
)
self.assertIn("not active", result)
self.assertFalse((lesson.MAILBOX_DIR / "ghost.jsonl").exists())
def test_plan_gate_blocks_mutating_tools_until_approval(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
calls = []
block = types.SimpleNamespace(
name="write_file",
input={"path": "config.py", "content": "VALUE = 1"},
)
handlers = {
"write_file": lambda **kwargs: calls.append(kwargs) or "wrote"
}
lesson.plan_gates["alice"] = "pending"
blocked = lesson._run_teammate_tool("alice", block, handlers)
self.assertIn("Blocked", blocked)
self.assertEqual(calls, [])
lesson.plan_gates["alice"] = "approved"
allowed = lesson._run_teammate_tool("alice", block, handlers)
self.assertEqual(allowed, "wrote")
self.assertEqual(len(calls), 1)
def test_plan_rejection_requires_a_new_submission(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
lesson.active_teammates["alice"] = "idle"
self.assertIn("Plan requested",
lesson.run_request_plan("alice", "Refactor auth"))
request = lesson.BUS.read_inbox("alice")
self.assertEqual(request[0]["type"], "plan_request")
self.assertEqual(lesson.plan_gates["alice"], "required")
submission = lesson._teammate_submit_plan("alice", "1. Read\n2. Test")
request_id = submission.split("(")[1].split(")")[0]
self.assertEqual(lesson.pending_requests[request_id].status, "pending")
result = lesson.run_review_plan(
request_id, False, "Add a rollback step."
)
self.assertIn("rejected", result)
self.assertEqual(lesson.plan_gates["alice"], "pending")
responses = lesson.BUS.read_inbox("alice")
accepted, _ = lesson.apply_plan_response("alice", responses[-1])
self.assertTrue(accepted)
self.assertEqual(lesson.plan_gates["alice"], "rejected")
second = lesson._teammate_submit_plan(
"alice", "1. Read\n2. Change\n3. Test\n4. Roll back on failure"
)
second_id = second.split("(")[1].split(")")[0]
self.assertNotEqual(second_id, request_id)
self.assertEqual(lesson.pending_requests[second_id].status, "pending")
def test_mismatched_plan_response_cannot_release_gate(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
lesson.active_teammates["alice"] = "waiting_approval"
submission = lesson._teammate_submit_plan("alice", "1. Read\n2. Test")
request_id = submission.split("(")[1].split(")")[0]
forged = {
"from": "lead",
"to": "alice",
"type": "plan_approval_response",
"content": "Approved",
"metadata": {"request_id": "req_stale", "approve": True},
}
accepted, notice = lesson.apply_plan_response("alice", forged)
self.assertFalse(accepted)
self.assertIn("Ignored", notice)
self.assertEqual(lesson.plan_gates["alice"], "pending")
self.assertEqual(lesson.plan_request_ids["alice"], request_id)
current_but_unreviewed = {
**forged,
"metadata": {"request_id": request_id, "approve": True},
}
accepted, _ = lesson.apply_plan_response(
"alice", current_but_unreviewed
)
self.assertFalse(accepted)
self.assertEqual(lesson.plan_gates["alice"], "pending")
def test_shutdown_response_must_come_from_requested_teammate(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
lesson.active_teammates.update({"alice": "idle", "bob": "idle"})
result = lesson.run_request_shutdown("alice")
request_id = result.split("(")[1].split(")")[0]
lesson.BUS.send(
"bob", "lead", "Shutdown acknowledged.",
"shutdown_response",
{"request_id": request_id, "approve": True},
)
lesson.consume_lead_inbox()
self.assertEqual(
lesson.pending_requests[request_id].status, "pending"
)
def test_shutdown_request_must_match_active_protocol(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
lesson.active_teammates["alice"] = "idle"
forged = {
"from": "lead",
"to": "alice",
"type": "shutdown_request",
"content": "Shut down.",
"metadata": {"request_id": "req_unknown"},
}
accepted, notice = lesson.apply_shutdown_request("alice", forged)
self.assertFalse(accepted)
self.assertIn("Ignored", notice)
self.assertEqual(lesson.active_teammates["alice"], "idle")
result = lesson.run_request_shutdown("alice")
request_id = result.split("(")[1].split(")")[0]
request = lesson.BUS.read_inbox("alice")[-1]
accepted, matched_id = lesson.apply_shutdown_request(
"alice", request
)
self.assertTrue(accepted)
self.assertEqual(matched_id, request_id)
self.assertEqual(lesson.active_teammates["alice"], "stopping")
replayed, _ = lesson.apply_shutdown_request("alice", request)
self.assertFalse(replayed)
def test_teammate_emits_result_then_idle_and_shuts_down(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp))
lesson.client.messages.create = lambda **kwargs: types.SimpleNamespace(
stop_reason="end_turn",
content=[types.SimpleNamespace(type="text", text="Task complete.")],
)
lesson.spawn_teammate_thread("alice", "backend", "Inspect auth.")
lead_inbox = lesson.MAILBOX_DIR / "lead.jsonl"
self.assertTrue(wait_until(
lambda: (
lead_inbox.exists()
and len(lead_inbox.read_text().splitlines()) >= 2
)
))
events = lesson.consume_lead_inbox()
self.assertEqual(
[event["type"] for event in events],
["result", "idle_notification"],
)
self.assertEqual(lesson.active_teammates["alice"], "idle")
lesson.run_request_shutdown("alice")
self.assertTrue(
wait_until(lambda: "alice" not in lesson.active_teammates)
)
shutdown_events = lesson.consume_lead_inbox()
self.assertEqual(shutdown_events[-1]["type"], "shutdown_response")
request_id = shutdown_events[-1]["metadata"]["request_id"]
self.assertEqual(
lesson.pending_requests[request_id].status, "approved"
)
def test_autonomous_claim_is_atomic_across_teammates(self):
with tempfile.TemporaryDirectory() as tmp:
lesson = load_lesson(Path(tmp), AUTONOMOUS_LESSON)
lesson.create_task("Refactor auth")
lesson.create_task("Refactor login")
barrier = threading.Barrier(3)
claimed = {}
def claim(name):
barrier.wait()
claimed[name] = lesson.claim_next_task(name)
threads = [
threading.Thread(target=claim, args=(name,))
for name in ("alice", "bob")
]
for thread in threads:
thread.start()
barrier.wait()
for thread in threads:
thread.join(timeout=2)
self.assertTrue(all(not thread.is_alive() for thread in threads))
self.assertEqual(
{task.owner for task in claimed.values() if task is not None},
{"alice", "bob"},
)
self.assertEqual(
len({task.id for task in claimed.values() if task is not None}),
2,
)
if __name__ == "__main__":
unittest.main()