import { expect, test } from "@playwright/test"; const baseStep = { sequence: 1, status: "completed", task_id: "task-structure", attempt_id: null, validation_id: null, decision_id: null, reasoning_source: "contract", process: { label: "创建整体结构 Task", actor: "Planner", tool_name: "plan_script_tasks", trace_id: "root-42", details: {} }, input_data: [{ label: "已接受的创作方向", kind: "direction", ref: null, detail: null }], output_data: [{ label: "TaskContract", kind: "contract", ref: null, detail: null }], contract: { action: "创建整体结构 Task", reasoning: "根据任务合同创建结构", goals: ["goal-1", "goal-2"], inputs: ["已接受的创作方向"], output: "整体结构", criteria: ["结构完整", "覆盖所有目标"] }, parallel_group_id: null, parallel_position: null, parallel_total: null, model: null, tokens: null, cost: null, duration_ms: null, created_at: "2026-07-21T01:00:00Z", evidence: { contract: { task_kind: "structure", objective: "组织脚本结构", goal_ids: ["goal-1", "goal-2"] }, tool_calls: [], artifact_refs: [], validation: null, decision: null }, }; test("业务用户可从全局回合进入步骤和原始证据", async ({ page }) => { await page.route(/\/api\/runs$/, (route) => route.fulfill({ headers: { "access-control-allow-origin": route.request().headers().origin ?? "http://127.0.0.1:3010", "access-control-allow-credentials": "true" }, json: [{ script_build_id: 42, status: "running", summary: "心理学反转脚本", started_at: null, completed_at: null }], })); await page.route(/\/api\/runs\/42\/journey$/, (route) => route.fulfill({ headers: { "access-control-allow-origin": route.request().headers().origin ?? "http://127.0.0.1:3010", "access-control-allow-credentials": "true" }, json: { schema_version: "script-build-journey/v1", generated_at: "2026-07-21T01:05:00Z", script_build_id: 42, root_trace_id: "root-42", status: "running", objective: "为「一次反转如何改变信念」创作可发布脚本", input_summary: { topic: "一次反转如何改变信念", account_name: "每天心理学", persona_point_count: 18, strategy_names: ["先冲突后解法"], snapshot_id: "11", digest: "sha256:input" }, steps: [ { ...baseStep, sequence: 1, step_id: "plan:task-structure", step_type: "plan", title: "Planner 规划·整体结构", reasoning: "当前缺少整体结构,目标之间需要统一组织。" }, { ...baseStep, sequence: 2, step_id: "execute:attempt-1", step_type: "execute", title: "Worker 执行·整体结构", attempt_id: "attempt-1", reasoning: "先建立五段式骨架,再检查每个 Goal 的落点。", reasoning_source: "observable", process: { label: "执行 create_script_structure", actor: "Worker", tool_name: null, trace_id: "worker-1", details: {} }, output_data: [{ label: "Structure", kind: "structure", ref: "script-build://artifact-versions/11", detail: null }], contract: null, model: "qwen-plus", tokens: 2310, duration_ms: 18400, created_at: "2026-07-21T01:01:00Z", evidence: { contract: null, tool_calls: [{ name: "create_script_structure", arguments: {} }], artifact_refs: [{ uri: "script-build://artifact-versions/11", kind: "structure" }], validation: null, decision: null } }, { ...baseStep, sequence: 3, step_id: "validate:validation-1", step_type: "validate", title: "Validator 验收·整体结构", attempt_id: "attempt-1", validation_id: "validation-1", status: "failed", reasoning: "goal-2 的成功标准没有明确落点。", reasoning_source: "validation", process: { label: "独立 Validator 语义质检", actor: "Validator", tool_name: null, trace_id: "validator-1", details: {} }, input_data: [{ label: "Structure", kind: "structure", ref: "script-build://artifact-versions/11", detail: null }], output_data: [{ label: "Validation·failed", kind: "validation", ref: "validation-1", detail: null }], contract: null, created_at: "2026-07-21T01:02:00Z", evidence: { contract: null, tool_calls: [], artifact_refs: [], validation: { verdict: "failed", reason: "goal-2 缺少落点" }, decision: null } }, { ...baseStep, sequence: 4, step_id: "decide:decision-1", step_type: "decide", title: "Planner 决定·重新执行", attempt_id: "attempt-1", validation_id: "validation-1", decision_id: "decision-1", status: "retry", reasoning: "保留当前结构,补齐 goal-2 后再执行一次。", reasoning_source: "decision", process: { label: "保留任务合同,让 Worker 再执行一次", actor: "Planner", tool_name: "decide_script_task", trace_id: "root-42", details: {} }, input_data: [{ label: "Validation", kind: "validation", ref: "validation-1", detail: null }], output_data: [{ label: "重新执行", kind: "decision", ref: "decision-1", detail: null }], contract: null, created_at: "2026-07-21T01:03:00Z", evidence: { contract: null, tool_calls: [], artifact_refs: [], validation: null, decision: { action: "retry", reason: "补齐 goal-2" } } }, ], edges: [ { edge_id: "loop:decide:decision-1:execute:attempt-1", source: "decide:decision-1", target: "execute:attempt-1", relation: "loop", label: "重试" }, ], warnings: ["部分“思考”由冻结任务合同转述,不是隐藏思维链。"], }, })); await page.goto("/"); await expect(page.getByRole("heading", { name: "为「一次反转如何改变信念」创作可发布脚本" })).toBeVisible(); await expect(page.getByText("这次创作经过了 1 个任务回合")).toBeVisible(); await page.getByRole("button", { name: /当前缺少整体结构/ }).click(); await expect(page.getByRole("heading", { name: "Planner 规划·整体结构" })).toBeVisible(); await expect(page.getByText("重试·回到前面继续")).toBeVisible(); await page.getByRole("button", { name: "证据", exact: true }).click(); await expect(page.getByText("冻结的 TaskContract")).toBeVisible(); await page.screenshot({ path: "../test-artifacts/journey-v1.png", fullPage: true }); });