docs(step097): close A2 Android Core validation
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
tei
2026-09-26 15:18:45 +09:00
parent f49ffa68a1
commit b1239ac3b1
6 changed files with 265 additions and 8 deletions

View File

@@ -13,10 +13,10 @@
| 01 N01/B01 | `paint_parameters.cpp:185` tile 集合相同跨 R-R target 复用 CPU mask | 同一未清 stencil target 可复用 | PaintParameters、Renderer、RenderTarget 已在新目标重置;同 tiles R-R/R-C-R 像素入口尚缺 | WAITING_RDC_BUILD_AND_RUNTIME / `e67e4961b` / GL、Metal |
| 02 N02/B02 | `mtl/render_pass.cpp:21` 仅 color clear;`offscreen_texture.cpp:67` 附件创建 | 无 depth/stencil 的 target 不可盲设附件 | Metal descriptor/combined 附件已修改;专用附件故障测试源码尚缺 | WAITING_RDC_BUILD_AND_RUNTIME / `e67e4961b` / Metal |
| 03 N03/B12 | `render_orchestrator.hpp:156` catch;`renderer_impl.cpp:824` 仍 mark success | 失败后 full fallback、下帧重试 | visitor 错误标志与 fallback 已接入;异常注入测试源码尚缺 | WAITING_RDC_BUILD_AND_RUNTIME / `e67e4961b` / GL、Metal |
| 04 N04/B06 | encoded playback clock 的生产调用方待核 | 显式 setTime 不双 tick | source/clock;PLAY/PAUSE/rate | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / Core、双平台 |
| 05 B13 | Particle GPU endpoint 更新门槛仅局部身份 | mix-only 不上传;跨窗只新端上传 | Particle field/renderer;仅 V/validity 变动 | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / GL、Metal |
| 06 B07 | 8-bit 中心量化不能精确表示零 | 不改公共 QBIN encoding | Particle texture/shader;零/微速/NaN | DEFERRED_DESIGN / 无 / GL、Metal |
| 07 B08 | Mercator 粒子位移 U 纬度度量 | 保持 U/V m/s 与既有时间倍率 | Particle shader;0°/45°/60° 四方向 | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / GL、Metal |
| 04 N04/B06 | `Map::Impl::onUpdate()` 在 Continuous update 驱动每个 RasterArraySource;Source 使用 monotonic tick,并用 `forecastTickInProgress` 阻止同步 SourceObserver 重入二次推进 | 显式 setTime/PLAY/PAUSE/rate 由一个 Core clock owner 推进;平台 timer 只唤醒 | `map_impl.cpp`、RasterArraySource、Android/iOS WeatherRuntime;`RasterArrayV4ProductionClockTicksOnceForBothBindingsAndResetsOnCommands`、`RasterArrayV4ClockSourceNotificationReentryDoesNotAdvanceTwice` | CODE_IMPLEMENTED_STATIC_CHECKED / A2 源码提交 `f49ffa68a` / OpenGL 与 Metal host A2 定向 3/3 PASS;FZG1 V4 Golden PLAY/PAUSE/速率/clear/reload PASS;无 iOS runtime(用户豁免) |
| 05 B13 | `sameFieldGpuContent()` 保持 revision/version 无关的 payload 相等;renderer GPU 槽位更新使用严格 `sameFieldGpuEndpoint()`;Source mix-only cache 使用 projection identity、binding、immutable frame 和 plane/validity storage pointer identity | mix-only 复用同一 T0/T1 snapshot;frame/revision、grid、validity、U/V、encoding 或 binding 改变则重物化并失效;invalid/clear fail-closed | `field_data_adapter.hpp`、projection materialization、RasterArraySource 与 renderer;Source cache 测试 + `ParticleGpuField.*` | CODE_IMPLEMENTED_STATIC_CHECKED / A2 源码提交 `f49ffa68a` / broad OpenGL 与 Metal host 各 121/121 PASS,A2 定向各 3/3 PASS;FZG1 stable mix 时 upload/reset 计数稳定;clear/reload 后合法增加 |
| 06 B07 | 新增内部 signed RGBA8 编码,byte 128 明确表示零;GL/Metal shader 以 high precision 还原 byte | 不改公开 QBIN/FieldProfile encoding;量化误差与 sub-half-quantum 微速边界明确测试 | `particle_gpu_math.hpp`、GL/Metal shader 源及生成头、`particle_gpu_math.test.cpp` | CODE_IMPLEMENTED_STATIC_CHECKED / A2 源码提交 `f49ffa68a` / broad OpenGL 与 Metal host 各 121/121 PASS,含 signed zero、取消、NaN/invalid 与微速边界;两次 shader generator 幂等;无 iOS runtime |
| 07 B08 | 统一 helper 与 GL/Metal 粒子位移路径都为 Mercator 东向 U、北向 V 应用相同 cos(latitude) metric,并夹紧极区分母 | 保持 U/V canonical m/s、V 北向为正、既有视觉时间倍率 | `particle_gpu_math.hpp`、renderer 与 GL/Metal shader 源及生成头;0°/45°/60° 四方向和极区测试 | CODE_IMPLEMENTED_STATIC_CHECKED / A2 源码提交 `f49ffa68a` / broad OpenGL 与 Metal host 各 121/121 PASS,含数学定向测试;Android FZG1 场景闭环通过;无 iOS runtime |
| 08 N05 | `render_segment_json.cpp` C 字符串解析 | invalid 清旧计划 | JSON/parser;NUL、重复键、恢复 | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / Core、桥接 |
| 09 N06 | `raster_array_source.cpp` 入库早于物化数值校验 | validity=0/noData 合法 | source/store;好旧帧→坏高 revision | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / Core |
| 10 N07 | Android attach map listener 重复注册 | detach/destroy 可重入 | Android bridge;100 次 attach/detach | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / Android |
@@ -26,7 +26,7 @@
| 14 F04/C04 | R 数 × viewport 独立附件内存 | 保留独立 R 与失败 fallback | cache;资源阶梯、失败注入 | DEFERRED_DESIGN / 无 / GL、Metal |
| 15 C04/B11 | encoded Store 无总 key/byte 预算 | 不静默驱逐绑定窗口 | Store;容量/旧读者 | DEFERRED_DESIGN / 无 / Core |
| 16 F07/C05 | `render_orchestrator.hpp:156` 每段前缀 distance | 全局 ordinal 与 Z 顺序不变 | orchestrator;重排/正反遍历 | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / Core |
| 17 C06/B05/B10 | 相同时间/mix-only 物化全网格 | owner-thread 世代发布 | runtime/source;重复时间/边界 | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / Core、桥接 |
| 17 C06/B05/B10 | A2 已处理相同 immutable projection 的 mix-only 重物化;其余 diagnostics pull、ordinal 与 UI owner 世代发布仍属后续范围 | A2 mix-only 不再复制/比较整张浮点快照;不据此宣称 C 阶段整体完成 | A2 部分:RasterArraySource cache 定向测试及 FZG1;C 部分仍按原任务另行实施 | A2 mix-only 子项已验证 / 当前工作树 `5bb1a0e` / OpenGL、Metal host 定向 3/3 PASS;C 其余项目未开始 |
| 18 C07 | drawable/tweaker tick 重建、端点复制 | 不保留 stale GPU 引用 | Particle renderer;tick/resize | DEFERRED_DESIGN / 无 / GL、Metal |
| 19 F09/O01 | `runtime_state.hpp:230` 新 topology;旧 cache 析构按 index 计数 | 总量与当前 topology 分离 | runtime/cache 按 revision 过滤;新增 `OldCacheReleaseCannotChargeReplacementAtSameIndex` GTest | CODE_IMPLEMENTED_STATIC_CHECKED / `e67e4961b` / 2026-09-26 Core GTest 1/1 PASS,诊断组 5/5 PASS;GPU 资源验收仍待测 |
| 20 F05/E01 | Host package `.10`、Native plugin `.13` | 精确同版,勿动发布产物 | Host package/lock;默认 install/typecheck | WAITING_RDC_BUILD_AND_RUNTIME / 待提交 / RN、Android |
@@ -38,7 +38,7 @@
## 操作次数模型(静态,非性能实测)
- A1:跨 target 清除 CPU mask 为每次目标切换一次 O(1) 状态清理;当前同 tiles 可能零次重绘但产生错误像素。Metal clear 每个 pass 最多各一次附件 load 设置。异常后额外一次 full fallback,避免错误缓存跨帧复用。
- A2:预期 PLAY 每 map/source 唯一时钟一次 tick;endpoint 内容识别随被提交场的数据量变化,mix-only 应为零次 GPU endpoint 上传。尚未实施。
- A2:PLAY 由唯一 Map/Source clock 每次 update 推进一次;V4 mix-only 的投影重物化计数为 0(50 次 Source tick 定向测试),decoded endpoint 变化时 color/particle projection 各物化一次。FZG1 日志在单次 stable mix-only epoch 内 upload/reset 计数不变;clear/reload 会合法增加计数。以上是源码测试和该次设备记录,不构成普遍 GPU 性能结论。
- B:预期 JSON 校验 O(输入长度),事务校验 O(有效 cell 数),attach 重复次数不再增加 listener 数。尚未实施。
- C:预期 full diagnostics 深复制从每 render 次降到每外部 pull 次;ordinal 前缀从每段 O(G) 降到 topology 更新 O(G);同时间物化从 O(cell) 降为 O(1)。尚未实施。
@@ -63,3 +63,10 @@
- 02:Metal host runner 已编译,GTest 两个测试均因没有 Metal device SKIP;用户决定不执行 iOS 运行测试,记 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`,不得称 Metal 实测 PASS。
- 03:`RenderOrchestratorError.*` 原生测试 2/2 PASS;真实 Android GPU fault injection 不在本次证据中。
- 19:前述 Core 1/1 PASS、诊断组 5/5 PASS、FZG1 辅助测试均保留。A1 在 Android/Core 验收及 iOS 用户豁免口径下进入 A2;详细事实见 `docs/报告/STEP-097_A1_Android专项验收报告_v1.md`。
## 2026-09-26 A2 RDC 最终验证
- 04–07 已在同一 dirty 源码工作树完成实现与 RDC 独立验证。旧 `sameFieldGpuContent()` 测试断言修复后原 58 项 58/58 PASS;更新后的 broad filter OpenGL 与 Metal host 各 121/121 PASS,三项 A2 Source 定向测试两平台各 3/3 PASS。
- 标准 Android Validation APK 为 OpenGL Debug/x86_64,61,753,803 bytes,SHA-256 `27bf4a6cc191bd86c4d1c10398478d81c2999edd61fe7242e40e5188516b0ca5`;安装到 FZG1-2 后设备 APK hash 相同。V4 Golden Wind test-only T0/T1 场景 17 张 PNG、24 个步骤、runner exit 0、ANR=0;PLAY 30 秒 UI 可响应,PAUSE 稳定,clear/reload 后再次 PLAY/PAUSE。
- 日志按资源窗口分别记录:clear/reload 前 mix-only epoch `fieldUploadCount=6/resetCount=2` 稳定;explicit clear/reload 后计数合法增加,达到 `fieldUploadCount=10/resetCount=4`,此后 replay 稳定。不可把 clear/reload 期间的上传与 reset 写成零。
- build source diff SHA-256 `18927a5f30a88f5c1c3a00e0017473dc33b04151c227e4baf52250dc4ad2e6a2` 与忽略目录中的 APK source snapshot 完全一致。未运行 iOS device runtime,按用户豁免记 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`;不得称 Metal host GTest 为 iOS PASS。A2 Android/Core 完成,B/C 未开始,整个 STEP-097 仍 PARTIAL。

