Prune stale docs and update .hermes content

Delete a large set of outdated documentation (many files under docs/ and .hermes/plans/, including audits, design, prd, technical, planning, assets, and todos). Update and consolidate .hermes content: refresh shared-memory pages (decision-log, development-workflow, document-map, pitfalls, project-overview, team-conventions) and several skills/references under .hermes/skills. Also modify AGENTS.md, README.md, UI_CODING_STANDARD.md, docs/README.md and .encoding-check-ignore. Purpose: clean up stale planning/audit material and keep current hermes documentation and related top-level docs in sync.
This commit is contained in:
2026-05-15 06:24:07 +08:00
parent 2eded08bc7
commit 3cb3efb4d0
708 changed files with 4033 additions and 142328 deletions
-5
View File
@@ -1,11 +1,6 @@
# Temporary baseline for legacy files that already contain broken text. # Temporary baseline for legacy files that already contain broken text.
# Remove a path from this list as soon as the file is repaired. # Remove a path from this list as soon as the file is repaired.
docs/audits/text/GAME_EDITOR_PRESET_TEXT_AUDIT_2026-03-29.md
docs/audits/text/GAME_UI_PRESET_EDITOR_TEXT_AUDIT_2026-03-30_CONTINUED.md
docs/audits/text/GAME_UI_PRESET_EDITOR_TEXT_AUDIT_2026-03-31.md
docs/audits/text/GAME_UI_PRESET_EDITOR_TEXT_AUDIT_2026-04-01.md
docs/audits/text/GAME_UI_PRESET_EDITOR_TEXT_AUDIT_2026-04-02.md
src/components/AdventurePanel.tsx src/components/AdventurePanel.tsx
src/data/customWorldCharacterLoadout.ts src/data/customWorldCharacterLoadout.ts
dist_check_monster_position/** dist_check_monster_position/**
+1 -2
View File
@@ -10,6 +10,7 @@
- 开发前先阅读本目录下与任务相关的记忆文件;开发后如产生稳定知识,更新对应文档。 - 开发前先阅读本目录下与任务相关的记忆文件;开发后如产生稳定知识,更新对应文档。
- 后续新增的 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`,便于团队跨目录检索。 - 后续新增的 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`,便于团队跨目录检索。
- 若本目录内容与 `docs/` 或代码事实冲突,以当前代码和最新 `docs/` 为准,并同步修正过期记忆。 - 若本目录内容与 `docs/` 或代码事实冲突,以当前代码和最新 `docs/` 为准,并同步修正过期记忆。
- 阶段性计划、一次性 TODO 和已关闭实验不再长期沉淀为仓库文档;仍有效内容应合并进 `docs/` 当前融合文档或 `.hermes/shared-memory/`
## 目录结构 ## 目录结构
@@ -24,8 +25,6 @@
│ ├─ decision-log.md # 长期决策记录 │ ├─ decision-log.md # 长期决策记录
│ ├─ pitfalls.md # 踩坑与排障记录 │ ├─ pitfalls.md # 踩坑与排障记录
│ └─ handoff-template.md # 任务交接模板 │ └─ handoff-template.md # 任务交接模板
├─ plans/ # 阶段性计划与实施方案
├─ todos/ # 已定稿但尚未执行的共享 TODO 计划
├─ skills/ # 仓库级 Hermes skills ├─ skills/ # 仓库级 Hermes skills
└─ plugins/ # 仓库级 Hermes plugins(需显式启用项目 plugin └─ plugins/ # 仓库级 Hermes plugins(需显式启用项目 plugin
``` ```
File diff suppressed because it is too large Load Diff
@@ -1,271 +0,0 @@
# 邀请码有效期与后台二次确认实施计划
> **For Hermes:** 按 plan 模式,仅输出并保存实施计划,不直接改业务代码。
**Goal:** 为邀请码新增开始日期与截止日期,并让后台所有会修改数据的操作在提交前增加二次确认,降低误操作风险。
**Architecture:**
邀请码仍作为“用户稳定邀请身份码”保留,不做停用删除;在数据层增加 `starts_at` / `expires_at`,前台填写邀请码时按时间窗校验,后台列表与编辑页展示状态。后台所有写操作统一先弹二次确认,再真正调用 API,避免对兑换码、邀请码、任务配置等管理动作误触发。
**Tech Stack:**
Rust / SpacetimeDB / Axum / shared-contracts / TS + React 的 admin-web。
---
## 当前上下文
- 邀请码当前只有 `user_id``invite_code``metadata_json``created_at``updated_at`,没有状态字段。
- 目前后台存在邀请码管理入口,但没有停用能力,也没有有效期概念。
- 邀请码用于 `redeem_profile_referral_invite_code` 时的实时校验,适合增加“时间窗”而不是“禁用删除”。
- 后台已存在兑换码、任务配置等可写操作;本次要求把所有后台操作统一加二次确认,包括新增、编辑、禁用、删除等写入口。
---
## 设计原则
1. **邀请码不做软删除**:保留历史记录和邀请链路。
2. **有效期由时间窗推导**
- `starts_at` 为空表示立即生效。
- `expires_at` 为空表示长期有效。
3. **前台只拒绝新绑定**:已绑定关系不回溯修改。
4. **后台写操作统一确认**:所有会触发 POST / PATCH / DELETE 的管理动作,在真正提交前必须弹出二次确认。
5. **尽量少改接口语义**:优先在现有 admin upsert/list 体系内扩展字段,而不是新增一套并行 API。
---
## 方案概要
### 邀请码时间窗
新增字段:
- `starts_at: Option<Timestamp>`
- `expires_at: Option<Timestamp>`
校验规则:
- 当前时间 `< starts_at`:返回“邀请码未生效”
- 当前时间 `>= expires_at`:返回“邀请码已过期”
- 其他情况允许填写
建议把状态展示为:
- 未生效
- 有效
- 已过期
- 长期有效(两个字段都为空或仅无截止)
### 后台二次确认
对 admin-web 所有管理动作统一加确认弹窗/对话框,至少覆盖:
- 兑换码新增/更新
- 兑换码停用
- 邀请码新增/更新
- 任务配置新增/更新
- 任务配置停用
- 其他后续新增的后台写操作
确认文案要求:
- 显示对象标识(如 code / inviteCode / taskId
- 显示操作类型(新增 / 更新 / 停用)
- 明确提醒“该操作会立即影响线上数据”
- 允许取消返回,不调用 API
---
## 预期修改文件
### 1. 服务端领域与契约
- `server-rs/crates/spacetime-module/src/runtime/profile.rs`
- `ProfileInviteCode` 表结构新增开始/截止字段
- 邀请码 upsert 逻辑写入时间窗
- 邀请码 redeem 逻辑增加时间窗校验
- 邀请中心快照补充时间窗/状态
- `server-rs/crates/spacetime-module/src/migration.rs`
- 兼容旧表数据,给旧邀请码补默认空值
- `server-rs/crates/shared-contracts/src/runtime*.rs` 或对应生成/手写契约文件
- `AdminUpsertProfileInviteCodeRequest` 扩展字段
- `ProfileInviteCodeAdminResponse` 扩展字段
- 如需要,增加时间窗相关状态枚举或派生字段
- `server-rs/crates/spacetime-client/src/module_bindings/*`
- 重新生成 bindings
- mapper 补齐新字段
### 2. API Server
- `server-rs/crates/api-server/src/runtime_profile.rs`
- 接收/转发邀请码时间窗参数
- 返回新增字段给后台
- 如需要,调整校验错误文案
- `server-rs/crates/api-server/src/app.rs`
- 若有新路由或错误码需挂接,在此统一登记
### 3. Admin Web
- `apps/admin-web/src/api/adminApiTypes.ts`
- 增加邀请码时间窗字段
- 如有需要,增加后台操作请求结构字段
- `apps/admin-web/src/api/adminApiClient.ts`
- 透传新的请求/响应字段
- `apps/admin-web/src/app/adminRoutes.ts`
- 不一定需要改,但如果新增独立页面/子面板,需要在此登记
- `apps/admin-web/src/styles/admin.css`
- 确认弹窗与时间窗展示样式
- `apps/admin-web/src/**` 实际管理页面组件
- 邀请码编辑表单
- 邀请码列表状态展示
- 所有写操作前的二次确认弹窗
### 4. 文档
- `docs/technical/``docs/design/`
- 补一份邀请码时间窗与后台确认交互说明
- 如现有文档已经覆盖后台管理规范,则优先补充现有文档,不重复造新说明页
---
## 分步实施计划
### Task 1: 明确数据模型与契约扩展
**Objective:** 定义邀请码开始/截止日期字段及其在响应中的展示方式。
**要点:**
- 确认字段名采用 `starts_at` / `expires_at`,避免与现有字段语义冲突。
- 确认时间类型统一用 `Timestamp` / 毫秒微秒整数转换策略。
- 明确返回给后台的字段是否需要附带派生状态(如 `status`)。
**产出:**
- 契约字段定义
- 状态枚举/派生规则
---
### Task 2: 更新 SpacetimeDB 表与迁移
**Objective:** 让邀请码表可保存有效期,并兼容旧数据。
**要点:**
- 修改 `ProfileInviteCode` 表结构。
- 更新迁移逻辑,旧记录默认无开始/截止。
- 检查是否需要补充索引或查询辅助字段。
**验证:**
- 旧数据能正常读取。
- 新数据能写入开始/截止。
---
### Task 3: 实现邀请填写时的时间窗校验
**Objective:** 在邀请码被填写时正确拒绝未生效或已过期的邀请码。
**要点:**
-`redeem_profile_referral_invite_code_record` 内增加开始/截止校验。
- 保持“自己的邀请码不能填”“邀请码不存在”等原有错误优先级清晰。
- 保留历史绑定关系不受影响。
**验证:**
- 未到开始时间时返回明确错误。
- 超过截止时间时返回明确错误。
- 正常区间可绑定成功。
---
### Task 4: 扩展后台邀请码管理接口
**Objective:** 让后台可以创建/修改邀请码时间窗,并在列表中查看状态。
**要点:**
- 扩展 `AdminUpsertProfileInviteCodeRequest`
- 扩展 `ProfileInviteCodeAdminResponse`
- `api-server` 接口负责接收新字段并转发。
- 列表接口返回可读时间字段与状态。
**验证:**
- 后台表单提交后,返回结果包含时间窗信息。
- 列表页能看到状态与时间。
---
### Task 5: 给后台所有写操作加二次确认
**Objective:** 统一拦截所有后台写动作,避免误点直接生效。
**覆盖范围建议:**
- 邀请码新增/更新
- 兑换码新增/更新/停用
- 任务配置新增/更新/停用
- 后续新增的管理写操作
**实现要求:**
- 在真正调用 API 之前弹出确认框。
- 确认框需要展示对象名、操作类型、影响范围。
- 取消后不发送请求。
- 尽量抽象出通用确认组件/通用 action 包装函数,避免每个页面重复写。
**验证:**
- 点击“保存”不会直接提交,需先确认。
- 点击“取消”不会发请求。
- 所有后台写入口行为一致。
---
### Task 6: 补充文档与交互说明
**Objective:** 把新规则写进项目文档,避免后续实现偏差。
**要点:**
- 记录邀请码时间窗语义。
- 记录后台二次确认规范。
- 说明哪些动作属于“必须确认”的写操作。
---
## 测试与验证
### 服务端
- 邀请码时间窗单测 / 集成测试
- 邀请码 redeem 流程回归测试
- 旧数据兼容测试
### API / 前端
- 管理后台列表展示正确
- 表单提交能回传新字段
- 二次确认取消后不请求接口
- 二次确认确认后正常提交
### 推荐验证命令
- 视项目现有脚本执行对应后端测试
- 前端按 admin-web 构建/测试脚本验证
- 如涉及生成绑定,先确认生成产物无漏字段
---
## 风险与权衡
1. **时间字段格式不统一**
- 风险:前后端对时间单位理解不一致。
- 处理:在契约层明确是 ISO 字符串还是微秒整数,并全链路统一。
2. **后台“所有操作”范围过大**
- 风险:遗漏某些写入口。
- 处理:先枚举现有写 API,再做统一确认封装。
3. **邀请码过期后历史链接解释成本**
- 风险:用户误以为历史邀请码失效影响已绑定关系。
- 处理:文案明确“仅影响新填写,不影响已绑定记录”。
4. **契约与生成绑定联动较多**
- 风险:字段变更后生成文件数量较多。
- 处理:先改源契约与服务端,再统一重生成 bindings。
---
## 待确认问题
1. `starts_at` / `expires_at` 在接口里要返回 **ISO 字符串** 还是 **微秒整数**
2. 后台二次确认是否统一用一个全局弹窗组件,还是页面级本地实现?
3. 邀请码列表是否需要直接展示“状态标签”还是只展示时间字段由前端推导?
4. 现有后台所有写操作里,是否还要覆盖调试类接口,还是仅覆盖业务管理接口?
---
## 建议执行顺序
1. 先确认时间字段格式与确认弹窗范围。
2. 再改服务端契约与迁移。
3. 再改 redeem 校验与后台接口。
4. 最后统一改 admin-web 的二次确认与表单展示。
---
**结论:** 这是一个适合分阶段落地的改动,建议先做“邀请码时间窗 + 后台统一二次确认”的基础能力,再补交互细节。
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,310 +0,0 @@
# K6 作品列表压测计划(使用 spacetime-migration-7.json 作为数据源)
## 目标
使用 K6 对 Genarrative 的“作品列表”相关接口进行压测,并将用户提供的 `spacetime-migration-7.json` 作为压测数据源;数据处理时**只导入作品列表相关数据**,不导入用户、会话、钱包、埋点、运行存档等非作品表,避免把敏感或无关数据带入压测环境。
## 当前上下文
- 工作区:`/c/proj/Genarrative`
- 原始迁移文件:`C:\Users\DSK\AppData\Local\hermes\cache\documents\doc_150e84029b2d_spacetime-migration-7.json`
- 已确认原始迁移文件结构:
- `schema_version = 1`
- `tables = 53`
- 作品相关表中当前有数据的重点表:
- `puzzle_work_profile`80 行
- `custom_world_profile`1 行
- `match3d_work_profile`0 行
- `big_fish_*`:当前样本中相关表为 0 行
- 原始文件还包含 `user_account``auth_identity``refresh_session``profile_wallet_ledger``asset_object`、运行记录等数据,压测导入时必须过滤。
- 当前仓库未发现现成 K6 脚本或 `k6` 相关文件,需要新增压测脚本与数据提取脚本。
- `package.json` 当前有 `dev/dev:rust/test/check` 等脚本,未发现 K6 npm script。
## 范围约束
### 本次只导入/使用
1. 作品列表表:
- `puzzle_work_profile`
- `custom_world_profile`
- 后续若接口覆盖其他玩法,可扩展:
- `match3d_work_profile`
- `square_hole_work_profile`(以实际 SpacetimeDB 表名为准)
- `big_fish_work_profile`(以实际 SpacetimeDB 表名为准)
- `visual_novel_work_profile`(以实际 SpacetimeDB 表名为准)
2. 为作品列表卡片展示所需的最小字段:
- 稳定 ID`profile_id``work_id``public_work_code`
- 标题:`work_title` / `level_name` / `world_name`
- 描述:`work_description` / `summary` / `summary_text` / `subtitle`
- 作者:`owner_user_id``author_display_name``author_public_user_code`
- 封面:`cover_image_src``cover_asset_id`(如果接口只返回 asset id,则压测阶段不额外导入二进制 asset)
- 状态与计数:`publication_status``published_at``play_count``like_count``remix_count`
- 作品内容摘要:`levels_json``profile_payload_json``theme_tags_json` 等列表渲染或进入作品详情可能需要的 JSON 字段
### 本次不导入/不使用
- 认证与账号:`user_account``auth_identity``refresh_session``auth_store_snapshot`
- 用户资产与钱包:`profile_wallet_ledger``profile_dashboard_state``profile_redeem_*``profile_invite_*`
- 游玩历史/存档/运行态:`profile_played_world``public_work_play_daily_stat``puzzle_runtime_run``profile_save_archive``runtime_snapshot`
- AI 任务过程:`ai_task``ai_task_stage``ai_text_chunk`
- asset 二进制与绑定:`asset_object``asset_entity_binding`,除非后续确认作品列表接口强依赖它们;即便需要,也只导入作品列表封面所需的最小 metadata,不导入原始大对象。
## 推荐目录与文件
建议新增:
```text
.hermes/plans/2026-05-11_195214-k6-works-list-load-test-plan.md # 本计划
scripts/loadtest/extract-works-list-data.mjs # 从迁移文件提取作品列表数据
scripts/loadtest/k6-works-list.js # K6 压测脚本
scripts/loadtest/data/works-list.sample.json # 过滤后的样例数据(不要提交敏感原始迁移全量)
scripts/loadtest/README.md # 执行说明与指标阈值
```
可选新增 npm scripts
```json
{
"loadtest:extract-works": "node scripts/loadtest/extract-works-list-data.mjs",
"loadtest:k6:works": "k6 run scripts/loadtest/k6-works-list.js"
}
```
## 数据提取方案
### 输入
默认读取:
```bash
node scripts/loadtest/extract-works-list-data.mjs \
--input "C:/Users/DSK/AppData/Local/hermes/cache/documents/doc_150e84029b2d_spacetime-migration-7.json" \
--output scripts/loadtest/data/works-list.local.json
```
### 输出结构
建议输出为 K6 直接可读的 JSON:
```json
{
"source": "spacetime-migration-7.json",
"generatedAt": "<iso datetime>",
"tables": {
"puzzle_work_profile": [
{
"profile_id": "...",
"work_id": "...",
"owner_user_id": "...",
"work_title": "...",
"work_description": "...",
"publication_status": "Published",
"published_at": { "__timestamp_micros_since_unix_epoch__": 0 },
"play_count": 0,
"like_count": 0,
"levels_json": "..."
}
],
"custom_world_profile": []
},
"workIds": {
"puzzle": ["<profile_id>"],
"customWorld": ["<profile_id>"]
}
}
```
### 过滤原则
1.`tables[].name` 白名单过滤,只保留作品 profile 表。
2. 对每个 row 再按字段白名单过滤,避免误带账号、手机号、token、钱包流水等字段。
3. 对特别大的字段进行处理:
- `cover_image_src` 如果是 `data:image/...base64`,默认替换为占位符或截断,避免压测数据文件过大。
- `levels_json``profile_payload_json` 保留原文,但可以记录大小;如果过大,再提供 `--compact` 选项只保留摘要。
4. 输出 `.local.json` 默认加入 `.gitignore`;如果要提交样例数据,只提交脱敏/裁剪后的 `works-list.sample.json`
## K6 压测接口矩阵
需要先确认本地 api-server 实际端口。默认以 `http://127.0.0.1:8787` 为例,实际运行时通过环境变量覆盖:
```bash
BASE_URL=http://127.0.0.1:<actual-api-port> k6 run scripts/loadtest/k6-works-list.js
```
初版建议覆盖以下“作品列表”读接口,具体路径以仓库服务端路由为准,实施时需要通过搜索 api-server 路由确认:
| 场景 | 目的 | 候选路径 |
| --- | --- | --- |
| 拼图作品列表 | 作品列表主场景之一,当前数据量最多 | `/api/creation/puzzle/works` 或实际 puzzle works list route |
| RPG/自定义世界作品列表 | 使用 `custom_world_profile` 数据 | `/api/creation/custom-world/works` 或实际 custom world works route |
| 作品详情/启动前读取 | 模拟用户从列表点进作品 | `/api/creation/*/works/:profileId``/api/runtime/*/works/:profileId` |
| 公开作品库 | 如果首页/发现页依赖 | `/api/runtime/*/works` 或 gallery/list route |
> 注意:不要凭空固定 endpoint。实施阶段先用 `search_files` / 路由源码确认真实路径,再写入 K6 脚本。
## K6 场景设计
### 阶段 1:基线 smoke
目的:确认脚本、数据和目标服务可用。
```js
export const options = {
scenarios: {
smoke: {
executor: 'constant-vus',
vus: 1,
duration: '30s'
}
},
thresholds: {
http_req_failed: ['rate<0.01'],
http_req_duration: ['p(95)<800']
}
};
```
### 阶段 2:常规读压
目的:模拟日常列表浏览。
- `constant-vus`: 10/25/50 三档
- 每个 VU 随机选择作品类型和列表分页参数
- `sleep(0.5~2s)` 模拟用户停留
- 阈值建议:
- `http_req_failed < 1%`
- `p95 < 800ms`
- `p99 < 1500ms`
### 阶段 3:峰值/突刺
目的:模拟首页入口或活动导致的作品列表突增。
- `ramping-arrival-rate`
- 从 5 RPS 增长到 100 RPS,维持 2~5 分钟,再降回
- 单独输出 `checks`:列表接口状态码、响应 JSON shape、items 数量
### 阶段 4:容量探索
目的:找瓶颈,不作为每次回归必跑。
- 每轮提升 RPS 或 VU
- 观察:api-server CPU/内存、SpacetimeDB 日志、错误率、p95/p99
- 一旦 `http_req_failed >= 5%` 或 p95 持续超过 2s,停止继续加压并记录容量点。
## K6 脚本设计要点
1. 使用 `SharedArray` 加载 `works-list.local.json`,避免每个 VU 重复解析大 JSON。
2. 基于数据源里的 `profile_id` / `work_id` 随机抽样,保证请求覆盖真实作品 ID。
3. 对列表接口添加分页/排序 query,例如:
- `?limit=20&offset=0`
- `?pageSize=20&cursor=...`(以真实 API 为准)
4. 使用 `check()` 验证:
- HTTP 200
- 响应体是 JSON
- `items``works` 是数组
- 列表项包含 `profileId/profile_id`、标题字段、状态字段
5. 使用 `Trend` / `Rate` 细分指标:
- `works_list_duration`
- `works_detail_duration`
- `works_list_shape_error_rate`
6. 支持环境变量:
```bash
BASE_URL=http://127.0.0.1:8787 \
WORKS_DATA=scripts/loadtest/data/works-list.local.json \
SCENARIO=baseline \
k6 run scripts/loadtest/k6-works-list.js
```
## 实施步骤
1. **确认路由**
- 搜索 api-server / BFF 的作品列表路由。
- 明确各玩法对应 endpoint、鉴权要求、分页参数、返回字段。
2. **实现数据提取脚本**
- 新增 `scripts/loadtest/extract-works-list-data.mjs`
- 只按表白名单读取作品列表 profile 表。
- 对字段做白名单与脱敏/截断。
- 输出 `works-list.local.json`
3. **生成本地压测数据**
- 用用户提供的迁移文件生成 `scripts/loadtest/data/works-list.local.json`
- 验证输出只包含作品表和作品字段。
4. **实现 K6 脚本**
- 新增 `scripts/loadtest/k6-works-list.js`
- 支持 `BASE_URL``WORKS_DATA``SCENARIO`
- 覆盖列表接口,必要时增加详情/启动前读取接口。
5. **新增执行说明**
-`scripts/loadtest/README.md` 写明:安装 K6、启动本地 dev 栈、提取数据、运行 smoke/baseline/spike、查看结果。
6. **本地验证**
- 启动 Genarrative dev 栈;注意端口可能漂移,使用实际 api-server 端口。
- 跑 smoke`SCENARIO=smoke`
- 确认失败率、p95、响应 shape。
7. **可选集成 npm scripts**
- 如果团队希望标准化入口,再加入 `package.json` scripts。
8. **记录结果**
- 将 smoke/baseline/spike 的结果摘要追加到 `scripts/loadtest/README.md` 或单独保存到 `.hermes/plans/` 的结果文档中。
## 启动与运行建议
本地服务启动按当前 Genarrative dev 栈约定:
```bash
npm run dev
```
如果 SpacetimeDB/API/Vite 端口被占用,项目脚本会寻找可用端口;压测时必须从启动日志中读取实际 api-server 地址,并传给 K6
```bash
BASE_URL=http://127.0.0.1:<actual-api-port> \
WORKS_DATA=scripts/loadtest/data/works-list.local.json \
SCENARIO=smoke \
k6 run scripts/loadtest/k6-works-list.js
```
## 验证标准
### 数据源验证
- `works-list.local.json` 中只出现作品 profile 表。
- 不出现以下字段或内容:
- `password_hash`
- `refresh_token_hash`
- `phone_number_e164`
- `phone_number_masked`
- `wallet_ledger_id`
- `auth_identity`
- `user_account`
- `puzzle_work_profile` 行数应接近原始文件中的 80 行。
- `custom_world_profile` 行数应接近原始文件中的 1 行。
### K6 smoke 验证
- 所有目标接口返回 2xx。
- `http_req_failed < 1%`
- 响应 JSON shape 与 shared contracts 对齐:`items``works` 数组。
- K6 输出中能区分不同 endpoint 的耗时。
### 性能阈值初稿
- Smoke`p95 < 800ms`,失败率 `< 1%`
- Baseline`p95 < 1000ms``p99 < 2000ms`,失败率 `< 1%`
- Spike:允许短暂 p95 抖动,但 1 分钟内应恢复;失败率 `< 5%`
阈值后续需要结合本地机器性能、SpacetimeDB 本地模式和正式部署规格调整。
## 风险与注意事项
1. **原始迁移文件包含敏感数据。** 必须只提取作品列表白名单字段,禁止把原始 JSON 全量提交到仓库。
2. **base64 封面可能导致压测数据膨胀。** 默认截断或替换为占位符,除非本次明确要测封面 payload 对响应体积的影响。
3. **本地 SpacetimeDB 与 api-server 端口会漂移。** 不要硬编码端口,运行时通过 `BASE_URL` 注入。
4. **列表接口可能需要鉴权。** 若实际接口要求登录,不要导入真实 refresh session;应使用本地测试账号或专门的压测 token 生成流程。
5. **作品表名/接口路径可能与候选名称不完全一致。** 实施前必须以源码路由为准。
6. **本计划仅保存压测方案,不执行实际压测。** 后续执行时再创建/修改脚本、导出过滤数据、跑 K6 并记录结果。
## 开放问题
1. 压测目标是本地 dev 栈、测试环境,还是预发/生产只读接口?不同环境阈值和安全边界不同。
2. “作品列表”是否只包含拼图和自定义世界,还是要覆盖 match3d、square-hole、big-fish、visual-novel 的统一列表入口?
3. 是否允许使用专门压测账号/token?如果接口无鉴权则无需处理。
4. 是否需要测封面/asset 加载,还是只测作品列表 JSON API?
@@ -1,447 +0,0 @@
# Genarrative 容灾方案设计计划
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
**Goal:** 基于当前 Genarrative 单机生产部署、Jenkins 流水线、SpacetimeDB 与 Rust `api-server` 架构,补齐一套可落地、可演练、可审计的容灾方案。
**Architecture:** 首版容灾不引入复杂多活系统,优先围绕现有 `systemd + Nginx + SpacetimeDB + api-server + Jenkins` 单机生产推荐方案做“备份可恢复、版本可回滚、故障可切换、演练可复盘”。方案采用分层容灾:入口层、静态资源层、API 服务层、SpacetimeDB 数据层、外部服务与密钥层、Jenkins/发布链路层。
**Tech Stack:** Nginx、systemd、SpacetimeDB self-hosting、Rust `api-server` / Axum、Jenkins Pipeline、Shell/Node.js 运维脚本、仓库 `deploy/``docs/technical/` 文档体系。
---
## 1. 当前上下文与已确认事实
### 1.1 当前生产部署口径
来自 `docs/technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md` 的现状:
- 生产为单机推荐方案,不使用 Docker。
- 公网入口为 Nginx,负责 HTTPS、静态站点、后台静态页面、维护页、`/admin/api/` 与临时 `/api/*` 反向代理。
- SpacetimeDB 作为 systemd 服务运行:
- `spacetimedb.service`
- 监听:`127.0.0.1:3101`
- 数据根目录:`/stdb`
- Rust `api-server` 作为 systemd 服务运行:
- `genarrative-api.service`
- 监听:`127.0.0.1:8082`
- 环境文件:`/etc/genarrative/api-server.env`
- 静态站点发布到 release/current 目录:
- `/opt/genarrative/releases/<version>/`
- `/opt/genarrative/current`
- `/srv/genarrative/web`
- 已有维护模式:
- 开关文件:`/var/lib/genarrative/maintenance/enabled`
- API 发布、SpacetimeDB 模块发布、数据库导入、服务器配置变更必须进入维护模式。
- 已有数据库导入导出 Jenkins Job
- `Genarrative-Database-Export`
- `Genarrative-Database-Import`
- 对应文件:`jenkins/Jenkinsfile.production-database-export``jenkins/Jenkinsfile.production-database-import`
- 已有回滚基本口径:
- Web 回滚:切 `/srv/genarrative/web``/opt/genarrative/current` 到上一版本并 reload Nginx。
- API 回滚:切 `/opt/genarrative/current` 到上一版本并重启 `genarrative-api.service`
- SpacetimeDB 模块回滚:发布上一版本 `spacetime_module.wasm`
- 数据回滚:使用导入流水线恢复指定备份,必须进入维护模式。
### 1.2 关键风险
- 当前是单机生产拓扑,单机磁盘、系统盘、`/stdb`、Nginx 或公网 IP 故障会造成整体不可用。
- SpacetimeDB 是核心业务真相,容灾重点必须围绕 `/stdb`、数据库导出产物、schema 迁移与导入验证。
- `/etc/genarrative/api-server.env` 持有生产密钥,不能进入 Git,也不能写进普通备份明文归档。
- Jenkins controller/agent 同时承担构建、发布、备份、导入导出编排;Jenkins 不可用时仍需要有最小人工恢复路径。
- 外部 LLM、图片、语音、3D 网关不是本仓库可控系统,容灾只能做到配置降级、超时隔离、能力熔断与可观测告警。
---
## 2. 容灾目标
### 2.1 恢复目标建议
| 灾难类型 | 目标 RTO | 目标 RPO | 首版策略 |
| --- | ---: | ---: | --- |
| Web 静态资源发布失败 | 5 分钟 | 0 | release/current 原子切换回滚 |
| API 发布失败 | 10 分钟 | 0 | 维护模式 + 上一版二进制回滚 |
| SpacetimeDB wasm 发布失败 | 15 分钟 | 0 或按迁移前备份 | 发布前导出 + 上一版 wasm 回滚 |
| 数据误写 / 迁移失败 | 30-60 分钟 | 最近一次导出点 | 导入流水线从备份恢复 |
| 生产机磁盘损坏 | 2-4 小时 | 最近一次异地备份 | 新机器 provision + 拉取 release 包 + 恢复数据库 |
| Jenkins controller 不可用 | 1-2 小时 | 不影响线上数据 | 手工脚本恢复 + Jenkins 备份恢复 |
| 第三方模型网关不可用 | 5-15 分钟内降级 | 不丢核心数据 | 配置切换 / 功能熔断 / 队列失败可重试 |
### 2.2 首版不做
- 不做跨地域双活写入。
- 不做 SpacetimeDB 在线主从复制,除非后续官方能力与项目压测验证支持。
- 不让前端绕过 `api-server` 直接承担正式业务真相。
- 不把生产密钥、Token、数据库 dump、Jenkins secret 写入 Git。
- 不恢复旧 `server-node`、Express、PostgreSQL 或 Docker 一体化部署方案。
---
## 3. 总体容灾设计
### 3.1 分层策略
1. **入口层:Nginx / DNS / HTTPS**
- 保留 Nginx 配置模板在 Git:`deploy/nginx/genarrative.conf``deploy/nginx/genarrative-dev-http.conf`
- 为 release 环境建立 Nginx 配置备份与证书恢复流程。
- 明确 DNS 切换预案:生产机不可恢复时,将域名指向灾备机公网 IP。
2. **静态资源层:Web / Admin Web**
- 依赖 `web.tar.gz``web.tar.gz.sha256``release-manifest.json`
- 保留最近 N 个 release 目录与构建产物指针。
- 回滚只切软链,不重新构建。
3. **API 服务层:Rust `api-server`**
- 依赖归档的 `api-server` 二进制、checksum、`release-manifest.json`
- `/etc/genarrative/api-server.env` 通过加密备份或密钥管理恢复,不进入 release 包。
- systemd unit 由 `deploy/systemd/genarrative-api.service` 重新安装。
4. **数据层:SpacetimeDB**
- 每次高风险发布前强制导出数据库。
- 定时导出:建议每天至少 1 次;高活跃期可每 4 小时 1 次。
- 导出产物同时保存在:Jenkins 归档 + 生产机 `SERVER_BACKUP_DIRECTORY` + 异地对象存储/备份机。
- 导入前自动生成安全备份,保留当前实现口径。
5. **发布编排层:Jenkins**
- Jenkins Job、Jenkinsfile 在 Git 中可恢复。
- Jenkins controller 配置、凭据、插件清单需要额外备份。
- 发布 agent 使用 inbound + systemd 自恢复,agent secret 仅存在目标机或 Jenkins 凭据。
6. **密钥与外部服务层**
- `/etc/genarrative/api-server.env`、Jenkins Secret Text、SSH PEM、agent secret 不进 Git。
- 制定密钥清单和恢复责任人,但不在仓库记录明文。
- 外部服务配置按 `docs/technical/API_SERVER_EXTERNAL_SERVICE_ENV_CONFIG_2026-05-07.md` 维护必配项。
---
## 4. 建议新增/更新的文档
### Task 1: 新增生产容灾技术方案文档
**Objective:** 形成团队可共享、可执行的容灾总纲。
**Files:**
- Create: `docs/technical/PRODUCTION_DISASTER_RECOVERY_PLAN_2026-05-11.md`
- Modify: `docs/technical/README.md`(若已有技术索引,应加入该文档入口)
- Optional Modify: `.hermes/shared-memory/project-overview.md`(只加稳定索引,不写敏感信息)
**文档必须覆盖:**
1. 容灾目标:RTO/RPO 表。
2. 生产资产清单:Nginx、systemd、release/current、`/stdb``/etc/genarrative/api-server.env`、Jenkins、构建产物。
3. 备份策略:
- 数据库导出。
- release 产物保留。
- Nginx/systemd/env 配置备份。
- Jenkins 配置备份。
4. 恢复流程:
- Web 回滚。
- API 回滚。
- Stdb module 回滚。
- 数据恢复。
- 整机重建。
5. 演练计划:每月一次数据库恢复演练,每季度一次整机重建演练。
6. 安全边界:密钥不进 Git,备份加密,最小权限。
7. 验收命令与人工检查清单。
**Verification:**
```bash
npm run check:encoding
```
Expected: PASS,无中文乱码、无 BOM/CRLF 问题。
---
## 5. 建议新增/更新的脚本与流水线
### Task 2: 增强数据库定时备份流水线
**Objective:** 把现有人工导出扩展为可定时执行、可异地保存、可审计的备份流程。
**Files:**
- Modify: `jenkins/Jenkinsfile.production-database-export`
- Modify: `docs/technical/PRODUCTION_DISASTER_RECOVERY_PLAN_2026-05-11.md`
- Optional Create: `scripts/deploy/production-backup-sync.sh`
**Implementation notes:**
- 在 Jenkins Job 中保留人工触发能力,同时建议配置 cron:
- development:每天凌晨。
- release:每天凌晨或业务低峰。
- 增加备份命名规范:
- `spacetime-migration-<database>-<yyyyMMdd-HHmmss>-<source_commit>.json`
- 增加 `SERVER_BACKUP_DIRECTORY` 默认建议:
- `/var/backups/genarrative/spacetimedb/<database>/`
- 增加备份保留策略:
- 本机保留 7-14 天。
- 异地保留 30-90 天。
- 如实现 `production-backup-sync.sh`,只做同步框架,不硬编码真实 bucket、账号、endpoint 或密钥。
**Verification:**
```bash
bash -n scripts/deploy/production-backup-sync.sh
npm run check:encoding
```
Expected: shell 语法通过;文档编码检查通过。
---
### Task 3: 增加灾备恢复 Runbook
**Objective:** 在真正故障时不依赖临场推理,按清单执行恢复。
**Files:**
- Create: `docs/operations/PRODUCTION_DR_RUNBOOK_2026-05-11.md`
- Modify: `docs/operations/README.md`(如果存在)
**Runbook sections:**
1. 故障分级:P0/P1/P2。
2. 第一响应:
- 判断 Nginx 是否在线。
- 判断 `genarrative-api.service` 是否在线。
- 判断 `spacetimedb.service` 是否在线。
- 判断磁盘是否满。
- 判断 Jenkins agent 是否在线。
3. 快速止血:
- 开维护模式。
- 禁止继续发布。
- 保留现场日志。
4. 回滚流程:
- Web 回滚命令。
- API 回滚命令。
- Stdb wasm 回滚命令。
5. 数据恢复流程:
- 选择备份。
- dry-run 导入。
- 确认导入。
- smoke test。
6. 整机重建流程:
- 新机器 provision。
- 恢复 `/etc/genarrative/api-server.env`
- 恢复 SpacetimeDB 数据。
- 发布最近稳定 release。
- DNS 切换。
7. 复盘模板。
**Verification:**
```bash
npm run check:encoding
```
Expected: PASS。
---
### Task 4: 增加备份健康检查与恢复演练记录模板
**Objective:** 防止“有备份但不可恢复”。
**Files:**
- Create: `docs/operations/DR_DRILL_REPORT_TEMPLATE.md`
- Optional Create: `scripts/deploy/verify-database-backup.sh`
- Modify: `docs/technical/PRODUCTION_DISASTER_RECOVERY_PLAN_2026-05-11.md`
**建议检查项:**
- 备份文件存在且大小非 0。
- 备份文件 checksum 可验证。
- 备份文件可被 `Genarrative-Database-Import` dry-run 解析。
- 最近一次备份时间未超过 RPO 阈值。
- 导入后 `/healthz` 可用。
- 首页、后台登录页、关键 API smoke 可用。
**Verification:**
```bash
bash -n scripts/deploy/verify-database-backup.sh
npm run check:encoding
```
Expected: PASS。
---
## 6. 具体恢复流程草案
### 6.1 Web 静态资源回滚
1. 进入目标机。
2. 查看 release 目录:`/opt/genarrative/releases/`
3. 选择上一个稳定版本。
4. 切换 `/srv/genarrative/web``/opt/genarrative/current` 软链。
5. 执行 Nginx 配置检查与 reload。
6. 访问首页与后台静态入口。
验收:
- `/` 返回最新稳定页面。
- `/admin/` 返回后台页面。
- 静态资源无 404。
### 6.2 API 回滚
1. 开维护模式。
2.`/opt/genarrative/current` 到上一版包含稳定 `api-server` 的 release。
3. 重启 `genarrative-api.service`
4. 本机检查 `http://127.0.0.1:8082/healthz`
5. 检查 Nginx 反代路径。
6. 解除维护模式。
验收:
- `systemctl status genarrative-api.service` 正常。
- `/healthz` 正常。
- 后台 `/admin/api/*` 基础接口正常。
### 6.3 SpacetimeDB 模块回滚
1. 开维护模式。
2. 确认目标数据库名与当前 API 环境一致:`GENARRATIVE_SPACETIME_DATABASE`
3. 选择上一版 `spacetime_module.wasm`
4. 使用 `spacetimedb` 服务用户发布上一版 wasm。
5. 重启或检查 `spacetimedb.service`
6. 检查 `api-server` 对目标数据库访问。
7. 解除维护模式。
注意:如果 schema 已迁移且旧 wasm 不兼容当前数据,需要走数据恢复,不应直接盲目发布旧 wasm。
### 6.4 数据恢复
1. 开维护模式。
2. 从 Jenkins 归档或 `SERVER_BACKUP_DIRECTORY` 选择备份。
3. 先执行导入 dry-run。
4. 真正导入前生成当前数据库安全备份。
5. 执行导入。
6. 执行 smoke test。
7. 解除维护模式。
必须记录:
- 备份文件名。
- 来源 Job/build number。
- 恢复目标 database。
- 恢复开始/结束时间。
- 恢复后验证结果。
### 6.5 整机重建
1. 准备新 Linux 机器。
2. 接入 Jenkins release deploy agent,或准备人工 SSH 运维路径。
3. 运行 `Genarrative-Server-Provision`
- 创建用户和目录。
- 安装 SpacetimeDB。
- 安装 systemd unit。
- 安装 Nginx 配置。
4. 恢复 `/etc/genarrative/api-server.env`
5. 发布最近稳定 Web/API/Stdb 产物。
6. 导入最近一次有效数据库备份。
7. smoke test。
8. 切 DNS。
9. 观察 30-60 分钟。
---
## 7. 文件可能变更清单
首版落地建议按以下文件收口:
- Create: `docs/technical/PRODUCTION_DISASTER_RECOVERY_PLAN_2026-05-11.md`
- Create: `docs/operations/PRODUCTION_DR_RUNBOOK_2026-05-11.md`
- Create: `docs/operations/DR_DRILL_REPORT_TEMPLATE.md`
- Modify: `docs/technical/README.md`
- Modify: `docs/operations/README.md`(若存在)
- Modify: `.hermes/shared-memory/project-overview.md`(仅增加文档索引)
- Optional Modify: `jenkins/Jenkinsfile.production-database-export`
- Optional Modify: `jenkins/Jenkinsfile.production-database-import`
- Optional Create: `scripts/deploy/production-backup-sync.sh`
- Optional Create: `scripts/deploy/verify-database-backup.sh`
---
## 8. 测试与验收
### 8.1 文档与编码
```bash
npm run check:encoding
```
Expected: PASS。
### 8.2 Shell 脚本语法
如新增 shell 脚本:
```bash
bash -n scripts/deploy/production-backup-sync.sh
bash -n scripts/deploy/verify-database-backup.sh
```
Expected: PASS。
### 8.3 Jenkinsfile 静态检查
建议在 Jenkins UI 或本地 Jenkins Pipeline Linter 中检查:
- `jenkins/Jenkinsfile.production-database-export`
- `jenkins/Jenkinsfile.production-database-import`
Expected: Pipeline syntax valid。
### 8.4 演练验收
至少完成一次 development 目标演练:
1. 触发 `Genarrative-Database-Export`
2. 确认备份产物存在并归档。
3. 使用 `Genarrative-Database-Import` dry-run 验证备份可解析。
4. 不覆盖生产数据的前提下,记录演练报告。
release 目标演练应在业务低峰进行,并先确认通知渠道可用。
---
## 9. 风险、取舍与开放问题
### 9.1 风险
- 单机生产仍存在物理机级单点故障,首版只能通过“快速重建 + 异地备份”降低恢复时间。
- SpacetimeDB schema 回滚不一定可逆,必须把发布前备份作为强约束。
- Jenkins controller 若在本地 Windowscontroller 自身备份和恢复需要单独制定,不应只依赖 agent 自恢复。
- 外部模型网关失败可能影响创作能力,但不应影响已发布作品浏览和后台基础能力。
### 9.2 取舍
- 选择先做可执行 runbook 和备份恢复演练,而不是直接引入复杂多活。
- 选择继续复用现有 Jenkins 导入导出流水线,降低工程改造风险。
- 选择不把密钥恢复细节写死到 Git 文档,避免泄露。
### 9.3 开放问题
1. release 环境是否已经有独立备份机或对象存储?如果有,需要补充备份同步目标,但不能提交密钥。
2. Jenkins controller 的 `JENKINS_HOME` 当前实际部署在哪里?是否已有周期备份?
3. 生产域名 DNS TTL 当前是多少?是否可降低到适合故障切换的值?
4. `/stdb` 所在磁盘是否独立于系统盘?是否已有磁盘水位告警?
5. release 环境的通知渠道除邮件外是否需要接入企业微信/飞书/Telegram?
---
## 10. 推荐实施顺序
1. 先只落文档:技术方案 + runbook + 演练模板。
2. 在 development 目标做一次数据库导出 + dry-run 导入演练。
3. 根据演练结果补脚本:备份同步、备份健康检查。
4. 再把 release 备份设置为定时任务。
5. 最后规划整机重建演练与 DNS 切换演练。
首版完成标准:
- 团队任一成员打开 runbook,即可在 30 分钟内完成 Web/API 回滚或数据库备份 dry-run 恢复。
- 最近一次数据库备份时间、备份位置、checksum、恢复演练结果可追溯。
- 生产密钥仍只存在于服务器/Jenkins 凭据/加密备份中,不进入 Git。
@@ -1,403 +0,0 @@
# 当前项目安全漏洞检查计划
> **For Hermes:** Use subagent-driven-development skill only if the user later asks to execute this plan. 本计划当前仅用于规划,不实施代码修改。
**Goal:** 对 Genarrative 当前工作区做一次可复现的安全漏洞基线检查,覆盖依赖漏洞、密钥泄露、常见高风险代码模式、后端 Rust crate 风险和前端/Node 供应链风险,并输出可落地的整改清单。
**Architecture:** 采用“只读扫描 → 结果归档 → 人工分级 → 最小修复建议”的方式推进。先不直接升级依赖或改代码,避免安全扫描引入不可控 breaking change;执行阶段只在用户确认后运行扫描命令,并把报告保存到 `docs/audits/``.hermes/plans/` 附件中。
**Tech Stack:** Node/Vite/React/TypeScript、Rust workspace/Axum/SpacetimeDB、npm lockfile、Cargo.lock、Git worktree。
---
## 当前上下文 / 假设
- 当前有效工作区:`C:/proj/Genarrative/.worktrees/hermes-3337436a`
- 本次用户以 `/plan` 模式要求“检查一下当前项目的安全漏洞”,因此本轮只制定计划,不执行会产生报告、安装工具、修改依赖、提交或推送的操作。
- 已确认项目包含:
-`package.json`,脚本包括 `npm run lint``npm run test``npm run build``npm run check:encoding`
-`package-lock.json`
- `server-rs/Cargo.toml``server-rs/Cargo.lock`
- `apps/admin-web/package.json``packages/shared/package.json`
- `.hermes/shared-memory/development-workflow.md` 要求开发前读取共享记忆,并以当前代码、`docs/``AGENTS.md` 为准。
- 安全扫描不应把真实密钥写入仓库;发现疑似密钥时只记录文件位置、变量名、脱敏片段和处置建议。
## 总体策略
1. 先做仓库状态和范围确认,避免扫描其他 worktree 或错误路径。
2. 优先运行不会修改文件的安全检查:`npm audit --json``cargo audit`、密钥扫描、危险代码模式扫描。
3. 分前端供应链、后端供应链、源码安全、配置/脚本安全四类归档。
4. 对结果按严重级别分层:Critical / High / Medium / Low / Informational。
5. 对每个真实问题给出:影响范围、证据、可行修复、验证命令、是否需要业务回归。
6. 只有在用户确认进入执行/修复阶段后,才做依赖升级、代码修复、文档更新、测试和提交。
---
## Step-by-step Plan
### Task 1: 确认扫描工作区和基线状态
**Objective:** 确保后续扫描针对当前 worktree,且不会误把既有未提交变更当成安全修复结果。
**Files:**
- Read-only: `AGENTS.md`
- Read-only: `.hermes/README.md`
- Read-only: `.hermes/shared-memory/development-workflow.md`
- Read-only: `package.json`
- Read-only: `server-rs/Cargo.toml`
**Commands:**
```bash
pwd
git status --short
git branch --show-current
git rev-parse --show-toplevel
```
**Expected:**
- `pwd` / `git rev-parse --show-toplevel` 指向 `C:/proj/Genarrative/.worktrees/hermes-3337436a` 对应路径。
- 分支为当前隔离 worktree 分支。
- 记录是否已有未提交变更;如存在,扫描报告需标注“基于含未提交变更的工作区”。
**Validation:**
- 不修改任何项目文件。
- 如发现路径不是当前 worktree,停止并重新确认路径。
### Task 2: 生成依赖清单和锁文件基线
**Objective:** 明确 Node 与 Rust 依赖入口,避免漏扫子包或 admin web。
**Files:**
- Read-only: `package.json`
- Read-only: `package-lock.json`
- Read-only: `apps/admin-web/package.json`
- Read-only: `packages/shared/package.json`
- Read-only: `server-rs/Cargo.toml`
- Read-only: `server-rs/Cargo.lock`
**Commands:**
```bash
npm --version
node --version
cargo --version
rustc --version
```
可选只读清单:
```bash
npm ls --all --json > /tmp/genarrative-npm-ls.json
cargo metadata --manifest-path server-rs/Cargo.toml --format-version 1 > /tmp/genarrative-cargo-metadata.json
```
**Expected:**
- 明确 npm / Node / Rust / Cargo 版本。
-`npm ls` 因 peer dependency 或历史依赖问题非 0,保留输出并继续 audit。
**Validation:**
- `/tmp` 输出不进入 Git。
- 不运行 `npm install``npm update``cargo update`
### Task 3: Node 供应链漏洞扫描
**Objective:** 检查根 lockfile 覆盖的前端、脚本和 admin web 依赖漏洞。
**Files:**
- Read-only: `package-lock.json`
- Read-only: `package.json`
**Commands:**
```bash
npm audit --json > /tmp/genarrative-npm-audit.json
npm audit --audit-level=moderate
```
**Expected:**
- `npm audit --json` 生成机器可读结果。
- 第二条命令给出人类可读摘要;如返回非 0,按漏洞严重度记录,不直接执行 `npm audit fix`
**Result fields to extract:**
- package name
- vulnerable versions
- installed version
- severity
- CVE / GHSA
- via chain
- fixAvailable 是否为 major/breaking
- affected direct dependency or transitive dependency
**Validation:**
- 不执行 `npm audit fix`
- 如 npm registry 网络不可用,记录阻塞原因和可重试命令。
### Task 4: Rust 供应链漏洞扫描
**Objective:** 检查 `server-rs` workspace 的 Cargo 依赖漏洞、弃用 crate 和 yanked crate。
**Files:**
- Read-only: `server-rs/Cargo.toml`
- Read-only: `server-rs/Cargo.lock`
**Commands:**
优先:
```bash
cargo audit --json --manifest-path server-rs/Cargo.toml > /tmp/genarrative-cargo-audit.json
cargo audit --manifest-path server-rs/Cargo.toml
```
如果本机没有 `cargo audit`
```bash
cargo install cargo-audit --locked
cargo audit --manifest-path server-rs/Cargo.toml
```
**Execution note:**
- 安装 `cargo-audit` 会改变用户 Cargo 工具目录,不属于纯只读扫描;执行前需用户确认。
- 如果用户不希望安装工具,则记录“Rust 漏洞扫描未完成”,并给出本地安装或 CI 执行建议。
**Result fields to extract:**
- advisory id
- package
- version
- patched versions
- unaffected versions
- severity / CVSS if available
- dependency path
- whether it is runtime reachable in `api-server` / `spacetime-module`
**Validation:**
- 不运行 `cargo update`
- 不改 `Cargo.lock`
### Task 5: 密钥和敏感配置泄露扫描
**Objective:** 检查仓库中是否误提交 API key、token、私钥、cookie、`.env` 类文件或个人 Hermes 配置。
**Files / paths to scan:**
- Full repo excluding `.git/`, `node_modules/`, `target/`, `dist/`, build artifacts。
- 特别关注:`.hermes/``scripts/``server-rs/``apps/admin-web/``src/``docs/`
**Preferred commands:**
如果有 gitleaks
```bash
gitleaks detect --source . --no-git --redact --report-format json --report-path /tmp/genarrative-gitleaks.json
```
如果没有 gitleaks,先用只读 grep/ripgrep 兜底:
```bash
git ls-files -z | xargs -0 grep -nIE "(api[_-]?key|secret|password|passwd|token|private[_-]?key|BEGIN (RSA|OPENSSH|EC|DSA)? ?PRIVATE KEY|AKIA[0-9A-Z]{16}|xox[baprs]-|sk-[A-Za-z0-9_-]{20,})" > /tmp/genarrative-secret-grep.txt || true
```
**Execution note:**
- 安装 gitleaks 需要用户确认。
- grep 结果包含 false positive,必须人工分级,不得直接当作泄露结论。
**Validation:**
- 报告中对值做脱敏,只保留前后 3-4 位或完全不记录值。
- 如果发现 `.env.local` 或真实 token 被跟踪,立即标为 Critical。
### Task 6: 常见源码安全模式扫描
**Objective:** 快速发现高风险代码模式:命令注入、动态执行、路径穿越、危险反序列化、XSS、日志泄密、宽松 CORS 等。
**Files / paths:**
- `src/**/*.{ts,tsx,js,mjs,cjs}`
- `apps/admin-web/**/*.{ts,tsx,js,mjs,cjs}`
- `scripts/**/*.{js,mjs,cjs,ts}`
- `server-rs/crates/**/*.rs`
**Commands:**
```bash
# JS/TS 动态执行与 HTML 注入
rg -n "\beval\(|new Function\(|dangerouslySetInnerHTML|innerHTML\s*=|document\.write\(" src apps scripts packages
# Node 命令执行风险
rg -n "exec\(|execSync\(|spawn\(|spawnSync\(|shell:\s*true|child_process" scripts src apps packages
# Rust 命令、文件路径、unwrap 风险热点
rg -n "Command::new|std::process|\.unwrap\(|\.expect\(|fs::|File::open|PathBuf|set_header|cors|CorsLayer" server-rs/crates
# 宽松 CORS / Cookie / Auth 相关热点
rg -n "allow_origin|Any|cookie|Authorization|Bearer|refresh|access_token|set_cookie|SameSite|Secure|HttpOnly" server-rs/crates src apps scripts
```
**Expected:**
- 输出作为“热点清单”,不等同于漏洞。
- 对 auth/session、文件上传、OSS 签名、外部 LLM/图片服务请求、SpacetimeDB 访问 facade 做人工复核。
**Validation:**
- 每个疑似问题必须能说明可利用条件,无法说明则降级为 Informational。
### Task 7: Web/API 安全配置人工复核
**Objective:** 对项目特有的安全边界做代码审阅,补足工具扫描无法覆盖的业务风险。
**Likely files to review:**
- `server-rs/crates/api-server/src/**`
- `server-rs/crates/platform-auth/src/**`
- `server-rs/crates/platform-oss/src/**`
- `server-rs/crates/platform-llm/src/**`
- `server-rs/crates/spacetime-client/src/**`
- `src/services/**`
- `apps/admin-web/src/**`
- `scripts/*deploy*`
- `scripts/*api-server*`
- `.github/workflows/**` if present
**Checklist:**
- Auth / sessionaccess token 与 refresh cookie 的生命周期、SameSite/Secure/HttpOnly、错误日志是否泄露 token。
- CORS:开发环境与生产环境是否区分,是否存在生产 `Any`
- SSRF / outboundLLM、图片生成、OSS、任意 URL 下载是否校验协议和大小。
- Upload / Data URL:大小限制、MIME 校验、base64 解析错误处理。
- Path traversal:脚本和后端是否拼接用户输入路径。
- Admin:后台接口是否有权限校验,是否复用普通用户 token。
- SpacetimeDBprivate table / reducer 是否绕过 api-server facade 暴露敏感数据。
- Logging:日志是否打印 API key、token、cookie、用户私密内容。
**Validation:**
- 对每个命中的真实风险,记录具体文件路径和函数名。
- 对“需要运行环境才能验证”的风险,列出 smoke 或单测建议。
### Task 8: 汇总漏洞分级与整改建议
**Objective:** 把扫描结果转成团队可执行的安全整改报告。
**Deliverable candidates:**
- `docs/audits/SECURITY_VULNERABILITY_SCAN_YYYY-MM-DD.md`
- 或如果用户只要临时报告:`.hermes/plans/assets/security-scan-YYYY-MM-DD.md`
**Report structure:**
```markdown
# 安全漏洞扫描报告 YYYY-MM-DD
## 扫描范围
## 扫描命令与环境
## 摘要
## Critical
## High
## Medium
## Low
## Informational / False Positive
## 依赖升级建议
## 代码修复建议
## 需要人工确认的问题
## 验证命令
```
**Validation:**
- 报告不包含真实密钥。
- 每条问题都有“证据、影响、建议、验证”。
- 明确哪些是工具扫描结果,哪些是人工判断。
### Task 9: 如用户要求修复,再分批执行最小修复
**Objective:** 避免一次性大规模升级导致回归,把修复拆为可验证的小批次。
**Suggested order:**
1. Critical secrets:立即移除、轮换密钥、补 `.gitignore`/文档约束(注意项目约束:不要在 `.gitignore` 中添加 `.env.local`)。
2. Critical/High direct dependencies:优先升级 direct dependency,运行最小测试。
3. Critical/High transitive dependencies:评估是否由 direct dependency patch/minor 升级带出。
4. 源码漏洞:按入口编写回归测试,再修复。
5. Medium/Low:按风险和 breaking change 代价排期。
**Required verification after fixes:**
```bash
npm run check:encoding
npm run lint:eslint
npm run typecheck
npm run test
npm run build
cd server-rs && cargo test --workspace
```
后端 API 或 auth 修复涉及运行态时,还需要:
```bash
npm run api-server
# 另一个终端检查 /healthz 并执行对应 smoke
```
**Validation:**
- 修复后重新跑对应 audit / secret scan。
-`requesting-code-review` 的独立安全复核流程。
---
## Files likely to change(仅修复阶段)
本计划阶段不修改以下文件;只有用户确认执行修复时才可能变化:
- `package.json`
- `package-lock.json`
- `apps/admin-web/package.json`
- `server-rs/Cargo.toml`
- `server-rs/Cargo.lock`
- `server-rs/crates/api-server/src/**`
- `server-rs/crates/platform-auth/src/**`
- `server-rs/crates/platform-oss/src/**`
- `server-rs/crates/platform-llm/src/**`
- `src/services/**`
- `apps/admin-web/src/**`
- `scripts/**`
- `docs/audits/SECURITY_VULNERABILITY_SCAN_YYYY-MM-DD.md`
- `.hermes/shared-memory/pitfalls.md`(仅当发现长期有效、会反复踩的安全排障经验时更新)
## Tests / Validation
安全扫描执行阶段:
```bash
npm audit --json > /tmp/genarrative-npm-audit.json
npm audit --audit-level=moderate
cargo audit --manifest-path server-rs/Cargo.toml
rg -n "\beval\(|new Function\(|dangerouslySetInnerHTML|innerHTML\s*=|document\.write\(" src apps scripts packages
rg -n "exec\(|execSync\(|spawn\(|spawnSync\(|shell:\s*true|child_process" scripts src apps packages
rg -n "Command::new|std::process|\.unwrap\(|\.expect\(|fs::|File::open|PathBuf|set_header|cors|CorsLayer" server-rs/crates
```
修复执行阶段:
```bash
npm run check:encoding
npm run lint:eslint
npm run typecheck
npm run test
npm run build
cd server-rs && cargo test --workspace
```
如变更后端运行态、安全中间件、auth/session
```bash
npm run api-server
# 检查 /healthz
# 执行相关 auth / API smoke
```
## Risks, tradeoffs, and open questions
- `npm audit fix` 可能升级 major version,破坏 Vite/React/ESLint/Vitest 兼容性;必须先人工审查 `fixAvailable`
- `cargo audit` 可能需要安装 `cargo-audit`;安装工具属于用户环境变更,应先确认。
- 密钥扫描极易产生 false positive;必须人工复核,报告中禁止输出真实密钥。
- Rust `unwrap/expect` 不是天然漏洞;只有对外部输入、网络、文件、数据库响应等不可信数据造成 panic/DoS 时才升级为真实风险。
- Web 安全检查需要区分开发环境和生产环境;开发 CORS 放宽不等于生产漏洞,但生产配置必须有明确边界。
- 如果扫描发现历史提交中曾泄露密钥,删除当前文件不够,必须轮换密钥并考虑历史清理策略。
- 当前计划未直接访问 CI/Jenkins/生产配置;若用户希望覆盖 CI/CD、镜像、部署主机和运行时端口,需要补充 Jenkins console、部署脚本和生产环境配置的只读访问方式。
## Missing artifacts / follow-up checkpoints
- 尚未获得用户确认是否允许安装 `cargo-audit` / `gitleaks` 等工具。
- 尚未执行真实扫描,因此当前没有漏洞结论;执行后需要生成正式报告。
- 如果用户希望“检查当前项目”包含远端仓库历史 secrets、Docker 镜像、Jenkins 凭据和生产运行时配置,需要另行确认访问范围和凭据边界。
@@ -1,206 +0,0 @@
# 远端作品列表压测排查报告
时间:2026-05-12 06:16 CST
目标:`http://82.157.175.59`
SSH:远端生产机 root 账号(具体私钥路径仅保留在本机环境,不写入仓库)
## 背景
远端 `k6-works-list.js` 压测中:
- smoke 通过。
- baseline 10 VU:无 HTTP 错误,但 p95/p99 超阈值。
- 50 RPS spike`http_req_failed` / `works_list_shape_error_rate` 约 21.99%。
- 100 RPS spike`http_req_failed` / `works_list_shape_error_rate` 约 25.47%。
- 从 k6 check 看,失败主要集中在 `puzzle_gallery_list``custom_world_gallery_list` 基本正常。
## 已完成排查
### 1. 服务器进程与资源
远端服务监听:
- Rust api-server`127.0.0.1:8082`systemd 服务 `genarrative-api.service`
- SpacetimeDB`127.0.0.1:3101`systemd 服务 `spacetimedb.service`
- Nginx:公网 80 反代 `/api/*``127.0.0.1:8082`
服务器规格/状态:
- 2 vCPU。
- 内存约 1.9GiB。
- Swap 约 1.9GiB,已有约 600MiB 使用。
- `/` 磁盘约 69%。
- Rust api-server 当前 CPU 不高。
- SpacetimeDB 当前 CPU 不高。
发现一个独立异常:
- PM2 下旧 `server-node` 进程 `genarrative` 正在重启风暴。
- cwd`/work/Genarrative/server-node`
- 错误:连接 `127.0.0.1:5432` PostgreSQL 被拒绝。
- PM2 restart 次数已超过 33 万。
- 该进程不是当前公网 `/api/*` 使用的 Rust api-server,但会制造额外 CPU/内存/日志抖动。
### 2. 压测窗口服务端日志
子任务聚合了 2026-05-12 04:50-05:05 的 nginx 与 api-server 日志。
nginx access
- `/api/runtime/puzzle/gallery`4661 次,全部 200。
- `/api/runtime/custom-world-gallery`4659 次,全部 200。
api-server journal
`/api/runtime/puzzle/gallery`
- completed4661
- status200 全部
- slow_request0
- latency_msmin 13 / p50 30 / p90 43 / p95 50 / p99 62 / max 88
`/api/runtime/custom-world-gallery`
- completed4659
- status200 全部
- slow_request0
- latency_msmin 0 / p50 1 / p90 5 / p95 7 / p99 13 / max 49
结论:
- 在服务端视角,两个接口在该窗口都没有 5xx,也没有慢请求。
- 这与 k6 客户端侧 30s timeout / failed check 存在明显不一致。
- 需要进一步区分:客户端侧网络/连接耗尽/本机 k6 执行环境问题,还是 k6 统计混合/响应解析问题。
### 3. k6 脚本行为
文件:`scripts/loadtest/k6-works-list.js`
`AUTH_TOKEN` 时,每轮 iteration 顺序请求两个接口:
1. `GET /api/runtime/puzzle/gallery`
2. `GET /api/runtime/custom-world-gallery`
`DETAIL_RATIO=0` 时不会请求详情。
`works_list_shape_error_rate` 不只代表字段结构错误,只要下面任意 check 失败都会计入:
- status is 200
- returns json object
- has collection
- list item shape
因此 timeout、非 JSON、非 200、响应结构不符合都会表现为 shape error。
数据文件实际路径:
- `scripts/loadtest/data/works-list.local.json`
脚本里 `data/works-list.local.json` 是相对 k6 脚本文件解析的,因此本身合理。
### 4. 代码层疑似瓶颈
虽然这次远端服务端日志没有复现慢请求,但代码层仍发现一个真实性能隐患。
`/api/runtime/puzzle/gallery` 调用链:
- `server-rs/crates/api-server/src/app.rs:1192`
- `server-rs/crates/api-server/src/puzzle.rs:1385-1409`
- `server-rs/crates/spacetime-client/src/puzzle.rs:367-381`
- `server-rs/crates/spacetime-module/src/puzzle.rs:430-443`
- `server-rs/crates/spacetime-module/src/puzzle.rs:1393-1404`
关键实现:
- `list_puzzle_gallery_tx``puzzle_work_profile().iter()` 全表扫描。
- 再过滤 `publication_status == Published`
- 对每个公开作品调用 `build_puzzle_work_profile_from_row_with_recent_count`
- 该函数调用 `count_recent_public_work_plays(ctx, "puzzle", &row.profile_id, now_micros)`
`count_recent_public_work_plays`
- 文件:`server-rs/crates/spacetime-module/src/runtime/profile.rs:1296-1321`
- 当前实现对 `public_work_play_daily_stat().iter()` 全表扫描过滤。
- 但表定义已有复合索引:
- `server-rs/crates/spacetime-module/src/runtime/profile.rs:242-248`
- `by_public_work_play_daily_stat_work_day(source_type, profile_id, played_day)`
- 当前统计函数未使用该索引。
复杂度风险:
```text
puzzle gallery ~= O(puzzle_work_profile 全表扫描 + Published作品数 * public_work_play_daily_stat 全表扫描)
```
`custom-world-gallery` 与 puzzle 的差异:
- custom-world 使用 `CustomWorldGalleryEntry` 公开读模型表。
- puzzle 直接从 `puzzle_work_profile` 即席拼装。
- 两者都调用 recent count,但 puzzle 更容易受作品表规模和统计表规模影响。
## 当前判断
本次排查有两个层面的结论:
1. 生产服务端日志没有证明 `puzzle/gallery` 在 04:50-05:05 窗口真的 30s 慢或 5xx。
- api-server 记录的 p95 只有 50ms。
- nginx 看到两个接口都是 200。
- 所以 k6 侧的 30s timeout 需要进一步从客户端网络、连接池、Windows/k6 执行环境、summary 混合统计角度验证。
2. 代码层确实存在可修的性能隐患。
- `count_recent_public_work_plays` 未使用已有索引。
- puzzle gallery 对每个作品重复做 recent count。
- puzzle gallery 未使用 `publication_status` 索引或读模型。
## 建议下一步
### A. 先处理服务器 PM2 重启风暴
建议确认旧 Node 服务是否仍需要。
如果不需要,应停止并禁用 PM2 中的旧 `server-node`
```bash
PM2_HOME=/home/ubuntu/.pm2 pm2 stop genarrative
PM2_HOME=/home/ubuntu/.pm2 pm2 delete genarrative
PM2_HOME=/home/ubuntu/.pm2 pm2 save
```
这是生产侧操作,执行前需要确认。
### B. 单接口短压验证客户端/服务端不一致
不要继续用混合脚本大压。
建议新增或临时使用单接口 k6 脚本,分别只测:
- `/api/runtime/puzzle/gallery`
- `/api/runtime/custom-world-gallery`
并在同一时间窗口并行采集:
- k6 客户端 summary
- nginx access 请求数/状态码
- api-server journal latency
- 本机到服务器网络错误/timeout
目标是确认 timeout 是不是发生在客户端侧连接/网络,而不是服务端处理慢。
### C. 修复代码性能隐患
优先级建议:
1. `count_recent_public_work_plays` 改为使用 `by_public_work_play_daily_stat_work_day` 复合索引,或至少改成批量统计,避免 N 次全表扫描。
2. `list_puzzle_gallery_tx` 使用 `by_puzzle_work_publication_status` 索引查询 Published,或参考 custom-world 建立 `puzzle_gallery_entry` 公开读模型。
3. gallery 列表页不要实时逐条扫描统计表,可维护读模型或批量聚合 `recent_play_count_7d`
### D. 调整 k6 脚本输出
建议 k6 summary 按 endpoint tag 输出或新增单接口模式,否则 overall 指标会把 puzzle/custom-world 混在一起。
建议增加:
- `ENDPOINT=puzzle_gallery_list`
- `ENDPOINT=custom_world_gallery_list`
让脚本只跑一个 endpoint,避免诊断时混淆。
@@ -1,343 +0,0 @@
# Genarrative 视觉小说“一句话生成”最小闭环落地计划
生成时间:2026-05-13 11:22
工作区:`C:/proj/Genarrative/.worktrees/hermes-visual-novel`
参考文档:`C:/Users/DSK/Documents/Interactive-fiction/一句话生成视觉小说整体流程总结.md`
## 1. 目标
把 Interactive-fiction 总结文档中的“一句话生成视觉小说”流程,映射并落地到 Genarrative 现有视觉小说能力中,优先做成一个可端到端验证的最小闭环:
1. 用户在视觉小说入口输入一句话并选择画风。
2. 前端进入生成过程页,展示分阶段进度。
3. 后端创建视觉小说创作会话,并基于 seedText 生成 `VisualNovelResultDraft`
4. 生成完成后进入草稿结果页,可看到世界观、角色、场景、剧情阶段、开场选择。
5. 草稿可编译/保存为作品 profile,并进入视觉小说运行态测试/正式游玩。
本计划只覆盖 Genarrative 内部最小闭环,不引入 Interactive-fiction 原项目的独立 TXT 播放记录、分享播放包、外部活动运营、独立账号/交易/资产系统。
## 2. 当前上下文与已发现实现
### 2.1 Interactive-fiction 总结文档提炼
参考文档将整体流程分为:
- 输入侧:一句话创意、主题/风格、可选文档或素材。
- 生成侧:理解意图、扩展世界观、角色、场景、剧情阶段、开场与选择。
- 编辑侧:草稿页可查看和调整生成结果。
- 运行侧:从草稿进入视觉小说游玩,支持剧情推进、玩家选择、历史与状态。
- 资产侧:角色立绘、背景、音乐/音效可作为后续增强,最小闭环可先使用文字描述与空资产占位。
### 2.2 Genarrative 已有实现基础
已确认项目中视觉小说相关能力并非从零开始:
- 前端入口表单:
- `src/components/visual-novel-creation/VisualNovelAgentWorkspace.tsx`
- 已有“一句话创作” textarea、6 个视觉画风选项、提交按钮“生成视觉小说草稿”。
- 前端入口 payload/progress
- `src/components/visual-novel-creation/visualNovelEntryGeneration.ts`
- 已有 `VisualNovelEntryFormPayload`、锚点展示、一句话/画风生成进度步骤。
- 前端平台主流程:
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
- 已接入 `createVisualNovelDraftFromForm`,会创建 session、stream message、进入 `visual-novel-generating`,完成后进入 `visual-novel-result`
- 前端 API client
- `src/services/visual-novel-creation/visualNovelCreationClient.ts`
- 已封装 session/message/action/compile 接口。
- 共享契约:
- `packages/shared/src/contracts/visualNovel.ts`
- 已定义 `VisualNovelResultDraft`、world/characters/scenes/storyPhases/opening/runtimeConfig/work/run/history 等结构。
- 后端 API
- `server-rs/crates/api-server/src/visual_novel.rs`
- 已有创建 session、发消息、流式消息、执行 action、compile、work、runtime run 等接口。
- 后端 prompt
- `server-rs/crates/api-server/src/prompt/visual_novel.rs`
- 已有 `VISUAL_NOVEL_CREATION_SYSTEM_PROMPT`、结构化输出契约、runtime GM prompt、repair prompt。
- SpacetimeDB 模块:
- `server-rs/crates/spacetime-module/src/visual_novel.rs`
- 已有 session/message/work/run/history/event 表与 procedure。
- 文档参考:
- `docs/prd/AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md`
- `docs/technical/VISUAL_NOVEL_IMPLEMENTATION_HANDOFF_2026-05-07.md`
- `docs/technical/VISUAL_NOVEL_PROMPT_AND_LLM_TOOLS_VN03_2026-05-05.md`
### 2.3 关键实现判断
当前项目已经实现了视觉小说的主要骨架,本次不应大规模重写。更合理的落地方式是补齐“一句话生成”闭环中最容易断裂的点:
- 入口输入与画风信息是否被稳定传给后端 prompt。
- 后端生成 draft 后是否自动保存/关联可编辑 work profile。
- 生成过程页是否能清晰展示 Interactive-fiction 文档中提到的阶段。
- 结果页是否有足够的字段展示与继续游玩入口。
- 运行态是否能基于 opening/choices 正常启动,而不依赖尚未生成的图片/音乐资产。
## 3. 拟采用方案
### 3.1 最小闭环范围
本次优先实现:
1. “一句话 + 视觉画风”作为 `sourceMode: 'idea'` 的 seedText。
2. 后端生成完整 `VisualNovelResultDraft`,包括:
- world
- 3-6 个角色
- 3-8 个场景
- 3-6 个剧情阶段
- opening narration/firstDialogue/2-4 个 choices
- runtimeConfig
3. 若 LLM 输出失败,使用 repair 或确定性 fallback,保证可回到草稿页并显示错误/警告。
4. 结果页支持保存/编译为 work profile。
5. work profile 支持启动 runtime runopening 能展示初始场景、旁白、对话和选择。
暂不做或仅预留:
- 真实图片/音乐生成队列。
- 多文档解析导入的完整链路。
- 复杂分镜/节点图编辑器。
- 外部 Interactive-fiction 项目的播放器、TXT 记录包、分享活动、独立账号系统。
### 3.2 与 Genarrative 架构的映射
| Interactive-fiction 概念 | Genarrative 落点 |
| --- | --- |
| 一句话创意 | `VisualNovelEntryFormPayload.ideaText` / `seedText` |
| 画风/主题 | `seedText` 中的“视觉画风/画风要求”,后续可结构化为 metadata |
| 世界观设定 | `VisualNovelResultDraft.world` |
| 角色设定 | `VisualNovelResultDraft.characters` |
| 场景设定 | `VisualNovelResultDraft.scenes` |
| 剧情阶段/章节 | `VisualNovelResultDraft.storyPhases` |
| 开场文本与选项 | `VisualNovelResultDraft.opening` |
| 运行时剧情推进 | `VisualNovelRuntimeStep[]` + run snapshot/history |
| 发布/作品库 | `VisualNovelWorkProfileRecord` / works API |
## 4. 分步计划
### Step 1:补齐入口 payload 与生成过程语义
涉及文件:
- `src/components/visual-novel-creation/VisualNovelAgentWorkspace.tsx`
- `src/components/visual-novel-creation/visualNovelEntryGeneration.ts`
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
任务:
1. 保持现有 6 个画风选项,但确认每个 option 的 prompt 会进入 `seedText`
2. 将生成过程阶段从当前 3 步细化为更贴合参考文档的 4-5 步,例如:
- 理解一句话创意
- 扩展世界观与玩家身份
- 设计角色/场景/剧情阶段
- 生成开场与选择
- 准备可编辑草稿
3. 生成过程页的 anchor 保留“一句话”和“视觉画风”,必要时增加“生成目标:视觉小说草稿”。
4. 确认 `createVisualNovelDraftFromForm` 对失败状态会保留返回入口/重试能力。
验收点:提交一句话后能进入 `visual-novel-generating`,看到阶段进度;完成后进入 `visual-novel-result`
### Step 2:增强后端 creation prompt 与 fallback 约束
涉及文件:
- `server-rs/crates/api-server/src/prompt/visual_novel.rs`
- `server-rs/crates/api-server/src/visual_novel.rs`
- 如已有 domain crate`server-rs/crates/module-visual-novel/**` 或相关 normalize/validate 文件
任务:
1. 在 creation prompt 中显式吸收 Interactive-fiction 的“一句话生成”目标:
- 从 seedText 提取核心创意、视觉风格、故事类型。
- 生成可直接运行的 opening 和 choices。
- 图片/音乐资产先置 null,但必须有可生成图像的描述。
2. 强化输出约束:
- `opening.sceneId` 必须指向存在且 availability 为 `opening` 的 scene。
- `opening.initialChoices` 必须 2-4 个。
- `storyPhases[0]` 必须包含 opening scene 和主要角色。
- `publishReady` 的判定与 validationIssues 一致。
3. 检查 `submit_visual_novel_message_turn` / `resolve_action_draft` / compile 相关代码:
- 如果 LLM 失败,是否已有 fallback;没有则补确定性 fallback draft。
- 如果 draft 不完整,是否会 normalize/repair 并写入 session。
4. 保留现有“不要输出旧 TXT 播放记录、分享播放包、外部商业字段”的约束,避免把参考项目的外部概念误并入 Genarrative。
验收点:后端给定 seedText 时,返回 session.draft 不为空且满足共享契约。
### Step 3:确认草稿结果页、保存/编译与作品库链路
涉及文件:
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
- `src/components/visual-novel-creation/**`
- `src/services/visual-novel-works*` 或相关 visual novel works client
- `server-rs/crates/api-server/src/visual_novel.rs`
- `packages/shared/src/contracts/visualNovel.ts`
任务:
1. 查找并确认 `visual-novel-result` 页面组件:
- 是否显示 workTitle/workDescription/world/characters/scenes/storyPhases/opening。
- 是否有保存/发布/开始试玩按钮。
2. 确认 `compileVisualNovelWorkProfile``executeVisualNovelAction({kind:'compile_work_profile'})` 会生成/更新 work profile。
3. 确认作品架上使用 `profileId` 而不是 sessionId 作为稳定作品 ID。
4. 如果结果页缺少“一句话来源/画风”的可视化提示,可在结果页或 summary 中补轻量展示,避免用户以为画风丢失。
验收点:生成完成后能保存为作品;作品出现在“我的作品/创作架”;再次打开能读取同一 draft。
### Step 4:确认运行态 opening 闭环
涉及文件:
- `src/components/visual-novel-runtime/**`
- `src/services/visual-novel-runtime*`
- `server-rs/crates/api-server/src/visual_novel.rs`
- `server-rs/crates/api-server/src/prompt/visual_novel.rs`
- `packages/shared/src/contracts/visualNovel.ts`
任务:
1. 启动 visual novel work run 时,优先使用 `draft.opening` 生成第一轮 runtime snapshot/history。
2. 如果没有图片/音乐,前端 runtime shell 必须可用文字 fallback,不应白屏或阻断游玩。
3. 玩家选择 `choice` 后,后端 runtime GM prompt 生成下一轮 `VisualNovelRuntimeStep[]`
4. 确认正式游玩入口调用 `work_play_start`,并满足已有埋点约定:
- `scope_kind=work`
- `scope_id=稳定作品 ID`
- metadata 包含 `playType/workId/sourceRoute/userId` 等。
验收点:从生成出的作品进入运行态,能看到 opening 并点击至少一个选择推进一轮。
### Step 5:补测试与文档
涉及文件:
- 前端测试:按仓库现有测试布局查找 `*.test.ts` / `*.test.tsx`
- Rust 测试:`server-rs/crates/api-server/src/**` 或 domain crate tests
- 文档:可追加到 `docs/technical/``.hermes/shared-memory/decision-log.md`(如团队约定需要)
建议测试:
1. TypeScript 单元测试:
- `buildVisualNovelEntryGenerationProgress` 阶段输出。
- `buildVisualNovelEntryGenerationAnchorEntries` 能展示一句话和画风。
2. Rust 单元测试:
- creation prompt 包含 seedText、sourceMode、输出契约。
- draft normalize/fallback 能生成合法 opening/choices。
- runtime opening 或 first-step 构造不依赖图片/音乐。
3. 集成/手工测试文档:
- 访问平台视觉小说入口。
- 输入一句话。
- 选择画风。
- 点击生成。
- 查看结果页。
- 保存作品。
- 启动试玩并点击选择。
## 5. 可能改动文件清单
高概率改动:
- `src/components/visual-novel-creation/VisualNovelAgentWorkspace.tsx`
- `src/components/visual-novel-creation/visualNovelEntryGeneration.ts`
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
- `server-rs/crates/api-server/src/prompt/visual_novel.rs`
- `server-rs/crates/api-server/src/visual_novel.rs`
- `packages/shared/src/contracts/visualNovel.ts`
中概率改动:
- `src/components/visual-novel-runtime/**`
- `src/services/visual-novel-creation/**`
- `src/services/visual-novel-runtime/**`
- `src/services/visual-novel-works/**`
- `server-rs/crates/spacetime-module/src/visual_novel.rs`
- `server-rs/crates/spacetime-client/**` 生成/绑定文件,若 SpacetimeDB contract 需要更新
低概率/仅文档:
- `docs/technical/VISUAL_NOVEL_IMPLEMENTATION_HANDOFF_2026-05-07.md`
- `docs/prd/AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md`
- `.hermes/shared-memory/decision-log.md`
## 6. 验证计划
### 6.1 静态检查
在 worktree 根目录执行:
```bash
npm run typecheck
```
如仓库无统一 typecheck,则按 package scripts 选择最接近的前端类型检查命令。
### 6.2 前端定向测试
优先运行与 visual novel / platform entry 相关测试,如存在:
```bash
npm test -- visual-novel
npm test -- platform-entry
```
若仓库使用 vitest
```bash
npm run test -- visual-novel
```
### 6.3 Rust 定向测试
`server-rs` 下运行 visual novel 相关测试:
```bash
cargo test -p api-server visual_novel
cargo test -p shared-contracts visual_novel
```
如改动 SpacetimeDB module
```bash
cargo test -p spacetime-module visual_novel
```
### 6.4 人工验收步骤
1. 启动本地 dev 栈。
2. 访问 Genarrative 主站。
3. 进入创作/视觉小说入口。
4. 输入:`一个雨夜,失忆的高中生在旧图书馆发现一本会回应她心声的日记。`
5. 选择任一画风,例如“映画动画”。
6. 点击“生成视觉小说草稿”。
7. 预期:进入生成过程页,能看到分阶段进度。
8. 预期:完成后进入草稿结果页,包含标题、简介、世界观、角色、场景、剧情阶段和 opening choices。
9. 点击保存/编译作品。
10. 从作品入口进入试玩。
11. 预期:opening 文本出现,至少 2 个选择可点击;点击后剧情继续推进一轮。
## 7. 风险、权衡与开放问题
### 7.1 风险
- 现有视觉小说代码已较完整,贸然新增一套 parallel pipeline 会制造重复逻辑;应复用当前 `VisualNovelResultDraft` 与 creation agent flow。
- LLM 输出不稳定可能导致草稿结构不完整;需要 normalize/repair/fallback 确保最小闭环。
- 视觉/音乐资产生成未接入时,UI 必须接受 null asset,否则运行态可能白屏。
- `PlatformEntryFlowShellImpl.tsx` 文件很大,改动需局部、谨慎,避免影响其他玩法入口。
- 若改动 SpacetimeDB 表结构,可能牵涉 publish、client binding、清库/迁移;最小闭环阶段应尽量避免 schema 变更。
### 7.2 权衡
- 先让文字版视觉小说完整跑通,再补角色立绘/背景图生成。
- 先用 `seedText` 承载画风,再考虑把 `visualStyleId/Label/Prompt` 结构化进 draft metadata。
- 先用现有 result/work/runtime 页面闭环,不引入新编辑器。
### 7.3 开放问题
1. 用户是否要求把 Interactive-fiction 原项目中的具体 UI 样式/页面布局迁移到 Genarrative?当前计划只迁移流程语义,不迁移独立 UI。
2. 画风是否需要成为作品可编辑字段?当前以 seedText/prompt 影响生成内容,后续可在 draft 中增加 metadata。
3. 文档导入模式是否本期要做?当前计划聚焦一句话模式,document 模式只保留契约能力。
4. 是否需要真实图片/音乐生成?当前计划作为后续增强,不纳入最小闭环。
## 8. 建议实施顺序
1. 先做只改 prompt/progress/少量前端展示的轻量闭环修补。
2. 运行前后端定向测试,确认现有能力是否已足够。
3. 如果后端没有 fallback 或 normalize,再补 Rust 层确定性兜底。
4. 手工跑通“一句话 -> 生成 -> 结果页 -> 保存 -> 试玩”。
5. 最后再考虑是否需要资产生成、文档导入、结构化画风 metadata。
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because it is too large Load Diff
+49 -130
View File
@@ -1,40 +1,20 @@
# 开发工作流 # 开发工作流
> 用途:给本地 Hermes 和开发人员提供统一的开发、测试、提交流程。具体命令以 `package.json`、`server-rs/Cargo.toml`、`AGENTS.md` 和相关 `docs/` 最新文档为准。 更新时间:`2026-05-15`
## 标准任务流程 ## 标准流程
```text ```text
同步代码 读取 AGENTS.md 读取 .hermes/shared-memory → 查找/完善 docs → 制定计划 → 小步实现 本地验证 更新文档/记忆 → 提交 同步代码 -> 读取 AGENTS.md -> 读取 .hermes/shared-memory -> 查当前 docs -> 小步实现 -> 本地验证 -> 更新 docs / .hermes -> 提交
``` ```
## 建议启动方式 当前 `docs/` 已压缩为少量融合文档。复杂任务优先读:
在项目根目录启动 Hermes 1. `docs/README.md`
2. `docs/【项目基线】当前产品与工程约束-2026-05-15.md`
```bash 3. `docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`
cd /path/to/Genarrative 4. `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
hermes 5. `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`
```
在本机当前常见路径为:
```bash
/home/dsk/workspace/Genarrative
```
其他开发者以自己本地实际路径为准,不要把个人绝对路径写入共享文档作为通用规则。
## 开发前检查清单
- [ ] 当前分支是否正确
- [ ] 是否已拉取最新代码
- [ ] 是否阅读 `AGENTS.md`
- [ ] 是否阅读 `.hermes/shared-memory/` 相关文件
- [ ] 是否阅读 `README.md` 中的运行和检查命令
- [ ] 是否阅读 `docs/README.md` 及任务相关分类 README
- [ ] 是否存在足够具体的 PRD / 设计 / 技术文档
- [ ] 是否明确测试、验收和文档更新方式
## 本地运行命令 ## 本地运行命令
@@ -44,19 +24,12 @@ hermes
npm install npm install
``` ```
完整联调开发环境 完整联调:
```bash ```bash
npm run dev npm run dev
``` ```
该命令会启动:
- SpacetimeDB standalone
- Rust `api-server`
- 主站 Vite
- 后台 Vite
单独启动前端: 单独启动前端:
```bash ```bash
@@ -69,15 +42,7 @@ npm run dev:web
npm run api-server 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
npm run dev:rust:logs
```
后台管理前端:
```bash ```bash
npm run admin-web:dev npm run admin-web:dev
@@ -85,128 +50,82 @@ npm run admin-web:build
npm run admin-web:typecheck npm run admin-web:typecheck
``` ```
SpacetimeDB bindings 生成 SpacetimeDB bindings
```bash ```bash
npm run spacetime:generate npm run spacetime:generate
``` ```
## 常用检查命令 ## 常用检查
- 后端通用用户行为埋点统一通过 `record_tracking_event_and_return` procedure、`SpacetimeRuntimeClient::record_tracking_event(...)` 与 api-server `tracking` 中间件写入 `tracking_event` / `tracking_daily_stat`;后台、RPG、大鱼吃小鱼、Visual Novel、Story、Combat 默认排除;作品级游玩埋点统一使用 `work_play_start`,详细事件清单见 `docs/technical/BACKEND_TRACKING_EVENT_COVERAGE_2026-05-09.md`
编码检查:
```bash ```bash
npm run check:encoding npm run check:encoding
``` npm run check:spacetime-schema
npm run check:server-rs-ddd
ESLint
```bash
npm run lint:eslint npm run lint:eslint
```
类型检查:
```bash
npm run typecheck npm run typecheck
```
综合 lint
```bash
npm run lint
```
测试:
```bash
npm run test npm run test
```
生产构建:
```bash
npm run build npm run build
```
内容检查:
```bash
npm run check:data
npm run check:overrides
npm run check:smoke
npm run check:content npm run check:content
``` ```
全量检查: 综合检查:
```bash ```bash
npm run lint
npm run check npm run check
``` ```
DDD 边界检查 视觉小说门禁
```bash ```bash
npm run check:server-rs-ddd npm run check:visual-novel-vn11
npm run check:visual-novel-vn12
``` ```
## 后端相关默认验证 ## 后端默认验证
后端修改后,按 DDD 文档中的验收命令执行。涉及 API smoke 时 后端代码修改后按范围选择
- 使用 `npm run api-server` 重新拉起后端。 - `cargo test -p <crate> --manifest-path server-rs/Cargo.toml`
- 禁止使用 `npm run api-server:maincloud``npm.cmd run api-server:maincloud` 或任何 `GENARRATIVE_SPACETIME_MAINCLOUD_*` 口径;这些只属于历史残留。 - `cargo check -p api-server --manifest-path server-rs/Cargo.toml`
- 检查 `/healthz` - `cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml`
- 执行对应自动测试。 - `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`
- 涉及 SpacetimeDB 表、reducer、procedure、row shape 或绑定变化时,同步更新 `migration.rs`、表目录和生成绑定。 - `npm run check:server-rs-ddd`
- SpacetimeDB 已有表新增字段必须放在 Rust 表结构体最后,并设置明确默认值;需要修改字段名时,先询问用户并确认迁移计划,再同步更新 `server-rs/crates/spacetime-module/src/migration.rs`、表目录和生成绑定。 - `npm run api-server` 后请求 `/healthz`
- 修改 SpacetimeDB schema 后运行 `npm run check:spacetime-schema`,用自动检查拦截缺 default、插入中间、字段删除/改名/重排/改类型,以及漏改迁移、表目录或绑定。
关键文档 涉及 SpacetimeDB table、reducer、procedure、row shape 或 bindings 时,还必须运行
- `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md` ```bash
- `docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md` npm run spacetime:generate
- `docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md` npm run check:spacetime-schema
- `docs/technical/SERVER_RS_DDD_G1_CONTRACT_AND_ROUTE_MATRIX_2026-04-29.md` ```
- `docs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md`
- `docs/technical/SPACETIMEDB_TABLE_CATALOG.md`
- `docs/technical/MAINCLOUD_REFERENCE_REMOVAL_POLICY_2026-05-06.md`
## 前端相关默认验证 禁止使用旧 `api-server:maincloud` 或任何 `GENARRATIVE_SPACETIME_MAINCLOUD_*` 口径。
前端修改后,应根据修改范围选择: ## 前端默认验证
前端修改后按范围选择:
- `npm run check:encoding` - `npm run check:encoding`
- `npm run lint:eslint` - `npm run lint:eslint`
- `npm run typecheck` - `npm run typecheck`
- `npm run test` - `npm run test -- <具体测试文件>`
- 页面交互 smoke - 页面交互 smoke
- 移动端视口检查 - 移动端视口检查
前端原则 UI 相关修改重点检查
- 移动端优先,再兼容网页端 - 390px 左右移动端宽度不横向溢出
- 页面只展示后端返回的状态,不自行计算结论型业务状态 - 输入法弹出时平台画布不被压缩
- 创作中心入口配置事实源在 SpacetimeDB,通过 `GET /api/creation-entry/config` 下发;前端只在 `platformEntryCreationTypes.ts` 做展示派生,api-server 路由熔断也使用同一份配置,禁止恢复前端硬编码入口配置文件 - 弹窗、抽屉和独立面板没有实现成当前面板下方展开
- 优先复用现有面板、抽屉、弹窗,不新建独立大系统 - UI 不包含默认规则说明长文
- 不在 UI 中默认写功能说明类文本 - 私有图片和音频不裸请求 `/generated-*`
- 弹出独立面板的交互不要实现成在当前面板下方追加内容。
## 文档更新规则 ## 文档更新
- 工程修改要同步更新对应文档。 - 工程修改要同步更新当前 `docs/` 文档。
- 如果没有现成文档,新文档统一放入 `docs/` 下合适分类 - 新增稳定知识优先合并进现有 4 份文档;只有现有文档无法容纳时才新增带 `【标签名】` 的 Markdown
- `.hermes/shared-memory/` 只记录高频、长期、团队共享的摘要和索引,不替代完整 PRD/技术文档 - `.hermes/shared-memory/` 只记录高频、长期、团队共享的摘要和索引。
- 阶段性流水账、一次性计划和已关闭 TODO 不再作为长期仓库文档依据。
- 如果 `.hermes/shared-memory/` 与代码或 `docs/` 冲突,以代码和最新 `docs/` 为准,并同步修正共享记忆。 - 如果 `.hermes/shared-memory/` 与代码或 `docs/` 冲突,以代码和最新 `docs/` 为准,并同步修正共享记忆。
## 提交前建议让 Hermes 执行
```text
请检查当前 git diff,指出:
1. 是否违反 AGENTS.md 或 .hermes/shared-memory 约定;
2. 是否需要补充 docs
3. 是否有长期知识需要写入 .hermes/shared-memory
4. 建议的测试命令和提交信息。
```
+28 -80
View File
@@ -1,103 +1,51 @@
# 文档地图与阅读索引 # 文档地图与阅读索引
> 用途:根据 `README.md`、`AGENTS.md` 和 `docs/` 下文档索引整理团队记忆入口,帮助本地 Hermes 快速选择应该读哪些资料。 更新时间:`2026-05-15`
## 全局入口 ## 当前文档入口
| 场景 | 优先阅读 | | 场景 | 优先阅读 |
| --- | --- | | --- | --- |
| 建立项目背景 | `README.md``AGENTS.md``.hermes/shared-memory/project-overview.md` | | 建立项目背景 | `README.md``AGENTS.md``.hermes/shared-memory/project-overview.md` |
| 找文档分类 | `docs/README.md` | | 找当前文档 | `docs/README.md` |
| 开发方法论 | `docs/experience/README.md` | | 产品、命名、UI、协作和废弃路线 | `docs/【项目基线】当前产品与工程约束-2026-05-15.md` |
| 查风险与历史问题 | `docs/audits/README.md` | | 后端、DDD、API、SpacetimeDB schema 和表目录 | `docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md` |
| 做玩法/交互/系统设计 | `docs/design/README.md` | | 创作入口、草稿架和玩法链路 | `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md` |
| 做技术实现/后端/部署 | `docs/technical/README.md` | | 本地启动、验证、部署、埋点和运营查询 | `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md` |
| 排期与拆阶段 | `docs/planning/README.md` | | UI 像素资产与 9-slice 规范 | `UI_CODING_STANDARD.md` |
| 查脚本/Function/prompt/职责地图 | `docs/reference/README.md` |
| 查埋点 SQL | `docs/tracking/README.md` |
| 查运营/任务/钱包对账 SQL | `docs/operations/README.md` |
| 查 PRD | `docs/prd/` |
## docs 分类规则 ## 阅读顺序
- `experience/`:方法论、交接经验、长期有效的开发结论。
- `audits/`:现状扫描、问题定位、是否达标的审查类文档。
- `design/`:玩法机制、叙事关系、系统结构设计。
- `technical/`:技术选型、实现路线、竞品/产品形态拆解。
- `planning/`:阶段优先级与推进顺序。
- `reference/`:目录、速查、检索辅助。
- `tracking/`:埋点原始事实和聚合投影查询。
- `operations/`:后台运营核查、对账和排障查询。
- `prd/`:产品需求与阶段计划。
新增 Markdown 文档文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`。标签用于跨目录检索,不替代 `docs/` 的目录分类;历史文档不要求批量重命名。
## 推荐阅读顺序
通用复杂任务: 通用复杂任务:
1. `AGENTS.md` 1. `AGENTS.md`
2. `.hermes/shared-memory/` 2. `.hermes/shared-memory/`
3. `docs/README.md` 3. `docs/README.md`
4. `docs/experience/README.md` 4. 与任务匹配的当前融合文档
5. `docs/audits/README.md`
6. 任务对应分类下的 README 和具体文档
后端 / 数据真相 / SpacetimeDB 后端 / 数据真相 / SpacetimeDB
1. `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md` 1. `docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`
2. `docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md` 2. `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`
3. `docs/technical/SERVER_RS_DDD_G1_CONTRACT_AND_ROUTE_MATRIX_2026-04-29.md` 3. 对应 crate README 或源码
4. `docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md`
5. `docs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md` 玩法 / 创作入口 / 运行态:
6. `docs/technical/SPACETIMEDB_TABLE_CATALOG.md`
7. 具体模块方案文档 1. `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
2. `docs/【项目基线】当前产品与工程约束-2026-05-15.md`
3. 相关前端组件、service、shared contract 和后端 module
生产部署 / 服务器 / Jenkins 生产部署 / 服务器 / Jenkins
1. `docs/technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md` 1. `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`
2. 需要迁移时再看 `SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md` 2. `deploy/env/api-server.env.example`
3. 历史 Jenkins / CORS / 本地远端脚本文档只作追溯,不作为当前入口 3. `deploy/nginx/README.md`
RPG 创作与运行时链路: ## 维护规则
1. `docs/reference/RPG_CREATION_AND_RUNTIME_SCRIPT_RESPONSIBILITY_MAP_2026-04-28.md` - 当前 `docs/` 只保留少量融合文档。
2. `docs/technical/CREATION_FLOW_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md` - 新增工程实现时,如果已有对应当前文档,必须同步更新。
3. `docs/technical/RPG_ENTRY_RUNTIME_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md` - 如果没有合适位置,新文档文件名必须使用 `【标签名】中文标题-YYYY-MM-DD.md`
4. 相关工作包 progress / closure 文档 - 阶段性流水账、一次性修复记录和已关闭实验不要再新增为长期文档
- 阶段性计划和一次性 TODO 不再作为长期文档目录;需要保留的决策、流程和坑点应进入 `docs/` 当前文档或 `.hermes/shared-memory/`
移动端 UI / 游戏 UI
1. `docs/experience/MOBILE_UI_DEV_EXPERIENCE.md`
2. `UI_CODING_STANDARD.md`
3. 相关 `docs/design/` 文档
创作 Agent / 自定义世界:
1. `docs/design/CUSTOM_WORLD_CREATOR_INPUT_AND_AI_BOUNDARY_DESIGN_2026-04-06.md`
2. `docs/design/CUSTOM_WORLD_CREATOR_MANUAL_AI_SYSTEM_BALANCE_DESIGN_2026-04-12.md`
3. `docs/design/CUSTOM_WORLD_CREATOR_PURE_AGENT_COMPARISON_AND_CONVERSION_DESIGN_2026-04-12.md`
4. `docs/technical/UNIFIED_CREATION_AGENT_CHAT_FRAMEWORK_2026-04-22.md`
5. 相关 `SPACETIMEDB_CUSTOM_WORLD_*` 技术方案
拼图 / 大鱼 / Match3D
- 拼图:优先看 `PUZZLE_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md``PUZZLE_RUNTIME_FRONTEND_LOGIC_REHOME_2026-05-02.md` 和相关 Puzzle 技术文档。
- 大鱼吃小鱼:优先看 `BIG_FISH_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-22.md` 和相关 Big Fish 技术/经验文档。
- 抓大鹅 Match3D:优先看 `docs/prd/AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md``MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md` 和相关 Match3D 技术文档。
个人任务 / 埋点 / 运营查询:
1. `docs/technical/PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md`
2. `docs/technical/RUNTIME_PROFILE_TASK_SCOPE_2026-05-04.md`
3. `docs/technical/ANALYTICS_DATE_DIMENSION_IMPLEMENTATION_2026-05-04.md`
4. `docs/tracking/TRACKING_QUERY_PLAYBOOK_2026-05-03.md`
5. `docs/operations/PROFILE_TASK_QUERY_PLAYBOOK_2026-05-03.md`
## 文档维护规则
- 新增工程实现时,如果已有对应文档,必须同步更新。
- 如果没有对应文档,新文档放入 `docs/` 下合适分类。
- 新文档文件名必须使用 `【标签名】` 前缀,标题尽量保留中文语义,日期使用 `YYYY-MM-DD`
- `.hermes/shared-memory/` 只保留跨任务、跨成员、高频使用的摘要和索引。
- 如果文档与代码冲突,先确认代码事实,再更新过期文档和共享记忆。 - 如果文档与代码冲突,先确认代码事实,再更新过期文档和共享记忆。
File diff suppressed because it is too large Load Diff
+33 -121
View File
@@ -1,143 +1,55 @@
# Genarrative 项目共享概览 # Genarrative 项目共享概览
> 用途:给团队成员本地 Hermes 快速建立项目背景。内容应保持高层、稳定、可验证;细节以代码、`README.md`、`AGENTS.md` 和 `docs/` 最新文档为准。 更新时间:`2026-05-15`
## 一句话定位 ## 一句话定位
Genarrative / AI Native Visual RPG 是一个以 **AI 叙事 + 本地规则 + 像素演出** 为核心的视觉 RPG 与 AI 原生游戏创作平台原型 Genarrative / 陶泥儿是一个 AI 原生互动内容与小游戏平台,把 AI 创作、作品草稿、公开分发、运行态、用户账号、钱包任务、后台管理和小程序外壳收在同一套工程中
项目当前不只是单一 RPG demo,而是在同一平台内同时承载: ## 当前主要能力
- RPG / 自定义世界创作与运行时 - RPG / 自定义世界创作与运行时
- 拼图玩法创作与运行时 - 拼图玩法创作、草稿、发布、运行态和排行榜。
- 大鱼吃小鱼玩法链路 - 抓大鹅 Match3D 创作、2D 多视角素材生成、发布和运行态。
- 抓大鹅 Match3D 玩法链路 - 大鱼吃小鱼、方洞挑战、视觉小说、汪汪声浪和儿童向寓教于乐玩法。
- 用户账号、存档、钱包、任务、埋点、后台管理与生产部署链路 - 账号、短信 / 密码 / 微信登录、个人资料、任务、钱包、邀请码、充值、反馈、法律信息和后台管理。
## 已具备的主要能力 ## 当前入口
来自根目录 `README.md` 的当前主能力: - 主站:`http://127.0.0.1:3000`
- 后台:`http://127.0.0.1:3000/admin/``http://127.0.0.1:3102`
- 后台前端工程:`apps/admin-web`
- 小程序 WebView 外壳:`miniprogram/`
- 法律文本:`media/files/user_agreement.md``media/files/privacy_policy.md``media/files/disclaimer.md`
- 世界与角色选择 移动端一级 Tab`推荐 / 发现 / 创作 / 草稿 / 我的`
- AI 剧情推进与流式对话
- 战斗演出、NPC 战斗、切磋
- NPC 交易、送礼、求助、招募
- 宝藏交互
- 同伴跟随与战斗
- 游戏主流程内嵌的角色资产工坊、自定义世界实体编辑与角色形象编辑
- 自动存档与继续游戏
## 当前前端与平台入口 ## 当前后端路线
- 主站默认地址:`http://127.0.0.1:3000` 唯一有效后端路线:
- 后台可从 `http://127.0.0.1:3000/admin/` 进入,也可直连 `http://127.0.0.1:3102`
- 主站、后台和 Rust 后端联调默认走 `npm run dev`
- 只启动前端页面可用 `npm run dev:web`,默认代理到本地 Rust `api-server`
- 后台管理独立前端工程为 `apps/admin-web`,管理端只做表现,数据和写操作走 `server-rs``/admin/api/*`
## 当前后端唯一落地口径
后端主线已经切到:
```text ```text
server-rs + Axum + SpacetimeDB server-rs + Axum + SpacetimeDB
``` ```
当前唯一有效后端方向 职责边界
- HTTP 门面:Rust `api-server` / Axum - `api-server`HTTP / SSE / BFF 门面和外部副作用编排。
- 实时状态与业务真相:`server-rs/crates/spacetime-module` / SpacetimeDB - `spacetime-module`SpacetimeDB 表、reducer、procedure、事务 adapter 和 row mapper。
- 共享领域与契约:`server-rs` 多 crate 分层维护 - `spacetime-client`:后端访问 SpacetimeDB 的 typed facade。
- 前端职责:表现、输入采集、临时 UI 状态、服务端结果渲染 - `module-*`:纯领域模型、命令、应用规则、领域事件和领域错误。
- `platform-*`:OSS、LLM、认证、语音等外部平台能力。
- `shared-contracts` / `packages/shared`:前后端 DTO 和公开契约。
- 前端:表现、交互、临时 UI 状态和后端结果渲染。
明确不再作为正式兼容目标: 明确废弃:旧 `server-node`、Express、PostgreSQL、Go 服务端、`maincloud`、人工 `spacetime --root-dir` 口径,以及前端承接正式业务真相的路线。
- `server-node` / Express / PostgreSQL 正式后端路线 ## 当前文档入口
- Go 服务端试验路线
- 浏览器侧承担正式运行时逻辑、正式生成编排或正式数据真相的路线
## server-rs DDD 分层边界 - `docs/README.md`
- `docs/【项目基线】当前产品与工程约束-2026-05-15.md`
- `docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`
- `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
- `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`
DDD 分层边界以 `docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md``SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md``AGENTS.md` 为准: 旧 PRD、设计、审计、阶段计划和技术流水账已融合进上述文档;没有融合的旧材料不再作为实现依据。
- `module-*`:领域模型、命令、应用编排结果、领域事件、领域错误
- `spacetime-module`SpacetimeDB 表、reducer、procedure、事务 adapter、mapper
- `spacetime-client`:后端访问 SpacetimeDB 的 typed facade
- `api-server`HTTP / SSE / BFF adapter 与外部平台服务编排
- `platform-*`:LLM、OSS、SMS、微信等外部副作用
- `shared-contracts`:前后端 DTO 与公开协议
- `shared-kernel`:跨纯领域 crate 复用的基础字符串、ID、时间和归一化能力
- `tests-support``server-rs` workspace 共享测试支撑
## 当前 Rust workspace 主要 crate
`server-rs/Cargo.toml` 为准,当前主要成员包括:
- 业务领域:`module-ai``module-assets``module-auth``module-big-fish``module-combat``module-inventory``module-custom-world``module-match3d``module-npc``module-puzzle``module-progression``module-quest``module-runtime``module-runtime-story``module-runtime-item``module-story`
- 平台副作用:`platform-oss``platform-auth``platform-llm`
- 共享层:`shared-contracts``shared-kernel``shared-logging`
- SpacetimeDB 接入:`spacetime-client``spacetime-module`
- HTTP 服务与测试:`api-server``tests-support`
注意:`server-rs` 的默认 `cargo build` 只构建 `crates/api-server`,本地 SpacetimeDB 模块发布继续走 `spacetime publish --module-path ... --build-options="--debug"`
Cargo 依赖口径:第三方依赖版本和 workspace 内部 crate path 统一维护在 `server-rs/Cargo.toml``[workspace.dependencies]`,成员 crate 默认继承 workspace 依赖,只保留自身 `features``optional` 或 target-specific 差异。
Rust 加密摘要依赖口径:新代码不再引入 `sha1`OSS V4 签名、阿里云 OpenAPI V3 签名和 refresh session token 摘要统一使用 `sha2::Sha256`
## SpacetimeDB 表域总览
`docs/technical/SPACETIMEDB_TABLE_CATALOG.md` 为持续维护入口。当前表域包括:
- 运维迁移:`database_migration_operator``database_migration_import_chunk`
- 认证:`auth_store_snapshot``user_account``auth_identity``refresh_session`
- 运行时档案:`runtime_setting``runtime_snapshot``user_browse_history``profile_dashboard_state``profile_wallet_ledger``analytics_date_dimension``tracking_event``tracking_daily_stat``profile_task_config``profile_task_progress``profile_task_reward_claim`
- RPG 运行时:`story_session``story_event``npc_state``inventory_slot``battle_state``treasure_record``quest_record``quest_log``player_progression``chapter_progression`
- 世界创作:`custom_world_profile``custom_world_session``custom_world_agent_session``custom_world_agent_message``custom_world_agent_operation``custom_world_draft_card``custom_world_gallery_entry`
- 拼图:`puzzle_agent_session``puzzle_agent_message``puzzle_work_profile``puzzle_event``puzzle_runtime_run``puzzle_leaderboard_entry`
- 抓大鹅 Match3D`match3d_agent_session``match3d_agent_message``match3d_work_profile``match3d_runtime_run`
- 大鱼吃小鱼:`big_fish_creation_session``big_fish_agent_message``big_fish_asset_slot``big_fish_event``big_fish_runtime_run`
- 资产:`asset_object``asset_entity_binding``asset_event`
- AI 任务:`ai_task``ai_task_stage``ai_text_chunk``ai_result_reference``ai_task_event`
## 产品命名与运营口径
`docs/technical/PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md` 为准:
- 产品展示名:陶泥儿
- 消费单位:泥点
- 公开账号标识:陶泥号
- 创作侧称谓:陶泥儿主
个人任务与埋点系统首版边界:
- 埋点原始事实写入 `tracking_event`
- 聚合投影写入 `tracking_daily_stat`
- 任务配置写入 `profile_task_config`
- 任务进度写入 `profile_task_progress`
- 领奖记录写入 `profile_task_reward_claim`
- 钱包流水写入 `profile_wallet_ledger`
- “星光”奖励复用现有“泥点”钱包,不新增第二种货币
- 个人任务 scope 首版仅支持 `user`
## 关键文档入口
- 根项目说明:`README.md`
- 项目总约束:`AGENTS.md`
- 文档总入口:`docs/README.md`
- 经验沉淀:`docs/experience/README.md`
- 审计与复盘:`docs/audits/README.md`
- 系统设计:`docs/design/README.md`
- 技术方案:`docs/technical/README.md`
- 规划与优先级:`docs/planning/README.md`
- 参考目录:`docs/reference/README.md`
- 埋点查询:`docs/tracking/README.md`
- 运营查询:`docs/operations/README.md`
- 后端当前基线:`docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
- 后端 DDD 总纲:`docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md`
- 后端并行任务清单:`docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md`
- 契约与路由矩阵:`docs/technical/SERVER_RS_DDD_G1_CONTRACT_AND_ROUTE_MATRIX_2026-04-29.md`
- SpacetimeDB 表结构变更约束:`docs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md`
- SpacetimeDB 表目录:`docs/technical/SPACETIMEDB_TABLE_CATALOG.md`
- Rust workspace 依赖集中配置:`docs/technical/RUST_WORKSPACE_DEPENDENCY_CONSOLIDATION_2026-05-07.md`
- 生产部署计划:`docs/technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md`
+34 -70
View File
@@ -1,100 +1,64 @@
# 团队协作约定 # 团队协作约定
> 用途:约定 3 名开发人员在各自本地 Hermes 中协作开发、共享项目记忆的方式。 更新时间:`2026-05-15`
## 基本模式 ## 基本模式
- 每位开发人员在自己的电脑上使用本地 Hermes。 - 每位开发人员在自己的电脑上使用本地 Hermes。
- 每位开发人员本地拉取同一个项目仓库,独立修改代码、运行测试、提交分支 - 团队共享内容放在仓库 `.hermes/``docs/` 中,通过 Git 同步
- 团队共享内容优先放在本仓库 `.hermes/` `docs/` 中,通过 Git 同步 - 不共享个人 `~/.hermes` 目录、密钥、会话、Token、Cookie、认证文件、本地私密路径或构建产物
- 不共享个人 `~/.hermes` 目录。
## 共享与禁止共享
推荐共享:
- `.hermes/shared-memory/` 团队级长期记忆
- `.hermes/plans/` 阶段性实施计划
- `.hermes/todos/` 已确定需要执行、但尚未进入实施的共享 TODO 计划
- `.hermes/skills/` 未来可复用仓库级 skills
- `docs/` 中 PRD、设计、技术、经验、审计、查询手册
- `AGENTS.md` 项目级 Agent 约束
禁止提交:
- 个人 `~/.hermes/config.yaml`
- 个人 `~/.hermes/.env`
- 个人 `~/.hermes/sessions/`
- API Key、Token、Cookie、认证文件
- 个人本地私密路径和个人隐私信息
- 构建产物、日志、缓存、数据库 dump
## 开发前 ## 开发前
1. 拉取最新代码。 1. 拉取最新代码。
2. 阅读 `AGENTS.md` 2. 阅读 `AGENTS.md`
3. 阅读 `.hermes/shared-memory/` 中与任务相关的文件。 3. 阅读 `.hermes/shared-memory/` 中与任务相关的文件。
4. 阅读 `docs/README.md`任务相关分类 README 4. 阅读 `docs/README.md` 4 份当前融合文档中与任务相关的部分
5. 阅读对应 PRD、设计、技术、经验或审计文档。 5. 如果文档不足以指导编码,先补充或修正文档。
6. 如果文档不足以指导编码,先补充或修正文档。
当前文档入口:
- `docs/【项目基线】当前产品与工程约束-2026-05-15.md`
- `docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`
- `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
- `docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`
## 开发中 ## 开发中
- 保持修改范围聚焦,不做无关重构。 - 保持修改范围聚焦,不做无关重构。
- 复用、修改、扩展现有系统优先,避免新建重复系统或页面 - 优先复用、修改、扩展现有系统、页面、组件和弹层
- 新增 Markdown 文档时,文件名必须以分类标签开头,格式为 `【标签名】中文标题-日期.md`;只在任务需要时重命名历史文档,避免无关大 diff - 新增 Markdown 文档时,文件名必须以分类标签开头,格式为 `【标签名】中文标题-YYYY-MM-DD.md`
- 阶段性计划、一次性 TODO 和已关闭实验不要长期沉淀为仓库文档;仍有效内容合并进当前 `docs/``.hermes/shared-memory/`
- 涉及中文文本时注意 UTF-8 编码和乱码排查。 - 涉及中文文本时注意 UTF-8 编码和乱码排查。
- 涉及后端时遵循 DDD 分层,不把业务真相下沉到前端或临时兼容层。 - 涉及后端时遵循 DDD 分层,不把业务真相下沉到前端或临时兼容层。
- `maincloud` / `Maincloud` / `MAINCLOUD` 相关代码、脚本、测试、环境变量、命令和文档要求均视为历史残留,禁止新增、运行或引用API smoke 统一使用 `npm run api-server``/healthz` - `maincloud` / `Maincloud` / `MAINCLOUD` 相关代码、脚本、测试、环境变量、命令和文档要求均视为历史残留,禁止新增、运行或引用。
- 涉及 SpacetimeDB 表结构、发布或迁移时,先看 `SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md` `SPACETIMEDB_TABLE_CATALOG.md` - API smoke 统一使用 `npm run api-server` `/healthz`
- 涉及生产发布、服务器配置、Jenkins Job 重建或回滚时,先看 `PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md` - 涉及 SpacetimeDB 表结构、发布或迁移时,先看当前后端架构文档的 schema 变更规则和表目录
- 涉及生产发布、服务器配置、Jenkins Job 重建或回滚时,先看当前开发运维文档。
## 开发后 ## 开发后
1. 运行与修改范围匹配的测试或验证命令。 1. 运行与修改范围匹配的测试或验证命令。
2. 更新相关 `docs/` 文档。 2. 更新相关 `docs/` 当前文档。
3. 新增或沉淀 Markdown 文档时,确认文件名已使用 `【标签名】` 前缀 3. 若产生长期有效知识,更新 `.hermes/shared-memory/`
4.产生长期有效知识,更新 `.hermes/shared-memory/` 4.形成可复用流程,考虑沉淀到 `.hermes/skills/`
5. 若形成可复用流程,考虑沉淀到 `.hermes/skills/` 5. 提交信息区分代码变更、文档变更和共享记忆变更
6. 在提交信息中区分代码变更与文档/记忆变更。
## 文档阅读顺序
通用任务建议:
1. `README.md`
2. `AGENTS.md`
3. `.hermes/shared-memory/`
4. `docs/README.md`
5. `docs/experience/README.md`
6. `docs/audits/README.md`
7. 任务所属分类:`docs/design/``docs/technical/``docs/planning/``docs/prd/``docs/reference/``docs/tracking/``docs/operations/`
后端任务建议:
1. `docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md`
2. `docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md`
3. `docs/technical/SERVER_RS_DDD_G1_CONTRACT_AND_ROUTE_MATRIX_2026-04-29.md`
4. `docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md`
5. `docs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md`
6. `docs/technical/SPACETIMEDB_TABLE_CATALOG.md`
7. `docs/technical/MAINCLOUD_REFERENCE_REMOVAL_POLICY_2026-05-06.md`
## 共享记忆更新准则 ## 共享记忆更新准则
适合更新: 适合更新:
- 新增稳定架构约定 - 稳定架构约定
- 新增长期开发流程 - 长期开发流程
- 已验证的踩坑和排障步骤 - 已验证的踩坑和排障步骤
- 重要接口契约变化 - 重要接口契约变化
- 团队协作规范变化 - 团队协作规范变化
- 文档索引或阅读顺序变化 - 当前文档索引或阅读顺序变化
不适合更新: 不适合更新:
- 一次性临时计划 - 一次性临时计划
- 未验证猜测 - 未验证猜测
- 个人偏好和个人路径 - 个人偏好和个人路径
- 敏感信息 - 敏感信息
- 大段聊天记录 - 大段聊天记录
@@ -280,26 +280,26 @@ fn anonymous_user_cannot_publish_generated_draft() {
| 产物类型 | 推荐路径 | 适用场景 | | 产物类型 | 推荐路径 | 适用场景 |
| --- | --- | --- | | --- | --- | --- |
| 实施前分析 / 临时计划 | `.hermes/plans/<task-name>-bdd-scenarios.md` | 某次 Hermes 开发任务前,用于澄清行为、拆测试、辅助实现;不一定作为长期产品依据。 | | 实施前分析 / 临时计划 | 当前任务说明或 `.tmp/<task-name>-bdd-scenarios.md` | 某次 Hermes 开发任务前,用于澄清行为、拆测试、辅助实现;不作为长期产品依据。 |
| 正式产品验收 / PRD 场景 | `docs/prd/<FEATURE>_BDD_YYYY-MM-DD.md` | 产品、测试、开发都需要长期参考的验收标准、用户故事、功能边界。 | | 正式产品验收 / PRD 场景 | 当前 `docs/` 融合文档,必要时新增 `docs/【产品验收】<功能名>BDD场景-YYYY-MM-DD.md` | 产品、测试、开发都需要长期参考的验收标准、用户故事、功能边界。 |
| 技术/API/领域行为场景 | `docs/technical/<FEATURE>_BDD_YYYY-MM-DD.md` | 后端 API、领域规则、状态机、SpacetimeDB reducer/table、SSE/异步任务、埋点副作用。 | | 技术/API/领域行为场景 | 当前 `docs/` 融合文档,必要时新增 `docs/【技术验收】<功能名>BDD场景-YYYY-MM-DD.md` | 后端 API、领域规则、状态机、SpacetimeDB reducer/table、SSE/异步任务、埋点副作用。 |
| 自动化 Gherkin feature 文件 | `tests/features/*.feature``e2e/features/*.feature` | 项目已接入 Cucumber/Playwright BDD 等 Gherkin runner 时。未接入前不要随意新建测试 runner 目录。 | | 自动化 Gherkin feature 文件 | `tests/features/*.feature``e2e/features/*.feature` | 项目已接入 Cucumber/Playwright BDD 等 Gherkin runner 时。未接入前不要随意新建测试 runner 目录。 |
| 稳定流程或团队经验 | `.hermes/shared-memory/``.hermes/skills/` | 不是某个功能验收,而是长期可复用的团队流程、坑点、执行规范。 | | 稳定流程或团队经验 | `.hermes/shared-memory/``.hermes/skills/` | 不是某个功能验收,而是长期可复用的团队流程、坑点、执行规范。 |
默认规则: 默认规则:
1. 用户只说“先用 BDD 梳理一下/写场景/写 Gherkin”,默认写到 `.hermes/plans/<task-name>-bdd-scenarios.md` 1. 用户只说“先用 BDD 梳理一下/写场景/写 Gherkin”,默认在当前任务上下文中输出;需要文件时写到 `.tmp/<task-name>-bdd-scenarios.md`
2. 用户说“正式验收标准/PRD/产品文档/给测试验收”,写到 `docs/prd/<FEATURE>_BDD_YYYY-MM-DD.md` 2. 用户说“正式验收标准/PRD/产品文档/给测试验收”,优先合并到当前 `docs/` 融合文档;无法容纳时新增带 `【产品验收】` 标签的 Markdown
3. 用户说“API 行为/后端规则/状态机/埋点/异步任务/SpacetimeDB”,写到 `docs/technical/<FEATURE>_BDD_YYYY-MM-DD.md` 3. 用户说“API 行为/后端规则/状态机/埋点/异步任务/SpacetimeDB”,优先合并到当前后端架构或开发运维文档;无法容纳时新增带 `【技术验收】` 标签的 Markdown
4. 用户明确要求“可执行 feature 文件”且项目已有 runner,再写 `.feature` 文件;否则先写 Markdown BDD 文档,并在测试映射中标注未来自动化落点。 4. 用户明确要求“可执行 feature 文件”且项目已有 runner,再写 `.feature` 文件;否则先写 Markdown BDD 文档,并在测试映射中标注未来自动化落点。
5. 如果 BDD 场景会作为编码依据,文档中必须包含“测试映射”表,标注场景要落到哪些测试文件。 5. 如果 BDD 场景会作为编码依据,文档中必须包含“测试映射”表,标注场景要落到哪些测试文件。
命名建议: 命名建议:
```text ```text
.hermes/plans/profile-feedback-bdd-scenarios.md .tmp/profile-feedback-bdd-scenarios.md
docs/prd/PROFILE_FEEDBACK_BDD_2026-05-11.md docs/【产品验收】帮助与反馈BDD场景-2026-05-11.md
docs/technical/WORK_PLAY_TRACKING_BDD_2026-05-11.md docs/【技术验收】作品游玩埋点BDD场景-2026-05-11.md
tests/features/profile-feedback.feature tests/features/profile-feedback.feature
e2e/features/invite-code.feature e2e/features/invite-code.feature
``` ```
@@ -308,9 +308,9 @@ e2e/features/invite-code.feature
除 BDD/Gherkin 场景外,相关配套内容可放在: 除 BDD/Gherkin 场景外,相关配套内容可放在:
- 实施计划:`.hermes/plans/<task-name>.md` - 实施计划:当前任务上下文或 `.tmp/<task-name>.md`
- 产品/验收文档:`docs/prd/<FEATURE>_PRD_YYYY-MM-DD.md` - 产品/验收文档:当前 `docs/` 融合文档,必要时新增 `docs/【产品验收】中文标题-YYYY-MM-DD.md`
- 技术设计:`docs/technical/<FEATURE>_TECHNICAL_YYYY-MM-DD.md` - 技术设计:当前 `docs/` 融合文档,必要时新增 `docs/【技术方案】中文标题-YYYY-MM-DD.md`
- 共享经验或稳定流程:`.hermes/shared-memory/``.hermes/skills/` - 共享经验或稳定流程:`.hermes/shared-memory/``.hermes/skills/`
BDD 文档建议包含: BDD 文档建议包含:

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