合并 origin/master 到 feat/ui-editor-v3
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m27s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m5s
Project CI / Native shell tests (pull_request) Failing after 1m47s
Project CI / Backend tests (pull_request) Successful in 3m53s
Project CI / Frontend tests (pull_request) Successful in 1m38s
Project CI / AI game creator shell web tests (pull_request) Failing after 38s
Project CI / Repository checks (pull_request) Failing after 1m33s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m0s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m2s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m27s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m5s
Project CI / Native shell tests (pull_request) Failing after 1m47s
Project CI / Backend tests (pull_request) Successful in 3m53s
Project CI / Frontend tests (pull_request) Successful in 1m38s
Project CI / AI game creator shell web tests (pull_request) Failing after 38s
Project CI / Repository checks (pull_request) Failing after 1m33s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 9m0s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 9m2s
- 合入 master 179 个提交(后台管理页、游戏发行入口、AGC 运行页签、编译 warning 清理等) - policy.rs 采用 master 版本:删除无调用方的 autonomous_design_foundation_command_is_allowed 重复名单,design-foundation 权限以 tool_policy_snapshot.rs 为准 - native-tools.json 保留双方结果:master 的描述文本 + 分支删除已退役的 ui.workflow.run.description - useUiEditorPage.ts 保留分支的 save / saveAndGenerateCode 状态返回契约,并接上 master 的 beginUiSaveAnalytics 与 saveSource: 'auto' 埋点 - 验证:cargo check --bin genarrative-ai-game-creator-shell、npm run check:rustfmt、tsc --noEmit、vitest tests/uiEditorPage.test.ts + tests/clientAnalytics.test.tsx(47 passed)
This commit is contained in:
@@ -22,7 +22,8 @@
|
||||
## 指标口径
|
||||
|
||||
- 生产素材数:`editor_project_resource` 中 `source_type = 'generated'` 的资源,按 `created_at` 映射到北京时间业务日。
|
||||
- 消耗泥点数:`profile_wallet_ledger` 中 `source_type = asset_operation_consume` 且 `amount_delta < 0` 的流水绝对值,按 `created_at` 映射到北京时间业务日。
|
||||
- 消耗泥点数(净消耗):`profile_wallet_ledger` 中 `source_type` 为 `asset_operation_consume` / `llm_router_consume` 且 `amount_delta < 0` 的流水绝对值,按 `created_at` 映射到北京时间业务日后,再按日对冲同期退还泥点——先抵当日消耗,不足再回溯抵扣最近仍有净额的业务日,抵扣不完的退还丢弃,因此每日净额非负,区间合计严格等于「消耗 − 退还」。充值退款追回、余额重置、赠送和 hold 都不计入。
|
||||
- 退还泥点数:`source_type = asset_operation_refund` 的正向流水(生成失败退还、精选审核返还)与 `llm_router_consume` 的正向冲正流水,按 `created_at` 映射到北京时间业务日。它只对冲本看板的消耗口径,不改变用户详情「历史花费」按既有决策的退款不冲减口径。
|
||||
- 总注册用户:`profile_dashboard_state` 行数。
|
||||
- 新增用户数:`profile_dashboard_state` 中 `created_at` 落在当前筛选时间窗内的账号数,按北京时间业务日归属,支持本日 / 本周 / 本月快捷日期范围。
|
||||
- 新增用户付费率:分母为当前筛选时间窗内的新增用户,分子为这些用户中截至本次查询时已至少完成一次真实支付的去重人数。真实支付以 `profile_recharge_order.paid_at` 存在且不晚于本次查询时刻为准;只创建订单或未支付订单不计,已退款订单仍表示曾经发生过付费转化,因此保留在分子。返回付费人数、新增用户数和四舍五入后的基点率;分母为 0 时 DTO 返回 0,前端百分比显示 `-`。
|
||||
@@ -33,6 +34,7 @@
|
||||
- 留存活跃:用户在注册日恰好 `D+1` / `D+7` 的 `tracking_daily_stat` 中存在上述有效 user scope 行;同一用户同日多个事件只计一次,不按“1 / 7 天内累计回访”计算。筛选范围约束注册 cohort,观察日允许晚于筛选结束日。
|
||||
- 留存成熟条件:目标观察日必须早于当前北京时间业务日;观察日为今天时因当天尚未完整结束而排除。D1、D7 的可观察人数通常不同,分别返回 `eligibleUsers`、`retainedUsers` 与 `rateBasisPoints = round(retainedUsers * 10000 / eligibleUsers)`;分母为 0 时 DTO 返回 0,前端百分比显示 `-`。汇总率按总人数加权,不平均每日百分比。
|
||||
- 运营汇总页签:复用同一时间窗,展示运营指标卡、素材类型分布和访问模块分布。
|
||||
- 趋势图:`消耗泥点` 图展示按日对冲之后的净额,区间合计与「消耗泥点数」指标一致;`退还泥点` 图展示同期退还金额,毛消耗可由「消耗 + 退还」核出,避免把退还金额藏进净额里。
|
||||
|
||||
## 前后端文件
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
# 外部生成 Worker 化方案
|
||||
> 文档状态:`historical`
|
||||
本文仅用于历史追溯,不作为当前实现依据。
|
||||
|
||||
|
||||
> 2026-07-18 退役覆盖:旧创作模板 job 类型、玩法写回和玩法恢复链路均已退出现役 worker。当前 worker 只领取 `source_module = editor-canvas` 的任务;本文涉及拼图、跳一跳、拼消消、敲木鱼等玩法的内容仅作为历史设计记录,历史队列行不得被领取或改写。
|
||||
本文记录 external generation worker 的稳定设计边界;当前实现细节以代码和现行架构文档为准。
|
||||
|
||||
> 2026-07-21 已实施、待生产压测专题:BgFilter 作为受限内部资源,仍遵守“单用户动作一个外部生成 job”;用户可见层与调度层都只有父 `external_generation_job`。父 future 保持原 lease 和 attempt,在当前调用栈内同步请求唯一 `bgfilter-worker` 的内部 HTTP,成功图片字节直接返回父流程。首版不新增 SpacetimeDB 子任务表、父 checkpoint / continuation 或 raw 中间结果 OSS。完整边界见 [`BgFilter 受限资源调度方案(同步内部 HTTP 原地等待版)`](./【后端架构】BgFilter受限资源调度方案-2026-07-21.md)。
|
||||
|
||||
更新时间:`2026-07-31`
|
||||
更新时间:`2026-09-23`
|
||||
|
||||
## 背景
|
||||
|
||||
@@ -20,8 +17,8 @@ VectorEngine `gpt-image-2`、音频、LLM 等外部生成不能由面向外部
|
||||
- 多个 worker 进程通过 SpacetimeDB 任务表抢占任务,依赖 lease 超时恢复,支持按进程数和单进程并发动态缩扩容。
|
||||
- 本地或小流量站内同步排查可显式启用 `inline` 模式,由站内 HTTP handler 复用同一 worker executor 同步执行并返回 `completed`;该模式不创建队列任务,也不具备 worker 横向扩容能力。External v1 不继承此例外,始终异步入队。
|
||||
- SpacetimeDB reducer / procedure 只做任务状态流转,不做网络、文件系统或外部 provider I/O。
|
||||
- 已接入拼图 `compile_puzzle_draft`、结果页 `generate_puzzle_images` 与结果页 `generate_puzzle_ui_background`,跳一跳、拼消消和敲木鱼的外部图片生成动作,以及图片画布编辑器的图片、改图、手动去背景、图标 spritesheet、UI 素材提取、角色动作、视频、音效和背景音乐生成。后续玩法和编辑器生成入口继续复用同一队列 Module,不再为每个入口发明独立队列。
|
||||
- 第一版外部生成队列粒度固定为“单个用户动作对应单个 job”。例如草稿编译、结果页单槽重生、图集重生都各自入一个 job;job 内部可以串行或并行调用 provider、OSS、SpacetimeDB 写回,但不再拆成“提示词 / 生图 / 切图 / 去背景 / 持久化 / 回写”等阶段 job。用户可见执行阶段通过现有任务行及摘要投影的轻量 `phase` 保存,不作为队列调度单位,也不写回大 payload。
|
||||
- 已接入图片画布编辑器的图片、改图、手动去背景、图标 spritesheet、UI 素材提取、角色动作、视频、音效和背景音乐生成。外部生成入口继续复用同一队列 Module,不再为每个入口发明独立队列。
|
||||
- 外部生成队列粒度固定为“单个用户动作对应单个 job”。例如一次图片生成、改图、视频生成或角色动作生成各自入一个 job;job 内部可以串行或并行调用 provider、OSS 和 SpacetimeDB 写回,但不再拆成“提示词 / 生图 / 处理 / 持久化 / 回写”等阶段 job。用户可见执行阶段通过现有任务行及摘要投影的轻量 `phase` 保存,不作为队列调度单位,也不写回大 payload。
|
||||
- 不调用外部图片 / 音频 / LLM provider 的动作继续 inline 执行,不为了统一排队而进入 `external_generation_job`。
|
||||
|
||||
## Module 与 Interface
|
||||
@@ -45,19 +42,19 @@ External API job 复用同一个 `result_payload_json` 列,但只额外保存
|
||||
|
||||
不带 `summary / summaries` 的旧 `get / list / acknowledge_external_generation_job*` procedure 只保留给受控内部兼容,不是 BFF 正式读取入口。
|
||||
|
||||
这个 Module 的 **Seam** 在 SpacetimeDB procedure + `spacetime-client` facade;`api-server` HTTP role 和 worker role 都只依赖这个 Interface。外部 provider、OSS、计费补偿、玩法草稿回写仍留在 `api-server` worker implementation 内,不进入 SpacetimeDB reducer。
|
||||
这个 Module 的 **Seam** 在 SpacetimeDB procedure + `spacetime-client` facade;`api-server` HTTP role 和 worker role 都只依赖这个 Interface。外部 provider、OSS、计费补偿和编辑器业务结果回写仍留在 `api-server` worker implementation 内,不进入 SpacetimeDB reducer。
|
||||
|
||||
## BFF 状态接口
|
||||
|
||||
队列状态对前端只通过 `api-server` BFF 暴露,不允许前端直接查询 SpacetimeDB private table:
|
||||
|
||||
- `GET /api/runtime/external-generation/queue-overview`:当前账号队列概览,用于兼容旧展示和轻量状态读取。返回 pending、running、未确认终态数量和更新时间。
|
||||
- `GET /api/runtime/external-generation/queue-overview`:当前账号队列概览,用于轻量状态读取。返回 pending、running、未确认终态数量和更新时间。
|
||||
- `GET /api/runtime/external-generation/jobs?limit=20&includeAcknowledgedTerminal=false`:当前账号正式生成任务列表,用于 `我的` 页签任务列表和完成 / 失败提示。返回每个任务的 job id、kind、source、可展示 label、状态、进度、错误、可选 `warning`、`priceMudPoints`、`refundLedgerId`、`notificationAcknowledgedAt` 和时间戳。默认不返回已确认的终态任务;需要拆分活跃和完成列表时可追加 `statuses=running,queued` 或 `statuses=completed,failed`,BFF 仍只返回当前账号任务。
|
||||
- 任务被 claim 后默认处于 `generating`,BFF 显示“正在生成”;真实进入 BgFilter、逐帧抠图或手动去背景时切换为 `processing`,BFF 显示“正在处理”。旧任务 `phase=None` 按 `generating` 兼容,前端不得按耗时或 job kind 推断阶段。
|
||||
- 任务被 claim 后默认处于 `generating`,BFF 显示“正在生成”;真实进入 BgFilter、逐帧抠图或手动去背景时切换为 `processing`,BFF 显示“正在处理”。`phase=None` 按 `generating` 兼容,前端不得按耗时或 job kind 推断阶段。
|
||||
- `POST /api/runtime/external-generation/jobs/acknowledge`:生成完成 / 失败提示展示后由前端后台调用,BFF 只传当前账号 job ids,后端只确认属于当前账号且已终态的任务。
|
||||
- `GET /api/runtime/external-generation/jobs/{jobId}`:单 job 状态,用于生成页轮询某次动作。返回 `operationId`(即任务 ID)、`status`、`phaseLabel`、`phaseDetail`、`progress`、`error`、`updatedAtMicros`,以及可选、可直接展示的 `warning` 完整文案。生成页轮询只依赖状态、阶段、进度、错误和警告;`jobKind`、source 和完整时间信息继续由任务列表接口或业务快照提供。`attempt` / `maxAttempts` 属于 worker 调度事实,不向该前端契约暴露;若未来需要面向用户展示,必须单独完成产品、契约和摘要投影设计。
|
||||
|
||||
BFF 只做鉴权、授权裁剪、字段脱敏和契约映射;worker 调度、lease、执行和计费事实仍以 `external_generation_job` 为准,用户可见任务列表、单任务状态、执行阶段和通知确认的正式读取事实源为 `external_generation_job_summary`,业务结果仍以玩法 session / work profile 为准。生成页 / 进度页只展示当前玩法业务进度;用户可见任务列表放在 `我的` 页签,必要时再用单 job 状态补充排障信息,并继续按原玩法 session/detail 接口收敛到 ready 或 failed。队列接口不替代玩法恢复接口,也不把 private `request_payload_json` 原样传给前端。终态提示的弹出与否以后端 `notification_acknowledged_at` 为准;前端在提示展示后后台调用 acknowledge 接口,关闭按钮只负责收起本地弹窗,不能只靠本地 dismiss 永久吞掉任务。
|
||||
BFF 只做鉴权、授权裁剪、字段脱敏和契约映射;worker 调度、lease、执行和计费事实仍以 `external_generation_job` 为准,用户可见任务列表、单任务状态、执行阶段和通知确认的正式读取事实源为 `external_generation_job_summary`,编辑器业务结果以 `editor_project`、`editor_canvas`、`editor_project_resource` 与 `editor_asset` 为准。用户可见任务列表放在 `我的` 页签,单 job 状态用于补充轮询和排障信息,最终结果仍以编辑器项目快照收敛。队列接口不替代编辑器结果接口,也不把 private `request_payload_json` 原样传给前端。终态提示的弹出与否以后端 `notification_acknowledged_at` 为准;前端在提示展示后后台调用 acknowledge 接口,关闭按钮只负责收起本地弹窗,不能只靠本地 dismiss 永久吞掉任务。
|
||||
|
||||
## 任务表
|
||||
|
||||
@@ -66,11 +63,11 @@ BFF 只做鉴权、授权裁剪、字段脱敏和契约映射;worker 调度、
|
||||
| 字段 | 说明 |
|
||||
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `job_id` | 主键,`extgen-` 前缀 UUID |
|
||||
| `dedupe_key` | 唯一键,建议为 `play/action/session/scope` |
|
||||
| `job_kind` | 执行类型,当前覆盖 `puzzle_compile_draft`、`puzzle_generate_images`、`puzzle_generate_ui_background`、跳一跳 / 拼消消 / 敲木鱼生成动作,以及 `editor_image_generation`、`editor_image_edit`、`editor_background_removal`、`editor_icon_spritesheet_generation`、`editor_ui_design_asset_extraction`、`editor_character_animation_generation`、`editor_video_generation`、`editor_sound_effect_generation`、`editor_background_music_generation` |
|
||||
| `dedupe_key` | 唯一键,按 owner、job kind 与稳定业务键派生 |
|
||||
| `job_kind` | 执行类型,当前覆盖 `editor_image_generation`、`editor_image_edit`、`editor_background_removal`、`editor_icon_spritesheet_generation`、`editor_ui_design_asset_extraction`、`editor_character_animation_generation`、`editor_video_generation`、`editor_sound_effect_generation`、`editor_background_music_generation` |
|
||||
| `owner_user_id` | 触发用户 |
|
||||
| `source_module` | 玩法或能力名,例如 `puzzle` |
|
||||
| `source_entity_id` | session/profile/work 等作用域 |
|
||||
| `source_module` | 来源模块,当前为 `editor-canvas` |
|
||||
| `source_entity_id` | 编辑器项目等稳定业务作用域 |
|
||||
| `request_label` | 排障标签 |
|
||||
| `request_payload_json` | worker 执行入参 JSON |
|
||||
| `status` | `pending/running/completed/failed/cancelled` |
|
||||
@@ -91,7 +88,7 @@ BFF 只做鉴权、授权裁剪、字段脱敏和契约映射;worker 调度、
|
||||
|
||||
新增私有审计表 `external_generation_job_event`,记录 `enqueued/claimed/lease_renewed/completed/failed/acknowledged` 等事件。事件表只追加状态转换事实,不作为当前状态源;排障时先看 `external_generation_job` 当前状态,再按 `job_id` 追 `external_generation_job_event` 时间线。
|
||||
|
||||
另新增私有 `editor_generation_operation` durable commit receipt。它不与 `external_generation_job` 争抢任务状态:job 仍负责队列、lease、计费和通知,receipt 只固化某个 owner/kind/operation 的 request fingerprint、整笔 commit SHA-256、可选 project 以及 queue 的 job/worker/lease/result 绑定。inline 虽没有 job,也必须写 receipt;否则 API 进程重启后无法安全区分“完整提交”与“稳定 ID 巧合/历史部分记录”。
|
||||
另新增私有 `editor_generation_operation` durable commit receipt。它不与 `external_generation_job` 争抢任务状态:job 仍负责队列、lease、计费和通知,receipt 只固化某个 owner/kind/operation 的 request fingerprint、整笔 commit SHA-256、可选 project 以及 queue 的 job/worker/lease/result 绑定。inline 虽没有 job,也必须写 receipt;否则 API 进程重启后无法安全区分“完整提交”与“稳定 ID 巧合或不完整记录”。
|
||||
|
||||
索引:
|
||||
|
||||
@@ -111,7 +108,7 @@ pending/running -> cancelled (预留)
|
||||
|
||||
`claim` 只领取 `pending` 且 `available_at <= now` 的任务,或 `running` 且 `lease_expires_at <= now` 的任务。领取时递增 `attempt`、写入 `worker_id`、`started_at`、新的 `lease_expires_at` 和 `lease_token`。SpacetimeDB procedure 使用 `ctx.timestamp` 作为状态流转时间,只从 worker 入参读取“时长差值”,不信任 worker 本机绝对时间。worker 每次执行只处理自己 claim 到的任务;续租、完成或失败时必须带同一个 `worker_id + lease_token`,且当前 lease 尚未过期,防止过期 worker 覆盖新 lease。
|
||||
|
||||
玩法业务写回也必须在 SpacetimeDB 同一事务里校验 lease fencing。拼图的 `compile_puzzle_agent_draft` worker 调用、`save_puzzle_generated_images`、`save_puzzle_ui_background`、`mark_puzzle_draft_generation_failed` 和 `mark_puzzle_level_generation_failed` 在 `queue` 模式下会带 `external_generation_job_id / worker_id / lease_token`,并校验 job 仍为 `running`、token 未过期、`job_kind`、`owner_user_id`、`source_module` 和 `source_entity_id` 均匹配后才写 session / work profile。`inline` 模式不创建 `external_generation_job`,因此这三个 guard 字段必须同时为空;transaction 只把三项全空识别为 api-server 受控同步写回,三项半空仍按非法请求拒绝。worker 路径的核心业务写回失败不能返回内存快照并把 job 标为 `completed`;失败态业务回写成功后才允许把队列 job 标为 `failed`,失败态仍未写回时保留当前租约并等待后续 lease 过期重领,避免队列状态和真实 session 脱节。api-server 的资产扣费包装遇到这类 stale worker lease guard 错误时不执行补偿退款,避免旧 worker 冲掉后续合法 worker 的同一账本扣费。
|
||||
编辑器业务写回也必须在 SpacetimeDB 同一事务里校验 lease fencing。`queue` 模式下,`persist_editor_generation_result_and_return` 会携带 `external_generation_job_id / worker_id / lease_token`,并校验 job 仍为 `running`、token 未过期、`job_kind`、`owner_user_id`、`source_module` 和 `source_entity_id` 均匹配后才写正式结果。`inline` 模式不创建 `external_generation_job`,这三个 guard 字段必须同时为空;transaction 只把三项全空识别为 api-server 受控同步写回,三项半空仍按非法请求拒绝。worker 路径的结果写回失败不能返回内存快照并把 job 标为 `completed`;失败态业务回写成功后才允许把队列 job 标为 `failed`,失败态仍未写回时保留当前租约并等待后续 lease 过期重领。api-server 的资产扣费包装遇到 stale worker lease guard 错误时不执行补偿退款,避免过期 worker 冲掉后续合法 worker 的同一账本扣费。
|
||||
|
||||
## 执行模式与进程角色
|
||||
|
||||
@@ -154,51 +151,7 @@ controller 配置:
|
||||
|
||||
动态缩扩容方式:生产默认由 `deploy/systemd/genarrative-external-generation-controller.service` 启动 `GENARRATIVE_PROCESS_ROLE=external-generation-controller`,controller 读取 `get_external_generation_queue_stats_and_return` 后对 `genarrative-external-generation-worker@N.service` 执行精确 `systemctl start/stop`;无需改变 HTTP 进程数。controller 只操作 `@1..@MAX` 中的缺口或最高编号多余实例,保留 `@1` 作为保底 worker。缩容或发布重启 worker 时,进程收到 SIGINT/SIGTERM 后会停止 claim 新任务并等待当前任务完成;若进程被硬杀、机器断电或超过 systemd `TimeoutStopSec`,未完成任务会在 lease 过期后被其它 worker 重新领取。VectorEngine 图片链路会先于整个 job 执行预算停止 provider 发送 / 重试,以便 worker 在有效 lease 内完成终态写回;若其他业务 future 仍长时间无返回,执行预算到期后 worker 会停止续租并释放槽位,在途 future 继续运行至租约仲裁窗口;有效租约内的写回仍可完成,租约过期后才会由其它 worker 重新认领,避免客户端取消与服务端写回竞态。本次预算收口不改变 lease 续租 / fencing、迟到写回仲裁、attempt 耗尽收口和原子退款语义。容器链路已有独立 `external-generation-worker` compose service;扩 worker 必须扩这个 worker service,不能只扩 `api-server` HTTP service。
|
||||
|
||||
## 已接入的拼图纵切
|
||||
|
||||
### 拼图
|
||||
|
||||
`compile_puzzle_draft`:
|
||||
|
||||
1. HTTP handler 保存拼图表单草稿;`queue` 模式下 `queued/running` 的持久事实源是 `external_generation_job`,不把 HTTP 进程变成外部生成执行者。
|
||||
2. `queue` 模式下 HTTP handler 入队 `puzzle_compile_draft`,返回 `operation.status = queued` 和当前 session。拼图 dedupe key 包含本次 `extgen-` job id,只保证同一任务行唯一,不把同一 session 后续重新生成吞掉。`inline` 模式下 HTTP handler 复用同一 executor 同步执行,成功后直接返回 `completed` 和最新 session。
|
||||
3. 前端保持 `puzzle-generating`,继续轮询 `getPuzzleAgentSession`;首期不把 `queued/running` 写回 `puzzle_agent_session`,因此刷新或跨设备恢复生成中状态仍是后续 read model 工作。
|
||||
4. worker claim 后执行原有 `compile_puzzle_draft_with_initial_cover` 或 `compile_puzzle_draft_with_uploaded_cover`;前置 `compile_puzzle_agent_draft` 也必须携带本次 `job_id / worker_id / lease_token`,防止过期 worker 先把草稿卡和 session 写到 ready。
|
||||
5. 成功后沿原有 SpacetimeDB 拼图会话/作品写回,前端轮询看到 `progressPercent >= 94/96/100` 和 ready 草稿。
|
||||
6. 失败后调用 `mark_puzzle_draft_generation_failed`,拼图首期业务失败直接进入 failed;只有失败态写回成功才把队列 job 标为 failed,失败态写回失败则保留租约等待重领。队列仍保留 lease 过期后的崩溃重领,避免 worker 退款后再次成功导致钱包账本漂移。前端通过现有失败草稿/弹窗机制展示来源错误。
|
||||
|
||||
`generate_puzzle_images`:
|
||||
|
||||
1. HTTP handler 校验本次 `levelsJson` 快照;`queue` 模式下入队 `puzzle_generate_images` 并返回 `operation.status = queued/running/completed/failed`,`inline` 模式下同步执行原 worker executor 并在成功后返回 `completed`。
|
||||
2. worker 执行原结果页关卡图链路:自动命名、VectorEngine / 上传图直用、关卡场景图、UI spritesheet、关卡背景资产包、OSS 持久化和 SpacetimeDB 回写。
|
||||
3. 成功后 `save_puzzle_generated_images` 写回目标关卡和草稿卡;失败后 `mark_puzzle_level_generation_failed` 只标记目标关卡 `failed`,不污染已 ready 的其它关卡。队列 job 只有在目标关卡失败态写回成功后才进入 failed。
|
||||
4. 前端结果页对 `queued/running` 操作继续轮询 `getPuzzleAgentSession`,目标关卡变为 ready 或 failed 后收敛。
|
||||
|
||||
`generate_puzzle_ui_background`:
|
||||
|
||||
1. HTTP handler 校验本次 `levelsJson` 快照;`queue` 模式下入队 `puzzle_generate_ui_background` 并返回 `operation.status = queued/running/completed/failed`,`inline` 模式下同步执行原 worker executor 并在成功后返回 `completed`。
|
||||
2. worker 执行原结果页 UI 背景链路:归一化提示词、VectorEngine 生成、OSS 持久化和 `save_puzzle_ui_background` 写回。
|
||||
3. 成功后目标关卡写入 `uiBackgroundPrompt/uiBackgroundImageSrc/uiBackgroundImageObjectKey`;失败后复用 `mark_puzzle_level_generation_failed` 标记目标关卡 `failed`,并在失败态写回成功后才终结队列 job,让前端轮询能收敛。
|
||||
|
||||
### 跳一跳、拼消消和敲木鱼扩展范围
|
||||
|
||||
以下动作按同一 worker 模式迁移。命名以现有玩法 action 为准,队列 `job_kind` 采用后端稳定 snake_case,不新增平行队列:
|
||||
|
||||
- 跳一跳 `jump-hop`
|
||||
- `compile-draft`:草稿编译阶段需要生成地块 / 视觉资产时入队,例如 `jump_hop_compile_draft`。
|
||||
- `regenerate-tiles`:结果页地块图集重生入队,例如 `jump_hop_regenerate_tiles`。
|
||||
- 拼消消 `puzzle-clear`
|
||||
- `compile-draft`:草稿编译阶段需要生成场地底图和卡片 atlas 时入队,例如 `puzzle_clear_compile_draft`。
|
||||
- `regenerate-atlas`:结果页素材 atlas 重生入队,例如 `puzzle_clear_regenerate_atlas`。
|
||||
- 敲木鱼 `wooden-fish`
|
||||
- `compile-draft`:草稿编译阶段需要生成背景、敲击物或其它图片资产时入队,例如 `wooden_fish_compile_draft`。
|
||||
- `regenerate-hit-object`:结果页敲击物图片重生入队,例如 `wooden_fish_regenerate_hit_object`。
|
||||
|
||||
这些动作首版都保持“单动作单 job”:一次 `compile-draft` 或一次 `regenerate-*` 请求只创建一个 job,worker 内部负责该动作所需的 provider 调用、素材处理、OSS 持久化、失败态写回和业务成功写回。非外部图片生成动作,例如纯元信息保存、标签编辑、发布、试玩启动、运行态动作、删除和公开 read model 读取,继续 inline 执行。
|
||||
|
||||
每个玩法迁移时必须同时接入业务写回 lease guard:worker 路径带 `external_generation_job_id / worker_id / lease_token`,inline 路径三项同时为空。过期 worker 不得写 session / work profile;业务失败态写回成功后才允许 job 进入 `failed`。
|
||||
|
||||
### 图片画布编辑器
|
||||
## 图片画布编辑器
|
||||
|
||||
图片画布 `/editor/canvas` 下所有会调用外部生成 provider 的入口在 `queue` 模式下入 `external_generation_job`,HTTP handler 只返回 `queueState`:
|
||||
|
||||
@@ -252,8 +205,6 @@ cargo test -p spacetime-module level_generation_failure --manifest-path server-r
|
||||
cargo test -p api-server external_generation_worker --manifest-path server-rs/Cargo.toml
|
||||
cargo test -p api-server external_editor_generation --manifest-path server-rs/Cargo.toml
|
||||
cargo test -p api-server external_mcp --manifest-path server-rs/Cargo.toml
|
||||
npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx -t "keeps generation progress visible"
|
||||
npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "compile_puzzle_draft"
|
||||
```
|
||||
|
||||
本地 smoke:
|
||||
@@ -265,7 +216,7 @@ curl -f http://127.0.0.1:<api-port>/healthz
|
||||
|
||||
本地 `npm run dev` 与 `npm run dev:api-server` 默认注入 `GENARRATIVE_PROCESS_ROLE=all`,同一 Rust 进程同时监听 HTTP 并消费外部生成队列;显式设置 `GENARRATIVE_PROCESS_ROLE` 时保留显式值。需要验证生产式拆分角色、lease 重领或扩缩容时,再分别启动 `api`、`external-generation-worker` 和 `external-generation-controller`,也可以使用隔离容器 smoke。
|
||||
|
||||
生产 smoke 需要保持 `GENARRATIVE_EXTERNAL_GENERATION_MODE=queue`,并至少启动一个 `api` 角色、一个 `external-generation-worker` 角色和一个 `external-generation-controller` 角色;发布脚本会在默认 worker pattern 下自动启用并启动 `genarrative-external-generation-worker@1.service`,重启并验活 `genarrative-external-generation-controller.service`。`genarrative-api.service` 还通过 systemd `Wants=genarrative-external-generation-controller.service` 弱依赖覆盖只启动 API 的现场兜底;controller 仍是独立进程,不由 HTTP 进程内执行 `systemctl`。若 worker 数量归零,生成任务会保持 `queued/running`,不会由 HTTP 进程偷偷执行。部署验证除 `/healthz` / `/readyz` 外,还要确认任务列表 BFF 可读、未确认终态任务会弹出提示、提示展示后后台 acknowledge 且刷新后不再弹出,单 job 状态能从 `queued/running` 收敛到业务 session/detail 的 ready 或 failed。External smoke 还必须证明生成 POST 返回 `202`、同幂等键不重复创建任务、统一查询能读到 compact completed result、跨 owner 返回 `404`,并通过托管 MCP 调用同一提交/查询工具链。
|
||||
生产 smoke 需要保持 `GENARRATIVE_EXTERNAL_GENERATION_MODE=queue`,并至少启动一个 `api` 角色、一个 `external-generation-worker` 角色和一个 `external-generation-controller` 角色;发布脚本会在默认 worker pattern 下自动启用并启动 `genarrative-external-generation-worker@1.service`,重启并验活 `genarrative-external-generation-controller.service`。`genarrative-api.service` 还通过 systemd `Wants=genarrative-external-generation-controller.service` 弱依赖覆盖只启动 API 的现场兜底;controller 仍是独立进程,不由 HTTP 进程内执行 `systemctl`。若 worker 数量归零,生成任务会保持 `queued/running`,不会由 HTTP 进程偷偷执行。部署验证除 `/healthz` / `/readyz` 外,还要确认任务列表 BFF 可读、未确认终态任务会弹出提示、提示展示后后台 acknowledge 且刷新后不再弹出,单 job 状态能从 `queued/running` 收敛到编辑器项目快照中的 completed 或 failed。External smoke 还必须证明生成 POST 返回 `202`、同幂等键不重复创建任务、统一查询能读到 compact completed result、跨 owner 返回 `404`,并通过托管 MCP 调用同一提交/查询工具链。
|
||||
|
||||
systemd 生产 controller 与手动兜底示例:
|
||||
|
||||
|
||||
@@ -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。
|
||||
|
||||
@@ -488,7 +488,7 @@ dev 根盘空间在安装后曾接近满盘;2026-06-17 进入 canary 前已清
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_ACME_ROOT` | `/var/www/html` | ACME challenge 静态目录。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_MAINTENANCE_FILE` | `/var/lib/genarrative/maintenance/enabled` | 存在即进入维护模式。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_FORWARDED_PROTO` | `http` | 写入 `X-Forwarded-Proto` 的值。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_MAX_API_BODY_BYTES` | `67108864` | `/api` 通用路由的 `Content-Length` 上限。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_MAX_API_BODY_BYTES` | `220200960` | `/api` 通用路由的 `Content-Length` 上限(210 MiB,覆盖游戏发行包 PUT 的 200 MiB + 1 KiB 路由上限)。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_COMPRESSION_ALGORITHMS` | `gzip` | 当前唯一允许的压缩算法白名单;Pingora 正式化口径固定为 gzip-only,Brotli 继续由 Nginx / 前置代理承担。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_GZIP_ENABLED` | `true` | 是否启用 gzip 响应压缩。 |
|
||||
| `GENARRATIVE_PINGORA_GATEWAY_GZIP_LEVEL` | `5` | gzip 压缩等级,必须在 `0..=9`。 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# AGC 客户端更新检查与下载
|
||||
|
||||
更新时间:`2026-09-21`
|
||||
更新时间:`2026-09-22`
|
||||
|
||||
本文件是 AGC 客户端自动更新的主规范:更新能力由 Tauri 官方插件 `tauri-plugin-updater` 承担,并按下文渠道分发。
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
- 数据不跨渠道共享:本地项目、工程快照、模板、登录态、诊断日志与 Runner/项目锁按渠道身份分目录。切渠道等于换一个客户端,不迁移、不合并本地数据;渠道内的 origin 隔离规则不变。
|
||||
- 主窗口与工作区/启动器窗口标题取构建期产品名,让同机并存的渠道客户端在任务栏与 Alt-Tab 中可区分;默认渠道标题仍是「陶泥儿」。
|
||||
- 首装包与更新包的对象名包含产品名(如 `陶泥儿 Release_0.1.96_x64-setup.exe`、`陶泥儿 Release_0.1.96_aarch64.dmg`)。清单 `downloads` 地址由发布脚本按本次真实产物派生,禁止写死产品名;首装包选择按 `<版本>_<架构>.dmg` 唯一匹配,不依赖产品名字面量。
|
||||
- 产品名中的空格在清单 URL 中必须使用标准百分号编码(如 `%20`);网站服务端允许这种合法文件名编码,但仍拒绝控制字符、路径分隔符、DEL 和非法百分号编码,不得通过改写真实产物名绕过校验。
|
||||
- Windows 提权 ACL 修复助手按目录名识别安装身份:`<基线>` 与 `<基线>.<渠道>` 都在 AGC 自有的 managed 范围内;相似前缀(例如 `world.genarrative.ai-game-creator-backup`)不在范围内,落回 user-selected 范围或直接拒绝。
|
||||
|
||||
## 非目标
|
||||
@@ -135,10 +136,11 @@
|
||||
- 发布入口:`npm run ai-game-creator-shell:release:upload`(构建 + 按渠道上传);仅构建不发布的 smoke 使用 `--no-bundle` 分支,不读远端版本、不改版本、不生成清单。
|
||||
- 发布入口只解析一次目标,优先级为 CLI `--target value` / `--target=value` / `-t value`、`AGC_BUILD_TARGET`、Windows 默认值;重复/空目标与不支持目标失败关闭。版本高水位、构建 feature/渠道端点、bundle 路径、产物后缀、清单平台键及摘要必须消费同一个发布上下文,不能分别回读默认目标。
|
||||
- 渠道由 `AGC_UPDATE_CHANNEL` 显式指定,默认 dev;Windows 与 macOS 目标均支持 dev、release 和自定义渠道,目标校验独立进行。
|
||||
- 渠道 `--config` 在 Tauri 构建前最后合并,同时注入 `productName`、`identifier` 与 updater 端点:安装身份与更新端点必须来自同一个渠道,不能各自回读默认值。macOS 发布入口构建 `*.app`、updater 归档与 DMG 前先按发布渠道解析产品名,产物名一律派生而不写死。
|
||||
- 定时调度只在本轮到达的提交包含 AGC 相关路径(客户端、共享包、`server-rs/crates`、AGC 插件、桌面壳图标、根依赖清单)时才触发渠道发布;纯文档或流水线自身的提交只跑 Full Build,不推高客户端版本号。判定失败或勾选强制触发时按"需要发布"处理。
|
||||
- 更新摘要自动生成:发布脚本用渠道清单里的 `commit` 字段(上一次发布的提交)到本次提交之间、且只覆盖客户端相关路径的提交列表生成 `notes`(每条 `- 提交标题(短 SHA)`,最多 12 条、主题 80 字、整体 900 字,超出折叠或截断),同时写入旧协议清单的 `releaseNotes` 和归档文件 `release-notes.txt`。`AGC_UPDATE_RELEASE_NOTES` 非空时以手动文案为准;无法判定起点(缺少上次 `commit` 或本地没有该提交)时不写摘要。清单缺少 `commit` 时回退用上一次成功构建的 `COMMIT_HASH`(CI 通过 `AGC_UPDATE_PREVIOUS_COMMIT` 传入)作为锚点,因此首次启用摘要或更换渠道后也能立即产出摘要。锚点仍不可得(清单读取失败或没有 CI 锚点)时降级为「最近客户端改动」列表并注明可能与上一版重复 —— 摘要属于附注,任何情况下都不允许因为它让发布失败。
|
||||
- 清单里的 `commit` 是非标准字段:更新插件忽略未知字段,发布脚本用它定位下一次摘要的起点。
|
||||
- 渠道 `--config` 在 Tauri 构建前最后合并,同时注入 `productName`、`identifier`、updater 端点与窗口标题:安装身份与更新端点必须来自同一个渠道,不能各自回读默认值。macOS 发布入口构建 `*.app`、updater 归档与 DMG 前先按发布渠道解析产品名,产物名一律派生而不写死。
|
||||
- 渠道配置走 Tauri 的 JSON Merge Patch 语义:对象递归合并,**数组整体替换**。因此 `app.windows` 必须按基线 `tauri.conf.json` 的完整 client 窗口对象下发、只覆盖 `title`(脚本从基线读取后展开);任何"只写 `{ title }`"的写法都会让 `label` / `decorations` / 尺寸回落成 Tauri 默认值(`label=main`、`decorations=true`、800x600),表现为打包产物重新出现系统标题栏,并按 label 连带失效承载平台 HTTP 权限等 capability。守卫用例:`build-release.test.mjs` 的渠道配置合并用例与 `check-config.mjs` 的 `decorations` 门禁。
|
||||
- 定时调度分别判断服务端与客户端 scope:dev 小时调度在提交含 AGC 相关路径时发布对应渠道,纯文档或流水线自身的提交仍只跑 Full Build;release 每日调度在服务端相关路径变化时发布正式 Full Build,在 AGC 相关路径变化时发布 release 客户端,并在同一调度内等待、汇总各 lane 结果,失败 lane 下一轮补发。判定失败或勾选强制触发时按"需要发布"处理。
|
||||
- 更新摘要不再自动生成:发布脚本不读取提交记录生成 `notes`;只有 `AGC_UPDATE_RELEASE_NOTES` 非空时,才把显式手动文案写入渠道清单和旧协议清单的 `releaseNotes`。未设置时清单不携带更新说明,归档文件 `release-notes.txt` 记录“本次没有可用的更新摘要”。
|
||||
- 清单里的 `commit` 是非标准字段:更新插件忽略未知字段;发布脚本只为线上排障保留源码 revision,不驱动更新摘要。
|
||||
- 上传:安装包与 `.sig` 上传到 `agc/<channel>-win|mac/<version>/`,清单以 `--force` 覆盖上传到对应分区的 `latest.json`,保证 latest 指针与清单内 URL 指向已存在的对象。
|
||||
- 首装发布:发布脚本生成 `downloads`,Windows 复用已选 NSIS `.exe`,Mac 选择本次版本和目标架构匹配的非空 `.dmg`;缺失、歧义或版本/架构不匹配时失败,不发布带悬空地址的清单。上传顺序为更新包、签名及首装包全部成功后再更新渠道清单,Windows 相同对象只上传一次。`dry-run` 不写 OSS。各渠道独立写自己的清单,由 BFF 汇总,Windows 与 Mac 发布不会覆盖彼此的下载项;Mac 跨架构合并仍遵循现有单架构发布约束。
|
||||
- Jenkins 流水线需要新增渠道参数与签名凭据;签名私钥与密码只以受保护凭据注入当前进程,不写入 workspace、日志或归档产物。
|
||||
@@ -176,7 +178,7 @@
|
||||
| 安装包与清单登记一致 | 下载安装包实算 SHA-256 与尺寸后与迁移桥清单比对 | 通过(size `104678031`、sha256 `1f67…4fd0` 一致) |
|
||||
| 旧协议迁移桥 | 公网读取 `agc/latest.json` | 通过(0.1.48,`downloadUrl` 指向同一对象,含 `sha256` / `size`) |
|
||||
| 真实更新闭环(含升级后重启) | 0.1.47 客户端按提示下载安装并重启 | 通过(2026-09-17 用户实测:提示 → 下载 → 安装 → 关于页显示新版本,再次检查为已是最新) |
|
||||
| 更新摘要端到端展示 | 公网读取渠道清单 `notes` 与客户端更新提示 | 通过(2026-09-17 用户实测:0.1.62 清单带 8 条自动摘要,客户端提示正常显示多行内容) |
|
||||
| 更新摘要按显式配置写入 | `node --test apps/ai-game-creator-shell/scripts/build-release.test.mjs` | 通过(未设置 `AGC_UPDATE_RELEASE_NOTES` 时渠道清单不写入 `notes`) |
|
||||
|
||||
渠道安装身份隔离已于 `2026-09-21` 完成源码验收:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# AGC 总版本号与发号
|
||||
|
||||
更新时间:`2026-09-20`
|
||||
更新时间:`2026-09-22`
|
||||
|
||||
## 背景
|
||||
|
||||
@@ -18,7 +18,7 @@ AGC 客户端此前按「渠道各自比高水位自增」发号:`dev-win` 与
|
||||
|
||||
- `next = 总号 + 1`;总号不存在时先一次性播种,见下节。
|
||||
- 顺序固定为「先写总号 → 再构建 → 再发渠道清单」;任何一步失败都不回滚,只烧号。
|
||||
- 统一构建:发一次号,通过 `AGC_RELEASE_VERSION` 同时传给 `dev-win`、`dev-mac`(以及后续渠道),各渠道共用同一个号。
|
||||
- 统一构建:发一次号,通过 `AGC_RELEASE_VERSION` 同时传给同一渠道组的两个平台;dev 调度写 `dev-win` / `dev-mac`,每日 release 调度写 `release-win` / `release-mac`,组内共用同一个号。
|
||||
- 单渠道热修:发一次号,只传给该渠道;其他渠道清单保持原值。
|
||||
- 显式传入 `AGC_RELEASE_VERSION` 的构建不再自行发号,只做高水位断言。
|
||||
|
||||
@@ -39,8 +39,8 @@ AGC 客户端此前按「渠道各自比高水位自增」发号:`dev-win` 与
|
||||
- 发号模块:`apps/ai-game-creator-shell/scripts/agc-global-version.mjs`(读总号 / 播种 / 发号 / 写后回读 / 渠道高水位断言 / dry-run 预览)。
|
||||
- 发号入口:`apps/ai-game-creator-shell/scripts/issue-global-version.mjs`(CI 与本地共用,输出固定为 `AGC_GLOBAL_VERSION=<version>`)。
|
||||
- 构建侧:`build-release.mjs` 的 `prepareReleaseVersion()` 优先采用传入总号,未传入时现场发号;`resolveRemoteHighWaterVersion()` 降级为断言来源,只用于「请求号低于本渠道清单版本即失败关闭」。
|
||||
- CI:`jenkins/Jenkinsfile.agc-global-version-issue` + `jenkins/agc-global-version-issue-job-config.xml`;调度管线 `jenkins/Jenkinsfile.scheduled-revision-trigger` 与手动管线先调发号 Job,再把号透传给 AGC Build。
|
||||
- 发号 Job 的 Copy Artifact 采用生产权限模式,`options` 里的 `copyArtifactPermission(...)` 必须显式列出**全部**消费者:定时调度 `Genarrative-Scheduled-Revision-Trigger` 与手动发布 `Genarrative-Manual-Build-And-Deploy`。用户触发的构建按「认证用户」判权(SYSTEM 定时构建短路放行),漏列时手动发布会报 `Unable to find project for artifact copy: Genarrative-Agc-Global-Version-Issue`,且失败点在发号之后。改完该 `options` 后必须先单独跑一次发号 Job,让 Declarative Pipeline 把 Job property 写回 Jenkins。
|
||||
- CI:`jenkins/Jenkinsfile.agc-global-version-issue` + `jenkins/agc-global-version-issue-job-config.xml`;dev 调度管线 `jenkins/Jenkinsfile.scheduled-revision-trigger`、每日 release 调度管线 `jenkins/Jenkinsfile.scheduled-release-trigger` 与手动管线先调发号 Job,再把号透传给 AGC Build;release 调度的服务端 Full Build 不使用 AGC 总号,只使用固定 `COMMIT_HASH` 与 Full Build 自身版本。
|
||||
- 发号 Job 的 Copy Artifact 采用生产权限模式,`options` 里的 `copyArtifactPermission(...)` 必须显式列出**全部**消费者:小时 dev 调度 `Genarrative-Scheduled-Revision-Trigger`、每日 release 调度 `Genarrative-Scheduled-Release-Trigger` 与手动发布 `Genarrative-Manual-Build-And-Deploy`。用户触发的构建按「认证用户」判权(SYSTEM 定时构建短路放行),漏列时手动发布会报 `Unable to find project for artifact copy: Genarrative-Agc-Global-Version-Issue`,且失败点在发号之后。改完该 `options` 后必须先单独跑一次发号 Job,让 Declarative Pipeline 把 Job property 写回 Jenkins。
|
||||
|
||||
## 不改的东西
|
||||
|
||||
|
||||
@@ -116,7 +116,10 @@ templates/
|
||||
- `src/features/template-library/templateLibraryModel.ts`:清单类型、搜索(空白分隔多关键词「与」)、标签/运行时/已下载筛选、标签选项聚合、体积格式化等纯函数。
|
||||
- `src/features/template-library/useTemplateLibrary.ts`:一次拉清单,暴露筛选状态、下载与「用模板建项目」;下载成功后只就地更新该条目的已下载状态。
|
||||
- `src/view/template-library/index.tsx`:模板库全屏页(返回、刷新、搜索、运行时/标签筛选、仅看已下载、卡片显示封面与已下载徽标、下载/使用模板)。
|
||||
- 筛选区拆两行:第一行是共享筛选条 `PlatformResourceFilterBar`(搜索框 + 运行时分段)与靠右的「仅看已下载 / 清除筛选」,第二行是标签 chip(带命中数量,换行排布、`max-h-[20vh]` 上限内滚动)。
|
||||
- 筛选控件的两态口径(模板库、资源画布、参考图弹窗共用):**未选 = 浅底描边 + 常规文字,选中 = 实心品牌填充 + 反白文字**,两态填充对比 ≥ 3:1、标签文字在选中填充上 ≥ 4.5:1(由 `tests/workbenchThemeContrast.test.ts` 钉住)。运行时分段用 `PlatformSegmentedTabs` 的 `tone="accent"`,与标签 chip 共用同一组 `--platform-chip-active-*` 语义色,不再出现「选中只换了一点点暖色」的弱状态。
|
||||
- 卡片动作按安装状态收口:已下载且版本一致时**不再显示下载入口**,只留「使用模板」;版本落后才显示「更新」;缺包显示「下载」。
|
||||
- 忙状态写在**触发它的那个按钮**上(下载中 / 创建中,按钮就地换图标与文案),动作行里不额外塞状态文本:最小卡宽(250px)下「使用模板 + 下载/更新 + 状态文本」三个元素会把按钮文案挤成两行并顶出卡片。
|
||||
- 过程提示(下载完成、开始建项目)走浮层 toast(复用 `packages/shared` 的 `PlatformRuntimeStatusToast`,`document.body` 浮层 + 2.6 秒自动消失),不再占用页面内位置;页面内只保留可操作的错误与空态。
|
||||
- 首页「灵感推荐」替换为「模板库」推荐位(`src/view/home/TemplateRecommendations.tsx`):只展示封面、标题、运行时与已下载徽标,点击进入模板库页面;首页不再直接触发建项目。
|
||||
- 左侧导航新增模板库入口(`LauncherView = 'template-library'`)。
|
||||
@@ -164,14 +167,15 @@ AGC_TEMPLATE_LIBRARY_SYNTHETIC_COUNT=300 AGC_DEV_CARGO_FEATURES=template-library
|
||||
### 卡片列表虚拟滚动(react-window)
|
||||
|
||||
- 列表改用 workspace 里已有的 `react-window@1.8.11` 的 `FixedSizeGrid`(`react-arborist` 已在用同一版本,不引入新包;类型来自 devDependency `@types/react-window`)。
|
||||
- 布局契约收在纯函数 `templateLibraryGrid.ts`(单测覆盖):列数 = `floor((容器宽 + gap) / (最小卡宽 + gap))`、列宽 = 容器宽 / 列数、行高 = `卡片宽 × 9/16 + 文字区 150 + gap`;`buildTemplateRows` 按行切分并在行尾补 `null` 占位。
|
||||
- 布局契约收在纯函数 `templateLibraryGrid.ts`(单测覆盖):列数 = `floor((容器宽 + gap) / (最小卡宽 + gap))`、列宽 = 容器宽 / 列数、行高 = `卡片宽 × 9/16 + 文字区 174 + gap`;`buildTemplateRows` 按行切分并在行尾补 `null` 占位。
|
||||
- **卡片文字区行高契约**:文字区 174 = 内边距 12×2 + 标题 20(`h-5`)+ 元信息 16(`h-4`)+ 简介 32(`h-8`,两行)+ 标签 22(`h-5.5`)+ 按钮行 28(`h-7`)+ 行距 8×4;这些分项在 `templateLibraryGrid.ts` 里各有一个常量,`TemplateCard` 用同一组固定高度 + `shrink-0` 渲染。**不要**再把文字区写成 `grid` 的 auto 行:auto 行按 max-content 计高,多行文字只按一行算,标题 / 简介 / 标签会被逐行裁掉。
|
||||
- 卡片抽成 `TemplateCard`(`memo`),网格只渲染可视行 + 2 行 overscan;筛选条件(关键词/标签/运行时/仅看已下载)变化时把滚动位置复位到顶部,避免"从筛选切回全量后停在空白处"。
|
||||
- **页面高度契约**:页面根节点的高度按**父级 `.launcher-main` 的实测高度**内联设置,既不用百分比也不用 `100vh`。原因:外壳样式 `.launcher-main > .platform-theme { height: 100% }` 特异性高于 Tailwind 工具类,而这条百分比在 `.launcher-shell { min-height: 100vh }` 链路上是不定高,页面会退化成内容高度(虚拟网格视口高度 0、卡片区整片空白);`100vh` 又比真实舞台高一个标题栏高度(窗口 100vh=800 / 舞台 750),底部会被裁掉。
|
||||
- 筛选区(运行时/标签)改成可独立滚动的区块(`max-h-[24vh]`),标签数量随库量增长时不再把卡片区挤出窗口。
|
||||
- 筛选区(运行时/标签)在窗口变窄时整体换行,标签行单独限高(`max-h-[20vh]` 内滚动),标签数量随库量增长时不再把卡片区挤出窗口。
|
||||
- 回归:`templateLibraryGrid.test.ts` 覆盖列数/行高/行数/切行;页面测试用固定视口断言「1000 条只渲染 ≤ 40 张卡片,滚动高度仍按 250 行计算」。
|
||||
|
||||
- 页面能正常渲染 1000 张卡片(头部显示「共 1000 个模板 · 已下载 335 个」),并且滚动容器生效(窗口高度压到 430px 时右侧出现滚动条,页面内容被裁切而不是溢出到窗口外)。
|
||||
- 需要后续收口的两点(本次未改):① 标签筛选条随库量膨胀——1000 条时聚合出 35 个标签、占三行;② 一次性渲染 1000 个卡片节点并触发 1000 次封面请求。建议标签只展示 Top N + 「更多」,卡片列表加分页或虚拟滚动。
|
||||
- 仍需关注:① 标签筛选条随库量膨胀——1000 条时聚合出 35 个标签;现为「换行 + `max-h-[20vh]` 滚动」兜底,量大时仍建议只展示 Top N + 「更多」;② 一次性渲染 1000 个卡片节点并触发 1000 次封面请求,建议加封面懒加载上限或分页。
|
||||
- 前端回归:1000 条渲染 + 已安装过滤(334)/标签过滤(50)/关键词过滤数量自洽,见 `apps/ai-game-creator-shell/tests/templateLibraryView.test.tsx`。
|
||||
|
||||
```bash
|
||||
|
||||
@@ -122,6 +122,8 @@ host.rpc(method, params)
|
||||
|
||||
`EditorAdapter` 契约位于通用 crate `server-rs/crates/editor-adapter-api`,只定义 `detect`、`connect`、`disconnect`、`translate_rpc` 和原生 `rpc`。宿主只保存适配器 registry,并把插件声明的适配器名称路由到对应实现;具体编辑器如何查找进程、校验 PID/项目/版本、建立连接和翻译编辑器消息,由插件包自带模块实现。
|
||||
|
||||
宿主注册方法只在实际链接编辑器的 feature 或测试编译中存在:Cocos 对应 Windows 的 `cocos-editor-execute`,Runner 托管的 Unity/Godot 对应 Windows x64 的各自 execute feature。未启用这些 feature 的默认构建不编译专用适配器及其导入。插件操作统一通过 `host.rpc` 调用适配器的 `rpc`;没有调用方的宿主 detect/connect/disconnect/translate 包装不作为兼容接口保留,trait 方法、项目切换和禁用清理继续按现役合同执行。
|
||||
|
||||
宿主源码不包含编辑器专属进程名、注入逻辑或 Tauri 命令。第一个适配器 `cocos-editor` 由 `plugins/agc-cocos-editor` 提供:native 模块实现 `EditorAdapter`,由 `editor_adapters.rs` 在启动时按编译期链接注册。新增适配器不会改变 Plugin 生命周期、SDK 或权限协议。
|
||||
|
||||
当前 native 适配器仍由宿主在编译期链接(Cargo path 依赖);动态加载插件 native 模块不在本次范围,插件包格式与宿主协议不受此限制。
|
||||
|
||||
@@ -361,7 +361,7 @@ npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> -
|
||||
- 历史账本曾在下一固定窗口合并旧账本和新里程碑,并用 `runtime.context` / `runtime.milestones` 代替部分普通 observation。
|
||||
- checkpoint 内容 diff 与 Git 工作树 diff 使用两个独立保护槽。后续 `git.inspect` 不得再挤掉已完成 `project.diff` 的 checkpointId/hunk,反之亦然;两类大 detail 仍共同受 128 KiB context bundle 总上限约束。
|
||||
|
||||
当时修复后的真实 `gpt-5.5` 回归在 10 轮内完成并收束,唯一 spawn / patchset / join 均保持 1 次,两次 Git 审阅和两类 diff 同时留在最终 context bundle,重复副作用为 0。当前 Runtime 每 6 轮只做进度 checkpoint 与停滞检测,完整 observation 继续保留在私有 bundle;真正摘要只由 V1.21 token 阈值或显式 `/compact` 触发,副作用去重继续以规范 action receipt 与各类 durable barrier 为准。
|
||||
当时修复后的真实 `gpt-5.5` 回归在 10 轮内完成并收束,唯一 spawn / patchset / join 均保持 1 次,两次 Git 审阅和两类 diff 同时留在最终 context bundle,重复副作用为 0。当前 Runtime 每 6 轮只做进度 checkpoint 与停滞检测,完整 observation 继续保留在私有 bundle;真正摘要只由 V1.21 token 阈值或显式手动压缩触发,副作用去重继续以规范 action receipt 与各类 durable barrier 为准。
|
||||
|
||||
## V1.6 持久动作回执与模型回查
|
||||
|
||||
@@ -661,21 +661,6 @@ V1.14 对标 `codex fork`,允许开发者从任意已有静态 Agent 会话创
|
||||
|
||||
确定性验收必须覆盖 active / archived / legacy 源、空会话、消息与 messageId 精确复制、源与分叉后续隔离、provenance 持久化、运行中父任务和委派 child 阻断、非 active 源任务阻断、损坏 task journal 失败关闭、默认 Session Runtime 入队与分叉线性化、未提交分叉文件不可见、非法源 ID、catalog 写入失败清理以及重复点击创建不同 Session。前端测试必须证明按钮调用精确源 Session、成功后加载复制历史并切换 active、后续消息写入新 Session 且源会话不变、归档源可分叉、Runtime 忙时按钮禁用。
|
||||
|
||||
## V1.15 Agent Swarm 纯聊天验证入口
|
||||
|
||||
V1.15 新增不依赖 Tauri WebView 或正常客户端 GUI 的终端聊天入口,用于开发阶段直接验证多 Agent 协作。入口固定为 `--swarm-chat [--init] <本地项目绝对路径> [parentAgentId]`;省略 `parentAgentId` 时固定使用 `project-supervisor`,推荐通过 `npm run agc:chat -- --config-dir <项目外 AppData 绝对路径> [--init] <project>` 启动总控聊天。需要直接调试其他父 Agent 时仍可使用 `npm run agc:swarm -- --config-dir <项目外 AppData 绝对路径> [--init] <project> <parentAgentId>`。它不是新的 Agent 实现:每条普通输入都投递给现有父 Agent background Runtime,继续由同一发布二进制的 External Runner 执行;不得退化到一次性 `--agent-chat`,也不得新建本地 HTTP 服务、旁路 Provider 客户端或第二套持久化。
|
||||
|
||||
- 首版复用父 Agent 当前 active Session;Runtime 继续把 user / assistant 写入 `.agent/conversations/agents/<agentId>/sessions/<sessionId>.jsonl`,静态委派、动态 `child-*`、私有记忆、项目黑板、durable action、verification gate 和 all-join 均沿用现有身份与恢复语义。`--init` 只复用现有项目初始化函数;Runtime 写命令仍强制显式传项目外 `--config-dir`。入口启动和一轮准备收束前都执行现有 resume / reconciliation 扫描,不能只凭 idle 快照跳过尚未发布的 receipt 或 join 修复。
|
||||
- 终端只提供聊天所需的轻量控制命令:`/help`、`/agents`、`/status`、`/history`、`/quit`。空闲时普通文本创建父 Agent 新 run;父 Agent run 仍处于 pending / running 时普通文本追加为同一 run steer,只有 child 忙而父 Agent 已终态时拒绝吞掉输入并要求稍后重发。确认动作在终端显示 Agent、run、action、tool 和安全摘要,并接受 `approve / reject`,分别调用现有 confirm / reject Runtime 路径,不能要求回到开发窗口。stdin 由独立读取线程投递,因此活跃 run 中 `/quit`、EOF、状态命令和 steer 仍可响应;退出只结束观察客户端。
|
||||
- 每轮轮询 `read_game_creator_agent_runtimes_at`,按 Agent / run / event 去重输出状态、phase、委派来源、父 Agent、delegationId、动态 child 和 join / receipt 事件。Provider token delta 当前没有经过 Runner RPC 暴露,首版只承诺 Runtime 状态与事件的持续输出以及持久化后的最终父 Agent 回复,禁止用拆字或延时打印伪装 token streaming。
|
||||
- 一轮只有在所有已发现 Runtime 都不处于 `pending / running / waiting-for-confirmation / cancelling / needs-reconciliation`,全部任务队列为空,并持续经过稳定观察窗口后才能收束。父 run 暂时 idle 但 delegated child 尚未终态、receipt 尚未入队或 all-join 尚未认领时不得提前返回。失败、取消和 reconciliation 要明确显示并保留项目现场,不自动重试副作用。
|
||||
- 每轮进入 `settled` 或 `needs-reconciliation` 终态后,终端必须额外输出且只输出一条 `[turn.report] <单行 JSON>`,schema 固定为 `game-creator-swarm-turn-report.v1`。报告只从本轮 authoritative conversation 与 Runtime snapshot 计算,白名单字段至少包含 outcome、父 Agent/Session/run 身份、Runtime 忙闲数量、四类任务队列计数、新增 assistant 数量、最终回复字符数和 reconciliation Agent 数量;不得包含项目路径、对话/任务/回复正文、observation、prompt、event detail、隐藏 thinking、Provider payload、凭据或本地存储路径。该行用于开发终端和真实 E2E 定位一轮边界,不替代 task/event/delivery/claim/receipt/conversation 等持久事实;`/quit` 不伪造 turn report。
|
||||
- 终端退出只结束观察客户端,不终止 External Runner、已投递 run 或 Runner-owned process session;下次启动先调用现有 resume,再从 conversation 与 Runtime journal 恢复。首版只允许一个前台输入流,不承诺多个终端并发编辑同一 active Session。
|
||||
|
||||
确定性验收必须覆盖 CLI parse、项目绝对路径与 `--config-dir` 门禁、`--init`、空输入和 EOF、命令分流、历史恢复、连续两轮写入同一 Session、状态与事件去重、两个静态 Agent 并行委派、多个隔离 child 并行与唯一 all-join、confirm / reject、父 Agent receipt 汇总、稳定窗口不早退、Runner / 终端重启恢复以及失败与 reconciliation 显示。真实 Provider 验收必须保存一份脱敏 transcript,并以 task / event / Agent DB / receipt / conversation 的结构化事实证明并行、最终父回复唯一、副作用无重放和密钥零泄漏;未实际运行时只能标记未验收,不能凭确定性测试宣称 swarm 可用。
|
||||
|
||||
2026-07-14 首轮真实 `gpt-5.5` 验证已证明终端入口能够启动真实 External Runner、持久化父 Session、实时展示状态 / event / parent / delegation、并行运行 `design-foundation` 与 `balance-seed`,并在终端完成两次 `agent.delegate` approve、一次重复委派 reject、重启恢复、receipt 续跑、`file.write` reject 和活跃 run 中 `/quit`。独立收束复验在同一 `code-prototype` Session 连续完成 4 轮固定回复,重启后 `/history` 读取 8 条 user / assistant 消息,最后一轮按 `idle -> 安静窗口 -> receipt/join 恢复扫描 -> 安静窗口 -> 最终回复` 返回 `FOURTH_OK`。但端到端 swarm 汇总未通过:第一轮父 Agent 反复调用全量 `agent.run_status`,因输出截断无法看到目标 Agent,18 轮后 `budget-exhausted` 并压掉两条排队 receipt;第二轮按 receipt 模式续跑时,父 Agent 没有恢复原始“只读汇总”目标,转而读取项目并请求写 `game/balance.json`,已由终端拒绝。当前结论只能是“V1.15 验证入口可用、现有静态委派的父回执汇总策略未验收”,不得标记完整 Agent Swarm 通过;后续需修复定向状态查询或 receipt continuation 原目标恢复后再跑唯一最终父回复验收。动态 isolated child / all-join 也仍待通过该入口真实复验。
|
||||
|
||||
## V1.16 Project Supervisor 总控 Agent
|
||||
|
||||
V1.16 把正式用户主聊天从一次性自然语言问答升级为现有 External Runner 中的根协调 Agent。规范 Runtime ID 固定为 `project-supervisor`,显示名为“项目总控 Agent”;它不是 manifest 任务、专业组角色或 isolated spawn 模板,不加入 `GAME_CREATOR_AGENT_GROUP_DEFINITIONS`。恢复扫描必须固定包含该 ID。LLM 首选 `agentLlm.project-supervisor`,发布 AppData 仍只有旧 `agentLlm.chat` 时把它作为兼容回退并继续继承全局配置,不复制或暴露 API Key。
|
||||
@@ -767,7 +752,7 @@ OpenAI Chat / Responses 的 strict function schema 顶层固定为 `thinkingSumm
|
||||
|
||||
## V1.18 单 Agent 持久 Goal mode
|
||||
|
||||
V1.18 对标 Codex CLI `/goal` 的长任务语义:目标文本既是首轮任务,也是后续完成判断的上层标准。Goal 不是 `currentGoal` 的展示别名,也不建立第二套 Runner;它绑定一个 Agent active Session 和同一 run,复用现有持久计划、steer、工具策略、确认、verification gate、context bundle、finalization 与 External Runner。
|
||||
V1.18 的持久 Goal 长任务语义:目标文本既是首轮任务,也是后续完成判断的上层标准。Goal 不是 `currentGoal` 的展示别名,也不建立第二套 Runner;它绑定一个 Agent active Session 和同一 run,复用现有持久计划、steer、工具策略、确认、verification gate、context bundle、finalization 与 External Runner。
|
||||
|
||||
### Goal 身份与持久化
|
||||
|
||||
@@ -777,7 +762,7 @@ V1.18 对标 Codex CLI `/goal` 的长任务语义:目标文本既是首轮任
|
||||
|
||||
### 启动、编辑与运行隔离
|
||||
|
||||
- `/goal <文本>`、Tauri start command 或 `--agent-goal-start [--init] <project> <agent> <session> <run> --stdin` 创建 Goal 并用同一 outcome 启动首个 background run;CLI 的 `--init` 只在 manifest 缺失时初始化一次性/新项目,不借道其它 Agent task。未显式提供 verification 时,outcome 自身作为完成标准。Goal 活跃或暂停期间,当前 Session 禁止另起不相关 run;后续普通输入默认继续走同 run steer,独立任务应使用另一 Session。
|
||||
- Tauri start command 或 `--agent-goal-start [--init] <project> <agent> <session> <run> --stdin` 创建 Goal 并用同一 outcome 启动首个 background run;CLI 的 `--init` 只在 manifest 缺失时初始化一次性/新项目,不借道其它 Agent task。未显式提供 verification 时,outcome 自身作为完成标准。Goal 活跃或暂停期间,当前 Session 禁止另起不相关 run;后续普通输入默认继续走同 run steer,独立任务应使用另一 Session。
|
||||
- 编辑 Goal 先在项目写锁内提交 revision,再把规范化的新目标作为同 run steer 持久化。Provider 正在 planning 时允许中断;确认中或工具执行中只排队,旧动作在下一安全边界前必须校验 Goal revision,不能在目标已变更后继续执行。旧自动动作或待确认动作若绑定旧 Goal 快照,统一转成 `blocked` observation 并在同一 run 重规划,不执行旧副作用,也不创建 retry run。编辑失败不得回退已提交 revision,Runtime 会以 sidecar 为事实源重规划并拒绝旧 finalization。
|
||||
- Goal 内容进入每轮 planning/final reply 的显式“持久目标”上下文。模型仍通过 V1.17 `planUpdate` 维护可观察步骤;Goal revision 不推进 project revision、不改变权限或 verification gate,也不能放宽 sandbox/approval。
|
||||
|
||||
@@ -798,7 +783,7 @@ V1.18 对标 Codex CLI `/goal` 的长任务语义:目标文本既是首轮任
|
||||
|
||||
### 控制面与验收
|
||||
|
||||
- 纯聊天入口支持 `/goal <文本>`、`/goal status`、`/goal pause`、`/goal resume`、`/goal edit <文本>`、`/goal clear`;开发 Agent UI 使用 `执行 / 聊天 / 目标` 三段模式,Goal 创建/编辑通过独立弹层提交,并在状态行显示 outcome、revision、状态与完成标准,提供暂停/恢复/清理。普通用户 Supervisor 首页不暴露开发 Goal 管理控件。
|
||||
- 开发 Agent UI 使用 `执行 / 聊天 / 目标` 三段模式,Goal 创建/编辑通过独立弹层提交,并在状态行显示 outcome、revision、状态与完成标准,提供暂停/恢复/清理;CLI 通过 `--agent-goal-status`、`--agent-goal-start`、`--agent-goal-edit`、`--agent-goal-pause`、`--agent-goal-resume`、`--agent-goal-clear` 管理同一 Goal。普通用户 Supervisor 首页不暴露开发 Goal 管理控件。
|
||||
- background planning / final reply 的专用 Provider 客户端强制 `max_retries=0`;每个 `agent.runtime.provider_request.lifecycle` 从 `started` 到唯一 `completed / failed / interrupted` 最多对应一次物理请求。`Timeout / Connectivity / Transport / EmptyResponse / 408 / 429 / 5xx` 以及无法证明请求未被上游接收的其它错误,不得在同一 lifecycle 内自动原样重放;只记录 error kind、SHA-256、字符数或脱敏摘要。显式 steer、Goal resume 或人工 reconciliation 决定再次调用时,必须使用新的 request slot/lifecycle;格式修复同样使用 `loop-<n>-repair-<m>` 新 slot,不能伪装成底层 retry。
|
||||
- 每次 request snapshot 固定绑定 `projectId / agentId / taskId / sessionId / runId / source / goalId / goalRevision / goalSnapshotFingerprint / appliedSteerCursor / requestKind / requestSlot`,requestId 从该闭集稳定派生。真正进入 Provider future 前,Runtime 在同一项目写锁内重读 task/Runtime 身份、queued steer、cancel tombstone、规范 Goal 状态与快照;已生效控制只返回未启动,不得写伪 `started`。Provider lifecycle 的生产字段闭集只允许 `recordType / auditSchemaVersion / agentId / taskId / sessionId / runId / source / requestId / requestKind / requestSlot / status`,持久层只可再添加统一 `schemaVersion / updatedAt` envelope;不包含 prompt、工具输入、URL、模型、回复或错误正文。
|
||||
- 启动新请求前必须在 Agent DB 锁内全量扫描同 Agent/run 的 Provider lifecycle,不依赖 recent tail。只要发现 `started` 后没有可信唯一终态,就把原 run/task/state 收束到 `needs-reconciliation` orphan barrier,阻断后续 Provider、工具和 finalization;同 request 多终态、缺 started、物理顺序倒置、重复阶段、身份/字段冲突或额外生产字段同样失败关闭,禁止自动补发。paused Runner 重启窗口必须以 started 数量零增长证明没有暗中请求,不能只看 plan/action 是否落盘。
|
||||
@@ -819,7 +804,7 @@ V1.19 对标 Codex 富客户端的增量 turn 事件:工具开始、完成和
|
||||
### 流身份与私有快照
|
||||
|
||||
- 新增 `game-creator-runtime-response-stream.v1` 私有快照,路径固定为 `.agent/runtime/response-streams/<agentHash>/<runHash>.json`,两个 hash 都取稳定身份 SHA-256 十六进制前 32 位。记录绑定 `agentId / taskId / sessionId / runId / requestKind=final-reply / requestSlot / appliedSteerCursor / responseRevision`,并保存单调 `sequence`、`status=streaming|ready|committed|discarded|failed`、`accumulatedText`、可选 `finishReason` 和时间。正文最多 32000 字符;路径、标识、schema、状态、sequence 和正文限制任一不合法时只关闭该展示流,不能把不可信内容显示给用户或据此恢复 Runtime。
|
||||
- 流快照是可丢失的本地展示缓存,不是 assistant、Provider lifecycle、任务完成或 finalization 的事实源。写入采用同路径原子替换并允许节流;Tauri 关闭、CLI 断线或单次快照写失败不能让已经可靠完成的 Provider 请求失败。`AgentRuntimeResult.responseStream` 只在快照与当前 Runtime 的 Agent/Session/run、`phase=response|finalizing|completed`、steer cursor 和请求身份一致时返回。
|
||||
- 流快照是可丢失的本地展示缓存,不是 assistant、Provider lifecycle、任务完成或 finalization 的事实源。写入采用同路径原子替换并允许节流;Tauri 关闭、客户端断线或单次快照写失败不能让已经可靠完成的 Provider 请求失败。`AgentRuntimeResult.responseStream` 只在快照与当前 Runtime 的 Agent/Session/run、`phase=response|finalizing|completed`、steer cursor 和请求身份一致时返回。
|
||||
- 开始新的 final-reply request slot 时先写空 `streaming` 快照。SSE delta 只在经过增量 `<think>...</think>` 过滤后追加;标记可跨 chunk,未闭合 thinking 永不外显。sequence 只随公开 accumulated text 或 finish reason 的真实变化增加。Provider 完整返回后用最终 `strip_llm_thinking_blocks` 结果校准为 `ready`,确保草稿与最终候选一致。
|
||||
|
||||
### Provider、控制与 finalization 边界
|
||||
@@ -829,14 +814,14 @@ V1.19 对标 Codex 富客户端的增量 turn 事件:工具开始、完成和
|
||||
- 完整候选仍必须通过 verification、plan、Goal、process/join/delegate 和项目 revision 门禁。`finish_game_creator_agent_background_runtime_turn_at` 仍是唯一 finalization 入口;只有 assistant 已按稳定 messageId 恰好一次写入并完成 Runtime 投影后,快照才可标记 `committed`。失败消息和 `plan.response` fallback 必须覆盖为其实际候选,不能保留不同 Provider 草稿。
|
||||
- 公共 event、Agent DB、receipt、activity/output 和报告不得复制 delta 或 accumulated text,只记录流身份、状态、sequence、字符数和 SHA-256。conversation、finalization、Runtime task/state 和 response-stream 都是本地私有事实面,可保存 canonical 最终正文;其中 response-stream 只是可丢失候选缓存,且不得保存 API Key、请求头、URL、模型 thinking、工具计划或原始 Provider error。
|
||||
|
||||
### 客户端与 CLI
|
||||
### 客户端
|
||||
|
||||
- 普通 Project Supervisor 聊天把匹配的 `streaming|ready` 快照渲染成一条 `runtimeOwned` 临时 assistant 消息;刷新、窗口重开和 Tauri event 丢失时由现有 750ms Runtime 轮询恢复。`committed` 后以 conversation 中的规范 assistant 替换草稿,不把临时消息写回 legacy project conversation 或 Agent Session。
|
||||
- `agc:chat` / `agc:swarm` 按 accumulated text 前缀增量打印 UTF-8 suffix;新 request slot、非前缀校准或 reconnect 要明确重置。已经完整流出的父回复在 settle 时只补完成换行/状态,不再整段重复打印。`/status` 只显示流状态、sequence 和字符数,不显示隐藏 planning 或 thinking。
|
||||
- 开发窗口按 accumulated text 前缀增量打印 UTF-8 suffix;新 request slot、非前缀校准或 reconnect 要明确重置。已经完整流出的父回复在 settle 时只补完成换行/状态,不再整段重复打印。流式状态行只显示流状态、sequence 和字符数,不显示隐藏 planning 或 thinking。
|
||||
|
||||
### 验收口径
|
||||
|
||||
- 确定性测试覆盖 Chat / Responses SSE 至少两个真实 delta、chunk 边界 thinking 过滤、sequence 单调、32K 上限、损坏/错身份快照不显示、Tauri 轮询恢复、CLI suffix/reconnect/非前缀重置、steer/取消/失败旧流失效、非流配置单次 ready、finalization 后唯一 assistant 与 committed 精确一致,以及公共持久面零正文。
|
||||
- 确定性测试覆盖 Chat / Responses SSE 至少两个真实 delta、chunk 边界 thinking 过滤、sequence 单调、32K 上限、损坏/错身份快照不显示、Tauri 轮询恢复、suffix/reconnect/非前缀重置、steer/取消/失败旧流失效、非流配置单次 ready、finalization 后唯一 assistant 与 committed 精确一致,以及公共持久面零正文。
|
||||
- 真实 Provider 使用一次性项目和独立 AppData,把目标 Agent 的 `stream=true`,证明首次公开 delta 发生在 Provider/finalization 终态之前、至少两个非空增量可观察、最终 conversation assistant 与 ready/committed 全文一致、同一 lifecycle 不发生应用层重试,并扫描密钥、thinking canary、项目绝对路径和 delta 正文在 event、Agent DB、receipt、activity/output 与报告等公共面泄漏为 0。上游物理请求数无法直接观测时,必须明确记录证明模式,不能把 lifecycle 计数冒充网络请求计数。
|
||||
- 2026-07-15 真实 `gpt-5.5` `response-stream` suite 已 PASS:隔离 AppData 只以 hardlink 读取正式配置并使用无密钥 `stream=true` overlay,正式配置 CLI 调用为 0、源 Runner endpoint 未变化。39 个不同非空 streaming 快照先于终态,sequence 从 1 单调推进到 418,最终以 425 committed;canonical 正文 883 字,conversation 恰好 1 条 user 和 1 条 assistant,final-reply lifecycle 恰好 1 组 `started -> completed`,fallback replay、重复 message/receipt 均为 0。该次上游物理请求计数未直接观测,证明模式为 lifecycle slot 与 canonical response identity 交叉核对。公共正文、API Key、thinking、诱饵、项目绝对路径及 transcript/report 路径泄漏均为 0;隔离 Runner 由 Linux pidfd 精确停止,AppData 和一次性项目按 sentinel 清理。
|
||||
|
||||
@@ -874,7 +859,7 @@ V1.20 对标 Codex CLI 的可选 Web Search,但只声明当前 `platform-llm`
|
||||
|
||||
## V1.21 单 Agent token-aware 持久上下文压缩
|
||||
|
||||
V1.21 对标 Codex CLI 的 `model_context_window`、`model_auto_compact_token_limit`、`tool_output_token_limit` 和 `/compact`。它替换“固定保留最近 12 条就算压缩”的能力口径,但不删除原始 conversation、task、event 或工具事实,也不把模型摘要提升为 Goal、计划、权限、验证或副作用事实源。
|
||||
V1.21 对标 Codex CLI 的 `model_context_window`、`model_auto_compact_token_limit`、`tool_output_token_limit` 和显式手动压缩。它替换“固定保留最近 12 条就算压缩”的能力口径,但不删除原始 conversation、task、event 或工具事实,也不把模型摘要提升为 Goal、计划、权限、验证或副作用事实源。
|
||||
|
||||
### 配置与预算
|
||||
|
||||
@@ -899,18 +884,18 @@ V1.21 对标 Codex CLI 的 `model_context_window`、`model_auto_compact_token_li
|
||||
### 自动与手动入口
|
||||
|
||||
- 每次 background tool-plan 构建后先计算输入估算。超过解析后的 `autoCompactTokenLimit` 时,在同 Agent/Session/run 的安全 planning 边界压缩可压缩 prefix,重建请求并再次估算;重建后仍超阈值或没有新的可压缩 prefix 时失败关闭并给出配置/新 Session 建议,不能继续发送已知超限请求。
|
||||
- `agc:chat` / `agc:swarm` 新增 `/compact`,开发 Agent 窗口提供同一动作和状态。手动压缩只允许当前 Agent active Session 没有 in-flight Provider、执行中工具、待确认动作或未收束 Runtime 时进行;有活动 run 时由自动安全边界处理,不能从 UI 直接打断副作用。正式用户 Project Supervisor 页面不增加压缩按钮。
|
||||
- `/status` 和开发面板展示 `estimatedInputTokens / autoCompactTokenLimit / lastPromptTokens / lastCompletionTokens / compactionRevision / lastCompactedAt`。手动和自动都写相同的哈希/计数审计,公共 event、Agent DB、receipt、activity/output 和报告不得出现 summary、原 conversation/observation、任务、路径或凭据正文。
|
||||
- 显式手动压缩入口为 `--agent-context-compact`,开发 Agent 面板展示压缩状态。手动压缩只允许当前 Agent active Session 没有 in-flight Provider、执行中工具、待确认动作或未收束 Runtime 时进行;有活动 run 时由自动安全边界处理,不能从 UI 直接打断副作用。正式用户 Project Supervisor 页面不增加压缩按钮。
|
||||
- 终端流式状态行和开发面板展示 `estimatedInputTokens / autoCompactTokenLimit / lastPromptTokens / lastCompletionTokens / compactionRevision / lastCompactedAt`。手动和自动都写相同的哈希/计数审计,公共 event、Agent DB、receipt、activity/output 和报告不得出现 summary、原 conversation/observation、任务、路径或凭据正文。
|
||||
|
||||
### 验收口径
|
||||
|
||||
- 确定性测试覆盖配置默认值与 per-Agent 继承、预算非法组合、token 估算包含 function schema、工具输出限额、自动阈值、手动 `/compact`、最近 tail 保留、同源幂等、追加后 revision 单调、conversation/observation 前缀篡改失败关闭、sidecar/bundle 身份冲突、summary 上限和公共审计零正文。
|
||||
- 确定性测试覆盖配置默认值与 per-Agent 继承、预算非法组合、token 估算包含 function schema、工具输出限额、自动阈值、手动压缩、最近 tail 保留、同源幂等、追加后 revision 单调、conversation/observation 前缀篡改失败关闭、sidecar/bundle 身份冲突、summary 上限和公共审计零正文。
|
||||
- Provider 生命周期测试覆盖 started 前退出可安全重试、started 未终态进入 reconciliation、completed 后 sidecar 缺失零重放、sidecar 已提交后恢复复用,以及 Goal、计划、steer、pending、verification 和副作用身份压缩前后逐字段相同。
|
||||
- 真实 Provider 使用隔离 AppData 和 disposable 项目完成至少 30 轮多轮任务,跨越至少两次压缩和一次 Runner 强杀;证明 planning 始终低于阈值、原 Agent/Session/run 身份稳定、已完成工具零重放、最终 assistant 唯一、summary 能引用早期用户约束,且全部公共持久面 API Key、原始对话/observation、项目绝对路径和 summary 正文泄漏为 0。未完成该长链路前只能记录确定性通过,不能宣称 V1.21 整体 PASS。
|
||||
|
||||
2026-07-15 使用正式 AppData 的 `openai_chat / gpt-5.5` 路由和隔离 Runner 执行 `context-compaction` suite,V1.21 整体 **PASS**。同一 Agent active Session 完成 30/30 轮、60 条 conversation message 和 30 个唯一 assistant audit;两次真实 Provider compaction 形成 revision 1/2,30 个 tool-plan 与 2 个 compaction request 共 32 组 lifecycle,全部唯一 `started -> completed`,fallback replay 为 0。Runner 通过 Linux pidfd `SIGKILL` 后 boot 变化、Session 身份保持稳定,早期用户显式约束可从最终回复召回;最大估算输入 29134,低于 64000 自动阈值。公共 task/event/Agent DB/conversation/report 中原始正文、summary、API Key、诱饵、项目绝对路径和正式配置路径泄漏均为 0,重复 message/audit、工具执行与 finalization journal 均为 0;隔离 AppData 和 disposable 项目按 sentinel 清理。首轮复验在第 22 轮收到 Provider `transport` 终态并按规则 FAIL,未自动重放;新 disposable 项目完整重跑后取得上述 PASS。
|
||||
|
||||
真实长链收口时同步修正四项实现边界:显式用户约束由确定性保留层逐字钉住并继续做密钥/绝对路径脱敏;`runtime.compact` 单独使用 6 分钟 IPC 响应窗口,其他 Runner 方法仍保持 10 秒;普通后台任务公共审计只保存 `taskChars + taskSha256`,任务正文仅留在私有 task ledger/conversation;每 6 轮只做进度 checkpoint 与停滞检测,真正摘要只由 token 阈值或显式 `/compact` 触发。终态旧 context bundle 仅允许在完整 schema、身份、Goal、revision、verification、observation、sidecar 和 steer 校验通过后刷新 legacy plan 投影差异。
|
||||
真实长链收口时同步修正四项实现边界:显式用户约束由确定性保留层逐字钉住并继续做密钥/绝对路径脱敏;`runtime.compact` 单独使用 6 分钟 IPC 响应窗口,其他 Runner 方法仍保持 10 秒;普通后台任务公共审计只保存 `taskChars + taskSha256`,任务正文仅留在私有 task ledger/conversation;每 6 轮只做进度 checkpoint 与停滞检测,真正摘要只由 token 阈值或显式手动压缩触发。终态旧 context bundle 仅允许在完整 schema、身份、Goal、revision、verification、observation、sidecar 和 steer 校验通过后刷新 legacy plan 投影差异。
|
||||
|
||||
## V1.22 Runner-owned MCP 动态工具
|
||||
|
||||
@@ -939,7 +924,7 @@ V1.22 对标 Codex CLI 的 MCP tool 能力,在现有单 Agent Runtime 内增
|
||||
|
||||
### 开发入口与验收
|
||||
|
||||
- 开发配置面板管理 MCP server,敏感字段沿用密码输入;保存前完成本地结构校验,连接测试走 Runner,不由 WebView 直接联网或启动进程。`agc:chat` / `agc:swarm` 提供 `/mcp` 查看 server 状态和有界工具目录;正式用户 Supervisor 首页不展示 MCP 配置或调试正文,但 Runtime 可以按已配置策略使用工具。
|
||||
- 开发配置面板管理 MCP server,敏感字段沿用密码输入;保存前完成本地结构校验,连接测试走 Runner,不由 WebView 直接联网或启动进程。MCP 状态与有界工具目录只通过开发配置面板和真实 E2E 门禁核验;正式用户 Supervisor 首页不展示 MCP 配置或调试正文,但 Runtime 可以按已配置策略使用工具。
|
||||
- 确定性测试覆盖两种 transport、initialize/instructions/tools list、allow/deny、审批映射、动态 schema/token 预算、配置/catalog 漂移、required/optional 失败、超时、Runner 强杀、pending/reconciliation、结果 sidecar、二进制降级和全部公共零正文。
|
||||
- 真实本地 E2E 使用一次性 STDIO fixture 与 Streamable HTTP fixture,各自让真实 Provider 发现并调用至少一个只读工具;再让一个有副作用 fixture 停在确认、批准后只执行一次,并在调用窗口强杀 Runner 证明零重放。报告必须证明 tool schema 来自 MCP、server instructions 被标为不可信、同一 Agent/Session/run 身份稳定、结果可回灌、重复调用/assistant 为 0,且凭据、arguments、结果正文、项目/配置绝对路径公共泄漏为 0。
|
||||
|
||||
@@ -968,10 +953,10 @@ V1.23 对齐 Codex Plan/Goal 在任务未完成时主动澄清并进入 `Needs i
|
||||
|
||||
- durable pending action 增加 `waiting-for-user-input`。Runtime state/phase 同名,保持原 Agent/task/Session/run/Goal、结构化计划和 steer cursor;不完成 active plan step、不生成 finalization、不消费下一任务。普通 steer 在该状态被拒绝,回答只能走精确 request API。
|
||||
- Runner 重启时:无 sidecar可安全补建;`pending`/`answer-prepared` 修复缺失的幂等 conversation 并继续等待;`answered` 从 sidecar 全量重算 observation 后继续原 run;任一身份、问题、答案或会话消息冲突进入 `needs-reconciliation`。取消将未回答请求标记 cancelled;Goal pause 保留请求,恢复后仍回到 Needs input。
|
||||
- `AgentRuntimeResult` 只在 owning Session 当前 run 暴露一个 pending request。Project Supervisor 主聊天、开发 Agent 窗口和 `agc:chat` 展示同一结构化问题;桌面端按题提供 2-3 个选项和自由输入,全部必答后才能提交。提交中禁用重复操作,刷新/切 Agent/重启后从 sidecar 恢复。
|
||||
- `AgentRuntimeResult` 只在 owning Session 当前 run 暴露一个 pending request。Project Supervisor 主聊天与开发 Agent 窗口展示同一结构化问题;桌面端按题提供 2-3 个选项和自由输入,全部必答后才能提交。提交中禁用重复操作,刷新/切 Agent/重启后从 sidecar 恢复。
|
||||
- 确定性验收覆盖 schema/预算、sole-action、child deny、幂等 create/answer、responseId 冲突、会话中间失败、Runner 强杀三窗口、Goal pause/resume、cancel、普通 steer 拒绝、跨 Agent/Session/run/request 回答拒绝和公共零正文。真实 Provider 必须在复杂任务中自主提问,用户回答后同 run 完成唯一最终回复,并验证问题/答案各一条、Provider 未在等待期调用、Runner 强杀后零重复。
|
||||
|
||||
2026-07-16 使用正式 AppData 的 `openai_chat / gpt-5.5` 路由执行隔离 `user-input-runtime` suite,V1.23 真实验收 **PASS**。Project Supervisor 自主发起 1 个含 2 个选项的结构化问题,等待期使用 Linux pidfd 强杀 Runner 并换 boot 恢复;Provider started 记录在重启前后保持 `1 -> 1`,未暗中请求。回答后保持同一 Agent/Session/run,会话恰好为 1 条初始任务、1 条 assistant 问题、1 条 user 回答和 1 条最终 assistant;全程 2 个 Provider request identity 均唯一闭合,重复 message、遗留 finalization、公共问题/答案正文、API Key、项目/配置路径和报告泄漏均为 0,隔离 Runner、AppData 和一次性项目已清理。
|
||||
2026-07-16 使用正式 AppData 的 `openai_chat / gpt-5.5` 路由在隔离 AppData 与一次性项目上完成 V1.23 真实验收 **PASS**。Project Supervisor 自主发起 1 个含 2 个选项的结构化问题,等待期使用 Linux pidfd 强杀 Runner 并换 boot 恢复;Provider started 记录在重启前后保持 `1 -> 1`,未暗中请求。回答后保持同一 Agent/Session/run,会话恰好为 1 条初始任务、1 条 assistant 问题、1 条 user 回答和 1 条最终 assistant;全程 2 个 Provider request identity 均唯一闭合,重复 message、遗留 finalization、公共问题/答案正文、API Key、项目/配置路径和报告泄漏均为 0,隔离 Runner、AppData 和一次性项目已清理。
|
||||
|
||||
## V1.24 Codex 式 scoped `AGENTS.md` 仓库指令
|
||||
|
||||
@@ -1028,7 +1013,7 @@ V1.27 在 V1.26 一次最多三个原生 action 的基础上,让同一 Agent
|
||||
|
||||
## V1.28 Project Supervisor 合同委派与单回复收束
|
||||
|
||||
V1.28 收紧 V1.16 的静态专业 Agent 协作协议:`project-supervisor` 是正式用户唯一默认对话 Agent,也是唯一可以向正式用户提交最终回复的 Agent;静态专业 Agent 与 isolated child 只向父 run 交付内部回执、摘要和证据。开发窗口仍可直调单个专业 Agent,`agc:swarm` 仍可显式指定其它父 Agent 做调试,但这些入口不构成正式用户对话或第二条用户回复。若本节与 V1.16 或实施计划中的旧表述冲突,以本节为准。
|
||||
V1.28 收紧 V1.16 的静态专业 Agent 协作协议:`project-supervisor` 是正式用户唯一默认对话 Agent,也是唯一可以向正式用户提交最终回复的 Agent;静态专业 Agent 与 isolated child 只向父 run 交付内部回执、摘要和证据。开发窗口仍可直调单个专业 Agent,但这些入口不构成正式用户对话或第二条用户回复。若本节与 V1.16 或实施计划中的旧表述冲突,以本节为准。
|
||||
|
||||
**状态:PASS。合同委派、结构化回执、单层 repair、Supervisor finalization、正式用户 GUI 接入和 Runtime 显式瞬时重试均已落地;2026-07-17 正式 `openai_chat / gpt-5.5` `supervisor-swarm` 已完成双专业 Agent 真并行、唯一 repair、pidfd Runner 强杀恢复、唯一 Supervisor assistant、零重复与零泄漏的完整验收。**
|
||||
|
||||
@@ -1137,41 +1122,41 @@ repair 深度固定为 `1`;同一原 delivery 同时最多存在一个非 `sup
|
||||
|
||||
最终加强版正式 `openai_chat / gpt-5.5` 复验 PASS:46 个 Provider request identity 全部形成唯一终态,`46 started / 46 terminal / 45 completed / 1 failed`,恰好 1 条 retry audit;失败 attempt 与后继 `-transient-1` 使用不同 request identity,Agent/task/Session/run/source/request kind 保持一致。forwarding gate 放行前 action、receipt、专业子委派、claim、assistant、pending、project revision 和 upstream forwarding 均为 `0`。代理观察到的 10 个目标 Agent 请求与该 Agent lifecycle 数量一致,其中 1 个注入失败、1 个暂停、9 个转发。放行后仍完成 2 个初始专业 Agent 真重叠、2+1 delivery、2 个 Observed claim、1 次 targeted contract read、唯一 repair、pidfd Runner 强杀/boot 恢复、5 步父计划、唯一 Supervisor assistant 与 3 条内部专业 assistant;27/27 成功计划和 14/14 repair 均为 `native_runtime_tools`。重复、残留 sidecar、Provider payload、私有正文、API Key、项目/正式配置路径、报告、secret 与 lure 泄漏均为 `0`;source-dir suite-prefix guard 与 `sourceAppDataDirectoryUntouched` 证明正式 AppData 未被写入,物理请求/lifecycle 一一对应和失败 partial checkpoint 门禁均通过,代理、隔离 Runner/AppData/项目全部清理。
|
||||
|
||||
该受控 suite 是 V1.28 协议与恢复的故障注入门禁,不替代后续自主 Swarm 验收。现有 fixture 明确给出两个专业方向、同轮要求和一次 repair 上限;“Supervisor 在不提供 Agent ID、并行配方或 repair 次数时自主选择编排”仍需独立 `supervisor-swarm-autonomous` 真实 suite 证明。真实 `--swarm-chat`、同一 run 的 static delivery + isolated all-join 组合以及 Tauri/WebView 宿主级 Supervisor GUI 也仍是单独完成项。
|
||||
该受控 suite 是 V1.28 协议与恢复的故障注入门禁,不替代后续自主 Swarm 验收。现有 fixture 明确给出两个专业方向、同轮要求和一次 repair 上限;“Supervisor 在不提供 Agent ID、并行配方或 repair 次数时自主选择编排”仍需独立自主编排真实 Provider 验收证明。同一 run 的 static delivery + isolated all-join 组合以及 Tauri/WebView 宿主级 Supervisor GUI 仍是单独完成项。
|
||||
|
||||
## V1.30 Project Supervisor 自主终端协作验收
|
||||
## V1.30 Project Supervisor 自主协作验收
|
||||
|
||||
V1.30 新增独立 `supervisor-swarm-autonomous-chat` 真实 Provider suite,同时证明 Project Supervisor 的自主专业编排和正式 `agc:chat / --swarm-chat` 入口。它复用 V1.28 的 static delivery/claim/repair、External Runner、隔离 AppData、确认、恢复、finalization 和唯一回复事实源,不新增 Agent、调度器、Provider 客户端或第二套对话持久化。现有 `supervisor-swarm` 与 `supervisor-swarm-transient-retry` 继续分别承担固定协议链和受控瞬态故障门禁,不能被本 suite 替代。
|
||||
V1.30 通过真实 Provider 验收证明 Project Supervisor 的自主专业编排。该验收复用 V1.28 的 static delivery/claim/repair、External Runner、隔离 AppData、确认、恢复、finalization 和唯一回复事实源,不新增 Agent、调度器、Provider 客户端或第二套对话持久化。现有 `supervisor-swarm` 与 `supervisor-swarm-transient-retry` 继续分别承担固定协议链和受控瞬态故障门禁,不能被该验收替代。
|
||||
|
||||
- 唯一用户任务只能表达业务结果,例如把试玩项目推进到可交给首批玩家体验并汇报交付、验证和风险;任务不得出现静态 Agent ID、Agent 数量、同轮/并行要求、planning 轮次、返工/repair 次数、原生工具名、run/action/delegation 身份或 Runner 操作。一次性仓库规则只描述玩家体验规格、发布质量记录、语义验收、修改后验证和安全边界;不得指定由哪个 Agent 承担、必须同批委派、必须返工几次或调用什么工具。
|
||||
- fixture 提供一项缺失的体验规格和一项“客观文件/验证存在但语义仍不满足”的质量记录。质量记录在初始阶段必须先独立审阅再允许修改;harness 只通过项目 policy 暂时拒绝质量角色写入,弱回执被父 run 认领后解除 policy,不发送 steer、不改业务文件、不补充新任务。初始弱回执必须是 `completed + evidence-ready` 且无缺失产物,确保后续 repair 来自 Supervisor 对 acceptance criteria 的语义判断,而不是 Runtime 自动把客观失败标成 `needs-repair`。
|
||||
- `--swarm-chat --init <project>` 必须由真实发布二进制启动,省略 parentAgentId 后进入 `project-supervisor`;用户任务通过 stdin 发送,所有确认也经同一终端 `approve` 入口完成。允许 Supervisor 先做必要读取,但首个包含专业委派的 native Provider 批次必须自主选择至少两个不同规范专业 Agent,并在同批形成两个初始合同;两个 child 的真实 Provider lifecycle 必须重叠,不能用同一 Agent 的 retry/format repair 或仅凭 delegate action 时间冒充并行。
|
||||
- 真实 Provider 验收必须由真实发布二进制启动 `project-supervisor`,用户任务只表达业务结果。允许 Supervisor 先做必要读取,但首个包含专业委派的 native Provider 批次必须自主选择至少两个不同规范专业 Agent,并在同批形成两个初始合同;两个 child 的真实 Provider lifecycle 必须重叠,不能用同一 Agent 的 retry/format repair 或仅凭 delegate action 时间冒充并行。
|
||||
- 弱质量 claim 进入 `Observed` 后,Supervisor 必须在同一父 Session/run 自主创建引用原 delivery 的唯一 repair;目标 Agent、acceptanceCriteria 和 expectedArtifacts 必须完整继承,repair action 必须晚于弱 claim、早于唯一最终回复。repair 待确认边界继续执行 pidfd Runner 强杀与 boot 恢复,任务、delivery、claim、pending action 和 Provider started 身份不得漂移或重放。
|
||||
- 终局必须同时满足:严格 host oracle 判定两项产物语义正确,最后修改后的验证凭证有效;`[turn.report]` 为 v1/settled、父 Agent/Session/run 与 journal 一致、新增 assistant 恰好 1、队列和 reconciliation 计数为 0;正式用户会话只有 1 条 user 和 1 条 Supervisor assistant,专业 assistant 仅留在内部 Session;无 steer、重复 delivery/action/message/receipt/Provider lifecycle、残留 sidecar、Provider payload、私有正文、API Key、诱饵、项目/正式配置路径或报告泄漏,隔离 Runner/AppData/项目全部清理。任何一次带更明确提示的重跑都只能算新的失败后尝试,不能与原 run 拼接成 PASS。
|
||||
- 终局必须同时满足:严格 host oracle 判定两项产物语义正确,最后修改后的验证凭证有效;父 Agent/Session/run 与 journal 一致、新增 assistant 恰好 1、队列和 reconciliation 计数为 0;正式用户会话只有 1 条 user 和 1 条 Supervisor assistant,专业 assistant 仅留在内部 Session;无 steer、重复 delivery/action/message/receipt/Provider lifecycle、残留 sidecar、Provider payload、私有正文、API Key、诱饵、项目/正式配置路径或报告泄漏,隔离 Runner/AppData/项目全部清理。任何一次带更明确提示的重跑都只能算新的失败后尝试,不能与原 run 拼接成 PASS。
|
||||
- `agent.message` 的语义身份固定绑定来源 Agent/run、目标 Agent/已解析 Session 和清洗截断后正文 SHA-256。同一语义消息重放只能复用唯一 conversation message 与 `agent.runtime.agent.message` 审计,并以 `messageAppended=false` 返回 durable no-op;不同正文、目标、Session、来源 Agent 或来源 run 仍是新消息。该 no-op 不得计入上下文窗口的新进展,也不能替代专业 Agent 自身最终回执。若模型持续重复同一消息,Runtime 最迟在当前完整 6 轮停滞窗口结束时写 `failed / budget-exhausted / loop-budget-exhausted`,保留原 `in_progress` 计划,不写 completed 或伪造成功回复;每个尝试的 action/observation/receipt 仍须完整落账且公共 receipt 不保存消息正文。
|
||||
|
||||
2026-07-17 最终正式 `openai_chat / gpt-5.5` 诊断轮 **PASS**。唯一业务任务未提供 Agent ID、Agent 数量、并行、工具、repair 或 Runner 配方;Supervisor 在 1 个 native planning 批次自主选择 2 个不同专业 Agent,真实 Provider 区间重叠,并在同一父 Session/run 完成 `2` 份初始 delivery、`1` 次语义 repair、`2` 个 Observed claim、严格宿主验证、pidfd Runner 强杀、boot 切换和身份稳定恢复。最终 `[turn.report]` 为 `settled`,正式会话新增 Supervisor assistant 恰好 `1`,内部专业 assistant 为 `3`;父计划 `4/4` completed,pending/running/confirmation/user-input/reconciliation 均为 `0`。
|
||||
2026-07-17 最终正式 `openai_chat / gpt-5.5` 诊断轮 **PASS**。唯一业务任务未提供 Agent ID、Agent 数量、并行、工具、repair 或 Runner 配方;Supervisor 在 1 个 native planning 批次自主选择 2 个不同专业 Agent,真实 Provider 区间重叠,并在同一父 Session/run 完成 `2` 份初始 delivery、`1` 次语义 repair、`2` 个 Observed claim、严格宿主验证、pidfd Runner 强杀、boot 切换和身份稳定恢复。正式会话新增 Supervisor assistant 恰好 `1`,内部专业 assistant 为 `3`;父计划 `4/4` completed,pending/running/confirmation/user-input/reconciliation 均为 `0`。
|
||||
|
||||
该轮共形成 110 条 task、197 条 event、330 条 Agent DB 和 9 条会话消息;51 个 Provider request identity 全部唯一闭合为 `51 started / 51 terminal / 51 completed / 0 failed`,28/28 个成功工具计划和 19/19 个格式修复均为 `native_runtime_tools`,wrapper/text fallback 为 `0`。delivery、message、action lifecycle、executing action、receipt、Provider lifecycle 的重复计数均为 `0`,所有 batch/finalization/confirmation/user-input sidecar 为 `0`,Provider payload、私有正文、API Key、诱饵、项目/正式配置绝对路径和报告泄漏均为 `0`。隔离 AppData 自动清理;保留的 disposable 项目经 sentinel/进程核对后手动删除。此前两次独立尝试在 `maxRetries=0` 下各遇到 1 次外部 Provider 终态失败并在恢复边界前停止,均只作失败证据,未与本轮拼接。
|
||||
|
||||
确定性 `background_agent_runtime_bounds_duplicate_agent_message_livelock` 同时证明:6 次同指纹 Runtime action/observation/receipt 全部实际落账,目标 conversation、`conversation.message` 和 `agent.runtime.agent.message` 各仅 1 条,后 5 次为 durable no-op,第 6 轮保留 `in_progress` 计划并进入 `budget-exhausted`,不存在第 7 次 Provider 请求、context compaction 或 completed 投影。
|
||||
|
||||
V1.30 至此只证明自主 static 专业编排与真实终端聊天可组合;同一父 run 的 static delivery + isolated all-join 真实组合恢复,以及 Tauri/WebView 宿主级 Supervisor E2E 仍需各自独立门禁。
|
||||
V1.30 至此只证明自主 static 专业编排;同一父 run 的 static delivery + isolated all-join 真实组合恢复,以及 Tauri/WebView 宿主级 Supervisor E2E 仍需各自独立门禁。
|
||||
|
||||
## V1.31 Project Supervisor 静态与隔离子 Agent 混合协作门禁
|
||||
|
||||
V1.31 新增独立 `supervisor-swarm-static-isolated-autonomous-chat` 真实 Provider suite,用于验证同一个 `project-supervisor` Session/run 可以自主同时使用 static `agent.delegate` 与 dynamic `agent.spawn_isolated(joinMode=all)`,并由同一个完成屏障、恢复链和 finalization journal 唯一收束。该 suite 复用 V1.28-V1.30 的 static delivery/claim/repair、isolated group/result/join delivery、External Runner、`--swarm-chat`、隔离 AppData 和零泄漏事实源,不新增调度器、对话入口、结果 sidecar 或第二种用户回复。
|
||||
V1.31 通过真实 Provider 验收证明同一个 `project-supervisor` Session/run 可以自主同时使用 static `agent.delegate` 与 dynamic `agent.spawn_isolated(joinMode=all)`,并由同一个完成屏障、恢复链和 finalization journal 唯一收束。该验收复用 V1.28-V1.30 的 static delivery/claim/repair、isolated group/result/join delivery、External Runner、隔离 AppData 和零泄漏事实源,不新增调度器、结果 sidecar 或第二种用户回复。
|
||||
|
||||
- 用户任务只明确业务范围包括仓库既有的正式交付、临时检查和实际验证,不得出现 Agent ID、数量、并行、static/isolated、delegate/spawn/join、repair 次数、run/action 身份或 Runner 操作。一次性仓库规则可声明既有验证要求和安全禁用边界,但不得指定 Agent 编排工具、调用顺序或 Runner 配方。Supervisor 系统策略要求提交首个协作批次前分别枚举长期专业交付与临时隔离检查;两类都非空时不得遗漏任一类。
|
||||
- 首个形成协作的 native Provider 批次必须包含两个不同 static `agent.delegate` 与一个 `agent.spawn_isolated`;spawn 请求固定 `joinMode=all`,三个 child 的 expectedArtifacts 指向三个既有证据文件,writeScopes 互不重叠。批次必须先停在 `waiting-confirmation / nextActionIndex=0`,唯一 `provider_action_batch.confirmation_required` 与唯一 approval 都绑定 spawn 和原批次,approval 必须早于三个 action 的任何真实副作用;随后每个 action 的 side effect、observed、receipt 和终态 observation 严格按 `actionIndex` 推进。两个 static child 的 Provider 区间必须真实重叠,且至少一个 static child 与一个 isolated child 的 Provider 区间也必须真实重叠,不能用 action 时间、同 Agent retry 或格式修复冒充并行。
|
||||
- static 与 isolated 继续使用各自 durable 事实源。static 的 2 份初始 delivery 与 1 份 repair 分别由两个 Observed claim 认领 2/1 份 receipt;isolated 形成 1 个 group、3 个唯一 instance/result、1 个 all-join delivery,并由同一父 run 的一个 `agent.run_status` action 认领。两类记录的 parent Agent/Session/run 必须一致;该 suite 要求 isolated child 的项目 mutation action 和实际文件修改均为 0,但这不是把生产 isolated 权限模型改成只读沙箱。
|
||||
- completion blocker 在项目锁内先检查 plan/Goal,再按 `provider-action-batch -> process -> isolated join -> static receipts` fail closed,随后检查 response revision 和 verification。单一 waiting phase 只是当前首个 blocker 的 UI 投影,不是事实源;Runner 恢复和每次 finalization 都必须重新枚举两类 barrier。`project_supervisor_mixed_waiting_recovery_does_not_plan_until_all_join_ready`、`project_supervisor_mixed_waiting_recovery_does_not_plan_until_static_delivery_ready` 与 `project_supervisor_mixed_run_status_recovery_reuses_partial_isolated_claim_after_revision_drift` 三条确定性回归分别覆盖双向等待切换和同 action 部分认领恢复,不能代替真实 Provider suite。
|
||||
- repair 待确认动作持久化后执行 pidfd Runner 强杀。强杀前后必须逐项比较 static delivery/claim、isolated group/instance/result/join delivery、父 task/context、pending action 和完整 Provider started identity set;boot 必须变化,任何 child/action/receipt/join 不得重放。static claim 与 isolated join claim 的 observation 都必须早于父 finalization prepared,父计划、验证、确认、用户输入、process、两类 barrier 全部清零后,原 Supervisor run 才能写唯一 assistant 和 `turn.report=settled`。
|
||||
- repair 待确认动作持久化后执行 pidfd Runner 强杀。强杀前后必须逐项比较 static delivery/claim、isolated group/instance/result/join delivery、父 task/context、pending action 和完整 Provider started identity set;boot 必须变化,任何 child/action/receipt/join 不得重放。static claim 与 isolated join claim 的 observation 都必须早于父 finalization prepared,父计划、验证、确认、用户输入、process、两类 barrier 全部清零后,原 Supervisor run 才能写唯一 assistant。
|
||||
- 最终报告必须单独给出两类 Provider 重叠、group/instance/result/join/claim、两类 parent identity、跨恢复身份稳定、isolated 项目修改、重复 continuation/group/join/action/receipt、残留 sidecar 和公共泄漏计数。任何一项缺失、从不同尝试拼接、用户/仓库规则含编排配方、isolated 修改项目、未认领即 final 或额外用户回复都必须 FAIL;确定性回归或 V1.30 static PASS 不能替代该门禁。
|
||||
|
||||
2026-07-17 最终正式 `openai_chat / gpt-5.5` 独立轮 **PASS**。该轮形成 149 条 task、261 条 event、451 条 Agent DB 和 14 条会话消息;67 个 Provider request identity 全部唯一闭合为 `67 started / 67 terminal / 67 completed / 0 failed`,37/37 个成功工具计划与 24/24 个格式修复均为 `native_runtime_tools`,wrapper/text fallback 为 0。首批 3 个 action 的 confirmation-required/approval 各 1 且时序有效,static-static 与 static-isolated Provider 区间均真实重叠;static 形成 2 份初始 delivery、1 份 repair 和 2 个 Observed claim,isolated 形成 1 个 group、3 个 completed result、1 个 parent-wake claimed join,全部绑定同一父 Session/run。
|
||||
|
||||
Runner pidfd 强杀后的 boot、父 context、pending action、两类 durable identity 和完整 Provider identity set 均稳定恢复;isolated mutation action、isolated 文件修改、continuation、重复 delivery/group/instance/result/join/claim/message/action/receipt/Provider lifecycle、残留 sidecar和公共正文/凭据/绝对路径/报告泄漏均为 0。`turn.report=settled`,父计划 4/4 completed,正式 Supervisor assistant 恰好 1,内部专业 assistant 3、isolated assistant 3,最终 disposable 项目与隔离 AppData 均自动清理。此前不完整编排、child 合同不满足、外部 Provider 终态失败和调试验收器误判均各自作为独立失败轮停止,未与本轮 PASS 拼接。
|
||||
Runner pidfd 强杀后的 boot、父 context、pending action、两类 durable identity 和完整 Provider identity set 均稳定恢复;isolated mutation action、isolated 文件修改、continuation、重复 delivery/group/instance/result/join/claim/message/action/receipt/Provider lifecycle、残留 sidecar和公共正文/凭据/绝对路径/报告泄漏均为 0。父计划 4/4 completed,正式 Supervisor assistant 恰好 1,内部专业 assistant 3、isolated assistant 3,最终 disposable 项目与隔离 AppData 均自动清理。此前不完整编排、child 合同不满足、外部 Provider 终态失败和调试验收器误判均各自作为独立失败轮停止,未与本轮 PASS 拼接。
|
||||
|
||||
## V1.32 Runtime 强制 Supervisor 协作合同
|
||||
|
||||
@@ -1189,7 +1174,7 @@ V1.31 证明真实 Provider 可以自主形成 static + isolated 混合协作,
|
||||
|
||||
2026-07-17 在最终代码 diff 上使用 `gpt-5.5 / openai_chat / high` 完成 V1.32 独立真实 PASS。`supervisor-swarm-collaboration-policy-mixed-recovery` 只在隔离 AppData 配置副本中把瞬态重试设为 `maxRetries=2 / retryBackoffMs=500`,正式 AppData、源配置和 Runner endpoint 均未修改;86 个 Provider lifecycle 全部完成,本轮未触发重试。首批 v2 batch 固化 3 个 action,包含 2 个指定 static delegate 与 1 个三 child isolated spawn;waiting-confirmation 零副作用边界、pidfd 强杀恢复、batch/contract/action identity、两类 Provider 重叠、1 次 repair、3 个 delivery、1 个 isolated group/3 个 instance/3 个 result/1 个 claimed join、宿主验证和唯一 Supervisor assistant 全部通过。
|
||||
|
||||
成功报告共记录 178 个 task snapshot、326 个 event、556 个 Agent DB record、30 个 action execution 和 38 个 receipt;重复 delivery/group/instance/result/join/claim/message/action/receipt/Provider lifecycle 与 pending/batch/finalization/confirmation sidecar 均为 0,私密正文、Provider payload、API Key、项目路径、正式配置路径和最终报告泄漏均为 0。`turn.report=settled` 且 reconciliation Agent 为 0。49 次 native tool plan 中发生 30 次格式修复,未破坏动作幂等与最终结果,但说明真实链路仍有明显延迟和 Provider 调用成本,后续应单独收敛工具合同表达和 repair 频率。
|
||||
成功报告共记录 178 个 task snapshot、326 个 event、556 个 Agent DB record、30 个 action execution 和 38 个 receipt;重复 delivery/group/instance/result/join/claim/message/action/receipt/Provider lifecycle 与 pending/batch/finalization/confirmation sidecar 均为 0,私密正文、Provider payload、API Key、项目路径、正式配置路径和最终报告泄漏均为 0。reconciliation Agent 为 0。49 次 native tool plan 中发生 30 次格式修复,未破坏动作幂等与最终结果,但说明真实链路仍有明显延迟和 Provider 调用成本,后续应单独收敛工具合同表达和 repair 频率。
|
||||
|
||||
## V1.33 原生工具计划 repair 收敛与分类
|
||||
|
||||
@@ -1353,7 +1338,7 @@ V1.38 把 collaboration policy 的执行语义从“每次动作或恢复都读
|
||||
|
||||
- 2026-07-19 确定性门禁已完成:E2E self-test **PASS**,同时覆盖 modern `provider_action_batch.confirmation_required` 与 legacy `tool_confirmation_required`、requirement/approval/receipt 唯一性、`confirmation` execution mode、目标 Session/run 和严格持久化顺序;snapshot/binding 的终态预期改为由已验真的非 `aborted` v2 collaboration batch 决定,不再用 mixed suite 拓扑代替 durable 事实。`supervisor_collaboration_` 52/52、`provider_action_batch_` 12/12、`project_supervisor_mixed_` 5/5 通过;Tauri/Rust 全量为 949 passed、4 个环境依赖用例按设计 ignored,`check:rustfmt` 通过。
|
||||
- 确定性覆盖包含 snapshot 的 9 个完整字段、首次 `aborted` 零绑定与 matching binding 的 `aborted` v2 恢复、batch -> snapshot -> binding 双故障窗口、CAS 冲突、篡改 contract、binding/snapshot 丢失组合、contractless/v1 协作批次失败关闭与非协作批次兼容、legacy 非终态迁移与终态拒绝、危险 Agent/run ID 路径及锁隔离、global policy 漂移、已有 claim 恢复与新 claim 失败关闭。新增 `supervisor_collaboration_policy_snapshot_survives_terminal_runtime_cleanup` 证明终态只删除 pending/provider batch/confirmation 等临时 sidecar,snapshot/binding 字节保持不变且 resolver 继续返回 `run-snapshot`。
|
||||
- 真实 `supervisor-swarm-static-isolated-autonomous-chat` 曾在单次独立运行中完整形成 2 个 isolated group / 3 个 child、1 个 observed join claim 覆盖两组、唯一 repair、宿主验证、Runner pidfd 强杀恢复和唯一 Supervisor assistant;snapshot/binding 均为唯一、字节及字段稳定,global policy drift 被观察,重复、临时 sidecar、正文、API Key、项目路径和配置路径泄漏均为 0。但该轮运行期间正式客户端在测试外部重启了正式 Runner,source endpoint 所有权门禁按设计失败,因此该功能样本不能记为 PASS。
|
||||
- 一次真实混合协作运行曾在单次独立运行中完整形成 2 个 isolated group / 3 个 child、1 个 observed join claim 覆盖两组、唯一 repair、宿主验证、Runner pidfd 强杀恢复和唯一 Supervisor assistant;snapshot/binding 均为唯一、字节及字段稳定,global policy drift 被观察,重复、临时 sidecar、正文、API Key、项目路径和配置路径泄漏均为 0。但该轮运行期间正式客户端在测试外部重启了正式 Runner,source endpoint 所有权门禁按设计失败,因此该功能样本不能记为 PASS。
|
||||
- 随后使用权限为 `0700/0600`、不含 endpoint/锁/会话的私有配置源副本隔离正式客户端干扰,source endpoint、源目录和清理门禁均稳定;五次最小 OpenAI-chat 探针全部 HTTP 200。然而多次独立完整运行仍在长链路耗尽 transient Provider retry。最后一轮隔离 overlay 已提高到 `requestTimeoutMs=300000 / maxRetries=3 / retryBackoffMs=500`,仍在首个业务批次前形成 4 个 failed lifecycle / 3 个 retry 后终止,child、delivery、claim 和项目 mutation 均为 0,现场清理与泄漏门禁通过。失败轮不得与前述功能完整轮拼接;截至当前,**V1.38 独立真实 Provider E2E 仍未 PASS**,需在外部 Provider 稳定后以最终代码重新独立运行。
|
||||
|
||||
## V1.39 首次规划 Provider 瞬态重试持久等待态
|
||||
@@ -1447,7 +1432,7 @@ V1.41 为 V1.40 明确留下的成功响应交接窗口增加 `.agent/runtime/pr
|
||||
|
||||
2026-07-20 当前最终实现的最新验证证据为:`provider_retry_` 21/21、`response_stream_` 23/23、`finalization_resume_` 12/12;Tauri/Rust 串行全量共 989 tests,`985 passed / 4 ignored / 0 failed`。这些数字替代 V1.40 较早快照,后续当前结果统一使用本行口径。
|
||||
|
||||
上表是 V1.41 的确定性门禁,不代表真实外部 Provider E2E 结论。除表内窗口外,还必须继续扫描 task/event/Agent DB/CLI/report,确认 Provider 响应、compaction summary、API Key、Provider URL 和项目/配置绝对路径公共泄漏均为 0。
|
||||
上表是 V1.41 的确定性门禁,不代表真实外部 Provider E2E 结论。除表内窗口外,还必须继续扫描 task/event/Agent DB/report,确认 Provider 响应、compaction summary、API Key、Provider URL 和项目/配置绝对路径公共泄漏均为 0。
|
||||
|
||||
## V1.42 Project Supervisor final-reply 瞬时重试 Runner 强杀真实门禁
|
||||
|
||||
@@ -1474,7 +1459,7 @@ npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-final-reply-transie
|
||||
### 终局门禁与六轮证据
|
||||
|
||||
- 恢复前后的父 tool-plan `started` 数必须完全相等,不得为收尾新增 tool-plan。终局只允许唯一成功的 parent final-reply、唯一 Project Supervisor assistant 和唯一 `committed` response stream,stream 身份绑定原 base final-reply slot 且正文与 assistant 完全一致。
|
||||
- retry、handoff、finalization artifacts 必须全部为 `0`;重复 delivery/claim/receipt/action/message/lifecycle 必须为 `0`。公共 task/event/Agent DB/CLI/report 中的 Provider/assistant 正文、API Key 和项目/发布配置绝对路径命中必须为 `0`。
|
||||
- retry、handoff、finalization artifacts 必须全部为 `0`;重复 delivery/claim/receipt/action/message/lifecycle 必须为 `0`。公共 task/event/Agent DB/report 中的 Provider/assistant 正文、API Key 和项目/发布配置绝对路径命中必须为 `0`。
|
||||
- 旧 `supervisor-swarm-transient-retry` 继续只证明 Project Supervisor 首次 tool-plan 的持久退避与 Runner 强杀,不能替代本 suite,也不能把它的历史 PASS 外推为 V1.42 final-reply PASS。
|
||||
- 2026-07-20 确定性与静态门禁已完成:fault proxy `14/14`、E2E self-test **PASS**、前端 `308/308`,以及 shell typecheck、`platform-llm 41/41`、`platform-agent 17/17`、`shared-contracts 7/7` 均通过。
|
||||
- 真实外部 Provider suite 总计执行六轮,逐轮独立裁决且严禁拼接:第一、二轮沿用既有失败记录,均为 **FAIL**;第三轮已走通故障、持久重试和唯一回复,但验收过早观察到 `1` 个 finalization journal,仍为 **FAIL**,随后改为终态后显式等待 sidecar 全部清零并设置 `10s` 硬超时;第四轮在 quality-review 的普通 tool-plan 连续发生 transport/connectivity 失败并耗尽重试,未进入目标 final-reply 故障,仍为 **FAIL**;第五轮暴露并修复并行 Agent 的 `file.write` 与项目写锁竞争,失败 observation 携带绝对锁路径,继而触发 pending 持久化拒绝并进入 `needs-reconciliation`,仍为 **FAIL**。修复后 `file.write / file.patch / file.delete` 统一使用 Runtime 短等待项目写锁,`file.write` 错误在持久化前脱敏,并新增 `2` 条 Rust 回归测试。
|
||||
@@ -1654,6 +1639,7 @@ V1.53 把根 Project Supervisor 的 same-run steer 从“收到消息立即中
|
||||
- 条件中断必须先读取已持久化 decision,并只允许中断注册时 `appliedSteerCursor < steer.sequence` 的旧 planning/final-reply Provider。若旧请求已自然结束,或新 Provider 已消费该 steer 后启动,则返回 `providerInterrupted=false`,不得误杀新规划。工具、外部副作用、确认、process session、Git、receipt 和 finalization 始终不强杀,在下一安全边界消费 steer。
|
||||
- LLM 判定、解析或持久化失败时写入关联的非终态 fallback 回复,保持当前任务运行,并在下一安全边界应用已排队 steer;失败不能退回“默认中断”。判定与回复按 `agentId / runId / steerId` 幂等,冲突终态失败关闭。
|
||||
- 验收必须覆盖判定 LLM 的 `true / false` 协议、公开回复幂等、入队本身不中断、`runtime.steer` 有活动 Provider 时仍不中断、缺失 decision 拒绝条件中断、`false` decision 不中断、`true` decision 只中断旧 cursor,以及判定失败后同一 run 继续。
|
||||
- 2026-09-23 复查收尾:本节描述的 LLM 判定链已随「退役AGC项目对话斜杠命令与终端swarm chat入口」整体删除——`runtime_steer_decision` 工具与 `decide_game_creator_agent_runtime_steer_at`、`runtime.interrupt_for_steer_decision` RPC、`agent.runtime.steer_decision` 持久记录、`steer_decision_*` prompt 键、`steer_game_creator_agent_runtime_task` 命令与只测该链的用例均不存在。same-run steer 仍 durable 入队并由 `runtime.steer`(`--agent-steer`)唤醒、在下一安全边界应用;本节仅作历史记录。
|
||||
|
||||
## V1.54 通用多 Agent DAG 编排 crate
|
||||
|
||||
@@ -1729,9 +1715,6 @@ V1.54 的公共编排层可以在运行前构造动态 DAG,但 LLM 在执行
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml isolated -- --nocapture --test-threads=1`
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_supervisor_mixed_ -- --nocapture --test-threads=1`
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml supervisor_collaboration_ -- --nocapture --test-threads=1`
|
||||
- `npm run agc:collaboration-policy-e2e -- --config-dir <AppData>`
|
||||
- `npm run agc:mixed-swarm-e2e -- --config-dir <AppData>`
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml swarm_cli::tests -- --nocapture`
|
||||
- `cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml typed_goal_pause_and_cancel_require_durable_intent_and_keep_exact_run -- --nocapture`
|
||||
- `npm run ai-game-creator-shell:typecheck`
|
||||
- `npm run test -- apps/ai-game-creator-shell/tests`
|
||||
@@ -1746,14 +1729,12 @@ V1.54 的公共编排层可以在运行前构造动态 DAG,但 LLM 在执行
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite web-search`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite context-compaction`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite mcp-runtime`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite user-input-runtime`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite scoped-agents`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite project-skill`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite parallel-read`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite supervisor-swarm`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-transient-retry-real-e2e -- --config-dir <AppData>`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-final-reply-transient-retry-real-e2e -- --config-dir <发布AppData绝对路径>`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-autonomous-chat-real-e2e -- --config-dir <AppData>`
|
||||
- `npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite full`
|
||||
- `npm run check:encoding`
|
||||
- `git diff --check`
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
|
||||
DirectProject 只使用 `.agent/conversations/project.jsonl` 作为对话历史。历史保存 Codex Responses API 的完整 item,使聊天展示与新线程恢复使用同一份事实来源;两者只是不同读取动作。
|
||||
|
||||
本方案只适用于 DirectProject,不改变 DirectHome、Agent session 历史或 `runtime/direct-codex/turns` 审计账本。
|
||||
本方案只适用于 DirectProject,不改变 Agent session 历史。DirectProject 已退役 `runtime/direct-codex/turns` 平行审计账本并删除旧审计 / 计时实现;完整回合条目统一来自本方案的 `project.jsonl`。用户项目中的旧日志不作为新回合必需产物,也不因代码清理被删除或迁移。
|
||||
|
||||
## 文件格式
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# DirectProject 本轮附件路径映射
|
||||
|
||||
> 文档状态:`historical`(旧 Home / sidecar 设计已由 canonical userItem 附件引用替代,不作为当前实现或保留代码的依据)
|
||||
|
||||
2026-09-23 核准:未注册的 DirectHome 与旧 sidecar DTO、渲染器、prompt key 和专属测试已清理。现役附件使用 `userItem.content` 中的 `agc_attachment_reference`,保留本轮名称到项目相对路径的映射、不灌正文、不按 GDD 特判;名称 / 媒体类型 / 路径清洗及数量上限仍服务 canonical validation/wire。当前权威合同见 [AGC 实施计划](./【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md)。以下为原设计记录,不要求恢复 Home 元数据文案、独立 attachments 参数或 sidecar。
|
||||
|
||||
- 日期:2026-08-31
|
||||
- 状态:现行合同(已按本文落地)
|
||||
- 状态:历史设计,原 sidecar 实现已退役
|
||||
- 问题:Gitea issue #212(DirectProject 未消费用户上传权威文档)
|
||||
- 关联入口:PR #210「批准 GDD 回填做游戏入口」(`feat/create_entrance`,未合入时仍按该 PR 的调用链理解)
|
||||
- 原则:落地后代码简洁可维护,不为了 diff 最小而打补丁;附件一律同等对待,不给 GDD 开协议特例
|
||||
@@ -27,7 +31,7 @@
|
||||
- 不把附件全文拼进 prompt,不按扩展名决定是否读取。
|
||||
- 不把「没读到就阻断」做成门禁。
|
||||
- 不扫 manifest 里历史 `kind=uploaded`。
|
||||
- 不做 native 读取审计;该项由 [`【技术方案】Direct回合行为审计账本-2026-08-31.md`](./【技术方案】Direct回合行为审计账本-2026-08-31.md) 承接。
|
||||
- 不新增附件专用 native 读取审计。现役回合工具条目从 `project.jsonl` 完整历史读取;旧平行审计日志及 `offeredRead` / `firstDesign` 投影已停用,不再由旧审计专题承接。
|
||||
- 不改 DirectHome 在「无项目路径」时的现有文案和列表格式。
|
||||
- 不改 `enterCreatedHomeProject` 的空正文兜底句(与做方案共用)。
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# Direct 回合行为审计账本
|
||||
|
||||
> 文档状态:`historical`(旧平行审计日志已停用,仅用于历史追溯,不作为当前实现或保留代码的依据)
|
||||
|
||||
2026-09-23 核准:DirectProject 已以 `.agent/conversations/project.jsonl` 保存完整回合条目,GUI 入口不再构造本方案的审计对象,也不承诺继续追加旧日志、`direct.codex.turn` 摘要或附属请求分段计时。当前边界见 [AGC 实施计划](./【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md) 的“Direct 历史、审计与耗时的现行边界”。既有用户项目内的旧审计数据不在本次文档修正中删除或迁移。以下保留原设计供追溯。
|
||||
|
||||
- 日期:2026-08-31
|
||||
- 状态:现行合同(已按本文落地)
|
||||
- 状态:历史设计,原实现已退出生产回合入口
|
||||
- 问题:Gitea issue #212 的第二段(Direct 原生读 / 工具行为无法从项目产物判断);用于分析「附件已映射仍未按文档实施」
|
||||
- 关联:[`【技术方案】DirectProject本轮附件路径映射-2026-08-31.md`](./【技术方案】DirectProject本轮附件路径映射-2026-08-31.md)、[`【技术说明】DirectProject未消费用户上传权威文档-2026-08-30.md`](./【技术说明】DirectProject未消费用户上传权威文档-2026-08-30.md)
|
||||
- 原则:落地后代码简洁可维护;审计是 Direct 行为时间线,不是 GDD 特例,也不替代 sidecar
|
||||
@@ -319,7 +323,7 @@ chat_with_game_creator_direct_codex
|
||||
|
||||
## 9. 代码落地
|
||||
|
||||
新增 [`apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs`](../../apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs):
|
||||
原方案新增 `apps/ai-game-creator-shell/src-tauri/src/agent/direct_codex_audit.rs`(现已删除,以下仅作历史追溯):
|
||||
|
||||
- `DirectCodexTurnAudit`
|
||||
- `start` / `observe_item` / `finish`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
# 立项策划 Agent(Fast GDD)技术方案
|
||||
|
||||
- 日期:2026-08-10
|
||||
- 状态:**已退役**。本文描述的 V1 策划链路(`project-supervisor-plan` 根 Run、`project-planning` 子 Agent、`plan.submit_gdd` 工具、Fast GDD 审批门禁与恢复机制)已由策划会话 Runtime V2 取代,源码已于 2026-09 按四不写原则整体删除;现行方案见 `【技术方案】策划会话RuntimeV2接入与旧链路退役-2026-09-03.md`。本文仅作为历史推导记录保留。
|
||||
- 状态:**历史方案,已退役**。策划 V1 和曾接替它的 Runtime V2 均已删除,V2 不是现行方案。当前策划入口统一使用独立 Design Agent,见[策划 Agent 生产迁移与工作区浏览](./【技术方案】策划Agent生产迁移与工作区浏览-2026-09-10.md)。本文仅供历史追溯,不要求恢复旧 Runtime、审批、工具、身份门禁、持久化协议或专属测试。
|
||||
- 适用范围:AI 游戏创作独立 App、Project Supervisor、Agent Runtime、本地项目策划 sidecar 与后续完整构建准入
|
||||
|
||||
> 当前口径(2026-08-30):以本文件中标注的 D11 / 最新修订和当前 `apps/ai-game-creator-shell` 实现为准。D6~D9 等被明确标注为作废或被取代的段落仅保留推导背景,不得作为现行拓扑、入口或 Runtime 真相;产品入口与 DirectProject 总体口径见 `docs/README.md` 和 App 实施计划。
|
||||
> 历史内容边界(2026-09-23):下文的 D11、版本修订、“当前”“必须”和验收要求均描述退役前的 V1,不能覆盖现役 Design Agent 合同。包括 exact planning lifecycle v3、`planningSessionBinding` 和 `plan.submit_gdd` 在内的旧要求,不构成恢复实现或保留孤立代码的依据。
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# 策划 Agent 生产迁移与工作区浏览方案
|
||||
|
||||
更新时间:2026-09-21
|
||||
更新时间:2026-09-23
|
||||
状态:已完成(2026-09-18)
|
||||
|
||||
> 现状说明(2026-09-18):本文记录的迁移已完成,当前策划入口统一使用 Design Agent。旧 Planning V1/V2 会话、专用命令、审批卡和展示适配已删除;文中提到的 V2 文件仅代表迁移时的参考来源,不得作为现行实现、回退路径或测试迁移目标。
|
||||
|
||||
策划 V1 和 V2 的退役均已确定,不再作为待实施迁移。旧 `plan.submit_gdd`、planning session binding、exact planning lifecycle v3、V1 专属工具身份白名单与 V2 IPC/Runtime 均不属于当前合同。清理孤立常量、未用参数、包装和旧说明时,不为满足这些历史要求恢复代码或迁移专属测试。共享锁、通用持久化、资源权限和当前 Design Agent 的会话、澄清、阶段审批按实际现役调用保留;用户已有文件不因源码清理而删除。
|
||||
|
||||
## 1. 目标
|
||||
|
||||
将 `local-scripts/design_agent_refactored` 中已经验证的自由协作型策划 Agent 迁移到生产 App。生产代码只提供可靠的运行基础设施,Agent 的工作方式以原型为准。
|
||||
@@ -276,6 +278,13 @@ concept → top_design → architecture → systems → tdd → consultant
|
||||
|
||||
`systems: []` 是已确定的行为,不是迁移时需要补齐的缺口。`project/analysis.md`、`project/决策台账.md`、`project/dialog.md` 保持原型中的共享过程文件口径,不升级为新的审批必需项。速览卡保留原型结构提示,但 Runtime 与 UI 不解析其章节或内容字段。
|
||||
|
||||
提示词中的路径是策划 Agent 使用的相对路径约定:
|
||||
|
||||
- `project/...` 以策划工作区为根,Agent 将其传给 `read_file`、`write_file`、`patch_file` 等文件工具来读取和维护正式产物及过程文件。宿主将它映射到项目的 `design_artifacts/project/...`;阶段审批按登记的相对路径检查必需产物。提示词写明 `project/速览卡.md`、`project/analysis.md` 等目标位置,是在告诉 Agent 文件应写在哪里,并非泄露宿主绝对路径。
|
||||
- `resources/skills/...`、`resources/templates/...`、`resources/exemplars/...` 和 `resources/modules/system-types/...` 指向随应用发布的固定策划资源包,用于定位分册、模板、例子及系统类型资料,不是策划工作区的写入目标。资源目录在 `resources/catalog.json` 中登记相对路径与资源 ID;Agent 可用 `list_resources` 查 ID,再用 `read_resource` 按 ID 读取。分册中省略 `resources/` 前缀的 `templates/...` 等写法仍指同一资源包内的位置。
|
||||
|
||||
这些路径直接服务于 Agent 的文件操作和资源查阅,属于提示词应保留的契约;即使阶段上下文也注入了某条产物路径,分册和模板中的路径仍提供目标文件与交叉引用的具体定位。去除客户端与宿主实现细节时,不应把这类相对路径当作意外暴露的内部实现;宿主安装目录、项目绝对路径及会话控制文件位置才不属于 Agent 的操作输入。
|
||||
|
||||
过程文档记录关键依据、决定和待办,不要求实时完整,也不应重复正式设计文档;阶段提交前补齐影响验收的关键记录。顶层设计的分册、模板和示例保留核心定位及按需说明的易混淆方向与排除理由,不强制使用固定的“不是 X,而是 Y”句式。
|
||||
|
||||
进入下一阶段必须由用户批准触发。Runtime 推进后向 Agent 追加明确的用户行为语义,例如“用户已批准上一阶段,现在进入顶层设计阶段”,避免 Agent 误认为 Runtime 自行推进。
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- 状态:**历史方案,已完成并退役**。Runtime V2 及其专用入口、命令、展示和测试已在 2026-09 按四不写原则删除;当前“做方案”统一使用独立 Design Agent。
|
||||
- 适用范围:历史 AGC“做方案”入口、策划会话、GDD 产物与审批设计
|
||||
|
||||
> 本文只用于追溯 Runtime V2 的设计和退役过程,不是现行实现依据。不要恢复 `planning_session_v2`、`planning_policy_v2`、`hydrate_planning_session_v2` 或 V2 专用 UI;当前行为以 Design Agent 生产迁移方案和代码为准。
|
||||
> 本文只用于追溯 Runtime V2 的设计和退役过程,不是现行实现依据。策划 V1、V2 均已删除,不保留兼容别名、双跑或回退路径;不要恢复 `planning_session_v2`、`planning_policy_v2`、`hydrate_planning_session_v2`、专属审批/UI 或旧测试。当前行为以[Design Agent 生产迁移方案](./【技术方案】策划Agent生产迁移与工作区浏览-2026-09-10.md)和代码为准,下文的版本要求与验收清单仅描述历史实现。
|
||||
|
||||
## 1. 决策摘要
|
||||
|
||||
|
||||
@@ -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 触发不稳定,只需要调整前台时长实现方式或降级为会话时长,不需要推翻整个埋点方案。
|
||||
Reference in New Issue
Block a user