# 04 · M2 开工前现实核查(Reality Check · 复核版 v2) - 核查人:Reality Checker(TestingRealityChecker,正式接管复核) - 日期:2026-09-07(复核);初版同日由通用核查人代写,本版为逐条重验后的接管版 - 方法:**不采信任何书面转述**。所有结论分三档标注——【亲验】命令自己跑、输出自己看;【UNVERIFIED】本地无法复现、明确不采信;【勘误】初版或同伴报告与实测不符之处 - 约束遵守:只读核查 + 运行测试/构建/匿名 API 查询;零生产代码改动、零 commit/push、未改 mkdocs.yml --- ## 0. 裁定(先说结论) **M2 开工 readiness:CONDITIONAL PASS(附条件放行)。** 测试与 CI 基线的证据是压倒性的且全部由本人亲验:后端 82/82、前端 34/34、flutter analyze 0 问题、mkdocs strict 通过、三仓 HEAD 的 CI 状态经 Gitea commit status API 亲查全为 success。代码仓(api/flutter)工作树干净且与远端一致。 不给 CERTIFIED 的理由:①patbond-doc 工作树当前**不干净**(第一迭代最高风险模式的复发苗头,见 §1 勘误);②D-1 契约缺口属实且因埋点接线问题而升级;③**生产 App 埋点整体空转**(亲验坐实,见 §3.1);④E2E 通道状态 UNVERIFIED。放行条件见 §5。 --- ## 1. 初版七项核查的逐条复验 ### RC-1 三仓 Git 状态 — 【亲验,**部分勘误**】 `git status --porcelain` + `git rev-list --count @{u}..HEAD` 逐仓实测(2026-09-07): | 仓库 | 分支 | 工作树 | 未推送 | 本地=远端 HEAD | | --- | --- | --- | --- | --- | | patbond-api | dev | 干净 | 0 | `0d81c38` ✓ | | patbond-flutter | dev | 干净 | 0 | `3f8388e` ✓ | | patbond-doc | main | **不干净** | 0(已提交部分) | `5537f92` ✓ | **勘误(初版 RC-1 与 08 号报告的「三仓干净」已过时)**:patbond-doc 当前有 `mkdocs.yml` 未提交修改(挂载第二迭代 8 份报告的导航)+ `docs/development/iterations/iteration-2/` 整目录(8 份开工报告)未跟踪。这些是本波次自产内容而非第一迭代残留,但**8 份开工报告 + 导航变更全部未提交、未推送**——这正是第一迭代教训里「文档长期不 commit」的同款模式,列为放行条件 1。 ### RC-2 后端测试基线 — 【亲验属实,**初版计数勘误**】 命令:`JAVA_HOME=/usr/lib/jvm/java-17-openjdk ./mvnw test`(本人重跑,BUILD SUCCESS,35.6s,0 失败 0 错误 0 跳过)。 - 逐模块汇总行实测:common **3**、user **48**、auth **31**,合计 **82**,与「82 全绿」声称一致。 - **勘误**:初版写「user 47」且「3 + 47 + 31 = 82」——3+47+31=81,算术不自洽;实测 user 模块汇总行为 `Tests run: 48`(初版自己罗列的 10 个测试类之和 5+1+7+13+5+3+3+1+7+3 也是 48)。结论未变,但这种笔误正是不能采信书面数字的例证。 - Testcontainers 正常(集成测试全过即为 Docker 可用的实证)。 ### RC-3 前端测试基线 — 【亲验属实】 `flutter test` 本人重跑:`00:05 +34: All tests passed!`,34/34。另补跑 `flutter analyze`:**No issues found**(0.7s),与 `3f8388e` 提交声称的「analyze 清零」一致。 ### RC-4 文档构建 — 【亲验属实】 `mkdocs build --strict` 本人重跑:通过(0.67s)。注意本次是在**已挂 iteration-2 导航的未提交 mkdocs.yml** 下通过的——即当前未提交导航不破坏门禁,提交后 CI docs-build 预期同样能过。mkdocs 1.6.1(pip user 安装 / Python 3.14)实测在位;本地 pip 与 CI apt 渠道不同的版本漂移注意项维持有效。 ### RC-5 OpenAPI 契约缺口 D-1 — 【亲验属实,严重度上调理由见 §3.1】 `docs/api/openapi.yaml` 全文 grep `events`:**0 命中**。契约仅 5 端点:`/api/v1/auth/register`(:54)、`/login`(:86)、`/refresh`(:126)、`/logout`(:159)、`/me`(:188)——行号与初版一致。`POST /api/v1/events` 已实现、已测(AnalyticsIntegrationTest 7 用例在本次 82 里全绿)却游离于契约之外,**D-1 属实**。 ### RC-6 环境事实 — 【亲验属实】 JDK 17.0.20.1、Docker Server 29.7.2、Flutter 可用(test+analyze 实跑)、mkdocs 1.6.1——均本人实测。初版「CI runner 本地不可核实」一条**已被 §2 的亲验取证取代**。 ### RC-7(初版)E2E 7/7 — 【**UNVERIFIED**,明确不采信】 真机联调 E2E 7/7 与「契约偏差 0」依赖起双服务 + 真机,本地无法复现,本人未取得任何一手证据。初版用词「书面采信」,本版改判 **UNVERIFIED**:该结果只代表 2026-09-04 收官时点,通道今日是否仍活没有证据。列为放行条件 3。 --- ## 2. CI 状态取证(初版 D-2 留白,本版补齐)— 【亲验,全绿属实】 Gitea commit status API 逐仓亲查(匿名 GET `…/api/v1/repos/zhaoyuxi//commits//status`): | 仓库 | HEAD | state | context | 耗时 | | --- | --- | --- | --- | --- | | patbond-api | `0d81c38` | **success** | CI / backend-test (push) | 3m18s | | patbond-flutter | `3f8388e` | **success** | CI / flutter-gates (push) | 50s | | patbond-doc | `5537f92` | **success** | CI / docs-build (push) | 12m21s | 08 号报告「CI 状态经 commit status API 逐仓核实」**属实**,D-2 关闭。 **附带发现(低,需用户确认意图)**:上述 API 从本机**匿名(无 token)即可读取**,仓库信息(含 owner 邮箱)对未认证请求可见。若 Gitea 实例意图私有,建议核对实例的匿名访问/仓库可见性设置。本报告不含任何凭据。 --- ## 3. 同伴报告高影响声称抽查(3 证实 + 2 证伪/纠正) ### 3.1 「AnalyticsService 生产未接线」— 【亲验**证实**,且比声称更严重】 调用链逐行核对:`lib/main.dart` → `runApp(const App())`;`lib/app/app.dart` 全文**零** analytics 引用,`_buildRepository()`(app.dart:38-51)构造 `ApiAuthRepository` 时不传可选参数 `_analytics`(auth_repository.dart:38、:45 `AnalyticsService? _analytics`)→ 生产路径 `_analytics` 恒为 null,登录/注册/退出三个已挂接点(auth_repository.dart:62-119)的 `_analytics?.` 调用**全部空转**。全仓 grep:`AnalyticsService(` 仅在其自身定义与测试中出现。 **推论(此前无人点破)**:生产 App 自 M1 上线以来**从未发出过任何事件**。06 号报告的 M2 指标体系、对账 SQL、「M1 存量指标不回退」护栏全部建立在有数据流入的假设上——接线不修,M2 全部指标为零数据。D-1 因此升级:修接线必然要消费 `POST /api/v1/events`,契约缺口必须先补。 ### 3.2 「bootstrap SQL 1156~1166 行四条跨 schema 外键」— 【亲验**证实**,01 号报告准确】 `docs/database/patbond_postgresql.sql` 实测:`ALTER TABLE pet_health.pet_vaccinations`(:1156)加 `fk_vaccinations_provider`(:1157)/`fk_vaccinations_booking`(:1159),`ALTER TABLE pet_health.health_events`(:1162)加 `fk_health_events_provider`(:1163)/`fk_health_events_booking`(:1165),四条均 REFERENCES `marketplace.providers/bookings`。01 号报告 T2-01 的行号与「V3 必须剥离」裁剪项**完全属实**。 **勘误(02 号报告 :32 被证伪)**:02 号称「目标模型中 `pet_vaccinations.provider_id/booking_id`、`health_events.provider_id/booking_id` 本就未设 FK(预留列)」——**与 SQL 原文不符**,外键就在上述行号。两报告矛盾时以 01 号为准;照抄 bootstrap SQL 的 V3 在无 marketplace schema 的干净库上会直接失败(01 号 R3 风险为真)。 ### 3.3 「analytics_service.dart 三处偏差」— 【亲验**证实**,另发现 06 号一处基线失实】 06 号报告 §0 三处偏差逐行核对,行号全部命中: 1. sessionId 每事件独立生成:analytics_service.dart:55 `'sessionId': const Uuid().v4()` ✓ 2. eventId 用 UUID v4 非 v7::50 `'eventId': const Uuid().v4()` ✓ 3. appVersion/osVersion 硬编码::57 `'1.0.0+1' // TODO`、:58-61 `'android-14'/'ios-17' // TODO` ✓ **勘误(06 号基线表另一行被证伪)**:06 号称「Flutter 队列 | shared_preferences 持久化,上限 500 条」——这是照抄了文件头**过期注释**(:6-9)。实际实现:**内存队列、阈值 20 条**(:18-19 注释自认「持久化队列留 M1」、:25 `_pendingEvents`),上传失败**整批丢弃**(:80-84)。App 一杀进程未满 20 条的事件全部丢失。06 号「事件丢失率 < 5%」的护栏在此实现下无保障——不过在 §3.1(根本没接线)面前,这暂时只是第二层问题。 --- ## 4. 「声称 vs 实际」差异表(复核版) | # | 声称 | 实测 | 严重度 | | --- | --- | --- | --- | | D-1 | OpenAPI 契约正式化 | 缺 `POST /api/v1/events`(grep 0 命中);因 M2 必须修埋点接线并消费该端点,从「中」**上调为高优先** | **中→高** | | D-2 | CI 全绿 | 本人 API 亲查三仓 HEAD 全 success,**关闭** | 已关闭 | | D-4(新) | 三仓干净(初版 RC-1、08 号) | patbond-doc 现有 mkdocs.yml 修改 + 8 份报告未跟踪,全部未提交未推送 | **中**(流程风险复发苗头) | | D-5(新) | 埋点「已挂 3/5 挂接点」(19/06 号語境暗示在采数) | 生产装配未接线,事件流恒为零;挂接点代码存在但空转 | **高**(M2 指标体系的前提为假) | | D-6(新) | 06 号:队列 shared_preferences 持久化 500 条 | 内存队列 20 条、失败丢弃(代码 :18/:25/:80-84) | 低(被 D-5 覆盖,接线后需修) | | D-7(新) | 02 号 :32:目标模型未设 provider/booking FK | bootstrap SQL :1156-1166 四条跨 schema FK 确凿存在,01 号正确 | 中(若按 02 号理解仍会做对,但依据是错的;V3 评审须以 SQL 原文为准) | | D-3 | (环境)本地 mkdocs pip vs CI apt | 维持初版判断 | 低 | | — | E2E 7/7、真机契约偏差 0 | **UNVERIFIED**(本地不可复现,无一手证据) | 待 M2 早期回归裁决 | 初版「7 项核查 6 项属实、1 项部分属实」的口径修正为:**核心测试/CI/环境基线全部亲验属实;但初版自身含一处计数错误(RC-2),且其「三仓干净」结论在当前时点已失效**。 ## 5. 放行条件清单(CONDITIONAL PASS 的条件) 1. **提交并推送 patbond-doc 当前未提交内容**(8 份开工报告 + mkdocs.yml 导航),第一波内完成,CI docs-build 须绿。不允许带着未提交文档开工——这是第一迭代原教训。 2. **契约冻结前把 `POST /api/v1/events` 补入 openapi.yaml**(或书面拍板「内部契约不入 OpenAPI」并留痕)。M2 走契约先行,基线契约不能自带游离端点。 3. **M2 第一波跑一轮 E2E 回归**,把 UNVERIFIED 的联调通道状态变成一手证据;通道已腐化则立刻修,不许拖到中后期。 4. **埋点生产接线立为 M2 显式工单**(App 装配传入 AnalyticsService + 06 号三偏差修复 + 队列持久化按 06 §3 验收),并在工单中注明「当前生产事件流为零」这一事实,防止指标基线被误读。 5. **V3 迁移评审以 bootstrap SQL 原文为准**(:1156-1166 四条 FK 必须剥离,01 号 T2-01 裁剪项照办;02 号 :32 的表述作废),验收含全新 Testcontainers 库 V1→V3 全量迁移一次成功。 条件 1、2 在第一波内完成即可,不阻塞今日开工排期;条件 3~5 已有对应工单/裁剪项,本清单是把它们钉死为放行前提。 ## 6. 合规确认 - 三仓生产代码零写入;未 commit、未 push、未改 mkdocs.yml(其现有修改为前序波次所留,本人未触碰)。本文件为 patbond-doc 中未跟踪的报告文件,按授权原地更新,文件名未改。 - Gitea 取证为匿名只读 GET,未使用亦未记录任何凭据;报告不含敏感信息。 - 测试/构建日志留存于会话 scratchpad(mvn-test-recheck.log、flutter-test-recheck.log),未混入仓库。 --- **复核人**:TestingRealityChecker · 证据分档:【亲验】/【UNVERIFIED】/【勘误】 · 再评估时点:放行条件 1~3 完成后