refactor: consume external road compiler
This commit is contained in:
@@ -1 +1,4 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
{"file":".trellis/spec/pipeline/external-tools.md","reason":"检查 CLI 子进程错误、signal 与日志处理是否符合宿主管线约定。"}
|
||||
{"file":".trellis/spec/pipeline/cli-and-stages.md","reason":"检查编译阶段、完成标记和 stage manifest 的跨层影响。"}
|
||||
{"file":".trellis/spec/guides/cross-layer-thinking-guide.md","reason":"检查配置、Node pipeline、Blender 消费链的边界没有漂移。"}
|
||||
{"file":".trellis/spec/guides/artifact-parity-guide.md","reason":"检查两个有效区域的严格基线 parity。"}
|
||||
|
||||
44
.trellis/tasks/08-25-rc-p2-repo-split/design.md
Normal file
44
.trellis/tasks/08-25-rc-p2-repo-split/design.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Phase 2:独立仓库与 CLI 边界设计
|
||||
|
||||
## Architecture
|
||||
|
||||
P1 已将实现收敛到 `packages/road-compiler/`。P2 把该目录以保留历史的方式导出为独立 package 仓库,保留两个明确方向的边界:
|
||||
|
||||
```
|
||||
宿主 area config
|
||||
-> scripts/lib/area-config.js
|
||||
-> RoadCompilerInput JSON(宿主 staging)
|
||||
-> @osm-asset/road-compiler CLI(子进程)
|
||||
-> native-road/ + NATIVE_ROAD_COMPILE_DONE
|
||||
-> build-area.js / Blender / preview
|
||||
```
|
||||
|
||||
编译器不知道区域配置、宿主仓库、Blender 或宿主输出目录约定以外的输入路径。宿主不知道 compiler 内部源文件;它只拥有输入 JSON、CLI 的完成标记和写出的契约文件。
|
||||
|
||||
## CLI Contract
|
||||
|
||||
- CLI 接收一个 JSON 文件中的 `RoadCompilerInput`,而不是宿主的 area config。
|
||||
- `comparisonDir` 继续作为可选输入,以维持现有 `comparison.json` 产物和 P0 baseline 的可比性。
|
||||
- 成功只打印一次 `NATIVE_ROAD_COMPILE_DONE <JSON>`。payload 必须至少含 `areaId`、`output`、`roads`、`endpoints` 和 `diagnostics`。
|
||||
- `build-area.js` 保持同步批处理模式,子进程日志对用户可见;为了验证标记,输出同时被捕获或 tee。它对启动失败、非零状态、signal、缺失/重复/非法标记和 payload 与当前输入不一致都报错。
|
||||
- 产物先由 compiler 的现有 staging/atomic promotion 逻辑写入目标 `native-road/`;宿主不接管这一写入过程。
|
||||
|
||||
## Repository Contents
|
||||
|
||||
独立仓库拥有:compiler source、public API、CLI、check、workbench、fixture、两个 parity baseline、契约文档、README、package lockfile 和 workbench 的 `ol` 依赖。测试和 workbench 均必须在没有宿主 checkout 的环境运行。
|
||||
|
||||
宿主保留:area-config 读取/归一化、`RoadCompilerInput` 映射、pipeline 阶段编排、Blender/preview、区域配置、运行产物和一份升级回归 baseline。宿主 spec 仅保留指针,契约正文随 compiler 仓库维护。
|
||||
|
||||
## History Extraction
|
||||
|
||||
导出只允许 `git subtree split` 或 `git filter-repo`。必须在独立仓库验证 `git log --follow src/compile/native-road.js`;验证的是迁移前的逻辑历史,而非仅 P1 的边界移动提交。导出和验证先在临时分支/clone 完成,外部远端创建和 push 必须使用用户给出的地址和授权范围。
|
||||
|
||||
## Dependency and Rollout
|
||||
|
||||
初始发布源定为私有 `https://git.app.que01.top/que01/road-compiler.git`。仓库以带注释 tag `v0.1.0` 首发,宿主以该精确 tag 作为依赖并写入 lockfile。开发临时形态可以指向独立 checkout 的本地 `file:` 依赖;它不能成为验收时的唯一消费方式。两个区域 parity 通过后删除 `packages/road-compiler/`;回滚由 revert 宿主消费改造实现,不能让 production host 继续直接 import 该目录。
|
||||
|
||||
## Compatibility and Risks
|
||||
|
||||
这是位置和调用方式迁移,不改变 compiler 行为。两个区域的 strict content/order hash 是主要 oracle;信号文档的确定性生成仍应通过 parity 覆盖。P2 不处理 `check:area` 的历史 stage-manifest freshness warning,也不把 Blender/Metal 沙箱问题归因为道路产物。
|
||||
|
||||
若外部 CLI 无法及时使用,回滚宿主消费 commit 即可;外部仓库历史和 tag 不需要删除。对于完整 Blender 构建,macOS Metal 初始化必须在提权的宿主环境运行。
|
||||
@@ -1 +1,4 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
{"file":".trellis/spec/pipeline/external-tools.md","reason":"CLI 子进程必须沿用管线的启动、日志和失败状态语义。"}
|
||||
{"file":".trellis/spec/pipeline/cli-and-stages.md","reason":"编译是 Blender 前的 pipeline 输入阶段,需保持阶段与 stdout 契约。"}
|
||||
{"file":".trellis/spec/config/index.md","reason":"宿主拥有区域配置归一化及 RoadCompilerInput 映射。"}
|
||||
{"file":".trellis/spec/guides/artifact-parity-guide.md","reason":"本阶段声称产物不变,必须用严格 parity 验证。"}
|
||||
|
||||
@@ -1,74 +1,55 @@
|
||||
# Phase 2 执行计划
|
||||
|
||||
## Step 1 — 前置
|
||||
执行前提:用户已在最新 P2 规划摘要后明确批准。发布目标已定为私有 `https://git.app.que01.top/que01/road-compiler.git`,首发 tag 为 `v0.1.0`。
|
||||
|
||||
- [ ] Phase 1 的 AC1.1–AC1.8 全绿
|
||||
- [ ] 定档 §「待决策」四项(仓库名 / 托管 / 分发 / 过渡期策略)
|
||||
## 1. 导出并核验历史
|
||||
|
||||
## Step 2 — 拆出仓库(保历史)
|
||||
- [ ] 创建临时 export 分支或临时 clone,使用 `git subtree split --prefix=packages/road-compiler` 或 `git filter-repo --path packages/road-compiler/ --path-rename packages/road-compiler/:` 导出。
|
||||
- [ ] 在导出仓库验证 `git log --follow src/compile/native-road.js` 包含 2026-08-13 以来的 native compiler 历史。
|
||||
- [ ] 在私有 `https://git.app.que01.top/que01/road-compiler.git` 创建并推送独立仓库;创建带注释的 `v0.1.0` tag。
|
||||
|
||||
## 2. 使编译器仓库自持
|
||||
|
||||
- [ ] 将 CLI 作为 package `bin` 入口,接受由宿主写出的 `RoadCompilerInput` JSON,并继续输出唯一的 `NATIVE_ROAD_COMPILE_DONE` JSON 标记。
|
||||
- [ ] 补全 `package.json`、锁文件和 `ol` 依赖;workbench vendor 文件从自身安装目录提供。
|
||||
- [ ] 迁入 `docs/native-road-package-v1.md`、两个 baseline 和它们的测试驱动,新增独立 README。
|
||||
- [ ] 在不含宿主文件的临时 clone 内执行依赖安装、单元测试、两区域 parity 与 workbench 启动测试。
|
||||
- [ ] grep 验证没有 `area-config`、`config/areas`、宿主项目名或宿主相对路径引用。
|
||||
|
||||
## 3. 宿主改为外部 CLI 消费
|
||||
|
||||
- [ ] 将 compiler 以精确 git tag `v0.1.0` 安装到宿主并记录 lockfile;禁止范围版本、`latest`、`*` 和裸分支。
|
||||
- [ ] 将 `toRoadCompilerInput()` 序列化到每个区域的 pipeline staging 目录,传给 compiler CLI。
|
||||
- [ ] 在 `build-area.js` 的 blender 前置阶段调用 CLI。沿用管线的 `spawnSync` / `runCommand` 失败语义(启动错误、exit status、signal)和直通日志;缓冲或 tee stdout 后,解析恰好一个完成标记并验证其 `areaId`、`output` 与当前区域匹配。
|
||||
- [ ] 将 host workbench 的 fresh compile 回调切换到同一 CLI,不改变 fresh-process 行为。
|
||||
- [ ] 把所有 host 对 `packages/road-compiler/**` 的直接 import 替换成已安装包的公开 API 或 CLI;两个区域 parity 均通过后删除 in-host 副本。
|
||||
- [ ] 将宿主 pipeline spec 改为指向编译器仓库所拥有的契约文档。
|
||||
|
||||
## 4. 验证与发布门
|
||||
|
||||
新仓库(干净 clone):
|
||||
|
||||
```bash
|
||||
# 方案 A:subtree split
|
||||
git subtree split --prefix=packages/road-compiler -b road-compiler-export
|
||||
# 在新目录初始化并拉入该分支
|
||||
|
||||
# 方案 B:filter-repo(更彻底,推荐)
|
||||
git clone --no-local . /tmp/road-compiler-split
|
||||
cd /tmp/road-compiler-split
|
||||
git filter-repo --path packages/road-compiler/ --path-rename packages/road-compiler/:
|
||||
npm ci
|
||||
npm test
|
||||
npm run test:road-parity
|
||||
npm run road:workbench -- --config test/fixtures/fengshu-er-road.input.json --no-compile
|
||||
```
|
||||
|
||||
⚠️ 注意:Phase 1 的搬迁若用了 `git mv`,历史可 `--follow` 追溯;
|
||||
若用了删除+新建,`filter-repo` 只能追到 Phase 1。
|
||||
**Phase 1 搬迁时必须用 `git mv`** —— 这条已在 Phase 1 implement Step 3 隐含,
|
||||
此处显式记录依赖。
|
||||
|
||||
- [ ] 拆出后验证:`git log --follow src/compile/native-road.js | tail -20`
|
||||
能看到 08-13 native-road-compiler 的提交
|
||||
|
||||
## Step 3 — 新仓库自持化
|
||||
|
||||
- [ ] `package.json` 补全依赖(含 K4 的 OpenLayers)
|
||||
- [ ] `npm install && npm test` 在新仓库独立通过
|
||||
- [ ] 基线 JSON 迁入 `test/baseline/`
|
||||
- [ ] 契约文档迁入 `docs/`
|
||||
- [ ] README:契约摘要 + 与宿主项目关系说明
|
||||
|
||||
## Step 4 — 宿主改造
|
||||
|
||||
- [ ] `package.json` 依赖指向新仓库(开发期 `file:`)
|
||||
- [ ] `build-area.js` 改子进程调用 + 解析 `NATIVE_ROAD_COMPILE_DONE`
|
||||
- [ ] `area-config.js` 的 `toRoadCompilerInput()` 输出改为 CLI 参数或 input JSON 文件
|
||||
- [ ] 删除 `packages/road-compiler/`(或按过渡期决策保留)
|
||||
- [ ] `.trellis/spec/pipeline/` 加契约指针
|
||||
|
||||
## Step 5 — 验证
|
||||
宿主两个有效区域的逐字节 parity:
|
||||
|
||||
```bash
|
||||
# 宿主端到端
|
||||
npm run build:area -- --config config/areas/fengshu-er-road.json
|
||||
|
||||
# 三区域 parity
|
||||
for a in fengshu-er-road hanyang-block nantaizi-lake-innovation-valley; do
|
||||
node scripts/road-parity.js --config config/areas/$a.json \
|
||||
--compare .trellis/tasks/08-25-road-compiler-extraction/baseline/$a.json || echo "FAIL $a"
|
||||
done
|
||||
|
||||
# 反向依赖为 0(在新仓库内跑)
|
||||
grep -rn "osm2streets-qgis-workflow\|area-config" . --exclude-dir=node_modules --exclude-dir=.git \
|
||||
&& echo "VIOLATION"
|
||||
|
||||
# 锁版本检查
|
||||
node -e 'const d=require("./package.json").dependencies;console.log(d)' | grep -i road
|
||||
node scripts/road-parity.js --config config/areas/fengshu-er-road.json \
|
||||
--compare .trellis/tasks/08-25-road-compiler-extraction/baseline/fengshu-er-road.json
|
||||
node scripts/road-parity.js --config config/areas/nantaizi-lake-innovation-valley.json \
|
||||
--compare .trellis/tasks/08-25-road-compiler-extraction/baseline/nantaizi-lake-innovation-valley.json
|
||||
```
|
||||
|
||||
- [ ] 在一台未 clone 宿主的环境(或 `/tmp` 全新 clone)验证 AC2.2
|
||||
|
||||
## Review Gate
|
||||
|
||||
AC2.1–AC2.7 全绿。特别是 AC2.2(脱离宿主可自测)—— 这是"独立可维护"的实质。
|
||||
- [ ] 为 CLI 标记成功、缺失、重复、非法 JSON、areaId 不匹配和 output 不匹配补测试。
|
||||
- [ ] 跑 package 单测、宿主 native-road / workbench / traffic signals / turn-lane-arrows 测试,以及两个 parity 检查。
|
||||
- [ ] 使用 `trellis-check` 做最终跨层检查;Blender 完整构建需以提权方式运行,原因是 macOS Metal 初始化不能在沙箱内启动。
|
||||
|
||||
## Rollback
|
||||
|
||||
- 宿主依赖改回 `file:packages/road-compiler`(若过渡期保留了该目录)
|
||||
- 或 `git revert` 宿主侧改造 commit;新仓库留着不影响宿主
|
||||
- 外部仓库和已发布 tag 保留不动;在宿主 revert 消费改造即可回到 P1 边界。
|
||||
- 若按决定临时保留 in-host 副本,可将依赖回指该副本以恢复;该退路不取代 host parity 验证。
|
||||
|
||||
@@ -1,80 +1,62 @@
|
||||
# Phase 2:拆仓库
|
||||
|
||||
父任务:`.trellis/tasks/08-25-road-compiler-extraction/`
|
||||
技术设计:父任务 `design.md` §1.3(消费方式)、§2(模块清单)
|
||||
|
||||
## Goal
|
||||
|
||||
把 `packages/road-compiler/` 拆成保留 git 历史的独立仓库,
|
||||
宿主改为锁版本依赖 + 子进程调用消费。
|
||||
把当前 `packages/road-compiler/` 拆为保留 git 历史、可脱离宿主独立测试和运行的仓库;宿主改为消费一个锁定版本的编译器 CLI。这样道路编译器可以独立演进,宿主依然通过版本化文件契约稳定构建场景。
|
||||
|
||||
## Confirmed Facts
|
||||
|
||||
- P1 已完成:编译器实现和 workbench 的所有权在 `packages/road-compiler/`;宿主负责将区域配置映射为 `RoadCompilerInput`。
|
||||
- `git log --follow packages/road-compiler/src/compile/native-road.js` 已能追溯到 2026-08-13 的 native-road compiler 历史。
|
||||
- 契约为 `native-road-package/v1`,完成标记为 `NATIVE_ROAD_COMPILE_DONE <json>`;`comparisonDir` 是可选输入,继续保留 `comparison.json`。
|
||||
- 当前宿主远端为内部 Git 服务 `https://git.app.que01.top/que01/osmWorkflow.git`;P2 独立编译器仓库定为私有 `https://git.app.que01.top/que01/road-compiler.git`。
|
||||
- 可维护范围只有 `fengshu-er-road` 和 `nantaizi-lake-innovation-valley`。`hanyang-block` 是废案,不参与基线、测试、验收或迁移语料。
|
||||
|
||||
## Requirements
|
||||
|
||||
### R2.1 保留 git 历史 🔴
|
||||
### R2.1 保留 Git 历史
|
||||
|
||||
- 用 `git subtree split` 或 `git filter-repo` 拆出,**不得**用 `cp` + `git init`
|
||||
- 理由(父任务 R3.2):1695 行几何逻辑的 blame 是踩坑记录,
|
||||
丢了以后没人敢改 `compileGeometry` 里任何一行
|
||||
- 验证:新仓库内 `git log --follow src/compile/native-road.js` 能看到
|
||||
08-13 native-road-compiler 以来的完整历史
|
||||
- 用 `git subtree split` 或 `git filter-repo` 导出,不得以复制目录再 `git init` 替代。
|
||||
- 新仓库中 `git log --follow src/compile/native-road.js` 必须能追溯到 P1 之前的 native-road compiler 提交。
|
||||
|
||||
### R2.2 子进程为主契约
|
||||
### R2.2 新仓库可独立运行
|
||||
|
||||
- 宿主 `build-area.js` 改为 `execFileSync` 调编译器 CLI,
|
||||
解析 `NATIVE_ROAD_COMPILE_DONE` stdout 标记(父任务 design §1.3)
|
||||
- in-process `require` 可保留为可选优化路径,但不得是唯一路径
|
||||
- 与既有 QGIS / GDAL / Blender 调用方式一致
|
||||
(见 `.trellis/spec/pipeline/external-tools.md`)
|
||||
- 新仓库拥有 compiler、CLI、check、workbench、其测试 fixture、两个 parity baseline、契约文档和 README。
|
||||
- 新仓库 own `ol` 及其 workbench 所需的运行依赖;workbench 不得从宿主 `node_modules` 提供浏览器资源。
|
||||
- 新仓库不得引用宿主的 `area-config`、`config/areas`、`scripts/` 或本仓库绝对路径。
|
||||
|
||||
### R2.3 锁版本依赖
|
||||
### R2.3 宿主的消费边界
|
||||
|
||||
- 开发期:`file:` 或 workspace 依赖
|
||||
- 稳定后:git tag / 私有 npm,宿主 `package.json` **锁具体版本,不用 `latest`**
|
||||
- 契约版本 `native-road-package/v1` 与包版本分开演进:
|
||||
包可以发 patch,契约版本只在破坏性变更时升
|
||||
- `scripts/lib/area-config.js` 继续是唯一的区域配置归一化与 `RoadCompilerInput` 映射位置。
|
||||
- `scripts/build-area.js` 用已安装编译器的 CLI 子进程编译,继承 stdout/stderr,检查启动错误、退出状态和 signal,并解析且校验唯一的 `NATIVE_ROAD_COMPILE_DONE` 标记。
|
||||
- 宿主只依赖 CLI、写入的文件和版本化输入 JSON;不再以相对路径 import 编译器内部模块。保留的宿主 signal 文件 I/O 适配层改为只调用公开包 API。
|
||||
- `road-workbench` 保持每次编译均启动新进程的语义,但改为调用已安装 CLI。
|
||||
|
||||
### R2.4 K4:workbench 依赖自持
|
||||
### R2.4 版本与迁移
|
||||
|
||||
- `road-workbench` 的 OpenLayers 从新仓库自己的 `node_modules` 提供
|
||||
- import map 路径相应调整
|
||||
|
||||
### R2.5 基线迁移
|
||||
|
||||
- Phase 0 的三区域基线 JSON 搬进新仓库当测试语料(父任务 R4 第三条)
|
||||
- 新仓库 CI/test 能独立跑 parity,无需宿主在场
|
||||
- **同时**宿主保留一份,用于验证升级编译器版本后产物未变
|
||||
|
||||
### R2.6 契约文档迁移
|
||||
|
||||
- `docs/native-road-package-v1.md` 搬进新仓库
|
||||
- 宿主 `.trellis/spec/pipeline/` 留指针,说明契约由编译器仓库拥有
|
||||
- 宿主依赖必须锁定一个具体编译器版本,禁止 `latest` 或 `*`;包版本与 `native-road-package/v1` 的契约版本独立演进。
|
||||
- 初始分发使用带注释的 git tag `v0.1.0`;宿主锁定该 tag。完整 parity 验证后移除 `packages/road-compiler/`,不保留 in-host 副本作为正常消费路径。
|
||||
- 宿主保留两份 baseline,用来验证今后升级编译器版本后没有产物漂移。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] AC2.1 新仓库 `git log --follow` 能追到搬迁前的历史
|
||||
- [ ] AC2.2 新仓库 `npm test` 在**未 clone 宿主**的机器上通过
|
||||
- [ ] AC2.3 宿主从锁版本依赖构建,三区域 parity 对基线全绿
|
||||
- [ ] AC2.4 `build-area.js` 走子进程路径,`NATIVE_ROAD_COMPILE_DONE` 被正确解析
|
||||
- [ ] AC2.5 宿主 `package.json` 依赖为具体版本,非 `latest` / 非 `*`
|
||||
- [ ] AC2.6 编译器仓库对宿主反向依赖数为 0(父任务 AC8,grep 验证)
|
||||
- [ ] AC2.7 `npm run road:workbench` 在新仓库内独立可跑
|
||||
|
||||
## 依赖与顺序
|
||||
|
||||
- **前置**:Phase 1 完成且 AC1.1–AC1.8 全绿
|
||||
- **阻塞**:Phase 3、Phase 4
|
||||
|
||||
## 待决策(进入本阶段时定)
|
||||
|
||||
| 项 | 选项 |
|
||||
|---|---|
|
||||
| 仓库名 | `road-compiler` / `native-road-compiler` / `osm-road-compiler` |
|
||||
| 托管 | GitHub 私有 / 公开 / 内部 git |
|
||||
| 分发 | git tag 依赖 / 私有 npm registry |
|
||||
| 宿主过渡期 | 是否保留 `packages/road-compiler/` 一段时间做双跑对照 |
|
||||
- [ ] AC2.1 独立仓库的 `git log --follow src/compile/native-road.js` 可见 P1 前的 compiler 历史。
|
||||
- [ ] AC2.2 在未 clone 宿主的干净目录中,新仓库 `npm ci`(或等价锁文件安装)和 `npm test` 均通过。
|
||||
- [ ] AC2.3 新仓库的两区域 parity(`fengshu-er-road`、`nantaizi-lake-innovation-valley`)均与迁入 baseline 完全一致。
|
||||
- [ ] AC2.4 宿主用锁版本依赖运行 CLI;`build-area.js` 成功解析一个有效的 `NATIVE_ROAD_COMPILE_DONE` 标记,缺失、重复或非法标记会失败。
|
||||
- [ ] AC2.5 宿主的两个区域 parity 均对保留 baseline 全绿。
|
||||
- [ ] AC2.6 宿主 `package.json` 的 compiler 依赖是具体、可复现版本,不是 `latest`、`*` 或裸分支。
|
||||
- [ ] AC2.7 编译器仓库对宿主反向依赖为 0,且其 workbench 可独立启动。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- layer manifest(Phase 3)
|
||||
- drawtonomy 扩展(Phase 4)
|
||||
- 任何编译器内部逻辑改动 —— 本阶段代码内容不变,只换位置与消费方式
|
||||
- 编译器几何、规则或输出内容改动。
|
||||
- 图层 manifest 和道路/建筑渲染分离(Phase 3)。
|
||||
- drawtonomy 扩展(Phase 4)。
|
||||
- `hanyang-block` 修复、迁移或作为验收样本。
|
||||
|
||||
## Release Decision
|
||||
|
||||
独立仓库为私有 `https://git.app.que01.top/que01/road-compiler.git`。首发以带注释 tag `v0.1.0` 发布,宿主依赖精确锁定该 tag;两个区域 parity 均通过后删除 `packages/road-compiler/`。该决定授权 P2 在该内部远端创建和推送仓库,但不授权发布到 npm 或其他托管平台。
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"name": "rc-p2-repo-split",
|
||||
"title": "Phase 2:拆仓库",
|
||||
"description": "保留 git 历史拆出独立仓库,宿主以锁版本依赖消费,子进程为主契约",
|
||||
"status": "planning",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
|
||||
Reference in New Issue
Block a user