# Bark Battle Phase 2 Platform Work Loop Implementation Plan > **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task. **Goal:** 将 `bark-battle` 从内部试玩 demo 升级为 Genarrative 正式 play type,打通轻创作配置、发布态作品、正式 runtime、run start / finish、后端裁决、个人历史、作品统计和最小排行榜闭环。 **Architecture:** 先冻结 shared contracts 与 `module-bark-battle` 纯领域规则,再落 SpacetimeDB 表/reducer、`spacetime-client` facade 和 `api-server` BFF,随后接前端最小纵切,最后补排行榜/个人历史/作品统计投影体验。前端只承接表现、交互和临时 UI 状态,正式业务真相由后端裁决。 **Tech Stack:** React + TypeScript + Vite, server-rs + Axum, SpacetimeDB Rust module, shared-contracts, Vitest, Cargo tests, npm scripts. --- ## 0. 已确认决策 1. “有效叫声”统一为 **有效声浪触发**:当前采样响度达到有效阈值且满足 `minBarkGapMs` 冷却即触发;不再要求 `minBarkDurationMs` / `maxBarkDurationMs`,也不等待响度回落。 2. Phase 2 范围是 **Bark Battle 平台作品闭环**,不是单纯玩法表现深化。 3. 作品形态是 **轻创作配置作品**:标题、描述、主题/背景预设、狗狗皮肤预设、难度预设、排行榜开关。 4. 难度预设只影响 AI 对手行为;不影响有效阈值、冷却、时长、分数公式或反作弊阈值。 5. 排行榜按 `workId + difficultyPreset + rulesetVersion` 分榜。 6. 后端裁决正式单局结果;前端只提交派生指标,`clientResult` 只用于 debug/对账。 7. 排行榜只收录 `serverResult = player_win` 且未被反作弊拒绝的单局结果,排序以 `finalEnergy` 优先。 8. 作品统计使用最小后端投影:start、finish、win/draw/loss、flagged、leaderboard、best/avg energy。 9. 个人历史成绩 = 最近记录列表 + 个人最佳摘要;仅本人可见。 10. 正式入口闭环覆盖创作入口、作品详情 CTA、广场/作品卡片、我的作品、稳定作品 ID runtime 路由和 `work_play_start`。 11. 创作编辑形态是单页轻配置表单 + 预览卡片。 12. 实施顺序固定为:契约与领域规则 → SpacetimeDB 表/reducer 与 api-server BFF → 最小前端纵切 → 投影与列表体验 → 收口验证。 --- ## 1. 必读文档与约束 实施前先读: - `AGENTS.md` - `CONTEXT.md` - `docs/prd/BARK_BATTLE_BDD_2026-05-11.md` - `docs/technical/BARK_BATTLE_BACKEND_DDD_TECHNICAL_PLAN_2026-05-11.md` - `docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md` - `docs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md` - `docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md` - `.codex/skills/spacetimedb-cli/SKILL.md` - `.codex/skills/spacetimedb-rust/SKILL.md` - `.codex/skills/spacetimedb-concepts/SKILL.md` - `.codex/skills/spacetimedb-typescript/SKILL.md` 关键约束: - 后端路线固定 `server-rs + Axum + SpacetimeDB`。 - 领域规则进 `module-bark-battle`,SpacetimeDB 表和事务编排进 `spacetime-module`。 - HTTP/SSE/BFF 留在 `api-server`。 - 前后端 DTO 留在 `shared-contracts`。 - 数据库表结构更改必须同步 `migration.rs` 和生成绑定。 - 人工命令/文档示例禁止继续使用 `spacetime --root-dir`。 - 修改中文文件后必须跑 `npm run check:encoding`。 --- ## 2. 阶段一:契约与领域规则 ### Task 1.1: 新增 Rust shared-contracts 模块 **Objective:** 定义 Bark Battle Phase 2 的 Rust DTO 边界。 **Files:** - Create: `server-rs/crates/shared-contracts/src/bark_battle.rs` - Modify: `server-rs/crates/shared-contracts/src/lib.rs` - Test: `server-rs/crates/shared-contracts/src/bark_battle.rs` **Steps:** 1. 新增枚举:`BarkBattleDifficultyPreset { Easy, Normal, Hard }`、`BarkBattleServerResult { PlayerWin, OpponentWin, Draw }`、`BarkBattleFinishStatus { Accepted, AcceptedWithFlags, Rejected }`。 2. 新增配置 DTO:`BarkBattleDraftConfig`、`BarkBattlePublishedConfig`、`BarkBattleRuntimeConfig`。 3. 新增 run DTO:`BarkBattleRunStartRequest/Response`、`BarkBattleRunFinishRequest/Response`。 4. 新增派生指标 DTO:`BarkBattleDerivedMetrics`,字段包含 `trigger_count`、`max_volume`、`average_volume`、`final_energy`、`combo_max`。 5. 新增排行榜/历史/统计 DTO:`BarkBattleLeaderboardEntry`、`BarkBattlePersonalHistoryItem`、`BarkBattlePersonalBestSummary`、`BarkBattleWorkStats`。 6. 在 `lib.rs` 导出 `pub mod bark_battle;`。 **Verification:** ```bash cargo test -p shared-contracts bark_battle ``` Expected: contracts tests pass. ### Task 1.2: 新增 TypeScript shared contracts mirror **Objective:** 让前端获得与 Rust DTO 对齐的类型。 **Files:** - Create: `packages/shared/src/contracts/barkBattle.ts` - Modify: `packages/shared/src/contracts/index.ts` - Test: `packages/shared/src/contracts/barkBattle.test.ts` **Steps:** 1. 定义 `BarkBattleDifficultyPreset = 'easy' | 'normal' | 'hard'`。 2. 定义 `BarkBattleServerResult = 'player_win' | 'opponent_win' | 'draw'`。 3. 定义 draft / published / runtime config 类型。 4. 定义 start / finish request response 类型。 5. 定义 leaderboard / personal history / work stats 类型。 6. 写最小序列化/fixture 测试,确保字段命名采用前端约定 camelCase,并在 API client 层做必要映射。 **Verification:** ```bash npm test -- --run packages/shared/src/contracts/barkBattle.test.ts npx tsc -p tsconfig.typecheck-guardrails.json --noEmit --pretty false ``` ### Task 1.3: 新建 module-bark-battle crate **Objective:** 将正式裁决规则放入纯领域 crate。 **Files:** - Create: `server-rs/crates/module-bark-battle/Cargo.toml` - Create: `server-rs/crates/module-bark-battle/src/lib.rs` - Create: `server-rs/crates/module-bark-battle/src/domain.rs` - Create: `server-rs/crates/module-bark-battle/src/scoring.rs` - Modify: `server-rs/Cargo.toml` **Steps:** 1. 在 workspace 中注册 `module-bark-battle`。 2. 定义 `RulesetVersion`,首版固定如 `bark-battle-ruleset-v1`。 3. 定义 `BarkBattleRuleset`,包含标准局时长 30s、`min_bark_gap_ms`、合法音量/能量/连击范围、duration tolerance。 4. 实现 `validate_finish_metrics()`。 5. 实现 `adjudicate_result()`:以后端 `final_energy` 和 draw threshold 生成 `serverResult`。 6. 实现 `compute_leaderboard_score()`:只允许胜利局入榜,排序因子为 `finalEnergy`、`triggerCount`、`maxVolume`、duration 接近度、`finishedAt`。 **Verification:** ```bash cargo test -p module-bark-battle ``` ### Task 1.4: 领域规则单测覆盖作弊边界 **Objective:** 防止前端伪造 finish 直接刷榜。 **Files:** - Modify: `server-rs/crates/module-bark-battle/src/scoring.rs` **Test cases:** - 28s-35s 合法窗口内可接受。 - 1s / 300s 应 rejected 或 flagged。 - `triggerCount > durationMs / minBarkGapMs + tolerance` 应 flagged。 - `finalEnergy` 越界应 rejected。 - 平/负不生成 leaderboard entry。 - easy/normal/hard 不改变阈值、冷却、分数公式,只改变 AI preset key。 **Verification:** ```bash cargo test -p module-bark-battle -- --nocapture ``` --- ## 3. 阶段二:SpacetimeDB 表/reducer 与 api-server BFF ### Task 2.1: 设计 SpacetimeDB 表目录 **Objective:** 新增 Bark Battle 表并与 migration 对齐。 **Files:** - Create: `server-rs/crates/spacetime-module/src/bark_battle/mod.rs` - Create: `server-rs/crates/spacetime-module/src/bark_battle/types.rs` - Create: `server-rs/crates/spacetime-module/src/bark_battle/tables.rs` - Modify: `server-rs/crates/spacetime-module/src/lib.rs` - Modify: `server-rs/crates/spacetime-module/src/migration.rs` **Tables:** - `bark_battle_draft_config` - `bark_battle_published_config` - `bark_battle_runtime_run` - `bark_battle_score_record` - `bark_battle_leaderboard_entry` - `bark_battle_work_stats_projection` - `bark_battle_personal_best_projection` **Pitfalls:** - 表结构不要 derive `SpacetimeType`。 - reducer 使用 `&ReducerContext`。 - 授权身份来自 `ctx.sender()`。 - 需要公开订阅的表才加 `public`。 **Verification:** ```bash cargo test -p spacetime-module ``` ### Task 2.2: 实现草稿/发布 reducer **Objective:** 支持轻配置草稿保存和发布态 config 固化。 **Reducers:** - `create_bark_battle_draft` - `update_bark_battle_draft_config` - `publish_bark_battle_work` - `get_bark_battle_runtime_config` 如仓库约定使用 reducer/procedure 查询则按现有 pattern 实现。 **Rules:** - 草稿配置只允许标题、描述、主题/背景预设、狗狗皮肤预设、难度预设、排行榜开关。 - 发布生成稳定作品 ID / config version。 - 发布态 config 包含 `rulesetVersion`。 **Verification:** ```bash cargo test -p spacetime-module bark_battle ``` ### Task 2.3: 实现 run start / finish reducer **Objective:** 打通正式运行态后端事务。 **Reducers:** - `start_bark_battle_run` - `finish_bark_battle_run` - `get_bark_battle_run` **Rules:** - start 创建 `run_id` 和一次性 `run_token`。 - start 记录 work/config/ruleset/difficulty 快照。 - finish 必须校验 run token、未 finish、work/config/ruleset/difficulty 一致。 - finish 调用 `module-bark-battle` 裁决结果。 - accepted 写 score record。 - `serverResult = player_win` 且排行榜开启且未 rejected 时写 leaderboard entry。 - accepted / accepted_with_flags 更新 work stats 和 personal best projection。 **Verification:** ```bash cargo test -p spacetime-module bark_battle_run ``` ### Task 2.4: 更新 migration 与生成绑定 **Objective:** 让 SpacetimeDB 表结构变更可发布。 **Files:** - Modify: `server-rs/crates/spacetime-module/src/migration.rs` - Generated: `server-rs/crates/spacetime-client/src/module_bindings/*bark*` **Commands:** 按仓库现有脚本优先;不要手改 generated bindings。 ```bash npm run spacetime:build npm run spacetime:generate ``` 若脚本名不同,先查 `package.json` 和 `server-rs` README。 ### Task 2.5: 实现 spacetime-client facade **Objective:** api-server 不直接操作 generated bindings。 **Files:** - Create: `server-rs/crates/spacetime-client/src/bark_battle.rs` - Modify: `server-rs/crates/spacetime-client/src/lib.rs` **Methods:** - `create_bark_battle_draft` - `save_bark_battle_draft_config` - `publish_bark_battle_work` - `get_bark_battle_runtime_config` - `start_bark_battle_run` - `finish_bark_battle_run` - `list_bark_battle_leaderboard` - `list_my_bark_battle_history` - `get_my_bark_battle_best_summary` - `get_bark_battle_work_stats` **Verification:** ```bash cargo test -p spacetime-client bark_battle ``` ### Task 2.6: 实现 api-server BFF 路由 **Objective:** 暴露前端需要的 HTTP API。 **Files:** - Create: `server-rs/crates/api-server/src/bark_battle.rs` - Modify: `server-rs/crates/api-server/src/app.rs` **Routes:** - `POST /api/bark-battle/drafts` - `PATCH /api/bark-battle/drafts/:draftId` - `POST /api/bark-battle/drafts/:draftId/publish` - `GET /api/bark-battle/works/:workId/runtime-config` - `POST /api/bark-battle/runs/start` - `POST /api/bark-battle/runs/:runId/finish` - `GET /api/bark-battle/works/:workId/leaderboard` - `GET /api/bark-battle/me/history` - `GET /api/bark-battle/me/best-summary` - `GET /api/bark-battle/works/:workId/stats` **Verification:** ```bash cargo test -p api-server bark_battle npm run api-server curl -f http://127.0.0.1:/healthz ``` --- ## 4. 阶段三:最小前端纵切 ### Task 3.1: 新增前端 service client **Files:** - Create: `src/services/bark-battle/barkBattleClient.ts` - Test: `src/services/bark-battle/barkBattleClient.test.ts` **Methods:** 与 BFF routes 一一对应。 **Verification:** ```bash npm test -- --run src/services/bark-battle/barkBattleClient.test.ts ``` ### Task 3.2: 接入创作入口与 SelectionStage **Files:** - Modify: `src/config/newWorkEntryConfig.ts` - Modify: `src/components/platform-entry/platformEntryCreationTypes.ts` - Modify: `src/components/platform-entry/platformEntryTypes.ts` - Modify: `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx` **Rules:** - 新增 `bark-battle` play type。 - 入口打开单页轻配置表单,不走复杂 agent workspace。 - 移动端入口布局不能溢出。 ### Task 3.3: 实现单页轻配置表单 + 预览卡片 **Files:** - Create: `src/components/bark-battle-creation/BarkBattleConfigEditor.tsx` - Create: `src/components/bark-battle-creation/BarkBattlePreviewCard.tsx` - Test: `src/components/bark-battle-creation/BarkBattleConfigEditor.test.tsx` **UI fields:** - 标题必填 - 简介选填 - 主题/背景预设 - 狗狗皮肤预设 - 难度预设,默认 `normal` - 排行榜开关,默认开启 **UI constraints:** - 不堆大段玩法说明。 - 按现有游戏 UI 风格设计。 - 移动端优先。 ### Task 3.4: 发布后进入作品详情 **Files:** - Modify: `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx` - Modify: `src/components/platform-entry/PlatformWorkDetailView.tsx` - Modify: `src/components/custom-world-home/CustomWorldCreationHub.tsx` - Modify: `src/components/custom-world-home/creationWorkShelf.ts` **Rules:** - 发布成功刷新 works/gallery/shelf。 - 跳作品详情。 - 详情 CTA 可以进入正式 runtime。 ### Task 3.5: runtime 拉发布态 config 并 start / finish **Files:** - Modify: `src/games/bark-battle/*` - Modify: `src/games/bark-battle/ui/BarkBattleRuntimeShell.tsx` - Create/Modify: `src/components/bark-battle-runtime/BarkBattleRuntimeRoute.tsx` 如需要 **Rules:** - runtime 通过稳定 `workId` 拉 `BarkBattleRuntimeConfig`。 - 开始正式局时调用 start run。 - 结束时提交 finish 派生指标。 - 结算展示 `serverResult`、`scoreSummary`、`antiCheatFlags`、leaderboard entry。 - 麦克风原始音频不上传。 **Verification:** ```bash npm test -- --run src/games/bark-battle/domain/__tests__/BarkDetector.test.ts src/games/bark-battle/application/__tests__/BarkBattleController.test.ts src/games/bark-battle/ui/__tests__/BarkBattleRuntimeShell.test.tsx ``` --- ## 5. 阶段四:投影与列表体验 ### Task 4.1: 排行榜 UI **Files:** - Create: `src/components/bark-battle-leaderboard/BarkBattleLeaderboardPanel.tsx` - Test: `src/components/bark-battle-leaderboard/BarkBattleLeaderboardPanel.test.tsx` - Modify: `src/components/platform-entry/PlatformWorkDetailView.tsx` **Rules:** - 查询维度 `workId + difficultyPreset + rulesetVersion`。 - 只展示胜利入榜成绩。 - 不展示平/负/flagged 历史。 ### Task 4.2: 个人历史最近记录 + 最佳摘要 UI **Files:** - Create: `src/components/bark-battle-history/BarkBattlePersonalHistoryPanel.tsx` - Test: `src/components/bark-battle-history/BarkBattlePersonalHistoryPanel.test.tsx` **Rules:** - 默认最近 20 条。 - 仅本人可见。 - 可按 workId / difficultyPreset 过滤。 - flagged 只做轻提示,不展示详细反作弊原因。 ### Task 4.3: 作品统计展示 **Files:** - Create: `src/components/bark-battle-stats/BarkBattleWorkStatsPanel.tsx` - Test: `src/components/bark-battle-stats/BarkBattleWorkStatsPanel.test.tsx` **Fields:** - `playStartCount` - `finishCount` - `winCount` - `drawCount` - `lossCount` - `flaggedCount` - `leaderboardEntryCount` - `bestLeaderboardScore` - `bestFinalEnergy` - `averageFinalEnergy` - `updatedAt` ### Task 4.4: 广场卡片/我的作品适配 **Files:** - Modify: `src/components/custom-world-home/creationWorkShelf.ts` - Modify: `src/components/custom-world-home/CustomWorldCreationHub.tsx` - Modify: `src/components/rpg-entry/rpgEntryWorldPresentation.ts` - Modify: `src/services/publicWorkCode.ts` 如分享码需要支持 **Rules:** - Bark Battle 作品能展示、打开详情、开始游玩。 - 不新增独立 Bark Battle 专区。 --- ## 6. 阶段五:收口验证 ### Task 5.1: 自动测试清单 ```bash cargo test -p shared-contracts bark_battle cargo test -p module-bark-battle cargo test -p spacetime-module bark_battle cargo test -p spacetime-client bark_battle cargo test -p api-server bark_battle npm test -- --run packages/shared/src/contracts/barkBattle.test.ts npm test -- --run src/services/bark-battle/barkBattleClient.test.ts npm test -- --run src/components/bark-battle-creation/BarkBattleConfigEditor.test.tsx npm test -- --run src/games/bark-battle/domain/__tests__/BarkDetector.test.ts src/games/bark-battle/application/__tests__/BarkBattleController.test.ts src/games/bark-battle/ui/__tests__/BarkBattleRuntimeShell.test.tsx npx tsc -p tsconfig.typecheck-guardrails.json --noEmit --pretty false npm run check:encoding git diff --check ``` ### Task 5.2: 后端 smoke 1. 按项目脚本启动 SpacetimeDB + api-server,优先使用 `npm run api-server`,不要使用旧命令。 2. 确认 `/healthz`。 3. smoke 流程:创建草稿 → 保存配置 → 发布 → 拉 runtime config → start run → finish run → 查询 leaderboard/history/stats。 ### Task 5.3: 人工验收路径 1. 进入创作入口/玩法选择,选择 Bark Battle。 2. 在单页轻配置表单中填写标题,选择主题、狗狗皮肤、难度,保持排行榜开启。 3. 保存草稿。 4. 发布作品。 5. 发布后自动进入作品详情。 6. 点击开始游玩进入正式 runtime。 7. 授权麦克风,完成 30 秒单局。 8. 结算页显示后端 `serverResult` 和 score summary。 9. 若胜利,排行榜出现本局成绩。 10. 我的记录显示最近记录和个人最佳摘要。 11. 作品详情/作者视角能看到作品统计。 12. 广场/作品卡片和我的作品入口都能再次进入详情和 runtime。 --- ## 7. 不做范围 - 不做实时多人。 - 不做 ghost replay。 - 不做 AI 狗叫识别。 - 不保存原始音频、PCM、waveform 或可还原语音内容。 - 不做独立 Bark Battle 专区/活动页。 - 不做挑战分享、好友邀请、多人数房间。 - 不做复杂编辑器、多步骤向导、规则参数编辑、AI 生成配置。 - 不做 DAU/留存、按小时统计曲线、好友对比。 --- ## 8. 三人并行建议 ### 开发者 A:后端契约与领域规则 负责 Task 1.1、1.3、1.4。先提交 contracts 与 `module-bark-battle`,为后续后端/前端提供稳定类型和裁决规则。 ### 开发者 B:SpacetimeDB + api-server 负责 Task 2.1 到 2.6。必须等开发者 A 的 DTO/领域规则基本稳定后开始,或先基于计划字段开分支实现表结构。 ### 开发者 C:前端纵切与 UI 负责 Task 3.x 与 4.x。开始时可先做组件空态和 service client 类型,真正联调等 B 的 BFF ready。 --- ## 9. 推荐提交节奏 1. `feat: add bark battle contracts and domain rules` 2. `feat: add bark battle spacetime tables and reducers` 3. `feat: add bark battle api server routes` 4. `feat: add bark battle creation editor` 5. `feat: connect bark battle runtime to server results` 6. `feat: add bark battle leaderboard history stats` 7. `docs: finalize bark battle phase2 verification guide` --- ## 10. 完成定义 Phase 2 完成必须同时满足: - Bark Battle 可以从正式创作入口创建轻配置作品。 - 作品可以发布为稳定 workId。 - 作品详情/广场/我的作品可以发现并进入正式 runtime。 - runtime 从后端发布态 config 拉配置。 - start run 写 `work_play_start`。 - finish 只上传派生指标。 - 后端裁决 `serverResult` / `scoreSummary` / `leaderboardScore` / `antiCheatFlags`。 - 胜利局进入按 `workId + difficultyPreset + rulesetVersion` 分榜的排行榜。 - 个人历史和作品统计可查询。 - 自动测试、encoding、typecheck、diff check 和人工验收路径通过。