118 lines
3.6 KiB
Rust
118 lines
3.6 KiB
Rust
use std::fs;
|
|
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct G6HostBridgeEntryGate {
|
|
#[serde(rename = "decisionDate")]
|
|
decision_date: String,
|
|
scope: String,
|
|
#[serde(rename = "startingState")]
|
|
starting_state: StartingState,
|
|
#[serde(rename = "hardGateConditions")]
|
|
hard_gate_conditions: Vec<HardGateCondition>,
|
|
#[serde(rename = "softConditions")]
|
|
soft_conditions: Vec<SoftCondition>,
|
|
#[serde(rename = "failCloseReasons")]
|
|
fail_close_reasons: Vec<String>,
|
|
#[serde(rename = "selectedFollowup")]
|
|
selected_followup: SelectedFollowup,
|
|
notes: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct StartingState {
|
|
#[serde(rename = "targetGroup")]
|
|
target_group: String,
|
|
#[serde(rename = "realExecutionOutOfScope")]
|
|
real_execution_out_of_scope: bool,
|
|
#[serde(rename = "implementationOutOfScope")]
|
|
implementation_out_of_scope: bool,
|
|
#[serde(rename = "heldGroups")]
|
|
held_groups: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct HardGateCondition {
|
|
name: String,
|
|
status: String,
|
|
#[serde(rename = "failureReason")]
|
|
failure_reason: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct SoftCondition {
|
|
name: String,
|
|
status: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct SelectedFollowup {
|
|
design: String,
|
|
plan: String,
|
|
}
|
|
|
|
#[test]
|
|
fn g6_host_bridge_entry_gate_stays_bounded() {
|
|
let asset: G6HostBridgeEntryGate = serde_json::from_str(
|
|
&fs::read_to_string(
|
|
"tests/fixtures/generated_scene/g6_host_bridge_entry_gate_2026-04-19.json",
|
|
)
|
|
.unwrap(),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(asset.decision_date, "2026-04-19");
|
|
assert_eq!(asset.scope, "g6-host-bridge-entry-gate");
|
|
assert_eq!(asset.starting_state.target_group, "G6");
|
|
assert!(asset.starting_state.real_execution_out_of_scope);
|
|
assert!(asset.starting_state.implementation_out_of_scope);
|
|
assert_eq!(asset.starting_state.held_groups, vec!["G8"]);
|
|
|
|
assert!(asset
|
|
.hard_gate_conditions
|
|
.iter()
|
|
.any(|item| item.name == "host-bridge-action-invocation-defined"
|
|
&& item.status == "required"
|
|
&& item.failure_reason == "g6_bridge_invocation_semantics_missing"));
|
|
assert!(asset
|
|
.hard_gate_conditions
|
|
.iter()
|
|
.any(|item| item.name == "callback-request-completion-defined"
|
|
&& item.status == "required"
|
|
&& item.failure_reason == "g6_callback_completion_semantics_missing"));
|
|
assert!(asset.hard_gate_conditions.iter().any(|item| item.name
|
|
== "callback-state-verification-targets-defined"
|
|
&& item.status == "required"
|
|
&& item.failure_reason == "g6_callback_state_targets_missing"));
|
|
|
|
assert!(asset
|
|
.soft_conditions
|
|
.iter()
|
|
.any(|item| item.name == "host-runtime-transport-implementation"
|
|
&& item.status == "optional-later"));
|
|
assert!(asset
|
|
.soft_conditions
|
|
.iter()
|
|
.any(|item| item.name == "real-sample-execution-proof" && item.status == "optional-later"));
|
|
|
|
assert_eq!(
|
|
asset.fail_close_reasons,
|
|
vec![
|
|
"g6_bridge_invocation_semantics_missing",
|
|
"g6_callback_completion_semantics_missing",
|
|
"g6_callback_state_targets_missing"
|
|
]
|
|
);
|
|
|
|
assert!(asset
|
|
.selected_followup
|
|
.design
|
|
.ends_with("2026-04-19-g6-host-bridge-entry-gate-verification-design.md"));
|
|
assert!(asset
|
|
.selected_followup
|
|
.plan
|
|
.ends_with("2026-04-19-g6-host-bridge-entry-gate-verification-plan.md"));
|
|
assert!(!asset.notes.is_empty());
|
|
}
|