journey.spec.ts 5.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import { expect, test } from "@playwright/test";
  2. const baseStep = {
  3. sequence: 1,
  4. status: "completed",
  5. task_id: "task-structure",
  6. attempt_id: null,
  7. validation_id: null,
  8. decision_id: null,
  9. reasoning_source: "contract",
  10. process: { label: "创建整体结构 Task", actor: "Planner", tool_name: "plan_script_tasks", trace_id: "root-42", details: {} },
  11. input_data: [{ label: "已接受的创作方向", kind: "direction", ref: null, detail: null }],
  12. output_data: [{ label: "TaskContract", kind: "contract", ref: null, detail: null }],
  13. contract: { action: "创建整体结构 Task", reasoning: "根据任务合同创建结构", goals: ["goal-1", "goal-2"], inputs: ["已接受的创作方向"], output: "整体结构", criteria: ["结构完整", "覆盖所有目标"] },
  14. parallel_group_id: null,
  15. parallel_position: null,
  16. parallel_total: null,
  17. model: null,
  18. tokens: null,
  19. cost: null,
  20. duration_ms: null,
  21. created_at: "2026-07-21T01:00:00Z",
  22. evidence: { contract: { task_kind: "structure", objective: "组织脚本结构", goal_ids: ["goal-1", "goal-2"] }, tool_calls: [], artifact_refs: [], validation: null, decision: null },
  23. };
  24. test("业务用户可从全局回合进入步骤和原始证据", async ({ page }) => {
  25. await page.route(/\/api\/runs$/, (route) => route.fulfill({
  26. headers: { "access-control-allow-origin": route.request().headers().origin ?? "http://127.0.0.1:3010", "access-control-allow-credentials": "true" },
  27. json: [{ script_build_id: 42, status: "running", summary: "心理学反转脚本", started_at: null, completed_at: null }],
  28. }));
  29. await page.route(/\/api\/runs\/42\/journey$/, (route) => route.fulfill({
  30. headers: { "access-control-allow-origin": route.request().headers().origin ?? "http://127.0.0.1:3010", "access-control-allow-credentials": "true" },
  31. json: {
  32. schema_version: "script-build-journey/v1",
  33. generated_at: "2026-07-21T01:05:00Z",
  34. script_build_id: 42,
  35. root_trace_id: "root-42",
  36. status: "running",
  37. objective: "为「一次反转如何改变信念」创作可发布脚本",
  38. input_summary: { topic: "一次反转如何改变信念", account_name: "每天心理学", persona_point_count: 18, strategy_names: ["先冲突后解法"], snapshot_id: "11", digest: "sha256:input" },
  39. steps: [
  40. { ...baseStep, sequence: 1, step_id: "plan:task-structure", step_type: "plan", title: "Planner 规划·整体结构", reasoning: "当前缺少整体结构,目标之间需要统一组织。" },
  41. { ...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 } },
  42. { ...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 } },
  43. { ...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" } } },
  44. ],
  45. edges: [
  46. { edge_id: "loop:decide:decision-1:execute:attempt-1", source: "decide:decision-1", target: "execute:attempt-1", relation: "loop", label: "重试" },
  47. ],
  48. warnings: ["部分“思考”由冻结任务合同转述,不是隐藏思维链。"],
  49. },
  50. }));
  51. await page.goto("/");
  52. await expect(page.getByRole("heading", { name: "为「一次反转如何改变信念」创作可发布脚本" })).toBeVisible();
  53. await expect(page.getByText("这次创作经过了 1 个任务回合")).toBeVisible();
  54. await page.getByRole("button", { name: /当前缺少整体结构/ }).click();
  55. await expect(page.getByRole("heading", { name: "Planner 规划·整体结构" })).toBeVisible();
  56. await expect(page.getByText("重试·回到前面继续")).toBeVisible();
  57. await page.getByRole("button", { name: "证据", exact: true }).click();
  58. await expect(page.getByText("冻结的 TaskContract")).toBeVisible();
  59. await page.screenshot({ path: "../test-artifacts/journey-v1.png", fullPage: true });
  60. });