Add desktop reset history checks and native wiring fixtures

This commit is contained in:
2026-09-24 19:18:31 -07:00
parent 6c44a2d6a1
commit 9eb4642e50
2 changed files with 421 additions and 0 deletions
@@ -0,0 +1,263 @@
//! Native UI wiring fixture/oracle. Expected output comes from candidate Layout,
//! not from an independent geometry algorithm. Run only after parent source freeze.
use oa_core::*;
use serde_json::{Value, json};
use std::{collections::BTreeMap, error::Error, fs, path::PathBuf};
fn id(n: u128) -> Id {
Id::from_u128(700_000 + n)
}
fn at(x: f32, y: f32) -> Position {
Position { x, y }
}
fn function(p: &mut Project, n: u128, name: &str, parent: Option<Id>) -> Id {
let old = p
.add_element(Kind::Function, Layer::Sa, name, parent)
.unwrap();
reidentify(p, old, id(n)).unwrap();
id(n)
}
fn place(p: &mut Project, d: Id, n: u128, element: Id, position: Position, size: Size) {
let old = p.place(d, element, position);
reidentify(p, old, id(n)).unwrap();
let node = p
.diagrams
.get_mut(&d)
.unwrap()
.nodes
.get_mut(&id(n))
.unwrap();
node.alias = format!("placement_{n}");
node.size = size;
}
fn exchange(p: &mut Project, n: u128, name: &str, source: Id, target: Id) -> Id {
let request = FunctionalExchangeRequest {
id: id(n),
alias: format!("exchange_{n}"),
name: name.into(),
description: String::new(),
source,
target,
source_port: PortChoice::Create,
target_port: PortChoice::Create,
items: vec![],
};
let commands = ports::plan_functional_exchange(p, &request).unwrap();
*p = execute_batch(p, &commands).unwrap();
id(n)
}
fn route(edge: Id, waypoints: Vec<Position>, fraction: f32, offset: Position) -> EdgeRoute {
EdgeRoute {
edge,
source_attachment: None,
target_attachment: None,
waypoints,
label: Some(EdgeLabel { fraction, offset }),
}
}
fn original() -> (Project, Id, Id, Value) {
let mut p = Project::empty();
p.id = id(0);
p.alias = "arrange_native_fixture".into();
p.name = "Arrange route reset trial".into();
let old = p.ensure_diagram(Layer::Sa);
let main = id(1);
reidentify(&mut p, old, main).unwrap();
{
let d = p.diagrams.get_mut(&main).unwrap();
d.alias = "main_dispatch".into();
d.name = "Main dispatch".into();
d.projection = ProjectionKind::FunctionalDataflow;
}
let group = function(&mut p, 10, "Prepare report", None);
let send = function(&mut p, 11, "Send report", Some(group));
let check = function(&mut p, 12, "Check report", Some(group));
let monitor = function(&mut p, 13, "Monitor report", None);
let archive = function(&mut p, 14, "Archive report", None);
let card = Size {
width: 224.,
height: 94.,
};
place(
&mut p,
main,
20,
group,
at(40., 80.),
Size {
width: 400.,
height: 420.,
},
);
for (n, element, x, y) in [
(21, send, 80., 160.),
(22, check, 80., 330.),
(23, monitor, 740., 80.),
(24, archive, 740., 380.),
] {
place(&mut p, main, n, element, at(x, y), card);
}
let authored = exchange(&mut p, 100, "Verified report", send, monitor);
exchange(&mut p, 101, "Report for checking", send, check);
exchange(&mut p, 102, "Checked report archive", check, archive);
let hidden = exchange(
&mut p,
103,
"Filtered archive acknowledgement",
monitor,
archive,
);
let RelationBody::FunctionalExchange {
source_port,
target_port,
..
} = p.relations[&authored].body
else {
unreachable!()
};
for (node, port, side, offset) in [
(id(21), source_port, PortAnchorSide::Right, 0.25),
(id(23), target_port, PortAnchorSide::Left, 0.75),
] {
p = prepare_command(
&p,
&Command::SetPortAnchor {
diagram: main,
node,
anchor: PortAnchor { port, side, offset },
},
)
.unwrap()
.project;
}
let mut visible = route(
authored,
vec![at(610., 210.), at(610., 420.)],
0.5,
at(0., -32.),
);
// Real semantic ports remain authoritative; these stored preferences are dormant.
visible.source_attachment = Some(EdgeAttachment {
side: PortAnchorSide::Bottom,
offset: 0.5,
});
visible.target_attachment = Some(EdgeAttachment {
side: PortAnchorSide::Top,
offset: 0.25,
});
let filtered = route(hidden, vec![at(1020., 270.)], 0.75, at(16., -16.));
p.diagrams.get_mut(&main).unwrap().routes = vec![visible, filtered];
p.diagrams.get_mut(&main).unwrap().view_options.hidden_edges = vec![hidden];
let second = id(2);
p.diagrams.insert(
second,
Diagram {
id: second,
alias: "review_sentinel".into(),
name: "Review sentinel".into(),
description:
"Independent other-view route; Arrange Main dispatch must retain this entire view"
.into(),
layer: Layer::Sa,
projection: ProjectionKind::FunctionalDataflow,
view_options: Default::default(),
nodes: BTreeMap::new(),
layout: None,
routes: vec![route(authored, vec![at(420., 40.)], 0.25, at(8., -8.))],
},
);
place(&mut p, second, 30, send, at(40., 120.), card);
place(&mut p, second, 31, monitor, at(660., 120.), card);
validate_candidate(&p).unwrap();
(
p,
main,
second,
json!({"authored_edge":authored,"authored_edge_name":"Verified report",
"filtered_edge":hidden,"container_placement":id(20),"source_port":source_port,"target_port":target_port,
"main_diagram":main,"second_diagram":second,"authored_pin_count":2,
"source_anchor":{"side":"Right","offset":0.25},"target_anchor":{"side":"Left","offset":0.75},
"dormant_source_attachment":{"side":"Bottom","offset":0.5},
"dormant_target_attachment":{"side":"Top","offset":0.25}}),
)
}
fn json_bytes(p: &Project) -> Vec<u8> {
let mut bytes = serde_json::to_vec_pretty(p).unwrap();
if !bytes.ends_with(b"\n") {
bytes.push(b'\n');
}
assert_eq!(persistence::decode(&bytes).unwrap(), *p);
bytes
}
fn source_bytes(p: &Project) -> Vec<u8> {
let source = language::format(p);
assert_eq!(language::parse(&source).unwrap(), *p);
let mut bytes = source.into_bytes();
if !bytes.ends_with(b"\n") {
bytes.push(b'\n');
}
bytes
}
fn main() -> Result<(), Box<dyn Error>> {
let mut args = std::env::args_os().skip(1);
let output = PathBuf::from(
args.next()
.ok_or("Usage: arrange_reset_native_probe NEW_DIRECTORY")?,
);
if args.next().is_some() || output.exists() {
return Err("Require exactly one output directory that does not already exist".into());
}
let (before, main, second, identities) = original();
let mut folded = before.clone();
folded
.diagrams
.get_mut(&main)
.unwrap()
.nodes
.get_mut(&id(20))
.unwrap()
.collapsed = true;
let mut files = Vec::new();
let mut cases = Vec::new();
for (name, project) in [("expanded", before), ("folded", folded)] {
validate_candidate(&project)?;
// Explicitly candidate-derived UI oracle: this is not an independent layout proof.
let expected = execute_batch(&project, &[Command::Layout(main)])?;
assert_eq!(project.elements, expected.elements);
assert_eq!(project.relations, expected.relations);
assert_eq!(project.diagrams[&second], expected.diagrams[&second]);
for (stage, p) in [("original", &project), ("expected-after", &expected)] {
files.push((format!("{name}-{stage}.json"), json_bytes(p)));
files.push((format!("{name}-{stage}.arcadia"), source_bytes(p)));
}
cases.push(json!({"name":name,"diagram":main,
"original_json":format!("{name}-original.json"),
"expected_json":format!("{name}-expected-after.json"),
"original_source":format!("{name}-original.arcadia"),
"expected_source":format!("{name}-expected-after.arcadia"),
"original_routes":project.diagrams[&main].routes,"expected_routes":expected.diagrams[&main].routes,
"expected_origin":"Candidate Command::Layout; UI-wiring oracle only"}));
}
let manifest = json!({"schema":1,"cases":cases,"identities":identities,
"definition":"Source-authored five-Function/two-view fixture; original geometry never generated by Layout.",
"comparison":"Decode saved JSON with production persistence and compare complete Project to immutable original/expected file. Prefer direct serializer bytes for byte checks; do not reserialize Project through generic JSON Value as a float oracle.",
"performed":"Generation and core checks only when this program is actually run; no native UI results recorded here."});
files.push((
"manifest.json".into(),
serde_json::to_vec_pretty(&manifest)?,
));
fs::create_dir(&output)?;
for (name, bytes) in files {
fs::write(output.join(name), bytes)?;
}
println!("{}", output.join("manifest.json").display());
Ok(())
}