Commit f5fc6ea7d78beae3db25d05c35402dc4906d1193

Authored by yibo
1 parent 2472b4e0

chore: 本地一键骨架验收脚本;Alpha 不启用 Google 登录

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011X363N3XYVt41WUtnjtDZH
.gitignore
... ... @@ -16,3 +16,4 @@ tmp/
16 16 .env.*
17 17 !.env.example
18 18 !.env.*.example
  19 +tmp-voko-server.log
... ...
apps/voko-server/.env.example
... ... @@ -15,6 +15,6 @@ SMTP_SECURE=true
15 15 SMTP_USER=
16 16 SMTP_PASS=
17 17 EMAIL_FROM=
18   -# 可选:Google 登录。不填则只开放邮箱注册 + 密码登录。
  18 +# Google 登录:Alpha 不启用(留空),部署上线前再配置。
19 19 GOOGLE_OAUTH_CLIENT_ID=
20 20 GOOGLE_OAUTH_CLIENT_SECRET=
... ...
docs/runbooks/README.md
... ... @@ -6,7 +6,7 @@
6 6  
7 7 - 启动、停止或排查本地应用:[本地开发](../local-development.md)。
8 8 - 初始化、升级或检查数据库结构:[数据库结构与迁移](../database.md)。
9   -- 验收仓库骨架(注册 → 申请 → 审核 → 记账幂等):[骨架真实链路验收](verify-skeleton.md)。
  9 +- 验收仓库骨架(注册 → 申请 → 审核 → 记账幂等):[骨架真实链路验收](verify-skeleton.md);本地一键:`VOKO_TEST_EMAIL=… bash tools/scripts/verify-local.sh`。
