# ============================================================ # AG-08 workspace golden tests # ============================================================ from __future__ import annotations import copy import os from server.state.projects import PERSONAL_PROJECT_ID, ProjectStore from server.state.seed import seed_world def test_workspace_persist_roundtrip(tmp_path): path = str(tmp_path / "projects.json") store = ProjectStore(path) created = store.create_project("pilot-plant") pid = created["project"]["id"] sid = created["session"]["id"] store.replace_messages(sid, [{"role": "user", "text": "run"}, {"role": "assistant", "text": "ok"}]) store2 = ProjectStore(path) snap = store2.snapshot() assert any(p["id"] == pid for p in snap["projects"]) assert snap["messages"][sid][0]["text"] == "run" assert snap["worldKey"] == "default" assert os.path.exists(path) def test_delete_project_does_not_touch_world(tmp_path): path = str(tmp_path / "projects.json") store = ProjectStore(path) world = seed_world() world_before = copy.deepcopy(world) created = store.create_project("temp-project") pid = created["project"]["id"] result = store.delete_project(pid) assert result["worldUntouched"] is True assert world == world_before assert len(world["salesOrders"]) == 7 assert not any(p["id"] == pid for p in store.snapshot()["projects"]) def test_migrate_local_workspace_replace(tmp_path): path = str(tmp_path / "projects.json") store = ProjectStore(path) local = { "projects": [{ "id": "proj_local1", "name": "migrated", "scopeLabel": "demo", "createdAt": "2026-07-22 10:00", }], "sessions": [{ "id": "sess_local1", "projectId": "proj_local1", "title": "topic", "status": "running", "updatedAt": "2026-07-22 10:00", }], "files": [], "messages": {"sess_local1": [{"role": "user", "text": "hello"}]}, "activeProjectId": "proj_local1", "activeSessionId": "sess_local1", "worldKey": "default", } snap = store.replace_workspace(local) assert snap["projects"][0]["name"] == "migrated" assert snap["messages"]["sess_local1"][0]["text"] == "hello" assert snap["activeSessionId"] == "sess_local1" def test_personal_scope_cannot_delete(tmp_path): store = ProjectStore(str(tmp_path / "p.json")) try: store.delete_project(PERSONAL_PROJECT_ID) assert False, "should raise" except ValueError as exc: assert "personal" in str(exc).lower() or "不可删除" in str(exc)