From 7e8fcd82ed97c39fbba3b5872a39531e91eb60fd Mon Sep 17 00:00:00 2001 From: que01 Date: Wed, 26 Aug 2026 12:59:31 +0800 Subject: [PATCH] chore: record ZIP artifact task completion --- .../08-25-road-compiler-extraction/task.json | 7 +- .../check.jsonl | 3 + .../design.md | 23 +++++ .../implement.jsonl | 3 + .../implement.md | 14 +++ .../08-26-rc-p5-artifact-consumption/prd.md | 95 +++++++++++++++++++ .../task.json | 29 ++++++ .../tasks/08-26-rc-p5a-zip-export/check.jsonl | 1 + .../tasks/08-26-rc-p5a-zip-export/design.md | 22 +++++ .../08-26-rc-p5a-zip-export/implement.jsonl | 1 + .../08-26-rc-p5a-zip-export/implement.md | 10 ++ .trellis/tasks/08-26-rc-p5a-zip-export/prd.md | 34 +++++++ .../tasks/08-26-rc-p5a-zip-export/task.json | 26 +++++ .../tasks/08-26-rc-p5b-zip-import/check.jsonl | 1 + .../tasks/08-26-rc-p5b-zip-import/design.md | 19 ++++ .../08-26-rc-p5b-zip-import/implement.jsonl | 1 + .../08-26-rc-p5b-zip-import/implement.md | 12 +++ .trellis/tasks/08-26-rc-p5b-zip-import/prd.md | 40 ++++++++ 18 files changed, 338 insertions(+), 3 deletions(-) create mode 100644 .trellis/tasks/08-26-rc-p5-artifact-consumption/check.jsonl create mode 100644 .trellis/tasks/08-26-rc-p5-artifact-consumption/design.md create mode 100644 .trellis/tasks/08-26-rc-p5-artifact-consumption/implement.jsonl create mode 100644 .trellis/tasks/08-26-rc-p5-artifact-consumption/implement.md create mode 100644 .trellis/tasks/08-26-rc-p5-artifact-consumption/prd.md create mode 100644 .trellis/tasks/08-26-rc-p5-artifact-consumption/task.json create mode 100644 .trellis/tasks/08-26-rc-p5a-zip-export/check.jsonl create mode 100644 .trellis/tasks/08-26-rc-p5a-zip-export/design.md create mode 100644 .trellis/tasks/08-26-rc-p5a-zip-export/implement.jsonl create mode 100644 .trellis/tasks/08-26-rc-p5a-zip-export/implement.md create mode 100644 .trellis/tasks/08-26-rc-p5a-zip-export/prd.md create mode 100644 .trellis/tasks/08-26-rc-p5a-zip-export/task.json create mode 100644 .trellis/tasks/08-26-rc-p5b-zip-import/check.jsonl create mode 100644 .trellis/tasks/08-26-rc-p5b-zip-import/design.md create mode 100644 .trellis/tasks/08-26-rc-p5b-zip-import/implement.jsonl create mode 100644 .trellis/tasks/08-26-rc-p5b-zip-import/implement.md create mode 100644 .trellis/tasks/08-26-rc-p5b-zip-import/prd.md diff --git a/.trellis/tasks/08-25-road-compiler-extraction/task.json b/.trellis/tasks/08-25-road-compiler-extraction/task.json index dcf2b37..05eebcc 100644 --- a/.trellis/tasks/08-25-road-compiler-extraction/task.json +++ b/.trellis/tasks/08-25-road-compiler-extraction/task.json @@ -22,12 +22,13 @@ "08-25-rc-p0-contract-baseline", "08-25-rc-p1-package-boundary", "08-25-rc-p2-repo-split", - "08-25-rc-p3-render-separation" + "08-25-rc-p3-render-separation", + "08-26-rc-p5-artifact-consumption" ], "parent": null, "relatedFiles": [], - "notes": "", + "notes": "P3 已完成。P5 artifact-only parent 已建立,P5A ZIP export 已在 road-compiler v0.3.0 完成;P5B 宿主 ZIP import 待实施。", "meta": { "next_task": "08-25-rc-p4-drawtonomy-ext" } -} \ No newline at end of file +} diff --git a/.trellis/tasks/08-26-rc-p5-artifact-consumption/check.jsonl b/.trellis/tasks/08-26-rc-p5-artifact-consumption/check.jsonl new file mode 100644 index 0000000..5ae275e --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5-artifact-consumption/check.jsonl @@ -0,0 +1,3 @@ +{"file":".trellis/spec/blender/testing.md","reason":"P3 scene digest parity 是消费迁移的回归门槛。"} +{"file":".trellis/spec/pipeline/native-road-package.md","reason":"验证 ZIP 解压后的 v1.1 contract、areaId 和 source 集合。"} +{"file":".trellis/spec/guides/artifact-parity-guide.md","reason":"验证导入迁移不改变 Blender 产物结构。"} diff --git a/.trellis/tasks/08-26-rc-p5-artifact-consumption/design.md b/.trellis/tasks/08-26-rc-p5-artifact-consumption/design.md new file mode 100644 index 0000000..3232bec --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5-artifact-consumption/design.md @@ -0,0 +1,23 @@ +# P5 Artifact-Only Road Package Design + +P5 replaces the current runtime dependency boundary with a file-only boundary: + +```text +road-compiler Web editor + -> deterministic root-flat native-road-package/v1.1 ZIP + -> osmWorkflow config nativeRoadPackage + -> private verified extraction cache + -> Blender / Cesium / preview +``` + +The road-compiler repository owns export and all editing/compiler internals. osmWorkflow owns ZIP safety, +contract validation, Blender materials and downstream scene construction. Neither repository reads the +other's source, configuration, overrides or runtime implementation. + +The ZIP is immutable input and the host's `_pipeline/native-road-import/` is disposable cache. +The host rejects unsafe archive topology before writing files, then validates v1.1 `manifest.json` and +area identity before starting Blender. Stage manifests record the ZIP hash and resolved package records. + +P5A publishes a fixture/exporter first. P5B uses that fixture to remove compiler CLI installation and +invocation from the host. The migration is intentionally a contract-preserving transport change: rendered +geometry and material behavior must remain at the P3 baseline. diff --git a/.trellis/tasks/08-26-rc-p5-artifact-consumption/implement.jsonl b/.trellis/tasks/08-26-rc-p5-artifact-consumption/implement.jsonl new file mode 100644 index 0000000..9b81041 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5-artifact-consumption/implement.jsonl @@ -0,0 +1,3 @@ +{"file":".trellis/spec/pipeline/native-road-package.md","reason":"宿主与编译器之间的现有文件契约。"} +{"file":".trellis/spec/pipeline/external-tools.md","reason":"ZIP 导入必须在 Blender 副作用前完成安全校验。"} +{"file":".trellis/spec/guides/cross-layer-thinking-guide.md","reason":"导出、Node 导入、Blender 和 preview 的跨层数据流。"} diff --git a/.trellis/tasks/08-26-rc-p5-artifact-consumption/implement.md b/.trellis/tasks/08-26-rc-p5-artifact-consumption/implement.md new file mode 100644 index 0000000..5898644 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5-artifact-consumption/implement.md @@ -0,0 +1,14 @@ +# P5 Integration Plan + +1. Complete P5A in `road-compiler`: deterministic Web/CLI ZIP export plus supported-area fixtures and a + tagged compiler release. +2. Complete P5B in `osmWorkflow`: safe importer, config migration, CLI/dependency removal and downstream + descriptor migration. +3. Run the shared end-to-end gate on `fengshu-er-road` and `nantaizi-lake-innovation-valley`: + import ZIP -> Blender -> Cesium -> package -> preview -> area checks. +4. Compare Blender scene digests to P3 control; run negative ZIP tests and legacy provider tests. +5. Record contract docs in both repositories, commit each repository independently, then archive both + children and this integration parent. + +Integration rollback: restore the host's previous tagged compiler dependency and compile adapter. ZIP export +is additive and its generated files remain valid standalone artifacts. diff --git a/.trellis/tasks/08-26-rc-p5-artifact-consumption/prd.md b/.trellis/tasks/08-26-rc-p5-artifact-consumption/prd.md new file mode 100644 index 0000000..0f0bd21 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5-artifact-consumption/prd.md @@ -0,0 +1,95 @@ +# 道路包导入与纯消费管线 + +父任务:`.trellis/tasks/08-25-road-compiler-extraction/` + +本任务是集成 parent:导出与导入分别在 road-compiler 和宿主仓库实现,只有两个子任务的 +端到端 ZIP 契约都通过后才完成。 + +## Goal + +让 road-compiler Web 导出的 `native-road-package/v1.1` 成为 Blender 管线的唯一 +native-road 输入。宿主只校验并消费完整道路包,不再安装、调用或理解道路编译器。 + +用户价值:人工在 road-compiler Web 编辑后,导出道路包即可稳定交给 Blender / Cesium +构建;编辑成果不再通过发布新的编译器代码版本传播。 + +## Confirmed Facts + +- P3 已使 Blender 通过 `manifest.json` 消费 `layers/*.geojson`,并拒绝无效 manifest、 + source/file 不一致和未知宿主材质槽。 +- 宿主当前仍通过 `scripts/build-area.js` 调用 `scripts/lib/road-compiler-cli.js`;后者安装并 + 运行 `@osm-asset/road-compiler`,将 `RoadCompilerInput` 写入 `_pipeline/`。 +- native Blender 构建当前强制使用 `outputs//native-road/`,并在每次构建前重新编译; + 宿主还持有 `nativeRoad.edgeLines`、`junctionTemplates`、overrides 和 compiler runtime + 路径等编译器内部概念。 +- `osm2streets` 是显式 legacy/debug provider,应保持现有行为。 +- 有效验证区域只有 `fengshu-er-road` 与 `nantaizi-lake-innovation-valley`; + `hanyang-block` 不参与。 + +## Requirements + +### R1 纯产物边界 + +- native provider 只接收一个完整 `native-road-package/v1.1` 目录。 +- 宿主不得依赖 `@osm-asset/road-compiler`,不得调用 compiler CLI,不得写 + `RoadCompilerInput`,不得读取或解释 compiler overrides / junction templates。 +- 宿主以 manifest 作为道路图层事实源,Blender 不增加 compiler 专用图层表。 + +### R2 ZIP 导入配置和校验 + +- 每个 native 区域配置一个道路包 ZIP 路径;路径相对于区域配置文件解析并可指向工作区外的 + road-compiler Web 导出文件。 +- ZIP 根目录必须直接包含 `manifest.json` 和契约定义的文件;不得接受多余顶层目录、绝对路径、 + `..` 路径或符号链接。 +- 在启动 Blender 前,宿主将 ZIP 安全解压到其私有 pipeline staging 目录,校验 manifest + 契约版本、`areaId` 和当前区域一致,并记录 ZIP hash 和展开文件记录到 stage manifest。 +- ZIP 永远只读:宿主不复制、覆盖或修改 road-compiler Web 的导出文件;成功或失败后仅清理 + 自己的临时解压目录。 +- Blender 继续校验 manifest 的图层、source、semantic 角色、材质槽和 splitBy 规则。 + +### R3 后续阶段 + +- Cesium、package、preview 和区域诊断从导入道路包读取原生车道中心线、signals 和 + 其他既有 native-road 输入;不重新编译或复制道路包。 +- build stage manifest 将道路包作为外部输入记录,而非宿主输出。 + +### R4 清理和迁移 + +- 删除宿主对 compiler npm 包、CLI 封装和编译脚本的生产依赖。 +- 删除或替换只测试宿主编译行为的测试;保留 package-contract、Blender 和下游消费测试。 +- 更新示例配置、README、pipeline spec 和道路包契约,明确 Web export -> host consume + 的单向关系。 + +## Acceptance Criteria + +- [ ] AC1 `package.json` / lockfile 和生产脚本不再引用 `@osm-asset/road-compiler` 或其 CLI。 +- [ ] AC2 两个有效区域均可从配置指定的已导出 ZIP 道路包运行 Blender、Cesium、package 和 preview, + 构建期间没有 compiler 子进程。 +- [ ] AC3 宿主在 Blender 前拒绝缺失包、错误 contract、错误 areaId 和无效 manifest;错误说明 + 指向导入包和契约,而非 compiler 内部。 +- [ ] AC4 Blender scene digest 与 P3 control 基线一致;native semantic 层仍不生成几何。 +- [ ] AC5 stage manifest / diagnose / check area 将导入道路包记录为输入并能识别缺失或变更。 +- [ ] AC6 `osm2streets` legacy provider 行为未变。 +- [ ] AC7 文档和配置将人工编辑传播路径表述为 road-compiler Web export -> host consume。 + +## Out of Scope + +- road-compiler Web 的编辑器功能、认证、部署或 UI 改造。 +- 修改道路几何、材质、Blender 建筑/植被/水体渲染。 +- 新的 manifest 破坏性版本或 lane graph IR。 +- 将道路包上传到远程制品库或实现同步服务。 + +## Key Decision + +- Web 导出的是标准 ZIP;宿主配置直接指向 ZIP 而不是目录。ZIP 是跨仓库的不可变交付物, + 宿主只在私有 staging 目录中解压和消费,因而没有导出目录 ownership 或覆盖歧义。 + +## Subtask Map + +| 子任务 | 仓库 | 交付物 | 依赖 | +|---|---|---|---| +| `rc-p5a-zip-export` | road-compiler | Web / CLI 可导出的 root-flat `native-road-package/v1.1` ZIP | 无 | +| `rc-p5b-zip-import` | osmWorkflow | 配置、受控解压、校验和纯消费管线 | p5a 的 ZIP fixture | + +跨任务验收:同一个 ZIP fixture 必须被 p5b 的两个有效区域构建消费;宿主不得保留 +compiler npm 或 CLI 耦合。 diff --git a/.trellis/tasks/08-26-rc-p5-artifact-consumption/task.json b/.trellis/tasks/08-26-rc-p5-artifact-consumption/task.json new file mode 100644 index 0000000..49b4aab --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5-artifact-consumption/task.json @@ -0,0 +1,29 @@ +{ + "id": "rc-p5-artifact-consumption", + "name": "rc-p5-artifact-consumption", + "title": "道路包导入与纯消费管线", + "description": "让宿主通过配置指向 road-compiler Web 导出的 ZIP 道路包,只校验和消费该版本化文件契约,不再安装或调用编译器。", + "status": "planning", + "dev_type": null, + "scope": null, + "package": null, + "priority": "P2", + "creator": "dingkang", + "assignee": "dingkang", + "createdAt": "2026-08-26", + "completedAt": null, + "branch": null, + "base_branch": "experiment/road-compiler-rethink", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [ + "08-26-rc-p5b-zip-import", + "08-26-rc-p5a-zip-export" + ], + "parent": "08-25-road-compiler-extraction", + "relatedFiles": [], + "notes": "", + "meta": {} +} \ No newline at end of file diff --git a/.trellis/tasks/08-26-rc-p5a-zip-export/check.jsonl b/.trellis/tasks/08-26-rc-p5a-zip-export/check.jsonl new file mode 100644 index 0000000..9dd3234 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5a-zip-export/check.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. 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."} diff --git a/.trellis/tasks/08-26-rc-p5a-zip-export/design.md b/.trellis/tasks/08-26-rc-p5a-zip-export/design.md new file mode 100644 index 0000000..607090e --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5a-zip-export/design.md @@ -0,0 +1,22 @@ +# P5A ZIP Export Design + +The compiler owns a pure `exportNativeRoadPackage(result, destination)` function. It writes a +temporary root-flat directory from the already compiled Web/CLI state, validates it with the same +manifest/source validator used by compiler output, then writes a deterministic ZIP. The Web download +handler and CLI are thin callers of this function. + +ZIP layout: + +```text +manifest.json +compiled.json +diagnostics.json +comparison.json +traffic-signal-assemblies.json +traffic-signals.json +layers/<12 declared sources>.geojson +``` + +`manifest.generator` is informational only. The host accepts solely the `contract`, `areaId`, and +declared files. ZIP creation normalizes entry order and timestamps so the export is hash-stable. +Failure never replaces a chosen output file. diff --git a/.trellis/tasks/08-26-rc-p5a-zip-export/implement.jsonl b/.trellis/tasks/08-26-rc-p5a-zip-export/implement.jsonl new file mode 100644 index 0000000..9dd3234 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5a-zip-export/implement.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. 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."} diff --git a/.trellis/tasks/08-26-rc-p5a-zip-export/implement.md b/.trellis/tasks/08-26-rc-p5a-zip-export/implement.md new file mode 100644 index 0000000..09fa083 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5a-zip-export/implement.md @@ -0,0 +1,10 @@ +# P5A Execution Plan + +1. Inspect workbench state ownership and compiler output writer; keep export sourced from the current + compiled state, not host paths. +2. Add deterministic root-flat ZIP writer plus validation and CLI entry point. +3. Add Web download action using the same writer. +4. Add fixtures for root layout, content determinism, manifest/source parity and edited-state export. +5. Export both supported-area fixtures for P5B, run compiler tests, then publish a compiler release. + +Rollback: remove the export entry point; no host behavior changes in this subtask. diff --git a/.trellis/tasks/08-26-rc-p5a-zip-export/prd.md b/.trellis/tasks/08-26-rc-p5a-zip-export/prd.md new file mode 100644 index 0000000..1bc3a07 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5a-zip-export/prd.md @@ -0,0 +1,34 @@ +# Web 导出原生道路 ZIP 包 + +## Goal + +让 road-compiler Web/CLI 以 root-flat native-road-package/v1.1 ZIP 导出人工编辑后的道路包。 + +## Requirements + +- 从 Web 当前编辑状态导出完整道路包,而不是源代码、npm 包或仅 overrides。 +- ZIP 根直接包含 `manifest.json`,并包含全部 manifest 声明的 `layers/.geojson`、 + `compiled.json`、`traffic-signals.json` 和 preview 所需的 signal / diagnostics 文档。 +- `manifest.json` 的 `contract` 保持 `native-road-package/v1.1`;新增可选 `generator` 元数据 + 记录应用版本和 revision,但不得让宿主依赖该版本。 +- Web 提供用户可见的下载操作;CLI 提供等价、可测试的 ZIP 导出入口。 +- ZIP 条目顺序、JSON 序列化和压缩时间戳必须确定性,重复导出未编辑内容的文件 hash 一致。 + +## Acceptance Criteria + +- [x] 从 Web 编辑后的区域可下载一个 root-flat ZIP,且无需宿主或 npm 发布。 +- [x] CLI fixture 导出 ZIP 后,解压内容通过 compiler 的 `validatePublishedLayers()`。 +- [x] ZIP 具有恰好一份 manifest 声明的 layer source,无额外 compiler source / overrides 文件。 +- [ ] 两个有效区域导出的 ZIP 可被 p5b 导入并完成 Blender/Cesium/preview 构建。 +- [x] 不修改 `compiled.json` 与 v1.1 manifest 的既有渲染语义。 + +## Out of Scope + +- 远程存储、上传、项目历史或多用户协作。 +- 修改道路编辑器交互、几何算法或 manifest 主版本。 + +## Key Decisions + +- ZIP 是单个标准交付物,根目录平铺 package 文件,不包裹 area-id 顶层目录。 +- ZIP 面向宿主消费,只携带已编译渲染/预览数据;编辑源、OSM 与 overrides 留在 road-compiler + 项目中,不泄露为宿主依赖。 diff --git a/.trellis/tasks/08-26-rc-p5a-zip-export/task.json b/.trellis/tasks/08-26-rc-p5a-zip-export/task.json new file mode 100644 index 0000000..f4b58c6 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5a-zip-export/task.json @@ -0,0 +1,26 @@ +{ + "id": "rc-p5a-zip-export", + "name": "rc-p5a-zip-export", + "title": "Web 导出原生道路 ZIP 包", + "description": "让 road-compiler Web/CLI 以 root-flat native-road-package/v1.1 ZIP 导出人工编辑后的道路包。", + "status": "in_progress", + "dev_type": null, + "scope": null, + "package": null, + "priority": "P2", + "creator": "dingkang", + "assignee": "dingkang", + "createdAt": "2026-08-26", + "completedAt": null, + "branch": null, + "base_branch": "experiment/road-compiler-rethink", + "worktree_path": null, + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": "08-26-rc-p5-artifact-consumption", + "relatedFiles": [], + "notes": "", + "meta": {} +} \ No newline at end of file diff --git a/.trellis/tasks/08-26-rc-p5b-zip-import/check.jsonl b/.trellis/tasks/08-26-rc-p5b-zip-import/check.jsonl new file mode 100644 index 0000000..9dd3234 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5b-zip-import/check.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. 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."} diff --git a/.trellis/tasks/08-26-rc-p5b-zip-import/design.md b/.trellis/tasks/08-26-rc-p5b-zip-import/design.md new file mode 100644 index 0000000..1793d0f --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5b-zip-import/design.md @@ -0,0 +1,19 @@ +# P5B ZIP Import Design + +`scripts/lib/native-road-package.js` becomes the single host adapter. It resolves the config-relative +ZIP path, hashes it, validates central-directory entry names and metadata, and extracts only accepted +regular files to `_pipeline/native-road-import//`. It validates the unpacked manifest and +returns an immutable package descriptor: + +```text +{ zipFile, zipRecord, rootDir, manifest, records } +``` + +The descriptor replaces `area.outputs.nativeRoadDir` as native input for Blender, native preview traffic, +diagnostics and stage manifests. The configured ZIP and unpacked cache are inputs, never published area +outputs. Cache invalidation is by ZIP SHA-256; cleanup only deletes importer-owned hash directories. + +The importer rejects any non-root-flat layout, duplicate path, symlink, unsupported compression/error, +path traversal, invalid manifest, area mismatch or declared/published mismatch before Blender starts. +The native compiler CLI dependency and host-owned `nativeRoad` compilation options are removed. Legacy +`osm2streets` remains an explicit separate provider. diff --git a/.trellis/tasks/08-26-rc-p5b-zip-import/implement.jsonl b/.trellis/tasks/08-26-rc-p5b-zip-import/implement.jsonl new file mode 100644 index 0000000..9dd3234 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5b-zip-import/implement.jsonl @@ -0,0 +1 @@ +{"_example": "Fill with {\"file\": \"\", \"reason\": \"\"}. 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."} diff --git a/.trellis/tasks/08-26-rc-p5b-zip-import/implement.md b/.trellis/tasks/08-26-rc-p5b-zip-import/implement.md new file mode 100644 index 0000000..97a8c7f --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5b-zip-import/implement.md @@ -0,0 +1,12 @@ +# P5B Execution Plan + +1. Add config normalization for `nativeRoadPackage`, migrate two supported configs and the template. +2. Add the tested ZIP importer with bounded extraction, root-flat/path/symlink validation, SHA cache and + manifest/area validation. +3. Route Blender, preview traffic, stage manifests and diagnostics through the imported descriptor. +4. Delete compiler CLI/compile production paths and package dependency; replace their tests with ZIP fixture + and negative importer tests. +5. Update docs/specs, run native/legacy unit suites, build two exported packages, then run Blender parity. + +Rollback: restore the old compiler dependency and native compile path in one revert; ZIP exports remain +non-destructive standalone files. diff --git a/.trellis/tasks/08-26-rc-p5b-zip-import/prd.md b/.trellis/tasks/08-26-rc-p5b-zip-import/prd.md new file mode 100644 index 0000000..bcf00f6 --- /dev/null +++ b/.trellis/tasks/08-26-rc-p5b-zip-import/prd.md @@ -0,0 +1,40 @@ +# ZIP 道路包安全导入与纯消费 + +## Goal + +让 osmWorkflow 配置、校验、解压并消费 road-compiler Web 导出的 ZIP 道路包,移除 compiler runtime 耦合。 + +## Requirements + +- 区域配置以 `nativeRoadPackage` 指向 ZIP,路径相对于该区域配置文件;native provider 不再 + 接受 compiler options、overrides 或输出目录作为输入。 +- 宿主在任何 Blender / Cesium 副作用前,验证 ZIP 文件、条目数量/大小、root-flat 文件路径、 + 无重复路径、无符号链接、无绝对路径与 `..` 路径。 +- 仅将已验证的文件解压至 `/_pipeline/native-road-import//`;解压目录是宿主 + 私有缓存,绝不写回 ZIP 或 road-compiler 导出目录。 +- 共享 importer 为 Blender、preview traffic、diagnose/check 和 stage manifest 提供同一包路径与 + 文件记录;不能让下游自行按字符串拼接另一份 native-road 目录。 +- 移除 compiler package、CLI wrapper、compile script、编译器输入配置、以及只覆盖旧调用链的测试。 + +## Acceptance Criteria + +- [ ] 两个有效区域均从 ZIP 完成 `blender,cesium,package,preview`,构建日志没有 compiler CLI。 +- [ ] 缺 ZIP、错误 ZIP、nested root、path traversal、symbolic link、错误 contract、错误 areaId 和 + manifest/source 不匹配均在启动 Blender 前失败。 +- [ ] stage manifest、`diagnose:area` 与 `check:area` 记录 ZIP hash 和已验证的导入目录;ZIP + 修改后会被判 stale。 +- [ ] `package.json`、lockfile、生产脚本与宿主测试不再引用 `@osm-asset/road-compiler`。 +- [ ] Blender digest 对 P3 control 基线一致;legacy `osm2streets` 路径的单元测试不变。 + +## Out of Scope + +- p5a 的 ZIP 生成与 Web 下载实现。 +- ZIP 远程下载、解密、签名验证或制品库管理。 +- 改道路内容、材质或 legacy QGIS 行为。 + +## Key Decisions + +- ZIP 是只读输入;宿主缓存的生命周期和目录 ownership 完全属于 `_pipeline/`。 +- ZIP 解码由明确声明的 Node ZIP 库完成,而不是依赖系统 `unzip`;这使路径/符号链接校验可控并 + 可在单元测试中覆盖。 +- 只有 `native-road-package/v1.1` 可被导入;契约升级必须另开兼容任务。