Files
MapLibreParticleLab/docs/20_调查/STEP-114_FastPath安全准入与闭环判定_v1.md
tei 21a1081643
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
feat: prepare STEP-114 guarded fast smoke validation
2026-10-11 10:01:10 +09:00

10 KiB
Raw Permalink Blame History

STEP-114 Fast Path 安全准入与闭环判定 v1

日期:2026-10-11(JST)。结论:PARTIAL;安全子集源码与独立最小场景已交付,真实 Fast 尚未验收。

1. 基线、证据等级与阅读

Mac / Darwin 24.6.0 / x86_64,/Users/tei/dev/MapLibreParticleLab,particle/main@b02e54de3d45fcf612126ae8f037cba204f590ea。源码版本 13.6.1-particle.23,没有发行或改 Source Lock。实际模型 GPT-6.1-Sol / high 已从当前本地 rollout 的 turn_context 核实。

已读根 AGENTS、PARTICLE_BASELINE、项目规范全部八份、项目总则 README 与四份有效总则、本任务、STEP-112 调查/完成报告、STEP-113 完成报告/Step(含两轮 RDC 追加)、实际 Shared Core 和 Test App 源码。Integration 只读 AGENTS、README、WORKFLOW、TEAM_MODEL、C-001/C-002、Contract 版本规则、RFC-001/002/004、ADR-001、COORD-005 决议;不写跨项目文件,不改 RN/JS API/ABI。

SOURCE-PROVEN 表示本轮源码控制流;RETAINED-EVIDENCE 表示本机保留的旧 RDC JSON;IMPLEMENTED 表示已改源码;NOT RUN 表示未编译/运行。旧设备证据不是本轮改动的设备验收。

2. R 的真实 SourceType 与初建失败点

不能从 unknown-dependency 推断 source 一定是 CustomMVTVector:它还覆盖未知依赖、缺 revision 登记等情况。

本轮只读 artifacts/maplibre-particle/android-validation/step113/source-change-after-full.json:Native source 表为 mapple/raster、navsea_delivery/vector、org.maplibre.annotations/annotations、rn-weather-fields/raster-array、step113-source-probe/geojson。R0 [0,63) 的依赖为 mapple、navsea_delivery、tide;第2层 tide-spots 是 symbol、sourceId=tide,source 表却没有 tide。R0 的 sourceRevision=0、sourceReady=false、Build=0、fallback=unknown-dependency。

源码 style/conversion/source.cpp::convertVectorSource 创建 VectorSource;其构造函数指定 SourceType::Vector;RenderSource::create 创建 RenderVectorSource。因此该 Test App 的正式 PBF source 不是 CustomMVTVector。任务书列出的 CustomMVTVector 限制是独立安全约束,本轮完整保留。没有改旧报告,也没有补造 tide 数据、删原正式 PBF 层或修改服务 Style。

retainedSegmentSourceState 原先先读取 revisionFor,缺少 tide 的登记会返回 nullopt,从而提前返回默认 unknown-dependency。现在在读取 revision 前发现缺失 RenderSource 时明确返回 missing-source;本例的ready/stable=false、revision=0 不变。有旧tombstone记录的缺源也提前返回revision=0,而不暴露旧登记hash;它仍不得Build/Reuse,RevisionBook登记机制不变。这是诊断修正,不改变缓存准入。source 存在但无 revision、CustomMVTVector、未知 layer dependency 仍 fail-closed。

后续即使 Host 合法补齐 tide,R 仍包含大量 Symbol,Placement 首建阻塞不会自动消失。缺源与 Placement 是不同失败点。

3. 已支持的本地 GeoJSON/circle 子集

FAST_SMOKE 选择本地 GeoJSON 非空点与 circle R,不新增 source 类型授权。其现有追踪链:

