from copy import deepcopy from fastapi.testclient import TestClient from app import main client = TestClient(main.app) def test_v8_execution_round_activity_and_artifact_endpoints(monkeypatch, current_bundle): bundle = deepcopy(current_bundle) monkeypatch.setattr(main.provider, "load_bundle", lambda _build_id: deepcopy(bundle)) monkeypatch.setattr(main.provider, "load_current_artifact", lambda _build_id: deepcopy(bundle["currentArtifact"])) monkeypatch.setattr(main.provider, "list_builds", lambda **_kwargs: [{"id": "88001", "status": "running"}]) execution = client.get("/api/script-builds/88001/execution-view") assert execution.status_code == 200 assert execution.json()["schemaVersion"] == "8" round_detail = client.get("/api/script-builds/88001/rounds/1") assert round_detail.status_code == 200 assert round_detail.json()["businessSections"] data_detail = client.get("/api/script-builds/88001/activities/data-decision:11") assert data_detail.status_code == 200 assert data_detail.json()["detailKind"] == "agent-decision" assert data_detail.json()["decisionType"] == "tradeoff" assert "明确取舍" in [block["title"] for block in data_detail.json()["blocks"]] artifact = client.get("/api/script-builds/88001/artifacts/base:current") assert artifact.status_code == 200 assert artifact.json()["changes"]["exactness"] == "current-only" assert artifact.json()["scriptTable"]["counts"] == {"paragraphs": 3, "elements": 2, "links": 1} round_artifact = client.get("/api/script-builds/88001/artifacts/artifact:round:1") assert round_artifact.status_code == 200 assert round_artifact.json()["artifactContext"] == { "type": "round", "roundIndex": 1, "versionKind": "current-base", "note": "当前数据库未保存第 1 轮结束时的独立快照;这里展示当前保存的主脚本。", "exactness": "current-only", } candidate = client.get("/api/script-builds/88001/artifacts/artifact:branch:1") assert candidate.status_code == 200 assert candidate.json()["artifactContext"] == { "type": "candidate", "roundIndex": 1, "branchId": 1, "branchStatus": "merged", "pathType": "内容", "versionKind": "saved-at-disposition", "historicalAccuracy": "exact", "currentProjectionAccuracy": "not-applicable", "note": "测试候选版本", "exactness": "historical-snapshot", } domain = client.get("/api/script-builds/88001/artifacts/artifact:branch:2") assert domain.status_code == 404 assert "领域信息方案" in domain.json()["detail"] def test_terminal_branch_without_snapshot_does_not_fake_a_candidate(monkeypatch, current_bundle): bundle = deepcopy(current_bundle) branch = bundle["branches"][0] branch["candidate_snapshot"] = { "snapshot": None, "snapshotKind": "missing-disposition-snapshot", "historicalAccuracy": "missing", "currentProjectionAccuracy": "not-applicable", } monkeypatch.setattr(main.provider, "load_bundle", lambda _build_id: deepcopy(bundle)) response = client.get("/api/script-builds/88001/artifacts/artifact:branch:1") assert response.status_code == 404 assert "没有可用的候选脚本快照" in response.json()["detail"] def test_event_body_is_loaded_only_from_activity_endpoint(monkeypatch, current_bundle): full_report = "评审原文" * 8_000 monkeypatch.setattr(main.provider, "load_bundle", lambda _build_id: deepcopy(current_bundle)) monkeypatch.setattr(main.provider, "load_event_detail", lambda _build_id, _event_id: { "id": 41, "event_name": "script_evaluator", "title": "整体评审", "input": {"content": "评审第1轮"}, "output": {"content": f"整体结论:部分通过\n{full_report}"}, }) execution = client.get("/api/script-builds/88001/execution-view").json() assert "评审第1轮" not in str(execution) detail = client.get("/api/script-builds/88001/activities/event:41") assert detail.status_code == 200 payload = detail.json() assert payload["detailKind"] == "agent-decision" assert payload["decisionType"] == "evaluation" assert any( block.get("title") == "总结论" and block.get("value") == "部分通过" for block in payload["blocks"] ) assert "script_evaluator" not in str(payload["blocks"]) assert full_report in payload["technical"]["output"]["content"] assert "[truncated" not in payload["technical"]["output"]["content"] def test_removed_fixture_and_raw_log_routes_are_not_exposed(): assert client.get("/api/fixtures/current-schema/execution-view").status_code == 404 assert client.get("/api/script-builds/1/raw-log").status_code == 404 def test_capabilities_only_advertise_new_db_contract(): response = client.get("/api/capabilities") assert response.status_code == 200 payload = response.json() assert payload["schemaVersion"] == "8" assert payload["readOnly"] is True assert "script_build_multipath_decision" in payload["businessSources"] assert payload["runtimeSupplement"] == ["script_build_event", "script_build_event_body"] def test_prompt_endpoint_marks_current_rules_as_not_a_run_snapshot(monkeypatch): monkeypatch.setattr( main.provider, "load_prompt_context", lambda _build_id, _prompt_ref: { "promptRef": "prompt:event:50", "actor": {"role": "implementer", "label": "实现 Agent"}, "task": "补齐烹饪步骤", "promptContent": "当前规则\nAuthorization: Bearer secret-token", "promptSource": "current-db", "promptVersion": 8, }, ) response = client.get( "/api/script-builds/88001/decision-prompts/prompt:event:50" ) assert response.status_code == 200 payload = response.json() assert payload["exactTask"] == { "content": "补齐烹饪步骤", "accuracy": "run-exact", } assert payload["systemPrompt"]["source"] == "current-db" assert payload["systemPrompt"]["accuracy"] == "current-not-run-snapshot" assert "secret-token" not in str(payload) assert any( item["code"] == "PROMPT_NOT_SNAPSHOTTED" for item in payload["notices"] )