Merge remote-tracking branch 'origin/master' into feat/smart-paste
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m10s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m30s
Project CI / Backend tests (pull_request) Successful in 4m43s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 8m16s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m10s
Project CI / Frontend tests (pull_request) Successful in 2m23s
Project CI / Native shell tests (pull_request) Successful in 7m2s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m10s
Project CI / Repository checks (pull_request) Successful in 2m49s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m10s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m30s
Project CI / Backend tests (pull_request) Successful in 4m43s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 8m16s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m10s
Project CI / Frontend tests (pull_request) Successful in 2m23s
Project CI / Native shell tests (pull_request) Successful in 7m2s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m10s
Project CI / Repository checks (pull_request) Successful in 2m49s
# Conflicts: # docs/project-memory/shared-memory/decision-log.md
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
|
||||
## AI 游戏创作与 Agent Runtime
|
||||
|
||||
- [客户端本地埋点与主站入库契约](./technical/【技术方案】客户端本地埋点与主站入库契约-2026-09-21.md):本地 12 类事件采集、每 15 分钟上传、私有事件表、确认后清理与后台明细查询已完成隔离环境验收;不扩充采集范围、不做加密,未部署生产。配置要求及验证边界见第 13 节。
|
||||
|
||||
- [AGC 资源 kind 枚举化契约](./technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md#2026-09-15-gamecreationapp-资源-kind-枚举化当前权威口径):GameCreationApp 资源 kind 的 Rust enum、ts-rs 绑定、Unknown 可观测性和 shell 内重构边界。
|
||||
|
||||
- [策划 Agent 生产迁移与工作区浏览](./technical/【技术方案】策划Agent生产迁移与工作区浏览-2026-09-10.md):已完成;当前策划入口统一使用 Design Agent,采用阶段审批与用户工作区文件浏览。旧 V1/V2 会话、命令、专用展示和测试不再作为兼容目标。
|
||||
|
||||
@@ -116,6 +116,11 @@
|
||||
- 发布入口灰度下发:`GET /api/runtime/frontend-config` 新增 `gameDistributionPublishEnabled`,复用既有 `is_game_distribution_publish_enabled_for_user`(未配置 `game-distribution:publish` 或 `enabled=false` 时对已登录作者默认开放,显式收紧后只放行白名单/灰度命中,匿名恒为 false),避免前端入口与写入口出现两套判据。网页端 `PlatformEntryActiveFlowShell` 据此隐藏「发布游戏 / 发布新版本」入口,`/games/publish` 直接访问时渲染「发布功能正在灰度中」并提供重新检查;AGC 端 `readGamePublishAvailability` 同样读该字段,只有命中才把发布回调交给 DirectProject 聊天头。
|
||||
- 灰度验证:`cargo test -p api-server frontend_runtime_config`(6 passed,含新增的 `frontend_runtime_config_game_distribution_publish_is_scoped_to_authenticated_gate`:无 gate 行 → 登录作者 true/匿名 false;`enabled=true` 无白名单 → false;白名单命中 → true;`deny_user_ids` → false;`enabled=false` → true;`rolloutPercent=100` → true)、网页发布页 15 用例(含灰度未命中隐藏表单与「重新检查」放行)、平台壳 18 用例(含广场入口按灰度隐藏/显示)、AGC 发布服务 6 用例(含字段缺失与读取失败按不开放处理)。
|
||||
|
||||
- Phaser 一键发布闭环(作者不构建、不打 ZIP):`export_local_project_package` 改为发布前构建——已有可玩入口直接打包,否则解析 `game/` 或项目根的 npm `build` 脚本(`resolve_publish_build_plan`),缺 `game/node_modules` 时先跑 `project.bootstrap`,再走 `project.verify` 的受控 npm 运行器执行 build,最后校验入口并打包;构建或安装失败返回带日志尾部的可操作错误。真实 Phaser 4.2.1 + Vite 7 工程验证:构建产物使用相对引用(`./assets/...`),ZIP 370,969 B 经真实素材直传 + 创建游戏/版本/上传/送审/审核通过后,发行网关 `index.html` 200(323 B)与 `assets/index-DZGg_tPs.js` 200(1,388,719 B),网页播放页在 `allow-scripts` 沙箱 iframe 内渲染出 `PHASER-PUBLISH-OK` 与可点击按钮。
|
||||
- 发行网关根路径:`GET /api/game-distribution/releases/{gameId}` 与带尾斜杠的同一路径等价于 `index.html`(生产由每游戏 origin 映射根路径,本地直连网关或入口直接填网关地址时同样可玩);路由级用例覆盖 Cookie 拒绝门与根路径。
|
||||
|
||||
- 发布灰度改为**默认关闭**并修掉客户端“看得到点不动”:`is_game_distribution_publish_enabled_for_user` 现在要求 gate 行存在且 `enabled=true`(未登录、无行、`enabled=false` 一律 false),因此没配灰度时 `gameDistributionPublishEnabled=false`,AGC 不再渲染「发布到游戏广场」按钮、网页入口也不出现;AGC 侧新增 `announcePublishMessage`,把「已构建并打包试玩包」「先打开一个项目再发布」等提示通过 DirectProject 聊天容器的 `announce` 出口回话(普通项目不渲染工作台状态行,之前只写 workspaceStatus 才会表现为点击无反应)。后台「灰度发布配置」新增「可配置开关」列表:预设开关在未创建行时也可见并可一键配置(不再需要先猜 gate key)。
|
||||
|
||||
## 尚未完成
|
||||
|
||||
- 真实独立发行域名、通配 TLS 与 CDN 仍属部署侧:边缘模板与门禁已就绪,本地已用真实 nginx 验证按主机映射、Cookie 403 与命名空间隔离,但仍需在真实域名/证书下跑一次“审核通过 → 游玩 → 换版 → 下架”并确认 CDN TTL 不超过 60 秒窗口。
|
||||
|
||||
@@ -22,6 +22,54 @@
|
||||
- 未纳入本次:斜杠命令 `/` 解析、拖拽文本(drop)、附件 / 运行画面区域 / 文件路径 / URL / 剪贴板图片、复制侧 `text/plain` 形态调整、扩展安装卸载后的目录即时失效。
|
||||
- 验证方式:`buildContentFromPastedText` 规则矩阵单测(含「显示文本再粘贴回来得到同一份 content」这条逆运算)、provider 的 `fuzzyLookup` / `lookup` 用例、输入区集成用例(真 Lexical `paste` 事件 → 芯片、未命中等价于默认粘贴、Skill 冷启动保持字面且敲过 `$` 后可解析);另跑 `npm run typecheck`、`npm run check:encoding`、`npm run check:doc-index`、`git diff --check`。
|
||||
|
||||
## 2026-09-22 Direct 埋点与业务持久化锁隔离
|
||||
|
||||
- Direct 采集身份和最新成果编号改由独立纯内存状态保存,初始化时从最终执行账本冻结项目与原 run 身份;成果采集、预览采集上下文和终态成果读取不再争用业务落盘锁。
|
||||
- 内存锁释放后才投递事件,不等待文件 I/O、后台队列或网络,不新增用户报错。缺少 run 元数据不套用当前用户身份,恢复不补造历史成果;退出仍尽力封存,不增加退出等待。
|
||||
- 修正后台埋点查询 DTO 的分页注释:按 `(event_time, event_id)` 倒序,入库时间仅限制快照;接口和查询行为不变。
|
||||
|
||||
## 2026-09-22 新项目埋点资格支持有限恢复
|
||||
|
||||
- 真实创建成功先登记有界进程内待办,不依赖埋点服务或身份快照;后台服务就绪及后续真实受理可重试初始化资格。资格文件格式、每项目最多一次首次提交和上传合同不变。
|
||||
- 业务线程仅更新内存和非阻塞投递;资格文件读写和独立锁操作仍在后台,不向用户报错或要求介入。队列满、暂时 I/O 失败和锁竞争保留待办;已有标记、备份或项目身份不符不重新授予资格。
|
||||
- 内存最多 1024 项、路径与 ID 合计 1 MiB;超限或持久化前退出仍允许漏记,不补旧项目历史,不承诺零丢失。细节与验证见客户端埋点主规范。
|
||||
|
||||
## 2026-09-22 清理无调用方的 GUI 文件写入命令
|
||||
|
||||
- 确认 `write_local_project_file` 无现役前端或业务调用方后,删除命令、Tauri 注册及命令检查豁免;移除对应测试片段,保留 checkpoint、UI 保存和记忆写入的既有测试。
|
||||
- Agent 使用的底层 `write_local_project_file_at` 保留。GUI 人工文件写入不再列为采集入口;不扩充其他文件操作埋点,不修改已有事件数据合同。
|
||||
|
||||
## 2026-09-22 客户端埋点后台按发生时间排序
|
||||
|
||||
- 按技术负责人要求,列表改为 `(event_time, event_id)` 倒序,历史补传按发生时间归位。入库时间仍用于固定分页快照,翻页期间新入库的事件在刷新后显示。
|
||||
- 分页游标改存发生时间;旧游标刷新后重新取得,不迁移持久表、不新增索引、不改变采集与上传行为。
|
||||
|
||||
## 2026-09-22 埋点分支同步发布入口与工作台更新
|
||||
|
||||
- 合并 master `079466b29`,同时保留项目离开埋点与工作台运行通知、后台埋点查询与游戏发布审核入口;不扩大采集范围。
|
||||
- 本次冲突位于工作台相邻回调、后台 API 测试导入及本文件新增记录,均保留双方现役内容;Direct 聊天的认证重试埋点与 master 回合状态调整继续共存。
|
||||
|
||||
## 2026-09-22 埋点分支合并 DirectProject 聊天重构
|
||||
|
||||
- 保留 master 的独立 DirectProject 聊天控制器及 canonical `userItem` 合同;旧 Supervisor、独立 prompt/attachments IPC 参数和已退役删除命令不恢复。
|
||||
- 原有 Direct run 埋点从 App 聊天链迁至 `useDirectProjectChatController.runTurn`,认证重试仍逐次生成 attempt ID,并仅确认最后一次;账号代次变化时丢弃确认。项目进入/离开及用户预览的原有接线继续保留,不扩大采集范围。
|
||||
- 过期测试按现役聊天入口调整,新增实际 UI→controller 认证重试用例验证最终尝试确认。上传、数据库和后台合同不变。
|
||||
- 合并验证:Rust analytics 56 项通过(真实服务桥接用例维持 ignored),App 界面 203 项通过 / 13 项既有跳过;预览激活、版本切换、工作台清单及客户端埋点辅助测试通过,客户端 TypeScript、原生契约、编码、文档索引和 diff 检查通过。本次未重跑上传真实服务 smoke 或完整 GUI/Provider 创作。
|
||||
|
||||
## 2026-09-21 客户端埋点方案进入团队共享文档
|
||||
|
||||
- 本期验收完成:原始需求与已确认口径的 12 类事件入口已核对,同一 writer/session/project/goal 的宿主组件链路通过真实文件、HTTP、checkpoint 与 JSONL 关联验证;最终 51 项 Rust、46 项前端测试和类型/格式/文档检查通过。仅测试辅助模拟创建投递、run 结果和构建产物,不宣称完整 GUI/Provider 端到端验证;未提交或发布。禁止把全部资源操作逐项接线重新当作本期必做范围。
|
||||
- 最新口径:共 12 类启用事件;策划审批通过后实际进入下一阶段并成功持久化,复用 project_revision_created,revision_id=design:<session_id>:<target_phase>、source=design_agent、revision_source=agent、change_kind=design_document。同会话同目标阶段幂等;不严格校验文档版本/差异,阶段内文件修改不逐次采集,重开不补历史。不新增独立策划进度事件或审批、澄清状态字段。Direct 文件/补丁、UI 成果、预览与保存已有定向验收,基础事件入口已核对,同一宿主组件链路验收已通过。
|
||||
- 两类 Agent run 元数据随真实受理保存,后台维护项目累计观测重试与双 Agent 当前终态槽位;重放不新建,恢复保留原身份且耗时未知,取消/不确定不伪造失败。Direct 自动认证刷新只确认最后一次原生尝试的有界内存候选,账号代次变化丢弃;缺失不回退旧失败,不为观测增加业务写盘等待。运行结果已通过独立验收,真实付费 Provider/完整 GUI run 尚未 smoke,现有 Direct 合同中断恢复行为未改变。
|
||||
- Direct 宿主文件写入/正式补丁仅在已知成果内容变化且原事务 revision 成功提交后记成果,原 run 用户归属不变,末尾 projection 不重复记。当前 session 内存关联最新可信成果到 run;缺证据为 null,不据全局 fingerprint 推断作者。真实 writer、bundled patch 执行器和定向测试已通过。
|
||||
- GUI 人工文件写入命令已于 2026-09-22 清理,不再作为采集入口;完整项目 checkpoint 按真实 checkpoint_id 记保存。UI State 仅 Saved 记成果;手动 Saved/Unchanged 可记保存,自动保存仅 Saved,保存并生成需全操作成功。起点冻结身份,埋点失败不影响业务。63 项 Rust、41 项前端测试及独立验收通过;无完整 GUI 跨层保存 smoke。旧 Runtime 开发/CLI 文件及 UI workflow 不因存在代码就纳入正式 GUI 必需采集。
|
||||
- 正式 Web preview_ready 由 GUI 用户持续预览和 Direct 临时浏览器预览接入,冻结原身份、版本与实例;异步2秒loopback GET禁代理/重定向,原入口及响应非空、版本/实例仍匹配才记录。实例停止/替换、验证结束或取消后丢弃迟到结果;可访问不等于JS/游戏验证成功。合并后78项Rust、104项前端测试及独立验收通过,未调用真实Provider或跑完整Chrome双端验证。资源操作全面接线计划已撤销;现有采集只表示已观测变化,不代表全部资源操作或项目全部修订。
|
||||
- 首次提交按本地观测口径每个新项目最多一条:真实受理候选在后台持久消费 `.agent/analytics-goal.json` 资格后投递。资格跨批次清理保留,旧项目不初始化;此前候选丢失时允许后续真实受理消费,使用后者自己的用户与时间,不宣称绝对首次。消费后事件丢失可零条,重放与恢复不补历史;不得为埋点扫描双 Agent 完整历史或阻塞业务写盘。
|
||||
|
||||
- 当前合同唯一维护入口为[客户端本地埋点与主站入库契约](../../technical/【技术方案】客户端本地埋点与主站入库契约-2026-09-21.md),原始需求作为仓库内历史来源保存;后续里程碑规范与实施计划放在 `docs/project-memory/plans/`。
|
||||
- 本地采集阶段已验收明文 JSONL 持久化;当前仍不做加密。一个项目对应一个目标,事件按业务节点采集,5 分钟封存,7 天或 20 MiB 清理;上传失败也受保留上限约束。
|
||||
- 当前上传实现已完成隔离环境验收,证据见同一主规范第 13 节:每 15 分钟上传匹配当前账号与平台的封存批次,新增一张客户端事件私有表、批次原子入库与幂等确认、成功清理及独立后台明细栏目;失败静默留待下周期重试。真实客户端文件、HTTP、数据库与后台查询已关联同一事件验证,浏览器列表/筛选/详情通过;未部署生产。保持原 12 类事件和原采集边界。上线须配置 `GENARRATIVE_AGC_ANALYTICS_ORIGIN`,按数据库、API/后台、客户端顺序发布。
|
||||
- 已按技术负责人授权开始实施:合同与本地队列、会话窗口与项目接入、策划阶段成果、首次提交及两类 Agent run 已实现并经独立审查;定向测试、生产编译和前序 GUI 启停证据统一见主规范第 12 节。不得宣称完整产品采集已上线。
|
||||
## 2026-09-22 引用输入区改为宿主注入引用 provider,选择器面板与输入区分离
|
||||
|
||||
- 背景:`ResourceReferenceInput`(`apps/ai-game-creator-shell/src/features/project-workspace/ResourceReferenceInput.tsx`)同时承担「拿数据」与「编辑数据」:素材以未过滤 manifest 传入后由组件自己派生候选、显示名与「当前版本素材」scope,Skill 候选由组件自己 invoke `list_agc_skill_catalog` 与 `list_client_extensions`(只在用户敲出 `$` 时触发),素材选择面板与缩略图预览 invoke 也住在组件内部。后果是 5 个宿主(DirectProject 聊天、策划输入盒、画布生成面板、资源卡快速编辑、测试夹具)无差别获得 `$` Skill 候选,而只有 DirectProject 回合会把 `agc_skill_reference` 解析成真 Skill(Rust `direct_codex_user_item_to_codex_turn_input`,`apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_user_item/wire.rs`),其余宿主只把它退化成字面文本,形成误导入口。
|
||||
@@ -819,6 +867,15 @@ Godot 编辑器操控复用既有 AGC 插件宿主、EditorAdapter、Runner 和
|
||||
- 验证方式:运行评论弹层恢复竞态回归、完整 `appSurface.test.ts`,并执行类型、编码和 diff 检查。
|
||||
- 关联文档:`docs/technical/【技术方案】立项策划Agent(Fast GDD)-2026-08-10.md`、`apps/ai-game-creator-shell/src/features/project-workspace/GddApprovalCard.tsx`。
|
||||
|
||||
## 2026-09-22 旧创作模板历史表从 schema 与生成绑定中删除
|
||||
|
||||
- 背景:旧创作模板的 63 张历史玩法表已经完成业务代码退役;release 在 2026-09-22 apply 前仍有 26 张表、5922 行历史数据。维护窗口内先完成可恢复备份,再执行固定清单清空,继续保留 table 定义、迁移白名单、旧行兼容分支和生成绑定会让当前 schema、客户端类型和迁移合同长期停留在退役状态。
|
||||
- 决策:从 `spacetime-module` 可达源码删除旧 gameplay、自定义世界、Puzzle / Puzzle Clear、Bark Battle、Match3D、Jump Hop、Wooden Fish、Square Hole、Visual Novel 与 Big Fish 的 63 张表定义及专属类型;同步删除只服务这些表的 `clear_retired_database_tables` procedure、固定清单、migration 导入导出项和旧行归一化分支,并重新生成 `spacetime-client` bindings。`runtime_setting`、`runtime_snapshot`、`user_browse_history`、`creation_entry_config` 等现役表和通用迁移能力保持不变。
|
||||
- 门禁处理:SpacetimeDB schema guard 只对本轮 63 个已确认 accessor 的从基线删除放行,其他表删除/改名以及字段级破坏性变更仍失败;该一次性白名单在删除结果进入后续主线基线后移除。生产发布仍必须单独完成冷备份、客户端兼容性和运行态确认,禁止用 SQL `DROP TABLE`、`--delete-data=always` 或系统表写入代替受控发布。
|
||||
- 影响范围:`server-rs/crates/spacetime-module/src/{active.rs,migration.rs}`、旧表专属 module/legacy schema 文件、`server-rs/crates/spacetime-client/src/module_bindings*`、schema guard 及后端数据契约。
|
||||
- 生产数据与发布闭环:`genarrative-prod` 在维护态、API/controller/worker 已停止时,以已授权 migration operator 执行 `clear_retired_database_tables`;apply 返回 63 张表且每张 `cleared_row_count == row_count_before`,共清空 5922 行。apply 前后两次 `dry_run=true` 均为 63/63 全零,第二次在 10 分钟观察窗口结束后执行。清空前完成 files-minimal OSS 备份、latest/catalog 验真和 restore dry-run;随后将 release 从 `2.7.0` 直接切换到本地锁定并有 commit 校验的 `2.8.3 / 8e410d…` 二进制,再用 source commit `05a5ea4d8534b3f96d4d462c6cfda9b0775073df` 的 wasm 发布。发布后 schema 为 84 张表、旧表为 0、`clear_retired_database_tables` 为 0;API/controller/worker 已恢复,维护退出,`genarrative.world` 与 `www.genarrative.world` 返回 200。
|
||||
- 验证方式:`npm run spacetime:generate` 生成 766 个 binding 文件;`cargo check -p spacetime-client -p api-server`、`cargo test -p spacetime-module migration`(21 passed)、`npm run check:server-rs-ddd`、`npm run check:spacetime-schema`(84 tables)、`npm run check:spacetime-runtime-access`、schema guard 单测(9 passed)、`npm run check:encoding`、`npm run check:doc-index` 与 `git diff --check` 通过。
|
||||
|
||||
## 2026-09-02 旧玩法表采用两阶段退役清理
|
||||
|
||||
- 背景:旧创作模板的业务代码已退出现役编译链,但 SpacetimeDB 中的历史表仍需先完成数据清理;直接删除表定义会扩大 schema 迁移和客户端兼容风险。
|
||||
|
||||
@@ -96,6 +96,14 @@ SpacetimeDB 任务统一先读取 `.codex/skills/genarrative-spacetimedb/SKILL.m
|
||||
|
||||
## Gitea CI 依赖闭合
|
||||
|
||||
缓存维护下载必须核对 artifact 元数据大小与实际响应,并立即检查 ZIP 完整性;有长度上限不等于能检测短读。网络或归档损坏最多重试 3 次且重新取签名链接。sccache 同 key 的不同 ZIP 成员排列会改变整个对象 SHA;新增对象去重仅在成员内容 SHA、权限和 ZIP 元数据均一致时接受排列差异,真实内容及继承对象冲突仍拒绝。禁止通过任取一份冲突对象绕过完整性契约。
|
||||
|
||||
Buildx 0.30.1 的 `inspect` 不支持 `--format`,builder 驱动校验读取普通输出的 `Driver:` 字段。相关命令须在宿主真实插件上验证;测试替身应拒绝不支持的参数,避免把模拟命令成功误当兼容性证据。
|
||||
|
||||
BuildKit 会把 Dockerfile 中的裸 `FROM sha256:<Image ID>` 当作远程镜像名;快照组装须在维护锁内把可信基础 Image ID 绑定到专用临时 tag,并显式使用能读取宿主镜像的 `default` Docker builder。成功或失败后去 tag,元数据和 runner 仍固定完整 Image ID;不要复用受管 `base_tag` 给历史基础镜像打别名,以免改变自动清理归属。
|
||||
|
||||
Gitea 基础镜像通过专用 `genarrative-ci-images` Buildx builder 持久复用 Cargo/npm 下载缓存;稳定 cache mount 与 commit、lock 哈希无关,以 `sharing=locked` 隔离并发写入,仅供可信宿主构建、不开放给 PR。最终镜像显式物化当前依赖下载快照,仍不包含 node_modules/target 或上一版 sccache 层。首次可用 `seed-downloads` 从可信完整 Image ID 提取包缓存,操作账号须与维护服务一致;部署要求及 builder GC 空间目标见 `deploy/container/README.md`。构建上下文必须覆盖 AGC vendor 与编辑器 bridge 的全部本地 path manifest,普通源码变化不应使依赖层失效。维护 journal 提供阶段耗时和失败 build.log 定位。
|
||||
|
||||
Gitea Rust 缓存自动维护由宿主 `genarrative-ci-cache.timer` 收集同一 master push run 六个 Rust job 的原生 V4 缓存产物,不重复执行 Cargo 预热。只传本轮新 key,命中对象只传使用时间;宿主与真实来源镜像对象合并、去重、按新近使用时间裁剪到 4 GiB,从无对象缓存基础镜像重新组装。源 run 不要求全绿,但取消、缺组、旧 attempt、未完成上传或混用来源镜像不得采用。网关暂停新 FetchTask、在途领取结束、持久化任务账本清空且内层活动容器为空才切换,不打断运行中的 CI。首次接入/升级网关需空闲窗口;Token 只需普通仓库 `write:repository`,不查管理员 API。候选装载后清理已收集 artifact,遗留项保留 7 天;真实 master CI 验证后才清理旧镜像,保留当前、一个回滚版、基础镜像及容器引用。部署入口见 `deploy/container/README.md`,合并代码不等于服务启用。
|
||||
|
||||
修改 Gitea workflow 的 job 显示名称、ID 或缓存导出组时,必须同步维护器的 `JOBS` / `RUST_JOB_IDS`;`test_gitea_cache_maintenance.py` 直接对照实际 workflow 检查全集和导出映射,避免自动刷新或镜像验收因名单漂移长期等待。维护器 `Api.request` 的 `method` 是必填关键字参数,GET 也必须显式指定,不根据 body 推断请求方法。
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
按上游 [#5555](https://github.com/clockworklabs/SpacetimeDB/pull/5555) 的 retention 语义,只有最近 `retain-snapshots`(默认 2)份 snapshot 与覆盖它之后的 commitlog 段是重启所需,其余历史可丢;因此备份改为 `files + full + --minimal --retain-snapshots 2`(release 实测 40G → 3.6G,热备不停服),不再做增量差异计算,也不需要 44.7G 冷备空间。
|
||||
|
||||
2026-09-22 的 release 清表窗口再次验证:41.2GiB 数据目录执行 `archive` 会因根盘不足失败;尝试非 minimal 的 `files + full + --stop-service` 虽通过空间预检,但在扫描 43GiB 后于 catalog 序列化阶段报 `RangeError: Invalid string length`。生产中等数据目录继续使用可验真的 `files + full + --minimal` 备份,并在 apply 前执行 `restore-files-state --dry-run`;非 minimal files 大库备份需要先修复 catalog 序列化上限,不能把失败备份当作通过。
|
||||
|
||||
## copyArtifacts 报「Unable to find project for artifact copy」的用户触发构建差异
|
||||
|
||||
Copy Artifact 插件在**非 SYSTEM 认证**下按「认证用户」判权:只有当被复制 Job 的 `CopyArtifactPermissionProperty`(仓库里由 Declarative 的 `copyArtifactPermission(...)` 维护)显式列出当前消费者,或者该 Job 对认证用户开放 Item.Read 时才放行;`ACL.SYSTEM2` 的定时构建会短路通过。因此会出现「定时调度一路成功、手动发布必挂」的现象(2026-09-21 手动发布 #6/#7 与同期的用户触发探测全部命中,定时调度 #104+ 正常)。`Genarrative-Agc-Global-Version-Issue` 生产权限模式的授权名单必须同时包含 `Genarrative-Scheduled-Revision-Trigger` 与 `Genarrative-Manual-Build-And-Deploy`;改完 `copyArtifactPermission` 后要先跑一次发号 Job 把 Job property 写回 Jenkins,只改仓库文件不生效。
|
||||
@@ -1121,7 +1123,7 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
|
||||
- 现象:画板生成按钮显示 `N泥点`,后端也能按模型配置计算出价格,但用户点击后钱包余额不变。
|
||||
- 原因:前端展示价和后端价格计算只证明价格能被展示 / 解析;如果 handler 没有包进 `execute_billable_asset_operation_with_cost`,或异步音频发布目标没有携带本次模型价格,外部 provider 仍会被调用但不会真实扣费。
|
||||
- 处理:新增或改造编辑器外部生成入口时,确认前端请求不携带 `priceMudPoints`,后端按运行时模型定价重新计算价格,并用该价格进入资产扣费 wrapper。音频提交 / 发布分离时,把后端计算出的价格写入 `AudioAssetBindingTarget.billing_points_cost`。
|
||||
- 验证:结构性测试覆盖对应 handler 包含 `execute_billable_asset_operation_with_cost` 和价格变量;音频测试覆盖 `resolve_creation_audio_points_cost` 优先读取 editor target 的 `billing_points_cost`。
|
||||
- 验证:结构性测试覆盖对应 handler 包含 `execute_billable_asset_operation_with_cost` 和价格变量;`worker_billing_context_freezes_charge_and_preserves_job_metadata` 与 `logged_in_background_music_queue_preparation_uses_canonical_prompt_and_frozen_price` 覆盖现役队列冻结价格,原子计费测试覆盖提交失败与结果未知时的退款边界。
|
||||
- 关联:`server-rs/crates/api-server/src/editor_project.rs`、`server-rs/crates/api-server/src/character_animation_assets.rs`、`server-rs/crates/api-server/src/vector_engine_audio_generation/`、`src/components/image-editor/ImageCanvasGenerationSubmissionModel.ts`。
|
||||
|
||||
## 本地 dev 启动日志先看成功锚点,不要把非阻断 warning 当失败
|
||||
|
||||
@@ -77,6 +77,7 @@ EditorGenerationResultPersistInput {
|
||||
|
||||
## api-server 接入
|
||||
|
||||
- 旧分段持久化、worker 独立完成及其重复结果序列化实现,在失去现役调用方后直接删除;不保留只供旧测试调用的生产副本。废弃实现的专属测试随实现删除,不因清理而将旧用例改接到现役函数;现有现役行为测试保持原有覆盖。手动拆分、上传等现役路径使用的底层 helper 继续保留,HTTP / DTO、inline 模式和历史任务解析兼容不受清理影响。
|
||||
- 通用持久化改为 `prepare -> build canvas candidate -> atomic commit`。prepare 阶段只生成稳定 ID、上传/验证对象和构造候选 DTO,不创建 resource/asset。
|
||||
- api-server 继续复用现有画布 completion / replacement 逻辑计算候选 `layers_json` 和 `expected_revision`;统一 procedure 在最终事务内重新执行既有 layout 校验和 CAS。
|
||||
- CAS 冲突只刷新当前 project、重新计算 layout 并重试 prepared commit;相同 operation、slot、对象和记录候选保持不变,禁止重跑 Provider。
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,431 @@
|
||||
> 文档状态:`historical`(原始需求存档,仅用于来源追溯,不作为当前实施依据)
|
||||
|
||||
归档日期:2026-09-21。下方保留原始正文;其中目标边界、异常会话、上传阶段等口径已由后续决策调整。当前合同见[客户端本地埋点与主站入库契约](./【技术方案】客户端本地埋点与主站入库契约-2026-09-21.md)。
|
||||
|
||||
# Game Agent 埋点设计方案|早期地基版 v1.0
|
||||
|
||||
状态:正式方案;待技术负责人拆解实施
|
||||
日期:2026-09-05
|
||||
适用产品:当前 Game Agent 桌面端编辑器 / 项目工作台
|
||||
|
||||
## 1. 方案目的
|
||||
|
||||
第一阶段不建设完整数据平台,也不一次性覆盖所有细粒度编辑动作。本方案只解决三个问题:
|
||||
|
||||
1. 能不能知道用户进入了编辑器、创建或打开了哪个项目。
|
||||
2. 能不能把一次创作任务和 Agent 执行、项目变化、预览结果串起来。
|
||||
3. 能不能判断用户是否回到同一个项目继续创作。
|
||||
|
||||
本版本新增**编辑器前台时长**。它表示编辑器窗口处于前台/获得焦点的累计时间,不等于用户持续操作,也不等于真实编辑时长。本版本仍不统计编辑器活跃编辑时长和单个项目完整创作时长。
|
||||
|
||||
核心分析对象从旧版的“浏览/消费行为”切换为当前产品的“持续创作行为”。
|
||||
|
||||
## 2. 当前用户路径
|
||||
|
||||
```text
|
||||
进入编辑器
|
||||
→ 创建项目 / 打开已有项目
|
||||
→ 提交一次创作任务
|
||||
→ Agent 执行
|
||||
→ 用户澄清、确认或追加指令
|
||||
→ 文件、代码或资源发生有效变化
|
||||
→ 项目产生 revision
|
||||
→ 预览就绪
|
||||
→ 用户试玩或继续修改
|
||||
→ 保存并退出
|
||||
→ 之后重新打开同一项目继续创作
|
||||
```
|
||||
|
||||
第一阶段不要求把 Asset Canvas、Resource Editor、UI Editor 的每一个点击都拆成独立事件;先通过项目、任务、运行、revision 和前台时长关系判断用户是否真的在使用创作工作台。
|
||||
|
||||
## 3. 第一阶段事件清单
|
||||
|
||||
| 事件 | 所在环节 | 触发条件 | 可回答的问题 |
|
||||
|---|---|---|---|
|
||||
| `editor_session_start` | 进入编辑器 | 编辑器启动并完成可用初始化 | 有多少编辑器会话、用户从哪里开始 |
|
||||
| `editor_session_end` | 离开编辑器 | 正常退出或明确关闭编辑器 | 正常结束的会话数;粗略会话时长 |
|
||||
| `session_timeout` | 异常离开 | 超过约定时间没有心跳或前台状态 | 哪些会话可能异常中断;不可替代真实退出 |
|
||||
| `editor_focus_start` | 进入前台 | 编辑器窗口获得焦点并处于可交互前台 | 用户把多少时间留在编辑器前台 |
|
||||
| `editor_focus_end` | 离开前台 | 编辑器失去焦点、最小化或退出 | 前台时长区间和累计前台时长 |
|
||||
| `project_create_success` | 创建项目 | 项目创建成功且拿到稳定 `project_id` | 创建项目人数、创建成功率 |
|
||||
| `project_open` | 打开项目 | 项目被成功加载并进入工作区 | 回访项目数、项目复访率 |
|
||||
| `creative_task_submit` | 发起创作 | 用户提交一次可执行的创作请求 | 用户发起了多少次真实创作任务 |
|
||||
| `agent_run_completed` | Agent 执行结束 | 一次 Agent run 正常完成 | Agent 任务完成率、耗时、重试情况 |
|
||||
| `agent_run_failed` | Agent 执行结束 | 一次 Agent run 明确失败 | 失败率、错误类型、失败后的修复行为 |
|
||||
| `project_revision_created` | 产生有效变化 | 项目产生可识别的新 revision | Agent 或人工操作是否真正改变了项目 |
|
||||
| `preview_ready` | 预览 | 当前项目预览达到可打开/可运行状态 | 有多少项目走到可预览;从任务到预览的转化 |
|
||||
| `project_save` | 保存 | 用户或系统完成一次项目保存 | 用户是否保存成果;保存与继续创作关系 |
|
||||
|
||||
说明:`project_revision_created` 是项目变化事件,不等于用户满意;`preview_ready` 是技术/产品中间成功,不等于用户完成试玩或认可结果。
|
||||
|
||||
## 4. 公共事件字段
|
||||
|
||||
每条正式产品事件使用统一 envelope。`properties` 只放该事件特有字段,不重复创造新的顶层 ID。
|
||||
|
||||
| 字段 | 类型 | 是否必填 | 字段说明 |
|
||||
|---|---|---:|---|
|
||||
| `event_id` | string | 是 | 单条事件唯一 ID,用于去重;建议 UUID |
|
||||
| `event_name` | string | 是 | 事件英文名,如 `creative_task_submit` |
|
||||
| `event_time` | datetime | 是 | 事件发生时间,统一 ISO 8601;不要只记录上传时间 |
|
||||
| `user_id` | string/null | 条件必填 | 稳定用户标识;没有登录用户时明确为空,不用设备 ID 冒充 |
|
||||
| `editor_session_id` | string | 是 | 一次编辑器打开到结束/超时的会话 ID |
|
||||
| `project_id` | string/null | 条件必填 | 当前项目的稳定 ID;编辑器入口事件可以为空 |
|
||||
| `creative_task_id` | string/null | 条件必填 | 一次用户创作任务的 ID;任务相关事件必须携带 |
|
||||
| `agent_run_id` | string/null | 条件必填 | 一次 Agent 执行的 ID;仅 Agent run 相关事件填写 |
|
||||
| `agent_turn_id` | string/null | 否 | Direct 的底层 turn 技术记录 ID;不能替代 `agent_run_id` |
|
||||
| `status` | string/null | 条件必填 | `success`、`failed`、`timeout`、`cancelled` 等有限枚举 |
|
||||
| `error_code` | string/null | 失败时必填 | 稳定错误码;不要把整段异常堆栈当作分析字段 |
|
||||
| `source` | string | 是 | 事件来源,如 `editor`、`supervisor`、`direct`、`asset_canvas`、`ui_editor`、`manual`、`system` |
|
||||
| `client_version` | string | 是 | 客户端/编辑器版本,用于按版本比较问题 |
|
||||
| `properties` | object | 是 | 事件专属属性;允许为空对象 |
|
||||
|
||||
### 4.1 ID 语义规则
|
||||
|
||||
- `editor_session_id`:编辑器会话,不能使用 Runtime 的 `sessionId`。
|
||||
- `creative_task_id`:用户的一次创作意图,可能包含多次 Agent run 和多轮追加指令。
|
||||
- `agent_run_id`:一次可独立判断成功/失败的 Agent 执行。Direct 需要单独生成,不能把 `clientTurnId` 直接当作 run ID。
|
||||
- `agent_turn_id`:底层技术 turn 记录,用于排错和技术审计,不直接作为产品任务口径。
|
||||
- `project_id`:项目身份,优先使用 manifest 中稳定的项目 ID,不使用路径作为长期主键。
|
||||
|
||||
## 5. 各事件最小字段
|
||||
|
||||
### 5.1 编辑器会话
|
||||
|
||||
`editor_session_start`:
|
||||
|
||||
```text
|
||||
entry_source
|
||||
first_project_id
|
||||
client_version
|
||||
```
|
||||
|
||||
`editor_session_end` / `session_timeout`:
|
||||
|
||||
```text
|
||||
end_reason
|
||||
session_duration_ms(若可可靠计算)
|
||||
last_project_id
|
||||
```
|
||||
|
||||
`editor_focus_start`:
|
||||
|
||||
```text
|
||||
focus_reason
|
||||
active_project_id
|
||||
```
|
||||
|
||||
`editor_focus_end`:
|
||||
|
||||
```text
|
||||
blur_reason
|
||||
focus_duration_ms(若可可靠计算)
|
||||
active_project_id
|
||||
```
|
||||
|
||||
前台时长计算规则:同一 `editor_session_id` 下,将成对的 `editor_focus_start` 与 `editor_focus_end` 区间相加。正常退出时补齐最后一个区间;崩溃、断电或强制结束造成的未闭合区间必须标记为不完整,不估算为完整前台时长。
|
||||
|
||||
### 5.2 项目
|
||||
|
||||
`project_create_success`:
|
||||
|
||||
```text
|
||||
project_template_id(如有)
|
||||
creation_source
|
||||
```
|
||||
|
||||
`project_open`:
|
||||
|
||||
```text
|
||||
open_source
|
||||
is_first_open
|
||||
```
|
||||
|
||||
`project_revision_created`:
|
||||
|
||||
```text
|
||||
revision_id
|
||||
revision_source
|
||||
change_kind
|
||||
files_changed_count(如可得)
|
||||
```
|
||||
|
||||
`project_save`:
|
||||
|
||||
```text
|
||||
save_source
|
||||
revision_id(如有)
|
||||
```
|
||||
|
||||
`revision_source` 建议至少使用:`agent`、`asset_canvas`、`resource_editor`、`ui_editor`、`manual_edit`、`system_projection`。
|
||||
|
||||
### 5.3 创作任务与 Agent
|
||||
|
||||
`creative_task_submit`:
|
||||
|
||||
第一阶段只要求带上:
|
||||
|
||||
```text
|
||||
creative_task_id
|
||||
project_id
|
||||
source
|
||||
```
|
||||
|
||||
不记录完整自然语言 prompt,也不要求第一阶段记录任务类型、输入方式、指令长度或附件信息。上述属性属于后续需要分析任务结构时再增加的可选字段。
|
||||
|
||||
`agent_run_completed` / `agent_run_failed`:
|
||||
|
||||
```text
|
||||
agent_type
|
||||
run_source
|
||||
duration_ms
|
||||
retry_index
|
||||
output_change_detected
|
||||
revision_id(如已产生)
|
||||
```
|
||||
|
||||
这里的 `agent_run_id` 只是一次 Agent 执行的技术关联 ID,不代表要记录每次执行的提示词内容。完成事件只能说明执行状态。`output_change_detected` 和后续 `project_revision_created` 用于区分“跑完了但没改变项目”。
|
||||
|
||||
### 5.4 预览
|
||||
|
||||
`preview_ready`:
|
||||
|
||||
```text
|
||||
preview_source
|
||||
preview_version
|
||||
ready_duration_ms(从触发构建到就绪,如可得)
|
||||
```
|
||||
|
||||
第一阶段的 `preview_ready` 必须有明确技术触发条件,例如预览服务确认可访问或本地运行状态确认 ready;不能用“返回了 URL”直接代替。
|
||||
|
||||
## 6. 可以看的数据
|
||||
|
||||
### 6.1 创作漏斗
|
||||
|
||||
```text
|
||||
编辑器进入
|
||||
→ 创建/打开项目
|
||||
→ 提交创作任务
|
||||
→ Agent 完成
|
||||
→ 项目产生 revision
|
||||
→ 预览就绪
|
||||
→ 保存
|
||||
→ 后续重新打开项目
|
||||
```
|
||||
|
||||
可计算:
|
||||
|
||||
- 编辑器到项目创建/打开转化率。
|
||||
- 项目到首次创作任务转化率。
|
||||
- 创作任务提交率:有项目用户中发生 `creative_task_submit` 的用户数 / 有项目用户数。
|
||||
- Agent 完成率:`agent_run_completed` /(`agent_run_completed` + `agent_run_failed`)。
|
||||
- 有效变化率:产生 `project_revision_created` 的任务数 / 创作任务数。
|
||||
- 预览到达率:产生 `preview_ready` 的任务数 / 创作任务数。
|
||||
- 保存率:产生 `project_save` 的项目用户数 / 产生 revision 的项目用户数。
|
||||
|
||||
### 6.2 创作行为
|
||||
|
||||
第一阶段可以看:
|
||||
|
||||
- 用户每次会话提交多少创作任务。
|
||||
- 一个项目累计发生多少次任务、run 和 revision。
|
||||
- Agent 完成后是否真的产生项目变化。
|
||||
- 失败后是否重试、追加指令或重新打开项目。
|
||||
- 用户是一次性尝试,还是回到同一个项目继续创作。
|
||||
- 不同来源、版本、任务类型的成功率差异。
|
||||
|
||||
第一阶段暂时不能可靠看:
|
||||
|
||||
- 编辑器活跃时长。
|
||||
- 完整项目创作总时长。
|
||||
- 用户是否满意或接受 Agent 结果。
|
||||
- 可靠的试玩成功率。
|
||||
- 仅凭这些事件直接得到 D1/D3/D7 留存,除非先确认 `user_id` 稳定且会话事件可靠落库。
|
||||
|
||||
## 7. 留存、LTV 与 ARPU 的当前口径
|
||||
|
||||
### 7.1 留存
|
||||
|
||||
当前先定义“创作者回访留存”,不定义泛产品活跃留存:
|
||||
|
||||
```text
|
||||
某 cohort 用户在 D0 发生 project_create_success 或 creative_task_submit
|
||||
在 D1/D3/D7 再次发生 project_open、creative_task_submit 或 project_revision_created
|
||||
```
|
||||
|
||||
公式:
|
||||
|
||||
```text
|
||||
Dk 创作者留存率 = D0 cohort 中在第 k 天至少发生一次创作相关事件的用户数 / D0 cohort 用户数
|
||||
```
|
||||
|
||||
前提是 `user_id` 稳定、事件可靠落库、日期按统一时区计算。当前代码审计结论是这些条件尚未全部确认,因此先把公式写入方案,不把结果宣称为已可用。
|
||||
|
||||
### 7.2 LTV 与单用户 ARPU
|
||||
|
||||
埋点本身不能产生 LTV 或 ARPU。需要另外存在可靠的订单/扣费/退款事实表,并用 `user_id` 关联。
|
||||
|
||||
```text
|
||||
ARPU = 统计周期内总收入 / 统计周期内活跃用户数
|
||||
```
|
||||
|
||||
如果看创作者商业价值,可另算:
|
||||
|
||||
```text
|
||||
创作者 ARPU = 统计周期内创作者收入 / 统计周期内发生创作行为的去重用户数
|
||||
```
|
||||
|
||||
```text
|
||||
LTV = 用户在定义生命周期内的累计净收入 / cohort 用户数
|
||||
```
|
||||
|
||||
其中净收入应扣除退款、赠送额度和必要的渠道/支付成本,具体财务口径需要业务和财务确认。当前早期地基埋点只负责提供用户行为侧的 cohort 和创作分群,不负责替代收入系统。
|
||||
|
||||
## 8. 第一阶段建议看板
|
||||
|
||||
只建议做四组:
|
||||
|
||||
1. **基础使用**:编辑器会话数、创建项目用户数、打开项目用户数、项目复访数。
|
||||
2. **创作漏斗**:任务提交、Agent 成功/失败、revision、preview ready、保存。
|
||||
3. **失败与恢复**:失败错误码、失败后重试率、失败后产生 revision 的比例。
|
||||
4. **回访创作**:D1/D3/D7 创作者回访,按任务类型、客户端版本、入口来源分组。
|
||||
|
||||
不要在第一阶段做几十个按钮点击看板,也不要把技术 JSONL、Runtime 状态和正式产品事件混成一张业务报表。
|
||||
|
||||
## 8.1 编辑时长的边界
|
||||
|
||||
本版本已经纳入前台时长事件,并区分三种时长:
|
||||
|
||||
- **会话时长**:`editor_session_start` 到 `editor_session_end`,包含用户离开电脑或切到其他窗口的时间,不等于编辑时长。
|
||||
- **前台时长**:`editor_focus_start` 到 `editor_focus_end` 的累计时间。
|
||||
- **活跃编辑时长**:前台期间发生有效编辑、任务提交、预览、保存等行为的累计时间。
|
||||
|
||||
本版本只承诺会话时长和前台时长两个粗粒度指标;即使记录了 `focus_duration_ms`,也不能把它解释成编辑器活跃时长。
|
||||
|
||||
前台时长的解释限制:
|
||||
|
||||
- 编辑器在前台但用户没有操作,仍会被计入。
|
||||
- 多窗口、系统锁屏、远程桌面或窗口状态异常时,可能出现边界误差。
|
||||
- 前台时长适合看停留和使用深度,不适合直接作为生产效率指标。
|
||||
|
||||
## 8.2 数据可靠性原则
|
||||
|
||||
已确认采用:
|
||||
|
||||
- 事件先写本地短暂 outbox。
|
||||
- 网络恢复后自动重试上传。
|
||||
- 服务端或接收端使用 `event_id` 去重。
|
||||
- 关闭、断网、崩溃导致的可能丢数需要在技术验收中明确记录。
|
||||
|
||||
## 9. 当前已收口的产品口径
|
||||
|
||||
根据当前讨论,本版本采用以下口径:
|
||||
|
||||
1. “创作成功”采用分层口径:`agent_run_completed` 表示执行完成,`project_revision_created` 表示项目发生有效变化,`preview_ready` 表示达到可预览状态;第一阶段不加入用户满意/接受结果事件。
|
||||
2. `creative_task_id` 表示用户一次创作意图;第一阶段不记录完整 Prompt,也不拆分 Prompt 内容。
|
||||
3. 第一阶段不加入 `task_type`、`input_mode`、指令长度和附件属性,避免早期方案过重。
|
||||
4. 事件允许先写本地短暂 outbox;网络恢复后自动重试;接收端按 `event_id` 去重。
|
||||
5. 创作者 D1/D3/D7 暂按 `project_open`、`creative_task_submit`、`project_revision_created` 作为回访事件,但只有在 `user_id` 和数据落库可靠后才正式出数。
|
||||
6. 编辑器前台时长纳入本版本;编辑器活跃编辑时长留到后续阶段。
|
||||
|
||||
## 9.1 仍需你确认的一项产品边界
|
||||
|
||||
只剩一个可能影响报表口径的问题:用户对同一个创作目标进行澄清或追加指令时,是否始终沿用同一个 `creative_task_id`。本方案默认沿用同一个任务 ID,只有用户明确开始新的创作目标时才生成新的任务 ID。
|
||||
|
||||
如果你没有特别异议,后续按这个默认口径执行即可;其余未收口项属于技术实现确认,不需要你继续定义。
|
||||
|
||||
## 10. 需要 master 开发对话回答的技术问题
|
||||
|
||||
开发对话只回答代码事实和实现成本:
|
||||
|
||||
- 是否已有服务端 analytics 接收接口和正式数据落点。
|
||||
- 若没有,第一阶段事件落本地 outbox、现有服务端 tracking,还是其他已有入口。
|
||||
- Tauri/Rust 是否能统一生成 `event_id`、`event_time`、`project_id`、`client_version`。
|
||||
- 当前能否稳定取得 `user_id`。
|
||||
- Direct 是否需要新增独立 `agent_run_id`。
|
||||
- `editor_session_id`、`creative_task_id` 是否能在现有生命周期生成。
|
||||
- `project_revision_created` 和 `preview_ready` 的可靠触发点在哪里。
|
||||
- 是否需要本地缓存、重试和去重;哪些异常场景会丢数。
|
||||
- 每个第一阶段事件对应的代码文件、触发函数、测试方式和估算成本。
|
||||
|
||||
前台时长还需要确认:
|
||||
|
||||
- Tauri 当前是否能可靠监听窗口 focus、blur、minimize、restore 和退出事件。
|
||||
- 窗口失焦后是否立即落一条 `editor_focus_end`,还是由统一会话管理器补齐。
|
||||
- 锁屏、系统休眠、崩溃和强制结束时,如何标记未闭合前台区间。
|
||||
- 多窗口场景是否存在;如存在,`editor_session_id` 是按应用实例还是按窗口生成。
|
||||
|
||||
## 11. 第一阶段验收标准
|
||||
|
||||
技术实现完成后,至少能够用一条测试链路证明:
|
||||
|
||||
```text
|
||||
editor_session_start
|
||||
→ editor_focus_start
|
||||
→ project_create_success
|
||||
→ creative_task_submit
|
||||
→ agent_run_completed 或 agent_run_failed
|
||||
→ project_revision_created(如果确实发生变化)
|
||||
→ preview_ready(如果确实达到 ready)
|
||||
→ project_save
|
||||
→ editor_focus_end
|
||||
→ editor_session_end
|
||||
```
|
||||
|
||||
并满足:
|
||||
|
||||
- 同一次链路中的 ID 能串联。
|
||||
- 重复上传不会制造重复事件。
|
||||
- Agent 失败不会被记成成功。
|
||||
- Agent 完成但没有项目变化时,不能伪造 `project_revision_created`。
|
||||
- 预览 URL 返回但不可访问时,不能伪造 `preview_ready`。
|
||||
- 关闭、断网、崩溃等场景的丢数风险已明确记录。
|
||||
- 能按 `user_id`、`project_id`、`creative_task_id`、`client_version` 做基本筛选。
|
||||
- 正常切换到其他窗口时,能闭合前台区间并计算 `focus_duration_ms`。
|
||||
- 最小化、恢复、正常退出至少有明确的 focus 结束/重新开始行为。
|
||||
- 崩溃或强制结束不会伪造一条完整的前台时长;未闭合区间必须可识别。
|
||||
|
||||
## 12. 对抗性自检审查
|
||||
|
||||
### 12.1 是否把技术完成误当创作成功
|
||||
|
||||
没有。方案明确区分 Agent 执行完成、项目产生 revision、预览就绪。三者分别是执行层、项目变化层和可预览层,不代表用户满意。
|
||||
|
||||
### 12.2 是否把前台时长误当编辑时长
|
||||
|
||||
没有。事件名、字段名和看板解释统一使用“前台时长”;用户没有操作但窗口保持前台的时间会被计入,并在文档中标明限制。
|
||||
|
||||
### 12.3 是否记录得过细、造成第一阶段过重
|
||||
|
||||
当前 P0 不记录完整 Prompt、任务类型、输入方式、指令长度和附件属性。保留的是会话、项目、任务、Agent 状态、revision、预览、保存和前台区间,属于基础漏斗与创作回访所需的最小集合。
|
||||
|
||||
### 12.4 前台事件是否会制造大量噪音
|
||||
|
||||
会比核心业务事件多,但仍是成对的窗口状态事件,不是按键或鼠标级事件。前台事件只用于时长聚合,不作为单独的产品成功指标。
|
||||
|
||||
### 12.5 断网、退出和崩溃是否会导致数据不可信
|
||||
|
||||
不能完全消除,但通过本地 outbox、重试和 `event_id` 去重降低风险。未闭合的 focus 区间必须标记不完整,不把估算时间写成事实。
|
||||
|
||||
### 12.6 是否能直接计算 D1/D3/D7、LTV、ARPU
|
||||
|
||||
不能直接保证。留存依赖稳定 `user_id` 和可靠落库;LTV/ARPU 还依赖订单、扣费、退款和净收入事实表。当前方案只提供行为 cohort 和创作者分群基础。
|
||||
|
||||
### 12.7 是否仍有未收口问题
|
||||
|
||||
有,但已经集中到技术实现确认,不影响产品方案定稿:
|
||||
|
||||
- 当前服务端 analytics 接口和正式落点是否存在。
|
||||
- Direct 是否能在现有生命周期生成独立 `agent_run_id`。
|
||||
- `project_revision_created` 和 `preview_ready` 的实际可靠触发点。
|
||||
- Tauri focus/blur 等窗口事件在当前多窗口、锁屏、休眠和崩溃场景下的行为。
|
||||
- `user_id` 是否稳定,以及匿名用户后续是否需要身份合并。
|
||||
|
||||
这些不是继续扩展事件的理由,而是技术负责人需要逐项确认的实现事实。
|
||||
|
||||
## 13. 当前结论
|
||||
|
||||
这套早期地基版埋点足以回答:用户有没有进入编辑器、在前台停留了多久、有没有创建项目、有没有发起创作、Agent 是否完成、项目是否真的变化、是否走到预览、是否回到同一项目继续创作。
|
||||
|
||||
它暂时不能回答:用户是否喜欢结果、是否完成试玩、编辑器真正活跃了多久、完整 LTV/ARPU,以及在用户身份和数据落库尚未确认前的可靠 D1/D3/D7 留存。
|
||||
|
||||
因此本方案的产品层已经基本收口。下一步是把第 10 节交给最新 master 开发对话核实,再由技术负责人拆成最小实现任务;如果技术核实发现 focus/blur 触发不稳定,只需要调整前台时长实现方式或降级为会话时长,不需要推翻整个埋点方案。
|
||||
@@ -51,6 +51,8 @@
|
||||
|
||||
以下文档明确是历史记录、实施记录、专利材料或问题记录:
|
||||
|
||||
- `docs/technical/【需求来源】GameAgent埋点设计原始方案-2026-09-05.md`
|
||||
|
||||
- `docs/【实施记录】SFX生成优化V2.0T6测试与发布门禁-2026-08-07.md`
|
||||
- `docs/【专利交底】一种极低成本快速生成高质量2D小游戏高一致性美术素材的解决方案-2026-05-25.md`
|
||||
- `docs/technical/【问题记录】DirectProject客户端Skill自然语言触发能力缺口-2026-09-01.md`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -678,8 +678,8 @@ journalctl -u genarrative-api -o cat | grep 'operation="release_rejected"'
|
||||
|
||||
发布事故或回滚窗口里用 `game-distribution:publish` 灰度开关控制写入,不需要改代码或重启:
|
||||
|
||||
- 开关位置:后台「灰度发布配置」(`GET/PUT /admin/api/feature-gates`),`gateKey = game-distribution:publish`。
|
||||
- 语义:没有该 gate 行或 `enabled=false` 表示**默认开放**;`enabled=true` 时只有 `allowUserIds` / `allowUserTags` / `rolloutPercent` 命中的作者能发布,`rolloutPercent=0` 且无白名单即**全部关闭**(等价紧急关闭投稿)。
|
||||
- 开关位置:后台「灰度发布配置」(`GET/PUT /admin/api/feature-gates`),`gateKey = game-distribution:publish`;后台「可配置开关」里固定列出「游戏分发 · 游戏发布」,点「配置」即按默认关闭填表(`enabled=false`),再填白名单 / 灰度比例并开启保存。灰度默认关闭:该键未创建或 `enabled=false` 时作者看不到发布入口、写入口返回 503。
|
||||
- 语义:没有该 gate 行或 `enabled=false` 表示**未开放**(灰度默认关闭);`enabled=true` 时只有 `allowUserIds` / `allowUserTags` / `rolloutPercent` 命中的作者能发布,`rolloutPercent=0` 且无白名单同样全关(等价紧急关闭投稿)。开放灰度就是把 `enabled` 打开并放白名单或提高比例。
|
||||
- 关闭范围:创建游戏、创建版本、上传包、送审、撤回、作者下架,以及管理员**批准**(新版本激活)都返回 `503 GAME_DISTRIBUTION_PUBLISH_DISABLED`。
|
||||
- 始终可用:目录、详情、版本回读、发行网关(已公开游戏继续游玩)、`/my-games`、审核队列读取、**拒绝审核**与管理员**安全下架**。
|
||||
- 失败姿态:开关状态读取失败时按关闭处理,避免绕过运营刚下的收紧动作;本地排障时确认 SpacetimeDB 正常后再判断业务是否被误伤。
|
||||
@@ -1141,20 +1141,7 @@ SELECT * FROM profile_recharge_product_config ORDER BY sort_order ASC;
|
||||
- 微信新用户的内部 `user_id` 改为不可复用的 `user_` 前缀 UUID 风格,避免清库后旧作品被后来的顺序号账号顶替。
|
||||
- 当作品作者的 `owner_user_id` 找不到真实账号时,作品统一显示为占位作者:`失效作者`,公开陶泥号固定为 `SY-00000000`,占位账号 ID 为 `wx-openid-placeholder`。
|
||||
- 该占位账号只用于作品作者域,不扩展到全站其它身份域。
|
||||
- 如需把历史孤儿作品批量回填到占位作者,使用 `scripts/rebind-orphan-work-owners.mjs` 先基于当前 auth 快照识别有效用户,再把缺失作者对应的作品表写回为占位 ID;脚本输入输出都基于 SpacetimeDB 迁移 JSON。
|
||||
|
||||
### 回填脚本用法
|
||||
|
||||
```bash
|
||||
node scripts/rebind-orphan-work-owners.mjs --in <exported-migration.json> --out <rebound-migration.json>
|
||||
node scripts/rebind-orphan-work-owners.mjs --in <exported-migration.json> --dry-run
|
||||
node scripts/rebind-orphan-work-owners.mjs --in <exported-migration.json> --out <rebound-migration.json> --placeholder-user-id wx-openid-placeholder
|
||||
```
|
||||
|
||||
- `--in`:SpacetimeDB 导出的迁移 JSON。
|
||||
- `--out`:写回后的迁移 JSON 输出路径。
|
||||
- `--dry-run`:只统计回填行数,不写文件。
|
||||
- `--placeholder-user-id`:需要时可覆盖默认占位账号 ID。
|
||||
- 旧作品表退役后,迁移 JSON 回填工具 `scripts/rebind-orphan-work-owners.mjs` 已删除,不再提供回填脚本用法或当前操作入口;占位作者的显示与身份域语义继续保持上述规则。
|
||||
|
||||
## 维护页目标文件安全边界(2026-08-05)
|
||||
|
||||
|
||||
@@ -86,10 +86,10 @@
|
||||
2. 所有运行依赖都必须在发行包内。资源 URL 使用与发行版本目录兼容的相对地址;前导 `/assets`、本地文件 URL、外部脚本/样式/媒体/字体地址均不属于可接受发行合同。客户端给出可操作错误,服务器仍独立校验;静态校验不能代替运行时 CSP 阻断。
|
||||
3. 建议首版限额:压缩包 100 MiB、展开总量 250 MiB、单文件 64 MiB、最多 10,000 个文件、展开/压缩比不超过 100。服务端拒绝加密 ZIP、重复或大小写冲突路径、绝对路径、`..`、符号链接/重解析点、设备文件和嵌套压缩包;拒绝 `.agent`、版本控制目录、`node_modules`、凭据文件与源码映射文件。超限返回明确错误,不截断后继续发布。
|
||||
4. 提交声明 ZIP 的 SHA-256 与字节数,服务端对收到的真实 ZIP 重新计算,再对展开文件建立相对路径、字节数和 SHA-256 清单。摘要不一致、缺文件或入口损坏时停止;只有 metadata 而没有已确认完整对象的提交必须失败。
|
||||
5. 游戏资料随发行版本冻结:标题 2–40 字、短简介不超过 120 字、详细介绍不超过 2,000 字、一个分类、最多 5 个标签(每个不超过 20 字)、必需封面、最多 6 张截图、操作方式不超过 240 字。分类首版为休闲、益智、动作、冒险、模拟、策略、其他;封面/截图复用平台图片上传与归属校验,不接受任意外链作为审核图片。发布入口按灰度下发:后端灰度配置键固定为 `game-distribution:publish`(后台「灰度发布配置」可改,支持 `enabled` / `rolloutPercent` / `allowUserIds` / `allowUserTags`)。未配置该键、或 `enabled=false` 时对已登录作者默认开放;显式 `enabled=true` 后只有白名单或灰度命中的作者拿到开放状态,匿名恒为不开放。发布入口的开放状态随 `/api/runtime/frontend-config` 的 `gameDistributionPublishEnabled` 下发,网页广场/我的游戏入口与 AGC 聊天头「发布到游戏广场」按钮据此显示或隐藏;写入口仍独立校验,收紧期间提交返回 503 与可读文案,读接口、目录、详情、发行网关与安全下架不受影响。作者续发时按版本冻结快照回填封面与截图并复用同一批素材;公开投影只暴露对象键,素材 ID 只在作者与管理员回读时返回,快照里缺素材 ID 的旧版本必须要求作者重新选择封面。
|
||||
5. 游戏资料随发行版本冻结:标题 2–40 字、短简介不超过 120 字、详细介绍不超过 2,000 字、一个分类、最多 5 个标签(每个不超过 20 字)、必需封面、最多 6 张截图、操作方式不超过 240 字。分类首版为休闲、益智、动作、冒险、模拟、策略、其他;封面/截图复用平台图片上传与归属校验,不接受任意外链作为审核图片。作者不需要自己构建或打 ZIP:AGC 发布时对 `game/` 子工程按需执行 `npm install`(复用 `project.bootstrap`)与 `npm run build`(复用 `project.verify` 的受控 npm 运行器,脚本白名单含 `build`、禁止项目级 `.npmrc` 改写语义),再把 `game/dist` 归一化成根 `index.html` 的发行包上传;已有可玩入口(`game/index.html` 或 `dist/index.html`)时跳过构建。Phaser 4 + Vite 已按此口径端到端验证(构建产物、发行网关与网页沙箱播放)。发布入口按灰度下发:后端灰度配置键固定为 `game-distribution:publish`(后台「灰度发布配置」可改,支持 `enabled` / `rolloutPercent` / `allowUserIds` / `allowUserTags`)。灰度默认关闭:未配置该键、或 `enabled=false` 时,未登录与已登录作者都拿到不开放(发布入口不渲染、写入口 503);运营在后台创建该键并 `enabled=true` 后,只有白名单 / 灰度比例 / 用户标签命中的作者拿到开放状态。发布入口的开放状态随 `/api/runtime/frontend-config` 的 `gameDistributionPublishEnabled` 下发,网页广场/我的游戏入口与 AGC 聊天头「发布到游戏广场」按钮据此显示或隐藏;写入口仍独立校验,收紧期间提交返回 503 与可读文案,读接口、目录、详情、发行网关与安全下架不受影响。作者续发时按版本冻结快照回填封面与截图并复用同一批素材;公开投影只暴露对象键,素材 ID 只在作者与管理员回读时返回,快照里缺素材 ID 的旧版本必须要求作者重新选择封面。
|
||||
6. `supportedDevices` 至少包含 `desktop` 或 `mobile`;`inputModes` 来自 `keyboard`、`mouse`、`touch`;声明移动端必须包含 `touch`。`orientation` 为 `landscape`、`portrait` 或 `responsive`。这些是待人工复核的作者声明,目录只显示已经随版本审核通过的值。
|
||||
7. 原始 ZIP、未审核展开目录、审核资料均为私有对象;公开版本不暴露源码镜像键、本地路径、访问凭据或私有账号元数据。运行文件只能由发行网关按游戏、版本和文件白名单读取,不能绕过网关访问公开 OSS bucket。
|
||||
8. 现役发行网关由 `api-server` 提供:`GET /api/game-distribution/releases/{gameId}/{assetPath}` 只服务当前已公开版本包内的文件,私有 ZIP 与未公开版本不因知道 ID 而可读。响应按扩展名白名单设定内容类型,未知扩展名返回 404;全部响应带 `X-Content-Type-Options: nosniff`、`Cross-Origin-Resource-Policy: cross-origin` 与不带 credentials 的 `Access-Control-Allow-Origin: *`(发行文档运行在 `allow-scripts` 的 opaque origin 沙箱里,`same-origin` 会让游戏自己的脚本被浏览器拦下),HTML 追加最小权限 CSP。带平台 `Cookie` 的请求一律 `403`,避免发行文件被主站同源读取;发行网关必须部署在独立来源。发行包按对象键在进程内做有界缓存,单个超预算包不进入缓存。
|
||||
8. 现役发行网关由 `api-server` 提供:`GET /api/game-distribution/releases/{gameId}`(含尾斜杠)等价于该游戏的 `index.html`,`GET /api/game-distribution/releases/{gameId}/{assetPath}` 只服务当前已公开版本包内的文件,私有 ZIP 与未公开版本不因知道 ID 而可读。响应按扩展名白名单设定内容类型,未知扩展名返回 404;全部响应带 `X-Content-Type-Options: nosniff`、`Cross-Origin-Resource-Policy: cross-origin` 与不带 credentials 的 `Access-Control-Allow-Origin: *`(发行文档运行在 `allow-scripts` 的 opaque origin 沙箱里,`same-origin` 会让游戏自己的脚本被浏览器拦下),HTML 追加最小权限 CSP。带平台 `Cookie` 的请求一律 `403`,避免发行文件被主站同源读取;发行网关必须部署在独立来源。发行包按对象键在进程内做有界缓存,单个超预算包不进入缓存。
|
||||
9. 审核通过时必须提交绝对 HTTPS `entryUrl`,且不接受凭据、query 和 fragment;服务端不根据请求 Host 或本地路径拼默认发行地址,避免把内网地址或主站来源写进公开投影。 非生产环境额外允许 http 回环地址(`127.0.0.1` / `localhost` / `[::1]`),口径与前端 `normalizeGameEntryUrl` 一致,便于本地在没有 TLS 的情况下验证内嵌游玩;生产环境只接受 HTTPS。
|
||||
|
||||
### 身份、状态、审核与更新
|
||||
@@ -119,7 +119,7 @@
|
||||
| --- | --- | --- |
|
||||
| `GET /games` | 游客 | **已实现**:关键词与分类筛选,最多 48 项;仅公开可玩版本 |
|
||||
| `GET /games/{gameId}` | 游客 | **已实现**:当前公开资料与 `currentVersion.entryUrl`;不可见时 404 |
|
||||
| `GET /game-distribution/releases/{gameId}/{assetPath}` | 游客 | **已实现**:发行网关只服务当前已公开版本包内文件,按扩展名白名单设内容类型,未知扩展名 404,带 Cookie 的请求 403;游玩页的入口来自详情投影的 `currentVersion.entryUrl` |
|
||||
| `GET /game-distribution/releases/{gameId}[/{assetPath}]` | 游客 | **已实现**:根路径等价于 `index.html`;发行网关只服务当前已公开版本包内文件,按扩展名白名单设内容类型,未知扩展名 404,带 Cookie 的请求 403;游玩页的入口来自详情投影的 `currentVersion.entryUrl` |
|
||||
| `GET /my/games` | 登录作者 | **已实现**:当前账号游戏、最近版本状态与驳回理由;owner 只从认证主体派生 |
|
||||
| `POST /games` | 登录作者 | **已实现**:幂等创建游戏身份,尚不公开;带 `localProjectId` 时同一作者复用既有 `gameId` |
|
||||
| `POST /games/{gameId}/versions` | owner | **已实现**:创建不可变待上传版本,冻结包摘要/字节数/文件数与资料 |
|
||||
@@ -151,7 +151,7 @@
|
||||
- 建议 HTML、公开状态与启动 API 使用 `no-store`;发行静态资源的浏览器与 CDN 有效期均不超过 60 秒,禁止 `stale-while-revalidate`、`stale-if-error` 和发行 Service Worker。下架主动 purge 相关 CDN 键,60 秒作为最大缓存撤销窗口,不把 purge 成功当唯一保障。旧版本被更新替代后,新启动只用当前版;旧游戏已经载入的脚本/资源不承诺远程抹除,用户退出或刷新后按当前授权重新判断。
|
||||
- 发布所需部署依赖包括独立站点域名及通配 TLS、每游戏 host 路由、私有存储、网关 CSP/CORS/MIME、CDN TTL/purge、管理员审核运营入口和可恢复校验执行器;缺少任一项不能宣布公开上线。
|
||||
- 观察上传失败、校验耗时、审核积压、发行 4xx/5xx、撤销传播时间与容量,日志按游戏/版本/操作 ID 关联,不记录 Token、完整用户文件内容或 signed URL。原始失败/撤回包建议保留 7 天后清理,公开版本和审核记录的保留周期在上线前确定;清理必须先检查引用,不能删除仍在服务的版本。
|
||||
- 回滚部署时关闭新提交和新版本激活,保留当前可玩版本与状态读取;数据库迁移不以删表回滚。安全事件通过服务端关闭游戏发行权限,不依赖前端隐藏按钮。现役实现:`game-distribution:publish` 灰度开关(后台「灰度发布配置」)控制作者写入与新版本激活——没有 gate 行或 `enabled=false` 时默认开放;`enabled=true` 时只有白名单/灰度命中的用户能发布(`rolloutPercent=0` 且无白名单即全部关闭)。关闭期间目录、详情、版本回读、发行网关、审核队列读取、拒绝审核与安全下架都不受影响;开关读取失败按关闭处理。
|
||||
- 回滚部署时关闭新提交和新版本激活,保留当前可玩版本与状态读取;数据库迁移不以删表回滚。安全事件通过服务端关闭游戏发行权限,不依赖前端隐藏按钮。现役实现:`game-distribution:publish` 灰度开关(后台「灰度发布配置」)控制作者写入与新版本激活——灰度默认关闭,没有 gate 行或 `enabled=false` 时不允许发布;`enabled=true` 时只有白名单/灰度命中的用户能发布(`rolloutPercent=0` 且无白名单即仍然全关)。关闭期间目录、详情、版本回读、发行网关、审核队列读取、拒绝审核与安全下架都不受影响;开关读取失败按关闭处理。
|
||||
|
||||
### 验收标准与证据
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
- 角色面板增加紧凑的 `像素艺术` 勾选项,请求使用可选字符串字段 `style`:未勾选传 `"none"`,勾选传 `"pixelArt"`。该选择可以随现有生成器快照和队列 payload 保存,但不写入用户可见 `generationInputs`、素材元数据或新建的持久化记录。
|
||||
- `style` 省略、为 `null`、空字符串或 `"none"` 时按内部 `None` 处理且不告警;`"pixelArt"` 在 `kind="character"` 时启用像素规整。未知字符串按 `None` 继续生成,并通过既有通用 `warning` 返回 `unsupported-image-style`;非字符串 JSON 仍返回 `400`。同一图片生成请求 DTO 被其它 `kind` 复用时,只有普通图片和 `character` 支持 `"pixelArt"`,其它 `kind` 收到该值也按不支持风格降级。
|
||||
- 2026-08-01 修订:`"pixelArt"` 不再只是后处理,同时向提交给 provider 的提示词末尾追加独立一行约束。角色链路使用「角色主体为像素风格」,**不得**使用「画面为像素风格」——角色生成后要按纯色抠像,绿幕底必须保持平整,同一段提示词里已写死「纯色背景必须平整无纹理、无渐变」,画面级像素化要求会与之互相拆台;且该提示词已禁止出现角色以外的场景内容,因此只需点名角色本身。注入发生在 `build_editor_character_image_prompt` 返回之后,该函数签名和输出契约不变。约束句**不会**进入角色链路的任何 `editor_project_resource`:原图 resource 的 prompt 列存的是 `role_setting`(用户原文),透明结果的 `output_prompt` 在抠图成功后被无条件覆盖为 `"去除纯色背景"`;完整提交提示词是否留存取决于 provider:`persist_editor_provider_source_image` 写原图 asset object 元数据时用的是 `actual_prompt.unwrap_or(prompt)`,provider 未回 `actualPrompt` 时才存 `submitted_prompt`(含约束句),此时排障可按 `object_key` 查;provider 回了 `actualPrompt` 就存 provider 改写后的文本,该次生成的 `submitted_prompt` 在系统内一处都不落——外部 API 审计的 `request_payload` 只记 `promptChars` 字符数,没有提示词原文。响应体返回的是用户原文,前端显示不变。以上 prompt 列写入与 asset object 元数据规则都是既有行为,与 `web/master` 逐行一致,本次未改动。角色提示词里既有的「严格基于图1的角色美术视觉规范的美术风格」与像素约束存在潜在冲突,本次未改写,等实测。
|
||||
- 2026-08-01 修订:`"pixelArt"` 不再只是后处理,同时向提交给 provider 的提示词末尾追加独立一行约束。角色链路使用「角色主体为像素风格」,**不得**使用「画面为像素风格」——角色生成后要按纯色抠像,绿幕底必须保持平整,同一段提示词里已写死「纯色背景必须平整无纹理、无渐变」,画面级像素化要求会与之互相拆台;且该提示词已禁止出现角色以外的场景内容,因此只需点名角色本身。注入发生在 `build_editor_character_image_prompt` 返回之后,该函数签名和输出契约不变。约束句**不会**进入角色链路的任何 `editor_project_resource`:原图 resource 的 prompt 列存的是 `role_setting`(用户原文),透明结果的 `output_prompt` 在抠图成功后被无条件覆盖为 `"去除纯色背景"`;原图 asset object 元数据由现役 `prepare_editor_generated_image` / upload-only helper 按传入的 `prompt` 构造,resource / asset 的 `actualPrompt` 由原子提交候选单独保存;排障应核对现役调用参数与记录,不能再按已退役的 provider-source 分步持久化函数推断提示词来源。角色提示词里既有的「严格基于图1的角色美术视觉规范的美术风格」与像素约束存在潜在冲突,本次未改写,等实测。
|
||||
- 角色 provider 回图先按统一业务像素矩阵执行交付尺寸归一:允许无放大恢复时使用 Lanczos 重采样并居中裁切,无法安全恢复时保留 provider 实际尺寸并返回非阻断告警。归一后的带纯色背景图先持久化并作为 BgFilter 输入;BgFilter 正常成功后,把 Alpha 蒙版回贴到这张同尺寸平底原图,再执行像素规整并上传透明主图。网格分析源使用已收口到实际交付尺寸的平底原图,RGBA 采样源使用 Alpha 已回贴的透明图;软 Alpha 只参与单格覆盖率和 Alpha 加权 RGB 计算,输出 Alpha 硬化为 `0 / 255`。
|
||||
- 首版参数固定为分析色数 `16`、Alpha 覆盖阈值 `0.375`、像素格尺寸自动检测、固定色板关闭、K-means 最大采样 `262144`。单格覆盖率 `Σ(A / 255) / N >= 0.375` 且 `ΣA > 0` 时输出 `A=255`,颜色按 `Σ(A × RGB) / ΣA` 计算;否则输出 `[0,0,0,0]`。分析色数不限制最终输出色数。
|
||||
- 像素规整 CPU 工作使用进程级最大并发 `2`;取得并发许可的排队时间与实际处理时间共享最多 `30` 秒预算,同时不得晚于当前请求 deadline,最终以两者中更早者为准。输入图片任一边不得超过 `10000` 像素,总像素不得超过 `8294400`;超限、排队超时或处理超时均保留 Alpha 已回贴的透明图并走非致命降级。
|
||||
|
||||
Reference in New Issue
Block a user