Files
patbond-doc/docs/development/iterations/iteration-4/00-kickoff-index.md
T
lixi 79b33dba31 docs: M4「AI 创作」开工分析八份报告 + 汇总拍板页入档挂导航
八角色并行开工分析,合计 7448 行;另出 00 汇总页(跨角色收敛结论、
13 项待拍板、6 项待仲裁分歧、未取证项汇总),挂第四迭代导航最前。
mkdocs build --strict 通过。

基线实测修正(文档与实况不符):
- api 测试 381(releases.md 记 379,成因待仲裁)
- 埋点白名单 41(四份文档记 42,experiment_exposed 重复计数)
- 真机验证挂起 10 项(转述链 4→6→8→10 每跳丢项)
- E2E 断言机械可数 226(声称 234 无可复核来源)
- v0.4.0 实际发布 09-14 11:17;CI 非红,三仓五上下文全绿

多方独立收敛(无需拍板):
- 队列用 Postgres SKIP LOCKED + 租约列,不引入 Redis/MQ
- 服务端零对象写能力(ObjectStorage 无 put/get),M4 立足点缺地基
- 「四模块字节级快照锁 CI」不存在,实际门禁仅结构断言
- 定稿模型 input_asset_id NOT NULL,即图生图不支持文生图
- 跨 schema 外键补回是 V5 自身指令,裁剪理由已不成立

阻塞项与安全缺口:
- AI provider BLOCKED:零 SDK/endpoint/额度,正典种子即 fixture
- 分支保护必需上下文选错触发器:(push) 限定 branches:[dev],
  致「推 dev 即满足门禁」且「非 dev 分支 PR 永久无法合并」
- check-secrets.sh 对 sk-/sk-ant- 零覆盖,须先于任何 AI key 落地
- 北极星 09-21 窗口已于 09-13 关闭,补救无从下手,建议改事件驱动

本批核心教训:13 处文档/注释与代码相反且多已被下游采信,其中
5 处造成实际规模误判(widthPx M→S、数据模型早已定稿 L→M、
社区侧 purpose 校验实际不存在等)。汇总页 §0 立转述纪律。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 15:48:56 +08:00

24 KiB
Raw Blame History

M4「AI 创作」开工汇总

日期2026-09-14 状态:开工分析完成,待拍板 上一迭代M3.5 收官、v0.4.0 已发布


0. 本页的使用纪律

本页是 8 份开工报告(合计 7448 行)的转述层,存在的目的是让拍板不必翻全文。

但本批分析最大的发现恰恰是**「转述即污染」**:十余处文档与注释所写与代码实际所做相反,且多数已被下游报告采信,直接造成过规模误判(见 §6)。因此:

  • 本页每条结论都标注来源报告编号(如 [02])。要动手实现或据此拍板时,回读该报告的取证行号,不要止步于本页
  • 本页不新增任何结论。凡本页出现而来源报告中没有的判断,视为本页的错误。
  • 各报告末尾均有「取证边界 / 未取证项」附录,汇总见 §7。未取证项不得当事实使用

1. 报告索引

# 报告 行数 一句话
01 任务分解 742 28 工单 / 4 波 / 14 决策;推翻 8 处既有结论
02 后端技术评估 1114 队列方案、新模块、V6+V7、契约 +4/+5/+810 决策
03 Flutter 技术评估 1670 自适应轮询、13 处 AI 模拟定位、测试 +300;11 决策
04 现实核查 687 总体 NEEDS WORKAI provider BLOCKED
05 AI 创作 UI 规格 1117 8 界面单元、等待态形态、新建 8 复用 16;18 决策
06 埋点与实验规划 762 字典 41→49、eventVersion 定型、A/A 空跑;10 决策
07 基线证据审计 550 基线逐条对账 6 对 3 错、真机项清点、发布流程一致性
08 Git 流程规划 806 门禁漏洞、分支策略、契约升版顺序、v0.5.0 门禁;10 决策

决策总计约 73 项,本页只提炼需要跨角色协调或阻塞开工的部分(§3、§4);其余为各报告内的细节决策,随工单执行时就地拍板。


2. 基线实测(开工基准)

三仓工作区洁净、均停 v0.4.0HEADapi dev@3cd8005 / flutter dev@fbcd734 / doc main@5cc6361[07][04]

