Add configurable area asset budgets
This commit is contained in:
@@ -54,6 +54,7 @@ cp config/examples/template.json config/areas/my-area.json
|
||||
| `osm2streets` | | 见下 | 透传给 osm2streets 的选项 |
|
||||
| `blender` | | 见下 | Blender 侧选项 |
|
||||
| `compress` | | 见下 | 显式 `compress` 阶段的 GLB 压缩选项 |
|
||||
| `budget` | | 见下 | 区域 GLB 性能与体量预算 |
|
||||
| `outputs` | | 从 `id` 推导 | 输出路径覆盖,逃生舱 |
|
||||
|
||||
**路径一律绝对**。`normalizeAreaConfig` 对每一项都做 `path.resolve`,相对路径会
|
||||
@@ -132,6 +133,23 @@ cp config/examples/template.json config/areas/my-area.json
|
||||
| `effort` | `80` | WebP 编码 effort,范围 `0..100` |
|
||||
| `meshopt` | `false` | 是否追加 `EXT_meshopt_compression`。开启前要单独验证 Cesium 兼容性 |
|
||||
|
||||
### `budget`
|
||||
|
||||
`budget` 是 `diagnose:area`、`check:area` 和 Cesium / compress manifest 共用的 GLB
|
||||
限制。未配置时采用全局默认;用户字段统一用 MB 或整数,归一化后内部使用 bytes / counts:
|
||||
|
||||
| 字段 | 默认 | 说明 |
|
||||
|---|---:|---|
|
||||
| `glbSizeMb` | `25` | GLB 文件总大小(MB) |
|
||||
| `nodes` | `1000` | GLB node 数量 |
|
||||
| `images` | `24` | GLB image 数量 |
|
||||
| `triangles` | `250000` | node 实例化后的 render triangles,不是唯一 mesh 的静态 triangles |
|
||||
| `embeddedImageBytesMb` | `20` | GLB 内嵌图片字节(MB) |
|
||||
| `reason` | `""` | 任一值高于默认时必填,记录区域例外原因 |
|
||||
|
||||
所有数值必须为正数,`nodes` / `images` / `triangles` 必须为正整数。收紧任何默认值不需要
|
||||
`reason`;放宽任一默认值而没有非空 `reason` 会在配置归一化时失败。
|
||||
|
||||
### `outputs`(逃生舱)
|
||||
|
||||
默认全部从 `id` 推导为 `<outputRoot>/<id>/<fileStem>.<ext>`。需要定制时逐项覆盖:
|
||||
@@ -165,7 +183,9 @@ cp config/examples/template.json config/areas/my-area.json
|
||||
3. 若要传给低层脚本,加进 `writeDerivedConfig` 的 `derivedConfig` 对象
|
||||
4. 若是数值,在消费侧加 `Number.isFinite` + 范围校验,**在任何副作用之前**
|
||||
5. 更新 `config/examples/template.json`
|
||||
6. 更新本文档的字段表
|
||||
6. 若字段影响区域质量门,确认 `diagnose:area`、`check:area` 和 stage manifest 共用同一
|
||||
个评估 helper,不能在入口脚本各自比较阈值
|
||||
7. 更新本文档的字段表
|
||||
|
||||
若新字段产出新文件,同时在 `outputs` 里加一行路径推导。
|
||||
|
||||
|
||||
@@ -323,6 +323,7 @@ node scripts/check-area.js [--config config/areas/<area>.json]
|
||||
| Cesium GLB / metadata / preview 缺失或类型错误 | failure |
|
||||
| metadata JSON 损坏 | failure |
|
||||
| GLB size / nodes / images 超保守预算 | failure |
|
||||
| GLB render triangles / embedded image bytes 超保守预算 | failure |
|
||||
| expected stage manifest 缺失、损坏或 stale | failure |
|
||||
| stage manifest warning 内容包含 budget exceeded | failure |
|
||||
| QGIS preview 缺失 | warning,不阻断 |
|
||||
@@ -481,6 +482,7 @@ File records use this shape:
|
||||
- `summary.glb.fileBytes`
|
||||
- `summary.glb.counts`
|
||||
- `summary.glb.extensionsUsed`
|
||||
- `summary.budget`:effective limits、usage 和 violations;warnings 来自同一个预算评估
|
||||
|
||||
`cesium` 会调用 preview 生成函数,但 preview HTML / route / vehicle model 的 freshness
|
||||
所有权属于独立 `preview` manifest。否则单跑 `--stages preview` 会把 Cesium manifest
|
||||
@@ -512,6 +514,7 @@ File records use this shape:
|
||||
- `summary.options`
|
||||
- `summary.compressionRatio`
|
||||
- `summary.savedBytes`
|
||||
- `summary.budget`:压缩 GLB 的 effective limits、usage 和 violations
|
||||
|
||||
Manifest files are written atomically via `*.tmp` then `renameSync`.
|
||||
|
||||
@@ -524,7 +527,7 @@ Manifest files are written atomically via `*.tmp` then `renameSync`.
|
||||
| Manifest output 文件缺失 | 写入时抛错;诊断时报告 stale/missing |
|
||||
| Manifest JSON 无法解析 | 诊断报告 invalid warning |
|
||||
| Manifest 记录的 input / output sha/bytes 与当前文件不同 | 诊断报告 stale warning |
|
||||
| GLB size / nodes / images 超保守预算 | manifest `warnings[]` 记录,诊断继续独立报警 |
|
||||
| GLB size / nodes / images / render triangles / embedded image bytes 超保守预算 | manifest `warnings[]` 记录,诊断继续独立报警 |
|
||||
| `intermediates` 后留有旧 reimport manifest | 成功后删除旧 reimport manifest |
|
||||
| `reimport` 后留有旧 intermediates manifest | 成功后删除旧 intermediates manifest |
|
||||
|
||||
|
||||
1
.trellis/tasks/08-04-add-area-asset-budgets/check.jsonl
Normal file
1
.trellis/tasks/08-04-add-area-asset-budgets/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."}
|
||||
39
.trellis/tasks/08-04-add-area-asset-budgets/design.md
Normal file
39
.trellis/tasks/08-04-add-area-asset-budgets/design.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Area asset budgets design
|
||||
|
||||
## Boundaries
|
||||
|
||||
`scripts/lib/area-config.js` 归一化配置的 `budget`。`scripts/glb-digest.js` 承担 GLB
|
||||
结构统计和 source/image 摘要;`scripts/lib/stage-manifest.js` 承担默认预算、覆盖合并、
|
||||
判定和 warning 文本。`scripts/lib/area-diagnostics.js` 只消费这两个共享事实源,并向
|
||||
diagnose/check 报告结果。
|
||||
|
||||
## Data Flow
|
||||
|
||||
```text
|
||||
config budget + global defaults
|
||||
-> normalizeAreaConfig()
|
||||
GLB JSON -> digest() -> usage + source/image summaries
|
||||
-> evaluateGlbBudget(digest, area.budget)
|
||||
-> stage manifest summary/warnings
|
||||
-> diagnose report / check failures
|
||||
```
|
||||
|
||||
预算字段面向用户使用 `glbSizeMb`,内部归一化为 bytes;其余计数为整数。有效预算对象应始终
|
||||
完整,避免 consumers 自己回退默认值。
|
||||
|
||||
## Attribution
|
||||
|
||||
`digest()` 将每个 node 的 mesh primitives 转为 triangles,并按有限、稳定的名称规则分组
|
||||
(building、foliage、roads、water、fountain、other)。同一 mesh 被多个 node 引用时,source
|
||||
summary 统计实例化后的渲染 triangles;它用于帧渲染复杂度而非 GLB 静态字节。图片条目从
|
||||
`bufferViews[image.bufferView].byteLength` 读取 embedded bytes,并按 bytes 排序。
|
||||
|
||||
## Compatibility
|
||||
|
||||
没有 `budget` 的区域仍使用当前全局 25 MB / 1000 nodes / 24 images,并增加 triangles 和
|
||||
embedded image bytes 的默认阈值。旧 stage manifest 可被读取;新字段只在后续 Cesium / compress
|
||||
阶段写入。现有 `check:area` 保持超预算失败。
|
||||
|
||||
## Rollback
|
||||
|
||||
移除配置归一化、预算评估和扩展摘要即可回退到固定三项预算;旧 manifest 中的附加字段可忽略。
|
||||
@@ -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."}
|
||||
24
.trellis/tasks/08-04-add-area-asset-budgets/implement.md
Normal file
24
.trellis/tasks/08-04-add-area-asset-budgets/implement.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Area asset budgets implementation plan
|
||||
|
||||
1. 扩展 GLB digest 的 triangles、embedded image bytes、image/source summaries,并添加纯 Node
|
||||
fixture 测试。
|
||||
2. 在 area config 归一化 `budget`,实现全局默认、数值范围与放宽例外原因校验;更新模板。
|
||||
3. 在 stage-manifest 提供单一预算评估函数,并接入 Cesium/compress manifest 写入。
|
||||
4. 让 area diagnostics 与质量门复用预算评估,改进 text report。
|
||||
5. 添加临时配置或 mock digest 测试,证明超标阻断、放宽无理由拒绝和收紧允许。
|
||||
6. 更新文档/spec/changelog,运行只针对南台子的验证。
|
||||
|
||||
## Validation
|
||||
|
||||
```bash
|
||||
node --check scripts/glb-digest.js
|
||||
node --check scripts/lib/area-config.js
|
||||
node --check scripts/lib/stage-manifest.js
|
||||
node --check scripts/lib/area-diagnostics.js
|
||||
npm run test:preflight
|
||||
npm run diagnose:area -- --config config/areas/nantaizi-lake-innovation-valley.json
|
||||
npm run check:area -- --config config/areas/nantaizi-lake-innovation-valley.json
|
||||
git diff --check
|
||||
```
|
||||
|
||||
不跑 Blender/QGIS/Cesium,除非现有 manifest 的 schema 验证无法在纯 Node 层覆盖。
|
||||
59
.trellis/tasks/08-04-add-area-asset-budgets/prd.md
Normal file
59
.trellis/tasks/08-04-add-area-asset-budgets/prd.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Add area asset budgets
|
||||
|
||||
## Goal
|
||||
|
||||
让区域 GLB 的性能和体量约束成为可配置、可追踪、可定位的契约。手工改 OSM、资产或场景
|
||||
生成逻辑后,使用者应能知道是否超出预算,以及节点、三角面和贴图主要来自哪一类资产。
|
||||
|
||||
## Confirmed Facts
|
||||
|
||||
- 原有全局保守阈值为 25 MB、1000 nodes、24 images;本任务将它扩展为统一预算评估,并
|
||||
新增 250k render triangles 与 20 MB embedded image bytes。
|
||||
- `scripts/glb-digest.js` 已可无依赖读取 GLB JSON chunk,且提供 node、mesh、material、
|
||||
image、accessor 和 primitive vertex/index 计数。图片可通过 image 的 `bufferView` 计算嵌入
|
||||
字节;三角面可由 primitive index count 计算。
|
||||
- 现有南台子基线为 21.37 MB、933 nodes、117 meshes、18 images,当前未超固定预算。
|
||||
- GLB node/mesh 命名已经包含可用来源线索,如 `Building_*`、`Shapespark_*` 与道路/植被
|
||||
资产名;可用于诊断“渲染实例和三角面”来源,但不能把交织二进制 buffer 的静态文件字节精确
|
||||
分配给单一节点。
|
||||
- `check:area` 已将超预算作为 failure;新增策略必须保持这个默认阻断方向。
|
||||
|
||||
## Requirements
|
||||
|
||||
1. 区域配置新增可选 `budget` 对象,可覆盖全局默认的 GLB size、nodes、images、triangles
|
||||
和 embedded image bytes 限额;未配置时保持现有默认约束,并为新增指标提供保守默认值。
|
||||
2. 任何比全局默认更宽松的区域覆盖必须提供非空 `budget.reason`,使例外可审计;更严格覆盖
|
||||
不需要理由。
|
||||
3. 扩展共享 GLB digest,提供总 triangles、embedded image bytes,以及按稳定 node-name 分类的
|
||||
source summary(节点数、mesh instances、triangles)。不虚构无法可靠归因的“每类文件字节”。
|
||||
4. `diagnose:area` 显示实际值、有效预算、超标项,以及 top source / top embedded images。
|
||||
5. `check:area` 复用相同预算计算,将任何超标项作为 failure;不在入口脚本复制阈值或 GLB
|
||||
解析逻辑。
|
||||
6. Cesium/compress stage manifest 写入其对应 GLB 的 budget、usage 和 budget warnings,供
|
||||
之后检查 stale 或回溯。
|
||||
7. 更新区域配置模板、README、pipeline/config specs 和 changelog;只验证南台子。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] `normalizeAreaConfig()` 对合法 budget 覆盖归一化,对负数、非数值或放宽默认值但缺
|
||||
`reason` 的配置明确报错。
|
||||
- [x] 南台子 diagnostics 显示有效预算、总 triangles、embedded image bytes、source summary
|
||||
与 top images,且当前默认 GLB 仍通过质量门。
|
||||
- [x] 临时配置/fixture 将任一预算压低后,`check:area` 以非零退出并指出实际值和阈值。
|
||||
- [x] stage manifest 包含和当前 GLB digest 对应的 budget/usage/warnings;不重跑 Blender 或
|
||||
Cesium 也可通过独立逻辑测试验证 payload。
|
||||
- [x] 对 GLB digest 的新统计和预算分类有纯 Node 回归测试。
|
||||
- [x] Node 语法检查、相关测试和 `git diff --check` 通过。
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- 不自动压缩、删减或替换资产;预算只报告和阻断。
|
||||
- 不改变默认 GLB、Cesium preview 或 Blender 的视觉结果。
|
||||
- 不尝试对共享/交织 GLB buffer 做不可靠的按节点文件字节归因。
|
||||
- 不验证 `hanyang-block`。
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- 默认预算仍是阻断性质量门;区域只可通过显式配置覆盖。
|
||||
- 放宽全局默认的例外必须在配置中写明原因;收紧预算不需理由。
|
||||
- 归因以准确的节点实例/三角面和嵌入图片字节为准,不把静态 GLB 总字节伪分配给资产类别。
|
||||
26
.trellis/tasks/08-04-add-area-asset-budgets/task.json
Normal file
26
.trellis/tasks/08-04-add-area-asset-budgets/task.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "add-area-asset-budgets",
|
||||
"name": "add-area-asset-budgets",
|
||||
"title": "Add area asset budgets",
|
||||
"description": "Make GLB asset budgets configurable, visible in diagnostics, and enforceable by check:area.",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "dingkang",
|
||||
"assignee": "dingkang",
|
||||
"createdAt": "2026-08-04",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user