test: record STEP-117 PBF R cache admission blockers
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
137
docs/20_调查/STEP-117_PBF_R首次缓存Build安全证据_v1.md
Normal file
137
docs/20_调查/STEP-117_PBF_R首次缓存Build安全证据_v1.md
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# STEP-117 PBF R 首次缓存 Build 安全证据 v1
|
||||||
|
|
||||||
|
日期:2026-10-11(JST)。结论:**安全准入 BLOCKED;本轮保持 missing-source 与 Symbol placement fail-closed,交付七项非 Jest C++ 回归源码。没有实现 R 零贡献准入或 Symbol 结果证书,没有新的 Native/Android PASS。**
|
||||||
|
|
||||||
|
## 1. 工作区与证据等级
|
||||||
|
|
||||||
|
Mac.lan / Darwin 24.6.0 / x86_64,仓库 `/Users/tei/dev/MapLibreParticleLab`,`particle/main@43e5f5b91598b9c3d3f1c788052d4bbd2d616668`。起点 tracked clean;STEP110/111 与 STEP117 任务书未跟踪。实际模型 GPT-6.1-Sol(gpt-6.1-sol)/ high,由当前 rollout `01a12912-9a0c-7712-9624-793f04b3f681` 的 `turn_context.model/effort` 核实。Integration 本地只读 HEAD 为 `80667d6c343411d03a760425438e3d292f452118`,没有跨仓写入或远端操作。Android VERSION 仍 `13.6.1-particle.23`。
|
||||||
|
|
||||||
|
已读根 AGENTS、PARTICLE_BASELINE、全部项目规范、总则 README 与四份有效总则、STEP117 任务、STEP112–116 关键任务/调查/Step/完成报告/验收文件;Integration AGENTS、instructions、README、WORKFLOW、TEAM_MODEL、contracts/rfc/adr/status/compatibility。本报告用以下等级区分事实:
|
||||||
|
|
||||||
|
- **源码事实**:当前 HEAD 的控制流和所有权;不等同运行安全证明。
|
||||||
|
- **保留实测**:STEP116 原设备 JSON 与报告;不是 STEP117 新二进制。
|
||||||
|
- **测试源码**:本轮已写、全部未编译和未运行。
|
||||||
|
- **待证明设计**:尚未实现的证书、影子比较与平台验证。
|
||||||
|
|
||||||
|
## 2. 原 120 帧重新核对
|
||||||
|
|
||||||
|
原文件:`artifacts/maplibre-particle/android-validation/step113-retest-20261011_121308/static_rc/native-full.json`;274,693 字节;SHA-256:`cd491d2acca97119f1d4f2d6f77eb7b229c17b90d4be1181a59202308429b219`。本轮只读解析完整 JSON,逐帧复算 failMask,不修改或纳入 Git。
|
||||||
|
|
||||||
|
实测源码 `c48a72a9d492ea0d05e4d58464f9643453158d50`,APK SHA `a8b7f4e0f8e026bde8835e18a04876062be84cce3a3749a511cb08605d9f8a35`,设备 FZG1-2 / `192.168.200.139:5555`。STEP116 报告记录安装 SHA 相同、90.008 秒 FastDelta=0 / FullDelta=920。本轮未接设备。
|
||||||
|
|
||||||
|
原正式 63 基础层保留;Native 65 层,R[0,63)、C[63,65);C 仅 `rn-weather-color`、`rn-weather-particles`。正式 Style fingerprint 为 `e0f9c2d1df38ae5d5953b561c52efe2f8590336de80b988e1d2935580d30b996`。生产 sources JSON 只有 mapple/raster 与 navsea_delivery/vector;Native 另有 org.maplibre.annotations/annotations、rn-weather-fields/raster-array。没有 tide。R index=2 的 `tide-spots` 为可见 Symbol,source/source-layer 均为 tide。
|
||||||
|
|
||||||
|
| 实测项 | 复核结果 |
|
||||||
|
|---|---|
|
||||||
|
| 120 帧范围 | sequence 5631–5750;119 completed Full / 0 Fast / 1 pending |
|
||||||
|
| 24 Gate | 120/120 knownMask=0xffffff、decisionConsistent=true;decisionMismatch=0 |
|
||||||
|
| #3 / #4 / #23 | 各失败120帧 |
|
||||||
|
| #12 / #13 | 各失败105帧 |
|
||||||
|
| #22 | 最近窗口失败0;生命周期累计6,不称启动全程零失败 |
|
||||||
|
| R cache | Build=0 / Reuse=0;textureCreate=0 / compositeCreate=0;fallback=missing-source |
|
||||||
|
| R dependency | mapple、navsea_delivery、tide;missingSourceIds=[tide];placementGatePassed=false |
|
||||||
|
| pre Placement 状态 | 105帧 false/非零/true;15帧 true/0/false(changed/fade/transition) |
|
||||||
|
| post Placement 状态 | 104帧 false/非零/true;15帧 true/0/false;pending 的 post=null |
|
||||||
|
| fade 范围 | pre/post 均为0至0.9914085268974304 |
|
||||||
|
|
||||||
|
这解释了一个容易误判的现象:15帧的 #12/#13 通过,并不建立 R cache;这些帧仍有 #3/#4/#23,且上一完成树的 changed=true。Fast #13 使用当前 controller transition,R 首建使用当前 Full 的三条件,二者取样点与职责不同。不得拼接 pre 与另一帧 post 来造出通过状态。
|
||||||
|
|
||||||
|
## 3. 缺 tide:新 RenderItem 为零与 GPU 零贡献的区别
|
||||||
|
|
||||||
|
### 3.1 Style 与 Source 创建
|
||||||
|
|
||||||
|
`src/mln/style/style_impl.cpp::parse/addSource/addLayer` 先加入 parser.sources,再加入 layers。addLayer 在 source 存在时检查兼容性;source 不存在时仍保留原层(源码 TODO verify source)。这正是原 Style 能保留 tide-spots 而没有 tide 的路径。removeSource 会拒绝仍被 Layer 引用的 source;同名恢复不能依靠违法删除调用,合法整份 Style 更换及后续创建也必须覆盖。
|
||||||
|
|
||||||
|
`RenderSource::create` 根据真实 SourceType 创建 RenderVectorSource、RenderRasterSource、RenderGeoJSONSource 等。原 navsea_delivery 是普通 Vector,不能将它归因为 CustomMVTVector;后者的未知 revision 准入限制继续保留。
|
||||||
|
|
||||||
|
### 3.2 Full 的注册、停用和绘制时序
|
||||||
|
|
||||||
|
| 环节 | 当前源码事实 | 能支持的结论 / 不能支持的结论 |
|
||||||
|
|---|---|---|
|
||||||
|
| createRenderTree source/layer 匹配 | `render_orchestrator.cpp` 在已有 sourceImpls 的外循环中收集 LayerRenderItem;缺源层不匹配,updateList 初始false | 本轮缺源层无新 RenderItem;不能单凭此证明旧 group 已移出 registry |
|
||||||
|
| renderability 更新 | 每次 source 更新后比较 isLayerRenderable 与 updateList,调用 markLayerRenderable | 有 source 的正常 Full 能排队停用;所有 sources 为空时此循环不执行,不能推广为任意状态的清理保证 |
|
||||||
|
| RenderLayer::markLayerRenderable | 更新 CPU bool;activateLayerGroup 创建 Add/RemoveLayerGroupRequest | bool=false 不是 request 已执行的证明;该方法没有清除 drawables、renderTilesOwner、placementData |
|
||||||
|
| RenderSymbolLayer 停用 | 同时为普通 group 与 collisionTileLayerGroup 排队停用 | 需覆盖两类 group;不能仅数普通 RenderItems |
|
||||||
|
| layerRemoved | RenderLayer 调用虚方法 removeAllDrawables;Symbol 的实现清除两类 group 的 drawable,然后停用 | 删除 Layer 与缺源导致不 renderable 的生命周期不同,不能互相替代 |
|
||||||
|
| processChanges | 移动 pendingChanges 后逐个 execute,RemoveLayerGroupRequest 删除对应 registry entry | 删除 registry 不等于销毁 Layer 所持 group/bucket/atlas;指针仍可能持有旧数据 |
|
||||||
|
| Renderer Full | tree.prepare → source/layer upload → updateLayers → processChanges → cache评估 → tweakers/group upload → Build/live draw → present/endFrame | Cache 评估位于处理 changes 之后,但此前没有生成覆盖旧数据与成功提交的零贡献证书 |
|
||||||
|
| Cache Build | R 使用 orchestrator 的 layer group range 双 pass;没有只遍历新 LayerRenderItem | 缺源层无 RenderItem不等于range里无旧group;需要独立registry与层身份审计 |
|
||||||
|
|
||||||
|
本轮实际读取 `render_layer.hpp/.cpp`、`render_symbol_layer.hpp/.cpp`、`change_request.cpp`、`render_orchestrator.hpp/.cpp`、`render_tree.hpp`、`renderer.cpp`、`renderer_impl.cpp`、`retained_underlay_cache.hpp/.cpp`。当前 src/include 中未找到名为 ResourceManager 的类;实际资源所有者是 gfx Context/backend、RetainedUnderlayCache 的 offscreen/composite、LayerGroup/Drawable 与 RenderTile bucket/atlas,以及 DynamicTextureAtlas/ImageManager/GlyphManager。GL 的 `Texture2DPool`(`src/mln/gl/resource_pool.hpp`)管理纹理复用,不提供“某个缺源层本帧零绘制”的语义证书。
|
||||||
|
|
||||||
|
**限定的正向事实**:新加载且从未获得 source 的 tide-spots,没有匹配 RenderItem;新 RenderLayer 默认 isRenderable=false。**仍缺的事实**:原设备 JSON 没有 per-layer registry identity、两类 group 的已执行停用、旧 drawables/tiles/placementData 清空和成功 Full 提交代次。不能从其他 sources 已 Loaded、cache textureCreate=0 或 pending-changes Gate=PASS 推出这些条件全部成立。尤其 task 要求“无旧 Renderable 数据”,单纯停用并不满足它。
|
||||||
|
|
||||||
|
### 3.3 失效链已存在,但不存在缺源的受控依赖状态
|
||||||
|
|
||||||
|
`retainedSegmentSourceState` 在读 revision 前要求每个 sourceId 存在;缺失即返回 ready=false/stable=false/revision=0/reason=missing-source。renderSegmentDependencies 从完整层表收集 source 和 Symbol 全局前提,不因隐藏/空桶删依赖。RevisionBook 没有为从未出现的 tide 登记;删除墓碑可保留,但不代表当前 source 存在或 loaded。
|
||||||
|
|
||||||
|
`sourceDiff.added/removed/changed` 增加 content revision 与对应 source revision,先删/建 RenderSource,再 update。同名同类型但 immutable Impl 改变属于 changed。Fast 的 non-camera signature 比较 immutable sources 身份,下一帧在 createRenderTree 之前拒绝旧输入;已有 PreparedTree 在 Full 创建前释放。异步 onTileChanged 增加全局 content 和局部 source revision并 invalidate。Image/Glyph/Style/Context 的全局 epoch、层身份 fingerprint、camera/viewport key也各自保留。
|
||||||
|
|
||||||
|
因此“同名 source 出现后可拒绝旧 Fast”的机制已有源码依据;**不能由此反推不存在的 source 可合法登记成 loaded/stable/零 revision**。新的缺源状态需要绑定 source absent identity、完整层集合、应用后 registry/旧对象状态和成功绘制代次;source 出现、替换、异步 layout、context改变必须撤销它。当前没有这些存储和核验,不实施空依赖准入。
|
||||||
|
|
||||||
|
## 4. Symbol 首次 Build 的安全根因
|
||||||
|
|
||||||
|
### 4.1 两个 Full 分支和第二重 scene 锁
|
||||||
|
|
||||||
|
`PlacementController::placementIsRecent` 按 commitTime+updatePeriod 判断;transitions关闭则总返回false。Continuous `createRenderTree`:
|
||||||
|
|
||||||
|
1. 不 recent:placementChanged=true;Placement::create → placeLayers → commit;setPlacement 清 stale,CrossTileSymbolIndex prune 与 source fading 更新。
|
||||||
|
2. recent:placementChanged=false;setPlacementStale;controller.hasTransitions 在 enabled 时优先因 stale 返回true。
|
||||||
|
|
||||||
|
`renderSegmentPlacementGatePassed` 对结构性 Symbol 要求 `!changed && fade==0 && !controllerTransition`。每个分支至少违反一项。关闭 transitions 时 Full 为 true/1/false;duration=0但enable=true时fade=1,recent分支仍stale。等待更久、改300/30ms阈值或关闭fade无法提供证书。
|
||||||
|
|
||||||
|
`renderer_impl.cpp` 还有独立保护:retainedPlacementStable、retainedStaticStable、retainedSupported,以及 `particlePreparedSceneSupported=retainedSupported && fastContinuousSupported`。只放宽 per-R Gate不会使 #23 安全通过;只放宽 #13也不能自举 Build。Fast 成功后 prepareParticleFastFrame 才重置树的 changed/fade;调用它来准备第一次 Build会循环假定尚不存在的安全证据。
|
||||||
|
|
||||||
|
### 4.2 CPU 结果不等于最终 GPU 输入
|
||||||
|
|
||||||
|
读 `placement.cpp::commit/updateLayerBuckets/updateBucketOpacities/updateBucketDynamicAttributeData`、CrossTileSymbolIndex、SymbolBucket::updateVertices、SymbolLayerTweaker 与 DrawableAtlasesTweaker,以及 GL/Metal symbol shader:
|
||||||
|
|
||||||
|
- commit 以每个 crossTileID 的 text/icon placed 状态更新 opacity;显隐未变可继承旧 fadeStartTime。controller transition=false不等于所有桶在GPU中已上传或与旧帧等价。
|
||||||
|
- RenderTreeImpl::prepare 更新 bucket opacity/dynamic data;SymbolBucket 将 uploaded、placementChangesUploaded、dynamicUploaded 标记为false。SymbolBucket::upload 的标记不是成功GPU Drawn R的证书。
|
||||||
|
- opacity处理 duplicate、默认allow-overlap、justReloaded、variable anchors、orientation、text/icon配对;沿线重投影与camera相关。碰撞为全局 Placement,并可能跨 source/段产生依赖。
|
||||||
|
- shader实际使用 `clamp(baseOpacity ± symbolFadeChange,0,1)`,再乘paint opacity。fade=0既可能为全透明新符号,也可能为已显示符号;fade非零也可能因clamp不再改变像素。用==0或>=1替代逐输入等价均不足。
|
||||||
|
- LayerTweaker 还使用tile/label/coord矩阵、size binders、paint插值、纹理尺寸与shader变体;DrawableAtlasesTweaker绑定glyph/icon atlas和sampler。
|
||||||
|
- retainedRangeContentFingerprint 只散列 layer.baseImpl 指针与index;它不包含 placement结果、opacity buffer、bucket身份、atlas纹理、uniform最终值。Source revision也不替代这些内容。
|
||||||
|
- Build成功计数来自双pass编码无捕获异常、finishBuild与markBuildSucceeded;随后主buffer present提交。现有实现没有完整的 per-R GPU输入证书或设备completion fence记录。将编码成功说成GPU执行完毕属于证据越界。
|
||||||
|
|
||||||
|
### 4.3 可继续的设计边界与反例
|
||||||
|
|
||||||
|
| 候选条件 | 反例 / 缺少的证明 |
|
||||||
|
|---|---|
|
||||||
|
| source loaded、无手势、静止90秒 | changed/stale循环继续;异步glyph/tile/image可改变结果 |
|
||||||
|
| Placement placed布尔相同 | opacity方向/基值、duplicate、anchor/orientation或dynamic vertices可不同 |
|
||||||
|
| fade=0且controller=false | 实测15帧changed=true,Build仍拒绝;刚出现符号可能base opacity=0 |
|
||||||
|
| 当前 RenderItems 为空 | 旧group可能仍在registry或旧数据留在RenderLayer;pending请求可能未执行 |
|
||||||
|
| layer fingerprint/source revision相同 | 不能区分同桶的dynamic opacity/atlas/uniform变化 |
|
||||||
|
| 两张末态截图看起来相同 | 未捕获变更瞬间、碰撞受害段及GPU提交代次,不能建立持续复用不变量 |
|
||||||
|
|
||||||
|
待证明证书至少应覆盖:R层身份/层序和drawable集合;bucket/tiles/crossTileID及跨段碰撞结果;text/icon显隐、opacity方向/基值、dynamic vertices、沿线/variable placement;paint/layout revision;glyph/image/atlas/shader/uniform版本;projection/camera/viewport/pixelRatio;context generation;已应用ChangeRequests及异步content epoch。只能在正常Full完成prepare/upload/tweakers、真实Build成功提交且资源一致时绑定,任何不一致先Full+invalidate/rebuild。不能只加入一个“结果稳定”bool。
|
||||||
|
|
||||||
|
这涉及 Placement→Bucket→Drawable/Atlas→Renderer提交生命周期的跨层实现,当前没有足够设备/图像证据保证安全。本轮停止该准入实现,不删或强制置假 placementChanged、symbolFadeChange、controllerTransition,不改24Gate。
|
||||||
|
|
||||||
|
## 5. 七项测试源码及真实覆盖限制
|
||||||
|
|
||||||
|
两个既有 test/CMakeLists.txt 已登记的测试文件内新增 `Step117Safety.*`,无需改构建表,全部 NOT RUN:
|
||||||
|
|
||||||
|
| 用例 | 实际测试目标 | 不覆盖的事实 |
|
||||||
|
|---|---|---|
|
||||||
|
| RealPlacementControllerHasNoFirstSymbolBuildWindow | 用实际Controller/Placement::create/placeLayers/commit执行120个逻辑时刻;两个分支均fallback,Build/Reuse为0 | 空桶生命周期最小复现,无原PBF碰撞/GPU |
|
||||||
|
| RealPlacementDisabledOrZeroDurationIsNotAResultCertificate | 实际enable=false与duration=0/enable=true,fade=1、stale行为继续保护 | 没有禁用生产fade |
|
||||||
|
| MissingAndSameNameRestorationCannotReuseAnOldCache | 缺源→创建→状态机构建/复用→删除墓碑→同名恢复必须新Build | 模拟status与markBuildSucceeded仅为cache状态机,无GPU成功 |
|
||||||
|
| CameraStyleAnnotationAndContextRequireRebuildBeforeReuse | camera/viewport/content/topology/config变化经过实际revision tracker和cache,使旧cache无效且#3/#4失败 | epoch输入是模拟,未触发真实Annotation/camera设备事件 |
|
||||||
|
| RealMissingSourceTreeHasNoRenderItemButStillFailsClosed | 真实createRenderTree:缺源Symbol零RenderItem/零group仍missing-source;实际sourceDiff创建、同名替换、移除;layer fingerprint保持不变而revision变化 | 使用step117-source无数据GeoJSON测试对象,未改生产tide;无旧GPU对象场景 |
|
||||||
|
| QueuedGroupRemovalIsNotAppliedUntilProcessChanges | 两个测试group实际进入registry,真实Remove请求入队前后遍历差异与pending变化 | 测试group代表两类生命周期,不是实际Symbol collision group或GPU Draw |
|
||||||
|
| RealAsyncCallbacksAndContextStyleCleanupAdvanceContentEpoch | 实际Tile/Glyph/Image observer分派、markContextLost/clearData推进content epoch;旧content输入单独命中#5 | 事件在测试线程注入,无实际网络并发/完整Renderer/设备 |
|
||||||
|
|
||||||
|
未新增Jest,未编译或运行这些测试。生产 src/include、所有Gate/计数、Android场景和63层零修改。既有Annotations.Step116图像用例保留;新测试不代替glyph/tile并发、跨段collision、old GPU drawable清理或Full/Fast像素验证。
|
||||||
|
|
||||||
|
## 6. 具体阻塞与协调需求
|
||||||
|
|
||||||
|
| 编号 | 无法继续的状态 | 应由谁处理 / 需要的产出 |
|
||||||
|
|---|---|---|
|
||||||
|
| B1 缺源零贡献 | 当前只有absent Source与新RenderItem缺席;无应用后双group/旧drawable数据/提交世代证书;revision=0不能登记为有效 | Shared Core制定absent依赖内部状态及销毁/禁用证书;Android/Metal分别验证初始缺源、曾有旧数据、合法Style替换、同名恢复 |
|
||||||
|
| B2 Symbol首次Build | 重算changed、recent stale;所有可达Full状态都不满足现有准入;无最终GPU结果等价/时间不变证书 | Shared Core提供跨层结果证书设计与影子比较实现任务;先影子不放行,证明后才讨论受控准入;粒子负责人组织双平台审查 |
|
||||||
|
| B3 正式tide语义 | 生产Style宣告tide-spots但sources不含tide;本仓库不能自行补业务数据、改服务器或删层 | Integration协调NavSea/Style所有者明确是否属于合法宿主动态注入、何时提供真实source及身份;改变公共缺源语义才走RFC/ADR,纯内部优化不强制新Contract |
|
||||||
|
| B4 独立验证 | 本轮没有Native编译、测试或设备新证据;STEP116历史Mac配置缺libuv | RDC复核当前环境、执行定向测试,首错保留;用户明确授权后由RDC/普通Terminal集中Android验收 |
|
||||||
|
|
||||||
|
B1/B2应形成具体设计/实现任务,不通过业务开关、假tide、删Symbol、改24Gate或STEP114烟测绕过。Integration是协调入口,本轮不向他人发消息、不写跨仓文件。当前代码阶段止于测试和证据交付;详见STEP117验收计划。原目标 Build>0、Reuse>0、FastDelta>0仍未完成。
|
||||||
26
docs/40_任务/STEP-117_原PBF_R段首次Build与Fast安全准入_Codex任务_v1.md
Normal file
26
docs/40_任务/STEP-117_原PBF_R段首次Build与Fast安全准入_Codex任务_v1.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# STEP-117 原STEP-113 PBF的R缓存首次Build与Fast安全准入
|
||||||
|
|
||||||
|
## 用户目标、代码基线和约束
|
||||||
|
2026-10-11 用户要求继续 STEP-116 实机之后的实际修复:原专用Android Test App STEP-113 STATIC_RC,保留所有正式PBF 63基础层,不代换成STEP114简化FAST_SMOKE。真正验收须Native Cache Build>0、Reuse>0、FastDelta>0,同时画面正确、24Gate mismatch=0、异步更新fail-closed。若现有证据不能安全准入,必须保留真实阻塞并如实标 PARTIAL/BLOCKED,禁止伪造Fast或PASS。
|
||||||
|
|
||||||
|
Mac repo /Users/tei/dev/MapLibreParticleLab 当前particle/main起点43e5f5b91598b9c3d3f1c788052d4bbd2d616668。Integration /Users/tei/dev/navsea-particle-integration origin/main同步至80667d6c343411d03a760425438e3d292f452118。模型固定 GPT-6.1-Sol High (gpt-6.1-sol, model_reasoning_effort=high),不得升级。先读AGENTS、PARTICLE_BASELINE、docs/00_项目规范、docs/00_项目总则README与全部4份当前总则、Integration instructions/README/WORKFLOW/TEAM_MODEL和contracts/rfc/adr/status/compatibility。阅读STEP112-116全部关键任务记录和实际源码。Shared Core代码仍同时服务Android/iOS,本次限平台中性的内实现与Test App诊断,不改跨平台公开API/ABI/RN/JNI合同、不改NavSea/iOS/外部PBF服务器。若改动需要新公共contract或跨项目决定必须停止该部分,并在报告中指出应由Integration协调RFC/ADR,不自行做新平台业务语义。
|
||||||
|
|
||||||
|
## 已测事实,一定先读取实机JSON和报告
|
||||||
|
docs/60_测试/STEP-116_FZG1_原PBF实机验收结果_20261011.md。原完整JSON:artifacts/maplibre-particle/android-validation/step113-retest-20261011_121308/static_rc/native-full.json,SHA=cd491d2acca97119f1d4f2d6f77eb7b229c17b90d4be1181a59202308429b219。
|
||||||
|
|
||||||
|
STEP116新APK源码c48a72a9,设备192.168.200.139:5555:原STATIC_RC已65层,原正式63层保留,C[63,65)仅WeatherColor与RasterParticle,#22最近120帧失败0。R[0,63)缺Source=tide,原style tide-spots Symbol引用tide;真实sources只有mapple:raster、navsea_delivery:vector、org.maplibre.annotations、rn-weather-fields。R Cache Build0 Reuse0、fallback=missing-source、placementGatePassed=false;24Gate最近120帧 #3/#4/#23失败120、#12/#13失败105、mismatch0,119Full/0Fast/1pending。90秒FastDelta=0、FullDelta=920。STEP116修好的空SDK Annotation条件和原63层定义不许回退。
|
||||||
|
|
||||||
|
## 必做实现/根因研究
|
||||||
|
1. 读 Style/Source creation、RenderOrchestrator::createRenderTree及LayerRenderItem、RenderLayer group disable/activate/processChanges、ResourceManager、sourceDiff、retainedSegmentSourceState、RenderSegmentRevisionBook、contentFingerprint、GPU提交。缺tide只可在具有可检查的零实际GPU绘制/无旧Renderable数据且同名Source添加/重建时完整Full+invalidate证书时作为缓存零贡献依赖;不得补假tide、删tide-spots、通过忽略revision/ready来放宽。无法证明则保持missing-source fail-closed,报告具体证据。
|
||||||
|
2. 读PlacementController::setPlacement/placementIsRecent/hasTransitions、Placement::placeLayers/commit/fade/opacities、RenderSymbolLayer/SymbolBucket::updateVertices、RenderTree::prepare、Renderer::render Full与Cache Build及particleFast path判定。当前全帧重算时placementChanged=true、不重算时stale=true,fade不断非零;使首Build一直0。若能建立与成功提交的GPU Drawn R精确等价的结果证书,才受控放宽首次缓存,包括crossTile collision/placement、glyph/image/atlas、dynamic opacity、tile/source/layout revision、projection/camera/viewport、GPU context、异步ChangeRequests;任何变更必须Full/rebuild。不能将任何placementChanged、symbolFadeChange或controllerTransition强制false或删除24Gate。若需跨层较大重写无法保证安全则保留Gate报告BLOCKED。
|
||||||
|
3. 原STEP113的正式63基础层完全保留,C空Annotation受控修复保留;旧五场景及SOURCE_CHANGE的负例保留。必要最少的Native诊断/Android测试入口增强可以做,但不可改变真实Fast计数/24Gate判定或把FAST_SMOKE当PASS。
|
||||||
|
4. 以一次未来Android用户授权的RDC标准完整build/install测试为目标批量实现可证明安全的改动;提供非Jest C++测试源码,覆盖缺源零绘制/新增同名Source后失效、Symbol placement/symbol fade、异步glyph/tile/style/annotation/camera/context改变时fallback。不能将没有运行的测试标PASS。Codex不要运行大编译/Gradle/ADB/CMake/Ninja/Bazel/Jest、安装、commit/push,由RDC独立执行。
|
||||||
|
|
||||||
|
## 必做中文交付文件
|
||||||
|
- 真正实施的源文件、非Jest测试源码;必要Test App README更新。
|
||||||
|
- docs/20_调查/STEP-117_PBF_R首次缓存Build安全证据_v1.md:真实源码/原设备JSON,GPU生命周期与Source缺失和Symbol placement安全边界、各项状态、设计/反例。
|
||||||
|
- docs/50_Step记录/STEP-117_原PBF_Fast缓存准入_v1.md:改变、阶段验收、未执行与下一步。
|
||||||
|
- docs/60_测试/STEP-117_FZG1_原PBF真实Fast验收计划_v1.md:严格原STEP113 STATIC_RC >=90秒、新APK源码SHA/设备SHA、Cache Build/Reuse/Fast及120帧24Gate、原63层与C、Source/Style/CAMERA mutation和用户画面、失败停止。
|
||||||
|
- docs/报告/STEP-117_原PBF_Fast缓存准入_Codex完成报告_v1.md:模型全名档位、源码文件/公共ABI不变、证据、静态检查、当前BLOCKED和RDC实际测试步骤,commit/hash留RDC回填。
|
||||||
|
- 粒子开发记录.md 末尾中文追加,必要README/说明文档修正。
|
||||||
|
- git diff --check、静态API一致性与中文交付核查。禁止git add -A/git add ./git reset --hard/git clean,不触碰用户两份保护未跟踪文件 docs/40_任务/STEP-110_...和STEP-111_...,保留原Git忽略设备JSON。未经RDC工具真实返回,不得自称Native/Android PASS。最后停止交RDC进行独立代码审计、scoped commit/push/remote verification及一次集中Android build/installation/test。
|
||||||
53
docs/50_Step记录/STEP-117_原PBF_Fast缓存准入_v1.md
Normal file
53
docs/50_Step记录/STEP-117_原PBF_Fast缓存准入_v1.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# STEP-117 原 PBF Fast 缓存准入 v1
|
||||||
|
|
||||||
|
日期:2026-10-11(JST)。状态:**阻塞**。调查与七项非Jest C++回归源码已交付;安全准入、真实Build/Reuse/Fast仍未完成。
|
||||||
|
|
||||||
|
## 目标与基线
|
||||||
|
|
||||||
|
原STEP113 STATIC_RC完整63基础层保持不变,以成功提交的GPU R结果证据解决缺tide和Symbol首次Build,达到Build>0、Reuse>0、FastDelta>0;证据不足保持fail-closed。
|
||||||
|
|
||||||
|
Mac.lan,`/Users/tei/dev/MapLibreParticleLab`,`particle/main@43e5f5b91598b9c3d3f1c788052d4bbd2d616668`;实际GPT-6.1-Sol(gpt-6.1-sol)/high已核实。Integration只读HEAD `80667d6c343411d03a760425438e3d292f452118`。VERSION `13.6.1-particle.23`,未改发行坐标。起点tracked clean,STEP110/111及117任务书未跟踪。
|
||||||
|
|
||||||
|
## 必做项与结果
|
||||||
|
|
||||||
|
- [x] 读取规则、当前任务/基线、STEP112–116关键资料与相关实际依赖源码。
|
||||||
|
- [x] 回读原274,693字节JSON并验证SHA,逐帧复算120帧24Gate与Placement状态。
|
||||||
|
- [x] 审查sourceDiff/revision/fingerprint、双group注册/停用、prepare/upload/Build/提交生命周期。
|
||||||
|
- [x] 分别说明缺源零贡献与Symbol最终GPU结果证书的缺口、反例及协调责任。
|
||||||
|
- [x] 保留fail-closed、原63层、STEP116空Annotation修复、原五场景及SOURCE_CHANGE负例。
|
||||||
|
- [x] 新增七项Step117Safety C++测试源码,复用已有构建登记。
|
||||||
|
- [x] 落盘调查、验收计划、完成报告,末尾追加开发记录。
|
||||||
|
- [ ] 建立可核验的缺源零GPU贡献与无旧Renderable数据证书,准入缓存。
|
||||||
|
- [ ] 建立Symbol最终GPU结果等价证书,解决首次Build。
|
||||||
|
- [ ] RDC独立编译并运行定向C++测试。
|
||||||
|
- [ ] 原STATIC_RC新制品≥90秒,Build/Reuse/Fast增长、完整120帧、Mutation回退与用户画面验收。
|
||||||
|
|
||||||
|
## 允许与禁止范围
|
||||||
|
|
||||||
|
本轮实际只改两个既有C++测试文件,新增四份中文文件并追加开发记录。未改生产src/include、公开API/ABI/RN/JNI/合同、Shader、Android场景、Style/服务器、NavSea、iOS、版本/Source Lock;没有放宽Source readiness/revision、Placement或24Gate,没有造Fast计数。STEP110/111原未跟踪MD保留,不暂存;原设备JSON保持Git忽略。
|
||||||
|
|
||||||
|
按用户当前禁止项,没有运行Gradle/ADB/Native编译/CMake/Ninja/Bazel/Jest、安装、commit/push。未启动后台编译或第二Codex,没有子代理。
|
||||||
|
|
||||||
|
## 阶段验收与当前结果
|
||||||
|
|
||||||
|
保留实测(STEP116,非STEP117):原STATIC_RC 90秒FastDelta=0、FullDelta=920;Native65层R[0,63)、C[63,65);R缺tide、Build/Reuse=0;最近120帧119Full/0Fast/1pending,#3/#4/#23失败120、#12/#13失败105、#22失败0、mismatch0。
|
||||||
|
|
||||||
|
本轮复算pre为105帧false/非零/true、15帧true/0/false;post为104+15,末帧pending。源码证明:缺源没有新RenderItem不等于无旧GPU数据;停用request未执行前registry仍可遍历旧group;停用不清旧drawables。Symbol重算changed与recent stale使首建条件不可达;layer fingerprint不包含最终GPU opacity/atlas/vertices。
|
||||||
|
|
||||||
|
因此两项准入均BLOCKED。七项测试只是可运行源码:真实controller/sourceDiff/registry/observer路径与状态机组合;没有GPU像素等价证据,不能称Native或全任务PASS。静态检查的实际结果在完成报告中记录。
|
||||||
|
|
||||||
|
## 构建测试、输出与下一步
|
||||||
|
|
||||||
|
RDC命令及失败停止、源/APK/设备SHA、完整JSON/画面、负例矩阵详见 `docs/60_测试/STEP-117_FZG1_原PBF真实Fast验收计划_v1.md`。本轮仅测试代码,Android生产行为无变化,重复构建不能解决B1/B2;先进行独立审计与Shared Core证书设计协调,形成受控实现后再安排一次用户授权的集中Android闭环。
|
||||||
|
|
||||||
|
必做输出:`docs/20_调查/STEP-117_PBF_R首次缓存Build安全证据_v1.md`、本文件、验收计划、`docs/报告/STEP-117_原PBF_Fast缓存准入_Codex完成报告_v1.md`、开发记录末尾追加。Git提交/hash、远端HEAD、Native/设备验收均留RDC在后续授权下回填,本轮未执行。
|
||||||
|
|
||||||
|
|
||||||
|
## RDC独立核验附录(2026-10-11)
|
||||||
|
|
||||||
|
- RDC先核对Integration main=80667d6c343411d03a760425438e3d292f452118、Particle当前particle/main=43e5f5b91598b9c3d3f1c788052d4bbd2d616668;源码与git已跟踪改动起点为空,仅两个用户保护未跟踪任务书。
|
||||||
|
- 用户本轮要求继续真实STEP113 PBF Fast优化,Codex实际GPT-6.1-Sol High。调查原STEP116实机120帧JSON,缺tide Source以及Symbol placement重算/stale循环仍无法安全创建首次GPU缓存;已有证据只能证明无新的LayerRenderItem,不能证明旧GPU drawables/已经应用的双LayerGroup删除。保留既有24Gate/生产Core,安全准入BLOCKED。
|
||||||
|
- Codex新增7个Step117Safety C++测试源码,分布于两个既有登记的test/renderer文件;RDC独立对两个最终文件以当前Android OpenGL/x86_64的NDK clang++、真实compile_commands.json C++20 flags和googletest头文件进行-fsyntax-only。retained_underlay_cache.test.cpp exit0(6.3s),render_orchestrator_error.test.cpp exit0(5.3s),RDC检查结果PASS。语法检查日志存Git忽略artifacts/maplibre-particle/step117-native-syntax/*.log。
|
||||||
|
- RDC核查原生产src/include/Renderer/Placement/Fast Gate、Android STEP113/114及Source/style均无文件改动,git diff --check通过。故**没有新的运行时改动供Android APK验证**:重复编译/安装STEP116相同行为的APK不能使Build/Reuse/Fast改善,未触发第二次高成本Android周期。GTest链接运行、GPU像素等价、iOS/Metal、真实Fast目标仍NOT RUN/BLOCKED,不能将NDK语法退出0标为GTest PASS。
|
||||||
|
- Integration正式现有RFC/ADR/Contract/status/coordination未包含所需R Symbol已提交GPU结果证书。B1缺源零贡献、B2 Symbol跨层结果证书与影子验收、B3真实tide Source身份/宿主动态注入语义须由粒子负责人/Integration按职责协调设计;本执行项目不得自行改变Shared Core公共契约或正式Style。
|
||||||
|
- 七项测试当前仍是源码语法检查级别,不等于实测; 下一步应先由粒子负责人协调Shared Core结果证书及合法真实tide来源,受控实现后再使用原STEP113 STATIC_RC APK复测。任意无法安全证明的条件继续fail-closed。
|
||||||
165
docs/60_测试/STEP-117_FZG1_原PBF真实Fast验收计划_v1.md
Normal file
165
docs/60_测试/STEP-117_FZG1_原PBF真实Fast验收计划_v1.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# STEP-117 FZG1 原 PBF 真实 Fast 验收计划 v1
|
||||||
|
|
||||||
|
日期:2026-10-11(JST)。**本计划全部运行命令交RDC/普通Terminal;Codex本轮未执行。当前安全准入BLOCKED,测试源码交付不表示真实Fast已修复。**
|
||||||
|
|
||||||
|
## 1. 执行顺序与停止条件
|
||||||
|
|
||||||
|
先独立审计STEP117调查、diff和七项测试,确认B1缺源零贡献与B2 Symbol结果证书仍未实现。本轮只有测试/文档,不应期待重新打APK获得不同Fast行为。RDC可先验证C++回归;粒子负责人协调Shared Core证书设计及正式tide语义,再授权具体实现。完成可证明的实现并复核后,安排一次完整Android build/install/原STATIC_RC集中验收。
|
||||||
|
|
||||||
|
本任务不授权Codex执行任何Native编译/测试、Gradle/ADB/安装、Jest、commit/push。RDC后续Git收尾须按独立授权scoped提交,核对origin远端HEAD,保护STEP110/111。Android与设备命令只能在用户明确授权的对应阶段执行。当前缺libuv历史记录只用于排查;不跳过失败、不改门槛、不运行旧runner、不改build-info使旧包冒充新源码。
|
||||||
|
|
||||||
|
遇到编译/测试失败、Source/Style版本不符、mismatch>0、未知Gate、错误恢复/漏内容或Fast仍为0,保存首个真实error/target及完整日志路径,停止相应通过判定。不要换STEP114烟测、删原层或补假tide来继续。
|
||||||
|
|
||||||
|
## 2. 独立源码与定向Native验收
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/tei/dev/MapLibreParticleLab
|
||||||
|
git branch --show-current
|
||||||
|
git rev-parse HEAD
|
||||||
|
git status --short
|
||||||
|
git diff --check
|
||||||
|
git diff -- test/renderer/retained_underlay_cache.test.cpp test/renderer/render_orchestrator_error.test.cpp 粒子开发记录.md
|
||||||
|
shasum -a 256 docs/40_任务/STEP-110_R0_Placement跨段归因只读调查_Codex任务_v1.md docs/40_任务/STEP-111_R段Placement结果等价与独立刷新可行性只读调查_Codex任务_v1.md
|
||||||
|
```
|
||||||
|
|
||||||
|
STEP110/111预期SHA分别为 `33037df71b4b30aa7956d59f4b99f77af3085405b24111bc0fe11ec857a93db0`、`f3a5806f25384bf46055db2edfea0d21bfbc4124184bc813b46e38b8079c1ec4`。查看新增四份文档及报告静态核查章节。生产src/include/Shader/TestApp/旧测试断言应与起点保持一致;不得把test fixture的markBuildSucceeded或测试线程注入事件当作实际GPU/并发完成。
|
||||||
|
|
||||||
|
以下逐项串行运行,上一项失败立即停止。使用当前Mac配置的CMake;如果PATH没有cmake,可用已配置的 `/Users/tei/Library/Android/sdk/cmake/3.31.6/bin/cmake`,不得自行升级依赖。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --preset macos-metal
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
build-macos-metal/mbgl-test-runner --gtest_filter='Step117Safety.*:Step116Safety.*:Annotations.*:RenderOrchestratorError.*:RenderOrchestratorTeardown.*:FastGateTrace.*:ParticleFastPath.*:RetainedUnderlayCache.*:RetainedUnderlayRevision.*:RenderSegmentDiagnostics.*:RenderSegmentPlacementFree.*:RenderSegmentLocality.*:RenderSegmentPlan.*' --gtest_color=no
|
||||||
|
```
|
||||||
|
|
||||||
|
新增Step117Safety必须实际运行7项,不能以filter未匹配的exit0通过。test/CMakeLists.txt已登记两个源文件,不需要绕过原target。记录当前HEAD、runner构建来源、命令、exit/耗时、用例数量、完整日志路径。Annotations.Step116是实际出图比较;其通过也不替代原PBF的Symbol结果证明。Mac Metal runner成功不代表Android OpenGL或iOS设备PASS。
|
||||||
|
|
||||||
|
## 3. 一次未来授权的Android制品闭环
|
||||||
|
|
||||||
|
在B1/B2受控实现完成、源码已锁定且tracked clean后,用户授权RDC/普通Terminal逐项执行标准Pipeline。保护未跟踪MD保留,git_dirty=true需结合tracked状态判断。记录真正的源HEAD,不能拿本轮起点43e5f5b当作包含未来实现的提交。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/tei/dev/MapLibreParticleLab
|
||||||
|
git rev-parse HEAD
|
||||||
|
git status --short
|
||||||
|
./tools/particle_android_validation/build_validation_apk.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Pipeline必须Java17、OpenGL/x86_64、strip,成功后核对ZIP、唯一ABI、libmaplibre.so、体积、完整build.log/build-info与SHA;失败不复用旧APK。版本名13.6.1-particle.23本身不能标识源码。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat artifacts/maplibre-particle/android-validation/build-info.txt
|
||||||
|
shasum -a 256 artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
|
||||||
|
/Users/tei/Library/Android/sdk/platform-tools/adb -s 192.168.200.139:5555 install -r artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
不得卸载/清数据。设备serial须重新核实为FZG1-2;变化时显式记录并修改后续参数。回读已安装base.apk SHA,由以下现有工具复核同HEAD/本地APK/设备安装包:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --adb /Users/tei/Library/Android/sdk/platform-tools/adb --serial 192.168.200.139:5555 --preflight-only
|
||||||
|
```
|
||||||
|
|
||||||
|
STALE_APK、SOURCE_NOT_LOCKED、ABI/SHA不符立即停止。PREFLIGHT_PASS仅说明版本闭环;旧c48a72a9 APK与本轮源码HEAD不同,即使生产文件未改也不能修改来源记录。
|
||||||
|
|
||||||
|
## 4. 原STATIC_RC≥90秒正式验收
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --adb /Users/tei/Library/Android/sdk/platform-tools/adb --serial 192.168.200.139:5555 --scenario STATIC_RC --seconds 90
|
||||||
|
```
|
||||||
|
|
||||||
|
从取得同PID起实际观察至少90秒,取得前后同sceneGeneration/lifecycle的摘要,计数单调、不撤销、不重置。保存result.json/logcat/launch、实际观察秒数。exit2/NO_FAST_OBSERVED如实失败;exit3为版本/环境阻塞。FAST_OBSERVED只是必要条件。
|
||||||
|
|
||||||
|
正式通过同时要求:
|
||||||
|
|
||||||
|
- 原Style的63基础层定义/顺序保留,记录productionFingerprint与baseLayerManifest、productionSources;原Style/Sprite/Glyph/Vector URI一致。若服务器内容改变导致fingerprint或层数不同,停止跨版本比较,交Style所有者协调。
|
||||||
|
- STEP116空SDK Annotation规则保留:零实例后一次受控移除points,Source保留;原C正常只有WeatherColor+Particle,Native65层/R[0,63)/C[63,65)。后续真实Annotation/Style改变不得被再次删除。
|
||||||
|
- 实际每个R Cache Build>0、Reuse>0,同生命周期FastDelta>0;completed fast-rendered帧必须cacheValid/revision一致、24Gate已知且全部PASS、mismatch=0。pending帧不计成功。
|
||||||
|
- 缺源准入若未来获证书,必须能回读该absent source的零绘制/旧数据排除及同名恢复失效证据;missingSourceIds非空不能自动通过,也不能简单规定非空一律失败而回避新证书审查。
|
||||||
|
- Symbol缓存绑定成功提交的R结果证书,列出受影响bucket/atlas/collision/opacity/动态属性/camera/context和变更代次;源码/设备证据中不得强制清三字段或改Gate。
|
||||||
|
- 用户验收底图、海岸/等深线、航标、文字、天气色带与粒子,无漏内容/闪烁/层序错误;同条件Full/Fast像素对照及资源变化回退分别取证。性能提升需额外相同条件测量,不能从Full减少单独推断。
|
||||||
|
|
||||||
|
## 5. 完整120帧与用户画面
|
||||||
|
|
||||||
|
同次运行在STEP093→STEP113菜单手动EXPORT LAST SNAPSHOT。导出由用户触发,RDC回读同次generation/lifecycle的文件;确认文件名/时间不属于旧运行。以下shell命令逐项执行,任何失败立即停;变量只用于本次任务:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p artifacts/maplibre-particle/android-validation/step117
|
||||||
|
step117_file="$(/Users/tei/Library/Android/sdk/platform-tools/adb -s 192.168.200.139:5555 shell run-as org.maplibre.android.testapp ls -t files | tr -d '\r' | grep -E '^step113-STATIC_RC-.*[.]json$' | head -n 1)"
|
||||||
|
test -n "$step117_file"
|
||||||
|
/Users/tei/Library/Android/sdk/platform-tools/adb -s 192.168.200.139:5555 exec-out run-as org.maplibre.android.testapp cat "files/$step117_file" > artifacts/maplibre-particle/android-validation/step117/static-rc-full.json
|
||||||
|
shasum -a 256 artifacts/maplibre-particle/android-validation/step117/static-rc-full.json
|
||||||
|
/Users/tei/Library/Android/sdk/platform-tools/adb -s 192.168.200.139:5555 exec-out screencap -p > artifacts/maplibre-particle/android-validation/step117/static-rc-screen.png
|
||||||
|
/Users/tei/Library/Android/sdk/platform-tools/adb -s 192.168.200.139:5555 logcat -b crash -d > artifacts/maplibre-particle/android-validation/step117/crash.log
|
||||||
|
```
|
||||||
|
|
||||||
|
完整JSON离线结构核对示例(不是新安全证书/性能验收):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -B - <<'PY'
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
v = json.loads(Path('artifacts/maplibre-particle/android-validation/step117/static-rc-full.json').read_text())
|
||||||
|
assert v['scenario'] == 'STATIC_RC' and v['sceneReady'] and not v['blockedReason']
|
||||||
|
assert v['styleParity']['baseLayerCount'] == 63 and v['styleParity']['baseLayersPreserved']
|
||||||
|
assert v['commands']['emptyBuiltinAnnotationLayerRemoved']
|
||||||
|
assert v['commands']['annotationInstancesAtRemoval'] == 0
|
||||||
|
assert v['commands']['annotationSourcePreserved']
|
||||||
|
n = v['native']; t = n['fastGateTrace']; fs = t['frames']
|
||||||
|
assert n['valid'] and n['styleLayerCount'] == 65
|
||||||
|
assert len(fs) == t['windowCount'] == 120
|
||||||
|
assert len(t['gates']) == 24 and t['decisionMismatch'] == 0
|
||||||
|
assert [g['order'] for g in t['gates']] == list(range(1, 25))
|
||||||
|
assert all(f['knownMask'] == 0xffffff and f['decisionConsistent'] and len(f['gateStatus']) == 24 for f in fs)
|
||||||
|
assert all(a['sequence'] < b['sequence'] for a, b in zip(fs, fs[1:]))
|
||||||
|
assert all(f['post'] is not None for f in fs if f['completed'])
|
||||||
|
assert all(f['post'] is None for f in fs if not f['completed'])
|
||||||
|
assert [(s['strategy'], s['beginIndex'], s['endExclusive']) for s in n['segments']] == [
|
||||||
|
('RETAINED', 0, 63), ('CONTINUOUS', 63, 65)]
|
||||||
|
fast = [f for f in fs if f['completed'] and f['outcome'] == 'fast-rendered']
|
||||||
|
assert fast, '原PBF当前窗口没有完成Fast帧;保持FAIL/BLOCKED'
|
||||||
|
assert all(f['failMask'] == 0 and all(c['exists'] and c['valid'] and
|
||||||
|
c['buildRevision'] == c['staticRevision'] for c in f['cacheInputs']) for f in fast)
|
||||||
|
assert all(s['cache']['build'] > 0 and s['cache']['reuse'] > 0 for s in n['segments'] if s['strategy'] == 'RETAINED')
|
||||||
|
print('必要结构/计数成立;继续检查证书、同次SHA/manifest、变更前后帧与用户画面')
|
||||||
|
PY
|
||||||
|
```
|
||||||
|
|
||||||
|
在当前STEP117无准入实现的代码上,Fast/Build断言预期不能通过;不得删除这些断言制造PASS。pre为上一完成树,post/full为本次完成树;#13另取当前controller,不能混为同帧。环形窗口可能覆盖变更瞬间,必须每项操作前/后及时导出;未捕获则NOT VERIFIED。
|
||||||
|
|
||||||
|
## 6. 安全反例与旧五场景
|
||||||
|
|
||||||
|
| 操作 | 必须取证的正确行为 | 当前入口/限制 |
|
||||||
|
|---|---|---|
|
||||||
|
| 初始缺源 | 没有证书时missing-source、Build/Fast0;未来证书需证明双group零贡献和无旧数据 | 原STATIC_RC真实缺tide;不补造source |
|
||||||
|
| 同名source创建/重建/数据到达 | 下一次尝试Full,旧证书和cache失效;真实内容可见后才重建 | 新C++真实sourceDiff用例及状态机;当前App没有生产tide注入入口,需Integration/真实来源协调,设备项NOT VERIFIED |
|
||||||
|
| 已有旧Symbol后缺源/合法Style替换 | 两类group停用请求执行,旧drawables/buckets排除;不得复用旧R | 当前测试只有registry生命周期,无实际GPU旧数据证书;必须追加真正渲染用例后验收 |
|
||||||
|
| Tile/Glyph/Image异步更新 | #5/#8/#14或对应稳定性Gate拒绝旧Fast,受影响R重建;未加载/fading继续fail-closed | C++回调注入不等同网络并发;实际资源延迟与事件顺序需独立工具/测试授权 |
|
||||||
|
| Symbol collision/fade/anchor/orientation/沿线 | Full/Fast最终像素等价;所有碰撞受害R失效;时间相关opacity不能冻结 | 结果证书当前不存在;不能用默认空桶测试代替 |
|
||||||
|
| Source mutation | 保留原SOURCE_CHANGE circle负例和手动MUTATE PROBE SOURCE ONCE;记录sourceId/affectedSegmentIndices与真实Full | 当前probe属C,不能冒充R的tide恢复 |
|
||||||
|
| Style mutation/重排/添加 | non-camera/topology/fingerprint拒绝旧树;内容不删除 | 原入口无自动全矩阵;没有触发能力则NOT VERIFIED |
|
||||||
|
| 真实Annotation add/no-op update/reload | STEP116同步恢复points并可见;#24/层表拒绝旧Fast;空层验收条件撤销 | Annotations.Step116图像回归和用户合法操作;不可周期删真实层 |
|
||||||
|
| Camera/viewport/pixelRatio/projection | #6/#7/#8、cache key/context失效,Full后正确重建,无拖影或错位 | 用户pan/zoom/rotate/pitch/resize;逐事件导出 |
|
||||||
|
| context/后台/恢复/disable/退出场景 | PreparedTree/资源正确失效释放,无旧GPU数据复活 | 用户设备生命周期及Native实际Renderer测试;现有callback用例不替代 |
|
||||||
|
|
||||||
|
原五场景依次独立运行、分别保存日志/导出/画面。以下复测工具命令由RDC在同SHA预检后执行,SOURCE_CHANGE保留普通circle与Annotation负例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --adb /Users/tei/Library/Android/sdk/platform-tools/adb --serial 192.168.200.139:5555 --scenario PBF63 --seconds 90
|
||||||
|
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --adb /Users/tei/Library/Android/sdk/platform-tools/adb --serial 192.168.200.139:5555 --scenario PARTICLE_OFF --seconds 90
|
||||||
|
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --adb /Users/tei/Library/Android/sdk/platform-tools/adb --serial 192.168.200.139:5555 --scenario PARTIAL_RCRR --seconds 90
|
||||||
|
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --adb /Users/tei/Library/Android/sdk/platform-tools/adb --serial 192.168.200.139:5555 --scenario SOURCE_CHANGE --seconds 90
|
||||||
|
```
|
||||||
|
|
||||||
|
受保护负例可能预期Fast0,exit2应按场景语义记录,不能调整工具返回码或删除负例。STATIC_RC正式正例仍要求真实Fast,不接受STEP114 FAST_SMOKE替代。
|
||||||
|
|
||||||
|
## 7. 最终证据包
|
||||||
|
|
||||||
|
RDC回填:锁定源HEAD与精确diff/相关源码SHA、scoped提交与远端HEAD(若获授权执行)、Native配置/构建/七测试日志、首错/阻塞;build-info/build.log/APK与安装包SHA、设备型号/serial;原Style fingerprint/63层manifest/C层表;同次90秒摘要、120帧完整JSON及SHA、每项24Gate/cache/Full/Fast/pre/post;Mutation前后/异步/碰撞/GPU生命周期证书;用户画面及同条件Full/Fast对照。
|
||||||
|
|
||||||
|
没有证书保持BLOCKED;编译成功、静态检查、PREFLIGHT_PASS或测试进程exit0不能代替原PBF真实Fast安全验收。
|
||||||
88
docs/报告/STEP-117_原PBF_Fast缓存准入_Codex完成报告_v1.md
Normal file
88
docs/报告/STEP-117_原PBF_Fast缓存准入_Codex完成报告_v1.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# STEP-117 原 PBF Fast 缓存准入 Codex 完成报告 v1
|
||||||
|
|
||||||
|
日期:2026-10-11(JST)。**结果:BLOCKED。缺tide零GPU贡献与Symbol首次Build均未获得充分安全证据,保持fail-closed;已完成源码调查、原120帧复核、七项非Jest回归源码及全部中文交付。原PBF Fast目标没有完成。**
|
||||||
|
|
||||||
|
## 1. 实际模型、环境和版本
|
||||||
|
|
||||||
|
- 实际 **GPT-6.1-Sol(gpt-6.1-sol)/ high**,读取当前会话rollout `01a12912-9a0c-7712-9624-793f04b3f681` 的turn_context.model/effort确认;未升级、切换、启动子代理或第二Codex。
|
||||||
|
- Mac.lan / Darwin24.6.0 / x86_64;仓库 `/Users/tei/dev/MapLibreParticleLab`;branch `particle/main`。
|
||||||
|
- 起点/交付HEAD `43e5f5b91598b9c3d3f1c788052d4bbd2d616668`;无commit/push、无远端回读、无分支/子模块操作。起点tracked clean,三份未跟踪任务书STEP110/111/117保留。
|
||||||
|
- `platform/android/VERSION=13.6.1-particle.23`,未改公开版本/发行/Source Lock;本轮没有APK/AAR/XCFramework。
|
||||||
|
- Integration本地只读HEAD `80667d6c343411d03a760425438e3d292f452118`;只读instructions/contract等规范,无跨仓写入、同步或向他人发送消息。
|
||||||
|
|
||||||
|
## 2. 根因与停止点
|
||||||
|
|
||||||
|
原实机JSON SHA `cd491d2acca97119f1d4f2d6f77eb7b229c17b90d4be1181a59202308429b219` 已完整解析并逐帧复算。STEP116的90秒FastDelta=0、FullDelta=920是保留实测。本轮复核120帧为119Full/0Fast/1pending;#3/#4/#23各失败120、#12/#13各105、#22为0、mismatch0。原63层和C两天气层保留,R仍缺tide、Build/Reuse=0。
|
||||||
|
|
||||||
|
**缺源**:缺source没有新LayerRenderItem,但RenderLayer的停用只排队RemoveGroup;processChanges执行后才退出registry,停用并不清旧drawables/tiles/placementData。原JSON无双group/旧数据排除与成功提交代次;不能把absence登记为loaded/stable或伪造revision。保持missing-source。
|
||||||
|
|
||||||
|
**Symbol**:pre有105帧changed=false/fade非零/transition=true及15帧true/0/false,post104+15。正常Continuous重算必changed,recent必stale;duration0/禁用transition也不能建立结果证书。per-R Build及retainedSupported/preparedScene各有独立保护,layer fingerprint只含Impl指针/index,缺opacity/dynamic attributes/atlas/collision/uniform等最终GPU状态。建立完整证书需要跨Placement/Bucket/Drawable/Atlas/Renderer生命周期实现与平台证据,本轮按任务停止该部分,所有Gate保持。
|
||||||
|
|
||||||
|
调查文件给出源码链、已成立/未成立证据、反例和B1–B4协调需求。任务明确允许证据不足保持fail-closed;没有以既有烟测或测试进程代替正式目标,也没有把研究完成称为实现完成。
|
||||||
|
|
||||||
|
## 3. 实际修改文件及接口边界
|
||||||
|
|
||||||
|
修改:
|
||||||
|
|
||||||
|
1. `test/renderer/retained_underlay_cache.test.cpp`:新增4项Step117Safety,实际Controller/Placement生命周期、disabled/zero duration、缺源墓碑与恢复的cache状态机、camera/viewport/content/topology/config失效。
|
||||||
|
2. `test/renderer/render_orchestrator_error.test.cpp`:新增3项Step117Safety,实际createRenderTree/sourceDiff、registry RemoveGroup队列、Tile/Glyph/Image回调与context/style清理;仅扩展已有测试friend结构的enqueue辅助,不改生产头文件。
|
||||||
|
3. `粒子开发记录.md`:只追加STEP117记录。
|
||||||
|
|
||||||
|
新增:
|
||||||
|
|
||||||
|
1. `docs/20_调查/STEP-117_PBF_R首次缓存Build安全证据_v1.md`。
|
||||||
|
2. `docs/50_Step记录/STEP-117_原PBF_Fast缓存准入_v1.md`。
|
||||||
|
3. `docs/60_测试/STEP-117_FZG1_原PBF真实Fast验收计划_v1.md`。
|
||||||
|
4. 本报告。
|
||||||
|
|
||||||
|
生产src/include/Shader/Android/RN/JNI/API/ABI零修改;没有新增诊断字段/控制协议、源状态或新的准入bool。test/CMakeLists.txt已登记两个测试文件,无需修改构建表。原Step113PbfGateScene、原五场景/SOURCE_CHANGE、STEP116空Annotation修复、STEP102/114入口、旧测试断言均保留。没有测试App假tide,没有删除正式tide-spots或Symbol。README无运行入口变化,本轮无需修改。
|
||||||
|
|
||||||
|
## 4. 七项测试的准确状态
|
||||||
|
|
||||||
|
`Step117Safety.*` 七项全部 **NOT RUN / NOT COMPILED**,没有GTest成功日志。Controller与sourceDiff/observer/registry测试调用真实实现;空桶、无数据step117-source与两个测试group是最小生命周期fixture,不能当作原PBF像素/旧GPU资源证书。显式markBuildSucceeded仅属于cache状态机fixture,不是GPU成功;observer在测试线程注入,不代表真正异步网络并发。
|
||||||
|
|
||||||
|
尚缺完整Renderer首次Build与提交证书、跨source/跨段collision、真实glyph/atlas延迟、曾渲染后缺源的旧Drawable清理、Full/Fast像素对照和设备恢复。既有Annotations.Step116实际图像测试保留,新增tracker测试不冒充真实Annotation设备验证。
|
||||||
|
|
||||||
|
## 5. 已执行与未执行检查
|
||||||
|
|
||||||
|
已执行:前置文档和实际源码读取;本机branch/HEAD/status/submodule与Integration本地HEAD只读核对;原JSON SHA/结构/120帧逐项Gate及pre/post统计复核;静态API/变更范围、测试登记/签名/生命周期人工核对;git diff --check、中文文档和开发记录/保护文件完整性核查。最终具体收尾结果见第8节。
|
||||||
|
|
||||||
|
未执行:任何Native/CMake/Ninja/Bazel编译/链接/codegen/GTest、Gradle/APK、ADB/安装/运行/设备logcat/截图、Jest、iOS/Metal设备、性能或像素测量、commit/push/远端HEAD、发布。未观察到新编译/测试失败,因为根本未运行;不能推断会通过。历史Mac缺libuv是STEP116 RDC事实,本轮没有重跑或修依赖。
|
||||||
|
|
||||||
|
## 6. RDC接手与具体协调需求
|
||||||
|
|
||||||
|
1. RDC独立审查本报告、调查、diff及七测试。按验收计划逐项运行Mac Native定向命令,首错即停,报告实际匹配7项的数量/结果;不使用旧runner。
|
||||||
|
2. 粒子负责人协调Shared Core:缺源absent依赖绑定已应用双group排除、旧Renderable数据与成功提交代次;Symbol结果证书先影子比较,覆盖collision/opacities/vertices/atlas/uniform/camera/context/异步纪元。没有证书维持BLOCKED,不修改Gate迎合计数。
|
||||||
|
3. Integration协调正式Style/Host tide是否为真实动态注入、加载与身份语义;不在此仓库改服务器/造数据。公共责任/错误语义改变才提交RFC/ADR;内部优化可以平台中性实现,无需凭空扩大公共合同。
|
||||||
|
4. 后续受控实现完成、RDC审计与源码锁定后,按用户明确授权执行一次标准 `./tools/particle_android_validation/build_validation_apk.sh`、install -r、同HEAD/设备SHA预检、原STATIC_RC至少90秒、完整120帧24Gate与Mutation/用户画面验收。没有生产改动时重建本轮测试源码不能解决Fast0。
|
||||||
|
|
||||||
|
精确命令与证据矩阵在 `docs/60_测试/STEP-117_FZG1_原PBF真实Fast验收计划_v1.md`。不由Codex运行,不以STEP114 FAST_SMOKE代替。Native编译与测试、Android SHA、真实Build/Reuse/Fast、用户视觉和安全回退分别判定,不把单项成功写成全任务PASS。
|
||||||
|
|
||||||
|
## 7. Git/制品待回填项
|
||||||
|
|
||||||
|
本轮不commit/push,提交message/hash不适用;远端HEAD未核验。RDC若后续获授权,只按第3节七个明确任务路径scoped提交(任务书是否纳入另按授权),不得包含STEP110/111、其他dirty/untracked或Git忽略JSON。普通push后回读 `origin refs/heads/particle/main` 并与实际提交核对。
|
||||||
|
|
||||||
|
Native runner来源/日志/exit/耗时、Android构建源码HEAD/制品SHA/设备SHA、独立Fast/视觉验收均为“待RDC回填”,不提前填成功或借用旧c48a72a9来源。
|
||||||
|
|
||||||
|
## 8. 静态收尾结果
|
||||||
|
|
||||||
|
- `git diff --check`退出0,无空白诊断。tracked差异只含第3节两个测试文件和开发记录,新增356行、删除0行;四份新文档逐个执行`git diff --no-index --check /dev/null <明确路径>`,无空白诊断,exit1仅表示与空文件有差异。
|
||||||
|
- 七项`TEST(Step117Safety, ...)`源码名称唯一,两个文件在现有test/CMakeLists.txt登记;原文件diff只有插入,原测试代码及断言没有删除或替换。人工核对当前UpdateParameters成员顺序、Placement/observer/sourceDiff相关声明,以及测试source销毁前detach与排空scheduler;未作编译,因此不能据此保证测试可执行。
|
||||||
|
- 生产Renderer/Orchestrator/Placement/particle_fast_path/render_segment_json/render_segment公开头、AnnotationManager和STEP113/114场景与HEAD字节相同。原Step113PbfGateScene SHA=`d50281713ae551edc9a48b1550254602e4950c9ddca66855bb689620c9f6f2b6`。全部tracked修改路径不含src/include、公共API/ABI或Android;24Gate、计数与正式场景保持。
|
||||||
|
- 开发记录原HEAD的167,048字节前缀完整,原SHA=`8544702389dab5d829afe145dd5e7cd23083992a887b5fc4857a8b57f468cf8a`;本轮仅追加2,252字节/10行。
|
||||||
|
- STEP110未跟踪MD SHA=`33037df71b4b30aa7956d59f4b99f77af3085405b24111bc0fe11ec857a93db0`;STEP111=`f3a5806f25384bf46055db2edfea0d21bfbc4124184bc813b46e38b8079c1ec4`,保持原值且仍未跟踪;暂存区为空。
|
||||||
|
- 四份新文档中文正文/成对代码围栏/空白核对完成;验收计划内Python只做AST解析,没有运行其中命令。原274,693字节JSON SHA未变、仍Git忽略,120帧24Gate失败数逐帧与聚合相符,pre/post所有R的Build/Reuse=0、placementGatePassed=false。
|
||||||
|
- 静态审计脚本曾分别因Git中文路径转义和pre/post中cache字段为扁平序列化而中止。随后改为`--name-only -z`读取真实路径,并按原JSON扁平build/reuse字段复核;没有修改证据、测试断言或验收阈值。修正后的范围/证据审计完成。这两次是审计读取错误,不是C++编译/测试结果。
|
||||||
|
- 终态HEAD保持`43e5f5b91598b9c3d3f1c788052d4bbd2d616668`;status只有三个tracked修改、四份新交付文档及起点三份未跟踪任务书。未commit/push,独立RDC验收尚未开始。
|
||||||
|
|
||||||
|
以上只证明静态范围与文件完整性。安全准入仍BLOCKED,Native/Android测试未运行,真实Fast/像素/性能目标没有通过。
|
||||||
|
|
||||||
|
|
||||||
|
## RDC独立核验附录(2026-10-11)
|
||||||
|
|
||||||
|
- RDC先核对Integration main=80667d6c343411d03a760425438e3d292f452118、Particle当前particle/main=43e5f5b91598b9c3d3f1c788052d4bbd2d616668;源码与git已跟踪改动起点为空,仅两个用户保护未跟踪任务书。
|
||||||
|
- 用户本轮要求继续真实STEP113 PBF Fast优化,Codex实际GPT-6.1-Sol High。调查原STEP116实机120帧JSON,缺tide Source以及Symbol placement重算/stale循环仍无法安全创建首次GPU缓存;已有证据只能证明无新的LayerRenderItem,不能证明旧GPU drawables/已经应用的双LayerGroup删除。保留既有24Gate/生产Core,安全准入BLOCKED。
|
||||||
|
- Codex新增7个Step117Safety C++测试源码,分布于两个既有登记的test/renderer文件;RDC独立对两个最终文件以当前Android OpenGL/x86_64的NDK clang++、真实compile_commands.json C++20 flags和googletest头文件进行-fsyntax-only。retained_underlay_cache.test.cpp exit0(6.3s),render_orchestrator_error.test.cpp exit0(5.3s),RDC检查结果PASS。语法检查日志存Git忽略artifacts/maplibre-particle/step117-native-syntax/*.log。
|
||||||
|
- RDC核查原生产src/include/Renderer/Placement/Fast Gate、Android STEP113/114及Source/style均无文件改动,git diff --check通过。故**没有新的运行时改动供Android APK验证**:重复编译/安装STEP116相同行为的APK不能使Build/Reuse/Fast改善,未触发第二次高成本Android周期。GTest链接运行、GPU像素等价、iOS/Metal、真实Fast目标仍NOT RUN/BLOCKED,不能将NDK语法退出0标为GTest PASS。
|
||||||
|
- Integration正式现有RFC/ADR/Contract/status/coordination未包含所需R Symbol已提交GPU结果证书。B1缺源零贡献、B2 Symbol跨层结果证书与影子验收、B3真实tide Source身份/宿主动态注入语义须由粒子负责人/Integration按职责协调设计;本执行项目不得自行改变Shared Core公共契约或正式Style。
|
||||||
|
- 七项测试当前仍是源码语法检查级别,不等于实测; 下一步应先由粒子负责人协调Shared Core结果证书及合法真实tide来源,受控实现后再使用原STEP113 STATIC_RC APK复测。任意无法安全证明的条件继续fail-closed。
|
||||||
@@ -1,19 +1,24 @@
|
|||||||
#include <mln/actor/scheduler.hpp>
|
#include <mln/actor/scheduler.hpp>
|
||||||
#include <mln/gfx/uniform_buffer.hpp>
|
#include <mln/gfx/uniform_buffer.hpp>
|
||||||
#include <mln/renderer/layer_group.hpp>
|
#include <mln/renderer/layer_group.hpp>
|
||||||
|
#include <mln/renderer/change_request.hpp>
|
||||||
#include <mln/renderer/render_orchestrator.hpp>
|
#include <mln/renderer/render_orchestrator.hpp>
|
||||||
#include <mln/renderer/renderer_observer.hpp>
|
#include <mln/renderer/renderer_observer.hpp>
|
||||||
#include <mln/renderer/retained_underlay_cache.hpp>
|
#include <mln/renderer/retained_underlay_cache.hpp>
|
||||||
|
#include <mln/renderer/particle_fast_path.hpp>
|
||||||
|
#include <mln/renderer/update_parameters.hpp>
|
||||||
#include <mln/renderer/render_source.hpp>
|
#include <mln/renderer/render_source.hpp>
|
||||||
#include <mln/renderer/render_source_observer.hpp>
|
#include <mln/renderer/render_source_observer.hpp>
|
||||||
#include <mln/renderer/tile_render_data.hpp>
|
#include <mln/renderer/tile_render_data.hpp>
|
||||||
#include <mln/style/sources/geojson_source_impl.hpp>
|
#include <mln/style/sources/geojson_source_impl.hpp>
|
||||||
|
#include <mln/style/layers/symbol_layer.hpp>
|
||||||
#include <mln/tile/tile.hpp>
|
#include <mln/tile/tile.hpp>
|
||||||
#include <mln/tile/tile_observer.hpp>
|
#include <mln/tile/tile_observer.hpp>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <initializer_list>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace mln;
|
using namespace mln;
|
||||||
@@ -24,6 +29,10 @@ struct RenderOrchestratorTeardownTestAccess {
|
|||||||
source->setObserver(&orchestrator);
|
source->setObserver(&orchestrator);
|
||||||
orchestrator.renderSources.emplace(source->baseImpl->id, std::move(source));
|
orchestrator.renderSources.emplace(source->baseImpl->id, std::move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void enqueue(RenderOrchestrator& orchestrator, UniqueChangeRequestVec& changes) {
|
||||||
|
orchestrator.addChanges(changes);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace mln
|
} // namespace mln
|
||||||
|
|
||||||
@@ -249,3 +258,180 @@ TEST(RenderOrchestratorTeardown, PendingTileCancellationAndSecondDrainRepeatSafe
|
|||||||
EXPECT_EQ(renderJobs.load(), iteration + 1);
|
EXPECT_EQ(renderJobs.load(), iteration + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::shared_ptr<UpdateParameters> step117TreeParameters(
|
||||||
|
const Immutable<std::vector<Immutable<style::Layer::Impl>>>& layers,
|
||||||
|
const Immutable<std::vector<Immutable<style::Source::Impl>>>& sources,
|
||||||
|
const std::shared_ptr<RetainedUnderlayRuntimeState>& runtime,
|
||||||
|
TimePoint now) {
|
||||||
|
TransformState state;
|
||||||
|
state.setSize({640, 480});
|
||||||
|
static const style::Light light; // Keep unrelated light revisions fixed across sourceDiff steps.
|
||||||
|
return std::make_shared<UpdateParameters>(UpdateParameters{
|
||||||
|
.styleLoaded = true,
|
||||||
|
.mode = MapMode::Continuous,
|
||||||
|
.pixelRatio = 1.0f,
|
||||||
|
.debugOptions = MapDebugOptions::NoDebug,
|
||||||
|
.timePoint = now,
|
||||||
|
.transformState = state,
|
||||||
|
.glyphURL = {},
|
||||||
|
.fontFaces = {},
|
||||||
|
.spriteLoaded = true,
|
||||||
|
.transitionOptions = {Milliseconds(0), std::nullopt, false},
|
||||||
|
.light = light.impl,
|
||||||
|
.images = makeMutable<std::vector<Immutable<style::Image::Impl>>>(),
|
||||||
|
.sources = sources,
|
||||||
|
.layers = layers,
|
||||||
|
.annotationManager = {},
|
||||||
|
.fileSource = {},
|
||||||
|
.prefetchZoomDelta = 0,
|
||||||
|
.stillImageRequest = false,
|
||||||
|
.crossSourceCollisions = true,
|
||||||
|
.retainedUnderlayState = runtime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(Step117Safety, RealMissingSourceTreeHasNoRenderItemButStillFailsClosed) {
|
||||||
|
TaggedScheduler scheduler{Scheduler::GetBackground(), {}};
|
||||||
|
RenderOrchestrator orchestrator(false, scheduler, std::nullopt);
|
||||||
|
auto runtime = std::make_shared<RetainedUnderlayRuntimeState>();
|
||||||
|
ASSERT_TRUE(runtime->setRenderSegmentPlan({1, {{RenderSegmentStrategy::Retained, std::nullopt}}}));
|
||||||
|
style::SymbolLayer symbol("step117-symbol", "step117-source");
|
||||||
|
const Immutable<std::vector<Immutable<style::Layer::Impl>>> layers =
|
||||||
|
makeMutable<std::vector<Immutable<style::Layer::Impl>>>(
|
||||||
|
std::initializer_list<Immutable<style::Layer::Impl>>{symbol.baseImpl});
|
||||||
|
const Immutable<std::vector<Immutable<style::Source::Impl>>> absent =
|
||||||
|
makeMutable<std::vector<Immutable<style::Source::Impl>>>();
|
||||||
|
const auto now = TimePoint{} + Seconds(10);
|
||||||
|
auto tree = orchestrator.createRenderTree(step117TreeParameters(layers, absent, runtime, now), nullptr);
|
||||||
|
ASSERT_TRUE(tree);
|
||||||
|
EXPECT_TRUE(tree->getLayerRenderItemMap().empty());
|
||||||
|
EXPECT_EQ(orchestrator.numLayerGroups(), 0u);
|
||||||
|
auto missing = orchestrator.retainedSegmentSourceState(0, 1);
|
||||||
|
EXPECT_STREQ(missing.reason, "missing-source");
|
||||||
|
EXPECT_FALSE(missing.ready);
|
||||||
|
EXPECT_EQ(missing.revision, 0u);
|
||||||
|
EXPECT_TRUE(orchestrator.retainedRangeHasPlacementCapableLayer(0, 1));
|
||||||
|
const auto fingerprint = orchestrator.retainedRangeContentFingerprint(0, 1);
|
||||||
|
tree.reset(); // Match Renderer: release reference-based render items before source replacement.
|
||||||
|
|
||||||
|
const auto sourceList = []() -> Immutable<std::vector<Immutable<style::Source::Impl>>> {
|
||||||
|
return makeMutable<std::vector<Immutable<style::Source::Impl>>>(
|
||||||
|
std::initializer_list<Immutable<style::Source::Impl>>{
|
||||||
|
makeMutable<style::GeoJSONSource::Impl>("step117-source", style::GeoJSONOptions::defaultOptions())});
|
||||||
|
};
|
||||||
|
// An unsubmitted test-only source exercises actual sourceDiff creation and
|
||||||
|
// same-ID replacement. It supplies no fake tide or production data.
|
||||||
|
tree = orchestrator.createRenderTree(step117TreeParameters(layers, sourceList(), runtime, now + Seconds(1)), nullptr);
|
||||||
|
ASSERT_TRUE(tree);
|
||||||
|
ASSERT_EQ(tree->getLayerRenderItemMap().size(), 1u);
|
||||||
|
const auto added = orchestrator.retainedSegmentSourceState(0, 1);
|
||||||
|
EXPECT_STRNE(added.reason, "missing-source");
|
||||||
|
EXPECT_NE(added.revision, missing.revision);
|
||||||
|
EXPECT_EQ(orchestrator.retainedRangeContentFingerprint(0, 1), fingerprint);
|
||||||
|
EXPECT_FALSE(renderSegmentPlacementGatePassed(true, tree->getParameters().placementChanged,
|
||||||
|
tree->getParameters().symbolFadeChange, orchestrator.retainedPlacementTransitionActive(now + Seconds(1))));
|
||||||
|
tree.reset();
|
||||||
|
tree = orchestrator.createRenderTree(step117TreeParameters(layers, sourceList(), runtime, now + Seconds(2)), nullptr);
|
||||||
|
ASSERT_TRUE(tree);
|
||||||
|
const auto replaced = orchestrator.retainedSegmentSourceState(0, 1);
|
||||||
|
EXPECT_NE(replaced.revision, added.revision);
|
||||||
|
tree.reset();
|
||||||
|
tree = orchestrator.createRenderTree(step117TreeParameters(layers, absent, runtime, now + Seconds(3)), nullptr);
|
||||||
|
ASSERT_TRUE(tree);
|
||||||
|
EXPECT_TRUE(tree->getLayerRenderItemMap().empty());
|
||||||
|
missing = orchestrator.retainedSegmentSourceState(0, 1);
|
||||||
|
EXPECT_STREQ(missing.reason, "missing-source");
|
||||||
|
EXPECT_FALSE(missing.ready); // Source tombstone does not supply readiness.
|
||||||
|
EXPECT_EQ(missing.revision, 0u);
|
||||||
|
// No Renderer/backend draw is invoked; zero RenderItems is not a GPU certificate.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Step117Safety, QueuedGroupRemovalIsNotAppliedUntilProcessChanges) {
|
||||||
|
TaggedScheduler scheduler{Scheduler::GetBackground(), {}};
|
||||||
|
RenderOrchestrator orchestrator(false, scheduler, std::nullopt);
|
||||||
|
auto symbolGroup = std::make_shared<TestLayerGroup>(2);
|
||||||
|
auto collisionGroup = std::make_shared<TestLayerGroup>(2);
|
||||||
|
ASSERT_TRUE(orchestrator.addLayerGroup(symbolGroup));
|
||||||
|
ASSERT_TRUE(orchestrator.addLayerGroup(collisionGroup));
|
||||||
|
UniqueChangeRequestVec changes;
|
||||||
|
changes.emplace_back(std::make_unique<RemoveLayerGroupRequest>(symbolGroup));
|
||||||
|
changes.emplace_back(std::make_unique<RemoveLayerGroupRequest>(collisionGroup));
|
||||||
|
RenderOrchestratorTeardownTestAccess::enqueue(orchestrator, changes);
|
||||||
|
EXPECT_TRUE(changes.empty());
|
||||||
|
EXPECT_TRUE(orchestrator.particleFastPathDynamicState(TimePoint{}).pendingChanges);
|
||||||
|
unsigned visits = 0;
|
||||||
|
orchestrator.visitLayerGroupsInRange(0, 63, [&](LayerGroupBase&, size_t) { ++visits; });
|
||||||
|
EXPECT_EQ(visits, 2u);
|
||||||
|
orchestrator.processChanges();
|
||||||
|
EXPECT_FALSE(orchestrator.particleFastPathDynamicState(TimePoint{}).pendingChanges);
|
||||||
|
visits = 0;
|
||||||
|
orchestrator.visitLayerGroupsInRange(0, 63, [&](LayerGroupBase&, size_t) { ++visits; });
|
||||||
|
EXPECT_EQ(visits, 0u);
|
||||||
|
EXPECT_EQ(orchestrator.numLayerGroups(), 0u);
|
||||||
|
// This is real queue/registry coverage with test groups, not actual GPU draws.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Step117Safety, RealAsyncCallbacksAndContextStyleCleanupAdvanceContentEpoch) {
|
||||||
|
TaggedScheduler scheduler{Scheduler::GetBackground(), {}};
|
||||||
|
RenderOrchestrator orchestrator(false, scheduler, std::nullopt);
|
||||||
|
std::atomic<int> deferred{0};
|
||||||
|
std::atomic<int> renderJobs{0};
|
||||||
|
std::atomic<int> detached{0};
|
||||||
|
auto source = std::make_unique<TeardownSource>(scheduler, deferred, renderJobs, detached);
|
||||||
|
source->setObserver(&orchestrator);
|
||||||
|
const auto changesEpoch = [&](auto event, RetainedUnderlayReason expected) {
|
||||||
|
const auto before = orchestrator.getRetainedUnderlayContentRevision();
|
||||||
|
event();
|
||||||
|
EXPECT_GT(orchestrator.getRetainedUnderlayContentRevision(), before);
|
||||||
|
EXPECT_EQ(orchestrator.getRetainedUnderlayContentReason(), expected);
|
||||||
|
ParticleFastPathGateInput input{
|
||||||
|
.hasPreparedTree = true,
|
||||||
|
.retainedEnabled = true,
|
||||||
|
.cacheValid = true,
|
||||||
|
.revisionMatches = true,
|
||||||
|
.contentRevisionMatches = true,
|
||||||
|
.cameraMatches = true,
|
||||||
|
.viewportMatches = true,
|
||||||
|
.updateParametersMatch = true,
|
||||||
|
.styleLoaded = true,
|
||||||
|
.boundaryMatches = true,
|
||||||
|
.topologyMatches = true,
|
||||||
|
.staticStable = true,
|
||||||
|
.hasPlacementTransition = false,
|
||||||
|
.hasPendingChanges = false,
|
||||||
|
.hasNonParticleTransition = false,
|
||||||
|
.hasNonParticleRepaint = false,
|
||||||
|
.hasFadingTiles = false,
|
||||||
|
.particleNeedsRepaint = true,
|
||||||
|
.stillImageRequest = false,
|
||||||
|
.continuousMode = true,
|
||||||
|
.debugDisabled = true,
|
||||||
|
.unsupportedContinuousLayer = false,
|
||||||
|
.supportedScene = true,
|
||||||
|
.annotationMutation = false,
|
||||||
|
};
|
||||||
|
input.contentRevisionMatches = before == orchestrator.getRetainedUnderlayContentRevision();
|
||||||
|
EXPECT_EQ(particleFastGateFailureMask(input), 1u << 4);
|
||||||
|
EXPECT_FALSE(evaluateParticleFastPath(input).candidate);
|
||||||
|
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::ContentMutation);
|
||||||
|
};
|
||||||
|
changesEpoch([&] {
|
||||||
|
static_cast<RenderSourceObserver&>(orchestrator).onTileChanged(*source, OverscaledTileID{0, 0, {0, 0, 0}});
|
||||||
|
}, RetainedUnderlayReason::TileMutation);
|
||||||
|
changesEpoch([&] {
|
||||||
|
static_cast<GlyphManagerObserver&>(orchestrator).onGlyphsLoaded(FontStack{}, GlyphRange{0, 255});
|
||||||
|
}, RetainedUnderlayReason::GlyphMutation);
|
||||||
|
changesEpoch([&] {
|
||||||
|
static_cast<ImageManagerObserver&>(orchestrator).onStyleImageMissing("step117-image", [] {});
|
||||||
|
}, RetainedUnderlayReason::ImageMutation);
|
||||||
|
changesEpoch([&] { orchestrator.markContextLost(); }, RetainedUnderlayReason::ContextReset);
|
||||||
|
changesEpoch([&] { orchestrator.clearData(); }, RetainedUnderlayReason::StyleMutation);
|
||||||
|
source->setObserver(nullptr);
|
||||||
|
source.reset();
|
||||||
|
scheduler.waitForEmpty();
|
||||||
|
scheduler.runRenderJobs();
|
||||||
|
// Actual callback dispatch, but no network delivery, GPU, or Android assertion.
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <mln/renderer/continuous_layer_range.hpp>
|
#include <mln/renderer/continuous_layer_range.hpp>
|
||||||
#include <mln/renderer/render_segment_json.hpp>
|
#include <mln/renderer/render_segment_json.hpp>
|
||||||
#include <mln/renderer/render_segment_plan.hpp>
|
#include <mln/renderer/render_segment_plan.hpp>
|
||||||
|
#include <mln/renderer/update_parameters.hpp>
|
||||||
|
#include <mln/text/placement.hpp>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
@@ -66,6 +68,33 @@ ParticleFastPathGateInput fastPathInput() {
|
|||||||
.annotationMutation = false,
|
.annotationMutation = false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<UpdateParameters> step117PlacementParameters(TimePoint now,
|
||||||
|
style::TransitionOptions transitions = {}) {
|
||||||
|
TransformState state;
|
||||||
|
state.setSize({640, 480});
|
||||||
|
return std::make_shared<UpdateParameters>(UpdateParameters{
|
||||||
|
.styleLoaded = true,
|
||||||
|
.mode = MapMode::Continuous,
|
||||||
|
.pixelRatio = 1.0f,
|
||||||
|
.debugOptions = MapDebugOptions::NoDebug,
|
||||||
|
.timePoint = now,
|
||||||
|
.transformState = state,
|
||||||
|
.glyphURL = {},
|
||||||
|
.fontFaces = {},
|
||||||
|
.spriteLoaded = true,
|
||||||
|
.transitionOptions = transitions,
|
||||||
|
.light = style::Light{}.impl,
|
||||||
|
.images = makeMutable<std::vector<Immutable<style::Image::Impl>>>(),
|
||||||
|
.sources = makeMutable<std::vector<Immutable<style::Source::Impl>>>(),
|
||||||
|
.layers = makeMutable<std::vector<Immutable<style::Layer::Impl>>>(),
|
||||||
|
.annotationManager = {},
|
||||||
|
.fileSource = {},
|
||||||
|
.prefetchZoomDelta = 0,
|
||||||
|
.stillImageRequest = false,
|
||||||
|
.crossSourceCollisions = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(RetainedDynamicBoundary, SelectsFirstCandidate) {
|
TEST(RetainedDynamicBoundary, SelectsFirstCandidate) {
|
||||||
@@ -1305,6 +1334,137 @@ TEST(Step116Safety, AnnotationMutationAndLayerOrderDisableReloadKeepAllShadowFai
|
|||||||
EXPECT_EQ(particleFastGateFailureMask(unmodified), 0u); // predicate-only; no rendered Fast claim
|
EXPECT_EQ(particleFastGateFailureMask(unmodified), 0u); // predicate-only; no rendered Fast claim
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Step117Safety, RealPlacementControllerHasNoFirstSymbolBuildWindow) {
|
||||||
|
PlacementController controller;
|
||||||
|
RetainedUnderlayCache cache;
|
||||||
|
unsigned recomputed = 0;
|
||||||
|
unsigned recent = 0;
|
||||||
|
const auto start = TimePoint{} + Seconds(10);
|
||||||
|
for (unsigned frame = 0; frame < 120; ++frame) {
|
||||||
|
const auto now = start + Milliseconds(frame * 30);
|
||||||
|
const bool changed = !controller.placementIsRecent(now, 0.0f);
|
||||||
|
if (changed) {
|
||||||
|
++recomputed;
|
||||||
|
auto placement = Placement::create(step117PlacementParameters(now), controller.getPlacement());
|
||||||
|
// Exercise the real Continuous commit even with no buckets. This is
|
||||||
|
// a controller lifecycle regression, not a Symbol GPU equivalence test.
|
||||||
|
placement->placeLayers({});
|
||||||
|
controller.setPlacement(std::move(placement));
|
||||||
|
EXPECT_FLOAT_EQ(controller.getPlacement()->symbolFadeChange(now), 0.0f);
|
||||||
|
EXPECT_FALSE(controller.hasTransitions(now));
|
||||||
|
} else {
|
||||||
|
++recent;
|
||||||
|
controller.setPlacementStale();
|
||||||
|
EXPECT_TRUE(controller.hasTransitions(now));
|
||||||
|
EXPECT_GT(controller.getPlacement()->symbolFadeChange(now), 0.0f);
|
||||||
|
}
|
||||||
|
const bool supported = renderSegmentPlacementGatePassed(
|
||||||
|
true, changed, controller.getPlacement()->symbolFadeChange(now), controller.hasTransitions(now));
|
||||||
|
EXPECT_FALSE(supported);
|
||||||
|
EXPECT_EQ(cache.evaluate(key(), 1, supported, "static-placement"), RetainedUnderlayDecision::Fallback);
|
||||||
|
EXPECT_FALSE(cache.isValid());
|
||||||
|
}
|
||||||
|
EXPECT_GT(recomputed, 0u);
|
||||||
|
EXPECT_GT(recent, 0u);
|
||||||
|
EXPECT_EQ(cache.getBuildCount(), 0u);
|
||||||
|
EXPECT_EQ(cache.getReuseCount(), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Step117Safety, RealPlacementDisabledOrZeroDurationIsNotAResultCertificate) {
|
||||||
|
const auto now = TimePoint{} + Seconds(10);
|
||||||
|
for (const bool enabled : {false, true}) {
|
||||||
|
SCOPED_TRACE(enabled);
|
||||||
|
PlacementController controller;
|
||||||
|
auto placement = Placement::create(step117PlacementParameters(
|
||||||
|
now, style::TransitionOptions{Milliseconds(0), std::nullopt, enabled}), controller.getPlacement());
|
||||||
|
placement->placeLayers({});
|
||||||
|
controller.setPlacement(std::move(placement));
|
||||||
|
EXPECT_FLOAT_EQ(controller.getPlacement()->symbolFadeChange(now), 1.0f);
|
||||||
|
EXPECT_FALSE(controller.hasTransitions(now));
|
||||||
|
EXPECT_EQ(controller.placementIsRecent(now, 0.0f), enabled);
|
||||||
|
EXPECT_FALSE(renderSegmentPlacementGatePassed(true, true, 1.0f, controller.hasTransitions(now)));
|
||||||
|
controller.setPlacementStale();
|
||||||
|
EXPECT_EQ(controller.hasTransitions(now + Seconds(5)), enabled);
|
||||||
|
EXPECT_FALSE(renderSegmentPlacementGatePassed(true, false,
|
||||||
|
controller.getPlacement()->symbolFadeChange(now + Seconds(5)), controller.hasTransitions(now + Seconds(5))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Step117Safety, MissingAndSameNameRestorationCannotReuseAnOldCache) {
|
||||||
|
// Test-only source status; no source is added to the production PBF style.
|
||||||
|
const RenderSegmentDependencies dependencies{{"step117-source"}, {}, false};
|
||||||
|
RenderSegmentRevisionBook book;
|
||||||
|
RetainedUnderlayCache cache;
|
||||||
|
bool exists = false;
|
||||||
|
const auto lookup = [&](const std::string&) -> std::optional<RenderSegmentSourceStatus> {
|
||||||
|
if (exists) return RenderSegmentSourceStatus{true, false};
|
||||||
|
return std::nullopt;
|
||||||
|
};
|
||||||
|
auto missing = assessRenderSegmentSources(dependencies, lookup);
|
||||||
|
EXPECT_FALSE(book.revisionFor(dependencies));
|
||||||
|
EXPECT_EQ(cache.evaluate(key(), 0, missing.stable, missing.reason), RetainedUnderlayDecision::Fallback);
|
||||||
|
EXPECT_EQ(cache.getBuildCount(), 0u);
|
||||||
|
exists = true;
|
||||||
|
book.advanceSource("step117-source");
|
||||||
|
const auto initial = book.revisionFor(dependencies);
|
||||||
|
ASSERT_TRUE(initial);
|
||||||
|
EXPECT_EQ(cache.evaluate(key(), *initial, assessRenderSegmentSources(dependencies, lookup).stable),
|
||||||
|
RetainedUnderlayDecision::Build);
|
||||||
|
cache.markBuildSucceeded(); // State-machine fixture only; no GPU draw is claimed.
|
||||||
|
EXPECT_EQ(cache.evaluate(key(), *initial, true), RetainedUnderlayDecision::Reuse);
|
||||||
|
const auto reuseBefore = cache.getReuseCount();
|
||||||
|
exists = false;
|
||||||
|
book.advanceSource("step117-source");
|
||||||
|
const auto removed = book.revisionFor(dependencies);
|
||||||
|
ASSERT_TRUE(removed);
|
||||||
|
missing = assessRenderSegmentSources(dependencies, lookup);
|
||||||
|
EXPECT_EQ(cache.evaluate(key(), *removed, missing.stable, missing.reason), RetainedUnderlayDecision::Fallback);
|
||||||
|
EXPECT_FALSE(cache.isValid());
|
||||||
|
EXPECT_EQ(cache.getBuildRevision(), 0u);
|
||||||
|
EXPECT_EQ(cache.getReuseCount(), reuseBefore);
|
||||||
|
exists = true;
|
||||||
|
book.advanceSource("step117-source");
|
||||||
|
const auto restored = book.revisionFor(dependencies);
|
||||||
|
ASSERT_TRUE(restored);
|
||||||
|
EXPECT_NE(restored, initial);
|
||||||
|
EXPECT_NE(restored, removed);
|
||||||
|
EXPECT_EQ(cache.evaluate(key(), *restored, true), RetainedUnderlayDecision::Build);
|
||||||
|
EXPECT_EQ(cache.getReuseCount(), reuseBefore);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Step117Safety, CameraStyleAnnotationAndContextRequireRebuildBeforeReuse) {
|
||||||
|
using Mutation = void (*)(RetainedUnderlayRevisionState&);
|
||||||
|
const std::array<Mutation, 5> mutations{{
|
||||||
|
[](auto& state) { state.cameraMatrix[12] += 1.0; },
|
||||||
|
[](auto& state) { state.viewport = {800, 600}; },
|
||||||
|
[](auto& state) { ++state.contentRevision; }, // style/glyph/image/context epoch
|
||||||
|
[](auto& state) { ++state.topologyRevision; }, // annotation/layer group
|
||||||
|
[](auto& state) { ++state.rangeConfigRevision; },
|
||||||
|
}};
|
||||||
|
for (std::size_t i = 0; i < mutations.size(); ++i) {
|
||||||
|
SCOPED_TRACE(i);
|
||||||
|
RetainedUnderlayRevisionTracker tracker;
|
||||||
|
RetainedUnderlayCache cache;
|
||||||
|
auto state = revisionState();
|
||||||
|
const auto cacheKey = [&] { return RetainedUnderlayKey{state.viewport, 0, *state.boundary, state.cameraMatrix}; };
|
||||||
|
const auto oldRevision = tracker.observe(state);
|
||||||
|
ASSERT_EQ(cache.evaluate(cacheKey(), oldRevision, true), RetainedUnderlayDecision::Build);
|
||||||
|
cache.markBuildSucceeded(); // State-machine fixture only.
|
||||||
|
mutations[i](state);
|
||||||
|
const auto newRevision = tracker.observe(state);
|
||||||
|
EXPECT_NE(newRevision, oldRevision);
|
||||||
|
EXPECT_EQ(cache.evaluate(cacheKey(), newRevision, true), RetainedUnderlayDecision::Build);
|
||||||
|
EXPECT_FALSE(cache.isValid());
|
||||||
|
EXPECT_EQ(cache.getReuseCount(), 0u);
|
||||||
|
auto input = fastPathInput();
|
||||||
|
input.cacheValid = cache.isValid();
|
||||||
|
input.revisionMatches = cache.getBuildRevision() == newRevision;
|
||||||
|
EXPECT_FALSE(evaluateParticleFastPath(input).candidate);
|
||||||
|
EXPECT_NE(particleFastGateFailureMask(input) & (1u << 2), 0u);
|
||||||
|
EXPECT_NE(particleFastGateFailureMask(input) & (1u << 3), 0u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RenderSegmentLocality, MixedExecutionDrawsEachLiveRangeOnceInStyleOrder) {
|
TEST(RenderSegmentLocality, MixedExecutionDrawsEachLiveRangeOnceInStyleOrder) {
|
||||||
ResolvedRenderSegmentPlan plan;
|
ResolvedRenderSegmentPlan plan;
|
||||||
plan.valid = true;
|
plan.valid = true;
|
||||||
|
|||||||
12
粒子开发记录.md
12
粒子开发记录.md
@@ -1169,3 +1169,15 @@ Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2`
|
|||||||
- 2026-10-11 STEP-116 RDC:审查Native空Annotation恢复、原STEP113受限空层移除、缺源诊断、7个C++测试源码与同HEAD/SHA复测脚本,git diff --check、Python AST通过。修正Mac测试命令rg为grep -E。实际CMake macos-metal配置exit1缺libuv,未继续C++测试/Android Gradle/真机Fast,PARTIAL;缺tide与Symbol R仍BLOCKED。
|
- 2026-10-11 STEP-116 RDC:审查Native空Annotation恢复、原STEP113受限空层移除、缺源诊断、7个C++测试源码与同HEAD/SHA复测脚本,git diff --check、Python AST通过。修正Mac测试命令rg为grep -E。实际CMake macos-metal配置exit1缺libuv,未继续C++测试/Android Gradle/真机Fast,PARTIAL;缺tide与Symbol R仍BLOCKED。
|
||||||
|
|
||||||
- 2026-10-11 STEP-116 RDC实测:按用户明确授权由Mac实际编译并安装Test App,源码c48a72a9、APK SHA a8b7f4e0f8e026bde8835e18a04876062be84cce3a3749a511cb08605d9f8a35、设备192.168.200.139:5555安装SHA一致。原STEP113 STATIC_RC 90s Fast0/Full+920;Native65层C正常两层,#22近120帧零失败,空Annotation修复有效;R缺tide、Build/Reuse0、Placement不稳定,119Full/0Fast,仍FAIL/PARTIAL。报告docs/60_测试/STEP-116_FZG1_原PBF实机验收结果_20261011.md;原始JSON/Screenshot存Git忽略artifacts目录。
|
- 2026-10-11 STEP-116 RDC实测:按用户明确授权由Mac实际编译并安装Test App,源码c48a72a9、APK SHA a8b7f4e0f8e026bde8835e18a04876062be84cce3a3749a511cb08605d9f8a35、设备192.168.200.139:5555安装SHA一致。原STEP113 STATIC_RC 90s Fast0/Full+920;Native65层C正常两层,#22近120帧零失败,空Annotation修复有效;R缺tide、Build/Reuse0、Placement不稳定,119Full/0Fast,仍FAIL/PARTIAL。报告docs/60_测试/STEP-116_FZG1_原PBF实机验收结果_20261011.md;原始JSON/Screenshot存Git忽略artifacts目录。
|
||||||
|
|
||||||
|
### 2026-10-11 STEP-117 原 PBF R 首次 Build 与 Fast 安全准入(BLOCKED)
|
||||||
|
|
||||||
|
- 实际GPT-6.1-Sol(gpt-6.1-sol)/high已从当前会话turn_context核实;Mac particle/main起点43e5f5b91598b9c3d3f1c788052d4bbd2d616668,Integration本地只读HEAD80667d6c343411d03a760425438e3d292f452118。无模型切换、子代理、commit/push或跨仓写入。
|
||||||
|
- 完整回读STEP116原STATIC_RC 120帧JSON,SHA cd491d2acca97119f1d4f2d6f77eb7b229c17b90d4be1181a59202308429b219。119Full/0Fast/1pending、mismatch0;pre105帧changed=false/fade非零/transition=true,15帧true/0/false,全部R placementGate失败。原63层/C两天气层及空Annotation受控修复保留。
|
||||||
|
- 源码证明缺源无新RenderItem不等于GPU零贡献/无旧数据:双group停用要processChanges执行,markLayerRenderable不清旧drawables/tiles;原JSON无提交代次/旧Renderable数据排除证书。Symbol重算changed、recent stale,无首次Build窗口;fingerprint只有Impl/index,不含最终opacity/vertices/atlas/collision/uniform。
|
||||||
|
- 按任务安全停止条件,缺tide继续missing-source,Symbol R继续fail-closed,未放宽24Gate/ready/revision、未删tide-spots或补假tide、未以STEP114烟测替代。零贡献准入和结果证书未实现,真实Build/Reuse/Fast目标未完成。
|
||||||
|
- 两个既有C++测试文件新增七项Step117Safety:真实Controller/Placement、真实缺源RenderTree及sourceDiff、RemoveGroup队列、Tile/Glyph/Image回调/context/style epoch、cache墓碑与revision重建;全部NOT RUN/NOT COMPILED,不冒称GPU/并发/像素PASS。
|
||||||
|
- 已生成四份中文调查/Step/验收计划/完成报告并追加本记录;仅执行原证据解析、静态一致性/范围/diff检查。未运行Native编译/CMake/Ninja/Bazel/GTest、Gradle/ADB/安装/Jest、设备或性能测量,STEP110/111未跟踪MD与原Git忽略JSON保持。
|
||||||
|
- 交RDC独立审计及定向Native验证;由粒子负责人协调Shared Core缺源与Symbol证书设计、Style/Host真实tide语义。受控实现完成后再安排一次用户授权的Android源码/APK/设备SHA与原STATIC_RC≥90秒、120帧24Gate/Mutation/用户画面闭环。详细状态见docs/报告/STEP-117_原PBF_Fast缓存准入_Codex完成报告_v1.md。
|
||||||
|
|
||||||
|
- 2026-10-11 STEP-117 RDC:新加7个C++非Jest安全回归用例源码,针对缺Source/旧GPU组、Symbol首次Build及源/图像/字形/相机变更fail-closed;两个test/renderer源文件由Android NDK OpenGL/x86_64实际compile_commands.json做C++20 -fsyntax-only,均exit0(6.3s/5.3s)。生产Native/Fast Gate/APK未改,本轮不重复构建相同APK,GTest运行/真实Fast仍BLOCKED。需要Shared Core结果证书和Integration核验真实tide语义,报告见docs/20_调查/STEP-117_PBF_R首次缓存Build安全证据_v1.md。
|
||||||
|
|||||||
Reference in New Issue
Block a user