ed081ec4772d9c9e82248862f2e89285e547a8d2
Plan 3 Task 4:media-writer(attachment 行三级对拍 + 内容行引用提取双事件消费) + magic-bytes 手写签名表(零新增依赖)。 - 三级对拍(前置事实 7):①uploads 相对路径清单精确命中 ②侧车 source_url→ file_path→清单实体(精确 miss 按文件名候选,多候选歧义不自动选全列 issue) ③missing 只进报告不插行(sha256 NOT NULL 库层防线) - 魔数校验:命中实体读存储副本头部实际字节——SVG 检出 status=quarantined 不进 产物语义(引用不建 usage);未知签名 unsupported;扩展名声明 MIME 与检测不符 → issue(按检测登记) - usage 两阶段时序(WXR 文档序 items 先于 attachment):内容行提取引用 + 修订 锚点(依赖 content-writer 先处理同事件——Task 6 编排顺序契约),finish 统一 对 media_assets 反查(id→source_id / URL→source_url→public_path),顺序无关 - 悬空引用计数 mediaDanglingRefs 不静默(mini 203/204 钉死) - counts 六键 media 前缀独占(勿复用 'skipped' 的键契约注记) - 幂等:(site,source_url) 定向 onConflictDoNothing + usage 复合主键——重跑零增行 308 测试(296+6 单测+6 集成);typecheck/lint 三绿。 Co-Authored-By: Claude Code <noreply@anthropic.com>
SiteForge
WordPress 站点到静态站点迁移引擎:读取 WXR/Sitemap/媒体归档 → 清洗入不可变内容库 → 主题化构建为自包含静态站点(Astro),全程可审计、可复现、契约冻结。
快速开始
前置:Node.js >= 22.12、Docker、corepack。
corepack enable # 激活 pnpm(或自行安装 pnpm@10)
pnpm install # 安装依赖
pnpm db:up # 启动 PostgreSQL 16(宿主端口 5434,等 healthcheck 就绪)
pnpm db:migrate # 开发库全量迁移(apps/api/drizzle)
pnpm db:test # 一键验收:起库 + 跑全部测试(测试用临时库,开发库零写入)
WXR 适配器(阶段 2)速览——pnpm sf CLI(tsx 直吃 TS,无需构建):
pnpm sf wxr:probe --wxr path/to/export.xml # 只读诊断:流式解析→映射→清洗→计数报告(不入库)
pnpm sf source:register --site <key> --wxr <path> [--sitemap <path>] [--media <dir>] # 快照登记(content-addressed、幂等)
日常质量门(等价于 CI):
pnpm lint && pnpm typecheck && pnpm test
说明:集成测试由 vitest globalSetup 自动创建临时库 sf_test_<ts> 并注入 DATABASE_URL_TEST,结束即 DROP——勿在 .env 手动设置该变量。
目录结构
apps/api/ NestJS standalone 骨架 + Drizzle schema/迁移(21 表,数据库约束即规格)+ source 快照登记
packages/contracts/ UniversalRow / Route / Render / Theme 跨源契约(冻结,变更须升版)
packages/adapter-wordpress/ WXR 适配器(saxes 流式解析 + PHP unserialize + 映射 + HTML 白名单清洗,纯函数无 DB)
tests/ 单元 + 集成测试(fixtures:WXR/Sitemap/媒体样例)
infra/ docker-compose:PostgreSQL 16(端口 5434,避开 cms 项目 5433)
scripts/ migrate-test.sh 等运维脚本 · sf.ts(source:register / wxr:probe CLI)
docs/ adr/ 决策记录 · evidence/ 基线证据 · superpowers/ 规格与计划
文档导航
- 设计基线(表结构/技术决策/阶段划分):
docs/superpowers/specs/2026-10-20-siteforge-vertical-slice-design-v2.md - 阶段 0+1 实施计划:
docs/superpowers/plans/2026-10-20-slice-foundation-phase0-1.md - 架构决策记录(ADR-001~016):
docs/adr/ - 基线证据(环境/真实 WXR):
docs/evidence/
当前状态
- 阶段 1 已完成:契约冻结、21 表数据模型全量落地(不可变触发器/唯一约束/CHECK 均落数据库并被 75 项测试锁定)、空环境一键启动+迁移验收通过。
- 阶段 2 已完成:WXR 流式适配器(saxes 流式解析 → PHP unserialize → UniversalRow 映射 → HTML 白名单清洗 → 导入前报告)、
source:register快照登记(content-addressed、幂等)与pnpm sfCLI;263 测试全绿,真实 hesupipe WXR(5.5MB)冒烟 18 项计数对照全过(峰值堆 62MiB < 100MiB,证据见docs/evidence/phase2-smoke.md)。 - 下一步:阶段 3——内容/分类/媒体入库(source_records 落库、稳定身份 upsert、checksum skip、route_registry 生成);输入清单见 Plan 2 文末"移交阶段 3 清单"。
Description