release: bump version to 0.58.0
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled

Release 0.58.0 includes the Earth high-precision boundary PMTiles/MVT pipeline, standardized Earth boundary source collectors, China POV boundary configuration templates, and removal of the legacy low-precision GeoJSON fallback. It also adds Earth news target-location queueing/archive support, fixes datasource task status visibility, documents the Earth surface depth-spacing rules that prevent far-zoom z-fighting snow/black blocks, and updates bilingual operations/developer docs.
This commit is contained in:
linkong
2026-05-15 17:40:07 +08:00
parent dd176a6ae6
commit 93eb41a9f7
75 changed files with 5217 additions and 716 deletions

View File

@@ -1,132 +1,67 @@
# Earth High Precision Boundary Tiles Plan
# Earth High Precision Boundary PMTiles Plan
## Status
Planning revised after visual review. The previous hand-authored China claim-line / point-buffer approach is rejected and must not be implemented.
Current implementation:
Implemented separately:
- Three standard source collectors now handle real source ingestion: `earth_admin0_boundaries`, `earth_coastline`, and `earth_claim_lines`.
- Each source collector reads endpoint / headers / auth / `target_schema=earth_boundary_source` from Collector Settings, downloads the configured payload, stores the full artifact under `data/earth-boundary-sources/<collector>/<sha256>.*`, and writes a hash / feature-count / artifact-path record to `CollectedData`.
- The backend `earth_boundary_tiles` item is now a downstream PMTiles builder. It refuses to run until the three source records exist, then skips rebuilds when source / POV policy / build config are unchanged.
- The frontend boundary layer now requires the production `pmtiles-mvt` provider and no longer falls back to legacy low-precision GeoJSON.
- Generated loose boundary data is ignored by Git and is not the production deployment format.
- Production PMTiles builds require external `tippecanoe` and `pmtiles` CLIs; missing tools fail the builder clearly instead of registering fake tile records.
- 地表 hover 三模式已实现。
Still required before claiming true one-to-one high precision:
Still planned:
- 权威 China POV 数据包。
- OSM / coastline 高精度离线构建。
- 版本化静态矢量瓦片输出。
- 前端 bbox/tile/LRU 高精度加载器。
- Replace the repository seed GeoJSON with audited high-precision admin boundary, coastline, and claim-line source packages.
- Run a real geometry preparation step that applies the China POV policy through union / subtract / validity repair before PMTiles creation.
- Build and publish `earth-boundaries-china-pov-v1.pmtiles` plus its manifest.
## Summary
Earth 国界线目标从“明显提升”升级为 **最高精度档按真实地图源一比一还原**
The Earth boundary layer should use one static PMTiles archive containing MVT tiles instead of thousands of loose GeoJSON files. The artifact is POV-specific: `earth-boundaries-china-pov-v1.pmtiles` has China POV baked in during offline source preparation, and the browser never patches political boundaries at runtime.
- 高缩放时不能使用当前 `countries-admin0.min.geojson` 这种低精度简化线。
- 最高 tile zoom 必须忠实保留选定权威矢量源的原始折点,不做视觉平滑,不做人工凭感觉补线。
- 藏南、阿克赛钦等争议陆地直接作为中国国家面的一部分表达hover 只显示普通 `中国 / CHN`,不显示特殊区域名。
- 九段线 / 十段线必须来自官方标准地图口径或经地理配准校核后的权威矢量数据;不能手工目测画线,不能把马来西亚、菲律宾等周边陆地或近岸底盘划入中国面。
Production must serve a single PMTiles artifact through static hosting and HTTP range requests. Missing PMTiles is a hard boundary-layer error, not a silent low-precision fallback.
方案仍采用 **离线构建 + 静态矢量瓦片**。低缩放加载简化 base line高缩放按当前视野 bbox 加载高精度 boundary tiles。第一版不使用 Redis依靠 Nginx 静态服务、浏览器 HTTP cache 和前端 LRU。
## Key Implementation Rules
## Data Source and Policy
- Source inputs must be auditable. OSM admin boundaries, coastline packages, and claim-line endpoints are configured through Collector Settings using the `earth_boundary_source` target schema; `config/earth-boundary-sources.example.json` remains the versioned example template.
- China POV geometry is applied before tiling:
- Zangnan and Aksai Chin are unioned into China and subtracted from India.
- Taiwan/Penghu, Diaoyu Dao and affiliated islands, Chiwei Yu, and South China Sea islands are China hover/country features.
- The South China Sea dashed line is a claim-line layer only; it never consumes Malaysian, Philippine, Vietnamese, or other land polygons.
- Kosovo is not an independent country surface in this profile; Gaza is a Palestine region.
- PMTiles/MVT layer names are fixed for the frontend:
- `boundary_admin0`
- `boundary_disputed_internal`
- `coastline`
- `claim_line`
- The frontend provider is selected from the boundary manifest:
- `tileProvider: "pmtiles-mvt"` reads the PMTiles artifact.
- Any other provider, missing manifest, or missing PMTiles artifact is treated as an error.
- Redis is not part of v1. Static PMTiles plus browser/CDN range caching is the default performance model.
- 基础陆地国界使用 OSM `boundary=administrative` + `admin_level=2`,并补充高精度 coastline避免只靠粗糙国家面导致海岸线缺失。
- China POV 覆盖数据必须独立成包,构建时优先级高于 OSM 原始归属:
- 藏南 union 到中国面,同时从印度面 subtract。
- 阿克赛钦 union 到中国面,同时从相关邻接面 subtract。
- 台湾、澎湖、钓鱼岛及附属岛屿、赤尾屿、东沙、西沙、中沙、南沙等作为中国国家面/岛礁面的一部分进入 hover index。
- 岛礁很小时可有最小可交互面,但 tooltip 仍是 `中国 / CHN`,不展示“某特殊区域归属”标签。
- 九段线 / 十段线是独立 maritime claim line 图层:
- 只渲染 dashed line不参与国家陆地面。
- 不用于吞并周边国家陆地或近岸水域。
- 坐标必须来自官方标准地图、权威矢量数据,或从官方示意图配准后人工复核,不接受手工猜测坐标。
- 必须保留 OSM 数据归因:`© OpenStreetMap contributors, ODbL`
## Cleanup And Documentation
## Precision Requirements
- 最高精度档的验收口径是 **source-faithful**,不是“看起来更细”:
- 对高精度源线,最高 zoom tile 不允许 Douglas-Peucker 简化。
- 坐标量化精度至少保留到 `1e-5` 度级别,构建时不得把经纬度粗暴四舍五入到低精度。
- 球面渲染只允许 densify 长边来贴合地球曲率;不允许 CatmullRom、Bezier 或任何会改变边界走向的平滑。
- 海岸/边界红框类区域必须与源地图折线逐点对齐;若有偏差,只能追溯并替换数据源,不能靠渲染平滑掩盖。
- 低缩放允许简化,但必须有误差预算:
- base line 只服务远景识别。
- 中 zoom tile 可简化到屏幕误差低于 `0.5px`
- 最高 zoom tile 使用无简化或近零误差版本。
## Implementation Plan
### 1. Data pipeline
新增边界构建脚本,使用 `/home/ray/.local/bin/uv` 运行:
1. 读取 OSM PBF 或预处理后的 admin-0 边界 / coastline GeoJSON。
2. 读取 China POV override package。
3. 使用可靠几何库做 union / difference / validity repair禁止手写 polygon overlay。
4. 生成中国国家面时直接合并藏南、阿克赛钦和相关岛礁;从相邻国家面扣除同一区域。
5. 单独读取官方口径九段线 / 十段线矢量,生成 claim-line tiles。
6. 输出:
- 低精度 global base line。
- 无简化 high-precision hover polygon index。
- 高精度静态瓦片:`frontend/public/earth/data/boundaries/v1/{z}/{x}/{y}.geojson`
- 海上断续线瓦片:`frontend/public/earth/data/boundaries/v1/china-claims/{z}/{x}/{y}.geojson`
- manifest记录数据源、覆盖规则版本、构建时间、简化误差和 attribution。
### 2. Tile levels and size budget
- Earth zoom `< 1.6`:只显示 global base line 和低精度 claim line。
- Earth zoom `1.6-2.8`:加载 tile zoom `4-5`
- Earth zoom `2.8-4.0`:加载 tile zoom `6-7`
- Earth zoom `> 4.0`:加载 tile zoom `8-10`,使用最高精度无简化折线。
- 单 tile gzip 目标 `20-80KB`,但最高精度档优先保证几何真实性;若超限,优先提高 tile zoom 或拆 tile而不是简化真实线。
### 3. Frontend loading model
`country-boundaries.js` 拆成 base layer、tile layer 和 China claim layer
- 首屏加载 base line + hover index不阻塞 Earth 初始化。
- 高缩放时根据 camera 可见范围计算经纬 bbox再转换为 Web Mercator tile keys。
- bbox 由屏幕中心、四角和边中点 raycast 得到,并扩张 `10-20%` 作为预取范围。
- 处理反经线,必要时拆成两个 bbox。
- 视野变化请求 debounce `150-250ms`
- 拖拽/惯性旋转中不每帧请求;缩放档或 tile key 集合没变时不刷新。
- 加载当前视野 tile并预取一圈邻接 tile。
- base line 在高精度 tile 到达后降低 opacity避免双线。
### 4. Caching and memory control
- 前端维护 `tileCache``inFlightTiles` 和 LRU 使用顺序。
- tile cache 上限建议 `120-180` 个 tile超过后释放最旧 tile 的 `BufferGeometry`
- Nginx 为 `/earth/data/boundaries/` 设置长缓存:
- `Cache-Control: public, max-age=31536000, immutable`
- gzip 包含 JSON。
- tile URL 包含版本目录,例如 `v1`;数据更新时改版本目录破浏览器缓存。
- 第一版不使用 Redis。只有改成动态裁剪 API、多 POV 同 URL、或压测证明静态服务成为瓶颈时再考虑 Redis。
## Acceptance Criteria
1. 最高 zoom 的海岸线和国界线与选定源地图逐点一致,不再只是“明显提升”。
2. 红框类海岸/边界细节在最高 zoom 下不能出现肉眼可见的低精度折线、直线切边或圆滑失真。
3. 藏南、阿克赛钦 hover 命中普通 `中国 / CHN`;印度或其他邻接国家不再包含这些区域。
4. 钓鱼岛、赤尾屿、南海诸岛代表点 hover 命中普通 `中国 / CHN`
5. 九段线 / 十段线位置与权威来源一致,不压入马来西亚、菲律宾等周边陆地或错误包围近岸底盘。
6. 首屏不加载全球超高精度整包。
7. 高缩放只请求当前视野附近 tile快速旋转不会出现请求风暴。
8. 回到已访问区域命中前端 cache 或浏览器 cache。
9. 国界图层开关、hover 高亮、移动端中心国家高亮、悬停提示三模式保持可用。
- Do not commit generated loose tiles under `frontend/public/earth/data/boundaries/` or source downloads under `data/earth-boundary-sources/`.
- Remove stale generated debug data before production builds; regenerate it only when smoke testing the debug path.
- Keep the high-level plan, backend collector docs, layer style docs, and ops runbook aligned whenever the provider contract changes.
- After implementation changes, provide user-facing operation steps covering source configuration, source collection, artifact build/deploy, page verification, and fallback troubleshooting.
## Verification
- 构建阶段:
- 几何 validity check 全通过。
- China POV 代表点测试全部返回 `CHN`
- 相邻国家代表点不得被 China override 误吞。
- 最高 zoom tile 抽样与源数据做坐标级 diff确认未简化。
- 前端阶段:
- `frontend` 运行 `/home/ray/.bun/bin/bun run build`
- 浏览器 DevTools 验证低缩放无高精度 tile 请求,高缩放请求数量受控,重复视野走 cache。
- 用截图中的红框区域、南海断续线、藏南、钓鱼岛、赤尾屿、南海诸岛做手动视觉验收。
- The PMTiles builder fails as not ready when any of `earth_admin0_boundaries`, `earth_coastline`, or `earth_claim_lines` has not produced a current artifact record.
- The PMTiles builder fails as not ready when source artifacts exist but `tippecanoe` / `pmtiles` are missing.
- Running the PMTiles builder twice returns `unchanged` on the second run when inputs are stable.
- `git add . --dry-run` does not include generated loose boundary tiles or source downloads.
- `/home/ray/.bun/bin/bun run build` passes in `frontend`.
- Manual Earth checks confirm:
- PMTiles range requests are issued only for visible tiles.
- Boundary toggle, hover tooltip, and country highlight still work.
- PMTiles failure reports a boundary-layer error; the frontend must not draw low-precision legacy boundaries.
## Sources and Assumptions
## Assumptions
- 产品默认采用中国标准地图/公开地图合规口径;若后续支持多 POV必须通过版本化数据目录隔离不能让同一 URL 返回不同政治口径。
- 当前仓库没有足够权威和足够精细的 China POV / 九段线矢量源,因此不能直接凭现有低精度 GeoJSON 完成“一比一还原”。
- 实施前必须先引入或生成可审计的高精度源数据包;没有源数据时,只能实现加载框架,不能伪造边界。
- "One-to-one" means source-faithful to the selected audited vector source, not hand-tuned to a screenshot.
- The China POV artifact is static and versioned; no runtime region-based POV switching is planned.
- The removed repository seed file cannot be used as a runtime fallback for country boundaries.

