710 lines
28 KiB
Markdown
710 lines
28 KiB
Markdown
# bark-battle 三阶段实施计划:浏览器原型 → AI 创作入口 → 数据库落地
|
||
|
||
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
|
||
|
||
**Goal:** 按“三阶段”推进 `bark-battle / 汪汪声浪大作战`:第一阶段先做纯浏览器可运行游戏原型并验证玩法跑通;第二阶段接入 Genarrative 创作入口,用 AI 生成可试玩内容;第三阶段再打通后端数据库、发布、成绩和作品闭环。
|
||
|
||
**Architecture:** 第一阶段只在前端 runtime 内闭环,优先落 `src/games/bark-battle/` 与直达路由,不依赖后端和 SpacetimeDB。第二阶段在已有创作入口、Agent flow controller、结果页和 runtime shell 上接入 `bark-battle`,AI 只生成配置化草稿,不承接正式业务真相。第三阶段按 `server-rs + Axum + SpacetimeDB` DDD 分层落库,前端只展示后端投影和调用后端 API。
|
||
|
||
**Tech Stack:** React 19、TypeScript、Vite、Vitest、Testing Library;第一阶段优先 DOM/Canvas 原型,可在验证玩法后再引入 Phaser 3;后端阶段使用 `server-rs`、Axum、SpacetimeDB、shared-contracts。
|
||
|
||
---
|
||
|
||
## 0. 当前上下文 / 假设
|
||
|
||
- 现有需求与技术文档:
|
||
- `docs/prd/BARK_BATTLE_BDD_2026-05-11.md`
|
||
- `docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md`
|
||
- `docs/technical/BARK_BATTLE_BACKEND_DDD_TECHNICAL_PLAN_2026-05-11.md`
|
||
- 用户明确要求阶段顺序:
|
||
1. 第一阶段:先制作纯浏览器运行的游戏原型,需要测试游戏功能是否能跑通。
|
||
2. 第二阶段:打通创作入口,使用 AI 赋能游戏内容创作。
|
||
3. 第三阶段:最后打通数据库落地。
|
||
- 因此本计划调整原技术方案中的落地优先级:
|
||
- 第一阶段不新增后端表、不接发布、不接作品架。
|
||
- 第一阶段可以用 mock / local draft 配置与直达路由 `/bark-battle` 完成 playable prototype。
|
||
- 第一阶段若 Phaser 依赖尚未安装,优先用 React DOM + Canvas/CSS 2D 原型跑通功能;待核心规则验证后再决定是否引入 Phaser,避免第一阶段被依赖安装和素材管线阻塞。
|
||
- 当前仓库 `package.json` 还没有 `phaser` 依赖;如实现者选择 Phaser,需要单独评估依赖引入、包体和测试影响。
|
||
- 本计划只写计划,不直接实现代码。
|
||
|
||
## 1. 总体分阶段验收口径
|
||
|
||
### Phase 1:纯浏览器游戏原型
|
||
|
||
目标:打开本地前端路由即可玩到一局 `bark-battle`,并通过自动测试确认核心规则跑通。
|
||
|
||
必须满足:
|
||
- 可从 `/bark-battle` 进入独立原型页面。
|
||
- 不登录、不请求后端、不依赖数据库。
|
||
- 支持开发 mock input:点击/按键/按钮可模拟音量峰值;有真实麦克风时可走 Web Audio。
|
||
- 能完成:权限/开始 → 校准或 mock 准备 → 倒计时 → 30 秒 playing → 结算 → 再来一局。
|
||
- 低于阈值输入不计数;有效叫声计数;能量条向玩家或对手移动;结算胜/负/平。
|
||
- 移动端至少能看到能量条、倒计时、双方狗狗、主要按钮和结算。
|
||
|
||
### Phase 2:AI 创作入口
|
||
|
||
目标:创作者能从创作中心选择 `bark-battle`,用 AI 生成玩法配置草稿,并进入结果页试玩。
|
||
|
||
必须满足:
|
||
- 后端入口配置中出现 `bark-battle`,按开关展示/可点击。
|
||
- 前端类型分流、SelectionStage、工作台、结果页、runtime 入口齐全。
|
||
- AI 生成内容仅限配置化草稿:标题、主题、狗狗外观描述、背景风格、难度、局长、AI 对手参数、提示文案 key 等。
|
||
- 生成结果可在本地 runtime 中试玩。
|
||
- 未落库前可先用 session/local state 保存草稿,但要清楚标识为“未发布草稿”。
|
||
|
||
### Phase 3:数据库落地与正式作品闭环
|
||
|
||
目标:`bark-battle` 草稿、发布态配置、runtime start/finish、成绩和作品级游玩埋点都进入后端 DDD / SpacetimeDB 链路。
|
||
|
||
必须满足:
|
||
- `shared-contracts`、`module-bark-battle`、`spacetime-module`、`spacetime-client`、`api-server` 分层清晰。
|
||
- 发布为稳定作品 ID,runtime 从后端读取发布态 config。
|
||
- start 成功写 `work_play_start`:`scope_kind=work`、`scope_id=稳定作品 ID`、metadata 包含 `playType/workId/sourceRoute/userId`。
|
||
- finish 只上传派生指标,不保存原始麦克风音频、波形或可还原语音内容。
|
||
- 作品架/广场/分享/排行榜如启用,均来自后端投影。
|
||
|
||
---
|
||
|
||
## 2. Phase 1:纯浏览器运行游戏原型
|
||
|
||
### Task 1.1:补齐阶段边界文档
|
||
|
||
**Objective:** 在现有技术方案中明确“先浏览器原型,后 AI 创作,最后数据库”的落地顺序,避免实现时过早接后端。
|
||
|
||
**Files:**
|
||
- Modify: `docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md`
|
||
- Modify: `docs/prd/BARK_BATTLE_BDD_2026-05-11.md`
|
||
|
||
**Steps:**
|
||
1. 在 runtime 技术方案中新增“三阶段落地顺序”小节。
|
||
2. 明确 Phase 1 不接后端、不接数据库、不接创作入口事实源。
|
||
3. 在 BDD 中补充“浏览器原型 smoke”验收场景。
|
||
4. 运行:
|
||
```bash
|
||
npm run check:encoding -- docs/prd/BARK_BATTLE_BDD_2026-05-11.md docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md
|
||
git diff --check
|
||
```
|
||
|
||
**Expected:** 编码检查和 diff 空白检查通过。
|
||
|
||
### Task 1.2:建立 Phase 1 目录骨架和类型
|
||
|
||
**Objective:** 建立不依赖 React/DOM/Web Audio 的核心类型,后续所有测试和 UI 都围绕这些类型。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/domain/BarkBattleTypes.ts`
|
||
- Create: `src/games/bark-battle/application/BarkBattleConfig.ts`
|
||
|
||
**Key design:**
|
||
- `BarkBattlePhase = 'permission' | 'calibration' | 'countdown' | 'playing' | 'finished' | 'unavailable'`
|
||
- `MicrophoneFailureReason` 覆盖已有文档中的 9 类失败原因。
|
||
- `BarkBattleSnapshot` 包含 `phase/uiState/errorReason/statusMessageKey/remainingMs/energy/player/opponent/winner/result/lastEvents`。
|
||
- `BarkBattleConfig` 包含 `roundDurationMs/drawThreshold/minBarkGapMs/minBarkDurationMs/maxBarkDurationMs/balanceFactor/calibrationMaxWaitMs`。
|
||
|
||
**Tests:**
|
||
- 本任务可先不写运行时逻辑,但需要让 typecheck 能引用这些类型。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run typecheck
|
||
npm run check:encoding -- src/games/bark-battle/domain/BarkBattleTypes.ts src/games/bark-battle/application/BarkBattleConfig.ts
|
||
```
|
||
|
||
### Task 1.3:TDD 实现叫声检测 BarkDetector
|
||
|
||
**Objective:** 用纯函数/纯类把音频样本转换为有效叫声事件。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/domain/BarkDetector.ts`
|
||
- Create: `src/games/bark-battle/domain/__tests__/BarkDetector.test.ts`
|
||
|
||
**Test cases:**
|
||
1. 超过阈值、持续时长合规、间隔足够时计为一次有效叫声。
|
||
2. 持续噪音不在每个 tick 无限计数。
|
||
3. 低于阈值的背景噪音不计数。
|
||
4. `minBarkGapMs` 内连续峰值不重复计数。
|
||
5. 过短脉冲不计数;过长持续声削弱为单段输入。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/domain/__tests__/BarkDetector.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 1.4:TDD 实现能量条 EnergyTugOfWar
|
||
|
||
**Objective:** 验证玩家/对手推动力能稳定改变 `energy`,并 clamp 到 `-100..100`。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/domain/EnergyTugOfWar.ts`
|
||
- Create: `src/games/bark-battle/domain/__tests__/EnergyTugOfWar.test.ts`
|
||
|
||
**Test cases:**
|
||
1. 玩家 power 高于对手时 `energy` 增加。
|
||
2. 对手 power 高于玩家时 `energy` 减少。
|
||
3. energy 不超过 `100`。
|
||
4. energy 不低于 `-100`。
|
||
5. power 相等时变化不超过浮点误差。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/domain/__tests__/EnergyTugOfWar.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 1.5:TDD 实现单局状态机 BarkBattleSession
|
||
|
||
**Objective:** 跑通 permission/calibration/countdown/playing/finished/unavailable 状态流转和结算。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/domain/BarkBattleSession.ts`
|
||
- Create: `src/games/bark-battle/domain/BarkBattleScoring.ts`
|
||
- Create: `src/games/bark-battle/domain/OpponentStrategy.ts`
|
||
- Create: `src/games/bark-battle/domain/__tests__/BarkBattleSession.test.ts`
|
||
- Create: `src/games/bark-battle/domain/__tests__/BarkBattleScoring.test.ts`
|
||
|
||
**Test cases:**
|
||
1. 校准完成后进入 countdown。
|
||
2. countdown 结束后进入 playing。
|
||
3. playing 中 `remainingMs` 随 tick 递减。
|
||
4. `remainingMs <= 0` 后进入 finished。
|
||
5. `energy > drawThreshold` 判定玩家胜。
|
||
6. `energy < -drawThreshold` 判定对手胜。
|
||
7. `abs(energy) <= drawThreshold` 判定平局。
|
||
8. finished 后新输入不再改变本局计数和能量。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/domain/__tests__/BarkBattleSession.test.ts src/games/bark-battle/domain/__tests__/BarkBattleScoring.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 1.6:实现 mock-first Application Controller
|
||
|
||
**Objective:** 不依赖真实麦克风,先用 mock audio sample 驱动完整 snapshot。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/application/BarkBattleController.ts`
|
||
- Create: `src/games/bark-battle/application/BarkBattleSnapshotStore.ts`
|
||
- Create: `src/games/bark-battle/application/__tests__/BarkBattleController.test.ts`
|
||
|
||
**Behavior:**
|
||
- `startWithMockInput()` 进入校准完成或直接 countdown。
|
||
- `submitMockSample(sample)` 更新玩家输入。
|
||
- `tick(deltaMs)` 推进对手、能量条、倒计时。
|
||
- `restart()` 重置状态。
|
||
- `failMicrophone(reason)` 进入 `phase: 'unavailable'`,并设置 `errorReason/statusMessageKey`。
|
||
|
||
**Test cases:**
|
||
1. mock start 后能进入 countdown/playing。
|
||
2. 提交 mock 峰值后 bark count 增加。
|
||
3. tick 后 energy 可变化。
|
||
4. finish 后生成 result。
|
||
5. `failMicrophone('permission-denied')` 不进入 playing。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/application/__tests__/BarkBattleController.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 1.7:实现浏览器原型 UI Shell(不接平台)
|
||
|
||
**Objective:** 提供 `/bark-battle` 可访问的 playable prototype。
|
||
|
||
**Files:**
|
||
- Create: `src/BarkBattlePlaygroundApp.tsx`
|
||
- Create: `src/games/bark-battle/ui/BarkBattleRuntimeShell.tsx`
|
||
- Create: `src/games/bark-battle/ui/BarkBattleHud.tsx`
|
||
- Create: `src/games/bark-battle/ui/BarkBattleResultPanel.tsx`
|
||
- Create: `src/games/bark-battle/ui/BarkBattleHud.css`
|
||
- Modify: `src/routing/appRoutes.tsx`
|
||
|
||
**Behavior:**
|
||
- 新增路由匹配:`/bark-battle`。
|
||
- 首屏只有清爽开始面板,不常驻大段规则。
|
||
- 提供开发原型按钮:开始、模拟叫声、模拟对手增强、再来一局。
|
||
- playing 画面展示:顶部能量条、倒计时、玩家/对手狗狗、叫声次数、麦克风/mock 状态。
|
||
- 结算面板独立居中,不追加在当前面板下方。
|
||
|
||
**UI constraints:**
|
||
- 移动端优先。
|
||
- 正常 playing 阶段不在 playfield 常驻规则说明。
|
||
- 大动效不遮挡顶部能量条和倒计时。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/ui/**/*.test.tsx
|
||
npm run typecheck
|
||
npm run dev:web
|
||
# 手动 smoke: 访问 /bark-battle → 开始 → 模拟叫声 → energy 变化 → 结算 → 再来一局
|
||
```
|
||
|
||
### Task 1.8:实现 HUD 组件测试
|
||
|
||
**Objective:** 自动验证核心 UI 状态,不只依赖人工试玩。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/ui/__tests__/BarkBattleHud.test.tsx`
|
||
- Create: `src/games/bark-battle/ui/__tests__/BarkBattleResultPanel.test.tsx`
|
||
|
||
**Test cases:**
|
||
1. playing 阶段展示倒计时和能量条。
|
||
2. energy 正值时玩家侧占比更大。
|
||
3. energy 负值时对手侧占比更大。
|
||
4. permission-denied 展示重试授权入口。
|
||
5. unsupported 不展示开始声控按钮。
|
||
6. finished 展示胜负、叫声次数、再来一局。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/ui/__tests__/BarkBattleHud.test.tsx src/games/bark-battle/ui/__tests__/BarkBattleResultPanel.test.tsx
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 1.9:接入真实 Web Audio(可晚于 mock 原型)
|
||
|
||
**Objective:** 在支持麦克风的浏览器中真实采样并驱动 controller,同时保留 mock fallback 便于测试。
|
||
|
||
**Files:**
|
||
- Create: `src/games/bark-battle/infrastructure/BrowserMicrophoneInput.ts`
|
||
- Create: `src/games/bark-battle/infrastructure/AudioAnalyserSampler.ts`
|
||
- Create: `src/games/bark-battle/infrastructure/MicrophonePermission.ts`
|
||
- Create: `src/games/bark-battle/infrastructure/__tests__/BrowserMicrophoneInput.test.ts`
|
||
- Create: `src/games/bark-battle/infrastructure/__tests__/AudioAnalyserSampler.test.ts`
|
||
|
||
**Behavior:**
|
||
- 用户点击开始后才请求麦克风。
|
||
- 用户手势后创建/resume `AudioContext`。
|
||
- 输出归一化 `BarkAudioSample`。
|
||
- 捕获并映射:unsupported、permission-denied、non-secure-context、not-found、not-readable、audio-context-blocked、unknown。
|
||
- stop/restart/page unload 时停止 tracks。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/infrastructure/__tests__/BrowserMicrophoneInput.test.ts src/games/bark-battle/infrastructure/__tests__/AudioAnalyserSampler.test.ts
|
||
npm run typecheck
|
||
npm run dev:web
|
||
# 手动 smoke: 真实麦克风授权 → 校准 → 发声 → 结算
|
||
```
|
||
|
||
### Task 1.10:Phase 1 收口验证
|
||
|
||
**Objective:** 确认“纯浏览器原型”已经可以交给产品/测试试玩。
|
||
|
||
**Commands:**
|
||
```bash
|
||
npm run test -- --run src/games/bark-battle/domain/**/*.test.ts src/games/bark-battle/application/**/*.test.ts src/games/bark-battle/infrastructure/**/*.test.ts src/games/bark-battle/ui/**/*.test.tsx
|
||
npm run typecheck
|
||
npm run lint:eslint
|
||
npm run check:encoding
|
||
npm run dev:web
|
||
```
|
||
|
||
**Manual smoke checklist:**
|
||
- [ ] `/bark-battle` 能打开。
|
||
- [ ] mock 模式可完整完成一局。
|
||
- [ ] 真实麦克风模式可授权、校准、发声、结算。
|
||
- [ ] 拒绝权限后不会进入 playing。
|
||
- [ ] 移动端窄屏能看到核心信息并能点击主要按钮。
|
||
- [ ] 再来一局不会继承上一局 energy/barkCount/result。
|
||
|
||
---
|
||
|
||
## 3. Phase 2:打通创作入口,用 AI 赋能内容创作
|
||
|
||
### Task 2.1:定义 `bark-battle` 草稿契约(前端本地版)
|
||
|
||
**Objective:** 在接后端前,先定义 AI 可生成的 runtime draft shape。
|
||
|
||
**Files:**
|
||
- Create: `packages/shared/src/contracts/barkBattle.ts`(临时前端共享类型,后端阶段再对齐 Rust shared-contracts)
|
||
- Create: `src/services/bark-battle-creation/barkBattleDraftDefaults.ts`
|
||
- Create: `src/services/bark-battle-creation/barkBattleDraftValidation.ts`
|
||
|
||
**Draft fields:**
|
||
- `title`
|
||
- `description`
|
||
- `themePrompt`
|
||
- `playerDogName`
|
||
- `opponentDogName`
|
||
- `backgroundStyle`
|
||
- `difficulty`
|
||
- `roundDurationMs`
|
||
- `drawThreshold`
|
||
- `opponentConfig`
|
||
- `audioSensitivityPreset`
|
||
- `visualStyle`
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/services/bark-battle-creation/**/*.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 2.2:新增创作入口配置
|
||
|
||
**Objective:** 让 `bark-battle` 出现在创作中心入口中,但可通过后端入口配置开关控制。
|
||
|
||
**Files likely to change:**
|
||
- `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
|
||
- `server-rs/crates/module-runtime/src/domain.rs`
|
||
- `server-rs/crates/module-runtime/src/application.rs`
|
||
- `server-rs/crates/shared-contracts/src/creation_entry_config.rs`
|
||
- `src/components/platform-entry/platformEntryCreationTypes.ts`
|
||
- `src/components/platform-entry/platformEntryCreationTypes.test.ts`
|
||
|
||
**Plan:**
|
||
1. 在入口 seed 中新增 `bark-battle`,首轮可设:`visible: true`、`open: true`(若需要灰度则 `open: false`)。
|
||
2. 前端展示派生只消费 API 返回,不恢复旧静态入口事实源。
|
||
3. 更新排序和锁定态测试。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts
|
||
npm run typecheck
|
||
cd server-rs && cargo check -p api-server -p spacetime-module --no-default-features
|
||
```
|
||
|
||
### Task 2.3:扩展 SelectionStage 与流程分流
|
||
|
||
**Objective:** 点击 `bark-battle` 入口后进入对应创作工作台。
|
||
|
||
**Files likely to change:**
|
||
- `src/components/platform-entry/platformEntryTypes.ts`
|
||
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
|
||
- `src/components/platform-entry/usePlatformCreationAgentFlowController.ts`(如复用通用 agent flow)
|
||
|
||
**Stages:**
|
||
- `bark-battle-agent-workspace`
|
||
- `bark-battle-generating`(可选)
|
||
- `bark-battle-result`
|
||
- `bark-battle-runtime`
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- src/components/platform-entry/**/*.test.tsx src/components/platform-entry/**/*.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 2.4:实现 AI 创作工作台
|
||
|
||
**Objective:** 用对话式或表单式输入生成 `BarkBattleDraft`。
|
||
|
||
**Files:**
|
||
- Create: `src/components/bark-battle-creation/BarkBattleAgentWorkspace.tsx`
|
||
- Create: `src/services/bark-battle-creation/barkBattleCreationClient.ts`
|
||
- Create: `src/services/bark-battle-creation/barkBattlePromptBuilder.ts`
|
||
- Create: `src/services/bark-battle-creation/__tests__/barkBattlePromptBuilder.test.ts`
|
||
|
||
**Behavior:**
|
||
- 用户输入一句主题,例如“柴犬在赛博公园比谁叫得响”。
|
||
- AI 返回结构化草稿。
|
||
- 前端校验并填默认值,不让非法 roundDuration/difficulty 进入 runtime。
|
||
- 错误时保留用户输入和已生成草稿。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/services/bark-battle-creation/**/*.test.ts
|
||
npm run typecheck
|
||
```
|
||
|
||
### Task 2.5:实现结果页与试玩入口
|
||
|
||
**Objective:** AI 草稿生成后可查看、返回编辑、进入 Phase 1 runtime 试玩。
|
||
|
||
**Files:**
|
||
- Create: `src/components/bark-battle-result/BarkBattleResultView.tsx`
|
||
- Create: `src/components/bark-battle-result/BarkBattleResultView.test.tsx`
|
||
- Modify: `src/games/bark-battle/ui/BarkBattleRuntimeShell.tsx`(允许传入 draft config)
|
||
|
||
**Behavior:**
|
||
- 展示标题、主题、狗狗名、背景风格、难度、局长。
|
||
- 提供“返回编辑”“试玩”按钮。
|
||
- 暂不展示发布按钮,或发布按钮显示为后端阶段能力。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- --run src/components/bark-battle-result/BarkBattleResultView.test.tsx
|
||
npm run typecheck
|
||
npm run dev:web
|
||
# 手动 smoke: 创作入口 → AI 草稿 → 结果页 → 试玩 → 返回编辑
|
||
```
|
||
|
||
### Task 2.6:Phase 2 收口验证
|
||
|
||
**Commands:**
|
||
```bash
|
||
npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts src/components/bark-battle-result/BarkBattleResultView.test.tsx src/services/bark-battle-creation/**/*.test.ts src/games/bark-battle/**/*.test.ts src/games/bark-battle/**/*.test.tsx
|
||
npm run typecheck
|
||
npm run lint:eslint
|
||
npm run check:encoding
|
||
```
|
||
|
||
**Manual smoke checklist:**
|
||
- [ ] 创作中心展示 `bark-battle`。
|
||
- [ ] 点击入口进入工作台。
|
||
- [ ] AI 可生成草稿。
|
||
- [ ] 草稿结果页可展示并返回编辑。
|
||
- [ ] 试玩使用草稿配置影响 runtime 表现。
|
||
- [ ] 未接数据库前不会假装发布成功。
|
||
|
||
---
|
||
|
||
## 4. Phase 3:数据库落地与正式作品闭环
|
||
|
||
### Task 3.1:补齐 shared contracts
|
||
|
||
**Objective:** 前后端共享 bark-battle DTO,避免前端手写正式契约漂移。
|
||
|
||
**Files likely to change:**
|
||
- `server-rs/crates/shared-contracts/src/bark_battle.rs`
|
||
- `server-rs/crates/shared-contracts/src/lib.rs`
|
||
- `packages/shared/src/contracts/barkBattle.ts`
|
||
|
||
**DTO:**
|
||
- `BarkBattleDraft`
|
||
- `BarkBattlePublishedConfig`
|
||
- `CreateBarkBattleSessionRequest/Response`
|
||
- `BarkBattleRuntimeStartRequest/Response`
|
||
- `BarkBattleRuntimeFinishRequest/Response`
|
||
- `BarkBattleRunResult`
|
||
- `BarkBattleScoreSummary`
|
||
- `BarkBattleLeaderboardEntry`
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run typecheck
|
||
cd server-rs && cargo check -p shared-contracts --no-default-features
|
||
```
|
||
|
||
### Task 3.2:新增 `module-bark-battle` 纯领域模块
|
||
|
||
**Objective:** 后端正式分数、配置校验、提交合法性不写在 api-server handler 里。
|
||
|
||
**Files:**
|
||
- Create: `server-rs/crates/module-bark-battle/`
|
||
- Modify: `server-rs/Cargo.toml`
|
||
|
||
**Responsibilities:**
|
||
- 配置合法性校验。
|
||
- run start/finish 状态约束。
|
||
- 派生指标范围校验。
|
||
- 分数与排行榜排序分计算。
|
||
- 不接 Axum、不接 SpacetimeDB、不接 HTTP。
|
||
|
||
**Validation:**
|
||
```bash
|
||
cd server-rs && cargo test -p module-bark-battle --no-default-features
|
||
cd server-rs && cargo check -p module-bark-battle --no-default-features
|
||
```
|
||
|
||
### Task 3.3:SpacetimeDB 表、reducer、migration
|
||
|
||
**Objective:** 保存草稿、发布态配置、run、result、leaderboard 投影。
|
||
|
||
**Files likely to change:**
|
||
- `server-rs/crates/spacetime-module/src/runtime/bark_battle.rs`(或按现有模块目录命名)
|
||
- `server-rs/crates/spacetime-module/src/migration.rs`
|
||
- `server-rs/crates/spacetime-module/src/lib.rs`
|
||
- 生成绑定目录(通过命令生成,不手改生成物)
|
||
|
||
**Tables draft:**
|
||
- `bark_battle_draft`
|
||
- `bark_battle_published_config`
|
||
- `bark_battle_run`
|
||
- `bark_battle_run_result`
|
||
- `bark_battle_leaderboard_entry`
|
||
|
||
**Reducers/procedures:**
|
||
- `create_bark_battle_draft`
|
||
- `publish_bark_battle_config`
|
||
- `start_bark_battle_run`
|
||
- `finish_bark_battle_run`
|
||
- `list_bark_battle_leaderboard`
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run spacetime:generate
|
||
cd server-rs && cargo check -p spacetime-module --no-default-features
|
||
npm run check:server-rs-ddd
|
||
```
|
||
|
||
### Task 3.4:spacetime-client facade
|
||
|
||
**Objective:** api-server 通过 facade 调用 SpacetimeDB,不直接散落 reducer 细节。
|
||
|
||
**Files likely to change:**
|
||
- `server-rs/crates/spacetime-client/src/runtime.rs`
|
||
- `server-rs/crates/spacetime-client/src/mapper.rs`
|
||
- `server-rs/crates/spacetime-client/src/lib.rs`
|
||
|
||
**Validation:**
|
||
```bash
|
||
cd server-rs && cargo check -p spacetime-client --no-default-features
|
||
```
|
||
|
||
### Task 3.5:api-server BFF 路由
|
||
|
||
**Objective:** 提供创作、发布态 runtime start/finish、leaderboard API。
|
||
|
||
**Files likely to change:**
|
||
- `server-rs/crates/api-server/src/bark_battle.rs`
|
||
- `server-rs/crates/api-server/src/main.rs` 或路由注册文件
|
||
|
||
**Routes draft:**
|
||
- `POST /api/bark-battle/sessions`
|
||
- `GET /api/bark-battle/sessions/:sessionId`
|
||
- `POST /api/bark-battle/runtime/start`
|
||
- `POST /api/bark-battle/runtime/finish`
|
||
- `GET /api/bark-battle/works/:workId/runtime-config`
|
||
- `GET /api/bark-battle/works/:workId/leaderboard`
|
||
|
||
**Tracking:**
|
||
- runtime start 成功后主动写 `work_play_start`。
|
||
- `scope_kind=work`。
|
||
- `scope_id=稳定作品 ID`。
|
||
- metadata 包含 `playType=bark-battle`、`workId`、`sourceRoute`、`userId`。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run api-server
|
||
# 另一个终端检查 /healthz,并执行对应 API smoke
|
||
cd server-rs && cargo check -p api-server --no-default-features
|
||
```
|
||
|
||
### Task 3.6:前端正式 client 与 runtime 切换
|
||
|
||
**Objective:** runtime 从本地草稿模式升级为可读取后端发布态 config,并提交正式派生结果。
|
||
|
||
**Files likely to change:**
|
||
- Create: `src/services/bark-battle-runtime/barkBattleRuntimeClient.ts`
|
||
- Create: `src/services/bark-battle-works/barkBattleWorksClient.ts`
|
||
- Modify: `src/games/bark-battle/ui/BarkBattleRuntimeShell.tsx`
|
||
- Modify: `src/components/bark-battle-result/BarkBattleResultView.tsx`
|
||
- Modify: `src/components/custom-world-home/creationWorkShelf.ts`
|
||
- Modify: `src/components/custom-world-home/CustomWorldCreationHub.tsx`
|
||
- Modify: `src/services/publicWorkCode.ts`
|
||
|
||
**Behavior:**
|
||
- 本地 preview 仍可使用 draft config。
|
||
- 正式作品 runtime 必须先调用 start API,拿 run token/session。
|
||
- finish 只提交派生 metrics。
|
||
- 发布后刷新作品架/广场。
|
||
|
||
**Validation:**
|
||
```bash
|
||
npm run test -- src/services/bark-battle-runtime/**/*.test.ts src/games/bark-battle/**/*.test.ts src/games/bark-battle/**/*.test.tsx
|
||
npm run typecheck
|
||
npm run check:encoding
|
||
```
|
||
|
||
### Task 3.7:Phase 3 收口验证
|
||
|
||
**Commands:**
|
||
```bash
|
||
npm run test -- src/games/bark-battle/**/*.test.ts src/games/bark-battle/**/*.test.tsx src/services/bark-battle-runtime/**/*.test.ts src/services/bark-battle-creation/**/*.test.ts
|
||
npm run typecheck
|
||
npm run lint:eslint
|
||
npm run check:encoding
|
||
npm run check:server-rs-ddd
|
||
cd server-rs && cargo test -p module-bark-battle --no-default-features
|
||
cd server-rs && cargo check -p api-server -p spacetime-module -p spacetime-client -p shared-contracts --no-default-features
|
||
npm run api-server
|
||
```
|
||
|
||
**Manual smoke checklist:**
|
||
- [ ] 创作者生成并发布 bark-battle 作品。
|
||
- [ ] 玩家从作品页进入 runtime。
|
||
- [ ] start API 成功并写 `work_play_start`。
|
||
- [ ] 浏览器本地完成一局。
|
||
- [ ] finish API 只上传派生指标。
|
||
- [ ] 成绩/排行榜/作品架刷新来自后端投影。
|
||
- [ ] 拒绝麦克风权限时不会创建非法 finished result。
|
||
|
||
---
|
||
|
||
## 5. 文件清单总览
|
||
|
||
### Phase 1 likely files
|
||
|
||
- `src/routing/appRoutes.tsx`
|
||
- `src/BarkBattlePlaygroundApp.tsx`
|
||
- `src/games/bark-battle/domain/BarkBattleTypes.ts`
|
||
- `src/games/bark-battle/domain/BarkDetector.ts`
|
||
- `src/games/bark-battle/domain/EnergyTugOfWar.ts`
|
||
- `src/games/bark-battle/domain/BarkBattleSession.ts`
|
||
- `src/games/bark-battle/domain/BarkBattleScoring.ts`
|
||
- `src/games/bark-battle/domain/OpponentStrategy.ts`
|
||
- `src/games/bark-battle/application/BarkBattleConfig.ts`
|
||
- `src/games/bark-battle/application/BarkBattleController.ts`
|
||
- `src/games/bark-battle/application/BarkBattleSnapshotStore.ts`
|
||
- `src/games/bark-battle/infrastructure/BrowserMicrophoneInput.ts`
|
||
- `src/games/bark-battle/infrastructure/AudioAnalyserSampler.ts`
|
||
- `src/games/bark-battle/infrastructure/MicrophonePermission.ts`
|
||
- `src/games/bark-battle/ui/BarkBattleRuntimeShell.tsx`
|
||
- `src/games/bark-battle/ui/BarkBattleHud.tsx`
|
||
- `src/games/bark-battle/ui/BarkBattleResultPanel.tsx`
|
||
- `src/games/bark-battle/ui/BarkBattleHud.css`
|
||
|
||
### Phase 2 likely files
|
||
|
||
- `packages/shared/src/contracts/barkBattle.ts`
|
||
- `src/components/platform-entry/platformEntryTypes.ts`
|
||
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
|
||
- `src/components/platform-entry/platformEntryCreationTypes.ts`
|
||
- `src/components/bark-battle-creation/BarkBattleAgentWorkspace.tsx`
|
||
- `src/components/bark-battle-result/BarkBattleResultView.tsx`
|
||
- `src/services/bark-battle-creation/*`
|
||
|
||
### Phase 3 likely files
|
||
|
||
- `server-rs/crates/shared-contracts/src/bark_battle.rs`
|
||
- `server-rs/crates/module-bark-battle/*`
|
||
- `server-rs/crates/spacetime-module/src/runtime/bark_battle.rs`
|
||
- `server-rs/crates/spacetime-module/src/migration.rs`
|
||
- `server-rs/crates/spacetime-client/src/runtime.rs`
|
||
- `server-rs/crates/spacetime-client/src/mapper.rs`
|
||
- `server-rs/crates/api-server/src/bark_battle.rs`
|
||
- `src/services/bark-battle-runtime/*`
|
||
- `src/services/bark-battle-works/*`
|
||
- `src/components/custom-world-home/creationWorkShelf.ts`
|
||
- `src/services/publicWorkCode.ts`
|
||
|
||
---
|
||
|
||
## 6. 风险、取舍与开放问题
|
||
|
||
### 风险
|
||
|
||
1. **麦克风权限和移动端 AudioContext 差异大。** 需要 mock input 保底,否则自动化和本地开发会被真实设备阻塞。
|
||
2. **第一阶段过早引入 Phaser 可能拖慢验证。** 当前仓库没有 `phaser` 依赖;建议先用 DOM/Canvas 跑通玩法,再决定是否引入 Phaser。
|
||
3. **AI 草稿和正式发布配置容易漂移。** Phase 2 临时 TS 类型必须在 Phase 3 与 Rust shared-contracts 对齐。
|
||
4. **不能保存原始音频。** 后端阶段只能保存派生指标,任何音频片段、波形、频谱明细都不应落库。
|
||
5. **入口配置事实源在后端/SpacetimeDB。** Phase 2 接入口时不要恢复旧前端静态入口配置。
|
||
|
||
### 取舍
|
||
|
||
- Phase 1 先把“游戏是否好玩、功能是否跑通”作为第一目标,不追求正式作品闭环。
|
||
- Phase 2 让 AI 生成内容配置,而不是让 AI 直接生成任意代码或不受控规则。
|
||
- Phase 3 再把正式业务真相交给后端,避免前端 runtime 先背上发布、成绩、排行榜的复杂度。
|
||
|
||
### 开放问题
|
||
|
||
1. Phase 1 是否必须使用 Phaser?如果只是验证玩法,可先使用 DOM/CSS/Canvas 原型,后续再替换 renderer。
|
||
2. `bark-battle` 的正式中文名是否固定为“汪汪声浪大作战”?如果名称要改,需先统一文档、入口配置和分享标题。
|
||
3. AI 创作阶段是否需要生成图片/狗狗视觉资产,还是只生成风格描述和使用占位素材?
|
||
4. 是否需要排行榜作为 Phase 3 必选,还是作为数据库落地后的增强项?
|
||
5. 真实麦克风 smoke 需要哪些目标设备:Chrome 桌面、Android Chrome、iOS Safari 是否都纳入首批验收?
|
||
|
||
---
|
||
|
||
## 7. 建议执行方式
|
||
|
||
1. 先按 Phase 1 执行,且每个 domain/application task 坚持 TDD:先失败测试,再实现。
|
||
2. Phase 1 合并前不要接数据库,不要新增后端表,不要把入口配置切到 open。
|
||
3. Phase 1 验证通过后,让产品/团队试玩 `/bark-battle`,确认玩法数值和 UI 方向。
|
||
4. 再进入 Phase 2,把 AI 创作工作台接到同一个 runtime draft config。
|
||
5. 最后进入 Phase 3,按后端 DDD 文档做数据库、发布、成绩和追踪闭环。
|
||
|