# -*- coding: utf-8 -*- """The binding: ligament features, the production `covers`, the donor filter. Every piece here is invented and every mark is a `PNL...` placeholder, which is this project's convention -- no real panel mark, job or client name appears in this file. The worked-example shapes are rebuilt with invented marks because the geometry is what the tests are about, not the job. """ # pylint: disable=import-error,invalid-name import os import pytest from vibe import reinforcecore as core from vibe import reinforcebind as B from vibe import reinforcematch as match # ---------------------------------------------------------------- fixtures # The design number every fixture carries unless a test says otherwise. # # It is SHARED on purpose. A donor must be the same design as its target # (owner ruling, 2026-09-01, enforced in `DonorFilter`), so a fixture set # where every piece had its own design number would be a fixture set where # nothing can ever donate to anything -- and every test about geometry, # ranking, MASTER or the cap would be testing the design filter instead of # what it says on its name. Tests that are about the design rule pass `design` # explicitly; everything else stays inside one design and reads as before. DESIGN = 'PNL1.0' def piece(name, length, width, thickness, rects, reinforced=1, on_hold=0, master=False, design=DESIGN, elevation_band=None, elevation_group=None): """An index piece record. `rects` are (x0, x1, y0, y1[, through]). `elevation_band` is a `{'axis': ..., 'min': ..., 'max': ...}` dict (or None) -- the geometric FLOOR (owner's 2026-09-02 ruling). `band(...)` below is the convenience most tests actually want. `elevation_group` is the optional ACCELERATOR -- an opaque plant-declared string (MC's is `Tagged_Sheet`) -- present on neither fixture unless a test says so, which mirrors most real jobs. """ feats = [] for i, r in enumerate(rects): through = r[4] if len(r) > 4 else True feats.append(core.feature(name, i, r[0], r[1], r[2], r[3], through, 0.0 if through else 3.5, length, width, thickness)) return core.piece_record(name, 1, 'sig', reinforced, on_hold, design_number=design, length_ft=length, width_ft=width, thickness_in=thickness, features=feats, master=master, master_note='MASTER' if master else None, elevation_band=elevation_band, elevation_group=elevation_group) def band(tag, axis='X'): """A distinct elevation band for a fixture, keyed by a short tag. Not a real coordinate -- these tests are about the RANKING and the AFFINITY logic, not about `elevation_band()`'s own geometry (that is `test_reinforcecore.py`'s job). Each distinct `tag` gets its own 100 ft-wide slot on `axis` so two different tags never accidentally overlap, and the same `tag` always returns the identical band, so two fixtures built with `band('ELEV-3')` genuinely share one elevation. """ if tag is None: return None # A plain character-code sum, not `hash()` -- Python randomises string # hashing per process, and this has to return the SAME band for the # SAME tag every time it is called, not just within one run. slot = sum(ord(c) for c in (axis + str(tag))) % 1000 lo = float(slot) * 100.0 return {'axis': axis, 'min': lo, 'max': lo + 0.667} def kinds(feats): out = {} for f in feats: out[f['kind']] = out.get(f['kind'], 0) + 1 return out def find(feats, kind, x0, x1, y0, y1): for f in feats: if (f['kind'] == kind and abs(f['x0'] - x0) < 1e-6 and abs(f['x1'] - x1) < 1e-6 and abs(f['y0'] - y0) < 1e-6 and abs(f['y1'] - y1) < 1e-6): return f return None # ------------------------------------------------- what a ligament is def test_two_openings_leave_the_strip_between_them(): """The reframe, in one test: the concrete between the holes is a feature belonging to neither hole.""" p = piece('PNL601', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (9.0, 11.0, 2.0, 5.0)]) feats = B.features_for(p) strip = find(feats, B.STRIP_X, 6.0, 9.0, 2.0, 5.0) assert strip is not None assert strip['strip_ft'] == 3.0 # the gap between them assert strip['span_ft'] == 3.0 # how far it runs across assert strip['between'] == B.VOID_VOID def test_identical_holes_different_spacing_are_different_features(): """Same two holes, moved apart. The holes are identical; the strip is not. This is the whole point of the reframe.""" near = B.features_for(piece('PNL602', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (6.5, 8.5, 2.0, 5.0)])) far = B.features_for(piece('PNL603', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (9.0, 11.0, 2.0, 5.0)])) assert find(near, B.STRIP_X, 6.0, 6.5, 2.0, 5.0)['strip_ft'] == 0.5 assert find(far, B.STRIP_X, 6.0, 9.0, 2.0, 5.0)['strip_ft'] == 3.0 def test_ligament_runs_to_the_panel_edge(): p = piece('PNL604', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) feats = B.features_for(p) left = find(feats, B.STRIP_X, 0.0, 4.0, 2.0, 5.0) right = find(feats, B.STRIP_X, 6.0, 20.0, 2.0, 5.0) below = find(feats, B.STRIP_Y, 4.0, 6.0, 0.0, 2.0) above = find(feats, B.STRIP_Y, 4.0, 6.0, 5.0, 10.0) for f in (left, right, below, above): assert f is not None assert f['between'] == B.VOID_EDGE assert left['edge'] == 'x0' and right['edge'] == 'x1' assert below['edge'] == 'y0' and above['edge'] == 'y1' def test_a_void_flush_with_the_edge_leaves_no_ligament_there(): """No concrete, no feature. The flush condition shows up as the ABSENCE of the strip, which the set cover reads correctly.""" p = piece('PNL605', 20.0, 10.0, 8.0, [(0.0, 2.0, 2.0, 5.0)]) feats = B.features_for(p) assert not [f for f in feats if f['edge'] == 'x0'] assert [f for f in feats if f['edge'] == 'x1'] def test_no_ligament_is_claimed_through_a_third_void(): """A strip must be concrete you can point at. Two voids far apart with a third between them do not leave a strip spanning the lot.""" p = piece('PNL606', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (12.0, 14.0, 2.0, 5.0), (20.0, 22.0, 2.0, 5.0)]) feats = B.features_for(p) assert find(feats, B.STRIP_X, 6.0, 20.0, 2.0, 5.0) is None # through v1 assert find(feats, B.STRIP_X, 6.0, 12.0, 2.0, 5.0) is not None assert find(feats, B.STRIP_X, 14.0, 20.0, 2.0, 5.0) is not None def test_voids_in_different_height_bands_leave_no_strip_between_them(): """Requirement 6, at the construction end: an x-gap is only a strip if the two voids actually overlap in y.""" p = piece('PNL607', 20.0, 12.0, 8.0, [(4.0, 6.0, 1.0, 3.0), (9.0, 11.0, 8.0, 10.0)]) feats = B.features_for(p) assert not [f for f in feats if f['between'] == B.VOID_VOID] def test_never_measured_stays_never_measured(): """`features is None` must not become an empty list on the way through.""" p = core.piece_record('PNL608', 1, 'sig', 1, 0, error='solid failed') assert B.features_for(p) is None def test_measured_and_empty_is_a_list_not_none(): p = piece('PNL609', 20.0, 10.0, 8.0, []) assert B.features_for(p) == [] def test_include_voids_off_leaves_only_ligaments(): p = piece('PNL610', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) assert kinds(B.features_for(p, include_voids=False)).get(B.OPENING) is None assert kinds(B.features_for(p)).get(B.OPENING) == 1 # ------------------------------------------------------- the covers contract def test_identical_features_are_exact(): a = piece('PNL611', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) b = piece('PNL612', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) fa, fb = B.features_for(a), B.features_for(b) for i in range(len(fa)): assert B.covers(fa[i], fb[i]) == 0.0 def test_covers_never_raises_on_junk(): """Requirement 1: total. Anything unjudgeable is None, not an exception.""" good = B.features_for(piece('PNL613', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]))[0] for junk in (None, {}, {'kind': B.OPENING}, 'nonsense', 42, [], {'kind': B.OPENING, 'x0': 'a', 'x1': 1, 'y0': 0, 'y1': 1}): assert B.covers(junk, good) is None assert B.covers(good, junk) is None def test_covers_is_deterministic(): a = B.features_for(piece('PNL614', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]))[0] b = B.features_for(piece('PNL615', 20.0, 10.0, 8.0, [(4.1, 6.1, 2.0, 5.0)]))[0] assert len(set(B.covers(a, b) for _ in range(20))) == 1 def test_a_strip_never_covers_an_opening(): """Requirement: kinds do not mix, however well the rectangles line up.""" p = piece('PNL616', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (9.0, 11.0, 2.0, 5.0)]) feats = B.features_for(p) opening = [f for f in feats if f['kind'] == B.OPENING][0] strip = find(feats, B.STRIP_X, 6.0, 9.0, 2.0, 5.0) assert B.covers(strip, opening) is None assert B.covers(opening, strip) is None def test_strips_on_the_two_axes_do_not_mix(): x_strip = {'kind': B.STRIP_X, 'x0': 4.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'strip_ft': 2.0} y_strip = {'kind': B.STRIP_Y, 'x0': 4.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'strip_ft': 3.0} assert B.covers(x_strip, y_strip) is None def test_donor_strip_may_be_narrower_but_never_wider(): """The directional rule (requirement 3): bars detailed for a narrow strip fit a wider one; a cage for a wide strip does not fit narrower concrete.""" narrow = {'kind': B.STRIP_X, 'x0': 5.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'strip_ft': 1.0} wide = {'kind': B.STRIP_X, 'x0': 4.5, 'x1': 6.5, 'y0': 2.0, 'y1': 5.0, 'strip_ft': 2.0} assert B.covers(narrow, wide) is not None # narrow donor -> wide target assert B.covers(wide, narrow) is None # will not fit def test_a_feature_in_a_different_height_band_is_not_covered(): """Requirement 6. The measurement this rule comes from: two features share an x-range while sitting in different Z bands.""" low = {'kind': B.OPENING, 'x0': 4.0, 'x1': 6.0, 'y0': 1.0, 'y1': 3.0} high = {'kind': B.OPENING, 'x0': 4.0, 'x1': 6.0, 'y0': 8.0, 'y1': 10.0} assert B.covers(low, high) is None def test_position_is_absolute_not_proportional(): """Requirement 5: the same rectangle on panels of different lengths is the same feature, and a mid-panel rectangle at the same FRACTION is not.""" short = piece('PNL617', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) long = piece('PNL618', 40.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) scaled = piece('PNL619', 40.0, 10.0, 8.0, [(8.0, 12.0, 2.0, 5.0)]) s = [f for f in B.features_for(short) if f['kind'] == B.OPENING][0] l = [f for f in B.features_for(long) if f['kind'] == B.OPENING][0] p = [f for f in B.features_for(scaled) if f['kind'] == B.OPENING][0] assert B.covers(l, s) == 0.0 assert B.covers(p, s) is None def test_distance_is_in_inches_and_comparable_across_kinds(): """Requirement 4: one unit for every kind, and that unit is INCHES. The records are feet -- 0.5 ft of corner offset -- and `covers` crosses the unit seam exactly once on the way out, so both kinds come back as 6.00 in. A strip and an opening that are off by the same amount get the same number; there is no per-kind weighting and none was asked for. """ o1 = {'kind': B.OPENING, 'x0': 4.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0} o2 = {'kind': B.OPENING, 'x0': 4.5, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0} s1 = {'kind': B.STRIP_Y, 'x0': 4.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'strip_ft': 3.0} s2 = {'kind': B.STRIP_Y, 'x0': 4.5, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'strip_ft': 3.0} assert B.covers(o2, o1) == pytest.approx(6.0) # 0.5 ft -> 6 in assert B.covers(s2, s1) == pytest.approx(6.0) def test_the_feet_to_inch_conversion_happens_exactly_once(): """THE 12x GUARD. This project has already lost time to a conversion applied at the wrong boundary, so the factor is pinned by test. The records are and stay feet -- `covers` must not mutate them -- and the returned distance is exactly twelve times the feet figure, not once and not one hundred and forty-four times. """ a = {'kind': B.OPENING, 'x0': 0.0, 'x1': 10.0, 'y0': 0.0, 'y1': 10.0} b = {'kind': B.OPENING, 'x0': 1.0, 'x1': 10.0, 'y0': 0.0, 'y1': 10.0} assert B.covers(b, a) == pytest.approx(12.0) # 1.0 ft of offset assert a['x0'] == 0.0 and b['x0'] == 1.0 # records untouched assert B.EXACT_TOL_IN == pytest.approx(B.EXACT_TOL_FT * 12.0) # ------------------------------------------------------------- the grain # # Two decimal inches is 0.01 in, an order of magnitude finer than any # tolerance this tool uses. These are the tests that keep the DISPLAY the # owner asked for from turning into a claim of PRECISION nobody measured. def test_a_non_exact_distance_lands_on_the_eighth_inch_grain(): """Every distance the report can print is a multiple of 1/8 in.""" a = {'kind': B.OPENING, 'x0': 0.0, 'x1': 10.0, 'y0': 0.0, 'y1': 10.0} for offset_ft in (0.05, 0.1, 0.2, 0.37, 0.5, 1.0, 2.13): b = dict(a, x0=offset_ft) got = B.covers(b, a) steps = got / B.GRAIN_IN assert steps == pytest.approx(round(steps), abs=1e-9), (offset_ft, got) def test_differences_finer_than_the_grain_do_not_reorder_anything(): """0.01 in apart is not a difference this tool can measure, so the two donors come back EQUAL and fall through to the next tie-break rather than being separated by noise.""" t = {'kind': B.OPENING, 'x0': 0.0, 'x1': 10.0, 'y0': 0.0, 'y1': 10.0} near = dict(t, x0=0.0400) # 0.480 in of offset nearer = dict(t, x0=0.0392) # 0.470 in of offset -- 0.01 in closer assert B.covers(near, t) == B.covers(nearer, t) assert B.covers(near, t) == pytest.approx(0.5) def test_the_grain_never_swallows_the_difference_between_off_and_exact(): """Quantizing to 1/8 in would round a 1/16 in miss down to zero, and zero means EXACT -- the one word in this report that has to keep meaning measured-identical. A hair off is floored, never rounded to exact.""" t = {'kind': B.OPENING, 'x0': 0.0, 'x1': 10.0, 'y0': 0.0, 'y1': 10.0} hair = dict(t, x0=0.004) # 0.048 in -- under half a grain step got = B.covers(hair, t) assert got > 0.0 assert got == pytest.approx(B.EXACT_TOL_IN) assert B.covers(t, t) == 0.0 def test_through_and_blind_are_not_the_same_reinforcing(): a = {'kind': B.OPENING, 'x0': 4.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'through': True} b = dict(a, through=False) assert B.covers(a, b) is None assert B.covers(a, dict(a)) == 0.0 def test_unjudged_penetration_is_not_read_as_blind(): """`through=None` is could-not-judge. Treating it as False would invent a judgement nobody made -- the standing rule on this project.""" through = {'kind': B.OPENING, 'x0': 4.0, 'x1': 6.0, 'y0': 2.0, 'y1': 5.0, 'through': True} unjudged = dict(through, through=None) blind = dict(through, through=False) assert B.covers(unjudged, through) == 0.0 assert B.covers(through, unjudged) == 0.0 assert B.covers(unjudged, blind) == 0.0 assert B.covers(blind, through) is None # --------------------------------------------- the approximate-outline flag def test_an_approximated_edge_never_scores_exact(): """A piece whose outline the index cannot see must not be reported as an exact edge match. It ranks just behind exact, and is never called exact.""" p = piece('PNL620', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) exact = B.features_for(p, outline_approximate=False) approx = B.features_for(p, outline_approximate=True) edge = [i for i, f in enumerate(exact) if f['between'] == B.VOID_EDGE] assert edge for i in edge: assert B.covers(exact[i], exact[i]) == 0.0 assert B.covers(approx[i], exact[i]) == B.EXACT_TOL_IN assert B.covers(exact[i], approx[i]) == B.EXACT_TOL_IN def test_an_approximated_piece_still_covers_interior_ligaments_exactly(): """The flag is about edges. A strip between two voids does not touch the outline, so nothing about it was approximated.""" p = piece('PNL621', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (9.0, 11.0, 2.0, 5.0)]) exact = B.features_for(p, outline_approximate=False) approx = B.features_for(p, outline_approximate=True) i = exact.index(find(exact, B.STRIP_X, 6.0, 9.0, 2.0, 5.0)) assert B.covers(approx[i], exact[i]) == 0.0 def test_an_approximate_donor_ranks_behind_an_exact_one(): """End to end: the flag has to change the ANSWER, not just a field.""" target = piece('PNL622', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) good = piece('PNL623', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) approx = piece('PNL624', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) sug, info = B.propose(target, [good, approx], donor_filter=PNL, approximate={'PNL624'}) assert sug.best.donors == ('PNL623',) assert info['approximate_in_pool'] == ['PNL624'] # ------------------------------------------------------------ the filter def base(name, thickness=8.0, width=10.0, **kw): return piece(name, 20.0, width, thickness, [(4.0, 6.0, 2.0, 5.0)], **kw) # Marks here are the project's `PNL...` placeholders, so the tests state the # prefix they mean rather than borrowing the real one. That the SHIPPED # default is wall-panels-only is asserted directly, just below. PNL = B.DonorFilter(prefixes=('PNL',)) def test_the_shipped_default_declares_no_prefix_of_its_own(): """The owner's ruling still stands -- only wall panels donate -- but it is a JOB fact now, declared in the job knowledge and handed in by `suggest_for_piece` (see vibe/scope.py). A prefix baked in here would be one job's division of labour hardcoded into a shareable repository, which is the same silent exclusion this codebase exists to refuse. None means no prefix rule, which is what an UNDECLARED scope must produce: judge everything, and say so on the report. """ assert B.DonorFilter().prefixes is None def test_only_the_wanted_prefix_survives(): kept, rejected = B.select_donors( [base('PNL002'), base('BM001'), base('SS001'), base('CL001')], base('PNL001'), PNL) assert [r['name'] for r in kept] == ['PNL002'] assert rejected['prefix'] == ['BM001', 'CL001', 'SS001'] def test_thickness_must_match(): kept, rejected = B.select_donors( [base('PNL002', thickness=8.0), base('PNL003', thickness=12.0)], base('PNL001', thickness=8.0), PNL) assert [r['name'] for r in kept] == ['PNL002'] assert rejected['thickness'] == ['PNL003'] def test_width_is_not_filtered_by_default(): """The arguable one. Off by default so a filter never excludes a better-shaped donor -- the owner's standing correction.""" assert B.DonorFilter().max_width_diff_ft is None kept, _ = B.select_donors([base('PNL002', width=30.0)], base('PNL001', width=10.0), PNL) assert [r['name'] for r in kept] == ['PNL002'] def test_width_can_be_switched_on(): kept, rejected = B.select_donors( [base('PNL002', width=30.0), base('PNL003', width=10.5)], base('PNL001', width=10.0), B.DonorFilter(prefixes=('PNL',), max_width_diff_ft=1.0)) assert [r['name'] for r in kept] == ['PNL003'] assert rejected['width'] == ['PNL002'] def test_a_piece_is_not_its_own_donor(): kept, rejected = B.select_donors( [base('PNL001'), base('PNL002')], base('PNL001'), PNL) assert [r['name'] for r in kept] == ['PNL002'] assert rejected['self'] == ['PNL001'] def test_on_hold_is_never_a_donor(): """The index already drops these; the filter re-asserts it, because a record can reach `propose` from somewhere other than the cache.""" kept, rejected = B.select_donors( [base('PNL002', on_hold=1), base('PNL003', reinforced=0)], base('PNL001'), PNL) assert kept == [] assert rejected['not_eligible'] == ['PNL002', 'PNL003'] def test_never_measured_and_measured_empty_are_rejected_separately(): """The distinction the index keeps must survive the filter.""" unjudged = core.piece_record('PNL002', 1, 'sig', 1, 0, error='no solid') empty = piece('PNL003', 20.0, 10.0, 8.0, []) kept, rejected = B.select_donors([unjudged, empty], base('PNL001'), PNL) assert kept == [] assert rejected['unjudged'] == ['PNL002'] assert rejected['no_features'] == ['PNL003'] # --------------------------------- require_features INVERTS for a featureless # target (owner, 2026-09-01, hit on a real WP2.0 piece with no openings): "如 # 果扫描到目标没有opening,那么就找另一块没有opening的板子给target当doner。" def test_a_featureless_donor_is_kept_when_the_target_is_also_featureless(): """The reported defect, as a fixture: WP397-shaped, not WP397. A target measured to have no openings must not have its featureless donor dropped by the same rule that (correctly) drops one when the target has voids.""" target = piece('PNL001', 20.0, 10.0, 8.0, []) twin = piece('PNL002', 20.0, 10.0, 8.0, []) kept, rejected = B.select_donors([twin], target, PNL) assert [r['name'] for r in kept] == ['PNL002'] assert 'no_features' not in rejected def test_the_inversion_does_not_relax_design_thickness_or_scope(): """The owner's very next sentence: "很多其他东西依然是有用的,比如说design number。" One rule inverted; the rest of the filter is unmoved.""" target = piece('PNL001', 20.0, 10.0, 8.0, [], design='PNL2.0') wrong_design = piece('PNL002', 20.0, 10.0, 8.0, [], design='PNL1.0') wrong_thickness = piece('PNL003', 20.0, 10.0, 12.0, [], design='PNL2.0') out_of_scope = piece('BM001', 20.0, 10.0, 8.0, [], design='PNL2.0') kept, rejected = B.select_donors( [wrong_design, wrong_thickness, out_of_scope], target, PNL) assert kept == [] assert rejected['design'] == ['PNL002'] assert rejected['thickness'] == ['PNL003'] assert rejected['prefix'] == ['BM001'] def test_an_unjudged_target_does_not_take_the_inverted_path(): """`features is None` (never measured) must NOT read as `features == []` (measured, empty) -- the project's cardinal distinction. A donor nobody would want to see offered for a piece nobody could even measure.""" unjudged_target = core.piece_record('PNL001', 1, 'sig', 1, 0, error='no solid') featureless_donor = piece('PNL002', 20.0, 10.0, 8.0, []) kept, rejected = B.select_donors([featureless_donor], unjudged_target, PNL) assert kept == [] assert rejected['no_features'] == ['PNL002'] def test_a_donor_with_features_survives_a_featureless_target_too(): """Never rejected for this reason either way -- the question of whether it should rank behind a featureless twin is `shape_search_for`'s, not the filter's.""" target = piece('PNL001', 20.0, 10.0, 8.0, []) has_features = base('PNL002') kept, _rejected = B.select_donors([has_features], target, PNL) assert [r['name'] for r in kept] == ['PNL002'] # --------------------------------------------- the featureless-target search def test_shape_search_ranks_featureless_donors_above_ones_with_openings(): target = piece('PNL001', 20.0, 10.0, 8.0, []) featureless = piece('PNL002', 20.0, 10.0, 8.0, []) has_features = base('PNL003') search = B.shape_search_for(target, [has_features, featureless]) assert [r['name'] for r in search['eligible']] == ['PNL002'] assert [r['name'] for r in search['secondary']] == ['PNL003'] assert search['considered'] == 2 def test_shape_search_ranks_the_closer_shape_first(): target = piece('PNL001', 20.0, 10.0, 8.0, []) close = piece('PNL002', 20.5, 10.0, 8.0, []) far = piece('PNL003', 24.0, 10.0, 8.0, []) search = B.shape_search_for(target, [far, close]) assert [r['name'] for r in search['eligible']] == ['PNL002', 'PNL003'] assert search['degenerate'] is False def test_shape_search_flags_a_genuine_tie_as_degenerate(): """Two panels of the same design very often ARE the same length and width -- see `precast-nomenclature`. Ranking a coin flip as an order would be a false precision this tool refuses everywhere else.""" target = piece('PNL001', 20.0, 10.0, 8.0, []) twin_a = piece('PNL003', 20.0, 10.0, 8.0, []) twin_b = piece('PNL002', 20.0, 10.0, 8.0, []) search = B.shape_search_for(target, [twin_a, twin_b]) assert search['degenerate'] is True # Still ordered -- by name, the last tie-break -- just not claimed as a # ranking by fit. assert [r['name'] for r in search['eligible']] == ['PNL002', 'PNL003'] def test_shape_search_one_donor_is_not_degenerate(): """Nothing to rank between is a plain single answer, not a tie.""" target = piece('PNL001', 20.0, 10.0, 8.0, [], design='PNL2.0') lone = piece('PNL002', 20.0, 10.0, 8.0, [], design='PNL2.0') search = B.shape_search_for(target, [lone]) assert search['degenerate'] is False assert [r['name'] for r in search['eligible']] == ['PNL002'] def test_propose_finds_the_featureless_donor_for_a_featureless_target(): """End to end, off Revit: the fixture analogue of the real defect. A target with no openings must come back with its matching, featureless donor as the eligible pool, must not reject it, and must still refuse a donor of a different design.""" target = piece('PNL2_001', 26.4167, 9.8333, 8.0, [], design='PNL2.0') twin = piece('PNL2_002', 26.4167, 9.8333, 8.0, [], design='PNL2.0') wrong_design = piece('PNL1_001', 26.4167, 9.8333, 8.0, [], design='PNL1.0') has_openings = base('PNL2_003', design='PNL2.0') sug, info = B.propose(target, [twin, wrong_design, has_openings], donor_filter=PNL) assert sug is None assert info['target_status'] == 'no_features' search = info['shape_search'] assert search['ran'] is True assert [r['name'] for r in search['eligible']] == ['PNL2_002'] assert [r['name'] for r in search['secondary']] == ['PNL2_003'] all_named = ([r['name'] for r in search['eligible']] + [r['name'] for r in search['secondary']]) assert 'PNL1_001' not in all_named assert info['rejected_names']['design'] == ['PNL1_001'] assert 'no_features' not in info['rejected_names'] # ------------------------------------------------- the design-number filter # # Owner, 2026-09-01: "选择母版的目标,必须得是跟自己的design number一样的panel。 # 我刚在一个WP2.0上面跑了reinforce,给我俩WP1.0的母版,压根用不了。" 必须 -- a # filter, not a ranking term. Every test below is about that one word. def test_a_donor_of_another_design_is_not_a_donor(): """The reported defect, as one test: a `PNL2.0` target offered `PNL1.0` templates. It must not be a low-ranked suggestion; it must be gone.""" kept, rejected = B.select_donors( [base('PNL002', design='PNL1.0'), base('PNL003', design='PNL2.0')], base('PNL001', design='PNL2.0'), PNL) assert [r['name'] for r in kept] == ['PNL003'] assert rejected['design'] == ['PNL002'] def test_the_same_design_survives_and_nothing_else_does(): kept, _rejected = B.select_donors( [base('PNL002', design='PNL2.0'), base('PNL003', design='PNL2.0'), base('PNL004', design='PNL1.0'), base('PNL005', design='PNL30.0')], base('PNL001', design='PNL2.0'), PNL) assert [r['name'] for r in kept] == ['PNL002', 'PNL003'] def test_a_packet_suffix_is_not_a_different_design(): """The established nomenclature ruling, reused rather than reinvented: `.0` is a cover sheet, `.A` is a note further into the same packet, and a piece may carry the bare number. One design, one family, four spellings. This is `specformat.design_key` -- the same reduction Ticket QC already checks a piece against its ticket with -- and not a rule written here. """ kept, rejected = B.select_donors( [base('PNL002', design='PNL1.A'), base('PNL003', design='PNL1'), base('PNL004', design='PNL1.B1'), base('PNL005', design='PNL2.A')], base('PNL001', design='PNL1.0'), PNL) assert [r['name'] for r in kept] == ['PNL002', 'PNL003', 'PNL004'] assert rejected['design'] == ['PNL005'] def test_a_donor_whose_design_could_not_be_read_is_refused_not_assumed(): """COULD NOT JUDGE IS NOT A MATCH. `None == None` is true in Python and false in precast: two pieces nobody read are not the same design.""" kept, rejected = B.select_donors( [base('PNL002', design=None), base('PNL003', design=' '), base('PNL004', design='...')], base('PNL001', design='PNL1.0'), PNL) assert kept == [] assert rejected['design_unknown'] == ['PNL002', 'PNL003', 'PNL004'] def test_a_target_with_no_readable_design_matches_nobody(): kept, rejected = B.select_donors( [base('PNL002', design='PNL1.0')], base('PNL001', design=None), PNL) assert kept == [] assert rejected['design_target_unknown'] == ['PNL002'] def test_the_design_rule_is_on_by_default(): assert B.DonorFilter().match_design is True assert B.DonorFilter().design_re is None def test_the_scope_is_reported_before_the_design(): """Another engineer's beam is out of SCOPE; it was never a candidate, and calling it a design mismatch would bury the real reason.""" _kept, rejected = B.select_donors( [base('BM001', design='BM9.0')], base('PNL001', design='PNL1.0'), PNL) assert rejected == {'prefix': ['BM001']} def test_the_plant_pattern_is_used_when_one_is_given(): """`nomenclature.design_number_re` is plant knowledge and is handed in, never read here -- this module has to run with no knowledge layer at all. A pattern that stops at the letters makes PNL1 and PNL2 one design.""" loose = B.DonorFilter(prefixes=('PNL',), design_re=r'^([A-Za-z]+)') kept, _rejected = B.select_donors( [base('PNL002', design='PNL2.0')], base('PNL001', design='PNL1.0'), loose) assert [r['name'] for r in kept] == ['PNL002'] def test_ranking_inside_one_design_is_untouched(): """The filter removes candidates; it must not reorder the survivors. Same three donors, same target, with and without a cross-design distractor in the pool: identical proposals in identical order.""" target = piece('PNL801', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (10.0, 12.0, 2.0, 5.0)]) near = piece('PNL802', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (10.0, 12.0, 2.0, 5.0)]) far = piece('PNL803', 20.0, 10.0, 8.0, [(4.05, 6.05, 2.0, 5.0), (10.05, 12.05, 2.0, 5.0)]) other = piece('PNL804', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (10.0, 12.0, 2.0, 5.0)], design='PNL9.0') clean, _i = B.propose(target, [near, far], donor_filter=PNL) mixed, _j = B.propose(target, [near, far, other], donor_filter=PNL) assert clean.status == mixed.status assert ([p.donors for p in clean.proposals] == [p.donors for p in mixed.proposals]) assert ([p.distances for p in clean.proposals] == [p.distances for p in mixed.proposals]) assert 'PNL804' not in (mixed.best.donors or ()) # --------------------------------------------- the four design refusals # # None of them may degrade into offering a donor of another design, labelled # or otherwise. `propose` returns NO suggestion for every one. def test_no_donor_of_this_design_refuses_rather_than_offering_another(): target = piece('PNL901', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL2.0') pool = [piece('PNL902', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL1.0'), piece('PNL903', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL1.A')] sug, info = B.propose(target, pool, donor_filter=PNL) assert sug is None # not a ranked list of PNL1s assert info['design']['status'] == B.DESIGN_NONE_MATCH assert info['design']['refused'] is True assert info['design']['target_key'] == 'PNL2' assert info['design']['candidates'] == 2 assert info['design']['designs_seen'] == {'PNL1': 2} def test_an_index_that_never_recorded_the_design_is_unjudged_not_matching(): """A record written before the field existed. It is not evidence of anything, least of all of a match.""" target = piece('PNL911', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL2.0') old = base('PNL912') del old['design_number'] sug, info = B.propose(target, [old], donor_filter=PNL) assert sug is None assert info['design']['status'] == B.DESIGN_INDEX_NOT_RECORDED assert info['design']['index_status'] == core.DESIGN_NOT_RECORDED def test_an_index_whose_design_numbers_are_all_empty_is_unjudged(): """Measured on the real index, 2026-09-01: 773 pieces, every one of them `design_number: null`, because the build ran with no knowledge layer. The field was there; nobody had read it. Not one donor may be offered off that, and the refusal has to name a different fix from the one above.""" target = piece('PNL921', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL2.0') blank = [base('PNL922', design=None), base('PNL923', design=None)] sug, info = B.propose(target, blank, donor_filter=PNL) assert sug is None assert info['design']['status'] == B.DESIGN_INDEX_UNREAD assert info['design']['index_status'] == core.DESIGN_UNREAD def test_a_target_with_no_design_number_refuses_before_it_compares(): target = piece('PNL931', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design=None) pool = [base('PNL932', design='PNL1.0')] sug, info = B.propose(target, pool, donor_filter=PNL) assert sug is None assert info['design']['status'] == B.DESIGN_TARGET_UNKNOWN def test_a_pool_emptied_before_the_design_test_is_not_a_design_refusal(): """The scope, eligibility and 'never measured' all empty the pool BEFORE the design is looked at. Blaming the design rule for their work would hide the real reason under a confident sentence, so the design verdict stands down and NO_DONORS -- the older finding -- is what the page reports.""" target = piece('PNL941', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL2.0') held = base('PNL942', design='PNL1.0', on_hold=1) sug, info = B.propose(target, [held], donor_filter=PNL) assert info['design']['refused'] is False assert info['design']['ran'] is False assert sug is not None and sug.status == match.NO_DONORS def test_the_four_refusals_are_four_different_answers(): """They have four different fixes -- rebuild the index, map the role, fix the piece, detail a first one by hand -- so they may never collapse.""" assert len(set(B.DESIGN_REFUSALS)) == 4 assert B.DESIGN_OK not in B.DESIGN_REFUSALS def test_every_rejection_is_named_and_counted(): kept, rejected = B.select_donors( [base('PNL001'), base('BM001'), base('PNL002', thickness=12.0), base('PNL003')], base('PNL001'), PNL) assert [r['name'] for r in kept] == ['PNL003'] assert set(rejected) == {'self', 'prefix', 'thickness'} # -------------------------------------------------------------- end to end def test_the_worked_example_shape_picks_the_matching_donor(): """Rebuilt from the worked example with invented marks: a donor that matches the left two-thirds, and a distractor that matches nothing.""" target = piece('PNL701', 27.625, 11.5, 8.0, [ (0.0, 0.875, 1.125, 3.0), (0.0, 0.667, 11.292, 11.5, False), (6.5, 10.583, 0.354, 4.479), (14.344, 18.427, 0.354, 4.479), (24.042, 25.875, 1.125, 3.0), (24.25, 27.625, 6.25, 11.5)]) twin = piece('PNL702', 24.917, 11.5, 8.0, [ (0.0, 0.875, 1.125, 3.0), (0.0, 0.667, 11.292, 11.5, False), (6.5, 10.583, 0.354, 4.479), (14.344, 18.427, 0.354, 4.479), (24.042, 24.917, 1.125, 3.0), (24.25, 24.917, 11.292, 11.5, False)]) other = piece('PNL703', 21.0, 11.5, 8.0, [(3.0, 4.0, 7.0, 9.0)]) sug, info = B.propose(target, [twin, other], donor_filter=PNL) assert sug.status == match.PARTIAL assert 'PNL702' in sug.best.donors assert sug.best.exact_count > 0 # The right-end features have no donor here, and the result says so # rather than quietly covering them. assert sug.uncovered def test_no_donors_is_not_no_coverage(): target = base('PNL001') sug, info = B.propose(target, [], donor_filter=PNL) assert sug.status == match.NO_DONORS assert info['donors'] == 0 def test_a_target_never_measured_yields_no_suggestion(): target = core.piece_record('PNL001', 1, 'sig', 1, 0, error='no solid') sug, info = B.propose(target, [base('PNL002')], donor_filter=PNL) assert sug is None assert info['target_status'] == 'unjudged' def test_a_target_measured_with_no_voids_is_a_different_answer(): sug, info = B.propose(piece('PNL001', 20.0, 10.0, 8.0, []), [base('PNL002')], donor_filter=PNL) assert sug is None assert info['target_status'] == 'no_features' def test_explain_names_the_donor_for_every_target_feature(): target = base('PNL001') sug, info = B.propose(target, [base('PNL002')], donor_filter=PNL) rows = B.explain(sug, info) assert len(rows) == len(info['target_features']) assert all(r['donor'] == 'PNL002' and r['exact'] for r in rows) def test_explain_reports_an_uncovered_feature_as_uncovered(): target = piece('PNL001', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (14.0, 16.0, 2.0, 5.0)]) donor = piece('PNL002', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) sug, info = B.propose(target, [donor], donor_filter=PNL) rows = B.explain(sug, info) assert [r['donor'] for r in rows].count(None) > 0 def test_explain_surfaces_registry_feature_ids_for_target_and_donor(): """The rows carry the shared-vocabulary ids so a reader can see the numbering. An exact-twin donor shares the target's descriptor, hence its id -- 'target #k <-> donor #k'.""" target = base('PNL001') donor = base('PNL002') sug, info = B.propose(target, [donor], donor_filter=PNL) # Stamp the vocabulary the way `suggest_from_index` does: built from the # donor pool, carried as the plain registry dict. cache = core.new_cache('m') core.register_features(cache, [donor]) info['registry'] = cache['registry'] rows = B.explain(sug, info) assert rows row = rows[0] assert row['target_feature_id'] is not None assert row['donor_feature_id'] == row['target_feature_id'] def test_explain_target_id_is_none_when_no_donor_carries_the_shape(): """A target feature whose SHAPE no donor produced projects to None -- a read-only lookup miss, the informative "nobody has this shape" signal, and it does not grow the vocabulary.""" target = piece('PNL001', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (14.0, 17.0, 2.0, 6.0)]) donor = piece('PNL002', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) sug, info = B.propose(target, [donor], donor_filter=PNL) cache = core.new_cache('m') core.register_features(cache, [donor]) next_before = core.Registry.deserialize(cache['registry']).serialize()['next_id'] info['registry'] = cache['registry'] rows = B.explain(sug, info) # the target feature the donor cannot cover has a shape no donor produced novel = [r for r in rows if r['donor'] is None] assert novel assert all(r['target_feature_id'] is None for r in novel) # the read-only projection did not assign it a fresh id next_after = core.Registry.deserialize(info['registry']).serialize()['next_id'] assert next_after == next_before # --------------------------------------------------- MASTER, end to end # # The index records it, the matcher ranks on it, and this is the join. Two # things have to hold here and nowhere else: the pool's masters are reported # AFTER the donor filter (a master the thickness filter dropped is not one # this answer could have used), and the flag reaches the matcher at all. def test_the_pool_reports_only_the_masters_that_survived_the_filter(): target = base('PNL001') kept_master = base('PNL002', master=True) dropped_master = base('PNL003', thickness=12.0, master=True) plain = base('PNL004') sug, info = B.propose(target, [kept_master, dropped_master, plain], donor_filter=PNL) assert info['master_donors'] == ['PNL002'] assert 'PNL003' in info['rejected_names']['thickness'] def test_a_pool_with_no_master_says_so_with_an_empty_list_not_a_missing_key(): sug, info = B.propose(base('PNL001'), [base('PNL002')], donor_filter=PNL) assert info['master_donors'] == [] def test_the_master_flag_reaches_the_ranking(): """Two identical donors, one reviewed. The reviewed one is proposed first. They are geometrically indistinguishable -- same rectangle, same panel -- so the distance vectors are equal and only the tie-break separates them. PNL002 is listed first, so input order alone would put it on top. """ target = base('PNL001') sug, info = B.propose(target, [base('PNL002'), base('PNL003', master=True)], donor_filter=PNL) assert sug.best.donors == ('PNL003',) assert sug.best.masters == ('PNL003',) assert sug.proposals[1].donors == ('PNL002',) def test_a_master_does_not_outrank_a_better_fitting_donor(): """The owner's ruling, held at the layer that actually runs on the index. PNL003 is reviewed but its opening is 2 ft off; PNL002 is an exact twin of the target and is not reviewed. Fit wins. """ target = piece('PNL001', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) twin = piece('PNL002', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) loose = piece('PNL003', 20.0, 10.0, 8.0, [(4.5, 6.5, 2.0, 5.0)], master=True) sug, info = B.propose(target, [twin, loose], donor_filter=PNL) assert sug.best.donors == ('PNL002',) assert sug.best.master_count == 0 def test_explain_rows_carry_whether_the_covering_donor_was_reviewed(): target = base('PNL001') sug, info = B.propose(target, [base('PNL002', master=True)], donor_filter=PNL) rows = B.explain(sug, info) assert rows assert all(r['donor_master'] for r in rows if r['donor'] is not None) def test_an_unread_signal_is_reported_as_not_run_not_as_no_masters(): """Every donor `master=None` -- the role is unmapped, nothing was read.""" target = base('PNL001') pool = [base('PNL002'), base('PNL003')] for rec in pool: rec['master'] = None sug, info = B.propose(target, pool, donor_filter=PNL) assert info['master_donors'] == [] assert info['master_unjudged'] is True def test_a_pool_that_was_read_is_never_reported_as_unjudged(): sug, info = B.propose(base('PNL001'), [base('PNL002')], donor_filter=PNL) assert info['master_unjudged'] is False # --------------------------------------------- SAME ELEVATION, end to end # # The incident, and the ruling that fixed it. Owner, 2026-09-02, on a real # run against WP425: five donors tied on every existing criterion -- 1 # donor, 5/5 covered, 4 exact, 0 reviewed, 0.04 in total distance, all five # identical -- and the tie fell through to mark order, so WP133 printed # first though WP234 shares WP425's own building elevation: # "WP234明明在同一个elevation,为什么排名没有提前?" Approved as briefed the # same day ("同意,就这么做"): elevation is an AFFINITY, the LAST tie-break, # never a filter -- a cross-elevation donor with better coverage still wins. # # RULED AGAIN THE SAME DAY: elevation is a purely GEOMETRIC fact (a # thickness-axis coordinate band), never a hand-typed parameter -- see # `reinforcecore.elevation_band`'s module note. Fixtures below use `band(tag)` # (defined above, next to `piece`/`base`) rather than a bare string: the same # `tag` always returns the identical band, so `band('ELEV-3')` on two # fixtures genuinely means "the same wall plane" the way a shared string # label used to. def test_the_incident_five_tied_donors_one_shares_elevation_wins(): """WP425, reproduced with invented marks. Five donors, geometrically identical to the target and to each other -- a dead tie on donor count, exactness, MASTER and total distance -- and only one shares the target's building elevation band. It ranks first, and the report can say why: `sug.best.same_elevation` names it, exactly as `masters` would. Without the affinity term this fell through to mark order and printed the alphabetically-first donor instead of the one actually on the target's own elevation -- PNL133, not PNL234, which is exactly what happened on the real run this reproduces. """ target = base('PNL425', elevation_band=band('ELEV-3')) donors = [ base('PNL133', elevation_band=band('ELEV-1')), base('PNL166', elevation_band=band('ELEV-2')), base('PNL234', elevation_band=band('ELEV-3')), base('PNL267', elevation_band=band('ELEV-4')), base('PNL271', elevation_band=None), ] sug, info = B.propose(target, donors, donor_filter=PNL) assert sug.best.donors == ('PNL234',) assert sug.best.same_elevation == ('PNL234',) assert info['target_elevation'] == {'group': None, 'band': band('ELEV-3')} assert info['same_elevation_donors'] == ['PNL234'] assert info['same_elevation_sources'] == {'PNL234': core.ELEVATION_BY_BAND} def test_cross_elevation_donor_with_better_coverage_still_wins(): """The ranking-not-filtering rule, as an executable statement. PNL501 is on a different elevation and fits the target's opening exactly. PNL502 shares the target's elevation but is 0.5 ft off. Fit wins, every time -- elevation never promotes a worse-shaped donor past one the geometry has already ranked ahead of it. """ target = piece('PNL425', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], elevation_band=band('ELEV-3')) exact_other_elevation = piece( 'PNL501', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], elevation_band=band('ELEV-9')) loose_same_elevation = piece( 'PNL502', 20.0, 10.0, 8.0, [(4.5, 6.5, 2.0, 5.0)], elevation_band=band('ELEV-3')) sug, info = B.propose(target, [exact_other_elevation, loose_same_elevation], donor_filter=PNL) assert sug.best.donors == ('PNL501',) assert sug.best.same_elevation == () def test_a_target_with_no_determined_elevation_prefers_nobody(): """UNKNOWN IS A STATE, NOT A BLANK. The target's own elevation band could not be determined, so nothing in the pool can be preferred on it -- not even a donor whose band happens to be equally undetermined.""" target = base('PNL425', elevation_band=None) donors = [base('PNL133', elevation_band=band('ELEV-1')), base('PNL166', elevation_band=None)] sug, info = B.propose(target, donors, donor_filter=PNL) assert info['same_elevation_donors'] == [] assert sug.best.same_elevation == () def test_a_donor_with_no_determined_elevation_is_never_preferred(): """The reverse case: the TARGET's elevation band is known, but a donor's own could not be determined. That donor is never added to the affinity set, even though a real match might exist -- could-not-judge is never guessed as a match.""" target = base('PNL425', elevation_band=band('ELEV-1')) donors = [base('PNL133', elevation_band=None), base('PNL166', elevation_band=band('ELEV-9'))] sug, info = B.propose(target, donors, donor_filter=PNL) assert info['same_elevation_donors'] == [] def test_a_record_missing_the_elevation_band_key_entirely_does_not_crash(): """A pre-migration cache record -- built before this field existed -- has no 'elevation_band' key at all, not even one holding None. The affinity computation must read that the same as an explicit None rather than raising, because a stale cache is exactly what the first press after this change serves before a refresh rebuilds it.""" target = base('PNL425', elevation_band=band('ELEV-1')) donor = base('PNL133', elevation_band=band('ELEV-1')) del donor['elevation_band'] sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == [] assert sug.best.same_elevation == () def test_a_pool_with_no_same_elevation_donor_says_so_with_an_empty_list(): sug, info = B.propose(base('PNL425', elevation_band=band('ELEV-1')), [base('PNL133', elevation_band=band('ELEV-9'))], donor_filter=PNL) assert info['same_elevation_donors'] == [] def test_a_perpendicular_axis_donor_never_matches_even_numerically_close(): """The owner's explicit confirmation: a donor thin in global Y never shares an elevation with a target thin in global X, however close the coordinates happen to be -- that is a wall returning a corner, not the same wall plane.""" target = base('PNL425', elevation_band={'axis': 'X', 'min': 100.0, 'max': 100.667}) donor = base('PNL133', elevation_band={'axis': 'Y', 'min': 100.0, 'max': 100.667}) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == [] assert sug.best.same_elevation == () def test_a_donor_whose_band_only_abuts_the_targets_does_not_match(): """The pinned edge case: touching at exactly one coordinate, no interior overlap, is a stepped facade, not a shared wall plane.""" target = base('PNL425', elevation_band={'axis': 'X', 'min': 100.0, 'max': 100.667}) donor = base('PNL133', elevation_band={'axis': 'X', 'min': 100.667, 'max': 101.334}) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == [] assert sug.best.same_elevation == () # ---------------------------------------- THE ELEVATION ACCELERATOR (group) # # Owner's ruling, 2026-09-02, refining the geometric-only ruling the SAME # day once MC's real model turned up a usable grouping parameter: # "对MC而言,所有的墙应该都有一个参数叫Tagged_Sheet。如果俩panel这个参数一 # 样,那么他们就是同一个elevation,不用跑哪个几何引擎。" It is checked FIRST # where it exists, but geometry stays the floor -- most jobs (plenty of # plants, simple MC jobs) never map it, and that absence is normal, not a # stand-down. def test_same_group_matches_with_no_geometry_agreement_at_all(): """The shortcut, at its starkest: matching groups, PERPENDICULAR bands (which would never agree geometrically) -- the group still decides it, with `core.ELEVATION_BY_GROUP` naming the source.""" target = base('PNL425', elevation_group='E3.16', elevation_band={'axis': 'X', 'min': 100.0, 'max': 100.667}) donor = base('PNL133', elevation_group=' e3.16 ', elevation_band={'axis': 'Y', 'min': 500.0, 'max': 500.667}) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == ['PNL133'] assert info['same_elevation_sources'] == {'PNL133': core.ELEVATION_BY_GROUP} assert sug.best.same_elevation == ('PNL133',) def test_a_different_group_falls_back_to_geometry_rather_than_vetoing_it(): """A group mismatch does not exclude the donor -- it just fails to answer tier 1, and the geometric floor gets to try (and here, agrees).""" shared = {'axis': 'X', 'min': 100.0, 'max': 100.667} target = base('PNL425', elevation_group='E3.16', elevation_band=shared) donor = base('PNL133', elevation_group='E3.22', elevation_band=shared) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == ['PNL133'] assert info['same_elevation_sources'] == {'PNL133': core.ELEVATION_BY_BAND} def test_an_unmapped_group_on_both_sides_is_the_normal_case_geometry_answers(): """No `elevation_group` anywhere -- the common state on a job with no such parameter mapped -- and the geometric floor answers exactly as it would have if the accelerator did not exist.""" shared = {'axis': 'X', 'min': 100.0, 'max': 100.667} target = base('PNL425', elevation_band=shared) donor = base('PNL133', elevation_band=shared) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == ['PNL133'] assert info['same_elevation_sources'] == {'PNL133': core.ELEVATION_BY_BAND} def test_group_on_only_one_side_falls_back_to_geometry(): shared = {'axis': 'X', 'min': 100.0, 'max': 100.667} target = base('PNL425', elevation_group='E3.16', elevation_band=shared) donor = base('PNL133', elevation_group=None, elevation_band=shared) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['same_elevation_donors'] == ['PNL133'] assert info['same_elevation_sources'] == {'PNL133': core.ELEVATION_BY_BAND} # ----------------------------------------------------- the donor cap, plumbed # # The cap is the matcher's, and it is tested there. What has to be true HERE # is that `propose` hands it down and reports it, because a cap the join # silently drops is a cap that only exists in the unit tests. def test_propose_declares_the_cap_it_ran_under(): target = piece('PNL640', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) donor = piece('PNL641', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) sug, info = B.propose(target, [donor], donor_filter=PNL) assert info['donor_cap'] == 4 assert sug.donor_cap == 4 def test_the_shipped_cap_is_four(): """The owner's number, asserted where it ships rather than trusted.""" assert match.DEFAULT_MAX_DONORS == 4 def test_propose_passes_the_cap_through_to_the_matcher(): """Driven to 1 so the cap has to bite on a two-donor problem: the answer is the better single donor plus a named gap, never a second donor.""" target = piece('PNL642', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (20.0, 22.0, 2.0, 5.0)]) left = piece('PNL643', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) right = piece('PNL644', 30.0, 10.0, 8.0, [(20.0, 22.0, 2.0, 5.0)]) two, _ = B.propose(target, [left, right], donor_filter=PNL) assert len(two.best.donors) == 2 covered_by_two = two.best.covered_count one, info = B.propose(target, [left, right], donor_filter=PNL, max_donors=1) assert info['donor_cap'] == 1 assert len(one.best.donors) == 1 # never a second donor assert one.best.covered_count < covered_by_two assert one.capped_out # and it says what it dropped # The two kinds of gap stay apart: what the cap dropped is not what # nobody has, whatever else this pair of donors could not reach. assert not set(one.capped_out) & set(one.uncovered) # ------------------------------------------------- the whole run, NO DOCUMENT # # `suggest_from_index` is `suggest_for_piece` with the cached target record in # place of the live measurement, and it is the only thing standing between # this feature and a Revit licence. What is asserted here is that it is the # SAME run -- same filter, same covers, same info dict -- and that the two # places it must say something different (where the target came from, and what # a missing target means) really do say something different. def _snapshot(pieces, built_at='2026-08-30 09:00:00', scope=None): cache = core.new_cache('a model') cache['built_at'] = built_at cache['scope'] = scope cache['pieces'] = dict((p['name'], p) for p in pieces) return cache def test_a_target_is_answered_straight_out_of_the_snapshot(): target = piece('PNL700', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (20.0, 22.0, 2.0, 5.0)], reinforced=0) donor = piece('PNL701', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0), (20.0, 22.0, 2.0, 5.0)]) cache = _snapshot([target, donor]) sug, info = B.suggest_from_index(cache, 'PNL700') assert sug is not None assert info['offline'] is True assert info['target_source'] == 'index' assert info['built_at'] == '2026-08-30 09:00:00' assert info['donor_names'] == ['PNL701'] assert sug.status == match.COMPLETE def test_the_target_record_is_never_offered_as_its_own_donor_pool(): """A not-yet-reinforced target sits in the same file as the donors now. It may not donate to anybody, including to another target.""" a = piece('PNL702', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0) b = piece('PNL703', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0) sug, info = B.suggest_from_index(_snapshot([a, b]), 'PNL702') assert info['donors'] == 0 assert sug.status == match.NO_DONORS def test_a_missing_target_offline_is_not_the_same_as_missing_from_the_model(): """With no model open nobody can say whether the piece exists.""" sug, info = B.suggest_from_index(_snapshot([]), 'PNL704') assert sug is None assert info['target_status'] == 'not_in_index' assert info['offline'] is True def test_the_same_call_from_the_live_path_still_says_not_in_model(): sug, info = B.suggest_from_index(_snapshot([]), 'PNL705', offline=False) assert sug is None assert info['target_status'] == 'not_in_model' # -------------------------------------------------------- the scope, and D2 def _scope(prefixes): from vibe import scope as scopelib return scopelib.Scope(prefixes=prefixes) def test_an_in_scope_target_is_never_annotated_as_out_of_scope(): """Verified against a live run, 2026-08-30: the info dict carried `target_in_scope: True` AND the "JUDGED OUTSIDE THE DECLARED SCOPE, AT YOUR REQUEST" annotation at the same time, because the name was passed to `Scope.annotation` unconditionally. A report that contradicts itself in one dict teaches the reader to skip both lines.""" target = piece('PNL706', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0) donor = piece('PNL707', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) _sug, info = B.suggest_from_index(_snapshot([target, donor]), 'PNL706', the_scope=_scope(['PNL'])) assert info['scope']['target_in_scope'] is True assert info['scope']['target_annotation'] is None def test_an_out_of_scope_target_is_still_annotated(): """The fix must not silence the case the annotation exists for.""" target = piece('BM708', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0) donor = piece('PNL709', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) _sug, info = B.suggest_from_index(_snapshot([target, donor]), 'BM708', the_scope=_scope(['PNL'])) assert info['scope']['target_in_scope'] is False assert 'OUTSIDE THE DECLARED SCOPE' in info['scope']['target_annotation'] def test_the_scope_bounds_the_offline_donor_pool_the_same_way(): target = piece('PNL710', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0) mine = piece('PNL711', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) theirs = piece('BM712', 30.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)]) _sug, info = B.suggest_from_index(_snapshot([target, mine, theirs]), 'PNL710', the_scope=_scope(['PNL'])) assert info['donor_names'] == ['PNL711'] assert info['rejected']['prefix'] == 1 # --------------------------------------------------------- the outline audit def test_the_audit_is_read_by_folder_when_there_is_no_document(tmp_path): import json folder = str(tmp_path) handle = open(os.path.join(folder, B.AUDIT_FILE), 'wb') try: handle.write(json.dumps({'approximate': ['PNL713']}).encode('utf-8')) finally: handle.close() assert B.load_audit_at(folder) == set(['PNL713']) def test_never_audited_stays_None_and_never_becomes_an_empty_set(tmp_path): """Never checked and checked-and-found-none are different answers.""" assert B.load_audit_at(str(tmp_path)) is None def test_the_offline_run_reduces_designs_with_the_pattern_in_the_file(): """`nomenclature.design_number_re` is plant knowledge and there is no knowledge layer with no model open, so the index stamps it and this is where it gets picked up. Without it, offline and the button could reduce the same two numbers to different families -- and the whole point of the family is deciding who may donate.""" target = piece('PNL950', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0, design='PNL1.0') other = piece('PNL951', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL2.0') snap = _snapshot([target, other]) strict, info = B.suggest_from_index(snap, 'PNL950') assert strict is None # PNL1 is not PNL2 assert info['design']['status'] == B.DESIGN_NONE_MATCH # The same file, stamped with a pattern that stops at the letters: now # they are one design and the donor is offered. snap['nomenclature'] = {'design_number_re': r'^([A-Za-z]+)'} loose, info = B.suggest_from_index(snap, 'PNL950') assert info['donor_names'] == ['PNL951'] assert loose is not None def test_an_index_with_no_stamped_pattern_falls_back_rather_than_refusing(): """An index built before the stamp is not an index that cannot be read. It falls back to the built-in pattern, which is what every other reader of an unmapped nomenclature in this codebase already does.""" target = piece('PNL960', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], reinforced=0, design='PNL1.0') donor = piece('PNL961', 20.0, 10.0, 8.0, [(4.0, 6.0, 2.0, 5.0)], design='PNL1.A') snap = _snapshot([target, donor]) del snap['nomenclature'] sug, info = B.suggest_from_index(snap, 'PNL960') assert info['donor_names'] == ['PNL961'] assert sug is not None