feat: add STEP-113 Android PBF fast gate diagnostics
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
tei
2026-10-11 09:11:27 +09:00
parent c6d13e1059
commit 92efa36f4c
14 changed files with 1368 additions and 5 deletions

View File

@@ -0,0 +1,250 @@
# STEP-113 FZG1 PBF Layer 与 Fast Gate 诊断 Codex 完成报告 v1
日期:2026-10-11(JST)。结论:**PARTIAL:诊断和专项测试场景源码已交付;构建、设备及生产113层完整等价未验收。**
## 1. 基线、模型与授权
- Mac.lan / Darwin 24.6.0 / x86_64;仓库 `/Users/tei/dev/MapLibreParticleLab`。
- 起点及交付 HEAD:`particle/main@c6d13e1059d464d312ac33acac87967300fa5dc4`;无 commit/push、无新 branch/worktree、无发行。
- 实际模型 **GPT-6.1-Sol(`gpt-6.1-sol`)/ high**,从本会话 `01a12808-4436-7d33-bc56-9135722348b1` rollout 的 `turn_context.model/effort` 核实。未切换模型、未启动其他 Codex/子代理。
- Native/Test App 的源码版本 `platform/android/VERSION=13.6.1-particle.23`,RN package 同为 `.23`;没有改版本或覆盖正式制品。新诊断只存在于本次未提交源码,不能把现有正式 V23 APK 当本次制品。
- NavSea 只读 HEAD `ad9aa043fde37f87462f31de3fbd8ce008f8424b`,读取时 tracked/untracked status 均无输出;Integration 本地 HEAD `80667d6c343411d03a760425438e3d292f452118`。没有 fetch/pull、跨项目写入或消息发送;Integration 远端核验采用用户提供的 RDC 事实。
- 起点 tracked clean;已有 STEP-110/111/113 三份未跟踪任务书均保留。子模块状态均为空格前缀,没有操作子模块。
- 已读根 AGENTS、PARTICLE_BASELINE、项目规范全部文件、总则 README 和四份有效总则、STEP-113 任务书、STEP-112 调查/记录/报告,以及 STEP-102/106 的相关实现与记录。
- 本轮不执行 CMake/Ninja/Bazel、Native 测试、Gradle/APK、ADB/安装/Logcat、Jest、发布、提交或 push。以下命令仅交 RDC 执行。
## 2. 实际修改与新增文件
| 文件 | 变更目的 |
|---|---|
| `src/mln/renderer/particle_fast_path.hpp` | 24项固定顺序表、无副作用失败掩码;生产 evaluator 原样保留 |
| `include/mln/renderer/render_segment.hpp` | 平台无关帧/phase/cache诊断值结构,现有 snapshot 可选 `fastGateTrace` |
| `src/mln/renderer/retained_underlay_runtime_state.hpp` | 120帧环形缓冲、生命周期聚合、受锁保护的快照/reset/完成记录 |
| `src/mln/renderer/render_segment_json.hpp` | 现有 JSON 出口增加可选 trace,24项状态、窗口与生命周期计数、pre/post |
| `src/mln/renderer/renderer_impl.cpp` | 原始 input/decision 采集点、实际 pre cache validity/revision、渲染后完成记录 |
| `src/mln/renderer/renderer.cpp` | 生命周期 reset 与没有 RenderTree 时的明确 outcome |
| `src/mln/map/map.cpp` | 外部诊断读取携带 trace;renderer 内部读不复制历史环形数据 |
| `test/renderer/retained_underlay_cache.test.cpp` | 新增4个 `FastGateTrace.*` C++ 回归用例;未运行 |
| `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step113PbfGateScene.kt`(新增) | 真 PBF、五个场景、parity证明/限制、固定预报、低频UI与分块导出 |
| 同目录 `ParticleCoreLayerValidationActivity.kt` | 菜单/Intent、scene生命周期与旧场景隔离,诊断区域临时扩展 |
| `docs/50_Step记录/STEP-113_FZG1_PBF_Layer与FastGate诊断_v1.md`(新增) | 当前状态、RDC验收填写栏 |
| 本完成报告(新增) | 源码交付事实、命令、证据与限制 |
| `粒子开发记录.md` | 仅末尾追加本次短记录 |
没有修改 Shader、Placement、Retained Cache 的准入/等价/回退算法、RN 类型或方法、JNI 方法签名、NavSea、Integration、构建流水线和发行版本。扩展的是任务明确授权的可选诊断 JSON 与其内部值结构,不新增公共控制 API/Host 契约。若后续需要新的公共控制面,应先走 Integration RFC。本任务不为未来接口变更提供授权。
## 3. B:24 Gate 同帧记录与真实性边界
每次真实 `tryRenderParticleFastFrame` 用**已经计算好的同一个 input**调用原 evaluator 一次,再独立计算掩码。没有再次调用 `particleFastPathDynamicState`、needsRepaint、Placement 计算或 cadence 推进。新增 Cache getter 是 `const noexcept` 的纯字段读取;用于观察已被 aggregate 短路掩盖的 R 状态。
`knownMask=0x00ffffff`:当前24条 evaluator 布尔输入全部已知;`gateStatus` 逐项给出 PASS/FAIL。若以后缺少输入,可通过 knownMask 显式输出 UNKNOWN。**这里观测的是实际 Gate 输入;如没有 prepared scene,其已有 false 标志导致 Gate FAIL,不表示调查过一个尚不存在的 scene。**
`firstFailure` 保存生产 evaluator 真正返回的首错;`failMask` 保存同一 input 的失败全集。`decisionConsistent` 比较首位失败与生产决定,`decisionMismatch` 累计不一致;任何非零值均需要保留现场,不能接受归因结果,也不会放宽生产 Gate。位0对应顺序1;enum 的 camera/viewport 数值顺序不能用作掩码顺序。
| 顺序 | 失败名 | FAIL 谓词 |
|---:|---|---|
| 1 | no-prepared-tree | `!hasPreparedTree` |
| 2 | retained-disabled | `!retainedEnabled` |
| 3 | cache-invalid | `!cacheValid` |
| 4 | revision-mismatch | `!revisionMatches` |
| 5 | content-mutation | `!contentRevisionMatches` |
| 6 | viewport-changed | `!viewportMatches` |
| 7 | camera-changed | `!cameraMatches` |
| 8 | update-parameters-changed | `!updateParametersMatch` |
| 9 | style-not-loaded | `!styleLoaded` |
| 10 | boundary-changed | `!boundaryMatches` |
| 11 | topology-changed | `!topologyMatches` |
| 12 | static-unstable | `!staticStable` |
| 13 | placement-or-fade | `hasPlacementTransition` |
| 14 | pending-changes | `hasPendingChanges` |
| 15 | non-particle-transition | `hasNonParticleTransition` |
| 16 | non-particle-repaint | `hasNonParticleRepaint` |
| 17 | fading-tiles | `hasFadingTiles` |
| 18 | no-particle-repaint | `!particleNeedsRepaint` |
| 19 | still-image-request | `stillImageRequest` |
| 20 | unsupported-mode | `!continuousMode` |
| 21 | debug-options | `!debugDisabled` |
| 22 | unsupported-continuous-layer | `unsupportedContinuousLayer` |
| 23 | unsupported-scene | `!supportedScene` |
| 24 | annotation-mutation | `annotationMutation` |
因此 CacheInvalid 同帧也会保留 #22、#23 的真假,不再通过后续Full快照推测此前Gate。
每帧有 lifecycle 内唯一 `sequence`、renderer `frame`、steady-clock 的 `updateTimeNs`;没有树时多个尝试可以共用一个尚未完成的 renderer frame,**关联主键是 lifecycle+sequence**。不把 updateTimeNs 当 UTC/forecast。外层原有fastPathHit/Miss/Full atomics沿用原快照语义,可能与正在写入的trace末帧相差一个调用阶段;逐帧归因以frame记录为准,不把外层字段拼成额外原子帧。
- `cacheInputs` 是实际 pre-fast cache exists/valid/buildRevision/staticRevision;最多16个 R,超限明确 `cacheInputsTruncated=true`,所有 aggregate Gate 仍完整。
- `pre` 保存判定阶段的缓存计数/失效/回退原因与上一已完成 RenderTree 诊断快照。`preFastPlacementTransition` 才是本次 Gate #13 的当前 Controller 值;`placementTransitionsEnabled` 来自本次 UpdateParameters。
- `post` 在渲染末尾取得同帧 R build/reuse/invalidation/fallback、sourceReady/stable、decision、actualExecution、Placement changed/transition/fade与Full计数。Full、Fast、无树分别有明确 outcome;中途异常或尚未结束时 `completed=false/post=null`。
- `placementBasis` 区分历史 RenderTree、当前 Full tree、当前 Fast tree(未重新计算Placement);没有完成过的诊断快照标 UNKNOWN。没有将 post Full 数据回填 pre Gate。
- 每phase最多16个R;`retainedSamplesTruncated` 明示超限。无同帧每Symbol输出签名、旧Placement options/duration/commitTime/fadeStartTime、CPU/GPU阶段计时,这些不在本次实现中伪造。
- Debug 的 `processSimulationAdvance` 复用现有进程级 atomic 计数;Release为null。它不是单Map的计数,也不等于Fast尝试或FPS。
120帧全部Gate每次尝试都记录;容量满时覆盖最早帧,`overwritten` 累计。生命周期 `gates[].failures/firstFailures` 保留聚合;`windowFailures`、窗口首末序号、窗口 Full/Fast/无树计数另行导出。默认30fps时120帧约4秒,真实渲染频率可能更高,不能承诺完整60秒逐帧档案。
环形记录在 render thread 更新;写入、完成、reset和外部copy沿用 `rangeMutex`。Android UI只读现有共享snapshot,不操作Renderer可变对象。内部render snapshot默认不复制trace;只有外部 `Map::getRenderSegmentDiagnostics()` 包含历史。reset发生于绑定新的 runtime state、观测到 styleLoaded true→false、context lost、Renderer.clearData;每次普通 Full miss清prepared tree**不会**清trace。sceneGeneration/configRevision另用于区分UI场景切换;同步加载没有暴露false帧时,不能假定trace epoch必然随UI场景切换。
新增CPU工作为O(24+R)、固定容量历史;没有额外GPU pass。每帧仍有小型vector/string副本与短mutex临界区,外部读取序列化120帧也有成本。**内存字节数和CPU成本没有实测,不声明低于某一百分比**;RDC需量测。没有诊断开关的新RN API;如需成本对照,应使用同环境基线源码制品与本次制品并记录差异。
## 4. A:Style、Layer 与场景等价度证据
| 项目 | 证据等级与当前结论 |
|---|---|
| 正式Style/Sprite/Glyph/VectorTile URI | **SOURCE-PROVEN**:NavSea `src/config/builtinRuntimeUrlConfig.ts` 与新场景常量相同 |
| NavSea当前分段选择器 | **SOURCE-PROVEN**:`RenderSegmentHost.tsx` 为R→C,C从 `rn-weather-color` 开始;不是现场四段计划 |
| 天气片段 ID/type/source | **SOURCE-PROVEN**:`particleStyle.ts` 调用shared fragment,追加到顶;shared `packages/maplibre-particle-rn/src/index.ts` 定义 `rn-weather-fields`、`rn-weather-color`、`rn-weather-particles` |
| 正式63层保序/显隐/完整定义 | **TEST-APP-STRUCTURAL**:运行时从正式URL加载,要求63层和实际锚点ID;完整原始定义逐层不变、顺序不变,并导出生产manifest与实际Native styleLayers。**尚未在设备执行该证明** |
| Sprite/Glyph/VectorTile访问成功 | **NOT-VERIFIED**:本机web open失败;urllib回读失败于域名无法解析,没有服务器JSON/SHA或瓦片访问成功证据 |
| 113层及[0,13)/[13,33)/[33,107)/[107,113) | 用户STEP-112历史现场输入;本轮没有同版本完整Layer/Source/visibility/业务数据快照,**NOT-VERIFIED,未完整复制** |
| 旧NavSea FZG采样 | 只读找到V15报告与129层采样;年代/版本/层数均不同,不用于补造当前113层 |
| 本轮真机/性能 | **DEVICE-MEASURED:无本轮结果** |
生产URI分别为:
- Style:`https://pbf.jpcn.ccwu.cc/style/style.navsea-delivery-full-semantic-extentfix.json`
- Sprite:`https://pbf.jpcn.ccwu.cc/sprite/sprite`
- Glyph:`https://pbf.jpcn.ccwu.cc/fonts/{fontstack}/{range}.pbf`
- VectorTile:`https://pbf.jpcn.ccwu.cc/pbf/pbf-delivery-full-20260418-rebuild/{z}/{x}/{y}.pbf`,source=`navsea_delivery`。
场景会检查真实回读的资源URI;变更或缺失则显示BLOCKED并导出原因,不切换假地图。`productionFingerprintSha256` 是SDK回读序列化JSON的UTF-8 SHA-256,**不是HTTP原始字节SHA**,且URL本身可变。导出styleVersion/name/metadata(styleVersion是Style规格版本,包版本未知时为null)、生产/增强fingerprint、basemanifest、请求plan、最终Native所有Layer的index/id/type/source/visibility,以及段边界与层名。Native可能追加Annotation等内部层,不能把JSON基础63层等同实际总层数。
| 场景 | 行为与等价限制 |
|---|---|
| PBF63 | 正式63层原定义;无测试天气片段;全RETAINED,实际总层数以Native为准 |
| STATIC_RC | 原63层+正式类型的天气/粒子片段(JSON65层);保序append;当前NavSea源码RC选择器;不等价NavSea全部动态业务层 |
| PARTICLE_OFF | 与STATIC_RC同样层序,粒子visibility=none;WeatherColor/forecast/camera保持对照 |
| PARTIAL_RCRR | 原63层+天气片段,片段放在实际 `clip-outline` 后;四段锚点为 `sea-area-fill`、`special-pattern-line-754`、**实际回读的最后生产层ID**;明示结构RCRR,与现场113层/数字边界不同 |
| SOURCE_CHANGE | STATIC_RC加一个独立GeoJSON/circle测试Source;显式菜单单次更新;结构探针,不冒充AIS/Radar/航线等生产数据 |
所有带天气场景使用既有ECMWF canonical两个时间片(2026080700/06),forecast请求 `1786060800000` ms,PAUSE,targetFps=30,粒子1024。与NavSea当前QBIN/预报业务输入不等价。命令接受结果逐项保存;实际Native预报时间没有新增查询API,`actualForecastTimeObservedMs=null`,不把Host请求值当Native独立回读结果。camera请求33.45/129.97、zoom10.5、bearing/pitch0;场景禁用手势,退出恢复原手势设置。静态轮询不改Source/Symbol/forecast/camera。
Native准入限制保持原样;RCRR结构模式预期可以暴露不支持的C层和Symbol R阻塞,但这只是源码预期,不是已经在FZG测到的结果。
## 5. C:UI、导出及精确RDC命令
入口:Test App `STEP 093 → STEP-113 FZG1-PBF GATE`。五个场景、`EXPORT LAST SNAPSHOT`、`MUTATE PROBE SOURCE ONCE`、退出。加载中或失败时也保留低频诊断读取,sceneReady=false/blockedReason明确标注,不能把可能仍在加载的旧Native层表当已完成场景。每3秒只有一次Native诊断查询;UI首错来自trace末帧,失败排名来自同copy聚合,各段显示范围/state/build/reuse/invalidation。仅STEP-113期间增大诊断区域,退出恢复。
每30秒一条逻辑summary(通常少量物理Logcat分块);不是每33ms输出JSON。完整120帧和Layer表仅手动导出最近一次copy,写App私有 `files/step113-<SCENARIO>-<elapsed>.json` 并使用标签 **STEP113Gate** 输出Base64分块。每块payload≤2400 ASCII字符,携带schemaVersion/kind/exportId/chunkIndex/chunkCount/encoding;按exportId和chunkIndex完整拼接后Base64解码,缺块不能当完整证据。手动完整导出会产生较多块,优先直接回读私有JSON文件。
以下仅RDC执行,本轮Codex没有执行。先在macOS普通Terminal核对设备主ABI与标准脚本的x86_64一致;不同则停止本构建流程并记录,不自行改脚本/环境:
```bash
cd /Users/tei/dev/MapLibreParticleLab
step113_abi="$(adb -s 192.168.200.139:5555 shell getprop ro.product.cpu.abi | tr -d '\r')"
step113_abilist="$(adb -s 192.168.200.139:5555 shell getprop ro.product.cpu.abilist | tr -d '\r')"
printf 'FZG1-2 primary ABI=%s; ABI list=%s\n' "$step113_abi" "$step113_abilist"
test "$step113_abi" = x86_64 || { echo 'ABI不一致,停止'; return 1 2>/dev/null || exit 1; }
./tools/particle_android_validation/build_validation_apk.sh
```
标准产物:`artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk`、`build.log`、`build-info.txt`;脚本记录commit/branch/dirty/SHA/体积并自验ZIP与Native ABI,失败不得复用旧APK。本轮源码未提交,build-info里的dirty必须真实,另保留任务文件diff/hash以证明制品来自本次修改。
安装前RDC核对现存同包签名,签名不匹配不得自动卸载用户数据;保留INSTALL_FAILED错误。安装与静态场景启动:
```bash
adb -s 192.168.200.139:5555 install -r artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
adb -s 192.168.200.139:5555 shell am start -S -n org.maplibre.android.testapp/org.maplibre.android.testapp.activity.particle.ParticleCoreLayerValidationActivity --es step113_scenario STATIC_RC
adb -s 192.168.200.139:5555 logcat -v raw -s STEP113Gate:I '*:S' > artifacts/maplibre-particle/android-validation/step113-static-rc.log
```
最后一条在RDC普通前台Terminal采集,窗口完成后Ctrl-C。其他场景各用一条明确启动命令,并独立保留日志:
```bash
adb -s 192.168.200.139:5555 shell am start -S -n org.maplibre.android.testapp/org.maplibre.android.testapp.activity.particle.ParticleCoreLayerValidationActivity --es step113_scenario PBF63
adb -s 192.168.200.139:5555 shell am start -S -n org.maplibre.android.testapp/org.maplibre.android.testapp.activity.particle.ParticleCoreLayerValidationActivity --es step113_scenario PARTICLE_OFF
adb -s 192.168.200.139:5555 shell am start -S -n org.maplibre.android.testapp/org.maplibre.android.testapp.activity.particle.ParticleCoreLayerValidationActivity --es step113_scenario PARTIAL_RCRR
adb -s 192.168.200.139:5555 shell am start -S -n org.maplibre.android.testapp/org.maplibre.android.testapp.activity.particle.ParticleCoreLayerValidationActivity --es step113_scenario SOURCE_CHANGE
```
不要把这些命令连续执行当场景测试;每个场景至少预热10秒、观察60秒、手动导出窗口,再切下一场景。SOURCE_CHANGE先导出baseline,单击手动探针变化,等一次3秒刷新后再次导出;不添加周期Symbol更新。
点击 `EXPORT LAST SNAPSHOT` 后回读最近文件(run-as仅适用于该Debug App):
```bash
step113_file="$(adb -s 192.168.200.139:5555 shell run-as org.maplibre.android.testapp ls -t files | tr -d '\r' | rg '^step113-.*[.]json$' | head -n 1)"
test -n "$step113_file" || { echo '未找到手动导出文件'; return 1 2>/dev/null || exit 1; }
adb -s 192.168.200.139:5555 exec-out run-as org.maplibre.android.testapp cat "files/$step113_file" > "artifacts/maplibre-particle/android-validation/$step113_file"
shasum -a 256 "artifacts/maplibre-particle/android-validation/$step113_file"
adb -s 192.168.200.139:5555 exec-out screencap -p > artifacts/maplibre-particle/android-validation/step113-screen.png
adb -s 192.168.200.139:5555 logcat -b crash -d > artifacts/maplibre-particle/android-validation/step113-crash.log
```
如果只保留Logcat,使用下面的离线重组命令;每个导出必须收齐chunkCount,否则直接报错:
```bash
python3 - <<'PY'
import base64, json
from pathlib import Path
root = Path('artifacts/maplibre-particle/android-validation')
groups = {}
for line in (root / 'step113-static-rc.log').read_text().splitlines():
try:
c = json.loads(line)
except json.JSONDecodeError:
continue
if c.get('encoding') != 'base64-utf8':
continue
key = (c['exportId'], c['kind'])
count, parts = groups.setdefault(key, (c['chunkCount'], {}))
assert count == c['chunkCount'], key
parts[c['chunkIndex']] = c['payload']
for (export_id, kind), (count, parts) in groups.items():
assert set(parts) == set(range(count)), ('缺块', export_id)
raw = base64.b64decode(''.join(parts[i] for i in range(count)), validate=True)
json.loads(raw)
(root / f'step113-{export_id}-{kind}.json').write_bytes(raw)
PY
```
RDC的macOS Native定向检查可按当前preset执行(历史缺libuv阻塞不代表当前环境仍相同;若失败保留首错,不扩大改依赖):
```bash
cmake --preset macos-metal
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
build-macos-metal/mbgl-test-runner --gtest_filter='FastGateTrace.*:ParticleFastPath.*:RenderSegmentDiagnostics.*:RenderSegmentPlacementFree.*:RenderSegmentLocality.*' --gtest_color=no
```
配置失败就停止该链;不运行旧runner冒充新源码通过。Metal host测试不能替代Android OpenGL/实体机/iOS验收。
## 6. 已执行静态检查与未做项
已执行:只读Git/源码/文档调查、diff范围检查、`git diff --check`(退出0);新增文件另用no-index whitespace检查。静态文本核对24条谓词及极性/顺序一致;生产 evaluator 与HEAD逐字相同;STEP-102 fixture与500ms poll逐字未变。最终hash与append-only核对见第7节。
4个测试源码覆盖:全部24独立失败位/生产首错顺序;CacheInvalid与#22/#23同帧并存、137次记录后120条有序窗口与reset;pending/null post/错误shadow显式计数和完成幂等;18个R截断及pre/post独立缓存计数。**没有运行这些测试,没有C++/Kotlin编译或语法编译PASS结论。**
本轮无APK/AAR、体积或SHA,无设备运行日志、截图、FPS、CPU、trace开销或性能改善数字。没有已观察到的构建/测试失败;未执行不表示会通过。
剩余RDC事项:Native/Kotlin编译和上述定向测试;设备ABI/制品SHA/版本证据;正式资源加载、原63层manifest/实际层序;plan接受与最终valid原因;所有24状态与首错一致性;cache-invalid同帧后续失败;Full/post和pre分离、Source变更前后、粒子关闭对照;reset/退出/恢复与旧场景回归;开销/CPU和截图。**APK成功仅是构建证据。**
113层完整等价仍需同版本真实Layer/Source/业务数据/显隐/选择器快照后才能扩展;本任务交付的部分模式不为生产Full循环提供完整因果或性能验收结论。
## 7. 收尾证据
- STEP-110任务书SHA-256:`33037df71b4b30aa7956d59f4b99f77af3085405b24111bc0fe11ec857a93db0`。
- STEP-111任务书SHA-256:`f3a5806f25384bf46055db2edfea0d21bfbc4124184bc813b46e38b8079c1ec4`。
- STEP-113任务书原样SHA-256:`4e3fef391dc3addef2702b3d588c1fcc8f79b898b5d9004bfc1410070533e0b4`。
- HEAD保持起点,暂存区为空;仅任务源码/测试、两个新交付文档和开发记录追加,既有三任务书未暂存。没有远端HEAD回读、commit/push或制品发布行为。
- 开发记录的HEAD原始160442字节前缀完全保留,原SHA-256=`070aaeaf85aa8fdbe8b15a899f74fd492a0e3eb2b6442b37cb3d5ee9724dbd24`;本次仅末尾追加1120字节(7行)。静态检查是范围与一致性证据,不是全任务PASS。
## RDC 独立验收补记(2026-10-11,设备证据)
以下是 Codex 退出后 RDC 新执行的证据,不修改上文 Codex 未构建/未实测的历史结论。本次阶段判定:**PARTIAL;Android 构建 PASS;五场景稳定基线采样 PASS;113 层等价与性能 NOT VERIFIED**。
- 环境:Mac、particle/main;构建源码基于 c6d13e1059d464d312ac33acac87967300fa5dc4 加 STEP-113 未提交改动,build-info 明确 git_dirty=true。此 APK 不是 Source Lock / 正式发行。
- 标准 build_validation_apk.sh 于 2026-10-11 08:35:08 JST 退出码 0;Gradle BUILD SUCCESSFUL in 19m 22s;Java 17.0.20.1;OpenGL/x86_64;ZIP/ABI/体积/SHA 自检通过。
- APK:artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk;66,587,454 bytes;libmaplibre.so 40,033,976 bytes;SHA-256 0054248bc3872e8670df4e9a10d11f1d65c0912a0482586cd7a247e880a6eaef。记录:同目录 build-info.txt、build.log。
- 设备:FZG1-2,ADB 192.168.200.139:5555,主 ABI x86_64;明确 -s 的 adb install -r 返回 Success,未卸载数据;设备安装后版本 13.6.1-particle.23。正式 PBF Style 模式运行并加载。启动前数秒 sceneReady=true 但 Native Layer=0 / plan not-configured 是加载暂态;只接受之后的 Native Layers 非零、planValid=true 稳定记录。
- 五个场景均由 ADB 明确 serial 启动;STEP113Gate Logcat Base64 summary 成功还原。每场景实际设备稳定状态的 decisionMismatch 都是 **0**。Full/Fast/Attempts 为生命周期累计,并非精确 60 秒窗口。
| 场景 | Native Layers | Attempts | Full | Fast | Retained 及关键证据 |
|---|---:|---:|---:|---:|---|
| PBF63 | 64(63+内部层) | 106 | 106 | 0 | R[0,64) Build0,unknown-dependency;无粒子持续驱动 |
| STATIC_RC | 66 | 876 | 875 | 0 | R[0,63) Build0,unknown-dependency;unsupported-continuous-layer、unsupported-scene 各876 |
| PARTICLE_OFF | 66 | 70 | 70 | 0 | no-particle-repaint=70;非相等时长性能对照 |
| PARTIAL_RCRR | 66 | 862 | 861 | 0 | R0[0,3) unknown-dependency;R2[39,64) 与 R3[64,66) Build0/static-placement;两个 unsupported Gate 各862 |
| SOURCE_CHANGE | 67 | 888 | 888 | 0 | 基线已记录;**没有执行菜单手动 Source mutation** |
- STATIC_RC 同帧失败全集汇总 CacheInvalid=870、revision-mismatch=871、placement-or-fade=780;PARTIAL_RCRR CacheInvalid=856。这些失败条件可能在**同一帧**并存,不能累加为帧数。即使修复缓存 Build,也还有 #22/#23 与其它独立 Gate。
- 设备摘要 JSON(不纳入 Git):artifacts/maplibre-particle/android-validation/step113/ 下的 pbf63-summary-ready.json、static-rc-summary.json、particle-off-summary.json、partial-rcrr-summary.json、source-change-baseline-summary.json。它们只是低频 summary,不是导出的完整 120 帧。
- 仍 NOT VERIFIED:原 NavSea 113 层完整 Layer/Source/显隐及真实四段边界;实际 PBF/Sprite/Glyph 画面截图;Source 单次变更后前后对照;120帧手动详情导出;C++ GTest 运行;reset/后台、旧 STEP-102 场景回归;CPU/GPU/诊断开销;生产性能提升、正式发行。不得把部分结构等价当成现场复测或将 STEP-113 判为 CLOSED/PASS。
- 下一阶段必须分别处理 retained first-build 的安全准入、unsupported continuous layer、unsupported scene;不能直接删除 Gate 放行。