Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions rust/decided/tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,46 @@ fn run(args: &[&str]) -> Output {
.expect("run decided")
}

#[test]
fn corpus_digest_version_two_is_explicit_and_keeps_v1_as_the_default() {
let root = empty_scratch_root("digest-v2");
fs::create_dir_all(root.join(".decided")).unwrap();
fs::create_dir_all(root.join("decisions")).unwrap();
fs::write(
root.join(".decided/config.yaml"),
"repository_key: STD\ncorpus:\n source: acme/standards\n",
)
.unwrap();
fs::write(root.join("decisions/policy.md"), "policy\n").unwrap();
let root_text = root.to_string_lossy().into_owned();

let v1 = run(&[
"corpus",
"digest",
"--root",
&root_text,
"--corpus",
"decisions",
]);
assert!(v1.status.success(), "{}", String::from_utf8_lossy(&v1.stderr));
assert!(String::from_utf8_lossy(&v1.stdout).starts_with("sha256:"));

let v2 = run(&[
"corpus",
"digest",
"--version",
"2",
"--root",
&root_text,
"--corpus",
"decisions",
]);
assert!(v2.status.success(), "{}", String::from_utf8_lossy(&v2.stderr));
assert!(String::from_utf8_lossy(&v2.stdout).starts_with("sha256-v2:"));

fs::remove_dir_all(root).unwrap();
}

fn empty_scratch_root(label: &str) -> PathBuf {
let root = std::env::temp_dir().join(format!("asdecided-cli-{label}-{}", scratch_suffix()));
fs::create_dir_all(&root).expect("create empty CLI scratch repository");
Expand Down
16 changes: 15 additions & 1 deletion rust/rac-engine/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ fn run_dispatch(args: &[String]) -> u8 {
let order_aware = matches!(
first.as_str(),
"mcp-stats" | "telemetry" | "usage" | "skill" | "hook" | "eval" | "init" | "quickstart"
| "migrate" | "watchkeeper"
| "migrate" | "watchkeeper" | "corpus"
);
if !order_aware {
if rest.iter().any(|a| a.as_str() == "--version") {
Expand Down Expand Up @@ -287,6 +287,7 @@ fn run_corpus(rest: &[&String]) -> u8 {
let mut action: Option<String> = None;
let mut root: Option<String> = None;
let mut corpus: Option<String> = None;
let mut version: u32 = 1;
let mut extras: Vec<String> = Vec::new();
let mut positional_only = false;

Expand Down Expand Up @@ -324,6 +325,18 @@ fn run_corpus(rest: &[&String]) -> u8 {
Err(code) => return code,
}
}
other if other == "--version" || other.starts_with("--version=") => {
match take_opt_value(prog, "--version", other, rest, &mut i) {
Ok(value) if value == "2" => version = 2,
Ok(value) => {
return argparse_error(
prog,
&format!("argument --version: invalid choice: '{value}' (choose from '2')"),
)
}
Err(code) => return code,
}
}
other => extras.push(other.to_string()),
}
i += 1;
Expand Down Expand Up @@ -351,6 +364,7 @@ fn run_corpus(rest: &[&String]) -> u8 {
cmd_corpus_digest(&CorpusDigestArgs {
root: root.expect("checked above"),
corpus: corpus.expect("checked above"),
version,
}) as u8
}

Expand Down
14 changes: 11 additions & 3 deletions rust/rac-engine/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2899,15 +2899,23 @@ pub fn cmd_rename(args: &RenameArgs) -> i32 {
pub struct CorpusDigestArgs {
pub root: String,
pub corpus: String,
pub version: u32,
}

/// Read-only operator calculation for the canonical parent corpus pin. The
/// implementation consumes only local bytes below `root` and cannot write,
/// fetch, refresh, or repin anything.
pub fn cmd_corpus_digest(args: &CorpusDigestArgs) -> i32 {
match crate::federation::calculate_parent_digest(&args.root, &args.corpus) {
Ok(result) => {
emit(result.digest);
let result = if args.version == 2 {
crate::federation::calculate_parent_digest_v2(&args.root, &args.corpus)
.map(|result| result.digest)
} else {
crate::federation::calculate_parent_digest(&args.root, &args.corpus)
.map(|result| result.digest)
};
match result {
Ok(digest) => {
emit(digest);
EXIT_OK
}
Err(error) => {
Expand Down
Loading
Loading