test(tools): rowgeom 逐行几何基线 + 长度不变式按类别判定
新增 `OffscreenChecks -run rowgeom`(§13.6 第 1 项),把 7 个面板的每个矩形的 每个字段导出为文本基线并逐项比对,作为"完整结构合并 / 重写布局算式"的前置护栏。 两层覆盖 - 细节层:6 信号 1 网格、7 面板全开、参数行展开、3 个真实固定点、折起+展开各一份, 983 条键(-data MF4-Record.MF4 时 1304 条),失败时直接给出字段名+行号+新旧值; - 规模层:全部信号合并成 1 个网格(MF4 = 566 行),每面板一个 FNV-1a 摘要 + 行数, 任何一行变动都会改哈希,同时不产生几十万行基线。 负向自检(证明护栏不是空转) - 篡改基线副本 `mark.markerRowCount=3 → 2` ⇒ `CHANGED … mismatches=1` + FAIL。 顺带修正第 36 轮定得过严的不变式 - `rowRefs` 是重载字段:MARK 面板用它表示"信号分组",真正的条目行在 markerRows, 且只填 rowNameRects / rowNameCloses,其余 14 列必须为空; ⇒ `panels` / `panelscroll` 的"18 列全等"改为按 `PanelStyle::markerGroups` 分流判定, 失败时打印 15 个计数字段便于定位。 - 导出器/不变式一律**逐列按自身长度**遍历(按 rowRefs.size() 索引其它列会越界, 这是本轮第一次 0xC0000005 的根因)。 测试用例里的两处修正 - `MERGE_LANES` 之后补 `SynchronizeView(true)`:`SetMode` 只重建 TabConfig 的网格配置, `PlotView::m_lanes` 要等下一次布局才刷新; - 场景 B 重新播固定点:`ShowSignals()` 先 `SetAllVisible(false)`,而"全部不可见 ⇒ 丢弃网格" 是 RebuildLanes 的既有设计,网格级状态随之清空(不是缺陷),因此不能跨场景依赖。 验证 - make release:零 warning,785,408 B 不变(本轮只动工具/检查与文档) - make -C Tools clean && make -C Tools:零 warning - UnitTests:checks=260 failed=0 cases=19 - OffscreenChecks -all:7 检查 / 127 断言全 PASS(原 6 / 101) - rowgeom -mode compare:默认数据 983+7 键、MF4 1304+7 键,0 差异 - panels -mode compare:7 个面板像素哈希 + 几何逐项不变 文档:Code_Review_Plan §九、Progress 第 37 轮、Report §14、agent_mem 第 37 轮、Tools/README §4.1/4.3/4.4
This commit is contained in:
1 parent
221f9d2410
commit
353c553721
6 files changed
+821
-48
No files matched your search
@@ -10564,3 +10564,77 @@ release/debug **零警告**;Release `TargetCheck.exe` **890,880 B**(< 1 MB
|
||||
* **逐行几何基线**(导出每行 18 个矩形做逐项比对)—— 完整结构合并与布局算式重写的前置护栏。
|
||||
* `rowPoints` / `rowIterations` 已无绘制方使用(旧式输入框排版早已删除),可标注/清理。
|
||||
* `PaintPanelListRows` 仍约 470 行,可再拆三段,但已不在"改一次就出错"的路径上。
|
||||
|
||||
---
|
||||
|
||||
## 2026-11-04 · 第 37 轮(`Code_Review` 分支):逐行几何基线(§13.6 第 1 项)
|
||||
|
||||
> 提交:见本轮提交信息;规则原文 `Documents/Code_Review_Report.md` §14、`Code_Review_Plan.md` §九、
|
||||
> `Code_Review_Progress.md` 第 37 轮、`Tools/README.md` §4.1/§4.3/§4.4。
|
||||
|
||||
### 1. ✅ 新增 `OffscreenChecks -run rowgeom`(`record` / `compare`)
|
||||
|
||||
两层覆盖:
|
||||
* **细节层**(6 信号 1 网格、7 面板全开、参数行展开、3 个固定点、折起+展开各一份):
|
||||
每个矩形的每个字段一条键,`Temp/tools/rows-baseline/rowgeom-baseline.txt` 共 **983** 条
|
||||
(`-data MF4-Record.MF4` 时 1304 条)。
|
||||
* **规模层**(全部信号 1 网格,MF4 = 566 行):每面板一个 FNV-1a 摘要 + 行数,7 条键。
|
||||
|
||||
键格式:`<panel>.<field>` / `<panel>.<列名>[NNN]=x,y,w,h` / `mark.markerGroup[NNN].header=…`。
|
||||
比对双向(MISSING / ADDED / CHANGED),差异 0 才 PASS。
|
||||
|
||||
### 2. 🔴 新硬规则一:`rowRefs` 是**重载字段**,长度不变式必须按类别判定
|
||||
|
||||
| 面板类别 | `rowRefs` 含义 | 真正的行在 |
|
||||
| --- | --- | --- |
|
||||
| 列表式(mean/center/peak/resample/clip) | 每个信号一行 | `rowRefs` 自身 + 其余 15 列 |
|
||||
| 边沿计数(count) | 每个信号一行(表格行) | 同上 |
|
||||
| 「自由标记」(mark) | 每个**信号分组**一项 | `markerRows` / `markerGroups` |
|
||||
|
||||
MARK 面板**只填** `rowNameRects` / `rowNameCloses`,其余 14 列**必须为空**。
|
||||
⇒ 第 36 轮定的"18 列全部等于行数"对 MARK 是**错的**,本轮已改为:
|
||||
|
||||
* `PanelStyle::markerGroups == true` ⇒ `rowNameRects`/`rowNameCloses` 等于分组数,
|
||||
且 `rowHeaders`/`rowChecks`/`rowLevelTracks`/`rowIterTracks` 必须为空;
|
||||
* 其余面板 ⇒ `rowRefs` + 16 列全部等于行数。
|
||||
|
||||
任何"遍历 18 列"的代码(导出器、不变式、批量处理)**都必须逐列按自身长度**遍历,
|
||||
不能拿 `rowRefs.size()` 当统一行数(否则 MARK 面板直接越界 —— 本轮第一次 `0xC0000005`)。
|
||||
|
||||
### 3. 🔴 新硬规则二:`SetMode()` 不同步 `m_lanes`
|
||||
|
||||
`ExecuteToolbarAction(MERGE_LANES / SPLIT_LANES)`(以及 `TabConfig::SetMode`)只重建
|
||||
`TabConfig` 的网格配置,`PlotView::m_lanes` 要等下一次布局/绘制才刷新。
|
||||
⇒ **合并/拆分后、读 `LaneCount()` 或 `EdgePanelLayoutFor()` 之前,必须先
|
||||
`app.SynchronizeView(true)`(必要时再 `RenderFrame()`)**。
|
||||
|
||||
### 4. ⚠️ 已知行为(不是缺陷):全部不可见 ⇒ 丢弃网格 ⇒ 网格级状态清空
|
||||
|
||||
`Session::ShowSignals()` 先 `SetAllVisible(false)`;`RebuildLanes` 的 MERGED 分支在
|
||||
"无可见信号"时 `lanes.clear()`(与工具栏「清空」一致)。
|
||||
⇒ 固定点 / 面板开关 / 面板滚动位置 / 面板显隐 **全部丢失**,不是新 BUG。
|
||||
检查里跨场景依赖这些状态时,必须**重新播**(`rowgeom` 用 `addFreeMarkers(wanted)` lambda)。
|
||||
|
||||
### 5. 基线的定位
|
||||
|
||||
**检测器,不是黄金图。** 预期内的几何变化要重新 `-mode record`,并在提交信息里写明原因。
|
||||
负向自检已做:篡改基线中 `mark.markerRowCount=3 → 2`,`-mode compare` 会
|
||||
`CHANGED … mismatches=1` 并 FAIL ⇒ 护栏不是空转。
|
||||
|
||||
### 6. 本轮数字
|
||||
|
||||
* Release **785,408 B 不变**(本轮只动工具/检查与文档);零 warning。
|
||||
* `UnitTests` 260 断言 / 19 用例;`OffscreenChecks -all` **7 检查 / 127 断言**(原 6/101)。
|
||||
* `rowgeom -mode compare`:默认数据 983+7 键、MF4 1304+7 键,0 差异。
|
||||
* `panels -mode compare` 7 个面板像素哈希 + 几何逐项不变。
|
||||
|
||||
### 7. 遗留(下一步候选,按价值)
|
||||
|
||||
1. **`rowPoints` / `rowIterations` 清理**(确认已无绘制方使用,仅 `BuildBoxes` / 命中键残留)——
|
||||
当前唯一"写了没人读"的列,删掉可省每次 `AppendRow` 的 2 次 push。
|
||||
判据:`rowgeom -mode compare` + `panels -mode compare`。
|
||||
2. **完整结构合并(`std::vector<PanelRow>` + 列视图)**:护栏已就绪,但 §13.3 的
|
||||
**失败可见性**问题未解(拷贝后忘重绑 = 静默悬垂)。若要做,必须同时给
|
||||
`EdgePanelLayout` 加"视图自检"(比对 `rows` 容量与视图长度)。
|
||||
3. `PaintPanelListRows` 再拆三段(纯可读性)。
|
||||
|
||||
Reference in new issue
Block a user