View File

@@ -0,0 +1,118 @@
# Earth High Resolution Basemap Tiles Plan
## Summary
High-precision borders now expose a separate visual problem: the vector coastline and border data are more accurate than the current raster Earth texture. The next step is a high-resolution basemap tile layer that aligns visually with the high-precision coastline instead of replacing the globe with one huge static image.
Do not solve this by committing a larger single world texture. A single 16K/32K raster still wastes memory, loads slowly, and becomes blurry or misaligned when zooming into coastal detail. The target architecture is viewport-based raster tiles with cache control, similar to terrain tiles.
## Goals
- Render a high-resolution Earth imagery basemap that visually matches the high-precision coastline and country boundary layer.
- Load imagery by visible bbox / tile key instead of loading a whole-world giant texture.
- Keep the current global texture only as a low-zoom background, not as the source of truth for coastlines at inspection zoom.
- Let imagery failures degrade only the imagery layer; high-precision borders and hover must continue working.
- Keep generated imagery cache out of Git.
## Data Sources
Candidate sources, in recommended order:
- NASA GIBS / Blue Marble / VIIRS style imagery for permissive global coverage and stable tile service behavior.
- Sentinel-2 cloudless style public imagery if licensing and tile access are acceptable.
- A self-hosted raster pyramid generated offline from audited global imagery if third-party online tile terms are unsuitable.
The selected source must document:
- license / attribution
- max zoom and native resolution
- tile matrix / projection
- cache policy
- whether commercial or public deployment is allowed
## Architecture
```text
global low-zoom texture
→ visible Earth bbox from camera raycast
→ Web Mercator tile keys by zoom
→ raster tile fetch/cache
→ project tile image patches onto Earth surface
→ high-precision coastline / border layer remains above imagery
```
Implementation should mirror the existing terrain tile discipline:
- dedupe in-flight requests
- LRU cache for decoded images / textures
- debounce camera movement
- cancel or ignore stale viewport requests
- cap max tiles per frame / per view
- expose loading/error diagnostics
## Rendering Rules
- The high-resolution imagery layer is visual only. It must not define country hover, coastline, or border geometry.
- The high-precision coastline remains the visual alignment reference.
- The border layer render order stays above the basemap imagery.
- Low zoom may use the current global texture for speed.
- Mid/high zoom overlays imagery tiles only for the visible region plus a small prefetch ring.
- Do not draw decorative gradients or fake coastlines to hide mismatch.
## Frontend Work
- Add a new `basemap-imagery.js` module instead of expanding `country-boundaries.js`.
- Add config in `constants.js`:
- source URL template
- attribution
- min/max zoom
- tile cache limit
- debounce interval
- opacity
- enable/disable setting
- Add Earth settings control:
- `高清底图`: off / auto / on
- default `auto`
- Add debug counters for:
- active tile count
- cached tile count
- failed tile count
- current imagery zoom
## Backend / Ops Work
- If using a third-party tile service directly, document attribution and rate-limit behavior.
- If proxying tiles, add backend cache with request coalescing and timeout limits.
- If self-hosting, add an offline builder that writes ignored tile artifacts under a dedicated data directory.
- Update Nginx static serving if self-hosted raster tiles are used.
## Performance Budget
- Desktop target: keep visible imagery tiles under a configurable cap, initially 64.
- Mobile target: lower max zoom and tile cap by default.
- Decode and upload textures incrementally; avoid blocking Earth startup on high-resolution imagery.
- First Earth paint must still use the existing lightweight global texture.
## Verification
- Compare high-precision coastline against imagery in coastal areas such as southeast China, Taiwan, Hainan, the Korean peninsula, Japan, and island chains in the South China Sea.
- Verify zooming / panning does not create visible tile thrash or long blank periods.
- Verify failed imagery requests do not hide borders or break hover.
- Verify memory stabilizes after repeated pan/zoom due to LRU eviction.
- Run `/home/ray/.bun/bin/bun run build`.
## User Operation Steps
After implementation, the user should be able to:
1. Open Earth settings.
2. Set `高清底图` to `auto` or `on`.
3. Open Earth and zoom into a coastline.
4. See imagery tiles refine under the high-precision boundary/coastline layer.
5. Use diagnostics to confirm which imagery zoom and tile source are active.
## Assumptions
- The existing high-precision vector coastline is the alignment reference.
- This plan improves visual texture fidelity; it does not replace the boundary data pipeline.
- A single larger static Earth texture is rejected as the primary solution.