文档声称 实测 裁决
api 测试 379 381 文档错(成因待仲裁,见 §4-2[07][04]
flutter 测试 597 597 通过 + 2 skipped 数字对,skip 从未披露 [07]
埋点白名单 42 41 文档错,根因 experiment_exposed 重复计数 [07][06]
真机验证挂起 8(或 4/6 10M2 2 + M3 4 + M3.5 4 文档错,转述链每跳丢项 [07][04]
E2E 场景 42 42 [07][04]
E2E 断言 234 机械可数 226 差异待仲裁,见 §4-6 [04]
契约 v1.4.0 32/45/75 逐格相符 [07][04]
四模块快照 字节一致 md5 a7081fb8…5801 五处一致 副本一致为真,但无 CI 保证(§6-2[07][04]
契约矩阵 181 格 表格自洽,不可机械复核 只存在于报告散文;代码唯一规模断言是 operations()==45 [04]
Flyway V1~V5 V1~V5,无 V6V5:48 generation_job_id uuid,REFERENCES [07][04]
ADR 001~022 22 条无缺号 [07]
容器 六容器 postgres/minio/auth/user/pet/community 对;无 Redis、无 MQ [07][02]
文档站 可构建无死链 mkdocs --strict exit 0102 页零孤立 [07]
CI 「仍红」(iteration-3.5/04 §7.3 三仓五上下文 09-14 全 success 过期快照,勿当风险继承 [04][08]
v0.4.0 发布时间 09-11 09-14 11:17 文档错 [08]

3. 多方独立收敛的结论(证据已定,无需拍板)

结论 独立证实方
队列用 Postgres FOR UPDATE SKIP LOCKED + 租约列,不引入 Redis/MQ。目标模型已备好六列租约字段与两条与出队/回收语句逐列对齐的部分索引(patbond_postgresql.sql:605-716,现成领取 SQL 在 :1896-1917);换中间件等于让这批列作废、推翻已评审模型。缺的只有租约超时回收器。 [01][02][04]
服务端零对象写能力ObjectStorage 仅 4 方法,putObject、零 getObject。故「媒体链路可直接复用」只对读侧与客户端上传侧成立,Worker 落产物与喂输入均为净新增。这是 M4 立足点缺失的一块地基。 [01][02][04]
「四模块字节级快照锁 CI」不存在CI 只有 check-secrets.sh + mvnw test,无任何 diff/校验和;实际门禁是结构断言(版本串 + 计数 + tag 操作集)。后果:只改 description 的契约漂移,四模块全都不会红。 [01][02][04][08]
定稿模型是图生图,不支持文生图input_asset_id uuid NOT NULL [01][02][05]
「等真机设备」是伪阻塞:本机 Pixel_7 AVD 可启动、/dev/kvmcrw-rw-rw-、android-36 镜像在位,而 device-verification.md:9 明文接受「Android 真机(推荐)或 Android 模拟器」。 [04][06]
契约完全没有 429 / Retry-After / 任何响应头机制components.headers: [],全契约 headers: 零命中);后端 429 亦零命中。M4 是首次引入。 [03][04][05]
跨 schema 外键的裁剪理由已不成立,补回是 V5 自己下的指令V5:15-19/V3:14-19 原话为「FKs into schemas not yet migrated are STRIPPED」——理由是目标 schema 当时不存在;反证有 V1:262-264V5:45-46V5:107 三条在案的跨 schema 外键。 [02]

4. 必须开工前拍板

阻塞 V6 定稿与开工

# 决策 现状与推荐
A AI provider 选型 BLOCKED。零 provider SDK、零 endpoint、零额度;密钥面仅 4 项(DB/internal/MinIO×2);本机 AMD Vega 集显无 CUDA,自托管不可行。最硬的反证:正典种子自己写的就是 provider_code='fixture',且 generation_jobs 三个快照列 NOT NULL,逼迫显式选边。推荐 fixture provider 起步 + 可插拔适配层(M4 四条验收标准全部与图好不好看无关,fixture 还能注入真实供应商难复现的故障)。缺失的外部输入:生产服务器 GPU 情况、云 API 报价 —— 这是唯一真正卡住的外部依赖。[01][02][04]
B 参考图必填(图生图)还是可选(文生图) 三方独立指出与工单描述「可选参考图」冲突;定稿模型 input_asset_id NOT NULL,正典原文亦为「上传一张照片…」。推荐沿用 NOT NULL、图生图先行。此项同时决定 V6 能否照抄目标模型、create 页整个交互、A2 的 gating 形态。[01][02][05]
C 上游调用形态 推荐可插拔 GenerationProvider 两阶段 submit/poll。两阶段是硬要求:否则「不重复扣费」的恢复路径永不被测试覆盖。stub 用 JDK 内置 ImageIO/Java2D 出真实字节,零新依赖。[02]
D 新模块归属与命名 推荐新建模块、端口 :8085、前缀 /api/v1/creation/**命名存在冲突patbond-creation``[01] vs patbond-ai``[02]。ADR-009 原文记载「后端评估建议 user 内包,用户裁定新建模块」。代价:BearerAuthFilter 将成第 4 份(community 版 Javadoc 自称 "Third copy")、存储/配置第 4 份、UuidV7 第 3 份。[01][02]
E 4 件共享物是否上提 common 推荐同波次上提,退路是各抄一份。本迭代最大回归面,与 D 强耦合。[02]

流程与安全(建议第一波,先于相关代码落地)

# 决策 现状与推荐
F 门禁必需上下文改为 (pull_request) 现状必需上下文为 CI / backend-test (push),而 ci.yml:16-17 把 push 触发器限定在 branches: [dev]双重后果:① 门禁实际由「推 dev」满足,PR 侧检查红也能合并;② 任何非 dev 分支 → main 的 PR 永久无法合并head 永不产生 (push) 状态),使 git-workflow.md:9 的 hotfix 短命分支纪律实际是死的。正确上下文真名已从 CI 实跑记录取得(非猜测):CI / backend-test (pull_request) / CI / flutter-gates (pull_request)推荐替换而非追加(追加不解除 hotfix 死锁),改完做一次空 PR 验证,勿拿正式发布当试验场。[04][08]
G check-secrets.sh 补 AI 凭证规则 现有 7 条规则对 sk-/sk-ant- 零覆盖KEY-ASSIGN 只认 access_key/secret_key 不认 api_key,故 ANTHROPIC_API_KEY=sk-ant-… 全漏网。必须先于任何 AI key 落地。 另:三仓 core.hooksPath 全部 unset,防泄漏第一层完全未生效。[08]
H 北极星 09-21 时限处置 窗口已于昨日关闭,不是「来不及」:09-21 是 W37 队列(首记 09-07~09-13+8 天的成熟日,而 09-13 = 周日 = W37 最后一天,今日 09-14 已是 W38 第 1 天,此后产生的首记永远进不了 W37。补救无从下手。 且 W37 分母极可能为 0(真机执行记录全空、无分发、API 未对外、桌面 100% 丢弃)。推荐:档 A 把首次出数由日期承诺改为事件驱动触发条件(改写 device-verification.md:40 等两处)+ 档 B 09-21 仍出一次「基建就绪读数」(只报 SQL 可执行 + 实测分母 + 链路证据)。明确否决用桌面 override 或 curl 造数凑读数。另:北极星出数至今无可执行 SQL 载体iteration-2/06 §2.1 的 SQL 只存在于报告正文。[06]
I 发布流程固化去处 正典是一份标题至今写着「草案」的迭代报告,8 步里 4 步过期(第 2/3/4/6 步);git-workflow.md 全文 65 行无任何发布/PR/E2E 内容。推荐固化进 git-workflow.md 新章节,E2E 份数只在一处写死,其余位置表述为「全份」并链接过去(防复发)。[07][08]
J 文档站访问控制 登记项仅为 server-exposure.md §2 表格里一个内联 ⚠️,无责任人、无期限、「归属决策」列为空、未进 §5 行动记录。102 页全部公开,含 server-exposure.md 自身、ci-runner-setup.md、以及 09-11 安全事件复盘(端口清单、常驻服务、内部 API 路径、刚被攻击那台主机的注入路径与处置手法)。与 Gitea 同机同 nginx、共用 443、无鉴权层。防护方式存在分歧,见 §4-3。[07][04]
K 进度反馈机制 推荐自适应轮询(1s×3 → 2s×5 → 3s,上限 5s,硬超时 5min),不做 SSE/WebSocket。决定性理由:现有网络层全部围绕「信封解包 + 401/40101 单飞刷新重放一次」构建(api_client.dart:97-131,163-176),SSE 两条都用不上,等于旁路整条已建好的鉴权链、形成第二套鉴权路径——而 M3.5 端口事故的根因正是「跨模块调用绕开既有接线纪律」;且两侧流式基础设施均为零(后端 SseEmitter 0 命中、客户端 ResponseType 0 命中);A 是 B 的真子集(任何推送方案都必须有「查状态」GET 兜底,有了它轮询已免费到手)。[03][05]
L 中断恢复的事实来源 推荐服务端「我的进行中任务」端点,不做本地持久化。理由:与「服务端是唯一事实来源」纪律一致;全仓刻意没有任何业务任务态被持久化(M3 防泄漏成果),开这个口子须在 app.dart:242-249 再加一处清理,漏则是安全缺口;换设备场景下本地方案完全失效。[03]
M eventVersion 定型 定为「每个事件自身的 props schema 版本」,否决「字典世代」读法。决定性理由是可修复性不对称:此读法下客户端现行硬编码 1 本就正确(零改动零回填);「字典世代」读法下全部历史行皆错且不可修复(server_ts 无法反推事件当初属于哪代字典)。落地:白名单 key 改 (name, version) 二元组 + 新增逐条拒绝原因 unknown_event_version——必须放逐条路径,不可放 DTO 校验,否则重犯 platform 的整批连坐错误(见 §6-1)。[06]

5. 待仲裁:agent 之间的分歧(6 项)

# 分歧 两方主张
1 新模块命名 patbond-creation[01]vs patbond-ai[02])。端口 :8085 与前缀一致,仅名称不同。
2 api 测试 381 的成因 [04]3cd8005 就是那次「379→381」的契约冻结提交,releases.md:17/:35feature-checklist.md:5 照抄了冻结前的数(给出 3+131+40+100+107 分解)。[01]379 是 surefire 报告数、381 是注解数,属参数化展开差异、非回归。两解释互斥[04] 给了可核的分解,倾向 [04],但两方均未联合复跑。
3 文档站防护方式 [07]:IP 白名单(单读者、纪律 6 下不必新增凭证),或内容分层把三份敏感文件剔出公开构建。[04]basic auth。
4 A/B 前置状态口径 [01]5 绿 3 半(分流哈希、Flutter 曝光封装、feature flag 三者代码零实现)。[06]放行条件 0/6 满足,故 M4 首个「实验」应为 A/A 基建验证空跑(零产品风险,≥200 曝光即可暴露分流失衡与曝光漏报)。两者可能在数不同的东西(前置组件 vs 放行条件),需统一口径后再排期。注意:原文档「6 绿 1 半」两方均否定 —— 按它排期会在实验启动日才发现要先写三个组件。
5 429 错误码个数 [02]:单码 42900[05]必须拆两个码 —— 配额耗尽等的是明天(弹 sheet 给出口),频率过快等的是几秒(弹 SnackBar),共用一码必然有一半场景的文案和出口是错的。
6 E2E 断言数 226 vs 234 [04]:机械可数 226210 check( + M1 16 )。[07]:静态调用点 207,缺口可能由循环执行产生但原报告从未说明。声称值 234 无来源可复核。

两处属细化而非冲突,一并记录

  • SegmentedButton 债的优先级[01] 改判搭车 M4(create 页分段器正是改造对象,一次修 6 处,边际 S);[05] 实测 secondaryContainer #FFDAD2 + onSecondaryContainer #5D4038 对比度 7.19:1 达标,故是 P2 品牌一致性债、非 P1 无障碍债,不应为它拖 M4 范围。[03] 补根因:主题层无 segmentedButtonTheme 亦无 chipTheme0 命中),与 M3.5-01 修 DatePicker 完全同构app_theme.dart:215-296 是现成样板。→ 结论:搭车但降级为 P2。
  • widthPx/heightPx 的归因[01][04] 记为服务端缺尺寸探测;[03] 拆成三段事实 —— 详情页客户端已正确消费post_detail_page.dart:515-521 有 clamp,服务端一给即生效)、Feed 卡片是客户端硬编码缺陷post_card.dartpost_media_grid.dart:326-327 硬编码 4:3,维度可用却被忽略)、客户端根本无法提供维度CreateMediaUploadRequest 契约无该字段)。→ 必须两侧同批改,只修一侧用户零感知。[05] 补严重度判断:不是「更严重了」而是**「从看不见变成看得见」——A4 用 job 自己的 width/height 画出完整构图、发到 Feed 后被裁成 4:3,是同一次会话内的直接前后对照**,9:16 竖图裁掉约 58%,用户结论会是「发布把我的图裁坏了」。修复成本极低(Worker 写 output asset 时 job 的 width/height 就在手里)。

6. 「文档与代码相反」清单(本批核心教训)

M3.5 曾因一句转述(报告写「无 nickname 字段」实指「契约未暴露」)把规模预估高估一整档。本批发现该模式远非孤例

# 说谎处 实际情况 已污染范围
1 analytics_service.dart:99-102 注释称「逐条 rejected、不影响客户端」 与实现相反TrackEventsRequest.java:16@Valid 级联到列表元素 → 任一元素失败即整请求 400 → 客户端 :273-281 视为永久拒绝并整批删段这是一个与平台无关的「毒丸批次放大器」:任何一条事件的任何一个字段失败都会毒死整批 50 条。桌面采集能力为零。 转述进 5 处文档 [03][06]
2 CI 自称 "byte-identical"、文档称「四模块字节级快照锁 CI」 CI 零 diff、零校验和;md5 比对是人工步骤 4 份报告 [01][02][04][08]
3 releases.md 同一文件 :36/:56「四份」vs :131「双份」 前瞻侧(给 M4 用的那条)写错,照它执行漏跑 17 个场景 [07][04][08]
4 发布 checklist iteration-3/08:84「跑 M2+M3 两份 应为全份;且该 checklist 标题至今是「草案(验证后固化进 git-workflow.md)」,固化从未发生grep git-workflow.mdchecklist|发布|E2E|PR 零命中) [07][08]
5 openapi.yaml:1228「purpose 仅 post_image :3460 三值枚举矛盾(M3.5 加值时漏改端点描述)。M4 再加值必须一并修,否则第三次漂移 [03]
6 PostMediaAttachIntegrationTest:44-45 断言 640/480 是绿的 CommunityTestData:55 夹具直插。测试绿 ≠ 生产有值,生产恒 null [04]
7 feature-checklist.md:218「community 域 19 条」 算术错误,代码自身注释拆分为 8+2+8=18experiment_exposed 被重复计数;EventDictionaryTest 零条数断言故漂移不可见 4 份文档 [07][06]
8 releases.md:17/:35feature-checklist.md:5 的 379 照抄了契约冻结前的数,实测 381 [04][07]
9 releases.md:121 整段漏掉 M3.5 真机项转述链 4→6→8→10 每跳都在丢项 [04][07]
10 releases.md:47「分支保护确实要求该 (pull_request) 检查」 表象对、机制归因错:真正解锁合并的是 09:44:05 转绿的 (push) [08]
11 iteration-3.5/04 §7.3「CI 仍红」 过期快照;同一 run 73 已于 09-14 09:38 重跑、09:44 转绿 [04][08]
12 iteration-3.5/05integration_test/ 证「桌面链路可用」 那 4 份真机测试完全在 flutter test 之外,无任何门禁会跑。凡「桌面/真机实测已验证」一律降级为「有脚本,无门禁」 [07][03]
13 M3 建议「话题随 ai_creation 一起做」 ai_creation 只是 category 枚举值,与 topics 表零字段关联,搭车理由不成立 [01]

由此造成的既有误判(本批已纠正)

  • widthPx/heightPx 规模 M→S(列早已存在于 V1:217-218,缺的只是尺寸探测)[01]
  • 「M4 需设计数据模型」→ 完整设计早已定稿3 表 40 列 11 索引),且零跨 schema FK 需裁剪T4-01 由 L→M [01]
  • 「社区侧有 purpose 白名单校验」→ 不存在PostService.validateAssets:343-358 只校验归属 + readyMediaAssetRef.java:9-16MediaAssetGateway 的 SQL 均不含 purpose 列(对比 pet 侧 PetService.java:196 确有校验)。后果:不补强制校验,「AI 创作」标签可被任意图片伪造。 [02]
  • 「需评估 DB / Redis / MQ 三选一」→ 前提本身多余,目标模型已把租约队列设计完(§3)[02][04]
  • 「A/B 前置 6 绿 1 半」→ 两方均否定(§5-4)[01][06]

7. 未取证项汇总(不得当事实使用)

缺什么 阻塞谁
生产服务器 GPU 情况、云 API 报价 外部输入 决策 A(阻塞开工) [01]
E2E 断言精确值(226 / 234 脚本无计数器;循环执行未证 门禁数字口径 [04][07]
契约矩阵 181 格 只存在于报告散文,无机械可数载体 契约漂移检测可信度 [04]
分支保护「禁直推」的具体机制 /branch_protections 返 401/branches/main 匿名可读故主结论仍成立) 决策 F 的复核 [08]
E2E 零失败重跑、零迁移实证 compose 未起 发布门禁复现 [04][07]
check-secrets.sh 实际效力 未实跑 决策 G [04][07]
服务器侧实际暴露面 只做了文档取证,未探测服务器 决策 J [04][07]
服务端是否探测图片尺寸、page_viewed props 取值集合 等 6 项 [03] 附录 A 相关工单 [03]
实验设计模板文档实体、北极星出数 SQL 载体 均无实体 决策 H [01][06]
厂商侧参数配比、配额默认值、单机资源余量 需产品/运维确认 后端工单 [02]

8. 规模概览(各报告独立估算,未经交叉校准)

维度 M4 预期 来源
工单 28(含 3 条件单),S×5 / M×16 / L×44 波 [01]
关键路径 4 个 L 单:后端队列 2 + 客户端状态机 2(与 M3「媒体双端占其二」同型) [01]
Flyway 2 个V6creation schema 三表 + 13 索引 + 3 触发器 + 补回 posts.generation_job_id 外键)、V7(目录种子)。creation schema 零结构偏离,逐列抄目标模型 [02]
契约 v1.4.0 → v1.5.0 纯增量+4 路径 / +5 操作 / +8 schema32/45/75 → 36/50/83)、+3 错误码、改 4 个既有 schema;零删除零重命名零必填收紧。「一键建草稿」复用既有 POST /api/v1/posts0 新增路径 [02]
客户端页面 6 页(4 AI + 2 搭车:我的收藏 / 我的草稿) [03]
UI 界面单元 86 页 + 1 sheet + 1 全局层),新建组件 8 / 复用 16(6 需小改) [05]
客户端测试 597 → 约 897(建议 +300 [03]
E2E 42 → 54 场景;新增第五份 test_e2e_m4_manual.dart [03][08]
埋点字典 41 → 49(新增 8 条 creation 域 + 2 处既有事件加属性 + 启用 experiment_exposed,废弃 0 [06]
demo 消亡 create_page.dart 563 行 → 约 40 行13 处模拟) [03]

9. 今天即可执行的两件事

  1. M2 两项真机验证 —— 约 55 分钟(其中 35 分钟纯等待),模拟器合规、Pixel_7 AVD 已就位,只差导出 ANDROID_HOME/PATH已白拖 6 天;虽已错过 W37 窗口(决策 H),但它把最早可得读数从「无限期」拉到 2026-09-28[04][06]
  2. check-secrets.sh 补 AI 凭证规则 —— 决策 G,须先于任何 AI key 落地。[08]

10. 必须与写侧同批修掉的两处(否则 M4 制造新缺陷)

  1. 数据损坏路径post_compose_page.dart:209-211 把恢复的 AI 草稿类目静默降级为 general。现在无害(写侧被封),M4 放开写侧后会把类目改错并写回服务端 —— 必须与放开写侧同一个提交改掉。[03]
  2. CommunityMigrationIntegrationTest.java:81-88 断言 fkCount == 0 —— V6 补外键必然让它变红,需拆成 generation=1 / region=0。提前知道可省一轮排查。[02]

11. 两条会影响 M4 观感的客户端纪律

  1. 绝不能承诺推送:客户端无任何推送能力(无 WS/SSE/FCM/相关端点)。等待页写「完成后通知你」会让用户锁屏等推送然后什么都收不到。正确说法是「回到 App 就能看到结果」。[05]
  2. 不要押注百分比进度generation_jobs 的 CHECK 规定 queued 时 progress 恒 0、running 时 progress 无下限约束,押注「会有百分比」的后果是最常见观感变成「0% 卡住」。故主形态为阶段文字 + 不确定进度环,progress>0 才叠确定型数字;不展示 ETA,改展示已用时(已用时是事实,ETA 是承诺,而 M4 给不出可信 ETA)。另需定义服务端 5 个 status 之外的第六个 UI 态:僵死/超时running 超阈值),且它不是错误态。[05]

12. M4 核心指标当前算不出来

两个 post 事件(post_publish_succeededpost_draft_saved)的现行白名单无任何标识帖子来源的属性,因此「AI 生成 → 发帖」这条 M4 最核心的转化在现行字典下根本不可计算。处置:各加 creationTaskId。另建议补一条断言白名单条数的测试——本批 41/42 漂移之所以四份文档不可见,正因 EventDictionaryTest 零条数断言。[06]