games-development-ai/docs/agent-specs/_archive/2026-06-09-B4四链路烟测报告.md
zizi 7f24a344d0 docs(agent-specs): B2 归档——64 个闭线工作记录移入 _archive/,热目录顶层 90→26
承接目录治理:上轮只压缩内容未减文件数,闭线工作记录仍平铺致目录看着仍一堆(创始人指出)。本次执行 B2 归档。

64 个 ≤06-15 闭线档(25 压缩桩 + 闭线 review/report/纪要/edit-plan)git mv 入 docs/agent-specs/_archive/(文件名不变、仍 git 跟踪可查)。热目录 ≤06-15 仅留 13 活档(决策/纲领/SoT/活spike)+13 个 06-16 在飞。

活资产 20 处旧路径引用(.agents/docs/memory/_index)同步改 _archive/,引用断裂复测=0;_index 活地图 + 治理档状态收口。约束:0 个 06-16 被移、orchestrator 等未跟踪在飞档零误纳。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:26:19 +00:00

159 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# B4 四链路(广告/收益/分享/互动staging 烟测登记
> 日期2026-06-09 执行:测试工程师 subagent 目标环境stagingmini-desktop, http://100.64.0.7:48080
> 目的:给 MVP 总账一份「真实/桩」的诚实清册,**不修代码、不下结论性承诺**。
> 判据HTTP 200 ∧ body.code==0 ∧ 结构合理 = 通;受控业务错误码精确命中 = 链路活但按设计拒绝。
> 写库纪律:全程零业务写入,唯一例外为 2 条 telemetry 测试事件eventId 前缀 `b4smoke-`,已留清理 SQL见 §6
---
## 1. 结论速览(总表)
| 链路 | 判定 | 一句话 |
|---|---|---|
| 广告 | **部分真实** | 后端计费链(幂等/归因/落账/合规闸门/T+1 对账锚点)真实,但计价与激励校验是 mock SPI、staging 0 个广告位、**前端完全未接后端计费 API**(宿主桩弹层自产自销) |
| 收益 | **部分真实** | 账户原子账本/提现状态机/80% 分成结算代码真实且幂等,但打款是 mock 状态机、**结算 Job 在 staging 被关闭xxl.job.enabled=false永不运行**、前端无收益页入口、全链路 0 数据 |
| 分享 | **部分真实** | 端点活发布门禁真实project.status==4、utm_source 渠道归因真实、versionId 回填真实;但 **OG 标题/封面/描述=空串桩**、分享域名写死占位 `https://wanxiang.ai/s/` |
| 互动 | **部分真实**(排序权重路径=**已证**,走 telemetry | interact 幂等落库+聚合计数回显真实、前端 InteractBar 已接线;但 **interact 信号未接排序权重**(排序的 like/share 权重实际来自 telemetry 事件B2 已证+本次复证)、举报转 compliance 是占位日志、互动态回显恒 false |
staging 数据现状(只读核查,烟测前后均如此,证明探针零污染):
```
ad_slot=0 ad_revenue=0 trade_account=0 trade_income=0 trade_withdraw=0 interact_log=0
```
即:**四条链路在 staging 从未被真实使用过**对比feed/telemetry 主链路 B1/B2 已有数据)。
---
## 2. 路径发现方法
- 模块定位:`game-cloud/game-module-ad`(广告)、`game-module-trade`(收益/分成/提现)、`game-module-feed`(分享+互动)、`game-module-telemetry`(互动遥测口径)。
- app 侧前缀:`/app-api` 由框架按包名 `controller.app.*` 自动添加(各 controller 头注释自述,如 AdController.java:28并经本次 curl 实测证实路径可达)。
- Flyway V6ad/V7trade/V10 均无 INSERT 种子grep 实证)→ 广告位等运营数据需人工配置staging 没人配过。
---
## 3. 各链路详情
### 3.1 广告链路game-module-ad
**端点烟测表**
| # | 路径 | 方法 | HTTP | code | 判定 | 证据 |
|---|---|---|---|---|---|---|
| 1 | `/app-api/ad/slot/list-enabled` | GET | 200 | 0 | 真实(但空配置) | 实测 `{"code":0,"data":[]}`DB `game_ad_slot`=0 行AdSlotService 真查库AdController.java:48-51 |
| 2 | `/app-api/ad/report/impression` | POST假 slotId 探针,零写) | 200 | 1111002000 | 部分真实 | 实测精确命中 `AD_REPORT_SLOT_DISABLED`ErrorCodeConstants.java:27证明 路由→VO 校验→Service→slot 查库 全链活;计费核心见下 |
| 3 | `/app-api/ad/report/reward` | POST同上探针 | 200 | 1111002000 | 部分真实 | 同上,同走 `bill()` 计费核心 |
**真伪判读(源码亲核)**
- 真实部分:计费核心 `bill()` = slot 校验→合规闸门→(traceId,eventType) 幂等先查+DuplicateKeyException 并发兜底→gameId 经 ProjectApi 反查创作者归因→落 `game_ad_revenue` 台账settle_status=0statDate=今日——AdRevenueServiceImpl.java:108-171。结算回标幂等 0→1同文件 179-188
- 桩部分:
- **计价 mock**:唯一 provider 是 `MockAdProvider``calcRevenue = ecpmFloor/1000` 整除MockAdProvider.java:29-35`verifyReward()` 恒 true同文件 38-41工厂对未注册 providercsj/gdt一律降级 mockAdProviderFactory.java:41-44
- **合规桩**`isMinor()` 恒 false、`currentSessionCount()` 恒 0AdComplianceChecker.java:60-75注释自述「MVP 对接点」)。
- **前端断链(亲核)**game-studio 无 `src/api/ad.ts`api 目录仅 aigc/feed/project/runtime/telemetry宿主侧广告是桩弹层——GamePlayer.vue:12「ad/pay 桩弹层:点击模拟激励视频/支付,回调 rewarded:true」、:315-336 模拟看完直接回 `rewarded:true`**不调 `/ad/report/*` 也不拉 `/ad/slot/list-enabled`**。即后端计费 API 真实可用但当前无任何调用方。
### 3.2 收益链路game-module-trade
**端点烟测表**
| # | 路径 | 方法 | HTTP | code | 判定 | 证据 |
|---|---|---|---|---|---|---|
| 4 | `/app-api/trade/income/page` | GET | 200 | 0 | 真实0 数据) | 实测 `{"code":0,"data":{"total":0,"list":[]}}`;真实分页查 `game_trade_income`IncomeServiceImpl.java:94-96userId 边界强制) |
| 5 | `/app-api/trade/withdraw/page` | GET | 200 | 0 | 真实0 数据) | 实测同上结构WithdrawServiceImpl.java:161-163 |
| 6 | `/app-api/trade/withdraw/apply` | POSTamount=1 门槛探针,零写) | 200 | 1106002000 | 真实 | 精确命中 `TRADE_WITHDRAW_BELOW_MIN`门槛校验先于一切写入WithdrawServiceImpl.java:70-72Nacos `trade.withdraw-min` 默认 500 分),实证未写库 |
| 7 | `/app-api/trade/account/mine` | GET | 未实测 | — | 真实(代码判读) | **有写副作用故未实测**首查即建零值账户AccountServiceImpl.java:33-58 getOrInitAccount为守住「不写库」纪律跳过同 controller 其余端点已证路由与鉴权通 |
**真伪判读(源码亲核)**
- 真实部分:
- 账户原子账本:余额增减全部下沉行级 UPDATE`SET balance=balance±? WHERE balance>=?`0 行=余额不足防超扣AccountServiceImpl.java 头注释 17-21 + freeze 72-78
- 提现状态机insert(uk_biz_no 幂等)+freeze 同事务、审核 CAS 流转防二次发钱/退款WithdrawServiceImpl.java:66-106、109-158
- 分成结算T+1 拉 ad 未结算台账→逐笔 `uk_source` 幂等入账net=gross×Nacos `trade.creator-share` 默认 0.80BigDecimal 向下取整)→先入账后回标+补偿SettlementServiceImpl.java:54-89IncomeServiceImpl.java:40-91
- 桩/休眠部分:
- **打款 mock**:审核通过即 1→2「已打款」纯状态翻转channel=`mock`无真实支付渠道WithdrawServiceImpl.java:44-45、126-135
- **结算调度休眠**:唯一触发器是 XXL-Job `tradeSettlementJob`SettlementJob.java:39admin 控制器无手动结算端点TradeAdminController 仅 withdraw/audit/income/report 四端点grep 实证);而 staging `xxl.job.enabled: false`application-staging.yaml:90-92且 docker 仅 mysql+redis 两容器(实测 `docker ps`)→ **即使广告计了费,钱也永远到不了创作者账户**
- **前端无入口**game-studio 无 `src/api/trade.ts`,无收益/提现页面。
### 3.3 分享链路game-module-feed · share
**端点烟测表**
| # | 路径 | 方法 | HTTP | code | 判定 | 证据 |
|---|---|---|---|---|---|---|
| 8 | `/app-api/feed/share/9001?channel=wechat` | GET | 200 | 0 | 部分真实 | 实测 `data={gameId:9001, shareUrl:"https://wanxiang.ai/s/9001?utm_source=wechat", ogTitle:"", ogImage:"", ogDescription:"", channel:"wechat", versionId:9001}` —— OG 三字段空串是**桩的活体证据** |
| 9 | `/app-api/feed/share/999999` | GET未发布探针 | 200 | 1103002001 | 真实 | 精确命中 `FEED_SHARE_GAME_NOT_PUBLISHED`,发布门禁生效 |
**真伪判读(源码亲核)**
- 真实部分:发布门禁经 ProjectApi 读 status 仅 PUBLISHED(4) 放行FeedServiceImpl.java:477-482utm_source 渠道归因拼接(:462-466versionId 经 ProjectApi 回填供落地页直达即玩(:261-264、278-284
- 桩部分:`ogTitle/ogImage/ogDescription` 写死空串TODO 待对接 project 本体元信息FeedServiceImpl.java:257-260分享域名写死占位 `https://wanxiang.ai/s/`TODO 待 Nacos 化(:463-464该域名可达性/备案未验证。
- 前端入口已接线game-studio `src/api/feed.ts:73-79` getShareMeta + `src/views/share/Share.vue`),属 B2 已跑通的前端面。
- 与 B2 的关系B2 实证的是「share **遥测事件** → share_count → quality_score」本链路是「分享**落地页元数据**生成」,两者独立、互不替代。
### 3.4 互动链路game-module-feed · interact telemetry 口径)
**端点烟测表**
| # | 路径 | 方法 | HTTP | code | 判定 | 证据 |
|---|---|---|---|---|---|---|
| 10 | `/app-api/feed/interact` | POSTaction=99 非法探针,零写) | 200 | 1103001000 | 部分真实 | 精确命中 `FEED_INTERACT_ACTION_INVALID`校验先于写入FeedServiceImpl.java:195-198链路活且实证未写库interact_log 测后仍 0 |
| 11 | `/app-api/telemetry/events/batch` | POSTb4smoke- like+share 各 1 条,任务豁免写入) | 200 | 0 | **已证** | 实测 `{"code":0,"data":{"accepted":2,"rejected":0}}`;落库核验:`game_telemetry_event` 两行 process_status=1`game_telemetry_game_stat` gameId=9002 当日 like_count=1、share_count=1 —— B2 链路复证成功 |
**真伪判读(源码亲核)**
- 真实部分interact = 动作枚举校验1 赞 2 藏 3 享 4 报FeedActionEnum.java:22-25→ 幂等 upsert `game_feed_interact_log`(命中唯一键翻转 active可取消语义正确→ 聚合计数回显FeedServiceImpl.java:193-241。前端已接线`src/api/feed.ts:60-65` + `src/components/InteractBar.vue`
- 桩/缺失部分:
- **未接排序权重**`FeedInteractLogMapper` 仅 feed 模块内部使用(全仓 grep 实证,消费方只有 FeedServiceImpl/FeedConvertcontroller 宣称「点赞/收藏/分享/举报 → 排序权重」AppFeedController.java:64**名不副实**——排序的 like/share 权重实际来自 telemetry 事件聚合回灌EventIngestServiceImpl.java:185-194 计数 → :150-162 QUALITY_REFRESH 回灌 feed_rank
- 举报转 compliance = 占位日志FeedServiceImpl.java:227-232TODO 事务内禁远程调用,待 MQ/Feign
- 匿名互动 anon_id = 空串 TODO:207feed 流互动态 liked/favorited 回显恒 false:118 TODO + FeedConvert.java:38
- 「已证」的边界说明B2 已实证 + 本次 b4smoke 复证的是 **telemetry 路径**like/share 事件 → game_stat 计数 → quality_score → feed_rank.sort_score 重排);而 **interact 路径**(按钮点击 → interact_log → 计数回显落库真实但只到「回显」为止不参与排序。staging `game_feed_interact_log`=0 行也佐证 B2 实玩未触发过 interact 写入。
---
## 4. 缺口清单MVP 上线前各链路还缺什么)
**广告(上线即赚钱的硬前提全缺)**
1. 前后端断链game-studio 无 ad API 接线,宿主桩弹层自回调 rewarded:true不拉广告位、不上报计费 → 后端台账永远 0。
2. 无真实广告联盟 SPI穿山甲/优量汇MockAdProvider 计价=ecpmFloor/1000、激励校验直通——真实接入还有联盟审核闸门日历闸门
3. 广告位运营数据为零Flyway 无种子、staging ad_slot=0需 admin 端配置流程跑一遍。
4. 未成年识别、单会话频控均为恒放行桩(合规风险,上线前必须接真实信号)。
**收益(钱的管道有管无水)**
5. T+1 结算调度在 staging 关闭xxl.job.enabled=false 且无 xxl-job-admin 容器),且无手动触发端点 → 广告收入到创作者账户的链路从未端到端跑通过一次。
6. 打款是 mock 状态机,未接微信/支付宝企业付款(涉及支付资质日历闸门)。
7. 前端无收益/提现页(无 trade.ts创作者「看见钱」的入口缺失。
8. `/trade/account/mine` 首查建账的写副作用本次未实测,待一次受控验证。
**分享(能分享但分享卡片是白板)**
9. OG 标题/封面/描述空串 → 微信/QQ 分享卡片无图无题,传播转化必伤;需对接 project 元信息。
10. 分享域名写死占位 `https://wanxiang.ai/s/`,未 Nacos 化,域名可达性/备案未验证。
**互动(信号进了库但不进排序)**
11. interact 信号未接入排序权重,与 controller 文档宣称不符需决策要么接通interact→telemetry 事件或直刷 rank要么改文档口径承认排序只认 telemetry。
12. 举报→compliance 受理链路未接(占位日志),举报功能存在合规缺口。
13. feed 流互动态回显恒 false用户刷新后看不到自己点过赞/收藏,体验断点。
14. 匿名互动 anon_id 未透传(未登录用户互动会归到 userId=0
---
## 5. 烟测覆盖与局限
- 覆盖11 个探测中 10 个实测4 GET + 5 POST + 1 落库核验1 个因写副作用主动跳过(标注于 §3.2 #7)。
- 局限:错误路径只探了首个闸门(如 ad 探针停在 slot 校验,未实测归因失败/会话超限分支——已由源码判读补位admin 侧端点withdraw/audit、slot 配置)未实测(需 admin 会话且涉写库)。
## 6. 测试残留物(可清理)
仅 2 条 telemetry 事件 + 1 行当日聚合增量gameId=90022026-06-10 行 like_count/share_count 各 +1
```sql
-- 清理(如需):
DELETE FROM `ruoyi-vue-pro`.game_telemetry_event WHERE event_id LIKE 'b4smoke-%';
-- 聚合行修正(或整行删除当日 9002 行,下次事件会重建):
UPDATE `ruoyi-vue-pro`.game_telemetry_game_stat SET like_count=like_count-1, share_count=share_count-1
WHERE game_id=9002 AND stat_date='2026-06-10';
```
其余六张链路表ad_slot/ad_revenue/trade_account/trade_income/trade_withdraw/interact_log测前测后均为 0 行,零污染。