View File

@@ -37,7 +37,7 @@
## Non-goals
- 不改变桌面端 hover 交互。
-替换 `countries-admin0.min.geojson` 数据源。
-引入旧低精度国界兜底;移动端中心国家能力必须复用生产 PMTiles/MVT 国界源。
- 不新增后端 API。
- 不把国家面填充做成新的 selected country 面状 shader。
- 不为移动端增加永久准星 UI除非后续产品明确需要视觉准星。
@@ -249,4 +249,3 @@ mobileCenterHoverGlowOpacity
3. 性能保护:加入节流、经纬度阈值和禁用态清理。
4. 验证:本地构建通过,移动端 viewport 手动检查通过。
5. 调优:根据截图或真机体验微调阻塞条件和节流阈值。

View File

@@ -0,0 +1,131 @@
# EarthFeed 新闻坐标与异步精修计划
## 目标
EarthFeed 的每条新闻都直接携带巡航可用坐标。初始响应使用新闻所属大区的锚点坐标,后台通过消息队列异步推理更精确的目标地址,完成后用实时补丁替换原新闻坐标,实现前端无感更新。
## 返回结构
`GET /api/v1/news/earth-feed` 返回:
```json
{
"generated_at": "2026-05-15T03:16:43Z",
"focus": {
"lat": null,
"lon": null,
"region": "global",
"label": "全球焦点",
"accent": "#d6e6ff"
},
"sources": [
{
"id": "bbc-world",
"name": "BBC World",
"region": "global",
"homepage_url": "https://www.bbc.com/news/world"
}
],
"items": [
{
"id": "bbc-world:af01519ba7dd",
"title": "Flattery and fanfare as Trump welcomed to China - but thorny issues remain",
"summary": "The leaders of the world's two superpowers were all smiles...",
"url": "https://www.bbc.com/news/articles/cdxpypg9dgeo",
"source": "BBC World",
"feed_name": "BBC World",
"region": "global",
"homepage_url": "https://www.bbc.com/news/world",
"published_at": "2026-05-14T13:02:13Z",
"latitude": 39.9057136,
"longitude": 116.3912972,
"location_label": "北京市, 中国",
"location_source": "headline_location_hint",
"verified": true,
"location_meta": {
"resolution_stage": "headline_location_hint",
"ai_attempted": false,
"ai_status": "skipped_text_hint",
"ai_error": null,
"debug_note": "text hint matched 北京市, 中国",
"target": {
"latitude": 39.9057136,
"longitude": 116.3912972,
"label": "北京市, 中国",
"source": "headline_location_hint",
"confidence": 0.78,
"country": "中国",
"city": "Beijing"
},
"anchor": {
"region": "global",
"label": "全球",
"latitude": 20.0,
"longitude": 0.0
}
},
"is_focus_match": true
}
],
"errors": [],
"stale": false
}
```
字段规则:
- `latitude` / `longitude`:前端巡航唯一读取的坐标。
- `location_label`:当前坐标展示名。
- `location_source``region_anchor``headline_location_hint``headline_country_hint``ai_inferred_target` 等。
- `verified``false` 表示仍是大区锚点;`true` 表示已经由标题规则、国家规则或 AI 得到目标地址。
- `location_meta`调试、诊断、AI 状态、目标地址和锚点详情都放这里,不再展开成 `t_*` 主字段。
## 后台队列
当前使用 Redis Streams
- stream`earth_news:target_location:jobs`
- consumer group`earth_news_target_location`
- result cache`earth_news:target_location:result:{item_id}`
- dedupe key`earth_news:target_location:queued:{item_id}`
请求流程:
1. RSS 拉取并排序。
2. 每条新闻先生成大区锚点坐标,`verified=false`
3. 若 Redis 已有该新闻的精修结果,则合并结果返回。
4. 若没有精修结果,则把新闻 job 入队,接口立即返回。
Worker 流程:
1. 从队列消费新闻 job。
2. 先跑标题/国家规则,再视情况调用 AI。
3. 写入 result cache。
4. 广播 WebSocket 补丁:
```json
{
"type": "data_frame",
"channel": "earth_news",
"timestamp": "2026-05-15T03:17:00Z",
"payload": {
"item_id": "bbc-world:af01519ba7dd",
"patch": {
"latitude": 39.9057136,
"longitude": 116.3912972,
"location_label": "北京市, 中国",
"location_source": "headline_location_hint",
"verified": true,
"location_meta": {}
}
}
}
```
## 可迁移性
业务代码只调用队列接口,不直接依赖 Redis Streams 细节。以后迁移 Kafka 时新增 Kafka adapter保持 job payload、result patch 和 worker 推理逻辑不变。
## 前端规则
新闻面板和巡航都只读取新闻项内的 `latitude` / `longitude`。实时补丁到达后按 `item_id` 合并到现有 `payload.items`,重新渲染并触发 `earth:news-payload-updated`,巡航下一轮自然使用精修坐标。