draftwright 0.5.0rc2__tar.gz → 0.5.0rc4__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.5.0rc4/CHANGELOG.md +3217 -0
- draftwright-0.5.0rc4/PKG-INFO +1074 -0
- draftwright-0.5.0rc4/README.md +371 -0
- draftwright-0.5.0rc4/docs/reference/recogniser-capabilities.md +820 -0
- draftwright-0.5.0rc4/pyproject.toml +205 -0
- draftwright-0.5.0rc4/skills/SKILL.md +378 -0
- draftwright-0.5.0rc4/src/draftwright/_build_profile.py +186 -0
- draftwright-0.5.0rc4/src/draftwright/_core.py +1539 -0
- draftwright-0.5.0rc4/src/draftwright/_geometry.py +1298 -0
- draftwright-0.5.0rc4/src/draftwright/_pmi_part21.py +1848 -0
- draftwright-0.5.0rc4/src/draftwright/_pmi_support_blockers.py +241 -0
- draftwright-0.5.0rc4/src/draftwright/_pmi_topology.py +222 -0
- draftwright-0.5.0rc4/src/draftwright/analysis.py +2494 -0
- draftwright-0.5.0rc4/src/draftwright/annotate.py +25 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_axial_render.py +1115 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_common.py +2496 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_diameters.py +981 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_dimension_ink_repair.py +506 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_edge_callouts.py +573 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_envelope.py +331 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_gdt.py +787 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_leader_commit.py +503 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_leader_fixed_ink.py +511 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_locations.py +829 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_machined_leaders.py +436 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_patterns.py +586 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_placement_occupancy.py +715 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_pmi_dimensions.py +1771 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_sheet_furniture.py +560 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_slots.py +717 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_step_lengths.py +934 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/_thin_profiles.py +299 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/angular.py +142 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/balloons.py +1164 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/drawing_port.py +128 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/from_model.py +2493 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/hole_locations.py +700 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/holes.py +2478 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/leaders.py +2474 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/orchestrator.py +1940 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/routed.py +142 -0
- draftwright-0.5.0rc4/src/draftwright/annotations/sections.py +1572 -0
- draftwright-0.5.0rc4/src/draftwright/audit.py +1430 -0
- draftwright-0.5.0rc4/src/draftwright/build_once.py +624 -0
- draftwright-0.5.0rc4/src/draftwright/build_options.py +159 -0
- draftwright-0.5.0rc4/src/draftwright/builder.py +2901 -0
- draftwright-0.5.0rc4/src/draftwright/cli.py +500 -0
- draftwright-0.5.0rc4/src/draftwright/compose.py +2878 -0
- draftwright-0.5.0rc4/src/draftwright/drawing.py +2591 -0
- draftwright-0.5.0rc4/src/draftwright/drawing_diagnostics.py +549 -0
- draftwright-0.5.0rc4/src/draftwright/drawing_evidence.py +425 -0
- draftwright-0.5.0rc4/src/draftwright/drawing_export.py +244 -0
- draftwright-0.5.0rc4/src/draftwright/drawing_state.py +163 -0
- draftwright-0.5.0rc4/src/draftwright/evaluation/_edge_profile_evidence.py +483 -0
- draftwright-0.5.0rc4/src/draftwright/evaluation/_hole_family_evidence.py +577 -0
- draftwright-0.5.0rc4/src/draftwright/evaluation/_pocket_evidence.py +628 -0
- draftwright-0.5.0rc4/src/draftwright/evaluation/_turned_step_evidence.py +364 -0
- draftwright-0.5.0rc4/src/draftwright/evaluation/step_analysis.py +2454 -0
- draftwright-0.5.0rc4/src/draftwright/export.py +839 -0
- draftwright-0.5.0rc4/src/draftwright/family_table.py +359 -0
- draftwright-0.5.0rc4/src/draftwright/inspection.py +800 -0
- draftwright-0.5.0rc4/src/draftwright/inspection_contract.py +279 -0
- draftwright-0.5.0rc4/src/draftwright/intent_routing.py +283 -0
- draftwright-0.5.0rc4/src/draftwright/layout.py +1400 -0
- draftwright-0.5.0rc4/src/draftwright/layout_selection.py +637 -0
- draftwright-0.5.0rc4/src/draftwright/linting/__init__.py +137 -0
- draftwright-0.5.0rc4/src/draftwright/linting/_coverage_common.py +198 -0
- draftwright-0.5.0rc4/src/draftwright/linting/_parameter_coverage.py +181 -0
- draftwright-0.5.0rc4/src/draftwright/linting/angular.py +618 -0
- draftwright-0.5.0rc4/src/draftwright/linting/blend_coverage.py +318 -0
- draftwright-0.5.0rc4/src/draftwright/linting/boss_coverage.py +247 -0
- draftwright-0.5.0rc4/src/draftwright/linting/chamfer_coverage.py +99 -0
- draftwright-0.5.0rc4/src/draftwright/linting/circular_blind_step_coverage.py +225 -0
- draftwright-0.5.0rc4/src/draftwright/linting/coverage.py +2592 -0
- draftwright-0.5.0rc4/src/draftwright/linting/envelope_coverage.py +211 -0
- draftwright-0.5.0rc4/src/draftwright/linting/fillet_coverage.py +96 -0
- draftwright-0.5.0rc4/src/draftwright/linting/gear_coverage.py +187 -0
- draftwright-0.5.0rc4/src/draftwright/linting/hole_coverage.py +1588 -0
- draftwright-0.5.0rc4/src/draftwright/linting/orchestration.py +693 -0
- draftwright-0.5.0rc4/src/draftwright/linting/paired_ramp_step_coverage.py +105 -0
- draftwright-0.5.0rc4/src/draftwright/linting/pmi_coverage.py +789 -0
- draftwright-0.5.0rc4/src/draftwright/linting/polygonal_boss_coverage.py +368 -0
- draftwright-0.5.0rc4/src/draftwright/linting/polygonal_stock_coverage.py +424 -0
- draftwright-0.5.0rc4/src/draftwright/linting/quality.py +1017 -0
- draftwright-0.5.0rc4/src/draftwright/linting/rectangular_blind_slot_coverage.py +190 -0
- draftwright-0.5.0rc4/src/draftwright/linting/requirements.py +222 -0
- draftwright-0.5.0rc4/src/draftwright/linting/round_bottom_blind_slot_coverage.py +196 -0
- draftwright-0.5.0rc4/src/draftwright/linting/structural.py +1697 -0
- draftwright-0.5.0rc4/src/draftwright/linting/through_step_coverage.py +673 -0
- draftwright-0.5.0rc4/src/draftwright/make_drawing.py +30 -0
- draftwright-0.5.0rc4/src/draftwright/measurement_support.py +144 -0
- draftwright-0.5.0rc4/src/draftwright/model/callout.py +810 -0
- draftwright-0.5.0rc4/src/draftwright/model/compiled.py +2485 -0
- draftwright-0.5.0rc4/src/draftwright/model/declare.py +2796 -0
- draftwright-0.5.0rc4/src/draftwright/model/detect.py +2881 -0
- draftwright-0.5.0rc4/src/draftwright/model/detect_inventory.py +281 -0
- draftwright-0.5.0rc4/src/draftwright/model/detect_ownership.py +545 -0
- draftwright-0.5.0rc4/src/draftwright/model/ir.py +2944 -0
- draftwright-0.5.0rc4/src/draftwright/model/ir_foundation.py +1115 -0
- draftwright-0.5.0rc4/src/draftwright/model/planner.py +2177 -0
- draftwright-0.5.0rc4/src/draftwright/model/pmi_lowering.py +1750 -0
- draftwright-0.5.0rc4/src/draftwright/pdf_text.py +666 -0
- draftwright-0.5.0rc4/src/draftwright/pmi.py +2917 -0
- draftwright-0.5.0rc4/src/draftwright/profile_angles.py +312 -0
- draftwright-0.5.0rc4/src/draftwright/projection.py +660 -0
- draftwright-0.5.0rc4/src/draftwright/recogniser_contract.py +1085 -0
- draftwright-0.5.0rc4/src/draftwright/recogniser_policy.py +163 -0
- draftwright-0.5.0rc4/src/draftwright/recogniser_schema.py +123 -0
- draftwright-0.5.0rc4/src/draftwright/recognition_ownership.py +1254 -0
- draftwright-0.5.0rc4/src/draftwright/repair.py +340 -0
- draftwright-0.5.0rc4/src/draftwright/reporting.py +2873 -0
- draftwright-0.5.0rc4/src/draftwright/section_recess_contract.py +1000 -0
- draftwright-0.5.0rc4/src/draftwright/sheet.py +2913 -0
- draftwright-0.5.0rc4/src/draftwright/sheet_emit.py +2126 -0
- draftwright-0.5.0rc4/src/draftwright/sheet_feature_lines.py +969 -0
- draftwright-0.5.0rc4/src/draftwright/sheet_metadata.py +47 -0
- draftwright-0.5.0rc4/src/draftwright/sheet_views.py +667 -0
- draftwright-0.5.0rc4/tests/_complexity_baseline.json +138 -0
- draftwright-0.5.0rc4/tests/_function_length_baseline.json +50 -0
- draftwright-0.5.0rc4/tests/_issue_module_baseline.txt +159 -0
- draftwright-0.5.0rc4/tests/_tier_manifest.py +975 -0
- draftwright-0.5.0rc4/tests/fixtures/evaluation/README.md +251 -0
- draftwright-0.5.0rc4/tests/fixtures/evaluation/corpus-hole-patterns-v1.json +159 -0
- draftwright-0.5.0rc4/tests/refactor_golden/grid_plate.json +527 -0
- draftwright-0.5.0rc4/tests/test_adr0018_view_selection.py +712 -0
- draftwright-0.5.0rc4/tests/test_adr_corpus.py +164 -0
- draftwright-0.5.0rc4/tests/test_agent_improvement_canary_issue_1716.py +302 -0
- draftwright-0.5.0rc4/tests/test_annotation_box_composition.py +169 -0
- draftwright-0.5.0rc4/tests/test_annotation_box_corpus.py +81 -0
- draftwright-0.5.0rc4/tests/test_annotation_layout_product.py +701 -0
- draftwright-0.5.0rc4/tests/test_annotation_scheme_compare_script.py +776 -0
- draftwright-0.5.0rc4/tests/test_architecture_docs.py +53 -0
- draftwright-0.5.0rc4/tests/test_boss_ownership.py +731 -0
- draftwright-0.5.0rc4/tests/test_build_drawing_entrypoints.py +288 -0
- draftwright-0.5.0rc4/tests/test_channel_ownership.py +391 -0
- draftwright-0.5.0rc4/tests/test_circular_blind_step_semantics.py +1095 -0
- draftwright-0.5.0rc4/tests/test_compiled_plan_boundary.py +1383 -0
- draftwright-0.5.0rc4/tests/test_compose_then_pack.py +504 -0
- draftwright-0.5.0rc4/tests/test_declare.py +2300 -0
- draftwright-0.5.0rc4/tests/test_declared_recognition_gate.py +572 -0
- draftwright-0.5.0rc4/tests/test_deprecation_dates.py +260 -0
- draftwright-0.5.0rc4/tests/test_detect_registry.py +338 -0
- draftwright-0.5.0rc4/tests/test_diameter_leaders.py +400 -0
- draftwright-0.5.0rc4/tests/test_dimension_lane_canary_issue_1757.py +165 -0
- draftwright-0.5.0rc4/tests/test_dimension_role_vocabulary.py +399 -0
- draftwright-0.5.0rc4/tests/test_document_build.py +498 -0
- draftwright-0.5.0rc4/tests/test_drawing_encapsulation.py +667 -0
- draftwright-0.5.0rc4/tests/test_e2e_standards.py +557 -0
- draftwright-0.5.0rc4/tests/test_edge_profile_coverage.py +75 -0
- draftwright-0.5.0rc4/tests/test_export_formats.py +247 -0
- draftwright-0.5.0rc4/tests/test_family_table.py +131 -0
- draftwright-0.5.0rc4/tests/test_feature_edit_verbs.py +399 -0
- draftwright-0.5.0rc4/tests/test_feature_leader_candidate_regions.py +1273 -0
- draftwright-0.5.0rc4/tests/test_gdt_ink_shared.py +304 -0
- draftwright-0.5.0rc4/tests/test_gdt_placement.py +529 -0
- draftwright-0.5.0rc4/tests/test_groove_completeness_evidence.py +656 -0
- draftwright-0.5.0rc4/tests/test_hole_annotations.py +521 -0
- draftwright-0.5.0rc4/tests/test_hole_pattern_callouts.py +458 -0
- draftwright-0.5.0rc4/tests/test_hole_table.py +772 -0
- draftwright-0.5.0rc4/tests/test_import_boundaries.py +1497 -0
- draftwright-0.5.0rc4/tests/test_inspection_contract.py +180 -0
- draftwright-0.5.0rc4/tests/test_interior_label_placement.py +348 -0
- draftwright-0.5.0rc4/tests/test_issue_1058_wheel_profile.py +911 -0
- draftwright-0.5.0rc4/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +496 -0
- draftwright-0.5.0rc4/tests/test_issue_1142_hole_leader_labels.py +262 -0
- draftwright-0.5.0rc4/tests/test_issue_1143_hole_completeness.py +2929 -0
- draftwright-0.5.0rc4/tests/test_issue_1166_cross_pass_feature_leaders.py +2787 -0
- draftwright-0.5.0rc4/tests/test_issue_1176_quality_fidelity.py +1032 -0
- draftwright-0.5.0rc4/tests/test_issue_1188_per_view_assignment.py +125 -0
- draftwright-0.5.0rc4/tests/test_issue_1190_section_decision.py +256 -0
- draftwright-0.5.0rc4/tests/test_issue_1202_observed_drawing_consumer.py +634 -0
- draftwright-0.5.0rc4/tests/test_issue_1215_envelope_tolerance.py +321 -0
- draftwright-0.5.0rc4/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +957 -0
- draftwright-0.5.0rc4/tests/test_issue_1217_the_facility_is_shared.py +429 -0
- draftwright-0.5.0rc4/tests/test_issue_1219_location_claims_its_own_axis.py +287 -0
- draftwright-0.5.0rc4/tests/test_issue_1298_manufacturing_requirements.py +1886 -0
- draftwright-0.5.0rc4/tests/test_issue_1308_machined_leader_analytics.py +427 -0
- draftwright-0.5.0rc4/tests/test_issue_1352_searchable_pdf_text.py +1103 -0
- draftwright-0.5.0rc4/tests/test_issue_1357_framed_activation.py +241 -0
- draftwright-0.5.0rc4/tests/test_issue_1370_double_d_completeness_evidence.py +731 -0
- draftwright-0.5.0rc4/tests/test_issue_1370_hole_pattern_completeness_evidence.py +308 -0
- draftwright-0.5.0rc4/tests/test_issue_1371_polygonal_stock_completeness_evidence.py +1226 -0
- draftwright-0.5.0rc4/tests/test_issue_1460_step_inspection.py +1062 -0
- draftwright-0.5.0rc4/tests/test_issue_1505_diameter_coverage.py +166 -0
- draftwright-0.5.0rc4/tests/test_issue_1518_explicit_rear.py +703 -0
- draftwright-0.5.0rc4/tests/test_issue_1531_semantic_hole_counts.py +255 -0
- draftwright-0.5.0rc4/tests/test_issue_1544_frame_document_canary.py +443 -0
- draftwright-0.5.0rc4/tests/test_issue_1596_bolt_circle_corroboration.py +441 -0
- draftwright-0.5.0rc4/tests/test_issue_740_leader_assignment.py +906 -0
- draftwright-0.5.0rc4/tests/test_issue_798_material_field.py +496 -0
- draftwright-0.5.0rc4/tests/test_issue_798_silhouette_lint.py +390 -0
- draftwright-0.5.0rc4/tests/test_issue_883_location_identity.py +644 -0
- draftwright-0.5.0rc4/tests/test_issue_916_pocket_leader.py +118 -0
- draftwright-0.5.0rc4/tests/test_label_provenance.py +190 -0
- draftwright-0.5.0rc4/tests/test_layout_override_lane_issue_1757.py +263 -0
- draftwright-0.5.0rc4/tests/test_layout_safety.py +758 -0
- draftwright-0.5.0rc4/tests/test_layout_scheme.py +583 -0
- draftwright-0.5.0rc4/tests/test_lint_summary.py +404 -0
- draftwright-0.5.0rc4/tests/test_location_dimensions.py +635 -0
- draftwright-0.5.0rc4/tests/test_manufacturing_pmi_lowering.py +745 -0
- draftwright-0.5.0rc4/tests/test_note_verb.py +61 -0
- draftwright-0.5.0rc4/tests/test_pad_rendering.py +491 -0
- draftwright-0.5.0rc4/tests/test_parameter_id.py +758 -0
- draftwright-0.5.0rc4/tests/test_pareto_loop_canary_issue_1753.py +170 -0
- draftwright-0.5.0rc4/tests/test_part_model.py +381 -0
- draftwright-0.5.0rc4/tests/test_pitch_dim_footprint.py +290 -0
- draftwright-0.5.0rc4/tests/test_pmi.py +2672 -0
- draftwright-0.5.0rc4/tests/test_pmi_datum_lowering.py +772 -0
- draftwright-0.5.0rc4/tests/test_pmi_gtol_lowering.py +883 -0
- draftwright-0.5.0rc4/tests/test_pmi_part21.py +1888 -0
- draftwright-0.5.0rc4/tests/test_pmi_records.py +88 -0
- draftwright-0.5.0rc4/tests/test_pocket_completeness_evidence.py +474 -0
- draftwright-0.5.0rc4/tests/test_pocket_pattern_completeness_evidence.py +973 -0
- draftwright-0.5.0rc4/tests/test_pocket_pattern_recognition.py +208 -0
- draftwright-0.5.0rc4/tests/test_private_test_attr_reads.py +308 -0
- draftwright-0.5.0rc4/tests/test_profile_angles.py +207 -0
- draftwright-0.5.0rc4/tests/test_quality_components.py +385 -0
- draftwright-0.5.0rc4/tests/test_recogniser_capabilities.py +1714 -0
- draftwright-0.5.0rc4/tests/test_recogniser_contract.py +672 -0
- draftwright-0.5.0rc4/tests/test_refactor_golden.py +463 -0
- draftwright-0.5.0rc4/tests/test_remaining_ink_overlaps.py +243 -0
- draftwright-0.5.0rc4/tests/test_render_seam.py +444 -0
- draftwright-0.5.0rc4/tests/test_report_projection.py +1024 -0
- draftwright-0.5.0rc4/tests/test_requirement_catalog.py +405 -0
- draftwright-0.5.0rc4/tests/test_requirement_catalog_families.py +151 -0
- draftwright-0.5.0rc4/tests/test_sheet_emit.py +4987 -0
- draftwright-0.5.0rc4/tests/test_sheet_furniture.py +149 -0
- draftwright-0.5.0rc4/tests/test_sheet_section.py +162 -0
- draftwright-0.5.0rc4/tests/test_sheet_tables.py +309 -0
- draftwright-0.5.0rc4/tests/test_slanted_blind_step.py +265 -0
- draftwright-0.5.0rc4/tests/test_slot_completeness.py +752 -0
- draftwright-0.5.0rc4/tests/test_slot_recognition.py +571 -0
- draftwright-0.5.0rc4/tests/test_source_shape.py +302 -0
- draftwright-0.5.0rc4/tests/test_step_analysis_evaluation.py +561 -0
- draftwright-0.5.0rc4/tests/test_step_profile_grouping.py +34 -0
- draftwright-0.5.0rc4/tests/test_strip_layout.py +2034 -0
- draftwright-0.5.0rc4/tests/test_suite_shape.py +104 -0
- draftwright-0.5.0rc4/tests/test_through_step_semantics.py +1811 -0
- draftwright-0.5.0rc4/tests/test_tier_manifest.py +781 -0
- draftwright-0.5.0rc4/tests/test_title_block_units_format.py +522 -0
- draftwright-0.5.0rc4/tests/test_turned_diameters.py +927 -0
- draftwright-0.5.0rc4/tests/test_turned_steps.py +118 -0
- draftwright-0.5.0rc4/tests/test_workflows.py +769 -0
- draftwright-0.5.0rc2/CHANGELOG.md +0 -3198
- draftwright-0.5.0rc2/PKG-INFO +0 -1074
- draftwright-0.5.0rc2/README.md +0 -371
- draftwright-0.5.0rc2/docs/reference/recogniser-capabilities.md +0 -802
- draftwright-0.5.0rc2/pyproject.toml +0 -200
- draftwright-0.5.0rc2/skills/SKILL.md +0 -381
- draftwright-0.5.0rc2/src/draftwright/_build_profile.py +0 -186
- draftwright-0.5.0rc2/src/draftwright/_core.py +0 -2277
- draftwright-0.5.0rc2/src/draftwright/_geometry.py +0 -1280
- draftwright-0.5.0rc2/src/draftwright/_pmi_part21.py +0 -1533
- draftwright-0.5.0rc2/src/draftwright/_pmi_support_blockers.py +0 -176
- draftwright-0.5.0rc2/src/draftwright/analysis.py +0 -2442
- draftwright-0.5.0rc2/src/draftwright/annotate.py +0 -26
- draftwright-0.5.0rc2/src/draftwright/annotations/_axial_render.py +0 -1091
- draftwright-0.5.0rc2/src/draftwright/annotations/_common.py +0 -2408
- draftwright-0.5.0rc2/src/draftwright/annotations/_diameters.py +0 -882
- draftwright-0.5.0rc2/src/draftwright/annotations/_dimension_ink_repair.py +0 -523
- draftwright-0.5.0rc2/src/draftwright/annotations/_edge_callouts.py +0 -573
- draftwright-0.5.0rc2/src/draftwright/annotations/_envelope.py +0 -329
- draftwright-0.5.0rc2/src/draftwright/annotations/_gdt.py +0 -622
- draftwright-0.5.0rc2/src/draftwright/annotations/_leader_commit.py +0 -502
- draftwright-0.5.0rc2/src/draftwright/annotations/_leader_fixed_ink.py +0 -492
- draftwright-0.5.0rc2/src/draftwright/annotations/_locations.py +0 -798
- draftwright-0.5.0rc2/src/draftwright/annotations/_machined_leaders.py +0 -437
- draftwright-0.5.0rc2/src/draftwright/annotations/_patterns.py +0 -585
- draftwright-0.5.0rc2/src/draftwright/annotations/_placement_occupancy.py +0 -626
- draftwright-0.5.0rc2/src/draftwright/annotations/_pmi_dimensions.py +0 -1768
- draftwright-0.5.0rc2/src/draftwright/annotations/_slots.py +0 -701
- draftwright-0.5.0rc2/src/draftwright/annotations/_step_lengths.py +0 -923
- draftwright-0.5.0rc2/src/draftwright/annotations/_thin_profiles.py +0 -299
- draftwright-0.5.0rc2/src/draftwright/annotations/angular.py +0 -142
- draftwright-0.5.0rc2/src/draftwright/annotations/balloons.py +0 -1161
- draftwright-0.5.0rc2/src/draftwright/annotations/from_model.py +0 -2485
- draftwright-0.5.0rc2/src/draftwright/annotations/hole_locations.py +0 -705
- draftwright-0.5.0rc2/src/draftwright/annotations/holes.py +0 -2469
- draftwright-0.5.0rc2/src/draftwright/annotations/leaders.py +0 -2430
- draftwright-0.5.0rc2/src/draftwright/annotations/orchestrator.py +0 -1918
- draftwright-0.5.0rc2/src/draftwright/annotations/routed.py +0 -138
- draftwright-0.5.0rc2/src/draftwright/annotations/sections.py +0 -1580
- draftwright-0.5.0rc2/src/draftwright/audit.py +0 -1430
- draftwright-0.5.0rc2/src/draftwright/build_once.py +0 -660
- draftwright-0.5.0rc2/src/draftwright/build_options.py +0 -152
- draftwright-0.5.0rc2/src/draftwright/builder.py +0 -2863
- draftwright-0.5.0rc2/src/draftwright/cli.py +0 -500
- draftwright-0.5.0rc2/src/draftwright/compose.py +0 -2745
- draftwright-0.5.0rc2/src/draftwright/drawing.py +0 -1956
- draftwright-0.5.0rc2/src/draftwright/drawing_diagnostics.py +0 -544
- draftwright-0.5.0rc2/src/draftwright/drawing_edits.py +0 -863
- draftwright-0.5.0rc2/src/draftwright/drawing_evidence.py +0 -419
- draftwright-0.5.0rc2/src/draftwright/drawing_export.py +0 -329
- draftwright-0.5.0rc2/src/draftwright/drawing_state.py +0 -160
- draftwright-0.5.0rc2/src/draftwright/evaluation/_edge_profile_evidence.py +0 -481
- draftwright-0.5.0rc2/src/draftwright/evaluation/_hole_family_evidence.py +0 -564
- draftwright-0.5.0rc2/src/draftwright/evaluation/_pocket_evidence.py +0 -626
- draftwright-0.5.0rc2/src/draftwright/evaluation/_turned_step_evidence.py +0 -363
- draftwright-0.5.0rc2/src/draftwright/evaluation/step_analysis.py +0 -2717
- draftwright-0.5.0rc2/src/draftwright/export.py +0 -843
- draftwright-0.5.0rc2/src/draftwright/inspection.py +0 -789
- draftwright-0.5.0rc2/src/draftwright/inspection_contract.py +0 -279
- draftwright-0.5.0rc2/src/draftwright/intent_routing.py +0 -279
- draftwright-0.5.0rc2/src/draftwright/layout.py +0 -1153
- draftwright-0.5.0rc2/src/draftwright/layout_selection.py +0 -638
- draftwright-0.5.0rc2/src/draftwright/linting/__init__.py +0 -135
- draftwright-0.5.0rc2/src/draftwright/linting/_coverage_common.py +0 -191
- draftwright-0.5.0rc2/src/draftwright/linting/angular.py +0 -618
- draftwright-0.5.0rc2/src/draftwright/linting/blend_coverage.py +0 -316
- draftwright-0.5.0rc2/src/draftwright/linting/boss_coverage.py +0 -247
- draftwright-0.5.0rc2/src/draftwright/linting/chamfer_coverage.py +0 -162
- draftwright-0.5.0rc2/src/draftwright/linting/circular_blind_step_coverage.py +0 -322
- draftwright-0.5.0rc2/src/draftwright/linting/coverage.py +0 -2574
- draftwright-0.5.0rc2/src/draftwright/linting/envelope_coverage.py +0 -211
- draftwright-0.5.0rc2/src/draftwright/linting/fillet_coverage.py +0 -159
- draftwright-0.5.0rc2/src/draftwright/linting/gear_coverage.py +0 -185
- draftwright-0.5.0rc2/src/draftwright/linting/hole_coverage.py +0 -1533
- draftwright-0.5.0rc2/src/draftwright/linting/orchestration.py +0 -672
- draftwright-0.5.0rc2/src/draftwright/linting/paired_ramp_step_coverage.py +0 -198
- draftwright-0.5.0rc2/src/draftwright/linting/pmi_coverage.py +0 -535
- draftwright-0.5.0rc2/src/draftwright/linting/polygonal_boss_coverage.py +0 -352
- draftwright-0.5.0rc2/src/draftwright/linting/polygonal_stock_coverage.py +0 -432
- draftwright-0.5.0rc2/src/draftwright/linting/quality.py +0 -1007
- draftwright-0.5.0rc2/src/draftwright/linting/rectangular_blind_slot_coverage.py +0 -269
- draftwright-0.5.0rc2/src/draftwright/linting/requirements.py +0 -222
- draftwright-0.5.0rc2/src/draftwright/linting/round_bottom_blind_slot_coverage.py +0 -275
- draftwright-0.5.0rc2/src/draftwright/linting/structural.py +0 -1671
- draftwright-0.5.0rc2/src/draftwright/linting/through_step_coverage.py +0 -673
- draftwright-0.5.0rc2/src/draftwright/make_drawing.py +0 -30
- draftwright-0.5.0rc2/src/draftwright/measurement_support.py +0 -95
- draftwright-0.5.0rc2/src/draftwright/model/callout.py +0 -731
- draftwright-0.5.0rc2/src/draftwright/model/compiled.py +0 -2458
- draftwright-0.5.0rc2/src/draftwright/model/declare.py +0 -2771
- draftwright-0.5.0rc2/src/draftwright/model/detect.py +0 -2816
- draftwright-0.5.0rc2/src/draftwright/model/detect_inventory.py +0 -276
- draftwright-0.5.0rc2/src/draftwright/model/detect_ownership.py +0 -527
- draftwright-0.5.0rc2/src/draftwright/model/ir.py +0 -2922
- draftwright-0.5.0rc2/src/draftwright/model/ir_foundation.py +0 -1048
- draftwright-0.5.0rc2/src/draftwright/model/planner.py +0 -2141
- draftwright-0.5.0rc2/src/draftwright/model/pmi_lowering.py +0 -1403
- draftwright-0.5.0rc2/src/draftwright/pdf_text.py +0 -672
- draftwright-0.5.0rc2/src/draftwright/pmi.py +0 -2910
- draftwright-0.5.0rc2/src/draftwright/profile_angles.py +0 -312
- draftwright-0.5.0rc2/src/draftwright/projection.py +0 -658
- draftwright-0.5.0rc2/src/draftwright/recogniser_contract.py +0 -1074
- draftwright-0.5.0rc2/src/draftwright/recogniser_policy.py +0 -100
- draftwright-0.5.0rc2/src/draftwright/recogniser_schema.py +0 -102
- draftwright-0.5.0rc2/src/draftwright/recognition_ownership.py +0 -1215
- draftwright-0.5.0rc2/src/draftwright/repair.py +0 -341
- draftwright-0.5.0rc2/src/draftwright/reporting.py +0 -2851
- draftwright-0.5.0rc2/src/draftwright/section_recess_contract.py +0 -998
- draftwright-0.5.0rc2/src/draftwright/sheet.py +0 -2917
- draftwright-0.5.0rc2/src/draftwright/sheet_emit.py +0 -2162
- draftwright-0.5.0rc2/src/draftwright/sheet_feature_lines.py +0 -961
- draftwright-0.5.0rc2/src/draftwright/sheet_views.py +0 -667
- draftwright-0.5.0rc2/tests/_tier_manifest.py +0 -661
- draftwright-0.5.0rc2/tests/fixtures/evaluation/README.md +0 -248
- draftwright-0.5.0rc2/tests/fixtures/evaluation/corpus-hole-patterns-v1.json +0 -151
- draftwright-0.5.0rc2/tests/refactor_golden/grid_plate.json +0 -503
- draftwright-0.5.0rc2/tests/test_adr0018_view_selection.py +0 -714
- draftwright-0.5.0rc2/tests/test_adr_corpus.py +0 -134
- draftwright-0.5.0rc2/tests/test_agent_improvement_canary_issue_1716.py +0 -290
- draftwright-0.5.0rc2/tests/test_annotation_box_composition.py +0 -131
- draftwright-0.5.0rc2/tests/test_annotation_box_corpus.py +0 -81
- draftwright-0.5.0rc2/tests/test_annotation_layout_product.py +0 -740
- draftwright-0.5.0rc2/tests/test_annotation_scheme_compare_script.py +0 -764
- draftwright-0.5.0rc2/tests/test_architecture_docs.py +0 -28
- draftwright-0.5.0rc2/tests/test_boss_ownership.py +0 -763
- draftwright-0.5.0rc2/tests/test_build_drawing_entrypoints.py +0 -279
- draftwright-0.5.0rc2/tests/test_channel_ownership.py +0 -390
- draftwright-0.5.0rc2/tests/test_circular_blind_step_semantics.py +0 -1073
- draftwright-0.5.0rc2/tests/test_compiled_plan_boundary.py +0 -1383
- draftwright-0.5.0rc2/tests/test_compose_then_pack.py +0 -504
- draftwright-0.5.0rc2/tests/test_declare.py +0 -2246
- draftwright-0.5.0rc2/tests/test_declared_recognition_gate.py +0 -573
- draftwright-0.5.0rc2/tests/test_deprecation_dates.py +0 -227
- draftwright-0.5.0rc2/tests/test_detect_registry.py +0 -337
- draftwright-0.5.0rc2/tests/test_diameter_leaders.py +0 -316
- draftwright-0.5.0rc2/tests/test_dimension_lane_canary_issue_1757.py +0 -153
- draftwright-0.5.0rc2/tests/test_dimension_role_vocabulary.py +0 -397
- draftwright-0.5.0rc2/tests/test_document_build.py +0 -498
- draftwright-0.5.0rc2/tests/test_drawing_encapsulation.py +0 -566
- draftwright-0.5.0rc2/tests/test_e2e_standards.py +0 -551
- draftwright-0.5.0rc2/tests/test_export_formats.py +0 -327
- draftwright-0.5.0rc2/tests/test_feature_edit_verbs.py +0 -396
- draftwright-0.5.0rc2/tests/test_feature_leader_candidate_regions.py +0 -1273
- draftwright-0.5.0rc2/tests/test_gdt_ink_shared.py +0 -288
- draftwright-0.5.0rc2/tests/test_gdt_placement.py +0 -512
- draftwright-0.5.0rc2/tests/test_groove_completeness_evidence.py +0 -655
- draftwright-0.5.0rc2/tests/test_hole_annotations.py +0 -316
- draftwright-0.5.0rc2/tests/test_hole_pattern_callouts.py +0 -173
- draftwright-0.5.0rc2/tests/test_hole_table.py +0 -759
- draftwright-0.5.0rc2/tests/test_import_boundaries.py +0 -1344
- draftwright-0.5.0rc2/tests/test_inspection_contract.py +0 -182
- draftwright-0.5.0rc2/tests/test_interior_label_placement.py +0 -337
- draftwright-0.5.0rc2/tests/test_issue_1058_wheel_profile.py +0 -911
- draftwright-0.5.0rc2/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +0 -484
- draftwright-0.5.0rc2/tests/test_issue_1142_hole_leader_labels.py +0 -262
- draftwright-0.5.0rc2/tests/test_issue_1143_hole_completeness.py +0 -2902
- draftwright-0.5.0rc2/tests/test_issue_1166_cross_pass_feature_leaders.py +0 -2615
- draftwright-0.5.0rc2/tests/test_issue_1176_quality_fidelity.py +0 -1028
- draftwright-0.5.0rc2/tests/test_issue_1188_per_view_assignment.py +0 -109
- draftwright-0.5.0rc2/tests/test_issue_1190_section_decision.py +0 -255
- draftwright-0.5.0rc2/tests/test_issue_1202_observed_drawing_consumer.py +0 -633
- draftwright-0.5.0rc2/tests/test_issue_1215_envelope_tolerance.py +0 -321
- draftwright-0.5.0rc2/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +0 -957
- draftwright-0.5.0rc2/tests/test_issue_1217_the_facility_is_shared.py +0 -427
- draftwright-0.5.0rc2/tests/test_issue_1219_location_claims_its_own_axis.py +0 -286
- draftwright-0.5.0rc2/tests/test_issue_1298_manufacturing_requirements.py +0 -1868
- draftwright-0.5.0rc2/tests/test_issue_1308_machined_leader_analytics.py +0 -420
- draftwright-0.5.0rc2/tests/test_issue_1352_searchable_pdf_text.py +0 -1101
- draftwright-0.5.0rc2/tests/test_issue_1357_framed_activation.py +0 -237
- draftwright-0.5.0rc2/tests/test_issue_1370_double_d_completeness_evidence.py +0 -731
- draftwright-0.5.0rc2/tests/test_issue_1370_hole_pattern_completeness_evidence.py +0 -306
- draftwright-0.5.0rc2/tests/test_issue_1371_polygonal_stock_completeness_evidence.py +0 -1211
- draftwright-0.5.0rc2/tests/test_issue_1460_step_inspection.py +0 -1063
- draftwright-0.5.0rc2/tests/test_issue_1505_diameter_coverage.py +0 -156
- draftwright-0.5.0rc2/tests/test_issue_1518_explicit_rear.py +0 -686
- draftwright-0.5.0rc2/tests/test_issue_1531_semantic_hole_counts.py +0 -255
- draftwright-0.5.0rc2/tests/test_issue_1544_frame_document_canary.py +0 -419
- draftwright-0.5.0rc2/tests/test_issue_1596_bolt_circle_corroboration.py +0 -452
- draftwright-0.5.0rc2/tests/test_issue_740_leader_assignment.py +0 -774
- draftwright-0.5.0rc2/tests/test_issue_798_material_field.py +0 -495
- draftwright-0.5.0rc2/tests/test_issue_798_silhouette_lint.py +0 -346
- draftwright-0.5.0rc2/tests/test_issue_883_location_identity.py +0 -574
- draftwright-0.5.0rc2/tests/test_issue_916_pocket_leader.py +0 -110
- draftwright-0.5.0rc2/tests/test_label_provenance.py +0 -186
- draftwright-0.5.0rc2/tests/test_layout_override_lane_issue_1757.py +0 -264
- draftwright-0.5.0rc2/tests/test_layout_safety.py +0 -756
- draftwright-0.5.0rc2/tests/test_layout_scheme.py +0 -583
- draftwright-0.5.0rc2/tests/test_lint_summary.py +0 -404
- draftwright-0.5.0rc2/tests/test_location_dimensions.py +0 -538
- draftwright-0.5.0rc2/tests/test_note_verb.py +0 -71
- draftwright-0.5.0rc2/tests/test_pad_rendering.py +0 -415
- draftwright-0.5.0rc2/tests/test_parameter_id.py +0 -757
- draftwright-0.5.0rc2/tests/test_pareto_loop_canary_issue_1753.py +0 -169
- draftwright-0.5.0rc2/tests/test_part_model.py +0 -367
- draftwright-0.5.0rc2/tests/test_pitch_dim_footprint.py +0 -290
- draftwright-0.5.0rc2/tests/test_pmi.py +0 -2506
- draftwright-0.5.0rc2/tests/test_pmi_datum_lowering.py +0 -480
- draftwright-0.5.0rc2/tests/test_pmi_gtol_lowering.py +0 -300
- draftwright-0.5.0rc2/tests/test_pmi_part21.py +0 -1506
- draftwright-0.5.0rc2/tests/test_pmi_records.py +0 -88
- draftwright-0.5.0rc2/tests/test_pocket_completeness_evidence.py +0 -474
- draftwright-0.5.0rc2/tests/test_pocket_pattern_completeness_evidence.py +0 -970
- draftwright-0.5.0rc2/tests/test_pocket_pattern_recognition.py +0 -206
- draftwright-0.5.0rc2/tests/test_private_test_attr_reads.py +0 -309
- draftwright-0.5.0rc2/tests/test_profile_angles.py +0 -195
- draftwright-0.5.0rc2/tests/test_quality_components.py +0 -382
- draftwright-0.5.0rc2/tests/test_recogniser_capabilities.py +0 -1709
- draftwright-0.5.0rc2/tests/test_recogniser_contract.py +0 -646
- draftwright-0.5.0rc2/tests/test_refactor_golden.py +0 -458
- draftwright-0.5.0rc2/tests/test_remaining_ink_overlaps.py +0 -242
- draftwright-0.5.0rc2/tests/test_render_seam.py +0 -430
- draftwright-0.5.0rc2/tests/test_report_projection.py +0 -1023
- draftwright-0.5.0rc2/tests/test_requirement_catalog.py +0 -403
- draftwright-0.5.0rc2/tests/test_requirement_catalog_families.py +0 -132
- draftwright-0.5.0rc2/tests/test_sheet_emit.py +0 -4974
- draftwright-0.5.0rc2/tests/test_sheet_furniture.py +0 -145
- draftwright-0.5.0rc2/tests/test_sheet_section.py +0 -159
- draftwright-0.5.0rc2/tests/test_sheet_tables.py +0 -307
- draftwright-0.5.0rc2/tests/test_slanted_blind_step.py +0 -260
- draftwright-0.5.0rc2/tests/test_slot_completeness.py +0 -706
- draftwright-0.5.0rc2/tests/test_slot_recognition.py +0 -558
- draftwright-0.5.0rc2/tests/test_source_shape.py +0 -104
- draftwright-0.5.0rc2/tests/test_step_analysis_evaluation.py +0 -417
- draftwright-0.5.0rc2/tests/test_strip_layout.py +0 -1935
- draftwright-0.5.0rc2/tests/test_suite_shape.py +0 -64
- draftwright-0.5.0rc2/tests/test_through_step_semantics.py +0 -1793
- draftwright-0.5.0rc2/tests/test_tier_manifest.py +0 -699
- draftwright-0.5.0rc2/tests/test_title_block_units_format.py +0 -189
- draftwright-0.5.0rc2/tests/test_turned_diameters.py +0 -821
- draftwright-0.5.0rc2/tests/test_turned_steps.py +0 -117
- draftwright-0.5.0rc2/tests/test_workflows.py +0 -761
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/.gitignore +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/LICENSE +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/docs/adr/README.md +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/docs/reference/sheet.md +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/__init__.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/_pmi_linear_geometry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/_pmi_schema.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/_warnings.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/angular_geometry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotation_layout_profile.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_circular_recesses.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_dimension_ink.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_height_ladder.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_hole_leader_placement.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_leader_candidates.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_placement_geometry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_pocket_pad.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_polygonal_prisms.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/_strip_postsolve.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/gears.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/hole_leader_candidates.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/annotations/solve_trace.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/auxiliary_layout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/blend_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/build_policy.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/contract_values.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/document.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/document_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/document_input.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/drawing_tables.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/evaluation/__init__.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/evaluation/_double_d_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/evaluation/_flat_polygonal_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/evaluation/_groove_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/evaluation/_prismatic_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/explicit_scale.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/feature_identity.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/fits.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/intent_drain.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/intents.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/layout_safety.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/layout_scheme.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/leader_policy.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/_registry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/angled_step_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/channel_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/flat_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/groove_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/gusset_rib_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/ink_overlap.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/issues.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/oriented_slot_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/pad_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/passage_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/plate_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/pocket_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/pocket_pattern_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/prismatic_pocket_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/profiled_bore_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/schedule_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/section_recess_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/slot_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/linting/turned_step_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/location_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/model/__init__.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/model/dimension_intent.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/model/manufacturing_schedule.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/model/oriented_slot_geometry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/obligations.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/oriented_slot_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/plate_correspondence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/progress.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/py.typed +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/recognition/__init__.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/recognition_cache.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/recognition_frame.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/registry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/replay_assessment.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/score.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/sheet_features.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/sheet_layout_controls.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/sheet_object_source.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/src/draftwright/view_plan.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_burden_report.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_corpus_cover.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_drawing_helpers.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_evidence_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_kernel.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_layout_helpers.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_layout_sig.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_mutation_corpus.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_pad_rendering_fixtures.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_parts.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_pattern_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_recogniser_public_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_section_recess_cases.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/_unit_manifest.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/conftest.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/annotation-layout-corpus-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/annotation-layout-corpus-v2.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/annotation-layout-holdout-ftc09-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/annotation-layout-holdout-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/ap242_single_cylinder_diameter.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/blind-hole.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-asymmetric.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-compound.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-overlap.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-plain.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-planar-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-planar-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-planar-z.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/chamfer-turned.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-chamfers-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-countersinks-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-double-d-bores-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-fillets-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-flats-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-grooves-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-plates-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-pocket-patterns-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-pockets-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-polygonal-bosses-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-polygonal-stock-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-rectangular-pads-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-turned-steps-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/corpus-v1.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/countersink-deburr.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/countersink-external-cone.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/countersink-mixed-pair.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/countersink-single.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/countersink-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/countersink-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-axis-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-axis-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-blind.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-coaxial-compound.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-opposed-blind.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-roll-30.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-round-bore.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-single-z.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/double-d-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-compound.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-overlap.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-plain.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-planar-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-planar-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-planar-z.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-repeated.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/fillet-turned.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-coaxial.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-double-d.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-lone-d.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-nonround.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-slanted-double-d.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/flat-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-compound.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-lone-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-lone-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-lone-z.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-monotonic-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-narrow.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/groove-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-compound-equal.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-detached-body-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-full-span-ledge-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-nested-staircase-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-x-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-x-positive.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-y-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-y-positive.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-z-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pad-z-positive.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pattern-ambiguous.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pattern-grid.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pattern-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pattern-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plain-block.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-compound-equal.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-cross-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-cross-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-detached-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-rotational-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-single-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-t-xz.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-t-yz.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-thick-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-u-additive.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/plate-u-cut.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-compound.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-edge-anchored.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-lone.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-opposed.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-pattern-ambiguous.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-pattern-grid.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-pattern-linear.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-pattern-pair.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-pattern-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-pattern-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-prismatic-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-side.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-through-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/pocket-two-equal.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-compound-equal.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-detached-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-in-plane-rotated.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-other-protrusions-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-recess-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-stock-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-boss-z.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-compound-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-cylinder-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-irregular-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-octagon-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-recess-negative.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-roll17.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-translated.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/polygonal-stock-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-axis-x.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-axis-y.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-axis-z.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-compound.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-repeated-lengths.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-through-bore.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-topology-a.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-topology-b.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/evaluation/turned-step-translated-blind-bore.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/grm03_thumbwheel_drive_screw_ap242_pmi.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/grm04_drive_plate.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/issue_1247_angled_blind_step.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/issue_1595_whistle_key_frame.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/issue_1595_whistle_key_lever.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/issue_915_case_study_2.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/nist_ftc_09_asme1_ap242-e1.stp +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/fixtures/whistle_frame_reference.step +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/bracket_section.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/centered_rebate.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/chamfered.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/filleted.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/flange_dense.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/grooved_shaft.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/hex_bar.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/holed_slot.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/pocketed.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/prismatic_ladder.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/scattered_plate.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/side_drilled.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/refactor_golden/turned_stepped.json +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_add_dimension.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_adr0018_view_routing.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_agents_guide.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_analysis_geometry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_angle_patterns.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_angular_references.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_angular_rendering.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_annotation_scheme_corpus_script.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_annotation_scheme_shadow_script.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_api_docs.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_arrangement_gate.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_assessment_comparison_issue_1712.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_audit_differential.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_auxiliary_layout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_axial_dimensions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_balloon_ring_standoff.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_blind_slot_completeness.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_blind_slot_semantics.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_build_profile_harness.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_burden_report.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_candidate_evidence_issue_1726.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_candidate_preview_sheet_holdout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_canonical_angles.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_carve_free_position_callers.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_cli_behavior.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_cli_report_sidecar.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_clone_budget.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_contract_values.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_corpus_cover.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_counting_calls.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_coverage_mode.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_declaration_identity_issue_1710.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_declaration_report_issue_1710.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_declared_report_issue_1688.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_deferred_edits.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_dense_sheet_canary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_depth_estimators.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_derived_view_integration.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_derived_view_planning.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_detail_views.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_detect_once.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_diameter_deduplication.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_dimension_intent_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_document_claim_authority.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_document_claims.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_document_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_document_report.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_document_report_authority.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_drawing_operations.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_drawing_state.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_dynamic_corridors.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_e2e_slice.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_envelope_view_route_issue_1813.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_equivalent_dimension_presentations_issue_1759.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_export_dxf_curves.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_export_dxf_zoom.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_export_reproducible.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_export_shape.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_external_recognition_boundary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_feature_edit_corridors.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_feature_edit_replay.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_feature_provenance.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_feature_queries.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_fillets_adjacency.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_fit_calculations.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_fits.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_flat_callout_precision.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_flat_completeness.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_flat_stock_identity.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_flat_stock_opposition.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_format_selector.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_formatting.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_framed_step_family_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_geometry_graph_spike.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_grid_lattice_convention.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_groove_profile.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_gusset_rib_semantics.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_ir_foundation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_iso_detail_growth.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_iso_layout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_iso_nts_caption_placement.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_isometric_orientation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_isometric_placement.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1000_envelope_reuse.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1006_measurement_comparison.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1073_cross_body_patterns.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1082_polygonal_stock.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1086_declared_gears.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1126_requesting_less_never_scores_better.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1130_view_planning_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1132_turned_profile_span_is_reported.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1144_transactional_hole_table.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1146_scale_completeness.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1147_legibility_pair_aggregation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1153_contradictory_dimensions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1154_one_owner_per_measurement.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1155_grm04_sheet_use.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1157_no_implicit_general_tolerance.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1177_angular_dimensions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1187_unroutable_leaders.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1196_deterministic_view_names.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1204_multiscale_view_issues.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1209_linear_pmi_witnesses.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1216_callout_reservation_measures_ink.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1216_pairwise_across_scale_groups.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1217_claimed_representations.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1229_ledger_member_keying.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1240_iso_above_strip_visibility.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1245_passage_disposition.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1246_prismatic_pocket_disposition.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1247_angled_step_disposition.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1254_turned_chamfers.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1260_view_constraints.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1262_automatic_turned_views.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1276_turned_leader_targets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1281_turned_fillets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1296_cylindrical_diameter_pmi.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1299_page_escalation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1312_engine_costs.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1325_nominal_agreement.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1332_overlap_remedy.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1333_bounded_ink_repair.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1334_prevent_ink.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1336_grm03_ap242_pmi_fixture.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1338_scale_before_page_escalation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1349_precision_display.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1350_detected_takeover.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1351_structured_note_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1353_cnc_authoritative_workflow.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1357_framed_boundary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1357_plural_turned_profiles.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1357_pmi_frame.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1360_thread_depth.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1369_hole_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1370_countersink_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1371_flat_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1373_plate_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1374_chamfer_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1374_fillet_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1374_turned_step_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1378_diameter_leader_targets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1392_recognisers_048.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1395_degenerate_iso_region.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1396_layout_advisories.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1397_unverifiable_requirement_message.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1432_adoption.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1432_boundary_failures.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1432_oriented_slot_semantics.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1433_blend_semantics.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1450_boss_blend_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1466_dimension_options.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1466_semantic_sides.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1479_radius_leader_targets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1485_curved_pockets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1485_quiddity_024_boundary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1485_rounded_pockets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1505_short_axial_chains.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1511_turned_boss_heights.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1514_projection_safeguard.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1515_first_angle.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1516_dimension_text.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1517_through_indicator.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1524_tolerance_magnitude.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1530_section_provenance.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1532_authored_section_examples.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1533_review_diagnostics.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1534_build_progress.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1536_title_overflow.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1543_feature_schedules.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1543_schedule_requirements.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1555_turned_recognition_format_invariance.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1560_envelope_axes.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1563_sheet_pmi_reconciliation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1585_title_block_date.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1593_title_block_keepout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1598_hex_pockets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1604_internal_section.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1612_frame_sergio_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1612_sheet_margins.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_1613_circular_channel.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_367_leader_ink.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_443_grm03_axial_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_563_placement_intent.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_676_polygonal_boss.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_798_floor_cardinality.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_827_real_part_canary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_885_prismatic_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_909_sloped_profile.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_915_dense_case.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_917_open_channel.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_924_zero_length_shoulders.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_955_height_contingency.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_issue_958_cross_solid_recognition.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_cleanliness.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_constants.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_evidence_issue_1711.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_generalisation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_hypothesis.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_override_side_issue_1757.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_layout_property.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_leader_footprint.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_leader_region_policy.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_box_cache.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_coverage_common.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_ink_overlap.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_reconciliation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_structural.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_lint_suggestions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_linting.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_location_vocabulary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_machined_feature_callouts.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_make_drawing_entrypoints.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_manufacturing_schedule.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_nested_recognition_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_nominal_step_pmi.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_object_aspects.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_occupancy_boxes.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_occurrence_recognition_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_overall_height_coverage.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_pad_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_paired_ramp_semantics.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_part_classification.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_pattern_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_pattern_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_place_dimension.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_plate_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_pmi_common_labels.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_pocket_pattern.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_polygonal_boss_completeness_evidence.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_pre_render_profile_choice.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_principal_profile_classifier.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_prismatic_boss_diameter.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_prismatic_classification.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_prismatic_dimensions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_private_test_imports.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_projection_symbol_default.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_quiddity_lifecycle_boundary.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_real_part_fixtures.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recogniser_adoption.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recogniser_policy.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recogniser_step_inventory.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recognition_boundary_failures.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recognition_evidence_schema.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recognition_policy_dispositions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_recognition_result.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_registry.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_repack_geometry_seam.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_repair.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_replay_assessment_issue_1715.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_report_status_reasons_issue_1618.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_report_writer.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_requirement_applicability.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_requirement_carriers.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_requirement_dimension_sharing.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_scale_policy.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_scale_selection.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_score.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_script_detail_parity.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_section_hatching.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_section_recess_contract.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_section_recess_pockets.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_shared_box_memo.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_shared_drawing_cache.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_sheet_fallback_issue_1797.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_sheet_gdt.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_sheet_generation_snapshot.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_sheet_identity_invariant.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_sheet_notes.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_sheet_of.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_slot_pattern.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_slot_pattern_recognition.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_soft_deprecation.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_solve_trace.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_strip_zones.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_suppression_ledger.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_suppression_marks.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_through_step_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_tolerances.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_turned_lengths.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_turned_step_ownership.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_two_pass_layout.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_typ_dimensions.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_typed_remediation_projection_issue_1759.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_version_bump_ci.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_view_blocks.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_view_coordinates.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_view_plan.py +0 -0
- {draftwright-0.5.0rc2 → draftwright-0.5.0rc4}/tests/test_witness_label_reconciliation.py +0 -0
|
@@ -0,0 +1,3217 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Pin Quiddity 0.3.10 and classify its seven new recognition families explicitly. Four-hole
|
|
8
|
+
rectangular sets now use the existing grid grammar and state both pitches instead of a
|
|
9
|
+
bolt-circle claim; paired-ramp and through-step schema 3 records retain their established
|
|
10
|
+
drawing claims.
|
|
11
|
+
- The agent usage guide moved from `AGENTS.md` to `docs/using-draftwright.md`; `AGENTS.md`
|
|
12
|
+
now holds the contributor instructions formerly in `CLAUDE.md` (#1938).
|
|
13
|
+
|
|
14
|
+
### Removed
|
|
15
|
+
|
|
16
|
+
- Removed the eight expired `Drawing` methods (`add`, `add_view`, `clear_annotations`,
|
|
17
|
+
`set_view_coordinates`, `drop_view_coordinates`, `attach_part_model`,
|
|
18
|
+
`attach_solve_trace`, and `export_pdf`) and the legacy `Drawing.export` tuple
|
|
19
|
+
forms at their published 0.5.0 target. Pass `formats=` explicitly; export
|
|
20
|
+
returns a `{format: path}` dict. `Drawing.place_dim`, `Sheet.add_view`,
|
|
21
|
+
`Sheet.export`'s PDF default, and `make_drawing`'s SVG/DXF tuple remain (#2113).
|
|
22
|
+
|
|
23
|
+
## v0.4.11–v0.5.0-rc1 — cumulative notes since v0.4.10
|
|
24
|
+
|
|
25
|
+
These entries accumulated across patch releases and were all present by v0.4.31.
|
|
26
|
+
They describe changes included by RC1; they do not assign each change to its first
|
|
27
|
+
released version.
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- A hash-pinned AP242 CTC-01 canary now proves the full Pareto-first layout loop against
|
|
32
|
+
a reviewed 80-measurement denominator: read typed finding remedies, apply only two public
|
|
33
|
+
declaration-side overrides, replay once, and establish legibility-only dominance while 12
|
|
34
|
+
unresolved claims remain carried and certification remains unavailable (#1753). Detailed
|
|
35
|
+
diagnostic prose remains optional presentation derived from structured evidence, never a
|
|
36
|
+
comparison identity or decision input.
|
|
37
|
+
- Declared slot width and length dimensions now expose bounded, feature-relative lanes through
|
|
38
|
+
`DimensionIntent.place(lane=...)` and declaration-scoped
|
|
39
|
+
`layout_override(..., parameter=..., lane=...)`. Generated scripts and report-v8 evidence
|
|
40
|
+
retain the layout-only policy; the shared solver admits only wholly interior or exterior,
|
|
41
|
+
page-safe, ink-clear candidates and reports bounded blocker evidence when a requested lane is
|
|
42
|
+
infeasible. Automatic drawings and scripts without lane intent remain unchanged (#1757).
|
|
43
|
+
- Declared sheets now support append-only, build-scoped `layout_override(..., side=...)`
|
|
44
|
+
edits plus structured capability and validation queries. Overrides select only a semantic
|
|
45
|
+
corridor, retain declaration identity through generated-script replay, and appear as
|
|
46
|
+
layout-only resolution evidence in declared report v8; coordinates and engineering meaning
|
|
47
|
+
remain unchanged, and sheets without overrides preserve existing behaviour (#1757).
|
|
48
|
+
- Raw automatic report assessments now include a typed remediation projection that separates
|
|
49
|
+
contradictions, missing carriers, layout, importer/lowering, source ambiguity, and unavailable
|
|
50
|
+
evidence. It retains affected evidence identities, names preservation invariants, advertises
|
|
51
|
+
only bounded public actions, and leaves unknown findings unclassified without guessing (#1759).
|
|
52
|
+
- Raw automatic reports now lead agents with a vector-first `lint.assessment`: per-axis status,
|
|
53
|
+
affected counts, available denominators, unavailable reasons, and stable structured reasons
|
|
54
|
+
for every `needs-attention` verdict. Its human summary is rendered from the same reason rows,
|
|
55
|
+
while legacy lint scores remain compatibility-only diagnostics and cannot select status
|
|
56
|
+
(#1609, #1618).
|
|
57
|
+
- Replay comparison now matches unresolved measurement evidence by its serialized annotation,
|
|
58
|
+
table cell, or ownerless parameter identity and classifies it as carried, resolved,
|
|
59
|
+
introduced, changed, or ambiguous. Carried uncertainty keeps certification unavailable but
|
|
60
|
+
no longer erases an otherwise Pareto-dominant layout improvement; new, changed, or duplicate
|
|
61
|
+
identities fail closed (#1753).
|
|
62
|
+
- Assessment comparison v2 reports independently evidenced requirement, completeness,
|
|
63
|
+
fidelity, legibility, and restraint axes plus their Pareto relation. Dominance,
|
|
64
|
+
equivalence, domination, incomparability, and unavailable evidence are derived from concrete
|
|
65
|
+
transitions rather than any legacy diagnostic, component, or audited-completeness score
|
|
66
|
+
(#1609). The v1 `decision` remains temporarily as a deprecated compatibility policy result.
|
|
67
|
+
- Stadium through-slots now retain Quiddity 0.3.2's proved end radius through detection,
|
|
68
|
+
declared `Sheet` scripts, compiled measurement identity, placement, and completeness. A
|
|
69
|
+
normal-to-arc `2× R…` leader distinguishes an obround from an equal-sized rectangular slot
|
|
70
|
+
without introducing coordinate placement (#1752).
|
|
71
|
+
- The Quiddity 0.3.2 adoption also retains corrected overall extents for rounded-corner
|
|
72
|
+
rectangular slots. Hole-pattern records whose members differ only along the drilling axis
|
|
73
|
+
are explicitly refused at the drafting boundary, preserving their ordinary grouped-hole
|
|
74
|
+
requirements instead of emitting a coincident, undrawable pitch pattern.
|
|
75
|
+
- Feature-leader placement now has one coordinate-free drawing policy across
|
|
76
|
+
`build_drawing`, `make_drawing`, `Sheet`, generated scripts, and the CLI. The default
|
|
77
|
+
`auto` policy keeps the shared interior/exterior solve, `interior` requires proved
|
|
78
|
+
interior candidates for eligible unconstrained families, and `exterior` restores the
|
|
79
|
+
historical exterior-only layout for existing diagrams.
|
|
80
|
+
- The standard title block now states drawing `UNITS` (`mm`) and the effective sheet `FORMAT`
|
|
81
|
+
(for example `A2`). Dimension-specified A-series pages receive the standard designation;
|
|
82
|
+
non-standard pages state their actual `WIDTHxHEIGHT`. Its rows share a four-line column grid,
|
|
83
|
+
avoiding visually offset dividers between adjacent fields.
|
|
84
|
+
- A bounded real-part canary now proves the complete agent improvement loop on NIST CTC-01
|
|
85
|
+
(#1716): inspection-to-declaration joins, traced baseline, one sanctioned `Sheet` layout edit,
|
|
86
|
+
replay assessment, fixed-denominator comparison, and fail-closed deletion/owner/provenance
|
|
87
|
+
checks. It performs exactly two CAD builds in the existing single PR canary lane.
|
|
88
|
+
- Replay assessments v2 now retain exact confirmed compiled measurement meanings, and
|
|
89
|
+
`compare_assessments()` evaluates two same-source replays as separate semantic, lint,
|
|
90
|
+
completeness, fidelity, layout, and availability deltas (#1712). Caller-fixed requirements
|
|
91
|
+
expose shared omissions; authorised design changes remain separate; no composite score is
|
|
92
|
+
produced.
|
|
93
|
+
- Generated scripts now atomically write a versioned post-build replay assessment beside their
|
|
94
|
+
outputs (#1715). It binds the exact STEP and edited Python bytes, producer/run options, output
|
|
95
|
+
hashes, declaration/representation map, layout evidence, and lint from the same finalized
|
|
96
|
+
drawing. Failed replays clear only stale Draftwright-owned assessments; `--no-report` opts out.
|
|
97
|
+
- Declared drawing report schema v8 publishes page/view geometry, named annotation ink and
|
|
98
|
+
public line segments, raw-lint joins, semantic remedy choices, and explicit opt-in solver
|
|
99
|
+
evidence (#1711). Coordinates are review evidence only; editable links remain final-IR
|
|
100
|
+
declarations, and an untraced or partially traced build says so instead of appearing clear.
|
|
101
|
+
- STEP inspection schema v4 projects a deterministic report-local source-face roster and
|
|
102
|
+
Quiddity 0.3.1's closed graph rooted at rejected candidates (#1726). Accepted occurrences and
|
|
103
|
+
candidates carry exact defining/constituent face links; rejected roots and direct relationships
|
|
104
|
+
reconcile with aggregate lifecycle counts. The report still states that this is diagnostic
|
|
105
|
+
evidence, not precision, recall, missed-feature truth, or persistent topology identity.
|
|
106
|
+
- Circular-seat recognition, declared features, and generated-script replay (#1613).
|
|
107
|
+
Diameter, open run, arc sweep, and three datum-to-axis coordinates retain each physical
|
|
108
|
+
seat's measurement identities, including counted coaxial callouts and shared axis marks.
|
|
109
|
+
- Opt-in independent sheet margins and exact title-block width on `Sheet`, `build_drawing`,
|
|
110
|
+
`make_drawing`, and the CLI, including generated-script replay (#1612, #1589). Sergio's
|
|
111
|
+
25/10/10/10 mm margins and 175 mm block are explicit options; existing defaults remain.
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- Assessment comparison now rejects an apparent resolution of measurement uncertainty when the
|
|
116
|
+
declaration carrying that unresolved annotation was removed. Deleting crossed GD&T ink can no
|
|
117
|
+
longer masquerade as evidence improvement; genuine resolution with the carrier retained still
|
|
118
|
+
compares normally (#1753).
|
|
119
|
+
- Imported upper/lower limit dimensions now retain their typed absolute interval through the
|
|
120
|
+
compiled evidence boundary. Both bounds together satisfy the owned nominal claim, while a
|
|
121
|
+
changed/missing bound or two coincidental numbers around the nominal still produces
|
|
122
|
+
`claimed_value_absent`; count and through requirements remain separate (#1759).
|
|
123
|
+
- Adopt Quiddity 0.3.1 and require its public rejected-candidate reference in the
|
|
124
|
+
evidence contract (#1726). The provider now suppresses rectangular recess candidates
|
|
125
|
+
that are not material-empty and restores passage discovery used during rotational
|
|
126
|
+
reconciliation; Draftwright's recognition and real-part regression corpora retain
|
|
127
|
+
their reviewed expectations.
|
|
128
|
+
|
|
129
|
+
- Direct and generated builds use the same final IR step ladder for page layout (#1592).
|
|
130
|
+
Raw face levels owned by another feature no longer reserve a phantom step corridor at
|
|
131
|
+
the title-block clearance threshold.
|
|
132
|
+
|
|
133
|
+
- Location intents now accept `.format(decimals=...)` for all selected directions (#1610),
|
|
134
|
+
including plan locations, side-drilled holes and slots. Compiler-owned labels reach
|
|
135
|
+
placement footprints, live location edits and generated scripts. Coincident marks with
|
|
136
|
+
incompatible explicit display text are refused instead of overriding an intent.
|
|
137
|
+
|
|
138
|
+
- Explicit dimension precision, including `.format(decimals=0)`, now reaches geometric
|
|
139
|
+
label critique (#1620). Correct rounding is reported as information; labels outside
|
|
140
|
+
the requested rounding interval still produce `label_vs_measured`. Height and step
|
|
141
|
+
ladders retain the same compiler policy as ordinary dimensions.
|
|
142
|
+
|
|
143
|
+
- **`label_vs_measured` no longer reports the drawing's own rounding as a topology error
|
|
144
|
+
(#1600).** A sheet at one decimal place prints 4.450 as `4.5`; the check then compared
|
|
145
|
+
`4.5` against 4.450 and said "possible axis swap or wrong endpoint". The comparison was
|
|
146
|
+
*relative*, so the same 0.05 mm of rounding passed silently on a 100 mm dimension and was
|
|
147
|
+
an error on a 4 mm one — it fired on smallness, not on wrongness.
|
|
148
|
+
|
|
149
|
+
A label now states its own precision: `4.5` shows one place, `4.45` two, `12` none. A
|
|
150
|
+
difference within half of the last displayed place is the label doing its job; anything
|
|
151
|
+
beyond it is still reported, and an axis swap or wrong endpoint misses by far more.
|
|
152
|
+
|
|
153
|
+
This is a prerequisite for #1602's proposed CI gate: `label_vs_measured` sits in the
|
|
154
|
+
register of codes meaning *the sheet says something untrue*, and a code that fires on
|
|
155
|
+
correct rounding cannot be hard-failed on.
|
|
156
|
+
|
|
157
|
+
### Added
|
|
158
|
+
|
|
159
|
+
- **`nominal_rounded` says where the sheet's precision loses the model value.** Silencing
|
|
160
|
+
the false alarm above left nothing reporting it at all, and `4.5` for 4.450 is still a
|
|
161
|
+
real 0.05 mm between drawing and model — on a part carrying 0.05 mm clearances, the whole
|
|
162
|
+
clearance. One `info` per sheet, naming the worst case:
|
|
163
|
+
|
|
164
|
+
> 7 dimension(s) print a nominal the model does not have, rounded to the sheet's
|
|
165
|
+
> precision; the largest is '15.7' for 15.6500 (0.0500 mm). Within a general tolerance
|
|
166
|
+
> this is ordinary; where a fit depends on it, raise that dimension's places with
|
|
167
|
+
> `.format(decimals=...)`
|
|
168
|
+
|
|
169
|
+
`.format(decimals=…)` cannot yet reach a **location** dimension (#1610), and on the
|
|
170
|
+
fixture this was measured against six of the seven offenders are locations — so the
|
|
171
|
+
message says so rather than prescribing a remedy that raises `ValueError`.
|
|
172
|
+
|
|
173
|
+
It does **not** guess, and does not change any rounding. `4.450` locating a hinge axis is
|
|
174
|
+
design intent; `71.595` as an overall envelope is parametric fallout no drafter would
|
|
175
|
+
print in full — and telling them apart needs to know what the part is *for*, which a STEP
|
|
176
|
+
file does not carry (the same gap as #1597). So the engine reports and the author decides:
|
|
177
|
+
`.format(decimals=…)` already sets places per dimension and survives the `--script` round
|
|
178
|
+
trip.
|
|
179
|
+
|
|
180
|
+
Measured: 7 of 25 numeric dimension labels on `whistle_frame_reference.step`; silent on
|
|
181
|
+
every golden fixture, all of which are built from round numbers.
|
|
182
|
+
|
|
183
|
+
### Fixed
|
|
184
|
+
- Adopt published Quiddity 0.2.9 (#1619). The frame document now retains six separate
|
|
185
|
+
hinge bores instead of a single path spanning air gaps. Three cylindrical seat occurrences
|
|
186
|
+
are reported explicitly; their drawing grammar remains pending #1613.
|
|
187
|
+
- Refused hole patterns retain their members in the hole-completeness ledger (#1607).
|
|
188
|
+
The adapter records the refusal against the exact recognition run, so a six-hole group
|
|
189
|
+
is no longer reported as an unverifiable four-hole pattern and two loose holes. Declared
|
|
190
|
+
pattern mismatches still undergo the independent correspondence checks.
|
|
191
|
+
|
|
192
|
+
- **A required dimension with nowhere to go now re-plans the sheet instead of being
|
|
193
|
+
reported and left (#1590).** The automatic recovery ladder — larger scales on the
|
|
194
|
+
selected page, then dropping the optional pictorial, then a larger page — already
|
|
195
|
+
existed and already refused any candidate that had not fixed the problem. It ran on
|
|
196
|
+
two symptoms: a turned part missing an axial station, and an **authored** intent that
|
|
197
|
+
failed to place. A required *envelope* dimension that found no room was neither, so
|
|
198
|
+
these drawings never entered the ladder at all — `scale_decision["attempts"]` came
|
|
199
|
+
back empty and an `overall_dim_withheld` error was reported on the first sheet tried.
|
|
200
|
+
|
|
201
|
+
`overall_dim_withheld` is deliberately not a scale blocker, and that is right:
|
|
202
|
+
reporting it through `placement_unsatisfiable` once made `build_drawing(part,
|
|
203
|
+
scale=...)` raise on parts that had always built. But that argument is about refusing
|
|
204
|
+
the scale a **caller asked for**. Choosing one automatically is a different question,
|
|
205
|
+
and one predicate was answering both.
|
|
206
|
+
|
|
207
|
+
What it changes, measured:
|
|
208
|
+
|
|
209
|
+
| part | before | after |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| stepped `Box(80, 60, 30)` | A4 1:1, overall depth withheld (error) | A4 1:1, **clean**, pictorial dropped |
|
|
212
|
+
| 80 × 60 plate, two close bores | A4 1:1, `incomplete`: unlocated hole, dropped location, withheld depth | A2 2:1, **clean**, every dimension placed |
|
|
213
|
+
|
|
214
|
+
**ADR 2 invariant 13 is amended** to match. It read "the optional isometric yields only
|
|
215
|
+
to close missing axial coverage", which had been one trigger behind the code since
|
|
216
|
+
2026-08-23 — the record was consolidated twelve days later and transcribed the narrower
|
|
217
|
+
claim. It now states the principle the triggers share: the isometric yields only to
|
|
218
|
+
preserve manufacturing completeness, never for space, crowding or preference. The list
|
|
219
|
+
itself is `builder._ISO_YIELD_TRIGGERS`, and a guard fails if it changes, so the next
|
|
220
|
+
widening is caught by a test rather than by a reader.
|
|
221
|
+
|
|
222
|
+
Dropping the optional pictorial is the first lever, which is the order #443/#1299
|
|
223
|
+
already argue for — a pictorial cannot outrank a dimension needed to manufacture the
|
|
224
|
+
part. Pin `page=` or `scale=` to opt out; a pinned sheet still reports honestly rather
|
|
225
|
+
than replanning.
|
|
226
|
+
|
|
227
|
+
- **A generated `--script` reproduces a re-planned layout.** A declared build does what
|
|
228
|
+
it is told and never enters the recovery ladder, so `generate_sheet_script` pins the
|
|
229
|
+
settled page, scale and view set into the script. It used to do that only for the two
|
|
230
|
+
families whose replan could be predicted from the model; nothing predicts the new
|
|
231
|
+
trigger, because whether a mark fits is a fact about a measured sheet. The reference
|
|
232
|
+
build is now unconditional — one extra `build_drawing` per generated script, measured
|
|
233
|
+
at 0.19 s for a plain box, 0.34 s for a pocket and 1.17 s for a part that actually
|
|
234
|
+
replans — and an **undrawable** source can never be the reason a script is not
|
|
235
|
+
written, the standard the inspection sidecar beside it already meets. A deliberate
|
|
236
|
+
refusal (an unknown page size, `ScaleIncompatibilityError`, `ViewPlanIncomplete`)
|
|
237
|
+
still reaches the caller.
|
|
238
|
+
|
|
239
|
+
A script that keeps `auto_dimensions()` is not handed a pinned view set: `Sheet`
|
|
240
|
+
refuses `authored_views()` beside it, so the two together wrote a script that raised
|
|
241
|
+
when run. The settled set is reported in a comment instead.
|
|
242
|
+
|
|
243
|
+
- **A bolt circle is no longer stated unless something other than the fit supports it
|
|
244
|
+
(#1596).** `EQ SP ON ø… BC` tells a machinist to work from a centre; #1595 found a real
|
|
245
|
+
part where that centre was in mid-air. Six ⌀2.4 holes in a 2×3 rectangular grid came out
|
|
246
|
+
as `4× ⌀2.4 THRU EQ SP ON ø34.4 BC` plus an unrelated `2× ⌀2.4 THRU`, the circle centred
|
|
247
|
+
on (0, −20.11) — nothing is concentric with it.
|
|
248
|
+
|
|
249
|
+
The fit was not a near miss. **Any three non-collinear points are concyclic, and so are the
|
|
250
|
+
four corners of any rectangle** — for those arrangements the residual is zero by
|
|
251
|
+
construction, so no tolerance on it can help. Nor does equal spacing rescue it: that
|
|
252
|
+
rectangle is near-square (24.30 × 24.38), so its corners sit 90.19° / 89.81° apart and
|
|
253
|
+
would pass an `EQ SP` check too.
|
|
254
|
+
|
|
255
|
+
What gives it away is the leftover callout beside it. Corroboration must now come from
|
|
256
|
+
somewhere the fit cannot reach — any one of:
|
|
257
|
+
|
|
258
|
+
1. **five or more members** — a circle through five holes could have failed to fit;
|
|
259
|
+
2. **a concentric physical feature** — a boss, spigot, central bore, or a round body whose
|
|
260
|
+
own axis is the circle's, something a machinist can indicate off;
|
|
261
|
+
3. **it accounts for every hole of its kind** — no identical hole left off the circle.
|
|
262
|
+
|
|
263
|
+
(3) is the discriminator here: six identical holes and the circle claimed four. A drawing
|
|
264
|
+
does not put two of six bolts on a different plan. It is also a question about the part
|
|
265
|
+
rather than about its angle to the axes, unlike the row/column test it replaced.
|
|
266
|
+
|
|
267
|
+
Refused patterns keep every hole: the members fall through to ordinary grouping, so the
|
|
268
|
+
#1595 part now reads `6× ⌀2.4 THRU` — which also repairs the fragmentation into 4 + 2.
|
|
269
|
+
|
|
270
|
+
**What refusing costs, measured.** `hole_requirement_outcomes` builds its pattern-member
|
|
271
|
+
set from the recogniser's patterns rather than the ones the IR adopted, so after a refusal
|
|
272
|
+
it keeps those holes out of the loose groups, finds no `PatternFeature` to join, and warns
|
|
273
|
+
`hole_requirement_unverifiable` about holes the sheet states correctly — two on this part,
|
|
274
|
+
26 issues against 23. The pre-existing oblique-pattern refusal (#971) has the same hole and
|
|
275
|
+
was simply never reachable; #1596 makes it so. Tracked as **#1607** with three attempted
|
|
276
|
+
fixes recorded, and guarded by an `xfail(strict)` here.
|
|
277
|
+
|
|
278
|
+
Refused at the recognition→IR adapter, not in the recogniser: a circle through those holes
|
|
279
|
+
is genuinely findable, and ADR 3 leaves the recogniser to report the geometry it finds.
|
|
280
|
+
Whether it may be *stated as a drafting datum* is drafting policy, which is draftwright's.
|
|
281
|
+
|
|
282
|
+
### Changed
|
|
283
|
+
|
|
284
|
+
- **The title block carries every ISO 7200:2004 mandatory data field.** Three had
|
|
285
|
+
no representation at all before — segment/sheet number (5.1.6), approval person
|
|
286
|
+
(5.3.4) and document type (5.3.6) — and are now `sheet=`, `approved_by=` and
|
|
287
|
+
`document_type=` on `build_drawing`, `make_drawing`, `Sheet`, the CLI and the
|
|
288
|
+
`--script` emitter. Cell widths come from the standard's own recommended
|
|
289
|
+
character counts (via `build123d-drafting-helpers>=0.15.4`), so they follow ISO
|
|
290
|
+
7200 and the font rather than a chosen proportion.
|
|
291
|
+
|
|
292
|
+
Eleven fields need four rows, so **the block is 32 mm tall rather than 16**, and
|
|
293
|
+
the band reserved for it goes 35 → 40 mm. `material` and `general_tolerance`
|
|
294
|
+
stay although neither is an ISO 7200 title-block field; they are on every real
|
|
295
|
+
drawing.
|
|
296
|
+
|
|
297
|
+
- **The scale is stated outside the title block**, beside the projection symbol,
|
|
298
|
+
per ISO 7200 §4 ("presented outside the title block only when used, e.g. scale,
|
|
299
|
+
projection symbol"). It is drawn unconditionally, and the new **`scale_not_stated`
|
|
300
|
+
error** checks the rendered sheet rather than trusting the code that draws it.
|
|
301
|
+
The `SCALE` cell is gone from the block.
|
|
302
|
+
|
|
303
|
+
**Two consequences worth knowing before you upgrade:**
|
|
304
|
+
|
|
305
|
+
- A dense sheet may escalate a page size. In the golden corpus one fixture of
|
|
306
|
+
fourteen (`flange_dense`) moves A4 → A3; the other thirteen keep their page
|
|
307
|
+
and scale, and a sweep of ten ordinary shapes showed no change at all.
|
|
308
|
+
- **Dimension placement now avoids the title block (#1593)**, which it never
|
|
309
|
+
did: the block is drawn after placement, so only GD&T frames ever avoided it
|
|
310
|
+
(#481). A two-row block kept that out of reach; a four-row one does not.
|
|
311
|
+
`build_drawing(Box(40, 30, 12))` used to run its `30` dimension 2.1 mm into
|
|
312
|
+
the block with `lint()` reporting a clean sheet; a stepped
|
|
313
|
+
`Box(80, 60, 30)` put the whole `60` label inside it, reported only as an
|
|
314
|
+
`annotation_overlap` between the labels `60` and `DRAWING`.
|
|
315
|
+
|
|
316
|
+
Most displaced dimensions move to the view's opposite strip and stay on the
|
|
317
|
+
sheet. Where both strips are full the dimension is **withheld as an error
|
|
318
|
+
naming the block**, rather than drawn through it: in the golden corpus
|
|
319
|
+
`pocketed` and `prismatic_ladder` lose their overall depth at the automatic
|
|
320
|
+
A4/1:1, and place it on A3 or at 1:2. Likewise a **pinned** A4 for a
|
|
321
|
+
five-step turned shaft no longer reaches 5:1, because at that scale the front
|
|
322
|
+
view runs down past the block and the overall height cannot be placed; the
|
|
323
|
+
2:1 sheet is returned with `axial_length_missing` stated. Leaving the page
|
|
324
|
+
automatic still carries every station, on A3 at 5:1.
|
|
325
|
+
|
|
326
|
+
Choosing a page and scale without knowing which dimensions will still need
|
|
327
|
+
room is #1590.
|
|
328
|
+
|
|
329
|
+
### Changed
|
|
330
|
+
|
|
331
|
+
- **Exports are reproducible by default.** `reproducible` now defaults to `True`
|
|
332
|
+
on `build_drawing`, `make_drawing`, `Drawing` and `Drawing.export`, so two
|
|
333
|
+
exports of one drawing are byte-identical without asking. Pass
|
|
334
|
+
`reproducible=False` to opt out.
|
|
335
|
+
|
|
336
|
+
It was opt-in on a cost argument, and the cost turns out to be small at the
|
|
337
|
+
scale most drawings are made: on the NIST CTC-01 AP242 fixture, +0.27 s on a
|
|
338
|
+
13.4 s job (+3.2% of export, +2.0% overall). The +32% of export measured when
|
|
339
|
+
the flag was introduced was a 358-part assembly; the ordering work is one
|
|
340
|
+
bounding box and one edge walk per part, so it scales with part count and a
|
|
341
|
+
part-heavy sheet is still the case to opt out of.
|
|
342
|
+
|
|
343
|
+
Two things pushed the default over. A file that changes between runs cannot be
|
|
344
|
+
diffed, checksummed or cached — the reason to want it is not speed-shaped. And
|
|
345
|
+
neither the CLI nor `Sheet` exposes the flag at all, so every drawing made
|
|
346
|
+
through those surfaces was non-reproducible with no way to change it.
|
|
347
|
+
|
|
348
|
+
One behaviour follows from the default rather than from this change: a DXF
|
|
349
|
+
export that cannot reach the ezdxf document to pin its metadata now raises
|
|
350
|
+
rather than writing live data, because every export now claims
|
|
351
|
+
reproducibility. Opting out restores the old fallback.
|
|
352
|
+
### Fixed
|
|
353
|
+
|
|
354
|
+
- **A supplied title-block `date` is stated on the sheet** (#1585). `TitleBlock`
|
|
355
|
+
could show only one of `revision`/`date` in its top-right cell and revision
|
|
356
|
+
won, while draftwright defaults `revision` to `"A"` — so every drawing that
|
|
357
|
+
set a date lost it, silently, in every version that has had the parameter.
|
|
358
|
+
Adopting `build123d-drafting-helpers>=0.15.4` gives the date a cell of its
|
|
359
|
+
own whenever a revision is also set, and `_make_title_block` now names that
|
|
360
|
+
cell, so the date reaches the PDF text layer and the cell-overflow lint
|
|
361
|
+
rather than only the rendered geometry.
|
|
362
|
+
|
|
363
|
+
`date`, `revision` and `company` are stripped before use, matching what the
|
|
364
|
+
block itself does: a whitespace-only `company` previously raised `KeyError`
|
|
365
|
+
from `cell_bbox`, and padded values were measured at a width the sheet never
|
|
366
|
+
drew. (The DRAWN BY narrowing this entry originally described, and the shared
|
|
367
|
+
top-right cell it named, are both gone with the ISO 7200 layout above — the
|
|
368
|
+
date has its own cell in its own row, so it costs DRAWN BY nothing.)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
### Added
|
|
372
|
+
|
|
373
|
+
- Report schema v1 now projects one recognition-owned physical requirement ledger shared with
|
|
374
|
+
completeness. Each bounded requirement identifies its accepted source occurrence(s), final IR
|
|
375
|
+
owner(s), semantic parameter where applicable, placement/satisfaction state, annotation names,
|
|
376
|
+
and representation rationale. The roster is evaluated once per report and fails closed when
|
|
377
|
+
exact same-run evidence or provenance is absent; it does not create a second recognition scan,
|
|
378
|
+
persistent topology identity, inferred manufacturing intent, or visual change (#1438, ADR 0017
|
|
379
|
+
Amendment 26).
|
|
380
|
+
|
|
381
|
+
- Direct CLI rendering now writes `<output>.draftwright.json` by default, after successful visual
|
|
382
|
+
export, and prints its path with the requested artefacts. `--no-report` is the explicit opt-out;
|
|
383
|
+
library `Drawing.export()` remains free of report-writing side effects (#1438, ADR 0017
|
|
384
|
+
Amendment 25).
|
|
385
|
+
|
|
386
|
+
- Generated Sheet Python now embeds a deterministic, versioned, JSON-compatible snapshot of
|
|
387
|
+
actionable accepted-occurrence gaps from the exact recognition run that produced its model.
|
|
388
|
+
The compact snapshot carries only unsupported, deferred, evidence-only, and unexpectedly
|
|
389
|
+
missing public records; STEP inputs are read once and recognition uses a private copy of the
|
|
390
|
+
exact bytes named by the embedded basename and SHA-256, with a best-effort final replay-target
|
|
391
|
+
check before writing. The hash is a later reconciliation boundary, not a lock on the mutable
|
|
392
|
+
source path. It is explicitly generation-time evidence, never current completeness authority
|
|
393
|
+
(#1438, ADR 0017 Amendment 24).
|
|
394
|
+
|
|
395
|
+
- Accepted Plate occurrences now retain exact conditional ownership. Genuine multi-axis plates
|
|
396
|
+
keep their direct `PlateFeature`; other slabs are absorbed only when released same-run AAG
|
|
397
|
+
evidence joins them to the exact retained face-level, riser-shoulder, or slot-pattern owner.
|
|
398
|
+
Multi-owner claims are conjunctive, while whole-envelope, polygonal-boss, disconnected,
|
|
399
|
+
ambiguous, or malformed cases remain visibly `unexpectedly_missing` rather than borrowing an
|
|
400
|
+
owner from matching values or traversal order (#1438, ADR 0017 Amendment 23).
|
|
401
|
+
|
|
402
|
+
- `Drawing.write_report(path)` now atomically writes the versioned report as deterministic,
|
|
403
|
+
strict UTF-8 JSON without coupling library export to sidecar generation. Report and filesystem
|
|
404
|
+
failures leave any existing destination untouched, with best-effort temporary cleanup that does
|
|
405
|
+
not mask the primary error (#1438, ADR 0017 Amendment 22).
|
|
406
|
+
|
|
407
|
+
- Raw automatic drawings now expose `Drawing.report()`, a strict version-1 JSON-compatible
|
|
408
|
+
projection of every accepted recognition occurrence, its explicit consumer disposition and
|
|
409
|
+
report-local final IR owner(s), plus the existing lint summary. The published schema never
|
|
410
|
+
serializes provider references, topology IDs, object addresses, or transient member positions;
|
|
411
|
+
it makes requirement coverage an explicit field (subsequently populated by Amendment 26) and
|
|
412
|
+
calls a clean result `bounded-clear`, not manufacturing-ready. Paths without exact occurrence
|
|
413
|
+
ownership and raw paths with an unclassified accepted occurrence fail explicitly rather than
|
|
414
|
+
emit an empty or inferred report. Rendering remains unchanged (#1438, ADR 0017 Amendment 21).
|
|
415
|
+
|
|
416
|
+
- Accepted `FaceLevel` and `RiserEvidence` occurrences now receive explicit `evidence_only`
|
|
417
|
+
outcomes. The released records remain shared substrate for the supported correlated height
|
|
418
|
+
ladder and shoulder projection, not independent inferred features or drawing requirements; no
|
|
419
|
+
IR, Sheet DSL, renderer, or recogniser API change is introduced (#1438, ADR 0017 Amendment 20).
|
|
420
|
+
|
|
421
|
+
- Accepted round-boss occurrences now retain the exact existing consumer outcome: a singleton
|
|
422
|
+
`BossFeature`, one diameter-consolidated representative with transient member lineage, the exact
|
|
423
|
+
turned-step owner, or the exact groove owner reached through that step or the profile-gate
|
|
424
|
+
fallback. Ambiguous or missing correspondence fails closed without another scan, persistent ID,
|
|
425
|
+
generated artefact, or visual change (#1438, ADR 0017 Amendment 19).
|
|
426
|
+
|
|
427
|
+
- Accepted through-step occurrences now retain either their exact `ThroughStepFeature` or every
|
|
428
|
+
exact final `StepLevelFeature`, `PlateFeature`, and `EnvelopeFeature` that jointly carries the
|
|
429
|
+
established compatibility projection. Plate claims are body-local, replacement is atomic, and a
|
|
430
|
+
missing or ambiguous selected owner fails closed rather than granting partial credit. One
|
|
431
|
+
occurrence can name multiple run-local IR owners without a second scan, persistent ID, generated
|
|
432
|
+
artefact, or change to rendering machinery (#1438, ADR 0017 Amendment 18).
|
|
433
|
+
|
|
434
|
+
- Accepted turned-step occurrences now retain the conversion decision that already gives an
|
|
435
|
+
ordinary profile band its exact `StepFeature` or absorbs a groove-floor band into the exact
|
|
436
|
+
same-run `GrooveFeature`. The takeover must be one-to-one in both directions, so an ambiguous
|
|
437
|
+
groove, an adjacent band inside its positional tolerance, or any missing final owner fails closed
|
|
438
|
+
as `unexpectedly_missing`, with no second scan, persistent ID, generated artefact, or visual
|
|
439
|
+
change (#1438, ADR 0017 Amendment 17).
|
|
440
|
+
|
|
441
|
+
- Accepted channel occurrences now receive an exact conditional consumer outcome. A genuine
|
|
442
|
+
multi-axis plate channel is `represented` by its `ChannelFeature`; a monolithic Z-depth rebate is
|
|
443
|
+
`absorbed` only when one retained body-local support carries its floor and both shoulders into the
|
|
444
|
+
final step ladder. Cross-axis, disconnected, or filtered channels fail closed as
|
|
445
|
+
`unexpectedly_missing` instead of inheriting an unrelated ladder, without a second scan,
|
|
446
|
+
persistent ID, generated artefact, or visual change (#1438, ADR 0017 Amendment 16).
|
|
447
|
+
|
|
448
|
+
- Accepted countersink occurrences now receive an exact run-local outcome. A seat carried by a
|
|
449
|
+
`HoleRecord` is `absorbed` by that hole's final feature and transient member lineage; an unattached,
|
|
450
|
+
unowned, or duplicate nested occurrence fails closed without dimension matching, topology IDs, a
|
|
451
|
+
second scan, duplicate IR requirements, or visual changes (#1438, ADR 0017 Amendment 15).
|
|
452
|
+
|
|
453
|
+
- Accepted angled-step, passage, prismatic-pocket, oriented-slot, and repeating-radial-profile
|
|
454
|
+
occurrences now receive exact run-local ownerless outcomes from Draftwright's existing consumer
|
|
455
|
+
capability declaration: `unsupported`, `deferred`, or report-facing `evidence_only`, with closed
|
|
456
|
+
reason codes and existing tracking issues. Equal-valued occurrences stay distinct; policy does
|
|
457
|
+
not invent IR owners, requirements, topology IDs, recognition scans, generated artefacts, or
|
|
458
|
+
visual output (#1438, ADR 0017 Amendment 14).
|
|
459
|
+
|
|
460
|
+
- Accepted physical hole, slot, and pocket occurrences now retain explicit run-local ownership
|
|
461
|
+
when conversion represents a singleton or absorbs members into one same-spec hole group or
|
|
462
|
+
derived pattern feature. Family-specific reason codes and transient member lineage follow
|
|
463
|
+
member-specific AP242 splits to the exact final IR objects; missing lineage fails closed rather
|
|
464
|
+
than retaining a stale owner. Provider-derived patterns do not become invented occurrences, and
|
|
465
|
+
no report ID, extra recognition scan, generated artefact, or visual output is introduced (#1438,
|
|
466
|
+
ADR 0017 Amendment 13).
|
|
467
|
+
|
|
468
|
+
- Raw automatic builds now capture run-local, conversion-time ownership from accepted provider
|
|
469
|
+
occurrences to their exact Draftwright IR features for unconditional one-to-one adapters. Equal
|
|
470
|
+
record values, order, coordinates and topology indices cannot create a binding; an omitted direct
|
|
471
|
+
binding fails closed as unexpectedly missing, while ownership rules not yet implemented remain
|
|
472
|
+
explicitly unclassified. The experimental read-only `Drawing.recognition_ownership()` exposes
|
|
473
|
+
the non-serializable ledger; it stays outside the IR/compiler and changes no generated or visual
|
|
474
|
+
artefact (#1438, ADR 0017 Amendment 12).
|
|
475
|
+
|
|
476
|
+
- Raw automatic recognition now retains the provider's run-scoped `RecognitionEvidence` beside
|
|
477
|
+
its exact `RecognitionResult`, exposed through the experimental read-only
|
|
478
|
+
`Drawing.recognition_evidence()`. Declared drawings acquire the pair lazily on first physical
|
|
479
|
+
critique; bare and framed results remain evidence-less, and Draftwright never rescans merely to
|
|
480
|
+
backfill evidence. This is a non-visual reporting foundation and changes no rendered artefact
|
|
481
|
+
(#1438, ADRs 0015, 0017, 0020).
|
|
482
|
+
|
|
483
|
+
- Automatic drawings can opt into the provider-owned local recognition frame with
|
|
484
|
+
`framed_recognition=True`. The returned drawing exposes caller provenance, the exact downstream
|
|
485
|
+
working solid, frame, and a copied framed/raw/refusal decision. PMI correlation, off-axis pattern
|
|
486
|
+
placement, compilation, projection and physical lint remain in one coordinate system; typed frame
|
|
487
|
+
refusal performs one visible top-level raw fallback. Raw remains the rollout default (#1357,
|
|
488
|
+
ADR 0020).
|
|
489
|
+
|
|
490
|
+
- Referential and measured Sheet dimensions accept optional `view=` / `side=` placement
|
|
491
|
+
intent. Supported pairs survive IR/compiler and generated-script round trips, constrain
|
|
492
|
+
ordinary corridor candidates without exposing page coordinates, and fail clearly when a
|
|
493
|
+
renderer cannot honour the requested view/strip. Compound hole callouts can therefore be
|
|
494
|
+
authored to opposite sides of one end view while retaining normal solve and lint behavior
|
|
495
|
+
(#563).
|
|
496
|
+
- Feature-linked Sheet notes can explicitly satisfy one or more canonical requirement ids with
|
|
497
|
+
`.note(..., satisfies=(...))`. Placed structured notes retain each requirement's identity in
|
|
498
|
+
coverage reports and generated scripts without masquerading as dimensions or parsing prose;
|
|
499
|
+
removing the note restores the ordinary missing/suppressed diagnostics (#1351).
|
|
500
|
+
- `Sheet.from_part(...).take_over(...)` now adopts detected features in place while choosing
|
|
501
|
+
authored or automatic dimension, principal-view, and derived-view sources explicitly. This
|
|
502
|
+
preserves detected handles, supports automatic principal views with authored requirements,
|
|
503
|
+
replaces or suppresses inferred sections without duplicates, and round-trips the adopted view
|
|
504
|
+
request through generated Sheet code (#1350).
|
|
505
|
+
- Referential Sheet dimensions can preserve an explicit number of decimal places with
|
|
506
|
+
`sheet.dimension(feature, "parameter.id").format(decimals=n)`. The policy changes only
|
|
507
|
+
printed display text: numeric reconciliation, tolerances, suppression and dimension
|
|
508
|
+
provenance continue to use the feature parameter, and generated Sheet scripts round-trip the
|
|
509
|
+
policy (#1349).
|
|
510
|
+
- New lint code `annotation_ink_overlap`: reports another annotation's line-work —
|
|
511
|
+
a dimension line, an extension line or a leader shaft — drawn through a label's
|
|
512
|
+
text, which `annotation_overlap` cannot see because it compares label boxes to
|
|
513
|
+
each other and to nothing else. Measured as the longest connected stroke path
|
|
514
|
+
crossing the label's exact polygon (or its axis-aligned box), in millimetres,
|
|
515
|
+
with a 0.5 mm floor. It scores on legibility, so
|
|
516
|
+
dense sheets that previously scored clean now score lower — 17 findings on
|
|
517
|
+
NIST CTC-02 AP203 alone, every sampled one confirmed a real defect by rendering.
|
|
518
|
+
Repair does not yet act on it (#1333) and the corridor solve does not yet avoid
|
|
519
|
+
it (#1334) (#1321, #1332).
|
|
520
|
+
|
|
521
|
+
### Changed
|
|
522
|
+
|
|
523
|
+
- Updated the exact Quiddity runtime and declared-inspection contract to **0.2.8**, which stops
|
|
524
|
+
a modelled thread being read as a stack of turned shoulders and coalesces contiguous
|
|
525
|
+
equal-diameter bands into the one span they physically are. Measured on the repo corpus,
|
|
526
|
+
NIST CTC-05 is again the only fixture that moves: its ⌀304.8 region was three adjacent
|
|
527
|
+
rungs and is now one, in both STEP encodings (#1135, quiddity#587).
|
|
528
|
+
|
|
529
|
+
- Updated the exact Quiddity runtime and declared-inspection contract to **0.2.7**. Unlike the
|
|
530
|
+
0.2.5 adoption below, this one changes drawings: the provider now requires circumferential
|
|
531
|
+
cylinder support to establish a turned-profile axis line, so rounded plate corners and parallel
|
|
532
|
+
offset cylinders no longer form a false stepped shaft. Measured on the repo corpus, NIST CTC-05
|
|
533
|
+
is the only fixture whose recognised turned profile moves — its two STEP encodings previously
|
|
534
|
+
disagreed (3 steps and 9 steps for the same solid) and now agree on 5 — and a plate part that
|
|
535
|
+
previously raised out of `generate_sheet_script` now emits and builds. No family, record schema
|
|
536
|
+
or adapter changed (#1555, quiddity#586).
|
|
537
|
+
|
|
538
|
+
- Updated the exact Quiddity runtime and declared-inspection contract to 0.2.5 for the
|
|
539
|
+
provider's recognition performance improvements.
|
|
540
|
+
|
|
541
|
+
- Production recognition now consumes published `quiddity==0.2.2`. Unified section-recess
|
|
542
|
+
occurrences and their same-run patterns feed the existing pocket, channel and blind-slot
|
|
543
|
+
drawing grammar. Original occurrence ownership, independent completeness and explicit
|
|
544
|
+
unsupported/refusal outcomes follow that single aggregate (#1471).
|
|
545
|
+
- Machine-readable reports and STEP inspection documents advance to schema v2 because their
|
|
546
|
+
closed producer object now names `quiddity`. The schema-v1 documents remain available for
|
|
547
|
+
existing files; readers must select the schema using `schema_version` (#1471).
|
|
548
|
+
- Groove membership now retains Quiddity's body-local profile identity. Generated declarations
|
|
549
|
+
use `profile_group` to associate coaxial grooves and steps without copying provider keys.
|
|
550
|
+
Omitted steps do not cause a groove to attach to another body (#1471).
|
|
551
|
+
- Known limitations in Quiddity 0.2.2: some mixed-profile/nested pockets, bore-intersected channels
|
|
552
|
+
and edge-open recesses, and pockets in cylindrical stock can lose automatic annotations.
|
|
553
|
+
Refusals remain visible in lint and evidence. Regression cases are retained as strict expected
|
|
554
|
+
failures while upstream [#536](https://github.com/pzfreo/quiddity/issues/536),
|
|
555
|
+
[#538](https://github.com/pzfreo/quiddity/issues/538) and
|
|
556
|
+
[#541](https://github.com/pzfreo/quiddity/issues/541) are open.
|
|
557
|
+
|
|
558
|
+
- Accepted schema-v3 straight or circular `Blend` chains, including concave occurrences, now cross
|
|
559
|
+
a dedicated end-to-end consumer path:
|
|
560
|
+
`BlendFeature`, explicit `Sheet.blend(...)`, executable generated declarations, one
|
|
561
|
+
compiler-approved `blend.radius` requirement, and a solver-owned grouped `n× R` leader. The
|
|
562
|
+
discriminated path kind, full canonical direction/normal, circular-path major radius,
|
|
563
|
+
rolling-ball radius, and material side remain in IR instead of being coerced to legacy Fillet
|
|
564
|
+
semantics; the provider aggregate remains the sole exact Fillet/Blend precedence authority.
|
|
565
|
+
Exact public-record/IR validation and completeness follow every accepted occurrence to placed,
|
|
566
|
+
structured-note, authored-suppressed, dropped, missing, or unverifiable outcomes. Raw and
|
|
567
|
+
provider-framed arbitrary rigid motions retain straight-path radius meaning; framed recognition
|
|
568
|
+
also retains circular paths, while raw arbitrarily rotated circular recognition remains an
|
|
569
|
+
upstream limitation (b123d-recognisers#491) (#1433; ADRs 0011, 0013–0017, 0020).
|
|
570
|
+
|
|
571
|
+
- The preceding recognition update pinned the immutable `b123d-recognisers` 0.4.14 release and advanced its
|
|
572
|
+
fail-closed capability and inspection joins. `Blend` schema v3 replaces the old flat cylindrical
|
|
573
|
+
fields with exact `StraightBlendPath` and `CircularBlendPath` records and admits proved concave
|
|
574
|
+
and toroidal occurrences; Draftwright preserves those semantics through IR, `Sheet.blend(...)`,
|
|
575
|
+
generated replay, reporting, drawing, and completeness. Passage nested records advance to schema
|
|
576
|
+
v2 without changing Draftwright's unsupported passage policy. The provider's previously
|
|
577
|
+
recognised shallow nonzero `PairedRampStep` keeps its existing
|
|
578
|
+
two-requirement IR, public `Sheet.paired_ramp_step(...)` declaration, generated-code, compiler
|
|
579
|
+
callout, solver placement, and completeness meaning (#1430; ADRs 0011, 0013–0017, 0020).
|
|
580
|
+
|
|
581
|
+
- Rectangular blind slots recognised by `b123d-recognisers` 0.4.10 now cross a dedicated
|
|
582
|
+
Draftwright semantic path: `RectangularBlindSlotFeature`, the explicit
|
|
583
|
+
`Sheet.rectangular_blind_slot(...)` word, generated-code and role-specific tolerance round
|
|
584
|
+
trips, compiler-approved width/capped-run/depth measurements, and one solver-owned
|
|
585
|
+
`OPEN SLOT … DEEP` leader. Authored subsets retain every approved value with explicit
|
|
586
|
+
`WIDE`/`LONG`/`DEEP` roles, and leaders target proved cap/side material rather than the open
|
|
587
|
+
mouth. Native raw and rigidly moved framed builds retain the same three
|
|
588
|
+
measurement outcomes. A seven-case independently authored corpus now pins all six run/open-side
|
|
589
|
+
orientations plus an independently sized specimen: each occurrence contributes separate width,
|
|
590
|
+
capped-run and depth requirements followed by exact structural correspondence and measurement
|
|
591
|
+
provenance to placed, structured-note, suppressed, dropped, missing or unverifiable outcomes.
|
|
592
|
+
Removing recognition cannot shrink that 21-requirement benchmark (#1421; ADRs 0011,
|
|
593
|
+
0013–0017, 0020).
|
|
594
|
+
|
|
595
|
+
- Round-bottom blind slots recognised by `b123d-recognisers` 0.4.10 now have their own complete
|
|
596
|
+
Draftwright path rather than borrowing through-slot, pocket or rectangular-blind-slot grammar.
|
|
597
|
+
`RoundBottomBlindSlotFeature` retains the released run/opening topology and exposes the three
|
|
598
|
+
independent manufacturing requirements: capped run length, straight bottom-flat width and equal
|
|
599
|
+
side radius. `Sheet.round_bottom_blind_slot(...)`, generated code, role-specific tolerances and
|
|
600
|
+
one solver-owned `ROUND-BOTTOM OPEN SLOT …` leader all preserve those exact identities; derived
|
|
601
|
+
total width and depth are not double-counted. A seven-case independently authored corpus covers
|
|
602
|
+
all six signed principal orientations plus a separately sized specimen (21 physical requirements),
|
|
603
|
+
proves raw/framed drawing parity, and follows exact source-to-IR correspondence to placed,
|
|
604
|
+
structured-note, suppressed, dropped, missing or unverifiable outcomes without labels, views or
|
|
605
|
+
page coordinates. The released 0.4.10 API is sufficient; no recogniser change is required (#1421;
|
|
606
|
+
ADRs 0011, 0013–0017, 0020).
|
|
607
|
+
|
|
608
|
+
- Turned-step completeness is now backed by an independently authored, hash-pinned 11-case STEP
|
|
609
|
+
corpus with 26 physical outside-diameter bands, 52 parameter checks and 104 downstream checks.
|
|
610
|
+
Axis line and station preserve body-local occurrence identity across automatic IR, the existing
|
|
611
|
+
public `Sheet.step(...)` DSL word, executed-and-built generated code, and exact compiler-confirmed
|
|
612
|
+
length and OD drawing evidence. Grouped equal-length chains retain every adjacent member identity
|
|
613
|
+
and their exact compiler-approved multiplier and value; native and global OD labels are checked
|
|
614
|
+
in full. Generated declarations preserve the half-thousandth midpoint of odd-thousandth spans,
|
|
615
|
+
complete body-local profile ownership is compared at its full published precision, and malformed
|
|
616
|
+
or surplus records fail closed—including coercible or non-finite groove evidence that controls
|
|
617
|
+
band ownership. The root turned-step and groove inventories must remain immutable tuples; a
|
|
618
|
+
mutable or one-shot substitute is snapshotted once only to preserve its observable requirement
|
|
619
|
+
denominator, then remains unverifiable; a non-iterable substitute retains one explicit aggregate
|
|
620
|
+
contract outcome rather than masquerading as an empty family. A profile OD may
|
|
621
|
+
satisfy one uniquely identifiable equivalent largest-band diameter
|
|
622
|
+
without multiplying across disjoint bodies; and uniquely groove-owned narrow
|
|
623
|
+
bands are excluded once by a shared fail-closed Groove schema and ownership rule used by lowering,
|
|
624
|
+
lint and the evidence ledger. That join accounts for the provider's 0.001 mm Groove coordinate
|
|
625
|
+
quantum against its eight-decimal profile axis without widening either published identity
|
|
626
|
+
(#1374; ADRs 0010, 0011, 0013, 0015, 0017, 0020).
|
|
627
|
+
|
|
628
|
+
- Framed recognition now carries all three 0.4.6 step families through their complete existing
|
|
629
|
+
consumer paths. `CircularBlindStep`, `PairedRampStep` and `ThroughStep` retain the same
|
|
630
|
+
manufacturing requirements from raw recognition through their public `Sheet` words, generated
|
|
631
|
+
code, compiler-owned drawing ink and lint; the provider-owned local records and Draftwright IR
|
|
632
|
+
remain invariant under a combined non-principal rotation and translation. Circular-step
|
|
633
|
+
validation now derives its bound from each independently published endpoint, centre, radius and
|
|
634
|
+
depth value's six-significant-figure decimal cell, while outside-cell geometric inconsistencies
|
|
635
|
+
still fail closed (#1382; ADRs 0011, 0013, 0015, 0017, 0018, 0020).
|
|
636
|
+
|
|
637
|
+
- Countersink completeness is now backed by an independently authored, hash-pinned seven-case STEP
|
|
638
|
+
corpus covering functional seats, solid external-cone and deburr negatives, grouped equal seats,
|
|
639
|
+
and reverse-serialized topology. Detection identity and all four provider measurements are scored
|
|
640
|
+
separately from the two actual drawing requirements. Exact aggregate object ownership follows
|
|
641
|
+
each seat once, validates the provider-selected hole semantically, and fails closed on swapped,
|
|
642
|
+
duplicated, or canonically colliding owners. It then crosses automatic IR, public `Sheet.hole`,
|
|
643
|
+
generated code, and role-specific confirmed placed diameter/angle ink without recounting the parent bore. The known second seat of a two-sided bore
|
|
644
|
+
remains explicitly unverifiable rather than hidden or heuristically attached (#1370; ADRs 0010,
|
|
645
|
+
0013, 0015, 0017).
|
|
646
|
+
|
|
647
|
+
- Double-D completeness is now backed by an independently authored, hash-pinned 11-case STEP
|
|
648
|
+
corpus with ten physical profile facts, 50 provider-parameter checks and 40 downstream checks.
|
|
649
|
+
Full-frame identity preserves disconnected coaxial bodies; exact multiplicity crosses automatic
|
|
650
|
+
IR, public `Sheet.double_d_bore`, generated code and role-specific compiler-confirmed
|
|
651
|
+
`⌀major THRU DOUBLE-D across A/F` ink. Round, blind, opposed-blind, malformed, duplicated and
|
|
652
|
+
foreign-owner mutations fail closed, while the provider's exclusive aggregate ownership keeps
|
|
653
|
+
each profile from being recounted as an ordinary hole (#1370; ADRs 0010, 0011, 0013, 0015,
|
|
654
|
+
0017).
|
|
655
|
+
- Updated the immutable `b123d-recognisers` pin and fail-closed inspection/capability joins to
|
|
656
|
+
0.4.10. All 28 previously consumed family schemas remain unchanged. The two new blind-slot
|
|
657
|
+
families were adopted fail-closed under #1421 and remain visible as unscored recognised
|
|
658
|
+
inventories until each gains independent completeness evidence; Draftwright does not coerce
|
|
659
|
+
their depth, terminal/open-end, or round-floor evidence into its ordinary through-slot grammar.
|
|
660
|
+
The provider's additive evidence API is not consumed by
|
|
661
|
+
this bounded adoption slice. Recognition output does change under the unchanged schemas: the
|
|
662
|
+
release closes slot-depth, subdivided paired-ramp/AngledStep, and noisy stubby-pocket gaps; fixes
|
|
663
|
+
Double-D/Hole ownership, external-cone countersink false positives, Plate tie covariance, and
|
|
664
|
+
turned-step translation covariance; and can move an edge-open rectangular recess from `Pocket`
|
|
665
|
+
to the dedicated blind-slot inventory. Draftwright regression tests pin the consumer-visible
|
|
666
|
+
ownership changes while the provider release suite owns its private predicates
|
|
667
|
+
([provider release](https://github.com/pzfreo/b123d-recognisers/releases/tag/v0.4.10); ADRs 0013,
|
|
668
|
+
0015, 0017, 0020).
|
|
669
|
+
|
|
670
|
+
- Principal-profile lint now correlates its independent extremal-face evidence with the cached
|
|
671
|
+
public `DoubleDBore` aggregate instead of importing provider-private profile helpers. Exact
|
|
672
|
+
axis/span, end-plane, centre, radius, A/F, chord, arc, and flat-direction checks fail closed;
|
|
673
|
+
occurrence mouths are consumed with matching multiplicity, and malformed records cannot earn
|
|
674
|
+
coverage. The exported low-level check now requires the aggregate projection explicitly so an
|
|
675
|
+
omitted inventory fails loudly; lint still owns its physical denominator and never reruns
|
|
676
|
+
recognition (#1411, ADRs 0013, 0015, 0017).
|
|
677
|
+
|
|
678
|
+
- Whole polygonal-stock completeness is now backed by an independently authored, hash-pinned
|
|
679
|
+
13-case STEP corpus covering all principal axes, in-plane rotation, translation, topology
|
|
680
|
+
order and circular/rectangular/irregular/octagonal/attached/recessed/compound negatives. The
|
|
681
|
+
provider's exact six-side stock boundary, A/F, axial length and coupled physical flat supports
|
|
682
|
+
are scored separately from four downstream boundaries. A fail-closed two-requirement ledger
|
|
683
|
+
follows A/F and stock length through automatic IR, public `Sheet.polygonal_stock`, generated
|
|
684
|
+
code and solver-placed semantic ink; malformed or duplicate correspondence cannot borrow
|
|
685
|
+
credit from another support ring (#1371).
|
|
686
|
+
|
|
687
|
+
- Multi-plate slab completeness is now backed by an independently authored, hash-pinned 11-case
|
|
688
|
+
STEP corpus covering all principal orientations, additive/cut channels, equal compound
|
|
689
|
+
occurrences, topology order and envelope/detached/thick/rotational negatives. A fail-closed
|
|
690
|
+
one-requirement ledger follows each body-local `thickness.length` through automatic IR, public
|
|
691
|
+
`Sheet.plate`, generated code and solver-placed Dimension provenance; the compiler-derived
|
|
692
|
+
opposite U-channel wall is represented explicitly without inventing duplicate ink. The corpus
|
|
693
|
+
owns 20 physical occurrences and cannot shrink when provider output is weakened or removed.
|
|
694
|
+
Exact step-level, slot-pattern, polygonal-boss and envelope ownership prevents derived material
|
|
695
|
+
spans from becoming duplicate Plate requirements while failing closed when that ownership cannot
|
|
696
|
+
be established (#1373).
|
|
697
|
+
|
|
698
|
+
- Polygonal-boss completeness is now backed by an independently authored, hash-pinned STEP
|
|
699
|
+
corpus covering all three principal axes, in-plane rotation, equal compound occurrences,
|
|
700
|
+
topology order, and recess/detached/stock/other-protrusion negatives. Detection, the provider's
|
|
701
|
+
six-side schema invariant, across-flats, height, physical flat supports, and four downstream
|
|
702
|
+
boundaries are observed; a
|
|
703
|
+
two-requirement fail-closed ledger follows across-flats and boss height through the existing
|
|
704
|
+
IR/compiler/shared-solve path. The corpus owns the independent evaluation denominator; runtime
|
|
705
|
+
drawing lint remains explicitly denominated by the recognition inventory (#1372).
|
|
706
|
+
|
|
707
|
+
- Updated the immutable `b123d-recognisers` pin and fail-closed manifest joins to 0.4.9. The
|
|
708
|
+
provider's body-local FaceLevel, RiserEvidence, and TurnedProfile schemas now cross an owned
|
|
709
|
+
prepared-frame boundary that normalizes, reuses one cylinder substrate, classifies locally,
|
|
710
|
+
and preserves the exact working solid/result pair. Every frame gauge and typed refusal has an
|
|
711
|
+
explicit conservative policy; refusal never hides a raw retry. Multiple physical turned
|
|
712
|
+
profiles fail explicitly where a singular adapter is required, while the unchanged raw
|
|
713
|
+
production route preserves its historical no-global-profile compound behavior with a visible
|
|
714
|
+
#1357 deferral. Production drawing remains on the explicit raw boundary until rigid-motion,
|
|
715
|
+
PMI, platform, and canary activation evidence is complete (ADR 0020, #1357).
|
|
716
|
+
|
|
717
|
+
- Updated the immutable `b123d-recognisers` pin and lock to 0.4.8. Draftwright now names
|
|
718
|
+
its existing caller/world-coordinate aggregate boundary explicitly with
|
|
719
|
+
`build_raw_recognition_result`; framed recognition remains disabled until #1357's
|
|
720
|
+
frame-to-IR adapter is reviewed end to end. Installed-wheel tests exercise the public
|
|
721
|
+
framed fixes for rectangular pads, polygonal bosses, and nested multi-body plates without
|
|
722
|
+
making that API the production path (#1392).
|
|
723
|
+
|
|
724
|
+
- Rectangular pads now consume `RaisedPad` schema v2 without assuming +Z. The IR, public
|
|
725
|
+
`Sheet.pad`, generated code, compiler, semantic-view planner, shared placement solve, and
|
|
726
|
+
lint correspondence preserve the exact footprint, terminal-to-attachment height, two
|
|
727
|
+
in-plane locations, axis, direction, and world bounds for all six signed principal
|
|
728
|
+
orientations. Every height uses one solver-placed `… HIGH` leader with stable measurement
|
|
729
|
+
identity; side-normal pad footprints no longer leak into the unrelated Z-level grammar
|
|
730
|
+
(#1392).
|
|
731
|
+
|
|
732
|
+
- Rectangular-pad completeness is now independently evidenced by a hash-pinned 12-case STEP
|
|
733
|
+
corpus covering all six signed principal orientations, equal compound occurrences, topology
|
|
734
|
+
order, and ledge/staircase/detached-body negatives. Detection, width/length/height fidelity,
|
|
735
|
+
and four downstream boundaries are scored separately; a five-requirement fail-closed ledger
|
|
736
|
+
follows both footprint sizes, height and directional location evidence through the shared
|
|
737
|
+
compiler and placement solve (#1372).
|
|
738
|
+
|
|
739
|
+
- Circular blind steps recognised by `b123d-recognisers` now have a complete consumer path.
|
|
740
|
+
The oriented terminal-to-open centreline and transverse quarter-arc lower without rescanning
|
|
741
|
+
to an explicit-only IR/Sheet feature; generated code preserves the full correspondence.
|
|
742
|
+
Radius and stopped depth remain independently addressable and tolerance-aware while sharing
|
|
743
|
+
one solver-placed end-view `R… × … DEEP` leader, and a fail-closed two-requirement ledger
|
|
744
|
+
follows each outcome without parsing labels or guessing by order (#1382).
|
|
745
|
+
|
|
746
|
+
- Paired-ramp steps recognised by `b123d-recognisers` now have one complete consumer path:
|
|
747
|
+
exact IR conversion, explicit `Sheet.paired_ramp_step(...)` declaration, generated-code
|
|
748
|
+
round trip, end-view solver-placed `2× angle × run RUN` leader, independent angle/run
|
|
749
|
+
tolerances and authored suppression, and a two-requirement fail-closed completeness ledger
|
|
750
|
+
(#1382).
|
|
751
|
+
|
|
752
|
+
- Rectangular through steps recognised by `b123d-recognisers` now lower without rescanning to
|
|
753
|
+
an explicit-only IR/Sheet feature. Automatic and explicit lowering support every principal
|
|
754
|
+
axis; an X/Y occurrence stays with the established face-level and shoulder/plate grammar only
|
|
755
|
+
when that grammar proves both exact leg intervals, avoiding both silent loss and duplicate
|
|
756
|
+
dimensions. The two
|
|
757
|
+
orthogonal open-section legs are independently addressable, tolerance-aware, solver-placed in
|
|
758
|
+
the end view, preserved by generated code and scored by a fail-closed two-requirement
|
|
759
|
+
completeness ledger. The through extent stays owned by the envelope (#1382).
|
|
760
|
+
|
|
761
|
+
- Hole completeness is now supported by a versioned, independently authored STEP corpus rather
|
|
762
|
+
than a Draftwright-derived census. Detection, parameter fidelity and downstream usefulness stay
|
|
763
|
+
separate, while the IR adapter, public Sheet declaration, executed generated code and placed
|
|
764
|
+
drawing are each observed through their real seam. Mutations prove that a missing provider hole
|
|
765
|
+
or a broken downstream boundary lowers the relevant evidence even when internal state remains
|
|
766
|
+
self-consistent (#1369).
|
|
767
|
+
- Hole-pattern completeness is now supported by a separate independently authored STEP
|
|
768
|
+
arrangement corpus covering grids, bolt circles, linear arrays, false-positive controls,
|
|
769
|
+
compound cases and topology-order variants. It scores one grouping fact per pattern while the
|
|
770
|
+
hole corpus remains the sole owner of member diameter/depth/location requirements, and follows
|
|
771
|
+
each group through the IR, public Sheet declaration, generated code and placed pattern
|
|
772
|
+
dimensions (#1370).
|
|
773
|
+
- Flat completeness is now supported by an independently authored STEP corpus covering lone,
|
|
774
|
+
opposed, slanted, parallel and coaxial stock plus negative and topology-order controls. It
|
|
775
|
+
counts one physical across-flats requirement per stock line and span, then observes automatic
|
|
776
|
+
IR, public `Sheet.flat`, executed generated code and placed measurement provenance independently
|
|
777
|
+
(#1371).
|
|
778
|
+
- Lone-pocket completeness is now supported by an independently authored STEP corpus covering
|
|
779
|
+
off-centre, edge-anchored, equal, opposed-opening, side-opening, compound, ownership-negative
|
|
780
|
+
and topology-order cases. Provider `open_sign` now survives the IR, declaration and generated
|
|
781
|
+
code boundaries; pocket sizes and both physical location ordinates are followed through exact
|
|
782
|
+
semantic placement evidence without counting pocket-pattern members twice (#1372).
|
|
783
|
+
- Pocket-pattern completeness is now supported by a separate independently authored STEP corpus
|
|
784
|
+
covering axis-aligned and 30° linear/grid arrangements, threshold and unequal-spacing
|
|
785
|
+
negatives, a compound underside pattern and reverse-serialized topology variants. One grouped
|
|
786
|
+
count/size/lattice/location requirement reaches automatic IR, public `Sheet.pocket_pattern`,
|
|
787
|
+
generated code and exact placed ink—including approved pitch tolerances—without recounting its
|
|
788
|
+
member pockets. Diagonal pocket-pattern dimensions use exact label-ink clearance instead of a
|
|
789
|
+
false-blocking hull; generated code preserves the member opening side and grouped callouts
|
|
790
|
+
retain structured count provenance (#1372).
|
|
791
|
+
- Groove completeness is now supported by an independently authored STEP corpus covering a
|
|
792
|
+
monotonic-step negative, all principal axes, a narrow circlip ownership contest, equal grooves
|
|
793
|
+
on separate bodies and reversed Boolean order. Each physical groove's width and floor diameter
|
|
794
|
+
pass independently through automatic IR, public `Sheet.groove`, executed generated code and
|
|
795
|
+
one exact compiler-backed `WIDE × ø` callout; mutations prove that recognition, identity,
|
|
796
|
+
parameters, provenance and printed syntax cannot disappear without lowering evidence (#1372).
|
|
797
|
+
- Chamfer completeness is now supported by an independently authored STEP corpus covering all
|
|
798
|
+
principal axes, equal and asymmetric planar bevels, conical turned treatments, equal features
|
|
799
|
+
on separate bodies, topology-order variants, a plain negative and the AngledStep ownership
|
|
800
|
+
boundary. Each physical bevel is followed through exact IR, public `Sheet.chamfer`, executed
|
|
801
|
+
generated code, compiler measurement provenance, callout syntax and its physical leader target;
|
|
802
|
+
equal requirements may share ink without collapsing occurrence identity (#1374).
|
|
803
|
+
- Fillet completeness is now supported by an independently authored STEP corpus covering all
|
|
804
|
+
principal axes, repeated equal rounds, turned toroidal treatments, separate bodies,
|
|
805
|
+
topology-order variants, a plain negative and the CircularBlindStep ownership boundary. Each
|
|
806
|
+
physical round is followed through exact IR, public `Sheet.fillet`, executed generated code,
|
|
807
|
+
compiler measurement provenance, `R`/`n× R` syntax and its physical leader target; grouped ink
|
|
808
|
+
retains every rounded edge's measurement identity (#1374).
|
|
809
|
+
|
|
810
|
+
- Recognised angled blind steps now fail visibly instead of remaining an undecided inventory.
|
|
811
|
+
Each aggregate-reconciled `AngledStep` produces an actionable warning and one `unsupported`
|
|
812
|
+
completeness outcome. A frozen STEP corpus fixture pins the AngledStep/Chamfer ownership
|
|
813
|
+
boundary, while Draftwright deliberately invents no angle/run, IR, Sheet, generated-code,
|
|
814
|
+
section/detail, or annotation semantics (#1247).
|
|
815
|
+
|
|
816
|
+
- Aggregate-reconciled `PrismaticPocket` occurrences now fail visibly instead of
|
|
817
|
+
remaining an unscored inventory. Each produces an actionable warning and one `unsupported`
|
|
818
|
+
completeness outcome, without repeating the provider's cross-family reconciliation or
|
|
819
|
+
inventing width/length, across-flats, IR, Sheet, generated-code, or annotation semantics (#1246).
|
|
820
|
+
|
|
821
|
+
- Recognised prismatic passages now fail visibly instead of disappearing into an unscored
|
|
822
|
+
inventory. Each authoritative `SectionPassage` produces an actionable warning and an
|
|
823
|
+
`unsupported` completeness outcome; the legacy `Passage` compatibility projection is never
|
|
824
|
+
double-counted. Draftwright retains the family-level unsupported disposition rather than
|
|
825
|
+
claiming a regular-polygon callout represents the provider's complete line/arc schema (#1245).
|
|
826
|
+
|
|
827
|
+
- Declared Double-D bore, countersink, chamfer, fillet, and groove geometry reads now use the
|
|
828
|
+
stable `b123d_recognisers.inspection` namespace from the exact 0.4.6 wheel. A separate
|
|
829
|
+
Draftwright-owned format-1 contract fails closed on changes to the consumed signatures, result
|
|
830
|
+
schemas, units, bevel rejection reasons, or cylindrical surface layout (#1362).
|
|
831
|
+
|
|
832
|
+
- Updated the exact `b123d-recognisers` production lock to 0.4.6. At adoption time, circular
|
|
833
|
+
blind, paired ramp, and through-step inventories were carried from the one aggregate and
|
|
834
|
+
surfaced as unscored completeness evidence pending the #1382 semantic slices now recorded
|
|
835
|
+
above. Rectangular-grid pitch placement also uses a
|
|
836
|
+
deterministic outer witness line across plan, front, and side views despite the release's
|
|
837
|
+
coordinate-rounding differences.
|
|
838
|
+
|
|
839
|
+
- `annotation_overlap` now reports the whole defect when the same pair also draws
|
|
840
|
+
line-work through one of the two labels: the message names the crosser, the label
|
|
841
|
+
crossed and the millimetres, and replaces the "use `label_offset_x`" remedy, which
|
|
842
|
+
is the advice that case contradicts. `LintIssue.suggestion` is `None` for those
|
|
843
|
+
issues rather than a snippet that re-places the text (#1321, #1332).
|
|
844
|
+
|
|
845
|
+
- Recogniser integration now uses only the exact `b123d-recognisers` dependency in
|
|
846
|
+
`pyproject.toml` and `uv.lock`. The separate release-evidence record, dependency-bump workflow,
|
|
847
|
+
candidate-checkout harness, and release-time capability-version rewrites have been removed;
|
|
848
|
+
ordinary compatibility tests validate the installed pinned package.
|
|
849
|
+
- Automatic composition now measures the next larger preferred scale when a conservative
|
|
850
|
+
crowded-detail reservation leaves a sparse sheet. A candidate wins only on the same paper
|
|
851
|
+
size, without the recovery detail, structural errors, or required-placement loss. GRM-04 now
|
|
852
|
+
uses A4 at 5:1 instead of 2:1, re-homes its shared side-hole Y location into the plan-view
|
|
853
|
+
corridor, and retains both the Ø2.4 diameter and location requirements (#1155).
|
|
854
|
+
- Closed the remaining dense-sheet leader cases as deliberate Policy-B behavior: exhaustive
|
|
855
|
+
route sweeps prove there is no route clear of both material and committed sheet ink, so the
|
|
856
|
+
required callout remains with an explicit crossing diagnostic instead of being dropped. A
|
|
857
|
+
fast synthetic release gate complements the retained exhaustive corpus characterization
|
|
858
|
+
(#1187).
|
|
859
|
+
|
|
860
|
+
### Fixed
|
|
861
|
+
|
|
862
|
+
- Overall height and envelope width remain dimensioned when approved turned-step lengths
|
|
863
|
+
cover only part of the respective extent. Redundancy suppression now requires adjoining
|
|
864
|
+
measurements on one profile to reach both overall endpoints; STC618 retains its missing
|
|
865
|
+
62 mm height (#1509).
|
|
866
|
+
- Non-1:1 orthographic and isometric projection now scales extracted solids about the world
|
|
867
|
+
origin, matching the view-coordinate mapper and solver zones. Solids carrying a non-zero
|
|
868
|
+
build123d `Location` no longer shift their silhouette away from dimensions and callouts.
|
|
869
|
+
- Notes and generic table cells now render U+2300 `⌀` with the established supported drafting
|
|
870
|
+
glyph instead of IBM Plex Mono's missing-glyph square. The substitution happens at the one
|
|
871
|
+
shared measurement/render seam, so source rows remain unchanged and table sizing stays exact
|
|
872
|
+
(#1275).
|
|
873
|
+
- Automatic turned-part composition now gives true shoulder coverage priority over optional
|
|
874
|
+
pictorial content. GRM-03 replans to 5:1 and renders its 0.5, 2, 3, and 18 mm axial lengths;
|
|
875
|
+
`axial_length_missing` disappears because the dimensions are present, not because the
|
|
876
|
+
diagnostic was suppressed (#443).
|
|
877
|
+
|
|
878
|
+
## v0.4.10 — 2026-08-22
|
|
879
|
+
|
|
880
|
+
**A view-set-aware planning and turned-edge-treatment patch.** Authored view constraints now
|
|
881
|
+
compile into an explicit resolved plan, automatic drawings fail closed when required content is
|
|
882
|
+
lost, AP242 hole tolerances reach their semantic feature owners, and the exact
|
|
883
|
+
`b123d-recognisers` 0.3.0 release supplies turned chamfer and fillet evidence through truthful
|
|
884
|
+
profile-view callouts.
|
|
885
|
+
|
|
886
|
+
### Added
|
|
887
|
+
|
|
888
|
+
- `Sheet` can now author a complete or augmenting semantic view set with `authored_views()`,
|
|
889
|
+
`auto_views()`, `view()`, `section_view()`, `detail_view()`, and their `add_*` forms. Fluent
|
|
890
|
+
view handles declare relationships, alignment, scale, and whole-view pins without exposing
|
|
891
|
+
annotation coordinates; unsupported or infeasible constraints fail at their declaration
|
|
892
|
+
source instead of being silently relaxed. `sheet.view_constraints` exposes the immutable
|
|
893
|
+
request and `drawing.view_plan` the distinct resolved result (#1260).
|
|
894
|
+
- Drawings now retain their resolved view topology, per-view requirement coverage, and
|
|
895
|
+
arrangement decision as inspectable values. The engine can build and semantically compare
|
|
896
|
+
alternative arrangements and requested view sets while keeping projection and page placement
|
|
897
|
+
derived from the same plan (#1130).
|
|
898
|
+
|
|
899
|
+
### Changed
|
|
900
|
+
|
|
901
|
+
- Dimension planning is now aware of the selected principal view set. Requirements supported by
|
|
902
|
+
another planned view are re-homed before projection; an unsupported set raises one aggregated
|
|
903
|
+
`ViewPlanIncomplete` naming every unmet requirement rather than failing late or producing a
|
|
904
|
+
plausible-looking drawing with missing dimensions (#1259).
|
|
905
|
+
- Three sparse corpus drawings now use a `stacked-iso` arrangement and fit A4 instead of A3 at
|
|
906
|
+
the same scale, with identical annotations, labels, and build issues. An alternative may only
|
|
907
|
+
compact the scale already selected by the default arrangement and must survive a real compile
|
|
908
|
+
without semantic loss; otherwise the default is retained (#1130).
|
|
909
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.9 to 0.3.0.
|
|
910
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `6645def94cbabaca7b9676fdb029b02e467266d1f020ea536e903b7d86b52685` are
|
|
911
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
912
|
+
normal consumer gates run on the generated PR.
|
|
913
|
+
- Accepted the additive Chamfer and Fillet schema-2 recogniser contract alongside schema 1 for
|
|
914
|
+
the `b123d-recognisers` 0.3.0 cutover; all other record schemas remain fail-closed at version 1
|
|
915
|
+
(#1276).
|
|
916
|
+
|
|
917
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.6 to 0.2.9.
|
|
918
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `805876905d548fd0ef1301e2cf24427a86d34bc2e592b8d2d0cb43db94e1d3bd` are
|
|
919
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
920
|
+
normal consumer gates run on the generated PR. The aggregate now inventories chamfers and
|
|
921
|
+
fillets on turned parts, and the fixed coaxial-post slot regression retires its downstream
|
|
922
|
+
strict xfail.
|
|
923
|
+
|
|
924
|
+
### Fixed
|
|
925
|
+
|
|
926
|
+
- Automatic builds now apply the same required-outcome gate as explicit-scale builds. A settled
|
|
927
|
+
drawing that lost required placement outcomes records `plan_incomplete`, reports an
|
|
928
|
+
`incomplete` scale decision, preserves measurement/hole/source provenance, and fails lint
|
|
929
|
+
rather than presenting a diagnostic drawing as complete (#1250).
|
|
930
|
+
|
|
931
|
+
- Supported AP242 diameter tolerances now correlate with their canonical hole or pattern owner at
|
|
932
|
+
the completed IR boundary and round-trip through emitted `Sheet` declarations with source
|
|
933
|
+
provenance. Unmatched, ambiguous, conflicting, partial-pattern, and unsupported requirements
|
|
934
|
+
fail closed to provenance-preserving measured dimensions rather than being duplicated or lost
|
|
935
|
+
(#1116).
|
|
936
|
+
|
|
937
|
+
- A declared step shoulder coincident with its datum is now pruned before rendering instead of
|
|
938
|
+
sending identical endpoints to the border-dimension helper and raising `ValueError`. Valid
|
|
939
|
+
siblings remain, while the omission is recorded in `Drawing.suppressions()` and reported as
|
|
940
|
+
`step_position_coincident_with_datum` (#924).
|
|
941
|
+
|
|
942
|
+
- Turned chamfer and fillet leaders now read in a shaft profile view and land on their physical
|
|
943
|
+
edge-treatment sites instead of collapsing axial stations in the end view. Cylindrical
|
|
944
|
+
feature notes, knurl callouts, and surface finishes likewise derive a model-space surface
|
|
945
|
+
target rather than pointing at the shaft axis; all continue through the shared placement
|
|
946
|
+
solves, with X/Y/Z parity and declared Sheet round-trip (#1276).
|
|
947
|
+
|
|
948
|
+
- Toroidal fillets returned for turned parts by the shared recognition inventory now lower into
|
|
949
|
+
the existing one-feature-per-round IR and render through the common leader solve. Equal radii
|
|
950
|
+
share one `n× R` callout carrying every physical fillet's measurement provenance, and emitted
|
|
951
|
+
Sheet programs preserve the full inventory without rescanning geometry (#1281).
|
|
952
|
+
|
|
953
|
+
- Turned chamfers returned by the shared recognition inventory now lower into the same
|
|
954
|
+
one-feature-per-edge-treatment IR as prismatic chamfers. Equal specifications render as one
|
|
955
|
+
`n×` callout carrying every member's measurement provenance; different chamfer forms do not
|
|
956
|
+
collapse merely because their first legs match, and distinct tolerances split into truthful
|
|
957
|
+
requirements instead of being lost or applied to untoleranced siblings (#1254).
|
|
958
|
+
|
|
959
|
+
- Recogniser dependency automation now starts a fresh `Unreleased` section when the previous
|
|
960
|
+
Draftwright release has finalized the changelog, so a published recogniser can enter through
|
|
961
|
+
the documented immutable update workflow instead of failing before it opens a PR (#1279).
|
|
962
|
+
|
|
963
|
+
## v0.4.9 — 2026-08-21
|
|
964
|
+
|
|
965
|
+
### Added
|
|
966
|
+
|
|
967
|
+
- Lint now verifies that an annotation claiming to carry a measurement actually renders it
|
|
968
|
+
(#1217). Coverage checks read provenance riders the annotations carry about themselves and
|
|
969
|
+
believed them; nothing checked the claim against what the annotation draws. Four new codes —
|
|
970
|
+
`claimed_value_absent`, `claimed_measurement_not_compiled`, and two that report an
|
|
971
|
+
unverifiable claim rather than passing it — and `Drawing.add_table` now keeps the rows it
|
|
972
|
+
draws so a table's claims are readable back. Measured over all 21 STEP fixtures: 1,081
|
|
973
|
+
claims, 1,078 confirmed, and three findings — all instances of one genuine provenance
|
|
974
|
+
defect, see #1219.
|
|
975
|
+
|
|
976
|
+
- `lint_summary()["quality"]` gains a fourth component, `fidelity`: whether what the drawing
|
|
977
|
+
says is TRUE. The existing three ask whether required content landed (completeness),
|
|
978
|
+
whether there is too much of it (restraint), and whether a reader can make it out
|
|
979
|
+
(legibility) — none asked whether it is correct, so a drawing labelled 99 over a 16 mm
|
|
980
|
+
path reported a perfect score on every component available to it. Also covers a callout
|
|
981
|
+
drawn for a feature the part does not have, and a gear data table stating a tooth count
|
|
982
|
+
the geometry contradicts — the last of which reports `passed: True` and zero errors, so
|
|
983
|
+
the only existing channel that names it is `by_code`. Completeness, restraint and fidelity
|
|
984
|
+
report `available: False` with a `reason` rather than a flattering number when they have no
|
|
985
|
+
evidence, and every lint code the engine emits is classified onto exactly one component,
|
|
986
|
+
an explicit unscored register, or a register of codes whose component depends on the
|
|
987
|
+
issue's `outcome_stage`. `quality["unscored"]` reports the findings that reached no
|
|
988
|
+
component at all and flags any whose classification nobody made — `section_dropped` was
|
|
989
|
+
found scoring on nothing while a comment beside its emission said the opposite, and eleven
|
|
990
|
+
more `*_dropped` codes reach the engine as `drop_code` data with the same shape (#1176).
|
|
991
|
+
|
|
992
|
+
### Changed
|
|
993
|
+
|
|
994
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.4 to 0.2.6.
|
|
995
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `aa52bc04216cd1eccc05796d2262547c7f476b80a3ec77334a77b9d8e3241a58` are
|
|
996
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
997
|
+
normal consumer gates run on the generated PR.
|
|
998
|
+
- `HoleRequirementOutcome` gains `members` and `features`, `ClaimOutcome` gains `measurement`,
|
|
999
|
+
and `linting.hole_coverage.canonical_hole_sites` is public (#1217). A consumer attributing a
|
|
1000
|
+
requirement outcome to a specific recognised hole needs the evidence the outcome accounts
|
|
1001
|
+
for, and needs to key into the canonical space the ledger publishes it in — a through hole's
|
|
1002
|
+
own-axis coordinate is zeroed there.
|
|
1003
|
+
- The STEP-analysis benchmark's `drawing_consumer` boundary now consumes
|
|
1004
|
+
`hole_requirement_outcomes` instead of a second correspondence implementation of its own
|
|
1005
|
+
(#1206), and follows the ledger's pointer through `linting.evidence` rather than trusting it.
|
|
1006
|
+
Holes the ledger reports `unverifiable` now score `unknown` where the duplicate credited them
|
|
1007
|
+
by guessing: 26 holes, five on each CTC-03 fixture and eight on each CTC-04 fixture. The
|
|
1008
|
+
five-case evaluation corpus is unchanged, and one lint message on CTC-03 now reports its
|
|
1009
|
+
coordinates in the ledger's own canonical space.
|
|
1010
|
+
|
|
1011
|
+
- `Drawing.suppressions()` rows gain a `conveyed_by` key: the dimension that states a
|
|
1012
|
+
withheld measurement instead, or `None` when nothing takes the fact over (#1154). It is not
|
|
1013
|
+
a synonym for the existing `authored` flag — that says whose decision it was, this says
|
|
1014
|
+
where the measurement went.
|
|
1015
|
+
|
|
1016
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.2 to 0.2.4.
|
|
1017
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `d0023d30e583c03abc55f09dfeaaa56fddf56334afa0417818480b2fa2ce3f0f` are
|
|
1018
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
1019
|
+
normal consumer gates run on the generated PR.
|
|
1020
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.1 to 0.2.2.
|
|
1021
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest `7985befc8572bfe6d1c0805dfdf690d74a5a4a5f14d5988cc29c366315ff04ca` are
|
|
1022
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
1023
|
+
normal consumer gates run on the generated PR.
|
|
1024
|
+
|
|
1025
|
+
### Fixed
|
|
1026
|
+
|
|
1027
|
+
- An authored tolerance the compiler approved now reaches the sheet wherever the measurement
|
|
1028
|
+
is drawn (#1215, #1216). `build123d_drafting` resolves a dimension's text as
|
|
1029
|
+
`label if label is not None else _number_with_units(measured, tolerance)`, and every
|
|
1030
|
+
dimension this engine emits passes a label — so a forwarded `tolerance=` rendered nothing
|
|
1031
|
+
while type-checking and reading back correctly from `Dimension.label`. Ten render paths
|
|
1032
|
+
discarded the band that way: envelope extents, the height ladder, the turned-step chain, two
|
|
1033
|
+
public `Drawing` verbs, the deferred corridor route, the detail-view redraw, the short-rise
|
|
1034
|
+
escape, step shoulders, pattern pitch, compound-callout recess terms, grid pitch, and both
|
|
1035
|
+
hole tables. A general guard now decorates every parameter of every feature across a corpus,
|
|
1036
|
+
through both `decorations=` key shapes, and joins what the compiler approved against what the
|
|
1037
|
+
claiming annotation renders.
|
|
1038
|
+
|
|
1039
|
+
- Collapsed `N×` marks no longer state a tolerance their members do not share (#1216). A
|
|
1040
|
+
pattern's pitch claimed the authored band of every gap although the recogniser admits 2%
|
|
1041
|
+
jitter — holes at −30, −10, 10.3, 30 printed `3× 20 ±0.1` over a 20.3 mm gap — and fillet and
|
|
1042
|
+
flat collapses took the "first-authored" band, so one of four fillets at ±0.1 printed
|
|
1043
|
+
`4× R5 ±0.1`. Equality is now judged at the drawn precision, and a withheld band is reported
|
|
1044
|
+
(`pattern_pitch_tolerance_withheld`, `collapsed_tolerance_withheld`) rather than dropped
|
|
1045
|
+
silently.
|
|
1046
|
+
|
|
1047
|
+
- An approved dimension that cannot be placed is now reported instead of vanishing (#1216).
|
|
1048
|
+
The overall extents' corridor candidate carried a no-op drop handler — the only drop in the
|
|
1049
|
+
engine that recorded nothing — and the step ladder's legibility floor skipped rungs without
|
|
1050
|
+
incrementing any counter. Both now record against the measurement they concern, and a
|
|
1051
|
+
withholding is withdrawn if a later pass draws the measurement after all.
|
|
1052
|
+
|
|
1053
|
+
- A feature leader filling a view's below corridor no longer costs the part its overall extent
|
|
1054
|
+
(#1236). The mandatory width or depth now retries on the view's above strip after every
|
|
1055
|
+
corridor has drained, the fallthrough starved slot and plate dimensions already use. Live on
|
|
1056
|
+
three NIST CTC fixtures, which drew no overall width.
|
|
1057
|
+
|
|
1058
|
+
- The iso view and the above strips are no longer invisible to each other (#1240). Strip
|
|
1059
|
+
placement never saw the iso, and the iso fit re-scaled after annotation without consulting
|
|
1060
|
+
what had been placed — so growth could invade dimension ink, which it did on CTC-01. The fit
|
|
1061
|
+
is now capped by measured re-projection rather than by a linear model of it: the projected
|
|
1062
|
+
bbox translates as it scales, by up to 7.35 mm on a part carrying a Location, which no
|
|
1063
|
+
prediction about the page centre can express.
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
- A part whose feature-local extent runs between the same two faces as an overall extent
|
|
1067
|
+
is no longer dimensioned twice (#1154). GRM-04's drive plate printed `4.5` twice — once
|
|
1068
|
+
as the hub's height and once as the overall thickness — because two detected records
|
|
1069
|
+
claim one physical fact. The overall extent keeps it; the feature-local one is withheld
|
|
1070
|
+
and records which dimension the reader finds it on. Reconciliation is by exact
|
|
1071
|
+
support-plane coincidence, never by value: a square part's two equal extents run between
|
|
1072
|
+
different faces and remain two facts (#997). A measurement is handed over only when the
|
|
1073
|
+
extent receiving it is actually drawn — by the planner's rules, by the compiler's
|
|
1074
|
+
overall-height rules, and by an authored set — and never when the yielding dimension
|
|
1075
|
+
carries a tolerance, since a toleranced dimension and an untoleranced one are not the same
|
|
1076
|
+
requirement. (A tolerance on the *receiving* extent is the same requirement on the same two
|
|
1077
|
+
faces, and does not prevent the consolidation.)
|
|
1078
|
+
|
|
1079
|
+
## v0.4.8 — 2026-08-16
|
|
1080
|
+
|
|
1081
|
+
### Fixed
|
|
1082
|
+
|
|
1083
|
+
- Compatible automatic/deferred sparse ordinary side/plan hole and post-drain
|
|
1084
|
+
machined-feature callouts now share one bounded same-view leader inventory
|
|
1085
|
+
(#1166). Pattern, profiled-bore, and dense table-eligible hole queues retain
|
|
1086
|
+
their specialised established paths because their winners affect downstream
|
|
1087
|
+
furniture/table semantics or await #798 silhouette-aware routing. The solve
|
|
1088
|
+
preserves required/priority-ranked evidence, rejects new-leader crossings,
|
|
1089
|
+
checks complete leader ink against actual-width fixed dimension/witness,
|
|
1090
|
+
arrow, label, and centre-furniture components (including rendered arrows on
|
|
1091
|
+
shifted dimensions and component-local dashed circular centre furniture);
|
|
1092
|
+
fixed residual faces and the selected survivor both require each tessellation
|
|
1093
|
+
triangle to fit one same analytical component rather than merely the union,
|
|
1094
|
+
plus exact continuous OCC containment for curved faces; residual lowering
|
|
1095
|
+
also retains filled datum/GD&T faces absent from segment metadata; if candidate
|
|
1096
|
+
or selected-survivor construction raises, or a survivor fails validation, the
|
|
1097
|
+
bad alternative fails closed and the canonical lazy producer tail is replayed
|
|
1098
|
+
instead of falsely dropping an otherwise valid callout; an all-invalid tail is
|
|
1099
|
+
reported as validation-stage geometry failure rather than no clear room (so
|
|
1100
|
+
scale fallback does not retry a non-spatial helper defect), while compiler
|
|
1101
|
+
invariant violations such as a missing semantic callout label remain loud;
|
|
1102
|
+
only explicitly marked global turning axes permit an arrow-local leader-tip
|
|
1103
|
+
attachment; near-collinear shaft travel and ownerless section/cutting lines
|
|
1104
|
+
remain fixed ink. The solve prefers
|
|
1105
|
+
clear routes over explicit Policy-B fallbacks, and then minimises real leader
|
|
1106
|
+
length. Provisional sections cannot veto that primary result: one separately
|
|
1107
|
+
bounded refinement may choose an equally complete leader inventory that clears
|
|
1108
|
+
their exact components, after which the final section performs one bounded
|
|
1109
|
+
end-symbol repair and yields if exact ink still conflicts. The selected OCC survivor is validated against the same analytical
|
|
1110
|
+
ink contract. A retained fixed-ink crossing now emits the machine-readable
|
|
1111
|
+
`feature_leader_crossing` info finding instead of appearing lint-clean. Candidate,
|
|
1112
|
+
fixed-component lowering, fixed-obstacle-probe, pair, and exact-search work is
|
|
1113
|
+
bounded; the fixed inventory is lowered once and reused with the producer's
|
|
1114
|
+
legacy lazy result as the floor, including state-cap exhaustion; page,
|
|
1115
|
+
own-silhouette, and title-reservation constraints remain hard in every fallback.
|
|
1116
|
+
A replay that exhausts exact fixed-probe classification is retained visibly as
|
|
1117
|
+
`feature_leader_fixed_ink_unverified` rather than rescanning past the cap, and
|
|
1118
|
+
that uncertainty participates in the legibility quality inventory.
|
|
1119
|
+
Trace output preserves an abandoned fully admitted inventory when state search
|
|
1120
|
+
exhausts, records the producer-floor replay separately, and names exact committed/provisional components,
|
|
1121
|
+
refinement status, and competing blockers; live
|
|
1122
|
+
single-callout edits remain immediate.
|
|
1123
|
+
|
|
1124
|
+
## v0.4.7 — 2026-08-16
|
|
1125
|
+
|
|
1126
|
+
### Added
|
|
1127
|
+
|
|
1128
|
+
- Recogniser co-development now has a one-command, wheel-based two-checkout check; an exact
|
|
1129
|
+
registry-release evidence record; automated dependency PR preparation; and documented landing,
|
|
1130
|
+
compatibility, deprecation, rollback, ownership, and CI-budget rules. Dependency PRs retain the
|
|
1131
|
+
canonical coverage/Codecov gate while avoiding four duplicate platform suites and the slow tier
|
|
1132
|
+
(#1170).
|
|
1133
|
+
- A versioned, independently authored STEP-analysis corpus and evaluator now report detection
|
|
1134
|
+
recall/false positives, parameter fidelity, and downstream usefulness as separate evidence
|
|
1135
|
+
layers. Hash-pinned positive, negative, ambiguous, compound, and topology-order-variant fixtures,
|
|
1136
|
+
per-layer diagnostics, and an anti-self-validation mutation prevent recogniser output from
|
|
1137
|
+
defining its own denominator (#1169).
|
|
1138
|
+
- Draftwright now validates the released `b123d-recognisers` 0.2.0 capability manifest against
|
|
1139
|
+
an exhaustive consumer-owned declaration of IR, DSL, generated-code, drawing, completeness,
|
|
1140
|
+
and documentation states. Unknown families, stale implementations, record-schema drift, and
|
|
1141
|
+
unevidenced state transitions fail closed; intentionally geometry-only repeating-profile
|
|
1142
|
+
evidence remains usable without acquiring invented drafting semantics.
|
|
1143
|
+
|
|
1144
|
+
### Changed
|
|
1145
|
+
|
|
1146
|
+
- Updated the exact `b123d-recognisers` production lock from 0.2.0 to 0.2.1.
|
|
1147
|
+
The immutable PyPI wheel/sdist hashes and capability-manifest digest
|
|
1148
|
+
`383a196329ed6a3d1bf88f18ae4ff75613c032f35d40f2b53302b6744da4d19e` are
|
|
1149
|
+
recorded in `.github/recogniser-release.json`; focused compatibility evidence and the
|
|
1150
|
+
normal consumer gates run on the generated PR.
|
|
1151
|
+
|
|
1152
|
+
### Fixed
|
|
1153
|
+
|
|
1154
|
+
- Stable release and TestPyPI snapshot builds now update package metadata and the independently
|
|
1155
|
+
validated Draftwright consumer-contract identity atomically. This prevents stripped `.dev0`
|
|
1156
|
+
and numbered development artifacts from failing their own capability-contract validation.
|
|
1157
|
+
- Installed wheels validate every portable recogniser-contract property without requiring the
|
|
1158
|
+
repository-only behavior-test files whose existence remains a strict source/CI gate. This keeps
|
|
1159
|
+
the packaged STEP-analysis evaluator usable without weakening evidence checks in development.
|
|
1160
|
+
- Post-release development-version bumps now update the consumer-contract identity on a branch,
|
|
1161
|
+
open a protected PR, and dispatch the narrow maintenance gate instead of attempting a rejected
|
|
1162
|
+
direct push to protected `main` (#1170).
|
|
1163
|
+
- Machined-feature leader callouts now collect all clear alternatives within each
|
|
1164
|
+
post-drain pass and use a bounded maximum-cardinality, minimum-leader-length
|
|
1165
|
+
assignment instead of taking corners greedily in feature order (#740). If a
|
|
1166
|
+
deterministic alternative-count, pass-size, candidate-pair, or search budget is
|
|
1167
|
+
reached, placement retains the legacy greedy result or a result no worse than it
|
|
1168
|
+
rather than losing additional callouts. Pre-drain diameter clearance ranking and
|
|
1169
|
+
its Policy-B fallback remain unchanged.
|
|
1170
|
+
|
|
1171
|
+
## v0.4.6 — 2026-08-15
|
|
1172
|
+
|
|
1173
|
+
### Changed
|
|
1174
|
+
|
|
1175
|
+
- **Geometry recognition is supplied by the standalone Apache-2.0
|
|
1176
|
+
[`b123d-recognisers`](https://github.com/pzfreo/b123d-recognisers) package.** The cutover
|
|
1177
|
+
pins the published stable release `v0.1.0` (built from commit
|
|
1178
|
+
`9e622716c14d491729b5191aa6e5d8351c982a51`), removes the
|
|
1179
|
+
duplicate embedded implementation, and keeps only identity-preserving
|
|
1180
|
+
`draftwright.recognition` / `draftwright.score` compatibility re-exports until 0.6.0.
|
|
1181
|
+
Draftwright continues to own the one-result build/lint cache, record→IR conversion, drafting
|
|
1182
|
+
policy, placement, and critique. The package migration is manifest-pinned and golden-backed;
|
|
1183
|
+
its sole normalization makes an exact dominant-axis tie deterministic across operating
|
|
1184
|
+
systems without changing feature policy.
|
|
1185
|
+
|
|
1186
|
+
### Fixed
|
|
1187
|
+
|
|
1188
|
+
- Hole-callout obstacle checks now account for the rendered leader shaft width and
|
|
1189
|
+
tip-local arrowhead flare instead of treating the leader as a zero-width centreline
|
|
1190
|
+
(#367). The analytical check remains geometry-only and does not over-reserve the
|
|
1191
|
+
arrowhead's clearance along the whole shaft.
|
|
1192
|
+
- Exact X/Z slanted flats retain their established lint-clean side-view callout after the
|
|
1193
|
+
recogniser package's cross-platform semantic-axis normalization. The normalized recognition
|
|
1194
|
+
record remains unchanged; `FlatFeature.presentation_axis` carries the downstream drawing-view
|
|
1195
|
+
choice, preventing a leader/silhouette crossing without duplicating recognition.
|
|
1196
|
+
|
|
1197
|
+
## v0.4.5 — 2026-08-15
|
|
1198
|
+
|
|
1199
|
+
**A focused technical-drawing correctness patch.** Cross-drilled hole locations now remain
|
|
1200
|
+
complete and ordered, datum-starting pocket annotations avoid redundant dimensions, and repeated
|
|
1201
|
+
equal-radius fillets collapse into one manufacturing callout.
|
|
1202
|
+
|
|
1203
|
+
### Fixed
|
|
1204
|
+
|
|
1205
|
+
- Side-drilled hole heights that relocate around callout leaders now join the alternate
|
|
1206
|
+
view's shared dimension ladder before placement, preserving every height and keeping
|
|
1207
|
+
feature locations inside the overall dimension. Datum-starting open pockets no longer
|
|
1208
|
+
print a redundant half-length centre offset, and equal-radius fillets across different
|
|
1209
|
+
edge axes collapse into one counted ``n× R`` callout.
|
|
1210
|
+
|
|
1211
|
+
## v0.4.4 — 2026-08-15
|
|
1212
|
+
|
|
1213
|
+
**A semantic-completeness and fail-closed layout patch release.** Hole requirements and drawing
|
|
1214
|
+
quality are now machine-readable, hole-table replacement is transactional, explicit scales
|
|
1215
|
+
preserve required output, notes tables use all viable sheet space, and gear declarations,
|
|
1216
|
+
recognition evidence, and callout metadata improve diagnostic trust.
|
|
1217
|
+
|
|
1218
|
+
### Added
|
|
1219
|
+
|
|
1220
|
+
- **External spur gears can be declared through the `Sheet` façade** (#1086). The declaration
|
|
1221
|
+
records the correlated ISO 1328-1 manufacturing requirements, renders a structured gear-data
|
|
1222
|
+
table, and survives script emission, declaration, export, and lint without inferring gear data
|
|
1223
|
+
that the caller did not supply.
|
|
1224
|
+
|
|
1225
|
+
- **Recognition carries serialisable repeating radial-profile evidence** (#1087). Exact
|
|
1226
|
+
rotational whole-wire proof can reconcile a declared gear with its physical profile while
|
|
1227
|
+
preserving ambiguity across separate bodies and without inventing module, pressure angle, or
|
|
1228
|
+
other manufacturing intent.
|
|
1229
|
+
|
|
1230
|
+
- **Explicit drawing scales now protect required annotation completeness** (#1146).
|
|
1231
|
+
`build_drawing(...)`, `make_drawing(...)`, `Sheet(...)`, and the CLI accept
|
|
1232
|
+
`scale_policy="fallback"|"strict"|"permissive"`. The safe default retries preferred ISO
|
|
1233
|
+
5455 reductions and returns the largest complete scale; strict mode raises with structured
|
|
1234
|
+
requirement blockers, while permissive mode is an explicit warned opt-in to the historical
|
|
1235
|
+
best-effort result. Every returned `Drawing.scale_decision` reports the requested and
|
|
1236
|
+
effective scales, status, attempted scales, and any semantic placement blockers.
|
|
1237
|
+
|
|
1238
|
+
- **Hole and hole-pattern requirements now participate in semantic completeness accounting**
|
|
1239
|
+
(#1143). `lint_summary()["quality"]["completeness"]` reconciles recognition-owned bore,
|
|
1240
|
+
depth/through, grouping, pattern, and location requirements to placed, suppressed, dropped,
|
|
1241
|
+
missing, or explicitly unverifiable outcomes. Ambiguous declared/automatic correspondence
|
|
1242
|
+
fails closed without shrinking the physical denominator. Z-normal hole locations retain ADR
|
|
1243
|
+
0016's feature-level `location.location` addressability while structured physical evidence
|
|
1244
|
+
distinguishes the independently required X and Y ordinates for critique.
|
|
1245
|
+
|
|
1246
|
+
- **`lint_summary()` exposes drawing-quality evidence as separate completeness, restraint,
|
|
1247
|
+
and legibility components** (#1127). The legacy `score` remains byte-compatible and is also
|
|
1248
|
+
returned as the honestly named `diagnostic_score`; no composite quality verdict is invented.
|
|
1249
|
+
Completeness scores recognition-owned requirements in the families with semantic outcome
|
|
1250
|
+
ledgers and states that conditional scope explicitly; recognized families not yet scored are
|
|
1251
|
+
listed separately. Its scalar is `audited_score`, not `score`, because a feature recognition
|
|
1252
|
+
missed never became a requirement — so a part with a recogniser gap can reach 1.0, and the
|
|
1253
|
+
qualifier belongs where it survives being quoted. The block also lists what its denominator
|
|
1254
|
+
`excludes` and counts `unrecognised_geometry_reports` (a floor on that gap, not a measure).
|
|
1255
|
+
It is not a completion gate. Legibility includes only layout and placement diagnostics, and
|
|
1256
|
+
scores information-severity ones — "place what fits" drops, a leader crossing a silhouette —
|
|
1257
|
+
against the warning floor, so it cannot read 1.0 while itemising output it calls unreadable.
|
|
1258
|
+
A drop is identified by its `*_dropped` code suffix unless its producer records an explicit
|
|
1259
|
+
`outcome_stage`, so a drop code added later counts without being registered anywhere.
|
|
1260
|
+
Restraint fails closed as unavailable until measurement provenance can classify every
|
|
1261
|
+
annotation.
|
|
1262
|
+
|
|
1263
|
+
### Fixed
|
|
1264
|
+
|
|
1265
|
+
- **Generic notes/data tables use every viable free sheet region and explain failed placement**
|
|
1266
|
+
(#1145). A drawn sheet frame or zone ruler now defines the usable inset instead of becoming a
|
|
1267
|
+
page-sized solid obstacle, so a measured four-row notes block can use clear lower-left A4
|
|
1268
|
+
space. Tables retain the drafting preset's external text clearance from named and anonymous
|
|
1269
|
+
existing annotations. Failed placement diagnostics report the measured page-space footprint,
|
|
1270
|
+
attempted candidate regions, and the named obstacles or clearance bands that blocked the
|
|
1271
|
+
nearest candidates without materialising the candidate Cartesian product.
|
|
1272
|
+
|
|
1273
|
+
- **Automatic hole-table escalation is transactional per semantic requirement** (#1144). The
|
|
1274
|
+
engine suppresses replaceable callouts and location dimensions only after the table fits and
|
|
1275
|
+
every visible row has its required feature-owned balloon. A failed or partial balloon attempt
|
|
1276
|
+
rolls the shared table back as a unit and restores the exact annotations, ordering, registry
|
|
1277
|
+
identities, coverage, and issues. Precise ring, glyph, and leader-segment tests keep placement
|
|
1278
|
+
clear of retained callout labels, leader shafts, and existing public-balloon components without
|
|
1279
|
+
changing the existing additive `add_hole_table()`/`add_balloons()` behavior; malformed component
|
|
1280
|
+
metadata—including Boolean cardinalities or coordinate payloads—falls back conservatively or fails the
|
|
1281
|
+
optional replacement closed. New balloon shafts must also remain mutually crossing-free.
|
|
1282
|
+
Compound, thread,
|
|
1283
|
+
profile, pattern, tolerance, and fit facts the table cannot state remain active, while
|
|
1284
|
+
independently replaceable X/Y locations may still move to the table. Guarded interval solving
|
|
1285
|
+
has deterministic pre-lane, pre-carve, and work/state budgets; an adversarially fragmented label
|
|
1286
|
+
inventory or band fails the replacement closed before excessive work or allocation. Required row-key
|
|
1287
|
+
balloons take priority over optional non-certifying pattern markers, so an independently complete
|
|
1288
|
+
table cannot be displaced by an auxiliary marker.
|
|
1289
|
+
Hole outcomes identify the winning representation per requirement;
|
|
1290
|
+
mixed table/feature evidence deliberately claims no single winner. Exceptions restore those
|
|
1291
|
+
semantic markers, and automatic escalation fails closed rather than overwrite an existing
|
|
1292
|
+
annotation that owns a reserved table or balloon name.
|
|
1293
|
+
|
|
1294
|
+
- **Generated hole-callout leaders expose their exact rendered semantic text through the public
|
|
1295
|
+
`Leader.label` field** (#1142). Geometry and placement are unchanged, and structured coverage
|
|
1296
|
+
remains authoritative instead of requiring downstream tools to parse display text.
|
|
1297
|
+
|
|
1298
|
+
- **Leader placement probes use analytic footprint arithmetic instead of constructing temporary
|
|
1299
|
+
OCCT geometry** (#1138). Representative probe-heavy layouts are substantially faster while
|
|
1300
|
+
preserving custom-style containment and placement behavior.
|
|
1301
|
+
|
|
1302
|
+
### Changed
|
|
1303
|
+
|
|
1304
|
+
- **Pairwise lint detail no longer multiplies the legibility score penalty** (#1147). Raw
|
|
1305
|
+
severity and code counts retain their existing finding-level semantics, and every offending
|
|
1306
|
+
pair remains in `issues`. The legibility component now also reports its primary issue counts
|
|
1307
|
+
and scores one producer-identified annotation/failure mechanism once, with `affected_pairs`
|
|
1308
|
+
exposing how many raw pair findings were aggregated. The legacy top-level `score` and
|
|
1309
|
+
`diagnostic_score` remain unchanged.
|
|
1310
|
+
|
|
1311
|
+
- **Pull-request validation now reports a stable aggregate `ci-ok` check and runs the supported
|
|
1312
|
+
Python matrix on Linux** (#1134/#1136). Weekly, manual, and labelled workflows retain the
|
|
1313
|
+
cross-platform escape hatch, reducing routine Actions cost without narrowing supported Python
|
|
1314
|
+
coverage.
|
|
1315
|
+
|
|
1316
|
+
## v0.4.3 — 2026-08-09
|
|
1317
|
+
|
|
1318
|
+
**A trust and validation-throughput patch release.** Whole-part hexagonal stock now receives its
|
|
1319
|
+
manufacturing definition, assembly recognition no longer combines evidence across bodies, and
|
|
1320
|
+
performance validation is both more stable and faster to run.
|
|
1321
|
+
|
|
1322
|
+
### Added
|
|
1323
|
+
|
|
1324
|
+
- **Whole-part regular hexagonal stock is recognised independently of an attached boss and
|
|
1325
|
+
dimensioned as `HEX … A/F` plus its axial length** (#1082). In-plane rotation preserves the
|
|
1326
|
+
geometric across-flats size instead of substituting an orientation-dependent bounding-box
|
|
1327
|
+
width. Automatic and declared paths share the same compiler and placement machinery, while
|
|
1328
|
+
completeness lint distinguishes placed, authored-suppressed, dropped, missing, and ambiguous
|
|
1329
|
+
outcomes.
|
|
1330
|
+
|
|
1331
|
+
### Fixed
|
|
1332
|
+
|
|
1333
|
+
- **Slot and pocket patterns cannot group members from separate assembly bodies** (#1073).
|
|
1334
|
+
Recognition carries solid ownership through grouping and fails closed when ownership is
|
|
1335
|
+
unavailable, preventing plausible-looking phantom patterns across disconnected parts.
|
|
1336
|
+
|
|
1337
|
+
- **The annotation-obstacle performance guard uses deterministic work-count evidence instead of
|
|
1338
|
+
a wall-clock threshold** (#1071). The regression test remains load-bearing under mutation but
|
|
1339
|
+
no longer flakes because of machine load or suite ordering.
|
|
1340
|
+
|
|
1341
|
+
### Changed
|
|
1342
|
+
|
|
1343
|
+
- **The post-merge slow tier distributes individual tests across workers** (#1108), using
|
|
1344
|
+
`pytest-xdist`'s load scheduling after local benchmark evidence showed a material speed-up
|
|
1345
|
+
without weakening fixture coverage. Hosted slow validation remains the single post-merge gate.
|
|
1346
|
+
|
|
1347
|
+
## v0.4.2 — 2026-08-09
|
|
1348
|
+
|
|
1349
|
+
**The trustworthy manufacturing drawings release.** AP242 PMI is now accounted for from its
|
|
1350
|
+
source records through lowering and rendering, imported datum faces retain an auditable topology
|
|
1351
|
+
identity, and several drawing paths that previously omitted, invented, or stalled on defining
|
|
1352
|
+
geometry now fail closed or produce the required annotation.
|
|
1353
|
+
|
|
1354
|
+
### Added
|
|
1355
|
+
|
|
1356
|
+
- **AP242 geometric tolerances and datum features survive as source-backed manufacturing
|
|
1357
|
+
requirements** (#62/#675/#1094/#1095/#1099/#1100). The importer recovers range-encoded
|
|
1358
|
+
dimensional tolerances, tolerance characteristics, magnitudes, datum chains, and supported
|
|
1359
|
+
all-around/all-over modifiers. Datum representation-item faces are resolved to imported
|
|
1360
|
+
topology through OCCT's exact transfer relationship rather than geometric resemblance, so the
|
|
1361
|
+
NIST CTC-01 datum definitions `A`, `B`, and `C` lower and render without guessing.
|
|
1362
|
+
|
|
1363
|
+
- **PMI completeness lint reconciles every AP242 source record through extraction, projection,
|
|
1364
|
+
lowering, and rendering** (#623). Unsupported or incomplete requirements remain explicit with
|
|
1365
|
+
source-specific outcomes instead of allowing a partial PMI transcription to report clean.
|
|
1366
|
+
|
|
1367
|
+
- **Hexagonal and other regular polygonal bosses are recognised and dimensioned by their
|
|
1368
|
+
across-flats size** (#676). Automatic and declared paths share the same feature model, and
|
|
1369
|
+
mutation tests reject incomplete, unequal, non-planar, and ambiguous face sets.
|
|
1370
|
+
|
|
1371
|
+
- **Generated `Sheet` scripts preserve references to named source objects where correspondence
|
|
1372
|
+
is proven** (#1041). The `--script` path emits declarations such as
|
|
1373
|
+
`sheet.hole(features.tap)` instead of copying detected numbers; ambiguous, stale, non-shape, or
|
|
1374
|
+
unused mappings fail closed.
|
|
1375
|
+
|
|
1376
|
+
- **A curated API reference is published at
|
|
1377
|
+
<https://pzfreo.github.io/draftwright/>** (#846), covering the supported entry points,
|
|
1378
|
+
`Sheet` declaration surface and fluent handles, `Drawing` results, and feature constructors.
|
|
1379
|
+
|
|
1380
|
+
### Fixed
|
|
1381
|
+
|
|
1382
|
+
- **Recognition no longer combines faces from different solids into phantom slots or pads**
|
|
1383
|
+
(#958). Each physical solid is recognised independently before the results are combined.
|
|
1384
|
+
|
|
1385
|
+
- **`Sheet.from_part(...).envelope()` reuses the detected whole-part envelope** (#1000) instead
|
|
1386
|
+
of appending a duplicate feature whose dimensions were then silently deduplicated on the page.
|
|
1387
|
+
|
|
1388
|
+
- **Crowded Z-turned step chains recover the independently approved overall height when the
|
|
1389
|
+
chain cannot be placed** (#955), and placed step lengths retain measurement identity for
|
|
1390
|
+
differential audit (#1004).
|
|
1391
|
+
|
|
1392
|
+
- **All-over GD&T leaders and complex STEP B-spline paths have bounded, export-safe DXF
|
|
1393
|
+
conversion** (#1097/#1070). All-over scope now reaches the existing export-safe leader
|
|
1394
|
+
representation, while spline conversion reads OCCT knots, poles, and weights through its
|
|
1395
|
+
indexed API instead of expensive sequence wrappers; visible curve geometry is preserved.
|
|
1396
|
+
|
|
1397
|
+
### Changed
|
|
1398
|
+
|
|
1399
|
+
- **Hosted CI retains every supported Python version and both dependency/kernel generations on
|
|
1400
|
+
macOS and Windows with a smaller compatibility matrix** (#1103). PRs still require lint,
|
|
1401
|
+
coverage, Codecov, and the compatibility gates; the slow standards tier runs once after merge.
|
|
1402
|
+
|
|
1403
|
+
- **The pinned wheel fixture now records mutation-gated evidence for a repeating 13-fold radial
|
|
1404
|
+
profile without claiming gear semantics** (#1085). Runtime recognition remains fail-closed
|
|
1405
|
+
until a separate feature contract has independently sufficient evidence.
|
|
1406
|
+
|
|
1407
|
+
## v0.4.1 — 2026-08-07
|
|
1408
|
+
|
|
1409
|
+
**The recognition trust release.** Automatic drawings now fail closed on unsupported inner
|
|
1410
|
+
profiles, prove semantic coverage for flats, slots and patterns, and retain the measurement
|
|
1411
|
+
identity needed to explain placed, suppressed, dropped and missing definitions. Several real
|
|
1412
|
+
STEP case studies also move from clean-looking but incomplete output to complete drawings or
|
|
1413
|
+
actionable lint.
|
|
1414
|
+
|
|
1415
|
+
### Discouraged (supported)
|
|
1416
|
+
|
|
1417
|
+
- **`Sheet.auto_dimensions()` and `Sheet.add_dimension()` now emit
|
|
1418
|
+
`SoftDeprecationWarning`** (#1043). They remain supported with no removal planned; the
|
|
1419
|
+
warning steers declared scripts toward `authored_dimensions()` plus explicit
|
|
1420
|
+
`dimension(feature, parameter_id)` lines, where omission can mean suppression. Automatic
|
|
1421
|
+
`build_drawing(part)` and the `Sheet.from_part(part)` on-ramp remain silent. See
|
|
1422
|
+
`docs/deprecations.md` for filtering and migration guidance.
|
|
1423
|
+
|
|
1424
|
+
### Added
|
|
1425
|
+
|
|
1426
|
+
- **Finished drawings expose why measurements were omitted and, on covered placement paths,
|
|
1427
|
+
what an annotation measures** (#996/#1002). `Drawing.suppressions()` returns the compiler's
|
|
1428
|
+
omission ledger, `Drawing.measurement_keys(name)` exposes recorded measurement provenance, and
|
|
1429
|
+
`draftwright.audit.diff_builds(before, after)` reports losses, substitutions and candidate
|
|
1430
|
+
suppression explanations. The differential is deliberately a triage aid, not a proof where
|
|
1431
|
+
renderer identity remains incomplete.
|
|
1432
|
+
|
|
1433
|
+
- **Physical-completeness lint now follows semantic correspondence for flats, lone slots and
|
|
1434
|
+
slot patterns** (#1018). Coverage is joined through recognition, IR and compiler identities
|
|
1435
|
+
rather than inferred from label text or page geometry, and distinguishes authored
|
|
1436
|
+
suppression, placement drops, missing definitions and unverifiable provenance.
|
|
1437
|
+
|
|
1438
|
+
- **Full-span floored open channels are recognised and dimensioned as first-class features**
|
|
1439
|
+
(#917). Automatic and declared drawings state the independent overall extent, one wall and
|
|
1440
|
+
channel width, suppress the derived opposite wall, and report any missing member of that
|
|
1441
|
+
defining chain.
|
|
1442
|
+
|
|
1443
|
+
### Fixed
|
|
1444
|
+
|
|
1445
|
+
- **Square and near-square parts retain both independent planar extents** (#997). A plain
|
|
1446
|
+
square plate could previously lose both plan dimensions, while parts up to five percent off
|
|
1447
|
+
square could lose one and be silently represented as square. The unsafe suppression rule is
|
|
1448
|
+
removed; explicit square notation remains tracked separately in #918.
|
|
1449
|
+
|
|
1450
|
+
- **Machined flats retain their physical stock identity from recognition through placement
|
|
1451
|
+
and completeness lint** (#1013/#1015/#1034/#1036). Flats on separate parallel, coaxial or
|
|
1452
|
+
slanted stock no longer collapse into one definition or borrow an opposite face from another
|
|
1453
|
+
stock region. Independent callouts receive clear-margin candidates, while double-D faces on
|
|
1454
|
+
one stock still form one A/F requirement.
|
|
1455
|
+
|
|
1456
|
+
- **Dense callout and step-detail cases keep their complete defining set** (#915). Hole
|
|
1457
|
+
callout batches are reconciled as a queue, detail views fit their actual aspect, step levels
|
|
1458
|
+
retain the supporting-face correspondence needed for truthful crops, and a detail redraws
|
|
1459
|
+
only rungs omitted from its parent view.
|
|
1460
|
+
|
|
1461
|
+
- **Pocket leaders start on the physical opening rim** (#916), removing the spurious inner
|
|
1462
|
+
silhouette crossing while preserving the solved label corridor and approved dimensions on
|
|
1463
|
+
X-, Y- and Z-depth pockets.
|
|
1464
|
+
|
|
1465
|
+
- **Wedge-mounted raised pads survive recognition** (#909). Lower ledges that touch only in
|
|
1466
|
+
plan no longer make the recogniser discard a valid upper pad; true staircase tiers remain
|
|
1467
|
+
excluded.
|
|
1468
|
+
|
|
1469
|
+
- **Annotation-dense detail placement no longer stalls the build** (#1065). Detail views
|
|
1470
|
+
avoid every decomposed annotation shaft, witness, label and item footprint; CTC-02
|
|
1471
|
+
supplies 571 such boxes. The free-rectangle search previously treated that set as tiny
|
|
1472
|
+
and admitted roughly 34 billion candidate rectangles, exhausting the slow tier's
|
|
1473
|
+
ten-minute test budget before export. A compressed-coordinate sweep preserves the same
|
|
1474
|
+
deterministic winning rectangle while completing the real search in seconds.
|
|
1475
|
+
|
|
1476
|
+
- **Through double-D bores are recognised and called out as first-class hole profiles**
|
|
1477
|
+
(#1061). Automatic and declared builds preserve the parent-circle diameter, A/F size,
|
|
1478
|
+
orientation and depth, and render one compound `DOUBLE-D ... A/F` bore callout. Physical
|
|
1479
|
+
critique now accepts that supported inner profile while retaining a separate warning for
|
|
1480
|
+
13 evenly spaced common-circle arcs on the unresolved outer boundary; it does not infer a
|
|
1481
|
+
repeating full profile or a gear standard.
|
|
1482
|
+
|
|
1483
|
+
- **Unsupported internal profiles no longer pass physical-completeness lint silently**
|
|
1484
|
+
(#1058). Inner loops on principal boundary faces are checked against the current
|
|
1485
|
+
circular-hole, rectangular-opening, true-obround, and proven through-double-D vocabulary.
|
|
1486
|
+
Profiles outside it now produce
|
|
1487
|
+
`unrecognised_defining_geometry` and reduce the lint score instead of allowing an
|
|
1488
|
+
envelope-only drawing to score 1.0.
|
|
1489
|
+
|
|
1490
|
+
### Changed
|
|
1491
|
+
|
|
1492
|
+
- **Crowded prismatic step dimensions recover into an enlarged detail view by default**
|
|
1493
|
+
(#909). The automatic `build_drawing` / `make_drawing` / CLI paths and generated
|
|
1494
|
+
`Sheet` scripts now preserve the omitted dimensions instead of returning
|
|
1495
|
+
`step_dim_dropped` unless the caller remembered `detail_view=True`. Pass
|
|
1496
|
+
`detail_view=False` to retain the parent-view-only behavior and its lint warning.
|
|
1497
|
+
|
|
1498
|
+
## v0.4.0 — 2026-08-02
|
|
1499
|
+
|
|
1500
|
+
**The compat-exit release.** Every surface whose documented removal target was 0.4.0 is gone,
|
|
1501
|
+
and every deprecation that remains now says when it goes — in the message the caller sees, not
|
|
1502
|
+
only in a release note. ADR 0005 §4's rule is that an alias carries a tracking issue *and* a
|
|
1503
|
+
removal date, because "a facade with no exit date is a failure mode"; this release is that rule
|
|
1504
|
+
being kept rather than restated. `docs/deprecations.md` is the new index, and
|
|
1505
|
+
`tests/test_deprecation_dates.py` fails any deprecation that names no removal.
|
|
1506
|
+
|
|
1507
|
+
Also lands ADR 0016's declared-dimensioning work (#867): a `dimension(feature, role)` is
|
|
1508
|
+
referential — it names a measurement and carries no number — and an authored set means omission
|
|
1509
|
+
is suppression, enforced at the compiled-plan boundary rather than by a flag renderers check.
|
|
1510
|
+
|
|
1511
|
+
**Read this before upgrading:** two removals break *without a release that warned you*, because
|
|
1512
|
+
their deprecation never appeared in a shipped version. See *Removed (breaking)* below and
|
|
1513
|
+
`docs/deprecations.md`.
|
|
1514
|
+
|
|
1515
|
+
### Removed (breaking)
|
|
1516
|
+
|
|
1517
|
+
Compat surfaces whose documented removal target was 0.4.0 (#720, ADR 0005 §4 — every alias
|
|
1518
|
+
carries a tracking issue *and* a removal date, or the facade is permanent by accident):
|
|
1519
|
+
|
|
1520
|
+
- **The seven `Drawing` compat aliases** — `_named` / `_anno_view` / `_pinned` /
|
|
1521
|
+
`_build_issues`, and `_pattern_callouts` / `_patterned_holes` / `_dropped_callout_diams`.
|
|
1522
|
+
These were private, and the public reads have existed since #699: use `dwg.registry`
|
|
1523
|
+
(`in reg`, `names()`, `issues`, `pinned_names()`) and `dwg.coverage`, or the `Drawing` verbs
|
|
1524
|
+
`annotations()` / `iter_annotations()` / `get_annotation()` / `view_of()`.
|
|
1525
|
+
**Note the asymmetry.** A *read* — `dwg._named` — now raises `AttributeError`. A *write* —
|
|
1526
|
+
`dwg._pinned = {...}` — does **not**: these were properties with setters, and `Drawing` has
|
|
1527
|
+
no `__slots__`, so assignment now quietly creates an unrelated instance attribute that no
|
|
1528
|
+
longer reaches the registry or coverage owner. Writes therefore fail silently rather than
|
|
1529
|
+
loudly. Grep for `\._(named|anno_view|pinned|build_issues|pattern_callouts|patterned_holes|dropped_callout_diams)\b`
|
|
1530
|
+
before upgrading; mutate through `registry.add()` / `pin()` / `record_issue()` /
|
|
1531
|
+
`restore_issues()` and the `CoverageState` methods instead.
|
|
1532
|
+
- **The `draftwright.sheet_dsl` module** — an import alias for `draftwright.sheet` since the
|
|
1533
|
+
#640 rename. Import `Sheet` from `draftwright` or `draftwright.sheet`.
|
|
1534
|
+
- **`generate_script`**, including its `draftwright.__all__` entry. It has raised since #940
|
|
1535
|
+
retired the imperative emitter; it is now simply absent, so the failure is an `ImportError`
|
|
1536
|
+
at the top of a script rather than a `RuntimeError` part-way through one. Use
|
|
1537
|
+
`--script` / `emit_sheet_script`.
|
|
1538
|
+
- **The bespoke `--style imperative` error message.** `--style` itself is unchanged and still
|
|
1539
|
+
accepts its sole value `sheet`; `imperative` is now an unrecognised value like any typo,
|
|
1540
|
+
rather than one carrying its own explanation of the #940 retirement.
|
|
1541
|
+
|
|
1542
|
+
- **Bare dimension-role spellings** — `sheet.dimension(f, "width")`. Use the parameter id,
|
|
1543
|
+
`"width.length"`; `dimension_ids()` on a handle lists the valid ones. The bare role is the
|
|
1544
|
+
*family* spelling: it selects every parameter carrying it, which is how
|
|
1545
|
+
`dimension(step, "step")` quietly declared two measurements. In an authored set, where
|
|
1546
|
+
omission means suppression, silently declaring an extra one is the mirror image of the rule
|
|
1547
|
+
— so it now raises rather than resolving. (A *discriminated* bare role, used with `axis=`,
|
|
1548
|
+
is unaffected: that is how variants like `grid_pitch.length.row` are addressed, and it never
|
|
1549
|
+
warned.)
|
|
1550
|
+
- **The `Sheet.dimension(kind=…, value=…)` call shape** — use `Sheet.measured_dimension(...)`.
|
|
1551
|
+
`dimension` is now solely the ADR 0016 referential verb: it names a feature and a parameter
|
|
1552
|
+
id and reads the value off the geometry.
|
|
1553
|
+
|
|
1554
|
+
Those last two break **without a release that warns you**. They were deprecated after v0.3.9
|
|
1555
|
+
and removed in 0.4.0, so the `DeprecationWarning` never appeared in a released version —
|
|
1556
|
+
upgrading from v0.3.9 or earlier goes straight from working to a raise. That is deliberate
|
|
1557
|
+
(ADR 0016); this entry and `docs/deprecations.md` are the only notice you get, so both
|
|
1558
|
+
failures name their replacement rather than raising about argument counts.
|
|
1559
|
+
|
|
1560
|
+
### Deprecated
|
|
1561
|
+
|
|
1562
|
+
- **The legacy `Drawing.export` shapes now emit `DeprecationWarning`** (#987) — they were
|
|
1563
|
+
announced as deprecated in v0.3.1 and then said nothing at runtime for four minor releases,
|
|
1564
|
+
which would have made their 0.5.0 removal a silent break. Three cases warn:
|
|
1565
|
+
- `export()` with `formats=` **omitted or `None`** — the legacy default, which writes
|
|
1566
|
+
SVG + DXF and returns an `(svg, dxf)` **tuple** rather than the `{format: path}` dict.
|
|
1567
|
+
- the **`svg=` / `dxf=` booleans**. The suggested replacement names the formats *that call*
|
|
1568
|
+
selected, so following it cannot change what gets written.
|
|
1569
|
+
- passing a boolean **alongside** `formats=`, where it is silently ignored — `formats` wins,
|
|
1570
|
+
and now says so.
|
|
1571
|
+
|
|
1572
|
+
**If you promote `DeprecationWarning` to an error, previously-passing exports will now
|
|
1573
|
+
raise.** Migration: `export(out, formats=("svg", "dxf"))` and read the dict. `make_drawing`
|
|
1574
|
+
is unaffected — it returns the same tuple and does not warn.
|
|
1575
|
+
|
|
1576
|
+
### Added
|
|
1577
|
+
|
|
1578
|
+
- **`sheet.add_dimension(feature, role)` — ask the planner to carry one more
|
|
1579
|
+
measurement** (ADR 0016 / #872). Referential: it names a feature and a role and
|
|
1580
|
+
carries **no number**, so the value still comes from the geometry and a size lives in
|
|
1581
|
+
exactly one place. It changes *selection*, not derivation — a request can never
|
|
1582
|
+
introduce a number the part does not have. Requesting something the planner already
|
|
1583
|
+
emits is a deliberate no-op, so a script can ask without first knowing the rule set's
|
|
1584
|
+
mind. `sheet.auto_dimensions()` states the source explicitly (optional in this
|
|
1585
|
+
release; #874 makes it mandatory).
|
|
1586
|
+
- **Suppressing a dimension marks it; it no longer leaks into the callout** (ADR 0016 /
|
|
1587
|
+
#875). `PlannedDimension.suppressed` was honoured at thirteen render sites but not by
|
|
1588
|
+
the compound hole-callout path, so a suppressed counterbore still printed. The group
|
|
1589
|
+
keeps its engineering data either way — what changes is whether a value reaches the
|
|
1590
|
+
page. Suppressing the bore ⌀ while a counterbore, spotface or countersink segment
|
|
1591
|
+
remains now **raises** and names the orphan: `⌀20 THRU ⌴ ⌀32 ↓ 1.5` has no reading with
|
|
1592
|
+
its leading term removed, and silently dropping the segments would discard authored
|
|
1593
|
+
intent while silently restoring the head would make the drawing say something the
|
|
1594
|
+
script does not.
|
|
1595
|
+
- **Addressable dimension identity** (#869/#870/#871): every planned measurement now has
|
|
1596
|
+
a stable `DimensionId(feature, parameter)`, and correlated measurements that must be
|
|
1597
|
+
named as one — a grid pattern's row and column pitch, a step ladder — group into an
|
|
1598
|
+
`AddressableDimension`. This is what a `dimension(...)` line will name, and what
|
|
1599
|
+
suppression and provenance key on.
|
|
1600
|
+
|
|
1601
|
+
### Changed
|
|
1602
|
+
|
|
1603
|
+
- **`Sheet.dimension(kind=…, value=…)` is now `Sheet.measured_dimension(...)`**
|
|
1604
|
+
(ADR 0016 / #873), and `model.declare.authored_dimension` is
|
|
1605
|
+
`model.declare.measured_dimension` to match. This **reserves** the name `dimension` for
|
|
1606
|
+
the referential verb ADR 0016 defines — name a feature and a role, carry no number, let
|
|
1607
|
+
the engine read the value off the geometry — which `Drawing.dimension` already is and
|
|
1608
|
+
`Sheet.dimension` will become. The verb that carries an explicit number needed a name
|
|
1609
|
+
saying so first. The old spelling was a transitional overload during development and is
|
|
1610
|
+
**removed in this same release** (#720) rather than shipping — `Sheet.dimension` is solely
|
|
1611
|
+
the referential verb, and the old keyword call raises with `measured_dimension` named. See
|
|
1612
|
+
*Removed (breaking)* above. Generated AP242 scripts emit `measured_dimension` and so arrive
|
|
1613
|
+
un-deprecated.
|
|
1614
|
+
- **`Sheet` handles address features by identity, not position** (#908/#910/#912). A
|
|
1615
|
+
handle, tolerance, GD&T origin, section request or dimension intent now follows *its*
|
|
1616
|
+
feature through a `features` reorder instead of naming whatever took the slot.
|
|
1617
|
+
Reordering with `reverse()`/`sort()` preserves every reference; deleting or replacing
|
|
1618
|
+
a referenced feature raises rather than silently retargeting a neighbour. `of()` now
|
|
1619
|
+
accepts a handle, and negative indices resolve uniformly across `of()`,
|
|
1620
|
+
`add_dimension()` and the GD&T verbs.
|
|
1621
|
+
|
|
1622
|
+
### Fixed
|
|
1623
|
+
|
|
1624
|
+
- **`sheet.envelope()` measured the file, not the part** (#977). An AP242 STEP import is a
|
|
1625
|
+
compound of the solid *plus its PMI presentation geometry* — annotation planes, leader
|
|
1626
|
+
curves — and the declared verb measured all of it. On the NIST CTC-01 fixture it declared
|
|
1627
|
+
1170 × 650 where the part is 800 × 450: an envelope 370 mm too wide, silently, in anything
|
|
1628
|
+
declared by hand. `step_level()` had the same exposure, offsetting every step position by
|
|
1629
|
+
the annotation overhang. Both now measure the solid body, sharing the helper the engine
|
|
1630
|
+
already used for exactly this (`_analyse` and `Sheet.model`).
|
|
1631
|
+
- **A declared envelope's frame origin sat a half-height below a detected one** (#977). It
|
|
1632
|
+
used `bbox_min.Z` where the detector uses the bbox centre. **Dimension output is unchanged** —
|
|
1633
|
+
envelope sizes derive from `bbox_min`/`bbox_max`, and the overall height is compiled from the
|
|
1634
|
+
model bbox — but `frame.origin` is the generic feature *site*, so **a GD&T control frame,
|
|
1635
|
+
surface finish or note targeting a hand-declared `sheet.envelope()` was anchored at the
|
|
1636
|
+
bottom face rather than the centre, and its leader now moves to the centre**. That is a
|
|
1637
|
+
visible change on drawings carrying such an annotation; drawings without one are unaffected.
|
|
1638
|
+
Scripts generated by `--script` were never affected either way: they bake the detected frame
|
|
1639
|
+
explicitly rather than calling the verb.
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
- **Front-view dimensions join the placement solve instead of committing to the strip**
|
|
1643
|
+
(#894): they previously took strip space before the global solve ran, so a
|
|
1644
|
+
higher-ranked dimension could find its space already gone. Priority only ranks
|
|
1645
|
+
candidates that are *in* the solve.
|
|
1646
|
+
- **A hole callout reads the feature's own `through` fact** (#868) rather than inferring
|
|
1647
|
+
it from whether a depth parameter happens to be present — so a suppressed depth can no
|
|
1648
|
+
longer make a blind hole print `THRU`.
|
|
1649
|
+
- **The balloon ring clears the view it annotates after a hole-table escalation**
|
|
1650
|
+
(#901/#903).
|
|
1651
|
+
|
|
1652
|
+
## v0.3.9 — 2026-07-26
|
|
1653
|
+
|
|
1654
|
+
### Added
|
|
1655
|
+
|
|
1656
|
+
- **Repeated recesses are dimensioned as one pattern, not N competing callouts**
|
|
1657
|
+
(#841): identical blind pockets and identical through-slots now collapse to a single
|
|
1658
|
+
grouped `5× 7.9 × 13.6 × 19 DEEP` / `4× SLOT 8 × 30` leader plus `(n-1)× pitch`
|
|
1659
|
+
dim(s). Previously each member competed for its own size dims and some silently
|
|
1660
|
+
dropped for want of strip room — five declared slots rendered only three length dims.
|
|
1661
|
+
Both new kinds (`PocketPatternFeature`, `SlotPatternFeature`) round-trip every
|
|
1662
|
+
surface: declare (`sheet.pocket_pattern(...)` / `sheet.slot_pattern(...)`),
|
|
1663
|
+
recognition from a real solid (coplanar, same-facing members only), the emitted
|
|
1664
|
+
Sheet script, and the editable surface (`dwg.callout(feature)` + `finalize()`).
|
|
1665
|
+
- **`Sheet.section()` and `Sheet.detail()` — ask for the view you need** (#841/#847):
|
|
1666
|
+
a section A–A auto-fires only for a Z-axis hole with a counterbore, spotface, or
|
|
1667
|
+
blind bottom, so a blind pocket's floor and depth stayed hidden-line-only with no
|
|
1668
|
+
supported way to request a cut. `sheet.section(feature)` / `section(at=y)` /
|
|
1669
|
+
bare `section()` force one (the cut plane is validated to lie strictly inside the
|
|
1670
|
+
part), and `sheet.detail()` exposes the existing `detail_view=True` opt-in as a
|
|
1671
|
+
chainable verb.
|
|
1672
|
+
- **External threads are a first-class declared aspect** (#859): the turned analog of
|
|
1673
|
+
the #764 internal thread — `sheet.step(shaft).thread("M3x0.5")`,
|
|
1674
|
+
`sheet.diameter(...).thread(...)`, and `sheet.boss(...).thread(...)` append the
|
|
1675
|
+
spec to the ⌀ callout (`ø3 M3x0.5`) instead of needing a free-text `.note()`. It
|
|
1676
|
+
composes with `.finish()` for Ra-on-thread, keys the callout bucket on `(⌀, thread)`
|
|
1677
|
+
so a threaded and a plain ø6 stay distinct, and now round-trips through the Sheet
|
|
1678
|
+
emitter — including pattern-member holes, closing the symmetric latent #764 gap.
|
|
1679
|
+
Declaration-only: a plain cylinder is geometrically indistinguishable from a
|
|
1680
|
+
threaded one, so there is no recogniser. *(Known limitation: the incremental
|
|
1681
|
+
`callout`/`finalize(only=…)` paths still dedup thread-blind — #863.)*
|
|
1682
|
+
- **Blind obround pocket recognition, including imported STEP** (#837): the blind
|
|
1683
|
+
counterpart of the #816 through-slot work. A stubby floored obround has side walls
|
|
1684
|
+
too short to pair, so it is recovered from its semicircular end caps — clustering
|
|
1685
|
+
faces by axis proximity so the quarter-cylinder split a STEP importer commonly
|
|
1686
|
+
produces recognises as well as build123d's half-cylinder. A sealed internal void
|
|
1687
|
+
(capped at both ends) is correctly *not* a pocket. A real tuner-jig STEP with five
|
|
1688
|
+
blind pockets ships as a fixture.
|
|
1689
|
+
- **`sheet.slot(...).note(...)` / `sheet.pocket(...).note(...)`** (#841/#845): the
|
|
1690
|
+
slot/pocket handle now anchors a note to its own feature, with no `ref=` needed
|
|
1691
|
+
(an explicit `ref` still forwards, as before).
|
|
1692
|
+
|
|
1693
|
+
### Changed
|
|
1694
|
+
|
|
1695
|
+
- **An anchored note, GD&T frame, or finish relaxes its side instead of silently
|
|
1696
|
+
vanishing** (#841/#855): an annotation declared with an explicit `view=`/`side=`
|
|
1697
|
+
used to drop with only a warning when that strip was full, while the export still
|
|
1698
|
+
reported success. The requested side is now a *preference* — when the strip has no
|
|
1699
|
+
room the placer tries the opposite side, then the two perpendicular sides, taking
|
|
1700
|
+
the first with room (via the same bounds and title-block checks, so it never
|
|
1701
|
+
overshoots). A relaxed placement records an INFO `gdt_side_relaxed` issue naming
|
|
1702
|
+
requested versus actual. Only when no strip fits does it drop.
|
|
1703
|
+
|
|
1704
|
+
### Internal
|
|
1705
|
+
|
|
1706
|
+
- **The state-bus endgame is closed to its permanent seam** (#830/#840): the
|
|
1707
|
+
solve trace is filled into `BuildState` at the one construction site, the redundant
|
|
1708
|
+
part-model re-attach is gone, and the detail view is now *transactional* — geometry
|
|
1709
|
+
is projected at the detail scale and committed only if dimensions land, so
|
|
1710
|
+
`_drop_view_coordinates` has zero engine callers. With those removed, the #817
|
|
1711
|
+
decision-D method-call exemption narrows from a blanket pass to a named
|
|
1712
|
+
`_LAYOUT_SEAM` allowlist (`_add_view`, `_set_view_coordinates`), accepted as the
|
|
1713
|
+
permanent interactive-layout seam; every other private-method call on the drawing
|
|
1714
|
+
is now flagged.
|
|
1715
|
+
- **A draftwright logo set** (#843) — drafting-idiom mark, all text outlined so the
|
|
1716
|
+
SVGs render font-independently; the README now leads with the lockup.
|
|
1717
|
+
- **A worked multi-feature object-reference example** (#853) in
|
|
1718
|
+
`docs/multi-feature-object-reference-workflow.md`.
|
|
1719
|
+
|
|
1720
|
+
## v0.3.8 — 2026-07-23
|
|
1721
|
+
|
|
1722
|
+
### Added
|
|
1723
|
+
|
|
1724
|
+
- **`Drawing.note()` — a public free-text note verb** (#817/#820): place a free-form
|
|
1725
|
+
`Note` at a page point without reaching for the low-level placement primitive —
|
|
1726
|
+
`dwg.note("SEE NOTE 1", at=(x, y))`. This is the safe door for free text that the
|
|
1727
|
+
privatisation below needs.
|
|
1728
|
+
- **Obround (racetrack) through-slot recognition** (#816): a part whose only features
|
|
1729
|
+
are obround through-slots is now recognised, dimensioned, and referenceable for GD&T.
|
|
1730
|
+
Previously such slots were silently undetected — and lint falsely reported the drawing
|
|
1731
|
+
complete. Stubby obrounds, whose straight side walls are too short to pair, are recovered
|
|
1732
|
+
from their two semicircular end caps (a round hole is never mistaken for a slot end).
|
|
1733
|
+
|
|
1734
|
+
### Changed
|
|
1735
|
+
|
|
1736
|
+
- **The generated Sheet script is now self-describing** (#833): `--script --style sheet`
|
|
1737
|
+
emits a feature-census header, section sub-headers with repeat tallies (`8× R50`), and a
|
|
1738
|
+
plain-language comment on each verb line (`# ⌀8 THRU ×4`, `# slot 40 × 120`, `# R50`).
|
|
1739
|
+
All additions are comment-only, so re-run fidelity is unchanged.
|
|
1740
|
+
|
|
1741
|
+
### Deprecated
|
|
1742
|
+
|
|
1743
|
+
- **The low-level `Drawing` placement API is now private — the public surface is
|
|
1744
|
+
safe-by-default** (#817): `add`, `place_dim`, and the view-coordinate / build-state
|
|
1745
|
+
plumbing (`set_view_coordinates`, `drop_view_coordinates`, `attach_part_model`,
|
|
1746
|
+
`attach_solve_trace`, `add_view`, `clear_annotations`) are deprecated in favour of the
|
|
1747
|
+
feature-backed verbs (`callout` / `dimension` / `locate` / `note` / …), which route
|
|
1748
|
+
through the layout solve. Each keeps a `@deprecated` (PEP 702) shim for one release —
|
|
1749
|
+
so type-checkers and IDEs flag call sites, not just a runtime warning — and is slated
|
|
1750
|
+
for removal in ~0.5.0.
|
|
1751
|
+
|
|
1752
|
+
### Internal
|
|
1753
|
+
|
|
1754
|
+
- **`AGENTS.md` — an AI-agent usage guide** (#818) with an executable check, steering
|
|
1755
|
+
agents toward the safe declarative surface rather than the low-level primitives.
|
|
1756
|
+
- **Coverage reporting is governed and a Codecov badge added** (#825/#832).
|
|
1757
|
+
|
|
1758
|
+
## v0.3.7 — 2026-07-21
|
|
1759
|
+
|
|
1760
|
+
### Fixed
|
|
1761
|
+
|
|
1762
|
+
- **Turned ⌀ leaders point at the feature, not a corner or across the body**
|
|
1763
|
+
(#794/#798): the diameter callouts on a turned part now centre on the step's
|
|
1764
|
+
mid-length (a boss keeps its frame origin; a ⌀ shared by disjoint steps centres
|
|
1765
|
+
on the longest run), so the arrow lands on the middle of the feature's edge
|
|
1766
|
+
rather than a step corner. A leader that would otherwise cut diagonally through
|
|
1767
|
+
the body — a nested or end feature such as a ⌀6 boss stub — is re-routed out to
|
|
1768
|
+
the nearest clear margin (axis-aware: X-turned → left/right, Z-turned → top/
|
|
1769
|
+
bottom), pointing straight at the feature instead of clipping the silhouette. A
|
|
1770
|
+
re-route that can't be placed clear-and-safe is restored and flagged, and a
|
|
1771
|
+
pinned leader is never moved.
|
|
1772
|
+
|
|
1773
|
+
### Added
|
|
1774
|
+
|
|
1775
|
+
- **`leader_crosses_silhouette` lint notice** (#796): an info-level structural
|
|
1776
|
+
notice when a leader shaft passes *through* the projected part body (as opposed
|
|
1777
|
+
to a hole callout legitimately exiting an internal hole), so the gap is
|
|
1778
|
+
observable even where routing cannot clear it.
|
|
1779
|
+
|
|
1780
|
+
## v0.3.6 — 2026-07-21
|
|
1781
|
+
|
|
1782
|
+
### Fixed
|
|
1783
|
+
|
|
1784
|
+
- **`Sheet.step(boss)` on a prismatic part fails loudly instead of silently
|
|
1785
|
+
dropping the height** (#631): declaring a turned `.step()` at a cylinder that is
|
|
1786
|
+
really an external boss set `orientation="z"`, which made `render_height_ladder`
|
|
1787
|
+
suppress the overall-height dim on the assumption the OD/step chain conveyed it —
|
|
1788
|
+
but on a prismatic box that chain never renders, so the height vanished and
|
|
1789
|
+
nothing replaced it (11 → 10 annotations). The build now detects a `StepFeature`
|
|
1790
|
+
coincident with a `BossFeature` (same axis, origin, diameter) — a combination
|
|
1791
|
+
that can never be legitimate — and raises a clear `ValueError` pointing to
|
|
1792
|
+
`.boss()` (which renders its own ø and height per #632). Legitimate turned shafts
|
|
1793
|
+
have steps but no coincident boss, so they are unaffected.
|
|
1794
|
+
- **`detail_view=True` no longer a silent no-op when the detail can't be placed**
|
|
1795
|
+
(#630): a part whose lint recommends a detail view (`step_dim_dropped`) but whose
|
|
1796
|
+
crowded band is full-width (e.g. a shelled cover's stacked face levels) can't be
|
|
1797
|
+
enlarged legibly *and* still fit alongside the main views — so `detail_view=True`
|
|
1798
|
+
produced a drawing byte-identical to `False`, silently ignoring the opt-in. It
|
|
1799
|
+
now records a `detail_unplaceable` warning naming the reason and an actionable
|
|
1800
|
+
remedy (dimension manually / move onto its own sheet), so the opt-in is
|
|
1801
|
+
observable. Parts whose detail *does* fit are unchanged.
|
|
1802
|
+
- **Imperative `--script` round-trips the title-block fields + sheet furniture**
|
|
1803
|
+
(#775): the imperative flavour reproduced only title/number/tolerance/drawn_by/
|
|
1804
|
+
scale/page, dropping the `material`/`date`/`revision`/`company` fields (#766) and
|
|
1805
|
+
the `frame`/`zones`/`projection` furniture (#767/#768/#769) — so a regenerated
|
|
1806
|
+
imperative script didn't match the direct CLI. They now ride the emitted script's
|
|
1807
|
+
cog config block and its `build_drawing(...)` call (the Sheet flavour already
|
|
1808
|
+
round-tripped them), and the CLI forwards them to `generate_script`.
|
|
1809
|
+
|
|
1810
|
+
### Internal
|
|
1811
|
+
|
|
1812
|
+
- **Fast-tier dense-sheet canary for the #733/#734 strip-pressure regression**
|
|
1813
|
+
(#737): a synthetic contended-front-strip fixture that drops a step-height
|
|
1814
|
+
principal dim on the pre-#734 commit and stays clean on `main` — closing the
|
|
1815
|
+
fast-tier gap the #733 regression fell through (only the CI-only slow CTC
|
|
1816
|
+
fixtures exercised real strip pressure before).
|
|
1817
|
+
- **Layout-hypothesis fuzz tier is now a reproducible PR gate** (#692):
|
|
1818
|
+
`derandomize=True` makes every run generate the same fixed example set (with
|
|
1819
|
+
`print_blob` for paste-able reproduction), so a failure recurs deterministically
|
|
1820
|
+
instead of surfacing on a seed-dependent minority of runs; exploratory fuzzing
|
|
1821
|
+
moves behind `DRAFTWRIGHT_FUZZ_EXPLORE=1`. The two `test_make_drawing.py` xdist
|
|
1822
|
+
observations (#669) were investigated and found non-reproducible — both tests are
|
|
1823
|
+
non-flaky by construction/measurement on current `main`.
|
|
1824
|
+
|
|
1825
|
+
## v0.3.5 — 2026-07-20
|
|
1826
|
+
|
|
1827
|
+
### Fixed
|
|
1828
|
+
|
|
1829
|
+
- **Generated `Sheet` script round-trips `--frame` / `--zones` / `--projection`**:
|
|
1830
|
+
the sheet-furniture flags added in #767/#768/#769 were not emitted into the
|
|
1831
|
+
generated `Sheet(...)` constructor (nor forwarded by the CLI's `--script` path),
|
|
1832
|
+
so a regenerated script dropped the border / zone ruler / projection symbol —
|
|
1833
|
+
the script no longer matched the direct CLI drawing. The emitter now emits
|
|
1834
|
+
`frame=True` / `zones=True` / `projection=…` when set (a plain drawing keeps a
|
|
1835
|
+
clean constructor), and the CLI forwards them to `generate_sheet_script`.
|
|
1836
|
+
|
|
1837
|
+
### Added
|
|
1838
|
+
|
|
1839
|
+
- **ISO 5457 zone-grid border ruler** (#768): `build_drawing(zones=True)` /
|
|
1840
|
+
`Sheet(zones=True)` / `--zones` draws the grid reference system — numbers 1..
|
|
1841
|
+
along the top/bottom edges, letters A.. (skipping I/O) down the sides — in the
|
|
1842
|
+
band between the frame and the page edge, with the standard division count per
|
|
1843
|
+
A-series page (~50 mm zones). Implies a frame (the ticks sit on it). Off by
|
|
1844
|
+
default → byte-identical. The border ticks are lint-exempt like the frame; the
|
|
1845
|
+
labels are exempt only from the page-bounds check (they legitimately sit outside
|
|
1846
|
+
the drawable), still covered by overlap lint.
|
|
1847
|
+
- **Projection-method symbol** (#769): `build_drawing(projection="third"|"first")` /
|
|
1848
|
+
`Sheet(projection=…)` / `--projection` draws the ISO 5456-2 third-/first-angle
|
|
1849
|
+
glyph in the reserved title-block band (above the title block). Uses the new
|
|
1850
|
+
`ProjectionSymbol` primitive from build123d-drafting-helpers **0.14.1** (the pin
|
|
1851
|
+
is bumped). Off by default → byte-identical. Unlike the page-spanning frame, the
|
|
1852
|
+
small well-placed glyph is *not* lint-exempt — lint covers it so a future
|
|
1853
|
+
mispositioning is caught.
|
|
1854
|
+
- **Opt-in drawn sheet frame / border** (#767): `build_drawing(frame=True)` /
|
|
1855
|
+
`Sheet(frame=True)` / `--frame` draws a border rectangle at the page margin. It's
|
|
1856
|
+
the *content boundary* (Option B), not a rectangle over the drawing: turning it on
|
|
1857
|
+
raises the effective content margin, and because `compose._layout_geometry` is the
|
|
1858
|
+
single authority shared by scale/page selection **and** placement, the reservation
|
|
1859
|
+
flows through `choose_scale` — so a framed drawing may pick a smaller scale / larger
|
|
1860
|
+
page (ADR 0004), with content clearing the border. Default `frame=False` is
|
|
1861
|
+
byte-identical (guarded by the golden + layout-cleanliness suites). The page-spanning
|
|
1862
|
+
border carries an `is_sheet_frame` rider so lint skips it.
|
|
1863
|
+
|
|
1864
|
+
## v0.3.4 — 2026-07-20
|
|
1865
|
+
|
|
1866
|
+
### Changed
|
|
1867
|
+
|
|
1868
|
+
- **Imperative `--script` output defaults to PDF and the modern export form**
|
|
1869
|
+
(#709). **Breaking** for regenerated imperative scripts: without `-f`, a
|
|
1870
|
+
regenerated script now writes `<stem>.pdf` (was SVG+DXF via the deprecated
|
|
1871
|
+
legacy tuple), and the script-visible variables changed from
|
|
1872
|
+
`svg_path, dxf_path` to a `paths` dict printed in the requested-format order.
|
|
1873
|
+
This aligns the imperative flavour with the Sheet flavour and the direct CLI,
|
|
1874
|
+
which have defaulted to PDF since #702/#288. Migration: regenerate with
|
|
1875
|
+
`--format svg,dxf` to keep the old outputs. Previously-generated scripts are
|
|
1876
|
+
unaffected (they carry their own export lines).
|
|
1877
|
+
- **`finalize()` drains in the auto-pass's order** (#699 slice b): both build
|
|
1878
|
+
paths now execute the orchestrator's one canonical `_PASS_SEQUENCE` (via the
|
|
1879
|
+
shared `run_stages`), removing the hand-mirrored second orchestration in
|
|
1880
|
+
`Drawing._drain_intents`. For the deferred/finalize path this reorders three
|
|
1881
|
+
things toward auto-pass parity: the turned diameter/step-length set-solves now
|
|
1882
|
+
place *before* the corridor drain (matching the auto-pass's obstacle
|
|
1883
|
+
visibility); slots register after them; and the register-only height-ladder /
|
|
1884
|
+
step-position stages register *after* locations — observable too, since
|
|
1885
|
+
registration order decides corridor key-creation (= drain) order and
|
|
1886
|
+
same-priority tie-breaks (Codex review; the new order is exactly the
|
|
1887
|
+
auto-pass's). Recompose output may shift accordingly; the auto-pass order is
|
|
1888
|
+
unchanged.
|
|
1889
|
+
- **`Sheet.export` speaks the modern export API** (#702): it now takes
|
|
1890
|
+
`formats=` (any of svg/dxf/pdf/png, default **PDF** — matching the CLI
|
|
1891
|
+
default) and `dpi=`, and returns the `{format: path}` dict. Previously it
|
|
1892
|
+
rode the deprecated legacy path, could only write SVG+DXF — the flagship
|
|
1893
|
+
facade couldn't produce a PDF — and returned the old `(svg_path, dxf_path)`
|
|
1894
|
+
tuple. **Breaking** for callers unpacking that tuple: use
|
|
1895
|
+
`sheet.export(stem, formats=("svg", "dxf"))` and read the dict.
|
|
1896
|
+
|
|
1897
|
+
### Added
|
|
1898
|
+
|
|
1899
|
+
- **Solve-trace / explain mode** (#736, from the #733 post-mortem): opt-in
|
|
1900
|
+
observability for strip placement. `build_drawing(trace=…)` or
|
|
1901
|
+
`DRAFTWRIGHT_TRACE=<path-or-dir>` writes ONE JSON file per build (schema v2)
|
|
1902
|
+
with two record types: `solves` — every corridor solve's key, strip bounds,
|
|
1903
|
+
candidate set, the obstacles that carved the strip (with owning annotation
|
|
1904
|
+
names), the free segments, and each candidate's outcome (placed /
|
|
1905
|
+
dropped-with-reason / deduped / promoted / deferred-to-post-drain) — and
|
|
1906
|
+
`pass_events` — the standalone strip passes plus the *immediate* placers
|
|
1907
|
+
(post-drain machined-feature leader callouts, the turned diameter row/column
|
|
1908
|
+
and step-length set-solves), each with per-item placed/dropped outcomes. So
|
|
1909
|
+
"why did X drop" is one `jq` query (`.solves[].outcomes[]` /
|
|
1910
|
+
`.pass_events[].items[]`). A `placement_unsatisfiable` strip-full drop now
|
|
1911
|
+
also names the top occupants in its lint message (`…strip full; occupied
|
|
1912
|
+
by: …`). Recording-only: an unwritable path logs a warning (never aborts a
|
|
1913
|
+
build), writes are atomic, and the recorder joins `finalize()`'s #647
|
|
1914
|
+
rollback. Default off; zero output change, nil cost when off.
|
|
1915
|
+
|
|
1916
|
+
- **`draftwright.model.authored_dimension`** (#704): the IR constructor behind
|
|
1917
|
+
`Sheet.dimension()`, extracted so `build_drawing(model=…)` callers can author
|
|
1918
|
+
a pre-measured drafting dimension without the `Sheet` façade.
|
|
1919
|
+
|
|
1920
|
+
### Added
|
|
1921
|
+
|
|
1922
|
+
- **Object-reference script workflow: docs + an inline tip** (#770/#771): a
|
|
1923
|
+
generated `Sheet` script from a **live-source** input (a `module:attr` /
|
|
1924
|
+
`file.py:attr` object spec, or a build123d object) now carries an inline tip
|
|
1925
|
+
showing how to swap each detected-numbers line for a reference to your object
|
|
1926
|
+
(ADR 0011 declare — the size is read off the object). A STEP-sourced script is
|
|
1927
|
+
unchanged (byte-stable — no object to reference). The README documents the full
|
|
1928
|
+
from-a-part-to-an-object-referenced-script workflow.
|
|
1929
|
+
- **Knurl callout verb** (#765): `sheet.diameter(shaft).knurl("0.8")` →
|
|
1930
|
+
`KNURL 0.8 STRAIGHT` (or `.knurl("0.8", "DIAMOND")`). Named sugar over
|
|
1931
|
+
`.note()` with canonical formatting — a knurl is a text callout on a leader,
|
|
1932
|
+
not modelled geometry, so it flows through the existing note path (no new
|
|
1933
|
+
IR/render).
|
|
1934
|
+
- **Standing ISO 7200 title-block fields** (#766): `material`, `date`, `revision`,
|
|
1935
|
+
and `company` (legal owner) are now first-class — settable on `build_drawing` /
|
|
1936
|
+
`make_drawing`, the `Sheet(...)` constructor, and the CLI (`--material` /
|
|
1937
|
+
`--date` / `--revision` / `--company`), and emitted into the generated `Sheet`
|
|
1938
|
+
script when non-default so a re-run reproduces them. Defaults preserve the prior
|
|
1939
|
+
output (revision `A`, the rest blank). The `revision`/`legal_owner` cells the
|
|
1940
|
+
renderer previously hardcoded now flow from these. (The imperative `--script`
|
|
1941
|
+
flavour's title-block round-trip of these fields is a follow-up.)
|
|
1942
|
+
- **First-class thread/tap callout on a hole** (#764): ``sheet.hole(...).thread("M3x0.5")``
|
|
1943
|
+
(and ``declare.hole(..., thread=)``) folds a tap/thread spec onto the hole's existing
|
|
1944
|
+
compound leader (e.g. ``ø2.5 THRU M3x0.5``) — a structured aspect that round-trips, so
|
|
1945
|
+
``.thread(...).finish(...)`` yields Ra-on-thread. A declaration-only aspect (ADR 0011
|
|
1946
|
+
side-layer: threads are cosmetic, not modelled geometry — no recogniser). The layout
|
|
1947
|
+
width estimator (``_est_planned_bore_callout_width``) now accounts for the thread text so
|
|
1948
|
+
the wider callout is reserved room and not dropped (the #261 estimator/render agreement).
|
|
1949
|
+
|
|
1950
|
+
### Fixed
|
|
1951
|
+
|
|
1952
|
+
- **Generated imperative script reconstructs side-drilled hole locations**
|
|
1953
|
+
(#426/#133): an X/Y-axis (side-drilled) bore gets `dim_loc_*` position dims in
|
|
1954
|
+
the direct build, but the `--script` emitter emitted a gap comment instead of a
|
|
1955
|
+
`locate()` for non-Z holes (because `locate()`/`render_locations` are Z-plan
|
|
1956
|
+
only, #133). The emitter now emits `dwg.locate(f)` for holes on any axis;
|
|
1957
|
+
`finalize()` routes by the feature's axis — Z-plan holes drain through
|
|
1958
|
+
`render_locations` as before, side-drilled bores through the whole-model
|
|
1959
|
+
`_locate_off_axis_holes` pass (registered at the auto-pass's own
|
|
1960
|
+
`off_axis_across`/`off_axis_along` stages, placed at the shared drain). The
|
|
1961
|
+
Z-only `locate()` live contract is untouched (side-drilled locates never reach
|
|
1962
|
+
it — they route to the off-axis stages). Closes the last direct-vs-generated
|
|
1963
|
+
script parity gap tracked by #426.
|
|
1964
|
+
- **Generated imperative script reconstructs rotational furniture** (#426/#424):
|
|
1965
|
+
a turned/cylindrical part's `dwg.model()` carries a `RotationalFeature`, but the
|
|
1966
|
+
`--script` emitter parked it in the gap-comment list, so an executed
|
|
1967
|
+
reconstruction of e.g. a plain cylinder was missing `dim_od` and the
|
|
1968
|
+
`centerline_front`/`centerline_side` marks the direct build draws. A new
|
|
1969
|
+
`Drawing.rotational(feature)` add-verb records the intent, and `finalize()`
|
|
1970
|
+
drains it through the shared whole-model `render_rotational` at the auto-pass's
|
|
1971
|
+
own `"rotational"` stage — byte-identical to the direct build (no `only=` subset,
|
|
1972
|
+
fixed literal names, so no naming-seam or `⊇`-vs-`==` gap). The emitter now emits
|
|
1973
|
+
`dwg.rotational(f)` for rotational features. Closes the rotational half of the
|
|
1974
|
+
direct-vs-generated-script convergence.
|
|
1975
|
+
- **Emitted `Sheet` script now faithfully reproduces the direct CLI drawing**
|
|
1976
|
+
(#707): the divergence reported against 0.3.3 on the Maquetto GRM-03 part was
|
|
1977
|
+
closed by #709 (script `--format` forwarding) + #661 (finalize detail drain).
|
|
1978
|
+
Locked with a vendored-fixture regression that asserts the full invariant the
|
|
1979
|
+
issue named — same views, annotation inventory, page, scale **and** lint
|
|
1980
|
+
between `build_drawing(...)` and the executed emitted `Sheet` — not just the
|
|
1981
|
+
annotation signature the synthetic parity cases check.
|
|
1982
|
+
- **`_largest_empty_rect` no longer blows up on crowded detail views** (#661):
|
|
1983
|
+
the largest-empty-rectangle placer enumerated every candidate rectangle
|
|
1984
|
+
(O(N⁴) in the coordinate-cut count) — fine for the iso view's handful of
|
|
1985
|
+
obstacles, but the detail-view placer feeds it *every* placed-annotation
|
|
1986
|
+
footprint, so a two-detail turned part reached ~70 obstacles and spent ~13 s
|
|
1987
|
+
in a single call (multi-minute on the slower Windows CI runners, which tipped
|
|
1988
|
+
some jobs over their wall-clock budget). It now skips candidates that provably
|
|
1989
|
+
can't beat the best found so far (a `bisect` past every too-narrow pair, an
|
|
1990
|
+
early `break` once even the widest is too small): the same exact result and
|
|
1991
|
+
tie-break — verified identical to the naïve search across 3 000 random cases —
|
|
1992
|
+
at ~85× the speed on the pathological input (12.6 s → 0.15 s).
|
|
1993
|
+
- **Detail-view height demotion is pin- and provenance-safe** (#661, user
|
|
1994
|
+
review): when a crowded prismatic detail needs the overall-height dim's room it
|
|
1995
|
+
is demoted and the detail retried, but (a) the canonical `dim_height` name was
|
|
1996
|
+
handed to that retry unconditionally — a *pinned* or user-replaced height could
|
|
1997
|
+
be removed; it now passes the same pin/label guards as the generalised
|
|
1998
|
+
`dim_length{n}` path (a pin, ADR 0012, is never demoted), and (b) if the retry
|
|
1999
|
+
also failed, the restore re-added only object/name/view, orphaning the dim from
|
|
2000
|
+
its envelope feature (lost `annotations_of`/`drop`/re-discovery); it now
|
|
2001
|
+
snapshots and restores the feature provenance and pin too.
|
|
2002
|
+
- **`finalize()` resolves queued detail requests — detail views now exist on the
|
|
2003
|
+
edit path** (#661): the finalize drain was missing the auto pass's
|
|
2004
|
+
`detail_request`/`details` stages, so a crowded turned head's queued
|
|
2005
|
+
`DetailRequest` died with the per-run context and a prismatic
|
|
2006
|
+
`detail_view=True` build never even queued one — generated scripts silently
|
|
2007
|
+
lost every DETAIL A/B view. `build_drawing(detail_view=…)` is now persisted on
|
|
2008
|
+
the build state so the drain gates the prismatic request exactly as the auto
|
|
2009
|
+
pass does; the details stage re-projects the iso at sheet scale for the
|
|
2010
|
+
free-rectangle search and refits it after (mirroring the auto pass's ordering,
|
|
2011
|
+
where details place before the iso is fitted); and the overall-height demotion
|
|
2012
|
+
retry now finds the height dim by its envelope attribution, not only the
|
|
2013
|
+
auto-pass `dim_height` name. Three script-parity characterisation tests
|
|
2014
|
+
(single detail, two details, turned head) flip from xfail to passing.
|
|
2015
|
+
- **Y-turned stepped shafts no longer crash** (#661): `render_step_lengths`
|
|
2016
|
+
projected every step span into the front view, where a Y-axis span is end-on
|
|
2017
|
+
(a point) — `Dimension` then raised "start and end points must be different"
|
|
2018
|
+
on BOTH the direct build and a generated script's finalize. Y-axis steps are
|
|
2019
|
+
now skipped (no step render pipeline consumes Y, #731 — mirroring
|
|
2020
|
+
`render_diameters`' x/z bucketing), the emitter flags the gap as a comment
|
|
2021
|
+
instead of emitting an unreplayable `dimension()` verb, and a hand-written
|
|
2022
|
+
Y step-length intent live-replays (surfacing the verb's own behaviour) rather
|
|
2023
|
+
than vanishing into the routed no-op. The Y-axis script-parity
|
|
2024
|
+
characterisation test flips from xfail to passing.
|
|
2025
|
+
- **Boss heights are modeled, rendered, and coverage-checked** (#632): detected
|
|
2026
|
+
and object-declared cylindrical bosses now carry their axial extent through
|
|
2027
|
+
`BossFeature` and the dimension planner. Prismatic bosses receive a linear
|
|
2028
|
+
height dimension in a profile view in addition to their end-on diameter
|
|
2029
|
+
leader. `Drawing.lint()` reconciles that modeled height against the live
|
|
2030
|
+
feature-owned `Dimension`, reporting `boss_height_missing` if it is removed
|
|
2031
|
+
or otherwise absent (demoted to `info` on assembly drawings). This closes the
|
|
2032
|
+
declarative false-negative where a boss's diameter and the overall envelope
|
|
2033
|
+
were documented but its own independent height was not.
|
|
2034
|
+
|
|
2035
|
+
- **`--format` now reaches `--script` output** (#709, from the #702 adversarial
|
|
2036
|
+
review): `--script -f svg` used to silently emit a PDF-producing script — the
|
|
2037
|
+
CLI parsed the flag but never forwarded it. Both emitters now thread it
|
|
2038
|
+
through: the Sheet script emits `sheet.export(stem, formats=(…,))` when
|
|
2039
|
+
non-default (bare call for the PDF default), the imperative template embeds
|
|
2040
|
+
the requested tuple and prints in the **requested** order, and
|
|
2041
|
+
`generate_script` / `generate_sheet_script` grow a `formats=` parameter. The
|
|
2042
|
+
dormant script-parity characterisation module
|
|
2043
|
+
(`test_script_detail_parity.py`) is also un-skipped so its strict xfails give
|
|
2044
|
+
the remaining gaps CI signal.
|
|
2045
|
+
|
|
2046
|
+
- **Authored fillet, flat, groove, pocket, plate and slot tolerances now render**
|
|
2047
|
+
(#725/#726/#727/#728/#729/#730 / #698): the four leader-callout kinds join
|
|
2048
|
+
`_CONVENTION` and their renderers (`render_fillets`/`render_flats`/
|
|
2049
|
+
`render_grooves`/`render_pockets`) — and the plate-thickness and slot
|
|
2050
|
+
width/length linear passes
|
|
2051
|
+
(`render_plates`/`render_slots`, explicit `"linear"` entries) — consume the
|
|
2052
|
+
planner's `DimensionGroup`s, binding each
|
|
2053
|
+
planned dim explicitly by `(role, kind)` — so a `decorations`-authored ± /
|
|
2054
|
+
limit tolerance reaches the placed callout (`R8 ±0.1`, `17 ±0.2 A/F`,
|
|
2055
|
+
`4 ±0.1 WIDE × ø16 ±0.5`, `18 ±0.2 × 30 ±0.2 × 5 ±0.2 DEEP`, a `10 ±0.1`
|
|
2056
|
+
thickness dim, an `8 ±0.1` slot width; on a
|
|
2057
|
+
multi-value label each suffix rides its own number). Previously all six
|
|
2058
|
+
passes formatted raw feature fields and silently dropped it — the latent #629
|
|
2059
|
+
bug class the ADR 0015 bypass list documents. The fillet `n× R` and flat
|
|
2060
|
+
double-D/hex collapses stay render-side (first-authored tolerance wins, the
|
|
2061
|
+
`render_diameters` precedent); a pocket's three values — and a slot's
|
|
2062
|
+
width + length — share one authored
|
|
2063
|
+
tolerance (all kind `"length"`). The slot's model-derived datum position dim
|
|
2064
|
+
and its corridor/immediate placement mechanics are untouched. Untolerated
|
|
2065
|
+
labels/views/placement are unchanged.
|
|
2066
|
+
- **Authored chamfer tolerances now render** (#724 / #698): `render_chamfers`
|
|
2067
|
+
consumes the planner's `DimensionGroup` (chamfer joins `_CONVENTION` as a
|
|
2068
|
+
leader), so a `decorations`-authored ± / limit tolerance on a chamfer leg
|
|
2069
|
+
reaches the placed callout (`C12 ±0.2`). Previously the pass formatted raw
|
|
2070
|
+
feature fields and silently dropped it — the latent #629 bug class the ADR
|
|
2071
|
+
0015 bypass list documents. Untolerated chamfer labels/views are unchanged.
|
|
2072
|
+
- **`model.chamfer(face=…)` rejects a non-planar face** (#704): the declared
|
|
2073
|
+
front-end silently accepted a curved face (`normal_at()` does not fail on
|
|
2074
|
+
one) and read garbage legs off it — e.g. a fillet or countersink face became
|
|
2075
|
+
a bogus `ChamferFeature`. It now raises the documented `ValueError`, using
|
|
2076
|
+
the recogniser's own planarity gate (`classify_bevel`), so declared and
|
|
2077
|
+
detected chamfers classify identically by construction.
|
|
2078
|
+
|
|
2079
|
+
### Fixed
|
|
2080
|
+
|
|
2081
|
+
- **CTC-02/04 no longer drop step-height / overall-height dims** (#733): when
|
|
2082
|
+
the height ladder joined the corridor solve (#689) it silently moved from
|
|
2083
|
+
"places early" to "registers early, places at the drain" — so the immediate
|
|
2084
|
+
machined-feature leader callouts (pockets on CTC-04) filled the front-right
|
|
2085
|
+
strip first and the FORCED principal dims hard-dropped
|
|
2086
|
+
(`placement_unsatisfiable`), a priority inversion the old stage ordering had
|
|
2087
|
+
prevented implicitly. The leader-callout stages (chamfers/fillets/flats/
|
|
2088
|
+
pockets) now sit **after the corridor drain** in `_PASS_SEQUENCE` (joining
|
|
2089
|
+
grooves, which already placed post-drain for exactly this reason): principal
|
|
2090
|
+
dims win by construction, and a callout with no clear room yields with a
|
|
2091
|
+
warning, never a principal-dim error. Callout leaders may shift (they now
|
|
2092
|
+
route around the drained dims); on the `hex_bar` golden this *recovers* a
|
|
2093
|
+
silently starved `m_env_width` envelope dim.
|
|
2094
|
+
|
|
2095
|
+
### Removed
|
|
2096
|
+
|
|
2097
|
+
- **Three orphaned root exports** (#704): `draftwright.recognise_face_levels`
|
|
2098
|
+
(one recogniser of ~12 — incoherent as a top-level surface; import it from
|
|
2099
|
+
`draftwright.recognition`), `draftwright.dedup_diams` (an analysis internal),
|
|
2100
|
+
and `draftwright.fix_svg_page_size` (still available from `draftwright.export`
|
|
2101
|
+
and the `draftwright.make_drawing` facade). None had any internal or test
|
|
2102
|
+
consumer via the root API.
|
|
2103
|
+
|
|
2104
|
+
### Deprecated
|
|
2105
|
+
|
|
2106
|
+
- **The seven `Drawing` compat aliases** (`_named`/`_anno_view`/`_pinned`/
|
|
2107
|
+
`_build_issues`/`_pattern_callouts`/`_patterned_holes`/
|
|
2108
|
+
`_dropped_callout_diams`) are formally on notice (#699 slice c, tracked by
|
|
2109
|
+
#720): removal target **0.4.0**, per ADR 0005 §4. Read through the public
|
|
2110
|
+
surface instead — `annotations()`, `iter_annotations()`, `get_annotation()`,
|
|
2111
|
+
`view_of()`, `registry.pinned_names()`/`is_pinned()`, and the new
|
|
2112
|
+
`registry.issues`. All external production and test call sites in this repo
|
|
2113
|
+
are already redirected (`drawing.py` internals ride the aliases until the
|
|
2114
|
+
#720 deletion).
|
|
2115
|
+
- **`draftwright.sheet_dsl`** (belated announcement — the alias shim shipped
|
|
2116
|
+
in 0.3.1 when #640 renamed the module to `draftwright.sheet`): importing it
|
|
2117
|
+
warns; it will be removed in **0.4.0**. Import from `draftwright.sheet`, or
|
|
2118
|
+
just `from draftwright import Sheet`.
|
|
2119
|
+
|
|
2120
|
+
## v0.3.3 — 2026-07-18
|
|
2121
|
+
|
|
2122
|
+
The **layout-quality release**: the occupancy model gets honest about ink shape,
|
|
2123
|
+
the last solver-invisible pass joins the corridor solve, and crossed labels shift
|
|
2124
|
+
themselves clear. Also completes the #635 consolidation epic (ADR 0005 fully
|
|
2125
|
+
executed; ADR 0009's no-invisible-occupant guarantee now holds by construction
|
|
2126
|
+
for every auto-pass).
|
|
2127
|
+
|
|
2128
|
+
### Added
|
|
2129
|
+
|
|
2130
|
+
- **Witness-crossing label shifts** (#690): a dimension label crossed by another
|
|
2131
|
+
dimension's witness stroke now shifts along its own line to clear it — a
|
|
2132
|
+
deterministic post-drain pass using the repair machinery (destination-aware,
|
|
2133
|
+
axis-aligned only, pinned dims exempt).
|
|
2134
|
+
|
|
2135
|
+
### Changed
|
|
2136
|
+
|
|
2137
|
+
- **L-shaped occupancy** (#685): placement obstacles decompose into per-stroke
|
|
2138
|
+
boxes + label box (helpers ≥0.14 `segments`) instead of one hull, with
|
|
2139
|
+
preset-aware arrowhead pads. View-corner contention between perpendicular
|
|
2140
|
+
strips disappears by construction (a plate-thickness dim returns to its
|
|
2141
|
+
natural strip); packing tightens. The cleanliness ratchet mirrors the model —
|
|
2142
|
+
only transverse stroke crossings are exempt, so parallel overprints and label
|
|
2143
|
+
contacts are detected honestly (twelve hull-artifact allowlist entries burned
|
|
2144
|
+
down; the legitimate shared-datum running-dimension pairs are documented).
|
|
2145
|
+
- **Height ladder joins the corridor solve** (#636): step heights + overall
|
|
2146
|
+
height are corridor candidates (the leapfrog witness cursor survives as a
|
|
2147
|
+
deterministic build-time chain; the overall height stacks outermost by
|
|
2148
|
+
construction and packs tighter). An explicitly-requested crowded-step detail
|
|
2149
|
+
view now *deliberately* demotes the overall-height dim when the sheet cannot
|
|
2150
|
+
hold both (previously the carve dropped it silently); a Y-drilled hole's Z
|
|
2151
|
+
location joins the front running ladder per the documented routing.
|
|
2152
|
+
- **One typed `BuildState`** (#639): the drawing's build context (analysis,
|
|
2153
|
+
part model, lint geometry caches) consolidates into a single object filled at
|
|
2154
|
+
one builder site, single-writer-guarded; the render passes make zero private
|
|
2155
|
+
`Drawing` reads (fail-closed empty allowlist).
|
|
2156
|
+
|
|
2157
|
+
### Fixed
|
|
2158
|
+
|
|
2159
|
+
- A prismatic detail view no longer loses both the detail *and* the height dim
|
|
2160
|
+
when space is tight (transactional demotion).
|
|
2161
|
+
- The GD&T alternate-strip fallback defers until every corridor has drained, so
|
|
2162
|
+
it can never preempt a sibling strip's reserved corner.
|
|
2163
|
+
|
|
2164
|
+
## v0.3.2 — 2026-07-18
|
|
2165
|
+
|
|
2166
|
+
The **performance release**: the #602 perf loop (six PRs) plus the
|
|
2167
|
+
build123d-drafting-helpers 0.14 upgrade. A dimension-dense drawing now builds
|
|
2168
|
+
roughly **14× faster** than v0.3.1 (grid-plate benchmark 40 s → 2.8 s; NIST
|
|
2169
|
+
CTC-02 ~107 s → well under half); the full test tier dropped ~14 min → ~3.5 min.
|
|
2170
|
+
|
|
2171
|
+
### Performance
|
|
2172
|
+
|
|
2173
|
+
- **Placement measures, then builds** (#678, #679): corridor/strip candidates are
|
|
2174
|
+
evaluated on analytical footprints (`dim_footprint`) or a single probe box; an
|
|
2175
|
+
accepted candidate builds its OCC geometry exactly once and re-validates the
|
|
2176
|
+
real box. Dimension constructions on the scattered-plate benchmark: 59 → 21
|
|
2177
|
+
(= the placed count).
|
|
2178
|
+
- **Detect once** (#682): the sizing model `_analyse` builds pre-scale is stored
|
|
2179
|
+
on `Analysis.model` and reused as the render model — restoring ADR 0008
|
|
2180
|
+
Amendment 5 ("one inventory, detected once"). ~13 s off CTC-02.
|
|
2181
|
+
- **Fillet recognition de-quadratised** (#683): edge→faces adjacency map replaces
|
|
2182
|
+
the O(faces²×edges²) `IsSame` sweep (3.7 M calls on CTC-02); 10.8 s → 4.6 s,
|
|
2183
|
+
byte-identical records.
|
|
2184
|
+
- **Lint bounding boxes memoised** (#681): `Drawing.lint()` 0.88 s → 0.07 s per
|
|
2185
|
+
call (identity+location-token-checked cache beside the #143 view-edge cache).
|
|
2186
|
+
- **DXF viewport from the known page window** (#680): skips `ezdxf.zoom.extents`'
|
|
2187
|
+
per-entity walk; ~2.4 s per DXF export.
|
|
2188
|
+
- **helpers 0.14** (#684): boolean-free dimension ink (upstream #177, filed and
|
|
2189
|
+
fixed same-day) — ~25 ms per `Dimension`, was ~234 ms.
|
|
2190
|
+
|
|
2191
|
+
### Changed
|
|
2192
|
+
|
|
2193
|
+
- **Tight-span dimensions now render honestly** (helpers 0.14): ISO outside
|
|
2194
|
+
arrows where 0.13 silently degraded to a bare line. Ink extents grow on such
|
|
2195
|
+
dims; placement models the flip analytically. Two placement-golden fixtures
|
|
2196
|
+
re-blessed (ink extent only).
|
|
2197
|
+
- Diameter-row leader labels space by **measured text width** and repair
|
|
2198
|
+
helpers' shelf-flip collisions (crowded rows only; ordinary rows unchanged).
|
|
2199
|
+
- A plate-thickness dim whose home strip corner is structurally contested falls
|
|
2200
|
+
through to the opposite strip / side view instead of dropping (#684; the
|
|
2201
|
+
underlying one-box-occupancy artifact is tracked as #685).
|
|
2202
|
+
|
|
2203
|
+
### Fixed
|
|
2204
|
+
|
|
2205
|
+
- `recognise_fillets` neighbour tie-break is order-independent (#683 review).
|
|
2206
|
+
- Lint's annotation-box cache prunes departed objects and detects in-place
|
|
2207
|
+
relocation (#681 review).
|
|
2208
|
+
|
|
2209
|
+
## v0.3.1 — 2026-07-17
|
|
2210
|
+
|
|
2211
|
+
Also lands the **#635 consolidation epic** (P1–P6, all six children closed): the render
|
|
2212
|
+
layer's state bus is retired (`annotations/` reads zero `Drawing` privates,
|
|
2213
|
+
machine-enforced), the three complexity hotspots are split (nesting ≤2), the whole-package
|
|
2214
|
+
import DAG + a test-import ratchet are enforced, and the test suite gains a Hypothesis fuzz
|
|
2215
|
+
tier + relational cross-kernel placement gates. All internal / behaviour-preserving
|
|
2216
|
+
(byte-identical golden) — no output change.
|
|
2217
|
+
|
|
2218
|
+
### Added
|
|
2219
|
+
|
|
2220
|
+
- **PNG raster export** — `--format png` on the CLI, or `Drawing.export(formats=("png",))`.
|
|
2221
|
+
Rendered SVG → PDF → PNG via **pypdfium2** (Apache-2.0, Google PDFium BSD-3) + **Pillow**
|
|
2222
|
+
(HPND) — both permissively licensed and pure-wheel, so PNG works cross-platform with **no
|
|
2223
|
+
native cairo** (ADR 0006) and keeps the render path dual-license-friendly. `dpi=` sets the
|
|
2224
|
+
raster resolution.
|
|
2225
|
+
|
|
2226
|
+
### Changed
|
|
2227
|
+
|
|
2228
|
+
- **Unified export API** — `Drawing.export(out, *, formats=("pdf",)) → {format: path}` is now
|
|
2229
|
+
the single entry point over `svg`/`dxf`/`pdf`/`png`; it returns a dict and internally handles
|
|
2230
|
+
the SVG→PDF→PNG intermediate chain (writing/cleaning up intermediates it wasn't asked to keep).
|
|
2231
|
+
The CLI `--format` gains `png`.
|
|
2232
|
+
|
|
2233
|
+
### Deprecated
|
|
2234
|
+
|
|
2235
|
+
- `Drawing.export_pdf()` — use `export(formats=("pdf",))["pdf"]`; the method now warns.
|
|
2236
|
+
- The legacy `export(svg=, dxf=)` boolean keywords and their `(svg_path, dxf_path)` tuple return
|
|
2237
|
+
— kept for back-compat; prefer `formats=[...]` (the dict API).
|
|
2238
|
+
|
|
2239
|
+
## v0.3.0 — 2026-07-14
|
|
2240
|
+
|
|
2241
|
+
**Breaking — feature-recogniser API renamed** (ADR 0013 / #568): *deliberate* breaks with
|
|
2242
|
+
**no compatibility aliases**, hence the minor bump. Only import paths and callable
|
|
2243
|
+
signatures change — but note this release also **changes drawing output**: new machined-
|
|
2244
|
+
feature callouts, corrected leader anchors, and a reoriented isometric (see Added / Fixed).
|
|
2245
|
+
|
|
2246
|
+
### Added
|
|
2247
|
+
|
|
2248
|
+
- **Machined-feature recognition — the #148 epic.** #135 deliberately handled only enclosed
|
|
2249
|
+
rectangular through-slots; this broadens recognition, and each feature is recognised **and**
|
|
2250
|
+
dimensioned **and** authorable (recognise + emit + declare, ADR 0011):
|
|
2251
|
+
- **Blind slots + pockets** — floored recesses, `W × L × D DEEP` (#603).
|
|
2252
|
+
- **Cross / intersecting slots** collapse into single continuous channels (#604).
|
|
2253
|
+
- **Machined flats** on round stock — `{across} A/F` (#605).
|
|
2254
|
+
- **Turned / circlip grooves** — `{width} WIDE × ø{floor}` (#606).
|
|
2255
|
+
- **Slots / pockets in curved stock** — arc-bounded walls (#607).
|
|
2256
|
+
- **Radiused-end (obround) slots** now report their **overall** length (#613).
|
|
2257
|
+
- **Chamfer callouts** — `C{leg}` / `{leg}×{angle}°` off each bevel (#560).
|
|
2258
|
+
- **Fillet radius callouts** — `R{radius}` off each rounded edge (#561).
|
|
2259
|
+
- **Plate / wall thickness** dimensions on multi-plate prismatics (#559).
|
|
2260
|
+
- **Prismatic step-position** dimensions locating each shoulder (#555).
|
|
2261
|
+
- **Countersink callouts** — `ø6 THRU ⌵ ø14 × 90°` (major-ø + included angle), like the
|
|
2262
|
+
counterbore `⊔ ø.. ↧..` (#558). The countersink rides on `HoleRecord`/`HoleFeature`, so
|
|
2263
|
+
grouping and the callout-width layout estimate account for it.
|
|
2264
|
+
- **Every recognised feature round-trips all three ADR-0011 surfaces (#574).** Beyond
|
|
2265
|
+
detection, each feature now **emits** into the generated `--script` Sheet and is
|
|
2266
|
+
**declarable** on the fluent `Sheet` surface — authored from scratch or read off a
|
|
2267
|
+
build123d object: chamfer (#576), countersink (#575), plate (#577), step-position (#585),
|
|
2268
|
+
fillet (#561), plus all the #148 features above.
|
|
2269
|
+
- **`draftwright.score.feature_census(part)`** — a per-kind recognised-feature census, a
|
|
2270
|
+
measurement tool for tracking recognition coverage (#608).
|
|
2271
|
+
|
|
2272
|
+
### Changed
|
|
2273
|
+
|
|
2274
|
+
- **Feature recognisers renamed `find_`/`analyse_` → `recognise_`** and their
|
|
2275
|
+
tuning/dependencies made keyword-only: `find_holes`→`recognise_holes`,
|
|
2276
|
+
`find_bosses`→`recognise_bosses`, `find_hole_patterns`→`recognise_hole_patterns`,
|
|
2277
|
+
`find_slots`→`recognise_slots`, `find_plates`→`recognise_plates`,
|
|
2278
|
+
`find_chamfers`→`recognise_chamfers`, `find_turned_steps`→`recognise_turned_steps`,
|
|
2279
|
+
`find_step_shoulders`→`recognise_step_shoulders`, `analyse_face_levels`→
|
|
2280
|
+
`recognise_face_levels` (the last was also re-exported at top level as
|
|
2281
|
+
`draftwright.analyse_face_levels` → now `draftwright.recognise_face_levels`).
|
|
2282
|
+
Cylinder-analysis substrate (`analyse_cylinders`, `full_cylinders`,
|
|
2283
|
+
`feature_diameters`) keeps its names.
|
|
2284
|
+
- **`recognise_step_shoulders` now returns `list[StepShoulder]`** (a frozen dataclass)
|
|
2285
|
+
instead of raw `(axis, position)` tuples; `levels` is keyword-only.
|
|
2286
|
+
- **`recognise_turned_steps` now returns `list[TurnedStep]`** (empty for a non-turned
|
|
2287
|
+
part) instead of `TurnedProfile | None`. `TurnedStep` gained an `axis` field (each step
|
|
2288
|
+
is now a self-contained record); `TurnedProfile` remains only as a pipeline aggregate
|
|
2289
|
+
(`TurnedProfile.from_steps(steps)`), no longer a recogniser return.
|
|
2290
|
+
- **`recognise_face_levels` now returns `list[FaceLevel]`** (a frozen `FaceLevel(z)`
|
|
2291
|
+
record) instead of `list[float]`.
|
|
2292
|
+
- **Recognition record classes renamed to avoid clashing with the IR `Feature` types:**
|
|
2293
|
+
`draftwright.recognition.HoleFeature` → `HoleRecord`, `BossFeature` → `BossRecord`
|
|
2294
|
+
(the IR `draftwright.model.ir.HoleFeature`/`BossFeature` are unchanged).
|
|
2295
|
+
- **Page/scale sizing now reads the IR, not recognition records (ADR 0008 / #588).** The
|
|
2296
|
+
part model is built up front and drives sheet sizing, so detected and declared parts share
|
|
2297
|
+
one path and no recogniser record reaches the sheet estimators. Byte-identical to the old
|
|
2298
|
+
estimators except a hole pattern that shares a machining spec with loose holes now sizes
|
|
2299
|
+
separately (no phantom merged `N×`), which can shift a tightly-packed such part's layout.
|
|
2300
|
+
|
|
2301
|
+
### Fixed
|
|
2302
|
+
|
|
2303
|
+
- **Isometric view orientation (#620).** The iso camera viewed the *rear* (+Y) side against a
|
|
2304
|
+
front-view orthographic set, mirroring asymmetric features; it now views from the same
|
|
2305
|
+
front (−Y) / plan (+Z) / right (+X) combination.
|
|
2306
|
+
- **Chamfer leaders (#621)** anchor on the bevel-face centroid (the diagonal middle), not the
|
|
2307
|
+
supporting plane's parametric origin (which projected to a corner/endpoint).
|
|
2308
|
+
- **Fillet leaders (#622)** anchor on the radius surface, not the face bounding-box centre
|
|
2309
|
+
(which sat off the round, near the virtual sharp corner).
|
|
2310
|
+
- **Authored `ref_pts`-only dimensions** now render (with Z-strip sizing) (#562).
|
|
2311
|
+
- **Pitch-dim labels** are cleared off centrelines / bolt circles at creation time, not via
|
|
2312
|
+
the repair loop (#129).
|
|
2313
|
+
|
|
2314
|
+
### Removed
|
|
2315
|
+
|
|
2316
|
+
- **`draftwright.features` compatibility module** — deleted. Import `recognise_slots`/
|
|
2317
|
+
`Slot` from `draftwright.recognition` instead.
|
|
2318
|
+
|
|
2319
|
+
## v0.2.13 — 2026-07-09
|
|
2320
|
+
|
|
2321
|
+
**Compose-then-pack is now the layout authority.** This patch finishes the
|
|
2322
|
+
ViewBlock footprint migration: estimated and measured layout paths now use the
|
|
2323
|
+
same composed block model, furniture declarations reserve their real footprint,
|
|
2324
|
+
and measure/repack iterates until stable instead of trusting one measured pass.
|
|
2325
|
+
|
|
2326
|
+
### Changed
|
|
2327
|
+
|
|
2328
|
+
- **ViewBlock footprints now drive the orthographic stack.** The old
|
|
2329
|
+
estimator-only plan-view balloon lift is gone; plan balloon headroom is part
|
|
2330
|
+
of the plan block in both estimated and measured/repack layout. (#112)
|
|
2331
|
+
- **Measure/repack iterates to a fixed point.** Repack now keeps measuring and
|
|
2332
|
+
repacking while view-owned footprints continue to grow, with bounded
|
|
2333
|
+
convergence and tests for multi-pass growth. (#302)
|
|
2334
|
+
- **Estimated view-block composition is explicit.** Scale/page fitness, repack,
|
|
2335
|
+
and furniture placement share the same composed block semantics instead of
|
|
2336
|
+
rebuilding corridor estimates independently.
|
|
2337
|
+
|
|
2338
|
+
### Fixed
|
|
2339
|
+
|
|
2340
|
+
- **Declared callout furniture reserves layout footprint.** User-declared
|
|
2341
|
+
furniture is now measured and fed into the layout model, reducing post-hoc
|
|
2342
|
+
collisions from declarations that previously existed only at render time.
|
|
2343
|
+
- **Annotation-box composition owns strip sizing.** Strip depths reduce from
|
|
2344
|
+
composed annotation boxes, making footprint sizing less dependent on divergent
|
|
2345
|
+
scalar estimates.
|
|
2346
|
+
|
|
2347
|
+
### Documentation
|
|
2348
|
+
|
|
2349
|
+
- **Layout architecture docs reflect the current state.** ADR 0004 and the
|
|
2350
|
+
layout primer now mark the core layout-authority tranche complete and separate
|
|
2351
|
+
remaining work into hardening, coverage, detail-view, and manual-intent phases.
|
|
2352
|
+
|
|
2353
|
+
## v0.2.12 — 2026-07-09
|
|
2354
|
+
|
|
2355
|
+
**Sheet scripts now round-trip authored layout intent.** This patch finishes the next
|
|
2356
|
+
slice of the layout-authority work: below/right ladders, pinned edits, height ladders,
|
|
2357
|
+
detected envelopes, and AP242 authored dimensions now survive the declarative Sheet path
|
|
2358
|
+
without being invalidated by post-hoc placement or raw imported metadata.
|
|
2359
|
+
|
|
2360
|
+
### Added
|
|
2361
|
+
|
|
2362
|
+
- **Pinned edit intents route through the corridor solve.** `locate(..., pin=True)` and
|
|
2363
|
+
pinned dimensions now become priority-ranked candidates in the shared corridor instead
|
|
2364
|
+
of fixed post-hoc edits, so user intent participates in the same ordering/spacing model
|
|
2365
|
+
as automatic dimensions. (#511)
|
|
2366
|
+
- **AP242 dimensional PMI lowers to authored drafting dimensions.** Imported AP242
|
|
2367
|
+
size/location dimensions now become `AuthoredDimension` IR and generated Sheet scripts
|
|
2368
|
+
emit `sheet.dimension(...)`; unsupported PMI records remain explicit raw fallbacks.
|
|
2369
|
+
(#503, #422, #62)
|
|
2370
|
+
|
|
2371
|
+
### Changed
|
|
2372
|
+
|
|
2373
|
+
- **`place_dim` is deprecated.** Manual dimensions should use pinned candidate/dimension
|
|
2374
|
+
intent instead of the old incremental edit path.
|
|
2375
|
+
- **Prismatic height ladders and detected envelopes round-trip through Sheet scripts.**
|
|
2376
|
+
Generated scripts now preserve `StepLevelFeature` and detected `EnvelopeFeature`
|
|
2377
|
+
fallbacks, preventing CTC01-style ladder swaps and raw STEP-envelope remeasurement
|
|
2378
|
+
drift.
|
|
2379
|
+
|
|
2380
|
+
### Fixed
|
|
2381
|
+
|
|
2382
|
+
- **Below/right corridors now share one solve.** Side-hole locations, height ladders,
|
|
2383
|
+
PMI/GD&T, envelope dims, and related below/right strip occupants negotiate in the shared
|
|
2384
|
+
corridor rather than competing through separate late passes. (#477)
|
|
2385
|
+
- **Sheet script parity is tighter.** Generated scripts preserve member positions, step
|
|
2386
|
+
levels, AP242 authored dimensions, raw PMI fallbacks, and detected envelopes so
|
|
2387
|
+
direct-vs-script CTC01 output has matching annotation names.
|
|
2388
|
+
|
|
2389
|
+
## v0.2.11 — 2026-07-08
|
|
2390
|
+
|
|
2391
|
+
**Automatic layout now has one authority.** Page/scale selection, section placement,
|
|
2392
|
+
furniture footprints, and table/balloon escalation now negotiate through the same layout
|
|
2393
|
+
fitness model instead of using separate fixed offsets or first-fit policies after the main
|
|
2394
|
+
solve.
|
|
2395
|
+
|
|
2396
|
+
### Fixed
|
|
2397
|
+
|
|
2398
|
+
- **Solver placement paths are more consistent.** STEP PMI dimensions now queue into
|
|
2399
|
+
the shared ADR 0009 corridor solve instead of carving after the drain; front-view
|
|
2400
|
+
hole callouts use the strip solver instead of fixed row stepping; pitch-dimension
|
|
2401
|
+
fallback searches bounded, obstacle-aware positions; repair no longer hides
|
|
2402
|
+
`annotation_overlap` with a fixed-step nudge; and step-count sizing now handles
|
|
2403
|
+
non-convergence conservatively. (#524)
|
|
2404
|
+
- **Page/scale fitness is shared across initial selection and repack.** Later layout
|
|
2405
|
+
passes now compare candidates with the same model as the page chooser, preventing a
|
|
2406
|
+
nominally "better" repack from invalidating the original layout decision. (#519)
|
|
2407
|
+
- **Section A-A participates in layout selection.** Section placement is measured as
|
|
2408
|
+
part of page/scale fitness, so a section view is no longer a fixed-offset afterthought
|
|
2409
|
+
that can disappear on dense sheets. (#515)
|
|
2410
|
+
- **Furniture placement reserves full rendered footprints.** Section arrows, detail
|
|
2411
|
+
views, balloons, hole/data tables, and other furniture now reserve/check their true
|
|
2412
|
+
rendered footprint instead of just their labels. (#518)
|
|
2413
|
+
- **Hole/data tables and balloon rings escalate through the layout model.** Dense table
|
|
2414
|
+
and balloon outputs can move or negotiate for available room rather than dropping from
|
|
2415
|
+
greedy first-fit placement when a small adjustment would fit. (#516, #517)
|
|
2416
|
+
|
|
2417
|
+
## v0.2.10 — 2026-07-07
|
|
2418
|
+
|
|
2419
|
+
**Declarative-surface fidelity and layout-engine unification.** Editing and re-running a
|
|
2420
|
+
declarative `Sheet` script now reproduces more of the drawing (title block, layout, PMI on the
|
|
2421
|
+
declared path), a new lint catches stale declarations, and an intentional scale is respected.
|
|
2422
|
+
Internally the annotation placer moves further onto the single collect-then-solve (ADR 0009),
|
|
2423
|
+
and `kiwisolver` is dropped as a dependency.
|
|
2424
|
+
|
|
2425
|
+
### Added
|
|
2426
|
+
|
|
2427
|
+
- **Declaration-vs-geometry reconciliation lint** — `lint()` now flags a declared cylindrical
|
|
2428
|
+
feature (hole/boss/step) with **no matching geometry** in the part (`declared_feature_absent`):
|
|
2429
|
+
a callout drawn over empty space because the part was edited but the declaration went stale.
|
|
2430
|
+
Closes the last gap in the "did my edit break the drawing?" loop (over-declaration; coverage
|
|
2431
|
+
lint already caught under-declaration). Matches on axis + ⌀ + in-plane position + bore/boss
|
|
2432
|
+
polarity. Gated on a caller-supplied `model=` (detection can't over-declare). (#487)
|
|
2433
|
+
- **Title-block + layout aspects on the `Sheet` DSL** — `Sheet(drawn_by=…, tolerance=…, scale=…,
|
|
2434
|
+
page=…)`; the generated `--script` reproduces them, and the CLI forwards
|
|
2435
|
+
`--drawn-by`/`--tolerance`/`--scale`/`--page` on the sheet path (no more inert-flag warning). (#474)
|
|
2436
|
+
- **PMI reproduced on the declared-model path** — `build_drawing(path, model=…, pmi="annotate")`
|
|
2437
|
+
synthesises the STEP AP242 PMI into the declared model, so a declared build draws the same PMI
|
|
2438
|
+
dimensions as the detection path. (#472)
|
|
2439
|
+
|
|
2440
|
+
### Changed
|
|
2441
|
+
|
|
2442
|
+
- **An intentional explicit `scale=` below the legibility floor is honoured with a warning**
|
|
2443
|
+
rather than rejected. A part deliberately drawn at 1:1 (or `Sheet(scale="1:10")`) whose smallest
|
|
2444
|
+
feature falls under the 10 mm legibility floor now renders (annotations may crowd) instead of
|
|
2445
|
+
raising `ValueError`; only a genuinely degenerate scale (< 0.1 mm projected, where OCCT arcs
|
|
2446
|
+
collapse) is rejected. The floor now binds only the *automatic* scale. (#489)
|
|
2447
|
+
- **`kiwisolver` is no longer a dependency.** The 1-D strip solve delegates to the built-in
|
|
2448
|
+
deterministic minimum-total-leader-length PAVA algorithm, which supersedes the Cassowary
|
|
2449
|
+
solver — same placement contract, one fewer third-party dependency. (#507)
|
|
2450
|
+
|
|
2451
|
+
### Fixed
|
|
2452
|
+
|
|
2453
|
+
- **Dimension placement is more robust under contention.** Candidate **priority** is plumbed
|
|
2454
|
+
through the shared corridor solve, so an authored GD&T frame is kept over a lower-value
|
|
2455
|
+
automatic dimension when a strip is over capacity (#357). Rotational concentric-bore leaders
|
|
2456
|
+
are now bounded to the front-view height with ranked drops, and pitch dimensions are placed
|
|
2457
|
+
onto the obstacle-aware per-side zone-strip solve — retiring the last fixed-offset,
|
|
2458
|
+
count-based stacking placers (the shape behind earlier dense-sheet overruns). (#374)
|
|
2459
|
+
|
|
2460
|
+
## v0.2.9 — 2026-07-06
|
|
2461
|
+
|
|
2462
|
+
**Declarative GD&T, datums, and surface finish (ADR 0011 Phase 2b/2c).** The `Sheet` DSL can
|
|
2463
|
+
now author the drawing information geometry can't carry — geometric tolerances, datum feature
|
|
2464
|
+
symbols, and surface-finish marks — by pointing at a build123d feature or face. They render
|
|
2465
|
+
through the auto-layout engine as first-class ADR 0009 corridor candidates, placed and spaced
|
|
2466
|
+
crossing-free alongside the automatic dimensions (not a post-hoc overlay).
|
|
2467
|
+
|
|
2468
|
+
```python
|
|
2469
|
+
sheet.datum("A", base_face)
|
|
2470
|
+
sheet.control(bore).position(0.1, to="A", diameter=True).perpendicularity(0.05, to="A")
|
|
2471
|
+
sheet.diameter(journal).finish("0.8")
|
|
2472
|
+
```
|
|
2473
|
+
|
|
2474
|
+
### Added
|
|
2475
|
+
|
|
2476
|
+
- **Feature control frames (ISO 1101)** — `sheet.control(ref)` returns a chainable builder with
|
|
2477
|
+
one method per **all 14** characteristics (`position`, `flatness`, `perpendicularity`,
|
|
2478
|
+
`cylindricity`, `circular_runout`, `total_runout`, …); `to=` names the referenced datum(s),
|
|
2479
|
+
`diameter=` prefixes the ⌀ tolerance zone, `modifier=` adds a material-condition symbol (Ⓜ/Ⓛ/Ⓟ).
|
|
2480
|
+
- **Datum feature symbols (ISO 5459)** — `sheet.datum("A", face_or_feature)`.
|
|
2481
|
+
- **Surface finish (ISO 1302, Ra)** — `.finish("1.6")` on a hole / diameter / step handle, or
|
|
2482
|
+
`sheet.finish(ra, face)`.
|
|
2483
|
+
- The target view + strip side are **derived from the referenced geometry** (a feature's axis →
|
|
2484
|
+
face-on view, a planar face's normal → edge-on view); `view=`/`side=` override.
|
|
2485
|
+
- Render core: `ControlFrame` / `DatumRef` / `Finish` IR features placed by `render_gdt` as
|
|
2486
|
+
first-class corridor candidates, with the real-footprint plumbing needed to space wide frames.
|
|
2487
|
+
|
|
2488
|
+
### Fixed
|
|
2489
|
+
|
|
2490
|
+
- A control frame referencing an **undeclared datum letter** now warns at build.
|
|
2491
|
+
- GD&T placement is **title-block aware** and **falls through to the opposite strip side** before
|
|
2492
|
+
dropping a frame, so stacked control frames place robustly rather than vanishing or overlapping
|
|
2493
|
+
the title block.
|
|
2494
|
+
- An invalid glyph spec / degenerate leader in a caller-supplied model **drops the one item with a
|
|
2495
|
+
warning** instead of crashing the whole build (the IR is public input).
|
|
2496
|
+
- Turned-shaft rotational furniture now reproduces correctly through the declared-model path
|
|
2497
|
+
(`model=` / `Sheet`) (#476).
|
|
2498
|
+
|
|
2499
|
+
## v0.2.8 — 2026-07-06
|
|
2500
|
+
|
|
2501
|
+
**`--script` now defaults to the declarative `Sheet` DSL.** The editable script the CLI
|
|
2502
|
+
writes is the beautiful-Python surface — one commentable line per feature — for both STEP and
|
|
2503
|
+
build123d-object input.
|
|
2504
|
+
|
|
2505
|
+
### Changed
|
|
2506
|
+
|
|
2507
|
+
- **`draftwright … --script` now emits the declarative `Sheet` script by default** (was the
|
|
2508
|
+
imperative edit-verb reconstruction). The imperative reconstruction is still available via
|
|
2509
|
+
`--script --style imperative`. For prismatic parts the generated script reproduces the same
|
|
2510
|
+
drawing as a direct build; a turned shaft's centre lines and base-diameter style are not yet
|
|
2511
|
+
identical (the remaining validity gap, tracked separately). `--style imperative` now errors
|
|
2512
|
+
clearly on a `module:attr` object spec (it reads a STEP file; use the default `sheet`).
|
|
2513
|
+
The Sheet DSL doesn't yet model the title-block / layout aspects the imperative script
|
|
2514
|
+
embeds, so `--script --style sheet` **warns** when `--drawn-by`, `--tolerance`, `--scale`
|
|
2515
|
+
or `--page` is set rather than silently ignoring it (use `--style imperative` to embed them).
|
|
2516
|
+
|
|
2517
|
+
## v0.2.7 — 2026-07-05
|
|
2518
|
+
|
|
2519
|
+
**The three authoring modes (ADR 0011 Amendment 1).** Naming how you drive draftwright —
|
|
2520
|
+
*just do it* / *auto then tweak* / *generate an editable script* — and filling in the third:
|
|
2521
|
+
a declarative `Sheet`-DSL generator, and number-free authoring against the build123d objects
|
|
2522
|
+
you built.
|
|
2523
|
+
|
|
2524
|
+
### Added
|
|
2525
|
+
|
|
2526
|
+
- **`draftwright part.step --script --style sheet`** — generate an **editable declarative
|
|
2527
|
+
`Sheet` script** from a detected part: one commentable line per feature (hole / diameter /
|
|
2528
|
+
step / slot / pattern / envelope), views noted, the auto-section flagged. Comment a line out
|
|
2529
|
+
to drop that feature; the script re-runs to the drawing. The existing `--script` (imperative
|
|
2530
|
+
edit-verb reconstruction) stays the default (#461).
|
|
2531
|
+
- **Object-reading `.cbore(tool)` / `.spotface(tool)`** on a declared hole — read the
|
|
2532
|
+
counterbore/spotface's ⌀ **and** depth off the tool object + part (depth measured from the
|
|
2533
|
+
local open face, so a rib/wall elsewhere doesn't skew it). A `Sheet`-declared drawing can now
|
|
2534
|
+
carry **zero magic numbers** and track the geometry parametrically (#462).
|
|
2535
|
+
- **`Sheet.of(feature)`** — a fluent handle onto an **existing / detection-seeded** feature (by
|
|
2536
|
+
the build123d object, an index, or the `Feature` itself), so you can `.fit(...)` /
|
|
2537
|
+
`.tolerance(...)` a feature from `Sheet.from_part()` without re-declaring it (#463).
|
|
2538
|
+
|
|
2539
|
+
### Docs
|
|
2540
|
+
|
|
2541
|
+
- **ADR 0011 Amendment 1** — the three authoring modes and the mode-3 generation surface;
|
|
2542
|
+
records the decision to emit **honest detected numbers** for a detected part rather than
|
|
2543
|
+
fabricate a build123d reconstruction that misrepresents the geometry (#464).
|
|
2544
|
+
|
|
2545
|
+
## v0.2.6 — 2026-07-05
|
|
2546
|
+
|
|
2547
|
+
**ADR 0011 — the IR as a public input: declare features, don't only detect them.**
|
|
2548
|
+
Detection stays the default, but the caller can now *supply* the feature model, so a
|
|
2549
|
+
part you built parametrically reads as its own drawing and misdetection becomes
|
|
2550
|
+
recoverable by construction. Plus the first Phase-2 aspect layer (tolerances + fits).
|
|
2551
|
+
|
|
2552
|
+
### Added
|
|
2553
|
+
|
|
2554
|
+
- **`build_drawing(part, model=…)`** accepts a caller-supplied `PartModel` (or a
|
|
2555
|
+
`Sequence[Feature]`); when given, **detection is skipped** and the auto-pass dimensions
|
|
2556
|
+
the declared features. Detection and declaration are two producers of the same IR (#447,
|
|
2557
|
+
ADR 0011 Phase 0).
|
|
2558
|
+
- **Object → feature constructors** `draftwright.model.hole` / `boss` / `step` / `slot` /
|
|
2559
|
+
`pattern` / `envelope` — read a feature's geometry off the build123d object you built (⌀
|
|
2560
|
+
from the cylindrical face, axis/location from the bbox), or supply explicit values (#447).
|
|
2561
|
+
- **The fluent `Sheet` façade** (`draftwright.Sheet`) — reference the objects you built,
|
|
2562
|
+
declare their drawing aspects, `.build()` / `.export()`. `Sheet.from_part()` seeds the
|
|
2563
|
+
hybrid override mode from detection (#447, Phase 1).
|
|
2564
|
+
- **Toleranced dimensions** — a `±` / limit tolerance on a diameter, step, or hole bore,
|
|
2565
|
+
rendered on both the linear and ⌀-callout paths (`Sheet.tolerance(...)`, or a
|
|
2566
|
+
`decorations=` side-layer) (#28, Phase 2 P2a).
|
|
2567
|
+
- **Fit-class deviation** — `Sheet.fit("H7")` resolves an ISO 286 fit class to its limit
|
|
2568
|
+
deviation for the feature's nominal ⌀, rendered as the class code (`ø20 H7`, default) or
|
|
2569
|
+
the signed deviations (`show="deviation"` → `ø20 +0.021/0`). Common classes; fails loud
|
|
2570
|
+
outside its table (#29, Phase 2 P2a.2).
|
|
2571
|
+
|
|
2572
|
+
### Changed
|
|
2573
|
+
|
|
2574
|
+
- **Object constructors honour explicit overrides** — a passed object supplies *defaults*;
|
|
2575
|
+
each explicit keyword overrides that field independently, and invalid public input fails
|
|
2576
|
+
at declaration with a clear `ValueError` (#451, #452).
|
|
2577
|
+
- **A declared hole/pattern renders at its declared position** even where detection missed
|
|
2578
|
+
it — the callout membership is sourced from the declared model, not only detection (#448).
|
|
2579
|
+
- **`Sheet.model()` / `Sheet.from_part()`** no longer build a full drawing just to return
|
|
2580
|
+
the IR — feature inspection/seeding is now a cheap, no-render path (#453).
|
|
2581
|
+
|
|
2582
|
+
### Fixed
|
|
2583
|
+
|
|
2584
|
+
- A narrow diameter band hidden under a larger OD silhouette is no longer silently
|
|
2585
|
+
undimensioned (the two feature inventories agreed) (#298).
|
|
2586
|
+
|
|
2587
|
+
## v0.2.5 — 2026-07-04
|
|
2588
|
+
|
|
2589
|
+
**The editable write API and record-then-finalize.** A detected drawing became an editable
|
|
2590
|
+
object, and a generated `--script` became a runnable reconstruction that reaches auto-pass
|
|
2591
|
+
quality.
|
|
2592
|
+
|
|
2593
|
+
### Added
|
|
2594
|
+
|
|
2595
|
+
- **`dwg.model()`** exposes the detected `PartModel` as a read surface, plus feature-
|
|
2596
|
+
referenced add verbs `dimension()` / `callout()` / `locate()` / `furniture()` /
|
|
2597
|
+
`section()` and `drop(feature)`, with a machine-checked completeness audit (#400).
|
|
2598
|
+
- **Record-then-finalize** (#426): the verbs record intents in deferred mode and
|
|
2599
|
+
`dwg.finalize()` (auto-run by export) drains them through the auto-pass's own solvers, so
|
|
2600
|
+
a reconstruction reaches auto-pass quality; `--script` now emits a runnable detect-only
|
|
2601
|
+
reconstruction.
|
|
2602
|
+
|
|
2603
|
+
### Changed
|
|
2604
|
+
|
|
2605
|
+
- **Dimension-line spacing now follows ISO 129-1 / ASME Y14.5 convention** (#347): a wider
|
|
2606
|
+
first-line gap (8 → 10 mm) and tighter, uniform parallel stacking (between-line clear gap
|
|
2607
|
+
4 → 2.5 mm), with the inter-view corridor widened in step. Re-drifts every drawing.
|
|
2608
|
+
|
|
2609
|
+
## v0.2.4 — 2026-07-03
|
|
2610
|
+
|
|
2611
|
+
A follow-up patch on the ADR 0009 placement rebuild in 0.2.3: it finishes unifying
|
|
2612
|
+
the shared "above-view" dimension corridor, adds a layout-overflow safety net, and
|
|
2613
|
+
makes two more drop paths non-silent.
|
|
2614
|
+
|
|
2615
|
+
### Changed
|
|
2616
|
+
|
|
2617
|
+
- **Plan-view X location dimensions, side-view Y location dimensions, and a
|
|
2618
|
+
coincident slot-position dimension now share one collect-then-solve pass** (ADR
|
|
2619
|
+
0009 Amendment 6, #345/#346). Previously each pass carved the strip independently,
|
|
2620
|
+
so a hole location and a slot position measuring the same datum span could both be
|
|
2621
|
+
drawn, and the location ladder could come out non-monotonic. One solve now dedups
|
|
2622
|
+
the coincident span (keeping the higher-priority location dimension) and orders the
|
|
2623
|
+
whole ladder as segregated, monotonic runs — feature-size dimensions nearest the
|
|
2624
|
+
view, datum locations nesting outward by distance.
|
|
2625
|
+
|
|
2626
|
+
### Fixed
|
|
2627
|
+
|
|
2628
|
+
- **`choose_scale` never returns an overflowing layout** (#350). Scale selection
|
|
2629
|
+
could pick a scale whose composed block layout exceeded the drawable area; it now
|
|
2630
|
+
rejects any overflowing candidate.
|
|
2631
|
+
- **A hole location and a coincident slot position are no longer drawn twice** (#345),
|
|
2632
|
+
including at fractional datum distances where a display-value snap gap previously let
|
|
2633
|
+
the duplicate escape deduplication.
|
|
2634
|
+
- **The plan-view location ladder is monotonic** (#346) — running dimensions off a
|
|
2635
|
+
shared datum stack outward in ascending order instead of interleaving.
|
|
2636
|
+
- **A dropped balloon is non-silent** (#387). A balloon that cannot be placed now
|
|
2637
|
+
reports the drop and clears its `callout_dropped` state precisely, instead of
|
|
2638
|
+
vanishing with no on-sheet signal.
|
|
2639
|
+
|
|
2640
|
+
## v0.2.3 — 2026-07-03
|
|
2641
|
+
|
|
2642
|
+
A large patch release: the **annotation-placement engine was rebuilt** as a
|
|
2643
|
+
collect-then-solve *boundary-labeling* stage (ADR 0009). Placement is now
|
|
2644
|
+
deterministic and minimises total leader length, and the recurring class of
|
|
2645
|
+
overlaps where a label was drawn on top of an "invisible" occupant — a leader
|
|
2646
|
+
shaft, a witness/extension line, the section hatch — is removed by construction.
|
|
2647
|
+
Drawing output changes for many turned, cross-drilled, and multi-feature parts.
|
|
2648
|
+
|
|
2649
|
+
### Changed
|
|
2650
|
+
|
|
2651
|
+
- **Every annotation in a view's margin is now placed by one collect-then-solve
|
|
2652
|
+
pass** (ADR 0009, #317–#323). Dimensions, hole callouts, turned-diameter
|
|
2653
|
+
leaders, and the section hatch share a single occupancy model instead of several
|
|
2654
|
+
independent passes each blind to the others. When a strip is over capacity it now
|
|
2655
|
+
drops the *lowest-priority* annotation (smallest bore first) rather than whichever
|
|
2656
|
+
pass happened to run last. The legacy strip cursor is retired.
|
|
2657
|
+
- **Leader placement minimises total leader length, deterministically** (P4,
|
|
2658
|
+
#318). A per-strip solve places each label at the shortest-leader position that
|
|
2659
|
+
keeps the labels in order and clear of keep-out rows (a view centre-line, a
|
|
2660
|
+
dimension's extension line); central/coaxial callouts are anchored to the
|
|
2661
|
+
view-centre row. Output is reproducible across platforms and Python versions.
|
|
2662
|
+
- **`scipy` is no longer a dependency** — the leader solve is a small deterministic
|
|
2663
|
+
algorithm (weighted-median isotonic regression), not a linear program.
|
|
2664
|
+
- **Output changes** for turned, cross-drilled, and multi-feature parts whose
|
|
2665
|
+
margin annotations are now positioned by the unified solver.
|
|
2666
|
+
|
|
2667
|
+
### Fixed
|
|
2668
|
+
|
|
2669
|
+
- **A PMI bore-diameter dimension spans the bore radius, not the full diameter**
|
|
2670
|
+
(#360). A `pmi="annotate"` diameter callout drew its witness lines at ±diameter
|
|
2671
|
+
from the centre — twice too wide, missing the bore edges.
|
|
2672
|
+
- **A bore coaxial with a rotational part's turning axis is no longer
|
|
2673
|
+
over-dimensioned** (#309). It carried a redundant offset *and* height location
|
|
2674
|
+
dimension even though its centre mark already locates it.
|
|
2675
|
+
- **A dropped turned step-length chain is no longer silent** (#362). When a turned
|
|
2676
|
+
head's shoulders are too crowded to dimension, the drop is now reported
|
|
2677
|
+
(`step_dim_dropped`) instead of vanishing with no lint or on-sheet signal.
|
|
2678
|
+
- **A diameter callout can no longer overprint a bore callout's leader shaft**
|
|
2679
|
+
(#358). The turned-diameter column now avoids the *full* footprint of existing
|
|
2680
|
+
annotations, not just their text boxes.
|
|
2681
|
+
- **The balloon ring hugs its dimensions on a cramped sheet** (#349) — its band
|
|
2682
|
+
depth is clamped to the drawable area.
|
|
2683
|
+
- **Dimension detection is robust to `SafeDimension`** (#335/#349) — the corridor
|
|
2684
|
+
and balloon-ring filters test the dimension *type*, not a class-name string, so a
|
|
2685
|
+
future dimension subclass can't slip through.
|
|
2686
|
+
|
|
2687
|
+
## v0.2.2 — 2026-06-30
|
|
2688
|
+
|
|
2689
|
+
A patch release of turned-part dimension-placement fixes and a CLI start-up
|
|
2690
|
+
speed-up. Drawing output changes for the affected turned/cross-drilled parts.
|
|
2691
|
+
|
|
2692
|
+
### Fixed
|
|
2693
|
+
|
|
2694
|
+
- **A coaxial bore callout on a *stepped* turned shaft is now lifted off the round
|
|
2695
|
+
view's centre axis** (#305). The earlier fix only triggered for a uniform
|
|
2696
|
+
(`is_rotational`) cylinder; a stepped shaft (e.g. the gramel GRM-03 drive screw)
|
|
2697
|
+
has a turned step profile but isn't classified rotational, so its `⌀… ↓…` bore
|
|
2698
|
+
callout was still leadered straight along the centreline, with the centre mark
|
|
2699
|
+
running through the text. The lift now also fires for a turned-profile part.
|
|
2700
|
+
- **A side-drilled hole's location dimension now stacks *inside* the overall
|
|
2701
|
+
envelope dimension** (ISO order — overall dim outermost, feature/location dims
|
|
2702
|
+
nearer the view). It was placed *outside* the envelope, which forced the shorter
|
|
2703
|
+
location dim's arrowheads to flip outward and clash (seen on GRM-01 and GRM-02).
|
|
2704
|
+
The mandatory overall dimension is still guaranteed placement.
|
|
2705
|
+
|
|
2706
|
+
### Changed
|
|
2707
|
+
|
|
2708
|
+
- **CLI shell completion and `--help` are fast again** (#313). The Typer CLI and
|
|
2709
|
+
the heavy CAD engine are now imported lazily, so tab-completion and `--help` no
|
|
2710
|
+
longer pay a ~6 s engine-import cost; a real drawing run is unaffected.
|
|
2711
|
+
|
|
2712
|
+
## v0.2.1 — 2026-06-30
|
|
2713
|
+
|
|
2714
|
+
A patch release focused on **turned-part dimensioning legibility**: crowded
|
|
2715
|
+
step-length chains and fine turned heads are now drawn legibly instead of crammed.
|
|
2716
|
+
Drawing output changes for affected turned parts.
|
|
2717
|
+
|
|
2718
|
+
### Added
|
|
2719
|
+
|
|
2720
|
+
- **Automatic enlarged detail view for a crowded turned head** (#304). A turned
|
|
2721
|
+
part with a fine cluster of steps near one end and a long shaft (e.g. a thumbwheel
|
|
2722
|
+
drive screw) cannot have its head dimensioned legibly in line at any sensible
|
|
2723
|
+
scale. The head is now located as one block on the main view and broken out into
|
|
2724
|
+
an enlarged **DETAIL A — SCALE n:1** — the textbook treatment — firing
|
|
2725
|
+
automatically when a head's shoulders fall below the page legibility floor.
|
|
2726
|
+
|
|
2727
|
+
### Changed
|
|
2728
|
+
|
|
2729
|
+
- **Crowded turned step-length chains stagger across two tiers** (#293) instead of
|
|
2730
|
+
cramming or being skipped. When the labels would collide on one line, the ISO
|
|
2731
|
+
129-1 staggered convention alternates them between a near and a far tier so every
|
|
2732
|
+
step length stays legible at the drawing's own scale — no rescale needed. A roomy
|
|
2733
|
+
chain stays on a single tier.
|
|
2734
|
+
- **Detail views are now one unified pipeline** (#307). The prismatic step-height
|
|
2735
|
+
detail and the new turned-head detail flow through a single
|
|
2736
|
+
detect → request → render path; several crowded regions become DETAIL A/B/…
|
|
2737
|
+
- **Output changes** for turned parts whose step chains were previously crammed, or
|
|
2738
|
+
whose fine heads are now broken out into a detail view.
|
|
2739
|
+
|
|
2740
|
+
### Fixed
|
|
2741
|
+
|
|
2742
|
+
- **A coaxial bore callout no longer overlaps the round view's centreline** (#305):
|
|
2743
|
+
its leader is angled off the centre axis so the callout text sits in clear space.
|
|
2744
|
+
|
|
2745
|
+
### Internal
|
|
2746
|
+
|
|
2747
|
+
- A new **layout-cleanliness invariant test** asserts that finished drawings have no
|
|
2748
|
+
view/annotation collisions across representative part archetypes, and the
|
|
2749
|
+
measure-and-repack pass gained a trigger for an annotation growing into a
|
|
2750
|
+
neighbouring view's line-work (so the views spread to make room).
|
|
2751
|
+
|
|
2752
|
+
## v0.2.0 — 2026-06-30
|
|
2753
|
+
|
|
2754
|
+
A major release. draftwright took ownership of feature recognition and linting
|
|
2755
|
+
(ADR 0007) and was re-architected onto a feature-IR + dimensioning-planner
|
|
2756
|
+
"compiler" (ADR 0008), gaining a Typer CLI and a portable, pure-Python PDF path
|
|
2757
|
+
along the way. **Generated drawings change** versus v0.1.13: the new pipeline
|
|
2758
|
+
dimensions parts more completely and consistently, so placement and the set of
|
|
2759
|
+
dimensions can differ — output is not byte-compatible with prior releases.
|
|
2760
|
+
|
|
2761
|
+
### Changed
|
|
2762
|
+
|
|
2763
|
+
- **Re-architected onto a feature-IR + dimensioning planner** (ADR 0008). The
|
|
2764
|
+
engine is now a compiler: detectors build one feature inventory → a typed IR /
|
|
2765
|
+
`PartModel` → a dimensioning planner emits render-intents → shared
|
|
2766
|
+
layout/projection/export. Orientation and feature-kind are *data in the IR*,
|
|
2767
|
+
not code branches, and every feature class (holes, patterns, counterbores,
|
|
2768
|
+
slots, turned diameters/steps, centre marks, location dims, envelope/OD,
|
|
2769
|
+
section A–A, PMI/GD&T) was migrated onto this one path; the old parallel
|
|
2770
|
+
recognisers and placement passes were deleted as each was replaced. Net effect
|
|
2771
|
+
for users: more complete, more consistent drawings — but output differs from
|
|
2772
|
+
v0.1.13.
|
|
2773
|
+
- **draftwright owns feature recognition and linting** (ADR 0007). The hole/
|
|
2774
|
+
boss/cylinder/pattern recognisers, the slot/turned-step recognisers, and the
|
|
2775
|
+
feature-coverage lint engine are vendored into `recognition/` and `linting.py`;
|
|
2776
|
+
`build123d-drafting-helpers` is now purely the rendering library.
|
|
2777
|
+
- **The CLI writes a PDF by default** and takes a `--format` selector (#288).
|
|
2778
|
+
Previously `draftwright part.step` emitted SVG + DXF; it now emits a single PDF.
|
|
2779
|
+
Choose outputs with `--format` (a comma-list, with an `all` alias) —
|
|
2780
|
+
`--format pdf,dxf`, `--format svg`, `--format all`. The library API is
|
|
2781
|
+
unchanged: `make_drawing(...)` / `Drawing.export()` still write SVG + DXF.
|
|
2782
|
+
- **PDF export is now pure-Python and a core capability** (#288). The renderer
|
|
2783
|
+
moved from `cairosvg` (which `dlopen`s the native `libcairo` system library —
|
|
2784
|
+
absent on stock macOS/Windows, so PDF-by-default would have crashed there) to
|
|
2785
|
+
`svglib` + `reportlab`, both pip-installable wheels with no system dependency.
|
|
2786
|
+
PDF therefore works out of the box on every platform; output is visually
|
|
2787
|
+
identical to the cairo renderer.
|
|
2788
|
+
|
|
2789
|
+
### Added
|
|
2790
|
+
|
|
2791
|
+
- **A Typer command-line interface** (#289/#291): shell completion
|
|
2792
|
+
(`--install-completion` / `--show-completion`), rich `--help`, and `--version`
|
|
2793
|
+
(reports the installed distribution version). All existing flags are preserved.
|
|
2794
|
+
- **`--format` output selector** (#288) — `pdf` (default), `svg`, `dxf`, or `all`,
|
|
2795
|
+
as a comma-list.
|
|
2796
|
+
- **Turned-part dimensioning**: axial step-length recognition and chains
|
|
2797
|
+
(#188/#189/#231), step-diameter callouts, collapse of a uniform step
|
|
2798
|
+
staircase to an "N× length" note (#290), and OD of a horizontal (X/Y) round
|
|
2799
|
+
body dimensioned on the profile view (#292).
|
|
2800
|
+
- **Slot recognition and dimensioning** converged onto the IR as `SlotFeature`
|
|
2801
|
+
(#242), and **section A–A** is now triggered by the planner (#271).
|
|
2802
|
+
- **A Contributor License Agreement** (#183).
|
|
2803
|
+
|
|
2804
|
+
### Removed
|
|
2805
|
+
|
|
2806
|
+
- **The `--pdf` flag** (use `--format pdf`, the new default), the **`[pdf]`
|
|
2807
|
+
install extra**, and the **`cairosvg` dependency** (#288).
|
|
2808
|
+
- The byte-exact golden-output test harness (#190) — regression coverage rests on
|
|
2809
|
+
the geometry-level and standards suites (ADR 0005 §3 / ADR 0007).
|
|
2810
|
+
|
|
2811
|
+
### Fixed
|
|
2812
|
+
|
|
2813
|
+
- Locate **every** side-drilled (off-axis) hole, not just the first (#225/#286).
|
|
2814
|
+
- Don't mis-detect a prismatic part with incidental cylinders as a turned part
|
|
2815
|
+
(#293/#294); drop phantom zero-diameter turned steps (#279/#284); skip an
|
|
2816
|
+
illegibly-dense step-length chain rather than cram it (#293/#296).
|
|
2817
|
+
- Degraded hole-pattern callout consistency (#262/#274).
|
|
2818
|
+
- Windows `python -m draftwright.make_drawing` CLI smoke / entrypoint (#181/#182).
|
|
2819
|
+
|
|
2820
|
+
## v0.1.13 — 2026-06-27
|
|
2821
|
+
|
|
2822
|
+
### Changed
|
|
2823
|
+
|
|
2824
|
+
- **Requires `build123d-drafting-helpers>=0.13.0`; text pinned to bundled fonts**
|
|
2825
|
+
(#149, ADR 0006). draftwright now vendors IBM Plex (OFL-1.1) and renders and
|
|
2826
|
+
measures all text via `font_path` — IBM Plex Mono for dimensions/callouts/notes,
|
|
2827
|
+
IBM Plex Sans Condensed for the title block — instead of resolving the system
|
|
2828
|
+
font name `"Arial"`. Resolving a name substitutes a different font on Linux,
|
|
2829
|
+
which shifted the whole sheet ~1 mm; pinning a bundled font file makes generated
|
|
2830
|
+
layout **deterministic across Linux/macOS/Windows** and gives a consistent
|
|
2831
|
+
typeface. **Drawing output changes**: positions shift slightly from prior
|
|
2832
|
+
releases and labels render in IBM Plex (helpers #172).
|
|
2833
|
+
|
|
2834
|
+
### Internal
|
|
2835
|
+
|
|
2836
|
+
- **Compiler-pipeline module split** (#138, ADR 0005). The two large modules
|
|
2837
|
+
`make_drawing.py` (3,907 lines) and `annotate.py` (2,587) were decomposed into a
|
|
2838
|
+
DAG of focused stage modules — `projection`, `sheet`, `analysis`, `drawing`,
|
|
2839
|
+
`builder`, the `annotations/` subpackage (sections/turned/pmi/holes/orchestrator),
|
|
2840
|
+
alongside the existing `registry`/`linting`/`repair`/`export`/`fonts`. Annotation
|
|
2841
|
+
identity, the lint coverage signal, and the deterministic repair loop each gained a
|
|
2842
|
+
single owner; `make_drawing.py` / `annotate.py` are now thin compat facades, so all
|
|
2843
|
+
existing imports and the `draftwright` CLI entry point keep working. A golden-output
|
|
2844
|
+
regression gate verified every step is behaviour-preserving (output byte-identical),
|
|
2845
|
+
and mypy was tightened on the settled contracts. No public API or drawing-output
|
|
2846
|
+
change. (Phases #160–#166.)
|
|
2847
|
+
|
|
2848
|
+
## v0.1.12 — 2026-06-21
|
|
2849
|
+
|
|
2850
|
+
### Changed
|
|
2851
|
+
|
|
2852
|
+
- **Requires `build123d-drafting-helpers>=0.12.0`** (#92, #122). draftwright now
|
|
2853
|
+
consumes the new sub-clustered hole-pattern recognition, the
|
|
2854
|
+
`feature_diameters()` coverage inventory, the persistent `view_edge_cache`,
|
|
2855
|
+
and the `ViewCoordinates.from_viewport()` ISO projection basis.
|
|
2856
|
+
- **Grouped hole-pattern callouts** (#92, #111, #114). A recognised perimeter,
|
|
2857
|
+
grid, or bolt circle collapses to a single `n× ⌀ …` callout plus its pattern
|
|
2858
|
+
dimensions instead of a balloon on every hole. A spec group now sub-clusters
|
|
2859
|
+
into multiple patterns (a perimeter → its edge `LinearArray` rows, a filled
|
|
2860
|
+
lattice → one `RectGrid` with a `(rows×cols)` callout and both pitch
|
|
2861
|
+
dimensions); only genuinely unpatterned holes fall back to the per-hole table.
|
|
2862
|
+
On NIST CTC-02 the table shrinks from 61 rows to the unpatterned remainder.
|
|
2863
|
+
- **Layout overhaul — compose-then-pack** (#121, #112, ADR 0004). Each view owns
|
|
2864
|
+
the annotations created against it, and the resulting view blocks are packed
|
|
2865
|
+
disjoint with automatic page/scale escalation. This eliminates cross-view
|
|
2866
|
+
overlap — most visibly, plan-view balloons landing on front-view dimensions.
|
|
2867
|
+
- **Drawing attribution** (#120). The title block records the author, the SVG
|
|
2868
|
+
and PDF carry a clickable draftwright hyperlink, and a "generated by
|
|
2869
|
+
draftwright" note is written to the SVG/DXF/PDF file metadata.
|
|
2870
|
+
- **Gap between wrapped hole-table column blocks** (#123) so a chart that wraps
|
|
2871
|
+
into several blocks reads as distinct columns.
|
|
2872
|
+
|
|
2873
|
+
### Fixed
|
|
2874
|
+
|
|
2875
|
+
- **Plan-view top balloon ring no longer floats over a phantom corridor** (#125).
|
|
2876
|
+
The hole-table escalation deletes the X-location dimensions but left their
|
|
2877
|
+
stale depth in the strip cursor, so the top balloons were parked far above the
|
|
2878
|
+
view. The ring is now sized to the real dimension stack, so the top-side
|
|
2879
|
+
leaders are short like the other three sides.
|
|
2880
|
+
- **No more phantom `feature_not_dimensioned` warnings** on slot-ends and shallow
|
|
2881
|
+
recesses, via the helpers 0.12.0 `feature_diameters()` coverage inventory
|
|
2882
|
+
(#92).
|
|
2883
|
+
|
|
2884
|
+
### Internal
|
|
2885
|
+
|
|
2886
|
+
- `AnnoBox` box-model footprint foundation and the four-side balloon ring placed
|
|
2887
|
+
in a reserved view halo (#111, #112); the title block is pinned as a
|
|
2888
|
+
first-class layout block (#112).
|
|
2889
|
+
|
|
2890
|
+
## v0.1.11 — 2026-06-19
|
|
2891
|
+
|
|
2892
|
+
### Changed
|
|
2893
|
+
|
|
2894
|
+
- **Feature-coverage lint is assembly-aware.** A general-arrangement drawing of
|
|
2895
|
+
a multi-solid part deliberately omits each part's bores (they belong on detail
|
|
2896
|
+
sheets), so `feature_not_dimensioned` / `feature_count_mismatch` are now
|
|
2897
|
+
emitted at `info` rather than `warning` when the part is multi-solid — out of
|
|
2898
|
+
the warning count and quality score, but still queryable. Auto-detected;
|
|
2899
|
+
override with `build_drawing(..., assembly=True/False)` or
|
|
2900
|
+
`lint_feature_coverage(..., assembly=...)` (#69).
|
|
2901
|
+
|
|
2902
|
+
### Fixed
|
|
2903
|
+
|
|
2904
|
+
- **`place_dim` now labels the real-world length, not the page distance**, at
|
|
2905
|
+
non-1:1 scale. Previously a dimension placed at a scale other than 1:1 showed
|
|
2906
|
+
the on-page millimetre span instead of the true model dimension (#104).
|
|
2907
|
+
|
|
2908
|
+
### Internal
|
|
2909
|
+
|
|
2910
|
+
- **`make_drawing.py` decomposed (#98).** The per-view projection math and the
|
|
2911
|
+
analysis namespace were deduplicated and typed (the namespace is now a frozen
|
|
2912
|
+
`Analysis` dataclass), and the annotation passes were extracted into a new
|
|
2913
|
+
`draftwright.annotate` module on top of a shared `draftwright._core`. The
|
|
2914
|
+
module graph is a DAG (`layout → _core → {make_drawing, annotate}`) and
|
|
2915
|
+
`make_drawing.py` shrank from ~5,270 to ~2,930 lines. No public API or
|
|
2916
|
+
behaviour change.
|
|
2917
|
+
|
|
2918
|
+
## v0.1.10 — 2026-06-18
|
|
2919
|
+
|
|
2920
|
+
### Added
|
|
2921
|
+
|
|
2922
|
+
- **Constraint-based layout engine (ADR 0003).** A new `draftwright.layout`
|
|
2923
|
+
module with a `Placeable` protocol and a `LayoutSolver`: a 1D Cassowary strip
|
|
2924
|
+
solver (`solve_strip`, with per-pair gaps) and a 2D free-rectangle placer
|
|
2925
|
+
(`place_box` / `fit_box`) that positions a box in a free part of the page
|
|
2926
|
+
clear of the views, title block, and existing annotations. Hole-callout and
|
|
2927
|
+
turned-diameter placement now run on the solver. The engine grows per real
|
|
2928
|
+
consumer; a monolithic global 2D solve is deferred (see the ADR).
|
|
2929
|
+
- **Hole table + balloons (#93).** `dwg.add_table(rows)` places a generic data
|
|
2930
|
+
table (gear data, BOM, revision block, …) in a free corner via `place_box`;
|
|
2931
|
+
`dwg.add_hole_table(view)` builds a hole chart from the detected holes with a
|
|
2932
|
+
circled balloon tag at each hole. A **too-dense plan view now auto-escalates**:
|
|
2933
|
+
a part the layout cannot legibly dimension hole-by-hole is replaced by a
|
|
2934
|
+
complete per-instance hole chart (`TAG | ⌀ | X | Y`, datum-relative) plus
|
|
2935
|
+
balloons, instead of silently dropping callouts and location dims. The chart
|
|
2936
|
+
wraps into multiple column-blocks to fit the page.
|
|
2937
|
+
- **External turned diameters (#77).** A turned part lying along the X axis now
|
|
2938
|
+
gets ø leader-callouts for its external stepped diameters, with thread/worm
|
|
2939
|
+
patches collapsed into a single boss.
|
|
2940
|
+
- **Pin / manual override (#89).** `dwg.pin(name)` / `dwg.unpin(name)` fix an
|
|
2941
|
+
annotation's position so `repair()` — and the layout engine — never move it; a
|
|
2942
|
+
deliberate (human or AI) placement wins over automatic layout.
|
|
2943
|
+
|
|
2944
|
+
### Changed
|
|
2945
|
+
|
|
2946
|
+
- Hole-callout and turned-diameter placement is deconflicted through the shared
|
|
2947
|
+
`LayoutSolver` instead of ad-hoc per-pass logic (no output change).
|
|
2948
|
+
|
|
2949
|
+
### Fixed
|
|
2950
|
+
|
|
2951
|
+
- **Exact circles recovered for revolution silhouettes.** `project_to_viewport`'s
|
|
2952
|
+
HLR returns the on-axis silhouette of a turned feature (or a concentric
|
|
2953
|
+
gear-tooth-tip arc) as an approximating spline, not a true circle — splines in
|
|
2954
|
+
the DXF where CAM expects `CIRCLE`/`ARC`, and fitted rather than exact radii.
|
|
2955
|
+
`add_view` now refits any silhouette whose samples are equidistant from a
|
|
2956
|
+
recognised revolution axis back to an exact circle/arc (#67).
|
|
2957
|
+
- **Blind-hole depth no longer measured across solid boundaries.** On a
|
|
2958
|
+
multi-solid assembly, coaxial bores in different bodies were merged into one
|
|
2959
|
+
hole, reporting a depth spanning the inter-body gap (the ⌀9.8 ↓111.4 symptom).
|
|
2960
|
+
Fixed upstream in `build123d-drafting-helpers` 0.10.1; the dependency pin is
|
|
2961
|
+
bumped to `>=0.10.1` to pick it up (#68).
|
|
2962
|
+
|
|
2963
|
+
### Docs
|
|
2964
|
+
|
|
2965
|
+
- The skill and generated-script header now lead with the domain API
|
|
2966
|
+
(`features` / `place_dim` / `repair` / `lint_summary`) and the
|
|
2967
|
+
build → critique → fix loop. ADR 0003 records the layout architecture; ADRs
|
|
2968
|
+
0001/0002 remain the editing-model and lint→repair foundations.
|
|
2969
|
+
|
|
2970
|
+
## v0.1.9 — 2026-06-16
|
|
2971
|
+
|
|
2972
|
+
### Added
|
|
2973
|
+
|
|
2974
|
+
- **Domain-semantic editing API.** `dwg.features(view)` returns detected holes
|
|
2975
|
+
and features grouped by machining spec in page coordinates, and
|
|
2976
|
+
`dwg.place_dim(p1, p2, side, view, draft, name=…)` places a dimension from
|
|
2977
|
+
domain inputs — the vocabulary a script (or an AI assistant) needs to edit a
|
|
2978
|
+
drawing without hand-computing page geometry (#25, #26).
|
|
2979
|
+
- **`dwg.annotations()` and `dwg.get_annotation(name)`.** Introspect what is
|
|
2980
|
+
already on the drawing — a `{name: type}` map and a name lookup — so a script
|
|
2981
|
+
can make incremental edits without risking a silent name-collision replace
|
|
2982
|
+
(#27).
|
|
2983
|
+
- **`dwg.view_bounds(view)`.** Returns `(x_min, y_min, x_max, y_max)`, the page
|
|
2984
|
+
bounding box of a view's projected geometry (or `None` for an unknown view),
|
|
2985
|
+
so free-form notes and leader elbows can be placed just outside a view without
|
|
2986
|
+
guessing offsets from `dwg.at()` (#28).
|
|
2987
|
+
- **Lint findings carry a suggested fix.** Each repairable lint issue now
|
|
2988
|
+
includes a ready-to-run domain-API call snippet, so acting on a finding is one
|
|
2989
|
+
copy-paste away (#29).
|
|
2990
|
+
- **Lint→repair loop.** `Drawing.repair()` — run by default in `build_drawing` —
|
|
2991
|
+
mechanically resolves the lint codes that have a deterministic placement fix:
|
|
2992
|
+
overlapping labels are pushed apart and wrong-side dimensions are flipped. A
|
|
2993
|
+
pass that would net-increase the issue count is rolled back, so repair never
|
|
2994
|
+
makes a drawing worse (#30).
|
|
2995
|
+
- **TYP / representative dimensioning for uniform step patterns.** A run of
|
|
2996
|
+
equal-rise, equal-going steps is dimensioned once and labelled representative
|
|
2997
|
+
(TYP) instead of repeating identical dimensions down the ladder (#45).
|
|
2998
|
+
- **Enlarged detail view for crowded step clusters (MVP).** When shoulders are
|
|
2999
|
+
too closely spaced to dimension legibly at sheet scale, an opt-in
|
|
3000
|
+
(`detail_view=True`) detail view re-draws them at a larger scale (#42).
|
|
3001
|
+
|
|
3002
|
+
### Changed
|
|
3003
|
+
|
|
3004
|
+
- **BREAKING: the annotation list `dwg.annotations` is renamed to `dwg.items`.**
|
|
3005
|
+
`dwg.annotations` is now a method (see Added); the ordered, mutable list of
|
|
3006
|
+
annotation objects it used to be is now `dwg.items`. Pre-1.0 with no published
|
|
3007
|
+
consumers, so the clearer name was taken now rather than spelling the new query
|
|
3008
|
+
method awkwardly (#27).
|
|
3009
|
+
|
|
3010
|
+
### Documentation
|
|
3011
|
+
|
|
3012
|
+
- ADRs 0001 (editing model) and 0002 (iteration loop) record the design
|
|
3013
|
+
direction behind the domain API and the lint→repair loop (#51).
|
|
3014
|
+
|
|
3015
|
+
## v0.1.8 — 2026-06-16
|
|
3016
|
+
|
|
3017
|
+
### Changed
|
|
3018
|
+
|
|
3019
|
+
- **Automatic scale selection now minimises the sheet size.** The preference
|
|
3020
|
+
ladder is page-major: every standard scale on the smallest sheet is tried
|
|
3021
|
+
before the next sheet up, so a part lands on the smallest sheet it fits at the
|
|
3022
|
+
largest scale that sheet allows. A 20 × 15 × 10 mm part is now drawn 2:1 on A4
|
|
3023
|
+
instead of 5:1 on A3 — a smaller sheet is preferred over a larger enlargement
|
|
3024
|
+
scale. Reductions keep their legibility-first balance, so a too-big part is
|
|
3025
|
+
not over-reduced onto a small sheet.
|
|
3026
|
+
- **A specified page now enlarges to the best fitting scale.** When the caller
|
|
3027
|
+
fixes the page (`--page A3`) or scale, scale selection packs the isometric
|
|
3028
|
+
view into the largest empty rectangle the placement engine actually uses (it
|
|
3029
|
+
may sit in vertical headroom above the views), instead of charging it a column
|
|
3030
|
+
in the view row. A long, short part — e.g. a 100 × 10 × 11 mm staircase — now
|
|
3031
|
+
fills a requested A3 at 2:1 where it was previously under-scaled to 1:1.
|
|
3032
|
+
Automatic selection (no page/scale given) keeps the conservative row model,
|
|
3033
|
+
which reserves enough room to place every annotation rather than dropping some
|
|
3034
|
+
onto a tighter sheet (staircase review).
|
|
3035
|
+
- **Isometric view growth is capped.** The iso is fitted to fill its zone but no
|
|
3036
|
+
longer grows past 1.3× sheet scale; on an oversized sheet it could previously
|
|
3037
|
+
balloon to ~8× and dwarf the dimensioned orthographic views. Shrinking to fit
|
|
3038
|
+
a small zone is unchanged.
|
|
3039
|
+
- **Step heights are dimensioned only where legibly separable.** After the
|
|
3040
|
+
adaptive cap (#36), a part with many closely-spaced shoulders (e.g. NIST
|
|
3041
|
+
CTC-02 at 1:5) tried to dimension faces only ~1 mm apart on the page. A step
|
|
3042
|
+
is now dimensioned only if it is both tall enough from the base *and* at least
|
|
3043
|
+
one legible step-height above the previously dimensioned one; the rest surface
|
|
3044
|
+
as `step_dim_dropped` (use a detail view). "Fits" is not the same as
|
|
3045
|
+
"legible" (#41).
|
|
3046
|
+
- **Hole-location dimensions are gated for legibility.** A hole-dense part (e.g.
|
|
3047
|
+
NIST CTC-02, ~38 distinct hole locations) previously stacked every location
|
|
3048
|
+
reference into a tall, busy tower above the views — "fits" is not "legible".
|
|
3049
|
+
Each axis's references are now gated by inter-dimension page spacing
|
|
3050
|
+
(`_legible_locations`, analogous to the step-height gate #41): only locations
|
|
3051
|
+
at least one value-label footprint apart on the page are dimensioned; the rest
|
|
3052
|
+
surface as `location_ref_dropped` (full fidelity belongs in a detail view,
|
|
3053
|
+
#42). Sparse parts are unchanged (#43).
|
|
3054
|
+
- **Tighter location-dimension tier pitch.** The vertical pitch between stacked
|
|
3055
|
+
X/Y location dimensions is now derived from the label footprint
|
|
3056
|
+
(`font_size + 2·pad_around_text`, ≈7 mm) instead of a looser `font_size·3`,
|
|
3057
|
+
so location stacks pack closer (#41).
|
|
3058
|
+
|
|
3059
|
+
### Fixed
|
|
3060
|
+
|
|
3061
|
+
- **Phantom step corridor no longer blocks a larger scale.** Page/scale
|
|
3062
|
+
selection reserved a step-ladder corridor sized for *every* candidate
|
|
3063
|
+
horizontal face, including ones the legibility gate would never dimension. A
|
|
3064
|
+
part with many sub-legible faces (e.g. a staircase with 15 tiny treads) was
|
|
3065
|
+
forced onto an oversized sheet at 1:1. Scale selection now iterates so the
|
|
3066
|
+
reserved corridor matches the step count actually placed, freeing the part to
|
|
3067
|
+
pick a tighter sheet (staircase.step review).
|
|
3068
|
+
- **Engraved-text faces are no longer dimensioned as steps.** `analyse_face_levels`
|
|
3069
|
+
gained a `min_area_frac` filter; a horizontal face counts as a step only if
|
|
3070
|
+
its area is at least 1% of the part's plan footprint. This drops sub-feature
|
|
3071
|
+
faces (fragments of engraved numbers/text) that were surfacing as phantom
|
|
3072
|
+
shoulders — e.g. a 0.57 mm² digit face dimensioned as z=6.4 on staircase.step.
|
|
3073
|
+
- **Overall-height dimension nests outside the step dims.** The overall height
|
|
3074
|
+
is now placed last on the front view's right ladder so it sits outermost, with
|
|
3075
|
+
the step-height dims inside it; extension lines nest instead of leapfrogging
|
|
3076
|
+
(staircase.step review).
|
|
3077
|
+
|
|
3078
|
+
## v0.1.7 — 2026-06-15
|
|
3079
|
+
|
|
3080
|
+
### Added
|
|
3081
|
+
|
|
3082
|
+
- `Drawing.lint_summary()` — a JSON-friendly aggregate of `lint()` for
|
|
3083
|
+
non-interactive callers (scripts, or an LLM via the API): severity counts,
|
|
3084
|
+
per-code counts, a `geometry_issues` tally (standards/geometry checks vs pure
|
|
3085
|
+
layout), a `passed` flag, a coarse 0–1 `score`, and the full issue list. Gives
|
|
3086
|
+
a single signal to gate and optimise on without rendering the SVG (#32).
|
|
3087
|
+
|
|
3088
|
+
### Changed
|
|
3089
|
+
|
|
3090
|
+
- **Adaptive annotation placement.** The three hard-coded cardinality caps —
|
|
3091
|
+
four hole callouts per view, four hole location references per part, and three
|
|
3092
|
+
step-height dimensions — are removed. The engine now places as many as the
|
|
3093
|
+
available strip/corridor space allows (callouts largest-first, locations
|
|
3094
|
+
nearest-datum-first, every legible step), so a part with room is dimensioned
|
|
3095
|
+
completely instead of dropped to an arbitrary count. An annotation that
|
|
3096
|
+
genuinely doesn't fit is never force-placed; it surfaces via lint
|
|
3097
|
+
(`callout_dropped` / `location_ref_dropped`, warning severity). On the NIST
|
|
3098
|
+
CTC parts this raises coverage substantially (e.g. CTC-02: 4 → 36 location
|
|
3099
|
+
dimensions, 4 → 9 callouts) with no error-severity lint (#36).
|
|
3100
|
+
- **No silent annotation drops.** Every place the layout has to drop an
|
|
3101
|
+
annotation now records a machine-readable lint issue, surfaced by `lint()`,
|
|
3102
|
+
so a short drawing always carries a reason. A dropped callout names its
|
|
3103
|
+
diameter and is excluded from `feature_not_dimensioned` (no double-report).
|
|
3104
|
+
`placement_unsatisfiable` (error severity) is reserved for the degenerate
|
|
3105
|
+
case where space was reserved but an annotation still could not be placed
|
|
3106
|
+
(#32).
|
|
3107
|
+
- **Layout constants derived from first principles.** Bare, fixture-tuned
|
|
3108
|
+
constants (strip slot widths, callout label widths, isometric fit factor) are
|
|
3109
|
+
now computed from text metrics and page size rather than hard-coded, so the
|
|
3110
|
+
layout generalises to unseen geometry instead of fitting the test cases (#31).
|
|
3111
|
+
- `_auto_annotate` clears its build-time lint records on re-entry, and repeated
|
|
3112
|
+
`lint()` calls are stable (#32).
|
|
3113
|
+
|
|
3114
|
+
### Fixed
|
|
3115
|
+
|
|
3116
|
+
- AP242 / PMI STEP import segfault: STEP geometry is now read directly via
|
|
3117
|
+
`STEPControl_Reader`, avoiding the XCAF/PMI read that crashed (SIGSEGV) on
|
|
3118
|
+
with-PMI files such as NIST CTC-02 (#20).
|
|
3119
|
+
|
|
3120
|
+
### Tests
|
|
3121
|
+
|
|
3122
|
+
- Overfitting guards pin the general layout behaviour on turned/hybrid parts
|
|
3123
|
+
(flange OD + bolt circle), multi-bore parts, and the step-legibility boundary
|
|
3124
|
+
(#13).
|
|
3125
|
+
- The full NIST CTC set (AP203 and AP242) builds and is covered by the slow
|
|
3126
|
+
end-to-end tier.
|
|
3127
|
+
|
|
3128
|
+
## v0.1.6 — 2026-06-15
|
|
3129
|
+
|
|
3130
|
+
### Fixed
|
|
3131
|
+
|
|
3132
|
+
- Section-view boolean cut on cast geometry: the exact `body - Box(...)` boolean
|
|
3133
|
+
raised an uncatchable `Standard_DomainError` (C++ abort, SIGABRT) on some parts
|
|
3134
|
+
(NIST CTC-04), crashing the whole drawing. `_fuzzy_cut()` now runs
|
|
3135
|
+
`BRepAlgoAPI_Cut` with a small fuzzy tolerance and keeps solids-only, making
|
|
3136
|
+
the section cut robust (#20, #22).
|
|
3137
|
+
|
|
3138
|
+
### Tests
|
|
3139
|
+
|
|
3140
|
+
- NIST CTC-04 (both AP203 and AP242) now build with a clean section view and are
|
|
3141
|
+
covered by the CTC build tests.
|
|
3142
|
+
- Known: CTC-02 AP242 still segfaults inside OCCT's AP242/PMI STEP read (#20),
|
|
3143
|
+
excluded from build tests.
|
|
3144
|
+
|
|
3145
|
+
## v0.1.5 — 2026-06-15
|
|
3146
|
+
|
|
3147
|
+
### Fixed
|
|
3148
|
+
|
|
3149
|
+
- CTC-02 spurious full-page line: build123d's `ExportSVG` projected
|
|
3150
|
+
circle-edge-on edges (hole/fillet rims seen edge-on) as elliptical arcs with
|
|
3151
|
+
a near-zero minor radius, which renderers blow up into full-page lines.
|
|
3152
|
+
`sanitize_svg_arcs()` rewrites any arc with a sub-1e-3 mm radius into the
|
|
3153
|
+
straight line it actually is, leaving real arcs untouched (#19). Not a PMI
|
|
3154
|
+
issue — the file is AP203 geometry-only.
|
|
3155
|
+
|
|
3156
|
+
### Tests
|
|
3157
|
+
|
|
3158
|
+
- Added the full NIST CTC set (01–05) as fixtures, both AP203 geometry-only and
|
|
3159
|
+
AP242 (with-PMI) variants.
|
|
3160
|
+
- Heavy end-to-end CTC fixture builds are marked `slow` and deselected from the
|
|
3161
|
+
default `pytest` run (fast normal run, ~4.5 min); CI runs the fast tier across
|
|
3162
|
+
the OS/Python matrix and the slow tier once.
|
|
3163
|
+
- Known: AP242 CTC-02 and both CTC-04 variants crash OCCT on import (#20); their
|
|
3164
|
+
fixtures are excluded from build tests.
|
|
3165
|
+
|
|
3166
|
+
## v0.1.4 — 2026-06-15
|
|
3167
|
+
|
|
3168
|
+
### Changed
|
|
3169
|
+
|
|
3170
|
+
- Feature annotations (hole callouts, location dimensions, section view) now
|
|
3171
|
+
fire on feature presence independent of the turned/prismatic classification,
|
|
3172
|
+
so turned-and-drilled parts (e.g. flanges) get both the OD/centreline base
|
|
3173
|
+
set and per-hole callouts plus bolt-circle furniture (#10).
|
|
3174
|
+
- Isometric view placement now uses a general largest-empty-rectangle search in
|
|
3175
|
+
place of the wide/flat-on-A3 special case (#11).
|
|
3176
|
+
- Concentric bore-leader stacking is generalised beyond three, and the
|
|
3177
|
+
step-height dimension gate is now a single derived constant (#10, #12).
|
|
3178
|
+
|
|
3179
|
+
### Internal
|
|
3180
|
+
|
|
3181
|
+
- Single-sourced duplicated geometry constants from the draft preset (#12).
|
|
3182
|
+
- Minor comment and logging cleanups.
|
|
3183
|
+
|
|
3184
|
+
## v0.1.0 — 2026-06-14
|
|
3185
|
+
|
|
3186
|
+
Initial release — spun out of `build123d-drafting-helpers` v0.9.1.
|
|
3187
|
+
|
|
3188
|
+
The automated drawing engine (`make_drawing`, `build_drawing`, `Drawing`)
|
|
3189
|
+
was previously part of `build123d-drafting-helpers`. It is now a separate
|
|
3190
|
+
AGPL-licensed package that depends on `build123d-drafting-helpers>=0.9.1`
|
|
3191
|
+
for annotation primitives.
|
|
3192
|
+
|
|
3193
|
+
### Migration from build123d-drafting-helpers
|
|
3194
|
+
|
|
3195
|
+
```python
|
|
3196
|
+
# Before
|
|
3197
|
+
from build123d_drafting import make_drawing, Drawing, build_drawing
|
|
3198
|
+
|
|
3199
|
+
# After
|
|
3200
|
+
from draftwright import make_drawing, Drawing, build_drawing
|
|
3201
|
+
```
|
|
3202
|
+
|
|
3203
|
+
### Features (carried over from build123d-drafting-helpers)
|
|
3204
|
+
|
|
3205
|
+
- **`make_drawing`** / **`build_drawing`** — automatic multi-view technical
|
|
3206
|
+
drawing from a build123d solid: view layout, scale selection, orthographic
|
|
3207
|
+
projection, dimension placement, title block.
|
|
3208
|
+
- **`Drawing`** — composable drawing object with `.lint()`, `.add()`,
|
|
3209
|
+
`.export_svg()`, `.export_dxf()`.
|
|
3210
|
+
- **`choose_scale`** — ISO/ASME standard scale selection.
|
|
3211
|
+
- **`lint_feature_coverage`** — checks annotation coverage against detected
|
|
3212
|
+
part features (holes, bosses, bolt circles).
|
|
3213
|
+
- **Section A–A views** — automatic section view for blind/stepped holes,
|
|
3214
|
+
with ISO 128-44 solid filled cutting-plane arrows and ISO 128-50 45°
|
|
3215
|
+
hatching on the cut face.
|
|
3216
|
+
- **`generate_script`** — generates a standalone drawing script from a STEP
|
|
3217
|
+
file.
|