The watertightness census treats a host's no-void probe going dark as the host getting better, and the lane stays green.
The mechanism
HostRow::is_torn_solid reads four things: open > 0, a closed-solid representation, !far, and pre != PreVoid::Failed. classify has a symmetric pair of arms on that predicate:
if r.is_torn_solid() && !g.is_torn_solid() {
c.worse_gated.push("newly a genuine watertightness defect (...)");
} else if !r.is_torn_solid() && g.is_torn_solid() {
c.better.push("no longer a genuine watertightness defect");
}
When process_no_voids starts returning None for a host, pre flips Open(n) -> Failed with open, tris, coll, far and alt all unmoved. The second arm fires, and nothing else in classify has anything to say, so the only reason attached to the host is that it is no longer a genuine defect.
reclassifications does not carry pre. It carries rep and far, on the grounds that those move is_torn_solid without any count moving, which is exactly what pre also does. So the host is not reclassified either.
What that costs
The host lands in improved. requires_bless() is false, no assert covers improved, and the derived closed solids that are not watertight ceiling falls, so the got <= want check passes too. The lane is green.
Measured directly against the current classifier:
golden SweptSolid open=3 tris=100 pre=0
run SweptSolid open=3 tris=100 pre=x
regressed=0 changed=0 improved=1 requires_bless=false
IMPROVED reasons=["no longer a genuine watertightness defect"]
This is the shape the module header already calls the worst of the three: a host that stops producing takes its own defects out of every sum, so a coverage loss reads as an improvement. Here it is the secondary diagnostic rather than the mesh, but the effect on the gate is the same. The pre reading is what separates "arrived torn" from "the boolean tore it", so losing it silently costs the census the attribution it exists to provide.
Suggested fix
Carry pre in reclassifications alongside rep and far, since the membership test for that list is "moves is_torn_solid without moving a count" and pre satisfies it. A reclassification outranks the gated flip, so the host files under changed, which requires a bless and is red.
This is not free and is why it was not folded into #3219's instrument PR:
- It re-routes the other direction too. A probe that starts running (
Failed -> Open(n)) currently files as regressed via worse_gated; under the fix it files as changed. Both are red and both require a bless, but the label changes.
- It changes the expectations of a pre-existing test,
a_no_void_pass_that_stops_failing_makes_the_host_a_gated_defect.
Both are defensible under the module's own doctrine, which says a relabel that moves a host into the gated population without counts moving is a change of question rather than a degradation. It wants its own review rather than a late addition to a PR scoped to the triangle-count classifier.
Provenance
Found in review of the census re-tessellation split. Deferred there deliberately, on the record, because it is pre-existing and orthogonal to that PR's scope.
The watertightness census treats a host's no-void probe going dark as the host getting better, and the lane stays green.
The mechanism
HostRow::is_torn_solidreads four things:open > 0, a closed-solid representation,!far, andpre != PreVoid::Failed.classifyhas a symmetric pair of arms on that predicate:When
process_no_voidsstarts returningNonefor a host,preflipsOpen(n) -> Failedwithopen,tris,coll,farandaltall unmoved. The second arm fires, and nothing else inclassifyhas anything to say, so the only reason attached to the host is that it is no longer a genuine defect.reclassificationsdoes not carrypre. It carriesrepandfar, on the grounds that those moveis_torn_solidwithout any count moving, which is exactly whatprealso does. So the host is not reclassified either.What that costs
The host lands in
improved.requires_bless()is false, no assert coversimproved, and the derivedclosed solids that are not watertightceiling falls, so thegot <= wantcheck passes too. The lane is green.Measured directly against the current classifier:
This is the shape the module header already calls the worst of the three: a host that stops producing takes its own defects out of every sum, so a coverage loss reads as an improvement. Here it is the secondary diagnostic rather than the mesh, but the effect on the gate is the same. The
prereading is what separates "arrived torn" from "the boolean tore it", so losing it silently costs the census the attribution it exists to provide.Suggested fix
Carry
preinreclassificationsalongsiderepandfar, since the membership test for that list is "movesis_torn_solidwithout moving a count" andpresatisfies it. A reclassification outranks the gated flip, so the host files underchanged, which requires a bless and is red.This is not free and is why it was not folded into #3219's instrument PR:
Failed -> Open(n)) currently files asregressedviaworse_gated; under the fix it files aschanged. Both are red and both require a bless, but the label changes.a_no_void_pass_that_stops_failing_makes_the_host_a_gated_defect.Both are defensible under the module's own doctrine, which says a relabel that moves a host into the gated population without counts moving is a change of question rather than a degradation. It wants its own review rather than a late addition to a PR scoped to the triangle-count classifier.
Provenance
Found in review of the census re-tessellation split. Deferred there deliberately, on the record, because it is pre-existing and orthogonal to that PR's scope.