160 lines
7.9 KiB
Python
160 lines
7.9 KiB
Python
from app.schemas.pmflow_ai_agent_runtime import (
|
||
PMFlowAIAgentActionCandidateLedgerEntry,
|
||
PMFlowAIAgentClaim,
|
||
PMFlowAIAgentCriticResult,
|
||
PMFlowAIAgentGoalFrame,
|
||
PMFlowAIAgentStepProposal,
|
||
PMFlowAIAgentWorkspace,
|
||
)
|
||
from app.services.pmflow_ai_agent_runtime.agent_answer_runtime import build_agent_terminal_answer_state
|
||
from app.services.pmflow_ai_agent_runtime.agent_deliverable_runtime import PMFlowAIAgentDeliverableRuntime
|
||
from app.services.pmflow_ai_agent_runtime.agent_payload_gate import build_agent_answer_canvas
|
||
|
||
|
||
def test_goal_authored_project_launch_affordance_reaches_customer_canvas() -> None:
|
||
question = "我想做一个帮助独立开发者管理产品验证和变现推进的工具"
|
||
workspace = PMFlowAIAgentWorkspace(
|
||
current_goal=question,
|
||
goal_frame=PMFlowAIAgentGoalFrame(
|
||
user_goal=question,
|
||
desired_output="给出可执行的产品推进蓝图,并能进入 PMFlow 下一步确认链。",
|
||
source_policy="internal_customer_safe",
|
||
freshness_policy="not_required",
|
||
answer_objective={"user_success": "拿到可落地的 MVP 推进方向"},
|
||
dynamic_rubric=[
|
||
{
|
||
"criterion": "回答必须覆盖目标用户、MVP 边界、验证动作和 PMFlow 承接动作",
|
||
"why_it_matters": "用户要从想法进入执行",
|
||
"evidence_expectation": "受控假设即可",
|
||
}
|
||
],
|
||
deliverable_shape={
|
||
"primary_shape": "产品执行蓝图",
|
||
"must_include": ["MVP 边界", "验证动作", "PMFlow 下一步"],
|
||
"artifact_slots": [
|
||
{
|
||
"slot_key": "mvp_scope",
|
||
"display_goal": "明确首版 MVP 的边界",
|
||
"must_cover": ["核心闭环", "先不做什么"],
|
||
"depth": "standard",
|
||
}
|
||
],
|
||
"pmflow_system_actions": [
|
||
{
|
||
"capability_key": "project_launch_draft",
|
||
"title": "生成项目草案待确认",
|
||
"summary": "本轮方向已经可以进入 Project Launch 生成结构化草案。",
|
||
"input_seed": question,
|
||
"completion_criteria": "看到可审查的草案后再决定是否创建项目。",
|
||
}
|
||
],
|
||
},
|
||
),
|
||
claim_ledger=[
|
||
PMFlowAIAgentClaim(
|
||
claim_type="controlled_hypothesis_basis",
|
||
claim_text="可以先把这个方向收敛成一个待验证的产品执行蓝图,再进入 PMFlow 草案确认链。",
|
||
customer_value="用户可以从想法进入结构化推进。",
|
||
confidence="medium",
|
||
allowed_to_state=True,
|
||
relevance_to_user_goal="direct",
|
||
claim_kind="directional_judgement",
|
||
)
|
||
],
|
||
)
|
||
|
||
terminal = build_agent_terminal_answer_state(
|
||
question=question,
|
||
workspace=workspace,
|
||
proposal=PMFlowAIAgentStepProposal(action="answer"),
|
||
observation=None,
|
||
critic_result=PMFlowAIAgentCriticResult(ready_to_answer=True, retry_would_change_state=False, recover_or_continue="compose_answer"),
|
||
)
|
||
|
||
assert terminal.action_candidates
|
||
candidate = terminal.action_candidates[0]
|
||
assert candidate.action_type == "create_draft"
|
||
assert candidate.safety == "prepare_only"
|
||
assert candidate.requires_confirmation is True
|
||
assert candidate.href == "/project-launch?source=pmflow-ai"
|
||
assert candidate.action_payload["input"] == question
|
||
assert candidate.action_payload["launch_seed"]["packet_version"] == "pmflow_project_launch_seed.v1"
|
||
assert candidate.action_payload["launch_seed"]["source_contract"] == "same_understanding_materialization"
|
||
assert candidate.action_payload["launch_seed"]["materialization_policy"]["do_not_reinterpret_as_new_idea"] is True
|
||
assert candidate.action_payload["launch_seed"]["customer_safe_claims"][0]["claim_text"].startswith("可以先把这个方向")
|
||
assert len(candidate.href) <= 300
|
||
|
||
deliverable = PMFlowAIAgentDeliverableRuntime().build(
|
||
question=question,
|
||
workspace=workspace,
|
||
proposal=PMFlowAIAgentStepProposal(action="answer"),
|
||
observation=None,
|
||
critic_result=PMFlowAIAgentCriticResult(ready_to_answer=True, retry_would_change_state=False, recover_or_continue="compose_answer"),
|
||
terminal_state=terminal,
|
||
answer_text="这个方向可以先做成一个围绕验证和变现推进的 MVP,并进入 PMFlow 生成项目草案待确认。",
|
||
)
|
||
canvas = build_agent_answer_canvas(answer=deliverable.answer_text, workspace=workspace, terminal_state=terminal, deliverable_packet=deliverable)
|
||
|
||
assert deliverable.artifacts
|
||
assert deliverable.artifacts[0].artifact_kind == "product_blueprint"
|
||
assert deliverable.artifacts[0].slots[0]["title"] == "明确首版 MVP 的边界"
|
||
assert canvas["artifacts"][0]["artifact_kind"] == "product_blueprint"
|
||
assert canvas["artifacts"][0]["slots"][0]["title"] == "明确首版 MVP 的边界"
|
||
assert canvas["action_candidates"][0]["action_type"] == "create_draft"
|
||
assert canvas["action_candidates"][0]["href"] == "/project-launch?source=pmflow-ai"
|
||
assert canvas["action_candidates"][0]["action_payload"]["input"] == question
|
||
assert canvas["action_candidates"][0]["action_payload"]["launch_seed"]["idea_input"] == question
|
||
|
||
|
||
def test_goal_authored_project_launch_action_wins_over_llm_generated_href() -> None:
|
||
question = "我想做个AI漫剧的工具"
|
||
workspace = PMFlowAIAgentWorkspace(
|
||
current_goal=question,
|
||
goal_frame=PMFlowAIAgentGoalFrame(
|
||
user_goal=question,
|
||
desired_output="生成可确认的项目草案入口。",
|
||
deliverable_shape={
|
||
"pmflow_system_actions": [
|
||
{
|
||
"capability_key": "project_launch_draft",
|
||
"title": "启动“AI漫剧工具”项目草案",
|
||
"summary": "进入 Project Launch 生成待确认草案。",
|
||
"input_seed": question,
|
||
}
|
||
]
|
||
},
|
||
),
|
||
action_candidate_ledger=[
|
||
PMFlowAIAgentActionCandidateLedgerEntry(
|
||
title="启动“AI漫剧工具”项目草案",
|
||
summary="模型建议进入项目草案。",
|
||
action_type="navigate",
|
||
href="/pmflow/项目列表/new?seed=ai_comic_tool_draft",
|
||
safety="prepare_only",
|
||
)
|
||
],
|
||
)
|
||
|
||
terminal = build_agent_terminal_answer_state(
|
||
question=question,
|
||
workspace=workspace,
|
||
proposal=PMFlowAIAgentStepProposal(action="answer"),
|
||
observation=None,
|
||
critic_result=PMFlowAIAgentCriticResult(ready_to_answer=True, retry_would_change_state=False, recover_or_continue="compose_answer"),
|
||
)
|
||
deliverable = PMFlowAIAgentDeliverableRuntime().build(
|
||
question=question,
|
||
workspace=workspace,
|
||
proposal=PMFlowAIAgentStepProposal(action="answer"),
|
||
observation=None,
|
||
critic_result=PMFlowAIAgentCriticResult(ready_to_answer=True, retry_would_change_state=False, recover_or_continue="compose_answer"),
|
||
terminal_state=terminal,
|
||
answer_text="可以进入 PMFlow 生成项目草案待确认。",
|
||
)
|
||
canvas = build_agent_answer_canvas(answer=deliverable.answer_text, workspace=workspace, terminal_state=terminal, deliverable_packet=deliverable)
|
||
|
||
assert canvas["action_candidates"][0]["action_type"] == "create_draft"
|
||
assert canvas["action_candidates"][0]["href"] == "/project-launch?source=pmflow-ai"
|
||
assert canvas["action_candidates"][0]["action_payload"]["input"] == question
|
||
assert canvas["action_candidates"][0]["action_payload"]["launch_seed"]["source"] == "space_ai_turn"
|