用途与实际影响
这项功能怎样使用
为什么需要它
复制或取得一批数据库和媒体文件后,仅看目录存在不能证明文件齐全或检查期间没有变化。另一方面,生成一份清单也不能凭空补全原始导出,所以两者必须分开。
举个实际例子
“这批已经取得的文件,给我核对一下并留一份清单。”工具逐个计算哈希、重新列目录再读一遍;一致时给出文件数、字节数和回读收据。空目录、已有输出或文件变化时明确失败,源文件保持原样。
最后我会得到什么
得到文件清单和两遍核对收据,原始文件仍在取得方的目录。收据只能证明这组文件当时读回一致,不能替代导出完成或数据库恢复。
可直接使用
两遍读到同一组文件与内容,才发布本次核对收据。
需要确认
文件变动或漏项时留下未完成结果供排查,不自动抹掉现场。
当前不可用
来源为空、目标已存在或来源与目标互相包含时拒绝开始;取得方先准备合法稳定的文件集。
从哪里开始
在取得合法且稳定的 WeFlow 导出文件后,运行 tools/build_private_snapshot_manifest.py,指定 --source-root、全新外部 --destination 和 --source-instance-id。
需要准备什么
- 已经合法取得的稳定导出文件集
- 新检查结果的保存位置
- 对应账号或来源的标识
从开始到拿到结果
- 1
先准备稳定来源
取得方先完成合法导出,不能把仍在写入的目录当作固定快照。
- 2
工具两遍核对
逐文件记录大小与内容,再重新列目录和读一遍;变化就停并保留未完成结果。
- 3
把收据连同原件交接
消费方取得文件和核对结果;数据库能否真的恢复,还要用对应工具另验。
技术实现与依据
这里保留实现、关键条件、精确入口、历史记录和验证结果。
虚构文件回读测试通过关键规则与设计选择
按一个账号来源实例分别检查;一个账号的一次成功不证明另一个账号也完整。
工具只读字节,不解析 SQLite、语音或媒体,不负责获取、解密、导出和恢复。
外部私有目标与本仓库分开,且与源目录不能相互包含;已存在目标不覆盖。
源目录中的符号链接和重解析项按实现拒绝,避免跨越被选文件集;不要把这一行为扩写成对所有文件系统变动的完整证明。
导出是否完成、版本是否匹配、账号和覆盖是否正确,需要交接方另外核对,不能由哈希工具单独宣告。
本模块用到的名词
- Readback Receipt(回读收据)
- 普通 JSON 结果,记录文件数、总字节、集合指纹和清单文件哈希;不是数字签名,也不会阻止结果文件被修改。
- Reparse Point(重解析点)
- 目录联接或符号链接等文件系统项。本工具不跟随源集合内部这些项,避免把别处文件混入范围。
- external_read_only_reference(外部只读引用)
- 结果引用已存在的外部源文件;没有复制数据,所以清单目录不能独立替代原件。
专业定义
文件清单、两遍 SHA-256、失败暂存区与明确的证明范围。
解决什么
把哈希结果说成“不可变快照”会掩盖源目录仍可变化、导出可能不完整,以及工具并未解密或验证数据库业务内容。
当前怎样实现
- tools/build_private_snapshot_manifest.py 使用 8 MiB 分块计算 SHA-256;首遍保存相对路径、size_bytes、mtime_ns、sha256。
- 输出 weflowbridge.private-snapshot-manifest.v1,记录 source_instance_id、payload_mode、file_count、total_bytes、snapshot_fingerprint 和 files_manifest。
- 第二遍重新枚举文件,比较集合与顺序,再逐个重算哈希并检查大小和修改时间;结尾再次比较目录集合与文件标识。
- 成功结果为 weflowbridge.private-snapshot-readback-receipt.v1,包含 verification=full_sha256_second_pass 和两份清单哈希。
- 每 1000 文件默认更新进度,也可调 progress_interval_files;先写 .incomplete,完成后重命名,失败不把暂存目录当最终交付。
执行流程
- 1
取得方先完成合法、版本明确且按账号区分的导出或恢复文件准备,并停止把持续写入的活目录当作稳定快照。
- 2
传入 source-root、全新外部 destination 和 source-instance-id,工具检查目录关系与已有输出。
- 3
列出常规文件并计算第一遍哈希,把每项写入 files.jsonl 与清单,更新 progress.json。
- 4
重新列目录并完整第二遍回读;任何已检测的不一致会终止本次结果。
- 5
核对结束后写出收据并将 .incomplete 重命名;消费方同时保留实际源文件和必要的来源完成证据。
- 6
恢复是否能成功,需要取得方再用对应数据库或导出工具实际验证;仅保存收据不构成恢复验收。
边界
- 不提供签署、可信时间戳、不可变存储、自动备份或文件恢复。
- 失败后的 .incomplete 可能存在;重试不会自动覆盖它,应先判断其内容和失败原因,再使用合适的新输出或明确清理。
- 旧消费规程中的历史下游示例不代表当前启用;本次不恢复中央个人系统,也不建立新的全账号档案。
- 本轮只有虚构文件验收,没有读取真实数据库、媒体或现有私有快照。
失败与恢复
- source changed while hashing / readback mismatch
- 返回失败,不发布最终成功目录;取得方先解决源仍在变化或文件取得不完整的问题。
- destination already exists / incomplete destination already exists
- 拒绝覆盖。检查已有结果或使用新的明确目标,不删除不明材料来追求成功。
- destination must be outside the repository tree
- 只选择本仓库外的获准私有目标;工具仍不负责把原始载荷复制过去。
- empty source snapshot is not acceptable
- 空目录不能作为完整取得成功,回到取得方核对真实导出结果。
真实入口
tools/build_private_snapshot_manifest.py文件列举、两遍哈希、进度与完成输出。
tests/test_private_snapshot_manifest.py5 项虚构文件和目录边界测试。
docs/ai_consumer_contract.md / project_manifest.json来源、版本、账号与交接责任要求。
如何验证
- 5 项既有测试通过:外部虚构文件成功、已有目标保留、仓库内输出拒绝、源目标嵌套拒绝和空源拒绝。
- 成功样例的 2 个文件写入清单并完整回读,输出本身不包含虚构原始文件正文。
- 没有把这 5 项写成真实数据库解密、恢复或全部并发改动场景都已验证。
与其他模块的关系
承接已经取得的私有文件,不替代 WeFlow 数据获取、原始导出或独立消费方的恢复责任。
