# M4「AI 创作」开工汇总 **日期**:2026-09-14 **状态**:开工分析完成,待拍板 **上一迭代**:M3.5 收官、v0.4.0 已发布 --- ## 0. 本页的使用纪律 本页是 8 份开工报告(合计 7448 行)的**转述层**,存在的目的是让拍板不必翻全文。 但本批分析最大的发现恰恰是**「转述即污染」**:十余处文档与注释所写与代码实际所做相反,且多数已被下游报告采信,直接造成过规模误判(见 §6)。因此: - 本页每条结论都标注**来源报告编号**(如 `[02]`)。要动手实现或据此拍板时,**回读该报告的取证行号,不要止步于本页**。 - 本页**不新增任何结论**。凡本页出现而来源报告中没有的判断,视为本页的错误。 - 各报告末尾均有「取证边界 / 未取证项」附录,汇总见 §7。**未取证项不得当事实使用**。 --- ## 1. 报告索引 | # | 报告 | 行数 | 一句话 | |---|---|---|---| | 01 | [任务分解](01-pm-task-breakdown.md) | 742 | 28 工单 / 4 波 / 14 决策;推翻 8 处既有结论 | | 02 | [后端技术评估](02-backend-technical-assessment.md) | 1114 | 队列方案、新模块、V6+V7、契约 +4/+5/+8;10 决策 | | 03 | [Flutter 技术评估](03-flutter-technical-assessment.md) | 1670 | 自适应轮询、13 处 AI 模拟定位、测试 +300;11 决策 | | 04 | [现实核查](04-reality-check.md) | 687 | 总体 **NEEDS WORK**,AI provider **BLOCKED** | | 05 | [AI 创作 UI 规格](05-ai-create-ui-spec.md) | 1117 | 8 界面单元、等待态形态、新建 8 复用 16;18 决策 | | 06 | [埋点与实验规划](06-experiment-tracking-plan.md) | 762 | 字典 41→49、eventVersion 定型、A/A 空跑;10 决策 | | 07 | [基线证据审计](07-evidence-baseline-audit.md) | 550 | 基线逐条对账 6 对 3 错、真机项清点、发布流程一致性 | | 08 | [Git 流程规划](08-git-workflow-plan.md) | 806 | 门禁漏洞、分支策略、契约升版顺序、v0.5.0 门禁;10 决策 | 决策总计约 **73 项**,本页只提炼需要跨角色协调或阻塞开工的部分(§3、§4);其余为各报告内的细节决策,随工单执行时就地拍板。 --- ## 2. 基线实测(开工基准) 三仓工作区洁净、均停 `v0.4.0`;HEAD:api `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) | **10**(M2 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,无 V6;`V5: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 0,102 页零孤立 | 对 `[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/kvm` 为 `crw-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-264`、`V5:45-46`、`V5: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/:35`、`feature-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]`:机械可数 226(210 `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` 亦无 `chipTheme`(0 命中),与 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.dart` 与 `post_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.md` 的 `checklist\|发布\|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=**18**,`experiment_exposed` 被重复计数;`EventDictionaryTest` **零条数断言**故漂移不可见 | 4 份文档 `[07][06]` | | 8 | `releases.md:17/:35`、`feature-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/05` 引 `integration_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` 只校验归属 + ready,`MediaAssetRef.java:9-16` 与 `MediaAssetGateway` 的 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×4,4 波 | `[01]` | | 关键路径 | 4 个 L 单:后端队列 2 + 客户端状态机 2(与 M3「媒体双端占其二」同型) | `[01]` | | Flyway | **2 个**:V6(creation schema 三表 + 13 索引 + 3 触发器 + 补回 `posts.generation_job_id` 外键)、V7(目录种子)。creation schema 零结构偏离,逐列抄目标模型 | `[02]` | | 契约 | v1.4.0 → **v1.5.0 纯增量**:+4 路径 / +5 操作 / +8 schema(32/45/75 → **36/50/83**)、+3 错误码、改 4 个既有 schema;零删除零重命名零必填收紧。「一键建草稿」复用既有 `POST /api/v1/posts`,**0 新增路径** | `[02]` | | 客户端页面 | 6 页(4 AI + 2 搭车:我的收藏 / 我的草稿) | `[03]` | | UI 界面单元 | 8(6 页 + 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_succeeded`、`post_draft_saved`)的现行白名单**无任何标识帖子来源的属性**,因此「AI 生成 → 发帖」这条 **M4 最核心的转化在现行字典下根本不可计算**。处置:各加 `creationTaskId`。另建议补一条**断言白名单条数**的测试——本批 41/42 漂移之所以四份文档不可见,正因 `EventDictionaryTest` 零条数断言。`[06]`