chore(task): archive 08-25-rc-p0-contract-baseline
This commit is contained in:
118
.trellis/tasks/08-25-rc-p1-package-boundary/implement.md
Normal file
118
.trellis/tasks/08-25-rc-p1-package-boundary/implement.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Phase 1 执行计划
|
||||||
|
|
||||||
|
分批搬迁,每批后跑 parity。**不要一次性大搬。**
|
||||||
|
|
||||||
|
## Step 0 — 前置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 基线必须先绿
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] 三区域基线全绿(否则回 Phase 0)
|
||||||
|
|
||||||
|
## Step 1 — K1 矩阵(动代码之前)
|
||||||
|
|
||||||
|
- [ ] 读 `scripts/lib/traffic-signals.js` 全文,列出所有 export
|
||||||
|
- [ ] 对每个 export `grep -rn` 找使用方
|
||||||
|
- [ ] 产出 `research/traffic-signals-split-matrix.md`:函数 × 使用方 × 归属判定
|
||||||
|
- [ ] `buildTrafficSignals`(`test-preview-assets.js`)归属定档
|
||||||
|
|
||||||
|
**门槛**:矩阵完成,无"待定"项。
|
||||||
|
|
||||||
|
## Step 2 — 建包骨架
|
||||||
|
|
||||||
|
```
|
||||||
|
packages/road-compiler/
|
||||||
|
package.json # CommonJS,无构建步骤(父任务 C2)
|
||||||
|
src/
|
||||||
|
bin/
|
||||||
|
test/fixtures/
|
||||||
|
docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] `package.json` 名称、入口、`test` script
|
||||||
|
- [ ] 根 `package.json` 加 workspace 或 `file:` 依赖
|
||||||
|
|
||||||
|
## Step 3 — 分批搬迁(每批一个 commit + 一次 parity)
|
||||||
|
|
||||||
|
**批 1:纯函数,零风险**
|
||||||
|
- [ ] `lib/lane-geometry.js` → `src/geometry/lane-geometry.js`
|
||||||
|
- [ ] `lib/gaode-junction-reference.js` → `src/reference/gaode.js`
|
||||||
|
- [ ] 宿主侧改 require 指向包
|
||||||
|
- [ ] parity ✓
|
||||||
|
|
||||||
|
**批 2:几何模块**
|
||||||
|
- [ ] `lib/turn-lane-arrows.js`
|
||||||
|
- [ ] `lib/complex-junction.js`
|
||||||
|
- [ ] parity ✓
|
||||||
|
|
||||||
|
**批 3:信号(K1 执行)**
|
||||||
|
- [ ] 按 Step 1 矩阵拆 `lib/traffic-signals.js`
|
||||||
|
- [ ] `lib/native-traffic-signals.js` 与 schema 部分入包
|
||||||
|
- [ ] `lib/osm.js` 入包
|
||||||
|
- [ ] 宿主保留 legacy 读取器,从包 import schema
|
||||||
|
- [ ] parity ✓ + `npm run test:traffic-signals`(若存在)
|
||||||
|
|
||||||
|
**批 4:编译器核心**
|
||||||
|
- [ ] `lib/native-road.js` → `src/compile/native-road.js`
|
||||||
|
- [ ] parity ✓
|
||||||
|
|
||||||
|
**批 5:CLI + 窄契约(R1.2)**
|
||||||
|
- [ ] `compile-native-roads.js` → `bin/compile.js`,入参改 `RoadCompilerInput`
|
||||||
|
- [ ] `check-native-roads.js` → `bin/check.js`
|
||||||
|
- [ ] 宿主 `area-config.js` 加 `toRoadCompilerInput(area)`
|
||||||
|
- [ ] `build-area.js` 改为传 input 对象
|
||||||
|
- [ ] K3:`referenceFile` 改为宿主解析后传绝对路径,config 内改相对路径
|
||||||
|
- [ ] parity ✓
|
||||||
|
|
||||||
|
**批 6:workbench**
|
||||||
|
- [ ] `road-workbench.js` + `workbench/app.js` 入包
|
||||||
|
- [ ] OpenLayers 依赖暂沿用宿主 `node_modules`(同仓库内可行),记入 Phase 2 K4
|
||||||
|
- [ ] `npm run test:road-workbench` ✓
|
||||||
|
|
||||||
|
**批 7:测试 fixture(R1.5)**
|
||||||
|
- [ ] `inputs/osm/枫树二路.osm` 复制进 `test/fixtures/`
|
||||||
|
- [ ] `test-native-road.js` 改读包内 fixture
|
||||||
|
- [ ] 在包目录内独立跑 `npm test` ✓
|
||||||
|
|
||||||
|
## Step 4 — 清理与验证
|
||||||
|
|
||||||
|
- [ ] 删除 `scripts/lib/` 下所有搬迁文件的残留(AC1.6)
|
||||||
|
- [ ] `grep -rn "area-config\|config/areas" packages/road-compiler/` 必须为空(AC1.4)
|
||||||
|
- [ ] `grep -rn "\.\./\.\./scripts\|osm2streets-qgis-workflow" packages/road-compiler/` 检查反向依赖
|
||||||
|
|
||||||
|
## 验证命令汇总
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 测试
|
||||||
|
npm run test:native-road
|
||||||
|
npm run test:road-workbench
|
||||||
|
(cd packages/road-compiler && npm test)
|
||||||
|
|
||||||
|
# 端到端(含 blender / cesium)
|
||||||
|
npm run build:area -- --config config/areas/fengshu-er-road.json
|
||||||
|
|
||||||
|
# 反向依赖为 0
|
||||||
|
grep -rn "area-config\|config/areas" packages/road-compiler/ && echo "VIOLATION"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Review Gate
|
||||||
|
|
||||||
|
AC1.1–AC1.8 全绿。**parity 有任何一项不绿都不得进 Phase 2** —— 那意味着搬迁改变了行为,
|
||||||
|
而在同一仓库内查因比拆仓库后查因便宜得多。
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
每批一个 commit,可逐批 `git revert`。
|
||||||
|
过渡期内若需紧急回退,宿主 require 改回 `scripts/lib/` 旧路径即可
|
||||||
|
(前提:该批尚未执行 Step 4 清理)。
|
||||||
98
.trellis/tasks/08-25-rc-p1-package-boundary/prd.md
Normal file
98
.trellis/tasks/08-25-rc-p1-package-boundary/prd.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# Phase 1:包边界(不换仓库)
|
||||||
|
|
||||||
|
父任务:`.trellis/tasks/08-25-road-compiler-extraction/`
|
||||||
|
技术设计:父任务 `design.md` §2(模块清单 / K1 拆分建议)
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
在**当前仓库内**建立 `packages/road-compiler/`,移入编译器全部模块,
|
||||||
|
把对 `readAreaConfig` 的耦合换成窄输入契约,产物对 Phase 0 基线逐字节一致。
|
||||||
|
|
||||||
|
**本阶段不换仓库。** 目的是把"改坏了编译器"与"拆坏了仓库"分成两个可归因的步骤
|
||||||
|
(父任务 D4)。
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### R1.1 目录与模块搬迁
|
||||||
|
|
||||||
|
在 `packages/road-compiler/` 内建立结构,移入父任务 `design.md` §2.1 列出的全部文件
|
||||||
|
(约 3400 行核心 + workbench)。
|
||||||
|
|
||||||
|
搬迁后 `scripts/lib/` 下不应再留下这些文件的副本 —— 并存会导致
|
||||||
|
"改了一份忘了另一份"的静默不一致。
|
||||||
|
|
||||||
|
### R1.2 窄输入契约
|
||||||
|
|
||||||
|
- 编译器入口只接受父任务 `design.md` §1.1 定义的 `RoadCompilerInput`
|
||||||
|
- 编译器内不得出现 `require("area-config")`、不得读 `config/areas/*.json`、
|
||||||
|
不得从 areaId 推导任何路径
|
||||||
|
- 宿主 `scripts/lib/area-config.js` 新增 `toRoadCompilerInput(area)` 做映射
|
||||||
|
- 三个 CLI(`compile` / `check` / `workbench`)改为接受显式参数或 input JSON
|
||||||
|
|
||||||
|
### R1.3 K1:`traffic-signals.js` 拆分 🔴
|
||||||
|
|
||||||
|
**全案唯一需要细读再动的地方。** 按父任务 `design.md` §2.3:
|
||||||
|
|
||||||
|
- 随编译器走:OSM 信号节点提取 + 信号文档 schema
|
||||||
|
- 留宿主:`readTrafficSignalFeatures`(`build-osm2streets-qgis.js`)、
|
||||||
|
`readTrafficSignals`(`build-area.js`)
|
||||||
|
- 待判定:`buildTrafficSignals`(`test-preview-assets.js`)—— 需读代码确认归属
|
||||||
|
- 拆完后宿主从编译器包 import schema(宿主→编译器是允许方向)
|
||||||
|
|
||||||
|
动手前必须先产出一份「函数 × 使用方」矩阵,确认无遗漏。
|
||||||
|
|
||||||
|
### R1.4 K3:参考文件路径约定
|
||||||
|
|
||||||
|
`config/areas/fengshu-er-road.json` 的
|
||||||
|
`junctionTemplates.clusters[].referenceFile` 是指向宿主仓库的绝对路径。
|
||||||
|
|
||||||
|
- 定义解析约定:相对 config 文件所在目录,或由宿主在 `toRoadCompilerInput()`
|
||||||
|
中解析为绝对路径后传入
|
||||||
|
- 倾向后者:**编译器只接受已解析的绝对路径,不做路径推导**(符合 R1.2)
|
||||||
|
- config 内改为相对路径,宿主负责解析
|
||||||
|
|
||||||
|
### R1.5 K5:自带测试 fixture
|
||||||
|
|
||||||
|
- `test-native-road.js:167` 读 `inputs/osm/枫树二路.osm`
|
||||||
|
- 该文件(或裁剪版)复制进 `packages/road-compiler/test/fixtures/`
|
||||||
|
- 测试改为读包内 fixture,不再访问宿主 `inputs/`
|
||||||
|
- 目标:编译器包 `npm test` 不依赖宿主任何目录
|
||||||
|
|
||||||
|
### R1.6 宿主侧接线保持不变
|
||||||
|
|
||||||
|
- `build-area.js` 本阶段继续 in-process `require`(子进程改造留到 Phase 2)
|
||||||
|
- `npm run road:compile` / `road:check` / `road:workbench` 行为对用户不变
|
||||||
|
- `blender/` 完全不改
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] AC1.1 三区域 `road-parity --compare` 对 Phase 0 基线全绿
|
||||||
|
- [ ] AC1.2 `npm run test:native-road`、`npm run test:road-workbench` 通过
|
||||||
|
- [ ] AC1.3 `npm run build:area` 三区域完整跑通(含 blender / cesium 阶段)
|
||||||
|
- [ ] AC1.4 `grep -rn "area-config\|config/areas" packages/road-compiler/` 无命中
|
||||||
|
- [ ] AC1.5 `packages/road-compiler/` 内 `npm test` 不访问宿主 `inputs/` 或 `outputs/`
|
||||||
|
- [ ] AC1.6 `scripts/lib/` 下无搬迁文件的残留副本
|
||||||
|
- [ ] AC1.7 K1 的「函数 × 使用方」矩阵已产出并归档到 `research/`
|
||||||
|
- [ ] AC1.8 `compiled.json` 结构未变(父任务 AC7 / C1)
|
||||||
|
|
||||||
|
## 依赖与顺序
|
||||||
|
|
||||||
|
- **前置**:Phase 0 必须完成且基线可靠
|
||||||
|
- **阻塞**:Phase 2
|
||||||
|
- 与 Phase 3、4 无直接依赖,但它们都在 Phase 2 之后
|
||||||
|
|
||||||
|
## 风险
|
||||||
|
|
||||||
|
| 风险 | 缓解 |
|
||||||
|
|---|---|
|
||||||
|
| K1 拆分遗漏某个使用方 → 运行时才炸 | 先做矩阵,再动代码;`grep -rn` 全仓验证 |
|
||||||
|
| 搬迁过程中相对 require 路径改错 | 分小步 commit,每步跑 parity |
|
||||||
|
| `workbench/app.js` 的 OpenLayers import map 指向宿主 node_modules | 本阶段仍在同仓库,可暂不处理;记入 Phase 2(K4) |
|
||||||
|
| 一次性大搬迁难以归因 | 按模块分批:先纯函数(lane-geometry / gaode-reference),再 complex-junction,最后 native-road 与 CLI |
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- 换仓库(Phase 2)
|
||||||
|
- layer manifest(Phase 3)
|
||||||
|
- IR / pass manager 重构(父任务 C1)
|
||||||
|
- 引入 TypeScript 或构建步骤(父任务 C2)
|
||||||
26
.trellis/tasks/08-25-rc-p1-package-boundary/task.json
Normal file
26
.trellis/tasks/08-25-rc-p1-package-boundary/task.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"id": "rc-p1-package-boundary",
|
||||||
|
"name": "rc-p1-package-boundary",
|
||||||
|
"title": "Phase 1:包边界(不换仓库)",
|
||||||
|
"description": "在本仓库内建 packages/road-compiler,移入编译器模块,用窄输入契约替换 readAreaConfig 耦合,产物对基线逐字节一致",
|
||||||
|
"status": "planning",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P1",
|
||||||
|
"creator": "dingkang",
|
||||||
|
"assignee": "dingkang",
|
||||||
|
"createdAt": "2026-08-25",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "main",
|
||||||
|
"worktree_path": null,
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": "08-25-road-compiler-extraction",
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
1
.trellis/tasks/08-25-rc-p2-repo-split/check.jsonl
Normal file
1
.trellis/tasks/08-25-rc-p2-repo-split/check.jsonl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
1
.trellis/tasks/08-25-rc-p2-repo-split/implement.jsonl
Normal file
1
.trellis/tasks/08-25-rc-p2-repo-split/implement.jsonl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
74
.trellis/tasks/08-25-rc-p2-repo-split/implement.md
Normal file
74
.trellis/tasks/08-25-rc-p2-repo-split/implement.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Phase 2 执行计划
|
||||||
|
|
||||||
|
## Step 1 — 前置
|
||||||
|
|
||||||
|
- [ ] Phase 1 的 AC1.1–AC1.8 全绿
|
||||||
|
- [ ] 定档 §「待决策」四项(仓库名 / 托管 / 分发 / 过渡期策略)
|
||||||
|
|
||||||
|
## Step 2 — 拆出仓库(保历史)
|
||||||
|
|
||||||
|
```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/:
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ 注意: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 — 验证
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] 在一台未 clone 宿主的环境(或 `/tmp` 全新 clone)验证 AC2.2
|
||||||
|
|
||||||
|
## Review Gate
|
||||||
|
|
||||||
|
AC2.1–AC2.7 全绿。特别是 AC2.2(脱离宿主可自测)—— 这是"独立可维护"的实质。
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
- 宿主依赖改回 `file:packages/road-compiler`(若过渡期保留了该目录)
|
||||||
|
- 或 `git revert` 宿主侧改造 commit;新仓库留着不影响宿主
|
||||||
80
.trellis/tasks/08-25-rc-p2-repo-split/prd.md
Normal file
80
.trellis/tasks/08-25-rc-p2-repo-split/prd.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Phase 2:拆仓库
|
||||||
|
|
||||||
|
父任务:`.trellis/tasks/08-25-road-compiler-extraction/`
|
||||||
|
技术设计:父任务 `design.md` §1.3(消费方式)、§2(模块清单)
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
把 `packages/road-compiler/` 拆成保留 git 历史的独立仓库,
|
||||||
|
宿主改为锁版本依赖 + 子进程调用消费。
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### 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 以来的完整历史
|
||||||
|
|
||||||
|
### 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`)
|
||||||
|
|
||||||
|
### R2.3 锁版本依赖
|
||||||
|
|
||||||
|
- 开发期:`file:` 或 workspace 依赖
|
||||||
|
- 稳定后:git tag / 私有 npm,宿主 `package.json` **锁具体版本,不用 `latest`**
|
||||||
|
- 契约版本 `native-road-package/v1` 与包版本分开演进:
|
||||||
|
包可以发 patch,契约版本只在破坏性变更时升
|
||||||
|
|
||||||
|
### R2.4 K4:workbench 依赖自持
|
||||||
|
|
||||||
|
- `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/` 留指针,说明契约由编译器仓库拥有
|
||||||
|
|
||||||
|
## 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/` 一段时间做双跑对照 |
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- layer manifest(Phase 3)
|
||||||
|
- drawtonomy 扩展(Phase 4)
|
||||||
|
- 任何编译器内部逻辑改动 —— 本阶段代码内容不变,只换位置与消费方式
|
||||||
26
.trellis/tasks/08-25-rc-p2-repo-split/task.json
Normal file
26
.trellis/tasks/08-25-rc-p2-repo-split/task.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"id": "rc-p2-repo-split",
|
||||||
|
"name": "rc-p2-repo-split",
|
||||||
|
"title": "Phase 2:拆仓库",
|
||||||
|
"description": "保留 git 历史拆出独立仓库,宿主以锁版本依赖消费,子进程为主契约",
|
||||||
|
"status": "planning",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P1",
|
||||||
|
"creator": "dingkang",
|
||||||
|
"assignee": "dingkang",
|
||||||
|
"createdAt": "2026-08-25",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "main",
|
||||||
|
"worktree_path": null,
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": "08-25-road-compiler-extraction",
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
1
.trellis/tasks/08-25-rc-p3-render-separation/check.jsonl
Normal file
1
.trellis/tasks/08-25-rc-p3-render-separation/check.jsonl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
85
.trellis/tasks/08-25-rc-p3-render-separation/implement.md
Normal file
85
.trellis/tasks/08-25-rc-p3-render-separation/implement.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Phase 3 执行计划
|
||||||
|
|
||||||
|
## Step 1 — 枚举现有分流逻辑(定 schema 之前)
|
||||||
|
|
||||||
|
- [x] 读 `blender/generate_scene.py:796-834` 全部道路分支
|
||||||
|
- [x] 列出每个 `source` 的处理方式:直接渲染 / 按属性分流 / 跳过
|
||||||
|
- [ ] 已知分流:
|
||||||
|
- `center_lines`:`color != "white"` → `center_lines` 材质;
|
||||||
|
`color == "white"` → `native_center_line_white`
|
||||||
|
- `lane_separators`:`color != "yellow"` → `lane_separators`;
|
||||||
|
`color == "yellow"` → `native_lane_separator_yellow`
|
||||||
|
- [x] 确认 `lane_centerlines` / `connectors` 确实未被消费(→ `role: "semantic"`)
|
||||||
|
- [x] 产出 `research/native-layer-consumption-matrix.md`
|
||||||
|
|
||||||
|
**门槛**:manifest schema 能表达矩阵里的每一行,无"特例硬编码"残留。
|
||||||
|
|
||||||
|
## Step 2 — 定 manifest schema 并落契约
|
||||||
|
|
||||||
|
- [ ] 按父任务 `design.md` §3.2 定稿 schema
|
||||||
|
- [ ] 写入编译器仓库契约文档,版本标为 `native-road-package/v1.1`
|
||||||
|
- [ ] 记录:v1.1 起 `manifest.json` 为必需输出
|
||||||
|
|
||||||
|
## Step 3 — 编译器侧:生成 manifest
|
||||||
|
|
||||||
|
- [ ] 编译器内建立图层注册表(单一事实源),`compileGeometry` 的输出键与之对应
|
||||||
|
- [ ] 写 `manifest.json` 到 outDir
|
||||||
|
- [ ] 编译器自校验:manifest 声明的每个 `source` 都必须有对应 geojson 文件,
|
||||||
|
反之亦然(缺一即报错,不静默)
|
||||||
|
- [ ] parity:此步只**新增** manifest.json,其余文件应逐字节不变
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 只应多出 manifest.json
|
||||||
|
node scripts/road-parity.js --config config/areas/fengshu-er-road.json \
|
||||||
|
--compare .../baseline/fengshu-er-road.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 4 — Blender 侧:抽模块 + 读 manifest
|
||||||
|
|
||||||
|
- [ ] 新建 `blender/osmassets/native_roads.py`
|
||||||
|
- [ ] 把 `generate_scene.py:796-834` 的道路分支迁入
|
||||||
|
- [ ] 改为读 manifest 遍历;`role == "semantic"` 跳过
|
||||||
|
- [ ] `splitBy` 通用化实现,替掉两处硬编码 lambda
|
||||||
|
- [ ] **加断言**:manifest 里的 `materialLayer` 若不在 `catalog.MATERIALS` /
|
||||||
|
`ROAD_LAYERS` 中,直接 raise,不静默跳过(风险表第二条)
|
||||||
|
- [ ] 删除 `catalog.NATIVE_ROAD_LAYERS`
|
||||||
|
- [ ] `generate_scene.py` 只保留一行调用
|
||||||
|
|
||||||
|
## Step 5 — 验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .blend 结构摘要对基线
|
||||||
|
npm run build:area -- --config config/areas/fengshu-er-road.json
|
||||||
|
# 走 artifact-parity-guide 的结构摘要比对
|
||||||
|
|
||||||
|
# 三区域跑通
|
||||||
|
for a in fengshu-er-road hanyang-block nantaizi-lake-innovation-valley; do
|
||||||
|
npm run build:area -- --config config/areas/$a.json || echo "FAIL $a"
|
||||||
|
done
|
||||||
|
|
||||||
|
# 建筑/植被/水体未被改动
|
||||||
|
git diff --stat -- blender/osmassets/ | grep -vE "native_roads|catalog"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] 渲染预览图人工对照(结构摘要粒度不足的兜底)
|
||||||
|
|
||||||
|
## Step 6 — AC3.4 实测(可扩展性证明)
|
||||||
|
|
||||||
|
这一步是整个 Phase 3 的价值证明,不可跳过。
|
||||||
|
|
||||||
|
- [ ] 编译器加一个 throwaway 图层 `debug_probe.geojson`(几个矩形即可)
|
||||||
|
+ manifest 声明 `role: "marking"`,复用现有材质槽
|
||||||
|
- [ ] **不改宿主任何代码**,跑 blender 阶段
|
||||||
|
- [ ] 确认 Blender 场景中出现该图层几何
|
||||||
|
- [ ] 截图/记录证据到任务 `research/`
|
||||||
|
- [ ] 回滚 throwaway 图层
|
||||||
|
|
||||||
|
## Review Gate
|
||||||
|
|
||||||
|
AC3.1–AC3.7 全绿,特别是 AC3.4 有实测证据。
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
- 恢复 `catalog.NATIVE_ROAD_LAYERS`,`generate_scene.py` 恢复内联分支
|
||||||
|
- `manifest.json` 可保留输出(无消费方时无害)
|
||||||
|
- 编译器侧图层注册表保留(它本身是改进)
|
||||||
90
.trellis/tasks/08-25-rc-p3-render-separation/prd.md
Normal file
90
.trellis/tasks/08-25-rc-p3-render-separation/prd.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# Phase 3:道路与建筑渲染分离
|
||||||
|
|
||||||
|
父任务:`.trellis/tasks/08-25-road-compiler-extraction/`
|
||||||
|
技术设计:父任务 `design.md` §3(含 manifest 形状与 Blender 侧改造方案)
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
让编译器自声明图层,Blender 改为读 manifest 而非硬编码表;
|
||||||
|
道路渲染从 `generate_scene.py` 抽离为独立模块,建筑/植被/水体保持原位。
|
||||||
|
|
||||||
|
**这是全案价值最高的一步** —— 它把一张跨仓库重复的表变成生成物,
|
||||||
|
使"编译器加图层忘了改宿主"这类静默错误在结构上不可能。
|
||||||
|
|
||||||
|
## 背景:当前的静默错误风险
|
||||||
|
|
||||||
|
`blender/osmassets/catalog.py:53` 的 `NATIVE_ROAD_LAYERS` 有 10 项,
|
||||||
|
而编译器写 12 个 geojson —— `lane_centerlines` 与 `connectors` 是语义层不参与渲染。
|
||||||
|
|
||||||
|
**但这个事实只存在于这张表的省略里,编译器侧没有任何声明。**
|
||||||
|
拆仓库之后,这张表和它描述的对象分处两个仓库,漂移只是时间问题。
|
||||||
|
|
||||||
|
`.trellis/spec/pipeline/index.md` 首页已经把图层表标为「最容易出静默错误」。
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### R3.1 编译器输出 layer manifest
|
||||||
|
|
||||||
|
`<outDir>/manifest.json`,形状见父任务 `design.md` §3.2。要点:
|
||||||
|
|
||||||
|
- 每个图层声明 `source`(geojson 文件名)、`role`、以及渲染角色所需的 `materialLayer`
|
||||||
|
- `role: "semantic"` 显式标记不渲染的图层 —— 把省略变成声明
|
||||||
|
- `splitBy` 表达按属性分流到不同材质的逻辑
|
||||||
|
(当前 `generate_scene.py:815-819` 硬编码的 `color != "white"` / `color == "yellow"`)
|
||||||
|
- 材质本体(颜色、z 高度、贴图)**仍归宿主** `catalog.py::MATERIALS`;
|
||||||
|
编译器不懂渲染,只声明"我有哪些图层、什么角色、该用哪个材质槽"
|
||||||
|
|
||||||
|
### R3.2 Blender 侧改造
|
||||||
|
|
||||||
|
- `generate_scene.py` 内道路分支抽为 `blender/osmassets/native_roads.py`
|
||||||
|
- 新模块读 manifest 遍历,不再查硬编码表
|
||||||
|
- 删除 `catalog.NATIVE_ROAD_LAYERS`
|
||||||
|
- 建筑(`handle_building` / `dispatch_ways`)、植被、水体**保持原位不动**
|
||||||
|
|
||||||
|
### R3.3 契约版本处理
|
||||||
|
|
||||||
|
新增 `manifest.json` 是**向后兼容的增量**(旧消费方忽略未知文件即可),
|
||||||
|
但 Blender 改为依赖它之后就成了必需项。
|
||||||
|
|
||||||
|
- 契约文档记录:`manifest.json` 自 v1.1 起为必需输出
|
||||||
|
- 宿主声明所需最低契约版本
|
||||||
|
|
||||||
|
### R3.4 跨层一致性检查
|
||||||
|
|
||||||
|
按 `.trellis/spec/guides/cross-layer-thinking-guide.md`:
|
||||||
|
本改动同时触碰 JS(编译器输出)、Python(Blender 消费)、契约文档三层,
|
||||||
|
必须走该指南的检查清单。
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] AC3.1 编译器输出 `manifest.json`,三区域均含全部 12 图层声明
|
||||||
|
- [ ] AC3.2 `catalog.NATIVE_ROAD_LAYERS` 已删除,Blender 无硬编码道路图层表
|
||||||
|
- [ ] AC3.3 `.blend` 结构摘要对 Phase 0 基线一致
|
||||||
|
(走 `.trellis/spec/guides/artifact-parity-guide.md`)
|
||||||
|
- [ ] AC3.4 **实测**:向编译器加一个 throwaway 图层 + manifest 声明,
|
||||||
|
不改宿主任何代码,跑 blender 阶段确认它被渲染出来;验证后回滚该图层
|
||||||
|
(父任务 AC5,见 design §3.4)
|
||||||
|
- [ ] AC3.5 `role: "semantic"` 的图层被 Blender 正确跳过(不产生几何)
|
||||||
|
- [ ] AC3.6 `center_lines` 的 white/非 white 与 `lane_separators` 的 yellow/非 yellow
|
||||||
|
分流行为与改造前一致
|
||||||
|
- [ ] AC3.7 建筑/植被/水体渲染代码未被修改(`git diff` 验证范围)
|
||||||
|
|
||||||
|
## 依赖与顺序
|
||||||
|
|
||||||
|
- **前置**:Phase 2 完成(编译器已独立,manifest 才有"跨仓库契约"的意义)
|
||||||
|
- 与 Phase 4 无依赖,可并行
|
||||||
|
- 完成本阶段后,父任务 Goal 中的「道路与建筑渲染分离」才算达成
|
||||||
|
|
||||||
|
## 风险
|
||||||
|
|
||||||
|
| 风险 | 缓解 |
|
||||||
|
|---|---|
|
||||||
|
| `splitBy` 表达力不足,覆盖不了现有分流逻辑 | 先枚举 `generate_scene.py` 里全部分流分支,再定 manifest schema |
|
||||||
|
| 材质槽名在两侧漂移 | manifest 里的 `materialLayer` 必须能被宿主校验:Blender 侧加断言,未知材质槽直接报错而非静默跳过 |
|
||||||
|
| `.blend` 结构摘要对比粒度不够,漏掉几何差异 | 除结构摘要外,加渲染预览图人工对照 |
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- 材质定义搬去编译器(材质属渲染,归宿主)
|
||||||
|
- osm2streets legacy 图层表 `ROAD_LAYERS` 的改动
|
||||||
|
- 建筑/植被/水体渲染逻辑
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Native Road 图层消费矩阵
|
||||||
|
|
||||||
|
调研日期:2026-08-25
|
||||||
|
|
||||||
|
## 证据
|
||||||
|
|
||||||
|
- 编译器在 `scripts/compile-native-roads.js:57,65-76` 声明并写出 12 个图层。
|
||||||
|
- Blender 在 `blender/generate_scene.py:796-834` 遍历
|
||||||
|
`catalog.NATIVE_ROAD_LAYERS`,只消费其中 10 个图层。
|
||||||
|
- 当前映射及基础高度来自 `blender/osmassets/catalog.py:53-64` 与 `ROAD_LAYERS`。
|
||||||
|
|
||||||
|
## 当前消费与 manifest 目标
|
||||||
|
|
||||||
|
| 编译器 source | 当前 Blender 行为 | 当前材质槽 / z 来源 | manifest 目标 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `road_surface` | 直接渲染 | `road_surface` / `ROAD_LAYERS.road_surface` | `role: surface`, `materialLayer: road_surface` |
|
||||||
|
| `edge_lines` | 直接渲染 | `lane_separators` / `ROAD_LAYERS.lane_separators` | `role: marking`, `materialLayer: lane_separators` |
|
||||||
|
| `intersection_surface` | 直接渲染 | `intersection_surface` / `ROAD_LAYERS.intersection_surface` | `role: surface`, `materialLayer: intersection_surface` |
|
||||||
|
| `sidewalk_surface` | 直接渲染 | `sidewalks` / `ROAD_LAYERS.sidewalks` | `role: surface`, `materialLayer: sidewalks` |
|
||||||
|
| `lane_separators` | 按 `color` 分流 | 非 yellow: `lane_separators`; yellow: `native_lane_separator_yellow`; z 取 `lane_separators` | `role: marking`, `materialLayer: lane_separators`, `splitBy.color`(yellow 特例) |
|
||||||
|
| `center_lines` | 按 `color` 分流 | 非 white: `center_lines`; white: `native_center_line_white`; z 取 `center_lines` | `role: marking`, `materialLayer: center_lines`, `splitBy.color`(white 特例) |
|
||||||
|
| `direction_arrows` | 直接渲染 | `lane_arrows_webscale` / `ROAD_LAYERS.lane_arrows_webscale` | `role: marking`, `materialLayer: lane_arrows_webscale` |
|
||||||
|
| `turn_arrows` | 直接渲染 | `lane_arrows_webscale` / `ROAD_LAYERS.lane_arrows_webscale` | `role: marking`, `materialLayer: lane_arrows_webscale` |
|
||||||
|
| `crosswalks` | 直接渲染 | `crosswalks` / `ROAD_LAYERS.crosswalks` | `role: marking`, `materialLayer: crosswalks` |
|
||||||
|
| `vehicle_stop_lines` | 直接渲染 | `vehicle_stop_lines` / `ROAD_LAYERS.vehicle_stop_lines` | `role: marking`, `materialLayer: vehicle_stop_lines` |
|
||||||
|
| `lane_centerlines` | 不进入 Blender 遍历 | 无 | `role: semantic`,Blender 跳过 |
|
||||||
|
| `connectors` | 不进入 Blender 遍历 | 无 | `role: semantic`,Blender 跳过 |
|
||||||
|
|
||||||
|
## 结论与实施约束
|
||||||
|
|
||||||
|
- manifest 必须声明全部 12 个编译器图层,不能再用“未出现在列表中”表达不渲染。
|
||||||
|
- `role: semantic` 的两个图层不得读取 GeoJSON 或创建 Blender 几何。
|
||||||
|
- `splitBy` 至少需表达属性 `color` 的精确匹配与默认分支,且分流后沿用同一个基础材质槽的 z 值。
|
||||||
|
- Blender 消费 manifest 时,未知 `materialLayer`、缺失 source 文件、或 source 未在 manifest 声明都必须报错;不能静默跳过。
|
||||||
26
.trellis/tasks/08-25-rc-p3-render-separation/task.json
Normal file
26
.trellis/tasks/08-25-rc-p3-render-separation/task.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"id": "rc-p3-render-separation",
|
||||||
|
"name": "rc-p3-render-separation",
|
||||||
|
"title": "Phase 3:道路与建筑渲染分离",
|
||||||
|
"description": "编译器输出 layer manifest 自声明图层,Blender 改为读 manifest;道路渲染从 generate_scene.py 抽离,消除跨仓库重复图层表",
|
||||||
|
"status": "planning",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"creator": "dingkang",
|
||||||
|
"assignee": "dingkang",
|
||||||
|
"createdAt": "2026-08-25",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "main",
|
||||||
|
"worktree_path": null,
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": "08-25-road-compiler-extraction",
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
1
.trellis/tasks/08-25-rc-p4-drawtonomy-ext/check.jsonl
Normal file
1
.trellis/tasks/08-25-rc-p4-drawtonomy-ext/check.jsonl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
96
.trellis/tasks/08-25-rc-p4-drawtonomy-ext/prd.md
Normal file
96
.trellis/tasks/08-25-rc-p4-drawtonomy-ext/prd.md
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# 后续计划:drawtonomy 扩展 PoC
|
||||||
|
|
||||||
|
前置任务:`08-25-road-compiler-extraction` 的 Phase 0-3 完成并完成验收。
|
||||||
|
评估依据:父任务归档前的 `design.md` §4 决策记录 D1 / D2 / D3。
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
在**编译器仓库内**实现一个 drawtonomy 扩展:把编译产物注入其浏览器编辑器,
|
||||||
|
回读快照后走其开源导出器产出 OpenDRIVE / Lanelet2。
|
||||||
|
|
||||||
|
定位是 **PoC,不进关键路径**。目的是验证「编译器当 scene generator +
|
||||||
|
drawtonomy 当编辑器与工业格式后端」这条链路是否值得投入。
|
||||||
|
|
||||||
|
## 前提认知(已核实)
|
||||||
|
|
||||||
|
必须先明确,否则会做错方向:
|
||||||
|
|
||||||
|
- **drawtonomy 编辑器闭源**,克隆仓库只有 SDK / dev-server / mcp-server。
|
||||||
|
README 卖点里的 topology-aware lanes、lane tool、intersection templates、
|
||||||
|
Map→lanes 全部不在开源代码内。
|
||||||
|
- **它不做 raw OSM 推导**。`exporter/osmParser.ts` 是 Lanelet2 解析器
|
||||||
|
(车道左右边界已显式)。整个 exporter 目录 grep `highway` 命中 1 次且是
|
||||||
|
车道类型字符串。→ **不能替代本编译器**,只能做下游。
|
||||||
|
- **junctionTools 不能做成扩展**:无 canvas/overlay 能力、无工具注册、
|
||||||
|
**无任何 change 事件推送**(`ExtensionClient.handleMessage` 入站只有
|
||||||
|
`ext:init` / 5 个 `*-response` / `ext:error`,读取全靠轮询)。
|
||||||
|
→ junction 编辑留在自有 workbench。
|
||||||
|
- **`drawtonomy-dev-server` 是 drawtonomy.com 的缓存代理**(TTL 1 小时),
|
||||||
|
非自托管。宿主协议会漂(manifest 有 `minHostVersion`)。→ 不进关键路径。
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### R4.1 扩展:编译产物 → 编辑器
|
||||||
|
|
||||||
|
- manifest capabilities:`shapes:write`、`ui:panel`、`snapshot:read`、`ui:notify`
|
||||||
|
- 面板调编译器的本地 HTTP 服务(`road-workbench` 已经是一个 HTTP 服务)取产物
|
||||||
|
- 车道边界 → `createLaneWithBoundaries(leftPoints, rightPoints, opts)` → `addShapes()`
|
||||||
|
- 坐标转换:本项目 WGS84/ENU(米)→ drawtonomy 画布像素。
|
||||||
|
沿用其 `drawtonomy_origin_lat/lon` + `latLonToCanvas` 约定
|
||||||
|
- ⚠️ **借它的结构,不借它的坐标系**:其 `BaseShape.x/y` 是画布像素
|
||||||
|
(`z` 注释明确写 "world units — NOT canvas pixels like x/y")。
|
||||||
|
编译器内部坐标系不得因此改变
|
||||||
|
|
||||||
|
### R4.2 回读 → 工业格式导出
|
||||||
|
|
||||||
|
- `requestSnapshot()` 取回快照
|
||||||
|
- 本地跑其开源 `exportToOpenDrive` / `lanelet2`(Apache-2.0)
|
||||||
|
- 产出 `.xodr` / `.osm`(Lanelet2),用其 `validateOpenDrive` 自校验
|
||||||
|
- Lanelet2 是 Autoware 的输入格式 —— 对本项目 V2X 方向有实际价值
|
||||||
|
|
||||||
|
### R4.3 许可与依赖合规
|
||||||
|
|
||||||
|
- drawtonomy SDK 是 Apache-2.0:借用代码需保留 NOTICE / 署名
|
||||||
|
- 若依赖 drawtonomy.com 托管服务,需查其服务条款(app 非 Apache-2.0)
|
||||||
|
- ESM/CJS 互操作:SDK 是 ESM+TS,编译器是 CJS。
|
||||||
|
本阶段可**局部**引入构建步骤,但仅限扩展目录,不得污染编译器核心
|
||||||
|
(父任务 C2 的边界)
|
||||||
|
|
||||||
|
### R4.4 归属
|
||||||
|
|
||||||
|
扩展代码放**编译器仓库**,不放宿主 —— 符合父任务「独立维护」目标。
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] AC4.1 扩展能把一个区域的编译产物注入 drawtonomy 编辑器并正确显示车道
|
||||||
|
- [ ] AC4.2 编辑器内手改后回读快照,能导出通过 `validateOpenDrive` 的 `.xodr`
|
||||||
|
- [ ] AC4.3 能导出 Lanelet2 `.osm`
|
||||||
|
- [ ] AC4.4 编译器核心未引入构建步骤(构建仅限扩展目录)
|
||||||
|
- [ ] AC4.5 编译器内部坐标系未因适配画布像素而改变
|
||||||
|
- [ ] AC4.6 Apache-2.0 署名 / NOTICE 已按要求保留
|
||||||
|
- [ ] AC4.7 结论记录:这条链路是否值得继续投入,写入任务 `research/`
|
||||||
|
|
||||||
|
## 启动条件
|
||||||
|
|
||||||
|
- 道路编译器独立化父任务(Phase 0-3)已完成验收。
|
||||||
|
- 编译器仓库、稳定 CLI 与版本化输出契约已可用。
|
||||||
|
- 此任务不阻塞道路编译器抽离或渲染分离的交付。
|
||||||
|
|
||||||
|
## 明确不做
|
||||||
|
|
||||||
|
- junctionTools 做成扩展(API 不支持,见前提认知)
|
||||||
|
- 把 drawtonomy 放进生产构建链路
|
||||||
|
- 用 drawtonomy 替代编译器(D1 已否决)
|
||||||
|
- 自建通用白板编辑器
|
||||||
|
|
||||||
|
## 后续可能(不属本阶段)
|
||||||
|
|
||||||
|
父任务 design §4 的 D3 列了三项值得从 drawtonomy 借用的东西,
|
||||||
|
它们与本阶段独立,应各自开任务:
|
||||||
|
|
||||||
|
- `odrGeometryFit.ts` 的拟合器 → 替掉手调的
|
||||||
|
`approachWidthMultiplier=1.45` / `coreRadiusMeters=28`,改为对 `referenceFile`
|
||||||
|
拟合、残差作质量指标
|
||||||
|
- validator 的 mutation-proven 方法 → 给现有 31 条诊断规则建触发证明
|
||||||
|
- validator 的分层命名空间(`xml.*` / `ref.*` / `junction.*` / `geom.*`)
|
||||||
|
→ 替代当前平铺的 31 条规则
|
||||||
28
.trellis/tasks/08-25-rc-p4-drawtonomy-ext/task.json
Normal file
28
.trellis/tasks/08-25-rc-p4-drawtonomy-ext/task.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"id": "rc-p4-drawtonomy-ext",
|
||||||
|
"name": "rc-p4-drawtonomy-ext",
|
||||||
|
"title": "后续计划:drawtonomy 扩展 PoC",
|
||||||
|
"description": "道路编译器独立化完成后,评估在编译器仓库内实现 drawtonomy 扩展:编译产物注入编辑器,快照回读后走开源 OpenDRIVE/Lanelet2 导出",
|
||||||
|
"status": "planning",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P3",
|
||||||
|
"creator": "dingkang",
|
||||||
|
"assignee": "dingkang",
|
||||||
|
"createdAt": "2026-08-25",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "main",
|
||||||
|
"worktree_path": null,
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": null,
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "不属于道路编译器独立化父任务的完成条件。父任务验收完成后,将此任务作为下一项候选任务提示。",
|
||||||
|
"meta": {
|
||||||
|
"follow_up_after": "08-25-road-compiler-extraction"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"_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."}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"name": "rc-p0-contract-baseline",
|
"name": "rc-p0-contract-baseline",
|
||||||
"title": "Phase 0:冻结契约与 parity 基线",
|
"title": "Phase 0:冻结契约与 parity 基线",
|
||||||
"description": "写死 native-road-package/v1 输入输出契约,并对两个有效区域建立逐文件 checksum 基线作为全案 oracle",
|
"description": "写死 native-road-package/v1 输入输出契约,并对两个有效区域建立逐文件 checksum 基线作为全案 oracle",
|
||||||
"status": "in_progress",
|
"status": "completed",
|
||||||
"dev_type": null,
|
"dev_type": null,
|
||||||
"scope": null,
|
"scope": null,
|
||||||
"package": null,
|
"package": null,
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"creator": "dingkang",
|
"creator": "dingkang",
|
||||||
"assignee": "dingkang",
|
"assignee": "dingkang",
|
||||||
"createdAt": "2026-08-25",
|
"createdAt": "2026-08-25",
|
||||||
"completedAt": null,
|
"completedAt": "2026-08-25",
|
||||||
"branch": null,
|
"branch": null,
|
||||||
"base_branch": "main",
|
"base_branch": "main",
|
||||||
"worktree_path": null,
|
"worktree_path": null,
|
||||||
Reference in New Issue
Block a user