draftwright 0.4.21__tar.gz → 0.4.22__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {draftwright-0.4.21 → draftwright-0.4.22}/CHANGELOG.md +3 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/PKG-INFO +2 -2
- {draftwright-0.4.21 → draftwright-0.4.22}/docs/reference/recogniser-capabilities.md +3 -3
- {draftwright-0.4.21 → draftwright-0.4.22}/pyproject.toml +6 -2
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/inspection_contract.py +1 -1
- draftwright-0.4.22/tests/_evidence_contract.py +61 -0
- draftwright-0.4.22/tests/_mutation_corpus.py +127 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/conftest.py +2 -0
- draftwright-0.4.22/tests/test_clone_budget.py +149 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_inspection_contract.py +1 -1
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1369_hole_completeness_evidence.py +9 -5
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1370_countersink_completeness_evidence.py +30 -20
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1370_double_d_completeness_evidence.py +21 -17
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1370_hole_pattern_completeness_evidence.py +21 -15
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1371_flat_completeness_evidence.py +31 -33
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1371_polygonal_stock_completeness_evidence.py +23 -27
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1372_groove_completeness_evidence.py +43 -37
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1372_pad_completeness_evidence.py +31 -36
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1372_pocket_completeness_evidence.py +31 -33
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1372_pocket_pattern_completeness_evidence.py +23 -29
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1372_polygonal_boss_completeness_evidence.py +28 -31
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1373_plate_completeness_evidence.py +37 -40
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1374_chamfer_completeness_evidence.py +32 -33
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1374_fillet_completeness_evidence.py +30 -33
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1374_turned_step_completeness_evidence.py +32 -33
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_recogniser_capabilities.py +1 -1
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_step_analysis_evaluation.py +13 -0
- draftwright-0.4.22/tests/test_version_bump_ci.py +250 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_workflows.py +176 -17
- draftwright-0.4.21/tests/test_recognition.py +0 -861
- {draftwright-0.4.21 → draftwright-0.4.22}/.gitignore +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/LICENSE +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/README.md +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/docs/adr/README.md +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/docs/reference/sheet.md +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/skills/SKILL.md +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/_build_profile.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/_core.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/_geometry.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/_pmi_part21.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/_warnings.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/analysis.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotate.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/_common.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/balloons.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/from_model.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/gears.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/holes.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/leaders.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/orchestrator.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/annotations/sections.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/audit.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/blend_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/builder.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/cli.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/compose.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/drawing.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/evaluation/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/evaluation/step_analysis.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/export.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/feature_identity.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/fits.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/inspection.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/intents.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/layout.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/_registry.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/angled_step_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/blend_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/chamfer_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/channel_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/circular_blind_step_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/evidence.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/fillet_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/flat_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/gear_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/groove_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/hole_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/ink_overlap.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/issues.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/oriented_slot_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/pad_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/paired_ramp_step_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/passage_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/plate_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/pmi_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/pocket_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/pocket_pattern_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/polygonal_boss_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/polygonal_stock_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/prismatic_pocket_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/profiled_bore_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/quality.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/rectangular_blind_slot_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/requirements.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/round_bottom_blind_slot_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/section_recess_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/slot_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/structural.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/through_step_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/linting/turned_step_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/make_drawing.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/callout.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/compiled.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/declare.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/detect.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/ir.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/planner.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/model/pmi_lowering.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/oriented_slot_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/plate_correspondence.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/pmi.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/projection.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/py.typed +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recogniser_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recogniser_policy.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recogniser_schema.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recognition/__init__.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recognition_cache.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recognition_frame.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/recognition_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/registry.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/repair.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/reporting.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/score.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/section_recess_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/sheet.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/sheet_emit.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/src/draftwright/view_plan.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/_kernel.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/_layout_sig.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/_recogniser_public_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/_section_recess_cases.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/ap242_single_cylinder_diameter.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/README.md +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/blind-hole.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-asymmetric.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-compound.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-overlap.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-plain.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-planar-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-planar-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-planar-z.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/chamfer-turned.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-chamfers-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-countersinks-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-double-d-bores-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-fillets-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-flats-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-grooves-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-hole-patterns-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-plates-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-pocket-patterns-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-pockets-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-polygonal-bosses-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-polygonal-stock-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-rectangular-pads-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-turned-steps-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/corpus-v1.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/countersink-deburr.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/countersink-external-cone.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/countersink-mixed-pair.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/countersink-single.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/countersink-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/countersink-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-axis-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-axis-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-blind.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-coaxial-compound.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-opposed-blind.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-roll-30.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-round-bore.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-single-z.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/double-d-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-compound.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-overlap.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-plain.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-planar-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-planar-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-planar-z.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-repeated.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/fillet-turned.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-coaxial.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-double-d.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-lone-d.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-nonround.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-slanted-double-d.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/flat-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-compound.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-lone-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-lone-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-lone-z.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-monotonic-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-narrow.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/groove-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-compound-equal.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-detached-body-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-full-span-ledge-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-nested-staircase-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-x-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-x-positive.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-y-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-y-positive.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-z-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pad-z-positive.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pattern-ambiguous.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pattern-grid.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pattern-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pattern-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plain-block.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-compound-equal.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-cross-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-cross-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-detached-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-rotational-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-single-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-t-xz.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-t-yz.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-thick-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-u-additive.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/plate-u-cut.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-compound.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-edge-anchored.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-lone.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-opposed.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-pattern-ambiguous.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-pattern-grid.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-pattern-linear.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-pattern-pair.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-pattern-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-pattern-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-prismatic-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-side.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-through-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/pocket-two-equal.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-compound-equal.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-detached-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-in-plane-rotated.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-other-protrusions-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-recess-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-stock-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-boss-z.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-compound-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-cylinder-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-irregular-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-octagon-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-recess-negative.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-roll17.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-translated.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/polygonal-stock-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-axis-x.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-axis-y.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-axis-z.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-compound.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-repeated-lengths.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-through-bore.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-topology-a.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-topology-b.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/evaluation/turned-step-translated-blind-bore.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/grm03_thumbwheel_drive_screw_ap242_pmi.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/grm04_drive_plate.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/issue_1247_angled_blind_step.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/issue_915_case_study_2.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/bracket_section.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/centered_rebate.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/chamfered.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/filleted.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/flange_dense.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/grid_plate.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/grooved_shaft.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/hex_bar.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/holed_slot.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/pocketed.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/prismatic_ladder.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/scattered_plate.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/side_drilled.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/refactor_golden/turned_stepped.json +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_add_dimension.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_adr0018_arrangement_gate.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_adr0018_view_routing.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_adr0018_view_selection.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_adr_corpus.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_agents_guide.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_api_docs.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_architecture_docs.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_audit_differential.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_balloon_ring_standoff.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_build_profile_harness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_carve_free_position_callers.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_compiled_plan_boundary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_counting_calls.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_declare.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_declared_recognition_gate.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_dense_sheet_canary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_deprecation_dates.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_detect_once.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_detect_registry.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_dimension_role_vocabulary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_drawing_encapsulation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_e2e_slice.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_e2e_standards.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_export_dxf_curves.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_export_dxf_zoom.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_export_reproducible.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_external_recognition_boundary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_fillets_adjacency.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_fits.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_flat_completeness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_flat_stock_identity.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_flat_stock_opposition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_gdt_placement.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_geometry_graph_spike.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_grid_lattice_convention.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_import_boundaries.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_iso_nts_caption_placement.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1000_envelope_reuse.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1006_measurement_comparison.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1058_wheel_profile.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1073_cross_body_patterns.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1082_polygonal_stock.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1086_declared_gears.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1130_view_planning_evidence.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1142_hole_leader_labels.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1143_hole_completeness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1144_transactional_hole_table.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1146_scale_completeness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1147_legibility_pair_aggregation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1153_contradictory_dimensions.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1154_one_owner_per_measurement.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1155_grm04_sheet_use.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1166_cross_pass_feature_leaders.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1176_quality_fidelity.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1177_angular_dimensions.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1187_unroutable_leaders.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1188_per_view_assignment.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1190_section_decision.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1196_deterministic_view_names.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1202_observed_drawing_consumer.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1204_multiscale_view_issues.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1209_linear_pmi_witnesses.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1215_envelope_tolerance.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1216_callout_reservation_measures_ink.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1216_pairwise_across_scale_groups.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1217_claimed_representations.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1217_the_facility_is_shared.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1219_location_claims_its_own_axis.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1229_ledger_member_keying.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1240_iso_above_strip_visibility.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1245_passage_disposition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1246_prismatic_pocket_disposition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1247_angled_step_disposition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1254_turned_chamfers.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1260_view_constraints.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1262_automatic_turned_views.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1276_turned_leader_targets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1281_turned_fillets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1296_cylindrical_diameter_pmi.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1298_manufacturing_requirements.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1299_page_escalation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1308_machined_leader_analytics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1312_engine_costs.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1325_nominal_agreement.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1332_overlap_remedy.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1332_zone_labels.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1333_bounded_ink_repair.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1334_prevent_ink.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1336_grm03_ap242_pmi_fixture.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1338_scale_before_page_escalation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1349_precision_display.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1350_detected_takeover.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1351_structured_note_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1352_searchable_pdf_text.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1353_cnc_authoritative_workflow.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1357_framed_activation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1357_framed_boundary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1357_plural_turned_profiles.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1357_pmi_frame.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1360_thread_depth.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1378_diameter_leader_targets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1382_046_step_inventory.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1382_circular_blind_step_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1382_framed_step_family_evidence.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1382_paired_ramp_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1382_through_step_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1390_sheet_registration.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1392_recognisers_048.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1395_degenerate_iso_region.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1396_layout_advisories.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1397_unverifiable_requirement_message.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1421_rectangular_blind_slot_completeness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1421_rectangular_blind_slot_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1421_round_bottom_blind_slot_completeness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1421_round_bottom_blind_slot_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1432_adoption.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1432_boundary_failures.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1432_oriented_slot_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1433_blend_semantics.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_boss_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_channel_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_cli_report_sidecar.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_generation_snapshot.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_nested_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_occurrence_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_pattern_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_plate_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_policy_dispositions.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_report_projection.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_report_writer.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_through_step_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1438_turned_step_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1450_boss_blend_ownership.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1460_step_inspection.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1466_dimension_options.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1466_semantic_sides.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1471_boundary_failures.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1471_evidence_schema.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1471_groove_profile.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1471_section_recess_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1471_section_recess_pockets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1479_radius_leader_targets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1485_curved_pockets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1485_quiddity_024_boundary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1485_rounded_pockets.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_367_leader_ink.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_443_grm03_axial_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_563_placement_intent.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_676_polygonal_boss.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_740_leader_assignment.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_798_floor_cardinality.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_798_material_field.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_798_silhouette_lint.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_827_real_part_canary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_883_location_identity.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_885_prismatic_coverage.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_909_sloped_profile.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_915_dense_case.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_916_pocket_leader.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_917_open_channel.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_924_zero_length_shoulders.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_955_height_contingency.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_958_cross_solid_recognition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_label_provenance.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_layout.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_layout_cleanliness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_layout_hypothesis.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_layout_property.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_leader_footprint.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_lint_box_cache.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_lint_ink_overlap.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_lint_reconciliation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_lint_structural.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_linting.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_location_vocabulary.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_make_drawing.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_note_verb.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_object_aspects.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_occupancy_boxes.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_parameter_id.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_part_model.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pitch_dim_footprint.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pmi.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pmi_datum_lowering.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pmi_gtol_lowering.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pmi_part21.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pocket_pattern.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_pocket_pattern_recognition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_principal_profile_classifier.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_private_test_attr_reads.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_private_test_imports.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_quality_components.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_recogniser_adoption.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_recogniser_contract.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_recognition_result.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_refactor_golden.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_registry.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_render_seam.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_repack_geometry_seam.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_score.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_script_detail_parity.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_shared_box_memo.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_emit.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_gdt.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_identity_invariant.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_notes.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_of.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_section.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_sheet_tables.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_slanted_blind_step.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_slot_completeness.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_slot_pattern.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_slot_pattern_recognition.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_soft_deprecation.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_solve_trace.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_strip_layout.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_suppression_ledger.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_suppression_marks.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_tolerances.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_turned_steps.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_view_plan.py +0 -0
- {draftwright-0.4.21 → draftwright-0.4.22}/tests/test_witness_label_reconciliation.py +0 -0
|
@@ -154,6 +154,9 @@
|
|
|
154
154
|
|
|
155
155
|
### Changed
|
|
156
156
|
|
|
157
|
+
- Updated the exact Quiddity runtime and declared-inspection contract to 0.2.5 for the
|
|
158
|
+
provider's recognition performance improvements.
|
|
159
|
+
|
|
157
160
|
- Production recognition now consumes published `quiddity==0.2.2`. Unified section-recess
|
|
158
161
|
occurrences and their same-run patterns feed the existing pocket, channel and blind-slot
|
|
159
162
|
drawing grammar. Original occurrence ownership, independent completeness and explicit
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: draftwright
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.22
|
|
4
4
|
Summary: Automated technical-drawing generation for build123d
|
|
5
5
|
Project-URL: Homepage, https://github.com/pzfreo/draftwright
|
|
6
6
|
Project-URL: Repository, https://github.com/pzfreo/draftwright
|
|
@@ -690,7 +690,7 @@ Requires-Dist: build123d<0.12,>=0.11; python_full_version >= '3.13'
|
|
|
690
690
|
Requires-Dist: numpy>=1.24
|
|
691
691
|
Requires-Dist: pillow>=10
|
|
692
692
|
Requires-Dist: pypdfium2>=4
|
|
693
|
-
Requires-Dist: quiddity==0.2.
|
|
693
|
+
Requires-Dist: quiddity==0.2.5
|
|
694
694
|
Requires-Dist: reportlab>=4.0
|
|
695
695
|
Requires-Dist: steputils==0.1
|
|
696
696
|
Requires-Dist: svglib>=1.5
|
|
@@ -70,10 +70,10 @@ issue. The contract test derives package record outputs, converter registries, l
|
|
|
70
70
|
and emitter branches independently, so copying a new name into the declaration alone cannot make CI
|
|
71
71
|
pass.
|
|
72
72
|
|
|
73
|
-
### Quiddity 0.2.
|
|
73
|
+
### Quiddity 0.2.5 runtime contract
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
The runtime pins the published `quiddity==0.2.5` package, following the 0.2.4 adoption in
|
|
76
|
+
[#1486](https://github.com/pzfreo/draftwright/pull/1486) and the migration in
|
|
77
77
|
[#1471](https://github.com/pzfreo/draftwright/issues/1471). Its public `quiddity`, `quiddity.evidence` and
|
|
78
78
|
`quiddity.inspection` surfaces supply recognition, exact occurrence evidence and declared geometry
|
|
79
79
|
reads. There is one recognition aggregate per build; consumers project that result rather than
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwright"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.22"
|
|
8
8
|
description = "Automated technical-drawing generation for build123d"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -18,7 +18,7 @@ dependencies = [
|
|
|
18
18
|
"build123d>=0.9.0,<0.11 ; python_full_version < '3.13'",
|
|
19
19
|
"build123d>=0.11,<0.12 ; python_full_version >= '3.13'",
|
|
20
20
|
"build123d-drafting-helpers>=0.14.2",
|
|
21
|
-
"quiddity==0.2.
|
|
21
|
+
"quiddity==0.2.5",
|
|
22
22
|
"numpy>=1.24",
|
|
23
23
|
# PNG raster export (SVG→PDF→PNG). Both permissively licensed (Pillow HPND; pypdfium2
|
|
24
24
|
# Apache-2.0 wrapping Google PDFium BSD-3) and ship pre-built wheels with NO native system
|
|
@@ -167,6 +167,10 @@ dev = [
|
|
|
167
167
|
"jsonschema>=4,<5",
|
|
168
168
|
"mypy>=2.1.0",
|
|
169
169
|
"pytest>=8",
|
|
170
|
+
# `coverage` is invoked directly by the CI `coverage-report` job (combine/xml/html/
|
|
171
|
+
# report); it arrives transitively via pytest-cov, but the job depends on the console
|
|
172
|
+
# script, so declare it.
|
|
173
|
+
"coverage>=7",
|
|
170
174
|
"pytest-cov>=5",
|
|
171
175
|
"pytest-split>=0.8",
|
|
172
176
|
"pytest-timeout>=2",
|
|
@@ -16,7 +16,7 @@ from quiddity.inspection import inspection_api_manifest
|
|
|
16
16
|
CONSUMER_INSPECTION_FORMAT = "draftwright-inspection-api"
|
|
17
17
|
CONSUMER_INSPECTION_FORMAT_VERSION = 1
|
|
18
18
|
SUPPORTED_INSPECTION_API_MAJOR = 1
|
|
19
|
-
SUPPORTED_RECOGNISER_VERSION = "0.2.
|
|
19
|
+
SUPPORTED_RECOGNISER_VERSION = "0.2.5"
|
|
20
20
|
_DISTRIBUTION = "quiddity"
|
|
21
21
|
_PROVIDER_FORMAT = "quiddity-inspection-api"
|
|
22
22
|
_NAMESPACE = "quiddity.inspection"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Per-family evidence contracts that every `*_completeness_evidence` module asserts.
|
|
2
|
+
|
|
3
|
+
These bodies were written out once per feature family — thirteen copies of the
|
|
4
|
+
`_<family>_model_outcomes` check, eleven of the one-recognition check — differing only
|
|
5
|
+
in which family symbol they named. That is the growth pattern `test_clone_budget.py`
|
|
6
|
+
exists to stop: the same assertion re-paid on every CI run, and one more copy to write
|
|
7
|
+
(and to get subtly wrong) with each new recogniser family.
|
|
8
|
+
|
|
9
|
+
Each function here is the single body; the per-family test calls it with its own
|
|
10
|
+
symbols, so the assertion still runs once per family and the evidence is unchanged.
|
|
11
|
+
Adding a family should add a call, not a copy.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from collections.abc import Callable
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def assert_missing_model_outcomes_fail_closed(
|
|
20
|
+
monkeypatch,
|
|
21
|
+
outcomes_attr: str,
|
|
22
|
+
states: Callable[..., object],
|
|
23
|
+
) -> None:
|
|
24
|
+
"""A family whose per-occurrence outcomes vanish scores `unknown`, never `supported`.
|
|
25
|
+
|
|
26
|
+
`outcomes_attr` is the family's `_<family>_model_outcomes` in
|
|
27
|
+
`draftwright.evaluation.step_analysis`; `states` is the module's own `_states`
|
|
28
|
+
reader, so each family still exercises its own observer and fixture part.
|
|
29
|
+
"""
|
|
30
|
+
import draftwright.evaluation.step_analysis as step_analysis
|
|
31
|
+
|
|
32
|
+
monkeypatch.setattr(step_analysis, outcomes_attr, lambda *_args: [])
|
|
33
|
+
# `set(...)`: a few families' `_states` returns a list, the rest a set. Both mean
|
|
34
|
+
# "every observed boundary state", and both must be exactly `unknown` here.
|
|
35
|
+
assert set(states("ir_adapter")) == {"unknown"}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def assert_observer_uses_one_build_owned_recognition(
|
|
39
|
+
monkeypatch,
|
|
40
|
+
family: str,
|
|
41
|
+
part: object,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""ADR 3: the observer scores the build's OWN aggregate, recognising exactly once.
|
|
44
|
+
|
|
45
|
+
A second `build_recognition_evidence` call would mean the facts being scored and the
|
|
46
|
+
features they are matched against came from different recognition runs.
|
|
47
|
+
"""
|
|
48
|
+
import draftwright.analysis as analysis
|
|
49
|
+
from draftwright.evaluation.step_analysis import _default_observers
|
|
50
|
+
|
|
51
|
+
original = analysis.build_recognition_evidence
|
|
52
|
+
calls = 0
|
|
53
|
+
|
|
54
|
+
def counted(*args, **kwargs):
|
|
55
|
+
nonlocal calls
|
|
56
|
+
calls += 1
|
|
57
|
+
return original(*args, **kwargs)
|
|
58
|
+
|
|
59
|
+
monkeypatch.setattr(analysis, "build_recognition_evidence", counted)
|
|
60
|
+
assert _default_observers()[family](part)
|
|
61
|
+
assert calls == 1
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""The smallest corpus subset that still exercises a provider mutation.
|
|
2
|
+
|
|
3
|
+
The `weakening_provider_*` / `deleting_provider_*` tests damage the provider and assert
|
|
4
|
+
that the benchmark's score falls. They read `detection` and `parameter_fidelity` only —
|
|
5
|
+
never `downstream_usefulness`, `complete_cases` or `conformant_cases` — yet they scored
|
|
6
|
+
every fixture in the family's corpus, and the drawing_consumer observer builds a full
|
|
7
|
+
drawing per case. Measured on the groove corpus: 4.77 s to re-prove one direction across
|
|
8
|
+
eight fixtures, of which 98% is `build_drawing`.
|
|
9
|
+
|
|
10
|
+
Scoring two fixtures proves the same direction. What it must NOT do is prove it vacuously,
|
|
11
|
+
so the subset is chosen rather than truncated, and chosen by TAG rather than by position:
|
|
12
|
+
|
|
13
|
+
* **one negative case**, always. Without a fixture the family must NOT match,
|
|
14
|
+
`false_positives == 0` is satisfied by a corpus that cannot produce a false positive at
|
|
15
|
+
all, and `detection.recall == 1.0` is trivially true of nothing.
|
|
16
|
+
|
|
17
|
+
Which negative matters. Taking the first in file order picked `chamfer-plain-negative`
|
|
18
|
+
and `fillet-plain-negative` — plain blocks carrying no bevel geometry whatsoever — so a
|
|
19
|
+
recogniser mutated to accept any `overlapping-family` shape would still have scored
|
|
20
|
+
`false_positives == 0`. That is exactly the vacuity the negative is here to prevent, so
|
|
21
|
+
an `ambiguous` or `overlapping-family` negative is preferred: one that the family could
|
|
22
|
+
plausibly claim and must not. `_NO_CONFUSABLE_NEGATIVE` records the two corpora that
|
|
23
|
+
offer none, rather than letting the weaker choice pass unremarked.
|
|
24
|
+
|
|
25
|
+
* **the positive expecting the most facts** (`BenchmarkCase.expected`), so the damaged
|
|
26
|
+
parameters are actually present to be scored. Ties are the norm — five positives tie in
|
|
27
|
+
pockets, six in polygonal-stock — so the tie is broken on `case_id`. Without that, the
|
|
28
|
+
exact ratios these tests assert would be pinned to JSON key order, and reformatting a
|
|
29
|
+
corpus file (touching no code) could silently re-point a test at different geometry.
|
|
30
|
+
|
|
31
|
+
`assert_reduced_corpus_is_sound` is the precondition that keeps this honest: the same
|
|
32
|
+
subset must score a clean 1.0. A subset that is already failing would let a damage
|
|
33
|
+
assertion pass for the wrong reason. `reduced_baseline_fixture` builds the per-module
|
|
34
|
+
fixture, so a new family adds a call rather than a tenth copy of the same body — the
|
|
35
|
+
growth pattern `test_clone_budget.py` exists to stop.
|
|
36
|
+
|
|
37
|
+
The full corpus is still scored in full by each module's `test_real_*_corpus_scores_*`,
|
|
38
|
+
which is where the absolute per-family counts live.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
from __future__ import annotations
|
|
42
|
+
|
|
43
|
+
from dataclasses import replace
|
|
44
|
+
|
|
45
|
+
import pytest
|
|
46
|
+
|
|
47
|
+
#: Corpora offering no `ambiguous` / `overlapping-family` negative, so the plain-block
|
|
48
|
+
#: negative is the only one available. Their `false_positives == 0` assertions are
|
|
49
|
+
#: correspondingly weaker, and adding a confusable negative fixture would strengthen them.
|
|
50
|
+
_NO_CONFUSABLE_NEGATIVE = frozenset({"corpus-chamfers-v1.json", "corpus-turned-steps-v1.json"})
|
|
51
|
+
|
|
52
|
+
#: Tags marking a negative the family could plausibly claim, and must not.
|
|
53
|
+
_CONFUSABLE = ("ambiguous", "overlapping-family")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def reduced_corpus(corpus):
|
|
57
|
+
"""One confusable negative plus the fact-richest positive, chosen deterministically."""
|
|
58
|
+
negatives = [case for case in corpus.cases if "negative" in _tags(case)]
|
|
59
|
+
positives = [
|
|
60
|
+
case
|
|
61
|
+
for case in corpus.cases
|
|
62
|
+
if "positive" in _tags(case) and "negative" not in _tags(case)
|
|
63
|
+
]
|
|
64
|
+
assert negatives, (
|
|
65
|
+
"no negative case: a corpus that cannot produce a false positive makes "
|
|
66
|
+
"`false_positives == 0` vacuous, so it cannot be reduced this way"
|
|
67
|
+
)
|
|
68
|
+
assert positives, "no positive case: `detection.recall` would be vacuous"
|
|
69
|
+
|
|
70
|
+
confusable = sorted(
|
|
71
|
+
(case for case in negatives if any(tag in _tags(case) for tag in _CONFUSABLE)),
|
|
72
|
+
key=lambda case: case.case_id,
|
|
73
|
+
)
|
|
74
|
+
negative = confusable[0] if confusable else sorted(negatives, key=lambda c: c.case_id)[0]
|
|
75
|
+
|
|
76
|
+
# `case_id` breaks the tie: `len(expected)` alone leaves the choice to JSON key order.
|
|
77
|
+
richest = max(positives, key=lambda case: (len(case.expected), case.case_id))
|
|
78
|
+
assert richest.expected, (
|
|
79
|
+
f"richest positive {richest.case_id!r} expects no facts, so parameter fidelity "
|
|
80
|
+
"would be scored over an empty denominator"
|
|
81
|
+
)
|
|
82
|
+
return replace(corpus, cases=(negative, richest))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _tags(case) -> tuple[str, ...]:
|
|
86
|
+
"""The case's tags, which `load_corpus` joins into `classification`."""
|
|
87
|
+
return tuple(case.classification.split("+"))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def assert_reduced_corpus_is_sound(evaluate, corpus) -> object:
|
|
91
|
+
"""Score the subset CLEAN and require a perfect result; return it for denominators.
|
|
92
|
+
|
|
93
|
+
Every damage assertion in the module is relative to this. If the subset were already
|
|
94
|
+
imperfect, `score == 0.5` after damage could hold because the fixture was broken
|
|
95
|
+
rather than because the damage was detected.
|
|
96
|
+
"""
|
|
97
|
+
clean = evaluate(reduced_corpus(corpus))
|
|
98
|
+
assert clean.detection.recall == 1.0, (
|
|
99
|
+
f"reduced corpus does not detect cleanly (recall {clean.detection.recall}); "
|
|
100
|
+
"damage assertions built on it would pass for the wrong reason"
|
|
101
|
+
)
|
|
102
|
+
assert clean.detection.false_positives == 0, (
|
|
103
|
+
f"reduced corpus false-positives cleanly ({clean.detection.false_positives})"
|
|
104
|
+
)
|
|
105
|
+
assert clean.parameter_fidelity.score == 1.0, (
|
|
106
|
+
f"reduced corpus scores {clean.parameter_fidelity.score} clean, not 1.0"
|
|
107
|
+
)
|
|
108
|
+
assert clean.parameter_fidelity.total > 0, "reduced corpus scores no parameters at all"
|
|
109
|
+
return clean
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def reduced_baseline_fixture(corpus_path):
|
|
113
|
+
"""The per-module `reduced_baseline` fixture, as a call rather than a tenth copy.
|
|
114
|
+
|
|
115
|
+
Module scope, so the clean evaluation is paid once per module — note that under
|
|
116
|
+
`--dist worksteal` (which `scripts/pr-check --full` uses) xdist may distribute one
|
|
117
|
+
module across workers and set it up once per worker. CI runs `loadscope` and pays it
|
|
118
|
+
once.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
@pytest.fixture(scope="module")
|
|
122
|
+
def reduced_baseline():
|
|
123
|
+
from draftwright.evaluation.step_analysis import evaluate_step_corpus, load_corpus
|
|
124
|
+
|
|
125
|
+
return assert_reduced_corpus_is_sound(evaluate_step_corpus, load_corpus(corpus_path))
|
|
126
|
+
|
|
127
|
+
return reduced_baseline
|
|
@@ -171,6 +171,7 @@ _UNIT_MODULES = frozenset(
|
|
|
171
171
|
"test_api_docs.py",
|
|
172
172
|
"test_architecture_docs.py",
|
|
173
173
|
"test_carve_free_position_callers.py",
|
|
174
|
+
"test_clone_budget.py",
|
|
174
175
|
"test_counting_calls.py",
|
|
175
176
|
"test_deprecation_dates.py",
|
|
176
177
|
"test_import_boundaries.py",
|
|
@@ -187,6 +188,7 @@ _UNIT_MODULES = frozenset(
|
|
|
187
188
|
"test_recogniser_adoption.py",
|
|
188
189
|
"test_registry.py",
|
|
189
190
|
"test_workflows.py",
|
|
191
|
+
"test_version_bump_ci.py",
|
|
190
192
|
}
|
|
191
193
|
)
|
|
192
194
|
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""The suite may not grow by copying a test body into another module.
|
|
2
|
+
|
|
3
|
+
Between 2026-08-21 and 2026-09-07 the corpus went from 3,347 to 4,934 test
|
|
4
|
+
functions and pull-request CI wall-clock went from ~31 to ~63 minutes. Sharding
|
|
5
|
+
absorbed that once; it cannot absorb it again, because sharding is a one-time
|
|
6
|
+
constant factor and cloning is not.
|
|
7
|
+
|
|
8
|
+
The growth is not people writing new assertions. It is one templated module
|
|
9
|
+
being copied per feature family: `test_missing_per_hole_boundary_outcomes_fail_closed`,
|
|
10
|
+
`..._per_pad_...`, `..._per_plate_...` — twelve hand-written copies of one three-line
|
|
11
|
+
body whose only difference is which `_<family>_model_outcomes` symbol it patches.
|
|
12
|
+
Each copy costs a real `build_drawing`, forever, on every CI run.
|
|
13
|
+
|
|
14
|
+
The two obvious ways to detect that both fail here, which is why it went unnoticed:
|
|
15
|
+
identical test NAMES miss it (every clone is renamed for its family) and identical
|
|
16
|
+
ASTs miss it (every clone substitutes its family's identifiers and literals). So this
|
|
17
|
+
guard compares test bodies with identifiers, attributes, literals and argument names
|
|
18
|
+
erased — the SHAPE — across modules, since same-module repetition is a much weaker smell
|
|
19
|
+
and often a deliberate readability choice, and only where a shape recurs in at least
|
|
20
|
+
`_MIN_GROUP_MEMBERS` places, since a bare pair is usually coincidence rather than a
|
|
21
|
+
template.
|
|
22
|
+
|
|
23
|
+
The fix when this fails is not to raise the budget. It is to parametrize over the
|
|
24
|
+
one thing that varies, which keeps every assertion and deletes the copies. Lower the
|
|
25
|
+
budget whenever you do. Raising it needs a reason in the pull request body, the same
|
|
26
|
+
way `fail_under` in `[tool.coverage.report]` does.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import ast
|
|
32
|
+
import collections
|
|
33
|
+
import hashlib
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
|
|
36
|
+
TESTS = Path(__file__).parent
|
|
37
|
+
|
|
38
|
+
#: Cross-module structurally identical test bodies, counted as `group size - 1`, over
|
|
39
|
+
#: groups of at least `_MIN_GROUP_MEMBERS`. Measured at 33 on 2026-09-07.
|
|
40
|
+
#: RATCHET DOWN ONLY — see the module docstring.
|
|
41
|
+
CLONE_BUDGET = 33
|
|
42
|
+
|
|
43
|
+
#: A shape must recur in at least this many modules to count as templated cloning.
|
|
44
|
+
#:
|
|
45
|
+
#: At two, the guard was measuring coincidence. 61 of its 70 groups were pairs, and the
|
|
46
|
+
#: pairs are ordinary tests that happen to share a shape once identifiers and literals are
|
|
47
|
+
#: erased — `test_add_dimension.py::test_a_tuple_swap_invalidates_rather_than_retargets`
|
|
48
|
+
#: against `test_sheet_identity_invariant.py::test_a_tuple_swap_raises`. With the budget
|
|
49
|
+
#: sitting exactly on the measured count, the next PR adding any three-statement test that
|
|
50
|
+
#: collided by accident would have failed CI telling its author to "parametrize and delete
|
|
51
|
+
#: the copies", which would usually be wrong — and a gate that cries wolf gets raised
|
|
52
|
+
#: rather than obeyed. Templated cloning shows up as a family, not a pair.
|
|
53
|
+
_MIN_GROUP_MEMBERS = 3
|
|
54
|
+
|
|
55
|
+
#: A body must have at least this many statements, and this many AST nodes, before it
|
|
56
|
+
#: counts. Short bodies (`build; assert`) collide by chance and would make the guard
|
|
57
|
+
#: noise rather than signal.
|
|
58
|
+
#:
|
|
59
|
+
#: The size gate counts NODES rather than the length of `ast.dump`. CI runs Python
|
|
60
|
+
#: 3.10 through 3.14, and `ast.dump` text gains and loses optional fields between
|
|
61
|
+
#: versions; 22 bodies sit within 15% of the equivalent character threshold, so any of
|
|
62
|
+
#: them could be counted on one interpreter and skipped on another and fail the gate on
|
|
63
|
+
#: one matrix leg only. A node count moves only when the grammar does.
|
|
64
|
+
_MIN_STATEMENTS = 3
|
|
65
|
+
_MIN_NODES = 16
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class _Shape(ast.NodeTransformer):
|
|
69
|
+
"""Erase everything nameable, keep control flow and call structure."""
|
|
70
|
+
|
|
71
|
+
def visit_Name(self, node: ast.Name) -> ast.Name:
|
|
72
|
+
return ast.copy_location(ast.Name(id="_", ctx=node.ctx), node)
|
|
73
|
+
|
|
74
|
+
def visit_Attribute(self, node: ast.Attribute) -> ast.Attribute:
|
|
75
|
+
self.generic_visit(node)
|
|
76
|
+
return ast.copy_location(ast.Attribute(value=node.value, attr="_", ctx=node.ctx), node)
|
|
77
|
+
|
|
78
|
+
def visit_Constant(self, node: ast.Constant) -> ast.Constant:
|
|
79
|
+
return ast.copy_location(ast.Constant(value="_"), node)
|
|
80
|
+
|
|
81
|
+
def visit_arg(self, node: ast.arg) -> ast.arg:
|
|
82
|
+
return ast.copy_location(ast.arg(arg="_"), node)
|
|
83
|
+
|
|
84
|
+
def visit_keyword(self, node: ast.keyword) -> ast.keyword:
|
|
85
|
+
self.generic_visit(node)
|
|
86
|
+
return ast.copy_location(ast.keyword(arg="_", value=node.value), node)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _clone_groups() -> dict[str, list[tuple[str, str]]]:
|
|
90
|
+
"""Structurally identical test bodies that span more than one module."""
|
|
91
|
+
shapes: dict[str, list[tuple[str, str]]] = collections.defaultdict(list)
|
|
92
|
+
for path in sorted(TESTS.glob("test_*.py")):
|
|
93
|
+
tree = ast.parse(path.read_text(encoding="utf-8"))
|
|
94
|
+
for node in ast.walk(tree):
|
|
95
|
+
if not (isinstance(node, ast.FunctionDef) and node.name.startswith("test_")):
|
|
96
|
+
continue
|
|
97
|
+
body = [
|
|
98
|
+
statement
|
|
99
|
+
for statement in node.body
|
|
100
|
+
# Drop the docstring: prose is where a clone legitimately differs.
|
|
101
|
+
if not (
|
|
102
|
+
isinstance(statement, ast.Expr) and isinstance(statement.value, ast.Constant)
|
|
103
|
+
)
|
|
104
|
+
]
|
|
105
|
+
if len(body) < _MIN_STATEMENTS:
|
|
106
|
+
continue
|
|
107
|
+
normalised = _Shape().visit(ast.Module(body=body, type_ignores=[]))
|
|
108
|
+
if sum(1 for _ in ast.walk(normalised)) < _MIN_NODES:
|
|
109
|
+
continue
|
|
110
|
+
digest = hashlib.md5(ast.dump(normalised).encode(), usedforsecurity=False).hexdigest()
|
|
111
|
+
shapes[digest].append((path.name, node.name))
|
|
112
|
+
return {
|
|
113
|
+
digest: members
|
|
114
|
+
for digest, members in shapes.items()
|
|
115
|
+
if len({module for module, _ in members}) > 1 and len(members) >= _MIN_GROUP_MEMBERS
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_the_suite_does_not_grow_by_cloning_test_bodies_across_modules() -> None:
|
|
120
|
+
groups = _clone_groups()
|
|
121
|
+
redundant = sum(len(members) - 1 for members in groups.values())
|
|
122
|
+
|
|
123
|
+
worst = sorted(groups.values(), key=len, reverse=True)[:5]
|
|
124
|
+
report = "\n".join(
|
|
125
|
+
f" x{len(members)} {members[0][1]}\n"
|
|
126
|
+
+ "\n".join(f" {module}" for module, _ in members[:4])
|
|
127
|
+
+ ("\n ..." if len(members) > 4 else "")
|
|
128
|
+
for members in worst
|
|
129
|
+
)
|
|
130
|
+
assert redundant <= CLONE_BUDGET, (
|
|
131
|
+
f"{redundant} cross-module clones, budget {CLONE_BUDGET}. The largest groups:\n"
|
|
132
|
+
f"{report}\n\n"
|
|
133
|
+
"A test body copied into another module with only its family's identifiers "
|
|
134
|
+
"changed is not new evidence — it is the same assertion paid for again on every "
|
|
135
|
+
"CI run. Parametrize over the symbol that varies and delete the copies, then "
|
|
136
|
+
"lower CLONE_BUDGET. Raising it needs a reason in the PR body."
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_the_budget_is_not_slack() -> None:
|
|
141
|
+
"""A budget far above the real count silently permits the next wave of copies."""
|
|
142
|
+
redundant = sum(len(members) - 1 for members in _clone_groups().values())
|
|
143
|
+
|
|
144
|
+
assert redundant >= CLONE_BUDGET - 10, (
|
|
145
|
+
f"only {redundant} cross-module clones against a budget of {CLONE_BUDGET}: "
|
|
146
|
+
"consolidation happened without ratcheting the budget down, so the guard now "
|
|
147
|
+
f"permits {CLONE_BUDGET - redundant} new copies before it complains. "
|
|
148
|
+
f"Set CLONE_BUDGET = {redundant}."
|
|
149
|
+
)
|
|
@@ -26,7 +26,7 @@ def _manifest() -> dict:
|
|
|
26
26
|
def test_installed_pypi_wheel_satisfies_the_inspection_contract() -> None:
|
|
27
27
|
distribution = importlib.metadata.distribution("quiddity")
|
|
28
28
|
|
|
29
|
-
assert distribution.version == "0.2.
|
|
29
|
+
assert distribution.version == "0.2.5"
|
|
30
30
|
assert distribution.read_text("direct_url.json") is None
|
|
31
31
|
assert (
|
|
32
32
|
Path(inspect.getfile(inspection.inspection_api_manifest))
|
{draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1369_hole_completeness_evidence.py
RENAMED
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
from dataclasses import replace
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
+
from _evidence_contract import assert_missing_model_outcomes_fail_closed
|
|
12
13
|
from build123d import Box, Cylinder, Pos
|
|
13
14
|
|
|
14
15
|
from draftwright.evaluation.step_analysis import (
|
|
@@ -31,8 +32,14 @@ def _states(boundary: str) -> set[str]:
|
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
def test_every_hole_boundary_is_observed_supported_on_the_real_public_path() -> None:
|
|
35
|
+
# One observation for all four boundaries. `_states` re-runs the observer —
|
|
36
|
+
# a full `build_drawing` — on every call, so the loop paid for four identical
|
|
37
|
+
# builds of the same part to read four keys off the same facts.
|
|
38
|
+
observed = _default_observers()["holes"](_part())
|
|
39
|
+
assert observed, "fixture produced no hole observations"
|
|
34
40
|
for boundary in ("ir_adapter", "dsl_declaration", "generated_code", "drawing_consumer"):
|
|
35
|
-
|
|
41
|
+
states = {fact.downstream[boundary] for fact in observed}
|
|
42
|
+
assert states == {"supported"}
|
|
36
43
|
|
|
37
44
|
|
|
38
45
|
def test_removing_holes_from_the_built_ir_loses_ir_adapter_credit(monkeypatch) -> None:
|
|
@@ -86,10 +93,7 @@ def test_deleting_generated_hole_lines_loses_generated_code_credit(monkeypatch)
|
|
|
86
93
|
|
|
87
94
|
|
|
88
95
|
def test_a_boundary_with_missing_per_hole_outcomes_fails_closed(monkeypatch) -> None:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
monkeypatch.setattr(step_analysis, "_hole_model_outcomes", lambda *_args: [])
|
|
92
|
-
assert _states("ir_adapter") == {"unknown"}
|
|
96
|
+
assert_missing_model_outcomes_fail_closed(monkeypatch, "_hole_model_outcomes", _states)
|
|
93
97
|
|
|
94
98
|
|
|
95
99
|
def test_a_post_build_model_access_failure_is_scored_not_raised(monkeypatch) -> None:
|
{draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1370_countersink_completeness_evidence.py
RENAMED
|
@@ -7,6 +7,8 @@ from pathlib import Path
|
|
|
7
7
|
from types import SimpleNamespace
|
|
8
8
|
|
|
9
9
|
import pytest
|
|
10
|
+
from _evidence_contract import assert_missing_model_outcomes_fail_closed
|
|
11
|
+
from _mutation_corpus import reduced_baseline_fixture, reduced_corpus
|
|
10
12
|
from build123d import Box, Compound, Cone, Cylinder, Pos, import_step
|
|
11
13
|
|
|
12
14
|
from draftwright.evaluation.step_analysis import (
|
|
@@ -19,6 +21,9 @@ from draftwright.evaluation.step_analysis import (
|
|
|
19
21
|
|
|
20
22
|
CORPUS = Path(__file__).parent / "fixtures" / "evaluation" / "corpus-countersinks-v1.json"
|
|
21
23
|
|
|
24
|
+
#: Clean score of the subset the damage tests below use, asserted perfect.
|
|
25
|
+
reduced_baseline = reduced_baseline_fixture(CORPUS)
|
|
26
|
+
|
|
22
27
|
|
|
23
28
|
def _single_part():
|
|
24
29
|
return import_step(CORPUS.parent / "countersink-single.step")
|
|
@@ -71,18 +76,18 @@ def test_versioned_countersink_corpus_covers_every_required_case_class() -> None
|
|
|
71
76
|
def test_real_countersink_corpus_scores_all_layers_and_topology_variants() -> None:
|
|
72
77
|
corpus = load_corpus(CORPUS)
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
assert
|
|
78
|
-
assert
|
|
79
|
-
assert
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
assert
|
|
84
|
-
assert
|
|
85
|
-
variants = [case for case in
|
|
79
|
+
evaluation = evaluate_step_corpus(corpus)
|
|
80
|
+
assert evaluation.detection.recall == 1.0
|
|
81
|
+
assert evaluation.detection.false_positive_rate == 0.0
|
|
82
|
+
assert (evaluation.parameter_fidelity.passed, evaluation.parameter_fidelity.total) == (28, 28)
|
|
83
|
+
assert evaluation.parameter_fidelity.score == 1.0
|
|
84
|
+
assert (evaluation.downstream_usefulness.passed, evaluation.downstream_usefulness.total) == (
|
|
85
|
+
28,
|
|
86
|
+
28,
|
|
87
|
+
)
|
|
88
|
+
assert evaluation.downstream_usefulness.score == 1.0
|
|
89
|
+
assert evaluation.conformant_cases == evaluation.complete_cases == len(corpus.cases)
|
|
90
|
+
variants = [case for case in evaluation.cases if "topology" in case.case_id]
|
|
86
91
|
assert len(variants) == 2
|
|
87
92
|
assert variants[0].detection == variants[1].detection
|
|
88
93
|
assert variants[0].parameter_fidelity == variants[1].parameter_fidelity
|
|
@@ -214,8 +219,14 @@ def test_equal_seats_still_remain_two_physical_observations() -> None:
|
|
|
214
219
|
|
|
215
220
|
|
|
216
221
|
def test_every_countersink_boundary_is_observed_supported_on_the_real_public_path() -> None:
|
|
222
|
+
# One observation for all four boundaries. `_states` re-runs the observer —
|
|
223
|
+
# a full `build_drawing` — on every call, so the loop paid for four identical
|
|
224
|
+
# builds of the same part to read four keys off the same facts.
|
|
225
|
+
observed = _default_observers()["countersinks"](_single_part())
|
|
226
|
+
assert len(observed) == 1, "fixture must produce one countersink observation"
|
|
217
227
|
for boundary in ("ir_adapter", "dsl_declaration", "generated_code", "drawing_consumer"):
|
|
218
|
-
|
|
228
|
+
states = {fact.downstream[boundary] for fact in observed}
|
|
229
|
+
assert states == {"supported"}
|
|
219
230
|
|
|
220
231
|
|
|
221
232
|
def test_removing_the_seat_from_built_ir_loses_ir_adapter_credit(monkeypatch) -> None:
|
|
@@ -276,10 +287,7 @@ def test_deleting_generated_countersink_argument_loses_generated_code_credit(
|
|
|
276
287
|
|
|
277
288
|
|
|
278
289
|
def test_a_boundary_with_missing_per_seat_outcomes_fails_closed(monkeypatch) -> None:
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
monkeypatch.setattr(step_analysis, "_countersink_model_outcomes", lambda *_args: [])
|
|
282
|
-
assert _states("ir_adapter") == {"unknown"}
|
|
290
|
+
assert_missing_model_outcomes_fail_closed(monkeypatch, "_countersink_model_outcomes", _states)
|
|
283
291
|
|
|
284
292
|
|
|
285
293
|
def test_removing_placed_countersink_ink_loses_drawing_credit(monkeypatch) -> None:
|
|
@@ -468,7 +476,7 @@ def test_countersink_observer_fails_closed_when_build_or_recognition_is_unavaila
|
|
|
468
476
|
|
|
469
477
|
@pytest.mark.parametrize("corruption", ["nonnumeric-location", "missing-axis"])
|
|
470
478
|
def test_malformed_public_countersink_records_become_missed_instead_of_aborting(
|
|
471
|
-
monkeypatch, corruption: str
|
|
479
|
+
monkeypatch, corruption: str, reduced_baseline
|
|
472
480
|
) -> None:
|
|
473
481
|
from draftwright.drawing import Drawing
|
|
474
482
|
|
|
@@ -496,9 +504,11 @@ def test_malformed_public_countersink_records_become_missed_instead_of_aborting(
|
|
|
496
504
|
monkeypatch.setattr(Drawing, "recognition", with_malformed_record)
|
|
497
505
|
|
|
498
506
|
assert _default_observers()["countersinks"](_single_part()) == ()
|
|
499
|
-
damaged = evaluate_step_corpus(load_corpus(CORPUS))
|
|
507
|
+
damaged = evaluate_step_corpus(reduced_corpus(load_corpus(CORPUS)))
|
|
500
508
|
assert damaged.detection.matched == 0
|
|
501
|
-
|
|
509
|
+
# Every seat that matched cleanly is now missed, stated against the clean subset
|
|
510
|
+
# rather than the full corpus's count of 7.
|
|
511
|
+
assert damaged.detection.missed == reduced_baseline.detection.matched
|
|
502
512
|
assert damaged.detection.false_positives == 0
|
|
503
513
|
|
|
504
514
|
|
{draftwright-0.4.21 → draftwright-0.4.22}/tests/test_issue_1370_double_d_completeness_evidence.py
RENAMED
|
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
from types import SimpleNamespace
|
|
8
8
|
|
|
9
9
|
import pytest
|
|
10
|
+
from _evidence_contract import assert_missing_model_outcomes_fail_closed
|
|
10
11
|
from build123d import Align, Box, Compound, Cylinder, Pos, import_step
|
|
11
12
|
|
|
12
13
|
from draftwright.evaluation.step_analysis import (
|
|
@@ -67,18 +68,18 @@ def test_versioned_double_d_corpus_covers_each_required_case_class() -> None:
|
|
|
67
68
|
def test_real_double_d_corpus_scores_all_layers_and_topology_variants() -> None:
|
|
68
69
|
corpus = load_corpus(CORPUS)
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
assert
|
|
74
|
-
assert
|
|
75
|
-
assert
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
assert
|
|
80
|
-
assert
|
|
81
|
-
variants = [case for case in
|
|
71
|
+
evaluation = evaluate_step_corpus(corpus)
|
|
72
|
+
assert evaluation.detection.recall == 1.0
|
|
73
|
+
assert evaluation.detection.false_positive_rate == 0.0
|
|
74
|
+
assert (evaluation.parameter_fidelity.passed, evaluation.parameter_fidelity.total) == (50, 50)
|
|
75
|
+
assert evaluation.parameter_fidelity.score == 1.0
|
|
76
|
+
assert (evaluation.downstream_usefulness.passed, evaluation.downstream_usefulness.total) == (
|
|
77
|
+
40,
|
|
78
|
+
40,
|
|
79
|
+
)
|
|
80
|
+
assert evaluation.downstream_usefulness.score == 1.0
|
|
81
|
+
assert evaluation.conformant_cases == evaluation.complete_cases == len(corpus.cases)
|
|
82
|
+
variants = [case for case in evaluation.cases if "topology" in case.case_id]
|
|
82
83
|
assert len(variants) == 2
|
|
83
84
|
assert variants[0].detection == variants[1].detection
|
|
84
85
|
assert variants[0].parameter_fidelity == variants[1].parameter_fidelity
|
|
@@ -187,8 +188,14 @@ def test_public_depth_quantization_allowance_is_independently_bracketed() -> Non
|
|
|
187
188
|
|
|
188
189
|
|
|
189
190
|
def test_every_double_d_boundary_is_supported_on_the_real_public_path() -> None:
|
|
191
|
+
# One observation for all four boundaries. `_states` re-runs the observer —
|
|
192
|
+
# a full `build_drawing` — on every call, so the loop paid for four identical
|
|
193
|
+
# builds of the same part to read four keys off the same facts.
|
|
194
|
+
observed = _default_observers()["double-d-bores"](_part())
|
|
195
|
+
assert len(observed) == 1, "fixture must produce one Double-D observation"
|
|
190
196
|
for boundary in ("ir_adapter", "dsl_declaration", "generated_code", "drawing_consumer"):
|
|
191
|
-
|
|
197
|
+
states = {fact.downstream[boundary] for fact in observed}
|
|
198
|
+
assert states == {"supported"}
|
|
192
199
|
|
|
193
200
|
|
|
194
201
|
@pytest.mark.parametrize(
|
|
@@ -629,10 +636,7 @@ def test_double_d_observer_fails_closed_when_build_or_recognition_is_unavailable
|
|
|
629
636
|
|
|
630
637
|
|
|
631
638
|
def test_a_boundary_with_missing_per_bore_outcomes_fails_closed(monkeypatch) -> None:
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
monkeypatch.setattr(step_analysis, "_double_d_model_outcomes", lambda *_args: [])
|
|
635
|
-
assert _states("ir_adapter") == {"unknown"}
|
|
639
|
+
assert_missing_model_outcomes_fail_closed(monkeypatch, "_double_d_model_outcomes", _states)
|
|
636
640
|
|
|
637
641
|
|
|
638
642
|
@pytest.mark.parametrize(
|