chore: sync production runtime and docs

This commit is contained in:
2026-04-25 15:02:40 +08:00
parent cb518b431f
commit 1e44101eb2
50 changed files with 8575 additions and 2177 deletions
+151
View File
@@ -0,0 +1,151 @@
# 当前状态快照
更新时间:2026-04-25
## 1. 项目形态
当前项目已经形成以下稳定形态:
- 主界面仍然是地图工作区。
- 顶级生产入口已经统一为“生产管理”。
- “生产管理”同时包含:
- D-InSAR 运行
- 时序 InSAR 运行
- D-InSAR 产物
- 时序 InSAR 产物
- 时序入口的前端显示名已经统一为“时序 InSAR”。
- 当前时序链路默认接入的是 SBAS 实现,而不是传统 PS-InSAR 单一路径。
## 2. 当前生产引擎
### D-InSAR
- `sarscape`
当前可用,已有 19 个发布产品进入 catalog。
- `isce2`
已完成托管式接入,运行在 WSL 共享运行时中。
- `gamma / pyint`
运行时接口与目录已经预留,后续可继续落生产设计。
### 时序 InSAR
- 当前产品名称统一为“时序 InSAR”。
- 当前默认执行路径是 SBAS。
- 后续可在该顶级入口下继续扩展 `psinsar``sbas-insar` 等类型。
## 3. 结果目录现状
当前结果目录已经统一收口到 `D:\production_results`
```text
D:\production_results
├─ dinsar
├─ timeseries
└─ _quarantine
```
当前健康检查中的目录状态:
- `D:\production_results\dinsar`
存在,catalog 正常。
- `D:\production_results\timeseries`
存在,catalog 正常。
- `D:\production_results\_quarantine`
已作为统一隔离根目录纳入配置模型。
说明:
- `backend\result_products` 旧目录已经不是当前文件系统事实来源。
- 数据库 `result_products` 表仍然保留,是发布产品登记表,不要与旧目录混淆。
## 4. 当前启动自维护链路
后端启动时会依次执行:
1. 数据库自维护
2. SQLAlchemy 会话初始化
3. 根目录登记同步
4. manifest inventory 同步
5. D-InSAR catalog 自举
6. 时序 InSAR catalog 自举
7. pairing cache 状态自举
8. 启动健康检查
这说明当前系统已经不是“纯手工维护目录 + 手工修库”的模式,而是有稳定的启动自维护链路。
## 5. 2026-04-25 现场健康摘要
本次审计现场读取到的核心状态如下:
- 数据库:
- `ok = true`
- `schema_ok = true`
- `postgis_ok = true`
- `required_table_count = 42`
- D-InSAR catalog
- `storage_root = D:\production_results\dinsar`
- `manifest_count = 19`
- `db_count = 19`
- `needs_rebuild = false`
- 时序 InSAR catalog
- `storage_root = D:\production_results\timeseries`
- `manifest_count = 0`
- `db_count = 0`
- `needs_rebuild = false`
- 产品包:
- `total_count = 19`
- `canonical_schema = insar.product-package/v1`
- 缺失 manifest / publish dir / processor / runtime / native output 均为 0
- WSL 共享运行时:
- `shared_distro = Ubuntu-24.04`
- `shared_conda_env_name = insar_wsl_v1`
- `shared_python_path = /home/administrator/miniconda3/envs/insar_wsl_v1/bin/python`
- `required_runtime_count = 2`
- `healthy_runtime_count = 2`
- 配对系统:
- `status = READY`
- `scene_count = 1500`
- `pair_count = 91737`
- `dirty_scene_count = 0`
## 6. 现场源目录状态
当前健康检查确认以下源目录可访问:
- `D:\LuTan1_Image_Pool`
- `D:\LT1_data_lsarorbit`
- `D:\DInSARResult`
即当前 `source_roots` 为全绿状态,没有不可访问目录。
## 7. 当前数据库设计是否匹配
结论:
- 当前 ORM 与现场数据库匹配。
- 当前 catalog、结果包、WSL 运行时和 pairing 状态与现有架构一致。
- 当前数据库自维护机制适合现在这批“新增字段、统一结果目录、增加运行时登记”的改动。
边界:
- 它仍然只是“增量补齐型”自维护,不是全功能 migration 框架。
- 如果后续要做字段改名、类型调整、约束重构,仍然需要显式迁移方案。
## 8. 当前最需要保持一致的事实
以下几件事已经是当前系统事实,后续文档和代码都应围绕它们展开:
- 顶级生产入口是“生产管理”,不是“生产规划”里的临时子入口。
- 时序 InSAR 是顶级产品族,当前默认接入 SBAS。
- 结果发布根目录是 `RESULT_PUBLISH_ROOT`,不是历史散落目录。
- WSL 运行时是共享模型,当前共享环境为 `insar_wsl_v1`
- 数据库自维护默认保守,不自动做破坏性重建。
@@ -0,0 +1,203 @@
# 数据库自维护审计
审计日期:2026-04-25
## 1. 审计目标
本次审计关注两件事:
1. 当前数据库自维护机制,是否仍然符合现在的系统设计。
2. 当前现场数据库,是否已经与现有 ORM / catalog / 运行时设计对齐。
## 2. 当前自维护机制实际做什么
代码入口位于 `backend/app/db_maintenance.py`,系统启动时由 `backend/app/main.py` 调用。
当前自维护能力包括:
- 自动创建 `postgis` 扩展
- 自动创建缺失表
- 自动补齐缺失列
- 自动执行 `backend/migrations/001``006`
- 自动引导管理员账号
- 自动灌入灾害点数据
当前启动链路中的相关步骤:
1. `ensure_database_ready(...)`
2. `database.init_db()`
3. 根目录登记同步
4. manifest inventory 同步
5. D-InSAR / 时序 catalog 自举
6. pairing state 自举
7. 健康检查
## 3. 当前机制不做什么
当前实现不是完整迁移框架,它不会自动处理:
- 字段改名
- 字段类型变更
- 可空性从宽到严
- 索引 / 约束漂移修补
- 旧字段 / 旧表删除
破坏性重建只有在以下两个开关同时为 `true` 时才允许:
```env
DB_SCHEMA_RESET_ON_MISMATCH=true
DB_SCHEMA_RESET_CONFIRM=true
```
默认情况下这是关闭的,符合当前内网生产环境“保守自维护”的要求。
## 4. 本次现场检查方法
本次检查直接用当前项目代码读取现场数据库并执行:
- `inspect_database_structure(...)`
- `ensure_database_ready(settings.DATABASE_URL, bootstrap_admin=False, seed_hazard=False)`
- `get_health_status(include_external=False, include_details=True, refresh=True)`
使用的是项目当前 `.env` 中配置的 Python 解释器和数据库连接。
## 5. 现场检查结果
### 5.1 schema 结构检查
结果:
- `mismatch = false`
- `reason_count = 0`
- `required_table_count = 42`
- `missing_tables = []`
- `extra_tables = []`
- `missing_columns = {}`
- `type_mismatches = []`
- `nullable_mismatches = []`
结论:
- 现场数据库结构与当前 ORM 一致。
- 当前新增的结果包、运行时、catalog 相关字段已经在数据库中落稳。
### 5.2 自维护执行结果
结果:
- `schema_reset = false`
- `mismatch_detected = false`
- `added_columns = []`
- `bootstrap_initialized = false`
启动时仍会执行以下 SQL 文件:
- `001_st_intersection_agg.sql`
- `002_spatial_functions.sql`
- `003_pairing_enhancement.sql`
- `004_pairing_refactor.sql`
- `005_pairing_task_trace.sql`
- `006_result_pairing_trace.sql`
结论:
- 当前数据库已处于“无需修补”的稳定状态。
- 启动自维护仍会重复执行迁移 SQL,因此这些 SQL 文件必须继续保持幂等。
### 5.3 健康检查结果
结果摘要:
- `health.ok = true`
- `database.ok = true`
- `database.schema_ok = true`
- `database.postgis_ok = true`
- `dinsar_result_catalog.ok = true`
- `timeseries_result_catalog.ok = true`
- `dinsar_bridge.ok = true`
- `source_roots.ok = true`
- `product_packages.ok = true`
- `wsl_runtime.ok = true`
- `pairing_system.ok = true`
关键现场值:
- D-InSAR catalog
- `storage_root = D:\production_results\dinsar`
- `manifest_count = 19`
- `db_count = 19`
- 时序 InSAR catalog
- `storage_root = D:\production_results\timeseries`
- `manifest_count = 0`
- `db_count = 0`
- 产品包:
- `total_count = 19`
- `canonical_schema = insar.product-package/v1`
- 所有缺失项计数均为 0
- WSL 共享运行时:
- `shared_distro = Ubuntu-24.04`
- `shared_conda_env_name = insar_wsl_v1`
- `shared_python_path = /home/administrator/miniconda3/envs/insar_wsl_v1/bin/python`
- `required_runtime_count = 2`
- `healthy_runtime_count = 2`
## 6. 结论
结论很明确:
- 当前数据库自维护机制与当前系统状态相符。
- 对于当前这轮改造引入的新增字段、catalog、结果包、WSL runtime 信息,它是足够的。
- 当前现场数据库已经对齐当前 ORM 和结果目录设计。
这意味着:
- 现在可以继续在当前 schema 基础上推进 D-InSAR / 时序 InSAR 生产。
- 不需要为了“数据库跟不上代码”而先清空库或强制重建。
## 7. 残余风险
虽然当前是对齐的,但仍有三个明确边界:
### 7.1 它不是 migration framework
后续如果要做以下改动,不能只靠当前自维护:
- 重命名字段
- 修改字段类型
- 增加更严格的非空约束
- 重建索引或唯一约束
- 删除旧结构
### 7.2 SQL 文件必须幂等
因为启动时会重复执行 `001``006`,任何新增 SQL 文件也必须遵守同样原则。
### 7.3 健康面板已成为设计约束的一部分
当前运维自检不只是“看数据库能不能连”,而是在验证:
- catalog 是否正常
- product package 是否完整
- WSL 运行时是否齐全
- pairing trace 是否一致
因此后续只要改目录模型、结果包模型、运行时模型,就必须同步维护健康检查逻辑。
## 8. 建议
当前建议如下:
1. 保持 `DB_SCHEMA_RESET_ON_MISMATCH=false``DB_SCHEMA_RESET_CONFIRM=false`
2. 后续涉及 schema 破坏性调整时,单独编写受控迁移,不要指望启动自维护自动兜底。
3. 新增数据库字段时,优先采用“可空 + 向后兼容 + 健康面板补校验”的方式推进。
4. 每次结果目录、运行时 registry、catalog 设计变动后,都重新跑一次:
- schema 检查
- `ensure_database_ready(...)`
- `GET /api/health`
## 9. 审计结语
截至 2026-04-25,数据库自维护机制与当前系统状态是匹配的,且现场数据库处于健康状态。当前更大的风险已经不在“数据库结构漂移”,而在后续若继续做结果模型或运行时模型重构时,是否同步维护 catalog、健康检查和文档。
+252 -913
View File
File diff suppressed because it is too large Load Diff
+63 -92
View File
@@ -1,117 +1,88 @@
# 当前文档总览
# 文档索引
这是 `docs/` 目录的统一入口文档
本索引用来区分“当前有效文档”和“历史参考文档”
从现在开始,`docs/` 根目录只保留“当前仍在使用”的文档;历史过程材料、已完成实施记录、被新文档覆盖的旧方案,统一放入 `docs/archive/`
原则:
## 1. 当前有效文档
- 以本页列为“当前有效”的文档,才作为现网架构、部署和运维的事实依据。
- 没有列入“当前有效”区域的文档,默认只作为设计过程记录或历史参考。
- 旧文档即使仍保留在 `docs/` 根目录,也不代表它仍然描述当前系统。
### 核心使用
## 1. 当前有效
- **[README.md](../README.md)**
系统主文档。优先阅读,包含整体功能、架构、快速开始和主要配置说明
- **[DEPLOYMENT.md](DEPLOYMENT.md)**
部署与运维细节文档。适合正式部署、数据库初始化、服务启动和环境核对时使用。
- **[PROJ_CONFIGURATION.md](PROJ_CONFIGURATION.md)**
PROJ/GDAL 相关专项配置说明。只有在坐标转换或 PROJ 冲突时才需要单独查看。
- [../README.md](../README.md)
项目总览、当前架构和启动入口
### 当前安全状态
- [CURRENT_STATUS_20260425.md](CURRENT_STATUS_20260425.md)
2026-04-25 的项目状态快照,包含结果目录、运行时、健康检查摘要。
- **[SECURITY_AUDIT_2026-03-12.md](SECURITY_AUDIT_2026-03-12.md)**
当前有效的安全审计结论。已经把“开发机阶段可接受暴露”和“上线前必须修复的问题”分开说明,后续安全判断以这份为准
- [DEPLOYMENT.md](DEPLOYMENT.md)
当前 Windows + PostgreSQL + WSL2 部署模型、环境变量和启动链路
### 仍在推进的设计与任务
- [DATABASE_SELF_MAINTENANCE_AUDIT_20260425.md](DATABASE_SELF_MAINTENANCE_AUDIT_20260425.md)
当前数据库自维护机制与现场数据库一致性审计结果。
- **[DINSAR_ENHANCEMENT_TASKS.md](DINSAR_ENHANCEMENT_TASKS.md)**
D-InSAR 多引擎生产增强与结果管理增强的总 Task 文档。覆盖前端架构、ENVI 六步链路、ISCE2 的 WSL 校验、运维自检与结果治理
- **[PAIRING_ENHANCEMENT_DESIGN.md](PAIRING_ENHANCEMENT_DESIGN.md)**
配对能力增强设计。属于未完全落地的专项设计文档。
- **[GAMMA_WSL2_INTEGRATION_PLAN.md](GAMMA_WSL2_INTEGRATION_PLAN.md)**
GAMMA + WSL2 双引擎方案。属于后续扩展规划,不是当前默认运行链路。
- **[PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md](PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md)**
PyINT 生产引擎与 Gamma 精配对总体设计。明确现有多引擎架构下的接入边界、配置管理、数据库策略、运维自检扩展与前端入口分布。
- **[PYINT_GAMMA_IMPLEMENTATION_TODO_20260418.md](PYINT_GAMMA_IMPLEMENTATION_TODO_20260418.md)**
PyINT 生产引擎与 Gamma 精配对实施清单。按阶段拆分后端、前端、接口、运维与可选数据库任务,作为后续落地执行顺序。
- **[PYINT_INPUT_ASSET_ADAPTATION_DESIGN_20260419.md](PYINT_INPUT_ASSET_ADAPTATION_DESIGN_20260419.md)**
PyINT 输入资产适配设计。聚焦 `Task_*` 路径如何映射到 PyINT 工作区,以及 DEM、LT-1 精密轨道、运维自检和前端入口应如何纳入系统托管治理。
- **[PYINT_LT1_COREG_ORBIT_HYPOTHESIS_EXPERIMENT_20260420.md](PYINT_LT1_COREG_ORBIT_HYPOTHESIS_EXPERIMENT_20260420.md)**
LT-1 在 PyINT/Gamma 中 `coreg` 失败的轨道假设验证实验设计。固定输入和 DEM,只改变 `.slc.par` 的 state vector 处理方式,对照验证问题是否集中在导入后的轨道几何链条。
- **[PYINT_LT1_DEM_GEOMETRY_CHAIN_EXPERIMENT_20260420.md](PYINT_LT1_DEM_GEOMETRY_CHAIN_EXPERIMENT_20260420.md)**
LT-1 在 PyINT/Gamma 中 `init_offsetm` 失败的 DEM 几何链定位实验。聚焦 `HGTSIM / lt0 / mli0 / Samp` 的中间产物,区分 DEM 本体问题、DEM 几何映射链问题和中心 patch 选取问题。
- **[WSL2_ISCE2_MINTPY_SBAS_INTEGRATION_PLAN_20260412.md](WSL2_ISCE2_MINTPY_SBAS_INTEGRATION_PLAN_20260412.md)**
基于本机 `Ubuntu-24.04` WSL2、`isce2` / `mintpy` / `isce2_mintpy_v1` 实际环境核对后的 SBAS 集成落地方案,明确推荐运行时、workflow 补全顺序和正式产品边界。
- **[ISCE2_SBAS_TIMESERIES_DESIGN.md](ISCE2_SBAS_TIMESERIES_DESIGN.md)**
ISCE2 框架下 SBAS / 时序生产设计稿,说明如何从现有 `PS stack batch` 扩展到 `workflow + psinsar catalog` 的正式生产链路。
- **[SBAS_PROGRESS_STATUS_20260406.md](SBAS_PROGRESS_STATUS_20260406.md)**
SBAS 系统改造当前落地状态。优先查看这份文档以了解“已经做到哪一步、验证做到哪一步、下一步该补什么”。
- **[SBAS_SYSTEM_INTEGRATION_AUDIT_20260406.md](SBAS_SYSTEM_INTEGRATION_AUDIT_20260406.md)**
对现有系统接入 SBAS 的审计结果,聚焦现状缺口与最小可行接入点。
- **[SBAS_SYSTEM_EMBEDDING_DESIGN_20260406.md](SBAS_SYSTEM_EMBEDDING_DESIGN_20260406.md)**
SBAS 嵌入现有系统的详细设计稿,覆盖运行记录、作业编排、结果注册与前端页面边界。
- **[SBAS_TASK_PATH_MODE_EVALUATION_20260406.md](SBAS_TASK_PATH_MODE_EVALUATION_20260406.md)**
评估是否沿用现有 D-InSAR `task 路径 -> 生产` 模式,以及 SBAS 为什么必须增加 `prepare` 阶段。
- **[SBAS_SYSTEM_CHANGE_RISK_ASSESSMENT_20260406.md](SBAS_SYSTEM_CHANGE_RISK_ASSESSMENT_20260406.md)**
SBAS 系统改造风险评估,重点约束“新增不伤旧链”。
- **[SBAS_RESULT_MANAGEMENT_AND_DISPLAY_SPEC_20260406.md](SBAS_RESULT_MANAGEMENT_AND_DISPLAY_SPEC_20260406.md)**
SBAS 结果管理、编目和展示约定,明确发布级 bundle 与系统结果目录的关系。
- **[SBAS_FRONTEND_UX_SPEC_20260406.md](SBAS_FRONTEND_UX_SPEC_20260406.md)**
SBAS 生产页、结果页与分析页的前端交互设计。
- **[SBAS_IMPLEMENTATION_TODO_20260406.md](SBAS_IMPLEMENTATION_TODO_20260406.md)**
SBAS 系统改造任务清单,适合作为后续 Phase 2 / Phase 3 推进的执行列表。
- [PROJ_CONFIGURATION.md](PROJ_CONFIGURATION.md)
PROJ / GDAL 相关专项配置说明
## 2. 已归档文档
## 2. 当前执行中的核心设计
以下文档已移入 `docs/archive/`,原因通常是“历史记录”“已完成实施”或“被后续结论覆盖”。
- [PRODUCTION_RESULTS_MULTI_ENGINE_DESIGN_20260423.md](PRODUCTION_RESULTS_MULTI_ENGINE_DESIGN_20260423.md)
多引擎结果目录、发布结构和 catalog 治理设计。
### 本轮归档
- [WSL_RUNTIME_REFACTOR_DESIGN_20260422.md](WSL_RUNTIME_REFACTOR_DESIGN_20260422.md)
WSL 共享运行时和 Broker 设计。
- `SECURITY_AUDIT_2026-03-04.md`
- `SECURITY_AUDIT_ANALYSIS_2026-03-04.md`
- `SECURITY_FIX_PLAN.md`
- `SECURITY_FIX_PROGRESS.md`
- `SECURITY_FIX_CHECKLIST.md`
- `SECURITY_FIX_STAGE1_SUMMARY.md`
- `SECURITY_OVERVIEW.md`
- `HARDCODE_AUDIT_2026-03-05.md`
- `LOG_MANAGEMENT_IMPLEMENTATION_2026-03-05.md`
- [ISCE2_MANAGED_DINSAR_IMPLEMENTATION_20260424.md](ISCE2_MANAGED_DINSAR_IMPLEMENTATION_20260424.md)
ISCE2 托管式 D-InSAR 落地说明。
### 既有归档
- [ISCE2_PRODUCTION_RELIABILITY_HARDENING_DESIGN_20260424.md](ISCE2_PRODUCTION_RELIABILITY_HARDENING_DESIGN_20260424.md)
ISCE2 生产链路稳定性修补与约束。
`docs/archive/` 中原有的旧设计、旧 TODO、阶段性分析和历史修复记录继续保留,仅作历史参考,不再视为当前执行依据。
- [DINSAR_ENHANCEMENT_TASKS.md](DINSAR_ENHANCEMENT_TASKS.md)
D-InSAR 生产相关任务清单。
## 3. 建议阅读顺序
## 3. 时序 InSAR / SBAS
### 新接手项目
- [ISCE2_SBAS_TIMESERIES_DESIGN.md](ISCE2_SBAS_TIMESERIES_DESIGN.md)
- [ISCE2_SBAS_PRODUCT_SPEC.md](ISCE2_SBAS_PRODUCT_SPEC.md)
1. 先读 [README.md](../README.md)
2. 再读 [DEPLOYMENT.md](DEPLOYMENT.md)
3. 若涉及上线前风险,再读 [SECURITY_AUDIT_2026-03-12.md](SECURITY_AUDIT_2026-03-12.md)
说明:
### 正式部署
- 当前前端顶级显示名已经统一为“时序 InSAR”。
- 当前默认接入仍然是 SBAS 路径,因此这两份文档仍然有效。
- `SBAS_*` 命名的一批旧文档大多是阶段性设计材料,不再作为总事实来源。
1. [README.md](../README.md)
2. [DEPLOYMENT.md](DEPLOYMENT.md)
3. [PROJ_CONFIGURATION.md](PROJ_CONFIGURATION.md)(仅在需要时)
## 4. 配对与前端导航
### 后续功能规划
- [PAIRING_ENHANCEMENT_DESIGN.md](PAIRING_ENHANCEMENT_DESIGN.md)
- [PAIRING_SYSTEM_REFACTOR_PLAN_20260413.md](PAIRING_SYSTEM_REFACTOR_PLAN_20260413.md)
- [FRONTEND_NAVIGATION_ARCHITECTURE.md](FRONTEND_NAVIGATION_ARCHITECTURE.md)
1. [DINSAR_ENHANCEMENT_TASKS.md](DINSAR_ENHANCEMENT_TASKS.md)
2. [PAIRING_ENHANCEMENT_DESIGN.md](PAIRING_ENHANCEMENT_DESIGN.md)
3. [PAIRING_SYSTEM_REFACTOR_PLAN_20260413.md](PAIRING_SYSTEM_REFACTOR_PLAN_20260413.md)
4. [ISCE2_SBAS_TIMESERIES_DESIGN.md](ISCE2_SBAS_TIMESERIES_DESIGN.md)
5. [WSL2_ISCE2_MINTPY_SBAS_INTEGRATION_PLAN_20260412.md](WSL2_ISCE2_MINTPY_SBAS_INTEGRATION_PLAN_20260412.md)
6. [GAMMA_WSL2_INTEGRATION_PLAN.md](GAMMA_WSL2_INTEGRATION_PLAN.md)
7. [PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md](PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md)
8. [PYINT_GAMMA_IMPLEMENTATION_TODO_20260418.md](PYINT_GAMMA_IMPLEMENTATION_TODO_20260418.md)
9. [PYINT_INPUT_ASSET_ADAPTATION_DESIGN_20260419.md](PYINT_INPUT_ASSET_ADAPTATION_DESIGN_20260419.md)
10. [PYINT_LT1_COREG_ORBIT_HYPOTHESIS_EXPERIMENT_20260420.md](PYINT_LT1_COREG_ORBIT_HYPOTHESIS_EXPERIMENT_20260420.md)
11. [PYINT_LT1_DEM_GEOMETRY_CHAIN_EXPERIMENT_20260420.md](PYINT_LT1_DEM_GEOMETRY_CHAIN_EXPERIMENT_20260420.md)
## 5. Gamma / PyINT / WSL 预留
## 4. 后续维护规则
- [GAMMA_WSL2_INTEGRATION_PLAN.md](GAMMA_WSL2_INTEGRATION_PLAN.md)
- [PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md](PYINT_GAMMA_INTEGRATION_DESIGN_20260418.md)
- [PYINT_INPUT_ASSET_ADAPTATION_DESIGN_20260419.md](PYINT_INPUT_ASSET_ADAPTATION_DESIGN_20260419.md)
- [PYINT_GAMMA_AB_FINDINGS_20260420.md](PYINT_GAMMA_AB_FINDINGS_20260420.md)
- `docs/` 根目录只放当前有效文档。
- 已完成实施总结、阶段性修复过程、旧审计分析、被覆盖方案,统一放入 `docs/archive/`
- 新增文档前,优先判断是否可以并入现有文档,避免再次堆出多份并行说明。
- 如果某份文档只记录一次任务过程,而不是长期参考资料,不应继续留在根目录。
说明:
**最后整理**2026-03-13
- 这部分主要作为 Gamma / PyINT 接入的预留设计和实验记录。
- 真正的当前运行时事实,以 `WSL_RUNTIME_REFACTOR_DESIGN_20260422.md``.env` 和健康面板为准。
## 6. 安全与审计
- [SECURITY_AUDIT_2026-03-12.md](SECURITY_AUDIT_2026-03-12.md)
## 7. 历史参考
以下材料默认视为历史设计记录或过程文档:
- `docs/archive/`
- `SBAS_*`
- `WSL2_ISCE2_MINTPY_SBAS_INTEGRATION_PLAN_20260412.md`
- `项目汇报.md`
- 各类 `*_EXPERIMENT_*` / `*_PROGRESS_*` / `*_TODO_*`
最后更新:2026-04-25
@@ -0,0 +1,142 @@
# ISCE2 Managed D-InSAR Implementation 2026-04-24
## Scope
This document records the backend implementation that moves ISCE2 D-InSAR onto the same managed production lifecycle already used by ENVI.
The goal of this round is not to redesign the scientific core of ISCE2. The goal is to make ISCE2 production operationally healthy:
- submitted from the same production-management entry
- tracked by the same run / item / execution tables
- published into the same managed result tree
- scanned by the same catalog rebuild path
- compatible with database self-maintenance and health checks
## Implemented changes
### 1. Submission path
`/dinsar-production/run` now sends both `sarscape` and `isce2` through `dinsar_production_service.create_run(...)`.
This means ISCE2 no longer bypasses production management when it is launched from the normal UI entry.
### 2. Production run lifecycle
`dinsar_production_service.create_run(...)` now supports:
- `sarscape`
- `isce2`
For ISCE2 it creates:
- `dinsar_production_runs`
- `dinsar_production_run_items`
- `dinsar_production_executions`
- workflow steps with job type `ISCE2_RUN`
No schema migration was required for this round.
### 3. Managed ISCE2 controller
`JOB_TYPE_ISCE2_RUN` now has two modes:
- legacy queued mode: no `production_run_id`, keep the old shared queued handler
- managed production mode: `production_run_id` present, use the new WSL production controller
The managed controller is responsible for:
- creating one execution row per selected task
- forcing a managed run directory for each task
- writing `execution_manifest.json`
- writing `current/isce2__<profile>.json`
- publishing successful run directories
- rebuilding the result catalog after publish
### 4. Managed result layout
Each successful ISCE2 task now lands in the same managed D-InSAR tree as ENVI:
```text
D:\production_results\dinsar\<pair_key>\
current\
isce2__lt1_stripmap.json
runs\
<run_key>\
.dinsar_run.json
execution_manifest.json
manifest.json
native\
workflow\
...
export\
<task>_disp.tif
<task>_coh.tif
assets\
disp\
disp.tif
coh\
coh.tif
preview\
thumb.webp
```
Rules:
- `native/` keeps the raw ISCE2 work and export outputs
- `assets/` holds the standardized files consumed by the system
- `manifest.json` is still written by `publish_from_sources(...)`
- `result_products` rows are still created by `rebuild_catalog(...)`
### 5. ISCE2 layout normalization
`backend/app/services/dinsar_result_layout_service.py` now includes `normalize_isce2_run_layout(...)`.
Behavior:
- copy raw ISCE2 `*_disp.tif` into `assets/disp/disp.tif`
- copy raw ISCE2 `*_coh.tif` into `assets/coh/coh.tif`
- keep the raw files under `native/export`
- rewrite run metadata / execution manifest / current pointer / package manifest when those files already exist
## Completion semantics
`rerun_mode=unfinished_only` for ISCE2 now checks the managed pointer:
```text
<DINSAR_PRODUCT_DIR>\<pair_key>\current\isce2__<profile>.json
```
This is intentional.
Legacy raw ISCE2 folders without a managed current pointer are no longer treated as a completed production result. That keeps skip logic aligned with production management rather than with stray historical outputs.
## Database and self-check compatibility
This implementation keeps the existing operational contract:
- no new tables
- no destructive migration
- no change to `result_products` / `result_assets` / `result_issues` schema
- no change to `dinsar_production_runs` schema
Operational compatibility points:
- catalog state is still rooted at `settings.DINSAR_PRODUCT_DIR`
- health checks still use the same catalog-state and manifest-tree logic
- database self-maintenance still works because manifests remain canonical and catalog rebuild remains the only registration path
## Validation completed in this round
- syntax compilation in memory for the edited Python modules
- direct module import validation for:
- `backend.app.dinsar_engines.isce2_engine`
- `backend.app.services.dinsar_result_layout_service`
- `backend.app.services.dinsar_production_service`
- `backend.app.routers.dinsar_production`
- `backend.app.services.job_handlers`
## Remaining work
- add hard cancellation for an in-flight WSL subprocess
- add Gamma D-InSAR on top of the same managed controller contract
- decide whether `lt1_stripmap` should stay as the public profile code or be renamed in a later migration round
@@ -0,0 +1,445 @@
# ISCE2 生产可靠性加固设计 2026-04-24
## 1. 背景
当前 ISCE2 生产链路已经具备:
- 统一的 WSL runtime 入口
- 共享 conda 环境 `insar_wsl_v1`
- 结果发布到 `D:\production_results`
- 统一 catalog / 自检 / 运维面板
但这条链路仍存在一个核心问题:
系统现在更像是“子进程执行器”,还不是“结果可靠性交付器”。
也就是说,当前成功判定主要依赖:
- WSL runner 返回码是否为 `0`
- 输出目录是否存在
- 自动发布阶段是否“尝试过”
这会导致几类假成功:
1. ISCE2 子进程返回 `0`,但没有形成可发布的主产物,任务仍显示完成。
2. 历史运行只留下目录和 `.dinsar_run.json`,但主产物已损坏或缺失,“只跑未完成” 仍会跳过。
3. 运维自检用的是一套路径规则,真实运行用的是另一套路径规则,面板和实际行为可能不一致。
本设计的目标不是重写 ISCE2 算法链,而是把 ISCE2 生产从“命令执行成功”收紧到“结果可验收、可发布、可重跑、可运维”。
## 2. 本轮范围
本轮只做可靠性加固,不做算法重写。
### 纳入本轮
- ISCE2 原生产结果的验收契约
- “只跑未完成” 判定收紧
- 自动发布阶段收紧
- 健康检查与真实运行入口对齐
- 文档、自检、日志字段同步
### 暂不纳入本轮
- stripmap/SNAPHU/PICKLE 恢复链的算法级改写
- 与 ENVI/IDL 流水线逐步逐项数值对比
- Gamma 生产实现细节
- MintPy / 时序生产链的算法可靠性评估
## 3. 当前问题拆解
### 3.1 成功判定过宽
当前 `backend/app/dinsar_engines/isce2_engine.py` 中,单对任务成功主要由 `rc == 0` 决定。
现状后果:
- 只要 runner 没报错,就写入 `.dinsar_run.json`
- 只要 `output_dir` 被加入 `output_dirs`,后续任务层就进入自动发布
- 自动发布即使 `processed == 0`,任务最终仍可标记为 `COMPLETED`
这不符合“生产完成”的系统定义。
### 3.2 未完成重跑判定过宽
当前 `_has_completed_task_result()` 只看:
- 历史 `run_dir`
- `.dinsar_run.json`
- `output_dir` 目录存在
它不看:
- 主产物是否存在
- 主产物是否可读
- 该结果是否满足发布器识别规则
因此历史半成品会被误判为“已完成”。
### 3.3 健康检查与真实运行入口不一致
当前存在两套 stripmapApp 路径逻辑:
- 健康检查依赖 `ISCE2_STRIPMAP_APP`
- 真正运行时在 WSL 内通过 `import isce` 动态定位
这会导致:
- 面板报错但实际能跑
- 面板通过但实际解释器/包位置已经漂移
### 3.4 手工恢复链缺少显式边界
当前 `run_lt1_dinsar_pipeline.py` 通过复制 `PICKLE` 中文件并改写 XML 来衔接:
- `filter -> filter_high_band`
- `unwrap -> ionosphere`
这条链路短期可用,但它对 ISCE2 内部文件结构有隐含依赖。
本轮不重写它,但必须把它从“隐式成功”改成“显式验收”。
## 4. 目标状态
ISCE2 生产链路调整后,系统对“完成”的定义变为:
1. WSL runner 执行完成。
2. 原生产物通过本地验收。
3. 验收通过的产物可被统一发布器识别。
4. 自动发布成功写入标准包。
5. 自检面板能看到 runtime、native output、publish package 三层状态一致。
换句话说:
- `rc == 0` 只表示“执行成功”
- “任务完成” 必须是“执行成功 + 产物验收成功 + 发布链成功”
## 5. 具体改造方案
### 5.1 新增 ISCE2 原生产物验收层
新增一个独立验收模块,建议位置:
- `backend/app/services/isce2_result_validator.py`
职责:
- 不参与计算
- 不参与数据库写入
- 只负责判断一个 `output_dir` 是否是“可发布、可交付”的 ISCE2 原生结果
#### 输入
- `output_dir`
- `task_alias`
- `engine_code`
- `profile_code`
- `run_key`
#### 核心检查项
必选检查:
- `output_dir` 目录存在
- 至少存在一个符合发布规则的主位移产物
- 主产物文件大小大于 0
- 主产物能被 GDAL 打开
- 若存在配对的相干产品,则记录为辅助资产
建议主产物识别规则直接复用发布器当前的规则,避免两套规则分叉:
- `*_disp.tif`
- 可选 `*_coh.tif`
#### 输出结构
返回统一 `acceptance_result`
```json
{
"accepted": true,
"primary_file": "D:/.../Task_xxx_disp.tif",
"asset_files": [
"D:/.../Task_xxx_disp.tif",
"D:/.../Task_xxx_coh.tif"
],
"issues": [],
"metrics": {
"primary_exists": true,
"primary_readable": true,
"asset_count": 2
}
}
```
#### 运行时行为
`isce2_engine.run()` 中:
- `rc != 0` 直接失败
- `rc == 0` 后必须执行验收
- 只有 `accepted == true` 才计入 `pairs_processed`
- 只有验收通过的 `output_dir` 才进入 `output_dirs`
这样“runner 成功但没产物”的情况会被收口为失败。
### 5.2 收紧 `.dinsar_run.json` 语义
当前 `.dinsar_run.json` 只是运行元数据,需要补成“运行 + 验收”的统一侧写。
本轮不改数据库表结构,先改 sidecar 内容。
新增字段建议:
```json
{
"run_key": "run_xxx",
"engine_code": "isce2",
"profile_code": "lt1_stripmap",
"runtime_id": "isce2_runtime_v1",
"output_dir": "D:/.../native",
"acceptance": {
"accepted": true,
"accepted_at": "2026-04-24T15:00:00Z",
"primary_file": "D:/.../Task_xxx_disp.tif",
"asset_files": [
"D:/.../Task_xxx_disp.tif",
"D:/.../Task_xxx_coh.tif"
],
"issues": [],
"metrics": {
"primary_exists": true,
"primary_readable": true,
"asset_count": 2
}
}
}
```
原则:
- `.dinsar_run.json` 不再只表示“跑过”
- 它要能表达“验收通过 / 未通过”
### 5.3 重写“只跑未完成”判定
`_has_completed_task_result()` 调整为 `_has_accepted_task_result()`
新的跳过条件:
1. 历史 run 的 `.dinsar_run.json` 存在
2. `engine_code / profile_code` 匹配当前请求
3. `acceptance.accepted == true`
4. `acceptance.primary_file` 存在且可读
只有满足以上条件,才视为“已完成”。
#### 不再采用的旧判断
- 仅凭 `output_dir` 存在
- 仅凭 `.dinsar_run.json` 存在
#### 这样做的效果
- 目录空壳不会再被跳过
- 历史损坏结果会重新进入生产
- “只跑未完成” 的含义变成“只跳过已验收成功的对”
### 5.4 自动发布阶段从“尽力而为”改为“交付闭环”
当前自动发布逻辑即使 `processed == 0` 也只记日志。
本轮改为:
- 引擎层只把“已验收通过”的 `output_dir` 交给发布器
- 任务层以“验收通过数量”作为发布期望值
- 发布结果必须满足:
- `processed == accepted_output_count`
- `failed == 0`
若不满足,则任务整体失败。
#### 原则
- 自动发布不再是可有可无的附属步骤
- 对托管生产来说,发布成功是交付定义的一部分
#### 失败语义
若 native output 已验收通过,但标准包发布失败:
- 任务状态标记为 `FAILED`
- 保留 native output 目录
- 日志明确写出:
- accepted count
- processed count
- failed count
这样后续可以修发布器或手动重建 catalog,但不会再出现“任务完成却没有结果”的误导状态。
### 5.5 健康检查与真实运行入口统一
目标:只保留一套 runtime 事实来源。
#### 调整方向
`ISCE2_STRIPMAP_APP` 不再作为运行事实来源,只保留为兼容字段。
健康检查改成:
1.`wsl_runtime_registry` 读取共享 Python
2. 在对应 Python 中执行:
```python
import isce
from pathlib import Path
print(Path(isce.__file__).resolve().parent / "applications" / "stripmapApp.py")
```
3. 检查该路径是否存在
4. 将解析出的真实路径回显到自检面板
#### 自检项调整
保留:
- WSL 可用
- 共享 Python 可执行
- `import isce` 成功
- stripmapApp 动态解析成功
- runner 脚本存在
弱化:
- 直接检查 `.env` 中的 `ISCE2_STRIPMAP_APP`
#### 自检返回建议新增字段
- `resolved_stripmap_app`
- `resolved_isce_package_path`
- `python_matches_shared`
- `runtime_id`
### 5.6 数据库与自维护策略
本轮尽量不动数据库 schema。
原因:
- 当前问题核心在文件系统验收语义,不在表结构
- 用户已经明确要求兼容数据库自维护与自检
- 现阶段没有必要为了可靠性问题引入一轮 schema 变更风险
#### 本轮原则
- 不新增非必要列
- 先把验收信息写入 `.dinsar_run.json`
- 数据库继续通过现有 `result_products / result_assets / result_issues` 表表达发布结果
#### 若后续必须加列
只允许:
- nullable
- 可由 `_add_missing_columns()` 自动补齐
- 不要求清库
但这不属于本轮必须项。
### 5.7 运维自检扩展
为避免“native 有结果但 publish 不一致”的灰区,本轮建议在健康面板新增两个聚合视角。
#### 1. runtime 视角
- 共享 distro / Python / stripmapApp 动态解析是否一致
#### 2. product 视角
- 已入库产品是否存在 `native_output_dir`
- `native_output_dir` 是否仍存在
- `manifest_path` 是否存在
#### 3. 新增建议计数项
- `missing_native_output_count`
- `missing_manifest_count`
- `missing_runtime_count`
其中前两项已有基础,重点是让 ISCE2 runtime 检查结果和产品检查结果在面板里串起来。
## 6. 文件落点
### 核心代码
- `backend/app/dinsar_engines/isce2_engine.py`
- `backend/app/services/job_handlers.py`
- `backend/app/services/result_catalog_service.py`
- `backend/app/services/health_service.py`
- `backend/app/services/wsl_service.py`
### 新增模块
- `backend/app/services/isce2_result_validator.py`
### 文档与运维
- `docs/ISCE2_PRODUCTION_RELIABILITY_HARDENING_DESIGN_20260424.md`
## 7. 分阶段实施
### Phase 1: 成功判定收口
- 新增 `isce2_result_validator`
- `rc == 0` 后执行验收
- 未验收通过不写成功结果
- `.dinsar_run.json``acceptance`
### Phase 2: 重跑语义收口
- `_has_completed_task_result()` 改为验收驱动
- “只跑未完成” 只跳过已验收成功的结果
### Phase 3: 发布闭环收口
- 自动发布必须与验收通过数量对齐
- `processed == 0` 不再仅告警,改为任务失败
### Phase 4: 自检对齐
- stripmapApp 改为动态解析检查
- 面板展示 runtime 实际解析结果
### Phase 5: 后续科学性加固
不在本轮立即落地,但建议保留后续专题:
- PIKCLE 恢复链版本敏感性评估
- bbox / geoPosting 的科学性收紧
- 与 ENVI/IDL 基线链的阶段性对比
## 8. 验收标准
改造完成后,至少满足以下场景:
1. WSL runner 返回 `0`,但没有 `*_disp.tif`
- 结果:任务失败,不得显示完成。
2. 历史 run 目录仍在,但 `*_disp.tif` 已被删掉。
- 结果:`只跑未完成` 不应跳过,应重新生产。
3. 健康面板显示 stripmapApp 路径。
- 结果:必须来自共享 Python 动态解析,不再依赖旧硬编码。
4. native output 验收通过,但发布器没识别到包。
- 结果:任务失败,日志明确指出 publish mismatch。
5. 自检面板与实际 runtime 使用的 Python / runner / runtime_id 一致。
## 9. 本轮结论
本轮实现不应该再把 ISCE2 生产理解为“跑完脚本”,而应理解为:
“执行成功 -> 原生结果验收通过 -> 标准包发布成功 -> 系统完成交付”。
先把这个闭环收紧,再谈后续算法科学性优化,顺序才是健康的。
@@ -0,0 +1,388 @@
# 多引擎生产结果管理与路径设计
更新日期:2026-04-24
## 1. 目标
本设计解决三个长期问题:
-`ENVI / SARscape``ISCE2`、后续 `Gamma` 的原生输出可以共存,但系统只消费统一结果包。
- 让生产、发布、catalog、数据库自维护、运维自检都围绕同一套受管理目录工作。
- 让同一对影像可以保留多引擎、多 profile、多次重跑结果,而不会互相覆盖。
本设计不是要求所有引擎输出长得一样,而是要求系统托管的结果目录、指针、manifest 和数据库语义一致。
## 2. 核心原则
- 结果管理以“标准包”为中心,不以某个引擎的原生目录命名为中心。
- 原生输出和系统发布资产必须分层,不能混在一起。
- `pair_key``stack_key` 是业务稳定主键,`run_key``run_id` 是一次具体生产实例。
- catalog 只扫描受管理发布根中的 `manifest.json`,不再把“历史扫描目录”和“正式生产目录”混用。
- `current` 指针只在“验收通过并成功发布”后更新。
- “只跑未完成”只看当前引擎和当前 profile 对应的 `current` 指针,不看裸目录是否存在。
## 3. 根路径设计
系统只保留一套正式受管理结果根:
```text
D:\production_results\
dinsar\
timeseries\
_quarantine\
```
环境变量语义固定为:
- `RESULT_PUBLISH_ROOT`
结果发布总根,默认 `D:\production_results`
- `DINSAR_PRODUCT_DIR`
D-InSAR 正式发布根,默认 `D:\production_results\dinsar`
- `TIMESERIES_PRODUCT_DIR`
时序 InSAR 正式发布根,默认 `D:\production_results\timeseries`
- `RESULT_QUARANTINE_ROOT`
结果隔离区,默认 `D:\production_results\_quarantine`
以下路径不再视为正式结果根:
- `MONITOR_DINSAR_DIRS`
只保留为历史导入或兼容扫描入口,不再作为新生产的默认落盘位置
- `Task_xxx\dinsar_results`
只保留迁移期兼容语义,最终退出正式生产链
## 4. 目录分层
### 4.1 D-InSAR
```text
D:\production_results\dinsar\<pair_key>\
current\
current.json
sarscape__custom6.json
isce2__lt1_dinsar_production_v1.json
gamma__lt1_gamma_dinsar_v1.json
runs\
<run_key>\
execution_manifest.json
manifest.json
native\
...
assets\
disp\
disp.tif
coh\
coh.tif
preview\
thumb.webp
```
目录语义:
- `<pair_key>`
同一对影像的稳定业务目录
- `runs/<run_key>`
一次具体生产
- `native/`
引擎原生输出,用于追溯、审计、复核,不直接作为系统消费入口
- `assets/`
系统统一消费的标准资产层
- `manifest.json`
正式 catalog 入库契约
- `execution_manifest.json`
生产执行记录
- `current/*.json`
当前可用结果指针
### 4.2 时序 InSAR
```text
D:\production_results\timeseries\<stack_key>\
current\
current.json
sbas__v1.json
psinsar__v1.json
runs\
<run_id>\
manifest.json
native\
...
assets\
...
preview\
thumb.webp
```
这里沿用同一哲学,只是主键从 `pair_key` 换成 `stack_key`
## 5. 指针设计
### 5.1 引擎级 current 指针
每个结果根都允许多个指针同时存在:
- `sarscape__custom6.json`
- `isce2__lt1_dinsar_production_v1.json`
- `gamma__lt1_gamma_dinsar_v1.json`
用途:
- 支持同一对影像保留多引擎结果
- 支持前端按引擎切换结果
- 支持“只跑未完成”按引擎和 profile 做跳过判断
### 5.2 默认 current 指针
`current.json` 不是必须立即启用。
建议语义:
- 只有在系统明确需要“默认展示结果”时才写入
- 默认值由人工或策略层决定,而不是由最近一次运行自动覆盖
## 6. 原生输出与发布资产分层
这是本轮设计的关键约束。
### 6.1 原生输出层
原生输出层由引擎控制,但必须落到受管理 run 目录的 `native/` 下:
- ENVI / SARscape
保留其成熟原生流程,但原生落盘最终收敛到 `native/`
- ISCE2
`stripmapApp` 原生输出、日志、中间文件全部进入 `native/`
- Gamma
后续接入时也遵循相同约束
### 6.2 标准资产层
系统统一暴露资产层:
- `assets/disp/disp.tif`
- `assets/coh/coh.tif`
- `preview/thumb.webp`
未来允许增加:
- `assets/conncomp/conncomp.tif`
- `assets/debug/...`
但 catalog 识别仍以标准 `manifest.json` 为准,不直接猜原生文件结构。
## 7. D-InSAR 生产路径设计
### 7.1 生产服务拥有 run 根目录
对任意一个 `pair_key`,生产服务先创建稳定结果根:
```text
<DINSAR_PRODUCT_DIR>\<pair_key>\runs\<run_key>\
```
然后再把引擎执行和打包都约束到这个 run 目录下。
这意味着:
- `results_root_dir` 指向 `<DINSAR_PRODUCT_DIR>\<pair_key>`
- `execution.output_dir` 指向 `<DINSAR_PRODUCT_DIR>\<pair_key>\runs\<run_key>`
- 原生输出默认进入 `<run_dir>\native`
### 7.2 ISCE2 的路径设计
对正式生产链,`ISCE2_OUTPUT_ROOT` 不再承担“正式发布根”的职责。
建议语义调整为:
- `ISCE2_WORK_ROOT`
仅用于调试、缓存、临时工作空间,或 standalone 调试运行
- 正式生产时,由编排层直接下发 `<run_dir>\native` 作为原生输出目录
- `ISCE2_OUTPUT_ROOT`
只保留 fallback 含义,不再默认等于 `DINSAR_PRODUCT_DIR`
### 7.3 ENVI 的路径设计
ENVI 当前仍可能写入 `Task_xxx\dinsar_results`。迁移完成后应统一为:
- 原生结果写入 `<run_dir>\native`
- 标准资产与 manifest 写入 `<run_dir>`
迁移期允许 packager 从历史目录导入,但这只是兼容,不再作为正式目标结构。
## 8. ISCE2 D-InSAR 生产设计约束
### 8.1 生产 profile
建议正式生产 profile 收敛为:
- `lt1_dinsar_production_v1`
不再为 ISCE2 复制 ENVI 的 `metatask/custom6` 形态。ISCE2 自己已经是成熟 orchestrator,项目层不应再人为拆成外部 6 步工作流。
### 8.2 流程边界
正式流程分四层:
1. `preflight`
2. `native_isce2`
3. `postprocess`
4. `acceptance_publish`
其中:
- `preflight`
负责解析主从影像、DEM、精轨、bbox、多视参数
- `native_isce2`
必须是一趟原生 `stripmapApp` 跑通到 geocode
- `postprocess`
负责位移导出、质量掩膜、稳定点精化、标准资产生成
- `acceptance_publish`
负责写 manifest、更新 current 指针、交给 catalog
### 8.3 参数设计
ISCE2 应继承 ENVI 已经验证过的工程经验,而不是机械复制 ENVI 步骤。
保留或新增的正式生产参数:
- `force`
- `target_grid_size_m`
- `bbox`
- `bbox_margin`
- `orbit_margin_sec`
- `coh_threshold`
- `unwrap_coh_threshold`
- `stable_point_coh_threshold`
- `stable_point_count`
- `refinement_mode`
不建议前端暴露的参数:
- `wavelength`
LT1 固定值,只读
- `filter_method`
v1 固定为工程默认值,不向前端开放高级切换
### 8.4 ENVI 经验映射
ENVI 现有工程经验中,值得保留的是:
- `target_resolution -> looks` 换算逻辑
- 基于高相干稳定点的精化思想
- 导出后再做稳定性等待与验收
不应该照搬的是:
- 把 ISCE2 拆成 ENVI 式的外部 6 步调度
- 依赖扫目录“捞”中间文件来续跑
## 9. Catalog、数据库与自检
### 9.1 Catalog
catalog 只扫描:
- `DINSAR_PRODUCT_DIR`
- `TIMESERIES_PRODUCT_DIR`
并且只认 `manifest.json`
`MONITOR_DINSAR_DIRS` 不再参与正式 catalog rebuild,只保留外部导入用途。
### 9.2 数据库
现有数据库设计可以继续使用,不需要推倒重建:
- `result_products`
- `result_assets`
- `result_issues`
- `result_catalog_states`
- `dinsar_production_runs`
- `dinsar_production_run_items`
- `dinsar_production_executions`
约束:
- `results_root_dir` 继续指向 `<pair_key>` 根目录
- `publish_root_dir` 继续指向 `DINSAR_PRODUCT_DIR`
- `native_output_dir` 由 manifest 持久化
- 启动自维护仍采用“增量补列,不破坏现有数据”的方式
### 9.3 运维自检
运维自检继续围绕 `storage_root` 工作,不围绕任务目录工作。
重点检查三层:
- 结果发布根是否存在
- catalog 状态是否健康
- manifest 数、数据库记录数、needs_rebuild 是否一致
后续再加两项专项检查:
- `product_packages`
检查 manifest 契约和资产完整性
- `wsl_runtime`
检查 WSL shared runtime、Python、ISCE2/Gamma 入口一致性
## 10. 迁移顺序
### Phase 1
- 固化本设计
- 不打断当前正在运行的 ENVI 生产
- 仅允许文档、审计、只读检查
### Phase 2
- D-InSAR run 目录强制收敛到 `<pair_key>\runs\<run_key>`
- 把引擎原生输出收敛到 `native/`
- packager 只在 run 目录内生成标准资产和 manifest
- current 指针更新改为“验收通过后再写”
### Phase 3
- ISCE2 正式 profile 切换到 `lt1_dinsar_production_v1`
- 停止 synthetic resume 方案
- 增加 preflight、稳定点精化、结果验收
### Phase 4
- ENVI 生产链迁移到同一结果结构
- legacy `Task_xxx\dinsar_results` 退出正式生产路径
### Phase 5
- catalog rebuild
- compat 视图同步
- 运维自检补齐结果包专项检查
## 11. 当前执行约束
当前如果 ENVI 仍在生产中,以下修改必须等待生产结束后再做:
- 修改 `ISCE2_OUTPUT_ROOT` 默认语义
- 修改 D-InSAR 生产 run 目录结构
- 修改 current 指针判定逻辑
- 修改 packager 输入路径和 in-place 规则
- 修改 catalog rebuild 入口和默认扫描路径
- 修改 ENVI 正式落盘位置
当前可以立即做的事情:
- 文档固化
- 代码审计
- 只读自检
- 改造计划维护
原因很简单:本轮改造会动到结果路径、发布契约、跳过判定和指针语义。生产进行中切这些逻辑,风险不是“某个功能出错”,而是直接污染正在生成的结果根。
## 12. 结论
健康的方案不是让所有引擎“输出一样”,而是让系统消费的“受管理结果结构”一样。
这样之后:
- ENVI 可以继续保留自己的成熟原生算法链
- ISCE2 可以按自己的原生工作流稳定生产
- Gamma 接入时不需要再改目录哲学
- 数据库自维护、catalog、自检、前端结果工作台都只围绕一套标准结果结构工作
@@ -0,0 +1,274 @@
# WSL Runtime 改造设计 2026-04-22
## 1. 背景
当前 `ISCE2``Gamma/PyINT` 的 WSL 执行存在三个根问题:
1. 执行边界仍是 shell 字符串,后端直接把命令交给 `wsl.exe ... bash -lc`
2. `.env` 直接持有 WSL Python、pipeline、Gamma 环境脚本等执行型配置,配置权和执行权耦合。
3. WSL 内的 conda 环境没有被定义成正式运行时资产,实际运行依赖“当前机器上碰巧可用的环境”。
这会带来四类风险:
- 参数或路径一旦逃逸 quote,直接进入 shell 解释边界。
- 引擎服务自己拼命令,执行治理无法集中落地。
- `ISCE2``Gamma/PyINT` 虽然物理上可以共用一套 WSL/conda,但逻辑上没有独立运行时标识,审计和迁移困难。
- WSL 环境漂移无法被健康检查和运维流程正式识别。
## 2. 目标
本次改造采用:
- 单 WSL distro
- 单共享 conda env
- 双逻辑 runtime
- 单一 WSL broker 出口
目标形态:
```text
业务服务
-> Engine Adapter
-> WslBroker
-> RuntimeRegistry
-> JobManifest
-> WSL Runner
-> shared conda env: insar_wsl_v1
```
其中:
- `ISCE2` 使用 `isce2_runtime_v1`
- `Gamma/PyINT` 使用 `gamma_pyint_runtime_v1`
二者可以共用:
- `WSL_DISTRO=Ubuntu-24.04`
- `WSL_SHARED_CONDA_ENV=insar_wsl_v1`
但不能共用“逻辑运行时定义”。
## 3. 运行时模型
### 3.1 共享运行时
共享运行时负责:
- distro 选择
- 共享 conda env 名称
- 共享 Python 路径
- broker 作业落盘目录
建议配置:
```env
WSL_DISTRO=Ubuntu-24.04
WSL_SHARED_CONDA_ENV=insar_wsl_v1
WSL_SHARED_PYTHON=/home/administrator/miniconda3/envs/insar_wsl_v1/bin/python
WSL_BROKER_JOB_ROOT=<backend/runtime/wsl_jobs>
```
### 3.2 逻辑 runtime
每个逻辑 runtime 固定:
- `runtime_id`
- `engine_code`
- `runner`
- `allowed_operations`
- 固定 profile 路径
- 固定审计标识
当前规划:
| runtime_id | engine | runner | 说明 |
| --- | --- | --- | --- |
| `isce2_runtime_v1` | `isce2` | `deploy/wsl/runners/isce2_runner.py` | LT-1 条带 D-InSAR |
| `gamma_pyint_runtime_v1` | `pyint` | `deploy/wsl/runners/gamma_pyint_runner.py` | Gamma / PyINT |
Gamma 固定 profile
- `deploy/wsl/profiles/gamma_env.sh`
注意:Gamma profile 属于部署资产,不再建议继续由 `.env` 动态指定脚本路径。
## 4. 执行模型
### 4.1 Broker
Broker 负责:
- 解析 `runtime_id`
- 写入结构化 `job manifest`
- 生成固定 `argv`
- 通过 `wsl.exe --exec` 执行 runner
禁止的旧模式:
- 服务层直接拼 `bash -lc "..."`
- 服务层直接决定 `source` 哪个环境脚本
- 服务层直接把 `.env` 中的 Python 绝对路径当成执行入口
### 4.2 Manifest
建议 manifest 固定包含:
- `job_id`
- `runtime_id`
- `engine_code`
- `operation`
- `created_at`
- `payload`
payload 中再放:
- 输入路径
- 工作路径
- 输出路径
- 参数
- 操作人
- 引擎内部业务上下文
### 4.3 Runner
Runner 是 WSL 内的固定可信入口。
阶段划分:
1. V1:只承担 manifest 读取、参数校验和 dry-run 输出
2. V2:接入实际 pipeline / PyINT / Gamma
3. V3:补齐固定 profile、版本指纹、错误分类与审计摘要
## 5. Conda 环境治理
### 5.1 基本原则
- 不原地继续污染旧环境
- 先冻结现有环境
- 再建立共享正式环境 `insar_wsl_v1`
- 旧环境只保留回滚用途
### 5.2 版本资产
`deploy/wsl/conda/` 下至少维护:
- `insar_wsl_v1.environment.yml`
- `insar_wsl_v1.explicit.lock`
- `insar_wsl_v1.fingerprint.json`
说明:
- `environment.yml` 用于人工维护和审阅
- `explicit.lock` 用于精确重建
- `fingerprint.json` 用于健康检查、审计和漂移检测
### 5.3 Gamma
Gamma 通常不作为 conda 包管理。
因此建议:
- Gamma 以固定安装路径存在于 WSL
-`deploy/wsl/profiles/gamma_env.sh` 统一注入环境变量
- 不再由 `.env` 直接提供动态 profile 路径
## 6. 配置迁移策略
### 6.1 新增配置
新增统一配置:
```env
WSL_DISTRO=Ubuntu-24.04
WSL_SHARED_CONDA_ENV=insar_wsl_v1
WSL_SHARED_PYTHON=/home/administrator/miniconda3/envs/insar_wsl_v1/bin/python
WSL_BROKER_JOB_ROOT=...
ISCE2_RUNTIME_ID=isce2_runtime_v1
PYINT_RUNTIME_ID=gamma_pyint_runtime_v1
```
### 6.2 旧配置处理
旧配置短期保留,用于兼容现有业务链路:
- `ISCE2_PYTHON`
- `PYINT_WSL_PYTHON`
- `PYINT_GAMMA_ENV_SCRIPT`
- `ISCE2_WSL_DISTRO`
- `PYINT_WSL_DISTRO`
但应逐步降级为:
- 历史兼容字段
- 启动检查告警来源
- 回滚开关
而不再是长期正式执行入口。
## 7. 目录规划
新增目录:
```text
deploy/wsl/
conda/
profiles/
runners/
backend/app/services/
wsl_runtime_registry.py
wsl_broker.py
```
运行时作业目录:
```text
backend/runtime/wsl_jobs/<runtime_id>/<operation>/<job_id>.json
```
## 8. 实施阶段
### Phase 1
- 新增 `WSL shared runtime` 配置
- 新增 `RuntimeRegistry`
- 新增 `WslBroker`
- 新增 runner/profile/conda 目录落点
### Phase 2
- 迁移 `ISCE2``runtime_id + manifest + broker`
- 去掉服务层 shell 字符串拼接
### Phase 3
- 迁移 `Gamma/PyINT`
-`PYINT_GAMMA_ENV_SCRIPT` 收敛到固定 profile
### Phase 4
- 增加环境指纹校验
- 健康检查显示 runtime 漂移
- 审计日志记录 runtime_id / fingerprint / runner / manifest
## 9. 本轮代码落点
本轮先完成 V1 骨架:
- `backend/app/services/wsl_service.py`
- 新增 `run_wsl_exec()`,支持 `wsl.exe --exec`
- `backend/app/services/wsl_runtime_registry.py`
- 新增共享 runtime 与双逻辑 runtime 定义
- `backend/app/services/wsl_broker.py`
- 新增 manifest staging 与 broker 执行骨架
- `deploy/wsl/runners/*`
- 新增 runner scaffold
- `deploy/wsl/profiles/gamma_env.sh`
- 固定 profile 落点
- `deploy/wsl/conda/README.md`
- 约束 conda 环境治理落点
下一步迁移优先级建议:
1. `ISCE2`
2. `Gamma/PyINT`
3. 健康检查与审计