# AGENTS.md — CM95 / CM93 → MySQL Importer ## 1. 当前项目状态 当前 CM93 → MySQL importer 已完成 CM93JAPAN Dataset ID=1 的全量验证。 冻结基线: ```text commit: 9d56592cadf7e047fb059e5a8746188595a08b43 tag: cm93-mysql-importer-baseline-v1 ``` 最终验收: ```text Geometry Audit: OVERALL: PASS Non-Geometry Audit: OVERALL: PASS ``` PBF 当前继续冻结。 --- ## 2. 核心原则 1. 真实源码优先,不根据历史报告猜测当前实现。 2. 修改旧文件前必须先读取当前实际文件。 3. 不重新设计已经通过验收的 importer 主流程,除非任务明确要求。 4. 生产数据链必须保持可追溯、可回归。 5. MySQL 目标环境按 MySQL 5.7 处理,不假设 MySQL 8 Spatial 行为。 6. PBF 不属于当前 importer 维护任务,除非明确启动 PBF 阶段。 --- ## 3. 冻结生产文件 以下是当前已验证的核心文件: ```text src/cm93db/geometry.py src/cm93db/importer.py sql/001_schema_mysql57.sql ``` 没有明确任务时,不得重写 geometry / importer 主流程。 如必须修改,完成后必须运行长期回归验收。 --- ## 4. Geometry Contract ### 4.1 Valid geometry 已经 OGC-valid 的 Area / Coverage: ```text PASS-THROUGH ``` 不得为了 canonical 风格、ring 顺序或代码统一而重建。 ### 4.2 Invalid polygon normalization 只有 OGC-invalid Area / Coverage 才允许: ```text boundary noding → polygonize_full → odd-even face selection → union selected faces → GEOS normalize → valid Polygon / MultiPolygon ``` 禁止用下列方法直接覆盖原始 CM93 Polygon: ```text make_valid() ST_MakeValid() buffer(0) ``` Normalization 必须满足: - 不创造原始 boundary linework 之外的新边界; - 最终必须是 non-empty valid Polygon/MultiPolygon; - 无法安全完成时保留 issue / 拒绝错误 Coverage; - raw source 永远保留。 ### 4.3 raw_geotype=16 `raw_geotype=16` 是正常 CM93 parent/no-geometry。 必须保持: ```text geometry_type = META geom = None / NULL geometry_issue = None / NULL geometry_repaired = False / 0 ``` 禁止重新生成: ```text geometry_issue = "geometry missing" ``` 禁止增加: ```text geometry_invalid_count ``` 不得人为创建空 geometry。 ### 4.4 bbox normalized Area 的 bbox 必须来自最终保存的 geometry.bounds。 ### 4.5 Coverage Coverage 参与 WGS offset 判断,因此 unresolved invalid Coverage 不允许静默落库并继续参与 offset 选择。 --- ## 5. Raw Source Contract 必须保留: ```text raw_feature_blob raw_attribute_blob chart_raw_record source_record_index ``` 任何 normalization 都只改变标准化 geometry 表达,不改变原始 CM93 二进制证据。 Feature 必须可追溯: ```text dataset_id cell_id source_record_index ``` --- ## 6. Database Contract 目标: ```text MySQL 5.7 ``` Normalized geometry: ```text SRID 4326 WKB double precision ``` 不要: - 把 MySQL 8 的 SRID column constraint 当成 MySQL 5.7; - 依赖 MySQL 8-only spatial behavior; - 擅自修改 schema 来迁就临时测试; - 把 geometry 直接塞回 `chart_feature` 代替现有独立 geometry tables。 --- ## 7. Import Contract 正常 import: - DONE + source size 相同 + SHA-256 相同 → SKIP; - FAILED 默认允许普通 import 重试; - `--reimport` 才强制重新解析并写入。 不要为了测试方便修改 SHA-256 skip 逻辑。 单 Cell 写库必须保持事务语义;失败时不得留下半个 Cell payload。 --- ## 8. Counter Contract `geometry_invalid_count`: - 只统计实际 unresolved geometry issue; - 正常 META/no-geometry 不统计。 `geometry_repaired_count`: - 统计通过冻结 normalization 得到最终有效 polygon 的 Feature; - 与 Coverage 表自身 `geometry_repaired` 的记录数不是简单独立相加关系。 当前基线: ```text Feature repaired = 55 Coverage repaired = 3 Geometry issues = 0 ``` --- ## 9. 当前验收基线 CM93JAPAN / Dataset ID=1: ```text Cells 784 Features 322465 Attributes 405153 Soundings 275700 Coverages 1156 Area 81080 Area valid 81080 Coverage valid 1156 Area bbox mismatch 0 Feature repaired 55 Coverage repaired 3 Feature geometry issues 0 Coverage geometry issues 0 raw_geotype=16 4406 geotype16 issues 0 Source files checked 784 Source missing 0 Source size mismatch 0 Source SHA256 mismatch 0 ``` --- ## 10. 必做回归 长期工具: ```text tools/cm93_mysql_final_geometry_audit.py tools/cm93_mysql_non_geometry_final_audit.py ``` 修改以下任一项后,必须重新运行相关全库验收: - parser; - edge / point / sounding decode; - geometry build; - Coverage; - WGS offset; - odd-even normalization; - bbox; - DB mapping; - raw preservation; - schema; - Feature / Attribute / Sounding / Coverage 关系。 验收目标: ```text OVERALL: PASS ``` 不能用“抽样看起来正常”代替全库 audit。 --- ## 11. 历史审计脚本 仓库根目录现有 V 系列脚本属于调查历史。 允许: - 保留; - 人工复查; - 用于追溯决策来源。 禁止: - 让生产代码 import 它们; - 把它们当运行时依赖; - 以旧 V 输出覆盖当前数据库事实; - 因为历史脚本报告过旧问题,就假设当前 importer 仍存在同一问题。 长期回归以 `tools/` 下两个 final audit 为准。 --- ## 12. 文档规则 修改行为后同步更新: ```text README.md AGENTS.md docs/CM93_Importer冻结基线_v1.md ``` 文档必须区分: - 当前生产行为; - 历史调查结论; - 已关闭问题; - 尚未启动的未来阶段。 不得继续把已经解决的问题写成“当前待处理”。 --- ## 13. Git 规则 当前稳定 tag: ```text cm93-mysql-importer-baseline-v1 ``` 不得移动或重写该 tag。 后续变更: 1. 在当前 `main` 基础上修改; 2. 验证; 3. commit; 4. push; 5. 必要时再创建新的版本 tag。 不要把与当前任务无关的本地文件一起提交。 --- ## 14. PBF 当前: ```text PBF = OUT OF SCOPE / FROZEN ``` 除非用户明确启动 PBF 阶段: - 不新增 PBF schema; - 不新增 PBF exporter; - 不修改 importer 为 PBF 服务; - 不以 PBF 需求反向破坏当前 MySQL/raw 数据模型。