The review gate checks that an op carries an independent two-stage approval; this crate produces one. A Reviewer is a distinct principal (its own signing key) that makes a real, falsifiable judgment of an op against its spec — not a rubber stamp. Two invariants keep it honest: - Independence enforced AT THE SOURCE: Reviewer::review refuses (SelfReview error) to review an op whose author == the reviewer's key. A principal cannot review its own work — human or agent — and the reviewer won't sign in the first place, not merely fail the audit later. - The judgment can FAIL: a reviewer that always approves is a stamp. Spec-compliance sends back an op that cites no clause, cites a NON-GOAL (out-of-scope), or makes no edits; quality sends back one that writes nothing or ships an unfinished marker (todo!(), unimplemented!(), FIXME). Two-stage order is honored — quality is not assessed on non-compliant work. This is the STRUCTURAL reviewer: the cheapest sufficient review tier — deterministic, reproducible, model-free, checking what a machine can check for certain. A semantic reviewer (does the code mean what the clause asks?) is the escalation tier above it: another distinct principal's model judgment, signing reviews with its own key, counted identically by the gate. Whoever the reviewer is — agent or human — its key is the trace. Its output is exactly what agent-zed ingests from .joule/reviews.json, closing the loop: an independent agent can now satisfy the review gate end to end. Runnable: `cargo run -p joule-code-reviewer --example review` (approves a finished op, sends back a todo!() and a non-goal, refuses self-review). 4 tests; example + clippy clean. Co-Authored-By: Claude Opus 4.8 <[email protected]>
84 lines
3.2 KiB
Rust
84 lines
3.2 KiB
Rust
//! The independent reviewer agent at work: a separate principal judges a batch
|
|
//! of ops against a spec and signs the reviews — some pass, some are sent back.
|
|
//!
|
|
//! Run: `cargo run -p joule-code-reviewer --example review`
|
|
|
|
use ed25519_dalek::SigningKey;
|
|
use joule_code_cargo::{Anchor, CodingOp, Edit, SignedOp};
|
|
use joule_code_review::{approval, ReviewVerdict};
|
|
use joule_code_schema::{ContentId, Tier};
|
|
use joule_code_reviewer::Reviewer;
|
|
use joule_code_spec::{Clause, ClauseKind, SignedSpec, Spec, ALG_ED25519 as SALG};
|
|
|
|
fn key(s: u8) -> SigningKey {
|
|
SigningKey::from_bytes(&[s; 32])
|
|
}
|
|
|
|
fn op(author: &SigningKey, 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: "implement".into(),
|
|
tier: Tier::L3,
|
|
}
|
|
.sign(author)
|
|
.unwrap()
|
|
}
|
|
|
|
fn main() {
|
|
let author = key(1); // the authoring principal
|
|
let reviewer = Reviewer::new(key(2)); // a DISTINCT, independent principal
|
|
|
|
let spec: SignedSpec = Spec {
|
|
alg: SALG,
|
|
intent: "a persistent todo list".into(),
|
|
clauses: vec![
|
|
Clause { id: "C1".into(), text: "todos persist across reloads".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();
|
|
|
|
let cases: &[(&str, &str, &[&str])] = &[
|
|
("a finished op implementing C1", "fn save() { write_to_disk(); }", &["C1"]),
|
|
("an op shipping an unfinished marker", "fn save() { todo!() }", &["C1"]),
|
|
("an op implementing a non-goal", "fn multiplayer() {}", &["NG1"]),
|
|
];
|
|
|
|
for (label, body, clauses) in cases {
|
|
let o = op(&author, body);
|
|
let claimed: Vec<String> = clauses.iter().map(|c| c.to_string()).collect();
|
|
let reviews = reviewer.review(&o, &spec, &claimed).unwrap();
|
|
let verdict = if approval(&o, &reviews).is_approved() { "✓ APPROVED" } else { "⛔ SENT BACK" };
|
|
println!("{label}\n {verdict} (reviewer principal {}…)", &hex8(reviewer.principal()));
|
|
for r in &reviews {
|
|
let mark = if r.review.verdict == ReviewVerdict::Approve { "✓" } else { "✗" };
|
|
print!(" {mark} {:?}", r.review.stage);
|
|
if !r.review.findings.is_empty() {
|
|
print!(" — {}", r.review.findings.join("; "));
|
|
}
|
|
println!();
|
|
}
|
|
println!();
|
|
}
|
|
|
|
// independence is enforced at the source, not just the audit:
|
|
let own = op(&key(2), "fn f() {}"); // authored by the reviewer's own principal
|
|
match reviewer.review(&own, &spec, &["C1".to_string()]) {
|
|
Err(e) => println!("self-review attempt → refused: {e}"),
|
|
Ok(_) => println!("self-review (should not happen)"),
|
|
}
|
|
}
|
|
|
|
fn hex8(k: [u8; 32]) -> String {
|
|
k[..4].iter().map(|b| format!("{b:02x}")).collect()
|
|
}
|