contract-first 基座(B1 step①,编译验证待 mini-desktop,与 step② 合并后编译): - feed-api: FeedApi.upsertRank + FeedRankUpsertReqDTO(UpsertMode 分流) + ApiConstants - runtime-api: RuntimePackageApi.publish + ApiConstants - project-api: ProjectVersionApi.createForPackage + DTO + 错误码 PROJECT_PUBLISH_PACKAGE_NOT_READY - V10: game_runtime_package.package_json + game_telemetry_event.event_id/uk_event_id(替换 uk_dedup);仅 contracts 源 + yudao-server 单一执行副本(守门②) - 契约 yaml: events/telemetry 信封加 eventId + runtime /manifest 端点(原样 JSON 不包 CommonResult) - pom: project-server→feed/runtime-api、telemetry-server→feed-api(守门④无环已核) 主 agent 独立核验: V10 双副本一致 / uk_dedup 索引名 / 错误码无碰撞 / 守门①②④ / telemetry x-mq 幂等口径同步改 eventId 避免契约自相矛盾 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
73 lines
5.4 KiB
JSON
73 lines
5.4 KiB
JSON
{
|
||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||
"$id": "https://wanxiang.ai/contracts/events.schema.json",
|
||
"title": "TelemetryEvents",
|
||
"description": "造梦AI 遥测事件契约 v1(契约 #5,owner=WS5)。前端批量上报 / SDK 上报 → /app-api/telemetry/events/batch → MQ 异步入库 → qualityScore → feed 排序(数据回路闭环)。每事件带 schemaVersion;新增字段给默认值、老消费者忽略未知字段;不兼容变更用新事件名。【Wave3 GAP-4 评审记录】利用无生产数据 + MQ 未实现窗口,一次性把信封 envelope/user 由 snake_case 统一为 camelCase(与 telemetry.yaml 及前端 SDK 对齐),保持 additionalProperties:false;豁免本文件 README §2『不兼容变更用新事件名并行』规则(本次改的是信封字段命名而非事件名),已确认仓外无 snake_case 消费者(telemetry.yaml/sdk-interface.d.ts/game-studio 均为 camelCase)。",
|
||
"type": "object",
|
||
"required": ["envelope", "eventRegistry"],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"envelope": {
|
||
"description": "事件信封(所有事件共用)。批量上报时为 { batch: Envelope[] }。",
|
||
"type": "object",
|
||
"required": ["event", "schemaVersion", "ts", "traceId", "eventId"],
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"event": { "description": "事件名(见 eventRegistry 键)", "type": "string" },
|
||
"schemaVersion": { "description": "事件 Schema 版本,如 v1 / v2", "type": "string", "pattern": "^v[0-9]+$" },
|
||
"ts": { "description": "事件发生时间戳(毫秒)", "type": "integer" },
|
||
"traceId": { "description": "全链路追踪 ID,贯穿生成→编译→加载→运行→上报", "type": "string" },
|
||
"eventId": { "description": "事件实例 UUID(每事件实例唯一,幂等真身)。前端 crypto.randomUUID() 生成;服务端落 game_telemetry_event.event_id(uk_event_id 唯一键),重放同 eventId 不重复计数。", "type": "string" },
|
||
"sessionId": { "description": "会话 ID(一次游戏流消费/一次创作会话)", "type": "string" },
|
||
"user": {
|
||
"description": "用户标识。匿名玩家用 anonId;登录后带 userId。",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"userId": { "type": "string" },
|
||
"anonId": { "description": "匿名 token 派生的稳定匿名 ID", "type": "string" }
|
||
}
|
||
},
|
||
"context": {
|
||
"description": "上下文",
|
||
"type": "object",
|
||
"additionalProperties": true,
|
||
"properties": {
|
||
"gameId": { "type": "string" },
|
||
"versionId": { "type": "string" },
|
||
"channel": { "description": "渠道归因(utm/channel 解析)", "type": "string" },
|
||
"deviceType": { "type": "string", "enum": ["mobile", "desktop", "miniapp"] }
|
||
}
|
||
},
|
||
"props": { "description": "事件私有字段(结构见对应 eventRegistry 项)", "type": "object" }
|
||
}
|
||
},
|
||
"eventRegistry": {
|
||
"description": "v1 核心事件登记表。值为该事件 props 的字段说明。覆盖:创作漏斗 / 消费漏斗 / 互动 / 广告 / 变现 / 性能。",
|
||
"type": "object",
|
||
"additionalProperties": false,
|
||
"properties": {
|
||
"create_start": { "description": "创作会话开始", "type": "object" },
|
||
"generate_submit": { "description": "提交生成。props: template_id, prompt_hash", "type": "object" },
|
||
"generate_succeeded": { "description": "生成成功。props: task_id, duration_ms(用于 ≥80% 成功率统计)", "type": "object" },
|
||
"generate_failed": { "description": "生成失败。props: task_id, reason_code(失败原因分类)", "type": "object" },
|
||
"preview_play": { "description": "预览试玩", "type": "object" },
|
||
"publish_submit": { "description": "提交发布审核", "type": "object" },
|
||
"feed_view": { "description": "进入游戏流", "type": "object" },
|
||
"game_impression": { "description": "游戏卡片曝光(首屏封面)。feed 排序信号", "type": "object" },
|
||
"game_load_failed": { "description": "加载失败(超时5s跳过触发)。props: reason。降权信号", "type": "object" },
|
||
"game_play_start": { "description": "试玩开始", "type": "object" },
|
||
"game_play_end": { "description": "试玩结束。props: duration_ms, completed(完玩)。quality_score 输入", "type": "object" },
|
||
"like": { "description": "点赞", "type": "object" },
|
||
"favorite": { "description": "收藏", "type": "object" },
|
||
"share": { "description": "分享", "type": "object" },
|
||
"report": { "description": "举报。props: reason。举报阈值降权信号", "type": "object" },
|
||
"ad_impression": { "description": "广告展示上报。props: slot_id, provider", "type": "object" },
|
||
"ad_reward": { "description": "激励视频完成。props: slot_id", "type": "object" },
|
||
"income_settled": { "description": "收益归集(T+1)。props: amount, source", "type": "object" },
|
||
"perf_first_screen": { "description": "首屏加载耗时埋点(P75<3s 验收)。props: ms", "type": "object" }
|
||
}
|
||
}
|
||
}
|
||
}
|