Files
osmWorkflow/.trellis/tasks/08-25-road-compiler-extraction/prd.md

8.0 KiB
Raw Blame History

道路编译器独立化parent

Goal

把 native road compiler 从本仓库拆成可独立维护的项目,与本项目通过版本化文件契约相辅相成; 同时把道路渲染与 OSM 建筑渲染分离,使二者可各自演进。

本任务是 parent它拥有源需求、契约定义、子任务地图、跨子任务验收标准和最终集成评审。 它自身不承担实现工作,所有可交付物在子任务中完成。

背景:为什么现在拆

  • scripts/lib/native-road.js 已 1695 行,compileGeometry() 单函数编排 15+ 个 pass 顺序依赖只由行号编码,每加一个特性就往既有函数尾部挂位置参数 compileLaneMarkings 已 7 个位置参数)。
  • 道路与建筑渲染纠缠在 blender/generate_scene.py 一个脚本内, 道路图层表 NATIVE_ROAD_LAYERS 硬编码在 blender/osmassets/catalog.py:53
  • 道路编译的迭代节奏几何、路口、标线、V2X 语义)与建筑/植被/水体渲染完全不同, 放在一个仓库里互相牵制。

拆分的可行性前提(已核实):

  • native-road.js 只 require fs / path / 两个同族道路模块,对宿主项目零耦合
  • 对宿主的唯一耦合是三个 CLI 入口里的 readAreaConfig
  • 输出侧 native-road/ 已经是文件契约blender/generate_scene.py:801 按图层名读取。
  • stdout 标记 NATIVE_ROAD_COMPILE_DONE 已存在,与 SCENE_DONE / CESIUM_EXPORT_DONE 同一约定 —— 子进程边界事实上已预留。

Requirements

R1 契约先行

  • R1.1 输入输出契约必须在任何代码移动之前写死并版本化为 native-road-package/v1 命名对齐既有 osm-asset-package/v1 约定。
  • R1.2 契约的权威定义见本任务 design.mdPhase 0 负责把它落成仓库内文档 + 校验脚本。

R2 可证明的等价性

  • R2.1 拆分过程中每一步都必须对两个有效区域 fengshu-er-road / nantaizi-lake-innovation-valley 验证产物与基线一致。
  • R2.2 任何差异必须逐条书面解释后才可接受,禁止"看起来差不多"。
  • R2.3 验证方法沿用既有 .trellis/spec/guides/artifact-parity-guide.md

R3 独立可维护

  • R3.1 拆出的项目必须能脱离宿主自测(自带 fixture不读宿主 inputs/outputs/)。
  • R3.2 保留 git 历史(git subtree splitgit filter-repo)—— 1695 行几何逻辑的 blame 是踩坑记录,丢失后无人敢改。
  • R3.3 编译器不得反向依赖宿主任何模块、配置或目录布局。

R4 相辅相成(防漂移)

四个机制缺一不可:

机制 作用 落地于
native-road-package/v1 版本号 破坏性变更必须升版本,宿主主动 opt-in Phase 0
编译器自声明图层layer manifest 加图层不需要改宿主代码 Phase 3
两区域 parity 基线留在编译器仓库当测试语料 编译器无法静默弄坏宿主 Phase 0 → Phase 2
宿主锁版本依赖,不用 latest 升级是决定,不是意外 Phase 2

R5 渲染分离

  • R5.1 道路图层表必须从宿主 catalog.py 的硬编码变为编译器输出的 manifest。
  • R5.2 blender/generate_scene.py 内道路渲染分支抽离为独立模块; 建筑 / 植被 / 水体保持原位。
  • R5.3 分离后,编译器新增图层不需要修改宿主任何代码即可被渲染。

Constraints硬约束

C1 不得在拆分过程中重构 IR 🔴

lane graph 提为一等 IR 是正确方向,但必须在 Phase 2 完成之后作为独立任务

理由:拆分的正确性完全依赖"产物逐字节不变"这一 oracle。 一旦同时改 IRoracle 失效,且无法判断产物变化来自搬迁还是重设计。

未来若做,形式是新增输出而非替换 compiled.json 靠"解锁 drawtonomy / OpenDRIVE / Lanelet2 导出"赚取存在理由。

C2 拆分期不引入构建步骤

