浅念
|
24220c5ee9
|
docs(plan): P3 Task 2 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 16:50:12 +08:00 |
|
浅念
|
8485c51d59
|
fix(import): term 边缘欠报闭合(null-id 双序等价/同 slug 双 id 报告);handleEvent 分派形状
审查修复:
- null-id wp:term 双序等价:seen 分支同样报缺 term_id issue;自建行 name-only
收编(UPDATE name 为权威名、source_id 不动),term 先行/row 先行终态 name
与 issue 双序一致(测试钉死);真实 id 行不覆盖(first-wins)
- 同 slug 双 term_id:镜像条件显式报告(保留先到、跳过后到 + rawLocation),
文档序 first-wins 策略 JSDoc 钉死(测试含关联绑保留行)
- 冲突重查未命中由 found[0]! 改显式 throw(taxonomy/term 两处,含键上下文)
- adoptTerm catch 注明 ctx.db 直连约定(事务内 25P02 连锁风险——Task 6 包
事务时须重估);收编撞唯一约束路径补测试(自建行原样保留 + issue)
- 重构:内部件抽为 createTermEventHandler({handleEvent, finish}) 可分派形状
(Task 6 单消费方拉流分派、无 tee 的编排意图),createTermWriter 为自消费
整流便捷壳
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 16:44:25 +08:00 |
|
浅念
|
191c275713
|
feat(import): term 物化与缺失自建
Plan 3 Task 2:createTermWriter 管道写入器——双源物化分类域。
- wp:term 事件:taxonomies(key→object_type 映射 + public_base_path 前置事实 9
常量)+ terms(source_id=term_id 字符串)
- row 的 taxonomyRefs miss 时自建(source_id=auto:<nicename>、slug=nicename;
phase2-smoke 实证真实 WXR 的 wp:term 表缺 category/post_tag 整域);同 nicename
多次引用只建一条(内存 (taxonomy,slug) 索引 + UNIQUE 兜底)
- 单遍流式 + 收编:WXR 文档序 items 先于 wp:term——row 先到自建、wp:term 后到
就地 UPDATE 扶正 source_id/name,两种顺序终态一致(测试钉死顺序无关性)
- content_terms:is_primary 每 (entry, taxonomy) 首个 true 余 false(WP 单主分类
近似);row 无 content entry → term 仍物化、关联跳过 + issue(禁静默)
- ctx 加法扩展 events: AsyncIterable<AdapterEvent>(测试手构注入,Task 6 接真流)
- Task 1 遗留两行:ImportErrorCode 补 REPORT_WRITE_FAILED、ctx.db 事务边界 JSDoc
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 16:19:00 +08:00 |
|
浅念
|
2d57c3c814
|
docs(plan): P3 Task 1 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 16:00:14 +08:00 |
|
浅念
|
eb188da5c2
|
fix(import): 复用口径忠实化;管道 Outcome 契约与 succeeded_with_issues;报告写入时序;stale 警告
评审修复(Plan 3 Task 1 复审):
- 复用路径只返回 job 锚定字段(jobId/status/reused/siteId/mapping_version/
report_path),快照/版本块仅在非复用时解析返回——复用结果不再回显编造数据
- ImportPipeline 契约钉死:返回 Promise<ImportPipelineOutcome>
({ counts, issues });服务按"累加器 ⊕ 返回值"合并(counts 同键返回值
覆盖、issues 累加器在前),issues 非空 → succeeded_with_issues;
ctx.report 即累加器(管道抛错时部分产出仍入报告)
- 报告时序:mkdir + tmp 写入 + rename 先于终态行更新——report_path 落库
即文件存在;写失败 → failed(REPORT_WRITE_FAILED),不挂悬空路径
- CLI 复用命中非终态(queued/running)→ 崩溃残留警告(重试需显式换 --key)
- 管道抛 ImportError 保留原 code 入 error_code,summary 冠 [pipeline]
- 确定性 23505 探针:未提交孪生 job 行事务内持唯一键触发真实 PG 唯一
冲突 → 败者复用既有 job
- 报告补 idempotencyKey / attempt 字段
- 计划文档 Task 6 增补 stale 回收决策项(ADR-017)
测试 282 通过(279 + 3:Outcome 合并/ImportError 前缀/23505 探针);
typecheck 四段链 + lint 全绿。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 15:56:00 +08:00 |
|
浅念
|
0e8b2b5356
|
feat(import): job 骨架与生命周期
Plan 3 Task 1:sf import 命令骨架 + import_jobs 生命周期(空管道,Task 6 接真实管道)。
- import.service.ts(零装饰器):createImportJob——站点/快照解析(缺省按 (connection,
kind='wxr') 选最新;三快照绑定按前置事实 13 记入报告,job 行不扩列)、幂等建行
(默认 key=site+wxr快照+三语义版本;重复提交复用既有 job 不重跑,并发撞唯一约束
重查收敛)、状态推进 queued→running→succeeded/failed(attempt/started_at/finished_at/
error_code/error_summary)、报告落 artifacts/import/<jobId>/reports/import.json
(全四版本块:adapter/mapping/sanitizer/parser;job 行落 mapping_version)
- 可预期错误带 code:SITE_NOT_FOUND / SNAPSHOT_NOT_FOUND / NO_WXR_SNAPSHOT /
PIPELINE_FAILED——解析期失败零 job 行
- adapter 事件加法式补 postId(前置事实 12):unsupported/error 事件可选携带
String(postId),缺失时键缺席不硬造 source_id;row 事件与报告聚合零影响、不触发版本 bump
- canonicalJson 提取至 apps/api/src/common/canonical.ts 共享导出(前置事实 6),
register 侧改 import 零行为变更(既有清单哈希测试守护)
- sf CLI + import 命令(--site/--snapshot/--key/--connection),输出 job 摘要与版本块
- 测试:tests/integration/import-job.test.ts(5 例:生命周期观察/最新快照解析/幂等复用
与并发收敛/可预期失败零落行/failed 路径)+ adapter postId 3 例 + canonical 单测 6 例
(265→279 全绿);typecheck 四段链/lint 绿;临时库 CLI 冒烟(register→import→复用)通过
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 15:30:42 +08:00 |
|
浅念
|
e52a2eb3e4
|
docs(plan): P3 Task 0 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 15:13:09 +08:00 |
|
浅念
|
a185254e19
|
chore(scripts): 侧车导出加固——site-id UUID 校验与 audit 非 CDATA 匹配
评审两条非阻塞加固:--site-id 拼入 SQL 前过 UUID 形态白名单(非 UUID 拒绝并
明确报错);--audit 的 attachment_url 抽取正则同时匹配 CDATA 与裸文本两形态。
对真实数据重跑数字不变(859 条 / 855 对 836 命中,输出哈希一致)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 15:12:41 +08:00 |
|
浅念
|
25dcdf0a4d
|
docs: 路线 V1.1——迁移优先快线为主(用户拍板最快见效),蓝图后移至迁移 MVP 后
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 15:04:51 +08:00 |
|
浅念
|
a227cfac49
|
feat(source): 媒体映射侧车导出与登记
Plan 3 Task 0(评审 Issue 1):旧 cms 库 media_assets 的 source_url→file_path
映射只读导出为侧车 JSON(859 条,覆盖率对照 WXR 855 attachment_url:精确命中
836 / 归一命中 0 / 未命中 19,97.8%),register 新增 --media-map 输入通道
(kind=manual_url_list 快照,形状校验 INVALID_MEDIA_MAP,metadata 含条目数,
幂等复用)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:42:32 +08:00 |
|
浅念
|
ceb6106025
|
docs: V4 基线重评估与路线定制 V1.0——路线A确认(Plan3→蓝图→双入口构建),资产保全判定与差距账本
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:31:07 +08:00 |
|
浅念
|
9937f76856
|
docs(plan): Plan 3 定稿——Task 1 补 adapter 扩展提示
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:19:51 +08:00 |
|
浅念
|
9233f1ce5d
|
docs(plan): Plan 3 终审收尾——unsupported 事件加法补 postId、product-tag 同步、Task0 SQL 过滤、措辞统一
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:17:56 +08:00 |
|
浅念
|
4f6d50a7ae
|
docs(plan): Plan 3 复审两 minor+五建议——status 入 checksum 域、unsupported 也写 source_records(1122)、三快照绑定语义、product-tag 勘误、permalink 措辞
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:15:40 +08:00 |
|
浅念
|
d392370fda
|
docs(plan): Plan 3 修复评审两 P0+四项——媒体映射侧车(真实数据实证扁平目录零命中)、checksum 输入域钉死(排 rawLocation)、attachment 降级 301、站点路径来源、悬空引用用例、§6.1 全行覆盖、locale 接缝、计数勘误
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:10:36 +08:00 |
|
浅念
|
664aade131
|
docs(plan): Plan 3 实施计划——阶段3 内容导入管道(8任务)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 14:00:09 +08:00 |
|
浅念
|
a96f35c854
|
docs(plan): Plan 2 收官——Task 9 勾选、终审账本补遗(issues 机器码化/媒体限额/ADR 第三处 paths)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 13:41:51 +08:00 |
|
浅念
|
2a0d830520
|
docs: 阶段2收尾——ADR-016/typecheck链/阶段3移交清单/README
- ADR-016:saxes ^6.0.0(勘误:计划曾误写 ^0.9)/commander ^14 根依赖/清洗三件套
同 range + 镜像直调 launder.naughtyHref/tsx ^4 CLI 直吃 TS;跨包接线(根 tsconfig
paths 三方消费、build 侧 dist+prebuild、tsconfig 双链型并存);根 engines 升
>=22.12(对齐 sanitize-html 2.18 engines,CI node 22 与本机 24 均满足)
- 根 typecheck 链扩为四段:追加 pnpm --filter @sf/adapter-wp typecheck
- Plan 2 文末新增"移交阶段 3 清单"定稿(7 项:taxonomyRefs 自建缺失 term、
media_bundle 映射、connection 库级唯一索引、REST 重审项、导入消费接口、
Task 0.2 cms 备份续传携带、versions.ts bump 纪律);Task 9 与验收节勾选
- README:快速开始加 pnpm sf 示例;目录结构/文档导航/当前状态更新为阶段 2 完成
- 三绿:lint / typecheck(四段)/ test 263 全部通过(数量不变)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 13:34:15 +08:00 |
|
浅念
|
57357cd493
|
docs(plan): P2 Task 8 勾选——真实冒烟验收通过
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 13:28:03 +08:00 |
|
浅念
|
21ef37232d
|
test(evidence): 阶段2真实WXR冒烟通过
真实 hesupipe WXR(5,490,399B,SHA-256 与 Plan 1 基线一致)跑 wxr:probe 全链:
计数 18 项对照全过(rows 1047 / terms 451 / unsupported 75 细分一致 / failed 0 /
item 总数 1122);heapUsed max 62.2MiB < 100MiB(setInterval(100ms) 双 max 口径,
全程 167ms 仅 2 样本如实注明);parseMs 含流 IO 等待口径注明。
nicename 锚点核对:在表 taxonomy 706/706 全命中(nicename≡slug,违例 0);
category/post_tag 共 807 引用因 wp:term 表缺该 taxonomy 不可解析——阶段 3 需按
(domain, nicename) 自建缺失 term,不能假设 term 表完备。
eslint.config.js:scripts/*.mjs 显式 node 全局(no-undef 误报)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 13:25:09 +08:00 |
|
浅念
|
75028e8a16
|
docs(plan): P2 Task 7 勾选 + Task 9 移交清单
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 13:14:35 +08:00 |
|
浅念
|
c28c1655a4
|
fix(source): DB 事务化;storageRoot 入 metadata;siteCreated 与并发测试;CLI 体验与校验小修
评审修复(4 项 Important + 8 项 Minor):
- DB 事务化:site→connection→snapshots 全部落库包进 db.transaction 单事务
("任何失败零落库"字面成立);助手改收 Pick<select|insert|execute> 结构类型
(tx 与直连 db 通用)。并发撞唯一约束不在事务内补查(语句失败后续查 25P02),
改为 registerSource 层事务级重试(≤3 次,第二次 select 命中复用分支)
- connection 并发:select-then-insert 无约束可兜底,事务内 pg_advisory_xact_lock
(siteId:name) 串行化同键登记(kind 枚举扩展推迟 REST 通道,注释注明)
- storageRoot 绝对路径固化进每条 snapshot metadata 与报告 inputs(快照不可变,
事后无法补写——永久缺口封堵)
- ensureSite 返回 created;RegisterResult.siteCreated;CLI 站点已存在时提示
--name/--locale/--origin 未生效
- 媒体复制期逐文件 sha 复核(copyAndHash 对拍清单,源中途变更 → COPY_FAILED)
- 空媒体目录拒绝(EMPTY_MEDIA_DIR)
- CLI:PATH_NOT_ALLOWED 追加 --allow 提示;--origin 经 new URL 校验(http/s)、
--locale 语言标签形状校验,fail fast;开跑打印生效白名单(审计)
- makeRunId 服务导出、CLI 复用;.tmp 残留手工清理策略写入文件头注释
- 测试 +2:并发同输入恰好一组行/双方同 id/新建标志恰一(3 次重跑稳定);
isUniqueViolation 形状单测(drizzle cause.code / 裸 code / 其他)
全套 263 绿;typecheck / lint 绿;CLI 冒烟对临时库验证事务路径、siteCreated
输出、defaults 落库(en-US / https://qa.example)、白名单打印与校验报错
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 13:06:48 +08:00 |
|
浅念
|
9732e1b684
|
fix(source): 中间段符号链接逃逸堵截(无条件 realpath);注释口径修正
- validateInputPath 原先只在末段是符号链接时 realpath——中间目录段含 junction
(链接在白名单内、目标在外,Windows 免特权可构造)时词法前缀判定被绕过,
会读到白名单外内容(评审 PoC 复现)。改为 lstat 存在性探测后无条件
realpath(abs),整条路径解析到物理位置再做白名单与类型判定;断链场景
realpath 抛 ENOENT 仍归入 INPUT_NOT_FOUND(语义不变)
- 回归测试:中间段 junction 逃逸用例(incoming/junc → pkg-outside/escape.xml,
断言 PATH_NOT_ALLOWED + 零落库);已对修复前代码验证为红(逃逸被接受)、
修复后绿
- 注释口径修正:registerSource 的"任何失败零落库零复制"只在校验阶段成立——
摄取中途失败不回滚已落位副本(content-addressed、幂等无害),但 DB 写入
在全部摄取完成后才开始,任何失败零落库不变
- 计划勾选:Task 7 "CLI 执行机制(钉死)"(已实现并双命令冒烟验证)
全套 261 测试绿(+1);typecheck / lint 绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 12:47:07 +08:00 |
|
浅念
|
46b823e667
|
docs(plan): P2 Task 7 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 12:31:31 +08:00 |
|
浅念
|
586d715455
|
feat(source): 输入登记服务与 sf CLI(content-addressed 快照)
- registerSource(db, input):wxr/sitemap/媒体目录三类输入登记为 content-addressed
快照——流式 copy+sha256 单遍双算(64KB 块),副本落
storage/snapshots/<kind>/<sha256前2>/<sha256>(文件)或 <sha256>/(媒体整树),
后续任务只读副本;UNIQUE(site,kind,sha256) 幂等(重复登记复用既有行)
- media_bundle 哈希钉死:排序相对路径('/' 归一)+ 每文件 sha256 → canonical
JSON(键排序无空白)→ 再 sha256;不含 mtime、不依赖遍历顺序;完整清单
(path/bytes/sha256)入 metadata jsonb;符号链接(含 junction)跳过并记录
- site 按 key select-then-insert upsert(23505 竞态重查);connection 判重键
(site_id,name) 为应用层 select-then-insert(表无库级唯一,注释注明)
- 路径安全:输入 realpath 后须在 allowedRoots 白名单内(缺省 storage/incoming),
ENOENT/越界/类型不符抛带 code 的 SourceRegisterError;全部输入先校验后摄取,
任何失败零落库零复制
- 报告落 artifacts/register/<runId>/reports/register.json(runId=时间戳+随机;
输入清单/哈希/大小/耗时)
- scripts/sf.ts(commander):wxr:probe 只读诊断(任意可读路径,IO/损坏文件出
报告不崩——Task 6 fatalError 契约)出 JSON/HTML 报告;source:register 调服务
出摘要。CLI 机制钉死:根 devDep tsx + 根 script sf + commander 根依赖,TS 源码
直连(@sf/* 经 tsconfig paths,不经 dist)
- source.module.ts:Nest 注册 SourceRegisterService(standalone context 用);
register.service.ts 刻意零装饰器(CLI/测试直 import 不拉 reflect-metadata)
- launder 类型垫片改经 triple-slash 引用随 html.ts 进任意编译程序(apps/api 与
根程序直连适配器源码的新场景);apps/api 增 @sf/adapter-wp workspace 依赖与
paths 映射(register.service 消费 ADAPTER_VERSION 单源)
- 测试 +7(tests/integration/source-register.test.ts,临时库 + tmpdir storage/
报告根 finally 清理):三输入登记/清单哈希定义对拍/重复登记幂等/mtime 排除/
副本布局与内容一致/路径安全六分支/junction 跳过/报告契约;全套 260 绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 12:31:15 +08:00 |
|
浅念
|
a535cde270
|
docs(plan): P2 Task 6 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 12:09:41 +08:00 |
|
浅念
|
073b9ca39c
|
fix(adapter-wp): IO 错误归入 fatalError;rowErrors 封顶;timings 契约与纯 term 流测试;PARSER 版本漂移保险
审查修复(Task 6 质量审查 5 项):
- Fix 1:Node 系统错误(Error 且 code 字符串——ENOENT/EACCES 等 IO 形态)与 WxrError
同路记入 fatalError(message 含 code 与 path),报告不上抛保留已聚合部分;无 code 的
程序 bug 仍原样上抛;模块头契约注释同步修正
- Fix 2:rowErrors 固化封顶 10_000 条 + rowErrorsTruncated 计数(超出只计数不固化,
防对抗性输入使报告体积失去上界;counts/byDiffType 统计维度不受截断影响);HTML
渲染追加截断说明行
- Fix 3:timings 注入契约测试(多 chunk 流消费完成后外部对象 parseMs>0/sanitizeMs>=0)
- Fix 4:纯 wp:term 流测试(counts 空对象/rows=0/terms 计数)
- Fix 5:PARSER_VERSION 漂移保险(createRequire 读 saxes/package.json,主版本不一致
即爆红,fail loud)
247 → 253 测试全绿;tsc/lint/build 绿。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 12:04:15 +08:00 |
|
浅念
|
6573b8b326
|
feat(adapter-wp): 全链组装与导入前报告
- src/versions.ts:ADAPTER/MAPPING/SANITIZER_VERSION 三常量(bump 语义 JSDoc 冻结:
映射表/清洗白名单实质变更才 bump 对应项,三者独立演进)+ PARSER_VERSION(saxes 硬编码)
- src/adapter.ts:runWxrAdapter 串联 parseWxrStream→mapItem→sanitizeBodyHtml 为
AsyncGenerator<AdapterEvent>;term 旁路直通;bodyHtml 为空跳过清洗零 diff;
changed 用 html!==input(Task 5 移交:diffs.length===0 ≠ 未变更);validateUniversalRow
加法式契约复检(不动 contracts);解析/清洗分段计时(parser.next() await 窗口归属解析)
- src/report.ts:runWxrAdapterReport 聚合(首条版本块/按 sourceType Created-Skipped(无
变化)-Failed-Unsupported/清洗统计按 diff.type+changedRows/行级错误 rawLocation+message
+excerpt/致命 WxrError 记 fatalError 不上抛——wxr:probe 消费通道);renderReportHtml
所有动态文本经 escapeHtml(<>&"',Task 5 移交的标记注入面防线)
- test/adapter.test.ts:19 用例(mini 全链/changed 语义/报告结构/恶意样本转义/
unsupported-error 汇聚/wppop 失败贯通/JSON 可序列化/致命解析错误交付确定性)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 11:44:55 +08:00 |
|
浅念
|
15e1e51a14
|
docs(plan): P2 Task 5 勾选 + Task 6 对接清单
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 11:27:18 +08:00 |
|
浅念
|
7506fef875
|
fix(adapter-wp): srcset 审计精确化(parse-srcset);false 形态防御;复用 launder.naughtyHref;等价测试参数化
审查修复四项:srcset 逐候选审计改用 parse-srcset 同库实现(data: 逗号内嵌
URL 不再误切;全候选被拒/解析异常/零候选→整属性删除记账,含空 srcset);
deriveMirrorView 对 false/缺省形态 fail fast(allowedTags/allowedAttributes
的 false=库全放行语义与镜像空集解释相反,修正原注释);URL 判定复用
launder.naughtyHref(sanitize-html 2.18 同一实现路径,删手写镜像);
仪表化等价测试参数化为 15 个对抗样本(实体/控制字符/NULL/URL 注释走私、
未引号/重复属性、深嵌套、srcset 形态)。测试 204→228。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 11:18:39 +08:00 |
|
浅念
|
8dd6eaf1b6
|
feat(adapter-wp): HTML 白名单清洗与差异收集
sanitize-html@^2(MIT)白名单清洗 + onOpenTag 观察钩子按文档序收集 SanitizeDiff[]
(镜像判定从 SANITIZE_CONFIG 单源推导;仪表化与清洗输出字节等价,测试钉死)。
白名单决策冻结:h1/布局标签/内联样式/iframe 拒绝(diff 留痕),外链 img 含
1x1 追踪像素本切片保留(远程依赖报告归 Task 6,路径重写归阶段 3)。
测试 184→204。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 10:39:37 +08:00 |
|
浅念
|
8796da03f1
|
docs(plan): P2 Task 4 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 10:14:47 +08:00 |
|
浅念
|
4c4c43f7d9
|
fix(adapter-wp): 原型键防御与对抗测试;meta 冲突策略统一(单值先者+issue/phpRaw 清理);extras 原型污染防御;config 校验;prebuild 依赖固化
- Fix 1:routes/STATUS_MAP 查键一律 Object.hasOwn 守卫('constructor'/
'valueOf' 等继承键裸索引命中函数值绕过 undefined 检查)+ 对抗测试
- Fix 2:prebuild 脚本先建 contracts dist(fresh-clone build 不再 TS2307,
亦防 stale dist 静默编译;已实测 rm -rf dist 后全链成功)
- Fix 3:单值 meta(thumbnail/seo×2)重复→先者胜出+issue(WP 单值语义,
首个占位即便值非法不被顶替);wppop 重复→最后一次决定终态(成功清
phpRaw/失败清 wppop_sections,两键互斥);三方策略 JSDoc 冻结
- Fix 4:extras 改 null 原型字典——'__proto__' meta 不再被 setter 静默
吞掉(测试钉死自有键+JSON 往返);gallery 累积语义明确
- Fix 5:typeRoutes 空字符串路由值 → TypeError fail fast
- 173→184 测试全绿;typecheck/lint/build 绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 10:10:03 +08:00 |
|
浅念
|
c99bbbb29e
|
feat(adapter-wp): WXR→UniversalRow 映射器(status 值域/悬空保留/unsupported 分流)
- mapItem 纯函数:WxrItem → MappedResult 三分支(row/unsupported/error),
DEFAULT_TYPE_ROUTES/STATUS_MAP/META_KEYS 三冻结表导出
- Plan 1 移交落实:status 值域表驱动(未知→unknown+issue);property 断言
(isUniversalRow+refs 形状非空)测试钉死
- Task 3 审查移交:postId null→error(不产 row 不猜);-7 原样;-0 归一 '0'
- taxonomyRefs 锚点=category @nicename(=term slug,Task 8 实数据核对后冻结)
- 悬空 gallery 203/204 原样保留;wppop 解析失败→extras.phpRaw+issue(不崩不丢)
- Task 2 审查移交补测四例:d: 键拒绝/NUL 往返/s:1:"0"→Map/1MB<50ms 烟雾
- tsconfig.build.json:src 首次引 @sf/contracts 后 build 经 contracts dist
声明解析(rootDir TS6059;typecheck/vitest/tsx 仍 src 直连,ADR-016 归口)
- 142→173 测试全绿;typecheck/lint 绿
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 09:45:34 +08:00 |
|
浅念
|
f4971a943b
|
docs(plan): P2 Task 3 勾选 + 两批审查移交件并入 Task 4
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 09:26:49 +08:00 |
|
浅念
|
8edbbad45b
|
fix(adapter-wp): 内存上界注释纠正;错误前事件排空确定化;post_id 严格解析;嵌套畸形 fail-fast;类型收紧与测试钉
审查修复六项(wxr-stream):
- 内存上界表述纠正:saxes 按节点内部缓冲整个 text/CDATA 节点,对抗性
单字段文件峰值 ≤ maxWxrBytes 的 UTF-16 表示(约 2×),并非与文件
大小解耦;maxFieldLength/maxCdataLength 封顶的是本模块缓冲与产出
字段长度
- parser.write/close 抛错前先排空待 yield 队列再重抛:错误前已完成
事件的交付不依赖 chunk 划分(测试钉死单 chunk 与 7 字节切块一致)
- wp:post_id / wp:term_id 严格解析:整串十进制 + Number.isSafeInteger,
否则 null(表驱动测试:''/'0x10'/'12abc'/超安全域 → null)
- 嵌套 item/wp:term 立即 WxrParseError(fail-fast,防外层截断产出)
- Target.field 经 Exclude 收窄为纯文本字段,消除 as string 断言
- 测试钉死:提前 break 销毁上游流、text+CDATA 混合累计、限额错误
message 含行列位置
142 测试全绿(新增 12)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 09:21:41 +08:00 |
|
浅念
|
25e8b9cb5c
|
feat(adapter-wp): saxes 流式 WXR 解析器
parseWxrStream(readable, {limits, now}) → AsyncGenerator<WxrEvent>:
逐 chunk 喂入 saxes(^6.0.0,ISC;计划所写 ^0.9 不存在于版本历史),
item/term 按文档序交错产出;任一时刻只持有当前聚合状态 + 单 chunk 内
待 yield 队列,绝不收集已产出 item 列表(峰值内存与文件大小解耦)。
- 字段:postId(数值解析)/postType/status/postName/link/title/
contentEncoded/excerptEncoded/postDate/postModified/attachmentUrl/
creator + metas{key,value}[] + categories{domain,nicename,value}[] +
rawLocation(wxr://item/<n>、wxr://term/<n>)
- 错误体系照 PhpError 先例:WxrError 基类;WxrParseError 带 saxes
行列位置(error 事件同步抛出时捕获);WxrLimitError 按 kind 区分
- 限额:bytes/items/terms/depth/cdata/fieldLength(先检查后追加,
超限内容永不入缓冲)/metaPerItem/time(可注入时钟)——超限即抛,
不静默截断
- 实体防线(测试钉死):saxes 实体表固定为五预定义 + 数字引用,
DOCTYPE 内部/SYSTEM 实体不注册——引用即 WxrParseError,替换文本
不进产出;纯字符串解析,全程无网络 I/O
- 跨 chunk 喂入(7 字节/块)与单 chunk 产出一致(StringDecoder 处理
多字节边界);畸形 XML(提前闭合/截断)→ WxrParseError 带行列
130 测试全绿(新增 22)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 08:55:11 +08:00 |
|
浅念
|
6eb5fa6dda
|
docs(plan): P2 Task 2 勾选
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 08:41:17 +08:00 |
|
浅念
|
4f90b63c61
|
fix(adapter-wp): phpValueToJson 辅助与 JSON 陷阱警示;错误上下文摘录;PhpError 公共基类
复审修复:新增 phpValueToJson(Map→字符串键普通对象,递归;bigint 分支
冻结为抛 TypeError 不静默转换),PhpValue JSDoc 警示 Map 直接
JSON.stringify 会静默变 {};两类错误 message 附 offset ±20 码元原文
摘录(控制字符转义、120 字符封顶);PhpError 公共抽象基类,两子类
互不 instanceof 的既有断言保持通过。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 08:37:08 +08:00 |
|
浅念
|
5550952fdb
|
feat(adapter-wp): PHP serialize 受限解析器
只支持 i/b/d/s/a 四类型的单指针递归下降解析器:深度与元素数双限额
(默认 DEFAULT_WXR_LIMITS phpMaxDepth=8/phpMaxElements=1000,超限抛
PhpLimitError 按 kind 区分),长度前缀/结构错误一律抛 PhpParseError
(含 offset),尾随垃圾抛错。a: 形状推断:连续 0 起整数键→密集数组,
否则 Map。s: 按 UTF-8 字节宽度取串(含代理对),中文 postmeta 准确。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 08:23:32 +08:00 |
|
浅念
|
ec898f6e0a
|
docs(plan): P2 Task 1 勾选;tsconfig 双链型注释(ADR-016 待记)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 08:16:18 +08:00 |
|
浅念
|
dc4557cccf
|
feat(adapter-wp): 包骨架与限额契约
Plan 2 Task 1:@sf/adapter-wp 包骨架(照 contracts 先例:build extends +
rootDir "." + exclude test)+ WxrLimits 十字段限额契约与 DEFAULT_WXR_LIMITS
值域冻结(设计基线 §7.2)+ 跨包接线。
跨包接线(一份 paths 三方消费):
- 根 tsconfig compilerOptions.paths 把 @sf/contracts、@sf/adapter-wp 映射到
各自 src/index.ts;adapter tsconfig extends 根 tsconfig 使包级 tsc 读同一
份 paths(extends 相对路径按声明处解析,映射始终落在仓库根)
- 根 vitest.config.ts resolve.alias 指向同一映射(vitest 不读 tsconfig paths)
- adapter 加 @sf/contracts workspace:* 依赖;三方均直连 src,不经 dist
(已实测:移走 contracts dist 后 vitest 与包级 tsc 仍全绿)
- 根 devDependencies 加 @types/node@^22(对齐 apps/api 钉 22):alias 的
fileURLToPath 辅助需 node 类型,此前根程序靠 apps/api 传递 @types 才有
node 全局,属偶合
限额类型锁(照 contracts 单源派生先例):DEFAULT_WXR_LIMITS as const
satisfies WxrLimits + _LIMIT_KEYS 键集与 keyof WxrLimits 双向咬合断言;
timeBudgetMs 以可注入时钟(构造函数 now())测试于 Task 3、实测覆盖于 Task 8。
验证:pnpm test 78 绿(75+3);pnpm --filter @sf/adapter-wp exec tsc
-p tsconfig.json --noEmit exit 0(--listFiles 证实 contracts 经 src 解析);
根 typecheck 链与 pnpm lint 绿;build 产物形状核验后清理。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-21 08:05:08 +08:00 |
|
浅念
|
2d33dd17dd
|
docs(plan): Plan 2 采纳复审建议——paths 统一三方消费、commander 定根依赖
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 22:53:40 +08:00 |
|
浅念
|
5cc98c584f
|
docs(plan): Plan 2 修复评审三 Issue 与建议——CLI机制/跨包接线前置/media清单哈希定义/probe路径策略/内存采样法/报告路径/责任链续传
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 22:51:53 +08:00 |
|
浅念
|
ecff5a34af
|
docs(plan): Plan 2 实施计划——阶段2 WXR 流式适配器(9任务)
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 22:46:37 +08:00 |
|
浅念
|
494beadf94
|
chore: 终审 Minor 清理——@types/node 钉 22、contracts 构建排除测试、helpers 盲区注记、计划收口注记
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 21:08:34 +08:00 |
|
浅念
|
c128ebf5a0
|
docs(plan): Task 14 勾选——Plan 1 全部任务完成;修注释笔误
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 20:59:58 +08:00 |
|
浅念
|
07483b5ae2
|
docs: ADR 001–015 落档 + README
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 20:56:26 +08:00 |
|
浅念
|
3c32becba6
|
chore: 收尾清账——type:module/gitattributes/engines/lint/CI/根typecheck覆盖
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 20:56:26 +08:00 |
|
浅念
|
622c2b09d8
|
docs(plan): Task 13 勾选——阶段 1 验收:globalSetup 临时库 + 空库一键迁移
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
2026-10-20 20:43:24 +08:00 |
|