docs: record STEP-060 RN bridge test host

This commit is contained in:
OpenAI Codex
2026-09-07 16:10:34 +08:00
parent 4c906b21fb
commit 5c6fa2c668
4 changed files with 100 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# STEP-060 RN Test Host 与 WeatherRuntime 薄桥接
状态:完成(`IMPLEMENTED / WAITING_ANDROID_VALIDATION`)
## 目标与基线
基于 `particle/main` 的 `b535d98263af58ac86845f15bb7c51bd85b59519`,在仓库内建立独立 RN Test Host,证明 `reactTag → MLRNMapView → MapLibreMap → per-map WeatherRuntime` 的低频控制链路;不进入 STEP-061 Binary Field 或 NavSea 正式接入。
## 完成项
- [x] 冻结 RN 0.85.2 / React 19.2.5 / Expo 56.0.4 / MLRN 11.3.6 / TypeScript 5.9.3 基线。
- [x] 以 MLRN 实际 11.3.6 源码核对 `nativeVersion/nativeVariant` 与 reactTag resolver;custom OpenGL SDK 只从 Maven Local 解析。
- [x] Test Host style 明确含 host-field RasterArraySource、WeatherColor 与 RasterParticle layers。
- [x] Phase A:getState、enabled、两层 visible、targetFps。
- [x] Phase B:forecast timestamp、playback/speed、ramp、独立 particle/trail color、粒子视觉与 WeatherColor opacity。
- [x] map-owned WeatherRuntime、style replacement、View detach 与 React unmount dispose 路径。
## 边界
Bridge 每次由 Fabric UIManager 解析 reactTag,不复制 MLRN 私有 `mViews`,不建立 global/current-map 或 timeline/playback registry。`MapLibreMap.replaceWeatherRuntime` / `disposeWeatherRuntime` 是为消除桥接 registry 所作的最小上游 Host ownership seam;它不改 WeatherRuntime 状态机或 C++ renderer。不存在 field payload、provider/network、RN JS state machine、iOS bridge 或 NavSea 业务代码。
## 验证与剩余
已执行 throttle 下 `npx tsc --noEmit`(PASS)、package-lock/config 一致性检查(PASS)、bridge boundary 搜索(PASS)与 `git diff --check`(PASS)。Android Gradle、artifact publish、APK、ADB、设备和 Jest 明确留给手工验收;本 Step 不宣称 Android 已验证。

View File

@@ -0,0 +1,12 @@
# STEP-060 RN Test Host Android 人工编译与验收
本说明只列出人工步骤;Codex 未执行 Android Gradle、发布、安装或 ADB。
1. 在当前 `particle/main` 编译并发布 custom OpenGL SDK:`cd platform/android && ./gradlew :MapLibreAndroid:publishToMavenLocal`。确认 `~/.m2/repository/org/maplibre/gl/android-sdk-opengl/13.4.1/` 是当前提交生成;建议先移走任何旧的同版本 artifact。
2. `cd integration/react-native/MapLibreParticleRNTestHost && yarn install && npx expo prebuild --platform android --clean`。检查生成 root Gradle 有 `MapLibreParticleRNTestHost custom OpenGL SDK` 标记、`nativeVersion=13.4.1`、`nativeVariant=opengl`,并且 Maven Central 对 `org.maplibre.gl` 被排除。
3. 用 JDK 17、AGP 8.5.0、Gradle 8.14.3、Kotlin 2.1.20、NDK 27.1.12297006、compile/targetSdk 36 编译/安装 Test Host;确认 Hermes 与 New Architecture 开启。
4. 启动后确认单一地图正常加载。style ready 后应显示 reactTag 和 `WAITING_FOR_FIELDS`,不提交 field 时粒子/色场为空是预期。
5. 对同一 reactTag 依次验证 Phase A:getState、enable、WeatherColor visible、particle visible、FPS 30 均得到结构化 Native result。
6. 验证 Phase B:PLAY/PAUSE、HALF/NORMAL/DOUBLE、epoch-ms seek、stops、独立 particle/trail RGBA、count/line/length/opacity/fade/WeatherColor opacity。不得出现 JS `PLAYING/PAUSED` 第二状态机。
7. 重载 style:旧 Runtime 必须 disposed;style ready attach 的新 Runtime 正常工作。remount Map 后,用旧 reactTag 调用必须返回 `MAP_VIEW_NOT_FOUND`,不得命中新 Map。
8. 卸载 Host:确认 view detach dispose;无持续 Handler wake、无全局 current map。STEP-061 前不要尝试 number[]、JSON/base64 大 field。

