feat(onboard/parity): 写入汇 WriteSink 与写入前计划 plan_onboarding,处置独立审查(P8c) #36
@ -1701,7 +1701,8 @@ pub fn client_static_status(project_id: &str) -> Vec<ClientReport> {
|
|||||||
|
|
||||||
// ── 一键接入计划(P8c):本机侧预计动作 + 项目文件演算 ──────────────────────────
|
// ── 一键接入计划(P8c):本机侧预计动作 + 项目文件演算 ──────────────────────────
|
||||||
|
|
||||||
/// 一键接入写入前计划(只读:不写文件、不起子进程)。P8e 接入 MCP / Tauri 投影前暂无生产调用方。
|
/// 一键接入写入前计划(只读:不写文件、不起客户端 CLI;混合文件预警会起只读的
|
||||||
|
/// git status --no-optional-locks 与 git show)。P8e 接入 MCP / Tauri 投影前暂无生产调用方。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn plan_onboarding(
|
pub(crate) fn plan_onboarding(
|
||||||
project_id: &str,
|
project_id: &str,
|
||||||
|
|||||||
@ -443,6 +443,38 @@ mod tests {
|
|||||||
let _ = std::fs::remove_dir_all(&root);
|
let _ = std::fs::remove_dir_all(&root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 「看到的就是将写的」:计划列出的文件集合与内容哈希,和随后 apply 实际写入的完全一致
|
||||||
|
/// (P8d 的 digest 复核依赖这条不变式)。
|
||||||
|
#[test]
|
||||||
|
fn plan_predicts_exactly_what_apply_writes() {
|
||||||
|
let root = temp_repo("predict");
|
||||||
|
let plan = plan_onboarding(&root, &PROJECT, machine("apply"));
|
||||||
|
assert!(write_project_files(&root, &PROJECT, &crate::DiskSink).is_empty());
|
||||||
|
for file in &plan.files {
|
||||||
|
let written = std::fs::read_to_string(root.join(&file.path)).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
sha256_hex(&written.replace("\r\n", "\n")),
|
||||||
|
file.content_sha256,
|
||||||
|
"{} 计划内容与实际写入不一致",
|
||||||
|
file.path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let status = std::process::Command::new("git")
|
||||||
|
.args(["status", "--porcelain", "-uall"])
|
||||||
|
.current_dir(&root)
|
||||||
|
.output()
|
||||||
|
.expect("git 可执行");
|
||||||
|
let mut changed: Vec<String> = String::from_utf8_lossy(&status.stdout)
|
||||||
|
.lines()
|
||||||
|
.map(|line| line[3..].trim_matches('"').to_string())
|
||||||
|
.collect();
|
||||||
|
changed.sort();
|
||||||
|
let mut planned: Vec<String> = plan.files.iter().map(|f| f.path.clone()).collect();
|
||||||
|
planned.sort();
|
||||||
|
assert_eq!(changed, planned, "apply 写入的文件集合与计划一致");
|
||||||
|
let _ = std::fs::remove_dir_all(&root);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn plan_after_apply_is_noop_and_digest_tracks_changes() {
|
fn plan_after_apply_is_noop_and_digest_tracks_changes() {
|
||||||
let root = temp_repo("applied");
|
let root = temp_repo("applied");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user