docs(spec): 采纳复审六条建议——G5措辞、附件页默认规则、NULLS NOT DISTINCT、verify.ts分工、incoming目录、周期对齐

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-20 16:40:10 +08:00
parent 255b166513
commit 80dcc8378f
@@ -59,7 +59,7 @@ SiteForge 是多站点静态迁移、内容维护、静态构建和发布平台
| G2 | 幂等与不可变修订 | 第二次导入同一 Source Snapshot 产生 0 条新修订;内容变化产生新修订,不 UPDATE 历史修订 |
| G3 | 导入不发布 | 首次导入只更新 current revision;只有显式 publish 才更新 published revision |
| G4 | URL 注册表 | WXR + 本地 Sitemap 构成的“当前已知 URL 基线”全部有明确处置;未处理 🔴=0 |
| G5 | 路径和媒体保真 | 可保真的内容、分类、分页和媒体按旧路径输出;不能保真的路径使用明确 Redirect/Gone/Unresolved 状态 |
| G5 | 路径和媒体保真 | 可保真的内容、分类、分页和媒体按旧路径输出;不能保真的路径使用明确 Redirect/Gone;登记为 unresolved 的路径必须在门禁前清零 |
| G6 | 可复现静态构建 | 构建只读取冻结快照;相同输入连续构建的业务文件 Hash 一致;禁止 Seed 和在线数据库读取 |
| G7 | 最小主题契约 | pilot-minimal 使用正式 Theme Manifest、Render Snapshot 和公共基础组件,不复制旧 cms 的整页硬编码架构 |
| G8 | 自动门禁 | 全量检查路由、SEO、死链、媒体、Sitemap、重定向图、路径冲突和远程依赖 |
@@ -133,7 +133,7 @@ WXR 可推导 URL
| ADR-001 | ORM | Drizzle + PostgreSQL 16 | 所有 Schema 通过迁移文件管理;关键约束落数据库 |
| ADR-002 | 服务形态 | NestJS 模块化单体 + Standalone App Context + CLI | 本切片不监听公网端口;服务层未来由 HTTP Controller 复用 |
| ADR-003 | Job 执行 | 进程内 Runner + 数据库 Job 状态 | 不要求 BullMQ,但不能只存内存;进程中断后可识别 stale Job |
| ADR-004 | 原始输入 | Source Connection 与 Source Snapshot 分离 | 每个 WXR/Sitemap/媒体包形成不可变 Snapshot 和 Hash |
| ADR-004 | 原始输入 | Source Connection 与 Source Snapshot 分离 | 每个 WXR/Sitemap/已解包媒体目录形成不可变 Snapshot 和 Hash |
| ADR-005 | WXR 解析 | 流式 SAX 解析 | 禁止整文件正则解析;限制字节、节点、深度、字段长度和处理时间 |
| ADR-006 | 内容身份 | Source Record 稳定键 | WordPress ID 是来源身份;Permalink 只是 URL 证据,不作为稳定主键 |
| ADR-007 | URL 模型 | Exact Route Key 与 Collision Key 分离 | 实际路由不大小写折叠、不去尾斜杠;碰撞键只用于风险检查 |
@@ -193,6 +193,7 @@ cms-one/
docker-compose.yml # 本切片仅 PostgreSQL
database/
storage/ # 全部 Git Ignore
incoming/ # 待登记的临时暂存输入(source:register 登记后复制进 snapshots/,可清理)
snapshots/
media/
quarantine/
@@ -516,6 +517,7 @@ UNIQUE(site_id, host, exact_route_key, query_key)
规则:
- `UNIQUE(site_id, host, exact_route_key, query_key)` 中 `query_key` 为 NULL 的纯路径路由,需以 PostgreSQL `NULLS NOT DISTINCT`(或哨兵值)实现数据库级唯一——写入 Schema 约束,避免迁移编写时才发现。
- `source_path_raw` 永远保存来源原文。
- `route_path` 是经过安全校验的实际公开路径。
- `exact_route_key` 用于请求匹配,保留大小写和尾斜杠语义。
@@ -612,7 +614,7 @@ CLI 必须接受或生成明确 Actor,不使用模糊的固定 `system/importe
| 产品分类/文章分类 | 根据 Taxonomy/Term 生成列表和分页 | html |
| Tag/Product Tag | 默认 301 到对应主列表(本切片不生成 Tag 页;生成能力留待 SP3 后按需评估) | redirect |
| 日期/作者归档 | 默认 301 到新闻主列表,逐条登记 | redirect |
| Attachment 页面 | 按 Sitemap/WXR 状态决定 HTML、Redirect 或 Gone | html/redirect/gone |
| Attachment 页面 | 确定性默认规则:出现在老站 Sitemap → html;仅 WXR 证据 → 301 到对应媒体文件(或父列表页);确认已删除 → 410。偏离默认的条目在报告中逐条列出 | html/redirect/gone |
| 上传媒体路径 | 按旧 `wp-content/uploads/...` 输出 | asset |
| 无法保真的内容路径 | 人工映射;不得默认跳首页 | redirect/unresolved |
| 已确认永久删除 | 410 | gone |
@@ -1068,6 +1070,8 @@ pnpm sf preview --build <build-job-id> --host 127.0.0.1 --port 4173
### 13.1 URL 与响应
门禁 CLI 分工:`gate.ts` 对 Artifacts 做静态检查(清单/文件/Hash/路径安全);`verify.ts` 启动 Preview 后对 Route Manifest **全部路由**做真实 HTTP 验证(本节规则与 §14.5)。
- 当前已知 URL 基线 `unresolved=0`。
- 自动请求 Route Manifest 中全部路由,不以 20 条抽样代替全量检查。
- HTML、Asset、Redirect、Gone 状态符合 Manifest。
@@ -1386,7 +1390,7 @@ pnpm sf preview --build <build-job-id> --host 127.0.0.1 --port 4173
- §16 全部满足。
预计总周期:约 4–6 周。真实数据异常、未知插件字段和媒体命名问题可能增加时间。
预计总周期:约 5–8 周(各阶段区间合计 24–42 个工作日)。真实数据异常、未知插件字段和媒体命名问题可能增加时间。
---