use super::clean_overlay_planner::{CleanOverlayManifest, ExcludedPath, ExclusionReason};
use serde::{Deserialize, Serialize};
pub const DEFAULT_TARGET_DIR: &str = "/data/tmp/rch_target_asupersync_test";
const FORBIDDEN_TOKENS: &[&str] = &[
"git branch",
"git worktree",
"worktree add",
"git clone",
"git clean",
"git reset",
"git checkout -b",
"rm -rf",
"rm -r ",
"rm -f ",
];
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OverlayProofCommand {
pub head_commit: String,
pub target_dir: String,
pub validation_intent: String,
pub selected_paths: Vec<String>,
pub overlay_paths: Vec<String>,
pub excluded_paths: Vec<ExcludedPath>,
pub reservation_evidence: Vec<String>,
pub admitted: bool,
pub report_only: bool,
pub fail_closed_path_count: usize,
pub no_claim_boundaries: Vec<String>,
}
impl OverlayProofCommand {
#[must_use]
pub fn from_manifest(manifest: &CleanOverlayManifest) -> Self {
Self::from_manifest_with_target(manifest, DEFAULT_TARGET_DIR)
}
#[must_use]
pub fn from_manifest_with_target(manifest: &CleanOverlayManifest, target_dir: &str) -> Self {
let fail_closed_path_count = manifest
.excluded_paths
.iter()
.filter(|excluded| is_fail_closed(excluded.reason))
.count();
let admitted =
!manifest.blocked && !manifest.report_only && !manifest.selected_paths.is_empty();
Self {
head_commit: manifest.head_commit.clone(),
target_dir: target_dir.to_string(),
validation_intent: manifest.command_intent.clone(),
selected_paths: manifest.selected_paths.clone(),
overlay_paths: manifest.included_paths.clone(),
excluded_paths: manifest.excluded_paths.clone(),
reservation_evidence: manifest.reservation_evidence.clone(),
admitted,
report_only: manifest.report_only,
fail_closed_path_count,
no_claim_boundaries: manifest.no_claim_boundaries.clone(),
}
}
#[must_use]
pub fn overlay_path_flags(&self) -> String {
self.overlay_paths
.iter()
.map(|path| format!("--overlay-path {path}"))
.collect::<Vec<_>>()
.join(" ")
}
#[must_use]
pub fn rendered_command(&self) -> String {
if !self.admitted {
if self.report_only {
return format!(
"# REPORT-ONLY: clean-overlay dry run; no RCH proof command emitted ({} path(s) would fail closed)",
self.fail_closed_path_count
);
}
return format!(
"# BLOCKED: clean-overlay refused; no RCH proof command emitted ({} fail-closed path(s))",
self.fail_closed_path_count
);
}
let flags = self.overlay_path_flags();
let base = format!(
"RCH_REQUIRE_REMOTE=1 rch exec --base {} --clean-overlay",
self.head_commit
);
let scope = if flags.is_empty() {
"--no-overlay".to_string()
} else {
flags
};
format!(
"{base} {scope} -- env CARGO_TARGET_DIR={} {}",
self.target_dir, self.validation_intent
)
}
#[must_use]
pub fn reproduction_command(&self) -> String {
if self.admitted {
return self.rendered_command();
}
format!(
"RCH_REQUIRE_REMOTE=1 rch exec -- env CARGO_TARGET_DIR={} \
cargo test --test proof_orch_clean_overlay_e2e -- --nocapture",
self.target_dir
)
}
#[must_use]
pub fn forbidden_operations(&self) -> Vec<&'static str> {
let surface = format!(
"{}\n{}",
self.rendered_command(),
self.reproduction_command()
);
FORBIDDEN_TOKENS
.iter()
.copied()
.filter(|token| surface.contains(token))
.collect()
}
#[must_use]
pub fn uses_local_cargo_fallback(&self) -> bool {
let surface = format!(
"{}\n{}",
self.rendered_command(),
self.reproduction_command()
);
surface.contains("|| cargo")
|| surface.contains("; cargo")
|| surface.contains("locally")
|| surface.contains("local fallback")
|| (surface.contains("cargo") && !surface.contains("rch exec"))
}
#[must_use]
pub fn has_exclusion(&self, reason: ExclusionReason) -> bool {
self.excluded_paths
.iter()
.any(|excluded| excluded.reason == reason)
}
#[must_use]
pub fn render_report(&self) -> String {
let mut out = String::new();
out.push_str("## Clean-overlay focused proof — ");
out.push_str(if self.admitted {
"admitted"
} else if self.report_only {
"report-only"
} else {
"blocked (fail-closed)"
});
out.push_str("\n\n- HEAD: `");
out.push_str(&self.head_commit);
out.push_str("`\n- Lane: RCH-only; no local Cargo fallback\n- Validation intent: `");
out.push_str(&self.validation_intent);
out.push_str("`\n- Exact RCH command:\n```sh\n");
out.push_str(&self.rendered_command());
out.push_str("\n```\n- Reproduction command:\n```sh\n");
out.push_str(&self.reproduction_command());
out.push_str("\n```\n\n");
push_path_list(&mut out, "Selected paths", &self.selected_paths);
push_path_list(&mut out, "Overlay (included) paths", &self.overlay_paths);
out.push_str(&format!(
"### Excluded paths ({})\n",
self.excluded_paths.len()
));
if self.excluded_paths.is_empty() {
out.push_str("- _none_\n");
} else {
for excluded in &self.excluded_paths {
out.push_str("- `");
out.push_str(&excluded.path);
out.push_str("` — ");
out.push_str(exclusion_label(excluded.reason));
out.push('\n');
}
}
out.push('\n');
push_path_list(&mut out, "Reservation evidence", &self.reservation_evidence);
out.push_str("### No-claim boundaries\n");
if self.no_claim_boundaries.is_empty() {
out.push_str("- _none recorded_\n");
} else {
for boundary in &self.no_claim_boundaries {
out.push_str("- ");
out.push_str(boundary);
out.push('\n');
}
}
out
}
}
const fn is_fail_closed(reason: ExclusionReason) -> bool {
matches!(
reason,
ExclusionReason::PeerDirtyUnselected
| ExclusionReason::UnreservedSelection
| ExclusionReason::DeletedSelectionRefused
)
}
fn push_path_list(out: &mut String, title: &str, paths: &[String]) {
out.push_str(&format!("### {title} ({})\n", paths.len()));
if paths.is_empty() {
out.push_str("- _none_\n");
} else {
for path in paths {
out.push_str("- `");
out.push_str(path);
out.push_str("`\n");
}
}
out.push('\n');
}
const fn exclusion_label(reason: ExclusionReason) -> &'static str {
match reason {
ExclusionReason::PeerDirtyUnselected => "peer-dirty (unselected) — excluded from overlay",
ExclusionReason::UnreservedSelection => "unreserved selection (no held lease)",
ExclusionReason::DeletedSelectionRefused => {
"deleted selection (an overlay cannot prove a removal)"
}
}
}