Preserve authored sizes during identity placement transfer

This commit is contained in:
2026-09-24 20:18:39 -07:00
parent 8a2010d8a6
commit fc5c22c903
2 changed files with 28 additions and 3 deletions
+21 -3
View File
@@ -899,19 +899,26 @@ fn import_placement(
}
let mut after = original.clone();
let ad = after.diagrams.get_mut(&diagram).unwrap();
let intended: BTreeMap<_, _> = plan
.nodes
.iter()
.map(|node| (node.id, (node.position, node.size)))
.collect();
for node in plan.nodes {
let placed = ad
.nodes
.get_mut(&node.id)
.ok_or_else(|| fail("Projected node is not stored"))?;
let projected_size = view.nodes.iter().find(|n| n.id == node.id).unwrap().size;
if placed.collapsed {
let compact = view.nodes.iter().find(|n| n.id == node.id).unwrap().size;
if node.size != compact {
if node.size != projected_size {
return Err(fail(
"Collapsed placement plan must retain exact projected compact size; stored expanded size is preserved",
));
}
} else {
} else if node.size != projected_size {
// Unchanged effective size must not bake derived projection minima
// into authored geometry during an identity transfer.
placed.size = node.size;
}
placed.position = node.position;
@@ -956,6 +963,17 @@ fn import_placement(
}
}
validate_candidate(&after)?;
let final_view = projection::project_view(&after, diagram);
if final_view.nodes.len() != intended.len()
|| final_view
.nodes
.iter()
.any(|node| intended.get(&node.id) != Some(&(node.position, node.size)))
{
return Err(fail(
"Final Rust projection differs from intended node geometry",
));
}
Ok(after)
}
fn import_placement_cli(
@@ -0,0 +1,7 @@
# Identity transfer correction after first run
The initial source8a2010d8 importer wrote every expanded node's projected size to its stored size. Independent audit of five identity plans showed unwanted source normalization:3 nodes in workshop original,2 in folded,10 in each mixed case and40 in sparse. Projection minimum sizing had made those effective rectangles larger than stored authored sizes. Positions, effective geometry, semantics, route policy and collapsed stored size were not implicated, but a no-layout identity transfer did not recover the original Project apart from eligible reset.
Correct the adapter by preserving stored size whenever the planned rectangle equals the original projected rectangle. Only an actual effective size change is imported. Keep collapsed compact-size equality mandatory and never replace its stored expanded size. After transfer, reproject and require the entire intended node ID/position/size map to match exactly, rejecting a requested rectangle that Rust would renormalize. Preserve first-run receipts and outputs; rerun the identical Rust control/import/negative cases against the corrected source without rerunning or tuning ELK.
This is an example-only adapter repair, not a production layout change. It cannot resolve the independently observed automatic-port drift:10/25 ports in each mixed case and48/110 in sparse differ materially from the engine's assumed endpoints, with7/32 side changes respectively. All six authored anchors in each mixed case remain exact. Geometry comparisons remain diagnostic until that mapping limitation is addressed.