diff --git a/crates/oa-core/src/routing.rs b/crates/oa-core/src/routing.rs index 334495cc..1e7ad638 100644 --- a/crates/oa-core/src/routing.rs +++ b/crates/oa-core/src/routing.rs @@ -759,6 +759,64 @@ impl<'a> RoutingSpace<'a> { ys: sorted_coordinates(obstacles.iter().flat_map(|r| [r.top, r.bottom]).collect()), } } + + /// Experimental bounded lanes around settled other-edge segments. Preserve + /// every obstacle coordinate; only new lane coordinates count toward the cap. + fn with_lanes(&self, start: Position, end: Position, previous: &[Segment]) -> Self { + const EXTRA_LIMIT: usize = 64; + let add = |base: &[f32], candidates: Vec, a: f32, b: f32| { + let lo = a.min(b); + let hi = a.max(b); + let midpoint = f64::from(a) / 2.0 + f64::from(b) / 2.0; + let mut extra = sorted_coordinates( + candidates + .into_iter() + .filter(|v| { + v.is_finite() && base.binary_search_by(|base| base.total_cmp(v)).is_err() + }) + .collect(), + ); + let distance = |v: f32| { + if v < lo { + f64::from(lo) - f64::from(v) + } else if v > hi { + f64::from(v) - f64::from(hi) + } else { + 0.0 + } + }; + extra.sort_by(|a, b| { + distance(*a) + .total_cmp(&distance(*b)) + .then_with(|| { + (f64::from(*a) - midpoint) + .abs() + .total_cmp(&(f64::from(*b) - midpoint).abs()) + }) + .then_with(|| a.total_cmp(b)) + }); + extra.truncate(EXTRA_LIMIT); + sorted_coordinates(base.iter().copied().chain(extra).collect()) + }; + let mut xs = Vec::new(); + let mut ys = Vec::new(); + for segment in previous { + if segment.a == segment.b { + continue; + } + if segment.a.x == segment.b.x { + xs.extend([segment.a.x - CLEARANCE, segment.a.x + CLEARANCE]); + } + if segment.a.y == segment.b.y { + ys.extend([segment.a.y - CLEARANCE, segment.a.y + CLEARANCE]); + } + } + Self { + obstacles: self.obstacles, + xs: add(&self.xs, xs, start.x, end.x), + ys: add(&self.ys, ys, start.y, end.y), + } + } } #[allow(clippy::too_many_arguments)] @@ -849,13 +907,17 @@ fn route_edge( // Only the final leg has a known continuation. Intermediate // authored pins must not inherit the target's terminal direction. let outgoing = (index == pins.len()).then_some(b.point); - let path = - fast_path(start, end, &space, &occupied, incoming, outgoing).or_else(|| { + // Both searches see identical lanes. Earlier legs/current + // source stubs affect cost as before, but do not generate lanes. + let leg_space = space.with_lanes(start, end, previous); + let path = fast_path(start, end, &leg_space, &occupied, incoming, outgoing) + .or_else(|| { if !search { return None; } - let (path, hit_limit) = - grid_path(start, end, &space, &occupied, incoming, outgoing, budget); + let (path, hit_limit) = grid_path( + start, end, &leg_space, &occupied, incoming, outgoing, budget, + ); exhausted |= hit_limit; path }); @@ -1611,6 +1673,97 @@ impl BoundsBuilder { mod terminal_join_tests { use super::*; + #[test] + fn lanes_preserve_base_coordinates_and_bound_unique_extras_deterministically() { + let base: Vec<_> = (0..80).map(|i| 10_000.0 + i as f32).collect(); + let space = RoutingSpace { + obstacles: &[], + xs: base.clone(), + ys: base.clone(), + }; + let mut previous = Vec::new(); + for i in 0..100 { + let coordinate = i as f32 * 40.0; + previous.push(Segment { + a: pos(coordinate, 0.0), + b: pos(coordinate, 100.0), + count: 1, + }); + previous.push(Segment { + a: pos(0.0, coordinate), + b: pos(100.0, coordinate), + count: 1, + }); + } + let lanes = space.with_lanes(pos(0.0, 0.0), pos(100.0, 100.0), &previous); + previous.reverse(); + previous.extend(previous.clone()); + let reordered = space.with_lanes(pos(0.0, 0.0), pos(100.0, 100.0), &previous); + assert_eq!(lanes.xs, reordered.xs); + assert_eq!(lanes.ys, reordered.ys); + for coordinates in [&lanes.xs, &lanes.ys] { + assert_eq!(coordinates.len(), 80 + 64); + assert!(base.iter().all(|v| coordinates.contains(v))); + assert!(coordinates.windows(2).all(|v| v[0] < v[1])); + assert!(coordinates.contains(&12.0)); + assert!(coordinates.contains(&92.0)); + assert!(!coordinates.contains(&3972.0)); + } + } + + #[test] + fn lanes_rank_interval_then_midpoint_and_skip_nonfinite_values() { + let space = RoutingSpace::new(&[]); + let previous: Vec<_> = (0..100) + .map(|i| Segment { + a: pos(i as f32 * 40.0, 0.0), + b: pos(i as f32 * 40.0, 100.0), + count: 1, + }) + .chain(std::iter::once(Segment { + a: pos(f32::INFINITY, 0.0), + b: pos(f32::INFINITY, 100.0), + count: 1, + })) + .collect(); + let lanes = space.with_lanes(pos(0.0, 0.0), pos(4000.0, 0.0), &previous); + assert_eq!(lanes.xs.len(), 64); + assert!(lanes.xs.contains(&1988.0)); + assert!(lanes.xs.contains(&2012.0)); + assert!(!lanes.xs.contains(&12.0)); + assert!(lanes.xs.iter().all(|v| v.is_finite())); + assert!(lanes.ys.is_empty()); + } + + #[test] + fn shared_lane_space_offers_clear_parallel_path_to_fast_and_grid() { + let start = pos(0.0, 0.0); + let end = pos(200.0, 0.0); + let previous = vec![Segment { + a: start, + b: end, + count: 1, + }]; + let base = RoutingSpace::new(&[]); + let lanes = base.with_lanes(start, end, &previous); + assert_eq!(lanes.ys, vec![-12.0, 12.0]); + let fast = fast_path(start, end, &lanes, &previous, None, None).unwrap(); + assert_eq!(fast.first(), Some(&start)); + assert_eq!(fast.last(), Some(&end)); + // Under experimental P=3, direct cost280 loses to length224 + turns48. + // No terminal direction is fixed in this private leg-level witness. + // Keep the witness valid when parent compares the baseline coefficient. + let expected = path_cost(&[start, end], &previous).min(272.0); + assert!((path_cost(&fast, &previous) - expected).abs() < EPSILON); + let mut budget = VIEW_SEARCH_BUDGET; + let (grid, exhausted) = grid_path(start, end, &lanes, &previous, None, None, &mut budget); + assert!(!exhausted); + let grid = grid.unwrap(); + assert_eq!(grid.first(), Some(&start)); + assert_eq!(grid.last(), Some(&end)); + assert!((path_cost(&grid, &previous) - expected).abs() < EPSILON); + } + fn complete_cost( path: &[Position], before: Position, diff --git a/harness/experiments/auto-layout-20260925/penalty-results-audit.md b/harness/experiments/auto-layout-20260925/penalty-results-audit.md new file mode 100644 index 00000000..eb0eab19 --- /dev/null +++ b/harness/experiments/auto-layout-20260925/penalty-results-audit.md @@ -0,0 +1,26 @@ +# P overlap-penalty experiment independent audit + +Confirmed the reported finite result. Static read-only audit; no build, probe rerun, source edit or GUI action. P does not improve any of the nine layered candidate metric vectors and is not a demonstrated solution to their remaining shared routes. + +Primary comparison: J06 `08656b18bf8934cf264469cf68fc6dea97c15cbb` versus P07 `3d7adff923dee5bed54dfdccc119dbee0c7c2773`. Inspected the latter commit: only routing.rs changes, overlap coefficient0.12→3.0 plus an experiment comment; cap80 remains unchanged. Both recorded `cargo run --locked --offline -p oa-core --example auto_layout_probe` receipts are Windows gnullvm/dev, exit0, inputs unchanged, failure null. Independently verified every log hash in both receipts. + +Independent traversal of the raw outputs confirmed all37 variant Projects, projected nodes, projected ports and emitted route endpoint records match exactly. All nine layered candidates retain supported=true, repeat-input exactness, idempotence, passes2–10 equal first/previous, exact JSON/single-source roundtrips and identical conservation results. The authored-detour route-reset exception remains intentional. Baseline Command::Layout history/Undo checks remain identical; this is still not candidate-command Undo evidence. + +Only two variant rows change numeric metrics: + +| Original/before scene | Raw sharing J→P | Nonterminal sharing J→P | Bends | Length | Point contacts | +|---|---:|---:|---:|---:|---:| +| crossed_bipartite |872→730|800→658|4→5|2064→2076|9→10| +| two_containers_reversed_children |54→6|54→6|4→5|1512→1524|2→3| + +Each extra contact is classified as a T contact in the separately generated independent interval audit: bipartite T3→4 and two-container T1→2; proper crossings remain0. Lower shared length therefore comes with one additional bend,12 length units and one additional point contact in each scene. Bipartite returns to the pre-J shared-length total; this does not establish trace readability. All baseline/reset rows, manual witness and nine layered scalar vectors are unchanged. Exact model/endpoint invariants do not imply identical polylines. + +Evidence identities: + +- J06 raw output `f9ac7c1320b1cf026259bfcaf13a39e968ae317463712d8dc793375d9a4a541f` (also identical to J03 output). +- P07 raw output `13111fe89e4e637d1af572a8a45b8bdd763e94b58a2ec5ec6ca83e40ffa209c7`. +- P07 result.json `6149122d05d77e02b463edb3dd359b06786bc4468c27d8cd625cbc1bc80c9894`. +- P comparison JSON `9f228fbe78e1888c5d93e87dddd8d2effc01bab723929a87423c61e23f5cad66`. +- P independent contact audit JSON `6f4add5c81f6d16c45efabbefd9e36c9beb637b6823993f0d51adc3e20485ad9`. Its recorded definitions and counts were inspected; this reviewer did not execute that helper again. + +Recommendation: archive P as a bounded negative result for the layered overlap objective, preserving the two ordinary-scene tradeoffs. A predefined bounded lane-candidate experiment can now test whether available route geometry, rather than this single coefficient, limits improvement. Retain the same Projects/endpoints and all quality metrics; do not tune indefinitely against these nine fixtures or claim general quality/native acceptance. The cap, sequential edge order, fast-path preference, axis-only grid state and estimated label bounds remain limits. diff --git a/harness/experiments/auto-layout-20260925/results-p.md b/harness/experiments/auto-layout-20260925/results-p.md new file mode 100644 index 00000000..d1ee380f --- /dev/null +++ b/harness/experiments/auto-layout-20260925/results-p.md @@ -0,0 +1,50 @@ +# Capped overlap-penalty experiment + +**P alone does not solve the arranged bipartite overlap.** Source +`3d7adff923dee5bed54dfdccc119dbee0c7c2773` changes only the overlap coefficient +from 0.12 to 3.0 (plus an experiment comment), retaining the per-segment cap 80. +Node placement, ports, target-join J logic, edge order and crossing cost remain +unchanged. This is a transient diagnostic source variant, not a proposed default. + +Windows command `cargo run --locked --offline -p oa-core --example +auto_layout_probe` completed exit 0 with unchanged inputs at +2026-09-25T01:04:57Z. Same frozen Rust1.98.1 gnullvm environment as J; Linux +excluded. Output SHA256 +`13111fe89e4e637d1af572a8a45b8bdd763e94b58a2ec5ec6ca83e40ffa209c7`. +J's 185 passing tests and strict Clippy are not claimed for P; this run executes +the diagnostic observer and its analytic primitives only. + +[Original evidence archive](run-p/penalty-3d7adff.zip), 916568 bytes, SHA256 +`6b819b01c8012aa72d423443f4dc04ae261f1ee9dc6907f0063c219ff173ad36`, +contains receipts, complete Projects/geometry, independent contact audit, +comparison, renderer output and runner. [Manifest](run-p/manifest.json) binds +original bytes and post-run probe executable; every member was checked against +its local original. + +Complete Projects, nodes, ports and route endpoints are exact versus J in all +37 variants. All nine layered candidates retain the previous quality vector; +in particular bipartite sharing remains 187 (115 nonterminal), with nine contacts +and zero proper crossings. Two original-scene vectors change; the other 35 do +not: + +| Original scene | Shared length J → P | Bends | Route length | Point contacts | +| --- | ---: | ---: | ---: | ---: | +| Crossed bipartite | 872 → 730 | 4 → 5 | 2064 → 2076 | 9 → 10 | +| Reversed children in two containers | 54 → 6 | 4 → 5 | 1512 → 1524 | 2 → 3 | + +The bipartite result restores the first experiment's original-scene vector; +the extra bend/length tradeoff was predicted by the low overlap cost diagnosis. +Both contact increases remain visible rather than being counted as a clean +readability win. These results concern core geometry, not native route tracing. + +The [independent P audit](penalty-results-audit.md) confirms these results and +all nine recorded conservation/roundtrip/repetition checks. Both additional +point contacts are T contacts; no proper crossing change is hidden by the table. + +The next L comparison adds a bounded number of deterministic parallel lane +coordinates while preserving all existing obstacle coordinates and fixed +endpoints. Use the same augmented geometry for fast/grid search. P+L and J+L +will distinguish available alternatives from preference. The cap 80 may still +reject a four-turn detour whose extra length/turn cost exceeds it; retain that +outcome rather than retuning cap, ordering and spacing together. No weight or +lane policy is accepted for production by this diagnostic run. diff --git a/harness/experiments/auto-layout-20260925/run-p/.gitattributes b/harness/experiments/auto-layout-20260925/run-p/.gitattributes new file mode 100644 index 00000000..e8ef64a1 --- /dev/null +++ b/harness/experiments/auto-layout-20260925/run-p/.gitattributes @@ -0,0 +1 @@ +* -text whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --git a/harness/experiments/auto-layout-20260925/run-p/manifest.json b/harness/experiments/auto-layout-20260925/run-p/manifest.json new file mode 100644 index 00000000..01ab7c16 --- /dev/null +++ b/harness/experiments/auto-layout-20260925/run-p/manifest.json @@ -0,0 +1,223 @@ +{ + "source_commit": "3d7adff923dee5bed54dfdccc119dbee0c7c2773", + "scope": "Transient P coefficient3.0/cap80 experiment, not production acceptance or claim that J tests pass with P.", + "post_run_probe_binary": { + "bytes": 24156160, + "sha256": "8f3ac5aa1fa01be6a8ab664e8ae269f6527b8ffb7e326c2926c8fae7c3d7e366" + }, + "members": { + "run/command/changes.patch": { + "bytes": 0, + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "run/command/context.json": { + "bytes": 3504, + "sha256": "6f6019b2be69e12e3270d8570e9e4950c93e42e8b3093a0e0324a30f7e5eb0ff" + }, + "run/command/inputs-after.json": { + "bytes": 1727969, + "sha256": "607febcd0d74d11deaa07a44b8b9cf6c382fd65d55deadb2d8ac7e889797dcf1" + }, + "run/command/inputs-before.json": { + "bytes": 1727969, + "sha256": "607febcd0d74d11deaa07a44b8b9cf6c382fd65d55deadb2d8ac7e889797dcf1" + }, + "run/command/output.log": { + "bytes": 371606, + "sha256": "13111fe89e4e637d1af572a8a45b8bdd763e94b58a2ec5ec6ca83e40ffa209c7" + }, + "run/command/result.json": { + "bytes": 4172, + "sha256": "6149122d05d77e02b463edb3dd359b06786bc4468c27d8cd625cbc1bc80c9894" + }, + "run/command/stderr.log": { + "bytes": 279, + "sha256": "fe5d8d303700ef5b92bfaa95ac1f99a2214e1fc5f6c5ac8d83f6303aa258965b" + }, + "run/environment.json": { + "bytes": 9463, + "sha256": "14e53dd6359601bdd9be3ad24c527fca96310d9eb4ffa91965f71841f8df2f82" + }, + "run/orchestration.log": { + "bytes": 181, + "sha256": "db5af22d893966919b9342fd06b99e7e1c82c5c87593544b7762cc85f9a7e45a" + }, + "geometry/authored_detour_and_label-after.png": { + "bytes": 12492, + "sha256": "44e30b94ef11b176155ab3df90fe5b52788c07442a42a355d3458fa904c147bd" + }, + "geometry/authored_detour_and_label-before.png": { + "bytes": 12468, + "sha256": "097588fae4fd6253c25ab4b60be1ad685ead3a3012b206f382cec0be1341e700" + }, + "geometry/authored_detour_and_label-experimental_candidate-metrics.png": { + "bytes": 13162, + "sha256": "82a07de168cda7dacdad2bd532dae408172466b2776acf8cfaabef6711c0539b" + }, + "geometry/authored_detour_and_label-reset_only_control-metrics.png": { + "bytes": 12777, + "sha256": "e676edc49ec6ebb2fe29e976c36cba589f76330e7f9eb27b8835415a2ed5d225" + }, + "geometry/chain_7_row_wrap-after.png": { + "bytes": 14271, + "sha256": "a020c1535e3d6e48cb5e6d7ae8403a256767c68ce26876fd773f3b626c61e365" + }, + "geometry/chain_7_row_wrap-before.png": { + "bytes": 13771, + "sha256": "0b282cbd29eb3e29fa7d3bb9c3c9746caa14c77372b3191d78fa1a60743d0b11" + }, + "geometry/chain_7_row_wrap-experimental_candidate-metrics.png": { + "bytes": 14396, + "sha256": "3ca042155d918083c5f4135ae059205b29b8ee5944819a6040a22eeb572f5f04" + }, + "geometry/chain_7_row_wrap-reset_only_control-metrics.png": { + "bytes": 14549, + "sha256": "8828f289159deb0c2bedd130495197639775cd8edeb561f0de5501e2980d1e1d" + }, + "geometry/crossed_bipartite-after.png": { + "bytes": 13144, + "sha256": "54a1b5e983bc9b6f619e67c13173d0ff5000e30f080aaf6c0a9064f59036f4b7" + }, + "geometry/crossed_bipartite-before.png": { + "bytes": 13413, + "sha256": "8622726dfdfc01e93fcd2d9d22c6d082e5a169b9dcd59f788e876954431214fd" + }, + "geometry/crossed_bipartite-experimental_candidate-metrics.png": { + "bytes": 13855, + "sha256": "e3cc0a326a2c8b577e40101c5f67ea9c3182bca6d3f0498cdc1f25a64df57b90" + }, + "geometry/crossed_bipartite-reset_only_control-metrics.png": { + "bytes": 13349, + "sha256": "0b2a8c49368258b23c15a8e06bf9b881f0e53fed8b5fd7d6f216a09837634abc" + }, + "geometry/diamond-after.png": { + "bytes": 12556, + "sha256": "6afcff1e5c10758e5eab3b803ec858d0af3da953be4af93df75257544a7252b2" + }, + "geometry/diamond-before.png": { + "bytes": 13228, + "sha256": "38e341a1ed51d4b4a94513f34c3d48b05c72177dcc3792dc660cb780fd7f98c9" + }, + "geometry/diamond-experimental_candidate-metrics.png": { + "bytes": 13555, + "sha256": "a61d178e2cd3fcff8fc4ed3c42e5ab71b042d26d776f59fe5eaadb3ef8481e5e" + }, + "geometry/diamond-reset_only_control-metrics.png": { + "bytes": 12982, + "sha256": "48414d7a859c774f2cef51d0fc1512b1c9fe1540c540f96fac7f9531583d8731" + }, + "geometry/fixed_ports-after.png": { + "bytes": 11889, + "sha256": "574cb0249c3bcc3140b9d61906332295a8462e32fbcd6b9526d8b05e202e38a0" + }, + "geometry/fixed_ports-before.png": { + "bytes": 12013, + "sha256": "d07ef2105aa63f3aaacb19e9a7ca4960239b01f05f734baa6270657a465b4ab0" + }, + "geometry/fixed_ports-experimental_candidate-metrics.png": { + "bytes": 12394, + "sha256": "d7fdcd7d4a1a014dd34243400dcd74a7596388fc5747853e5a6629535ca3083e" + }, + "geometry/fixed_ports-reset_only_control-metrics.png": { + "bytes": 12231, + "sha256": "237e181db92baf49c24554ec4325137b014413603b62cb08dee63e6e68fa3e8d" + }, + "geometry/flat_chain_4-after.png": { + "bytes": 12582, + "sha256": "7326cd482a61bea4cb787770449253a55f41e102794c8fc6a8500d9244c20cc7" + }, + "geometry/flat_chain_4-before.png": { + "bytes": 12723, + "sha256": "b086e2b23d4b68cb43366725a26fbb39fdc2e87d18cd7109c9b3ec950ab665ba" + }, + "geometry/flat_chain_4-experimental_candidate-metrics.png": { + "bytes": 13405, + "sha256": "3bb352dd5066a3b2cc5bb298c9f47a02416186421df4841b96c944e523d11104" + }, + "geometry/flat_chain_4-reset_only_control-metrics.png": { + "bytes": 12918, + "sha256": "eba3eede6771a1ebfc7b773b48b599f5ca49613ad7444ab26acfea7d20dde515" + }, + "geometry/long_ordinary_labels-after.png": { + "bytes": 12643, + "sha256": "f4f0c360e9ce44d631dd1d9f7c202954be943fdbede6288edbaddf9b890fcaec" + }, + "geometry/long_ordinary_labels-before.png": { + "bytes": 12661, + "sha256": "3c17c1195337cda7cd4141a15428b66cac1475421600b6ecffc3db57dbfd9f94" + }, + "geometry/long_ordinary_labels-experimental_candidate-metrics.png": { + "bytes": 13235, + "sha256": "d2931b576901fec68b23afd1a54d4c301eda4a75ba30184344749e0add277bc0" + }, + "geometry/long_ordinary_labels-reset_only_control-metrics.png": { + "bytes": 12969, + "sha256": "68aacc7196a4995ff8a884a15ec91a31bd386bdd2d232fd2c27696a7f83cf791" + }, + "geometry/manifest.json": { + "bytes": 8099, + "sha256": "c1b59384878e519efec99757efee571635f30d814247db2f183eebbf9c467a0f" + }, + "geometry/nested_cross_boundary-after.png": { + "bytes": 13344, + "sha256": "51db6785ab89f5d92c61288604ae3c76aee467e291738b54466db5704c0eec8b" + }, + "geometry/nested_cross_boundary-before.png": { + "bytes": 13547, + "sha256": "3b3963f5ef5a42106a006f1825ae5d85b722aa3bf163452ba986ef3369b57cc2" + }, + "geometry/nested_cross_boundary-experimental_candidate-metrics.png": { + "bytes": 13535, + "sha256": "0ba365785753e748dc7c86c3f1eb5767f9ccb87c0ae0e18085e6a9d32b79f60d" + }, + "geometry/nested_cross_boundary-reset_only_control-metrics.png": { + "bytes": 13549, + "sha256": "fbe21b57616459ecdbbd083dccd73bd120f5b7ad59a8ad80ea38cbbf9c3f49c1" + }, + "geometry/two_containers_reversed_children-after.png": { + "bytes": 13955, + "sha256": "1722ff21eaadd831e00b2176d61f8fa65b083d2fd5b633a196a3335d48ca125e" + }, + "geometry/two_containers_reversed_children-before.png": { + "bytes": 14092, + "sha256": "dcbc521b8e5efd6a201da8a724ed218a9f1331a8abb2eda299a5807828037cb9" + }, + "geometry/two_containers_reversed_children-experimental_candidate-metrics.png": { + "bytes": 14500, + "sha256": "8a0744cf04d305a0431468395b3676604e03991e577f9f9d2f45e8497b1ef9ca" + }, + "geometry/two_containers_reversed_children-manual_planar_order_witness-metrics.png": { + "bytes": 14531, + "sha256": "60623d358d9cb930c2c2c4995c9286c653e597c411b8879b77ac099fe9b0406b" + }, + "geometry/two_containers_reversed_children-reset_only_control-metrics.png": { + "bytes": 14134, + "sha256": "ce6bc93dc38fe5b25552c8ebc5e778da175df53992e6a70ded8377fd99372587" + }, + "support/auto-layout-p-comparison-20260925.json": { + "bytes": 77494, + "sha256": "9f228fbe78e1888c5d93e87dddd8d2effc01bab723929a87423c61e23f5cad66" + }, + "support/auto-layout-p-contact-audit-20260925.json": { + "bytes": 104912, + "sha256": "6f4add5c81f6d16c45efabbefd9e36c9beb637b6823993f0d51adc3e20485ad9" + }, + "support/auto-layout-contact-audit-20260925.py": { + "bytes": 9838, + "sha256": "398b9677d2ef2333514dd9c1ba5bc2f020c9927f395ed33bf11ac59b68139f46" + }, + "support/run-auto-layout-check-20260925.py": { + "bytes": 2771, + "sha256": "d652c4df47f13aefc723bc54362d7b61308b8983c8d39ae7721c012519358ea2" + }, + "support/run.py": { + "bytes": 13814, + "sha256": "698ed7182726c77fa4a1c85fc6dd08187ed20689941f57e749e3f0bc845f3252" + } + }, + "archive": { + "name": "penalty-3d7adff.zip", + "bytes": 916568, + "sha256": "6b819b01c8012aa72d423443f4dc04ae261f1ee9dc6907f0063c219ff173ad36" + } +} diff --git a/harness/experiments/auto-layout-20260925/run-p/penalty-3d7adff.zip b/harness/experiments/auto-layout-20260925/run-p/penalty-3d7adff.zip new file mode 100644 index 00000000..1fb4df97 Binary files /dev/null and b/harness/experiments/auto-layout-20260925/run-p/penalty-3d7adff.zip differ