@@ -15,6 +15,97 @@
- 关联文档:相关 PRD、技术文档、提交或 Issue
```
## 2026-09-05 Planning V2 一次性写路径对齐 V1 的项目锁等待窗口
- 背景:V2 审批修改意见后立即 `continue_planning_session_v2` 。审批、回合启动、策略落盘和 hydrate 原先无等待取锁,和 GUI 重灌或其它写操作撞车就返回 `项目正在被其他写操作占用` ,前端再映射成总控失败。V1 已用完整/短窗口处理同一形状。
- 决策:V2 审批、回合启动、策略落盘、失败投影和 GDD 认领使用完整等待窗口;V2 hydrate 使用短窗口。不引入可重入项目锁,不放宽失效回收。
- 影响范围:`planning_policy_v2.rs` 、`planning_session_v2.rs` 、V2 hydrate 前端瞬时争用处理。
- 验证方式:Rust 定向测试覆盖短暂占用下的审批、修订续跑和 hydrate。
- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 、`docs/project-memory/shared-memory/pitfalls.md` 。
## 2026-09-05 本进程新建 Windows 私有对象不因继承 DACL 自动 UAC
- 背景:#211 要求 sidecar 满足当前用户独占、禁止继承的 DACL。新建文件会先继承父目录 ACE,生产路径把这种短暂不合格送进 UAC;`project.lock` 还在独占句柄上 harden。含空格项目路径上提权 ArgumentList 被拆开,修复以 exit 1 失败。GDD 审批改意见因此弹权限,V1 锁创建不会。
- 决策:`harden_new_game_creator_private_path` 只在本进程收紧 owner/DACL,失败则删除刚创建的对象,不 UAC 接管。项目锁先写再释放句柄再 harden,并用内容回读防换绑;UAC 仍只用于允许范围内的已有外人本对象。提权 helper 的 ArgumentList 改为一条按 Windows 规则加引号的字符串。
- 影响范围:`config.rs` 的新建 harden 与提权命令行、`project/write_lock.rs` 的项目锁创建;不改变锁竞争、失效回收、Drop 删除,也不放宽 symlink / reparse / 外人本 fail-closed。
- 验证方式:Windows 定向测试覆盖 `Genarrative GameAgent\gameagent-*` 取锁与私有 DACL,以及带空格路径的 quoted ArgumentList。
- 关联文档:`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` 、`docs/project-memory/shared-memory/pitfalls.md` 。
## 2026-09-05 Planning V2 的 3 轮策略与 8 个问题门禁有意不对称
- 决策:模型提示最多提问 3 轮,并在达到 3 后要求出稿;Runtime `question_limit` 默认 8,对偏离模型策略的合法问题保留接收空间,达到 8 才拒绝新 question。前者是模型行为指令,后者是运行时接收边界,数值有意不同,不是缺陷或配置不一致。
- 评审口径:Session/UI 的 8 是容量,不是必须问满的配额;正常路径在 3 轮或更早出稿符合设计。不得仅因数值不同,把模型提示改为按 `question_limit` 出稿、把 3 改成可继续到 8 的软目标,或把 Runtime 门禁收紧为 3。
- 影响范围:仅补充文档解释,现有提示词、运行逻辑、校验和测试保持不变。
- 关联文档:[策划会话 Runtime V2 接入与旧链路退役方案 §1.3 ](../../technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md#13-问询策略与-runtime-门禁的不对称设计 )。
## 2026-09-04 Planning V2 将决定 ID 从 Provider 输入移回 Runtime
- 背景:`plan_submit_gdd` 原先要求模型生成 `decisions[].id` 及原型验证项引用 ID。该字段既不是方案内容,又容易出现 `initial_request` 、`initialRequest` 或错误层级,导致合法 GDD 在 Runtime 事后校验阶段失败。
- 决策:Provider-facing `plan_submit_gdd` schema 和入参删除决定/原型验证项 ID。Runtime 按决定数组顺序生成首项 `initial-request` 、后续 `decision-{序号}` ,并按 `prototype_pending` 决定顺序给原型验证项绑定同一 ID。最终持久化 `plan-gdd.v2` 仍保留 ID,供审批、引用和 fingerprint 使用。V2 尚未上线,不为旧 Provider 输入或历史 V2 artifact 增加兼容转换;不符合新契约的历史数据按现有失败策略处理。
- 影响范围:`planning_policy_v2.rs` 的工具 schema、Provider 入参解析、Runtime 产物构建与定向测试;Planning V2 技术方案。
- 验证方式:定向 Rust 测试确认 schema 不含 ID、无 ID 输入可生成 Runtime ID;并运行 `cargo fmt --check` 、`npm run check:encoding` 、`git diff --check` 。
- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_policy_v2.rs` 、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs` 。
## 2026-09-04 Planning V2 持久化每次 Provider 尝试的诊断产物
- 背景:Provider 已成功返回但策略解析失败时,原 V2 只保留最终错误,无法核对实际请求、原始工具参数和单次重试结果。
- 决策:在 `.agent/planning-v2/debug/<call-id>/` 保存每次尝试的 request、response 和分类事件;诊断文件不进入会话上下文,不参与恢复、重试或 GDD 业务判断,写入失败不改变主流程结果。
- 影响范围:`planning_session_v2.rs` 的 Provider 调用外围和 Planning V2 技术方案持久化目录说明。
- 验证方式:通过 Provider 请求/响应产物可还原每次尝试及 `toolCalls.arguments` ,并确认主流程仍按原有解析、重试和状态转换执行。
- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 、`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_session_v2.rs` 。
## 2026-09-04 Planning V2 把 `gdd.vN.json` 创建成功当作提交点
- 背景:V2 persist 先 create-only 写入不可变 GDD,再更新 index、Markdown、conversation 和 session。后续任一步失败会把 session 标成 `provider_failed` ,但不回滚已创建文件;重试会重新生成 UUID/时间戳并撞上“已存在且内容不同”,hydrate 又只信 `current_artifact_version` ,项目会卡死。
- 决策:`gdd.v{N}.json` 创建成功即提交点,禁止回滚不可变文件。persist / hydrate / 回合启动若发现 session 指针的下一个连续版本已在磁盘,必须读取既有 GDD 补投影,不得用新的 LLM 入参重建身份。session 指针写成功前的投影失败仍可返回 persist 错误,但恢复路径必须认领该版本。
- 影响范围:`planning_policy_v2.rs` persist/认领、`planning_session_v2.rs` hydrate 与回合启动;V2 技术方案。
- 验证方式:Rust 测试覆盖孤儿 GDD 重试认领、hydrate 认领、成功提交后仍分配下一版本;`cargo fmt --check` 、`npm run check:encoding` 、`git diff --check` 。
- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 。
## 2026-09-04 PlanningSessionRuntime V2 用协议工具输出问询和 GDD
- 背景:原型已验证 `plan_ask_question` / `plan_submit_gdd` 两个协议工具、深层 schema、提示词只留策略、`tool_choice=auto` 可跑通;生产 V2 仍解析正文 `{kind,question|gdd}` JSON,并把形状骨架写在 system prompt 里。浅 schema + 正文 JSON 会误导模型把 GDD 写成普通文本;`tool_choice=required` 与 DeepSeek thinking 不能同时使用。
- 决策:V2 Provider 请求固定挂这两个协议工具,`tool_choice=auto` , `strict=false` 。模型必须恰好调用其中一个;Runtime 解析 `toolCalls` 归一为 Question/Artifact,正文 JSON 视为非法。system prompt 只保留问询/出稿策略和当前问询进度,不再附 JSON 骨架或数量清单。入参不再要求模型回声 `schemaVersion` ,落盘 GDD 仍由 Runtime 写入 `plan-gdd.v2` 。既有结构门禁(含 `initial-request` 首项、`validate_plan_game` 数量/字数)不变,失败仍回灌一次。不把协议工具写入 `capabilities.tools` ,不执行 MCP/Skill,不把 `tool_call` /`tool_result` 写入会话消息。
- 影响范围:`planning_session_v2.rs` 请求构造、重试文案与 Provider 结果投影;`planning_policy_v2.rs` 工具 schema、解析和入参 `schemaVersion` ; V2 技术方案。
- 验证方式:Planning V2 定向 Rust 测试覆盖工具解析、缺 `schemaVersion` 的合法 GDD、正文 JSON 拒收、工具 schema 含嵌套 `game` 字段、提示词不再含骨架;`cargo fmt --check` 、`npm run check:encoding` 、`git diff --check` 。
- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 。
## 2026-09-03 新建策划会话采用 PlanningSessionRuntime V2,旧 Supervisor 链路直接退役
- 背景:现有“做方案”依赖 `project-supervisor-plan` 根 Run、`project-planning` 子 Run、静态委派、delivery、Acceptance Graph 和审批前 evidence。新策划 Agent 只需要单 Agent 会话、问询、GDD 和审批;继续在旧 Runtime 上逐条放宽会保留身份/编排耦合。未来策划 Agent 可能支持无限多轮、MCP 和 Skill,需要避免把当前 8 题/GDD/no-tools 固化为 Runtime 根结构。
- 决策:新增独立 `PlanningSessionRuntime` ,复用 Provider/流式、会话持久化、项目锁、原子写和基础错误恢复;当前启用 `mode=gdd` 、最多展示 8 个有效问题、GDD 审批和用户修改。新建“做方案”会话不创建 Supervisor root、planning child、delegation 或 acceptance evidence。V2 使用独立 `.agent/planning-v2/` 与 V2 schema,继续输出 `game/fast_gdd.md` ;不自动转换旧会话。
- 兼容性:Session 保存 `mode` 、可空 `questionLimit` 、`capabilities.tools/skills` ;完整会话记录与 Provider 请求上下文分离;消息模型预留 tool/skill 事件类型但本期不执行 MCP/Skill。无限问询、上下文摘要、多产物和能力执行以后作为策略/能力层扩展,不重新引入 Supervisor 身份模型。
- 当前进度:P0 合同冻结、P1 会话内核和 P2 GDD/审批核心已落地;P3 正式入口/UI 接入已开始,P5 旧链路退役尚未开始。
- 退役:V2 切换时旧链路直接封存;所有未完成旧会话投影为 `legacy_retired` 失败,禁止继续问询、审批、恢复或 continuation。旧 GDD、approval、conversation 和 `.agent/planning` 文件只读保留;旧入口 caller 关闭,但不删除旧代码、旧测试或旧数据。
- 影响范围:AGC 做方案入口、Rust/Tauri planning session/Provider adapter、GDD/审批 V2、前端 planning lane、阶段任务与 BDD 验收;做游戏/做素材 DirectProject 不变。
- 验证方式:按 `docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 的 P0~P5 阶段验收执行;至少覆盖第 8 个问题、上限后 question 抑制、Provider 失败、非法输出、批准/修改/退回、重启恢复、旧会话切换强制失败、迟到 Provider 结果丢弃和当前空能力快照。
- 关联文档:`docs/technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md` 、`docs/technical/【技术方案】立项策划Agent( Fast GDD) -2026-08-10.md` 。
## 2026-09-03 PlanningSessionRuntime V2 统一 Agent 推断语义
- 背景:旧 V1 使用 `default_pending` / `answerSource=default` 表示未提问时由 Agent 按默认建议补齐的字段;该语义会让 V2 的 Agent 推断看起来像产品默认值,也会造成原型与生产字段不一致。
- 决策:V2 只使用 `confirmed` 、`assumption_pending` 、`prototype_pending` 三种决定状态;`assumption_pending` 的来源统一为 `agent_inferred` 。`answerSource` 仍不是独立阻断项,缺失或不一致时按状态归一为 `user_freeform` 、`user_option` 或 `agent_inferred` 。V1 的 `default_pending` / `default` 校验和历史数据保持不动,不作为 V2 合同的一部分。
- 问询策略:V2 出稿前必须确认玩家核心行为、单局目标/核心循环、MVP 制作边界;其中任一仅由 Agent 推断时继续问一个关键问题。`questionLimit` 是 Runtime 对已展示问题数的硬上限,提示词中的“默认最多三轮”只是策略偏好,不要求与硬上限数值一致。
- 影响范围:V2 GDD 输入/产物、Provider system prompt、前端 V2 类型与决定状态展示;旧 Supervisor/V1 存储、校验和历史产物不变。
- 验证方式: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-04 PlanningSessionRuntime V2 提示词只保留形状和策略
- 背景:把逐字段长度、数量、类型清单写入 system prompt 后,提示词与 JSON 骨架、Rust 校验器三重叠,模型也难以消化长清单;精确数字已由校验失败的一次重试回灌。
- 决策:V2 system prompt 只保留问询/GDD 骨架、`game` 与 `decisions` / `prototypeValidationItems` 同级边界、状态枚举、首条 `initial-request` 约束,以及一行易错数量范围(options / keywords / pillars / coreLoop / mvpSystems / outOfScope / oneLiner)。不把逐字段长度、控制字符、label 去重等校验细则写入 prompt;校验范围、门禁和重试次数不变。
- 影响范围:`planning_session_v2.rs` 的 Provider system prompt; `planning_policy_v2.rs` 校验逻辑与非法输出重试路径不变。
- 验证方式:提示词含骨架与同级边界、不含逐字段长度清单;现有 Planning V2 定向测试、编码和 diff 检查通过。
- 关联文档:`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` 又会受到不同来源登录顺序影响。
@@ -1507,6 +1598,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 背景:主站与图片画板的泥点余额入口、余额明细和充值弹窗存在不同实现,旧充值口径仍展示六档泥点、首充双倍和会员购买 / 升级入口,容易让展示、商品资格与后端余额真相发生漂移。
- 决策:主站与图片画板统一复用公共泥点资产入口,收起态展示总额与充值,展开态只展示不限时泥点、每日免费泥点和使用详情;充值中心 BFF 继续统一下发总额、三桶余额、限时到期时间、每日免费基础重置额及下次重置时间,前端不得自行相减推算,但会员周期限时泥点仅用于存量兼容和后端结算,当前版本不在前台展示。钱包明细每次展开都重新读取充值中心 BFF,打开期间实时总额变化时继续补读;图片画板的生成扣费或退款完成后同时刷新总额与充值中心拆分。充值中心读请求必须使用 revision 门禁,支付创建、到账确认等权威响应写入时使旧读失效,避免旧响应覆盖新的每日免费 / 不限时明细。默认泥点商品收敛为 `60 / ¥6` 、`180 + 90 / ¥18` 、`300 + 150 / ¥30` 、`680 + 340 / ¥68` 四档,`60` 档无赠送,后三档按现有 `user_id + product_id` 独立资格规则首次购买加赠 `50%` 。当前版本关闭会员购买页签、会员商品和购买 / 升级入口。
- 2026-07-17 追加:主站、图片画板与 AI 游戏创作独立 App 的泥点账单统一复用 `packages/shared/src/components/PlatformProfileWalletLedgerModal` 。共享组件只依赖 `ProfileWalletLedgerResponse` ,承接来源 label、金额正负号、UTC 日期、余额兜底和 loading / empty / error 展示;`/api/profile/wallet-ledger` 请求、鉴权、打开状态与重试生命周期继续由各宿主持有,不把账户事实或后端副作用下沉到共享 UI。
- 2026-09-07 追加:资产扣费在既有钱包流水 metadata 中记录服务端确定的 `assetKind` , `GET /api/profile/wallet-ledger` 只把白名单类型映射为可选用户文案 `reason` ,不暴露原始 metadata、资源 ID、任务 ID 或未知内部枚举。共享账单组件优先展示非空 `reason` ;历史、未知和空 metadata 继续按 `sourceType` 回退为“资产操作消耗”,不得由客户端猜测业务类型。
- 影响范围:`profile_recharge_product_config` 默认商品、充值中心 read model、共享前后端契约、主站与图片画板泥点资产入口、充值弹窗、后台充值商品默认值。
- 验证方式:充值与统一入口定向前端测试、`npm run typecheck` 、充值商品定向 Rust 测试、`cargo check -p spacetime-module -p spacetime-client -p api-server --manifest-path server-rs/Cargo.toml` 、`npm run check:encoding` 、`git diff --check` 。
- 关联文档:`docs/【项目基线】当前产品与工程约束-2026-05-15.md` 、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md` 。
@@ -7960,6 +8052,19 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 新建/恢复 ephemeral Codex thread 时,replay 使用 `contextWindowTokens` 、`autoCompactTokenLimit` 、本次 `maxOutputTokens` 与 4096 安全余量计算预算,从最新记录向前选择连续完整的 `user` / `assistant` / `tool` 行;超预算旧前缀被省略,单条记录不截断,当前 user request 始终保留。
- 发生省略时在 prompt 开头加入普通 `system: Earlier conversation history was omitted due to context budget.` 提示;当前请求本身超过硬上下文预算则直接失败。该策略是 Direct 专用滑动窗口,不复用 Runtime Agent 的摘要、tail 或 session compaction 生命周期。
## 2026-09-05 共享 CanvasWorld 统一超采样与资源页迁移
- 背景:资源总览页曾在业务层重复实现 world 的渲染与尺寸逻辑,需与网站 / Tauri 共用的 `@genarrative/image-canvas-react` 统一。
- 决策:`CanvasWorld` 的公开契约为逻辑 `viewport` ,最终视觉比例由 `viewport.scale` 定义。渲染细节由共享包封装,调用方不得自行换算。所有调用方继续使用共享默认正方形 `CANVAS_WORLD_SIZE = 12000` ,不引入 `worldWidth/worldHeight` 等矩形 API。资源页 `navigationBounds` 只保留布局、fit、依赖线 geometry 和 data 属性用途,不再驱动 world DOM 尺寸。非缩放描边只应用于资源依赖关系线等几何 overlay,静态卡片图标不继承统一 SVG 描边规则;位图维持浏览器默认插值,不全局启用 `pixelated` 。
- 影响范围:资源总览迁移为直接渲染共享 `CanvasWorld` ,卡片控件通过共享 inverse-scale CSS 变量保持屏幕级尺寸;Asset Canvas、UI Editor 和依赖线继续消费相同 viewport 坐标与事件换算,不改变业务状态或持久化合同。
- 验证方式:调用方测试以预期逻辑 `{ x, y, scale }` 调用公开 helper `canvasViewportToWorldTransform` ,再与实际 world 的 `style.transform` 比较;不手写渲染换算,不以缩放按钮文案替代 viewport 断言。运行共享包与 AGC 定向类型 / 测试、资源页集成测试、`npm run check:encoding` 和 `git diff --check` ,覆盖 SVG 描边、拖拽坐标、关系线端点和默认 world 尺寸。
## 2026-09-07 DirectProject 用户消息由 AGC 预写并过滤 Codex 回显
- `.agent/conversations/project.jsonl` 中的 DirectProject 用户消息由 AGC 在 `turn/start` 前以 `direct-codex:{clientTurnId}:user` 幂等追加;写入失败时禁止发起 Codex turn,失败或中断也保留该 user item。
- Codex app-server 回显的 `userMessage` / `role=user` item 不是第二个历史来源。AGC 只处理其观察和关联,不再把该 echo 追加到项目历史;Codex 的 assistant、tool 和其它有效 response item 仍按现有 append-only 规则落盘。
- 本地 AGC user-item 写入必须使用允许 user item 的内部入口,Codex raw item 写入使用过滤入口,避免“过滤回显”反过来阻断预写。相同 `clientTurnId` 只能复用相同规范化 prompt,内容冲突必须失败关闭。
## 2026-08-31 AGC 错误报告与诊断上传
- AGC 采用 IDEA 风格的当前进程错误池:按 fingerprint 合并 React / window / Promise / Tauri / Agent 错误,重启后不恢复,不使用 run 或 run_id。
@@ -7983,6 +8088,37 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 生成文件名保留可读清洗前缀,并追加 asset ID 的 SHA-256 摘要前缀以避免不同 ID 碰撞;不迁移既有旧路径,调用方需在采用新命名后使用新返回路径。
- Radial90 的前端预览与 Rust 导出统一使用角点映射和顺时针起始角规则,顺时针填充从角点前一条边开始,避免两端渲染偏移。
## 2026-09-03 策划会话 Runtime V2 P1 内核落地
- 新增 `PlanningSessionRuntime V2` 内核入口:`start_planning_session_v2` 、`continue_planning_session_v2` 、`hydrate_planning_session_v2` 。P1 只负责单 Agent 会话生命周期、Provider 流式/普通调用、消息持久化、回合幂等、单项目单活跃回合、耗时和失败恢复,不接入 GDD 解析、审批或旧 Supervisor。
- V2 会话快照落在 `.agent/planning-v2/session.json` ,完整消息落在 `.agent/planning-v2/conversation.jsonl` 。同一 `clientTurnId` 已有成功 assistant 记录时直接重放;若只有 error 记录则允许沿用同一用户意图重试,不重复追加用户消息。进程退出后 hydrate 发现 `planning` 会投影为 `provider_failed/RECOVERY_REQUIRED` ,不伪造成功或自动重试。
- Provider 调用复用现有 `platform-llm` 的 API-kind、流式解析、超时和重试配置;当前策略快照固定 `mode=gdd` 、`questionLimit=8` 、`tools=[]` 、`skills=[]` 。GDD 业务规则留给 P2,生产 UI 接入留给 P3。
## 2026-09-03 策划会话 Runtime V2 P2 产物闭环
- V2 新增 `GddPlanningPolicy` : Provider 输出只接受合法 question 或完整 GDD JSON; question 在 `questionCount < questionLimit` 时保存并展示,第 8 个问题仍可展示,第 8 个之后再次返回 question 时只允许一次内部强制出稿重试,额外 question 不落盘、不进入用户等待态。
- V2 GDD 使用独立 `plan-gdd.v2` ,只保留项目身份、版本、游戏内容、决定、原型验证项和指纹,不带旧 Supervisor/Run/delegation 字段。每个版本写入 `.agent/planning-v2/gdd.vN.json` ,同步更新 V2 index 和 `game/fast_gdd.md` ;旧版本不可覆盖。
- 新增 `decide_planning_artifact_v2` 与 `plan-approval.v2` 。批准、修改、退回均绑定当前 Session、artifact、version 和 fingerprint;修改/退回必须有意见,修改后 Session 回到 `revision_requested` ,下一轮由同一 V2 Session 继续。`answerSource` 缺失或未知值回退,不成为单独阻断项。
## 2026-09-03 策划会话 Runtime V2 P3 入口与 UI 接入开始
- 正式 AGC“做方案”入口在 `planningStartMode` 下直接调用 `start_planning_session_v2` 、`continue_planning_session_v2` 和 `decide_planning_artifact_v2` ,不再为新策划回合创建 Supervisor root、child Run 或 delegation。
- 前端以适配层复用现有聊天区、澄清输入卡、GDD 审批卡和阶段进度条;V2 hydrate 返回 `conversation` 消息,用于页面刷新和重启后恢复可见历史。
- V2 会话使用独立 `planning-session-v2-stream` 事件,旧 Supervisor Runtime 轮询、专业 Agent 轮询和旧 Runtime 事件不会介入 V2 会话。
- 没有 V2 authority 的项目仍按旧读取路径打开;旧链路封存、未完成旧会话强制失败和旧入口彻底关闭仍留在 P5。
## 2026-09-05 策划会话 Runtime V2 P4 收口
- Planning V2 的 P4 灰度与回归验收已通过人工校验:正常提问/回答/GDD/批准链路、GDD 修改后再次批准链路、Provider 失败恢复、非法输出失败边界、重启恢复、前端工作台展示以及编码/差异门禁均完成验证。
- P4 收口不代表旧链路退役;旧 `project-supervisor-plan` / `project-planning` 源码和入口仍保留,旧活跃会话封存、迟到结果隔离、旧入口关闭和只读历史展示统一留在后续 P5。
- P5 收缩为最小退役:旧 `project-supervisor-plan` caller 统一立即返回退役错误,不启动旧 Runtime/Provider;不扩展 V1 `PlanSessionV1` schema,不做旧数据迁移,旧文件继续保留只读,V2 只读取 `.agent/planning-v2` 。
## 2026-09-05 修正 Planning V2 流式交互契约
- Planning V2 不要求把 Provider 的文本 stream delta 逐条投影为用户可见对话。V2 的用户交互是结构化工具调用结果:`plan_ask_question` 渲染澄清选项卡,`plan_submit_gdd` 渲染 GDD 输出和审批卡;中间纯文本不是用户对话内容。
- `planning-session-v2-stream` 若继续存在,只能作为内部状态/兼容事件能力,不构成实时逐 delta 的功能契约;Provider 是否使用流式传输不影响 V2 的业务验收。
- 文档措辞约束:凡出现“流式响应”“流式事件”或 `text_delta` ,均须注明其属于 Provider adapter/Runtime 内部实现能力;不得将其描述为前端必须逐条接收的用户可见消息。V2 的唯一用户交互结果是 `plan_ask_question` 和 `plan_submit_gdd` 的结构化工具结果,Provider 完成前是否产生多个 delta 不参与验收。
## 2026-08-29 AGC 官方 LLM 代理与 Windows 私有路径修复
## 2026-08-29 AGC 官方 LLM 代理与 Windows 私有路径修复
@@ -8034,3 +8170,40 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 配置契约提升为 `game-creator-config.v2` :新模板默认 `stream=true` 、受控搜索开启;无版本旧 DirectProject 配置仅在省略 `webSearchEnabled` 时把历史默认补为开启,旧配置显式 `false` 不覆盖,v2 显式 `false` 同样保留;Provider / Anthropic 未提供搜索覆盖时保持关闭。本地覆盖配置只补 schema 版本,不凭不完整 overlay 推断或写入 `agentMode` / 搜索布尔值;未知版本失败关闭。
- 搜索结果始终是不可信外部输入,只可作为资料;工具 schema、参数、客户端权限、Agent 身份、系统规则和工具协议不得由网页内容修改。搜索结果与状态投影不携带 API Key、请求头、宿主绝对路径或 Provider 原始错误正文。
- 验证锁定:`configuration` 、`direct_tools_mcp` 、`direct_tool_bridge` 、`codex_app_server` 定向 Rust 测试,以及前端状态格式化 / AppSurface 测试;真实 Provider 登录态与真实公网搜索仍需单独现场 smoke。
## 2026-09-08 策划 V1 链路源码整体退役(四不写)
- 策划会话 Runtime V2 全量接管“做方案”入口后,旧 V1 链路(`project-supervisor-plan` 根 Run、`project-planning` 子 Agent、`plan.submit_gdd` 工具、Fast GDD 审批门禁与恢复车道)按四不写原则整体删除源码,不保留兼容实现、墓碑注释或防御性测试。
- 删除范围:`runtime_protocol` 六个 V1 模块与四条 V1 提示词、prompt manifest planning 目录与生成常量、`capabilities.planning` 配置开关、CLI `--swarm-chat --plan` 与 `--plan-gdd-status/--plan-gdd-decide` 、provider_retry 的 planning session binding、provider_action_batch 的 V1 提交批次校验、main_loop/pending_recovery/recovery_scan/acceptance_graph 的 plan 根特判、agent_db 三条 V1 专用持久车道(`agent.runtime.plan.provider_usage` 、`agent.runtime.plan.gdd_decided` 、`agent.runtime.plan_submit_gdd.committed` )及预留配额、前端旧 V1 读模型、`scripts/agent-swarm-test-chat.mjs --plan` 与 `test:plan*` 脚本。
- 保留项:V2 与 V1 共用的 GDD 数据模型收敛到 `runtime_protocol/planning_gdd_model.rs` ; `.agent/planning/` 旧文件不迁移、不删除,旧 `fast_gdd.md` 仍可只读打开;前端 `PROJECT_SUPERVISOR_PLAN_SOURCE` 字符串与 `GddApprovalCard.tsx` ( `PlanGddSurface` )是 V2 现役的适配/展示面,不属于退役对象。
- 旧 sidecar 中带已删字段(`clarification` 、`continuation` 、`requestId` 、`turnId` 、`pendingApproval` 等)的记录会因 `deny_unknown_fields` 拒绝反序列化,这是退役语义的一部分,不做迁移。
- 测试基线说明:收尾时测试套件存在 25 个既有失败(mock LLM 时序敏感类,HEAD worktree 对照验证与本次无关),后续清理时不要误记到本次退役头上。
## 2026-09-08 Planning V2 正常 run 优先的恢复旁路
- 恢复只利用已经落盘的合法 question、GDD 和 approval receipt;不调用 Provider、不要求模型额外输出恢复字段、不设置复杂状态机或自动重试。
- 正常 run 进行时不读取或写入其 Planning V2 文件,也不增加文件锁或等待;无活跃 run 时恢复只做一次非阻塞锁尝试,竞争即退出,交给既有轮询。
- question 恢复为成功结果,approval 重放复用 receipt 原始 decisionId。
## 2026-09-08 Planning V2 用户输入与异步投影身份
- 问题回答携带被回答卡片的 questionId,在已有回合锁内核对 Session 和当前问题;自由文本回答同样绑定问题,已完成回合保留幂等重放。此身份匹配服务于用户提交,不增加恢复门禁或模型输出要求。
- hydrate 结果(包括空结果)写入前端状态前同时核对请求序列和当前项目路径;过期结果直接丢弃,不重试、不阻塞正常 run。
## 2026-09-09 项目写锁残留回收与启动诊断
- 决策:`.agent/project.lock` 记录 `processStartedAt` ;PID 存活时用启动身份区分“原持有者仍在”与“PID 被复用”,身份不一致才回收。旧锁无该字段时用“进程启动时间晚于锁 `createdAt` + 5 秒容差”推断,锁创建时间未知时不做该推断。空锁 / 坏锁(崩溃停在 `create_new` 与落盘之间)宽限期 30 秒,无法判定存活时保持 600 秒,mtime 不可读时按未知年龄不回收。活持有者始终不回收。
- 决策:回收判据与删除基于同一次读到的锁文件快照——payload 只解析一次,删除前重新核对字节,只有内容仍是判定时的内容才 unlink;文件已消失或被替换时重试 `create_new` ,不把并发回收当成错误。
- 决策:启动诊断日志用 `StartupLogSlot` ,优先用已生效的配置目录(含 `--config-dir` ),否则退到平台配置根(Windows APPDATA、macOS Application Support、其它平台 `XDG_CONFIG_HOME` / `~/.config` ),配置目录就绪后再切换;`startup.*.failed` 与 `show_startup_error_dialog` 必须可达,日志路径未知时也必须给出用户可见提示;Windows 启动失败弹系统消息框,其它平台写 stderr。
- 边界:`agent-runner.lock` / `agent-runner.gui-owner.lock` 是 OS 独占句柄锁,进程退出即释放,残留文件不阻塞下次启动;不要把它们当成项目写锁的同类残留处理。
- 边界:锁文件里的 PID 若超出平台进程号空间(Unix `pid_t` 是有符号 32 位、Windows 是 32 位,均恒大于 0),它不可能属于任何活进程,按“持有者不存在”直接回收,不再落回 600 秒保守分支。
- 验证:`project_lock_recovery` 11 条与 `diagnostic_log` 7 条定向测试通过,真实二进制双实例复现“第二个实例写 `startup.runner.owner-lock.failed` 并弹出可见提示”。
## 2026-09-10 Direct 写通道纳入统一项目锁等待窗口并补齐持锁方可诊断
- 背景:Issue #318 。`agc_write_file` 是用户直接触发、失败即整轮无法落盘的项目写入通道,却用零等待取锁,任何重叠都在 24-42ms 内被投影成“项目正在被其他写操作占用”;同一形状已在 2026-07-22 由 `file.write / file.patch / file.delete` 用有界等待修过,本项目技术方案的 2026-08-13 一节也已规定这类争用结果“统一投影为争用并进入既有有界等待”。现场取证还缺 `commandId / pid / createdAt / ownerIsSelf` ,无法回答“谁在持锁”,加上 `create_new` 把 ACL 拒绝、delete-pending 和真实跨进程争用压成同一句话,排障被引向“残留锁”。
- 决策:① Direct 写路径改用 `acquire_game_creator_agent_runtime_project_write_lock_with_wait` ,与其它写入口同语义,同一轮并行写按同一把锁串行。①′ 这条等待是同步轮询(最多约 10 秒),handler 是 async,因此写路径经 `spawn_blocking` 走阻塞线程池:直接在 handler 里同步等待会占住 tokio worker,争用窗口内并行写多个文件时会波及共享同一 runtime 的只读端点与 UI 命令,破坏 Issue #318 现场“只读工具全部正常”的诊断特征。② 争用错误前缀逐字不变并追加持锁方身份;`create_new` 失败拆成可重试(进入有界等待)/ 权限拒绝(失败关闭,文案不含争用前缀)/ 其它三类,**重试性只看错误码**:Windows 的 `ACCESS_DENIED(5)` 与删除拆链窗口在错误码上不可区分,一律先按可重试处理,等满预算且目标仍不存在时才由 `exhausted_projection` 改判成权限拒绝(单次试探不改判);`sharing violation(32)` 与 `lock violation(33)` 恒定归可重试。③ 等待预算耗尽时按 `project.write_lock.wait_exhausted` 记录持锁方快照、等待时长与 `projection=` ( contention / permission_denied),Unix 上明确判定的权限拒绝按 `project.write_lock.permission_denied` 记录;这条日志与终态改判都只在真的等过(`max_attempts > 1` )时发生,hydrate 的单次试探既不写日志也不改判。④ 重试与否改由类型决定:`acquire_project_write_lock_failure` 返回 `ProjectWriteLockFailure::{Retryable, Terminal}` ,有界等待按 `is_retryable()` 分流,`acquire_project_write_lock` 只是它的文案包装;`PROJECT_WRITE_LOCK_CONTENTION_PREFIX` 同时收口 `provider_recovery.rs` / `planning_session_v2.rs` / `direct_runtime.rs` 三处手写文案。⑤ 平台判据的每一环都要带平台:终态改判也曾只比 `ErrorKind` ,而 errno 5 在 Windows 是 `ACCESS_DENIED` 、在 Linux 是 `EIO` , CI 直接把它判成 `contention` ;现由 `Retryable { platform, path, source }` 携带平台。
- 为什么不按“目标是否存在”当场分类:目标被删除时目录项先消失、删除挂起随后才结束,`create_new` 会在这个拆链窗口里返回 `ACCESS_DENIED(5)` 而 `exists()` 已经报 false(本机 6 万次建锁 / 删锁竞争实测 396-538 例命中该组合)。按一次 metadata 观察判成权限拒绝,等待层会立刻失败关闭,等于把 Issue #318 的“毫秒级直接失败”换成更误导的 ACL 文案;这也是对 2026-08-13 已定口径“这些结果统一投影为争用并进入既有有界等待”的回归。
- 复用既有实现:回收判据沿用 2026-09-09 的 `ProjectWriteLockSnapshot` + `project_write_lock_reclaim_decision` + 字节 CAS 删除,不新增第二套回收机制;本次只给快照补 `commandId` 与 `describe_holder()` ,供错误文案和日志使用。
- 不做什么:不放宽 `.agent/project.lock` 的项目级串行化语义,不引入可重入项目锁,不改“同一调用链禁止二次获取 `.agent/project.lock` ”的既有约定,不改 AGC 多进程拓扑,不改 `pendingOperations` 语义,也不改“活持有者始终不回收”的既有判据。其它仍用零等待取锁的入口(`command.exec / project.verify / memory / conversation / task / checkpoint / 预览 / UI 编辑器 / 资源编辑器 / Tauri 命令` )不在本次范围。
- 验证方式:`project_lock_recovery` 追加持锁方身份与权限拒绝两条;`direct_tool_bridge` 追加同进程重叠写等待、同轮并行写、有界等待不占 runtime worker(默认 `current_thread` runtime 加心跳任务,同步阻塞会立刻让心跳停摆)、ACL 拒绝不投影成争用四条;`project/write_lock` 追加“重试性只由错误码决定”与“终态改判三条件”两条平台无关用例(平台作参数传入,Linux CI 覆盖 Windows 分支)。Windows 本机定向结果:`project_write_lock` 18 条、`bridge_write_file` 4 条、`parent_wake` 16 条、`waits_across` 3 条全过;CI( `71e9ad313` )四个 job 全绿,其中 Native shell tests 的首轮失败正是第 ⑤ 条平台判据缺陷。
- 关联文档:`docs/project-memory/shared-memory/pitfalls.md` 、`docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` 、Issue #318 。