View File

@@ -0,0 +1,58 @@
# STEP-060 RN Test Host 与 WeatherRuntime 薄桥接 — Codex 完成报告
状态:`IMPLEMENTED / WAITING_ANDROID_VALIDATION`
Starting HEAD:`b535d98263af58ac86845f15bb7c51bd85b59519`。
## 实际完成内容
1. RN Test Host 最终目录为 `integration/react-native/MapLibreParticleRNTestHost/`。冻结 RN `0.85.2`、React `19.2.5`、Expo `56.0.4`、TypeScript `5.9.3`、MLRN `11.3.6`;New Architecture 已在 Expo config 开启。
2. MLRN `11.3.6` 实际 Android `build.gradle` 按 root extra `org.maplibre.reactnative.nativeVersion/nativeVariant` 解析 `android-sdk-<variant>`。Test Host config plugin 固定 `13.4.1`/`opengl`。
3. plugin 在 Android project 配置完成后清除各 project repositories,设置 Maven Local、Google 与 Maven Central(后者排除 `org.maplibre.gl`)。因此 custom `android-sdk-opengl:13.4.1` 缺失即依赖失败,不会从普通官方 SDK fallback;artifact 的字节来源仍须用户手工发布/检查。
4. MLRN 的共享 `ReactTagResolver` 实例由 `MLRNPackage` 私有持有,不能安全注入外部模块。Bridge 没有复制其 `mViews`:使用 React Native/Fabric 的公开 `UIManagerHelper.getUIManager(...).resolveView(reactTag)`,验证结果是具体 `MLRNMapView`。
5. 从该具体 View 读取 MLRN 公开只读 `mapLibreMap`;不存在 global/current map。
6. `MapLibreMap` 新增唯一 map-owned `WeatherRuntime` attachment seam。Bridge 不维护 Map→Runtime 表:style replacement 通过 `MapLibreMap.setStyle()` dispose,View detach listener dispose,React `useEffect` unmount 也调用 detach;下一次 style ready attach 必定创建新 facade。
7. style ready 前分别 fail-closed 为 `MAP_NOT_READY` 或 `STYLE_NOT_READY`;source/layers 缺失为 `WEATHER_OBJECTS_NOT_READY`。不存在/已 drop tag 为 `MAP_VIEW_NOT_FOUND`,已 dispose runtime 为 `RUNTIME_DISPOSED`;参数问题为 `INVALID_ARGUMENT`,facade throw 为 `NATIVE_REJECTED`。
8. Style JSON 由 Test Host 预先创建 background、host-field `RasterArraySource`、WeatherColorLayer、RasterParticleLayer。Bridge 不创建 Weather 私有 Style registry;style reload 后由 MLRN style event 的 attach 重建。
9. Phase A 五项均完成:`getState`、`setWeatherEnabled`、`setWeatherColorVisible`、`setParticleVisible`、`setTargetFps`。
10. Phase B 完成:epoch-ms `setForecastTime`、playback state/speed、ColorStop list、独立 particle/trail RGBA、particle count/line width/length/opacity、trail opacity/fade、WeatherColor opacity 与 native snapshot。未完成:Binary Field、JSI/zero-copy、provider/network、NavSea 正式接入、iOS bridge。
11. 为 snapshot 增加唯一最小 getter `WeatherRuntime.getPlaybackState()`;`state`、target FPS、disposed 均为既有 native 权威值,Bridge 不缓存播放/runtime state。没有 Adapter、Normalizer、第二 registry 或 renderer 改动。
## 修改/新增文件
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java`
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/WeatherRuntime.java`
- `integration/react-native/MapLibreParticleRNTestHost/`(Expo Test Host、Android TurboModule、style、README、lock/config plugin)
- `docs/50_Step记录/STEP-060_RNTestHost与WeatherRuntime薄桥接_v1.md`
- `docs/60_测试/STEP-060_RNTestHost_Android人工编译与验收_v1.md`
- `粒子开发记录.md` 与本报告。
## API 与生命周期
```text
JS typed TurboModule + reactTag
→ Fabric UIManager resolveView(tag)
→ concrete MLRNMapView.mapLibreMap
→ MapLibreMap.replaceWeatherRuntime(config)
→ WeatherRuntime typed command
```
Bridge 不接触 T0/T1/MIX/timeline integer command。`setForecastTime` 只接收 non-negative integral epoch milliseconds;ColorStop 限有限 RGBA `[0,1]` 与严格递增 speed;particle/trail color 独立于 WeatherColor ramp。无 `number[]`、JSON 数组、base64 或 Binary Field contract。
## 实际验证
- `npm install --package-lock-only --ignore-scripts --legacy-peer-deps --no-audit --no-fund`:PASS,生成/核对 lock。
- 构建输出节流下 `npx tsc --noEmit`:PASS。
- `node --check plugins/withParticleNativeAndroid.js`、版本/lock 一致性检查、禁止边界搜索:PASS。
- `git diff --check`:PASS。
## 未执行与风险
没有执行 Android Gradle、custom artifact publish、APK/AAB、ADB、安装、App launch、模拟器/真机或 Jest。故 Android codegen/TurboModule 的实际 Java/Kotlin 编译、MLRN autolinking project name、Maven Local artifact provenance、Fabric event target、style reload/remount 的时序和 Handler/renderer 行为均仍待人工验收。详细步骤在 `docs/60_测试/STEP-060_RNTestHost_Android人工编译与验收_v1.md`;包括 custom SDK build/publish、Test Host build/install、地图、同 reactTag 的五个 Phase A 命令、Phase B、style reload、old tag fail-closed、remount/unmount。
## Git
- 功能 commit:`4c906b21fbc9834699c5dcd62e551b05b2526c53`(`feat: add RN WeatherRuntime bridge test host`)
- 文档 commit:待提交
- Push:待提交至 `origin/particle/main`
- Final HEAD / Remote HEAD:待提交并 push 后回填。

