docs(plan): Plan 3 复审两 minor+五建议——status 入 checksum 域、unsupported 也写 source_records(1122)、三快照绑定语义、product-tag 勘误、permalink 措辞
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -19,12 +19,14 @@
|
||||
3. 既有纪律全套沿用:TDD、临时库测试、身份断言、无包级 test 脚本、typecheck 四段链、cms 只读。
|
||||
4. **导入语义核心**(spec §7.5/§8.1):同一 (site, connection, source_type, source_id, locale) 的 row → 已有 source_record 且 normalized_checksum 相同 → **skip(0 新修订)**;不同 → 新修订 + entry_locales.current_revision_id 前移(**published 不动**)。permalink 变化只影响 route,不影响条目身份。
|
||||
5. wppop/extras 等未知字段已在 UniversalRow.extras——落 revision.data.extras 原样保留。
|
||||
6. **normalized checksum 输入域(P0 钉死,评审 Issue 2)**:`canonicalJson({ universal_row_version, adapter_version, mapping_version, sanitizer_version, locale, mapped_content: {title, slug, bodyHtml, seo, knownFields, extras}, taxonomy_relations: taxonomyRefs, media_reference_identities: attachmentRefs, route_source_values: {sourceUrl} })`——**rawLocation 显式排除**(位置性字段,进哈希破坏跨快照 skip);版本三常量必入(bump 语义)。canonicalJson 帮助函数从 register.service.ts 提取到 `apps/api/src/common/canonical.ts` 共享导出(register 侧改 import,零行为变更)。
|
||||
6. **normalized checksum 输入域(P0 钉死,评审 Issue 2)**:`canonicalJson({ universal_row_version, adapter_version, mapping_version, sanitizer_version, locale, mapped_content: {title, slug, **status**, bodyHtml, seo, knownFields, extras}, taxonomy_relations: taxonomyRefs, media_reference_identities: attachmentRefs, route_source_values: {sourceUrl} })`——**rawLocation 显式排除**(位置性字段,进哈希破坏跨快照 skip);版本三常量必入(bump 语义);status 必入(draft↔publish 翻转必须可见)。revision.data 顶层结构钉死:`{ title?, slug?, status, bodyHtml, seo, knownFields, extras }`。canonicalJson 帮助函数从 register.service.ts 提取到 `apps/api/src/common/canonical.ts` 共享导出(register 侧改 import,零行为变更)。**注**:sourceUrl 在哈希内(route_source_values)→ permalink 变化**会产新修订**(spec §7.5 一致),只是不建新 entry。
|
||||
7. **媒体映射侧车(P0 钉死,评审 Issue 1——真实数据实证)**:真实媒体目录为扁平 GUID 命名(2625 文件无 yyyy/mm),与 WXR attachment_url 零精确命中;唯一映射在旧 cms 库 media_assets 表(source_url→file_path)。阶段 3 增加**映射侧车输入**:Task 0 从 cms PG(5433,只读 SELECT)导出该站 (source_url, file_path) 清单 JSON → 登记为 `manual_url_list` 快照(register 复用既有 kind)。对拍三级:①清单 uploads 相对路径精确命中 → ②侧车 source_url 命中(file_path 再对清单实体)→ ③missing 报告。**清单 miss 的 attachment 不插 media_assets 行**(sha256 NOT NULL 插不进),只进报告。
|
||||
8. **locale 接缝坑(评审提醒)**:适配器 mapConfig.locale 缺省空串——import 必须传 `site.default_locale`,否则 1047 行全被拒为未知 locale。Task 6 编排钉死。
|
||||
9. **阶段 3 站点路径来源(评审 Issue 4)**:主列表路径用 CLI 参数 `--products-path /products/ --news-path /news/`(默认值即此,记入 job metadata);taxonomy public_base_path 常量钉死(WP 默认):category→`/category/`、post_tag→`/tag/`、product_cat→`/product-category/`、product_tag→`/product_tag/`(spec §19.5 权威路径确认后可调——记入报告备注)。collision_key 折叠函数钉死:NFC + lowercase + 去尾斜杠。
|
||||
10. **attachment 页三态降级(评审 Issue 3)**:阶段 3 无 sitemap 解析器——attachment 页**一律按"仅 WXR→301 媒体文件"**处理(sitemap→html 分支留待 sitemap 解析能力落地,报告注明降级)。
|
||||
11. **attachment 行不建 content_entries**:wp:attachment 行只进媒体管道(media_assets)+ 路由(301);content_entries 仅 129 post + 48 product + 15 page = **192**(Task 7 计数以此为准)。sourceType→typeKey 映射钉死:wp:post→news_article、wp:page→basic_page、wp:product→product。
|
||||
12. **unsupported item 也写 source_records**(评审 Issue ②选项①):nav_menu_item 等 75 条 → source_records 行(parse_status='unsupported'、locale=站点默认、source_id=post_id、不关联 content_entry)——"不支持对象有明确结果"的可审计性;**source_records 总数 = 1122**。
|
||||
13. **import_jobs 与三快照的绑定**:job.source_snapshot_id 指向 **wxr 快照**(主输入);media_bundle 与 manual_url_list 由 CLI 按 (connection, kind) 解析最新并记入 job 报告(job 行不扩列)。Task 0 导出 SQL 加 `AND source_url IS NOT NULL`(867 中 8 行 NULL 不带出)。
|
||||
|
||||
## 仓库结构增量
|
||||
|
||||
@@ -98,7 +100,7 @@ tests/integration/import-*.test.ts
|
||||
**Files:** `route-writer.ts`;Test `tests/integration/import-routes.test.ts`
|
||||
|
||||
- [ ] 失败测试(spec §6.1 全部行有对应用例——含评审补的 asset 与首页两行,mini 数据手构补充):
|
||||
- 内容 permalink → html(路径保真含 .html;target_content_id 关联);**首页 `/` → html**;**媒体上传路径 `/wp-content/uploads/...` → asset**(media public_path 生成);主列表页 `/products/`、`/news/`(**CLI 参数来源**,默认即此)→ html;产品/文章分类 → html(public_base_path 常量按前置事实 9);tag/product_tag/日期/作者 → redirect 301 主列表;attachment 页 → **一律 301 媒体文件**(前置事实 10 降级,报告注明);`?p=` → excluded_with_reason 登记
|
||||
- 内容 permalink → html(路径保真含 .html;target_content_id 关联);**首页 `/` → html**;**媒体上传路径 `/wp-content/uploads/...` → asset**(media public_path 生成);主列表页 `/products/`、`/news/`(**CLI 参数来源**,默认即此)→ html;产品/文章分类 → html(public_base_path 常量按前置事实 9,product_tag 记 `/product-tag/`——WooCommerce 默认,本切片该路径不生效仅记录);tag/product_tag/日期/作者 → redirect 301 主列表;attachment 页 → **一律 301 媒体文件**(前置事实 10 降级,报告注明);`?p=` → excluded_with_reason 登记。**"所有阶段 3 可产生的 §6.1 行"均有用例**(人工映射/确认删除两行无输入源,属合理空缺)
|
||||
- **exact/collision 双键**:`/About` 与 `/about` 两条并存(collision_key 折叠函数按前置事实 9 钉死);同 exact_key 冲突(两内容同路径)→ 报告 conflict 不静默覆盖
|
||||
- **重导幂等**:同路径同目标 → 0 新行;目标变 → 更新(route 表可变,非不可变表)
|
||||
- [ ] 实现 + 绿 → commit `feat(import): 路由注册表生成`
|
||||
|
||||
Reference in New Issue
Block a user