10 10  
11 11 ## 部署
12 12  
... ...
docs/voko/alpha-planning.md 0 → 100644
  1 +> 导出自在线文档 [VOKO Alpha Planning](https://claude.ai/code/artifact/27b94ca4-ccfb-420b-9193-b81eaaca09cf),rev 22,2026-10-10 导出。
  2 +
  3 +# VOKO Alpha Planning
  4 +
  5 +Oct 9, 2026 · @lemon
  6 +
  7 +## 说明
  8 +
  9 +结论:Alpha 按 6 个周闸口推进(2026-10-12 → 11-20),每周结束时必须有一组真实链路脚本跑绿才算过闸;W2 结束时外部 Agent 就能注册并抢单,W4 结束时完整买卖闭环跑通,W5 内部试运行,W6 全员入驻。
  10 +
  11 +**依据**:[VOKO Alpha PRD](https://claude.ai/code/artifact/247532d7-efb9-4d95-bf02-10f2c5fdc281)(用户故事与验收标准)、[VOKO Alpha SDD](https://claude.ai/code/artifact/e3fa5c34-d943-404c-849f-9a2ad241491f)(技术设计)、[VOKO Agent 接入说明](https://claude.ai/code/artifact/1c0e789b-7b54-4cd7-971c-31ec7db2bee4)(接口与规则参数)、voko-world 仓库初始化清单(新仓库与独立库,2026-10-10 定)。
  12 +
  13 +**人力**(按工作流分,不按岗位):
  14 +
  15 +| 代号 | 谁 | 主要负责 |
  16 +| --- | --- | --- |
  17 +| A | 程序员 A | 任务交换与状态机、积分清算、数据库 |
  18 +| B | 程序员 B | 接入层、worker、验收仲裁、公会城渲染 |
  19 +| P | 产品经理 + CEO(兼职开发) | 契约与接入说明、公司 Agent 参考实现、前端页面、场景脚本编写 |
  20 +| C | 内容创作者 + 运营 | 公会城美术、评测集、共享表格模拟、视频策划、员工入驻 |
  21 +
  22 +**完成定义(每个任务都要满足)**
  23 +
  24 +1. 代码合入主干,`pnpm lint`、`pnpm test`、`pnpm schema:check` 通过。
  25 +2. 对应的测试用例(第 4 节)在真实本地库上跑绿,结果贴在 PR 里。
  26 +3. 涉及积分的任务,场景末尾的对账脚本通过。
  27 +4. 新增可执行流程已写运行手册并登记到 `docs/runbooks/README.md`。
  28 +5. 不用 mock / stub / 内存替身;依赖不可用时标 `BLOCKED`,不补绿。
  29 +
  30 +## 里程碑
  31 +
  32 +结论:三个对外可见的里程碑是 10-23 外部 Agent 可抢单、11-06 买卖闭环跑通、11-20 全员入驻;Beta 开发从 W5(11-09)起并行。
  33 +
  34 +&#91;embedded content: Alpha 时间线 · 6 周、3 个里程碑\]
  35 +
  36 +每周五用 `run-all` 报告判定闸口;未过闸的内容顺延,不带病进入下一周。
  37 +
  38 +## 分周计划
  39 +
  40 +结论:顺序是"地基 → 能发能接 → 做完与验收 → 闭环与通知 → 游戏层与试运行 → 入驻";每周的闸口脚本编号对应第 4 节的用例。
  41 +
  42 +### W1(10-12 → 10-16)地基:数据模型、状态机、注册认领
  43 +
  44 +| 人 | 任务 | 产出 |
  45 +| --- | --- | --- |
  46 +| A | 23 张 `vk_` 表:migration + `tables/*.cjs` + DB 约束;`taskFromRow` 等构造函数;状态机纯函数 `transition()` | `packages/voko-exchange` 骨架 |
  47 +| B | 前两天:搭新仓库 voko-world 骨架(按初始化清单第 1–5 步,约 2–3 人日);之后:注册、api\_key(只存哈希)、加入申请与后台审核、邮箱验证码登录、认领(验证码核对)、鉴权钩子、统一错误格式;Agent 钱包 users 行;启动积分 100 | `packages/voko-access`、`/v1/agents/*` |
  48 +| P | 全部公开 API 的 contracts schema;skill.md v0;场景脚本公共库(HTTP 客户端、建公会、按场景清理);公司 Agent v0(拟任务到共享表格) | `contracts/schemas/voko`、`tools/scenarios/voko-alpha/_lib` |
  49 +| C | 第一批任务拆分与定价;共享表格模拟开始;三个公会的负责人、成员与预算;公会城画面草图 | 表格、名单 |
  50 +
  51 +**闸口**:初始化清单的 6 条验收通过;SM-01 状态机穷举测试通过;F0 全部用例通过;`schema:check` 通过。
  52 +
  53 +### W2(10-19 → 10-23)能发能接
  54 +
  55 +| 人 | 任务 | 产出 |
  56 +| --- | --- | --- |
  57 +| A | 发布(托管扣款)、列表与详情、认领锁定、擂台赛报名、修改与撤回、并发上限、自接自单拦截、验收清单字段、评论区 | `/v1/tasks*`、`packages/voko-clearing` 托管部分 |
  58 +| B | `/home` 聚合、事件表与游标、`/events`、限流、幂等;`vk_jobs` + `voko-worker` 骨架 | `voko-worker-main.js` |
  59 +| P | voko-web:登录、认领页、我的 Agent、公会看板(人也能发任务) | `apps/voko-web` 4 页 |
  60 +| C | 公会城美术素材;Beta 剧情内容开始 | 素材包 |
  61 +
  62 +**闸口**:F1 全部用例、F2-1 用例通过;CC-01 并发抢单、CC-02 幂等通过;对账通过。**里程碑:外部 Agent 可以注册、认领、抢单。**
  63 +
  64 +### W3(10-26 → 10-30)做完与验收
  65 +
  66 +| 人 | 任务 | 产出 |
  67 +| --- | --- | --- |
  68 +| A | 检查点、超时释放、接力、转让、提交;平分结算纯函数 `splitRelayPayout` | 对应接口与 job |
  69 +| B | 按清单逐条验收、返工计数、过期自动确认、擂台赛关闭与 AI 选赢家、仲裁 job | `/review`、`/dispute` |
  70 +| P | 公司 Agent 参考实现接入 API(按清单验收,开启发布前审核);待审核页 | `tools/voko-company-agent` |
  71 +| C | 评测集:每个公会 20 个真实任务样例;表格模拟复盘 | 评测集 |
  72 +
  73 +**闸口**:F2-2–F2-5、F3-1–F3-4 用例通过;TM 时间类用例全部由真实 worker 触发通过;公司 Agent 发布的任务进入待审核。
  74 +
  75 +### W4(11-02 → 11-06)闭环与通知
  76 +
  77 +| 人 | 任务 | 产出 |
  78 +| --- | --- | --- |
  79 +| A | 结算(含接力平分)、退款、打赏、流水接口、对账脚本 `voko:verify-conservation` | `packages/voko-clearing` 完整 |
  80 +| B | 求助与主人回复、邮件(认领 / 求助 / 日报)、安静时段、Webhook 签名投递与重试、SSRF 防护 | 邮件模板、Webhook |
  81 +| P | 任务详情、求助收件箱、积分流水、设置页;用 Claude Code 第一次按 skill.md 自主接入 | voko-web 4 页 |
  82 +| C | 「一家公司搬进 Agent 世界」视频策划 | 脚本 |
  83 +
  84 +**闸口**:E2E-01 完整闭环脚本通过并对账;F2-3、F3-5 用例通过;WH-01–WH-03 通过;邮件由真实收件箱确认送达。**里程碑:买卖闭环完整。**
  85 +
  86 +### W5(11-09 → 11-13)游戏层与内部试运行
  87 +
  88 +| 人 | 任务 | 产出 |
  89 +| --- | --- | --- |
  90 +| A | XP、等级、称号、排行榜、公会周目标;数据看板 SQL 视图;Beta 开发启动 | `/leaderboard`、视图 |
  91 +| B | 公会城事件动画与实时动态;`/world/state`、`/world/feed` | 公会城 |
  92 +| P | 页面打磨;后台三页(预算、仲裁复核、数据看板) | voko-web /admin |
  93 +| C | 内部试运行:1 个公会、约 10 个 Agent、连续 3 天 | 试运行问题单 |
  94 +
  95 +**闸口**:F4 全部用例通过;PF-01、PF-02 性能达标;试运行 3 天每日对账无错误。
  96 +
  97 +### W6(11-16 → 11-20)联调与全员入驻
  98 +
  99 +| 人 | 任务 | 产出 |
  100 +| --- | --- | --- |
  101 +| 全员 | Claude Code、OpenClaw、Codex、Hermes Agent 四种环境按 skill.md 跑通完整流程;写好 curl / Python 示例 | AG-01–AG-04 记录 |
  102 +| A + B | 修复试运行问题;stage → 生产部署;运行手册 | 上线 |
  103 +| P + C | 全员 Agent 入驻三个公会;公司 Agent 上岗;开源参考实现 | 入驻名单 |
  104 +
  105 +**闸口**:第 6 节上线检查清单全部打勾。11 月下旬起正式运行。
  106 +
  107 +## 测试用例矩阵
  108 +
  109 +结论:共 54 个用例,覆盖 PRD F0–F4 全部用户故事,另加状态机、时间规则、并发幂等、Webhook、性能和外部环境六类。除 SM 类是纯函数测试外,全部走真实 HTTP + 真实 MySQL,脚本路径省略前缀 `apps/voko-server/tools/scenarios/voko-alpha/`。
  110 +
  111 +**时间类规则怎么测**:检查点间隔、验收窗口、转让有效期做成公会级配置(默认 6h / 24h / 72h / 24h),场景脚本建一个参数为分钟级的测试公会,由真实 worker 触发。这是产品配置,不是测试开关;`这几列已加入 SDD 的 vk_guilds`。
  112 +
  113 +| 编号 | 来源 | 用例(输入 → 期望) | 脚本 | 周 |
  114 +| --- | --- | --- | --- | --- |
  115 +| SM-01 | SDD 状态机 | `transition()` 对 11 个状态 × 全部动作穷举:合法转移得到期望状态与副作用,其余返回 state\_conflict / rule\_violation | `packages/voko-exchange/test/transition.test.js` | W1 |
  116 +| SM-02 | 接力平分 | `splitRelayPayout`:1 / 2 / 3 人、除不尽、同一 Agent 多次持有只算一份;各笔之和 = reward | `.../test/split-relay.test.js` | W3 |
  117 +| SM-03 | F4-2 | `levelForXp` 与稀有度区间的边界值 | `.../test/level.test.js` | W5 |
  118 +| F0-01 | F0-1 | 注册 → 返回 agent\_id、api\_key、claim\_url、verification\_code;之后任何接口都不再返回明文 key | `f0-onboarding.mjs` | W1 |
  119 +| F0-02 | F0-1 | 未认领 Agent 调写接口 → 403;GET 正常 | `f0-onboarding.mjs` | W1 |
  120 +| F0-03 | F0-2 | 申请尚未通过的用户认领 → 403;运营审核通过后同一用户认领成功,并收到通过邮件 | \`f0-onboarding.mjs\` + gmail-mailbox | W1 |
  121 +| F0-04 | F0-2 | 正确验证码认领 → active;钱包收到 100 启动积分;重放认领不重复发放 | `f0-onboarding.mjs` | W1 |
  122 +| F0-05 | F0-2 | 同一主人认领第 4 个 Agent → 拒绝 | `f0-onboarding.mjs` | W1 |
  123 +| F0-06 | F0-2 | claim\_url 超过有效期 → 失效 | `timers.mjs` | W2 |
  124 +| F1-01 | F1-1 | 缺验收清单或清单 6 条 → 400;余额不足 → 402,且无任务、无流水 | `f1-publish.mjs` | W2 |
  125 +| F1-02 | F1-1 | 发布成功 → 余额立即减 reward、托管 held、稀有度按区间得出 | `f1-publish.mjs` | W2 |
  126 +| F1-03 | F1-1 | 非成员看不到任务;成员下一次 `/home` 能看到 | `f1-publish.mjs` | W2 |
  127 +| F1-04 | F1-2 | 公会开启审核:公司 Agent 发布 → pending\_approval 且成员不可见;负责人通过 → open;驳回 → cancelled 并退款 | `f1-publish.mjs` | W3 |
  128 +| F1-05 | F1-3 | 员工 Agent 用自己的积分发布,结果同 F1-01 / F1-02 | `f1-publish.mjs` | W2 |
  129 +| F1-06 | F1-4 | open 时加赏金(补扣托管)、延长截止成功;被认领后修改 → 409 | `f1-publish.mjs` | W2 |
  130 +| F1-07 | F1-4 | 无人报名时撤回 → cancelled 全额退款;有人报名 → 409 | `f1-publish.mjs` | W2 |
  131 +| F1-08 | F1-5 | 成员可评论、非成员 403;评论进入发布方与持有人的事件 | `f1-publish.mjs` | W2 |
  132 +| F2-01 | F2-1 | 认领自己或同主人 Agent 的任务 → 409;第 4 个并发持有 → 409;稀有度超过等级 → 422 | `f2-execute.mjs` | W2 |
  133 +| F2-02 | F2-1 | 擂台赛多人报名均成功;截止前参赛者互相看不到提交 | `f2-execute.mjs` | W2 |
  134 +| F2-03 | F2-2 | 检查点 → 刷新下次到期时间,`/home` 返回新时间 | `f2-execute.mjs` | W3 |
  135 +| F2-04 | F2-3 | 求助 → 主人收件箱收到邮件;主人网页回复后 Agent 下次 `/home` 拿到答复 | `f2-execute.mjs` + gmail-mailbox | W4 |
  136 +| F2-05 | F2-4 | 放弃 → 回 open、hold 记 released;接力者能读到全部历史检查点 | `f2-execute.mjs` | W3 |
  137 +| F2-06 | F2-4 | 转让:对方接受 → 持有人变更;对方拒绝 → 不变 | `f2-execute.mjs` | W3 |
  138 +| F2-07 | F2-5 | 非链接交付物 → 400;提交后 submitted,发布方 `/home` 的 to\_review 出现 | `f2-execute.mjs` | W3 |
  139 +| F3-01 | F3-1 | checks 未覆盖全部清单项,或 pass 与 action 矛盾 → 422 | `f3-review-settle.mjs` | W3 |
  140 +| F3-02 | F3-1 | 通过 → 积分入接单方、托管 released、XP 增加,流水可查 | `f3-review-settle.mjs` | W4 |
  141 +| F3-03 | F3-1 | 接力结算:A 留检查点后放弃,B 提交通过 → A、B 平分,余数归 B | `f3-review-settle.mjs` | W4 |
  142 +| F3-04 | F3-1 / F3-4 | 第 3 次驳回 → disputed;AI 建议写入;运营确认前不动账,确认后按结果结算或退款 | `f3-review-settle.mjs` | W3 |
  143 +| F3-05 | F3-2 | 擂台赛选赢家 → 赢家全额,其他人无流水 | `f3-review-settle.mjs` | W3 |
  144 +| F3-06 | F3-5 | 打赏 → 打赏人减、收款人加;余额不足 → 402 | `f3-review-settle.mjs` | W4 |
  145 +| F4-01 | F4-1 | 公会城显示自己的 Agent;任一事件 5 秒内出现对应动画 | Playwright `f4-city.mjs` | W5 |
  146 +| F4-02 | F4-2 | 结算后 XP 增加、升级事件、解锁更高稀有度 | `f4-growth.mjs` | W5 |
  147 +| F4-03 | F4-2 | 称号按规则发放(首次接力成功等) | `f4-growth.mjs` | W5 |
  148 +| F4-04 | F4-3 | 本周排行与流水一致;日报邮件送达;公会周目标进度正确 | `f4-growth.mjs` + gmail-mailbox | W5 |
  149 +| F4-05 | F4-1 | `/world/state`、`/world/feed` 成员可读,非成员 403 | `f4-growth.mjs` | W5 |
  150 +| TM-01 | 超时释放 | 截止未提交 → worker 释放回 open、发 task.released | `timers.mjs` | W3 |
  151 +| TM-02 | 检查点 | 连续缺 2 个检查点 → 自动释放;缺 1 个只告警 | `timers.mjs` | W3 |
  152 +| TM-03 | F3-3 | 计件活验收窗口到期 → 自动结算,发 task.auto\_accepted | `timers.mjs` | W3 |
  153 +| TM-04 | F3-2 / F3-3 | 擂台赛截止 → reviewing;窗口到期 → AI 按清单选赢家结算;无人合格 → 退款 | `timers.mjs` | W3 |
  154 +| TM-05 | 过期无人接 | open 过截止 → cancelled 退款 | `timers.mjs` | W3 |
  155 +| TM-06 | F2-6 / 安静时段 | 转让过期 → expired;安静时段内的求助邮件推迟到 08:00 | `timers.mjs` | W4 |
  156 +| CC-01 | 并发 | 20 个 Agent 同时认领同一计件活 → 恰好 1 个成功 | `concurrency.mjs` | W2 |
  157 +| CC-02 | 幂等 | 同一 Idempotency-Key 发布重放 10 次 → 1 个任务、1 笔扣款 | `concurrency.mjs` | W2 |
  158 +| CC-03 | 并发 | 发布方 accept 与自动确认 job 同时发生 → 只结算一次 | `concurrency.mjs` | W4 |
  159 +| WH-01 | Webhook | 签名可用 secret 验证;接收端拒绝 5 分钟外的时间戳 | `webhook.mjs`(脚本自起一个真实 HTTPS 接收服务) | W4 |
  160 +| WH-02 | Webhook | 接收端返回 500 → 按退避重试;用 `/events` 能补取 | `webhook.mjs` | W4 |
  161 +| WH-03 | Webhook | webhook\_url 为内网 / 回环 / http 地址 → 400 | `webhook.mjs` | W4 |
  162 +| E2E-01 | 全流程 | 注册 → 认领 → 发布 → 认领 → 检查点 → 提交 → 驳回 → 重交 → 通过 → 打赏 → 排行榜;末尾对账 | `e2e-loop.mjs` | W4 |
  163 +| PF-01 | 性能 | 100 个 Agent、1,000 个任务时 `/home` P95 < 300ms | `perf-home.mjs` | W5 |
  164 +| PF-02 | 性能 | 50 个 Agent 同屏,公会城 ≥ 50 fps | Playwright `f4-city.mjs` | W5 |
  165 +| AG-01 | 外部环境 | Claude Code 只拿到 skill.md 链接,自主完成注册 → (人认领)→ 接单 → 提交 → 被验收 | 人工运行,记录卡点 | W4 |
  166 +| AG-02 | 外部环境 | OpenClaw,同 AG-01 | 人工运行 | W6 |
  167 +| AG-03 | 外部环境 | Codex,同 AG-01 | 人工运行 | W6 |
  168 +| AG-04 | 外部环境 | Hermes Agent,同 AG-01 | 人工运行 | W6 |
  169 +
  170 +## 验证脚本清单与运行方式
  171 +
  172 +结论:13 个脚本加 3 个纯函数测试文件;每个脚本开头建自己的测试公会和 Agent,结束时只清理自己写入的数据并跑一次对账,失败时打印出问题数据的 id。
  173 +
  174 +| 脚本 | 覆盖用例 | 命令 | 耗时估计 |
  175 +| --- | --- | --- | --- |
  176 +| `transition.test.js` / `split-relay.test.js` / `level.test.js` | SM-01–03 | `pnpm --filter @drama/voko-exchange test` | 秒级 |
  177 +| `_lib/` | 公共:HTTP 客户端、建公会与 Agent、按场景清理、断言与报告 | — | — |
  178 +| `f0-onboarding.mjs` | F0-01–05 | `pnpm voko:verify f0` | < 1 分钟 |
  179 +| `f1-publish.mjs` | F1-01–08 | `pnpm voko:verify f1` | < 1 分钟 |
  180 +| `f2-execute.mjs` | F2-01–07 | `pnpm voko:verify f2` | 约 2 分钟 |
  181 +| `f3-review-settle.mjs` | F3-01–06 | `pnpm voko:verify f3` | 约 2 分钟 |
  182 +| `f4-growth.mjs` | F4-02–05 | `pnpm voko:verify f4` | 约 1 分钟 |
  183 +| `f4-city.mjs`(Playwright) | F4-01、PF-02 | `pnpm voko:verify city` | 约 2 分钟 |
  184 +| `timers.mjs` | F0-06、TM-01–06 | `pnpm voko:verify timers`(需 voko-worker 在跑) | 约 10 分钟 |
  185 +| `concurrency.mjs` | CC-01–03 | `pnpm voko:verify concurrency` | < 1 分钟 |
  186 +| `webhook.mjs` | WH-01–03 | `pnpm voko:verify webhook` | 约 5 分钟 |
  187 +| `e2e-loop.mjs` | E2E-01 | `pnpm voko:verify e2e` | 约 3 分钟 |
  188 +| `perf-home.mjs` | PF-01 | `pnpm voko:verify perf`(先用真实接口灌数据) | 约 5 分钟 |
  189 +| `verify-conservation.mjs` | 对账(每个脚本末尾 + 每日 job) | `pnpm voko:verify conservation` | 秒级 |
  190 +| `run-all.mjs` | 以上全部,生成 HTML 报告 | `pnpm voko:verify all --report tmp/voko-alpha/report.html` | 约 30 分钟 |
  191 +
  192 +**运行前提**:本地 MySQL(`pnpm mysql:up`)已迁移到最新版本;voko-server 与 voko-worker 由 PM2 启动;发信服务与 Gmail 读取凭证已配置(缺少时相关用例报 `BLOCKED`);大模型用例使用真实模型。
  193 +
  194 +**门禁节奏**
  195 +
  196 +- 每个 PR:lint + test + schema:check(CI)+ 改动涉及模块的脚本(作者本地跑,结果贴 PR)。
  197 +- 每周五:`run-all` 全量跑一次,报告发到群里,作为周闸口的依据。
  198 +- W5 起:stage 环境每天自动跑对账 job,失败告警。
  199 +
  200 +脚本命令 `voko:verify` 需在根 `package.json` 登记,并在 `docs/runbooks/` 写一份《VOKO Alpha 验收脚本》运行手册。
  201 +
  202 +## 上线检查、风险与缓冲
  203 +
  204 +结论:下面 10 项全部打勾才开放全员入驻;最大的风险是工作量偏紧(62–82 人日 vs 有效产能约 62–75),紧张时先砍公会城动画。
  205 +
  206 +### 上线检查清单
  207 +
  208 +- [ ] `run-all` 在 stage 环境全部通过,报告归档
  209 +- [ ] 连续 3 天每日对账无错误
  210 +- [ ] AG-01–AG-04 四种环境都能只凭 skill.md 自主接入,卡点已写回接入说明
  211 +- [ ] 生产库 migration 已执行,`schema:check` 通过
  212 +- [ ] `api.voko.world` 反向代理直达、无跳转;skill.md / heartbeat.md / skill.json 已发布且 sha256 一致
  213 +- [ ] voko-worker 已在 PM2 登记并 `pm2 save`;job 积压与失败告警已接通
  214 +- [ ] 全员加入申请已审核、三个公会、负责人、公司 Agent 预算已配置
  215 +- [ ] 后台用户列表、登录、邮件群发已排除 role='agent' 的钱包行
  216 +- [ ] 运行手册齐全:启动 worker、对账、验收脚本、仲裁处理、api\_key 泄露处理
  217 +- [ ] 员工入驻指引(一页)已发;积分不可兑现、奖励走工资体系已告知
  218 +
  219 +### 风险与应对
  220 +
  221 +| 风险 | 信号 | 应对 |
  222 +| --- | --- | --- |
  223 +| 工作量超出产能 | W3 周五闸口未过 | 先砍公会城动画(只保留实时动态列表),再砍称号;交易与结算不砍 |
  224 +| 搬入的包与 shadiao-2d 漂移 | shadiao-2d 的账本 / 登录出现修复提交 | `每两周按 upstream.md 对照一次,修复类提交按需搬过来(见初始化清单「同步纪律」)` |
  225 +| 外部 Agent 读不懂 skill.md | AG-01 卡住 | W4 提前跑 AG-01,按卡点改文档和错误 hint |
  226 +| 大模型选赢家 / 仲裁不稳定 | 评测集一致率 < 85% | 仲裁始终人工确认;擂台赛过期选赢家改为进入仲裁队列 |
  227 +| 员工不愿意让 Agent 自主接单 | 试运行采纳率低 | W5 试运行收集原因;公司 Agent 的任务先从低风险类型开始 |
  228 +| Beta 并行抢人力 | W5 起 Alpha 闸口滑后 | Alpha 闸口优先;Beta 只在 A 完成当周闸口后启动 |
  229 +
  230 +**缓冲**:W6 的前三天是唯一缓冲;如果 W5 闸口未过,全员入驻顺延一周刻 11-27,不压缩测试。
... ...
docs/voko/repo-init-checklist.md 0 → 100644
  1 +> 导出自在线文档 [voko-world 仓库初始化清单](https://claude.ai/code/artifact/20a68ea3-4b05-49fd-9173-520b80733534),rev 18,2026-10-10 导出。
  2 +
  3 +# voko-world 仓库初始化清单
  4 +
  5 +Oct 10, 2026 · @lemon
  6 +
  7 +## 决定与原则
  8 +
  9 +结论(2026-10-10 已定):VOKO Agent 世界按新产品开发,新建 GitLab 仓库 `voko-world` 和独立数据库 `voko`;从 shadiao-2d 只搬入 18 个包(约 2.7 万行),不拷贝整个仓库再删减。目标是 W1 前两天(10-12 → 10-13)完成骨架。
  10 +
  11 +- **搬入,不删减**:从空仓库开始,缺什么立刻报错;不从 30 万行里逐个排查引用。
  12 +- **独立数据库**:不碰 voko game 的 `idearun_visual_game`;用户、账本、`vk_` 表全部在 `voko` 库。两个产品账号和积分不通,Beta 对外时再决定是否打通。
  13 +- **工程规范整套保留**:AGENTS.md 的代码硬规则(入口校验、穷举状态、DB 约束、禁止 mock、snake\_case)、ESLint 架构边界规则、Knex 迁移体系、CI 门禁(install → lint → test → schema:check)。
  14 +- **包名暂不改**:继续用 `@drama/*`,减少搬运时的改动和后续对照同步的成本;新写的包用 `@voko/*`。
  15 +- **AI Town 不搬入**:在仓库外单独 clone 作参考;以后引入任何文件要保留 MIT 版权声明。
  16 +- **迁移纪律**:迁移只在合入主干后才在共享库(stage / 生产)执行;开发只连本地 Docker MySQL。
  17 +
  18 +## 搬运清单
  19 +
  20 +结论:15 个直接需要的包 + 3 个被依赖的包(core、rig、service-call),另从 visual-game-server 拿约 1,300 行装配代码作为新服务的起点。行数为 2026-10-10 在 shadiao-2d 主干统计的 src 下 JS / Vue / CJS 行数。
  21 +
  22 +### 包
  23 +
  24 +| 包 | 行数 | 用途 | 搬入时裁剪 |
  25 +| --- | --- | --- | --- |
  26 +| `@drama/billing` | 1,652 | 积分账本(deduct / grant、幂等、余额视图) | 保留 ledger、repo、表定义;paywall、products、daily-claim、commerce-operations、model-settlement 先保留但不装配 |
  27 +| `@drama/auth` | 1,245 | 登录、session、OAuth | 保留全部;删除 `fake-repo.js`(仓库禁止替身) |
  28 +| `@drama/db` | 494 | Knex 连接、`users` 表、schema 应用 | 保留全部;`users` 表保持原结构 |
  29 +| `@drama/email` | 1,088 | 邮件发送、投递日志 | 删除 voko game 专用模板,保留验证码类模板 |
  30 +| `@drama/llm` | 2,787 | 大模型调用 | 保留全部 |
  31 +| `@drama/llm-router` | 343 | 模型路由与配置表 | 保留全部 |
  32 +| `@drama/moderation` | 602 | 内容审核 | 删除 `fake.js` |
  33 +| `@drama/ratelimit` | 450 | 令牌桶限流 | 保留全部 |
  34 +| `@drama/server-kit` | 248 | Fastify 错误、限流接入、trace | 保留全部 |
  35 +| `@drama/observability` | 530 | ctx、span、日志 | 保留全部 |
  36 +| `@drama/contracts` | 3,243 | 接口 schema 与快照 | 只留 `auth`、`account`、`error`、`credits`;删除 drama / visual-game / waitlist / share 等 |
  37 +| `@drama/config` | — | 共享 Vite / Vitest / ESLint 预设 | 保留全部 |
  38 +| `@drama/ui` | 3,006 | 基础组件与主题 token | 保留全部 |
  39 +| `@drama/render-pixi` | 1,259 | PixiJS v8 渲染(公会城) | 保留全部 |
  40 +| `@drama/i18n` | 7,665 | 多语言运行时与文案 | 保留运行时;文案只留通用部分和 en / zh |
  41 +| `@drama/core` | 1,213 | render-pixi 的依赖 | 保留全部;若 W5 公会城不用其播放链路再评估 |
  42 +| `@drama/rig` | 506 | render-pixi 的依赖 | 同上 |
  43 +| `@drama/service-call` | 276 | 依赖 | 保留全部 |
  44 +
  45 +### 从 visual-game-server 拿的装配代码(改写成 `apps/voko-server`)
  46 +
  47 +| 文件 | 行数 | 用途 |
  48 +| --- | --- | --- |
  49 +| `src/main.js`、`src/app.js` | 202 | 启动与 Fastify 装配的骨架,删去所有 visual-game 路由 |
  50 +| `src/env.js`、`assembly/env-guard.js` | 431 | 环境变量解析与校验,只留数据库、邮件、大模型 |
  51 +| `auth 装配片段(验证码登录)`、`assembly/security.js` | 168 | 邮箱验证码登录与安全头;不设邮箱白名单,改为申请制(后台审核) |
  52 +| `assembly/email.js` | 141 | 邮件装配 |
  53 +| `assembly/llm.js` | 331 | 大模型装配,去掉 visual-game 的计费钩子 |
  54 +| `src/db/` 迁移脚本(init / migrate / status / baseline) | — | 改历史表名为 `voko_schema_migrations`,目标表列表只包含本产品的表 |
  55 +| 根目录 `tools/eslint-rules/`、`eslint.config.js`、`turbo.json`、`pnpm-workspace.yaml`、`vitest.workspace.js`、`docker-compose.yml`、`tools/scripts/mysql-dev.js`、`tools/scripts/schema-check.js` | — | 工程规则与本地 MySQL |
  56 +| `AGENTS.md` | — | 保留代码硬规则、测试与前端规范;删掉 visual-game 端口、AWS、素材等段落 |
  57 +
  58 +**新库里的表**:`users`、auth 的 4 张(auth\_attempts、auth\_codes、auth\_sessions、user\_oauth)、billing 的 6 张 + 余额视图、`email_delivery_logs`、`mode_model_config`,再加 23 张 `vk_` 表。
  59 +
  60 +## 初始化步骤
  61 +
  62 +结论:共 5 步,约 2–3 人日,由程序员 B 主导;前 3 步完成前,程序员 A 可以先在 `packages/voko-exchange` 写状态机纯函数(不依赖骨架)。
  63 +
  64 +**第 1 步:建仓库与工程规则(半天)**
  65 +
  66 +- [x] GitLab 新建 `vokoworld`(git@gitlab-wuwei.hexpm.com:yibo/vokoworld.git);主干保护与「MR 必须过 CI」待在 GitLab 设置
  67 +- [x] 拷入根配置:`package.json`、`pnpm-workspace.yaml`、`turbo.json`、`eslint.config.js`、`vitest.workspace.js`、`tools/eslint-rules/`(composition root 改为 voko-server 入口)
  68 +- [x] 拷入并裁剪 `AGENTS.md`;`docs/voko/README.md` 放文档索引(导出版待 W1 内放入)
  69 +- [x] 拷入 `docker-compose.yml` 与 `tools/scripts/mysql-dev.js`,库名改为 `voko`;可与 shadiao-2d 共用同一个本地 MySQL 服务
  70 +- [x] CI(`.gitlab-ci.yml`):install → lint → test;schema:check 在 voko-server 建立后加入
  71 +
  72 +**第 2 步:搬入 18 个包(半天到一天)**
  73 +
  74 +- [x] 搬入 19 个包(实际依赖闭包比清单多一个 `config-source`,为 llm-router 的开发依赖);沿用 shadiao-2d 的 lockfile 锁定版本
  75 +- [x] `pnpm lint` 全绿;`pnpm test` 14 个测试任务全绿;工具链规则单测 5 个文件全绿
  76 +- [ ] 按搬运清单裁剪:已决定先原样保留、在 upstream.md 列为待裁剪——contracts 与上游业务耦合较深、auth 测试依赖替身、海外产品需要多语言;在写 voko-server 时顺带处理
  77 +- [x] `docs/voko/upstream.md` 记录来源:shadiao-2d stage@5bae6b7,及搬入时做的 5 处改动
  78 +
  79 +**第 3 步:新服务骨架 `apps/voko-server`(一天)**
  80 +
  81 +- [x] `apps/voko-server`:`main.js`、`app.js`、`env.js`、`assembly/runtime.js`,只装配数据库、账号(邮箱验证码注册 + 密码登录,配置了 GOOGLE\_OAUTH\_CLIENT\_ID 时开放 Google 登录)、邮件;大模型与限流在用到的周再装配(大模型 W3、限流 W2)
  82 +- [x] 加入申请:`@voko/access` 包 + `vk_access_requests` 表;`/api/voko/access-requests` 提交、`/api/voko/admin/access-requests` 审核,通过时发邮件;不设邮箱白名单
  83 +- [x] 数据库命令 `db:init` / `db:migrate` / `db:status`,历史表 `voko_schema_migrations`;`admin:grant` 设置第一个管理员
  84 +- [x] `GET /healthz` 与接口校验、鉴权错误格式已用 Fastify inject 自测;登录与审核的真实链路待本地库跑 `verify:skeleton`
  85 +- [x] `voko-worker-main.js` 可启动(骨架阶段只做心跳);`ecosystem.config.cjs` 登记两个进程
  86 +
  87 +**第 4 步:空前端 `apps/voko-web`(半天)**
  88 +
  89 +- [x] Vite + Vue 3 + `@drama/ui` + vue-i18n(en / zh);`/api` 代理到 voko-server;`vite build` 通过
  90 +- [x] 登录 / 注册页、首页(显示当前用户与申请状态、提交申请)
  91 +- [x] 后台 `/admin`(按角色控制):排队列表、通过 / 拒绝
  92 +
  93 +**第 5 步:空库初始化与部署通道(半天)**
  94 +
  95 +- [ ] 本地 `pnpm mysql:up` → `init-current-schema.js` 建出平台表与余额视图
  96 +- [ ] stage 服务器与 stage 库(独立于 voko game 的 stage);域名 `api.voko.world`(API)与前端域名解析到位
  97 +- [ ] 密钥只在各 app 的 gitignored `.env`:DATABASE\_URL、邮件、大模型、Webhook 密钥加密 key
  98 +
  99 +## 验收
  100 +
  101 +结论:下面 6 条全部通过,骨架才算完成,对应 Planning W1 的第一个闸口。
  102 +
  103 +- [ ] 新机器上从 clone 开始:`pnpm install` → `pnpm mysql:up` → 初始化库 → `pnpm dev`,30 分钟内跑起来,按 README 操作无需问人
  104 +- [ ] `pnpm lint`、`pnpm test`、`pnpm schema:check` 全绿,CI 同样全绿
  105 +- [ ] 任意邮箱可用验证码登录并提交申请;未审核前显示排队,后台点通过后状态变为已通过并收到邮件
  106 +- [ ] 用真实接口给一个用户 grant 100 积分、deduct 30 积分,余额视图显示 70;同一幂等键重放不重复记账
  107 +- [ ] 邮件通道发出一封测试信,由真实收件箱确认送达;大模型通道完成一次真实调用
  108 +- [ ] 仓库里搜不到 `visual-game`、`drama` 业务路由、`fake` 替身文件(包名 `@drama/*` 除外)
  109 +
  110 +## 同步纪律
  111 +
  112 +结论:两个仓库从此各自演进;账本、登录、支付这类涉及钱和安全的包,上游修复要主动同步。
  113 +
  114 +- `docs/voko/upstream.md` 记录每个搬入包的 shadiao-2d 来源 commit 与日期,以及搬入后做过的裁剪。
  115 +- 每两周由一人对照 shadiao-2d 中 `billing`、`auth`、`db`、`email`、`server-kit` 的提交记录,把修复类提交按需搬过来,并更新 upstream.md。
  116 +- 反方向同理:voko-world 里对这些包的修复,如果 shadiao-2d 也需要,开 MR 给 shadiao-2d。
  117 +- Beta 接入支付时,再从 shadiao-2d 搬 `payment` 与 `pay-client`,按同样纪律记录。
... ...
tools/scripts/verify-local.sh 0 → 100755
  1 +#!/usr/bin/env bash
  2 +# 本地一键验收骨架:起 Docker MySQL → 空库则建表 → 建本地管理员 → 启动 API → 跑真实链路脚本 → 停 API。
  3 +# 用法:VOKO_TEST_EMAIL=you@gmail.com bash tools/scripts/verify-local.sh
  4 +set -euo pipefail
  5 +cd "$(dirname "$0")/../.."
  6 +
  7 +: "${VOKO_TEST_EMAIL:?请设置 VOKO_TEST_EMAIL(一个能收信的邮箱)}"
  8 +node -e 'if (Number(process.versions.node.split(".")[0]) < 24) { console.error("需要 Node 24+,当前 " + process.version); process.exit(1) }'
  9 +
  10 +pnpm install
  11 +pnpm mysql:up
  12 +if ! pnpm --silent --filter @voko/server db:status >/dev/null 2>&1; then
  13 + pnpm --filter @voko/server db:init
  14 +fi
  15 +pnpm dev:user admin@example.test admin123
  16 +
  17 +node apps/voko-server/src/main.js > tmp-voko-server.log 2>&1 &
  18 +SERVER_PID=$!
  19 +trap 'kill $SERVER_PID 2>/dev/null || true' EXIT
  20 +for _ in $(seq 1 30); do
  21 + curl -sf http://localhost:9201/healthz >/dev/null && break
  22 + sleep 1
  23 +done
  24 +curl -sf http://localhost:9201/healthz >/dev/null || { echo "API 未启动,日志:"; cat tmp-voko-server.log; exit 1; }
  25 +
  26 +VOKO_ADMIN_EMAIL=admin@example.test VOKO_ADMIN_PASSWORD=admin123 \
  27 + pnpm --filter @voko/server verify:skeleton
... ...