View File

@@ -498,3 +498,9 @@ WeatherColorLayer 的 `ParticleGpuValidationUBO` designated initializer 补齐 `
- 独立代码审计发现 REAL WEATHER 下 `WeatherRuntime` timeline 命令被拒绝时,TestApp 原条件表达式会跳过 reject 分支并误记为成功。
- 已改为显式 `commandAccepted` 判定:REAL WEATHER 只接受 `WeatherRuntime.CommandResult.ACCEPTED`;拒绝时立即 return,绝不 fallback;legacy/diagnostic 低层 timeline 路径继续保留。
- 修正提交:`74e3cc911b8cecd4f3d75613055c213a8bcebcdb`;未执行 Android Gradle、APK、ADB、设备测试或 Jest。
# 2026-09-07 — STEP-060 RN Test Host 与 WeatherRuntime 薄桥接
- 建立 `integration/react-native/MapLibreParticleRNTestHost`,冻结 RN/Expo/MLRN 技术基线;style 预先创建 host-field RasterArraySource、WeatherColorLayer、RasterParticleLayer,但不传 Binary Field。
- MLRN 11.3.6 的共享 ReactTagResolver 实例由 `MLRNPackage` 私有持有;Test Host 改用 RN/Fabric 的公开 UIManager view resolver,即时收窄到 MLRNMapView 并读取其公开 MapLibreMap,不复制私有 mViews 或建立 current-map registry。
- MapLibreMap 新增 map-owned WeatherRuntime attach/detach seam;style replacement、view detach 与 React unmount dispose 旧 facade。Android custom SDK 必须先手工发布 Maven Local,Host 配置会排除 Maven Central 中 org.maplibre.gl fallback。
- 非 Android 验证:冻结 package-lock/config、Node config plugin 语法、禁止 Binary Field/global map/private registry 搜索与 throttle 下 `tsc --noEmit` 均通过;Android Gradle/设备/Jest 未执行。