Merge remote-tracking branch 'origin/master' into codex/wooden-fish-template
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
## 2026-05-21 外部 API 失败必须 OTLP 上报并落库
|
||||
|
||||
- 背景:图片生成等外部供应商调用失败时,仅返回 502/504 或普通日志无法支持后续按 provider、阶段和重试属性聚合排障。
|
||||
- 决策:外部 API 调用未成功时,`api-server` 必须同时发送 OTLP 失败观测并写入 `tracking_event`。当前通用 VectorEngine `gpt-image-2-all` 图片生成 / 编辑适配器记录 `external_api_call_failure`,`scope_kind = module`、`scope_id = provider`、`module_key = external-api`,metadata 包含 endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、latencyMs、promptChars、referenceImageCount、imageModel 和 rawExcerpt。
|
||||
- 决策:外部 API 调用未成功时,`api-server` 必须同时发送 OTLP 失败观测并写入 `tracking_event`。当前通用 VectorEngine `gpt-image-2` 图片生成 / 编辑适配器记录 `external_api_call_failure`,`scope_kind = module`、`scope_id = provider`、`module_key = external-api`,metadata 包含 endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、latencyMs、promptChars、referenceImageCount、imageModel 和 rawExcerpt。
|
||||
- 落库方式:优先复用 tracking outbox 异步批量写入;outbox 不可写或因保护阈值拒绝时回退同步直写 SpacetimeDB。不新增 SpacetimeDB 表,不让 reducer 做外部 I/O。
|
||||
- 影响范围:`server-rs/crates/api-server/src/external_api_audit.rs`、`server-rs/crates/api-server/src/openai_image_generation.rs`、`server-rs/crates/api-server/src/telemetry.rs`、tracking outbox、后端架构文档和开发运维文档。
|
||||
- 验证方式:执行 `cargo test -p api-server external_api_audit --manifest-path server-rs/Cargo.toml -- --nocapture`、`cargo test -p api-server openai_image_generation --manifest-path server-rs/Cargo.toml -- --nocapture`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding`。
|
||||
@@ -50,6 +50,15 @@
|
||||
- 验证方式:目标机 `nginx -T 2>/dev/null | grep client_max_body_size` 应看到 `client_max_body_size 64m;`;大于 1 MiB 的参考图请求不再在 Nginx 层直接 413,access log 应出现有效 `upstream_status`。
|
||||
- 关联文档:`deploy/nginx/README.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## 2026-05-22 抓大鹅素材生成改为关卡整图派生三图
|
||||
|
||||
- 背景:旧抓大鹅素材链路按物品 5x5 sheet、纯背景和独立容器图分开生产,难以保证背景、UI、容器和物品风格一致,也让结果页继续暴露背景 / 容器重生成入口。
|
||||
- 决策:抓大鹅草稿生成先用 `gpt-image-2` 无参考图生成竖屏 `9:16` 完整关卡画面;关卡画面完成后,以它作为参考并发生成三张可运行资产:`1K 1:1` UI spritesheet、`1K 9:16` 关卡背景图、`2K 1:1` 物品 spritesheet。UI 与物品 spritesheet 都固定要求纯绿色绿幕背景,后端上传 OSS 前扣成真实透明 PNG。物品 spritesheet 固定 `10*10`,每行两种物品、每种五个形态。运行态和编辑器都按 alpha 连通域矩形检测解析 UI 和物品图集,不按固定像素坐标切图。
|
||||
- 兼容:新增字段继续存入现有 `generatedItemAssets[].backgroundAsset` / `generatedBackgroundAsset` JSON,不新增 SpacetimeDB schema 字段。历史 `containerImage*` 字段只作兼容;如果它与 `uiSpritesheetImage*` 同源,不得再作为运行态中心容器图。
|
||||
- 影响范围:`server-rs/crates/api-server/src/match3d/*`、`server-rs/crates/shared-contracts/src/match3d_*`、`packages/shared/src/contracts/match3dWorks.ts`、`src/components/match3d-result/Match3DResultView.tsx`、`src/components/match3d-runtime/Match3DRuntimeShell.tsx`、`src/services/match3dSpritesheetParser.ts`。
|
||||
- 验证方式:执行 `cargo test -p api-server match3d --manifest-path server-rs\Cargo.toml`、`npm run test -- src/components/match3d-result/Match3DResultView.test.tsx src/components/match3d-runtime/Match3DRuntimeShell.test.tsx src/services/match3dSpritesheetParser.test.ts src/services/match3dGeneratedModelCache.test.ts`、`npm run typecheck`、`npm run check:encoding`。
|
||||
- 关联文档:`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
|
||||
## 2026-05-18 Rust 手写模块入口统一不用 mod.rs
|
||||
|
||||
@@ -172,6 +181,14 @@
|
||||
- 验证方式:默认 `compile-draft` 返回的 `hitObjectAsset.generationProvider` 应为 `bundled-default` 且 `imageSrc=/wooden-fish/default-hit-object.png`;自定义关键词或参考图仍走 image2;前端静态资源可通过 Vite 直接访问。
|
||||
- 关联文档:`docs/prd/【玩法创作】敲木鱼玩法模板PRD-2026-05-20.md`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## 2026-05-21 RPG publish_world 设定文本以后端草稿真相派生
|
||||
|
||||
- 背景:RPG 结果页发布动作只保证提交 `{ action: 'publish_world' }`;旧 agent 会话可能没有 `seed_text`,但 `draft_profile_json` 已经通过 `publish_gate` 并可发布。
|
||||
- 决策:发布正式世界时,`spacetime-module` 不再把 `session.seed_text` 当作唯一 `setting_text` 兜底,而是调用 `module-custom-world::resolve_custom_world_publish_setting_text(...)` 从 payload、当前草稿 profile 和 seed 依次派生。
|
||||
- 影响范围:RPG / custom-world agent 发布链路、`custom_world_profile` 编译入库、公开 gallery 投影。
|
||||
- 验证方式:`cargo test -p module-custom-world publish_setting_text --manifest-path server-rs\Cargo.toml`;`cargo check -p spacetime-module --manifest-path server-rs\Cargo.toml`;本地 api-server 重启后检查 `/healthz`。
|
||||
- 关联文档:`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`、`.hermes/shared-memory/pitfalls.md`。
|
||||
|
||||
## 2026-05-19 系列素材 n*n 图集抽为 api-server 通用模块
|
||||
|
||||
- 背景:抓大鹅物品 sheet 已包含 prompt 组装、固定网格切图、绿幕 / 近白底透明化、切片 PNG 持久化和 prompt 追踪;继续留在 Match3D 私有模块会让跳一跳、后续地块 / 道具类玩法重复复制同一套算法和 OSS 元数据口径。
|
||||
@@ -255,6 +272,7 @@
|
||||
|
||||
## 2026-05-14 抓大鹅物品素材 sheet 改用 VectorEngine Gemini
|
||||
|
||||
- 状态:历史决策,已被 `2026-05-22 抓大鹅素材生成改为关卡整图派生三图` 取代;当前物品 spritesheet 走 `gpt-image-2` 参考关卡整图编辑生成 `2K 1:1`、`10*10` 绿幕图,上传 OSS 前扣成透明 PNG。
|
||||
- 背景:抓大鹅 2D 五视角物品素材仍沿用 5x5 sheet、绿幕去背、切图、OSS 转存和 `generatedItemAssets` 持久化,但用户要求物品素材图片生成步骤改用 VectorEngine Apifox `api-381740608` 对应的 Gemini 原生图片接口。
|
||||
- 决策:抓大鹅物品素材 sheet 生图固定走 VectorEngine `POST {VECTOR_ENGINE_BASE_URL}/v1beta/models/gemini-3-pro-image-preview:generateContent?key={VECTOR_ENGINE_API_KEY}`,请求体使用 `contents[].parts[].text` 与 `generationConfig.responseModalities = ["TEXT", "IMAGE"]`、`imageConfig.aspectRatio = "1:1"`;响应从 `candidates[].content.parts[].inlineData.data` / `inline_data.data` 读取 base64 图片。封面、9:16 纯背景图、1:1 容器 UI 图、切图、OSS、扣费和运行态消费链路保持不变;音频以后续“拼图与抓大鹅音频生成入口临时关闭”决策为准。
|
||||
- 影响范围:`server-rs/crates/api-server/src/match3d.rs`、`server-rs/crates/api-server/src/config.rs`、`deploy/env/api-server.env.example`、抓大鹅素材生成技术文档。
|
||||
@@ -306,7 +324,7 @@
|
||||
## 2026-05-12 抓大鹅入口素材风格改为 2D 常见素材风格
|
||||
|
||||
- 背景:抓大鹅草稿素材生成已经收敛为多视角 2D 图片素材,但入口页和旧参考图仍沿用黏土、低多边形、塑料、木雕、体素、金属等偏 3D 素材语言,容易让后续生成链路和用户预期继续漂移。
|
||||
- 决策:抓大鹅创作入口 `2D素材风格` 固定为 `扁平图标 / 赛璐璐卡通 / 像素复古 / 手绘水彩 / 贴纸描边 / 厚涂图标 / 自定义`;默认风格为 `flat-icon`。入口参考图统一由 `npm run assets:match3d-style-references -- --live` 调用 VectorEngine `gpt-image-2-all` 生成,输出到 `public/match3d-style-references/`。旧 3D 风格参考图不再保留为入口资产。
|
||||
- 决策:抓大鹅创作入口 `2D素材风格` 固定为 `扁平图标 / 赛璐璐卡通 / 像素复古 / 手绘水彩 / 贴纸描边 / 厚涂图标 / 自定义`;默认风格为 `flat-icon`。入口参考图统一由 `npm run assets:match3d-style-references -- --live` 调用 VectorEngine `gpt-image-2` 生成,输出到 `public/match3d-style-references/`。旧 3D 风格参考图不再保留为入口资产。
|
||||
- 影响范围:`Match3DAgentWorkspace`、抓大鹅入口交互测试、Match3D PRD、素材生成流水线技术文档、F1 入口文档和 `public/match3d-style-references/` 静态资产。
|
||||
- 验证方式:执行 `npm run test -- src\components\match3d-creation\Match3DAgentWorkspace.interaction.test.tsx`、`cargo test -p shared-contracts match3d --manifest-path server-rs\Cargo.toml`、`npm run typecheck`、`npm run check:encoding`,并人工抽查 `.tmp/match3d-style-preview.png`。
|
||||
- 关联文档:`docs/prd/AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md`、`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`、`docs/technical/MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md`。
|
||||
@@ -322,8 +340,9 @@
|
||||
## 2026-05-12 拼图 UI 背景图复用 levels_json 持久化
|
||||
|
||||
- 背景:拼图草稿结果页需要像抓大鹅一样支持 UI 背景生成,但首版只需要作品级/首关背景,不应为图片生成结果新增 SpacetimeDB 表结构。
|
||||
- 决策:拼图 UI 背景字段存入首关 `levels_json`,字段为 `uiBackgroundPrompt`、`uiBackgroundImageSrc`、`uiBackgroundImageObjectKey`;`compile_puzzle_draft` 草稿编译阶段自动生成首关 UI 背景,自动草稿阶段必须拿到 `uiBackgroundImageSrc` 或 `uiBackgroundImageObjectKey` 才能返回成功;结果页新增 `UI` Tab,可编辑提示词并触发 `generate_puzzle_ui_background`,手动生成失败只展示在当前面板。`api-server` 读取 `public/ui-previews/puzzle-image-compact-ui-2026-05-08.png` 作为非拼图 UI 参考图,调用 VectorEngine `gpt-image-2-all` 生成 9:16 背景并要求中央正方形拼图区与外部 UI 背景边界清晰。SpacetimeDB 只保存结果,不做外部 I/O。
|
||||
- 决策:拼图 UI 背景字段存入首关 `levels_json`,字段为 `uiBackgroundPrompt`、`uiBackgroundImageSrc`、`uiBackgroundImageObjectKey`;`compile_puzzle_draft` 草稿编译阶段自动生成首关 UI 背景,自动草稿阶段必须拿到 `uiBackgroundImageSrc` 或 `uiBackgroundImageObjectKey` 才能返回成功;结果页新增 `UI` Tab,可编辑提示词并触发 `generate_puzzle_ui_background`,手动生成失败只展示在当前面板。`api-server` 读取 `public/ui-previews/puzzle-image-compact-ui-2026-05-08.png` 作为非拼图 UI 参考图,调用 VectorEngine `gpt-image-2` 生成 9:16 背景并要求中央正方形拼图区与外部 UI 背景边界清晰。SpacetimeDB 只保存结果,不做外部 I/O。
|
||||
- 2026-05-18 追加:为缩短首版草稿等待,`compile_puzzle_draft` 在首关命名和 `uiBackgroundPrompt` 稳定后并行启动首关关卡图生成与 UI 背景生成;上传主图且关闭 AI 重绘时,并行执行上传图持久化与 UI 背景生成。生成页预计完成时间按 5 分钟展示。
|
||||
- 2026-05-21 追加:拼图结果页独立“素材配置”Tab 已移除,UI spritesheet 与关卡纯背景收口到每关图片生成资产包。每次 `gpt-image-2` 预计 90 秒;草稿完整 AI 重绘路径约 298 秒,上传图且关闭 AI 重绘路径跳过首图生成约 208 秒。结果页关卡详情继续复用 `CreativeImageInputPanel`,本次上传/历史选择图优先成为主图卡片,正式图只作为无新参考图时的预览;仅有正式图时仍允许在画面描述框上传多张参考图。
|
||||
- 影响范围:拼图结果页、拼图运行态背景渲染、拼图 agent action、`module-puzzle` / `spacetime-module` / `spacetime-client` 的拼图关卡 JSON 映射、拼图流程技术文档。
|
||||
- 验证方式:执行 `npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx`、`cargo test -p api-server puzzle_ui_background --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run typecheck`、`npm run check:encoding`。
|
||||
- 关联文档:`docs/technical/PUZZLE_FORM_CREATION_FLOW_2026-04-29.md`。
|
||||
@@ -331,7 +350,7 @@
|
||||
## 2026-05-12 抓大鹅结果页素材编辑统一走作品级资产面板
|
||||
|
||||
- 背景:抓大鹅结果页需要支持封面图上传 / AI 重绘、物品素材独立预览、单项删除和批量新增,且不能把素材编辑继续做成列表内联展开或前端临时状态。
|
||||
- 决策:结果页 `作品信息` 的封面图点击打开独立面板,封面图面板对齐拼图入口上传卡。已有上传主图时,请求体传 `uploadedImageSrc`,AI 重绘走 VectorEngine `/v1/images/edits`;关闭 AI 重绘时只写回上传图,不调用生图。没有上传主图时,请求体传 `referenceImageSrcs`,可混合本地上传、物品素材和 UI 素材,多参考图作为 `gpt-image-2-all` generations 的 `image` 数组传入。生成结果统一调用 `POST /api/creation/match3d/works/{profileId}/cover-image` 并转存到 `generated-match3d-assets`。`素材配置 > 物品` 列表项点击打开独立预览面板,不再提供单项重新生成按钮;单项删除和批量新增都写回同一份 `generated_item_assets_json`。批量新增调用 `POST /api/creation/match3d/works/{profileId}/item-assets`,复用草稿生成的 2D 素材图、5x5 切图、OSS 上传和可选点击音效链路,仅作用于新增物品,不新增 SpacetimeDB 表。
|
||||
- 决策:结果页 `作品信息` 的封面图点击打开独立面板,封面图面板对齐拼图入口上传卡。已有上传主图时,请求体传 `uploadedImageSrc`,AI 重绘走 VectorEngine `/v1/images/edits`,后端把上传图作为 multipart `image` part 传入 `gpt-image-2`;关闭 AI 重绘时只写回上传图,不调用生图。没有上传主图但存在 `referenceImageSrcs` 时,多参考图同样走 edits 的多个 `image` part;完全无参考图时走 `/v1/images/generations`。生成结果统一调用 `POST /api/creation/match3d/works/{profileId}/cover-image` 并转存到 `generated-match3d-assets`。`素材配置 > 物品` 列表项点击打开独立预览面板,不再提供单项重新生成按钮;单项删除和批量新增都写回同一份 `generated_item_assets_json`。批量新增调用 `POST /api/creation/match3d/works/{profileId}/item-assets`;该接口的物品 spritesheet 生成口径已被 2026-05-22 决策更新为关卡整图参考、`10*10` 绿幕图和上传前透明化。
|
||||
- 影响范围:Match3D 结果页、Match3D works shared contracts、`api-server` Match3D 作品路由、生成资产历史类型和草稿恢复路径。
|
||||
- 验证方式:执行 `npm run test -- src/components/match3d-result/Match3DResultView.test.tsx`、`npm run typecheck`、`cargo test -p api-server match3d --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding`。
|
||||
- 关联文档:`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
@@ -354,7 +373,7 @@
|
||||
## 2026-05-13 宝贝爱画先作为寓教于乐独立本地 Demo 落地
|
||||
|
||||
- 背景:第三关 `宝贝爱画` 需要默认出现在“发现 / 寓教于乐”板块下方,但本阶段只验证画板、手部绘制、绘画魔法和本地保存闭环,不进入创作模板、公开作品或正式持久化。
|
||||
- 决策:`baby-love-drawing / 宝贝爱画` 先作为独立运行态接入,入口由发现页寓教于乐默认卡片打开,并支持 `/runtime/baby-love-drawing` 直达;关闭 `VITE_ENABLE_EDUTAINMENT_ENTRY` 时前端不展示频道/卡片且直达路由回落主应用。绘画魔法统一走 `POST /api/creation/edutainment/baby-love-drawing/magic` 后端安全代理,使用 VectorEngine `gpt-image-2-all` 与原始画布 Data URL 参考图生成绘本风图片;保存只写 localStorage,正式持久化后续再设计。
|
||||
- 决策:`baby-love-drawing / 宝贝爱画` 先作为独立运行态接入,入口由发现页寓教于乐默认卡片打开,并支持 `/runtime/baby-love-drawing` 直达;关闭 `VITE_ENABLE_EDUTAINMENT_ENTRY` 时前端不展示频道/卡片且直达路由回落主应用。绘画魔法统一走 `POST /api/creation/edutainment/baby-love-drawing/magic` 后端安全代理,使用 VectorEngine `gpt-image-2` 与原始画布 Data URL 参考图生成绘本风图片;保存只写 localStorage,正式持久化后续再设计。
|
||||
- 影响范围:`packages/shared/src/contracts/edutainmentBabyDrawing.ts`、`src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.tsx`、`src/services/edutainment-baby-drawing/`、`src/routing/appRoutes.tsx`、`src/components/rpg-entry/RpgEntryHomeView.tsx`、`server-rs/crates/api-server/src/edutainment_baby_drawing.rs`、`src/index.css`、宝贝爱画 PRD 与技术方案。
|
||||
- 验证方式:执行宝贝爱画 model/runtime/service/route 定向测试、`npm run typecheck`、定向 ESLint、`cargo test -p api-server edutainment_baby_drawing --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server resolves_runtime_paths_to_creation_type_ids --manifest-path server-rs/Cargo.toml` 和编码检查;真实魔法生成需配置 `VECTOR_ENGINE_BASE_URL` 与 `VECTOR_ENGINE_API_KEY`。
|
||||
- 关联文档:`docs/prd/BABY_LOVE_DRAWING_EDUTAINMENT_LEVEL_PRD_2026-05-13.md`、`docs/technical/BABY_LOVE_DRAWING_RUNTIME_DEMO_IMPLEMENTATION_2026-05-13.md`。
|
||||
@@ -387,7 +406,7 @@
|
||||
## 2026-05-10 儿童动作 Demo 视觉资产统一为绘本草地舞台
|
||||
|
||||
- 背景:儿童动作 Demo 需要从暗色科技风切换到更适合儿童互动的卡通绘本草地风格,并且要让背景、地面、UI、地面指示环和用户轮廓使用同一套 image-2 资源口径。
|
||||
- 决策:热身舞台及后续儿童动作 Demo 场景、物品、UI 资源统一采用明亮卡通绘本草地视觉语言。真实资源默认输出到 `public/child-motion-demo/`。背景沿用 `picture-book-grass-stage.png`;地面、指示环、角色指示器和 UI 已拆分为用途专属资源:`picture-book-foreground-grass-v2.png`、`picture-book-ground-ring-v3.png`、`picture-book-character-outline-v4.png`、`picture-book-hud-strip-v2.png`、`picture-book-calibration-strip-v2.png`、`picture-book-start-panel-v2.png` 和 `picture-book-ui-button-v2.png`。其中角色指示器 v4 基于 v2 本地后处理为更细的白色描边样式,内部透明,耳朵、手指、脚趾等细节已弱化,页面显示尺寸相对上一版放大 50%。生成脚本固定为 `scripts/generate-child-motion-demo-assets.mjs`,并通过 `npm run assets:child-motion-demo` 调用 VectorEngine `gpt-image-2-all`;透明资源使用品红底生成后本地去背,中间源图仅保存在 `tmp/child-motion-demo-assets/`。在缺少 `VECTOR_ENGINE_BASE_URL` 或 `VECTOR_ENGINE_API_KEY` 时,只允许 dry-run 和 CSS 兜底,不伪造 live 生图结果。
|
||||
- 决策:热身舞台及后续儿童动作 Demo 场景、物品、UI 资源统一采用明亮卡通绘本草地视觉语言。真实资源默认输出到 `public/child-motion-demo/`。背景沿用 `picture-book-grass-stage.png`;地面、指示环、角色指示器和 UI 已拆分为用途专属资源:`picture-book-foreground-grass-v2.png`、`picture-book-ground-ring-v3.png`、`picture-book-character-outline-v4.png`、`picture-book-hud-strip-v2.png`、`picture-book-calibration-strip-v2.png`、`picture-book-start-panel-v2.png` 和 `picture-book-ui-button-v2.png`。其中角色指示器 v4 基于 v2 本地后处理为更细的白色描边样式,内部透明,耳朵、手指、脚趾等细节已弱化,页面显示尺寸相对上一版放大 50%。生成脚本固定为 `scripts/generate-child-motion-demo-assets.mjs`,并通过 `npm run assets:child-motion-demo` 调用 VectorEngine `gpt-image-2`;透明资源使用品红底生成后本地去背,中间源图仅保存在 `tmp/child-motion-demo-assets/`。在缺少 `VECTOR_ENGINE_BASE_URL` 或 `VECTOR_ENGINE_API_KEY` 时,只允许 dry-run 和 CSS 兜底,不伪造 live 生图结果。
|
||||
- 影响范围:`src/index.css`、`src/components/child-motion-demo/ChildMotionWarmupDemo.tsx` 的舞台视觉层、儿童动作 Demo 技术文档、后续 image-2 资产生成流程。
|
||||
- 验证方式:检查 `/child-motion-demo` 舞台是否在未生成资产时仍有可用草地绘本兜底;补齐 VectorEngine 私密配置后运行 `npm run assets:child-motion-demo -- --live` 或 `--live --only <asset-id>` 应能写出对应 PNG,并确认页面静态资源返回 `image/png`。若只调整透明去背、裁切或品红边缘,可运行 `npm run assets:child-motion-demo -- --live --postprocess-only --force --only <asset-id>` 复用源图后处理。页面接入时必须按资源原始比例等比使用,不得把方形软纸面板拉伸成 HUD、状态条或底部草坪。
|
||||
- 关联文档:`docs/technical/CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md`、`docs/technical/VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md`。
|
||||
@@ -408,6 +427,14 @@
|
||||
- 验证方式:执行入口配置、创作 Hub、平台入口交互和 api-server 路由熔断定向测试,确认“视觉小说”不出现在创作页且 `/api/creation/visual-novel/*` 默认被熔断。
|
||||
- 关联文档:`docs/design/PLATFORM_CREATE_TAB_CREATIVE_AGENT_HOME_2026-05-05.md`、`docs/technical/ADMIN_CREATION_ENTRY_SWITCH_CONFIG_2026-05-11.md`。
|
||||
|
||||
## 2026-05-20 RPG 创作入口开放
|
||||
|
||||
- 背景:RPG 文字冒险能力已经具备历史 custom-world 创作和运行闭环,但入口默认种子仍 `visible=false`,创作页不展示。
|
||||
- 决策:SpacetimeDB `creation_entry_type_config` 默认种子中 `rpg.visible=true` 且 `open=true`,旧默认隐藏配置只在标题、subtitle、badge、图片、排序和开关完全匹配时迁移为可见可创建。`airp` 仍保持 AI RPG 占位,不接管当前 RPG 链路。结构化创作 / RPG JSON 链路默认关闭 Responses `web_search`,需要联网增强时才通过 `GENARRATIVE_RPG_LLM_WEB_SEARCH_ENABLED=true` 或 `GENARRATIVE_CREATION_AGENT_LLM_WEB_SEARCH_ENABLED=true` 显式启用;未开通工具的上游会返回 `ToolNotOpen`,不能把这类失败暴露成“模型返回结果解析失败”。
|
||||
- 影响范围:创作入口默认种子、旧库入口纠偏、`api-server` 入口熔断、创作页模板 Tab、创作 Hub 测试、玩法链路文档和后端路由文档。
|
||||
- 验证方式:执行入口配置、api-server 路由熔断、创作 Hub 和平台入口交互定向测试,确认“文字冒险”出现在创作入口,`/api/runtime/custom-world*`、`/api/story/*`、`/api/runtime/chat/*` 都按 `rpg` 入口开关熔断。
|
||||
- 关联文档:`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。
|
||||
|
||||
## 2026-05-10 运行态输入设备抽象层全项目通用化
|
||||
|
||||
- 背景:拼图运行态接入 mocap 后,鼠标/触控和 mocap 各自维护输入逻辑会导致合并大块、拖拽语义和取消会话行为不一致;后续其他玩法也需要复用体感、摇杆、键盘等设备输入。
|
||||
@@ -441,11 +468,19 @@
|
||||
## 2026-05-09 GPT-image-2 图片生成统一迁移到 VectorEngine
|
||||
|
||||
- 背景:仓库内 RPG、拼图、方洞和本地模板脚本的 GPT-image-2 生图此前依赖 APIMart 图片网关;团队要求参考 VectorEngine Apifox `api-448710071`,后续不再使用 APIMart 执行 GPT-image-2 图片生成。
|
||||
- 决策:所有 GPT-image-2 生图请求统一走 VectorEngine `POST /v1/images/generations`,基础配置读取 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` / `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`,上游模型使用 `gpt-image-2-all`,请求体不再携带 `official_fallback`,参考图字段改为 `image`。APIMart 只保留给创意 Agent 的 `gpt-5` Responses 文本/多模态链路。
|
||||
- 决策:所有 GPT-image-2 无参考图生图请求统一走 VectorEngine `POST /v1/images/generations`,有参考图请求走 `POST /v1/images/edits` multipart,基础配置读取 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` / `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`,上游模型使用 `gpt-image-2`,请求体不再携带 `official_fallback`。APIMart 只保留给创意 Agent 的 `gpt-5` Responses 文本/多模态链路。
|
||||
- 影响范围:`api-server` 共享图片 helper、拼图图片生成、角色主图、RPG 场景图、开局 CG 故事板、方洞视觉资产、生产环境示例、gpt-image-2 本地 skill 和相关技术文档。
|
||||
- 验证方式:执行 `npm run check:encoding`、`cargo test -p api-server openai_image --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server puzzle --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server custom_world_ai --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server character_visual --manifest-path server-rs/Cargo.toml`,并用 `npm run dev:api-server` + `/healthz` 做后端 smoke。
|
||||
- 关联文档:`docs/technical/VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md`、`docs/technical/API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md`。
|
||||
|
||||
## 2026-05-21 GPT-image-2 参考图统一走 edits multipart
|
||||
|
||||
- 背景:VectorEngine Apifox 创建 `api-446794806` 与编辑 `api-446794807` 明确区分无参考图创建和有参考图编辑;仓库旧实现曾把参考图塞入 `gpt-image-2` generations 的 `image` 数组,导致与供应商当前契约不一致。
|
||||
- 决策:所有 GPT-image-2 无参考图生成调用 `POST /v1/images/generations`,所有有参考图生成调用 `POST /v1/images/edits`,模型固定 `gpt-image-2`,参考图作为 multipart `image` part 传入;仓库不再调用 `gpt-image-2-all`。
|
||||
- 影响范围:`api-server` 共享图片 helper、拼图图片生成、Match3D 封面重绘和容器 UI 图、gpt-image-2 本地 skill、玩法链路文档和后端架构文档。
|
||||
- 验证方式:搜索仓库不应再出现 VectorEngine 图片编辑路径调用;执行 `cargo test -p api-server openai_image_generation --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server puzzle_vector_engine --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server match3d_background --manifest-path server-rs/Cargo.toml`。
|
||||
- 关联文档:`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。
|
||||
|
||||
## 2026-05-08 Hyper3D Rodin Gen-2 只通过后端安全代理接入
|
||||
|
||||
- 背景:需要接入 Hyper3D Rodin Gen-2 的文生 3D 模型与图生 3D 模型,但供应商 API Key 不能进入前端、文档或 Git;本次只是外部副作用代理,不需要新增平台真相表。
|
||||
@@ -619,7 +654,7 @@
|
||||
## 2026-05-10 视觉小说入口收敛为单句创作 + 画风选择
|
||||
|
||||
- 背景:视觉小说入口页要对齐抓大鹅式的线性创作入口,只保留最小可用输入,避免再暴露文档 / 空白 / 对话式工作台。
|
||||
- 决策:入口页只展示一句话创作输入框和横向视觉画风卡片;画风通过 `seedText` 追加 `视觉画风` 和 `画风要求` 两行透传给既有创作链路;点击生成后先进入 `visual-novel-generating` 过程页,再自动进入 `visual-novel-result`。画风卡片主视觉固定消费 `public/visual-novel-style-references/` 下由 VectorEngine `gpt-image-2-all` 生成的静态参考图,不在前端运行时现场调用生图接口。
|
||||
- 决策:入口页只展示一句话创作输入框和横向视觉画风卡片;画风通过 `seedText` 追加 `视觉画风` 和 `画风要求` 两行透传给既有创作链路;点击生成后先进入 `visual-novel-generating` 过程页,再自动进入 `visual-novel-result`。画风卡片主视觉固定消费 `public/visual-novel-style-references/` 下由 VectorEngine `gpt-image-2` 生成的静态参考图,不在前端运行时现场调用生图接口。
|
||||
- 影响范围:`VisualNovelAgentWorkspace`、`visualNovelEntryGeneration`、`PlatformEntryFlowShellImpl`、视觉小说 PRD 和创作 Tab 设计文档;不新增后端字段或数据库结构。
|
||||
- 验证方式:执行 `npm run test -- VisualNovelAgentWorkspace`、视觉小说工作台相关 ESLint、`npx prettier --check` 和 `npm run check:encoding`;`npm run typecheck` 若失败需先区分是否来自无关 Match3D / RPG 既有改动。
|
||||
- 关联文档:`docs/prd/AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md`、`docs/design/PLATFORM_CREATE_TAB_CREATIVE_AGENT_HOME_2026-05-05.md`。
|
||||
@@ -643,7 +678,7 @@
|
||||
## 2026-05-12 抓大鹅物品种类从消除次数中拆出并改为 2D 五视角素材
|
||||
|
||||
- 背景:结果页草稿素材已经能生成和预览,但标准 / 硬核难度仍可能按 `clearCount` 误判需要 12 / 20 种素材,且继续生产 GLB 会拉长草稿生成耗时。
|
||||
- 决策:难度配置统一使用 `物品种类`:轻松 3、标准 9、进阶 15、硬核 21;历史硬核 `clearCount=20` 在运行态升为 21 组三消。新草稿和批量新增不再调用 Rodin、不再生成 GLB。每个物品生成 5 个不同 2D 视角,单张 1K 素材图固定按 5x5 切割,最多承载 5 个物品;超过 5 个物品时由 `api-server` 自动分批并行生图。发布必须校验已生成 `image_ready` 且有 `imageViews[]` 或首图引用的素材数量满足当前难度;试玩通过 `itemTypeCountOverride` 自动降到可用 2D 素材数量。历史模型字段只作为旧数据兼容,不再进入新生产链路。
|
||||
- 决策:难度配置统一使用运行态 `物品种类`:轻松 3、标准 9、进阶 15、硬核 20;历史硬核 `clearCount=20` 在运行态仍升为 21 组三消,但类型池最多 20 种。新草稿和批量新增不再调用 Rodin、不再生成 GLB。每次固定从 `2K 1:1`、`10*10` 物品 spritesheet 解析并持久化 20 个物品、每个 5 个不同 2D 形态,物品信息列表全部展示 20 个;持久化行列索引按每行两种物品计算,不能超过 `1..=10`。发布必须校验已生成 `image_ready` 且有 `imageViews[]`、首图引用或可解析的物品 spritesheet 满足当前难度;试玩通过 `itemTypeCountOverride` 自动降到可用 2D 素材数量。历史模型字段只作为旧数据兼容,不再进入新生产链路。
|
||||
- 影响范围:Match3D 结果页、运行态启动契约、`module-match3d` 初始 run 生成、SpacetimeDB start input / restart、发布校验和 Match3D 技术文档。
|
||||
- 验证方式:`npm run test -- src/components/match3d-result/Match3DResultView.test.tsx`、`cargo test -p module-match3d --manifest-path server-rs\Cargo.toml`、相关后端 check / tests。
|
||||
- 关联文档:`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
|
||||
@@ -14,6 +14,32 @@
|
||||
- 关联:相关文件、文档、提交或 Issue
|
||||
```
|
||||
|
||||
## 抓大鹅新 UI spritesheet 不要回退成中心容器图
|
||||
|
||||
- 现象:新素材流程生成后,运行态棋盘中心可能叠出一整张 UI spritesheet,导致按钮素材、方格和空白图集覆盖容器区域。
|
||||
- 原因:为了兼容旧 DTO,后端可能把 `uiSpritesheetImage*` 同步写入历史 `containerImage*` 字段;旧前端只看 `containerImage*`,会误把 UI 图集当透明中心容器。
|
||||
- 处理:读取中心容器图时先比较归一化后的 `containerImage*` 与 `uiSpritesheetImage*`。两者同源时忽略 `containerImage*`,只把它作为旧数据兼容字段;新流程背景图本身已经保留容器,运行态只需加载背景和解析 UI / 物品 spritesheet。
|
||||
- 验证:`npm run test -- src/components/match3d-runtime/Match3DRuntimeShell.test.tsx` 应覆盖“运行态不把兼容写入的UI spritesheet当中心容器图”。
|
||||
- 关联:`src/components/match3d-runtime/Match3DRuntimeShell.tsx`、`server-rs/crates/api-server/src/match3d/mappers.rs`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## UI spritesheet 不要依赖模型直接生成透明背景
|
||||
|
||||
- 现象:拼图或抓大鹅运行态解析 UI spritesheet 时,把整张背景图、棋盘格、叶子或装饰图也当作 UI 素材区域,按钮映射错乱;截图里常表现为底部按钮区只剩透明棋盘格或素材碎片。
|
||||
- 原因:前端解析依赖 alpha 连通域检测,透明背景是前提;但生图模型收到“透明背景 spritesheet”提示后仍可能输出带实景背景或伪透明棋盘格的普通不透明 PNG,OSS 中保存的图没有真实 alpha。
|
||||
- 处理:UI spritesheet 提示词应要求统一纯绿色绿幕背景,而不是让模型直接产透明背景;后端在上传 OSS 前复用 `generated_asset_sheets::apply_generated_asset_sheet_green_screen_alpha(...)` 把绿幕扣成真实透明 PNG,再把透明图写入 `uiSpritesheetImageSrc/uiSpritesheetImageObjectKey`。
|
||||
- 验证:`cargo test -p api-server puzzle_ui_spritesheet_postprocess_turns_green_screen_transparent --manifest-path server-rs\Cargo.toml`、`cargo test -p api-server puzzle_level_scene_spritesheet_and_background_requests_use_references --manifest-path server-rs\Cargo.toml`、`cargo test -p api-server match3d_derived_asset_prompts_match_three_sheet_pipeline --manifest-path server-rs\Cargo.toml`。
|
||||
- 关联:`server-rs/crates/api-server/src/puzzle/generation.rs`、`server-rs/crates/api-server/src/match3d/works.rs`、`server-rs/crates/api-server/src/generated_asset_sheets.rs`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## 拼图 UI spritesheet 运行态不要二次包圆底或拉伸比例
|
||||
|
||||
- 现象:拼图运行态左上返回和右上设置按钮外面出现白色圆圈;底部“提示 / 原图 / 冻结”三枚素材被压扁、拉宽或拉成正圆,和图集原始按钮比例不一致。
|
||||
- 原因:UI spritesheet 已经包含按钮视觉本体,但运行态仍给顶部按钮套默认圆形 icon 容器;底部三枚素材用 `h-full w-full rounded-full` 铺满按钮格,覆盖了自动检测矩形的真实宽高比。
|
||||
- 处理:有 `uiSpritesheetImage*` 时,顶部返回 / 设置按钮容器只保留透明点击区和 focus 状态,不再叠加默认圆形底;`buildPuzzleUiSpriteBackgroundStyle(...)` 对检测到的矩形写入 `aspectRatio`,底部三枚素材按原始宽高比和最大尺寸渲染,不强制 `w-full`。
|
||||
- 验证:`npm run test -- src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx`、`npm run test -- src/services/puzzle-runtime/puzzleUiSpritesheetParser.test.ts`。
|
||||
- 关联:`src/components/puzzle-runtime/PuzzleRuntimeShell.tsx`、`src/services/puzzle-runtime/puzzleUiSpritesheetParser.ts`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
2026-05-22 补充:展示矩形和点击热区要分开处理。`puzzleUiSpritesheetParser` 的 `regions` 保留完整视觉裁切矩形,`hitRegions` 用较高 alpha 阈值只包住实心按钮主体;运行态底部 spritesheet 道具按钮启用 `puzzle-runtime-sprite-tool-button--precise-hit`,父按钮不吃整块透明留白,内部 `puzzle-runtime-ui-sprite-hit-zone` 才接收指针事件,避免透明区域成为点击热区。
|
||||
|
||||
## 图像输入组件不要把业务状态藏在页面内联实现里
|
||||
|
||||
- 现象:拼图页把参考图上传、缩略图、主图删除确认和 AI 重绘开关内联实现后,后续想复用到其它创作页时,页面级状态和通用 UI 状态混在一起,容易出现多套上传卡和参考图展示口径。
|
||||
@@ -22,6 +48,54 @@
|
||||
- 验证:拼图入口测试仍可通过,且新组件可通过不同页面复用而不需要复制上传卡实现。
|
||||
- 关联:`src/components/common/CreativeImageInputPanel.tsx`、`src/components/puzzle-agent/PuzzleAgentWorkspace.tsx`。
|
||||
|
||||
## RPG 发布不能只依赖 agent session seed_text
|
||||
|
||||
- 现象:RPG 结果页 `publish_world` 返回 `UPSTREAM_ERROR`,details 为 `custom_world.setting_text 不能为空`;同一 session 的 `result-view` 日志显示 `publish_ready=true`。
|
||||
- 原因:前端发布动作只提交 `{ action: 'publish_world' }`,旧 agent 会话的 `seed_text` 可能为空;如果后端只从 action payload 或 `seed_text` 取 `setting_text`,就会在最终 compile / publish 校验阶段失败。
|
||||
- 处理:`module-custom-world::resolve_custom_world_publish_setting_text(...)` 以当前 `draft_profile_json` 为草稿真相,优先读取 `settingText`、`creatorIntent.rawSettingText`、`creatorIntent.worldHook`、`worldHook`、`anchorContent.worldPromise(.hook)`、`summary`、`name/title`,最后才回退 `seed_text`。
|
||||
- 验证:`cargo test -p module-custom-world publish_setting_text --manifest-path server-rs\Cargo.toml`;`cargo check -p spacetime-module --manifest-path server-rs\Cargo.toml`。
|
||||
- 关联:`server-rs/crates/module-custom-world/src/application.rs`、`server-rs/crates/spacetime-module/src/custom_world.rs`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## RPG 已发布结果页进入世界不能重复 publish_world
|
||||
|
||||
- 现象:RPG 草稿发布成功后,按钮文案已变为“进入世界”,但点击仍请求 `POST /api/runtime/custom-world/agent/sessions/{sessionId}/actions` 且 payload 为 `{"action":"publish_world"}`,后端返回 `publish_world is only available during object_refining, visual_refining, long_tail_review or ready_to_publish`。
|
||||
- 原因:按钮文案依据 agent session `stage === 'published'` 切换,但点击处理仍走发布协调路径;如果前端只依赖草稿同步回包判断是否已发布,回包为空或缺少可进入状态时就会继续重复发送 `publish_world`。
|
||||
- 处理:进入世界协调器接收当前 agent session stage;当 stage 已为 `published` 时,只调用 `result-view` 回读已发布 profile 并启动运行态,不再调用 `sync_result_profile` 或 `publish_world`。
|
||||
- 验证:`npm run test -- src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx`;确认已发布场景下 `syncAgentDraftResultProfile` 与 `executePublishWorld` 均未被调用。
|
||||
- 关联:`src/components/rpg-entry/useRpgCreationEnterWorld.ts`、`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## RPG 点击启动黑屏 / 默认 profile 先查 profile 归一化和摘要覆盖
|
||||
|
||||
- 现象:作品详情点击“启动”后页面切到 RPG runtime,但用户只看到黑屏、空白,或进入默认角色 / 默认 profile;从作品详情点“作品编辑”后开局 CG、封面、角色图、技能动作预览、初始物品图标或场景背景图丢失;DevTools 里可能同时看到旧自动存档 `/api/runtime/save/snapshot` 被主动 cancel。
|
||||
- 原因:`/custom-world-library` / `/custom-world-gallery` 详情接口可能返回历史或摘要式 `profile`,缺少 `playableNpcs`、`storyNpcs`、`landmarks`、`attributeSchema` 等运行态字段;前端 client 若直接把该对象传给 runtime,角色选择首屏会在 `buildCustomWorldPlayableCharacters(profile)` 或后续属性解析处抛错。另一类常见原因是详情接口已回读完整 profile 后,`savedCustomWorldEntries` 里的列表摘要又把 `selectedDetailEntry` 覆盖回空 profile,导致启动或编辑时只剩卡片摘要。发布 / 回读 result-view 若返回字段更少的旧视图,也可能把当前结果页已编辑资产降级掉。`save/snapshot (canceled)` 通常是切 runtime 或卸载时 `AbortController` 取消旧自动存档,不是黑屏根因。
|
||||
- 处理:RPG 入口作品库 client 在所有返回 `CustomWorldLibraryEntry<CustomWorldProfile>` 的接口边界统一调用 `normalizeCustomWorldProfileRecord`,并用 `profileId/worldName/subtitle/summaryText` 补齐旧数据缺字段;详情页已拿到运行态字段或资产槽位更多的完整 profile 时,不允许列表摘要覆盖当前详情;同一 `profile.id` 下,正式进入世界发布 / 回读不得用字段更少的后端旧视图降级当前结果页 profile。`normalizeCustomWorldProfileRecord` 必须近似无损保留 `cover`、`openingCg`、`camp.narrativeResidues`、`landmark.visualDescription/narrativeResidues`、`skills[].actionPreviewConfig`、`initialItems[].iconSrc`、`attributeSchema`、角色 `attributeProfile` 和 `sceneChapterBlueprints[].acts[]` 的背景与结构字段;只有背景资产的 act 也不能被过滤。角色选择页对角色生成异常或空数组回退默认角色,并保留返回按钮/轻量空态;顶层 runtime 懒加载 fallback 不使用纯 `null`。
|
||||
- 验证:`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "creation hub published work start uses loaded detail profile instead of library summary|creation hub published work edit keeps loaded detail profile assets instead of library summary"`;`npm run test -- src/data/customWorldLibrary.test.ts -t "保留结果页封面和关键图片资产槽位|近似无损保留编辑态和运行态结构字段|保留只有背景资产的场景幕"`;`npm run test -- src/components/rpg-entry/useRpgEntryAgentDraftRestore.test.tsx -t "默认封面和角色编辑结构差异也不能被列表摘要覆盖"`;`npm run test -- src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx -t "正式进入世界回读结果页字段更少时不降级当前完整 profile"`;`npm run typecheck`。
|
||||
- 关联:`src/components/rpg-entry/useRpgEntryLibraryDetail.ts`、`src/components/rpg-entry/useRpgCreationEnterWorld.ts`、`src/data/customWorldLibrary.ts`、`src/services/rpg-entry/rpgEntryLibraryClient.ts`、`src/components/rpg-entry/RpgEntryCharacterSelectView.tsx`、`src/App.tsx`、`src/components/rpg-runtime-shell/RpgRuntimeShell.tsx`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## RPG 战后一轮战斗后卡在观察/试探/调息先查 post-battle finalization
|
||||
|
||||
- 现象:RPG 一轮战斗胜利后,运行态只显示默认 `观察周围迹象 / 主动出声试探 / 原地调息`,这些按钮只有文字反馈;点“继续冒险”后又回到同样选项,点探索只播退场/进场动画,场景和剧情不推进。
|
||||
- 原因:终局战斗 action 如果只走通用 `resolve_story_runtime_action` fallback,而没有在后端调用 `finalize_post_battle_resolution(...)`,就不会持久写入 `story_continue_adventure`、`deferredOptions` 和下一幕 `currentSceneActState`。另外旧 bootstrap 快照可能只有 `connectedSceneIds` / `forwardSceneId`、没有 `connections`,战后选项生成若只读 `connections` 也会退回 `idle_explore_forward` 循环。
|
||||
- 处理:`module-runtime-story` 在 story action 投影后统一调用 post-battle finalization;`idle_explore_forward` 清理战斗态并生成下一段遭遇预览;`idle_travel_next_scene` / `camp_travel_home_scene` 由后端写入新 `currentScenePreset`、场景 act 状态、遭遇预览和 `runtimeStats.scenesTraveled`。前端只负责播放继续、探索和切场景动画,不承接正式剧情推进真相。
|
||||
- 验证:`cargo test -p module-runtime-story --manifest-path server-rs\Cargo.toml battle_tests -- --nocapture` 应覆盖战斗终局持久化 `story_continue_adventure`、`deferredOptions`、下一幕 act,以及 `idle_travel_next_scene` 真正切换场景。
|
||||
- 关联:`server-rs/crates/module-runtime-story/src/session_action.rs`、`server-rs/crates/module-runtime-story/src/post_battle.rs`、`server-rs/crates/module-runtime-story/src/battle_tests.rs`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## RPG 战斗飘字不要只靠低对比红绿文字
|
||||
|
||||
- 现象:暗色或棕黑噪声背景下,战斗伤害飘字看起来像背景纹理,尤其是远端敌人头顶的小号红字几乎不可读。
|
||||
- 原因:旧 `CombatFloatingNumber` 主要依赖 `text-rose-200` / `text-emerald-200` 和 8px 同色 glow;在暗红、棕黑、像素噪声背景上,颜色与背景混在一起,1px 深色描边也不足以形成轮廓。
|
||||
- 处理:飘字本体使用高亮近白文字、小面积半透明深色底、明显深色描边和多层黑色阴影;只增强瞬时反馈,不新增说明面板,不遮挡主要战斗画面。
|
||||
- 验证:`npm run test -- src/components/game-canvas/GameCanvasEntityLayer.test.tsx` 覆盖伤害/治疗飘字样式策略;运行态截图中敌方头顶伤害数字应能在暗场景上辨认。
|
||||
- 关联:`src/components/game-canvas/GameCanvasEntityLayer.tsx`、`docs/【项目基线】当前产品与工程约束-2026-05-15.md`。
|
||||
|
||||
## 弹窗里复用 CreativeImageInputPanel 要保留画面卡高度
|
||||
|
||||
- 现象:拼图草稿结果页的关卡详情弹窗中仍能看到“画面图”标题、画面描述和生成按钮,但实际画面图卡片视觉上消失。
|
||||
- 原因:`CreativeImageInputPanel` 内部依赖 `flex-1`、`h-full` 和 `max-h-full` 撑开正方形画面卡;放进弹窗里的普通 `section` 后,父级没有可计算高度,卡片会被压到不可见。
|
||||
- 处理:通用画面卡 `puzzle-image-upload-card` 保持 `aspect-square` 的同时设置稳定 `min-height`,让入口页和关卡详情弹窗都能显示主图/上传区。
|
||||
- 验证:`npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx -t "opens an independent level detail dialog"` 应断言关卡详情中的 `.puzzle-image-upload-card` 具备最小高度类;`npm run test -- src/components/common/CreativeImageInputPanel.test.tsx` 应继续通过。
|
||||
- 关联:`src/components/common/CreativeImageInputPanel.tsx`、`src/components/puzzle-result/PuzzleResultView.tsx`、`src/components/puzzle-result/PuzzleResultView.test.tsx`。
|
||||
|
||||
## Windows provision 下载截断要断点续传而不是回退目标机下载
|
||||
|
||||
- 现象:`Genarrative-Server-Provision` 在 `Download Provision Tool Archives` 阶段出现 `curl: (18) end of response ... bytes missing`,常见于 `otelcol-contrib_0.151.0_linux_amd64.tar.gz` 等 GitHub release 大文件。
|
||||
@@ -189,7 +263,7 @@
|
||||
|
||||
## 陶泥儿 logo 生图慢请求先缩短 prompt 并单张串行
|
||||
|
||||
- 现象:使用 VectorEngine `gpt-image-2-all` 生成陶泥儿 logo 概念图时,部分 prompt 会超过 10 分钟仍无响应,或返回 `429` / `当前分组上游负载已饱和`;同一批次里后续图片会被前面的慢请求拖住。
|
||||
- 现象:使用 VectorEngine `gpt-image-2` 生成陶泥儿 logo 概念图时,部分 prompt 会超过 10 分钟仍无响应,或返回 `429` / `当前分组上游负载已饱和`;同一批次里后续图片会被前面的慢请求拖住。
|
||||
- 原因:复杂抽象 logo prompt 同时包含品牌解释、禁用元素、中文结构和多重隐喻时,上游排队与生成时长不稳定;并发或批量运行会放大单条慢请求的影响。
|
||||
- 处理:先 `--dry-run` 看请求体;真实生成时优先短 prompt、单一造型、单张串行或小批量。失败后不要反复重试同一长 prompt,先压缩到“一个主体 + 一个负形 + 颜色 + 禁用文字/播放键/聊天气泡”再跑。联系表中的中文标签不要通过 PowerShell 管道内联 Python 写入,容易因编码链路显示为问号,可改用英文标签或脚本文件方式。
|
||||
- 验证:生成文件落在 `public/branding/taonier-logo-*/`,用 Pillow 检查图片尺寸和非空;执行 `node --check scripts/generate-taonier-logo-concepts.mjs`、`npm run check:encoding`、`git diff --check`。
|
||||
@@ -223,11 +297,11 @@
|
||||
|
||||
- 现象:点击生成抓大鹅草稿后,页面只提示“服务暂不可用”,或者本地 `npm run dev:api-server` 看似启动但生成接口不可用。
|
||||
- 原因:配置缺失类错误通常在后端 `error.details.reason` 中给出具体缺项,前端如果只读 `details.message` 会吞掉原因;本地只配置 `ALIYUN_OSS_BUCKET` / `ALIYUN_OSS_ENDPOINT` 时,旧逻辑还会在启动期构造空 AccessKey 的 OSS 客户端并失败。抓大鹅新链路仍是 2D 生图切割,不需要也不应回退 Rodin/GLB。
|
||||
- 处理:前端 API 错误展示优先读取 `details.reason`,再读取 `details.message`,避免底层 `error sending request` 覆盖真正可操作的配置或网络原因;`api-server` 只有在 OSS 四件套齐全时初始化 OSS 客户端,部分缺失只记 warning 并让具体 generated 上传/换签接口返回 `OSS 未完成环境变量配置`。抓大鹅素材、封面和背景生成在调用 VectorEngine 前先预检 OSS,并通过 `details.missingEnv` 列出缺项;真实生成需补齐 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和完整 `ALIYUN_OSS_*` 四件套。抓大鹅 `5*5` 素材图提示词还必须要求相邻物体主体至少保留 `1/4` 单格宽度空白间距,避免切割后相邻格内容污染。
|
||||
- 处理:前端 API 错误展示优先读取 `details.reason`,再读取 `details.message`,避免底层 `error sending request` 覆盖真正可操作的配置或网络原因;`api-server` 只有在 OSS 四件套齐全时初始化 OSS 客户端,部分缺失只记 warning 并让具体 generated 上传/换签接口返回 `OSS 未完成环境变量配置`。抓大鹅素材、封面和背景生成在调用 VectorEngine 前先预检 OSS,并通过 `details.missingEnv` 列出缺项;真实生成需补齐 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和完整 `ALIYUN_OSS_*` 四件套。抓大鹅 UI spritesheet 和物品 spritesheet 的提示词必须要求纯绿色绿幕背景,后端上传 OSS 前统一扣成透明 PNG,避免运行态 alpha 连通域解析失败。
|
||||
- 验证:`npm run test -- src/services/apiClient.test.ts` 覆盖 `details.reason`;`cargo test -p api-server state --manifest-path server-rs/Cargo.toml` 覆盖半配置 OSS 不阻断启动;`npm run dev:api-server` 后按实际 `GENARRATIVE_API_PORT` 请求 `/healthz`,不要默认打 `3100`。
|
||||
- 关联:`packages/shared/src/http.ts`、`server-rs/crates/api-server/src/state.rs`、`docs/technical/API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md`、`docs/technical/AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md`。
|
||||
|
||||
2026-05-14 补充:抓大鹅“物品素材 sheet”已改用 VectorEngine Gemini `gemini-3-pro-image-preview` 原生 `generateContent`,真实生成读取 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;封面和 `9:16` 背景图走 VectorEngine `/v1/images/generations`,`1:1` 容器 UI 走 VectorEngine `/v1/images/edits` multipart 参考图链路。排查素材 sheet 时看请求路径是否为 `/v1beta/models/gemini-3-pro-image-preview:generateContent?key=...`,响应图片在 `candidates[].content.parts[].inlineData.data` / `inline_data.data`,不要再按 APIMart `/images/generations` 或 `/tasks/{task_id}` 排查。
|
||||
2026-05-22 补充:抓大鹅“物品 spritesheet”不再按旧 Gemini `generateContent` / `5*5` sheet 路径排查;当前链路先用 `gpt-image-2` 无参考图生成 `9:16` 关卡整图,再以该关卡整图作为 multipart `image` 参考并发编辑生成 `1K 1:1` UI spritesheet、`1K 9:16` 背景图和 `2K 1:1` 物品 spritesheet。UI 与物品 spritesheet 都要求纯绿色绿幕背景,上传 OSS 前通过后端透明化处理写入真实 alpha PNG。
|
||||
|
||||
## 抓大鹅发布按钮要先开发布面板,封面编辑收口到发布面板内
|
||||
|
||||
@@ -321,7 +395,7 @@
|
||||
## 儿童动作 Demo 绘本风资源未生成先查 VectorEngine 配置
|
||||
|
||||
- 现象:`/child-motion-demo` 已经呈现绘本草地风格,但 `public/child-motion-demo/picture-book-grass-stage.png`、`picture-book-grass-floor.png`、`picture-book-ground-ring.png`、`picture-book-character-outline.png`、`picture-book-ui-panel.png` 或 `picture-book-ui-button.png` 不存在,Network 里对应图片返回 404,或运行 `npm run assets:child-motion-demo -- --live` 返回缺少 VectorEngine 配置。
|
||||
- 原因:儿童动作 Demo 的真实背景、地面、UI、地面指示环和角色轮廓资源都使用 VectorEngine `gpt-image-2-all` 生成,脚本只读取 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和可选 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;仓库内不能提交真实 key,缺配置时页面只能使用 CSS 草地绘本兜底。
|
||||
- 原因:儿童动作 Demo 的真实背景、地面、UI、地面指示环和角色轮廓资源都使用 VectorEngine `gpt-image-2` 生成,脚本只读取 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和可选 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;仓库内不能提交真实 key,缺配置时页面只能使用 CSS 草地绘本兜底。
|
||||
- 处理:在本地私密环境补齐 `VECTOR_ENGINE_BASE_URL=https://api.vectorengine.ai` 与 `VECTOR_ENGINE_API_KEY`,不要把 key 写入 Git;先运行 `npm run assets:child-motion-demo -- --dry-run` 核对 prompt,再运行 `npm run assets:child-motion-demo -- --live` 或 `npm run assets:child-motion-demo -- --live --only ui-panel` 等小批量命令生成资源。透明资源的品红底源图写入 `tmp/child-motion-demo-assets/`,不要把源图或预览图放入 `public/child-motion-demo/` 作为正式资产。
|
||||
- 验证:生成后确认 `public/child-motion-demo/` 只保留页面引用的最终 PNG,重新打开 `/child-motion-demo` 可看到真实绘本草地背景、地面、圆环、角色轮廓和 UI 资源;`npm run check:encoding` 仍通过。
|
||||
- 关联:`scripts/generate-child-motion-demo-assets.mjs`、`src/index.css`、`docs/technical/CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md`。
|
||||
@@ -345,8 +419,8 @@
|
||||
## GPT-image-2 不再读 APIMart 图片配置
|
||||
|
||||
- 现象:配置了 `APIMART_BASE_URL` / `APIMART_API_KEY` 后,RPG、拼图或方洞的 GPT-image-2 生图仍返回缺配置,或请求体里还出现 `official_fallback` / `image_urls`。
|
||||
- 原因:2026-05-09 后 GPT-image-2 图片生成已切到 VectorEngine `gpt-image-2-all`,APIMart 只保留给创意 Agent 的 `gpt-5` Responses 文本/多模态链路。
|
||||
- 处理:为图片生成配置 `VECTOR_ENGINE_BASE_URL=https://api.vectorengine.ai`、`VECTOR_ENGINE_API_KEY`、`VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;排查请求体时确认路径为 `/v1/images/generations`、模型为 `gpt-image-2-all`、参考图字段为 `image`。
|
||||
- 原因:2026-05-21 后 GPT-image-2 图片生成按 VectorEngine 创建/编辑接口分流,APIMart 只保留给创意 Agent 的 `gpt-5` Responses 文本/多模态链路。
|
||||
- 处理:为图片生成配置 `VECTOR_ENGINE_BASE_URL=https://api.vectorengine.ai`、`VECTOR_ENGINE_API_KEY`、`VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;排查请求体时确认无参考图路径为 `/v1/images/generations`、有参考图路径为 `/v1/images/edits`,模型为 `gpt-image-2`。
|
||||
- 验证:运行 `cargo test -p api-server openai_image --manifest-path server-rs/Cargo.toml` 和相关玩法图片生成测试;真实联调只在本地私密环境放置 VectorEngine key。
|
||||
- 关联:`docs/technical/VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md`、`server-rs/crates/api-server/src/openai_image_generation.rs`。
|
||||
|
||||
@@ -366,19 +440,19 @@
|
||||
- 验证:后端单测覆盖 `build_puzzle_levels_with_primary_update` 和 `apply_generated_puzzle_candidates_to_session_snapshot`;结果页重新生成应在未重新上传时继续带入 `level.pictureReference`。
|
||||
- 关联:`server-rs/crates/api-server/src/puzzle.rs`、`src/components/puzzle-result/PuzzleResultView.tsx`。
|
||||
|
||||
## 拼图图生图仍不像参考图时先看是否走了 edits
|
||||
## 拼图参考图不像时先看 edits multipart image
|
||||
|
||||
- 现象:Network payload 已带 `referenceImageSrc`,但 VectorEngine 生成结果仍明显不像上传图。
|
||||
- 原因:`gpt-image-2-all` 的 `/v1/images/generations` 更适合纯文生图;有参考图且需要重绘时应切到 `/v1/images/edits` 的 multipart 图生图接口。
|
||||
- 处理:`referenceImageSrc` 存在且 `aiRedraw = true` 时直接走 edits,prompt 仍保留参考图强约束;入口页关闭 AI 重绘时直接应用上传图,不调用图片生成;前端把参考图压到单边 1024 内,后端解析后拒绝超过 8MB 的参考图字节。
|
||||
- 验证:后端单测应覆盖 `images/edits` 路由、`b64_json` 响应解码和参考图强提示;真实联调先看日志里是否命中 `拼图 VectorEngine 图片编辑 HTTP 返回`。
|
||||
- 原因:参考图只在 `aiRedraw = true` 时由后端解析并传给 `gpt-image-2` `/v1/images/edits` 的 multipart `image` part;若前端没传 `referenceImageSrc`、后端解析失败或 prompt 缺少参考图强约束,生成会退化为纯文生图。
|
||||
- 处理:`referenceImageSrc` 存在且 `aiRedraw = true` 时走 edits multipart,prompt 保留参考图强约束;入口页关闭 AI 重绘时直接应用上传图,不调用图片生成;前端把参考图压到单边 1024 内,后端解析后拒绝超过 8MB 的参考图字节。
|
||||
- 验证:后端单测应覆盖 `/v1/images/edits` 路由、`b64_json` 响应解码和参考图强提示;真实联调看日志里是否命中 `拼图 VectorEngine 图片编辑 HTTP 返回`。
|
||||
- 关联:`server-rs/crates/api-server/src/puzzle.rs`、`src/services/puzzleReferenceImage.ts`、`docs/technical/VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md`。
|
||||
|
||||
## 拼图 edits 报 error sending request 先看网络分类
|
||||
|
||||
- 现象:拼图有参考图时返回 `拼图图片生成失败:创建拼图 VectorEngine 图片编辑任务失败:error sending request for url (https://api.vectorengine.ai/v1/images/edits)`,后端没有 `拼图 VectorEngine 图片编辑 HTTP 返回` 日志。
|
||||
- 原因:这是 `reqwest` 在 `send()` 阶段失败,尚未收到 VectorEngine HTTP 响应;常见原因是服务器网络 / DNS / 防火墙 / 代理问题,或上游网关中断 multipart 连接。
|
||||
- 处理:查看错误响应 `details.reason/source/connect/body/timeout/endpoint` 和 `拼图 VectorEngine 请求发送失败` 日志。拼图图片客户端已强制 HTTP/1.1,降低 multipart HTTP/2 兼容风险;若 `connect=true` 先查网络出口,若 `body=true` 先查参考图大小和 multipart 发送。
|
||||
- 处理:查看错误响应和 `拼图 VectorEngine 图片编辑` 相关日志;若请求发送阶段失败,先查网络出口、DNS、防火墙、代理、参考图大小和 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`。
|
||||
- 验证:`curl --http1.1 -i -X POST https://api.vectorengine.ai/v1/images/edits -H "Authorization: Bearer invalid" -F "model=gpt-image-2" -F "prompt=test" -F "n=1" -F "size=1024x1024" -F "image=@public/match3d-background-references/pot-fused-reference.png;type=image/png"` 至少应返回 HTTP `401`,说明域名、TLS、路径和 multipart 上传可达;执行 `cargo test -p api-server puzzle_vector_engine --manifest-path server-rs/Cargo.toml`。
|
||||
- 关联:`server-rs/crates/api-server/src/puzzle.rs`、`docs/technical/VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md`、`docs/technical/API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md`。
|
||||
|
||||
@@ -409,17 +483,41 @@
|
||||
## 拼图草稿生成 180 秒后 502/504 先查 VectorEngine 超时与前端重试
|
||||
|
||||
- 现象:点击“生成拼图游戏草稿”后,`POST /api/runtime/puzzle/agent/sessions/{sessionId}/actions` 等待约 180 秒返回 `502 Bad Gateway` 或 `504 Gateway Timeout`;钱包流水里同一 session 可能出现连续两组 `puzzle_initial_image` 扣费后退款。
|
||||
- 原因:首图生成走 VectorEngine `gpt-image-2-all`,默认 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=1000000`;若上游在该窗口内未返回,后端退款并返回超时错误。旧前端 action 写请求会对 502/503/504 自动重试一次,导致同一次点击重复触发生图与扣退费。
|
||||
- 原因:首图生成走 VectorEngine `gpt-image-2`,默认 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=1000000`;若上游在该窗口内未返回,后端退款并返回超时错误。旧前端 action 写请求会对 502/503/504 自动重试一次,导致同一次点击重复触发生图与扣退费。
|
||||
- 处理:拼图/创作 Agent 的 `executeAction` 默认不做前端自动重试;后端将 VectorEngine / 图片请求超时映射为 `504 Gateway Timeout`,`error.details.provider=vector-engine` 且 `timeout=true`。真实排障按日志同一 `session_id` 查 `拼图 VectorEngine 图片生成 HTTP 返回` 是否缺失,以及钱包流水扣费到退款的时间差是否接近 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`。
|
||||
- 验证:运行 `npm run test -- src/services/creation-agent/creationAgentClientFactory.test.ts src/services/apiClient.test.ts`、`cargo test -p api-server puzzle_vector_engine --manifest-path server-rs/Cargo.toml`,真实联调重启 `npm run dev:api-server` 后检查 `/healthz`。
|
||||
- 关联:`src/services/creation-agent/creationAgentClientFactory.ts`、`server-rs/crates/api-server/src/puzzle.rs`、`docs/technical/API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md`。
|
||||
|
||||
## 开局 CG 故事板生图失败先查 VectorEngine 请求预算和旧进程
|
||||
|
||||
- 现象:RPG 结果页点击开局 CG 后,`POST /api/runtime/custom-world/opening-cg` 在较长等待后返回“开局 CG 故事板生成失败:创建图片生成任务失败:error sending request for url (https://api.vectorengine.ai/v1/images/generations)”。
|
||||
- 原因:该故事板会把角色图和首幕背景图作为参考图一起传给 VectorEngine `gpt-image-2-all`,请求体和上游生成耗时都比普通单图更大;若运行中的 `api-server` 仍沿用旧 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`,或者参考图过大,会在请求发送/等待阶段被 reqwest 截断。日志里 `timeout=false connect=false request=true body=false source=client error (SendRequest)` 表示还没拿到上游 HTTP 响应,通常优先怀疑大 JSON 请求体、上游网关中断或 HTTP 协议兼容,而不是业务响应解析失败。直接请求 VectorEngine 若无效 token 可快速返回 401,不能据此判断真实生图不会超时。
|
||||
- 处理:开局 CG 参考图入参先压到单边 768 的 JPEG;`/v1/images/generations` 保持 reqwest 默认 HTTP 协商,只有 multipart `/v1/images/edits` 单独强制 HTTP/1.1。后端图片 helper 将 `request_body_bytes`、每张参考图 Data URL 长度、`timeout/connect/body/source/rootSource/sourceChain/endpoint` 分类写入日志和 `error.details`,前端优先展示 `details.reason`。修改 `.env.secrets.local` 后必须重启 `api-server`,`npm run dev` 终端用 `rs api-server`,否则旧进程仍按旧超时运行。
|
||||
- 验证:分别运行 `cargo test -p api-server custom_world_ai --manifest-path server-rs/Cargo.toml` 和 `cargo test -p api-server openai_image_generation --manifest-path server-rs/Cargo.toml`;真实联调重启后再触发开局 CG,若仍失败看返回的 `details.reason/source/rootSource/sourceChain/timeout/connect/body/endpoint` 和 `logs/api-server/` 同一 request_id。
|
||||
- 关联:`server-rs/crates/api-server/src/custom_world_ai.rs`、`server-rs/crates/api-server/src/custom_world_ai/opening_cg.rs`、`server-rs/crates/api-server/src/openai_image_generation.rs`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## 开局 CG 成功后又变空白要保留 profile.openingCg
|
||||
|
||||
- 现象:RPG 结果页里的开局 CG 成功显示一瞬后,窗口又退回空白占位。
|
||||
- 原因:`openingCg` 只存在于结果页 profile 槽位,如果父层在 `onProfileChange` 后重新同步了 profile,却经过 `normalizeCustomWorldProfileRecord` 或作品库写回时丢掉 `openingCg`,预览就会从视频 / 故事板回退为空白。
|
||||
- 处理:`src/data/customWorldLibrary.ts` 的 profile 归一化必须透传 `openingCg`;结果页和父层后续同步都应把它当作受控资产槽位,而不是临时 UI 状态。
|
||||
- 验证:`npm run test -- src/data/customWorldLibrary.test.ts src/components/CustomWorldResultView.test.tsx`,确认生成后即使父层做一次归一化回写,开局 CG 仍继续显示。
|
||||
- 关联:`src/data/customWorldLibrary.ts`、`src/components/rpg-creation-result/RpgCreationResultViewImpl.tsx`、`src/components/CustomWorldEntityCatalog.tsx`。
|
||||
|
||||
## RPG 发布报 legacy_result_profile_json 非法先查 null 兼容
|
||||
|
||||
- 现象:RPG 结果页发布动作返回 `UPSTREAM_ERROR`,SpacetimeDB details 里是 `custom_world.compile.legacy_result_profile_json 不是合法 JSON object`。
|
||||
- 原因:`publish_world` 前端契约只要求 `{ action: 'publish_world' }`;`ExecuteCustomWorldAgentActionRequest.legacy_result_profile` 是可选字段,经 HTTP / serde / SpacetimeDB payload 传递时可能显式成为 JSON `null`。旧的编译器只接受 object 或缺省,把 `Some("null")` 当成非法 legacy JSON。
|
||||
- 处理:`module-custom-world` 的 optional JSON object 解析要把 `null` 视为未提供,仍拒绝数组、字符串、数字和坏 JSON;正式发布继续以 session `draft_profile_json` 为草稿真相。
|
||||
- 验证:`cargo test -p module-custom-world published_profile_compile --manifest-path server-rs/Cargo.toml`。
|
||||
- 关联:`server-rs/crates/module-custom-world/src/application.rs`、`server-rs/crates/spacetime-module/src/custom_world.rs`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## 本地脚本调 VectorEngine 生图卡住先区分 fetch 首部超时
|
||||
|
||||
- 现象:用 Node `fetch` 直接请求 `POST /v1/images/generations`,已经设置较长的 AbortController 超时,但仍在约 180 到 300 秒后抛 `AbortError`、`TypeError: fetch failed` 或 `UND_ERR_HEADERS_TIMEOUT`;同一 prompt 改用原生 `https.request` 可以在较短时间内成功返回图片。
|
||||
- 原因:Node/Undici 的默认 headers timeout 可能早于业务脚本期望的长生图等待窗口触发,表现上容易被误判成 VectorEngine 上游本身超时。
|
||||
- 处理:长期脚本优先复用后端 reqwest 或项目已有生成脚本;临时本地工具若必须用 Node,可改用原生 `http`/`https.request` 并显式设置 socket timeout,或为 Undici 单独配置 headers timeout。仍需隐藏 `VECTOR_ENGINE_API_KEY`,只报告配置是否存在。
|
||||
- 验证:同一 `gpt-image-2-all` 请求体、同一环境变量下,原生 HTTP 请求能返回 `url` / `b64_json` 并落盘;失败时错误里能区分请求发送、首部等待、下载和解码阶段。
|
||||
- 验证:同一 `gpt-image-2` 请求体、同一环境变量下,原生 HTTP 请求能返回 `url` / `b64_json` 并落盘;失败时错误里能区分请求发送、首部等待、下载和解码阶段。
|
||||
- 关联:`.codex/skills/gpt-image-2-apimart/SKILL.md`、`server-rs/crates/api-server/src/openai_image_generation.rs`。
|
||||
|
||||
## 旧后端路线文档造成判断漂移
|
||||
@@ -852,7 +950,7 @@
|
||||
|
||||
- 现象:修改抓大鹅素材时容易沿用旧 Rodin/GLB 方案,导致新草稿生成耗时变长、进度停在模型阶段,或运行态等待不存在的 GLB。
|
||||
- 原因:仓库里保留了 Hyper3D 通用代理和历史模型字段,旧文档也曾要求草稿阶段同步生成 GLB。当前产品口径已经改为 2D 多视角素材。
|
||||
- 处理:新 `match3d_compile_draft` 与批量新增只生成 2D 图片:每个物品 5 个视角,单张 1K 素材图固定 5x5,最多承载 5 个物品,一行对应一个物品,不足 5 个物品也补齐到完整 5 行;超过 5 个物品自动分批并行生图。素材图 prompt 固定要求纯绿色绿幕背景,切割前先把绿幕处理为透明 alpha,再做格内内容前景边界校准并带留白,避免固定内缩切掉贴近格线的主体。`generatedItemAssets[].status` 使用 `image_ready`,发布校验看 `imageViews[]` 或首图引用。`generated-models` 仅用于历史外部模型链接转存,不能作为新生产链路。
|
||||
- 处理:新 `match3d_compile_draft` 与批量新增只生成 2D 图片:每个物品 5 个形态,单张 `2K 1:1` 物品 spritesheet 固定 `10*10`,每行承载两种物品、每种五个形态,单张最多承载 20 种物品。素材图 prompt 固定要求纯绿色绿幕背景,上传 OSS 前先把整张 spritesheet 绿幕处理为透明 alpha,再由运行态和编辑器按 alpha 连通域解析;`generatedItemAssets[].status` 使用 `image_ready`,发布校验看 `imageViews[]`、首图引用或可解析的物品 spritesheet。`generated-models` 仅用于历史外部模型链接转存,不能作为新生产链路。
|
||||
- 验证:`cargo test -p api-server match3d --manifest-path server-rs/Cargo.toml`、`npm run test -- src\services\miniGameDraftGenerationProgress.test.ts src\components\match3d-result\Match3DResultView.test.tsx src\components\match3d-runtime\Match3DRuntimeShell.test.tsx`。
|
||||
- 关联:`server-rs/crates/api-server/src/match3d.rs`、`src/components/match3d-runtime/Match3DRuntimeShell.tsx`、`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
|
||||
@@ -888,11 +986,11 @@
|
||||
- 验证:执行 `npm run test -- src/components/match3d-runtime/Match3DRuntimeShell.test.tsx` 和 `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "Match3D runtime"`;浏览器 Network 中背景和容器 generated path 应先请求 `/api/assets/read-url` 换签,局内出现 `match3d-background-image` 和 `match3d-container-image` 对应图片。
|
||||
- 关联:`src/components/match3d-runtime/Match3DRuntimeShell.tsx`、`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`、`src/components/rpg-entry/rpgEntryWorldPresentation.ts`、`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
|
||||
## 抓大鹅容器参考图必须走 edits 并接管棋盘外观
|
||||
## 抓大鹅容器参考图必须进入 edits multipart image 并接管棋盘外观
|
||||
|
||||
- 现象:抓大鹅结果页看似有容器生成入口,但真实生成出的局内容器不像 `pot-fused-reference.png`,或进入试玩后仍被默认圆形锅壳、金色边框和径向底色覆盖/裁切。
|
||||
- 原因:`/v1/images/generations` 的 `image` 数组更适合弱参考文生图,难以稳定锁定大尺寸轻俯视容器构图;即使生成了容器图,如果运行态继续保留默认 `rounded-full` 锅壳和 `overflow-hidden`,生成图也会被默认视觉覆盖或裁掉。
|
||||
- 处理:抓大鹅 `1:1` 容器 UI 图必须用 VectorEngine `POST /v1/images/edits` multipart,参考 `public/match3d-background-references/pot-fused-reference.png` 的透明容器图作为 `image` part;该参考图属于后端生图协议输入,需通过 `include_bytes!` 编译进 `api-server`,不能在运行时按当前工作目录读取 `public/`。共享 GPT-image-2 HTTP client 承载 multipart 时强制 HTTP/1.1。`Match3DRuntimeShell` 在容器图换签并成功加载后,把棋盘外壳切为透明和 `overflow-visible`,只在容器缺失或加载失败时使用默认圆形容器。
|
||||
- 原因:容器参考图必须进入 `gpt-image-2` `/v1/images/edits` multipart `image` part,并配合强 prompt 锁定大尺寸轻俯视容器构图;即使生成了容器图,如果运行态继续保留默认 `rounded-full` 锅壳和 `overflow-hidden`,生成图也会被默认视觉覆盖或裁掉。
|
||||
- 处理:抓大鹅 `1:1` 容器 UI 图统一调用 VectorEngine `POST /v1/images/edits`,参考 `public/match3d-background-references/pot-fused-reference.png` 的透明容器图由后端作为 `image` part 上传;该参考图属于后端生图协议输入,需通过 `include_bytes!` 编译进 `api-server`,不能在运行时按当前工作目录读取 `public/`。`Match3DRuntimeShell` 在容器图换签并成功加载后,把棋盘外壳切为透明和 `overflow-visible`,只在容器缺失或加载失败时使用默认圆形容器。
|
||||
- 验证:执行 `cargo test -p api-server vector_engine --manifest-path server-rs/Cargo.toml`、`cargo test -p api-server match3d_background --manifest-path server-rs/Cargo.toml`、`npm run test -- src/components/match3d-runtime/Match3DRuntimeShell.test.tsx src/components/match3d-result/Match3DResultView.test.tsx`;真实联调看容器生成请求是否命中 `/v1/images/edits`,局内 `match3d-container-image` 是否渲染且 `match3d-board` 不再含默认 `rounded-full`。
|
||||
- 关联:`server-rs/crates/api-server/src/openai_image_generation.rs`、`server-rs/crates/api-server/src/match3d.rs`、`src/components/match3d-runtime/Match3DRuntimeShell.tsx`、`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
|
||||
@@ -970,9 +1068,9 @@
|
||||
|
||||
## 抓大鹅难度配置的物品种类和消除次数必须分离
|
||||
|
||||
- 现象:历史草稿选择标准 / 硬核难度后,系统可能把 `clearCount` 当成局内物品种类数量,导致标准需要 12 种、硬核需要 20/21 种;素材不足时发布或试玩行为不一致。
|
||||
- 现象:历史草稿选择标准 / 硬核难度后,系统可能把 `clearCount` 当成局内物品种类数量,导致标准需要 12 种、硬核需要 20/21 种;或者把第 11 到 20 个物品持久化为第 11 到 20 行,触发“系列素材图集持久化的行列索引必须落在 n*n 范围内”。
|
||||
- 原因:旧运行态把消除次数和类型数量绑在一起,结果页文案又同时展示“素材图片 / 局内类型”,导致前端、发布校验和 run start 口径不一致。
|
||||
- 处理:统一使用 `物品种类` 口径:轻松 3、标准 9、进阶 15、硬核 21;历史 `clearCount=20` 且难度为硬核的运行态按新硬核升为 21 组三消,避免 20 组却要求 21 种素材。发布前按 `image_ready` 且有 `imageViews[]` 或 `imageSrc/imageObjectKey` 的生成素材数量阻断不足难度;试玩不阻断,但通过 `itemTypeCountOverride` 自动降到已生成 2D 素材数量。重启从已有 run 快照反推实际物品种类,保持同一局重开不变。
|
||||
- 处理:生成和持久化固定使用 20 个物品素材;运行态物品种类口径为轻松 3、标准 9、进阶 15、硬核 20,历史 `clearCount=20` 且难度为硬核的运行态仍可升为 21 组三消,但类型池不超过 20。10*10 sheet 每行两种物品、每种五个形态,持久化行列为 `row = itemIndex / 2 + 1`、`col = itemIndex % 2 * 5 + viewIndex + 1`。发布前按 `image_ready` 且有 `imageViews[]` 或 `imageSrc/imageObjectKey` 的生成素材数量阻断不足难度;试玩不阻断,但通过 `itemTypeCountOverride` 自动降到已生成 2D 素材数量。重启从已有 run 快照反推实际物品种类,保持同一局重开不变。
|
||||
- 验证:`npm run test -- src\components\match3d-result\Match3DResultView.test.tsx`、`cargo test -p module-match3d --manifest-path server-rs\Cargo.toml`,涉及发布 reducer 时补跑 `cargo test -p spacetime-module match3d --manifest-path server-rs\Cargo.toml`。
|
||||
- 关联:`src/components/match3d-result/Match3DResultView.tsx`、`src/services/match3d-runtime/match3dRuntimeClient.ts`、`server-rs/crates/module-match3d/src/application.rs`、`server-rs/crates/spacetime-module/src/match3d.rs`、`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
|
||||
@@ -989,7 +1087,7 @@
|
||||
- 现象:抓大鹅生成的物品视角图裁剪后仍带白边,或者整块纯绿色绿幕背景没有被透明化,运行态看到绿色方块。
|
||||
- 原因:素材 sheet 可能是“每格内部绿幕、整张图外圈近白底”,内部绿幕不一定连通到 sheet 外边缘;旧 flood fill 只从外边缘找背景会漏掉这种绿幕块。白底抗锯齿如果不纳入抠像和边缘去污染,也会随裁剪输出成一圈白边。即使顺序已是先整张 sheet 去绿再裁剪,较厚的半透明或混色软绿边仍可能低于高置信绿幕阈值,被当作前景带进独立 PNG。
|
||||
- 处理:`api-server` 的 `slice_match3d_material_sheet` 必须先在整张 sheet 上做透明背景后处理:外边缘连通绿幕/近白底清 alpha,非连通但高置信纯绿块也清 alpha,沿整张 sheet 透明背景继续吃掉软绿边,边缘近白和绿幕抗锯齿做透明或去污染;同时保护不够纯的绿色主体像素。不要改成先裁剪单格再去绿。
|
||||
- 验证:`cargo test -p api-server match3d_material_sheet_slicing --manifest-path server-rs\Cargo.toml` 覆盖非连通绿幕、白边、贴边主体保留和固定 5x5 切图。
|
||||
- 验证:`cargo test -p api-server match3d_material_sheet_slicing --manifest-path server-rs\Cargo.toml` 覆盖非连通绿幕、白边、贴边主体保留和固定 `10*10` 切图;`cargo test -p api-server match3d_spritesheet_green_screen_postprocess_turns_background_transparent --manifest-path server-rs\Cargo.toml` 覆盖完整 spritesheet 上传前绿幕透明化。
|
||||
- 关联:`server-rs/crates/api-server/src/match3d.rs`、`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`。
|
||||
|
||||
## 抓大鹅物品详情大方格只做单张大图查看
|
||||
@@ -1056,6 +1154,14 @@
|
||||
- 验证:运行 `npm run test -- src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx -t "拖拽合并大块时底层单格不显示选中色块"`,并确认合并块拖拽时底层 `[data-piece-id]` 仍为 `puzzle-runtime-piece--merged`。
|
||||
- 关联:`src/components/puzzle-runtime/PuzzleRuntimeShell.tsx`、`src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx`、`docs/technical/PUZZLE_FORM_CREATION_FLOW_2026-04-29.md`。
|
||||
|
||||
## 推荐页嵌入拼图通关结算不要放在运行态内部 absolute 层
|
||||
|
||||
- 现象:推荐页里玩拼图通关后,结算面板只显示上半部分,排行榜、下一关按钮或相似作品卡被截断。
|
||||
- 原因:推荐页把运行态放在滑动作品卡的视觉区内,`platform-recommend-swipe-page`、`platform-recommend-swipe-card__visual` 和 `platform-recommend-runtime-viewport` 都是 `overflow: hidden`;拼图通关结算如果仍是运行态内部 `absolute inset-0` 弹层,就只能在半屏卡片区域里显示。
|
||||
- 处理:`PuzzleRuntimeShell` 在 `embedded` 模式下把通关结算层通过 portal 挂到 `document.body`,使用 `puzzle-runtime-modal-overlay--fixed` 页面级 fixed 浮层;非嵌入态继续使用运行态内部覆盖层。
|
||||
- 验证:运行 `npm run test -- src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx -t "推荐页嵌入拼图通关结算使用页面级浮层避免卡片裁剪"`,确认弹层不再位于 `.platform-recommend-runtime-viewport` 内。
|
||||
- 关联:`src/components/puzzle-runtime/PuzzleRuntimeShell.tsx`、`src/index.css`、`src/components/rpg-entry/RpgEntryHomeView.tsx`。
|
||||
|
||||
## 拼图历史图片列表不要把账号归属当图片名
|
||||
|
||||
- 现象:拼图创作页或结果页打开“选择历史图片”后,历史列表显示 `账号 user-1` 之类归属文案而不是图片名;`1713686400.000000Z` 这类时间显示为未知;选中后预览或生成参考图可能被怀疑不可用。
|
||||
@@ -1074,12 +1180,22 @@
|
||||
|
||||
## 拼图结果页局部生图不要污染草稿生成态
|
||||
|
||||
- 现象:拼图草稿已经生成完成后,在结果页重新生成 UI 背景或追加关卡生成图片,草稿页仍显示整卡“生成中”,点击草稿会回到生成过程页,无法查看已有结果;UI 背景生成中还会禁用“新增关卡”和关卡图生成。
|
||||
- 现象:拼图草稿已经生成完成后,在结果页重新生成关卡图片或追加关卡生成图片,草稿页仍显示整卡“生成中”,点击草稿会回到生成过程页,无法查看已有结果;关卡图片生成中还会禁用“新增关卡”和其它关卡详情编辑。
|
||||
- 原因:结果页局部 action 复用了全局 `isPuzzleBusy` / 持久化 `generationStatus=generating` 语义,作品架没有区分“初始草稿不可查看”和“已有结果上的局部关卡生成”。
|
||||
- 处理:作品架只在拼图没有可用封面、首关候选图或任一可查看关卡时才把 `generationStatus=generating` 解释为初始草稿生成;结果页 UI 背景和关卡图走 background action,不设置全局 busy,UI 背景只禁用自己的按钮;SpacetimeDB/API mapper 读写时把已有图片但状态仍是 `generating` 的历史关卡归一为 `ready`。
|
||||
- 处理:作品架只在拼图没有可用封面、首关候选图或任一可查看关卡时才把 `generationStatus=generating` 解释为初始草稿生成;结果页关卡图走 background action,不设置全局 busy,只标记对应关卡局部生成进度;SpacetimeDB/API mapper 读写时把已有图片但状态仍是 `generating` 的历史关卡归一为 `ready`。
|
||||
- 验证:`npm run test -- src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/puzzle-result/PuzzleResultView.test.tsx`、`cargo test -p api-server puzzle --manifest-path server-rs\Cargo.toml`。
|
||||
- 关联:`src/components/custom-world-home/creationWorkShelf.ts`、`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`、`src/components/puzzle-result/PuzzleResultView.tsx`、`server-rs/crates/api-server/src/puzzle/mappers.rs`、`server-rs/crates/spacetime-module/src/puzzle.rs`。
|
||||
|
||||
2026-05-22 补充:结果页关卡详情的“关卡测试”不能把单关 `draft` 传给父级再调用 `updatePuzzleWork`。`updatePuzzleWork` 会同步 `puzzle_work_profile.levels_json` 和 source session 草稿,单关快照会把整份多关卡草稿覆盖成一个关卡,退出重进后只剩最后测试的关卡且序号表现为第一关。修复口径是 `PuzzleResultView` 始终传完整 `syncedDraft`,额外用 `{ levelId }` 指定起始关卡;父级持久化完整 levels 后调用 `startLocalPuzzleRun(item, levelId)`。
|
||||
|
||||
## 拼图上传图关闭 AI 重绘不要走首图生图
|
||||
|
||||
- 现象:用户在拼图入口页或结果页关卡详情上传图片并关闭 AI 重绘后,生成页仍显示“生成拼图首图”,或者后端仍调用 `generate_puzzle_image_candidates` 生成第一张 1:1 候选图。
|
||||
- 原因:上传图直用路径应把 Data URL 或 `/generated-*` 历史图解析后持久化为 `sourceType=uploaded` 的正式候选,再继续生成 9:16 关卡画面、UI spritesheet 和纯背景;如果只把 `aiRedraw=false` 当作“不参考图片生成”,就会误走首图生成。
|
||||
- 处理:入口页用 payload 的 `aiRedraw` 写入生成页 metadata,`puzzleAiRedraw=false` 时进度跳过 `生成拼图首图`;后端 `compile_puzzle_draft` 和结果页 `generate_puzzle_images` 都在 `aiRedraw=false && referenceImageSrc 非空` 时走上传图直用候选。结果页关卡详情必须复用 `CreativeImageInputPanel`,不要把正式图当成可重绘参考图;本次上传或历史选择的图才显示 AI 重绘开关并可删除。
|
||||
- 验证:`npm run test -- src/services/miniGameDraftGenerationProgress.test.ts src/components/puzzle-result/PuzzleResultView.test.tsx`、`cargo test -p api-server puzzle_result_level_direct_upload_skips_cover_image_generation --manifest-path server-rs\Cargo.toml`。
|
||||
- 关联:`src/services/miniGameDraftGenerationProgress.ts`、`src/components/puzzle-agent/PuzzleAgentWorkspace.tsx`、`src/components/puzzle-result/PuzzleResultView.tsx`、`server-rs/crates/api-server/src/puzzle/draft.rs`、`server-rs/crates/api-server/src/puzzle/generation.rs`。
|
||||
|
||||
## Jenkins 数据库导入导出脚本先补 Node 工具链 PATH
|
||||
|
||||
- 现象:`Genarrative-Database-Import` 或 `Genarrative-Database-Export` 运行到迁移脚本时,`bash` 报 `node: command not found`,常见在日志里表现为某个 `sh` 块内第 61 行直接调用 `node` 失败。
|
||||
@@ -1135,3 +1251,11 @@
|
||||
- 处理:优先切换到拥有目标库权限的 SpacetimeDB 身份后重新运行 `npm run dev` 完成发布;若只是本地验证,可用 gitignored 的 `spacetime.local.json` 指向可发布的本地库。debug 构建的 `api-server` 对入口配置缺 procedure 会使用后端默认入口配置兜底,避免作品架因本地库漂移整块空白。
|
||||
- 验证:`curl.exe -i http://127.0.0.1:8082/api/creation-entry/config` 返回 `200` 且包含 `baby-object-match`;前端草稿页作品架重新渲染。
|
||||
- 关联:`server-rs/crates/api-server/src/state.rs`、`server-rs/crates/api-server/src/creation_entry_config.rs`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## 存档选择入口不要只藏在“玩过”弹窗里
|
||||
|
||||
- 现象:用户有 RPG / 拼图运行态存档,但平台底部 `草稿` Tab 只展示作品架,个人中心只有点击 `玩过` 后才可能看到“可继续”,导致看起来没有存档选择入口。
|
||||
- 原因:`/api/profile/save-archives` 已在入口 bootstrap 加载,但前端只把 `saveEntries` 注入 `ProfilePlayedWorksModal`;没有独立的存档入口。
|
||||
- 处理:个人中心 `常用功能` 必须保留 `存档` 快捷入口,点击后打开独立存档选择弹窗并复用 `SaveArchiveCard`;恢复仍走 `/api/profile/save-archives/{worldKey}`,拼图存档继续走拼图 resume 分支,RPG 走 `handleContinueGame(snapshot)`。
|
||||
- 验证:`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile page exposes save archive picker"`。
|
||||
- 关联:`src/components/rpg-entry/RpgEntryHomeView.tsx`、`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`、`src/components/rpg-entry/useRpgEntryBootstrap.ts`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
Reference in New Issue
Block a user