小红书注册表保存补上并发窗口的接受说明

- registry::save 在读与写之间加注释:保存由用户手动触发、明知 code agent 在改,接受后写覆盖先写
- 说明不做 CAS 的原因:把 expected_hash 下沉进共享 save 会改所有导出目标的写契约
This commit is contained in:
2026-10-06 19:23:29 +08:00
parent 065a193e4e
commit 158fae5879
@@ -44,6 +44,13 @@ pub(crate) fn save(
base_hash: &str,
) -> Result<RegistrySnapshot, XHSMiniToolExportSaveError> {
let path = registry_path(root);
// 读 `load_or_create` 与下面的 `write_registry` 之间没有锁,两步不是原子的:并发写(用户保存
// 撞上 code agent 改同一个 `.export/xhs-minitool.json`)存在「后写覆盖先写」的窗口。
//
// 这里明确接受这个窗口,不加 compare-and-swap:保存一律由用户手动触发(点保存 / 停手后的
// 自动落盘 / 点打包前的 flush),用户本来就知道 code agent 在同一项目里改文件;真撞上时重新
// 读一次注册表就能看到最新内容,不需要写入门禁级别的并发保证。把 `base_hash` 比较下沉进共享的
// `crate::export::save`(原子重读 + 比较 + rename)会改掉所有导出目标的写契约,成本高于收益。
let current = load_or_create(&path, &XHSMiniToolExportRegistry::default())?;
let form = form.normalized();
if !current.created && current.content_hash != base_hash {