输入或事件 源码链与保护
GeoJSON setGeoJSON GeoJSONSource::setGeoJSONData 替换 immutable Impl 并通知 SourceChanged;Fast non-camera signature 比较 sources;Full diffSources 推进全局 content 和本 source revision
Source 增删/同ID重建 createRenderTree 的 sourceDiff added/removed/changed 都 advanceSource;RevisionBook 保留 tombstone;PreparedTree 在 Full 更新对象前释放
异步 GeoJSON 数据/布局 RenderGeoJSONSource::update → GeoJSONTile::updateData;capturedData 和 weakPtr 防陈旧/销毁回调;GeometryTile correlationID 保护 pending;onLayout 每次更换 layoutResult 都 onTileChanged;RenderSource → orchestrator 推进 source-local revision 和全局 content,再 invalidate
Tile 未就绪/淡入 isLoaded、hasFadingTiles、source assessment、#17 与 R 稳定性检查继续保留
Layer paint/layout/顺序 immutable layers signature、per-R content fingerprint、resolved plan/topology;有 transition/repaint 仍阻止
Camera/viewport/pixelRatio #6/#7/#8、RetainedUnderlayKey 与 revision state;旧 texture 不能按新矩阵复用
Style reload styleLoaded/signature、配置/层序/Source 新身份、PreparedTree 生命周期保护;trace 在实际看到 loaded→false 时重置
Image/Sprite imageDiff、spriteLoaded、imageManager readiness、missing/unused image callbacks 推进全局 revision;#8 先捕获新 images 输入
Glyph/fontFaces/URL non-camera signature、glyph URL/font identity 追踪、onGlyphsLoaded 推进全局 revision;不删除资源门禁
Annotation #24 pending 检查、source/tile/图片变化与层表;实际 Symbol 继续纳入全场结构检查
context/reset/destroy markContextLost、Renderer.clearData 清 PreparedTree/trace,orchestrator 推进 revision;析构 detach observer 前排空 source/tile 工作;Test App 取消 callback、dispose runtime、删除自有 marker,MapView 原生命周期仍由 Activity 执行

这一闭环是现有实现的源码依据,不是本轮已跑出的 Source mutation/GPU PASS。异步过渡中 Full 也可能继续展示尚未更新的旧 bucket;要求 Fast 与同一时刻合法 Full 等价,而非承诺提交 API 后同步完成画面更新。成功布局后必须失效并正确重建;不可用两张稳定末态截图代替事件顺序证据。

R source policy、RevisionBook、GPU Build/Reuse 算法本轮零语义修改。新增 C++ 用例验证既有 revision/cache 状态机组合;unit 中显式推进 epoch/标记构建只用于状态机测试,不是实际 Native 帧或 GPU 成功的证据。

4. C、Annotation 与 Scene 聚合

continuousRangeSupportsParticleFastPath 要求每个 C layer 都 startsRetainedDynamicRange,并至少有粒子动画层。WeatherColor 与 RasterParticle 符合;普通 circle、Symbol、内建 Annotation Symbol 不符合。particlePreparedSceneSupported = retainedSupported && fastContinuousSupported,并要求单一 C。#22/#23 可以共享 C 不支持根因。

本轮没有修改 #22/#23、C GPU 复合流程、层序或 AnnotationManager。不能证明非粒子 C 与既有 Fast prepare/postRender 等价,故不放行。

独立 FAST_SMOKE 在确认 map.annotations.isEmpty() 后,仅从本场景 Style 删除自动生成且空的 org.maplibre.annotations.points layer,保留内建 source;若缺层或 remove 失败则 BLOCKED。Native annotation 更新规则未变,正式 PBF 五场景不删除该层。baseline 层序应为 background、R circle、weather-color、raster-particle,实际 JSON 仍需 RDC 核对。

ANNOTATION_BLOCKED 重新加载一个正常 Style,保留自动内建层并用现有 map.addMarker 加真实 marker;可单次修改其 position。内建 Symbol 位于 C,#22/#23 必须继续阻止 Fast。从该场景切回 baseline 时只删除本场景拥有的 marker,不能清除其他 Annotation。若存在其他 Annotation,baseline 拒绝启动。该场景转换含合法 Style reload,不是生产 Annotation 零重载支持的证明。

