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

3.7 KiB
Raw Blame History

Phase 0 技术设计

契约本体见父任务 design.md §1本文件只补 Phase 0 自身的实现设计。

1. 确定性核查的具体做法

编译器的潜在非确定性来源,按可疑度排序:

来源 表现 处置
fs.mkdtempSync(path.join(pipelineDir, "native-road-")) staging 目录名随机 若名字出现在 compiled.jsonsource 字段里,需归一化
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.jsonloadOrGenerate,已存在则复用,首次生成可能不确定

核查顺序

  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

输出形状

{
  "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 验证不需要等仓库拆分。