diff --git a/docs/40_任务/STEP-060F_WeatherColorOpacity与Android收尾修复_Codex任务_v1.md b/docs/40_任务/STEP-060F_WeatherColorOpacity与Android收尾修复_Codex任务_v1.md new file mode 100644 index 000000000..00e974431 --- /dev/null +++ b/docs/40_任务/STEP-060F_WeatherColorOpacity与Android收尾修复_Codex任务_v1.md @@ -0,0 +1,297 @@ +# STEP-060F WeatherColor Opacity 与 Android 收尾修复 — Codex任务 v1 + +## 1. 任务定位 + +当前仍属于 **STEP-060**,不得进入 STEP-061。 + +STEP-060E 已完成 CoreOnly layer 存在性检查修复,并已完成 Android 实际验证: + +- `WeatherRuntime attached` 成功; +- `reactTag` 为有效 Fabric MLRNMapView tag; +- `WEATHER_OBJECTS_NOT_READY` 已消失; +- Phase A 的 enable / weather visible / particle visible / FPS 30 均返回 `ACCEPTED`; +- 无 Binary Field 时 runtime 保持 `WAITING_FOR_FIELDS / PAUSE / ...` 符合预期。 + +本任务是 STEP-060 最后一次源码收尾,集中处理: + +1. 修复 `WeatherRuntime.setWeatherColorOpacity()` Android 真 bug; +2. 固化 Test Host Metro 8091 的 Android 8081 reverse 兼容; +3. 保持已提交的 Test Host 横屏锁定; +4. 准备 `13.4.1-step060f`,由用户后续一次性手工构建 AAR + APK 并做最终验证。 + +## 2. 开工基线 + +仓库:`/mnt/sda1/MapLibreParticleLab` +分支:`particle/main` +开工目标 HEAD / remote HEAD:`204102f26049049151cd5471fada804d471e15a9` + +开工前必须: + +- `git pull --ff-only origin particle/main`; +- 确认 HEAD / remote HEAD 一致; +- 检查 working tree,不得清理或提交与本任务无关的历史文件; +- 保留 STEP-060E `hasStyleSource/hasStyleLayer` Core 真值链; +- 保留 `app.json` 的 `"orientation": "landscape"`; +- 不得回退 Win11 已验证的 RN 0.85.2 / React 19.2.3 / Expo 56 / MLRN 11.3.6 基线。 + +## 3. 已确认 Android 实测证据 + +ChatGPT 已通过 CARBON7i + ADB 对 `13.4.1-step060e` 实测,以下为已确认输入,不要重新猜根因: + +- `color stops` → `ACCEPTED` +- `particle RGBA` → `ACCEPTED` +- `trail RGBA` → `ACCEPTED` +- `particle count` → `ACCEPTED` +- `line width` → `ACCEPTED` +- `particle length` → `ACCEPTED` +- `particle opacity` → `ACCEPTED` +- `trail opacity` → `ACCEPTED` +- `trail fade` → `ACCEPTED` +- `weather opacity` → **`REJECTED`** + +时间线相关控制在尚无 T0/T1 field window 时返回: + +- PLAY / PAUSE → `REJECTED` +- HALF / NORMAL / DOUBLE → `REJECTED` +- seek now → `REJECTED` +- Native warning:`ParticleTimeline: event=REJECTED reason=TIMELINE_NOT_READY` + +这是当前无 field 的正常 fail-closed 行为,本任务不得为了让这些命令在 `WAITING_FOR_FIELDS` 下返回 ACCEPTED 而修改 Timeline/Playback 语义。 + +真正 blocker 为设备两次稳定复现: + +`ParticleGPU: event=STYLE_PROPERTY_SET result=UNSUPPORTED_PROPERTY` + +对应 UI:`weather opacity: REJECTED`。 + +## 4. 已确认源码根因 + +当前 `WeatherRuntime.setWeatherColorOpacity(float)` 走: + +`MapLibreMap.setStyleLayerFloatProperty(weatherColorLayerId, "weather-color-opacity", opacity)`。 + +但 `NativeMapView::setStyleLayerFloatProperty(...)` 只允许 `raster-particle-*` 属性,并把目标 layer `dynamic_cast` 为 `RasterParticleLayer`。 + +因此 `weather-color-opacity` 必然被 `UNSUPPORTED_PROPERTY` 拒绝。 + +Core `WeatherColorLayer` 已有正式 typed API: + +- `float getOpacity() const` +- `void setOpacity(float)` +- finite value;Core 内部 clamp 到 `[0,1]` + +Android 当前也已经有独立 `setWeatherColorStops(...)` Java → JNI → Core 路径,并直接 `dynamic_cast`。本任务应沿该模式做最小修正,不得扩大通用 particle property setter。 + +## 5. 必做实现 A:专用 WeatherColor opacity 路径 + +新增窄范围 typed Host API,建议稳定命名: + +`MapLibreMap.setWeatherColorOpacity(String layerId, float opacity): boolean` + +必须贯通至少: + +- `NativeMap.java` +- `NativeMapView.java` +- `MapLibreMap.java` +- `native_map_view.hpp` +- `native_map_view.cpp` +- JNI method registration + +C++ 必须: + +- 直接从 Core Style 按 id 取 layer; +- `dynamic_cast`; +- 非 WeatherColorLayer / layer 不存在 / 非 finite 输入时返回 false; +- 成功时调用 `WeatherColorLayer::setOpacity(opacity)` 并返回 true; +- 保持 `WeatherColorLayer` CoreOnly,不创建 Java Layer peer; +- 日志不得再复用误导性的 `ParticleGPU ... UNSUPPORTED_PROPERTY` 作为 WeatherColor 正常路径。 + +修改 `WeatherRuntime.setWeatherColorOpacity(float)`: + +- 不再调用 `setStyleLayerFloatProperty(..., "weather-color-opacity", ...)`; +- 改调新的 typed `setWeatherColorOpacity(...)`; +- `WeatherRuntime.CommandResult` 契约保持 `ACCEPTED / REJECTED`; +- 不在 Bridge/JS 增加第二套状态或兼容分支。 + +不得把 `weather-color-opacity` 加进现有 `setStyleLayerFloatProperty()` 的 particle whitelist 后再混合处理两个 layer 类型;应保持 WeatherColor 与 RasterParticle 两条 typed 路径分离。 + +## 6. 必做实现 B:Metro 8091 启动兼容 + +Android 实测确认:Test Host Metro 固定监听 CARBON7i `8091`,但当前 Debug APK 的 RN dev-server 探测仍从设备 `localhost:8081` 发起。 + +成功运行时需要同时存在: + +```text +adb -s 192.168.1.146 reverse tcp:8091 tcp:8091 +adb -s 192.168.1.146 reverse tcp:8081 tcp:8091 +``` + +仓库当前未跟踪 Win11 legacy 的 `scripts/05-install-and-run.ps1`。本任务应先检查现有仓库 README / 测试文档 / scripts 状态,再以最小可维护方式把该启动规则纳入 Git 受控来源。 +Win11 已验证 legacy 脚本现状为: + +- `$device = '192.168.1.146'` +- `adb -s $device get-state` +- `adb -s $device reverse tcp:8091 tcp:8091` +- `adb -s $device install -r $apk` +- force-stop + `org.maplibre.particle.rntesthost/.MainActivity` 启动 + +修正时只需在 install 前增加: + +`adb -s $device reverse tcp:8081 tcp:8091` + +不得删除原 `8091 -> 8091` reverse,不得改设备地址、package、activity 或 Metro 端口。 + +如果决定把脚本正式纳入仓库,则创建 `integration/react-native/MapLibreParticleRNTestHost/scripts/05-install-and-run.ps1`,内容以上述已验证行为为基线;同时更新中文 README / Android 人工验收文档说明双 reverse。不得顺手引入整套无关 Win11 脚本。 + +## 7. 必做实现 C:横屏配置保持 + +`204102f26049049151cd5471fada804d471e15a9` 已把: + +`app.json -> "orientation": "landscape"` + +提交到 `particle/main`。 + +本任务只需保护该配置,并在文档中明确下一次 Android prebuild/build 后应生成 `MainActivity android:screenOrientation="landscape"`。不得回退 portrait;Codex 不需要为了横屏运行 Android prebuild 或 APK build。 + +## 8. Maven / AAR 临时版本 + +Native Android API/JNI 会变化,因此必须使用新 coordinate: + +`org.maplibre.gl:android-sdk-opengl:13.4.1-step060f` + +同步更新至少: + +- `platform/android/VERSION` +- `integration/react-native/MapLibreParticleRNTestHost/modules/weather-runtime-bridge/android/build.gradle` +- `integration/react-native/MapLibreParticleRNTestHost/plugins/withParticleNativeAndroid.js` +- README 中当前 temporary native version 描述 + +不得复用 `13.4.1-step060e` 发布内容不同的 artifact。 + +Codex **不得构建 AAR,不得 publish Maven Local,不得构建 APK,不得运行 ADB/安装/启动 App**。 + +完成报告必须明确:`AAR_BUILD_NOT_EXECUTED_BY_CODEX`。 + +## 9. Linux 验证边界 + +只执行本轮必要的静态/精确非 Android-runtime 验证: + +- JNI Java/C++ 声明、实现、registration 签名一致性; +- 新 WeatherColor opacity 路径最终直达 `WeatherColorLayer::setOpacity()`; +- `WeatherRuntime.setWeatherColorOpacity()` 不再走 particle `setStyleLayerFloatProperty()`; +- 保持 particle float setter whitelist 与 `RasterParticleLayer` 语义不扩大; +- 检查 Metro 双 reverse 脚本/文档内容; +- 检查 `app.json` 仍为 landscape; +- 可执行 Linux OpenGL/C++ 精确编译或已有等价最小验证; +- 不执行 Android Gradle build/compile task; +- 不执行 Jest; +- `git diff --check`; +- 最终 diff 不得混入无关文件。 + +编译输出遵循全局 `$build-output-throttle`。 + +## 10. 明确禁止 + +本任务不得: + +- 修改 `RasterParticleLayerFactory` / `WeatherColorLayerFactory` 的 CoreOnly 注册; +- 新建 WeatherColor Java Layer peer; +- 把 WeatherColor opacity 混进 particle property whitelist; +- 改变 Timeline 在无 field 时 `TIMELINE_NOT_READY` 的 fail-closed 行为; +- 实现或提前提交 Binary U/V Field Bridge; +- 进入 STEP-061; +- 修改 NavSea 正式代码; +- 启动 Metro、Android emulator、ADB 或设备验证; +- 为了验证横屏单独构建 APK; +- 清理历史 build/node_modules/untracked 文件。 + +## 11. 文档要求 +完成后至少: + +- 新增 `docs/报告/STEP-060F_WeatherColorOpacity与Android收尾修复_Codex完成报告_v1.md`; +- 生成 `docs/50_Step记录/STEP-060_RNTestHost与WeatherRuntime薄桥接_v2.md`,保留 v1 作为历史; +- 更新 `docs/60_测试/STEP-060_RNTestHost_Android人工编译与验收_v1.md` 或递增版本,加入:双 reverse、横屏、weather opacity 最终验证; +- 更新 `粒子开发记录.md`。 + +文档必须记录: + +- STEP-060E Android attach 已 PASS; +- `WEATHER_OBJECTS_NOT_READY` 已解决; +- `TIMELINE_NOT_READY` 在无 Binary Field 时是预期行为; +- STEP-060F blocker 是 WeatherColor opacity 错走 particle-only setter; +- 修复后临时版本为 `13.4.1-step060f`; +- Android 最终 AAR/APK/设备复验仍等待用户; +- 当前状态必须是 `IMPLEMENTED / WAITING_ANDROID_VALIDATION`,不得提前写 CLOSED / PASS。 + +## 12. Git 收尾 + +只提交本任务相关源码、版本接线、脚本/文档和本任务文件。 + +必须: + +- `git diff --check` PASS; +- commit 到当前 `particle/main`; +- push `origin/particle/main`; +- push 失败时不得声称完成; +- 不得提交与本任务无关的本地改动。 + +完成报告必须记录: + +- Starting HEAD; +- source commit SHA; +- Final HEAD; +- Remote HEAD; +- commit message; +- push 结果; +- remote branch; +- 预期 Maven coordinate:`org.maplibre.gl:android-sdk-opengl:13.4.1-step060f`; +- `AAR_BUILD_NOT_EXECUTED_BY_CODEX`。 + +## 13. Codex 最终报告清单 + +结束时逐项报告 `已完成 / 未完成 / 无法验证`: + +- WeatherColor typed opacity Java API; +- NativeMap / NativeMapView JNI 链; +- C++ 直达 `WeatherColorLayer::setOpacity()`; +- `WeatherRuntime.setWeatherColorOpacity()` 切换到 typed 路径; +- particle property setter 未扩大; +- Metro `8081 -> 8091` 与 `8091 -> 8091` 双 reverse 纳入受控来源; +- landscape 配置保持; +- `13.4.1-step060f` 版本接线; +- Linux 精确验证; +- 中文文档更新; +- Git commit/push; +- AAR/APK/ADB 未由 Codex 执行; +- 未进入 STEP-061。 + +## 14. 停止条件与后续人工链路 + +Codex 成功 push 后立即停止,不得自行进入 Android artifact/runtime 阶段。 + +后续固定顺序: + +1. ChatGPT 审核 `particle/main` 远端实际源码与 diff; +2. 审核通过后,用户在 Linux 手工构建并 publish `13.4.1-step060f` OpenGL Release AAR; +3. Linux 记录 build AAR 与 Maven Local AAR SHA256,必须一致; +4. CARBON7i Git pull 最新 Test Host 源码; +5. AAR 临时复制到 `/mnt/nas/pbf/`,Win11 使用 `curl.exe -L` 从 `https://pbf.jpcn.ccwu.cc/` 下载; +6. 下载 URL 必须使用每次不同的 `?v=` 防止 CDN cache; +7. Win11 SHA256 必须与 Linux 完全一致; +8. 安装 Win11 Maven Local; +9. Bridge 与 MLRN 两条 `dependencyInsight` 必须共同解析到 `13.4.1-step060f`; +10. 用户手工 `assembleDebug`; +11. 使用修正后的启动流程安装/启动; +12. Android 最终验收。 + +最终 Android hard gate: + +- App 锁定横屏; +- `WeatherRuntime attached`; +- `WEATHER_OBJECTS_NOT_READY` 不出现; +- `weather opacity: ACCEPTED`; +- 不再出现 `STYLE_PROPERTY_SET result=UNSUPPORTED_PROPERTY`; +- Phase A 基础命令继续工作; +- 无 field 时 `TIMELINE_NOT_READY` 仍允许存在。 + +只有上述最终 Android 结果通过后,才允许把 **STEP-060 标记为 CLOSED / PASS**,然后进入 **STEP-061 Binary U/V Field Transport**。