Prune stale docs and update .hermes content

Delete a large set of outdated documentation (many files under docs/ and .hermes/plans/, including audits, design, prd, technical, planning, assets, and todos). Update and consolidate .hermes content: refresh shared-memory pages (decision-log, development-workflow, document-map, pitfalls, project-overview, team-conventions) and several skills/references under .hermes/skills. Also modify AGENTS.md, README.md, UI_CODING_STANDARD.md, docs/README.md and .encoding-check-ignore. Purpose: clean up stale planning/audit material and keep current hermes documentation and related top-level docs in sync.
This commit is contained in:
2026-05-15 06:24:07 +08:00
parent 2eded08bc7
commit 3cb3efb4d0
708 changed files with 4033 additions and 142328 deletions

View File

@@ -1,252 +0,0 @@
# 宝贝识物创作发布实现方案 2026-05-11
## 1. 范围
本方案对应第 2 线程:创作发布线程。
本线程落地:
1. 创作入口配置;
2. 模板表单;
3. 本地草稿生成 service
4. 结果页;
5. 发布 payload 约束;
6. 本地 Demo 运行态;
7. 后端 image-2 / 作品持久化 / 运行态接口预留形状。
本阶段运行态先做浏览器本地 Demo并消费现有本地 mocap 动作数据源;正式硬件接口和摄像头调教在后续接口稳定后继续接入。
## 2. 前端接入点
新增玩法 ID
```text
baby-object-match
```
用户展示名:
```text
宝贝识物
```
工程接入文件:
1. `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
2. `src/components/platform-entry/platformEntryCreationTypes.ts`
3. `src/components/platform-entry/PlatformEntryCreationTypeModal.tsx`
4. `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
`src/config/newWorkEntryConfig.ts` 已迁移删除,不再作为入口事实源。`baby-object-match` 必须存在于 SpacetimeDB `creation_entry_type_config` 默认种子中,默认展示名为 `宝贝识物``visible=true``open=true``sortOrder=90`;前端只通过 `GET /api/creation-entry/config` 读取后端配置并在 `platformEntryCreationTypes.ts` 做展示派生。
`baby-object-match` 必须复用 `VITE_ENABLE_EDUTAINMENT_ENTRY` 开关;开关关闭时,创作类型弹层不展示 `宝贝识物`,创作页作品架不展示本地宝贝识物草稿或已发布作品卡,公开发现、搜索、详情、作品号和浏览历史也继续完全不可见。
新增阶段:
```text
baby-object-match-workspace
baby-object-match-generating
baby-object-match-result
baby-object-match-runtime
```
## 3. 契约
前端共享契约放在:
```text
packages/shared/src/contracts/edutainmentBabyObject.ts
```
核心字段:
1. `BabyObjectMatchDraft.templateId = "baby-object-match"`
2. `BabyObjectMatchDraft.templateName = "宝贝识物"`
3. `BabyObjectMatchDraft.themeTags` 必须包含精确 `寓教于乐`
4. `BabyObjectMatchItemAsset.generationProvider` 首版允许为 `vector-engine-gpt-image-2``placeholder`
5. `BabyObjectMatchDraft.visualPackage` 可选承载背景环境、UI 装饰框、礼物盒、篮子和烟雾弹出特效五类视觉资源;
6. `BabyObjectMatchPublishRequest.draft.themeTags` 发布前必须归一化补齐 `寓教于乐`
## 4. Service 边界
前端 service 放在:
```text
src/services/edutainment-baby-object/babyObjectMatchClient.ts
```
首版提供:
1. `createBabyObjectMatchDraft(payload)`
2. `saveBabyObjectMatchDraft(draft)`
3. `publishBabyObjectMatchWork(payload)`
4. `deleteLocalBabyObjectMatchDraft(profileId)`
5. `regenerateBabyObjectMatchDraftAssets(draft)`
6. `hasBabyObjectMatchPlaceholderAssets(draft)`
当前后端正式作品持久化接口未在本线程扩表落地,因此 service 仍使用本地 Demo 存储草稿和发布状态。由于 image-2 会返回多张 base64 PNG 大图,本地 Demo 草稿必须优先写入 IndexedDB `genarrative-edutainment-baby-object-drafts/drafts`,不得把完整草稿 JSON 写入 `localStorage``localStorage` 仅作为旧版小草稿迁移读取来源,读取后迁移到 IndexedDB 并清理旧 key避免触发浏览器 `Storage` 配额错误。
物品图片生成已接入后端 image-2 接口:
```text
POST /api/creation/edutainment/baby-object-match/assets
```
请求体:
```json
{
"itemNames": ["苹果", "香蕉"]
}
```
响应体:
```json
{
"assets": [
{
"itemId": "baby-object-item-1",
"itemName": "苹果",
"imageSrc": "data:image/png;base64,...",
"assetObjectId": null,
"generationProvider": "vector-engine-gpt-image-2",
"prompt": "..."
}
],
"visualPackage": {
"themePrompt": "...",
"assets": [
{
"assetId": "baby-object-visual-background",
"assetKind": "background",
"imageSrc": "data:image/png;base64,...",
"assetObjectId": null,
"generationProvider": "vector-engine-gpt-image-2",
"prompt": "..."
}
]
}
}
```
该接口返回物品透明 PNG data URL以及同一次创作生成的视觉主题包。本地 Demo 阶段暂不写入 OSS 或 SpacetimeDB `asset_object`。当前创作链路必须真实拿到 `generationProvider = "vector-engine-gpt-image-2"` 的物品图和视觉主题包后才允许进入结果页;若本地未配置 VectorEngine、登录态失效、接口返回 401/5xx、上游生成失败或响应缺少任一资源前端 service 必须抛出错误并停留在生成失败状态,不得静默回退到占位图。
由于一次创作会生成 2 张物品图和 `background``ui-frame``gift-box``basket``smoke-puff` 5 张视觉包装图,该请求属于长耗时 image-2 链路。前端 `babyObjectMatchClient` 对该 POST 使用 10 分钟请求超时,且不做自动重试,避免第一次生成仍在后端执行时又发起第二次重复生成。后端同时启动物品图与视觉主题包生成,并把该路由的 VectorEngine 单图请求等待预算提升到至少 8 分钟,避免某张图 3 分钟附近仍在生成时被后端提前断开。后端日志记录每类资源的开始、完成和耗时,排查时优先按同一次 HTTP 请求查看 `宝贝识物 image-2 物品资源生成完成``宝贝识物 image-2 视觉资源生成完成``VectorEngine 图片生成上游错误`
历史本地草稿中若已保存 `generationProvider = "placeholder"` 的旧占位资源,结果页必须提示“重新生成 image-2 资源”,并禁用试玩和发布。用户点击重新生成、发布或试玩前,前端统一调用 `regenerateBabyObjectMatchDraftAssets(draft)` 补齐资源;补齐失败时保留在结果页并展示错误。
后续正式作品持久化接入时,应补齐:
```text
POST /api/creation/edutainment/baby-object-match/drafts
PUT /api/creation/edutainment/baby-object-match/drafts/{draftId}
POST /api/creation/edutainment/baby-object-match/drafts/{draftId}/publish
```
图片生成必须在后端调用 VectorEngine `gpt-image-2-all`,不得从前端直接调用外部图片接口。
后端 image-2 prompt 约束:
1. 锁定寓教于乐板块统一的卡通绘本草地舞台插画风;
2. 每张图只能围绕对应关键词生成一个单一物品;
3. 不生成背景、场景、氛围渲染、人物、手、篮子、礼物盒、文字、水印或 UI
4. 优先要求纯白或透明抠图友好的干净背景,服务端再统一转透明 PNG 并执行背景 alpha 清理;
5. 返回 `generationProvider = "vector-engine-gpt-image-2"` 的素材必须已经完成透明抠图。
后端视觉主题包 prompt 约束:
1. 同一次请求根据两个物品关键词生成 `background``ui-frame``gift-box``basket``smoke-puff` 五类资源;
2. 总风格继续锁定寓教于乐明亮卡通绘本插画风;
3. 若关键词偏动漫角色、玩具或公仔,背景环境和 UI 元素匹配动漫、玩具主题;若关键词偏水果,匹配果园、自然主题;其它关键词按语义匹配合适主题;
4. 背景环境图使用非透明 16:9 图,但必须保证中间、中下方和底部左右篮子区域清爽,给放大后的礼物盒、中央物品和左右篮子预留空间,不画入礼物盒、篮子、物品、人物、文字或操作 UI
5. UI 装饰框、礼物盒、篮子和烟雾弹出特效使用透明 PNG 后处理,不生成文字、数字、按钮、人物或待分类物品;
6. `gift-box` 提示词必须面向运行态约 2 倍视觉尺寸生成主体饱满的大号礼物盒,`basket` 提示词必须面向运行态约 1.5 倍视觉尺寸生成可读性高的大号篮子;
7. `smoke-puff` 只生成礼物盒打开瞬间使用的柔和烟雾云朵特效,不生成礼物盒、篮子、物品或文字;
8. 左右篮子的固定选项规则不受主题包影响,运行态只把 `basket` 作为篮子造型包装复用。
## 5. UI 边界
工作台只展示两个必填输入和生成按钮。
结果页只展示草稿核心信息、两个物品、保存草稿、发布、试玩。不在 UI 内写玩法说明长文案。
移动端优先:表单和结果页使用单列布局,桌面端自然扩展为双列。
## 6. 运行态边界
前端运行态放在:
```text
src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.tsx
```
运行态直接消费 `BabyObjectMatchDraft`,必须使用草稿中的两个物品名称和物品图。
每轮只随机当前从礼物盒跳出的物品;左右篮子不随机交换,左侧固定为草稿 `itemAssets[0]`,右侧固定为草稿 `itemAssets[1]`
若草稿包含 `visualPackage`运行态通过背景图片层、CSS 变量和图片节点消费:
1. `background`:作为舞台最底层 `ResolvedAssetImage` 背景图;存在该资源时必须关闭默认草地兜底层,避免生成场景被 CSS 草地遮住或弱化;
2. `ui-frame`:作为字幕条和计数器装饰背景;
3. `gift-box`:替换 CSS 礼物盒主体,按旧视觉约 2 倍尺寸展示,只在礼盒入场和打开阶段存在;
4. `basket`:替换篮子主体造型,按旧视觉约 1.5 倍尺寸展示,左右两侧复用同一张主题篮子图;
5. `smoke-puff`:作为礼物盒打开和中央物品弹出期间的透明烟雾特效资源。
旧草稿或接口失败时 `visualPackage = null`,运行态继续使用现有 CSS 绘本风兜底。
首关状态机:
1. `gift-entering`:礼物盒从上方落下入场动画阶段,不接受动作判定;
2. `gift-opening`:礼物盒打开并播放烟雾特效阶段,不接受动作判定;
3. `item-appearing`:礼物盒从舞台移除,当前物品从烟雾中出现并停稳,不接受动作判定;
4. `active`:物品彻底出现后才开放选篮判定;
5. `correct`:展示“真棒”反馈,对应篮筐播放正确特效并停顿,成功次数加 1特效完全结束后重新进入 `gift-entering`,下一轮礼物盒从上方落下;
6. `wrong`:展示“再想一想吧”反馈,物品弹回中央;反馈结束后回到 `active`,不重新随机物品;
7. `complete`:成功次数达到 20展示“恭喜你小朋友”和按钮。
动作输入:
1. 左手连续横向移动达到阈值:将当前物品送入左侧篮子;
2. 右手连续横向移动达到阈值:将当前物品送入右侧篮子。
运行态直接通过 `useMocapInput` 消费本地 mocap WebSocket `/stream`。选篮只使用明确 `leftHand``rightHand` 的连续横向轨迹阈值,不再通过 `wave_left_hand``wave_right_hand``wave` 等动作名触发;侧别为 `unknown` 的手部轨迹也不参与选篮,以避免多套判定误命中和连续误触发。动作判定只在 `active` 阶段开放,礼盒入场、礼盒打开、物品出现、正确反馈和错误反馈阶段收到的动作包必须清空轨迹并忽略,不允许跨阶段补判定。当前本地 mocap 输出的 handedness 按摄像头视角标记,宝贝识物运行态必须先换算为用户身体视角:`rightHand` 轨迹映射玩家左手并进入左侧篮子,`leftHand` 轨迹映射玩家右手并进入右侧篮子。草稿试玩、发布后正式体验和热身关后的本地 Demo 都复用同一个运行态,因此三条入口都必须具备同一套动作控制能力。
开发者调试输入:
1. 鼠标左键按下并拖动:映射左手轨迹,抬起后将当前物品送入左侧篮子;
2. 鼠标右键按下并拖动:映射右手轨迹,抬起后将当前物品送入右侧篮子。
运行态不得新增计时、失败次数、分数、体力或难度递增规则。
音效和语音播报当前只保留接口预留边界,正式语音接口后续接入。
## 7. 发布约束
发布前必须执行:
1. 两个物品名非空;
2. 两个物品名对应的 asset 存在;
3. 标签补齐精确 `寓教于乐`
4. `publicationStatus``draft` 变为 `published`
发布后首版本地响应返回 `publicWorkCode`,用于分享弹窗;正式后端接入时 public code 生成规则需要纳入统一作品号服务。
## 8. 热身关衔接
`/child-motion-demo` 热身完成后的“开始游戏”按钮进入同一个 `BabyObjectMatchRuntimeShell`
热身关独立 Demo 没有创作者草稿上下文,因此使用固定本地 Demo 草稿承载两个物品,仅用于热身关后验证首关体验;正式平台体验仍必须从 `宝贝识物` 模板创作发布后进入寓教于乐板块。
## 9. 验收命令
```bash
npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts src/components/edutainment-creation/BabyObjectMatchWorkspace.test.tsx src/components/edutainment-result/BabyObjectMatchResultView.test.tsx src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.test.tsx src/components/child-motion-demo/ChildMotionWarmupDemo.test.tsx src/services/edutainment-baby-object/babyObjectMatchClient.test.ts
cargo test -p api-server edutainment_baby_object --manifest-path server-rs/Cargo.toml
npx vitest run src/components/platform-entry/platformEdutainmentVisibility.test.ts src/components/platform-entry/PlatformWorkDetailView.test.tsx src/components/custom-world-home/creationWorkShelf.test.ts src/services/useMocapInput.test.ts src/services/child-motion-demo/childMotionDebugInput.test.ts src/routing/appRoutes.test.ts
npx eslint src/components/platform-entry/platformEntryCreationTypes.ts src/components/platform-entry/platformEntryCreationTypes.test.ts src/components/platform-entry/PlatformEntryFlowShellImpl.tsx --ext .ts,.tsx --max-warnings 0
npm run check:encoding
npm run typecheck
npm run build:raw
```
若后续接入真实 Rust API 和 SpacetimeDB 表,再补充 `npm run api-server``/healthz`、Rust contract / api-server / spacetime-client 定向测试和 migration 表目录更新。