diff --git a/docs/40_任务/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex任务_v1.md b/docs/40_任务/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex任务_v1.md new file mode 100644 index 000000000..592ad789e --- /dev/null +++ b/docs/40_任务/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex任务_v1.md @@ -0,0 +1,318 @@ +# STEP-066 MapLibreParticleLab V3-02 Core Contract + Scalar Snapshot/Adapter — Codex任务 v1 + +## 0. 任务定位 + +本任务承接 STEP-065 已冻结的 MapLibreParticleLab V3 架构,只实施 **Core Contract / Snapshot / Adapter 层**。 + +目标:把当前 Wind-only、单 U/V payload 的 `maplibre-particle-field/v1` Core 输入模型,升级为 V3 内部统一的 generic snapshot,支持: + +- vector-only +- scalar-only +- scalar + vector +- shared validity +- vector semantics: `VELOCITY | DIRECTION` +- v1 vector-only 作为最薄兼容 ingress normalize 到同一套 V3 snapshot + +本任务不进入 GPU、shader、Android/JNI、RN、NavSea、WeatherV2,也不做 Android 构建。 + +## 1. 当前基线 + +仓库:`/mnt/sda1/MapLibreParticleLab` + +分支:`particle/main` + +任务书创建时 HEAD / origin: + +`d23ae2079dcfef3ce48517f734fe487207e28d23` + +执行时必须重新确认 branch、HEAD、origin 和 `git status --short`。若远端已合法推进,先阅读新增提交,不得 reset、checkout 覆盖或丢弃用户修改。 + +当前工作区已有 STEP-062 用户修改和大量历史 untracked/build 产物,全部视为无关用户内容。禁止 `git add .`、`git add -A`、clean/reset/stash 覆盖它们。 + +## 2. 开工前必须阅读 + +必须完整阅读: + +- `AGENTS.md` +- `PARTICLE_BASELINE.md` +- `docs/00_项目规范/` +- `docs/20_调查/STEP-065_MapLibreParticleLab_V3通用ScalarVectorField现状调查_v1.md` +- `docs/30_设计/MapLibreParticleLab_V3通用ScalarVectorField运行时架构设计_v1.md` +- `docs/50_Step记录/STEP-065_MapLibreParticleLab_V3通用ScalarVectorField架构冻结_v1.md` +- `docs/报告/STEP-065_MapLibreParticleLab_V3通用ScalarVectorField架构冻结_Codex完成报告_v1.md` +- 当前 `field_data_adapter.*` +- 当前 `local_particle_field_feed.*` +- 当前 `raster_array_source.*` 中 host field parser / Timeline / Runtime Window 相关实现 +- 与 `ParticleFieldDescriptor`、`ParticleFieldSnapshot`、`ParticleFieldTimeWindow`、`sameFieldGpuContent`、`fieldIdentityChanged` 直接相关的所有调用点 +- 现有相关 C++ tests/fixtures + +不得根据 STEP-065 文档示例直接猜当前源码。 + +## 3. 冻结架构,禁止重新讨论 + +STEP-065 已冻结以下方向,本任务必须按此实现,不重新发明第二套模型: + +1. 新 canonical schema:`maplibre-particle-field/v2`。 +2. 一个 Snapshot:0/1 scalar + 0/1 vector + 1 shared validity。 +3. scalar-only、vector-only、scalar+vector 合法;neither 非法。 +4. vector 为 `float32-le / interleaved-uv`,U eastward、V northward。 +5. scalar 为 `float32-le` 单 plane。 +6. validity 为显式 shared logical validity;V3 Core 内统一为 `std::vector` 或现有等价表示。 +7. `VectorSemantics = VELOCITY | DIRECTION`,只在 vector present 时合法。 +8. `fieldType` / `displayDomain` 不再作为 Core capability 或 validity 判断依据。 +9. Renderer 的 `FieldValueSource` 属于后续 V3-03,不在本任务实现。 +10. Timeline / T0-T1 / MIX / Pause / rollover ownership 不重构。 + +## 4. 本任务必须形成的 Core 模型 + +优先扩展现有 `ParticleFieldDescriptor` / `ParticleFieldSnapshot`,不要创建 `GenericWeatherField`、`RainField`、`WaveField` 等平行模型。 + +目标语义至少包含: + +```text +ParticleFieldSnapshot + common identity/grid/time + scalar? : width*height float + vector? : width*height*2 float interleaved UV + valid : width*height uint8 shared validity + vectorSemantics? : VELOCITY | DIRECTION +``` + +字段命名可结合现有代码做最小调整,但必须 generic,不出现 Wind/Rain/Wave/Tide 业务枚举。 + +## 5. v2 Descriptor / Plane Bundle + +本任务需要在 Core 层定义明确的 v2 descriptor 和 decode 输入形态。 + +推荐采用独立 plane bundle,而不是把三种数据重新塞回一个 ambiguous `std::vector`: + +```text +ParticleFieldPayloadBundle + scalar? bytes + vector? bytes + validity? bytes +``` + +具体 C++ 类型可根据当前接口选择 `std::optional>`、span/view 或等价简单结构,但不能引入大型新抽象。 + +必须保证: + +- vector plane expected bytes = `cells * 2 * sizeof(float)` +- scalar plane expected bytes = `cells * sizeof(float)` +- validity plane expected bytes = `cells`(uint8) +- descriptor 声明的 channel presence 与实际 payload presence 一致 +- 所有 float 必须 finite,除明确 noData 策略外不得接受 NaN/Inf +- shared validity 为 0 的 cell 可以允许 payload 内存在 finite placeholder/noData;validity=1 的 cell 对 present channel 必须是有效 finite 数据 +- 不允许 neither +- DIRECTION 但无 vector 必须 reject +- vector present 但缺 vector semantics 必须 reject(除 v1 normalize) + +## 6. v1 最薄兼容 ingress + +现有 `maplibre-particle-field/v1` 必须继续可读,但不要维护第二套 Runtime。 + +v1 只支持现有 vector-only: + +- `interleaved-uv` +- `float32-le` +- validity 从当前 U/V noData 规则派生 +- normalize 后:`vector present`、`scalar absent`、`VectorSemantics::VELOCITY` + +兼容层应该尽量放在 parser/adapter ingress,进入 Timeline 前就成为与 v2 相同的统一 snapshot。 + +不得给 v1 增加 scalar 字段、不得重新定义 v1 payload。 + +## 7. Identity / compatibility / hashing + +必须重新审查并调整: + +- `ParticleFieldSnapshot::isValid()` +- `isTimeInterpolationCompatibleWith()` +- `fieldIdentityChanged()` +- `sameFieldGpuContent()` + +要求: + +### isValid +不再硬编码 `fieldType == WIND` / `displayDomain == GLOBAL`。 + +必须验证至少:identity、generation、validTime、grid/bounds、channel presence、plane sizes、shared validity size、vector semantics 与 channel presence 的一致性。 + +### Timeline compatibility +T0/T1 必须至少保持: + +- width/height 相同 +- bounds 相同 +- scalar presence 相同 +- vector presence 相同 +- vector semantics 相同 +- plane encoding/layout 兼容 + +不得允许 scalar-only 与 vector-only 被当成同一 interpolation window。 + +### GPU content identity +虽然本任务不改 GPU,但 `sameFieldGpuContent()` 必须能够在未来正确区分 scalar/vector/validity 内容变化。 + +如果当前单 `fieldSha256` 已无法无歧义表示多 plane,应在 Core contract 中明确设计并实现最小 content identity,例如 per-plane hash 或一个明确的 aggregate hash。不得靠 fieldId/dataVersion 猜内容相同。 + +## 8. RasterArraySource host parser 范围 + +本任务只允许修改 host metadata/parser 到能够构造 v1/v2 Core descriptor/plane bundle 的程度。 + +若当前 `RasterArraySource::submitHostField(metadataText, payload)` 是唯一入口,允许在 C++ 层增加一个 **Core-only v2 overload / typed internal entry**,用于 tests/fixtures 直接提交 plane bundle。 + +但本任务禁止: + +- 修改 Java/Kotlin API +- 修改 JNI signature +- 修改 RN API +- 修改已发布 `.2` package + +因此 Android/RN 仍只能走现有 v1 入口是允许的;v2 正式跨 JNI ingress 留到 V3-05。 + +## 9. Local fixture / feed + +若 `local_particle_field_feed` 或现有 C++ fixture 是最合适的验证入口,可做最小扩展以生成: + +1. v1 vector-only fixture +2. v2 vector-only fixture +3. v2 scalar-only fixture +4. v2 scalar+vector fixture +5. invalid/neither fixture +6. channel mismatch fixture + +Fixture 只用于 Core contract 验证,不做 GPU 可视化。 + +## 10. 必做验证 + +不加入 Jest。 + +必须使用现有 C++ 测试体系或最小精确 executable/test,至少验证: + +- v1 Wind-style vector-only decode PASS,并 normalize 为 VELOCITY vector +- v2 vector-only PASS +- v2 scalar-only PASS +- v2 scalar+vector PASS +- neither REJECT +- scalar byteLength mismatch REJECT +- vector byteLength mismatch REJECT +- validity byteLength mismatch REJECT +- missing vector semantics REJECT +- DIRECTION without vector REJECT +- NaN/Inf in valid cell REJECT +- invalid cell 可按冻结策略安全接受 finite noData/placeholder +- T0/T1 compatible:same channel shape/semantics PASS +- scalar-only vs vector-only incompatible +- VELOCITY vs DIRECTION incompatible +- changed scalar/vector/validity content 不会被 `sameFieldGpuContent()` 误判为相同 + +执行规定的精确编译/测试,编译输出遵循全局 `$build-output-throttle`。 + +不得执行 Android Gradle、AAR、APK、ADB。 + +## 11. 回归保护线 + +本任务不得破坏: + +- 当前 v1 canonical Wind fixture parser +- Source-owned Timeline +- Runtime Field Window +- T0/T1/MIX +- Pause semantics +- OLD_T1→NEW_T0 reuse 的现有决策逻辑 +- normal rollover 时 `simulationRebuild=false / trailCleared=false` 的架构条件 +- WeatherColorLayer / RasterParticleLayer 分离 + +本任务不要求 renderer 能消费 scalar;在 V3-03 前 scalar snapshot 进入 renderer 应保持 fail-closed/unavailable,而不是伪造成 U/V。 + +## 12. 禁止事项 + +不得: + +- 修改 shader 或 shader generator +- 修改 `render_weather_color_layer.cpp` / `render_particle_validation_layer.cpp` 的渲染语义,除非纯编译适配且不改变行为;若确需适配必须在报告逐项列出 +- 增加 FieldValueSource +- 实现 DIRECTION particle movement +- 增加 Wave physics +- 修改 Android/JNI/Java/Kotlin +- 修改 RN package/API/version +- 修改 Test Host JS/TS +- 修改 WeatherV2 / NavSea +- 解析 NSFT/PMTiles +- 新增 provider/network/cache +- 设计 N scalar/N vector channel framework +- 做 JSI/zero-copy 重构 +- 执行 Jest +- 执行 Android build/install/ADB + +## 13. 文档输出 + +必须新增/更新: + +- `docs/50_Step记录/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_v1.md` +- `docs/报告/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex完成报告_v1.md` +- 追加 `粒子开发记录.md` + +若实施中对 STEP-065 冻结设计产生必要的小修正,必须更新 `docs/30_设计/MapLibreParticleLab_V3通用ScalarVectorField运行时架构设计_v1.md` 并明确原因;禁止静默改变设计。 + +所有文档使用中文。 + +## 14. 必做清单 + +结束前逐项报告“已完成 / 未完成 / 无法验证”: + +- [ ] 阅读规范、STEP-065 与当前实际源码 +- [ ] 确认 branch/HEAD/origin/dirty worktree +- [ ] 定义 V3 Core generic snapshot/descriptor/payload bundle +- [ ] 去除 Core validity 中 WIND/GLOBAL capability hardcode +- [ ] 实现 v2 vector-only +- [ ] 实现 v2 scalar-only +- [ ] 实现 v2 scalar+vector +- [ ] 实现 shared validity +- [ ] 实现 VectorSemantics contract +- [ ] 实现 v1 vector-only thin normalize +- [ ] 调整 interpolation compatibility +- [ ] 调整 content identity / sameFieldGpuContent +- [ ] 保持 Timeline/Runtime Window ownership 不变 +- [ ] 加入最小 Core fixtures/tests +- [ ] 完成精确 Linux/Core 编译/测试 +- [ ] `git diff --check` PASS +- [ ] 确认无 Android/JNI/RN/WeatherV2/NavSea 修改 +- [ ] 生成 Step、完成报告、追加开发记录 + +不得静默跳过。 + +## 15. Git 收尾 + +完成本任务规定修改与文档后,只提交本任务相关文件到当前 `particle/main` 并 push `origin/particle/main`。 + +禁止提交现有 STEP-062 用户修改、历史 untracked、build/cache/android/tgz。 + +必须使用显式文件列表 `git add -- `,禁止 `git add .` / `-A`。 + +完成报告必须记录: + +- source/function commit hash 与 message +- docs handoff commit(如有) +- push 结果 +- 最终 `HEAD` +- 最终 `origin/particle/main` +- 未完成/无法验证项 + +push 失败不得声称完成。 + +## 16. 完成门槛 + +STEP-066 只有同时满足以下条件才可 CLOSED / PASS: + +1. v1 vector-only 继续可 decode,并 normalize 到统一 V3 snapshot; +2. v2 vector-only/scalar-only/scalar+vector 三种组合全部 Core 验证通过; +3. neither、尺寸/semantic/finite/validity 错误全部 fail-closed; +4. Timeline compatibility 已按 channel presence + vector semantics 收紧; +5. content identity 不会把 plane 内容变化误判为 GPU same-content; +6. 未改 GPU 渲染语义、Android/JNI/RN、WeatherV2/NavSea; +7. 精确 Linux/Core 编译/测试与 `git diff --check` 通过; +8. Step/报告/开发记录完成; +9. scoped commit 成功 push 到 `origin/particle/main`。 + +下一步仅在 STEP-066 CLOSED / PASS 后进入 V3-03:Scalar GPU Texture + Generic Field Renderer。 diff --git a/docs/报告/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex完成报告_v1.md b/docs/报告/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex完成报告_v1.md index 291a0b251..b045dddf2 100644 --- a/docs/报告/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex完成报告_v1.md +++ b/docs/报告/STEP-066_MapLibreParticleLab_V3-02_CoreContract与ScalarSnapshotAdapter_Codex完成报告_v1.md @@ -33,6 +33,7 @@ Linux OpenGL `mbgl-test`、受影响 `source.test.cpp.o`、`mbgl-test-runner` ## Git 收尾 - Source/function commits:`379c9ed0e`(`core: add scalar vector field snapshots`)与 `6d1f3e051`(`core: preserve fixture times in generic snapshots`)。 -- Docs handoff commit:`b366a2d16`,`docs: record STEP-066 core contract`。 -- Push:成功,`particle/main -> origin/particle/main`(`d23ae2079..b366a2d16`)。 -- Push 后复核:`HEAD == origin/particle/main == b366a2d16170957937505e6ce05da541650dc20d`。 +- Docs commits:`b366a2d16`(`docs: record STEP-066 core contract`)与 `9a09278a2`(`docs: record STEP-066 push handoff`)。 +- 已完成 handoff commit:`9a09278a28170446fd3e180ae5f7c2d8d558972d`。 +- 已完成 push:`particle/main -> origin/particle/main`,先后为 `d23ae2079..b366a2d16`、`b366a2d16..9a09278a2`;当时复核 `HEAD == origin/particle/main == 9a09278a28170446fd3e180ae5f7c2d8d558972d`。 +- 本次仅补纳遗留任务书与本报告 Git 收尾回填;其 scoped commit/push 后最终 HEAD 以本次收尾回执为准。