Merge remote-tracking branch 'origin/master' into opt/win-ssache
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
|
||||
- [AI 游戏创作智能体 App 实施计划](./technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md):当前 DirectProject、受控语义工具、UI workflow、资源和运行时合同。
|
||||
- [AGC 异步操作可恢复闭环](./【技术方案】AGC异步操作可恢复闭环-2026-09-14.md):认证响应体、最近项目检查和首页自动创建的超时、逐项恢复与跨页防重合同。
|
||||
- [AGC 客户端稳定版生命周期大切换](./【技术方案】AGC客户端稳定版生命周期大切换-2026-09-14.md):统一 operation、认证/Runner、项目入口、本地恢复和 dev-stack 身份边界。
|
||||
- [策划会话 Runtime V2 接入与旧链路退役方案](./technical/【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md):新单 Agent 策划会话、GDD 策略、未来 MCP/Skill 兼容插槽、阶段任务与退役验收合同。
|
||||
- [DirectProject Codex 原始历史与异常恢复](<./technical/【技术方案】DirectProject Codex原始历史与异常恢复-2026-09-04.md>):原始 Responses item 持久化、线程注入与异常回合收尾。
|
||||
- [DirectProject 客户端 Skill 与 MCP 扩展导入方案](./technical/【技术方案】DirectProject客户端Skill与MCP扩展导入方案-2026-08-31.md):客户端扩展导入、按独立 Skill/MCP 拆分、命名、启用和启动时注入边界。
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
Version: 1.0
|
||||
Status: implemented; real-project runtime smoke pending
|
||||
Date: 2026-09-14
|
||||
Parent Milestone: docs/project-memory/plans/【里程碑】DirectProject Phaser迁移闭环-2026-09-14.md
|
||||
|
||||
## 修改顺序
|
||||
|
||||
1. 扩展 shared command contract 与原生工具 schema。
|
||||
2. 增加 `project.bootstrap` 的安全校验、npm install 执行、审计与分发。
|
||||
3. 扩展 `project.verify` 的 cwd/package/dist 门禁和提示词。
|
||||
4. 更新 DirectProject 迁移工程指导与前端命令显示。
|
||||
5. 补充定向测试并运行 typecheck、Rust 检查、编码与 diff 检查。
|
||||
|
||||
## 验证命令
|
||||
|
||||
- `npm run ai-game-creator-shell:typecheck`
|
||||
- `cargo test -p ai-game-creator-shell project_bootstrap`
|
||||
- `cargo test -p ai-game-creator-shell project_verify`
|
||||
- `npm run check:encoding`
|
||||
- `git diff --check`
|
||||
|
||||
## 风险与回滚
|
||||
|
||||
- 旧 `project.verify` 输入不带 cwd 时保持项目根行为。
|
||||
- bootstrap 不修改 command.exec 的 npm 白名单;失败关闭并返回可诊断错误。
|
||||
- 若 sandbox 网络能力无法在当前平台验证,仅保留实现与单测证据,不宣称真实安装通过。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 【实施计划】项目客户端占用锁收敛-2026-09-14
|
||||
|
||||
Version: 1
|
||||
Status: in-progress
|
||||
Date: 2026-09-14
|
||||
Milestone: `【里程碑】项目客户端占用锁收敛-2026-09-14.md`
|
||||
|
||||
## 代码边界
|
||||
|
||||
- `apps/ai-game-creator-shell/src-tauri/src/project/write_lock.rs`
|
||||
- `apps/ai-game-creator-shell/src-tauri/src/runner/project_owner.rs`
|
||||
- `apps/ai-game-creator-shell/src-tauri/src/runner/protocol.rs`
|
||||
- 锁恢复、Runtime 写入和 Runner owner 定向测试
|
||||
|
||||
## 修改顺序
|
||||
|
||||
1. 统一同进程嵌套调用的项目锁语义,禁止自等待。
|
||||
2. 盘点并迁移 Runner 的项目级 owner 文件到统一锁,保留诊断投影与跨 boot 恢复。
|
||||
3. 删除重复项目级锁路径及其专属调用,保留底层原子写和 Git 锁。
|
||||
4. 补齐同进程重入、跨进程占用、崩溃恢复和锁释放测试。
|
||||
|
||||
## 验证命令
|
||||
|
||||
- `cargo fmt --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --check`
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_write_lock_reuses_same_process_owner_and_releases_on_drop --no-default-features`
|
||||
- Runner owner 与 response stream 相关定向测试
|
||||
- `npm run check:encoding`
|
||||
- `git diff --check`
|
||||
|
||||
## 风险与回滚点
|
||||
|
||||
- Runner 与 GUI 可能是不同进程;统一锁前必须验证同一客户端不会互相阻塞。
|
||||
- 旧 `.agent/runtime/execution-owner.lock` 残留需要按 PID/启动身份安全回收,不能直接删除。
|
||||
- 若跨 boot 恢复或 GUI/Runner 联动回归,回滚统一路径迁移,保留已验证的同进程重入修复。
|
||||
@@ -0,0 +1,28 @@
|
||||
Version: 1.0
|
||||
Status: implemented; real-project runtime smoke pending
|
||||
Date: 2026-09-14
|
||||
Parent Spec: docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md
|
||||
|
||||
## 目标
|
||||
|
||||
为 DirectProject 建立单 HTML 到 Phaser 4 + Vite 的可运行迁移闭环:项目文件真实落盘、受控依赖初始化、`game` 子目录构建验证、`game/dist` 预览与桌面/移动验收。
|
||||
|
||||
## 边界
|
||||
|
||||
- DirectProject 迁移请求固定使用 `workspaceMode=DirectProject`,不再通过 JSON Generator 的 `gameHtml` 协议生成 npm 工程。
|
||||
- `project.bootstrap` 只允许在项目内 `game` 目录执行无参数 `npm install`,读取并记录 package/lock 指纹。
|
||||
- `project.verify` 支持相对 `cwd`,构建验证必须读取该目录 package.json 的原始脚本并确认 `dist/index.html`。
|
||||
- 预览继续只读取构建产物;不实现自动迁移未知游戏玩法语义或真实 Provider 生成。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 命令契约、原生工具 schema、运行时分发、权限面板和提示词包含 `project.bootstrap`。
|
||||
2. bootstrap 拒绝越界 cwd、非 `game` 目录、参数注入和缺失/非法 package 文件,并在成功后返回依赖指纹。
|
||||
3. `project.verify` 能在 `cwd=game` 执行原样 `npm run build`,成功条件包含 `game/dist/index.html`。
|
||||
4. DirectProject 提示明确要求 Phaser 4.2.1、`import Phaser from 'phaser'`、Vite 输出 `game/dist` 及完整玩法迁移。
|
||||
5. 定向 Rust/TypeScript 测试、类型检查、编码检查和 `git diff --check` 通过;无法运行真实 Provider/浏览器时明确记录。
|
||||
|
||||
## 依赖
|
||||
|
||||
- 现有 project command sandbox、verification gate、preview resolver 和 command run/audit 持久化。
|
||||
- 用户选择的真实项目目录必须包含 `game/index.html` 才能执行实际迁移。
|
||||
@@ -0,0 +1,28 @@
|
||||
# 【里程碑】项目客户端占用锁收敛-2026-09-14
|
||||
|
||||
Version: 1
|
||||
Status: in-progress
|
||||
Date: 2026-09-14
|
||||
Parent Spec: `docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md`
|
||||
|
||||
## 目标
|
||||
|
||||
项目只保留一个面向客户端占用的项目级跨进程锁,防止多个客户端同时打开同一项目;同一客户端进程内的嵌套调用复用既有项目锁,不因自身持锁进入等待。
|
||||
|
||||
## 边界
|
||||
|
||||
- 项目客户端占用锁与项目写入调用的职责统一,跨进程竞争仍返回占用语义。
|
||||
- Agent DB、session lane、manifest 原子写和 Git 自身的底层一致性机制不在本里程碑删除范围内。
|
||||
- 不改变项目 revision、权限、幂等、恢复和数据格式合同。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 同一进程内嵌套取得项目锁立即返回 advisory guard,不等待、不删除真实持有者锁。
|
||||
- 不同进程持有项目锁时仍保持占用失败与残留回收判据。
|
||||
- 客户端项目占用入口与 Runtime 写入入口不会各自维护第二个项目级锁文件。
|
||||
- 锁释放后下一客户端可重新取得锁。
|
||||
- 定向 Rust 锁测试、`cargo fmt --check`、`npm run check:encoding`、`git diff --check` 通过。
|
||||
|
||||
## 未决事项
|
||||
|
||||
- Runner 的 `execution-owner.lock` 如何迁移到统一客户端占用锁,需要补充跨进程启动、恢复和诊断测试后再落地。
|
||||
@@ -5495,3 +5495,10 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
- **真机判据**:点进任一栏目(或展开「所有资源」)时,**每一张**卡片都从它那一摞的位置/尺寸位移并缩放到自己的位置,而不只是总览里那 3 张;同一栏目里不同类型的两摞各自飞各自的卡。`prefers-reduced-motion: reduce` 下仍不播放动画(口径未改)。
|
||||
- **已知未覆盖**:① 子画布内直接切到另一个栏目(分页画布换栏目)时目标栏目的卡片在该次 `begin` 时未渲染、拿不到任何 First,整段转场仍按旧口径跳过(`play` 的 `!captured.entries.size` 早退),本次未改;② 真机动画观感由浏览器渲染,jsdom 只覆盖几何与调用契约,需要按上面那条判据人工确认一次。
|
||||
- **关联**:`apps/ai-game-creator-shell/src/view/project-development/resourceBookController.ts`(`begin` 的堆锚点 / `syncNodes` 的合成 First)、`resourceBookLayout.ts`(`allOpen` 列号)、`index.tsx`(宿主 `data-resource-book-stack-*`)、`apps/ai-game-creator-shell/tests/{resourceBookController,resourceBookLayout}.test.ts`、`tests/appSurface/project-development.suite.ts`、`docs/technical/【技术方案】GameAgent资源自由画板与快速编辑-2026-08-20.md`。
|
||||
|
||||
## 稳定版 AGC 复用开发栈必须核对 instance identity
|
||||
|
||||
- 现象:端口和 `/healthz` 都正常,但 AGC 连接了另一个 worktree 的 API、SpacetimeDB 或旧 Vite,表现为登录、项目列表、Runner 状态与当前代码不一致。
|
||||
- 原因:健康检查只能证明“有服务响应”,不能证明服务属于当前工作树;旧 `.app/dev-stack.json` 可能没有当前 `repoRoot`、`instanceId` 和服务级 dataDir 身份。
|
||||
- 处理:先读取 `.app/dev-stack.json`,核对顶层 `repoRoot + instanceId`,再核对服务 `repoRoot + instanceId + dataDir + pid + port`;AGC Vite marker 还必须带 `repoRoot + processId + port`。任何字段缺失或不匹配都拒绝静默复用,改为启动当前工作树自己的服务或明确提示清理。
|
||||
- 验证:`scripts/dev.test.ts`、`apps/ai-game-creator-shell/tests/start-dev-stack.test.ts` 覆盖 snapshot identity 和旧状态拒绝复用;运行时记录实际端口、进程命令行和 dataDir,不要只记录 HTTP 200。
|
||||
|
||||
@@ -51,7 +51,7 @@ SpacetimeDB crate、SDK、CLI / standalone 与生成 bindings 按 `2.8.3` 对齐
|
||||
|
||||
## AGC DirectProject 与 UI workflow
|
||||
|
||||
- 新 Web 游戏为 `game/` 下的 npm + Vite + Phaser 4.2.1 工程,使用包导入且允许其它依赖;npm 预览与导出只读取 dist,运行素材需纳入构建,已有单 HTML/Godot 不自动迁移。
|
||||
- 新 Web 游戏为 `game/` 下的 npm + Vite + Phaser 4.2.1 工程,使用包导入且允许其它依赖;npm 预览与导出只读取 dist,运行素材需纳入构建。单 HTML → Phaser 迁移固定走 DirectProject:文件落盘后先用受控 `project.bootstrap` 在 `game` 执行无参数 `npm install`,再用支持相对 cwd 的 `project.verify` 构建并确认 `game/dist/index.html`,已有单 HTML/Godot 不通过 JSON Generator 伪装成 npm 工程。
|
||||
|
||||
- 通用 Agent Rust 分层为 `agent-runtime-core`(catalog、执行生命周期、ToolHost/spawn/all-join/Provider 契约)、`agent-runtime-orchestration`(动态无环任务图、ready、依赖波次、返工下游闭包和受限自主扩图提案)与 `platform-agent` 游戏适配器;循环返工通过新 pass / epoch 表达,不在单张依赖图中建立回边。LLM 可经宿主结构化 function call 提出新增节点/边,编排层只生成经校验的新候选图,epoch 与持久化仍由宿主掌控。
|
||||
- DirectProject 始终连接客户端内置的 `agc_tools` STDIO MCP,并在启动时额外读取客户端扩展仓库中已启用的第三方 MCP 独立项。第三方 STDIO/HTTP 配置只写入本次隔离 `CODEX_HOME`,单项非 required,启停、重命名和内容指纹进入 app-server pool identity;完整 Plugin Runtime、hooks/apps 和单文件脚本手动指定入口仍关闭。Skill 正文与 references 由 Codex 原生按需读取;`agc_tools` 负责标准美术准备、已登记资源有界查询、视频 / 角色动画 / 音效 / BGM 的 create-or-derive、已登记图片去背景、desktop/mobile 浏览器试玩和受控 `agc_web_search`;付费资源调用仍由客户端绑定回合、幂等账本、请求上限和投影权威。
|
||||
|
||||
@@ -40,9 +40,9 @@ DirectProject 自身的 `read_direct_project_conversation` 也必须在 blocking
|
||||
|
||||
新建 Web 游戏使用 npm 工程:默认 `game/package.json` 声明 Phaser 4.2.1 和 Vite 构建工具,源码使用 `import Phaser from 'phaser'`,`package-lock.json` 由 npm 维护。默认脚手架文件位于 `game/`,包含 `index.html`、`game.js`、`style.css`、`vite.config.js` 和 npm 配置/锁文件;已有根目录 npm 工程沿用原根,可按需求拆分模块并添加任意其它 npm 依赖,不设置包名白名单。客户端不手工分发 Phaser bundle,不用 import map 模拟 package 导入。
|
||||
|
||||
Agent 在包含 `package.json` 的目录执行 `npm ci`(依赖变更使用 `npm install`)和 `npm run build`;默认可从工作区根执行 `npm --prefix game ci` 与 `npm --prefix game run build`。DirectProject 保持 workspace-write 目录边界并开放网络,以支持 npm 依赖解析和安装;凭据仍由客户端代理持有,不进入项目或原生命令环境。其它执行模式维持现有权限。新游戏完成后执行 `npm run build` 并用真实浏览器试玩;依赖安装与构建失败必须反馈真实错误,不能回退成未解析裸模块导入的静态页面。
|
||||
Agent 在包含 `package.json` 的目录执行 `npm ci`(依赖变更使用 `npm install`)和 `npm run build`;默认可从工作区根执行 `npm --prefix game ci` 与 `npm --prefix game run build`。DirectProject 保持 workspace-write 目录边界并开放网络,以支持 npm 依赖解析和安装;凭据仍由客户端代理持有,不进入项目或原生命令环境。依赖初始化必须通过受控 `project.bootstrap`(固定 `cwd=game`、无参数 `npm install`、只读取 package/lock 并记录 SHA-256 指纹),不得放开通用 `command.exec npm install`。构建使用 `project.verify` 的相对 cwd(例如 `cwd=game`);`build` 通过后还必须存在 `game/dist/index.html` 才能签发验证凭证。其它执行模式维持现有权限。新游戏完成后执行 `npm run build` 并用真实浏览器试玩;依赖安装与构建失败必须反馈真实错误,不能回退成未解析裸模块导入的静态页面。
|
||||
|
||||
npm 游戏的可预览产物固定为对应 package 目录下的 `dist/index.html`,静态 smoke 校验构建入口及本地文件引用,实际可玩性由浏览器验证。预览服务与导出读取该构建目录,所有运行素材必须由构建纳入 dist;npm 预览不回退读取源码或项目素材目录,保证试玩与导出一致。源码投影包含 package、锁文件、配置和真实游戏源码,排除 `node_modules/`、`dist/`、控制文件与凭据;npm 试玩包将 dist 文件映射到 `game/` 并附带发布说明,不包含源码依赖安装目录。现有单 HTML 项目不自动迁移,Godot 项目保持原合同。旧 JSON Generator 仅接受已初始化的单 HTML 项目,npm 项目或新建请求在调用 LLM 前明确拒绝并引导使用 DirectProject,避免静态草案伪装为 npm 构建产物。本节覆盖下文仅适用于旧单 HTML 产物的 Canvas API、手写动画循环和禁止外部本地脚本要求。
|
||||
npm 游戏的可预览产物固定为对应 package 目录下的 `dist/index.html`,静态 smoke 校验构建入口及本地文件引用,实际可玩性由浏览器验证。预览服务与导出读取该构建目录,所有运行素材必须由构建纳入 dist;npm 预览不回退读取源码或项目素材目录,保证试玩与导出一致。源码投影包含 package、锁文件、配置和真实游戏源码,排除 `node_modules/`、`dist/`、控制文件与凭据;npm 试玩包将 dist 文件映射到 `game/` 并附带发布说明,不包含源码依赖安装目录。单 HTML → Phaser 迁移必须在 DirectProject 中完成:先识别 `game/index.html`,再将状态、输入、敌人/守卫、波次、胜负、重开和画布绘制迁移到 Phaser Scene 与 update 循环,并落盘 `game/package.json`、`game/game.js`、`game/style.css`、`game/vite.config.js` 和锁文件;不得把迁移目标伪装成 `gameHtml`。现有单 HTML 项目不自动迁移,Godot 项目保持原合同。旧 JSON Generator 仅接受已初始化的单 HTML 项目,npm 项目或新建请求在调用 LLM 前明确拒绝并引导使用 DirectProject,避免静态草案伪装为 npm 构建产物。本节覆盖下文仅适用于旧单 HTML 产物的 Canvas API、手写动画循环和禁止外部本地脚本要求。
|
||||
|
||||
## 2026-09-02 项目名称显示与自动提炼
|
||||
|
||||
@@ -1369,3 +1369,8 @@ DirectProject 使用 `approvalPolicy=never`,避免每次原生调用再经过
|
||||
- **成功后行为**:重读 manifest,**不切换版本**(没有新版本可切),**不自动重载 / 重启运行中的预览**(PRD §3.2 末条),不做运行时资源重映射。可见变化只有资源卡「当前使用」高亮移到替换素材、`@` 面板「当前版本素材」更新。
|
||||
- **已知代价(用户已确认接受)**:**替换历史不可回溯**——替换前身份只剩那条审计与 manifest 的 `.previous` 副本;需要"某版本历史上换过什么"时要另立切片(PRD §3.2 / §5.3 保留为未来合同正是为此)。
|
||||
- **验证**:绑定改写通道定向 7 条(`project/manifest/version_binding_rewrite_tests.rs`)+ 替换定向 8 条 + `shared-contracts` 20 条。**变异验证**:① 去掉「未放行版本整条相等」→ 两周转红;② 放行集合改成整个版本数组 → 「未放行版本」转红;③ 去掉长度检查 → 「不增不删」转红;④ 准入删掉 category → 硬门禁与候选两条转红;另有 ⑤ 改回"原地改既有版本但绕过放行口"→ 被「项目版本记录写入后不可修改、删除或重排」拦下。前端 13 条(模型 9 + 真链路 4)。AGC 全量 1231 passed / 4 skipped / 0 failed;共享美术画布组件 1385 passed;`npm run ai-game-creator-shell:typecheck`(含 check-config)、`cargo check --locked --all-targets`、`npm run check:encoding`、`git diff --check` 全绿。`/api/external/v1`、SpacetimeDB schema、`packages/shared` 与 `shared-contracts` 的 wire DTO、manifest 结构、布局 sidecar schema 均未改动。
|
||||
|
||||
## 2026-09-14 项目客户端占用锁收敛
|
||||
|
||||
项目锁职责收敛为“客户端占用项目”这一事实:同一客户端进程内的嵌套项目写入调用复用已有项目锁并返回 advisory guard,不再等待自身持有的 `.agent/project.lock`;跨进程竞争继续沿用现有占用、残留回收和权限分类。Runner 的 `.agent/runtime/execution-owner.lock` 迁移到统一项目占用锁仍属于进行中的里程碑,完成前不改变其恢复诊断合同。
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ npm run dev
|
||||
- 主站 Vite。
|
||||
- 后台 Vite。
|
||||
|
||||
`npm run dev` 和单模块 `npm run dev:web`、`npm run dev:api-server`、`npm run dev:bgfilter-worker`、`npm run dev:spacetime`、`npm run dev:admin-web` 启动后都会更新根目录 `.app/dev-stack.json`。该文件记录本次命令、数据库、更新时间,以及 `spacetime`、`api-server`、`bgfilter-worker`、`web`、`admin-web` 的 `pid`、监听 host / port、可访问 URL、启动状态和当前命令。`.app/` 是本地运行态目录,不提交 Git;端口漂移、服务重启或子进程退出后以该文件里的实际状态为准。
|
||||
`npm run dev` 和单模块 `npm run dev:web`、`npm run dev:api-server`、`npm run dev:bgfilter-worker`、`npm run dev:spacetime`、`npm run dev:admin-web` 启动后都会更新根目录 `.app/dev-stack.json`。该文件记录本次命令、数据库、更新时间,以及 `spacetime`、`api-server`、`bgfilter-worker`、`web`、`admin-web` 的 `pid`、监听 host / port、可访问 URL、启动状态和当前命令;稳定版状态还记录顶层 `repoRoot + instanceId`,每个服务记录 `repoRoot + instanceId + dataDir`,与端口组成复用身份。`.app/` 是本地运行态目录,不提交 Git;端口漂移、服务重启或子进程退出后以该文件里的实际状态为准。缺少身份字段或身份不匹配的旧状态不得被 AGC 静默复用。
|
||||
|
||||
通过 `nohup` 在仓库根目录启动 dev 栈且未显式重定向 stdout / stderr 时,默认 `nohup.out` 会持续收集 SpacetimeDB、api-server、bgfilter-worker、主站 Vite 和后台 Vite 的整套 dev 栈输出;该文件已被主站 Vite watcher 和 Git 忽略,避免日志追加触发页面刷新循环,重启主站 Vite 后生效。若把输出显式重定向到其它仓库内文件(例如 `> dev.out`),该自定义文件不会自动获得同样的 watcher 保护,应改为写到 Vite root 之外,或同步配置精确的忽略规则。
|
||||
|
||||
@@ -62,7 +62,7 @@ Linux 本机多用户并发开发时,`npm run dev`、`npm run dev:*` 单模块
|
||||
|
||||
后端日志默认写入 `logs/api-server/`,独立 BgFilter worker 日志默认写入 `logs/bgfilter-worker/`。后端 API smoke 使用 `npm run dev:api-server`,先检查 BgFilter worker `/readyz`,再检查 API `/healthz`;需要确认 API 实例可接生产流量时检查 API `/readyz`。不要使用旧 `api-server:maincloud` 或任何 `GENARRATIVE_SPACETIME_MAINCLOUD_*` 口径。
|
||||
|
||||
AI 游戏创作客户端使用 `npm run agc`。该入口由 `apps/ai-game-creator-shell/scripts/start-tauri-dev.mjs` 解析 AGC Vite 实际端口:Linux 默认取当前用户端口段的 `start + 5`,占用时只在本用户段内漂移;Windows / macOS 保留 `3080` 为兼容首选并允许统一漂移。最终端口通过 `GENARRATIVE_AGC_VITE_PORT` 传给 `beforeDevCommand` 和配套后端端口解析器,通过 Tauri CLI 动态 `build.devUrl` 配置传给 WebView,并通过 Vite CLI `--port` 启动严格监听;Vite 继续使用 `strictPort`,任何一层都不得自行改到另一个端口。AGC 配套后端的 `backend` 模式启动 SpacetimeDB、独立 `bgfilter-worker` 和 `api-server`,并在复用现有后端前同时检查三者状态及 `/v1/ping`、`/readyz`、`/healthz`;worker 缺失时不得把不完整的 API/数据库组合误判为 ready。任一配套服务在启动阶段进入 `failed` 时,外层启动器必须立即报告具体服务和退出原因,不能继续等待前端地址超时。端口健康不等于归属正确:复用前还必须证明端口上的监听进程属于当前工作树(Windows 按 `server-rs/target/debug/api-server.exe` 绝对路径与 SpacetimeDB `--data-dir` 校验,探测不可用时退化为旧行为),无法证明归属时一律不复用,改为启动本工作树自己的后端并在需要时端口漂移;否则上个工作树 Ctrl+C 残留的后端会被当成自己的后端复用,改了数据库的工作树会连到旧库。启动器在创建原生窗口前预检最终地址;若竞态中该地址被 AGC Vite、无响应监听器或其它服务占用,一律失败关闭,不复用、也不擅自终止无法证明归属的进程。
|
||||
AI 游戏创作客户端使用 `npm run agc`。该入口由 `apps/ai-game-creator-shell/scripts/start-tauri-dev.mjs` 解析 AGC Vite 实际端口:Linux 默认取当前用户端口段的 `start + 5`,占用时只在本用户段内漂移;Windows / macOS 保留 `3080` 为兼容首选并允许统一漂移。最终端口通过 `GENARRATIVE_AGC_VITE_PORT` 传给 `beforeDevCommand` 和配套后端端口解析器,通过 Tauri CLI 动态 `build.devUrl` 配置传给 WebView,并通过 Vite CLI `--port` 启动严格监听;Vite 继续使用 `strictPort`,任何一层都不得自行改到另一个端口。AGC 配套后端的 `backend` 模式启动 SpacetimeDB、独立 `bgfilter-worker` 和 `api-server`,并在复用现有后端前同时检查三者状态及 `/v1/ping`、`/readyz`、`/healthz`;worker 缺失时不得把不完整的 API/数据库组合误判为 ready。任一配套服务在启动阶段进入 `failed` 时,外层启动器必须立即报告具体服务和退出原因,不能继续等待前端地址超时。端口健康不等于归属正确:复用前还必须证明端口上的监听进程属于当前工作树(Windows 按 `server-rs/target/debug/api-server.exe` 绝对路径与 SpacetimeDB `--data-dir` 校验,探测不可用时退化为旧行为),无法证明归属时一律不复用,改为启动本工作树自己的后端并在需要时端口漂移;否则上个工作树 Ctrl+C 残留的后端会被当成自己的后端复用,改了数据库的工作树会连到旧库。启动器在创建原生窗口前预检最终地址;AGC Vite marker 同时提供 `repoRoot + processId + port`,与 `.app/dev-stack.json` 的 `instanceId` 和 API target 交叉核对;若竞态中该地址被 AGC Vite、无响应监听器或其它服务占用,一律失败关闭,不复用、也不擅自终止无法证明归属的进程。
|
||||
|
||||
Tauri `beforeDevCommand` 默认与客户端构建并行,不能把上述检查只放在 `beforeDevCommand` 内:选定地址上若已有旧 Vite,Tauri 可能先创建加载旧前端的窗口,随后配套后端才因代理不匹配退出。外层启动器会把 Tauri CLI 放入受控进程树;CLI 正常退出、启动失败或收到终止信号后,POSIX 先向保留的 PGID 发送 `SIGTERM`、有界等待后升级 `SIGKILL`,Windows 使用 `taskkill /PID <pid> /T /F`。Windows 下每个长驻服务都经 `cmd.exe /d /s /c` 包装层启动,Ctrl+C 会先杀掉包装层(退出码 `0xC000013A`),因此清理不能只看直接子进程是否存活:`taskkill` 对已退出的 PID 只会失败,必须继续按记录下来的根 PID 遍历,并在退出时按本工作树 `api-server.exe` 绝对路径(以及本次自己拉起的 SpacetimeDB `--data-dir`)做一次身份兜底清扫;`scripts/dev-windows-process.mjs` 是这套判定的唯一实现。Linux 容器中的孤儿后代退出后可能暂时保留为 zombie,`kill(-PGID, 0)` 仍会返回成功;启动器必须结合 `/proc/<pid>/stat` 判断同组是否还存在非 zombie 成员,不能把等待 PID 1 回收误报为清理失败。配套后端和 Vite 仍由 `start-dev-stack.mjs` 各自持有,退出时同样有界收束,避免只剩客户端、Runner、Cargo 或旧订阅进程。排障时同时核对控制台输出的 AGC Vite 实际地址及其 marker、`.app/dev-stack.json` 的实际 API URL 和进程 cwd;不要把“终端已返回”当成客户端及其 Runner 已退出的证据。
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# 【技术方案】AGC 客户端稳定版生命周期大切换
|
||||
|
||||
更新时间:`2026-09-14`
|
||||
|
||||
## 目标
|
||||
|
||||
在 AGC 尚未对外发布的前提下,统一现役客户端入口的异步操作生命周期,并删除会继续制造重复状态机的旧局部防重路径。现有本地项目、`.agent` 文件、Runner 账本和公开后端契约继续作为迁移边界。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不删除或重排本地 manifest、会话、资源生成账本和 Runtime journal。
|
||||
- 不删除 `/api/external/v1`、账号、编辑器素材、生成接口、SpacetimeDB schema 或共享 DTO。
|
||||
- 不把新玩法、插件、支付、编辑器大功能和主站架构调整并入稳定版切换。
|
||||
- 不自动重放无法确认已经受理的 pending 外部操作。
|
||||
|
||||
## 新的内部合同
|
||||
|
||||
### ClientOperation
|
||||
|
||||
所有 renderer 异步入口必须能投影以下字段:`operationId`、`requestId`、`kind`、`phase`、`startedAt`、`deadlineAt`、`scope`、`cancelled`。phase 使用 `idle / network / runner / project / success / retryable-failure / unknown`;迟到结果只能在 operationId、scope 和 session generation 都仍匹配时写回。
|
||||
|
||||
### AuthTransition / RunnerTransition
|
||||
|
||||
启动恢复、手工登录、发送验证码、退出和 401 refresh 共享认证 operation 身份与 session generation。Runner 安装/清除在 blocking worker 执行;前端只展示 network/runner/success/retryable-failure/unknown,并提供重试或重新登录。
|
||||
|
||||
### HomeCreationOperation
|
||||
|
||||
首页创建由 Launcher controller 持有,payload 保留 draft 快照和 startMode,scope 在建项后绑定 projectPath;创建、附件导入、首轮投递分别推进 phase。页面卸载不取消 operation;成功、可重试失败和不确定状态均可被重新投影。
|
||||
|
||||
### RecentProjectInspection
|
||||
|
||||
每个最近项目拥有独立 operation 和结果。检查中、可打开、失败、超时、不存在、非目录、未初始化和可导入不能通过一个全局刷新 gate 互相覆盖。
|
||||
|
||||
### DevStackIdentity
|
||||
|
||||
`.app/dev-stack.json` 和服务 marker 必须包含 `repoRoot + processId + port + dataDir + instanceId` 可验证的身份信息。客户端发现状态时,数据库名、dataDir、repoRoot 或进程归属不匹配就拒绝复用并启动/提示当前工作树自己的服务。
|
||||
|
||||
## 本地数据迁移
|
||||
|
||||
- 旧 manifest、项目资源、Planning/GDD、会话和 Runtime journal 继续按现有读取与恢复规则打开。
|
||||
- 缺少 operationId 的旧 pending 记录只能转换为可重试或 `unknown`,不自动重放外部副作用。
|
||||
- 旧 Runner endpoint 只有在当前 dataDir、repoRoot、进程归属和协议/可用性都匹配时才能复用。
|
||||
- 迁移失败保留原文件并给出可操作错误,不以新状态覆盖旧数据。
|
||||
|
||||
## 任务列表与验收顺序
|
||||
|
||||
1. **操作合同**:建立共享 `ClientOperation` 类型、状态转移和 stale-result 规则;认证 refresh 与首页创建接入。
|
||||
2. **认证/Runner**:统一登录恢复、手工登录、退出、401 refresh 的 operation 投影,保留 session generation 和 blocking worker。
|
||||
3. **入口迁移**:首页创建、手动打开、附件导入、Planning V2、DirectProject、资源生成和预览入口复用 operation scope,不再新增 component-level busy ref。
|
||||
4. **开发栈身份**:dev-stack snapshot、Vite marker、AGC 配套后端复用门禁统一使用 repoRoot/processId/port/dataDir/instanceId。
|
||||
5. **本地恢复**:对旧 pending operation、旧 endpoint 和正在写入的项目执行失败关闭、可重试或人工核对迁移。
|
||||
6. **旧路径清理**:仅删除无现役调用方、无持久化合同、无公开契约的旧分支;每次删除前补调用方和持久化证据。
|
||||
7. **完整验收**:启动、登录、进入首页、打开项目、对话、确认、资源、预览、切项目、恢复对话/运行态、失败重试、退出登录,并验证坏项目、迟到结果、Runner 重复启动和旧 worktree 串用门禁。
|
||||
|
||||
## 当前实现状态
|
||||
|
||||
- HTTP body-aware timeout、refresh singleflight 清理、Runner blocking worker、最近项目逐项检查和首页创建跨页防重已完成并在 PR #346 中提交。
|
||||
- `ClientOperation` 基础合同、认证 refresh 与 Runner auth-transition operation 投影、首页创建 operation 投影和 dev-stack `instanceId` 已在本轮切换中落地。
|
||||
- 稳定版基础切换里程碑已完成;后续入口只允许复用该合同,不再新增 component-level busy/ref 状态机。
|
||||
- Planning/DirectProject/资源生成/预览已有各自 durable operation 或 request scope;本轮只补统一投影与身份校验,不重写其持久化账本。
|
||||
|
||||
## 现役边界审计
|
||||
|
||||
以下能力在本次切换前已经具备 durable 恢复或失败关闭合同,因此本轮按现有实现接入统一投影,不重复重写:
|
||||
|
||||
| 边界 | 当前证据 | 切换结论 |
|
||||
| --- | --- | --- |
|
||||
| 本地 manifest、Godot/Cocos 导入和项目 revision | `src-tauri/src/project/manifest/`、`import_tests.rs`、`recovery_tests.rs` | 保留旧文件格式,失败关闭,不复制平行项目根 |
|
||||
| 资源生成与 pending operation | `src-tauri/src/project/resource_editor.rs`、`generation/*` 测试 | 已有 operation/幂等/needs-reconciliation,禁止未知结果自动重放 |
|
||||
| Agent Runtime、Planning V2、DirectProject | `runtime_driver/recovery_scan.rs`、`runtime_protocol/`、`direct_runtime.rs` | 继续使用 durable task/session/run,统一 renderer operation 投影 |
|
||||
| 公开后端与共享契约 | `server-rs`、`packages/shared`、`docs/openapi` | 不删除、不改公开契约 |
|
||||
| 已退役客户端入口 | 当前 `WorkspaceLauncher`、`App.tsx` 和路由调用方审计 | 无现役调用方的旧分支才允许后续删除,暂不以猜测删除 |
|
||||
|
||||
完整真实 Provider、原生安装包和跨重启端到端时序仍需在具备登录/Provider 的环境中执行;本次代码门禁已覆盖 deterministic surface、operation、认证和 dev-stack identity。
|
||||
|
||||
## 验收证据
|
||||
|
||||
| 条款 | 证据 |
|
||||
| --- | --- |
|
||||
| operation identity 与 stale-result | `clientOperation.test.ts`、认证/home 定向测试 |
|
||||
| HTTP/auth/Runner | client HTTP/API 测试、Rust cargo check、认证 appSurface |
|
||||
| 最近项目逐行刷新 | `recentProjectsModel.test.ts`、home appSurface |
|
||||
| dev-stack 身份 | `scripts/dev.test.ts`、`start-dev-stack.test.ts`、端口 marker 检查 |
|
||||
| 本地恢复边界 | 现有 manifest/runtime/resource recovery tests;未确认外部副作用不自动重放 |
|
||||
| 完整流程 | AGC appSurface、开发栈 smoke;真实 Provider/安装包另行记录 |
|
||||
Reference in New Issue
Block a user