编译器保持 CommonJS、无构建步骤与宿主 pipeline 层运行时一致 (见 .trellis/spec/pipeline/index.md)。 TypeScript / ESM 是独立决策;若后续 drawtonomy PoC 需要 SDK 互操作,只能在其独立任务的扩展目录内处理。

C3 Phase 1 必须先于 Phase 2

"包边界"与"换仓库"分两步做。合并执行时若产物变化,无法区分成因。

子任务地图

Phase 子任务 交付物 阻塞后续
0 08-25-rc-p0-contract-baseline 契约文档 + 两区域 checksum 基线 + 校验脚本
1 08-25-rc-p1-package-boundary 本仓库内 packages/road-compiler/,窄输入契约
2 08-25-rc-p2-repo-split 独立仓库 + 宿主锁版本消费
3 08-25-rc-p3-render-separation layer manifest + Blender 道路模块抽离

顺序约束:0 → 1 → 2 必须串行。3 依赖 2 完成。

跨子任务验收标准

  • AC1 Phase 0 基线建立后,两区域每个输出文件的 checksum 已提交进版本控制
  • AC2 Phase 1 结束时,npm run build:area 两区域产物对 AC1 基线逐字节一致
  • AC3 Phase 2 结束时,宿主从打包依赖构建,两区域 parity 仍成立
  • AC4 Phase 2 结束时,编译器仓库 npm test 在不访问宿主仓库的情况下通过
  • AC5 Phase 3 结束时,向编译器新增一个图层,宿主零代码改动即可渲染出来(实测验证)
  • AC6 Phase 3 结束时,.blend 结构摘要对基线一致(走 artifact-parity-guide
  • AC7 全程未修改 compiled.json 的结构C1 未被违反)
  • AC8 编译器仓库对宿主的反向依赖数为 0grep 验证)

已识别风险(跨子任务,逐个必须有归属)

# 风险 归属 Phase 处置
K1 lib/traffic-signals.js 是真共用模块:reimport-gpkg.js / build-osm2streets-qgis.js / build-area.js / test-preview-assets.js 都在用,而 native-traffic-signals.js 也依赖它 1 需细读后拆分:信号文档 schema + OSM 信号节点提取随编译器走编译器生成它就该拥有契约legacy QGIS/预览读取器留宿主。全案唯一需要细读再动的地方
K2 comparison.json 依赖宿主产物 —— compile-native-roads.js:87area.outputs.geojsonDir 里 osm2streets 输出做对比,拆出后摸不到 0决策/ 1执行 osm2streets 已 legacy倾向直接砍掉用高德参考 + 规范校验取代。决策需在 Phase 0 定档
K3 config 内绝对路径指向宿主仓库:config/areas/fengshu-er-road.jsonreferenceFile: "/Users/que01/osm2streets-qgis-workflow/inputs/osm/珠山湖大道(枫树二路)口.geojson" 1 需定参考文件解析约定(相对 config 目录 / 显式 basePath
K4 workbench 的 OpenLayers 来自宿主 node_modulesdesign.md 的 import map 方案) 2 新仓库自带依赖
K5 测试 fixture 依赖宿主:test-native-road.js:167inputs/osm/枫树二路.osm,其余为内联合成 OSM 1 该文件(或裁剪版)作为测试数据提交进编译器仓库

Out of Scope

  • lane graph IR 重构(见 C1未来独立任务
  • pass manager / 显式依赖声明重构(同上,属编译器内部演进,不属本次拆分)
  • 替换编译器为 drawtonomy 或 osm2streets —— 已评估否决: drawtonomy 开源部分只读 Lanelet2显式车道边界不做 OSM highway=* 推导, 与本编译器的核心能力方向垂直
  • osm2streets / QGIS legacy 链路的任何改动
  • 宿主侧建筑 / 植被 / 水体渲染逻辑的改动Phase 3 只抽离道路部分)

Notes

  • 评估结论与选型依据见 design.md 的「决策记录」一节。
  • 时间估计Phase 0-2 约 3 天(搬家 + 证明没搬坏Phase 3 约 1-2 天。 拿到"道路与建筑渲染分离、可独立维护"是在 Phase 3 结束。
  • 父任务验收完成后,下一项候选任务是独立的 08-25-rc-p4-drawtonomy-extdrawtonomy 扩展 PoC它不属于本任务完成条件。