View File

@@ -6,7 +6,7 @@
| --- | --- | --- |
| 阶段 0 基线与反证 | 完成(静态) | 读取三轮审查、STEP-094~096 交付及 C-001/RFC-001 本地副本。当前 HEAD 比任务书基线只新增任务文档;远端 particle/main 经 `git ls-remote` 核对一致。建立 24 项矩阵。Integration 远端同步状态待 RDC 复核。 |
| A1 Renderer 正确性 | Android/Core 检查点完成,iOS runtime 用户豁免 | `e67e4961b` 记录 01/02/03/19 的部分代码;19 有 GTest。01/02/03 缺少任务要求的专用可执行像素/附件/故障注入测试入口;且未进行 GL/Metal 编译。故 A1 不判完成,严格停止于此,不进入 A2。 |
| A2 Field/粒子正确性 | 计划 | 尚未开始。 |
| A2 Field/粒子正确性 | Android/Core 验证完成;iOS runtime 用户豁免 | 04–07 在当前 GPT-6 Luna High 可见会话实现,RDC 独立验证完成;详见本记录末尾补记及 `docs/报告/STEP-097_A2_阶段验证记录_v3.md`。A2 达到 Android/Core 阶段门槛,不能据此关闭整个 STEP-097。 |
| B 输入/生命周期 | 计划 | 尚未开始。 |
| C 安全性能 | 计划 | 尚未开始;必须先完成 A1 正确性。 |
| D 交付 | 部分完成 | 已写 24 项矩阵、集中验证清单、Step、本轮完成报告和开发记录。所有构建、测试、运行、发布均 NOT RUN;后续 RDC 独立审查。 |
@@ -47,3 +47,17 @@
- Codex GPT-6-Sol medium 在 A2 四项范围内写入生产/测试源码但触及当期使用额度,未完成最终审查/提交。RDC OpenGL 原生编译 exit 0、16/16 定向 GTest PASS;Shader generator 双次 exit 0/幂等;Metal host 源码编译 exit 0、同样 16/16 Core GTest PASS,**没有 iOS runtime**。
- A2 仍 PARTIAL;完整差异和构建/测试日志位于 `artifacts/maplibre-particle/step097-a2-rdc/`,中文事实报告:`docs/报告/STEP-097_A2_阶段验证记录_v1.md`。B/C 均未启动;用户未跟踪 STEP-098 与已发布 `.13` 未动。已安排 Codex 额度恢复后严格串行继续。
## 2026-09-26 A2 Core/Android 最终验证收口(B/C 未启动)
- Codex 配置:GPT-6 Luna High,可见会话。仓库 `/Users/tei/dev/MapLibreParticleLab`,`particle/main`,验证基线 HEAD `5bb1a0e6353c5dfe8db8a61bbeba9cef447280ef`;A2 源码保持 dirty、未提交。Integration `main` 已有报告基线 `318f8ccf911ac3136c3086a1d14e61f83e2d4bce`,C-001 未改。
- 04–07 完成:唯一 Core forecast clock 加 synchronous notification reentry guard;严格 GPU endpoint identity 与 mix-only immutable snapshot reuse;内部 RGBA8 signed zero/byte 解码;Mercator U/V 同纬度度量。旧 `sameFieldGpuContent` 的语义未改变,修正了与其 version-agnostic payload 等价定义相冲突的旧测试断言。新增 source 回归覆盖 50 次 mix ticks 不重物化、endpoint/revision 改变触发 materialize、clear fail-closed 与重入单 tick。
- RDC 独立结果:原 58/58 完整回归 PASS;当前 broad filter OpenGL 121/121 与 Metal host 121/121 PASS;三项 A2 定向测试两平台各 3/3 PASS;shader generator 连跑两次幂等。Metal host 仅 Mac Core runner,不是 iOS 设备验证。
- 标准 Android OpenGL Debug x86_64 APK `61,753,803` bytes,SHA-256 `27bf4a6cc191bd86c4d1c10398478d81c2999edd61fe7242e40e5188516b0ca5`;已安装到 FZG1-2(`192.168.200.139:5555`),设备 APK hash 相同。V4 Golden Wind test-only fixture 覆盖 load、seek 25/75、speed 2x/1x、PLAY 30 秒、responsive UI、PAUSE、stable pause、replay、clear、reload、再次 PLAY/PAUSE;runner exit 0、17 PNG、24 steps、ANR=0。15 秒截图可见粒子。
- Mix-only 计数按两个稳定资源 epoch 记录:clear/reload 前 upload/reset=`6/2` 稳定;clear/reload 后合法增至 `10/4`,reload 后 playback 稳定。不能说跨 clear/reload 零上传或零 reset。APK source diff SHA-256 与 `mix-reuse-build-source.diff` 一致:`18927a5f30a88f5c1c3a00e0017473dc33b04151c227e4baf52250dc4ad2e6a2`。
- 历史异常保留:12:43 首次 FZG1 ANR 根因为 source notification 同步重入 forecast tick,当前 `forecastTickInProgress` 与 `RasterArrayV4ClockSourceNotificationReentryDoesNotAdvanceTwice` 覆盖此项;后续有过无 ANR 但主线程高负载、PLAY/TIME 无响应的失败试跑,栈指向 forecast tick 内重复投影物化。最终 mix reuse APK 通过本次闭环。历史 debuggerd、失败试跑和最终日志均保留在 `artifacts/maplibre-particle/step097-a2-final-validation/`。
- A1 与 A2 的 Android/Core 阶段检查完成;iOS runtime 明确按用户决定记 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`,不写成 iOS PASS。STEP-097 整体仍 PARTIAL:B/C 未开始,Jest 未运行,STEP-098 未运行,`.13` 未发布/覆盖。Git commit/push 留给 RDC 独立 QA 后执行。
### 2026-09-26 A2 源码独立 scoped commit 核验
- A2 的 26 个生产源码、shader、TestApp-only V4 Golden fixture 和定向测试文件已固定为 `f49ffa68a17e0a505199bdbeccf07f8543f3a05f` 并推送,`origin/particle/main` 回读一致;没有 stage 用户未跟踪 STEP-098。完整代码/设备证据仍见 `docs/报告/STEP-097_A2_阶段验证记录_v3.md`,不因 Git 提交改变原 APK 的 `git_dirty=true` 来源事实。STEP-097 整体 PARTIAL,B/C 待用户指令。

View File

@@ -1,6 +1,6 @@
# STEP-097 V13 修复后集中验证清单 v1
状态:**PARTIAL:FZG1 A1 既有场景冒烟已执行,其余 NOT RUN**。下方原清单编写于 Codex A1 部分交付时;后续 RDC 实际执行事实与边界见文末。A1 专用 stencil 像素、Metal 附件、render 异常注入与 19 GTest 仍待完成;A2/B/C 未实施,不得以设备冒烟替代正式验收。
状态:**STEP-097 整体 PARTIAL;A1 与 A2 的 Android/Core 检查已完成,B/C 未开始。** 下方较早段落按当时事实保留;后续 RDC 结果以本文末尾带日期的更新为准。Metal host Core 测试不等于 iOS runtime,iOS runtime 按用户豁免记 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`。
## 通用 Core 与现有测试入口(RDC)
@@ -83,3 +83,35 @@ Android 同源 stencil:以本提交标准脚本构建 Validation APK,打开
- OpenGL `mbgl-test-runner` 编译 exit 0;定向 16/16 PASS;两次 Shader generator 均 exit 0 且输出一致。Metal host 可编译并执行同一跨 Core GTest 16/16 PASS,未运行 iOS 设备。
- 上述结果仅覆盖现有原生测试入口。Codex A2 代码尚未审查/提交,Android 设备/APK 仍 NOT RUN,不能推进 B/C。证据与完整边界见 `docs/报告/STEP-097_A2_阶段验证记录_v1.md`。
## 2026-09-26 A2 最终验证结果(RDC 独立执行)
### Core / Shader
- 原先因旧测试断言与既有语义不一致而失败的 58 项完整集合,在修复断言后 **58/58 PASS**。`sameFieldGpuContent()` 仍表达忽略 producer generation/dataVersion 的解码 payload 等价;`sameFieldGpuEndpoint()` 单独负责严格 GPU endpoint identity。
- 当前 broad filter 在 OpenGL 与 Metal host `mbgl-test-runner` 各 **121/121 PASS**。命令:
```sh
build-step088-opengl/mbgl-test-runner --gtest_filter='Particle*.*:Source.RasterArray*:Source.HostField*:Source.ParticleField*:Source.CanonicalField*'
build-step097-metal-host/mbgl-test-runner --gtest_filter='Particle*.*:Source.RasterArray*:Source.HostField*:Source.ParticleField*:Source.CanonicalField*'
```
- 三项 A2 Source 定向回归在 OpenGL 与 Metal host 各 **3/3 PASS**:mix-only 50 ticks 不重物化、真 endpoint 与 revision 变化触发物化、同步通知重入不双推进、clear fail-closed。
- `node shaders/generate_shader_code.mjs` 两次执行成功且输出幂等。Metal host 是 Mac 上 Core 测试,不是 iOS device runtime。
### Android / FZG1-2
- RDC 使用 `./tools/particle_android_validation/build_validation_apk.sh` 构建标准 OpenGL Debug x86_64 APK;61,753,803 bytes,SHA-256 `27bf4a6cc191bd86c4d1c10398478d81c2999edd61fe7242e40e5188516b0ca5`。FZG1-2 `192.168.200.139:5555` 安装成功,设备 APK SHA-256 相同。
- Test-App-only V4 Golden Wind T0/T1:load、seek 25/75、speed 2x/1x、PLAY 30 秒、PLAY 时 UI/TIME 可响应、PAUSE/stable pause、replay、CLEAR、reload、再次 PLAY/PAUSE;脚本 exit 0、17 PNG、24 steps、ANR=0。`05_play_15s.png` 可见粒子。30 秒场景闭环不是长期稳定性或性能测试。
- stable mix-only epoch 中 renderer 日志的 `fieldUploadCount=6/resetCount=2` 保持不变;explicit CLEAR/reload 后 upload 合法增至 10,reset 增至 4;reload 后 playback 稳定在该新计数。不能宣称跨 CLEAR/reload 零上传/零 reset。
- APK 工作树源 diff 与 `mix-reuse-build-source.diff` SHA-256 均为 `18927a5f30a88f5c1c3a00e0017473dc33b04151c227e4baf52250dc4ad2e6a2`,源码快照一致。原始 build/device/test 日志、steps 与截图位于 `artifacts/maplibre-particle/step097-a2-final-validation/`。
### 历史失败与范围
- 12:43 首次 ANR 为 synchronous Source notification 重入 forecast tick;`forecastTickInProgress` guard 与重入 GTest 已修复并覆盖。
- 后续无 ANR 但主线程仍高负载、PLAY/TIME 无响应的试跑由 debuggerd 定位到每 tick 重物化大场和深比较;mix-only immutable endpoint reuse 后通过本次 FZG1 闭环。旧失败日志和 debuggerd 保留,不从报告中删除。
- 本次不测 iOS runtime;标 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`。没有完成 GPU 性能基准、FPS/pXX 或长期运行测试。STEP-097 整体仍 PARTIAL,B/C 未开始;不包含 Jest、STEP-098、发布 `.13`。
### 2026-09-26 A2 源码独立 scoped commit 核验
- A2 的 26 个生产源码、shader、TestApp-only V4 Golden fixture 和定向测试文件已固定为 `f49ffa68a17e0a505199bdbeccf07f8543f3a05f` 并推送,`origin/particle/main` 回读一致;没有 stage 用户未跟踪 STEP-098。完整代码/设备证据仍见 `docs/报告/STEP-097_A2_阶段验证记录_v3.md`,不因 Git 提交改变原 APK 的 `git_dirty=true` 来源事实。STEP-097 整体 PARTIAL,B/C 待用户指令。

View File

@@ -0,0 +1,96 @@
# STEP-097 A2 阶段验证记录 v3
## 1. 结论
**A2 Android/Core 验证完成;STEP-097 整体仍 PARTIAL。** A2 的 04–07 在 Core、OpenGL/Metal host 回归和 FZG1-2 设备闭环达到本阶段检查点。没有开始 B/C,没有执行 Jest、STEP-098 或 `.13` 发布。iOS runtime 依用户决定豁免,记为 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`,不是 iOS PASS。
Codex 会话配置:**GPT-6 Luna High**,用户可见会话。RDC 独立执行了 CMake/GTest、shader generator、标准 Android APK 构建、FZG1-2 安装和设备场景。Codex 本轮未执行这些命令。
## 2. Git 与版本基线
- 仓库:Mac `Mac-mini-tei.lan`,`/Users/tei/dev/MapLibreParticleLab`;分支 `particle/main`。
- 验证源码基线 HEAD:`5bb1a0e6353c5dfe8db8a61bbeba9cef447280ef`;A2 源码工作树 dirty,尚未提交。结束 HEAD 未变化。
- 本次记录前的 A2 source diff SHA-256:`18927a5f30a88f5c1c3a00e0017473dc33b04151c227e4baf52250dc4ad2e6a2`;与 `artifacts/maplibre-particle/step097-a2-final-validation/mix-reuse-build-source.diff` SHA-256 完全一致。标准 APK 的 build-info 也记录相同 commit/branch 和 `git_dirty=true`,证明设备验证所用 source snapshot 与本轮代码一致。
- Integration `main`:`318f8ccf911ac3136c3086a1d14e61f83e2d4bce`;C-001 未修改。
- 冻结的 `.13` 发布坐标、tag、manifest 与产物未修改;本轮不发布。
- 用户 untracked `docs/40_任务/STEP-098_QBIN_V4单帧首显与八帧滚动缓存_Codex任务_v1.md` 保持原样、未 stage。
## 3. A2 实施内容
| 项 | 实施与不变量 |
| --- | --- |
| 04 N04/B06 Forecast PLAY | Map Continuous update 驱动 Source-owned monotonic forecast clock;Android/iOS timer 只负责唤醒。同步 SourceObserver reentry 由 `forecastTickInProgress` 防止重复推进。显式 setTime、PLAY/PAUSE、rate、clear 保持 Core clock 所有权。 |
| 05 B13 GPU endpoint / mix-only reuse | `sameFieldGpuContent()` 继续只表示 version-agnostic decoded payload 等价;新的 `sameFieldGpuEndpoint()` 严格比较 revision/time、U/V、validity、grid、encoding 等 renderer endpoint 身份。Source 对相同 content identity、binding、immutable decoded frame 与 plane/validity storage pointer 复用已有 materialized T0/T1,只更新 `sampleState`。frame/revision 或任一输入 storage 改变则重新物化;invalid/clear fail-closed。移除每 tick 深比较完整 snapshot vectors。 |
| 06 B07 RGBA8 signed zero | 增加内部 `particle_gpu_math.hpp` signed RGBA8 编码,byte 128 明确表示 0;shader 以 high precision 还原 byte。未改公开 QBIN/FieldProfile encoding。数学测试覆盖正负取消、零、NaN/invalid 与量化下限。 |
| 07 B08 Mercator U/V | helper 与 GL/Metal shader 的东向 U、北向 V 都使用相同纬度度量,极区分母夹紧;保持 canonical m/s 和现有视觉时间倍率。测试覆盖 0°/45°/60° 四方向及极区有限值。 |
三项 A2 Source 测试还覆盖 50 次 mix-only clock tick 不重物化、真实 endpoint 和相同 valid-time revision 替换触发重物化、clear 后 projection 清空,以及 source notification 嵌套 tick 不双推进。Host-facing 新 API、C-001、QBIN 格式未改变。
## 4. 修改文件
### 源码、shader 与 A2 测试
- `include/mbgl/particle/field/field_data_adapter.hpp`
- `include/mbgl/particle/field/particle_gpu_math.hpp`(新增)
- `include/mbgl/shaders/gl/particle_gpu_validation.hpp`
- `include/mbgl/shaders/mtl/particle_gpu_validation.hpp`
- `include/mbgl/style/sources/raster_array_source.hpp`
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/WeatherRuntime.java`
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step097V4GoldenFixture.kt`(新增)
- `platform/android/MapLibreAndroidTestApp/src/main/assets/integration/step097-v4/wind/T0.qbin`、`T1.qbin`、`contract.json`(新增 test-only fixture)
- `platform/ios/src/MLNParticleFieldRuntime.mm`
- `shaders/particle_gpu_validation.fragment.glsl`、`shaders/particle_gpu_validation.vertex.glsl`
- `src/mbgl/map/map_impl.cpp`
- `src/mbgl/particle/field/field_data_adapter.cpp`
- `src/mbgl/particle/field/field_projection_materialization.cpp`
- `src/mbgl/particle/field/field_runtime.cpp`
- `src/mbgl/renderer/layers/render_particle_validation_layer.cpp`
- `src/mbgl/style/sources/raster_array_source.cpp`、`src/mbgl/style/sources/raster_array_source_impl.hpp`
- `test/CMakeLists.txt`
- `test/particle/field_runtime.test.cpp`
- `test/particle/particle_gpu_math.test.cpp`(新增)
- `test/source/raster_array_v4_host_api.test.cpp`
- `test/style/source.test.cpp`(仅修正旧断言对 `sameFieldGpuContent()` 的预期;严格 endpoint identity 由新断言覆盖)
本报告之后的文档变更为 `docs/30_设计/STEP-097_V13三轮问题去重与修复矩阵_v1.md`、本报告、`docs/报告/STEP-097_V13三轮审查问题合并修复_Codex完成报告_v2.md`、`docs/50_Step记录/STEP-097_V13三轮审查问题合并修复_v1.md`、`docs/60_测试/STEP-097_V13修复后集中验证清单_v1.md` 及根目录 `粒子开发记录.md`。无其他步骤范围代码。
## 5. RDC 构建与测试
| 验证 | RDC 结果 |
| --- | --- |
| 原有完整 58 项回归(修正旧断言后) | OpenGL **58/58 PASS**。先前 57/58 的失败根因是旧断言把 `sameFieldGpuContent()` 当成 revision-sensitive;函数原有契约明确忽略 generation/dataVersion。测试现在分别验证 payload 等价与 strict endpoint identity,没有放宽 endpoint 比较。 |
| 当前 broad Core filter `Particle*.*:Source.RasterArray*:Source.HostField*:Source.ParticleField*:Source.CanonicalField*` | OpenGL **121/121 PASS**;Metal host **121/121 PASS**。 |
| A2 定向 Source 三项 | OpenGL **3/3 PASS**;Metal host **3/3 PASS**,包括 mix-only 50 ticks、endpoint/revision invalidation 与同步通知重入。 |
| shader generator | `node shaders/generate_shader_code.mjs` 连续两次成功,输出幂等。 |
构建/测试日志:`artifacts/maplibre-particle/step097-a2-final-validation/mix-reuse-broad-opengl.log`、`mix-reuse-broad-metal-host.log`、`mix-reuse-focused-opengl.log`、`mix-reuse-focused-metal-host.log`、`build-mix-reuse-opengl.log`、`build-mix-reuse-metal-host.log`。Metal host 测试是 Mac Core runner,不是 iOS runtime 或设备 Metal 验证。
## 6. Android APK 与 FZG1-2
- 标准命令由 RDC 执行:`./tools/particle_android_validation/build_validation_apk.sh`。
- 产物:`artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk`;OpenGL Debug、x86_64、61,753,803 bytes;SHA-256 `27bf4a6cc191bd86c4d1c10398478d81c2999edd61fe7242e40e5188516b0ca5`。步骤归档副本:`artifacts/maplibre-particle/step097-a2-final-validation/MapLibreAndroidTestApp-A2-mix-reuse-x86_64.apk`。
- RDC 安装至 Panasonic FZG1-2(ADB `192.168.200.139:5555`)成功;设备内 APK SHA-256 与构建产物相同。
- Test-App-only Golden Wind T0/T1 场景脚本 exit 0,17 PNG、24 steps、ANR=0:load、seek 25/75、speed 2x/1x、PLAY 30 秒与 PLAY 时 UI/TIME 响应、PAUSE/stable pause、replay、CLEAR、reload、再次 PLAY/PAUSE。截图 `after-v4-mix-reuse/05_play_15s.png` 可见粒子。
- 上传/reset 计数按资源 epoch 记录:clear/reload 前 mix-only playback 稳定于 `fieldUploadCount=6/resetCount=2`;CLEAR/reload 后计数合法增加到 `fieldUploadCount=10/resetCount=4`,reload 后 playback 稳定。没有宣称跨 CLEAR/reload 零上传/零 reset。
- APK 输入源码 diff 与保存快照 `mix-reuse-build-source.diff` 的 SHA-256 都为 `18927a5f30a88f5c1c3a00e0017473dc33b04151c227e4baf52250dc4ad2e6a2`。
## 7. 历史失败、性能与平台边界
- 2026-09-26 12:43 首次 FZG1 ANR 的 main stack 是 Forecast clock tick 的同步 SourceObserver reentry;`forecastTickInProgress` guard 与回归测试针对该缺陷。后续有一轮没有 ANR 但 UI/TIME 仍不可用、主线程高负载;debuggerd 定位到每 tick 对大 QBIN projection 重复物化 validity/vector 并深比较 snapshot。mix-only immutable snapshot reuse 后,最终 FZG1 闭环通过。
- 历史 debuggerd、首次 ANR、第二次无响应试跑及最终验证证据均保存在 `artifacts/maplibre-particle/step097-a2-final-validation/`;报告保留失败经过,不把中间失败覆盖成 PASS。
- PLAY 30 秒只是交互闭环,不是 long-run 稳定性、FPS、frame time、内存或 GPU 性能基准;本轮没有这类数字。
- 用户豁免 iOS runtime:`USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`。Android 与 Metal host Core 结果不能替代 iOS device PASS。
- Integration C-001 未改,Host 公开 API/QBIN schema 未改;没有进入 B/C、没有运行 STEP-098/Jest、没有更改 `.13` 发布物。
## 8. 阶段与 Git 收尾
- A2 状态:Android/Core 代码、原生回归和 FZG1 验证完成。
- STEP-097 整体:**PARTIAL**;B/C 未开始。其余 24 项逐项状态见更新后的去重矩阵。
- 本报告无 commit/push。RDC 后续做独立 QA 与 scoped Git 操作;用户未跟踪 STEP-098 不得纳入。
## 9. RDC Git 源码提交核验(报告编写后更新)
- A2 源码、标准 TestApp 内部 fixture 与定向测试已以 **`f49ffa68a17e0a505199bdbeccf07f8543f3a05f`** 独立 scoped commit 提交并推送 `origin/particle/main`;26 个代码/fixture/test 路径,未包含任何文档、STEP-098、Integration、NavSea 或发布资产。远端 HEAD 回读相同。
- 该提交只是把已经通过 RDC 验证的源码固定进 Git;构建时仍如实为 `5bb1a0e` + dirty source diff。源码部分保存快照的 SHA-256 对应提交内容,不把后续文档更新误算进构建输入。
- 文档与 Step/矩阵/测试清单将作为独立 scoped commit 收尾。

