use serde::{Deserialize, Serialize};
pub const METHOD_REPAIR_PLAN: &str = "max/repairPlanSynth";
pub const METHOD_WHAT_IF: &str = "max/whatIf";
pub const STATUS_ADMITTED: &str = "ADMITTED";
pub const STATUS_PARTIAL: &str = "PARTIAL";
pub const STATUS_UNKNOWN: &str = "UNKNOWN";
pub const STATUS_REFUSED: &str = "REFUSED";
pub const STATUS_BLOCKED: &str = "BLOCKED";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepairStep {
pub order: usize,
pub action: String,
pub rationale: String,
pub verb: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepairPlanParams {
pub diagnostic_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepairPlanResult {
pub diagnostic_id: String,
pub status: String,
pub steps: Vec<RepairStep>,
pub repairability: String,
pub summary: String,
}
impl RepairPlanResult {
fn unknown(diagnostic_id: &str) -> Self {
Self {
diagnostic_id: diagnostic_id.to_string(),
status: STATUS_UNKNOWN.to_string(),
steps: Vec::new(),
repairability: "Unknown".to_string(),
summary: format!(
"no repair catalog entry for `{diagnostic_id}`; status UNKNOWN — \
admissibility cannot be determined and is not coerced to REFUSED or ADMITTED"
),
}
}
}
fn steps_from(raw: &[(&str, &str, Option<&str>)]) -> Vec<RepairStep> {
raw.iter()
.enumerate()
.map(|(i, (action, rationale, verb))| RepairStep {
order: i + 1,
action: (*action).to_string(),
rationale: (*rationale).to_string(),
verb: verb.map(str::to_string),
})
.collect()
}
pub fn repair_plan_for(diagnostic_id: &str) -> RepairPlanResult {
match diagnostic_id {
"WASM4PM-ANDON" | "WASM4PM-GATE" | "WASM4PM-GATE-BLOCKED" => RepairPlanResult {
diagnostic_id: diagnostic_id.to_string(),
status: STATUS_BLOCKED.to_string(),
steps: steps_from(&[
(
"Run the gate check to read the current ANDON state.",
"The ANDON signal is a one-byte gate; the check reports whether it is set \
before any further shell-side action is attempted.",
Some("gate check"),
),
(
"Resolve every active WASM4PM-* and GGEN-* Error-severity diagnostic.",
"Lambda_CD blocks while any governed Error is present in the diagnostic \
context; the gate clears only when that set drains.",
None,
),
(
"Re-run the gate check and confirm it reports clear before proceeding.",
"Re-reading the gate confirms the BLOCKED floor has lifted; status remains \
BLOCKED until the gate is observed clear.",
Some("gate check"),
),
]),
repairability: "Repairable".to_string(),
summary: "ANDON gate is active; status BLOCKED — resolve governed diagnostics and \
confirm the gate clears before any build, test, or release action"
.to_string(),
},
"TPOT2-NONCONVERGENCE" => RepairPlanResult {
diagnostic_id: diagnostic_id.to_string(),
status: STATUS_PARTIAL.to_string(),
steps: steps_from(&[
(
"Increase the number of generations the breed search evolves.",
"More generations give the optimizer additional rounds to climb toward the \
admission threshold the previous run fell short of.",
None,
),
(
"Increase the population size per generation.",
"A larger population widens the explored breed space, reducing the chance \
the search stalls in a below-threshold local optimum.",
None,
),
(
"Re-run the search and compare best observed fitness against the threshold.",
"The status stays PARTIAL until a re-run clears the bar; the comparison is \
what distinguishes PARTIAL from ADMITTED.",
None,
),
]),
repairability: "Repairable".to_string(),
summary: "breed search ended below the admission threshold; status PARTIAL — widen \
the search (more generations / larger population) and re-run"
.to_string(),
},
"TPOT2-EMPTY-POOL" => RepairPlanResult {
diagnostic_id: diagnostic_id.to_string(),
status: STATUS_REFUSED.to_string(),
steps: steps_from(&[
(
"Inspect the breed catalog to confirm whether any breeds are registered.",
"An empty pool is a REFUSED outcome; the first step is to verify the catalog \
is the cause rather than a filter excluding every entry.",
None,
),
(
"Repopulate the breed pool with at least one candidate before searching.",
"With no breeds there is nothing to evaluate; admission is impossible until \
the pool is non-empty.",
None,
),
]),
repairability: "Repairable".to_string(),
summary: "breed pool is empty; status REFUSED — check the catalog and repopulate the \
pool before a search can yield any admissible breed"
.to_string(),
},
_ => RepairPlanResult::unknown(diagnostic_id),
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WhatIfParams {
pub andon_active: bool,
pub unknown_axes: usize,
pub refused_axes: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WhatIfResult {
pub admission: String,
pub rationale: String,
}
pub fn simulate_admission(p: &WhatIfParams) -> WhatIfResult {
if p.andon_active {
return WhatIfResult {
admission: STATUS_BLOCKED.to_string(),
rationale: "an ANDON signal is active; status BLOCKED — it is the highest-precedence \
floor and no admission verdict is reached while it is set"
.to_string(),
};
}
if p.refused_axes > 0 {
return WhatIfResult {
admission: STATUS_REFUSED.to_string(),
rationale: format!(
"{} law axis/axes are explicitly refused; status REFUSED — refusal dominates \
any unknown or admitted axes",
p.refused_axes
),
};
}
if p.unknown_axes > 0 {
return WhatIfResult {
admission: STATUS_UNKNOWN.to_string(),
rationale: format!(
"{} law axis/axes are undetermined; status UNKNOWN — this is never coerced to \
ADMITTED or REFUSED, even when every other axis is admitted",
p.unknown_axes
),
};
}
WhatIfResult {
admission: STATUS_ADMITTED.to_string(),
rationale: "no ANDON signal, no refused axes, and no unknown axes; status ADMITTED"
.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_code_yields_ordered_bounded_plan() {
let plan = repair_plan_for("TPOT2-NONCONVERGENCE");
assert!(!plan.steps.is_empty(), "a known code must produce steps");
assert_eq!(plan.status, STATUS_PARTIAL);
for (i, step) in plan.steps.iter().enumerate() {
assert_eq!(step.order, i + 1, "step order must be 1-based contiguous");
}
assert!([
STATUS_ADMITTED,
STATUS_PARTIAL,
STATUS_UNKNOWN,
STATUS_REFUSED,
STATUS_BLOCKED,
]
.contains(&plan.status.as_str()));
}
#[test]
fn andon_code_is_blocked_and_routes_to_gate() {
let plan = repair_plan_for("WASM4PM-ANDON");
assert_eq!(plan.status, STATUS_BLOCKED);
assert!(!plan.steps.is_empty());
assert!(
plan.steps
.iter()
.any(|s| s.verb.as_deref() == Some("gate check")),
"an ANDON plan must route the agent to `gate check`"
);
}
#[test]
fn empty_pool_code_is_refused() {
let plan = repair_plan_for("TPOT2-EMPTY-POOL");
assert_eq!(plan.status, STATUS_REFUSED);
assert!(!plan.steps.is_empty());
}
#[test]
fn unknown_code_yields_unknown_and_empty_steps() {
let plan = repair_plan_for("NOT-A-REAL-DIAGNOSTIC-CODE");
assert_eq!(plan.status, STATUS_UNKNOWN);
assert!(
plan.steps.is_empty(),
"an unrecognized code must not fabricate any repair step"
);
assert_ne!(plan.status, STATUS_REFUSED);
assert_ne!(plan.status, STATUS_ADMITTED);
assert_eq!(plan.repairability, "Unknown");
}
#[test]
fn what_if_unknown_axis_stays_unknown() {
let r = simulate_admission(&WhatIfParams {
andon_active: false,
unknown_axes: 1,
refused_axes: 0,
});
assert_eq!(r.admission, STATUS_UNKNOWN);
assert_ne!(r.admission, STATUS_ADMITTED);
assert_ne!(r.admission, STATUS_REFUSED);
}
#[test]
fn what_if_precedence_holds() {
let blocked = simulate_admission(&WhatIfParams {
andon_active: true,
unknown_axes: 3,
refused_axes: 3,
});
assert_eq!(blocked.admission, STATUS_BLOCKED);
let refused = simulate_admission(&WhatIfParams {
andon_active: false,
unknown_axes: 3,
refused_axes: 1,
});
assert_eq!(refused.admission, STATUS_REFUSED);
let unknown = simulate_admission(&WhatIfParams {
andon_active: false,
unknown_axes: 1,
refused_axes: 0,
});
assert_eq!(unknown.admission, STATUS_UNKNOWN);
let admitted = simulate_admission(&WhatIfParams {
andon_active: false,
unknown_axes: 0,
refused_axes: 0,
});
assert_eq!(admitted.admission, STATUS_ADMITTED);
}
}