4.0 KiB
FAIL
crates/ely-files/src/save.rs:40 — [P1] 固定 .bak 路径直接交给 fs::copy,会截断已有目标并跟随链接,违反 FILE-04 与 §6.1 的旧文件保留要求。macOS 实测:创建 report.md.bak 为 report.md 的硬链接,把目录设为 0555,调用 save_with_backup;复制先将原文件清空,随后创建临时文件返回 PermissionDenied,保存失败后原文件已变成零字节。目录可写时函数返回成功,但备份仍是零字节;.bak 指向其他文档的符号链接也会导致该文档被覆盖。修复方向:以排他创建方式取得独立备份文件,处理已有名称和链接冲突,验证备份完成后再替换目标;增加上述失败路径回归测试。
crates/ely-files/src/save.rs:17 — [P1] 保存路径没有执行 FILE-05 要求的外部修改检查。Session::external_changed 只有测试调用,begin_save 仅检查手动设置的冲突标记,save_atomic 与 save_with_backup 直接写入。实测:加载文件、产生本地编辑、由外部改写文件,在文件监听通知到达前执行 begin_save → save_atomic → finish_save,外部内容被覆盖,会话进入 Saved。修复方向:将加载指纹与保存目标绑定,在保存流程内检查并传播检查错误和冲突,冲突时保留两个版本供重新加载、保留本地副本或比较;回归测试须覆盖尚未收到外部通知的保存。
crates/ely-files/src/save.rs:61 — [P1] 导出防覆盖只比较路径文本,同一文件的路径别名可以绕过检查,违反 FILE-06。实测:正在编辑 /tmp/.../report.md,创建 child 目录,将导出目标设为 /tmp/.../child/../report.md;export 返回成功,源文件内容变成 %PDF-export。修复方向:按实际解析后的目标路径和文件身份校验是否与编辑源文件重合,保留路径解析错误,并增加父目录别名、符号链接目录及大小写别名的覆盖测试。
crates/ely-files/src/save.rs:19 — [P2] 原子替换直接使用临时文件的权限,保存会改变已有文档的访问权限。macOS 实测:将已有文件权限设为 0640,执行 save_atomic 成功后权限变成 0600,原来通过组权限读取该文档的用户失去访问权。修复方向:替换前保留原目标的适用权限和访问控制属性,将复制失败作为保存错误处理;增加保存前后访问权限一致的回归测试。
crates/ely-files/src/save.rs:48 — [P2] 备份名称无条件在完整文件名后追加 .bak,使合法长文件名无法保存,违反 FILE-09。实测:先创建文件名为 250 个 x 加 .md 的文件,普通文件写入成功,save_with_backup 因生成 257 字节的文件名返回 InvalidFilename / File name too long。修复方向:为内部备份生成符合目标文件系统长度限制的独立名称,覆盖接近文件名上限的保存测试。
crates/ely-files/src/save.rs:89 — [P2] 附件重名处理直接追加数字后缀,也会把合法文件名扩展到文件系统上限之外,违反 FILE-09。实测:文件名为 251 个 x 加 .png,首次导入成功,第二次导入生成 257 字节的 ...-1.png,返回 InvalidFilename。修复方向:在生成重名目标时预留后缀空间并安全处理非 ASCII 文件名,增加长文件名重复导入测试。
crates/ely-files/src/save.rs:108 — [P2] 单独文件名的 Path::parent() 返回空路径,unwrap_or(".") 保留了这个空值,随后 statfs("") 失败。macOS 实测:在有效工作目录调用 atomic_capable(Path::new("report.md")),返回 NotFound / No such file or directory,导致合法相对目标无法完成保存能力检查。修复方向:将无目录分量的目标解析到当前目录,再探测对应存储介质;增加单独相对文件名测试。
crates/ely-files/src/session.rs:501 — [P2] 文件实测为 501 行,超过 agents.md 规则 5 的 500 行上限。修复方向:将该文件收至 500 行以内,并在检查中覆盖此限制。