5. Placement:安全局部修复与 BLOCKED

正常 Continuous Full:placementIsRecent=false 则 placeLayers/commit,placementChanged=true;recent=true 则 setPlacementStale,controller.hasTransitions=true;关闭 transitions 时正常 Full changed=true、fade=1。含结构性 Symbol 的 R 无可证明的首次 Build 稳定窗口。

本轮保持 Symbol R 的三项 gate、scene placementStable、全图碰撞、fade/transition 和跨 source 规则。完整 GPU symbol 输入、bucket/atlas/opacity/duplicate/anchor 的结果证书仍不存在;建立它需要独立结果签名或更大生命周期设计。Symbol R 准入修复 BLOCKED,不能删除 changed/stale/fade 条件。

唯一行为修复限定于完整非空层表没有任何结构性 Symbol:此时 controller 的 stale/transition 没有 Symbol 像素消费者,单独阻止 #13 不代表画面可能变化。particleFastPathHasPlacementTransition 按完整 Style 表检查;隐藏/空数据的 Symbol 与 Annotation Symbol 一律保守保护。production 还核对层表数量与 renderLayers 数量,不一致保持原 transition;空表也保守保留。

这是 Shared Core 内部实现优化,无 Android/iOS 分叉,不新增控制 API、不禁止正常 Full Placement、不修改原始 controller。其余23项 Gate、source/cache/scene 条件全部继续生效。新增 Symbol 尚未进入旧表时,immutable layers 的 non-camera signature 不相等,且 Annotation pending 单独阻止 Fast;Full 更新后表重新包含 Symbol。未取得新层表前不得只凭这个 helper 放行。

反例边界:同场只要存在一个隐藏 Symbol、空 Symbol、C Annotation Symbol,仍使用原 controller transition;缺层表、source mutation、未完成 tile layout、image/glyph 更新、camera/viewport、style reload、debug/context 问题都不能被本修复抵消。未来若引入新的 Placement-capable layer 类型,应先扩展结构检测及测试;当前源码仅 Symbol 的 LayerTypeInfo 使用 CrossTileIndex::Required。

6. 实施结果、验证方案和限制

  • IMPLEMENTED:缺源明确诊断、无 Symbol 场景的 #13 限定检查;3个非 Jest C++ 用例源码;独立4场景及 UI/Intent、真实 Native 快照与操作前后自动采样;中文文档和追加记录。
  • 保留 fail-closed:CustomMVTVector、未知 revision、缺源;非粒子 C;所有 Symbol R Build/Placement 保护。
  • NOT RUN:Native/Kotlin 编译、C++ 测试、Android build/设备/GPU/Fast 命中、像素对照、性能、iOS Metal 设备验证。
  • 保留:正式 STEP-113 五个 PBF 场景实现原样、STEP-102 fixture 原样、STEP-110/111 未跟踪文件原样。新增菜单明确标识独立 smoke,不冒充63/113层等价。

验收步骤和命令见 docs/60_测试/STEP-114_独立FastSmoke场景与RDC验收_v1.md;Native 定向命令也直接写在本轮完成报告。baseline 必须取得真实 Native Full>0、Fast 增长、CacheBuild>0、Reuse 增长、completed fast-rendered、24 PASS/knownMask 完整/decisionMismatch=0;否则维持 PARTIAL,不能标 Fast Path 已修复。

Source/Image/Camera/缓存禁用/Reload 的反向证据需保存事件前/提交后/100/500/1500ms 快照,必要时以更早的精确帧复核;未捕获瞬间 gate 不能用计数猜测。后台/恢复/Teardown、Symbol/Annotation 与原 PBF 回归、双平台共享源码独立检查仍为 RDC/用户待执行项。