mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-04 02:55:54 +00:00
engine: feature replies carry no boolean diagnostics
doc's FeatureResult has no boolean_diagnostics any more (truck's Boolean
retry reports, gone with truck; SMLib's boolean has no retries). The
timeline.inspect and doc.inspect replies drop the key.
Tests of the removed reports: tests/boolean_diagnostics.rs is deleted (it
checked truck's retry events and their survival through the cache, undo and
reopen); the assertions that a feature's report had no events go from
features_more_tests, patterns_tests, hole_face_tests and tests/rim_cut (the
rest of each test stays). The CLI corpus's expected replies
(move-bodies, issue-489-stacked-join, issue-616-lid-ribs) drop the key; the
issue-616 one listed a planar_fallback event. docs/robustness.md: its
section on retries becomes one on SMLib's booleans, which have none.
Left to the blends work: engine fuzz.rs (its retry-event counts) and
clearance/interference (capture_boolean_diagnostics, coaxial_overlap,
with_attempt_budget).
Not built: base in progress (kernel-smlib/no-truck 66ab6b7f does not build).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
This commit is contained in:
@@ -90,10 +90,6 @@
|
||||
],
|
||||
"timeline": [
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 1,
|
||||
"ms": 0.131943,
|
||||
@@ -104,10 +100,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 2,
|
||||
"ms": 1.0812709999999999,
|
||||
@@ -118,10 +110,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 3,
|
||||
"ms": 0.450002,
|
||||
@@ -132,10 +120,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 4,
|
||||
"ms": 5.191514000000001,
|
||||
|
||||
@@ -54,10 +54,6 @@
|
||||
],
|
||||
"timeline": [
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 1,
|
||||
"ms": 1.178957,
|
||||
@@ -68,10 +64,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 2,
|
||||
"ms": 83.24342399999999,
|
||||
@@ -82,10 +74,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 3,
|
||||
"ms": 0.150889,
|
||||
@@ -96,10 +84,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 4,
|
||||
"ms": 94.465481,
|
||||
@@ -110,10 +94,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 5,
|
||||
"ms": 50.426736,
|
||||
@@ -124,10 +104,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 6,
|
||||
"ms": 40.383005,
|
||||
@@ -138,10 +114,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 7,
|
||||
"ms": 59.041461000000005,
|
||||
@@ -152,18 +124,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [
|
||||
{
|
||||
"face_shift_mm": 0.0,
|
||||
"rotation_rad": 0.0,
|
||||
"strategy": "planar_fallback",
|
||||
"tolerance_mm": 0.0,
|
||||
"translation_mm": 0.0
|
||||
}
|
||||
],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 8,
|
||||
"ms": 562.5477970000001,
|
||||
@@ -174,10 +134,6 @@
|
||||
"warning": "Boolean retry: exact planar fallback (no displacement)"
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 9,
|
||||
"ms": 89.56076,
|
||||
@@ -188,10 +144,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 10,
|
||||
"ms": 65.330634,
|
||||
@@ -202,10 +154,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 11,
|
||||
"ms": 97.229403,
|
||||
|
||||
@@ -99,10 +99,6 @@
|
||||
],
|
||||
"timeline": [
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 1,
|
||||
"ms": 0.204585,
|
||||
@@ -113,10 +109,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 2,
|
||||
"ms": 2.318662,
|
||||
@@ -127,10 +119,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 3,
|
||||
"ms": 0.109196,
|
||||
@@ -141,10 +129,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 4,
|
||||
"ms": 0.338859,
|
||||
@@ -155,10 +139,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 5,
|
||||
"ms": 0.312259,
|
||||
@@ -169,10 +149,6 @@
|
||||
"warning": null
|
||||
},
|
||||
{
|
||||
"boolean_diagnostics": {
|
||||
"events": [],
|
||||
"truncated": false
|
||||
},
|
||||
"error": null,
|
||||
"id": 6,
|
||||
"ms": 0.23144699999999999,
|
||||
|
||||
@@ -1031,7 +1031,6 @@ fn inspect_feature(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
"id": f.id, "name": f.name, "type": f.kind.type_name(), "suppressed": f.suppressed, "rolled_back": rolled_back,
|
||||
"definition": def, "omitted": omitted, "inputs": inputs,
|
||||
"error": r.and_then(|r| r.error.clone()), "warning": r.and_then(|r| r.warning.clone()),
|
||||
"boolean_diagnostics": r.map(|r| &r.boolean_diagnostics),
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -1870,7 +1870,7 @@ fn a_ring_cut_round_a_hole_takes_in_the_hole_it_is_drawn_round() {
|
||||
.ok()
|
||||
.and_then(|v| v["feature"].as_u64())
|
||||
.and_then(|id| s.model.result(id))
|
||||
.is_some_and(|f| f.boolean_diagnostics.events.is_empty());
|
||||
.is_some_and(|f| f.error.is_none());
|
||||
(r.is_ok(), before - volume(&mut s), clean)
|
||||
};
|
||||
let taken = std::f64::consts::PI * (36.0 - 9.0) * 3.0;
|
||||
@@ -1932,7 +1932,7 @@ fn a_line_of_text_is_cut_in_one_exact_boolean() {
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
let id = run(&mut s, "solid.extrude", json!({"distance":-depth,"operation":"cut"}))["feature"].as_u64().unwrap();
|
||||
let r = s.model.result(id).unwrap();
|
||||
assert!(r.error.is_none() && r.boolean_diagnostics.events.is_empty(), "{at:?} {depth}: {r:?}");
|
||||
assert!(r.error.is_none(), "{at:?} {depth}: {r:?}");
|
||||
before - volume(&mut s)
|
||||
};
|
||||
// Straight walls: the material taken grows with the depth, the letters' area each mm.
|
||||
@@ -1961,7 +1961,7 @@ fn a_line_of_text_cut_through_or_joined_in_relief_is_one_boolean() {
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
let id = run(&mut s, "solid.extrude", json!({"distance":distance,"operation":op}))["feature"].as_u64().unwrap();
|
||||
let r = s.model.result(id).unwrap();
|
||||
assert!(r.error.is_none() && r.boolean_diagnostics.events.is_empty(), "{op}: {r:?}");
|
||||
assert!(r.error.is_none(), "{op}: {r:?}");
|
||||
(before, volume(&mut s), s.model.state().bodies.len())
|
||||
};
|
||||
let (before, through, pieces) = text("cut", -40.0);
|
||||
@@ -1995,7 +1995,7 @@ fn a_line_of_text_cut_again_deeper_is_one_exact_boolean() {
|
||||
run(s, "sketch.finish", json!({}));
|
||||
let id = run(s, "solid.extrude", json!({"distance":-depth,"operation":"cut"}))["feature"].as_u64().unwrap();
|
||||
let r = s.model.result(id).unwrap();
|
||||
assert!(r.error.is_none() && r.boolean_diagnostics.events.is_empty(), "{depth}: {r:?}");
|
||||
assert!(r.error.is_none(), "{depth}: {r:?}");
|
||||
before - volume(s)
|
||||
};
|
||||
let first = cut(&mut s, 1.0);
|
||||
@@ -2021,7 +2021,7 @@ fn text_cut_through_a_large_plate_is_one_exact_boolean() {
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
let id = run(&mut s, "solid.extrude", json!({"distance":-2,"operation":"cut"}))["feature"].as_u64().unwrap();
|
||||
let r = s.model.result(id).unwrap();
|
||||
assert!(r.error.is_none() && r.boolean_diagnostics.events.is_empty(), "{w} x {h}: {r:?}");
|
||||
assert!(r.error.is_none(), "{w} x {h}: {r:?}");
|
||||
before - volume(&mut s)
|
||||
};
|
||||
let (small, large) = (taken(200.0, 120.0, [60.0, 40.0]), taken(2000.0, 1200.0, [860.0, 125.0]));
|
||||
|
||||
@@ -326,7 +326,6 @@ fn inspect(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
json!({
|
||||
"id": f.id, "name": f.name, "type": f.kind.type_name(), "suppressed": f.suppressed, "rolled_back": i >= marker,
|
||||
"error": r.and_then(|r| r.error.clone()), "warning": r.and_then(|r| r.warning.clone()), "ms": r.map(|r| r.ms),
|
||||
"boolean_diagnostics": r.map(|r| &r.boolean_diagnostics),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -632,7 +632,6 @@ fn pattern_of_touching_cuts_needs_no_fallback() {
|
||||
let (mut s, id) = sawtooth_bar(40, true);
|
||||
let result = s.model.result(id.unwrap()).unwrap();
|
||||
assert!(result.error.is_none() && result.warning.is_none(), "{result:?}");
|
||||
assert!(result.boolean_diagnostics.events.is_empty(), "{:?}", result.boolean_diagnostics);
|
||||
let m = run(&mut s, "inspect.measure", json!({}));
|
||||
let (mut one, _) = sawtooth_bar(40, false);
|
||||
let single = run(&mut one, "inspect.measure", json!({}));
|
||||
@@ -670,7 +669,6 @@ fn pattern_of_cuts_beside_a_round_needs_no_retries() {
|
||||
let id = created["feature"].as_u64().unwrap();
|
||||
let result = s.model.result(id).unwrap();
|
||||
assert!(result.error.is_none() && result.warning.is_none(), "{result:?}");
|
||||
assert!(result.boolean_diagnostics.events.is_empty(), "{:?}", result.boolean_diagnostics);
|
||||
}
|
||||
// The bar, less the rounds' corners and 40 teeth (a 4 x 2 triangle below the top, 16 wide).
|
||||
let expected = 16000.0 - 400.0 * (1.0 - PI / 4.0) - 40.0 * 4.0 * 16.0;
|
||||
|
||||
@@ -343,7 +343,6 @@ fn drilled_sketch_points_break_through_a_sloping_back_face() {
|
||||
let id = s.doc.find_feature("H").unwrap().id;
|
||||
let result = s.model.result(id).unwrap();
|
||||
assert!(result.error.is_none());
|
||||
assert!(result.boolean_diagnostics.unverified().is_none());
|
||||
// The cylindrical bore and cone, less the oblique conical cap outside x = z/4.
|
||||
let r = 2.5;
|
||||
let k = 59f64.to_radians().tan();
|
||||
|
||||
@@ -324,7 +324,6 @@ fn join_of_a_lobed_disc_pattern_is_not_refused() {
|
||||
}
|
||||
|
||||
mod blend_fit;
|
||||
mod boolean_diagnostics;
|
||||
mod component_frames;
|
||||
mod curved_seam_round;
|
||||
mod flush_join_loft;
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
use super::*;
|
||||
use solidcraft_kernel::BooleanStrategy;
|
||||
|
||||
#[test]
|
||||
fn boolean_retry_warning_and_details_survive_cache_undo_and_reopen() {
|
||||
let slope = 1f64.to_radians().tan();
|
||||
let mut session = Session::default();
|
||||
run(&mut session, "sketch.create", json!({"plane":"XZ","name":"Floor section"}));
|
||||
run(&mut session, "sketch.line", json!({"points":[[0,0],[100,0],[100,-10.-slope*100.],[0,-10.]],"closed":true}));
|
||||
run(&mut session, "sketch.finish", json!({}));
|
||||
run(&mut session, "solid.extrude", json!({"sketch":"Floor section","distance":80,"body_name":"Floor"}));
|
||||
run(&mut session, "solid.cylinder", json!({"base":[50,40,-5],"radius":10,"height":30,"operation":"cut"}));
|
||||
run(&mut session, "sketch.create", json!({"plane":"XY","name":"Ring section"}));
|
||||
run(&mut session, "sketch.circle.center", json!({"center":[50,40],"radius":20}));
|
||||
run(&mut session, "sketch.circle.center", json!({"center":[50,40],"radius":10}));
|
||||
run(&mut session, "sketch.finish", json!({}));
|
||||
run(
|
||||
&mut session,
|
||||
"solid.extrude",
|
||||
json!({"sketch":"Ring section","profiles":[{"point":[65,40]}],"start_offset":-5,"distance":7,"body_name":"Ring"}),
|
||||
);
|
||||
let id = run(&mut session, "solid.combine", json!({"target":"Floor","tools":["Ring"],"operation":"join"}))["feature"].as_u64().unwrap();
|
||||
let check = |session: &Session| {
|
||||
let result = session.model.result(id).unwrap();
|
||||
assert!(result.error.is_none());
|
||||
assert!(result.warning.as_ref().is_some_and(|warning| warning.contains("Boolean retry:")), "{result:?}");
|
||||
assert!(
|
||||
result.boolean_diagnostics.events.iter().any(|event| event.strategy == BooleanStrategy::CommonBore),
|
||||
"{:?}",
|
||||
result.boolean_diagnostics
|
||||
);
|
||||
result.boolean_diagnostics.clone()
|
||||
};
|
||||
let original = check(&session);
|
||||
let expected = (10. + slope * 50.) * (8000. - PI * 100.) + PI * 300. * 5.;
|
||||
assert!(rel(volume(&mut session), expected) < 2e-5);
|
||||
let inspected = run(&mut session, "timeline.inspect", json!({"feature":id}));
|
||||
assert_eq!(inspected["boolean_diagnostics"], serde_json::to_value(&original).unwrap());
|
||||
session.refresh();
|
||||
assert_eq!(check(&session), original);
|
||||
run(&mut session, "edit.undo", json!({}));
|
||||
run(&mut session, "edit.redo", json!({}));
|
||||
assert_eq!(check(&session), original);
|
||||
let reopened_doc = solidcraft_doc::Document::from_json(&session.doc.to_json()).unwrap();
|
||||
let reopened = Session::new(reopened_doc);
|
||||
assert_eq!(check(&reopened), original);
|
||||
// A later independent feature must not inherit the earlier retry's warning.
|
||||
run(&mut session, "solid.box", json!({"corner":[200,0,0],"length":5,"width":5,"height":5}));
|
||||
let last = session.model.results.last().unwrap();
|
||||
assert!(last.warning.is_none());
|
||||
assert!(last.boolean_diagnostics.events.is_empty());
|
||||
}
|
||||
|
||||
/// A barrel joined under a plate's back edge, its ends flush with the sides of the leaf it hangs
|
||||
/// from (#827 without its fillets): the join is exact, so the command's reply carries no Boolean
|
||||
/// retry, and the barrel's ends stay in the leaf's sides (it is not nudged to make the join go).
|
||||
#[test]
|
||||
fn a_barrel_joined_between_the_sides_of_a_leaf_needs_no_retry() {
|
||||
let mut session = Session::default();
|
||||
run(&mut session, "solid.box", json!({"length": 40, "width": 20, "height": 6, "corner": [0, 0, 5], "body_name": "Plate"}));
|
||||
run(&mut session, "solid.box", json!({"length": 14, "width": 10, "height": 6, "corner": [10, 10, 0], "operation": "join", "targets": ["Plate"]}));
|
||||
let reply = run(
|
||||
&mut session,
|
||||
"solid.cylinder",
|
||||
json!({"radius": 5, "height": 14, "axis": "X", "base": [10, 20, 0], "operation": "join", "targets": ["Plate"]}),
|
||||
);
|
||||
assert!(reply["warning"].is_null(), "{reply}");
|
||||
let result = session.model.result(reply["feature"].as_u64().unwrap()).unwrap();
|
||||
assert!(result.boolean_diagnostics.events.is_empty(), "{:?}", result.boolean_diagnostics);
|
||||
let state = session.model.state();
|
||||
let plate = &state.body("Plate").unwrap().body;
|
||||
assert_eq!(plate.shell_count(), 1);
|
||||
assert!(plate.validity().is_empty(), "{:?}", plate.validity());
|
||||
// Every edge ends on a level along x of the plate, the leaf or the barrel.
|
||||
for edge in plate.edges(1e-3).unwrap() {
|
||||
for p in [edge.points.first(), edge.points.last()].into_iter().flatten() {
|
||||
assert!([0., 10., 24., 40.].iter().any(|x| (p.x - x).abs() < 1e-9), "an edge ends at {p:?}");
|
||||
}
|
||||
}
|
||||
// A quarter of the barrel lies in the leaf.
|
||||
let expected = 5500. + 0.75 * PI * 25. * 14.;
|
||||
let actual = plate.mesh(&solidcraft_kernel::MeshTolerance::chord(1e-4)).unwrap().measure().volume;
|
||||
assert!(rel(actual, expected) < 1e-5, "{actual} vs {expected}");
|
||||
}
|
||||
@@ -48,7 +48,6 @@ fn rim_cut_after_the_round_on_the_other_end() {
|
||||
let id = cut_window(&mut after)["feature"].as_u64().unwrap();
|
||||
let result = after.model.result(id).unwrap();
|
||||
assert!(result.error.is_none() && result.warning.is_none(), "{result:?}");
|
||||
assert!(result.boolean_diagnostics.events.is_empty(), "{:?}", result.boolean_diagnostics);
|
||||
// The window's three faces (two sides and the top), at both points of the timeline.
|
||||
assert_eq!(faces(&before), f1 + 3);
|
||||
assert_eq!(faces(&after), f2 + 3);
|
||||
|
||||
+4
-53
@@ -112,60 +112,11 @@ changes to body grouping can therefore change the generated design. This preserv
|
||||
original geometric reference independently of those choices. These checks supplement the
|
||||
snapshots' stricter repeatability comparisons of raw topology and tessellated measurements.
|
||||
|
||||
## Successful Boolean retries
|
||||
## Booleans
|
||||
|
||||
When an accepted Boolean result needs a retry that can make it differ from the
|
||||
exact one (a tool nudge, or the unverified shortcut), the feature shows a
|
||||
warning in the timeline. Every other retry works on temporary geometry or
|
||||
tolerances and leaves the exact result, so it is recorded but not warned about.
|
||||
`timeline.inspect` and `doc.inspect` expose every retry in the feature's
|
||||
`boolean_diagnostics`, including the strategy and the applied translation,
|
||||
rotation, face offset and tessellation tolerance in millimetres/radians.
|
||||
Candidates those retries discarded before measuring them are listed in its
|
||||
`rejected`, with the reason: a candidate with an edge further outside the
|
||||
operands than 5% of their size cannot be their union, cut or intersection,
|
||||
and meshing one (a trim loop running metres along a cone's continuation)
|
||||
could take minutes or never finish (#3020).
|
||||
|
||||
A common shift of both operands is reversed on the result. Coincident-face
|
||||
separation and bore offsets describe temporary working geometry; they are not
|
||||
claims about the final model's error. A coincident face is separated only
|
||||
where the space it moves through holds what the Boolean leaves there anyway
|
||||
(nothing of the target for a cut's face, the target's material for a join's);
|
||||
a face with no such room stays, and the exact planar fallback is tried first.
|
||||
A tool nudge changes the relative operand
|
||||
placement and reports both its translation magnitude and rotation angle. When it
|
||||
fails, or leaves a sliver face (narrower than 1/200 of the part), it is tried the
|
||||
other way too: one way can push a face into a curved face it only touched (a cut
|
||||
whose end lies tangent to a round side) and leave a sliver of it, where the other
|
||||
way parts them (#897, #827).
|
||||
Exact planar and piecewise fallbacks report zero displacement. When a conical
|
||||
cutter meets a body with earlier conical faces (pointed bores copied in a pattern),
|
||||
two finer, unshifted passes are tried first, at 1e-5 and 1e-6 of their size (never
|
||||
below 1e-6 mm). A coarse first cut can leave tiny junctions that later copies cannot
|
||||
intersect, so refining only the failing copy is too late. Every candidate must pass
|
||||
the volume, membership and spatial checks; a rejected candidate continues to the
|
||||
next tolerance, then the ordinary routes. The existing acceptance checks still
|
||||
apply to all results.
|
||||
|
||||
A join or a cut that needed any retry is then held to what it can do at all
|
||||
(`crates/kernel/src/boolean_guard.rs`, #616): the result is closed, a join
|
||||
never loses volume and a cut never gains any, and outside the tool's box the
|
||||
result's surface is the target's and the target's is the result's (a join or
|
||||
a cut can only change the target where the tool is). A cut may come out empty
|
||||
only when the tool covers the target. A result that fails is refused with an
|
||||
error naming what was wrong and where, rather than returned: a wrong result
|
||||
that looks right is worse than an error.
|
||||
|
||||
Reports belong to the evaluated feature and survive cached rebuilds and
|
||||
undo/redo. Cold reopening regenerates them from the embedded design. Failed or
|
||||
discarded retry branches do not contribute successful-retry events. Reports
|
||||
are capped at 1024 events per feature and explicitly identify truncation.
|
||||
|
||||
Fuzz JSON and the text report count successful retry events by strategy for
|
||||
designs and Boolean identity checks separately, including nested operations.
|
||||
These are event counts, so a single Boolean or seed can contribute several.
|
||||
Truncated reports are counted separately rather than implying complete totals.
|
||||
Booleans run in SMLib, with no retries or fallbacks: a Boolean SMLib cannot do exactly is an
|
||||
error that names why, never a nudged or approximate result. The retry reports truck's Booleans
|
||||
kept (`boolean_diagnostics` in `timeline.inspect` and `doc.inspect`) are gone with them.
|
||||
|
||||
## Results
|
||||
|
||||
|
||||
Reference in New Issue
Block a user