open-standards/joule-code/joule-code-rs/crates/joule-code-reviewer/tests/file_handoff.rs
Transaction Science 4132daa233 joule-review: persistent per-role identities replace the fixed demo seeds
The reviewer and semantic-tier principals were fixed demo keys ([0xAE], [0x5e]).
They are now persistent joule-code-identity keyfiles: the structural reviewer
loads/creates .joule/reviewer.key (or JOULE_REVIEWER_IDENTITY), the semantic
tier .joule/semantic-reviewer.key (or JOULE_REVIEW_SEMANTIC_IDENTITY). Each is
a distinct, traced agent principal that stays the same across runs — the same
reviewer signs across sessions, attributable by its did:key, rather than an
anonymous per-run seed.

Separation of duties is unchanged and now identity-backed: author, structural
reviewer, and semantic reviewer are three distinct persistent principals; an
op authored by the reviewer's own identity is still skipped (self-review). The
self-review integration test now exercises the real path — write a reviewer
keyfile, author an op as that principal, confirm the binary skips it.

(joule-code-identity needs ed25519-dalek's rand_core feature for key
generation; enabled on that crate.) 17 tests; clippy clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-11 19:01:45 -04:00

190 lines
7.9 KiB
Rust

//! The cross-process loop: an author exports a signed spec + ops into
//! `.joule/`, the `joule-review` binary runs as an independent reviewer
//! process, and the reviews it writes back satisfy (or fail) the gate.
use std::path::PathBuf;
use std::process::Command;
use ed25519_dalek::SigningKey;
use joule_code_cargo::{Anchor, CodingOp, Edit, SignedOp};
use joule_code_review::{approval, SignedReview};
use joule_code_schema::{ContentId, Tier};
use joule_code_spec::{Clause, ClauseKind, SignedSpec, Spec, ALG_ED25519 as SALG};
fn sk(s: u8) -> SigningKey {
SigningKey::from_bytes(&[s; 32])
}
fn op(author: &SigningKey, intent: &str, body: &str) -> SignedOp {
CodingOp {
alg: 0x01,
prior: ContentId::of_bytes(body.as_bytes()),
edits: vec![Edit {
path: "src/store.rs".into(),
anchor: Anchor::ByteRange { start: 0, end: 0 },
replacement: body.as_bytes().to_vec(),
}],
author: author.verifying_key().to_bytes(),
intent: intent.into(),
tier: Tier::L3,
}
.sign(author)
.unwrap()
}
#[test]
fn an_independent_reviewer_process_closes_the_loop_over_files() {
let author = sk(1);
let work = std::env::temp_dir().join(format!("joule-review-it-{}", std::process::id()));
let joule = work.join(".joule");
std::fs::create_dir_all(&joule).unwrap();
// author exports the adopted spec + ops
let spec: SignedSpec = Spec {
alg: SALG,
intent: "a persistent todo list".into(),
clauses: vec![
Clause { id: "C1".into(), text: "todos persist".into(), kind: ClauseKind::Requirement },
Clause { id: "NG1".into(), text: "no multiplayer".into(), kind: ClauseKind::NonGoal },
],
parent: None,
author: author.verifying_key().to_bytes(),
}
.sign(&author)
.unwrap();
std::fs::write(joule.join("spec.adopted.json"), serde_json::to_string(&spec).unwrap()).unwrap();
let good = op(&author, "C1: persist todos", "fn save() { write_to_disk(); }");
let bad = op(&author, "C1: persist todos", "fn save() { todo!() }");
let scope = op(&author, "NG1: multiplayer", "fn mp() {}");
let ops = vec![good.clone(), bad.clone(), scope.clone()];
std::fs::write(joule.join("ops.json"), serde_json::to_string(&ops).unwrap()).unwrap();
// run the independent reviewer process
let status = Command::new(env!("CARGO_BIN_EXE_joule-review"))
.arg(&work)
.status()
.expect("joule-review runs");
assert!(status.success());
// ingest the reviews it wrote
let text = std::fs::read_to_string(joule.join("reviews.json")).unwrap();
let reviews: Vec<SignedReview> = serde_json::from_str(&text).unwrap();
// the reviewer is a DIFFERENT principal than the author → reviews count
let for_op = |o: &SignedOp| -> Vec<SignedReview> {
let id = o.op.op_id().unwrap();
reviews.iter().filter(|r| r.review.op_id == id).cloned().collect()
};
assert!(approval(&good, &for_op(&good)).is_approved(), "the finished op is approved");
assert!(!approval(&bad, &for_op(&bad)).is_approved(), "the todo!() op is sent back");
assert!(!approval(&scope, &for_op(&scope)).is_approved(), "the non-goal op is sent back");
let _ = std::fs::remove_dir_all(&work);
let _: PathBuf = work; // silence unused on early-return paths
}
#[test]
fn the_reviewer_skips_ops_it_authored_itself() {
// give the binary a known persistent identity (its reviewer keyfile), then
// author an op with THAT principal: self-review, skipped, no reviews.
use joule_code_identity::{ActorKind, Identity};
let work = std::env::temp_dir().join(format!("joule-review-self-{}", std::process::id()));
let joule = work.join(".joule");
std::fs::create_dir_all(&joule).unwrap();
// the reviewer principal the binary will load from .joule/reviewer.key
let reviewer = Identity::generate("structural-reviewer", ActorKind::Agent);
reviewer.save(&joule.join("reviewer.key")).unwrap();
let spec: SignedSpec = Spec {
alg: SALG,
intent: "x".into(),
clauses: vec![Clause { id: "C1".into(), text: "a".into(), kind: ClauseKind::Requirement }],
parent: None,
author: sk(1).verifying_key().to_bytes(),
}
.sign(&sk(1))
.unwrap();
std::fs::write(joule.join("spec.adopted.json"), serde_json::to_string(&spec).unwrap()).unwrap();
let own = op(reviewer.signing_key(), "C1: x", "fn f() { ok(); }");
std::fs::write(joule.join("ops.json"), serde_json::to_string(&vec![own]).unwrap()).unwrap();
let status = Command::new(env!("CARGO_BIN_EXE_joule-review"))
.arg(&work)
.status()
.unwrap();
assert!(status.success());
let reviews: Vec<SignedReview> =
serde_json::from_str(&std::fs::read_to_string(joule.join("reviews.json")).unwrap()).unwrap();
assert!(reviews.is_empty(), "self-authored op yields no reviews");
let _ = std::fs::remove_dir_all(&work);
}
/// The full amortization loop, through the real binary and a real subprocess
/// model: run 1 escalates a clean-but-unsafe op to the model, which rejects it
/// and teaches a skill that persists to `.joule/review-skills.json`; run 2,
/// with NO model configured, catches a *recurrence* of the same defect at the
/// learned tier — the model's judgment, paid once, applied for free.
#[test]
fn the_model_teaches_a_skill_that_persists_and_catches_recurrences_model_free() {
use std::os::unix::fs::PermissionsExt;
let author = sk(1);
let work = std::env::temp_dir().join(format!("joule-review-learn-{}", std::process::id()));
let joule = work.join(".joule");
std::fs::create_dir_all(&joule).unwrap();
let spec: SignedSpec = Spec {
alg: SALG,
intent: "x".into(),
clauses: vec![Clause { id: "C1".into(), text: "run input".into(), kind: ClauseKind::Requirement }],
parent: None,
author: author.verifying_key().to_bytes(),
}
.sign(&author)
.unwrap();
std::fs::write(joule.join("spec.adopted.json"), serde_json::to_string(&spec).unwrap()).unwrap();
// a subprocess "model" that rejects eval( and names it as the inducible cause
let model = work.join("model.sh");
std::fs::write(
&model,
"#!/bin/sh\ncat >/dev/null\nprintf 'VERDICT: REQUEST_CHANGES\\nFINDINGS: eval on untrusted input\\nINDUCE: eval(\\n'\n",
)
.unwrap();
std::fs::set_permissions(&model, std::fs::Permissions::from_mode(0o755)).unwrap();
// run 1: a clean-but-unsafe op (passes structural, escalates to the model)
let unsafe1 = op(&author, "C1: run", "fn run() { eval(input); }");
std::fs::write(joule.join("ops.json"), serde_json::to_string(&vec![unsafe1.clone()]).unwrap()).unwrap();
let status = Command::new(env!("CARGO_BIN_EXE_joule-review"))
.arg(&work)
.env("JOULE_REVIEW_MODEL_CMD", &model)
.status()
.unwrap();
assert!(status.success());
let r1: Vec<SignedReview> =
serde_json::from_str(&std::fs::read_to_string(joule.join("reviews.json")).unwrap()).unwrap();
assert!(!approval(&unsafe1, &r1).is_approved()); // the model rejected it
// the skill was learned and persisted
let skills = std::fs::read_to_string(joule.join("review-skills.json")).unwrap();
assert!(skills.contains("eval("), "the eval( skill persisted: {skills}");
// run 2: a DIFFERENT op with the same defect, NO model configured at all
let unsafe2 = op(&author, "C1: run", "fn other() { eval(x); }");
std::fs::write(joule.join("ops.json"), serde_json::to_string(&vec![unsafe2.clone()]).unwrap()).unwrap();
let status = Command::new(env!("CARGO_BIN_EXE_joule-review"))
.arg(&work) // no JOULE_REVIEW_MODEL_CMD
.status()
.unwrap();
assert!(status.success());
let r2: Vec<SignedReview> =
serde_json::from_str(&std::fs::read_to_string(joule.join("reviews.json")).unwrap()).unwrap();
assert!(!approval(&unsafe2, &r2).is_approved()); // caught by the LEARNED tier, no model
let _ = std::fs::remove_dir_all(&work);
}