From a418e50a0105a23e70112eb77cd813485eae6855 Mon Sep 17 00:00:00 2001 From: OpenAI Codex Date: Fri, 4 Sep 2026 13:43:30 +0800 Subject: [PATCH] fix: restore particle timeline readiness after field adapter --- ...al_Field_Data_Adapter与Runtime输入契约_v2.md | 32 +++++++++++++ ...TEP-049_Timeline回归修复_Codex完成报告_v1.md | 45 ++++++++++++++++++ .../particle/field/field_data_adapter.hpp | 2 + .../ParticleCoreLayerValidationActivity.kt | 11 +++-- .../particle/field/field_data_adapter.cpp | 14 ++++++ .../offline_fixture_particle_adapter.cpp | 5 +- .../style/sources/raster_array_source.cpp | 15 +++++- test/style/source.test.cpp | 47 +++++++++++++++++++ 粒子开发记录.md | 7 +++ 9 files changed, 170 insertions(+), 8 deletions(-) create mode 100644 docs/50_Step记录/STEP-049_Provider-neutral_Field_Data_Adapter与Runtime输入契约_v2.md create mode 100644 docs/报告/STEP-049_Timeline回归修复_Codex完成报告_v1.md diff --git a/docs/50_Step记录/STEP-049_Provider-neutral_Field_Data_Adapter与Runtime输入契约_v2.md b/docs/50_Step记录/STEP-049_Provider-neutral_Field_Data_Adapter与Runtime输入契约_v2.md new file mode 100644 index 000000000..92ec1ec4f --- /dev/null +++ b/docs/50_Step记录/STEP-049_Provider-neutral_Field_Data_Adapter与Runtime输入契约_v2.md @@ -0,0 +1,32 @@ +# STEP-049 Provider-neutral Field Data Adapter 与 Runtime 输入契约 — Timeline 回归修复 + +- 状态:进行中(等待 Android 重新验收) +- Starting HEAD:`dcedbe7394e74b80d91f00315a9956dfaea35229` +- 分支:`particle/main` + +## Android 回归与根因 + +STEP-049 后 Android 的 Runtime Window 和 Renderer 正常,但 Timeline 没有 READY。失败链路定位为 `RasterArraySource::tryLoadRuntimeField()` 调用 fixture wrapper 时传入 generation `0`;正式 `ParticleFieldDataAdapter` 正确拒绝 `generation == 0`。Runtime Window 初始 field 使用已分配的全局 generation,因此未受影响。Timeline 原本计划在 `tryInitializeTimeline()` 中才给 candidate 分配 generation,顺序晚于 adapter 校验。 + +## 修复点与语义 + +candidate 在 metadata/payload 完整后、调用正式 adapter 前分配 `++nextRasterArrayFieldGeneration`,因此每个进入 Core 的 Snapshot 都满足非空 identity 与 `generation > 0`。Timeline 构建阶段不再重复改写 generation。没有放宽 adapter contract,没有新增 adapter/Timeline/Window,也没有改变 Timeline 状态机、Runtime Field Window、Renderer 或 Android Timeline ownership。 + +低频 rejection 路径补充 error code、fieldId、generation、validTime 和 candidate index 上下文,不输出 payload。 + +## 测试 + +新增 `RasterArrayTimelineCandidatesReachReadyThroughFieldAdapter`,实际加载 EAST/NORTH 初始窗口和 VORTEX candidate,覆盖 fixture wrapper → formal adapter → candidate preload → Timeline READY,并断言 candidate identity/generation 合法、PLAY 成功。原有 generation=0/invalid descriptor 结构化拒绝测试继续通过。 + +- Linux OpenGL `mbgl-test-runner`:PASS +- 定向测试:12/12 PASS +- `git diff --check`:PASS +- Android/APK/ADB/Jest:未执行 + +## Validation UI + +仅修改 Android Validation UI 展示:Window 与 Timeline 分离显示,Timeline 使用 `TL NOT READY`、`TL READY`、`TL PLAY`、`TL PAUSE`、`TL WAIT`、`TL INVALID`,MIX 保持显示。未修改 Core 状态机。 + +## 待复验与阻塞 + +代码无已知阻塞。Android 尚未复验,当前只能标记 `IMPLEMENTED / WAITING_ANDROID_REVALIDATION`;用户需重新构建一次 APK 并完成 Timeline READY、PLAY、跨 boundary、Pause/Resume、GAP、INVALID NEXT 综合验收。 diff --git a/docs/报告/STEP-049_Timeline回归修复_Codex完成报告_v1.md b/docs/报告/STEP-049_Timeline回归修复_Codex完成报告_v1.md new file mode 100644 index 000000000..4649c1f54 --- /dev/null +++ b/docs/报告/STEP-049_Timeline回归修复_Codex完成报告_v1.md @@ -0,0 +1,45 @@ +# STEP-049 Timeline 回归修复 — Codex 完成报告 + +## 状态 + +`IMPLEMENTED / WAITING_ANDROID_REVALIDATION`。本报告不宣称 `CLOSED / PASS`。 + +## 基线与根因 + +- Starting HEAD:`dcedbe7394e74b80d91f00315a9956dfaea35229` +- 实际远端 `origin/particle/main` 起始 HEAD:`dcedbe7394e74b80d91f00315a9956dfaea35229` +- 根因:`tryLoadRuntimeField()` 以 generation `0` 调用正式 adapter;adapter 合法拒绝,Timeline candidate 在更晚的 `tryInitializeTimeline()` 才分配 generation。Runtime Window 使用已分配 generation,故出现 Timeline 失败而 Window 正常。 +- 原 STEP-049 11/11 未捕获:测试覆盖了直接 adapter、手工 Timeline 和 Runtime Window,但没有覆盖真实 Source 异步 candidate preload → adapter → Timeline READY 顺序。 + +## 实际修改 + +- `src/mbgl/style/sources/raster_array_source.cpp`:candidate decode 前分配全局 generation,移除 Timeline 阶段重复赋值;增强低频 adapter rejection 日志。 +- `src/mbgl/particle/field/field_data_adapter.cpp`、`.hpp` 与 fixture wrapper:保留正式 contract 和 generation 非零校验,提供 error code 名称用于日志。 +- `test/style/source.test.cpp`:新增真实 candidate → adapter → Timeline READY 回归测试。 +- `platform/android/MapLibreAndroidTestApp/.../ParticleCoreLayerValidationActivity.kt`:仅整理 Window/Timeline 状态可见性。 +- `docs/50_Step记录/STEP-049..._v2.md`、本报告、`粒子开发记录.md`。 + +未修改 Runtime Field Window、Duplicate、Renderer simulation、Timeline Core 状态机或 Android per-frame JNI;未新增兼容层。 + +## 验证 + +- C++/Core/OpenGL:`cmake --build build-linux-opengl --target mbgl-test-runner -j3`,PASS。 +- 定向测试:`Source.RasterArrayTimelineCandidatesReachReadyThroughFieldAdapter:Source.ParticleFieldDataAdapter*:Source.RasterArray*`,12/12 PASS。 +- 合法 candidate 通过正式 adapter 并进入 Timeline READY:PASS。 +- generation=0 / invalid descriptor 结构化拒绝:PASS。 +- `git diff --check`:PASS。 +- Android Gradle/APK/copy/install/ADB/设备:未执行。 +- Jest:未新增、未执行。 + +## Android 待复验 + +需验证 `ParticleTimeline: event=READY`、PLAY 不再 `TIMELINE_NOT_READY`、MIX/cursor 推进、跨至少两个 Window boundary、Pause/Resume、GAP WAIT、INVALID NEXT、fail-closed、Renderer 持续和 `simulationRebuild=false`/`trailCleared=false`。 + +## Git 收尾 + +- commit hash:待提交 +- commit message:`fix: restore particle timeline readiness after field adapter` +- push result:待执行 +- remote branch:`origin/particle/main` +- Final HEAD:待提交 +- 无关 untracked 文件:保留,未修改、未 stage、未提交。 diff --git a/include/mbgl/particle/field/field_data_adapter.hpp b/include/mbgl/particle/field/field_data_adapter.hpp index 1a60378ba..ebc6c6ea9 100644 --- a/include/mbgl/particle/field/field_data_adapter.hpp +++ b/include/mbgl/particle/field/field_data_adapter.hpp @@ -79,6 +79,8 @@ enum class ParticleFieldAdapterError : uint8_t { DecodeValidationFailure, }; +const char* particleFieldAdapterErrorName(ParticleFieldAdapterError); + struct ParticleFieldAdapterResult { std::optional snapshot; ParticleFieldAdapterError error = ParticleFieldAdapterError::None; diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt index d8d66ddcd..18d93cee9 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt @@ -35,7 +35,7 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() { private var styleLoadEpoch = 0L private var styleReady = false // Display mirror only; Core remains the playback state authority. - private var timelineState = "READY" + private var timelineState = "NOT READY" private var timelineSpeed = "1x" override fun onCreate(savedInstanceState: Bundle?) { @@ -114,7 +114,7 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() { timeWindowMode = true fixtureMode = FIXTURE_UNIFORM_EAST timeMix = 0.0f - timelineState = "READY" + timelineState = "NOT READY" if (this::maplibreMap.isInitialized) loadValidationStyle(active, enabled, "TIME_WINDOW") } findViewById