From 8e304f2b2212ce38dccb780f96b94e21d2c32d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sun, 4 Oct 2026 13:38:51 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=9ACI=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=9B=BA=E5=AE=9A=20`silent:=20true`=EF=BC=8C?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E9=9D=99=E9=BB=98=E6=88=90=E5=8A=9F=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/project-memory/shared-memory/decision-log.md | 8 ++++++++ .../shared-memory/development-workflow.md | 3 +++ scripts/project-ci-workflow.test.ts | 10 ++++++++++ vitest.config.ts | 4 ++++ 4 files changed, 25 insertions(+) diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index bf30e4c85..6a39012a7 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -1,5 +1,13 @@ # 决策记录 +## 2026-10-04 CI 测试成功时静默(silent is gold) + +- 背景:`Frontend tests` 的 `npm run test:ci:frontend` 在成功 run 里仍回放被测代码的 console 输出——React `act(...)` 警告、`scripts/dev.test.ts` / `scripts/dev-all.test.ts` 的开发栈调度日志——把 CI 日志刷出大量与「红灯」无关的内容。 +- 决策:根 `vitest.config.ts` 固定 `test.silent: true`(`--silent` 的配置形态)。成功用例不再回放写进 stdout / stderr 的内容;reporter 仍输出每个文件一行进度与最终汇总,失败用例仍打印断言摘要与源码位置。`vitest.frontend-ci.config.ts` 通过 `mergeConfig` 继承该设置,AGC 与 repository checks 直接使用的根配置同样生效。本机排查用 `vitest run --silent=false` 覆盖。 +- 守护:`scripts/project-ci-workflow.test.ts` 新增用例钉住根配置的 `silent: true`,防止日后被顺手删掉。 +- 影响范围:`vitest.config.ts`、`scripts/project-ci-workflow.test.ts`、`docs/project-memory/shared-memory/development-workflow.md`、本文件。 +- 验证:`npx vitest run --config vitest.frontend-ci.config.ts`(243 files / 2761 passed,输出中 `stdout |` / `stderr |` 块与 `act(...)` 警告均为 0);定向 `scripts/{project-ci-workflow,dev,dev-all,dev-utils}.test.ts`(4 files / 114 passed);临时失败用例确认失败摘要仍打印;`--silent=false` 可恢复 console 输出;`git diff --check`、prettier、eslint `--max-warnings 0`(改动文件)通过。 + ## 2026-10-03 AGC 画布引用统一走「活跃聊天输入区」注册表(Issue 602) - 背景:画布的「引用」按钮与「拖拽批量引用」只派发 window 事件,消费者只有 `App.tsx` 一处,而它插的是绑在 `PlanningChatView` 上的 `chatComposerRef`;2026-09-22 DirectProject 拆分后普通项目走 `directProjectMode` 提前 return,渲染不到策划面 → ref 恒为 `null`,可选链静默吞掉点击(画布上是死按钮)。同一批合并冲突还丢了 `RESOURCE_REFERENCE_INSERT_MANY_EVENT` 的监听,批量引用连消费者都没有。 diff --git a/docs/project-memory/shared-memory/development-workflow.md b/docs/project-memory/shared-memory/development-workflow.md index c4e72194e..f241edbfd 100644 --- a/docs/project-memory/shared-memory/development-workflow.md +++ b/docs/project-memory/shared-memory/development-workflow.md @@ -120,6 +120,9 @@ AGC Rust 两条 lane、crates、smoke、Backend 和桌面壳测试使用镜像 `.gitea/workflows/project-ci.yml` 的客户端门禁拆成 lane 与功能 job,每个 job 只预热自己会构建的那几份依赖:`AI game creator shell Rust lane 1/2`、`lane 2/2` 各自预取一次 AGC 壳 manifest,并顺序运行两片 Rust bin 单测;`AI game creator shell Rust smoke` 同样只预取 AGC 壳 manifest(`agent-run` smoke 会用 `src-tauri/Cargo.toml` spawn `cargo run`),`AI game creator shell Rust crates` 预取 `server-rs/Cargo.toml` 与独立 crate,`Native shell tests` 预取桌面壳与 AGC 壳 manifest,`AI game creator shell web tests` 不触碰 Cargo,不预热。两条 Rust lane 与 smoke job 必须在编译前通过 `scripts/ci-npm-ci-with-retry.sh` 执行根 `npm ci`:AGC 壳的 `build.rs` 会从 `node_modules` 准备 Claude Agent SDK 与目标平台原生运行时,镜像中的 npm 下载缓存不能替代安装。人工 `scripts/build-gitea-rust-cache.sh` bootstrap 同样在首次编译 AGC 壳前安装 npm 依赖;只有不构建壳的 crates job 继续省略 npm 安装。两个被 `server-rs/Cargo.toml` 排除、且没有提交 `Cargo.lock` 的独立 crate(`agent-runtime-core`、`agent-runtime-orchestration`)只能在 `AI game creator shell Rust crates` 里用不带锁标志的 fetch。AGC 壳的 bin target 单测(约 2466 条)由 `apps/ai-game-creator-shell/scripts/run-rust-shell-test-shards.mjs` 编译后按 `--list` 名单分 4 片:每次分片调用用 `--shard-index=` 只跑自己那片,片内保持 `--test-threads=1` 并使用独立 `TMPDIR`;两条 lane 之间并发,lane 内顺序运行两片,避免重复依赖预热和同一容器内多进程争抢。不要改回「一个 job 内多进程并行这几片」——同一容器里它们会争抢共享 `HOME`、target 目录与固定临时路径,实测比整套串行还慢。每个分片调用都会自校验「片并集等于全集且互斥」,因此改分片规则不会静默漏跑。Backend host workspace tests 使用 `cargo test --locked --workspace --exclude spacetime-module --no-fail-fast`,避免 `spacetime-module` 的 `spacetime-types` feature 统一污染普通领域 crate 的 host 测试;随后单独执行 `cargo test --locked -p spacetime-module --no-fail-fast`,由 `spacetime-module/src/active.rs` 在 host 测试构建期间提供仅测试期的 SpacetimeDB ABI 链接支持,使该 crate 的纯单元测试也纳入 Backend 门禁。`spacetime-module` 的 reducer / procedure 运行时行为仍必须通过真实 SpacetimeDB runtime/integration harness 验证,host 链接支持不得被当作运行时替身。Backend 另外执行 `cargo check --locked -p spacetime-module` 验证模块源码。AGC 壳检查还会运行 `platform-llm` 与 `shared-contracts` 的 server-rs workspace 测试,这些命令以及 AGC 壳测试必须带 `--locked`,避免在测试阶段重新解析 registry index;锁文件发生变化时应先更新受信任 CI 镜像缓存,再重跑门禁。 +根 `vitest.config.ts` 固定 `test.silent: true`(`--silent` 的配置形态,silent is gold):成功用例不回放被测代码写进 stdout / stderr 的内容(React `act(...)` 警告、`scripts/dev*.test.ts` 的 dev 调度日志等),CI 日志只保留每个文件一行进度、最终汇总与失败用例的断言摘要加源码位置。`vitest.frontend-ci.config.ts` 通过 `mergeConfig` 继承该设置,AGC 与 repository checks 直接使用的根配置同样生效——所以不要改成只对某一个配置生效,那会让另一条 CI 测试重新刷屏。本机排查需要完整 console 输出时用 `vitest run --silent=false` 覆盖,不要改回 `silent: false`。`scripts/project-ci-workflow.test.ts` 有守护用例钉住这条口径。 + + ## AGC 测试类型门禁 AGC 测试(`apps/ai-game-creator-shell/tests/`)与生产 `src/` 同受类型门禁。`apps/ai-game-creator-shell/tsconfig.tests.json` 以 `include: ["src", "tests", "vite.config.ts"]`、`types: ["vite/client", "vitest/globals"]`、`allowImportingTsExtensions`、`allowJs` 全量覆盖:新增测试文件自动纳入,不存在基线、豁免名单或 `@ts-nocheck`。入口 `npm --prefix apps/ai-game-creator-shell run check:tests:types`(`tsc -p tsconfig.tests.json --noEmit`)已并入该 app 的 `typecheck`,因此 `npm run agc:typecheck`、`npm run ai-game-creator-shell:check:web` 与 CI 的 `AI game creator shell web tests` 都会执行。修测试只做类型层改动,不改断言与行为;禁止 `@ts-ignore`、`as any`,仅当 mock 泛型函数确实不可兼容时才允许带中文注释的 `as unknown as`。 diff --git a/scripts/project-ci-workflow.test.ts b/scripts/project-ci-workflow.test.ts index 015533b15..923c6a6ac 100644 --- a/scripts/project-ci-workflow.test.ts +++ b/scripts/project-ci-workflow.test.ts @@ -75,6 +75,12 @@ const jobsWithoutNpmInstall: readonly string[] = [ const rootPackageJson = JSON.parse( readFileSync(resolve(process.cwd(), 'package.json'), 'utf8'), ) as { scripts?: Record }; +// 前端与 AGC 的 CI 测试都跑根 vitest 配置(`vitest.frontend-ci.config.ts` 也 merge 它), +// 这里钉住「成功用例静默」,避免有人顺手删掉后 CI 日志重新被 act 警告与 dev 日志刷屏。 +const rootVitestConfig = readFileSync( + resolve(process.cwd(), 'vitest.config.ts'), + 'utf8', +); const nativeShellGateScript = readFileSync( resolve(process.cwd(), 'scripts/check-native-shells.mjs'), 'utf8', @@ -540,6 +546,10 @@ describe('project CI workflow', () => { ).toHaveLength(2); }); + it('keeps passing CI tests silent so only failures reach the log', () => { + expect(rootVitestConfig).toMatch(/^\s*silent:\s*true,$/mu); + }); + it('keeps frontend, operations fixture, and native shell gates in dedicated jobs', () => { const frontendJob = jobSection('frontend-tests'); expect(frontendJob).toMatch(/^ {8}run: npm run test:ci:frontend$/mu); diff --git a/vitest.config.ts b/vitest.config.ts index 2d66a04ff..6401f100f 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -94,6 +94,10 @@ export default defineConfig({ test: { environment: 'node', globals: true, + // 成功用例不回放被测代码写进 stdout / stderr 的内容:CI 日志里只保留每个 + // 失败用例的断言摘要,避免 React act 警告、dev 调度日志这类噪音刷屏。 + // 需要在本机排查时用 `vitest run --silent=false` 覆盖本次配置。 + silent: true, minThreads: 1, maxThreads: 8, server: { From a1b80ffde9eab7c75a32d327567504d9ebed070a Mon Sep 17 00:00:00 2001 From: lhk Date: Sun, 4 Oct 2026 07:47:13 +0100 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E8=AF=84=E4=BB=B7=E7=8A=B6=E6=80=81=E4=B8=8E?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=8C=89=E9=92=AE=E6=8D=A2=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为游戏评价列表增加专属表格样式类 状态胶囊保持单行,操作按钮禁止换行和压缩 同步后台评价列表布局规范 --- apps/admin-web/src/pages/AdminGameReviewsPage.tsx | 1 + apps/admin-web/src/styles/admin.css | 13 +++++++++++++ docs/【玩法创作】平台入口与玩法链路-2026-05-15.md | 1 + 3 files changed, 15 insertions(+) diff --git a/apps/admin-web/src/pages/AdminGameReviewsPage.tsx b/apps/admin-web/src/pages/AdminGameReviewsPage.tsx index a7ad0e543..52f59dda9 100644 --- a/apps/admin-web/src/pages/AdminGameReviewsPage.tsx +++ b/apps/admin-web/src/pages/AdminGameReviewsPage.tsx @@ -290,6 +290,7 @@ export function AdminGameReviewsPage({ token, onUnauthorized }: PageProps) { button { + flex-shrink: 0; +} + @media (max-width: 700px) { .admin-review-filters { grid-template-columns: minmax(0, 1fr); diff --git a/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md b/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md index f6263e3aa..8b602cf76 100644 --- a/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md +++ b/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md @@ -351,6 +351,7 @@ - 列表列为游戏名称/ID、评价用户昵称/ID、评分、评论摘要、状态、提交时间、修改时间和操作。空评论在后台显示“仅评分”;摘要最多 120 Unicode 码点,截断时加省略号。 - “查看详情”使用现有弹窗,展示完整纯文本评论、分数、游戏/用户/评价 ID、创建和修改时间,并展示该次评价的操作记录。名称与头像关联现有游戏/账号信息,不复制到评价表。 - 评价表格的评论与操作原因保留换行,清除单元格内段落的默认上下外边距,与其他列顶对齐。 +- 评价列表的状态胶囊保持单行;行内操作按钮不换行、不压缩,避免删除按钮另起一行撑高整条评价。样式仅作用于游戏评价列表,窄屏沿用表格容器横向滚动。 - 行内提供“隐藏”或“恢复”和“删除”。隐藏、删除通过原因输入及确认弹窗提交;原因 trim 后必须为 1–4000 Unicode 码点,不静默截断;恢复沿用现有后台确认交互。删除明确提示“删除后不可恢复,用户可以重新评价”。 - 请求期间禁用对应操作,失败保留原因草稿并显示错误,不先移除记录;成功刷新当前筛选。删除或状态过滤导致当前页越界时回到最后一页,零记录回第 1 页并显示空态。详情打开期间切换目标,不接受旧目标的迟到响应覆盖。 - 管理列表/详情不受游戏公开可见性限制。移动端表格横向滚动、弹窗内正文可滚动,操作按钮可达。 From 33552d2ed643871c08c2f5b401c4eef5895309cc Mon Sep 17 00:00:00 2001 From: lhk Date: Sun, 4 Oct 2026 07:52:24 +0100 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B8=B8=E6=88=8F?= =?UTF-8?q?=E8=AF=84=E4=BB=B7=E6=93=8D=E4=BD=9C=E5=88=97=E5=B7=A6=E5=AF=B9?= =?UTF-8?q?=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将评价列表操作按钮与操作列头左对齐 同步评价列表布局规范 --- apps/admin-web/src/styles/admin.css | 1 + docs/【玩法创作】平台入口与玩法链路-2026-05-15.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/admin-web/src/styles/admin.css b/apps/admin-web/src/styles/admin.css index 9ddd33170..1f8880d60 100644 --- a/apps/admin-web/src/styles/admin.css +++ b/apps/admin-web/src/styles/admin.css @@ -853,6 +853,7 @@ button:disabled { .admin-game-reviews-table td:last-child .admin-action-row { flex-wrap: nowrap; + justify-content: flex-start; } .admin-game-reviews-table td:last-child .admin-action-row > button { diff --git a/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md b/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md index 8b602cf76..c241dd71c 100644 --- a/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md +++ b/docs/【玩法创作】平台入口与玩法链路-2026-05-15.md @@ -351,7 +351,7 @@ - 列表列为游戏名称/ID、评价用户昵称/ID、评分、评论摘要、状态、提交时间、修改时间和操作。空评论在后台显示“仅评分”;摘要最多 120 Unicode 码点,截断时加省略号。 - “查看详情”使用现有弹窗,展示完整纯文本评论、分数、游戏/用户/评价 ID、创建和修改时间,并展示该次评价的操作记录。名称与头像关联现有游戏/账号信息,不复制到评价表。 - 评价表格的评论与操作原因保留换行,清除单元格内段落的默认上下外边距,与其他列顶对齐。 -- 评价列表的状态胶囊保持单行;行内操作按钮不换行、不压缩,避免删除按钮另起一行撑高整条评价。样式仅作用于游戏评价列表,窄屏沿用表格容器横向滚动。 +- 评价列表的状态胶囊保持单行;行内操作按钮与“操作”列头左对齐,不换行、不压缩,避免删除按钮另起一行撑高整条评价。样式仅作用于游戏评价列表,窄屏沿用表格容器横向滚动。 - 行内提供“隐藏”或“恢复”和“删除”。隐藏、删除通过原因输入及确认弹窗提交;原因 trim 后必须为 1–4000 Unicode 码点,不静默截断;恢复沿用现有后台确认交互。删除明确提示“删除后不可恢复,用户可以重新评价”。 - 请求期间禁用对应操作,失败保留原因草稿并显示错误,不先移除记录;成功刷新当前筛选。删除或状态过滤导致当前页越界时回到最后一页,零记录回第 1 页并显示空态。详情打开期间切换目标,不接受旧目标的迟到响应覆盖。 - 管理列表/详情不受游戏公开可见性限制。移动端表格横向滚动、弹窗内正文可滚动,操作按钮可达。 From 84c30b680cb3bbd312047f09f4ea9681118a402f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sun, 4 Oct 2026 15:29:16 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=9ACI=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=88=90=E5=8A=9F=E9=9D=99=E9=BB=98=E6=94=B9=E7=94=A8?= =?UTF-8?q?=20cargo/node=20=E5=8E=9F=E7=94=9F=20quiet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .gitea/workflows/project-ci.yml:全局加 CARGO_TERM_QUIET=true,cargo test 成功只打点号、失败才列用例名。 - scripts/build-gitea-rust-cache.sh:预热脚本同步 CARGO_TERM_QUIET=true,与 workflow 的 Cargo 环境一致。 - package.json:agc:plugins:test 改用 node --test --test-reporter=dot。 - apps/ai-game-creator-shell/package.json:bundled-resources:test 改用 node --test --test-reporter=dot。 - scripts/check-native-shells.mjs:去掉每个 step 的成功进度标签,失败时才打印标签。 - scripts/project-ci-workflow.test.ts:移除 silent: true 守护用例。 - docs/project-memory/shared-memory/decision-log.md:移除本次静默决策条目。 - docs/project-memory/shared-memory/development-workflow.md:移除本次静默说明段落。 --- .gitea/workflows/project-ci.yml | 3 +++ apps/ai-game-creator-shell/package.json | 2 +- docs/project-memory/shared-memory/decision-log.md | 8 -------- .../shared-memory/development-workflow.md | 3 --- package.json | 2 +- scripts/build-gitea-rust-cache.sh | 2 +- scripts/check-native-shells.mjs | 5 ++++- scripts/project-ci-workflow.test.ts | 10 ---------- 8 files changed, 10 insertions(+), 25 deletions(-) diff --git a/.gitea/workflows/project-ci.yml b/.gitea/workflows/project-ci.yml index 5bde92df5..d56eba0f4 100644 --- a/.gitea/workflows/project-ci.yml +++ b/.gitea/workflows/project-ci.yml @@ -20,6 +20,9 @@ env: CARGO_HTTP_MULTIPLEXING: 'false' CARGO_NET_RETRY: '10' CARGO_TERM_COLOR: always + # 等价于给每条 `cargo test` 加 `-q`:通过的用例只打点号,失败的才按名字列出。 + # 对 npm 脚本、shard runner 里嵌套的 cargo 同样生效,避免逐条 `test ... ok` 刷屏。 + CARGO_TERM_QUIET: 'true' NPM_CONFIG_AUDIT: 'false' NPM_CONFIG_FETCH_RETRIES: '10' NPM_CONFIG_FETCH_RETRY_FACTOR: '2' diff --git a/apps/ai-game-creator-shell/package.json b/apps/ai-game-creator-shell/package.json index 0d3ec33c6..54a85623d 100644 --- a/apps/ai-game-creator-shell/package.json +++ b/apps/ai-game-creator-shell/package.json @@ -16,7 +16,7 @@ "bundled-resources:check": "node scripts/check-package-layout.mjs", "bundled-resources:sync": "node scripts/check-package-layout.mjs --write", "bundled-resources:prepare": "node scripts/prepare-bundled-resources.mjs", - "bundled-resources:test": "node --test scripts/prepare-bundled-resources.test.mjs", + "bundled-resources:test": "node --test --test-reporter=dot scripts/prepare-bundled-resources.test.mjs", "llm-status": "node scripts/run-cli-with-config.mjs --llm-status", "config": "node scripts/game-creator-config-wizard.mjs", "check:tests:types": "tsc -p tsconfig.tests.json --noEmit", diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index 6a39012a7..bf30e4c85 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -1,13 +1,5 @@ # 决策记录 -## 2026-10-04 CI 测试成功时静默(silent is gold) - -- 背景:`Frontend tests` 的 `npm run test:ci:frontend` 在成功 run 里仍回放被测代码的 console 输出——React `act(...)` 警告、`scripts/dev.test.ts` / `scripts/dev-all.test.ts` 的开发栈调度日志——把 CI 日志刷出大量与「红灯」无关的内容。 -- 决策:根 `vitest.config.ts` 固定 `test.silent: true`(`--silent` 的配置形态)。成功用例不再回放写进 stdout / stderr 的内容;reporter 仍输出每个文件一行进度与最终汇总,失败用例仍打印断言摘要与源码位置。`vitest.frontend-ci.config.ts` 通过 `mergeConfig` 继承该设置,AGC 与 repository checks 直接使用的根配置同样生效。本机排查用 `vitest run --silent=false` 覆盖。 -- 守护:`scripts/project-ci-workflow.test.ts` 新增用例钉住根配置的 `silent: true`,防止日后被顺手删掉。 -- 影响范围:`vitest.config.ts`、`scripts/project-ci-workflow.test.ts`、`docs/project-memory/shared-memory/development-workflow.md`、本文件。 -- 验证:`npx vitest run --config vitest.frontend-ci.config.ts`(243 files / 2761 passed,输出中 `stdout |` / `stderr |` 块与 `act(...)` 警告均为 0);定向 `scripts/{project-ci-workflow,dev,dev-all,dev-utils}.test.ts`(4 files / 114 passed);临时失败用例确认失败摘要仍打印;`--silent=false` 可恢复 console 输出;`git diff --check`、prettier、eslint `--max-warnings 0`(改动文件)通过。 - ## 2026-10-03 AGC 画布引用统一走「活跃聊天输入区」注册表(Issue 602) - 背景:画布的「引用」按钮与「拖拽批量引用」只派发 window 事件,消费者只有 `App.tsx` 一处,而它插的是绑在 `PlanningChatView` 上的 `chatComposerRef`;2026-09-22 DirectProject 拆分后普通项目走 `directProjectMode` 提前 return,渲染不到策划面 → ref 恒为 `null`,可选链静默吞掉点击(画布上是死按钮)。同一批合并冲突还丢了 `RESOURCE_REFERENCE_INSERT_MANY_EVENT` 的监听,批量引用连消费者都没有。 diff --git a/docs/project-memory/shared-memory/development-workflow.md b/docs/project-memory/shared-memory/development-workflow.md index f241edbfd..c4e72194e 100644 --- a/docs/project-memory/shared-memory/development-workflow.md +++ b/docs/project-memory/shared-memory/development-workflow.md @@ -120,9 +120,6 @@ AGC Rust 两条 lane、crates、smoke、Backend 和桌面壳测试使用镜像 `.gitea/workflows/project-ci.yml` 的客户端门禁拆成 lane 与功能 job,每个 job 只预热自己会构建的那几份依赖:`AI game creator shell Rust lane 1/2`、`lane 2/2` 各自预取一次 AGC 壳 manifest,并顺序运行两片 Rust bin 单测;`AI game creator shell Rust smoke` 同样只预取 AGC 壳 manifest(`agent-run` smoke 会用 `src-tauri/Cargo.toml` spawn `cargo run`),`AI game creator shell Rust crates` 预取 `server-rs/Cargo.toml` 与独立 crate,`Native shell tests` 预取桌面壳与 AGC 壳 manifest,`AI game creator shell web tests` 不触碰 Cargo,不预热。两条 Rust lane 与 smoke job 必须在编译前通过 `scripts/ci-npm-ci-with-retry.sh` 执行根 `npm ci`:AGC 壳的 `build.rs` 会从 `node_modules` 准备 Claude Agent SDK 与目标平台原生运行时,镜像中的 npm 下载缓存不能替代安装。人工 `scripts/build-gitea-rust-cache.sh` bootstrap 同样在首次编译 AGC 壳前安装 npm 依赖;只有不构建壳的 crates job 继续省略 npm 安装。两个被 `server-rs/Cargo.toml` 排除、且没有提交 `Cargo.lock` 的独立 crate(`agent-runtime-core`、`agent-runtime-orchestration`)只能在 `AI game creator shell Rust crates` 里用不带锁标志的 fetch。AGC 壳的 bin target 单测(约 2466 条)由 `apps/ai-game-creator-shell/scripts/run-rust-shell-test-shards.mjs` 编译后按 `--list` 名单分 4 片:每次分片调用用 `--shard-index=` 只跑自己那片,片内保持 `--test-threads=1` 并使用独立 `TMPDIR`;两条 lane 之间并发,lane 内顺序运行两片,避免重复依赖预热和同一容器内多进程争抢。不要改回「一个 job 内多进程并行这几片」——同一容器里它们会争抢共享 `HOME`、target 目录与固定临时路径,实测比整套串行还慢。每个分片调用都会自校验「片并集等于全集且互斥」,因此改分片规则不会静默漏跑。Backend host workspace tests 使用 `cargo test --locked --workspace --exclude spacetime-module --no-fail-fast`,避免 `spacetime-module` 的 `spacetime-types` feature 统一污染普通领域 crate 的 host 测试;随后单独执行 `cargo test --locked -p spacetime-module --no-fail-fast`,由 `spacetime-module/src/active.rs` 在 host 测试构建期间提供仅测试期的 SpacetimeDB ABI 链接支持,使该 crate 的纯单元测试也纳入 Backend 门禁。`spacetime-module` 的 reducer / procedure 运行时行为仍必须通过真实 SpacetimeDB runtime/integration harness 验证,host 链接支持不得被当作运行时替身。Backend 另外执行 `cargo check --locked -p spacetime-module` 验证模块源码。AGC 壳检查还会运行 `platform-llm` 与 `shared-contracts` 的 server-rs workspace 测试,这些命令以及 AGC 壳测试必须带 `--locked`,避免在测试阶段重新解析 registry index;锁文件发生变化时应先更新受信任 CI 镜像缓存,再重跑门禁。 -根 `vitest.config.ts` 固定 `test.silent: true`(`--silent` 的配置形态,silent is gold):成功用例不回放被测代码写进 stdout / stderr 的内容(React `act(...)` 警告、`scripts/dev*.test.ts` 的 dev 调度日志等),CI 日志只保留每个文件一行进度、最终汇总与失败用例的断言摘要加源码位置。`vitest.frontend-ci.config.ts` 通过 `mergeConfig` 继承该设置,AGC 与 repository checks 直接使用的根配置同样生效——所以不要改成只对某一个配置生效,那会让另一条 CI 测试重新刷屏。本机排查需要完整 console 输出时用 `vitest run --silent=false` 覆盖,不要改回 `silent: false`。`scripts/project-ci-workflow.test.ts` 有守护用例钉住这条口径。 - - ## AGC 测试类型门禁 AGC 测试(`apps/ai-game-creator-shell/tests/`)与生产 `src/` 同受类型门禁。`apps/ai-game-creator-shell/tsconfig.tests.json` 以 `include: ["src", "tests", "vite.config.ts"]`、`types: ["vite/client", "vitest/globals"]`、`allowImportingTsExtensions`、`allowJs` 全量覆盖:新增测试文件自动纳入,不存在基线、豁免名单或 `@ts-nocheck`。入口 `npm --prefix apps/ai-game-creator-shell run check:tests:types`(`tsc -p tsconfig.tests.json --noEmit`)已并入该 app 的 `typecheck`,因此 `npm run agc:typecheck`、`npm run ai-game-creator-shell:check:web` 与 CI 的 `AI game creator shell web tests` 都会执行。修测试只做类型层改动,不改断言与行为;禁止 `@ts-ignore`、`as any`,仅当 mock 泛型函数确实不可兼容时才允许带中文注释的 `as unknown as`。 diff --git a/package.json b/package.json index ca24fab4d..1a9caaae3 100644 --- a/package.json +++ b/package.json @@ -189,7 +189,7 @@ "agc:bundled-resources:sync": "npm --prefix apps/ai-game-creator-shell run bundled-resources:sync", "agc:bundled-resources:prepare": "npm --prefix apps/ai-game-creator-shell run bundled-resources:prepare --", "agc:bundled-resources:test": "npm --prefix apps/ai-game-creator-shell run bundled-resources:test --", - "agc:plugins:test": "node --test plugins/agc-cocos-editor/src/entry.test.mjs plugins/agc-unity-editor/src/entry.test.mjs plugins/agc-godot-editor/src/entry.test.mjs", + "agc:plugins:test": "node --test --test-reporter=dot plugins/agc-cocos-editor/src/entry.test.mjs plugins/agc-unity-editor/src/entry.test.mjs plugins/agc-godot-editor/src/entry.test.mjs", "agc:plugins:native-test": "cargo test --manifest-path plugins/agc-cocos-editor/native/cocos-editor-bridge/Cargo.toml && cargo test --locked --manifest-path plugins/agc-unity-editor/native/unity-editor-bridge/Cargo.toml && cargo test --locked --manifest-path plugins/agc-godot-editor/native/godot-editor-bridge/Cargo.toml", "agc:plugins:check": "npm run agc:plugins:test && npm run agc:plugins:native-test", "agc:check": "npm run ai-game-creator-shell:check", diff --git a/scripts/build-gitea-rust-cache.sh b/scripts/build-gitea-rust-cache.sh index 13ff337c9..75932951f 100644 --- a/scripts/build-gitea-rust-cache.sh +++ b/scripts/build-gitea-rust-cache.sh @@ -75,7 +75,7 @@ set -euo pipefail rustc -vV > /opt/genarrative-ci/rust-cache/rustc.txt export GITHUB_ENV=/tmp/rust-cache.env CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=4 CI=true # sccache 对 CARGO_*(除 jobserver/jobs 等特例)参与 hash,必须与 workflow 对齐。 -export CARGO_HTTP_MULTIPLEXING=false CARGO_NET_RETRY=10 CARGO_TERM_COLOR=always +export CARGO_HTTP_MULTIPLEXING=false CARGO_NET_RETRY=10 CARGO_TERM_COLOR=always CARGO_TERM_QUIET=true bash /tmp/ci-rust-cache.sh prepare set -a source "${GITHUB_ENV}" diff --git a/scripts/check-native-shells.mjs b/scripts/check-native-shells.mjs index 4dcf9550b..84e7c5125 100644 --- a/scripts/check-native-shells.mjs +++ b/scripts/check-native-shells.mjs @@ -5081,7 +5081,7 @@ for (const step of steps) { continue; } - console.log(`[check:native-shells] ${step.label}`); + // 成功不打印进度标签;只有在失败时才知道是哪个 step,避免每个 step 一行刷屏。 const result = spawnSync(step.command, step.args, { cwd: process.cwd(), stdio: 'inherit', @@ -5102,6 +5102,9 @@ for (const step of steps) { } if ((result.status ?? 0) !== 0) { + console.error( + `[check:native-shells] ${step.label} failed (exit=${result.status})`, + ); process.exit(result.status ?? 1); } } diff --git a/scripts/project-ci-workflow.test.ts b/scripts/project-ci-workflow.test.ts index 923c6a6ac..015533b15 100644 --- a/scripts/project-ci-workflow.test.ts +++ b/scripts/project-ci-workflow.test.ts @@ -75,12 +75,6 @@ const jobsWithoutNpmInstall: readonly string[] = [ const rootPackageJson = JSON.parse( readFileSync(resolve(process.cwd(), 'package.json'), 'utf8'), ) as { scripts?: Record }; -// 前端与 AGC 的 CI 测试都跑根 vitest 配置(`vitest.frontend-ci.config.ts` 也 merge 它), -// 这里钉住「成功用例静默」,避免有人顺手删掉后 CI 日志重新被 act 警告与 dev 日志刷屏。 -const rootVitestConfig = readFileSync( - resolve(process.cwd(), 'vitest.config.ts'), - 'utf8', -); const nativeShellGateScript = readFileSync( resolve(process.cwd(), 'scripts/check-native-shells.mjs'), 'utf8', @@ -546,10 +540,6 @@ describe('project CI workflow', () => { ).toHaveLength(2); }); - it('keeps passing CI tests silent so only failures reach the log', () => { - expect(rootVitestConfig).toMatch(/^\s*silent:\s*true,$/mu); - }); - it('keeps frontend, operations fixture, and native shell gates in dedicated jobs', () => { const frontendJob = jobSection('frontend-tests'); expect(frontendJob).toMatch(/^ {8}run: npm run test:ci:frontend$/mu); From 8ada23ea0ec745d94a18fed6416286fa96253b31 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Sun, 4 Oct 2026 17:34:27 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9AAGC=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B0=83=E7=94=A8=E7=BB=84=E6=8A=98=E5=8F=A0=E7=AE=AD?= =?UTF-8?q?=E5=A4=B4=E5=B1=95=E5=BC=80=E6=97=B6=E4=BB=8D=E6=9C=9D=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 .agent-tool-call-group-head[aria-expanded='true'] .agent-tool-call-group-chevron 的 rotate(180deg),消除与共享 AgentProcessSummary wrapper 叠加的 360° 旋转 - 在 .agent-tool-call-group-chevron 上方补注释,写明换向唯一来源在共享 wrapper,避免再次重复旋转 --- apps/ai-game-creator-shell/src/styles.css | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/ai-game-creator-shell/src/styles.css b/apps/ai-game-creator-shell/src/styles.css index 74d8e5e41..6c1c2d398 100644 --- a/apps/ai-game-creator-shell/src/styles.css +++ b/apps/ai-game-creator-shell/src/styles.css @@ -12415,17 +12415,15 @@ button.design-workspace-tree__entry:hover, white-space: nowrap; } +/* 组头 chevron 只保留外层定位与过渡;**换向唯一来源**是共享 `AgentProcessSummary` 的 + `[aria-expanded='true'] > .agent-process-summary .agent-process-summary-chevron`。 + 这里若再写一条 `rotate(180deg)`,会与 wrapper 的旋转叠加成 360°,展开态看起来仍是朝下。 */ .agent-tool-call-group-chevron { flex: 0 0 auto; color: inherit; transition: transform 120ms ease; } -.agent-tool-call-group-head[aria-expanded='true'] - .agent-tool-call-group-chevron { - transform: rotate(180deg); -} - /* `hidden` 必须压过下面的 `display: grid`,否则折叠态只是内容不可见却仍占位。 */ .agent-tool-call-group-body[hidden], .agent-tool-call-row-detail[hidden] {