fix: secure Symbol Retained drawable lifetime and record investigations
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:
161
docs/40_任务/STEP-110_R0_Placement跨段归因只读调查_Codex任务_v1.md
Normal file
161
docs/40_任务/STEP-110_R0_Placement跨段归因只读调查_Codex任务_v1.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# STEP-110 R0 Placement 跨段归因与缓存安全边界只读调查 — Codex 任务 v1
|
||||
|
||||
## 一、任务性质与核心问题
|
||||
|
||||
**性质:Particle Native / Shared Core 专项,只读调查;不实现、不修复、不编译、不上机。**
|
||||
|
||||
用户要求粒子项目独立回答:
|
||||
|
||||
> Native 能否区分“R0 自己的 Placement 变化”和“其他 RenderSegment 引起的 Placement 变化”?如果能区分,是否足以在**不破坏 Symbol 碰撞、文字/图标位置及图层顺序**的条件下让未变化的 R0 复用缓存?
|
||||
|
||||
必须把以下不同概念分开审查:
|
||||
1. **事件来源**:哪个 source/layer/segment 引发了 placement/repaint/revision;
|
||||
2. **实际影响范围**:全局碰撞计算是否使 R0 的 Symbol 位置、可见性、fade 或绘制结果改变;
|
||||
3. **缓存安全判据**:能否证明 R0 内容/Placement 仍与已缓存画面等价;
|
||||
4. **当前实现**:上述信息目前是否已有、是否按 Segment 使用、还是仅采用全局保守 Gate。
|
||||
|
||||
禁止预设“全局 Placement 变化一定是 Bug”,也禁止以“R0 自己没有提交数据”直接推导“R0 视觉必然没有变化”。
|
||||
|
||||
## 二、仓库、版本与事实优先级
|
||||
|
||||
- 项目:`/Users/tei/dev/MapLibreParticleLab`,正式分支 `particle/main`、远端 `origin/particle/main`。
|
||||
- 创建任务时只读确认:`particle/main` HEAD `2df504cdc0403bdad85d3f31f16fd54a8744abac`、干净工作树。执行时必须**重新读取 Git 实际状态**,不得把此 HEAD 当作永恒基线。
|
||||
- NavSea 产品实机所用 APK 内 `assets/component-manifest.json` 记录:RN / Android Native AAR `13.6.1-particle.23`。V23 正式来源对应 `refs/tags/maplibre-particle/rn/13.6.1-particle.23`、GSRL Git commit `87f3d1c59a52581fb8339f0ea7d106b9f4b94fef`。
|
||||
- **必须分别标明 V23 发布源码与当前 `particle/main` 的事实**。如当前 main 有未发行后续改动,不能以 main 代替 V23,不能以 V23 APK 推断未发行修复已经生效。
|
||||
- 跨项目事实遵循 `D:\React\navsea-particle-integration\instructions\NAVSEA_PROJECT_INSTRUCTIONS.md` 及最新 COORD / RFC / ADR / Contract / Status;当前既有外部契约 C-001。此任务不新增/更改公共 API 或契约。
|
||||
- 粒子项目根 `AGENTS.md`、`PARTICLE_BASELINE.md`、`docs/00_项目规范/`、`docs/00_项目总则/README.md` 与四份有效总则必须先读,按当前项目事实处理过时的历史环境/发布坐标。
|
||||
- 必读既有证据:STEP-088、089、090、092、094、099、100、102、106、108、109;重点对比 STEP-090 早期缓存/快路成功条件、STEP-102 placement-free 分段隔离范围、STEP-106 T1/T2 Symbol 与 Annotation 边界的真实验收。
|
||||
|
||||
## 三、来自 NavSea 的问题证据(仅作为输入,不由本任务修改 NavSea)
|
||||
|
||||
FZG1-2 / Android 13 / V23 当前 APK,NavSea 采用**两段 R-C**:
|
||||
|
||||
- R0:RETAINED,31 层,`background` 至 `place-labels-land-ja`,包含有 Placement 能力的 Symbol;
|
||||
- C1:CONTINUOUS,82 层,`rn-weather-color` 至 `chartDangerScanCenterLineLayer`,包含天气/粒子和其他业务层。
|
||||
|
||||
固定同一风场、同一 map 生命周期,连续约 15.24 秒,`mapReactTag=864`、`generation=4`、`configRevision=1`、`topologyRevision=8`、113 层均不变:
|
||||
- 风场期间进程 CPU 样本均值约 98.6% / 99.1%,关闭天气后约 4%~8%;
|
||||
- `fastPathHit Δ0`、`fastPathMiss Δ452`、`fullCpuFrame Δ453`;
|
||||
- R0 `build Δ0`、`reuse Δ0`、`invalidation Δ453`、`fallbackCount Δ453`、texture/composite create `Δ0`;
|
||||
- 两端 `valid=true`、`fallback=false`、`sourceReady=true`、`sourceStable=true`、`placementChanged=true`、`placementGatePassed=false`、`cache.supported=false`、`cacheState=fallback`、`lastInvalidationReason=static-placement`;
|
||||
- `mainBufferExecutionMode=mixed`、`globalLiveFallbackReason=none`、`fastPathFallbackReason=cache-invalid`。
|
||||
|
||||
**这些是症状,不代表已证明 C1 导致 R0 Placement 改变。** 此外,历史较早的 V23 短时快照曾观察到 `placementChanged=false` 但 R0 记录仍为 `static-placement`,需要区分“当前门槛值”和“上次失效原因/诊断时序”,避免误读。
|
||||
|
||||
Mac 粒子团队如无法访问 Windows 原始快照,可依据上述冻结事实做 Native 只读审计;缺失证据须列为“需要后续验证”,不得自行编造 NavSea 图层或运行结果。
|
||||
|
||||
## 四、必须回答的调查问题
|
||||
|
||||
### Q1:Placement 的产生与传播
|
||||
|
||||
从真实 V23 Native 代码绘制完整的因果链:
|
||||
- 触发 RenderTree / Placement 计算的入口与时机是什么?
|
||||
- `placementChanged`、`symbolFadeChange`、`placementTransitionActive`、`crossSourceCollisions` 分别表示**当前帧/上帧/全局/局部**的什么事实?何时清零或稳定?
|
||||
- Source/Layer 的 layout、tile、visibility、camera、animation 等变化,分别可能影响哪些 Placement 状态?
|
||||
- R0 以外的 C1 Symbol/Annotation/业务层变化,**在哪些条件下**可能影响 R0 的符号碰撞与最终视觉?
|
||||
- 如果 RenderTree 每次都重新算 Placement 但画面没有变化,如何区分“执行过计算”和“R0 最终结果发生变化”?
|
||||
|
||||
### Q2:现有 R0 Gate 的作用域
|
||||
|
||||
调查 V23 实际调用链及数据结构,至少解释:
|
||||
- R0 结构性 `placementCapable` 如何判定,与动态 `needsPlacement()` 有何区别;
|
||||
- R0 `placementGatePassed` 如何使用全局 `placementChanged`、fade、transition;
|
||||
- R0 `cache.supported`、`static-placement`、`actualExecution=live` 的完整因果关系;
|
||||
- R0 的 source-local mutation、segment fingerprint、retained revision 与 placement gate 是否真正各自独立;
|
||||
- STEP-102 对 **placement-free** R 的隔离已解决什么、**placement-bearing** R 仍未解决什么;
|
||||
- `lastInvalidationReason` 与当前失败条件是否可能属于不同采样/缓存生命周期。
|
||||
|
||||
### Q3:能否证明“R0 不受 C1 变化影响”
|
||||
|
||||
针对以下反事实场景逐项作出有证据的判断:
|
||||
1. R0 含静态地名,C1 只有普通非 Symbol 动画/颜色/粒子更新;
|
||||
2. R0 含静态地名,C1 的 Symbol 内容变化,但不同 Source 且跨源碰撞关闭;
|
||||
3. R0 含静态地名,C1 的 Symbol 内容变化且跨源碰撞开启;
|
||||
4. R0 Symbol 自身 layout/tile/visibility/zoom 发生变化;
|
||||
5. Camera/pan/zoom/rotation/pitch 变化;
|
||||
6. Symbol Fade/Placement Transition 活跃或刚结束;
|
||||
7. C1 有内部自动插入的 Annotation Symbol(参照 STEP-106)。
|
||||
|
||||
每行必须分别给出:
|
||||
- “谁触发 Placement”能否识别;
|
||||
- “R0 最终 Placement/可见性是否改变”能否独立证明;
|
||||
- **允许 R0 Reuse 的必要安全条件**;
|
||||
- 当前 V23 是否具备这种判定能力及证据来源;
|
||||
- 无法证明时为什么必须继续 fail-closed。
|
||||
|
||||
严禁把“不同 Segment”简单等同于“碰撞和 Placement 相互独立”。
|
||||
|
||||
### Q4:对 Fast Path 的影响(仅限前置依赖)
|
||||
|
||||
解释“R0 缓存有效”是否为 Fast Path 的必要条件但**非充分条件**。只读标出 R0 Gate 与单 C / unsupported continuous layer / revision / pending changes 等后续 Gate 的先后关系。不要扩大成 C1 全图层性能调查,不实施多 C 优化。
|
||||
|
||||
## 五、只读检查范围与方法
|
||||
|
||||
允许读取:
|
||||
- 当前 Particle Core 的 Renderer、RenderOrchestrator、PlacementController、RenderTree、Symbol/Collision、Retained Cache、RenderSegment Plan、Diagnostics 与 Fast Path 相关源码;
|
||||
- V23 tag 与当前 `particle/main` 的只读 `git show`、`git diff`、`git log`;
|
||||
- STEP-090/102/106 等历史设计、报告、设备验证结果;
|
||||
- 现有 C++ 定向测试源码与 Validation 场景源码(只读,不执行、不修改)。
|
||||
|
||||
建议从当前实际路径 `src/mln/renderer/` 与相关 Shared Core 源码定位,**不得沿用旧 STEP 中过时的路径假设**。
|
||||
|
||||
每一条重要结论必须给出:**文件路径 + 类/函数或结构名称 + 适当行范围或 commit + 相关调用顺序**。核心论断不得只引用历史文档或本任务描述。
|
||||
|
||||
允许纯只读 Git/文本搜索,不要求也不允许额外建立实验分支、修改 Native/JS/Kotlin/测试代码、插桩、添加日志、运行 Jest、运行测试、Gradle、CMake/Ninja/Bazel、ADB 或重新安装 App。不得改 NavSea、Integration 或正式 release/tag。
|
||||
|
||||
## 六、最终必须提供的结论矩阵
|
||||
|
||||
**每个问题必须选择明确判定**,而不是只罗列建议:
|
||||
|
||||
| 维度 | 可选结论 |
|
||||
|---|---|
|
||||
| 能否定位 Placement 事件来源 | 现有数据可区分 / 现有数据不足 / 条件性可区分 |
|
||||
| 能否证明 R0 的实际视觉结果未变化 | 已能证明 / 需扩展内部安全证据 / 不能按段安全证明 |
|
||||
| 现有 Gate 是什么性质 | 正确的设计保守限制 / 明确可证的过度阻塞 Bug / 混合 / 证据不足 |
|
||||
| 缓存失效的主要责任边界 | Native Placement 数据模型 / Native Gate 判定 / 当前跨段碰撞语义 / Host Style 组合 / 多因素 / 未确定 |
|
||||
| 可选后续方向 | 无需代码调整 / Native 内部诊断补强 / Native 内部安全判据设计 / 宿主层序方案需协调 / 需真机对照实验 |
|
||||
|
||||
如果判断是 Bug,必须指出**违背了哪项既有语义/可复现的状态不变量**;如果判断是安全限制,必须指出**缺少何种证明才不能放宽**。如有多个阻塞项,按必要性和因果顺序排序,避免“修第一个之后才继续猜下一个”。
|
||||
|
||||
## 七、报告与交接产物
|
||||
|
||||
只允许新建/更新以下本 Step 文档(不改现有源码):
|
||||
|
||||
1. `docs/20_调查/R0_Placement跨段归因与缓存安全边界调查_v1.md`(主报告);
|
||||
2. `docs/50_Step记录/STEP-110_R0_Placement跨段归因只读调查_v1.md`(状态及完成项);
|
||||
3. `docs/报告/STEP-110_R0_Placement跨段归因只读调查_Codex完成报告_v1.md`(执行报告);
|
||||
4. `粒子开发记录.md`(简短追加式记录)。
|
||||
|
||||
调查主报告必备章节:
|
||||
- V23 tag / 当前 main 基线对照,说明是否有相关行为变化;
|
||||
- Q1~Q4 的逐条答案及代码证据;
|
||||
- **数据流/状态流**:Placement 事件 → 全局/局部状态 → R0 安全判定 → Cache Build/Reuse/Fallback → Fast Path;
|
||||
- 七类反事实场景矩阵,明确跨源碰撞、Fade、Annotation 的影响;
|
||||
- 已确定事实、假设、证据不足之处三栏;
|
||||
- 结论矩阵、根因优先级、最小下一步验证建议;
|
||||
- 若需调整公共 Contract / API,则仅提出 Integration 阻塞,不自行实施。
|
||||
|
||||
完成报告必须逐项按“**已完成 / 未完成 / 无法验证**”回答任务项并说明原因;记录实际检查范围、当前 branch/HEAD、Git 提交及推送信息。不得用“源码已读”代替代码证据。
|
||||
|
||||
**状态判定**:只读因果审计证据完整才可标为 `调查 PASS(不等于修复 PASS)`;否则 `PARTIAL/BLOCKED` 并列出缺失项。严禁声称“Native 已修复”、“R0 已缓存”或“CPU 已下降”。
|
||||
|
||||
## 八、Git 收尾与执行界限
|
||||
|
||||
- 本任务**只负责调查**。Codex/粒子项目未经用户后续明确授权,不得实施任何缓存、Placement、Fast Path 逻辑修改。
|
||||
- 完成相关文档后,仅提交本 Step 新增报告、Step 记录及追加的开发记录;保留所有无关 dirty/untracked 文件,不得强制清理。
|
||||
- 将本任务相关文档 scoped commit 到正式主线 `particle/main` 并 push 到公开远端 `origin/particle/main`。禁止 force push、改写历史、推送 upstream 或增加无关文件。
|
||||
- 完成报告必须给出**实际 commit hash、commit message、push 结果、远端分支**;push 失败不得宣称完成,应明确报告阻塞。
|
||||
- 本 MD 是交给粒子项目执行的**待办合同**。写入任务书本身不代表调查已执行、已验证或已得出结论。
|
||||
- 本任务不包含 Jest,不涉及原生编译、测试执行或 Android 设备操作。
|
||||
|
||||
## 九、停止条件
|
||||
|
||||
遇到以下情形须停留在调查层,提交 PARTIAL/BLOCKED 事实,不得扩大实现:
|
||||
1. V23 tag 与当前代码差异导致无法确认实际执行版本;
|
||||
2. Placement 影响关系必须依赖运行时数据,静态源码无法证明;
|
||||
3. 证明缓存安全需新增 per-segment collision/placement fingerprint 或改写 Core 算法;
|
||||
4. 需要改变对外 Native/RN 公共接口或跨项目责任;
|
||||
5. 需要 NavSea 配合修改 Style、增加调试或重新编译/测试;
|
||||
6. 所需证据缺失或与 STEP-090/102/106 的历史结论相冲突。
|
||||
|
||||
出现以上情况,在报告中给出**最小下一步任务建议**,等待用户/Integration 决定;不得在本任务中直接实施。
|
||||
@@ -0,0 +1,41 @@
|
||||
# STEP-111 R 段 Placement 结果等价与独立刷新可行性只读调查 — Codex 任务 v1
|
||||
|
||||
## 一、用户目标
|
||||
用户希望 Native 对 R-C-R-C-R-C(简称 RCRCRC)中的每一个 RETAINED R 段单独决定是否更新。若该段本身最终视觉输出未变化,不应仅因另一段 Symbol/Placement/Fade 全局状态更新而被动重建;确实受跨段碰撞影响的 R 段必须正确更新,不能破坏文字、图标或层序。此任务是下一步架构/可实现性调查,不是授权实施优化。
|
||||
|
||||
**核心区别**:A. 哪个 Layer/Source/Segment 触发重新计算;B. 全图 Placement 后每一个 R 段的最终 Symbol 视觉结果是否改变;C. Retained R 段缓存能否安全复用;D. 是否可进一步省略 R 段 prepare/placement 计算。A≠B、B≠C、C≠D。不要把各 R 分段直接当作 Collision Domain,也不要承诺每段无需参与全图 Placement 计算。
|
||||
|
||||
## 二、正式边界与必读
|
||||
- Mac /Users/tei/dev/MapLibreParticleLab,particle/main,origin/particle/main;执行时重新记录 HEAD、branch、dirty、远端基线;保留未跟踪 STEP-110 任务书。
|
||||
- 先读仓库 AGENTS.md、PARTICLE_BASELINE.md、docs/00_项目规范/、docs/00_项目总则/README.md 和全部现行总则;读 STEP-110 主报告和 Codex 完成报告,以及 STEP-102、106、109、Fast Path 相关历史证据;以当前源码事实为准。
|
||||
- 先检查 /Users/tei/dev/navsea-particle-integration 的 main 与 origin/main 同步状态,读取其 README、WORKFLOW、TEAM_MODEL、contracts、rfc、adr、status、compatibility;已有跨项目结论优先。本 Step 只讨论 Shared Core Native,不直接修改 Integration/NavSea/Android/iOS。
|
||||
- STEP-110 已证明:PlacementController 仍是整图语义;R 的 placementCapable=true 时 Gate 消费 global placementChanged、symbolFadeChange、placementTransitionActive;跨 Source Collision 可能影响 R0,source≠segment。STEP-102/106 只验收过 placement-free R 的安全复用。本 Step 不能简单重复这些事实,重点给出**新增的判等/判无变化能力**具体可行性。
|
||||
|
||||
## 三、只读调查工作项
|
||||
1. **从源码定位可实现性**:追踪 CrossTileSymbolIndex、Placement::placeLayers/commit、CollisionIndex/CollisionGroups、symbol buckets、placed icon/text、opacity/fade、RenderTree、RenderLayer、RenderSegment/Retained Cache 的真实控制与数据所有权。指出计算结束何处可以读取每一个 R 的最终 Placement 输出,是否已有稳定 ID、可见性/位置/opacity;写明路径、函数、行号和生命周期。辨别层间/Source 间/段间影响。
|
||||
2. **定义每段结果等价契约候选**:提出具体 per-R PlacementResultKey/Signature/Revision 候选字段(Symbol 实例稳定 ID、tile/source/bucket generation、placement result、collision visible/hidden、text/icon anchor/offset、paint opacity/fade/transition、zoom/camera、glyph/image atlas、style/layer order、render target boundary 等)。逐项解释哪些是 Placement 专属,哪些已有其他 cache gate 覆盖,哪些必须动态比较,哪些不需要加入,避免对每个 Symbol 每帧做过度 O(N) 或漏比较;比较发生于何时、如何处理首次帧、transition、reset、missing data。
|
||||
3. **RCRCRC 示例与判定表**:至少 R0/C0/R1/C1/R2/C2,其中 R0/R1/R2 都有 Symbol。分别分析:
|
||||
- C1 仅粒子/颜色动画,R 均无可见变化;
|
||||
- C1 Symbol 变动且只影响 R2;
|
||||
- C1 Symbol 变动,碰撞也影响 R0/R1;
|
||||
- R1 自己改变但 R0/R2 不变;
|
||||
- 同一 Source 跨段、不同 Source 且 crossSourceCollisions=true/false;
|
||||
- Annotation Symbol 自动插入,layer 顺序、camera/zoom/pitch、tile/glyph fade/opacity transition;
|
||||
- 不能证明者 fail-closed。
|
||||
结论表需区分“依然执行全局 Placement”、“该段仅避免 cache rebuild/composite 是否可复用”、“能否避免 render/prepare”、“Fast Path 仍被哪些其它 Gate 阻断”。
|
||||
4. **方案对比与难度**:对 A 只加 tracing/per-R 指标(不改变判定)、B 新增 per-R result fingerprint 但 shadow compare(仅记录真假)、C 利用已证明等价替换 global-only Symbol Gate 允许单段 Reuse、D 深改 Placement/Collision 成分段增量计算,逐一评估前提、复杂度(1-5)、改动范围、CPU/GPU/内存开销、风险、能否只改 Shared Core、对 Android OpenGL/iOS Metal 的影响。不能因为理论上可 hash 就声称 hash 一定安全。
|
||||
5. **执行与验收计划**:给出最小分阶段实现建议和真实可验证指标,包括 per-R signature stable/change、false invalidation、false reuse(严格 0)、build/reuse/fallback、视觉 A/B、Fade 长尾、CPU/frame、same frame draw ordering;指出先做诊断或原型是否需要新 Native 内部接口,哪些行为必须同时覆盖 Android/iOS。分别评估改善 retained cache 命中与改善整帧 CPU/Fast Path 的边界。
|
||||
6. **明确推荐结论**:回答每个 R 段可否“自身未变就不刷新”、可做到的最小粒度、不能保证的情形、最佳第一阶段(原型)与中长期方案,给出具体源码位置和工程量区间;区分源码已证实 vs 推断 vs 必须运行时验证。
|
||||
|
||||
## 四、禁止项
|
||||
调查只允许读取 Native/历史 Git/本机历史实验文件以及新增本 Step 文档。禁止修改任何 C++/JS/Kotlin/Swift/编译脚本/测试代码;禁止执行编译、链接、测试、Jest、Gradle、ADB、Bazel、CMake、设备操作;禁止更改 NavSea、Integration、公用 Contract/API、GSRL、release/Source Lock、发行 Tag;禁止放宽当前 fail-closed Gate。禁止重置/清除现有 dirty、禁止 force push。除非明确用户授权,不执行后续实施。
|
||||
|
||||
## 五、必做输出(实际生成)
|
||||
1. docs/20_调查/STEP-111_R段Placement结果等价与独立刷新可行性调查_v1.md — 主报告:代码路径/行号、RCRCRC 场景矩阵、Signature 草案字段逐项依据与生命周期、可行方案 A-D 对比、复杂度与工程量估计、风险、可执行的后续 Step 拆分、源码已证/待验证标识。
|
||||
2. docs/50_Step记录/STEP-111_R段Placement结果等价调查_v1.md — 简短中文 Step 记录,状态 PASS(调查完整)/PARTIAL/BLOCKED,记录未验证项与下一步。
|
||||
3. docs/报告/STEP-111_R段Placement结果等价调查_Codex完成报告_v1.md — 完成报告:实际模型与 reasoning effort(仅凭运行会话证据)、读取资料、逐任务结果、调查起/终 HEAD、branch、dirty、文件修改、未运行构建和测试、检查命令、限制、Git/Push 状态如实记录。
|
||||
4. 粒子开发记录.md — 本阶段简短追加(不要重写历史)。
|
||||
Codex 仅负责内容调查和上述报告落盘,Git scoped commit/push/远端验证由 GPT 指挥 RDC 独立负责,完成报告不得预报未执行 Git 结果。原有未跟踪 STEP-110 任务文件不纳入提交。本任务书自身保持未跟踪,避免误提交。
|
||||
|
||||
## 六、验收与停止
|
||||
只在调查结果有对应源码位置/函数/调用顺序,明确安全条件、未证实风险、工程阶段与复杂度对比时,记“调查 PASS”;如生产实际视觉等价无法仅通过源码证明,可记“调查 PASS / 运行验证未执行”,不得声称优化已通过。必要的实机状态/插桩超出只读范围时明确给出下一阶段最小需求,不得扩大当前范围。不得把历史 STEP-110 的 PARTIAL 当成本次已经实现结果。任务退出前向 GPT 汇报生成文件、最后状态和未完事项。
|
||||
41
docs/50_Step记录/STEP-119_SymbolRetained生命周期修复_v1.md
Normal file
41
docs/50_Step记录/STEP-119_SymbolRetained生命周期修复_v1.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# STEP-119 SymbolRetained 生命周期修复 v1
|
||||
|
||||
日期:2026-10-12(JST)。Step 状态:进行中。代码交付:**IMPLEMENTED / WAITING_RDC_VALIDATION**。这是此前中断任务的续作;不关闭整体 STEP-119,不构成编译、GTest、GPU 或设备验收 PASS。
|
||||
|
||||
## 目标与基线
|
||||
|
||||
按照 `/tmp/fzg1_astra_guidance_20261012.md` 修复内部 Symbol Drawable 的 RenderTile 同源绑定、旧 Drawable 更新及 Bucket/Atlas 更换生命周期;保留原缓存、证书和 Full → Build → 成功 Full Reuse → Fast 顺序。
|
||||
|
||||
- 机器:Mac.lan / Darwin 24.6.0 / x86_64;仓库:`/Users/tei/dev/MapLibreParticleLab`。
|
||||
- 开工及交付分支:`particle/main`;HEAD:`badb515d590fbdf221751b6677de3da0a5650d7e`。未切换分支/worktree,未提交或操作远端。
|
||||
- 接续已有四个源码修改;起点另有受保护 STEP-110/111 两份未跟踪任务书。
|
||||
- 用户本轮明确指定模型 `GPT-6.1 Sol High`(`gpt-6.1-sol / high`)。当前工具未提供执行器模型元数据,且本机当日 sessions 目录不存在,无法独立核验实际运行参数;不宣称已从日志核实,没有主动切换模型或启动子代理。
|
||||
- 当前发行锁为 Android/RN `13.6.1-particle.25`、iOS `6.29.0-particle.25`,构建冻结源 `f32f6f45fd359007e8b3c77911b66d9e7fc93848`;本修复不改 Source Lock/发行物,不声称已进入 v25 制品。
|
||||
|
||||
## 必做项
|
||||
|
||||
- [x] 读取 Astra 指导、AGENTS、PARTICLE_BASELINE、规范、四份当前总则、当前 STEP-119 任务/实现/测试资料,核对现有四文件 diff。
|
||||
- [x] 同次 source prepare 获取 raw owner 和 Y 排序引用列表;仅比较地址完成同源校验,再复制当前 ID/atlas。
|
||||
- [x] 同 Bucket/Atlas 的完整 tile/pass 组先检查,再全部重新绑定当前 owner/RenderTile;不逐帧重建 Drawable/tweaker。
|
||||
- [x] Bucket/Atlas/组内成员失配或缺 atlas 时移除整组,走原创建路径;Text/IconRGBA/IconSDF/Halo 使用同一 atlas 与实际 tweaker 配对。
|
||||
- [x] Retained 使用内部强引用 atlas 和当前地址映射,不沿旧 Drawable 裸指针读取 atlas/Tile;缺证立即 complete=false。
|
||||
- [x] 保活 RenderTile → renderData → LayoutResult 的证据资源,不把每次 prepare 的 owner 地址写入比较字节。
|
||||
- [x] 编写并静态核对 13 项 SymbolRetainedLifetime GTest 源码,修正 atlas-only TileRenderData 查询默认 assert 的测试替身缺口。
|
||||
- [x] 中文 Step、完成报告及开发记录末尾追加;四源码路径 scoped diff 空白检查 exit0。
|
||||
- [ ] RDC 实际编译/链接并发现、运行生命周期与 STEP-119 定向 GTest。
|
||||
- [ ] Android OpenGL、Metal 实际路径验证与 Vulkan 编译兼容性证据。
|
||||
- [ ] 新源码锁/APK/SO 身份闭环、FZ-G1 动态生命周期、原24Gate、Full/Fast 视觉及释放验收。
|
||||
|
||||
## 修改范围与当前结果
|
||||
|
||||
生产修改限 `src/mln/gfx/symbol_drawable_data.hpp`、`src/mln/renderer/layers/render_symbol_layer.cpp`、`src/mln/renderer/layers/render_symbol_layer.hpp`;测试限 `test/renderer/retained_underlay_cache.test.cpp`。沿用此前修改,续作只补未知 Symbol 类型拒绝、测试替身空查询覆盖、Text/Icon/SDF/Halo 连续 prepare 稳定性与证书资源释放检查。
|
||||
|
||||
未改 RN/JNI 公共 API、原24Gate/证书判据、Placement、缓存开关、发行物、Integration、旧报告或两份保护任务书。未运行 CMake、编译/链接/语法编译、GTest、Gradle/APK、ADB/安装、Jest;没有新制品或设备数据。
|
||||
|
||||
## 阻塞与下一步
|
||||
|
||||
实现已落盘,可编译性与运行正确性仍待 RDC。现 verifier 会拒绝 tracked dirty,后续 Git 来源锁须在独立审计和另行授权后处理;本轮禁止 Git 收尾,不能绕过 verifier 或借旧 APK。历史 Metal/libuv 缺口未重新验证,不安装升级依赖。
|
||||
|
||||
RenderTile 容器不拥有底层 `Tile&`;强引用 atlas/texture 也不能证明原地像素或槽位不变,继续依赖既有 content epoch 和真实绑定复核。原始寄存器 tombstone 缺失,不能断言 `0x8cdc7c` 唯一根因为本缺陷;保留原 SO Build ID `485459ba44f806ef0a0c08633c717bfd5d82ad8f` 与匹配符号交 RDC。
|
||||
|
||||
准确命令、测试覆盖限制、停止门槛和交接证据见 [本轮完成报告](../报告/STEP-119_SymbolRetained生命周期修复_Codex完成报告_v1.md)。Codex 到此交接,RDC 独立审计后逐条验证;失败保留首错与现场,不放宽条件。
|
||||
128
docs/报告/STEP-119_SymbolRetained生命周期修复_Codex完成报告_v1.md
Normal file
128
docs/报告/STEP-119_SymbolRetained生命周期修复_Codex完成报告_v1.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# STEP-119 SymbolRetained 生命周期修复 Codex 完成报告 v1
|
||||
|
||||
日期:2026-10-12(JST)。状态:**IMPLEMENTED / WAITING_RDC_VALIDATION**。接续此前因用量限制中断的同一任务,四个既有修改经静态复审及明确缺口修正后交付。没有运行编译或测试,整体 STEP-119 仍未验收,不报告整体 PASS。
|
||||
|
||||
## 1. 模型、环境与 Git 基线
|
||||
|
||||
- 用户本轮明确指定 `GPT-6.1 Sol High`,即 `gpt-6.1-sol / high`。当前工具没有执行器模型/推理参数元数据;轻量查找 `/Users/tei/.codex/sessions/2026/10/12` 返回目录不存在,实际运行参数无法独立核验。记录用户指定值,不把它写成已从执行器日志核实。未主动升级模型、启动第二实例或子代理。
|
||||
- `Mac.lan`,Darwin 24.6.0,x86_64;目录 `/Users/tei/dev/MapLibreParticleLab`。
|
||||
- 开工/交付 branch=`particle/main`,HEAD=`badb515d590fbdf221751b6677de3da0a5650d7e`。基线为四个已有 tracked 修改及 STEP-110/111 两份 untracked 任务书;不从头复写,不改分支/worktree/HEAD。
|
||||
- `git submodule status` 已只读检查,没有变更前缀;无子模块修改。未 commit/push/tag/fetch/pull/rebase/reset/clean,未回读远端 HEAD(本轮禁止远端操作)。
|
||||
- 只读当前 v25 Source Lock:Android/RN `13.6.1-particle.25`,iOS `6.29.0-particle.25`,冻结构建源 `f32f6f45fd359007e8b3c77911b66d9e7fc93848`。发行记录与制品未修改,本轮未生成制品,不能以现有 v25 包验证本工作区修复。
|
||||
- 首先读取 Astra 原文 `/tmp/fzg1_astra_guidance_20261012.md`,再读取仓库规则、当前资料和现有 diff。当前用户续作授权优先于旧任务中的历史基线/跨项目调查和 Git 收尾安排。
|
||||
|
||||
## 2. 实际修改文件及生命周期不变量
|
||||
|
||||
| 文件 | 实际变更与不变量 |
|
||||
|---|---|
|
||||
| `src/mln/gfx/symbol_drawable_data.hpp` | 内部数据保存强类型 atlas 与实际原生 atlas tweaker;创建时两者来自同一份 atlas,增加内部 Drawable 类型标记。它们不拥有 RenderTile 或底层 Tile。 |
|
||||
| `src/mln/renderer/layers/render_symbol_layer.hpp` | 私有同源/绑定/整组复用/采集辅助方法及当前地址→ID/atlas 映射;仅保存当前代次,不建立历史容器列表。friend 测试入口不修改公共 API。 |
|
||||
| `src/mln/renderer/layers/render_symbol_layer.cpp` | prepare 从同次 source 获取 raw owner 与原 Y 排序列表,先校验成员地址再读 ID/atlas,保留 fading tile。成功复用先检查 tile/pass 整组,再全部刷新当前 RenderTile/owner;Bucket、atlas、layer tweaker、数据/类型或成员失配整组移除重建,atlas 缺失移除旧绘制。Retained 从强引用 atlas 取证,旧指针只作当前地址映射查找,使用 Drawable 自己的 ID;类型未知/绑定不符/未上传立即拒绝。owner 只放入 resources,不序列化 owner 地址。 |
|
||||
| `test/renderer/retained_underlay_cache.test.cpp` | 13 项 `SymbolRetainedLifetime` 源码调用生产 prepare/bind/rebind/retained 辅助路径与原生 atlas tweaker;真实类接口/签名和友元访问逐项静态核对。atlas-only TileRenderData 显式覆盖空 Bucket/LayerRenderData 查询,避免基类 assert;补组内类型失配、Text/IconRGBA/IconSDF/Halo 稳定身份、未知类型及证书释放检查。 |
|
||||
| `docs/50_Step记录/STEP-119_SymbolRetained生命周期修复_v1.md`(新增) | 本阶段目标、基线、完成/待验清单及交接。 |
|
||||
| `docs/报告/STEP-119_SymbolRetained生命周期修复_Codex完成报告_v1.md`(新增) | 本报告,记录事实、准确命令、风险和停止条件。 |
|
||||
| `粒子开发记录.md` | 仅末尾追加本次实现与未验证事实,保留历史内容。 |
|
||||
|
||||
两个新文档路径创建前已确认不存在,同主题无旧版本,选择 v1;使用独占创建,未覆盖旧报告。前三个生产文件及测试均沿用开工时修改;本续作生产补丁仅增加 Retained 对未知 SymbolType 的拒绝,测试补丁只处理上述明确缺口及覆盖不足。
|
||||
|
||||
### 所有权与稳定性
|
||||
|
||||
1. Drawable 只由通过同源校验的 owner/元素绑定。复用检查不从旧 RenderTile 读取 ID/Bucket/atlas;任何一个 Text/Icon/Halo 成员不兼容时整组移除,避免 `updateTile()` 的“任一成功”留下半新半旧组。
|
||||
2. 同 Bucket/atlas 保持 Drawable 和 tweaker 身份,仅刷新 owner/RenderTile 与既有动态属性;source 每次产生新容器不应自行造成每帧重建或证书字节变化。
|
||||
3. 当前容器拥有 RenderTile;RenderTile 独占 renderData;真实 GeometryTileRenderData 强持有 LayoutResult/atlas,LayoutResult 负责槽位释放。证据 resources 保活容器,但不调用 `result.retain(renderTilesOwner)`,因此 owner 地址不进入比较字节。证书 candidate/completed 替换或 invalidate 后旧证据可退出,未新增无界容器。
|
||||
4. Retained 先验证当前地址/保存的 ID、内部数据类型、atlas 来源、实际 tweaker 和 shader,再检查真实 glyph/icon 纹理绑定及上传状态。任何缺证立即返回 incomplete,不沿失效裸指针追读 renderData/atlas。
|
||||
5. RenderTile 内 `Tile&` 的寿命独立;保活容器不保活 Tile,不允许把旧 Tile 上的 getOverscaledTileID/holdForFade 当成安全操作。测试分别计数 Tile 与 TileRenderData,旧 Tile 销毁后仅比较旧地址及读取 atlas 强引用。
|
||||
6. 同 atlas 的 texture 替换经原生 tweaker 更新实际绑定,前后证据不同;原地像素更新即使上传后指针不变,仍依赖真实 content epoch。既有 Build 前/后及提交后复核、证书版本/R cache/prepared Fast 保护保留,未改变准入顺序或放宽任何判据。
|
||||
|
||||
## 3. 静态审查与测试源码范围
|
||||
|
||||
13 项生命周期源码覆盖:连续 prepare 后刷新/释放旧 renderData、owner/元素错配、atlas 替换整组清理与新纹理绑定、组内单成员失配、atlas 缺失、同 atlas texture 更换及重新 Build/Reuse 状态、未上传原地更新拒绝、owner 身份不进入完整空组结果字节、Tile 与 renderData 寿命分离、Layer 移除及证书失效释放 atlas、同名 Source 替换、tile 退出清理、Text/Icon/SDF/Halo 连续三代保持身份、未知 Symbol 类型拒绝(其中相关情形合并在同一用例)。
|
||||
|
||||
测试使用真实 RenderSource/Tile/TileRenderData/RenderTile、SymbolBucket、Drawable/TileLayerGroup 接口和生产辅助方法;GPU Texture/Drawable/Shader 使用 CPU 替身。真实 API 的纯虚函数、构造参数、Mutable→Immutable 转换、SymbolLayer.baseImpl 可见性及派生类 friend 访问继承 protected 成员已静态核对,没有用悬空指针解引用构造普通反例。
|
||||
|
||||
**覆盖限制**:atlas-only fixture 不生成真实 Placement/顶点/GPU 命令;atlasResult 是生产采集的局部证据,不能代表完整渲染证书。整组失配测试走生产移除入口,但重新创建由 fixture 添加 Drawable,仍需 RDC 实际 update/builder/GPU 链验证。tile 退出测试直接调用正常 update 使用的清理入口,没有伪造 Context 或声称执行完整 update。owner 稳定证书测试走完整生产空组采集;非空 Text/Icon/Halo 稳定性只检查绑定输入和身份。原地 image patch 上传后的 epoch、Style/context 清理引用既有 `Step119SymbolResults.RealTileGlyphImageStyleContextCallbacksRejectBuiltCertificate` 等回调测试源码,不等同真实槽位释放、Source/Style/context 完整运行验收。
|
||||
|
||||
## 4. 已做及未做检查
|
||||
|
||||
已做:必要文件阅读、开工 Git/机器/版本及 diff 审查;真实 C++ 接口/生命周期调用静态核对;确认测试文件在 `test/CMakeLists.txt` 已登记;源码静态计数 `SymbolRetainedLifetime` 为13项;新增文档版本/路径检查;STEP-110/111 SHA-256 保护检查;开发记录追加与文件范围检查。
|
||||
|
||||
已执行四源码路径 scoped `git diff --check -- src/mln/gfx/symbol_drawable_data.hpp src/mln/renderer/layers/render_symbol_layer.cpp src/mln/renderer/layers/render_symbol_layer.hpp test/renderer/retained_underlay_cache.test.cpp`:**exit=0,stdout/stderr 空**。最终全工作区及七任务路径空白检查由本轮落盘后再次执行,结果见下方交付记录。空白检查不证明 C++ 编译或测试通过。
|
||||
|
||||
未执行:CMake 配置、Native/NDK 编译、`-fsyntax-only`、链接、GTest、Metal/iOS/GPU运行、Gradle/APK、ADB/安装、Jest、Bazel/codegen、发行、Git写操作及远端读取。没有新编译失败日志、设备日志、截图、APK/SO SHA 或 Build/Reuse/Fast 数据;既有 libuv 环境失败只作为历史限制,未重试也未修改环境。
|
||||
|
||||
保护的未跟踪任务书 SHA-256:
|
||||
|
||||
- STEP-110:`33037df71b4b30aa7956d59f4b99f77af3085405b24111bc0fe11ec857a93db0`。
|
||||
- STEP-111:`f3a5806f25384bf46055db2edfea0d21bfbc4124184bc813b46e38b8079c1ec4`。
|
||||
|
||||
## 5. RDC 准确编译与定向测试命令(Codex 未执行)
|
||||
|
||||
独立审查本报告和实际 diff 后,在同一工作区逐条执行;每条保存 command/exit/耗时/完整日志路径,失败立即停止下一步,回传首个真实 error、target 与必要上下文。PATH 找不到 cmake 时可使用既有 `/usr/local/opt/cmake/bin/cmake`;不得安装升级依赖或关闭宏绕过 libuv/工具链错误。
|
||||
|
||||
```bash
|
||||
cd /Users/tei/dev/MapLibreParticleLab
|
||||
cmake --preset macos-metal
|
||||
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
|
||||
build-macos-metal/mbgl-test-runner --gtest_filter='SymbolRetainedLifetime.*:Step119SymbolResults.*' --gtest_list_tests
|
||||
build-macos-metal/mbgl-test-runner --gtest_filter='SymbolRetainedLifetime.*:Step119SymbolResults.*:RetainedUnderlayCache.*:RenderOrchestratorError.*:RenderOrchestratorTeardown.*:CrossTileSymbolLayerIndex.*' --gtest_color=no
|
||||
```
|
||||
|
||||
必须发现本轮13项 `SymbolRetainedLifetime` 与既有13项 `Step119SymbolResults`(后者分布两个已登记文件),真实执行数量非零。零匹配、旧 runner、仅语法检查不能写 GTest PASS。Metal 与 Android OpenGL 分别保留编译及运行事实;Android 实际 compile_commands 的类型核对须保持原 `-Werror`,不加 `-Wno-error`。本轮未生成额外编译脚本。
|
||||
|
||||
Vulkan 至少取得生产修改的兼容性编译证据;已有 macOS Vulkan 环境可用以下真实 preset/target,环境缺失则记未验证/阻塞,不升级环境:
|
||||
|
||||
```bash
|
||||
cmake --preset macos-vulkan
|
||||
cmake --build build-macos-vulkan --target mbgl-core --parallel 3
|
||||
```
|
||||
|
||||
Vulkan Symbol provenance 既有保守边界保持,编译成功不等于其 Symbol retained 运行通过。可在既有 sanitizer 配置下补查 UAF,不改造构建体系;Host Metal/GTest 也不替代 iOS 真机。
|
||||
|
||||
## 6. 后续 FZ-G1 验收命令与证据(Codex 未执行)
|
||||
|
||||
**前置门槛**:独立审计/Native验证完成、后续 Git 来源锁和 Android/设备操作获得授权。当前 tracked dirty,verifier 的 `SOURCE_NOT_LOCKED` 会拒绝本工作区;本轮禁止提交,故这是后续验收前置条件,不能改 verifier、伪造 build-info 或用旧 APK。本报告仅交命令,不代执行 Android/ADB,也不代授权 Git。
|
||||
|
||||
用户/RDC 按其阶段授权完成一次标准新 APK 构建与安装,固定 FZG1-2、serial=`192.168.200.139:5555`、OpenGL Debug/x86_64:
|
||||
|
||||
```bash
|
||||
cd /Users/tei/dev/MapLibreParticleLab
|
||||
./tools/particle_android_validation/build_validation_apk.sh
|
||||
adb -s 192.168.200.139:5555 install -r artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
|
||||
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --serial 192.168.200.139:5555 --preflight-only
|
||||
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --serial 192.168.200.139:5555 --scenario STATIC_RC_NO_TIDE --seconds 90
|
||||
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --serial 192.168.200.139:5555 --scenario RCRR_C_NARROW_NO_TIDE --seconds 90
|
||||
python3 -B tools/particle_android_validation/verify_step113_fast_path.py --serial 192.168.200.139:5555 --scenario STATIC_RC --seconds 90
|
||||
```
|
||||
|
||||
正向缓存保持开启,每次稳定后须真实 Build>0、Reuse>0、FastDelta>0,完整120帧24Gate mismatch=0;原63层 STATIC_RC 缺 tide 继续作为安全拒绝负对照,验证器可能返回 NO_FAST_OBSERVED/exit2,不能当正向 PASS,也不能添加假 tide。正向静止90秒不是生命周期验收。
|
||||
|
||||
RDC/用户还需反复 pan/zoom/rotate、跨 tile/world wrap、Source同名替换、Style清理/重载、glyph/icon/atlas更新、后台恢复/context reset;每次变化保存失效 → Full → 新 Build → 成功 Full Reuse → Fast 的顺序证据,Text/Icon/SDF/Halo 不消失、残影或错位。相同相机的 Full/Fast 图像对照、资源随循环最终释放均须实测。保持正式 Style/Source 和公共契约,不以禁用 Retained、每帧重建或放宽24Gate替代验证。
|
||||
|
||||
必须保存:新锁定源码 HEAD/diff、build-info/完整构建日志、本地及安装 APK SHA-256、实际 libmaplibre.so Build ID与匹配符号、测试发现/执行数、Build/Reuse/Full/Fast/Invalidate 区间增量、完整24Gate快照、操作前后截图及视觉判断、资源数量/释放证据和全部未验证项。证据写新目录,不覆盖 ignored 历史证据。
|
||||
|
||||
异常先保存 crash 日志/bugreport,不先清日志;由获授权执行者执行:
|
||||
|
||||
```bash
|
||||
STEP119_EVIDENCE_DIR=$(mktemp -d /tmp/step119-symbol-lifetime-XXXXXX)
|
||||
adb -s 192.168.200.139:5555 logcat -b crash -d > "$STEP119_EVIDENCE_DIR/crash-logcat.txt"
|
||||
adb -s 192.168.200.139:5555 bugreport "$STEP119_EVIDENCE_DIR/bugreport.zip"
|
||||
```
|
||||
|
||||
## 7. 风险、证据缺口与停止门槛
|
||||
|
||||
- 缺原始寄存器 tombstone;原 Build ID `485459ba44f806ef0a0c08633c717bfd5d82ad8f` 和匹配符号应保留,不能断言 `0x8cdc7c` 唯一原因是本 UAF 链。
|
||||
- 当前模型运行参数没有可独立回读的执行器元数据,RDC报告须补该身份事实;不伪造“已核实”。
|
||||
- 真实 C++ 编译、GTest、Metal/OpenGL/Vulkan、底层 Tile 寿命及真实 atlas 槽位/像素变化、异步线程边界、释放/内存开销均未验收。静态检查只能排除部分明显问题。
|
||||
- 若必须改变公共契约、重构全部 Tile 所有权、永久禁用缓存、放宽测试/证书或修改发行物才能继续,停止扩大修改并标 BLOCKED。
|
||||
- 编译/链接/GTest失败、SIGSEGV、24Gate mismatch、Fast永久归零、资源循环单调增长、Symbol视觉异常均保留现场,不能通过降门槛、旧APK或隐藏失败制造 PASS。
|
||||
|
||||
本轮实现交接到此,后续由 RDC 独立验证;失败按 Codex 修复 → RDC 验证闭环返回,不继续后续开发阶段。
|
||||
|
||||
## 8. 最终交付静态检查记录
|
||||
|
||||
- 完整命令 `git diff --check`:exit=0,stdout/stderr 空。
|
||||
- 七个任务文件显式路径的 `git diff --check -- ...`:exit=0,stdout/stderr 空。新建 Step/报告尚未跟踪,Git diff 不包含其内容;另以轻量 Python 文件检查确认两份 UTF-8 文档状态、末尾换行及无行尾空白,不借此声称 Git 已检查 untracked 内容。
|
||||
- `git status --short`:仅四个接续源码、开发记录、两份新增本任务文档及两份原有保护任务书;没有其它修改。branch/HEAD 与开工一致。
|
||||
- 最终 STEP-110/111 SHA-256 与开工值一致;开发记录内容以 HEAD 原文的完整字节为前缀,只有末尾追加。
|
||||
- 静态计数:生命周期13项,既有 Step119SymbolResults 为9+4=13项。没有发现/执行 GTest,不能声称实际26项通过。
|
||||
- 没有新的编译/测试/设备验收结论;状态维持 IMPLEMENTED / WAITING_RDC_VALIDATION。
|
||||
Reference in New Issue
Block a user