Files
osmWorkflow/.trellis/tasks/archive/2026-08/08-25-rc-p0-contract-baseline/design.md

82 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 0 技术设计
契约本体见父任务 `design.md` §1本文件只补 Phase 0 自身的实现设计。
## 1. 确定性核查的具体做法
编译器的潜在非确定性来源,按可疑度排序:
| 来源 | 表现 | 处置 |
|---|---|---|
| `fs.mkdtempSync(path.join(pipelineDir, "native-road-"))` | staging 目录名随机 | 若名字出现在 `compiled.json``source` 字段里,需归一化 |
| `compiled.json` 内的绝对路径 | `source.osm` / `source.overrides` / `source.trafficSignals` 是绝对路径 | 归一化为相对 repo root |
| 时间戳 | 未确认是否存在 | 核查 `compile-native-roads.js` 写入的 metadata |
| `Map` / `Set` 迭代顺序 | JS 保证插入序,若插入源本身有序则确定 | 观测两次运行 `orderHash` 是否一致即可暴露 |
| 浮点累加顺序 | 几何坐标末位抖动 | 若出现,说明存在顺序依赖,属真 bug需修 |
| `crypto` 随机(`traffic-signals.js` require 了 `crypto` | 信号 ID 可能含随机成分 | 重点核查 —— `native-traffic-signals.json``loadOrGenerate`,已存在则复用,首次生成可能不确定 |
**核查顺序**
1. 备份两个有效区域的 `native-road/``native-traffic-signals.json`
2. 删除 `native-road/`(保留 signals因为 `loadOrGenerate` 语义是已存在则复用)
3. 跑第一次 → snapshot A
4. 再删 `native-road/`,跑第二次 → snapshot B
5. diff A/B → volatile 字段清单
6. 额外一轮:删掉 signals 文件也重生成一次,确认 signal ID 是否确定
## 2. `scripts/road-parity.js` 设计
```
用法:
node scripts/road-parity.js --config <area-config> --snapshot <out.json>
node scripts/road-parity.js --config <area-config> --compare <baseline.json>
```
### 归一化规则(写死在脚本里,并回写进契约文档)
1. **路径**:任何绝对路径 → 相对 repo rootstaging 目录名 → 字面量 `<staging>`
2. **JSON**:递归按 key 排序后 `JSON.stringify`,再 hash
3. **GeoJSON**
- `contentHash` = features 按 `properties.native_id`(缺失则按几何首坐标)排序后 hash
- `orderHash` = 原序 hash
- 两者都记录;比对时 `contentHash` 不一致 = 语义变化(严重),
`orderHash` 不一致 = 顺序抖动(需解释但可能可接受)
4. **浮点**:不做舍入。坐标变化就是变化,不允许用容差掩盖
(拆分是纯搬迁,任何坐标位移都是 bug
### 输出形状
```json
{
"contract": "native-road-package/v1",
"areaId": "fengshu-er-road",
"files": {
"compiled.json": { "contentHash": "…", "bytes": 12345 },
"diagnostics.json": { "contentHash": "…", "bytes": 678, "count": 42 },
"layers/road_surface.geojson": {
"contentHash": "…", "orderHash": "…", "features": 128 }
},
"volatileExcluded": ["source.osm", "source.overrides", "<staging>"]
}
```
`count` / `features` 是冗余的人类可读字段 —— hash 变了但计数没变,
说明是内容变化;计数也变了,说明是增删。加速归因。
## 3. 基线目录布局
```
.trellis/tasks/08-25-road-compiler-extraction/baseline/
fengshu-er-road.json
nantaizi-lake-innovation-valley.json
README.md ← 记录生成时的 git commit、命令、volatile 字段清单
```
`README.md` 必须记录生成基线时的 commit hash否则将来无法判断
"基线是在哪个代码状态下产生的"。
## 4. 为什么校验脚本放宿主而不是直接放未来的编译器仓库
Phase 0 时编译器仓库还不存在。脚本先落宿主 `scripts/`
Phase 2 随编译器一起搬走,届时宿主保留一个薄封装(或直接调编译器包的 CLI
这样 Phase 1 的 parity 验证不需要等仓库拆分。