合并最新主分支并保留策划退役清理
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
合入 origin/master 的现役 Direct、Mac 随包资源、配置和测试变更 保留策划 Agent V1/V2 退役删除结果 仅在重叠文件保留当前分支的策划解耦代码 不额外处理 master 自身已有缺陷
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
# AGC 对话历史分页恢复实施计划
|
||||
|
||||
- Date: 2026-09-16
|
||||
- Status: awaiting-runtime-acceptance
|
||||
- Milestone: [AGC 对话历史分页恢复](./【里程碑】AGC对话历史分页恢复-2026-09-16.md)
|
||||
|
||||
## 实施
|
||||
|
||||
1. 原生历史读取复用逐行解析,增加消息模式,过滤后分页并返回已有原始消息 ID 游标;保持原始接口默认行为和路径权限。
|
||||
2. 工作台首屏与更早消息读取显式请求消息模式,消费游标;加载代次隔离、单飞与 ID 去重。
|
||||
3. 合成记录测试复现原始工具页卡住的形状,覆盖旧无 ID、坏行、时间、失败/重复/切项目;临时目录只读重放用户日志。
|
||||
4. 前端/原生定向测试、类型、Lint、编码、文档和差异检查通过后,更新问题表及 PR 草稿并本地提交。
|
||||
5. 在临时消息投影中标记历史来源,保留 Runtime 所有权语义;刷新合并时只保留非历史来源的待回读消息。补齐「先加载旧页,再 /history,再翻页」的顺序与去重回归,保持尚未落盘用户输入的保留逻辑。
|
||||
|
||||
## 边界与停止条件
|
||||
|
||||
不调整 Direct 消息呈现归属、不修未证明的写入丢失、不上传日志、不触碰用户项目。必要 API 变化仅为本地 IPC 可选参数和游标字段;无 OpenAPI、SpacetimeDB 或持久化迁移。远程推送/PR/WIP 操作仍待额外确认。
|
||||
|
||||
## 验收证据
|
||||
|
||||
- 历史消息模型、回合呈现及分页集成共 24 个前端测试通过;包含真实 App 的首屏/更早页、单飞、失败重试、重叠消息、同项目重新加载及离开再进入的迟到响应。
|
||||
- 16 个历史原生测试通过;人工日志重放用例在 CI 默认忽略,已在本地单独执行通过。
|
||||
- 使用用户提供的原始日志运行修复后的原生读取:44 条现存聊天消息(含 2 条用户消息)分 3 页取回,逐项内容与顺序一致,原文件字节未变;未在仓库保存原始日志。
|
||||
- 工作台/Direct 恢复与画布导航的 8 个定向回归通过。真实客户端重新进入与向上翻页尚待用户验收;本次涉及 Rust IPC,需重新构建并启动原生端。
|
||||
- 与前面画布/JSON 修复联合复验:119 个前端定向测试、30 个原生测试通过;AGC TypeScript、修改文件 ESLint、编码、文档索引和差异检查通过。
|
||||
- 状态只覆盖日志中已经证明的分页卡页,不据此宣称其它可能的未落盘消息也已恢复。
|
||||
@@ -32,7 +32,7 @@
|
||||
| B02 | 初次进入双指平移无效,整理后恢复 | 已优化;用户在本轮反馈未再复现,按用户要求更新状态。隔离组件连续平移通过。 |
|
||||
| B03 | 快速平移触发更新深度错误 | 已修复已确认的窗口 Context 反馈循环,回归验证收敛;真实操作继续观察。 |
|
||||
| B04 | 资源选中后运行不可用提示消失 | 已修复,提示与选择解耦,自动化验证通过。 |
|
||||
| B05 | 对话记录偶发丢失 | 已修复日志复现的历史分页卡点:消息模式过滤后分页、原生游标与读取代次隔离。原生只读重放分 3 页取回全部 44 条现存消息,原文件未变;真实客户端待验收,不扩大为其它未落盘记录已恢复。 |
|
||||
| B05 | 对话记录偶发丢失 | 已定位历史分页卡点,尚未修改。只读复验用户提供的历史:558 条合法原始记录中有 44 条聊天消息;首屏原始 20 条只投影出一条助手消息,下一页原始 20 条没有聊天消息,按消息计算的游标不推进。已存用户提问和最终回答因此无法继续翻出;不能凭该文件排除其它未落盘记录。 |
|
||||
| B06 | JSON 文档未正确识别展示 | 已按用户确认完成本地修复:合法 UI State 由原生完整校验,卡片显示 UI 设计并进入现有编辑器;普通 JSON 显示 JSON 并可代码预览。自动化验证通过,待重建原生客户端验收;详见 JSON 语义识别实施计划。 |
|
||||
| C01 | 右键平移,保留左键框选 | 已实现,卡片左键拖动、框选、指针取消/失焦/捕获丢失及控件边界测试通过。 |
|
||||
|
||||
@@ -41,4 +41,4 @@
|
||||
- 修复前新增回归测试能检出外壳重复发布、运行提示消失和右键无效;修复后窗口/画布定向测试通过,现有导航、框选、指针点击/取消、UI 编辑器返回平移和素材定位用例通过。
|
||||
- AGC TypeScript、修改文件 ESLint、编码、文档索引及差异空白检查通过。
|
||||
- 测试仍有既有 React 列表 key、旧用例 act/IPC 桩告警,未作为本批功能修复扩大范围。
|
||||
- 用户反馈 B01/B02 本轮未再复现,记为已优化;右键手感与其它真实客户端细节继续观察。对话历史分页与 JSON 双路径均已本地修复并通过定向验证,待重建原生端后真实客户端验收。本计划保持开放。
|
||||
- 用户反馈 B01/B02 本轮未再复现,记为已优化;右键手感与其它真实客户端细节继续观察。对话历史分页尚未修复;JSON 双路径已本地修复并通过自动化验证,待真实客户端验收。本计划保持开放。
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# AGC 项目创建目录可选实施计划
|
||||
|
||||
Version: 1.0
|
||||
Status: active
|
||||
Date: 2026-09-17
|
||||
Related Spec: `docs/technical/【技术方案】AGC模板库与模板建项-2026-09-17.md`、`docs/【技术方案】AGC异步操作可恢复闭环-2026-09-14.md`
|
||||
|
||||
## 目标
|
||||
|
||||
让用户在 AGC 里能自己选项目创建目录:首页「做游戏 / 做方案」自动建项与模板库「使用模板」建项都落在用户选定的目录下;不选时保持 AGC 管理的默认位置(`<app_data>/projects`),行为与现状一致。
|
||||
|
||||
## 交接结果
|
||||
|
||||
- `create_automatic_local_game_project`、`create_automatic_local_game_project_from_template` 新增可选参数 `projectsRoot`;为空时由 Rust 侧回落到默认目录。
|
||||
- `pick_local_project_directory` 新增可选参数 `title`(只接受短标题,其余回退「选择游戏项目目录」)。
|
||||
- 新增用户偏好「项目创建目录」:`localStorage` 键 `genarrative-ai-game-creator.project-creation-directory.v1`。
|
||||
- 入口在客户端设置里:侧边栏「配置」→ 设置分类「工作区」;`RuntimeConfigDialog` 内用 `useProjectCreationDirectory` 展示与改选目录,不经过首页或模板库页头。
|
||||
- 首页「做游戏 / 做方案」与模板库「使用模板」建项时读取同一份偏好,用户不需要在建项前再选一次。
|
||||
|
||||
## 行为契约
|
||||
|
||||
- 允许的来源只有一个:本机原生目录选择器(`pick_local_project_directory`)。它返回的目录已在选择时按 user-selected 范围做过一次加固,构成「用户显式选择」边界。
|
||||
- Rust 侧 `validate_requested_game_project_creation_root` 对传入目录要求:非空、绝对路径、无控制字符、已存在的普通目录(符号链接 / Windows reparse point / 普通文件一律拒绝),并通过 `prepare_game_creator_project_root_for_read`(user-selected 范围的一次性修复)。目录不存在时不代为创建,直接失败。
|
||||
- 建出的项目目录仍在所选目录下按 `gameagent-<8位短ID>` 命名,项目名、`.agent` 初始化、首轮投递与既有自动建项完全一致。
|
||||
- 偏好只保存「用户意图」,不是授权凭据:存储被外部改动最坏只是回退默认位置或一次可见的建项失败,不会跳过 Rust 门禁。
|
||||
- 该偏好是客户端本地设置,不写入 `read_game_creator_app_config` / 保存设置的那份运行时配置:在「工作区」里选择目录当场生效,与「保存设置」按钮无关。
|
||||
- 「恢复默认位置」清空偏好即回到应用数据目录;既有项目不迁移。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. **Rust 建项入口**
|
||||
- `commands.rs`:新增 `validate_requested_game_project_creation_root` / `resolve_game_project_creation_root`,`create_automatic_local_game_project` 接受 `projects_root`;`pick_local_project_directory` 接受 `title`。
|
||||
- `template_library.rs`:模板建项复用同一解析函数。
|
||||
- 交付:两条定向单测(校验矩阵、在指定创建目录下建项)。
|
||||
- 验收:`cargo test --bin genarrative-ai-game-creator-shell creation_root` 全绿。
|
||||
|
||||
2. **前端偏好与入口**
|
||||
- `features/app-shell/model.ts`:`normalizeProjectCreationDirectory` / `readProjectCreationDirectory` / `writeProjectCreationDirectory` / `projectCreationDirectoryLabel`。
|
||||
- `useProjectCreationDirectory`:选择目录、恢复默认、状态文案(失败在设置页字段内可见)。
|
||||
- `RuntimeConfigDialog` 新增「工作区」设置分类,承载「项目创建目录」字段与「选择目录 / 恢复默认位置」动作。
|
||||
- `useHomeProjectCreation` 与 `useTemplateLibrary` 在建项时带上 `projectsRoot`。
|
||||
- 交付:偏好模型 4 项单测、设置页 1 项交互测试、appSurface 1 项「设置里选目录后建项」端到端场景。
|
||||
- 验收:`npx vitest run apps/ai-game-creator-shell/tests/projectCreationDirectory.test.ts apps/ai-game-creator-shell/tests/appSurface.test.ts` 全绿。
|
||||
|
||||
3. **文档与共享记忆**
|
||||
- 本实施计划;模板库技术方案的命令表补 `projectsRoot`;`decision-log.md` 记录偏好键与命令参数;`pitfalls.md` 说明用户自选目录与 AGC 管理目录的关系。
|
||||
- 验收:`node scripts/check-doc-index.mjs` 通过。
|
||||
|
||||
## 验证命令
|
||||
|
||||
```bash
|
||||
cargo check --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --bin genarrative-ai-game-creator-shell
|
||||
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --bin genarrative-ai-game-creator-shell creation_root
|
||||
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --bin genarrative-ai-game-creator-shell template_library
|
||||
cd apps/ai-game-creator-shell && npx tsc -p tsconfig.json --noEmit
|
||||
npx vitest run apps/ai-game-creator-shell/tests
|
||||
npm run check:encoding
|
||||
node scripts/check-doc-index.mjs
|
||||
git diff --check
|
||||
```
|
||||
|
||||
手动验收(客户端内):侧边栏「配置」→「工作区」→「选择目录」选 `F:\Projects\我的游戏`,回首页建项后项目目录应为 `F:\Projects\我的游戏\gameagent-<8位>`;模板库「使用模板」建项同样落在该目录;点「恢复默认位置」后再建项回到应用数据目录。
|
||||
|
||||
## 风险与回退
|
||||
|
||||
- **自选目录无法加固**:`Documents` 等带受保护继承 ACL 的位置可能加固失败。失败发生在选择器或建项前置校验阶段,报错可见且不会留下半成品项目;用户改选其它目录或用默认位置即可。
|
||||
- **偏好漂移**:偏好只是提示值,每次建项都会重新校验;存储被改坏不会绕过门禁。
|
||||
- **回退**:删掉偏好键(或点「恢复默认位置」)即回到默认目录;需要彻底移除该能力时,去掉两个命令的可选参数与设置页字段即可,Rust 默认路径逻辑不变。
|
||||
@@ -0,0 +1,43 @@
|
||||
# 【实施计划】DirectProject 聊天真相源收敛
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Milestone | `docs/project-memory/plans/【里程碑】DirectProject聊天真相源收敛-2026-09-16.md` |
|
||||
| Status | implemented |
|
||||
| Owner | Codex |
|
||||
|
||||
## 修改边界
|
||||
|
||||
- 允许修改:`agent/direct_thread_wire.rs`、`agent/direct_thread_manager.rs`、`agent/codex_app_server/`、`agent/direct_project_history.rs`、`main.rs` 命令注册、`src/features/project-workspace/generated/`(ts-rs 生成目录)、AGC 前端订阅与聊天投影、对应测试与 `docs/`。
|
||||
- 明确不修改:SpacetimeDB schema 与绑定、HTTP/OpenAPI、DirectRuntime 自己的进度事件与 `turn-stream.jsonl` / `tool-calls.jsonl` 写入、Codex durable thread 行为、审批弹层现有状态来源。
|
||||
- 保持 `.env` 未提交修改,不触碰个人配置。
|
||||
|
||||
## 实现顺序
|
||||
|
||||
1. Rust 只搬运:`agent/direct_thread_wire.rs` 把 Codex 原始条目挑字段、脱敏、截断后下发,事件载荷与历史切片同形,不生成卡片形状;线上模型是 ts-rs 导出的 tagged enum(`DirectThreadItem` / `DirectThreadEvent` / bootstrap / consume / history slice),`at` 标 `#[ts(as = "f64")]`,改完模型跑 `cargo test export_bindings` 生成前端绑定。
|
||||
2. 条目身份归一:进队列前收敛成一个 `itemId`,事件 envelope 与前端形状里都不出现第二个 id 概念;历史切片的 `firstItemId` 继续取文件里的原始 item id。
|
||||
3. 删掉回合身份:`turn.started` 无载荷、`turn.completed{status}`,条目 / 增量 / 请求 / 生命周期锚点都不带 turn id;队列 `append` 直接收 `DirectThreadEvent`,`seq` 内部自算。
|
||||
4. 思考正文流式:`item/reasoning/summaryTextDelta` 与 `item/reasoning/textDelta` 产出 `item.delta{kind:"reasoning"}`;plan 文本与命令输出保持活动状态。
|
||||
5. 前端收敛为单一 reducer:`subscribe` 返回的 bootstrap 事件就是已暂存的运行态,游标已经在队尾,前端直接 reduce 这批事件即可(不需要为了拿这批事件再补一次 `consume`);此后只由 notify 唤醒 `consume`。唯一例外是回执竞态:Rust 注册完 subscriber 就开始通知,而前端要等回执才知道 `subscriptionId`,这段时间到达的通知只能记欠账,回执到达后立刻补一次 `consume`(否则整轮最后一个事件之后可能再无通知,事件会卡死在队列里)。合并规则只保留"先到定形、后到补空白"(正文只增不减、工具状态允许从 running 升级到终态),`item.delta` 直接追加到运行态条目正文,删掉 `deltaText` 缓冲,`turn.completed` 把运行态条目并入历史再清空。
|
||||
6. 首屏与分页:以 `lastCompletedItemId` 为锚点取最近切片,历史读取改为从文件尾反向扫描;切片的新端边界由这个锚点给出(含该条,命令参数 `throughItemId`),首屏读取等订阅回执里的锚点,回执到达前不发请求、也不退化成「取文件尾」;之后锚点按原始 item id 推进(`beforeItemId`,不含锚点)。一次翻页操作在前端连拉,直到合并后聊天投影出现新回合(新的用户气泡)或 `hasMore=false`,每个操作上限 5 页;锚点未推进(`items` 为空 / `firstItemId` 为 null / 与请求锚点相同)时立即停止。可见性口径只在 `features/project-workspace/directHistoryPaging.ts` 实现一份,首屏与「显示更早」共用。
|
||||
7. App.tsx 接线:订阅 + 立即 reduce bootstrap + notify 唤醒 consume,聊天视图改由 reducer 状态投影(含工具卡片),删除 Direct 回合事件订阅与 `directTurnStream` / `directToolCalls` 状态。
|
||||
8. 删除只服务旧读路径的命令与前端调用(`read_direct_project_history`、`read_direct_turn_stream`、`read_direct_tool_calls`),DirectRuntime 自己的写入保留。`list_game_creator_direct_active_turns` 是唯一的例外并有意保留:它服务首页跨页面的「运行中的项目」列表(`WorkspaceLauncher` / `directActiveTurns.ts`),不是聊天框读路径。
|
||||
9. 测试与文档收口:补 reducer 单测、解锁跳过的工具卡片用例、更新主规范并把冲突的实施计划与工具卡片文档改写为当前状态。
|
||||
|
||||
## 验证命令
|
||||
|
||||
1. `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml direct_thread -- --nocapture`
|
||||
2. `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml export_bindings`(生成 `src/features/project-workspace/generated/`),随后用 `prettier --write` 格式化生成目录,避免未格式化的 ts-rs 输出混进提交
|
||||
3. `npx vitest run apps/ai-game-creator-shell/tests/directThreadChat.test.ts apps/ai-game-creator-shell/tests/directTurnPresentation.test.ts apps/ai-game-creator-shell/tests/directHistoryPaging.test.ts`
|
||||
4. `npx vitest run apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts`
|
||||
5. TypeScript 类型检查与 ESLint(范围同前次 DirectProject 迁移)。
|
||||
6. `npm run check:encoding`、`npm run check:doc-index`、`git diff --check`
|
||||
|
||||
## 风险与回滚点
|
||||
|
||||
- 条目 id 空间不一致会让活跃条目永远收不到完成事件:第 2 步的归一必须在 Rust 出口完成;前端不得再拿到两个 id。
|
||||
- 事件 payload 变大(命令输出、文件变更明细):继续沿用既有截断上限,并观察 Thread Manager 单 thread 字节上限是否被提前触发。
|
||||
- 订阅过期:以重新 `subscribe` + 原子替换处理,需要单测覆盖;不引入定时轮询。
|
||||
- 回执竞态:`subscribe` 回执到达前产生的 `notify` 拿不到订阅身份,必须记欠账并在回执到达后补一次 `consume`;已有专门用例 `drains a notify that lands before the subscribe receipt` 钉住,改坏会让整轮事件卡死。
|
||||
- 合并规则退化为"先到定形"后,若某类条目只有输出没有调用条目,该输出不显示;这是有意取舍,先观察再决定是否补规则。
|
||||
- 回滚点:每一步都保持"新源可用即不依赖旧源"的中间态可回退;不允许出现新源未启用而旧源已删除的提交。
|
||||
@@ -0,0 +1,27 @@
|
||||
# Mac 客户端随包运行依赖补齐实施计划
|
||||
|
||||
- Version: 2
|
||||
- Status: awaiting-windows-acceptance
|
||||
- Date: 2026-09-18
|
||||
- Parent Spec: `【里程碑】Mac客户端随包运行依赖补齐-2026-09-18.md`
|
||||
|
||||
## 修改顺序
|
||||
|
||||
本轮评审修复顺序:统一 release context(覆盖 build/upload 两入口)→ 版本/端点/产物/清单的定向回归 → 宿主列表/启动/面板与前端自动启动能力门禁 → 同步单架构权威文档 → Node/Vitest/Rust/typecheck/编码/文档/diff 检查。用户随后授权同步 master、重打 0.1.67 并推送当前 PR 分支;不读取私钥、不上传安装包、不合并 PR。
|
||||
|
||||
1. 提取构建与运行共用的 Codex 平台布局;按 Cargo TARGET stage 锁定原生依赖并校验包元数据,保留可执行位。
|
||||
2. 增加 macOS 专属 Tauri 资源映射、声明、产物忽略规则;复用插件 staging,不复制 Windows 原生 payload。
|
||||
3. 修正 `.app/Contents/Resources` 定位与平台清单验证,保持外部安装回退。
|
||||
4. 补目标布局、资源映射、缺失/篡改/平台身份、候选顺序与路径测试,运行定向门禁。
|
||||
5. 构建 `.app`,在隔离目录做资源清点、原生二进制启动和 app-server 握手;生成 DMG 并校验。记录 GUI/真实 Provider 和 Cocos 未验收项。
|
||||
|
||||
## 命令与边界
|
||||
|
||||
- `cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml agent::codex_cli::tests:: -- --test-threads=1`
|
||||
- `npm run ai-game-creator-shell:typecheck`
|
||||
- 定向 Node 打包契约测试、`npm run check:encoding`、`npm run check:doc-index`、`git diff --check`
|
||||
- 本地 Tauri 构建关闭 updater artifact;版本按用户要求统一为 0.1.67,不读取发布私钥,不运行 release upload。
|
||||
|
||||
## 风险与停止条件
|
||||
|
||||
磁盘不足、目标包不匹配或配置测试回归时停止打包,先修正原因,不跳过验证。用户已确认 Mac 本地可用并授权提交、推送当前分支和创建草稿 PR;产物放 gitignored target,不上传发布。回滚以本次路径 diff 为边界,不恢复无关文件。保留计划等待 Windows 回归验收,证据见对应里程碑规范。
|
||||
@@ -1,20 +0,0 @@
|
||||
# AGC 对话历史分页恢复
|
||||
|
||||
- Version: 1
|
||||
- Status: reviewed
|
||||
- Date: 2026-09-16
|
||||
- Parent Spec: [AGC 实施计划:DirectProject 回合展示唯一归属](../../technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md)
|
||||
|
||||
## 范围与评审
|
||||
|
||||
用户已要求修复 B05。已用用户提供的原始日志只读复验:原始切片被工具/推理填满时,聊天投影为空,消息游标不推进。修复聊天读取与分页,不改历史写入、不删除记录、不修改模型上下文,不扩大到其它尚无证据的对话丢失原因。
|
||||
|
||||
采用已有切片接口的显式消息模式与原生游标。原始模式缺省行为保持不变,旧无 ID 消息保留;前端以项目和加载代次隔离结果。本轮不包含远程写入。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 工具/推理密集、末尾无消息、纯工具历史均不产生空页死循环。
|
||||
2. 消息正文、原始 ID、时间和顺序保持不变,翻页能到达早期用户提问及最终回答,不重复。
|
||||
3. 连点、请求失败重试、项目切换和同项目重新加载不会污染消息或游标。
|
||||
4. 原始切片默认模式回归通过,用户日志只读重放可以取回全部现存消息;不把真实日志或对话正文提交到仓库。
|
||||
5. 加载更早消息后重新读取历史,旧页不出现在最新回复之后;再次翻页保持顺序且不重复。未落盘的实时用户输入不因历史刷新被丢弃。
|
||||
@@ -0,0 +1,75 @@
|
||||
# 【里程碑】DirectProject 聊天真相源收敛
|
||||
|
||||
| 字段 | 值 |
|
||||
| --- | --- |
|
||||
| Version | 1.0 |
|
||||
| Status | implemented(自动化验收通过,运行时验收待补) |
|
||||
| Date | 2026-09-16 |
|
||||
| Parent Spec | `docs/technical/【技术方案】DirectProject Codex原始历史与异常恢复-2026-09-04.md` |
|
||||
|
||||
## 目标
|
||||
|
||||
AGC 项目开发对话的显示与恢复只依赖两项输入:**项目对话历史**(`.agent/conversations/project.jsonl`)与 **运行态事件**(Thread Manager `subscribe` / `consume` / `notify`)。Direct 回合事件、`turn-stream.jsonl`、`tool-calls.jsonl` 与活动回合快照都不再是聊天视图的输入。
|
||||
|
||||
边界固定为:Thread Manager 只是**搬运层**——把 Codex 原始条目挑字段、脱敏、截断后下发;工具卡片的形状、可见性与合并全部由前端投影完成。线上模型是 ts-rs 导出的 tagged enum(`agent/direct_thread_wire.rs`),条目身份只有一个:Rust 在进队列前归一成一个 `itemId`,不再暴露第二个 id 概念,也不带任何回合身份。
|
||||
|
||||
## 范围
|
||||
|
||||
- 运行态事件自足化:`item.started` / `item.completed` 携带与历史切片同形的脱敏**原始条目**,前端用同一个投影函数处理实时与回读。
|
||||
- 线上模型与提示词同源:条目与事件是 ts-rs 导出的 tagged enum,前端消费生成绑定(改 Rust 模型后跑 `cargo test export_bindings`);毫秒时间戳用 `#[ts(as = "f64")]` 对齐 Tauri JSON 通道的 `number`。
|
||||
- 条目身份归一:进队列前收敛成一个 `itemId`(工具条目在 `project.jsonl` 里带调用 id 与 response item id 两个值);历史切片另给 `firstItemId` 作为分页锚点,锚点始终是文件里的原始 item id。
|
||||
- 思考正文流式:`item/reasoning/summaryTextDelta` 与 `item/reasoning/textDelta` 以 `item.delta{kind:"reasoning"}` 下发正文;plan 文本与命令输出仍只降级为活动状态。
|
||||
- 历史读取以 `subscribe` 返回的 `lastCompletedItemId` 为首屏锚点,切片从**文件尾反向扫描**;首屏切片的新端边界就是这个锚点(含该条,命令参数 `throughItemId`),比锚点更新的条目只从运行态事件来;向后翻页用切片返回的 `firstItemId`(`beforeItemId`,不含锚点)。后端切片只按原始条目切片,可见性判断留在前端聊天投影;一次翻页操作在前端连拉取页,直到合并后聊天投影出现新回合或 `hasMore=false`,每个操作上限 5 页。
|
||||
- 前端收敛为单一事件 reducer 与单一聊天投影;活动回合只由 `turn.started` 与 `turn.completed` 判定(事件不带 turn id,前端只有一个 `turnRunning` 布尔);`item.delta` 直接追加到运行态条目正文,不保留增量缓冲;`turn.completed` 把该回合运行态条目并入历史再清空。
|
||||
- 删除前端对 Direct 回合事件、`turn-stream.jsonl`、`tool-calls.jsonl`、活动回合快照的读取,以及只服务这些读取的命令与状态。
|
||||
|
||||
## 不在范围内
|
||||
|
||||
- 审批、提问与用户输入请求的状态机迁移;本次事件只作同一条流的 pass-through。
|
||||
- 跨进程回合账本、按回合统计与持久 turn ledger。
|
||||
- DirectRuntime 自己的进度事件与该运行时仍在使用的 `turn-stream.jsonl` / `tool-calls.jsonl` 写入:它们属于运行时的账本,本轮只切 DirectProject 聊天框的读路径。
|
||||
- 旧项目磁盘上既有投影文件的清理、迁移或回填。
|
||||
- 非 DirectProject 运行时、Codex durable thread 语义、SpacetimeDB 与 HTTP 契约。
|
||||
|
||||
## 已确认的决策
|
||||
|
||||
- 投影在前端:Rust 不生成 `kind` / 标题 / 折叠摘要,也不做合并。
|
||||
- 合并只保留"先到定形、后到补空白":第一次见到的快照决定卡片形状,后续快照只补输出与状态;不做逐字段优先级表。
|
||||
- 条目 id 只有一套:归一到 `itemId`;前端与 Thread Manager 都不再出现第二个 id。
|
||||
- 事件不带回合身份:`turn.started` 无载荷、`turn.completed{status}`;Thread Manager 的生命周期锚点、条目、增量与请求都不带 turn id。
|
||||
- 思考正文流式下发不放宽可见范围:被下发的就是此前已在 `item.completed` 展示、并已落进 `project.jsonl` 的同一段文本。
|
||||
- 失败与中止说明只在运行期显示(不写 `project.jsonl`),页面重进后不再出现。
|
||||
- 未知 item 类型由 Rust 原样透传(只有类型与身份,Rust 侧留 TODO),当前由前端投影丢弃。
|
||||
- 前端聊天卡片的工具形状是 `Omit<GameCreatorDirectToolCall, 'turnId'>`;`tool-calls.jsonl` 的持久化形状与 DirectRuntime 的写入保持不变。
|
||||
- 「可显示」的判据取**前端回合反馈**:一次翻页操作连拉到「合并后聊天投影的回合数增加」为止。工具卡片与思考文本虽然能通过 `projectDirectThreadItem`,但可能整页落进已渲染回合的折叠「执行过程」,不构成用户可见反馈;口径只在 `directHistoryPaging.ts` 里实现一份,首屏与「显示更早」共用。
|
||||
- 首屏切片的**新端边界**只认 `subscribe` 回执里的 `lastCompletedItemId`(含该条):回执到达之前不读首屏,也不退化成「取文件尾」;锚点缺失(订阅不可用 / 失败 / 历史为空)时才按文件尾取尾屏,`/history` 手动重读保持按当前文件尾取尾屏的恢复语义。
|
||||
|
||||
## 依赖与前置条件
|
||||
|
||||
- Thread Manager 深模块、app-server 事件适配与 Tauri 桥接已存在。
|
||||
- 主规范中的生命周期锚点、事件自足与首屏锚点条款已生效。
|
||||
- id 空间已用源码核对:codex-rs `app-server-protocol/src/protocol/thread_history.rs` 中所有工具 item 都是 `id: payload.call_id.clone()`,而 `project.jsonl` 落盘的是原始 response item(`id` 与 `call_id` 不同)。真实 app-server 会话核对仍作为运行时验收项。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 一次回合内,实时渲染的文本段与工具卡片顺序,与回合结束后重进项目看到的顺序一致。【自动化:`project-development.suite.ts` 空对话首轮 + 历史切片工具卡片用例】
|
||||
- [ ] 回合进行中终止并重启进程后重进项目:已落盘的部分文本与工具卡片按原顺序出现,且界面不显示忙碌态。【待真实 app-server 运行时验收】
|
||||
- [ ] 进程存活期间的页面重进(含切走再切回)能恢复运行中回合,并允许终止。【待真实 app-server 运行时验收】
|
||||
- [x] 历史切片从文件尾反向回扫,锚点始终是文件里的原始 item id;切片内全部是不可显示条目时仍能继续向前,不出现锚点停滞。【自动化:`direct_project_history` 尾部回扫与分页锚点用例】
|
||||
- [x] 首屏切片的新端边界是 `subscribe` 回执里的 `lastCompletedItemId`(含该条):比它更新的条目只从运行态事件来;锚点缺失时按文件尾取尾屏,订阅回执到达前不发首屏请求。【自动化:`cargo test agent::direct_project_history` 22 条(含 `through_item_id` 锚点用例)+ `directHistoryAnchorGate.test.ts` 10 条 + `project-development.suite.ts` 的 `anchors the first history page at the subscribe receipt instead of the file tail`(变异验证见下)】
|
||||
- [x] 前端一次翻页操作自动连拉,直到合并后聊天投影出现新回合或 `hasMore=false`,每个操作上限 5 页;锚点不前进时立即停止,不空转。【自动化:`directHistoryPaging.test.ts` 8 条 + `project-development.suite.ts` 跨页同回合用例(变异验证见下)】
|
||||
- [x] 聊天视图不再读取 `turn-stream.jsonl` / `tool-calls.jsonl` / Direct 回合事件 / 活动回合快照;`read_direct_turn_stream` 与 `read_direct_tool_calls` 命令已删除。`list_game_creator_direct_active_turns` **有意保留**:它服务首页跨页面的「运行中的项目」列表(`WorkspaceLauncher` / `directActiveTurns.ts`),不属于聊天框读路径。
|
||||
- [x] 同一工具调用在实时与回读各只出现一张卡片(两个 id 空间按归一后的 `itemId` 对齐)。【自动化:reducer「先到定形、后到补空」合并单测 + 工具卡片渲染用例】
|
||||
- [x] 前端聊天状态里不再出现第二个 id 概念与任何回合身份字段;事件解析统一来自 ts-rs 生成绑定。【自动化:`directThreadChat` / `directTurnPresentation` 单测 + `cargo test export_bindings` 生成绑定无差异】
|
||||
- [x] 思考正文在回合进行中即可见,且不进入活动状态文本。【自动化:`directThreadChat` 的 `item.delta{kind:"reasoning"}` 单测】
|
||||
- [x] 订阅过期后重新 `subscribe` 并原子替换状态,不重复渲染已完成的条目。【自动化:reducer 过期重订阅单测】
|
||||
- [x] 通知先于 `subscribe` 回执到达时不丢事件:前端记欠账,回执到达后立刻补一次 `consume`。【自动化:`drains a notify that lands before the subscribe receipt` 用例】
|
||||
|
||||
## 证据要求
|
||||
|
||||
- 自动化(已跑):`cargo test direct_thread`(25 条)、`cargo test direct_project_history`(20 条)、`cargo test export_bindings`(生成绑定与工作区无差异)、`NODE_OPTIONS=--localstorage-file=… npx vitest run apps/ai-game-creator-shell/tests`(125 files / 1676 passed / 17 skipped)、`npx tsc -p apps/ai-game-creator-shell/tsconfig.json --noEmit`(exit 0)、ESLint 与 `prettier`。
|
||||
- 自动化(分页连拉,已跑):`npx vitest run apps/ai-game-creator-shell/tests/directHistoryPaging.test.ts`(8 passed)、`npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts`(470 tests / 453 passed / 17 skipped,含新增的 `keeps pulling earlier pages while the page only deepens the rendered turn`)、`npx tsc -p apps/ai-game-creator-shell/tsconfig.json --noEmit`(exit 0)。变异验证:把停止判据退化成「这一页有可渲染条目就停」后,跨页用例以 `Unable to find an element with the text: 更早的用户提问` 变红,即用户报的「点了没变化」。
|
||||
- 自动化(首屏锚点,已跑):`cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml agent::direct_project_history`(22 passed)、`npx vitest run apps/ai-game-creator-shell/tests/directHistoryAnchorGate.test.ts`(10 passed)、`npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts`(475 tests / 457 passed / 17 skipped,含新增的 `anchors the first history page at the subscribe receipt instead of the file tail`)、`npx tsc -p apps/ai-game-creator-shell/tsconfig.json --noEmit`(exit 0)、ESLint / prettier / `npm run check:encoding` / `npm run check:doc-index` / `git diff --check`。同一次全量里唯一失败是既有的 `edits the published runtime config without leaking API keys into chat`(`appSurface/runtime-settings.suite.ts`),与本次改动无关:把本次前端改动 stash 掉后它同样变红。变异验证:① 锚点闸门忽略「已消费」后,`directHistoryAnchorGate.test.ts` 的「同项目已消费返回 null」变红;② 首屏不等闸门后,`anchors the first history page at the subscribe receipt instead of the file tail` 以 `throughItemId` 缺失变红。
|
||||
- 运行时(待补):真实 app-server 会话下的新回合、杀进程重开、页面重进、分页与终止。
|
||||
- 边界:订阅过期、回执竞态、不可显示切片、无 `turn.completed` 的残回合、工具输出超长截断与脱敏。
|
||||
- 环境注意:`rehype-highlight` 已装齐后 `ChatMarkdownMessage` / `AgentMessageContent` 转绿;Node 26 下 vitest 的 jsdom 用例需要 `--localstorage-file` 才能拿到 `window.localStorage`(`clientApi.test.ts` / `chatPromptPolish.test.tsx`),已记入 `docs/project-memory/shared-memory/pitfalls.md`。
|
||||
@@ -0,0 +1,42 @@
|
||||
# Mac 客户端随包运行依赖补齐
|
||||
|
||||
- Version: 2
|
||||
- Status: awaiting-windows-acceptance
|
||||
- Date: 2026-09-18
|
||||
- Parent Spec: `docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md` / Runtime 边界 / 安装包侧车
|
||||
|
||||
## 目标与范围
|
||||
|
||||
产出可交给用户本地测试的 Apple Silicon DMG;Codex、平台辅助组件、插件入口和面板来自安装包,不依赖仓库或全局 Codex。保持 Windows 现有路径、版本、回退和安全语义。
|
||||
|
||||
## 非目标与依赖
|
||||
|
||||
不修改 Agent Loop、公开 API、持久化数据、版本号或更新签名;远程推送与草稿 PR 已获用户确认,不发布安装包、不自动合并。Node/Cocos Creator/账号仍使用现有外部前提。Cocos macOS 原生桥接不是文件打包修复,不计为本里程碑完成能力;Intel 实机构建与 universal 不在本次交付验收内。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 构建目标与锁定原生包匹配,缺组件或元数据错误失败关闭。
|
||||
2. `.app` 内包含全部原生组件、SHA-256 清单、声明及插件清单/入口/面板;Unix 可执行位保留,不含 Windows DLL、私有配置与构建缓存。
|
||||
3. 运行时先选随包文件,验证完整性和版本;覆盖缺失、篡改、平台不匹配及 macOS Resources 路径解析。
|
||||
4. 脱离仓库且限制 PATH、隔离 HOME 后,真实内置 Codex app-server 完成初始化握手;不能借全局 Codex 掩盖缺包。
|
||||
5. 定向 Rust 测试、配置/类型门禁、编码、文档索引和 diff 检查通过,DMG 校验通过;用户本地 GUI/登录/对话测试另行验收。
|
||||
|
||||
## 评审结论
|
||||
|
||||
2026-09-18 编码前自审:平台资源与运行时查找必须一起改;共享文件白名单避免双份清单漂移;不会复制 Windows 专属组件到 Mac;安装包结构证据和真实交互证据分开。以上范围可实施,不推进 Cocos 原生桥接下一里程碑。
|
||||
|
||||
## 验收现状与剩余门禁
|
||||
|
||||
### 评审反馈修订合同
|
||||
|
||||
2026-09-18 编码前自审:本轮仅修复同里程碑的目标平台传递、Cocos 能力门禁和文档冲突,不新增原生桥接或发布管线。CLI 显式目标必须覆盖环境默认,并在版本、构建、产物和清单全链路保持一致;不支持平台或渠道错配应在副作用前失败。Cocos 必须由已注册适配器决定可见/启动,覆盖无适配器、有适配器及非 Cocos 项目;前端不盲目启动隐藏插件。更新权威文档改为单架构策略,拒绝 universal,且不宣称现有发布脚本支持跨构建合并两种架构。新增回归通过后仍等待 Windows 验收;本地 0.1.67 版本修改保留,不与旧 0.1.47 安装包证据混淆。
|
||||
|
||||
评审修复验证:发布/feature/上传脚本测试 32 项通过,前端插件自动启动 5 项通过,Rust PluginHost 11 项与内置插件 10 项通过;Rust 使用 `TMPDIR=/private/tmp` 避免 macOS `/var` 系统链接触发既有路径安全断言。类型/配置、定向 ESLint、编码、文档索引和 diff 检查通过。测试覆盖显式目标覆盖环境、错误渠道提前拒绝、Tauri 实际注入配置、真实临时清单写入、Windows 默认 feature 保留、无 adapter 隐藏/启动拒绝、有 adapter RPC 回归。上述是自动化证据,不代表 Windows 真机、GUI 或带本次修复的新安装包已验收。
|
||||
|
||||
重打验证:重新 fetch/merge `origin/master` 确认当前分支已包含最新 master;按用户要求将 package、Tauri、Cargo 与锁文件版本同步到 `0.1.67`。包含上述修复的 Release `.app` 构建通过,Info.plist 实测版本 `0.1.67`、最低系统 `15.0`;隔离安装包脚本再次通过,DMG 用 hdiutil 生成并校验通过。此版本仍等待用户 GUI 与 Windows 回归,不做正式签名、公证、更新签名或产物上传。
|
||||
|
||||
- Mac 本地测试包已由用户确认“可以用了”;不外推为全部对话、工具和其它机器兼容性已覆盖。
|
||||
- 定向 Rust 验证 14 项通过,1 项真实认证用例按原配置跳过;发布脚本测试 21 项通过;隔离 HOME/PATH 的安装包资源检查、正式 Codex 查找、app-server 握手及缺组件拒绝通过。
|
||||
- 类型与配置、编码、文档索引、定向脚本 lint 和 diff 检查通过;139 MiB DMG 完整性通过。
|
||||
- 随包 zsh 的原生最低系统为 macOS 15.0;macOS Tauri 最低版本声明随之对齐,不能仅按主程序的 macOS 11.0 下限宣称整包兼容性。
|
||||
- Windows NSIS 构建、安装、随包 Codex 与 Cocos 原有能力回归尚待用户测试;其它 Mac、Intel、正式签名/公证和更新签名未验收。保持草稿,不推进合并或发布。
|
||||
@@ -1,29 +1,32 @@
|
||||
# 对话回合唯一投影
|
||||
|
||||
- Version: 2
|
||||
- Status: implemented-awaiting-runtime-acceptance
|
||||
- Version: 3
|
||||
- Status: superseded
|
||||
- Date: 2026-09-16
|
||||
- Superseded by: `../【里程碑】DirectProject聊天真相源收敛-2026-09-16.md`
|
||||
- Parent Spec: ../../technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md
|
||||
|
||||
## 范围与评审
|
||||
## 结论
|
||||
|
||||
单里程碑修复回合展示和流写入的一致性;补充终态重进恢复、用户发送时间和完成后的过程折叠。评审确认:活动快照及 Direct 事件拥有生命周期,Provider 回放不创建 client 回合;JSONL 信封可选时间字段不污染原始 item,无须数据库或旧数据迁移;最终回复沿用 Runtime 的最后 assistant item 合同,失败提示不折叠。没有身份的旧记录不得做位置猜配。
|
||||
本里程碑原先把「回合唯一投影」落在 Direct 回合事件 + `turn-stream.jsonl` + `tool-calls.jsonl` + 活动回合快照这条读路径上,方向已被推翻:聊天视图的输入只剩**项目对话历史**与**运行态事件**两项,Direct 回合事件、`turn-stream.jsonl`、`tool-calls.jsonl`、活动回合快照都不再是聊天视图的输入。后续实现与验收一律以 `../【里程碑】DirectProject聊天真相源收敛-2026-09-16.md` 与 `docs/adr/【ADR】DirectProject对话历史单一事实源-2026-09-16.md` 为准。
|
||||
|
||||
## 验收
|
||||
## 仍然有效的部分
|
||||
|
||||
1. 一个 turn 只有一个呈现入口,用户消息不丢失。
|
||||
2. item 增量、完成、持久化和回读保持相同身份与固定顺序。
|
||||
3. 工具输入输出保留,重复快照不重复渲染。
|
||||
4. TypeScript、最小 Cargo 检查、编码和 diff 检查通过;用户要求不运行测试,实机新回合/重开/分页验收待确认。
|
||||
5. 已结束回合重进不显示提交中,真实运行回合可恢复;跨项目/新回合迟到快照无效。
|
||||
6. 用户消息时间可刷新恢复,旧无时间记录不造值;完成后中间正文和工具统一折叠,最终回复及失败提示保持可见。
|
||||
1. 一个回合只有一个呈现入口,用户消息不丢失;历史里带不了身份(没有 id)的旧记录不得做位置猜配。
|
||||
2. 同一 item 的增量、完成、持久化与回读使用同一个身份、同一个顺序;重复快照不重复渲染。
|
||||
3. 工具调用的输入与输出都保留,展开后仍显示「输入 / 输出」。
|
||||
4. 已结束回合重进不显示提交中;真实运行回合可恢复。
|
||||
5. 用户消息时间只来自条目自己的时间戳,旧无时间记录不造值;完成后中间正文与工具统一折叠,最终回复与失败提示保持可见。
|
||||
6. 失败与中止说明只在运行期显示,不写进 `project.jsonl`;页面重进后不再出现。
|
||||
|
||||
依赖:既有项目历史和 v1 turn-stream / tool-calls DTO。未完成真实 UI 验收前不进入其它里程碑。
|
||||
## 已作废的部分
|
||||
|
||||
- 由活动回合快照接管运行中回合:改为由 `subscribe` bootstrap 事件判定(事件序列里 `turn.started` 之后没有 `turn.completed` 即运行中)。
|
||||
- 按 `turnId` 归并回合并把工具卡片挂在回合上:事件与条目都不再带回合身份,前端只有一个 `turnRunning` 布尔,卡片形状去掉 `turnId`。
|
||||
- 用 `turn-stream.jsonl` 的 `seq` 决定文本与工具的交替顺序:改为按运行态事件顺序 + 历史文件顺序投影。
|
||||
- 前端订阅 `game-creator-direct-turn-update`:改为 `subscribe` + `notify` 唤醒 `consume`(bootstrap 的事件直接 reduce,不再补一次 `consume`)。
|
||||
|
||||
## 当前证据
|
||||
|
||||
- 定向 TypeScript 类型检查、`cargo check --locked --bin genarrative-ai-game-creator-shell`、编码检查、文档索引检查、`git diff --check` 通过。
|
||||
- 已补充回合归属、分页、重复快照、无流回退及 writer 完成/切段、持久快照单调性/跨回合裁剪用例;按用户要求未执行测试,不能作为已通过凭证。
|
||||
- 静态自审确认视图只剩统一回合列表,不再存在 mapped/unmapped/live 三个回合流出口;失败提示使用稳定 failure 身份。
|
||||
- 真实新回合、历史重开、分页、失败/中断、工具展开输入输出仍待重启原生客户端后验收;仅本地提交,不推送。
|
||||
- 本次增量已完成生命周期来源收敛、信封发送时间和完成过程折叠;定向 TypeScript、ESLint、Cargo check、文档索引通过。新增时间幂等/旧记录、终态分类及内容分区用例但未运行;主页进入项目、重新发送/切项目竞态和自动折叠仍待原生实机验收,仅本地提交,不推送。
|
||||
- 里程碑版本的静态检查结论(TypeScript、Cargo、编码、文档索引、`git diff --check`)仍然成立;该增量按当时授权未运行测试。
|
||||
- 新路径的证据要求见 `../【里程碑】DirectProject聊天真相源收敛-2026-09-16.md` 的「验收标准」与「证据要求」,其中包含解锁此前跳过的工具卡片渲染用例。
|
||||
|
||||
@@ -3,14 +3,31 @@
|
||||
> 用途:记录已经确认、会影响后续开发的长期技术/产品/协作决策。短期讨论不要写在这里。
|
||||
> 当前口径:历史条目的旧路径、旧版本和已退役对象只用于追溯,不构成现行实现依据;如与当前代码或 `docs/README.md` 冲突,以当前代码和最新专题文档为准。
|
||||
|
||||
## 2026-09-18 Provider 瞬态重试次数严格按设置执行(游戏开发 Agent 与策划 Agent 不再被档位收进区间)
|
||||
|
||||
- 背景:AGC 客户端此前把 `agentLlm.<agent>.maxRetries` 按运行档位重新收进固定区间——`autonomous-game-build` 档位(自主构建的游戏开发 Agent 及其继承档位的专业子 Agent)被抬到 12~16,`standard` 档位(含立项策划入口的策划 Agent 与普通 Agent 对话)被压到最多 3;瞬态分类里的上游 400 还在同一预算上再收窄到 2 次。现场把 `maxRetries` 设成 5 时,游戏开发与策划两条链路都不按设置执行。
|
||||
- 决策:删除这三处区间限制,`maxRetries` 严格等于允许的物理重试次数(显式 `0` 仍表示不重试)。运行档位只保留「上游 400 是否算瞬态错误」的判定(autonomous 档位才重试 400),不再改写次数:`AGENT_RUNTIME_PROVIDER_TRANSIENT_RETRY_LIMIT`、`AGENT_RUNTIME_AUTONOMOUS_PROVIDER_TRANSIENT_RETRY_FLOOR`、`AGENT_RUNTIME_AUTONOMOUS_PROVIDER_TRANSIENT_RETRY_LIMIT`、`AGENT_RUNTIME_AUTONOMOUS_PROVIDER_UPSTREAM_400_RETRY_LIMIT` 四个常量与 `game_creator_agent_runtime_provider_transient_max_retries_at` 一并删除,换成返回 `{max_retries, retry_upstream_400}` 的 `game_creator_agent_runtime_provider_transient_retry_policy_at`。
|
||||
- 边界:只改重试次数的来源。瞬态错误分类(`timeout / connectivity / transport / 408 / 429 / 5xx / empty-response / deserialize / stream-unavailable`,以及 autonomous 档位下的 400)、`retryBackoffMs` 指数退避(仍封顶 30s)、durable retry sidecar / lifecycle / `-transient-N` slot 身份、cancel / steer / goal 门禁、耗尽后的 reconciliation 口径与「泥点不足不重试」都不变;前端设置面板与 `agentLlm.<agent>.maxRetries` 契约不变。
|
||||
- 验证方式:`provider_transient_retry_` 7 项中重写后的档位用例与 upstream-400 用例通过(断言 `maxRetries` 直取设置值、400 与其它瞬态共用同一预算),`provider_retry_` 其余 26/28 通过;该组 2 项(`provider_transient_retry_transport_failure_closes_then_stable_retry_succeeds`、`provider_transient_retry_backoff_is_exponential_and_capped_at_thirty_seconds`)与 `provider_retry_waiting_final_reply_*` 2 项在本机改动前后同为失败(`stash` 基线复跑确认,现象是等待自动重试唤醒超时)。本机串行全量套件另有既有环境失败(`tempfile::tempdir()` 归属校验、缺少 npm 构建产物、Windows 启动失败 MessageBox 阻塞 `startup_log_slot_fail_without_path...`);抽查其中 5 项在 `stash` 基线上同样失败,与本次改动无关。仓库 `cargo fmt --check`、`npm run check:encoding`、`git diff --check` 通过。
|
||||
- 关联文档:[AI游戏创作智能体App实施计划](../../technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md)、[踩坑记录](pitfalls.md)。
|
||||
|
||||
## 2026-09-17 AGC 抠图提交使用远端画布项目身份
|
||||
|
||||
- 背景:AGC 已通过本地项目 ID 建立并持久化本地项目到主站远端画布项目的绑定,但 `agc_remove_background` 提交请求仍把本地 `manifest.project_id` 放入 `projectId`;`assetFolderId` 已使用远端素材目录 ID。主站因此按项目不存在或不属于当前账号返回 404,主站抠图和 BgFilter 本身均正常。
|
||||
- 决策:抠图请求及工具回执统一使用 `prepare_external_canvas_generation_context` 返回的远端 `context.project_id`;本地 manifest 项目 ID 只用于绑定键和本地状态,不得作为主站业务请求的 `projectId`。
|
||||
- 验证:客户端定向 Rust 测试、格式、编码和 diff 检查通过;未修改主站路由或 BgFilter。
|
||||
|
||||
## 2026-09-17 图集切分模式改为显式声明
|
||||
|
||||
## 2026-09-17 DirectProject 首屏历史锚点只认订阅回执的 lastCompletedItemId
|
||||
|
||||
- 背景:ADR「首屏历史由 `subscribe` 返回的 `lastCompletedItemId` 锚定,再取最近切片」只落了一半。`DirectThreadManager` 是搬运层,内存里没有「已完成条目」的锚点,`subscribe` 一律返回 `last_completed_item_id: None`;`commands.rs` 的 `subscribe_direct_project_thread` 在为空时用 `read_direct_project_last_item_id_at` 从磁盘回填,所以线上回执里的值是真的(订阅那一刻文件里最后一条可显示条目的原始 item id)。前端侧:首屏一直在 `loadProjectConversation` 里用 `beforeItemId: null` 直接取文件尾一屏,`lastCompletedItemId` 自 `1b40f030e` 起不再被任何代码读取。
|
||||
- 决策(锚点语义):首屏切片的新端(较新一侧)边界就是这个锚点,**含锚点条目本身**;切片命令新增 `throughItemId` 参数表达「取到这条为止」。比锚点更新的条目只从运行态事件来,历史切片与实时流因此不重叠(原来的文件尾读取会把订阅回执之后才完成的条目也拉进历史,与运行态事件同 id 重叠,只靠前端合并兜住)。
|
||||
- 决策(读取时机):订阅回执到达之前不读首屏,也不退化成「取文件尾」;锚点缺失(订阅不可用 / 失败 / 历史为空)时才按文件尾取尾屏。`/history` 手动重读保持「按当前文件尾取尾屏」的恢复语义,不锚定。
|
||||
- 决策(翻页不变):向后翻页仍用切片返回的 `firstItemId` 作 `beforeItemId`(不含锚点),`hasMore` 与连拉口径不变。
|
||||
- 影响范围:`agent/direct_project_history.rs`(切片锚点 + `through_item_id` 参数)、`commands.rs`(`read_direct_project_history_slice` 命令参数)、AGC 前端首屏读取接线与测试骨架。**未改**:DirectRuntime 的 `turn-stream.jsonl` / `tool-calls.jsonl` 写入与进度事件、`list_game_creator_direct_active_turns`、SpacetimeDB 与 HTTP 契约。
|
||||
- 验证方式(已跑):Rust 侧 `cargo test agent::direct_project_history`(22 passed,含「窗口取到锚点那条、排除比锚点更新的条目、`beforeItemId` 与 `throughItemId` 互斥报错」三类用例);前端 `npx vitest run .../directHistoryAnchorGate.test.ts`(10 passed)与 appSurface 的 `anchors the first history page at the subscribe receipt instead of the file tail`(全量 475 tests / 457 passed / 17 skipped;唯一失败 `edits the published runtime config without leaking API keys into chat` 与本次改动无关,stash 掉本次前端改动后同样变红);`tsc` / ESLint / prettier / `check:encoding` / `check:doc-index` / `git diff --check` 全绿。变异验证:闸门忽略「已消费」、首屏不等闸门两处改动各自让对应用例变红。
|
||||
- 关联文档:[ADR](../../adr/【ADR】DirectProject对话历史单一事实源-2026-09-16.md)、[里程碑](../plans/【里程碑】DirectProject聊天真相源收敛-2026-09-16.md)、[实施计划](../plans/【实施计划】DirectProject聊天真相源收敛-2026-09-16.md)。
|
||||
|
||||
- 决策:`sliceMode` 在图标图集生成入口成为必填字段且不保留任何默认值。省略、`null` 或空字符串必须在引用解析、定价、入队和 provider / OSS 副作用之前返回 `400`(`field=sliceMode`);`grid` 必须同时提供 `gridX`/`gridY`,`connected-components` 不得携带网格尺寸,二者矛盾同样在副作用前失败关闭。
|
||||
- 决策要求:只有用户或需求明确要求等分网格、固定槽位或指定行列数时才使用 `grid`,且行列数必须来自该需求;自由排布、数量不定或只要求一张图集时显式传 `connected-components`,需要约束素材张数时用 `sliceCount`,不得用网格参数表达张数,也不得用固定 `2×2` 表达“四类素材”。
|
||||
- 影响面:平台两个图集生成入口(`/api/editor/...` 与 `/api/external/v1/editor/...`)、OpenAPI、画板 Agent 工具、画板前端提交计划、AGC 客户端 MCP 工具说明与桥接校验、AGC 原生工具 schema 与观察器、AGC Skill 与外部编辑器 Skill。
|
||||
@@ -80,6 +97,16 @@
|
||||
- 验证方式:`three_dimensional_game_request_frees_the_engine_choice`、`explicit_flat_presentation_requests_do_not_trigger_three_dimensional_selection`、`named_engine_requests_keep_the_existing_engineering_rule`、`three_dimensional_contract_reports_the_current_project_engine`、`home_three_dimensional_note_keeps_project_creation_available`、`system_prompt_is_bounded_and_declares_direct_runtime`,以及 `agent::direct_tools_mcp` 17 passed;`cargo fmt --check` 通过。本机临时目录 owner ACL 与进程用户不一致,涉及 `init_local_game_project_at` 的既有用例(含未改动模块)在本机无法执行,全量分片与真机 smoke 未在本轮取得。
|
||||
- 关联文档:[里程碑](../plans/【里程碑】Direct三维请求自选技术栈-2026-09-16.md)、[实施计划](../plans/【实施计划】Direct三维请求自选技术栈-2026-09-16.md)。
|
||||
|
||||
## 2026-09-17 DirectProject 历史分页的「可显示」口径定为前端回合反馈,一次翻页连拉上限 5 页
|
||||
|
||||
- 背景:ADR 与里程碑要求「一次翻页操作在前端自动连拉,直到出现可显示条目或 `hasMore=false`,上限 5 页」,但实现只落地了后端锚点与文件尾回扫,前端仍是单发一页。历史切片的 `limit` 按原始条目计,一整页全是工具卡片 / 思考文本且落进同一个已渲染回合的折叠「执行过程」时,用户点「显示更早的对话」看不到任何变化。
|
||||
- 决策(可显示 = 出现新回合):一次翻页操作连续取页,停止判据是**合并后聊天投影的回合数增加**(出现新的用户气泡)。工具卡片与思考文本虽然能通过 `projectDirectThreadItem`,但它们可能整页落进已渲染回合的折叠过程区,不构成用户可见反馈。
|
||||
- 决策(粒度和上限):每个用户操作最多 5 次请求,首屏那次算第 1 页、之后每次点击重新计数;每页仍是 `limit = CONVERSATION_VISIBLE_STEP`,上限只约束请求次数,不改页大小契约。
|
||||
- 决策(硬性终止):`items` 为空、`firstItemId` 为 null 或与请求锚点相同 → 立即停止,不靠 5 页上限兜底。
|
||||
- 决策(落点):口径与循环只在 `features/project-workspace/directHistoryPaging.ts` 一份实现里,首屏与「显示更早」共用;`DIRECT_HISTORY_MAX_PAGES_PER_ACTION` 放 `app/constants.ts`。
|
||||
- 边界:循环内只累积、结束后一次性并入聊天 state;某页失败时保留已成功页并沿用现有报错文案;切换项目时丢弃整批;不新增 loading / 禁用态与新文案,不做滚动锚定补偿;运行中回合允许连拉历史。
|
||||
- 验证:`directHistoryPaging` 单测 8 条覆盖口径、上限、`hasMore=false` 早停、锚点不前进、单页失败;`project-development.suite.ts` 新增「跨页同回合」集成用例作为真实回归网(变异验证:把判据退化成「有可渲染条目就停」后该用例变红);`tsc` 与 `appSurface.test.ts`(470 tests / 17 skipped)全绿。
|
||||
|
||||
## 2026-09-16 图标图集自动拆图上限提高到 256
|
||||
|
||||
- 背景:AGC 图标图集自动连通域识别在一次生成中识别出 86 个区域,原有 64 片上限在后处理阶段阻断了请求;该上限同时影响 api-server 自动 / 手动切片、SpacetimeDB 批量落库和统一生成结果 item 数量。
|
||||
@@ -8329,6 +8356,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
|
||||
- `.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 规则落盘。
|
||||
- 2026-09-17 追加:回显过滤必须同时覆盖**运行态事件侧**(`direct_thread_visible_item`,`item/started` 与 `rawResponseItem/completed` 两条路径),不能只过滤落盘。只过滤落盘时实时聊天会多出两条没有历史对应的孤儿用户气泡,各自开出一个「耗时 0 秒」的假回合,重进页面读同一份已过滤的 `project.jsonl` 又恢复正常;判据是 `direct_project_turn_does_not_forward_codex_user_echo_as_chat_items`(回合事件里只能有一条 `direct-codex:{clientTurnId}:user` 用户条目)。
|
||||
- 本地 AGC user-item 写入必须使用允许 user item 的内部入口,Codex raw item 写入使用过滤入口,避免“过滤回显”反过来阻断预写。相同 `clientTurnId` 只能复用相同规范化 prompt,内容冲突必须失败关闭。
|
||||
|
||||
## 2026-08-31 AGC 错误报告与诊断上传
|
||||
@@ -8907,3 +8935,13 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 上线依赖(本次未完成):`*.preview.genarrative.world` 通配证书(Let's Encrypt 通配只能走 DNS-01,域名在 DNSPod,certbot 无官方插件,需要 DNSPod API Token 配合 acme.sh)、station 侧按 Host 分发到 `84xx` 端口、dev 通配 vhost 与隧道;控制面本体需在 station 用 `scripts/deploy/preview-deployer-install.sh` 重建发布。
|
||||
- 验证:`cargo test -p preview-deployer-server`(13 项)、`apps/preview-deployer-web` vitest(13 项,含新增公网地址用例)、`npx tsc --noEmit`、`npm run preview-deployer:web:build`(`PREVIEW_DEPLOYER_WEB_BASE=/build/`)、`npm run check:preview-deployer`、`npm run check:encoding`、`git diff --check` 全部通过。
|
||||
- 关联文档:[开发运维](../../【开发运维】本地开发验证与生产运维-2026-05-15.md)、[Jenkins容器预览部署控制面技术方案](../../technical/【开发运维】Jenkins容器预览部署控制面技术方案-2026-08-15.md)。
|
||||
|
||||
## 2026-09-17 AGC 自动建项支持用户自选项目创建目录(入口设在设置「工作区」)
|
||||
|
||||
- 背景:首页「做游戏 / 做方案」与模板库「使用模板」的自动建项固定落在 `<app_data>/projects`,用户无法把游戏放到自己的工作盘或工程目录;同时该路径不能随意放开(受管私有目录门禁与 Documents 继承 ACL 的既有约束见 `pitfalls.md`)。
|
||||
- 决策:新增可选参数 `projectsRoot`(`create_automatic_local_game_project`、`create_automatic_local_game_project_from_template`),为空时由 Rust 回落到 `<app_data>/projects`。可选值只接受本机原生目录选择器返回的目录:`validate_requested_game_project_creation_root` 要求非空绝对路径、无控制字符、已存在的普通目录(拒绝链接/reparse point),并通过 `prepare_game_creator_project_root_for_read` 的 user-selected 范围校验与一次性修复;目录不存在不代为创建。
|
||||
- 决策:客户端偏好「项目创建目录」存 `localStorage` 键 `genarrative-ai-game-creator.project-creation-directory.v1`;入口只在设置里(侧边栏「配置」→ 分类「工作区」),首页输入行与模板库页头不再各挂一个入口。「恢复默认位置」即清空偏好。偏好只表达用户意图,不是授权凭据:每次建项都重新过 Rust 门禁,存储被改坏最坏是回退默认位置或一次可见失败。既有项目不迁移。
|
||||
- 决策:该偏好属于客户端本地设置,不并入 `read_game_creator_app_config` 那份运行时配置:在「工作区」里选择目录当场生效,不受「保存设置」按钮影响;首页与模板库建项时各自读取同一份偏好。
|
||||
- 决策:`pick_local_project_directory` 增加可选 `title`(限 24 字符、无控制字符,其余回退默认标题),使「选择项目创建目录」不再冒用「选择游戏项目目录」文案。
|
||||
- 关联规范:`docs/project-memory/plans/【实施计划】AGC项目创建目录可选-2026-09-17.md`、`docs/technical/【技术方案】AGC模板库与模板建项-2026-09-17.md`。
|
||||
- 验证:`cargo test --bin genarrative-ai-game-creator-shell creation_root`(2 项)、模板库定向单测 14 项、偏好模型 3 项、`appSurface` 472 项(含设置页「工作区」选择/恢复目录与「设置里选目录后建项带 `projectsRoot`」两条场景)、`tsc`、`check:encoding` 与 `check-doc-index` 通过。
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# 踩坑与排障记录
|
||||
|
||||
## 发布目标与原生能力必须贯穿完整入口
|
||||
|
||||
显式 `--target` 不能只改变 Tauri 命令参数;AGC 发布入口必须把同一解析结果传给版本高水位、更新端点、产物目录/后缀和清单平台键,否则 macOS 构建可能错误使用 Windows 渠道。插件文件存在也不代表 native 能力可用:Cocos 在宿主注册表缺少适配器时应隐藏并拒绝启动,前端自动启动消费后端列表投影,不能仅凭项目类型推断能力。发布策略以客户端更新权威文档为准,单架构资源不能登记成双架构产物。
|
||||
|
||||
## macOS 安装包小不代表运行依赖齐全
|
||||
|
||||
AGC 的 DMG 生成成功只证明应用可以被打包。平台专属 Codex staging、Tauri resource 映射、运行时资源目录定位和辅助组件 SHA-256 清单必须同时闭合;只配置 Windows 资源会让 Mac 开发机因全局 Codex 而掩盖缺包。macOS 使用锁定原生依赖中的 Codex、code-mode host、rg 和 zsh,不能复制 Windows EXE/DLL。用 `scripts/check-macos-bundle.mjs`(AGC 应用目录下)对复制到临时目录的 `.app` 做限制 PATH、隔离 HOME 的正式查找、app-server 握手和缺组件拒绝检查;GUI、账号、Provider 与 Cocos 原生桥接另行验收。插件 JS 入口仍依赖系统 Node,不得将“插件文件随包”表述为“无需任何外部工具链”。
|
||||
|
||||
## AGC 空快照测试必须等待请求完成
|
||||
|
||||
`waitFor(() => expect(activeTurns).toEqual([]))` 在 Hook 初始状态就能成功,不能证明首次异步读取已经完成。引用稳定性回归应显式控制 Promise 完成,并同时检查首次空响应与禁用后的引用;快照签名初值必须与初始空数组一致。窗口同步测试应验证未变化状态不重复发布,不能依赖一次多余的空态更新。
|
||||
@@ -27,10 +35,6 @@ Vite 默认监听应用根下的 Rust `src-tauri/target`,构建产物较多时
|
||||
- **原因**:这个 shell 以管理员身份运行,`New-Item` / `tempfile` 新建目录的 owner 是 `BUILTIN\Administrators`,而 AGC 的校验要求 owner 等于当前用户 SID(`KDLETTERS\<user>`)。`Get-Acl <path> | Select Owner` 与 `whoami` 一比就能定性;同一台机器上由客户端自己创建的目录 owner 正确,所以「客户端自己建的项目能用、手建的不能用」。
|
||||
- **处理**:手工夹具先 `icacls <path> /setowner "<DOMAIN>\<user>" /T`;Rust 用例改用工程自带的 `crate::tests::canonical_test_tempdir(prefix)`(它会 canonicalize 并重置目录 owner),不要直接用 `tempfile::tempdir()`。判「用例失败与本改动无关」时,先确认失败信息是不是这一条。
|
||||
|
||||
## DirectProject 历史不能按工具条目切页再按消息推进游标
|
||||
|
||||
原始 `response_item` 历史同时含用户/助手消息、推理与工具输出。若原生每次取 20 个原始条目、前端过滤聊天消息后再找最旧 ID,纯工具页会让消息集合为空且游标不动,看起来历史丢失。聊天读取固定显式请求 `messagesOnly: true`,原生逐行过滤后按消息分页并返回 `oldestItemId`;默认原始模式留给原始条目消费者。无 ID 旧消息保留并扩展到可寻址边界,不能造 ID。前端保留项目与读取代次、单飞及 ID 去重,旧请求的成功、失败与 finally 都不能覆盖新读取;真实日志只在临时目录只读重放,不能提交正文夹具。
|
||||
|
||||
## JSON 卡片显示与 UI 编辑能力必须同源
|
||||
|
||||
JSON 的文本读取分支不等于卡面应该展示原始 State 摘要。卡片、缩略图及编辑器入口共同消费受控文本预览的 `uiDesignAssetId`;只有原生复用 UI 持久化合同校验 schema、完整 State 和项目/资产身份后才设置它。普通 JSON 保留 JSON 代码预览,不按 `kind: UI/ui` 或 schema 字符串片段猜测编辑能力。已有合法 UI State 的加载/保存不依赖 kind 精确大小写,但新建初始化仍保留正式 UI 资产门禁;缓存与项目切换须保留现有身份隔离。
|
||||
@@ -244,6 +248,15 @@ AGC 的 Cocos 能力来自随客户端分发的 `agc-cocos-editor` 内置插件
|
||||
首页命名回合成功后创建命令失败且不会留下项目目录。用户通过目录选择器创建的
|
||||
项目仍走 user-selected 权限范围。
|
||||
|
||||
- 2026-09-17 补充:首页与模板建项支持用户自选 `projectsRoot`(见
|
||||
`docs/project-memory/plans/【实施计划】AGC项目创建目录可选-2026-09-17.md`)。
|
||||
自选目录只有一条合法来源——本机原生目录选择器返回的目录,并且必须在 Rust 侧
|
||||
通过 `validate_requested_game_project_creation_root`
|
||||
(绝对路径 / 无控制字符 / 已存在普通目录 / 非链接与 reparse point /
|
||||
`prepare_game_creator_project_root_for_read`)。默认值仍必须是
|
||||
`app_data_dir()/projects`:不要因为"用户能自选"就把默认值改成 Documents 或
|
||||
其它用户目录,也不要在目录不存在时替用户创建。
|
||||
|
||||
## 2026-09-12 Cocos 项目识别不等于编辑器桥就绪
|
||||
|
||||
- 现象:能发现正确 Creator PID、Agent 也有 `agc_cocos_execute`,但首次执行报 pipe 不存在;仅登记目标的 `connect` 会误报成功。
|
||||
@@ -5695,10 +5708,17 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
|
||||
- **现象**:在 `apps/ai-game-creator-shell/src-tauri` 跑过 `cargo test` 之后,`npm run ai-game-creator-shell:typecheck` 报 10 条类型错(`src/features/project-workspace/resourceReferences.ts:106-112` 的 `string | undefined` 不能赋给 `string | null`;同文件 134 行的对象字面量带 `type: 'message'`,而 `DirectCodexUserMessageItem` 里没有该字段),`npm run ai-game-creator-shell:build` 也死在 `beforeBuildCommand` 的同一条 typecheck 上。
|
||||
- **原因**:crate 里的 ts-rs 导出会按**本机依赖版本**重写 `src/features/project-workspace/generated/DirectCodexUser*.ts`:注释头变成 "This file was generated…"、字符串改双引号、`DirectCodexUserMessageItem` 丢掉 `type: 'message'` 判别字段、并多出一个 `DirectCodexUserMessageEnvelope.ts`。仓库里提交的那份是前端真正依赖的形状(前端按带 `type` 的判别联合写),重写后两边就对不上——错在生成器版本漂移,不在前端。
|
||||
- **处理(现行口径)**:不要把重写结果当改动提交。跑过 `cargo test` 或构建后先 `git checkout -- apps/ai-game-creator-shell/src/features/project-workspace/generated`,再删掉多出来的 `DirectCodexUserMessageEnvelope.ts`,然后才做 typecheck / 打包;绑定与前端形状冲突时以**已提交的绑定 + 前端**为基准排查。
|
||||
- **验证**:恢复提交版本后 `npm run ai-game-creator-shell:typecheck` exit 0(`[skill-pack] OK`);保留重写结果时同一条命令 exit 2。release 构建本身还会在 `src/features/ui-editor/types/` 落下 `BindingChange.ts` / `BindingDTO.ts` 两个无人引用的未跟踪文件,属同类生成产物。
|
||||
- **处理(现行口径)**:不要把重写结果当改动提交。跑过 `cargo test` 或构建后只恢复 `apps/ai-game-creator-shell/src/features/project-workspace/generated/DirectCodexUser*.ts` 的仓库版本,再删掉多出来的 `DirectCodexUserMessageEnvelope.ts`;不要恢复整个 `generated/` 目录,以免误删 DirectThread 的现役绑定。绑定与前端形状冲突时以**已提交的 DirectCodexUser 绑定 + 前端**为基准排查。
|
||||
- **验证**:恢复仓库版本后 `npm run ai-game-creator-shell:typecheck` exit 0(`[skill-pack] OK`);保留重写结果时同一条命令 exit 2。release 构建本身还会在 `src/features/ui-editor/types/` 落下 `BindingChange.ts` / `BindingDTO.ts` 两个无人引用的生成产物;它们不属于前端契约,发现后直接删除,不提交。
|
||||
- **关联**:`apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_user_item/`(ts-rs 导出源)、`apps/ai-game-creator-shell/src/features/project-workspace/resourceReferences.ts`、`apps/ai-game-creator-shell/scripts/build-release.mjs`(`beforeBuildCommand`)。
|
||||
|
||||
## 2026-09-16 Node 26 下 vitest 的 jsdom 用例拿不到 window.localStorage
|
||||
|
||||
- **现象**:只声明 `@vitest-environment jsdom` 的用例里 `window.localStorage` 是 `undefined`(典型报错 `Cannot read properties of undefined (reading 'clear')`);而 `appSurface.test.ts` 里同样访问 `window.localStorage` 却一切正常。
|
||||
- **原因(已核对,不是推断)**:Node 26 在 `globalThis` 上定义了实验性 `localStorage` 访问器,不传 `--localstorage-file` 时它返回 `undefined`。vitest 0.34 的 jsdom 环境把 jsdom window 的描述符复制到全局时,不会覆盖 `globalThis` 上已存在的键,于是 jsdom 真正的 `Storage` 被 Node 的 `undefined` 顶掉。`appSurface` 之所以不受影响,是因为 `apps/ai-game-creator-shell/tests/appSurface/harness.ts` 自己用 `Object.defineProperty(window, 'localStorage', …)` 挂了内存实现。
|
||||
- **处理**:跑这类用例时给 Node 加 `--localstorage-file`,例如 `NODE_OPTIONS="--localstorage-file=/tmp/vitest-node-localstorage" npx vitest run <files>`;`apps/ai-game-creator-shell/tests/clientApi.test.ts` 与 `chatPromptPolish.test.tsx` 加这个开关后 26 项全绿。不要改业务代码或往测试里塞假 storage 来绕过。
|
||||
- **关联**:`vitest.config.ts`(`environment: 'node'` + 用例内 docblock 切 jsdom)、`apps/ai-game-creator-shell/tests/appSurface/harness.ts` 的内存 localStorage 垫片。
|
||||
|
||||
## 2026-09-17 AGC 壳首页无限 setState:effect 依赖了每次渲染都换身份的普通函数
|
||||
|
||||
- **现象**:dev 客户端停在首页、不点任何东西也会持续刷 `WEBVIEW error webview: Maximum update depth exceeded …`(5 秒涨 ~8.5 KB 日志),对应 WebView2 renderer 工作集涨到 **4.2 GB**、CPU 持续累计(约 0.7–1.5 核);表现上很像"模板库卡片太多/滚动卡",实际与页面内容无关。
|
||||
|
||||
Reference in New Issue
Block a user