Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+199
View File
@@ -0,0 +1,199 @@
use super::{BuildTarget, Directory, copy_tree, success};
use dever::compiler::toolchain::packaging;
use sha2::{Digest, Sha256};
use std::path::Path;
use std::process::Command;
#[test]
fn unsigned_bootstrap_relocates_builds_and_rejects_changed_inputs() {
let directory = Directory::new();
let author = directory.0.join("author");
let source = author.join("source");
let checkout = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
for path in [
"rust/Cargo.toml",
"rust/Cargo.lock",
"rust/rust-toolchain.toml",
"rust/src",
"lib",
"skills",
"LANGUAGE.md",
"DOCUMENTATION.md",
] {
copy_tree(&checkout.join(path), &source.join(path));
}
copy_tree(
Path::new(env!("CARGO_BIN_EXE_dever")),
&author.join("bin/dever"),
);
std::fs::create_dir(author.join("config")).unwrap();
let compiler = std::fs::read(author.join("bin/dever")).unwrap();
let mut input = serde_json::json!({
"format": "dever-local-bootstrap-input-v1", "version": env!("CARGO_PKG_VERSION"),
"target": BuildTarget::host().unwrap().name(), "source": "source",
"core": {"source": "bin/dever", "sha256": format!("{:x}", Sha256::digest(&compiler))}
});
let settings = author.join("config/setting.json");
std::fs::write(&settings, serde_json::to_vec(&input).unwrap()).unwrap();
let bundle = directory.0.join("bootstrap");
success(
Command::new(env!("CARGO_BIN_EXE_dever"))
.args([
"release",
author.to_str().unwrap(),
"--output",
bundle.to_str().unwrap(),
])
.output()
.unwrap(),
);
let manifest = packaging::verify(&bundle).unwrap();
assert!(!manifest.signed);
assert!(manifest.artifacts.len() > 100);
assert!(!bundle.join("config").exists());
assert!(packaging::create(&author, &source.join("rust/src/recursive")).is_err());
assert!(!source.join("rust/src/recursive").exists());
assert!(packaging::create(&author, &bundle).is_err());
packaging::verify(&bundle).unwrap();
let rejected = directory.0.join("rejected");
input["core"]["sha256"] = "0".repeat(64).into();
std::fs::write(&settings, serde_json::to_vec(&input).unwrap()).unwrap();
assert!(packaging::create(&author, &rejected).is_err());
assert!(!rejected.exists());
input["core"]["sha256"] = format!("{:x}", Sha256::digest(&compiler)).into();
input["source"] = "../author/source".into();
std::fs::write(&settings, serde_json::to_vec(&input).unwrap()).unwrap();
assert!(packaging::create(&author, &rejected).is_err());
// 作者输入移除并移动包后,实际 CLI 构建必须使用包内 runtime。
std::fs::remove_dir_all(&author).unwrap();
let moved = directory.0.join("moved");
std::fs::rename(&bundle, &moved).unwrap();
let cli = moved.join("bin/dever");
let project = directory.0.join("project");
success(
Command::new(&cli)
.args(["new", project.to_str().unwrap()])
.output()
.unwrap(),
);
success(
Command::new(&cli)
.args(["check", project.to_str().unwrap()])
.output()
.unwrap(),
);
let selected = success(
Command::new(&cli)
.args(["skill", "path", project.to_str().unwrap()])
.output()
.unwrap(),
);
assert_eq!(selected.trim(), moved.join("skills").to_str().unwrap());
let agents = project.join("AGENTS.md");
std::fs::write(&agents, "# 保留项目规则\n").unwrap();
success(
Command::new(&cli)
.current_dir(&project)
.args(["skill", "install"])
.output()
.unwrap(),
);
let installed = std::fs::read(&agents).unwrap();
assert!(String::from_utf8_lossy(&installed).starts_with("# 保留项目规则\n"));
success(
Command::new(&cli)
.current_dir(&project)
.args(["skill", "install"])
.output()
.unwrap(),
);
assert_eq!(std::fs::read(&agents).unwrap(), installed);
// 包内规则被篡改或移除时不能回退到作者源码,也不能修改项目文件。
let template = moved.join("skills/assets/template/AGENTS.md");
let original = std::fs::read(&template).unwrap();
std::fs::write(&template, "tampered").unwrap();
let failed = Command::new(&cli)
.current_dir(&project)
.args(["skill", "install"])
.output()
.unwrap();
assert!(!failed.status.success());
assert!(String::from_utf8_lossy(&failed.stderr).contains("artifact changed"));
assert_eq!(std::fs::read(&agents).unwrap(), installed);
std::fs::remove_file(&template).unwrap();
assert!(
!Command::new(&cli)
.current_dir(&project)
.args(["skill", "path", "."])
.output()
.unwrap()
.status
.success()
);
assert_eq!(std::fs::read(&agents).unwrap(), installed);
std::fs::write(&template, original).unwrap();
let binary = directory.0.join("hello");
success(
Command::new(&cli)
.args([
"build",
project.to_str().unwrap(),
"--output",
binary.to_str().unwrap(),
])
.output()
.unwrap(),
);
assert!(moved.join("rust/target/generated").is_dir());
let output = success(
Command::new(&binary)
.args(["hello.greeting.greet", r#"{"name":"relocated"}"#])
.output()
.unwrap(),
);
assert_eq!(
serde_json::from_str::<serde_json::Value>(&output).unwrap()["data"],
"Hello, relocated"
);
packaging::verify(&moved).unwrap();
// 连同已生成的 Cargo 缓存再次搬移,不能保留旧 runtime 绝对路径。
let relocated = directory.0.join("relocated");
std::fs::rename(&moved, &relocated).unwrap();
success(
Command::new(relocated.join("bin/dever"))
.args(["build", project.to_str().unwrap(), "--output"])
.arg(directory.0.join("rebuilt"))
.output()
.unwrap(),
);
std::fs::rename(&relocated, &moved).unwrap();
std::fs::write(moved.join("rust/src/runtime/lib.rs"), "tampered").unwrap();
assert!(packaging::verify(&moved).is_err());
let failed = Command::new(&cli)
.args([
"build",
project.to_str().unwrap(),
"--output",
directory.0.join("tampered").to_str().unwrap(),
])
.output()
.unwrap();
assert!(!failed.status.success());
assert!(String::from_utf8_lossy(&failed.stderr).contains("artifact changed"));
assert!(!directory.0.join("tampered").exists());
std::fs::remove_file(moved.join("bootstrap.json")).unwrap();
let missing = Command::new(&cli)
.args([
"build",
project.to_str().unwrap(),
"--output",
directory.0.join("missing").to_str().unwrap(),
])
.output()
.unwrap();
assert!(!missing.status.success());
assert!(String::from_utf8_lossy(&missing.stderr).contains("bootstrap.json"));
assert!(!directory.0.join("missing").exists());
}