# 粒子开发记录 ## 2026-08-27 — STEP-000 - 建立正式 Ubuntu MapLibreParticleLab 工作目录。 - MapLibre core:18545ca10d296704b2cba675b182ff2c8da24588 ## 2026-08-28 — STEP-000 环境基线冻结 - Ubuntu 24.04 x86_64 MapLibreParticleLab 主开发环境建立完成。 - Linux OpenGL Native 构建通过。 - `mbgl-render` 构建通过。 - `mbgl-render-test-runner` 构建通过。 - Android OpenGL Debug `apackage` 构建通过。 - Android Vulkan Debug `apackage` 构建通过。 - OpenGL/Vulkan AAR 均包含 arm64-v8a、armeabi-v7a、x86、x86_64 的 `libmaplibre.so`。 - Vulkan Debug AAR 同时包含 Khronos Validation Layer。 - Android SDK 路径已通过 `ANDROID_HOME` 与 `local.properties` 固化。 - 下一步进入 STEP-001:MapLibre Native 粒子接入点只读调查。 ## 2026-08-29 — 10_架构调查 - 按 `docs/40_任务/10_架构调查指令书_v1.md` 完成只读架构调查。 - 确认当前仓库是 MapLibre Native monorepo,不是 React Native 应用;确认 Android 13.4.1、iOS 6.28.0 和共用 Core 渲染链。 - 确认 Android OpenGL/Vulkan、iOS OpenGL/Metal、Core CustomLayer/gfx、Camera/Matrix、帧驱动和线程边界;粒子 fixture 目前只有空目录占位,暂无粒子运行时代码。 - 生成 `docs/20_调查/10_架构调查报告_v1.md` 和 `docs/报告/10_架构调查_Codex完成报告_v1.md`。 - 本次未修改生产代码、原生工程、依赖或项目总则;遵循用户要求未自行创建或修改 Step 文件。 ## 2026-08-29 — 20_架构设计 - 按 `docs/40_任务/20_架构设计指令书_v1.md` 完成第一版正式粒子系统总体架构设计。 - 生成 `docs/10_架构/20_粒子系统总体架构设计_v1.md` 和 `docs/报告/20_架构设计_Codex完成报告_v1.md`。 - 正式主路线冻结为独立 Core `RasterParticleLayer/RenderRasterParticleLayer` + `RasterArraySource` + 隔离 `mbgl::particle` 模块,进入 Style/RenderTree 并使用 MapLibre gfx;CustomLayer/CustomDrawable 不作为产品主宿主。 - 冻结 WeatherColor/Particle 分层、Field/fixture contract、Wind GLOBAL、海洋场 OCEAN_ONLY 共用 Mask、MapLibre frame driver、同帧 Camera Matrix、GPU resource/context-loss 和平台薄接入原则。 - 下一阶段选择 `30_最小技术验证`,集中验证独立 RenderLayer、OpenGL/Vulkan ping-pong/trail/context、Camera/wrap/Mask 和 iOS 薄接入。 - 最终 FPS、最大粒子数、最佳 texture format、生产 Mask 来源、真实天气协议和生产 Host API 仍未确认。 - 本次未修改生产代码、依赖、构建配置、项目总则或 Step,未运行构建/测试。 ## 2026-08-29 — 30-01 Core RenderLayer 接入验证(阶段 A) - 按 `docs/40_任务/30_01_CoreRenderLayer接入验证指令书_v1.md` 完成最小验证代码准备。 - 新增 source-less `ParticleValidationLayer/RenderParticleValidationLayer`,经正式 Style/LayerManager/RenderTree/LayerGroup/translucent pass 链接入;代码明确标记 `VALIDATION ONLY`。 - 新增默认 false 的 RenderLayer repaint hook;ACTIVE 通过 MapLibre 自身 `needsRepaint → Map::onUpdate → Android requestRender` 链持续帧,STATIC 停止验证层额外请求。 - 验证 Drawable 在真实 pass 内读取当前 `PaintParameters/TransformParameters/TransformState` 的 viewport、zoom、bearing、pitch 和 projection matrix 摘要。 - Android Test App 新增 `Particle Core Layer Validation` 页面,提供 ACTIVE/STATIC 切换和蓝/黄普通 Style Layer 顺序参照。 - Linux OpenGL 重新配置通过;本任务新增/直接修改的 5 个 Core 对象精确编译通过。全量增量因公共头触发 321 个对象重编译,在 41/321 无错误时主动停止,未宣称全量 PASS。 - 遵循指令书未运行 Android/Gradle/npm/ADB;等待用户手工 Android OpenGL 编译、运行、手势、resize 与日志证据。 - 当前结论为 `WAITING_MANUAL_VALIDATION`;不得进入下一项 GPU ping-pong/Trail 验证。 ## 2026-08-29 — 30-01 Core RenderLayer 接入验证(阶段 B 修复轮次 1) - 用户 Android OpenGL 实机日志暴露 `RenderParticleValidationLayer::update()` 的 DrawableBuilder 生命周期错误:当前 Drawable 未完成就调用 `clearDrawables()`,RenderThread 随后触发 SIGSEGV。 - 对照 `DrawableBuilder::flush(context)` 与仓库既有 Drawable 使用方式,在 `clearDrawables()` 前补充 `builder->flush(context)`,使 custom validation Drawable 完成后再转移给 LayerGroup。 - 未以空指针判断跳过 Drawable;Tweaker 仍必须进入真实 translucent render pass 并读取同帧 Transform。 - Linux OpenGL 对应目标对象编译通过;C++ 格式和 `git diff --check` 通过。 - 未运行 Android/Gradle/npm/ADB,等待用户在新提交上重新手工编译和实机运行。 - 当前结论仍为 `WAITING_MANUAL_VALIDATION`;未扩大到粒子、GPU ping-pong、Trail、Mask、Vulkan 或 iOS。 ## 2026-08-29 — 30-01 Android Test App APK 版本标识 - 在 Test App 主菜单列表顶部增加当前 APK 构建身份显示。 - 显示 `versionName/versionCode`、renderer flavor、build type 和构建时 Git revision 前 10 位,均来自 BuildConfig,不写死版本。 - 版本条用于人工验证时区分旧 APK 与当前源码构建,避免只凭安装时间或文件名判断。 - `git diff --check` 与 Android XML 标准库解析通过;按用户要求未执行任何编译。 - 等待用户手工构建、安装后确认设备端显示。 ## 2026-08-29 — 30-02 GPU Ping-Pong 与 Context Recreation(前置阻塞) - 开始执行 `docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md` 并首先检查硬前置门槛。 - 30-01 最新技术报告与完成报告均仍为 `WAITING_MANUAL_VALIDATION`,不存在正式 PASS 记录或 PASS commit。 - 按 30-02 指令书第 2 节停止:未创建 State A/B、Trail A/B、RenderTarget、Shader、ping-pong、generation 或 context recreation 验证代码。 - State A/B、Trail A/B、gfx 同步、resize、disable/enable 和 context recreation 均未验证,无 PASS/FAIL 技术结论。 - 当前 30-02 状态为 `BLOCKED`;不允许进入 30-03。 - 阻塞报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md`。 - Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v1.md`。 ## 2026-08-29 — 30-01 Core RenderLayer 接入验证(用户验收 PASS 回填) - 用户已完成 Android OpenGL 构建和 `Particle Core Layer Validation` 实际运行验收,明确确认结果为 OK/PASS。 - 30-01 正式状态由 `WAITING_MANUAL_VALIDATION` 更新为 `PASS`;Core RenderLayer 接入、ACTIVE/STATIC repaint、同帧 Transform 及 pan/zoom/bearing/pitch/resize 验证范围均由用户确认满足要求。 - 本次只回填验收状态:未重新修改 30-01 代码、未重新编译、未重新运行 Android、未执行 ADB。 - 30-01 正式完成,允许重新开始 30-02。 - 30-02 v1 的 `BLOCKED` 历史记录继续保留;它反映当时 30-01 正式 PASS 尚未回填,不代表 GPU/gfx 架构验证失败。 ## 2026-08-29 — 30-02 GPU Ping-Pong 与 Context Recreation(阶段 A) - 30-01 正式状态为 `PASS`,此前 30-02 v1 的历史 `BLOCKED` 前置原因已解除;开始重新执行 30-02 指令书。 - validation-only State A/B 已使用两套固定尺寸独立 GPU RenderTarget 实现;每帧 read/write 反向选择,无 CPU 完整状态复制。 - Trail A/B 已使用两套 viewport 尺寸真实 RenderTarget 实现 previous fade/marker → next,并把 next 合成到 MapLibre 主 translucent pass。 - 静态确认只注册当帧 write target,read target 不作为当帧附件;RenderTarget 顺序为 State → Trail,主 pass 后续 composite,slot 在 composite Tweaker 到达时提交。 - resize 只重建 Trail A/B 并保留 State A/B;disable/remove 会停止并释放或重置资源;context lost 记录旧 generation discard,新资源使用递增 generation。 - 复用 `Particle Core Layer Validation`,保留 ACTIVE/STATIC 并增加 DISABLE/ENABLE;没有修改通用 gfx API、正式粒子、Mask、Vulkan 或 iOS。 - 静态格式、JSON、shader 注册链与 diff 检查通过;遵守用户要求未编译,未运行 Gradle/Android/ADB。 - 当前状态为 `WAITING_MANUAL_VALIDATION`:State/Trail 实际 GPU 交替、OpenGL 同步、resize、disable/enable 和真实 context recreation 均等待用户手工运行证据。 - 不允许进入 30-03;若无法确认真实 context recreation,最终应按指令书标记 `BLOCKED`。 - 技术报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v2.md`。 - Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v2.md`。 ## 2026-08-30 — 30-02 T3 STATIC freeze 实机缺陷修复 - 用户 Android OpenGL 手工验证确认:STATIC 静止时 State/Trail 停止,但 STATIC 拖动地图触发 MapLibre redraw 时仍继续推进,停止拖动后再停止;原 T3 正式判定为 FAIL。 - 原因是 `needsRepaint=false` 只停止 validation 主动请求帧,而原 `update()` 在地图手势帧中仍无条件注册 State/Trail RenderTarget、设置 pending,并由 composite Tweaker提交 slot/frame。 - 最小修复在 `RenderParticleValidationLayer` 增加 STATIC frozen-composite 路径:地图主 pass 仍正常 redraw 并显示最后 commit 的 Trail,但不注册离屏 target、不执行 State/Trail update、不 fade/加 marker、不 swap、不增加 simulation frame/index。 - STATIC 下不因 resize 重建/清空 Trail;恢复 ACTIVE 后才继续原 ping-pong 与 resize 生命周期。 - 仅修改 validation RenderLayer `.cpp/.hpp` 和本轮文档;未修改 Test App、shader、通用 gfx、正式粒子、Mask、Vulkan 或 iOS。 - C++ 格式、diff 与 GPU scheduling/commit 静态控制流检查通过;按用户要求未编译,未运行 Android/Gradle/ADB。 - 修复后的 T3 等待用户在 commit `364b8f381e27eee36c4895084b2f0578a023fa61` 上重新手工验证;30-02 总体状态仍为 `WAITING_MANUAL_VALIDATION`,不允许进入 30-03。 - 技术报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v3.md`。 - Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v3.md`。 ## 2026-08-30 — 30-02 Android Rotation 状态恢复定向修复 - 用户确认此前 STATIC 的 pan/zoom/bearing/pitch 手势回归已经通过,DISABLE / ENABLE 正常;但旋转导致 Activity recreation 后 STATIC 错误恢复为 ACTIVE。 - 根因是 Test App 没有将 `active/enabled` 写入 Bundle,且 `onCreate()` 无条件恢复 ACTIVE + ENABLED 并重置 camera。 - 仅在 `ParticleCoreLayerValidationActivity.kt` 新增 Bundle key、保存/恢复 validation control mode;recreation 复用恢复后的统一 `loadValidationStyle()`,且只在首次进入设置默认 camera。 - 未修改 Manifest、C++、gfx、RenderLayer、shader、GPU ping-pong、GPU 状态、Gradle 或依赖;未使用 configChanges、方向锁定、SharedPreferences、全局变量或 GPU 序列化。 - `git diff --check` 与状态控制静态检查通过;按要求未运行 Gradle、Android 编译或 ADB。 - R1 STATIC、R2 ACTIVE、R3 DISABLED rotation 与 R4 STATIC gesture 回归等待用户实机验证;30-02 保持 `WAITING_MANUAL_VALIDATION`,不允许进入 30-03。 - 技术报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v4.md`。 - Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v4.md`。 ## 2026-08-30 — 30-02 正式关闭(EGL Context Recreation Accepted Risk) - 用户已完成并确认 30-02 的 Android OpenGL 实机结果;ACTIVE/STATIC、GPU ping-pong、STATIC 手势冻结、DISABLE/ENABLE 与 rotation control-mode 恢复纳入正式结论。 - 30-02 正式状态为 `PASS`,并正式关闭;允许进入 30-03。 - 真实 EGL Context recreation 没有独立实机验证证据,明确标记为 `Accepted Risk / 未验证项`;用户已明确决定该风险不阻塞后续阶段。 - 未伪造 context-loss PASS,也未重写 v1 `BLOCKED`、v2、v3 或 v4 历史报告。 - 本次只回填报告与开发记录;未修改代码,未重新编译,未运行 Gradle、Android 或 ADB。 - 技术报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v5.md`。 - Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v5.md`。 ## 2026-08-30 — 30-03 Camera / World Wrap 与 Land/Ocean Mask(阶段 A) - 30-02 已正式 PASS,EGL Context recreation 作为用户接受的未验证风险不阻塞,故开始 30-03。 - validation composite 改为使用当前 `PaintParameters::matrixForTile()` 的 canonical z0 world quad;ACTIVE/STATIC 继续区分 simulation update 与 Camera redraw。 - 通过 `UnwrappedTileID.wrap` 绘制中心和相邻 MapLibre world copy;仅中心 copy commit,避免 world copy 额外推进 30-02 GPU simulation。 - 增加反经线两侧 deterministic anchors C/D,并以全球 canonical mask UV 复用 MapLibre wrap,不建立第二套 world 状态机。 - 增加 validation-only shared 16×16 synthetic coastal mask,GLOBAL、OCEAN_ONLY_A/B 复用同一 GPU texture;Camera/consumer 切换不重建,context-destroy 通知后按新 generation 重建。 - Android Test App 复用既有入口,增加 GLOBAL/OCEAN A/OCEAN B/DATELINE/WORLD WRAP 最小控制;未运行 Android 编译、Gradle 或 ADB。 - Linux OpenGL 受影响 Core 对象精确编译、C++ 格式与 diff 检查通过;用户 T1–T13 实机验证仍待执行。 - 当前状态:`WAITING_MANUAL_VALIDATION`;不允许进入 iOS 最小验证。 - 技术报告:`docs/60_测试/30_03_Camera_WorldWrap与LandOceanMask最小技术验证报告_v1.md`。 - Codex 完成报告:`docs/报告/30_03_Camera_WorldWrap与LandOceanMask验证_Codex完成报告_v1.md`。 ## 2026-08-31 — 30-03 Camera / World Wrap 与 Land/Ocean Mask(最终 PASS) - 用户已完成 Android OpenGL 手工验收,T1–T13 全部记录为 `PASS`;30-03 正式状态更新为 `PASS`。 - 已确认本最小验证范围内的 Camera 同帧地理锁定、ACTIVE/STATIC camera redraw 分离、world wrap、双向反经线连续性,以及 shared Land/Ocean Mask 的 GLOBAL / OCEAN_ONLY_A / OCEAN_ONLY_B 语义。 - `Rotation/Viewport 自动恢复问题` 为已知问题;用户接受延期,明确在下一个任务修复。本轮不声称该问题已修复,也不将其伪造为已验证功能。 - 真实 EGL context recreation 的独立设备证据、正式 fixture adapter、正式 NoData fail-closed 和生产 coastline 数据仍未完成;EGL 风险沿用 30-02 的 `Accepted Risk / 未验证` 边界。 - 30-03 已允许进入下一阶段;下一任务优先处理 Rotation/Viewport 自动恢复延期项。 ## 2026-08-31 — 40-01 Android 离线 Fixture 到正式粒子渲染最小闭环(Stage A) - 30-03 后进入 Android 第一条离线 fixture 粒子闭环;Rotation/Viewport 自动恢复技术债已纳入本任务。 - 新增 backend-neutral `OfflineFixtureParticleAdapter` 和 `ParticleFieldSnapshot`,以 v1 metadata、binary length 与 SHA-256 把 uniform-east、uniform-north、vortex 解码为正式 Field;不使用在线数据或 Android UI 依赖。 - GPU field texture 接入既有 State A/B;Trail A/B 改为读取 State write texture,fixture 切换递增 field/gpu field generation 并清理旧 trail;Mask 继续走既有 shared GLOBAL/OCEAN_ONLY 路线。 - STATIC 不再阻止 resource bootstrap:Activity/context recreation 后会建立 field/mask/trail/state 并做零步 first composite,`simulationFrame` 不增加;Activity 保存 active/enabled/mask/fixture 选择。 - Linux OpenGL 受影响 Core 对象、C++ format、diff、fixture checksum 和 adapter smoke test 均通过;未运行 Gradle/ADB/实机验证。 - 当前结论:`WAITING_MANUAL_VALIDATION`。用户仍需完成 Android OpenGL T1-T12,尤其 T1 rotation 无按钮恢复;iOS、Vulkan、真实数据、生产 mask 和性能均未覆盖,尚不建议进入下一 Android 子任务。 - Stage A 实现提交 `0b076c6d52fffb2ee4411cac64f06d43cea260c8` 已成功 push 到 `origin/particle/main`。 ## 2026-08-31 — 40-01 Stage A 正式链、Android fixture 边界与 NoData 修正 - 纠正此前实现仍借用 source-less `ParticleValidationLayer` 的偏差:新增正式 `RasterArraySource -> RenderRasterArraySource -> RasterParticleLayer (Source::Required) -> RenderRasterParticleLayer`,并让正式 RenderLayer 复用既有 GPU field、State A/B、Trail A/B、Mask、Camera/World Wrap/Antimeridian 与生命周期。 - Android Test App 的 Style 现在创建 `raster-array` / `raster-particle`,fixture 由 APK `assets/integration/particle-fixtures/` 的 `asset://` URI 提供;Core adapter 仅接收 FileSource bytes。Linux smoke helper 继续读取仓库 fixture,生成工具验证并同步两端完全相同的 metadata/field 内容。 - `ParticleFieldSnapshot` 将 cell validity 独立于 fixture validity:合法 NoData cell 产生 invalid mask,GPU texture alpha 表示该 mask;State sample 命中 NoData 后确定性 respawn,不将 `-9999` 当普通速度;NaN/Inf 仍拒绝。新增 `nodata` deterministic fixture。 - STATIC/context recreation 的 zero-step bootstrap 未推翻:新资源自动建立并首帧 composite,bootstrap commit 不增加 simulation frame。 - Linux Core 精确编译、format/diff、fixture generator、adapter/asset parity 检查在最终收尾复跑;未运行 Gradle、APK、ADB 或 T1-T12。最终状态仍只能是 `WAITING_MANUAL_VALIDATION`,等待 GPT 再次复审远端代码。 ## 2026-09-01 — 40-01 RasterArray OfflineDownload 穷尽接入 - Android OpenGL 实际 C++ 编译暴露 `OfflineDownload` 的 required-resource-count 与 resource-queue 两处 `SourceType` 穷尽 switch 漏掉 `RasterArray`。 - 根据当前实现,`RasterArraySource` 只从平台 `FileSource` 获取确定性 fixture metadata/field bytes;40-01 Android 输入固定为 APK `asset://integration/particle-fixtures/...`,且 Source Impl 不包含 tileset、zoom range 或 OfflineDownload 托管资源 contract。因此两处都以显式 `SourceType::RasterArray` no-op 表达语义,不虚报资源数、不进入下载队列。 - 不增加 `default:`;全仓非 vendor 的 `SourceType` switch 已复核,本次仅修复新增枚举的直接遗漏。Linux/Core `offline_download.cpp.o` 精确编译(`-Werror`)、`clang-format --dry-run --Werror` 与 `git diff --check` 均通过;未运行 Gradle 或 ADB,40-01 继续为 `WAITING_MANUAL_VALIDATION`。 ## 2026-09-01 — 40-01 RasterArray Source RenderItem 空指针修复 - Android OpenGL 首次实机启动确认 field fixture 已加载、RasterParticleLayer 已 evaluate 后,RenderThread 在 State A/B 创建前因 `Renderer::Impl::render()` fault addr `0x0` 崩溃。 - 调用链确认:loaded + needsRendering 使 `RenderRasterArraySource` enabled;RenderOrchestrator 要求 enabled source 返回合法 RenderItem;RenderTree 无条件解引用。原 `createRenderItem()` 返回空指针违反该既有契约。 - RasterArray source 改为按 ImageSource 的 prepare/create 生命周期提供 no-op RenderItem(无 upload、无 render pass、无 debug drawable、无 particle draw);不改全局 RenderOrchestrator,不增加第二套粒子 renderer,粒子 GPU 路径仍由 `RenderRasterParticleLayer` 负责。 - Linux/Core `render_source.cpp.o` 与新增 source test object 均以 `-Werror` 精确编译;format、diff 与全部 RenderSource `createRenderItem()` return audit 通过。未运行完整 Linux 测试二进制、Android Gradle、ADB 或真机测试,40-01 继续为 `WAITING_MANUAL_VALIDATION`。 ## 2026-09-01 — 40-01 Android ACTIVE / STATIC simulation lifecycle 修复 - 实机日志中反复出现的 `ParticleValidation30_02: disabled reset generation=...` 唯一来自 `RenderRasterParticleLayer::markLayerRenderable(false)`。调用链复核确认:`RenderOrchestrator::createRenderTree()` 在逐一处理每个 source 时为不匹配 source 的 layer 给出临时 `false`;同一 render tree 随后处理匹配的 `raster-array` source 又恢复 `true`。该 `false` 不是持久 disabled 生命周期事件。 - 原 override 在这个临时回调中移除 target、清空注册、执行 `ParticleGpuResources::resetSequence()`;因此 `committedFrame`(正式 `simulationFrame`)每帧回到 0,`stateRead/trailRead` 每帧回到 A、seed 标记变 false,ACTIVE 永远 schedule/commit frame 1,STATIC 每帧重新走 zero-step bootstrap。 - 已移除 `markLayerRenderable(false)` 的错误 reset;layer 仍保留 base renderable 状态。State/Trail 资源只在 field/fixture generation 改变、Trail viewport 重建、context lost 后资源重建、或 layer removal 时按已有路径失效/清理。`ParticleGpuResources` 仍由 `RenderRasterParticleLayer::gpuResources` 持有,跨 `render()` 持久存在。 - ACTIVE 现在连续按 A→B、B→A 交换并让 `committedFrame` 递增;STATIC 在未 seed(初次或真实资源事件)时只做一次 zero-step bootstrap,已有状态时只走 FrozenComposite,不注册离屏 target、不 commit;STATIC→ACTIVE 复用既有 slot/frame 继续 simulation。没有改变 pass 次序 `State,Trail,Composite`、hazard=SAFE、fixture/resourceGeneration contract 或 public API。 - 日志现在在 ACTIVE/STATIC transition 输出 generation、fixture、frame 与 read slot;schedule/pass/commit 输出前 3 帧及每 60 帧,避免长期高频洪水,同时可明确验收 1→2→3 与 A/B 交替。 - Linux OpenGL `render_particle_validation_layer.cpp.o` 精确编译、`clang-format` 与 `git diff --check`:PASS。40-01 保持 `WAITING_MANUAL_VALIDATION`,等待用户用新 APK 完成 GLOBAL ACTIVE、ACTIVE→STATIC、STATIC→ACTIVE 手工验收。 ## 2026-09-01 — 40-01 Formal RasterParticle Trail Composite 显示修复 - 实机已证明 generation 稳定、simulationFrame 连续递增、State/Trail A/B ping-pong 与 `hazard=SAFE` 正常;画面静止不再是 lifecycle/repaint/clock 问题。 - 根因位于最终 Composite:Trail pass 确实从最新 State write 画入 Trail A/B,但 Composite 仅将 Trail RGB 计算为 alpha intensity,最终 RGB 始终是 30-03 legacy 的 stripe/anchor。因此正式 field simulation 没有成为屏幕主体。 - `ParticleGpuResources::formalDisplay` 由 `RasterParticleLayer` 的 formal source 身份设置,并通过现有 UBO `u_mask.z` 传入 shader。正式 `FORMAL_PARTICLE` Composite 输出当前 Trail RGB 与由其 intensity 导出的 premultiplied alpha;legacy `ParticleValidationLayer` 继续走未改变的 `VALIDATION` stripe/anchor/world-wrap 分支。 - `ParticleRender` 新增一次性 displayMode 日志;既有低频 schedule 日志补充 `trailStateSource`、`compositeTrailSource` 和 displayMode,可证明 State write → Trail write → Composite Trail write 的数据关系,而不每帧刷屏。 - `shaders/particle_gpu_validation.fragment.glsl` 为唯一 shader source,使用 `node shaders/generate_shader_code.mjs` 正常生成 OpenGL header;二次生成哈希一致。生成器同时规范化 `src/mbgl/shaders/shader_source.cpp`,该生成物一并保留以保证生成后工作树稳定。 - Linux OpenGL 受影响 RenderLayer object、相关 `source.test.cpp.o` 均精确编译;C++ format、diff check 通过。按任务边界未运行 Android Gradle、ADB 或真机;40-01 继续为 `WAITING_MANUAL_VALIDATION`,下一轮只验收 GLOBAL + ACTIVE + uniform-east 的可见 eastward 运动。 ## 2026-09-01 — 40-01 Formal RasterParticle 显式 State Seed 修复 - 实机日志确认 formal display、State/Trail/Composite slot wiring、simulation frame 与 hazard 均正确,但正式粒子仍不可见。`RenderTarget::render()` 的既有全局 clear 是 opaque black `(0,0,0,1)`;未修改该 MapLibre contract。 - 原 State shader 用 `previous.a < 0.5` 判断是否第一次 seed,但新 State target alpha 为 1,导致全部 16×16 texel 从 `(0,0)` 而非各自 `v_uv` 开始。uniform-east 只推动 x,marker 聚集在 canonical world 顶缘、常在当前视口外。 - `ParticleGpuResources::stateSeeded` 现在是唯一权威。State pass 把 `!stateSeeded` 通过现有 UBO 的 `u_mask.w` 传入;shader 仅以该 flag 选择 `v_uv` 或 `previous.rg`,不再以 texture alpha 推断生命周期。Field `alpha` 仍仅表示 NoData validity。 - ACTIVE 第一次 State pass 与 STATIC zero-step bootstrap 都对每个 texel 进行 `v_uv` seed;Composite commit 后 `stateSeeded=true`,之后继续 read texture。新 resources、context recreation 和 fixture/field `resetSequence()` 保持重新 seed;普通 ACTIVE、Camera、STATIC 与 transient source renderability 不会 seed。 - 新增低频 `ParticleRender: stateSeed=INITIALIZE|CONTINUE` 日志,含 generation、State A/B 与 fixture。shader source/header generator parity、生成器幂等、Linux Core 与 Source test object 编译、format 和 diff 均通过;未运行 Android Gradle/ADB/真机,状态仍为 `WAITING_MANUAL_VALIDATION`。 ## 2026-09-02 — 40-01 RasterArray Source 重建 Field Identity 修复 - 用户实机确认 GLOBAL ACTIVE uniform-east、ACTIVE→STATIC→ACTIVE 均通过;点击 uniform-north 后仍 eastward。Android Test App 已正确重建 `raster-array` source,根因不在 UI 或 shader/ping-pong。 - `RasterArraySource::tryLoad()` 原有 `generation` 是 source 实例成员;Style 用同一 source ID 重建时 east 与 north 都可得到 generation 1。`RenderRasterParticleLayer` 正式路径又只比较 generation,因此错误保留 east GPU field texture。 - runtime generation 改为 `raster_array_source.cpp` 的 process-wide atomic 单调 revision;它只表达运行时 snapshot identity,不混用 metadata `dataVersion`,也不使用时间或随机数。source load 日志现在含 fixtureId、generation、dataVersion。 - renderer 使用 shared `fieldIdentityChanged()` 三元判断:generation、fixtureID、dataVersion 任一改变都会重新上传 field texture 并保留既有 `resetSequence()`、State re-seed、Trail clear 路径;三者相同不重复上传。fixture switch 日志记录 from/to、old/new generation、gpuFieldGeneration、trail clear 与 state seed。 - 新增定向 C++ 测试:两个独立 RasterArraySource 实例加载 east/north 得到不同 generation;同 generation 的 east/north 仍判定 identity changed;同 fixture/generation/dataVersion 不判定变更,dataVersion 改变则判定变更。 - Linux OpenGL 的 RasterArraySource、RenderLayer 与 `source.test.cpp` 精确编译,format/diff 均通过;未运行 Android Gradle/ADB/真机,40-01 继续 `WAITING_MANUAL_VALIDATION`。下一轮只验收 GLOBAL + ACTIVE + uniform-east 后切 uniform-north 的方向变化。 ## 2026-09-02 — 40-01 Stage B Android OpenGL 最终关闭 - 用户完成 Android OpenGL x86_64 手工验收,40-01 正式状态更新为 `PASS`。 - GLOBAL + ACTIVE + UNIFORM EAST、ACTIVE→STATIC→ACTIVE、UNIFORM EAST→UNIFORM NORTH→UNIFORM EAST、STATIC OCEAN A/B Rotation 自动恢复、ACTIVE Rotation、Pan/Zoom/Bearing/Pitch、World Wrap、双向 Antimeridian、GLOBAL/OCEAN A/OCEAN B、Shared Mask reuse、DISABLE/ENABLE、快速 fixture 切换与最终重复 Rotation 回归全部 PASS。 - 同一 RenderThread/resource generation 内 GLOBAL/OCEAN_ONLY_A/OCEAN_ONLY_B 复用同一 `maskGeneration`,日志为 `reuse=true`;graphics resource 重建后的 generation/maskGeneration 递增属于新 GPU resource,不属于同 generation 内重复创建。 - 40-01 历史调试链完整保留:OfflineDownload exhaustive switch、RasterArray no-op RenderItem SIGSEGV、Android APK/.cxx 旧 native 缓存、lifecycle reset loop、formal Composite Trail 显示、shader source/generated header 同步、opaque clear State seed、field identity generation collision、Rotation/Viewport STATIC restore 均已解决并由最终手工回归覆盖。 - 本次仅回填 Stage B 文档,不重新运行 Android Gradle、ADB 或实体机;iOS/Metal、Vulkan、真实数据、生产 mask、性能和独立 EGL context-loss 设备证据仍为范围外,不被 40-01 Android OpenGL PASS 隐含覆盖。 ## 2026-09-02 — 40-02 Android 双时间片 GPU 时间插值(代码阶段) - 在 40-01 唯一正式 `RasterArraySource -> RasterParticleLayer -> GPU Simulation -> Trail -> Composite` 链路上扩展为 T0/T1 两份 immutable Field snapshot;source 通过可选 `next-fixture/next-metadata/next-field` 从同一 FileSource byte boundary 加载,拒绝 grid/bounds/NoData/Field 语义不兼容的窗口。 - `RasterParticleLayer` 新增 `raster-particle-time-mix` 常量属性;其只更新既有 UBO。State shader 分别从两张 GPU Field texture 解码速度后 GPU `mix`,没有 CPU 完整中间 Field、第二 Layer 或第二 simulation。 - Renderer 保持一套 State A/B、Trail A/B、shared Mask 和 Composite;T0/T1 使用两个可复用 GPU Field slot。窗口 A/B -> B/C 通过 generation + fixtureID + dataVersion 识别 B,复用其 texture、只上传 C,保留 simulation/trail;无重叠的新窗口沿用 40-01 的安全 reset/reseed。 - Android Test App 增加 T0 EAST/T1 NORTH、MIX 0/50/100 与 ADVANCE B→C 入口,原 ACTIVE/STATIC、GLOBAL/OCEAN、Camera、wrap/antimeridian 入口保留。 - Linux OpenGL 受影响 Core/source-test object、shader generator、C++ format 和 diff check 已通过;未执行 Android Gradle、ADB 或设备操作。40-02 当前只能标记 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`,T1–T10 手工 Android OpenGL 验收后才能判 PASS。 - 实现提交为 `4675a8a29dd6fc7b684bfb64913a8c9075ad8583`(`feat: add GPU particle time interpolation`);文档收尾提交另行记录,均只面向 40-02。 ## 2026-09-02 — 40-02A Android Validation 测试界面紧凑化(代码阶段) - 仅调整 Android Test App 的 `Particle Core Layer Validation` UI:底部控制区从 7 个默认大按钮行压缩为 4 行,状态行 36dp、控制行 34dp、padding 4dp,MapView 保持全屏并获得更多粒子观察区域。 - EAST/NORTH、T0/T1、ADVANCE、MIX、ACTIVE/STATIC、DISABLE/ENABLE、GLOBAL/OCEAN、DATELINE/WORLD WRAP 的 16 个既有 ID/click binding 均保留;状态改为单行 mask/runtime/field/mix 表达,不改变 40-02 业务语义。 - 未修改 C++ Core、shader、GPU、simulation、trail、composite、mask、Gradle 或 ABI。静态 ID/binding 核对与 diff check 通过;未运行 Android Gradle、ADB 或设备。状态为 `IMPLEMENTED / WAITING FOR ANDROID UI VALIDATION`。 - 实现提交为 `f4d519ca789c0488d6b9d8259427ac070b15eb63`(`ui: compact particle validation controls`);文档收尾提交另行记录。 ## 2026-09-02 — STEP-043 / 40-02C 最终修正 - 修正 north-positive V 到 Mercator Y 的最终 displacement 符号;Field canonical contract 未变。 - MIX 移除 Style reload fallback,未就绪只拒绝并记录日志;GPU reuse 使用已验证 SHA-256 content identity,revision generation 仍独立保留。 - 状态:`IMPLEMENTED / WAITING FOR ANDROID VALIDATION`;未运行 Android Gradle/ADB,T1--T10 待用户验收。 ## 2026-09-03 — STEP-043A 源码审查后最小修正 - texture reuse 现消费 wanted revision;MIX reject 不再改变 timeMix;补充 lifecycle diagnostics 与 Style reason。状态仍为 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`。 ## 2026-09-03 — STEP-043B Android→Core MIX 属性桥接 - 自定义 raster-particle 没有 Android Java Layer peer,`Style.getLayer()` 不能作为 Core layer readiness;新增最小 NativeMapView bridge 走正式 Core `Layer::setProperty`,MIX 仅 bridge 成功后更新状态。 ## 2026-09-03 — 40-02 双时间片 GPU 时间插值 Android 最终验收完成 - STEP-043B 最终使用 `RasterParticleLayer::setTimeMix(float)`;Android x86_64 OpenGL Debug 编译、安装、启动通过,T1--T10 全部 PASS。 - A/B→B/C GPU texture reuse、MIX property-only、DISABLE/ENABLE 生命周期通过;`uniform-north + vortex` 的 MIX 50% 局部低速/近零速是正常逐点插值。 - 单 ABI APK 约 696.5 MiB 是独立 packaging 技术债,不阻塞本阶段。40-02 / 40-02C / STEP-043B 正式 `CLOSED / PASS`。 ## 2026-09-03 — 40-03 Android OpenGL 粒子数量容量基线(代码阶段) - 正式 RasterParticle GPU 链的粒子数实际由 State A/B render target 网格承载:既有 `16x16` 即 256 个 State shader texel。新增 `raster-particle-particle-count` Core 属性与强类型 `RasterParticleLayer::setParticleCount(uint32_t)`,只接受 256..1,048,576 的平方数,确保实际 count 与 State grid 面积一致。 - Android Validation 页面新增 256、1K、4K、16K、64K、1M 档位;使用既有 Android→Core 薄桥,不建立 Java layer peer、CPU simulation 或第二 GPU simulation。切换只重建 State A/B、执行一次可解释的 `PARTICLE_COUNT_CHANGE` reset/reseed,Field T0/T1、MIX、interpolation、GPU content reuse、mask 与既有 lifecycle 均不改变。 - 日志包含请求/实际 count、State grid、State target create/rebuild/release 和拒绝原因;Trail 继续用四个确定性 State texel作低开销可视健康指示,实际并行 simulation 数仍是整个 State 网格。 - Linux OpenGL 受影响 Core 和新增 Layer test object 精确编译、C++ format、diff check 均通过;未运行 Android Gradle、ADB、APK 或设备,也未加入 Jest。 - 当前状态只能是 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`。用户将以 x86_64 Android OpenGL 逐档填写容量矩阵后,才能确定稳定区间、性能下降区间和压力边界。 ## 2026-09-03 — 40-03 Full Particle Draw 补齐(STEP-044 v2) - 暂停 v1 容量验收的根因已补齐:v1 的 State A/B 虽可容纳 N 个 State texel,但 Trail fragment 只读取四个固定 sample,实际 Trail draw 只是全屏 quad,不能证明 N 个粒子已绘制。 - 正式 RasterParticle Trail 现在先保留既有全屏 fade,再在同一 Trail A/B write target 绘制 N 个 point。particle index 在资源创建/count change 时一次性映射到 State texel `(x,y)`;vertex shader 每帧直接从当前 State write texture fetch RG position,Composite 仍消费 Trail write。没有 CPU readback、每帧 CPU position loop、第二 simulation 或 overlay。 - 16-bit index buffer 每 segment 最多 65,536 point;1M 使用多个 segment,但继续走同一 State→Trail→Composite GPU path。日志明确输出 `trailDrawCount`、`particleIndexCount` 与 `fullParticleDraw=true`;legacy validation 的四 sample 诊断保留且不再限制正式层。 - U/V、Mercator `dy=-v`、T0/T1、MIX、Field reuse、seed/lifecycle 和 Android JNI 均未改变。Linux OpenGL 精确 Core/test object 编译、shader generator 二次幂等、format 与 diff check 通过;未运行 Android Gradle、ADB、设备或 Jest。 - 状态继续为 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`,用户下一轮只验收 256、1K、256→1K→256 的 full draw 正确性,之后才恢复完整容量矩阵。 ## 2026-09-03 — 40-03 Android OpenGL 粒子数量容量基线最终关闭(STEP-044 v3) - 40-03 正式 `CLOSED / PASS`。原 `c0d1ad43...` 只扩展 State A/B 容量,Trail/render 未 full draw,故验收曾暂停;`a0aae48...` 完成正式 full particle draw,使 `State N -> draw N -> Trail -> Composite` 成立。 - 用户 Android OpenGL 实机确认:256→draw 256、1K→draw 1024、4K→draw 4096、16K→draw 16384、64K→draw 65536、1M→draw 1048576;所有档位日志均为 `fullParticleDraw=true`,用户确认 1M 运行 OK。T-FULL-01~03(含 256→1K→256 重建回归)全部 PASS。 - count change 仅重建 State/full draw resources,未引入 Field upload、Style reload 或 MIX 改变;40-02 的 MIX property-only 与时间窗 Field reuse(`simulationRebuild=false`、`trailCleared=false`)保持。 - 已验证容量 **≥ 1M**,满足当前项目需求,不再扩展 2M/4M/8M 压测。1M 是本验证设备上的已验证容量,不是理论最大值、硬编码产品默认值或所有 Android 设备的统一保证。 - 本收尾只回填文档;Codex 未运行 Android Gradle、ADB、设备测试或 Jest,也未修改功能代码。 ## 2026-09-03 — 40-04 Runtime Field 动态更新接口(STEP-045) - 正式 Runtime Field 更新入口落在 `RasterArraySource`:`updateRuntimeFieldWindow(ParticleFieldSnapshot)` 把 Source 权威窗口由 `T0/T1` 推进为 `T1/newT1`,并通过既有 Source observer 通知正式 RasterParticle renderer;没有 Style reload、Source/Layer recreate 或第二套 Field/GPU 系统。 - `RasterArraySource::Impl::field/nextField` 继续是唯一正式 T0/T1 权威状态。Android Validation 只通过 `MapLibreMap -> NativeMapView -> JNI -> Style::getSource()` 薄桥请求 advance;Kotlin/JNI 不保存窗口,不操作 renderer 私有资源。 - 离线验证初始 A/B 为 uniform-east/uniform-north;Source 自己预加载 C=vortex、D=nodata。候选在真正进入 T1 时才获得 process-wide runtime generation,避免异步 asset 完成顺序造成 stale/non-monotonic revision。 - 既有 renderer content identity/slot ownership 未改:A/B→B/C 和 B/C→C/D 都复用 OLD_T1 作为 NEW_T0,只上传新 T1,保留 simulation 与 Trail(`simulationRebuild=false`、`trailCleared=false`)。MIX 仍是 property-only,不参与 Field update。 - 重复当前内容明确 NOOP;无效、未加载、不兼容、非单调或无候选更新 fail closed,不污染当前有效窗口。没有每帧 Field copy/hash/upload,也未修改 40-03 full particle draw。 - Linux/OpenGL 受影响 Core/conversion/source test object 精确编译;定向窗口推进 test object 覆盖已加入,完整 `mbgl-test` 因 build tree 缺失大量无关依赖未执行,未将其误报为通过。格式与 diff 检查结果在完成报告收尾记录。未执行 Android Gradle、ADB、APK、实体机或 Jest;当前状态仅为 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`。 - 实现提交:`45502a53f4fc486bd24cb0008d1ab0ff221e7e63`(`feat: add runtime particle field updates`);文档收尾提交另行记录。 ## 2026-09-03 — 40-04 T-RUNTIME-05 Duplicate NOOP 补验收入口 - 已有 Runtime API 的 `sameFieldGpuContent(currentT1, newT1)` NOOP 分支正确,但 Android 只有 ADVANCE(候选耗尽后为 T-RUNTIME-06 reject),无法真实重提当前 T1。 - 新增 Source-owned `repeatRuntimeFieldWindow()` 和最小 Android/JNI 薄桥;`DUPLICATE T1` 只把当前 `Impl::nextField` 重交正式 update API,在 vortex/nodata 窗口返回 NOOP,不推进 candidate queue,不改变 Source window,也不触发 `onSourceChanged()`。 - C++ Source test 在 C/D 后断言 Noop、T0/T1 不变及 source changed count 不增;Linux/OpenGL 精确 Core/test object 编译、format/diff check 通过。Android Gradle、ADB、设备和 Jest 未执行;状态继续 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`。 ## 2026-09-03 — 40-04 / STEP-045 Runtime Field 动态更新最终关闭 - 40-04 / STEP-045 正式 `CLOSED / PASS`。Android OpenGL 最终统一验证 T-RUNTIME-01~06 全部 PASS。 - 正式 Runtime Field 接口已证明支持 A/B→B/C→C/D 连续时间窗推进:OLD_T1 复用为 NEW_T0,只上传真正的新 T1,正常推进不重载 Style、不重建 Layer、不重启 simulation、不清 Trail。 - MIX 保持 property-only;Duplicate 重提当前 T1 返回 NOOP,不产生 Field upload/reset/style reload;候选耗尽 fail-closed,当前 vortex/nodata 窗口继续可用。 - `STYLE_LOAD reason=TIME_WINDOW` 仅是用户建立初始窗口的允许初始化;真正 Runtime 操作期间 styleEpoch 稳定。MIX 的 `LAYER_CHANGED` 不是 Layer recreate,最终 renderLayerInstanceId 保持 1。 - 40-04 未改变 U/V、`dy=-v`、GPU interpolation、40-03 full particle draw 或已验证 capacity ≥ 1,048,576;真实网络/GRIB/provider、视觉阶段、WeatherColorLayer、Vulkan、iOS/Metal、生产 mask、APK 技术债仍属范围外,未进入下一阶段。 ## 2026-09-03 — 40-05 / STEP-046 Android OpenGL 正式粒子视觉与运行时渲染控制(代码阶段) - 正式 `RasterParticleLayer` full draw 从固定 blue point 扩展为短 streak:每个 State texel 对应一颗粒子、两个静态 line endpoint,GPU vertex shader 从 current State write 与 T0/T1 插值 Field 求位置、方向和速度;CPU 不持有 live particle position/direction/color,也不做 readback 或第二 simulation。 - 继续冻结 `U=east-positive`、`V=north-positive` 与 Mercator 边界 `dy=-v`;EAST/NORTH/vortex 的视觉方向与 MIX 后最终速度一致。NoData、NaN 和近零速 fail-closed,不画 streak。 - 新增 `raster-particle-line-width`、`particle-length`、`particle-opacity`、`trail-opacity`、`trail-fade`、`speed-color-enabled` 等 Core Render/Visual properties。它们经现有 Android→Core JNI boolean bridge 运行时更新,只改 Render/UBO,不 reload Style/Source、不上传 Field、不 reset State/Trail。 - GPU fragment shader 使用最终插值 speed magnitude 的最小蓝→绿→橙 ramp;COLOR 控制可以回退固定蓝色。该粒子着色与未实现的 WeatherColorLayer 明确分离。 - Android Validation 页增加 VISUAL DEFAULT、SIZE、LENGTH、OPACITY、TRAIL、FADE、COLOR 集中入口、直接 VORTEX fixture 与 256K 容量档,并保存 Activity 状态;资源日志补充 `particleDrawCount=N`、`streakVertexCount=2N` 和低频 visual property snapshot。 - shader generator 二次幂等、Linux OpenGL Core/style test object 精确编译、format/diff 均通过;未运行 Android Gradle、ADB、真机或 Jest。当前状态只能是 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`;用户下一轮以一次 x86_64 APK 编译完成 T1--T8 综合验收后才可关闭。 ## 2026-09-03 — 40-05 / STEP-046 Android OpenGL 正式粒子视觉与运行时渲染控制最终关闭 - 实施提交 `e48fa087e01e9710c5d0c18ab062726226bbb6bd` 已由用户完成 Android APK 编译、安装和最终手工验证;T1--T8 全部 PASS,40-05 / STEP-046 正式 `CLOSED / PASS`。 - UNIFORM EAST、UNIFORM NORTH、VORTEX 的正式 GPU streak 正常显示;Runtime visual properties、speed color 与 MIX 0/50/100 均正常,MIX 保持 property-only。 - 40-04 Runtime Field Window 连续推进、`OLD_T1 -> NEW_T0` reuse、Duplicate NOOP、fail-closed、无 Style reload / 无无意义 simulation reset / 无 Trail clear 均无回归。 - pan、zoom、bearing、DATELINE、WORLD WRAP、DISABLE/ENABLE、屏幕/生命周期恢复、GLOBAL/OCEAN A/OCEAN B 均通过;Renderer 持续 `State -> Trail -> Composite` 且 `hazard=SAFE`。 - 容量档 256、1K、4K、16K、64K、256K、1M 在新的 streak + speed color 路径均通过。4K 以上在小 Validation viewport 内趋于高密度铺满是可读性现象,不是功能失败;1M 仍只是当前验证设备上的已验证容量,不是全设备保证或产品默认值。 - Android logcat 的 `TimeStats: RenderEngineTimes are already at its maximum size[64]` 是 RenderEngine/虚拟机环境噪声,未伴随粒子 Renderer crash 或中断,不判为本阶段失败。未进入 WeatherColorLayer、真实网络/GRIB、Vulkan、iOS/Metal 或生产 mask 等范围外工作。 ## 2026-09-03 — 40-06 / STEP-047 Runtime Timeline 与 Playback(代码阶段) - `RasterArraySource` 现持有唯一的有界 Timeline runtime:六个离线 immutable snapshot、严格递增逻辑时间、T0/T1、mix、cursor、播放/暂停、0.5x/1x/2x、step、seek、gap/invalid/recover/end。Android 只经薄 JNI 发低频命令,没有 Android timer 或 per-frame JNI。 - RenderRasterParticleLayer 只读取 Source Core 给出的当前 T0/T1/mix;窗口 revision 变化继续进入既有 Field identity/GPU reuse 路径,自动边界维持 `OLD_T1 -> NEW_T0` 的重用语义。正常 timeline MIX 不需要 Style reload。 - Validation UI 收敛为 `TIME | VIS | COUNT | MAP | MORE`;原有动作均由菜单保留,TIME 提供 load/play/pause/speed/step/seek/gap/invalid/recover。 - 已加 Source timeline 单元覆盖并运行 Linux/OpenGL Core 精确构建;未运行 Android Gradle、ADB、实体机或 Jest。状态仍为 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`,等待 Android x86_64 逐项验收。 ## 2026-09-04 — 40-06 / STEP-047 Android Round 1 集中修复 - Round 1 为 `PARTIAL / NEEDS FIX`:主链、自动 MIX/window reuse 和紧凑 UI 通过,但 timeline 过短、END/seek 语义、异常入口、VIS 可达性与 cache 可观测性不足。 - Core validation timeline 改为约 200 秒;END PLAY restart、PLAYING/PAUSED seek 状态保持、GAP/INVALID fail-closed 和 RECOVER 保留此前状态。TIME 直接暴露 NORMAL/GAP/INVALID/RECOVER,VIS 将 COLOR 前置并使用明显的 validation 步长。 - 仍保持 Source 有界 CPU snapshot preload、GPU 仅 T0/T1、相邻窗口 reuse 与 STEP-046 visual property-only。状态为 `IMPLEMENTED / WAITING FOR ANDROID RE-VALIDATION`。 ## 2026-09-04 — 40-06 / STEP-047 Playback Tick 根因修复 - Android Round 2 确认 PLAY/SPEED bridge 成功、RenderThread 持续,但 Timeline 只短暂推进。根因是 tick 错接到非持续的 RenderLayer update。 - tick 已移到每个正式 State drawable frame 的 Core tweaker;没有 Android timer、每帧 JNI、线程或自旋。新增低频 PLAYBACK_TICK heartbeat;状态继续 `IMPLEMENTED / WAITING FOR ANDROID RE-VALIDATION`。 ## 2026-09-04 — 40-06 / STEP-047 Runtime Timeline 与 Playback 最终关闭 - Android 最终验收在 `1343929474796b1313489ee9fecbf23b949580a7` 功能基线上全部 PASS,STEP-047 正式 `CLOSED / PASS`。 - Playback tick、Pause/Resume、0.5x/1x/2x、Seek/Step、Gap/Invalid fail-closed 与 Recover、Preload/Cache、`OLD_T1 → NEW_T0` reuse、仅上传 NEW_T1、无正常 reset/clear trail、VIS/MAP/MORE 与紧凑 UI 均已验证。 - snapshots=6/cacheCapacity=8 下没有 CACHE_EVICT 是正常容量现象。状态栏对自动 MIX/WAITING/INVALID 的展示记录为非阻塞 Validation UI observability 技术债;TimeStats 上限信息为 Android RenderEngine 环境噪音。此次仅文档收尾,未修改功能代码。 ## 2026-09-04 — STEP-049 Provider-neutral C++ Field Data Adapter 与 Runtime 输入契约 - 新增 `ParticleFieldDescriptor`、`ParticleFieldDataAdapter`、structured error result 与 provider-neutral `ParticleFieldSnapshot`;descriptor/payload 边界不携带 provider、URL、token、network 或 Renderer 对象。 - `OfflineFixtureParticleAdapter` 保留 fixture-v1 whitelist、metadata/checksum 校验,但最终调用正式 Data Adapter;EAST/NORTH/VORTEX/NODATA validation fixture 继续工作,fixture identity 改为 neutral `fieldID`。 - `RasterArraySource` 继续复用唯一 `updateRuntimeFieldWindow()`;没有第二套 T0/T1、Timeline、Playback、GPU upload policy 或 Renderer 业务语义。`OLD_T1 → NEW_T0`、NEW_T1-only、Duplicate NOOP、MIX property-only 和 fail-closed 保持。 - Linux OpenGL `mbgl-test-runner` 构建通过,adapter + RasterArray 定向 11 项测试通过,`git diff --check` 通过;未执行 Android Gradle/APK/ADB/设备/Jest。 - 状态:`IMPLEMENTED / WAITING FOR ANDROID VALIDATION`,等待用户一次 Android 综合验收后再 docs-only closeout。 ## 2026-09-04 — STEP-049 Timeline 回归修复 - 根因是 Timeline candidate 在 `tryLoadRuntimeField()` 以 generation=0 进入正式 Field Adapter;adapter 的非零 generation 校验正确拒绝,Runtime Window 因使用已分配 generation 仍正常。 - 修复为 candidate decode 前分配 Core 全局 runtime generation,Timeline 构建不再重复改写;未放宽 contract,未新增 adapter、Timeline 或 Window。 - 新增真实 Source candidate preload → formal adapter → Timeline READY 回归测试,并保留 generation=0/invalid descriptor 负向校验;Linux OpenGL 构建通过,定向测试 12/12 PASS。 - Validation UI 仅明确显示 `TL NOT READY/READY/PLAY/PAUSE/WAIT/INVALID`,与 Window 状态分离;未执行 Android Gradle/APK/ADB/Jest。 - 状态:`IMPLEMENTED / WAITING_ANDROID_REVALIDATION`,等待用户重新构建 APK 并完成一次综合 Timeline 验收。 ## 2026-09-04 — STEP-049 Android 复验与最终关闭 - 用户已在 `e34f04ba7038c5cb8fba8dc72c0d253cc4f7c85b` 基线上完成 Android 综合复验:Timeline READY/PLAY、auto MIX、A/B→B/C→C/D、OLD_T1→NEW_T0 reuse、only NEW_T1 upload、Pause/Resume、Step/Seek、Gap/Recover、Invalid Next/Recover、Duplicate NOOP、Renderer fail-closed 与不黑屏全部 PASS。 - 正常连续播放保持 `simulationRebuild=false`、`trailCleared=false`;Window 内 MIX 不产生 Field upload、simulation reset 或 style reload。 - Validation UI MIX 百分比文本可能滞后,保留为 `NON-BLOCKING observability`,不影响 Core/Playback/Window/Renderer/Adapter 结论。 - 本次为 docs-only 收尾,未执行 Android Gradle/APK/ADB/App/Jest,STEP-049 正式状态更新为 `CLOSED / PASS`。 ## 2026-09-04 — STEP-051 Local Production-like Field Feed 与 Core Snapshot Submit Bridge - Starting HEAD `885e7aebef7fb5d02acaed57f9dcf98b8d9e9ba3`;新增 provider-neutral `maplibre-particle-field/v1` local metadata feed、四个时间片资源与 `LocalParticleFieldFeed`,正式复用 ParticleFieldDataAdapter/Snapshot。 - `RasterArraySource::submitInitialRuntimeFieldWindow(T0,T1)` 建立薄 Core submit bridge;Timeline 使用 producer `validTime`,旧 fixture null timestamp 保留兼容 fallback,Window/Playback/Renderer ownership 未改变。 - 新增 local feed 成功、严格 identity/generation/validTime、Timeline READY/PLAY 与非法 generation 拒绝测试;Linux OpenGL 定向 14/14 PASS。Android/Jest 未执行。 - Android TIME 入口可加载 production-like resources;MIX 文本滞后仍为 NON-BLOCKING observability,Rotation/Viewport 技术债未扩大处理。 - 状态:`IMPLEMENTED / WAITING_ANDROID_VALIDATION`。 ## 2026-09-04 — STEP-053 Windy-style Canonical Field 与 Host Submission - 新增 Host 已持有数据后的低频 ingress:`metadata + contiguous binary UV bytes → RasterArraySource::submitHostField() → LocalParticleFieldFeed → ParticleFieldDataAdapter → ParticleFieldSnapshot`;没有新增第二套 Descriptor、Snapshot、Timeline 或 Runtime Window。 - canonical v1 固定 north-west origin、row-major、north-to-south rows、west-to-east columns、`float32-le interleaved-uv`,其中 U=eastward、V=northward;Field payload 不走巨大 JSON/JS Array。 - 第一个合法 Field 暂存 T0,第二个复用既有 initial T0/T1 bridge 并建立 Core-owned Timeline,后续 Field 只追加到同一个有界 Timeline;Duplicate/Invalid 均 fail-closed,last valid 保持。 - Android `MapLibreMap`/JNI 增加单 Field binary submit;Validation Host 增加 HOST FIELD SUBMIT、HOST DUPLICATE、INVALID HOST,并由 Kotlin 读取本地资源模拟未来 React Native Host。旧 fixture 与 STEP-051 production feed 保留。 - Linux OpenGL `mbgl-test-runner`、`mbgl-render`、`mbgl-render-test-runner` 构建通过;新增 Host/canonical 4/4、Source 44/44、RasterParticle property 2/2 PASS。未执行 Android Gradle/APK/ADB/设备或 Jest。 - Renderer、GPU simulation/trail、Runtime Window、Playback ownership、WeatherColorLayer 分离边界未改。状态:`IMPLEMENTED / WAITING_ANDROID_VALIDATION`;用户正式数据尚未提供,不能提前关闭。 ## 2026-09-04 — STEP-053 Android Validation Host 接线补充 - STEP-053 Host submission API/JNI 和 Host 控件已在 `b31f80c...` 存在;为让手工入口与 STEP-051 `PRODUCTION FEED` 一眼区分,MORE 现显示 `PRODUCTION FEED → HOST FIELD → INVALID PROD → HOST DUPLICATE → HOST INVALID`。 - `HOST FIELD` 继续只读取既有 T0~T3 metadata/binary assets 并逐片调用正式 `MapLibreMap.submitRasterArraySourceHostField()`;新增低频 `HOST_FIELD_DATASET_LOAD` 日志,Native 继续输出带 fieldId/generation/validTime 的 Host submit 事件。 - Host duplicate 与 Host invalid 均重用同一 Host submission contract,不通过 style reload 伪造验证。未修改 Adapter、Timeline、Runtime Window、Renderer、JNI/Core 语义或任何网络/provider 逻辑;状态仍为 `IMPLEMENTED / WAITING_ANDROID_VALIDATION`。 ## 2026-09-04 — STEP-053 Android 技术验收最终收尾 - STEP-053 正式 `CLOSED / PASS`。用户 Android 综合验收确认 `HOST FIELD` 与 STEP-051 `PRODUCTION FEED` 路径分离;canonical `production-wind-t00`~`t03` 真实经过 Host Submission、Adapter、Snapshot、Timeline、Runtime Window 和 GPU Renderer。 - T0/T1 initial、T2/T3 next、PLAY、automatic MIX 和两次 production→production boundary 全部 PASS;两次 boundary 均为 `OLD_T1 → NEW_T0` reuse、only NEW_T1 upload、`simulationRebuild=false`、`trailCleared=false`。 - `fieldUploadCount=4 → 5 → 6` 证明正常 boundary 每次仅上传一个 NEW_T1。唯一 `simulationResetCount=1` 属于旧 fixture 切到 Host dataset 的允许初始化,不是正常 production boundary 回归。 - `HOST DUPLICATE` 返回 `DUPLICATE_NOOP` 且 upload/reset 不增长;`HOST INVALID` 经 Adapter reject fail-closed,last valid field 与 Renderer continuity(`stateSeed=CONTINUE`)保持,无黑屏、无 crash。 - 用户正式风场数据集仍未提供、未验证,但不阻塞 contract 阶段关闭;后续可在同一 canonical contract 下追加。MIX 文本滞后及 WAITING/INVALID 视觉为 `NON-BLOCKING observability`,本次未修改功能代码或执行 Android/Jest。 ## 2026-09-04 — STEP-054 真实 WeatherV2 风数据 Canonical 测试 asset - 只读核对 WeatherV2 `bin_export.py`、`decode_wind()`、QBIN/NSFT export 后,确认 `wind_vectors.bin` 为完整拼接 `WVECBIN1` grid:row-major U/V/speed float32-le planes + valid uint8 plane,U=eastward、V=northward,单位 m/s;QBIN/NSFT 均由同一 decoded U/V Field 生成。 - 从 run `2026080600` 生成真实 ECMWF HRES `2026080700/06/12/18` 四帧。原始日本及周边 bounds 为 112.5/0.0/157.5/55.776573,`513×769`,不裁剪、不重采样;输出 canonical interleaved U/V Android assets,每帧 3,155,976 bytes。 - 转换器独立放在 `tools/weatherv2_wind_canonical/`,保留 valid/noData:invalid 写既有 -9999 sentinel,不伪造为 0 风;四帧 hash 不同,重复 T0 hash 相同,source→canonical 抽样误差 0。未改 Core/Renderer/Android,也未执行 Android/Jest;等待下一阶段集中 Android 集成验收。 # STEP-055 — Android 真实 WeatherV2 风场色场/粒子综合可视化(IMPLEMENTED / WAITING_ANDROID_VALIDATION) - 复用 STEP-054 的真实 ECMWF HRES WeatherV2 canonical T0–T3(513×769、原始 validTime、U eastward/V northward、m/s),未重生成或重采样。 - 新增独立 `weather-color` 层:同一 canonical T0/T1 的 U/V 先插值再计算风速,固定 0–30 m/s 色标;与 RasterParticleLayer 保持分离。 - `MORE → REAL WEATHER` 通过既有 Host Submission Contract 一键提交真实字段,使用 OSM 无 Key 底图、自动 fit metadata bounds,并恢复旋转/Activity 重建后的可见内容。 - Android 综合验收待用户手工完成;详见 STEP-055 人工验收指令。 ## 2026-09-05 — STEP-055 首轮 Android 视觉修复(IMPLEMENTED / WAITING_ANDROID_VALIDATION) - 首轮实机已证实真实 WeatherV2 T0–T3、513×769 canonical Field、Host submit 和 WeatherColorLayer 可用;本轮将 REAL WEATHER 底图从 OSM 切到 GSI,并把入口提升为 `TIME | VIS | COUNT | MAP | REAL WEATHER | MORE` 的一级菜单。 - REAL WEATHER 首次加载采用 P=2048、W=.75、L=.0040、O=.75、T=.55、F=.88,并提供同状态 HUD、低频 `PARTICLE TUNING` 调整与 RESET;不重载 Style/Field/Timeline,只有容量调整会重建粒子 State/draw resources。 - 将原无单位 `velocity * 0.00004` 位移替换为 canonical m/s 到 Web Mercator world 的 Earth-circumference/cos(latitude) 换算;6000 simulation-seconds/real-second 是独立的 validation visual clock,不污染 U/V、validTime 或 Timeline。新增低频 `ParticleMotion` CPU 估算日志,未做 GPU readback。 - Linux OpenGL 受影响 Core/style test translation unit 精确编译与 shader generator 通过;Android Gradle/APK/ADB/Jest 未执行。等待用户按人工验收 v2 做一次综合复验。 ## 2026-09-05 — STEP-055 Particle State Float 精度修复(IMPLEMENTED / WAITING_ANDROID_VALIDATION) - Android 日志已将“真实 U/V、非零 world displacement、State A/B ping-pong 均存在但粒子静止”收敛为 RGBA8 State 量化:单步 `3e-6–8e-6 world` 小于 UByte `1/255` 的可表示间隔。 - State A/B 现在为 Float,Trail A/B 保持 UnsignedByte;初次创建、context recreation 与 particleCount replacement 均通过同一 Float target 路径,FBO 创建失败明确 fail-closed,不静默降级。 - 现有 OpenGL `Float → RGBA32F/GL_FLOAT → FBO check` 支持直接复用,未改 backend、canonical/Timeline/Window/WeatherColorLayer 或 visualSpeedScale=6000。下一次 Android 的首要检查是 Timeline Pause 下真实固定场粒子是否持续移动,并核对 `ParticleStateTarget` 类型日志。 ## STEP-055 Float State fail-closed 小修复 在 Particle Validation `createValidationTarget()` 增加局部标准异常与未知异常捕获。Float State RenderTarget/FBO 创建失败会记录结构化错误并返回空 target,不会向上抛出或降级到 UnsignedByte;State A/B=Float、Trail A/B=UnsignedByte 保持。Linux 精确编译通过,仍待 Android 验收。 ## STEP-055 生命周期、真实轨迹与 view-space Trail 修复 真实 Weather 路径改为 GPU age/哈希 respawn,StateRead→StateWrite 真实位移 segment,且 Trail 仅在当前 camera view 内累积。相机变化只重建 Trail;`trailFade` 改为 wall-time 指数衰减。visual clock 调整为 1200 simulation seconds/real second。canonical、Timeline、Runtime、WeatherColorLayer 未改,仍待 Android 综合验收。 ## STEP-055 生命周期错峰小修复 粒子基础生命周期调整为 14400 simulation seconds(12 real seconds),首次 seed 与 maxAge 都由稳定 hash 错峰,消除同步生命周期到期。日志改用 configuredSlots 并说明无 GPU readback;其他粒子视觉与数据链语义未改。 ## STEP-055 低缩放可见性与 Trail 稳定性修复 Particle visual clock 改为基于 zoom 的有界 scale 与 2400s/frame clamp;State lifecycle 改为 12s base 的 wall-time hash jitter。普通 camera 交互只 invalidate 一次并在稳定后恢复 Trail,只有 resize 重分配 Trail texture。canonical 与 Core 时间线边界未改,待 Android 验收。 ## STEP-055 Zoom 下 Viewport 粒子密度调整 configured particleCount 保持不变;稳定相机后,State respawn 域改为“viewport 四角 Mercator AABB + 15% margin”与 canonical Field bounds 的交集。camera moving 期间继续从 full Field respawn,稳定至少 150ms 后才让 viewport 外 slot 回收进入该域;无效/空/过小交集安全回退 full Field。新增独立 respawnBounds UBO,不改变 Field sampling 边界、Timeline、Runtime、WeatherColorLayer 或 canonical U/V,仍待 Android 验收。 ## STEP-055 v9 Android C++ 编译遗漏修复 WeatherColorLayer 的 `ParticleGpuValidationUBO` designated initializer 补齐 `respawnBounds`,并使用与 `fieldBounds` 相同的中性范围;仅修复 Android `-Wmissing-designated-field-initializers` 编译失败。已搜索确认两个 C++ initializer 均完整,未改粒子 respawn、色场行为或冻结数据/时间线边界,仍待 Android 验收。 ## 2026-09-05 — STEP-056 React Native 天气渲染桥接现状调查 - 仓库当前没有 React Native/TurboModule/Fabric/JSI binding;可复用正式入口是 Android `byte[] → JNI → RasterArraySource::submitHostField()`,它已接入 canonical Adapter/Snapshot、Core Timeline/Window 与两个 GPU layer。 - 推荐先建立 Android Host Weather Runtime typed facade:runtime unload/clear、canonical field submit、timestamp playback、visibility/style 和低频 result/event;RN module 应在具备 RN host/build dependency 的后续任务中薄包裹该 facade。 - 单帧 WeatherV2 payload 为 3,155,976 bytes;RN v1 应先稳定复用 byte[] path,zero-copy/direct ByteBuffer 仅在 profiling 后处理。动态 WeatherColor stops、独立 particle/trail color 和 weather-local targetFps 均是当前缺口;后者应独立性能批次,不能使用全图 `MapView#setMaximumFps()` 冒充。 ## 2026-09-07 — STEP-057 Android Host 天气运行时接口基础 - 新增主线程 `WeatherRuntime` typed facade,封装 canonical submit、typed result/state、clear、OFF unload、timestamp seek、play/pause/0.5/1/2x、独立 visibility 和 visual API;未来 RN 只需包裹该 facade。 - clear 后 Source 保持可复用但无 field;Render 线程空场路径释放 Particle State/Trail/draw、field texture 与 WeatherColor resources。OFF 不 reload style,ON 后要求重新 submit T0/T1。 - WeatherColor 支持最多 8 个 validated dynamic stops;particleColor/trailColor 独立 UBO 数据通路,不依赖 WeatherColor ramp。正常 time seek 和 visual/ramp/color 更新均不重新提交 field 或 reset simulation。 - Linux shader generator、OpenGL Core 及相关 Source/Style test translation unit 已验证;Android Gradle/APK/ADB/设备/Jest 留待后续人工验收。 ## 2026-09-07 — STEP-057A 审计修正 - `WeatherRuntime` 正式 Host API 改为明确 typed 粒子外观方法,删除 public string property setter;Test App 的通用 fixture 调试仍为低层路径。 - enable/clear/disable/submit 状态转换已幂等并可恢复,另增加既有 Android JUnit state transition 测试源码;未运行 Gradle。 - hidden unload 改成 RasterParticle/WeatherColor renderer 的 Host-empty-source 显式 opt-in cleanup,移除对所有 hidden RasterArray layer 的全局 prepare/update。 - timestamp 测试改用真实 epoch milliseconds,覆盖 T0、midpoint、T1、上下边界和 clear 后拒绝;WeatherColor capacity 由 Java 通过 JNI 读取 C++ `MaxWeatherColorStops`。 ## 2026-09-07 — STEP-057B WeatherRuntime 状态语义修正 - 普通 field rejection 与 facade/runtime failure 分离:Core 保留有效 timeline 时,READY/WAITING 状态不被坏提交改成 ERROR;空 metadata/payload 同样只拒绝本次提交。 - `REJECTED_SOURCE_MODE`/`UNKNOWN` 才进入 ERROR;ERROR + enable(true) 返回 REJECTED 并保持 ERROR;READY/WAITING enable 保持幂等,DISABLED enable 成功后等待新 fields。 - 扩展 `WeatherRuntimeStateTest`,覆盖 static state transition 与 Mockito public control flow;未执行 Android Gradle、设备测试或 Jest。 ## 2026-09-07 — STEP-057C Android JNI 数组读取编译修正 - Android x86_64 CMake 编译发现 `jni::Array` 误用底层 5 参数 `jni::GetArrayRegion`,导致 `native_map_view.cpp` 四处编译失败。 - 已改为 `jni::Array::GetRegion()`,只修正 particle/trail 与 WeatherColor stops 的数组读取,不改变业务语义或渲染生命周期。 - 功能提交:`4f76245533817751f4e24f76e47e856c35fb23c7`;Android Gradle/设备验证由用户重新执行。 ## 2026-09-07 — STEP-057D WeatherRuntime 接口收尾与 RN 桥接前冻结 - `WeatherRuntime` 新增独立 typed `setParticleColor()` / `setTrailColor()`,分别委托 Core 独立颜色 setter;保留原 `setParticleColors()` 作为兼容成对提交 helper,不猜测或复制 Core 默认色值。 - REAL WEATHER submit 使用 `FieldSubmitResult`/`accepted()` 与 enum 日志,不再依赖 `getCode()`;REAL WEATHER 的 playback/visual 不再回退到 MapLibreMap 低层入口,旧 fixture/diagnostic 路径继续保留。 - 本轮仅执行 `git diff --check` 与源码静态审计;未执行 Android Gradle、APK、ADB、设备测试或 Jest,状态为 `IMPLEMENTED / READY_ANDROID_COMPILE_CHECK`。 ## 2026-09-07 — STEP-058 Weather-local Target FPS 与 Repaint Gate - 新增 source-owned `RasterArrayTargetFps`(AUTO/30/60)与单一 `RasterArrayTimelineRuntime` cadence authority;Particle/WeatherColor 共用 monotonic deadline,真实 wall-time simulation、Timeline、T0/T1 window reuse 保持不变。 - Android `WeatherRuntime.setTargetFps()` 通过 typed MapLibreMap/JNI source setter 接线;使用已有 `triggerRepaint()` 做目标间隔 delayed wake-up,不使用全局 `MapView#setMaximumFps()`,REAL WEATHER popup 提供 FPS AUTO/30/60 与 HUD。 - 未到 deadline 的 camera frame 不推进天气 State/Trail/Timeline;两层 visibility、PLAY/PAUSE、clear/disabled 组合按 shared cadence 规则处理。Linux/OpenGL 增量构建与 deterministic/source 定向测试通过,Android Gradle/设备/Jest 未执行。 ## 2026-09-07 — STEP-058A Shared Cadence 与 WeatherRuntime 生命周期修正 - `advanceIfDue()` 将 shared deadline claim、cadence revision、真实 wall-time MIX 推进合为 Source-owned 原子操作;WeatherColor-only PLAY 能推进 timeline,Particle 后到同一 deadline 不重复推进 State/Trail/Timeline。 - WeatherColor-only PAUSE 不维持连续 repaint;Particle PAUSE 仍可独立按 cadence 运动。`WeatherRuntime.dispose()` 幂等取消 Handler wake,Test App 在 style reload、leave REAL WEATHER、Activity destroy 显式释放旧 facade。 ## 2026-09-07 — STEP-057D 审计后小修正 - 独立代码审计发现 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 未执行。 # 2026-09-07 — STEP-060A RN Test Host 编译前修正 - 按 RN 0.85.2 当前 Codegen 模板为 TurboModule 的 20 个必选 Kotlin Spec 方法补齐 `override`,消除首次 Android 编译的确定 blocker。 - Test Host package manager 统一为 npm/package-lock;实际 `npm ci --ignore-scripts` 不需 legacy peer deps。文档将 Android toolchain 数值改为首次 prebuild 前的验收目标,待生成工程实测。 # 2026-09-07 — STEP-060B Gate C 封存环境与 Custom AAR 接入修正 - Gate C 继续只表示 MapLibre Native custom AAR 的封存 Linux 编译环境;STEP-060 Maven Local 继续是 RN Test Host handoff,不因 Expo 生成工程的 Gradle/AGP/NDK 数字反向修改 Gate C。 - publication 源码确认 custom OpenGL 坐标 `org.maplibre.gl:android-sdk-opengl:13.4.1` 与精确 Maven Local task `publishOpenglreleasePublicationToMavenLocal`。plugin 将 Central 排除收敛到该唯一 custom module,确保 AAR 缺失 fail-closed,且不阻断 MLRN turf/plugins 辅助依赖。 # 2026-09-07 — STEP-060C Maven Local 签名隔离修正 - Vanniktech `signAllPublications()` 仍负责建立 Maven Central 的 publication 签名;其默认 release required 条件覆盖 Maven Local,导致无 signatory 时 Local handoff 失败。 - publication build logic 现将 Gradle `SigningExtension.required` 延迟绑定到 task graph:存在 `*PublicationToMavenCentralRepository` 时必须签名;精确 Maven Local publication 则跳过 Sign task,不需要 PGP secrets、`-x sign`、SNAPSHOT 或第二仓库。 - 实现阶段曾核对中间 AAR SHA-256 `47646fb708d096cf5ee0c3b8eeaeb7e6083081279c79f4a642db554efe88fad7`,当时未重建、未执行 Gradle publish;该 SHA 与等待状态已在随后的人工 publication 验收中被最终 artifact 结果取代。 # 2026-09-07 — STEP-060C 人工 Maven Local 验收收尾 - 用户在 Gate C 实际运行精确 Maven Local publication task:`signOpenglreleasePublication SKIPPED`,`publishOpenglreleasePublicationToMavenLocal` 成功,`BUILD SUCCESSFUL in 3m 33s`,不再有 `no configured signatory`。 - 最终 Maven Local AAR、当前 build output AAR SHA-256 一致,均为 `2e73e25cfd31bb181f75ba2d84974afb949640f72de46bc0234d4579abe3ba38`;POM/module 坐标正确,AAR 含 WeatherRuntime/MapLibreMap 和四 ABI,Local 无 `.asc` 符合设计。此前 `47646fb…` 是 publication 前中间 SHA,已失效。 - STEP-060C 状态关闭为 `CLOSED / PASS`,范围仅 Maven Local signing isolation 与 publication handoff;RN Test Host Android compile、Phase A/B、lifecycle、Binary Field 与 STEP-061 仍未验证。 # 2026-09-08 — STEP-060D WeatherRuntimeBridge attach 精确诊断 - attach 现独立报告 `rn-weather-fields`、`rn-weather-color`、`rn-weather-particles` 状态;`WEATHER_OBJECTS_NOT_READY` 包含 reactTag、MapView/MapLibreMap/Style 状态、三个 ID 的 present/missing、Style source/layer count 和 weather-first 的有界 ID 摘要。 - Linux 生成并发布唯一诊断 AAR:`org.maplibre.gl:android-sdk-opengl:13.4.1-step060d`,build output 与 Maven Local AAR SHA-256 均为 `7391440f02e976f295caa265bc15e895a7c0183883a0e2cb08deef4cf42b0096`,含四 ABI。 - 当前 Expo 生成工程缺失 `NativeWeatherRuntimeBridgeSpec`,标准 codegen task 为 SKIPPED,故 bridge Kotlin compile 不能独立验证;未改生成工程绕过。后续由 CARBON7i 用此唯一 AAR 收集 Android attach 诊断,仍不进入 STEP-061。 # 2026-09-08 — STEP-060E CoreOnly Layer 存在性检查修复 - 根因确认:WeatherColorLayer 与 RasterParticleLayer 属于 CoreOnly layer,Core 能渲染但没有 Java Layer peer;故 STEP-060D bridge 用 Style.getLayer() 会对真实 layer 产生假阴性。 - 新增 MapLibreMap.hasStyleSource/hasStyleLayer,经 Android JNI 直接查询 Core Style;bridge attach 三项 weather object 判断统一使用该真值,保留既有成功路径与 WeatherRuntime 生命周期,不增 Java peer、重试或私有 registry。 - WEATHER_OBJECTS_NOT_READY 改用 styleUri(JSON style 为 )并移除不可靠的 Java layer/source 枚举;临时 Maven version 升为 13.4.1-step060e。 - 本轮不构建 AAR、不发布 Maven Local,APK/ADB/设备验收待人工构建该版本后进行;仍属于 STEP-060,未进入 STEP-061。 # 2026-09-08 — STEP-060F WeatherColor Opacity 与 Android 收尾修复 - Android 已实测 attach PASS,`WEATHER_OBJECTS_NOT_READY` 已由 STEP-060E CoreOnly 真值链解决;无 Binary Field 的 `TIMELINE_NOT_READY` 仍是预期 fail-closed 行为。 - 修正 WeatherColor opacity 错走 particle-only setter:新增独立 Java/JNI/Core typed 路径,直达 `WeatherColorLayer::setOpacity()`,不扩大 RasterParticle whitelist 或新增 Java Layer peer。 - Test Host 将 `8091 -> 8091` 与 Android debug probe 所需 `8081 -> 8091` 固化到 Git 受控启动脚本,保留 `app.json` landscape;临时坐标升为 `13.4.1-step060f`。 - 状态为 `IMPLEMENTED / WAITING_ANDROID_VALIDATION`;AAR/APK/ADB/设备最终复验等待用户,本轮未进入 STEP-061。 # 2026-09-08 — STEP-060F Android 最终验收通过 - `13.4.1-step060f` OpenGL AAR 以 `JOBS=1` 构建并发布成功;Linux build output、Maven Local 与 CARBON7i 下载 AAR SHA-256 均为 `53dfcd43f3479ae43a3c0fd91c10ccbfec7cf1c84ae22ae3435c94393806da6d`。 - Bridge 与 MLRN 两条 `dependencyInsight` 均解析到 `13.4.1-step060f`;Test Host APK `assembleDebug` 通过。 - Android 实测横屏、双 Metro reverse、`WeatherRuntime attached` 均通过;完整验证 UI 的 `weather opacity` 返回 `ACCEPTED`。 - 当前 App PID 日志无 `WEATHER_OBJECTS_NOT_READY`、`UNSUPPORTED_PROPERTY`、FATAL/JNI/SIGSEGV hard-gate 错误;无 Binary Field 时 `TIMELINE_NOT_READY` 继续按预期 fail-closed。 - STEP-060 正式 `CLOSED / PASS`;后续可进入 STEP-061 Binary U/V Field Transport。 # 2026-09-08 — STEP-061 Binary U/V Field Transport(IMPLEMENTED / WAITING_RDC_REVIEW) - RN Test Host 固定以 Expo FileSystem `File.write(Uint8Array)` 写 raw canonical `float32-le/interleaved-uv` U/V bytes,并经 TurboModule 的 `metadataJson + payloadFileUri` 交给 Kotlin;没有 number-array、payload JSON、base64 或 hex transport。 - Bridge 限制本地 `file://`/绝对路径、可读非空和 64 MiB payload,再调用既有 `WeatherRuntime.submitWindField(metadataJson, byte[])`;Core Adapter/Timeline/Runtime Window 未修改,仍是唯一验证与状态所有者。 - UI 提供 invalid byteLength probe(预期 `REJECTED_ADAPTER`)、T0(预期 `ACCEPTED_PENDING_INITIAL_WINDOW`)、T1(预期 `INITIAL_WINDOW_READY`)及 Native READY state evidence;JS 不管理 T0/T1/MIX runtime state。 - `npm run typecheck`、RN 0.85.2 Codegen(仅 `/tmp` 生成)和 `git diff --check` 已通过;未执行 AAR/Windows/APK/ADB/设备/Jest,等待 RDC 审查真实 diff。 # 2026-09-09 — STEP-061 RDC NEEDS FIX 修正(IMPLEMENTED / WAITING_RDC_REVIEW) - Binary UI 改为初始/提交时 PENDING,仅在 invalid/T0/T1/Native state 严格为 `REJECTED_ADAPTER`、`ACCEPTED_PENDING_INITIAL_WINDOW`、`INITIAL_WINDOW_READY`、`READY` 后显示 READY;任一不符 fail-closed 显示 ERROR。 - Runtime 文案严格分离 Core evidence(`INITIAL_WINDOW_READY + runtime READY`)和 producer identity;MIX 为 Core-owned/not exposed,Android 最终 T0/T1 仍由既有 HOST_FIELD logcat 事件验证。 - Kotlin 显式捕获 IOException、拒绝无 scheme 相对路径,metadata 上限按 UTF-8 bytes 计算。AAR 坐标已准备为唯一 `13.4.1-step061`,不覆盖冻结 step060f;本轮按限制未 build/publish,待 RDC 后续指令。 - 本轮 `npm run typecheck`、RN Codegen(仅 `/tmp`)、plugin `node --check`、禁止 transport 审计与 `git diff --check` 均通过;继续停在 Codex prompt 等待 RDC。 # 2026-09-09 — STEP-061 Binary U/V Field Transport Android 最终关闭 - Source commit `4467adcce02db7f1bbbea1f4a829023c53085e39` 的 RN binary file-reference transport 已完成 Android OpenGL 端到端验收,STEP-061 正式 `CLOSED / PASS`。 - AAR `org.maplibre.gl:android-sdk-opengl:13.4.1-step061` 以 `JOBS=1` 构建;Linux build output 与 Maven Local SHA-256 均为 `40ec19724cbe0807c09c6acf9b7e6e0dac2f2498f1269b6bacdd35740a6cd77a`,CARBON7i 下载与 Win11 Maven Local 同 SHA。 - Bridge 与 MLRN dependencyInsight 均唯一解析到 `13.4.1-step061`;Win11 Test Host `assembleDebug` 为 `BUILD SUCCESSFUL in 1m 50s`。 - Android `192.168.1.146` 实测:Invalid=`REJECTED_ADAPTER`,T0=`ACCEPTED_PENDING_INITIAL_WINDOW`,T1=`INITIAL_WINDOW_READY`,GETSTATE 后 runtime=`READY / PAUSE / AUTO`;Binary Transport=`READY: FILE_REF / FLOAT32_LE / INTERLEAVED_UV`。 - 当前 App PID hard gate 中 FATAL/SIGSEGV/WEATHER_OBJECTS_NOT_READY/JNI DETECTED/UnsatisfiedLinkError/NoSuchMethodError 均为 0;非法 payload 的 `PAYLOAD_SIZE_MISMATCH` Warning 可见并保持 fail-closed。 - Release AAR 的 `HOST_FIELD_SNAPSHOT_READY` / `HOST_FIELD_INITIAL_WINDOW_READY` INFO 日志本轮未在设备 logcat 观察到,已如实记录为 observability 限制;未伪造日志证据,正向以 direct Core result + Native READY 为权威。 - 未进入 NavSea,未引入 provider/network/vendor 逻辑,未使用 number[]/payload JSON/base64/hex,未加入或运行 Jest;`/mnt/nas/pbf` 临时制品已清理,baseline UI 与 Git 当前 App.tsx 保持一致。 # 2026-09-09 — STEP-062 RN Test Host 真实 WeatherV2 底图粒子综合验证(IMPLEMENTED / WAITING_ANDROID_VALIDATION) - Test Host 固定 `13.4.1-step061` AAR,不改 Native/Core/JNI/WeatherRuntime,不 build/publish AAR,不进入 NavSea。 - style 升级为 `background → GSI raster → WeatherColorLayer → RasterParticleLayer`,GSI 使用 Android Validation 已验证 URL、256/maxzoom18/attribution;Camera 初始聚焦日本及周边。 - Android Validation 的 ECMWF HRES 20260807 canonical T0–T3 assets 已原样放入 Host assets,四帧各 3,155,976 bytes 且逐文件 SHA-256 一致。 - `expo-asset` 以静态 `.f32` require + `downloadAsync()` 输出 cache `file://` URI;只把 metadata string 与 local file reference 交给既有 STEP-061 bridge,绝不 materialize payload 为 array/JSON/base64/hex。 - `LOAD REAL WEATHER T0-T3` clear 后严格断言 Pending、InitialWindowReady、NextSnapshot、NextSnapshot 和 Native READY;控制页提供 timestamp seek、playback/speed/FPS、独立 visibility/stops/colors 与视觉参数。静态 typecheck/Metro/asset hash 通过;RDC 追加 Android Expo export 也已确认四个 `.f32` 正常打包,功能提交 `a91e3601f37f3adfe5d8b7b6a6c3f7f04fcadb8f` 已 push;Android APK/实机待 CARBON7i 一次综合验收。 # 2026-09-09 — STEP-062 Android APK-only 最终关闭 - 用户已在 Win11 Test Host 手工完成依赖安装、typecheck、APK 编译/安装和实体机综合验收;Metro 确认 `.f32=true`,Test Host 始终使用冻结 `org.maplibre.gl:android-sdk-opengl:13.4.1-step061`。 - GSI 日本标准底图、真实 WeatherV2 T0–T3、binary file ingress、既有 Native/Core 正式入口、WeatherColor、GPU 粒子、地图拖动/缩放/旋转联动、双层独立显示、视觉参数、四时次切换及其他可操作交互均经用户确认 OK;LOAD 后整体评价为“非常完美”。 - Timeline/Playback 可操作且未见明确异常;因四帧间隔 6 小时,短时自动播放视觉变化不明显。用户接受当前表现,不追加专用 Timeline 可观测性 UI,不构成关闭阻塞。 - 最终用户验收未额外执行完整 PID logcat 硬门槛扫描,未声称 logcat 0 error。未改功能代码/Native/Core/JNI/WeatherRuntime,未 build/publish AAR,未接入 NavSea,未执行 Gradle/APK/ADB/Jest;STEP-062 正式 `CLOSED / PASS`。 # 2026-09-09 — STEP-063 Android v1 发布工程化(IMPLEMENTED / WAITING_MANUAL_RELEASE_VALIDATION) - 实际 upstream Android 基线确认是 MapLibre Native `13.4.1` / core `18545ca` / OpenGL;建立 `13.4.1-particle.1` release manifest、`@navsea/maplibre-particle-rn` 与 `cc.navsea.maplibre:android-sdk-particle-opengl` 正式契约。 - Android publication 配置、正式 bridge/package 和 Gradle substitution 统一到 NavSea AAR,MLRN 保持唯一 native module;Consumer Host 只依赖正式 npm package,不引用源码路径、Native tree 或 bridge source。 - `npm pack` 与 package TypeScript/static audit 完成;未执行 Android Gradle/AAR/APK/ADB/Jest,未决定 registry,未创建 release tag。下一步为用户手工 AAR publication 与 tarball Consumer APK/实体机验证。 # 2026-09-10 — STEP-064 RN 纯 Field Renderer 接口 V2(IMPLEMENTED / WAITING_CONSUMER_VALIDATION) - `@navsea/maplibre-particle-rn` 升为 `13.4.1-particle.2`,根入口只提供 `FieldRuntime`、纯类型与 field style fragment;旧 Weather/Wind 公共 API、MLRN facade re-export 与兼容 wrapper 均删除。 - 包内 WeatherV2 HTTP、manifest、time index、decoder 与 loader 已移出,Consumer Test Host 保留自身的真实 fixture/file URI 业务链,并直接从官方 MLRN 导入 Map/Camera。 - `FieldColorStop.value` 在 RN 薄层转换为冻结 Native ABI;无 Native module 时 import 安全,实际调用明确失败。图场与粒子继续共享一次 canonical Field 提交,显示可独立控制。 - Native/Core/JNI/shader/Android AAR 未改,artifact 继续 `cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.1`;Android Gradle/AAR/APK/ADB/Jest/NavSea 均未执行。package 与 Consumer TypeScript 检查已通过,发布 tarball 的实际 Consumer 验证待后续完成。 ## 2026-09-10 — STEP-064 Consumer 验证通过 / Release Freeze 前 - `.2` Consumer 首轮发现 RN style helper 的 `raster-particle-opacity` 非 Native `.1` 支持属性,导致 particle layer 缺失;RN-only 修正为 `raster-particle-active`。 - 固定 Consumer 复用既有 Native `.1` APK,通过 Metro 加载 `.2`:FieldRuntime attach、真实 T0–T3、Runtime READY、Field/Particle 独立开关与恢复全部通过。 - hard gate 未见 WEATHER_OBJECTS_NOT_READY、FATAL、SIGSEGV、JNI/链接错误;未重建 Android AAR/APK。 - 当前进入 `maplibre-particle/rn/13.4.1-particle.2` Release Freeze/Tag。 ## 2026-09-10 — STEP-064 正式发布 / 冻结 - `@navsea/maplibre-particle-rn@13.4.1-particle.2` 已正式发布;release source `e43b58707cfd0f87965424477ed3f95625b3f724`,tag `maplibre-particle/rn/13.4.1-particle.2` 已 push。 - 正式 HTTPS tgz 为 10,660 bytes,SHA256 `ace9e0401824839d18a93cc4201c1f5d4cccbff0636570cfde82fd80b60779b5`,NAS 与公网下载字节一致。 - Win11 Consumer 已从正式 HTTPS URL 安装并通过 TypeScript/依赖树检查;此前 Android Consumer 已通过 FieldRuntime、T0–T3、Runtime READY 与 Field/Particle 独立开关。 - Native AAR 继续使用 `13.4.1-particle.1`;STEP-064 冻结,后续 RN 修改从 `.3` 开始。 # 2026-09-10 — STEP-065 V3 通用 Scalar / Vector Field 架构冻结 - 只读核对当前 v1 Core/RasterArray Timeline/两 renderer/GLSL、Android/JNI/RN binary ingress,以及 WeatherV2 NSFT Wind/Tide/Rain/Wave;未修改生产代码、WeatherV2 或 NavSea,未执行 Gradle/APK/ADB/Jest。 - V3.0 冻结为 `maplibre-particle-field/v2`:一个 Snapshot 最多一个 scalar plane、一个 interleaved U/V vector plane 和一个 shared validity plane;scalar-only、vector-only、scalar+vector 合法,neither fail-closed。 - Renderer policy 与数据分离:Field 明确选择 `SCALAR` 或 `VECTOR_MAGNITUDE`,Particle 明确选择 `VELOCITY` 或 `DIRECTION`;Wave direction 是归一化方向,插值近零/反向时 fail-closed,推进 scale 独立于业务数据。 - 保留 v1 作为最薄 ingress normalize,运行时只保留一套 V3 Timeline/GPU bundle;保护 T0/T1/MIX、pause、OLD_T1→NEW_T0 bundle reuse、only NEW_T1 upload、normal rollover 不重建 simulation/clear trail。 - 下一步为 V3-02 Core Contract + Scalar Snapshot/Adapter;先完成 Linux/Core fixture 与 compatibility,再统一进入 GPU、Android/JNI/RN 与一次 Android 综合验收。 # 2026-09-10 — STEP-066 V3-02 Core Contract 与 Scalar Snapshot Adapter - Core snapshot 现为 optional scalar、optional interleaved U/V vector 与 shared validity;v2 vector-only、scalar-only、scalar+vector 均由独立 plane bundle 解码,neither 和尺寸/semantic/finite/validity 错误 fail-closed。 - 旧 v1 单 payload 未扩展:adapter 从 U/V noData 派生 shared validity,并归一为 `VELOCITY` vector snapshot;Core 不再以 `WIND/GLOBAL` 判断 capability 或 compatibility。 - Timeline T0/T1/MIX/pause/rollover ownership 未改;compatibility 收紧为 grid/bounds、channel presence 与 vector semantics;content identity 覆盖 scalar/vector/validity 的逐值变化。 - 既有 GPU renderer 尚不消费 scalar:本轮只让 scalar-only 不可用,未改 shader 或渲染计算。Linux OpenGL Core/source test 精确编译和 `Source.ParticleFieldV3*` 过滤测试通过;未运行 Gradle/AAR/APK/ADB/Jest。 # 2026-09-10 — STEP-067 V3-03 Scalar GPU 与 Generic Field Renderer - WeatherColor 现以显式 `FieldValueSource::Scalar|VectorMagnitude` 决定使用 canonical scalar 或 U/V magnitude;默认仍是 `VectorMagnitude`,保持现有 Wind 色场。两个时间片均按 selected channel + shared validity fail-closed,scalar 在 GPU 作 T0/T1 数值插值后走同一 generic color ramp。 - `WeatherColorStop` 的 C++ 字段从 `speedMps` 收敛为 generic `value`;shader/UBO/log 不再声称固定 m/s。切换 value source 会重新编码资源,正常 OLD_T1→NEW_T0 rollover 仍复用同一 decoded bundle。 - RasterParticleLayer 继续只接受 `Velocity` U/V;scalar-only 或 `Direction` 立即不可绘制并释放粒子资源,未实现 DIRECTION advection。 - shader generator、受影响 C++ 对象和 Core/layer 过滤测试均通过;全量 OpenGL `mbgl-test` 链接受当前单次终端时限限制未完成,未虚报 PASS。未运行 Gradle/AAR/APK/ADB/Jest,未触碰 STEP-062 或历史未跟踪内容。 ## 2026-09-11 — STEP-067 Linux 全量目标验证收尾 - 用户在当前 `HEAD` `06fcbef9ccb820e595f06acbd356950de7e3a73f` 手工执行 `ninja -C build-linux-opengl -j3 mbgl-test mbgl-test-runner`,Ninja 返回 `no work to do.`;确认 `mbgl-test` 与 `mbgl-test-runner` 完整目标及其依赖已经最新,没有待处理构建或重链接工作。 - 此结果只关闭此前 Linux 全量目标重链复验,不代表重新执行全量测试用例;本轮未执行 Android Gradle/AAR/APK/ADB/Jest,未修改生产代码、STEP-062 用户修改或其他历史未跟踪内容。STEP-067 正式 `CLOSED / PASS`。 # 2026-09-11 STEP-068:实现 V3 DIRECTION 粒子推进与 renderer `advectionScale`。DIRECTION 为 T0/T1 分量 MIX 后归一化,近零/非有限 fail-closed;VELOCITY 保持旧 m/s 数学且不消费 scale。已生成 shader 并完成变更前精确对象/过滤测试;新增最终 CPU oracle 后的精确编译与重链受本沙箱约 30 秒单次终端限制阻塞,状态为 IMPLEMENTED / WAITING_VALIDATION,未执行 Android 或 Jest。 # 2026-09-11 STEP-068:全量 Linux 重编译发现 WeatherColor 的 `ParticleGpuValidationUBO` 聚合初始化漏填新增 `advection`,触发 `-Wmissing-field-initializers`。仅补入 `{Direction=0, scale=1, epsilon=1e-5, reserved=0}` 的色场安全中性值;审计确认另一处 Particle renderer initializer 已完整初始化。未修改 shader/Android/JNI/RN/WeatherV2/NavSea/STEP-062;不据此声称全量重链 PASS。 # 2026-09-11 STEP-068 收尾:WeatherColor UBO 漏初始化修复后,最终受影响精确对象 PASS;`mbgl-test` / `mbgl-test-runner` 完整 Linux OpenGL 目标重编译与重链 PASS;STEP-068 相关 `Source.ParticleFieldV3*:Layer.RasterParticle*` 8/8 PASS;`git diff --check` PASS。额外扩大过滤范围发现基线既有 WeatherColor 测试末尾断言逻辑错误,已确认不由 STEP-068 引入,未混入本任务修复。STEP-068 正式 CLOSED / PASS;Android/Jest 未执行。 # 2026-09-11 STEP-068 Git:主实现 `f3c33c67275b24f61b80924abbb9d10d68b2cb7c`(`feat: add direction particle advection`)已成功 push 到 `origin/particle/main`,推送后 HEAD 与远端一致;STEP-062 用户修改与历史无关文件未提交。 # 2026-09-11 STEP-069:实现 RN `.3` 的 `maplibre-particle-field/v2` 多 plane ingress。`FieldPayloadRefs` 强制 shared validity、scalar/vector 至少一个,Kotlin 在读取前完成 local file 与 aggregate 64 MiB 校验;Java/JNI 以 presence flags/lengths 的明确 container 恢复 Core optional bundle。v1 单 vector ABI 保留为 `submitLegacyVectorField`。同时桥接 SCALAR/VECTOR_MAGNITUDE 与正 finite `advectionScale`,不改 Timeline、WeatherV2、NavSea 或 STEP-062。Android Gradle/AAR/APK/ADB/Jest 未执行,状态 `IMPLEMENTED / WAITING_ANDROID_VALIDATION`。 # 2026-09-11 STEP-069 复核修正:Native TurboModule Spec 移除 codegen 不支持的外部 `FieldPayloadRefs` object 参数,改用明确的 validity/scalar/vector string ABI;公共 `FieldRuntime.submitField(..., FieldPayloadRefs)` 不变,空 scalar/vector 仅为 bridge optional marker。外部复核指定 codegen schema 命令与 package `tsc` 均实际 PASS。Java facade 对 nullable scalar/vector 明确 `@Nullable`,并补 total <=64 MiB 防御;新增 Core 最小测试确认 v1 legacy 与 compatible v2 vector-only 进入同一 RasterArraySource Timeline,精确编译、`mbgl-test` 重链和过滤测试 2/2 PASS。Android Gradle/AAR/APK/ADB/Jest 未执行,仍为 `IMPLEMENTED / WAITING_ANDROID_VALIDATION`。 # 2026-09-11 STEP-069 Git:主实现 `148bf80fe41ba566de6c1d4b439cfe372a8a453c`(`feat: add v2 multi-plane field ingress`)已完成 scoped commit;最终独立复验确认 RN codegen、TypeScript、Linux 重链与 STEP-069 两个 Core 过滤测试 2/2 PASS。STEP-062 用户修改与历史无关文件未纳入;Android Gradle/AAR/APK/ADB/Jest 仍未执行。 # 2026-09-11 STEP-069 首轮推送:implementation `148bf80fe41ba566de6c1d4b439cfe372a8a453c` + handoff `12827489f4c377175554562632129df125c0a556` 已成功 push 到 `origin/particle/main`,首轮 push 后本地与远端一致。随后仅回填 Git 结果形成 metadata 收尾,不改变功能代码。 # 2026-09-11 STEP-070 V3-06 - 离线 v2 fixture validator 现逐 valid cell 检查所有存在 plane 的 finite/noData;Wind shared validity 严格来自 U/V 同时 finite 且均非 `-9999`。 - Wave 已由 WeatherV2 `2026090912` 正式 `waves_particles.bin`(T0=2026090918、T1=2026090919)直转为 height scalar + 归一化 DIRECTION vector;Tide 已由 CMEMS `2026090900` 正式 `current_vectors.bin`(T0=2026090901、T1=2026090902)直转 VELOCITY vector。每帧保留 BIN/sidecar SHA-256、target_time、grid/bounds/provenance;Wave period 不进入 canonical。 - Rain 仍为明确“非真实场值”的 PMTiles decoder fallback,generation=1/2;RN Host 已将 Wave/Tide 指向 real fixture,并继续只用 `.3` `FieldRuntime` 公共 API。 - fixture validator、package tsc、Host typecheck、RN codegen 与 `/tmp/step070-ccache` 精确 Core object PASS。随后 Linux OpenGL 完整依赖闭包构建 459/459 完成,`mbgl-test-runner` 成功链接,`Source.ParticleFieldV3*` 过滤测试 6/6 PASS,验证链退出码 0,`git diff --check` PASS。Android Gradle/AAR/APK/ADB/Jest 均未运行,STEP-070 保持 IMPLEMENTED / WAITING_ANDROID_VALIDATION。 - STEP-070 implementation `8588e6fcb4f3f5d874159c2e42619c5227cb7921` 已 scoped push 到 `origin/particle/main`;STEP-062 与历史 untracked/build/cache/tgz 未纳入。 ## 2026-09-11 — STEP-071 V3-07 Linux 综合冻结 - 最终冻结链:fixture validator、package tsc、RN Test Host typecheck、RN codegen、Linux OpenGL `mbgl-test`/`mbgl-test-runner` target 均 PASS;V3 综合过滤 21/21 PASS,`git diff --check` PASS,验证链退出码 0。 - 综合回归发现并修正两个测试 fixture 陈旧问题:Host T0/T1 重复 GPU content 导致 Duplicate,以及旧 east/north/vortex `timeIndex=0` 导致 Timeline fail-closed。只改测试数据组合,不改 Runtime/Timeline/Renderer 生产逻辑。 - Android Gradle/AAR/APK/ADB/Jest 未运行;V3-07 Linux 冻结关闭,下一步统一进入 V3-08 Android 综合验收。STEP-062 用户 dirty 与历史 untracked/build/cache/tgz 未纳入。 ## 2026-09-11 — STEP-072 V3-08 Android Native v2 与单次综合验收准备 - Native Android 目标版本升为 `13.4.1-particle.2`;RN package `13.4.1-particle.3`、Expo plugin、RN Test Host 与 release manifest 统一到该坐标,当前 Android 状态保持 `not_run`,未伪造 AAR SHA、发布时间或 release tag。 - 准备审计发现 Test Host 同时 autolink legacy local bridge 与正式 package bridge,二者均注册 `WeatherRuntimeBridge` / `WeatherRuntimeBridgeSpec`。STEP-072A 删除 legacy tracked bridge、根 `react-native.config.js`,并收敛 `tsconfig.json`;Expo autolinking 复核后只剩正式 `@navsea/maplibre-particle-rn` bridge。 - 静态 hard gate:Host/package TypeScript、RN codegen、V3 fixture validator、两个 Expo plugin 语法、release manifest JSON、`git diff --check` 全部 PASS;legacy untracked `android/build/` 原样保留。 - 已冻结 V3-08 单次 Android 验收流程:Linux 构建/发布 Native `.2` → SHA/API 检查 → Win11 Maven Local handoff → clean prebuild/dependencyInsight/一次 APK build → Metro 8091 → 固定设备 `192.168.1.146` → Wind/Rain/Wave/Tide/synthetic Wave 五组综合验收。Android Gradle/AAR/APK/ADB/Jest 均未执行,状态 `IMPLEMENTED / WAITING_ANDROID_VALIDATION`。 - STEP-072 implementation/preparation `11cf58d344e64e6aff77deceb2c34c8eda045f1b`(`chore: prepare V3-08 android validation`)已成功 push 到 `origin/particle/main`;push 后实现基线 HEAD 与远端一致。 ### 2026-09-11 STEP-072 / V3-08 CLOSED / PASS Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2` 已发布并验证;RN `13.4.1-particle.3` 通过正式 npm tarball + 远程 Maven 消费链。Win11 Gradle 8.14.3 / AGP 8.12.0 / Kotlin 2.1.20 构建 PASS。实体机 `192.168.1.146` 五组 Wind/Rain/Wave/Tide/Wave synthetic 均通过 T0/T1/READY 门槛,播放、速度、FPS、seek、独立显隐和视觉 API 均 ACCEPTED,fatal/JNI 扫描为空。 ### 2026-09-13 STEP-073 QBIN2 V4 Core 与通用 Profile Validator - 新增 provider-neutral `DecodedFieldFrame` / FieldSeries / ForecastClock primitive 及 Contract Schema v1 的纯数据驱动 Validator;不接入 QBIN decoder、Renderer、V3 生产路径、Android/JNI/RN。 - Validity 采用独立 descriptor 与共享只读 payload;REQUIRED 双向一致、额外 plane、时间关系、共享 validity 能力和 Velocity/Direction/Validity Core 规则均 fail-closed 且结构化返回。 - Linux OpenGL `mbgl-test` 构建、新 Validator/Runtime 定向测试和既有 V3 Field/Timeline 定向回归均 PASS;未执行 Android Gradle/APK/ADB。 ### 2026-09-13 STEP-073 v2 审计修正 - QBIN V2 DEGREE Core Unit ID 由错误 `2` 修正为冻结 registry `4`(NONE=0、MPS=1 保持);Generic Validator 覆盖 Direction `4` 接受、`2` 的 `InvalidCoreUnit` 拒绝。 - Plane identity 收紧为 `(semanticID, groupID)`;Frame/Contract 同 key 不同 component 均结构非法,已定位但 component 错误返回 `PlaneDescriptorMismatch`,既有 U/V 各 semanticID 的 velocity group 规则不变。 - ForecastClock 采用 half-millisecond remainder,修复 HALF 连续短 tick 的逐 tick 取整漂移;seek 清残差、pause 与 overflow fail-closed,NORMAL/DOUBLE 保持。 - Linux OpenGL `mbgl-test`、V4 Validator/Runtime 与 V3 Field/Timeline 定向回归均 PASS;未执行 Android Gradle/APK/ADB/Jest,未进入 QBIN Decoder/JNI/Renderer/RN。 ### 2026-09-13 STEP-073 v3 审计修正 - Generic Validator 新增静态数据表驱动的 Native Core semantic contract:`1/2` 固定 U/V velocity、`3` 固定 shared validity、`10/11` 固定 Direction DEGREE/NONE/group0;Contract 与 Frame 的冲突均结构化拒绝为 `SemanticContractMismatch`,不依赖任何 profile 或产品名称。 - `DIRECTION_ANGLE` 通用 Circular Quantization 现强制 `DEGREE=4`、NONE、group0、UINT16、offset=0、`scale=360/65536`(极小 float32 tolerance);opaque unknown Scalar unit 保持可扩展。 - Linux OpenGL `mbgl-test`、Validator/Runtime 过滤测试和 V3 Field/Timeline 过滤回归均 PASS,`git diff --check` PASS;未执行 Android Gradle/APK/ADB/真机/Jest/iOS-Metal,未进入 QBIN Decoder、Binding/Projection、Renderer、JNI、Android 或 RN。 ### 2026-09-13 STEP-073 v4 最终关闭修正 - `DecodedFieldFrame` 固化 single shared validity domain:designated validity 必须为 `Validity/Bitset/NONE/group0/None/REQUIRED`,与 `validityBits` 同一共享引用;普通 `planes[]` 禁止第二张 Validity。空 numeric `planes[]` 仍结构有效,缺 Profile numeric requirement 正确返回 `MissingRequiredPlane`。 - Validator 在 required descriptor 匹配前检查 actual reserved Core semantic;semantic 1 Scalar 伪装、semantic 10 的 component/group 冲突优先为 `SemanticContractMismatch`。unknown Scalar opaque 与 Direction circular quantization 规则保持。 - ForecastClock 测试在 pause 后显式恢复 `play()`,生产 pause 语义未改。实际重建并重链 `mbgl-test-runner` 后,V4 filter 11/11 PASS、V3 定向回归 11/11 PASS、`git diff --check` PASS;未进入 Decoder/Renderer/JNI/Android/RN,停止等待独立复验。 ### 2026-09-13 STEP-074 QBIN2 V4 Encoded Ingress 与 Decoder - 新增独立 `mbgl::particle::ingress::QbinV2Decoder` 与纯函数 `EncodedFieldIngress`:严格解析 raw QBV2,构造只读 `DecodedFieldFrame` 后交给既有 generic `FieldProfileValidator`;未接入 Store、Renderer、Binding、Host 或 platform bridge。 - Header/descriptor/limits/CRC/canonical packing/zero padding、single shared validity、invalid-cell raw-zero 和 per-plane local content identity 均 fail-closed;numeric bytes 不预展开为 float。 - 新测试 fixture 只位于 C++ test 范围,覆盖 2×2、损坏输入与 513×769 结构 frame;未实现下载、URL、HTTP、gzip、JNI、Android、RN 或 Renderer。 ### 2026-09-13 STEP-074 v2 审计关闭 - per-plane identity 已改为 raw bytes + descriptor 的显式 Little Endian canonical hashing,float 采用 IEEE754 bits;byte offset 不参与 identity。fixture writer 同样改为显式 Little Endian。 - 32 MiB 限制只计所有 Plane raw bytes,16-byte canonical padding 不计入;QBIN 文件整体仍限制为 64 MiB。BITSET/VALIDITY 双向约束,decode accepted 前强制 Frame structural self-check。 - `ParticleQbinV2Decoder` / `ParticleEncodedFieldIngress` 实际 18/18 PASS(v1 6);STEP-073 11/11、既有 V3 11/11、Linux runner 重链与 `git diff --check` 均 PASS。未执行或修改 Android/JNI/RN/Host/Renderer/Binding/网络/iOS-Metal。 ### 2026-09-13 STEP-074 v3 最终测试覆盖收口 - Decoder 入口优先级已由 production `QbinV2Decoder::decode` 直接覆盖:0/1/111 byte 为 `InputTooSmall`,完整 Header 的非 QBV2 magic 为 `BadMagic`,空 fieldID 或 generation=0 为 `InvalidRuntimeMetadata`;`dataVersion=0` 合法 Accepted。 - Header width 和 descriptor count 的 big/mixed-endian corruption 均在重算 CRC 后 fail-closed,分别结构化为 `LimitExceeded`、`InvalidDescriptor`。 - 1447×1449、7 plane 的 raw sum=31,712,633 bytes,canonical payload=31,712,648 bytes,15 bytes padding 不计入 32 MiB decoded raw limit 且 decoder Accepted。 - Linux runner 重建/重链、STEP-074 24/24、STEP-073 11/11、既有 V3 11/11 与 `git diff --check` 均 PASS;未改 production Decoder、Host、网络、JNI、Android/RN、Binding/Projection、Renderer 或 iOS/Metal。 ### 2026-09-13 STEP-074 v4 审计最终修正 - `AcceptsRawLimitWithCanonicalPaddingExcluded` 改为 1101×1890(2,080,890 cells)的 17-plane canonical fixture:single shared validity BITSET 加 16 个 UINT8 numeric plane。rawSum=33,554,352 bytes,小于 32 MiB limit=33,554,432;payloadLength=33,554,448 bytes,大于 limit 与 rawSum;totalQbinBytes=33,555,104 bytes,小于 64 MiB。 - production `QbinV2Decoder::decode(...)` Accepted;未发现生产缺陷,未改 Decoder 或 Host/网络/JNI/RN/Binding/Projection/Renderer。真实 runner 重建 PASS,Decoder/Ingress 24/24、Runtime/Profile 11/11、Source 回归 11/11 PASS,`git diff --check` PASS;未执行 Android Gradle/APK/ADB/Jest,按范围停止。 ### 2026-09-13 STEP-075 QBIN2 V4 Binding 与 Projection Identity - 新增 provider-neutral Color/Particle Binding 与 Resolver;每个 binding 按自己的 fieldKey 解析 FieldSeries Window,SampleState 单独保存 requested time/mix,Content Identity 不包含 mix 或视觉/播放状态。 - Vector U/V 与 DirectionAngle 都严格按 selected plane assertion fail-closed;Scalar-only revision 保持 Particle U/V/validity storage 与 identity 不变。 - Linux runner 真实重建、规定 Core filter 50/50 PASS、`git diff --check` PASS;未执行 Android Gradle/APK/ADB/Jest/iOS/Metal,未进入 Renderer/GPU/Host/JNI/RN,STEP-075 关闭并停止。 ### 2026-09-13 STEP-075 v2 Binding/Projection Identity 审计收口 - Color 与 Particle identity 统一以 `ProjectionFrameCoordinate(fieldID, validTimeMs)` 定位 T0/T1 window,只纳入各 binding 实际 selected plane 与 shared validity content identity;无关 plane 的 generation/dataVersion revision 不再污染另一 projection。 - Store public-path `ReplacedRevision` 对称覆盖:Scalar-only 仅改变 Color、U/V-only 仅改变 Particle、validity-only 同时改变两者;MIX 仍不进入 identity,in-window storage 仍稳定。 - Resolver 删除不可达 `InterpolationIncompatible`;相邻 frame compatibility 继续由既有 `FieldSeries::submit` fail-closed 保证。真实 Linux runner rebuild、规定过滤 50/50、`git diff --check` 全部 PASS;未执行 Android Gradle/APK/ADB/Jest,按范围关闭并停止,不进入 STEP-076。 - scoped commit `90d05f596a42c157502f9a2a5f20425c999cebab`(`fix: close STEP-075 projection identity audit`)已成功 push 至 `origin/particle/main`;STEP-062 dirty 和既有 untracked 均未暂存或提交。 ### 2026-09-13 STEP-075 v3 Binding/Projection Identity 最终审计收口 - `ParticleBinding::operator==` 收敛为 mode-aware active-selector identity:VectorComponents 仅比较 U/V,DirectionAngle 仅比较 direction;共同仍比较 mode、fieldKey、expectedUnitID,selector 保持 `(semanticID, groupID)`,component 继续只作 resolved descriptor assertion。 - 新增两组离线回归:Vector 的 inactive direction 与 Direction 的 inactive U/V 都不改变 binding/resolved projection identity;各自 active selector 变更仍 binding 不同并 `PlaneMissing` fail-closed。 - Linux OpenGL runner 真实重建 PASS;Binding 6/6、Runtime/Profile 11/11、QBIN/Ingress 24/24、Source 11/11,均 0 failure;`git diff --check` PASS。Android Gradle/APK/ADB/Jest、iOS/Metal 未执行;STEP-062 dirty 与历史 untracked/build 输出未纳入。 - scoped implementation `2645bd725f63c4da12ab48a0cc11ff034c9d9878`(`fix: close STEP-075 binding selector identity audit`)已成功 push:`653e6f2f1..2645bd725 particle/main -> particle/main`,remote 为 `origin/particle/main`。 ### 2026-09-13 STEP-076 QBIN2 V4 Core Host API 与 RasterArraySource 接线 - `RasterArraySource` 新增完全隔离的 V4 QBIN Host API:submission 严格执行 key/runtime metadata → QBIN decoder → Profile validator → per-field Store,稳定返回 insert/replace/duplicate 与各类 fail-closed rejection;失败不留下 partial Store mutation。 - V4 owner 独立持有 `EncodedFieldStore`、`ForecastClock`、Color/Particle binding;每个 binding 在 resolve 时按自己的 fieldKey 获得 window/mix。没有 Host T0/T1/MIX API,没有切换 renderer,也未改动 V3 timeline。 - 离线 Source V4 suite 3/3、Binding 6/6、Runtime/Profile 11/11、QBIN/Ingress 24/24、V3 Source 11/11,均为 0 failure;Linux runner 真实重建、`git diff --check` PASS。Android Gradle/APK/ADB/Jest、iOS/Metal 未执行;STEP-062 dirty 与既有 untracked/build 输出未纳入。 ### 2026-09-13 STEP-076 v2 审计测试收口 - V4 public-path reject 现在逐项证明 `RejectedDecode`、`RejectedContract`、`RejectedInvalidFieldKey`、`RejectedStaleRevision` 不改变既有可 resolve projection 的 content identity、T0/T1 coordinate、selected U/V plane 与 validity storage identity;未读取 Store 私有状态。 - clear 测试先用公开 `submitInitialRuntimeFieldWindow(...)` 建立 V3 `field/nextField`,对 `clearEncodedField`、`clearAllEncodedFields` 和 V4 re-submit 全程核验 V3 identity/generation/validTime 不变;V4 清空后 fail-closed,binding intent 仍可重解。 - Linux runner 真实重建 PASS;Source V4 4/4、Binding 6/6、Runtime/Profile 11/11、QBIN/Ingress 24/24、Source regression 11/11,全部 0 failure,`git diff --check` PASS。未执行 Android 编译/Gradle/APK/ADB/Jest/iOS-Metal;STEP-062 dirty 与历史 untracked/build 输出未纳入 scoped commit。 ### 2026-09-13 STEP-077 QBIN2 V4 Android / JNI / RN 桥接只读调查 - 已按实际 RN TurboModule、Kotlin、WeatherRuntime、MapLibreMap、NativeMapView JNI 与 RasterArraySource V4 API 完成只读调查;未修改 production code、Test Host、Renderer/GPU,也未下载真实 QBIN 或运行 Android 构建。 - 结论:V4 必须是独立 encoded-field API。现有 V3 `submitField`、`clearFields`、`setForecastTime`、playback 会操作 V3 Host field/timeline,绝不能复用。RN 应传本地 QBIN URI,Kotlin 使用既有 64 MiB guarded read,Java `byte[]` / JNI copy 是可复用的 binary seam;禁止 JS number[]/Base64。 - 建议 V4 结果逐项映射 Core `RasterArrayEncodedFieldSubmitResult`,桥接层 file/lifecycle/style/source 错误用独立 rejection code;每次 command 都沿用 Fabric tag -> current MLRNMapView -> MapLibreMap 的 UI queue late lookup,不建立第二 registry 或缓存 native pointer。 ### 2026-09-13 STEP-078 QBIN2 V4 Android / JNI / RN 桥接实现 v2 - 完成隔离 V4 RN/TurboModule/Kotlin/Java/JNI/Core Host 调用链;QBIN 只经受 1..64 MiB 限制的本地 file URI 传输。十种 Core submit result 保持逐项 resolve,source/type 生命周期错误只经私有 sentinel 转为明确 rejection。 - frozen contract schema 改为 Core 同名 `contractSchemaVersion` / `requiredFlag` 等字段,并抽取为可 Linux 测试的 provider-neutral C++ parser;新增合法与所有指定 fail-closed case 单测。 - Color binding 端到端传递 expected unit;Particle binding 固化 mode-aware U/V/direction slots,inactive slot 仅 `(0,0)`;forecast state/speed 为完全独立 Core command。 - Linux 限流 runner build、parser/Source V4/Binding/QBIN/Runtime/V3 Source 回归、TypeScript、TurboModule codegen、JNI declaration-registration 静态核对和 `git diff --check` 均 PASS。Android Gradle/APK/ADB/JNI 真实编译、Jest、iOS/Metal 未执行,等待后续一次性 Android 验收;未进入 STEP-079。 ### 2026-09-13 STEP-078 v3 production guard 审计收口 - QBIN transport 的 1..64 MiB 上限现由 Kotlin local-file、Java `WeatherRuntime` facade、JNI copy 三层执行;JNI 在 `std::vector` 分配前 fail-closed。Decoder 的 64 MiB file / 32 MiB decoded-raw 业务限制不变。 - fieldKey、runtime fieldID、profileID 统一按 UTF-8 byte length 1..64 验证:RN `TextEncoder`、Kotlin `toByteArray(Charsets.UTF_8)`、Java `StandardCharsets.UTF_8`。多字节 33 CJK(99 bytes)输入在 RN/Java guard tests 中拒绝。 - `particle-codex` 内所有限流验证均 PASS:package tsc、TS directed test、TurboModule schema、JDK-only Java guard、Linux runner rebuild、V4/V3 指定 filter、JNI name-set 与 `git diff --check`。Android Gradle/APK/ADB/JNI 真实编译、设备、Jest、iOS/Metal 仍未运行;未改 Renderer/GPU/shader/Test Host/NavSea,不进入 STEP-079。 - 实现 scoped commit `75a974e77503c56ec5bd2823ac1b689225ed80a7`(`fix: close STEP-078 V4 bridge guard audit`)已成功 push:`73779b89b..75a974e77 particle/main -> particle/main`;仅文档 Git 收尾 commit 随后推送并停止。 ### 2026-09-13 STEP-079 真实 QBIN Golden Fixture RN Test Host 接入阻塞 - 在复制/接入前核对冻结 fixture contract 与 STEP-078 V4 public API:Wind/Current U/V 是 `VELOCITY_COMPONENT`(semantic 1/2、group 1、MPS),而 `setEncodedColorBinding` 的 RN/Android public contract 仅允许 `SCALAR` 或 `DIRECTION_ANGLE`。 - 用 scalar 伪装 U/V 会被 Core ColorBinding resolver 以 `PlaneClassMismatch` fail-closed;扩 public enum 则改变 STEP-078 冻结 public API。本 Step 未堆叠 Test Host wrapper、未改 Core/Renderer/bridge,也未保留半成品 fixture。 - 已按任务的接口阻塞停止条款生成 STEP/阻塞报告;未运行 TypeScript/codegen/C++/Android 验证,等待独立 API 修订 Step。 ### 2026-09-13 STEP-078 v4 ColorBinding VELOCITY_COMPONENT 接口修订 - `FieldRuntime.setEncodedColorBinding(...)` 现公开支持 `VELOCITY_COMPONENT`:TS string contract、Kotlin `1` 映射、JNI `0..2` guard 与现有 Core `FieldValueClass::VelocityComponent` 一致;TurboModule primitive ABI 和 Java 透传签名未改变。 - 新 Core 回归通过真实 U-east velocity component plane 成功 resolve ColorBinding,`Validity` ColorBinding 仍为 `InvalidBinding` fail-closed;未增加 vector magnitude、单位转换或 provider 特例。 - `particle-codex` 中经输出节流的 package tsc、TurboModule schema、Linux runner rebuild、Binding/Source V4/QBIN-Ingress/Runtime-Profile/V3 Source 过滤回归均 PASS;Android Gradle/APK/install/ADB/设备、Jest、iOS-Metal 未执行。STEP-079 不在本次进入,待 ChatGPT 独立复验后重启。 ### 2026-09-13 STEP-079 真实 QBIN Golden Fixture 接入 RN Test Host v2 - Test Host 已保留 V3 区并新增 V4 Wind/Wave/Current/Rain 四组冻结 QBIN T0/T1。8 个 raw asset 仅从冻结 WeatherV2 source 复制并随 Host 打包;`expo-asset` materialize 后只传本地 `file://` URI,运行时无 source-server、网络或 gzip 依赖。 - V4 dataset 真实表达 Wind/Current U `VELOCITY_COMPONENT` ColorBinding 与 U/V particle,Wave height/direction,Rain precipitation/Particle N/A;load、submit result、binding、midpoint seek(不宣称 mix)、PLAY/PAUSE、正 speed、clear 均有独立 UI。 - `particle-codex` 限流验证:Host/package TypeScript、TurboModule combine/codegen、8 文件 bytes/SHA-256、Linux runner target、Contract/Transport/V4/Binding/QBIN/Runtime/V3 filter 与 `git diff --check` 均 PASS。Android Gradle/APK/install/ADB/设备/Jest/iOS-Metal 未运行;状态 `IMPLEMENTED / WAITING FOR WINDOWS 11 ANDROID VALIDATION`。 ### 2026-09-13 STEP-080 Android AAR 与 RN Test Host 标准构建流水线 - 固化 Linux `linux_build_publish.sh`:仅接受 RN/Native 完全一致版本,默认固定 OpenGL Release 四 ABI build、Maven Local publish、AAR/POM/module 校验、RN package typecheck/npm pack,以及 AAR/tgz bytes+SHA-256 的版本隔离 build-manifest;noisy Linux build/typecheck/package 一律经 build-output-throttle,缺 runner 立即 fail-closed。 - 固化 Windows `windows_build_testhost.ps1`:manifest 是唯一 artifact/version 输入,支持先 `-DryRun`,再把 bundle 校验安装到 Windows Maven Local、固定 tgz/coordinate、显式 prebuild 与 Debug APK build。默认没有 ADB/设备;`-Install`/`-Run` 显式开关才可访问 `192.168.1.146`。 - 在 `particle-codex` 使用已存在的 Native `.3` Maven Local publication 运行 `--reuse-existing`:AAR/POM/module、`.2` 历史保护、RN typecheck、npm tgz、manifest 路径/bytes/SHA/version 全部 PASS;未重复完整 AAR 编译、未执行 Gradle APK/ADB/设备/Jest。Linux 无 `pwsh`,Windows PowerShell parser 未本机执行,已明确记录而未伪称 PASS。 ### 2026-09-14 QBIN V4 Android `.3` 人工验收与文档基线整理 - Linux OpenGL Native 与 RN package 已统一为 `13.4.1-particle.3`;AAR 通过 `/mnt/nas/pbf/maven` 对应公网 `https://pbf.jpcn.ccwu.cc/maven` 发布,RN tgz 通过 `/mnt/nas/pbf/npm` 对应公网 `/npm/` 发布。Win11 Test Host 正常路径改为直接消费公网 npm/Maven,不再以 LAN AAR/Maven Local 作为当前主流程。 - Win11 实际构建发现并修正 JNI particle binding declaration 参数数目与 Kotlin `validUInt16`/`validSafeInteger` 编译表达式;Debug APK 成功生成、安装并启动。Metro 固定监听 8091,App 仍访问 localhost:8081,正确 reverse 为 `8081 -> 8091`。 - Test Host 的 8 个 V4 QBIN Golden Fixture(Wind/Wave/Current/Rain,各 T0/T1)已由用户人工确认功能正常;V4 调用经 `submitEncodedField` 进入 `RasterArraySource::submitEncodedField` / `QbinV2Decoder`,不是 JS 解码。 - 当前入口文档已整理:`docs/00_项目总则/当前基线与开发路线_v2.md`、`docs/50_Step记录/STEP-080_Android_AAR与RNTestHost标准构建流水线_v2.md`、`docs/70_发布/Android_RN_QBINV4_13.4.1-particle.3_发布基线_v1.md`。旧 STEP-060~072 与 STEP-080 v1 保留历史事实,但不再作为当前构建命令来源。 # STEP-081(2026-09-17):新增 Metal `ParticleGpuValidationShader` 与 iOS Test App Wind QBIN V4 private smoke 入口。Codex 后已完成 GPT/RDC 独立静态审查;RDC 随后完成 iPhoneOS arm64 无签名 Test App 编译并取得 `BUILD SUCCEEDED`,`particle_gpu_validation.cpp` 与 `MBXViewController.mm` 均通过,61 MB app bundle 内 T0/T1 QBIN SHA-256 与源 fixture 一致。当前真机均 unavailable,签名安装、Metal runtime compile 与 T0/MID/T1/Clear 真机 Smoke 待执行,状态 WAITING_DEVICE_SMOKE。 ### 2026-09-18 STEP-081 iOS Metal Renderer 真机最终关闭 - Pleiades(iPad mini 5 / iPadOS 26.5.2)完成签名安装与 Metal 真机验收。Deterministic Uniform East 向东、Uniform North 向北、Vortex 粒子可见且连续有轨迹;QBIN Wind Golden T0/MID/T1/Clear/重进均通过,STEP-081 CLOSED / PASS。 - 真机确认 Metal render pipeline cache key 原先遗漏 color/depth/stencil attachment format,导致 State RGBA32Float、Trail RGBA8Unorm 等同 shader pipeline 可能错误复用;已把 attachment formats 合入 cache key。 - 正式 previous→current 线平均约 0.065 px、最大约 0.24 px,Metal line primitive 对亚像素长度无稳定 coverage;保留真实 line,并用 Metal-only 1 px current-endpoint quad 补 coverage,不改变 State、U/V、时间步或物理线长。 - Wind QBIN Golden fixture 范围为 112.5E..157.5E / 0..55.776573N;iOS private smoke 相机调整到约 27.8883N / 135E、zoom 3 后可正常观察。所有 STEP081 临时 readback/固定线/Point fallback 均已清除;错误 Point fallback 的整屏绿色结果未进入正式代码。 - STEP-081 功能/真机验收提交 `f1c0f92b2b`(`fix: close STEP-081 iOS Metal particle rendering`)已成功 push 到 `origin/particle/main`。 ### 2026-09-18 STEP-082 iOS Native FieldRuntime Facade 与 XCFramework 发行基线 - 新增 public `MLNParticleFieldRuntimeConfiguration`、`MLNParticleFieldRuntime` 与 `MLNMapView (ParticleFieldRuntime)`;MapView 通过 associated object 持有 runtime,runtime 仅弱引用 MapView,replace 先 dispose 旧实例,dispose 幂等。 - facade 每次命令均重新查找 current style 的 `RasterArraySource`、`WeatherColorLayer` 与 `RasterParticleLayer` 并核验真实 Core 类型和 source 关联,不缓存跨 style 生命周期的 Core pointer;style reload、source/layer 缺失均以独立 NSError fail-closed。 - V4 入口复用 Core contract parser、decoder/submit、binding、forecast 与 clear;ObjC 层只执行与 Android 一致的 transport guard 和稳定结果映射,未改 QBIN/renderer/Metal、Android、RN 或 NavSea,也未重做 STEP-081。 - `MLNParticleFieldRuntime.h` 已加入 iOS Bazel SDK public headers 和 `Mapbox.h`;`MLNMapView_Private.h` 仍仅为 implementation private include。建立 `release/maplibre-particle/ios/` SwiftPM template/manifest,因 XCFramework zip 未生成而明确 `NOT_BUILT`。 - macOS Bazel `//platform/ios:MapLibre.dynamic` 在 facade 编译前被既有 style-codegen 输出声明阻断:`particle_validation_layer.cpp` 被列为生成输出但 generator 不生成;未越权改 Core/codegen。iPhoneOS arm64 CMake `ios-sdk-static` 编译已启动,最终状态以 Step/完成报告记录为准;在 XCFramework 成功验证前,STEP-082 保持 `IMPLEMENTED / WAITING_MAC_XCFRAMEWORK_VALIDATION`。 - 随后 `cmake --build build-ios --target ios-sdk-static -- -quiet` 返回 0,完成 iPhoneOS arm64 static framework build,且 `MLNParticleFieldRuntime.o` 已由真实 Xcode build graph 生成;唯一 warning 是已有 `MLNMapView_Private.h` 的 EAGL deprecation。Bazel XCFramework codegen blocker 未改变,未产出 zip/SHA-256。 ### 2026-09-18 STEP-082 XCFramework Bazel 阻塞修复与最终关闭 - 宿主在真实 implementation commit `136ed726cf749c24b3673c046581a38ef48be390`(`fix: close ios xcframework packaging blockers`)上修复 iOS XCFramework packaging blocker;`bazel build //:generated_style_code` 与 `bazel build //platform/ios:MapLibre.dynamic` 均 PASS,后者最终日志为 `/tmp/step082-host-maplibre-dynamic-final2.log`,以 `Build completed successfully` 结束。 - 真实本地产物 `bazel-bin/platform/ios/MapLibre.dynamic.xcframework.zip`:`24639200` bytes,SHA-256=`64faa174c5c0dc0a2da3e289f0beaf2dedf7298665e3345f39836729b668e239`。device `ios-arm64` 和 simulator `ios-arm64_x86_64-simulator` 都有 public `Headers/MLNParticleFieldRuntime.h`,两份 `Mapbox.h` 均导入该 header。 - 两 slice binary 都有 `_OBJC_CLASS_$_MLNParticleFieldRuntime` 和 `_OBJC_CLASS_$_MLNParticleFieldRuntimeConfiguration`;`MLNMapView_Private.h` public export count=0。device 为 arm64,simulator 同时含 x86_64 与 arm64。 - iOS release manifest 现为 `VALIDATED`,distributionVersion 仍为 `6.28.0-particle.1`、module 为 `MapLibre`;artifact 尚未发布,URL 明确为 `LOCAL_BUILD`。STEP-082 CLOSED / PASS;Git closeout commit/push 将由宿主在本轮文档生成后完成,最终 hash 以宿主回填/最终回复为准。 ### 2026-09-18 STEP-083 iOS RN TurboModule / Fabric bridge 实现批次 2 - package 新增 RN 0.85 codegen `WeatherRuntimeBridge` iOS ObjC++ module、podspec、autolinking/provider;公共 TS API 未分叉,仅把缺 module 文案改为平台中性。每条命令由当前 Fabric/UIManager injected registry UI block 重新验证 MLRN component/content view,再使用 public `MLNMapView` facade;不缓存 map/runtime,也无第二 registry。 - V3、V4、bindings、forecast 与全部视觉命令映射现有 iOS facade;本地 payload guard 限 file:///absolute readable regular file、1..64 MiB 和读取前后长度一致。pod 只依赖 `MapLibreReactNative`,复用 MLRN `$MLRN_SPM_SPEC` 的唯一 `MapLibre` product。 - podspec syntax、package dry-run tarball、provider config、34/34 method parity 和 `git diff --check` PASS。离线 npm cache 缺 package,故 TypeScript/codegen/Pod/Xcode/runtime 未执行;STEP-082 的 `LOCAL_BUILD` XCFramework zip 也尚非 MLRN 可消费的 custom SwiftPM URL。状态 `IMPLEMENTED / WAITING_IOS_VALIDATION`,由 RDC 在真实 single-binary consumer 环境继续验证;未 commit/push,既有 dirty 未触碰。 ### 2026-09-18 STEP-083 iOS Metal artifact 与 RN 真机验证纠正 - 已确认裸 `bazel build //platform/ios:MapLibre.dynamic` 默认走 OpenGL:旧 XCFramework 虽可显示色场,但 RN Test Host 不渲染粒子,旧 `24639200` bytes / `64faa174c5c0dc0a2da3e289f0beaf2dedf7298665e3345f39836729b668e239` artifact 作废,不再作为 iOS Particle 发行基线。 - 发行固定为 `bazel build --//:renderer=metal //platform/ios:MapLibre.dynamic`。新 Metal zip 为 `24943196` bytes,SHA-256=`ae88975fc20f4d9961b95079638d0e9c0d8e61d4394d5c0a8ffcc48d173a827f`,source commit=`bdd7f40f9029031816c9bf4db6e1cd6c7c69b7bd`;device binary 含 Metal/`MTLDevice`/`ParticleGPU` 且无 OpenGL marker,远端 URL 仍为 `LOCAL_BUILD`。 - RDC 已实际完成 npm ci、typecheck、RN codegen、Expo prebuild、Pod integration、device arm64 build、signed Release build/签名/安装;MLRN/App/Particle 使用 single MapLibre SPM product。Pleiades iPad mini 5 上一次 V4 Wind load 观察到 clearAll、bindings、T0/T1 accepted 与 midpoint seek,用户确认粒子恢复。 - 当前状态 `IMPLEMENTED / IOS_CORE_PATH_PASS / WAITING_FINAL_CONTROL_REGRESSION`:PLAY/PAUSE、clear selected/all、detach/re-attach 尚未逐按钮实测;不将单次 load 证据扩大为完整控制面验收。未 commit/push。 ### 2026-09-18 STEP-083 iOS RN 真机最终控制回归与正式关闭 - Pleiades iPad mini 5 真机在 Test Host signed Release 上完成 `RUN V4 FINAL CONTROL REGRESSION` 单按钮序列:`prepare#1 → PLAY → 约500ms → PAUSE → clear selected → prepare#2 → clear all → detach → attach → prepare#3 → refresh`;用户明确确认“FINAL CONTROL REGRESSION PASS”。 - 最后一次 prepare/refresh 后 Metal V4 Wind 粒子恢复并保持可见;此前用户已确认“粒子恢复了”。single MapLibre SPM、signed Release `BUILD SUCCEEDED`、安装启动与 Metal artifact(`24943196` bytes,SHA-256 `ae88975fc20f4d9961b95079638d0e9c0d8e61d4394d5c0a8ffcc48d173a827f`)验证事实不变。 - STEP-083 正式 `CLOSED / PASS`。App.tsx 回归按钮保留且逻辑不变;未修改 RN public API/native/Core/renderer/release manifest,未提交。下一步进入 NavSea iOS 首批大集成,不再拆分微小 build/install Step。