6 Commits

483 changed files with 6522 additions and 36207 deletions

View File

@@ -47,7 +47,7 @@ Default body:
}
```
For weak visual references in text-to-image generation, add:
For a reference image, add:
```json
{
@@ -55,26 +55,6 @@ For weak visual references in text-to-image generation, add:
}
```
For image-to-image work that must follow a reference image closely, use the VectorEngine edits endpoint instead of the generations `image` array:
```text
POST {VECTOR_ENGINE_BASE_URL}/v1/images/edits
Authorization: Bearer {VECTOR_ENGINE_API_KEY}
Content-Type: multipart/form-data
```
Multipart fields:
```text
model=gpt-image-2
prompt=<prompt>
n=1
size=1024x1024
image=@reference.png
```
Prefer edits for workflows where the reference image controls composition, pose, container shape, or layout. In this repository, Match3D container UI generation uses edits with `public/match3d-background-references/pot-fused-reference.png` as the `image` part.
Accept image output from `data[].url`, `data[].b64_json`, or direct nested `url` fields. VectorEngine GPT-image-2-all currently returns synchronously; do not poll APIMart task endpoints.
## Environment

View File

@@ -1,351 +0,0 @@
import { Buffer } from 'node:buffer';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const skillRoot = path.resolve(__dirname, '..');
const repoRoot = path.resolve(skillRoot, '..', '..', '..');
const defaultOutDir = path.join(repoRoot, 'public', 'anthro-cat-illustrations');
const defaultTimeoutMs = 180000;
const prompts = [
{
id: 'cat-barista',
title: '咖啡师猫咪',
subject:
'一只奶油色猫咪像人一样双足站立,穿深绿色围裙,在温暖咖啡馆吧台前专注拉花,爪子扶着咖啡杯,蓬松尾巴自然弯起,童书级精致插画,柔和自然光,主体清晰。',
},
{
id: 'cat-detective',
title: '侦探猫咪',
subject:
'一只黑白猫咪像侦探一样双足站在雨后街角,穿短风衣和小帽子,单爪拿放大镜,另一只爪插兜,路灯和湿润石板路反光,电影感但可爱,插画风格。',
},
{
id: 'cat-dancer',
title: '舞者猫咪',
subject:
'一只橘猫以拟人舞者姿态单脚旋转,穿轻盈舞台披肩,前爪展开,尾巴形成优雅弧线,背景是暖色小剧场灯光,动作灵动,精致插画。',
},
{
id: 'cat-knight',
title: '骑士猫咪',
subject:
'一只银灰猫咪像小骑士一样站在苔藓石台上,披短斗篷,双爪握着细剑指向地面,姿态勇敢但可亲,远处森林微光,奇幻插画风格。',
},
{
id: 'cat-painter',
title: '画家猫咪',
subject:
'一只三花猫咪双足站在画架前,穿宽松蓝色工作衫,一爪拿画笔一爪托调色盘,鼻尖有颜料点,窗边画室阳光明亮,温柔手绘插画。',
},
{
id: 'cat-astronaut',
title: '宇航员猫咪',
subject:
'一只白猫咪以拟人宇航员姿态站在月面,透明头盔内露出猫脸,尾巴在宇航服后轻轻翘起,爪子向远处蓝色星球敬礼,梦幻插画风格。',
},
];
const args = new Map();
for (let index = 2; index < process.argv.length; index += 1) {
const raw = process.argv[index];
if (raw.startsWith('--')) {
const next = process.argv[index + 1];
if (next && !next.startsWith('--')) {
args.set(raw, next);
index += 1;
} else {
args.set(raw, true);
}
}
}
function readDotenv(fileName) {
const filePath = path.join(repoRoot, fileName);
if (!existsSync(filePath)) {
return {};
}
const values = {};
for (const line of readFileSync(filePath, 'utf8').split(/\r?\n/u)) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) {
continue;
}
const match = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/u.exec(trimmed);
if (!match) {
continue;
}
let value = match[2].trim();
if (
(value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))
) {
value = value.slice(1, -1);
}
values[match[1]] = value;
}
return values;
}
function resolveEnv() {
const loaded = {
...readDotenv('.env.example'),
...readDotenv('.env.local'),
...readDotenv('.env.secrets.local'),
...process.env,
};
return {
baseUrl: String(loaded.VECTOR_ENGINE_BASE_URL || '')
.trim()
.replace(/\/+$/u, ''),
apiKey: String(loaded.VECTOR_ENGINE_API_KEY || '').trim(),
timeoutMs: Number.parseInt(
String(loaded.VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
10,
),
};
}
function buildVectorEngineImagesGenerationUrl(baseUrl) {
return baseUrl.endsWith('/v1')
? `${baseUrl}/images/generations`
: `${baseUrl}/v1/images/generations`;
}
function buildPrompt(entry) {
return [
'请生成一张高清 1:1 方形插画。',
`画面主体:${entry.subject}`,
'要求:猫咪保留清晰猫脸、猫耳、猫尾和毛发质感,但身体姿态像人一样自然;构图完整,角色占画面主体,适合作为项目插画素材。',
'避免文字、水印、边框、按钮、UI 元素、低清晰度、过度写实恐怖感、畸形肢体、多余手指。',
].join('');
}
function collectStringsByKey(value, targetKey, output) {
if (Array.isArray(value)) {
value.forEach((entry) => collectStringsByKey(entry, targetKey, output));
return;
}
if (!value || typeof value !== 'object') {
return;
}
for (const [key, nested] of Object.entries(value)) {
if (key === targetKey) {
if (typeof nested === 'string' && nested.trim()) {
output.push(nested.trim());
}
if (Array.isArray(nested)) {
nested.forEach((entry) => {
if (typeof entry === 'string' && entry.trim()) {
output.push(entry.trim());
}
});
}
}
collectStringsByKey(nested, targetKey, output);
}
}
function extractImageUrls(payload) {
const urls = [];
collectStringsByKey(payload, 'url', urls);
collectStringsByKey(payload, 'image', urls);
collectStringsByKey(payload, 'image_url', urls);
return [...new Set(urls)].filter((url) => /^https?:\/\//u.test(url));
}
function extractBase64Images(payload) {
const values = [];
collectStringsByKey(payload, 'b64_json', values);
return values;
}
function inferExtensionFromContentType(contentType) {
const normalized = contentType.split(';')[0]?.trim().toLowerCase();
if (normalized === 'image/png') {
return 'png';
}
if (normalized === 'image/webp') {
return 'webp';
}
if (normalized === 'image/gif') {
return 'gif';
}
return 'jpg';
}
function inferExtensionFromBytes(bytes) {
if (bytes.subarray(0, 8).equals(Buffer.from('\x89PNG\r\n\x1A\n', 'binary'))) {
return 'png';
}
if (bytes.subarray(0, 3).equals(Buffer.from([0xff, 0xd8, 0xff]))) {
return 'jpg';
}
if (
bytes.subarray(0, 4).toString('ascii') === 'RIFF' &&
bytes.subarray(8, 12).toString('ascii') === 'WEBP'
) {
return 'webp';
}
return 'png';
}
async function fetchJson(url, options, timeoutMs) {
const abortController = new AbortController();
const timer = setTimeout(() => abortController.abort(), timeoutMs);
try {
const response = await fetch(url, {
...options,
signal: abortController.signal,
});
const text = await response.text();
if (!response.ok) {
throw new Error(`VectorEngine ${response.status}: ${text.slice(0, 600)}`);
}
return JSON.parse(text);
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`VectorEngine request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
clearTimeout(timer);
}
}
async function downloadUrl(url, timeoutMs) {
const abortController = new AbortController();
const timer = setTimeout(() => abortController.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: abortController.signal });
if (!response.ok) {
throw new Error(`download ${response.status}`);
}
const bytes = Buffer.from(await response.arrayBuffer());
return {
bytes,
extension: inferExtensionFromContentType(
response.headers.get('content-type') || 'image/jpeg',
),
};
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`Generated image download timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
clearTimeout(timer);
}
}
async function generateOne(env, entry, outDir) {
const requestBody = {
model: 'gpt-image-2-all',
prompt: buildPrompt(entry),
n: 1,
size: '1024x1024',
};
const payload = await fetchJson(
buildVectorEngineImagesGenerationUrl(env.baseUrl),
{
method: 'POST',
headers: {
Authorization: `Bearer ${env.apiKey}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
},
env.timeoutMs,
);
const urls = extractImageUrls(payload);
const b64Images = extractBase64Images(payload);
let image;
if (urls[0]) {
image = await downloadUrl(urls[0], env.timeoutMs);
} else if (b64Images[0]) {
const bytes = Buffer.from(b64Images[0], 'base64');
image = {
bytes,
extension: inferExtensionFromBytes(bytes),
};
} else {
throw new Error(`VectorEngine returned no image for ${entry.id}`);
}
mkdirSync(outDir, { recursive: true });
const outputPath = path.join(outDir, `${entry.id}.${image.extension}`);
writeFileSync(outputPath, image.bytes);
return outputPath;
}
const dryRun = args.has('--dry-run') || !args.has('--live');
const outDir = path.resolve(String(args.get('--out-dir') || defaultOutDir));
const limit = Number.parseInt(String(args.get('--limit') || '0'), 10);
const selectedPrompts = limit > 0 ? prompts.slice(0, limit) : prompts;
if (dryRun) {
const env = resolveEnv();
console.log(
JSON.stringify(
{
mode: 'dry-run',
outDir,
count: selectedPrompts.length,
hasBaseUrl: Boolean(env.baseUrl),
hasApiKey: Boolean(env.apiKey),
requests: selectedPrompts.map((entry) => ({
id: entry.id,
title: entry.title,
body: {
model: 'gpt-image-2-all',
prompt: buildPrompt(entry),
n: 1,
size: '1024x1024',
},
})),
},
null,
2,
),
);
process.exit(0);
}
const env = resolveEnv();
if (!env.baseUrl || !env.apiKey) {
console.error(
JSON.stringify({
ok: false,
error: 'Missing VECTOR_ENGINE_BASE_URL or VECTOR_ENGINE_API_KEY',
hasBaseUrl: Boolean(env.baseUrl),
hasApiKey: Boolean(env.apiKey),
}),
);
process.exit(1);
}
const generated = [];
for (const entry of selectedPrompts) {
console.log(`Generating ${entry.id}...`);
generated.push(await generateOne(env, entry, outDir));
}
console.log(
JSON.stringify(
{
ok: true,
count: generated.length,
files: generated,
},
null,
2,
),
);

View File

@@ -122,7 +122,7 @@ RPG_LLM_WEB_SEARCH_ENABLED="true"
DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/api/v1"
DASHSCOPE_API_KEY="YOUR_DASHSCOPE_API_KEY"
# APIMart Responses config for creative-agent text/multimodal understanding.
# Server-side APIMart image generation config for optional puzzle image models.
APIMART_BASE_URL="https://api.apimart.ai/v1"
APIMART_API_KEY="YOUR_APIMART_API_KEY"
APIMART_IMAGE_REQUEST_TIMEOUT_MS="180000"

1
.gitignore vendored
View File

@@ -32,7 +32,6 @@ temp*build*/
/logs
.worktrees/
.env.secrets.local
spacetime.local.json
# Local load-test data extracted from private migration files
scripts/loadtest/data/*.local.json

View File

@@ -8,7 +8,6 @@
- 不提交个人配置、API Key、会话转录、模型密钥、本地路径密钥等敏感内容。
- 个人 Hermes 的 `~/.hermes/config.yaml``~/.hermes/.env``~/.hermes/sessions/` 不应复制到本仓库。
- 开发前先阅读本目录下与任务相关的记忆文件;开发后如产生稳定知识,更新对应文档。
- 后续新增的 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`,便于团队跨目录检索。
- 若本目录内容与 `docs/` 或代码事实冲突,以当前代码和最新 `docs/` 为准,并同步修正过期记忆。
## 目录结构
@@ -25,7 +24,6 @@
│ ├─ pitfalls.md # 踩坑与排障记录
│ └─ handoff-template.md # 任务交接模板
├─ plans/ # 阶段性计划与实施方案
├─ todos/ # 已定稿但尚未执行的共享 TODO 计划
├─ skills/ # 仓库级 Hermes skills
└─ plugins/ # 仓库级 Hermes plugins需显式启用项目 plugin
```
@@ -91,3 +89,4 @@ HERMES_ENABLE_PROJECT_PLUGINS=1 HERMES_PLUGINS_DEBUG=1 hermes chat -q "请读取
- 大段临时聊天记录
- 尚未确认的一次性猜测
- 构建产物、日志、缓存、数据库 dump

View File

@@ -1,549 +0,0 @@
# 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:<api-port>/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`,为后续后端/前端提供稳定类型和裁决规则。
### 开发者 BSpacetimeDB + 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 和人工验收路径通过。

View File

@@ -16,70 +16,14 @@
---
## 2026-05-15 微信充值支付路径以后端 JWT 设备快照为准
- 背景:前端隐藏非微信环境充值入口只能改善体验,不能阻止用户手动调用 `/api/profile/recharge/orders` 并伪造 `paymentChannel`
- 决策access JWT 只新增最小设备快照 `device.client_type/client_runtime/client_platform`,来源为登录或 refresh session 中的 `client_info`;不把完整 session、IP、UA 或设备列表塞进 JWT。真实微信充值下单必须由后端按 JWT 设备快照拦截:小程序 `wechat_mp` 只允许 `mini_program`,手机微信内网页 `wechat_h5` 只允许 `wechat_h5 + ios/android`,桌面微信内网页 `wechat_native` 只允许 `wechat_h5 + windows/macos/linux`。非微信环境前端不显示充值入口,改显示兑换码入口。
- 影响范围:`platform-auth` JWT claims、`api-server` auth session/refresh session 签发、`runtime_profile` 充值订单接口、前端支付平台隔离层和“我的”页常用功能区。
- 验证方式:执行 `npm run test -- src/services/payment/paymentPlatform.test.ts src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx``cargo test -p api-server profile_recharge_order --manifest-path server-rs/Cargo.toml``npm run typecheck``npm run check:encoding`
- 关联文档:`docs/technical/OIDC_JWT_CLAIMS_DESIGN_2026-04-21.md``docs/technical/MY_TAB_ACCOUNT_RECHARGE_IMPLEMENTATION_2026-04-25.md`
## 2026-05-14 抓大鹅物品素材批量重新生成复用 item-assets 替换模式
- 背景:抓大鹅结果页 `素材配置 > 物品` 需要在不改变玩法物品映射的前提下,批量重新生成已存在物品的 2D 五视角图片。
- 决策:继续复用 `POST /api/creation/match3d/works/{profileId}/item-assets`,请求体通过 `mode = "replace"` 表达替换模式;前端面板预填当前素材名称,只提交仍能匹配到已有素材的名称。后端只替换匹配素材的 `imageSrc/imageObjectKey/imageViews/status/error`,保留原 `itemId`、列表顺序、模型兼容字段、UI 背景、历史背景音乐和点击音效字段;未匹配名称不计费、不新增、不持久化。
- 影响范围Match3D 结果页素材配置、前端/后端 shared contracts、`api-server` Match3D item-assets 编排、运行态物品类型映射和素材生成技术文档。
- 验证方式:执行 `npm run test -- src/components/match3d-result/Match3DResultView.test.tsx``cargo test -p api-server match3d_item_asset --manifest-path server-rs\Cargo.toml``cargo test -p api-server match3d_regenerated_asset --manifest-path server-rs\Cargo.toml``npm run check:encoding`
- 关联文档:`docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 2026-05-14 拼图与抓大鹅音频生成入口临时关闭
- 背景:当前需要暂时关闭抓大鹅、拼图中生成背景音乐和音效的能力,并隐藏草稿中的相关入口。
- 决策:拼图 `compile_puzzle_draft` 不再自动生成背景音乐,结果页素材配置只保留 `UI`;抓大鹅 `match3d_compile_draft` 和批量新增只生成 2D 图片、背景和容器 UI不再调用 Suno/Vidu结果页隐藏 `背景音乐` 子 Tab 与点击音效生成控件;通用 `/api/creation/audio/*` 当前整体返回 `410 Gone`。历史已写入的 `backgroundMusic` / `clickSound` 字段保留,运行态继续兼容播放旧音频。
- 影响范围:`api-server` 拼图/抓大鹅草稿编排、通用创作音频路由、拼图/抓大鹅结果页、生成进度模型、相关技术文档。
- 验证方式:执行拼图/抓大鹅结果页定向测试、生成进度单测、`cargo check -p api-server --manifest-path server-rs/Cargo.toml``npm run check:encoding`
- 关联文档:`docs/technical/PUZZLE_MATCH3D_RESULT_AUDIO_TAB_2026-05-11.md``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 2026-05-14 抓大鹅物品素材 sheet 改用 VectorEngine Gemini
- 背景:抓大鹅 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`、抓大鹅素材生成技术文档。
- 验证方式:执行 `cargo test -p api-server match3d_material_sheet --manifest-path server-rs\Cargo.toml``cargo test -p api-server match3d_vector_engine_gemini --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`
## 2026-05-14 草稿页作品卡对齐分类页列表
- 背景:草稿页作品架原本偏封面大卡片,和发现页分类列表的横向卡片样式不一致;生成中状态也缺少整卡级的统一遮罩。
- 决策:草稿页作品卡统一收口为与分类页一致的横向列表卡结构,左侧承载标题/状态/类型/摘要与必要数据,右侧显示带透明度的封面图;移动端保持单列列表,网页端使用两到三列卡片式网格,避免宽屏长条列表。不再常驻“继续创作”“查看详情”“查看进度”等右侧动作按钮。原有删除、分享、积分激励、公开统计、未读红点全部保留,其中删除与分享进入左滑操作层,常态不显示删除按钮,也不得透出删除底层。生成中的作品在整卡上加半透明蒙版、旋转等待符号和“生成中...”标识,但不移除任何原有信息。
- 影响范围:`src/components/custom-world-home/CustomWorldCreationHub.tsx``src/components/custom-world-home/CustomWorldWorkCard.tsx`、相关样式与测试、草稿页 UI 文档。
- 验证方式:草稿页作品卡与分类页列表视觉口径保持一致;`npm run test -- src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx``npm run typecheck``npm run check:encoding`
- 关联文档:`docs/design/MOBILE_CREATION_WORK_LIST_TWO_COLUMN_LAYOUT_2026-04-29.md``docs/experience/MOBILE_UI_DEV_EXPERIENCE.md`
## 2026-05-13 认证运行期同步直接导入正式认证表
- 背景:`auth_store_snapshot` 是 Stage 1 整包快照过渡表,主键固定 `default`,会让所有用户状态集中在一条 `snapshot_json`Stage 2/3 已有 `user_account/auth_identity/refresh_session` 正式认证表,继续刷新 `default` 容易让运行时真相和表拆分目标混在一起。
- 决策:运行期认证变更继续由 `module-auth` 生成一致内存快照,但 `api-server` 改为调用 `import_auth_store_snapshot_json` 直接覆盖导入 `user_account/auth_identity/refresh_session``auth_store_projection_meta/default` 只记录正式认证表最近一次导入时间;`upsert_auth_store_snapshot``import_auth_store_snapshot` 仅保留为旧库迁移和兜底入口。
- 影响范围:`spacetime-module` auth procedures/tables、`spacetime-client` auth facade/bindings、`api-server` 认证同步和启动恢复、SpacetimeDB 表目录与认证 Stage 3 文档。
- 验证方式:执行 `npm run spacetime:generate -- --rust-only``cargo check -p api-server --manifest-path server-rs/Cargo.toml`、认证相关定向测试和 `npm run check:encoding`
- 关联文档:`docs/technical/AUTH_SPACETIMEDB_FORMAL_TABLE_RECOVERY_STAGE3_2026-04-24.md``docs/technical/SPACETIMEDB_TABLE_CATALOG.md`
## 2026-05-13 微信小程序支付以后端通知为唯一入账事实
- 背景:“我的”账户充值需要接入微信小程序支付,同时保留本地 / H5 mock 支付联调能力。
- 决策:`paymentChannel = "mock"` 继续创建即 paid 订单并立即入账;`paymentChannel = "wechat_mp"` 先在 `profile_recharge_order` 写入 `pending` 订单,再由 `api-server` 调微信支付 JSAPI 下单并返回小程序 `wx.requestPayment` 参数。小程序或 H5 的支付成功回调只触发刷新,不直接发放点或会员;最终入账只由 `/api/profile/recharge/wechat/notify` 验签、解密并确认 `trade_state = SUCCESS` 后完成。`provider_transaction_id` 保存微信支付平台交易号,用于对账、查单、退款和客服排障。
- 决策:`paymentChannel = "mock"` 继续创建即 paid 订单并立即入账;`paymentChannel = "wechat_mp"` 先在 `profile_recharge_order` 写入 `pending` 订单,再由 `api-server` 调微信支付 JSAPI 下单并返回小程序 `wx.requestPayment` 参数。小程序或 H5 的支付成功回调只触发刷新,不直接发放点或会员;最终入账只由 `/api/profile/recharge/wechat/notify` 验签、解密并确认 `trade_state = SUCCESS` 后完成。`provider_transaction_id` 保存微信支付平台交易号,用于对账、查单、退款和客服排障。
- 影响范围:`profile_recharge_order` 表、SpacetimeDB 充值 procedure、`api-server` 微信支付客户端、小程序 native 支付页、H5 充值弹窗与共享 contract。
- 验证方式:执行 `npm run typecheck``npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx``cargo test -p module-runtime recharge --manifest-path server-rs/Cargo.toml``cargo test -p api-server wechat_pay --manifest-path server-rs/Cargo.toml`,后端联调仍用 `npm run api-server``/healthz`
- 关联文档:`docs/technical/MY_TAB_ACCOUNT_RECHARGE_IMPLEMENTATION_2026-04-25.md``docs/technical/SPACETIMEDB_TABLE_CATALOG.md`
## 2026-05-15 微信充值默认真实渠道与 mock 禁用
- 背景:账户充值扩展到普通商户直连 H5 与 Native 支付后,旧的“非小程序默认 mock”会把真实用户充值静默导向测试通道。
- 决策:默认支付渠道只由设备平台隔离层解析为 `wechat_mp` / `wechat_h5` / `wechat_native`:小程序走 `wechat_mp`,移动网页含微信内 H5 走 `wechat_h5`,桌面网页走 `wechat_native` 二维码。`paymentChannel` 缺失或未知直接 `400`;生产/真实支付配置拒绝 `mock`,只有自动测试或显式 mock 测试配置可手动传 `paymentChannel = "mock"`。真实微信渠道必须在 `WECHAT_PAY_ENABLED=true``WECHAT_PAY_PROVIDER=real` 下单,禁止由 mock provider 返回 H5/Native/小程序 mock 支付载荷。所有微信渠道仍以后端通知与服务端查单入账。
- 影响范围:`src/services/payment/paymentPlatform.ts``RpgEntryHomeView` 充值弹窗、`api-server` 充值订单接口、`WechatPayClient` H5/Native 下单、共享 recharge contracts。
- 验证方式:执行 `npm run test -- src/services/payment/paymentPlatform.test.ts src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx``cargo test -p module-runtime recharge --manifest-path server-rs/Cargo.toml``cargo test -p api-server wechat_pay --manifest-path server-rs/Cargo.toml``npm run typecheck``npm run check:encoding`
- 关联文档:`docs/technical/MY_TAB_ACCOUNT_RECHARGE_IMPLEMENTATION_2026-04-25.md`
## 2026-05-13 修改密码后全设备强制下线
- 背景:修改密码原本只递增 `token_version`,旧 access token 会失效,但旧 refresh cookie 仍可通过 `/api/auth/refresh` 重新签发新 token不符合“改密后全设备强制下线”的账号安全预期。
@@ -107,7 +51,7 @@
## 2026-05-12 拼图与抓大鹅草稿背景音乐按纯音乐自动生成
- 背景:拼图和抓大鹅需要在草稿生成阶段直接产出可试听、可重生成、可进入运行态循环播放的背景音乐。
- 决策:复用通用 VectorEngine Suno 创作音频链路,不新增 SpacetimeDB 表;拼图音乐保存到首关 `PuzzleDraftLevel.backgroundMusic`,运行态通过 `PuzzleRuntimeLevelSnapshot.backgroundMusic` 下发;抓大鹅音乐保存到首个 `generatedItemAssets[].backgroundMusic`。两者草稿生成都使用 `title` 驱动、`prompt = ""``make_instrumental = true`;自动草稿阶段必须拿到可播放 `audioSrc` 才能返回成功,失败时停留在生成页并允许重试同一 session/profile。结果页内的手动重新生成继续作为已有草稿的补救入口
- 决策:复用通用 VectorEngine Suno 创作音频链路,不新增 SpacetimeDB 表;拼图音乐保存到首关 `PuzzleDraftLevel.backgroundMusic`,运行态通过 `PuzzleRuntimeLevelSnapshot.backgroundMusic` 下发;抓大鹅音乐保存到首个 `generatedItemAssets[].backgroundMusic`。两者草稿生成都使用 `title` 驱动、`prompt = ""``make_instrumental = true`,失败只降级记录 warning结果页允许重新生成
- 影响范围:`api-server` 音频生成、拼图草稿编译、抓大鹅草稿编译、Puzzle/Match3D 结果页和运行态音频播放。
- 验证方式:检查草稿 response / work detail 中的 `backgroundMusic.audioSrc`,运行态开局后隐藏 audio 循环播放;执行音频相关后端 check、前端 typecheck 和编码检查。
- 关联文档:`docs/technical/PUZZLE_MATCH3D_RESULT_AUDIO_TAB_2026-05-11.md``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
@@ -115,15 +59,15 @@
## 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 背景,失败只记录 warning 并允许结果页重试;结果页新增 `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。
- 影响范围:拼图结果页、拼图运行态背景渲染、拼图 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`
## 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 表。
- 背景:抓大鹅结果页需要支持面图上传 / AI 重绘、物品素材独立预览、单项删除和批量新增,且不能把素材编辑继续做成列表内联展开或前端临时状态。
- 决策:结果页 `作品信息`面图点击打开独立面板,参考图可来自本地上传、物品素材和 UI 素材AI 重绘统一调用 `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 表。
- 影响范围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`
@@ -143,22 +87,6 @@
- 验证方式:执行 `npm run check:encoding``node scripts/check-wechat-miniprogram-auth-smoke.mjs``cargo test -p shared-contracts wechat_bind_phone_request_accepts_mini_program_phone_code --manifest-path server-rs/Cargo.toml``cargo test -p api-server wechat_miniprogram_bind_phone_code_activates_pending_user --manifest-path server-rs/Cargo.toml -- --nocapture`
- 关联文档:`docs/technical/WECHAT_MINIPROGRAM_WEB_VIEW_SHELL_2026-05-03.md`
## 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正式持久化后续再设计。
- 影响范围:`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`
## 2026-05-12 宝贝识物创作同时生成玩法视觉主题包
- 背景:`宝贝识物` 创作原本只根据两个关键词生成物品透明图运行态背景、UI、礼物盒和篮子仍使用固定 CSS 绘本风,无法根据“小猪佩琪 / 奥特曼”或“苹果 / 橘子”等创作者提示词做主题化包装。
- 决策:`POST /api/creation/edutainment/baby-object-match/assets` 同一次 image-2 / VectorEngine 调用链返回两个物品图和 `visualPackage`。视觉包包含 `background``ui-frame``gift-box``basket``smoke-puff` 五类资源;总风格保持寓教于乐明亮卡通绘本插画风,主题按两个物品关键词匹配,水果偏果园自然,动漫角色 / 玩具偏动漫玩具。物品图和礼物盒 / 篮子 / UI / 烟雾特效资源走透明 PNG 后处理,背景为清爽不遮挡玩法区的环境图;运行态中礼物盒按约 2 倍视觉尺寸展示、篮子按约 1.5 倍展示,礼物盒打开时使用 `smoke-puff` 弹出中央物品并移除礼盒。前端草稿保存该包,运行态消费该包;旧草稿以 `visualPackage = null` 继续使用 CSS 兜底。
- 影响范围:`packages/shared/src/contracts/edutainmentBabyObject.ts``server-rs/crates/api-server/src/edutainment_baby_object.rs``src/services/edutainment-baby-object/babyObjectMatchClient.ts``src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.tsx``src/index.css`、宝贝识物 PRD 与技术方案。
- 验证方式:执行宝贝识物 service / runtime 定向测试、`cargo test -p api-server edutainment_baby_object --manifest-path server-rs/Cargo.toml`、相关 ESLint 与编码检查;真实生图需配置 `VECTOR_ENGINE_BASE_URL``VECTOR_ENGINE_API_KEY`
- 关联文档:`docs/prd/BABY_OBJECT_MATCH_EDUTAINMENT_TEMPLATE_PRD_2026-05-11.md``docs/technical/BABY_OBJECT_MATCH_CREATION_PUBLISH_IMPLEMENTATION_2026-05-11.md`
## 2026-05-11 拼图与抓大鹅结果页音频资产复用通用创作音频链路
- 背景:拼图和抓大鹅结果页需要接入 Suno 背景音乐,抓大鹅还需要物体点击音效,但当前两类作品没有独立的作品级音频表或 metadata 字段。
@@ -192,14 +120,6 @@
- 验证方式:执行入口配置、创作 Hub 和平台入口交互定向测试,确认看不到“方洞挑战” Tab、按钮和作品架条目。
- 关联文档:`docs/technical/NEW_WORK_ENTRY_CONFIG_2026-05-01.md``docs/design/PLATFORM_CREATE_TAB_CREATIVE_AGENT_HOME_2026-05-05.md`
## 2026-05-14 视觉小说从创作页入口隐藏
- 背景:当前创作页需要关闭视觉小说模板入口,不能继续在模板 Tab、旧选择弹层或创作 Hub 卡片中展示。
- 决策SpacetimeDB `creation_entry_type_config` 默认种子中 `visual-novel.visible=false``open=false`;旧默认可见配置会被迁移为隐藏和关闭。前端继续只消费 `GET /api/creation-entry/config`,不得用硬编码恢复视觉小说模板入口。
- 影响范围SpacetimeDB 入口配置默认种子、api-server 测试配置、创作页模板 Tab、创作 Hub 测试和创作入口文档。
- 验证方式:执行入口配置、创作 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-10 运行态输入设备抽象层全项目通用化
- 背景:拼图运行态接入 mocap 后,鼠标/触控和 mocap 各自维护输入逻辑会导致合并大块、拖拽语义和取消会话行为不一致;后续其他玩法也需要复用体感、摇杆、键盘等设备输入。
@@ -211,7 +131,7 @@
## 2026-05-11 前端调试模式统一判断
- 背景:拼图 mocap 调试面板此前在运行态常驻展示,生产构建和正式体验里容易遮挡棋盘内容;后续其它局部诊断 UI 也需要统一的调试模式入口。
- 决策:前端新增 `src/config/debugMode.ts` 作为全局调试模式判断,默认跟随 Vite 开发态,允许 `VITE_DEBUG_MODE=true/false` 显式覆盖。2026-05-14 起,拼图运行态已临时移除 mocap 调用、体感光标和 mocap 调试面板调试模式仍供其它局部诊断 UI 使用
- 决策:前端新增 `src/config/debugMode.ts` 作为全局调试模式判断,默认跟随 Vite 开发态,允许 `VITE_DEBUG_MODE=true/false` 显式覆盖。拼图运行态 mocap 调试面板只在调试模式下渲染,并默认折叠,只保留连接状态行
- 影响范围:前端局部调试 UI、拼图运行态 mocap 诊断面板、`.env.example` 和运行态输入技术文档。
- 验证方式:执行 `npm run test -- src\components\puzzle-runtime\PuzzleRuntimeShell.test.tsx``npm run typecheck` 和编码检查。
- 关联文档:`docs/technical/RUNTIME_INPUT_DEVICE_ABSTRACTION_2026-05-10.md`
@@ -282,10 +202,10 @@
- 验证方式:未登录首次访问应展示新手引导;生成后只进入 1 关本地拼图;通关后登录保存应在当前用户拼图作品架出现草稿作品;不应产生 SpacetimeDB schema 变更。
- 关联文档:`docs/prd/FIRST_LAUNCH_PUZZLE_ONBOARDING_PRD_2026-05-05.md`
## 2026-05-05 text-game 作为陶泥儿幕间文字游戏模板接入
## 2026-05-05 text-game 作为百梦幕间文字游戏模板接入
- 背景:团队希望参考 MOKU / 幕间类 AI 文游,设计可在陶泥儿内落地的 AI 文字游戏模板,但不能把外部平台社区、支付、榜单、论坛、账号或私有存档迁入 Genarrative。
- 决策:新增 `text-game` 作为陶泥儿 AI 原生文字游戏模板口径,展示名可用“幕间”或“幕间文字”;它与 `visual-novel` 分离,重点是 AI GM、自由行动、状态后果、长期记忆、章节目标和轻量剧本模拟器入口、作品、发布、资产、钱包、埋点、存档和广场全部复用陶泥儿平台接口;禁止新增 replay、外部社区、外部支付、外部榜单和私有存档系统。
- 背景:团队希望参考 MOKU / 幕间类 AI 文游,设计可在百梦内落地的 AI 文字游戏模板,但不能把外部平台社区、支付、榜单、论坛、账号或私有存档迁入 Genarrative。
- 决策:新增 `text-game` 作为百梦 AI 原生文字游戏模板口径,展示名可用“幕间”或“幕间文字”;它与 `visual-novel` 分离,重点是 AI GM、自由行动、状态后果、长期记忆、章节目标和轻量剧本模拟器入口、作品、发布、资产、钱包、埋点、存档和广场全部复用百梦平台接口;禁止新增 replay、外部社区、外部支付、外部榜单和私有存档系统。
- 影响范围:后续 `text-game` shared contracts、`module-text-game`、SpacetimeDB 表、`api-server` 路由、前端入口 / workspace / result / runtime、平台作品架和发现聚合。
- 验证方式:后续落地时确认路由使用 `/api/creation/text-game/*``/api/runtime/text-game/*`;确认正式业务真相在 Rust / SpacetimeDB 后端;确认没有 `replay` 能力和外部平台功能误入;确认 `text-game` 不复用 `visual-novel` step 契约作为运行态真相。
- 关联文档:`docs/prd/AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md`

View File

@@ -69,8 +69,6 @@ npm run dev:web
npm run api-server
```
该命令会保留终端实时输出,并把同一份输出持久化到 `logs/api-server/api-server-<timestamp>.log`。完整联调入口 `npm run dev` / `npm run dev:rust` 启动的 Rust `api-server` 也会写入 `logs/api-server/api-server-dev-rust-<timestamp>.log`。如需改写路径,可设置 `GENARRATIVE_API_SERVER_LOG_FILE`;如只改目录,可设置 `GENARRATIVE_API_SERVER_LOG_DIR`
查看本地 Rust/SpacetimeDB 日志:
```bash

View File

@@ -30,8 +30,6 @@
- `operations/`:后台运营核查、对账和排障查询。
- `prd/`:产品需求与阶段计划。
新增 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`。标签用于跨目录检索,不替代 `docs/` 的目录分类;历史文档不要求批量重命名。
## 推荐阅读顺序
通用复杂任务:
@@ -98,6 +96,5 @@ RPG 创作与运行时链路:
- 新增工程实现时,如果已有对应文档,必须同步更新。
- 如果没有对应文档,新文档放入 `docs/` 下合适分类。
- 新文档文件名必须使用 `【标签名】` 前缀,标题尽量保留中文语义,日期使用 `YYYY-MM-DD`
- `.hermes/shared-memory/` 只保留跨任务、跨成员、高频使用的摘要和索引。
- 如果文档与代码冲突,先确认代码事实,再更新过期文档和共享记忆。

View File

@@ -14,14 +14,6 @@
- 关联:相关文件、文档、提交或 Issue
```
## 抓大鹅批量重新生成物品不要新增 itemId
- 现象:结果页批量重新生成物品后,试玩或正式运行态的物品类型和图片对应关系漂移,或者用户输入一个不存在名称后被当作新物品追加。
- 原因:重新生成和批量新增共用 `item-assets` 接口,如果前端不传 `mode = "replace"`,或后端替换时重新分配 `itemId` / 追加未匹配名称,就会破坏 `generatedItemAssets` 顺序和运行态类型映射。
- 处理:批量重新生成只提交当前素材列表中能匹配到的名称,并传 `mode = "replace"`;后端只对同名已有素材生成新图片,合并时保留原 `itemId``itemName`、模型兼容字段、UI 背景和历史音频字段,未匹配名称直接忽略且不计费。
- 验证:`npm run test -- src\components\match3d-result\Match3DResultView.test.tsx` 覆盖前端提交口径,`cargo test -p api-server match3d_item_asset --manifest-path server-rs\Cargo.toml``cargo test -p api-server match3d_regenerated_asset --manifest-path server-rs\Cargo.toml` 覆盖后端替换计划与身份保留。
- 关联:`src/components/match3d-result/Match3DResultView.tsx``server-rs/crates/api-server/src/match3d.rs``packages/shared/src/contracts/match3dWorks.ts``server-rs/crates/shared-contracts/src/match3d_works.rs``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## OSS V4 签名时间和 bucket/object_key 兼容
- 现象OSS V4 私有读签名在部分时间点失败,可能出现 `OSS V4 签名时间格式化失败` 或服务端判定签名格式错误;排查用例中 bucket 为 `xushi-dev`object_key 为 `generated-square-hole-assets/.../image.png`
@@ -33,19 +25,11 @@
## generated 音频路径进运行态前要先换签
- 现象:草稿页 audio 控件能播放背景音乐但拼图或抓大鹅运行态开局后背景音乐不响Network 可能出现裸 `/generated-*-assets/...mp3` 私有路径 403。
- 原因:生成音乐转存到 OSS 私有对象后,`audioSrc` 是 generated legacy path浏览器 `<audio>` 不能像公开静态资源一样直接请求裸路径。另一个常见误判是浏览器拒绝自动播放,资源已经进入运行态但开局第一次 `audio.play()` 被拦截。
- 处理:结果页试听控件和运行态隐藏 `<audio>` 设置 `src` 前,先通过 `useResolvedAssetReadUrl``resolveAssetReadUrl` 换签;签名未就绪时不要回退请求裸 generated 路径。运行态自动播放失败只静默兜底,但玩家首次按下拼图块或点击抓大鹅物品时要重试同一个背景音乐播放函数。拼图读取 `currentLevel.backgroundMusic.audioSrc`,抓大鹅读取 `generatedItemAssets[].backgroundMusic.audioSrc`
- 验证:结果页试听和运行态 `<audio loop>``src` 为签名 URL 或公开 URL拼图/抓大鹅运行态首次局内交互后会再次尝试播放背景音乐;`npm run typecheck` 不报契约字段缺失,后端 run response 带 `backgroundMusic`
- 原因:生成音乐转存到 OSS 私有对象后,`audioSrc` 是 generated legacy path浏览器 `<audio>` 不能像公开静态资源一样直接请求裸路径。
- 处理:运行态隐藏 `<audio>` 设置 `src` 前,先通过 `useResolvedAssetReadUrl``resolveAssetReadUrl` 换签;播放失败只静默兜底,不阻断局内交互。拼图读取 `currentLevel.backgroundMusic.audioSrc`,抓大鹅读取 `generatedItemAssets[].backgroundMusic.audioSrc`
- 验证:运行态开局后 `<audio loop>``src` 为签名 URL 或公开 URL`npm run typecheck` 不报契约字段缺失,后端 run response 带 `backgroundMusic`
- 关联:`src/components/puzzle-runtime/PuzzleRuntimeShell.tsx``src/components/match3d-runtime/Match3DRuntimeShell.tsx``docs/technical/PUZZLE_MATCH3D_RESULT_AUDIO_TAB_2026-05-11.md`
## 抓大鹅背景音乐是作品级字段但暂存在首个物品素材
- 现象:抓大鹅草稿生成日志和 work detail 中已有背景音乐,但结果页 `素材配置 > 背景音乐` 显示“暂无音乐”,点击试玩后局内也不播放生成音乐。
- 原因:当前表结构没有作品级音频字段,背景音乐暂存在 `generatedItemAssets[]`。如果 action response 的 draft assets 缺音乐,前端又优先用它覆盖 work detail或音乐落在非首个素材而结果页只读 `assetDrafts[0].backgroundMusic`,就会丢掉已生成音乐。
- 处理:前端统一使用 `normalizeMatch3DGeneratedItemAssetsForRuntime` / `mergeMatch3DGeneratedItemAssetsForRuntime`:把任意素材上的 `backgroundMusic` 与音乐元信息迁移到首个素材清空其它素材上的作品级音乐字段action draft assets 与 work detail assets 按 `itemId` 合并保留详情里的音乐、UI 背景和点击音效。
- 验证:`npm run test -- src\services\match3dGeneratedModelCache.test.ts src\components\match3d-result\Match3DResultView.test.tsx src\components\match3d-runtime\Match3DRuntimeShell.test.tsx`;平台推荐流定向跑 `RpgEntryFlowShell.agent.interaction.test.tsx` 中的 Match3D runtime assets 用例;`npm run typecheck`
- 关联:`src/services/match3dGeneratedModelCache.ts``src/components/match3d-result/Match3DResultView.tsx``src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 中文乱码与编码风险
- 现象:中文文案、注释、剧情或文档显示为乱码,或被改写成英文。
@@ -67,16 +51,6 @@
- 验证:执行 `cargo test -p module-auth password --manifest-path server-rs/Cargo.toml``cargo test -p api-server password --manifest-path server-rs/Cargo.toml`;手测时重设密码后旧密码应失败,新密码应成功,重启后仍应保持。
- 关联:`server-rs/crates/api-server/src/password_management.rs``server-rs/crates/api-server/src/state.rs``docs/technical/PASSWORD_LOGIN_CHANGE_RESET_DESIGN_2026-04-24.md`
## 抓大鹅生成页只显示服务暂不可用先查 reason 和外部服务配置
- 现象:点击生成抓大鹅草稿后,页面只提示“服务暂不可用”,或者本地 `npm run api-server` 看似启动但生成接口不可用。
- 原因:配置缺失类错误通常在后端 `error.details.reason` 中给出具体缺项,前端如果只读 `details.message` 会吞掉原因;本地只配置 `ALIYUN_OSS_BUCKET` / `ALIYUN_OSS_ENDPOINT` 时,旧逻辑还会在启动期构造空 AccessKey 的 OSS 客户端并失败。抓大鹅新链路仍是 2D 生图切割,不需要也不应回退 Rodin/GLB。
- 处理:前端 API 错误展示读取 `details.message` 后继续读取 `details.reason``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` 单格宽度空白间距,避免切割后相邻格内容污染。
- 验证:`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 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}` 排查。
## `.hermes` 只放共享内容,不放个人 Hermes 配置
- 现象:团队成员误把个人 Hermes 配置、会话或密钥复制进仓库。
@@ -93,55 +67,15 @@
- 验证:运行 `npx vitest run src\services\useMocapInput.test.ts src\components\child-motion-demo\ChildMotionWarmupDemo.test.tsx`,并在本地硬件服务启动后进入 `/child-motion-demo` 实测站位、招手、左右手挥动和跳跃阶段。
- 关联:`src/services/useMocapInput.ts``src/components/child-motion-demo/ChildMotionWarmupDemo.tsx``docs/technical/CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md`
## 儿童动作 Demo 左右手阶段误通过先查身体侧映射和手臂展开阈值
- 现象:热身关“挥动左手 / 挥动右手”阶段,用户只是手自然下垂、横向小幅抖动,或挥了相反侧手,也可能被判定通过。
- 原因:本地 mocap 的 handedness 当前按摄像头视角输出,不能直接当作用户身体左/右;同时左右手阶段的目标是确认现实空间安全,需要验证手臂向外打开和上下摆动角度,不能只看手部 `x` 轨迹范围。
- 处理:热身关中用户左手应消费 camera-right用户右手应消费 camera-left左右手阶段只在同侧肩肘腕外展、手腕非自然下垂、连续有效帧、横向范围、上下摆动范围、肩腕角度范围和上下方向变化全部达标时完成并记录轨迹空间包络、角度范围和最大外展距离。
- 验证:运行 `npx vitest run src\components\child-motion-demo\ChildMotionWarmupDemo.test.tsx src\components\child-motion-demo\childMotionWarmupModel.test.ts`,确认相反侧手、自然下垂、单纯横向轨迹不会完成,真实展开上下摆动可以完成。
- 关联:`src/components/child-motion-demo/ChildMotionWarmupDemo.tsx``src/components/child-motion-demo/childMotionWarmupModel.ts``docs/technical/CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md`
## 儿童动作 Demo 角色轮廓抽搐先查 mocap 坐标防抖和渲染分层
- 现象:`/child-motion-demo` 中间半透明小人在真实硬件驱动下左右轻微来回摆,移动过程中看起来忽大忽小,用户很难稳定停在目标圆环内。
- 原因:`general.body.center_norm.x` 原始值逐包直接写入 `avatarX` 时,硬件坐标小噪声会直接驱动位置保持判定和 CSS 动画;如果角色外层同时承担横向定位和跳跃 `transform`,半透明 PNG 在移动时也更容易出现重采样抖动观感。
- 处理mocap 身体中心进入角色位置前必须先 clamp再经过小幅死区、低通阻尼和单包最大步长限制键盘 A/D 调试输入仍保持即时。角色 DOM 外层只负责横向定位,内层 sprite 负责轮廓图和跳跃位移,避免同一层 `transform` 同时表达多种运动。
- 验证:运行 `npx vitest run src\components\child-motion-demo\ChildMotionWarmupDemo.test.tsx src\components\child-motion-demo\childMotionWarmupModel.test.ts src\services\useMocapInput.test.ts src\services\child-motion-demo\childMotionDebugInput.test.ts`,并用真实硬件进入站位阶段观察小幅身体晃动不会导致角色频繁左右跳动。
- 关联:`src/components/child-motion-demo/ChildMotionWarmupDemo.tsx``src/index.css``docs/technical/CHILD_MOTION_DEMO_WARMUP_IMPLEMENTATION_SPEC_2026-05-09.md`
## 宝贝识物选篮误触发先查多套判定和残余轨迹
- 现象:`宝贝识物` 运行态打开礼物盒或反馈结束后,当前物品被连续送入左侧或右侧篮子,或硬件动作名偶发命中导致未做明确横移动作也触发选篮。
- 原因:选篮如果同时消费 `wave_left_hand` / `wave_right_hand` / `wave` 动作名和手部轨迹,或在 `correct` / `wrong` 反馈阶段继续累计手部路径,会把抓握、反馈期间残留移动或未知侧别手部误算成下一次选篮。
- 处理:宝贝识物选篮只使用明确 `leftHand` / `rightHand` 的连续横向轨迹阈值;侧别为 `unknown` 的手部轨迹不参与选篮;反馈阶段清空轨迹,不在非 `active` 阶段累计路径。进入关卡和每次正确反馈结束后自动弹出物品,不再`open_palm -> grab` 抓握序列激活礼物盒
- 处理:宝贝识物选篮只使用明确 `leftHand` / `rightHand` 的连续横向轨迹阈值;侧别为 `unknown` 的手部轨迹不参与选篮;礼物盒打开和反馈阶段清空轨迹,不在非 `active` 阶段累计路径。礼物盒激活仍使`open_palm -> grab` 抓握序列。
- 补充:当前本地 mocap 的 handedness 是摄像头视角,宝贝识物选篮前需要换算为用户身体视角;`rightHand` 轨迹代表玩家左手并进入左篮,`leftHand` 轨迹代表玩家右手并进入右篮。键鼠调试不走该换算,仍保持鼠标左键=左篮、右键=右篮。
- 验证:运行 `npm run test -- src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.test.tsx src/services/useMocapInput.test.ts`,确认动作名负向测试、未知侧别负向测试和左右手横向轨迹测试通过。
- 关联:`src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.tsx``docs/technical/BABY_OBJECT_MATCH_CREATION_PUBLISH_IMPLEMENTATION_2026-05-11.md`
## 宝贝爱画左右手反了先查 mocap 摄像头视角换算
- 现象:`宝贝爱画` 中真实硬件下左手指示器和右手画笔表现反向,用户抬右手却出现左手选色指示器,或抬左手却驱动画笔 / 橡皮。
- 原因:本地 mocap 的 handedness 当前按摄像头视角输出,不能直接当成用户身体左 / 右;宝贝爱画初版直接消费 `latestCommand.leftHand/rightHand`,漏做摄像头视角到用户身体视角的换算。
- 处理:宝贝爱画运行态消费 mocap 前先换算:`rightHand` 作为用户左手,用于颜色悬停和左手指示器;`leftHand` 作为用户右手,用于画笔 / 橡皮光标、绘制、擦除和工具切换。键鼠调试输入不做该换算,继续保持鼠标左键为左手、右键为右手。
- 验证:运行 `npm run test -- src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.test.tsx src/components/edutainment-runtime/babyLoveDrawingModel.test.ts`,确认 camera-left 驱动用户右手画笔、camera-right 渲染用户左手选色指示器。
- 关联:`src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.tsx``docs/technical/BABY_LOVE_DRAWING_RUNTIME_DEMO_IMPLEMENTATION_2026-05-13.md`
## 宝贝识物创作卡在准备结果页先查长耗时 image-2 请求
- 现象:`/creation/baby-object-match` 创作生成停在“准备结果页”,约 3 分钟后显示“生成失败 / 请求超时”;后端日志可能出现同一路由 `status=502 latency_ms=231291`,或前端已失败但后端稍后返回 200。
- 原因:宝贝识物一次创作会生成 2 张物品图和 `background``ui-frame``gift-box``basket``smoke-puff` 5 张视觉包装图。旧前端只等待 180 秒并对长耗时 POST 自动重试,容易在 VectorEngine 仍在生成时先 abort再重复发起第二次生成上游某张图超过后端 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 或返回 5xx 时会表现为 502。
- 处理:`babyObjectMatchClient``/api/creation/edutainment/baby-object-match/assets` 使用 10 分钟超时并取消自动重试;后端并发启动物品图和视觉主题包生成,并把该路由的 VectorEngine 单图请求等待预算提升到至少 8 分钟,按资源类别输出开始、完成和耗时日志。
- 验证:运行 `npm run test -- src/services/edutainment-baby-object/babyObjectMatchClient.test.ts src/services/miniGameDraftGenerationProgress.test.ts``cargo test -p api-server edutainment_baby_object --manifest-path server-rs/Cargo.toml` 和编码检查;真实联调时查看 `宝贝识物 image-2 资源生成完成` 耗时是否小于前端超时,若仍 502 再看 `VectorEngine 图片生成上游错误``upstreamStatus/raw_excerpt`
- 关联:`src/services/edutainment-baby-object/babyObjectMatchClient.ts``src/services/miniGameDraftGenerationProgress.ts``server-rs/crates/api-server/src/edutainment_baby_object.rs``docs/technical/BABY_OBJECT_MATCH_CREATION_PUBLISH_IMPLEMENTATION_2026-05-11.md`
## 寓教于乐作品和宝贝识物模板同时消失先查入口种子
- 现象:发现页“寓教于乐”分类下已发布的宝贝识物作品突然消失,同时创作界面模板选项中也看不到或无法正常展示 `宝贝识物`
- 原因:创作入口配置事实源已迁到 SpacetimeDB `creation_entry_type_config`;前端用 `baby-object-match` 入口可见性同时控制创作模板展示和发现页宝贝识物公开作品合入。若默认种子或后台配置缺少 `baby-object-match` 行,两条链路会一起被判定为不可见。
- 处理:确认 `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs` 默认种子包含 `id=baby-object-match``title=宝贝识物``visible=true``open=true``sort_order=90`api-server 测试降级配置也要同步包含该类型。入口图片路径需指向真实存在资源,避免卡片图片 404。
- 验证:运行 `cargo test -p module-runtime default_creation_entry_types_include_baby_object_match --manifest-path server-rs/Cargo.toml``cargo test -p api-server test_creation_entry_config_response_keeps_baby_object_match_visible --manifest-path server-rs/Cargo.toml``cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml``npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts`
- 关联:`server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs``server-rs/crates/api-server/src/creation_entry_config.rs``docs/technical/NEW_WORK_ENTRY_CONFIG_2026-05-01.md`
## 儿童动作 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 配置。
@@ -190,54 +124,6 @@
- 验证:后端单测应覆盖 `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 发送。
- 验证:`curl -i -X POST https://api.vectorengine.ai/v1/images/edits -H "Authorization: Bearer invalid" -F "model=gpt-image-2-all" -F "prompt=test" -F "n=1" -F "size=1024x1024"` 至少应返回 HTTP `401`说明域名、TLS 和路径可达;执行 `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`
## 拼图 UI 背景缺失先区分生成失败和消费链路丢字段
- 现象:拼图草稿生成完成后,素材配置页没有展示生成的 UI 背景,或结果页能看到背景但自动试玩 / 结果页“试玩”进入局内仍只显示封面模糊背景。
- 原因:`compile_puzzle_draft` 设计上会在首图后生成 UI 背景,且缺 `uiBackgroundImageSrc/uiBackgroundImageObjectKey` 会让自动草稿失败;若草稿已成功,通常不是“没生成”,而是前端消费链路漏了 `levels[].uiBackgroundImageObjectKey` 回退,或本地 `startLocalPuzzleRun(...)` 只把 `coverImageSrc` 带入 `currentLevel`
- 处理:结果页预览、运行态和本地运行态统一用 `resolvePuzzleUiBackgroundSource`,优先 `uiBackgroundImageSrc`,为空时把 `uiBackgroundImageObjectKey` 规范成 `/generated-...` 路径并交给 `/api/assets/read-url` 换签;`startLocalPuzzleRun` 与本地下一关 handoff 都要从 `PuzzleWorkSummary.levels[]` 复制 `uiBackgroundImageSrc/uiBackgroundImageObjectKey/backgroundMusic``currentLevel`。结果页 `UI背景提示词` 输入框不得把本地兜底 prompt 直接显示成已保存提示词,避免误判为后端已生成。
- 验证:`npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx src/services/puzzle-runtime/puzzleLocalRuntime.test.ts src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx`,以及 `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "puzzle draft generation auto starts trial"`;后端用 `cargo test -p api-server puzzle_ui_background --manifest-path server-rs\Cargo.toml` 确认生成 / 序列化链路。
- 关联:`src/services/puzzle-runtime/puzzleUiBackgroundSource.ts``src/services/puzzle-runtime/puzzleLocalRuntime.ts``src/components/puzzle-runtime/PuzzleRuntimeShell.tsx``src/components/puzzle-result/PuzzleResultView.tsx``docs/technical/PUZZLE_FORM_CREATION_FLOW_2026-04-29.md`
## 拼图草稿生成后音乐/UI 又变空先查结果页回包合并
- 现象拼图草稿生成完成后音乐面板曲名有值但音频槽仍显示“暂无音乐”UI 仍展示默认预览;试玩进入局内也没有生成音乐或 UI 背景。
- 原因:结果页若已有本地 `generationStatus = generating` 编辑态,后端生成完成回包会走 `mergeDraftEditStateWithIncomingState(...)` 合并。该合并必须把生成候选图、正式图、`uiBackground*``backgroundMusic` 作为同一批生成资产处理;漏掉 `backgroundMusic` 时,随后自动保存会把空音乐写回 `levels_json`
- 处理:`PuzzleResultView` 合并生成完成回包时同步保留 `backgroundMusic`,并用回归测试覆盖 UI 预览、音乐试听和试玩 payload 都读取最新 `levels[]` 资产。
- 验证:`npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx`,以及自动试玩入口测试 `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "puzzle draft generation auto starts trial"`
- 关联:`src/components/puzzle-result/PuzzleResultView.tsx``src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx``docs/technical/PUZZLE_MATCH3D_RESULT_AUDIO_TAB_2026-05-11.md`
## 自动草稿成功但缺音乐或 UI 先查后端吞错
- 现象:拼图或抓大鹅生成页提示完成,但草稿页仍显示“暂无音乐”,拼图 UI 仍是默认预览,试玩局内也没有生成音乐或 UI 背景。
- 原因:自动草稿阶段如果把 VectorEngine / Suno / OSS / 资产绑定错误记录为 warning 后继续返回成功,前端只能拿到缺关键资产的成功 draft随后保存和试玩都会消费这份空资产状态。
- 处理:自动草稿必须把必需生成资产当作后端完成条件:拼图首关需同时具备 `levels[0].backgroundMusic.audioSrc``levels[0].uiBackgroundImageSrc/uiBackgroundImageObjectKey`;抓大鹅需在 `generatedItemAssets[]` 中具备非空 `backgroundMusic.audioSrc`。缺失或上游失败时返回错误并停留在生成页,结果页手动重新生成只作为已有草稿补救入口。
- 验证:`cargo test -p api-server puzzle_initial_draft_assets_must_include_music_and_ui_background match3d_background_music_ready_requires_audio_src match3d_background_music_title_is_required_for_auto_draft --manifest-path server-rs\Cargo.toml`,并重启 `npm run api-server` 后检查 `/healthz`
- 关联:`server-rs/crates/api-server/src/puzzle.rs``server-rs/crates/api-server/src/match3d.rs``docs/technical/PUZZLE_FORM_CREATION_FLOW_2026-04-29.md``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 拼图草稿生成 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=180000`;若上游在该窗口内未返回,后端退款并返回超时错误。旧前端 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 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`
## 本地脚本调 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` 并落盘;失败时错误里能区分请求发送、首部等待、下载和解码阶段。
- 关联:`.codex/skills/gpt-image-2-apimart/SKILL.md``server-rs/crates/api-server/src/openai_image_generation.rs`
## 旧后端路线文档造成判断漂移
- 现象:开发时参考到 Express、Node、PostgreSQL 或 Go 方向旧文档,导致接口、数据真相或部署路径与当前主线不一致。
@@ -290,8 +176,8 @@
- 现象:本地 `npm run dev``3101` 已占用、重复发布 SpacetimeDB wasm 编译太慢,或只想检查 `spacetime-module` 语法而被完整联调链路拖慢。
- 原因:`npm run dev` 默认同时启动 SpacetimeDB standalone、发布 `server-rs/crates/spacetime-module`、启动 Rust `api-server`、主站 Vite 与后台 Vite并非每个阶段都需要完整重启和重新发布。
- 处理:`npm run dev` 启动后会把实际 SpacetimeDB URL 记录到 `server-rs/.spacetimedb/local/data/dev-rust-spacetime-url`。下次启动即使没有传 `--skip-spacetime`,脚本也会先检查 `spacetime.pid` 对应进程和该 URL 是否在线;在线则直接复用现有宿主。确认需要新启动 SpacetimeDB 时,脚本先检测 `3101`,被占用则输出占用进程并选择最近可用端口,保证 publish 与 `api-server` 都连接同一个实际 SpacetimeDB URL。显式传 `--skip-spacetime` 时表示复用既有宿主,脚本不再对 SpacetimeDB 端口做可用性漂移;`--spacetime-port 3101` 就是后端要连接的实际端口,避免被误改到空闲但未启动的 `3102``api-server` 启动前也会检测 `8082` 并选择最近可用端口。Windows / Git Bash 下不要用 `tr/head/xargs` 管道读取 `spacetime.pid` 或 URL 记录,脚本应使用 Node 读取并短重试,避免 `tr: read error: Device or resource busy`;未修改 `spacetime-module` 时使用 `npm run dev -- --skip-publish`;只查模块语法时执行 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml``npm run dev` 会在启动前检查 SpacetimeDB、api-server、主站 Vite、后台 Vite 端口,不可用时自动寻找后续可用端口,并把实际端口传给 publish、后端环境变量和前端代理目标。
- 验证:`--skip-spacetime` 后脚本复用现有 `http://127.0.0.1:3101`日志中的 `[dev:rust] spacetime:` 不应漂移到没有服务的 `3102``GET /api/creation-entry/config` 不应返回连接空端口导致的 `502``3101``8082` 被其他进程占用时,脚本输出占用进程并使用最近可用端口;`--skip-publish` 后不再进入 publish 阶段;`cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml` 能完成 Rust 语法和类型检查。端口漂移时控制台会打印 `[dev:ports] ... 不可用,改用 ...`,后续 `[dev:rust] web/admin web/rust api/spacetime` 地址应与实际端口一致。
- 处理:`npm run dev` 启动后会把实际 SpacetimeDB URL 记录到 `server-rs/.spacetimedb/local/data/dev-rust-spacetime-url`。下次启动即使没有传 `--skip-spacetime`,脚本也会先检查 `spacetime.pid` 对应进程和该 URL 是否在线;在线则直接复用现有宿主。确认需要新启动 SpacetimeDB 时,脚本先检测 `3101`,被占用则输出占用进程并选择最近可用端口,保证 publish 与 `api-server` 都连接同一个实际 SpacetimeDB URL。`api-server` 启动前也会检测 `8082` 并选择最近可用端口。Windows / Git Bash 下不要用 `tr/head/xargs` 管道读取 `spacetime.pid` 或 URL 记录,脚本应使用 Node 读取并短重试,避免 `tr: read error: Device or resource busy`;未修改 `spacetime-module` 时使用 `npm run dev -- --skip-publish`;只查模块语法时执行 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml``npm run dev` 会在启动前检查 SpacetimeDB、api-server、主站 Vite、后台 Vite 端口,不可用时自动寻找后续可用端口,并把实际端口传给 publish、后端环境变量和前端代理目标。
- 验证:`--skip-spacetime` 后脚本复用现有 `http://127.0.0.1:3101``3101``8082` 被其他进程占用时,脚本输出占用进程并使用最近可用端口;`--skip-publish` 后不再进入 publish 阶段;`cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml` 能完成 Rust 语法和类型检查。端口漂移时控制台会打印 `[dev:ports] ... 不可用,改用 ...`,后续 `[dev:rust] web/admin web/rust api/spacetime` 地址应与实际端口一致。
- 关联:`docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md``scripts/dev-rust-stack.sh`
## 本地 SpacetimeDB publish 401 可清本地库重发
@@ -342,13 +228,6 @@
- 验证:本地加入临时测试后,`HYPER3D_API_KEY` 应能被 `.env.secrets.local` 覆盖,且 shell 变量仍然最高优先级。
- 关联:`scripts/api-server-dev.mjs``server-rs/crates/api-server/src/hyper3d_generation.rs``docs/technical/HYPER3D_RODIN_GEN2_MODEL_GENERATION_2026-05-08.md`
## OSS 密钥键名不要把字母 O 写成数字 0
- 现象:`.env.secrets.local` 看起来已经配置 OSS AccessKey Secret但拼图或抓大鹅生成仍返回 `OSS 未完成环境变量配置`
- 原因:后端只读取 `ALIYUN_OSS_ACCESS_KEY_SECRET`。如果写成 `ALIYUN_0SS_ACCESS_KEY_SECRET`,中间是数字 `0`,配置合并检查会显示正确键缺失,`api-server` 不会初始化 OSS 客户端。另一个常见原因是外层 shell / IDE 预置了空的 `ALIYUN_OSS_*`,旧启动脚本会把空值当作最高优先级,导致 `.env.local``.env.secrets.local` 的真实值被跳过。
- 处理:只改键名为 `ALIYUN_OSS_ACCESS_KEY_SECRET`,保留原值;不要在日志、文档或对话里输出密钥内容。本地启动脚本应只保护非空外层环境变量,空字符串或全空白值不得遮蔽本地 env 文件。
- 验证:运行 `npm run check:api-server-env`,确认 `VECTOR_ENGINE_BASE_URL``VECTOR_ENGINE_API_KEY``ALIYUN_OSS_BUCKET``ALIYUN_OSS_ENDPOINT``ALIYUN_OSS_ACCESS_KEY_ID``ALIYUN_OSS_ACCESS_KEY_SECRET` 都是 `present`,再重启 `npm run api-server``npm run dev`
## 拼图图片生成 98% 后报 OSS V4 签名时间格式化失败
- 现象:拼图创作表单生成进度卡在 98%`POST /api/runtime/puzzle/agent/sessions/{sessionId}/actions` 返回 `502 Bad Gateway`,前端提示 `拼图图片生成失败OSS V4 签名时间格式化失败`
@@ -594,9 +473,9 @@
## 拼图发布 409 不一定是接口故障
- 现象:拼图结果页点击发布后,控制台出现 `POST /api/runtime/puzzle/agent/sessions/{sessionId}/actions 409 (Conflict)`,用户只看到发布失败。
- 原因:`publish_puzzle_work` 是资产操作发布入口,发布前会预扣 `1`点;余额不足时后端按业务冲突返回 `409 CONFLICT``details.message``点余额不足`
- 原因:`publish_puzzle_work` 是资产操作发布入口,发布前会预扣 `1`点;余额不足时后端按业务冲突返回 `409 CONFLICT``details.message``点余额不足`
- 处理:前端发布弹窗在用户点击发布后必须保留并展示后端业务错误,不能只把错误写到弹窗背后的页面 banner。
- 验证:`PuzzleResultView` 单测覆盖发布弹窗内展示 `点余额不足`
- 验证:`PuzzleResultView` 单测覆盖发布弹窗内展示 `点余额不足`
- 关联:`src/components/puzzle-result/PuzzleResultView.tsx``docs/technical/PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md``docs/technical/ASSET_GENERATION_POINTS_CONSUMPTION_2026-04-27.md`
## WebGL 画布在高 DPR 移动端放大溢出
@@ -619,7 +498,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 个视角,单张 1K 素材图固定 5x5 切割,一行对应一个物品,超过 5 个物品自动分批并行生图`generatedItemAssets[].status` 使用 `image_ready`,发布校验看 `imageViews[]` 或首图引用。`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`
@@ -643,34 +522,10 @@
- 现象:结果页能看到生成的物品图片,但点击试玩或从推荐 / 公开作品进入正式抓大鹅时,局内仍显示默认积木素材。
- 原因:结果页本地 `assetDrafts` 和作品 profile 的 `generatedItemAssets` 可能不同步;推荐流内嵌运行态若只读卡片摘要,卡片缺素材时会把已持久化 profile 素材丢掉;点击试玩时 React state 异步更新也可能让运行态第一帧读取旧 `match3dProfile`
- 处理:删除、批量新增、音效生成或封面引用物品素材后,都把当前 `generatedItemAssets` 写回作品 profile`Match3DResultView` 合并同 `itemId` 的 draft/profile 素材,用 profile 已有 `imageViews[]`首图引用`backgroundMusic``backgroundAsset` 补齐旧 draft点击试玩前把试玩可用物品种类通过 `itemTypeCountOverride` 降到已生成 2D 素材数量;推荐流内嵌运行态启动前若卡片摘要没有物品图片素材,补读 `getMatch3DWorkDetail(profileId)` 并把详情资产传给 `Match3DRuntimeShell``PlatformEntryFlowShellImpl` 需要维护 `match3dRuntimeProfile`,在 `startMatch3DRunFromProfile` 创建 run 后立即锁定本次完整 profileruntime 渲染时优先按 `run.profileId` 使用这份 profile而不是等待普通 `match3dProfile` state 下一轮刷新。同 profile 下已有 `generatedItemAssets` 时不能因为图片完整性判断失败就覆盖为空数组。判断是否需要补读详情时只看 `imageViews[]``imageSrc/imageObjectKey`;背景、音乐、容器 UI 是附属运行态资产,不能单独证明物品素材已完整。
- 处理:删除、批量新增、音效生成或封面引用物品素材后,都把当前 `generatedItemAssets` 写回作品 profile`Match3DResultView` 合并同 `itemId` 的 draft/profile 素材,用 profile 已有 `imageViews[]`首图引用补齐旧 draft点击试玩前把试玩可用物品种类通过 `itemTypeCountOverride` 降到已生成 2D 素材数量;推荐流内嵌运行态启动前若卡片摘要没有生成素材,补读 `getMatch3DWorkDetail(profileId)` 并把详情资产传给 `Match3DRuntimeShell``PlatformEntryFlowShellImpl` 需要维护 `match3dRuntimeProfile`,在 `startMatch3DRunFromProfile` 创建 run 后立即锁定本次完整 profileruntime 渲染时优先按 `run.profileId` 使用这份 profile而不是等待普通 `match3dProfile` state 下一轮刷新。
- 验证:执行 `npm run test -- src/components/match3d-result/Match3DResultView.test.tsx``npm run test -- src/components/match3d-runtime/Match3DRuntimeShell.test.tsx``npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx`,并检查历史草稿和公开 M3 作品的 Network 响应里 `generatedItemAssets[].imageViews/imageSrc/imageObjectKey`
- 关联:`src/components/match3d-result/Match3DResultView.tsx``src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``src/components/match3d-runtime/Match3DPhysicsBoard.tsx``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 抓大鹅 UI 背景和容器只在顶层字段时也要传进运行态
- 现象:抓大鹅草稿 / 推荐卡片响应里已有 `generatedBackgroundAsset`,结果页 UI 预览能看到纯背景图和容器图,但进入试玩或正式局内仍显示默认渐变背景和默认圆形容器。
- 原因:部分链路把 UI 资产只放在作品顶层 `generatedBackgroundAsset` / `backgroundImageObjectKey`,没有同步放进首个 `generatedItemAssets[].backgroundAsset`;如果运行态入口只传 `generatedItemAssets``backgroundImageSrc``Match3DRuntimeShell` 就拿不到 `containerImageObjectKey`
- 处理:`PlatformMatch3DGalleryCard``mapPublicWorkDetailToMatch3DWork``resolveMatch3DRuntimeGeneratedBackgroundAsset``Match3DRuntimeShell` 都必须保留并传递顶层 `generatedBackgroundAsset`;运行态背景读取顺序为 `backgroundImageSrc` / 顶层 `generatedBackgroundAsset.image*` / `generatedItemAssets[].backgroundAsset.image*`,容器读取顺序为顶层 `generatedBackgroundAsset.containerImage*` / `generatedItemAssets[].backgroundAsset.containerImage*`
- 验证:执行 `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 并接管棋盘外观
- 现象:抓大鹅结果页看似有容器生成入口,但真实生成出的局内容器不像 `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 上传;共享 GPT-image-2 HTTP client 承载 multipart 时强制 HTTP/1.1。`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`
## 抓大鹅结果页音频试听也要先换签
- 现象:抓大鹅草稿生成完成后,背景音乐已写在 `generatedItemAssets[0].backgroundMusic.audioSrc`,但 `素材配置 > 背景音乐` 或物品详情音效 `<audio>` 不能播放Network 可能请求裸 `/generated-match3d-assets/...mp3` 并返回 403。
- 原因:结果页试听控件和运行态一样运行在浏览器里,不能直接读取 generated 私有对象;只在运行态换签会造成“运行态可能有声,结果页不能预览”的割裂。
- 处理:结果页音频控件统一通过 `useResolvedAssetReadUrl` / `/api/assets/read-url` 取得签名 URL 后再传给 `<audio>`;换签失败时只显示“音频已绑定”,不要回退请求裸 generated path。
- 验证:`npm run test -- src/components/match3d-result/Match3DResultView.test.tsx` 覆盖背景音乐和点击音效试听使用签名 URL。
- 关联:`src/components/match3d-result/Match3DResultView.tsx``src/services/assetReadUrlService.ts``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 法律文档弹窗通过 portal 挂载时要显式带平台主题
- 现象:登录弹窗内点击协议链接打开法律文档时,弹窗可能继承不到 `platform-theme--light/dark` 变量,或者层级低于登录遮罩导致不可见。
@@ -691,26 +546,9 @@
- 现象:微信小程序支付下单能返回 `prepay_id`,但真实支付通知验签失败,或者本地实现误把商户 API 私钥当作回调验签 key。
- 原因:商户私钥只用于商户请求微信支付和生成小程序 `paySign`;微信支付通知的 `Wechatpay-Signature` 需要使用微信支付平台公钥或平台证书公钥验签,并按通知头里的平台序列号匹配。
- 处理api-server 真实微信支付配置同时需要商户私钥与微信平台公钥:`WECHAT_PAY_PRIVATE_KEY_*` 用于签名,`WECHAT_PAY_PLATFORM_PUBLIC_KEY_*``WECHAT_PAY_PLATFORM_SERIAL_NO` 用于通知验签,`WECHAT_PAY_API_V3_KEY` 只用于解密通知 resource。支付成功后只通过通知里的 `out_trade_no` 确认本地 pending 订单,并保存 `transaction_id``profile_recharge_order.provider_transaction_id`
- APIv3 通知成功应答使用 HTTP `204 No Content`,不要沿用 V2 XML 成功报文;失败仍返回 4XX/5XX 让微信重试。
- 验证mock 通知测试只能覆盖本地回调推进;真实环境还需用微信支付平台公钥、真实通知头和 API v3 密钥验证签名与解密链路。
- 关联:`server-rs/crates/api-server/src/wechat_pay.rs``docs/technical/MY_TAB_ACCOUNT_RECHARGE_IMPLEMENTATION_2026-04-25.md`
## 微信支付 JSAPI 下单必须显式带 User-Agent
- 现象:调用 `/v3/pay/transactions/jsapi` 失败微信返回“Http头缺少Accept或User-Agent”。
- 原因:`reqwest` 请求即使已设置 `Accept: application/json`,也不会默认附带业务侧 `User-Agent`;微信支付网关会校验这两个头。
- 处理:`api-server` 的 JSAPI 下单请求统一通过 `with_wechat_pay_jsapi_headers(...)` 设置 `Accept: application/json``Content-Type: application/json``User-Agent: Genarrative-WechatPay/1.0`
- 验证:执行 `cargo test -p api-server jsapi_order_request_sets_wechat_required_http_headers --manifest-path server-rs/Cargo.toml`
- 关联:`server-rs/crates/api-server/src/wechat_pay.rs``docs/technical/MY_TAB_ACCOUNT_RECHARGE_IMPLEMENTATION_2026-04-25.md`
## 后台表查询展示 SpacetimeDB 枚举时不要套用 Option 解码
- 现象:后台“表查询”查看 `profile_recharge_order` 时,`kind``status` 显示为空数组 `[]`,例如充值订单原始行里 `points_60` 的类型和状态都不可读。
- 原因SpacetimeDB HTTP SQL 对无载荷枚举会返回 SATS 形态 `[variant_index, []]`;后台通用 normalizer 曾把任何 `[0, value]` 都当作 `Option::Some(value)` 展开,导致 `[0, []]` 最终只剩 `[]`
- 处理:通用表查询解析应先按表名和列名识别已知业务枚举,再落回 Option / Timestamp 通用展开;例如 `profile_recharge_order.kind` 映射为 `points` / `membership``profile_recharge_order.status` 映射为 `pending` / `paid` / `failed` / `closed` / `refunded`
- 验证:执行 `cargo test -p api-server admin_database -- --nocapture`,并确认后台详情弹层的 `raw` 与表格 `cells` 都显示业务字符串。
- 关联:`server-rs/crates/api-server/src/admin.rs``docs/technical/ADMIN_DATABASE_TABLE_QUERY_2026-05-08.md`
## 抓大鹅历史草稿外部 Rodin GLB 链接必须转存后再试玩或发布
- 现象:草稿页预览模型失败并报 `GL_INVALID_ENUM: Invalid cap.`,或结果页能看到历史生成记录但试玩、发布和正式运行态仍显示默认积木。
@@ -735,22 +573,6 @@
- 验证:`cargo test -p api-server match3d_tag_normalization --manifest-path server-rs/Cargo.toml`,并保留 `normalize_match3d_tag("3D素材") == "3D素材"` 的单测。
- 关联:`server-rs/crates/api-server/src/match3d.rs`
## 抓大鹅物品切图白边或绿幕残留先查后端透明化
- 现象:抓大鹅生成的物品视角图裁剪后仍带白边,或者整块纯绿色绿幕背景没有被透明化,运行态看到绿色方块。
- 原因:素材 sheet 可能是“每格内部绿幕、整张图外圈近白底”,内部绿幕不一定连通到 sheet 外边缘;旧 flood fill 只从外边缘找背景会漏掉这种绿幕块。白底抗锯齿如果不纳入抠像和边缘去污染,也会随裁剪输出成一圈白边。
- 处理:`api-server``slice_match3d_material_sheet` 必须先在整张 sheet 上做透明背景后处理:外边缘连通绿幕/近白底清 alpha非连通但高置信纯绿块也清 alpha边缘近白和绿幕抗锯齿做透明或去污染同时保护不够纯的绿色主体像素。
- 验证:`cargo test -p api-server match3d_material_sheet_slicing --manifest-path server-rs\Cargo.toml` 覆盖非连通绿幕、白边、贴边主体保留和固定 5x5 切图。
- 关联:`server-rs/crates/api-server/src/match3d.rs``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`
## 草稿页卡片有真实素材但仍显示黑卡先查摘要字段
- 现象:草稿页拼图卡片没有关卡图背景,抓大鹅卡片没有背景图或物品图背景,甚至兜底视觉也退回黑色面板。
- 原因:拼图列表摘要若不下发 `levels`,前端拿不到关卡 `coverImageSrc` / 候选图;抓大鹅列表摘要若只提供公开 URL、不保留 `generatedBackgroundAsset``generatedItemAssets` 中的 object key前端无法换签读取私有生成图。卡片封面组件如果自带暗色默认背景也会让兜底失败时看起来仍是黑卡。
- 处理:拼图 `map_puzzle_work_summary_response` 必须保留 `levels`;草稿页优先用关卡 `coverImageSrc`,再用候选图。抓大鹅货架封面解析必须读取 `backgroundImageObjectKey``generatedBackgroundAsset.imageObjectKey/containerImageObjectKey``generatedItemAssets[].imageObjectKey``imageViews[].imageObjectKey`。图片渲染统一交给 `ResolvedAssetImage` 换签,并给卡片传入玩法参考图与暖色底兜底。
- 验证:执行 `npm run test -- src/components/custom-world-home/creationWorkShelf.test.ts src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/hooks/useResolvedAssetReadUrl.test.tsx``cargo test -p api-server puzzle_work_summary_response_keeps_levels_for_shelf_cover --manifest-path server-rs\Cargo.toml``npm run typecheck`
- 关联:`src/components/custom-world-home/creationWorkShelf.ts``src/components/CustomWorldCoverArtwork.tsx``server-rs/crates/api-server/src/puzzle.rs``docs/technical/CREATION_WORK_SHELF_UNIFICATION_2026-04-25.md`
## 用户标签不要直接外显SpacetimeDB Vec 字段不要写 default 宏
- 现象:给 `user_account.user_tags` 或邀请码独立标签列写 `#[default(Vec::<String>::new())]`SpacetimeDB WASM 构建报 `destructor of Vec<String> cannot be evaluated at compile-time`
@@ -766,27 +588,3 @@
- 处理:公开详情失效统一走 `resolveWorkNotFoundRecoveryAction(...)`,覆盖 `/works/detail``/gallery/puzzle/detail``/gallery/visual-novel/detail`;搜索失败和拼图详情 404 分支清理详情/运行态临时状态并回首页;`work-detail` 空数据阶段显示轻量读取态,避免异步间隙白屏。
- 验证:`npm run test -- src/routing/runtimeNotFoundRecovery.test.ts``npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "direct missing public work detail alert returns to platform home"`
- 关联:`docs/technical/PUBLIC_WORK_DETAIL_NOT_FOUND_RECOVERY_2026-05-11.md``src/routing/runtimeNotFoundRecovery.ts``src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
## 拼图 UI 背景只有 objectKey 时不要回退默认 UI
- 现象:拼图草稿页、试玩和正式运行态都显示默认 UI或者只在结果页看到生成图进入试玩后又回到默认背景。
- 原因:`uiBackgroundImageSrc` 可能为空而真实生成结果只写了 `uiBackgroundImageObjectKey`;如果前端和运行态只读 `src`,或者本地试玩 / 正式 run 没把 `objectKey` 一起传递,就会丢掉已有背景。
- 处理:统一通过一个解析入口把 `uiBackgroundImageSrc || uiBackgroundImageObjectKey` 归一到可展示路径;本地试玩和正式运行态都要保留 `uiBackgroundImageObjectKey`,并在 `uiBackgroundImageSrc` 为空时换签读取。
- 验证:结果页 UI Tab、`startLocalPuzzleRun``PuzzleRuntimeShell` 都应在仅有 `objectKey` 时显示生成背景,不再回落默认 UI。
- 关联:`src/services/puzzle-runtime/puzzleUiBackgroundSource.ts``src/components/puzzle-result/PuzzleResultView.tsx``src/services/puzzle-runtime/puzzleLocalRuntime.ts``src/components/puzzle-runtime/PuzzleRuntimeShell.tsx``server-rs/crates/module-puzzle/src/application.rs`
## 拼图 UI 背景提示词不像 AI 生成先查首关命名契约
- 现象:拼图草稿生成完成后,`素材配置 > UI` 里显示的 `UI背景提示词` 像前端或后端模板拼接,而不是 AI 生成的视觉提示词。
- 原因:首关命名 LLM 旧契约只返回 `levelName`,自动 UI 背景阶段只能用作品名、作品描述、关卡描述和标签拼接确定性兜底提示词;前端旧实现又会在 `uiBackgroundPrompt` 为空时把本地默认模板直接填进文本框,造成“看起来已有 AI 提示词”的假象。
- 处理:首关命名 LLM 契约必须同时返回 `{"levelName":"...","uiBackgroundPrompt":"..."}`;草稿自动 UI 背景生成优先使用该 AI 提示词,视觉精修请求若返回新提示词则覆盖文本请求提示词,否则保留文本请求提示词。前端文本框只展示已保存的 `uiBackgroundPrompt` 或用户编辑值,字段为空时不展示本地兜底模板。
- 验证:执行 `cargo test -p api-server puzzle_level_naming --manifest-path server-rs\Cargo.toml``cargo test -p api-server puzzle_initial_ui_background_prompt --manifest-path server-rs\Cargo.toml``npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx`
- 关联:`server-rs/crates/api-server/src/prompt/puzzle/level_name.rs``server-rs/crates/api-server/src/puzzle.rs``src/components/puzzle-result/PuzzleResultView.tsx``docs/technical/PUZZLE_FORM_CREATION_FLOW_2026-04-29.md`
## 拼图 / 抓大鹅 UI 背景重生成报 No such procedure 先查 SpacetimeDB 版本漂移
- 现象:拼图或抓大鹅结果页点击 `重新生成` UI 背景时报 `No such procedure`,常见位置是泥点预扣、`save_puzzle_ui_background` 或 Match3D 草稿写回。
- 原因:`api-server``spacetime-client` 已按新 bindings 调用 procedure但目标 SpacetimeDB 数据库仍运行旧 wasm尚未导出钱包扣退费、拼图 UI 背景保存或 Match3D 写回相关 procedure。
- 处理:临时容错是把这类 `No such procedure` 当作后端版本漂移:泥点预扣阶段跳过扣费,图片已经生成但保存失败时返回本次内存快照 / 内存 profile避免草稿页直接报错。长期修复仍是发布最新 `spacetime-module`、重新生成 bindings并用 `spacetime describe` 或定向 smoke 确认 procedure 已导出。
- 验证:`cargo test -p api-server asset_operation_billing_skips_spacetime_connectivity_errors --manifest-path server-rs\Cargo.toml``cargo test -p api-server match3d_fallback_work_profile_keeps_generated_background_asset --manifest-path server-rs\Cargo.toml``npm run api-server` 后检查 `/healthz`
- 关联:`server-rs/crates/api-server/src/asset_billing.rs``server-rs/crates/api-server/src/match3d.rs``docs/technical/PUZZLE_FORM_CREATION_FLOW_2026-04-29.md``docs/technical/MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md`

View File

@@ -104,10 +104,10 @@ Rust 加密摘要依赖口径:新代码不再引入 `sha1`OSS V4 签名、
`docs/technical/PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md` 为准:
- 产品展示名:陶泥儿
- 消费单位:
- 公开账号标识:陶泥
- 创作侧称谓:陶泥儿
- 产品展示名:百梦
- 消费单位:
- 公开账号标识:百梦
- 创作侧称谓:百梦
个人任务与埋点系统首版边界:
@@ -117,7 +117,7 @@ Rust 加密摘要依赖口径:新代码不再引入 `sha1`OSS V4 签名、
- 任务进度写入 `profile_task_progress`
- 领奖记录写入 `profile_task_reward_claim`
- 钱包流水写入 `profile_wallet_ledger`
- “星光”奖励复用现有“点”钱包,不新增第二种货币
- “星光”奖励复用现有“点”钱包,不新增第二种货币
- 个人任务 scope 首版仅支持 `user`
## 关键文档入口

View File

@@ -15,7 +15,6 @@
- `.hermes/shared-memory/` 团队级长期记忆
- `.hermes/plans/` 阶段性实施计划
- `.hermes/todos/` 已确定需要执行、但尚未进入实施的共享 TODO 计划
- `.hermes/skills/` 未来可复用仓库级 skills
- `docs/` 中 PRD、设计、技术、经验、审计、查询手册
- `AGENTS.md` 项目级 Agent 约束
@@ -42,7 +41,6 @@
- 保持修改范围聚焦,不做无关重构。
- 复用、修改、扩展现有系统优先,避免新建重复系统或页面。
- 新增 Markdown 文档时,文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`;只在任务需要时重命名历史文档,避免无关大 diff。
- 涉及中文文本时注意 UTF-8 编码和乱码排查。
- 涉及后端时遵循 DDD 分层,不把业务真相下沉到前端或临时兼容层。
- `maincloud` / `Maincloud` / `MAINCLOUD` 相关代码、脚本、测试、环境变量、命令和文档要求均视为历史残留禁止新增、运行或引用API smoke 统一使用 `npm run api-server``/healthz`
@@ -53,10 +51,9 @@
1. 运行与修改范围匹配的测试或验证命令。
2. 更新相关 `docs/` 文档。
3. 新增或沉淀 Markdown 文档时,确认文件名已使用 `【标签名】` 前缀
4.产生长期有效知识,更新 `.hermes/shared-memory/`
5. 若形成可复用流程,考虑沉淀到 `.hermes/skills/`
6. 在提交信息中区分代码变更与文档/记忆变更。
3. 若产生长期有效知识,更新 `.hermes/shared-memory/`
4.形成可复用流程,考虑沉淀到 `.hermes/skills/`
5. 在提交信息中区分代码变更与文档/记忆变更
## 文档阅读顺序

View File

@@ -1,23 +1,23 @@
---
name: genarrative-admin-backoffice
short_description: 在 Genarrative/陶泥儿后台新增或修改管理页、后台只读/写接口、导出能力时使用。
description: 在 Genarrative/陶泥儿后台新增或修改管理页、后台 BFF 接口、shared-contracts/admin DTO、admin-web 路由导航、Excel/表格导出与验证发布时使用。
short_description: 在 Genarrative/百梦后台新增或修改管理页、后台只读/写接口、导出能力时使用。
description: 在 Genarrative/百梦后台新增或修改管理页、后台 BFF 接口、shared-contracts/admin DTO、admin-web 路由导航、Excel/表格导出与验证发布时使用。
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [Genarrative, 陶泥儿后台, admin-web, 后台接口, Excel导出, Rust, Axum, SpacetimeDB]
tags: [Genarrative, 百梦后台, admin-web, 后台接口, Excel导出, Rust, Axum, SpacetimeDB]
related_skills: [genarrative-play-type-integration]
---
# Genarrative / 陶泥儿后台管理功能接入流程
# Genarrative / 百梦后台管理功能接入流程
用于在 Genarrative 项目中新增或修改陶泥儿后台管理端能力,包括后台页面、后台 API、管理端 DTO、导航路由、表格明细、导出、鉴权与验证。
用于在 Genarrative 项目中新增或修改百梦后台管理端能力,包括后台页面、后台 API、管理端 DTO、导航路由、表格明细、导出、鉴权与验证。
## 适用场景
- 新增陶泥儿后台页面或导航项,例如“埋点数据”“任务配置”“邀请码”。
- 新增百梦后台页面或导航项,例如“埋点数据”“任务配置”“邀请码”。
- 新增 `/admin/api/*` 接口。
- 修改 `apps/admin-web` 的后台页面、API client、路由、Shell 导航。
- 在后台展示 SpacetimeDB 表明细或统计数据。

View File

@@ -2,7 +2,7 @@
## 背景
本次在 Genarrative/陶泥儿后台新增“埋点数据”页:
本次在 Genarrative/百梦后台新增“埋点数据”页:
- 后端新增 `GET /admin/api/tracking/events`
- shared-contracts 新增 admin tracking query/list/entry DTO。

View File

@@ -1,15 +0,0 @@
# 项目共享 TODO 计划
本目录用于存放已经讨论定稿、需要后续执行,但当前尚未实施的项目级计划文档。
## 使用规则
- 每个 TODO 计划单独一个 Markdown 文件,文件名优先使用可检索的中文标题与日期。
- 每个 TODO 计划文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`
- 计划内容必须足够明确,后续开发者可以直接据此开始实施。
- 已执行完成的计划应迁移到对应 `docs/` 技术/规划文档,或在本文档中标记完成并移出 TODO 队列。
- 不在这里保存个人私密路径、密钥、临时聊天记录或未确认猜测。
## 当前待执行
- [【后端架构】api-server 能力模块化与图片资产 Adapter 收口计划](./【后端架构】api-server能力模块化与图片资产Adapter收口计划-2026-05-14.md)

View File

@@ -1,108 +0,0 @@
# api-server 能力模块化与生成资产 Adapter 完整收口计划
状态:待执行
## Summary
目标是把 `api-server` 从“超大 `app.rs` + 多个超大 handler 文件 + 多处生成资产重复链路”收成可长期维护的能力 Module 结构。
本计划完整覆盖:路由能力模块化、生成图片资产 Adapter、复杂媒体链路扩展、大 handler 瘦身、文档与验收。全程不改变 HTTP contract、DTO、SpacetimeDB schema、前端行为和计费语义除非某阶段文档先明确提出并单独批准。
## 文档交付
先新增一个总纲,再按阶段新增单独执行文档:
- 总纲:`docs/technical/【后端架构】api-server能力模块化与生成资产Adapter总纲-2026-05-14.md`
- 阶段 1`docs/technical/【后端架构】api-server路由能力模块化执行计划-2026-05-14.md`
- 阶段 2`docs/technical/【后端架构】生成图片资产Adapter收口执行计划-2026-05-14.md`
- 阶段 3`docs/technical/【后端架构】复杂媒体资产链路Adapter扩展计划-2026-05-14.md`
- 阶段 4`docs/technical/【后端架构】api-server大Handler瘦身执行计划-2026-05-14.md`
- 同步更新 `server-rs/crates/api-server/README.md``docs/technical/README.md`、本 TODO 文档。
## 阶段 0基线盘点与总纲冻结
- 盘点 `app.rs` 当前全部 route`admin/auth/assets/profile/creation/runtime/story/platform/internal` 分类形成 route inventory。
- 盘点 Big Fish、Square Hole、Custom World、Puzzle、Match3D、Visual Novel、音频、视频、GLB 的生成资产链路,标出 provider、下载方式、OSS prefix、asset kind、entity binding、计费位置、降级行为。
- 在总纲文档中冻结边界:`api-server` 只做 HTTP/SSE/BFF、鉴权、DTO 映射、平台服务编排;领域规则仍归 `module-*`SpacetimeDB 真相仍归 `spacetime-module`
退出条件:总纲和 inventory 能指导后续编码,不再只是一段方向描述。
## 阶段 1路由能力模块化完整收口
- 新增 `server-rs/crates/api-server/src/modules/`,每个能力 Module 暴露 `router(state) -> Router<AppState>`
- 第一批迁移低风险路由:`admin``auth``assets``profile``internal``health`
- 第二批迁移平台编排路由:`ai_tasks``llm``speech``wechat``creative_agent``visual_novel`、通用 audio。
- 第三批迁移玩法路由:`big_fish``square_hole``puzzle``match3d``custom_world``story`、runtime save/settings/chat/inventory。
- `app.rs` 最终只保留全局 middleware、TraceLayer、request context、tracking middleware、`.merge(modules::*::router(...))` 和少量顶层 glue。
- handler 实现第一阶段可以继续留在原文件;本阶段只改变路由装配位置,不混入业务重构。
验收route inventory 中所有原 route 仍存在;旧明确下线 route 继续 404`cargo test -p api-server app --manifest-path server-rs/Cargo.toml` 或等价 route 回归通过。
## 阶段 2稳定单图生成资产 Adapter 收口
- 新增 `modules/assets/generated_image_assets` 内部 ModuleInterface 覆盖“provider 生成 -> 下载/base64 解码 -> MIME/extension 归一 -> OSS private upload -> HEAD -> asset_object confirm -> entity binding”。
- Adapter 输入包含 provider、prompt、negative prompt、size、reference images、OSS prefix/path/file name、asset kind、entity kind/id、slot、owner/profile/source_job_id、metadata、可选透明背景后处理。
- Adapter 输出包含 `legacy_public_path``object_key``asset_object_id``mime_type``extension``task_id``actual_prompt`
- 首批迁移:
- Big Fish 正式图片:主图、动作图、舞台背景。
- Square Hole 图片:保留生成成功但入库失败时回退 Data URL。
- Custom World 场景图、自动草稿场景图、生成封面图。
- `asset_billing.rs` 仍由调用方显式包裹Adapter 不扣费、不退款、不读钱包。
验收:三类调用方都经过同一 Adapter删除旧重复 persist 函数后行为不变Big Fish、Square Hole、Custom World 定向测试通过。
## 阶段 3复杂媒体资产链路扩展
- 扩展 Adapter但不把玩法图像处理规则塞进公共 Interface。
- Puzzle
- 收口普通 generations、edits/multipart 生成结果的下载、OSS、asset object、binding。
- 拼图关卡 JSON 更新、参考图策略、UI 背景落位仍留在 Puzzle 编排层。
- Match3D
- APIMart material sheet、VectorEngine 背景/容器/封面生成接入统一入库能力。
- 5x5 切图、绿幕透明化、格内校准、批量新增补齐规则仍留在 Match3D 专属处理器。
- 音频:
- 评估是否抽 `generated_media_assets`,但背景音乐、点击音效的计费和落位语义不与图片 Adapter 混用。
- GLB/视频:
- 仅历史转存链路复用“OSS + asset_object + binding”底层持久化能力不恢复新草稿 GLB 生产。
验收Puzzle 与 Match3D 的 generated 私有资产仍通过 `/api/assets/read-url` 换签读取Match3D 不回退 Rodin/GLB音频试听和运行态仍可播放。
## 阶段 4超大 handler 能力内瘦身
- 在路由已模块化、资产 Adapter 已稳定后,再拆大文件,避免同时改 route 和业务实现。
-`match3d.rs``puzzle.rs``custom_world.rs``custom_world_ai.rs``big_fish.rs``square_hole.rs` 分别按能力拆:
- `router.rs` 只挂路由。
- `handlers.rs` 只做 Axum extract、鉴权、request/response。
- `application.rs` 做 api-server 层编排。
- `assets.rs` 只放玩法专属生成资产策略。
- `mapper.rs` 只做 DTO/record 映射。
- `errors.rs` 只做该能力错误映射。
- 不把领域规则留在 handler发现领域规则时只登记迁出候选不在本阶段直接扩大到 `module-*` 重构。
验收:每个原超大文件显著缩小;新文件按能力可读;定向玩法测试和全量 `api-server` 测试通过。
## 阶段 5清理、文档和最终验收
- 删除旧重复 helper、过时注释和已迁移的私有函数。
- 更新 `api-server` README目录规则、Router 暴露规则、Adapter 边界、禁止事项。
- 更新 `.hermes/shared-memory` 中长期有效的架构约定和排障经验。
- 最终验收命令:
- `cargo check -p api-server --manifest-path server-rs/Cargo.toml`
- `cargo test -p api-server --manifest-path server-rs/Cargo.toml`
- `npm run check:server-rs-ddd`
- `npm run check:encoding`
- `git diff --check`
- `npm run api-server` 后检查 `/healthz`
- 禁止使用 `api-server:maincloud` 作为本轮 smoke。
## Public Interfaces
- HTTP route、DTO、error envelope、SpacetimeDB schema、前端调用方式默认不变。
- 新增的都是 `api-server` 内部 Rust Interface不进入 `shared-contracts`
- 若后续任何阶段发现必须改 contract先更新对应阶段文档和 G1 route/contract 矩阵,再单独实施。
## Assumptions
- 本计划目标是完整收口,不是只完成第一阶段。
- 可以分阶段提交,但每个阶段都必须有文档、测试和明确退出条件。
- `generated_image_assets` 首版必须至少被三个真实调用方使用,否则不算形成有效 Module。

View File

@@ -30,7 +30,6 @@ Single-context layout: read root `CONTEXT.md` when present and architecture deci
- 代码需要有完善的中文注释
- 在落地工程修改前检查是否有详细指导本次落地的文档,若没有文档或文档的完善程度仍有落地过程中编码级别的歧义优先优化文档后落地工程迭代。
- 对工程的修改不仅要落地到代码更面还要更改对应文档若没有生成新的文档文档统一存在doc目录中
- 后续新增的 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`;例如 `【后端架构】api-server能力模块化与图片资产Adapter收口计划-2026-05-14.md`。不要求批量重命名历史文档,除非本次任务明确涉及该文档。
- 不要擅自把现有中文文案、注释、剧情、文档改写成英文,除非用户明确要求翻译。
- 看到中文乱码时,不要直接沿用乱码文本,也不要用英文替换;先确认文件真实编码,再决定是否修改。
- 在 PowerShell 5.1 中读取或写入文本时,必须显式使用 UTF-8如果终端输出疑似乱码要用 `Get-Content -Encoding UTF8`、Python 或 Node 再次核对原文。

View File

@@ -1,110 +0,0 @@
# Genarrative Domain Context
Genarrative 是一个 AI 原生互动内容与小游戏平台,当前上下文记录团队在玩法、作品、运行态和平台闭环中使用的领域语言。
## Language
### Bark Battle
**汪汪声浪大作战**:
浏览器 2D 声控对战玩法,玩家通过麦克风响度触发声浪并推动能量条。
_Avoid_: 狗叫识别游戏、声纹识别玩法
**有效声浪触发**:
玩家麦克风采样点的归一化响度在冷却结束后达到或超过有效阈值时产生的一次计分输入。
_Avoid_: 有效叫声持续时长、狗叫识别结果、等待回落后的叫声
**有效阈值**:
用于判定麦克风采样是否产生有效声浪触发的响度门槛。
_Avoid_: 狗叫识别阈值、语义识别阈值
**声浪冷却**:
两次有效声浪触发之间必须满足的最小时间间隔。
_Avoid_: 叫声持续时长、回落等待时间
**能量条**:
表示玩家与对手当前声浪优势的连续对抗刻度。
_Avoid_: 血条、分数条
**单局结果**:
一局 Bark Battle 结束后形成的胜负、平局和派生统计摘要。
_Avoid_: 原始音频记录、语音内容
**Bark Battle 平台作品闭环**:
Bark Battle 从创作配置、发布作品、正式运行态到单局结果记录和作品统计的完整平台流程。
_Avoid_: 孤立 demo、只做表现深化
**轻创作配置作品**:
创作者只配置展示与难度预设字段、但不能直接配置公平性敏感规则的 Bark Battle 作品。
_Avoid_: 完整规则编辑器、固定官方关卡
**难度预设**:
Bark Battle 作品中用于选择 AI 对手行为强度的发布态配置值。
_Avoid_: 阈值配置、分数公式配置
**排行榜分榜**:
排行榜按作品、难度预设和规则集版本拆分后的独立排名空间,只收录后端裁决为玩家胜利的单局结果。
_Avoid_: 全难度混排、跨规则版本混排、失败刷分榜
**后端裁决结果**:
后端根据 start run 记录和 finish 派生指标校验后生成的正式单局结果。
_Avoid_: 前端最终分数、客户端胜负裁决
**派生指标**:
前端从本地 runtime 汇总出的不可还原原始音频的单局统计值。
_Avoid_: 原始音频、可还原语音内容
**作品统计投影**:
按作品聚合的 Bark Battle 游玩开始、完成结果、反作弊标记和最佳/平均表现摘要。
_Avoid_: 只从排行榜反推、原始音频分析、留存分析
**个人历史成绩**:
玩家本人可查看的 Bark Battle 最近完成记录和个人最佳摘要。
_Avoid_: 公开失败记录、完整无限历史、好友对比
**正式作品入口闭环**:
Bark Battle 作品从创作入口、作品详情、广场/作品卡片、我的作品到正式 runtime 路由的可发现、可进入流程。
_Avoid_: 内部试玩入口、独立活动专区
**轻配置编辑流程**:
Bark Battle 创作者用单页轻配置表单和预览卡片完成草稿保存与发布的创作流程。
_Avoid_: 多步骤向导、完整规则编辑器、拖拽编辑器
**Phase 2 实施顺序**:
Bark Battle 平台作品闭环按契约与领域规则、后端存储/API、最小前端纵切、投影体验、收口验证的顺序推进。
_Avoid_: mock 先行堆积、前后端各自发散、先做排行榜 UI
## Relationships
- 一个 **汪汪声浪大作战** 单局包含多个 **有效声浪触发**
- 每个 **有效声浪触发** 必须达到 **有效阈值** 并满足 **声浪冷却**
- **有效声浪触发** 推动 **能量条**
- **能量条** 在倒计时结束时产生一个 **单局结果**
- **单局结果** 可以被后端记录为派生摘要,但不包含原始麦克风音频。
- **Bark Battle 平台作品闭环** 包含发布态作品配置、**正式作品入口闭环**、run start / finish、个人历史成绩、**作品统计投影** 和最小排行榜。
- Phase 2 的 Bark Battle 作品是 **轻创作配置作品**,通过 **轻配置编辑流程** 创建;配置范围限制为标题、描述、主题/背景预设、狗狗皮肤预设和排行榜开关,其中 **难度预设** 只影响 AI 对手行为。
- **排行榜分榜** 由 `workId + difficultyPreset + rulesetVersion` 唯一确定,只收录 `serverResult = player_win` 的单局结果。
- **单局结果** 的正式胜负、分数与排行榜成绩来自 **后端裁决结果**;前端只提交 **派生指标**,客户端结果仅用于 debug/对账。
- **作品统计投影** 计入成功 start run 的 playStartCount、后端接受 finish 的 finishCount、胜/平/负、flagged、leaderboard 以及最佳/平均能量表现。
- **个人历史成绩** 由最近记录列表和个人最佳摘要组成,只允许本人查看;排行榜只公开入榜胜利成绩。
- **正式作品入口闭环** 必须覆盖创作入口、作品详情 CTA、广场/作品卡片、我的作品/个人作品架、稳定作品 ID runtime 路由和 `work_play_start` 埋点。
- **Phase 2 实施顺序** 固定为:契约与领域规则 → SpacetimeDB 表/reducer 与 api-server BFF → 最小前端纵切 → 投影与列表体验 → 收口验证。
## Example dialogue
> **Dev:** “第二阶段排行榜要按玩家狗叫持续时间排序吗?”
> **Domain expert:** “不按持续时间Bark Battle 的计分输入是有效声浪触发,排行榜只能基于触发次数、峰值、能量条结果等派生摘要。”
## Flagged ambiguities
- “有效叫声”曾同时指代持续时长合规的声音片段和瞬时响度触发;已解析为 **有效声浪触发**,不再要求 `minBarkDurationMs` / `maxBarkDurationMs`,也不等待响度回落。
- “第二阶段”曾可能指玩法表现深化或平台接入;已解析为 **Bark Battle 平台作品闭环**,优先补正式 play type、作品配置、发布、正式 runtime、结果持久化、历史成绩、作品统计和最小排行榜。
- “创作者可配置作品”曾可能指完整规则编辑器;已解析为 **轻创作配置作品**Phase 2 不允许创作者直接配置单局时长、有效阈值、声浪冷却、AI 细粒度参数、分数公式或反作弊阈值。
- “难度预设”曾可能影响阈值、冷却或计分;已解析为只影响 AI 对手行为,排行榜按 `workId + difficultyPreset + rulesetVersion` 分榜。
- “单局结果”曾可能由前端直接决定;已解析为必须由 **后端裁决结果** 决定,前端只提交触发次数、音量、能量、连击、时长等 **派生指标**
- “排行榜成绩”曾可能收录胜/平/负或按触发次数排序;已解析为只收录玩家胜利局,并以 `finalEnergy` 优先、`triggerCount` / `maxVolume` / 标准局时长接近度 / `finishedAt` 作为后续排序因子。
- “作品统计”曾可能只从排行榜反推;已解析为独立 **作品统计投影**,失败、平局和 flagged finish 都可进入统计,但 rejected finish 不进入完成统计。
- “个人历史成绩”曾可能指完整无限历史或公开记录;已解析为仅本人可见的最近记录列表 + 个人最佳摘要,不公开失败、平局或 flagged 历史。
- “入口闭环”曾可能只指内部 demo 或单个详情 CTA已解析为 **正式作品入口闭环**,不新增独立专区或活动页。
- “创作编辑”曾可能指多步骤向导或完整编辑器;已解析为 **轻配置编辑流程**,使用单页表单 + 预览卡片完成保存草稿、发布和发布后跳转作品详情。
- “实施顺序”曾可能按 UI 或功能并行发散;已解析为契约/领域规则先行,再做后端存储/API随后打通最小前端纵切最后补投影体验与收口验证。

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>陶泥儿后台</title>
<title>百梦后台</title>
</head>
<body>
<div id="root"></div>

View File

@@ -50,7 +50,7 @@ export function AdminShell({
<ShieldCheck size={20} aria-hidden="true" />
</div>
<div>
<strong></strong>
<strong></strong>
<span>Admin</span>
</div>
</div>

View File

@@ -86,7 +86,7 @@ export const adminTrackingEventDefinitions: AdminTrackingEventDefinition[] = [
key: 'wallet_ledger_view',
title: '钱包流水查看',
scopeKind: 'user',
remark: '读取点钱包流水成功后记录。',
remark: '读取点钱包流水成功后记录。',
},
{
key: 'recharge_center_view',

View File

@@ -742,9 +742,9 @@ const databaseTableColumnLabelMap: Record<string, string> = {
theme_tags_json: '主题标签JSON',
cover_image_src: '封面图',
cover_asset_id: '封面资产ID',
public_user_code: '陶泥号',
public_user_code: '百梦号',
public_work_code: '公开作品号',
author_public_user_code: '作者陶泥号',
author_public_user_code: '作者百梦号',
author_display_name: '作者昵称',
display_name: '显示名',
avatar_url: '头像地址',
@@ -874,9 +874,9 @@ const databaseTableColumnDescriptionMap: Record<string, string> = {
theme_tags_json: '主题标签列表 JSON',
cover_image_src: '封面图片地址或平台资产引用',
cover_asset_id: '封面对应的平台资产 ID',
public_user_code: '用户对外展示的陶泥号',
public_user_code: '用户对外展示的百梦号',
public_work_code: '作品公开后对外展示的作品号',
author_public_user_code: '作者对外展示的陶泥号',
author_public_user_code: '作者对外展示的百梦号',
author_display_name: '作者展示昵称',
display_name: '用户展示名称',
avatar_url: '用户头像地址',

View File

@@ -39,7 +39,7 @@ export function AdminLoginPage({notice, onLogin}: AdminLoginPageProps) {
<ShieldCheck size={26} aria-hidden="true" />
</div>
<div>
<h1></h1>
<h1></h1>
<span>Admin Console</span>
</div>
</div>

View File

@@ -253,7 +253,7 @@ export function AdminRedeemCodePage({
/>
</label>
<label className="admin-field">
<span></span>
<span></span>
<textarea
rows={6}
value={allowedPublicUserCodes}

View File

@@ -373,7 +373,7 @@ export function AdminTaskConfigPage({
/>
</label>
<label className="admin-field">
<span></span>
<span></span>
<input
min={1}
step={1}

View File

@@ -37,9 +37,8 @@ GENARRATIVE_CREATION_AGENT_LLM_WEB_SEARCH_ENABLED=false
APIMART_BASE_URL=
APIMART_API_KEY=
APIMART_IMAGE_REQUEST_TIMEOUT_MS=180000
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.ai
VECTOR_ENGINE_API_KEY=
VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=180000
VECTOR_ENGINE_AUDIO_REQUEST_TIMEOUT_MS=180000

View File

@@ -13,7 +13,7 @@
重点补充RPG 创作与运行时脚本职责地图见 [RPG_CREATION_AND_RUNTIME_SCRIPT_RESPONSIBILITY_MAP_2026-04-28.md](./reference/RPG_CREATION_AND_RUNTIME_SCRIPT_RESPONSIBILITY_MAP_2026-04-28.md)。
- [埋点查询](./tracking/README.md):埋点原始事件与聚合投影的本地 SQL 查询。
- [运营查询](./operations/README.md):任务、领奖、钱包对账等后台核查查询。
- [PRD](./prd/README.md):产品需求与阶段计划;参考 MOKU / 幕间类 AI 文游的陶泥儿 `text-game` 模板口径见 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md](./prd/AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md),视觉小说模板 TXT 玩法平台化接入口径见 [AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md](./prd/AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md),创意互动内容 Agent Phase 1 的 LangChain-Rust PoC、拼图闭环和并行任务拆分见 [CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md](./prd/CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md),幸存者类模板闭环见 [AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md](./prd/AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md),后台管理独立前端工程见 [ADMIN_WEB_CONSOLE_PRD_2026-04-30.md](./prd/ADMIN_WEB_CONSOLE_PRD_2026-04-30.md),新增 RPG 开场动画方案见 [AI_NATIVE_RPG_OPENING_ANIMATION_PRD_2026-04-25.md](./prd/AI_NATIVE_RPG_OPENING_ANIMATION_PRD_2026-04-25.md),新增抓大鹅 Match3D 玩法方案见 [AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md](./prd/AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md),方洞挑战创作、发布与试玩闭环见 [AI_NATIVE_SQUARE_HOLE_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-04.md](./prd/AI_NATIVE_SQUARE_HOLE_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-04.md)。
- [PRD](./prd/README.md):产品需求与阶段计划;参考 MOKU / 幕间类 AI 文游的百梦 `text-game` 模板口径见 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md](./prd/AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md),视觉小说模板 TXT 玩法平台化接入口径见 [AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md](./prd/AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md),创意互动内容 Agent Phase 1 的 LangChain-Rust PoC、拼图闭环和并行任务拆分见 [CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md](./prd/CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md),幸存者类模板闭环见 [AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md](./prd/AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md),后台管理独立前端工程见 [ADMIN_WEB_CONSOLE_PRD_2026-04-30.md](./prd/ADMIN_WEB_CONSOLE_PRD_2026-04-30.md),新增 RPG 开场动画方案见 [AI_NATIVE_RPG_OPENING_ANIMATION_PRD_2026-04-25.md](./prd/AI_NATIVE_RPG_OPENING_ANIMATION_PRD_2026-04-25.md),新增抓大鹅 Match3D 玩法方案见 [AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md](./prd/AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md),方洞挑战创作、发布与试玩闭环见 [AI_NATIVE_SQUARE_HOLE_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-04.md](./prd/AI_NATIVE_SQUARE_HOLE_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-04.md)。
生产部署切换到 systemd + Nginx + SpacetimeDB 自托管的总方案见 [PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md](./technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md),该文档也是当前生产 Jenkinsfile 的唯一入口。SpacetimeDB 表结构变更、自动迁移边界和保留旧数据的分阶段迁移流程见 [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md)private 表迁移 JSON 导入导出、HTTP 413 分片导入和旧数据库迁移流水线经验见 [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./technical/SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md) 与 [JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md](./technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md);后台管理独立前端工程技术方案见 [ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md](./technical/ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md)。
@@ -49,7 +49,3 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_
- `reference/`:偏目录、速查、检索辅助。
- `tracking/`:偏埋点原始事实和聚合投影查询,不放任务进度或钱包对账。
- `operations/`:偏后台运营核查、对账和排障查询。
## 文档命名规则
后续新增的 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`。标签用于跨目录检索,不替代上面的目录分类;历史文档不要求批量重命名,除非本次任务明确涉及该文档。

View File

@@ -6,7 +6,7 @@
当前自定义世界创作工具已经有了比较强的生成骨架、锚点结构和结果编辑能力,但整体仍处在一个很明显的“半收口状态”:
**设计目标已经走到“陶泥儿主工作台”,数据结构已经支持“锚点化输入”,但实际体验仍然更像“大文本生成器 + 大型结果总表编辑器”。**
**设计目标已经走到“百梦主工作台”,数据结构已经支持“锚点化输入”,但实际体验仍然更像“大文本生成器 + 大型结果总表编辑器”。**
如果用一句话概括当前问题,就是:
@@ -61,7 +61,7 @@
- 标志性要素
- 禁止事项
但实际入口 `src/components/SelectionCustomizationModals.tsx` 里,陶泥儿主弹窗仍然基本只有:
但实际入口 `src/components/SelectionCustomizationModals.tsx` 里,百梦主弹窗仍然基本只有:
- 生成模式
- 一块大 textarea
@@ -82,7 +82,7 @@
---
## 2.2 澄清机制已经存在,但没有真正服务陶泥儿
## 2.2 澄清机制已经存在,但没有真正服务百梦
`server-node/src/services/customWorldSessionStore.ts` 已经支持:
@@ -101,7 +101,7 @@
这意味着:
**系统表面上已经有“先澄清再生成”的能力,但实际体验里,陶泥儿主并没有真正参与这一步。**
**系统表面上已经有“先澄清再生成”的能力,但实际体验里,百梦主并没有真正参与这一步。**
结果就是:
@@ -113,7 +113,7 @@
- 把 session question 真正接到前端,作为生成前的二次确认步骤。
- 每次只问 `1~3` 个最关键问题,不要把它做成问卷。
- 支持“一键使用系统建议”,但必须让陶泥儿主可见,而不是静默自动填充。
- 支持“一键使用系统建议”,但必须让百梦主可见,而不是静默自动填充。
- 把回答结果回写到 `creatorIntent`,而不是只作为一次性会话答案。
---
@@ -175,7 +175,7 @@
这会带来三层问题:
1. 陶泥儿主负担过重
1. 百梦主负担过重
- 很多字段属于“系统编译层”,不属于“创作决策层”。
2. 移动端负担过重
@@ -240,7 +240,7 @@
---
## 2.6 快速模式还不够“快”,生成页也还不够“陶泥儿主视角”
## 2.6 快速模式还不够“快”,生成页也还不够“百梦主视角”
当前快速模式的主要区别,是把数量降成:
@@ -269,7 +269,7 @@
- 计时
- 模型阶段
而不是陶泥儿主真正关心的:
而不是百梦主真正关心的:
- 关键角色有没有成型
- 核心冲突有没有稳定
@@ -281,7 +281,7 @@
- 快速模式改成真正的“关键锚点预览模式”:
- 先只生成关键角色、关键地点、核心冲突摘要
- 暂不补全所有长尾档案
- 生成页改成“陶泥儿主视角进度”:
- 生成页改成“百梦主视角进度”:
- 世界灵魂已确定
- 关键角色已成型
- 关键地点已落地
@@ -391,16 +391,16 @@
### P0先修主链路闭环
- 补卡片化输入入口,至少把关键锚点输入真正开放出来。
- 把澄清问题正式接入陶泥儿主流程,不再静默自动兜底。
- 把澄清问题正式接入百梦主流程,不再静默自动兜底。
- 修正“新建完成后直接回世界列表”的流程,生成后默认进入结果工作台。
- 统一锁定与局部重生成规则,先让“陶泥儿主不怕重生成”成立。
- 统一锁定与局部重生成规则,先让“百梦主不怕重生成”成立。
### P1再降低工作台负担
- 结果页默认只展示高杠杆编辑。
- 低杠杆字段进入高级模式。
- 快速模式改成真正的关键对象预览模式。
- 生成页改成陶泥儿主视角进度,而不是模型批次视角。
- 生成页改成百梦主视角进度,而不是模型批次视角。
### P2最后做架构收口与去模板化
@@ -441,4 +441,4 @@
当前自定义世界创作工具最需要的,不是再继续补更多字段或更多生成步骤,而是:
**把“陶泥儿主先决定灵魂锚点,系统再稳定展开世界”这条主逻辑真正落到 UI、流程和后端边界上。**
**把“百梦主先决定灵魂锚点,系统再稳定展开世界”这条主逻辑真正落到 UI、流程和后端边界上。**

View File

@@ -1,15 +1,15 @@
# 陶泥儿线下展会易拉宝设计记录 2026-05-07
# 百梦线下展会易拉宝设计记录 2026-05-07
## 1. 目标
陶泥儿线下展会制作一张纵向易拉宝广告展板,用于在展位现场快速传达:
百梦线下展会制作一张纵向易拉宝广告展板,用于在展位现场快速传达:
1. 产品名称:陶泥儿
2. 产品愿景:陶泥儿AI团队致力于打造AI互动内容UGC平台。
1. 产品名称:百梦
2. 产品愿景:百梦AI团队致力于打造AI互动内容UGC平台。
3. 产品slogan不用代码不用美术10分钟把脑洞变成有趣的体验。
4. 产品特点:低门槛创作、高完成度作品、玩过后可改造并发布。
5. 关键技术Harness Engineering、多Agent调度、AI创作工具、AI原生游戏框架。
6. 产品心智:想玩但找不到、玩到不满意、平台外体验不满意时,都可以来陶泥儿做成自己满意的。
6. 产品心智:想玩但找不到、玩到不满意、平台外体验不满意时,都可以来百梦做成自己满意的。
## 2. 视觉方向
@@ -27,7 +27,7 @@
第一层:品牌识别
```text
陶泥儿
百梦
10分钟做自己的互动内容
```
@@ -57,10 +57,10 @@
第四层:产品心智与关键技术
```text
当用户找不到想玩的游戏 -> 来陶泥儿做给自己玩
当用户找不到想玩的游戏 -> 来百梦做给自己玩
当用户玩到了不好玩的游戏 -> 快速改成自己喜欢玩的
当用户在平台外玩到了不满意的游戏 -> 来陶泥儿做成自己满意的
什么游戏最好玩? -> 来陶泥儿玩自己做的游戏最好玩
当用户在平台外玩到了不满意的游戏 -> 来百梦做成自己满意的
什么游戏最好玩? -> 来百梦玩自己做的游戏最好玩
```
关键技术压缩为:
@@ -82,7 +82,7 @@ AI原生游戏框架
```text
model: gpt-image-2
size: 1536x3840
reference image: 陶泥儿气泡共创logo方向图
reference image: 百梦气泡共创logo方向图
output: output/imagegen/baimeng-expo-rollup/baimeng-rollup-background-gpt-image-2.png
```
@@ -119,17 +119,17 @@ output/imagegen/baimeng-expo-rollup/baimeng-rollup-final-cn-preview.png
北京亓盒网络科技有限公司
岗位名称AI 原生游戏产品/内容实习生
行业方向AI 原生游戏 × UGC 内容创作 × 互动叙事
产品:陶泥儿 AI互动内容创作平台
产品:百梦 AI互动内容创作平台
```
新版保留陶泥儿气泡色彩、轻盈白底和创作流动感但新增校园实验室、AI 游戏创作、作品卡、产品测试与内容设计氛围。版面结构调整为:
新版保留百梦气泡色彩、轻盈白底和创作流动感但新增校园实验室、AI 游戏创作、作品卡、产品测试与内容设计氛围。版面结构调整为:
1. 顶部:公司名、岗位名、行业方向与招聘主标题。
2. 中上:陶泥儿产品主张与三枚产品能力标签。
2. 中上:百梦产品主张与三枚产品能力标签。
3. 中部:按 `游玩 -> 改造 -> 创作` 顺序展示产品体验闭环。
4. 中下:介绍“我们正在做的事「陶泥儿」”。
4. 中下:介绍“我们正在做的事「百梦」”。
5. 下部:实习生参与内容、加分项、团队背景和联系方式。
6. 底部:预留两个方形二维码占位,收尾文案为 `陶泥儿 | 让每个人都能做自己的游戏`
6. 底部:预留两个方形二维码占位,收尾文案为 `百梦 | 让每个人都能做自己的游戏`
新版使用当前仓库 `VectorEngine gpt-image-2-all` 路径生成底图:
@@ -137,7 +137,7 @@ output/imagegen/baimeng-expo-rollup/baimeng-rollup-final-cn-preview.png
model: gpt-image-2-all
size: 1536x3840
reference image 1: 用户提供的上一版海报截图
reference image 2: 陶泥儿气泡共创logo方向图
reference image 2: 百梦气泡共创logo方向图
output: output/imagegen/baimeng-recruitment-rollup/baimeng-recruitment-rollup-background-gpt-image-2-all.png
```

View File

@@ -1,8 +1,8 @@
# 陶泥儿 logo gpt-image-2 概念方案 2026-05-05
# 百梦 logo gpt-image-2 概念方案 2026-05-05
## 1. 产品气质提炼
当前产品对外名为“陶泥儿”,核心不是单一 RPG 玩法,而是面向互动叙事、世界生成和运行时演出的 AI 原生创作平台。
当前产品对外名为“百梦”,核心不是单一 RPG 玩法,而是面向互动叙事、世界生成和运行时演出的 AI 原生创作平台。
本次 logo 概念围绕以下关键词设计:
@@ -16,7 +16,7 @@
视觉方向:
- 用一个打开的门 / 星门作为主体,门内有多条细线向外延展,代表陶泥儿主从一个灵感入口进入多个世界。
- 用一个打开的门 / 星门作为主体,门内有多条细线向外延展,代表百梦主从一个灵感入口进入多个世界。
- 负形中弱化出“百”的结构,不强行写字,方便后续做 App icon、favicon 和小尺寸导航标。
- 色彩以暖白、珊瑚粉、少量紫蓝和深墨色组成,贴近平台亮色主题,同时保留梦境和 AI 的科技感。
@@ -28,7 +28,7 @@
设计含义:
“梦门”代表创作入口,“星轨”代表剧情线程、角色关系和世界分支。它强调陶泥儿是让创作者开启世界的工具,而不是只播放固定剧情的游戏。
“梦门”代表创作入口,“星轨”代表剧情线程、角色关系和世界分支。它强调百梦是让创作者开启世界的工具,而不是只播放固定剧情的游戏。
## 3. 方案 B叙事图谱
@@ -36,7 +36,7 @@
- 用节点、弧线和轻微书页轮廓组成一个稳定的圆形标志。
- 图谱整体形成近似“百”的秩序感,避免复杂到小尺寸失真。
- 色彩以深墨、湖青、点金和珊瑚色组合,体现规则边界与创作活力并存。
- 色彩以深墨、湖青、点金和珊瑚色组合,体现规则边界与创作活力并存。
适合场景:
@@ -48,13 +48,13 @@
这个方向更强调“世界不是一段文本,而是一张可控的叙事图谱”。节点是角色、地点、物件和任务,弧线是关系、暗线与回响。
## 4. 方案 C点梦织
## 4. 方案 C点梦织
视觉方向:
- 多个点汇聚成柔和的“B / 百”抽象符号,中心像一枚被点亮的种子。
- 多个点汇聚成柔和的“B / 百”抽象符号,中心像一枚被点亮的种子。
- 线条更轻,图形更偏平台化和消费级,不做重游戏徽章。
- 色彩采用珊瑚粉、暖金、浅青和深色细线,表达“点”消费单位与灵感生长。
- 色彩采用珊瑚粉、暖金、浅青和深色细线,表达“点”消费单位与灵感生长。
适合场景:
@@ -64,7 +64,7 @@
设计含义:
每个点都是一次生成、一次灵感、一次世界推进。多点汇聚成梦,呼应“陶泥儿”里从许多小创意生长出完整作品的路径。
每个点都是一次生成、一次灵感、一次世界推进。多点汇聚成梦,呼应“百梦”里从许多小创意生长出完整作品的路径。
## 5. 方案 D像素剧场
@@ -82,11 +82,11 @@
设计含义:
舞台代表演出,卷轴代表叙事,星形光标代表 AI 与玩家选择。它让陶泥儿看起来仍然属于游戏和互动内容,而不是泛 AI 工具。
舞台代表演出,卷轴代表叙事,星形光标代表 AI 与玩家选择。它让百梦看起来仍然属于游戏和互动内容,而不是泛 AI 工具。
## 6. 生成说明
本次推荐先用 `gpt-image-2` 生成 4 张 `1024x1024` 方形草案。由于图片模型对中文文字的稳定性有限,首轮应优先验证“图形标识”而不是直接把“陶泥儿”两个字烘焙进图片。最终产品落地时,建议使用真实前端字体或 SVG 字形承载“陶泥儿”字标,把生成图作为图形标志参考。
本次推荐先用 `gpt-image-2` 生成 4 张 `1024x1024` 方形草案。由于图片模型对中文文字的稳定性有限,首轮应优先验证“图形标识”而不是直接把“百梦”两个字烘焙进图片。最终产品落地时,建议使用真实前端字体或 SVG 字形承载“百梦”字标,把生成图作为图形标志参考。
## 7. 女性友好与全年龄潮流版补充
@@ -96,8 +96,8 @@
- 字形更圆润,减少尖锐笔锋、黑底压迫感和玄幻气质。
- 色彩从黑白、金色、深墨切换到奶油白、莓果粉、薰衣草紫、薄荷青。
- 允许轻量梦泡、云朵、柔软点等符号,但不堆叠插画。
- 保留“陶泥儿”中文字标作为主识别,图标可作为 App icon 或社交头像补充。
- 允许轻量梦泡、云朵、柔软点等符号,但不堆叠插画。
- 保留“百梦”中文字标作为主识别,图标可作为 App icon 或社交头像补充。
本轮生成 prompt

View File

@@ -1,4 +1,4 @@
# 自定义世界陶泥儿主输入与 AI 分工边界设计
# 自定义世界百梦主输入与 AI 分工边界设计
更新时间:`2026-04-06`
@@ -6,9 +6,9 @@
这份文档回答一个非常关键的问题:
**在“低创作门槛、高创作自由度”的前提下,自定义世界里哪些内容应该交给陶泥儿主直接定义,哪些内容应该交给 AI 和系统完成。**
**在“低创作门槛、高创作自由度”的前提下,自定义世界里哪些内容应该交给百梦主直接定义,哪些内容应该交给 AI 和系统完成。**
这里默认我们的陶泥儿主:
这里默认我们的百梦主:
- 不需要有专业作家背景
- 不需要有专业游戏设计背景
@@ -16,33 +16,33 @@
一句话目标:
**让陶泥儿主把精力放在“决定这个世界为什么值得被创作”,把 AI 用在“把这个世界展开、编译、铺开、校验、补足”。**
**让百梦主把精力放在“决定这个世界为什么值得被创作”,把 AI 用在“把这个世界展开、编译、铺开、校验、补足”。**
## 1. 总体结论
自定义世界的分工边界应该遵守 3 条硬原则:
1. 灵魂归陶泥儿主,杂活归 AI。
- 凡是决定作品气质、主题、冲突、人物关系、审美方向的内容,都应由陶泥儿主掌握。
1. 灵魂归百梦主,杂活归 AI。
- 凡是决定作品气质、主题、冲突、人物关系、审美方向的内容,都应由百梦主掌握。
2. 重点对象归陶泥儿主,长尾铺量归 AI。
- 陶泥儿主应重点塑造少量关键角色、关键地点、关键冲突、关键意象,而不是被迫手填几十个 NPC、几十个场景、几百条描述。
2. 重点对象归百梦主,长尾铺量归 AI。
- 百梦主应重点塑造少量关键角色、关键地点、关键冲突、关键意象,而不是被迫手填几十个 NPC、几十个场景、几百条描述。
3. 决策归陶泥儿主,编译归 AI / 系统。
- 陶泥儿主负责说“这个世界要成为什么样”AI / 系统负责把它编译成可运行的数据、规则、文本、关系钩子和运行时结构。
3. 决策归百梦主,编译归 AI / 系统。
- 百梦主负责说“这个世界要成为什么样”AI / 系统负责把它编译成可运行的数据、规则、文本、关系钩子和运行时结构。
这意味着:
- 陶泥儿主应该主要编辑“高杠杆创作锚点”
- 百梦主应该主要编辑“高杠杆创作锚点”
- AI 应该主要承担“批量展开 + 结构编译 + 一致性维护 + 专业执行”
## 2. 什么内容应该交给陶泥儿
## 2. 什么内容应该交给百梦
真正应该交给陶泥儿主的,不是大量表格字段,而是下面这些会显著决定作品质量、且 AI 不擅长替代的内容。
真正应该交给百梦主的,不是大量表格字段,而是下面这些会显著决定作品质量、且 AI 不擅长替代的内容。
## 2.1 世界核心命题
陶泥儿主应该直接定义:
百梦主应该直接定义:
- 这个世界的一句话设定
- 这个世界最吸引人的核心幻想
@@ -56,7 +56,7 @@
## 2.2 主题、气质与边界
陶泥儿主应该直接定义:
百梦主应该直接定义:
- 主题关键词
- 情绪基调
@@ -71,7 +71,7 @@
## 2.3 玩家身份与开局处境
陶泥儿主应该直接定义:
百梦主应该直接定义:
- 玩家扮演的是什么人
- 玩家一开始最缺什么、最想要什么
@@ -85,7 +85,7 @@
## 2.4 核心冲突与关键势力
陶泥儿主应该直接定义少量高价值内容:
百梦主应该直接定义少量高价值内容:
- 世界当前最重要的 `2~4` 条明面冲突
- 世界背后最关键的 `1~3` 条暗面问题
@@ -96,13 +96,13 @@
- 冲突结构决定世界是否“有戏”
- 势力关系是 AI 最容易写散、写平、写成百科介绍的部分
- 这一层由陶泥儿主把握,才能真正提高作品的辨识度
- 这一层由百梦主把握,才能真正提高作品的辨识度
## 2.5 关键角色与关系张力
陶泥儿主应该直接定义少量关键角色,而不是所有 NPC。
百梦主应该直接定义少量关键角色,而不是所有 NPC。
建议重点交给陶泥儿主的,是:
建议重点交给百梦主的,是:
- `3~8` 个关键角色
- 玩家与这些人的潜在关系
@@ -113,11 +113,11 @@
- 角色关系是最能显著提升作品质量的部分之一
- 这也是 AI 最容易写得“完整但无味”的部分
- 陶泥儿主不需要写长篇背景,但应掌握这些角色真正的关系骨架
- 百梦主不需要写长篇背景,但应掌握这些角色真正的关系骨架
## 2.6 关键地点与空间记忆点
陶泥儿主应该直接定义:
百梦主应该直接定义:
- `4~12` 个关键地点 / 区域 / 地标
- 这些地方为什么重要
@@ -131,7 +131,7 @@
## 2.7 标志性意象、物件、怪物、制度与规则
陶泥儿主应该优先控制世界里最能代表它的东西:
百梦主应该优先控制世界里最能代表它的东西:
- 标志性物件
- 标志性怪物 / 生物
@@ -144,9 +144,9 @@
- 这些内容决定世界的“手感”
- 它们不是普通细节,而是会反复影响命名、剧情、视觉、对话与玩法解释的母题
## 2.8 陶泥儿主应直接控制的“禁止事项”
## 2.8 百梦主应直接控制的“禁止事项”
陶泥儿主必须能明确锁定:
百梦主必须能明确锁定:
- 什么绝对不能改
- 什么不能被 AI 自动扩写到别的方向
@@ -156,7 +156,7 @@
原因:
- 高自由度不等于所有内容都开放漂移
- 如果没有“锁定机制”AI 会把陶泥儿主真正关心的内容稀释掉
- 如果没有“锁定机制”AI 会把百梦主真正关心的内容稀释掉
## 3. 什么内容应该交给 AI 和系统
@@ -176,7 +176,7 @@
原因:
- 这些内容数量大、重复度高
- 它们需要“贴合世界”,但不需要都由陶泥儿主逐个手写
- 它们需要“贴合世界”,但不需要都由百梦主逐个手写
- AI 很适合做“围绕锚点的批量铺量”
## 3.2 从创作锚点到系统结构的编译
@@ -186,7 +186,7 @@
- 从自然语言世界设定中提取题材词汇
- 从关键冲突中编译出世界叙事图谱
- 从关键角色卡编译出角色叙事档案
-陶泥儿主输入里自动生成标签、钩子、隐藏线索、章节摘要
-百梦主输入里自动生成标签、钩子、隐藏线索、章节摘要
- 从地点和关系中编译出场景连接、事件触发和叙事回响
对应当前仓库,下面这些结构更适合由 AI / 系统生成,而不是让玩家直接编辑:
@@ -203,7 +203,7 @@
原因:
- 这些是运行时结构,不是陶泥儿主真正想表达的作品内容
- 这些是运行时结构,不是百梦主真正想表达的作品内容
- 直接暴露给玩家,会把创作过程变成专业数据填表
## 3.3 专业化、规则化的任务
@@ -223,7 +223,7 @@
原因:
- 这些工作要么重复、要么专业、要么容易做脏活累活
- 让非专业陶泥儿主处理,会显著提高门槛,却不一定显著提高质量
- 让非专业百梦主处理,会显著提高门槛,却不一定显著提高质量
## 3.4 一致性、纠错与查漏补缺
@@ -240,15 +240,15 @@
原因:
- 这是 AI 比人更适合做的“维护型工作”
- 它属于创作支持,不属于陶泥儿主必须亲手完成的创作
- 它属于创作支持,不属于百梦主必须亲手完成的创作
## 4. 最合理的边界不是二分法,而是三层分工
自定义世界最合理的结构不是“玩家写”与“AI 写”的简单二选一,而是三层。
## 4.1 第一层:陶泥儿主必控层
## 4.1 第一层:百梦主必控层
这一层必须给陶泥儿主高自由度,且能被锁定:
这一层必须给百梦主高自由度,且能被锁定:
- 世界核心命题
- 主题与气质
@@ -264,9 +264,9 @@
**少而重。**
## 4.2 第二层:陶泥儿主可选强化层
## 4.2 第二层:百梦主可选强化层
这一层不应强制填写,但应该允许陶泥儿主继续深挖:
这一层不应强制填写,但应该允许百梦主继续深挖:
- 明线 / 暗线种子
- 角色之间的旧事
@@ -301,17 +301,17 @@
## 5. 具体模块的建议归属
| 模块 | 建议归属 | 陶泥儿主应控制什么 | AI / 系统应负责什么 |
| 模块 | 建议归属 | 百梦主应控制什么 | AI / 系统应负责什么 |
| --- | --- | --- | --- |
| 世界一句话设定、核心幻想、核心卖点 | 陶泥儿主直接控制 | 直接写、直接改、可锁定 | 给出备选表述和扩展方向 |
| 主题、基调、审美、禁忌 | 陶泥儿主直接控制 | 选择 / 改写 / 锁定 | 生成风格词、避雷词、提示词约束 |
| 玩家身份、开局处境、玩家目标 | 陶泥儿主直接控制 | 直接定义 | 补足开局钩子和初始叙事包装 |
| 关键势力与核心冲突 | 陶泥儿主控AI 辅助 | 定义核心关系和立场 | 扩展冲突支路、生成世界线程 |
| 关键角色 | 陶泥儿主控AI 辅助 | 定义角色骨架、关系张力、秘密方向 | 生成长背景、章节拆分、技能、物品、叙事档案 |
| 关键地点 | 陶泥儿主控AI 辅助 | 定义地点意义、气氛、秘密 | 扩展场景细节、连接关系、遭遇分布 |
| 标志性物件 / 怪物 / 制度 / 规则 | 陶泥儿主控AI 辅助 | 定义代表性要素与硬边界 | 扩展变体、命名、说明、运行时挂钩 |
| 世界一句话设定、核心幻想、核心卖点 | 百梦主直接控制 | 直接写、直接改、可锁定 | 给出备选表述和扩展方向 |
| 主题、基调、审美、禁忌 | 百梦主直接控制 | 选择 / 改写 / 锁定 | 生成风格词、避雷词、提示词约束 |
| 玩家身份、开局处境、玩家目标 | 百梦主直接控制 | 直接定义 | 补足开局钩子和初始叙事包装 |
| 关键势力与核心冲突 | 百梦主控AI 辅助 | 定义核心关系和立场 | 扩展冲突支路、生成世界线程 |
| 关键角色 | 百梦主控AI 辅助 | 定义角色骨架、关系张力、秘密方向 | 生成长背景、章节拆分、技能、物品、叙事档案 |
| 关键地点 | 百梦主控AI 辅助 | 定义地点意义、气氛、秘密 | 扩展场景细节、连接关系、遭遇分布 |
| 标志性物件 / 怪物 / 制度 / 规则 | 百梦主控AI 辅助 | 定义代表性要素与硬边界 | 扩展变体、命名、说明、运行时挂钩 |
| 普通 NPC / 路人 / 杂兵 / 次级地点 | 主要交给 AI | 仅在需要时抽查或替换 | 批量生成与风格保持 |
| 角色长背景、章节 teaser、context snippet | 主要交给 AI | 陶泥儿主只改关键角色即可 | 自动拆章、压缩、解锁节奏整理 |
| 角色长背景、章节 teaser、context snippet | 主要交给 AI | 百梦主只改关键角色即可 | 自动拆章、压缩、解锁节奏整理 |
| 技能、初始物品、标签、构筑倾向 | 主要交给 AI / 系统 | 提供偏好或少量 override | 按角色和世界规则自动编译 |
| 世界图谱、知识事实、可见性、导演指令 | AI / 系统内部层 | 不应默认暴露给玩家 | 运行时编译与维护 |
| 一致性检查、冲突检查、越权检查 | AI / 系统内部层 | 查看报告、决定是否采纳修改 | 自动扫描并提出修正建议 |
@@ -328,7 +328,7 @@
- 精确数值型 build 倾向
- 复杂掉落预算
更合理的做法是让陶泥儿主填写直觉表达,例如:
更合理的做法是让百梦主填写直觉表达,例如:
- `初见就戒备`
- `容易合作`
@@ -351,7 +351,7 @@
原因:
- 这些字段属于系统运行结构,不属于陶泥儿主自然的创作语言
- 这些字段属于系统运行结构,不属于百梦主自然的创作语言
- 直接让玩家填,会把工具变成只有懂系统的人才能用
## 6.3 不应该要求玩家逐个补完所有人物设定字段
@@ -378,7 +378,7 @@
## 7. 推荐的创作输入形态
要让非专业陶泥儿主也能高自由度创作,输入形态必须改成“自然语言创作卡”,而不是“系统字段表单”。
要让非专业百梦主也能高自由度创作,输入形态必须改成“自然语言创作卡”,而不是“系统字段表单”。
## 7.1 世界层卡片
@@ -397,10 +397,10 @@
## 7.2 每张卡片都允许 3 种输入方式
1. 一句话自由输入
- 适合低门槛陶泥儿
- 适合低门槛百梦
2. 标签 / 选项 / 语气滑条
- 适合不想写太多字的陶泥儿
- 适合不想写太多字的百梦
3. 高级补充
- 适合愿意继续深挖的人
@@ -414,7 +414,7 @@
这是高创作自由度里非常关键的一点。
陶泥儿主应当能:
百梦主应当能:
- 锁定一个角色
- 锁定一个地点
@@ -422,13 +422,13 @@
- 只重生成未锁定部分
- 围绕锁定内容重写其余世界
否则陶泥儿主每次调用 AI都会有“好不容易想好的东西被洗掉”的感受。
否则百梦主每次调用 AI都会有“好不容易想好的东西被洗掉”的感受。
## 8. 面向当前仓库的结构映射建议
为了便于后续落实现有系统,这份边界建议可以直接映射到当前结构:
## 8.1 陶泥儿主输入层
## 8.1 百梦主输入层
建议主要映射到:
@@ -445,7 +445,7 @@
## 8.2 AI 编译层
由 AI / 系统从陶泥儿主输入自动补出:
由 AI / 系统从百梦主输入自动补出:
- `themePack`
- `storyGraph`
@@ -465,7 +465,7 @@
- `CarrierStoryFingerprint`
- `StorySignal`
这些内容应该是“系统如何把世界跑起来”,不是“陶泥儿主必须亲手写完的创作内容”。
这些内容应该是“系统如何把世界跑起来”,不是“百梦主必须亲手写完的创作内容”。
## 9. 产品层面的最终结论
@@ -480,12 +480,12 @@
它应该做成这样:
1. 陶泥儿主决定世界的灵魂锚点。
2. 陶泥儿主重点塑造少量关键人、关键地、关键冲突、关键物。
1. 百梦主决定世界的灵魂锚点。
2. 百梦主重点塑造少量关键人、关键地、关键冲突、关键物。
3. AI 围绕这些锚点批量展开长尾内容。
4. 系统把这些内容编译成可运行的图谱、可见性、任务、物件和关系结构。
5. 陶泥儿主随时可以锁定核心创意,并局部重生成其余部分。
5. 百梦主随时可以锁定核心创意,并局部重生成其余部分。
一句话收束:
**陶泥儿主应该写“这个世界为什么动人”AI 应该负责“让这个世界长出来并跑起来”。**
**百梦主应该写“这个世界为什么动人”AI 应该负责“让这个世界长出来并跑起来”。**

View File

@@ -6,17 +6,17 @@
这份文档用于回答一个更具体的问题:
**参考 RPG 专业剧情策划全流程后,在自定义世界创作工具里,哪些设定必须要求陶泥儿主手动填写,哪些设定应该由 AI 先生成但允许陶泥儿主修改,哪些设定应完全交给系统托管,才能在“尽可能降低门槛”和“尽可能提高作品质量”之间取一个平衡。**
**参考 RPG 专业剧情策划全流程后,在自定义世界创作工具里,哪些设定必须要求百梦主手动填写,哪些设定应该由 AI 先生成但允许百梦主修改,哪些设定应完全交给系统托管,才能在“尽可能降低门槛”和“尽可能提高作品质量”之间取一个平衡。**
这份文档不再只回答“陶泥儿主与 AI 怎么分工”,而是进一步把创作工作台收束成一个更可执行的三层输入结构:
这份文档不再只回答“百梦主与 AI 怎么分工”,而是进一步把创作工作台收束成一个更可执行的三层输入结构:
1. 陶泥儿主必须手填的高杠杆锚点
2. AI 先生成、陶泥儿主可修改的内容草稿层
1. 百梦主必须手填的高杠杆锚点
2. AI 先生成、百梦主可修改的内容草稿层
3. 系统自动编译和运行的托管层
一句话结论:
**让陶泥儿主只负责决定作品的灵魂、视角、冲突和关系钩子,让 AI 负责把这些锚点展开成可编辑的剧情草稿,让系统负责把草稿编译成可运行的结构。**
**让百梦主只负责决定作品的灵魂、视角、冲突和关系钩子,让 AI 负责把这些锚点展开成可编辑的剧情草稿,让系统负责把草稿编译成可运行的结构。**
---
@@ -25,27 +25,27 @@
这套平衡设计要同时满足 5 个目标:
1. 低门槛
-陶泥儿主不需要写长篇设定,也不需要理解底层系统结构。
-百梦主不需要写长篇设定,也不需要理解底层系统结构。
2. 高辨识度
- 陶泥儿主写出来的世界,不应该只是“像一个世界”,而应该保留明显的个人方向。
- 百梦主写出来的世界,不应该只是“像一个世界”,而应该保留明显的个人方向。
3. 高可编辑性
- AI 不能一次生成后就不可控,陶泥儿主必须能改关键对象、关键关系和关键章节。
- AI 不能一次生成后就不可控,百梦主必须能改关键对象、关键关系和关键章节。
4. 高稳定性
- 任务、章节、关系、物件和可见性等运行层结构不能依赖陶泥儿主手填专业字段。
- 任务、章节、关系、物件和可见性等运行层结构不能依赖百梦主手填专业字段。
5. 可扩展
- 愿意深挖的陶泥儿主可以继续补充世界上限,不愿深挖的人也能快速产出质量不错的作品。
- 愿意深挖的百梦主可以继续补充世界上限,不愿深挖的人也能快速产出质量不错的作品。
---
## 2. 核心原则
## 2.1 陶泥儿主手填的必须是“高杠杆决策”,不是“高工作量字段”
## 2.1 百梦主手填的必须是“高杠杆决策”,不是“高工作量字段”
应该要求陶泥儿主手填的内容,必须同时满足下面两个条件:
应该要求百梦主手填的内容,必须同时满足下面两个条件:
1. 会显著决定作品气质和辨识度
2. AI 很难替代判断
@@ -67,9 +67,9 @@
- 章节拆分
- 运行时信号结构
## 2.2 陶泥儿主可改层应该承接“专业策划初稿”,而不是“原始底层字段”
## 2.2 百梦主可改层应该承接“专业策划初稿”,而不是“原始底层字段”
AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,而应该是一批已经成形的内容卡片,例如:
AI 生成后允许百梦主修改的,不应该是一堆技术型字段,而应该是一批已经成形的内容卡片,例如:
- 关键角色卡
- 势力卡
@@ -81,11 +81,11 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
也就是说:
**AI 先给陶泥儿主一个像策划初稿的东西,而不是给一堆系统字段让陶泥儿主自己拼。**
**AI 先给百梦主一个像策划初稿的东西,而不是给一堆系统字段让百梦主自己拼。**
## 2.3 系统托管层必须彻底隐藏专业运行结构
以下这类结构不应该默认要求陶泥儿主理解或编辑:
以下这类结构不应该默认要求百梦主理解或编辑:
- `ThemePack`
- `WorldStoryGraph`
@@ -98,7 +98,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
- 稀有度映射
- 掉落和 build 权重
陶泥儿主应该编辑的是自然语言与内容卡,而不是运行时图结构。
百梦主应该编辑的是自然语言与内容卡,而不是运行时图结构。
## 2.4 先少量必填,再逐层展开
@@ -107,9 +107,9 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
```text
先填最小必填卡
-> AI 生成世界初稿
-> 陶泥儿主修改关键对象
-> 百梦主修改关键对象
-> 系统继续展开长尾
-> 陶泥儿主决定是否进入高级补充
-> 百梦主决定是否进入高级补充
```
## 2.5 默认清爽,深度能力后置
@@ -127,27 +127,27 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 3. 最终建议:三层分工
## 3.1 第一层:必须要求陶泥儿主手动填写
## 3.1 第一层:必须要求百梦主手动填写
这一层只保留最影响作品质量的高杠杆锚点,建议默认强制填写 6 张卡。
## 3.2 第二层AI 生成后支持陶泥儿主修改
## 3.2 第二层AI 生成后支持百梦主修改
这一层由 AI 根据第一层锚点自动展开成专业剧情策划初稿,陶泥儿主可以逐项修改、锁定、局部重生成。
这一层由 AI 根据第一层锚点自动展开成专业剧情策划初稿,百梦主可以逐项修改、锁定、局部重生成。
## 3.3 第三层:其余都交给系统
这一层是把前两层编译成可运行游戏结构所需的系统字段、数值和运行时指令,默认不要求陶泥儿主处理。
这一层是把前两层编译成可运行游戏结构所需的系统字段、数值和运行时指令,默认不要求百梦主处理。
---
## 4. 最低门槛方案:只强制手填 6 张卡
如果目标是尽可能降低门槛,同时又保留作品辨识度,建议只强制陶泥儿主填写以下 6 张卡。
如果目标是尽可能降低门槛,同时又保留作品辨识度,建议只强制百梦主填写以下 6 张卡。
## 4.1 卡 1世界一句话与核心幻想
陶泥儿主必须手填:
百梦主必须手填:
- 世界一句话设定
- 玩家来到这个世界最想体验的感觉
@@ -165,7 +165,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 4.2 卡 2玩家身份与开局困境
陶泥儿主必须手填:
百梦主必须手填:
- 玩家是谁
- 玩家开局最缺什么
@@ -179,7 +179,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 4.3 卡 3主题气质与禁忌边界
陶泥儿主必须手填:
百梦主必须手填:
- 主题关键词
- 情绪基调
@@ -199,7 +199,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 4.4 卡 4核心冲突
陶泥儿主必须手填:
百梦主必须手填:
- 当前世界最重要的 `1~3` 个明面冲突
- 至少 `1` 个隐藏问题或暗面危机
@@ -212,9 +212,9 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 4.5 卡 5关键关系钩子
这里不强制陶泥儿主一开始填写完整角色档案,只要求填写更高杠杆的“关系骨架”。
这里不强制百梦主一开始填写完整角色档案,只要求填写更高杠杆的“关系骨架”。
陶泥儿主必须手填:
百梦主必须手填:
- `2~4` 条关键关系钩子
- 每条钩子至少说明:
@@ -229,7 +229,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 4.6 卡 6标志性要素与硬规则
陶泥儿主必须手填:
百梦主必须手填:
- `2~5` 个标志性要素
- 物件
@@ -247,11 +247,11 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
---
## 5. 不建议强制手填,但应该让 AI 生成后支持陶泥儿主修改的设定
## 5. 不建议强制手填,但应该让 AI 生成后支持百梦主修改的设定
这一层是平衡“低门槛”和“高质量”的关键。
陶泥儿主不需要从零填写这些内容,但 AI 生成后必须能看、能改、能锁定、能局部重生成。
百梦主不需要从零填写这些内容,但 AI 生成后必须能看、能改、能锁定、能局部重生成。
## 5.1 世界外观层
@@ -282,7 +282,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 势力很重要,但让新手一开始手写完整势力表太重
- 更合理的做法是让 AI 基于核心冲突先出草稿,再由陶泥儿主修正
- 更合理的做法是让 AI 基于核心冲突先出草稿,再由百梦主修正
## 5.3 关键角色层
@@ -302,8 +302,8 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 陶泥儿主已经通过“关系钩子”给出最关键的人物骨架
- AI 负责把钩子展开成可编辑角色卡,陶泥儿主再做精修
- 百梦主已经通过“关系钩子”给出最关键的人物骨架
- AI 负责把钩子展开成可编辑角色卡,百梦主再做精修
## 5.4 关键地点层
@@ -319,7 +319,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 地点是世界感的重要来源
- 但新陶泥儿主未必能一开始就写出完整地点网络
- 但新百梦主未必能一开始就写出完整地点网络
## 5.5 世界线程层
@@ -335,7 +335,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 线程是专业剧情结构,适合 AI 先搭骨架
-陶泥儿主必须有权修正哪条线更重要、哪条线该隐藏
-百梦主必须有权修正哪条线更重要、哪条线该隐藏
## 5.6 主线章节层
@@ -350,9 +350,9 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 陶泥儿主已经给出了世界目标、冲突和关系
- 百梦主已经给出了世界目标、冲突和关系
- AI 可以先把它们编成主线章节初稿
- 陶泥儿主再选择保留、删减或重排
- 百梦主再选择保留、删减或重排
## 5.7 支线、角色线、阵营线层
@@ -367,7 +367,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 这是最适合 AI 拉开内容宽度的部分
- 也是最需要陶泥儿主局部精修的部分
- 也是最需要百梦主局部精修的部分
## 5.8 场景章节层
@@ -384,7 +384,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 当前项目已经在走“场景 = 章节单元”的方向
- 这层非常适合 AI 编排出第一版,再由陶泥儿主补强记忆点
- 这层非常适合 AI 编排出第一版,再由百梦主补强记忆点
## 5.9 叙事载体层
@@ -397,7 +397,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
- 场景遗物
- 怪物命名及其故事指向
陶泥儿主主要修改:
百梦主主要修改:
- 哪些载体最重要
- 哪些载体和哪条线程绑定
@@ -417,13 +417,13 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 这些内容适合 AI 批量铺量
- 陶泥儿主只需要挑、改、锁定,不必从零起草
- 百梦主只需要挑、改、锁定,不必从零起草
---
## 6. 其余设定应交给系统托管
以下内容不建议默认暴露给陶泥儿主编辑,应由系统根据前两层自动编译和维护。
以下内容不建议默认暴露给百梦主编辑,应由系统根据前两层自动编译和维护。
## 6.1 题材与术语编译层
@@ -450,7 +450,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 陶泥儿主要的是“故事线能对”,不是维护图数据库
- 百梦主要的是“故事线能对”,不是维护图数据库
## 6.3 可见性和 prompt 裁剪层
@@ -465,7 +465,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
原因:
- 这层必须稳定、严格、自动化
- 不适合依赖陶泥儿主手动维护
- 不适合依赖百梦主手动维护
## 6.4 运行时导演层
@@ -494,7 +494,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
说明:
- 陶泥儿主可以编辑“任务卡”和“章节卡”
- 百梦主可以编辑“任务卡”和“章节卡”
- 但不应默认编辑底层 contract 结构
## 6.6 数值与配置层
@@ -511,7 +511,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
说明:
- 陶泥儿主可以给“偏向”
- 百梦主可以给“偏向”
- 系统负责编译成具体数值
## 6.7 QA 与一致性层
@@ -547,7 +547,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
| 主线 | 不强制首轮手写完整主线 | 幕结构、章节卡、高潮与 handoff | 章节状态编译 |
| 支线/角色线 | 不强制首轮手写完整矩阵 | 支线种子、角色线事件、阵营线分歧 | 任务 contract 编译 |
| 场景章节 | 不强制首轮手写全量章节 | 场景章节卡、阶段内容、章节载体 | signal 与导演层 |
| 运行时结构 | 不建议陶泥儿主接触 | 不建议默认编辑 | 可见性、导演、信号、编译、QA |
| 运行时结构 | 不建议百梦主接触 | 不建议默认编辑 | 可见性、导演、信号、编译、QA |
---
@@ -555,7 +555,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 8.1 第一步:只填写最小必填集
陶泥儿主只需要完成:
百梦主只需要完成:
1. 世界一句话与核心幻想
2. 玩家身份与开局困境
@@ -584,9 +584,9 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
这里的重点不是一次补满全世界,而是先形成一个像样的内容骨架。
## 8.3 第三步:陶泥儿主只精修高价值卡片
## 8.3 第三步:百梦主只精修高价值卡片
建议默认优先让陶泥儿主编辑这 4 类卡片:
建议默认优先让百梦主编辑这 4 类卡片:
1. 关键角色
2. 核心冲突与线程
@@ -606,7 +606,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
- 任务包装
- 文案变体
## 8.5 第五步:陶泥儿主按需进入高级模式
## 8.5 第五步:百梦主按需进入高级模式
高级模式只对愿意深挖的人开放:
@@ -665,7 +665,7 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
## 10.2 每张卡只保留自然语言输入
不要强迫陶泥儿主在首轮填写:
不要强迫百梦主在首轮填写:
- tags
- ids
@@ -676,20 +676,20 @@ AI 生成后允许陶泥儿主修改的,不应该是一堆技术型字段,
更合理的做法是:
-陶泥儿主输入自然语言或选择直觉标签
-百梦主输入自然语言或选择直觉标签
- 再由系统编译成结构化字段
## 10.3 首轮生成后默认先看“精修建议”
AI 初稿生成后,不应该把陶泥儿主直接扔进一个大编辑器。
AI 初稿生成后,不应该把百梦主直接扔进一个大编辑器。
更好的做法是先给出:
1. 哪些卡片最值得改
2. 哪些内容已经比较稳定
3. 哪些内容仍然偏泛,需要陶泥儿主补个性
3. 哪些内容仍然偏泛,需要百梦主补个性
这样能明显提高陶泥儿主的修改效率。
这样能明显提高百梦主的修改效率。
## 10.4 移动端优先只保留高杠杆操作
@@ -707,15 +707,15 @@ AI 初稿生成后,不应该把陶泥儿主直接扔进一个大编辑器。
## 11. 最后结论
如果目标是在自定义世界创作中真正平衡“降低门槛”和“提高作品质量”,最好的做法不是让陶泥儿主填更多字段,也不是把一切都交给 AI。
如果目标是在自定义世界创作中真正平衡“降低门槛”和“提高作品质量”,最好的做法不是让百梦主填更多字段,也不是把一切都交给 AI。
更合理的平衡是:
1. 陶泥儿主必须手填最小但高杠杆的 6 张卡,掌握世界灵魂。
1. 百梦主必须手填最小但高杠杆的 6 张卡,掌握世界灵魂。
2. AI 根据这 6 张卡生成一套可编辑的专业剧情初稿,负责把骨架展开成角色、地点、线程、章节和载体。
3. 陶泥儿主只精修最有价值的关键对象,锁定真正重要的内容。
3. 百梦主只精修最有价值的关键对象,锁定真正重要的内容。
4. 其余运行结构、数值、可见性、任务编译和 QA 检查都交给系统托管。
一句话收束:
**陶泥儿主负责决定“这个世界为什么值得被创作”AI 负责把它整理成可修改的策划初稿,系统负责把它稳定地跑成一个游戏世界。**
**百梦主负责决定“这个世界为什么值得被创作”AI 负责把它整理成可修改的策划初稿,系统负责把它稳定地跑成一个游戏世界。**

View File

@@ -10,7 +10,7 @@
- 基于“最小必填锚点 + AI 初稿卡片 + 系统托管层”的结构化创作方案
2. 纯 Agent 式方向
- 以前台对话为唯一主交互,陶泥儿主主要通过和 Agent 聊天来完成世界构建、角色塑造、剧情扩展和修改
- 以前台对话为唯一主交互,百梦主主要通过和 Agent 聊天来完成世界构建、角色塑造、剧情扩展和修改
文档需要回答 3 个问题:
@@ -34,7 +34,7 @@
当前方案的核心是:
1. 陶泥儿主手填最小高杠杆锚点
1. 百梦主手填最小高杠杆锚点
2. AI 生成一批可编辑的剧情策划初稿卡片
3. 系统把内容编译成运行时结构
@@ -42,7 +42,7 @@
**结构化工作台 + AI 协作生成。**
陶泥儿主的主要行为是:
百梦主的主要行为是:
1. 填写关键卡片
2. 修改关键角色、地点、势力、章节等内容卡
@@ -53,9 +53,9 @@
纯 Agent 式不是指“系统内部没有结构”,而是指:
**陶泥儿主前台几乎不需要面对表单和卡片编辑器,主要通过自然语言对话来完成创作。**
**百梦主前台几乎不需要面对表单和卡片编辑器,主要通过自然语言对话来完成创作。**
陶泥儿主的主要行为变成:
百梦主的主要行为变成:
1. 用自然语言描述世界想法
2. 回答 Agent 的追问
@@ -77,7 +77,7 @@
1. 前台用户主要通过什么方式思考和输入?
2. 后台系统是否仍然有稳定的世界模型和编译层?
3. 陶泥儿主是否还能看见摘要、锁定内容和修改范围?
3. 百梦主是否还能看见摘要、锁定内容和修改范围?
对当前项目来说,真正危险的不是“转成聊天”,而是:
@@ -93,11 +93,11 @@
它更擅长:
1. 帮不擅长表单和结构思考的陶泥儿主起步
2.陶泥儿主思路模糊时做追问和陪创作
1. 帮不擅长表单和结构思考的百梦主起步
2.百梦主思路模糊时做追问和陪创作
3. 把“我要做一个世界”变成一次自然聊天
4. 动态决定追问深度,而不是一上来摆很多字段
5.陶泥儿主感觉自己是在和一个懂 RPG 的剧情搭档共创
5.百梦主感觉自己是在和一个懂 RPG 的剧情搭档共创
## 2.2 纯 Agent 式的主要问题
@@ -110,7 +110,7 @@
1. 聊天很多,但世界状态越来越难总览
2. 角色、地点、势力和章节信息散落在多轮消息里
3. 锁定范围不清,重生成容易误伤已有内容
4. Agent 很容易“替陶泥儿主决定太多”
4. Agent 很容易“替百梦主决定太多”
5. 长会话越来越贵,越来越慢,也越来越容易漂移
## 2.3 对当前项目的判断
@@ -197,7 +197,7 @@
纯 Agent 式更弱的地方在于:
1. 世界模型隐藏得太深时,陶泥儿主会失去整体掌控感
1. 世界模型隐藏得太深时,百梦主会失去整体掌控感
2. 多轮对话后,已确定内容不容易被清晰回看
3. 局部重做和精确编辑边界会变模糊
4. Agent 容易过度代写、过度主导
@@ -223,7 +223,7 @@
因为这些环节的关键问题不是“字段如何摆放”,而是:
**陶泥儿主有没有被真正引导出自己想做的世界。**
**百梦主有没有被真正引导出自己想做的世界。**
## 4.2 不值得直接转成纯聊天黑箱的部分
@@ -261,8 +261,8 @@
即使转成纯 Agent 式,也仍然要保留这三层:
1. 陶泥儿主必须确认的高杠杆锚点
2. AI 生成但允许陶泥儿主修改的策划初稿层
1. 百梦主必须确认的高杠杆锚点
2. AI 生成但允许百梦主修改的策划初稿层
3. 系统托管的运行时编译层
变化的只是:
@@ -339,7 +339,7 @@
2. 会阶段性总结
3. 会把聊天结果沉淀成结构化世界状态
4. 会提醒风险和冲突
5. 会在陶泥儿主要求时进行局部重写和定向扩展
5. 会在百梦主要求时进行局部重写和定向扩展
## 6.2 正确理解
@@ -349,7 +349,7 @@
也就是说:
1. 陶泥儿主看到的是对话
1. 百梦主看到的是对话
2. 系统内部维护的是世界模型、锁定状态、摘要和编译结果
---
@@ -389,7 +389,7 @@ Agent 首轮不应该直接铺满全世界,而应该给出一份简明底稿
2. 建议内容
3. 待确认内容
## 7.3 阶段 C陶泥儿主锁定锚点
## 7.3 阶段 C百梦主锁定锚点
在纯 Agent 模式里,锁定行为必须被显式支持。
@@ -455,7 +455,7 @@ Agent 不应该每轮都继续扩全局,而应该支持“单对象工作模
| 结构 | 作用 |
| --- | --- |
| `creatorIntentProfile` | 当前陶泥儿主最初和最新的创作意图 |
| `creatorIntentProfile` | 当前百梦主最初和最新的创作意图 |
| `lockedAnchors` | 已确认不可自动改写的内容 |
| `worldDraftSnapshot` | 当前世界底稿快照 |
| `editableDraftCards` | 角色、地点、势力、章节等可编辑初稿 |
@@ -530,7 +530,7 @@ Agent 不能像问卷系统,也不能一次追问太多。
1. 一次最多追问 `1~3` 个问题
2. 问题必须是当前最缺的高杠杆信息
3. 每次追问都给默认建议方向
4. 如果陶泥儿主不想细答,允许 Agent 先代补一个版本再确认
4. 如果百梦主不想细答,允许 Agent 先代补一个版本再确认
这样才能保持“像聊天”,而不是“像客服表单”。
@@ -614,14 +614,14 @@ Agent 应能识别这些常见修改类型:
3. 锁定内容固定展示
4. 提供“当前世界圣经”入口
## 11.2 风险 2Agent 过度代写,陶泥儿主失去作品归属感
## 11.2 风险 2Agent 过度代写,百梦主失去作品归属感
防护方式:
1. 高杠杆锚点必须要求确认
2. 重要改动前先说“我准备改什么”
3. 默认优先给多个候选,而不是直接盖写
4. 允许陶泥儿主随时回退到旧版本
4. 允许百梦主随时回退到旧版本
## 11.3 风险 3局部修改带出全局漂移

View File

@@ -37,8 +37,8 @@
- 不能先删旧字段,再补新结构。
- 必须先补新设定层,再逐步迁读,最后再让旧模板字段退化成兼容层。
4. 不能增加陶泥儿主负担
- 这次不是让陶泥儿主多填一堆底层 schema。
4. 不能增加百梦主负担
- 这次不是让百梦主多填一堆底层 schema。
- 这些设定仍然应由 AI / 系统编译出来,只是所有权从模板世界转移到自定义世界自己。
---

View File

@@ -102,9 +102,9 @@
这不是真正跨题材,只是换了名字。
## 3.3 不能让陶泥儿主承担更多底层配置工作
## 3.3 不能让百梦主承担更多底层配置工作
这次优化不是让陶泥儿主额外填写:
这次优化不是让百梦主额外填写:
- 怪物模板表
- 场景参考池

View File

@@ -349,7 +349,7 @@ export interface ChapterProgressionPlan {
}
```
建议作为后端运行时编译结果缓存,不作为陶泥儿主直接编辑字段。
建议作为后端运行时编译结果缓存,不作为百梦主直接编辑字段。
## 3.7 章节经验记账
@@ -636,7 +636,7 @@ chapterXpBudget =
3. 非主角色友方 NPC
- `support``ambient`
如需修正,再允许章节蓝图加可选 override但不要求陶泥儿主每次手填。
如需修正,再允许章节蓝图加可选 override但不要求百梦主每次手填。
## 7.2 等级锚点

View File

@@ -1,29 +1,27 @@
# 移动端草稿页作品列表统一卡片设计 2026-04-29
# 移动端创作页作品列表统一卡片设计 2026-04-29
## 背景
草稿页的作品模块需要同时承载 RPG、拼图和大鱼吃小鱼等玩法。不同玩法卡片不能各自展示阶段、素材、主题等细节标签否则作品列表会在移动端显得拥挤并且草稿作品会暴露过多编辑态信息。
创作页的作品模块需要同时承载 RPG、拼图和大鱼吃小鱼等玩法。不同玩法卡片不能各自展示阶段、素材、主题等细节标签否则作品列表会在移动端显得拥挤并且草稿作品会暴露过多编辑态信息。
本次将作品列表卡片收口成统一信息结构:草稿只用于快速识别和继续创作,已发布作品才展示公开数据;删除与分享等低频操作收进左滑操作层,避免列表常态被按钮挤占
本次将作品列表卡片收口成统一信息结构:草稿只用于快速识别和继续创作,已发布作品才展示公开数据与分享入口
## 落地范围
- 列表容器:`src/components/custom-world-home/CustomWorldCreationHub.tsx`
- 作品卡片:`src/components/custom-world-home/CustomWorldWorkCard.tsx`
- 不改动作品数据聚合、筛选、打开和体验逻辑。
- 已发布作品保留分享能力;可删除作品保留删除能力,但常态不显示为右侧按钮
- 已发布作品右上角动作从删除改为分享;草稿仍保留删除入口
## 卡片结构规则
1. 卡片整体对齐发现 / 分类页的横向作品列表结构:左侧为标题、状态、类型、摘要与必要数据,右侧为带透明度的封面图
1. 标题上方只显示两个标签:作品状态与游戏类型
2. 不再显示阶段、主题、素材完成度、作者、作品号等额外标签。
3.题区域保留作品状态与游戏类型;生成中的草稿状态显示为“生成中”
4. 草稿卡片到作品描述为止,不显示右侧“继续创作”等固定动作、统计、作品号或公开指标
3.签下方依次显示作品名称与作品描述
4. 草稿卡片到作品描述为止,不显示其他统计、作品号或体验按钮
5. 已发布卡片在描述下方显示三项公开指标:游玩数、改造数、点赞数。
6. 已发布卡片的分享入口收进左滑操作层,点击后复制作品分享文案,不触发卡片打开。
7. 可删除卡片的删除入口收进左滑操作层,常态不显示删除按钮;左滑露出后点击删除不触发卡片打开。
8. 卡片不显示最后修改时间;`updatedAt` 只用于作品列表排序。
9. 生成中的卡片在整卡上叠加半透明蒙版、旋转等待符号和“生成中...”标识;蒙版不能移除标题、状态、类型、摘要、右侧封面等原有信息。
6. 已发布卡片右上角显示分享 icon,点击后复制作品分享文案,不触发卡片打开。
7. 草稿卡片右上角继续显示删除 icon点击删除不触发卡片打开。
## 公开指标重点展示补充
@@ -32,24 +30,14 @@
3. 用户每次进入创作页时,前端读取上一次进入该页面缓存的公开指标快照;当已发布作品卡片滑动进入视口后,数字从缓存值增长到本次接口返回的最新值。
4. 若最新值高于缓存值,动画完成后在对应指标右下角展示红色向上箭头和本次上涨的具体数值,字号低于主数字,避免抢占主信息层级。
5. 若没有缓存值、缓存值不低于最新值或作品仍是草稿,则直接显示最新值,不展示上涨标记。
6. 每张作品卡片继续使用作品封面作为右侧方形半透明主视觉;封面不能因为列表收缩被拉伸变形
7. 作品列表按 `updatedAt` 倒序排列;前端排序需要兼容 ISO 时间和 Rust 后端常用的 `seconds.microsZ` 时间文本。
8. 若玩法摘要缺少 `coverImageSrc`,允许从同一作品的正式关卡图、背景图或素材图里取第一张可用图片作为卡片背景兜底。
9. 若作品真实图片为空、私有资源换签失败或浏览器图片加载失败,卡片必须切到对应玩法的 `public/creation-type-references/` 参考图;最终兜底底色使用平台浅粉暖白色系,不允许退回黑色普通面板。
6. 每张作品卡片继续使用作品封面作为整卡背景,封面需要有透明度和渐变遮罩,确保标题、描述和指标在亮色与暗色主题下都清晰可读
## 移动端布局规则
1. 作品列表默认使用单列纵向列表,视觉上与发现页分类列表保持一致
2. 移动端每张卡片使用固定右列方形半透明封面,右列建议 `5.1rem` 左右;草稿卡即使复用分类页基础类名,也必须用自身选择器覆盖分类页的 `4.3rem + 正文 + action` 三列规则,避免正文被压进窄列
3. 已发布作品的公开指标在卡片正文内保留,但需要压缩字号和间距,不能让右侧封面列错位
1. 作品列表默认使用 2 列网格,保证草稿可以快速扫视
2. 已发布作品卡片在移动端固定 `col-span-2`,即占据一整行,避免公开指标和分享入口互相挤压
3. `sm` 及以上视口恢复普通网格跨度,由卡片自然进入多列布局
4. 小屏卡片降低高度、内边距、标题字号和徽标尺寸,避免长标题或中文描述撑破容器。
5. 右侧封面容器本身必须带玩法参考图 CSS 背景兜底;`img` 的真实封面或 `ResolvedAssetImage` fallback 加载失败时,也不能出现空白或黑卡。
## 网页端布局规则
1. 网页端作品架不能继续拉成整行超宽列表;从 `768px` 起使用多列卡片式网格,默认两列,宽屏提升到三列。
2. 网页端卡片保留移动端同一信息结构,但卡片高度增加,正文区可显示更多摘要与公开指标,右侧封面改为更高的半透明视觉区。
3. 删除与分享仍然只在左滑或键盘揭示态显示;默认态不得透出红色删除底层或分享底层。
## 文案约束

View File

@@ -1,6 +1,6 @@
# 平台创作 Tab 模板入口设计
更新时间:`2026-05-14`
更新时间:`2026-05-07`
## 1. 目标
@@ -18,7 +18,7 @@
```text
标题10分钟创作一个精品互动玩法
模板 Tab拼图 / 抓大鹅 / AIRP
模板 Tab拼图 / 抓大鹅 / 视觉小说(敬请期待)/ AIRP
默认内容:拼图创作表单
```
@@ -34,17 +34,16 @@
1. 打开“创作”一级 Tab 时默认停留在拼图 Tab不主动创建拼图 session。
2. 点击拼图表单“生成草稿”后,才创建拼图 session 并执行 `compile_puzzle_draft`
3. 拼图表单内的模板按钮使用 `tablist / tab` 语义,点击后只填充画面描述。
4. 点击非拼图且已开放的模板 Tab 时进入该玩法既有工作台AIRP 当前保持敬请期待禁用态。
5. `visual-novel` 暂时从创作页完全隐藏,不出现在模板 Tab、旧选择弹层和创作 Hub 卡片中;既有作品、详情、运行链路继续保留
6. `creative-agent` 不出现在模板 Tab选择弹层中,不再作为创作 Tab 首屏入口
7. 方洞挑战暂时从创作页完全隐藏,不出现在模板 Tab、旧选择弹层和创作 Hub 卡片中;既有作品链路继续保留。
4. 点击非拼图且已开放的模板 Tab 时,进入该玩法既有工作台;视觉小说与 AIRP 当前保持敬请期待禁用态。
5. `creative-agent` 不出现在模板 Tab选择弹层中,不再作为创作 Tab 首屏入口
6. 方洞挑战暂时从创作页完全隐藏,不出现在模板 Tab、旧选择弹层和创作 Hub 卡片中;既有作品链路继续保留
## 4. 验收
1. 点击“创作”后首屏出现“10分钟创作一个精品互动玩法”。
2. 顶部选择模板入口为 Tab拼图 Tab 默认 `aria-selected=true`
3. 创作 Tab 默认显示拼图创作表单内容且不显示旧“Hi, 朋友”、输入框或智能创作快捷按钮。
4. 隐藏的智能创作类型、视觉小说与方洞挑战不出现在模板 Tab、旧选择弹层和创作 Hub 卡片中。
4. 隐藏的智能创作类型与方洞挑战不出现在模板 Tab、旧选择弹层和创作 Hub 卡片中。
5. 草稿页返回创作页后仍回到同一模板入口,并可保留拼图表单草稿内容。
## 5. 嵌入式表单 UI 细节

View File

@@ -96,7 +96,7 @@
- 同时开放短信与密码登录时,面板顶部展示两个居中的文字页签,当前页签使用深色字重和短下划线强调。
- 只渲染当前页签对应的输入区;切换页签不弹出新面板,不展示二维码入口。
- `短信登录` 页签包含手机号、验证码、获取验证码和主按钮。
- `密码登录` 页签只包含手机号、密码、主按钮和忘记密码入口;不支持邮箱、用户名或陶泥号。
- `密码登录` 页签只包含手机号、密码、主按钮和忘记密码入口;不支持邮箱、用户名或百梦号。
- 密码登录只是手机号验证码登录的补充方式:只有已登录并设置过密码的手机号账号才能使用,不能在密码页签创建账号。
- `密码登录` 主按钮固定为 `登录`,不得使用 `注册/登录`
- 未开放某个登录方式时不展示对应页签,避免用户进入不可用表单。

View File

@@ -68,9 +68,6 @@
- 默认显示全部作品列表,保留草稿/已发布筛选。
- 入口、删除、分享、领取拼图激励等行为全部复用现有 `CustomWorldCreationHub` 的作品卡逻辑。
- 一级底部 Tab 文案为“草稿”,内部仍可按草稿与已发布筛选。
- 作品列表必须按最后修改时间倒序排列;排序使用后端 `updatedAt`,前端需要兼容 ISO 字符串和 `seconds.microsZ` 两种时间文本。
- 每张作品卡以作品封面图铺满整卡背景,并叠加遮罩保证标题和描述可读;遮罩不能把封面洗成普通面板底色。缺 `coverImageSrc` 但同一作品已有正式关卡图、背景图或素材图时,优先用这些真实作品图兜底;若封面签名失败或作品还没有可用图片,再按玩法使用 `public/creation-type-references/` 的参考图兜底,最终无图底色也必须保持百梦浅粉暖色调,不能回退为黑色卡片。
- 草稿页卡片不展示“最后修改时间”“更新于”或原始 `updatedAt` 文本,时间只参与排序。
## 6. 我的页玩过列表
@@ -127,5 +124,3 @@
- 草稿作品卡在生成中展示“生成中”状态标记;新生成完成且用户尚未查看的草稿在卡片右上角展示红点。
- 底部一级“草稿”Tab 在存在未查看新完成草稿时展示红点用户点击查看带红点的作品后该作品红点消失。若草稿页已无任何带红点作品底部“草稿”Tab 红点同步消失。
- 生成完成时如果用户仍停留在对应生成过程页,可自动进入结果页;如果用户已经回到创作中心或其它功能页,不打断当前操作。
- 创作 Tab 的模板入口只允许被模板自身的开放状态禁用;某个草稿后台生成中时,不得用该玩法的 busy 状态禁用其它模板入口、同模板再次创建入口或阻止用户继续创建新作品。
- 同模板再次点击生成时必须创建新的草稿生成任务,不得因为当前玩法已有后台生成 session 就跳回上一条草稿的生成过程页;查看上一条生成进度只能从草稿 Tab 的对应作品卡进入。

View File

@@ -59,9 +59,8 @@
### 3.2 排版
- 平台层正文、按钮、说明、功能标签统一使用非像素字体
- 左上角 `陶泥儿 / GENARRATIVE` 品牌字标允许单独做成像素化 logo
- `GENARRATIVE``陶泥儿` 都优先直接使用游戏内同款 `Fusion Pixel`
- 品牌中文主标固定显示为 `陶泥` + 半字号 `儿``儿` 必须继承主标同一字体和字号后再视觉缩放到 50%,并与 `陶泥` 底部对齐,随移动端和场景覆盖等比例缩放
- 左上角 `百梦 / GENARRATIVE` 品牌字标允许单独做成像素化 logo
- `GENARRATIVE``百梦` 都优先直接使用游戏内同款 `Fusion Pixel`
- 品牌字标默认保持正常像素字观感,禁止再叠双层粗阴影或手动加粗到影响识别
- 品牌字标直接使用字体文件内原字形,不额外做运行时描字、轮廓拼字或伪粗体处理
- 主标题保留明显层级,但不再做像素描边效果

View File

@@ -5,8 +5,7 @@
## 文档列表
- [CHILD_MOTION_DEMO_WARMUP_LEVEL_DESIGN_2026-05-09.md](./CHILD_MOTION_DEMO_WARMUP_LEVEL_DESIGN_2026-05-09.md)4-8 岁儿童动作识别互动玩法 Demo 固定热身关的横屏体验流程、识别目标、表现需求与待确认事项。
- [TAONIER_BRAND_LOGO_CONCEPTS_2026-05-13.md](./TAONIER_BRAND_LOGO_CONCEPTS_2026-05-13.md)候选产品名“陶泥儿”的品牌定位归纳、gpt-image-2 Logo 概念图和主标选择建议
- [CUSTOM_WORLD_CREATOR_INPUT_AND_AI_BOUNDARY_DESIGN_2026-04-06.md](./CUSTOM_WORLD_CREATOR_INPUT_AND_AI_BOUNDARY_DESIGN_2026-04-06.md):自定义世界里陶泥儿主输入与 AI 分工边界设计。
- [CUSTOM_WORLD_CREATOR_INPUT_AND_AI_BOUNDARY_DESIGN_2026-04-06.md](./CUSTOM_WORLD_CREATOR_INPUT_AND_AI_BOUNDARY_DESIGN_2026-04-06.md)自定义世界里百梦主输入与 AI 分工边界设计
- [CUSTOM_WORLD_CREATOR_MANUAL_AI_SYSTEM_BALANCE_DESIGN_2026-04-12.md](./CUSTOM_WORLD_CREATOR_MANUAL_AI_SYSTEM_BALANCE_DESIGN_2026-04-12.md):自定义世界创作里“手填锚点 / AI 可改初稿 / 系统托管层”的平衡设计。
- [CUSTOM_WORLD_CREATOR_PURE_AGENT_COMPARISON_AND_CONVERSION_DESIGN_2026-04-12.md](./CUSTOM_WORLD_CREATOR_PURE_AGENT_COMPARISON_AND_CONVERSION_DESIGN_2026-04-12.md):纯 Agent 式创作工具与结构化工作台方案的优缺点对比,以及转型设计。
- [CUSTOM_WORLD_TEMPLATE_DECOUPLING_AND_CROSS_GENRE_GENERALIZATION_DESIGN_2026-04-08.md](./CUSTOM_WORLD_TEMPLATE_DECOUPLING_AND_CROSS_GENRE_GENERALIZATION_DESIGN_2026-04-08.md):把自定义世界从武侠/仙侠模板依赖迁到跨题材通用设定层的优化设计。
@@ -19,7 +18,7 @@
- [PLATFORM_CATEGORY_AND_CREATE_TAB_DESIGN_2026-04-24.md](./PLATFORM_CATEGORY_AND_CREATE_TAB_DESIGN_2026-04-24.md):平台入口新增分类 Tab、登录态导航裁剪与创作 Tab 视觉强化设计。
- [PLATFORM_BIG_FISH_ENTRY_HIDE_2026-04-28.md](./PLATFORM_BIG_FISH_ENTRY_HIDE_2026-04-28.md):平台入口暂时隐藏大鱼吃小鱼创作卡片,但保留现有玩法链路。
- [UNIFIED_MODAL_WINDOW_DESIGN_2026-04-25.md](./UNIFIED_MODAL_WINDOW_DESIGN_2026-04-25.md):统一平台风与 RPG 像素风模态窗口外壳、交互边界和迁移顺序。
- [BAIMENG_EXPO_ROLLUP_BANNER_DESIGN_2026-05-07.md](./BAIMENG_EXPO_ROLLUP_BANNER_DESIGN_2026-05-07.md)陶泥儿线下展会易拉宝广告展板的文案层级、视觉方向与 gpt-image-2 生成记录。
- [BAIMENG_EXPO_ROLLUP_BANNER_DESIGN_2026-05-07.md](./BAIMENG_EXPO_ROLLUP_BANNER_DESIGN_2026-05-07.md)百梦线下展会易拉宝广告展板的文案层级、视觉方向与 gpt-image-2 生成记录。
- [AI_NATIVE_RUNTIME_ITEM_SYSTEM_REDESIGN_2026-04-02.md](./AI_NATIVE_RUNTIME_ITEM_SYSTEM_REDESIGN_2026-04-02.md):运行时物品生成系统重设计。
- [LEVEL_PROGRESS_AND_CHAPTER_NPC_AUTO_SCALING_DESIGN_2026-04-20.md](./LEVEL_PROGRESS_AND_CHAPTER_NPC_AUTO_SCALING_DESIGN_2026-04-20.md):等级成长、章节经验节奏与 NPC 自动定级设计。
- [RPG_NARRATIVE_PLANNING_FULL_PIPELINE_WORKFLOW_2026-04-12.md](./RPG_NARRATIVE_PLANNING_FULL_PIPELINE_WORKFLOW_2026-04-12.md):专业剧情策划构建 RPG 游戏全剧情的工作流程与交付模板。
@@ -34,8 +33,8 @@
- 做物品、Build、锻造相关需求时先看前两份。
- 做 RPG 全剧情规划、主支线矩阵、角色线、场景章节与剧情交付模板时,先看新增的全剧情策划流程。
- 做自定义世界创作工作台、陶泥儿主输入边界、AI 分工设计时,先看第一份。
- 做“哪些内容必须让陶泥儿主手填、哪些适合 AI 先生成再改、哪些必须系统托管”这类分层设计时,优先看新增的输入平衡设计稿。
- 做自定义世界创作工作台、百梦主输入边界、AI 分工设计时,先看第一份。
- 做“哪些内容必须让百梦主手填、哪些适合 AI 先生成再改、哪些必须系统托管”这类分层设计时,优先看新增的输入平衡设计稿。
- 做“是否应该转成纯 Agent 式创作工具、转了之后前后台各该怎么收口”这类产品方向评估时,优先看新增的纯 Agent 对比与转型设计稿。
- 做自定义世界去模板依赖、跨题材泛化、兼容迁移设计时,优先看新增的去模板化优化设计稿。
- 做“模板依赖如何真正变成自定义世界自有设定层”的具体迁移方案时,优先看新增的自有设定层优化方案。

View File

@@ -1,423 +0,0 @@
# 陶泥儿品牌 Logo 概念稿
> 本稿是围绕候选产品名“陶泥儿”的品牌视觉探索,不替代当前已冻结的“百梦”正式命名口径。若后续确认更名,需要另起产品命名、前后端文案和商标检索落地方案。
## 1. 品牌定位归纳
“陶泥儿”适合承接的不是传统陶艺或儿童黏土,而是“把灵感塑形成可玩内容”的 AI 创作平台隐喻。
核心关键词:
- 精品:作品不是随手糊出来,而是经过 AI 辅助打磨、可被消费和传播的轻精品内容。
- UGC用户是主要造物者平台降低创作门槛。
- 创作:从一句脑洞、一个梗、一张图,生成小游戏、互动作品或可分享内容。
- 裂变与梗:名字要支持“开捏”“捏个梗”“捏个小游戏”这类用户语言。
- 轻度休闲:体验应松弛、即时、好玩,不走硬核生产工具气质。
- AIAI 是塑形能力,不是冷冰冰的技术标签。
推荐品牌主张:
```text
把脑洞捏成小游戏
```
备选表达:
```text
捏个脑洞,马上开玩
AI 开捏,人人会创作
随手造梗,随心开玩
```
## 2. 生成原则
本轮使用仓库 GPT-image-2 / VectorEngine 工作流生成 Logo 概念图,生成时刻意要求“无文字 Logo 图标”。
原因:
- AI 生图直接生成中文品牌字容易出现笔画错误,不适合作为正式字标。
- 当前阶段更适合先确定图形符号方向,再由设计师或前端继续做矢量化、字标搭配和多尺寸适配。
- 图标需要优先服务 App icon、平台左上角品牌、分享卡片和加载页而不是一次性海报图。
生成文件:
```text
public/branding/taonier-logo-v3-concepts/
├─ taonier-logo-v3-contact-sheet.png
├─ taonier-v3-finger-spark.png
├─ taonier-v3-seed-pop.png
├─ taonier-v3-magic-dot.png
├─ taonier-v3-work-gem.png
└─ taonier-v3-soft-t.png
public/branding/taonier-logo-magic-dot-concepts/
├─ taonier-logo-magic-dot-contact-sheet.png
├─ taonier-magic-dot-orbit.png
├─ taonier-magic-dot-seal.png
├─ taonier-magic-dot-squish.png
├─ taonier-magic-dot-mold.png
└─ taonier-magic-dot-bloom.png
public/branding/taonier-logo-flat-concepts/
├─ taonier-logo-flat-contact-sheet.png
├─ taonier-flat-play-clay.png
├─ taonier-flat-spark-clay.png
├─ taonier-flat-meme-smile.png
├─ taonier-flat-loop-mold.png
└─ taonier-flat-seal-blocks.png
public/branding/taonier-logo-concepts/
├─ taonier-logo-contact-sheet.png
├─ taonier-clay-spark.png
├─ taonier-play-mold.png
├─ taonier-meme-bubble.png
├─ taonier-creation-loop.png
└─ taonier-premium-seal.png
```
生成脚本:
```text
scripts/generate-taonier-logo-concepts.mjs
```
## 3. V3-03 一捏成型延展
这一组专门沿 V3 “一捏成型”继续打磨。目标是保留“两个软形触点 + 中央作品核”的成型瞬间,同时降低括号感、碰撞特效感和功能按钮感。
![陶泥儿 Logo 一捏成型延展总览](../../public/branding/taonier-logo-magic-dot-concepts/taonier-logo-magic-dot-contact-sheet.png)
### 3.1 捏合星核
![捏合星核](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-orbit.png)
定位:一捏成型方向的主标首选。
这个方向最稳地保留了“左右合拢、中央成型”的核心动作,中心青绿色星核形成了明确焦点,整体比原 V3-03 更完整,也没有明显播放器、聊天或表情联想。
优点:
- 结构清楚,第一眼能看出“合拢生成”。
- 元素少,小尺寸适配潜力好。
- 中央星核可以做加载、生成成功、发布完成等动效延展。
风险:
- 左右软形仍有一点括号感,后续矢量化可把外轮廓做得更不对称、更像被捏塑的软泥。
建议用途:主 Logo 备选首选、AI 生成按钮、启动动效核心符号。
### 3.2 成型印记
![成型印记](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-seal.png)
定位:完整主标感最强的延展方向。
这个方向把左右触点收成一个更完整的软形图腾,减少了“两个括号”的割裂感。视觉上更像独立品牌符号,但也因此少了一点“捏合动作”的即时感。
建议用途:主 Logo 强备选;若选择它,后续应去掉背景底色并强化中心负形星点。
### 3.3 软泥合拍
![软泥合拍](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-squish.png)
定位:轻松、年轻、动效友好。
这个方向的上下软形更活泼,适合表达“啪嗒一下成型”。但静态 Logo 中的黄色星点和短线略像特效贴纸,主标使用前需要继续简化。
建议用途:生成中动效、运营图、互动反馈,不建议直接定为主 Logo。
### 3.4 灵感模口
![灵感模口](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-mold.png)
定位:最有“模口 / 造物容器”意味。
这个方向图形独特,和“从软泥模口里生成作品”的隐喻贴合。但外形复杂度比 01、02 更高,边缘细节在小尺寸下可能损失。
建议用途:主 Logo 备选探索,适合继续做专业矢量简化。
### 3.5 捏开灵感
![捏开灵感](../../public/branding/taonier-logo-magic-dot-concepts/taonier-magic-dot-bloom.png)
定位:温和、包裹、生成容器。
这个方向亲和、平衡,但整体像眼睛 / 容器 / 开合结构,陶泥儿的“捏”动作弱一些。
建议用途AI 生成入口、等待态、创作容器辅助图形。
## 4. V3 抽象主标候选
V3 根据评审反馈重新避开了五个问题:播放三角、褐色陶土主色、聊天气泡 / 表情包、循环符号,以及过多碎元素。方向转为更抽象、更亮眼、更像长期主 Logo 的符号。
![陶泥儿 Logo V3 概念总览](../../public/branding/taonier-logo-v3-concepts/taonier-logo-v3-contact-sheet.png)
### 4.1 灵感捏痕
![灵感捏痕](../../public/branding/taonier-logo-v3-concepts/taonier-v3-finger-spark.png)
定位:主 Logo 首选。
这个方向用醒目的珊瑚红软形、指纹捏痕和星点负形建立记忆点。它不再依赖“陶泥的褐色”,而是用“被捏过的痕迹”表达陶泥儿的核心动作:用户把脑洞捏成作品。
优点:
- 第一眼足够醒目,远离旧版褐色和播放器感。
- 指纹捏痕有独特性,能承接“人人创作”和“亲手塑形”。
- 元素少,适合继续矢量化和小尺寸适配。
风险:
- 指纹弧线后续需要进一步简化,避免在 24px 以下变糊。
- 星点比例要克制,避免变成普通灵感图标。
建议用途:主 Logo、App icon、平台顶栏、启动页、生成按钮。
### 4.2 脑洞种子
![脑洞种子](../../public/branding/taonier-logo-v3-concepts/taonier-v3-seed-pop.png)
定位:创意生长与新手友好。
这个方向从“灵感发芽”切入,比陶泥更偏创造生命力。它亲和、可爱,但容易让用户联想到教育、植物、儿童启蒙或种植类产品。
建议用途:新手引导、创作孵化、儿童 / 寓教于乐支线,不建议作为主 Logo。
### 4.3 一捏成型
![一捏成型](../../public/branding/taonier-logo-v3-concepts/taonier-v3-magic-dot.png)
定位AI 把灵感合成为作品的瞬间。
这个方向很简洁,用左右两个软形触点和中心星点表达“捏合”。它避开了播放器和聊天气泡,也能做动效,但静态图形目前稍像碰撞特效或括号,需要继续重绘增强独特轮廓。
建议用途生成按钮、AI 施法动效、主 Logo 备选微调方向。
### 4.4 作品胶囊
![作品胶囊](../../public/branding/taonier-logo-v3-concepts/taonier-v3-work-gem.png)
定位:精品内容和作品沉淀。
这个方向更稳、更精品,青绿色也比褐色更吸睛。但整体像水滴、宝石或通用内容图标,和“捏”这个动作的关系弱。
建议用途:精选作品、作品库、创作者中心,不建议优先做主 Logo。
### 4.5 软体 T 形
![软体 T 形](../../public/branding/taonier-logo-v3-concepts/taonier-v3-soft-t.png)
定位:英文辅助名 / Taonier 的抽象首字母。
这个方向试图做更品牌化的抽象符号,但当前形体还不够自然,也未形成足够强的“陶泥儿”心智。若未来英文名确定为 `Taonier` 或类似形式,可以继续沿这个方向做专业字母标重绘。
建议用途:英文标识探索,不作为当前主 Logo 首选。
## 5. V2 扁平矢量候选
第一批图形偏 3D 和拟物,更适合作为吉祥物、运营图或启动页气氛图,不适合作为长期主 Logo。V2 已把约束收紧为扁平、矢量、少元素、强轮廓和小尺寸可识别。
![陶泥儿 Logo 扁平概念总览](../../public/branding/taonier-logo-flat-concepts/taonier-logo-flat-contact-sheet.png)
### 5.1 扁平开捏
![扁平开捏](../../public/branding/taonier-logo-flat-concepts/taonier-flat-play-clay.png)
定位:最直接的主 Logo 候选。
这个方向用一团柔软陶泥承载播放符号,用户一眼能理解“点开玩 / 马上玩”,同时外形保留“捏出来”的不规则软泥感。
优点:
- 识别速度最快,移动端小尺寸也成立。
- 符合主流 App Logo 语言,亲和、不重、不技术冷。
- 和“把脑洞捏成小游戏”的主张绑定最强。
风险:
- 播放符号是常见母题,后续矢量化时要通过不规则软泥外轮廓、颜色和字标形成独特资产。
建议用途:主 Logo 首选、App icon、平台顶栏、分享卡片角标。
### 5.2 灵感泥星
![灵感泥星](../../public/branding/taonier-logo-flat-concepts/taonier-flat-spark-clay.png)
定位AI 创作与灵感生成。
这个方向比“扁平开捏”更品牌化中心负形星点表达灵感、AI 生成和创意爆发。它没有播放符号那么直白,但更容易和“陶泥儿”的创作平台气质绑定。
优点:
- 图形更简洁,品牌记忆点强。
- 陶泥心智、AI 灵感和精品感比较平衡。
- 适合未来扩成字标、启动页和生成态动效。
风险:
- 对“小游戏/马上玩”的表达弱于播放符号。
建议用途:主 Logo 强备选、创作首页、AI 生成按钮和品牌主视觉。
### 5.3 造梗笑泥
![造梗笑泥](../../public/branding/taonier-logo-flat-concepts/taonier-flat-meme-smile.png)
定位:社交传播和玩梗亲和力。
这个方向的气泡与笑脸非常亲和,适合表达“分享快乐”和“造梗”。但它和聊天、社区类产品的通用图形过近,作为主 Logo 可能会让用户误判产品品类。
建议用途:社区、评论、分享、活动贴纸,不建议做主 Logo。
### 5.4 共创泥环
![共创泥环](../../public/branding/taonier-logo-flat-concepts/taonier-flat-loop-mold.png)
定位AI 与用户共创闭环。
这个方向表达共创与循环,但生成结果带有偏柔和彩虹渐变的视觉倾向,与“陶泥儿”的软泥名称关联不够直观,也不如 01/02 容易记住。
建议用途:创作流程、共创能力、生成进度辅助图形。
### 5.5 精品泥印
![精品泥印](../../public/branding/taonier-logo-flat-concepts/taonier-flat-seal-blocks.png)
定位:精品作品和内容集合。
这个方向像内容平台或作品库入口,能表达图片、用户、游戏等多形态内容。但图形元素较多,主标识别不如 01/02 凝练。
建议用途:精选作品、作品集、创作者中心、内容品质标识。
## 6. V1 立体探索
### 6.1 灵感陶团
![灵感陶团](../../public/branding/taonier-logo-concepts/taonier-clay-spark.png)
定位AI 共创与灵感造物。
这个方向把“陶泥”作为主视觉,内部用发光火花和节点表达 AI 赋能。它最贴“陶泥儿”名字本身,也能说明平台不是普通小游戏集合,而是从灵感生成作品的创作容器。
优点:
- 与“陶泥儿”的名称绑定最强。
- 有 AI、创作、造物的综合含义。
- 适合启动页、品牌介绍、创作首页空状态。
风险:
- 小尺寸下细节偏多,需要后续矢量化时压缩节点和纹理。
- 如果色彩处理不当,会回到手工陶艺联想。
建议用途:品牌主视觉备选、官网/启动页、创作入口图形。
### 6.2 开玩模具
![开玩模具](../../public/branding/taonier-logo-concepts/taonier-play-mold.png)
定位:把脑洞捏成小游戏。
这个方向用软陶捏出播放符号,最直接地连接“创作”和“马上玩”。它比单纯陶泥团更有产品动作,也更适合轻休闲、小游戏、短内容传播。
优点:
- 识别强,小尺寸也清楚。
- 与轻度休闲小游戏的关系最直接。
- 适合作为 App icon 和主 Logo 图形。
风险:
- 播放符号相对常见,需要后续在外轮廓、捏痕和色彩上做独特性。
- 如果三角形过硬,会削弱“陶泥儿”的柔软感。
建议用途:主 Logo 首选、App icon、分享卡片角标、加载态图形。
### 6.3 造梗气泡
![造梗气泡](../../public/branding/taonier-logo-concepts/taonier-meme-bubble.png)
定位:社交传播、玩梗、裂变。
这个方向把陶泥变形成聊天气泡和表情,强调“梗”和“传播”。它最有社交平台感,也适合表情包、活动贴纸和运营视觉。
优点:
- 传播感强,年轻、轻松、容易做 IP 化。
- 能承接社区、评论、分享和玩梗场景。
- 比较容易延展成贴纸和表情包。
风险:
- 偏软萌,可能削弱“精品 AI 创作平台”的质感。
- 作为主 Logo 容易显得像聊天或表情产品。
建议用途社区模块、活动运营、IP 辅助形象,不建议作为唯一主 Logo。
### 6.4 共创回路
![共创回路](../../public/branding/taonier-logo-concepts/taonier-creation-loop.png)
定位AI 与用户共同迭代生成。
这个方向用软陶带形成循环和造物轨迹,表达“灵感 -> AI 塑形 -> 用户修改 -> 作品传播”的闭环。它比其他方向更抽象,也更有平台级和工具级气质。
优点:
- 高级、简洁,避免儿童化。
- 适合表达 AI 共创、迭代和作品循环。
- 可用于创作者工作台或生成进度标识。
风险:
- 与“陶泥儿”名称的直观关联较弱。
- 缺少小游戏和玩梗的即时识别。
建议用途创作流程标识、AI 共创能力图标、品牌辅助图形。
### 6.5 精品泥印
![精品泥印](../../public/branding/taonier-logo-concepts/taonier-premium-seal.png)
定位:精品内容、作品认证、创作者成果。
这个方向像一个被压印的软陶徽章,中间有方块和火花,比较适合表达“作品被打磨成型”。它的内容平台感强于游戏入口感。
优点:
- 精品感和作品库气质较强。
- 适合作品认证、精选、创作者徽章。
- 与“陶泥压印”隐喻相对自然。
风险:
- 细节较多,主 Logo 小尺寸可读性不如“开玩模具”。
- 徽章感偏静态,轻休闲的即时性稍弱。
建议用途:精选作品标识、创作者荣誉、内容品质标签。
## 7. 推荐结论
优先级建议:
```text
主 Logo 首选V3 01 灵感捏痕
一捏成型首选V3-03 延展 01 捏合星核
完整主标备选V3-03 延展 02 成型印记
英文标识探索V3 05 软体 T 形
精品内容辅助V3 04 作品胶囊
新手 / 寓教于乐辅助V3 02 脑洞种子
```
若要兼顾主流、亲和、醒目和“陶泥儿”的动作隐喻,优先继续打磨 V3 “灵感捏痕”。
若想把 Logo 做得更抽象、更像 AI 生成瞬间,可以继续打磨 V3-03 延展中的“捏合星核”或“成型印记”。
V1 的 3D 图标不建议直接作为主 Logo只适合做运营图、吉祥物探索或风格参考V2 的播放、气泡、碎元素方向本轮已降级为历史探索。
## 8. 后续落地建议
1. 先围绕 V3 “灵感捏痕”做 3 到 5 个专业矢量微调版:减少指纹线条、强化软形轮廓、测试深色 / 浅色底。
2. 同步对 V3-03 “捏合星核”做一版更独特的轮廓重绘,弱化括号感,保留中央成型星核。
3. 字标不要直接使用生图结果,应单独设计“陶泥儿”中文字标,并准备英文辅助名。
4. 正式应用前做商标近似检索,重点覆盖第 9、35、38、41、42 类。
5. 若确认替换“百梦”再更新现有命名规范文档、前端品牌组件、HTML metadata、后台和后端默认文案。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

View File

@@ -1,5 +0,0 @@
生成一张适合商业路演 PPT 使用的横版高清主视觉配图,主题是“陶泥:将 Harness Engineering 理论、专家知识、多 Agent 调度融入 AI 创作工具与 AI 原生游戏框架”。
画面构图:深色但清爽的现代科技工作室/游戏创作中枢,中心是一个温润陶泥质感的抽象核心装置,核心装置连接两条清晰的知识管线。左侧表现 AI 创作工具:多 Agent 协作节点、策划 SOP、美术 SOP、模板框架、剧本/数值/系统/角色/场景/CG 等垂类任务以图标化模块呈现。右侧表现 AI 原生游戏框架:实时剧情生成、数值与剧情对齐、画面与剧情对齐、实时任务与物品生成,以游戏世界投影、角色剪影、场景画面和规则约束网格呈现。
底部远景加入克制的学术评审氛围:讲台、投影、评审席、优秀课程设计的荣誉感,但不要出现真实学校校徽、真实教授肖像或任何可识别真实人物。
视觉风格:高端产品发布会 Key Visual精致 3D 插画结合轻量界面光效,专业、可信、面向 AI 游戏与创作者工具,色彩使用陶土暖色、青绿色、冷白光和少量金色点缀,信息结构清楚,主体居中偏左,右上和左上保留干净留白用于 PPT 叠加标题。
要求:无文字、无字母、无水印、无 UI 按钮、无品牌 logo、无真实校徽、无真实人物肖像、避免杂乱、避免过暗、避免卡通幼稚、避免纯抽象背景。

View File

@@ -29,7 +29,7 @@
结论:
- 独立编辑器入口如果没有继续接入主流程,应及时物理删除,不要长期保留兼容壳
- 页签命名要贴近陶泥儿主语言,而不是内部实现命名
- 页签命名要贴近百梦主语言,而不是内部实现命名
### 2.2 NPC 视觉模块并入 NPC 编辑
@@ -144,7 +144,7 @@
经验:
- 陶泥儿主并不关心 “function” 这个技术词,更关心“这个选项会发生什么”
- 百梦主并不关心 “function” 这个技术词,更关心“这个选项会发生什么”
- 同类编辑器如果只给字段表单而没有模板起稿能力,复用效率会很低
### 2.8 选项行为预览升级到实机回放
@@ -217,7 +217,7 @@
- 预览面板要么都显示“实时状态”
- 要么都显示“同一个阶段的快照”
- 混用实时值和预测值会让陶泥儿主误判
- 混用实时值和预测值会让百梦主误判
## 4. 这类项目里沉淀下来的方法论
@@ -245,7 +245,7 @@
- 不是所有字段都应该在所有行为类型下开放
- 如果某类行为最终不会直接读取某个字段,就应该禁用或弱化它
- 否则陶泥儿主会错误地以为改动无效是 bug
- 否则百梦主会错误地以为改动无效是 bug
### 4.4 模板比空白表单更重要

View File

@@ -142,15 +142,6 @@
4. 说明
5. 标签
## 6.3 草稿页作品卡对齐分类列表
- 草稿 Tab 的作品架要优先对齐发现页分类列表的横向卡片:左侧承载标题/状态/类型/摘要,右侧显示带透明度的方形封面图。
- 草稿卡不能为了视觉对齐丢掉原有信息:删除、分享、已发布统计、拼图积分激励、未读红点都要保留;其中删除和分享属于低频动作,常态不显示按钮,向左划动列表项后露出操作。
- 卡片右侧不再常驻“继续创作”“查看详情”“查看进度”等动作按钮,打开作品由整张卡片承担。
- 移动端保持单列列表;网页端使用多列卡片式网格,避免在宽屏上把作品卡拉成一整行长条。
- 生成中的状态使用整卡蒙版、旋转等待符号和“生成中...”标识;蒙版只能作为状态层,不能替换或移除卡片本身的信息。
- 草稿卡复用分类页基础类名时,要用 `.creation-work-card.platform-category-game-item` 覆盖分类页移动端三列规则;否则正文会被当作封面列压缩,中文标题会断成一两个字一行。
- 右侧封面不要只依赖 `img` fallback容器层也要有玩法参考图 CSS 背景兜底,私有资源换签失败或图片 onerror 时仍能看到封面视觉。
## 7. 样式与动画经验
### 7.1 轮播动画要连续,不要离散

View File

@@ -25,7 +25,7 @@
3. 历史已发布作品必须能自动补齐 gallery 投影。
- 公开列表读取 `list_custom_world_gallery_entries` 前,会扫描 `custom_world_profile` 中已发布且未删除的 profile。
- 若已发布 profile 缺少 `custom_world_gallery_entry`,或缺少公开作品码 / 作者陶泥号,会先补齐公开字段并同步 gallery 投影。
- 若已发布 profile 缺少 `custom_world_gallery_entry`,或缺少公开作品码 / 作者百梦号,会先补齐公开字段并同步 gallery 投影。
- 这样旧版本发布成功但未落入广场读模型的作品,在下一次首页 / 分类页读取公开列表时会自动出现。
## 经验

View File

@@ -394,7 +394,7 @@ MVP 阶段不需要单独设置密码。
落地规则:
- 入参只允许 `phone``password`,不支持邮箱、用户名或陶泥号。
- 入参只允许 `phone``password`,不支持邮箱、用户名或百梦号。
- 手机号不存在时,不创建账号,返回统一的登录失败。
- 手机号存在但账号未设置过密码时,不允许密码登录。
- 首次设置密码只能在已登录账号中心内完成;用户必须先通过手机号验证码或已绑定手机号的微信账号进入已登录态。
@@ -734,7 +734,7 @@ MVP 阶段建议至少提供一个轻量账号中心,包含:
约束:
- 不支持邮箱、用户名或陶泥号。
- 不支持邮箱、用户名或百梦号。
- 不承担注册能力。
- 只有已存在、已验证手机号、且 `passwordLoginEnabled=true` 的账号可以登录。

View File

@@ -55,7 +55,7 @@
- 调用 `POST /admin/api/profile/redeem-codes` 创建/更新兑换码。
- 调用 `POST /admin/api/profile/redeem-codes/disable` 停用兑换码。
- 支持 `public``unique``private` 三种模式。
- 私有码支持输入内部 `userId` 和公开陶泥号,提交给后端统一解析。
- 私有码支持输入内部 `userId` 和公开百梦号,提交给后端统一解析。
7. 邀请码管理页:
- 调用 `POST /admin/api/profile/invite-codes` 创建/更新注册邀请码。
- 支持输入 JSON 对象 metadata提交前做基础 JSON 对象校验,最终校验以服务端为准。
@@ -114,7 +114,7 @@ API 调试页是受控接口调试台,不是通用代理工具:
4. maxUses必须为正整数最终校验以服务端为准。
5. enabled创建/更新时可切换。
6. allowedUserIds私有码允许的内部用户 ID 列表。
7. allowedPublicUserCodes私有码允许的公开陶泥号列表。
7. allowedPublicUserCodes私有码允许的公开百梦号列表。
提交成功后展示后端返回的兑换码记录;失败时展示后端错误消息。

View File

@@ -12,7 +12,7 @@
## 1. 一句话定义
`2048` 是一个主题化数字合成玩法模板:陶泥儿主通过 Agent 设定棋盘主题、合成链、视觉皮肤、目标格和难度参数,系统生成可试玩、可发布的 2048 作品;玩家通过滑动方向移动棋盘格,相同等级方块合并升级,直到达成目标格或棋盘无可行动作。
`2048` 是一个主题化数字合成玩法模板:百梦主通过 Agent 设定棋盘主题、合成链、视觉皮肤、目标格和难度参数,系统生成可试玩、可发布的 2048 作品;玩家通过滑动方向移动棋盘格,相同等级方块合并升级,直到达成目标格或棋盘无可行动作。
---
@@ -108,7 +108,7 @@ Agent 型创作至少收集下面 5 个锚点:
Agent 行为要求:
1. 优先接住陶泥儿主的一句话灵感,不把创作变成问卷。
1. 优先接住百梦主的一句话灵感,不把创作变成问卷。
2. 每轮最多追问 1 个最影响成品质量的问题。
3. 当主题和合成链已经足够明确时,优先生成草稿。
4. 合成链必须围绕同一主题递进,不允许出现互不相关的方块名。
@@ -860,4 +860,4 @@ npm run check:encoding
## 20. 一句话结论
`2048` 在 Genarrative 中应被做成一个可创作、可换皮、可发布、可排行的主题合成棋盘模板:创作端让陶泥儿主定义合成链和视觉承诺,运行端保持经典 2048 的滑动合并手感,服务端负责正式棋盘裁决、作品状态和成绩真相。
`2048` 在 Genarrative 中应被做成一个可创作、可换皮、可发布、可排行的主题合成棋盘模板:创作端让百梦主定义合成链和视觉承诺,运行端保持经典 2048 的滑动合并手感,服务端负责正式棋盘裁决、作品状态和成绩真相。

View File

@@ -31,7 +31,7 @@
大鱼吃小鱼玩法是一个 `Agent-First` 的轻量实时成长玩法创作链:
**陶泥儿主先与 Agent 共创“进化母题、等级阶梯、生态风格与场地气质”,系统再自动编译出一个竖屏全屏、摇杆移动、吞噬收编、三合一进化、持续刷怪、升到最高级即通关的可运行玩法作品。**
**百梦主先与 Agent 共创“进化母题、等级阶梯、生态风格与场地气质”,系统再自动编译出一个竖屏全屏、摇杆移动、吞噬收编、三合一进化、持续刷怪、升到最高级即通关的可运行玩法作品。**
---
@@ -115,26 +115,26 @@
`Agent-First 大鱼吃小鱼玩法创作工具`
玩法运行态对外展示名可由陶泥儿主自定义,不强绑平台内部域名。
玩法运行态对外展示名可由百梦主自定义,不强绑平台内部域名。
## 5.2 目标用户
目标用户主要是 3 类:
1.陶泥儿
1.百梦
- 想快速做一个可玩的成长吞噬小游戏,但不懂完整关卡编辑器
2. 视觉驱动型陶泥儿
2. 视觉驱动型百梦
- 更关心“每级长什么样、动作怎么样、背景氛围如何”
3. 玩法原型陶泥儿
3. 玩法原型百梦
- 想快速验证一套吞噬成长节奏、等级曲线和场地压迫感
## 5.3 成功标准
本期上线后,至少要满足下面这些结果:
1. 陶泥儿主可在 `5~12` 分钟内通过 Agent 聊天形成一版可用锚点草稿。
1. 百梦主可在 `5~12` 分钟内通过 Agent 聊天形成一版可用锚点草稿。
2. 系统默认能编译出 `8` 级实体阶梯的初版玩法草稿。
3. 每一级实体都能在结果页单独生成和重生成主图。
4. 每一级实体都能在结果页单独生成和重生成动作。
@@ -179,9 +179,9 @@
Agent 在这一玩法里不负责实时玩法裁决,它只负责 3 件事:
1.陶泥儿主明确高杠杆锚点
2.陶泥儿主把模糊灵感总结成可编译结构
3.陶泥儿主收束出第一版等级阶梯与视觉方向
1.百梦主明确高杠杆锚点
2.百梦主把模糊灵感总结成可编译结构
3.百梦主收束出第一版等级阶梯与视觉方向
## 7.2 前台交互原则
@@ -222,7 +222,7 @@ Agent 在这一玩法里不负责实时玩法裁决,它只负责 3 件事:
3. `成长阶梯`
- 这一玩法一共大致有几级,以及每一级如何逐步升级、变大、变强、变异
- 最高级终局形态也并入这一锚点统一确定
-陶泥儿主没有明确总层数,本期默认按 `8` 级编译,可配置范围固定为 `6~12`
-百梦主没有明确总层数,本期默认按 `8` 级编译,可配置范围固定为 `6~12`
4. `风险节奏`
- 玩家周围应该更偏压迫、平衡还是偏爽快
@@ -235,7 +235,7 @@ Agent 在这一玩法里不负责实时玩法裁决,它只负责 3 件事:
2. `等级总层数` 并入 `成长阶梯`
3. `升级轮廓` 并入 `成长阶梯`
4. `终局形态` 并入 `成长阶梯`
5. `开局成长方式` 改为系统固定规则,不再作为陶泥儿主锚点
5. `开局成长方式` 改为系统固定规则,不再作为百梦主锚点
后续 Agent 追问时,不再把这些内容拆成独立必答题。
@@ -302,7 +302,7 @@ Agent 在这一玩法里不负责实时玩法裁决,它只负责 3 件事:
## 9.1 默认草稿规模
陶泥儿主没有特别指定时,第一版玩法草稿必须默认编译为:
百梦主没有特别指定时,第一版玩法草稿必须默认编译为:
1. `8` 级实体阶梯
2. `1` 张活动区域背景图

View File

@@ -680,7 +680,7 @@ assistant 回复应包含:
1. 对 seedText / 用户消息的简要复述
2. 当前仍缺哪些世界锚点
3. 建议陶泥儿主下一步回答什么
3. 建议百梦主下一步回答什么
#### 用户后续消息

View File

@@ -24,7 +24,7 @@
那么第二阶段的目标就是:
**让 Agent 会话真正开始理解陶泥儿主输入,并把自然语言聊天沉淀成结构化创作锚点。**
**让 Agent 会话真正开始理解百梦主输入,并把自然语言聊天沉淀成结构化创作锚点。**
一句话定义:

View File

@@ -26,7 +26,7 @@
那么第四阶段的目标就是:
**让陶泥儿主直接修改这版草稿设定,并且继续用 AI 为这版草稿扩出新的角色和场景。**
**让百梦主直接修改这版草稿设定,并且继续用 AI 为这版草稿扩出新的角色和场景。**
一句话定义:
@@ -100,7 +100,7 @@
一句话目标:
**让第四阶段结束时,陶泥儿主第一次能像在真正做作品一样修改草稿、继续长出新对象。**
**让第四阶段结束时,百梦主第一次能像在真正做作品一样修改草稿、继续长出新对象。**
---

View File

@@ -200,7 +200,7 @@
1. 主线关键角色
2. 可扮演角色
3. 陶泥儿主重点想看的角色
3. 百梦主重点想看的角色
## 7.2 入口位置

View File

@@ -42,21 +42,21 @@
## 1.2 一句话定义
陶泥儿主通过与一个懂 RPG 剧情策划方法的 Agent 对话,逐步完成世界锚点收集、关键对象塑造、剧情骨架搭建和长尾内容展开;同时由 Express 后端持续维护结构化世界状态、锁定边界、局部重生成和质量检查。
百梦主通过与一个懂 RPG 剧情策划方法的 Agent 对话,逐步完成世界锚点收集、关键对象塑造、剧情骨架搭建和长尾内容展开;同时由 Express 后端持续维护结构化世界状态、锁定边界、局部重生成和质量检查。
## 1.3 目标用户
目标用户分三类:
1.陶泥儿
1.百梦
- 有世界灵感,但不擅长结构化填表
2. 中度陶泥儿
2. 中度百梦
- 愿意精修角色、地点、主线第一幕,但不想维护大量底层字段
3. 重度陶泥儿
3. 重度百梦
- 需要局部重生成、锁定、版本化和导出世界圣经
## 1.4 产品成功标准
@@ -76,7 +76,7 @@
1. 不把整套系统做成纯聊天黑箱。
2. 不让前端继续承担锁定合并、重生成裁决、结构编译等核心逻辑。
3. 不要求陶泥儿主直接编辑 `ThemePack / WorldStoryGraph / VisibilitySlice / ThreadContract` 等运行时结构。
3. 不要求百梦主直接编辑 `ThemePack / WorldStoryGraph / VisibilitySlice / ThreadContract` 等运行时结构。
4. 不把长项目世界管理完全交给一条无限增长的聊天记录。
5. 不再保留“生成完直接回世界列表并自动保存”的旧流程。
6. 不允许角色主图、角色动作、场景背景图继续停留在临时候选状态后直接发布世界。
@@ -151,7 +151,7 @@
1. `src/services/customWorldCreatorIntent.ts`
- 已有陶泥儿主意图、锚点包、锁定状态的基础结构
- 已有百梦主意图、锚点包、锁定状态的基础结构
2. `src/types/customWorld.ts`
@@ -228,7 +228,7 @@
后台必须持续维护:
1. 陶泥儿主意图
1. 百梦主意图
2. 锁定状态
3. 世界底稿快照
4. 可编辑草稿对象列表
@@ -271,11 +271,11 @@
-> 打开 Agent 创作入口
-> Agent 收集最小锚点
-> Agent 输出首轮世界底稿
-> 陶泥儿主锁定/修改关键内容
-> 百梦主锁定/修改关键内容
-> Agent 局部生成关键角色/地点/主线第一幕
-> 进入角色与场景资产工坊,生成主形象 / 动作 / 背景图
-> Agent 扩展长尾内容
-> 陶泥儿主发布世界
-> 百梦主发布世界
-> 保存到世界库并进入世界
```
@@ -2077,4 +2077,4 @@ Agent 会话每次 operation 完成后自动保存 session snapshot。
这次新创作工具的正确方向,不是把现有工作台换成一个更大的聊天框,而是:
**让 Agent 成为陶泥儿主的主交互入口,让 Express 后端成为真正的世界状态管理者,让锁定、局部重生成、摘要、质量护栏和发布链把整个创作过程牢牢收住。**
**让 Agent 成为百梦主的主交互入口,让 Express 后端成为真正的世界状态管理者,让锁定、局部重生成、摘要、质量护栏和发布链把整个创作过程牢牢收住。**

View File

@@ -37,15 +37,15 @@
## 1.3 目标用户
目标用户仍然是当前自定义世界创作工具的三类陶泥儿主,但本流程更偏向解决其中两类人的起步问题:
目标用户仍然是当前自定义世界创作工具的三类百梦主,但本流程更偏向解决其中两类人的起步问题:
1.陶泥儿
1.百梦
- 有模糊灵感,但不知道先想什么
2. 中度陶泥儿
2. 中度百梦
- 有一些设定点子,但缺少把设定收束成可运行剧情骨架的方法
重度陶泥儿主也可使用本流程,但他们更关心的是:
重度百梦主也可使用本流程,但他们更关心的是:
- Agent 是否会少问废话
- 摘要是否准确
@@ -1190,7 +1190,7 @@ Agent 不应回复成八问表:
## 13.2 后续可编辑范围
进入世界底稿阶段后,陶泥儿主默认优先精修:
进入世界底稿阶段后,百梦主默认优先精修:
1. 关键角色
2. 核心冲突与线程

View File

@@ -1,4 +1,4 @@
# AI 原生自定义世界生成流程优化 PRD
# AI 原生自定义世界生成流程优化 PRD
更新时间:`2026-04-06`
@@ -8,11 +8,11 @@
目标不是推翻当前已经存在的多阶段生成链,而是解决下面这个核心错位:
**当前仓库已经开始把世界生成拆成 `framework -> themePack -> storyGraph -> role outline -> dossier -> narrativeProfile` 的分阶段 AI 编译流程,但陶泥儿主入口仍然是“一段大文本”,结果页又把大量低杠杆字段重新扔回给陶泥儿主人工兜底。**
**当前仓库已经开始把世界生成拆成 `framework -> themePack -> storyGraph -> role outline -> dossier -> narrativeProfile` 的分阶段 AI 编译流程,但百梦主入口仍然是“一段大文本”,结果页又把大量低杠杆字段重新扔回给百梦主人工兜底。**
一句话定义本次优化:
**让陶泥儿主先定义世界灵魂锚点,再让 AI / 系统围绕锚点分层生成、分层展开、分层可控地完成长尾内容。**
**让百梦主先定义世界灵魂锚点,再让 AI / 系统围绕锚点分层生成、分层展开、分层可控地完成长尾内容。**
## 1. 当前流程现状
@@ -64,7 +64,7 @@
## 1.3 当前流程的核心问题
## 1.3.1 陶泥儿主入口过于粗糙
## 1.3.1 百梦主入口过于粗糙
当前创建入口只有一块大文本输入框。
@@ -72,23 +72,23 @@
1. 不会写长描述的用户很难开局。
2. 愿意精细创作的用户没有结构化落点。
3. 系统无法明确分辨“哪些是陶泥儿主真正想锁定的锚点,哪些只是随口补充的描述”。
3. 系统无法明确分辨“哪些是百梦主真正想锁定的锚点,哪些只是随口补充的描述”。
结果就是:
**输入端自由但信息信号不稳定AI 虽然能生成很多内容,却不一定生成的是陶泥儿主真正关心的内容。**
**输入端自由但信息信号不稳定AI 虽然能生成很多内容,却不一定生成的是百梦主真正关心的内容。**
## 1.3.2 陶泥儿主与 AI 的职责发生倒置
## 1.3.2 百梦主与 AI 的职责发生倒置
当前流程实际上是:
- 陶泥儿主先写一段泛化设定
- 百梦主先写一段泛化设定
- AI 再把整个世界铺满
- 陶泥儿主最后回到结果页,人工修改大量角色、章节、技能、初始物品、场景连接等细节
- 百梦主最后回到结果页,人工修改大量角色、章节、技能、初始物品、场景连接等细节
这与“低创作门槛、高创作自由度”的目标相反。
因为真正应该由陶泥儿主控制的,是:
因为真正应该由百梦主控制的,是:
- 世界核心命题
- 主题与气质
@@ -98,7 +98,7 @@
- 关键地点
- 标志性物件 / 怪物 / 禁忌
而不是让陶泥儿主在结果页里逐个补:
而不是让百梦主在结果页里逐个补:
- `backstoryReveal.chapters`
- `skills`
@@ -117,13 +117,13 @@
问题不在数量本身,而在于系统并没有明确区分:
1. 哪些是陶泥儿主应重点塑造的关键对象
1. 哪些是百梦主应重点塑造的关键对象
2. 哪些只是 AI 应自动展开的长尾铺量
这会导致两个问题:
1. AI 在早期就花大量成本生成长尾内容,等待时间长。
2. 陶泥儿主在结果页里面对的是一整套“全部都生成了”的世界,而不是“先抓关键锚点,再决定是否继续铺开”。
2. 百梦主在结果页里面对的是一整套“全部都生成了”的世界,而不是“先抓关键锚点,再决定是否继续铺开”。
## 1.3.4 当前结果页暴露了过多低杠杆字段
@@ -134,7 +134,7 @@
- 场景 NPC 分配
- 场景连接网络
这对“专业陶泥儿主”当然有帮助,但对目标用户来说,容易把工具变成:
这对“专业百梦主”当然有帮助,但对目标用户来说,容易把工具变成:
**看起来自由度很高,实际上需要承担很多系统编辑工作。**
@@ -144,11 +144,11 @@
这意味着:
1. 陶泥儿主一旦修改过内容,就会担心被覆盖。
1. 百梦主一旦修改过内容,就会担心被覆盖。
2. 没有“锁定关键内容,只重生成长尾部分”的机制。
3. AI 无法真正成为创作搭档,只像一次性大批量生成器。
## 1.3.6 当前生成阶段是“模型视角”,不是“陶泥儿主视角”
## 1.3.6 当前生成阶段是“模型视角”,不是“百梦主视角”
当前生成页展示的是系统批次和阶段进度,这很好,但它主要回答的是:
@@ -156,7 +156,7 @@
没有回答的是:
- 陶泥儿主最关心的关键角色是否已经成型
- 百梦主最关心的关键角色是否已经成型
- 世界冲突是否已经稳定
- 当前这轮已经锁定了哪些核心创意
- 接下来生成的是关键锚点,还是长尾内容
@@ -170,19 +170,19 @@
这次优化要同时满足 6 个目标:
1. 降低输入门槛
- 不要求陶泥儿主一上来写长文,不要求理解系统字段。
- 不要求百梦主一上来写长文,不要求理解系统字段。
2. 提高高杠杆创作自由度
-陶泥儿主直接控制世界灵魂锚点,而不是低价值细节。
-百梦主直接控制世界灵魂锚点,而不是低价值细节。
3. 明确陶泥儿主与 AI 的职责边界
- 陶泥儿主负责“决定什么值得创作”AI 负责“把它展开并跑起来”。
3. 明确百梦主与 AI 的职责边界
- 百梦主负责“决定什么值得创作”AI 负责“把它展开并跑起来”。
4. 保留现有分阶段生成骨架
- 不推翻 `framework -> themePack -> storyGraph -> role/landmark` 的已有结构。
5. 引入锁定与局部重生成
-陶泥儿主能保住自己在乎的内容,只重做其余部分。
-百梦主能保住自己在乎的内容,只重做其余部分。
6. 把结果页从“数据总表”升级成“创作工作台”
- 让编辑界面按创作价值组织,而不是按底层对象堆字段。
@@ -192,11 +192,11 @@
优化后的自定义世界流程应该改为:
```text
陶泥儿主输入世界锚点
-> AI 编译陶泥儿主意图摘要
-> 陶泥儿主确认 / 锁定关键锚点
百梦主输入世界锚点
-> AI 编译百梦主意图摘要
-> 百梦主确认 / 锁定关键锚点
-> AI 先生成关键角色与关键地点
-> 陶泥儿主可局部修改 / 局部重生成
-> 百梦主可局部修改 / 局部重生成
-> AI 再展开长尾 NPC、长尾场景与运行时编译结构
-> 结果页以“锚点 / 关键对象 / 扩展内容 / 运行时摘要”方式组织
-> 保存并进入世界
@@ -204,7 +204,7 @@
一句话:
**先做创作决策,再做内容展开;先做关键对象,再做长尾铺量;先让陶泥儿主锁定灵魂,再让 AI 扩散世界。**
**先做创作决策,再做内容展开;先做关键对象,再做长尾铺量;先让百梦主锁定灵魂,再让 AI 扩散世界。**
## 4. 输入层优化方案
@@ -251,7 +251,7 @@
2. 卡片模式
- 用户直接按结构化方式输入世界锚点
两种模式最终都编译成统一的陶泥儿主意图对象。
两种模式最终都编译成统一的百梦主意图对象。
## 4.3 必填与选填要分开
@@ -272,7 +272,7 @@
- 标志性要素
- 禁止事项
这样既能保证世界最小成型,又不会把陶泥儿主门槛抬高。
这样既能保证世界最小成型,又不会把百梦主门槛抬高。
## 4.3.1 抽象统一“聊天补充设定”能力
@@ -307,11 +307,11 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
1. AI 不得在重生成时覆盖该内容
2. 长尾内容只能围绕它展开
3. 结果页里应明确显示其为“陶泥儿主锚点”
3. 结果页里应明确显示其为“百梦主锚点”
## 5. 生成链路优化方案
## 5.1 新增“陶泥儿主意图编译层”
## 5.1 新增“百梦主意图编译层”
在真正开始世界生成前,先新增一个轻量阶段:
@@ -324,19 +324,19 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
输出:
- 陶泥儿主意图摘要
- 百梦主意图摘要
- 世界锚点摘要
- 系统识别出的关键角色 / 冲突 / 地点 / 禁忌
这一步的作用不是生成世界,而是先回答:
1. 系统理解到的世界核心是什么
2. 哪些内容将被视为陶泥儿主强锚点
2. 哪些内容将被视为百梦主强锚点
3. 哪些内容将交给 AI 扩展
## 5.2 把当前生成链改成“关键先行、长尾后补”
当前 `generateCustomWorldProfile(...)` 的分阶段结构可以保留,但生成顺序需要更陶泥儿主化。
当前 `generateCustomWorldProfile(...)` 的分阶段结构可以保留,但生成顺序需要更百梦主化。
建议改成 5 层:
@@ -347,9 +347,9 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
- 世界框架
- ThemePack
- StoryGraph 的基础版
- 陶泥儿主锚点摘要
- 百梦主锚点摘要
这一层完成后,系统应能让陶泥儿主看到:
这一层完成后,系统应能让百梦主看到:
- 世界现在到底被理解成了什么
- 哪些冲突 / 势力 / 意象被识别出来了
@@ -362,11 +362,11 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
- 关键场景角色
- 关键地点
这一层优先围绕陶泥儿主明确输入的角色和地点,而不是先铺满全部数量。
这一层优先围绕百梦主明确输入的角色和地点,而不是先铺满全部数量。
### 第三层:陶泥儿主校对层
### 第三层:百梦主校对层
在继续展开长尾内容前,应允许陶泥儿主做一次轻量校对:
在继续展开长尾内容前,应允许百梦主做一次轻量校对:
- 确认关键角色是否对
- 确认关键地点是否对
@@ -408,7 +408,7 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
这样做的价值很高:
1. 降低首次等待焦虑
2.陶泥儿主更早介入关键对象校正
2.百梦主更早介入关键对象校正
3. 避免系统在创作方向还没稳定前,先铺满大量长尾内容
## 5.4 角色与场景生成要改成“锚点优先 + 长尾补位”
@@ -417,11 +417,11 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
优化后应改为:
1. 先生成陶泥儿主明确指定的关键角色 / 地点
1. 先生成百梦主明确指定的关键角色 / 地点
2. 再根据世界冲突自动补位缺失的角色原型和场景功能位
3. 最后再铺长尾
这样生成出来的世界会更像“围绕陶泥儿主意图长出来”,而不是“先生成了一个完整世界,再让陶泥儿主去认领”
这样生成出来的世界会更像“围绕百梦主意图长出来”,而不是“先生成了一个完整世界,再让百梦主去认领”
## 6. 结果页与编辑工作台优化方案
@@ -439,7 +439,7 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
优化后建议改成 4 层工作台:
1. 创作锚点
- 展示陶泥儿主输入和锁定内容
- 展示百梦主输入和锁定内容
2. 关键对象
- 关键角色、关键地点、关键冲突对象
@@ -448,11 +448,11 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
- AI 自动展开的长尾角色、长尾地点、补位内容
4. 世界编译摘要
- 展示世界线程、题材包、运行时摘要,但默认不要求陶泥儿主编辑
- 展示世界线程、题材包、运行时摘要,但默认不要求百梦主编辑
## 6.2 编辑界面应遵守“高价值字段前置,低价值字段折叠”
陶泥儿主默认暴露的应是:
百梦主默认暴露的应是:
- 角色一句话定位
- 角色表面面貌
@@ -507,7 +507,7 @@ RPG 创作工作台、拼图创作工作台、大鱼吃小鱼创作工作台都
## 7.1 新增 `CustomWorldCreatorIntent`
建议新增陶泥儿主输入的统一结构:
建议新增百梦主输入的统一结构:
```ts
interface CustomWorldCreatorIntent {
@@ -529,7 +529,7 @@ interface CustomWorldCreatorIntent {
作用:
- 把“陶泥儿主真正输入了什么”从最终 `CustomWorldProfile` 中分离出来
- 把“百梦主真正输入了什么”从最终 `CustomWorldProfile` 中分离出来
## 7.2 新增 `CustomWorldAnchorPack`
@@ -583,7 +583,7 @@ interface CustomWorldGenerationDraft {
作用:
- 让“陶泥儿主输入、AI 编译、结果编辑”成为连续工作流,而不是只有最终成品对象
- 让“百梦主输入、AI 编译、结果编辑”成为连续工作流,而不是只有最终成品对象
## 8. 与当前仓库的接入建议
@@ -597,7 +597,7 @@ interface CustomWorldGenerationDraft {
目标:
- 把单 textarea 升级为“快速模式 + 卡片模式”
- 新增陶泥儿主意图状态
- 新增百梦主意图状态
- 新增锁定和局部重生成入口
## 8.2 prompt 与生成服务层
@@ -623,7 +623,7 @@ interface CustomWorldGenerationDraft {
目标:
-`CustomWorldProfile` 增加陶泥儿主意图与锚点相关扩展字段
-`CustomWorldProfile` 增加百梦主意图与锚点相关扩展字段
- 保持旧档兼容
- 让现有 builder 能同时消费 `creatorIntent + anchorPack + profile seed`
@@ -647,28 +647,28 @@ interface CustomWorldGenerationDraft {
本次优化不做以下事情:
1. 不推翻当前自定义世界最终输出仍是 `CustomWorldProfile` 的兼容目标
2. 不把所有运行时结构都暴露给陶泥儿主直接编辑
3. 不要求陶泥儿主理解 `themePack / storyGraph / knowledgeFacts / threadContracts` 等系统结构
4. 不把复杂数值平衡、掉落预算、build 预算转移给陶泥儿
2. 不把所有运行时结构都暴露给百梦主直接编辑
3. 不要求百梦主理解 `themePack / storyGraph / knowledgeFacts / threadContracts` 等系统结构
4. 不把复杂数值平衡、掉落预算、build 预算转移给百梦
5. 不把“高自由度”理解成“所有字段都手工可改”
## 10. 验收标准
做到以下几点,才算这次优化真正成立:
1. 陶泥儿主可以不用写长文,只靠卡片输入也能完成自定义世界创建。
2. 系统会明确区分“陶泥儿主锚点”和“AI 自动展开内容”。
3. 陶泥儿主不再需要默认手改大量 `skills / initialItems / backstoryReveal / scene connections` 才能得到可用世界。
1. 百梦主可以不用写长文,只靠卡片输入也能完成自定义世界创建。
2. 系统会明确区分“百梦主锚点”和“AI 自动展开内容”。
3. 百梦主不再需要默认手改大量 `skills / initialItems / backstoryReveal / scene connections` 才能得到可用世界。
4. 结果页支持锁定关键角色、关键地点、关键冲突,并支持局部重生成。
5. 重新生成不再默认覆盖整个世界。
6. 当前 `framework -> themePack -> storyGraph -> role/landmark` 生成主链可以继续复用,而不是被废弃。
7. 结果页默认展示的是高创作价值对象,而不是系统级低层字段。
8. 长尾内容生成明显后置于关键对象生成,陶泥儿主能更早看到并修正关键对象。
8. 长尾内容生成明显后置于关键对象生成,百梦主能更早看到并修正关键对象。
9. 旧的自由文本输入模式仍然可用,但不再是唯一入口。
## 11. 推荐落地顺序
## 阶段 A先加陶泥儿主意图层
## 阶段 A先加百梦主意图层
先做:
@@ -678,7 +678,7 @@ interface CustomWorldGenerationDraft {
目标:
- 先把陶泥儿主输入从“单一大文本”升级成“可识别的创作锚点”
- 先把百梦主输入从“单一大文本”升级成“可识别的创作锚点”
## 阶段 B再加锚点包与锁定能力
@@ -721,4 +721,4 @@ interface CustomWorldGenerationDraft {
当前自定义世界流程最需要优化的,不是“让 AI 再多生成一点内容”,而是:
**把陶泥儿主从低价值字段编辑里解放出来,让陶泥儿主负责世界灵魂锚点,让 AI 负责围绕这些锚点分层生成、分层展开、分层可控地把世界长出来。**
**把百梦主从低价值字段编辑里解放出来,让百梦主负责世界灵魂锚点,让 AI 负责围绕这些锚点分层生成、分层展开、分层可控地把世界长出来。**

View File

@@ -16,7 +16,7 @@
## 1. 一句话定义
陶泥儿主在创作页通过表单确认题材主题和难度选项,系统根据难度选项派生需要消除次数与难度数值,并编译出一个可试玩、可发布的单局抓大鹅玩法作品;玩家在 `10` 分钟倒计时内点击圆形空间中可见物品,把物品放入下方 `7` 格备选栏,每凑齐 `3` 个同物品 id 自动消除,最终清空圆形空间内全部物品即胜利。
百梦主在创作页通过表单确认题材主题和难度选项,系统根据难度选项派生需要消除次数与难度数值,并编译出一个可试玩、可发布的单局抓大鹅玩法作品;玩家在 `10` 分钟倒计时内点击圆形空间中可见物品,把物品放入下方 `7` 格备选栏,每凑齐 `3` 个同物品 id 自动消除,最终清空圆形空间内全部物品即胜利。
---
@@ -99,20 +99,19 @@ Match3D 必须形成独立玩法域,后续技术方案至少需要覆盖:
- 2D 素材风格
- 难度选项
4. `需要消除次数` 与难度 `1~10` 数值不再作为独立输入框展示,由难度选项派生。
5. 生成抓大鹅草稿固定消耗 `10` 点,生成按钮必须显式展示。
6. 结果页背景音乐重新生成固定消耗 `5` 泥点UI 背景重新生成固定消耗 `2` 泥点;批量新增物品素材按实际可新增物品名每 `5` 个消耗 `2` 泥点,不足 `5` 个向上取整
7. 结果页支持编辑游戏名称、标签、封面图等基础发布信息
8. 发布前支持试玩,并允许随时停止和修改配置
9. 发布不要求试玩通关
10. 单局运行态使用 `10` 分钟倒计时
11. 下方备选栏固定为 `7` 个格子
12. 玩家点击可见物品后,物品飞入备选栏。
13. 备选栏中每凑齐 `3` 个相同物品 id 自动消除
14. 清空圆形空间中全部物品即胜利
15. 倒计时结束或备选栏满即失败
16. 胜利 / 失败后展示结算界面
17. 入口页的 2D 素材风格选择会进入素材图提示词,并作为后续物品素材新增和重绘的默认提示词依据
18. 点击、入槽、消除、失败、胜利的即时反馈效果由前端先行呈现,后端负责权威确认、状态落库和成绩可信性。
5. 生成抓大鹅草稿消耗 `20` 点,生成按钮必须显式展示。
6. 结果页支持编辑游戏名称、标签、封面图等基础发布信息
7. 发布前支持试玩,并允许随时停止和修改配置
8. 发布不要求试玩通关
9. 单局运行态使用 `10` 分钟倒计时
10. 下方备选栏固定为 `7` 个格子
11. 玩家点击可见物品后,物品飞入备选栏
12. 备选栏中每凑齐 `3` 个相同物品 id 自动消除
13. 清空圆形空间中全部物品即胜利
14. 倒计时结束或备选栏满即失败
15. 胜利 / 失败后展示结算界面
16. 入口页的 2D 素材风格选择会进入素材图提示词,并作为后续物品素材新增和重绘的默认提示词依据
17. 点击、入槽、消除、失败、胜利的即时反馈效果由前端先行呈现,后端负责权威确认、状态落库和成绩可信性
---
@@ -192,19 +191,17 @@ Match3D 首版参考拼图后期的入口表单收集方式,而不是早期的
扁平图标 / 赛璐璐卡通 / 像素复古 / 手绘水彩 / 贴纸描边 / 厚涂图标 / 自定义
```
每个内置选项使用 VectorEngine `gpt-image-2-all` 生成的画风参考图展示;参考图保存在 `public/match3d-style-references/`,只作为入口选择的视觉提示,不作为用户上传参考图。每张参考图只展示 `1` 个完整独立物品,不能展示 `5` 个物品样张或多物品散点图,避免用户误判为物品数量配置。选择内置风格时,前端提交 `assetStyleId``assetStyleLabel` 与对应 `assetStylePrompt`。选择 `自定义` 时必须弹出独立面板,用户填写描述后才允许应用;自定义描述作为 `assetStylePrompt` 进入后端生成链路。
`像素复古``assetStylePrompt` 必须是强约束而不是泛化描述:真正复古像素 2D 游戏道具 sprite先按约 `64x64` 低分辨率像素块绘制再整数倍放大,硬边方块像素清晰可见,有限色板 `12-24` 色,并禁止抗锯齿、柔焦、平滑渐变、真实 3D 渲染、PBR 材质和摄影光照。后端收到 `assetStyleId = pixel-retro` 时必须兜底补齐这组约束。
每个内置选项使用 VectorEngine `gpt-image-2-all` 生成的画风参考图展示;参考图保存在 `public/match3d-style-references/`,只作为入口选择的视觉提示,不作为用户上传参考图。选择内置风格时,前端提交 `assetStyleId``assetStyleLabel` 与对应 `assetStylePrompt`。选择 `自定义` 时必须弹出独立面板,用户填写描述后才允许应用;自定义描述作为 `assetStylePrompt` 进入后端生成链路。
## 6.3 参考图片
抓大鹅入口页不展示参考图片上传。题材表现由题材文本和草稿切割图片链路承接;草稿生成阶段会生成多视角 2D 物品素材并写入作品 profile。结果页 `素材配置 > 物品` 继续承接物品素材预览、删除批量新增;点击音效配置当前临时隐藏
抓大鹅入口页不展示参考图片上传。题材表现由题材文本和草稿切割图片链路承接;草稿生成阶段会生成多视角 2D 物品素材并写入作品 profile。结果页 `素材配置 > 物品` 继续承接物品素材预览、删除批量新增音效配置。
## 6.4 生成音效入口
## 6.4 生成音效开关
抓大鹅入口页不展示 `生成音效` Toggle草稿生成阶段只保存 `generatedItemAssets[].soundPrompt`,不调用 Vidu 生成点击音效,也不产生点击音效相关扣费
抓大鹅入口页在生成按钮前提供 `生成音效` Toggle,默认关闭。关闭时,草稿生成只保存 `generatedItemAssets[].soundPrompt`,不调用 Vidu 生成点击音效。
结果页当前不保留单个物品音效的手动补生成入口。历史 `generatedItemAssets[].clickSound` 字段继续兼容传递给运行态;后续恢复音效能力时再复用通用创作音频接口和资产落点
用户打开 Toggle 后,前端在创建会话和执行 `match3d_compile_draft` 时提交 `generateClickSound=true`。后端完成物品名称与 `soundPrompt` 生成后,在图片素材生成阶段为每个生成物品调用 Vidu 生成点击音效,并把结果写入对应 `generatedItemAssets[].clickSound`。音效生成复用通用创作音频接口和资产落点;结果页仍保留单个物品音效的手动补生成入口
---
@@ -231,16 +228,10 @@ Match3D 首版参考拼图后期的入口表单收集方式,而不是早期的
## 7.3 素材生成边界
抓大鹅草稿生成链路会根据难度生成题材物品素材文本模型生成物品名VectorEngine 分批生成 `1:1` 素材图并切割为每个物品 `5` 张不同视角图片,再转存 OSS。实际生成数量必须向上补齐为 `5` 的倍数,并生成补齐物品的名称和对应图片;例如标准难度玩法使用 `9` 种物品,但素材实际生成 `10` 种。入口页选择的 `assetStylePrompt` 必须写入素材图提示词;结果页批量新增物品时继续以该风格作为默认提示词起点。
批量新增物品素材与草稿生成使用同一素材图处理流程:先按用户实际新增名称补齐到 `5` 的倍数,整图生成完成后丢弃补齐用临时物品,只对用户实际新增项继续绿幕抠背景、切割和 OSS 上传,并只把这些真实新增物品写入 `generatedItemAssets`;补齐用临时物品不进入作品资产列表、不参与发布校验和运行态映射。计费数量按清洗、去重、排除已有物品并截断到容量上限后的实际新增数量计算。
素材图提示词必须固定要求 `5*5` 严格均匀排布,每格主体完整居中,不得跨格、贴边或越界,避免切割成独立图片后出现相邻物品内容污染。
抓大鹅草稿生成链路会根据难度生成题材物品素材文本模型生成物品名VectorEngine 分批生成 `1:1` 素材图并切割为每个物品 `5` 张不同视角图片,再转存 OSS。入口页选择的 `assetStylePrompt` 必须写入素材图提示词;结果页批量新增物品时继续以该风格作为默认提示词起点。
生成出的独立图片必须作为结果页 `素材配置 > 物品` 的预览资产返回。图片素材生成成功时 `generatedItemAssets[].status = image_ready`,并携带 `imageViews[]`,兼容字段 `imageSrc` / `imageObjectKey` 指向首张视角图;正式平台资产绑定和更完整的二次编辑流程以后续技术方案为准。
局内 UI 生成分为两类图片:`9:16` 纯背景图和 `1:1` 中心容器 UI 图。纯背景图只表现题材氛围和环境不得生成锅、圆盘、托盘、拼图槽、物品槽、HUD、文字、按钮、倒计时、分数或物品中心容器 UI 图单独生成,贴合题材设定,用于覆盖运行态默认圆形竞技容器。容器图必须通过 VectorEngine `/v1/images/edits` multipart 图生图生成,并参考 `public/match3d-background-references/pot-fused-reference.png` 的大尺寸轻俯视构图:容器外轮廓接近画布四边,宽度约占画布 `86%-92%`、高度约占 `82%-90%`,内口为横向椭圆,不能生成小圆盘、正俯视扁盘、侧视碗或小托盘。底部备选栏、顶部控件和拼图/物品槽位继续使用运行态默认 UI不烘进生成背景容器图成功加载后运行态默认圆形锅壳不得再覆盖或裁切生成容器。
## 7.4 发布前试玩
发布前需要支持试玩当前关卡。
@@ -276,8 +267,8 @@ Match3D 首版参考拼图后期的入口表单收集方式,而不是早期的
运行时主交互空间是一个有边界的圆形空间。
1. 圆形空间使用俯视角。
2. 背景环境资源只作为纯背景层,不承接圆形空间边界
3. 圆形空间边界由运行态默认容器或生成出的中心容器 UI 图承接,不能烘进纯背景图
2. 背景环境资源后续可以尝试伪 3D 视角效果
3. 圆形空间边界是中间交互图案的边界
4. 物品不能超出圆形边界,也不能被边界压住或裁切。
5. 运行态快照中的 `x / y / radius` 使用前端可直接渲染的 `0~1` 归一化坐标;圆心固定为 `(0.5, 0.5)`,圆形可用半径为 `0.5`
6. 后端生成和前端兜底渲染都必须满足 `distance((x, y), (0.5, 0.5)) + radius <= 0.5 - safeMargin``safeMargin` 至少覆盖圆形边框和视觉阴影,避免可消除图案贴边裁切。
@@ -689,11 +680,12 @@ GET /api/runtime/match3d/runs/:runId
## 14.2 入口表单
入口表单只展示个输入块:
入口表单只展示个输入块:
1. `想做一个什么题材的抓大鹅?` 大文本输入框。
2. `2D素材风格` 横向滑动风格卡,最后一个为 `自定义`
3. `难度` 选项按钮。
4. `生成音效` Toggle默认关闭。
入口页不展示参考图、`需要消除次数` 数值输入、`难度数值` 滑杆,也不展示 `题材 / 物品 / 难度` 三个摘要框。`需要消除次数``difficulty` 由难度选项派生后提交给后端。
@@ -703,8 +695,6 @@ GET /api/runtime/match3d/runs/:runId
结果页保持清爽,复用平台已有作品结果页风格。
结果页 `难度配置` 中的四档难度使用横向离散拖动条呈现,拖动条只允许停在 `轻松 / 标准 / 进阶 / 硬核` 四个刻度上,刻度标签可点击切换,仍按同一映射派生 `需要消除次数``difficulty``物品种类`
点击按钮弹出独立面板时,不实现成在当前面板下面展开内容。
## 14.4 运行态
@@ -728,7 +718,7 @@ GET /api/runtime/match3d/runs/:runId
3. 入口页不展示参考图上传。
4. 内置风格显示画风参考图,自定义风格通过独立面板填写并进入提交 payload。
5. 移动端入口页所有内容一屏展示,不产生纵向滚动。
6. 入口页不展示 `生成音效` Toggle草稿生成不产生 `clickSound`,结果页物品详情当前也不展示点击音效生成入口
6. `生成音效` 关闭时草稿生成不产生 `clickSound`;打开时首批生成物品随图片素材生成并持久化点击音效
7. 系统可生成待发布结果页,并在草稿中返回首批多视角 2D 切割图片素材预览。
8. 用户可编辑游戏名称、标签、封面图等基础信息。
9. 用户可发布前试玩,且试玩失败不阻断发布。

View File

@@ -13,7 +13,7 @@
-> 选择“拼图玩法”
-> Agent 聊天收束高杠杆锚点
-> 生成拼图结果页
-> 陶泥儿主生成并确认拼图图片
-> 百梦主生成并确认拼图图片
-> 发布到拼图广场
-> 玩家从广场进入第 1 关
-> 全屏拼图运行时
@@ -26,7 +26,7 @@
## 1. 一句话定义
陶泥儿主通过 Agent 对话确定拼图作品的高杠杆视觉锚点再由系统生成结果页、AI 生成拼图图片并发布到广场;玩家进入游戏后,在全屏拼图画布中通过交换、合并、拖动和拆分完成关卡,并沿着“相似题材优先、同作者次优先”的关卡链持续游玩。
百梦主通过 Agent 对话确定拼图作品的高杠杆视觉锚点再由系统生成结果页、AI 生成拼图图片并发布到广场;玩家进入游戏后,在全屏拼图画布中通过交换、合并、拖动和拆分完成关卡,并沿着“相似题材优先、同作者次优先”的关卡链持续游玩。
---
@@ -78,7 +78,7 @@
- 拼图关卡名
- AI 生成拼图图片的功能
- 图片题材标签
4. 陶泥儿主发布后的拼图作品必须进入平台广场。
4. 百梦主发布后的拼图作品必须进入平台广场。
5. 玩家从广场进入某个作品时,第 1 关必须先显示当前作品本身。
6. 第 2 关及以后必须按照“标签相似度权重 `70%` + 同作者权重 `30%`”选择下一关。
7. 游戏运行时必须全屏展示拼图画布。
@@ -129,7 +129,7 @@
创建拼图作品
-> Agent 聊天收束 5 个视觉锚点
-> 生成结果页
-> 陶泥儿主确认关卡名、标签、图片
-> 百梦主确认关卡名、标签、图片
-> 发布到拼图广场
```
@@ -137,12 +137,12 @@
### 5.1.1 已发布作品二次编辑
陶泥儿主在“我的创作”中点击自己已发布的拼图作品时,不进入只读详情页,而是回到该作品绑定的拼图结果页继续编辑。独立的“体验”按钮仍然直接进入第 1 关,不与编辑入口混用。
百梦主在“我的创作”中点击自己已发布的拼图作品时,不进入只读详情页,而是回到该作品绑定的拼图结果页继续编辑。独立的“体验”按钮仍然直接进入第 1 关,不与编辑入口混用。
落地规则:
1. 已发布拼图作品必须优先通过 `sourceSessionId` 恢复原 Agent session。
2. 恢复后的结果页沿用原草稿、当前正式图、标题、摘要和标签;陶泥儿主可以继续改标题、摘要、标签,并重新生成图片。
2. 恢复后的结果页沿用原草稿、当前正式图、标题、摘要和标签;百梦主可以继续改标题、摘要、标签,并重新生成图片。
3. 再次点击发布时不得创建新作品,必须覆盖同一个 `profileId / workId`
4. 覆盖发布只更新作品内容、更新时间、发布时间与广场投影;不得清零 `playCount`,不得改变作品归属。
5. 如果历史作品缺少 `sourceSessionId`,前端只能退回作品详情,不伪造编辑 session。
@@ -210,9 +210,9 @@
拼图 Agent 必须做到:
1. 优先接住陶泥儿主的画面灵感,而不是立刻列问卷。
1. 优先接住百梦主的画面灵感,而不是立刻列问卷。
2. 每轮只追问当前最影响图片生成质量的 `1` 个问题。
3.陶泥儿主已经说出足够信息时,优先总结,不重复追问。
3.百梦主已经说出足够信息时,优先总结,不重复追问。
4. 当会话至少完成 `2` 轮后,工作区必须提供 `补充剩余关键字` 快捷动作。
- 该动作沿用 RPG 聊天链路,仍走发送消息接口,但请求体必须携带 `quickFillRequested: true`
- 前端不补数据、不伪造锚点状态,只发送“请补充剩余关键字。”作为本轮用户消息。
@@ -255,7 +255,7 @@ interface PuzzleAnchorPack {
## 7.1 结果页定位
拼图结果页是陶泥儿主从 Agent 共创转入正式发布前的最小工作台。
拼图结果页是百梦主从 Agent 共创转入正式发布前的最小工作台。
它至少承担 5 件事:
@@ -303,7 +303,7 @@ interface PuzzleAnchorPack {
关卡名生成规则建议如下:
1. 默认由 Agent 根据锚点自动生成 `1` 个正式候选名。
2. 陶泥儿主可直接手改。
2. 百梦主可直接手改。
3. 关卡名长度建议控制在 `4~12` 个中文字符。
4. 不允许空标题发布。
@@ -357,7 +357,6 @@ interface PuzzleAnchorPack {
4. 历史素材入口与添加参考图并列放在输入框右下角,打开独立素材选择面板,不在当前面板下方展开。
5. UI 不默认写玩法规则说明,只展示必要状态、预览和操作。
6. 移动端中输入框右下角按钮必须可点且不遮挡正文输入;输入框需要预留底部内边距。
7. 本地上传的非正方形拼图图片进入平台通用正方形图片裁剪弹窗;该弹窗的拖拽裁剪框、八向边界手柄、九宫格辅助线、遮罩和触控行为同时服务拼图图片上传与头像上传,后续不得在头像或拼图侧各自维护一套裁剪交互。
后端落地契约:
@@ -679,7 +678,7 @@ V1 规则如下:
1. 点击道具必须弹出独立确认窗口。
2. 确认窗口期间暂停游戏时间。
3. 正式后端运行态每次确认消耗 `1` 点。
3. 正式后端运行态每次确认消耗 `1` 点。
4. 本地调试 run 不伪造钱包扣费,只保持确认、暂停和表现一致。
---
@@ -1161,7 +1160,7 @@ interface PuzzleRunSnapshot {
完成标准:
1. 陶泥儿主能从平台进入拼图 Agent 工作区
1. 百梦主能从平台进入拼图 Agent 工作区
2. 能通过聊天生成结果页草稿
## 阶段 B再做结果页与图片资产
@@ -1175,7 +1174,7 @@ interface PuzzleRunSnapshot {
完成标准:
1. 陶泥儿主能生成正式拼图图片并发布
1. 百梦主能生成正式拼图图片并发布
2. 作品能进入拼图广场
## 阶段 C再做拼图运行时核心循环
@@ -1233,4 +1232,4 @@ interface PuzzleRunSnapshot {
这次平台新增拼图玩法,正确的做法不是只补一个拼图画布,而是:
**把拼图作为平台内独立玩法类型接进现有 Agent-first 创作中心、结果页、发布链、广场分发链和运行时链,让陶泥儿主先收束高杠杆视觉锚点,让玩家在全屏交换-合并-拆分的拼图循环中持续游玩。**
**把拼图作为平台内独立玩法类型接进现有 Agent-first 创作中心、结果页、发布链、广场分发链和运行时链,让百梦主先收束高杠杆视觉锚点,让玩家在全屏交换-合并-拆分的拼图循环中持续游玩。**

View File

@@ -630,7 +630,7 @@ SSE 事件:
1. 增加背景音乐和环境音,但不改变四帧三段主链。
2. 为移动端生成 `9:16` 竖版裁切版本。
3. 支持陶泥儿主手动上传某张关键帧,再生成相邻视频。
3. 支持百梦主手动上传某张关键帧,再生成相邻视频。
4. 支持发布后版本化替换开场动画。
5. 支持用第四幕直接生成开局场景动态背景。
6. 支持把开场动画拆出的关键帧回流为作品详情页轮播素材。

View File

@@ -22,7 +22,7 @@
接成一条新的稳定流程:
**每个场景由陶泥儿主在工具中配置为 `2~5` 幕;每一幕都绑定独立背景图和相遇 NPC 顺序;每一幕的第一个 NPC 视为主角色;运行时按幕切换背景和可遇对象,并根据主角色当前好感度裁决聊天轮数与第 5 轮收束方式。**
**每个场景由百梦主在工具中配置为 `2~5` 幕;每一幕都绑定独立背景图和相遇 NPC 顺序;每一幕的第一个 NPC 视为主角色;运行时按幕切换背景和可遇对象,并根据主角色当前好感度裁决聊天轮数与第 5 轮收束方式。**
本次还追加一条必须和草稿生成阶段一起落地的约束:
@@ -31,13 +31,13 @@
补充口径修正:
1. `scene_chapter` 在本期继续保留为数据层 / 编译层 / 运行时层概念。
2. `scene_chapter` 不作为陶泥儿主可见的独立 Tab、独立卡片或独立导航入口。
3. 陶泥儿主配置多幕的唯一入口,是现有“场景”列表里的场景编辑弹层。
2. `scene_chapter` 不作为百梦主可见的独立 Tab、独立卡片或独立导航入口。
3. 百梦主配置多幕的唯一入口,是现有“场景”列表里的场景编辑弹层。
4. 每一幕的 NPC 配置区必须直接叠在当前幕背景预览上,以“对面角色站位”的方式呈现;三个站位既是预览,也是编辑入口。
5. 幕编辑站位中每个角色只显示角色形象与名称,不展示额外信息块、规则说明或说明性标签。
6. 幕内小预览的构图固定为左侧玩家、右侧当前幕角色;右侧三个站位采用一前两后。
前排主角色的 y 轴必须与玩家角色对齐后排两个角色必须同一列、x 轴对齐,上下分布,且后排整体的 y 轴中点与前排主角色保持一致。
7. 新建幕默认仅预置 1 个主角色槽位内容,其余槽位留空,等待陶泥儿主补充。
7. 新建幕默认仅预置 1 个主角色槽位内容,其余槽位留空,等待百梦主补充。
8. 角色名称显示在角色形象上方,角色渲染不附带方形 UI 底板。
9. 世界档案的场景详情页不再单独展示“场景图片”和“场景内 NPC”字段相关兼容数据统一由多幕配置自动同步回场景对象。
@@ -55,7 +55,7 @@
本次迭代必须同时满足以下目标:
1. 陶泥儿主可以在现有创作页面中为每个场景章节配置多幕内容。
1. 百梦主可以在现有创作页面中为每个场景章节配置多幕内容。
2. 每一幕都必须绑定一张正式背景图。
3. 每一幕都可以配置玩家会遇到哪些 NPC并且保留顺序。
4. 每一幕配置的第一个 NPC 必须被系统认定为该幕主角色。
@@ -89,7 +89,7 @@
1. 不新建独立的“场景编辑器”页面。
2. 不把幕推进逻辑放到前端本地计算。
3. 不让陶泥儿主直接编辑底层运行时 `ChapterState` 或聊天状态对象。
3. 不让百梦主直接编辑底层运行时 `ChapterState` 或聊天状态对象。
4. 不做多 NPC 并行聊天。
5. 不做每一幕的复杂分支树可视化编辑器。
6. 不把“规则说明文案”默认堆到创作页或游戏 UI 面板里。
@@ -122,7 +122,7 @@
1. 场景章节没有“幕”这一层结构化对象。
2. 背景图是场景级资产,不是幕级资产。
3. NPC 与场景的关系主要还是地点级归属,不是幕级相遇编排。
4. 陶泥儿主无法在创作页里明确控制“这一幕谁先出场、谁是主角色”。
4. 百梦主无法在创作页里明确控制“这一幕谁先出场、谁是主角色”。
## 4.2 游戏运行侧现状
@@ -185,7 +185,7 @@
这意味着:
1. 陶泥儿主在工具里编辑的是“第几幕”。
1. 百梦主在工具里编辑的是“第几幕”。
2. 运行时仍然只认现有章节阶段枚举。
3. `chapterDirector` 可以继续复用,只是数据来源从“纯 quest 推导”升级成“quest + 幕蓝图联合推导”。
@@ -214,7 +214,7 @@
- `name`
- `description`
- `imageSrc`
- `sceneNpcIds`(仅作为兼容字段,由多幕配置自动派生,不再作为陶泥儿主可编辑字段)
- `sceneNpcIds`(仅作为兼容字段,由多幕配置自动派生,不再作为百梦主可编辑字段)
- `connections`
- `sceneChapterBlueprints` 对应的多幕配置
2. 场景配置面板中,开局场景必须复用普通场景同级的配置 UI而不是继续保留一套缩水版表单。
@@ -251,7 +251,7 @@
原因:
1. 当前创作工作区已经进入“先收关键锚点、再逐步扩写”的阶段。
2. 一次铺太多 playable、场景和长尾对象会稀释陶泥儿主对第一版底稿的掌控感。
2. 一次铺太多 playable、场景和长尾对象会稀释百梦主对第一版底稿的掌控感。
3. 本期还要把幕级背景图和角色主形象自动挂回草稿,如果对象规模不收束,等待时间和生成成本都会直接失控。
### 5.5.2 幕级出演角色与背景必须由剧情引擎判定
@@ -309,7 +309,7 @@
- 角色主形象是否就绪
- 场景幕背景是否就绪
这样陶泥儿主一进入草稿精修工作区,就能直接看到:
这样百梦主一进入草稿精修工作区,就能直接看到:
1. 角色已经带主形象
2. 每个场景章节的每一幕已经带背景图
@@ -369,7 +369,7 @@ interface CustomWorldFoundationDraftSceneChapter {
1. `primaryNpcId` 必须等于 `encounterNpcIds[0]`,不允许单独填写成别的角色。
2. 每幕必须至少有 `1` 个 NPC。
3. 每幕必须有 `backgroundImageSrc``backgroundAssetId`
4. `advanceRule` 由系统按幕位置默认编译,第一版不要求陶泥儿主手改。
4. `advanceRule` 由系统按幕位置默认编译,第一版不要求百梦主手改。
## 6.2 发布到运行时的蓝图结构
@@ -416,7 +416,7 @@ sceneChapterBlueprints?: SceneChapterBlueprint[] | null;
原因:
1. 现有 `landmarks` 只足够表达地点,不足够表达幕顺序。
2. 现有 `ChapterState` 是运行时状态,不适合直接兼做陶泥儿主蓝图。
2. 现有 `ChapterState` 是运行时状态,不适合直接兼做百梦主蓝图。
3. 独立蓝图层更适合后端编译和发布校验。
## 6.3 聊天状态扩展
@@ -483,9 +483,9 @@ type NpcChatTurnResult = {
新增规则:
1. 陶泥儿主从现有“场景”列表点击任一场景卡,进入对应场景编辑弹层。
1. 百梦主从现有“场景”列表点击任一场景卡,进入对应场景编辑弹层。
2. 多幕配置必须作为场景编辑弹层内的一个区块出现,归属于该场景。
3. `scene_chapter` 仅作为保存层和运行时蓝图存在,不单独暴露在陶泥儿主导航里。
3. `scene_chapter` 仅作为保存层和运行时蓝图存在,不单独暴露在百梦主导航里。
4. 场景卡片可增加“幕数量”轻量摘要,但第一版不是阻塞项。
## 7.2 场景编辑弹层展示要求
@@ -498,8 +498,8 @@ type NpcChatTurnResult = {
补充约束:
1. “场景图片”不再作为场景详情页里的独立字段展示,陶泥儿主只能通过每一幕的“配置背景”入口管理视觉。
2. “场景内 NPC”不再作为场景详情页里的独立字段展示陶泥儿主只能通过每一幕角色槽位配置相遇 NPC。
1. “场景图片”不再作为场景详情页里的独立字段展示,百梦主只能通过每一幕的“配置背景”入口管理视觉。
2. “场景内 NPC”不再作为场景详情页里的独立字段展示百梦主只能通过每一幕角色槽位配置相遇 NPC。
3. 为兼容现有运行时与旧数据结构,场景对象上的 `imageSrc / sceneNpcIds` 仍然保留,但必须由多幕配置自动回填,前台不再暴露单独编辑控件,且不能再用 `sceneNpcIds` 限制每幕可选角色。
多幕区块至少展示:
@@ -566,11 +566,11 @@ NPC 配置面板必须支持:
3. 不允许把不存在于当前世界角色池中的 id 写入幕配置。
4. 若主角色未与当前场景或线程建立任何关联,给出发布警告。
5. 存储时继续落到 `encounterNpcIds` 有序数组,槽位从左到右按顺序压缩写入。
6. `sceneNpcIds` 不再作为陶泥儿主字段,也不再作为幕角色选择范围;保存时只从所有幕的 `encounterNpcIds` 自动派生兼容值。
6. `sceneNpcIds` 不再作为百梦主字段,也不再作为幕角色选择范围;保存时只从所有幕的 `encounterNpcIds` 自动派生兼容值。
## 7.6 幕预览
陶泥儿主在场景编辑弹层里点击“幕预览”后,必须直接进入当前幕的运行时预览。
百梦主在场景编辑弹层里点击“幕预览”后,必须直接进入当前幕的运行时预览。
要求如下:
@@ -633,7 +633,7 @@ interface SceneActRuntimeState {
## 8.3 幕推进规则
第一版不要求陶泥儿主手填推进条件,而是由系统按幕位置默认编译:
第一版不要求百梦主手填推进条件,而是由系统按幕位置默认编译:
1.`1` 幕默认 `after_primary_contact`
- 玩家与主角色发生首次有效接触后可进入下一幕判定
@@ -871,7 +871,7 @@ Adventure 主面板在本次迭代中至少增加下面这些表现:
当下面这些结果都成立时,视为本次 PRD 已被正确落地:
1. 陶泥儿主可以在现有场景编辑弹层中配置每个场景的多幕。
1. 百梦主可以在现有场景编辑弹层中配置每个场景的多幕。
2. 每个场景章节都可以配置 `2~5` 幕。
3. 每一幕都可以绑定独立背景图。
4. 每一幕都可以配置有序 NPC 列表,第一位自动成为主角色。

View File

@@ -14,7 +14,7 @@
## 1. 一句话定义
“方洞挑战”是一个反直觉形状分拣玩法:陶泥儿主通过 Agent 设定形状主题、洞口规则、误导节奏和反差演出,系统生成一个移动端优先的单局挑战;玩家在限时内把连续出现的形状投入正确洞口,后端根据当前关卡的真实兼容规则裁决成功、失败和连击。
“方洞挑战”是一个反直觉形状分拣玩法:百梦主通过 Agent 设定形状主题、洞口规则、误导节奏和反差演出,系统生成一个移动端优先的单局挑战;玩家在限时内把连续出现的形状投入正确洞口,后端根据当前关卡的真实兼容规则裁决成功、失败和连击。
---
@@ -130,7 +130,7 @@ Agent 需要把玩家一句灵感收束为上述锚点,不允许逐项盘问
落地约束:
1. `replyText` 是直接展示给陶泥儿主的中文回复,不得出现 JSON、字段名、内部结构等说明。
1. `replyText` 是直接展示给百梦主的中文回复,不得出现 JSON、字段名、内部结构等说明。
2. `nextConfig` 必须是完整配置,不允许只输出 patch缺失字段只能由后端用当前会话配置兜底。
3. `shapeCount` 由后端限制在 `6``24``difficulty` 限制在 `1``10`
4. `quickFillRequested=true` 时,模型应直接补齐剩余配置,后端把 `progressPercent` 固定为 `100`

View File

@@ -14,7 +14,7 @@
## 1. 一句话定义
`survivor` 是一个 AI 原生幸存者类游戏模板:陶泥儿主通过 Agent 设定主角幻想、敌潮母题、武器技能、成长流派和战场节奏,系统编译出一个移动端优先的俯视角割草生存作品;玩家通过移动躲避敌潮,武器自动攻击,拾取经验升级,在若干分钟内完成生存挑战、击败首领或倒下结算。
`survivor` 是一个 AI 原生幸存者类游戏模板:百梦主通过 Agent 设定主角幻想、敌潮母题、武器技能、成长流派和战场节奏,系统编译出一个移动端优先的俯视角割草生存作品;玩家通过移动躲避敌潮,武器自动攻击,拾取经验升级,在若干分钟内完成生存挑战、击败首领或倒下结算。
---
@@ -90,7 +90,7 @@
3. 不做复杂地形寻路、真实物理碰撞和高精度弹幕编辑器。
4. 不做多地图章节战役,只做单局挑战。
5. 不做局外装备养成、抽卡、永久技能树或付费强化。
6. 不要求陶泥儿主逐帧编辑怪物 AI、弹道曲线或数值公式。
6. 不要求百梦主逐帧编辑怪物 AI、弹道曲线或数值公式。
7. 不把玩法规则说明长文默认写进 UI 面板。
8. 不把按钮弹出的资产、升级或参数编辑做成当前卡片下方展开内容,统一使用独立面板。
9. 不让前端本地结算直接写入正式成绩、钱包、任务或排行榜。
@@ -161,7 +161,7 @@ Agent 必须围绕用户灵感收束这些锚点,不允许把创作入口做
落地约束:
1. `replyText` 是直接展示给陶泥儿主的中文回复,不得出现 JSON、字段名或内部协议说明。
1. `replyText` 是直接展示给百梦主的中文回复,不得出现 JSON、字段名或内部协议说明。
2. `progressPercent` 只能由后端校验后采纳,范围 `0~100`
3. `nextDraftPatch` 只允许写入幸存者草稿字段,不允许修改平台账号、钱包或作品归属。
4. 模型不可用或结果无法解析时,接口返回明确错误,不用固定模板伪装 AI 回复。

View File

@@ -4,7 +4,7 @@
## 0. 文档目的
这份 PRD 用于设计 `Genarrative / 陶泥儿` 内的 AI 文字游戏模板,暂定工程 ID 为 `text-game`,展示名可用“幕间”或“幕间文字”。它参考 MOKU / 幕间类 AI 互动平台的剧本游乐场、低门槛创作、自由行动、AI 记忆和模拟器强反馈经验,但不迁入任何外部平台工程、账号体系、社区、支付、榜单、论坛或私有存档。
这份 PRD 用于设计 `Genarrative / 百梦` 内的 AI 文字游戏模板,暂定工程 ID 为 `text-game`,展示名可用“幕间”或“幕间文字”。它参考 MOKU / 幕间类 AI 互动平台的剧本游乐场、低门槛创作、自由行动、AI 记忆和模拟器强反馈经验,但不迁入任何外部平台工程、账号体系、社区、支付、榜单、论坛或私有存档。
外部参考只用于提炼产品模式:
@@ -13,13 +13,13 @@
3. TextGame.ai 体现 AI Game Master、模板即玩、自定义世界、AI 队友和持久世界状态。
4. Aventura 体现 lorebook、智能记忆、分支故事和本地/隐私优先的创作辅助理念。
本文只冻结陶泥儿自己的模板落地口径。若后续实现与旧 TXT / visual novel 文档冲突,应按本文与当前后端 DDD 总纲重新修正文档后再编码。
本文只冻结百梦自己的模板落地口径。若后续实现与旧 TXT / visual novel 文档冲突,应按本文与当前后端 DDD 总纲重新修正文档后再编码。
---
## 1. 一句话定义
`text-game` 是一个 AI 原生文字游戏模板:陶泥儿主可以用一句话、文档、空白或改作入口创建一个可玩的文字互动剧本,系统把题材、玩家身份、角色、地点、目标、机制、记忆和 GM 规则编译成结构化草稿;玩家进入后通过自由输入或快捷选项推动剧情,后端 AI GM 根据世界状态、长期记忆和阶段目标生成下一轮叙事、状态变化、关系变化和可继续行动。
`text-game` 是一个 AI 原生文字游戏模板:百梦主可以用一句话、文档、空白或改作入口创建一个可玩的文字互动剧本,系统把题材、玩家身份、角色、地点、目标、机制、记忆和 GM 规则编译成结构化草稿;玩家进入后通过自由输入或快捷选项推动剧情,后端 AI GM 根据世界状态、长期记忆和阶段目标生成下一轮叙事、状态变化、关系变化和可继续行动。
---
@@ -35,7 +35,7 @@
### 2.2 不等同于 RPG 主运行时
RPG 主运行时承载陶泥儿现有视觉 RPG、场景探索、战斗、NPC、物品和章节系统。
RPG 主运行时承载百梦现有视觉 RPG、场景探索、战斗、NPC、物品和章节系统。
`text-game` 首版是轻量互动剧本模板不接入完整地图移动、战斗演出、装备背包、NPC 商店和 RPG 章节任务系统。它可以在以后把成熟剧本升级为 RPG 世界,但 V1 不做自动升级。
@@ -55,11 +55,11 @@ RPG 主运行时承载陶泥儿现有视觉 RPG、场景探索、战斗、NPC、
### 3.1 核心目标
1.陶泥儿主在 3 分钟内从一个想法生成可试玩的文字游戏。
1.百梦主在 3 分钟内从一个想法生成可试玩的文字游戏。
2. 让玩家每一轮行动都看到世界状态、关系或目标推进的反馈。
3. 让模板支持高复用题材:恋爱养成、古代言情、宫斗宅斗、修仙仙侠、末日生存、灵异怪谈、科幻未来、经营养成、校园都市、娱乐圈。
4. 让剧本不只是聊天对象,而是一个有目标、规则、记忆和结局的轻量模拟器。
5. 让作品可以进入陶泥儿作品架、草稿、发布、广场、存档和继续体验链路。
5. 让作品可以进入百梦作品架、草稿、发布、广场、存档和继续体验链路。
### 3.2 首版不追求
@@ -100,7 +100,7 @@ RPG 主运行时承载陶泥儿现有视觉 RPG、场景探索、战斗、NPC、
3. AI 可以填补空位,作为队友、对手或观众角色参与。
4. 世界状态、队伍、库存、任务进度需要持久化。
陶泥儿落点:
百梦落点:
1. V1 支持单人玩家 + AI 角色群。
2. AI 角色群只作为剧本内角色,不做多人房间。
@@ -115,7 +115,7 @@ RPG 主运行时承载陶泥儿现有视觉 RPG、场景探索、战斗、NPC、
3. 分支故事需要保存 alternate timeline 的结构,而不是只保存最终文本。
4. 创作者需要能查看和修正 AI 记住了什么。
陶泥儿落点:
百梦落点:
1. V1 只做当前主线历史与局部重生成,不做多时间线编辑器。
2. 记忆分为剧本静态设定、运行时事件摘要、角色记忆、玩家画像和未解决伏笔。
@@ -125,9 +125,9 @@ RPG 主运行时承载陶泥儿现有视觉 RPG、场景探索、战斗、NPC、
## 5. 用户角色
### 5.1 陶泥儿
### 5.1 百梦
陶泥儿主负责创建、编辑、试玩和发布文字游戏。核心诉求是:
百梦主负责创建、编辑、试玩和发布文字游戏。核心诉求是:
1. 用少量输入生成可玩的剧本。
2. 控制题材、关系张力、目标、结局和禁区。
@@ -197,7 +197,7 @@ RPG 主运行时承载陶泥儿现有视觉 RPG、场景探索、战斗、NPC、
### 7.1 一句话创建 `idea`
输入:陶泥儿主写一句或几句话。
输入:百梦主写一句或几句话。
示例语义:
@@ -1013,12 +1013,12 @@ src/components/text-game-runtime/TextGameRuntimeShell.tsx
V1 默认不新增第二套消费单位。若运行时需要扣费:
1. 使用平台“点”钱包。
1. 使用平台“点”钱包。
2. 扣费由 `api-server` 编排,不能在前端自行计算。
3. 幂等依赖 `clientEventId`
4. 测试 run 是否扣费需要产品确认。
本文不冻结具体点数。
本文不冻结具体点数。
---
@@ -1268,10 +1268,10 @@ cargo check -p api-server
1. 展示名最终用“幕间”“幕间文字”还是“AI文字游戏”。
2. V1 是否开放 `remix`
3. V1 测试 run 是否消耗点。
3. V1 测试 run 是否消耗点。
4. V1 是否允许创作者配置封面图。
5. V1 是否开放 `allowOutOfCharacterCommand`
6. V1 是否需要接入内容审核队列后才允许公开发布。
7. 作品发现页是否单独展示文字游戏分类入口。
无论这些默认值如何选择,三条硬边界不变:只做陶泥儿内的 AI 文字游戏模板,复用平台接口,不迁入外部平台和 replay。
无论这些默认值如何选择,三条硬边界不变:只做百梦内的 AI 文字游戏模板,复用平台接口,不迁入外部平台和 replay。

View File

@@ -683,7 +683,7 @@ GET /api/runtime/profile/save-archives
1. 创作底稿生成和运行时 GM 输出由 `api-server` 编排 `platform-llm`SpacetimeDB reducer 不直接调用 LLM。
2. 图片和音乐生成 / 上传由 `api-server` 编排平台资产服务,不把二进制写入 SpacetimeDB。
3. 消耗点时走平台钱包流水;不得迁入外部仓库积分表。
3. 消耗点时走平台钱包流水;不得迁入外部仓库积分表。
4. prompt 必须输出可解析 JSON step 或工具调用结果;解析失败时由后端 repair不让前端猜测业务状态。
---
@@ -1801,7 +1801,7 @@ cargo check -p api-server
这些问题不阻塞本文冻结边界,但进入编码前需要产品确认默认值:
1. 视觉小说运行时 AI 推进是否首版收费,以及单次推进默认点数。
1. 视觉小说运行时 AI 推进是否首版收费,以及单次推进默认点数。
2. 文档上传首版支持的最大大小和格式。
3. 角色立绘、场景图是否首版自动生成,还是仅提供手动上传和后续生成按钮。
4. 属性面板是否首版关闭,还是只对内部白名单开启。

View File

@@ -1,101 +0,0 @@
# 宝贝爱画寓教于乐独立关卡 PRD 2026-05-13
## 1. 目标
新增寓教于乐内容线独立关卡:
```text
宝贝爱画
```
工程 ID 固定为:
```text
baby-love-drawing
```
该关卡默认出现在“发现 / 寓教于乐”板块下方。当前阶段只做本地 Demo 保存,验证完成后再补正式持久化。
## 2. 关卡结构
启动宝贝爱画后进入绘画运行态:
1. 屏幕中央是带边框的空白画板;
2. 画板边框内是可绘画区域;
3. 画板外左侧展示彩虹 7 色;
4. 画板外右侧中下方展示画笔和橡皮;
5. 用户进入内容后默认手持画笔;
6. 手持画笔或橡皮时,屏幕上实时显示跟随右手位置的工具图案标识。
## 3. 输入规则
颜色选择:
1. 仅检测左手;
2. 左手悬停在某个颜色区域 1.5 秒后,选中该颜色;
3. 颜色固定为彩虹 7 色。
工具切换:
1. 右手移动到画笔或橡皮工具区域;
2. 右手握拳后,将手里的工具切换为对应工具。
绘画与擦除:
1. 右手在画布区域握拳时,当前工具生效;
2. 当前工具为画笔时留下轨迹;
3. 当前工具为橡皮时擦除轨迹;
4. 右手张开时,画笔或橡皮抬起,不在画布上生效。
按钮选择:
1. 完成;
2. 使用绘画魔法;
3. 保存;
4. 再画一张;
5. 返回。
以上按钮都使用任一手悬停 2 秒完成选中。
## 4. 绘画魔法
用户完成绘画后,可使用“绘画魔法”。
绘画魔法使用 image-2以用户绘画内容和笔触轨迹生成对应绘本风格图片内容。
前端不得直接读取、拼接或暴露图片生成密钥。image-2 调用必须通过后端代理。
## 5. 保存规则
当前只做本地 Demo 保存。
保存规则:
1. 魔法生成前保存,只保存一张原图;
2. 若用户未保存原图,直接点击魔法生成,则魔法生成后保存时同时保存原图和魔法图;
3. 保存完毕后,可继续“再画一张”或“返回”。
## 6. 展示与开关
宝贝爱画只属于寓教于乐内容线。
`VITE_ENABLE_EDUTAINMENT_ENTRY` 关闭时:
1. 不展示“发现 / 寓教于乐”频道;
2. 不展示宝贝爱画默认卡片;
3. 不允许通过 `/runtime/baby-love-drawing` 直达运行态。
## 7. 验收
1. 寓教于乐开启时,“发现 / 寓教于乐”下方展示“宝贝爱画”默认关卡卡片;
2. 寓教于乐关闭时,不展示宝贝爱画,也不能直达运行态;
3. 进入后展示空白画板、彩虹 7 色、画笔和橡皮;
4. 默认工具为画笔;
5. 左手悬停颜色 1.5 秒后选中颜色;
6. 右手移动到工具区并握拳后切换画笔或橡皮;
7. 右手握拳在画布内绘制或擦除,张开时不生效;
8. 任一手悬停按钮 2 秒后触发按钮;
9. 完成后可保存原图;
10. 完成后可使用绘画魔法生成绘本风格图片;
11. 未保存原图直接使用绘画魔法后,保存会同时保存原图和魔法图;
12. 保存后可再画一张或返回。

View File

@@ -29,24 +29,11 @@
2. 模板名称:`宝贝识物`
3. 两个物品;
4. 两个物品图;
5. 游戏视觉主题包;
6. 作品标签。
5. 作品标签。
物品图使用 VectorEngine `gpt-image-2-all` / image-2 生成。图片生成只能走后端接口,前端不得读取、拼接或暴`VECTOR_ENGINE_API_KEY`
物品图使用 VectorEngine `gpt-image-2-all` / image-2 生成。图片生成只能走后端或后续后端预留接口,前端不得泄`VECTOR_ENGINE_API_KEY`
每个关键词只生成一张围绕该关键词的单一物品形象。生成 prompt 必须锁定寓教于乐板块统一的卡通绘本草地舞台插画风,但最终画面不生成背景、场景、氛围渲染、人物、手、篮子、礼物盒、文字、水印或 UI。服务端必须把生成结果转成透明 PNG并执行透明抠图后处理只有透明抠图后的素材才允许写入草稿 `itemAssets` 并进入游戏运行态
同一次创作还必须使用 image-2 生成游戏视觉主题包包含背景环境、UI 装饰框、礼物盒、篮子和烟雾弹出特效资源。主题包必须继续保持寓教于乐插画风,并根据用户填写的两个物品关键词匹配主题:例如关键词偏动漫角色或玩具时,背景环境和元素可使用动漫、玩具主题;关键词偏水果时,背景环境和元素可匹配果园、自然主题;其它关键词按其语义匹配合适主题。主题包不得改变关卡玩法规则,不新增文字说明、额外按钮或额外判定规则。
视觉主题包的资源边界:
1. 背景环境图不做透明抠图,但必须保证屏幕中间、中下方和底部左右篮子区域清爽,不遮挡放大后的物品、礼物盒和篮子;
2. UI 装饰框用于字幕条和计数器风格化包装,只生成装饰边框和主题点缀,不生成文字、数字或按钮;
3. 礼物盒资源输出为透明 PNG运行态按当前礼盒视觉的 2 倍尺寸展示,素材主体必须饱满清晰;
4. 篮子资源输出为透明 PNG运行态按当前篮子视觉的 1.5 倍尺寸展示,左右篮子仍固定为两个物品对应选项,篮子造型资源可以复用同一张主题篮子图;
5. 烟雾弹出特效资源输出为透明 PNG用于礼物盒打开瞬间覆盖开盒区域并承接中央物品弹出不生成物品、篮子、礼物盒或文字。
当前本地 Demo 阶段已接入真实 image-2 资源链路。创作提交必须成功获得 `generationProvider = "vector-engine-gpt-image-2"` 的两个物品透明 PNG 和完整视觉主题包后才能进入结果页、试玩或发布若后端接口、登录态、VectorEngine 配置或上游生成失败,前端必须停留在生成失败状态并展示错误,不得静默回退为占位图。历史草稿中若仍存在 `generationProvider = "placeholder"` 的占位资源,结果页必须提示重新生成,试玩和发布前必须先补齐 image-2 资源。
本地 Demo 阶段若真实生图接口未接入完成,允许前端 service 返回明确标记为 `placeholder` 的占位图形,用于打通创作到结果页的交互链路;该占位结果不得伪装成正式 image-2 资产
## 4. 标签规则
@@ -76,8 +63,6 @@
试玩按钮进入宝贝识物首关运行态,运行态消费当前草稿中的两个物品名称和两张物品图,不重新生成或改写物品内容。
若草稿包含视觉主题包运行态还必须消费该主题包中的背景环境、UI 装饰、礼物盒、篮子和烟雾弹出特效资源;旧草稿或接口失败时允许回退到当前 CSS 绘本风兜底。
## 6. 发布后体验
发布完成后作品应进入寓教于乐内容线,并在寓教于乐入口开启时可被板块消费。
@@ -88,30 +73,27 @@
本 PRD 同步约束首关运行态,已确认规则包括:
1. 进入关卡后礼物盒自动打开并弹出首个随机物品
1. 礼物盒打开在本地调试绑定 `F`
2. 每轮仅中间礼物盒跳出的物品随机;左右两侧篮子固定为当前草稿两个物品的顺序;
3. 下一关按钮当前占位;
4. 不新增用户未确认的计时、失败次数、分数、体力或难度递增。
5. 屏幕中上方字幕固定为“将物品放入对应的篮子里”。
6. 礼物盒位于屏幕中下方并按当前视觉放大一倍,首次进入关卡和每次正确反馈结束后的新轮次都从上方落下后自动打开
6. 礼物盒位于屏幕中下方,任意手抬起后打开并跳出下一个随机物品
7. 屏幕下方左侧和右侧分别展示两个固定篮子,左侧固定使用草稿第一个物品图,右侧固定使用草稿第二个物品图。
8. 左右篮子按当前视觉放大 50%
9. 礼物盒打开时播放烟雾特效,中央物品从烟雾特效中弹出;物品弹出后礼物盒从舞台移除
10. 明确左手连续横向移动达到阈值时将当前物品送入左侧篮子,明确右手连续横向移动达到阈值时将当前物品送入右侧篮子;选篮不使用动作名判定,侧别未知的手部轨迹不参与选篮
11. 正确时展示“真棒”字幕和正确特效;错误时展示“再想一想吧”字幕和错误特效,物品回到中央
12. 成功 20 次后展示“恭喜你!小朋友!”字幕和特效,并展示“再来一次”和“下一关”按钮。
13. 当前本地 Demo 阶段音效与语音播报接口只预留调用点,不在前端写死外部硬件或服务接口。
8. 明确左手连续横向移动达到阈值时将当前物品送入左侧篮子,明确右手连续横向移动达到阈值时将当前物品送入右侧篮子;选篮不使用动作名判定,侧别未知的手部轨迹不参与选篮
9. 正确时展示“真棒”字幕和正确特效;错误时展示“再想一想吧”字幕和错误特效,物品回到中央
10. 成功 20 次后展示“恭喜你!小朋友!”字幕和特效,并展示“再来一次”和“下一关”按钮
11. 当前本地 Demo 阶段音效与语音播报接口只预留调用点,不在前端写死外部硬件或服务接口
## 8. 验收
1. 创作入口显示 `宝贝识物` 并可进入模板表单。
2. 未填写任一物品名称时不能生成草稿。
3. 生成草稿后进入结果页,展示两个物品名称和物品图。
4. 生成草稿后包含视觉主题包主题包含背景环境、UI 装饰框、礼物盒、篮子和烟雾弹出特效资源
5. 草稿标签中始终包含精确 `寓教于乐`
6. 发布 payload 始终包含精确 `寓教于乐`
7. 发布完成后出现分享弹窗或发布完成状态
8. 前端不读取或暴露 VectorEngine 密钥
9. 结果页试玩进入宝贝识物运行态,不再显示“试玩关卡正在接入中”
10. 运行态通过鼠标左键拖动映射左手横向移动,通过鼠标右键拖动映射右手横向移动。
11. 成功 20 次后出现“再来一次”和“下一关”按钮。
4. 草稿标签中始终包含精确 `寓教于乐`
5. 发布 payload 始终包含精确 `寓教于乐`
6. 发布完成后出现分享弹窗或发布完成状态
7. 前端不读取或暴露 VectorEngine 密钥
8. 结果页试玩进入宝贝识物运行态,不再显示“试玩关卡正在接入中”
9. 运行态可通过 `F` 打开礼物盒,通过鼠标左键拖动映射左手横向移动,通过鼠标右键拖动映射右手横向移动
10. 成功 20 次后出现“再来一次”和“下一关”按钮。

View File

@@ -4,7 +4,7 @@
- 需求来源:用户提供的视频 `C:\Users\DSK\Videos\一款双方比狗叫的游戏 - 1.一款双方比狗叫的游戏(Av116504192360177,P1).mp4`,并已在 `.hermes/plans/2026-05-11_144229-bark-battle-2d-game-bdd-ddd-tdd-plan.md` 中完成抽帧分析和玩法方案整理。
- 玩法定位:浏览器 2D 声控狗叫对战小游戏,暂定中文名 `汪汪声浪大作战`,英文代号与 play type ID 建议为 `bark-battle`
- 核心玩法:双方狗狗在 30 秒限时内通过麦克风输入“狗叫声”进行声浪拔河;系统依据声音强度、有效声浪触发次数和声节奏计算推动力,实时推动顶部红蓝能量条;倒计时结束后按能量条位置判定胜负或平局。
- 核心玩法:双方狗狗在 30 秒限时内通过麦克风输入“狗叫声”进行声浪拔河;系统依据声音强度、有效声次数和声节奏计算推动力,实时推动顶部红蓝能量条;倒计时结束后按能量条位置判定胜负或平局。
- 文档目的:为产品、测试、前端、后端在编码前统一可验证验收口径;本文只定义 PRD/BDD 级行为与测试映射,不实现工程代码。
## 角色与目标
@@ -20,14 +20,14 @@
### 用户目标
- 玩家可以在开局前完成麦克风授权和环境噪音校准。
- 玩家产生有效声浪触发时,能看到声计数、狗狗动画、拟声词/冲击波以及能量条变化。
- 低于阈值的背景噪音不会被误计为有效声浪触发
- 玩家发出有效狗叫时,能看到声计数、狗狗动画、拟声词/冲击波以及能量条变化。
- 低于阈值的背景噪音不会被误计为有效声。
- 单局在 30 秒后给出明确胜负、平局和关键数据。
- 移动端和不支持麦克风的环境不会进入不可操作状态。
### 非目标
- MVP 不要求识别“是否真实狗叫”,不引入机器学习声纹/物种分类;有效输入以音量阈值、峰值冷却间隔和校准结果为准。
- MVP 不要求识别“是否真实狗叫”,不引入机器学习声纹/物种分类;有效输入以音量阈值、峰值间隔、持续时间和校准结果为准。
- MVP 不要求实时联机对战;可先按“玩家 vs AI 对手”完成单机浏览器 runtime。
- MVP 不要求成绩持久化、作品发布、作品架、广场和排行榜;若后续接入 Genarrative 作品闭环,需要另补玩法类型集成 PRD/技术文档。
- MVP 不要求在 UI 中长期展示大段规则说明;游戏界面应保持倒计时、能量条、狗狗、麦克风状态和结算信息为主。
@@ -38,10 +38,10 @@
- 单局时长:默认 30 秒,从正式进入 `playing` 阶段开始计时。
- 能量条:使用 `-100``100` 的连续值表示,负数偏对手侧,正数偏玩家侧,`0` 为中线。
- 平局阈值:倒计时结束时,若能量条绝对值小于或等于 `drawThreshold`,判定平局;具体数值由实现配置,但测试需可注入固定阈值。
- 有效声浪触发:一次有效声浪触发满足:当前麦克风采样点的归一化响度达到或超过校准后的有效阈值,且与上一次有效声浪触发间隔不小于 `minBarkGapMs`;不再要求持续高响度时长达标,也不等待响度回落
- 背景噪音:校准阶段采集到的环境声用于计算动态阈值;低于阈值的输入不得增加声浪触发次数,也不得让能量条出现可见推进。
- 推动力:玩家推动力由音量分数、有效声浪触发频率和连击加成组成;能量条按玩家推动力与对手推动力差值移动,并被限制在 `-100``100`
- UI 反馈:有效声浪触发应触发可观察反馈,包括玩家侧狗狗张嘴/吠叫动画、拟声词或冲击波;反馈不应遮挡倒计时和顶部能量条。
- 有效声:一次有效叫声至少满足:音量超过校准后的有效阈值与上一次有效峰值间隔不小于 `minBarkGapMs`、持续时长在 `minBarkDurationMs``maxBarkDurationMs` 之间
- 背景噪音:校准阶段采集到的环境声用于计算动态阈值;低于阈值的输入不得增加声次数,也不得让能量条出现可见推进。
- 推动力:玩家推动力由音量分数、有效声频率和连击加成组成;能量条按玩家推动力与对手推动力差值移动,并被限制在 `-100``100`
- UI 反馈:有效声应触发可观察反馈,包括玩家侧狗狗张嘴/吠叫动画、拟声词或冲击波;反馈不应遮挡倒计时和顶部能量条。
## 中文 Gherkin 场景
@@ -66,7 +66,7 @@
场景: 校准完成后进入开局倒计时
假如
而且
那么
而且 30
而且线
@@ -84,19 +84,19 @@
功能: 环境噪音校准
场景: 安静环境生成低但非零的有效阈值
假如 RMS 线
那么
那么
而且
场景: 嘈杂环境生成更高的有效阈值
假如 RMS 线
那么
而且
那么
而且
场景: 校准期间无法获得有效音频样本
假如
@@ -106,36 +106,36 @@
而且
```
### 功能: 有效声浪触发计数
### 功能: 有效声计数
```gherkin
功能: 有效声浪触发计数
功能: 有效声计数
背景:
假如 30 playing
而且
场景: 单次超过阈值且间隔足够的声浪触发计数加一
假如 0
而且 minBarkGapMs
那么 1
场景: 单次超过阈值且间隔足够的声计数加一
假如 0
而且 minBarkGapMs
那么 1
而且
而且
场景: 持续高响度输入只按冷却节奏计数
假如 1
那么 tick
而且
场景: 持续噪音不会被无限计数
假如 1
那么 tick
而且
场景: 间隔过短的连续峰值不重复计数
假如
minBarkGapMs
那么
假如
minBarkGapMs
那么
而且
```
@@ -145,23 +145,23 @@
功能: 声浪推动能量条
背景:
假如 30 playing
而且线
场景: 玩家推动力高于对手时能量条向玩家侧移动
假如
假如
而且
simulation tick
那么
而且
场景: 连续强声浪触发触发更强反馈
假如
场景: 连续大声叫声触发更强反馈
假如
那么
那么
而且
但是
@@ -185,30 +185,31 @@
功能: 背景噪音过滤
背景:
假如 30 playing
而且
场景: 低于阈值的背景噪音不计数
那么
那么
而且
而且
场景: 冷却内重复达阈值不计数
假如
minBarkGapMs
那么
场景: 过短脉冲不计为有效叫声
假如
但是 minBarkDurationMs
那么
而且
场景: 持续高响度输入只按冷却节奏产生触发
假如
那么 tick
那么
场景: 过长持续声被削弱为单段输入
假如
但是 maxBarkDurationMs
那么
而且
```
### 功能: 倒计时与胜负结算
@@ -226,20 +227,20 @@
30 0
那么
而且 finished
而且
而且
场景: 玩家侧占优时判定玩家胜利
假如 drawThreshold
那么
而且
而且
而且
场景: 对手侧占优时判定玩家失败
假如 -drawThreshold
那么
而且
而且
而且
场景: 能量条接近平衡时判定平局
@@ -264,7 +265,7 @@
那么 30
而且线
而且
而且
而且
场景: 结算后返回玩法入口
@@ -352,7 +353,7 @@
假如 playing
bark-battle
那么
而且沿
而且沿
```
## 测试映射
@@ -366,15 +367,15 @@
| 嘈杂环境生成更高的有效阈值 | unit | `src/games/bark-battle/domain/BarkNoiseCalibration.test.ts` | planned |
| 校准期间无法获得有效音频样本 | application/component | `src/games/bark-battle/application/BarkBattleController.test.ts`, `src/games/bark-battle/ui/BarkBattlePermissionPanel.test.tsx` | planned |
| 单次超过阈值且间隔足够的叫声计数加一 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 持续高响度输入只按冷却节奏计数 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 持续噪音不会被无限计数 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 间隔过短的连续峰值不重复计数 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 玩家推动力高于对手时能量条向玩家侧移动 | unit | `src/games/bark-battle/domain/EnergyTugOfWar.test.ts` | planned |
| 连续强声浪触发触发更强反馈 | unit/integration/component | `src/games/bark-battle/domain/BarkBattleScoring.test.ts`, `src/games/bark-battle/ui/BarkBattleHud.test.tsx` | planned |
| 连续大声叫声触发更强反馈 | unit/integration/component | `src/games/bark-battle/domain/BarkBattleScoring.test.ts`, `src/games/bark-battle/ui/BarkBattleHud.test.tsx` | planned |
| 能量条到达边界后不会越界 | unit | `src/games/bark-battle/domain/EnergyTugOfWar.test.ts` | planned |
| 对手推动力高于玩家时能量条向对手侧移动 | unit | `src/games/bark-battle/domain/EnergyTugOfWar.test.ts` | planned |
| 低于阈值的背景噪音不计数 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 冷却内重复达阈值不计数 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 持续高响度输入只按冷却节奏产生触发 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 过短脉冲不计为有效叫声 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 过长持续声被削弱为单段输入 | unit | `src/games/bark-battle/domain/BarkDetector.test.ts` | planned |
| 倒计时每秒递减并在归零时停止对战输入 | unit/application | `src/games/bark-battle/domain/BarkBattleSession.test.ts`, `src/games/bark-battle/application/BarkBattleController.test.ts` | planned |
| 玩家侧占优时判定玩家胜利 | unit/component | `src/games/bark-battle/domain/BarkBattleSession.test.ts`, `src/games/bark-battle/ui/BarkBattleResultPanel.test.tsx` | planned |
| 对手侧占优时判定玩家失败 | unit/component | `src/games/bark-battle/domain/BarkBattleSession.test.ts`, `src/games/bark-battle/ui/BarkBattleResultPanel.test.tsx` | planned |
@@ -393,8 +394,8 @@
## 验收清单
- [ ] 权限允许、拒绝、非安全上下文、API 不支持、麦克风未找到/不可读、AudioContext 被拦截、校准超时或样本不可读均有明确状态,且不会误进入 playing。
- [ ] 校准阶段会影响有效声阈值,低噪音不会增加叫声计数。
- [ ] 有效声浪触发计数具备阈值与声浪冷却约束。
- [ ] 校准阶段会影响有效声阈值,低噪音不会增加叫声计数。
- [ ] 有效声计数具备阈值、峰值间隔、持续时长约束。
- [ ] 能量条根据双方推动力差值双向移动,并限制在 `-100``100`
- [ ] 30 秒归零后停止本局输入影响,并按玩家胜利、对手胜利、平局三类结果结算。
- [ ] 移动端核心元素可见,非关键设置收起,不在主画面堆叠长规则说明。
@@ -404,8 +405,8 @@
## 开放问题
1. MVP 是否确认只做“玩家 vs AI”还是第一版需要双人同屏或联机对战
2. `drawThreshold``minBarkGapMs`有效声浪阈值 的首版默认值由产品/调参阶段确认,还是先采用开发可配置默认值?
2. `drawThreshold``minBarkGapMs``minBarkDurationMs``maxBarkDurationMs` 的首版默认值由产品/调参阶段确认,还是先采用开发可配置默认值?
3. 是否允许无麦克风设备提供键盘/点击备用输入?若允许,需要另补非声控模式场景;若不允许,当前降级只提供返回入口。
4. 是否需要在结算中记录或上报成绩、最高音量、声浪触发次数和声浪评分?若需要,需补埋点/后端持久化场景。
4. 是否需要在结算中记录或上报成绩、最高音量、声次数和声浪评分?若需要,需补埋点/后端持久化场景。
5. bark-battle 是否作为 Genarrative 正式 play type 接入创作入口、作品发布和广场,还是先作为独立 runtime 原型验证?
6. 狗狗、背景、拟声词和冲击波素材来源是临时占位、AI 生成,还是复用项目现有素材管线?

View File

@@ -12,7 +12,7 @@ Phase 1 的目标不是重做现有拼图创作系统,也不是把 Agent 降
## 1. 一句话定义
Phase 1 是一个“只开放拼图模板的创意互动内容生成 Agent”它必须先展示多个拼图模板候选用户选择某个模板后再确认该模板下的关卡模式、关卡数和预计点范围;确认后才通过拼图模块 Tool 填充同一份 `PuzzleResultDraft` 草稿字段,并复用现有 `puzzle-result``puzzle-runtime` 完成表单编辑、自然语言修订和立即试玩闭环。
Phase 1 是一个“只开放拼图模板的创意互动内容生成 Agent”它必须先展示多个拼图模板候选用户选择某个模板后再确认该模板下的关卡模式、关卡数和预计点范围;确认后才通过拼图模块 Tool 填充同一份 `PuzzleResultDraft` 草稿字段,并复用现有 `puzzle-result``puzzle-runtime` 完成表单编辑、自然语言修订和立即试玩闭环。
---
@@ -91,7 +91,7 @@ APIMart Responses 请求必须按多模态内容块组织:
1. 新增 `platform-agent` PoC crate封装 LangChain-Rust 的 Function Calling / AgentExecutor 能力。
2. 新增创意 Agent shared contract支持阶段、消息、模板选择、积分范围、关卡图片计划、目标拼图 session 绑定。
3. 新增拼图模板协议,当前只提供一个可用拼图模板,但仍必须显式展示选择步骤。
4. 拼图模板卡必须展示模板标题、预览、选择理由、单关卡/多关卡能力、计划关卡数、预计点范围。
4. 拼图模板卡必须展示模板标题、预览、选择理由、单关卡/多关卡能力、计划关卡数、预计点范围。
5. 用户确认模板后Agent 才能创建或复用拼图 session并填充 `PuzzleResultDraft`
6. Agent 可写草稿字段只允许:
- `PuzzleResultDraft.workTitle`
@@ -133,7 +133,7 @@ APIMart Responses 请求必须按多模态内容块组织:
-> Agent 思考并选择拼图模板
-> 前端展示多个拼图模板卡
-> 用户选择一个模板
-> 前端弹出该模板的关卡模式、关卡数和预计点范围确认面板
-> 前端弹出该模板的关卡模式、关卡数和预计点范围确认面板
-> Agent 调用拼图模块 Tool 生成草稿字段和图片计划
-> 拼图模块创建 / 更新 puzzle_agent_session
-> 拼图模块生成单关卡或多关卡图片候选
@@ -174,7 +174,7 @@ Agent 生成草稿前必须展示独立确认卡。确认卡字段:
| 选择理由 | `reason` | 一到两句中文,不展示内部推理链。 |
| 关卡模式 | `selectedLevelMode` | 单关卡 / 多关卡。 |
| 计划关卡数 | `plannedLevelCount` | 在模板 min/max 内。 |
| 预计点 | `costRange` | 显示 `minPoints``maxPoints` 点。 |
| 预计点 | `costRange` | 显示 `minPoints``maxPoints` 点。 |
交互:
@@ -529,7 +529,7 @@ done
事件要求:
1. `messages/stream` 首轮必须先返回 `puzzle_template_catalog`,并把 `puzzleTemplateCatalog` 写入 session`puzzleTemplateSelection` 保持为空。
2. 用户点击某个模板后,前端基于模板协议打开独立配置确认面板,确认关卡模式、关卡数和预计点范围。
2. 用户点击某个模板后,前端基于模板协议打开独立配置确认面板,确认关卡模式、关卡数和预计点范围。
3. `confirm-template` 后才允许写入 `puzzle_template_selection``puzzle_level_plan` 并创建拼图草稿。
4. `target_session` 必须带 `targetSessionId` 和可跳转 stage。
5. 流式失败时保留已显示文字,并发送结构化 `error`
@@ -719,7 +719,7 @@ Agent 必须被提示为:
1. 你是创意互动内容生成 Agent不是规则分类器。
2. 当前产品只开放拼图模板。
3. 你要相信自己的图文理解能力,主动形成拼图创意。
4. 即使只有拼图可用,也必须显式选择模板并展示预计点范围。
4. 即使只有拼图可用,也必须显式选择模板并展示预计点范围。
5. 未经用户确认模板,不得创建草稿。
6. 你只能调用已注册工具。
7. 可写草稿字段只限 `workTitle``workDescription``workTags``levels[].levelName``levels[].pictureDescription``levels[].pictureReference`
@@ -996,7 +996,7 @@ npm run test -- PuzzleResultView
4. `PuzzleResultView` 已显示并编辑 `levels[].pictureReference`,并在智能创作链路进入结果页时显示自然语言修订输入条,调用 `streamCreativeDraftEdit` 后回写同一份拼图 session。
5. 前端定向验证已通过:`npm run typecheck``npm run check:encoding``npx eslint src/services/creative-agent/creativeAgentClient.ts src/services/creative-agent/creativeAgentSse.ts src/services/creative-agent/index.ts src/components/creative-agent/CreativeAgentWorkspace.tsx src/components/creative-agent/CreativeAgentInputComposer.tsx src/components/creative-agent/CreativeAgentTemplateConfirmPanel.tsx src/components/creative-agent/CreativeAgentStageTimeline.tsx src/components/creative-agent/creativeAgentViewModel.ts src/components/platform-entry/PlatformEntryFlowShellImpl.tsx src/components/platform-entry/platformEntryCreationTypes.ts src/components/platform-entry/PlatformEntryCreationTypeModal.tsx src/components/puzzle-result/PuzzleResultView.tsx --max-warnings 0``npm run test -- src/services/creative-agent/creativeAgentSse.test.ts``npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx``npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx``npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "create hub hides RPG"`
6. 2026-05-05 补充:智能创作工作区的过程区不再只展示最近 6 个短进度标签,改为基于 SSE 事件生成详细过程项,覆盖阶段切换、工具开始/完成、模板选择、预计点、关卡计划、反思、目标绑定、错误和完成事件;刷新或非流式恢复时会从 session 快照补模板、关卡计划和目标绑定,移动端使用紧凑可滚动列表。
6. 2026-05-05 补充:智能创作工作区的过程区不再只展示最近 6 个短进度标签,改为基于 SSE 事件生成详细过程项,覆盖阶段切换、工具开始/完成、模板选择、预计点、关卡计划、反思、目标绑定、错误和完成事件;刷新或非流式恢复时会从 session 快照补模板、关卡计划和目标绑定,移动端使用紧凑可滚动列表。
7. 2026-05-05 补充:流式过程新增 `thought_summary_delta` 事件,只展示可给用户看的“思考摘要”,例如素材理解、模板选择摘要和关卡规划摘要;该事件不承载模型内部推理链,前端按 `thoughtId` 合并多段 delta 后在过程面板中显示为一条持续更新的“思考摘要”。
8. 2026-05-06 补充:智能创作 Agent 的模板步骤拆成两段,`messages/stream` 只返回 `puzzle_template_catalog` 和 session 里的 `puzzleTemplateCatalog`;前端先展示多个模板卡,用户选中后才打开独立确认面板并提交 `confirm-template``puzzle_template_selection``puzzle_cost_range``puzzle_level_plan` 不再由首轮消息流自动发送。工作区在 `sessionId` 变化时必须清空本地待确认模板,避免上一会话已点开的确认面板残留到新会话。
@@ -1051,7 +1051,7 @@ cargo check -p api-server
1. 任务 G 已补 API facade 回归:`cargo test -p api-server creative_agent` 覆盖未确认模板时 `draft-edits/stream` 返回错误且不绑定 `targetBinding`,以及 `rpg.unsupported` 非拼图模板确认被拒绝且不创建目标 session。
2. 任务 G 已补拼图模块回归:`cargo test -p module-puzzle creative` 同时覆盖单关卡、多关卡 draft 和 `pictureReference` / `workDescription -> summary` / `workTags -> themeTags` 的 Phase 1 映射。
3. 任务 G 已补前端回归:`CreativeAgentTemplateConfirmPanel.test.tsx` 覆盖模板确认卡点范围,`CreativeAgentWorkspace.test.tsx` 覆盖 target ready 后展示打开草稿入口,并通过 `resolveCreativeAgentTargetSelectionStage` 固定 `puzzle-result` 跳转落点;`creativeAgentSse.test.ts` 覆盖 creative Agent SSE 事件与 draft edit payload。
3. 任务 G 已补前端回归:`CreativeAgentTemplateConfirmPanel.test.tsx` 覆盖模板确认卡点范围,`CreativeAgentWorkspace.test.tsx` 覆盖 target ready 后展示打开草稿入口,并通过 `resolveCreativeAgentTargetSelectionStage` 固定 `puzzle-result` 跳转落点;`creativeAgentSse.test.ts` 覆盖 creative Agent SSE 事件与 draft edit payload。
4. 定向验收已通过:`npm run check:encoding``npm run test -- src/components/creative-agent/CreativeAgentWorkspace.test.tsx src/components/creative-agent/CreativeAgentTemplateConfirmPanel.test.tsx src/services/creative-agent/creativeAgentSse.test.ts``npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx``cargo test -p module-puzzle creative``cargo test -p module-puzzle puzzle_draft``cargo test -p shared-contracts creative_agent``cargo test -p api-server creative_agent``cargo check -p api-server`
5. 全量 `npm run typecheck` 当前被视觉小说链路既有类型错误阻塞,包含 `packages/shared/src/contracts/visualNovel.ts``src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``onSelectVisualNovel` 缺失和 `src/components/visual-novel-result/VisualNovelResultView.tsx`;全量 `npm run test` 当前被既有 RPG 首页搜索 / 拼图 workspace 旧断言等非本任务用例阻塞。上述阻塞不来自本次 creative-agent Task G 回归补测。
@@ -1095,7 +1095,7 @@ cargo check -p api-server
1. 用户从创作中心进入创意 Agent。
2. 用户输入文字和 1 张图片后SSE 显示感知和思考阶段。
3. Agent 显式展示拼图模板确认卡。
4. 确认卡显示预计点范围。
4. 确认卡显示预计点范围。
5. 未确认模板时不会创建拼图草稿。
6. 确认模板后进入草稿生成。
7. 生成的草稿字段对齐 `workTitle``workDescription``workTags``levels[].levelName``levels[].pictureDescription``levels[].pictureReference`

View File

@@ -4,7 +4,7 @@
## 0. 目标
把“点 / 游戏时长 / 玩过”这一排信息卡,从静态数字展示升级成稳定的个人数据看板,让玩家在进入“我的”页时一眼知道自己的账号资产和游玩投入。
把“点 / 游戏时长 / 玩过”这一排信息卡,从静态数字展示升级成稳定的个人数据看板,让玩家在进入“我的”页时一眼知道自己的账号资产和游玩投入。
---
@@ -12,7 +12,7 @@
当前三个数字来源并不统一:
1. 点来自当前存档上下文,不等于账号总资产
1. 点来自当前存档上下文,不等于账号总资产
2. 游戏时长依赖当前快照,不代表全账号累计
3. 玩过当前几乎是硬编码推导,不是真实统计
@@ -39,11 +39,11 @@
## 3. 指标定义
## 3.1
## 3.1
定义:
- 当前账号可立即消费的点余额
- 当前账号可立即消费的点余额
不使用:
@@ -80,7 +80,7 @@
点击行为:
1. 点卡
1. 点卡
- 打开资产流水抽屉
2. 游戏时长卡
- 打开游玩统计抽屉
@@ -125,7 +125,7 @@
返回:
- 点流水列表
- 点流水列表
### `GET /api/profile/play-stats`

View File

@@ -73,7 +73,7 @@
首期奖励建议采用可控方案:
1. 邀请人获得
1. 邀请人获得
2. 被邀请人获得新手奖励
所有奖励必须走台账,不允许前端本地加值。
@@ -164,4 +164,4 @@
1. 用户能看到自己的邀请码与邀请链接
2. 可以一键复制或分享
3. 邀请成功后能看到正确统计
4. 奖励到账后点余额同步变化
4. 奖励到账后点余额同步变化

View File

@@ -51,11 +51,11 @@
首期只保留两种状态:
1. `普通用户`
2. `陶泥儿会员`
2. `百梦会员`
会员权益首期建议控制在直接可编码的范围:
1. 每日额外点领取额度
1. 每日额外点领取额度
2. 高级世界模板或创作槽位
3. 更高的云存档上限
4. 会员专属标识
@@ -119,7 +119,7 @@
支付成功后:
1. 刷新会员状态
2. 刷新点余额
2. 刷新点余额
3. 刷新权益标签
---

View File

@@ -8,7 +8,7 @@
1. 头像编辑
2. 昵称编辑
3. 陶泥号展示与复制
3. 百梦号展示与复制
4. 登录方式与绑定状态展示
5. 进入资料编辑抽屉
@@ -22,7 +22,7 @@
- 头像占位
- 昵称
- 陶泥
- 百梦
- 登录方式
- 绑定状态
@@ -31,7 +31,7 @@
1. 头像按钮和昵称编辑按钮都直接打开账号弹窗,信息架构混在一起
2. 头像当前只是视觉壳,没有真正的上传与裁剪能力
3. 昵称缺少明确的编辑规则与唯一性策略
4. 陶泥号只是前端拼接值,不适合长期作为正式公开识别码
4. 百梦号只是前端拼接值,不适合长期作为正式公开识别码
---
@@ -43,7 +43,7 @@
2. 资料编辑抽屉
3. 头像上传、裁切、保存
4. 昵称编辑、校验、保存
5. 陶泥号固定生成与复制
5. 百梦号固定生成与复制
6. 登录方式与账号状态标签展示
## 2.2 本期不做
@@ -63,7 +63,7 @@
- 用户头像
- 用户昵称
- `陶泥号`
- `百梦号`
- 登录方式标签
- 账号状态标签
- 资料编辑入口
@@ -85,7 +85,7 @@
- 打开“编辑资料”抽屉,并默认聚焦头像编辑区域
2. 点击昵称右侧编辑按钮
- 打开“编辑资料”抽屉,并默认聚焦昵称输入框
3. 点击陶泥号复制按钮
3. 点击百梦号复制按钮
- 直接复制,并给出轻提示
4. 点击登录方式/状态标签
- 不跳页,不弹复杂说明
@@ -103,7 +103,6 @@
3. 上传后进入正方形裁切
4. 服务端生成 `256x256` 主图和 `96x96` 缩略图
5. 超过大小或格式限制时直接拦截
6. 头像裁切工具必须复用平台通用正方形图片裁剪弹窗,并与拼图图片上传裁剪保持同一套拖拽裁剪框、八向边界手柄、九宫格辅助线、遮罩和移动端触控行为;不得在头像侧保留独立的缩放/横向/纵向滑杆实现
支持格式:
@@ -126,9 +125,9 @@
4. 不要求全站唯一,但要允许后端做敏感词审核
5. 审核失败时返回明确错误
## 4.3 陶泥
## 4.3 百梦
陶泥号规则:
百梦号规则:
1. 作为公开可复制识别码
2. 用户创建后固定生成,不允许用户修改
@@ -208,6 +207,6 @@
1. 用户可以上传并保存头像
2. 用户可以修改昵称并实时看到更新
3. 陶泥号由后端返回,复制后可正常使用
3. 百梦号由后端返回,复制后可正常使用
4. 未登录或待绑定状态下,不出现无效编辑入口
5. 页面不出现冗长规则说明文案

View File

@@ -4,9 +4,8 @@
## 重点入口
- [宝贝爱画寓教于乐独立关卡 PRD](./BABY_LOVE_DRAWING_EDUTAINMENT_LEVEL_PRD_2026-05-13.md):定义寓教于乐内容线的 `宝贝爱画` 独立本地 Demo 关卡,覆盖画板、七色选择、画笔/橡皮、手部绘画、完成、image-2 绘画魔法、本地保存和关闭入口隐藏边界。
- [宝贝识物寓教于乐模板 PRD](./BABY_OBJECT_MATCH_EDUTAINMENT_TEMPLATE_PRD_2026-05-11.md):定义寓教于乐内容线的 `宝贝识物` 创作模板覆盖两个物品名称输入、image-2 物品图生成、精确 `寓教于乐` 标签、结果页和发布边界。
- [AI 原生幕间文字游戏模板 PRD参考 MOKU 的剧本模拟器闭环](./AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md):参考 MOKU / 幕间类 AI 文游的剧本游乐场、自由行动、AI GM、记忆和模拟器强反馈经验但只落为陶泥儿 `text-game` 模板,复用平台接口,不迁入外部社区、支付、私有存档或回放。
- [AI 原生幕间文字游戏模板 PRD参考 MOKU 的剧本模拟器闭环](./AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md):参考 MOKU / 幕间类 AI 文游的剧本游乐场、自由行动、AI GM、记忆和模拟器强反馈经验但只落为百梦 `text-game` 模板,复用平台接口,不迁入外部社区、支付、私有存档或回放。
- [AI 原生视觉小说模板 PRDTXT 玩法平台化接入](./AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md):参考 `Interactive-fiction-backend` / `Interactive-fiction-frontend` 的 TXT 玩法经验,但只保留视觉小说模板创作与运行闭环,完全使用 Genarrative 平台接口,并明确删除回放和外部平台功能。
- [AI 原生幸存者类游戏模板 PRD](./AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md):定义 `survivor` 幸存者挑战模板,从 Agent 创作、结果页、资产、试玩、发布到后端权威配置与前端高频运行表现的完整闭环。
- [创意互动内容生成 Agent Phase 1 PRDLangChain-Rust PoC + 拼图闭环](./CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md)首版只支持拼图模板Agent 使用 APIMart Responses `gpt-5` 支持文本和图像多模态输入,明确模板选择、积分范围、草稿字段填充、单关卡/多关卡图片生成、立即试玩、自然语言修改和可并行任务拆分。

View File

@@ -37,7 +37,7 @@ TXT 模式核心玩法是一个包含“创作编辑器 -> 测试体验 -> 正
1. 支持创建 TXT 模式作品。
2. 支持 TXT 模式作品的完整创作流程。
3. 支持陶泥儿主测试体验。
3. 支持百梦主测试体验。
4. 支持玩家正式游玩。
5. 支持文本模式运行。
6. 支持双会话机制。
@@ -176,9 +176,9 @@ TXT 模式核心玩法必须完整保留双会话机制。
2. 正式继续体验
3. 正式游玩推进
## 7.2 陶泥儿主测试/读档会话
## 7.2 百梦主测试/读档会话
陶泥儿主测试/读档会话用于:
百梦主测试/读档会话用于:
1. 编辑器内测试体验
2. 指定存档加载

View File

@@ -67,8 +67,6 @@ Admin Web
`visible=false` 会让创作中心不展示对应入口;`open=false` 会让前端展示锁定态,并让 api-server 熔断对应玩法创作 / 运行态 API。隐藏入口但仍保留既有作品号、广场详情或试玩链路时应只关闭 `visible`,不要关闭 `open`
当前默认配置中,`visual-novel` 暂时从创作页隐藏并关闭入口,默认种子为 `visible=false``open=false`。如果后续只想恢复已发布作品试玩而不恢复创作入口,需要先明确 API 熔断范围,再通过后台入口开关调整,不能在前端硬编码恢复模板 Tab。
## 注意
- 前端后台页面只做管理表单,不成为配置事实源。

View File

@@ -70,7 +70,7 @@ Query
- SQL 固定为 `SELECT * FROM {tableName} LIMIT {limit}`SpacetimeDB 2.2 HTTP SQL 不拼 `ORDER BY`
- 用户输入不直接拼入 SQL关键词和条件在 API Server 内存中过滤。
- private 表或 token 不可见时返回后台可读错误信息。
- SpacetimeDB SQL 行和 SATS 值统一转成人可读 JSONOption None 为 nullSome 展开为内部值Timestamp 单元素数组展开为内部值;已知业务枚举列应在 API Server 按表名和列名转换为业务字符串,例如 `profile_recharge_order.kind` 转为 `points` / `membership``profile_recharge_order.status` 转为 `pending` / `paid` / `failed` / `closed` / `refunded`
- SpacetimeDB SQL 行和 SATS 值统一转成人可读 JSONOption None 为 nullSome 展开为内部值Timestamp 单元素数组展开为内部值enum 可保留 tag/name 或原始数组文本
## 前端页面

View File

@@ -2,7 +2,7 @@
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
**Goal:**陶泥儿后台新增“埋点数据”页,展示每条埋点原始事件的详细字段,并支持导出为 Excel 可直接打开的表格文件。
**Goal:**百梦后台新增“埋点数据”页,展示每条埋点原始事件的详细字段,并支持导出为 Excel 可直接打开的表格文件。
**Architecture:** 后端继续由 `api-server` 作为后台 BFF经 SpacetimeDB HTTP SQL 只读查询 `tracking_event`,不改变表结构和 reducer。前端在 `apps/admin-web` 中新增独立路由与页面,页面渲染后端返回的原始明细,并在浏览器侧导出 Excel 兼容的 `.xls` HTML 表格,避免新增依赖。

View File

@@ -45,7 +45,7 @@
修复:
1.`map_password_entry_error(...)` 中补充 `InvalidPublicUserCode`
2. 返回中文错误文案 `陶泥号格式不正确`
2. 返回中文错误文案 `百梦号格式不正确`
### 3.3 `module-custom-world` 的 `Display` 分支未覆盖新字段错误

View File

@@ -37,10 +37,9 @@ GENARRATIVE_LLM_MODEL=
# APIMart / OpenAI 兼容 Responses 文本网关
APIMART_BASE_URL=
APIMART_API_KEY=
APIMART_IMAGE_REQUEST_TIMEOUT_MS=180000
# VectorEngine / Gemini 原生图片 / GPT-image-2 / Suno / Vidu 生成网关
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn
# VectorEngine / GPT-image-2 / Suno / Vidu 生成网关
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.ai
VECTOR_ENGINE_API_KEY=
VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=180000
VECTOR_ENGINE_AUDIO_REQUEST_TIMEOUT_MS=180000
@@ -102,25 +101,11 @@ HYPER3D_MODEL_REQUEST_TIMEOUT_MS / RODIN_MODEL_REQUEST_TIMEOUT_MS
3. 文本 LLM provider 为 `ark` 且未配置 `GENARRATIVE_LLM_BASE_URL` 时,仍回退到 Ark 公开基础 URL。
4. 角色视频 provider 复用 Ark 且未配置 `ARK_CHARACTER_VIDEO_BASE_URL` 时,仍回退到 Ark 公开基础 URL。
5. 具体模型名缺失时不在配置层伪造默认模型,调用到对应能力时由下游配置校验返回缺配置错误。
6. VectorEngine 图片与音频生成只读取 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY`,其中 GPT-image-2 与抓大鹅 Gemini 素材 sheet 图片生成额外读取 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;不复用 `APIMART_*``GENARRATIVE_LLM_*` 或前端变量。拼图 Agent 的生成 action 不做前端自动重试,避免一次点击在上游超时后重复触发外部生图与钱包扣退费;若 VectorEngine 请求达到该超时窗口api-server 返回 `504 Gateway Timeout``error.details.provider``vector-engine`,并保留具体超时 message。
6. VectorEngine 图片与音频生成只读取 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY`,其中 GPT-image-2 图片生成额外读取 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;不复用 `APIMART_*``GENARRATIVE_LLM_*` 或前端变量。
7. 火山引擎语音能力由 `platform-speech` 收口协议帧与上游鉴权,`api-server` 只暴露平台鉴权后的代理路由,不向前端返回任何密钥字段。
8. Hyper3D Rodin Gen-2 使用公开默认 `https://api.hyper3d.com/api/v2`API Key 只读取 `HYPER3D_API_KEY` / `RODIN_API_KEY`,不复用文本 LLM、图片或音频网关密钥。
9. APIMart 当前只保留给创意 Agent 的 `gpt-5` Responses 文本/多模态理解链路;抓大鹅物品素材 sheet、GPT-image-2 图片生成和音频生成都不得读取 APIMart 配置。
10. 本地 `npm run api-server``npm run dev:rust``npm run dev``npm run dev:web` 的环境文件优先级固定为非空外层 shell 变量最高,其后 `.env``.env.local``.env.secrets.local` 逐层覆盖;真实密钥建议放在 `.env.secrets.local`,防止 `.env` 中的空示例值覆盖私密配置。外层 shell 变量如果是空字符串或全空白,不再遮蔽本地 env 文件中的真实值。
11. OSS 客户端只在 `ALIYUN_OSS_BUCKET``ALIYUN_OSS_ENDPOINT``ALIYUN_OSS_ACCESS_KEY_ID``ALIYUN_OSS_ACCESS_KEY_SECRET` 四项齐全时初始化。四项全部缺失表示未启用 OSS部分缺失时 `api-server` 记录 warning 并继续启动,具体上传、换签或读取 generated 私有资产的接口返回 `OSS 未完成环境变量配置`,并在 `error.details.missingEnv` 中列出缺失变量。
12. 抓大鹅 2D 草稿素材生成需要同时具备 VectorEngine 与 OSS 配置VectorEngine Gemini `gemini-3-pro-image-preview` 原生 `generateContent` 负责生成 5x5 物品素材 sheet封面和 `9:16` 背景图走 VectorEngine `/v1/images/generations``gpt-image-2-all` JSON 链路;`1:1` 容器 UI 图走 VectorEngine `/v1/images/edits` multipart 链路,并把 `public/match3d-background-references/pot-fused-reference.png` 作为 `image` part 上传,不能再用 generations `image` 数组弱参考。OSS 负责保存切割后的五视角图片及其它生成图。缺少 VectorEngine 或 OSS 时应通过 `error.details.reason` 向前端暴露具体缺项,不能只显示泛化“服务暂不可用”。素材图、封面图和背景图生成在调用外部生图前必须先预检 OSS避免已消耗外部生图后才发现无法落库。
13. 拼图有参考图且开启 AI 重绘时使用 VectorEngine `POST /v1/images/edits` multipart 接口。若返回 `error sending request for url`,代表后端未收到 HTTP 响应;响应 `details` 会带 `reason``source``connect``body``timeout``endpoint`排查时优先检查服务器网络、DNS、防火墙、代理和参考图大小。拼图图片客户端强制 HTTP/1.1,以降低上游 multipart HTTP/2 连接中断风险。
14. 本地排查 `OSS 未完成环境变量配置` 时必须核对键名是否精确为 `ALIYUN_OSS_ACCESS_KEY_SECRET`。常见误写是把 `OSS` 的首字母 `O` 写成数字 `0`,例如 `ALIYUN_0SS_ACCESS_KEY_SECRET`;该键不会被 `api-server` 读取。
## 本地配置检查
拼图真实生成同时依赖 VectorEngine 与 OSS。触发生成前可先运行
```bash
npm run check:api-server-env
```
该命令只输出配置项是否存在,不打印密钥值。若显示 `ALIYUN_0SS_*`,说明把 `OSS` 的字母 `O` 写成了数字 `0`。修正 env 文件后必须重启 `npm run api-server``npm run dev`,已经运行中的 `api-server` 进程不会自动读取新的环境变量。
9. APIMart 当前只保留给创意 Agent 的 `gpt-5` Responses 文本/多模态理解链路GPT-image-2 图片生成不得读取 APIMart 配置。
10. 本地 `npm run api-server``npm run dev:rust``npm run dev` 的环境文件优先级固定为外层 shell 变量最高,其后 `.env``.env.local``.env.secrets.local` 逐层覆盖;真实密钥建议放在 `.env.secrets.local`,防止 `.env` 中的空示例值覆盖私密配置。
## 示例文件

View File

@@ -1,8 +1,8 @@
# 资产操作点消耗接入方案
# 资产操作点消耗接入方案
## 背景
当前点钱包余额、充值流水与邀请奖励已经收口到 `server-rs/crates/spacetime-module/src/runtime/profile.rs`。资产图片生成和作品发布由 Axum API 调用外部模型或写入业务状态SpacetimeDB reducer/procedure 不能直接执行外部网络生成,因此计费需要拆成两层:
当前点钱包余额、充值流水与邀请奖励已经收口到 `server-rs/crates/spacetime-module/src/runtime/profile.rs`。资产图片生成和作品发布由 Axum API 调用外部模型或写入业务状态SpacetimeDB reducer/procedure 不能直接执行外部网络生成,因此计费需要拆成两层:
- SpacetimeDB 负责钱包余额和流水的原子变更。
- Axum 资产操作服务负责在执行业务资产操作前扣费,并在生成、持久化或发布失败时补偿退款。
@@ -20,47 +20,28 @@
- Big Fish Agent 动作 `big_fish_publish_game`
- Puzzle Agent 图片生成动作 `compile_puzzle_draft``generate_puzzle_images`
- Puzzle Agent 动作 `publish_puzzle_work`
- Match3D / 抓大鹅草稿生成动作 `match3d_compile_draft`
- 拼图 / 抓大鹅结果页 UI 背景与抓大鹅批量新增物品素材;背景音乐和点击音效生成入口当前临时关闭,不进入计费范围
暂不接入以下入口:
- 旧资产工坊角色主形象/动作生成接口:当前仍使用 `asset-tool` 作为兼容归属,无法确认真实用户。
- 手动上传封面:不调用外部生成模型,不消耗点。
- 手动上传封面:不调用外部生成模型,不消耗点。
- 自定义世界草稿自动补图链路:属于后台补全流程,避免一次用户操作触发多笔不可预期扣费。
- 文本实体、NPC 生成:本次需求聚焦图片资产和发布资产操作,首期只覆盖可明确归属的入口。
## 计费规则
- 每次可计费资产操作消耗 `1`点。
- 例外Match3D / 抓大鹅草稿生成是一次完整草稿外部生成动作,固定消耗 `10` 枚泥点;流水仍复用 `asset_operation_consume` / `asset_operation_refund``asset_kind = match3d_draft_generation`
- 例外:拼图 / 抓大鹅 UI 背景重新生成固定消耗 `2` 枚泥点。
- 例外:抓大鹅结果页批量新增物品素材按实际可新增物品名计费,每 `5` 个消耗 `2` 枚泥点,不足 `5` 个向上按 `5` 个计。重复名称、作品中已有名称和超过容量上限的名称不进入计费数量。
- 每次可计费资产操作消耗 `1`点。
- 图片生成和作品发布都按资产操作计费;余额不足时禁止继续执行。
- 在调用外部图片生成或发布 mutation 前预扣,余额不足时直接返回业务错误,不继续调用后续资产操作。
- 如果图片生成、远程下载、OSS 写入、资产记录确认或发布 mutation 失败,资产操作服务自动发起同额退款。
- 如果退款失败,原始错误仍返回给调用方,同时服务端日志记录退款失败,便于后续人工核对。
## 前端确认交互
所有前端可见且会消耗泥点的按钮,点击后必须先弹出独立确认面板,面板标题使用 `确认消耗泥点`,正文只展示本次消耗数量,例如 `消耗 2 泥点`。用户点击 `确定` 后才允许调用后端扣费动作;点击 `取消` 或关闭面板不得触发接口。
2026-05-14 当前已覆盖的草稿页入口包括:
- 拼图入口 `AI重绘=true``生成拼图游戏草稿``2` 泥点;`AI重绘=false` 直接使用上传图,不显示泥点确认。
- 拼图结果页关卡 `生成画面` / `重新生成画面``2` 泥点。
- 拼图结果页 `素材配置 > UI``生成UI背景` / `重新生成``2` 泥点。
- 拼图结果页发布按钮:`1` 泥点,发布确认面板必须显示本次消耗数量。
- 抓大鹅入口 `生成抓大鹅草稿``10` 泥点。
- 抓大鹅结果页 `素材配置 > 物品` 的批量新增与批量重新生成:按实际计费数量展示动态泥点数。
- 抓大鹅结果页 `素材配置 > UI``素材配置 > 容器形象``重新生成`:各 `2` 泥点。
## 钱包流水
公开两个流水来源类型,统一覆盖“资产生成”和“资产发布”这两类资产操作。流水金额由具体资产操作成本决定,不再假定所有资产操作都是 `1` 枚泥点
公开两个流水来源类型,统一覆盖“资产生成”和“资产发布”这两类资产操作:
- `asset_operation_consume`:资产操作预扣,`amount_delta = -points_cost`
- `asset_operation_refund`:资产操作失败退款,`amount_delta = +points_cost`
- `asset_operation_consume`:资产操作预扣,`amount_delta = -1`
- `asset_operation_refund`:资产操作失败退款,`amount_delta = +1`
`wallet_ledger_id` 由 Axum 传入,格式:

View File

@@ -40,12 +40,12 @@ HTTP status server error (503 Service Unavailable)
### 3.1 认证快照同步改为非阻断
`AppState::sync_auth_store_snapshot_to_spacetime` 保持导出本地认证快照,但运行期会直接调用 `import_auth_store_snapshot_json` 覆盖导入 SpacetimeDB 正式认证表,不再刷新 `auth_store_snapshot/default`;当远端导入失败时只写 warn 日志并返回 `Ok(())`
`AppState::sync_auth_store_snapshot_to_spacetime` 保持导出本地快照、写入 SpacetimeDB、导入正式表的顺序但当远端写入或导入失败时只写 warn 日志并返回 `Ok(())`
设计边界:
1. 当前认证请求的即时真相源是本地 `auth_store`
2. SpacetimeDB 正式认证表用于跨进程恢复`auth_store_snapshot/default` 只保留为历史迁移和兜底恢复记录
2. SpacetimeDB 认证快照用于跨进程恢复和正式表投影
3. 远端库挂起或网络异常只降级远端恢复能力,不回滚已经成功的登录、刷新、退出和资料更新。
### 3.2 Vite 补齐创作接口代理
@@ -98,25 +98,10 @@ npm run dev:web
1. `GET http://127.0.0.1:3000/api/auth/login-options` 返回 `["phone","password"]`
2. `GET http://127.0.0.1:3000/api/runtime/match3d/gallery` 返回 `{"items":[]}`,不再返回 SpacetimeDB 503。
3. 未登录请求 `POST http://127.0.0.1:3000/api/creation/match3d/sessions` 返回 `401`,说明同源请求已进入 Rust 鉴权层,不再被 Vite `404`
4. 隔离端口指向挂起的远端库并使用 mock 短信时,手机号验证码登录返回 `200` 和 token日志只记录“认证快照入 SpacetimeDB 正式表失败,当前认证流程继续”。
4. 隔离端口指向挂起的远端库并使用 mock 短信时,手机号验证码登录返回 `200` 和 token日志只记录“认证快照入 SpacetimeDB 失败,当前认证流程继续”。
## 6. 后续
1. 远端 `xushi-p4wfr` 仍需恢复数据库挂起状态,否则对应玩法 procedure 仍不可用。
2. 本地开发如只为体验抓大鹅,可继续使用本地 SpacetimeDB 链路。
3. 认证快照同步失败会影响进程重启后的远端恢复完整性,需要在目标库恢复后重新完成一次成功同步。
## 7. 2026-05-13 补充:服务暂不可用的分层排查
抓大鹅生成页只看到“服务暂不可用”时,不应先回退旧 3D / Rodin 链路,应按 2D 素材生成链路逐层定位:
1. 前端通用 API 错误展示必须读取 `error.details.reason`。VectorEngine、OSS 等配置缺失类错误常把具体原因写在 `details.reason`,如果只读 `details.message`,用户只能看到泛化的“服务暂不可用”。
2. `api-server` 启动不应被 OSS 半配置阻断。`ALIYUN_OSS_BUCKET` / `ALIYUN_OSS_ENDPOINT` 已配置但 `ALIYUN_OSS_ACCESS_KEY_ID` / `ALIYUN_OSS_ACCESS_KEY_SECRET` 缺失时,服务应记录 warning 并跳过 OSS 客户端初始化;需要上传或读取 generated 私有资产的接口继续返回 `OSS 未完成环境变量配置`,并通过 `details.missingEnv` 明确缺少哪几项。
3. 启动阶段从 SpacetimeDB 恢复认证快照只能降级远端恢复能力,不能长期卡住 `/healthz`。本地库未发布、连接后立即 close 或远端库挂起时,`api-server` 应在启动恢复超时后使用本地 `auth_store` 继续进入监听。
4. 抓大鹅真实生成仍依赖两组私密配置:`VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` 用于 `gpt-image-2-all` 生成 1K 素材图;完整 `ALIYUN_OSS_*` 四件套用于上传切割后的 `generated-match3d-assets` 五视角图片。缺任一组都应返回明确 `details.reason`;抓大鹅素材、封面和背景生成在调用 VectorEngine 前先预检 OSS不应先消耗生图调用再失败也不应恢复 GLB 生成。
验证时以实际 `GENARRATIVE_API_PORT` 为准;本地 `.env.local` 可能覆盖脚本默认 `3100`。例如当前本地端口为 `8082` 时,应请求:
```powershell
Invoke-WebRequest -UseBasicParsing http://127.0.0.1:8082/healthz
```

View File

@@ -6,9 +6,8 @@
落地口径:
- `user_account``auth_identity``refresh_session` 作为 SpacetimeDB 中的正式认证持久化表。
- `auth_store_projection_meta` 只记录正式认证表最近一次由认证快照导入的时间,不保存用户快照内容。
- API 启动时优先从正式表导出兼容 `module-auth` 的认证快照,再恢复到内存认证服务。
- 运行期认证变更仍先复用现有 `module-auth` 逻辑生成一致快照,随后调用 `import_auth_store_snapshot_json` 直接覆盖导入正式表;不再继续刷新 `auth_store_snapshot/default`
- 运行期认证变更仍先复用现有 `module-auth` 逻辑生成一致快照,随后同步快照并导入正式表,保证正式表与快照一致
- 本阶段不重写登录、刷新、登出内部业务规则,避免在 JWT、refresh rotation、微信绑定合并等复杂语义中引入行为漂移。
## 2. 非目标
@@ -22,7 +21,7 @@
### 3.1 启动恢复
1. API 调用 `export_auth_store_snapshot_from_tables`
2. 若正式表已有用户、身份或会话数据,则返回兼容 `module-auth` 的 JSON 快照,并带上 `auth_store_projection_meta/default.updated_at`
2. 若正式表已有用户、身份或会话数据,则返回兼容 `module-auth` 的 JSON 快照。
3. API 用 `InMemoryAuthStore::from_snapshot_json` 恢复认证服务。
4. 若正式表为空或调用失败,则回退到 Stage 1 的 `auth_store_snapshot`
5. 若 Stage 1 也不可用,则回退本地 JSON 热修复文件。
@@ -30,10 +29,9 @@
### 3.2 运行期同步
1. 登录、刷新、登出等路径继续调用当前内存认证服务。
2. 每次认证状态变更后导出当前内存认证快照 JSON
3. API 调用 `import_auth_store_snapshot_json`,在同一 SpacetimeDB transaction 中清空并重建 `user_account/auth_identity/refresh_session`,同时更新 `auth_store_projection_meta/default.updated_at`
4. `upsert_auth_store_snapshot``import_auth_store_snapshot` 保留为旧库迁移入口,只服务 `auth_store_snapshot/default` 到正式认证表的历史导入,不作为运行期同步路径
5. 远端导入失败只记录 warn 并继续当前认证响应,避免远端库挂起时回滚已经成功的登录、刷新、退出和资料更新。
2. 每次认证状态变更后调用 `upsert_auth_store_snapshot`
3. 快照写入成功后调用 `import_auth_store_snapshot`,覆盖导入正式表
4. 导入失败时返回错误,避免用户误以为状态已经持久化
## 4. 数据重建规则

View File

@@ -23,7 +23,7 @@ Stage 1 已把 Rust 鉴权快照同步到 SpacetimeDB 的 `auth_store_snapshot`
1. `POST /api/auth/refresh` 改写 `refresh_session` 表。
2. 登录成功写 `user_account/auth_identity/refresh_session`
3. `logout/logout-all/revoke-session` 改写细粒度表。
4. `auth_store_snapshot` 退化为迁移备份;运行期若仍复用内存认证快照,也应通过 `import_auth_store_snapshot_json` 直接导入正式认证表,不再刷新 `auth_store_snapshot/default`
4. `auth_store_snapshot` 退化为迁移备份。
## 3. 表设计落地口径
@@ -34,7 +34,7 @@ Stage 1 已把 Rust 鉴权快照同步到 SpacetimeDB 的 `auth_store_snapshot`
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `user_id` | `String` | 主键。 |
| `public_user_code` | `String` | 公开陶泥号。 |
| `public_user_code` | `String` | 公开百梦号。 |
| `username` | `String` | 当前账号用户名。 |
| `display_name` | `String` | 展示名。 |
| `phone_number_masked` | `Option<String>` | 脱敏手机号。 |
@@ -94,3 +94,4 @@ Stage 1 已把 Rust 鉴权快照同步到 SpacetimeDB 的 `auth_store_snapshot`
2. Rust bindings 已刷新。
3. `spacetime-client` 暴露导入 procedure facade。
4. `api-server/spacetime-client/module-auth` 定向检查通过。

View File

@@ -1,202 +0,0 @@
# 宝贝爱画本地 Demo 运行态实现方案 2026-05-13
## 1. 范围
本方案落地寓教于乐独立关卡:
```text
baby-love-drawing / 宝贝爱画
```
当前范围只做本地 Demo 闭环:
1. 寓教于乐频道默认关卡卡片;
2. 独立运行态;
3. mocap 与开发者调试输入;
4. Canvas 绘制和擦除;
5. image-2 绘画魔法后端代理;
6. localStorage 本地保存;
7. 直达路由开关保护。
本阶段不接正式持久化表,不新增作品发布、作品号、公开详情或搜索入口。
## 2. 前端接入点
已新增页面阶段:
```text
baby-love-drawing-runtime
```
已新增路由:
```text
/runtime/baby-love-drawing
```
已新增文件:
```text
packages/shared/src/contracts/edutainmentBabyDrawing.ts
src/services/edutainment-baby-drawing/babyDrawingClient.ts
src/components/edutainment-runtime/babyLoveDrawingModel.ts
src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.tsx
server-rs/crates/api-server/src/edutainment_baby_drawing.rs
```
已接入:
1. `src/components/rpg-entry/RpgEntryHomeView.tsx`:寓教于乐频道默认展示宝贝爱画卡片;
2. `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`:启动宝贝爱画运行态;
3. `src/components/platform-entry/platformEntryTypes.ts`:扩展 `SelectionStage`
4. `src/routing/appPageRoutes.ts`:扩展路由;
5. `src/routing/appRoutes.tsx`:直达路由开关保护;
6. `src/index.css`:补齐寓教于乐默认关卡卡片和宝贝爱画运行态样式;
7. `server-rs/crates/api-server/src/app.rs`:挂载绘画魔法后端路由。
## 3. 契约
契约放在:
```text
packages/shared/src/contracts/edutainmentBabyDrawing.ts
```
核心字段:
1. `templateId = "baby-love-drawing"`
2. `templateName = "宝贝爱画"`
3. `originalImageSrc` 保存原始画布图;
4. `magicImageSrc` 保存 image-2 魔法图,可为 `null`
5. `strokeTrace` 保存画笔和橡皮轨迹;
6. `saveMode = "original-only" | "original-and-magic"` 记录保存结果。
## 4. 运行态模型
运行态状态:
```text
drawing
finished
magicPending
magicReady
saved
```
工具:
```text
brush
eraser
```
颜色:
```text
红、橙、黄、绿、青、蓝、紫
```
按钮悬停:
1. 颜色选择只接受左手悬停,阈值 1500ms
2. 按钮选择接受任一手悬停,阈值 2000ms
3. 工具切换只接受右手在工具区域握拳。
4. 画笔 / 橡皮光标位置只接受右手坐标;左手缺帧或左手移动不得重置、替换或驱动画笔位置。
5. 左手需要显示独立位置指示器,帮助用户确认当前是否悬停在目标颜色上;该指示器只表达左手位置,不参与画笔 / 橡皮操作。
6. 本地 mocap handedness 当前按摄像头视角输出,宝贝爱画运行态消费前需要换算为用户身体视角:`rightHand` 作为用户左手,`leftHand` 作为用户右手。键鼠调试输入不做该换算。
7. 真实硬件短暂缺失某只手时,显示层保留上一帧位置约 320ms 并做轻微坐标平滑;绘制层仍只在当前帧确认用户右手存在时生效。
8. 为避免左手抢画笔,本关不做动态 handedness 换手纠正;`rightHand` 永远只进入用户左手选色通道,`leftHand` 永远只进入用户右手画笔通道。若硬件侧 handedness 继续抖动,宁可右手画笔短暂停住,也不允许左手驱动画笔。
9. 右手画笔通道增加单帧最大位移门禁;若 camera-left 候选点相对上一帧右手位置出现不合理大跳,判定为不可信帧,只保留上一帧光标并停止绘制。
## 5. Canvas 绘制
画板使用 DOM Canvas。
绘制规则:
1. 右手在画板内且状态为 `grab` 时生效;
2. 工具为 `brush` 时,以当前颜色绘制连续线段;
3. 工具为 `eraser` 时,以 `destination-out` 擦除;
4. 右手状态为 `open_palm` 或离开画板时结束当前笔画;
5. 当前帧没有右手坐标时只结束当前笔画,不把左手坐标用于绘制、擦除或光标定位;
6. 每条笔画记录工具、颜色、点位和时间。
## 6. 绘画魔法
前端 service
```text
createBabyDrawingMagicImage(payload)
```
后端接口:
```text
POST /api/creation/edutainment/baby-love-drawing/magic
```
请求体:
```json
{
"originalImageSrc": "data:image/png;base64,...",
"strokeTrace": []
}
```
响应体:
```json
{
"magicImageSrc": "data:image/png;base64,...",
"generationProvider": "vector-engine-gpt-image-2",
"prompt": "..."
}
```
后端使用 VectorEngine `gpt-image-2-all`,把原始画布图作为参考图,生成绘本风格图片。
本地未配置 VectorEngine 或接口失败时,前端允许提示错误并保留原图保存能力;不得把失败伪装成正式魔法图。
后端接入约束:
1. 接口需要 Bearer 鉴权;
2. 请求体限制为 8MB
3. `originalImageSrc` 只接受图片 Data URL
4. 笔触数量上限为 600 条;
5. 上游参考图字段使用 VectorEngine 统一契约 `image`
6. 关闭入口时,`creation_entry_config` 路由熔断可识别 `baby-love-drawing`
## 7. 本地保存
本地保存使用:
```text
localStorage key = genarrative.edutainmentBabyDrawing.localDrawings.v1
```
保存策略:
1. 魔法生成前保存:`saveMode = "original-only"`,只保存 `originalImageSrc`
2. 未保存原图直接生成魔法后保存:`saveMode = "original-and-magic"`,保存 `originalImageSrc``magicImageSrc`
3. 保存后展示“再画一张”和“返回”。
## 8. 验收命令
```bash
npm run test -- src/components/edutainment-runtime/babyLoveDrawingModel.test.ts src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.test.tsx src/services/edutainment-baby-drawing/babyDrawingClient.test.ts src/routing/appRoutes.test.ts
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
npx eslint src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.tsx src/components/edutainment-runtime/babyLoveDrawingModel.ts src/services/edutainment-baby-drawing/babyDrawingClient.ts src/routing/appRoutes.tsx --ext .ts,.tsx --max-warnings 0
npm run typecheck
npm run check:encoding
```
## 9. 已覆盖测试
1. `src/components/edutainment-runtime/babyLoveDrawingModel.test.ts`:颜色 / 按钮悬停阈值、坐标归一化、笔触追加;
2. `src/components/edutainment-runtime/BabyLoveDrawingRuntimeShell.test.tsx`:画板、七色、画笔 / 橡皮、完成保存、返回按钮、左手位置指示器、mocap 摄像头视角到用户身体视角换算、左手输入不替换画笔光标位置、左手短暂缺帧不闪烁、用户左手不能抢占右手画笔、camera-left 大跳不接入画笔;
3. `src/services/edutainment-baby-drawing/babyDrawingClient.test.ts`:原图保存、原图加魔法图保存、后端魔法接口请求;
4. `src/routing/appRoutes.test.ts``/runtime/baby-love-drawing` 开启可达、关闭回落主应用;
5. `server-rs/crates/api-server/src/edutainment_baby_drawing.rs` 内部单测prompt、Data URL 校验、PNG 输出和轨迹范围摘要;
6. `server-rs/crates/api-server/src/creation_entry_config.rs` 路由映射单测:确认后端熔断可识别 `baby-love-drawing`

View File

@@ -30,15 +30,13 @@ baby-object-match
宝贝识物
```
工程接入文件:
文件:
1. `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
1. `src/config/newWorkEntryConfig.ts`
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` 开关;开关关闭时,创作类型弹层不展示 `宝贝识物`,创作页作品架不展示本地宝贝识物草稿或已发布作品卡,公开发现、搜索、详情、作品号和浏览历史也继续完全不可见。
新增阶段:
@@ -64,8 +62,7 @@ packages/shared/src/contracts/edutainmentBabyObject.ts
2. `BabyObjectMatchDraft.templateName = "宝贝识物"`
3. `BabyObjectMatchDraft.themeTags` 必须包含精确 `寓教于乐`
4. `BabyObjectMatchItemAsset.generationProvider` 首版允许为 `vector-engine-gpt-image-2``placeholder`
5. `BabyObjectMatchDraft.visualPackage` 可选承载背景环境、UI 装饰框、礼物盒、篮子和烟雾弹出特效五类视觉资源;
6. `BabyObjectMatchPublishRequest.draft.themeTags` 发布前必须归一化补齐 `寓教于乐`
5. `BabyObjectMatchPublishRequest.draft.themeTags` 发布前必须归一化补齐 `寓教于乐`
## 4. Service 边界
@@ -79,64 +76,9 @@ 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)`
3. `publishBabyObjectMatchWork(payload)`
当前后端正式作品持久化接口未在本线程扩表落地,因此 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)` 补齐资源;补齐失败时保留在结果页并展示错误。
后续正式作品持久化接入时,应补齐:
当前后端正式接口未在本线程扩表落地,因此 service 先走本地 Demo 存储,并把 asset 结果标记为 `placeholder`。后续后端接入时,应替换为:
```text
POST /api/creation/edutainment/baby-object-match/drafts
@@ -146,25 +88,6 @@ 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 边界
工作台只展示两个必填输入和生成按钮。
@@ -184,37 +107,27 @@ 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. `waiting`:礼物盒关闭,等待任意手抬起
2. `active`:当前物品停留在屏幕中央
3. `correct`:展示“真棒”反馈,成功次数加 1
4. `wrong`:展示“再想一想吧”反馈,当前物品回到中央
5. `complete`:成功次数达到 20展示“恭喜你小朋友”和按钮。
动作输入:
1. 左手连续横向移动达到阈值:将当前物品送入左侧篮子
2. 手连续横向移动达到阈值:将当前物品送入侧篮子
1. 任意手完成一次 `open_palm -> grab` 抓握序列:打开礼物盒并生成当前物品
2. 手连续横向移动达到阈值:将当前物品送入侧篮子
3. 右手连续横向移动达到阈值:将当前物品送入右侧篮子。
运行态直接通过 `useMocapInput` 消费本地 mocap WebSocket `/stream`。选篮只使用明确 `leftHand``rightHand` 的连续横向轨迹阈值,不再通过 `wave_left_hand``wave_right_hand``wave` 等动作名触发;侧别为 `unknown` 的手部轨迹也不参与选篮,以避免多套判定误命中和连续误触发。动作判定只在 `active` 阶段开放,礼盒入场、礼盒打开、物品出现、正确反馈和错误反馈阶段收到的动作包必须清空轨迹并忽略,不允许跨阶段补判定。当前本地 mocap 输出的 handedness 按摄像头视角标记,宝贝识物运行态必须先换算为用户身体视角:`rightHand` 轨迹映射玩家左手并进入左侧篮子,`leftHand` 轨迹映射玩家右手并进入右侧篮子。草稿试玩、发布后正式体验和热身关后的本地 Demo 都复用同一个运行态,因此三条入口都必须具备同一套动作控制能力。
运行态直接通过 `useMocapInput` 消费本地 mocap WebSocket `/stream`。选篮只使用明确 `leftHand``rightHand` 的连续横向轨迹阈值,不再通过 `wave_left_hand``wave_right_hand``wave` 等动作名触发;侧别为 `unknown` 的手部轨迹也不参与选篮,以避免多套判定误命中和连续误触发。当前本地 mocap 输出的 handedness 按摄像头视角标记,宝贝识物运行态必须先换算为用户身体视角:`rightHand` 轨迹映射玩家左手并进入左侧篮子,`leftHand` 轨迹映射玩家右手并进入右侧篮子。草稿试玩、发布后正式体验和热身关后的本地 Demo 都复用同一个运行态,因此三条入口都必须具备同一套动作控制能力。
开发者调试输入:
1. 鼠标左键按下并拖动:映射左手轨迹,抬起后将当前物品送入左侧篮子
2. 鼠标键按下并拖动:映射手轨迹,抬起后将当前物品送入侧篮子
1. `F`:映射任意手抬起,打开礼物盒并生成当前物品
2. 鼠标键按下并拖动:映射手轨迹,抬起后将当前物品送入侧篮子
3. 鼠标右键按下并拖动:映射右手轨迹,抬起后将当前物品送入右侧篮子。
运行态不得新增计时、失败次数、分数、体力或难度递增规则。
@@ -241,7 +154,6 @@ src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.tsx
```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

View File

@@ -4,7 +4,7 @@
### 1.1 背景
`bark-battle` / “汪汪声浪大作战”是一个浏览器 2D 声控狗叫对战玩法。玩家通过麦克风发出狗叫声,浏览器 runtime 根据音量峰值、有效声浪触发次数与节奏推动顶部红蓝能量条;每局默认 30 秒;结束后按能量条偏向判定胜负或平局。
`bark-battle` / “汪汪声浪大作战”是一个浏览器 2D 声控狗叫对战玩法。玩家通过麦克风发出狗叫声,浏览器 runtime 根据音量峰值、有效声次数与节奏推动顶部红蓝能量条;每局默认 30 秒;结束后按能量条偏向判定胜负或平局。
现有前端方案 `docs/technical/BARK_BATTLE_2D_RUNTIME_TECHNICAL_PLAN_2026-05-11.md` 已覆盖 Phaser / TypeScript / Vite / Web Audio / DOM HUD 的 runtime 落地方式,并明确不覆盖后端表结构、成绩持久化、作品发布、广场接入与实时多人协议。因此需要单独补充后端 DDD 技术方案,避免前端 runtime 在接入平台作品、正式游玩埋点、成绩、排行榜和发布闭环时承接不属于表现层的业务真相。
@@ -44,80 +44,26 @@ MVP 明确不做:
## 2. 玩法接入级别建议
### 2.1 第二阶段范围:平台作品闭环
### 2.1 推荐首版闭环
第二阶段已明确为“Bark Battle 平台作品闭环”,不是单纯玩法表现深化。目标是让 bark-battle 成为 Genarrative 的正式 play type并完成从轻创作配置、发布、正式 runtime、run start / finish、单局结果持久化、个人历史成绩、作品统计到最小排行榜的闭环
建议先支持“本地 runtime + 可发布配置化作品 + 单局结果记录 / 可选排行榜的闭环
Phase 2 的作品配置边界是“轻创作配置作品”:创作者可以配置标题、描述、主题/背景预设、狗狗皮肤预设、难度预设和排行榜开关;不得直接配置单局时长、有效声浪阈值、`minBarkGapMs`、AI 对手细粒度参数、分数公式或反作弊阈值。难度预设只影响 AI 对手行为强度,不影响有效阈值、声浪冷却、单局时长或分数公式;排行榜必须按 `workId + difficultyPreset + rulesetVersion` 分榜,避免不同难度和不同规则版本混排
建议先支持“本地 runtime + 可发布配置化作品 + 单局结果记录 + 个人历史成绩 / 作品统计 / 最小排行榜”的闭环:
1. 创作者从玩法选择进入 bark-battle 后创建草稿,通过单页轻配置表单 + 预览卡片配置标题、描述、主题/背景预设、狗狗皮肤预设、难度预设和排行榜开关。
1. 创作者创建 bark-battle 草稿,配置标题、描述、狗狗主题背景、难度、单局时长、音量阈值、AI 对手参数和排行榜开关
2. 发布为稳定作品 ID`playTypeId = "bark-battle"`
3. 玩家从作品详情页 CTA、广场/作品卡片、我的作品/个人作品架进入正式 runtime前端使用稳定作品 ID 获取发布态 runtime config。
3. 玩家从作品页或广场进入 runtime前端获取发布态 runtime config。
4. 玩家授权麦克风后在本地完成 30 秒声控对战。
5. 前端提交单局 finish 请求,只上传派生指标,例如峰值、有效声浪触发次数、节奏命中、最终能量、客户端结果摘要等。
6. 后端校验 work、config version、ruleset version、difficulty preset、run token、时长、派生指标范围和权限后,生成服务端裁决的 run result / score summary。
7. 写入个人历史成绩与最小作品统计投影
8. 若作品开启排行榜且后端裁决 `serverResult = player_win`,则写入可投影的 leaderboard 记录;排行榜首版只做最小排序与展示,不引入赛季、段位或复杂反作弊,并按 `workId + difficultyPreset + rulesetVersion` 分榜
9. 正式作品级游玩埋点统一写 `work_play_start`,其中 `scope_kind=work``scope_id=稳定作品 ID`metadata 包含 `playType``workId``sourceRoute``userId`
### 2.2.1 难度预设与排行榜分榜
Phase 2 只允许三个难度预设:`easy``normal``hard`。难度预设只能影响 AI 对手推动力曲线和 AI 声浪节奏;不得影响单局时长、有效声浪阈值、`minBarkGapMs`、分数公式或反作弊阈值。排行榜记录和查询必须带上 `difficultyPreset``rulesetVersion`,以 `workId + difficultyPreset + rulesetVersion` 作为分榜维度。
### 2.2.2 单局结果后端裁决
Phase 2 不信任前端提交的最终胜负和正式分数。前端 `finish` 只提交不可还原原始音频的派生指标:`runId``workId``configVersion``rulesetVersion``difficultyPreset``clientStartedAt``clientFinishedAt``durationMs``triggerCount``maxVolume``averageVolume``finalEnergy``comboMax``clientResult`,以及可选的 `sampleDigest`。其中 `clientResult` 只用于 debug/对账,不进入正式结果或排行榜。
后端必须校验 run 由 start 创建且未 finish、run token 匹配、work/config/ruleset/difficulty 与 start 时一致、duration 处于合理窗口、triggerCount 不超过 `durationMs / minBarkGapMs + tolerance`、音量/能量/连击字段在合法范围内。后端生成 `serverResult``scoreSummary``leaderboardScore``antiCheatFlags`,排行榜只使用后端裁决后的胜利局成绩。
### 2.2.3 排行榜排序口径
Phase 2 排行榜只收录 `serverResult = player_win` 且未被反作弊规则拒绝的单局结果;平局和失败仍进入个人历史成绩与作品统计,但不进入排行榜。`leaderboardScore` 由后端规则集生成,排序优先级为:`finalEnergy` 降序、`triggerCount` 降序、`maxVolume` 降序、`durationMs` 越接近标准局时长越优、`finishedAt` 越早越优。
### 2.2.4 作品统计投影口径
Phase 2 的作品统计是最小后端投影,不从排行榜反推。`playStartCount` 在 start run 成功时计入一次,并对齐 `work_play_start` 埋点;`finishCount` 在 finish 被后端接受时计入一次,包含胜利、平局和失败。`accepted_with_flags` 可以计入 `finishCount`,但必须同时计入 `flaggedCount`;未 start 成功、run token 不合法、重复 finish、被后端 rejected 的结果不计入 `finishCount`
作品统计字段首版包含:`playStartCount``finishCount``winCount``drawCount``lossCount``flaggedCount``leaderboardEntryCount``bestLeaderboardScore``bestFinalEnergy``averageFinalEnergy``updatedAt`。Phase 2 不做 DAU/留存、按小时曲线、原始音频分析或每玩家每天聚合统计。
### 2.2.5 个人历史成绩口径
Phase 2 的个人历史成绩由“最近记录列表 + 个人最佳摘要”组成,并且只允许本人查询。后端可以保存每次被接受的 finish 记录,但首版查询接口只暴露默认最近 20 条记录,可按 `workId``difficultyPreset` 过滤;最近记录包含胜利、平局、失败和是否 flagged但不展示详细反作弊原因。
个人最佳摘要按 `userId + workId + difficultyPreset + rulesetVersion` 聚合,字段包含 `bestLeaderboardScore``bestFinalEnergy``bestTriggerCount``bestMaxVolume``winCount``finishCount``lastPlayedAt`。失败、平局和 flagged 历史不对其他玩家公开排行榜只展示公开入榜的胜利成绩。Phase 2 不做无限滚动完整历史、每日/每周曲线、好友对比或普通玩家可见的详细反作弊说明。
### 2.2.6 正式作品入口闭环
Phase 2 必须接入 Bark Battle 正式作品入口闭环,但不新增独立专区、活动页、挑战分享页、好友邀请或多人房间入口。入口范围包括:创作入口/玩法选择中出现 `bark-battle`,进入单页轻配置表单 + 预览卡片;作品详情页 CTA 点击“开始游玩”进入正式 runtime广场/作品卡片可以展示、打开详情并开始游玩;我的作品/个人作品架能看到作者发布的 Bark Battle 作品runtime 路由使用稳定作品 ID 并从后端发布态 config 拉取配置。
正式 run start 成功后必须写 `work_play_start`,其中 `scope_kind=work``scope_id=稳定作品 ID`metadata 至少包含 `playType=bark-battle``workId``sourceRoute``userId`。内部试玩入口可以作为开发调试保留,但不得作为 Phase 2 正式入口。
### 2.2.7 轻配置编辑流程
Phase 2 的创作编辑形态是“单页轻配置表单 + 预览卡片”,不是多步骤向导、拖拽编辑器或完整规则编辑器。表单字段包含:标题(必填)、简介(选填)、主题/背景预设(必填枚举)、狗狗皮肤预设(必填枚举)、难度预设(必填,默认 `normal`)、排行榜开关(默认开启)。
交互流程创作者从玩法选择进入后生成草稿在同一页编辑轻配置并查看预览卡片支持保存草稿和发布发布成功后跳转作品详情可从我的作品再次编辑草稿或基于已发布作品创建新版本。Phase 2 不做 AI 生成配置、多步骤 wizard、规则参数编辑、复杂封面编辑、runtime 内嵌预览或大段玩法说明文案。
5. 前端提交单局 finish 请求,只上传派生指标,例如峰值、有效声次数、节奏命中、最终能量、客户端结果摘要等。
6. 后端校验 work、config version、run token、时长、分数范围和权限后,生成服务端认可的 run result / score summary。
7. 若作品开启排行榜,则写入可投影的 leaderboard 记录
8. 正式作品级游玩埋点统一写 `work_play_start`,其中 `scope_kind=work``scope_id=稳定作品 ID`metadata 包含 `playType``workId``sourceRoute``userId`
### 2.2 后续增强路径
第二阶段之后再考虑
后续再考虑多人实时
- Phase 2.1:挑战分享、作品统计面板细化、排行榜体验优化
- Phase 2:排行榜、挑战分享、个人历史成绩、作品统计面板
- Phase 3异步影子对手 / ghost replay但仍不保存原始音频只保存低维派生曲线或聚合指标。
- Phase 4实时多人对战协议需要独立同步模型、房间服务、延迟补偿、断线恢复与更严格反作弊不应混入第二阶段平台作品闭环
## 2.3 Phase 2 技术实施顺序
Phase 2 按“契约和领域规则先行,然后最小纵切,再扩展投影”的顺序实施,避免前端 mock 堆积、后端孤岛或排行榜 UI 先行。
1. 契约与领域规则:补 `shared-contracts` DTO、`module-bark-battle` 纯领域规则、`rulesetVersion` / `difficultyPreset` / score adjudication并先写单测。
2. SpacetimeDB 表与 reducer + api-server BFF落草稿/config/发布态 config、runtime run start / finish、score record、leaderboard entry、work stats projection、personal summary projection、`migration.rs` 与绑定生成。
3. 最小前端纵切:接创作入口、单页轻配置表单、发布到稳定 workId、作品详情 CTA、runtime 拉 config、start / finish 串通、结算展示 `serverResult`
4. 投影与列表体验:接排行榜、个人历史最近记录 + 最佳摘要、作品统计、我的作品/广场卡片适配。
5. 收口验证:把 BDD 场景落到测试,执行编码检查、后端 `/healthz` + API smoke、前端人工验收路径并更新 README/文档。
- Phase 4实时多人对战协议需要独立同步模型、房间服务、延迟补偿、断线恢复与更严格反作弊不应混入 MVP
## 3. DDD 分层设计
@@ -144,7 +90,7 @@ frontend/runtime
- 定义配置版本兼容规则。
- 计算提交结果的派生分数区间与胜负判定是否自洽。
- 计算 `ScoreSummary`、排行榜排序分数、统计指标。
- 定义反作弊基础规则:时长范围、有效声浪触发次数上限、峰值范围、能量范围、提交窗口、run 状态机。
- 定义反作弊基础规则:时长范围、有效声次数上限、峰值范围、能量范围、提交窗口、run 状态机。
不职责:

View File

@@ -170,9 +170,6 @@
3. 位置类状态必须满足“到达绿色圆环并保持 2 秒”。
4. 动作类状态没有最长等待时间。
5. 动作类状态等待 3 秒后可以播放对应引导动画。
6. 每个步骤进入时需要先展示本步骤文字字幕和语音播报入口,约 1 秒后再进入可交互阶段并展示绿色圆环、手势引导等检测提示。
7. 步骤完成后需要先进入完成停顿阶段,当前停顿约 0.8 秒;停顿期间保留完成反馈位置,后续可在该阶段补充完成特效或音效,再切换到下一步骤。
8. 入场等待和完成停顿阶段不消费动作完成判定,避免用户上一步残留动作直接触发下一步。
### 6.3 开发者调试输入
@@ -371,17 +368,6 @@
用户完成挥动左手。
当前本地 mocap 的 handedness 按摄像头视角输出,热身关内需要先换算成用户身体视角再判断:摄像头右侧手对应用户左手。挥动左手不是普通横向轨迹检测,而是用于确认现实环境中用户左侧手臂打开空间足够和安全。
完成条件必须同时满足:
1. 使用用户身体左手轨迹。
2. 手腕在左肩外侧达到最小外展距离。
3. 手腕不能处于自然下垂低位。
4. 最近连续有效帧中,手臂存在足够上下摆动幅度。
5. 最近连续有效帧中,肩膀到手腕向量的角度变化达到阈值。
6. 至少出现一次上下摆动方向变化。
#### 完成反馈
```text
@@ -390,7 +376,7 @@
#### 数据记录
记录用户挥动左手的轨迹、空间包络、角度范围和最大外展距离,保存为该用户对应的行为坐标。
记录用户挥动左手的空间,保存为该用户对应的行为坐标。
---
@@ -412,17 +398,6 @@
用户完成挥动右手。
当前本地 mocap 的 handedness 按摄像头视角输出,热身关内需要先换算成用户身体视角再判断:摄像头左侧手对应用户右手。挥动右手不是普通横向轨迹检测,而是用于确认现实环境中用户右侧手臂打开空间足够和安全。
完成条件必须同时满足:
1. 使用用户身体右手轨迹。
2. 手腕在右肩外侧达到最小外展距离。
3. 手腕不能处于自然下垂低位。
4. 最近连续有效帧中,手臂存在足够上下摆动幅度。
5. 最近连续有效帧中,肩膀到手腕向量的角度变化达到阈值。
6. 至少出现一次上下摆动方向变化。
#### 完成反馈
```text
@@ -431,7 +406,7 @@
#### 数据记录
记录用户挥动右手的轨迹、空间包络、角度范围和最大外展距离,保存为该用户对应的行为坐标。
记录用户挥动右手的空间,保存为该用户对应的行为坐标。
---
@@ -678,21 +653,18 @@
3. 鼠标左键按下并拖动映射左手轨迹。
4. 鼠标右键按下并拖动映射右手轨迹。
5. 空格键映射原地跳跃。
6. 调试输入只在步骤可交互阶段触发步骤完成;步骤入场字幕阶段和完成停顿阶段会忽略完成判定,便于观察节奏和后续补充特效。
当前硬件和动作检测接口接入:
1. 浏览器摄像头视频流已接入舞台背景。
2. 热身关全流程已通过 `src/services/useMocapInput.ts` 接入本地 mocap WebSocket `/stream`;动作数据源状态优先于浏览器背景摄像头状态展示。
3. mocap 包支持从 `general.body.center_norm` 读取身体中心,位置类步骤使用该身体中心更新角色剪影横向位置并完成圆环保持检测。
4. 身体中心横向坐标进入角色剪影前必须做输入稳定化处理:先 clamp 到 `0..1`,再使用小幅死区、低通阻尼和单包最大步长限制,避免硬件噪声造成角色左右误判、画面抽搐或视觉上的忽大忽小。当前实现参数为死区 `0.012`、阻尼系数 `0.28`、单包最大步长 `0.035`;位置保持检测使用稳定化后的角色坐标。
5. 角色剪影渲染需要把水平位移和跳跃表现拆开:外层只负责横向定位,内层资源只负责轮廓图和跳跃位移,避免 `left``transform` 同时抢占导致半透明资源重采样抖动
6. mocap 包支持从 `actions/action/gesture/gestures/event/name/type` 读取动作名,并支持 `hands[]``leftHand/rightHand``left_hand/right_hand` 读取左右手坐标
7. `hands[].landmarks` 存在时优先用手腕和 MCP 点计算掌心中心;掌心点不足时退回 wrist landmark再退回 hand 直出坐标
8. `wave_greeting` 消费左手、右手或未知单手的连续横向挥手轨迹,不再使用 `wave``hand_wave``open_palm`、张手状态或动作名直接完成判定;进入轨迹判定前必须先满足抬手有效区:优先使用 `hands[].landmarks.wrist``general.limb_nodes` 的同侧 `*_elbow` / `*_shoulder` 判断,当前阈值为 `wrist.y <= elbow.y + 0.04`,缺少肘部时使用 `wrist.y <= shoulder.y + 0.08`;缺少同侧肘部和肩膀参考时不允许招呼通过,不再使用身体中心兜底判断抬手。轨迹阈值为至少 5 个连续抬手点,横向 `x` 范围差值不小于 `0.075`,且至少出现 1 次横向方向变化,避免“手刚露出画面”或“手自然下垂抖动”被误判为招手
9. `wave_left_hand``wave_right_hand` 只消费用户身体侧对应手的连续坐标轨迹,不再使用动作名、张手状态或 primary hand 兜底完成判定;本地 mocap handedness 当前按摄像头视角输出,因此用户左手使用 camera-right用户右手使用 camera-left。完成判定必须同时满足对应肩肘腕外展、手腕非自然下垂、连续有效帧、横向范围、上下摆动范围、肩腕角度范围和上下方向变化当前阈值为连续外展点不少于 5 个、横向 `x` 范围不小于 `0.055`、垂直 `y` 范围不小于 `0.08`、肩腕角度范围不小于 `28°`、外展距离不小于 `0.12`、手腕相对肩膀外侧距离不小于 `0.1`;后续以真实体验结果继续调参
10. `jump_once` 消费 `jump/jump_once/hop` 等跳跃动作事件完成。
11. 键盘 `A/D/Space` 与鼠标左右键拖拽仍保留为本地 Demo 调试兜底,不代表正式硬件口径。
4. mocap 包支持从 `actions/action/gesture/gestures/event/name/type` 读取动作名,并支持 `hands[]``leftHand/rightHand``left_hand/right_hand` 读取左右手坐标。
5. `hands[].landmarks` 存在时优先用手腕和 MCP 点计算掌心中心;掌心点不足时退回 wrist landmark再退回 hand 直出坐标
6. `wave_greeting` 可由 `wave/wave_greeting/hand_wave/open_palm` 等动作或 open palm 手势完成
7. `wave_left_hand``wave_right_hand` 优先消费对应左右手动作名;当硬件只持续输出手部坐标时,也可以根据连续手部横向轨迹完成挥手检测
8. `jump_once` 消费 `jump/jump_once/hop` 等跳跃动作事件完成
9. 键盘 `A/D/Space` 与鼠标左右键拖拽仍保留为本地 Demo 调试兜底,不代表正式硬件口径
当前未接入但已保留边界:
@@ -710,17 +682,14 @@
5. 当前已生成并接入以下正式 Demo 资源:
- `public/child-motion-demo/picture-book-grass-stage.png`:默认草地舞台背景。
- `public/child-motion-demo/picture-book-foreground-grass-v2.png`:底部前景草坪条,只覆盖舞台下沿,不作为整块地板拉伸。
- `public/child-motion-demo/picture-book-ground-ring-v3.png`:已按透视绘制的浅蓝与暖黄色地面椭圆指示环,和草地材质做明显区分,CSS 只等比缩放。
- `public/child-motion-demo/picture-book-ground-ring-v2.png`已按透视绘制的地面椭圆指示环CSS 只等比缩放。
- `public/child-motion-demo/picture-book-character-outline-v2.png`:半透明用户角色轮廓,使用独立去背后处理避免内部填充被误删。
- `public/child-motion-demo/picture-book-hud-strip-v2.png`:顶部 HUD 细长软纸条。
- `public/child-motion-demo/picture-book-calibration-strip-v2.png`:右下角五格热身状态条。
- `public/child-motion-demo/picture-book-start-panel-v2.png`:开始按钮背后的轻盈托盘。
- `public/child-motion-demo/picture-book-ui-button-v2.png`:开始按钮绘本风按钮底图。
- `public/child-motion-demo/picture-book-wave-cat-body-guide-v6.png`:招手阶段中央猫咪身体底座资源,按可动纸偶结构只包含猫头、短身体和肩部连接点,不再和旧猫头、胸口或猫爪资源叠加。
- `public/child-motion-demo/picture-book-wave-cat-arm-guide-v6.png`:招手阶段左右独立手臂资源,也用于左右手阶段单手提示;网页用同一拆件镜像复用,并围绕肩部挂点做挥手摆动动画。
6. v2 资源按最终用途拆分CSS 必须按资源原始比例、`aspect-ratio``background-size: contain / auto` 等方式等比使用;禁止把方形面板强行拉伸为 HUD、状态条或地板也禁止把底部草坪扩展成覆盖角色脚下的大色块。
7. 猫咪招手引导资源使用 `cat-guide` 透明后处理:先由 image-2 生成品红底源图,再通过边缘背景连通区域去背,避免把浅粉、淡橘和暖棕主体误删。源图只保存在 `tmp/child-motion-demo-assets/`,正式页面只引用 `public/child-motion-demo/` 下的最终 PNG
8. 若后续补充或重绘资源,应先运行 `npm run assets:child-motion-demo -- --dry-run` 核对 prompt 和输出路径,再使用 `--live --only <asset-id>` 小批量生成;仅调整透明去背、裁切、画布归一或品红边缘时,可用 `npm run assets:child-motion-demo -- --live --postprocess-only --force --only <asset-id>` 复用 `tmp/child-motion-demo-assets/` 中的源图,不额外请求 image-2不得把 `VECTOR_ENGINE_API_KEY`、源图或中间预览图提交到仓库。
7. 若后续补充或重绘资源,应先运行 `npm run assets:child-motion-demo -- --dry-run` 核对 prompt 和输出路径,再使用 `--live --only <asset-id>` 小批量生成;仅调整透明去背、裁切、画布归一或品红边缘时,可用 `npm run assets:child-motion-demo -- --live --postprocess-only --force --only <asset-id>` 复用 `tmp/child-motion-demo-assets/` 中的源图,不额外请求 image-2不得把 `VECTOR_ENGINE_API_KEY`、源图或中间预览图提交到仓库
已执行的定向验证命令:

View File

@@ -43,15 +43,4 @@
1. 创作中心三类作品仍在同一个网格展示。
2. 草稿 / 已发布筛选计数统一从 `CreationWorkShelfItem.status` 读取。
3. 卡片渲染不再直接判断 `publicationStatus` 或不同 works schema 的标题字段。
4. 统一货架按 `updatedAt` 倒序排序,兼容 ISO 字符串和 `seconds.microsZ` 后端时间文本。
5. 作品卡片以 `coverImageSrc` 作为整卡背景;若 `coverImageSrc` 为空,允许从同一作品已有的关卡图、背景图或素材图兜底,避免草稿页退回普通面板视觉。
6. 卡片不展示最后修改时间,`updatedAt` 只参与排序。
7. 现有创作中心交互测试通过。
## 2026-05-14 封面兜底补充
1. 货架视图模型仍只保存作品真实 `coverImageSrc` 或同作品真实素材兜底,不把玩法参考图写进数据模型,避免把 UI 兜底误认为作品资产。
2. `CustomWorldWorkCard``CreationWorkShelfKind``CustomWorldCoverArtwork` 传入本地玩法参考图;`ResolvedAssetImage` 在私有资源换签失败、普通图片 404 或真实封面缺失时使用该参考图作为卡片背景。
3. 兜底背景底色跟随百梦浅粉、暖白和珊瑚色调,不能继续使用深黑或暗蓝渐变作为草稿卡默认视觉。
4. 拼图作品列表摘要必须下发 `levels`,草稿页优先用关卡 `coverImageSrc`,再用选中候选图或最后一张候选图作为真实作品封面兜底。
5. 抓大鹅作品列表摘要必须保留 `generatedBackgroundAsset``generatedItemAssets` 中的 `imageObjectKey``containerImageObjectKey``imageViews[].imageObjectKey`;前端拿到 object key 后统一交给 `ResolvedAssetImage` 换签,不能因为缺少公开 URL 而退回黑卡。
4. 现有创作中心交互测试通过。

View File

@@ -582,7 +582,7 @@ puzzle_creative_level_generation_plan
- Agent 选择理由
- 支持单关卡、多关卡或二者皆可
- 计划关卡数
- 预计积分范围,例如 `预计消耗 8 到 18 点`
- 预计积分范围,例如 `预计消耗 8 到 18 点`
积分范围来自拼图模板协议:

View File

@@ -1,4 +1,4 @@
# 自定义世界草稿场景幕事件与任务字段落地设计2026-04-25
# 自定义世界草稿场景幕事件与任务字段落地设计2026-04-25
## 背景
@@ -37,7 +37,7 @@
- 当前场景的核心任务描述。
- 文本会作为游戏中首次进入某个场景生成章节任务的关键上下文。
- 必须结合场景描述、场景入口钩子、出场角色与 3 幕事件,说明玩家首次进入该场景时要完成什么。
- 世界档案的场景详情页必须直接展示该字段,便于陶泥儿主确认每个场景的默认章节任务。
- 世界档案的场景详情页必须直接展示该字段,便于百梦主确认每个场景的默认章节任务。
### Landmark 生成源字段

View File

@@ -32,8 +32,6 @@ process didn't exit successfully: `server-rs\target\debug\api-server.exe`
主站和后台 Vite 也追加 `--strictPort`,避免默认漂移到 `3001``3103` 等端口后让浏览器继续访问旧页面。
`--skip-spacetime` 是复用既有 SpacetimeDB 宿主的模式。该模式下脚本不会再把 SpacetimeDB 端口纳入可用性漂移;如果传入 `--spacetime-port 3101`,后端就会连接 `http://127.0.0.1:3101`。这可以避免 `3101` 已有 SpacetimeDB 在线时,端口工具误把它当作冲突并改到空闲的 `3102`,导致 api-server 连接空端口后 `/api/creation-entry/config`、作品架和公开图库接口同时返回 `502`
## 排障步骤
PowerShell 查看默认端口占用:
@@ -74,4 +72,3 @@ node scripts/run-bash-script.mjs scripts/dev-rust-stack.sh \
1. `bash -n scripts/dev-rust-stack.sh` 通过。
2. 默认端口被占用时重新运行完整栈,脚本应在 publish 前失败并打印占用进程。
3. 清理占用进程或换端口后,重新启动时不再出现 Vite 端口漂移或 `api-server` `AddrInUse`
4. 复用 SpacetimeDB 时执行 `npm run dev -- --skip-spacetime --skip-publish --spacetime-port 3101`,启动日志里的 `[dev:rust] spacetime:` 应保持为 `http://127.0.0.1:3101`,并且 `GET /api/creation-entry/config` 不应因连接 `3102` 这类空端口而失败。

View File

@@ -408,7 +408,7 @@ Node 侧入口位于:
## 10.2 2026-05-01 新用户注册赠送修正
新注册用户默认获得 `10`点,注册链路通过 SpacetimeDB procedure 写入 `profile_dashboard_state.wallet_balance``profile_wallet_ledger`。流水来源为 `new_user_registration_reward`,流水 ID 固定为 `new-user-registration:{user_id}`,重复调用不重复发放。
新注册用户默认获得 `10`点,注册链路通过 SpacetimeDB procedure 写入 `profile_dashboard_state.wallet_balance``profile_wallet_ledger`。流水来源为 `new_user_registration_reward`,流水 ID 固定为 `new-user-registration:{user_id}`,重复调用不重复发放。
注册赠送、邀请码奖励、充值、兑换码、资产扣费等都属于真实平台钱包流水。用户只要已经存在非 `snapshot_sync` 钱包流水,后续 `runtime_snapshot.game_state.playerCurrency` 不再覆盖 `wallet_balance`,只继续刷新游玩时长和玩过世界,避免首次保存旧运行态货币字段时把注册赠送覆盖成 `0`

View File

@@ -1,15 +1,5 @@
# 抓大鹅草稿素材生成流水线 2026-05-10
## 0. 2026-05-14 临时关闭音频生成
抓大鹅音频生成能力暂时关闭:
1. `match3d_compile_draft` 不再调用 Suno 生成背景音乐,也不再生成点击音效。
2. 结果页 `素材配置` 不再展示 `背景音乐` 子 Tab物品详情面板不再展示点击音效提示词和生成按钮。
3. 批量新增物品只生成 2D 五视角图片,不生成点击音效。
4. 通用 `/api/creation/audio/*` 路由对 `match3d_work` / `match3d_item` 暂时返回 `410 Gone`;视觉小说专用音频路由保持可用。
5. 历史 `generatedItemAssets[].backgroundMusic``clickSound` 字段保留,运行态仍可消费旧音频。
## 1. 范围
本方案用于改造 `生成抓大鹅草稿` 的首版生成链路:点击按钮后先进入独立生成过程页,生成结束后自动进入抓大鹅结果页,并在结果页 `素材配置 > 物品` 预览本次生成的 2D 多视角物品素材。
@@ -18,7 +8,7 @@
## 2. 前端流程
入口仍复用 `Match3DAgentWorkspace` 表单。点击 `生成抓大鹅草稿`必须先弹出 `确认消耗泥点` 面板,展示 `消耗 10 泥点`;用户确认后才进入后端生成流程
入口仍复用 `Match3DAgentWorkspace` 表单。点击 `生成抓大鹅草稿` 后:
1. 创建 Match3D session。
2. 后端先用当前题材和本地兜底元信息创建同一个 Match3D 草稿 profile草稿 Tab 必须立即能看到这份存档。
@@ -30,7 +20,7 @@
生成页步骤固定为:
```text
建立草稿存档 -> 生成作品计划 -> 生成背景提示词 -> 分批生成素材图 -> 切割独立图片 -> 上传图片资产 -> 校验素材结构 -> 生成UI背景与容器 -> 写入草稿页
生成游戏名称 -> 生成物品名称与背景音乐名称 -> 生成背景提示词 -> 分批生成1K素材图 -> 切割五视角图片 -> 上传图片资产 -> 生成背景音乐 -> 生成背景图 -> 写入草稿页
```
生成页只展示题材和物品数量,不展示玩法规则说明。
@@ -39,27 +29,27 @@
## 3. 后端编排边界
外部生图和 OSS 上传全部由 `api-server` 编排,不进入 SpacetimeDB reducer。音频生成当前临时关闭。SpacetimeDB 继续只负责 Match3D 会话、草稿和作品 profile 的确定性写入。
外部生图、音频生成和 OSS 上传全部由 `api-server` 编排,不进入 SpacetimeDB reducer。SpacetimeDB 继续只负责 Match3D 会话、草稿和作品 profile 的确定性写入。
`match3d_compile_draft` action 的后端顺序为:
1. 读取 session config。
2. 对本次 `match3d_compile_draft` 生成动作按 `sessionId + profileId + action 时间戳` 构造幂等流水并预扣 `10` 泥点。余额不足时不继续创建草稿;后续任一步失败时自动按同额退款
3. 草稿编译先创建可恢复 profile素材生成数量由入口页难度派生的物品种类决定轻松 `3` 种、标准 `9` 种、进阶 `15` 种、硬核 `21`
4. 先调用 SpacetimeDB compile procedure 写入草稿。首次执行使用新 `profileId`;重试时复用 session draft / work profile 中已有 `profileId`。这一步不能等待 LLM、图片或 OSS 成功后才执行
5. 基于入口页题材设定文本调用文本模型生成作品生成计划。模型固定请求 `gpt-4o`,只返回 JSON其中 `gameName` 为 4 到 12 个中文字符的游戏名称,`summary` 为 18 到 48 个中文字符的作品描述。生成计划还必须包含 `tags``backgroundPrompt`,以及 `items[]` 中每个物品的 `name``soundPrompt``soundPrompt` 只作为历史字段保留,当前不触发音效生成;`backgroundPrompt` 用于生成局内竖屏纯背景图只描述题材氛围、色彩和环境不得描述锅、圆盘、托盘、拼图槽、物品槽、HUD、UI、文字、按钮、倒计时、分数或物品。文本模型不可用时保留第 4 步的本地兜底,不阻断草稿
6. 后端把生成计划中的 `gameName` `summary` 写入 `match3d_work_profile` 作品信息后,自动调用作品标签生成器。标签生成器使用题材、作品名称和作品描述生成 3 到 6 个中文短标签;若调用失败或返回不足,则使用生成计划 tags 和本地兜底标签补齐。结果页手动 `AI生成作品标签` 也使用同一接口,并传入当前作品描述
7. 后端从同一份作品生成计划读取当前难度所需数量的短物品名称,并兼容保存历史 `soundPrompt` 字段;当前不生成点击音效
8. 调用 VectorEngine Gemini 原生图片接口生成 `1:1` 素材图,请求模型固定为 `gemini-3-pro-image-preview`,走 `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"]``generationConfig.imageConfig.aspectRatio = "1:1"`,响应从 `candidates[].content.parts[].inlineData.data` / `inline_data.data` 读取 base64 图片。提示词必须合入入口页选择的 `assetStylePrompt`,并强制每格使用统一纯绿色绿幕背景,避免白底或纹理背景进入运行态素材。该调整只作用于抓大鹅物品素材 sheet封面和 `9:16` 纯背景图继续使用 VectorEngine `/v1/images/generations``gpt-image-2-all` JSON 链路,`1:1` 容器 UI 图必须使用 VectorEngine `/v1/images/edits` multipart 图生图链路,不能再把参考图作为 generations 的 `image` 数组弱参考
9. 每个物品固定需要 `5` 个不同视角。单张素材图固定为 `5*5 = 25` 格,因此单张图承载 `5` 个物品。若用户要求或难度派生的物品种类不是 `5` 的倍数,后端必须向上补齐物品名称和对应图片到最近的 `5` 的倍数;例如标准难度需要 `9` 种玩法物品,实际生成 `10` 个物品名称和对应五视角图片。若草稿物品数超过 `5`,后端按每批 `5` 个物品自动分批,多张素材图并行生成
10. 将每张素材图按固定 `5 行 * 5 列` 切割成独立图片,并按物品顺序连续分配 `5` 张视角图。素材图提示词必须要求 `5*5` 严格均匀排布、每格主体完整居中、统一纯绿色绿幕背景、相邻物体主体至少保留 `1/4` 单格宽度空白间距、不得跨格、贴边或越界,避免裁剪后相邻格内容污染。切割前必须先在整张素材图上做透明背景后处理:连通到 sheet 外边缘的绿幕/近白底要清成 alpha每格内部未连到外边缘但高置信的纯绿绿幕块也必须清成 alpha物品边缘的绿幕抗锯齿和近白白边要做透明或去污染处理不够纯的绿色主体像素不得被当作绿幕误删。随后再在每个理论格子内按透明背景/前景像素做内容边界校准,并带少量安全留白导出;不能做固定内缩裁剪,避免贴近格线但未跨格的樱桃、叶片、把手等主体边缘被切掉。每个物品 JSON 写入 `imageViews[]`,同时把第一个视角兼容写入 `imageSrc/imageObjectKey`
11. 将素材图和每张独立视角图片上传到 OSS。每次获得可恢复的图片资产后都要回写 `match3d_work_profile.generated_item_assets_json`。成功素材状态为 `image_ready`;失败素材保留已成功图片引用并记录 `error`。每个素材 JSON 可继续保存历史 `soundPrompt`;不再写入新的 `backgroundMusicTitle/backgroundMusicStyle/backgroundMusicPrompt`
12. UI 背景生成由 `api-server` 分成两张资产:第一张是 `9:16` 纯背景图,走 VectorEngine `/v1/images/generations``gpt-image-2-all` JSON 请求不传锅参考图且必须禁止锅、圆盘、托盘、拼图槽、物品槽、HUD、文字、按钮、倒计时、分数和物品第二张是 `1:1` 题材容器 UI 图,走 VectorEngine `/v1/images/edits` multipart 请求,把 `public/match3d-background-references/pot-fused-reference.png` 作为 `image` part 上传,只生成一个贴合题材设定的圆形或浅盘状竞技容器,不生成整页背景、文字按钮或物品。容器图必须沿用参考图的大尺寸轻俯视构图:外轮廓接近画布四边,宽度约占 `86%-92%`、高度约占 `82%-90%`,内口为横向椭圆,禁止生成小容器、正俯视圆盘、侧视碗、餐盘或小托盘。纯背景上传到 `generated-match3d-assets/{sessionId}/{profileId}/background/{taskId}/background.png`容器 UI 图上传到 `generated-match3d-assets/{sessionId}/{profileId}/ui-container/{taskId}/container.png`,两者都作为 `backgroundAsset` 挂在首个 `generatedItemAssets[]` JSON 上HTTP DTO 同时顶层输出兼容的 `backgroundPrompt``backgroundImageSrc``backgroundImageObjectKey``generatedBackgroundAsset`,容器图通过 `generatedBackgroundAsset.containerImageSrc/containerImageObjectKey` 返回。若作品尚无用户自定义封面,草稿生成完成后默认把容器 UI 图写入 `coverImageSrc`,作为草稿架和作品信息的默认封面
13. 在 HTTP 返回的 draft/profile DTO 中附带本次生成的素材资产预览信息、背景资产信息和默认封面;后续重进草稿页时从 work profile 的持久化 `generatedItemAssets` `coverImageSrc` 恢复同一批素材、UI 与封面。历史音频字段只做兼容传递
2. 草稿编译先创建可恢复 profile素材生成数量由入口页难度派生的物品种类决定轻松 `3` 种、标准 `9` 种、进阶 `15` 种、硬核 `21`
3. 先调用 SpacetimeDB compile procedure 写入草稿。首次执行使用新 `profileId`;重试时复用 session draft / work profile 中已有 `profileId`。这一步不能等待 LLM、图片、音频或 OSS 成功后才执行
4. 基于入口页题材设定文本调用文本模型生成作品生成计划。模型固定请求 `gpt-4o`,只返回 JSON其中 `gameName` 为 4 到 12 个中文字符的游戏名称,`tags` 为 3 到 6 个中文短标签;`summary` 首版必须保持空字符串,结果页 `作品描述` 默认留给用户填写。生成计划还必须包含 `backgroundMusic.title``backgroundMusic.style``backgroundMusic.prompt``backgroundPrompt`,以及 `items[]` 中每个物品的 `name``soundPrompt``backgroundMusic.title` 是背景音乐名称,`backgroundMusic.prompt` 固定为空字符串,用于后续 Suno 纯音乐生成;`backgroundPrompt` 用于生成局内竖屏背景图,必须描述绿色纵向背景与居中浅锅/圆盘状竞技区融合为一张完整背景图,且不包含 UI、文字、按钮、倒计时或物品。文本模型不可用时保留第 3 步的本地兜底,不阻断草稿
5. 后端从同一份作品生成计划读取当前难度所需数量的短物品名称和音效提示词;不得再只生成物品名称而丢失后续音效生成上下文
6. 调用项目当前图片链路 VectorEngine `gpt-image-2-all` 生成 `1:1``1024x1024` 素材图,提示词必须合入入口页选择的 `assetStylePrompt`。历史 `nanobanana2` 图片选项当前按项目统一决策回落到 VectorEngine不重新接入 APIMart 图片网关
7. 每个物品固定需要 `5` 个不同视角。单张素材图最多切成 `5*5 = 25` 格;因此单张图最多承载 `5` 个物品。若草稿物品数超过 `5`,后端按每批最多 `5` 个物品自动分批,多张素材图并行生成
8. 将每张素材图按 `n*n` 网格切割成独立图片,并按物品顺序连续分配 `5` 张视角图。每个物品 JSON 写入 `imageViews[]`,同时把第一个视角兼容写入 `imageSrc/imageObjectKey`
9. 将素材图和每张独立视角图片上传到 OSS。每次获得可恢复的图片资产后都要回写 `match3d_work_profile.generated_item_assets_json`。成功素材状态为 `image_ready`;失败素材保留已成功图片引用并记录 `error`。每个素材 JSON 同步保存 `soundPrompt`,首个素材 JSON 同步保存 `backgroundMusicTitle``backgroundMusicStyle``backgroundMusicPrompt` 保存为空字符串作为兼容字段
10. 后端在图片素材生成后使用 `backgroundMusic.title` 提交 Suno 背景音乐任务,`prompt` 为空,`tags` 来自 `backgroundMusic.style`,并固定走纯音乐生成。轮询完成后通过通用创作音频资产链路转存 OSS、确认 `asset_object`、绑定到 `match3d_work/background_music`,再写回首个素材的 `backgroundMusic`。音乐生成失败只记录 warning不阻断草稿页进入用户可在结果页 `素材配置 > 背景音乐` 重试
11. 若入口页 `generateClickSound=true`,后端在图片素材生成后继续为缺少 `clickSound` 的已生成物品并行提交 Vidu 点击音效任务,轮询完成后通过通用创作音频资产链路转存 OSS、确认 `asset_object`、绑定实体并写回对应素材的 `clickSound`;若开关关闭则只保存 `soundPrompt`,不调用音频生成
12. 背景生成同样`api-server` 调用 VectorEngine `gpt-image-2-all`,尺寸固定为 `9:16`,并固定传入 `public/match3d-background-references/pot-fused-reference.png` 作为参考图。参考图只表达抓大鹅绿色页面背景和锅状圆形竞技区的融合构图,不包含 HUD、物品、文字按钮。生成后的背景上传到 `generated-match3d-assets/{sessionId}/{profileId}/background/{taskId}/background.png`作为 `backgroundAsset` 挂在首个 `generatedItemAssets[]` JSON 上HTTP DTO 同时顶层输出 `backgroundPrompt``backgroundImageSrc``backgroundImageObjectKey``generatedBackgroundAsset`
13. 在 HTTP 返回的 draft/profile DTO 中附带本次生成的素材资产预览信息、背景音乐资产信息和背景资产信息;后续重进草稿页时从 work profile 的持久化 `generatedItemAssets` 恢复同一批素材、音乐与背景
若文本模型不可用或返回无法解析,后端必须降级为 `{themeText}抓大鹅`、本地作品描述与本地标签兜底,不阻断素材生成;标签仍通过作品标签生成器优先生成,失败后再用兜底标签补齐
若文本模型不可用或返回无法解析,后端必须降级为 `{themeText}抓大鹅` 与本地标签兜底,不阻断素材生成;但描述仍保持空字符串
草稿生成阶段不再调用 Hyper3D Rodin不生成 GLB也不等待任何模型轮询。前端 `match3d_compile_draft` action 的长耗时主要来自文本生成、分批 1K 生图、切图、OSS 上传、背景图和容器 UI 图。批量新增物品由 `POST /api/creation/match3d/works/{profileId}/item-assets` 复用同一套 2D 素材图生成、固定 `5*5` 切图OSS 上传链路;若本次新增数量不是 `5` 的倍数,同样向上补齐名称和图片到最近的 `5` 的倍数。整图生成完成后立即丢弃补齐用临时物品,只对用户实际新增项执行绿幕抠背景、切割和上传,并只把这些真实新增项的 `imageViews[]` 写回 `generatedItemAssets`。批量重新生成同样调用该接口,但请求体增加 `mode = "replace"`,前端从现有素材列表收集用户确认的物品名称;后端只匹配已存在的同名素材,保留原 `itemId`、列表顺序、UI 背景、历史背景音乐和点击音效字段,只替换该素材的 `imageSrc/imageObjectKey/imageViews/status/error`,避免试玩和正式运行态的物品类型映射漂移
草稿生成阶段不再调用 Hyper3D Rodin不生成 GLB也不等待任何模型轮询。前端 `match3d_compile_draft` action 的长耗时主要来自文本生成、分批 1K 生图、切图、OSS 上传、背景图和可选音频生成。批量新增物品由 `POST /api/creation/match3d/works/{profileId}/item-assets` 复用同一套 2D 素材图生成、5x5 切图OSS 上传和可选点击音效链路,只补齐本次新增物品并把 `imageViews[]` 写回 `generatedItemAssets`
## 4. 图片提示词
@@ -67,21 +57,15 @@
```text
生成一张1:1图片
生成严格5*5均匀网格素材图
生成不超过5*5网格素材图
整体画风遵循:...
只绘制这些物品:...
每格背景必须是统一纯绿色绿幕背景,方便后续转透明
物品本身不得使用与绿幕相同的纯绿色
每格主体完整居中,禁止跨格、贴边或越界影响裁剪后的效果
相邻物体主体之间至少保留 1/4 单格宽度空白间距,物体主体不得占满格子
不要出现文字、水印、UI、边框、网格线、白色背景、灰色背景、纹理背景
不要出现文字、水印、UI、边框
```
`包含若干个物品名称` 在落地中解释为“按生成出的物品名称绘制对应主体”,不要求图片上写出物品名称。这样可以避免文字渲染污染切图和局内 2D 素材表现。
内置 `像素复古` 不能只写“复古像素”或“有限色板”。入口页、参考图脚本和后端素材图 prompt 必须使用同一组硬约束:真正复古像素 2D 游戏道具 sprite先按约 `64x64` 低分辨率像素块绘制再整数倍放大,硬边方块像素清晰可见,有限色板 `12-24` 色;同时在负向约束中禁止抗锯齿、柔焦、平滑渐变、真实 3D 渲染、PBR 材质、摄影光照和平滑插画。后端即使只收到 `assetStyleId = pixel-retro``assetStyleLabel = 像素复古`,也必须补齐这组约束,避免旧会话、恢复会话或批量新增物品退回普通插画风格。
入口页内置 2D 风格参考图通过同一 VectorEngine `gpt-image-2-all` 能力生成,执行命令为 `npm run assets:match3d-style-references -- --live`。每张入口参考图只展示 `1` 个完整独立物品,不能展示 `5` 个物品样张或多物品散点图,避免风格选择被误读为物品数量配置。保存路径固定为:
入口页内置 2D 风格参考图通过同一 VectorEngine `gpt-image-2-all` 能力生成,执行命令为 `npm run assets:match3d-style-references -- --live`,保存路径固定为:
```text
public/match3d-style-references/flat-icon.png
@@ -94,13 +78,13 @@ public/match3d-style-references/painterly-icon.png
这些图片只作为入口页风格选择的视觉参考,不进入用户草稿资产,不替代生成时的物品素材图。
局内容器 UI 图生成固定参考图路径为:
局内背景生成固定参考图路径为:
```text
public/match3d-background-references/pot-fused-reference.png
```
这张图作为容器 UI 图的 VectorEngine `/v1/images/edits` multipart `image` part用来锁定“大尺寸轻俯视浅盘容器”的构图。参考图本身是 `1:1` 透明底容器素材,外轮廓接近画布四边,内口为横向椭圆;结果页没有真实生成容器时也只把它作为容器预览兜底,不能再作为 `9:16` 背景预览。每次草稿生成仍会根据 `backgroundPrompt` 生成新的题材化背景图;纯背景图不再传入该参考图,也不得生成锅或 UI 元素
这张图作为 VectorEngine `image` 参考输入使用,用来锁定“绿色竖屏背景 + 居中锅状竞技区”的构图。每次草稿生成仍会根据 `backgroundPrompt` 生成新的题材化背景图;参考图本身不作为运行态最终背景
## 5. OSS 路径
@@ -124,9 +108,7 @@ generated-match3d-assets/{sessionId}/{profileId}/background/{taskId}/background.
`itemSlug` 必须带 `itemId` 前缀,例如 `match3d-item-1-item`。中文物品名清洗后可能都退回 `item`,不能只用物品名做路径,否则多张切割图会写到同一个 object key导致草稿页预览图全部一致。
HTTP DTO 同时返回兼容字段 `imageSrc``imageObjectKey`,以及正式 2D 字段 `imageViews[]``backgroundAsset``status`。图片素材生成成功后 `status = image_ready`背景和容器 UI 图都生成成功后首个素材的 `backgroundAsset.status = image_ready`,并携带 `containerImageSrc/containerImageObjectKey`。前端通过 `/api/assets/read-url` 将 generated legacy path 换签后加载私有图片,不直接请求裸 `/generated-match3d-assets/...` 路径。运行态背景图和容器 UI 图同样通过 `/api/assets/read-url` 换签后加载:背景作为全屏 `object-cover`,容器作为中心棋盘视觉层;当容器图成功解析为可渲染图片时,`Match3DRuntimeShell` 必须移除默认圆形锅壳、边框和径向底色,让生成容器接管棋盘外观
结果页手动点击 `素材配置 > UI > 重新生成` 时,目标库可能仍运行旧 SpacetimeDB wasm缺少钱包扣退费或 Match3D 写回相关 procedure。`api-server` 对这类 `No such procedure` 只做临时容错:泥点预扣阶段跳过扣费,背景图和容器 UI 已经生成但草稿写回失败时HTTP 响应仍返回本次生成的 `generatedBackgroundAsset` 和带该资产的内存 profile避免草稿页直接报错。该容错不等于持久化成功刷新、换设备或公开详情稳定恢复仍以发布最新 SpacetimeDB module、确认 procedure 导出和重新生成 bindings 为准。
HTTP DTO 同时返回兼容字段 `imageSrc``imageObjectKey`,以及正式 2D 字段 `imageViews[]``backgroundAsset``status`。图片素材生成成功后 `status = image_ready`;背景生成成功后首个素材的 `backgroundAsset.status = image_ready`。前端通过 `/api/assets/read-url` 将 generated legacy path 换签后加载私有图片,不直接请求裸 `/generated-match3d-assets/...` 路径。运行态背景图同样通过 `/api/assets/read-url` 换签后作为全屏 `object-cover` 背景加载
## 5.1 运行态 2D 素材消费
@@ -134,25 +116,23 @@ HTTP DTO 同时返回兼容字段 `imageSrc`、`imageObjectKey`,以及正式 2
```text
Match3DWorkProfile / PlatformMatch3DGalleryCard
-> Match3DRuntimeShell(generatedItemAssets, generatedBackgroundAsset, backgroundImageSrc)
-> Match3DRuntimeShell(generatedItemAssets, backgroundImageSrc)
-> Match3DPhysicsBoard / Match3DTrayPreviewBoard
```
运行态按运行快照中的 `itemTypeId` 稳定排序后,把 `generatedItemAssets` 顺序映射到对应类型。加载某个物品实例时,从该类型素材的 `imageViews[]` 中按实例 id 稳定随机选择一个视角;若历史数据没有 `imageViews[]`,则回退到 `imageSrc/imageObjectKey`。没有生成图片或图片加载失败时,继续使用默认积木图标兜底。
运行态背景优先读取 `backgroundImageSrc` / 顶层 `generatedBackgroundAsset.imageSrc/imageObjectKey`,为空时从 `generatedItemAssets[].backgroundAsset.imageSrc/imageObjectKey` 兜底。中心容器优先读取顶层 `generatedBackgroundAsset.containerImageSrc/containerImageObjectKey`,再读取 `generatedItemAssets[].backgroundAsset.containerImageSrc/containerImageObjectKey`;为空或换签/图片加载失败时继续使用默认圆形容器样式。容器图成功加载后,`Match3DRuntimeShell` 的棋盘容器必须切换为透明、可溢出承载,不再叠加默认 `rounded-full` 圆形锅壳、金色边框和默认径向背景,避免 AI 生成的大尺寸轻俯视容器被裁切或被默认锅视觉覆盖。运行态入口判断是否需要补读作品详情时,只能把 `imageViews[]``imageSrc/imageObjectKey` 视为“已有物品图片素材”;`backgroundMusic.audioSrc``clickSound.audioSrc``generatedBackgroundAsset``backgroundAsset.image*``backgroundAsset.containerImage*` 是随物品素材一起传入的附属运行态资产,不能单独证明物品素材已完整。也不能继续只用历史 `modelSrc/modelObjectKey` 判断,否则新 2D 草稿会在试玩或推荐流中被当成“无素材”并回退默认积木。`Match3DRuntimeShell` 只保留顶部返回、倒计时、重开三个控件;这些顶部控件和底部备选栏统一使用题材无关的半透明玻璃组件样式,不能随背景题材改成木质、金属、果园、科幻等主题皮肤,也不能重新烘进 AI 背景图。进度、组数、版本等状态信息不得再作为顶部常驻 UI 出现,避免遮挡生成背景和中心容器
运行态背景优先读取 `backgroundImageSrc` / `generatedBackgroundAsset.imageSrc`,为空时从 `generatedItemAssets[].backgroundAsset.imageSrc/imageObjectKey` 兜底。`Match3DRuntimeShell` 只保留顶部返回、倒计时、重开三个控件;进度、组数、版本等状态信息不得再作为顶部常驻 UI 出现,避免遮挡生成背景和锅状竞技区
前端加载规则:
1. 优先读取 `imageViews[]` 中的 `imageSrc/imageObjectKey`,为空时使用兼容字段 `imageSrc/imageObjectKey`
2. 对 generated legacy path 通过同源 `/api/assets/read-url` 换签后交给浏览器图片加载;结果页音频试听入口当前隐藏,后续恢复时也必须先换签,不能把裸 `/generated-match3d-assets/...` 音频路径直接交给 `<audio>`
2. 对 generated legacy path 通过同源 `/api/assets/read-url` 换签后交给浏览器图片加载。
3. 场内物品、点击命中和备选栏继续使用后端快照中的 `itemInstanceId/itemTypeId/x/y/radius/layer`;生成 2D 图片只替换视觉表现,不承接规则真相。
4. 同一物品类型的多个实例可以展示不同视角,但同一实例在本局中应稳定使用同一个视角,避免移动或入槽时闪图。
5. 图片缺失、读取失败或解码失败时,继续使用默认积木素材,不能阻断开局、点击、入槽或结算。
结果页点击 `试玩` 时,前端必须把当前结果页可见的 `generatedItemAssets` 带入运行态启动入参。`PUT /api/runtime/match3d/works/{profileId}` 若因为并发或旧快照返回了缺少素材的 profile`Match3DResultView` 需要把当前 draft / profile 的素材重新合并到运行态 profile并在启动试玩前调用生成素材保存接口把当前可见的 `generatedItemAssets` 写回作品 profile不能只在内存里把素材补到 `onStartTestRun(profile)`。发布同理必须先落库当前素材,再调用 `publish_match3d_work`,否则公开推荐流和正式运行态只能读到旧 profile 快照。结果页顶部返回按钮固定回到平台创作页,不再回到抓大鹅专属内嵌入口表单;需要修改题材时由用户在创作页重新选择或从草稿继续进入。若历史草稿同时存在旧 `draft.generatedItemAssets` 和较新的 `profile.generatedItemAssets`,同 `itemId` 下以 profile 中已有的 `imageViews[]``imageSrc``imageObjectKey``backgroundMusic``backgroundAsset` 补齐 draft不能让旧 draft 把素材覆盖成空列表。`PlatformEntryFlowShellImpl` 在渲染 `match3d-runtime` 时按 `run.profileId` 优先使用当前 `match3dRuntimeProfile / match3dProfile.generatedItemAssets`,只有 profileId 不匹配时才读取 `selectedPublicWorkDetail.generatedItemAssets`;即使当前 profile 暂时没有物品图片,也不能把同 profile 的已有 `generatedItemAssets` 覆盖为空数组。推荐流内嵌正式运行态也必须走同一解析器;当推荐卡片摘要缺少物品图片素材时,启动前补读 `getMatch3DWorkDetail(profileId)`,把详情里的生成图片、历史背景音乐和 UI 素材写入 `match3dRuntimeProfile` 后再传给运行态。这样可以避免从公开详情页残留状态或推荐卡片旧摘要进入试玩 / 正式游戏时,把已生成草稿的 2D 素材、历史音乐或 UI 覆盖成空列表。
2026-05-14 补充:`backgroundMusic` 虽然暂存在 `generatedItemAssets[]` 中,但语义上是作品级音乐。前端读取、保存、试玩、推荐流和运行态入口都必须先通过统一归一化逻辑把任意素材上的 `backgroundMusic/backgroundMusicTitle/backgroundMusicStyle/backgroundMusicPrompt` 迁移到首个素材,并清空其它素材上的作品级音乐字段,避免 action response 中缺音乐的 draft assets 覆盖 work detail 中已经持久化的音乐,也为未来恢复音乐入口保留稳定读取口径。`match3d_compile_draft` action 完成后,如果同时拿到 `response.session.draft.generatedItemAssets``getMatch3DWorkDetail(profileId).item.generatedItemAssets`,必须以同 `itemId` 合并保留详情里的历史背景音乐、UI 背景和点击音效,再进入结果页或试玩。
结果页点击 `试玩` 时,前端必须把当前结果页可见的 `generatedItemAssets` 带入运行态启动入参。`PUT /api/runtime/match3d/works/{profileId}` 若因为并发或旧快照返回了缺少素材的 profile`Match3DResultView` 需要把当前 draft / profile 的素材重新合并到运行态 profile并在启动试玩前调用生成素材保存接口把当前可见的 `generatedItemAssets` 写回作品 profile不能只在内存里把素材补到 `onStartTestRun(profile)`。发布同理必须先落库当前素材,再调用 `publish_match3d_work`,否则公开推荐流和正式运行态只能读到旧 profile 快照。若历史草稿同时存在旧 `draft.generatedItemAssets` 和较新的 `profile.generatedItemAssets`,同 `itemId` 下以 profile 中已有的 `imageViews[]``imageSrc``imageObjectKey` 补齐 draft不能让旧 draft 把素材覆盖成空列表。`PlatformEntryFlowShellImpl` 在渲染 `match3d-runtime` 时按 `run.profileId` 优先使用当前 `match3dProfile.generatedItemAssets`,只有 profileId 不匹配时才读取 `selectedPublicWorkDetail.generatedItemAssets`。推荐流内嵌正式运行态也必须走同一解析器;当推荐卡片摘要缺少素材时,启动前补读 `getMatch3DWorkDetail(profileId)`,把详情里的生成图片素材写入 `match3dProfile` 后再传给运行态。这样可以避免从公开详情页残留状态或推荐卡片旧摘要进入试玩 / 正式游戏时,把已生成草稿的 2D 素材覆盖成空列表。
历史草稿若仍保存 `status = model_ready``modelSrc``modelObjectKey`,仅作为旧版本兼容读取,不再参与新素材生产。历史外部模型链接转存接口只用于清理旧数据,不能被新草稿生成、批量新增或结果页普通编辑入口调用。
@@ -162,9 +142,9 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
点击 `生成抓大鹅草稿` 后,草稿存档创建与素材生成解耦:
1. 首次 compile 必须先写 `match3d_work_profile` 草稿行,即使后续卡在文本模型、图片生成或 OSS 上传任意阶段。
1. 首次 compile 必须先写 `match3d_work_profile` 草稿行,即使后续卡在文本模型、图片生成、音频生成或 OSS 上传任意阶段。
2. 失败态前端要重新读取 session / work detail并刷新草稿作品架保证用户离开生成页后仍能在草稿 Tab 找到这份作品。
3. 重新生成时优先使用当前 session 的 `draft.profileId``publishedProfileId`,不得重新创建 session后端读取同一 profile 的 `generated_item_assets_json` 后,只补齐缺失图片、UI 背景或容器资源
3. 重新生成时优先使用当前 session 的 `draft.profileId``publishedProfileId`,不得重新创建 session后端读取同一 profile 的 `generated_item_assets_json` 后,只补齐缺失图片或缺失音频的阶段
4. 已有 `status = image_ready` 且带 `imageViews[]``imageSrc/imageObjectKey` 的素材视为完成,不再重复生成图片。
抓大鹅结果页的基础信息自动保存继续调用 `PUT /api/runtime/match3d/works/{profileId}` 更新名称、题材、描述、标签、封面、消除数和难度;该保存不得清空 `generated_item_assets_json`。结果页 `素材配置 > 物品` 只在独立面板中预览和编辑当前素材,不再提供单项重新生成入口;删除单项或批量新增成功后,都必须把当前素材列表重新序列化成 `generatedItemAssets` 并写回作品 profile否则试玩、发布和重进草稿会读取旧素材快照。SpacetimeDB `update_match3d_work` / `publish_match3d_work` 必须保留当前行的生成素材 JSON。
@@ -175,18 +155,16 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
草稿 Tab -> getMatch3DWorkDetail(profileId) -> Match3DResultView(profile.generatedItemAssets)
```
若草稿卡已经带有前端生成中标记,即使作品列表已经刷新成真实 `match3d_work_profile` 草稿行,点击该卡也必须优先回到 `match3d-generating` 生成过程页,并按 `sourceSessionId` 重新读取当前 session不能因为 `getSession` 返回了带 `draft` 的快照就直接进入结果页。若后台生成已经收口为 ready 且草稿卡仍有未读红点,首次点击必须消费红点并直接启动抓大鹅试玩,返回后展示 `Match3DResultView`;红点已读后的后续点击才按常规结果页恢复路径进入 `Match3DResultView`。因此点击恢复优先级固定为:未读 ready 红点自动试玩 > 仍在 generating 的本地 / 后台任务回生成页 > 普通草稿结果页。
因此 `map_match3d_work_summary_response` / `map_match3d_work_profile_response` 需要从 work profile snapshot 反序列化 `generated_item_assets_json` 并输出 `generatedItemAssets` 与顶层背景字段。前端 `Match3DResultView` 的读取顺序为:有 `draft.generatedItemAssets` 时先用 draft 保留本次生成顺序和图片;同 `itemId``profile.generatedItemAssets` 中已有 `imageViews[]``imageSrc/imageObjectKey` 时,用 profile 图片字段补齐 draft背景资产同样必须从 profile 或 draft 的首个 `backgroundAsset` 保留到保存 payload从草稿架重进没有 draft 时,用 `profile.generatedItemAssets`;两者都没有才回退到默认素材占位。
结果页 `作品信息` Tab 字段命名对齐拼图草稿:
1. `作品名称` 对应 Match3D `gameName`
2. `作品描述` 对应 Match3D `summary`,草稿生成阶段由同一次作品生成计划自动填入
3. `作品标签` 对应 Match3D `tags`草稿生成阶段在写入名称和描述后自动调用标签生成器填入;结果页仍允许用户继续编辑或再次 AI 生成
4. 封面图与作品名称不再拆成左右两个大模块;封面只作为同一 Tab 内的可选入口,避免和作品基础信息割裂。旧称“碰面图”统一改为“封面图”。草稿生成默认使用生成出的中心容器 UI 图作为 `coverImageSrc`点击封面图必须弹出独立编辑面板,不允许在当前作品信息面板下方展开。封面面板布局对齐拼图创作页上传卡:移动端优先左侧/上方为方形预览卡,预览卡本身就是上传热区;上传图片后,预览卡内出现和拼图入口一致的 `AI重绘` 开关与删除按钮,面板底部不再额外展示旧 `AI重绘` 选项。已有上传图时,右侧/下方输入框标题为 `AI重绘要求`;关闭 AI 重绘时只把上传图 Data URL 写入封面字段,不调用生图模型。没有上传图时,输入框标题为 `封面描述`,可选择多张参考图后调用 VectorEngine `gpt-image-2-all` 文生图链路,参考图通过请求体 `image` 数组传入;参考图来源支持直接引用 `物品素材` / `UI素材` 中已有图片,也支持自定义上传。上传图 AI 重绘与无上传图多参考图生成都通过 `api-server` 的 Match3D 作品封面生成接口完成,生成结果转存到 `generated-match3d-assets/{sessionId}/{profileId}/cover/{taskId}/cover.png` 后再写回 `coverImageSrc`
2. `作品描述` 对应 Match3D `summary`,草稿生成默认空
3. `作品标签` 对应 Match3D `tags`可由 AI 首次生成并允许用户继续编辑
4. 封面图与作品名称不再拆成左右两个大模块;封面只作为同一 Tab 内的可选入口,避免和作品基础信息割裂。点击封面图必须弹出独立编辑面板,不允许在当前作品信息面板下方展开。封面面板布局参考拼图创作页上传卡:移动端优先左侧/上方为方形预览,右侧/下方为提示词与操作区。面板支持三类输入:本地上传图片、上传后开启 AI 重绘、直接引用 `物品素材` `UI素材` 中已有图片作为封面或 AI 重绘参考图。AI 重绘通过 `api-server` 的 Match3D 作品封面生成接口调用 VectorEngine `gpt-image-2-all`,生成结果转存到 `generated-match3d-assets/{sessionId}/{profileId}/cover/{taskId}/cover.png` 后再写回 `coverImageSrc`;关闭 AI 重绘时只把选中的 Data URL 或 generated legacy path 写入封面字段
结果页 `难度配置` Tab 取代旧 `玩法配置`,不再展示旧的分散输入项。该 Tab 顶部使用横向离散拖动条调整难度,四个刻度分别为 `轻松 / 标准 / 进阶 / 硬核`;拖动条只能落在这四个点上,刻度标签可点击切换。该 Tab 必须与创作入口页使用同一组难度选项,并统一把原“类型素材图片 / 局内类型”等口径归一为 `物品种类`
结果页 `难度配置` Tab 取代旧 `玩法配置`,不再展示旧的分散输入项。该 Tab 必须与创作入口页使用同一组难度选项,并统一把原“类型素材图片 / 局内类型”等口径归一为 `物品种类`
| 难度 | clearCount | difficulty | 总物品数 | 物品种类 |
| ---- | ---------: | ---------: | -------: | -------: |
@@ -197,36 +175,36 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
预览区展示 `需要消除``总物品数``物品种类``已生成物品种类`。历史草稿如果保存的是旧 `clearCount/difficulty`,前端按 `clearCount` 精确命中优先、否则按 `difficulty` 就近归一到上述选项,并把归一后的数值保存回 profile。发布校验以 `generatedItemAssets[]``image_ready` 且至少有 `5` 张有效 `imageViews[]` 的素材数量为准;试玩启动时用同一数量计算 `itemTypeCountOverride`,不足时自动降低,不修改草稿难度配置本身。历史单图 `imageSrc/imageObjectKey` 只作为运行态和预览兜底,不计入新发布素材完成数。
结果页 `素材配置` Tab 取代旧一级素材入口,当前包含三个子 Tab
结果页 `素材配置` Tab 取代旧一级素材入口,包含三个子 Tab
1. `物品`:显示 2D 物品素材列表、五视角预览素材名称点击音效提示词与生成入口已临时隐藏
2. `UI`:预览生成的竖屏游戏背景图,并在独立运行态 UI 预览面板中叠加当前中心容器形象。背景读取顺序为 draft 顶层背景、draft `generatedBackgroundAsset`、profile 顶层背景、profile `generatedBackgroundAsset``generatedItemAssets[].backgroundAsset`、本地兜底图;容器读取 `generatedItemAssets[].backgroundAsset.containerImageSrc/containerImageObjectKey`,缺失时使用默认圆形容器。该页必须展示默认画面描述提示词,默认值来自草稿生成计划的 `backgroundPrompt` 或持久化 `backgroundAsset.prompt`;用户修改后点击重新生成,先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`,确认后调用 `POST /api/creation/match3d/works/{profileId}/background-image`,现阶段后端仍会同时生成纯背景图和容器 UI 图,并把新的 `backgroundAsset` 写回同一份 `generated_item_assets_json`确认后按钮区域必须显示生成进度条,按 `90` 秒估算倒计时后端真实返回后立即收口。UI 子 Tab 的预览面板直接用当前背景图、容器 UI 图、顶部返回/倒计时/重开控件和底部默认托盘模拟竖屏页面,不在 Tab 下方内联展开。
3. `容器形象`:预览和重新生成 `1:1` 中心容器 UI 图,页面能力与 `UI` 子 Tab 对齐,包含方形容器预览、容器提示词输入、独立运行态 UI 预览面板、泥点确认和生成进度。默认提示词来自持久化 `backgroundAsset.containerPrompt`,缺失时从当前题材、作品描述和容器参考约束生成兜底提示词;用户修改后点击重新生成,先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`,确认后调用 `POST /api/creation/match3d/works/{profileId}/container-image`,按钮区域同样按 `90` 秒估算显示倒计时进度。该接口只重新生成并写回 `backgroundAsset.containerPrompt/containerImageSrc/containerImageObjectKey`,必须保留已有纯背景 `prompt/imageSrc/imageObjectKey`、物品素材、历史背景音乐和点击音效字段,避免用户只换容器时刷新掉背景图或物品素材
1. `物品`:显示 2D 物品素材列表、五视角预览素材名称点击音效提示词和点击音效生成入口
2. `UI`:预览生成的竖屏游戏背景图,读取顺序为 draft 顶层背景、draft `generatedBackgroundAsset`、profile 顶层背景、profile `generatedBackgroundAsset``generatedItemAssets[].backgroundAsset`、本地参考图兜底。该页必须展示默认画面描述提示词,默认值来自草稿生成计划的 `backgroundPrompt` 或持久化 `backgroundAsset.prompt`;用户修改后点击重新生成,后端继续固定使用 `public/match3d-background-references/pot-fused-reference.png` 作为 VectorEngine `image` 参考图,并把新的 `backgroundAsset` 写回同一份 `generated_item_assets_json`UI 子 Tab 还必须提供独立的运行态 UI 预览面板直接用当前背景图模拟抓大鹅竖屏页面的顶部返回倒计时重开控件、锅状竞技区和底部托盘,不在 Tab 下方内联展开。
3. `背景音乐`:承载原一级音乐 Tab 的背景音乐曲名、风格、生成进度和试听控件;背景音乐始终按纯音乐生成,前端不提供提示词输入
旧一级 `音乐` Tab 删除;`素材配置 > 背景音乐` 当前也不展示
旧一级 `音乐` Tab 删除;抓大鹅背景音乐入口只保留在 `素材配置 > 背景音乐`
`素材配置 > 物品` 详情页只保留:
1. 五视角预览区:优先展示 `imageViews[]`,缺失时展示兼容字段 `imageSrc/imageObjectKey`
2. 素材名称输入。
3. 不展示点击音效提示词输入或点击音效生成入口
五视角预览区采用“上方大预览 + 底部缩略图栏”的布局:上方是方形焦点预览区,中间横向排列当前物品的各视角图片,并用内框标出当前焦点;底部缩略图栏固定露出 `4` 个方形槽位,多出的第 `5` 个视角通过横向滚动访问。点击缩略图只切换焦点视角,不在面板内新增说明文案或额外规则区。
3. 可编辑的点击音效提示词输入。
4. 点击音效生成入口。
详情页不再展示参考图、用途、模型提示词、文生/图生切换、状态查询、下载列表、taskUuid 或 subscriptionKey。
`物品素材` 列表项点击必须弹出独立预览面板,不允许在列表右侧或列表下方内联展示。列表本身使用移动端至少两列的多列卡片布局;每个列表项只展示图片预览、物品名称和垃圾箱删除图标,不展示用途、状态胶囊、视角数量或 `2D素材` 标记。预览面板只承担查看五视角图片编辑素材名称;不再展示单项 `重新生成` 按钮。列表项自身支持单项删除,删除后立即把剩余 `generatedItemAssets` 写回作品 profile。批量新增通过列表顶部按钮打开独立面板面板内每个输入框只输入一个物品名称`新增物品名称` 按钮追加一个输入框;提交按钮点击后必须先弹出 `确认消耗泥点` 面板并展示按当前有效名称计算出的泥点数,用户确认后才按输入框顺序清洗、去重并调用 Match3D 作品批量生图接口。批量重新生成通过列表顶部另一个按钮打开独立面板,面板预填当前全部素材名称,用户可清空不需要重新生成的输入框;提交按钮点击后同样先弹出泥点确认面板,确认后按输入框顺序清洗、去重并以替换模式调用同一接口。生成进度同时显示在批量面板和 `素材配置 > 物品` 列表顶部,面板可关闭,后台生成继续推进,不阻塞封面或 UI 生成操作。后端复用草稿生成的素材图、切图OSS 上传流程,但新增模式仅按实际可新增名称持久化,不重新生成已有物品;替换模式仅按实际匹配到的已有名称持久化,不新增物品、不改变 `itemId`。两者都不新增 SpacetimeDB 表,最终仍写回同一份 `generated_item_assets_json`批量新增和批量重新生成都先补齐到 `5` 个参与整图生成,随后丢弃补齐用临时物品,只对真实新增或真实替换物品抠背景、切割和上传。计费按实际新增或替换名称每 `5` 个消耗 `2` 泥点,不足 `5` 个向上取整;重复名称、已有名称、未匹配名称和超过容量上限的名称不计费。
`物品素材` 列表项点击必须弹出独立预览面板,不允许在列表右侧或列表下方内联展示。预览面板只承担查看五视角图片编辑素材名称、编辑点击音效提示词和生成点击音效;不再展示 `重新生成` 按钮。列表项自身支持单项删除,删除后立即把剩余 `generatedItemAssets` 写回作品 profile。批量新增通过列表顶部按钮打开独立面板面板内每个输入框只输入一个物品名称`新增物品名称` 按钮追加一个输入框;提交后按输入框顺序清洗、去重并调用 Match3D 作品批量生图接口。生成进度同时显示在批量新增面板和 `素材配置 > 物品` 列表顶部,面板可关闭,后台生成继续推进,不阻塞封面、音频等其他生成操作。后端复用草稿生成的素材图、切图OSS 上传和可选点击音效流程,但仅作用于本次新增名称,不重新生成已有物品不新增 SpacetimeDB 表,最终仍写回同一份 `generated_item_assets_json`
## 6.1 音频生成与扣费
抓大鹅结果页音频生成当前临时关闭
抓大鹅结果页音频生成复用通用创作音频路由
1. `素材配置 > 背景音乐` 不展示
2. `素材配置 > 物品` 详情面板不展示点击音效提示词和生成入口
3. 通用 `/api/creation/audio/*` 路由对 `match3d_work` / `match3d_item` 暂时返回 `410 Gone`,防止旧前端或脚本继续触发抓大鹅扣费音频任务
4. 历史 `generatedItemAssets[].backgroundMusic``clickSound` 字段保留,运行态仍可消费旧音频;结果页不提供重新生成入口
1. `素材配置 > 背景音乐` 默认读取首个 `generatedItemAssets[0].backgroundMusicTitle/backgroundMusicStyle`,用户可继续编辑曲名和风格;`backgroundMusicPrompt` 保留为空字符串兼容旧 JSON生成请求固定传空 `prompt`
2. 物品点击音效默认读取对应 `generatedItemAssets[].soundPrompt`,用户可在 `素材配置 > 物品` 详情面板内编辑
3. 背景音乐与物品音效生成过程必须显示进度条;提交任务、等待生成、转存资产和完成分别推进到不同进度,不再只展示旋转图标
4. 音频生成完成后立即展示浏览器原生 audio 控件,支持试听
5. `POST /api/creation/audio/background-music/{task_id}/asset``POST /api/creation/audio/sound-effect/{task_id}/asset` 在真正拿到音频并转存资产前,由后端按 `taskId + 资产槽位` 幂等预扣 `10` 光点任务仍在处理中时不扣费。资产下载、OSS 转存或资产绑定失败时后端自动退款。前端只展示生成按钮和进度,不自行计算或写入钱包。
创作入口不展示 `生成音效` Toggle。草稿生成阶段不产生背景音乐或物品点击音效任务,也不产生音频相关扣费;入口只产生一次固定 `10` 泥点的草稿生成扣费。结果页 `素材配置 > UI` 重新生成背景固定扣 `2` 泥点;`素材配置 > 容器形象` 单独重新生成容器同样固定扣 `2` 泥点
入口页 `生成音效` Toggle 复用同一扣费与资产绑定规则。默认关闭,关闭时草稿生成阶段不产生音频任务也不扣除音频光点;开启时每个首批物品点击音效按单独任务和单独 `match3d_click_sound` 资产槽位扣费。音效生成失败不阻断草稿结果页进入,失败素材保留 `soundPrompt`,用户可在结果页物品详情面板手动重试
## 7. 验收
@@ -248,4 +226,4 @@ cargo check -p spacetime-client --manifest-path server-rs\Cargo.toml
cargo check -p spacetime-module --manifest-path server-rs\Cargo.toml
```
真实草稿生成需要本地私密环境配置 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` / `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;其中物品素材 sheet 走 VectorEngine Gemini 原生 `generateContent`,封面和 `9:16` 纯背景走 VectorEngine `/v1/images/generations``gpt-image-2-all` JSON 链路,`1:1` 容器 UI 走 VectorEngine `/v1/images/edits` multipart 参考图链路。同时必须补齐完整 `ALIYUN_OSS_BUCKET``ALIYUN_OSS_ENDPOINT``ALIYUN_OSS_ACCESS_KEY_ID``ALIYUN_OSS_ACCESS_KEY_SECRET`。如果只配置 bucket 和 endpoint抓大鹅素材、封面或背景生成会在调用外部生图前返回 `OSS 未完成环境变量配置``details.missingEnv` 会列出缺少的 AccessKey 项;不要回退到 Rodin/GLB 或伪造本地上传成功。临时关闭期间不需要音频上游配置。后端改动后使用 `npm run api-server` 启动,并检查 `/healthz`
真实草稿生成需要本地私密环境配置 `VECTOR_ENGINE_API_KEY` 和 OSS 访问变量;开启音频生成还需要对应音频上游配置。后端改动后使用 `npm run api-server` 启动,并检查 `/healthz`

View File

@@ -2,13 +2,9 @@
> 2026-05-08 更新:抓大鹅创作端入口已重新开放,当前 `match3d.visible` 为 `true`。本文件记录 F1 接入能力,入口是否展示以 `NEW_WORK_ENTRY_CONFIG_2026-05-01.md` 和 `src/config/newWorkEntryConfig.ts` 为准。
>
> 2026-05-10 更新:抓大鹅入口页对齐拼图入口页,直接嵌入创作页模板 Tab。入口表单不再展示参考图、消除次数输入、难度数值滑杆和题材/物品/难度摘要框,仅保留题材主题大输入框和难度选项。难度选项负责派生 `clearCount` 与 `difficulty`。
> 2026-05-10 更新:抓大鹅入口页对齐拼图入口页,直接嵌入创作页模板 Tab。入口表单不再展示参考图、消除次数输入、难度数值滑杆和题材/物品/难度摘要框,仅保留题材主题大输入框和难度选项。难度选项负责派生 `clearCount` 与 `difficulty`,生成按钮必须展示 `消耗20光点`
>
> 2026-05-12 补充:入口页风格选择收敛为 `2D素材风格`,首批常见 2D 素材风格参考图通过 `npm run assets:match3d-style-references -- --live` 调用 VectorEngine `gpt-image-2-all` 生成并保存到 `public/match3d-style-references/`。2026-05-13 起,入口参考图固定只展示 `1` 个完整独立物品,不再展示 `5` 个物品样张或多物品散点图。最后一个选项为 `自定义`,点击后弹出独立面板填写画风描述。
>
> 2026-05-13 补充:草稿素材实际生成数量按 `5` 的倍数向上补齐,补齐物品同样需要生成名称和五视角图片。素材图提示词固定要求 `5*5` 严格均匀排布,禁止主体跨格、贴边或越界影响裁剪效果。
>
> 2026-05-13 补充:创作页隐藏抓大鹅 `生成音效` Toggle草稿生成固定预扣 `10` 泥点,按钮展示 `消耗10泥点`。点击音效生成只保留在结果页 `素材配置 > 物品` 详情面板中手动触发。
> 2026-05-12 补充:入口页风格选择收敛为 `2D素材风格`,首批常见 2D 素材风格参考图通过 `npm run assets:match3d-style-references -- --live` 调用 VectorEngine `gpt-image-2-all` 生成并保存到 `public/match3d-style-references/`。最后一个选项为 `自定义`,点击后弹出独立面板填写画风描述。
## 1. 阶段边界
@@ -44,11 +40,12 @@ badge: 可创建
创作页 `选择模板` Tab 中切换到 `抓大鹅` 时,直接渲染该表单,不创建会话,也不跳到独立工作台。点击生成后才创建 Match3D 会话并执行 `match3d_compile_draft`
表单只展示个输入块:
表单只展示个输入块:
1. `想做一个什么题材的抓大鹅?`:大文本输入框,收集 `themeText`
2. `2D素材风格`:横向滑动风格卡,选择会写入 `assetStyleId``assetStyleLabel``assetStylePrompt`
3. `难度`:四个选项按钮,选项内部派生消除次数和难度数值。
4. `生成音效`Toggle默认关闭开启后提交 `generateClickSound=true`
当前难度映射固定为:
@@ -69,7 +66,7 @@ badge: 可创建
自定义风格必须在弹出面板中填写描述后才能应用。入口表单必须在移动端创作页可视区内完成题材、风格、难度和生成按钮的展示,页面自身不产生纵向滚动;风格卡只允许横向滑动。
生成按钮文案为 `生成抓大鹅草稿`,按钮内必须同时展示 `消耗10泥点`。UI 中不默认展示玩法规则长文,也不展示隐藏派生数值的摘要框。
生成按钮文案为 `生成抓大鹅草稿`,按钮内必须同时展示 `消耗20光点`。UI 中不默认展示玩法规则长文,也不展示隐藏派生数值的摘要框。
## 5. mock client
@@ -115,7 +112,7 @@ POST /api/creation/match3d/sessions/:sessionId/compile
2. 切换到 `抓大鹅` Tab 后,页面内直接显示抓大鹅入口表单,不提前创建会话。
3. 表单不展示参考图、`需要消除次数``难度数值``题材``物品``难度`摘要框。
4. 输入题材、选择风格和难度后,提交 payload 包含派生后的 `clearCount``difficulty``referenceImageSrc``null`,并包含 `assetStyleId``assetStyleLabel``assetStylePrompt`
5. 生成按钮展示 `消耗10泥点`,创作页不展示 `生成音效` Toggle
5. 生成按钮展示 `消耗20光点`
6. 点击 `自定义` 风格弹出独立面板,填写后应用到提交 payload未填写时不能应用空自定义风格。
7. 移动端创作页内抓大鹅入口内容不产生纵向滚动,风格卡横向滑动。
8. 点击生成后创建会话并进入草稿生成/结果页链路。

View File

@@ -6,33 +6,33 @@
本轮在“我的”页面的“会员充值”入口落地账户充值弹窗,包含两个页签:
1. `点充值`
1. `点充值`
2. `会员卡充值`
前端只负责展示与发起购买,套餐、价格、赠送规则、会员权益、生效时间、钱包余额与交易流水统一由 `server-rs` 后端返回。支付接入固定为普通商户直连模式:小程序 web-view 使用 `wechat_mp`,手机微信内网页使用 `wechat_h5`,桌面微信内网页使用 `wechat_native` 二维码。生产默认永远不走 `mock`;只有自动测试或显式测试配置手动传 `paymentChannel = "mock"` 时才允许 mock 即时入账。所有真实微信渠道的到账事实以后端微信支付通知和服务端查单为准。
前端只负责展示与发起购买,套餐、价格、赠送规则、会员权益、生效时间、钱包余额与交易流水统一由 `server-rs` 后端返回。普通 H5 / 本地联调继续使用 `mock` 渠道:创建订单后立即写入余额或会员状态,并返回最新账户中心快照。微信小程序 web-view 使用 `wechat_mp` 渠道:创建订单时只写入 `pending` 订单并返回小程序 `wx.requestPayment` 参数,真实到账以后端微信支付通知为准。
## 2. 产品规则
### 2.1 点充值套餐
### 2.1 点充值套餐
| productId | 点 | 金额分 | 徽标 | 说明 |
| productId | 点 | 金额分 | 徽标 | 说明 |
| ------------- | ---: | -----: | -------- | -------------- |
| `points_60` | 60 | 600 | 首充双倍 | 首充送60点 |
| `points_180` | 180 | 1800 | 首充双倍 | 首充送180点 |
| `points_300` | 300 | 3000 | 首充双倍 | 首充送300点 |
| `points_680` | 680 | 6800 | 首充双倍 | 首充送680点 |
| `points_1280` | 1280 | 12800 | 首充双倍 | 首充送1280点 |
| `points_3280` | 3280 | 32800 | 首充双倍 | 首充送3280点 |
| `points_60` | 60 | 600 | 首充双倍 | 首充送60点 |
| `points_180` | 180 | 1800 | 首充双倍 | 首充送180点 |
| `points_300` | 300 | 3000 | 首充双倍 | 首充送300点 |
| `points_680` | 680 | 6800 | 首充双倍 | 首充送680点 |
| `points_1280` | 1280 | 12800 | 首充双倍 | 首充送1280点 |
| `points_3280` | 3280 | 32800 | 首充双倍 | 首充送3280点 |
点充值固定为 `¥6 / ¥18 / ¥30 / ¥68 / ¥128 / ¥328` 六个档位。全部档位参与首充双倍:用户历史上没有 `points_recharge` 流水时,本次购买到账点为基础点与等额赠送点之和;已有充值流水后只到账基础点。实际到账点写入交易流水,余额以 SpacetimeDB projection 为准。
点充值固定为 `¥6 / ¥18 / ¥30 / ¥68 / ¥128 / ¥328` 六个档位。全部档位参与首充双倍:用户历史上没有 `points_recharge` 流水时,本次购买到账点为基础点与等额赠送点之和;已有充值流水后只到账基础点。实际到账点写入交易流水,余额以 SpacetimeDB projection 为准。
### 2.2 会员卡套餐
| productId | 类型 | 天数 | 金额分 | 权益 |
| --------------- | ---- | ---: | -----: | --------------------------------- |
| `member_month` | 月卡 | 30 | 2800 | 免点回合数100每日签到加成0% |
| `member_season` | 季卡 | 90 | 7800 | 免点回合数100每日签到加成100% |
| `member_year` | 年卡 | 365 | 24800 | 免点回合数100每日签到加成210% |
| `member_month` | 月卡 | 30 | 2800 | 免点回合数100每日签到加成0% |
| `member_season` | 季卡 | 90 | 7800 | 免点回合数100每日签到加成100% |
| `member_year` | 年卡 | 365 | 24800 | 免点回合数100每日签到加成210% |
购买会员时,如果当前会员仍有效,则从当前到期时间顺延;如果已过期或从未购买,则从当前服务端时间开始计算。状态只区分 `普通` 与已生效会员,前端不自行推断。
@@ -42,8 +42,8 @@
需要 Bearer JWT。返回
1. 当前点余额、会员状态、到期时间
2. 点套餐与会员套餐
1. 当前点余额、会员状态、到期时间
2. 点套餐与会员套餐
3. 会员权益表
4. 最近订单摘要
@@ -56,30 +56,21 @@
```json
{
"productId": "points_300",
"paymentChannel": "wechat_h5"
"paymentChannel": "mock"
}
```
行为:
1. 校验 `productId`
2. 缺少 `paymentChannel` 或传入未知渠道时直接返回 `400`,不得再默认解释为 `mock`
3. 后端根据 Bearer JWT 中的 `device` 快照拦截真实微信渠道,不能只信任前端隐藏入口或请求体传入的 `paymentChannel`
- `wechat_mp` 只允许 `device.client_type = "mini_program"`
- `wechat_h5` 只允许 `device.client_type = "wechat_h5"``device.client_platform``ios``android`
- `wechat_native` 只允许 `device.client_type = "wechat_h5"``device.client_platform``windows``macos``linux`
- 缺少设备快照、普通浏览器设备、手机微信手动传 Native、桌面微信手动传 H5 都返回 `403`
4. 生产/真实支付配置拒绝 `paymentChannel = "mock"`mock 只服务自动测试或显式 mock 测试配置
- `wechat_mp` / `wechat_h5` / `wechat_native` 必须在 `WECHAT_PAY_ENABLED=true``WECHAT_PAY_PROVIDER=real` 时才允许下单;`WECHAT_PAY_PROVIDER=mock` 不能为真实微信渠道返回 mock 支付载荷。
5. `paymentChannel = "wechat_mp"` 时后端创建待支付订单,并调用微信支付 JSAPI 下单生成小程序支付参数;本地 `orderId` 会作为微信 `out_trade_no` 传递,格式固定为 `rcg` 前缀 + 小写字母数字,长度在 6-32 字符内,满足微信支付 JSAPI 下单文档对商户订单号的限制。商品描述限制为 127 字符内,回调地址限制为 HTTPS、255 字符内且不携带 query/fragment。
- JSAPI 下单请求必须显式携带 `Accept: application/json``Content-Type: application/json``User-Agent: Genarrative-WechatPay/1.0`;微信侧会把缺少 `User-Agent` 的请求返回为“Http头缺少Accept或User-Agent”。
6. `paymentChannel = "wechat_h5"` 时调用微信支付 H5 下单,返回 `wechatH5Payment.h5Url`,前端跳转到该地址
7. `paymentChannel = "wechat_native"` 时调用微信支付 Native 下单,返回 `wechatNativePayment.codeUrl`,前端在充值弹窗内把 `codeUrl` 渲染成二维码;该渠道只面向桌面微信内网页
8. 所有微信真实渠道订单不提前发泥点或会员,只返回待支付订单、账户中心快照与对应支付载荷
2. `paymentChannel = "mock"` 时后端创建已支付订单
3. `paymentChannel = "wechat_mp"` 时后端创建待支付订单,并调用微信支付 JSAPI 下单生成小程序支付参数
4. mock 光点套餐立即写入钱包余额与流水mock 会员套餐立即写入会员状态
5. wechat_mp 订单不提前发光点或会员,只返回待支付订单、账户中心快照与 `wechatMiniProgramPayParams`
兼容路径:`POST /api/runtime/profile/recharge/orders`
响应里的支付字段只在对应微信支付渠道返回。`wechatMiniProgramPayParams` 字段直接对应 `wx.requestPayment`
响应里的 `wechatMiniProgramPayParams` 只在微信小程序支付渠道返回,字段直接对应 `wx.requestPayment`
```json
{
@@ -93,62 +84,23 @@
}
```
H5 与 Native 响应:
```json
{
"wechatH5Payment": {
"h5Url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=..."
},
"wechatNativePayment": {
"codeUrl": "weixin://pay.weixin.qq.com/bizpayurl/up?pr=..."
}
}
```
### 3.3 `POST /api/profile/recharge/orders/{order_id}/wechat/confirm`
需要 Bearer JWT。该接口用于微信支付返回页面或 Native 扫码后的主动查单确认,不替代微信支付通知:
1. 后端读取本地 `profile_recharge_order` 并校验订单归属、支付渠道和当前状态;`wechat_mp` / `wechat_h5` / `wechat_native` 都可确认,`mock` 不能走该接口。
2. 若订单已是 `paid`,直接返回订单与账户中心快照。
3. 若订单仍是 `pending`,后端调用微信支付按商户订单号查单接口。
4. 只有微信查单返回 `trade_state = "SUCCESS"` 时,才调用统一入账 procedure 把订单改为 `paid` 并写入钱包流水或会员状态。
5. 如果微信查单仍不是 `SUCCESS`,接口返回当前 pending 订单与账户中心快照;前端只在全局支付结果模态显示“支付已提交”,不提前发放泥点或会员。
响应结构:
```json
{
"order": {
"orderId": "rcg...",
"status": "paid"
},
"center": {
"walletBalance": 120
}
}
```
### 3.4 `POST /api/profile/recharge/wechat/notify`
### 3.3 `POST /api/profile/recharge/wechat/notify`
微信支付通知地址,无需 Bearer JWT。行为
1. 真实渠道使用微信支付平台公钥和 `Wechatpay-*` 请求头验签;验签必须使用原始 HTTP body bytes 构造 `timestamp\nnonce\nbody\n`,不能先把 body 转成字符串再重建
1. 真实渠道使用微信支付平台公钥和 `Wechatpay-*` 请求头验签。
2. 使用 `WECHAT_PAY_API_V3_KEY` 解密通知 `resource`
3. 仅当 `trade_state = "SUCCESS"` 时确认订单支付。
4. 使用微信通知里的 `out_trade_no` 查本地 `profile_recharge_order.order_id`,把订单从 `pending` 改为 `paid`
5. 将微信平台订单号写入 `provider_transaction_id`,用于对账、查单、退款和客服排障。
6. 在同一 SpacetimeDB procedure 内写入钱包流水或会员到期时间,确保重复通知幂等。
7. 验签、解密和业务确认通过后返回 HTTP `204 No Content`;不要返回 V2 XML。
8. 微信支付公钥模式下,真实请求会携带 `Wechatpay-Serial: PUB_KEY_ID_...`,通知验签必须要求回调头 `Wechatpay-Serial``WECHAT_PAY_PLATFORM_SERIAL_NO` 对应;若不匹配应返回 `401` 并在日志里记录 reason。
关键环境变量:
| 变量 | 说明 |
| ---------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `WECHAT_PAY_ENABLED` | 是否启用微信支付客户端 |
| `WECHAT_PAY_PROVIDER` | `mock``real`;真实微信渠道只能使用 `real``mock` 只允许显式测试渠道 |
| `WECHAT_PAY_PROVIDER` | `mock``real` |
| `WECHAT_PAY_MCH_ID` | 微信支付商户号 |
| `WECHAT_PAY_MERCHANT_SERIAL_NO` | 商户 API 证书序列号,用于请求微信支付签名头 |
| `WECHAT_PAY_PRIVATE_KEY_PEM` / `WECHAT_PAY_PRIVATE_KEY_PATH` | 商户 API 私钥 |
@@ -161,25 +113,15 @@ H5 与 Native 响应:
1. “我的”页会员充值按钮打开独立弹窗,不在当前面板下方展开。
2. 弹窗顶部标题为 `账户充值`,右上角关闭。
3. 默认打开 `点充值`,可切换到 `会员卡充值`
3. 默认打开 `点充值`,可切换到 `会员卡充值`
4. 点击套餐后调用下单接口,按钮进入处理中状态;小程序环境走 native 支付页拉起 `wx.requestPayment`,支付页返回后刷新 `profileDashboard`
- 支付渠道由 `src/services/payment/paymentPlatform.ts` 统一判断,业务 UI 不内联区分小程序、手机网页和桌面网页
- 小程序 web-view 内的 H5 只负责加载微信 JS-SDK 并通过 `wx.miniProgram.navigateTo` 跳转到 `/pages/wechat-pay/index`;实际支付必须在小程序 native 页调用 `wx.requestPayment`,不要切换为 H5 支付产品
- native 支付页通过 `wx_pay_result=<requestId>:success|cancel|fail` 回填 web-viewH5 在 `hashchange``focus``pageshow``visibilitychange` 中都会尝试消费该结果,避免小程序返回 web-view 时没有触发单一事件导致状态不刷新。
- `success` 只表示微信客户端支付流程返回成功,前端随后调用 `POST /api/profile/recharge/orders/{order_id}/wechat/confirm` 由服务端查单确认;只有通知或服务端查单确认为 `SUCCESS` 才入账。
- 小程序返回后,前端会对确认接口做短轮询,覆盖微信通知/查单结果与 web-view 恢复之间的秒级时间差;只有确认响应里的订单状态变成 `paid` 后,才触发父级 `profileDashboard` 刷新,确保“我的”页泥点卡片读取到最新余额。
- `cancel``fail` 只复位按钮、刷新账户中心并通过全局支付结果模态展示,不调用入账逻辑。
5. 手机微信内 H5 首版统一走 `wechat_h5`:拿到 `h5Url` 后跳转;若微信内 H5 调起失败,失败态提示用户改用系统浏览器或小程序。
6. 桌面微信内网页走 `wechat_native`:充值弹窗展示二维码,用户扫码后点击“我已支付”,前端调用 confirm 接口短轮询确认;确认前不刷新父级余额。
7. 支付结果使用页面级全局模态展示,不写回商品卡片或账户充值弹窗内部;充值弹窗只负责套餐选择、加载失败和下单失败。
8. 弹窗内不写大段说明文案,只保留必要金额、泥点、会员权益和操作状态。
9. 会员卡充值区以套餐卡片优先展示周期、价格和处理状态;移动端单列,桌面端三列,权益表允许横向滚动,避免小屏挤压。
5. 弹窗内不写大段说明文案,只保留必要金额、光点、会员权益和状态反馈
6. 会员卡充值区以套餐卡片优先展示周期、价格和处理状态;移动端单列,桌面端三列,权益表允许横向滚动,避免小屏挤压
## 5. 验收
1. 普通用户打开弹窗能看到点与会员套餐。
2. 默认平台通道只会解析到 `wechat_mp` / `wechat_h5` / `wechat_native`,不会解析到 `mock`
3. 泥点购买后余额增加,流水来源为 `points_recharge`
4. 首充赠送只在首次泥点充值时生效
5. 会员购买后会员状态与到期时间立即更新。
6. 移动端弹窗单列可滚动,桌面端接近参考图卡片网格。
1. 普通用户打开弹窗能看到点与会员套餐。
2. 光点购买后余额增加,流水来源为 `points_recharge`
3. 首充赠送只在首次光点充值时生效
4. 会员购买后会员状态与到期时间立即更新
5. 移动端弹窗单列可滚动,桌面端接近参考图卡片网格。

View File

@@ -13,9 +13,9 @@
## 2. 前端交互
### 2.1 陶泥号复制
### 2.1 百梦号复制
1. 点击“我的”页陶泥号后的复制按钮后,按钮文案临时切换为 `已复制`
1. 点击“我的”页百梦号后的复制按钮后,按钮文案临时切换为 `已复制`
2. 复制失败时临时切换为 `复制失败`
3. 状态自动恢复为 `复制`
@@ -84,7 +84,7 @@ SpacetimeDB 正式表 `user_account` 需要增加 `avatar_url: Option<String>`
## 5. 验收
1. 创作页已发布作品分享按钮点击后显示 `已复制`
2. “我的”页陶泥号复制按钮点击后显示 `已复制`
2. “我的”页百梦号复制按钮点击后显示 `已复制`
3. “我的”页不展示 `手机号``正常` 标签。
4. 昵称编辑成功后,资料卡与顶部账号入口同步新昵称。
5. 昵称与头像裁剪弹窗面板不透明,不能露出底层页面内容。

Some files were not shown because too many files have changed in this diff Show More