合并远端 master(直连 Codex 改造)
冲突 19 处 / 6 个文件,逐处判定归属而不是二选一:
· commands.rs —— 保留本分支的 hydrate_game_creator_plan_gdd_state 输入解析,
丢掉与 master 重复的项目根定义(master 把它挪到了后面)。
· types.ts / useHomeProjectCreation.ts —— 取 master 把 mode/prompt/attachments
重构成 HomeDraft 的形状,保留本分支新增的 startMode。
· App.tsx —— directGameChatRuntime(master)与 !planningStartMode(本分支)是两个
互不相干的条件,合并保留;refreshDirectProjectSurface 在 merge base 里就带预览
逻辑,是 master 主动删掉并改名成 refreshDirectProjectManifest 的,取 master;
capturePendingGameChatStageManifestBeforeNextRun 是分支新增且仍被调用,保留。
· SupervisorChatOnlyView.tsx —— master 的 directCodex 短路与本分支的
projectedRuntime / descendantsStillActive 正交,逐处合成。
· project-development.suite.ts —— 那段专业 Agent 断言 base 里就有、master 主动
删除(直连 Codex 之后不再适用),取 master。
两处语义缺口一并补上:master 新增的 codex_app_server 构造
AgentRuntimeProviderRequestSnapshot 时缺本分支新增的 planning_session_binding
字段(首页直连对话不属于任何立项 session,填 None);首页提交按钮的 aria-label
还引用着已被删除的 homeAgentMode,取 master 的固定文案。
**做方案 UI 入口暂时缺失,待定。** master 在 bacd7a9da 里把 HomeAgentMode 整个删了,
首页的「做游戏 / 做素材 / 做方案」模式选择不再存在,而 startMode 在前端只有那一个
来源(homeDraftStartMode(mode))。立项策划链路的代码全部保留——后端、prompt、
澄清卡、审批卡、E2E 都在——但首页现在统一按 direct-build 进入
(HOME_DRAFT_START_MODE 常量,已在原处留注释)。入口放哪由产品侧决定后另做一笔。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -183,6 +183,13 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- **结论**:`WP1` 的 `repair_depth≤1` 结论未被推翻;Unknown 只增加前向不兼容时的保守阻塞,不会放宽普通做游戏链路的返工深度门。
|
||||
- **验收门禁与关联**:定向回归须覆盖未知 raw round-trip、barrier/waiting、无条件返工拒绝、保守 lineage 分类,以及损坏 sidecar 整体锁死;详见技术方案第 23.7 节裁决三与第 23.8 节 `M1C-0b` 门禁。
|
||||
|
||||
## 2026-08-15 完美像素编码前按整数倍 nearest 放大到接近源图
|
||||
|
||||
- 背景:2026-08-10 起成功产物直接落逻辑网格 PNG,画布按资源实际宽高显示,结果会明显小于源图。用户要求保持逻辑图宽高比,并把产物放大到接近原图;禁止再走非整数 nearest 拉回精确源尺寸(会让逻辑块宽窄不一)。
|
||||
- 决策:`style="pixelArt"` 与手动 `POST /api/editor/images/pixel-art-snaps` 仍共用 `snap_pixel_art_with_grid_policy`。检测、切线、采样、Alpha、strict 拒兜底不变。`resample` 之后、`encode_png` 之前,用单一整数 N 做 nearest 放大:`N*` 为 `(C·W + R·H) / (C² + R²)`,在 `floor` / `ceil`(小于 1 当 1)中取距离平方更小者,并列取较小 N;超单边 `10000` 或总像素 `8294400` 则降 N,最低 `N=1`。只持久化这一张 PNG。手动算法指纹升为 `perfect-pixel-v3`。
|
||||
- 不做:改 walker、透明补边、裁切、横纵不同倍率、Lanczos / bilinear、另存逻辑图、前端框缩放、失败路径、新测试。
|
||||
- 关联文档:`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`、`docs/【编辑器】画板角色形象生成入口设计-2026-06-15.md`、`docs/【编辑器】画板图标素材生成入口设计-2026-06-15.md`、`docs/【编辑器】图片画布结构化持久化与迁移回滚方案-2026-07-19.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。
|
||||
|
||||
## 2026-08-15 AGC game-chat 主代码 Run 接管直属美术 delivery
|
||||
|
||||
- 背景:真实 `gpt-5.6-sol / max` 验收中,`art-director` 失败后已形成 `ready + needs-repair` delivery,但认领、合同读取、claim observation 和完成 blocker 均硬编码为 Supervisor-only;实际直属父 Run `code-prototype` 无法消费回执,随后又发起 29 次 Provider 请求。
|
||||
|
||||
@@ -536,15 +536,6 @@ H5 支付链接跳转在原生壳声明 `app.openExternalUrl` 时必须优先走
|
||||
该命令同时会运行微信小程序 `miniprogram/host-bridge/`、`miniprogram/shell/`、`pages/web-view` 样式和 `scripts/miniprogram-web-view-auth.test.ts` 的壳层测试,保证微信桥接层拆分后的支付、订阅消息、九宫切图、分享目标和 WebView 登录 / 分享入口行为与 Expo、Tauri 壳一起验收。
|
||||
该命令还会反查微信小程序 `app.json.pages` 与 `host-bridge/protocol.js` 现役页面 URL、H5 小程序页面常量、WebView 分享入口、分享目标消息类型、`WEB_VIEW_SOURCE_QUERY`、微信请求头运行时标记、H5 runtime parser、H5 路由保留字段和 H5 / API base URL 格式,避免页面路由、来源标记、宿主上下文 query 或域名配置在微信壳、H5 HostBridge 与运行时配置之间分叉。旧生成结果订阅授权页和对应 H5 service 不再进入清单。生产 / 开发 H5 与 API 域名都必须显式配置为纯 HTTPS domain,运行时开发域名回退生产域名只作为异常兜底。
|
||||
|
||||
内容检查:
|
||||
|
||||
```bash
|
||||
npm run check:data
|
||||
npm run check:overrides
|
||||
npm run check:smoke
|
||||
npm run check:content
|
||||
```
|
||||
|
||||
全量检查:
|
||||
|
||||
```bash
|
||||
@@ -559,18 +550,12 @@ npm run check:server-rs-ddd
|
||||
|
||||
## Gitea CI 与 PR 检查
|
||||
|
||||
- 仓库 CI 入口是 `.gitea/workflows/project-ci.yml`,向 `master`、`codex/ai-game-creator-app` 推送和所有 PR 创建、更新时必须运行,也允许手工触发。
|
||||
- 仓库 CI 入口是 `.gitea/workflows/project-ci.yml`,在 `master` push、所有 PR 创建或更新以及手工触发时运行。
|
||||
- CI 固定拆分为 `Repository checks`、`Frontend tests`、`Backend tests`、`Native shell tests` 四个 required job;对应 PR context 完整名称是 `Project CI / Repository checks (pull_request)`、`Project CI / Frontend tests (pull_request)`、`Project CI / Backend tests (pull_request)`、`Project CI / Native shell tests (pull_request)`,首次运行后仍须从 Gitea 最近一周 context 表复核。测试使用独立 job,不能只藏在综合检查 step 中;原生壳验收单独运行以便定位重型构建失败。
|
||||
- 四个 job 共同覆盖 `npm run check`,并追加 `npm run check:server-rs-ddd`、`cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml` 和 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`。Backend job 必须先用 `cargo fetch --locked` 的 5 次整命令级有界重试准备当前 `server-rs` 锁定依赖,再进入会触发 `cargo build` 的 DDD / module-runtime 产物边界门禁;不得把依赖准备放在该门禁之后,否则镜像缺少锁新增 crate 时会在首次 registry / TLS 抖动处提前失败。后端 runner 安装 `ffmpeg`,避免视频抽帧测试因工具缺失提前返回。`codex/ai-game-creator-app` 分支必须用独立 lockfile 安装 AI 游戏创作壳依赖,其原生壳入口还必须覆盖 `npm run ai-game-creator-shell:check`、release build smoke,并检查 AI Tauri `Cargo.lock` 不漂移。原生壳 job 还要通过 Google 官方签名 APT 源安装 `google-chrome-stable`,用于 headless preview 的真实 DOM / canvas smoke;同时安装 `ripgrep`,把 `actions/setup-node` 的完整 Node.js 22 发行目录与 root-owned rustup proxy 映射到 `/usr/local`,供只接受受信任系统命令目录的 `command.exec` 沙箱测试使用,不能放宽生产命令目录白名单。Tauri 的 1132 项级别 suite 固定 `--test-threads=1`,避免共享 Agent Runtime 后台锁与异步终态在 libtest 并行调度下互相干扰。
|
||||
- 四个 job 共同覆盖根检查、前端与脚本测试、生产运维 fixture、server-rs DDD/workspace 测试和原生壳验收;AI 游戏创作壳检查与 release build smoke 对所有触发方式一致执行。
|
||||
- checkout 必须使用完整历史。PR 将 base SHA 写入 `SPACETIME_SCHEMA_BASE_REF`,直接推送 `master` 使用 before SHA;事件基线不可解析时直接失败。Gitea 检查的是 PR head 而非预合并 commit,workflow 必须拒绝不包含最新 base commit 的过期 PR,分支保护同时保持“PR 过期禁止合并”。
|
||||
- 普通 PR job 不读取业务 secret,不运行真实 API/SpacetimeDB/OSS/支付/生成/live smoke,也不执行会修改外部状态的维护、迁移、发布或备份命令。
|
||||
- Gitea 至少升级到 `1.26.4` 后才能注册执行 PR job 的 runner;`ubuntu-latest` 标签只映射到固定 digest 的 Ubuntu 24.04 级 Docker/临时隔离镜像,不使用浮动镜像 tag,不映射 host,不向 job 暴露 Docker socket、业务 secret 或不必要内网。runner 能访问 Gitea、GitHub Actions 与 `actions/node-versions`、nodejs.org、npm、Rust 分发、crates.io 和 Google Chrome 的 `dl.google.com` 官方签名 APT 源;workflow 的官方 action 固定完整 commit,若内网禁用 GitHub,先在当前 Gitea 镜像对应 commit 并改用绝对 URL。受控镜像优先预装 rustup。Gitea 1.26 的任务超时由 runner 全局配置控制;首次运行成功后,`master` 分支保护必须要求上述四个 job 全部成功。
|
||||
- `genarrative-station` 当前使用 Gitea `1.26.4` + 基于 Runner `2.0.0-dind-rootless` 的固定 digest 修补镜像:只修复 `systempaths=unconfined` 的空 slice 被 `mergo` 丢失,真实 job 必须保持 `MaskedPaths=[]`、`ReadonlyPaths=[]`;外层仍非 privileged、无 `CAP_SYS_ADMIN`,内部 Docker 只监听 Unix socket,`docker_host: "-"` 阻止 socket 进入 job。job 只在 `gitea-actions` internal network,通过 `/git` reverse gateway 访问 Gitea,通过拒绝私网、保留地址和 metadata 的 80/443 proxy 访问公共依赖;直连公网和 Gitea 数据网必须失败。内层 bwrap 所需 namespace/proc 选项只能用于该 rootless DinD,不能放宽宿主 rootful runner。系统依赖步骤在 root job 中不调用 sudo,非 root 时用 `sudo -E` 保留受控 proxy;Cargo 关闭 HTTP multiplexing 并设置 10 次网络重试,rustup bootstrap/toolchain 安装也按有界次数重试。AI 原生壳 job 把 Node 发行目录与 rustup proxy 安装到 `/usr/local` 的受信任只读路径,并在测试前执行完整 bwrap canary。宿主 compose helper 必须把 `/opt/gitea-stack` 挂到同名绝对路径,避免相对 volume 错误落到 `/stack` 空目录。
|
||||
- 四个 job 共同覆盖 `npm run check`,并追加 `npm run bgfilter-worker:smoke-test`、`npm run check:production-health-patrol`、`npm run check:production-api-release`、`npm run check:production-api-deploy`、`npm run check:server-rs-ddd`、`cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml` 和 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`。BgFilter 的 `.test.mjs` 使用 Node test runner,必须由 workflow 显式调用;生产巡检 / 发布 / 部署行为检查只运行无密钥临时 fixture,不连接现场环境。`ffmpeg` 由预构建 job 镜像提供,避免视频抽帧测试因工具缺失提前返回。`codex/ai-game-creator-app` 分支的原生壳入口还必须覆盖 `npm run ai-game-creator-shell:check` 和 release build smoke。
|
||||
- checkout 必须使用完整历史。PR 将 base SHA 写入 `SPACETIME_SCHEMA_BASE_REF`,直接推送 `master` 使用 before SHA;事件基线不可解析时直接失败。Gitea 检查的是 PR head 而非预合并 commit,workflow 必须拒绝不包含最新 base commit 的过期 PR,分支保护同时保持“PR 过期禁止合并”。
|
||||
- 普通 PR job 不读取业务 secret,不运行真实 API/SpacetimeDB/OSS/支付/生成/live smoke,也不执行会修改外部状态的维护、迁移、发布或备份命令。
|
||||
- Gitea 至少升级到 `1.26.4` 后才能注册执行 PR job 的 runner。runner 保留 `ubuntu-latest` 固定 digest 映射,并把 workflow 使用的 `genarrative-ci` 映射到 runner 内层 Docker 已装入的完整 Image ID;不映射 host,不向 job 暴露 Docker socket、业务 secret 或不必要内网。当前 CI 镜像约 `1.788 GB`,Image ID 为 `sha256:c04b114b1f145072c9df7842c4c974e1bb2eaaf391d95d84c9212a460546b7d5`,标签映射为 `genarrative-ci:docker://sha256:c04b114b1f145072c9df7842c4c974e1bb2eaaf391d95d84c9212a460546b7d5`。内层 Docker 数据持久化且 `force_pull: false`,该 ID 缺失时失败关闭,不现场拉取或回退浮动 tag。Runner 2.0.0 支持 job 级 `timeout-minutes`,但 runner 全局 `3h` 仍是硬上限;首次运行成功后,`master` 分支保护必须要求上述四个 job 全部成功。
|
||||
- `deploy/container/gitea-ci-job.Dockerfile` 固定 Ubuntu base digest `sha256:58ea92624c7c09582e05594d95488331045053d3a3f34cf09649f2a32313a614`、Rust stage digest `sha256:19817ead3289c8c631c73df281e18b59b172f6a31f4f563290f69cddd06c30e9`、带 SHA-256 校验的 Node `22.23.1`、Google Linux 主签名指纹和 Chrome `150.0.7871.181-1`,预装 Rust 1.96、`rustfmt`、Chrome、`bwrap`、`rg`、`ffmpeg`、`clang/lld` 与 Tauri / 后端系统依赖,并预热根 npm、server-rs 与桌面壳 Cargo 下载缓存。构建脚本使用约 `1.638 MB` 的白名单 tar context,不发送源码、素材或本地私密文件;`cargo fetch --locked` 同时受 Cargo 网络重试和最多 5 次整命令级重试保护,最后必须通过断网 fetch。更新按 `scripts/gitea-ci-job-image.sh build/verify -> export 仓库外镜像归档 -> load-runner -> 确认无活跃 job -> 仓库外备份 config -> 替换 label -> docker restart --timeout 660` 执行;真实 CI 全部通过后才清旧镜像。回滚先把 workflow 改回 `ubuntu-latest`,再恢复 config 备份并重启。备份不进 Git,不在共享文档记录宿主私密路径或注册信息。
|
||||
- runner、隔离镜像、工具链和网络边界的当前配置以 `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md` 为准,不在共享记忆中复制易漂移的镜像大小、Image ID 或安装步骤。
|
||||
- 四个 workflow job 都使用 `runs-on: genarrative-ci`,先用镜像内脚本直接从 Gitea checkout,再以 `GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1` 运行 `scripts/check-gitea-ci-job-image.sh`,同时校验缓存锁、工具链、完整 bwrap sandbox 和 Chrome headless。workflow 不再包含 GitHub checkout action、apt、setup-node 或 rustup 安装,并设置 `RUSTUP_AUTO_INSTALL=0`;工具链变更时先重建镜像。每个 job 仍各自执行 `npm ci` 以校验 lockfile 和隔离 PR 依赖,但优先复用镜像只读 cache,不烘入 `node_modules`,不挂载跨 PR 可写 Actions cache。`genarrative-station` 继续使用固定 digest 的 Runner `2.0.0-dind-rootless` 修补镜像,真实 job 保持 `MaskedPaths=[]`、`ReadonlyPaths=[]`、`Privileged=false`、`Binds=[]`,`docker_host: "-"` 阻止 socket 进入 job。job 只在 `gitea-actions` internal network,锁文件差量依赖只经拒绝私网、保留地址和 metadata 的 80/443 proxy,直连公网和 Gitea 数据网必须失败;npm 与 Cargo 都设置 10 次网络重试,Cargo 继续关闭 HTTP multiplexing。
|
||||
|
||||
## 后端相关默认验证
|
||||
|
||||
@@ -749,12 +749,12 @@
|
||||
- 验证:`npm run test -- src/components/image-editor/ImageCanvasEditorModel.test.ts src/components/image-editor/ImageCanvasInteractionModel.test.ts`,并在多素材画布拖拽时确认参考线仍能命中邻近图层且 pointermove 不再明显掉帧。
|
||||
- 关联:`src/components/image-editor/ImageCanvasEditorModel.ts`、`src/components/image-editor/ImageCanvasInteractionModel.ts`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
|
||||
|
||||
## 图片画布视口拖动卡顿先查自动保存和小地图合帧
|
||||
## 图片画布拖动卡顿先查 Stage 合帧和交互期自动保存
|
||||
|
||||
- 现象:素材多或序列帧多时,拖动小地图视口框或手型平移明显卡顿,像是接口慢或 CSS 动画掉帧,但网络请求不一定异常。
|
||||
- 原因:`pointermove` 高频修改 `viewport` 会触发画布重渲染、小地图模型重算和工程持久化 effect;持久化链路会同步 `serializeCanvasLayout`、`JSON.stringify` 并写 sessionStorage。远端 PATCH 有防抖也挡不住本地同步缓存写入。
|
||||
- 处理:把 viewport 拖动标记为临时交互;拖动中只更新画布显示,不触发项目保存、session cache 写入或封面快照上传,`pointerup` / `pointercancel` 后保存最终 viewport。小地图拖动的 `updateViewportFromMinimapDrag` 必须用 `requestAnimationFrame` 合帧,结束拖拽时 flush 最后一帧。
|
||||
- 验证:`npm run test -- src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx --reporter verbose` 应覆盖小地图拖动合帧、平移 / 小地图 viewport 交互边界,以及拖动期间不写 sessionStorage / 不调用 `saveEditorProjectLayout`。
|
||||
- 现象:素材多或序列帧多时,拖动图层、生成占位、小地图视口框或手型平移明显卡顿,像是接口慢或 CSS 动画掉帧,但网络请求不一定异常。
|
||||
- 原因:高刷新率输入设备会在单个屏幕帧内发出多次 `pointermove`;每次直接 `setLayers` / `setViewport` 都会触发画布重渲染、吸附或小地图模型重算和工程持久化 effect。即使 `moveLayersFromDrag` 保留未移动图层的对象引用,若 WorldView 仍在每帧重建全部图层子树,所有真实位图的 URL hook、加载态、标签和 SVG 操作也会重复执行。持久化链路还会同步 `serializeCanvasLayout`、`JSON.stringify` 并写 sessionStorage,远端 PATCH 有防抖也挡不住本地同步缓存写入。
|
||||
- 处理:Stage 的图层、生成占位、框选和手型平移统一用单一在途 `requestAnimationFrame` 合并同帧输入,只应用最新坐标;结束拖拽时 flush 最后一帧,主动清理和卸载时 cancel。图层、生成占位、平移和小地图拖动一旦越过拖动阈值就标记为临时交互,拖动中不触发项目保存、session cache 写入或封面快照上传,`pointerup` / `pointercancel` 后保存最终布局。WorldView 的完整单图层节点必须按稳定 layer 对象浅比较 memo,父回调通过 latest ref 的稳定门面转发,避免未移动图层重渲染或读取陈旧闭包。小地图继续只在 viewport controls 内合帧,不要重复套 rAF。
|
||||
- 验证:`npm run test -- src/components/image-editor/ImageCanvasWorldView.test.tsx src/components/image-editor/useImageCanvasViewportControls.test.tsx src/components/image-editor/useImageCanvasStageInteractions.test.tsx src/components/image-editor/useImageCanvasProjectPersistence.test.tsx --reporter verbose` 应覆盖只重渲染移动图层、稳定节点调用最新回调、同帧只保留最新坐标、结束前 flush、卸载 cancel、小地图无双重合帧、图层 / 生成占位 / 平移 / 小地图交互边界,以及拖动期间不写 sessionStorage / 不调用 `saveEditorProjectLayout`。浏览器验收必须使用多个独立 raster URL,并区分 rAF 心跳与目标实际位置变化帧;共享 data URI SVG 和包含空闲尾帧的自由 rAF 不能作为拖动流畅证据。
|
||||
- 关联:`src/components/image-editor/useImageCanvasViewportControls.ts`、`src/components/image-editor/useImageCanvasStageInteractions.ts`、`src/components/image-editor/useImageCanvasProjectPersistence.ts`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
|
||||
|
||||
## 图片编辑器宣发素材生成器刷新后不要丢快照
|
||||
@@ -4298,6 +4298,27 @@
|
||||
- 处理:CONNECT 一开始就为 client socket 注册 `error / close`,解析完成后为 upstream socket注册同样的双向销毁处理;DNS 返回、写 200 和开始 pipe 前都检查 client 是否已销毁。任一端 error、close 或 timeout 都幂等 destroy 两端,不把普通客户端 reset 写成错误日志。不要用进程级 `uncaughtException` 吞掉问题,也不要只增加 npm/Cargo 重试掩盖 gateway 崩溃。
|
||||
- 验证:在独立 canary 和正式 gateway 上分别并发制造至少 500 次“CONNECT 后立即断开”,随后确认容器仍运行、restart count 不增加、日志无 EPIPE;再通过同一 proxy 对 npm registry 与 crates index 建立完整 TLS 隧道。切换前仍须确认 Gitea 无活跃 run 且 Runner 内层无 job 容器。
|
||||
|
||||
## 独立 AGC lockfile 不能丢失可选 WASM 包的 bundled 依赖节点(2026-08-21)
|
||||
|
||||
- 现象:`npm ci --prefix apps/ai-game-creator-shell` 在安装前失败,报告 lockfile 缺少 `@emnapi/core` / `@emnapi/runtime`;错误版本可能是 registry 当前满足 `^1.11.1` 的最新版,而不是原 lock 中曾记录的版本。
|
||||
- 原因:重写或解决 `apps/ai-game-creator-shell/package-lock.json` 冲突时,保留了 `@tailwindcss/oxide-wasm32-wasi` 对 bundled `@emnapi` 包的声明,却删掉了对应嵌套 package 节点。npm 会重新解析当前 registry 版本并判定 manifest 与 lock 不同步;这不是单一 npm 版本问题,也不表示应用应直接依赖两个 `@emnapi` 包。
|
||||
- 处理:只在最新目标分支执行 `npm install --package-lock-only --ignore-scripts --prefix apps/ai-game-creator-shell`,保留 npm 对 bundled 节点及 `peer` / `optional` 标记的完整规范化结果;确认子包 `package.json` 没有变化,不要手工只补报错中的两个版本。
|
||||
- 验证:至少用 Jenkins 对应 npm major 和当前开发 npm 分别执行干净的 `npm ci --prefix apps/ai-game-creator-shell`,再运行 AGC typecheck、编码检查和 `git diff --check`;根目录 `npm ci` 不能替代独立子包 lock 验证。
|
||||
|
||||
## Windows 专属 Tauri resource 不能写进通用配置(2026-08-21)
|
||||
|
||||
- 现象:Linux CI 已完成 AGC `npm ci`,却在 Tauri custom build command 中报 `resources/codex/win-x64/...exe doesn't exist`;Windows 侧车的 Rust staging 受 `cfg(windows)` 保护,因此非 Windows 构建不会生成这些文件。
|
||||
- 原因:Tauri 会在所有平台校验通用 `tauri.conf.json` 的 bundle resource 源路径;把 Windows x64 资源映射写进通用配置,等于要求 Linux / macOS 也预先拥有不属于其安装闭包的 Windows 可执行文件。
|
||||
- 处理:通用配置只保留跨平台 bundle 项;Windows 原生侧车的完整白名单放入 Tauri 自动合并的 `tauri.windows.conf.json`。不要提交二进制占位文件,也不要让非 Windows build script 下载或伪造 Windows 资源。
|
||||
- 验证:配置门禁断言通用配置没有 Windows resource、Windows 平台配置保留完整固定白名单;Linux 运行原生壳门禁必须越过 Tauri resource 校验,Windows release 仍由 build script 对 npm 原生包、SHA-256 清单和目标布局失败关闭。
|
||||
|
||||
## AGC Skill 指纹与相对路径校验必须跨平台一致(2026-08-21)
|
||||
|
||||
- 现象:内置 Skill 文件集合没有缺失,原生测试却统一报内容指纹不匹配;另一个测试在 Linux 上把 `C:\\temp\\SKILL.md` 判为安全相对路径,受控资源工具可能继续处理 Windows 盘符或反斜杠遍历形式。
|
||||
- 原因:审核文件定稿后未按最终字节重新生成 manifest SHA-256;同时 `std::path::Path` 只按当前宿主语义解析路径,Linux 不会把 Windows 盘符和反斜杠视为绝对路径或分隔符。
|
||||
- 处理:Skill 文件变化与 manifest 指纹更新必须同次提交,并提升审核包版本;资源引用只接受使用 `/` 的普通相对段,显式拒绝反斜杠、冒号盘符、UNC、绝对路径和父目录段,再查询审核清单。不要先把反斜杠替换成 `/` 后再做安全检查。
|
||||
- 验证:逐项按排序后的 `relativePath + NUL + file bytes + NUL` 重算并核对 manifest;Rust 单测同时覆盖 POSIX 绝对路径、`..`、`C:\\...`、`C:/...`、UNC 和反斜杠相对路径,受控 MCP 工具也必须把 Windows 绝对路径投影为 `isError=true`。
|
||||
|
||||
## Gitea CI 预构建镜像不能只靠 tag 判断内容
|
||||
|
||||
- 现象:宿主已重建带日期修订 tag 的 `genarrative/gitea-project-ci` 镜像,但 `genarrative-ci` job 仍跑旧内容,或直接报 image not found;另一种危险操作是只改 runner label,没把对应镜像装入 rootless runner 的内层 Docker。
|
||||
@@ -4787,8 +4808,8 @@
|
||||
|
||||
- 现象:像素规整后的图片虽然保持了源图宽高,放大观察却能看到相邻逻辑块占用的物理列数或行数不同,表现为部分块更宽、部分块更窄;整数倍样例看起来正常,换一张网格数不能整除输入尺寸的图才复现。
|
||||
- 原因:逻辑图宽高为检测后的列数、行数。把 `C × R` 的逻辑图用 nearest 恢复到 `W × H` 时,只要 `W % C != 0` 或 `H % R != 0`,目标栅格就只能在不同逻辑像素间分配 `floor / ceil` 数量的列或行;nearest 能避免混色,却不能让非整数缩放后的块严格等大。只用 `128 × 128 → 64 × 64 → 128 × 128` 这类整数倍测试会掩盖问题。
|
||||
- 处理:最终资产直接编码一格一像素的逻辑分辨率 PNG,不再执行输入 / 交付尺寸 nearest 恢复,也不要求成功输出与源图或占位尺寸相等。普通图片和角色的前置 Lanczos 交付尺寸归一仍用于确定检测输入;平底网格源与透明 RGBA 源仍必须同尺寸,不能把“取消输出同尺寸”误解为放开两个内部采样坐标系。
|
||||
- 验证:使用至少一组逻辑列数或行数不能整除输入尺寸的图片,断言输出宽高等于切线数减一而不是输入宽高;同时核对响应、project resource、账号素材和结果 layer 都记录最终 PNG 实际尺寸,且只持久化一个最终 PNG,没有输入尺寸恢复版、诊断图或额外资源。失败降级用例继续验证 Alpha / 交付尺寸守卫,不应因成功输出改为逻辑分辨率而删除。
|
||||
- 处理:采样仍是一格一像素;编码前只允许横纵同一整数 N 的 nearest 放大,N 取最接近规整输入尺寸的正整数,禁止非整数拉回精确 `W × H`。成品宽高比等于逻辑图,尺寸接近但不保证等于源图或占位。普通图片和角色的前置 Lanczos 交付尺寸归一仍用于确定检测输入;平底网格源与透明 RGBA 源仍必须同尺寸。
|
||||
- 验证:整数倍样例与非整除样例都不得出现宽窄不一的逻辑块;响应、project resource、账号素材和结果 layer 都记录最终 PNG 实际尺寸,且只持久化一个最终 PNG,没有未放大逻辑图、输入尺寸恢复版、诊断图或额外资源。失败降级用例继续验证 Alpha / 交付尺寸守卫。
|
||||
- 关联:`server-rs/crates/platform-image/src/pixel_art_snapper.rs`、`server-rs/crates/api-server/src/editor_project.rs`、`docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`。
|
||||
|
||||
## Codex CLI 节点不能把进程终态当成 Runtime 提交证据(2026-08-10)
|
||||
@@ -4864,3 +4885,17 @@
|
||||
- 原因:测试代码仅为动态生成 RSA fixture 引入 `openssl` dev-dependency,从而把原本使用纯 Rust 加密实现的 crate 额外绑定到本机原生 OpenSSL 工具链;Strawberry 附带的库面向 MinGW,不等于可用的 MSVC OpenSSL SDK。
|
||||
- 处理:测试优先使用明确标记、只供测试的固定 PEM fixture,并继续通过项目自身的密钥解析与签名验证路径覆盖真实行为;不要仅为生成 fixture 引入系统原生库,也不要把 MinGW OpenSSL 路径写入 `OPENSSL_DIR` 冒充 MSVC 依赖。
|
||||
- 验证:运行目标 crate 的 `cargo tree -i openssl-sys --target all` 确认依赖已退出,再执行包含测试目标的 `cargo test --tests`,不能只用不会编译 dev-dependency 的 `cargo check --lib` 代替。
|
||||
|
||||
## 隔离 Codex app-server 会误吃代理的 ChatGPT 额度头(2026-08-20)
|
||||
|
||||
- 现象:同一自定义 Responses endpoint 和 API Key 直接 HTTP 为 200,普通用户 HOME 下的 smoke 也完成,但隔离 `CODEX_HOME/HOME` 的 app-server 在真正发请求前返回 `usageLimitExceeded`,并投影 credits balance 0。
|
||||
- 原因:开发网关把 `X-Codex-*` ChatGPT 账户额度头附在 API Key Provider 响应上;隔离进程没有用户 ChatGPT 额度状态覆盖,Codex 0.147 将这些头当作本地账户限制。模型、Key、MCP 和 Skill 均不是根因。
|
||||
- 处理:只为 Direct conversation 启动随机 loopback `/responses` 流式代理;它不注入 Authorization,只转发请求自带 Bearer,拒绝其它方法/路径并剥离 `X-Codex-*` 账户头。不要复制用户 `auth.json` 来掩盖问题,也不要把 Provider 切换当根因修复。
|
||||
- 验证:同时记录上游直接 200、未过滤时 credits=0/usage-limit、过滤后真实 turn completed;代理测试必须证明无 Bearer 拒绝、路径收窄、正文流式保留和额度头不下传。
|
||||
|
||||
## Codex MCP 子进程不适合直接启动桌面浏览器(2026-08-20)
|
||||
|
||||
- 现象:同一 `agc_browser_playtest` 在普通进程中能返回双视口截图,但从 Codex 启动的 STDIO MCP 子进程调用时 Chrome 启动超时。
|
||||
- 原因:MCP 子进程继承隔离 HOME/AppData 和 Codex 进程约束;把真实浏览器或 GUI 登录态硬塞给子进程既不稳定,也扩大凭据边界。
|
||||
- 处理:STDIO MCP 只做 schema 与协议适配;浏览器和付费美术通过随机 loopback 工具桥回到持有项目、登录态和正常桌面环境的客户端主进程。桥只绑定当前项目、限制请求大小和审核工具名,返回脱敏文本与有界 PNG。
|
||||
- 验证:必须从真实 Codex thread 发起 MCP 调用并观察 desktop/mobile `readyState=complete` 与两张截图;直接运行 MCP 二进制成功不能替代该链路。
|
||||
|
||||
Reference in New Issue
Block a user