From 45568797f9a952a15d196cefe783456bbbdccaca Mon Sep 17 00:00:00 2001 From: Linghong Date: Fri, 4 Sep 2026 07:40:36 +0000 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E7=AD=96=E5=88=92=20V2=20=E6=97=A2?= =?UTF-8?q?=E6=9C=89=E9=98=BB=E6=96=AD=E6=A0=A1=E9=AA=8C=E5=9B=9E=E7=81=8C?= =?UTF-8?q?=E7=BB=99=20Provider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把当前 question/GDD 硬校验契约写入 V2 system prompt,不扩大校验范围或新增门禁 校验失败的一次重试改为列出具体阻断原因并要求逐项修复 同步 Runtime V2 技术方案和项目决策记录 --- .../runtime_protocol/planning_session_v2.rs | 20 +++++++++++++++++-- .../shared-memory/decision-log.md | 8 ++++++++ ...策划会话RuntimeV2接入与旧链路退役-2026-09-03.md | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs index 490f5501d..7f68ba256 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs @@ -625,6 +625,21 @@ GDD 输出必须严格使用下面的字段名和层级;不要增加其它字 } } decisions[] 每项只能有 id、topic、state、answerSource、round、answerSummary;answerSource 可以省略,但不能使用 decision、question、answer 或其它字段。state 只能是 confirmed、assumption_pending、prototype_pending;没有被用户明确决定、由 Agent 根据上下文补出的内容使用 assumption_pending,并将 answerSource 记为 agent_inferred。prototype_pending 决定必须在 prototypeValidationItems 中有同 id 的 question、microPrototype、observation、passCriterion。 + +以下是当前 Runtime 已存在的输出硬校验契约;不是新增门禁。返回前请逐项检查,避免因类型、数量、长度或额外字段导致输出被拒收: +- 所有 JSON 字段名必须使用上面给出的 camelCase;question、选项、GDD 及其嵌套对象不能增加未列出的字段。所有受校验的文本字段必须首尾无空白,不得包含回车、NUL、DEL 或其它不允许的控制字符。 +- question 必须是对象,且只能包含 id、header、question、options;id 必须是小写 snake_case、1~32 个字符;header 是 1~120 个字符的非空字符串;question 是 1~400 个字符的非空字符串;options 必须是 2~4 项数组。 +- 每个 question option 必须是对象且只能包含 label、description;label 必须非空、1~80 个字符,description 必须非空、1~400 个字符;所有 label 不能重复。 +- GDD 的 schemaVersion 必须严格为 plan-gdd.v2;game、decisions、prototypeValidationItems 必须存在且类型正确;game 不要输出 platformFacts(由 Runtime 注入固定平台事实)。 +- game.title 为 1~80 个字符;genre.primary 为 1~40 个字符,genre.fusion 可以为 null,否则必须是 1~40 个字符的字符串。 +- artStyle.visualType 为 1~80 个字符;keywords 必须是 3~5 个互不重复的字符串,每项 1~32 个字符;moodAndColor、mvpArtBoundary 各为 1~400 个字符;oneLiner 必须是 45~90 个字符。 +- pillars 必须是 2~4 项;每项 name 必须唯一且为 1~40 个字符,playerFeel 和 mechanism 各为 1~240 个字符,decisionState 只能是 confirmed、assumption_pending、prototype_pending。 +- coreLoop 必须是 4~8 个非空字符串,每步 1~120 个字符;targetUsers 的 coreUsers、preferences、sessionLength 各为 1~240 个字符,referenceGames 必须是数组且最多 5 项,每项为 1~80 个字符。 +- mvpSystems 必须是 3~6 项;每项 system 必须唯一且为 1~40 个字符,minimalFunction、whyRequired、verifyMethod 各为 1~240 个字符,decisionState 只能使用上述三种状态。 +- outOfScope 必须是 1~12 个互不重复的字符串,每项 1~80 个字符;creatorTips 的 doFirst、deferForNow、howToVerify、expandWhen 各为 1~400 个字符。 +- decisions 必须是 1~64 项且 id 不能重复;第一项必须是唯一的 initial-request,state 必须为 confirmed、round 必须为 0。其它 id 必须以小写字母开头,只能使用小写字母、数字和连字符,长度 1~64;topic 为 1~120 个字符;state 只能使用上述三种状态;round 必须是非负整数。 +- decisions[].answerSummary 为非空字符串;initial-request 最多 4001 个字符,其它决定最多 400 个字符。answerSource 可以省略或使用任意值,Runtime 不因其缺失/未知值单独拒收;不要使用 V1 的 default_pending / default 语义。 +- prototypeValidationItems 必须是数组,最多 3 项;没有 prototype_pending 决定时必须为空;有 prototype_pending 决定时必须与这些决定按 id 一一对应,不能多也不能少。每项 id 只能使用小写字母、数字和连字符,长度 1~64,且 question、microPrototype、observation、passCriterion 都必须是 1~400 个字符的非空字符串。 "#; let system = platform_llm::LlmMessage::system(format!( "你是 Planning Session V2 的立项策划 Agent。当前会话 {},回合 {}。只返回一个合法 JSON object,不要 Markdown 代码围栏、解释文字、Supervisor、子 Agent、委派或验收协议。\n\n{}\n\n出稿前必须先确认三项核心闭环信息:玩家核心行为(玩家每一局反复做什么)、单局目标/核心循环(怎样算完成一局)、MVP 制作边界(首个可玩版本做什么、不做什么)。只要其中一项仍然只是 Agent 推断、没有出现在用户需求或用户回答中,就继续只问一个最关键的问题,不能用 assumption_pending 代替用户确认;主题包装、美术、数值和次要系统可以先使用 assumption_pending,并将 answerSource 记为 agent_inferred。不要重复已经回答的问题。\n\n如果需要向用户确认,只返回 {{\"kind\":\"question\",\"question\":{{\"id\":\"snake_case_id\",\"header\":\"当前要决定:...\",\"question\":\"...\",\"options\":[{{\"label\":\"方案 A\",\"description\":\"...\"}},{{\"label\":\"方案 B\",\"description\":\"...\"}}]}}}}。如果信息足够或问题数已达到上限,只返回上面完整形状的 {{\"kind\":\"gdd\",\"gdd\":...}}。GDD 必须完整填写所有字段,不要省略字段。\n\n{}", @@ -846,10 +861,11 @@ where Ok(output) => break output, Err(detail) if policy_retry < 1 => { policy_retry = policy_retry.saturating_add(1); + let retry_detail = detail.replace('\n', "\n- "); attempt_prompt = format!( - "{}\n\n【Runtime】上一次输出未通过策划协议:{}。请只返回合法 JSON;当前只允许返回合法 question 或完整 GDD,不要输出解释文字。{}", + "{}\n\n【阻断校验失败】Runtime 拒绝了上一次输出,具体原因如下:\n- {}\n请针对以上原因逐项修复,保持未涉及内容不变,只返回合法 JSON;当前只允许返回合法 question 或完整 GDD,不要输出解释文字。{}", prompt, - detail, + retry_detail, if start.session.question_limit.is_some_and(|limit| { start.session.question_count >= limit }) { diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 23ed380ad..8bef9a086 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -35,6 +35,14 @@ - 验证方式:V2 解析 `assumption_pending` 不报错并落盘为 `assumption_pending/agent_inferred`;`default_pending` 不作为 V2 合法状态;核心三项未确认时提示词要求继续问询;相关 Rust/TS 定向测试、类型和编码检查通过。 - 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md`、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_policy_v2.rs`。 +## 2026-09-04 PlanningSessionRuntime V2 将既有输出阻断原因回灌给 Provider + +- 背景:原型已将会导致输出拒收的字段、类型、数量和长度契约写入提示词,并在校验失败重试时回灌具体原因;生产 V2 仍只有简要 GDD 形状提示,模型可能重复犯同一结构错误。 +- 决策:生产 V2 只同步当前已经存在的 question/GDD 校验契约到 Provider system prompt,并在现有一次重试中明确列出本次阻断原因、要求逐项修复;不扩大校验范围、不新增门禁、不增加重试次数,也不把 `answerSource` 变成阻断条件。 +- 影响范围:`planning_session_v2.rs` 的 Provider prompt 与现有非法输出重试提示;`planning_policy_v2.rs` 校验逻辑、问询上限和持久化契约不变。 +- 验证方式:运行 Planning V2 定向 Rust 测试、`cargo fmt --check`、`git diff --check`,确认提示词构造和现有校验路径通过;不改变既有校验结果。 +- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md`、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs`。 + ## 2026-09-03 AGC 登录 route event 使用 handler 已验证主体归属 - 背景:登录请求进入时尚未拥有 `AuthenticatedAccessToken`,通用 tracking middleware 无法从响应 extensions 归属登录成功用户;将 AGC marker 直接写入按用户/业务日幂等的 `daily_login` 又会受到不同来源登录顺序影响。 diff --git a/docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md b/docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md index 4414d8c8f..19aa1a888 100644 --- a/docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md +++ b/docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md @@ -717,7 +717,7 @@ hydrate_planning_session_v2 - 对已存在 V2 Session 的项目,打开项目时先 hydrate V2;没有 V2 authority 的旧项目继续走旧读取路径,避免误把旧项目数据当成 V2。 - P3 已完成;旧会话 `legacy_retired` 封存、入口彻底关闭和真实 Provider/UI 全链路回归仍属于 P4/P5。 -P3 首轮人工测试暴露的问题已在进入 P4 前修正:做方案创建工作区不再额外调用自动项目命名 Provider;策划等待态立即显示处理中提示;V2 GDD 提示词明确给出完整嵌套字段和 `decisions[]` 契约;失败结果不重复渲染,GDD 结构错误给出可操作的重试提示。严格解析和失败不落盘成功产物的规则保持不变。 +P3 首轮人工测试暴露的问题已在进入 P4 前修正:做方案创建工作区不再额外调用自动项目命名 Provider;策划等待态立即显示处理中提示;V2 GDD 提示词明确给出完整嵌套字段和 `decisions[]` 契约;当前已存在的 question/GDD 硬校验(字段类型、数量、长度、额外字段和 prototype_pending 对应关系)同步写入 Provider 提示词,不新增校验范围或门禁;输出校验失败的重试提示携带具体阻断原因,要求逐项修复;失败结果不重复渲染,GDD 结构错误给出可操作的重试提示。严格解析和失败不落盘成功产物的规则保持不变。 ### P4:灰度、真实 Provider 与回归验收