View File

@@ -0,0 +1,96 @@
# STEP-097 V13 三轮审查问题合并修复 — Codex 完成报告 v2
## 1. 执行结论
**PARTIAL:A1 与 A2 的 Android/Core 检查完成;B/C 未开始。** A2 04–07 已由 Codex GPT-6 Luna High 在用户可见会话实现,由 RDC 独立构建、测试和执行 FZG1-2 运行闭环。iOS runtime 依据用户决定豁免,状态为 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`,不是 iOS PASS。没有运行 Jest、STEP-098 或发布 `.13`。
## 2. Git、环境与发布基线
- 机器:`Mac-mini-tei.lan`;仓库:`/Users/tei/dev/MapLibreParticleLab`;branch:`particle/main`。
- 源码验证基线 HEAD:`5bb1a0e6353c5dfe8db8a61bbeba9cef447280ef`;验证时 worktree dirty,未提交。报告编写只增加/更新本报告所列 A2 文档。
- A2 source diff SHA-256 `18927a5f30a88f5c1c3a00e0017473dc33b04151c227e4baf52250dc4ad2e6a2`,与 APK build source snapshot 完全相同。
- Integration `main`=`318f8ccf911ac3136c3086a1d14e61f83e2d4bce`;C-001 未修改。
- 冻结 `.13` 坐标/tag/manifest/发布产物未改。没有提交或 push。
- 用户 untracked STEP-098 任务文件保持未跟踪、未修改、未 stage。
## 3. 修改文件
源码、shader、测试及 Test-App-only V4 Golden fixture 的完整路径列于 [A2 阶段验证记录 v3](STEP-097_A2_阶段验证记录_v3.md) 第 4 节。核心范围包括 `RasterArraySource` 与 `Map::Impl` Forecast clock、严格 GPU endpoint identity 和 mix-only snapshot reuse、signed RGBA8 helper、GL/Metal shader 与 Mercator 数学、Android/iOS timer wake bridge、A2 Core 回归和 test-only Wind T0/T1 fixture。
本轮交付文档:
- `docs/报告/STEP-097_A2_阶段验证记录_v3.md`
- 本文件 `docs/报告/STEP-097_V13三轮审查问题合并修复_Codex完成报告_v2.md`
- 更新 `docs/30_设计/STEP-097_V13三轮问题去重与修复矩阵_v1.md`、`docs/50_Step记录/STEP-097_V13三轮审查问题合并修复_v1.md`、`docs/60_测试/STEP-097_V13修复后集中验证清单_v1.md`
- 仅追加根目录 `粒子开发记录.md`
未修改 Integration、NavSea、项目总则、C-001、QBIN schema、`.13` 发布物、用户 STEP-098 或 Host public API。
## 4. 24 项状态
| # | 状态与实际结论 |
| --- | --- |
| 01 N01/B01 | A1 Android/Core 检查完成;同源 stencil fixture FZG1 检查已在 A1 报告记录。A1 iOS runtime 按用户决定豁免。 |
| 02 N02/B02 | A1 Android/Core 阶段收口;Metal host 不是设备验证。无 iOS runtime,按用户豁免记录。 |
| 03 N03/B12 | A1 Android/Core 阶段收口;异常恢复 GTest 已在 A1 报告记录。 |
| 04 N04/B06 | A2 完成;唯一 Source forecast clock、wake-only timer 与同步回调重入保护;OpenGL/Metal host 定向测试和 FZG1 PLAY/PAUSE 实测通过。 |
| 05 B13 | A2 完成;`sameFieldGpuContent` 仍为 payload 等价,strict endpoint identity 独立比较;mix-only snapshot reuse 与 revision invalidation 通过 Core/设备验证。 |
| 06 B07 | A2 完成;内部 signed zero encoding/shader 路径和数学边界测试通过 OpenGL 与 Metal host broad 回归。 |
| 07 B08 | A2 完成;U/V 纬度 metric 和极区夹紧,数学回归与 Android 场景通过;不等于 iOS runtime。 |
| 08 N05 | `WAITING_RDC_BUILD_AND_RUNTIME`;B 未开始。 |
| 09 N06 | `WAITING_RDC_BUILD_AND_RUNTIME`;B 未开始。 |
| 10 N07 | `WAITING_RDC_BUILD_AND_RUNTIME`;B 未开始。 |
| 11 F01/C01 | `WAITING_RDC_BUILD_AND_RUNTIME`;C 未开始。 |
| 12 F02/C02/B03 | `DEFERRED_DESIGN`;同步等待依赖未在本阶段处理。 |
| 13 F03/C03/B04 | `WAITING_RDC_BUILD_AND_RUNTIME`;C 未开始。 |
| 14 F04/C04 | `DEFERRED_DESIGN`;无资源预算改动。 |
| 15 C04/B11 | `DEFERRED_DESIGN`;无 store 总容量语义改动。 |
| 16 F07/C05 | `WAITING_RDC_BUILD_AND_RUNTIME`;C 未开始。 |
| 17 C06/B05/B10 | mix-only immutable materialization 子项随 A2 完成;其他 diagnostics、ordinal、UI owner 工作仍待后续,整体不得解读为 C 完成。 |
| 18 C07 | `DEFERRED_DESIGN`;drawable/tweaker 生命周期未改。 |
| 19 F09/O01 | A1 已有 GTest 与 FZG1 证据保留;不把资源诊断夸大为 GPU 无泄漏证明。 |
| 20 F05/E01 | `WAITING_RDC_BUILD_AND_RUNTIME`;B/Test Host package lock 未改、未验证。 |
| 21 F06 | `DEFERRED_DESIGN`;保留 multi-C 安全 fallback。 |
| 22 F08 | `DEFERRED_DESIGN`;保留保守失效策略。 |
| 23 F10/E02 | `DEFERRED_DESIGN`;需要跨项目协调,Integration status 未改。 |
| 24 STEP-095 §7/B09 | `DEFERRED_DESIGN`;共享地理 Ocean Mask 需要后续跨项目契约。 |
矩阵保留全部 24 项、旧编号及平台边界。
## 5. 实现摘要与偏差
1. Forecast clock 每次由 Map Continuous update 调用一次;同步 SourceObserver 重入不再触发第二次 tick。Android/iOS timers 负责 triggerRepaint 唤醒,不独立推进时间。
2. Strict endpoint identity 涵盖 frame/revision、grid、U/V、validity 与 encoding。mix-only 时复用当前 immutable materialized snapshots;新 frame/revision 或 storage identity 改变时重新 materialize;clear/invalid 仍 fail-closed。没有使用 generation/dataVersion 偷换 `sameFieldGpuContent()` 的已有语义。
3. RGBA8 byte 128 表示 signed zero,GL/Metal shader 使用高精度 byte reconstruction。东/北向 Mercator 位移应用一致纬度 metric。
4. 新增 A2 定向 source 测试、GPU math 测试及 test-only Golden Wind 两帧 fixture;没有新建 Host API、QBIN 格式或 C-001 语义。
5. 首次 FZG1 ANR 是同步 clock notification 重入;guard 修复后仍有一轮因每 tick 重物化大场、深比较而 UI 不响应。最终 mix reuse 版本完成设备闭环。原始失败日志与 debuggerd 均保留。
## 6. RDC 构建、测试、设备及产物
- 原 58 项回归:旧断言修复后 **58/58 PASS**。失败断言与旧函数定义不符,修复测试语义;没有放宽新 strict endpoint 条件。
- OpenGL broad Core filter:**121/121 PASS**。
- Metal host 相同 broad Core filter:**121/121 PASS**。
- 三项 A2 Source 定向测试:OpenGL 和 Metal host 各 **3/3 PASS**。
- Shader generator 连续两次成功、输出幂等。
- 标准 APK `./tools/particle_android_validation/build_validation_apk.sh`:OpenGL Debug、x86_64、61,753,803 bytes;SHA-256 `27bf4a6cc191bd86c4d1c10398478d81c2999edd61fe7242e40e5188516b0ca5`。FZG1-2 安装成功、设备 hash 相同。
- Golden 闭环:17 PNG、24 steps、exit 0、ANR=0;PLAY 30 秒并确认 TIME/UI 操作响应,随后 PAUSE/stable pause/replay/CLEAR/reload/replay/PAUSE。15 秒截图有可见粒子。
- 日志资源 epoch:首次 stable mix-only `upload=6/reset=2` 保持不变;CLEAR/reload 后合法到 `upload=10/reset=4`,随后 playback 稳定。没有宣称跨 CLEAR/reload 零上传或 reset。
- Android 产物、测试日志、设备日志、截图、步骤清单、debuggerd 与历史失败证据在 `artifacts/maplibre-particle/step097-a2-final-validation/`。
- 本轮无 FPS、p50/p95/p99、frame time、内存或 long-run 性能结论。iOS runtime 未运行,用户豁免。
## 7. 未完成与限制
- STEP-097 总体仍 `PARTIAL`:B/C 未进入。04–07 完成不代表 08–24 全完成;第 17 项只有 mix-only 子项完成。
- iOS runtime:`USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`。Metal host GTest 只证明共享 Core host 路径,不能替代 iOS Metal device PASS。
- FZG1 Golden 是 Test-App-only fixture,不是 NavSea、正式产品数据链或全量天气验收。
- 30 秒 PLAY 交互不构成长时稳定性或正式 GPU 性能验收。
- 无提交/推送;用户 STEP-098 未触碰;`.13` 未发布。
## 8. 后续交接
RDC 对当前 dirty A2 代码与本报告做独立 QA,按用户后续授权执行 scoped Git 操作。若后续继续 STEP-097,只能由用户明确允许进入下一个阶段后启动 B;本报告不自动开启 B/C。
## 9. RDC 源码 Git 后续事实(本报告编写后)
- 源码 scoped commit **`f49ffa68a17e0a505199bdbeccf07f8543f3a05f`** 已推送 `origin/particle/main`,远端核对一致。此事实覆盖前文“未提交/未推送”的报告编写时状态,保留原始验证 HEAD 以便追溯 dirty APK 的实际构建来源。
- 文档另行提交;不将源代码 Git commit 当作额外编译/设备测试。用户 STEP-098 仍不提交,B/C 不启动。

View File

@@ -978,3 +978,15 @@ Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2`
- A2 修改处于未提交状态,Codex GPT-6-Sol medium 用量限制触发暂停;RDC OpenGL 原生构建 PASS、16/16 GTest PASS、Shader generator 两次幂等,Metal host 编译 PASS、同样 16/16 Core GTest PASS。非 iOS runtime。
- 记录 `docs/报告/STEP-097_A2_阶段验证记录_v1.md`;保留完整工作树、未跟踪 STEP-098 和产物,不进入 B/C。已设定 13:55 JST 恢复检查。
### 2026-09-26 STEP-097 A2 最终 Android/Core 验证
- 当前可见 Codex 会话为 GPT-6 Luna High。RDC 独立复核原 58/58 回归、当前 OpenGL broad 121/121、Metal host broad 121/121,A2 focused tests 两平台各 3/3;shader generator 两次幂等。修复旧断言以区分忽略 dataVersion 的 decoded-content equality 与严格 endpoint identity。
- RDC 标准 Android OpenglDebug x86_64 APK 构建成功,61,753,803 bytes,SHA-256 `27bf4a6cc191bd86c4d1c10398478d81c2999edd61fe7242e40e5188516b0ca5`;FZG1-2 安装包 hash 一致。TEST-ONLY V4 Golden Wind T0/T1 完成加载、seek、倍速、PLAY 30 秒、PAUSE、重播、CLEAR/重载与再次播放;runner exit 0,17 张 PNG、24 steps、ANR=0,15 秒截图可见粒子。
- mix-only 稳定区间 `fieldUploadCount=6`、`resetCount=2`;显式 CLEAR/重载后计数合法增加到 upload 10/reset 4,故不把 clear/reload 描述为零上传。历史 12:43 同步重入 ANR 与后续 main-thread 高负载/TIME 无响应失败均保留在证据中;修复包含防重入与 mix-only 缓存物化优化。
- 证据与限制见 `docs/报告/STEP-097_A2_阶段验证记录_v3.md`、集中验证清单和更新后的 24 项矩阵。Metal 结果是 host/Core,不是 iOS 设备测试;iOS runtime 按用户决定标为 `USER_ACCEPTED_WITHOUT_IOS_RUNTIME_TEST`。没有长时间 GPU 性能结论;STEP-097 整体 PARTIAL,B/C 未开始。
- 本次仅完成报告、Step、矩阵、清单与开发记录;没有执行构建、测试、Gradle、ADB、codegen、提交或推送。用户未跟踪 STEP-098 任务文档保持原样,交由 RDC 独立审查并按范围处理 Git。
### 2026-09-26 A2 源码独立 scoped commit 核验
- A2 的 26 个生产源码、shader、TestApp-only V4 Golden fixture 和定向测试文件已固定为 `f49ffa68a17e0a505199bdbeccf07f8543f3a05f` 并推送,`origin/particle/main` 回读一致;没有 stage 用户未跟踪 STEP-098。完整代码/设备证据仍见 `docs/报告/STEP-097_A2_阶段验证记录_v3.md`,不因 Git 提交改变原 APK 的 `git_dirty=true` 来源事实。STEP-097 整体 PARTIAL,B/C 待用户指令。