use super::clean_overlay_planner::{
CleanOverlayManifest, CleanOverlayRequest, ExcludedPath, ExclusionReason, plan_clean_overlay,
};
use super::overlay_proof_command::OverlayProofCommand;
use super::proof_traffic_receipt::ProofTrafficDecision;
use serde::{Deserialize, Serialize};
pub const PROOF_TRAFFIC_OVERLAY_HANDSHAKE_SCHEMA_VERSION: &str =
"proof-traffic-clean-overlay-handshake-v1";
const FORBIDDEN_COMMAND_TOKENS: &[&str] = &[
"|| cargo",
"; cargo",
"\ncargo ",
"run cargo locally",
"git branch",
"git checkout -b",
"git switch -c",
"git worktree",
"worktree add",
"git clone",
"git clean",
"git reset",
"rm -rf",
"rm -r ",
"rm -f ",
];
const NO_CLAIM_BOUNDARIES: &[&str] = &[
"No release-readiness claim.",
"No broad workspace-health claim.",
"No runtime-correctness claim.",
"No performance-improvement claim.",
"No live RCH fleet-availability claim.",
"No local Cargo fallback approval.",
"No peer-owned build cancellation authority.",
"No permission to delete files, clean worktrees, create branches, or create worktrees.",
"No claim that peer dirt was excluded unless the installed RCH clean-overlay capability is supported.",
];
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProofTrafficOverlayCapability {
pub capability_probe_version: String,
pub clean_overlay_supported: bool,
pub missing_flags: Vec<String>,
pub capability_findings: Vec<String>,
}
impl ProofTrafficOverlayCapability {
#[must_use]
pub fn new(
capability_probe_version: impl Into<String>,
clean_overlay_supported: bool,
missing_flags: Vec<String>,
capability_findings: Vec<String>,
) -> Self {
Self {
capability_probe_version: capability_probe_version.into(),
clean_overlay_supported,
missing_flags: sorted_unique(missing_flags),
capability_findings: sorted_unique(capability_findings),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProofTrafficOverlayHandshakeInput {
pub gate_id: String,
pub request: CleanOverlayRequest,
pub target_dir: String,
pub capability: ProofTrafficOverlayCapability,
}
impl ProofTrafficOverlayHandshakeInput {
#[must_use]
pub fn new(
gate_id: impl Into<String>,
request: CleanOverlayRequest,
target_dir: impl Into<String>,
capability: ProofTrafficOverlayCapability,
) -> Self {
Self {
gate_id: gate_id.into(),
request,
target_dir: target_dir.into(),
capability,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProofTrafficOverlayHandshake {
pub schema_version: String,
pub gate_id: String,
pub decision: ProofTrafficDecision,
pub head_commit: String,
pub command_intent: String,
pub target_dir: String,
pub selected_paths: Vec<String>,
pub included_paths: Vec<String>,
pub excluded_paths: Vec<ExcludedPath>,
pub reservation_evidence: Vec<String>,
pub capability_probe_version: String,
pub clean_overlay_supported: bool,
pub missing_flags: Vec<String>,
pub capability_findings: Vec<String>,
pub rendered_command: String,
pub admitted: bool,
pub report_only: bool,
pub retry_condition: String,
pub no_claim_boundaries: Vec<String>,
}
impl ProofTrafficOverlayHandshake {
#[must_use]
pub fn from_input(input: &ProofTrafficOverlayHandshakeInput) -> Self {
let manifest = plan_clean_overlay(&input.request);
let decision = classify(&manifest, &input.capability);
let rendered_command = rendered_command(&manifest, &input.target_dir, &input.capability);
let admitted = matches!(decision, ProofTrafficDecision::RunNow);
let retry_condition = retry_condition(&manifest, &input.capability, decision);
Self {
schema_version: PROOF_TRAFFIC_OVERLAY_HANDSHAKE_SCHEMA_VERSION.to_string(),
gate_id: input.gate_id.clone(),
decision,
head_commit: manifest.head_commit.clone(),
command_intent: manifest.command_intent.clone(),
target_dir: input.target_dir.clone(),
selected_paths: manifest.selected_paths.clone(),
included_paths: manifest.included_paths.clone(),
excluded_paths: manifest.excluded_paths.clone(),
reservation_evidence: manifest.reservation_evidence.clone(),
capability_probe_version: input.capability.capability_probe_version.clone(),
clean_overlay_supported: input.capability.clean_overlay_supported,
missing_flags: input.capability.missing_flags.clone(),
capability_findings: input.capability.capability_findings.clone(),
rendered_command,
admitted,
report_only: manifest.report_only,
retry_condition,
no_claim_boundaries: NO_CLAIM_BOUNDARIES
.iter()
.map(|boundary| (*boundary).to_string())
.collect(),
}
}
#[must_use]
pub fn render_markdown(&self) -> String {
let mut out = String::new();
out.push_str("## Proof-traffic clean-overlay handshake - ");
out.push_str(self.decision.label());
out.push_str("\n\n");
self.push_handoff_fields(&mut out);
out.push_str("\n### rendered_command\n```sh\n");
out.push_str(&self.rendered_command);
out.push_str("\n```\n\n");
push_path_section(&mut out, "selected_paths", &self.selected_paths);
push_path_section(&mut out, "included_paths", &self.included_paths);
push_excluded_section(&mut out, &self.excluded_paths);
push_path_section(&mut out, "reservation_evidence", &self.reservation_evidence);
push_string_section(&mut out, "missing_flags", &self.missing_flags);
push_string_section(&mut out, "capability_findings", &self.capability_findings);
push_string_section(&mut out, "no_claim_boundaries", &self.no_claim_boundaries);
out
}
#[must_use]
pub fn agent_mail_body(&self) -> String {
let mut out = String::new();
out.push_str("proof_traffic_clean_overlay_handshake:\n");
self.push_handoff_fields(&mut out);
out
}
#[must_use]
pub fn br_comment_body(&self) -> String {
let mut out = String::new();
out.push_str("Proof-traffic clean-overlay handshake\n\n");
self.push_handoff_fields(&mut out);
out
}
#[must_use]
pub fn forbidden_command_tokens(&self) -> Vec<&'static str> {
let surface = self.rendered_command.to_ascii_lowercase();
FORBIDDEN_COMMAND_TOKENS
.iter()
.copied()
.filter(|token| surface.contains(token))
.collect()
}
#[must_use]
pub fn uses_local_cargo_fallback(&self) -> bool {
let surface = self.rendered_command.to_ascii_lowercase();
surface.contains("|| cargo")
|| surface.contains("; cargo")
|| surface.contains("\ncargo ")
|| surface.contains("run cargo locally")
|| surface.contains("local fallback allowed")
|| (surface.contains("cargo") && !surface.contains("rch exec"))
}
fn push_handoff_fields(&self, out: &mut String) {
out.push_str("- gate_id: `");
out.push_str(&self.gate_id);
out.push_str("`\n- status: `");
out.push_str(self.decision.label());
out.push_str("`\n- head_commit: `");
out.push_str(&self.head_commit);
out.push_str("`\n- command_intent: `");
out.push_str(&self.command_intent);
out.push_str("`\n- target_dir: `");
out.push_str(&self.target_dir);
out.push_str("`\n- clean_overlay_supported: `");
out.push_str(if self.clean_overlay_supported {
"true"
} else {
"false"
});
out.push_str("`\n- capability_probe_version: `");
out.push_str(&self.capability_probe_version);
out.push_str("`\n- admitted: `");
out.push_str(if self.admitted { "true" } else { "false" });
out.push_str("`\n- report_only: `");
out.push_str(if self.report_only { "true" } else { "false" });
out.push_str("`\n- retry_condition: ");
out.push_str(&self.retry_condition);
out.push_str("\n- local_cargo_fallback_allowed: `false`\n");
out.push_str("- peer_build_cancellation_allowed: `false`\n");
out.push_str("- branch_or_worktree_allowed: `false`\n");
out.push_str("- file_deletion_allowed: `false`\n");
}
}
fn classify(
manifest: &CleanOverlayManifest,
capability: &ProofTrafficOverlayCapability,
) -> ProofTrafficDecision {
if manifest.report_only {
return ProofTrafficDecision::ReportOnly;
}
if !capability.clean_overlay_supported {
return ProofTrafficDecision::BlockedByCapabilityDrift;
}
if manifest.blocked {
return if manifest
.excluded_paths
.iter()
.any(|excluded| excluded.reason == ExclusionReason::PeerDirtyUnselected)
{
ProofTrafficDecision::BlockedByPeer
} else {
ProofTrafficDecision::ParkRerunRequired
};
}
if manifest.selected_paths.is_empty() {
return ProofTrafficDecision::ParkRerunRequired;
}
ProofTrafficDecision::RunNow
}
fn rendered_command(
manifest: &CleanOverlayManifest,
target_dir: &str,
capability: &ProofTrafficOverlayCapability,
) -> String {
if manifest.report_only {
return "# REPORT-ONLY: clean-overlay handshake dry run; no proof command emitted"
.to_string();
}
if !capability.clean_overlay_supported {
return "# BLOCKED: installed RCH clean-overlay capability unsupported; no proof command emitted"
.to_string();
}
OverlayProofCommand::from_manifest_with_target(manifest, target_dir).rendered_command()
}
fn retry_condition(
manifest: &CleanOverlayManifest,
capability: &ProofTrafficOverlayCapability,
decision: ProofTrafficDecision,
) -> String {
match decision {
ProofTrafficDecision::RunNow => {
"none; selected paths are reserved and installed clean-overlay capability is supported"
.to_string()
}
ProofTrafficDecision::ReportOnly => "report-only; no proof command emitted".to_string(),
ProofTrafficDecision::BlockedByCapabilityDrift => {
let missing = capability.missing_flags.join(",");
format!("rerun after installed RCH exposes clean-overlay flags [{missing}]")
}
ProofTrafficDecision::BlockedByPeer => {
"rerun after peer-dirty unselected paths are cleared or selected by their owner"
.to_string()
}
ProofTrafficDecision::ParkRerunRequired => {
if manifest.selected_paths.is_empty() {
"rerun with at least one selected path".to_string()
} else if manifest
.excluded_paths
.iter()
.any(|excluded| excluded.reason == ExclusionReason::DeletedSelectionRefused)
{
"rerun with a non-deleted selected path; clean-overlay cannot prove removals"
.to_string()
} else {
"rerun after selected dirty/untracked paths have exclusive self reservations"
.to_string()
}
}
ProofTrafficDecision::QueueWait | ProofTrafficDecision::RemoteRequiredRefused => {
"not used by clean-overlay handshake".to_string()
}
}
}
fn push_path_section(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');
}
fn push_string_section(out: &mut String, title: &str, values: &[String]) {
out.push_str(&format!("### {title} ({})\n", values.len()));
if values.is_empty() {
out.push_str("- _none_\n");
} else {
for value in values {
out.push_str("- ");
out.push_str(value);
out.push('\n');
}
}
out.push('\n');
}
fn push_excluded_section(out: &mut String, excluded_paths: &[ExcludedPath]) {
out.push_str(&format!("### excluded_paths ({})\n", excluded_paths.len()));
if excluded_paths.is_empty() {
out.push_str("- _none_\n");
} else {
for excluded in 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');
}
const fn exclusion_label(reason: ExclusionReason) -> &'static str {
match reason {
ExclusionReason::PeerDirtyUnselected => "peer-dirty-unselected",
ExclusionReason::UnreservedSelection => "unreserved-selection",
ExclusionReason::DeletedSelectionRefused => "deleted-selection-refused",
}
}
fn sorted_unique(mut values: Vec<String>) -> Vec<String> {
values.sort();
values.dedup();
values
}