Merge branch 'master' into feat/agc-run-preview-tip
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m28s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m59s
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 lane 2/2 (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 / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m28s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m59s
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 lane 2/2 (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 / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
This commit is contained in:
@@ -5909,6 +5909,56 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
- **验证**:修复后同一台机器、同一路径下 35 秒内新增 `Maximum update depth` **0 条**,renderer 工作集 **254 MB**(修复前 4.2–4.4 GB);`apps/ai-game-creator-shell/tests/directActiveTurns.test.tsx` 断言轮询返回值不变时快照引用不变。
|
||||
- **关联**:`apps/ai-game-creator-shell/src/features/app-shell/WorkspaceLauncher.tsx`、`apps/ai-game-creator-shell/src/features/agent-runtime/directActiveTurns.ts`、`apps/ai-game-creator-shell/src/components/WindowChrome.tsx`、`apps/ai-game-creator-shell/src/features/app-shell/useHomeProjectCreation.ts`。
|
||||
|
||||
## 2026-09-22 自动合并"无冲突"也可能静默拼坏 CSS 分组选择器
|
||||
|
||||
- **现象**:合并 master 时 git 报告 0 冲突,但 `apps/ai-game-creator-shell/src/styles.css` 里新加的头条规则被并进了 master 策划态分组选择器的中间——`.game-workbench-layout--design .project-chat-topbar-status,` 后面直接跟了别的选择器,策划态的 `font-size` / `color` 等声明整块丢失;类型检查与多数用例都不受影响,只有 `chatDialogFrameLayout` 这类 CSS 级联用例报"缺少生效声明"。
|
||||
- **原因**:双方在同一分组选择器附近各自插入规则时,hunk 可以"兼容"地拼在一起,git 不会报冲突,但选择器列表被拆散。
|
||||
- **处理**:改完 CSS 后按 master 原文重建分组规则、把新增规则独立成块;顺手删掉重复规则时要用带上下文的精确片段,避免删到分组选择器的第二个选择器。
|
||||
- **验证**:`npx vitest run apps/ai-game-creator-shell/tests/chatDialogFrameLayout.test.ts`(12 用例)与全量 `npm test` 通过。
|
||||
|
||||
## 2026-09-22 合并 master 时“双方保留”不是通用解法
|
||||
|
||||
- **现象**:把分支与 master 的同一批冲突统一按“ours + theirs 依次保留”处理后,`apps/admin-web/src/api/adminApiTypes.ts`、`api/adminApiClient.ts`、`app/adminRoutes.test.ts` 都出现语法/结构错误(接口少闭合、函数体被截断、用例少 `});`)。prettier 能通过、vitest 里被转译的纯类型文件也不报错,只有 `tsc`(admin-web typecheck)与随后单文件跑测试才暴露。
|
||||
- **原因**:冲突块可能切断一个语法结构(接口、函数、`test(...)` 调用),而双方各自的块只是在“同一位置添加内容”,拼起来会丢闭合;类型文件在 vitest 里被 esbuild 直接剥离类型,不会校验。
|
||||
- **处理**:冲突若落在语法结构内部,按“以某一侧为完整骨架、把另一侧的新增内容插到正确位置”重建,而不是简单拼接;重建后必须跑 `tsc`(含 `npm run admin-web:typecheck`)并对改动文件单独跑一次 vitest,别只看全量测试是否绿。
|
||||
- **验证**:合并后 admin-web 23 个测试文件 212 用例全绿、两端 typecheck 通过。
|
||||
|
||||
## 2026-09-20 复用注册端口段时可能连到别的 worktree 的 SpacetimeDB
|
||||
|
||||
- **现象**:在 `/data/dsk/Genarrative` 跑 `npm run dev:api-server` 后,日志显示端口段 `10000-10099 (dsk)`、spacetime `http://127.0.0.1:10002`,但 api-server 反复报 `ws://127.0.0.1:10002/v1/database/xushi-p4wfr/subscribe` 返回 `HTTP error: 404 Not Found`,且始终不响应 `/healthz`。
|
||||
- **原因**:该端口段是**按用户**登记的,同一用户的其他 worktree 实例已占用 `10002`;启动器只探测到端口被占用就按"已复用"继续,api-server 于是连到了另一份 data-dir 的 standalone,那里没有当前 database,发布步骤也没有落到这个实例上。api-server 在启动恢复阶段会一直重试,**accept 了连接但不返回任何响应**,所以 `curl` 表现为超时而不是连接拒绝。
|
||||
- **处理(现行口径)**:核对 `ss -ltnp | grep :10002` 的进程与 `--data-dir` 是否属于当前仓库;不属于就换用空闲端口段(`GENARRATIVE_DEV_PORT_RANGE` / `--port-range`)或先停掉确认无用的实例,不要把 404 当作 schema 缺失去改代码。排查"健康检查通过但接口 404"时不要只跑 `/healthz`。
|
||||
- **关联**:`scripts/dev.mjs`、`scripts/dev-stack-port-utils.mjs`、`/var/tmp/genarrative-dev-port-ranges/registry.json`、[`.codex/skills/genarrative-dev-stack-port-routing/SKILL.md`](../../../.codex/skills/genarrative-dev-stack-port-routing/SKILL.md)。
|
||||
|
||||
## 2026-09-20 新增 API 命名空间在本地返回 404:Vite 代理是前缀白名单
|
||||
|
||||
- **现象**:api-server 上 `GET /api/game-distribution/games` 直连返回 200,但浏览器里 `http://127.0.0.1:<web>/games` 报 `404`,页面显示「读取游戏目录失败」。同一 URL 换成 `curl` 直连后端却正常。
|
||||
- **原因**:`vite.config.ts` 的 `server.proxy` 是**逐个前缀白名单**(`/api/auth`、`/api/profile`、`/api/runtime`、`/api/editor`、`/api/assets`、`/api/llm`、`/api/ws`),没有兜底 `/api/`。未登记的新命名空间不会转发到 Rust 后端,而是回退到 SPA 静态资源,前端再按 JSON 解析就失败。生产 nginx 走的是通用 `location ^~ /api/`,所以症状只出现在本地 dev。
|
||||
- **处理(现行口径)**:新增任何 `/api/<namespace>` 时,同一次变更里补 `vite.config.ts` 代理项和 `src/config/viteProxyConfig.test.ts` 断言;`src/config/**` 已加入 `vitest.config.ts` 的 include,漏测会直接红。注意该测试文件里可能残留已退役前缀(例如已退役的 `/api/creation-entry`)的断言,退役命名空间按「四不写」直接删断言,不要为它补代理。
|
||||
- **关联**:`vite.config.ts`、`src/config/viteProxyConfig.test.ts`、`vitest.config.ts`、`server-rs/crates/api-server/src/app.rs`、`deploy/nginx/genarrative.conf`。
|
||||
|
||||
## 2026-09-20 发行网关用 CORP same-origin 会让沙箱内游戏加载不了自己的脚本
|
||||
|
||||
- **现象**:平台游玩页的 iframe 明明 `onLoad` 了(加载遮罩消失、`game-player-frame--ready`),但控制台出现 `net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin … /releases/<gameId>/assets/app.js`,游戏内的脚本从未执行;直接在新标签页打开同一个 `index.html` 却一切正常,很容易误判成「已经能玩」。
|
||||
- **原因**:按安全合同 iframe 必须只用 `sandbox="allow-scripts"`(禁止 `allow-same-origin`),文档因此是不透明来源(opaque origin)。此时它对同包资源的请求不再与网关同源,而响应上的 `Cross-Origin-Resource-Policy: same-origin` 会把请求判为跨来源并拦下;ES modules 还会额外走 CORS,需要 `Access-Control-Allow-Origin`。
|
||||
- **处理(现行口径)**:发行网关的公开静态响应使用 `Cross-Origin-Resource-Policy: cross-origin` 与不带 credentials 的 `Access-Control-Allow-Origin: *`,继续保留 `X-Content-Type-Options: nosniff`、内容类型白名单、HTML 最小权限 CSP 和「带 Cookie 一律 403」。这些都是公开静态文件,放宽 CORP/CORS 不暴露凭据;容器隔离靠沙箱、CSP 与独立来源,不靠 CORP。
|
||||
- **验证方式**:不要只用 `onLoad` 判断可玩。要在真实浏览器里点「开始游戏」,确认控制台没有 `ERR_BLOCKED_BY_RESPONSE`/CSP 报错,并核对 api-server 访问日志里该版本资源的 `http.response.status_code=200`。
|
||||
- **关联**:`server-rs/crates/api-server/src/modules/game_distribution.rs`(`release_asset_response`)、`src/components/game-distribution/GamePlayPage.tsx`、[`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`](../../【玩法创作】平台入口与玩法链路-2026-05-15.md)。
|
||||
|
||||
## 2026-09-20 在 jsdom 里把 AGC 发布接到真实后端:Blob 没有 arrayBuffer,且跨 realm BodyInit 会被 undici 拒绝
|
||||
|
||||
- **现象**:给 AGC 的 `publishLocalProjectGame` 写“默认跳过”的真实后端集成测试时,创建游戏、创建版本都成功,只有上传 ZIP 报“无法连接登录服务”(`networkError: true`),服务端访问日志里也没有这次上传。
|
||||
- **原因**:测试跑在 jsdom 环境,`fetch` 是 Node(undici),但请求体是 jsdom 的 `Blob`:① 该 jsdom 版本的 `Blob` 没有 `arrayBuffer()`(`typeof blob.arrayBuffer === 'undefined'`),直接调用会抛异常;② 即便拿到字节,jsdom realm 的 `ArrayBuffer`/`Uint8Array` 也不是 undici 认得的 `BodyInit`。
|
||||
- **处理(现行口径)**:桥接层用 `FileReader.readAsArrayBuffer` 读 jsdom Blob(有 `arrayBuffer` 时才走它),再用 `Buffer.from(new Uint8Array(...))` 复制成 Node 侧 Buffer 交给 undici。参考 `apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts`。
|
||||
- **关联**:`apps/ai-game-creator-shell/tests/gameDistributionPublishLive.test.ts`、`apps/ai-game-creator-shell/src/services/clientHttp.ts`。
|
||||
|
||||
## 2026-09-20 AGC 导出后自动弹发布面板:焦点陷阱会吞掉模态之外的点击,既有导出快捷操作用例变红
|
||||
|
||||
- **现象**:给 AGC 加「导出试玩包后自动打开发布到游戏广场面板」后,`appSurface.test.ts` 的「预览快捷操作:导出确认、取消与包列表」变红——期望点消息上的「显示目录」把 `/open-project` 填进输入框,实际输入框仍是空。把发布面板的自动打开去掉,或用例先关掉面板,就恢复绿色。
|
||||
- **原因**:同目录的 `ThemedModal` 用 `createPortal` + `focus-trap-react` 渲染模态。焦点陷阱存在时,模态之外的 `click` 不会触达 React 的处理器(实测:临时把 `FocusTrap` 换成普通 `div`、其余不动,同一个被模态遮住的按钮点击立刻恢复生效),所以自动化里“点模态背后的按钮”不会报错,只是静默无效。
|
||||
- **处理(现行口径)**:① 产品行为保留“导出成功后自动打开面板”(一键发布入口),但受影响的用例必须先用 `findByRole('dialog', { name: '发布到游戏广场' })` 断言面板出现、点「关闭发布面板」再继续后续会话操作;② 给这类“新增自动弹窗”改流程时,先跑一遍相关 `appSurface` 用例,避免只跑新增用例;③ 排查同类“点了没反应”时,先看当前是否有焦点陷阱模态打开,而不是先怀疑事件绑定或状态。
|
||||
- **关联**:`apps/ai-game-creator-shell/src/App.tsx`(`setPublishPanelOpen(true)`)、`apps/ai-game-creator-shell/src/components/modal/ThemedModal.tsx`、`apps/ai-game-creator-shell/src/components/game-distribution/GameDistributionPublishPanel.tsx`、`apps/ai-game-creator-shell/tests/appSurface/project-preview/preview-shortcuts/assert-project-tools-and-preview.ts`。
|
||||
|
||||
## 2026-09-21 受控 Lexical 输入区的回写用被动 effect:滞后渲染的 props 会把用户草稿清空
|
||||
|
||||
- **现象**:DirectProject 输入盒里粘贴(或连续输入)长文本,提交时 `chat_with_game_creator_direct_codex` 根本没发出去,界面停在空输入盒;`chat-composer` 用例里表现为「队列/终止/语音追加」五条一起红,但手工操作只在快速输入后偶发。
|
||||
@@ -5962,5 +6012,7 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
- 处理:预热使用已核实的 Gitea 路径 `/workspace/GenarrativeAI/Genarrative`,并与分片运行器一样从 AGC `src-tauri` 启动 Cargo;保存 `workspace.txt`,路径不符时回退直接编译。wrapper 放在容器内固定路径,daemon 状态与 Unix socket 仍使用随机私有目录;预热环境与 workflow 的 Cargo 环境由定向契约测试核对。不要为命中率随意增加 `RUSTFLAGS`、改写源码路径或恢复共享可写 target。
|
||||
- 验证:相同源码、资源上限和独立干净 target 下分别记录无缓存、冷缓存、热缓存的编译耗时和 hit/miss;只有真实热命中有净收益才切换候选镜像。PR 的写入始终留在 job 容器层,公共快照仍由可信维护流程生成。
|
||||
- 统计:job 私有 daemon 设置 `SCCACHE_IDLE_TIMEOUT=0`,由 `report` 显式停止;最终测试 bin 的不可缓存编译或测试可能超过一分钟,短 idle timeout 会让 daemon 提前退出,结尾查询启动新 daemon 后误报零次请求。容器销毁仍会回收该 job 的全部进程。
|
||||
- 磁盘:快照构建拒绝含 `/opt/genarrative-ci/rust-cache` 的基础镜像,始终从无对象缓存的镜像重建;容器内删除旧对象不能释放 Docker 底层。对象缓存容量上限不涵盖宿主旧镜像及导出归档,切换验证后按运维文档人工保留当前版和一个回滚版,同时保护运行中 CI 使用的镜像。
|
||||
- 磁盘:快照构建拒绝含 `/opt/genarrative-ci/rust-cache` 的基础镜像,始终从无对象缓存的镜像重建;容器内删除旧对象不能释放 Docker 底层。对象缓存容量上限不涵盖宿主旧镜像及导出归档。自动维护只回收自己预先登记的 Image ID/tag 和专属归档,保留当前、一个回滚版、基础镜像及所有容器引用;内层按 ID 导入的镜像可能没有 tag,不能只按 tag 判断已清理。接管前历史试验版本仍需人工确认。
|
||||
- CI 产物清理:Gitea 1.26.4 的仓库 REST 仅列出 finalized/expired V4 artifact,内置到期清理不回收上传中断的 tmp-upload 分块。缓存上传块须带专属标识,宿主只清理目标仓库已结束且超过 7 天的 master run 中同样过期的自有普通文件,未知文件/符号链接保护,不改数据库或全局 prune。Artifact.workflow_run 仅含 ID/SHA,判断过期产物所属事件和状态须再读 run API,不能当作完整 run 使用。
|
||||
- 自动切换:Gitea 1.26.4 的 disabled 检查与 FetchTask 事务不原子,Runner 客户端超时不能证明服务端回滚,容器暂时为空也不能证明没有已领取任务。网关必须解析实际 Connect Protobuf/gzip,转发 FetchTask 结果前持久化任务 ID,仅在最终日志及执行清理后的最终 UpdateTask 确认后清账;取消响应不能提前释放。暂停新领取、在途为零、账本为零且内层活动容器为空才可切换,无需全局 Runner admin API。未知协议/响应或崩溃遗留标记停止切换;旧网关缺 active_tasks 不能默认零。首次接入与账本升级须空闲窗口。.runner 的 mtime 不证明地址已加载,应核验真实 FetchTask 来源及本次容器启动时间。
|
||||
- 扩展:预热所有 Rust 测试组时保留各自 cwd、profile、features 和锁策略;同一临时 target 的 Cargo fresh 不代表不同 cwd 都已生成缓存键,AGC 提示词契约、分片和 smoke 切换入口前清理预热 target。不要把 workspace 与 spacetime-module 合并成一次编译;Native shell release step 清空双 wrapper,避免将测试缓存扩展成发布缓存。当前 sccache 0.18.0 的 READ_ONLY 在 miss 后仍打包产物并产生 cache write error,不适合用来承诺“未命中无开销”。
|
||||
|
||||
Reference in New Issue
Block a user